summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/ac97/bus.c26
-rw-r--r--sound/ac97_bus.c4
-rw-r--r--sound/aoa/fabrics/layout.c6
-rw-r--r--sound/arm/Kconfig7
-rw-r--r--sound/arm/Makefile4
-rw-r--r--sound/atmel/ac97c.c1
-rw-r--r--sound/core/compress_offload.c13
-rw-r--r--sound/core/control.c36
-rw-r--r--sound/core/control_led.c11
-rw-r--r--sound/core/hrtimer.c2
-rw-r--r--sound/core/init.c21
-rw-r--r--sound/core/jack.c13
-rw-r--r--sound/core/misc.c24
-rw-r--r--sound/core/oss/pcm_oss.c22
-rw-r--r--sound/core/oss/pcm_plugin.c2
-rw-r--r--sound/core/pcm_compat.c4
-rw-r--r--sound/core/pcm_drm_eld.c4
-rw-r--r--sound/core/pcm_lib.c5
-rw-r--r--sound/core/pcm_native.c48
-rw-r--r--sound/core/rawmidi.c4
-rw-r--r--sound/core/seq/oss/seq_oss_event.c6
-rw-r--r--sound/core/seq/oss/seq_oss_event.h4
-rw-r--r--sound/core/seq/oss/seq_oss_init.c4
-rw-r--r--sound/core/seq/oss/seq_oss_ioctl.c7
-rw-r--r--sound/core/seq/oss/seq_oss_midi.c6
-rw-r--r--sound/core/seq/oss/seq_oss_midi.h2
-rw-r--r--sound/core/seq/oss/seq_oss_readq.c90
-rw-r--r--sound/core/seq/oss/seq_oss_readq.h3
-rw-r--r--sound/core/seq/oss/seq_oss_rw.c7
-rw-r--r--sound/core/seq/seq_clientmgr.c47
-rw-r--r--sound/core/seq/seq_dummy.c17
-rw-r--r--sound/core/seq/seq_fifo.c52
-rw-r--r--sound/core/seq/seq_memory.c4
-rw-r--r--sound/core/seq/seq_midi.c55
-rw-r--r--sound/core/seq/seq_midi_emul.c38
-rw-r--r--sound/core/seq/seq_ports.c34
-rw-r--r--sound/core/seq/seq_ports.h8
-rw-r--r--sound/core/seq/seq_prioq.c14
-rw-r--r--sound/core/seq/seq_timer.c11
-rw-r--r--sound/core/seq/seq_ump_client.c22
-rw-r--r--sound/core/seq_device.c5
-rw-r--r--sound/core/timer.c151
-rw-r--r--sound/core/timer_compat.c5
-rw-r--r--sound/drivers/aloop.c14
-rw-r--r--sound/drivers/mpu401/mpu401.c4
-rw-r--r--sound/drivers/pcmtest.c4
-rw-r--r--sound/firewire/dice/dice.c34
-rw-r--r--sound/firewire/fireface/ff.c12
-rw-r--r--sound/firewire/isight.c4
-rw-r--r--sound/firewire/motu/motu-register-dsp-message-parser.c11
-rw-r--r--sound/firewire/motu/motu.c6
-rw-r--r--sound/firewire/oxfw/oxfw.c4
-rw-r--r--sound/hda/codecs/Kconfig1
-rw-r--r--sound/hda/codecs/ca0132.c155
-rw-r--r--sound/hda/codecs/cirrus/cs420x.c1
-rw-r--r--sound/hda/codecs/conexant.c12
-rw-r--r--sound/hda/codecs/hdmi/hdmi.c9
-rw-r--r--sound/hda/codecs/realtek/alc269.c94
-rw-r--r--sound/hda/codecs/realtek/alc882.c22
-rw-r--r--sound/hda/codecs/side-codecs/Kconfig3
-rw-r--r--sound/hda/codecs/side-codecs/cs35l41_hda.c81
-rw-r--r--sound/hda/codecs/side-codecs/cs35l41_hda.h5
-rw-r--r--sound/hda/codecs/side-codecs/cs35l41_hda_i2c.c5
-rw-r--r--sound/hda/codecs/side-codecs/cs35l41_hda_property.c2
-rw-r--r--sound/hda/codecs/side-codecs/cs35l41_hda_spi.c1
-rw-r--r--sound/hda/codecs/side-codecs/cs35l56_hda.c18
-rw-r--r--sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c8
-rw-r--r--sound/hda/codecs/side-codecs/tas2781_hda_i2c.c8
-rw-r--r--sound/hda/codecs/side-codecs/tas2781_hda_spi.c22
-rw-r--r--sound/hda/common/auto_parser.c4
-rw-r--r--sound/hda/common/bind.c3
-rw-r--r--sound/hda/common/codec.c17
-rw-r--r--sound/hda/common/controller.c32
-rw-r--r--sound/hda/common/hda_controller.h14
-rw-r--r--sound/hda/common/jack.c6
-rw-r--r--sound/hda/controllers/Kconfig2
-rw-r--r--sound/hda/controllers/intel.c106
-rw-r--r--sound/hda/controllers/intel.h15
-rw-r--r--sound/hda/core/hda_bus_type.c1
-rw-r--r--sound/hda/core/i915.c30
-rw-r--r--sound/isa/cmi8330.c4
-rw-r--r--sound/isa/cs423x/cs4236.c8
-rw-r--r--sound/isa/es18xx.c12
-rw-r--r--sound/isa/gus/gus_pcm.c2
-rw-r--r--sound/isa/gus/interwave.c4
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c4
-rw-r--r--sound/isa/opl3sa2.c8
-rw-r--r--sound/isa/opti9xx/miro.c268
-rw-r--r--sound/isa/sb/sb16.c4
-rw-r--r--sound/isa/sscape.c4
-rw-r--r--sound/isa/wavefront/wavefront.c65
-rw-r--r--sound/isa/wavefront/wavefront_midi.c47
-rw-r--r--sound/isa/wavefront/wavefront_synth.c96
-rw-r--r--sound/oss/dmasound/dmasound_core.c10
-rw-r--r--sound/pci/ali5451/ali5451.c4
-rw-r--r--sound/pci/als300.c6
-rw-r--r--sound/pci/als4000.c4
-rw-r--r--sound/pci/asihpi/asihpi.c17
-rw-r--r--sound/pci/asihpi/hpicmn.c22
-rw-r--r--sound/pci/asihpi/hpicmn.h4
-rw-r--r--sound/pci/asihpi/hpipcida.h18
-rw-r--r--sound/pci/atiixp.c10
-rw-r--r--sound/pci/atiixp_modem.c6
-rw-r--r--sound/pci/au88x0/au8810.c4
-rw-r--r--sound/pci/au88x0/au8820.c4
-rw-r--r--sound/pci/au88x0/au8830.c4
-rw-r--r--sound/pci/aw2/aw2-alsa.c5
-rw-r--r--sound/pci/azt3328.c6
-rw-r--r--sound/pci/ca0106/ca0106_main.c4
-rw-r--r--sound/pci/cmipci.c18
-rw-r--r--sound/pci/cs4281.c4
-rw-r--r--sound/pci/cs46xx/cs46xx.c8
-rw-r--r--sound/pci/ctxfi/ctmixer.c44
-rw-r--r--sound/pci/ctxfi/ctmixer.h7
-rw-r--r--sound/pci/ctxfi/ctsrc.c15
-rw-r--r--sound/pci/ctxfi/ctsrc.h2
-rw-r--r--sound/pci/echoaudio/darla20.c4
-rw-r--r--sound/pci/echoaudio/darla24.c6
-rw-r--r--sound/pci/echoaudio/echo3g.c4
-rw-r--r--sound/pci/echoaudio/gina20.c4
-rw-r--r--sound/pci/echoaudio/gina24.c10
-rw-r--r--sound/pci/echoaudio/indigo.c4
-rw-r--r--sound/pci/echoaudio/indigodj.c4
-rw-r--r--sound/pci/echoaudio/indigodjx.c4
-rw-r--r--sound/pci/echoaudio/indigoio.c4
-rw-r--r--sound/pci/echoaudio/indigoiox.c4
-rw-r--r--sound/pci/echoaudio/layla20.c6
-rw-r--r--sound/pci/echoaudio/layla24.c4
-rw-r--r--sound/pci/echoaudio/mia.c6
-rw-r--r--sound/pci/echoaudio/mona.c20
-rw-r--r--sound/pci/emu10k1/emu10k1.c8
-rw-r--r--sound/pci/emu10k1/emu10k1x.c4
-rw-r--r--sound/pci/emu10k1/emupcm.c18
-rw-r--r--sound/pci/ens1370.c10
-rw-r--r--sound/pci/es1938.c6
-rw-r--r--sound/pci/es1968.c27
-rw-r--r--sound/pci/fm801.c15
-rw-r--r--sound/pci/ice1712/aureon.c2
-rw-r--r--sound/pci/ice1712/ice1712.c12
-rw-r--r--sound/pci/ice1712/ice1724.c29
-rw-r--r--sound/pci/intel8x0.c118
-rw-r--r--sound/pci/intel8x0m.c88
-rw-r--r--sound/pci/maestro3.c51
-rw-r--r--sound/pci/mixart/mixart.c4
-rw-r--r--sound/pci/nm256/nm256.c8
-rw-r--r--sound/pci/oxygen/oxygen.c270
-rw-r--r--sound/pci/pcxhr/pcxhr.c83
-rw-r--r--sound/pci/pcxhr/pcxhr.h2
-rw-r--r--sound/pci/pcxhr/pcxhr_mix22.c33
-rw-r--r--sound/pci/rme32.c8
-rw-r--r--sound/pci/rme96.c10
-rw-r--r--sound/pci/sonicvibes.c4
-rw-r--r--sound/pci/trident/trident.c16
-rw-r--r--sound/pci/via82xx.c6
-rw-r--r--sound/pci/via82xx_modem.c4
-rw-r--r--sound/pci/vx222/vx222.c6
-rw-r--r--sound/pci/ymfpci/ymfpci.c14
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c6
-rw-r--r--sound/sh/aica.c8
-rw-r--r--sound/soc/amd/Kconfig10
-rw-r--r--sound/soc/amd/Makefile1
-rw-r--r--sound/soc/amd/acp-config.c14
-rw-r--r--sound/soc/amd/acp/acp-sdw-legacy-mach.c9
-rw-r--r--sound/soc/amd/acp/acp-sdw-sof-mach.c7
-rw-r--r--sound/soc/amd/acp/amd-acp70-acpi-match.c44
-rw-r--r--sound/soc/amd/acp7x/Makefile5
-rw-r--r--sound/soc/amd/acp7x/acp7x-common.c125
-rw-r--r--sound/soc/amd/acp7x/acp7x.h110
-rw-r--r--sound/soc/amd/acp7x/pci-acp7x.c168
-rw-r--r--sound/soc/amd/ps/pci-ps.c3
-rw-r--r--sound/soc/amd/ps/ps-mach.c2
-rw-r--r--sound/soc/amd/renoir/acp3x-rn.c2
-rw-r--r--sound/soc/amd/yc/acp6x-mach.c30
-rw-r--r--sound/soc/apple/mca.c14
-rw-r--r--sound/soc/atmel/atmel-classd.c41
-rw-r--r--sound/soc/atmel/mchp-spdifrx.c33
-rw-r--r--sound/soc/atmel/sam9x5_wm8731.c1
-rw-r--r--sound/soc/bcm/cygnus-ssp.c10
-rw-r--r--sound/soc/codecs/Kconfig43
-rw-r--r--sound/soc/codecs/Makefile8
-rw-r--r--sound/soc/codecs/ad193x-i2c.c4
-rw-r--r--sound/soc/codecs/adau1372-i2c.c3
-rw-r--r--sound/soc/codecs/adau1372-spi.c1
-rw-r--r--sound/soc/codecs/adau1372.c6
-rw-r--r--sound/soc/codecs/adau1373.c2
-rw-r--r--sound/soc/codecs/adau1701.c8
-rw-r--r--sound/soc/codecs/adau1761-i2c.c9
-rw-r--r--sound/soc/codecs/adau1761-spi.c1
-rw-r--r--sound/soc/codecs/adau1781-i2c.c5
-rw-r--r--sound/soc/codecs/adau1781-spi.c1
-rw-r--r--sound/soc/codecs/adau1977-i2c.c7
-rw-r--r--sound/soc/codecs/adau1977-spi.c1
-rw-r--r--sound/soc/codecs/adau7118-hw.c1
-rw-r--r--sound/soc/codecs/adau7118-i2c.c4
-rw-r--r--sound/soc/codecs/adav803.c2
-rw-r--r--sound/soc/codecs/ak4104.c1
-rw-r--r--sound/soc/codecs/ak4118.c4
-rw-r--r--sound/soc/codecs/ak4535.c2
-rw-r--r--sound/soc/codecs/ak4613.c7
-rw-r--r--sound/soc/codecs/ak4619.c10
-rw-r--r--sound/soc/codecs/ak4642.c8
-rw-r--r--sound/soc/codecs/ak4671.c2
-rw-r--r--sound/soc/codecs/alc5623.c8
-rw-r--r--sound/soc/codecs/alc5632.c4
-rw-r--r--sound/soc/codecs/audio-iio-aux.c1
-rw-r--r--sound/soc/codecs/aw87390.c4
-rw-r--r--sound/soc/codecs/aw88081.c16
-rw-r--r--sound/soc/codecs/aw88166.c2
-rw-r--r--sound/soc/codecs/aw88261.c600
-rw-r--r--sound/soc/codecs/aw88261.h185
-rw-r--r--sound/soc/codecs/aw88395/aw88395.c13
-rw-r--r--sound/soc/codecs/aw88395/aw88395_device.h2
-rw-r--r--sound/soc/codecs/aw88399.c2
-rw-r--r--sound/soc/codecs/cs-amp-lib.c22
-rw-r--r--sound/soc/codecs/cs35l32.c4
-rw-r--r--sound/soc/codecs/cs35l33.c4
-rw-r--r--sound/soc/codecs/cs35l34.c4
-rw-r--r--sound/soc/codecs/cs35l35.c4
-rw-r--r--sound/soc/codecs/cs35l36.c4
-rw-r--r--sound/soc/codecs/cs35l41-i2c.c10
-rw-r--r--sound/soc/codecs/cs35l45-i2c.c4
-rw-r--r--sound/soc/codecs/cs35l56-i2c.c6
-rw-r--r--sound/soc/codecs/cs35l56-sdw.c235
-rw-r--r--sound/soc/codecs/cs35l56-shared-test.c6
-rw-r--r--sound/soc/codecs/cs35l56-shared.c6
-rw-r--r--sound/soc/codecs/cs35l56.c104
-rw-r--r--sound/soc/codecs/cs35l56.h7
-rw-r--r--sound/soc/codecs/cs4234.c1
-rw-r--r--sound/soc/codecs/cs4265.c2
-rw-r--r--sound/soc/codecs/cs4270.c5
-rw-r--r--sound/soc/codecs/cs4271-i2c.c2
-rw-r--r--sound/soc/codecs/cs42l42-i2c.c4
-rw-r--r--sound/soc/codecs/cs42l42-sdw.c12
-rw-r--r--sound/soc/codecs/cs42l43-jack.c5
-rw-r--r--sound/soc/codecs/cs42l43.c1
-rw-r--r--sound/soc/codecs/cs42l51-i2c.c2
-rw-r--r--sound/soc/codecs/cs42l52.c2
-rw-r--r--sound/soc/codecs/cs42l56.c2
-rw-r--r--sound/soc/codecs/cs42l73.c4
-rw-r--r--sound/soc/codecs/cs42l84.c4
-rw-r--r--sound/soc/codecs/cs42xx8-i2c.c7
-rw-r--r--sound/soc/codecs/cs42xx8-spi.c103
-rw-r--r--sound/soc/codecs/cs42xx8.c3
-rw-r--r--sound/soc/codecs/cs43130.c10
-rw-r--r--sound/soc/codecs/cs4341.c2
-rw-r--r--sound/soc/codecs/cs4349.c5
-rw-r--r--sound/soc/codecs/cs530x-i2c.c14
-rw-r--r--sound/soc/codecs/cs530x.c29
-rw-r--r--sound/soc/codecs/cs530x.h6
-rw-r--r--sound/soc/codecs/cs53l30.c4
-rw-r--r--sound/soc/codecs/cx20442.c11
-rw-r--r--sound/soc/codecs/cx20442.h5
-rw-r--r--sound/soc/codecs/cx2072x.c6
-rw-r--r--sound/soc/codecs/da7210.c2
-rw-r--r--sound/soc/codecs/da7213.c7
-rw-r--r--sound/soc/codecs/da7218.c4
-rw-r--r--sound/soc/codecs/da7219.c2
-rw-r--r--sound/soc/codecs/da732x.c2
-rw-r--r--sound/soc/codecs/da9055.c2
-rw-r--r--sound/soc/codecs/es8311.c2
-rw-r--r--sound/soc/codecs/es8316.c5
-rw-r--r--sound/soc/codecs/es8323.c3
-rw-r--r--sound/soc/codecs/es8326.c4
-rw-r--r--sound/soc/codecs/es8328-i2c.c4
-rw-r--r--sound/soc/codecs/es8375.c2
-rw-r--r--sound/soc/codecs/es8389.c2
-rw-r--r--sound/soc/codecs/es9356.c1143
-rw-r--r--sound/soc/codecs/es9356.h208
-rw-r--r--sound/soc/codecs/framer-codec.c8
-rw-r--r--sound/soc/codecs/fs210x.c8
-rw-r--r--sound/soc/codecs/hdac_hdmi.c4
-rw-r--r--sound/soc/codecs/idt821034.c9
-rw-r--r--sound/soc/codecs/isabelle.c2
-rw-r--r--sound/soc/codecs/lm4857.c2
-rw-r--r--sound/soc/codecs/lm49453.c2
-rw-r--r--sound/soc/codecs/lpass-va-macro.c7
-rw-r--r--sound/soc/codecs/max9768.c2
-rw-r--r--sound/soc/codecs/max98088.c4
-rw-r--r--sound/soc/codecs/max98090.c14
-rw-r--r--sound/soc/codecs/max98090.h3
-rw-r--r--sound/soc/codecs/max98095.c2
-rw-r--r--sound/soc/codecs/max98357a.c1
-rw-r--r--sound/soc/codecs/max98363.c17
-rw-r--r--sound/soc/codecs/max98371.c2
-rw-r--r--sound/soc/codecs/max98373-i2c.c5
-rw-r--r--sound/soc/codecs/max98373-sdw.c17
-rw-r--r--sound/soc/codecs/max98388.c5
-rw-r--r--sound/soc/codecs/max98390.c4
-rw-r--r--sound/soc/codecs/max98396.c6
-rw-r--r--sound/soc/codecs/max9850.c2
-rw-r--r--sound/soc/codecs/max98504.c2
-rw-r--r--sound/soc/codecs/max98520.c4
-rw-r--r--sound/soc/codecs/max9860.c2
-rw-r--r--sound/soc/codecs/max9867.c2
-rw-r--r--sound/soc/codecs/max9877.c2
-rw-r--r--sound/soc/codecs/max98925.c2
-rw-r--r--sound/soc/codecs/max98926.c2
-rw-r--r--sound/soc/codecs/max98927.c4
-rw-r--r--sound/soc/codecs/ml26124.c2
-rw-r--r--sound/soc/codecs/mt6351.c1
-rw-r--r--sound/soc/codecs/mt6358.c1
-rw-r--r--sound/soc/codecs/mt6660.c4
-rw-r--r--sound/soc/codecs/nau8325.c2
-rw-r--r--sound/soc/codecs/nau8540.c2
-rw-r--r--sound/soc/codecs/nau8810.c6
-rw-r--r--sound/soc/codecs/nau8821.c2
-rw-r--r--sound/soc/codecs/nau8822.c48
-rw-r--r--sound/soc/codecs/nau8822.h3
-rw-r--r--sound/soc/codecs/nau8824.c2
-rw-r--r--sound/soc/codecs/nau8825.c14
-rw-r--r--sound/soc/codecs/ntp8835.c4
-rw-r--r--sound/soc/codecs/ntp8918.c4
-rw-r--r--sound/soc/codecs/pcm1681.c4
-rw-r--r--sound/soc/codecs/pcm1789-i2c.c2
-rw-r--r--sound/soc/codecs/pcm179x-i2c.c2
-rw-r--r--sound/soc/codecs/pcm186x-i2c.c8
-rw-r--r--sound/soc/codecs/pcm3168a-i2c.c3
-rw-r--r--sound/soc/codecs/pcm3168a.c30
-rw-r--r--sound/soc/codecs/pcm512x-i2c.c14
-rw-r--r--sound/soc/codecs/pcm512x.c8
-rw-r--r--sound/soc/codecs/pcm6240.c80
-rw-r--r--sound/soc/codecs/pcm6240.h2
-rw-r--r--sound/soc/codecs/peb2466.c9
-rw-r--r--sound/soc/codecs/pm4125.c11
-rw-r--r--sound/soc/codecs/rk3328_codec.c54
-rw-r--r--sound/soc/codecs/rt1011.c2
-rw-r--r--sound/soc/codecs/rt1015.c2
-rw-r--r--sound/soc/codecs/rt1016.c2
-rw-r--r--sound/soc/codecs/rt1017-sdca-sdw.c17
-rw-r--r--sound/soc/codecs/rt1019.c2
-rw-r--r--sound/soc/codecs/rt1305.c4
-rw-r--r--sound/soc/codecs/rt1308-sdw.c17
-rw-r--r--sound/soc/codecs/rt1308.c2
-rw-r--r--sound/soc/codecs/rt1316-sdw.c17
-rw-r--r--sound/soc/codecs/rt1318-sdw.c17
-rw-r--r--sound/soc/codecs/rt1318.c2
-rw-r--r--sound/soc/codecs/rt1320-sdw.c17
-rw-r--r--sound/soc/codecs/rt274.c4
-rw-r--r--sound/soc/codecs/rt286.c6
-rw-r--r--sound/soc/codecs/rt298.c4
-rw-r--r--sound/soc/codecs/rt5514.c2
-rw-r--r--sound/soc/codecs/rt5575-spi.c2
-rw-r--r--sound/soc/codecs/rt5575.c2
-rw-r--r--sound/soc/codecs/rt5616.c6
-rw-r--r--sound/soc/codecs/rt5631.c10
-rw-r--r--sound/soc/codecs/rt5640.c43
-rw-r--r--sound/soc/codecs/rt5645.c10
-rw-r--r--sound/soc/codecs/rt5645.h1
-rw-r--r--sound/soc/codecs/rt5651.c2
-rw-r--r--sound/soc/codecs/rt5659.c4
-rw-r--r--sound/soc/codecs/rt5660.c2
-rw-r--r--sound/soc/codecs/rt5663.c4
-rw-r--r--sound/soc/codecs/rt5665.c4
-rw-r--r--sound/soc/codecs/rt5668.c4
-rw-r--r--sound/soc/codecs/rt5670.c6
-rw-r--r--sound/soc/codecs/rt5677.c2
-rw-r--r--sound/soc/codecs/rt5682-i2c.c4
-rw-r--r--sound/soc/codecs/rt5682-sdw.c14
-rw-r--r--sound/soc/codecs/rt5682.c14
-rw-r--r--sound/soc/codecs/rt5682s.c4
-rw-r--r--sound/soc/codecs/rt700-sdw.c17
-rw-r--r--sound/soc/codecs/rt711-sdca-sdw.c15
-rw-r--r--sound/soc/codecs/rt711-sdw.c15
-rw-r--r--sound/soc/codecs/rt712-sdca-dmic.c18
-rw-r--r--sound/soc/codecs/rt712-sdca-sdw.c15
-rw-r--r--sound/soc/codecs/rt715-sdca-sdw.c17
-rw-r--r--sound/soc/codecs/rt715-sdw.c17
-rw-r--r--sound/soc/codecs/rt721-sdca-sdw.c15
-rw-r--r--sound/soc/codecs/rt722-sdca-sdw.c54
-rw-r--r--sound/soc/codecs/rt722-sdca.c369
-rw-r--r--sound/soc/codecs/rt722-sdca.h27
-rw-r--r--sound/soc/codecs/rt9123.c1
-rw-r--r--sound/soc/codecs/rt9123p.c1
-rw-r--r--sound/soc/codecs/rtq9124.c1
-rw-r--r--sound/soc/codecs/rtq9128.c1
-rw-r--r--sound/soc/codecs/sdw-mockup.c1
-rw-r--r--sound/soc/codecs/sgtl5000.c4
-rw-r--r--sound/soc/codecs/sigmadsp.c4
-rw-r--r--sound/soc/codecs/simple-amplifier.c917
-rw-r--r--sound/soc/codecs/simple-mux.c2
-rw-r--r--sound/soc/codecs/sma1303.c5
-rw-r--r--sound/soc/codecs/sma1307.c39
-rw-r--r--sound/soc/codecs/src4xxx-i2c.c3
-rw-r--r--sound/soc/codecs/ssm2518.c2
-rw-r--r--sound/soc/codecs/ssm2602-i2c.c6
-rw-r--r--sound/soc/codecs/ssm4567.c2
-rw-r--r--sound/soc/codecs/sta32x.c6
-rw-r--r--sound/soc/codecs/sta350.c8
-rw-r--r--sound/soc/codecs/sta529.c2
-rw-r--r--sound/soc/codecs/tac5xx2-sdw.c2039
-rw-r--r--sound/soc/codecs/tac5xx2.h259
-rw-r--r--sound/soc/codecs/tas2552.c2
-rw-r--r--sound/soc/codecs/tas2562.c6
-rw-r--r--sound/soc/codecs/tas2764.c2
-rw-r--r--sound/soc/codecs/tas2770.c2
-rw-r--r--sound/soc/codecs/tas2780.c2
-rw-r--r--sound/soc/codecs/tas2781-fmwlib.c7
-rw-r--r--sound/soc/codecs/tas2781-i2c.c49
-rw-r--r--sound/soc/codecs/tas2783-sdw.c97
-rw-r--r--sound/soc/codecs/tas2783.h8
-rw-r--r--sound/soc/codecs/tas5086.c12
-rw-r--r--sound/soc/codecs/tas571x.c14
-rw-r--r--sound/soc/codecs/tas5720.c6
-rw-r--r--sound/soc/codecs/tas5805m.c2
-rw-r--r--sound/soc/codecs/tas6424.c2
-rw-r--r--sound/soc/codecs/tas675x.c2194
-rw-r--r--sound/soc/codecs/tas675x.h367
-rw-r--r--sound/soc/codecs/tda7419.c2
-rw-r--r--sound/soc/codecs/tfa9879.c2
-rw-r--r--sound/soc/codecs/tlv320adc3xxx.c6
-rw-r--r--sound/soc/codecs/tlv320adcx140.c8
-rw-r--r--sound/soc/codecs/tlv320aic23-i2c.c4
-rw-r--r--sound/soc/codecs/tlv320aic31xx.c16
-rw-r--r--sound/soc/codecs/tlv320aic32x4-i2c.c6
-rw-r--r--sound/soc/codecs/tlv320aic3x-i2c.c10
-rw-r--r--sound/soc/codecs/tlv320aic3x.c32
-rw-r--r--sound/soc/codecs/ts3a227e.c2
-rw-r--r--sound/soc/codecs/tscs42xx.c4
-rw-r--r--sound/soc/codecs/tscs454.c2
-rw-r--r--sound/soc/codecs/uda1334.c1
-rw-r--r--sound/soc/codecs/uda1342.c2
-rw-r--r--sound/soc/codecs/uda1380.c15
-rw-r--r--sound/soc/codecs/wcd937x.c11
-rw-r--r--sound/soc/codecs/wcd938x.c11
-rw-r--r--sound/soc/codecs/wcd939x.c11
-rw-r--r--sound/soc/codecs/wm1250-ev1.c2
-rw-r--r--sound/soc/codecs/wm2000.c2
-rw-r--r--sound/soc/codecs/wm2200.c2
-rw-r--r--sound/soc/codecs/wm5100.c2
-rw-r--r--sound/soc/codecs/wm8510.c3
-rw-r--r--sound/soc/codecs/wm8523.c3
-rw-r--r--sound/soc/codecs/wm8524.c1
-rw-r--r--sound/soc/codecs/wm8580.c5
-rw-r--r--sound/soc/codecs/wm8711.c3
-rw-r--r--sound/soc/codecs/wm8728.c3
-rw-r--r--sound/soc/codecs/wm8731-i2c.c3
-rw-r--r--sound/soc/codecs/wm8731-spi.c1
-rw-r--r--sound/soc/codecs/wm8737.c3
-rw-r--r--sound/soc/codecs/wm8741.c2
-rw-r--r--sound/soc/codecs/wm8750.c4
-rw-r--r--sound/soc/codecs/wm8753.c3
-rw-r--r--sound/soc/codecs/wm8770.c1
-rw-r--r--sound/soc/codecs/wm8776.c5
-rw-r--r--sound/soc/codecs/wm8804-i2c.c2
-rw-r--r--sound/soc/codecs/wm8900.c8
-rw-r--r--sound/soc/codecs/wm8903.c2
-rw-r--r--sound/soc/codecs/wm8904.c6
-rw-r--r--sound/soc/codecs/wm8940.c2
-rw-r--r--sound/soc/codecs/wm8955.c2
-rw-r--r--sound/soc/codecs/wm8960.c2
-rw-r--r--sound/soc/codecs/wm8961.c2
-rw-r--r--sound/soc/codecs/wm8962.c2
-rw-r--r--sound/soc/codecs/wm8971.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.c4
-rw-r--r--sound/soc/codecs/wm8988.c2
-rw-r--r--sound/soc/codecs/wm8990.c2
-rw-r--r--sound/soc/codecs/wm8991.c2
-rw-r--r--sound/soc/codecs/wm8993.c2
-rw-r--r--sound/soc/codecs/wm8995.c4
-rw-r--r--sound/soc/codecs/wm8996.c2
-rw-r--r--sound/soc/codecs/wm9081.c8
-rw-r--r--sound/soc/codecs/wm9090.c4
-rw-r--r--sound/soc/codecs/wm_adsp.c10
-rw-r--r--sound/soc/codecs/wsa881x.c45
-rw-r--r--sound/soc/fsl/Kconfig7
-rw-r--r--sound/soc/fsl/eukrea-tlv320.c11
-rw-r--r--sound/soc/fsl/fsl-asoc-card.c111
-rw-r--r--sound/soc/fsl/fsl_asrc_dma.c20
-rw-r--r--sound/soc/fsl/fsl_aud2htx.c1
-rw-r--r--sound/soc/fsl/fsl_audmix.c6
-rw-r--r--sound/soc/fsl/fsl_micfil.c79
-rw-r--r--sound/soc/fsl/fsl_micfil.h1
-rw-r--r--sound/soc/fsl/fsl_qmc_audio.c7
-rw-r--r--sound/soc/fsl/fsl_sai.c52
-rw-r--r--sound/soc/fsl/fsl_sai.h2
-rw-r--r--sound/soc/fsl/imx-pcm-rpmsg.c12
-rw-r--r--sound/soc/fsl/imx-rpmsg.c38
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c1
-rw-r--r--sound/soc/generic/audio-graph-card2-custom-sample.c1
-rw-r--r--sound/soc/generic/simple-card.c61
-rw-r--r--sound/soc/generic/test-component.c7
-rw-r--r--sound/soc/hisilicon/hi6210-i2s.c6
-rw-r--r--sound/soc/img/img-spdif-in.c70
-rw-r--r--sound/soc/img/img-spdif-out.c16
-rw-r--r--sound/soc/intel/boards/Kconfig1
-rw-r--r--sound/soc/intel/boards/bytcht_es8316.c29
-rw-r--r--sound/soc/intel/boards/cht_bsw_rt5672.c73
-rw-r--r--sound/soc/intel/boards/sof_sdw.c31
-rw-r--r--sound/soc/intel/catpt/Makefile3
-rw-r--r--sound/soc/intel/catpt/core.h1
-rw-r--r--sound/soc/intel/catpt/device.c14
-rw-r--r--sound/soc/intel/catpt/dsp.c19
-rw-r--r--sound/soc/intel/catpt/ipc.c17
-rw-r--r--sound/soc/intel/catpt/loader.c10
-rw-r--r--sound/soc/intel/catpt/pcm.c63
-rw-r--r--sound/soc/intel/catpt/registers.h14
-rw-r--r--sound/soc/intel/catpt/trace.c27
-rw-r--r--sound/soc/intel/catpt/trace.h22
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-arl-match.c123
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-mtl-match.c132
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-nvl-match.c13
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-ptl-match.c134
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c16
-rw-r--r--sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h1
-rw-r--r--sound/soc/intel/common/sof-function-topology-lib.c11
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c1
-rw-r--r--sound/soc/loongson/Makefile4
-rw-r--r--sound/soc/loongson/loongson_dma.c160
-rw-r--r--sound/soc/loongson/loongson_dma.h6
-rw-r--r--sound/soc/loongson/loongson_i2s.c56
-rw-r--r--sound/soc/loongson/loongson_i2s.h7
-rw-r--r--sound/soc/loongson/loongson_i2s_pci.c59
-rw-r--r--sound/soc/loongson/loongson_i2s_plat.c67
-rw-r--r--sound/soc/mediatek/Kconfig40
-rw-r--r--sound/soc/mediatek/Makefile1
-rw-r--r--sound/soc/mediatek/common/mtk-afe-fe-dai.c8
-rw-r--r--sound/soc/mediatek/common/mtk-afe-platform-driver.c56
-rw-r--r--sound/soc/mediatek/common/mtk-afe-platform-driver.h2
-rw-r--r--sound/soc/mediatek/common/mtk-btcvsd.c81
-rw-r--r--sound/soc/mediatek/common/mtk-dsp-sof-common.c13
-rw-r--r--sound/soc/mediatek/common/mtk-dsp-sof-common.h5
-rw-r--r--sound/soc/mediatek/common/mtk-soundcard-driver.c22
-rw-r--r--sound/soc/mediatek/mt2701/Makefile1
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c26
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-afe-common.h8
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-afe-pcm.c305
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-hdmi.c114
-rw-r--r--sound/soc/mediatek/mt2701/mt2701-reg.h29
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-afe-pcm.c39
-rw-r--r--sound/soc/mediatek/mt8173/mt8173-max98090.c4
-rw-r--r--sound/soc/mediatek/mt8183/mt8183-afe-pcm.c23
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-afe-gpio.c13
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-common.c6
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366-common.h2
-rw-r--r--sound/soc/mediatek/mt8186/mt8186-mt6366.c18
-rw-r--r--sound/soc/mediatek/mt8188/mt8188-afe-clk.c29
-rw-r--r--sound/soc/mediatek/mt8189/mt8189-afe-pcm.c38
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-gpio.c4
-rw-r--r--sound/soc/mediatek/mt8192/mt8192-afe-pcm.c21
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-afe-clk.c42
-rw-r--r--sound/soc/mediatek/mt8195/mt8195-dai-etdm.c16
-rw-r--r--sound/soc/mediatek/mt8196/Makefile14
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-afe-clk.c581
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-afe-clk.h64
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-afe-common.h205
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-afe-pcm.c2519
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-dai-adda.c845
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-dai-i2s.c2613
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-dai-tdm.c675
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-interconnection.h121
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-nau8825.c870
-rw-r--r--sound/soc/mediatek/mt8196/mt8196-reg.h12068
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-afe-clk.c30
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-afe-pcm.c13
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-dai-adda.c10
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-dai-i2s.c5
-rw-r--r--sound/soc/mediatek/mt8365/mt8365-mt6357.c11
-rw-r--r--sound/soc/meson/aiu-acodec-ctrl.c3
-rw-r--r--sound/soc/meson/aiu-codec-ctrl.c3
-rw-r--r--sound/soc/meson/axg-tdm-formatter.c22
-rw-r--r--sound/soc/pxa/Kconfig6
-rw-r--r--sound/soc/pxa/Makefile4
-rw-r--r--sound/soc/pxa/mmp-sspa.c2
-rw-r--r--sound/soc/pxa/pxa-ssp.c2
-rw-r--r--sound/soc/pxa/pxa2xx-ac97-lib.c (renamed from sound/arm/pxa2xx-ac97-lib.c)39
-rw-r--r--sound/soc/pxa/pxa2xx-ac97-regs.h (renamed from sound/arm/pxa2xx-ac97-regs.h)0
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c6
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c2
-rw-r--r--sound/soc/pxa/pxa2xx-lib.h45
-rw-r--r--sound/soc/pxa/pxa2xx-pcm-lib.c (renamed from sound/arm/pxa2xx-pcm-lib.c)26
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c3
-rw-r--r--sound/soc/qcom/apq8096.c1
-rw-r--r--sound/soc/qcom/common.c47
-rw-r--r--sound/soc/qcom/qdsp6/audioreach.c79
-rw-r--r--sound/soc/qcom/qdsp6/audioreach.h96
-rw-r--r--sound/soc/qcom/qdsp6/q6apm-dai.c151
-rw-r--r--sound/soc/qcom/qdsp6/q6apm.c230
-rw-r--r--sound/soc/qcom/qdsp6/q6apm.h13
-rw-r--r--sound/soc/qcom/qdsp6/q6asm-dai.c48
-rw-r--r--sound/soc/qcom/sc7280.c1
-rw-r--r--sound/soc/qcom/storm.c1
-rw-r--r--sound/soc/renesas/Kconfig1
-rw-r--r--sound/soc/renesas/fsi.c288
-rw-r--r--sound/soc/renesas/rcar/adg.c197
-rw-r--r--sound/soc/renesas/rcar/cmd.c2
-rw-r--r--sound/soc/renesas/rcar/core.c173
-rw-r--r--sound/soc/renesas/rcar/ctu.c29
-rw-r--r--sound/soc/renesas/rcar/dma.c280
-rw-r--r--sound/soc/renesas/rcar/dvc.c29
-rw-r--r--sound/soc/renesas/rcar/gen.c180
-rw-r--r--sound/soc/renesas/rcar/mix.c29
-rw-r--r--sound/soc/renesas/rcar/msiof.c5
-rw-r--r--sound/soc/renesas/rcar/rsnd.h73
-rw-r--r--sound/soc/renesas/rcar/src.c93
-rw-r--r--sound/soc/renesas/rcar/ssi.c49
-rw-r--r--sound/soc/renesas/rcar/ssiu.c92
-rw-r--r--sound/soc/renesas/rz-ssi.c399
-rw-r--r--sound/soc/rockchip/rk3399_gru_sound.c2
-rw-r--r--sound/soc/rockchip/rockchip_i2s.c230
-rw-r--r--sound/soc/rockchip/rockchip_i2s_tdm.c10
-rw-r--r--sound/soc/rockchip/rockchip_pdm.c16
-rw-r--r--sound/soc/rockchip/rockchip_sai.c1
-rw-r--r--sound/soc/rockchip/rockchip_spdif.c11
-rw-r--r--sound/soc/samsung/i2s.c118
-rw-r--r--sound/soc/samsung/idma.c26
-rw-r--r--sound/soc/samsung/odroid.c21
-rw-r--r--sound/soc/samsung/pcm.c99
-rw-r--r--sound/soc/samsung/spdif.c25
-rw-r--r--sound/soc/sdca/Kconfig2
-rw-r--r--sound/soc/sdca/sdca_asoc.c109
-rw-r--r--sound/soc/sdca/sdca_class.c61
-rw-r--r--sound/soc/sdca/sdca_class.h4
-rw-r--r--sound/soc/sdca/sdca_class_function.c23
-rw-r--r--sound/soc/sdca/sdca_function_device.c24
-rw-r--r--sound/soc/sdca/sdca_functions.c51
-rw-r--r--sound/soc/sdca/sdca_interrupts.c3
-rw-r--r--sound/soc/sdca/sdca_jack.c76
-rw-r--r--sound/soc/sdw_utils/Makefile1
-rw-r--r--sound/soc/sdw_utils/soc_sdw_es9356.c230
-rw-r--r--sound/soc/sdw_utils/soc_sdw_ti_amp.c134
-rw-r--r--sound/soc/sdw_utils/soc_sdw_utils.c323
-rw-r--r--sound/soc/soc-card.c13
-rw-r--r--sound/soc/soc-core.c344
-rw-r--r--sound/soc/soc-dai.c225
-rw-r--r--sound/soc/soc-dapm.c109
-rw-r--r--sound/soc/soc-devres.c28
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c5
-rw-r--r--sound/soc/soc-ops.c4
-rw-r--r--sound/soc/soc-pcm.c119
-rw-r--r--sound/soc/soc-topology.c37
-rw-r--r--sound/soc/soc-utils.c8
-rw-r--r--sound/soc/sof/amd/acp-common.c3
-rw-r--r--sound/soc/sof/amd/acp-ipc.c4
-rw-r--r--sound/soc/sof/amd/acp.c30
-rw-r--r--sound/soc/sof/amd/acp.h2
-rw-r--r--sound/soc/sof/intel/Kconfig6
-rw-r--r--sound/soc/sof/intel/hda-mlink.c11
-rw-r--r--sound/soc/sof/intel/hda.c14
-rw-r--r--sound/soc/sof/intel/lnl.c40
-rw-r--r--sound/soc/sof/ipc3-control.c79
-rw-r--r--sound/soc/sof/ipc3-topology.c10
-rw-r--r--sound/soc/sof/ipc4-control.c124
-rw-r--r--sound/soc/sof/ipc4-topology.c151
-rw-r--r--sound/soc/sof/nocodec.c4
-rw-r--r--sound/soc/sof/sof-client-ipc-flood-test.c1
-rw-r--r--sound/soc/sof/sof-client-ipc-kernel-injector.c1
-rw-r--r--sound/soc/sof/sof-client-ipc-msg-injector.c1
-rw-r--r--sound/soc/sof/sof-client-probes-ipc3.c23
-rw-r--r--sound/soc/sof/sof-client-probes-ipc4.c11
-rw-r--r--sound/soc/sof/topology.c71
-rw-r--r--sound/soc/spacemit/k1_i2s.c36
-rw-r--r--sound/soc/sprd/sprd-mcdt.c66
-rw-r--r--sound/soc/sti/uniperif_player.c73
-rw-r--r--sound/soc/sti/uniperif_reader.c20
-rw-r--r--sound/soc/stm/stm32_adfsdm.c29
-rw-r--r--sound/soc/stm/stm32_i2s.c67
-rw-r--r--sound/soc/stm/stm32_sai_sub.c29
-rw-r--r--sound/soc/stm/stm32_spdifrx.c44
-rw-r--r--sound/soc/sunxi/sun50i-codec-analog.c1
-rw-r--r--sound/soc/sunxi/sun50i-dmic.c1
-rw-r--r--sound/soc/tegra/tegra186_asrc.c1
-rw-r--r--sound/soc/tegra/tegra186_dspk.c1
-rw-r--r--sound/soc/tegra/tegra20_ac97.c2
-rw-r--r--sound/soc/tegra/tegra20_das.c2
-rw-r--r--sound/soc/tegra/tegra20_i2s.c2
-rw-r--r--sound/soc/tegra/tegra20_spdif.c1
-rw-r--r--sound/soc/tegra/tegra210_admaif.c28
-rw-r--r--sound/soc/tegra/tegra210_admaif.h2
-rw-r--r--sound/soc/tegra/tegra210_adx.c92
-rw-r--r--sound/soc/tegra/tegra210_adx.h5
-rw-r--r--sound/soc/tegra/tegra210_ahub.c4
-rw-r--r--sound/soc/tegra/tegra210_amx.c83
-rw-r--r--sound/soc/tegra/tegra210_amx.h5
-rw-r--r--sound/soc/tegra/tegra210_dmic.c1
-rw-r--r--sound/soc/tegra/tegra210_i2s.c1
-rw-r--r--sound/soc/tegra/tegra210_mixer.c289
-rw-r--r--sound/soc/tegra/tegra210_mixer.h21
-rw-r--r--sound/soc/tegra/tegra210_mvc.c4
-rw-r--r--sound/soc/tegra/tegra210_ope.c1
-rw-r--r--sound/soc/tegra/tegra30_ahub.c2
-rw-r--r--sound/soc/tegra/tegra30_i2s.c2
-rw-r--r--sound/soc/tegra/tegra_isomgr_bw.c20
-rw-r--r--sound/soc/ti/ams-delta.c47
-rw-r--r--sound/soc/ti/davinci-mcasp.c183
-rw-r--r--sound/soc/ti/j721e-evm.c47
-rw-r--r--sound/soc/ti/omap-dmic.c47
-rw-r--r--sound/soc/ti/omap-hdmi.c18
-rw-r--r--sound/soc/ti/omap-mcbsp-st.c26
-rw-r--r--sound/soc/ti/omap-mcbsp.c92
-rw-r--r--sound/soc/ti/omap-mcpdm.c9
-rw-r--r--sound/soc/ti/omap3pandora.c5
-rw-r--r--sound/soc/ti/rx51.c4
-rw-r--r--sound/soc/uniphier/aio-compress.c24
-rw-r--r--sound/soc/uniphier/aio-dma.c52
-rw-r--r--sound/soc/ux500/mop500_ab8500.c24
-rw-r--r--sound/synth/emux/emux_seq.c11
-rw-r--r--sound/usb/6fire/control.c13
-rw-r--r--sound/usb/caiaq/input.c12
-rw-r--r--sound/usb/card.c14
-rw-r--r--sound/usb/endpoint.c10
-rw-r--r--sound/usb/fcp.c6
-rw-r--r--sound/usb/midi.c12
-rw-r--r--sound/usb/midi2.c17
-rw-r--r--sound/usb/misc/ua101.c5
-rw-r--r--sound/usb/mixer.c149
-rw-r--r--sound/usb/mixer.h1
-rw-r--r--sound/usb/mixer_quirks.c148
-rw-r--r--sound/usb/mixer_scarlett.c4
-rw-r--r--sound/usb/mixer_scarlett2.c534
-rw-r--r--sound/usb/mixer_us16x08.c127
-rw-r--r--sound/usb/qcom/mixer_usb_offload.c6
-rw-r--r--sound/usb/qcom/qc_audio_offload.c76
-rw-r--r--sound/usb/quirks-table.h22
-rw-r--r--sound/usb/quirks.c18
-rw-r--r--sound/usb/usbaudio.h26
-rw-r--r--sound/usb/usx2y/us144mkii.c17
-rw-r--r--sound/usb/usx2y/us144mkii_capture.c2
-rw-r--r--sound/usb/usx2y/usbusx2y.c39
-rw-r--r--sound/virtio/virtio_kctl.c50
-rw-r--r--sound/virtio/virtio_pcm.c3
-rw-r--r--sound/virtio/virtio_pcm_ops.c3
-rw-r--r--sound/xen/xen_snd_front_alsa.c17
-rw-r--r--sound/xen/xen_snd_front_evtchnl.c28
-rw-r--r--sound/xen/xen_snd_front_evtchnl.h6
727 files changed, 40516 insertions, 6118 deletions
diff --git a/sound/ac97/bus.c b/sound/ac97/bus.c
index 15487837e894..a4d230a19c56 100644
--- a/sound/ac97/bus.c
+++ b/sound/ac97/bus.c
@@ -206,24 +206,6 @@ void snd_ac97_codec_driver_unregister(struct ac97_codec_driver *drv)
}
EXPORT_SYMBOL_GPL(snd_ac97_codec_driver_unregister);
-/**
- * snd_ac97_codec_get_platdata - get platform_data
- * @adev: the ac97 codec device
- *
- * For legacy platforms, in order to have platform_data in codec drivers
- * available, while ac97 device are auto-created upon probe, this retrieves the
- * platdata which was setup on ac97 controller registration.
- *
- * Returns the platform data pointer
- */
-void *snd_ac97_codec_get_platdata(const struct ac97_codec_device *adev)
-{
- struct ac97_controller *ac97_ctrl = adev->ac97_ctrl;
-
- return ac97_ctrl->codecs_pdata[adev->num];
-}
-EXPORT_SYMBOL_GPL(snd_ac97_codec_get_platdata);
-
static void ac97_ctrl_codecs_unregister(struct ac97_controller *ac97_ctrl)
{
int i;
@@ -337,7 +319,6 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
* @dev: the device providing the ac97 DC function
* @slots_available: mask of the ac97 codecs that can be scanned and probed
* bit0 => codec 0, bit1 => codec 1 ... bit 3 => codec 3
- * @codecs_pdata: codec platform data
*
* Register a digital controller which can control up to 4 ac97 codecs. This is
* the controller side of the AC97 AC-link, while the slave side are the codecs.
@@ -346,18 +327,15 @@ static int ac97_add_adapter(struct ac97_controller *ac97_ctrl)
*/
struct ac97_controller *snd_ac97_controller_register(
const struct ac97_controller_ops *ops, struct device *dev,
- unsigned short slots_available, void **codecs_pdata)
+ unsigned short slots_available)
{
struct ac97_controller *ac97_ctrl;
- int ret, i;
+ int ret;
ac97_ctrl = kzalloc_obj(*ac97_ctrl);
if (!ac97_ctrl)
return ERR_PTR(-ENOMEM);
- for (i = 0; i < AC97_BUS_MAX_CODECS && codecs_pdata; i++)
- ac97_ctrl->codecs_pdata[i] = codecs_pdata[i];
-
ac97_ctrl->ops = ops;
ac97_ctrl->slots_available = slots_available;
ac97_ctrl->parent = dev;
diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c
index 8a44297964f5..ad7fb6b0c2c0 100644
--- a/sound/ac97_bus.c
+++ b/sound/ac97_bus.c
@@ -73,7 +73,6 @@ int snd_ac97_reset(struct snd_ac97 *ac97, bool try_warm, unsigned int id,
if (snd_ac97_check_id(ac97, id, id_mask))
return 0;
-
return -ENODEV;
}
EXPORT_SYMBOL_GPL(snd_ac97_reset);
@@ -81,6 +80,7 @@ EXPORT_SYMBOL_GPL(snd_ac97_reset);
const struct bus_type ac97_bus_type = {
.name = "ac97",
};
+EXPORT_SYMBOL(ac97_bus_type);
static int __init ac97_bus_init(void)
{
@@ -96,7 +96,5 @@ static void __exit ac97_bus_exit(void)
module_exit(ac97_bus_exit);
-EXPORT_SYMBOL(ac97_bus_type);
-
MODULE_DESCRIPTION("Legacy AC97 bus interface");
MODULE_LICENSE("GPL");
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/layout.c
index c3ebb6de4789..7bb541577a26 100644
--- a/sound/aoa/fabrics/layout.c
+++ b/sound/aoa/fabrics/layout.c
@@ -948,6 +948,8 @@ static void layout_attached_codec(struct aoa_codec *codec)
if (lineout == 1)
ldev->gpio.methods->set_lineout(codec->gpio, 1);
ctl = snd_ctl_new1(&lineout_ctl, codec->gpio);
+ if (!ctl)
+ return;
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
strscpy(ctl->id.name, "Headphone Switch");
ldev->lineout_ctrl = ctl;
@@ -961,12 +963,16 @@ static void layout_attached_codec(struct aoa_codec *codec)
if (ldev->have_lineout_detect) {
ctl = snd_ctl_new1(&lineout_detect_choice,
ldev);
+ if (!ctl)
+ return;
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
strscpy(ctl->id.name,
"Headphone Detect Autoswitch");
aoa_snd_ctl_add(ctl);
ctl = snd_ctl_new1(&lineout_detected,
ldev);
+ if (!ctl)
+ return;
if (cc->connected & CC_LINEOUT_LABELLED_HEADPHONE)
strscpy(ctl->id.name,
"Headphone Detected");
diff --git a/sound/arm/Kconfig b/sound/arm/Kconfig
index e4d7288d1e1e..09054ce8074f 100644
--- a/sound/arm/Kconfig
+++ b/sound/arm/Kconfig
@@ -19,10 +19,3 @@ config SND_ARMAACI
select SND_AC97_CODEC
endif # SND_ARM
-
-config SND_PXA2XX_LIB
- tristate
- select SND_DMAENGINE_PCM
-
-config SND_PXA2XX_LIB_AC97
- bool
diff --git a/sound/arm/Makefile b/sound/arm/Makefile
index 99325a66cf77..6b91eb796b9b 100644
--- a/sound/arm/Makefile
+++ b/sound/arm/Makefile
@@ -5,7 +5,3 @@
obj-$(CONFIG_SND_ARMAACI) += snd-aaci.o
snd-aaci-y := aaci.o
-
-obj-$(CONFIG_SND_PXA2XX_LIB) += snd-pxa2xx-lib.o
-snd-pxa2xx-lib-y := pxa2xx-pcm-lib.o
-snd-pxa2xx-lib-$(CONFIG_SND_PXA2XX_LIB_AC97) += pxa2xx-ac97-lib.o
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index df0a049192de..e394205f469b 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -12,7 +12,6 @@
#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/interrupt.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/mutex.h>
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index fd63d219bf86..ea699491f0c3 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -1083,15 +1083,18 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_
file descriptors are allocated before fd_install() */
if (!task->input || !task->input->file || !task->output || !task->output->file) {
retval = -EINVAL;
- goto cleanup;
+ goto free_driver_task;
}
fd_i = get_unused_fd_flags(O_WRONLY|O_CLOEXEC);
- if (fd_i < 0)
- goto cleanup;
+ if (fd_i < 0) {
+ retval = fd_i;
+ goto free_driver_task;
+ }
fd_o = get_unused_fd_flags(O_RDONLY|O_CLOEXEC);
if (fd_o < 0) {
+ retval = fd_o;
put_unused_fd(fd_i);
- goto cleanup;
+ goto free_driver_task;
}
/* keep dmabuf reference until freed with task free ioctl */
get_dma_buf(task->input);
@@ -1103,6 +1106,8 @@ static int snd_compr_task_new(struct snd_compr_stream *stream, struct snd_compr_
list_add_tail(&task->list, &stream->runtime->tasks);
stream->runtime->total_tasks++;
return 0;
+free_driver_task:
+ stream->ops->task_free(stream, task);
cleanup:
snd_compr_task_free(task);
return retval;
diff --git a/sound/core/control.c b/sound/core/control.c
index 5e51857635e6..7a8dc506221e 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -1550,7 +1550,6 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
unsigned int size)
{
struct user_element *ue = snd_kcontrol_chip(kctl);
- unsigned int *container;
unsigned int mask = 0;
int i;
int change;
@@ -1564,17 +1563,16 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
if (check_user_elem_overflow(ue->card, (ssize_t)(size - ue->tlv_data_size)))
return -ENOMEM;
- container = vmemdup_user(buf, size);
+ unsigned int *container __free(kvfree) = vmemdup_user(buf, size);
+
if (IS_ERR(container))
return PTR_ERR(container);
change = ue->tlv_data_size != size;
if (!change)
change = memcmp(ue->tlv_data, container, size) != 0;
- if (!change) {
- kvfree(container);
+ if (!change)
return 0;
- }
if (ue->tlv_data == NULL) {
/* Now TLV data is available. */
@@ -1587,7 +1585,7 @@ static int replace_user_tlv(struct snd_kcontrol *kctl, unsigned int __user *buf,
kvfree(ue->tlv_data);
}
- ue->tlv_data = container;
+ ue->tlv_data = no_free_ptr(container);
ue->tlv_data_size = size;
// decremented at private_free.
ue->card->user_ctl_alloc_size += size;
@@ -1628,7 +1626,6 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kctl, int op_flag,
/* called in controls_rwsem write lock */
static int snd_ctl_elem_init_enum_names(struct user_element *ue)
{
- char *names, *p;
size_t buf_len, name_len;
unsigned int i;
const uintptr_t user_ptrval = ue->info.value.enumerated.names_ptr;
@@ -1641,27 +1638,28 @@ static int snd_ctl_elem_init_enum_names(struct user_element *ue)
if (check_user_elem_overflow(ue->card, buf_len))
return -ENOMEM;
- names = vmemdup_user((const void __user *)user_ptrval, buf_len);
+ char *names __free(kvfree) = vmemdup_user((const void __user *)user_ptrval,
+ buf_len);
+
if (IS_ERR(names))
return PTR_ERR(names);
/* check that there are enough valid names */
- p = names;
+ char *p = names;
+
for (i = 0; i < ue->info.value.enumerated.items; ++i) {
- if (buf_len == 0) {
- kvfree(names);
+ if (buf_len == 0)
return -EINVAL;
- }
+
name_len = strnlen(p, buf_len);
- if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
- kvfree(names);
+ if (name_len == 0 || name_len >= 64 || name_len == buf_len)
return -EINVAL;
- }
+
p += name_len + 1;
buf_len -= name_len + 1;
}
- ue->priv_data = names;
+ ue->priv_data = no_free_ptr(names);
ue->info.value.enumerated.names_ptr = 0;
// increment the allocation size; decremented again at private_free.
ue->card->user_ctl_alloc_size += ue->info.value.enumerated.names_length;
@@ -2293,7 +2291,6 @@ EXPORT_SYMBOL_GPL(snd_ctl_request_layer);
*/
void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops)
{
- struct snd_card *card;
int card_number;
scoped_guard(rwsem_write, &snd_ctl_layer_rwsem) {
@@ -2301,11 +2298,12 @@ void snd_ctl_register_layer(struct snd_ctl_layer_ops *lops)
snd_ctl_layer = lops;
}
for (card_number = 0; card_number < SNDRV_CARDS; card_number++) {
- card = snd_card_ref(card_number);
+ struct snd_card *card __free(snd_card_unref) =
+ snd_card_ref(card_number);
+
if (card) {
scoped_guard(rwsem_read, &card->controls_rwsem)
lops->lregister(card);
- snd_card_unref(card);
}
}
}
diff --git a/sound/core/control_led.c b/sound/core/control_led.c
index d92b36ab5ec6..8cbacee57ce7 100644
--- a/sound/core/control_led.c
+++ b/sound/core/control_led.c
@@ -240,8 +240,6 @@ static void snd_ctl_led_notify(struct snd_card *card, unsigned int mask,
}
}
-DEFINE_FREE(snd_card_unref, struct snd_card *, if (_T) snd_card_unref(_T))
-
static int snd_ctl_led_set_id(int card_number, struct snd_ctl_elem_id *id,
unsigned int group, bool set)
{
@@ -758,18 +756,17 @@ static int __init snd_ctl_led_init(void)
static void __exit snd_ctl_led_exit(void)
{
struct snd_ctl_led *led;
- struct snd_card *card;
unsigned int group, card_number;
snd_ctl_disconnect_layer(&snd_ctl_led_lops);
for (card_number = 0; card_number < SNDRV_CARDS; card_number++) {
if (!snd_ctl_led_card_valid[card_number])
continue;
- card = snd_card_ref(card_number);
- if (card) {
+ struct snd_card *card __free(snd_card_unref) =
+ snd_card_ref(card_number);
+
+ if (card)
snd_ctl_led_sysfs_remove(card);
- snd_card_unref(card);
- }
}
for (group = 0; group < MAX_LED; group++) {
led = &snd_ctl_leds[group];
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
index 9fcd1c03dc5b..92c585f8eeb1 100644
--- a/sound/core/hrtimer.c
+++ b/sound/core/hrtimer.c
@@ -20,7 +20,7 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_HRTIMER));
#define NANO_SEC 1000000000UL /* 10^9 in sec */
-static unsigned int resolution;
+static unsigned int resolution __ro_after_init;
struct snd_hrtimer {
struct snd_timer *timer;
diff --git a/sound/core/init.c b/sound/core/init.c
index 0c316189e947..56dde5bd73c4 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -181,7 +181,7 @@ int snd_card_new(struct device *parent, int idx, const char *xid,
if (extra_size < 0)
extra_size = 0;
- card = kzalloc(sizeof(*card) + extra_size, GFP_KERNEL);
+ card = kzalloc_flex(*card, private_data_area, extra_size);
if (!card)
return -ENOMEM;
@@ -232,7 +232,8 @@ int snd_devm_card_new(struct device *parent, int idx, const char *xid,
int err;
*card_ret = NULL;
- card = devres_alloc(__snd_card_release, sizeof(*card) + extra_size,
+ card = devres_alloc(__snd_card_release,
+ struct_size(card, private_data_area, extra_size),
GFP_KERNEL);
if (!card)
return -ENOMEM;
@@ -280,7 +281,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
int err;
if (extra_size > 0)
- card->private_data = (char *)card + sizeof(struct snd_card);
+ card->private_data = card->private_data_area;
if (xid)
strscpy(card->id, xid, sizeof(card->id));
err = 0;
@@ -327,8 +328,7 @@ static int snd_card_init(struct snd_card *card, struct device *parent,
mutex_init(&card->memory_mutex);
#ifdef CONFIG_PM
init_waitqueue_head(&card->power_sleep);
- init_waitqueue_head(&card->power_ref_sleep);
- atomic_set(&card->power_ref, 0);
+ snd_refcount_init(&card->power_ref);
#endif
init_waitqueue_head(&card->remove_sleep);
card->sync_irq = -1;
@@ -1139,7 +1139,7 @@ EXPORT_SYMBOL(snd_card_file_remove);
* typically around calling control ops.
*
* The caller needs to pull down the refcount via snd_power_unref() later
- * no matter whether the error is returned from this function or not.
+ * when this function returns 0.
*
* Return: Zero if successful, or a negative error code.
*/
@@ -1152,7 +1152,11 @@ int snd_power_ref_and_wait(struct snd_card *card)
card->shutdown ||
snd_power_get_state(card) == SNDRV_CTL_POWER_D0,
snd_power_unref(card), snd_power_ref(card));
- return card->shutdown ? -ENODEV : 0;
+ if (card->shutdown) {
+ snd_power_unref(card);
+ return -ENODEV;
+ }
+ return 0;
}
EXPORT_SYMBOL_GPL(snd_power_ref_and_wait);
@@ -1169,7 +1173,8 @@ int snd_power_wait(struct snd_card *card)
int ret;
ret = snd_power_ref_and_wait(card);
- snd_power_unref(card);
+ if (!ret)
+ snd_power_unref(card);
return ret;
}
EXPORT_SYMBOL(snd_power_wait);
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 5e8a2f3f4196..96e0733ede77 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -250,18 +250,15 @@ static const char * const jack_events_name[] = {
/* the recommended buffer size is 256 */
static int parse_mask_bits(unsigned int mask_bits, char *buf, size_t buf_size)
{
+ int len = scnprintf(buf, buf_size, "0x%04x", mask_bits);
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);
+ if (mask_bits & (1 << i))
+ len += scnprintf(buf + len, buf_size - len, " %s", jack_events_name[i]);
+ len += scnprintf(buf + len, buf_size - len, "\n");
- return strlen(buf);
+ return len;
}
static ssize_t jack_kctl_mask_bits_read(struct file *file,
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 833124c8e4fa..4772b2a3b808 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -174,3 +174,27 @@ void snd_fasync_free(struct snd_fasync *fasync)
kfree(fasync);
}
EXPORT_SYMBOL_GPL(snd_fasync_free);
+
+/*
+ * generic refcount helper
+ */
+
+void snd_refcount_init(struct snd_refcount *ref)
+{
+ atomic_set(&ref->count, 0);
+ init_waitqueue_head(&ref->waiter);
+}
+EXPORT_SYMBOL_GPL(snd_refcount_init);
+
+void snd_refcount_put(struct snd_refcount *ref)
+{
+ if (atomic_dec_and_test(&ref->count))
+ wake_up(&ref->waiter);
+}
+EXPORT_SYMBOL_GPL(snd_refcount_put);
+
+void snd_refcount_sync(struct snd_refcount *ref)
+{
+ wait_event(ref->waiter, !atomic_read(&ref->count));
+}
+EXPORT_SYMBOL_GPL(snd_refcount_sync);
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 33fd34f0d615..9826d9a0be6d 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -32,8 +32,8 @@
#define OSS_ALSAEMULVER _SIOR ('M', 249, int)
-static int dsp_map[SNDRV_CARDS];
-static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
+static int dsp_map[SNDRV_CARDS] __ro_after_init;
+static int adsp_map[SNDRV_CARDS] __ro_after_init = {[0 ... (SNDRV_CARDS-1)] = 1};
static bool nonblock_open = 1;
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
@@ -2974,8 +2974,10 @@ static void snd_pcm_oss_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_pcm_str *pstr = entry->private_data;
- struct snd_pcm_oss_setup *setup = pstr->oss.setup_list;
+ struct snd_pcm_oss_setup *setup;
+
guard(mutex)(&pstr->oss.setup_mutex);
+ setup = pstr->oss.setup_list;
while (setup) {
snd_iprintf(buffer, "%s %u %u%s%s%s%s%s%s\n",
setup->task_name,
@@ -3060,6 +3062,13 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
buffer->error = -ENOMEM;
return;
}
+ template.task_name = kstrdup(task_name, GFP_KERNEL);
+ if (!template.task_name) {
+ kfree(setup);
+ buffer->error = -ENOMEM;
+ return;
+ }
+ *setup = template;
if (pstr->oss.setup_list == NULL)
pstr->oss.setup_list = setup;
else {
@@ -3067,12 +3076,7 @@ static void snd_pcm_oss_proc_write(struct snd_info_entry *entry,
setup1->next; setup1 = setup1->next);
setup1->next = setup;
}
- template.task_name = kstrdup(task_name, GFP_KERNEL);
- if (! template.task_name) {
- kfree(setup);
- buffer->error = -ENOMEM;
- return;
- }
+ continue;
}
*setup = template;
}
diff --git a/sound/core/oss/pcm_plugin.c b/sound/core/oss/pcm_plugin.c
index 14b4a390a219..5f4d6945a7df 100644
--- a/sound/core/oss/pcm_plugin.c
+++ b/sound/core/oss/pcm_plugin.c
@@ -146,7 +146,7 @@ int snd_pcm_plugin_build(struct snd_pcm_substream *plug,
return -ENXIO;
if (snd_BUG_ON(!src_format || !dst_format))
return -ENXIO;
- plugin = kzalloc(sizeof(*plugin) + extra, GFP_KERNEL);
+ plugin = kzalloc_flex(*plugin, extra_data, extra);
if (plugin == NULL)
return -ENOMEM;
plugin->name = name;
diff --git a/sound/core/pcm_compat.c b/sound/core/pcm_compat.c
index 5313f50f17da..55ecf87586c4 100644
--- a/sound/core/pcm_compat.c
+++ b/sound/core/pcm_compat.c
@@ -293,7 +293,7 @@ static int snd_pcm_ioctl_xferi_compat(struct snd_pcm_substream *substream,
return -ENOTTY;
if (substream->stream != dir)
return -EINVAL;
- if (substream->runtime->state == SNDRV_PCM_STATE_OPEN)
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (get_user(buf, &data32->buf) ||
@@ -338,7 +338,7 @@ static int snd_pcm_ioctl_xfern_compat(struct snd_pcm_substream *substream,
return -ENOTTY;
if (substream->stream != dir)
return -EINVAL;
- if (substream->runtime->state == SNDRV_PCM_STATE_OPEN)
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
ch = substream->runtime->channels;
diff --git a/sound/core/pcm_drm_eld.c b/sound/core/pcm_drm_eld.c
index cb2eebaac85f..1941ee520063 100644
--- a/sound/core/pcm_drm_eld.c
+++ b/sound/core/pcm_drm_eld.c
@@ -334,7 +334,7 @@ int snd_parse_eld(struct device *dev, struct snd_parsed_hdmi_eld *e,
e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
if (e->eld_ver != ELD_VER_CEA_861D &&
e->eld_ver != ELD_VER_PARTIAL) {
- dev_info(dev, "HDMI: Unknown ELD version %d\n", e->eld_ver);
+ dev_info_ratelimited(dev, "HDMI: Unknown ELD version %d\n", e->eld_ver);
goto out_fail;
}
@@ -357,7 +357,7 @@ int snd_parse_eld(struct device *dev, struct snd_parsed_hdmi_eld *e,
e->product_id = get_unaligned_le16(buf + 18);
if (mnl > ELD_MAX_MNL) {
- dev_info(dev, "HDMI: MNL is reserved value %d\n", mnl);
+ dev_info_ratelimited(dev, "HDMI: MNL is reserved value %d\n", mnl);
goto out_fail;
} else if (ELD_FIXED_BYTES + mnl > size) {
dev_info(dev, "HDMI: out of range MNL %d\n", mnl);
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 09c421cd9319..4d665b4148d7 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -545,7 +545,7 @@ void snd_pcm_set_sync_per_card(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
const unsigned char *id, unsigned int len)
{
- *(__u32 *)params->sync = cpu_to_le32(substream->pcm->card->number);
+ *(__le32 *)params->sync = cpu_to_le32(substream->pcm->card->number);
len = min(12, len);
memcpy(params->sync + 4, id, len);
memset(params->sync + 4 + len, 0, 12 - len);
@@ -2138,6 +2138,9 @@ static int interleaved_copy(struct snd_pcm_substream *substream,
off = frames_to_bytes(runtime, off);
frames = frames_to_bytes(runtime, frames);
+ if (!data)
+ return fill_silence(substream, 0, hwoff, NULL, frames);
+
return do_transfer(substream, 0, hwoff, data + off, frames, transfer,
in_kernel);
}
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index a541bb235cfa..7dc0060617f1 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -645,6 +645,14 @@ snd_pcm_state_t snd_pcm_get_state(struct snd_pcm_substream *substream)
}
EXPORT_SYMBOL_GPL(snd_pcm_get_state);
+static bool snd_pcm_state_open_or_disconnected(struct snd_pcm_substream *substream)
+{
+ snd_pcm_state_t state = snd_pcm_get_state(substream);
+
+ return state == SNDRV_PCM_STATE_OPEN ||
+ state == SNDRV_PCM_STATE_DISCONNECTED;
+}
+
static inline void snd_pcm_timer_notify(struct snd_pcm_substream *substream,
int event)
{
@@ -1973,13 +1981,15 @@ static int snd_pcm_reset(struct snd_pcm_substream *substream)
static int snd_pcm_pre_prepare(struct snd_pcm_substream *substream,
snd_pcm_state_t state)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
+ snd_pcm_state_t cur_state = snd_pcm_get_state(substream);
int f_flags = (__force int)state;
- if (runtime->state == SNDRV_PCM_STATE_OPEN ||
- runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
+ if (cur_state == SNDRV_PCM_STATE_OPEN ||
+ cur_state == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
- if (snd_pcm_running(substream))
+ if (cur_state == SNDRV_PCM_STATE_RUNNING ||
+ (cur_state == SNDRV_PCM_STATE_DRAINING &&
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK))
return -EBUSY;
substream->f_flags = f_flags;
return 0;
@@ -2139,7 +2149,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
card = substream->pcm->card;
runtime = substream->runtime;
- if (runtime->state == SNDRV_PCM_STATE_OPEN)
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (file) {
@@ -2199,9 +2209,8 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
drain_no_period_wakeup = to_check->no_period_wakeup;
drain_rate = to_check->rate;
drain_bufsz = to_check->buffer_size;
- init_waitqueue_entry(&wait, current);
- set_current_state(TASK_INTERRUPTIBLE);
- add_wait_queue(&to_check->sleep, &wait);
+ init_wait_entry(&wait, 0);
+ prepare_to_wait(&to_check->sleep, &wait, TASK_INTERRUPTIBLE);
snd_pcm_stream_unlock_irq(substream);
if (drain_no_period_wakeup)
tout = MAX_SCHEDULE_TIMEOUT;
@@ -2219,7 +2228,7 @@ static int snd_pcm_drain(struct snd_pcm_substream *substream,
group = snd_pcm_stream_group_ref(substream);
snd_pcm_group_for_each_entry(s, substream) {
if (s->runtime == to_check) {
- remove_wait_queue(&to_check->sleep, &wait);
+ finish_wait(&to_check->sleep, &wait);
break;
}
}
@@ -3304,10 +3313,9 @@ static int snd_pcm_xferi_frames_ioctl(struct snd_pcm_substream *substream,
struct snd_xferi __user *_xferi)
{
struct snd_xferi xferi;
- struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_sframes_t result;
- if (runtime->state == SNDRV_PCM_STATE_OPEN)
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (put_user(0, &_xferi->result))
return -EFAULT;
@@ -3330,7 +3338,7 @@ static int snd_pcm_xfern_frames_ioctl(struct snd_pcm_substream *substream,
void *bufs __free(kfree) = NULL;
snd_pcm_sframes_t result;
- if (runtime->state == SNDRV_PCM_STATE_OPEN)
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_OPEN)
return -EBADFD;
if (runtime->channels > 128)
return -EINVAL;
@@ -3393,7 +3401,7 @@ static int snd_pcm_common_ioctl(struct file *file,
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
- if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
res = snd_power_wait(substream->pcm->card);
@@ -3524,7 +3532,7 @@ int snd_pcm_kernel_ioctl(struct snd_pcm_substream *substream,
snd_pcm_uframes_t *frames = arg;
snd_pcm_sframes_t result;
- if (substream->runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
+ if (snd_pcm_get_state(substream) == SNDRV_PCM_STATE_DISCONNECTED)
return -EBADFD;
switch (cmd) {
@@ -3569,8 +3577,7 @@ static ssize_t snd_pcm_read(struct file *file, char __user *buf, size_t count,
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
- if (runtime->state == SNDRV_PCM_STATE_OPEN ||
- runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
+ if (snd_pcm_state_open_or_disconnected(substream))
return -EBADFD;
if (!frame_aligned(runtime, count))
return -EINVAL;
@@ -3594,8 +3601,7 @@ static ssize_t snd_pcm_write(struct file *file, const char __user *buf,
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
- if (runtime->state == SNDRV_PCM_STATE_OPEN ||
- runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
+ if (snd_pcm_state_open_or_disconnected(substream))
return -EBADFD;
if (!frame_aligned(runtime, count))
return -EINVAL;
@@ -3621,8 +3627,7 @@ static ssize_t snd_pcm_readv(struct kiocb *iocb, struct iov_iter *to)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
- if (runtime->state == SNDRV_PCM_STATE_OPEN ||
- runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
+ if (snd_pcm_state_open_or_disconnected(substream))
return -EBADFD;
if (!user_backed_iter(to))
return -EINVAL;
@@ -3661,8 +3666,7 @@ static ssize_t snd_pcm_writev(struct kiocb *iocb, struct iov_iter *from)
if (PCM_RUNTIME_CHECK(substream))
return -ENXIO;
runtime = substream->runtime;
- if (runtime->state == SNDRV_PCM_STATE_OPEN ||
- runtime->state == SNDRV_PCM_STATE_DISCONNECTED)
+ if (snd_pcm_state_open_or_disconnected(substream))
return -EBADFD;
if (!user_backed_iter(from))
return -EINVAL;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 3b1034a44938..4dfd9d53e6d3 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -28,8 +28,8 @@ MODULE_DESCRIPTION("Midlevel RawMidi code for ALSA.");
MODULE_LICENSE("GPL");
#ifdef CONFIG_SND_OSSEMUL
-static int midi_map[SNDRV_CARDS];
-static int amidi_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
+static int midi_map[SNDRV_CARDS] __ro_after_init;
+static int amidi_map[SNDRV_CARDS] __ro_after_init = {[0 ... (SNDRV_CARDS-1)] = 1};
module_param_array(midi_map, int, NULL, 0444);
MODULE_PARM_DESC(midi_map, "Raw MIDI device number assigned to 1st OSS device.");
module_param_array(amidi_map, int, NULL, 0444);
diff --git a/sound/core/seq/oss/seq_oss_event.c b/sound/core/seq/oss/seq_oss_event.c
index 76fb81077eef..122735862044 100644
--- a/sound/core/seq/oss/seq_oss_event.c
+++ b/sound/core/seq/oss/seq_oss_event.c
@@ -39,8 +39,10 @@ static int set_echo_event(struct seq_oss_devinfo *dp, union evrec *rec, struct s
*/
int
-snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev)
+snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q,
+ struct snd_seq_event *ev, snd_use_lock_t **lockp)
{
+ *lockp = NULL;
switch (q->s.code) {
case SEQ_EXTENDED:
return extended_event(dp, q, ev);
@@ -69,7 +71,7 @@ snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd
if (snd_seq_oss_midi_open(dp, q->s.dev, SNDRV_SEQ_OSS_FILE_WRITE))
break;
if (snd_seq_oss_midi_filemode(dp, q->s.dev) & SNDRV_SEQ_OSS_FILE_WRITE)
- return snd_seq_oss_midi_putc(dp, q->s.dev, q->s.parm1, ev);
+ return snd_seq_oss_midi_putc(dp, q->s.dev, q->s.parm1, ev, lockp);
break;
case SEQ_ECHO:
diff --git a/sound/core/seq/oss/seq_oss_event.h b/sound/core/seq/oss/seq_oss_event.h
index b4f723949a17..54da1f810b3a 100644
--- a/sound/core/seq/oss/seq_oss_event.h
+++ b/sound/core/seq/oss/seq_oss_event.h
@@ -91,9 +91,11 @@ union evrec {
#define ev_is_long(ev) ((ev)->s.code >= 128)
#define ev_length(ev) ((ev)->s.code >= 128 ? LONG_EVENT_SIZE : SHORT_EVENT_SIZE)
-int snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q, struct snd_seq_event *ev);
+int snd_seq_oss_process_event(struct seq_oss_devinfo *dp, union evrec *q,
+ struct snd_seq_event *ev, snd_use_lock_t **lockp);
int snd_seq_oss_process_timer_event(struct seq_oss_timer *rec, union evrec *q);
int snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data, int atomic, int hop);
+DEFINE_FREE(seq_oss_use_lock, snd_use_lock_t *, if (_T) snd_use_lock_free(_T))
#endif /* __SEQ_OSS_EVENT_H */
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index d3e6a8a8d823..1aece46c8b06 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -27,8 +27,8 @@ static int maxqlen = SNDRV_SEQ_OSS_MAX_QLEN;
module_param(maxqlen, int, 0444);
MODULE_PARM_DESC(maxqlen, "maximum queue length");
-static int system_client = -1; /* ALSA sequencer client number */
-static int system_port = -1;
+static int system_client __ro_after_init = -1; /* ALSA sequencer client number */
+static int system_port __ro_after_init = -1;
static int num_clients;
static struct seq_oss_devinfo *client_table[SNDRV_SEQ_OSS_MAX_CLIENTS];
diff --git a/sound/core/seq/oss/seq_oss_ioctl.c b/sound/core/seq/oss/seq_oss_ioctl.c
index ccf682689ec9..f1a79776773f 100644
--- a/sound/core/seq/oss/seq_oss_ioctl.c
+++ b/sound/core/seq/oss/seq_oss_ioctl.c
@@ -51,9 +51,11 @@ static int snd_seq_oss_oob_user(struct seq_oss_devinfo *dp, void __user *arg)
memset(&tmpev, 0, sizeof(tmpev));
snd_seq_oss_fill_addr(dp, &tmpev, dp->addr.client, dp->addr.port);
tmpev.time.tick = 0;
- if (! snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev)) {
+
+ snd_use_lock_t *lock __free(seq_oss_use_lock) = NULL;
+
+ if (!snd_seq_oss_process_event(dp, (union evrec *)ev, &tmpev, &lock))
snd_seq_oss_dispatch(dp, &tmpev, 0, 0);
- }
return 0;
}
@@ -175,4 +177,3 @@ snd_seq_oss_ioctl(struct seq_oss_devinfo *dp, unsigned int cmd, unsigned long ca
}
return 0;
}
-
diff --git a/sound/core/seq/oss/seq_oss_midi.c b/sound/core/seq/oss/seq_oss_midi.c
index b50a49ca42ff..70f94df65144 100644
--- a/sound/core/seq/oss/seq_oss_midi.c
+++ b/sound/core/seq/oss/seq_oss_midi.c
@@ -593,7 +593,8 @@ send_midi_event(struct seq_oss_devinfo *dp, struct snd_seq_event *ev, struct seq
* non-zero : invalid - ignored
*/
int
-snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, struct snd_seq_event *ev)
+snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c,
+ struct snd_seq_event *ev, snd_use_lock_t **lockp)
{
struct seq_oss_midi *mdev __free(seq_oss_midi) =
get_mididev(dp, dev);
@@ -602,6 +603,9 @@ snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c, stru
return -ENODEV;
if (snd_midi_event_encode_byte(mdev->coder, c, ev)) {
snd_seq_oss_fill_addr(dp, ev, mdev->client, mdev->port);
+ /* the caller must release this later */
+ *lockp = &mdev->use_lock;
+ snd_use_lock_use(*lockp);
return 0;
}
return -EINVAL;
diff --git a/sound/core/seq/oss/seq_oss_midi.h b/sound/core/seq/oss/seq_oss_midi.h
index bcc1683773df..4819d4170bf6 100644
--- a/sound/core/seq/oss/seq_oss_midi.h
+++ b/sound/core/seq/oss/seq_oss_midi.h
@@ -26,7 +26,7 @@ void snd_seq_oss_midi_open_all(struct seq_oss_devinfo *dp, int file_mode);
int snd_seq_oss_midi_close(struct seq_oss_devinfo *dp, int dev);
void snd_seq_oss_midi_reset(struct seq_oss_devinfo *dp, int dev);
int snd_seq_oss_midi_putc(struct seq_oss_devinfo *dp, int dev, unsigned char c,
- struct snd_seq_event *ev);
+ struct snd_seq_event *ev, snd_use_lock_t **lockp);
int snd_seq_oss_midi_input(struct snd_seq_event *ev, int direct, void *private);
int snd_seq_oss_midi_filemode(struct seq_oss_devinfo *dp, int dev);
int snd_seq_oss_midi_make_info(struct seq_oss_devinfo *dp, int dev, struct midi_info *inf);
diff --git a/sound/core/seq/oss/seq_oss_readq.c b/sound/core/seq/oss/seq_oss_readq.c
index c880d4771169..d5dc76501ada 100644
--- a/sound/core/seq/oss/seq_oss_readq.c
+++ b/sound/core/seq/oss/seq_oss_readq.c
@@ -34,16 +34,10 @@ snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen)
{
struct seq_oss_readq *q;
- q = kzalloc_obj(*q);
+ q = kzalloc_flex(*q, q, maxlen);
if (!q)
return NULL;
- q->q = kzalloc_objs(union evrec, maxlen);
- if (!q->q) {
- kfree(q);
- return NULL;
- }
-
q->maxlen = maxlen;
q->qlen = 0;
q->head = q->tail = 0;
@@ -61,10 +55,7 @@ snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen)
void
snd_seq_oss_readq_delete(struct seq_oss_readq *q)
{
- if (q) {
- kfree(q->q);
- kfree(q);
- }
+ kfree(q);
}
/*
@@ -73,13 +64,17 @@ snd_seq_oss_readq_delete(struct seq_oss_readq *q)
void
snd_seq_oss_readq_clear(struct seq_oss_readq *q)
{
- if (q->qlen) {
- q->qlen = 0;
- q->head = q->tail = 0;
+ scoped_guard(spinlock_irqsave, &q->lock) {
+ if (q->qlen) {
+ q->qlen = 0;
+ q->head = 0;
+ q->tail = 0;
+ }
+ q->input_time = (unsigned long)-1;
}
+
/* if someone sleeping, wake'em up */
wake_up(&q->midi_sleep);
- q->input_time = (unsigned long)-1;
}
/*
@@ -136,11 +131,11 @@ int snd_seq_oss_readq_sysex(struct seq_oss_readq *q, int dev,
/*
* copy an event to input queue:
* return zero if enqueued
+ * caller must hold lock
*/
-int
-snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
+static int snd_seq_oss_readq_put_event_locked(struct seq_oss_readq *q,
+ union evrec *ev)
{
- guard(spinlock_irqsave)(&q->lock);
if (q->qlen >= q->maxlen - 1)
return -ENOMEM;
@@ -148,12 +143,27 @@ snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
q->tail = (q->tail + 1) % q->maxlen;
q->qlen++;
- /* wake up sleeper */
- wake_up(&q->midi_sleep);
-
return 0;
}
+/*
+ * copy an event to input queue:
+ * return zero if enqueued
+ */
+int
+snd_seq_oss_readq_put_event(struct seq_oss_readq *q, union evrec *ev)
+{
+ int rc;
+
+ scoped_guard(spinlock_irqsave, &q->lock) {
+ rc = snd_seq_oss_readq_put_event_locked(q, ev);
+ if (!rc)
+ wake_up(&q->midi_sleep);
+ }
+
+ return rc;
+}
+
/*
* pop queue
@@ -209,23 +219,31 @@ snd_seq_oss_readq_poll(struct seq_oss_readq *q, struct file *file, poll_table *w
int
snd_seq_oss_readq_put_timestamp(struct seq_oss_readq *q, unsigned long curt, int seq_mode)
{
- if (curt != q->input_time) {
- union evrec rec;
- memset(&rec, 0, sizeof(rec));
- switch (seq_mode) {
- case SNDRV_SEQ_OSS_MODE_SYNTH:
- rec.echo = (curt << 8) | SEQ_WAIT;
- snd_seq_oss_readq_put_event(q, &rec);
- break;
- case SNDRV_SEQ_OSS_MODE_MUSIC:
- rec.t.code = EV_TIMING;
- rec.t.cmd = TMR_WAIT_ABS;
- rec.t.time = curt;
- snd_seq_oss_readq_put_event(q, &rec);
- break;
+ int queued = 0;
+
+ scoped_guard(spinlock_irqsave, &q->lock) {
+ if (curt != q->input_time) {
+ union evrec rec;
+
+ memset(&rec, 0, sizeof(rec));
+ switch (seq_mode) {
+ case SNDRV_SEQ_OSS_MODE_SYNTH:
+ rec.echo = (curt << 8) | SEQ_WAIT;
+ queued = !snd_seq_oss_readq_put_event_locked(q, &rec);
+ break;
+ case SNDRV_SEQ_OSS_MODE_MUSIC:
+ rec.t.code = EV_TIMING;
+ rec.t.cmd = TMR_WAIT_ABS;
+ rec.t.time = curt;
+ queued = !snd_seq_oss_readq_put_event_locked(q, &rec);
+ break;
+ }
+ q->input_time = curt;
}
- q->input_time = curt;
}
+ if (queued)
+ wake_up(&q->midi_sleep);
+
return 0;
}
diff --git a/sound/core/seq/oss/seq_oss_readq.h b/sound/core/seq/oss/seq_oss_readq.h
index 38d0c4682b29..d8e1e7504d8f 100644
--- a/sound/core/seq/oss/seq_oss_readq.h
+++ b/sound/core/seq/oss/seq_oss_readq.h
@@ -10,13 +10,13 @@
#define __SEQ_OSS_READQ_H
#include "seq_oss_device.h"
+#include "seq_oss_event.h"
/*
* definition of read queue
*/
struct seq_oss_readq {
- union evrec *q;
int qlen;
int maxlen;
int head, tail;
@@ -24,6 +24,7 @@ struct seq_oss_readq {
unsigned long input_time;
wait_queue_head_t midi_sleep;
spinlock_t lock;
+ union evrec q[] __counted_by(maxlen);
};
struct seq_oss_readq *snd_seq_oss_readq_new(struct seq_oss_devinfo *dp, int maxlen);
diff --git a/sound/core/seq/oss/seq_oss_rw.c b/sound/core/seq/oss/seq_oss_rw.c
index 307ef98c44c7..6e417b10a102 100644
--- a/sound/core/seq/oss/seq_oss_rw.c
+++ b/sound/core/seq/oss/seq_oss_rw.c
@@ -57,7 +57,8 @@ snd_seq_oss_read(struct seq_oss_devinfo *dp, char __user *buf, int count)
break;
}
ev_len = ev_length(&rec);
- if (ev_len < count) {
+ if (count < ev_len) {
+ err = -EINVAL;
snd_seq_oss_readq_unlock(readq, flags);
break;
}
@@ -164,7 +165,9 @@ insert_queue(struct seq_oss_devinfo *dp, union evrec *rec, struct file *opt)
event.type = SNDRV_SEQ_EVENT_NOTEOFF;
snd_seq_oss_fill_addr(dp, &event, dp->addr.client, dp->addr.port);
- if (snd_seq_oss_process_event(dp, rec, &event))
+ snd_use_lock_t *lock __free(seq_oss_use_lock) = NULL;
+
+ if (snd_seq_oss_process_event(dp, rec, &event, &lock))
return 0; /* invalid event - no need to insert queue */
event.time.tick = snd_seq_oss_timer_cur_tick(dp->timer);
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 5719637575a9..28782e1776fa 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -441,6 +441,7 @@ static ssize_t snd_seq_read(struct file *file, char __user *buf, size_t count,
memcpy(&tmpev, &cell->event, aligned_size);
tmpev.data.ext.len &= ~SNDRV_SEQ_EXT_MASK;
+ tmpev.data.ext.ptr = NULL;
if (copy_to_user(buf, &tmpev, aligned_size)) {
err = -EFAULT;
break;
@@ -535,18 +536,44 @@ static int bounce_error_event(struct snd_seq_client *client,
! client->accept_input)
return 0; /* ignored */
+ if (event->type == SNDRV_SEQ_EVENT_BOUNCE ||
+ event->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
+ return err; /* avoid re-bouncing */
+
/* set up quoted error */
memset(&bounce_ev, 0, sizeof(bounce_ev));
- bounce_ev.type = SNDRV_SEQ_EVENT_KERNEL_ERROR;
- bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_FIXED;
+
+ if (client->type == USER_CLIENT) {
+ /*
+ * For user clients, send SNDRV_SEQ_EVENT_BOUNCE with the
+ * original event embedded as variable-length data. This
+ * avoids exposing data.quote.event (a kernel pointer) to
+ * userspace. The variable-length path in snd_seq_event_dup()
+ * copies the event data from data.ext.ptr into chained cells,
+ * and snd_seq_expand_var_event() copies only the data content
+ * -- never the pointer -- to userspace.
+ */
+ bounce_ev.type = SNDRV_SEQ_EVENT_BOUNCE;
+ bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_VARIABLE;
+ bounce_ev.data.ext.len = sizeof(struct snd_seq_event);
+ bounce_ev.data.ext.ptr = (char *)event;
+ } else {
+ /*
+ * For kernel clients, quote the event pointer directly.
+ * Kernel consumers can safely dereference the pointer.
+ */
+ bounce_ev.type = SNDRV_SEQ_EVENT_KERNEL_ERROR;
+ bounce_ev.flags = SNDRV_SEQ_EVENT_LENGTH_FIXED;
+ bounce_ev.data.quote.origin = event->dest;
+ bounce_ev.data.quote.event = event;
+ bounce_ev.data.quote.value = -err; /* use positive value */
+ }
+
bounce_ev.queue = SNDRV_SEQ_QUEUE_DIRECT;
bounce_ev.source.client = SNDRV_SEQ_CLIENT_SYSTEM;
bounce_ev.source.port = SNDRV_SEQ_PORT_SYSTEM_ANNOUNCE;
bounce_ev.dest.client = client->number;
bounce_ev.dest.port = event->source.port;
- bounce_ev.data.quote.origin = event->dest;
- bounce_ev.data.quote.event = event;
- bounce_ev.data.quote.value = -err; /* use positive value */
result = snd_seq_deliver_single_event(NULL, &bounce_ev, atomic, hop + 1);
if (result < 0) {
client->event_lost++;
@@ -1287,7 +1314,7 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
port_idx = -1;
if (port_idx >= SNDRV_SEQ_ADDRESS_UNKNOWN)
return -EINVAL;
- err = snd_seq_create_port(client, port_idx, &port);
+ err = snd_seq_create_port(client, &port);
if (err < 0)
return err;
@@ -1306,9 +1333,13 @@ static int snd_seq_ioctl_create_port(struct snd_seq_client *client, void *arg)
}
}
- info->addr = port->addr;
-
snd_seq_set_port_info(port, info);
+ err = snd_seq_insert_port(client, port_idx, port);
+ if (err < 0) {
+ kfree(port);
+ return err;
+ }
+ info->addr = port->addr;
if (info->capability & SNDRV_SEQ_PORT_CAP_UMP_ENDPOINT)
client->ump_endpoint_port = port->addr.port;
snd_seq_system_client_ev_port_start(port->addr.client, port->addr.port);
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index af45f328ae99..a6bd66ab40af 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -9,6 +9,7 @@
#include <linux/module.h>
#include <sound/core.h>
#include "seq_clientmgr.h"
+#include "seq_memory.h"
#include <sound/initval.h>
#include <sound/asoundef.h>
@@ -71,7 +72,7 @@ struct snd_seq_dummy_port {
int connect;
};
-static int my_client = -1;
+static int my_client __ro_after_init = -1;
/*
* event input callback - just redirect events to subscribers
@@ -81,19 +82,21 @@ dummy_input(struct snd_seq_event *ev, int direct, void *private_data,
int atomic, int hop)
{
struct snd_seq_dummy_port *p;
- struct snd_seq_event tmpev;
+ union __snd_seq_event tmpev;
+ size_t size;
p = private_data;
if (ev->source.client == SNDRV_SEQ_CLIENT_SYSTEM ||
ev->type == SNDRV_SEQ_EVENT_KERNEL_ERROR)
return 0; /* ignore system messages */
- tmpev = *ev;
+ size = snd_seq_event_packet_size(ev);
+ memcpy(&tmpev, ev, size);
if (p->duplex)
- tmpev.source.port = p->connect;
+ tmpev.legacy.source.port = p->connect;
else
- tmpev.source.port = p->port;
- tmpev.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
- return snd_seq_kernel_client_dispatch(p->client, &tmpev, atomic, hop);
+ tmpev.legacy.source.port = p->port;
+ tmpev.legacy.dest.client = SNDRV_SEQ_ADDRESS_SUBSCRIBERS;
+ return snd_seq_kernel_client_dispatch(p->client, &tmpev.legacy, atomic, hop);
}
/*
diff --git a/sound/core/seq/seq_fifo.c b/sound/core/seq/seq_fifo.c
index ebe1394c18a9..cffa8d430374 100644
--- a/sound/core/seq/seq_fifo.c
+++ b/sound/core/seq/seq_fifo.c
@@ -101,13 +101,17 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
struct snd_seq_event *event)
{
struct snd_seq_event_cell *cell;
+ struct snd_seq_pool *pool;
+ bool linked;
int err;
if (snd_BUG_ON(!f))
return -EINVAL;
guard(snd_seq_fifo)(f);
- err = snd_seq_event_dup(f->pool, event, &cell, 1, NULL, NULL); /* always non-blocking */
+retry:
+ pool = READ_ONCE(f->pool);
+ err = snd_seq_event_dup(pool, event, &cell, 1, NULL, NULL); /* always non-blocking */
if (err < 0) {
if ((err == -ENOMEM) || (err == -EAGAIN))
atomic_inc(&f->overflow);
@@ -115,14 +119,24 @@ int snd_seq_fifo_event_in(struct snd_seq_fifo *f,
}
/* append new cells to fifo */
+ linked = false;
scoped_guard(spinlock_irqsave, &f->lock) {
- if (f->tail != NULL)
- f->tail->next = cell;
- f->tail = cell;
- if (f->head == NULL)
- f->head = cell;
- cell->next = NULL;
- f->cells++;
+ if (cell->pool == f->pool) {
+ if (f->tail)
+ f->tail->next = cell;
+ f->tail = cell;
+ if (!f->head)
+ f->head = cell;
+ cell->next = NULL;
+ f->cells++;
+ linked = true;
+ }
+ }
+
+ if (!linked) {
+ /* Retry against the replacement pool after resize publishes it. */
+ snd_seq_cell_free(cell);
+ goto retry;
}
/* wakeup client */
@@ -194,13 +208,21 @@ int snd_seq_fifo_cell_out(struct snd_seq_fifo *f,
void snd_seq_fifo_cell_putback(struct snd_seq_fifo *f,
struct snd_seq_event_cell *cell)
{
+ bool linked = false;
+
if (cell) {
- guard(spinlock_irqsave)(&f->lock);
- cell->next = f->head;
- f->head = cell;
- if (!f->tail)
- f->tail = cell;
- f->cells++;
+ scoped_guard(spinlock_irqsave, &f->lock) {
+ if (cell->pool == f->pool) {
+ cell->next = f->head;
+ f->head = cell;
+ if (!f->tail)
+ f->tail = cell;
+ f->cells++;
+ linked = true;
+ }
+ }
+ if (!linked)
+ snd_seq_cell_free(cell);
}
}
@@ -237,7 +259,7 @@ int snd_seq_fifo_resize(struct snd_seq_fifo *f, int poolsize)
oldpool = f->pool;
oldhead = f->head;
/* exchange pools */
- f->pool = newpool;
+ WRITE_ONCE(f->pool, newpool);
f->head = NULL;
f->tail = NULL;
f->cells = 0;
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index aaf808316c30..209b08c2a940 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -211,7 +211,7 @@ int snd_seq_expand_var_event_at(const struct snd_seq_event *event, int count,
len -= offset;
if (len > count)
len = count;
- err = expand_var_event(event, offset, count, buf, true);
+ err = expand_var_event(event, offset, len, buf, true);
if (err < 0)
return err;
return len;
@@ -364,7 +364,7 @@ int snd_seq_event_dup(struct snd_seq_pool *pool, struct snd_seq_event *event,
size = snd_seq_event_packet_size(event);
memcpy(&cell->ump, event, size);
#if IS_ENABLED(CONFIG_SND_SEQ_UMP)
- if (size < sizeof(cell->event))
+ if (size < sizeof(cell->ump))
cell->ump.raw.extra = 0;
#endif
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index ca3f5fc30992..2eb12199c92f 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -24,6 +24,7 @@ Possible options for midisynth module:
#include <sound/seq_device.h>
#include <sound/seq_midi_event.h>
#include <sound/initval.h>
+#include "seq_lock.h"
MODULE_AUTHOR("Frank van de Pol <fvdpol@coil.demon.nl>, Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Advanced Linux Sound Architecture sequencer MIDI synth.");
@@ -42,6 +43,8 @@ struct seq_midisynth {
int device;
int subdevice;
struct snd_rawmidi_file input_rfile;
+ spinlock_t output_lock; /* protects output_rfile publication */
+ snd_use_lock_t output_use_lock; /* in-flight event_input users */
struct snd_rawmidi_file output_rfile;
int seq_client;
int seq_port;
@@ -125,31 +128,42 @@ static int event_process_midi(struct snd_seq_event *ev, int direct,
struct seq_midisynth *msynth = private_data;
unsigned char msg[10]; /* buffer for constructing midi messages */
struct snd_rawmidi_substream *substream;
+ int err = 0;
int len;
if (snd_BUG_ON(!msynth))
return -EINVAL;
- substream = msynth->output_rfile.output;
- if (substream == NULL)
- return -ENODEV;
+
+ scoped_guard(spinlock_irqsave, &msynth->output_lock) {
+ substream = msynth->output_rfile.output;
+ if (!substream)
+ return -ENODEV;
+ snd_use_lock_use(&msynth->output_use_lock);
+ }
+
if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { /* special case, to save space */
if ((ev->flags & SNDRV_SEQ_EVENT_LENGTH_MASK) != SNDRV_SEQ_EVENT_LENGTH_VARIABLE) {
/* invalid event */
pr_debug("ALSA: seq_midi: invalid sysex event flags = 0x%x\n", ev->flags);
- return 0;
+ goto out;
}
snd_seq_dump_var_event(ev, __dump_midi, substream);
snd_midi_event_reset_decode(msynth->parser);
} else {
- if (msynth->parser == NULL)
- return -EIO;
+ if (!msynth->parser) {
+ err = -EIO;
+ goto out;
+ }
len = snd_midi_event_decode(msynth->parser, msg, sizeof(msg), ev);
if (len < 0)
- return 0;
+ goto out;
if (dump_midi(substream, msg, len) < 0)
snd_midi_event_reset_decode(msynth->parser);
}
- return 0;
+
+out:
+ snd_use_lock_free(&msynth->output_use_lock);
+ return err;
}
@@ -163,6 +177,8 @@ static int snd_seq_midisynth_new(struct seq_midisynth *msynth,
msynth->card = card;
msynth->device = device;
msynth->subdevice = subdevice;
+ spin_lock_init(&msynth->output_lock);
+ snd_use_lock_init(&msynth->output_use_lock);
return 0;
}
@@ -215,12 +231,13 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
{
int err;
struct seq_midisynth *msynth = private_data;
+ struct snd_rawmidi_file rfile = {};
struct snd_rawmidi_params params;
/* open midi port */
err = snd_rawmidi_kernel_open(msynth->rmidi, msynth->subdevice,
SNDRV_RAWMIDI_LFLG_OUTPUT,
- &msynth->output_rfile);
+ &rfile);
if (err < 0) {
pr_debug("ALSA: seq_midi: midi output open failed!!!\n");
return err;
@@ -229,12 +246,14 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
params.avail_min = 1;
params.buffer_size = output_buffer_size;
params.no_active_sensing = 1;
- err = snd_rawmidi_output_params(msynth->output_rfile.output, &params);
+ err = snd_rawmidi_output_params(rfile.output, &params);
if (err < 0) {
- snd_rawmidi_kernel_release(&msynth->output_rfile);
+ snd_rawmidi_kernel_release(&rfile);
return err;
}
snd_midi_event_reset_decode(msynth->parser);
+ scoped_guard(spinlock_irqsave, &msynth->output_lock)
+ msynth->output_rfile = rfile;
return 0;
}
@@ -242,11 +261,19 @@ static int midisynth_use(void *private_data, struct snd_seq_port_subscribe *info
static int midisynth_unuse(void *private_data, struct snd_seq_port_subscribe *info)
{
struct seq_midisynth *msynth = private_data;
+ struct snd_rawmidi_file rfile = {};
- if (snd_BUG_ON(!msynth->output_rfile.output))
+ scoped_guard(spinlock_irqsave, &msynth->output_lock) {
+ rfile = msynth->output_rfile;
+ msynth->output_rfile = (struct snd_rawmidi_file){};
+ }
+
+ if (snd_BUG_ON(!rfile.output))
return -EINVAL;
- snd_rawmidi_drain_output(msynth->output_rfile.output);
- return snd_rawmidi_kernel_release(&msynth->output_rfile);
+
+ snd_use_lock_sync(&msynth->output_use_lock);
+ snd_rawmidi_drain_output(rfile.output);
+ return snd_rawmidi_kernel_release(&rfile);
}
/* delete given midi synth port */
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index fd067c85c524..a90ebc7b3811 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -81,9 +81,6 @@ snd_midi_process_event(const struct snd_midi_op *ops,
pr_debug("ALSA: seq_midi_emul: ev or chanbase NULL (snd_midi_process_event)\n");
return;
}
- if (chanset->channels == NULL)
- return;
-
if (snd_seq_ev_is_channel_type(ev)) {
dest_channel = ev->data.note.channel;
if (dest_channel >= chanset->max_channels) {
@@ -643,23 +640,6 @@ static void snd_midi_channel_init(struct snd_midi_channel *p, int n)
}
/*
- * Allocate and initialise a set of midi channel control blocks.
- */
-static struct snd_midi_channel *snd_midi_channel_init_set(int n)
-{
- struct snd_midi_channel *chan;
- int i;
-
- chan = kmalloc_objs(struct snd_midi_channel, n);
- if (chan) {
- for (i = 0; i < n; i++)
- snd_midi_channel_init(chan+i, i);
- }
-
- return chan;
-}
-
-/*
* reset all midi channels
*/
static void
@@ -687,13 +667,18 @@ reset_all_channels(struct snd_midi_channel_set *chset)
struct snd_midi_channel_set *snd_midi_channel_alloc_set(int n)
{
struct snd_midi_channel_set *chset;
+ int i;
+
+ chset = kmalloc_flex(*chset, channels, n);
+ if (!chset)
+ return NULL;
+
+ chset->max_channels = n;
+ chset->private_data = NULL;
+
+ for (i = 0; i < n; i++)
+ snd_midi_channel_init(&chset->channels[i], i);
- chset = kmalloc_obj(*chset);
- if (chset) {
- chset->channels = snd_midi_channel_init_set(n);
- chset->private_data = NULL;
- chset->max_channels = n;
- }
return chset;
}
EXPORT_SYMBOL(snd_midi_channel_alloc_set);
@@ -717,7 +702,6 @@ void snd_midi_channel_free_set(struct snd_midi_channel_set *chset)
{
if (chset == NULL)
return;
- kfree(chset->channels);
kfree(chset);
}
EXPORT_SYMBOL(snd_midi_channel_free_set);
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index da8d358958f1..6612e92d801f 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -108,14 +108,13 @@ static void port_subs_info_init(struct snd_seq_port_subs_info *grp)
}
-/* create a port, port number or a negative error code is returned
+/* create a port, 0 on success or a negative error code is returned
* the caller needs to unref the port via snd_seq_port_unlock() appropriately
*/
-int snd_seq_create_port(struct snd_seq_client *client, int port,
+int snd_seq_create_port(struct snd_seq_client *client,
struct snd_seq_client_port **port_ret)
{
- struct snd_seq_client_port *new_port, *p;
- int num;
+ struct snd_seq_client_port *new_port;
*port_ret = NULL;
@@ -141,25 +140,38 @@ int snd_seq_create_port(struct snd_seq_client *client, int port,
port_subs_info_init(&new_port->c_dest);
snd_use_lock_use(&new_port->use_lock);
+ *port_ret = new_port;
+
+ return 0;
+}
+
+/* insert the port; return the port address or a negative error code */
+int snd_seq_insert_port(struct snd_seq_client *client, int port,
+ struct snd_seq_client_port *new_port)
+{
+ struct snd_seq_client_port *p;
+ int num;
+
num = max(port, 0);
guard(mutex)(&client->ports_mutex);
guard(write_lock_irq)(&client->ports_lock);
+ struct list_head *insert_before = &client->ports_list_head;
list_for_each_entry(p, &client->ports_list_head, list) {
- if (p->addr.port == port) {
- kfree(new_port);
+ if (p->addr.port == port)
return -EBUSY;
- }
- if (p->addr.port > num)
+ if (p->addr.port > num) {
+ insert_before = &p->list;
break;
+ }
if (port < 0) /* auto-probe mode */
num = p->addr.port + 1;
}
/* insert the new port */
- list_add_tail(&new_port->list, &p->list);
+ list_add_tail(&new_port->list, insert_before);
client->num_ports++;
new_port->addr.port = num; /* store the port number in the port */
- sprintf(new_port->name, "port-%d", num);
- *port_ret = new_port;
+ if (!new_port->name[0])
+ sprintf(new_port->name, "port-%d", num);
return num;
}
diff --git a/sound/core/seq/seq_ports.h b/sound/core/seq/seq_ports.h
index 40ed6cf7cb90..b689c0f4867c 100644
--- a/sound/core/seq/seq_ports.h
+++ b/sound/core/seq/seq_ports.h
@@ -98,10 +98,14 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl
DEFINE_FREE(snd_seq_port, struct snd_seq_client_port *, if (!IS_ERR_OR_NULL(_T)) snd_seq_port_unlock(_T))
-/* create a port, port number or a negative error code is returned */
-int snd_seq_create_port(struct snd_seq_client *client, int port_index,
+/* create a port, 0 on success or a negative error code is returned */
+int snd_seq_create_port(struct snd_seq_client *client,
struct snd_seq_client_port **port_ret);
+/* insert the port; return the port address or a negative error code */
+int snd_seq_insert_port(struct snd_seq_client *client, int port,
+ struct snd_seq_client_port *new_port);
+
/* delete a port */
int snd_seq_delete_port(struct snd_seq_client *client, int port);
diff --git a/sound/core/seq/seq_prioq.c b/sound/core/seq/seq_prioq.c
index 25c0ed8f9f0f..d5bad1c585f6 100644
--- a/sound/core/seq/seq_prioq.c
+++ b/sound/core/seq/seq_prioq.c
@@ -132,7 +132,7 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f,
struct snd_seq_event_cell * cell)
{
struct snd_seq_event_cell *cur, *prev;
- int count;
+ int remaining;
int prior;
if (snd_BUG_ON(!f || !cell))
@@ -162,10 +162,16 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f,
prev = NULL; /* previous cell */
cur = f->head; /* cursor */
- count = 10000; /* FIXME: enough big, isn't it? */
+ remaining = f->cells;
while (cur != NULL) {
/* compare timestamps */
int rel = compare_timestamp_rel(&cell->event, &cur->event);
+
+ if (remaining-- <= 0) {
+ pr_err("ALSA: seq: inconsistent prioq cell count\n");
+ return -EINVAL;
+ }
+
if (rel < 0)
/* new cell has earlier schedule time, */
break;
@@ -176,10 +182,6 @@ int snd_seq_prioq_cell_in(struct snd_seq_prioq * f,
/* move cursor to next cell */
prev = cur;
cur = cur->next;
- if (! --count) {
- pr_err("ALSA: seq: cannot find a pointer.. infinite loop?\n");
- return -EINVAL;
- }
}
/* insert it before cursor */
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 9bef2f792498..4cd7211ccf48 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -333,10 +333,10 @@ int snd_seq_timer_stop(struct snd_seq_timer *tmr)
static int initialize_timer(struct snd_seq_timer *tmr)
{
- struct snd_timer *t;
unsigned long freq;
- t = tmr->timeri->timer;
+ struct snd_timer *t __free(snd_timeri_timer) =
+ snd_timeri_timer_get(tmr->timeri);
if (!t)
return -EINVAL;
@@ -456,7 +456,12 @@ void snd_seq_info_timer_read(struct snd_info_entry *entry,
ti = tmr->timeri;
if (!ti)
break;
- snd_iprintf(buffer, "Timer for queue %i : %s\n", q->queue, ti->timer->name);
+
+ struct snd_timer *t __free(snd_timeri_timer) =
+ snd_timeri_timer_get(ti);
+ snd_iprintf(buffer, "Timer for queue %i : %s\n",
+ q->queue,
+ t ? t->name : "DEAD");
resolution = snd_timer_resolution(ti) * tmr->ticks;
snd_iprintf(buffer, " Period time : %lu.%09lu\n", resolution / 1000000000, resolution % 1000000000);
snd_iprintf(buffer, " Skew : %u / %u\n", tmr->skew, tmr->skew_base);
diff --git a/sound/core/seq/seq_ump_client.c b/sound/core/seq/seq_ump_client.c
index 9079ccfdc866..ccd93599b493 100644
--- a/sound/core/seq/seq_ump_client.c
+++ b/sound/core/seq/seq_ump_client.c
@@ -37,6 +37,7 @@ struct seq_ump_client {
struct snd_ump_endpoint *ump; /* assigned endpoint */
int seq_client; /* sequencer client id */
int opened[2]; /* current opens for each direction */
+ rwlock_t output_lock; /* protects out_rfile output access */
struct snd_rawmidi_file out_rfile; /* rawmidi for output */
struct seq_ump_input_buffer input; /* input parser context */
void *ump_info[SNDRV_UMP_MAX_BLOCKS + 1]; /* shadow of seq client ump_info */
@@ -88,6 +89,7 @@ static int seq_ump_process_event(struct snd_seq_event *ev, int direct,
unsigned char type;
int len;
+ guard(read_lock_irqsave)(&client->output_lock);
substream = client->out_rfile.output;
if (!substream)
return -ENODEV;
@@ -106,6 +108,7 @@ static int seq_ump_process_event(struct snd_seq_event *ev, int direct,
static int seq_ump_client_open(struct seq_ump_client *client, int dir)
{
struct snd_ump_endpoint *ump = client->ump;
+ struct snd_rawmidi_file rfile = {};
int err;
guard(mutex)(&ump->open_mutex);
@@ -113,9 +116,11 @@ static int seq_ump_client_open(struct seq_ump_client *client, int dir)
err = snd_rawmidi_kernel_open(&ump->core, 0,
SNDRV_RAWMIDI_LFLG_OUTPUT |
SNDRV_RAWMIDI_LFLG_APPEND,
- &client->out_rfile);
+ &rfile);
if (err < 0)
return err;
+ scoped_guard(write_lock_irqsave, &client->output_lock)
+ client->out_rfile = rfile;
}
client->opened[dir]++;
return 0;
@@ -125,11 +130,19 @@ static int seq_ump_client_open(struct seq_ump_client *client, int dir)
static int seq_ump_client_close(struct seq_ump_client *client, int dir)
{
struct snd_ump_endpoint *ump = client->ump;
+ struct snd_rawmidi_file rfile = {};
guard(mutex)(&ump->open_mutex);
- if (!--client->opened[dir])
- if (dir == STR_OUT)
- snd_rawmidi_kernel_release(&client->out_rfile);
+ if (!--client->opened[dir]) {
+ if (dir == STR_OUT) {
+ scoped_guard(write_lock_irqsave, &client->output_lock) {
+ rfile = client->out_rfile;
+ client->out_rfile = (struct snd_rawmidi_file){};
+ }
+ if (rfile.rmidi)
+ snd_rawmidi_kernel_release(&rfile);
+ }
+ }
return 0;
}
@@ -467,6 +480,7 @@ static int snd_seq_ump_probe(struct snd_seq_device *dev)
INIT_WORK(&client->group_notify_work, handle_group_notify);
client->ump = ump;
+ rwlock_init(&client->output_lock);
client->seq_client =
snd_seq_create_kernel_client(card, ump->core.device,
diff --git a/sound/core/seq_device.c b/sound/core/seq_device.c
index 1b062d6b17ea..8be1f3ab5b63 100644
--- a/sound/core/seq_device.c
+++ b/sound/core/seq_device.c
@@ -234,7 +234,10 @@ int snd_seq_device_new(struct snd_card *card, int device, const char *id,
if (snd_BUG_ON(!id))
return -EINVAL;
- dev = kzalloc(sizeof(*dev) + argsize, GFP_KERNEL);
+ if (argsize < 0)
+ return -EINVAL;
+
+ dev = kzalloc_flex(*dev, args, argsize);
if (!dev)
return -ENOMEM;
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 820901d503af..51c6ac4df9f4 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -132,8 +132,8 @@ static LIST_HEAD(snd_timer_slave_list);
/* list of open master instances that can accept slave links */
static LIST_HEAD(snd_timer_master_list);
-/* lock for slave active lists */
-static DEFINE_SPINLOCK(slave_active_lock);
+/* rwlock for timer instance (for trigger actions) */
+static DEFINE_RWLOCK(timeri_lock);
#define MAX_SLAVE_INSTANCES 1000
static int num_slaves;
@@ -229,6 +229,44 @@ static void snd_timer_request(struct snd_timer_id *tid)
#endif
+/*
+ * refcount management of timer object
+ */
+static void snd_timer_kref_release(struct kref *kref);
+
+static inline void snd_timer_ref_get(struct snd_timer *timer)
+{
+ kref_get(&timer->kref);
+}
+
+static inline void snd_timer_ref_put(struct snd_timer *timer)
+{
+ kref_put(&timer->kref, snd_timer_kref_release);
+}
+
+/*
+ * Return the assigned timer for the instance, NULL if not present;
+ * the caller is responsible to call snd_timeri_timer_put(), or use auto-cleanup
+ */
+struct snd_timer *snd_timeri_timer_get(struct snd_timer_instance *timeri)
+{
+ struct snd_timer *t;
+
+ guard(read_lock_irqsave)(&timeri_lock);
+ t = timeri->timer;
+ if (!t)
+ return NULL;
+ snd_timer_ref_get(t);
+ return t;
+}
+EXPORT_SYMBOL_GPL(snd_timeri_timer_get);
+
+void snd_timeri_timer_put(struct snd_timer *timer)
+{
+ snd_timer_ref_put(timer);
+}
+EXPORT_SYMBOL_GPL(snd_timeri_timer_put);
+
/* move the slave if it belongs to the master; return 1 if match */
static int check_matching_master_slave(struct snd_timer_instance *master,
struct snd_timer_instance *slave)
@@ -240,7 +278,8 @@ static int check_matching_master_slave(struct snd_timer_instance *master,
return -EBUSY;
list_move_tail(&slave->open_list, &master->slave_list_head);
master->timer->num_instances++;
- guard(spinlock_irq)(&slave_active_lock);
+ snd_timer_ref_get(master->timer);
+ guard(write_lock_irq)(&timeri_lock);
guard(spinlock)(&master->timer->lock);
slave->master = master;
slave->timer = master->timer;
@@ -386,6 +425,7 @@ int snd_timer_open(struct snd_timer_instance *timeri,
if (snd_timer_has_slave_key(timeri))
list_add_tail(&timeri->master_list, &snd_timer_master_list);
timer->num_instances++;
+ snd_timer_ref_get(timer);
err = snd_timer_check_master(timeri);
list_added:
if (err < 0)
@@ -406,12 +446,13 @@ static void remove_slave_links(struct snd_timer_instance *timeri,
{
struct snd_timer_instance *slave, *tmp;
- guard(spinlock_irq)(&slave_active_lock);
+ guard(write_lock_irq)(&timeri_lock);
guard(spinlock)(&timer->lock);
timeri->timer = NULL;
list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head, open_list) {
list_move_tail(&slave->open_list, &snd_timer_slave_list);
timer->num_instances--;
+ snd_timer_ref_put(timer);
slave->master = NULL;
slave->timer = NULL;
list_del_init(&slave->ack_list);
@@ -430,6 +471,8 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
if (timer) {
guard(spinlock_irq)(&timer->lock);
+ if (timeri->flags & SNDRV_TIMER_IFLG_DEAD)
+ return; /* already closed */
timeri->flags |= SNDRV_TIMER_IFLG_DEAD;
}
@@ -459,17 +502,16 @@ static void snd_timer_close_locked(struct snd_timer_instance *timeri,
remove_slave_links(timeri, timer);
/* slave doesn't need to release timer resources below */
- if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
- timer = NULL;
- }
+ if (!(timeri->flags & SNDRV_TIMER_IFLG_SLAVE)) {
+ if (list_empty(&timer->open_list_head) && timer->hw.close)
+ timer->hw.close(timer);
+ /* release a card refcount for safe disconnection */
+ if (timer->card)
+ *card_devp_to_put = &timer->card->card_dev;
+ module_put(timer->module);
+ }
- if (timer) {
- if (list_empty(&timer->open_list_head) && timer->hw.close)
- timer->hw.close(timer);
- /* release a card refcount for safe disconnection */
- if (timer->card)
- *card_devp_to_put = &timer->card->card_dev;
- module_put(timer->module);
+ snd_timer_ref_put(timer);
}
}
@@ -501,12 +543,13 @@ static unsigned long snd_timer_hw_resolution(struct snd_timer *timer)
unsigned long snd_timer_resolution(struct snd_timer_instance *timeri)
{
- struct snd_timer * timer;
unsigned long ret = 0;
if (timeri == NULL)
return 0;
- timer = timeri->timer;
+
+ struct snd_timer *timer __free(snd_timeri_timer)
+ = snd_timeri_timer_get(timeri);
if (timer) {
guard(spinlock_irqsave)(&timer->lock);
ret = snd_timer_hw_resolution(timer);
@@ -558,7 +601,7 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,
if (!timer)
return -EINVAL;
- guard(spinlock_irqsave)(&timer->lock);
+ guard(spinlock)(&timer->lock);
if (timeri->flags & SNDRV_TIMER_IFLG_DEAD)
return -EINVAL;
if (timer->card && timer->card->shutdown)
@@ -606,7 +649,6 @@ static int snd_timer_start1(struct snd_timer_instance *timeri,
static int snd_timer_start_slave(struct snd_timer_instance *timeri,
bool start)
{
- guard(spinlock_irqsave)(&slave_active_lock);
if (timeri->flags & SNDRV_TIMER_IFLG_DEAD)
return -EINVAL;
if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING)
@@ -630,7 +672,7 @@ static int snd_timer_stop1(struct snd_timer_instance *timeri, bool stop)
timer = timeri->timer;
if (!timer)
return -EINVAL;
- guard(spinlock_irqsave)(&timer->lock);
+ guard(spinlock)(&timer->lock);
list_del_init(&timeri->ack_list);
list_del_init(&timeri->active_list);
if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
@@ -669,7 +711,6 @@ static int snd_timer_stop_slave(struct snd_timer_instance *timeri, bool stop)
{
bool running;
- guard(spinlock_irqsave)(&slave_active_lock);
running = timeri->flags & SNDRV_TIMER_IFLG_RUNNING;
timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
if (timeri->timer) {
@@ -690,6 +731,7 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
{
if (timeri == NULL || ticks < 1)
return -EINVAL;
+ guard(read_lock_irqsave)(&timeri_lock);
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
return snd_timer_start_slave(timeri, true);
else
@@ -704,6 +746,7 @@ EXPORT_SYMBOL(snd_timer_start);
*/
int snd_timer_stop(struct snd_timer_instance *timeri)
{
+ guard(read_lock_irqsave)(&timeri_lock);
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
return snd_timer_stop_slave(timeri, true);
else
@@ -720,6 +763,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
if (!(timeri->flags & SNDRV_TIMER_IFLG_PAUSED))
return -EINVAL;
+ guard(read_lock_irqsave)(&timeri_lock);
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
return snd_timer_start_slave(timeri, false);
else
@@ -732,6 +776,7 @@ EXPORT_SYMBOL(snd_timer_continue);
*/
int snd_timer_pause(struct snd_timer_instance * timeri)
{
+ guard(read_lock_irqsave)(&timeri_lock);
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE)
return snd_timer_stop_slave(timeri, false);
else
@@ -959,6 +1004,7 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
spin_lock_init(&timer->lock);
INIT_WORK(&timer->task_work, snd_timer_work);
timer->max_instances = 1000; /* default limit per timer */
+ kref_init(&timer->kref);
if (card != NULL) {
timer->module = card->module;
err = snd_device_new(card, SNDRV_DEV_TIMER, timer, &ops);
@@ -973,27 +1019,37 @@ int snd_timer_new(struct snd_card *card, char *id, struct snd_timer_id *tid,
}
EXPORT_SYMBOL(snd_timer_new);
+static void snd_timer_kref_release(struct kref *kref)
+{
+ struct snd_timer *timer = container_of(kref, struct snd_timer, kref);
+
+ if (timer->private_free)
+ timer->private_free(timer);
+ kfree(timer);
+}
+
static int snd_timer_free(struct snd_timer *timer)
{
+ struct snd_timer_instance *ti, *n;
+
if (!timer)
return 0;
- guard(mutex)(&register_mutex);
- if (! list_empty(&timer->open_list_head)) {
- struct list_head *p, *n;
- struct snd_timer_instance *ti;
- pr_warn("ALSA: timer %p is busy?\n", timer);
- list_for_each_safe(p, n, &timer->open_list_head) {
- list_del_init(p);
- ti = list_entry(p, struct snd_timer_instance, open_list);
- ti->timer = NULL;
+ scoped_guard(mutex, &register_mutex) {
+ if (!list_empty(&timer->open_list_head)) {
+ list_for_each_entry_safe(ti, n, &timer->open_list_head, open_list) {
+ struct device *card_dev_to_put = NULL;
+
+ snd_timer_close_locked(ti, &card_dev_to_put);
+ put_device(card_dev_to_put);
+ }
}
+ list_del(&timer->device_list);
}
- list_del(&timer->device_list);
- if (timer->private_free)
- timer->private_free(timer);
- kfree(timer);
+ disable_work_sync(&timer->task_work);
+
+ snd_timer_ref_put(timer);
return 0;
}
@@ -1007,6 +1063,7 @@ static int snd_timer_dev_register(struct snd_device *dev)
{
struct snd_timer *timer = dev->device_data;
struct snd_timer *timer1;
+ struct list_head *insert_before = &snd_timer_list;
if (snd_BUG_ON(!timer || !timer->hw.start || !timer->hw.stop))
return -ENXIO;
@@ -1016,28 +1073,36 @@ static int snd_timer_dev_register(struct snd_device *dev)
guard(mutex)(&register_mutex);
list_for_each_entry(timer1, &snd_timer_list, device_list) {
- if (timer1->tmr_class > timer->tmr_class)
+ if (timer1->tmr_class > timer->tmr_class) {
+ insert_before = &timer1->device_list;
break;
+ }
if (timer1->tmr_class < timer->tmr_class)
continue;
if (timer1->card && timer->card) {
- if (timer1->card->number > timer->card->number)
+ if (timer1->card->number > timer->card->number) {
+ insert_before = &timer1->device_list;
break;
+ }
if (timer1->card->number < timer->card->number)
continue;
}
- if (timer1->tmr_device > timer->tmr_device)
+ if (timer1->tmr_device > timer->tmr_device) {
+ insert_before = &timer1->device_list;
break;
+ }
if (timer1->tmr_device < timer->tmr_device)
continue;
- if (timer1->tmr_subdevice > timer->tmr_subdevice)
+ if (timer1->tmr_subdevice > timer->tmr_subdevice) {
+ insert_before = &timer1->device_list;
break;
+ }
if (timer1->tmr_subdevice < timer->tmr_subdevice)
continue;
/* conflicts.. */
return -EBUSY;
}
- list_add_tail(&timer->device_list, &timer1->device_list);
+ list_add_tail(&timer->device_list, insert_before);
return 0;
}
@@ -1767,12 +1832,13 @@ static int snd_timer_user_info(struct file *file,
struct snd_timer_info __user *_info)
{
struct snd_timer_user *tu;
- struct snd_timer *t;
tu = file->private_data;
if (!tu->timeri)
return -EBADFD;
- t = tu->timeri->timer;
+
+ struct snd_timer *t __free(snd_timeri_timer) =
+ snd_timeri_timer_get(tu->timeri);
if (!t)
return -EBADFD;
@@ -1797,13 +1863,14 @@ static int snd_timer_user_params(struct file *file,
{
struct snd_timer_user *tu;
struct snd_timer_params params;
- struct snd_timer *t;
int err;
tu = file->private_data;
if (!tu->timeri)
return -EBADFD;
- t = tu->timeri->timer;
+
+ struct snd_timer *t __free(snd_timeri_timer) =
+ snd_timeri_timer_get(tu->timeri);
if (!t)
return -EBADFD;
if (copy_from_user(&params, _params, sizeof(params)))
diff --git a/sound/core/timer_compat.c b/sound/core/timer_compat.c
index 4ae9eaeb5afb..25ee81c1668b 100644
--- a/sound/core/timer_compat.c
+++ b/sound/core/timer_compat.c
@@ -49,12 +49,13 @@ static int snd_timer_user_info_compat(struct file *file,
{
struct snd_timer_user *tu;
struct snd_timer_info32 info;
- struct snd_timer *t;
tu = file->private_data;
if (!tu->timeri)
return -EBADFD;
- t = tu->timeri->timer;
+
+ struct snd_timer *t __free(snd_timeri_timer) =
+ snd_timeri_timer_get(tu->timeri);
if (!t)
return -EBADFD;
memset(&info, 0, sizeof(info));
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index a37a1695f51c..06bfe09eae1a 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -100,8 +100,7 @@ struct loopback_cable {
spinlock_t lock;
struct loopback_pcm *streams[2];
/* in-flight peer stops running outside cable->lock */
- atomic_t stop_count;
- wait_queue_head_t stop_wait;
+ struct snd_refcount stop_count;
struct snd_pcm_hardware hw;
/* flags */
unsigned int valid;
@@ -371,7 +370,7 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
return -EIO;
else if (cruntime->state == SNDRV_PCM_STATE_RUNNING) {
/* close must not free the peer runtime below */
- atomic_inc(&cable->stop_count);
+ snd_refcount_get(&cable->stop_count);
stop_capture = true;
}
}
@@ -404,8 +403,7 @@ static int loopback_check_format(struct loopback_cable *cable, int stream)
if (stop_capture) {
snd_pcm_stop(dpcm_capt->substream, SNDRV_PCM_STATE_DRAINING);
- if (atomic_dec_and_test(&cable->stop_count))
- wake_up(&cable->stop_wait);
+ snd_refcount_put(&cable->stop_count);
}
return 0;
@@ -728,7 +726,6 @@ static void loopback_jiffies_timer_function(struct timer_list *t)
if (dpcm->period_update_pending) {
dpcm->period_update_pending = 0;
period_elapsed = true;
- break;
}
}
}
@@ -1071,7 +1068,7 @@ static void free_cable(struct snd_pcm_substream *substream)
}
/* Pair with the stop_count increment in loopback_check_format(). */
- wait_event(cable->stop_wait, !atomic_read(&cable->stop_count));
+ snd_refcount_sync(&cable->stop_count);
if (other_alive)
return;
@@ -1275,8 +1272,7 @@ static int loopback_open(struct snd_pcm_substream *substream)
goto unlock;
}
spin_lock_init(&cable->lock);
- atomic_set(&cable->stop_count, 0);
- init_waitqueue_head(&cable->stop_wait);
+ snd_refcount_init(&cable->stop_count);
cable->hw = loopback_pcm_hardware;
if (loopback->timer_source)
cable->ops = &loopback_snd_timer_ops;
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index d3f9424088d4..c217c427bf1e 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -46,7 +46,7 @@ module_param_array(uart_enter, bool, NULL, 0444);
MODULE_PARM_DESC(uart_enter, "Issue UART_ENTER command at open.");
static struct platform_device *platform_devices[SNDRV_CARDS];
-static int pnp_registered;
+static int pnp_registered __ro_after_init;
static unsigned int snd_mpu401_devices;
static int snd_mpu401_create(struct device *devptr, int dev,
@@ -123,7 +123,7 @@ static struct platform_driver snd_mpu401_driver = {
static const struct pnp_device_id snd_mpu401_pnpids[] = {
{ .id = "PNPb006" },
- { .id = "" }
+ { }
};
MODULE_DEVICE_TABLE(pnp, snd_mpu401_pnpids);
diff --git a/sound/drivers/pcmtest.c b/sound/drivers/pcmtest.c
index 7f93557b51ec..5d5281e4deb7 100644
--- a/sound/drivers/pcmtest.c
+++ b/sound/drivers/pcmtest.c
@@ -113,7 +113,7 @@ struct pcmtst_buf_iter {
struct timer_list timer_instance;
};
-static struct snd_pcm_hardware snd_pcmtst_hw = {
+static struct snd_pcm_hardware snd_pcmtst_hw __ro_after_init = {
.info = (SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
SNDRV_PCM_INFO_NONINTERLEAVED |
@@ -137,7 +137,7 @@ struct pattern_buf {
u32 len;
};
-static int buf_allocated;
+static int buf_allocated __ro_after_init;
static struct pattern_buf patt_bufs[MAX_CHANNELS_NUM];
static inline void inc_buf_pos(struct pcmtst_buf_iter *v_iter, size_t by, size_t bytes)
diff --git a/sound/firewire/dice/dice.c b/sound/firewire/dice/dice.c
index f7a50bae4b55..58f14aadc73d 100644
--- a/sound/firewire/dice/dice.c
+++ b/sound/firewire/dice/dice.c
@@ -148,7 +148,7 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *ent
snd_dice_detect_formats_t detect_formats;
int err;
- if (!entry->driver_data && entry->vendor_id != OUI_SSL) {
+ if (!entry->driver_data_ptr && entry->vendor_id != OUI_SSL) {
err = check_dice_category(unit);
if (err < 0)
return -ENODEV;
@@ -164,10 +164,10 @@ static int dice_probe(struct fw_unit *unit, const struct ieee1394_device_id *ent
dev_set_drvdata(&unit->device, dice);
dice->card = card;
- if (!entry->driver_data)
+ if (!entry->driver_data_ptr)
detect_formats = snd_dice_stream_detect_current_formats;
else
- detect_formats = (snd_dice_detect_formats_t)entry->driver_data;
+ detect_formats = entry->driver_data_ptr;
// Below models are compliant to IEC 61883-1/6 and have no quirk at high sampling transfer
// frequency.
@@ -255,7 +255,7 @@ static void dice_bus_reset(struct fw_unit *unit)
.model_id = (model), \
.specifier_id = (vendor), \
.version = DICE_INTERFACE, \
- .driver_data = (kernel_ulong_t)(data), \
+ .driver_data_ptr = (data), \
}
static const struct ieee1394_device_id dice_id_table[] = {
@@ -267,7 +267,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_MAUDIO,
.model_id = 0x000010,
- .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
+ .driver_data_ptr = snd_dice_detect_extension_formats,
},
/* M-Audio Profire 610 has a different value in version field. */
{
@@ -275,7 +275,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_MAUDIO,
.model_id = 0x000011,
- .driver_data = (kernel_ulong_t)snd_dice_detect_extension_formats,
+ .driver_data_ptr = snd_dice_detect_extension_formats,
},
/* TC Electronic Konnekt 24D. */
{
@@ -283,7 +283,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000020,
- .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
+ .driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Konnekt 8. */
{
@@ -291,7 +291,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000021,
- .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
+ .driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Studio Konnekt 48. */
{
@@ -299,7 +299,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000022,
- .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
+ .driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Konnekt Live. */
{
@@ -307,7 +307,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000023,
- .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
+ .driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Desktop Konnekt 6. */
{
@@ -315,7 +315,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000024,
- .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
+ .driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Impact Twin. */
{
@@ -323,7 +323,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000027,
- .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
+ .driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* TC Electronic Digital Konnekt x32. */
{
@@ -331,7 +331,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_TCELECTRONIC,
.model_id = 0x000030,
- .driver_data = (kernel_ulong_t)snd_dice_detect_tcelectronic_formats,
+ .driver_data_ptr = snd_dice_detect_tcelectronic_formats,
},
/* Alesis iO14/iO26. */
{
@@ -339,7 +339,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_ALESIS,
.model_id = MODEL_ALESIS_IO_BOTH,
- .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_formats,
+ .driver_data_ptr = snd_dice_detect_alesis_formats,
},
// Alesis MasterControl.
{
@@ -347,7 +347,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_ALESIS,
.model_id = 0x000002,
- .driver_data = (kernel_ulong_t)snd_dice_detect_alesis_mastercontrol_formats,
+ .driver_data_ptr = snd_dice_detect_alesis_mastercontrol_formats,
},
/* Mytek Stereo 192 DSD-DAC. */
{
@@ -355,7 +355,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
IEEE1394_MATCH_MODEL_ID,
.vendor_id = OUI_MYTEK,
.model_id = 0x000002,
- .driver_data = (kernel_ulong_t)snd_dice_detect_mytek_formats,
+ .driver_data_ptr = snd_dice_detect_mytek_formats,
},
// Solid State Logic, Duende Classic and Mini.
// NOTE: each field of GUID in config ROM is not compliant to standard
@@ -469,7 +469,7 @@ static const struct ieee1394_device_id dice_id_table[] = {
.model_id = OUI_TEAC,
.specifier_id = OUI_TEAC,
.version = 0x800006,
- .driver_data = (kernel_ulong_t)snd_dice_detect_teac_formats,
+ .driver_data_ptr = snd_dice_detect_teac_formats,
},
{ }
};
diff --git a/sound/firewire/fireface/ff.c b/sound/firewire/fireface/ff.c
index 5d2c4fbf4434..13472822d2be 100644
--- a/sound/firewire/fireface/ff.c
+++ b/sound/firewire/fireface/ff.c
@@ -70,7 +70,7 @@ static int snd_ff_probe(struct fw_unit *unit, const struct ieee1394_device_id *e
init_waitqueue_head(&ff->hwdep_wait);
ff->unit_version = entry->version;
- ff->spec = (const struct snd_ff_spec *)entry->driver_data;
+ ff->spec = entry->driver_data_ptr;
err = snd_ff_transaction_register(ff);
if (err < 0)
@@ -186,7 +186,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_FF800,
.model_id = 0x101800,
- .driver_data = (kernel_ulong_t)&spec_ff800,
+ .driver_data_ptr = &spec_ff800,
},
/* Fireface 400 */
{
@@ -198,7 +198,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_FF400,
.model_id = 0x101800,
- .driver_data = (kernel_ulong_t)&spec_ff400,
+ .driver_data_ptr = &spec_ff400,
},
// Fireface UFX.
{
@@ -210,7 +210,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_UFX,
.model_id = 0x101800,
- .driver_data = (kernel_ulong_t)&spec_ufx_802,
+ .driver_data_ptr = &spec_ufx_802,
},
// Fireface UCX.
{
@@ -222,7 +222,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_UCX,
.model_id = 0x101800,
- .driver_data = (kernel_ulong_t)&spec_ucx,
+ .driver_data_ptr = &spec_ucx,
},
// Fireface 802.
{
@@ -234,7 +234,7 @@ static const struct ieee1394_device_id snd_ff_id_table[] = {
.specifier_id = OUI_RME,
.version = SND_FF_UNIT_VERSION_802,
.model_id = 0x101800,
- .driver_data = (kernel_ulong_t)&spec_ufx_802,
+ .driver_data_ptr = &spec_ufx_802,
},
{}
};
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c
index 2b7f071d593b..f16e2e223494 100644
--- a/sound/firewire/isight.c
+++ b/sound/firewire/isight.c
@@ -11,7 +11,6 @@
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/string.h>
#include <sound/control.h>
@@ -179,7 +178,8 @@ static void isight_packet(struct fw_iso_context *context, u32 cycle,
if (likely(length >= 16 &&
payload->signature == cpu_to_be32(0x73676874/*"sght"*/))) {
count = be32_to_cpu(payload->sample_count);
- if (likely(count <= (length - 16) / 4)) {
+ if (likely(count <= (length - 16) / 4 &&
+ count <= MAX_FRAMES_PER_PACKET)) {
total = be32_to_cpu(payload->sample_total);
if (unlikely(total != isight->total_samples)) {
if (!isight->first_packet)
diff --git a/sound/firewire/motu/motu-register-dsp-message-parser.c b/sound/firewire/motu/motu-register-dsp-message-parser.c
index a8053e3ef065..4ec23e6880d9 100644
--- a/sound/firewire/motu/motu-register-dsp-message-parser.c
+++ b/sound/firewire/motu/motu-register-dsp-message-parser.c
@@ -386,6 +386,8 @@ unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *m
{
struct msg_parser *parser = motu->message_parser;
+ guard(spinlock_irqsave)(&parser->lock);
+
if (parser->pull_pos > parser->push_pos)
return EVENT_QUEUE_SIZE - parser->pull_pos + parser->push_pos;
else
@@ -395,13 +397,14 @@ unsigned int snd_motu_register_dsp_message_parser_count_event(struct snd_motu *m
bool snd_motu_register_dsp_message_parser_copy_event(struct snd_motu *motu, u32 *event)
{
struct msg_parser *parser = motu->message_parser;
- unsigned int pos = parser->pull_pos;
-
- if (pos == parser->push_pos)
- return false;
+ unsigned int pos;
guard(spinlock_irqsave)(&parser->lock);
+ if (parser->pull_pos == parser->push_pos)
+ return false;
+
+ pos = parser->pull_pos;
*event = parser->event_queue[pos];
++pos;
diff --git a/sound/firewire/motu/motu.c b/sound/firewire/motu/motu.c
index fd2a9dddbfa6..1fec6c8cdf6c 100644
--- a/sound/firewire/motu/motu.c
+++ b/sound/firewire/motu/motu.c
@@ -78,7 +78,7 @@ static int motu_probe(struct fw_unit *unit, const struct ieee1394_device_id *ent
dev_set_drvdata(&unit->device, motu);
motu->card = card;
- motu->spec = (const struct snd_motu_spec *)entry->driver_data;
+ motu->spec = entry->driver_data_ptr;
mutex_init(&motu->mutex);
spin_lock_init(&motu->lock);
init_waitqueue_head(&motu->hwdep_wait);
@@ -148,7 +148,7 @@ static void motu_bus_update(struct fw_unit *unit)
snd_motu_transaction_reregister(motu);
}
-#define SND_MOTU_DEV_ENTRY(model, data) \
+#define SND_MOTU_DEV_ENTRY(model, data_ptr) \
{ \
.match_flags = IEEE1394_MATCH_VENDOR_ID | \
IEEE1394_MATCH_SPECIFIER_ID | \
@@ -156,7 +156,7 @@ static void motu_bus_update(struct fw_unit *unit)
.vendor_id = OUI_MOTU, \
.specifier_id = OUI_MOTU, \
.version = model, \
- .driver_data = (kernel_ulong_t)data, \
+ .driver_data_ptr = data_ptr, \
}
static const struct ieee1394_device_id motu_id_table[] = {
diff --git a/sound/firewire/oxfw/oxfw.c b/sound/firewire/oxfw/oxfw.c
index 5039bd79b18e..38a3c3b150df 100644
--- a/sound/firewire/oxfw/oxfw.c
+++ b/sound/firewire/oxfw/oxfw.c
@@ -95,7 +95,7 @@ static int name_card(struct snd_oxfw *oxfw, const struct ieee1394_device_id *ent
/* to apply card definitions */
if (entry->vendor_id == VENDOR_GRIFFIN || entry->vendor_id == VENDOR_LACIE) {
- info = (const struct compat_info *)entry->driver_data;
+ info = entry->driver_data_ptr;
d = info->driver_name;
v = info->vendor_name;
m = info->model_name;
@@ -321,7 +321,7 @@ static const struct compat_info lacie_speakers = {
.model_id = model, \
.specifier_id = SPECIFIER_1394TA, \
.version = VERSION_AVC, \
- .driver_data = (kernel_ulong_t)data, \
+ .driver_data_ptr = data, \
}
static const struct ieee1394_device_id oxfw_id_table[] = {
diff --git a/sound/hda/codecs/Kconfig b/sound/hda/codecs/Kconfig
index addbc9424336..dcf340e5a0c1 100644
--- a/sound/hda/codecs/Kconfig
+++ b/sound/hda/codecs/Kconfig
@@ -69,6 +69,7 @@ comment "Set to Y if you want auto-loading the codec driver"
config SND_HDA_CODEC_CA0132
tristate "Build Creative CA0132 codec support"
+ select SND_HDA_GENERIC
help
Say Y or M here to include Creative CA0132 codec support in
snd-hda-intel driver.
diff --git a/sound/hda/codecs/ca0132.c b/sound/hda/codecs/ca0132.c
index ad533b04ab29..3fe11983d6ca 100644
--- a/sound/hda/codecs/ca0132.c
+++ b/sound/hda/codecs/ca0132.c
@@ -24,6 +24,7 @@
#include "hda_local.h"
#include "hda_auto_parser.h"
#include "hda_jack.h"
+#include "generic.h"
#include "ca0132_regs.h"
@@ -1060,6 +1061,8 @@ enum dsp_download_state {
*/
struct ca0132_spec {
+ struct hda_gen_spec gen;
+
const struct snd_kcontrol_new *mixers[5];
unsigned int num_mixers;
const struct hda_verb *base_init_verbs;
@@ -1174,6 +1177,7 @@ enum {
QUIRK_R3D,
QUIRK_AE5,
QUIRK_AE7,
+ QUIRK_GENERIC,
QUIRK_NONE = HDA_FIXUP_ID_NOT_SET,
};
@@ -1292,6 +1296,20 @@ static const struct hda_pintbl ae7_pincfgs[] = {
{}
};
+static const struct hda_pintbl ca0132_generic_pincfgs[] = {
+ { 0x0b, 0x41014111 },
+ { 0x0c, 0x414520f0 }, /* SPDIF out */
+ { 0x0d, 0x01014010 }, /* lineout */
+ { 0x0e, 0x41c501f0 },
+ { 0x0f, 0x411111f0 }, /* disabled */
+ { 0x10, 0x411111f0 }, /* disabled */
+ { 0x11, 0x41012014 },
+ { 0x12, 0x37a790f0 }, /* mic */
+ { 0x13, 0x77a701f0 },
+ { 0x18, 0x500000f0 },
+ {}
+};
+
static const struct hda_quirk ca0132_quirks[] = {
SND_PCI_QUIRK(0x1028, 0x057b, "Alienware M17x R4", QUIRK_ALIENWARE_M17XR4),
SND_PCI_QUIRK(0x1028, 0x0685, "Alienware 15 2015", QUIRK_ALIENWARE),
@@ -1304,6 +1322,7 @@ static const struct hda_quirk ca0132_quirks[] = {
SND_PCI_QUIRK(0x1458, 0xA016, "Recon3Di", QUIRK_R3DI),
SND_PCI_QUIRK(0x1458, 0xA026, "Gigabyte G1.Sniper Z97", QUIRK_R3DI),
SND_PCI_QUIRK(0x1458, 0xA036, "Gigabyte GA-Z170X-Gaming 7", QUIRK_R3DI),
+ SND_PCI_QUIRK(0x1458, 0xA046, "Gigabyte GA-Z170X-Gaming G1", QUIRK_GENERIC),
SND_PCI_QUIRK(0x3842, 0x1038, "EVGA X99 Classified", QUIRK_R3DI),
SND_PCI_QUIRK(0x3842, 0x104b, "EVGA X299 Dark", QUIRK_R3DI),
SND_PCI_QUIRK(0x3842, 0x1055, "EVGA Z390 DARK", QUIRK_R3DI),
@@ -1325,6 +1344,7 @@ static const struct hda_model_fixup ca0132_quirk_models[] = {
{ .id = QUIRK_R3D, .name = "r3d" },
{ .id = QUIRK_AE5, .name = "ae5" },
{ .id = QUIRK_AE7, .name = "ae7" },
+ { .id = QUIRK_GENERIC, .name = "generic" },
{}
};
@@ -5498,6 +5518,30 @@ static int zxr_headphone_gain_set(struct hda_codec *codec, long val)
return 0;
}
+/*
+ * Manual output selection (HP/Speaker Playback Switch or alt Output Select)
+ * is meaningful only when HP/Speaker auto-detect is disabled, since the
+ * select_out path always prefers jack presence when auto-detect is on. When
+ * the user explicitly chooses an output, turn auto-detect off so the manual
+ * choice actually takes effect, and notify userspace so the auto-detect
+ * control reflects the new state.
+ */
+static void ca0132_disable_hp_auto_detect(struct hda_codec *codec)
+{
+ struct ca0132_spec *spec = codec->spec;
+ struct snd_kcontrol *kctl;
+
+ if (!spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID])
+ return;
+
+ spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID] = 0;
+ kctl = snd_hda_find_mixer_ctl(codec,
+ "HP/Speaker Auto Detect Playback Switch");
+ if (kctl)
+ snd_ctl_notify(codec->card, SNDRV_CTL_EVENT_MASK_VALUE,
+ &kctl->id);
+}
+
static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -5510,14 +5554,11 @@ static int ca0132_vnode_switch_set(struct snd_kcontrol *kcontrol,
int auto_jack;
if (nid == VNID_HP_SEL) {
- auto_jack =
- spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
- if (!auto_jack) {
- if (ca0132_use_alt_functions(spec))
- ca0132_alt_select_out(codec);
- else
- ca0132_select_out(codec);
- }
+ ca0132_disable_hp_auto_detect(codec);
+ if (ca0132_use_alt_functions(spec))
+ ca0132_alt_select_out(codec);
+ else
+ ca0132_select_out(codec);
return 1;
}
@@ -5978,7 +6019,6 @@ static int ca0132_alt_output_select_put(struct snd_kcontrol *kcontrol,
struct ca0132_spec *spec = codec->spec;
int sel = ucontrol->value.enumerated.item[0];
unsigned int items = NUM_OF_OUTPUTS;
- unsigned int auto_jack;
if (sel >= items)
return 0;
@@ -5988,10 +6028,8 @@ static int ca0132_alt_output_select_put(struct snd_kcontrol *kcontrol,
spec->out_enum_val = sel;
- auto_jack = spec->vnode_lswitch[VNID_HP_ASEL - VNODE_START_NID];
-
- if (!auto_jack)
- ca0132_alt_select_out(codec);
+ ca0132_disable_hp_auto_detect(codec);
+ ca0132_alt_select_out(codec);
return 1;
}
@@ -9879,14 +9917,57 @@ static void sbz_detect_quirk(struct hda_codec *codec)
}
}
+static void ca0132_generic_init_hook(struct hda_codec *codec)
+{
+ struct ca0132_spec *spec = codec->spec;
+
+ snd_hda_sequence_write(codec, spec->spec_init_verbs);
+}
+
+static int ca0132_generic_probe(struct hda_codec *codec)
+{
+ struct ca0132_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->gen.autocfg;
+ int err;
+
+ snd_hda_gen_spec_init(&spec->gen);
+
+ snd_hda_apply_pincfgs(codec, ca0132_generic_pincfgs);
+
+ ca0132_init_chip(codec);
+
+ err = ca0132_prepare_verbs(codec);
+ if (err < 0)
+ return err;
+
+ err = snd_hda_parse_pin_def_config(codec, cfg, NULL);
+ if (err < 0)
+ return err;
+ err = snd_hda_gen_parse_auto_config(codec, cfg);
+ if (err < 0)
+ return err;
+
+ spec->gen.init_hook = ca0132_generic_init_hook;
+ spec->gen.automute_speaker = 0;
+ spec->gen.automute_lo = 0;
+
+ snd_hda_sequence_write(codec, spec->spec_init_verbs);
+ return 0;
+}
+
static void ca0132_codec_remove(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
- if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
+ switch (ca0132_quirk(spec)) {
+ case QUIRK_GENERIC:
+ snd_hda_gen_remove(codec);
+ return;
+ case QUIRK_ZXR_DBPRO:
return dbpro_free(codec);
- else
+ default:
return ca0132_free(codec);
+ }
}
static int ca0132_codec_probe(struct hda_codec *codec,
@@ -9903,14 +9984,21 @@ static int ca0132_codec_probe(struct hda_codec *codec,
codec->spec = spec;
spec->codec = codec;
- /* Detect codec quirk */
- snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL);
- if (ca0132_quirk(spec) == QUIRK_SBZ)
- sbz_detect_quirk(codec);
-
+ /* These must be set before any path is taken */
codec->pcm_format_first = 1;
codec->no_sticky_stream = 1;
+ /* Detect codec quirk */
+ snd_hda_pick_fixup(codec, ca0132_quirk_models, ca0132_quirks, NULL);
+ switch (ca0132_quirk(spec)) {
+ case QUIRK_SBZ:
+ sbz_detect_quirk(codec);
+ break;
+ case QUIRK_GENERIC:
+ return ca0132_generic_probe(codec);
+ default:
+ break;
+ }
spec->dsp_state = DSP_DOWNLOAD_INIT;
spec->num_mixers = 1;
@@ -10011,36 +10099,51 @@ static int ca0132_codec_build_controls(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
- if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
+ switch (ca0132_quirk(spec)) {
+ case QUIRK_GENERIC:
+ return snd_hda_gen_build_controls(codec);
+ case QUIRK_ZXR_DBPRO:
return dbpro_build_controls(codec);
- else
+ default:
return ca0132_build_controls(codec);
+ }
}
static int ca0132_codec_build_pcms(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
- if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
+ switch (ca0132_quirk(spec)) {
+ case QUIRK_GENERIC:
+ return snd_hda_gen_build_pcms(codec);
+ case QUIRK_ZXR_DBPRO:
return dbpro_build_pcms(codec);
- else
+ default:
return ca0132_build_pcms(codec);
+ }
}
static int ca0132_codec_init(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
- if (ca0132_quirk(spec) == QUIRK_ZXR_DBPRO)
+ switch (ca0132_quirk(spec)) {
+ case QUIRK_GENERIC:
+ return snd_hda_gen_init(codec);
+ case QUIRK_ZXR_DBPRO:
return dbpro_init(codec);
- else
+ default:
return ca0132_init(codec);
+ }
}
static int ca0132_codec_suspend(struct hda_codec *codec)
{
struct ca0132_spec *spec = codec->spec;
+ if (ca0132_quirk(spec) == QUIRK_GENERIC)
+ return 0;
+
cancel_delayed_work_sync(&spec->unsol_hp_work);
return 0;
}
diff --git a/sound/hda/codecs/cirrus/cs420x.c b/sound/hda/codecs/cirrus/cs420x.c
index 42559edbba05..85c2ecf46d38 100644
--- a/sound/hda/codecs/cirrus/cs420x.c
+++ b/sound/hda/codecs/cirrus/cs420x.c
@@ -582,6 +582,7 @@ static const struct hda_quirk cs4208_mac_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
SND_PCI_QUIRK(0x106b, 0x7800, "MacPro 6,1", CS4208_MACMINI),
SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11),
+ SND_PCI_QUIRK(0x106b, 0x7f00, "iMac 16,1", CS4208_MBP11),
{} /* terminator */
};
diff --git a/sound/hda/codecs/conexant.c b/sound/hda/codecs/conexant.c
index e3b6aaabe3a9..3d92262763f6 100644
--- a/sound/hda/codecs/conexant.c
+++ b/sound/hda/codecs/conexant.c
@@ -291,6 +291,7 @@ enum {
CXT_FIXUP_HEADSET_MIC,
CXT_FIXUP_HP_MIC_NO_PRESENCE,
CXT_PINCFG_SWS_JS201D,
+ CXT_PINCFG_LENOVO_IDEAPAD_SLIM5_16AKP10,
CXT_PINCFG_TOP_SPEAKER,
CXT_FIXUP_HP_A_U,
CXT_FIXUP_ACER_SWIFT_HP,
@@ -826,6 +827,12 @@ static const struct hda_pintbl cxt_pincfg_lemote[] = {
{}
};
+/* Lenovo IdeaPad Slim 5 16AKP10 with SN6140 */
+static const struct hda_pintbl cxt_pincfg_lenovo_ideapad_slim5_16akp10[] = {
+ { 0x1a, 0x95a60130 }, /* Internal mic, fixed/always-connected */
+ {}
+};
+
/* SuoWoSi/South-holding JS201D with sn6140 */
static const struct hda_pintbl cxt_pincfg_sws_js201d[] = {
{ 0x16, 0x03211040 }, /* hp out */
@@ -1006,6 +1013,10 @@ static const struct hda_fixup cxt_fixups[] = {
.type = HDA_FIXUP_PINS,
.v.pins = cxt_pincfg_sws_js201d,
},
+ [CXT_PINCFG_LENOVO_IDEAPAD_SLIM5_16AKP10] = {
+ .type = HDA_FIXUP_PINS,
+ .v.pins = cxt_pincfg_lenovo_ideapad_slim5_16akp10,
+ },
[CXT_PINCFG_TOP_SPEAKER] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
@@ -1114,6 +1125,7 @@ static const struct hda_quirk cxt5066_fixups[] = {
SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT_PINCFG_LENOVO_TP410),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo IdeaPad Z560", CXT_FIXUP_MUTE_LED_EAPD),
+ SND_PCI_QUIRK(0x17aa, 0x38b6, "Lenovo IdeaPad Slim 5 16AKP10", CXT_PINCFG_LENOVO_IDEAPAD_SLIM5_16AKP10),
SND_PCI_QUIRK(0x17aa, 0x3905, "Lenovo G50-30", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x390b, "Lenovo G50-80", CXT_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x17aa, 0x3975, "Lenovo U300s", CXT_FIXUP_STEREO_DMIC),
diff --git a/sound/hda/codecs/hdmi/hdmi.c b/sound/hda/codecs/hdmi/hdmi.c
index f20d1715da62..1f4d646724ed 100644
--- a/sound/hda/codecs/hdmi/hdmi.c
+++ b/sound/hda/codecs/hdmi/hdmi.c
@@ -1549,6 +1549,7 @@ static const struct snd_pci_quirk force_connect_list[] = {
SND_PCI_QUIRK(0x103c, 0x83e2, "HP EliteDesk 800 G4", 1),
SND_PCI_QUIRK(0x103c, 0x83ef, "HP MP9 G4 Retail System AMS", 1),
SND_PCI_QUIRK(0x103c, 0x845a, "HP EliteDesk 800 G4 DM 65W", 1),
+ SND_PCI_QUIRK(0x103c, 0x8595, "HP EliteDesk 800 G5 Mini", 1),
SND_PCI_QUIRK(0x103c, 0x83f3, "HP ProDesk 400", 1),
SND_PCI_QUIRK(0x103c, 0x870f, "HP", 1),
SND_PCI_QUIRK(0x103c, 0x871a, "HP", 1),
@@ -2285,6 +2286,7 @@ EXPORT_SYMBOL_NS_GPL(snd_hda_hdmi_acomp_init, "SND_HDA_CODEC_HDMI");
enum {
MODEL_GENERIC,
MODEL_GF,
+ MODEL_LOONGSON,
};
static int generichdmi_probe(struct hda_codec *codec,
@@ -2302,6 +2304,11 @@ static int generichdmi_probe(struct hda_codec *codec,
if (id->driver_data == MODEL_GF)
codec->no_sticky_stream = 1;
+ if (id->driver_data == MODEL_LOONGSON) {
+ if (codec->bus && codec->bus->pci->revision == 0x2)
+ codec->eld_jack_detect = 1; /* Jack-detection by ELD */
+ }
+
return 0;
}
@@ -2319,7 +2326,7 @@ static const struct hda_codec_ops generichdmi_codec_ops = {
/*
*/
static const struct hda_device_id snd_hda_id_generichdmi[] = {
- HDA_CODEC_ID_MODEL(0x00147a47, "Loongson HDMI", MODEL_GENERIC),
+ HDA_CODEC_ID_MODEL(0x00147a47, "Loongson HDMI", MODEL_LOONGSON),
HDA_CODEC_ID_MODEL(0x10951390, "SiI1390 HDMI", MODEL_GENERIC),
HDA_CODEC_ID_MODEL(0x10951392, "SiI1392 HDMI", MODEL_GENERIC),
HDA_CODEC_ID_MODEL(0x11069f84, "VX11 HDMI/DP", MODEL_GENERIC),
diff --git a/sound/hda/codecs/realtek/alc269.c b/sound/hda/codecs/realtek/alc269.c
index 11d0ea8ed859..f7700713dc62 100644
--- a/sound/hda/codecs/realtek/alc269.c
+++ b/sound/hda/codecs/realtek/alc269.c
@@ -3338,6 +3338,18 @@ static void alc256_fixup_acer_sfg16_micmute_led(struct hda_codec *codec,
alc_fixup_hp_gpio_led(codec, action, 0, 0x04);
}
+static void alc287_fixup_acer_micmute_led(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+
+ alc_fixup_hp_gpio_led(codec, action, 0, 0x10);
+ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+ spec->micmute_led_polarity = 1;
+ spec->gpio_mask |= 0x10;
+ spec->gpio_dir |= 0x10;
+ }
+}
/* for alc295_fixup_hp_top_speakers */
#include "../helpers/hp_x360.c"
@@ -4076,6 +4088,7 @@ enum {
ALC287_FIXUP_YOGA7_14ITL_SPEAKERS,
ALC298_FIXUP_LENOVO_C940_DUET7,
ALC287_FIXUP_LENOVO_YOGA_BOOK_9I,
+ ALC287_FIXUP_LENOVO_YOGA_PRO7,
ALC287_FIXUP_13S_GEN2_SPEAKERS,
ALC256_FIXUP_SET_COEF_DEFAULTS,
ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
@@ -4095,6 +4108,7 @@ enum {
ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED,
ALC285_FIXUP_HP_SPEAKERS_MICMUTE_LED,
ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE,
+ ALC295_FIXUP_FRAMEWORK_LAPTOP_LIMIT_INT_MIC_BOOST,
ALC287_FIXUP_LEGION_16ITHG6,
ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK,
ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN,
@@ -4154,6 +4168,7 @@ enum {
ALC236_FIXUP_HP_DMIC,
ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO,
ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX,
+ ALC287_FIXUP_ACER_MICMUTE_LED,
};
/* A special fixup for Lenovo C940 and Yoga Duet 7;
@@ -5457,7 +5472,7 @@ static const struct hda_fixup alc269_fixups[] = {
[ALC299_FIXUP_PREDATOR_SPK] = {
.type = HDA_FIXUP_PINS,
.v.pins = (const struct hda_pintbl[]) {
- { 0x21, 0x90170150 }, /* use as headset mic, without its own jack detect */
+ { 0x21, 0x90170150 }, /* use as internal speaker */
{ }
}
},
@@ -6100,6 +6115,13 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC285_FIXUP_THINKPAD_HEADSET_JACK,
},
+ [ALC287_FIXUP_LENOVO_YOGA_PRO7] = {
+ .type = HDA_FIXUP_FUNC,
+ /* Reuse the DAC routing selected for ThinkPad X1 Gen7 */
+ .v.func = alc285_fixup_thinkpad_x1_gen7,
+ .chained = true,
+ .chain_id = ALC269_FIXUP_LENOVO_XPAD_ACPI,
+ },
[ALC623_FIXUP_LENOVO_THINKSTATION_P340] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_no_shutup,
@@ -6346,6 +6368,12 @@ static const struct hda_fixup alc269_fixups[] = {
.chained = true,
.chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
},
+ [ALC295_FIXUP_FRAMEWORK_LAPTOP_LIMIT_INT_MIC_BOOST] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc269_fixup_limit_int_mic_boost,
+ .chained = true,
+ .chain_id = ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE,
+ },
[ALC287_FIXUP_LEGION_16ITHG6] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc287_fixup_legion_16ithg6_speakers,
@@ -6720,7 +6748,13 @@ static const struct hda_fixup alc269_fixups[] = {
.v.func = cs35l41_fixup_i2c_two,
.chained = true,
.chain_id = ALC245_FIXUP_HP_X360_MUTE_LEDS
- }
+ },
+ [ALC287_FIXUP_ACER_MICMUTE_LED] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc287_fixup_acer_micmute_led,
+ .chained = true,
+ .chain_id = ALC2XX_FIXUP_HEADSET_MIC,
+ },
};
static const struct hda_quirk alc269_fixup_tbl[] = {
@@ -6770,14 +6804,16 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x1466, "Acer Aspire A515-56", ALC255_FIXUP_ACER_HEADPHONE_AND_MIC),
SND_PCI_QUIRK(0x1025, 0x1534, "Acer Predator PH315-54", ALC255_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1539, "Acer Nitro 5 AN515-57", ALC2XX_FIXUP_HEADSET_MIC),
- SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC2XX_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x159c, "Acer Nitro 5 AN515-58", ALC287_FIXUP_ACER_MICMUTE_LED),
SND_PCI_QUIRK(0x1025, 0x1597, "Acer Nitro 5 AN517-55", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x160e, "Acer PT316-51S", ALC2XX_FIXUP_HEADSET_MIC),
+ SND_PCI_QUIRK(0x1025, 0x161f, "Acer S40-54", ALC256_FIXUP_ACER_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1025, 0x1640, "Acer Aspire A315-44P", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
SND_PCI_QUIRK(0x1025, 0x1679, "Acer Nitro 16 AN16-41", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1025, 0x169a, "Acer Swift SFG16", ALC256_FIXUP_ACER_SFG16_MICMUTE_LED),
SND_PCI_QUIRK(0x1025, 0x171e, "Acer Nitro ANV15-51", ALC245_FIXUP_ACER_MICMUTE_LED),
SND_PCI_QUIRK(0x1025, 0x173a, "Acer Swift SFG14-73", ALC245_FIXUP_ACER_MICMUTE_LED),
+ SND_PCI_QUIRK(0x1025, 0x1758, "Acer Nitro ANV15-41", ALC245_FIXUP_ACER_MICMUTE_LED),
SND_PCI_QUIRK(0x1025, 0x1826, "Acer Helios ZPC", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1025, 0x182c, "Acer Helios ZPD", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1025, 0x1844, "Acer Helios ZPS", ALC287_FIXUP_PREDATOR_SPK_CS35L41_I2C_2),
@@ -6948,9 +6984,11 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x84da, "HP OMEN dc0019-ur", ALC295_FIXUP_HP_OMEN),
SND_PCI_QUIRK(0x103c, 0x84e7, "HP Pavilion 15", ALC269_FIXUP_HP_MUTE_LED_MIC3),
SND_PCI_QUIRK(0x103c, 0x8519, "HP Spectre x360 15-df0xxx", ALC285_FIXUP_HP_SPECTRE_X360),
+ SND_PCI_QUIRK(0x103c, 0x8536, "HP ProBook 430 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8537, "HP ProBook 440 G6", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8548, "HP EliteBook x360 830 G6", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x854a, "HP EliteBook 830 G6", ALC285_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x854d, "HP EliteBook 840 G6", ALC285_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x856a, "HP Pavilion 15-cs1xxx", ALC295_FIXUP_HP_PAVILION_MUTE_LED_1B),
SND_PCI_QUIRK(0x103c, 0x85c6, "HP Pavilion x360 Convertible 14-dy1xxx", ALC295_FIXUP_HP_MUTE_LED_COEFBIT11),
SND_PCI_QUIRK(0x103c, 0x85de, "HP Envy x360 13-ar0xxx", ALC285_FIXUP_HP_ENVY_X360),
@@ -7030,6 +7068,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x88d1, "HP Pavilion 15-eh1xxx (mainboard 88D1)", ALC245_FIXUP_HP_MUTE_LED_V1_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x88dd, "HP Pavilion 15z-ec200", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x88eb, "HP Victus 16-e0xxx", ALC245_FIXUP_HP_MUTE_LED_V2_COEFBIT),
+ SND_PCI_QUIRK(0x103c, 0x88ee, "HP Victus 16-e0xxx (MB 88EE)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8902, "HP OMEN 16", ALC285_FIXUP_HP_MUTE_LED),
SND_PCI_QUIRK(0x103c, 0x890e, "HP 255 G8 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8919, "HP Pavilion Aero Laptop 13-be0xxx", ALC287_FIXUP_HP_GPIO_LED),
@@ -7062,7 +7101,9 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x89d3, "HP EliteBook 645 G9 (MB 89D2)", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x89da, "HP Spectre x360 14t-ea100", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
SND_PCI_QUIRK(0x103c, 0x89e7, "HP Elite x2 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8a06, "HP Dragonfly Folio G3 2-in-1", ALC245_FIXUP_CS35L41_SPI_4_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8a0f, "HP Pavilion 14-ec1xxx", ALC287_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8a1b, "HP 255 15.6 inch G9 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8a1f, "HP Laptop 14s-dr5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8a20, "HP Laptop 15s-fq5xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8a25, "HP Victus 16-d1xxx (MB 8A25)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
@@ -7077,6 +7118,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8a30, "HP Envy 17", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8a31, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8a34, "HP Pavilion x360 2-in-1 Laptop 14-ek0xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
+ SND_PCI_QUIRK(0x103c, 0x8a36, "HP Pavilion Plus 14-eh0xxx", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8a3d, "HP Victus 15-fb0xxx (MB 8A3D)", ALC245_FIXUP_HP_MUTE_LED_V2_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8a4f, "HP Victus 15-fa0xxx (MB 8A4F)", ALC245_FIXUP_HP_MUTE_LED_COEFBIT),
SND_PCI_QUIRK(0x103c, 0x8a6e, "HP EDNA 360", ALC287_FIXUP_CS35L41_I2C_4),
@@ -7096,6 +7138,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8ad8, "HP 800 G9", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b0f, "HP Elite mt645 G7 Mobile Thin Client U81", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8b2f, "HP 255 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
+ SND_PCI_QUIRK(0x103c, 0x8b34, "HP 250 15.6 inch G10 Notebook PC", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
SND_PCI_QUIRK(0x103c, 0x8b3a, "HP Envy 15", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8b3f, "HP mt440 Mobile Thin Client U91", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8b42, "HP", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
@@ -7193,6 +7236,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8ca4, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8ca7, "HP ZBook Fury", ALC245_FIXUP_CS35L41_SPI_2_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8caf, "HP Elite mt645 G8 Mobile Thin Client", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
+ SND_PCI_QUIRK(0x103c, 0x8cbc, "HP Pavilion Laptop 16-ag0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
SND_PCI_QUIRK(0x103c, 0x8cbd, "HP Pavilion Aero Laptop 13-bg0xxx", ALC245_FIXUP_HP_X360_MUTE_LEDS),
SND_PCI_QUIRK(0x103c, 0x8cdd, "HP Spectre", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
SND_PCI_QUIRK(0x103c, 0x8cde, "HP OmniBook Ultra Flip Laptop 14t", ALC245_FIXUP_HP_SPECTRE_X360_EU0XXX),
@@ -7221,7 +7265,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8da0, "HP 16 Clipper OmniBook 7(X360)", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8da1, "HP 16 Clipper OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8da7, "HP 14 Enstrom OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
- SND_PCI_QUIRK(0x103c, 0x8da8, "HP 16 Piston OmniBook X", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x103c, 0x8da8, "HP 16 Piston OmniBook X", ALC245_FIXUP_HP_ENVY_X360_15_FH0XXX),
SND_PCI_QUIRK(0x103c, 0x8dc9, "HP Laptop 15-fc0xxx", ALC236_FIXUP_HP_DMIC),
SND_PCI_QUIRK(0x103c, 0x8dd4, "HP EliteStudio 8 AIO", ALC274_FIXUP_HP_AIO_BIND_DACS),
SND_PCI_QUIRK(0x103c, 0x8dd7, "HP Laptop 15-fd0xxx", ALC236_FIXUP_HP_MUTE_LED_COEFBIT2),
@@ -7233,6 +7277,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8def, "HP EliteBook 660 G12", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8df0, "HP EliteBook 630 G12", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8df1, "HP EliteBook 630 G12", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8df7, "HP Z66 G6", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8dfb, "HP EliteBook 6 G1a 14", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8dfc, "HP EliteBook 645 G12", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8dfd, "HP EliteBook 6 G1a 16", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
@@ -7285,6 +7330,10 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x8f0e, "HP ZBook X G2i 16W", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8f2d, "HP Auster 14", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x103c, 0x8f2e, "HP Auster 14", ALC287_FIXUP_CS35L41_I2C_2),
+ SND_PCI_QUIRK(0x103c, 0x8f37, "HP EliteBook 6 G2i", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8f38, "HP EliteBook 6 G2i", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8f39, "HP EliteBook 6 G2i", ALC236_FIXUP_HP_GPIO_LED),
+ SND_PCI_QUIRK(0x103c, 0x8f3a, "HP EliteBook 6 G2i", ALC236_FIXUP_HP_GPIO_LED),
SND_PCI_QUIRK(0x103c, 0x8f3c, "HP EliteBook 6 G2a", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8f3d, "HP EliteBook 6 G2a", ALC236_FIXUP_HP_MUTE_LED_MICMUTE_VREF),
SND_PCI_QUIRK(0x103c, 0x8f40, "HP ZBook 8 G2a 14", ALC245_FIXUP_HP_TAS2781_I2C_MUTE_LED),
@@ -7312,6 +7361,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x11c0, "ASUS X556UR", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
HDA_CODEC_QUIRK(0x1043, 0x1204, "ASUS Strix G16 G615JMR", ALC287_FIXUP_TXNW2781_I2C_ASUS),
SND_PCI_QUIRK(0x1043, 0x1204, "ASUS Strix G615JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
+ HDA_CODEC_QUIRK(0x1043, 0x1214, "ASUS ROG Strix G615LP", ALC287_FIXUP_TXNW2781_I2C_ASUS),
SND_PCI_QUIRK(0x1043, 0x1214, "ASUS Strix G615LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x1043, 0x125e, "ASUS Q524UQK", ALC255_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1271, "ASUS X430UN", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
@@ -7365,9 +7415,11 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x18f1, "Asus FX505DT", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x194e, "ASUS UX563FD", ALC294_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x1970, "ASUS UX550VE", ALC289_FIXUP_ASUS_GA401),
+ SND_PCI_QUIRK(0x1043, 0x197e, "ASUS VivoBook X509DAP", ALC256_FIXUP_ASUS_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1043, 0x1982, "ASUS B1400CEPE", ALC256_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x19ce, "ASUS B9450FA", ALC294_FIXUP_ASUS_HPE),
SND_PCI_QUIRK(0x1043, 0x19e1, "ASUS UX581LV", ALC295_FIXUP_ASUS_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1043, 0x19f4, "ASUS UM3405GA", ALC294_FIXUP_ASUS_I2C_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
SND_PCI_QUIRK(0x1043, 0x1a63, "ASUS UX3405MA", ALC294_FIXUP_ASUS_SPI_HEADSET_MIC),
SND_PCI_QUIRK(0x1043, 0x1a83, "ASUS UM5302LA", ALC294_FIXUP_CS35L41_I2C_2),
@@ -7445,12 +7497,12 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x3e00, "ASUS G814FH/FM/FP", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x3e20, "ASUS G814PH/PM/PP", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x1043, 0x3e30, "ASUS TP3607SA", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3ee0, "ASUS Strix G815_JHR_JMR_JPR", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3ef0, "ASUS Strix G635LR_LW_LX", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3f00, "ASUS Strix G815LH_LM_LP", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3f10, "ASUS Strix G835LR_LW_LX", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3f20, "ASUS Strix G615LR_LW", ALC287_FIXUP_TAS2781_I2C),
- SND_PCI_QUIRK(0x1043, 0x3f30, "ASUS Strix G815LR_LW", ALC287_FIXUP_TAS2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3ee0, "ASUS Strix G815_JHR_JMR_JPR", ALC287_FIXUP_TXNW2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3ef0, "ASUS Strix G635LR_LW_LX", ALC287_FIXUP_TXNW2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3f00, "ASUS Strix G815LH_LM_LP", ALC287_FIXUP_TXNW2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3f10, "ASUS Strix G835LR_LW_LX", ALC287_FIXUP_TXNW2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3f20, "ASUS Strix G615LR_LW", ALC287_FIXUP_TXNW2781_I2C),
+ SND_PCI_QUIRK(0x1043, 0x3f30, "ASUS Strix G815LR_LW", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x1043, 0x3fd0, "ASUS B3605CVA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x3ff0, "ASUS B5405CVA", ALC245_FIXUP_CS35L41_SPI_2),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
@@ -7504,6 +7556,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x144d, 0xc870, "Samsung Galaxy Book2 Pro (NP950XED)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
SND_PCI_QUIRK(0x144d, 0xc872, "Samsung Galaxy Book2 Pro (NP950XEE)", ALC298_FIXUP_SAMSUNG_AMP_V2_2_AMPS),
SND_PCI_QUIRK(0x144d, 0xc886, "Samsung Galaxy Book3 Pro (NP964XFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
+ SND_PCI_QUIRK(0x144d, 0xc902, "Samsung Galaxy Book5 360 (NP750QHA)", ALC256_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET),
SND_PCI_QUIRK(0x144d, 0xc1ca, "Samsung Galaxy Book3 Pro 360 (NP960QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
SND_PCI_QUIRK(0x144d, 0xc1cb, "Samsung Galaxy Book3 Pro 360 (NP965QFG)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
SND_PCI_QUIRK(0x144d, 0xc1cc, "Samsung Galaxy Book3 Ultra (NT960XFH)", ALC298_FIXUP_SAMSUNG_AMP_V2_4_AMPS),
@@ -7552,6 +7605,7 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0x51b3, "Clevo NS70AU", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x5630, "Clevo NP50RNJS", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x5700, "Clevo X560WN[RST]", ALC256_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0x1558, 0x6480, "Clevo V6xxAW", ALC245_FIXUP_CLEVO_NOISY_MIC),
SND_PCI_QUIRK(0x1558, 0x70a1, "Clevo NB70T[HJK]", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x70b3, "Clevo NK70SB", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0x1558, 0x70f2, "Clevo NH79EPY", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
@@ -7675,10 +7729,12 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x3801, "Lenovo Yoga9 14IAP7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
HDA_CODEC_QUIRK(0x17aa, 0x3802, "DuetITL 2021", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo Yoga Pro 9 14IRP8", ALC287_FIXUP_TAS2781_I2C),
- /* Yoga Pro 9 16IMH9 shares PCI SSID 17aa:3811 with Legion S7 15IMH05;
- * use codec SSID to distinguish them
+ /* Yoga Pro 9 16IMH9 and Legion 7 16ITHG6 share PCI SSID 17aa:3811
+ * with Legion S7 15IMH05; use codec SSID to distinguish them
*/
+ HDA_CODEC_QUIRK(0x17aa, 0x38d5, "Lenovo Yoga Pro 9 16IMH9", ALC287_FIXUP_TAS2781_I2C),
HDA_CODEC_QUIRK(0x17aa, 0x38d6, "Lenovo Yoga Pro 9 16IMH9", ALC287_FIXUP_TAS2781_I2C),
+ HDA_CODEC_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
SND_PCI_QUIRK(0x17aa, 0x3811, "Legion S7 15IMH05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3813, "Legion 7i 15IMHG05", ALC287_FIXUP_LEGION_15IMHG05_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3818, "Lenovo C940 / Yoga Duet 7", ALC298_FIXUP_LENOVO_C940_DUET7),
@@ -7696,17 +7752,23 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
HDA_CODEC_QUIRK(0x17aa, 0x38cf, "Lenovo Yoga Pro 7 14IMH9", ALC287_FIXUP_YOGA9_14IMH9_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x3847, "Legion 7 16ACHG6", ALC287_FIXUP_LEGION_16ACHG6),
SND_PCI_QUIRK(0x17aa, 0x384a, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
+ /* Yoga Pro 7 14IRH8 shares PCI SSID 17aa:3852 with Yoga 7 14ITL5;
+ * use codec SSID to distinguish them
+ */
+ HDA_CODEC_QUIRK(0x17aa, 0x38b1, "Lenovo Yoga Pro 7 14IRH8", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x3852, "Lenovo Yoga 7 14ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3853, "Lenovo Yoga 7 15ITL5", ALC287_FIXUP_YOGA7_14ITL_SPEAKERS),
SND_PCI_QUIRK(0x17aa, 0x3855, "Legion 7 16ITHG6", ALC287_FIXUP_LEGION_16ITHG6),
SND_PCI_QUIRK(0x17aa, 0x3865, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3866, "Lenovo 13X", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3869, "Lenovo Yoga7 14IAL7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+ HDA_CODEC_QUIRK(0x17aa, 0x386a, "Lenovo Yoga 7 16IAP7", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
HDA_CODEC_QUIRK(0x17aa, 0x386e, "Legion Y9000X 2022 IAH7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x386e, "Yoga Pro 7 14ARP8", ALC285_FIXUP_SPEAKER2_TO_DAC1),
HDA_CODEC_QUIRK(0x17aa, 0x38a8, "Legion Pro 7 16ARX8H", ALC287_FIXUP_TAS2781_I2C), /* this must match before PCI SSID 17aa:386f below */
SND_PCI_QUIRK(0x17aa, 0x386f, "Legion Pro 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3870, "Lenovo Yoga 7 14ARB7", ALC287_FIXUP_YOGA7_14ARB7_I2C),
+ SND_PCI_QUIRK(0x17aa, 0x3874, "Legion 7i 16IAX7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3877, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x3878, "Lenovo Legion 7 Slim 16ARHA7", ALC287_FIXUP_CS35L41_I2C_2),
SND_PCI_QUIRK(0x17aa, 0x387d, "Yoga S780-16 pro Quad AAC", ALC287_FIXUP_TAS2781_I2C),
@@ -7752,16 +7814,19 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x17aa, 0x38df, "Y990 YG DUAL", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x38f9, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x38fa, "Thinkbook 16P Gen5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
+ SND_PCI_QUIRK(0x17aa, 0x38fc, "Lenovo Yoga Pro 7 15ASH11", ALC287_FIXUP_LENOVO_YOGA_PRO7),
SND_PCI_QUIRK(0x17aa, 0x38fd, "ThinkBook plus Gen5 Hybrid", ALC287_FIXUP_TAS2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3902, "Lenovo E50-80", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x390d, "Lenovo Yoga Pro 7 14ASP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x3911, "Lenovo Yoga Pro 7 14IAH10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
+ SND_PCI_QUIRK(0x17aa, 0x3912, "Lenovo Xiaoxin 14 GT", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x3913, "Lenovo 145", ALC236_FIXUP_LENOVO_INV_DMIC),
SND_PCI_QUIRK(0x17aa, 0x391a, "Lenovo Yoga Slim 7 14AKP10", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x391f, "Yoga S990-16 pro Quad YC Quad", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3920, "Yoga S990-16 pro Quad VECO Quad", ALC287_FIXUP_TXNW2781_I2C),
SND_PCI_QUIRK(0x17aa, 0x3929, "Thinkbook 13x Gen 5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x392b, "Thinkbook 13x Gen 5", ALC287_FIXUP_MG_RTKC_CSAMP_CS35L41_I2C_THINKPAD),
+ HDA_CODEC_QUIRK(0x17aa, 0x394c, "Lenovo Yoga Slim 7 14AGP11", ALC287_FIXUP_YOGA9_14IAP7_BASS_SPK_PIN),
SND_PCI_QUIRK(0x17aa, 0x3977, "IdeaPad S210", ALC283_FIXUP_INT_MIC),
SND_PCI_QUIRK(0x17aa, 0x3978, "Lenovo B50-70", ALC269_FIXUP_DMIC_THINKPAD_ACPI),
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_PCM_44K),
@@ -7828,6 +7893,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0x1d72, 0x1945, "Redmi G", ALC256_FIXUP_ASUS_HEADSET_MIC),
SND_PCI_QUIRK(0x1d72, 0x1947, "RedmiBook Air", ALC255_FIXUP_XIAOMI_HEADSET_MIC),
SND_PCI_QUIRK(0x1e39, 0xca14, "MEDION NM14LNL", ALC233_FIXUP_MEDION_MTL_SPK),
+ SND_PCI_QUIRK(0x1e50, 0x7007, "Positivo DN50E", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
+ SND_PCI_QUIRK(0x1e50, 0x7038, "Positivo DN140", ALC269_FIXUP_LIMIT_INT_MIC_BOOST),
SND_PCI_QUIRK(0x1ee7, 0x2078, "HONOR BRB-X M1010", ALC2XX_FIXUP_HEADSET_MIC),
SND_PCI_QUIRK(0x1ee7, 0x2081, "HONOR MRB-XXX M1020", ALC256_FIXUP_HONOR_MRB_XXX_M1020_AUDIO),
SND_PCI_QUIRK(0x1f4c, 0xe001, "Minisforum V3 (SE)", ALC245_FIXUP_BASS_HP_DAC),
@@ -7853,7 +7920,8 @@ static const struct hda_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK(0xf111, 0x0009, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0xf111, 0x000b, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
SND_PCI_QUIRK(0xf111, 0x000c, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
- SND_PCI_QUIRK(0xf111, 0x000f, "Framework Laptop", ALC295_FIXUP_FRAMEWORK_LAPTOP_MIC_NO_PRESENCE),
+ SND_PCI_QUIRK(0xf111, 0x000f, "Framework Laptop 13 Pro PTL", ALC295_FIXUP_FRAMEWORK_LAPTOP_LIMIT_INT_MIC_BOOST),
+ SND_PCI_QUIRK(0xf111, 0x010f, "Framework Laptop 13 PTL", ALC295_FIXUP_FRAMEWORK_LAPTOP_LIMIT_INT_MIC_BOOST),
#if 0
/* Below is a quirk table taken from the old code.
diff --git a/sound/hda/codecs/realtek/alc882.c b/sound/hda/codecs/realtek/alc882.c
index 529fecd5baa0..fd466b6985f0 100644
--- a/sound/hda/codecs/realtek/alc882.c
+++ b/sound/hda/codecs/realtek/alc882.c
@@ -61,6 +61,7 @@ enum {
ALC887_FIXUP_ASUS_HMIC,
ALCS1200A_FIXUP_MIC_VREF,
ALC888VD_FIXUP_MIC_100VREF,
+ ALC898_FIXUP_CLEVO_P775TM1,
};
static void alc889_fixup_coef(struct hda_codec *codec,
@@ -236,6 +237,19 @@ static void alc1220_fixup_clevo_pb51ed(struct hda_codec *codec,
alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
}
+/* On Clevo P775TM1, VREF of pin 0x1b enables the external headphone amp */
+static void alc898_fixup_clevo_p775tm1(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+
+ if (action != HDA_FIXUP_ACT_PRE_PROBE)
+ return;
+
+ snd_hda_set_pin_ctl_cache(codec, 0x1b, PIN_VREF80);
+ spec->gen.keep_vref_in_automute = 1;
+}
+
static void alc887_asus_hp_automute_hook(struct hda_codec *codec,
struct hda_jack_callback *jack)
{
@@ -560,6 +574,12 @@ static const struct hda_fixup alc882_fixups[] = {
{}
}
},
+ [ALC898_FIXUP_CLEVO_P775TM1] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = alc898_fixup_clevo_p775tm1,
+ .chained = true,
+ .chain_id = ALC882_FIXUP_EAPD,
+ },
};
static const struct hda_quirk alc882_fixup_tbl[] = {
@@ -664,6 +684,7 @@ static const struct hda_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1558, 0x67f1, "Clevo PC70H[PRS]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x67f5, "Clevo PD70PN[NRT]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x70d1, "Clevo PC70[ER][CDF]", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
+ SND_PCI_QUIRK(0x1558, 0x7709, "Clevo P775TM1", ALC898_FIXUP_CLEVO_P775TM1),
SND_PCI_QUIRK(0x1558, 0x7714, "Clevo X170SM", ALC1220_FIXUP_CLEVO_PB51ED_PINS),
SND_PCI_QUIRK(0x1558, 0x7715, "Clevo X170KM-G", ALC1220_FIXUP_CLEVO_PB51ED),
SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
@@ -719,6 +740,7 @@ static const struct hda_model_fixup alc882_fixup_models[] = {
{.id = ALC1220_FIXUP_GB_DUAL_CODECS, .name = "dual-codecs"},
{.id = ALC1220_FIXUP_GB_X570, .name = "gb-x570"},
{.id = ALC1220_FIXUP_CLEVO_P950, .name = "clevo-p950"},
+ {.id = ALC898_FIXUP_CLEVO_P775TM1, .name = "clevo-p775tm1"},
{}
};
diff --git a/sound/hda/codecs/side-codecs/Kconfig b/sound/hda/codecs/side-codecs/Kconfig
index fc5651e555e3..2a2e8804bf9e 100644
--- a/sound/hda/codecs/side-codecs/Kconfig
+++ b/sound/hda/codecs/side-codecs/Kconfig
@@ -28,6 +28,7 @@ config SND_HDA_SCODEC_CS35L41_I2C
depends on ACPI
depends on EFI
depends on SND_SOC
+ imply SERIAL_MULTI_INSTANTIATE
select SND_SOC_CS35L41_LIB
select SND_HDA_SCODEC_CS35L41
select SND_SOC_CS_AMP_LIB
@@ -44,6 +45,7 @@ config SND_HDA_SCODEC_CS35L41_SPI
depends on ACPI
depends on EFI
depends on SND_SOC
+ imply SERIAL_MULTI_INSTANTIATE
select SND_SOC_CS35L41_LIB
select SND_HDA_SCODEC_CS35L41
select SND_SOC_CS_AMP_LIB
@@ -94,7 +96,6 @@ menu "CS35L56 driver options"
config SND_HDA_SCODEC_CS35L56_CAL_DEBUGFS
bool "CS35L56 create debugfs for factory calibration"
- default N
depends on DEBUG_FS
select SND_SOC_CS35L56_CAL_DEBUGFS_COMMON
help
diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.c b/sound/hda/codecs/side-codecs/cs35l41_hda.c
index b64890006bb7..64a5bd895fd1 100644
--- a/sound/hda/codecs/side-codecs/cs35l41_hda.c
+++ b/sound/hda/codecs/side-codecs/cs35l41_hda.c
@@ -1325,6 +1325,43 @@ static int cs35l41_fw_type_ctl_info(struct snd_kcontrol *kcontrol, struct snd_ct
return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(cs35l41_hda_fw_ids), cs35l41_hda_fw_ids);
}
+static void cs35l41_remove_controls(struct cs35l41_hda *cs35l41)
+{
+ if (!cs35l41->codec)
+ return;
+
+ snd_ctl_remove(cs35l41->codec->card, cs35l41->mute_override_ctl);
+ cs35l41->mute_override_ctl = NULL;
+
+ snd_ctl_remove(cs35l41->codec->card, cs35l41->fw_load_ctl);
+ cs35l41->fw_load_ctl = NULL;
+
+ snd_ctl_remove(cs35l41->codec->card, cs35l41->fw_type_ctl);
+ cs35l41->fw_type_ctl = NULL;
+}
+
+static int cs35l41_add_control(struct cs35l41_hda *cs35l41,
+ struct snd_kcontrol_new *ctl,
+ struct snd_kcontrol **kctl)
+{
+ int ret;
+
+ *kctl = snd_ctl_new1(ctl, cs35l41);
+ if (!*kctl)
+ return -ENOMEM;
+
+ ret = snd_ctl_add(cs35l41->codec->card, *kctl);
+ if (ret) {
+ dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", ctl->name, ret);
+ *kctl = NULL;
+ return ret;
+ }
+
+ dev_dbg(cs35l41->dev, "Added Control %s\n", ctl->name);
+
+ return 0;
+}
+
static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
{
char fw_type_ctl_name[SNDRV_CTL_ELEM_ID_NAME_MAXLEN];
@@ -1360,32 +1397,23 @@ static int cs35l41_create_controls(struct cs35l41_hda *cs35l41)
scnprintf(mute_override_ctl_name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN, "%s Forced Mute Status",
cs35l41->amp_name);
- ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_type_ctl, cs35l41));
- if (ret) {
- dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_type_ctl.name, ret);
- return ret;
- }
-
- dev_dbg(cs35l41->dev, "Added Control %s\n", fw_type_ctl.name);
-
- ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&fw_load_ctl, cs35l41));
- if (ret) {
- dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", fw_load_ctl.name, ret);
- return ret;
- }
-
- dev_dbg(cs35l41->dev, "Added Control %s\n", fw_load_ctl.name);
+ ret = cs35l41_add_control(cs35l41, &fw_type_ctl, &cs35l41->fw_type_ctl);
+ if (ret)
+ goto err;
- ret = snd_ctl_add(cs35l41->codec->card, snd_ctl_new1(&mute_override_ctl, cs35l41));
- if (ret) {
- dev_err(cs35l41->dev, "Failed to add KControl %s = %d\n", mute_override_ctl.name,
- ret);
- return ret;
- }
+ ret = cs35l41_add_control(cs35l41, &fw_load_ctl, &cs35l41->fw_load_ctl);
+ if (ret)
+ goto err;
- dev_dbg(cs35l41->dev, "Added Control %s\n", mute_override_ctl.name);
+ ret = cs35l41_add_control(cs35l41, &mute_override_ctl, &cs35l41->mute_override_ctl);
+ if (ret)
+ goto err;
return 0;
+
+err:
+ cs35l41_remove_controls(cs35l41);
+ return ret;
}
static bool cs35l41_dsm_supported(acpi_handle handle, unsigned int commands)
@@ -1522,6 +1550,10 @@ static void cs35l41_hda_unbind(struct device *dev, struct device *master, void *
device_link_remove(&cs35l41->codec->core.dev, cs35l41->dev);
unlock_system_sleep(sleep_flags);
memset(comp, 0, sizeof(*comp));
+
+ cs35l41_remove_controls(cs35l41);
+ cancel_work_sync(&cs35l41->fw_load_work);
+ cs35l41->codec = NULL;
}
}
@@ -1896,8 +1928,10 @@ static int cs35l41_hda_read_acpi(struct cs35l41_hda *cs35l41, const char *hid, i
cs35l41->dacpi = adev;
physdev = get_device(acpi_get_first_physical_node(adev));
- if (!physdev)
+ if (!physdev) {
+ acpi_dev_put(adev);
return -ENODEV;
+ }
sub = acpi_get_subsystem_id(ACPI_HANDLE(physdev));
if (IS_ERR(sub))
@@ -2058,6 +2092,7 @@ void cs35l41_hda_remove(struct device *dev)
struct cs35l41_hda *cs35l41 = dev_get_drvdata(dev);
component_del(cs35l41->dev, &cs35l41_hda_comp_ops);
+ cancel_work_sync(&cs35l41->fw_load_work);
pm_runtime_get_sync(cs35l41->dev);
pm_runtime_dont_use_autosuspend(cs35l41->dev);
diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda.h b/sound/hda/codecs/side-codecs/cs35l41_hda.h
index 7d003c598e93..56ec07c0bb74 100644
--- a/sound/hda/codecs/side-codecs/cs35l41_hda.h
+++ b/sound/hda/codecs/side-codecs/cs35l41_hda.h
@@ -57,6 +57,8 @@ enum control_bus {
SPI
};
+struct snd_kcontrol;
+
struct cs35l41_hda {
struct device *dev;
struct regmap *regmap;
@@ -75,6 +77,9 @@ struct cs35l41_hda {
int speaker_id;
struct mutex fw_mutex;
struct work_struct fw_load_work;
+ struct snd_kcontrol *fw_type_ctl;
+ struct snd_kcontrol *fw_load_ctl;
+ struct snd_kcontrol *mute_override_ctl;
struct regmap_irq_chip_data *irq_data;
bool firmware_running;
diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda_i2c.c b/sound/hda/codecs/side-codecs/cs35l41_hda_i2c.c
index e77495413c21..fdf406e92fca 100644
--- a/sound/hda/codecs/side-codecs/cs35l41_hda_i2c.c
+++ b/sound/hda/codecs/side-codecs/cs35l41_hda_i2c.c
@@ -6,7 +6,6 @@
//
// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/i2c.h>
@@ -39,8 +38,8 @@ static void cs35l41_hda_i2c_remove(struct i2c_client *clt)
}
static const struct i2c_device_id cs35l41_hda_i2c_id[] = {
- { "cs35l41-hda" },
- {}
+ { .name = "cs35l41-hda" },
+ { }
};
static const struct acpi_device_id cs35l41_acpi_hda_match[] = {
diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda_property.c b/sound/hda/codecs/side-codecs/cs35l41_hda_property.c
index 732ae534db36..416d7bf3e289 100644
--- a/sound/hda/codecs/side-codecs/cs35l41_hda_property.c
+++ b/sound/hda/codecs/side-codecs/cs35l41_hda_property.c
@@ -128,6 +128,7 @@ static const struct cs35l41_config cs35l41_config_table[] = {
{ "17AA3866", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
{ "17AA386E", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
{ "17AA386F", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
+ { "17AA3874", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
{ "17AA3877", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
{ "17AA3878", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, -1, -1, 0, 0, 0 },
{ "17AA38A9", 2, EXTERNAL, { CS35L41_LEFT, CS35L41_RIGHT, 0, 0 }, 0, 2, -1, 0, 0, 0 },
@@ -554,6 +555,7 @@ static const struct cs35l41_prop_model cs35l41_prop_model_table[] = {
{ "CSC3551", "17AA3866", generic_dsd_config },
{ "CSC3551", "17AA386E", generic_dsd_config },
{ "CSC3551", "17AA386F", generic_dsd_config },
+ { "CSC3551", "17AA3874", generic_dsd_config },
{ "CSC3551", "17AA3877", generic_dsd_config },
{ "CSC3551", "17AA3878", generic_dsd_config },
{ "CSC3551", "17AA38A9", generic_dsd_config },
diff --git a/sound/hda/codecs/side-codecs/cs35l41_hda_spi.c b/sound/hda/codecs/side-codecs/cs35l41_hda_spi.c
index 2acbaf8467a0..aab2066a20eb 100644
--- a/sound/hda/codecs/side-codecs/cs35l41_hda_spi.c
+++ b/sound/hda/codecs/side-codecs/cs35l41_hda_spi.c
@@ -6,7 +6,6 @@
//
// Author: Lucas Tanure <tanureal@opensource.cirrus.com>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda.c b/sound/hda/codecs/side-codecs/cs35l56_hda.c
index 4c8d01799931..a0ea08eb96a9 100644
--- a/sound/hda/codecs/side-codecs/cs35l56_hda.c
+++ b/sound/hda/codecs/side-codecs/cs35l56_hda.c
@@ -1025,7 +1025,7 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
u32 values[HDA_MAX_COMPONENTS];
char hid_string[8];
struct acpi_device *adev;
- const char *property, *sub;
+ const char *property;
int i, ret;
/*
@@ -1041,12 +1041,14 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
return -ENODEV;
}
ACPI_COMPANION_SET(cs35l56->base.dev, adev);
+ acpi_dev_put(adev);
}
/* Initialize things that could be overwritten by a fixup */
cs35l56->index = -1;
- sub = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
+ const char *sub __free(kfree) = acpi_get_subsystem_id(ACPI_HANDLE(cs35l56->base.dev));
+
ret = cs35l56_hda_apply_platform_fixups(cs35l56, sub, &id);
if (ret)
return ret;
@@ -1094,15 +1096,16 @@ static int cs35l56_hda_read_acpi(struct cs35l56_hda *cs35l56, int hid, int id)
ret = cirrus_scodec_get_speaker_id(cs35l56->base.dev, cs35l56->index,
cs35l56->num_amps, -1);
if (ret == -ENOENT) {
- cs35l56->system_name = sub;
+ cs35l56->system_name = devm_kstrdup(cs35l56->base.dev, sub, GFP_KERNEL);
} else if (ret >= 0) {
- cs35l56->system_name = kasprintf(GFP_KERNEL, "%s-spkid%d", sub, ret);
- kfree(sub);
- if (!cs35l56->system_name)
- return -ENOMEM;
+ cs35l56->system_name = devm_kasprintf(cs35l56->base.dev, GFP_KERNEL,
+ "%s-spkid%d", sub, ret);
} else {
return ret;
}
+
+ if (!cs35l56->system_name)
+ return -ENOMEM;
}
cs35l56->base.reset_gpio = devm_gpiod_get_index_optional(cs35l56->base.dev,
@@ -1253,7 +1256,6 @@ void cs35l56_hda_remove(struct device *dev)
cs_dsp_remove(&cs35l56->cs_dsp);
- kfree(cs35l56->system_name);
pm_runtime_put_noidle(cs35l56->base.dev);
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
diff --git a/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c b/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c
index 1072f17385ac..e2f51612a73d 100644
--- a/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c
+++ b/sound/hda/codecs/side-codecs/cs35l56_hda_i2c.c
@@ -51,10 +51,10 @@ static void cs35l56_hda_i2c_remove(struct i2c_client *clt)
}
static const struct i2c_device_id cs35l56_hda_i2c_id[] = {
- { "cs35l54-hda", 0x3554 },
- { "cs35l56-hda", 0x3556 },
- { "cs35l57-hda", 0x3557 },
- {}
+ { .name = "cs35l54-hda", .driver_data = 0x3554 },
+ { .name = "cs35l56-hda", .driver_data = 0x3556 },
+ { .name = "cs35l57-hda", .driver_data = 0x3557 },
+ { }
};
static const struct acpi_device_id cs35l56_acpi_hda_match[] = {
diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
index 67240ce184e1..69a22fdfeedb 100644
--- a/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
+++ b/sound/hda/codecs/side-codecs/tas2781_hda_i2c.c
@@ -14,7 +14,6 @@
#include <linux/efi.h>
#include <linux/firmware.h>
#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pci_ids.h>
#include <linux/pm_runtime.h>
@@ -588,6 +587,9 @@ static void tas2781_hda_unbind(struct device *dev,
comp->playback_hook = NULL;
}
+ request_firmware_nowait_cancel(tas_hda->priv->dev, tas_hda->priv,
+ tasdev_fw_ready);
+
tas2781_hda_remove_controls(tas_hda);
tasdevice_config_info_remove(tas_hda->priv);
@@ -791,8 +793,8 @@ static const struct dev_pm_ops tas2781_hda_pm_ops = {
};
static const struct i2c_device_id tas2781_hda_i2c_id[] = {
- { "tas2781-hda" },
- {}
+ { .name = "tas2781-hda" },
+ { }
};
static const struct acpi_device_id tas2781_acpi_hda_match[] = {
diff --git a/sound/hda/codecs/side-codecs/tas2781_hda_spi.c b/sound/hda/codecs/side-codecs/tas2781_hda_spi.c
index 0e4f3553f273..4899ea372798 100644
--- a/sound/hda/codecs/side-codecs/tas2781_hda_spi.c
+++ b/sound/hda/codecs/side-codecs/tas2781_hda_spi.c
@@ -14,7 +14,6 @@
#include <linux/crc32.h>
#include <linux/efi.h>
#include <linux/firmware.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pm_runtime.h>
@@ -190,15 +189,15 @@ static void tas2781_spi_reset(struct tasdevice_priv *tas_dev)
gpiod_set_value_cansleep(tas_dev->reset, 0);
fsleep(800);
gpiod_set_value_cansleep(tas_dev->reset, 1);
- } else {
- ret = tasdevice_dev_write(tas_dev, tas_dev->index,
- TASDEVICE_REG_SWRESET, TASDEVICE_REG_SWRESET_RESET);
- if (ret < 0) {
- dev_err(tas_dev->dev, "dev sw-reset fail, %d\n", ret);
- return;
- }
- fsleep(1000);
}
+
+ ret = tasdevice_dev_write(tas_dev, tas_dev->index,
+ TASDEVICE_REG_SWRESET, TASDEVICE_REG_SWRESET_RESET);
+ if (ret < 0) {
+ dev_err(tas_dev->dev, "dev sw-reset fail, %d\n", ret);
+ return;
+ }
+ fsleep(1000);
}
static int tascodec_spi_init(struct tasdevice_priv *tas_priv,
@@ -593,7 +592,7 @@ static int tas2781_hda_spi_snd_ctls(struct tas2781_hda *h)
return rc;
}
i++;
- snprintf(name, sizeof(name), "Froce Speaker-%d FW Load", p->index);
+ snprintf(name, sizeof(name), "Force Speaker-%d FW Load", p->index);
tas2781_snd_ctls[i].name = name;
h_priv->snd_ctls[i] = snd_ctl_new1(&tas2781_snd_ctls[i], p);
rc = snd_ctl_add(c->card, h_priv->snd_ctls[i]);
@@ -750,6 +749,9 @@ static void tas2781_hda_unbind(struct device *dev, struct device *master,
comp->playback_hook = NULL;
}
+ request_firmware_nowait_cancel(tas_priv->dev, tas_priv,
+ tasdev_fw_ready);
+
tas2781_hda_remove_controls(tas_hda);
tasdevice_config_info_remove(tas_priv);
diff --git a/sound/hda/common/auto_parser.c b/sound/hda/common/auto_parser.c
index 8923813ce424..5bc95d3116ff 100644
--- a/sound/hda/common/auto_parser.c
+++ b/sound/hda/common/auto_parser.c
@@ -1013,7 +1013,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
const char *name = NULL;
const char *type = NULL;
unsigned int vendor, device;
- u16 pci_vendor, pci_device;
+ u16 pci_vendor = 0, pci_device = 0;
u16 codec_vendor, codec_device;
if (codec->fixup_id != HDA_FIXUP_ID_NOT_SET)
@@ -1066,7 +1066,7 @@ void snd_hda_pick_fixup(struct hda_codec *codec,
/* match primarily with the PCI SSID */
for (q = quirk; q->subvendor || q->subdevice; q++) {
/* if the entry is specific to codec SSID, check with it */
- if (!codec->bus->pci || q->match_codec_ssid) {
+ if (!pci_vendor || !pci_device || q->match_codec_ssid) {
if (hda_quirk_match(codec_vendor, codec_device, q)) {
type = "codec SSID";
goto found_device;
diff --git a/sound/hda/common/bind.c b/sound/hda/common/bind.c
index bb1090b65699..6a728a773556 100644
--- a/sound/hda/common/bind.c
+++ b/sound/hda/common/bind.c
@@ -162,8 +162,7 @@ static int hda_codec_driver_remove(struct device *dev)
snd_hda_codec_disconnect_pcms(codec);
snd_hda_jack_tbl_disconnect(codec);
- if (!refcount_dec_and_test(&codec->pcm_ref))
- wait_event(codec->remove_sleep, !refcount_read(&codec->pcm_ref));
+ snd_refcount_sync(&codec->pcm_ref);
snd_power_sync_ref(codec->bus->card);
if (driver->ops->remove)
diff --git a/sound/hda/common/codec.c b/sound/hda/common/codec.c
index c2af2511a831..ef533770179b 100644
--- a/sound/hda/common/codec.c
+++ b/sound/hda/common/codec.c
@@ -689,13 +689,6 @@ get_hda_cvt_setup(struct hda_codec *codec, hda_nid_t nid)
/*
* PCM device
*/
-void snd_hda_codec_pcm_put(struct hda_pcm *pcm)
-{
- if (refcount_dec_and_test(&pcm->codec->pcm_ref))
- wake_up(&pcm->codec->remove_sleep);
-}
-EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_put);
-
struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec,
const char *fmt, ...)
{
@@ -716,7 +709,7 @@ struct hda_pcm *snd_hda_codec_pcm_new(struct hda_codec *codec,
}
list_add_tail(&pcm->list, &codec->pcm_list_head);
- refcount_inc(&codec->pcm_ref);
+ snd_hda_codec_pcm_get(pcm);
return pcm;
}
EXPORT_SYMBOL_GPL(snd_hda_codec_pcm_new);
@@ -787,7 +780,7 @@ void snd_hda_codec_cleanup_for_unbind(struct hda_codec *codec)
remove_conn_list(codec);
snd_hdac_regmap_exit(&codec->core);
codec->configured = 0;
- refcount_set(&codec->pcm_ref, 1); /* reset refcount */
+ snd_refcount_init(&codec->pcm_ref); /* reset refcount */
}
EXPORT_SYMBOL_GPL(snd_hda_codec_cleanup_for_unbind);
@@ -927,8 +920,7 @@ snd_hda_codec_device_init(struct hda_bus *bus, unsigned int codec_addr,
INIT_LIST_HEAD(&codec->conn_list);
INIT_LIST_HEAD(&codec->pcm_list_head);
INIT_DELAYED_WORK(&codec->jackpoll_work, hda_jackpoll_work);
- refcount_set(&codec->pcm_ref, 1);
- init_waitqueue_head(&codec->remove_sleep);
+ snd_refcount_init(&codec->pcm_ref);
return codec;
}
@@ -1699,6 +1691,9 @@ int snd_hda_ctl_add(struct hda_codec *codec, hda_nid_t nid,
unsigned short flags = 0;
struct hda_nid_item *item;
+ if (!kctl)
+ return -EINVAL;
+
if (kctl->id.subdevice & HDA_SUBDEV_AMP_FLAG) {
flags |= HDA_NID_ITEM_AMP;
if (nid == 0)
diff --git a/sound/hda/common/controller.c b/sound/hda/common/controller.c
index 5934e5cdfdfd..afec5c5546ec 100644
--- a/sound/hda/common/controller.c
+++ b/sound/hda/common/controller.c
@@ -97,6 +97,8 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
trace_azx_pcm_close(chip, azx_dev);
scoped_guard(mutex, &chip->open_mutex) {
+ if (chip->ops->pcm_close)
+ chip->ops->pcm_close(chip, azx_dev);
azx_release_device(azx_dev);
if (hinfo->ops.close)
hinfo->ops.close(hinfo, apcm->codec, substream);
@@ -489,9 +491,9 @@ static int azx_get_time_info(struct snd_pcm_substream *substream,
struct snd_pcm_audio_tstamp_config *audio_tstamp_config,
struct snd_pcm_audio_tstamp_report *audio_tstamp_report)
{
+ struct system_device_crosststamp xtstamp = { .clock_id = CLOCK_REALTIME };
struct azx_dev *azx_dev = get_azx_dev(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
- struct system_device_crosststamp xtstamp;
int ret;
u64 nsec;
@@ -525,7 +527,7 @@ static int azx_get_time_info(struct snd_pcm_substream *substream,
break;
default:
- *system_ts = ktime_to_timespec64(xtstamp.sys_realtime);
+ *system_ts = ktime_to_timespec64(xtstamp.sys_systime);
break;
}
@@ -1264,19 +1266,17 @@ int azx_codec_configure(struct azx *chip)
}
EXPORT_SYMBOL_GPL(azx_codec_configure);
-static int stream_direction(struct azx *chip, unsigned char index)
+void azx_add_stream(struct azx *chip, struct azx_dev *azx_dev, int idx, int tag)
{
- if (index >= chip->capture_index_offset &&
- index < chip->capture_index_offset + chip->capture_streams)
- return SNDRV_PCM_STREAM_CAPTURE;
- return SNDRV_PCM_STREAM_PLAYBACK;
+ snd_hdac_stream_init(azx_bus(chip), azx_stream(azx_dev), idx,
+ azx_stream_direction(chip, idx), tag);
}
+EXPORT_SYMBOL_GPL(azx_add_stream);
/* initialize SD streams */
int azx_init_streams(struct azx *chip)
{
int i;
- int stream_tags[2] = { 0, 0 };
/* initialize each stream (aka device)
* assign the starting bdl address to each stream (device)
@@ -1284,24 +1284,10 @@ int azx_init_streams(struct azx *chip)
*/
for (i = 0; i < chip->num_streams; i++) {
struct azx_dev *azx_dev = kzalloc_obj(*azx_dev);
- int dir, tag;
if (!azx_dev)
return -ENOMEM;
-
- dir = stream_direction(chip, i);
- /* stream tag must be unique throughout
- * the stream direction group,
- * valid values 1...15
- * use separate stream tag if the flag
- * AZX_DCAPS_SEPARATE_STREAM_TAG is used
- */
- if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG)
- tag = ++stream_tags[dir];
- else
- tag = i + 1;
- snd_hdac_stream_init(azx_bus(chip), azx_stream(azx_dev),
- i, dir, tag);
+ azx_add_stream(chip, azx_dev, i, i + 1);
}
return 0;
diff --git a/sound/hda/common/hda_controller.h b/sound/hda/common/hda_controller.h
index 7434f38038a0..38227f82e704 100644
--- a/sound/hda/common/hda_controller.h
+++ b/sound/hda/common/hda_controller.h
@@ -57,13 +57,12 @@ enum {
struct azx_dev {
struct hdac_stream core;
- unsigned int irq_pending:1;
/*
* For VIA:
* A flag to ensure DMA position is 0
* when link position is not greater than FIFO size
*/
- unsigned int insufficient:1;
+ bool insufficient;
};
#define azx_stream(dev) (&(dev)->core)
@@ -79,6 +78,8 @@ struct hda_controller_ops {
int (*position_check)(struct azx *chip, struct azx_dev *azx_dev);
/* enable/disable the link power */
int (*link_power)(struct azx *chip, bool enable);
+ /* additional hook for PCM */
+ void (*pcm_close)(struct azx *chip, struct azx_dev *azx_dev);
};
struct azx_pcm {
@@ -206,6 +207,15 @@ int azx_bus_init(struct azx *chip, const char *model);
int azx_probe_codecs(struct azx *chip, unsigned int max_slots);
int azx_codec_configure(struct azx *chip);
int azx_init_streams(struct azx *chip);
+void azx_add_stream(struct azx *chip, struct azx_dev *s, int idx, int tag);
void azx_free_streams(struct azx *chip);
+static inline int azx_stream_direction(struct azx *chip, unsigned char index)
+{
+ if (index >= chip->capture_index_offset &&
+ index < chip->capture_index_offset + chip->capture_streams)
+ return SNDRV_PCM_STREAM_CAPTURE;
+ return SNDRV_PCM_STREAM_PLAYBACK;
+}
+
#endif /* __SOUND_HDA_CONTROLLER_H */
diff --git a/sound/hda/common/jack.c b/sound/hda/common/jack.c
index 98ba1c4d5ba4..e0a5cc38540b 100644
--- a/sound/hda/common/jack.c
+++ b/sound/hda/common/jack.c
@@ -58,6 +58,12 @@ static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid, int dev_id)
AC_VERB_GET_PIN_SENSE, dev_id);
if (codec->inv_jack_detect)
val ^= AC_PINSENSE_PRESENCE;
+ if (codec->eld_jack_detect) {
+ if (val & AC_PINSENSE_ELDV)
+ val |= AC_PINSENSE_PRESENCE;
+ else
+ val &= ~AC_PINSENSE_PRESENCE;
+ }
return val;
}
diff --git a/sound/hda/controllers/Kconfig b/sound/hda/controllers/Kconfig
index 72855f2df451..5d6a77e68588 100644
--- a/sound/hda/controllers/Kconfig
+++ b/sound/hda/controllers/Kconfig
@@ -1,7 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
config SND_HDA_INTEL
tristate "HD Audio PCI"
- depends on SND_PCI
+ depends on PCI
select SND_HDA
select SND_INTEL_DSP_CONFIG
help
diff --git a/sound/hda/controllers/intel.c b/sound/hda/controllers/intel.c
index c87d75dbd8aa..4b03c64e72ab 100644
--- a/sound/hda/controllers/intel.c
+++ b/sound/hda/controllers/intel.c
@@ -615,17 +615,17 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev);
/* called from IRQ */
static int azx_position_check(struct azx *chip, struct azx_dev *azx_dev)
{
- struct hda_intel *hda = container_of(chip, struct hda_intel, chip);
+ struct hda_intel_stream *istream = azx_dev_to_istream(azx_dev);
int ok;
ok = azx_position_ok(chip, azx_dev);
if (ok == 1) {
- azx_dev->irq_pending = 0;
+ istream->irq_pending = false;
return ok;
} else if (ok == 0) {
/* bogus IRQ, process it later */
- azx_dev->irq_pending = 1;
- schedule_work(&hda->irq_pending_work);
+ istream->irq_pending = true;
+ schedule_work(&istream->irq_pending_work);
}
return 0;
}
@@ -721,11 +721,13 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
*/
static void azx_irq_pending_work(struct work_struct *work)
{
- struct hda_intel *hda = container_of(work, struct hda_intel, irq_pending_work);
+ struct hda_intel_stream *istream =
+ container_of(work, struct hda_intel_stream, irq_pending_work);
+ struct azx_dev *azx_dev = &istream->azx_dev;
+ struct hda_intel *hda = istream->hda;
struct azx *chip = &hda->chip;
struct hdac_bus *bus = azx_bus(chip);
- struct hdac_stream *s;
- int pending, ok;
+ int ok;
if (!hda->irq_pending_warned) {
dev_info(chip->card->dev,
@@ -735,42 +737,51 @@ static void azx_irq_pending_work(struct work_struct *work)
}
for (;;) {
- pending = 0;
- spin_lock_irq(&bus->reg_lock);
- list_for_each_entry(s, &bus->stream_list, list) {
- struct azx_dev *azx_dev = stream_to_azx_dev(s);
- if (!azx_dev->irq_pending ||
- !s->substream ||
- !s->running)
- continue;
+ scoped_guard(spinlock_irq, &bus->reg_lock) {
+ if (!istream->irq_pending ||
+ !azx_dev->core.substream ||
+ !azx_dev->core.running) {
+ return;
+ }
+
ok = azx_position_ok(chip, azx_dev);
- if (ok > 0) {
- azx_dev->irq_pending = 0;
- spin_unlock(&bus->reg_lock);
- snd_pcm_period_elapsed(s->substream);
- spin_lock(&bus->reg_lock);
- } else if (ok < 0) {
- pending = 0; /* too early */
- } else
- pending++;
+ if (ok < 0)
+ return; /* too early */
+ if (ok > 0)
+ istream->irq_pending = false;
}
- spin_unlock_irq(&bus->reg_lock);
- if (!pending)
+
+ if (ok) {
+ snd_pcm_period_elapsed(azx_dev->core.substream);
return;
+ }
+
msleep(1);
}
}
/* clear irq_pending flags and assure no on-going workq */
+static void hda_intel_stream_clear_irq_pending(struct azx_dev *azx_dev)
+{
+ struct hda_intel_stream *istream = azx_dev_to_istream(azx_dev);
+
+ istream->irq_pending = false;
+ cancel_work_sync(&istream->irq_pending_work);
+}
+
+/* called at PCM close */
+static void hda_intel_pcm_close(struct azx *chip, struct azx_dev *azx_dev)
+{
+ hda_intel_stream_clear_irq_pending(azx_dev);
+}
+
static void azx_clear_irq_pending(struct azx *chip)
{
struct hdac_bus *bus = azx_bus(chip);
struct hdac_stream *s;
- guard(spinlock_irq)(&bus->reg_lock);
list_for_each_entry(s, &bus->stream_list, list) {
- struct azx_dev *azx_dev = stream_to_azx_dev(s);
- azx_dev->irq_pending = 0;
+ hda_intel_stream_clear_irq_pending(stream_to_azx_dev(s));
}
}
@@ -1797,7 +1808,6 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
if (jackpoll_ms[dev] >= 50 && jackpoll_ms[dev] <= 60000)
chip->jackpoll_interval = msecs_to_jiffies(jackpoll_ms[dev]);
INIT_LIST_HEAD(&chip->pcm_list);
- INIT_WORK(&hda->irq_pending_work, azx_irq_pending_work);
INIT_LIST_HEAD(&hda->list);
init_vga_switcheroo(chip);
init_completion(&hda->probe_wait);
@@ -1846,6 +1856,39 @@ static int azx_create(struct snd_card *card, struct pci_dev *pci,
return 0;
}
+/* create and assign streams */
+static int hda_init_streams(struct azx *chip)
+{
+ int i;
+ int stream_tags[2] = { 0, 0 };
+
+ for (i = 0; i < chip->num_streams; i++) {
+ struct hda_intel_stream *s = kzalloc_obj(*s);
+ int tag, dir;
+
+ if (!s)
+ return -ENOMEM;
+
+ s->hda = container_of(chip, struct hda_intel, chip);
+ INIT_WORK(&s->irq_pending_work, azx_irq_pending_work);
+
+ /* stream tag must be unique throughout
+ * the stream direction group,
+ * valid values 1...15
+ * use separate stream tag if the flag
+ * AZX_DCAPS_SEPARATE_STREAM_TAG is used
+ */
+ dir = azx_stream_direction(chip, i);
+ if (chip->driver_caps & AZX_DCAPS_SEPARATE_STREAM_TAG)
+ tag = ++stream_tags[dir];
+ else
+ tag = i + 1;
+ azx_add_stream(chip, &s->azx_dev, i, tag);
+ }
+
+ return 0;
+}
+
static int azx_first_init(struct azx *chip)
{
int dev = chip->dev_index;
@@ -2000,7 +2043,7 @@ static int azx_first_init(struct azx *chip)
}
/* initialize streams */
- err = azx_init_streams(chip);
+ err = hda_init_streams(chip);
if (err < 0)
return err;
@@ -2099,6 +2142,7 @@ static const struct dmi_system_id driver_denylist_dmi[] = {
static const struct hda_controller_ops pci_hda_ops = {
.disable_msi_reset_irq = disable_msi_reset_irq,
.position_check = azx_position_check,
+ .pcm_close = hda_intel_pcm_close,
};
static DECLARE_BITMAP(probed_devs, SNDRV_CARDS);
diff --git a/sound/hda/controllers/intel.h b/sound/hda/controllers/intel.h
index 2d1725f86ef1..4efb3b0fc2d8 100644
--- a/sound/hda/controllers/intel.h
+++ b/sound/hda/controllers/intel.h
@@ -9,9 +9,6 @@
struct hda_intel {
struct azx chip;
- /* for pending irqs */
- struct work_struct irq_pending_work;
-
/* sync probing */
struct completion probe_wait;
struct delayed_work probe_work;
@@ -35,4 +32,16 @@ struct hda_intel {
int probe_retry; /* being probe-retry */
};
+struct hda_intel_stream {
+ struct azx_dev azx_dev;
+
+ /* for pending irqs */
+ struct hda_intel *hda;
+ struct work_struct irq_pending_work;
+ bool irq_pending;
+};
+
+#define azx_dev_to_istream(azx_dev) \
+ container_of(azx_dev, struct hda_intel_stream, azx_dev)
+
#endif
diff --git a/sound/hda/core/hda_bus_type.c b/sound/hda/core/hda_bus_type.c
index eb72a7af2e56..a4afd41b6f84 100644
--- a/sound/hda/core/hda_bus_type.c
+++ b/sound/hda/core/hda_bus_type.c
@@ -5,7 +5,6 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/export.h>
#include <sound/hdaudio.h>
diff --git a/sound/hda/core/i915.c b/sound/hda/core/i915.c
index 44438c799f95..6c068b135b7d 100644
--- a/sound/hda/core/i915.c
+++ b/sound/hda/core/i915.c
@@ -130,22 +130,22 @@ static int i915_gfx_present(struct pci_dev *hdac_pci)
/* List of known platforms with no i915 support. */
static const struct pci_device_id denylist[] = {
/* CNL */
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a40), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a41), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a42), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a44), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a49), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a4a), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a4c), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a50), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a51), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a52), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a54), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a59), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a5a), 0x030000, 0xff0000 },
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a5c), 0x030000, 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a40), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a41), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a42), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a44), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a49), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a4a), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a4c), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a50), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a51), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a52), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a54), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a59), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a5a), .class = 0x030000, .class_mask = 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x5a5c), .class = 0x030000, .class_mask = 0xff0000 },
/* LKF */
- { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9840), 0x030000, 0xff0000 },
+ { PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x9840), .class = 0x030000, .class_mask = 0xff0000 },
{}
};
struct pci_dev *display_dev = NULL;
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index 3d1f19321b9e..ecff521957cb 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -103,8 +103,8 @@ MODULE_PARM_DESC(mpuport, "MPU-401 port # for CMI8330/CMI8329 driver.");
module_param_hw_array(mpuirq, int, irq, NULL, 0444);
MODULE_PARM_DESC(mpuirq, "IRQ # for CMI8330/CMI8329 MPU-401 port.");
#ifdef CONFIG_PNP
-static int isa_registered;
-static int pnp_registered;
+static int isa_registered __ro_after_init;
+static int pnp_registered __ro_after_init;
#endif
#define CMI8330_RMUX3D 16
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index e36cc147651a..ecce31b348b0 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -69,9 +69,9 @@ module_param_hw_array(dma2, int, dma, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA2 # for " IDENT " driver.");
#ifdef CONFIG_PNP
-static int isa_registered;
-static int pnpc_registered;
-static int pnp_registered;
+static int isa_registered __ro_after_init;
+static int pnpc_registered __ro_after_init;
+static int pnp_registered __ro_after_init;
#endif /* CONFIG_PNP */
struct snd_card_cs4236 {
@@ -94,7 +94,7 @@ static const struct pnp_device_id snd_cs423x_pnpbiosids[] = {
/* Guillemot Turtlebeach something appears to be cs4232 compatible
* (untested) */
{ .id = "GIM0100" },
- { .id = "" }
+ { }
};
MODULE_DEVICE_TABLE(pnp, snd_cs423x_pnpbiosids);
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index 1da7b400a17b..3cadbf7cf238 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -1762,6 +1762,8 @@ static int snd_es18xx_mixer(struct snd_card *card)
for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_base_controls); idx++) {
struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(&snd_es18xx_base_controls[idx], chip);
+ if (!kctl)
+ return -ENOMEM;
if (chip->caps & ES18XX_HWV) {
switch (idx) {
case 0:
@@ -1823,6 +1825,8 @@ static int snd_es18xx_mixer(struct snd_card *card)
for (idx = 0; idx < ARRAY_SIZE(snd_es18xx_hw_volume_controls); idx++) {
struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(&snd_es18xx_hw_volume_controls[idx], chip);
+ if (!kctl)
+ return -ENOMEM;
if (idx == 0)
chip->hw_volume = kctl;
else
@@ -1924,14 +1928,14 @@ module_param_hw_array(dma2, int, dma, NULL, 0444);
MODULE_PARM_DESC(dma2, "DMA 2 # for ES18xx driver.");
#ifdef CONFIG_PNP
-static int isa_registered;
-static int pnp_registered;
-static int pnpc_registered;
+static int isa_registered __ro_after_init;
+static int pnp_registered __ro_after_init;
+static int pnpc_registered __ro_after_init;
static const struct pnp_device_id snd_audiodrive_pnpbiosids[] = {
{ .id = "ESS1869" },
{ .id = "ESS1879" },
- { .id = "" } /* end */
+ { } /* end */
};
MODULE_DEVICE_TABLE(pnp, snd_audiodrive_pnpbiosids);
diff --git a/sound/isa/gus/gus_pcm.c b/sound/isa/gus/gus_pcm.c
index a0757e1ede46..08ccb4d80ade 100644
--- a/sound/isa/gus/gus_pcm.c
+++ b/sound/isa/gus/gus_pcm.c
@@ -851,6 +851,8 @@ int snd_gf1_pcm_new(struct snd_gus_card *gus, int pcm_dev, int control_index)
kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control1, gus);
else
kctl = snd_ctl_new1(&snd_gf1_pcm_volume_control, gus);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.index = control_index;
err = snd_ctl_add(card, kctl);
if (err < 0)
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index 6c3a2977dcb3..115f900fa063 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -111,8 +111,8 @@ struct snd_interwave {
#ifdef CONFIG_PNP
-static int isa_registered;
-static int pnp_registered;
+static int isa_registered __ro_after_init;
+static int pnp_registered __ro_after_init;
static const struct pnp_card_device_id snd_interwave_pnpids[] = {
#ifndef SNDRV_STB
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 5b729bb02ef6..0d5f4461a7bc 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -1199,8 +1199,8 @@ static int snd_msnd_pnp_resume(struct pnp_card_link *pcard)
}
#endif
-static int isa_registered;
-static int pnp_registered;
+static int isa_registered __ro_after_init;
+static int pnp_registered __ro_after_init;
static const struct pnp_card_device_id msnd_pnpids[] = {
/* Pinnacle PnP */
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 8c1767697b62..66b1e361c101 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -69,9 +69,9 @@ module_param_array(opl3sa3_ymode, int, NULL, 0444);
MODULE_PARM_DESC(opl3sa3_ymode, "Speaker size selection for 3D Enhancement mode: Desktop/Large Notebook/Small Notebook/HiFi.");
#ifdef CONFIG_PNP
-static int isa_registered;
-static int pnp_registered;
-static int pnpc_registered;
+static int isa_registered __ro_after_init;
+static int pnp_registered __ro_after_init;
+static int pnpc_registered __ro_after_init;
#endif
/* control ports */
@@ -125,7 +125,7 @@ struct snd_opl3sa2 {
static const struct pnp_device_id snd_opl3sa2_pnpbiosids[] = {
{ .id = "YMH0021" },
{ .id = "NMX2210" }, /* Gateway Solo 2500 */
- { .id = "" } /* end */
+ { } /* end */
};
MODULE_DEVICE_TABLE(pnp, snd_opl3sa2_pnpbiosids);
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index c320af3e9a05..e5870e5e07db 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -88,6 +88,25 @@ MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
#define OPTi9XX_MC_REG(n) n
+enum {
+ MIRO_ACI_MASTER,
+ MIRO_ACI_MIC,
+ MIRO_ACI_LINE,
+ MIRO_ACI_CD,
+ MIRO_ACI_SYNTH,
+ MIRO_ACI_PCM,
+ MIRO_ACI_LINE1,
+ MIRO_ACI_LINE2,
+ MIRO_ACI_EQ1,
+ MIRO_ACI_EQ2,
+ MIRO_ACI_EQ3,
+ MIRO_ACI_EQ4,
+ MIRO_ACI_EQ5,
+ MIRO_ACI_EQ6,
+ MIRO_ACI_EQ7,
+ MIRO_ACI_COUNT,
+};
+
struct snd_miro {
unsigned short hardware;
unsigned char password;
@@ -102,6 +121,7 @@ struct snd_miro {
spinlock_t lock;
struct snd_pcm *pcm;
+ struct snd_wss *codec;
long wss_base;
int irq;
@@ -113,6 +133,12 @@ struct snd_miro {
struct snd_card *card;
struct snd_miro_aci *aci;
+#ifdef CONFIG_PM
+ unsigned char aci_saved[MIRO_ACI_COUNT][2];
+ unsigned char aci_saved_amp;
+ unsigned char aci_saved_preamp;
+ unsigned char aci_saved_solomode;
+#endif
};
static struct snd_miro_aci aci_device;
@@ -664,6 +690,44 @@ static const unsigned char aci_init_values[][2] = {
{ ACI_SET_MASTER + 1, 0x20 },
};
+#ifdef CONFIG_PM
+static const unsigned char snd_miro_saved_get_regs[MIRO_ACI_COUNT] = {
+ [MIRO_ACI_MASTER] = ACI_GET_MASTER,
+ [MIRO_ACI_MIC] = ACI_GET_MIC,
+ [MIRO_ACI_LINE] = ACI_GET_LINE,
+ [MIRO_ACI_CD] = ACI_GET_CD,
+ [MIRO_ACI_SYNTH] = ACI_GET_SYNTH,
+ [MIRO_ACI_PCM] = ACI_GET_PCM,
+ [MIRO_ACI_LINE1] = ACI_GET_LINE1,
+ [MIRO_ACI_LINE2] = ACI_GET_LINE2,
+ [MIRO_ACI_EQ1] = ACI_GET_EQ1,
+ [MIRO_ACI_EQ2] = ACI_GET_EQ2,
+ [MIRO_ACI_EQ3] = ACI_GET_EQ3,
+ [MIRO_ACI_EQ4] = ACI_GET_EQ4,
+ [MIRO_ACI_EQ5] = ACI_GET_EQ5,
+ [MIRO_ACI_EQ6] = ACI_GET_EQ6,
+ [MIRO_ACI_EQ7] = ACI_GET_EQ7,
+};
+
+static const unsigned char snd_miro_saved_set_regs[MIRO_ACI_COUNT] = {
+ [MIRO_ACI_MASTER] = ACI_SET_MASTER,
+ [MIRO_ACI_MIC] = ACI_SET_MIC,
+ [MIRO_ACI_LINE] = ACI_SET_LINE,
+ [MIRO_ACI_CD] = ACI_SET_CD,
+ [MIRO_ACI_SYNTH] = ACI_SET_SYNTH,
+ [MIRO_ACI_PCM] = ACI_SET_PCM,
+ [MIRO_ACI_LINE1] = ACI_SET_LINE1,
+ [MIRO_ACI_LINE2] = ACI_SET_LINE2,
+ [MIRO_ACI_EQ1] = ACI_SET_EQ1,
+ [MIRO_ACI_EQ2] = ACI_SET_EQ2,
+ [MIRO_ACI_EQ3] = ACI_SET_EQ3,
+ [MIRO_ACI_EQ4] = ACI_SET_EQ4,
+ [MIRO_ACI_EQ5] = ACI_SET_EQ5,
+ [MIRO_ACI_EQ6] = ACI_SET_EQ6,
+ [MIRO_ACI_EQ7] = ACI_SET_EQ7,
+};
+#endif
+
static int snd_set_aci_init_values(struct snd_miro *miro)
{
int idx, error;
@@ -702,11 +766,116 @@ static int snd_set_aci_init_values(struct snd_miro *miro)
}
aci->aci_amp = 0;
aci->aci_preamp = 0;
- aci->aci_solomode = 1;
+ aci->aci_solomode = 0;
+
+ return 0;
+}
+
+static int snd_miro_aci_force_known_state(struct snd_miro_aci *aci)
+{
+ int i, err;
+
+ for (i = 0; i < 3; i++) {
+ err = snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1);
+ if (err < 0)
+ return err;
+ }
return 0;
}
+static int snd_miro_aci_initialize(struct snd_miro_aci *aci)
+{
+ int err;
+
+ err = snd_aci_cmd(aci, ACI_INIT, -1, -1);
+ if (err < 0)
+ return err;
+ err = snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP);
+ if (err < 0)
+ return err;
+
+ return snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP);
+}
+
+#ifdef CONFIG_PM
+static int snd_miro_save_aci_state(struct snd_miro *miro)
+{
+ struct snd_miro_aci *aci = miro->aci;
+ int i, limit, value;
+
+ limit = aci->aci_product == 'C' ? MIRO_ACI_COUNT : MIRO_ACI_LINE2 + 1;
+ for (i = 0; i < limit; i++) {
+ value = aci_getvalue(aci, snd_miro_saved_get_regs[i]);
+ if (value < 0)
+ return value;
+ miro->aci_saved[i][1] = value;
+
+ value = aci_getvalue(aci, snd_miro_saved_get_regs[i] + 1);
+ if (value < 0)
+ return value;
+ miro->aci_saved[i][0] = value;
+ }
+
+ miro->aci_saved_amp = aci->aci_amp;
+ if (aci->aci_version <= 176) {
+ miro->aci_saved_preamp = aci->aci_preamp;
+ } else {
+ value = aci_getvalue(aci, ACI_GET_PREAMP);
+ if (value < 0)
+ return value;
+ miro->aci_saved_preamp = value;
+ }
+
+ value = aci_getvalue(aci, ACI_S_GENERAL);
+ if (value < 0)
+ return value;
+ miro->aci_saved_solomode = !(value & 0x20);
+
+ return 0;
+}
+
+static int snd_miro_restore_aci_state(struct snd_miro *miro)
+{
+ struct snd_miro_aci *aci = miro->aci;
+ int i, limit, err, left_reg;
+
+ err = snd_set_aci_init_values(miro);
+ if (err < 0)
+ return err;
+
+ limit = aci->aci_product == 'C' ? MIRO_ACI_COUNT : MIRO_ACI_LINE2 + 1;
+ for (i = 0; i < limit; i++) {
+ left_reg = snd_miro_saved_set_regs[i] == ACI_SET_MASTER ?
+ snd_miro_saved_set_regs[i] + 1 :
+ snd_miro_saved_set_regs[i] + 8;
+ err = aci_setvalue(aci, left_reg, miro->aci_saved[i][0]);
+ if (err < 0)
+ return err;
+ err = aci_setvalue(aci, snd_miro_saved_set_regs[i],
+ miro->aci_saved[i][1]);
+ if (err < 0)
+ return err;
+ }
+
+ err = aci_setvalue(aci, ACI_SET_POWERAMP, miro->aci_saved_amp);
+ if (err < 0)
+ return err;
+ err = aci_setvalue(aci, ACI_SET_PREAMP, miro->aci_saved_preamp);
+ if (err < 0)
+ return err;
+ err = aci_setvalue(aci, ACI_SET_SOLOMODE, miro->aci_saved_solomode);
+ if (err < 0)
+ return err;
+
+ aci->aci_amp = miro->aci_saved_amp;
+ aci->aci_preamp = miro->aci_saved_preamp;
+ aci->aci_solomode = miro->aci_saved_solomode;
+
+ return 0;
+}
+#endif
+
static int snd_miro_mixer(struct snd_card *card,
struct snd_miro *miro)
{
@@ -1203,7 +1372,7 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
struct snd_miro *miro)
{
unsigned char regval;
- int i;
+ int err;
struct snd_miro_aci *aci = &aci_device;
miro->aci = aci;
@@ -1224,12 +1393,12 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
return -ENOMEM;
}
- /* force ACI into a known state */
- for (i = 0; i < 3; i++)
- if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) {
- dev_err(card->dev, "can't force aci into known state.\n");
- return -ENXIO;
- }
+ /* force ACI into a known state */
+ err = snd_miro_aci_force_known_state(aci);
+ if (err < 0) {
+ dev_err(card->dev, "can't force aci into known state.\n");
+ return -ENXIO;
+ }
aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1);
aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1);
@@ -1246,9 +1415,8 @@ static int snd_card_miro_aci_detect(struct snd_card *card,
return -ENXIO;
}
- if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 ||
- snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 ||
- snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) {
+ err = snd_miro_aci_initialize(aci);
+ if (err < 0) {
dev_err(card->dev, "can't initialize aci.\n");
return -ENXIO;
}
@@ -1299,6 +1467,7 @@ static int snd_miro_probe(struct snd_card *card)
WSS_HW_DETECT, 0, &codec);
if (error < 0)
return error;
+ miro->codec = codec;
error = snd_wss_pcm(codec, 0);
if (error < 0)
@@ -1408,6 +1577,7 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
return error;
miro = card->private_data;
+ miro->card = card;
error = snd_card_miro_detect(card, miro);
if (error < 0) {
@@ -1470,12 +1640,69 @@ static int snd_miro_isa_probe(struct device *devptr, unsigned int n)
return 0;
}
+#ifdef CONFIG_PM
+static int snd_miro_suspend(struct snd_card *card)
+{
+ struct snd_miro *miro = card->private_data;
+ int error;
+
+ error = snd_miro_save_aci_state(miro);
+ if (error < 0)
+ return error;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ miro->codec->suspend(miro->codec);
+ return 0;
+}
+
+static int snd_miro_resume(struct snd_card *card)
+{
+ struct snd_miro *miro = card->private_data;
+ int error;
+
+ error = snd_miro_configure(miro);
+ if (error < 0)
+ return error;
+ error = snd_miro_aci_force_known_state(miro->aci);
+ if (error < 0) {
+ dev_err(card->dev, "can't force aci into known state\n");
+ return error;
+ }
+ error = snd_miro_aci_initialize(miro->aci);
+ if (error < 0) {
+ dev_err(card->dev, "can't initialize aci\n");
+ return error;
+ }
+ error = snd_miro_restore_aci_state(miro);
+ if (error < 0)
+ return error;
+
+ miro->codec->resume(miro->codec);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+
+static int snd_miro_isa_suspend(struct device *dev, unsigned int n,
+ pm_message_t state)
+{
+ return snd_miro_suspend(dev_get_drvdata(dev));
+}
+
+static int snd_miro_isa_resume(struct device *dev, unsigned int n)
+{
+ return snd_miro_resume(dev_get_drvdata(dev));
+}
+#endif
+
#define DEV_NAME "miro"
static struct isa_driver snd_miro_driver = {
.match = snd_miro_isa_match,
.probe = snd_miro_isa_probe,
- /* FIXME: suspend/resume */
+#ifdef CONFIG_PM
+ .suspend = snd_miro_isa_suspend,
+ .resume = snd_miro_isa_resume,
+#endif
.driver = {
.name = DEV_NAME
},
@@ -1591,12 +1818,29 @@ static void snd_miro_pnp_remove(struct pnp_card_link *pcard)
snd_miro_pnp_is_probed = 0;
}
+#ifdef CONFIG_PM
+static int snd_miro_pnp_suspend(struct pnp_card_link *pcard,
+ pm_message_t state)
+{
+ return snd_miro_suspend(pnp_get_card_drvdata(pcard));
+}
+
+static int snd_miro_pnp_resume(struct pnp_card_link *pcard)
+{
+ return snd_miro_resume(pnp_get_card_drvdata(pcard));
+}
+#endif
+
static struct pnp_card_driver miro_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "miro",
.id_table = snd_miro_pnpids,
.probe = snd_miro_pnp_probe,
.remove = snd_miro_pnp_remove,
+#ifdef CONFIG_PM
+ .suspend = snd_miro_pnp_suspend,
+ .resume = snd_miro_pnp_resume,
+#endif
};
#endif
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 208d1942a015..866d7f5c58a0 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -99,8 +99,8 @@ MODULE_PARM_DESC(seq_ports, "Number of sequencer ports for WaveTable synth.");
#endif
#ifdef CONFIG_PNP
-static int isa_registered;
-static int pnp_registered;
+static int isa_registered __ro_after_init;
+static int pnp_registered __ro_after_init;
#endif
struct snd_card_sb16 {
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index 553ceb92d298..ce8a59650e38 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -71,8 +71,8 @@ module_param_array(joystick, bool, NULL, 0444);
MODULE_PARM_DESC(joystick, "Enable gameport.");
#ifdef CONFIG_PNP
-static int isa_registered;
-static int pnp_registered;
+static int isa_registered __ro_after_init;
+static int pnp_registered __ro_after_init;
static const struct pnp_card_device_id sscape_pnpids[] = {
{ .id = "ENS3081", .devs = { { "ENS0000" } } }, /* Soundscape PnP */
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 07c68568091d..5b1917cc19ce 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -71,8 +71,8 @@ module_param_array(use_cs4232_midi, bool, NULL, 0444);
MODULE_PARM_DESC(use_cs4232_midi, "Use CS4232 MPU-401 interface (inaccessibly located inside your computer)");
#ifdef CONFIG_PNP
-static int isa_registered;
-static int pnp_registered;
+static int isa_registered __ro_after_init;
+static int pnp_registered __ro_after_init;
static const struct pnp_card_device_id snd_wavefront_pnpids[] = {
/* Tropez */
@@ -353,6 +353,7 @@ snd_wavefront_probe (struct snd_card *card, int dev)
dev_err(card->dev, "can't allocate WSS device\n");
return err;
}
+ acard->chip = chip;
err = snd_wss_pcm(chip, 0);
if (err < 0)
@@ -400,6 +401,7 @@ snd_wavefront_probe (struct snd_card *card, int dev)
acard->wavefront.irq = ics2115_irq[dev];
card->sync_irq = acard->wavefront.irq;
acard->wavefront.base = ics2115_port[dev];
+ snd_wavefront_cache_firmware(&acard->wavefront);
wavefront_synth = snd_wavefront_new_synth(card, hw_dev, acard);
if (wavefront_synth == NULL) {
@@ -553,12 +555,51 @@ static int snd_wavefront_isa_probe(struct device *pdev,
return 0;
}
+#ifdef CONFIG_PM
+static int snd_wavefront_suspend(struct snd_card *card)
+{
+ snd_wavefront_card_t *acard = card->private_data;
+
+ snd_wavefront_midi_suspend(acard);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ acard->chip->suspend(acard->chip);
+ return 0;
+}
+
+static int snd_wavefront_resume(struct snd_card *card)
+{
+ snd_wavefront_card_t *acard = card->private_data;
+ int err;
+
+ acard->chip->resume(acard->chip);
+ err = snd_wavefront_resume_synth(acard);
+ if (err < 0)
+ return err;
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
+}
+
+static int snd_wavefront_isa_suspend(struct device *dev, unsigned int id,
+ pm_message_t state)
+{
+ return snd_wavefront_suspend(dev_get_drvdata(dev));
+}
+
+static int snd_wavefront_isa_resume(struct device *dev, unsigned int id)
+{
+ return snd_wavefront_resume(dev_get_drvdata(dev));
+}
+#endif
+
#define DEV_NAME "wavefront"
static struct isa_driver snd_wavefront_driver = {
.match = snd_wavefront_isa_match,
.probe = snd_wavefront_isa_probe,
- /* FIXME: suspend, resume */
+#ifdef CONFIG_PM
+ .suspend = snd_wavefront_isa_suspend,
+ .resume = snd_wavefront_isa_resume,
+#endif
.driver = {
.name = DEV_NAME
},
@@ -600,12 +641,28 @@ static int snd_wavefront_pnp_detect(struct pnp_card_link *pcard,
return 0;
}
+#ifdef CONFIG_PM
+static int snd_wavefront_pnpc_suspend(struct pnp_card_link *pcard,
+ pm_message_t state)
+{
+ return snd_wavefront_suspend(pnp_get_card_drvdata(pcard));
+}
+
+static int snd_wavefront_pnpc_resume(struct pnp_card_link *pcard)
+{
+ return snd_wavefront_resume(pnp_get_card_drvdata(pcard));
+}
+#endif
+
static struct pnp_card_driver wavefront_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.name = "wavefront",
.id_table = snd_wavefront_pnpids,
.probe = snd_wavefront_pnp_detect,
- /* FIXME: suspend,resume */
+#ifdef CONFIG_PM
+ .suspend = snd_wavefront_pnpc_suspend,
+ .resume = snd_wavefront_pnpc_resume,
+#endif
};
#endif /* CONFIG_PNP */
diff --git a/sound/isa/wavefront/wavefront_midi.c b/sound/isa/wavefront/wavefront_midi.c
index 69d87c4cafae..fb184d9ef284 100644
--- a/sound/isa/wavefront/wavefront_midi.c
+++ b/sound/isa/wavefront/wavefront_midi.c
@@ -455,6 +455,49 @@ snd_wavefront_midi_disable_virtual (snd_wavefront_card_t *card)
card->wavefront.midi.isvirtual = 0;
}
+void
+snd_wavefront_midi_suspend(snd_wavefront_card_t *card)
+
+{
+ snd_wavefront_midi_t *midi = &card->wavefront.midi;
+
+ if (!midi->istimer)
+ return;
+
+ timer_delete_sync(&midi->timer);
+
+ guard(spinlock_irqsave)(&midi->virtual);
+ midi->istimer = 0;
+}
+
+void
+snd_wavefront_midi_resume(snd_wavefront_card_t *card)
+
+{
+ snd_wavefront_midi_t *midi = &card->wavefront.midi;
+ int istimer = 0;
+ bool pending_output = false;
+
+ midi->timer_card = card;
+
+ scoped_guard(spinlock_irqsave, &midi->virtual) {
+ if (midi->mode[internal_mpu] & MPU401_MODE_OUTPUT_TRIGGER)
+ istimer++;
+ if (midi->mode[external_mpu] & MPU401_MODE_OUTPUT_TRIGGER)
+ istimer++;
+ if (!istimer)
+ return;
+
+ midi->istimer = istimer;
+ timer_setup(&midi->timer, snd_wavefront_midi_output_timer, 0);
+ mod_timer(&midi->timer, 1 + jiffies);
+ pending_output = true;
+ }
+
+ if (pending_output)
+ snd_wavefront_midi_output_write(card);
+}
+
int
snd_wavefront_midi_start (snd_wavefront_card_t *card)
@@ -466,6 +509,7 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card)
dev = &card->wavefront;
midi = &dev->midi;
+ midi->timer_card = card;
/* The ICS2115 MPU-401 interface doesn't do anything
until its set into UART mode.
@@ -511,6 +555,8 @@ snd_wavefront_midi_start (snd_wavefront_card_t *card)
dev_warn(card->wavefront.card->dev,
"can't enable MIDI-IN-2-synth routing.\n");
/* XXX error ? */
+ } else {
+ dev->midi_in_to_synth = 1;
}
/* Turn on Virtual MIDI, but first *always* turn it off,
@@ -553,4 +599,3 @@ const struct snd_rawmidi_ops snd_wavefront_midi_input =
.close = snd_wavefront_midi_input_close,
.trigger = snd_wavefront_midi_input_trigger,
};
-
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index 33b563707a58..2f57a6795d22 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -1626,6 +1626,14 @@ wavefront_synth_control (snd_wavefront_card_t *acard,
"support for sample aliases still being considered.\n");
break;
+ case WFC_MISYNTH_OFF:
+ dev->midi_in_to_synth = 0;
+ break;
+
+ case WFC_MISYNTH_ON:
+ dev->midi_in_to_synth = 1;
+ break;
+
case WFC_VMIDI_OFF:
snd_wavefront_midi_disable_virtual (acard);
break;
@@ -1639,6 +1647,83 @@ wavefront_synth_control (snd_wavefront_card_t *acard,
return 0;
}
+static int
+wavefront_restore_midi_state(snd_wavefront_card_t *acard, char isvirtual,
+ char midi_in_to_synth)
+{
+ snd_wavefront_t *dev = &acard->wavefront;
+ unsigned char rbuf[4], wbuf[4];
+
+ if (dev->midi_in_to_synth != midi_in_to_synth) {
+ if (snd_wavefront_cmd(dev, midi_in_to_synth ?
+ WFC_MISYNTH_ON : WFC_MISYNTH_OFF,
+ rbuf, wbuf)) {
+ dev_err(dev->card->dev,
+ "cannot restore MIDI-IN routing after resume\n");
+ return -EIO;
+ }
+ dev->midi_in_to_synth = midi_in_to_synth;
+ }
+
+ if (dev->midi.isvirtual != isvirtual) {
+ if (snd_wavefront_cmd(dev, isvirtual ?
+ WFC_VMIDI_ON : WFC_VMIDI_OFF,
+ rbuf, wbuf)) {
+ dev_err(dev->card->dev,
+ "cannot restore virtual MIDI mode after resume\n");
+ return -EIO;
+ }
+ if (isvirtual)
+ snd_wavefront_midi_enable_virtual(acard);
+ else
+ snd_wavefront_midi_disable_virtual(acard);
+ }
+
+ return 0;
+}
+
+int snd_wavefront_resume_synth(snd_wavefront_card_t *acard)
+{
+ snd_wavefront_t *dev = &acard->wavefront;
+ char was_virtual = dev->midi.isvirtual;
+ char midi_in_to_synth = dev->midi_in_to_synth;
+ char rom_samples_rdonly = dev->rom_samples_rdonly;
+ int err;
+
+ err = snd_wavefront_detect(acard);
+ if (err < 0)
+ dev->israw = 1;
+
+ if (dev->israw) {
+ dev->fx_initialized = 0;
+ err = snd_wavefront_start(dev);
+ if (err < 0)
+ return err;
+ } else {
+ dev->has_fx = (snd_wavefront_fx_detect(dev) == 0);
+ wavefront_get_sample_status(dev, 0);
+ wavefront_get_program_status(dev);
+ wavefront_get_patch_status(dev);
+ outb(0x80 | 0x40 | 0x20, dev->control_port);
+ }
+
+ dev->rom_samples_rdonly = rom_samples_rdonly;
+ dev->midi.base = dev->base;
+
+ err = snd_wavefront_midi_start(acard);
+ if (err < 0)
+ return err;
+
+ err = wavefront_restore_midi_state(acard, was_virtual,
+ midi_in_to_synth);
+ if (err < 0)
+ return err;
+
+ snd_wavefront_midi_resume(acard);
+
+ return 0;
+}
+
int
snd_wavefront_synth_open (struct snd_hwdep *hw, struct file *file)
@@ -2032,6 +2117,17 @@ wavefront_download_firmware (snd_wavefront_t *dev, char *path)
return 1;
}
+void snd_wavefront_cache_firmware(snd_wavefront_t *dev)
+{
+ int err;
+
+ err = firmware_request_cache(dev->card->dev, ospath);
+ if (err < 0)
+ dev_warn(dev->card->dev,
+ "unable to cache firmware %s for resume: %d\n",
+ ospath, err);
+}
+
static int
wavefront_do_reset (snd_wavefront_t *dev)
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
index a718b75bb6a0..e80f730d0803 100644
--- a/sound/oss/dmasound/dmasound_core.c
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -574,11 +574,6 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft,
uWritten = 0 ;
}
-/* FIXME: I think that this may be the wrong behaviour when we get strapped
- for time and the cpu is close to being (or actually) behind in sending data.
- - because we've lost the time that the N samples, already in the buffer,
- would have given us to get here with the next lot from the user.
-*/
/* The interrupt doesn't start to play the last, incomplete frame.
* Thus we can append to it without disabling the interrupts! (Note
* also that write_sq.rear isn't affected by the interrupt.)
@@ -598,6 +593,11 @@ static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft,
write_sq.syncing &= ~2 ; /* take out POST status */
spin_unlock_irqrestore(&dmasound.lock, flags);
+ /* Start any already-complete fragments before we spend
+ * more time extending the incomplete tail fragment.
+ */
+ sq_play();
+
if (write_sq.count > 0 &&
(bLeft = write_sq.block_size-write_sq.rear_size) > 0) {
dest = write_sq.buffers[write_sq.rear];
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index 571d89a6a8da..f07c5f4c2380 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -247,8 +247,8 @@ struct snd_ali {
};
static const struct pci_device_id snd_ali_ids[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451), 0, 0, 0},
- {0, }
+ { PCI_DEVICE(PCI_VENDOR_ID_AL, PCI_DEVICE_ID_AL_M5451) },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_ali_ids);
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index a73893a2cbd6..00f0720169c3 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -127,9 +127,9 @@ struct snd_als300_substream_data {
};
static const struct pci_device_id snd_als300_ids[] = {
- { 0x4005, 0x0300, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300 },
- { 0x4005, 0x0308, PCI_ANY_ID, PCI_ANY_ID, 0, 0, DEVICE_ALS300_PLUS },
- { 0, }
+ { PCI_DEVICE(0x4005, 0x0300), .driver_data = DEVICE_ALS300 },
+ { PCI_DEVICE(0x4005, 0x0308), .driver_data = DEVICE_ALS300_PLUS },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_als300_ids);
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index 636f309c9424..6396aa6c3bf0 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -102,8 +102,8 @@ struct snd_card_als4000 {
};
static const struct pci_device_id snd_als4000_ids[] = {
- { 0x4005, 0x4000, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0, }, /* ALS4000 */
- { 0, }
+ { PCI_DEVICE(0x4005, 0x4000) }, /* ALS4000 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_als4000_ids);
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index b1c7ed7f1604..4dbc79899c09 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -2933,13 +2933,16 @@ static void snd_asihpi_remove(struct pci_dev *pci_dev)
}
static const struct pci_device_id asihpi_pci_tbl[] = {
- {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205,
- HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
- (kernel_ulong_t)HPI_6205},
- {HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040,
- HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
- (kernel_ulong_t)HPI_6000},
- {0,}
+ {
+ PCI_DEVICE_SUB(HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205,
+ HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID),
+ .driver_data = (kernel_ulong_t)HPI_6205,
+ }, {
+ PCI_DEVICE_SUB(HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040,
+ HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID),
+ .driver_data = (kernel_ulong_t)HPI_6000,
+ },
+ {}
};
MODULE_DEVICE_TABLE(pci, asihpi_pci_tbl);
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c
index d846777e7462..5f69c04c672a 100644
--- a/sound/pci/asihpi/hpicmn.c
+++ b/sound/pci/asihpi/hpicmn.c
@@ -276,6 +276,12 @@ static short find_control(u16 control_index,
return 0;
}
+ if (control_index >= p_cache->control_count) {
+ HPI_DEBUG_LOG(VERBOSE, "control_index out of bounce %d\n",
+ control_index);
+ return 0;
+ }
+
*pI = p_cache->p_info[control_index];
if (!*pI) {
HPI_DEBUG_LOG(VERBOSE, "Uncached Control %d\n",
@@ -641,16 +647,11 @@ void hpi_cmn_control_cache_sync_to_msg(struct hpi_control_cache *p_cache,
struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
const u32 size_in_bytes, u8 *p_dsp_control_buffer)
{
- struct hpi_control_cache *p_cache = kmalloc_obj(*p_cache);
- if (!p_cache)
- return NULL;
+ struct hpi_control_cache *p_cache;
- p_cache->p_info =
- kzalloc_objs(*p_cache->p_info, control_count);
- if (!p_cache->p_info) {
- kfree(p_cache);
+ p_cache = kzalloc_flex(*p_cache, p_info, control_count);
+ if (!p_cache)
return NULL;
- }
p_cache->cache_size_in_bytes = size_in_bytes;
p_cache->control_count = control_count;
@@ -661,10 +662,7 @@ struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
void hpi_free_control_cache(struct hpi_control_cache *p_cache)
{
- if (p_cache) {
- kfree(p_cache->p_info);
- kfree(p_cache);
- }
+ kfree(p_cache);
}
static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
diff --git a/sound/pci/asihpi/hpicmn.h b/sound/pci/asihpi/hpicmn.h
index 8ec656cf8848..40af7329587a 100644
--- a/sound/pci/asihpi/hpicmn.h
+++ b/sound/pci/asihpi/hpicmn.h
@@ -37,10 +37,10 @@ struct hpi_control_cache {
u16 adap_idx;
u32 control_count;
u32 cache_size_in_bytes;
- /** pointer to allocated memory of lookup pointers. */
- struct hpi_control_cache_info **p_info;
/** pointer to DSP's control cache. */
u8 *p_cache;
+ /** pointer to allocated memory of lookup pointers. */
+ struct hpi_control_cache_info *p_info[] __counted_by(control_count);
};
struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index);
diff --git a/sound/pci/asihpi/hpipcida.h b/sound/pci/asihpi/hpipcida.h
index 0673e8278070..6dceff2b4741 100644
--- a/sound/pci/asihpi/hpipcida.h
+++ b/sound/pci/asihpi/hpipcida.h
@@ -15,12 +15,12 @@
*/
{
-HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205,
- HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
- (kernel_ulong_t) HPI_6205}
-, {
-HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040,
- HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID, 0, 0,
- (kernel_ulong_t) HPI_6000}
-, {
-0}
+ PCI_DEVICE_SUB(HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_DSP6205,
+ HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID),
+ .driver_data = (kernel_ulong_t) HPI_6205,
+}, {
+ PCI_DEVICE_SUB(HPI_PCI_VENDOR_ID_TI, HPI_PCI_DEV_ID_PCI2040,
+ HPI_PCI_VENDOR_ID_AUDIOSCIENCE, PCI_ANY_ID),
+ .driver_data = (kernel_ulong_t) HPI_6000,
+},
+{ }
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 2a0c59d5afa5..b738295b41e5 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -272,11 +272,11 @@ struct atiixp {
/*
*/
static const struct pci_device_id snd_atiixp_ids[] = {
- { PCI_VDEVICE(ATI, 0x4341), 0 }, /* SB200 */
- { PCI_VDEVICE(ATI, 0x4361), 0 }, /* SB300 */
- { PCI_VDEVICE(ATI, 0x4370), 0 }, /* SB400 */
- { PCI_VDEVICE(ATI, 0x4382), 0 }, /* SB600 */
- { 0, }
+ { PCI_VDEVICE(ATI, 0x4341) }, /* SB200 */
+ { PCI_VDEVICE(ATI, 0x4361) }, /* SB300 */
+ { PCI_VDEVICE(ATI, 0x4370) }, /* SB400 */
+ { PCI_VDEVICE(ATI, 0x4382) }, /* SB600 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 91f31e2ad3d3..8aaeb197ce45 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -247,9 +247,9 @@ struct atiixp_modem {
/*
*/
static const struct pci_device_id snd_atiixp_ids[] = {
- { PCI_VDEVICE(ATI, 0x434d), 0 }, /* SB200 */
- { PCI_VDEVICE(ATI, 0x4378), 0 }, /* SB400 */
- { 0, }
+ { PCI_VDEVICE(ATI, 0x434d) }, /* SB200 */
+ { PCI_VDEVICE(ATI, 0x4378) }, /* SB400 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
diff --git a/sound/pci/au88x0/au8810.c b/sound/pci/au88x0/au8810.c
index b2bfa50bfe30..f712e32d3370 100644
--- a/sound/pci/au88x0/au8810.c
+++ b/sound/pci/au88x0/au8810.c
@@ -2,8 +2,8 @@
#include "au8810.h"
#include "au88x0.h"
static const struct pci_device_id snd_vortex_ids[] = {
- {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE), 1,},
- {0,}
+ { PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_ADVANTAGE), .driver_data = 1 },
+ { }
};
#include "au88x0_core.c"
diff --git a/sound/pci/au88x0/au8820.c b/sound/pci/au88x0/au8820.c
index dbc2263b49c6..aa841b615182 100644
--- a/sound/pci/au88x0/au8820.c
+++ b/sound/pci/au88x0/au8820.c
@@ -2,8 +2,8 @@
#include "au8820.h"
#include "au88x0.h"
static const struct pci_device_id snd_vortex_ids[] = {
- {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1), 0,},
- {0,}
+ { PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_1), .driver_data = 0 },
+ { }
};
#include "au88x0_synth.c"
diff --git a/sound/pci/au88x0/au8830.c b/sound/pci/au88x0/au8830.c
index e963c4e2f026..aeb8d458c629 100644
--- a/sound/pci/au88x0/au8830.c
+++ b/sound/pci/au88x0/au8830.c
@@ -2,8 +2,8 @@
#include "au8830.h"
#include "au88x0.h"
static const struct pci_device_id snd_vortex_ids[] = {
- {PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2), 0,},
- {0,}
+ { PCI_VDEVICE(AUREAL, PCI_DEVICE_ID_AUREAL_VORTEX_2), .driver_data = 0 },
+ { }
};
#include "au88x0_synth.c"
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index e2c501f4394c..60a87322eae4 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -142,9 +142,8 @@ module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable Audiowerk2 soundcard.");
static const struct pci_device_id snd_aw2_ids[] = {
- {PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0, 0,
- 0, 0, 0},
- {0}
+ { PCI_DEVICE_SUB(PCI_VENDOR_ID_PHILIPS, PCI_DEVICE_ID_PHILIPS_SAA7146, 0, 0) },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_aw2_ids);
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 6cdf76e2b7d2..ccca82417657 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -305,9 +305,9 @@ struct snd_azf3328 {
};
static const struct pci_device_id snd_azf3328_ids[] = {
- { 0x122D, 0x50DC, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* PCI168/3328 */
- { 0x122D, 0x80DA, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* 3328 */
- { 0, }
+ { PCI_DEVICE(0x122D, 0x50DC) }, /* PCI168/3328 */
+ { PCI_DEVICE(0x122D, 0x80DA) }, /* 3328 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_azf3328_ids);
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 35392f6525b3..cf923f551211 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1820,8 +1820,8 @@ static SIMPLE_DEV_PM_OPS(snd_ca0106_pm, snd_ca0106_suspend, snd_ca0106_resume);
// PCI IDs
static const struct pci_device_id snd_ca0106_ids[] = {
- { PCI_VDEVICE(CREATIVE, 0x0007), 0 }, /* Audigy LS or Live 24bit */
- { 0, }
+ { PCI_VDEVICE(CREATIVE, 0x0007) }, /* Audigy LS or Live 24bit */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_ca0106_ids);
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index cd73b6833639..9d9f784e3a8c 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -2637,16 +2637,22 @@ static int snd_cmipci_mixer_new(struct cmipci *cm, int pcm_spdif_device)
}
if (cm->can_ac3_hw) {
kctl = snd_ctl_new1(&snd_cmipci_spdif_default, cm);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = pcm_spdif_device;
err = snd_ctl_add(card, kctl);
if (err < 0)
return err;
kctl = snd_ctl_new1(&snd_cmipci_spdif_mask, cm);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = pcm_spdif_device;
err = snd_ctl_add(card, kctl);
if (err < 0)
return err;
kctl = snd_ctl_new1(&snd_cmipci_spdif_stream, cm);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = pcm_spdif_device;
err = snd_ctl_add(card, kctl);
if (err < 0)
@@ -2721,12 +2727,12 @@ static void snd_cmipci_proc_init(struct cmipci *cm)
}
static const struct pci_device_id snd_cmipci_ids[] = {
- {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A), 0},
- {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B), 0},
- {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738), 0},
- {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B), 0},
- {PCI_VDEVICE(AL, PCI_DEVICE_ID_CMEDIA_CM8738), 0},
- {0,},
+ {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338A) },
+ {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8338B) },
+ {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738) },
+ {PCI_VDEVICE(CMEDIA, PCI_DEVICE_ID_CMEDIA_CM8738B) },
+ {PCI_VDEVICE(AL, PCI_DEVICE_ID_CMEDIA_CM8738) },
+ { }
};
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index d00b2c9fb1e3..f51f4bb63766 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -476,8 +476,8 @@ struct cs4281 {
static irqreturn_t snd_cs4281_interrupt(int irq, void *dev_id);
static const struct pci_device_id snd_cs4281_ids[] = {
- { PCI_VDEVICE(CIRRUS, 0x6005), 0, }, /* CS4281 */
- { 0, }
+ { PCI_VDEVICE(CIRRUS, 0x6005) }, /* CS4281 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_cs4281_ids);
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 9c1995737eb7..0cb7c2a2929f 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -43,10 +43,10 @@ module_param_array(mmap_valid, bool, NULL, 0444);
MODULE_PARM_DESC(mmap_valid, "Support OSS mmap.");
static const struct pci_device_id snd_cs46xx_ids[] = {
- { PCI_VDEVICE(CIRRUS, 0x6001), 0, }, /* CS4280 */
- { PCI_VDEVICE(CIRRUS, 0x6003), 0, }, /* CS4612 */
- { PCI_VDEVICE(CIRRUS, 0x6004), 0, }, /* CS4615 */
- { 0, }
+ { PCI_VDEVICE(CIRRUS, 0x6001) }, /* CS4280 */
+ { PCI_VDEVICE(CIRRUS, 0x6003) }, /* CS4612 */
+ { PCI_VDEVICE(CIRRUS, 0x6004) }, /* CS4615 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_cs46xx_ids);
diff --git a/sound/pci/ctxfi/ctmixer.c b/sound/pci/ctxfi/ctmixer.c
index e3ee76bd8482..9abe1d53c3c5 100644
--- a/sound/pci/ctxfi/ctmixer.c
+++ b/sound/pci/ctxfi/ctmixer.c
@@ -221,10 +221,6 @@ ct_mixer_recording_select(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
static void
ct_mixer_recording_unselect(struct ct_mixer *mixer, enum CT_AMIXER_CTL type);
-/* FIXME: this static looks like it would fail if more than one card was */
-/* installed. */
-static struct snd_kcontrol *kctls[2] = {NULL};
-
static enum CT_AMIXER_CTL get_amixer_index(enum CTALSA_MIXER_CTL alsa_index)
{
switch (alsa_index) {
@@ -481,17 +477,18 @@ static struct snd_kcontrol_new mic_source_ctl = {
static void
do_line_mic_switch(struct ct_atc *atc, enum CTALSA_MIXER_CTL type)
{
+ struct ct_mixer *mixer = atc->mixer;
if (MIXER_LINEIN_C_S == type) {
atc->select_line_in(atc);
- set_switch_state(atc->mixer, MIXER_MIC_C_S, 0);
+ set_switch_state(mixer, MIXER_MIC_C_S, 0);
snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
- &kctls[1]->id);
+ &mixer->line_mic_kctls[1]->id);
} else if (MIXER_MIC_C_S == type) {
atc->select_mic_in(atc);
- set_switch_state(atc->mixer, MIXER_LINEIN_C_S, 0);
+ set_switch_state(mixer, MIXER_LINEIN_C_S, 0);
snd_ctl_notify(atc->card, SNDRV_CTL_EVENT_MASK_VALUE,
- &kctls[0]->id);
+ &mixer->line_mic_kctls[0]->id);
}
}
@@ -778,9 +775,9 @@ ct_mixer_kcontrol_new(struct ct_mixer *mixer, struct snd_kcontrol_new *new)
switch (new->private_value) {
case MIXER_LINEIN_C_S:
- kctls[0] = kctl; break;
+ mixer->line_mic_kctls[0] = kctl; break;
case MIXER_MIC_C_S:
- kctls[1] = kctl; break;
+ mixer->line_mic_kctls[1] = kctl; break;
default:
break;
}
@@ -965,35 +962,20 @@ error1:
static int ct_mixer_get_mem(struct ct_mixer **rmixer)
{
struct ct_mixer *mixer;
- int err;
+ size_t alloc_size;
*rmixer = NULL;
/* Allocate mem for mixer obj */
- mixer = kzalloc_obj(*mixer);
+ alloc_size = struct_size(mixer, amixers, NUM_CT_AMIXERS * CHN_NUM);
+ alloc_size += sizeof(*mixer->sums) * NUM_CT_SUMS * CHN_NUM;
+ mixer = kzalloc(alloc_size, GFP_KERNEL);
if (!mixer)
return -ENOMEM;
- mixer->amixers = kcalloc(NUM_CT_AMIXERS * CHN_NUM, sizeof(void *),
- GFP_KERNEL);
- if (!mixer->amixers) {
- err = -ENOMEM;
- goto error1;
- }
- mixer->sums = kcalloc(NUM_CT_SUMS * CHN_NUM, sizeof(void *),
- GFP_KERNEL);
- if (!mixer->sums) {
- err = -ENOMEM;
- goto error2;
- }
+ mixer->sums = (struct sum **)(mixer->amixers + (NUM_CT_AMIXERS * CHN_NUM));
*rmixer = mixer;
return 0;
-
-error2:
- kfree(mixer->amixers);
-error1:
- kfree(mixer);
- return err;
}
static int ct_mixer_topology_build(struct ct_mixer *mixer)
@@ -1228,8 +1210,6 @@ int ct_mixer_destroy(struct ct_mixer *mixer)
}
/* Release mem assigned to mixer object */
- kfree(mixer->sums);
- kfree(mixer->amixers);
kfree(mixer);
return 0;
diff --git a/sound/pci/ctxfi/ctmixer.h b/sound/pci/ctxfi/ctmixer.h
index e812f6c93b41..0c0963bba99c 100644
--- a/sound/pci/ctxfi/ctmixer.h
+++ b/sound/pci/ctxfi/ctmixer.h
@@ -17,6 +17,8 @@
#include "ctatc.h"
#include "ctresource.h"
+struct snd_kcontrol;
+
#define INIT_VOL 0x1c00
enum MIXER_PORT_T {
@@ -41,8 +43,8 @@ enum MIXER_PORT_T {
struct ct_mixer {
struct ct_atc *atc;
- void **amixers; /* amixer resources for volume control */
- void **sums; /* sum resources for signal collection */
+ struct sum **sums; /* sum resources for signal collection */
+ struct snd_kcontrol *line_mic_kctls[2]; /* line/mic capture switch controls */
unsigned int switch_state; /* A bit-map to indicate state of switches */
int (*get_output_ports)(struct ct_mixer *mixer, enum MIXER_PORT_T type,
@@ -55,6 +57,7 @@ struct ct_mixer {
#ifdef CONFIG_PM_SLEEP
int (*resume)(struct ct_mixer *mixer);
#endif
+ struct amixer *amixers[]; /* amixer resources for volume control */
};
int ct_alsa_mix_create(struct ct_atc *atc,
diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c
index 326997bb885d..46dc1f509234 100644
--- a/sound/pci/ctxfi/ctsrc.c
+++ b/sound/pci/ctxfi/ctsrc.c
@@ -668,13 +668,6 @@ static int srcimp_rsc_init(struct srcimp *srcimp,
if (err)
return err;
- /* Reserve memory for imapper nodes */
- srcimp->imappers = kzalloc_objs(struct imapper, desc->msr);
- if (!srcimp->imappers) {
- err = -ENOMEM;
- goto error1;
- }
-
/* Set srcimp specific operations */
srcimp->rsc.ops = &srcimp_basic_rsc_ops;
srcimp->ops = &srcimp_ops;
@@ -683,16 +676,10 @@ static int srcimp_rsc_init(struct srcimp *srcimp,
srcimp->rsc.ops->master(&srcimp->rsc);
return 0;
-
-error1:
- rsc_uninit(&srcimp->rsc);
- return err;
}
static int srcimp_rsc_uninit(struct srcimp *srcimp)
{
- kfree(srcimp->imappers);
- srcimp->imappers = NULL;
srcimp->ops = NULL;
srcimp->mgr = NULL;
rsc_uninit(&srcimp->rsc);
@@ -711,7 +698,7 @@ static int get_srcimp_rsc(struct srcimp_mgr *mgr,
*rsrcimp = NULL;
/* Allocate mem for SRCIMP resource */
- srcimp = kzalloc(sizeof(*srcimp), GFP_KERNEL);
+ srcimp = kzalloc_flex(*srcimp, imappers, desc->msr);
if (!srcimp)
return -ENOMEM;
diff --git a/sound/pci/ctxfi/ctsrc.h b/sound/pci/ctxfi/ctsrc.h
index e6366cc6a7ae..7ba94adde920 100644
--- a/sound/pci/ctxfi/ctsrc.h
+++ b/sound/pci/ctxfi/ctsrc.h
@@ -103,10 +103,10 @@ struct srcimp_rsc_ops;
struct srcimp {
struct rsc rsc;
unsigned char idx[8];
- struct imapper *imappers;
unsigned int mapped; /* A bit-map indicating which conj rsc is mapped */
struct srcimp_mgr *mgr;
const struct srcimp_rsc_ops *ops;
+ struct imapper imappers[];
};
struct srcimp_rsc_ops {
diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c
index e295c71c7a39..48c25bd3f401 100644
--- a/sound/pci/echoaudio/darla20.c
+++ b/sound/pci/echoaudio/darla20.c
@@ -52,8 +52,8 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x1801, 0xECC0, 0x0010, 0, 0, 0}, /* DSP 56301 Darla20 rev.0 */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0010) }, /* DSP 56301 Darla20 rev.0 */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c
index ae816e78f599..c8cdd1b052df 100644
--- a/sound/pci/echoaudio/darla24.c
+++ b/sound/pci/echoaudio/darla24.c
@@ -56,9 +56,9 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x1801, 0xECC0, 0x0040, 0, 0, 0}, /* DSP 56301 Darla24 rev.0 */
- {0x1057, 0x1801, 0xECC0, 0x0041, 0, 0, 0}, /* DSP 56301 Darla24 rev.1 */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0040) }, /* DSP 56301 Darla24 rev.0 */
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0041) }, /* DSP 56301 Darla24 rev.1 */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c
index 3d37bb4030ec..e8b476e07307 100644
--- a/sound/pci/echoaudio/echo3g.c
+++ b/sound/pci/echoaudio/echo3g.c
@@ -70,8 +70,8 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x3410, 0xECC0, 0x0100, 0, 0, 0}, /* Echo 3G */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0100) }, /* Echo 3G */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c
index 4f864ddc9530..b5f88922e19a 100644
--- a/sound/pci/echoaudio/gina20.c
+++ b/sound/pci/echoaudio/gina20.c
@@ -56,8 +56,8 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x1801, 0xECC0, 0x0020, 0, 0, 0}, /* DSP 56301 Gina20 rev.0 */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0020) }, /* DSP 56301 Gina20 rev.0 */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c
index eff69e83ca0a..fe0e510209ed 100644
--- a/sound/pci/echoaudio/gina24.c
+++ b/sound/pci/echoaudio/gina24.c
@@ -74,11 +74,11 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x1801, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56301 Gina24 rev.0 */
- {0x1057, 0x1801, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56301 Gina24 rev.1 */
- {0x1057, 0x3410, 0xECC0, 0x0050, 0, 0, 0}, /* DSP 56361 Gina24 rev.0 */
- {0x1057, 0x3410, 0xECC0, 0x0051, 0, 0, 0}, /* DSP 56361 Gina24 rev.1 */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0050) }, /* DSP 56301 Gina24 rev.0 */
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0051) }, /* DSP 56301 Gina24 rev.1 */
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0050) }, /* DSP 56361 Gina24 rev.0 */
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0051) }, /* DSP 56361 Gina24 rev.1 */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c
index a9f2efc58f6e..496cc5aa9516 100644
--- a/sound/pci/echoaudio/indigo.c
+++ b/sound/pci/echoaudio/indigo.c
@@ -57,8 +57,8 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x3410, 0xECC0, 0x0090, 0, 0, 0}, /* Indigo */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0090) }, /* Indigo */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c
index 14e9769ceba1..45ad92e8f531 100644
--- a/sound/pci/echoaudio/indigodj.c
+++ b/sound/pci/echoaudio/indigodj.c
@@ -57,8 +57,8 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x3410, 0xECC0, 0x00B0, 0, 0, 0}, /* Indigo DJ*/
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x00B0) }, /* Indigo DJ*/
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c
index a14a7dc8c87d..b1878ecb8375 100644
--- a/sound/pci/echoaudio/indigodjx.c
+++ b/sound/pci/echoaudio/indigodjx.c
@@ -57,8 +57,8 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x3410, 0xECC0, 0x00E0, 0, 0, 0}, /* Indigo DJx*/
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x00E0) }, /* Indigo DJx*/
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c
index 97e024450d19..2c6a6f74b0bd 100644
--- a/sound/pci/echoaudio/indigoio.c
+++ b/sound/pci/echoaudio/indigoio.c
@@ -58,8 +58,8 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x3410, 0xECC0, 0x00A0, 0, 0, 0}, /* Indigo IO*/
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x00A0) }, /* Indigo IO*/
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c
index a017c966b4dc..dfaa563317ad 100644
--- a/sound/pci/echoaudio/indigoiox.c
+++ b/sound/pci/echoaudio/indigoiox.c
@@ -58,8 +58,8 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x3410, 0xECC0, 0x00D0, 0, 0, 0}, /* Indigo IOx */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x00D0) }, /* Indigo IOx */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c
index 7e38bc9c025d..82c089f7b452 100644
--- a/sound/pci/echoaudio/layla20.c
+++ b/sound/pci/echoaudio/layla20.c
@@ -65,9 +65,9 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x1801, 0xECC0, 0x0030, 0, 0, 0}, /* DSP 56301 Layla20 rev.0 */
- {0x1057, 0x1801, 0xECC0, 0x0031, 0, 0, 0}, /* DSP 56301 Layla20 rev.1 */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0030) }, /* DSP 56301 Layla20 rev.0 */
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0031) }, /* DSP 56301 Layla20 rev.1 */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c
index 95c52210fb65..efd676467a37 100644
--- a/sound/pci/echoaudio/layla24.c
+++ b/sound/pci/echoaudio/layla24.c
@@ -76,8 +76,8 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x3410, 0xECC0, 0x0060, 0, 0, 0}, /* DSP 56361 Layla24 rev.0 */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0060) }, /* DSP 56361 Layla24 rev.0 */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c
index a2d4b0003b57..950aaec74a43 100644
--- a/sound/pci/echoaudio/mia.c
+++ b/sound/pci/echoaudio/mia.c
@@ -66,9 +66,9 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x3410, 0xECC0, 0x0080, 0, 0, 0}, /* DSP 56361 Mia rev.0 */
- {0x1057, 0x3410, 0xECC0, 0x0081, 0, 0, 0}, /* DSP 56361 Mia rev.1 */
- {0,}
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0080) }, /* DSP 56361 Mia rev.0 */
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0081) }, /* DSP 56361 Mia rev.1 */
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c
index 1b45a2b5066f..4f999324f388 100644
--- a/sound/pci/echoaudio/mona.c
+++ b/sound/pci/echoaudio/mona.c
@@ -81,13 +81,19 @@ static const struct firmware card_fw[] = {
};
static const struct pci_device_id snd_echo_ids[] = {
- {0x1057, 0x1801, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56301 Mona rev.0 */
- {0x1057, 0x1801, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56301 Mona rev.1 */
- {0x1057, 0x1801, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56301 Mona rev.2 */
- {0x1057, 0x3410, 0xECC0, 0x0070, 0, 0, 0}, /* DSP 56361 Mona rev.0 */
- {0x1057, 0x3410, 0xECC0, 0x0071, 0, 0, 0}, /* DSP 56361 Mona rev.1 */
- {0x1057, 0x3410, 0xECC0, 0x0072, 0, 0, 0}, /* DSP 56361 Mona rev.2 */
- {0,}
+ /* DSP 56301 Mona rev.0 */
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0070) },
+ /* DSP 56301 Mona rev.1 */
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0071) },
+ /* DSP 56301 Mona rev.2 */
+ { PCI_DEVICE_SUB(0x1057, 0x1801, 0xECC0, 0x0072) },
+ /* DSP 56361 Mona rev.0 */
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0070) },
+ /* DSP 56361 Mona rev.1 */
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0071) },
+ /* DSP 56361 Mona rev.2 */
+ { PCI_DEVICE_SUB(0x1057, 0x3410, 0xECC0, 0x0072) },
+ { }
};
static const struct snd_pcm_hardware pcm_hardware_skel = {
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index 548e7d049901..3b21bd2883b6 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -58,10 +58,10 @@ MODULE_PARM_DESC(subsystem, "Force card subsystem model.");
* Class 0401: 1102:0008 (rev 00) Subsystem: 1102:1001 -> Audigy2 Value Model:SB0400
*/
static const struct pci_device_id snd_emu10k1_ids[] = {
- { PCI_VDEVICE(CREATIVE, 0x0002), 0 }, /* EMU10K1 */
- { PCI_VDEVICE(CREATIVE, 0x0004), 1 }, /* Audigy */
- { PCI_VDEVICE(CREATIVE, 0x0008), 1 }, /* Audigy 2 Value SB0400 */
- { 0, }
+ { PCI_VDEVICE(CREATIVE, 0x0002), .driver_data = 0 }, /* EMU10K1 */
+ { PCI_VDEVICE(CREATIVE, 0x0004), .driver_data = 1 }, /* Audigy */
+ { PCI_VDEVICE(CREATIVE, 0x0008), .driver_data = 1 }, /* Audigy 2 Value SB0400 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_emu10k1_ids);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 1b207ca25814..ed4630c8342b 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -1518,8 +1518,8 @@ static int snd_emu10k1x_probe(struct pci_dev *pci,
// PCI IDs
static const struct pci_device_id snd_emu10k1x_ids[] = {
- { PCI_VDEVICE(CREATIVE, 0x0006), 0 }, /* Dell OEM version (EMU10K1) */
- { 0, }
+ { PCI_VDEVICE(CREATIVE, 0x0006) }, /* Dell OEM version (EMU10K1) */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_emu10k1x_ids);
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 9023f3444d20..b8749e0131ad 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1181,19 +1181,17 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
runtime->private_free = snd_emu10k1_pcm_free_substream;
runtime->hw = snd_emu10k1_playback;
err = snd_emu10k1_playback_set_constraints(runtime);
- if (err < 0) {
- kfree(epcm);
- return err;
- }
+ if (err < 0)
+ goto free_epcm;
+
if (emu->card_capabilities->emu_model)
sample_rate = emu->emu1010.word_clock;
else
sample_rate = 48000;
err = snd_pcm_hw_rule_noresample(runtime, sample_rate);
- if (err < 0) {
- kfree(epcm);
- return err;
- }
+ if (err < 0)
+ goto free_epcm;
+
mix = &emu->pcm_mixer[substream->number];
for (i = 0; i < 8; i++)
mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i;
@@ -1204,6 +1202,10 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
mix->epcm = epcm;
snd_emu10k1_pcm_mixer_notify(emu, substream->number, 1);
return 0;
+
+free_epcm:
+ kfree(epcm);
+ return err;
}
static int snd_emu10k1_playback_close(struct snd_pcm_substream *substream)
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index 657056a59175..0b9eb55a2121 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -426,14 +426,14 @@ static irqreturn_t snd_audiopci_interrupt(int irq, void *dev_id);
static const struct pci_device_id snd_audiopci_ids[] = {
#ifdef CHIP1370
- { PCI_VDEVICE(ENSONIQ, 0x5000), 0, }, /* ES1370 */
+ { PCI_VDEVICE(ENSONIQ, 0x5000) }, /* ES1370 */
#endif
#ifdef CHIP1371
- { PCI_VDEVICE(ENSONIQ, 0x1371), 0, }, /* ES1371 */
- { PCI_VDEVICE(ENSONIQ, 0x5880), 0, }, /* ES1373 - CT5880 */
- { PCI_VDEVICE(ECTIVA, 0x8938), 0, }, /* Ectiva EV1938 */
+ { PCI_VDEVICE(ENSONIQ, 0x1371) }, /* ES1371 */
+ { PCI_VDEVICE(ENSONIQ, 0x5880) }, /* ES1373 - CT5880 */
+ { PCI_VDEVICE(ECTIVA, 0x8938) }, /* Ectiva EV1938 */
#endif
- { 0, }
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_audiopci_ids);
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 280125eff362..217beb9376ac 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -222,8 +222,8 @@ struct es1938 {
static irqreturn_t snd_es1938_interrupt(int irq, void *dev_id);
static const struct pci_device_id snd_es1938_ids[] = {
- { PCI_VDEVICE(ESS, 0x1969), 0, }, /* Solo-1 */
- { 0, }
+ { PCI_VDEVICE(ESS, 0x1969) }, /* Solo-1 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_es1938_ids);
@@ -1655,6 +1655,8 @@ static int snd_es1938_mixer(struct es1938 *chip)
for (idx = 0; idx < ARRAY_SIZE(snd_es1938_controls); idx++) {
struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(&snd_es1938_controls[idx], chip);
+ if (!kctl)
+ return -ENOMEM;
switch (idx) {
case 0:
chip->master_volume = kctl;
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index b7282b3fa1b1..f04628c8cbb7 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -549,13 +549,26 @@ struct es1968 {
static irqreturn_t snd_es1968_interrupt(int irq, void *dev_id);
static const struct pci_device_id snd_es1968_ids[] = {
- /* Maestro 1 */
- { 0x1285, 0x0100, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO },
- /* Maestro 2 */
- { 0x125d, 0x1968, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO2 },
- /* Maestro 2E */
- { 0x125d, 0x1978, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, TYPE_MAESTRO2E },
- { 0, }
+ {
+ /* Maestro 1 */
+ PCI_DEVICE(0x1285, 0x0100),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ .driver_data = TYPE_MAESTRO,
+ }, {
+ /* Maestro 2 */
+ PCI_DEVICE(0x125d, 0x1968),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ .driver_data = TYPE_MAESTRO2,
+ }, {
+ /* Maestro 2E */
+ PCI_DEVICE(0x125d, 0x1978),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ .driver_data = TYPE_MAESTRO2E,
+ },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_es1968_ids);
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index 4ca992449ea3..9cc96b807dd7 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -240,9 +240,18 @@ static inline u16 fm801_ioread16(struct fm801 *chip, unsigned short offset)
}
static const struct pci_device_id snd_fm801_ids[] = {
- { 0x1319, 0x0801, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* FM801 */
- { 0x5213, 0x0510, PCI_ANY_ID, PCI_ANY_ID, PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0, }, /* Gallant Odyssey Sound 4 */
- { 0, }
+ {
+ /* FM801 */
+ PCI_DEVICE(0x1319, 0x0801),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ }, {
+ /* Gallant Odyssey Sound 4 */
+ PCI_DEVICE(0x5213, 0x0510),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_fm801_ids);
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 1191a2686dfd..d6abff2978f3 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -1891,6 +1891,8 @@ static int aureon_add_controls(struct snd_ice1712 *ice)
for (i = 0; i < ARRAY_SIZE(cs8415_controls); i++) {
struct snd_kcontrol *kctl;
kctl = snd_ctl_new1(&cs8415_controls[i], ice);
+ if (!kctl)
+ return -ENOMEM;
if (i > 1)
kctl->id.device = ice->pcm->device;
err = snd_ctl_add(ice->card, kctl);
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 1e39b985bef2..7d1a357ed90d 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -86,8 +86,8 @@ MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE.");
static const struct pci_device_id snd_ice1712_ids[] = {
- { PCI_VDEVICE(ICE, PCI_DEVICE_ID_ICE_1712), 0 }, /* ICE1712 */
- { 0, }
+ { PCI_VDEVICE(ICE, PCI_DEVICE_ID_ICE_1712) }, /* ICE1712 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_ice1712_ids);
@@ -2346,21 +2346,29 @@ int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice)
if (snd_BUG_ON(!ice->pcm_pro))
return -EIO;
kctl = snd_ctl_new1(&snd_ice1712_spdif_default, ice);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = ice->pcm_pro->device;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
return err;
kctl = snd_ctl_new1(&snd_ice1712_spdif_maskc, ice);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = ice->pcm_pro->device;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
return err;
kctl = snd_ctl_new1(&snd_ice1712_spdif_maskp, ice);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = ice->pcm_pro->device;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
return err;
kctl = snd_ctl_new1(&snd_ice1712_spdif_stream, ice);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = ice->pcm_pro->device;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 65bf48647d08..859bb87393b4 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -62,8 +62,8 @@ MODULE_PARM_DESC(model, "Use the given board model.");
/* Both VT1720 and VT1724 have the same PCI IDs */
static const struct pci_device_id snd_vt1724_ids[] = {
- { PCI_VDEVICE(ICE, PCI_DEVICE_ID_VT1724), 0 },
- { 0, }
+ { PCI_VDEVICE(ICE, PCI_DEVICE_ID_VT1724) },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_vt1724_ids);
@@ -730,13 +730,22 @@ static int snd_vt1724_pcm_hw_params(struct snd_pcm_substream *substream,
static int snd_vt1724_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ bool released = false;
int i;
- guard(mutex)(&ice->open_mutex);
- /* unmark surround channels */
- for (i = 0; i < 3; i++)
- if (ice->pcm_reserved[i] == substream)
+ scoped_guard(mutex, &ice->open_mutex) {
+ /* unmark surround channels */
+ for (i = 0; i < 3; i++) {
+ if (ice->pcm_reserved[i] != substream)
+ continue;
ice->pcm_reserved[i] = NULL;
+ released = true;
+ }
+ }
+
+ if (released && ice->pcm_ds)
+ wake_up(&ice->pcm_ds->open_wait);
+
return 0;
}
@@ -1364,7 +1373,7 @@ static int snd_vt1724_playback_indep_open(struct snd_pcm_substream *substream)
scoped_guard(mutex, &ice->open_mutex) {
/* already used by PDMA0? */
if (ice->pcm_reserved[substream->number])
- return -EBUSY; /* FIXME: should handle blocking mode properly */
+ return -EAGAIN;
}
runtime->private_data = (void *)&vt1724_playback_dma_regs[substream->number];
ice->playback_con_substream_ds[substream->number] = substream;
@@ -2379,16 +2388,22 @@ static int snd_vt1724_spdif_build_controls(struct snd_ice1712 *ice)
return err;
kctl = snd_ctl_new1(&snd_vt1724_spdif_default, ice);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = ice->pcm->device;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
return err;
kctl = snd_ctl_new1(&snd_vt1724_spdif_maskc, ice);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = ice->pcm->device;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
return err;
kctl = snd_ctl_new1(&snd_vt1724_spdif_maskp, ice);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = ice->pcm->device;
err = snd_ctl_add(ice->card, kctl);
if (err < 0)
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 3b53c5e63c29..e2ea9016a73e 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -384,30 +384,100 @@ struct intel8x0 {
};
static const struct pci_device_id snd_intel8x0_ids[] = {
- { PCI_VDEVICE(INTEL, 0x2415), DEVICE_INTEL }, /* 82801AA */
- { PCI_VDEVICE(INTEL, 0x2425), DEVICE_INTEL }, /* 82901AB */
- { PCI_VDEVICE(INTEL, 0x2445), DEVICE_INTEL }, /* 82801BA */
- { PCI_VDEVICE(INTEL, 0x2485), DEVICE_INTEL }, /* ICH3 */
- { PCI_VDEVICE(INTEL, 0x24c5), DEVICE_INTEL_ICH4 }, /* ICH4 */
- { PCI_VDEVICE(INTEL, 0x24d5), DEVICE_INTEL_ICH4 }, /* ICH5 */
- { PCI_VDEVICE(INTEL, 0x25a6), DEVICE_INTEL_ICH4 }, /* ESB */
- { PCI_VDEVICE(INTEL, 0x266e), DEVICE_INTEL_ICH4 }, /* ICH6 */
- { PCI_VDEVICE(INTEL, 0x27de), DEVICE_INTEL_ICH4 }, /* ICH7 */
- { PCI_VDEVICE(INTEL, 0x2698), DEVICE_INTEL_ICH4 }, /* ESB2 */
- { PCI_VDEVICE(INTEL, 0x7195), DEVICE_INTEL }, /* 440MX */
- { PCI_VDEVICE(SI, 0x7012), DEVICE_SIS }, /* SI7012 */
- { PCI_VDEVICE(NVIDIA, 0x01b1), DEVICE_NFORCE }, /* NFORCE */
- { PCI_VDEVICE(NVIDIA, 0x003a), DEVICE_NFORCE }, /* MCP04 */
- { PCI_VDEVICE(NVIDIA, 0x006a), DEVICE_NFORCE }, /* NFORCE2 */
- { PCI_VDEVICE(NVIDIA, 0x0059), DEVICE_NFORCE }, /* CK804 */
- { PCI_VDEVICE(NVIDIA, 0x008a), DEVICE_NFORCE }, /* CK8 */
- { PCI_VDEVICE(NVIDIA, 0x00da), DEVICE_NFORCE }, /* NFORCE3 */
- { PCI_VDEVICE(NVIDIA, 0x00ea), DEVICE_NFORCE }, /* CK8S */
- { PCI_VDEVICE(NVIDIA, 0x026b), DEVICE_NFORCE }, /* MCP51 */
- { PCI_VDEVICE(AMD, 0x746d), DEVICE_INTEL }, /* AMD8111 */
- { PCI_VDEVICE(AMD, 0x7445), DEVICE_INTEL }, /* AMD768 */
- { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */
- { 0, }
+ {
+ /* 82801AA */
+ PCI_VDEVICE(INTEL, 0x2415),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* 82901AB */
+ PCI_VDEVICE(INTEL, 0x2425),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* 82801BA */
+ PCI_VDEVICE(INTEL, 0x2445),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* ICH3 */
+ PCI_VDEVICE(INTEL, 0x2485),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* ICH4 */
+ PCI_VDEVICE(INTEL, 0x24c5),
+ .driver_data = DEVICE_INTEL_ICH4,
+ }, {
+ /* ICH5 */
+ PCI_VDEVICE(INTEL, 0x24d5),
+ .driver_data = DEVICE_INTEL_ICH4,
+ }, {
+ /* ESB */
+ PCI_VDEVICE(INTEL, 0x25a6),
+ .driver_data = DEVICE_INTEL_ICH4,
+ }, {
+ /* ICH6 */
+ PCI_VDEVICE(INTEL, 0x266e),
+ .driver_data = DEVICE_INTEL_ICH4,
+ }, {
+ /* ICH7 */
+ PCI_VDEVICE(INTEL, 0x27de),
+ .driver_data = DEVICE_INTEL_ICH4,
+ }, {
+ /* ESB2 */
+ PCI_VDEVICE(INTEL, 0x2698),
+ .driver_data = DEVICE_INTEL_ICH4,
+ }, {
+ /* 440MX */
+ PCI_VDEVICE(INTEL, 0x7195),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* SI7012 */
+ PCI_VDEVICE(SI, 0x7012),
+ .driver_data = DEVICE_SIS,
+ }, {
+ /* NFORCE */
+ PCI_VDEVICE(NVIDIA, 0x01b1),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* MCP04 */
+ PCI_VDEVICE(NVIDIA, 0x003a),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* NFORCE2 */
+ PCI_VDEVICE(NVIDIA, 0x006a),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* CK804 */
+ PCI_VDEVICE(NVIDIA, 0x0059),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* CK8 */
+ PCI_VDEVICE(NVIDIA, 0x008a),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* NFORCE3 */
+ PCI_VDEVICE(NVIDIA, 0x00da),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* CK8S */
+ PCI_VDEVICE(NVIDIA, 0x00ea),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* MCP51 */
+ PCI_VDEVICE(NVIDIA, 0x026b),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* AMD8111 */
+ PCI_VDEVICE(AMD, 0x746d),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* AMD768 */
+ PCI_VDEVICE(AMD, 0x7445),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* Ali5455 */
+ PCI_VDEVICE(AL, 0x5455),
+ .driver_data = DEVICE_ALI,
+ },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_intel8x0_ids);
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 84e1b7ea34e2..27dbf6125427 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -190,26 +190,78 @@ struct intel8x0m {
};
static const struct pci_device_id snd_intel8x0m_ids[] = {
- { PCI_VDEVICE(INTEL, 0x2416), DEVICE_INTEL }, /* 82801AA */
- { PCI_VDEVICE(INTEL, 0x2426), DEVICE_INTEL }, /* 82901AB */
- { PCI_VDEVICE(INTEL, 0x2446), DEVICE_INTEL }, /* 82801BA */
- { PCI_VDEVICE(INTEL, 0x2486), DEVICE_INTEL }, /* ICH3 */
- { PCI_VDEVICE(INTEL, 0x24c6), DEVICE_INTEL }, /* ICH4 */
- { PCI_VDEVICE(INTEL, 0x24d6), DEVICE_INTEL }, /* ICH5 */
- { PCI_VDEVICE(INTEL, 0x266d), DEVICE_INTEL }, /* ICH6 */
- { PCI_VDEVICE(INTEL, 0x27dd), DEVICE_INTEL }, /* ICH7 */
- { PCI_VDEVICE(INTEL, 0x7196), DEVICE_INTEL }, /* 440MX */
- { PCI_VDEVICE(AMD, 0x7446), DEVICE_INTEL }, /* AMD768 */
- { PCI_VDEVICE(SI, 0x7013), DEVICE_SIS }, /* SI7013 */
- { PCI_VDEVICE(NVIDIA, 0x01c1), DEVICE_NFORCE }, /* NFORCE */
- { PCI_VDEVICE(NVIDIA, 0x0069), DEVICE_NFORCE }, /* NFORCE2 */
- { PCI_VDEVICE(NVIDIA, 0x0089), DEVICE_NFORCE }, /* NFORCE2s */
- { PCI_VDEVICE(NVIDIA, 0x00d9), DEVICE_NFORCE }, /* NFORCE3 */
- { PCI_VDEVICE(AMD, 0x746e), DEVICE_INTEL }, /* AMD8111 */
+ {
+ /* 82801AA */
+ PCI_VDEVICE(INTEL, 0x2416),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* 82901AB */
+ PCI_VDEVICE(INTEL, 0x2426),
+ .driver_data = DEVICE_INTEL
+ }, {
+ /* 82801BA */
+ PCI_VDEVICE(INTEL, 0x2446),
+ .driver_data = DEVICE_INTEL
+ }, {
+ /* ICH3 */
+ PCI_VDEVICE(INTEL, 0x2486),
+ .driver_data = DEVICE_INTEL
+ }, {
+ /* ICH4 */
+ PCI_VDEVICE(INTEL, 0x24c6),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* ICH5 */
+ PCI_VDEVICE(INTEL, 0x24d6),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* ICH6 */
+ PCI_VDEVICE(INTEL, 0x266d),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* ICH7 */
+ PCI_VDEVICE(INTEL, 0x27dd),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* 440MX */
+ PCI_VDEVICE(INTEL, 0x7196),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* AMD768 */
+ PCI_VDEVICE(AMD, 0x7446),
+ .driver_data = DEVICE_INTEL,
+ }, {
+ /* SI7013 */
+ PCI_VDEVICE(SI, 0x7013),
+ .driver_data = DEVICE_SIS,
+ }, {
+ /* NFORCE */
+ PCI_VDEVICE(NVIDIA, 0x01c1),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* NFORCE2 */
+ PCI_VDEVICE(NVIDIA, 0x0069),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* NFORCE2s */
+ PCI_VDEVICE(NVIDIA, 0x0089),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* NFORCE3 */
+ PCI_VDEVICE(NVIDIA, 0x00d9),
+ .driver_data = DEVICE_NFORCE,
+ }, {
+ /* AMD8111 */
+ PCI_VDEVICE(AMD, 0x746e),
+ .driver_data = DEVICE_INTEL
#if 0
- { PCI_VDEVICE(AL, 0x5455), DEVICE_ALI }, /* Ali5455 */
+ }, {
+ /* Ali5455 */
+ PCI_VDEVICE(AL, 0x5455),
+ .driver_data = DEVICE_ALI,
#endif
- { 0, }
+ },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids);
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 3353980d5cd8..dd45ffa171e1 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -779,23 +779,40 @@ struct snd_m3 {
* pci ids
*/
static const struct pci_device_id snd_m3_ids[] = {
- {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1, PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
- {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO, PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
- {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2LE, PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
- {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2, PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
- {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3, PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
- {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_1, PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
- {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_HW, PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
- {PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_2, PCI_ANY_ID, PCI_ANY_ID,
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
- {0,},
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO_1),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ }, {
+ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_ALLEGRO),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ }, {
+ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2LE),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ }, {
+ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_CANYON3D_2),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ }, {
+ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ }, {
+ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_1),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ }, {
+ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_HW),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ }, {
+ PCI_DEVICE(PCI_VENDOR_ID_ESS, PCI_DEVICE_ID_ESS_MAESTRO3_2),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ },
+ { },
};
MODULE_DEVICE_TABLE(pci, snd_m3_ids);
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index a7760a23bfe9..f451554cff5f 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -48,8 +48,8 @@ MODULE_PARM_DESC(enable, "Enable Digigram " CARD_NAME " soundcard.");
*/
static const struct pci_device_id snd_mixart_ids[] = {
- { PCI_VDEVICE(MOTOROLA, 0x0003), 0, }, /* MC8240 */
- { 0, }
+ { PCI_VDEVICE(MOTOROLA, 0x0003) }, /* MC8240 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_mixart_ids);
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index da74b923bc88..a7da55d9c025 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -245,10 +245,10 @@ struct nm256 {
* PCI ids
*/
static const struct pci_device_id snd_nm256_ids[] = {
- {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO), 0},
- {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO), 0},
- {PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO), 0},
- {0,},
+ { PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256AV_AUDIO) },
+ { PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256ZX_AUDIO) },
+ { PCI_VDEVICE(NEOMAGIC, PCI_DEVICE_ID_NEOMAGIC_NM256XL_PLUS_AUDIO) },
+ { },
};
MODULE_DEVICE_TABLE(pci, snd_nm256_ids);
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index e6f869cf8ca2..a4212b2558ee 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -25,6 +25,11 @@
* GPIO 6 -> S/PDIF from optical (0) or coaxial (1) input
* GPIO 8 -> enable headphone amplifier
*
+ * eClaro model:
+ * GPIO 2 -> M0 of CS5361
+ * GPIO 3 -> M1 of CS5361
+ * GPIO 8 -> enable headphone amplifier
+ *
* CM9780:
*
* LINE_OUT -> input of ADC
@@ -51,6 +56,7 @@
#include "oxygen.h"
#include "xonar_dg.h"
#include "ak4396.h"
+#include "cs4362a.h"
#include "wm8785.h"
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
@@ -74,6 +80,7 @@ enum {
MODEL_MERIDIAN_2G,
MODEL_CLARO,
MODEL_CLARO_HALO,
+ MODEL_ECLARO,
MODEL_FANTASIA,
MODEL_SERENADE,
MODEL_2CH_OUTPUT,
@@ -113,6 +120,8 @@ static const struct pci_device_id oxygen_ids[] = {
{ OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CLARO },
/* HT-Omega Claro halo */
{ OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_CLARO_HALO },
+ /* HT-Omega eClaro */
+ { OXYGEN_PCI_SUBID(0x7284, 0x9783), .driver_data = MODEL_ECLARO },
{ }
};
MODULE_DEVICE_TABLE(pci, oxygen_ids);
@@ -130,27 +139,35 @@ MODULE_DEVICE_TABLE(pci, oxygen_ids);
#define GPIO_CLARO_DIG_COAX 0x0040
#define GPIO_CLARO_HP 0x0100
+#define GPIO_ECLARO_CS4362A_NRESET 0x0001 /* GPIO 0: CS4362A RESET# (active-low) */
+#define GPIO_ECLARO_FRONT_ENABLE 0x0020 /* GPIO 5: front output stage enable */
+
+/* CS4362A SPI: 3-byte frame [0x30, reg, value] on CE1, 1280 ns/bit clock */
+#define ECLARO_CS4362A_SPI_CONTROL \
+ (OXYGEN_SPI_TRIGGER | OXYGEN_SPI_DATA_LENGTH_3 | \
+ OXYGEN_SPI_CLOCK_1280 | (1 << OXYGEN_SPI_CODEC_SHIFT) | \
+ OXYGEN_SPI_CEN_LATCH_CLOCK_HI)
+
struct generic_data {
unsigned int dacs;
+ u8 spi_map[4];
+ u16 spi_prefix[4];
u8 ak4396_regs[4][5];
+ u8 cs4362a_regs[15];
u16 wm8785_regs[3];
};
static void ak4396_write(struct oxygen *chip, unsigned int codec,
u8 reg, u8 value)
{
- /* maps ALSA channel pair number to SPI output */
- static const u8 codec_spi_map[4] = {
- 0, 1, 2, 4
- };
struct generic_data *data = chip->model_data;
oxygen_write_spi(chip, OXYGEN_SPI_TRIGGER |
OXYGEN_SPI_DATA_LENGTH_2 |
OXYGEN_SPI_CLOCK_160 |
- (codec_spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) |
+ (data->spi_map[codec] << OXYGEN_SPI_CODEC_SHIFT) |
OXYGEN_SPI_CEN_LATCH_CLOCK_HI,
- AK4396_WRITE | (reg << 8) | value);
+ data->spi_prefix[codec] | (reg << 8) | value);
data->ak4396_regs[codec][reg] = value;
}
@@ -163,6 +180,51 @@ static void ak4396_write_cached(struct oxygen *chip, unsigned int codec,
ak4396_write(chip, codec, reg, value);
}
+static void eclaro_cs4362a_write(struct oxygen *chip, u8 reg, u8 value)
+{
+ struct generic_data *data = chip->model_data;
+ int err;
+
+ if (reg < ARRAY_SIZE(data->cs4362a_regs))
+ data->cs4362a_regs[reg] = value;
+
+ err = oxygen_write_spi(chip, ECLARO_CS4362A_SPI_CONTROL,
+ (0x30u << 16) | ((u32)reg << 8) | value);
+ if (err)
+ dev_err(chip->card->dev,
+ "CS4362A SPI timeout: reg=0x%02x val=0x%02x\n",
+ reg, value);
+}
+
+static void eclaro_cs4362a_write_cached(struct oxygen *chip, u8 reg, u8 value)
+{
+ struct generic_data *data = chip->model_data;
+
+ if (value != data->cs4362a_regs[reg])
+ eclaro_cs4362a_write(chip, reg, value);
+}
+
+static void eclaro_cs4362a_registers_init(struct oxygen *chip)
+{
+ struct generic_data *data = chip->model_data;
+
+ eclaro_cs4362a_write(chip, 1, CS4362A_CPEN | CS4362A_PDN);
+ eclaro_cs4362a_write(chip, 2, CS4362A_DIF_LJUST);
+ eclaro_cs4362a_write(chip, 3, CS4362A_SOFT_RAMP | CS4362A_AMUTE);
+ eclaro_cs4362a_write(chip, 4, data->cs4362a_regs[4]);
+ eclaro_cs4362a_write(chip, 5, 0);
+ eclaro_cs4362a_write(chip, 6, data->cs4362a_regs[6]);
+ eclaro_cs4362a_write(chip, 7, data->cs4362a_regs[7]);
+ eclaro_cs4362a_write(chip, 8, data->cs4362a_regs[8]);
+ eclaro_cs4362a_write(chip, 9, data->cs4362a_regs[9]);
+ eclaro_cs4362a_write(chip, 10, data->cs4362a_regs[10]);
+ eclaro_cs4362a_write(chip, 11, data->cs4362a_regs[11]);
+ eclaro_cs4362a_write(chip, 12, data->cs4362a_regs[12]);
+ eclaro_cs4362a_write(chip, 13, data->cs4362a_regs[13]);
+ eclaro_cs4362a_write(chip, 14, data->cs4362a_regs[14]);
+ eclaro_cs4362a_write(chip, 1, CS4362A_CPEN);
+}
+
static void wm8785_write(struct oxygen *chip, u8 reg, unsigned int value)
{
struct generic_data *data = chip->model_data;
@@ -199,8 +261,13 @@ static void ak4396_registers_init(struct oxygen *chip)
static void ak4396_init(struct oxygen *chip)
{
struct generic_data *data = chip->model_data;
+ static const u8 default_spi_map[4] = { 0, 1, 2, 4 };
+ unsigned int i;
data->dacs = chip->model.dac_channels_pcm / 2;
+ memcpy(data->spi_map, default_spi_map, sizeof(default_spi_map));
+ for (i = 0; i < 4; ++i)
+ data->spi_prefix[i] = AK4396_WRITE;
data->ak4396_regs[0][AK4396_CONTROL_2] =
AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
ak4396_registers_init(chip);
@@ -322,6 +389,102 @@ static void claro_resume(struct oxygen *chip)
claro_enable_hp(chip);
}
+#define GPIO_CS5361_M_MASK 0x000c
+#define GPIO_CS5361_M_SINGLE 0x0000
+#define GPIO_CS5361_M_DOUBLE 0x0004
+#define GPIO_CS5361_M_QUAD 0x0008
+
+static void cs5361_init(struct oxygen *chip)
+{
+ oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CS5361_M_MASK);
+ oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+ GPIO_CS5361_M_SINGLE, GPIO_CS5361_M_MASK);
+}
+
+static void set_cs5361_params(struct oxygen *chip,
+ struct snd_pcm_hw_params *params)
+{
+ unsigned int value;
+
+ if (params_rate(params) <= 54000)
+ value = GPIO_CS5361_M_SINGLE;
+ else if (params_rate(params) <= 108000)
+ value = GPIO_CS5361_M_DOUBLE;
+ else
+ value = GPIO_CS5361_M_QUAD;
+ oxygen_write16_masked(chip, OXYGEN_GPIO_DATA,
+ value, GPIO_CS5361_M_MASK);
+}
+
+static void eclaro_init(struct oxygen *chip)
+{
+ struct generic_data *data = chip->model_data;
+
+ oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, GPIO_CLARO_DIG_COAX);
+ oxygen_clear_bits16(chip, OXYGEN_GPIO_DATA, GPIO_CLARO_DIG_COAX);
+
+ /* Single AK4396VF on SPI CE0/CA=00 handles front L/R */
+ data->dacs = 1;
+ data->spi_map[0] = 0;
+ data->spi_prefix[0] = AK4396_WRITE;
+ data->ak4396_regs[0][AK4396_CONTROL_2] =
+ AK4396_SMUTE | AK4396_DEM_OFF | AK4396_DFS_NORMAL;
+
+ ak4396_write(chip, 0, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_ACKS);
+ ak4396_write(chip, 0, AK4396_CONTROL_2,
+ data->ak4396_regs[0][AK4396_CONTROL_2]);
+ ak4396_write(chip, 0, AK4396_CONTROL_3, AK4396_PCM);
+ ak4396_write(chip, 0, AK4396_LCH_ATT, chip->dac_volume[0] * 2);
+ ak4396_write(chip, 0, AK4396_RCH_ATT, chip->dac_volume[1] * 2);
+ ak4396_write(chip, 0, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_ACKS | AK4396_RSTN);
+
+ /* CS4362A (SPI CE1): surround/center-LFE/side L/R.
+ * GPIO 0 (RESET#, active-low) and GPIO 5 (front output enable) must
+ * be driven high. GPIOs 1 and 7 are outputs driven high.
+ */
+ oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL, 0x00a3);
+ oxygen_set_bits16(chip, OXYGEN_GPIO_DATA, 0x00a3);
+ usleep_range(1000, 2000);
+
+ data->cs4362a_regs[4] = CS4362A_RMP_DN | CS4362A_DEM_NONE;
+ data->cs4362a_regs[6] = CS4362A_FM_SINGLE |
+ CS4362A_ATAPI_B_R | CS4362A_ATAPI_A_L;
+ data->cs4362a_regs[7] = CS4362A_MUTE;
+ data->cs4362a_regs[9] = data->cs4362a_regs[6];
+ data->cs4362a_regs[12] = data->cs4362a_regs[6];
+
+ eclaro_cs4362a_registers_init(chip);
+
+ snd_component_add(chip->card, "AK4396");
+ snd_component_add(chip->card, "CS4362A");
+ cs5361_init(chip);
+ claro_enable_hp(chip);
+ snd_component_add(chip->card, "CS5361");
+}
+
+static void eclaro_resume(struct oxygen *chip)
+{
+ struct generic_data *data = chip->model_data;
+
+ oxygen_set_bits16(chip, OXYGEN_GPIO_CONTROL,
+ GPIO_ECLARO_CS4362A_NRESET | GPIO_ECLARO_FRONT_ENABLE);
+ oxygen_set_bits16(chip, OXYGEN_GPIO_DATA,
+ GPIO_ECLARO_CS4362A_NRESET | GPIO_ECLARO_FRONT_ENABLE);
+
+ /* AK4396 chip 0 */
+ ak4396_write(chip, 0, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_ACKS | AK4396_RSTN);
+ ak4396_write(chip, 0, AK4396_CONTROL_2,
+ data->ak4396_regs[0][AK4396_CONTROL_2]);
+ ak4396_write(chip, 0, AK4396_CONTROL_3, AK4396_PCM);
+ ak4396_write(chip, 0, AK4396_LCH_ATT, chip->dac_volume[0] * 2);
+ ak4396_write(chip, 0, AK4396_RCH_ATT, chip->dac_volume[1] * 2);
+
+ eclaro_cs4362a_registers_init(chip);
+
+ cs5361_init(chip);
+ claro_enable_hp(chip);
+}
+
static void stereo_resume(struct oxygen *chip)
{
ak4396_registers_init(chip);
@@ -355,6 +518,76 @@ static void set_ak4396_params(struct oxygen *chip,
}
}
+static void eclaro_set_dac_params(struct oxygen *chip,
+ struct snd_pcm_hw_params *params)
+{
+ struct generic_data *data = chip->model_data;
+ u8 ak_value, cs_fm;
+
+ ak_value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_DFS_MASK;
+ if (params_rate(params) <= 54000) {
+ ak_value |= AK4396_DFS_NORMAL;
+ cs_fm = CS4362A_FM_SINGLE;
+ } else if (params_rate(params) <= 108000) {
+ ak_value |= AK4396_DFS_DOUBLE;
+ cs_fm = CS4362A_FM_DOUBLE;
+ } else {
+ ak_value |= AK4396_DFS_QUAD;
+ cs_fm = CS4362A_FM_QUAD;
+ }
+
+ usleep_range(1000, 2000);
+
+ if (ak_value != data->ak4396_regs[0][AK4396_CONTROL_2]) {
+ ak4396_write(chip, 0, AK4396_CONTROL_1, AK4396_DIF_24_MSB | AK4396_ACKS);
+ ak4396_write(chip, 0, AK4396_CONTROL_2, ak_value);
+ ak4396_write(chip, 0, AK4396_CONTROL_1,
+ AK4396_DIF_24_MSB | AK4396_ACKS | AK4396_RSTN);
+ data->ak4396_regs[0][AK4396_CONTROL_2] = ak_value;
+ }
+
+ /* Update CS4362A FM mode for all three DAC pairs */
+ cs_fm |= data->cs4362a_regs[6] & ~CS4362A_FM_MASK;
+ eclaro_cs4362a_write_cached(chip, 6, cs_fm);
+ eclaro_cs4362a_write_cached(chip, 12, cs_fm);
+ cs_fm &= CS4362A_FM_MASK;
+ cs_fm |= data->cs4362a_regs[9] & ~CS4362A_FM_MASK;
+ eclaro_cs4362a_write_cached(chip, 9, cs_fm);
+}
+
+static void update_eclaro_volume(struct oxygen *chip)
+{
+ u8 mute = chip->dac_mute ? CS4362A_MUTE : 0;
+
+ ak4396_write_cached(chip, 0, AK4396_LCH_ATT, chip->dac_volume[0] * 2);
+ ak4396_write_cached(chip, 0, AK4396_RCH_ATT, chip->dac_volume[1] * 2);
+
+ /* CS4362A attenuation is inverse: 0 = 0 dB, 127 = max attenuation.
+ * Pair 1 (regs 7/8) is wired to the side outputs (ALSA ch 6/7);
+ * pair 3 (regs 13/14) is wired to the rear outputs (ALSA ch 2/3).
+ */
+ eclaro_cs4362a_write_cached(chip, 7, mute | (127 - chip->dac_volume[6]));
+ eclaro_cs4362a_write_cached(chip, 8, mute | (127 - chip->dac_volume[7]));
+ eclaro_cs4362a_write_cached(chip, 10, mute | (127 - chip->dac_volume[4]));
+ eclaro_cs4362a_write_cached(chip, 11, mute | (127 - chip->dac_volume[5]));
+ eclaro_cs4362a_write_cached(chip, 13, mute | (127 - chip->dac_volume[2]));
+ eclaro_cs4362a_write_cached(chip, 14, mute | (127 - chip->dac_volume[3]));
+}
+
+static void update_eclaro_mute(struct oxygen *chip)
+{
+ struct generic_data *data = chip->model_data;
+ u8 value;
+
+ value = data->ak4396_regs[0][AK4396_CONTROL_2] & ~AK4396_SMUTE;
+ if (chip->dac_mute)
+ value |= AK4396_SMUTE;
+ ak4396_write_cached(chip, 0, AK4396_CONTROL_2, value);
+
+ /* Re-apply volume+mute to CS4362A so the mute bit is set correctly */
+ update_eclaro_volume(chip);
+}
+
static void update_ak4396_volume(struct oxygen *chip)
{
struct generic_data *data = chip->model_data;
@@ -702,6 +935,8 @@ static void dump_oxygen_registers(struct oxygen *chip,
}
static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
+/* CS4362A: 0.5 dB/step, raw=127 -> 0 dB, raw=0 -> -63.5 dB */
+static const DECLARE_TLV_DB_SCALE(eclaro_db_scale, -6350, 50, 0);
static const struct oxygen_model model_generic = {
.shortname = "C-Media CMI8788",
@@ -745,6 +980,7 @@ static int get_oxygen_model(struct oxygen *chip,
[MODEL_MERIDIAN_2G] = "AuzenTech X-Meridian 2G",
[MODEL_CLARO] = "HT-Omega Claro",
[MODEL_CLARO_HALO] = "HT-Omega Claro halo",
+ [MODEL_ECLARO] = "HT-Omega eClaro",
[MODEL_FANTASIA] = "TempoTec HiFier Fantasia",
[MODEL_SERENADE] = "TempoTec HiFier Serenade",
[MODEL_HG2PCI] = "CMI8787-HG2PCI",
@@ -788,6 +1024,28 @@ static int get_oxygen_model(struct oxygen *chip,
CAPTURE_0_FROM_I2S_2 |
CAPTURE_1_FROM_SPDIF;
break;
+ case MODEL_ECLARO:
+ chip->model.init = eclaro_init;
+ chip->model.mixer_init = generic_mixer_init;
+ chip->model.cleanup = claro_cleanup;
+ chip->model.suspend = claro_suspend;
+ chip->model.resume = eclaro_resume;
+ chip->model.set_dac_params = eclaro_set_dac_params;
+ chip->model.set_adc_params = set_cs5361_params;
+ chip->model.update_dac_volume = update_eclaro_volume;
+ chip->model.update_dac_mute = update_eclaro_mute;
+ chip->model.dump_registers = dump_ak4396_registers;
+ chip->model.device_config = PLAYBACK_0_TO_I2S |
+ PLAYBACK_1_TO_SPDIF |
+ CAPTURE_0_FROM_I2S_2 |
+ CAPTURE_1_FROM_SPDIF;
+ chip->model.function_flags = OXYGEN_FUNCTION_SPI |
+ OXYGEN_FUNCTION_ENABLE_SPI_4_5;
+ chip->model.dac_mclks = OXYGEN_MCLKS(256, 128, 128);
+ chip->model.dac_volume_min = 0;
+ chip->model.dac_volume_max = 127;
+ chip->model.dac_tlv = eclaro_db_scale;
+ break;
case MODEL_FANTASIA:
case MODEL_SERENADE:
case MODEL_2CH_OUTPUT:
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index e7d63972c2ca..25a640304430 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -89,41 +89,41 @@ enum {
};
static const struct pci_device_id pcxhr_ids[] = {
- { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, },
- { 0x10b5, 0x9056, 0x1369, 0xb021, 0, 0, PCI_ID_VX882E, },
- { 0x10b5, 0x9056, 0x1369, 0xb121, 0, 0, PCI_ID_PCX882E, },
- { 0x10b5, 0x9056, 0x1369, 0xb221, 0, 0, PCI_ID_VX881E, },
- { 0x10b5, 0x9056, 0x1369, 0xb321, 0, 0, PCI_ID_PCX881E, },
- { 0x10b5, 0x9656, 0x1369, 0xb401, 0, 0, PCI_ID_VX1222HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb601, 0, 0, PCI_ID_VX1221HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, },
- { 0x10b5, 0x9056, 0x1369, 0xb421, 0, 0, PCI_ID_VX1222E, },
- { 0x10b5, 0x9056, 0x1369, 0xb521, 0, 0, PCI_ID_PCX1222E, },
- { 0x10b5, 0x9056, 0x1369, 0xb621, 0, 0, PCI_ID_VX1221E, },
- { 0x10b5, 0x9056, 0x1369, 0xb721, 0, 0, PCI_ID_PCX1221E, },
- { 0x10b5, 0x9056, 0x1369, 0xba01, 0, 0, PCI_ID_VX222HR, },
- { 0x10b5, 0x9056, 0x1369, 0xba21, 0, 0, PCI_ID_VX222E, },
- { 0x10b5, 0x9056, 0x1369, 0xbd01, 0, 0, PCI_ID_PCX22HR, },
- { 0x10b5, 0x9056, 0x1369, 0xbd21, 0, 0, PCI_ID_PCX22E, },
- { 0x10b5, 0x9056, 0x1369, 0xbc01, 0, 0, PCI_ID_VX222HRMIC, },
- { 0x10b5, 0x9056, 0x1369, 0xbc21, 0, 0, PCI_ID_VX222E_MIC, },
- { 0x10b5, 0x9056, 0x1369, 0xbb01, 0, 0, PCI_ID_PCX924HR, },
- { 0x10b5, 0x9056, 0x1369, 0xbb21, 0, 0, PCI_ID_PCX924E, },
- { 0x10b5, 0x9056, 0x1369, 0xbf01, 0, 0, PCI_ID_PCX924HRMIC, },
- { 0x10b5, 0x9056, 0x1369, 0xbf21, 0, 0, PCI_ID_PCX924E_MIC, },
- { 0x10b5, 0x9656, 0x1369, 0xd001, 0, 0, PCI_ID_VX442HR, },
- { 0x10b5, 0x9656, 0x1369, 0xd101, 0, 0, PCI_ID_PCX442HR, },
- { 0x10b5, 0x9056, 0x1369, 0xd021, 0, 0, PCI_ID_VX442E, },
- { 0x10b5, 0x9056, 0x1369, 0xd121, 0, 0, PCI_ID_PCX442E, },
- { 0x10b5, 0x9656, 0x1369, 0xd201, 0, 0, PCI_ID_VX822HR, },
- { 0x10b5, 0x9656, 0x1369, 0xd301, 0, 0, PCI_ID_PCX822HR, },
- { 0x10b5, 0x9056, 0x1369, 0xd221, 0, 0, PCI_ID_VX822E, },
- { 0x10b5, 0x9056, 0x1369, 0xd321, 0, 0, PCI_ID_PCX822E, },
- { 0, }
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb001), .driver_data = PCI_ID_VX882HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb101), .driver_data = PCI_ID_PCX882HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb201), .driver_data = PCI_ID_VX881HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb301), .driver_data = PCI_ID_PCX881HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb021), .driver_data = PCI_ID_VX882E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb121), .driver_data = PCI_ID_PCX882E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb221), .driver_data = PCI_ID_VX881E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb321), .driver_data = PCI_ID_PCX881E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb401), .driver_data = PCI_ID_VX1222HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb501), .driver_data = PCI_ID_PCX1222HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb601), .driver_data = PCI_ID_VX1221HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xb701), .driver_data = PCI_ID_PCX1221HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb421), .driver_data = PCI_ID_VX1222E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb521), .driver_data = PCI_ID_PCX1222E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb621), .driver_data = PCI_ID_VX1221E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xb721), .driver_data = PCI_ID_PCX1221E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xba01), .driver_data = PCI_ID_VX222HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xba21), .driver_data = PCI_ID_VX222E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbd01), .driver_data = PCI_ID_PCX22HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbd21), .driver_data = PCI_ID_PCX22E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbc01), .driver_data = PCI_ID_VX222HRMIC },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbc21), .driver_data = PCI_ID_VX222E_MIC },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbb01), .driver_data = PCI_ID_PCX924HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbb21), .driver_data = PCI_ID_PCX924E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbf01), .driver_data = PCI_ID_PCX924HRMIC },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xbf21), .driver_data = PCI_ID_PCX924E_MIC },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xd001), .driver_data = PCI_ID_VX442HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xd101), .driver_data = PCI_ID_PCX442HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xd021), .driver_data = PCI_ID_VX442E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xd121), .driver_data = PCI_ID_PCX442E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xd201), .driver_data = PCI_ID_VX822HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9656, 0x1369, 0xd301), .driver_data = PCI_ID_PCX822HR },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xd221), .driver_data = PCI_ID_VX822E },
+ { PCI_DEVICE_SUB(0x10b5, 0x9056, 0x1369, 0xd321), .driver_data = PCI_ID_PCX822E },
+ { }
};
MODULE_DEVICE_TABLE(pci, pcxhr_ids);
@@ -180,16 +180,18 @@ static const struct board_parameters pcxhr_board_params[] = {
(x->fw_file_set == 0) || \
(x->fw_file_set == 2))
-static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
- unsigned int* realfreq)
+int pcxhr_pll_freq_register(unsigned int freq, unsigned int max_freq,
+ unsigned int *pllreg, unsigned int *realfreq)
{
unsigned int reg;
- if (freq < 6900 || freq > 110000)
+ if (freq < 6900 || freq > max_freq)
return -EINVAL;
reg = (28224000 * 2) / freq;
reg = (reg - 1) / 2;
- if (reg < 0x200)
+ if (reg < 0x100)
+ *pllreg = reg + 0xc00;
+ else if (reg < 0x200)
*pllreg = reg + 0x800;
else if (reg < 0x400)
*pllreg = reg & 0x1ff;
@@ -260,7 +262,8 @@ static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
default :
val = PCXHR_FREQ_PLL;
/* get the value for the pll register */
- err = pcxhr_pll_freq_register(rate, &pllreg, &realfreq);
+ err = pcxhr_pll_freq_register(rate, 110000, &pllreg,
+ &realfreq);
if (err)
return err;
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h
index 1b85200d00dd..011227b1fe79 100644
--- a/sound/pci/pcxhr/pcxhr.h
+++ b/sound/pci/pcxhr/pcxhr.h
@@ -190,6 +190,8 @@ struct pcxhr_hostport
};
/* exported */
+int pcxhr_pll_freq_register(unsigned int freq, unsigned int max_freq,
+ unsigned int *pllreg, unsigned int *realfreq);
int pcxhr_create_pcm(struct snd_pcxhr *chip);
int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate);
int pcxhr_get_external_clock(struct pcxhr_mgr *mgr,
diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c
index 80d22e22ea30..76beb443d983 100644
--- a/sound/pci/pcxhr/pcxhr_mix22.c
+++ b/sound/pci/pcxhr/pcxhr_mix22.c
@@ -305,36 +305,6 @@ int hr222_sub_init(struct pcxhr_mgr *mgr)
}
-/* calc PLL register */
-/* TODO : there is a very similar fct in pcxhr.c */
-static int hr222_pll_freq_register(unsigned int freq,
- unsigned int *pllreg,
- unsigned int *realfreq)
-{
- unsigned int reg;
-
- if (freq < 6900 || freq > 219000)
- return -EINVAL;
- reg = (28224000 * 2) / freq;
- reg = (reg - 1) / 2;
- if (reg < 0x100)
- *pllreg = reg + 0xC00;
- else if (reg < 0x200)
- *pllreg = reg + 0x800;
- else if (reg < 0x400)
- *pllreg = reg & 0x1ff;
- else if (reg < 0x800) {
- *pllreg = ((reg >> 1) & 0x1ff) + 0x200;
- reg &= ~1;
- } else {
- *pllreg = ((reg >> 2) & 0x1ff) + 0x400;
- reg &= ~3;
- }
- if (realfreq)
- *realfreq = (28224000 / (reg + 1));
- return 0;
-}
-
int hr222_sub_set_clock(struct pcxhr_mgr *mgr,
unsigned int rate,
int *changed)
@@ -345,7 +315,8 @@ int hr222_sub_set_clock(struct pcxhr_mgr *mgr,
switch (mgr->use_clock_type) {
case HR22_CLOCK_TYPE_INTERNAL:
- err = hr222_pll_freq_register(rate, &pllreg, &realfreq);
+ err = pcxhr_pll_freq_register(rate, 219000,
+ &pllreg, &realfreq);
if (err)
return err;
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index ca9bbf554650..454a30a2c07e 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -211,10 +211,10 @@ struct rme32 {
};
static const struct pci_device_id snd_rme32_ids[] = {
- {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32), 0,},
- {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8), 0,},
- {PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO), 0,},
- {0,}
+ { PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32) },
+ { PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_8) },
+ { PCI_VDEVICE(XILINX_RME, PCI_DEVICE_ID_RME_DIGI32_PRO) },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_rme32_ids);
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 58b8ebf1a24e..892fcc598557 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -242,11 +242,11 @@ struct rme96 {
};
static const struct pci_device_id snd_rme96_ids[] = {
- { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96), 0, },
- { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8), 0, },
- { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO), 0, },
- { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST), 0, },
- { 0, }
+ { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96) },
+ { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8) },
+ { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PRO) },
+ { PCI_VDEVICE(XILINX, PCI_DEVICE_ID_RME_DIGI96_8_PAD_OR_PST) },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_rme96_ids);
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index a4c72799d034..a885d544acd6 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -227,8 +227,8 @@ struct sonicvibes {
};
static const struct pci_device_id snd_sonic_ids[] = {
- { PCI_VDEVICE(S3, 0xca00), 0, },
- { 0, }
+ { PCI_VDEVICE(S3, 0xca00) },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_sonic_ids);
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index ddb6ccc72e44..8dcbd022ca1f 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -36,12 +36,16 @@ module_param_array(wavetable_size, int, NULL, 0444);
MODULE_PARM_DESC(wavetable_size, "Maximum memory size in kB for wavetable synth.");
static const struct pci_device_id snd_trident_ids[] = {
- {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
- PCI_CLASS_MULTIMEDIA_AUDIO << 8, 0xffff00, 0},
- {PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
- 0, 0, 0},
- {PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018), 0, 0, 0},
- { 0, }
+ {
+ PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX),
+ .class = PCI_CLASS_MULTIMEDIA_AUDIO << 8,
+ .class_mask = 0xffff00,
+ }, {
+ PCI_DEVICE(PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX),
+ }, {
+ PCI_DEVICE(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018)
+ },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_trident_ids);
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index 41b322fbd9ef..24ee1302f27d 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -389,10 +389,10 @@ struct via82xx {
static const struct pci_device_id snd_via82xx_ids[] = {
/* 0x1106, 0x3058 */
- { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686_5), TYPE_CARD_VIA686, }, /* 686A */
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_82C686_5), .driver_data = TYPE_CARD_VIA686 }, /* 686A */
/* 0x1106, 0x3059 */
- { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_5), TYPE_CARD_VIA8233, }, /* VT8233 */
- { 0, }
+ { PCI_VDEVICE(VIA, PCI_DEVICE_ID_VIA_8233_5), .driver_data = TYPE_CARD_VIA8233 }, /* VT8233 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_via82xx_ids);
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index a6f176d612e3..9b84d3fb9eaf 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -246,8 +246,8 @@ struct via82xx_modem {
};
static const struct pci_device_id snd_via82xx_modem_ids[] = {
- { PCI_VDEVICE(VIA, 0x3068), TYPE_CARD_VIA82XX_MODEM, },
- { 0, }
+ { PCI_VDEVICE(VIA, 0x3068), .driver_data = TYPE_CARD_VIA82XX_MODEM },
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_via82xx_modem_ids);
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 693a4e471cf7..0b89ca859e66 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -47,9 +47,9 @@ enum {
};
static const struct pci_device_id snd_vx222_ids[] = {
- { 0x10b5, 0x9050, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_OLD, }, /* PLX */
- { 0x10b5, 0x9030, 0x1369, PCI_ANY_ID, 0, 0, VX_PCI_VX222_NEW, }, /* PLX */
- { 0, }
+ { PCI_DEVICE_SUB(0x10b5, 0x9050, 0x1369, PCI_ANY_ID), .driver_data = VX_PCI_VX222_OLD }, /* PLX */
+ { PCI_DEVICE_SUB(0x10b5, 0x9030, 0x1369, PCI_ANY_ID), .driver_data = VX_PCI_VX222_NEW }, /* PLX */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_vx222_ids);
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 764ca59e98d1..d3fb047c9a45 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -46,13 +46,13 @@ module_param_array(rear_switch, bool, NULL, 0444);
MODULE_PARM_DESC(rear_switch, "Enable shared rear/line-in switch");
static const struct pci_device_id snd_ymfpci_ids[] = {
- { PCI_VDEVICE(YAMAHA, 0x0004), 0, }, /* YMF724 */
- { PCI_VDEVICE(YAMAHA, 0x000d), 0, }, /* YMF724F */
- { PCI_VDEVICE(YAMAHA, 0x000a), 0, }, /* YMF740 */
- { PCI_VDEVICE(YAMAHA, 0x000c), 0, }, /* YMF740C */
- { PCI_VDEVICE(YAMAHA, 0x0010), 0, }, /* YMF744 */
- { PCI_VDEVICE(YAMAHA, 0x0012), 0, }, /* YMF754 */
- { 0, }
+ { PCI_VDEVICE(YAMAHA, 0x0004) }, /* YMF724 */
+ { PCI_VDEVICE(YAMAHA, 0x000d) }, /* YMF724F */
+ { PCI_VDEVICE(YAMAHA, 0x000a) }, /* YMF740 */
+ { PCI_VDEVICE(YAMAHA, 0x000c) }, /* YMF740C */
+ { PCI_VDEVICE(YAMAHA, 0x0010) }, /* YMF744 */
+ { PCI_VDEVICE(YAMAHA, 0x0012) }, /* YMF754 */
+ { }
};
MODULE_DEVICE_TABLE(pci, snd_ymfpci_ids);
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index b9a09568afc9..2ccb976e68e0 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -1781,16 +1781,22 @@ int snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
if (snd_BUG_ON(!chip->pcm_spdif))
return -ENXIO;
kctl = snd_ctl_new1(&snd_ymfpci_spdif_default, chip);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = chip->pcm_spdif->device;
err = snd_ctl_add(chip->card, kctl);
if (err < 0)
return err;
kctl = snd_ctl_new1(&snd_ymfpci_spdif_mask, chip);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = chip->pcm_spdif->device;
err = snd_ctl_add(chip->card, kctl);
if (err < 0)
return err;
kctl = snd_ctl_new1(&snd_ymfpci_spdif_stream, chip);
+ if (!kctl)
+ return -ENOMEM;
kctl->id.device = chip->pcm_spdif->device;
err = snd_ctl_add(chip->card, kctl);
if (err < 0)
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index 9438c3a68ee9..8196e1bf0416 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -564,10 +564,9 @@ static int snd_aica_probe(struct platform_device *devptr)
return -ENOMEM;
err = snd_card_new(&devptr->dev, index, SND_AICA_DRIVER,
THIS_MODULE, 0, &dreamcastcard->card);
- if (unlikely(err < 0)) {
- kfree(dreamcastcard);
- return err;
- }
+ if (unlikely(err < 0))
+ goto free_card;
+
strscpy(dreamcastcard->card->driver, "snd_aica");
strscpy(dreamcastcard->card->shortname, SND_AICA_DRIVER);
strscpy(dreamcastcard->card->longname,
@@ -593,6 +592,7 @@ static int snd_aica_probe(struct platform_device *devptr)
return 0;
freedreamcast:
snd_card_free(dreamcastcard->card);
+free_card:
kfree(dreamcastcard);
return err;
}
diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig
index 53139766fafb..9f4f1f4ac3f8 100644
--- a/sound/soc/amd/Kconfig
+++ b/sound/soc/amd/Kconfig
@@ -174,5 +174,15 @@ config SND_SOC_AMD_PS_MACH
Say m if you have such a device.
If unsure select "N".
+config SND_SOC_AMD_ACP7X
+ tristate "AMD Audio Coprocessor-v7.x support"
+ depends on X86 && PCI && ACPI
+ help
+ This option enables Audio Coprocessor i.e ACP7.x
+ variants support(ACP7.D/7.E/7.F). By enabling this flag build
+ will be triggered for ACP PCI driver.
+ Say m if you have such a device.
+ If unsure select "N".
+
endif
endmenu
diff --git a/sound/soc/amd/Makefile b/sound/soc/amd/Makefile
index 23b25ff0d800..ef2b36d47705 100644
--- a/sound/soc/amd/Makefile
+++ b/sound/soc/amd/Makefile
@@ -18,3 +18,4 @@ obj-$(CONFIG_SND_SOC_AMD_ACP6x) += yc/
obj-$(CONFIG_SND_AMD_ACP_CONFIG) += acp/
obj-$(CONFIG_SND_AMD_ACP_CONFIG) += snd-acp-config.o
obj-$(CONFIG_SND_SOC_AMD_PS) += ps/
+obj-$(CONFIG_SND_SOC_AMD_ACP7X) += acp7x/
diff --git a/sound/soc/amd/acp-config.c b/sound/soc/amd/acp-config.c
index 1604ed679224..0d977f4f758d 100644
--- a/sound/soc/amd/acp-config.c
+++ b/sound/soc/amd/acp-config.c
@@ -30,6 +30,20 @@ static const struct dmi_system_id acp70_acpi_flag_override_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "HN7306EA"),
},
},
+ {
+ /* ASUS Zenbook S16 UM5606GA (Strix Point, ACP 7.0) */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Zenbook S16 UM5606GA"),
+ },
+ },
+ {
+ /* Lenovo Yoga Pro 7 15ASH11 (Strix Halo, ACP 7.0) */
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "LENOVO"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "83W5"),
+ },
+ },
{}
};
diff --git a/sound/soc/amd/acp/acp-sdw-legacy-mach.c b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
index 0f21e5f64531..e8b6819cc4b4 100644
--- a/sound/soc/amd/acp/acp-sdw-legacy-mach.c
+++ b/sound/soc/amd/acp/acp-sdw-legacy-mach.c
@@ -260,9 +260,9 @@ static int create_sdw_dailink(struct snd_soc_card *card,
cpus->dai_name = devm_kasprintf(dev, GFP_KERNEL,
"SDW%d Pin%d",
link_num, cpu_pin_id);
- dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name);
if (!cpus->dai_name)
return -ENOMEM;
+ dev_dbg(dev, "cpu->dai_name:%s\n", cpus->dai_name);
codec_maps[j].cpu = 0;
codec_maps[j].codec = j;
@@ -303,13 +303,14 @@ static int create_sdw_dailink(struct snd_soc_card *card,
static int create_sdw_dailinks(struct snd_soc_card *card,
struct snd_soc_dai_link **dai_links, int *be_id,
- struct asoc_sdw_dailink *soc_dais,
+ struct asoc_sdw_dailink *soc_dais, int num_dais,
struct snd_soc_codec_conf **codec_conf)
{
struct device *dev = card->dev;
struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
struct amd_mc_ctx *amd_ctx = (struct amd_mc_ctx *)ctx->private;
struct snd_soc_dai_link_component *sdw_platform_component;
+ int i;
int ret;
sdw_platform_component = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link_component),
@@ -329,7 +330,7 @@ static int create_sdw_dailinks(struct snd_soc_card *card,
}
/* generate DAI links by each sdw link */
- while (soc_dais->initialised) {
+ for (i = 0; i < num_dais && soc_dais->initialised; i++) {
int current_be_id = 0;
ret = create_sdw_dailink(card, soc_dais, dai_links,
@@ -463,7 +464,7 @@ static int soc_card_dai_links_create(struct snd_soc_card *card)
/* SDW */
if (sdw_be_num) {
ret = create_sdw_dailinks(card, &dai_links, &be_id,
- soc_dais, &codec_conf);
+ soc_dais, num_ends, &codec_conf);
if (ret)
return ret;
}
diff --git a/sound/soc/amd/acp/acp-sdw-sof-mach.c b/sound/soc/amd/acp/acp-sdw-sof-mach.c
index a0fd8a6f9970..a423853f3a97 100644
--- a/sound/soc/amd/acp/acp-sdw-sof-mach.c
+++ b/sound/soc/amd/acp/acp-sdw-sof-mach.c
@@ -220,13 +220,14 @@ static int create_sdw_dailink(struct snd_soc_card *card,
static int create_sdw_dailinks(struct snd_soc_card *card,
struct snd_soc_dai_link **dai_links, int *be_id,
- struct asoc_sdw_dailink *sof_dais,
+ struct asoc_sdw_dailink *sof_dais, int num_dais,
struct snd_soc_codec_conf **codec_conf)
{
+ int i;
int ret;
/* generate DAI links by each sdw link */
- while (sof_dais->initialised) {
+ for (i = 0; i < num_dais && sof_dais->initialised; i++) {
int current_be_id = 0;
ret = create_sdw_dailink(card, sof_dais, dai_links,
@@ -334,7 +335,7 @@ static int sof_card_dai_links_create(struct snd_soc_card *card)
/* SDW */
if (sdw_be_num) {
ret = create_sdw_dailinks(card, &dai_links, &be_id,
- sof_dais, &codec_conf);
+ sof_dais, num_ends, &codec_conf);
if (ret)
return ret;
}
diff --git a/sound/soc/amd/acp/amd-acp70-acpi-match.c b/sound/soc/amd/acp/amd-acp70-acpi-match.c
index 1ae43df5da6c..18f2918d4ada 100644
--- a/sound/soc/amd/acp/amd-acp70-acpi-match.c
+++ b/sound/soc/amd/acp/amd-acp70-acpi-match.c
@@ -619,6 +619,45 @@ static const struct snd_soc_acpi_link_adr acp70_rt721_l1u0_tas2783x2_l1u8b[] = {
{}
};
+static const struct snd_soc_acpi_endpoint rt721_endpoints[] = {
+ { /* Jack Playback/Capture Endpoint (AIF1) */
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Speaker Amplifier Endpoint (AIF2, internal amp) */
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* DMIC Capture Endpoint (AIF3) */
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
+static const struct snd_soc_acpi_adr_device rt721_1_single_adr[] = {
+ {
+ .adr = 0x000130025D072101ull,
+ .num_endpoints = ARRAY_SIZE(rt721_endpoints),
+ .endpoints = rt721_endpoints,
+ .name_prefix = "rt721"
+ }
+};
+
+static const struct snd_soc_acpi_link_adr acp70_rt721_only[] = {
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt721_1_single_adr),
+ .adr_d = rt721_1_single_adr,
+ },
+ {}
+};
+
struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[] = {
{
.link_mask = BIT(0) | BIT(1),
@@ -711,6 +750,11 @@ struct snd_soc_acpi_mach snd_soc_acpi_amd_acp70_sdw_machines[] = {
.links = acp70_rt721_l1u0_tas2783x2_l1u8b,
.drv_name = "amd_sdw",
},
+ {
+ .link_mask = BIT(1),
+ .links = acp70_rt721_only,
+ .drv_name = "amd_sdw",
+ },
{},
};
EXPORT_SYMBOL(snd_soc_acpi_amd_acp70_sdw_machines);
diff --git a/sound/soc/amd/acp7x/Makefile b/sound/soc/amd/acp7x/Makefile
new file mode 100644
index 000000000000..9426e3b47c08
--- /dev/null
+++ b/sound/soc/amd/acp7x/Makefile
@@ -0,0 +1,5 @@
+# SPDX-License-Identifier: GPL-2.0-only
+# ACP7.x variants platform Support
+snd-pci-acp7x-y := pci-acp7x.o acp7x-common.o
+
+obj-$(CONFIG_SND_SOC_AMD_ACP7X) += snd-pci-acp7x.o
diff --git a/sound/soc/amd/acp7x/acp7x-common.c b/sound/soc/amd/acp7x/acp7x-common.c
new file mode 100644
index 000000000000..df94864a1693
--- /dev/null
+++ b/sound/soc/amd/acp7x/acp7x-common.c
@@ -0,0 +1,125 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AMD ACP PCI driver callback routines for ACP7.x
+ * platforms.
+ *
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ */
+
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/types.h>
+
+#include "acp7x.h"
+
+static int acp7x_power_on(void __iomem *acp_base)
+{
+ u32 val = 0;
+
+ val = readl(acp_base + ACP_PGFSM_STATUS);
+ if (!(val & ACP7X_PGFSM_STATUS_MASK))
+ return 0;
+
+ writel(ACP7X_PGFSM_CNTL_POWER_ON_MASK, acp_base + ACP_PGFSM_CONTROL);
+ val = readl(acp_base + ACP_PGFSM_CONTROL);
+ return readl_poll_timeout(acp_base + ACP_PGFSM_STATUS, val,
+ ((val & ACP7X_PGFSM_STATUS_MASK) == 0), DELAY_US, ACP7X_TIMEOUT);
+}
+
+static int acp7x_reset(void __iomem *acp_base)
+{
+ u32 val;
+ int ret;
+
+ writel(1, acp_base + ACP_SOFT_RESET);
+ ret = readl_poll_timeout(acp_base + ACP_SOFT_RESET, val,
+ val & ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK,
+ DELAY_US, ACP7X_TIMEOUT);
+ if (ret)
+ return ret;
+
+ writel(0, acp_base + ACP_SOFT_RESET);
+ return readl_poll_timeout(acp_base + ACP_SOFT_RESET, val, !val, DELAY_US, ACP7X_TIMEOUT);
+}
+
+static int acp7x_init(void __iomem *acp_base, struct device *dev)
+{
+ int ret;
+
+ ret = acp7x_power_on(acp_base);
+ if (ret) {
+ dev_err(dev, "ACP power on failed\n");
+ return ret;
+ }
+ writel(0x01, acp_base + ACP_CONTROL);
+ ret = acp7x_reset(acp_base);
+ if (ret) {
+ dev_err(dev, "ACP reset failed\n");
+ return ret;
+ }
+ writel(0, acp_base + ACP_ZSC_DSP_CTRL);
+ return 0;
+}
+
+static int acp7x_deinit(void __iomem *acp_base, struct device *dev)
+{
+ int ret;
+
+ ret = acp7x_reset(acp_base);
+ if (ret) {
+ dev_err(dev, "ACP reset failed\n");
+ return ret;
+ }
+ writel(0x01, acp_base + ACP_ZSC_DSP_CTRL);
+ return 0;
+}
+
+static int __maybe_unused snd_acp7x_suspend(struct device *dev)
+{
+ struct acp7x_dev_data *adata;
+ int ret;
+
+ adata = dev_get_drvdata(dev);
+ ret = acp_hw_deinit(adata, dev);
+ if (ret)
+ dev_err(dev, "ACP de-init failed\n");
+ return ret;
+}
+
+static int __maybe_unused snd_acp7x_runtime_resume(struct device *dev)
+{
+ struct acp7x_dev_data *adata;
+ int ret;
+
+ adata = dev_get_drvdata(dev);
+ ret = acp_hw_init(adata, dev);
+ if (ret) {
+ dev_err(dev, "ACP init failed\n");
+ return ret;
+ }
+ return 0;
+}
+
+static int __maybe_unused snd_acp7x_resume(struct device *dev)
+{
+ struct acp7x_dev_data *adata;
+ int ret;
+
+ adata = dev_get_drvdata(dev);
+ ret = acp_hw_init(adata, dev);
+ if (ret)
+ dev_err(dev, "ACP init failed\n");
+
+ return ret;
+}
+
+void acp7x_hw_init_ops(struct acp_hw_ops *hw_ops)
+{
+ hw_ops->acp_init = acp7x_init;
+ hw_ops->acp_deinit = acp7x_deinit;
+ hw_ops->acp_suspend = snd_acp7x_suspend;
+ hw_ops->acp_resume = snd_acp7x_resume;
+ hw_ops->acp_suspend_runtime = snd_acp7x_suspend;
+ hw_ops->acp_resume_runtime = snd_acp7x_runtime_resume;
+}
diff --git a/sound/soc/amd/acp7x/acp7x.h b/sound/soc/amd/acp7x/acp7x.h
new file mode 100644
index 000000000000..ddb5eabf6828
--- /dev/null
+++ b/sound/soc/amd/acp7x/acp7x.h
@@ -0,0 +1,110 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * AMD Common ACP header file for ACP7.X variants(ACP7.D/7.E/7.F)
+ *
+ * Copyright (C) 2026 Advanced Micro Devices, Inc. All rights reserved.
+ */
+
+#ifndef __SOUND_SOC_AMD_ACP7X_H
+#define __SOUND_SOC_AMD_ACP7X_H
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/pci.h>
+#include <linux/types.h>
+
+#include <sound/acp7x_chip_offset_byte.h>
+
+#define ACP_DEVICE_ID 0x15E2
+#define ACP7X_REG_START 0x1240000
+#define ACP7X_REG_END 0x125C000
+
+#define ACP7D_PCI_REV 0x7D
+#define ACP7E_PCI_REV 0x7E
+#define ACP7F_PCI_REV 0x7F
+
+/* Common register helper bits used by acp7x-common.c */
+#define ACP_SOFT_RESET_SOFTRESET_AUDDONE_MASK 0x00010001
+
+#define DELAY_US 5
+#define ACP7X_TIMEOUT 5000
+
+#define ACP7X_PGFSM_CNTL_POWER_ON_MASK 7
+#define ACP7X_PGFSM_STATUS_MASK 0x3F
+
+/* time in ms for runtime suspend delay */
+#define ACP_SUSPEND_DELAY_MS 2000
+
+struct acp_hw_ops {
+ int (*acp_init)(void __iomem *acp_base, struct device *dev);
+ int (*acp_deinit)(void __iomem *acp_base, struct device *dev);
+ int (*acp_suspend)(struct device *dev);
+ int (*acp_resume)(struct device *dev);
+ int (*acp_suspend_runtime)(struct device *dev);
+ int (*acp_resume_runtime)(struct device *dev);
+};
+
+struct acp7x_dev_data {
+ void __iomem *acp7x_base;
+ struct acp_hw_ops *hw_ops;
+ u32 addr;
+ u32 reg_range;
+ u32 acp_rev;
+};
+
+void acp7x_hw_init_ops(struct acp_hw_ops *hw_ops);
+
+static inline int acp_hw_init(struct acp7x_dev_data *adata, struct device *dev)
+{
+ if (adata && adata->hw_ops && adata->hw_ops->acp_init)
+ return adata->hw_ops->acp_init(adata->acp7x_base, dev);
+ return -EOPNOTSUPP;
+}
+
+static inline int acp_hw_deinit(struct acp7x_dev_data *adata, struct device *dev)
+{
+ if (adata && adata->hw_ops && adata->hw_ops->acp_deinit)
+ return adata->hw_ops->acp_deinit(adata->acp7x_base, dev);
+ return -EOPNOTSUPP;
+}
+
+static inline int acp_hw_suspend(struct device *dev)
+{
+ struct acp7x_dev_data *adata = dev_get_drvdata(dev);
+
+ if (adata && adata->hw_ops && adata->hw_ops->acp_suspend)
+ return adata->hw_ops->acp_suspend(dev);
+ return -EOPNOTSUPP;
+}
+
+static inline int acp_hw_resume(struct device *dev)
+{
+ struct acp7x_dev_data *adata = dev_get_drvdata(dev);
+
+ if (adata && adata->hw_ops && adata->hw_ops->acp_resume)
+ return adata->hw_ops->acp_resume(dev);
+ return -EOPNOTSUPP;
+}
+
+static inline int acp_hw_suspend_runtime(struct device *dev)
+{
+ struct acp7x_dev_data *adata = dev_get_drvdata(dev);
+
+ if (adata && adata->hw_ops && adata->hw_ops->acp_suspend_runtime)
+ return adata->hw_ops->acp_suspend_runtime(dev);
+ return -EOPNOTSUPP;
+}
+
+static inline int acp_hw_runtime_resume(struct device *dev)
+{
+ struct acp7x_dev_data *adata = dev_get_drvdata(dev);
+
+ if (adata && adata->hw_ops && adata->hw_ops->acp_resume_runtime)
+ return adata->hw_ops->acp_resume_runtime(dev);
+ return -EOPNOTSUPP;
+}
+
+int snd_amd_acp_find_config(struct pci_dev *pci);
+
+#endif /* __SOUND_SOC_AMD_ACP7X_H */
diff --git a/sound/soc/amd/acp7x/pci-acp7x.c b/sound/soc/amd/acp7x/pci-acp7x.c
new file mode 100644
index 000000000000..d29a149cf175
--- /dev/null
+++ b/sound/soc/amd/acp7x/pci-acp7x.c
@@ -0,0 +1,168 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * AMD common ACP PCI driver for ACP7.x variants
+ * which includes ACP7.D/7.E/7.F and future variants
+ * with same register layout.
+ *
+ * Copyright 2026 Advanced Micro Devices, Inc.
+ */
+
+#include <linux/errno.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#include "acp7x.h"
+
+static int acp_hw_init_ops(struct acp7x_dev_data *adata, struct pci_dev *pci)
+{
+ adata->hw_ops = devm_kzalloc(&pci->dev, sizeof(struct acp_hw_ops),
+ GFP_KERNEL);
+ if (!adata->hw_ops)
+ return -ENOMEM;
+
+ switch (adata->acp_rev) {
+ case ACP7D_PCI_REV:
+ case ACP7E_PCI_REV:
+ case ACP7F_PCI_REV:
+ acp7x_hw_init_ops(adata->hw_ops);
+ break;
+ default:
+ dev_err(&pci->dev, "ACP device not found\n");
+ return -ENODEV;
+ }
+ return 0;
+}
+
+static int snd_acp7x_probe(struct pci_dev *pci,
+ const struct pci_device_id *pci_id)
+{
+ struct acp7x_dev_data *adata;
+ u32 addr;
+ u32 flag;
+ int ret;
+
+ flag = snd_amd_acp_find_config(pci);
+ if (flag)
+ return -ENODEV;
+ /* ACP PCI revision id check for ACP7.x platforms */
+ switch (pci->revision) {
+ case ACP7D_PCI_REV:
+ case ACP7E_PCI_REV:
+ case ACP7F_PCI_REV:
+ break;
+ default:
+ return -ENODEV;
+ }
+ if (pci_enable_device(pci)) {
+ dev_err(&pci->dev, "pci_enable_device failed\n");
+ return -ENODEV;
+ }
+
+ ret = pci_request_regions(pci, "AMD ACP7.x audio");
+ if (ret < 0) {
+ dev_err(&pci->dev, "pci_request_regions failed\n");
+ goto disable_pci;
+ }
+ adata = devm_kzalloc(&pci->dev, sizeof(struct acp7x_dev_data),
+ GFP_KERNEL);
+ if (!adata) {
+ ret = -ENOMEM;
+ goto release_regions;
+ }
+ addr = pci_resource_start(pci, 0);
+ adata->acp7x_base = devm_ioremap(&pci->dev, addr,
+ pci_resource_len(pci, 0));
+ if (!adata->acp7x_base) {
+ ret = -ENOMEM;
+ goto release_regions;
+ }
+ adata->addr = addr;
+ adata->reg_range = ACP7X_REG_END - ACP7X_REG_START;
+ adata->acp_rev = pci->revision;
+ pci_set_master(pci);
+ pci_set_drvdata(pci, adata);
+ ret = acp_hw_init_ops(adata, pci);
+ if (ret) {
+ dev_err(&pci->dev, "ACP hw ops init failed\n");
+ goto release_regions;
+ }
+ ret = acp_hw_init(adata, &pci->dev);
+ if (ret)
+ goto release_regions;
+
+ pm_runtime_set_autosuspend_delay(&pci->dev, ACP_SUSPEND_DELAY_MS);
+ pm_runtime_use_autosuspend(&pci->dev);
+ pm_runtime_put_noidle(&pci->dev);
+ pm_runtime_allow(&pci->dev);
+ return 0;
+
+release_regions:
+ pci_release_regions(pci);
+disable_pci:
+ pci_disable_device(pci);
+
+ return ret;
+}
+
+static int __maybe_unused snd_acp_suspend(struct device *dev)
+{
+ return acp_hw_suspend(dev);
+}
+
+static int __maybe_unused snd_acp_runtime_resume(struct device *dev)
+{
+ return acp_hw_runtime_resume(dev);
+}
+
+static int __maybe_unused snd_acp_resume(struct device *dev)
+{
+ return acp_hw_resume(dev);
+}
+
+static const struct dev_pm_ops acp7x_pm_ops = {
+ SET_RUNTIME_PM_OPS(snd_acp_suspend, snd_acp_runtime_resume, NULL)
+ SET_SYSTEM_SLEEP_PM_OPS(snd_acp_suspend, snd_acp_resume)
+};
+
+static void snd_acp7x_remove(struct pci_dev *pci)
+{
+ struct acp7x_dev_data *adata;
+ int ret;
+
+ adata = pci_get_drvdata(pci);
+ ret = acp_hw_deinit(adata, &pci->dev);
+ if (ret)
+ dev_err(&pci->dev, "ACP de-init failed\n");
+ pm_runtime_forbid(&pci->dev);
+ pm_runtime_get_noresume(&pci->dev);
+ pci_release_regions(pci);
+ pci_disable_device(pci);
+}
+
+static const struct pci_device_id snd_acp7x_ids[] = {
+ { PCI_DEVICE(PCI_VENDOR_ID_AMD, ACP_DEVICE_ID),
+ .class = PCI_CLASS_MULTIMEDIA_OTHER << 8,
+ .class_mask = 0xffffff },
+ { 0, },
+};
+MODULE_DEVICE_TABLE(pci, snd_acp7x_ids);
+
+static struct pci_driver acp7x_pci_driver = {
+ .name = KBUILD_MODNAME,
+ .id_table = snd_acp7x_ids,
+ .probe = snd_acp7x_probe,
+ .remove = snd_acp7x_remove,
+ .driver = {
+ .pm = &acp7x_pm_ops,
+ }
+};
+
+module_pci_driver(acp7x_pci_driver);
+
+MODULE_AUTHOR("Vijendar.Mukunda@amd.com");
+MODULE_DESCRIPTION("AMD ACP PCI driver for ACP7.X");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index 9751cf0784a6..4ecda224157b 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -329,7 +329,8 @@ static struct snd_soc_acpi_mach *acp63_sdw_machine_select(struct device *dev)
break;
}
if (i == acp_data->info.count || !link->num_adr)
- break;
+ if (!mach->machine_check || mach->machine_check(acp_data->sdw))
+ break;
}
if (mach && mach->link_mask) {
mach->mach_params.links = mach->links;
diff --git a/sound/soc/amd/ps/ps-mach.c b/sound/soc/amd/ps/ps-mach.c
index ff8ad036b077..3e49c255c025 100644
--- a/sound/soc/amd/ps/ps-mach.c
+++ b/sound/soc/amd/ps/ps-mach.c
@@ -45,7 +45,6 @@ static struct snd_soc_card acp63_card = {
static int acp63_probe(struct platform_device *pdev)
{
- struct acp63_pdm *machine = NULL;
struct snd_soc_card *card;
int ret;
@@ -53,7 +52,6 @@ static int acp63_probe(struct platform_device *pdev)
card = platform_get_drvdata(pdev);
acp63_card.dev = &pdev->dev;
- snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
return dev_err_probe(&pdev->dev, ret,
diff --git a/sound/soc/amd/renoir/acp3x-rn.c b/sound/soc/amd/renoir/acp3x-rn.c
index 3249f74a0197..516c3d4f4ede 100644
--- a/sound/soc/amd/renoir/acp3x-rn.c
+++ b/sound/soc/amd/renoir/acp3x-rn.c
@@ -44,14 +44,12 @@ static struct snd_soc_card acp_card = {
static int acp_probe(struct platform_device *pdev)
{
int ret;
- struct acp_pdm *machine = NULL;
struct snd_soc_card *card;
card = &acp_card;
acp_card.dev = &pdev->dev;
platform_set_drvdata(pdev, card);
- snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
return dev_err_probe(&pdev->dev, ret,
diff --git a/sound/soc/amd/yc/acp6x-mach.c b/sound/soc/amd/yc/acp6x-mach.c
index 7a637d6b5576..d6df7de70b27 100644
--- a/sound/soc/amd/yc/acp6x-mach.c
+++ b/sound/soc/amd/yc/acp6x-mach.c
@@ -524,6 +524,20 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
{
.driver_data = &acp6x_card,
.matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Raider A18 HX A9WJG"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"),
+ DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m15 R7 AMD"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
DMI_MATCH(DMI_BOARD_VENDOR, "Alienware"),
DMI_MATCH(DMI_PRODUCT_NAME, "Alienware m17 R5 AMD"),
}
@@ -794,13 +808,26 @@ static const struct dmi_system_id yc_acp_quirk_table[] = {
DMI_MATCH(DMI_PRODUCT_NAME, "M7601RM"),
}
},
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "Micro-Star International Co., Ltd."),
+ DMI_MATCH(DMI_BOARD_NAME, "MS-17LN"),
+ }
+ },
+ {
+ .driver_data = &acp6x_card,
+ .matches = {
+ DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTeK COMPUTER INC."),
+ DMI_MATCH(DMI_BOARD_NAME, "PM1403CDA"),
+ }
+ },
{}
};
static int acp6x_probe(struct platform_device *pdev)
{
const struct dmi_system_id *dmi_id;
- struct acp6x_pdm *machine = NULL;
struct snd_soc_card *card;
struct acpi_device *adev;
acpi_handle handle;
@@ -847,7 +874,6 @@ check_dmi_entry:
dev_info(&pdev->dev, "Enabling ACP DMIC support via %s", dmi_id ? "DMI" : "ACPI");
acp6x_card.dev = &pdev->dev;
- snd_soc_card_set_drvdata(card, machine);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (ret) {
return dev_err_probe(&pdev->dev, ret,
diff --git a/sound/soc/apple/mca.c b/sound/soc/apple/mca.c
index 39269cc7def6..492165c0e1ea 100644
--- a/sound/soc/apple/mca.c
+++ b/sound/soc/apple/mca.c
@@ -307,7 +307,7 @@ static bool mca_fe_clocks_in_use(struct mca_cluster *cl)
struct mca_cluster *be_cl;
int stream, i;
- mutex_lock(&mca->port_mutex);
+ guard(mutex)(&mca->port_mutex);
for (i = 0; i < mca->nclusters; i++) {
be_cl = &mca->clusters[i];
@@ -316,12 +316,10 @@ static bool mca_fe_clocks_in_use(struct mca_cluster *cl)
for_each_pcm_streams(stream) {
if (be_cl->clocks_in_use[stream]) {
- mutex_unlock(&mca->port_mutex);
return true;
}
}
}
- mutex_unlock(&mca->port_mutex);
return false;
}
@@ -765,9 +763,8 @@ static int mca_be_startup(struct snd_pcm_substream *substream,
cl->base + REG_PORT_CLOCK_SEL);
writel_relaxed(PORT_DATA_SEL_TXA(fe_cl->no),
cl->base + REG_PORT_DATA_SEL);
- mutex_lock(&mca->port_mutex);
- cl->port_driver = fe_cl->no;
- mutex_unlock(&mca->port_mutex);
+ scoped_guard(mutex, &mca->port_mutex)
+ cl->port_driver = fe_cl->no;
cl->port_started[substream->stream] = true;
return 0;
@@ -788,9 +785,8 @@ static void mca_be_shutdown(struct snd_pcm_substream *substream,
*/
writel_relaxed(0, cl->base + REG_PORT_ENABLES);
writel_relaxed(0, cl->base + REG_PORT_DATA_SEL);
- mutex_lock(&mca->port_mutex);
- cl->port_driver = -1;
- mutex_unlock(&mca->port_mutex);
+ scoped_guard(mutex, &mca->port_mutex)
+ cl->port_driver = -1;
}
}
diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c
index 1f8c60d2de82..6693bdcbb8f5 100644
--- a/sound/soc/atmel/atmel-classd.c
+++ b/sound/soc/atmel/atmel-classd.c
@@ -11,6 +11,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
+#include <linux/bitfield.h>
#include <linux/string_choices.h>
#include <sound/core.h>
#include <sound/dmaengine_pcm.h>
@@ -236,34 +237,34 @@ static int atmel_classd_component_probe(struct snd_soc_component *component)
u32 mask, val;
mask = CLASSD_MR_PWMTYP_MASK;
- val = pdata->pwm_type << CLASSD_MR_PWMTYP_SHIFT;
+ val = FIELD_PREP(CLASSD_MR_PWMTYP_MASK, pdata->pwm_type);
mask |= CLASSD_MR_NON_OVERLAP_MASK;
if (pdata->non_overlap_enable) {
- val |= (CLASSD_MR_NON_OVERLAP_EN
- << CLASSD_MR_NON_OVERLAP_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NON_OVERLAP_MASK,
+ CLASSD_MR_NON_OVERLAP_EN);
mask |= CLASSD_MR_NOVR_VAL_MASK;
switch (pdata->non_overlap_time) {
case 5:
- val |= (CLASSD_MR_NOVR_VAL_5NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_5NS);
break;
case 10:
- val |= (CLASSD_MR_NOVR_VAL_10NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_10NS);
break;
case 15:
- val |= (CLASSD_MR_NOVR_VAL_15NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_15NS);
break;
case 20:
- val |= (CLASSD_MR_NOVR_VAL_20NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_20NS);
break;
default:
- val |= (CLASSD_MR_NOVR_VAL_10NS
- << CLASSD_MR_NOVR_VAL_SHIFT);
+ val |= FIELD_PREP(CLASSD_MR_NOVR_VAL_MASK,
+ CLASSD_MR_NOVR_VAL_10NS);
dev_warn(component->dev,
"non-overlapping value %d is invalid, the default value 10 is specified\n",
pdata->non_overlap_time);
@@ -370,8 +371,10 @@ atmel_classd_cpu_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
mask = CLASSD_INTPMR_DSP_CLK_FREQ_MASK | CLASSD_INTPMR_FRAME_MASK;
- val = (sample_rates[best].dsp_clk << CLASSD_INTPMR_DSP_CLK_FREQ_SHIFT)
- | (sample_rates[best].sample_rate << CLASSD_INTPMR_FRAME_SHIFT);
+ val = FIELD_PREP(CLASSD_INTPMR_DSP_CLK_FREQ_MASK,
+ sample_rates[best].dsp_clk) |
+ FIELD_PREP(CLASSD_INTPMR_FRAME_MASK,
+ sample_rates[best].sample_rate);
snd_soc_component_update_bits(component, CLASSD_INTPMR, mask, val);
@@ -395,8 +398,8 @@ static int atmel_classd_cpu_dai_prepare(struct snd_pcm_substream *substream,
snd_soc_component_update_bits(component, CLASSD_MR,
CLASSD_MR_LEN_MASK | CLASSD_MR_REN_MASK,
- (CLASSD_MR_LEN_DIS << CLASSD_MR_LEN_SHIFT)
- |(CLASSD_MR_REN_DIS << CLASSD_MR_REN_SHIFT));
+ FIELD_PREP(CLASSD_MR_LEN_MASK, CLASSD_MR_LEN_DIS) |
+ FIELD_PREP(CLASSD_MR_REN_MASK, CLASSD_MR_REN_DIS));
return 0;
}
@@ -418,8 +421,8 @@ static int atmel_classd_cpu_dai_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- val = (CLASSD_MR_LEN_DIS << CLASSD_MR_LEN_SHIFT)
- | (CLASSD_MR_REN_DIS << CLASSD_MR_REN_SHIFT);
+ val = FIELD_PREP(CLASSD_MR_LEN_MASK, CLASSD_MR_LEN_DIS) |
+ FIELD_PREP(CLASSD_MR_REN_MASK, CLASSD_MR_REN_DIS);
break;
default:
return -EINVAL;
diff --git a/sound/soc/atmel/mchp-spdifrx.c b/sound/soc/atmel/mchp-spdifrx.c
index 521bee4998f8..2c47aabdca95 100644
--- a/sound/soc/atmel/mchp-spdifrx.c
+++ b/sound/soc/atmel/mchp-spdifrx.c
@@ -6,6 +6,7 @@
//
// Author: Codrin Ciubotariu <codrin.ciubotariu@microchip.com>
+#include <linux/bitfield.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/module.h>
@@ -41,6 +42,13 @@
#define SPDIFRX_VERSION 0xFC /* Version Register */
+
+/* 32-bit word byte masks */
+#define SPDIFRX_BYTE_0_MASK GENMASK(7, 0)
+#define SPDIFRX_BYTE_1_MASK GENMASK(15, 8)
+#define SPDIFRX_BYTE_2_MASK GENMASK(23, 16)
+#define SPDIFRX_BYTE_3_MASK GENMASK(31, 24)
+
/*
* ---- Control Register (Write-only) ----
*/
@@ -55,7 +63,7 @@
#define SPDIFRX_MR_RXEN_ENABLE (1 << 0) /* SPDIF Receiver Enabled */
/* Validity Bit Mode */
-#define SPDIFRX_MR_VBMODE_MASK GENAMSK(1, 1)
+#define SPDIFRX_MR_VBMODE_MASK GENMASK(1, 1)
#define SPDIFRX_MR_VBMODE_ALWAYS_LOAD \
(0 << 1) /* Load sample regardless of validity bit value */
#define SPDIFRX_MR_VBMODE_DISCARD_IF_VB1 \
@@ -74,7 +82,7 @@
/* Sample Data Width */
#define SPDIFRX_MR_DATAWIDTH_MASK GENMASK(5, 4)
#define SPDIFRX_MR_DATAWIDTH(width) \
- (((6 - (width) / 4) << 4) & SPDIFRX_MR_DATAWIDTH_MASK)
+ FIELD_PREP(SPDIFRX_MR_DATAWIDTH_MASK, 6 - ((width) / 4))
/* Packed Data Mode in Receive Holding Register */
#define SPDIFRX_MR_PACK_MASK GENMASK(7, 7)
@@ -118,15 +126,14 @@
#define SPDIFRX_RSR_LOWF BIT(2)
#define SPDIFRX_RSR_NOSIGNAL BIT(3)
#define SPDIFRX_RSR_IFS_MASK GENMASK(27, 16)
-#define SPDIFRX_RSR_IFS(reg) \
- (((reg) & SPDIFRX_RSR_IFS_MASK) >> 16)
+#define SPDIFRX_RSR_IFS(reg) FIELD_GET(SPDIFRX_RSR_IFS_MASK, reg)
/*
* ---- Version Register (Read-only) ----
*/
#define SPDIFRX_VERSION_MASK GENMASK(11, 0)
#define SPDIFRX_VERSION_MFN_MASK GENMASK(18, 16)
-#define SPDIFRX_VERSION_MFN(reg) (((reg) & SPDIFRX_VERSION_MFN_MASK) >> 16)
+#define SPDIFRX_VERSION_MFN(reg) FIELD_GET(SPDIFRX_VERSION_MFN_MASK, reg)
static bool mchp_spdifrx_readable_reg(struct device *dev, unsigned int reg)
{
@@ -317,10 +324,10 @@ static void mchp_spdifrx_channel_status_read(struct mchp_spdifrx_dev *dev,
for (i = 0; i < ARRAY_SIZE(ctrl->ch_stat[channel].data) / 4; i++) {
regmap_read(dev->regmap, SPDIFRX_CHSR(channel, i), &val);
- *ch_stat++ = val & 0xFF;
- *ch_stat++ = (val >> 8) & 0xFF;
- *ch_stat++ = (val >> 16) & 0xFF;
- *ch_stat++ = (val >> 24) & 0xFF;
+ *ch_stat++ = FIELD_GET(SPDIFRX_BYTE_0_MASK, val);
+ *ch_stat++ = FIELD_GET(SPDIFRX_BYTE_1_MASK, val);
+ *ch_stat++ = FIELD_GET(SPDIFRX_BYTE_2_MASK, val);
+ *ch_stat++ = FIELD_GET(SPDIFRX_BYTE_3_MASK, val);
}
}
@@ -334,10 +341,10 @@ static void mchp_spdifrx_channel_user_data_read(struct mchp_spdifrx_dev *dev,
for (i = 0; i < ARRAY_SIZE(ctrl->user_data[channel].data) / 4; i++) {
regmap_read(dev->regmap, SPDIFRX_CHUD(channel, i), &val);
- *user_data++ = val & 0xFF;
- *user_data++ = (val >> 8) & 0xFF;
- *user_data++ = (val >> 16) & 0xFF;
- *user_data++ = (val >> 24) & 0xFF;
+ *user_data++ = FIELD_GET(SPDIFRX_BYTE_0_MASK, val);
+ *user_data++ = FIELD_GET(SPDIFRX_BYTE_1_MASK, val);
+ *user_data++ = FIELD_GET(SPDIFRX_BYTE_2_MASK, val);
+ *user_data++ = FIELD_GET(SPDIFRX_BYTE_3_MASK, val);
}
}
diff --git a/sound/soc/atmel/sam9x5_wm8731.c b/sound/soc/atmel/sam9x5_wm8731.c
index 1b5ef4e9d2b8..a603e4a57d50 100644
--- a/sound/soc/atmel/sam9x5_wm8731.c
+++ b/sound/soc/atmel/sam9x5_wm8731.c
@@ -15,7 +15,6 @@
#include <linux/of.h>
#include <linux/export.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/device.h>
diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c
index e0ce0232eb1e..47706ae0a31f 100644
--- a/sound/soc/bcm/cygnus-ssp.c
+++ b/sound/soc/bcm/cygnus-ssp.c
@@ -1298,7 +1298,6 @@ static int audio_clk_init(struct platform_device *pdev,
static int cygnus_ssp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct device_node *child_node;
struct cygnus_audio *cygaud;
int err;
int node_count;
@@ -1331,16 +1330,15 @@ static int cygnus_ssp_probe(struct platform_device *pdev)
active_port_count = 0;
- for_each_available_child_of_node(pdev->dev.of_node, child_node) {
+ for_each_available_child_of_node_scoped(pdev->dev.of_node, child_node) {
err = parse_ssp_child_node(pdev, child_node, cygaud,
&cygnus_ssp_dai[active_port_count]);
/* negative is err, 0 is active and good, 1 is disabled */
- if (err < 0) {
- of_node_put(child_node);
+ if (err < 0)
return err;
- }
- else if (!err) {
+
+ if (!err) {
dev_dbg(dev, "Activating DAI: %s\n",
cygnus_ssp_dai[active_port_count].name);
active_port_count++;
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index cf94a1c756e0..252f683be3c1 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -93,6 +93,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_CS4271_I2C
imply SND_SOC_CS4271_SPI
imply SND_SOC_CS42XX8_I2C
+ imply SND_SOC_CS42XX8_SPI
imply SND_SOC_CS43130
imply SND_SOC_CS4341
imply SND_SOC_CS4349
@@ -122,6 +123,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_ES8328_I2C
imply SND_SOC_ES8375
imply SND_SOC_ES8389
+ imply SND_SOC_ES9356
imply SND_SOC_ES7134
imply SND_SOC_ES7241
imply SND_SOC_FRAMER
@@ -264,6 +266,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_STA529
imply SND_SOC_STAC9766
imply SND_SOC_STI_SAS
+ imply SND_SOC_TAC5XX2_SDW
imply SND_SOC_TAS2552
imply SND_SOC_TAS2562
imply SND_SOC_TAS2764
@@ -275,6 +278,7 @@ config SND_SOC_ALL_CODECS
imply SND_SOC_TAS571X
imply SND_SOC_TAS5720
imply SND_SOC_TAS6424
+ imply SND_SOC_TAS675X
imply SND_SOC_TDA7419
imply SND_SOC_TFA9879
imply SND_SOC_TFA989X
@@ -884,7 +888,7 @@ config SND_SOC_CS35L56_SPI
config SND_SOC_CS35L56_SDW
tristate "Cirrus Logic CS35L56 CODEC (SDW)"
depends on SOUNDWIRE
- select REGMAP
+ select REGMAP_SOUNDWIRE
select SND_SOC_CS35L56
select SND_SOC_CS35L56_SHARED
help
@@ -898,7 +902,6 @@ menu "CS35L56 driver options"
config SND_SOC_CS35L56_CAL_DEBUGFS
bool "CS35L56 create debugfs for factory calibration"
- default N
depends on DEBUG_FS
select SND_SOC_CS35L56_CAL_DEBUGFS_COMMON
help
@@ -909,7 +912,6 @@ config SND_SOC_CS35L56_CAL_DEBUGFS
config SND_SOC_CS35L56_CAL_SET_CTRL
bool "CS35L56 ALSA control to restore factory calibration"
- default N
select SND_SOC_CS35L56_CAL_DEBUGFS_COMMON
help
Allow restoring factory calibration data through an ALSA
@@ -923,7 +925,6 @@ config SND_SOC_CS35L56_CAL_SET_CTRL
config SND_SOC_CS35L56_CAL_PERFORM_CTRL
bool "CS35L56 ALSA control to perform factory calibration"
- default N
select SND_SOC_CS35L56_CAL_DEBUGFS_COMMON
help
Allow performing factory calibration data through an ALSA
@@ -1077,6 +1078,12 @@ config SND_SOC_CS4271_SPI
config SND_SOC_CS42XX8
tristate
+config SND_SOC_CS42XX8_SPI
+ tristate "Cirrus Logic CS42448/CS42888 CODEC (SPI)"
+ depends on SPI_MASTER
+ select SND_SOC_CS42XX8
+ select REGMAP_SPI
+
config SND_SOC_CS42XX8_I2C
tristate "Cirrus Logic CS42448/CS42888 CODEC (I2C)"
depends on I2C
@@ -1300,6 +1307,13 @@ config SND_SOC_ES8389
tristate "Everest Semi ES8389 CODEC"
depends on I2C
+config SND_SOC_ES9356
+ tristate "Everest Semi ES9356 CODEC SDW"
+ depends on SND_SOC_SDCA
+ depends on SOUNDWIRE
+ select REGMAP_SOUNDWIRE
+ select REGMAP_SOUNDWIRE_MBQ
+
config SND_SOC_FRAMER
tristate "Framer codec"
depends on GENERIC_FRAMER
@@ -2139,6 +2153,16 @@ config SND_SOC_STAC9766
config SND_SOC_STI_SAS
tristate "codec Audio support for STI SAS codec"
+config SND_SOC_TAC5XX2_SDW
+ tristate "Texas Instruments TAC5XX2 SoundWire Smart Amplifier"
+ depends on SOUNDWIRE
+ depends on SND_SOC_SDCA
+ help
+ This option enables support for Texas Instruments TAC5XX2 family
+ of SoundWire Smart Amplifiers. This includes TAC5572, TAC5672,
+ TAC5682 and TAS2883. To compile this driver as a module, choose
+ M here: the module will be called snd-soc-tac5xx2.
+
config SND_SOC_TAS2552
tristate "Texas Instruments TAS2552 Mono Audio amplifier"
depends on I2C
@@ -2237,6 +2261,17 @@ config SND_SOC_TAS6424
Enable support for Texas Instruments TAS6424 high-efficiency
digital input quad-channel Class-D audio power amplifiers.
+config SND_SOC_TAS675X
+ tristate "Texas Instruments TAS675x Quad-Channel Audio Amplifier"
+ depends on I2C
+ select REGMAP_I2C
+ help
+ Enable support for Texas Instruments TAS675x quad-channel Class-D
+ audio power amplifiers (TAS6754, TAS67524). The devices support I2S
+ and TDM interfaces with real-time voltage and current sense feedback
+ via SDOUT, and provide DC/AC/real-time load diagnostics for speaker
+ monitoring.
+
config SND_SOC_TDA7419
tristate "ST TDA7419 audio processor"
depends on I2C
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 172861d17cfd..aa0396e5b575 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -103,6 +103,7 @@ snd-soc-cs4271-i2c-y := cs4271-i2c.o
snd-soc-cs4271-spi-y := cs4271-spi.o
snd-soc-cs42xx8-y := cs42xx8.o
snd-soc-cs42xx8-i2c-y := cs42xx8-i2c.o
+snd-soc-cs42xx8-spi-y := cs42xx8-spi.o
snd-soc-cs43130-y := cs43130.o
snd-soc-cs4341-y := cs4341.o
snd-soc-cs4349-y := cs4349.o
@@ -138,6 +139,7 @@ snd-soc-es8328-i2c-y := es8328-i2c.o
snd-soc-es8328-spi-y := es8328-spi.o
snd-soc-es8375-y := es8375.o
snd-soc-es8389-y := es8389.o
+snd-soc-es9356-y := es9356.o
snd-soc-framer-y := framer-codec.o
snd-soc-fs-amp-lib-y := fs-amp-lib.o
snd-soc-fs210x-y := fs210x.o
@@ -313,11 +315,13 @@ snd-soc-sta350-y := sta350.o
snd-soc-sta529-y := sta529.o
snd-soc-stac9766-y := stac9766.o
snd-soc-sti-sas-y := sti-sas.o
+snd-soc-tac5xx2-sdw-y := tac5xx2-sdw.o
snd-soc-tas5086-y := tas5086.o
snd-soc-tas571x-y := tas571x.o
snd-soc-tas5720-y := tas5720.o
snd-soc-tas5805m-y := tas5805m.o
snd-soc-tas6424-y := tas6424.o
+snd-soc-tas675x-y := tas675x.o
snd-soc-tda7419-y := tda7419.o
snd-soc-tas2770-y := tas2770.o
snd-soc-tas2781-comlib-y := tas2781-comlib.o
@@ -540,6 +544,7 @@ obj-$(CONFIG_SND_SOC_CS4271_I2C) += snd-soc-cs4271-i2c.o
obj-$(CONFIG_SND_SOC_CS4271_SPI) += snd-soc-cs4271-spi.o
obj-$(CONFIG_SND_SOC_CS42XX8) += snd-soc-cs42xx8.o
obj-$(CONFIG_SND_SOC_CS42XX8_I2C) += snd-soc-cs42xx8-i2c.o
+obj-$(CONFIG_SND_SOC_CS42XX8_SPI) += snd-soc-cs42xx8-spi.o
obj-$(CONFIG_SND_SOC_CS43130) += snd-soc-cs43130.o
obj-$(CONFIG_SND_SOC_CS4341) += snd-soc-cs4341.o
obj-$(CONFIG_SND_SOC_CS4349) += snd-soc-cs4349.o
@@ -575,6 +580,7 @@ obj-$(CONFIG_SND_SOC_ES8328_I2C)+= snd-soc-es8328-i2c.o
obj-$(CONFIG_SND_SOC_ES8328_SPI)+= snd-soc-es8328-spi.o
obj-$(CONFIG_SND_SOC_ES8375) += snd-soc-es8375.o
obj-$(CONFIG_SND_SOC_ES8389) += snd-soc-es8389.o
+obj-$(CONFIG_SND_SOC_ES9356) += snd-soc-es9356.o
obj-$(CONFIG_SND_SOC_FRAMER) += snd-soc-framer.o
obj-$(CONFIG_SND_SOC_FS_AMP_LIB)+= snd-soc-fs-amp-lib.o
obj-$(CONFIG_SND_SOC_FS210X) += snd-soc-fs210x.o
@@ -746,6 +752,7 @@ obj-$(CONFIG_SND_SOC_STA350) += snd-soc-sta350.o
obj-$(CONFIG_SND_SOC_STA529) += snd-soc-sta529.o
obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
obj-$(CONFIG_SND_SOC_STI_SAS) += snd-soc-sti-sas.o
+obj-$(CONFIG_SND_SOC_TAC5XX2_SDW) += snd-soc-tac5xx2-sdw.o
obj-$(CONFIG_SND_SOC_TAS2552) += snd-soc-tas2552.o
obj-$(CONFIG_SND_SOC_TAS2562) += snd-soc-tas2562.o
obj-$(CONFIG_SND_SOC_TAS2764) += snd-soc-tas2764.o
@@ -760,6 +767,7 @@ obj-$(CONFIG_SND_SOC_TAS571X) += snd-soc-tas571x.o
obj-$(CONFIG_SND_SOC_TAS5720) += snd-soc-tas5720.o
obj-$(CONFIG_SND_SOC_TAS5805M) += snd-soc-tas5805m.o
obj-$(CONFIG_SND_SOC_TAS6424) += snd-soc-tas6424.o
+obj-$(CONFIG_SND_SOC_TAS675X) += snd-soc-tas675x.o
obj-$(CONFIG_SND_SOC_TDA7419) += snd-soc-tda7419.o
obj-$(CONFIG_SND_SOC_TAS2770) += snd-soc-tas2770.o
obj-$(CONFIG_SND_SOC_TFA9879) += snd-soc-tfa9879.o
diff --git a/sound/soc/codecs/ad193x-i2c.c b/sound/soc/codecs/ad193x-i2c.c
index 6aa168e01fbb..d4d6560bdb80 100644
--- a/sound/soc/codecs/ad193x-i2c.c
+++ b/sound/soc/codecs/ad193x-i2c.c
@@ -14,8 +14,8 @@
#include "ad193x.h"
static const struct i2c_device_id ad193x_id[] = {
- { "ad1936", AD193X },
- { "ad1937", AD193X },
+ { .name = "ad1936", .driver_data = AD193X },
+ { .name = "ad1937", .driver_data = AD193X },
{ }
};
MODULE_DEVICE_TABLE(i2c, ad193x_id);
diff --git a/sound/soc/codecs/adau1372-i2c.c b/sound/soc/codecs/adau1372-i2c.c
index 73f83be38f74..bdb3e3a8509d 100644
--- a/sound/soc/codecs/adau1372-i2c.c
+++ b/sound/soc/codecs/adau1372-i2c.c
@@ -7,7 +7,6 @@
*/
#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
@@ -21,7 +20,7 @@ static int adau1372_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id adau1372_i2c_ids[] = {
- { "adau1372" },
+ { .name = "adau1372" },
{ }
};
MODULE_DEVICE_TABLE(i2c, adau1372_i2c_ids);
diff --git a/sound/soc/codecs/adau1372-spi.c b/sound/soc/codecs/adau1372-spi.c
index 656bd1fabeb3..a12961e2fb1e 100644
--- a/sound/soc/codecs/adau1372-spi.c
+++ b/sound/soc/codecs/adau1372-spi.c
@@ -6,7 +6,6 @@
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
diff --git a/sound/soc/codecs/adau1372.c b/sound/soc/codecs/adau1372.c
index d7363f9d53bb..cc174ec3a1f8 100644
--- a/sound/soc/codecs/adau1372.c
+++ b/sound/soc/codecs/adau1372.c
@@ -11,7 +11,6 @@
#include <linux/gpio/consumer.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/pm.h>
#include <linux/slab.h>
@@ -813,6 +812,11 @@ static int adau1372_set_power(struct adau1372 *adau1372, bool enable)
if (adau1372->use_pll) {
ret = adau1372_enable_pll(adau1372);
if (ret) {
+ if (!adau1372->pd_gpio)
+ regmap_update_bits(adau1372->regmap,
+ ADAU1372_REG_CLK_CTRL,
+ ADAU1372_CLK_CTRL_PLL_EN,
+ 0);
regcache_cache_only(adau1372->regmap, true);
if (adau1372->pd_gpio)
gpiod_set_value(adau1372->pd_gpio, 1);
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
index 16b9b2658341..5dd961b233ce 100644
--- a/sound/soc/codecs/adau1373.c
+++ b/sound/soc/codecs/adau1373.c
@@ -1599,7 +1599,7 @@ static int adau1373_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id adau1373_i2c_id[] = {
- { "adau1373" },
+ { .name = "adau1373" },
{ }
};
MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id);
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 6876462d8bdb..329ab01b62c0 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -860,10 +860,10 @@ exit_regulators_disable:
}
static const struct i2c_device_id adau1701_i2c_id[] = {
- { "adau1401" },
- { "adau1401a" },
- { "adau1701" },
- { "adau1702" },
+ { .name = "adau1401" },
+ { .name = "adau1401a" },
+ { .name = "adau1701" },
+ { .name = "adau1702" },
{ }
};
MODULE_DEVICE_TABLE(i2c, adau1701_i2c_id);
diff --git a/sound/soc/codecs/adau1761-i2c.c b/sound/soc/codecs/adau1761-i2c.c
index eba7e4f42c78..ae73136d0a6e 100644
--- a/sound/soc/codecs/adau1761-i2c.c
+++ b/sound/soc/codecs/adau1761-i2c.c
@@ -7,7 +7,6 @@
*/
#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
@@ -33,10 +32,10 @@ static void adau1761_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id adau1761_i2c_ids[] = {
- { "adau1361", ADAU1361 },
- { "adau1461", ADAU1761 },
- { "adau1761", ADAU1761 },
- { "adau1961", ADAU1361 },
+ { .name = "adau1361", .driver_data = ADAU1361 },
+ { .name = "adau1461", .driver_data = ADAU1761 },
+ { .name = "adau1761", .driver_data = ADAU1761 },
+ { .name = "adau1961", .driver_data = ADAU1361 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adau1761_i2c_ids);
diff --git a/sound/soc/codecs/adau1761-spi.c b/sound/soc/codecs/adau1761-spi.c
index 7c9242c2ff94..eb6f63d63783 100644
--- a/sound/soc/codecs/adau1761-spi.c
+++ b/sound/soc/codecs/adau1761-spi.c
@@ -6,7 +6,6 @@
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
diff --git a/sound/soc/codecs/adau1781-i2c.c b/sound/soc/codecs/adau1781-i2c.c
index cb67fde8d9a8..3ab624417f12 100644
--- a/sound/soc/codecs/adau1781-i2c.c
+++ b/sound/soc/codecs/adau1781-i2c.c
@@ -7,7 +7,6 @@
*/
#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
@@ -33,8 +32,8 @@ static void adau1781_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id adau1781_i2c_ids[] = {
- { "adau1381", ADAU1381 },
- { "adau1781", ADAU1781 },
+ { .name = "adau1381", .driver_data = ADAU1381 },
+ { .name = "adau1781", .driver_data = ADAU1781 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adau1781_i2c_ids);
diff --git a/sound/soc/codecs/adau1781-spi.c b/sound/soc/codecs/adau1781-spi.c
index 1a09633d5a88..0e6d42b10077 100644
--- a/sound/soc/codecs/adau1781-spi.c
+++ b/sound/soc/codecs/adau1781-spi.c
@@ -6,7 +6,6 @@
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>
diff --git a/sound/soc/codecs/adau1977-i2c.c b/sound/soc/codecs/adau1977-i2c.c
index 441c8079246a..d1c6c4ddf506 100644
--- a/sound/soc/codecs/adau1977-i2c.c
+++ b/sound/soc/codecs/adau1977-i2c.c
@@ -7,7 +7,6 @@
*/
#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/soc.h>
@@ -28,9 +27,9 @@ static int adau1977_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id adau1977_i2c_ids[] = {
- { "adau1977", ADAU1977 },
- { "adau1978", ADAU1978 },
- { "adau1979", ADAU1978 },
+ { .name = "adau1977", .driver_data = ADAU1977 },
+ { .name = "adau1978", .driver_data = ADAU1978 },
+ { .name = "adau1979", .driver_data = ADAU1978 },
{ }
};
MODULE_DEVICE_TABLE(i2c, adau1977_i2c_ids);
diff --git a/sound/soc/codecs/adau1977-spi.c b/sound/soc/codecs/adau1977-spi.c
index e7e95e5d1911..878cde9d1014 100644
--- a/sound/soc/codecs/adau1977-spi.c
+++ b/sound/soc/codecs/adau1977-spi.c
@@ -6,7 +6,6 @@
* Author: Lars-Peter Clausen <lars@metafoo.de>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/of.h>
diff --git a/sound/soc/codecs/adau7118-hw.c b/sound/soc/codecs/adau7118-hw.c
index 45a5d2dcc0f2..92b226b8b4bb 100644
--- a/sound/soc/codecs/adau7118-hw.c
+++ b/sound/soc/codecs/adau7118-hw.c
@@ -6,7 +6,6 @@
// Copyright 2019 Analog Devices Inc.
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include "adau7118.h"
diff --git a/sound/soc/codecs/adau7118-i2c.c b/sound/soc/codecs/adau7118-i2c.c
index f9dc8f4ef9a4..7cccb4c6cff7 100644
--- a/sound/soc/codecs/adau7118-i2c.c
+++ b/sound/soc/codecs/adau7118-i2c.c
@@ -68,8 +68,8 @@ static const struct of_device_id adau7118_of_match[] = {
MODULE_DEVICE_TABLE(of, adau7118_of_match);
static const struct i2c_device_id adau7118_id[] = {
- {"adau7118"},
- {}
+ { .name = "adau7118" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, adau7118_id);
diff --git a/sound/soc/codecs/adav803.c b/sound/soc/codecs/adav803.c
index 8b96c41f0354..9e5f8e866acb 100644
--- a/sound/soc/codecs/adav803.c
+++ b/sound/soc/codecs/adav803.c
@@ -14,7 +14,7 @@
#include "adav80x.h"
static const struct i2c_device_id adav803_id[] = {
- { "adav803" },
+ { .name = "adav803" },
{ }
};
MODULE_DEVICE_TABLE(i2c, adav803_id);
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index a33cb329865c..6ea7cb78cd44 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -5,7 +5,6 @@
* Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/spi/spi.h>
diff --git a/sound/soc/codecs/ak4118.c b/sound/soc/codecs/ak4118.c
index 23e868e4e3fb..03dadba0b038 100644
--- a/sound/soc/codecs/ak4118.c
+++ b/sound/soc/codecs/ak4118.c
@@ -395,8 +395,8 @@ MODULE_DEVICE_TABLE(of, ak4118_of_match);
#endif
static const struct i2c_device_id ak4118_id_table[] = {
- { "ak4118" },
- {}
+ { .name = "ak4118" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, ak4118_id_table);
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index aadc46a47280..37555674cd15 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -430,7 +430,7 @@ static int ak4535_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id ak4535_i2c_id[] = {
- { "ak4535" },
+ { .name = "ak4535" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
diff --git a/sound/soc/codecs/ak4613.c b/sound/soc/codecs/ak4613.c
index de9e43185555..3e0696b5abf5 100644
--- a/sound/soc/codecs/ak4613.c
+++ b/sound/soc/codecs/ak4613.c
@@ -303,7 +303,7 @@ static const struct of_device_id ak4613_of_match[] = {
MODULE_DEVICE_TABLE(of, ak4613_of_match);
static const struct i2c_device_id ak4613_i2c_id[] = {
- { "ak4613", (kernel_ulong_t)&ak4613_regmap_cfg },
+ { .name = "ak4613", .driver_data = (kernel_ulong_t)&ak4613_regmap_cfg },
{ }
};
MODULE_DEVICE_TABLE(i2c, ak4613_i2c_id);
@@ -748,11 +748,6 @@ static int ak4613_dai_trigger(struct snd_pcm_substream *substream, int cmd,
return 0;
}
-/*
- * Select below from Sound Card, not Auto
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
- */
static const u64 ak4613_dai_formats =
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J;
diff --git a/sound/soc/codecs/ak4619.c b/sound/soc/codecs/ak4619.c
index daf6e15b7077..d9c9f6b20028 100644
--- a/sound/soc/codecs/ak4619.c
+++ b/sound/soc/codecs/ak4619.c
@@ -778,17 +778,13 @@ static int ak4619_dai_startup(struct snd_pcm_substream *substream,
}
static u64 ak4619_dai_formats[] = {
- /*
- * Select below from Sound Card, not here
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
- */
-
/* First Priority */
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J,
/* Second Priority */
+ SND_SOC_POSSIBLE_DAIFMT_I2S |
+ SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
SND_SOC_POSSIBLE_DAIFMT_DSP_B,
};
@@ -831,7 +827,7 @@ static const struct of_device_id ak4619_of_match[] = {
MODULE_DEVICE_TABLE(of, ak4619_of_match);
static const struct i2c_device_id ak4619_i2c_id[] = {
- { "ak4619", (kernel_ulong_t)&ak4619_regmap_cfg },
+ { .name = "ak4619", .driver_data = (kernel_ulong_t)&ak4619_regmap_cfg },
{ }
};
MODULE_DEVICE_TABLE(i2c, ak4619_i2c_id);
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index fe035d2fc913..08ec2035b270 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -672,10 +672,10 @@ static const struct of_device_id ak4642_of_match[] = {
MODULE_DEVICE_TABLE(of, ak4642_of_match);
static const struct i2c_device_id ak4642_i2c_id[] = {
- { "ak4642", (kernel_ulong_t)&ak4642_drvdata },
- { "ak4643", (kernel_ulong_t)&ak4643_drvdata },
- { "ak4648", (kernel_ulong_t)&ak4648_drvdata },
- {}
+ { .name = "ak4642", .driver_data = (kernel_ulong_t)&ak4642_drvdata },
+ { .name = "ak4643", .driver_data = (kernel_ulong_t)&ak4643_drvdata },
+ { .name = "ak4648", .driver_data = (kernel_ulong_t)&ak4648_drvdata },
+ { }
};
MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index d545aa2e0a39..aac54e9d54ee 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -646,7 +646,7 @@ static int ak4671_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id ak4671_i2c_id[] = {
- { "ak4671" },
+ { .name = "ak4671" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ak4671_i2c_id);
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index ec229b315f9f..f5a666c49361 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -963,10 +963,10 @@ static const struct regmap_config alc5623_regmap = {
};
static const struct i2c_device_id alc5623_i2c_table[] = {
- {"alc5621", 0x21},
- {"alc5622", 0x22},
- {"alc5623", 0x23},
- {}
+ { .name = "alc5621", .driver_data = 0x21 },
+ { .name = "alc5622", .driver_data = 0x22 },
+ { .name = "alc5623", .driver_data = 0x23 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, alc5623_i2c_table);
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
index 72f4622204ff..2fd3dd7ef8b3 100644
--- a/sound/soc/codecs/alc5632.c
+++ b/sound/soc/codecs/alc5632.c
@@ -1092,8 +1092,8 @@ static const struct regmap_config alc5632_regmap = {
};
static const struct i2c_device_id alc5632_i2c_table[] = {
- {"alc5632", 0x5c},
- {}
+ { .name = "alc5632", .driver_data = 0x5c },
+ { }
};
MODULE_DEVICE_TABLE(i2c, alc5632_i2c_table);
diff --git a/sound/soc/codecs/audio-iio-aux.c b/sound/soc/codecs/audio-iio-aux.c
index 066e401912b0..964b9a5b2990 100644
--- a/sound/soc/codecs/audio-iio-aux.c
+++ b/sound/soc/codecs/audio-iio-aux.c
@@ -9,7 +9,6 @@
#include <linux/cleanup.h>
#include <linux/iio/consumer.h>
#include <linux/minmax.h>
-#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/string_helpers.h>
diff --git a/sound/soc/codecs/aw87390.c b/sound/soc/codecs/aw87390.c
index 37ca42a25889..020213e0ca4b 100644
--- a/sound/soc/codecs/aw87390.c
+++ b/sound/soc/codecs/aw87390.c
@@ -599,8 +599,8 @@ static const struct of_device_id aw87390_of_match[] = {
MODULE_DEVICE_TABLE(of, aw87390_of_match);
static const struct i2c_device_id aw87390_i2c_id[] = {
- { AW87390_I2C_NAME },
- { AW87391_I2C_NAME },
+ { .name = AW87390_I2C_NAME },
+ { .name = AW87391_I2C_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, aw87390_i2c_id);
diff --git a/sound/soc/codecs/aw88081.c b/sound/soc/codecs/aw88081.c
index 8c5bb3ea0227..d5e886a8f106 100644
--- a/sound/soc/codecs/aw88081.c
+++ b/sound/soc/codecs/aw88081.c
@@ -1137,6 +1137,7 @@ static int aw88081_dev_init(struct aw88081 *aw88081, struct aw_container *aw_cfg
static int aw88081_request_firmware_file(struct aw88081 *aw88081)
{
const struct firmware *cont = NULL;
+ struct aw_container *aw_cfg;
int ret;
aw88081->aw_pa->fw_status = AW88081_DEV_FW_FAILED;
@@ -1148,13 +1149,16 @@ static int aw88081_request_firmware_file(struct aw88081 *aw88081)
dev_dbg(aw88081->aw_pa->dev, "loaded %s - size: %zu\n",
AW88081_ACF_FILE, cont ? cont->size : 0);
- aw88081->aw_cfg = devm_kzalloc(aw88081->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL);
- if (!aw88081->aw_cfg) {
+ aw_cfg = devm_kzalloc(aw88081->aw_pa->dev, struct_size(aw_cfg, data, cont->size), GFP_KERNEL);
+ if (!aw_cfg) {
release_firmware(cont);
return -ENOMEM;
}
- aw88081->aw_cfg->len = (int)cont->size;
- memcpy(aw88081->aw_cfg->data, cont->data, cont->size);
+ aw_cfg->len = (int)cont->size;
+ memcpy(aw_cfg->data, cont->data, cont->size);
+
+ aw88081->aw_cfg = aw_cfg;
+
release_firmware(cont);
ret = aw88395_dev_load_acf_check(aw88081->aw_pa, aw88081->aw_cfg);
@@ -1240,8 +1244,8 @@ static const struct snd_soc_component_driver soc_codec_dev_aw88081 = {
};
static const struct i2c_device_id aw88081_i2c_id[] = {
- { AW88081_I2C_NAME, AW88081},
- { AW88083_I2C_NAME, AW88083},
+ { .name = AW88081_I2C_NAME, .driver_data = AW88081 },
+ { .name = AW88083_I2C_NAME, .driver_data = AW88083 },
{ }
};
MODULE_DEVICE_TABLE(i2c, aw88081_i2c_id);
diff --git a/sound/soc/codecs/aw88166.c b/sound/soc/codecs/aw88166.c
index ea277a940c44..3f15f4ac51f7 100644
--- a/sound/soc/codecs/aw88166.c
+++ b/sound/soc/codecs/aw88166.c
@@ -1801,7 +1801,7 @@ static int aw88166_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id aw88166_i2c_id[] = {
- { AW88166_I2C_NAME },
+ { .name = AW88166_I2C_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, aw88166_i2c_id);
diff --git a/sound/soc/codecs/aw88261.c b/sound/soc/codecs/aw88261.c
index a6805d5405cd..549783d3e75e 100644
--- a/sound/soc/codecs/aw88261.c
+++ b/sound/soc/codecs/aw88261.c
@@ -10,9 +10,12 @@
#include <linux/i2c.h>
#include <linux/firmware.h>
+#include <linux/bitops.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
#include "aw88261.h"
#include "aw88395/aw88395_data_type.h"
#include "aw88395/aw88395_device.h"
@@ -27,64 +30,10 @@ static const struct regmap_config aw88261_remap_config = {
static void aw88261_dev_set_volume(struct aw_device *aw_dev, unsigned int value)
{
- struct aw_volume_desc *vol_desc = &aw_dev->volume_desc;
- unsigned int real_value, volume;
- unsigned int reg_value;
-
- volume = min((value + vol_desc->init_volume), (unsigned int)AW88261_MUTE_VOL);
- real_value = DB_TO_REG_VAL(volume);
-
- regmap_read(aw_dev->regmap, AW88261_SYSCTRL2_REG, &reg_value);
-
- real_value = (real_value | (reg_value & AW88261_VOL_START_MASK));
-
- dev_dbg(aw_dev->dev, "value 0x%x , real_value:0x%x", value, real_value);
-
- regmap_write(aw_dev->regmap, AW88261_SYSCTRL2_REG, real_value);
-}
-
-static void aw88261_dev_fade_in(struct aw_device *aw_dev)
-{
- struct aw_volume_desc *desc = &aw_dev->volume_desc;
- int fade_in_vol = desc->ctl_volume;
- int fade_step = aw_dev->fade_step;
- int i;
-
- if (fade_step == 0 || aw_dev->fade_in_time == 0) {
- aw88261_dev_set_volume(aw_dev, fade_in_vol);
- return;
- }
-
- for (i = AW88261_MUTE_VOL; i >= fade_in_vol; i -= fade_step) {
- aw88261_dev_set_volume(aw_dev, i);
- usleep_range(aw_dev->fade_in_time,
- aw_dev->fade_in_time + 10);
- }
-
- if (i != fade_in_vol)
- aw88261_dev_set_volume(aw_dev, fade_in_vol);
-}
-
-static void aw88261_dev_fade_out(struct aw_device *aw_dev)
-{
- struct aw_volume_desc *desc = &aw_dev->volume_desc;
- int fade_step = aw_dev->fade_step;
- int i;
-
- if (fade_step == 0 || aw_dev->fade_out_time == 0) {
- aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL);
- return;
- }
+ unsigned int volume = min(value, (unsigned int)AW88261_MUTE_VOL);
- for (i = desc->ctl_volume; i <= AW88261_MUTE_VOL; i += fade_step) {
- aw88261_dev_set_volume(aw_dev, i);
- usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10);
- }
-
- if (i != AW88261_MUTE_VOL) {
- aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL);
- usleep_range(aw_dev->fade_out_time, aw_dev->fade_out_time + 10);
- }
+ regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL2_REG,
+ ~AW88261_VOL_MASK, DB_TO_REG_VAL(volume));
}
static void aw88261_dev_i2s_tx_enable(struct aw_device *aw_dev, bool flag)
@@ -120,13 +69,13 @@ static void aw88261_dev_amppd(struct aw_device *aw_dev, bool amppd)
static void aw88261_dev_mute(struct aw_device *aw_dev, bool is_mute)
{
if (is_mute) {
- aw88261_dev_fade_out(aw_dev);
+ aw88261_dev_set_volume(aw_dev, AW88261_MUTE_VOL);
regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG,
~AW88261_HMUTE_MASK, AW88261_HMUTE_ENABLE_VALUE);
} else {
regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG,
~AW88261_HMUTE_MASK, AW88261_HMUTE_DISABLE_VALUE);
- aw88261_dev_fade_in(aw_dev);
+ aw88261_dev_set_volume(aw_dev, aw_dev->volume_desc.ctl_volume);
}
}
@@ -151,21 +100,21 @@ static int aw88261_dev_get_iis_status(struct aw_device *aw_dev)
if (ret)
return ret;
if ((reg_val & AW88261_BIT_PLL_CHECK) != AW88261_BIT_PLL_CHECK) {
- dev_err(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val);
+ dev_dbg(aw_dev->dev, "check pll lock fail,reg_val:0x%04x", reg_val);
return -EINVAL;
}
return ret;
}
-static int aw88261_dev_check_mode1_pll(struct aw_device *aw_dev)
+static int aw88261_dev_check_pll(struct aw_device *aw_dev)
{
int ret, i;
for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) {
ret = aw88261_dev_get_iis_status(aw_dev);
if (ret) {
- dev_err(aw_dev->dev, "mode1 iis signal check error");
+ dev_dbg(aw_dev->dev, "mode1 iis signal check error");
usleep_range(AW88261_2000_US, AW88261_2000_US + 10);
} else {
return ret;
@@ -175,71 +124,74 @@ static int aw88261_dev_check_mode1_pll(struct aw_device *aw_dev)
return -EPERM;
}
-static int aw88261_dev_check_mode2_pll(struct aw_device *aw_dev)
+static int aw88261_dev_configure_syspll(struct aw88261 *aw88261)
{
- unsigned int reg_val;
- int ret, i;
+ struct aw_device *aw_dev = aw88261->aw_pa;
+ int ret;
- ret = regmap_read(aw_dev->regmap, AW88261_PLLCTRL1_REG, &reg_val);
+ /* Configure TDM slots (I2S is represented as no slots) */
+ ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL2_REG,
+ ~AW88261_SLOT_NUM_MASK, aw88261->slot_num_value);
if (ret)
return ret;
- reg_val &= (~AW88261_CCO_MUX_MASK);
- if (reg_val == AW88261_CCO_MUX_DIVIDED_VALUE) {
- dev_dbg(aw_dev->dev, "CCO_MUX is already divider");
- return -EPERM;
- }
+ ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL2_REG,
+ ~AW88261_I2S_TX_SLOTVLD_MASK,
+ aw88261->tx_slotvld_mask);
+ if (ret)
+ return ret;
- /* change mode2 */
- ret = regmap_update_bits(aw_dev->regmap, AW88261_PLLCTRL1_REG,
- ~AW88261_CCO_MUX_MASK, AW88261_CCO_MUX_DIVIDED_VALUE);
+ ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL2_REG,
+ ~AW88261_I2S_RXL_SLOTVLD_MASK,
+ aw88261->rxl_slotvld_mask);
if (ret)
return ret;
- for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) {
- ret = aw88261_dev_get_iis_status(aw_dev);
- if (ret) {
- dev_err(aw_dev->dev, "mode2 iis signal check error");
- usleep_range(AW88261_2000_US, AW88261_2000_US + 10);
- } else {
- break;
- }
- }
+ ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL2_REG,
+ ~AW88261_I2S_RXR_SLOTVLD_MASK,
+ aw88261->rxr_slotvld_mask);
+ if (ret)
+ return ret;
- /* change mode1 */
+ /* PLL divider must be used for 8/16/32 kHz modes */
ret = regmap_update_bits(aw_dev->regmap, AW88261_PLLCTRL1_REG,
- ~AW88261_CCO_MUX_MASK, AW88261_CCO_MUX_BYPASS_VALUE);
- if (ret == 0) {
- usleep_range(AW88261_2000_US, AW88261_2000_US + 10);
- for (i = 0; i < AW88261_DEV_SYSST_CHECK_MAX; i++) {
- ret = aw88261_dev_check_mode1_pll(aw_dev);
- if (ret) {
- dev_err(aw_dev->dev, "mode2 switch to mode1, iis signal check error");
- usleep_range(AW88261_2000_US, AW88261_2000_US + 10);
- } else {
- break;
- }
- }
- }
+ ~AW88261_CCO_MUX_MASK, aw88261->cco_mux_value);
+ if (ret)
+ return ret;
- return ret;
-}
+ /* The word clock (WCK) defines the beginning of a frame */
+ ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL1_REG,
+ ~AW88261_I2SSR_MASK, aw88261->sr_value);
+ if (ret)
+ return ret;
-static int aw88261_dev_check_syspll(struct aw_device *aw_dev)
-{
- int ret;
+ /* The bit clock (BCK) defines the length of a frame */
+ ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL1_REG,
+ ~AW88261_I2SBCK_MASK,
+ (aw88261->tdm_bck_value != AW88261_TDM_BCK_UNSET)
+ ? aw88261->tdm_bck_value : aw88261->bck_value);
+ if (ret)
+ return ret;
- ret = aw88261_dev_check_mode1_pll(aw_dev);
- if (ret) {
- dev_dbg(aw_dev->dev, "mode1 check iis failed try switch to mode2 check");
- ret = aw88261_dev_check_mode2_pll(aw_dev);
- if (ret) {
- dev_err(aw_dev->dev, "mode2 check iis failed");
- return ret;
- }
- }
+ /* The logical frame size is the width of data for 1 slot */
+ ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL1_REG,
+ ~AW88261_I2SFS_MASK, aw88261->fs_value);
+ if (ret)
+ return ret;
- return ret;
+ /* The I2S interface mode (Philips standard, LSB/MSB justified) */
+ ret = regmap_update_bits(aw_dev->regmap, AW88261_I2SCTRL1_REG,
+ ~AW88261_I2SMD_MASK, aw88261->md_value);
+ if (ret)
+ return ret;
+
+ /* The polarity of the bit clock (BCK) */
+ ret = regmap_update_bits(aw_dev->regmap, AW88261_SYSCTRL_REG,
+ ~AW88261_BCKINV_MASK, aw88261->bck_inv_value);
+ if (ret)
+ return ret;
+
+ return aw88261_dev_check_pll(aw_dev);
}
static int aw88261_dev_check_sysst(struct aw_device *aw_dev)
@@ -256,7 +208,7 @@ static int aw88261_dev_check_sysst(struct aw_device *aw_dev)
check_val = reg_val & (~AW88261_BIT_SYSST_CHECK_MASK)
& AW88261_BIT_SYSST_CHECK;
if (check_val != AW88261_BIT_SYSST_CHECK) {
- dev_err(aw_dev->dev, "check sysst fail, reg_val=0x%04x, check:0x%x",
+ dev_dbg(aw_dev->dev, "check sysst fail, reg_val=0x%04x, check:0x%x",
reg_val, AW88261_BIT_SYSST_CHECK);
usleep_range(AW88261_2000_US, AW88261_2000_US + 10);
} else {
@@ -284,22 +236,22 @@ static void aw88261_reg_force_set(struct aw88261 *aw88261)
if (aw88261->frcset_en == AW88261_FRCSET_ENABLE) {
/* set FORCE_PWM */
regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL3_REG,
- AW88261_FORCE_PWM_MASK, AW88261_FORCE_PWM_FORCEMINUS_PWM_VALUE);
+ ~AW88261_FORCE_PWM_MASK, AW88261_FORCE_PWM_FORCEMINUS_PWM_VALUE);
/* set BOOST_OS_WIDTH */
regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL5_REG,
- AW88261_BST_OS_WIDTH_MASK, AW88261_BST_OS_WIDTH_50NS_VALUE);
+ ~AW88261_BST_OS_WIDTH_MASK, AW88261_BST_OS_WIDTH_50NS_VALUE);
/* set BURST_LOOPR */
regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL6_REG,
- AW88261_BST_LOOPR_MASK, AW88261_BST_LOOPR_340K_VALUE);
+ ~AW88261_BST_LOOPR_MASK, AW88261_BST_LOOPR_340K_VALUE);
/* set RSQN_DLY */
regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL7_REG,
- AW88261_RSQN_DLY_MASK, AW88261_RSQN_DLY_35NS_VALUE);
+ ~AW88261_RSQN_DLY_MASK, AW88261_RSQN_DLY_35NS_VALUE);
/* set BURST_SSMODE */
regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL8_REG,
- AW88261_BURST_SSMODE_MASK, AW88261_BURST_SSMODE_FAST_VALUE);
+ ~AW88261_BURST_SSMODE_MASK, AW88261_BURST_SSMODE_FAST_VALUE);
/* set BST_BURST */
regmap_update_bits(aw88261->regmap, AW88261_BSTCTRL9_REG,
- AW88261_BST_BURST_MASK, AW88261_BST_BURST_30MA_VALUE);
+ ~AW88261_BST_BURST_MASK, AW88261_BST_BURST_30MA_VALUE);
} else {
dev_dbg(aw88261->aw_pa->dev, "needn't set reg value");
}
@@ -550,7 +502,7 @@ static int aw88261_dev_start(struct aw88261 *aw88261)
int ret;
if (aw_dev->status == AW88261_DEV_PW_ON) {
- dev_info(aw_dev->dev, "already power on");
+ dev_dbg(aw_dev->dev, "already power on");
return 0;
}
@@ -558,9 +510,9 @@ static int aw88261_dev_start(struct aw88261 *aw88261)
aw88261_dev_pwd(aw_dev, false);
usleep_range(AW88261_2000_US, AW88261_2000_US + 10);
- ret = aw88261_dev_check_syspll(aw_dev);
+ ret = aw88261_dev_configure_syspll(aw88261);
if (ret) {
- dev_err(aw_dev->dev, "pll check failed cannot start");
+ dev_dbg(aw_dev->dev, "pll check failed");
goto pll_check_fail;
}
@@ -571,7 +523,7 @@ static int aw88261_dev_start(struct aw88261 *aw88261)
/* check i2s status */
ret = aw88261_dev_check_sysst(aw_dev);
if (ret) {
- dev_err(aw_dev->dev, "sysst check failed");
+ dev_dbg(aw_dev->dev, "sysst check failed");
goto sysst_check_fail;
}
@@ -672,31 +624,25 @@ static void aw88261_start_pa(struct aw88261 *aw88261)
for (i = 0; i < AW88261_START_RETRIES; i++) {
ret = aw88261_reg_update(aw88261, aw88261->phase_sync);
if (ret) {
- dev_err(aw88261->aw_pa->dev, "fw update failed, cnt:%d\n", i);
+ dev_dbg(aw88261->aw_pa->dev,
+ "aw88261_reg_update failed, cnt:%d, ret:%d\n", i, ret);
continue;
}
ret = aw88261_dev_start(aw88261);
if (ret) {
- dev_err(aw88261->aw_pa->dev, "aw88261 device start failed. retry = %d", i);
+ dev_dbg(aw88261->aw_pa->dev,
+ "aw88261_dev_start failed, cnt:%d, ret:%d\n", i, ret);
continue;
} else {
- dev_info(aw88261->aw_pa->dev, "start success\n");
+ dev_dbg(aw88261->aw_pa->dev, "start success\n");
break;
}
}
+ if (ret != 0)
+ dev_err(aw88261->aw_pa->dev, "start failure (%d)\n", ret);
}
-static void aw88261_startup_work(struct work_struct *work)
-{
- struct aw88261 *aw88261 =
- container_of(work, struct aw88261, start_work.work);
-
- mutex_lock(&aw88261->lock);
- aw88261_start_pa(aw88261);
- mutex_unlock(&aw88261->lock);
-}
-
-static void aw88261_start(struct aw88261 *aw88261, bool sync_start)
+static void aw88261_start(struct aw88261 *aw88261)
{
if (aw88261->aw_pa->fw_status != AW88261_DEV_FW_OK)
return;
@@ -704,104 +650,248 @@ static void aw88261_start(struct aw88261 *aw88261, bool sync_start)
if (aw88261->aw_pa->status == AW88261_DEV_PW_ON)
return;
- if (sync_start == AW88261_SYNC_START)
- aw88261_start_pa(aw88261);
- else
- queue_delayed_work(system_dfl_wq,
- &aw88261->start_work,
- AW88261_START_WORK_DELAY_MS);
+ aw88261_start_pa(aw88261);
}
-static struct snd_soc_dai_driver aw88261_dai[] = {
- {
- .name = "aw88261-aif",
- .id = 1,
- .playback = {
- .stream_name = "Speaker_Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = AW88261_RATES,
- .formats = AW88261_FORMATS,
- },
- .capture = {
- .stream_name = "Speaker_Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = AW88261_RATES,
- .formats = AW88261_FORMATS,
- },
- },
-};
-
-static int aw88261_get_fade_in_time(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int aw88261_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_component *component = dai->component;
struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component);
- struct aw_device *aw_dev = aw88261->aw_pa;
- ucontrol->value.integer.value[0] = aw_dev->fade_in_time;
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ aw88261->bck_inv_value = AW88261_BCKINV_NOT_INVERT_VALUE;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ aw88261->bck_inv_value = AW88261_BCKINV_INVERTED_VALUE;
+ break;
+ default:
+ dev_err(aw88261->aw_pa->dev, "unsupported invert mode 0x%x\n",
+ fmt & SND_SOC_DAIFMT_INV_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ case SND_SOC_DAIFMT_DSP_A:
+ aw88261->md_value = AW88261_I2SMD_PHILIPS_STANDARD_VALUE;
+ break;
+ case SND_SOC_DAIFMT_MSB:
+ case SND_SOC_DAIFMT_DSP_B:
+ aw88261->md_value = AW88261_I2SMD_MSB_JUSTIFIED_VALUE;
+ break;
+ case SND_SOC_DAIFMT_LSB:
+ aw88261->md_value = AW88261_I2SMD_LSB_JUSTIFIED_VALUE;
+ break;
+ default:
+ dev_err(aw88261->aw_pa->dev, "unsupported DAI format 0x%x\n",
+ fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ return -EINVAL;
+ }
return 0;
}
-static int aw88261_set_fade_in_time(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int aw88261_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
{
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_component *component = dai->component;
struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct aw_device *aw_dev = aw88261->aw_pa;
- int time;
- time = ucontrol->value.integer.value[0];
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ return 0;
- if (time < mc->min || time > mc->max)
+ aw88261->cco_mux_value = AW88261_CCO_MUX_BYPASS_VALUE;
+ switch (params_rate(params)) {
+ case 8000:
+ aw88261->sr_value = AW88261_I2SSR_8KHZ_VALUE;
+ aw88261->cco_mux_value = AW88261_CCO_MUX_DIVIDED_VALUE;
+ break;
+ case 11025:
+ aw88261->sr_value = AW88261_I2SSR_11P025KHZ_VALUE;
+ break;
+ case 12000:
+ aw88261->sr_value = AW88261_I2SSR_12KHZ_VALUE;
+ break;
+ case 16000:
+ aw88261->sr_value = AW88261_I2SSR_16KHZ_VALUE;
+ aw88261->cco_mux_value = AW88261_CCO_MUX_DIVIDED_VALUE;
+ break;
+ case 22050:
+ aw88261->sr_value = AW88261_I2SSR_22P05KHZ_VALUE;
+ break;
+ case 24000:
+ aw88261->sr_value = AW88261_I2SSR_24KHZ_VALUE;
+ break;
+ case 32000:
+ aw88261->sr_value = AW88261_I2SSR_32KHZ_VALUE;
+ aw88261->cco_mux_value = AW88261_CCO_MUX_DIVIDED_VALUE;
+ break;
+ case 44100:
+ aw88261->sr_value = AW88261_I2SSR_44P1KHZ_VALUE;
+ break;
+ case 48000:
+ aw88261->sr_value = AW88261_I2SSR_48KHZ_VALUE;
+ break;
+ case 96000:
+ aw88261->sr_value = AW88261_I2SSR_96KHZ_VALUE;
+ break;
+ case 192000:
+ aw88261->sr_value = AW88261_I2SSR_192KHZ_VALUE;
+ break;
+ default:
+ dev_err(aw88261->aw_pa->dev, "unsupported sample rate %d\n",
+ params_rate(params));
return -EINVAL;
+ }
- if (time != aw_dev->fade_in_time) {
- aw_dev->fade_in_time = time;
- return 1;
+ switch (params_width(params)) {
+ case 16:
+ aw88261->fs_value = AW88261_I2SFS_16_BITS_VALUE;
+ break;
+ case 20:
+ aw88261->fs_value = AW88261_I2SFS_20_BITS_VALUE;
+ break;
+ case 24:
+ aw88261->fs_value = AW88261_I2SFS_24_BITS_VALUE;
+ break;
+ case 32:
+ aw88261->fs_value = AW88261_I2SFS_32_BITS_VALUE;
+ break;
+ default:
+ dev_err(aw88261->aw_pa->dev, "unsupported bit width %d\n",
+ params_width(params));
+ return -EINVAL;
+ }
+
+ switch (params_physical_width(params)) {
+ case 16:
+ aw88261->bck_value = AW88261_I2SBCK_32FS_VALUE;
+ break;
+ case 24:
+ aw88261->bck_value = AW88261_I2SBCK_48FS_VALUE;
+ break;
+ case 32:
+ aw88261->bck_value = AW88261_I2SBCK_64FS_VALUE;
+ break;
+ default:
+ dev_err(aw88261->aw_pa->dev, "unsupported physical bit width %d\n",
+ params_physical_width(params));
+ return -EINVAL;
}
return 0;
}
-static int aw88261_get_fade_out_time(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int aw88261_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 = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_component *component = dai->component;
struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component);
- struct aw_device *aw_dev = aw88261->aw_pa;
+ int chan;
+
+ switch (slots) {
+ case 0:
+ /* Just reset everything TDM related to I2S values */
+ aw88261->slot_num_value = AW88261_SLOT_NUM_I2S_MODE_VALUE;
+ aw88261->tdm_bck_value = AW88261_TDM_BCK_UNSET;
+ aw88261->tx_slotvld_mask = 0 << AW88261_I2S_TX_SLOTVLD_START_BIT;
+ aw88261->rxl_slotvld_mask = 0 << AW88261_I2S_RXL_SLOTVLD_START_BIT;
+ aw88261->rxr_slotvld_mask = 1 << AW88261_I2S_RXR_SLOTVLD_START_BIT;
+ return 0;
+ case 1:
+ aw88261->slot_num_value = AW88261_SLOT_NUM_TDM1S_VALUE;
+ break;
+ case 2:
+ aw88261->slot_num_value = AW88261_SLOT_NUM_TDM2S_VALUE;
+ break;
+ case 4:
+ aw88261->slot_num_value = AW88261_SLOT_NUM_TDM4S_VALUE;
+ break;
+ case 6:
+ aw88261->slot_num_value = AW88261_SLOT_NUM_TDM6S_VALUE;
+ break;
+ case 8:
+ aw88261->slot_num_value = AW88261_SLOT_NUM_TDM8S_VALUE;
+ break;
+ case 16:
+ aw88261->slot_num_value = AW88261_SLOT_NUM_TDM16S_VALUE;
+ break;
+ default:
+ dev_err(aw88261->aw_pa->dev, "unsupported slot count %d\n", slots);
+ return -EINVAL;
+ }
- ucontrol->value.integer.value[0] = aw_dev->fade_out_time;
+ switch (slot_width) {
+ case 16:
+ aw88261->tdm_bck_value = AW88261_I2SBCK_32FS_VALUE;
+ break;
+ case 20:
+ case 24:
+ aw88261->tdm_bck_value = AW88261_I2SBCK_48FS_VALUE;
+ break;
+ case 32:
+ aw88261->tdm_bck_value = AW88261_I2SBCK_64FS_VALUE;
+ break;
+ default:
+ dev_err(aw88261->aw_pa->dev, "unsupported slot width %d\n",
+ slot_width);
+ return -EINVAL;
+ }
- return 0;
-}
+ if (tx_mask != 0) {
+ if ((chan = __ffs(tx_mask)) > 16)
+ return -EINVAL;
-static int aw88261_set_fade_out_time(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
- struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct aw_device *aw_dev = aw88261->aw_pa;
- int time;
+ aw88261->tx_slotvld_mask = chan << AW88261_I2S_TX_SLOTVLD_START_BIT;
+ }
- time = ucontrol->value.integer.value[0];
- if (time < mc->min || time > mc->max)
- return -EINVAL;
+ if (rx_mask != 0) {
+ if ((chan = __ffs(rx_mask)) > 16)
+ return -EINVAL;
- if (time != aw_dev->fade_out_time) {
- aw_dev->fade_out_time = time;
- return 1;
+ aw88261->rxl_slotvld_mask = chan << AW88261_I2S_RXL_SLOTVLD_START_BIT;
+ }
+
+ if ((rx_mask & ~BIT(chan)) != 0) {
+ if ((chan = __ffs(rx_mask & ~BIT(chan))) > 16)
+ return -EINVAL;
+
+ aw88261->rxr_slotvld_mask = chan << AW88261_I2S_RXR_SLOTVLD_START_BIT;
}
return 0;
}
+static const struct snd_soc_dai_ops aw88261_dai_ops = {
+ .set_fmt = aw88261_set_fmt,
+ .hw_params = aw88261_hw_params,
+ .set_tdm_slot = aw88261_set_tdm_slot,
+};
+
+static struct snd_soc_dai_driver aw88261_dai[] = {
+ {
+ .name = "aw88261-aif",
+ .id = 1,
+ .playback = {
+ .stream_name = "Speaker_Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AW88261_RATES,
+ .formats = AW88261_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Speaker_Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AW88261_RATES,
+ .formats = AW88261_FORMATS,
+ },
+ .ops = &aw88261_dai_ops,
+ },
+};
+
static int aw88261_dev_set_profile_index(struct aw_device *aw_dev, int index)
{
/* check the index whether is valid */
@@ -880,7 +970,7 @@ static int aw88261_profile_set(struct snd_kcontrol *kcontrol,
if (aw88261->aw_pa->status) {
aw88261_dev_stop(aw88261->aw_pa);
- aw88261_start(aw88261, AW88261_SYNC_START);
+ aw88261_start(aw88261);
}
mutex_unlock(&aw88261->lock);
@@ -895,7 +985,8 @@ static int aw88261_volume_get(struct snd_kcontrol *kcontrol,
struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec);
struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc;
- ucontrol->value.integer.value[0] = vol_desc->ctl_volume;
+ ucontrol->value.integer.value[0] =
+ (AW88261_MUTE_VOL - vol_desc->ctl_volume) / 2;
return 0;
}
@@ -908,13 +999,13 @@ static int aw88261_volume_set(struct snd_kcontrol *kcontrol,
struct aw_volume_desc *vol_desc = &aw88261->aw_pa->volume_desc;
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- int value;
-
- value = ucontrol->value.integer.value[0];
+ int value = ucontrol->value.integer.value[0];
if (value < mc->min || value > mc->max)
return -EINVAL;
+ value = AW88261_MUTE_VOL - (value * 2);
+
if (vol_desc->ctl_volume != value) {
vol_desc->ctl_volume = value;
aw88261_dev_set_volume(aw88261->aw_pa, vol_desc->ctl_volume);
@@ -925,48 +1016,18 @@ static int aw88261_volume_set(struct snd_kcontrol *kcontrol,
return 0;
}
-static int aw88261_get_fade_step(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_component *codec = snd_kcontrol_chip(kcontrol);
- struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec);
-
- ucontrol->value.integer.value[0] = aw88261->aw_pa->fade_step;
-
- return 0;
-}
-
-static int aw88261_set_fade_step(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_component *codec = snd_kcontrol_chip(kcontrol);
- struct aw88261 *aw88261 = snd_soc_component_get_drvdata(codec);
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- int value;
-
- value = ucontrol->value.integer.value[0];
- if (value < mc->min || value > mc->max)
- return -EINVAL;
-
- if (aw88261->aw_pa->fade_step != value) {
- aw88261->aw_pa->fade_step = value;
- return 1;
- }
-
- return 0;
-}
+/*
+ * The field contains 4 bits in units of 6dB + 6 bits in units of 0.125dB
+ * which is too precise for TLV (!) so we have to multiply the scale by 2.
+ *
+ * The range is clamped at -90dB to prevent overflowing the 4-bit part.
+ */
+static const DECLARE_TLV_DB_SCALE(volume_tlv, -9000, 25, 0);
static const struct snd_kcontrol_new aw88261_controls[] = {
- SOC_SINGLE_EXT("PCM Playback Volume", AW88261_SYSCTRL2_REG,
- 6, AW88261_MUTE_VOL, 0, aw88261_volume_get,
- aw88261_volume_set),
- SOC_SINGLE_EXT("Fade Step", 0, 0, AW88261_MUTE_VOL, 0,
- aw88261_get_fade_step, aw88261_set_fade_step),
- SOC_SINGLE_EXT("Volume Ramp Up Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN,
- aw88261_get_fade_in_time, aw88261_set_fade_in_time),
- SOC_SINGLE_EXT("Volume Ramp Down Step", 0, 0, FADE_TIME_MAX, FADE_TIME_MIN,
- aw88261_get_fade_out_time, aw88261_set_fade_out_time),
+ SOC_SINGLE_EXT_TLV("PCM Playback Volume", AW88261_SYSCTRL2_REG,
+ 6, AW88261_CTL_MAX_VOL, 1,
+ aw88261_volume_get, aw88261_volume_set, volume_tlv),
AW88261_PROFILE_EXT("Profile Set", aw88261_profile_info,
aw88261_profile_get, aw88261_profile_set),
};
@@ -980,7 +1041,7 @@ static int aw88261_playback_event(struct snd_soc_dapm_widget *w,
mutex_lock(&aw88261->lock);
switch (event) {
case SND_SOC_DAPM_PRE_PMU:
- aw88261_start(aw88261, AW88261_ASYNC_START);
+ aw88261_start(aw88261);
break;
case SND_SOC_DAPM_POST_PMD:
aw88261_dev_stop(aw88261->aw_pa);
@@ -1057,8 +1118,6 @@ static int aw88261_dev_init(struct aw88261 *aw88261, struct aw_container *aw_cfg
if (ret)
return ret;
- aw_dev->fade_in_time = AW88261_500_US;
- aw_dev->fade_out_time = AW88261_500_US;
aw_dev->prof_cur = AW88261_INIT_PROFILE;
aw_dev->prof_index = AW88261_INIT_PROFILE;
@@ -1094,6 +1153,7 @@ static int aw88261_dev_init(struct aw88261 *aw88261, struct aw_container *aw_cfg
static int aw88261_request_firmware_file(struct aw88261 *aw88261)
{
const struct firmware *cont = NULL;
+ struct aw_container *aw_cfg;
const char *fw_name;
int ret;
@@ -1111,15 +1171,17 @@ static int aw88261_request_firmware_file(struct aw88261 *aw88261)
dev_info(aw88261->aw_pa->dev, "loaded %s - size: %zu\n",
fw_name, cont ? cont->size : 0);
- aw88261->aw_cfg = devm_kzalloc(aw88261->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL);
- if (!aw88261->aw_cfg) {
+ aw_cfg = devm_kzalloc(aw88261->aw_pa->dev, struct_size(aw_cfg, data, cont->size), GFP_KERNEL);
+ if (!aw_cfg) {
release_firmware(cont);
return -ENOMEM;
}
- aw88261->aw_cfg->len = (int)cont->size;
- memcpy(aw88261->aw_cfg->data, cont->data, cont->size);
+ aw_cfg->len = (int)cont->size;
+ memcpy(aw_cfg->data, cont->data, cont->size);
release_firmware(cont);
+ aw88261->aw_cfg = aw_cfg;
+
ret = aw88395_dev_load_acf_check(aw88261->aw_pa, aw88261->aw_cfg);
if (ret) {
dev_err(aw88261->aw_pa->dev, "load [%s] failed !", fw_name);
@@ -1142,8 +1204,6 @@ static int aw88261_codec_probe(struct snd_soc_component *component)
struct aw88261 *aw88261 = snd_soc_component_get_drvdata(component);
int ret;
- INIT_DELAYED_WORK(&aw88261->start_work, aw88261_startup_work);
-
ret = aw88261_request_firmware_file(aw88261);
if (ret)
return dev_err_probe(aw88261->aw_pa->dev, ret,
@@ -1167,16 +1227,8 @@ static int aw88261_codec_probe(struct snd_soc_component *component)
return ret;
}
-static void aw88261_codec_remove(struct snd_soc_component *aw_codec)
-{
- struct aw88261 *aw88261 = snd_soc_component_get_drvdata(aw_codec);
-
- cancel_delayed_work_sync(&aw88261->start_work);
-}
-
static const struct snd_soc_component_driver soc_codec_dev_aw88261 = {
.probe = aw88261_codec_probe,
- .remove = aw88261_codec_remove,
};
static void aw88261_parse_channel_dt(struct aw88261 *aw88261)
@@ -1208,7 +1260,7 @@ static int aw88261_init(struct aw88261 *aw88261, struct i2c_client *i2c, struct
return ret;
}
if (chip_id != AW88261_CHIP_ID) {
- dev_err(&i2c->dev, "unsupported device");
+ dev_err(&i2c->dev, "unsupported device id = %x", chip_id);
return -ENXIO;
}
@@ -1229,8 +1281,7 @@ static int aw88261_init(struct aw88261 *aw88261, struct i2c_client *i2c, struct
aw_dev->prof_info.prof_type = AW88395_DEV_NONE_TYPE_ID;
aw_dev->channel = 0;
aw_dev->fw_status = AW88261_DEV_FW_FAILED;
- aw_dev->fade_step = AW88261_VOLUME_STEP_DB;
- aw_dev->volume_desc.ctl_volume = AW88261_VOL_DEFAULT_VALUE;
+ aw_dev->volume_desc.ctl_volume = AW88261_CTL_DEFAULT_VOL;
aw_dev->volume_desc.mute_volume = AW88261_MUTE_VOL;
aw88261_parse_channel_dt(aw88261);
@@ -1249,6 +1300,17 @@ static int aw88261_i2c_probe(struct i2c_client *i2c)
if (!aw88261)
return -ENOMEM;
+ /* set defaults */
+ aw88261->slot_num_value = AW88261_SLOT_NUM_I2S_MODE_VALUE;
+ aw88261->sr_value = AW88261_I2SSR_48KHZ_VALUE;
+ aw88261->cco_mux_value = AW88261_CCO_MUX_BYPASS_VALUE;
+ aw88261->fs_value = AW88261_I2SFS_24_BITS_VALUE;
+ aw88261->bck_value = AW88261_I2SBCK_64FS_VALUE;
+ aw88261->bck_inv_value = AW88261_BCKINV_NOT_INVERT_VALUE;
+ aw88261->tdm_bck_value = AW88261_TDM_BCK_UNSET;
+ aw88261->md_value = AW88261_I2SMD_PHILIPS_STANDARD_VALUE;
+ aw88261->rxr_slotvld_mask = 1 << AW88261_I2S_RXR_SLOTVLD_START_BIT;
+
mutex_init(&aw88261->lock);
i2c_set_clientdata(i2c, aw88261);
@@ -1274,7 +1336,7 @@ static int aw88261_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id aw88261_i2c_id[] = {
- { "aw88261" },
+ { .name = "aw88261" },
{ }
};
MODULE_DEVICE_TABLE(i2c, aw88261_i2c_id);
diff --git a/sound/soc/codecs/aw88261.h b/sound/soc/codecs/aw88261.h
index 1fee589608d6..270ccf375f36 100644
--- a/sound/soc/codecs/aw88261.h
+++ b/sound/soc/codecs/aw88261.h
@@ -116,6 +116,19 @@
#define AW88261_VCALK_SHIFT (0)
#define AW88261_VCALKL_SHIFT (0)
+#define AW88261_BCKINV_START_BIT (4)
+#define AW88261_BCKINV_BITS_LEN (1)
+#define AW88261_BCKINV_MASK \
+ (~(((1<<AW88261_BCKINV_BITS_LEN)-1) << AW88261_BCKINV_START_BIT))
+
+#define AW88261_BCKINV_NOT_INVERT (0)
+#define AW88261_BCKINV_NOT_INVERT_VALUE \
+ (AW88261_BCKINV_NOT_INVERT << AW88261_BCKINV_START_BIT)
+
+#define AW88261_BCKINV_INVERTED (1)
+#define AW88261_BCKINV_INVERTED_VALUE \
+ (AW88261_BCKINV_INVERTED << AW88261_BCKINV_START_BIT)
+
#define AW88261_AMPPD_START_BIT (1)
#define AW88261_AMPPD_BITS_LEN (1)
#define AW88261_AMPPD_MASK \
@@ -249,7 +262,8 @@
#define AW88261_VOL_MASK \
(~(((1<<AW88261_VOL_BITS_LEN)-1) << AW88261_VOL_START_BIT))
-#define AW88261_VOL_DEFAULT_VALUE (0)
+#define AW88261_CTL_MAX_VOL (AW88261_MUTE_VOL / 2)
+#define AW88261_CTL_DEFAULT_VOL (AW88261_CTL_MAX_VOL / 2)
#define AW88261_I2STXEN_START_BIT (6)
#define AW88261_I2STXEN_BITS_LEN (1)
@@ -264,7 +278,148 @@
#define AW88261_I2STXEN_ENABLE_VALUE \
(AW88261_I2STXEN_ENABLE << AW88261_I2STXEN_START_BIT)
-#define AW88261_CCO_MUX_START_BIT (14)
+#define AW88261_I2SMD_START_BIT (8)
+#define AW88261_I2SMD_BITS_LEN (2)
+#define AW88261_I2SMD_MASK \
+ (~(((1<<AW88261_I2SMD_BITS_LEN)-1) << AW88261_I2SMD_START_BIT))
+
+#define AW88261_I2SMD_PHILIPS_STANDARD (0)
+#define AW88261_I2SMD_PHILIPS_STANDARD_VALUE \
+ (AW88261_I2SMD_PHILIPS_STANDARD << AW88261_I2SMD_START_BIT)
+
+#define AW88261_I2SMD_MSB_JUSTIFIED (1)
+#define AW88261_I2SMD_MSB_JUSTIFIED_VALUE \
+ (AW88261_I2SMD_MSB_JUSTIFIED << AW88261_I2SMD_START_BIT)
+
+#define AW88261_I2SMD_LSB_JUSTIFIED (2)
+#define AW88261_I2SMD_LSB_JUSTIFIED_VALUE \
+ (AW88261_I2SMD_LSB_JUSTIFIED << AW88261_I2SMD_START_BIT)
+
+#define AW88261_I2SFS_START_BIT (6)
+#define AW88261_I2SFS_BITS_LEN (2)
+#define AW88261_I2SFS_MASK \
+ (~(((1<<AW88261_I2SFS_BITS_LEN)-1)<<AW88261_I2SFS_START_BIT))
+
+#define AW88261_I2SFS_16_BITS (0)
+#define AW88261_I2SFS_16_BITS_VALUE \
+ (AW88261_I2SFS_16_BITS << AW88261_I2SFS_START_BIT)
+#define AW88261_I2SFS_20_BITS (1)
+#define AW88261_I2SFS_20_BITS_VALUE \
+ (AW88261_I2SFS_20_BITS << AW88261_I2SFS_START_BIT)
+#define AW88261_I2SFS_24_BITS (2)
+#define AW88261_I2SFS_24_BITS_VALUE \
+ (AW88261_I2SFS_24_BITS << AW88261_I2SFS_START_BIT)
+#define AW88261_I2SFS_32_BITS (3)
+#define AW88261_I2SFS_32_BITS_VALUE \
+ (AW88261_I2SFS_32_BITS << AW88261_I2SFS_START_BIT)
+
+#define AW88261_I2SBCK_START_BIT (4)
+#define AW88261_I2SBCK_BITS_LEN (2)
+#define AW88261_I2SBCK_MASK \
+ (~(((1<<AW88261_I2SBCK_BITS_LEN)-1) << AW88261_I2SBCK_START_BIT))
+
+#define AW88261_I2SBCK_32FS (0)
+#define AW88261_I2SBCK_32FS_VALUE \
+ (AW88261_I2SBCK_32FS << AW88261_I2SBCK_START_BIT)
+
+#define AW88261_I2SBCK_48FS (1)
+#define AW88261_I2SBCK_48FS_VALUE \
+ (AW88261_I2SBCK_48FS << AW88261_I2SBCK_START_BIT)
+
+#define AW88261_I2SBCK_64FS (2)
+#define AW88261_I2SBCK_64FS_VALUE \
+ (AW88261_I2SBCK_64FS << AW88261_I2SBCK_START_BIT)
+
+#define AW88261_TDM_BCK_UNSET UINT_MAX
+
+#define AW88261_I2SSR_START_BIT (0)
+#define AW88261_I2SSR_BITS_LEN (4)
+#define AW88261_I2SSR_MASK \
+ (~(((1<<AW88261_I2SSR_BITS_LEN)-1) << AW88261_I2SSR_START_BIT))
+
+#define AW88261_I2SSR_8KHZ (0)
+#define AW88261_I2SSR_8KHZ_VALUE \
+ (AW88261_I2SSR_8KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_11P025KHZ (1)
+#define AW88261_I2SSR_11P025KHZ_VALUE \
+ (AW88261_I2SSR_11P025KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_12KHZ (2)
+#define AW88261_I2SSR_12KHZ_VALUE \
+ (AW88261_I2SSR_12KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_16KHZ (3)
+#define AW88261_I2SSR_16KHZ_VALUE \
+ (AW88261_I2SSR_16KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_22P05KHZ (4)
+#define AW88261_I2SSR_22P05KHZ_VALUE \
+ (AW88261_I2SSR_22P05KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_24KHZ (5)
+#define AW88261_I2SSR_24KHZ_VALUE \
+ (AW88261_I2SSR_24KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_32KHZ (6)
+#define AW88261_I2SSR_32KHZ_VALUE \
+ (AW88261_I2SSR_32KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_44P1KHZ (7)
+#define AW88261_I2SSR_44P1KHZ_VALUE \
+ (AW88261_I2SSR_44P1KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_48KHZ (8)
+#define AW88261_I2SSR_48KHZ_VALUE \
+ (AW88261_I2SSR_48KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_96KHZ (9)
+#define AW88261_I2SSR_96KHZ_VALUE \
+ (AW88261_I2SSR_96KHZ << AW88261_I2SSR_START_BIT)
+#define AW88261_I2SSR_192KHZ (10)
+#define AW88261_I2SSR_192KHZ_VALUE \
+ (AW88261_I2SSR_192KHZ << AW88261_I2SSR_START_BIT)
+
+#define AW88261_SLOT_NUM_START_BIT (12)
+#define AW88261_SLOT_NUM_BITS_LEN (3)
+#define AW88261_SLOT_NUM_MASK \
+ (~(((1<<AW88261_SLOT_NUM_BITS_LEN)-1) << AW88261_SLOT_NUM_START_BIT))
+
+#define AW88261_SLOT_NUM_I2S_MODE (0)
+#define AW88261_SLOT_NUM_I2S_MODE_VALUE \
+ (AW88261_SLOT_NUM_I2S_MODE << AW88261_SLOT_NUM_START_BIT)
+
+#define AW88261_SLOT_NUM_TDM1S (1)
+#define AW88261_SLOT_NUM_TDM1S_VALUE \
+ (AW88261_SLOT_NUM_TDM1S << AW88261_SLOT_NUM_START_BIT)
+
+#define AW88261_SLOT_NUM_TDM2S (2)
+#define AW88261_SLOT_NUM_TDM2S_VALUE \
+ (AW88261_SLOT_NUM_TDM2S << AW88261_SLOT_NUM_START_BIT)
+
+#define AW88261_SLOT_NUM_TDM4S (3)
+#define AW88261_SLOT_NUM_TDM4S_VALUE \
+ (AW88261_SLOT_NUM_TDM4S << AW88261_SLOT_NUM_START_BIT)
+
+#define AW88261_SLOT_NUM_TDM6S (4)
+#define AW88261_SLOT_NUM_TDM6S_VALUE \
+ (AW88261_SLOT_NUM_TDM6S << AW88261_SLOT_NUM_START_BIT)
+
+#define AW88261_SLOT_NUM_TDM8S (5)
+#define AW88261_SLOT_NUM_TDM8S_VALUE \
+ (AW88261_SLOT_NUM_TDM8S << AW88261_SLOT_NUM_START_BIT)
+
+#define AW88261_SLOT_NUM_TDM16S (6)
+#define AW88261_SLOT_NUM_TDM16S_VALUE \
+ (AW88261_SLOT_NUM_TDM16S << AW88261_SLOT_NUM_START_BIT)
+
+#define AW88261_I2S_TX_SLOTVLD_START_BIT (8)
+#define AW88261_I2S_TX_SLOTVLD_BITS_LEN (4)
+#define AW88261_I2S_TX_SLOTVLD_MASK \
+ (~(((1<<AW88261_I2S_TX_SLOTVLD_BITS_LEN)-1) << AW88261_I2S_TX_SLOTVLD_START_BIT))
+
+#define AW88261_I2S_RXR_SLOTVLD_START_BIT (4)
+#define AW88261_I2S_RXR_SLOTVLD_BITS_LEN (4)
+#define AW88261_I2S_RXR_SLOTVLD_MASK \
+ (~(((1<<AW88261_I2S_RXR_SLOTVLD_BITS_LEN)-1) << AW88261_I2S_RXR_SLOTVLD_START_BIT))
+
+#define AW88261_I2S_RXL_SLOTVLD_START_BIT (0)
+#define AW88261_I2S_RXL_SLOTVLD_BITS_LEN (4)
+#define AW88261_I2S_RXL_SLOTVLD_MASK \
+ (~(((1<<AW88261_I2S_RXL_SLOTVLD_BITS_LEN)-1) << AW88261_I2S_RXL_SLOTVLD_START_BIT))
+
+#define AW88261_CCO_MUX_START_BIT (6)
#define AW88261_CCO_MUX_BITS_LEN (1)
#define AW88261_CCO_MUX_MASK \
(~(((1<<AW88261_CCO_MUX_BITS_LEN)-1) << AW88261_CCO_MUX_START_BIT))
@@ -370,21 +525,20 @@
#define AW88261_START_RETRIES (5)
#define AW88261_START_WORK_DELAY_MS (0)
+/* NOTE: 192000 has a reg value donwstream but not listed in datasheet */
#define AW88261_RATES (SNDRV_PCM_RATE_8000_48000 | \
+ SNDRV_PCM_RATE_12000 | \
+ SNDRV_PCM_RATE_24000 | \
SNDRV_PCM_RATE_96000)
#define AW88261_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
-#define FADE_TIME_MAX 100000
-#define FADE_TIME_MIN 0
-
#define AW88261_DEV_DEFAULT_CH (0)
#define AW88261_ACF_FILE "aw88261_acf.bin"
#define AW88261_DEV_SYSST_CHECK_MAX (10)
#define AW88261_SOFT_RESET_VALUE (0x55aa)
#define AW88261_REG_TO_DB (0x3f)
-#define AW88261_VOL_START_MASK (0xfc00)
#define AW88261_INIT_PROFILE (0)
#define REG_VAL_TO_DB(value) ((((value) >> AW88261_VOL_6DB_START) * \
@@ -403,11 +557,6 @@
.put = profile_set, \
}
-enum {
- AW88261_SYNC_START = 0,
- AW88261_ASYNC_START,
-};
-
enum aw88261_id {
AW88261_CHIP_ID = 0x2113,
};
@@ -442,7 +591,6 @@ struct aw88261 {
struct aw_device *aw_pa;
struct mutex lock;
struct gpio_desc *reset_gpio;
- struct delayed_work start_work;
struct regmap *regmap;
struct aw_container *aw_cfg;
@@ -451,6 +599,19 @@ struct aw88261 {
unsigned int mute_st;
unsigned int amppd_st;
+ unsigned int sr_value;
+ unsigned int cco_mux_value;
+ unsigned int fs_value;
+ unsigned int bck_value;
+ unsigned int bck_inv_value;
+ unsigned int tdm_bck_value;
+ unsigned int md_value;
+
+ unsigned int slot_num_value;
+ unsigned int tx_slotvld_mask;
+ unsigned int rxl_slotvld_mask;
+ unsigned int rxr_slotvld_mask;
+
bool phase_sync;
};
diff --git a/sound/soc/codecs/aw88395/aw88395.c b/sound/soc/codecs/aw88395/aw88395.c
index dd09bac652f7..ee0e8bd8c54c 100644
--- a/sound/soc/codecs/aw88395/aw88395.c
+++ b/sound/soc/codecs/aw88395/aw88395.c
@@ -462,6 +462,7 @@ static void aw88395_hw_reset(struct aw88395 *aw88395)
static int aw88395_request_firmware_file(struct aw88395 *aw88395)
{
const struct firmware *cont = NULL;
+ struct aw_container *aw_cfg;
int ret;
aw88395->aw_pa->fw_status = AW88395_DEV_FW_FAILED;
@@ -475,15 +476,17 @@ static int aw88395_request_firmware_file(struct aw88395 *aw88395)
dev_info(aw88395->aw_pa->dev, "loaded %s - size: %zu\n",
AW88395_ACF_FILE, cont ? cont->size : 0);
- aw88395->aw_cfg = devm_kzalloc(aw88395->aw_pa->dev, cont->size + sizeof(int), GFP_KERNEL);
- if (!aw88395->aw_cfg) {
+ aw_cfg = devm_kzalloc(aw88395->aw_pa->dev, struct_size(aw_cfg, data, cont->size), GFP_KERNEL);
+ if (!aw_cfg) {
release_firmware(cont);
return -ENOMEM;
}
- aw88395->aw_cfg->len = (int)cont->size;
- memcpy(aw88395->aw_cfg->data, cont->data, cont->size);
+ aw_cfg->len = (int)cont->size;
+ memcpy(aw_cfg->data, cont->data, cont->size);
release_firmware(cont);
+ aw88395->aw_cfg = aw_cfg;
+
ret = aw88395_dev_load_acf_check(aw88395->aw_pa, aw88395->aw_cfg);
if (ret < 0) {
dev_err(aw88395->aw_pa->dev, "Load [%s] failed ....!", AW88395_ACF_FILE);
@@ -557,7 +560,7 @@ static int aw88395_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id aw88395_i2c_id[] = {
- { AW88395_I2C_NAME },
+ { .name = AW88395_I2C_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, aw88395_i2c_id);
diff --git a/sound/soc/codecs/aw88395/aw88395_device.h b/sound/soc/codecs/aw88395/aw88395_device.h
index 3626f222899d..7b74eeb84c43 100644
--- a/sound/soc/codecs/aw88395/aw88395_device.h
+++ b/sound/soc/codecs/aw88395/aw88395_device.h
@@ -152,7 +152,7 @@ struct aw_cali_desc {
struct aw_container {
int len;
- u8 data[];
+ u8 data[] __counted_by(len);
};
struct aw_device {
diff --git a/sound/soc/codecs/aw88399.c b/sound/soc/codecs/aw88399.c
index b588c27909b5..b2ec3503f7e2 100644
--- a/sound/soc/codecs/aw88399.c
+++ b/sound/soc/codecs/aw88399.c
@@ -2146,7 +2146,7 @@ static int aw88399_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id aw88399_i2c_id[] = {
- { AW88399_I2C_NAME },
+ { .name = AW88399_I2C_NAME },
{ }
};
MODULE_DEVICE_TABLE(i2c, aw88399_i2c_id);
diff --git a/sound/soc/codecs/cs-amp-lib.c b/sound/soc/codecs/cs-amp-lib.c
index b34b1f5f121f..371e99205b58 100644
--- a/sound/soc/codecs/cs-amp-lib.c
+++ b/sound/soc/codecs/cs-amp-lib.c
@@ -118,7 +118,7 @@ static int cs_amp_read_cal_coeff(struct cs_dsp *dsp,
}
if (ret < 0) {
- dev_err(dsp->dev, "Failed to write to '%s': %d\n", ctl_name, ret);
+ dev_err(dsp->dev, "Failed to read '%s': %d\n", ctl_name, ret);
return ret;
}
@@ -500,7 +500,7 @@ static int _cs_amp_set_efi_calibration_data(struct device *dev, int amp_index, i
* must be set.
*/
if (data->count == 0)
- data->count = (data->size - sizeof(data)) / sizeof(data->data[0]);
+ data->count = (data->size - struct_offset(data, data)) / sizeof(data->data[0]);
if (amp_index < 0) {
/* Is there already a slot for this target? */
@@ -748,10 +748,7 @@ static const char *cs_amp_devm_get_dell_ssidex(struct device *dev,
char *ssidex_buf __free(kfree) = cs_amp_alloc_get_efi_variable(DELL_SSIDEXV2_EFI_NAME,
&DELL_SSIDEXV2_EFI_GUID,
NULL);
- ret = PTR_ERR_OR_ZERO(ssidex_buf);
- if (ret == -ENOENT)
- return ERR_PTR(-ENOENT);
- else if (ret < 0)
+ if (IS_ERR(ssidex_buf))
return ssidex_buf;
/*
@@ -833,11 +830,18 @@ EXPORT_SYMBOL_NS_GPL(cs_amp_devm_get_vendor_specific_variant_id, "SND_SOC_CS_AMP
*/
struct dentry *cs_amp_create_debugfs(struct device *dev)
{
- struct dentry *dir;
+ struct dentry *dir, *created;
+ /* debugfs_lookup() can return NULL or ERR_PTR on error */
dir = debugfs_lookup("cirrus_logic", NULL);
- if (!dir)
- dir = debugfs_create_dir("cirrus_logic", NULL);
+ if (!IS_ERR_OR_NULL(dir)) {
+ created = debugfs_create_dir(dev_name(dev), dir);
+ dput(dir);
+
+ return created;
+ }
+
+ dir = debugfs_create_dir("cirrus_logic", NULL);
return debugfs_create_dir(dev_name(dev), dir);
}
diff --git a/sound/soc/codecs/cs35l32.c b/sound/soc/codecs/cs35l32.c
index 0bb4bdb3deec..c835088de578 100644
--- a/sound/soc/codecs/cs35l32.c
+++ b/sound/soc/codecs/cs35l32.c
@@ -555,8 +555,8 @@ MODULE_DEVICE_TABLE(of, cs35l32_of_match);
static const struct i2c_device_id cs35l32_id[] = {
- {"cs35l32"},
- {}
+ { .name = "cs35l32" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs35l32_id);
diff --git a/sound/soc/codecs/cs35l33.c b/sound/soc/codecs/cs35l33.c
index 98b4d371d931..f49edb9ea1f2 100644
--- a/sound/soc/codecs/cs35l33.c
+++ b/sound/soc/codecs/cs35l33.c
@@ -1262,8 +1262,8 @@ static const struct of_device_id cs35l33_of_match[] = {
MODULE_DEVICE_TABLE(of, cs35l33_of_match);
static const struct i2c_device_id cs35l33_id[] = {
- {"cs35l33"},
- {}
+ { .name = "cs35l33" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs35l33_id);
diff --git a/sound/soc/codecs/cs35l34.c b/sound/soc/codecs/cs35l34.c
index a5a8075598ff..e80984b22159 100644
--- a/sound/soc/codecs/cs35l34.c
+++ b/sound/soc/codecs/cs35l34.c
@@ -1175,8 +1175,8 @@ static const struct of_device_id cs35l34_of_match[] = {
MODULE_DEVICE_TABLE(of, cs35l34_of_match);
static const struct i2c_device_id cs35l34_id[] = {
- {"cs35l34"},
- {}
+ { .name = "cs35l34" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs35l34_id);
diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c
index 7a01b1d9fc9d..b2439ec3c19f 100644
--- a/sound/soc/codecs/cs35l35.c
+++ b/sound/soc/codecs/cs35l35.c
@@ -1639,8 +1639,8 @@ static const struct of_device_id cs35l35_of_match[] = {
MODULE_DEVICE_TABLE(of, cs35l35_of_match);
static const struct i2c_device_id cs35l35_id[] = {
- {"cs35l35"},
- {}
+ { .name = "cs35l35" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs35l35_id);
diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c
index 93818d7ec1a7..89645327945f 100644
--- a/sound/soc/codecs/cs35l36.c
+++ b/sound/soc/codecs/cs35l36.c
@@ -1918,8 +1918,8 @@ static const struct of_device_id cs35l36_of_match[] = {
MODULE_DEVICE_TABLE(of, cs35l36_of_match);
static const struct i2c_device_id cs35l36_id[] = {
- {"cs35l36"},
- {}
+ { .name = "cs35l36" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs35l36_id);
diff --git a/sound/soc/codecs/cs35l41-i2c.c b/sound/soc/codecs/cs35l41-i2c.c
index 34097996b784..23f59f3025bd 100644
--- a/sound/soc/codecs/cs35l41-i2c.c
+++ b/sound/soc/codecs/cs35l41-i2c.c
@@ -20,11 +20,11 @@
#include "cs35l41.h"
static const struct i2c_device_id cs35l41_id_i2c[] = {
- { "cs35l40" },
- { "cs35l41" },
- { "cs35l51" },
- { "cs35l53" },
- {}
+ { .name = "cs35l40" },
+ { .name = "cs35l41" },
+ { .name = "cs35l51" },
+ { .name = "cs35l53" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs35l41_id_i2c);
diff --git a/sound/soc/codecs/cs35l45-i2c.c b/sound/soc/codecs/cs35l45-i2c.c
index a09aa3b92ae1..3eba61e107a5 100644
--- a/sound/soc/codecs/cs35l45-i2c.c
+++ b/sound/soc/codecs/cs35l45-i2c.c
@@ -53,8 +53,8 @@ static const struct of_device_id cs35l45_of_match[] = {
MODULE_DEVICE_TABLE(of, cs35l45_of_match);
static const struct i2c_device_id cs35l45_id_i2c[] = {
- { "cs35l45" },
- {}
+ { .name = "cs35l45" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs35l45_id_i2c);
diff --git a/sound/soc/codecs/cs35l56-i2c.c b/sound/soc/codecs/cs35l56-i2c.c
index 0492ddc4102d..0f64ab628b03 100644
--- a/sound/soc/codecs/cs35l56-i2c.c
+++ b/sound/soc/codecs/cs35l56-i2c.c
@@ -72,9 +72,9 @@ static void cs35l56_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id cs35l56_id_i2c[] = {
- { "cs35l56", 0x3556 },
- { "cs35l63", 0x3563 },
- {}
+ { .name = "cs35l56", .driver_data = 0x3556 },
+ { .name = "cs35l63", .driver_data = 0x3563 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs35l56_id_i2c);
diff --git a/sound/soc/codecs/cs35l56-sdw.c b/sound/soc/codecs/cs35l56-sdw.c
index 9dc47fec1ea0..0a55b93b96f9 100644
--- a/sound/soc/codecs/cs35l56-sdw.c
+++ b/sound/soc/codecs/cs35l56-sdw.c
@@ -17,6 +17,7 @@
#include <linux/string_choices.h>
#include <linux/swab.h>
#include <linux/types.h>
+#include <linux/unaligned.h>
#include <linux/workqueue.h>
#include "cs35l56.h"
@@ -59,8 +60,6 @@ static int cs35l56_sdw_slow_read(struct sdw_slave *peripheral, unsigned int reg,
{
int ret, i;
- reg += CS35L56_SDW_ADDR_OFFSET;
-
for (i = 0; i < val_size; i += sizeof(u32)) {
/* Poll for bus bridge idle */
ret = cs35l56_sdw_poll_mem_status(peripheral,
@@ -97,57 +96,23 @@ static int cs35l56_sdw_slow_read(struct sdw_slave *peripheral, unsigned int reg,
return 0;
}
-static int cs35l56_sdw_read_one(struct sdw_slave *peripheral, unsigned int reg, void *buf)
-{
- int ret;
-
- ret = sdw_nread_no_pm(peripheral, reg, 4, (u8 *)buf);
- if (ret != 0) {
- dev_err(&peripheral->dev, "Read failed @%#x:%d\n", reg, ret);
- return ret;
- }
-
- swab32s((u32 *)buf);
-
- return 0;
-}
-
static int cs35l56_sdw_read(void *context, const void *reg_buf,
const size_t reg_size, void *val_buf,
size_t val_size)
{
struct sdw_slave *peripheral = context;
- u8 *buf8 = val_buf;
- unsigned int reg, bytes;
+ struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
+ unsigned int reg_addr = get_unaligned_le32(reg_buf);
int ret;
- reg = le32_to_cpu(*(const __le32 *)reg_buf);
-
- if (cs35l56_is_otp_register(reg))
- return cs35l56_sdw_slow_read(peripheral, reg, buf8, val_size);
-
- reg += CS35L56_SDW_ADDR_OFFSET;
+ if (cs35l56_is_otp_register(reg_addr - CS35L56_SDW_ADDR_OFFSET))
+ return cs35l56_sdw_slow_read(peripheral, reg_addr, (u8 *)val_buf, val_size);
- if (val_size == 4)
- return cs35l56_sdw_read_one(peripheral, reg, val_buf);
-
- while (val_size) {
- bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */
- if (bytes > val_size)
- bytes = val_size;
-
- ret = sdw_nread_no_pm(peripheral, reg, bytes, buf8);
- if (ret != 0) {
- dev_err(&peripheral->dev, "Read failed @%#x..%#x:%d\n",
- reg, reg + bytes - 1, ret);
- return ret;
- }
+ ret = regmap_raw_read(cs35l56->sdw_bus_regmap, reg_addr, val_buf, val_size);
+ if (ret)
+ return ret;
- swab32_array((u32 *)buf8, bytes / 4);
- val_size -= bytes;
- reg += bytes;
- buf8 += bytes;
- }
+ swab32_array((u32 *)val_buf, val_size / sizeof(u32));
return 0;
}
@@ -161,58 +126,34 @@ static inline void cs35l56_swab_copy(void *dest, const void *src, size_t nbytes)
*dest32++ = swab32(*src32++);
}
-static int cs35l56_sdw_write_one(struct sdw_slave *peripheral, unsigned int reg, const void *buf)
-{
- u32 val_le = swab32(*(u32 *)buf);
- int ret;
-
- ret = sdw_nwrite_no_pm(peripheral, reg, 4, (u8 *)&val_le);
- if (ret != 0) {
- dev_err(&peripheral->dev, "Write failed @%#x:%d\n", reg, ret);
- return ret;
- }
-
- return 0;
-}
-
static int cs35l56_sdw_gather_write(void *context,
const void *reg_buf, size_t reg_size,
const void *val_buf, size_t val_size)
{
struct sdw_slave *peripheral = context;
- const u8 *src_be = val_buf;
- u32 val_le_buf[64]; /* Define u32 so it is 32-bit aligned */
- unsigned int reg, bytes;
+ struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
+ unsigned int reg_addr = get_unaligned_le32(reg_buf);
+ u32 swab_buf[64]; /* Define u32 so it is 32-bit aligned */
int ret;
- reg = le32_to_cpu(*(const __le32 *)reg_buf);
- reg += CS35L56_SDW_ADDR_OFFSET;
-
- if (val_size == 4)
- return cs35l56_sdw_write_one(peripheral, reg, src_be);
-
- while (val_size) {
- bytes = SDW_REG_NO_PAGE - (reg & SDW_REGADDR); /* to end of page */
- if (bytes > val_size)
- bytes = val_size;
- if (bytes > sizeof(val_le_buf))
- bytes = sizeof(val_le_buf);
-
- cs35l56_swab_copy(val_le_buf, src_be, bytes);
-
- ret = sdw_nwrite_no_pm(peripheral, reg, bytes, (u8 *)val_le_buf);
- if (ret != 0) {
- dev_err(&peripheral->dev, "Write failed @%#x..%#x:%d\n",
- reg, reg + bytes - 1, ret);
+ while (val_size > sizeof(swab_buf)) {
+ cs35l56_swab_copy(swab_buf, val_buf, sizeof(swab_buf));
+ ret = regmap_raw_write(cs35l56->sdw_bus_regmap, reg_addr,
+ swab_buf, sizeof(swab_buf));
+ if (ret)
return ret;
- }
- val_size -= bytes;
- reg += bytes;
- src_be += bytes;
+ val_size -= sizeof(swab_buf);
+ reg_addr += sizeof(swab_buf);
+ val_buf += sizeof(swab_buf);
}
- return 0;
+ if (val_size == 0)
+ return 0;
+
+ cs35l56_swab_copy(swab_buf, val_buf, val_size);
+
+ return regmap_raw_write(cs35l56->sdw_bus_regmap, reg_addr, swab_buf, val_size);
}
static int cs35l56_sdw_write(void *context, const void *val_buf, size_t val_size)
@@ -231,7 +172,7 @@ static int cs35l56_sdw_write(void *context, const void *val_buf, size_t val_size
* byte controls always have the same byte order, and firmware file blobs
* can be written verbatim.
*/
-static const struct regmap_bus cs35l56_regmap_bus_sdw = {
+static const struct regmap_bus cs35l56_regmap_swab_bus_sdw = {
.read = cs35l56_sdw_read,
.write = cs35l56_sdw_write,
.gather_write = cs35l56_sdw_gather_write,
@@ -239,6 +180,18 @@ static const struct regmap_bus cs35l56_regmap_bus_sdw = {
.val_format_endian_default = REGMAP_ENDIAN_BIG,
};
+/* Low-level SoundWire regmap to transfer the data over the bus */
+static const struct regmap_config cs35l56_sdw_bus_regmap = {
+ .name = "sdw-le32",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ .reg_format_endian = REGMAP_ENDIAN_LITTLE,
+ .val_format_endian = REGMAP_ENDIAN_LITTLE,
+ .max_register = CS35L56_DSP1_PMEM_5114 + 0x8000,
+ .cache_type = REGCACHE_NONE,
+};
+
static int cs35l56_sdw_get_unique_id(struct cs35l56_private *cs35l56)
{
int ret;
@@ -277,11 +230,8 @@ static void cs35l56_sdw_init(struct sdw_slave *peripheral)
* cs35l56_init can return with !init_done if it triggered
* a soft reset.
*/
- if (cs35l56->base.init_done) {
- /* Enable SoundWire interrupts */
- sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1,
- CS35L56_SDW_INT_MASK_CODEC_IRQ);
- }
+ if (cs35l56->base.init_done)
+ cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral);
out:
pm_runtime_put_autosuspend(cs35l56->base.dev);
@@ -306,15 +256,11 @@ static int cs35l56_sdw_interrupt(struct sdw_slave *peripheral,
pm_runtime_get_noresume(cs35l56->base.dev);
/*
- * Mask and clear until it has been handled. The read of GEN_INT_STAT_1
- * is required as per the SoundWire spec for interrupt status bits
- * to clear. GEN_INT_MASK_1 masks the _inputs_ to GEN_INT_STAT1.
+ * Mask and clear until it has been handled.
* None of the interrupts are time-critical so use the
* power-efficient queue.
*/
- sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0);
- sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1);
- sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF);
+ cs35l56_mask_soundwire_interrupts(peripheral);
queue_work(system_power_efficient_wq, &cs35l56->sdw_irq_work);
return 0;
@@ -330,8 +276,7 @@ static void cs35l56_sdw_irq_work(struct work_struct *work)
/* unmask interrupts */
if (!cs35l56->sdw_irq_no_unmask)
- sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1,
- CS35L56_SDW_INT_MASK_CODEC_IRQ);
+ cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral);
pm_runtime_put_autosuspend(cs35l56->base.dev);
}
@@ -385,18 +330,18 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral,
switch (status) {
case SDW_SLAVE_ATTACHED:
- dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__);
- cs35l56->sdw_in_clock_stop_1 = false;
if (cs35l56->sdw_attached)
break;
+ dev_dbg(cs35l56->base.dev, "%s: ATTACHED\n", __func__);
if (!cs35l56->base.init_done || cs35l56->soft_resetting)
cs35l56_sdw_init(peripheral);
cs35l56->sdw_attached = true;
break;
case SDW_SLAVE_UNATTACHED:
- dev_dbg(cs35l56->base.dev, "%s: UNATTACHED\n", __func__);
+ if (cs35l56->sdw_attached)
+ dev_dbg(cs35l56->base.dev, "%s: UNATTACHED\n", __func__);
cs35l56->sdw_attached = false;
break;
default:
@@ -406,57 +351,29 @@ static int cs35l56_sdw_update_status(struct sdw_slave *peripheral,
return 0;
}
-static int __maybe_unused cs35l56_sdw_clk_stop(struct sdw_slave *peripheral,
- enum sdw_clk_stop_mode mode,
- enum sdw_clk_stop_type type)
-{
- struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
-
- dev_dbg(cs35l56->base.dev, "%s: clock_stop_mode%d stage:%d\n", __func__, mode, type);
-
- switch (type) {
- case SDW_CLK_POST_PREPARE:
- if (mode == SDW_CLK_STOP_MODE1)
- cs35l56->sdw_in_clock_stop_1 = true;
- else
- cs35l56->sdw_in_clock_stop_1 = false;
- return 0;
- default:
- return 0;
- }
-}
-
static const struct sdw_slave_ops cs35l56_sdw_ops = {
.read_prop = cs35l56_sdw_read_prop,
.interrupt_callback = cs35l56_sdw_interrupt,
.update_status = cs35l56_sdw_update_status,
- .clk_stop = cs35l56_sdw_clk_stop,
};
static int __maybe_unused cs35l56_sdw_handle_unattach(struct cs35l56_private *cs35l56)
{
struct sdw_slave *peripheral = cs35l56->sdw_peripheral;
+ int ret;
- dev_dbg(cs35l56->base.dev, "attached:%u unattach_request:%u in_clock_stop_1:%u\n",
- cs35l56->sdw_attached, peripheral->unattach_request, cs35l56->sdw_in_clock_stop_1);
-
- if (cs35l56->sdw_in_clock_stop_1 || peripheral->unattach_request) {
- /* Cannot access registers until bus is re-initialized. */
- dev_dbg(cs35l56->base.dev, "Wait for initialization_complete\n");
- if (!wait_for_completion_timeout(&peripheral->initialization_complete,
- msecs_to_jiffies(5000))) {
- dev_err(cs35l56->base.dev, "initialization_complete timed out\n");
- return -ETIMEDOUT;
- }
+ dev_dbg(cs35l56->base.dev, "attached:%u unattach_request:%u\n",
+ cs35l56->sdw_attached, peripheral->unattach_request);
- peripheral->unattach_request = 0;
- cs35l56->sdw_in_clock_stop_1 = false;
+ /* Cannot access registers until bus is re-initialized. */
+ ret = sdw_slave_wait_for_init(peripheral, 5000);
+ if (ret)
+ return ret;
- /*
- * Don't call regcache_mark_dirty(), we can't be sure that the
- * Manager really did issue a Bus Reset.
- */
- }
+ /*
+ * Don't call regcache_mark_dirty(), we can't be sure that the
+ * Manager really did issue a Bus Reset.
+ */
return 0;
}
@@ -489,9 +406,7 @@ static int __maybe_unused cs35l56_sdw_runtime_resume(struct device *dev)
if (ret)
return ret;
- /* Re-enable SoundWire interrupts */
- sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1,
- CS35L56_SDW_INT_MASK_CODEC_IRQ);
+ cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral);
return 0;
}
@@ -503,18 +418,7 @@ static int __maybe_unused cs35l56_sdw_system_suspend(struct device *dev)
if (!cs35l56->base.init_done)
return 0;
- /*
- * Disable SoundWire interrupts.
- * Flush - don't cancel because that could leave an unbalanced pm_runtime_get.
- */
- cs35l56->sdw_irq_no_unmask = true;
- flush_work(&cs35l56->sdw_irq_work);
-
- /* Mask interrupts and flush in case sdw_irq_work was queued again */
- sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0);
- sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1);
- sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF);
- flush_work(&cs35l56->sdw_irq_work);
+ cs35l56_disable_sdw_interrupts(cs35l56);
return cs35l56_system_suspend(dev);
}
@@ -561,8 +465,16 @@ static int cs35l56_sdw_probe(struct sdw_slave *peripheral, const struct sdw_devi
cs35l56->base.type = ((unsigned int)id->driver_data) & 0xff;
- cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_bus_sdw,
- peripheral, regmap_config);
+ /* Low-level regmap to transfer read/writes over SoundWire bus */
+ cs35l56->sdw_bus_regmap = devm_regmap_init_sdw(peripheral, &cs35l56_sdw_bus_regmap);
+ if (IS_ERR(cs35l56->sdw_bus_regmap)) {
+ ret = PTR_ERR(cs35l56->sdw_bus_regmap);
+ return dev_err_probe(dev, ret, "Failed to allocate bus register map\n");
+ }
+
+ /* Wrapper regmap to simulate big-endian ordering */
+ cs35l56->base.regmap = devm_regmap_init(dev, &cs35l56_regmap_swab_bus_sdw,
+ peripheral, regmap_config);
if (IS_ERR(cs35l56->base.regmap)) {
ret = PTR_ERR(cs35l56->base.regmap);
return dev_err_probe(dev, ret, "Failed to allocate register map\n");
@@ -582,12 +494,7 @@ static void cs35l56_sdw_remove(struct sdw_slave *peripheral)
{
struct cs35l56_private *cs35l56 = dev_get_drvdata(&peripheral->dev);
- /* Disable SoundWire interrupts */
- cs35l56->sdw_irq_no_unmask = true;
- cancel_work_sync(&cs35l56->sdw_irq_work);
- sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0);
- sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1);
- sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF);
+ cs35l56_disable_sdw_interrupts(cs35l56);
cs35l56_remove(cs35l56);
}
diff --git a/sound/soc/codecs/cs35l56-shared-test.c b/sound/soc/codecs/cs35l56-shared-test.c
index cfe7938065f9..4f52c8a192e5 100644
--- a/sound/soc/codecs/cs35l56-shared-test.c
+++ b/sound/soc/codecs/cs35l56-shared-test.c
@@ -29,6 +29,7 @@ struct cs35l56_shared_test_priv {
struct faux_device *gpio_dev;
struct cs35l56_shared_test_mock_gpio *gpio_priv;
struct regmap *registers;
+ unsigned int reg_offset;
struct cs35l56_base *cs35l56_base;
u8 applied_pad_pull_state[CS35L56_MAX_GPIO];
};
@@ -194,6 +195,8 @@ static int cs35l56_shared_test_reg_read(void *context, unsigned int reg, unsigne
{
struct cs35l56_shared_test_priv *priv = context;
+ reg -= priv->reg_offset;
+
switch (reg) {
case CS35L56_SYNC_GPIO1_CFG ... CS35L56_ASP2_DIO_GPIO13_CFG:
case CS35L56_GPIO1_CTRL1 ... CS35L56_GPIO13_CTRL1:
@@ -214,6 +217,8 @@ static int cs35l56_shared_test_reg_write(void *context, unsigned int reg, unsign
{
struct cs35l56_shared_test_priv *priv = context;
+ reg -= priv->reg_offset;
+
switch (reg) {
case CS35L56_UPDATE_REGS:
return cs35l56_shared_test_updt_gpio_pres(priv, reg, val);
@@ -673,6 +678,7 @@ static int cs35l56_shared_test_case_base_init(struct kunit *test, u8 type, u8 re
priv->cs35l56_base->rev = rev;
if (regmap_config) {
+ priv->reg_offset = regmap_config->reg_base;
ret = cs35l56_shared_test_case_regmap_init(test, regmap_config);
if (ret)
return ret;
diff --git a/sound/soc/codecs/cs35l56-shared.c b/sound/soc/codecs/cs35l56-shared.c
index 795e2764d67e..f14e2eaaa4ee 100644
--- a/sound/soc/codecs/cs35l56-shared.c
+++ b/sound/soc/codecs/cs35l56-shared.c
@@ -534,6 +534,7 @@ static void cs35l56_spi_system_reset(struct cs35l56_base *cs35l56_base)
* The regmap must remain in cache-only until the chip has
* booted, so use a bypassed read.
*/
+ val = 0;
ret = read_poll_timeout(regmap_read_bypassed, read_ret,
(val > 0) && (val < 0xffffffff),
CS35L56_HALO_STATE_POLL_US,
@@ -1259,7 +1260,7 @@ ssize_t cs35l56_cal_data_debugfs_write(struct cs35l56_base *cs35l56_base,
return -EMSGSIZE;
ret = simple_write_to_buffer(&cal_data, sizeof(cal_data), ppos, from, count);
- if (ret)
+ if (ret < 0)
return ret;
ret = cs35l56_stash_calibration(cs35l56_base, &cal_data);
@@ -1293,6 +1294,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_create_cal_debugfs, "SND_SOC_CS35L56_SHARED");
void cs35l56_remove_cal_debugfs(struct cs35l56_base *cs35l56_base)
{
debugfs_remove_recursive(cs35l56_base->debugfs);
+ cs35l56_base->debugfs = ERR_PTR(-ENOENT);
}
EXPORT_SYMBOL_NS_GPL(cs35l56_remove_cal_debugfs, "SND_SOC_CS35L56_SHARED");
@@ -1880,6 +1882,7 @@ EXPORT_SYMBOL_NS_GPL(cs35l56_regmap_spi, "SND_SOC_CS35L56_SHARED");
const struct regmap_config cs35l56_regmap_sdw = {
.reg_bits = 32,
+ .reg_base = 0x8000,
.val_bits = 32,
.reg_stride = 4,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
@@ -1915,6 +1918,7 @@ const struct regmap_config cs35l63_regmap_sdw = {
.reg_bits = 32,
.val_bits = 32,
.reg_stride = 4,
+ .reg_base = 0x8000,
.reg_format_endian = REGMAP_ENDIAN_LITTLE,
.val_format_endian = REGMAP_ENDIAN_BIG,
.max_register = CS35L56_DSP1_PMEM_5114,
diff --git a/sound/soc/codecs/cs35l56.c b/sound/soc/codecs/cs35l56.c
index 849d70ca23d6..570a68829ccd 100644
--- a/sound/soc/codecs/cs35l56.c
+++ b/sound/soc/codecs/cs35l56.c
@@ -37,6 +37,49 @@
#include "wm_adsp.h"
#include "cs35l56.h"
+void cs35l56_mask_soundwire_interrupts(struct sdw_slave *peripheral)
+{
+ /*
+ * The read of GEN_INT_STAT_1 is required as per the SoundWire spec
+ * for interrupt status bits to clear.
+ * GEN_INT_MASK_1 masks the _inputs_ to GEN_INT_STAT1.
+ */
+ sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0);
+ sdw_read_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1);
+ sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF);
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_mask_soundwire_interrupts, "SND_SOC_CS35L56_CORE");
+
+void cs35l56_unmask_soundwire_interrupts(struct sdw_slave *peripheral)
+{
+ sdw_write_no_pm(peripheral, CS35L56_SDW_GEN_INT_MASK_1, CS35L56_SDW_INT_MASK_CODEC_IRQ);
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_unmask_soundwire_interrupts, "SND_SOC_CS35L56_CORE");
+
+void cs35l56_disable_sdw_interrupts(struct cs35l56_private *cs35l56)
+{
+ if (!cs35l56->sdw_peripheral)
+ return;
+
+ cs35l56->sdw_irq_no_unmask = true;
+ flush_work(&cs35l56->sdw_irq_work);
+
+ /* Mask interrupts and flush in case sdw_irq_work was queued again */
+ cs35l56_mask_soundwire_interrupts(cs35l56->sdw_peripheral);
+ flush_work(&cs35l56->sdw_irq_work);
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_disable_sdw_interrupts, "SND_SOC_CS35L56_CORE");
+
+void cs35l56_enable_sdw_interrupts(struct cs35l56_private *cs35l56)
+{
+ if (!cs35l56->sdw_peripheral)
+ return;
+
+ cs35l56->sdw_irq_no_unmask = false;
+ cs35l56_unmask_soundwire_interrupts(cs35l56->sdw_peripheral);
+}
+EXPORT_SYMBOL_NS_GPL(cs35l56_enable_sdw_interrupts, "SND_SOC_CS35L56_CORE");
+
static int cs35l56_dsp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
@@ -426,6 +469,8 @@ static unsigned int cs35l56_make_tdm_config_word(unsigned int reg_val, unsigned
reg_val &= ~(0x3f << channel_shift);
reg_val |= bit_num << channel_shift;
channel_shift += 8;
+ if (channel_shift > 24)
+ break;
}
return reg_val;
@@ -788,14 +833,7 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing
* Setting sdw_irq_no_unmask prevents the handler re-enabling
* the SoundWire interrupt.
*/
- if (cs35l56->sdw_peripheral) {
- cs35l56->sdw_irq_no_unmask = true;
- flush_work(&cs35l56->sdw_irq_work);
- sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1, 0);
- sdw_read_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1);
- sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_STAT_1, 0xFF);
- flush_work(&cs35l56->sdw_irq_work);
- }
+ cs35l56_disable_sdw_interrupts(cs35l56);
ret = cs35l56_firmware_shutdown(&cs35l56->base);
if (ret)
@@ -847,12 +885,7 @@ static void cs35l56_patch(struct cs35l56_private *cs35l56, bool firmware_missing
err_unlock:
mutex_unlock(&cs35l56->base.irq_lock);
err:
- /* Re-enable SoundWire interrupts */
- if (cs35l56->sdw_peripheral) {
- cs35l56->sdw_irq_no_unmask = false;
- sdw_write_no_pm(cs35l56->sdw_peripheral, CS35L56_SDW_GEN_INT_MASK_1,
- CS35L56_SDW_INT_MASK_CODEC_IRQ);
- }
+ cs35l56_enable_sdw_interrupts(cs35l56);
}
static void cs35l56_dsp_work(struct work_struct *work)
@@ -867,11 +900,16 @@ static void cs35l56_dsp_work(struct work_struct *work)
if (!cs35l56->base.init_done)
return;
- pm_runtime_get_sync(cs35l56->base.dev);
+ PM_RUNTIME_ACQUIRE(cs35l56->base.dev, pm);
+ ret = PM_RUNTIME_ACQUIRE_ERR(&pm);
+ if (ret) {
+ dev_err(cs35l56->base.dev, "dsp_work failed to runtime-resume: %d\n", ret);
+ return;
+ }
ret = cs35l56_read_prot_status(&cs35l56->base, &firmware_missing, &firmware_version);
if (ret)
- goto err;
+ return;
/* Populate fw file qualifier with the revision and security state */
kfree(cs35l56->dsp.fwf_name);
@@ -887,7 +925,7 @@ static void cs35l56_dsp_work(struct work_struct *work)
}
if (!cs35l56->dsp.fwf_name)
- goto err;
+ return;
dev_dbg(cs35l56->base.dev, "DSP fwf name: '%s' system name: '%s'\n",
cs35l56->dsp.fwf_name, cs35l56->dsp.system_name);
@@ -905,8 +943,6 @@ static void cs35l56_dsp_work(struct work_struct *work)
cs35l56_patch(cs35l56, firmware_missing);
cs35l56_log_tuning(&cs35l56->base, &cs35l56->dsp.cs_dsp);
-err:
- pm_runtime_put_autosuspend(cs35l56->base.dev);
}
static struct snd_soc_dapm_context *cs35l56_power_up_for_cal(struct cs35l56_private *cs35l56)
@@ -1323,7 +1359,7 @@ VISIBLE_IF_KUNIT int cs35l56_set_fw_name(struct snd_soc_component *component)
}
EXPORT_SYMBOL_IF_KUNIT(cs35l56_set_fw_name);
-static int cs35l56_component_probe(struct snd_soc_component *component)
+static int _cs35l56_component_probe(struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct cs35l56_private *cs35l56 = snd_soc_component_get_drvdata(component);
@@ -1423,6 +1459,17 @@ static void cs35l56_component_remove(struct snd_soc_component *component)
cs35l56->component = NULL;
}
+static int cs35l56_component_probe(struct snd_soc_component *component)
+{
+ int ret;
+
+ ret = _cs35l56_component_probe(component);
+ if (ret < 0)
+ cs35l56_component_remove(component);
+
+ return ret;
+}
+
static int cs35l56_set_bias_level(struct snd_soc_component *component,
enum snd_soc_bias_level level)
{
@@ -1477,6 +1524,7 @@ static int __maybe_unused cs35l56_runtime_resume_i2c_spi(struct device *dev)
int cs35l56_system_suspend(struct device *dev)
{
struct cs35l56_private *cs35l56 = dev_get_drvdata(dev);
+ int ret;
dev_dbg(dev, "system_suspend\n");
@@ -1492,7 +1540,11 @@ int cs35l56_system_suspend(struct device *dev)
if (cs35l56->base.irq)
disable_irq(cs35l56->base.irq);
- return pm_runtime_force_suspend(dev);
+ ret = pm_runtime_force_suspend(dev);
+ if ((ret < 0) && cs35l56->base.irq)
+ enable_irq(cs35l56->base.irq);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(cs35l56_system_suspend);
@@ -1961,11 +2013,14 @@ int cs35l56_common_probe(struct cs35l56_private *cs35l56)
cs35l56_dai, ARRAY_SIZE(cs35l56_dai));
if (ret < 0) {
dev_err_probe(cs35l56->base.dev, ret, "Register codec failed\n");
- goto err;
+ goto err_remove_wm_adsp;
}
return 0;
+err_remove_wm_adsp:
+ wm_adsp2_remove(&cs35l56->dsp);
+
err:
gpiod_set_value_cansleep(cs35l56->base.reset_gpio, 0);
regulator_bulk_disable(ARRAY_SIZE(cs35l56->supplies), cs35l56->supplies);
@@ -1991,7 +2046,8 @@ int cs35l56_init(struct cs35l56_private *cs35l56)
if (cs35l56->base.init_done)
return 0;
- pm_runtime_set_autosuspend_delay(cs35l56->base.dev, 100);
+ pm_runtime_set_autosuspend_delay(cs35l56->base.dev,
+ CS35L56_FW_REQ_ACTIVE_TIMEOUT_MS + 50);
pm_runtime_use_autosuspend(cs35l56->base.dev);
pm_runtime_set_active(cs35l56->base.dev);
pm_runtime_enable(cs35l56->base.dev);
@@ -2073,6 +2129,8 @@ void cs35l56_remove(struct cs35l56_private *cs35l56)
destroy_workqueue(cs35l56->dsp_wq);
+ wm_adsp2_remove(&cs35l56->dsp);
+
pm_runtime_dont_use_autosuspend(cs35l56->base.dev);
pm_runtime_suspend(cs35l56->base.dev);
pm_runtime_disable(cs35l56->base.dev);
diff --git a/sound/soc/codecs/cs35l56.h b/sound/soc/codecs/cs35l56.h
index cd71b23b2a3a..9acd2e7e17c9 100644
--- a/sound/soc/codecs/cs35l56.h
+++ b/sound/soc/codecs/cs35l56.h
@@ -37,12 +37,12 @@ struct cs35l56_private {
struct snd_soc_component *component;
struct regulator_bulk_data supplies[CS35L56_NUM_BULK_SUPPLIES];
struct sdw_slave *sdw_peripheral;
+ struct regmap *sdw_bus_regmap;
const char *fallback_fw_suffix;
struct work_struct sdw_irq_work;
bool sdw_irq_no_unmask;
bool soft_resetting;
bool sdw_attached;
- bool sdw_in_clock_stop_1;
struct completion init_completion;
int speaker_id;
@@ -65,6 +65,11 @@ static inline struct cs35l56_private *cs35l56_private_from_base(struct cs35l56_b
extern const struct dev_pm_ops cs35l56_pm_ops_i2c_spi;
+void cs35l56_mask_soundwire_interrupts(struct sdw_slave *peripheral);
+void cs35l56_unmask_soundwire_interrupts(struct sdw_slave *peripheral);
+void cs35l56_disable_sdw_interrupts(struct cs35l56_private *cs35l56);
+void cs35l56_enable_sdw_interrupts(struct cs35l56_private *cs35l56);
+
int cs35l56_system_suspend(struct device *dev);
int cs35l56_system_suspend_late(struct device *dev);
int cs35l56_system_suspend_no_irq(struct device *dev);
diff --git a/sound/soc/codecs/cs4234.c b/sound/soc/codecs/cs4234.c
index 89c424dd838b..a889fbd519a8 100644
--- a/sound/soc/codecs/cs4234.c
+++ b/sound/soc/codecs/cs4234.c
@@ -11,7 +11,6 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/jiffies.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
diff --git a/sound/soc/codecs/cs4265.c b/sound/soc/codecs/cs4265.c
index 3f759c13d6d1..286d5ca29854 100644
--- a/sound/soc/codecs/cs4265.c
+++ b/sound/soc/codecs/cs4265.c
@@ -638,7 +638,7 @@ static const struct of_device_id cs4265_of_match[] = {
MODULE_DEVICE_TABLE(of, cs4265_of_match);
static const struct i2c_device_id cs4265_id[] = {
- { "cs4265" },
+ { .name = "cs4265" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs4265_id);
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index a48980e746ff..47b2f903a32c 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -19,7 +19,6 @@
* - Power management is supported
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -732,8 +731,8 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client)
* cs4270_id - I2C device IDs supported by this driver
*/
static const struct i2c_device_id cs4270_id[] = {
- {"cs4270"},
- {}
+ { .name = "cs4270" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs4270_id);
diff --git a/sound/soc/codecs/cs4271-i2c.c b/sound/soc/codecs/cs4271-i2c.c
index 1d210b969173..869a5317f677 100644
--- a/sound/soc/codecs/cs4271-i2c.c
+++ b/sound/soc/codecs/cs4271-i2c.c
@@ -23,7 +23,7 @@ static int cs4271_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id cs4271_i2c_id[] = {
- { "cs4271" },
+ { .name = "cs4271" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs4271_i2c_id);
diff --git a/sound/soc/codecs/cs42l42-i2c.c b/sound/soc/codecs/cs42l42-i2c.c
index 98b6718ccabf..c0942f28723b 100644
--- a/sound/soc/codecs/cs42l42-i2c.c
+++ b/sound/soc/codecs/cs42l42-i2c.c
@@ -78,8 +78,8 @@ static const struct acpi_device_id __maybe_unused cs42l42_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, cs42l42_acpi_match);
static const struct i2c_device_id cs42l42_id[] = {
- {"cs42l42"},
- {}
+ { .name = "cs42l42" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs42l42_id);
diff --git a/sound/soc/codecs/cs42l42-sdw.c b/sound/soc/codecs/cs42l42-sdw.c
index d5999ad9ff9b..ad1256910a18 100644
--- a/sound/soc/codecs/cs42l42-sdw.c
+++ b/sound/soc/codecs/cs42l42-sdw.c
@@ -9,7 +9,6 @@
#include <linux/gpio/consumer.h>
#include <linux/iopoll.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/of_irq.h>
#include <linux/pm_runtime.h>
#include <linux/soundwire/sdw.h>
@@ -433,19 +432,16 @@ static const struct reg_sequence cs42l42_soft_reboot_seq[] = {
static int cs42l42_sdw_handle_unattach(struct cs42l42_private *cs42l42)
{
struct sdw_slave *peripheral = cs42l42->sdw_peripheral;
+ int ret;
if (!peripheral->unattach_request)
return 0;
/* Cannot access registers until master re-attaches. */
dev_dbg(&peripheral->dev, "Wait for initialization_complete\n");
- if (!wait_for_completion_timeout(&peripheral->initialization_complete,
- msecs_to_jiffies(5000))) {
- dev_err(&peripheral->dev, "initialization_complete timed out\n");
- return -ETIMEDOUT;
- }
-
- peripheral->unattach_request = 0;
+ ret = sdw_slave_wait_for_init(peripheral, 5000);
+ if (ret)
+ return ret;
/*
* After a bus reset there must be a reconfiguration reset to
diff --git a/sound/soc/codecs/cs42l43-jack.c b/sound/soc/codecs/cs42l43-jack.c
index 3e04e6897b14..934666295ee3 100644
--- a/sound/soc/codecs/cs42l43-jack.c
+++ b/sound/soc/codecs/cs42l43-jack.c
@@ -805,7 +805,7 @@ irqreturn_t cs42l43_tip_sense(int irq, void *data)
if (priv->suspend_jack_debounce)
db_delay += priv->tip_fall_db_ms + priv->tip_rise_db_ms;
- queue_delayed_work(system_long_wq, &priv->tip_sense_work,
+ queue_delayed_work(system_dfl_long_wq, &priv->tip_sense_work,
msecs_to_jiffies(db_delay));
return IRQ_HANDLED;
@@ -932,7 +932,8 @@ int cs42l43_jack_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *u
snd_soc_jack_report(priv->jack_hp, 0, 0xFFFF);
if (!override) {
- queue_delayed_work(system_long_wq, &priv->tip_sense_work, 0);
+ queue_delayed_work(system_dfl_long_wq, &priv->tip_sense_work,
+ 0);
} else {
override--;
diff --git a/sound/soc/codecs/cs42l43.c b/sound/soc/codecs/cs42l43.c
index f0d6ff0b2976..1d133577702e 100644
--- a/sound/soc/codecs/cs42l43.c
+++ b/sound/soc/codecs/cs42l43.c
@@ -19,7 +19,6 @@
#include <linux/jiffies.h>
#include <linux/mfd/cs42l43.h>
#include <linux/mfd/cs42l43-regs.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
diff --git a/sound/soc/codecs/cs42l51-i2c.c b/sound/soc/codecs/cs42l51-i2c.c
index ba7e237619f2..a20a1030c498 100644
--- a/sound/soc/codecs/cs42l51-i2c.c
+++ b/sound/soc/codecs/cs42l51-i2c.c
@@ -14,7 +14,7 @@
#include "cs42l51.h"
static const struct i2c_device_id cs42l51_i2c_id[] = {
- { "cs42l51" },
+ { .name = "cs42l51" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs42l51_i2c_id);
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 662dc1a4835b..9d6bcfbbf0b2 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -1226,7 +1226,7 @@ MODULE_DEVICE_TABLE(of, cs42l52_of_match);
static const struct i2c_device_id cs42l52_id[] = {
- { "cs42l52" },
+ { .name = "cs42l52" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs42l52_id);
diff --git a/sound/soc/codecs/cs42l56.c b/sound/soc/codecs/cs42l56.c
index aabb74f1f43c..4d9a22a1029c 100644
--- a/sound/soc/codecs/cs42l56.c
+++ b/sound/soc/codecs/cs42l56.c
@@ -1353,7 +1353,7 @@ MODULE_DEVICE_TABLE(of, cs42l56_of_match);
static const struct i2c_device_id cs42l56_id[] = {
- { "cs42l56" },
+ { .name = "cs42l56" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs42l56_id);
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
index bda8442c1d66..6ddc6549492a 100644
--- a/sound/soc/codecs/cs42l73.c
+++ b/sound/soc/codecs/cs42l73.c
@@ -1369,8 +1369,8 @@ static const struct of_device_id cs42l73_of_match[] = {
MODULE_DEVICE_TABLE(of, cs42l73_of_match);
static const struct i2c_device_id cs42l73_id[] = {
- {"cs42l73"},
- {}
+ { .name = "cs42l73" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs42l73_id);
diff --git a/sound/soc/codecs/cs42l84.c b/sound/soc/codecs/cs42l84.c
index e590a43559e4..f2a58163de0e 100644
--- a/sound/soc/codecs/cs42l84.c
+++ b/sound/soc/codecs/cs42l84.c
@@ -1101,8 +1101,8 @@ static const struct of_device_id cs42l84_of_match[] = {
MODULE_DEVICE_TABLE(of, cs42l84_of_match);
static const struct i2c_device_id cs42l84_id[] = {
- { "cs42l84" },
- {}
+ { .name = "cs42l84" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs42l84_id);
diff --git a/sound/soc/codecs/cs42xx8-i2c.c b/sound/soc/codecs/cs42xx8-i2c.c
index 0faca384073a..4427d3214dee 100644
--- a/sound/soc/codecs/cs42xx8-i2c.c
+++ b/sound/soc/codecs/cs42xx8-i2c.c
@@ -9,7 +9,6 @@
#include <linux/i2c.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/pm_runtime.h>
#include <sound/soc.h>
@@ -49,9 +48,9 @@ static const struct of_device_id cs42xx8_of_match[] = {
MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
static const struct i2c_device_id cs42xx8_i2c_id[] = {
- {"cs42448", (kernel_ulong_t)&cs42448_data},
- {"cs42888", (kernel_ulong_t)&cs42888_data},
- {}
+ { .name = "cs42448", .driver_data = (kernel_ulong_t)&cs42448_data },
+ { .name = "cs42888", .driver_data = (kernel_ulong_t)&cs42888_data },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs42xx8_i2c_id);
diff --git a/sound/soc/codecs/cs42xx8-spi.c b/sound/soc/codecs/cs42xx8-spi.c
new file mode 100644
index 000000000000..2e4b8e6c4081
--- /dev/null
+++ b/sound/soc/codecs/cs42xx8-spi.c
@@ -0,0 +1,103 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Cirrus Logic CS42448/CS42888 Audio CODEC DAI SPI driver
+ *
+ * Copyright 2026 NXP
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/spi/spi.h>
+#include <sound/soc.h>
+
+#include "cs42xx8.h"
+
+/*
+ * CS42448/CS42888 SPI register access (from datasheet Figure 23):
+ *
+ * The SPI frame is 3 bytes:
+ * Byte 0: chip address [7:1] = 1001111, bit[0] = R/W (0=write, 1=read)
+ * Write: 0x9E, Read: 0x9F
+ * Byte 1: MAP - Memory Address Pointer
+ * bit[7] = INCR (auto-increment for burst), bits[6:0] = address
+ * Byte 2: data byte
+ *
+ * We configure reg_bits=16 so that regmap treats the address field as 2 bytes
+ * (big-endian). The chip address byte (0x9E/0x9F) is placed in the high byte
+ * via write_flag_mask / read_flag_mask, and the MAP register address occupies
+ * the low byte. Currently INCR (MAP bit[7]) is not set and use_single_read/write
+ * are enabled. This produces the correct 3-byte on-wire frame without any
+ * custom bus implementation:
+ *
+ * write: [0x9E, MAP_addr, data]
+ * read: [0x9F, MAP_addr] -> [data]
+ */
+
+static int cs42xx8_spi_probe(struct spi_device *spi)
+{
+ struct cs42xx8_driver_data *drvdata;
+ struct regmap_config config;
+ int ret;
+
+ drvdata = (struct cs42xx8_driver_data *)spi_get_device_match_data(spi);
+ if (!drvdata)
+ return dev_err_probe(&spi->dev, -EINVAL,
+ "failed to find driver data\n");
+
+ config = cs42xx8_regmap_config;
+ /*
+ * reg_bits=16 makes regmap send a 2-byte address field (big-endian).
+ * write_flag_mask/read_flag_mask are OR'd into that address field:
+ */
+ config.reg_bits = 16;
+ config.write_flag_mask = 0x9E;
+ config.read_flag_mask = 0x9F;
+
+ ret = cs42xx8_probe(&spi->dev,
+ devm_regmap_init_spi(spi, &config), drvdata);
+ if (ret)
+ return ret;
+
+ pm_runtime_enable(&spi->dev);
+ pm_request_idle(&spi->dev);
+
+ return 0;
+}
+
+static void cs42xx8_spi_remove(struct spi_device *spi)
+{
+ pm_runtime_disable(&spi->dev);
+}
+
+static const struct of_device_id cs42xx8_of_match[] = {
+ { .compatible = "cirrus,cs42448", .data = &cs42448_data, },
+ { .compatible = "cirrus,cs42888", .data = &cs42888_data, },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, cs42xx8_of_match);
+
+static const struct spi_device_id cs42xx8_spi_id[] = {
+ { .name = "cs42448", .driver_data = (kernel_ulong_t)&cs42448_data },
+ { .name = "cs42888", .driver_data = (kernel_ulong_t)&cs42888_data },
+ { }
+};
+MODULE_DEVICE_TABLE(spi, cs42xx8_spi_id);
+
+static struct spi_driver cs42xx8_spi_driver = {
+ .driver = {
+ .name = "cs42xx8",
+ .pm = pm_ptr(&cs42xx8_pm),
+ .of_match_table = cs42xx8_of_match,
+ },
+ .probe = cs42xx8_spi_probe,
+ .remove = cs42xx8_spi_remove,
+ .id_table = cs42xx8_spi_id,
+};
+
+module_spi_driver(cs42xx8_spi_driver);
+
+MODULE_DESCRIPTION("Cirrus Logic CS42448/CS42888 ALSA SoC Codec SPI Driver");
+MODULE_AUTHOR("Chancel Liu <chancel.liu@nxp.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42xx8.c b/sound/soc/codecs/cs42xx8.c
index 12fe9b3e2525..5b689549c74e 100644
--- a/sound/soc/codecs/cs42xx8.c
+++ b/sound/soc/codecs/cs42xx8.c
@@ -478,6 +478,9 @@ const struct regmap_config cs42xx8_regmap_config = {
.volatile_reg = cs42xx8_volatile_register,
.writeable_reg = cs42xx8_writeable_register,
.cache_type = REGCACHE_MAPLE,
+ .reg_format_endian = REGMAP_ENDIAN_BIG,
+ .use_single_read = true,
+ .use_single_write = true,
};
EXPORT_SYMBOL_GPL(cs42xx8_regmap_config);
diff --git a/sound/soc/codecs/cs43130.c b/sound/soc/codecs/cs43130.c
index a3bdaac9c059..e7b06f962790 100644
--- a/sound/soc/codecs/cs43130.c
+++ b/sound/soc/codecs/cs43130.c
@@ -2753,11 +2753,11 @@ MODULE_DEVICE_TABLE(acpi, cs43130_acpi_match);
static const struct i2c_device_id cs43130_i2c_id[] = {
- {"cs43130"},
- {"cs4399"},
- {"cs43131"},
- {"cs43198"},
- {}
+ { .name = "cs43130" },
+ { .name = "cs4399" },
+ { .name = "cs43131" },
+ { .name = "cs43198" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs43130_i2c_id);
diff --git a/sound/soc/codecs/cs4341.c b/sound/soc/codecs/cs4341.c
index b726e22ef57d..a44e6b3c298e 100644
--- a/sound/soc/codecs/cs4341.c
+++ b/sound/soc/codecs/cs4341.c
@@ -248,7 +248,7 @@ static int cs4341_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id cs4341_i2c_id[] = {
- { "cs4341" },
+ { .name = "cs4341" },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs4341_i2c_id);
diff --git a/sound/soc/codecs/cs4349.c b/sound/soc/codecs/cs4349.c
index d9a9c34fffe3..6ac6d306b054 100644
--- a/sound/soc/codecs/cs4349.c
+++ b/sound/soc/codecs/cs4349.c
@@ -7,7 +7,6 @@
* Authors: Tim Howe <Tim.Howe@cirrus.com>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -358,8 +357,8 @@ static const struct of_device_id cs4349_of_match[] = {
MODULE_DEVICE_TABLE(of, cs4349_of_match);
static const struct i2c_device_id cs4349_i2c_id[] = {
- {"cs4349"},
- {}
+ { .name = "cs4349" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs4349_i2c_id);
diff --git a/sound/soc/codecs/cs530x-i2c.c b/sound/soc/codecs/cs530x-i2c.c
index 52b02ceaa7e3..98cb61dd88c1 100644
--- a/sound/soc/codecs/cs530x-i2c.c
+++ b/sound/soc/codecs/cs530x-i2c.c
@@ -40,13 +40,13 @@ static const struct of_device_id cs530x_of_match[] = {
MODULE_DEVICE_TABLE(of, cs530x_of_match);
static const struct i2c_device_id cs530x_i2c_id[] = {
- { "cs4282", CS4282 },
- { "cs4302", CS4302 },
- { "cs4304", CS4304 },
- { "cs4308", CS4308 },
- { "cs5302", CS5302 },
- { "cs5304", CS5304 },
- { "cs5308", CS5308 },
+ { .name = "cs4282", .driver_data = CS4282 },
+ { .name = "cs4302", .driver_data = CS4302 },
+ { .name = "cs4304", .driver_data = CS4304 },
+ { .name = "cs4308", .driver_data = CS4308 },
+ { .name = "cs5302", .driver_data = CS5302 },
+ { .name = "cs5304", .driver_data = CS5304 },
+ { .name = "cs5308", .driver_data = CS5308 },
{ }
};
MODULE_DEVICE_TABLE(i2c, cs530x_i2c_id);
diff --git a/sound/soc/codecs/cs530x.c b/sound/soc/codecs/cs530x.c
index 18b5ff75feec..2c7e33135911 100644
--- a/sound/soc/codecs/cs530x.c
+++ b/sound/soc/codecs/cs530x.c
@@ -1093,6 +1093,29 @@ static int cs530x_component_probe(struct snd_soc_component *component)
return 0;
}
+static bool cs530x_mclk_freq_is_valid(struct cs530x_priv *cs530x,
+ unsigned int freq)
+{
+ /*
+ * All these chips support 48 kHz- and 44.1 kHz-related sample rates,
+ * but they differ in what MCLK frequency is required for achieving
+ * the sample rate.
+ */
+ switch (cs530x->devtype) {
+ case CS4282:
+ case CS4302:
+ case CS4304:
+ case CS4308:
+ return freq == 49152000 || freq == 45158400;
+ case CS5302:
+ case CS5304:
+ case CS5308:
+ return freq == 24576000 || freq == 22579200;
+ }
+
+ return false;
+}
+
static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id,
int source, unsigned int freq, int dir)
{
@@ -1101,11 +1124,7 @@ static int cs530x_set_sysclk(struct snd_soc_component *component, int clk_id,
switch (source) {
case CS530X_SYSCLK_SRC_MCLK:
- switch (freq) {
- case CS530X_SYSCLK_REF_45_1MHZ:
- case CS530X_SYSCLK_REF_49_1MHZ:
- break;
- default:
+ if (!cs530x_mclk_freq_is_valid(cs530x, freq)) {
dev_err(component->dev, "Invalid MCLK source rate %d\n", freq);
return -EINVAL;
}
diff --git a/sound/soc/codecs/cs530x.h b/sound/soc/codecs/cs530x.h
index 1e2f6a7a589c..18aa4dfd0c86 100644
--- a/sound/soc/codecs/cs530x.h
+++ b/sound/soc/codecs/cs530x.h
@@ -200,12 +200,6 @@
/* IN_VOL_CTL5 and OUT_VOL_CTL5 */
#define CS530X_INOUT_VU BIT(0)
-/* MCLK Reference Source Frequency */
-/* 41KHz related */
-#define CS530X_SYSCLK_REF_45_1MHZ 45158400
-/* 48KHz related */
-#define CS530X_SYSCLK_REF_49_1MHZ 49152000
-
/* System Clock Source */
#define CS530X_SYSCLK_SRC_MCLK 0
#define CS530X_SYSCLK_SRC_PLL 1
diff --git a/sound/soc/codecs/cs53l30.c b/sound/soc/codecs/cs53l30.c
index 93ea2fb4dae9..511453b4c375 100644
--- a/sound/soc/codecs/cs53l30.c
+++ b/sound/soc/codecs/cs53l30.c
@@ -1083,8 +1083,8 @@ static const struct of_device_id cs53l30_of_match[] = {
MODULE_DEVICE_TABLE(of, cs53l30_of_match);
static const struct i2c_device_id cs53l30_id[] = {
- { "cs53l30" },
- {}
+ { .name = "cs53l30" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cs53l30_id);
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index c0dc69ce4d0e..0dea84cd8ef2 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -236,7 +236,8 @@ err:
/* Line discipline .close() */
static void v253_close(struct tty_struct *tty)
{
- struct snd_soc_component *component = tty->disc_data;
+ struct cx20442_codec *codec = tty->disc_data;
+ struct snd_soc_component *component = codec->component;
struct cx20442_priv *cx20442;
tty->disc_data = NULL;
@@ -248,7 +249,7 @@ static void v253_close(struct tty_struct *tty)
/* Prevent the codec driver from further accessing the modem */
cx20442->tty = NULL;
- component->card->pop_time = 0;
+ codec->ready = false;
}
/* Line discipline .hangup() */
@@ -261,7 +262,8 @@ static void v253_hangup(struct tty_struct *tty)
static void v253_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp,
size_t count)
{
- struct snd_soc_component *component = tty->disc_data;
+ struct cx20442_codec *codec = tty->disc_data;
+ struct snd_soc_component *component = codec->component;
struct cx20442_priv *cx20442;
if (!component)
@@ -274,7 +276,7 @@ static void v253_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp,
/* Set up codec driver access to modem controls */
cx20442->tty = tty;
- component->card->pop_time = 1;
+ codec->ready = true;
}
}
@@ -375,7 +377,6 @@ static int cx20442_component_probe(struct snd_soc_component *component)
cx20442->tty = NULL;
snd_soc_component_set_drvdata(component, cx20442);
- component->card->pop_time = 0;
return 0;
}
diff --git a/sound/soc/codecs/cx20442.h b/sound/soc/codecs/cx20442.h
index bb897bcb2486..78ab1eab083e 100644
--- a/sound/soc/codecs/cx20442.h
+++ b/sound/soc/codecs/cx20442.h
@@ -8,6 +8,11 @@
#ifndef _CX20442_CODEC_H
#define _CX20442_CODEC_H
+struct cx20442_codec {
+ struct snd_soc_component *component;
+ bool ready;
+};
+
extern struct tty_ldisc_ops v253_ops;
#endif
diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c
index b0033bf9be3a..83c6cbd40804 100644
--- a/sound/soc/codecs/cx2072x.c
+++ b/sound/soc/codecs/cx2072x.c
@@ -1681,9 +1681,9 @@ static void cx2072x_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id cx2072x_i2c_id[] = {
- { "cx20721" },
- { "cx20723" },
- {}
+ { .name = "cx20721" },
+ { .name = "cx20723" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, cx2072x_i2c_id);
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 94e59546c2fe..4df1a25e318b 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -1238,7 +1238,7 @@ static int da7210_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id da7210_i2c_id[] = {
- { "da7210" },
+ { .name = "da7210" },
{ }
};
MODULE_DEVICE_TABLE(i2c, da7210_i2c_id);
diff --git a/sound/soc/codecs/da7213.c b/sound/soc/codecs/da7213.c
index 19f69a523f22..4bf91ab2553a 100644
--- a/sound/soc/codecs/da7213.c
+++ b/sound/soc/codecs/da7213.c
@@ -1720,11 +1720,6 @@ static int da7213_set_component_pll(struct snd_soc_component *component,
return _da7213_set_component_pll(component, pll_id, source, fref, fout);
}
-/*
- * Select below from Sound Card, not Auto
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
- */
static const u64 da7213_dai_formats =
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
@@ -2271,7 +2266,7 @@ static const struct dev_pm_ops da7213_pm = {
};
static const struct i2c_device_id da7213_i2c_id[] = {
- { "da7213" },
+ { .name = "da7213" },
{ }
};
MODULE_DEVICE_TABLE(i2c, da7213_i2c_id);
diff --git a/sound/soc/codecs/da7218.c b/sound/soc/codecs/da7218.c
index 5c80839704c7..93bd045ed870 100644
--- a/sound/soc/codecs/da7218.c
+++ b/sound/soc/codecs/da7218.c
@@ -3282,8 +3282,8 @@ static int da7218_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id da7218_i2c_id[] = {
- { "da7217", DA7217_DEV_ID },
- { "da7218", DA7218_DEV_ID },
+ { .name = "da7217", .driver_data = DA7217_DEV_ID },
+ { .name = "da7218", .driver_data = DA7218_DEV_ID },
{ }
};
MODULE_DEVICE_TABLE(i2c, da7218_i2c_id);
diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c
index ec4059f381be..f0874d891e12 100644
--- a/sound/soc/codecs/da7219.c
+++ b/sound/soc/codecs/da7219.c
@@ -2712,7 +2712,7 @@ static int da7219_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id da7219_i2c_id[] = {
- { "da7219", },
+ { .name = "da7219" },
{ }
};
MODULE_DEVICE_TABLE(i2c, da7219_i2c_id);
diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c
index 140e449d3ef4..12d1ac98461e 100644
--- a/sound/soc/codecs/da732x.c
+++ b/sound/soc/codecs/da732x.c
@@ -1547,7 +1547,7 @@ err:
}
static const struct i2c_device_id da732x_i2c_id[] = {
- { "da7320"},
+ { .name = "da7320" },
{ }
};
MODULE_DEVICE_TABLE(i2c, da732x_i2c_id);
diff --git a/sound/soc/codecs/da9055.c b/sound/soc/codecs/da9055.c
index a52276e32f2f..a88c13533145 100644
--- a/sound/soc/codecs/da9055.c
+++ b/sound/soc/codecs/da9055.c
@@ -1513,7 +1513,7 @@ static int da9055_i2c_probe(struct i2c_client *i2c)
* and PMIC, which must be different to operate together.
*/
static const struct i2c_device_id da9055_i2c_id[] = {
- { "da9055-codec" },
+ { .name = "da9055-codec" },
{ }
};
MODULE_DEVICE_TABLE(i2c, da9055_i2c_id);
diff --git a/sound/soc/codecs/es8311.c b/sound/soc/codecs/es8311.c
index 564af5c04dbb..6fe3ae41afbd 100644
--- a/sound/soc/codecs/es8311.c
+++ b/sound/soc/codecs/es8311.c
@@ -955,7 +955,7 @@ static int es8311_i2c_probe(struct i2c_client *i2c_client)
}
static const struct i2c_device_id es8311_id[] = {
- { "es8311" },
+ { .name = "es8311" },
{ }
};
MODULE_DEVICE_TABLE(i2c, es8311_id);
diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c
index 9245c33700de..3abe77423f29 100644
--- a/sound/soc/codecs/es8316.c
+++ b/sound/soc/codecs/es8316.c
@@ -12,7 +12,6 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
#include <sound/pcm.h>
@@ -895,8 +894,8 @@ static int es8316_i2c_probe(struct i2c_client *i2c_client)
}
static const struct i2c_device_id es8316_i2c_id[] = {
- {"es8316" },
- {}
+ { .name = "es8316" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, es8316_i2c_id);
diff --git a/sound/soc/codecs/es8323.c b/sound/soc/codecs/es8323.c
index 605375b154c8..b926340256be 100644
--- a/sound/soc/codecs/es8323.c
+++ b/sound/soc/codecs/es8323.c
@@ -18,7 +18,6 @@
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
#include <linux/regmap.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -787,7 +786,7 @@ static int es8323_i2c_probe(struct i2c_client *i2c_client)
}
static const struct i2c_device_id es8323_i2c_id[] = {
- { "es8323" },
+ { .name = "es8323" },
{ }
};
MODULE_DEVICE_TABLE(i2c, es8323_i2c_id);
diff --git a/sound/soc/codecs/es8326.c b/sound/soc/codecs/es8326.c
index 55a65ef99208..a79b2da35099 100644
--- a/sound/soc/codecs/es8326.c
+++ b/sound/soc/codecs/es8326.c
@@ -1347,8 +1347,8 @@ static void es8326_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id es8326_i2c_id[] = {
- {"es8326" },
- {}
+ { .name = "es8326" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, es8326_i2c_id);
diff --git a/sound/soc/codecs/es8328-i2c.c b/sound/soc/codecs/es8328-i2c.c
index 56bfbe9261ce..36a4987e1a59 100644
--- a/sound/soc/codecs/es8328-i2c.c
+++ b/sound/soc/codecs/es8328-i2c.c
@@ -16,8 +16,8 @@
#include "es8328.h"
static const struct i2c_device_id es8328_id[] = {
- { "es8328" },
- { "es8388" },
+ { .name = "es8328" },
+ { .name = "es8388" },
{ }
};
MODULE_DEVICE_TABLE(i2c, es8328_id);
diff --git a/sound/soc/codecs/es8375.c b/sound/soc/codecs/es8375.c
index 0b9406e93c0e..e8747bc24433 100644
--- a/sound/soc/codecs/es8375.c
+++ b/sound/soc/codecs/es8375.c
@@ -752,7 +752,7 @@ static void es8375_i2c_shutdown(struct i2c_client *i2c)
}
static const struct i2c_device_id es8375_id[] = {
- {"es8375"},
+ { .name = "es8375" },
{ }
};
MODULE_DEVICE_TABLE(i2c, es8375_id);
diff --git a/sound/soc/codecs/es8389.c b/sound/soc/codecs/es8389.c
index 449d9574b03a..3484c87853cb 100644
--- a/sound/soc/codecs/es8389.c
+++ b/sound/soc/codecs/es8389.c
@@ -1015,7 +1015,7 @@ MODULE_DEVICE_TABLE(of, es8389_if_dt_ids);
#endif
static const struct i2c_device_id es8389_i2c_id[] = {
- {"es8389"},
+ { .name = "es8389" },
{ }
};
MODULE_DEVICE_TABLE(i2c, es8389_i2c_id);
diff --git a/sound/soc/codecs/es9356.c b/sound/soc/codecs/es9356.c
new file mode 100644
index 000000000000..1122455aab77
--- /dev/null
+++ b/sound/soc/codecs/es9356.c
@@ -0,0 +1,1143 @@
+// SPDX-License-Identifier: GPL-2.0-only
+//
+// es9356.c -- SoundWire codec driver
+//
+// Copyright(c) 2025 Everest Semiconductor Co., Ltd
+//
+//
+
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_type.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <linux/pm_runtime.h>
+#include <sound/sdw.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
+#include <sound/sdca_function.h>
+#include <sound/sdca_regmap.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <sound/jack.h>
+#include <sound/sdca_asoc.h>
+#include "es9356.h"
+
+struct es9356_sdw_priv {
+ struct sdw_slave *slave;
+ struct device *dev;
+ struct regmap *regmap;
+ struct snd_soc_component *component;
+ struct snd_soc_jack *hs_jack;
+
+ /* lock for irq*/
+ struct mutex disable_irq_lock;
+
+ /* lock for pde*/
+ struct mutex pde_lock;
+
+ bool hw_init;
+ bool first_hw_init;
+ int jack_type;
+ bool disable_irq;
+
+ struct delayed_work interrupt_handle_work;
+ struct delayed_work button_detect_work;
+ unsigned int sdca_status;
+};
+
+static int es9356_sdw_component_probe(struct snd_soc_component *component)
+{
+ struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component);
+
+ es9356->component = component;
+
+ return 0;
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -9600, 12, 0);
+static const DECLARE_TLV_DB_SCALE(amic_gain_tlv, 0, 3, 0);
+static const DECLARE_TLV_DB_SCALE(dmic_gain_tlv, 0, 6, 0);
+
+static const struct snd_kcontrol_new es9356_sdca_controls[] = {
+ SDCA_SINGLE_Q78_TLV("FU41 Left Playback Volume",
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_L),
+ ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv),
+ SDCA_SINGLE_Q78_TLV("FU41 Right Playback Volume",
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_R),
+ ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv),
+ SDCA_SINGLE_Q78_TLV("FU36 Left Capture Volume",
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_L),
+ ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv),
+ SDCA_SINGLE_Q78_TLV("FU36 Right Capture Volume",
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_R),
+ ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv),
+ SDCA_SINGLE_Q78_TLV("FU33 Capture Volume",
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU33, ES9356_SDCA_CTL_FU_CH_GAIN, 0),
+ ES9356_GAIN_MIN, ES9356_AMIC_GAIN_MAX, ES9356_AMIC_GAIN_STEP, amic_gain_tlv),
+ SDCA_SINGLE_Q78_TLV("FU21 Left Playback Volume",
+ SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_L),
+ ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv),
+ SDCA_SINGLE_Q78_TLV("FU21 Right Playback Volume",
+ SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_R),
+ ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv),
+ SDCA_SINGLE_Q78_TLV("FU113 Left Capture Volume",
+ SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_L),
+ ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv),
+ SDCA_SINGLE_Q78_TLV("FU113 Right Capture Volume",
+ SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_R),
+ ES9356_VOLUME_MIN, ES9356_VOLUME_MAX, ES9356_VOLUME_STEP, out_vol_tlv),
+ SDCA_SINGLE_Q78_TLV("FU11 Capture Volume",
+ SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU11, ES9356_SDCA_CTL_FU_CH_GAIN, 0),
+ ES9356_GAIN_MIN, ES9356_DMIC_GAIN_MAX, ES9356_DMIC_GAIN_STEP, dmic_gain_tlv),
+};
+
+static const char *const es9356_left_mux_txt[] = {
+ "Left",
+ "Right",
+};
+
+static const char *const es9356_right_mux_txt[] = {
+ "Right",
+ "Left",
+};
+
+static const struct soc_enum es9356_left_mux_enum =
+ SOC_ENUM_SINGLE(ES9356_DAC_SWAP, 1,
+ ARRAY_SIZE(es9356_left_mux_txt), es9356_left_mux_txt);
+static const struct soc_enum es9356_right_mux_enum =
+ SOC_ENUM_SINGLE(ES9356_DAC_SWAP, 0,
+ ARRAY_SIZE(es9356_right_mux_txt), es9356_right_mux_txt);
+
+static const struct snd_kcontrol_new es9356_left_mux_controls =
+ SOC_DAPM_ENUM("Channel MUX", es9356_left_mux_enum);
+static const struct snd_kcontrol_new es9356_right_mux_controls =
+ SOC_DAPM_ENUM("Channel MUX", es9356_right_mux_enum);
+
+static const struct snd_soc_dapm_widget es9356_dapm_widgets[] = {
+ SND_SOC_DAPM_OUTPUT("HP"),
+ SND_SOC_DAPM_OUTPUT("SPK"),
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_INPUT("PDM_DIN"),
+
+ SND_SOC_DAPM_SUPPLY("DMIC Clock", ES9356_DMIC_GPIO, 1, 1, NULL, 0),
+
+ SND_SOC_DAPM_AIF_IN("DP4RX", "DP4 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("DP1TX", "DP1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_PGA("IF DP3RXL", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IF DP3RXR", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("Left Channel MUX", SND_SOC_NOPM, 0, 0, &es9356_left_mux_controls),
+ SND_SOC_DAPM_MUX("Right Channel MUX", SND_SOC_NOPM, 0, 0, &es9356_right_mux_controls),
+
+ SND_SOC_DAPM_DAC("FU 21 Left", NULL,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_MUTE, CH_L), 0, 1),
+ SND_SOC_DAPM_DAC("FU 21 Right", NULL,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_MUTE, CH_R), 0, 1),
+ SND_SOC_DAPM_DAC("FU 41 Left", NULL,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_MUTE, CH_L), 0, 1),
+ SND_SOC_DAPM_DAC("FU 41 Right", NULL,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_MUTE, CH_R), 0, 1),
+ SND_SOC_DAPM_DAC("FU 113 Left", NULL,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_MUTE, CH_L), 0, 1),
+ SND_SOC_DAPM_DAC("FU 113 Right", NULL,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_MUTE, CH_R), 0, 1),
+ SND_SOC_DAPM_DAC("FU 36 Left", NULL,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_MUTE, CH_L), 0, 1),
+ SND_SOC_DAPM_DAC("FU 36 Right", NULL,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_MUTE, CH_R), 0, 1),
+};
+
+static const struct snd_soc_dapm_route es9356_audio_map[] = {
+ {"FU 36 Left", NULL, "MIC1"},
+ {"FU 36 Right", NULL, "MIC1"},
+ {"DP2TX", NULL, "FU 36 Left"},
+ {"DP2TX", NULL, "FU 36 Right"},
+
+ {"PDM_DIN", NULL, "DMIC Clock"},
+ {"FU 113 Left", NULL, "PDM_DIN"},
+ {"FU 113 Right", NULL, "PDM_DIN"},
+ {"DP1TX", NULL, "FU 113 Left"},
+ {"DP1TX", NULL, "FU 113 Right"},
+
+ {"FU 41 Left", NULL, "DP4RX"},
+ {"FU 41 Right", NULL, "DP4RX"},
+
+ {"IF DP3RXL", NULL, "DP3RX"},
+ {"IF DP3RXR", NULL, "DP3RX"},
+
+ {"Left Channel MUX", "Left", "IF DP3RXL"},
+ {"Left Channel MUX", "Right", "IF DP3RXR"},
+ {"Right Channel MUX", "Left", "IF DP3RXL"},
+ {"Right Channel MUX", "Right", "IF DP3RXR"},
+
+ {"FU 21 Left", NULL, "Left Channel MUX"},
+ {"FU 21 Right", NULL, "Right Channel MUX"},
+
+ {"SPK", NULL, "FU 21 Left"},
+ {"SPK", NULL, "FU 21 Right"},
+
+ {"HP", NULL, "FU 41 Left"},
+ {"HP", NULL, "FU 41 Right"},
+};
+
+static int es9356_set_jack_detect(struct snd_soc_component *component,
+ struct snd_soc_jack *hs_jack, void *data)
+{
+ struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ es9356->hs_jack = hs_jack;
+
+ /* we can only resume if the device was initialized at least once */
+ if (!es9356->first_hw_init)
+ return 0;
+
+ ret = pm_runtime_resume_and_get(component->dev);
+ if (ret < 0) {
+ if (ret != -EACCES) {
+ dev_err(component->dev, "%s: failed to resume %d\n", __func__, ret);
+ return ret;
+ }
+ /* pm_runtime not enabled yet */
+ dev_info(component->dev, "%s: skipping jack init for now\n", __func__);
+ return 0;
+ }
+
+ if (es9356->hs_jack)
+ sdw_write_no_pm(es9356->slave, SDW_SCP_SDCA_INTMASK1,
+ (SDW_SCP_SDCA_INTMASK_SDCA_7 | SDW_SCP_SDCA_INTMASK_SDCA_5 | SDW_SCP_SDCA_INTMASK_SDCA_1));
+
+ pm_runtime_mark_last_busy(component->dev);
+ pm_runtime_put_autosuspend(component->dev);
+
+ return 0;
+}
+static const struct snd_soc_component_driver snd_soc_es9356_sdw_component = {
+ .probe = es9356_sdw_component_probe,
+ .controls = es9356_sdca_controls,
+ .num_controls = ARRAY_SIZE(es9356_sdca_controls),
+ .dapm_widgets = es9356_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(es9356_dapm_widgets),
+ .dapm_routes = es9356_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(es9356_audio_map),
+ .set_jack = es9356_set_jack_detect,
+ .endianness = 1,
+};
+
+static int es9356_sdw_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream,
+ int direction)
+{
+ snd_soc_dai_dma_data_set(dai, direction, sdw_stream);
+
+ return 0;
+}
+
+static void es9356_sdw_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ snd_soc_dai_set_dma_data(dai, substream, NULL);
+}
+
+static int es9356_sdca_button(unsigned int *buffer)
+{
+ int cur_button = -1;
+
+ if (*(buffer + 1) | *(buffer + 2))
+ return -EINVAL;
+ switch (*buffer) {
+ case 0x00:
+ cur_button = 0;
+ break;
+ case 0x20:
+ cur_button = SND_JACK_BTN_4;
+ break;
+ case 0x10:
+ cur_button = SND_JACK_BTN_2;
+ break;
+ case 0x08:
+ cur_button = SND_JACK_BTN_1;
+ break;
+ case 0x02:
+ cur_button = SND_JACK_BTN_3;
+ break;
+ case 0x01:
+ cur_button = SND_JACK_BTN_0;
+ break;
+ default:
+ break;
+ }
+
+ return cur_button;
+}
+
+static int es9356_sdca_button_detect(struct es9356_sdw_priv *es9356)
+{
+ unsigned int btn_type = 0, offset, idx, val, owner;
+ unsigned int button[3];
+ int ret;
+
+ ret = regmap_read(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_HID, ES9356_SDCA_ENT_HID01, ES9356_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), &owner);
+ if (ret < 0 || owner == 0x01)
+ return 0;
+
+ ret = regmap_read(es9356->regmap, ES9356_BUF_ADDR_HID, &offset);
+ if (ret < 0)
+ goto button_det_end;
+
+ for (idx = 0; idx < ARRAY_SIZE(button); idx++) {
+ ret = regmap_read(es9356->regmap, ES9356_BUF_ADDR_HID + offset + idx, &val);
+ if (ret < 0)
+ goto button_det_end;
+ button[idx] = val;
+ }
+
+ btn_type = es9356_sdca_button(&button[0]);
+
+button_det_end:
+ if (owner == 0x00)
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_HID, ES9356_SDCA_ENT_HID01, ES9356_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01);
+
+ return btn_type;
+}
+
+static int es9356_sdca_headset_detect(struct es9356_sdw_priv *es9356)
+{
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_DETECTED_MODE, 0), &reg);
+
+ if (ret < 0)
+ goto io_error;
+
+ switch (reg) {
+ case 0x00:
+ es9356->jack_type = 0;
+ break;
+ case 0x03:
+ es9356->jack_type = SND_JACK_HEADPHONE;
+ break;
+ case 0x04:
+ es9356->jack_type = SND_JACK_HEADSET;
+ break;
+ default:
+ es9356->jack_type = 0;
+ return -1;
+ }
+
+ if (reg) {
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_SELECTED_MODE, 0), reg);
+ regmap_write(es9356->regmap, ES9356_HP_DETECTTIME, 0x75);
+ } else {
+ regmap_write(es9356->regmap, ES9356_HP_DETECTTIME, 0xa4);
+ }
+
+ return 0;
+
+io_error:
+ pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
+ return ret;
+}
+
+static void es9356_interrupt_handler(struct work_struct *work)
+{
+ struct es9356_sdw_priv *es9356 =
+ container_of(work, struct es9356_sdw_priv, interrupt_handle_work.work);
+ int ret, btn_type = 0;
+
+ if (!es9356->hs_jack)
+ return;
+
+ if (!es9356->component->card || !es9356->component->card->instantiated)
+ return;
+
+ /* Handling different types of interrupts based on the mask bit */
+ if (es9356->sdca_status & SDW_SCP_SDCA_INT_SDCA_7) {
+ btn_type = es9356_sdca_button_detect(es9356);
+ if (btn_type < 0)
+ return;
+ } else {
+ ret = es9356_sdca_headset_detect(es9356);
+ if (ret < 0)
+ return;
+ }
+
+ if (es9356->jack_type != SND_JACK_HEADSET)
+ btn_type = 0;
+
+ snd_soc_jack_report(es9356->hs_jack, es9356->jack_type | btn_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+ SND_JACK_BTN_4);
+
+ if (btn_type) {
+ snd_soc_jack_report(es9356->hs_jack, es9356->jack_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+ SND_JACK_BTN_4);
+ mod_delayed_work(system_power_efficient_wq,
+ &es9356->button_detect_work, msecs_to_jiffies(280));
+ }
+}
+
+static void es9356_button_detect_handler(struct work_struct *work)
+{
+ struct es9356_sdw_priv *es9356 =
+ container_of(work, struct es9356_sdw_priv, button_detect_work.work);
+ int ret, idx, btn_type = 0;
+ unsigned int reg, offset;
+ unsigned int button[3];
+
+ /* Check headset */
+ ret = regmap_read(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_DETECTED_MODE, 0), &reg);
+
+ if (ret < 0)
+ goto io_error;
+
+ if (reg == 0x04) {
+ ret = regmap_read(es9356->regmap, ES9356_BUF_ADDR_HID, &offset);
+ if (ret < 0)
+ goto io_error;
+ for (idx = 0; idx < ARRAY_SIZE(button); idx++) {
+ ret = regmap_read(es9356->regmap, ES9356_BUF_ADDR_HID + offset + idx, &reg);
+ if (ret < 0)
+ goto io_error;
+ button[idx] = reg;
+ }
+ btn_type = es9356_sdca_button(&button[0]);
+ if (btn_type < 0)
+ return;
+ }
+
+ snd_soc_jack_report(es9356->hs_jack, es9356->jack_type | btn_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+ SND_JACK_BTN_4);
+
+ if (btn_type) {
+ snd_soc_jack_report(es9356->hs_jack, es9356->jack_type,
+ SND_JACK_HEADSET |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+ SND_JACK_BTN_4);
+ mod_delayed_work(system_power_efficient_wq,
+ &es9356->button_detect_work, msecs_to_jiffies(280));
+ }
+
+ return;
+io_error:
+ pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
+}
+
+static int es9356_pde_transition_delay(struct es9356_sdw_priv *es9356, unsigned char func,
+ unsigned char entity, unsigned char ps)
+{
+ unsigned int retries = 10, val;
+
+ /* waiting for Actual PDE becomes to PS0/PS3 */
+ while (retries) {
+ regmap_read(es9356->regmap,
+ SDW_SDCA_CTL(func, entity, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0), &val);
+ if (val == ps)
+ return 1;
+
+ usleep_range(1000, 1500);
+ retries--;
+ }
+ if (!retries) {
+ dev_dbg(&es9356->slave->dev, "%s PDE is NOT %s", __func__, ps?"PS3":"PS0");
+ }
+ return 0;
+}
+
+static int es9356_power_state(struct snd_soc_dai *dai, unsigned char ps, unsigned int *rate)
+{
+ struct snd_soc_component *component = dai->component;
+ struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component);
+ unsigned char ps0 = 0x0, ps3 = 0x3;
+ unsigned char func, cs_entity, pde_entity;
+ int ret;
+
+ switch (dai->id) {
+ case ES9356_DMIC:
+ func = FUNC_NUM_MIC;
+ cs_entity = ES9356_SDCA_ENT_CS113;
+ pde_entity = ES9356_SDCA_ENT_PDE11;
+ break;
+ case ES9356_AMP:
+ func = FUNC_NUM_AMP;
+ cs_entity = ES9356_SDCA_ENT_CS21;
+ pde_entity = ES9356_SDCA_ENT_PDE23;
+ break;
+ case ES9356_JACK_IN:
+ func = FUNC_NUM_UAJ;
+ cs_entity = ES9356_SDCA_ENT_CS36;
+ pde_entity = ES9356_SDCA_ENT_PDE34;
+ break;
+ case ES9356_JACK_OUT:
+ func = FUNC_NUM_UAJ;
+ cs_entity = ES9356_SDCA_ENT_CS41;
+ pde_entity = ES9356_SDCA_ENT_PDE47;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* power state changes are not independent across functions */
+ mutex_lock(&es9356->pde_lock);
+ ret = es9356_pde_transition_delay(es9356, func, pde_entity, ps?ps0:ps3);
+ if (ret) {
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(func, pde_entity, ES9356_SDCA_CTL_REQ_POWER_STATE, 0), ps?ps3:ps0);
+ es9356_pde_transition_delay(es9356, func, pde_entity, ps?ps3:ps0);
+ } else
+ dev_dbg(component->dev, "%s PDE is already %d\n", __func__, ps?ps0:ps3);
+
+ mutex_unlock(&es9356->pde_lock);
+
+ if (rate)
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(func, cs_entity, ES9356_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), *rate);
+
+ return 0;
+}
+
+static int es9356_sdw_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_config stream_config = {0};
+ struct sdw_port_config port_config = {0};
+ struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
+ unsigned char ps0 = 0x0;
+ unsigned int rate;
+ int ret;
+
+ if (!sdw_stream)
+ return -EINVAL;
+
+ if (!es9356->slave)
+ return -EINVAL;
+
+ /* SoundWire specific configuration */
+ snd_sdw_params_to_config(substream, params, &stream_config, &port_config);
+
+ port_config.num = dai->id;
+
+ ret = sdw_stream_add_slave(es9356->slave, &stream_config,
+ &port_config, 1, sdw_stream);
+ if (ret) {
+ dev_err(dai->dev, "Unable to configure port\n");
+ return -EINVAL;
+ }
+
+ switch (params_rate(params)) {
+ case 16000:
+ rate = ES9356_SDCA_RATE_16000HZ;
+ break;
+ case 44100:
+ rate = ES9356_SDCA_RATE_44100HZ;
+ break;
+ case 48000:
+ rate = ES9356_SDCA_RATE_48000HZ;
+ break;
+ case 96000:
+ rate = ES9356_SDCA_RATE_96000HZ;
+ break;
+ default:
+ dev_err(component->dev, "%s: Rate %d is not supported\n",
+ __func__, params_rate(params));
+ return -EINVAL;
+ }
+
+ ret = es9356_power_state(dai, ps0, &rate);
+ if (ret) {
+ dev_err(component->dev, "%s: Invalid dai id: %d\n",
+ __func__, dai->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int es9356_sdw_pcm_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_component *component = dai->component;
+ struct es9356_sdw_priv *es9356 = snd_soc_component_get_drvdata(component);
+ struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
+ unsigned char ps3 = 0x3;
+ int ret;
+
+ if (!es9356->slave)
+ return -EINVAL;
+
+ sdw_stream_remove_slave(es9356->slave, sdw_stream);
+
+ ret = es9356_power_state(dai, ps3, NULL);
+ if (ret) {
+ dev_err(component->dev, "%s: Invalid dai id: %d\n",
+ __func__, dai->id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops es9356_sdw_ops = {
+ .hw_params = es9356_sdw_pcm_hw_params,
+ .hw_free = es9356_sdw_pcm_hw_free,
+ .set_stream = es9356_sdw_set_sdw_stream,
+ .shutdown = es9356_sdw_shutdown,
+};
+
+static struct snd_soc_dai_driver es9356_sdw_dai[] = {
+ {
+ .name = "es9356-sdp-aif4",
+ .id = ES9356_DMIC,
+ .capture = {
+ .stream_name = "DP1 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &es9356_sdw_ops,
+ },
+ {
+ .name = "es9356-sdp-aif2",
+ .id = ES9356_JACK_IN,
+ .capture = {
+ .stream_name = "DP2 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &es9356_sdw_ops,
+ },
+ {
+ .name = "es9356-sdp-aif3",
+ .id = ES9356_AMP,
+ .playback = {
+ .stream_name = "DP3 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &es9356_sdw_ops,
+ },
+ {
+ .name = "es9356-sdp-aif1",
+ .id = ES9356_JACK_OUT,
+ .playback = {
+ .stream_name = "DP4 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ },
+ .ops = &es9356_sdw_ops,
+ },
+};
+
+static int es9356_sdca_mbq_size(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_L):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_R):
+ case SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_L):
+ case SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_R):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_L):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_R):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_L):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_R):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU33, ES9356_SDCA_CTL_FU_CH_GAIN, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU11, ES9356_SDCA_CTL_FU_CH_GAIN, 0):
+ return 2;
+ default:
+ return 1;
+ }
+}
+
+static struct regmap_sdw_mbq_cfg es9356_mbq_config = {
+ .mbq_size = es9356_sdca_mbq_size,
+};
+
+static bool es9356_sdca_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case ES9356_BUF_ADDR_HID:
+ case ES9356_HID_BYTE2:
+ case ES9356_HID_BYTE3:
+ case ES9356_HID_BYTE4:
+ case SDW_SDCA_CTL(FUNC_NUM_HID, ES9356_SDCA_ENT_HID01, ES9356_SDCA_CTL_HIDTX_CURRENT_OWNER, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_DETECTED_MODE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_GE35, ES9356_SDCA_CTL_SELECTED_MODE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_PDE23, ES9356_SDCA_CTL_REQ_POWER_STATE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_PDE23, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_PDE11, ES9356_SDCA_CTL_REQ_POWER_STATE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_PDE11, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_PDE47, ES9356_SDCA_CTL_REQ_POWER_STATE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_PDE47, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_PDE34, ES9356_SDCA_CTL_REQ_POWER_STATE, 0):
+ case SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_PDE34, ES9356_SDCA_CTL_ACTUAL_POWER_STATE, 0):
+ case ES9356_FLAGS_HP:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_config es9356_sdca_regmap = {
+ .reg_bits = 32,
+ .val_bits = 16,
+ .volatile_reg = es9356_sdca_volatile_register,
+ .max_register = 0x45ffffff,
+ .cache_type = REGCACHE_MAPLE,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+static void es9356_register_init(struct es9356_sdw_priv *es9356)
+{
+ regmap_write(es9356->regmap, ES9356_STATE, 0x02);
+ regmap_write(es9356->regmap, ES9356_ENDPOINT_MODE, 0x24);
+ regmap_write(es9356->regmap, ES9356_PRE_DIV_CTL, 0x00);
+ regmap_write(es9356->regmap, ES9356_ADC_OSR, 0x18);
+ regmap_write(es9356->regmap, ES9356_ADC_OSRGAIN, 0x13);
+ regmap_write(es9356->regmap, ES9356_DAC_OSR, 0x16);
+ regmap_write(es9356->regmap, ES9356_CLK_CTL, 0x0f);
+ regmap_write(es9356->regmap, ES9356_CSM_RESET, 0x01);
+ regmap_write(es9356->regmap, ES9356_CLK_SEL, 0x30);
+
+ regmap_write(es9356->regmap, ES9356_DETCLK_CTL, 0x51);
+ regmap_write(es9356->regmap, ES9356_HP_TYPE, 0x10);
+ regmap_write(es9356->regmap, ES9356_MICBIAS_CTL, 0x10);
+ regmap_write(es9356->regmap, ES9356_HPDETECT_CTL, 0x07);
+ regmap_write(es9356->regmap, ES9356_ADC_ANA, 0x30);
+ regmap_write(es9356->regmap, ES9356_PGA_CTL, 0xa8);
+ regmap_write(es9356->regmap, ES9356_ADC_INT, 0xaa);
+ regmap_write(es9356->regmap, ES9356_ADC_LP, 0x19);
+ regmap_write(es9356->regmap, ES9356_VMID1SEL, 0xbc);
+ regmap_write(es9356->regmap, ES9356_VMID_TIME, 0x0b);
+ regmap_write(es9356->regmap, ES9356_STATE_TIME, 0xbb);
+ regmap_write(es9356->regmap, ES9356_HP_SPK_TIME, 0x77);
+ regmap_write(es9356->regmap, ES9356_HP_DETECTTIME, 0xa4);
+ regmap_write(es9356->regmap, ES9356_MICBIAS_SEL, 0x15);
+ regmap_write(es9356->regmap, ES9356_KEY_PRESS_TIME, 0xff);
+ regmap_write(es9356->regmap, ES9356_KEY_RELEASE_TIME, 0xff);
+ regmap_write(es9356->regmap, ES9356_KEY_HOLD_TIME, 0x0f);
+ regmap_write(es9356->regmap, ES9356_BTSEL_REF, 0x00);
+ regmap_write(es9356->regmap, ES9356_KEYD_DETECT, 0x18);
+ regmap_write(es9356->regmap, ES9356_MICBIAS_RES, 0x03);
+ regmap_write(es9356->regmap, ES9356_BUTTON_CHARGE, 0x00);
+ regmap_write(es9356->regmap, ES9356_CALIBRATION_TIME, 0x13);
+ regmap_write(es9356->regmap, ES9356_CALIBRATION_SETTING, 0xf4);
+
+ regmap_write(es9356->regmap, ES9356_SPK_VOLUME, 0x33);
+ regmap_write(es9356->regmap, ES9356_DAC_VROI, 0x01);
+ regmap_write(es9356->regmap, ES9356_DAC_LP, 0x00);
+ regmap_write(es9356->regmap, ES9356_HP_IBIAS, 0x04);
+ regmap_write(es9356->regmap, ES9356_HP_LP, 0x03);
+ regmap_write(es9356->regmap, ES9356_SPKLDO_CTL, 0x65);
+ regmap_write(es9356->regmap, ES9356_SPKBIAS_COMP, 0x09);
+ regmap_write(es9356->regmap, ES9356_VMID1STL, 0x00);
+ regmap_write(es9356->regmap, ES9356_VMID2STL, 0x00);
+ regmap_write(es9356->regmap, ES9356_VSEL, 0xfc);
+
+ regmap_write(es9356->regmap, ES9356_IBIASGEN, 0x10);
+ regmap_write(es9356->regmap, ES9356_ADC_AMIC_CTL, 0x0d);
+ regmap_write(es9356->regmap, ES9356_STATE, 0x0e);
+ regmap_write(es9356->regmap, ES9356_CSM_RESET, 0x00);
+ regmap_write(es9356->regmap, ES9356_HP_TYPE, 0x08);
+
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_L), ES9356_DEFAULT_VOLUME);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_FU113, ES9356_SDCA_CTL_FU_VOLUME, CH_R), ES9356_DEFAULT_VOLUME);
+
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_L), ES9356_DEFAULT_VOLUME);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_FU21, ES9356_SDCA_CTL_FU_VOLUME, CH_R), ES9356_DEFAULT_VOLUME);
+
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_L), ES9356_DEFAULT_VOLUME);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU41, ES9356_SDCA_CTL_FU_VOLUME, CH_R), ES9356_DEFAULT_VOLUME);
+
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_L), ES9356_DEFAULT_VOLUME);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_FU36, ES9356_SDCA_CTL_FU_VOLUME, CH_R), ES9356_DEFAULT_VOLUME);
+}
+
+static int es9356_sdca_io_init(struct device *dev, struct sdw_slave *slave)
+{
+ struct es9356_sdw_priv *es9356 = dev_get_drvdata(&slave->dev);
+
+ if (es9356->hw_init)
+ return 0;
+
+ es9356->disable_irq = false;
+
+ regcache_cache_only(es9356->regmap, false);
+
+ if (es9356->first_hw_init) {
+ regcache_cache_bypass(es9356->regmap, true);
+ } else {
+ /* update count of parent 'active' children */
+ pm_runtime_set_active(&slave->dev);
+
+ es9356_register_init(es9356);
+ }
+ pm_runtime_get_noresume(&slave->dev);
+
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT_XU12, ES9356_SDCA_CTL_SELECTED_MODE, 0), 0x01);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_MIC, ES9356_SDCA_ENT0, ES9356_SDCA_CTL_FUNC_STATUS, 0), 0x40);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT_XU22, ES9356_SDCA_CTL_SELECTED_MODE, 0), 0x01);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, ES9356_SDCA_ENT0, ES9356_SDCA_CTL_FUNC_STATUS, 0), 0x40);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_XU42, ES9356_SDCA_CTL_SELECTED_MODE, 0), 0x01);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT_XU36, ES9356_SDCA_CTL_SELECTED_MODE, 0), 0x01);
+ regmap_write(es9356->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_UAJ, ES9356_SDCA_ENT0, ES9356_SDCA_CTL_FUNC_STATUS, 0), 0x40);
+
+ if (es9356->first_hw_init) {
+ regcache_cache_bypass(es9356->regmap, false);
+ regcache_mark_dirty(es9356->regmap);
+ } else
+ es9356->first_hw_init = true;
+
+ es9356->hw_init = true;
+
+ pm_runtime_mark_last_busy(&slave->dev);
+ pm_runtime_put_autosuspend(&slave->dev);
+
+ return 0;
+}
+
+static int es9356_sdw_update_status(struct sdw_slave *slave,
+ enum sdw_slave_status status)
+{
+ struct es9356_sdw_priv *es9356 = dev_get_drvdata(&slave->dev);
+
+ if (status == SDW_SLAVE_UNATTACHED) {
+ es9356->hw_init = false;
+ cancel_delayed_work_sync(&es9356->interrupt_handle_work);
+ cancel_delayed_work_sync(&es9356->button_detect_work);
+ regcache_cache_only(es9356->regmap, true);
+ }
+
+ if (status == SDW_SLAVE_ATTACHED) {
+ if (es9356->hs_jack)
+ sdw_write_no_pm(es9356->slave, SDW_SCP_SDCA_INTMASK1,
+ (SDW_SCP_SDCA_INTMASK_SDCA_7 | SDW_SCP_SDCA_INTMASK_SDCA_5 | SDW_SCP_SDCA_INTMASK_SDCA_1));
+ }
+
+ if (es9356->hw_init || status != SDW_SLAVE_ATTACHED)
+ return 0;
+
+ return es9356_sdca_io_init(&slave->dev, slave);
+}
+
+static int es9356_sdw_read_prop(struct sdw_slave *slave)
+{
+ struct sdw_slave_prop *prop = &slave->prop;
+ int nval;
+ int i, j;
+ u32 bit;
+ unsigned long addr;
+ struct sdw_dpn_prop *dpn;
+
+ prop->paging_support = true;
+
+ /*
+ * first we need to allocate memory for set bits in port lists
+ * the port allocation is completely arbitrary:
+ * DP0 is not supported
+ * DP3 and DP4 is sink
+ * DP1 and DP2 is source
+ */
+ prop->source_ports = BIT(1) | BIT(2);
+ prop->sink_ports = BIT(3) | BIT(4);
+
+ nval = hweight32(prop->source_ports);
+ prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval,
+ sizeof(*prop->src_dpn_prop),
+ GFP_KERNEL);
+ if (!prop->src_dpn_prop)
+ return -ENOMEM;
+
+ i = 0;
+ dpn = prop->src_dpn_prop;
+ addr = prop->source_ports;
+ for_each_set_bit(bit, &addr, 32) {
+ dpn[i].num = bit;
+ dpn[i].type = SDW_DPN_FULL;
+ dpn[i].simple_ch_prep_sm = true;
+ i++;
+ }
+
+ /* do this again for sink now */
+ nval = hweight32(prop->sink_ports);
+ prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval,
+ sizeof(*prop->sink_dpn_prop),
+ GFP_KERNEL);
+ if (!prop->sink_dpn_prop)
+ return -ENOMEM;
+
+ j = 0;
+ dpn = prop->sink_dpn_prop;
+ addr = prop->sink_ports;
+ for_each_set_bit(bit, &addr, 32) {
+ dpn[j].num = bit;
+ dpn[j].type = SDW_DPN_FULL;
+ dpn[j].simple_ch_prep_sm = true;
+ j++;
+ }
+
+ /* wake-up event */
+ prop->wake_capable = 1;
+
+ return 0;
+}
+
+static int es9356_sdw_interrupt_callback(struct sdw_slave *slave,
+ struct sdw_slave_intr_status *status)
+{
+ struct es9356_sdw_priv *es9356 = dev_get_drvdata(&slave->dev);
+ unsigned int sdca_cascade, scp_sdca_stat1 = 0;
+ int count = 0, retry = 3;
+ int ret, stat, reg;
+
+ mutex_lock(&es9356->disable_irq_lock);
+
+ ret = sdw_read_no_pm(es9356->slave, SDW_SCP_SDCA_INT1);
+ if (ret < 0)
+ goto io_error;
+ es9356->sdca_status = ret;
+
+ do {
+ reg = sdw_read_no_pm(es9356->slave, SDW_SCP_SDCA_INT1);
+ if (reg < 0)
+ goto io_error;
+ if (reg & SDW_SCP_SDCA_INTMASK_SDCA_1) {
+ ret = sdw_update_no_pm(es9356->slave, SDW_SCP_SDCA_INT1,
+ SDW_SCP_SDCA_INT_SDCA_1, SDW_SCP_SDCA_INT_SDCA_1);
+ if (ret < 0)
+ goto io_error;
+ }
+
+ if (reg & SDW_SCP_SDCA_INTMASK_SDCA_5) {
+ ret = sdw_update_no_pm(es9356->slave, SDW_SCP_SDCA_INT1,
+ SDW_SCP_SDCA_INT_SDCA_5, SDW_SCP_SDCA_INT_SDCA_5);
+ if (ret < 0)
+ goto io_error;
+ }
+
+ if (reg & SDW_SCP_SDCA_INTMASK_SDCA_7) {
+ ret = sdw_update_no_pm(es9356->slave, SDW_SCP_SDCA_INT1,
+ SDW_SCP_SDCA_INT_SDCA_7, SDW_SCP_SDCA_INT_SDCA_7);
+ if (ret < 0)
+ goto io_error;
+ }
+
+ ret = sdw_read_no_pm(es9356->slave, SDW_DP0_INT);
+ if (ret < 0)
+ goto io_error;
+ sdca_cascade = ret & SDW_DP0_SDCA_CASCADE;
+
+ ret = sdw_read_no_pm(es9356->slave, SDW_SCP_SDCA_INT1);
+ if (ret < 0)
+ goto io_error;
+ scp_sdca_stat1 = ret &
+ (SDW_SCP_SDCA_INTMASK_SDCA_1 | SDW_SCP_SDCA_INTMASK_SDCA_5 | SDW_SCP_SDCA_INTMASK_SDCA_7);
+
+ stat = scp_sdca_stat1 || sdca_cascade;
+
+ count++;
+ } while (stat != 0 && count < retry);
+
+ /* The 280 ms figure was determined through testing */
+ if (status->sdca_cascade && !es9356->disable_irq)
+ mod_delayed_work(system_power_efficient_wq,
+ &es9356->interrupt_handle_work, msecs_to_jiffies(280));
+
+ mutex_unlock(&es9356->disable_irq_lock);
+ return 0;
+
+io_error:
+ mutex_unlock(&es9356->disable_irq_lock);
+ pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret);
+ return ret;
+}
+
+static const struct sdw_slave_ops es9356_sdw_slave_ops = {
+ .read_prop = es9356_sdw_read_prop,
+ .interrupt_callback = es9356_sdw_interrupt_callback,
+ .update_status = es9356_sdw_update_status,
+};
+
+static int es9356_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave *slave)
+{
+ struct es9356_sdw_priv *es9356;
+ int ret;
+
+ es9356 = devm_kzalloc(dev, sizeof(*es9356), GFP_KERNEL);
+ if (!es9356)
+ return -ENOMEM;
+
+ dev_set_drvdata(dev, es9356);
+
+ es9356->slave = slave;
+ es9356->regmap = regmap;
+ mutex_init(&es9356->disable_irq_lock);
+ mutex_init(&es9356->pde_lock);
+
+ regcache_cache_only(es9356->regmap, true);
+
+ es9356->hw_init = false;
+ es9356->first_hw_init = false;
+
+ INIT_DELAYED_WORK(&es9356->interrupt_handle_work,
+ es9356_interrupt_handler);
+ INIT_DELAYED_WORK(&es9356->button_detect_work,
+ es9356_button_detect_handler);
+
+ ret = devm_snd_soc_register_component(dev,
+ &snd_soc_es9356_sdw_component,
+ es9356_sdw_dai,
+ ARRAY_SIZE(es9356_sdw_dai));
+ if (ret) {
+ dev_err_probe(dev, ret, "Failed to register component\n");
+ return ret;
+ }
+ /* set autosuspend parameters */
+ pm_runtime_set_autosuspend_delay(dev, 3000);
+ pm_runtime_use_autosuspend(dev);
+ /* make sure the device does not suspend immediately */
+ pm_runtime_mark_last_busy(dev);
+ pm_runtime_enable(dev);
+
+ return 0;
+}
+
+static int es9356_sdw_probe(struct sdw_slave *slave,
+ const struct sdw_device_id *id)
+{
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init_sdw_mbq_cfg(&slave->dev, slave, &es9356_sdca_regmap, &es9356_mbq_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ return es9356_sdca_init(&slave->dev, regmap, slave);
+}
+
+static void es9356_sdw_remove(struct sdw_slave *slave)
+{
+ struct es9356_sdw_priv *es9356 = dev_get_drvdata(&slave->dev);
+
+ if (es9356->hw_init) {
+ cancel_delayed_work_sync(&es9356->interrupt_handle_work);
+ cancel_delayed_work_sync(&es9356->button_detect_work);
+ }
+
+ if (es9356->first_hw_init)
+ pm_runtime_disable(&slave->dev);
+
+ mutex_destroy(&es9356->disable_irq_lock);
+ mutex_destroy(&es9356->pde_lock);
+}
+
+static const struct sdw_device_id es9356_sdw_id[] = {
+ SDW_SLAVE_ENTRY_EXT(0x04b3, 0x9356, 0x02, 0, 0),
+ SDW_SLAVE_ENTRY_EXT(0x04b3, 0x9356, 0x03, 0, 0),
+ {},
+};
+MODULE_DEVICE_TABLE(sdw, es9356_sdw_id);
+
+static int es9356_sdca_dev_suspend(struct device *dev)
+{
+ struct es9356_sdw_priv *es9356 = dev_get_drvdata(dev);
+
+ cancel_delayed_work_sync(&es9356->interrupt_handle_work);
+ cancel_delayed_work_sync(&es9356->button_detect_work);
+
+ regcache_cache_only(es9356->regmap, true);
+
+ return 0;
+}
+
+static int es9356_sdca_dev_system_suspend(struct device *dev)
+{
+ struct es9356_sdw_priv *es9356 = dev_get_drvdata(dev);
+
+ mutex_lock(&es9356->disable_irq_lock);
+ es9356->disable_irq = true;
+ mutex_unlock(&es9356->disable_irq_lock);
+
+ return es9356_sdca_dev_suspend(dev);
+}
+
+#define es9356_PROBE_TIMEOUT 2000
+
+static int es9356_sdca_dev_resume(struct device *dev)
+{
+ struct sdw_slave *slave = dev_to_sdw_dev(dev);
+ struct es9356_sdw_priv *es9356 = dev_get_drvdata(dev);
+ int ret;
+
+ if (!slave->unattach_request)
+ es9356->disable_irq = false;
+
+ ret = sdw_slave_wait_for_init(slave, es9356_PROBE_TIMEOUT);
+ if (ret) {
+ sdw_show_ping_status(slave->bus, true);
+ return ret;
+ }
+
+ regcache_cache_only(es9356->regmap, false);
+ regcache_sync(es9356->regmap);
+ return 0;
+}
+
+static const struct dev_pm_ops es9356_sdca_pm = {
+ SYSTEM_SLEEP_PM_OPS(es9356_sdca_dev_system_suspend, es9356_sdca_dev_resume)
+ RUNTIME_PM_OPS(es9356_sdca_dev_suspend, es9356_sdca_dev_resume, NULL)
+};
+
+static struct sdw_driver es9356_sdw_driver = {
+ .driver = {
+ .name = "es9356",
+ .pm = pm_ptr(&es9356_sdca_pm),
+ },
+ .probe = es9356_sdw_probe,
+ .remove = es9356_sdw_remove,
+ .ops = &es9356_sdw_slave_ops,
+ .id_table = es9356_sdw_id,
+};
+module_sdw_driver(es9356_sdw_driver);
+
+MODULE_IMPORT_NS("SND_SOC_SDCA");
+MODULE_DESCRIPTION("ASoC ES9356 SDCA SDW codec driver");
+MODULE_AUTHOR("Michael Zhang <zhangyi@everest-semi.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/es9356.h b/sound/soc/codecs/es9356.h
new file mode 100644
index 000000000000..2a676f36590f
--- /dev/null
+++ b/sound/soc/codecs/es9356.h
@@ -0,0 +1,208 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ES9356_H__
+#define __ES9356_H__
+
+/*ES9356 Implementation-define*/
+#define ES9356_FLAGS_HP 0x2003
+#define ES9356_CSM_RESET 0x2020
+#define ES9356_FUC_RESET 0x2021
+#define ES9356_STATE 0x2022
+#define ES9356_VMID_TIME 0x2023
+#define ES9356_STATE_TIME 0x2024
+#define ES9356_HP_SPK_TIME 0x2025
+#define ES9356_WP_ENABLE 0x2026
+#define ES9356_DMIC_GPIO 0x2027
+#define ES9356_ENDPOINT_MODE 0x2028
+
+/*HP DETECT*/
+#define ES9356_HP_TYPE 0x2029
+#define ES9356_HP_DETECTTIME 0x202A
+#define ES9356_MICBIAS_SEL 0x202B
+#define ES9356_KEY_PRESS_TIME 0x202C
+#define ES9356_KEY_RELEASE_TIME 0x202D
+#define ES9356_KEY_HOLD_TIME 0x202E
+#define ES9356_BTSEL_REF 0x202F
+#define ES9356_BUTTON_CHARGE 0x2030
+
+#define ES9356_KEYD_DETECT 0x2031
+#define ES9356_DPEN_TIME 0x2032
+#define ES9356_TIMER_CHECK 0x2033
+#define ES9356_IBIASGEN 0x2041
+#define ES9356_VMID1SEL 0x2042
+#define ES9356_VMID1STL 0x2043
+#define ES9356_VMID2SEL 0x2044
+#define ES9356_VMID2STL 0x2045
+#define ES9356_VSEL 0x2046
+#define ES9356_MICBIAS_CTL 0x2047
+#define ES9356_HPDETECT_CTL 0x2048
+#define ES9356_MICBIAS_RES 0x2049
+
+/*CLK*/
+#define ES9356_CLK_SEL 0x2050
+#define ES9356_CLK_CTL 0x2051
+#define ES9356_DETCLK_CTL 0x2052
+#define ES9356_CPCLK_CTL 0x2053
+#define ES9356_SPKCLK_CTL 0x2054
+#define ES9356_PRE_DIV_CTL 0x2055
+#define ES9356_DLL_MODE 0x2056
+#define ES9356_ANACLK_SEL 0x2057
+#define ES9356_OSRCLK_SEL 0x2058
+#define ES9356_DSPCLK_SEL 0x2059
+#define ES9356_SPK9M_MODE 0x205a
+
+/*ADC DIG CTL*/
+#define ES9356_DMIC_POL 0x2061
+#define ES9356_ADC_SWAP 0x2062
+#define ES9356_ADC_OSR 0x2063
+#define ES9356_ADC_OSRGAIN 0x2064
+#define ES9356_ADC_CLEARRAM 0x2065
+#define ES9356_ADC_RAMP 0x2066
+#define ES9356_ADC_HPF1 0x2067
+#define ES9356_ADC_HPF2 0x2068
+#define ES9356_ADC_ALC 0x206C
+#define ES9356_ALC_LEVEL 0x206D
+#define ES9356_ALC_RAMP_WINSIZE 0x206E
+
+/*ADC ANA CTL*/
+#define ES9356_ADC_REF_EN 0x2080
+#define ES9356_ADC_AMIC_CTL 0x2081
+#define ES9356_ADC_ANA 0x2082
+#define ES9356_PGA_CTL 0x2083
+#define ES9356_ADC_INT 0x2084
+#define ES9356_ADC_VCM 0x2085
+#define ES9356_ADC_VRPBIAS 0x2086
+#define ES9356_ADC_LP 0x2087
+
+/*DAC DIG CTL*/
+#define ES9356_DAC_FSMODE 0x2090
+#define ES9356_DAC_OSR 0x2091
+#define ES9356_DAC_INV 0x2092
+#define ES9356_DAC_RAMP 0x2093
+#define ES9356_DAC_VPPSCALE 0x2094
+#define ES9356_DAC_SWAP 0x2097
+#define ES9356_SPKCMP_VPPSC 0x20A0
+#define ES9356_CALIBRATION_TIME 0x20A1
+#define ES9356_CALIBRATION_SETTING 0x20A2
+#define ES9356_DAC_OFFSET_LH 0x20A3
+#define ES9356_DAC_OFFSET_LL 0x20A4
+#define ES9356_DAC_OFFSET_RH 0x20A5
+#define ES9356_DAC_OFFSET_RL 0x20A6
+
+/*DAC ANA CTL*/
+#define ES9356_DAC_REF_EN 0x20B0
+#define ES9356_DAC_ENABLE 0x20B1
+#define ES9356_DAC_VROI 0x20B2
+#define ES9356_DAC_LP 0x20B3
+
+/*HP CTL*/
+#define ES9356_CHARGEPUMP_CTL 0x20C0
+#define ES9356_CPLDO_CTL 0x20C1
+#define ES9356_HP_REF_CTL 0x20C2
+#define ES9356_HP_IBIAS 0x20C3
+#define ES9356_HP_EN 0x20C4
+#define ES9356_HP_VOLUME 0x20C5
+#define ES9356_HP_LP 0x20C6
+
+/*SPK CTL*/
+#define ES9356_SPKLDO_CTL 0x20D0
+#define ES9356_CLASSD_CTL 0x20D1
+#define ES9356_SPK_HBDG 0x20D5
+#define ES9356_SPK_VOLUME 0x20D7
+#define ES9356_SPK_SCP 0x20D8
+#define ES9356_SPK_DT 0x20D9
+#define ES9356_SPK_OTP 0x20DA
+#define ES9356_SPKBIAS_COMP 0x20DB
+
+/* ES9356 SDCA Control - function number */
+#define FUNC_NUM_UAJ 0x01
+#define FUNC_NUM_MIC 0x02
+#define FUNC_NUM_AMP 0x03
+#define FUNC_NUM_HID 0x04
+
+/* ES9356 SDCA entity */
+#define ES9356_SDCA_ENT0 0x00
+#define ES9356_SDCA_ENT_PDE11 0x03
+#define ES9356_SDCA_ENT_FU11 0x04
+#define ES9356_SDCA_ENT_XU12 0x05
+#define ES9356_SDCA_ENT_FU113 0x07
+#define ES9356_SDCA_ENT_CS113 0x09
+#define ES9356_SDCA_ENT_PPU11 0x0C
+
+#define ES9356_SDCA_ENT_CS21 0x02
+#define ES9356_SDCA_ENT_PPU21 0x03
+#define ES9356_SDCA_ENT_FU21 0X04
+#define ES9356_SDCA_ENT_XU22 0x06
+#define ES9356_SDCA_ENT_SAPU29 0x03
+#define ES9356_SDCA_ENT_PDE23 0x0B
+#define ES9356_SDCA_ENT_HID01 0x01
+
+#define ES9356_SDCA_ENT_CS41 0x02
+#define ES9356_SDCA_ENT_FU35 0x04
+#define ES9356_SDCA_ENT_XU42 0x06
+#define ES9356_SDCA_ENT_FU41 0x07
+#define ES9356_SDCA_ENT_PDE47 0x0E
+#define ES9356_SDCA_ENT_IT33 0x0F
+#define ES9356_SDCA_ENT_PDE34 0x10
+#define ES9356_SDCA_ENT_FU33 0x11
+#define ES9356_SDCA_ENT_XU36 0x13
+#define ES9356_SDCA_ENT_FU36 0x15
+#define ES9356_SDCA_ENT_CS36 0x17
+#define ES9356_SDCA_ENT_GE35 0x18
+
+/* ES9356 SDCA control */
+#define ES9356_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10
+#define ES9356_SDCA_CTL_FU_MUTE 0x01
+#define ES9356_SDCA_CTL_FU_VOLUME 0x02
+#define ES9356_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10
+#define ES9356_SDCA_CTL_SELECTED_MODE 0x01
+#define ES9356_SDCA_CTL_DETECTED_MODE 0x02
+#define ES9356_SDCA_CTL_REQ_POWER_STATE 0x01
+#define ES9356_SDCA_CTL_FU_CH_GAIN 0x0b
+#define ES9356_SDCA_CTL_FUNC_STATUS 0x10
+#define ES9356_SDCA_CTL_ACTUAL_POWER_STATE 0x10
+#define ES9356_SDCA_CTL_POSTURE_NUMBER 0x00
+
+/* ES9356 SDCA channel */
+#define CH_L 0x01
+#define CH_R 0x02
+#define MBQ 0x2000
+
+/* ES9356 HID*/
+#define ES9356_BUF_ADDR_HID 0x44000000
+#define ES9356_HID_BYTE2 0x44000001
+#define ES9356_HID_BYTE3 0x44000002
+#define ES9356_HID_BYTE4 0x44000003
+
+/* ES9356 Volume Setting*/
+#define ES9356_VU_BASE 768
+#define ES9356_OFFSET_HIGH 0x07F8
+#define ES9356_OFFSET_LOW 0x0007
+#define ES9356_DEFAULT_VOLUME 0x00
+#define ES9356_VOLUME_STEP 32
+#define ES9356_VOLUME_MIN -768
+#define ES9356_VOLUME_MAX 285
+#define ES9356_AMIC_GAIN_STEP 768
+#define ES9356_DMIC_GAIN_STEP 1536
+#define ES9356_GAIN_MIN 0
+#define ES9356_AMIC_GAIN_MAX 10
+#define ES9356_DMIC_GAIN_MAX 3
+
+enum {
+ ES9356_DMIC = 1, /* For dmic */
+ ES9356_JACK_IN, /* For headset mic */
+ ES9356_AMP, /* For speaker */
+ ES9356_JACK_OUT, /* For headphone */
+};
+
+enum {
+ ES9356_SDCA_RATE_16000HZ,
+ ES9356_SDCA_RATE_24000HZ,
+ ES9356_SDCA_RATE_32000HZ,
+ ES9356_SDCA_RATE_44100HZ,
+ ES9356_SDCA_RATE_48000HZ,
+ ES9356_SDCA_RATE_88200HZ,
+ ES9356_SDCA_RATE_96000HZ,
+};
+
+#endif
diff --git a/sound/soc/codecs/framer-codec.c b/sound/soc/codecs/framer-codec.c
index 6f57a3aeecc8..a87a78390172 100644
--- a/sound/soc/codecs/framer-codec.c
+++ b/sound/soc/codecs/framer-codec.c
@@ -238,15 +238,13 @@ static int framer_dai_startup(struct snd_pcm_substream *substream,
return 0;
}
-static const u64 framer_dai_formats[] = {
- SND_SOC_POSSIBLE_DAIFMT_DSP_B,
-};
+static const u64 framer_dai_formats = SND_SOC_POSSIBLE_DAIFMT_DSP_B;
static const struct snd_soc_dai_ops framer_dai_ops = {
.startup = framer_dai_startup,
.set_tdm_slot = framer_dai_set_tdm_slot,
- .auto_selectable_formats = framer_dai_formats,
- .num_auto_selectable_formats = ARRAY_SIZE(framer_dai_formats),
+ .auto_selectable_formats = &framer_dai_formats,
+ .num_auto_selectable_formats = 1,
};
static struct snd_soc_dai_driver framer_dai_driver = {
diff --git a/sound/soc/codecs/fs210x.c b/sound/soc/codecs/fs210x.c
index e6195b71adad..5f381fe063e8 100644
--- a/sound/soc/codecs/fs210x.c
+++ b/sound/soc/codecs/fs210x.c
@@ -968,7 +968,7 @@ static int fs210x_effect_scene_info(struct snd_kcontrol *kcontrol,
if (scene->name)
name = scene->name;
- strscpy(uinfo->value.enumerated.name, name, strlen(name) + 1);
+ strscpy(uinfo->value.enumerated.name, name);
return 0;
}
@@ -1557,9 +1557,9 @@ static void fs210x_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id fs210x_i2c_id[] = {
- { "fs2104" },
- { "fs2105s" },
- {}
+ { .name = "fs2104" },
+ { .name = "fs2105s" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, fs210x_i2c_id);
diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c
index 2652fcf2a3a3..3220f9226e0b 100644
--- a/sound/soc/codecs/hdac_hdmi.c
+++ b/sound/soc/codecs/hdac_hdmi.c
@@ -911,12 +911,14 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol,
struct hdac_device *hdev = dev_to_hdac_dev(dev);
struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
struct hdac_hdmi_pcm *pcm;
- const char *cvt_name = e->texts[ucontrol->value.enumerated.item[0]];
+ const char *cvt_name;
ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
if (ret < 0)
return ret;
+ cvt_name = e->texts[ucontrol->value.enumerated.item[0]];
+
if (port == NULL)
return -EINVAL;
diff --git a/sound/soc/codecs/idt821034.c b/sound/soc/codecs/idt821034.c
index 39bafefa6a18..084090ccef77 100644
--- a/sound/soc/codecs/idt821034.c
+++ b/sound/soc/codecs/idt821034.c
@@ -860,18 +860,17 @@ static int idt821034_dai_startup(struct snd_pcm_substream *substream,
return 0;
}
-static const u64 idt821034_dai_formats[] = {
+static const u64 idt821034_dai_formats =
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
- SND_SOC_POSSIBLE_DAIFMT_DSP_B,
-};
+ SND_SOC_POSSIBLE_DAIFMT_DSP_B;
static const struct snd_soc_dai_ops idt821034_dai_ops = {
.startup = idt821034_dai_startup,
.hw_params = idt821034_dai_hw_params,
.set_tdm_slot = idt821034_dai_set_tdm_slot,
.set_fmt = idt821034_dai_set_fmt,
- .auto_selectable_formats = idt821034_dai_formats,
- .num_auto_selectable_formats = ARRAY_SIZE(idt821034_dai_formats),
+ .auto_selectable_formats = &idt821034_dai_formats,
+ .num_auto_selectable_formats = 1,
};
static struct snd_soc_dai_driver idt821034_dai_driver = {
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c
index b7a94631d77d..fa1c23dda4eb 100644
--- a/sound/soc/codecs/isabelle.c
+++ b/sound/soc/codecs/isabelle.c
@@ -1133,7 +1133,7 @@ static int isabelle_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id isabelle_i2c_id[] = {
- { "isabelle" },
+ { .name = "isabelle" },
{ }
};
MODULE_DEVICE_TABLE(i2c, isabelle_i2c_id);
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 26cdb750cbca..06add7fb6737 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -128,7 +128,7 @@ static int lm4857_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id lm4857_i2c_id[] = {
- { "lm4857" },
+ { .name = "lm4857" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm4857_i2c_id);
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index 043030509795..6e2e292d143b 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -1443,7 +1443,7 @@ static int lm49453_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id lm49453_i2c_id[] = {
- { "lm49453" },
+ { .name = "lm49453" },
{ }
};
MODULE_DEVICE_TABLE(i2c, lm49453_i2c_id);
diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c
index 528d5b167ecf..58a5798823d7 100644
--- a/sound/soc/codecs/lpass-va-macro.c
+++ b/sound/soc/codecs/lpass-va-macro.c
@@ -244,6 +244,11 @@ static const struct va_macro_data sm8250_va_data = {
.version = LPASS_CODEC_VERSION_1_0,
};
+static const struct va_macro_data sc7280_va_data = {
+ .has_swr_master = false,
+ .has_npl_clk = false,
+};
+
static const struct va_macro_data sm8450_va_data = {
.has_swr_master = true,
.has_npl_clk = true,
@@ -1755,7 +1760,7 @@ static const struct dev_pm_ops va_macro_pm_ops = {
};
static const struct of_device_id va_macro_dt_match[] = {
- { .compatible = "qcom,sc7280-lpass-va-macro", .data = &sm8250_va_data },
+ { .compatible = "qcom,sc7280-lpass-va-macro", .data = &sc7280_va_data },
{ .compatible = "qcom,sm6115-lpass-va-macro", .data = &sm8450_va_data },
{ .compatible = "qcom,sm8250-lpass-va-macro", .data = &sm8250_va_data },
{ .compatible = "qcom,sm8450-lpass-va-macro", .data = &sm8450_va_data },
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
index 7ad7a9fb7255..8621d9bdb9fd 100644
--- a/sound/soc/codecs/max9768.c
+++ b/sound/soc/codecs/max9768.c
@@ -213,7 +213,7 @@ static int max9768_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id max9768_i2c_id[] = {
- { "max9768" },
+ { .name = "max9768" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max9768_i2c_id);
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index 9f40ca4b60d5..df438baf05dc 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -1722,8 +1722,8 @@ static const struct snd_soc_component_driver soc_component_dev_max98088 = {
};
static const struct i2c_device_id max98088_i2c_id[] = {
- { "max98088", MAX98088 },
- { "max98089", MAX98089 },
+ { .name = "max98088", .driver_data = MAX98088 },
+ { .name = "max98089", .driver_data = MAX98089 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max98088_i2c_id);
diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c
index 13a15459040f..da416329b038 100644
--- a/sound/soc/codecs/max98090.c
+++ b/sound/soc/codecs/max98090.c
@@ -2337,7 +2337,7 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
}
/**
- * max98090_mic_detect - Enable microphone detection via the MAX98090 IRQ
+ * max98090_set_jack - Enable microphone detection via the MAX98090 IRQ
*
* @component: MAX98090 component
* @jack: jack to report detection events on
@@ -2349,12 +2349,12 @@ static irqreturn_t max98090_interrupt(int irq, void *data)
*
* If no jack is supplied detection will be disabled.
*/
-int max98090_mic_detect(struct snd_soc_component *component,
- struct snd_soc_jack *jack)
+static int max98090_set_jack(struct snd_soc_component *component,
+ struct snd_soc_jack *jack, void *data)
{
struct max98090_priv *max98090 = snd_soc_component_get_drvdata(component);
- dev_dbg(component->dev, "max98090_mic_detect\n");
+ dev_dbg(component->dev, "%s\n", __func__);
max98090->jack = jack;
if (jack) {
@@ -2377,7 +2377,6 @@ int max98090_mic_detect(struct snd_soc_component *component,
return 0;
}
-EXPORT_SYMBOL_GPL(max98090_mic_detect);
#define MAX98090_RATES SNDRV_PCM_RATE_8000_96000
#define MAX98090_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
@@ -2554,6 +2553,7 @@ static const struct snd_soc_component_driver soc_component_dev_max98090 = {
.remove = max98090_remove,
.seq_notifier = max98090_seq_notifier,
.set_bias_level = max98090_set_bias_level,
+ .set_jack = max98090_set_jack,
.idle_bias_on = 1,
.use_pmdown_time = 1,
.endianness = 1,
@@ -2572,8 +2572,8 @@ static const struct regmap_config max98090_regmap = {
};
static const struct i2c_device_id max98090_i2c_id[] = {
- { "max98090", MAX98090 },
- { "max98091", MAX98091 },
+ { .name = "max98090", .driver_data = MAX98090 },
+ { .name = "max98091", .driver_data = MAX98091 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max98090_i2c_id);
diff --git a/sound/soc/codecs/max98090.h b/sound/soc/codecs/max98090.h
index 6ce8dd176e48..048af4a1376f 100644
--- a/sound/soc/codecs/max98090.h
+++ b/sound/soc/codecs/max98090.h
@@ -1543,7 +1543,4 @@ struct max98090_priv {
bool shdn_pending;
};
-int max98090_mic_detect(struct snd_soc_component *component,
- struct snd_soc_jack *jack);
-
#endif
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index aae6423156e1..ced9bd4d94da 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -2109,7 +2109,7 @@ static const struct snd_soc_component_driver soc_component_dev_max98095 = {
};
static const struct i2c_device_id max98095_i2c_id[] = {
- { "max98095", MAX98095 },
+ { .name = "max98095", .driver_data = MAX98095 },
{ }
};
MODULE_DEVICE_TABLE(i2c, max98095_i2c_id);
diff --git a/sound/soc/codecs/max98357a.c b/sound/soc/codecs/max98357a.c
index cc811f58c9d2..b0f8043fb9e2 100644
--- a/sound/soc/codecs/max98357a.c
+++ b/sound/soc/codecs/max98357a.c
@@ -10,7 +10,6 @@
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/sound/soc/codecs/max98363.c b/sound/soc/codecs/max98363.c
index 25af78ab30d5..099dc5bf6195 100644
--- a/sound/soc/codecs/max98363.c
+++ b/sound/soc/codecs/max98363.c
@@ -90,24 +90,15 @@ static int max98363_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct max98363_priv *max98363 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!max98363->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(MAX98363_PROBE_TIMEOUT));
- if (!time) {
- dev_err(dev, "Initialization not complete, timed out\n");
- return -ETIMEDOUT;
- }
-
-regmap_sync:
+ ret = sdw_slave_wait_for_init(slave, MAX98363_PROBE_TIMEOUT);
+ if (ret)
+ return ret;
- slave->unattach_request = 0;
regcache_cache_only(max98363->regmap, false);
regcache_sync(max98363->regmap);
diff --git a/sound/soc/codecs/max98371.c b/sound/soc/codecs/max98371.c
index 852db211ba1e..c8d4c68af562 100644
--- a/sound/soc/codecs/max98371.c
+++ b/sound/soc/codecs/max98371.c
@@ -400,7 +400,7 @@ static int max98371_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id max98371_i2c_id[] = {
- { "max98371" },
+ { .name = "max98371" },
{ }
};
diff --git a/sound/soc/codecs/max98373-i2c.c b/sound/soc/codecs/max98373-i2c.c
index f58b8c8625a7..8805bd01153c 100644
--- a/sound/soc/codecs/max98373-i2c.c
+++ b/sound/soc/codecs/max98373-i2c.c
@@ -5,7 +5,6 @@
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/pm.h>
#include <linux/regmap.h>
@@ -576,8 +575,8 @@ static int max98373_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id max98373_i2c_id[] = {
- { "max98373"},
- { },
+ { .name = "max98373" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max98373_i2c_id);
diff --git a/sound/soc/codecs/max98373-sdw.c b/sound/soc/codecs/max98373-sdw.c
index 16673440218c..8fe9c58e1a62 100644
--- a/sound/soc/codecs/max98373-sdw.c
+++ b/sound/soc/codecs/max98373-sdw.c
@@ -4,7 +4,6 @@
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/slab.h>
@@ -266,25 +265,17 @@ static int max98373_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct max98373_priv *max98373 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!max98373->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(MAX98373_PROBE_TIMEOUT));
- if (!time) {
- dev_err(dev, "Initialization not complete, timed out\n");
+ ret = sdw_slave_wait_for_init(slave, MAX98373_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(max98373->regmap, false);
regcache_sync(max98373->regmap);
diff --git a/sound/soc/codecs/max98388.c b/sound/soc/codecs/max98388.c
index 076f15a9867e..a4c57152d25f 100644
--- a/sound/soc/codecs/max98388.c
+++ b/sound/soc/codecs/max98388.c
@@ -6,7 +6,6 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
@@ -977,8 +976,8 @@ static int max98388_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id max98388_i2c_id[] = {
- { "max98388"},
- { },
+ { .name = "max98388" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max98388_i2c_id);
diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c
index 65f095c47191..2bbedf84ee5d 100644
--- a/sound/soc/codecs/max98390.c
+++ b/sound/soc/codecs/max98390.c
@@ -1096,8 +1096,8 @@ static int max98390_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id max98390_i2c_id[] = {
- { "max98390"},
- {},
+ { .name = "max98390" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max98390_i2c_id);
diff --git a/sound/soc/codecs/max98396.c b/sound/soc/codecs/max98396.c
index 18fd90227187..9c1d7213410c 100644
--- a/sound/soc/codecs/max98396.c
+++ b/sound/soc/codecs/max98396.c
@@ -1871,9 +1871,9 @@ static int max98396_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id max98396_i2c_id[] = {
- { "max98396", CODEC_TYPE_MAX98396},
- { "max98397", CODEC_TYPE_MAX98397},
- { },
+ { .name = "max98396", .driver_data = CODEC_TYPE_MAX98396 },
+ { .name = "max98397", .driver_data = CODEC_TYPE_MAX98397 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max98396_i2c_id);
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index 1fcbc64a2771..9bd6a61212c1 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -321,7 +321,7 @@ static int max9850_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id max9850_i2c_id[] = {
- { "max9850" },
+ { .name = "max9850" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max9850_i2c_id);
diff --git a/sound/soc/codecs/max98504.c b/sound/soc/codecs/max98504.c
index c94142768c81..8b2620eaf9b0 100644
--- a/sound/soc/codecs/max98504.c
+++ b/sound/soc/codecs/max98504.c
@@ -363,7 +363,7 @@ MODULE_DEVICE_TABLE(of, max98504_of_match);
#endif
static const struct i2c_device_id max98504_i2c_id[] = {
- { "max98504" },
+ { .name = "max98504" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max98504_i2c_id);
diff --git a/sound/soc/codecs/max98520.c b/sound/soc/codecs/max98520.c
index 5bc3d95ade5a..4fb98505db1a 100644
--- a/sound/soc/codecs/max98520.c
+++ b/sound/soc/codecs/max98520.c
@@ -734,8 +734,8 @@ static int max98520_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id max98520_i2c_id[] = {
- { "max98520"},
- { },
+ { .name = "max98520" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max98520_i2c_id);
diff --git a/sound/soc/codecs/max9860.c b/sound/soc/codecs/max9860.c
index 716d16daf7d7..0d7ac37850bb 100644
--- a/sound/soc/codecs/max9860.c
+++ b/sound/soc/codecs/max9860.c
@@ -709,7 +709,7 @@ static void max9860_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id max9860_i2c_id[] = {
- { "max9860", },
+ { .name = "max9860" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max9860_i2c_id);
diff --git a/sound/soc/codecs/max9867.c b/sound/soc/codecs/max9867.c
index 9cad9b698cf2..07a53ec2a18a 100644
--- a/sound/soc/codecs/max9867.c
+++ b/sound/soc/codecs/max9867.c
@@ -689,7 +689,7 @@ static int max9867_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id max9867_i2c_id[] = {
- { "max9867" },
+ { .name = "max9867" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max9867_i2c_id);
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
index 1bd0d4761ca6..7cd07b6f9dd6 100644
--- a/sound/soc/codecs/max9877.c
+++ b/sound/soc/codecs/max9877.c
@@ -151,7 +151,7 @@ static int max9877_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id max9877_i2c_id[] = {
- { "max9877" },
+ { .name = "max9877" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max9877_i2c_id);
diff --git a/sound/soc/codecs/max98925.c b/sound/soc/codecs/max98925.c
index 124af6408d96..4302ab16a642 100644
--- a/sound/soc/codecs/max98925.c
+++ b/sound/soc/codecs/max98925.c
@@ -617,7 +617,7 @@ static int max98925_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id max98925_i2c_id[] = {
- { "max98925" },
+ { .name = "max98925" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max98925_i2c_id);
diff --git a/sound/soc/codecs/max98926.c b/sound/soc/codecs/max98926.c
index ae962bda163e..5305e1f9d97f 100644
--- a/sound/soc/codecs/max98926.c
+++ b/sound/soc/codecs/max98926.c
@@ -565,7 +565,7 @@ err_out:
}
static const struct i2c_device_id max98926_i2c_id[] = {
- { "max98926" },
+ { .name = "max98926" },
{ }
};
MODULE_DEVICE_TABLE(i2c, max98926_i2c_id);
diff --git a/sound/soc/codecs/max98927.c b/sound/soc/codecs/max98927.c
index 0e9b8970997c..65e6fdb30eec 100644
--- a/sound/soc/codecs/max98927.c
+++ b/sound/soc/codecs/max98927.c
@@ -873,8 +873,8 @@ static void max98927_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id max98927_i2c_id[] = {
- { "max98927"},
- { },
+ { .name = "max98927" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, max98927_i2c_id);
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index fad0cc902346..8a14626d43ff 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -573,7 +573,7 @@ static int ml26124_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id ml26124_i2c_id[] = {
- { "ml26124" },
+ { .name = "ml26124" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ml26124_i2c_id);
diff --git a/sound/soc/codecs/mt6351.c b/sound/soc/codecs/mt6351.c
index 2a5e963fb2b5..1768c249650d 100644
--- a/sound/soc/codecs/mt6351.c
+++ b/sound/soc/codecs/mt6351.c
@@ -8,7 +8,6 @@
#include <linux/dma-mapping.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/delay.h>
diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c
index a787accb88e8..ed8cbc63fa77 100644
--- a/sound/soc/codecs/mt6358.c
+++ b/sound/soc/codecs/mt6358.c
@@ -6,7 +6,6 @@
// Author: KaiChieh Chuang <kaichieh.chuang@mediatek.com>
#include <linux/platform_device.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/kthread.h>
diff --git a/sound/soc/codecs/mt6660.c b/sound/soc/codecs/mt6660.c
index ef63fd113cb7..21741afc80ef 100644
--- a/sound/soc/codecs/mt6660.c
+++ b/sound/soc/codecs/mt6660.c
@@ -557,8 +557,8 @@ static const struct of_device_id __maybe_unused mt6660_of_id[] = {
MODULE_DEVICE_TABLE(of, mt6660_of_id);
static const struct i2c_device_id mt6660_i2c_id[] = {
- {"mt6660" },
- {},
+ { .name = "mt6660" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, mt6660_i2c_id);
diff --git a/sound/soc/codecs/nau8325.c b/sound/soc/codecs/nau8325.c
index 58ef5c493835..236d94c29c24 100644
--- a/sound/soc/codecs/nau8325.c
+++ b/sound/soc/codecs/nau8325.c
@@ -877,7 +877,7 @@ err:
}
static const struct i2c_device_id nau8325_i2c_ids[] = {
- { "nau8325" },
+ { .name = "nau8325" },
{ }
};
MODULE_DEVICE_TABLE(i2c, nau8325_i2c_ids);
diff --git a/sound/soc/codecs/nau8540.c b/sound/soc/codecs/nau8540.c
index caf2edb23088..fefbd5722c00 100644
--- a/sound/soc/codecs/nau8540.c
+++ b/sound/soc/codecs/nau8540.c
@@ -965,7 +965,7 @@ static int nau8540_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id nau8540_i2c_ids[] = {
- { "nau8540" },
+ { .name = "nau8540" },
{ }
};
MODULE_DEVICE_TABLE(i2c, nau8540_i2c_ids);
diff --git a/sound/soc/codecs/nau8810.c b/sound/soc/codecs/nau8810.c
index 9870e62d372e..a050387dd485 100644
--- a/sound/soc/codecs/nau8810.c
+++ b/sound/soc/codecs/nau8810.c
@@ -896,9 +896,9 @@ static int nau8810_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id nau8810_i2c_id[] = {
- { "nau8810" },
- { "nau8812" },
- { "nau8814" },
+ { .name = "nau8810" },
+ { .name = "nau8812" },
+ { .name = "nau8814" },
{ }
};
MODULE_DEVICE_TABLE(i2c, nau8810_i2c_id);
diff --git a/sound/soc/codecs/nau8821.c b/sound/soc/codecs/nau8821.c
index ffb526de0021..c45c5b864ea4 100644
--- a/sound/soc/codecs/nau8821.c
+++ b/sound/soc/codecs/nau8821.c
@@ -1968,7 +1968,7 @@ static int nau8821_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id nau8821_i2c_ids[] = {
- { "nau8821" },
+ { .name = "nau8821" },
{ }
};
MODULE_DEVICE_TABLE(i2c, nau8821_i2c_ids);
diff --git a/sound/soc/codecs/nau8822.c b/sound/soc/codecs/nau8822.c
index a11759f85eac..830164e991a7 100644
--- a/sound/soc/codecs/nau8822.c
+++ b/sound/soc/codecs/nau8822.c
@@ -19,6 +19,7 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -108,6 +109,10 @@ static const struct reg_default nau8822_reg_defaults[] = {
{ NAU8822_REG_OUTPUT_TIEOFF, 0x0000 },
};
+static const char * const nau8822_supply_names[NAU8822_NUM_SUPPLIES] = {
+ "vdda", "vddb", "vddc", "vddspk",
+};
+
static bool nau8822_readable_reg(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -1056,6 +1061,7 @@ static int nau8822_suspend(struct snd_soc_component *component)
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
snd_soc_dapm_force_bias_level(dapm, SND_SOC_BIAS_OFF);
+ regulator_bulk_disable(NAU8822_NUM_SUPPLIES, nau8822->supplies);
regcache_mark_dirty(nau8822->regmap);
@@ -1066,6 +1072,15 @@ static int nau8822_resume(struct snd_soc_component *component)
{
struct nau8822 *nau8822 = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
+ int ret = regulator_bulk_enable(NAU8822_NUM_SUPPLIES, nau8822->supplies);
+
+ if (ret) {
+ dev_err(component->dev,
+ "Failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ fsleep(100);
regcache_sync(nau8822->regmap);
@@ -1153,7 +1168,7 @@ static int nau8822_i2c_probe(struct i2c_client *i2c)
{
struct device *dev = &i2c->dev;
struct nau8822 *nau8822 = dev_get_platdata(dev);
- int ret;
+ int ret, i;
if (!nau8822) {
nau8822 = devm_kzalloc(dev, sizeof(*nau8822), GFP_KERNEL);
@@ -1167,6 +1182,13 @@ static int nau8822_i2c_probe(struct i2c_client *i2c)
return dev_err_probe(&i2c->dev, PTR_ERR(nau8822->mclk),
"Error getting mclk\n");
+ for (i = 0; i < NAU8822_NUM_SUPPLIES; i++)
+ nau8822->supplies[i].supply = nau8822_supply_names[i];
+
+ ret = devm_regulator_bulk_get(dev, NAU8822_NUM_SUPPLIES, nau8822->supplies);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to get regulators\n");
+
nau8822->regmap = devm_regmap_init_i2c(i2c, &nau8822_regmap_config);
if (IS_ERR(nau8822->regmap)) {
ret = PTR_ERR(nau8822->regmap);
@@ -1175,25 +1197,42 @@ static int nau8822_i2c_probe(struct i2c_client *i2c)
}
nau8822->dev = dev;
+ ret = regulator_bulk_enable(NAU8822_NUM_SUPPLIES, nau8822->supplies);
+ if (ret)
+ return dev_err_probe(dev, ret, "Failed to enable regulators\n");
+
+ fsleep(100);
+
/* Reset the codec */
ret = regmap_write(nau8822->regmap, NAU8822_REG_RESET, 0x00);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
- return ret;
+ goto err_reg;
}
ret = devm_snd_soc_register_component(dev, &soc_component_dev_nau8822,
&nau8822_dai, 1);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
- return ret;
+ goto err_reg;
}
return 0;
+
+err_reg:
+ regulator_bulk_disable(NAU8822_NUM_SUPPLIES, nau8822->supplies);
+ return ret;
+}
+
+static void nau8822_i2c_remove(struct i2c_client *i2c)
+{
+ struct nau8822 *nau8822 = i2c_get_clientdata(i2c);
+
+ regulator_bulk_disable(NAU8822_NUM_SUPPLIES, nau8822->supplies);
}
static const struct i2c_device_id nau8822_i2c_id[] = {
- { "nau8822" },
+ { .name = "nau8822" },
{ }
};
MODULE_DEVICE_TABLE(i2c, nau8822_i2c_id);
@@ -1212,6 +1251,7 @@ static struct i2c_driver nau8822_i2c_driver = {
.of_match_table = of_match_ptr(nau8822_of_match),
},
.probe = nau8822_i2c_probe,
+ .remove = nau8822_i2c_remove,
.id_table = nau8822_i2c_id,
};
module_i2c_driver(nau8822_i2c_driver);
diff --git a/sound/soc/codecs/nau8822.h b/sound/soc/codecs/nau8822.h
index 13fe0a091e9e..24799c7b5931 100644
--- a/sound/soc/codecs/nau8822.h
+++ b/sound/soc/codecs/nau8822.h
@@ -211,6 +211,8 @@ struct nau8822_pll {
int freq_out;
};
+#define NAU8822_NUM_SUPPLIES 4
+
/* Codec Private Data */
struct nau8822 {
struct device *dev;
@@ -219,6 +221,7 @@ struct nau8822 {
struct nau8822_pll pll;
int sysclk;
int div_id;
+ struct regulator_bulk_data supplies[NAU8822_NUM_SUPPLIES];
};
#endif /* __NAU8822_H__ */
diff --git a/sound/soc/codecs/nau8824.c b/sound/soc/codecs/nau8824.c
index 6ce763762443..426a488ff2a3 100644
--- a/sound/soc/codecs/nau8824.c
+++ b/sound/soc/codecs/nau8824.c
@@ -2020,7 +2020,7 @@ static int nau8824_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id nau8824_i2c_ids[] = {
- { "nau8824" },
+ { .name = "nau8824" },
{ }
};
MODULE_DEVICE_TABLE(i2c, nau8824_i2c_ids);
diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c
index dd3528537ae4..ae83b778bf93 100644
--- a/sound/soc/codecs/nau8825.c
+++ b/sound/soc/codecs/nau8825.c
@@ -712,8 +712,8 @@ static void nau8825_xtalk_measure(struct nau8825 *nau8825)
/* In left headphone IMM state, read out left headphone
* impedance measure result, and delay some time to wait
* detection sine wave output finish. Then, we can calculate
- * the cross talk suppresstion side tone according to the L/R
- * headphone imedance.
+ * the cross talk suppression side tone according to the L/R
+ * headphone impedance.
*/
regmap_read(nau8825->regmap, NAU8825_REG_IMM_RMS_L,
&nau8825->imp_rms[NAU8825_XTALK_HPL_R2L]);
@@ -2237,7 +2237,7 @@ static void nau8825_component_remove(struct snd_soc_component *component)
{
struct nau8825 *nau8825 = snd_soc_component_get_drvdata(component);
- /* Cancel and reset cross tak suppresstion detection funciton */
+ /* Cancel and reset cross talk suppression detection function */
nau8825_xtalk_cancel(nau8825);
}
@@ -2651,7 +2651,7 @@ static int nau8825_set_bias_level(struct snd_soc_component *component,
/* ground HPL/HPR, MICGRND1/2 */
regmap_update_bits(nau8825->regmap,
NAU8825_REG_HSD_CTRL, 0xf, 0xf);
- /* Cancel and reset cross talk detection funciton */
+ /* Cancel and reset cross talk detection function */
nau8825_xtalk_cancel(nau8825);
/* Turn off all interruptions before system shutdown. Keep the
* interruption quiet before resume setup completes.
@@ -2930,11 +2930,8 @@ static int nau8825_i2c_probe(struct i2c_client *i2c)
&nau8825_dai, 1);
}
-static void nau8825_i2c_remove(struct i2c_client *client)
-{}
-
static const struct i2c_device_id nau8825_i2c_ids[] = {
- { "nau8825" },
+ { .name = "nau8825" },
{ }
};
MODULE_DEVICE_TABLE(i2c, nau8825_i2c_ids);
@@ -2962,7 +2959,6 @@ static struct i2c_driver nau8825_driver = {
.acpi_match_table = ACPI_PTR(nau8825_acpi_match),
},
.probe = nau8825_i2c_probe,
- .remove = nau8825_i2c_remove,
.id_table = nau8825_i2c_ids,
};
module_i2c_driver(nau8825_driver);
diff --git a/sound/soc/codecs/ntp8835.c b/sound/soc/codecs/ntp8835.c
index 2b93bea11752..5837b9379fee 100644
--- a/sound/soc/codecs/ntp8835.c
+++ b/sound/soc/codecs/ntp8835.c
@@ -454,8 +454,8 @@ static int ntp8835_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id ntp8835_i2c_id[] = {
- { "ntp8835" },
- {}
+ { .name = "ntp8835" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, ntp8835_i2c_id);
diff --git a/sound/soc/codecs/ntp8918.c b/sound/soc/codecs/ntp8918.c
index 5593d48ef696..a18d79aa80aa 100644
--- a/sound/soc/codecs/ntp8918.c
+++ b/sound/soc/codecs/ntp8918.c
@@ -370,8 +370,8 @@ static int ntp8918_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id ntp8918_i2c_id[] = {
- { "ntp8918" },
- {}
+ { .name = "ntp8918" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, ntp8918_i2c_id);
diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c
index f4e5f3133f2b..cb923cecb47f 100644
--- a/sound/soc/codecs/pcm1681.c
+++ b/sound/soc/codecs/pcm1681.c
@@ -290,8 +290,8 @@ static const struct snd_soc_component_driver soc_component_dev_pcm1681 = {
};
static const struct i2c_device_id pcm1681_i2c_id[] = {
- {"pcm1681"},
- {}
+ { .name = "pcm1681" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pcm1681_i2c_id);
diff --git a/sound/soc/codecs/pcm1789-i2c.c b/sound/soc/codecs/pcm1789-i2c.c
index abadf4f8ed5e..4f1bb13fd4c3 100644
--- a/sound/soc/codecs/pcm1789-i2c.c
+++ b/sound/soc/codecs/pcm1789-i2c.c
@@ -41,7 +41,7 @@ MODULE_DEVICE_TABLE(of, pcm1789_of_match);
#endif
static const struct i2c_device_id pcm1789_i2c_ids[] = {
- { "pcm1789" },
+ { .name = "pcm1789" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcm1789_i2c_ids);
diff --git a/sound/soc/codecs/pcm179x-i2c.c b/sound/soc/codecs/pcm179x-i2c.c
index effc1dd6df22..5337bcc7c62c 100644
--- a/sound/soc/codecs/pcm179x-i2c.c
+++ b/sound/soc/codecs/pcm179x-i2c.c
@@ -38,7 +38,7 @@ MODULE_DEVICE_TABLE(of, pcm179x_of_match);
#endif
static const struct i2c_device_id pcm179x_i2c_ids[] = {
- { "pcm179x" },
+ { .name = "pcm179x" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcm179x_i2c_ids);
diff --git a/sound/soc/codecs/pcm186x-i2c.c b/sound/soc/codecs/pcm186x-i2c.c
index a50f9f6e39c1..3bd9d557e3c2 100644
--- a/sound/soc/codecs/pcm186x-i2c.c
+++ b/sound/soc/codecs/pcm186x-i2c.c
@@ -23,10 +23,10 @@ static const struct of_device_id pcm186x_of_match[] = {
MODULE_DEVICE_TABLE(of, pcm186x_of_match);
static const struct i2c_device_id pcm186x_i2c_id[] = {
- { "pcm1862", PCM1862 },
- { "pcm1863", PCM1863 },
- { "pcm1864", PCM1864 },
- { "pcm1865", PCM1865 },
+ { .name = "pcm1862", .driver_data = PCM1862 },
+ { .name = "pcm1863", .driver_data = PCM1863 },
+ { .name = "pcm1864", .driver_data = PCM1864 },
+ { .name = "pcm1865", .driver_data = PCM1865 },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcm186x_i2c_id);
diff --git a/sound/soc/codecs/pcm3168a-i2c.c b/sound/soc/codecs/pcm3168a-i2c.c
index ff18c74b616c..dd24027836b2 100644
--- a/sound/soc/codecs/pcm3168a-i2c.c
+++ b/sound/soc/codecs/pcm3168a-i2c.c
@@ -10,7 +10,6 @@
#include <linux/i2c.h>
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <sound/soc.h>
@@ -33,7 +32,7 @@ static void pcm3168a_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id pcm3168a_i2c_id[] = {
- { "pcm3168a", },
+ { .name = "pcm3168a" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcm3168a_i2c_id);
diff --git a/sound/soc/codecs/pcm3168a.c b/sound/soc/codecs/pcm3168a.c
index c8617a488b11..cb6a6f08f2f8 100644
--- a/sound/soc/codecs/pcm3168a.c
+++ b/sound/soc/codecs/pcm3168a.c
@@ -564,12 +564,6 @@ static int pcm3168a_hw_params(struct snd_pcm_substream *substream,
static const u64 pcm3168a_dai_formats[] = {
/*
- * Select below from Sound Card, not here
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
- */
-
- /*
* First Priority
*/
SND_SOC_POSSIBLE_DAIFMT_I2S |
@@ -581,6 +575,8 @@ static const u64 pcm3168a_dai_formats[] = {
* see
* pcm3168a_hw_params()
*/
+ SND_SOC_POSSIBLE_DAIFMT_I2S |
+ SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
SND_SOC_POSSIBLE_DAIFMT_DSP_B,
@@ -799,7 +795,6 @@ int pcm3168a_probe(struct device *dev, struct regmap *regmap)
pm_runtime_set_active(dev);
pm_runtime_enable(dev);
- pm_runtime_idle(dev);
memcpy(pcm3168a->dai_drv, pcm3168a_dais, sizeof(pcm3168a->dai_drv));
ret = devm_snd_soc_register_component(dev, &pcm3168a_driver,
@@ -822,15 +817,6 @@ err_clk:
}
EXPORT_SYMBOL_GPL(pcm3168a_probe);
-static void pcm3168a_disable(struct device *dev)
-{
- struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev);
-
- regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies),
- pcm3168a->supplies);
- clk_disable_unprepare(pcm3168a->scki);
-}
-
void pcm3168a_remove(struct device *dev)
{
struct pcm3168a_priv *pcm3168a = dev_get_drvdata(dev);
@@ -842,10 +828,12 @@ void pcm3168a_remove(struct device *dev)
* The asserted level of GPIO_ACTIVE_LOW is LOW.
*/
gpiod_set_value_cansleep(pcm3168a->gpio_rst, 1);
+
pm_runtime_disable(dev);
-#ifndef CONFIG_PM
- pcm3168a_disable(dev);
-#endif
+ if (!pm_runtime_status_suspended(dev)) {
+ regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), pcm3168a->supplies);
+ clk_disable_unprepare(pcm3168a->scki);
+ }
}
EXPORT_SYMBOL_GPL(pcm3168a_remove);
@@ -900,13 +888,15 @@ static int pcm3168a_rt_suspend(struct device *dev)
regcache_cache_only(pcm3168a->regmap, true);
- pcm3168a_disable(dev);
+ regulator_bulk_disable(ARRAY_SIZE(pcm3168a->supplies), pcm3168a->supplies);
+ clk_disable_unprepare(pcm3168a->scki);
return 0;
}
EXPORT_GPL_DEV_PM_OPS(pcm3168a_pm_ops) = {
RUNTIME_PM_OPS(pcm3168a_rt_suspend, pcm3168a_rt_resume, NULL)
+ SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
};
MODULE_DESCRIPTION("PCM3168A codec driver");
diff --git a/sound/soc/codecs/pcm512x-i2c.c b/sound/soc/codecs/pcm512x-i2c.c
index a1d849b0c50f..836865d11d22 100644
--- a/sound/soc/codecs/pcm512x-i2c.c
+++ b/sound/soc/codecs/pcm512x-i2c.c
@@ -35,13 +35,13 @@ static void pcm512x_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id pcm512x_i2c_id[] = {
- { "pcm5121", },
- { "pcm5122", },
- { "pcm5141", },
- { "pcm5142", },
- { "pcm5242", },
- { "tas5754", },
- { "tas5756", },
+ { .name = "pcm5121" },
+ { .name = "pcm5122" },
+ { .name = "pcm5141" },
+ { .name = "pcm5142" },
+ { .name = "pcm5242" },
+ { .name = "tas5754" },
+ { .name = "tas5756" },
{ }
};
MODULE_DEVICE_TABLE(i2c, pcm512x_i2c_id);
diff --git a/sound/soc/codecs/pcm512x.c b/sound/soc/codecs/pcm512x.c
index a70e8ea166dc..fe3b5011fa16 100644
--- a/sound/soc/codecs/pcm512x.c
+++ b/sound/soc/codecs/pcm512x.c
@@ -235,7 +235,7 @@ static int pcm512x_overclock_pll_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
- struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
switch (snd_soc_dapm_get_bias_level(dapm)) {
@@ -264,7 +264,7 @@ static int pcm512x_overclock_dsp_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
- struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
switch (snd_soc_dapm_get_bias_level(dapm)) {
@@ -293,7 +293,7 @@ static int pcm512x_overclock_dac_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
- struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_to_dapm(kcontrol);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct pcm512x_priv *pcm512x = snd_soc_component_get_drvdata(component);
switch (snd_soc_dapm_get_bias_level(dapm)) {
@@ -633,7 +633,7 @@ static int pcm512x_dai_startup_slave(struct snd_pcm_substream *substream,
struct regmap *regmap = pcm512x->regmap;
if (IS_ERR(pcm512x->sclk)) {
- dev_info(dev, "No SCLK, using BCLK: %ld\n",
+ dev_info_once(dev, "No SCLK, using BCLK: %ld\n",
PTR_ERR(pcm512x->sclk));
/* Disable reporting of missing SCLK as an error */
diff --git a/sound/soc/codecs/pcm6240.c b/sound/soc/codecs/pcm6240.c
index 78b21fbfad50..4ac4448ac3c8 100644
--- a/sound/soc/codecs/pcm6240.c
+++ b/sound/soc/codecs/pcm6240.c
@@ -27,28 +27,28 @@
#include "pcm6240.h"
static const struct i2c_device_id pcmdevice_i2c_id[] = {
- { "adc3120", ADC3120 },
- { "adc5120", ADC5120 },
- { "adc6120", ADC6120 },
- { "dix4192", DIX4192 },
- { "pcm1690", PCM1690 },
- { "pcm3120", PCM3120 },
- { "pcm3140", PCM3140 },
- { "pcm5120", PCM5120 },
- { "pcm5140", PCM5140 },
- { "pcm6120", PCM6120 },
- { "pcm6140", PCM6140 },
- { "pcm6240", PCM6240 },
- { "pcm6260", PCM6260 },
- { "pcm9211", PCM9211 },
- { "pcmd3140", PCMD3140 },
- { "pcmd3180", PCMD3180 },
- { "pcmd512x", PCMD512X },
- { "taa5212", TAA5212 },
- { "taa5412", TAA5412 },
- { "tad5212", TAD5212 },
- { "tad5412", TAD5412 },
- {}
+ { .name = "adc3120", .driver_data = ADC3120 },
+ { .name = "adc5120", .driver_data = ADC5120 },
+ { .name = "adc6120", .driver_data = ADC6120 },
+ { .name = "dix4192", .driver_data = DIX4192 },
+ { .name = "pcm1690", .driver_data = PCM1690 },
+ { .name = "pcm3120", .driver_data = PCM3120 },
+ { .name = "pcm3140", .driver_data = PCM3140 },
+ { .name = "pcm5120", .driver_data = PCM5120 },
+ { .name = "pcm5140", .driver_data = PCM5140 },
+ { .name = "pcm6120", .driver_data = PCM6120 },
+ { .name = "pcm6140", .driver_data = PCM6140 },
+ { .name = "pcm6240", .driver_data = PCM6240 },
+ { .name = "pcm6260", .driver_data = PCM6260 },
+ { .name = "pcm9211", .driver_data = PCM9211 },
+ { .name = "pcmd3140", .driver_data = PCMD3140 },
+ { .name = "pcmd3180", .driver_data = PCMD3180 },
+ { .name = "pcmd512x", .driver_data = PCMD512X },
+ { .name = "taa5212", .driver_data = TAA5212 },
+ { .name = "taa5412", .driver_data = TAA5412 },
+ { .name = "tad5212", .driver_data = TAD5212 },
+ { .name = "tad5412", .driver_data = TAD5412 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, pcmdevice_i2c_id);
@@ -1230,15 +1230,11 @@ static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt,
int *status)
{
struct pcmdevice_priv *pcm_dev = (struct pcmdevice_priv *)ctxt;
- struct pcmdevice_config_info *cfg_info;
+ struct pcmdevice_config_info *cfg_info = NULL;
struct pcmdevice_block_data **bk_da;
+ char cfg_name[64] = {};
unsigned int config_offset = 0, i;
-
- cfg_info = kzalloc_obj(struct pcmdevice_config_info);
- if (!cfg_info) {
- *status = -ENOMEM;
- goto out;
- }
+ unsigned int nblocks;
if (pcm_dev->regbin.fw_hdr.binary_version_num >= 0x105) {
if (config_offset + 64 > (int)config_size) {
@@ -1247,7 +1243,7 @@ static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt,
"%s: cfg_name out of boundary\n", __func__);
goto out;
}
- memcpy(cfg_info->cfg_name, &config_data[config_offset], 64);
+ memcpy(cfg_name, &config_data[config_offset], 64);
config_offset += 64;
}
@@ -1257,16 +1253,17 @@ static struct pcmdevice_config_info *pcmdevice_add_config(void *ctxt,
__func__);
goto out;
}
- cfg_info->nblocks =
- get_unaligned_be32(&config_data[config_offset]);
+ nblocks = get_unaligned_be32(&config_data[config_offset]);
config_offset += 4;
- bk_da = cfg_info->blk_data = kzalloc_objs(struct pcmdevice_block_data *,
- cfg_info->nblocks);
- if (!bk_da) {
+ cfg_info = kzalloc_flex(*cfg_info, blk_data, nblocks);
+ if (!cfg_info) {
*status = -ENOMEM;
goto out;
}
+ cfg_info->nblocks = nblocks;
+ memcpy(cfg_info->cfg_name, cfg_name, sizeof(cfg_info->cfg_name));
+ bk_da = cfg_info->blk_data;
cfg_info->real_nblocks = 0;
for (i = 0; i < cfg_info->nblocks; i++) {
if (config_offset + 12 > config_size) {
@@ -1449,14 +1446,11 @@ static void pcmdevice_config_info_remove(void *ctxt)
for (i = 0; i < regbin->ncfgs; i++) {
if (!cfg_info[i])
continue;
- if (cfg_info[i]->blk_data) {
- for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) {
- if (!cfg_info[i]->blk_data[j])
- continue;
- kfree(cfg_info[i]->blk_data[j]->regdata);
- kfree(cfg_info[i]->blk_data[j]);
- }
- kfree(cfg_info[i]->blk_data);
+ for (j = 0; j < (int)cfg_info[i]->real_nblocks; j++) {
+ if (!cfg_info[i]->blk_data[j])
+ continue;
+ kfree(cfg_info[i]->blk_data[j]->regdata);
+ kfree(cfg_info[i]->blk_data[j]);
}
kfree(cfg_info[i]);
}
diff --git a/sound/soc/codecs/pcm6240.h b/sound/soc/codecs/pcm6240.h
index 2d8f9e798139..e27afd33910c 100644
--- a/sound/soc/codecs/pcm6240.h
+++ b/sound/soc/codecs/pcm6240.h
@@ -199,7 +199,7 @@ struct pcmdevice_config_info {
unsigned int nblocks;
unsigned int real_nblocks;
unsigned char active_dev;
- struct pcmdevice_block_data **blk_data;
+ struct pcmdevice_block_data *blk_data[] __counted_by(nblocks);
};
struct pcmdevice_regbin {
diff --git a/sound/soc/codecs/peb2466.c b/sound/soc/codecs/peb2466.c
index 2d5163c15d0d..2d71d204d8fa 100644
--- a/sound/soc/codecs/peb2466.c
+++ b/sound/soc/codecs/peb2466.c
@@ -817,18 +817,17 @@ static int peb2466_dai_startup(struct snd_pcm_substream *substream,
&peb2466_sample_bits_constr);
}
-static const u64 peb2466_dai_formats[] = {
+static const u64 peb2466_dai_formats =
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
- SND_SOC_POSSIBLE_DAIFMT_DSP_B,
-};
+ SND_SOC_POSSIBLE_DAIFMT_DSP_B;
static const struct snd_soc_dai_ops peb2466_dai_ops = {
.startup = peb2466_dai_startup,
.hw_params = peb2466_dai_hw_params,
.set_tdm_slot = peb2466_dai_set_tdm_slot,
.set_fmt = peb2466_dai_set_fmt,
- .auto_selectable_formats = peb2466_dai_formats,
- .num_auto_selectable_formats = ARRAY_SIZE(peb2466_dai_formats),
+ .auto_selectable_formats = &peb2466_dai_formats,
+ .num_auto_selectable_formats = 1,
};
static struct snd_soc_dai_driver peb2466_dai_driver = {
diff --git a/sound/soc/codecs/pm4125.c b/sound/soc/codecs/pm4125.c
index 1f0a3f5389f1..29655175ea28 100644
--- a/sound/soc/codecs/pm4125.c
+++ b/sound/soc/codecs/pm4125.c
@@ -1309,17 +1309,12 @@ static int pm4125_irq_init(struct pm4125_priv *pm4125, struct device *dev)
static int pm4125_soc_codec_probe(struct snd_soc_component *component)
{
struct pm4125_priv *pm4125 = snd_soc_component_get_drvdata(component);
- struct sdw_slave *tx_sdw_dev = pm4125->tx_sdw_dev;
struct device *dev = component->dev;
- unsigned long time_left;
int i, ret;
- time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
- msecs_to_jiffies(5000));
- if (!time_left) {
- dev_err(dev, "soundwire device init timeout\n");
- return -ETIMEDOUT;
- }
+ ret = sdw_slave_wait_for_init(pm4125->tx_sdw_dev, 5000);
+ if (ret)
+ return ret;
snd_soc_component_init_regmap(component, pm4125->regmap);
ret = pm_runtime_resume_and_get(dev);
diff --git a/sound/soc/codecs/rk3328_codec.c b/sound/soc/codecs/rk3328_codec.c
index 9697aefc6e03..5871b5a81975 100644
--- a/sound/soc/codecs/rk3328_codec.c
+++ b/sound/soc/codecs/rk3328_codec.c
@@ -425,7 +425,6 @@ static int rk3328_platform_probe(struct platform_device *pdev)
struct rk3328_codec_priv *rk3328;
struct regmap *grf;
void __iomem *base;
- int ret = 0;
rk3328 = devm_kzalloc(&pdev->dev, sizeof(*rk3328), GFP_KERNEL);
if (!rk3328)
@@ -441,14 +440,13 @@ static int rk3328_platform_probe(struct platform_device *pdev)
regmap_write(grf, RK3328_GRF_SOC_CON2,
(BIT(14) << 16 | BIT(14)));
- ret = of_property_read_u32(rk3328_np, "spk-depop-time-ms",
- &rk3328->spk_depop_time);
- if (ret < 0) {
+ if (of_property_read_u32(rk3328_np, "spk-depop-time-ms",
+ &rk3328->spk_depop_time)) {
dev_info(&pdev->dev, "spk_depop_time use default value.\n");
rk3328->spk_depop_time = 200;
}
- rk3328->mute = gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH);
+ rk3328->mute = devm_gpiod_get_optional(&pdev->dev, "mute", GPIOD_OUT_HIGH);
if (IS_ERR(rk3328->mute))
return PTR_ERR(rk3328->mute);
/*
@@ -461,57 +459,31 @@ static int rk3328_platform_probe(struct platform_device *pdev)
regmap_write(grf, RK3328_GRF_SOC_CON10, BIT(17) | BIT(1));
}
- rk3328->mclk = devm_clk_get(&pdev->dev, "mclk");
+ rk3328->mclk = devm_clk_get_enabled(&pdev->dev, "mclk");
if (IS_ERR(rk3328->mclk))
return PTR_ERR(rk3328->mclk);
- ret = clk_prepare_enable(rk3328->mclk);
- if (ret)
- return ret;
clk_set_rate(rk3328->mclk, INITIAL_FREQ);
- rk3328->pclk = devm_clk_get(&pdev->dev, "pclk");
- if (IS_ERR(rk3328->pclk)) {
- dev_err(&pdev->dev, "can't get acodec pclk\n");
- ret = PTR_ERR(rk3328->pclk);
- goto err_unprepare_mclk;
- }
-
- ret = clk_prepare_enable(rk3328->pclk);
- if (ret < 0) {
- dev_err(&pdev->dev, "failed to enable acodec pclk\n");
- goto err_unprepare_mclk;
- }
+ rk3328->pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
+ if (IS_ERR(rk3328->pclk))
+ return dev_err_probe(&pdev->dev, PTR_ERR(rk3328->pclk),
+ "failed to get or enable acodec pclk\n");
base = devm_platform_ioremap_resource(pdev, 0);
- if (IS_ERR(base)) {
- ret = PTR_ERR(base);
- goto err_unprepare_pclk;
- }
+ if (IS_ERR(base))
+ return PTR_ERR(base);
rk3328->regmap = devm_regmap_init_mmio(&pdev->dev, base,
&rk3328_codec_regmap_config);
- if (IS_ERR(rk3328->regmap)) {
- ret = PTR_ERR(rk3328->regmap);
- goto err_unprepare_pclk;
- }
+ if (IS_ERR(rk3328->regmap))
+ return PTR_ERR(rk3328->regmap);
platform_set_drvdata(pdev, rk3328);
- ret = devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
+ return devm_snd_soc_register_component(&pdev->dev, &soc_codec_rk3328,
rk3328_dai,
ARRAY_SIZE(rk3328_dai));
- if (ret)
- goto err_unprepare_pclk;
-
- return 0;
-
-err_unprepare_pclk:
- clk_disable_unprepare(rk3328->pclk);
-
-err_unprepare_mclk:
- clk_disable_unprepare(rk3328->mclk);
- return ret;
}
static const struct of_device_id rk3328_codec_of_match[] __maybe_unused = {
diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c
index 03f31d9d916e..15488a059283 100644
--- a/sound/soc/codecs/rt1011.c
+++ b/sound/soc/codecs/rt1011.c
@@ -2201,7 +2201,7 @@ MODULE_DEVICE_TABLE(acpi, rt1011_acpi_match);
#endif
static const struct i2c_device_id rt1011_i2c_id[] = {
- { "rt1011" },
+ { .name = "rt1011" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt1011_i2c_id);
diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c
index ca1ed9d5a24e..ff0c08ff610e 100644
--- a/sound/soc/codecs/rt1015.c
+++ b/sound/soc/codecs/rt1015.c
@@ -1094,7 +1094,7 @@ static const struct regmap_config rt1015_regmap = {
};
static const struct i2c_device_id rt1015_i2c_id[] = {
- { "rt1015" },
+ { .name = "rt1015" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt1015_i2c_id);
diff --git a/sound/soc/codecs/rt1016.c b/sound/soc/codecs/rt1016.c
index 9f86f071fca8..11c8c45574a1 100644
--- a/sound/soc/codecs/rt1016.c
+++ b/sound/soc/codecs/rt1016.c
@@ -608,7 +608,7 @@ static const struct regmap_config rt1016_regmap = {
};
static const struct i2c_device_id rt1016_i2c_id[] = {
- { "rt1016" },
+ { .name = "rt1016" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt1016_i2c_id);
diff --git a/sound/soc/codecs/rt1017-sdca-sdw.c b/sound/soc/codecs/rt1017-sdca-sdw.c
index 148b36173a25..95405cea8143 100644
--- a/sound/soc/codecs/rt1017-sdca-sdw.c
+++ b/sound/soc/codecs/rt1017-sdca-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/pm_runtime.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/core.h>
@@ -773,25 +772,17 @@ static int rt1017_sdca_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt1017_sdca_priv *rt1017 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt1017->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT1017_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ ret = sdw_slave_wait_for_init(slave, RT1017_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt1017->regmap, false);
regcache_sync(rt1017->regmap);
diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c
index 86539c6f6cc1..370521149ac8 100644
--- a/sound/soc/codecs/rt1019.c
+++ b/sound/soc/codecs/rt1019.c
@@ -540,7 +540,7 @@ static const struct regmap_config rt1019_regmap = {
};
static const struct i2c_device_id rt1019_i2c_id[] = {
- { "rt1019" },
+ { .name = "rt1019" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt1019_i2c_id);
diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c
index 26b7382f97ef..2d5fad76cf52 100644
--- a/sound/soc/codecs/rt1305.c
+++ b/sound/soc/codecs/rt1305.c
@@ -981,8 +981,8 @@ MODULE_DEVICE_TABLE(acpi, rt1305_acpi_match);
#endif
static const struct i2c_device_id rt1305_i2c_id[] = {
- { "rt1305" },
- { "rt1306" },
+ { .name = "rt1305" },
+ { .name = "rt1306" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt1305_i2c_id);
diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c
index e077d096bc23..2f30497498c7 100644
--- a/sound/soc/codecs/rt1308-sdw.c
+++ b/sound/soc/codecs/rt1308-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/pm_runtime.h>
-#include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h>
@@ -768,25 +767,17 @@ static int rt1308_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt1308_sdw_priv *rt1308 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt1308->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT1308_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ ret = sdw_slave_wait_for_init(slave, RT1308_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt1308->regmap, false);
regcache_sync_region(rt1308->regmap, 0xc000, 0xcfff);
diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c
index df50b38c24b9..630946cd7cdf 100644
--- a/sound/soc/codecs/rt1308.c
+++ b/sound/soc/codecs/rt1308.c
@@ -795,7 +795,7 @@ MODULE_DEVICE_TABLE(acpi, rt1308_acpi_match);
#endif
static const struct i2c_device_id rt1308_i2c_id[] = {
- { "rt1308" },
+ { .name = "rt1308" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt1308_i2c_id);
diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c
index 20fc1579eb9c..ca318dbd946e 100644
--- a/sound/soc/codecs/rt1316-sdw.c
+++ b/sound/soc/codecs/rt1316-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/pm_runtime.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <sound/core.h>
@@ -745,25 +744,17 @@ static int rt1316_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt1316->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT1316_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
+ ret = sdw_slave_wait_for_init(slave, RT1316_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt1316->regmap, false);
regcache_sync(rt1316->regmap);
diff --git a/sound/soc/codecs/rt1318-sdw.c b/sound/soc/codecs/rt1318-sdw.c
index d28f1afe68f1..c038ac0e3b76 100644
--- a/sound/soc/codecs/rt1318-sdw.c
+++ b/sound/soc/codecs/rt1318-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/pm_runtime.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/dmi.h>
@@ -821,23 +820,15 @@ static int rt1318_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt1318_sdw_priv *rt1318 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt1318->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT1318_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
- return -ETIMEDOUT;
- }
+ ret = sdw_slave_wait_for_init(slave, RT1318_PROBE_TIMEOUT);
+ if (ret)
+ return ret;
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt1318->regmap, false);
regcache_sync(rt1318->regmap);
diff --git a/sound/soc/codecs/rt1318.c b/sound/soc/codecs/rt1318.c
index a80643099644..d13fd0e14125 100644
--- a/sound/soc/codecs/rt1318.c
+++ b/sound/soc/codecs/rt1318.c
@@ -1139,7 +1139,7 @@ static const struct regmap_config rt1318_regmap = {
};
static const struct i2c_device_id rt1318_i2c_id[] = {
- { "rt1318" },
+ { .name = "rt1318" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt1318_i2c_id);
diff --git a/sound/soc/codecs/rt1320-sdw.c b/sound/soc/codecs/rt1320-sdw.c
index 192faa431b5e..1e930b27c67a 100644
--- a/sound/soc/codecs/rt1320-sdw.c
+++ b/sound/soc/codecs/rt1320-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/pm_runtime.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
#include <linux/dmi.h>
@@ -3053,23 +3052,15 @@ static int rt1320_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt1320_sdw_priv *rt1320 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt1320->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT1320_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
- return -ETIMEDOUT;
- }
+ ret = sdw_slave_wait_for_init(slave, RT1320_PROBE_TIMEOUT);
+ if (ret)
+ return ret;
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt1320->regmap, false);
regcache_sync(rt1320->regmap);
regcache_cache_only(rt1320->mbq_regmap, false);
diff --git a/sound/soc/codecs/rt274.c b/sound/soc/codecs/rt274.c
index bba714020c70..63b5fc439773 100644
--- a/sound/soc/codecs/rt274.c
+++ b/sound/soc/codecs/rt274.c
@@ -1098,8 +1098,8 @@ MODULE_DEVICE_TABLE(of, rt274_of_match);
#endif
static const struct i2c_device_id rt274_i2c_id[] = {
- {"rt274"},
- {}
+ { .name = "rt274" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, rt274_i2c_id);
diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c
index 195658f626cc..ded0ea332480 100644
--- a/sound/soc/codecs/rt286.c
+++ b/sound/soc/codecs/rt286.c
@@ -1077,9 +1077,9 @@ static const struct regmap_config rt286_regmap = {
};
static const struct i2c_device_id rt286_i2c_id[] = {
- {"rt286"},
- {"rt288"},
- {}
+ { .name = "rt286" },
+ { .name = "rt288" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, rt286_i2c_id);
diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c
index 7d532a5a5f73..5414a1712b57 100644
--- a/sound/soc/codecs/rt298.c
+++ b/sound/soc/codecs/rt298.c
@@ -1138,8 +1138,8 @@ static const struct regmap_config rt298_regmap = {
};
static const struct i2c_device_id rt298_i2c_id[] = {
- {"rt298"},
- {}
+ { .name = "rt298" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, rt298_i2c_id);
diff --git a/sound/soc/codecs/rt5514.c b/sound/soc/codecs/rt5514.c
index 649b44b790b0..00a4a208d2fa 100644
--- a/sound/soc/codecs/rt5514.c
+++ b/sound/soc/codecs/rt5514.c
@@ -1200,7 +1200,7 @@ static const struct regmap_config rt5514_regmap = {
};
static const struct i2c_device_id rt5514_i2c_id[] = {
- { "rt5514" },
+ { .name = "rt5514" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5514_i2c_id);
diff --git a/sound/soc/codecs/rt5575-spi.c b/sound/soc/codecs/rt5575-spi.c
index 9a349965435b..d5b3a57c8866 100644
--- a/sound/soc/codecs/rt5575-spi.c
+++ b/sound/soc/codecs/rt5575-spi.c
@@ -17,7 +17,7 @@
struct rt5575_spi_burst_write {
u8 cmd;
- u32 addr;
+ __le32 addr;
u8 data[RT5575_SPI_BUF_LEN];
u8 dummy;
} __packed;
diff --git a/sound/soc/codecs/rt5575.c b/sound/soc/codecs/rt5575.c
index 24e41af29689..5c3e60eaa6a4 100644
--- a/sound/soc/codecs/rt5575.c
+++ b/sound/soc/codecs/rt5575.c
@@ -325,7 +325,7 @@ static int rt5575_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id rt5575_i2c_id[] = {
- { "rt5575" },
+ { .name = "rt5575" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5575_i2c_id);
diff --git a/sound/soc/codecs/rt5616.c b/sound/soc/codecs/rt5616.c
index fb9cf127e3ff..46ee412dc81d 100644
--- a/sound/soc/codecs/rt5616.c
+++ b/sound/soc/codecs/rt5616.c
@@ -1321,7 +1321,7 @@ static const struct regmap_config rt5616_regmap = {
};
static const struct i2c_device_id rt5616_i2c_id[] = {
- { "rt5616" },
+ { .name = "rt5616" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5616_i2c_id);
@@ -1386,9 +1386,6 @@ static int rt5616_i2c_probe(struct i2c_client *i2c)
rt5616_dai, ARRAY_SIZE(rt5616_dai));
}
-static void rt5616_i2c_remove(struct i2c_client *i2c)
-{}
-
static void rt5616_i2c_shutdown(struct i2c_client *client)
{
struct rt5616_priv *rt5616 = i2c_get_clientdata(client);
@@ -1403,7 +1400,6 @@ static struct i2c_driver rt5616_i2c_driver = {
.of_match_table = of_match_ptr(rt5616_of_match),
},
.probe = rt5616_i2c_probe,
- .remove = rt5616_i2c_remove,
.shutdown = rt5616_i2c_shutdown,
.id_table = rt5616_i2c_id,
};
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
index 19c6d8f760d9..ed1233973eb8 100644
--- a/sound/soc/codecs/rt5631.c
+++ b/sound/soc/codecs/rt5631.c
@@ -1671,8 +1671,8 @@ static const struct snd_soc_component_driver soc_component_dev_rt5631 = {
};
static const struct i2c_device_id rt5631_i2c_id[] = {
- { "rt5631" },
- { "alc5631" },
+ { .name = "rt5631" },
+ { .name = "alc5631" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id);
@@ -1722,16 +1722,12 @@ static int rt5631_i2c_probe(struct i2c_client *i2c)
return ret;
}
-static void rt5631_i2c_remove(struct i2c_client *client)
-{}
-
static struct i2c_driver rt5631_i2c_driver = {
.driver = {
.name = "rt5631",
.of_match_table = of_match_ptr(rt5631_i2c_dt_ids),
},
- .probe = rt5631_i2c_probe,
- .remove = rt5631_i2c_remove,
+ .probe = rt5631_i2c_probe,
.id_table = rt5631_i2c_id,
};
diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c
index f6c6294e1588..74fd05176eff 100644
--- a/sound/soc/codecs/rt5640.c
+++ b/sound/soc/codecs/rt5640.c
@@ -2397,7 +2397,7 @@ static void rt5640_jack_work(struct work_struct *work)
* disabled the OVCD IRQ, the IRQ pin will stay high and as
* we react to edges, we miss the unplug event -> recheck.
*/
- queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
+ queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, 0);
}
}
@@ -2410,7 +2410,8 @@ static irqreturn_t rt5640_irq(int irq, void *data)
delay = 100;
if (rt5640->jack)
- mod_delayed_work(system_long_wq, &rt5640->jack_work, delay);
+ mod_delayed_work(system_dfl_long_wq, &rt5640->jack_work,
+ delay);
return IRQ_HANDLED;
}
@@ -2419,7 +2420,7 @@ static irqreturn_t rt5640_jd_gpio_irq(int irq, void *data)
{
struct rt5640_priv *rt5640 = data;
- queue_delayed_work(system_long_wq, &rt5640->jack_work,
+ queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work,
msecs_to_jiffies(JACK_SETTLE_TIME));
return IRQ_HANDLED;
@@ -2553,10 +2554,12 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
rt5640->jd_gpio = jack_data->jd_gpio;
rt5640->jd_gpio_irq = gpiod_to_irq(rt5640->jd_gpio);
- ret = request_irq(rt5640->jd_gpio_irq, rt5640_jd_gpio_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "rt5640-jd-gpio", rt5640);
- if (ret) {
+ ret = request_any_context_irq(rt5640->jd_gpio_irq,
+ rt5640_jd_gpio_irq,
+ IRQF_TRIGGER_RISING |
+ IRQF_TRIGGER_FALLING,
+ "rt5640-jd-gpio", rt5640);
+ if (ret < 0) {
dev_warn(component->dev, "Failed to request jd GPIO IRQ %d: %d\n",
rt5640->jd_gpio_irq, ret);
rt5640_disable_jack_detect(component);
@@ -2568,10 +2571,10 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
if (jack_data && jack_data->use_platform_clock)
rt5640->use_platform_clock = jack_data->use_platform_clock;
- ret = request_irq(rt5640->irq, rt5640_irq,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "rt5640", rt5640);
- if (ret) {
+ ret = request_any_context_irq(rt5640->irq, rt5640_irq,
+ IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+ "rt5640", rt5640);
+ if (ret < 0) {
dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret);
rt5640_disable_jack_detect(component);
return;
@@ -2579,7 +2582,7 @@ static void rt5640_enable_jack_detect(struct snd_soc_component *component,
rt5640->irq_requested = true;
/* sync initial jack state */
- queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
+ queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, 0);
}
static const struct snd_soc_dapm_route rt5640_hda_jack_dapm_routes[] = {
@@ -2622,9 +2625,9 @@ static void rt5640_enable_hda_jack_detect(
rt5640->jack = jack;
- ret = request_irq(rt5640->irq, rt5640_irq,
- IRQF_TRIGGER_RISING, "rt5640", rt5640);
- if (ret) {
+ ret = request_any_context_irq(rt5640->irq, rt5640_irq,
+ IRQF_TRIGGER_RISING, "rt5640", rt5640);
+ if (ret < 0) {
dev_warn(component->dev, "Failed to request IRQ %d: %d\n", rt5640->irq, ret);
rt5640->jack = NULL;
return;
@@ -2632,7 +2635,7 @@ static void rt5640_enable_hda_jack_detect(
rt5640->irq_requested = true;
/* sync initial jack state */
- queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
+ queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, 0);
snd_soc_dapm_add_routes(dapm, rt5640_hda_jack_dapm_routes,
ARRAY_SIZE(rt5640_hda_jack_dapm_routes));
@@ -2860,7 +2863,7 @@ static int rt5640_resume(struct snd_soc_component *component)
}
enable_irq(rt5640->irq);
- queue_delayed_work(system_long_wq, &rt5640->jack_work, 0);
+ queue_delayed_work(system_dfl_long_wq, &rt5640->jack_work, 0);
}
return 0;
@@ -2958,9 +2961,9 @@ static const struct regmap_config rt5640_regmap = {
};
static const struct i2c_device_id rt5640_i2c_id[] = {
- { "rt5640" },
- { "rt5639" },
- { "rt5642" },
+ { .name = "rt5640" },
+ { .name = "rt5639" },
+ { .name = "rt5642" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5640_i2c_id);
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index f7701b8d0d3c..e9819653b30d 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -83,6 +83,8 @@ static const struct reg_sequence rt5650_init_list[] = {
{RT5645_PWR_ANLG1, 0x02},
{RT5645_IL_CMD3, 0x6728},
{RT5645_PR_BASE + 0x3a, 0x0000},
+ {RT5645_CLSD_OUT_CTRL1, 0x4059},
+ {RT5645_GEN_CTRL3, 0x0200},
};
static const struct reg_default rt5645_reg[] = {
@@ -1855,13 +1857,9 @@ static int rt5645_spk_event(struct snd_soc_dapm_widget *w,
RT5645_PWR_CLS_D_L,
RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
RT5645_PWR_CLS_D_L);
- snd_soc_component_update_bits(component, RT5645_GEN_CTRL3,
- RT5645_DET_CLK_MASK, RT5645_DET_CLK_MODE1);
break;
case SND_SOC_DAPM_PRE_PMD:
- snd_soc_component_update_bits(component, RT5645_GEN_CTRL3,
- RT5645_DET_CLK_MASK, RT5645_DET_CLK_DIS);
snd_soc_component_write(component, RT5645_EQ_CTRL2, 0);
snd_soc_component_update_bits(component, RT5645_PWR_DIG1,
RT5645_PWR_CLS_D | RT5645_PWR_CLS_D_R |
@@ -3646,8 +3644,8 @@ static const struct regmap_config temp_regmap = {
};
static const struct i2c_device_id rt5645_i2c_id[] = {
- { "rt5645" },
- { "rt5650" },
+ { .name = "rt5645" },
+ { .name = "rt5650" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5645_i2c_id);
diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h
index bef74b29fd54..a5bfe9861b8b 100644
--- a/sound/soc/codecs/rt5645.h
+++ b/sound/soc/codecs/rt5645.h
@@ -118,6 +118,7 @@
#define RT5645_A_JD_CTRL1 0x94
#define RT5645_VAD_CTRL4 0x9d
#define RT5645_CLSD_OUT_CTRL 0xa0
+#define RT5645_CLSD_OUT_CTRL1 0xa1
/* Function - Digital */
#define RT5645_ADC_EQ_CTRL1 0xae
#define RT5645_ADC_EQ_CTRL2 0xaf
diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c
index 23c4bf3da298..5c729135f71b 100644
--- a/sound/soc/codecs/rt5651.c
+++ b/sound/soc/codecs/rt5651.c
@@ -2202,7 +2202,7 @@ MODULE_DEVICE_TABLE(acpi, rt5651_acpi_match);
#endif
static const struct i2c_device_id rt5651_i2c_id[] = {
- { "rt5651" },
+ { .name = "rt5651" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5651_i2c_id);
diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c
index 3590ebd41c27..3097ee6d4e89 100644
--- a/sound/soc/codecs/rt5659.c
+++ b/sound/soc/codecs/rt5659.c
@@ -3814,8 +3814,8 @@ static const struct regmap_config rt5659_regmap = {
};
static const struct i2c_device_id rt5659_i2c_id[] = {
- { "rt5658" },
- { "rt5659" },
+ { .name = "rt5658" },
+ { .name = "rt5659" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5659_i2c_id);
diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c
index 84cdfb810c66..edf2e3e346e4 100644
--- a/sound/soc/codecs/rt5660.c
+++ b/sound/soc/codecs/rt5660.c
@@ -1225,7 +1225,7 @@ static const struct regmap_config rt5660_regmap = {
};
static const struct i2c_device_id rt5660_i2c_id[] = {
- { "rt5660" },
+ { .name = "rt5660" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5660_i2c_id);
diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c
index eee1c98cc4aa..262d3bba1f3d 100644
--- a/sound/soc/codecs/rt5663.c
+++ b/sound/soc/codecs/rt5663.c
@@ -3307,8 +3307,8 @@ static const struct regmap_config temp_regmap = {
};
static const struct i2c_device_id rt5663_i2c_id[] = {
- { "rt5663" },
- {}
+ { .name = "rt5663" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, rt5663_i2c_id);
diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c
index 38fb3a277e26..48f57cd0920d 100644
--- a/sound/soc/codecs/rt5665.c
+++ b/sound/soc/codecs/rt5665.c
@@ -4534,8 +4534,8 @@ static const struct regmap_config rt5665_regmap = {
};
static const struct i2c_device_id rt5665_i2c_id[] = {
- {"rt5665"},
- {}
+ { .name = "rt5665" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, rt5665_i2c_id);
diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c
index c551696ae11a..fed6de40b8c8 100644
--- a/sound/soc/codecs/rt5668.c
+++ b/sound/soc/codecs/rt5668.c
@@ -2334,8 +2334,8 @@ static const struct regmap_config rt5668_regmap = {
};
static const struct i2c_device_id rt5668_i2c_id[] = {
- {"rt5668b"},
- {}
+ { .name = "rt5668b" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, rt5668_i2c_id);
diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c
index cb5d03bf4c7f..1d120b5dc2be 100644
--- a/sound/soc/codecs/rt5670.c
+++ b/sound/soc/codecs/rt5670.c
@@ -2876,9 +2876,9 @@ static const struct regmap_config rt5670_regmap = {
};
static const struct i2c_device_id rt5670_i2c_id[] = {
- { "rt5670" },
- { "rt5671" },
- { "rt5672" },
+ { .name = "rt5670" },
+ { .name = "rt5671" },
+ { .name = "rt5672" },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5670_i2c_id);
diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c
index 60a93c3fe2e7..ac084ca008f3 100644
--- a/sound/soc/codecs/rt5677.c
+++ b/sound/soc/codecs/rt5677.c
@@ -5210,7 +5210,7 @@ static const struct acpi_device_id rt5677_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, rt5677_acpi_match);
static const struct i2c_device_id rt5677_i2c_id[] = {
- { "rt5677", RT5677 },
+ { .name = "rt5677", .driver_data = RT5677 },
{ }
};
MODULE_DEVICE_TABLE(i2c, rt5677_i2c_id);
diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c
index e556a365adc8..286cf0d17968 100644
--- a/sound/soc/codecs/rt5682-i2c.c
+++ b/sound/soc/codecs/rt5682-i2c.c
@@ -324,8 +324,8 @@ static const struct acpi_device_id rt5682_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, rt5682_acpi_match);
static const struct i2c_device_id rt5682_i2c_id[] = {
- {"rt5682"},
- {}
+ { .name = "rt5682" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, rt5682_i2c_id);
diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c
index fc464538ceff..dec8c2147d68 100644
--- a/sound/soc/codecs/rt5682-sdw.c
+++ b/sound/soc/codecs/rt5682-sdw.c
@@ -754,7 +754,7 @@ static int rt5682_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt5682_priv *rt5682 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt5682->first_hw_init)
return 0;
@@ -766,20 +766,14 @@ static int rt5682_dev_resume(struct device *dev)
rt5682->disable_irq = false;
}
mutex_unlock(&rt5682->disable_irq_lock);
- goto regmap_sync;
}
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT5682_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
+ ret = sdw_slave_wait_for_init(slave, RT5682_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt5682->sdw_regmap, false);
regcache_cache_only(rt5682->regmap, false);
regcache_sync(rt5682->regmap);
diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c
index d39f8e4f3474..4b82e07d3b2c 100644
--- a/sound/soc/codecs/rt5682.c
+++ b/sound/soc/codecs/rt5682.c
@@ -2929,20 +2929,14 @@ static int rt5682_probe(struct snd_soc_component *component)
{
struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component);
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
- struct sdw_slave *slave;
- unsigned long time;
+ int ret;
rt5682->component = component;
if (rt5682->is_sdw) {
- slave = rt5682->slave;
- time = wait_for_completion_timeout(
- &slave->initialization_complete,
- msecs_to_jiffies(RT5682_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
- return -ETIMEDOUT;
- }
+ ret = sdw_slave_wait_for_init(rt5682->slave, RT5682_PROBE_TIMEOUT);
+ if (ret)
+ return ret;
}
snd_soc_dapm_disable_pin(dapm, "MICBIAS");
diff --git a/sound/soc/codecs/rt5682s.c b/sound/soc/codecs/rt5682s.c
index 98de94a79260..3624067950c0 100644
--- a/sound/soc/codecs/rt5682s.c
+++ b/sound/soc/codecs/rt5682s.c
@@ -3325,8 +3325,8 @@ static const struct acpi_device_id rt5682s_acpi_match[] = {
MODULE_DEVICE_TABLE(acpi, rt5682s_acpi_match);
static const struct i2c_device_id rt5682s_i2c_id[] = {
- {"rt5682s"},
- {}
+ { .name = "rt5682s" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, rt5682s_i2c_id);
diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c
index 9ce36a66fae1..a451d5d1f8ab 100644
--- a/sound/soc/codecs/rt700-sdw.c
+++ b/sound/soc/codecs/rt700-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h>
@@ -522,25 +521,17 @@ static int rt700_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt700_priv *rt700 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt700->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT700_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ ret = sdw_slave_wait_for_init(slave, RT700_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt700->regmap, false);
regcache_sync_region(rt700->regmap, 0x3000, 0x8fff);
regcache_sync_region(rt700->regmap, 0x752010, 0x75206b);
diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c
index 49dacceddf81..e028a1c3a9ac 100644
--- a/sound/soc/codecs/rt711-sdca-sdw.c
+++ b/sound/soc/codecs/rt711-sdca-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw_registers.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
@@ -438,7 +437,7 @@ static int rt711_sdca_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt711->first_hw_init)
return 0;
@@ -451,20 +450,14 @@ static int rt711_sdca_dev_resume(struct device *dev)
rt711->disable_irq = false;
}
mutex_unlock(&rt711->disable_irq_lock);
- goto regmap_sync;
}
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT711_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
+ ret = sdw_slave_wait_for_init(slave, RT711_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt711->regmap, false);
regcache_sync(rt711->regmap);
regcache_cache_only(rt711->mbq_regmap, false);
diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c
index 72ddf4cebdf3..a0c6a9efa840 100644
--- a/sound/soc/codecs/rt711-sdw.c
+++ b/sound/soc/codecs/rt711-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h>
@@ -530,7 +529,7 @@ static int rt711_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt711_priv *rt711 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt711->first_hw_init)
return 0;
@@ -542,18 +541,12 @@ static int rt711_dev_resume(struct device *dev)
rt711->disable_irq = false;
}
mutex_unlock(&rt711->disable_irq_lock);
- goto regmap_sync;
}
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT711_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
- return -ETIMEDOUT;
- }
+ ret = sdw_slave_wait_for_init(slave, RT711_PROBE_TIMEOUT);
+ if (ret)
+ return ret;
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt711->regmap, false);
regcache_sync_region(rt711->regmap, 0x3000, 0x8fff);
regcache_sync_region(rt711->regmap, 0x752009, 0x752091);
diff --git a/sound/soc/codecs/rt712-sdca-dmic.c b/sound/soc/codecs/rt712-sdca-dmic.c
index 4d83544ef204..85779547653e 100644
--- a/sound/soc/codecs/rt712-sdca-dmic.c
+++ b/sound/soc/codecs/rt712-sdca-dmic.c
@@ -7,7 +7,6 @@
//
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/pm_runtime.h>
#include <linux/soundwire/sdw_registers.h>
#include <linux/slab.h>
@@ -905,26 +904,17 @@ static int rt712_sdca_dmic_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt712_sdca_dmic_priv *rt712 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt712->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT712_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n",
- __func__);
+ ret = sdw_slave_wait_for_init(slave, RT712_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt712->regmap, false);
regcache_sync(rt712->regmap);
regcache_cache_only(rt712->mbq_regmap, false);
diff --git a/sound/soc/codecs/rt712-sdca-sdw.c b/sound/soc/codecs/rt712-sdca-sdw.c
index 8c82887174db..70d661ce2ef2 100644
--- a/sound/soc/codecs/rt712-sdca-sdw.c
+++ b/sound/soc/codecs/rt712-sdca-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/soundwire/sdw_registers.h>
@@ -450,7 +449,7 @@ static int rt712_sdca_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt712_sdca_priv *rt712 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt712->first_hw_init)
return 0;
@@ -464,20 +463,14 @@ static int rt712_sdca_dev_resume(struct device *dev)
rt712->disable_irq = false;
}
mutex_unlock(&rt712->disable_irq_lock);
- goto regmap_sync;
}
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT712_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
+ ret = sdw_slave_wait_for_init(slave, RT712_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt712->regmap, false);
regcache_sync(rt712->regmap);
regcache_cache_only(rt712->mbq_regmap, false);
diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c
index 968bc183b8d8..1b183b21a4b8 100644
--- a/sound/soc/codecs/rt715-sdca-sdw.c
+++ b/sound/soc/codecs/rt715-sdca-sdw.c
@@ -8,7 +8,6 @@
#include <linux/delay.h>
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h>
@@ -224,25 +223,17 @@ static int rt715_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt715->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT715_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
+ ret = sdw_slave_wait_for_init(slave, RT715_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt715->regmap, false);
regcache_sync_region(rt715->regmap,
SDW_SDCA_CTL(FUN_JACK_CODEC, RT715_SDCA_ST_EN, RT715_SDCA_ST_CTRL,
diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c
index 49c91d015be4..f5ec348a9628 100644
--- a/sound/soc/codecs/rt715-sdw.c
+++ b/sound/soc/codecs/rt715-sdw.c
@@ -9,7 +9,6 @@
*/
#include <linux/delay.h>
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
#include <linux/soundwire/sdw_registers.h>
@@ -501,25 +500,17 @@ static int rt715_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt715_priv *rt715 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt715->first_hw_init)
return 0;
- if (!slave->unattach_request)
- goto regmap_sync;
-
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT715_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "%s: Initialization not complete, timed out\n", __func__);
+ ret = sdw_slave_wait_for_init(slave, RT715_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt715->regmap, false);
regcache_sync_region(rt715->regmap, 0x3000, 0x8fff);
regcache_sync_region(rt715->regmap, 0x752039, 0x752039);
diff --git a/sound/soc/codecs/rt721-sdca-sdw.c b/sound/soc/codecs/rt721-sdca-sdw.c
index 6eb8512975b8..041b381e582b 100644
--- a/sound/soc/codecs/rt721-sdca-sdw.c
+++ b/sound/soc/codecs/rt721-sdca-sdw.c
@@ -9,7 +9,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/pm_runtime.h>
#include <linux/soundwire/sdw_registers.h>
@@ -489,7 +488,7 @@ static int rt721_sdca_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt721_sdca_priv *rt721 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt721->first_hw_init)
return 0;
@@ -502,20 +501,14 @@ static int rt721_sdca_dev_resume(struct device *dev)
rt721->disable_irq = false;
}
mutex_unlock(&rt721->disable_irq_lock);
- goto regmap_sync;
}
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT721_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ ret = sdw_slave_wait_for_init(slave, RT721_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt721->regmap, false);
regcache_sync(rt721->regmap);
regcache_cache_only(rt721->mbq_regmap, false);
diff --git a/sound/soc/codecs/rt722-sdca-sdw.c b/sound/soc/codecs/rt722-sdca-sdw.c
index 0a5b3ffa90da..e68aa0350a5b 100644
--- a/sound/soc/codecs/rt722-sdca-sdw.c
+++ b/sound/soc/codecs/rt722-sdca-sdw.c
@@ -9,7 +9,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/pm_runtime.h>
#include <linux/soundwire/sdw_registers.h>
@@ -19,7 +18,9 @@
static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg)
{
switch (reg) {
- case 0x2f01 ... 0x2f0a:
+ case 0x22f0 ... 0x22f1:
+ case 0x2f01 ... 0x2f0c:
+ case 0x2f21 ... 0x2f24:
case 0x2f35 ... 0x2f36:
case 0x2f50 ... 0x2f52:
case 0x2f54:
@@ -84,6 +85,21 @@ static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg)
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_CS31,
RT722_SDCA_CTL_SAMPLE_FREQ_INDEX, 0):
case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2:
+ case 0x44011000 ... 0x440115ff:
+ case 0x44012000:
+ case 0x44012021:
+ case 0x44012022:
+ case 0x44012025:
+ case 0x44021000 ... 0x440211ff:
+ case 0x44022000:
+ case 0x44022019:
+ case 0x4402201a:
+ case 0x4402201d:
+ case 0x44041000 ... 0x440415ff:
+ case 0x44042000:
+ case 0x44042019:
+ case 0x4404201a:
+ case 0x4404201d:
return 1;
case 0x2000000 ... 0x2000024:
case 0x2000029 ... 0x200004a:
@@ -95,8 +111,10 @@ static int rt722_sdca_mbq_size(struct device *dev, unsigned int reg)
case 0x200007f:
case 0x2000082 ... 0x200008e:
case 0x2000090 ... 0x2000094:
+ case 0x20000b1:
+ case 0x20000b4:
case 0x3110000:
- case 0x5300000 ... 0x5300002:
+ case 0x5300000 ... 0x5300300:
case 0x5400002:
case 0x5600000 ... 0x5600007:
case 0x5700000 ... 0x5700004:
@@ -175,6 +193,7 @@ static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg)
case SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_PDE23, RT722_SDCA_CTL_ACTUAL_POWER_STATE, 0):
case RT722_BUF_ADDR_HID1 ... RT722_BUF_ADDR_HID2:
case 0x2000000:
+ case 0x2000007:
case 0x200000d:
case 0x2000019:
case 0x2000020:
@@ -186,6 +205,21 @@ static bool rt722_sdca_volatile_register(struct device *dev, unsigned int reg)
case 0x3110000:
case 0x5800003:
case 0x5810000:
+ case 0x44011000 ... 0x440115ff:
+ case 0x44012000:
+ case 0x44012021:
+ case 0x44012022:
+ case 0x44012025:
+ case 0x44021000 ... 0x440211ff:
+ case 0x44022000:
+ case 0x44022019:
+ case 0x4402201a:
+ case 0x4402201d:
+ case 0x44041000 ... 0x440415ff:
+ case 0x44042000:
+ case 0x44042019:
+ case 0x4404201a:
+ case 0x4404201d:
return true;
default:
return false;
@@ -501,7 +535,7 @@ static int rt722_sdca_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct rt722_sdca_priv *rt722 = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
if (!rt722->first_hw_init)
return 0;
@@ -514,20 +548,14 @@ static int rt722_sdca_dev_resume(struct device *dev)
rt722->disable_irq = false;
}
mutex_unlock(&rt722->disable_irq_lock);
- goto regmap_sync;
}
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(RT722_PROBE_TIMEOUT));
- if (!time) {
- dev_err(&slave->dev, "Initialization not complete, timed out\n");
+ ret = sdw_slave_wait_for_init(slave, RT722_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
-
- return -ETIMEDOUT;
+ return ret;
}
-regmap_sync:
- slave->unattach_request = 0;
regcache_cache_only(rt722->regmap, false);
regcache_sync(rt722->regmap);
return 0;
diff --git a/sound/soc/codecs/rt722-sdca.c b/sound/soc/codecs/rt722-sdca.c
index 79b8b7e70a33..1b6729f363fc 100644
--- a/sound/soc/codecs/rt722-sdca.c
+++ b/sound/soc/codecs/rt722-sdca.c
@@ -7,19 +7,21 @@
//
#include <linux/bitops.h>
-#include <sound/core.h>
#include <linux/delay.h>
+#include <linux/dmi.h>
+#include <linux/firmware.h>
#include <linux/init.h>
-#include <sound/initval.h>
-#include <sound/jack.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <sound/pcm.h>
#include <linux/pm_runtime.h>
-#include <sound/pcm_params.h>
-#include <linux/soundwire/sdw_registers.h>
#include <linux/slab.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
#include <sound/soc-dapm.h>
#include <sound/tlv.h>
@@ -344,6 +346,280 @@ static int rt722_sdca_set_jack_detect(struct snd_soc_component *component,
return 0;
}
+static int rt722_cae_load(struct rt722_sdca_priv *rt722)
+{
+ struct device *dev = &rt722->slave->dev;
+ static const char func_tag[] = "FUNC";
+ static const char xu_tag[] = "XU";
+ const char *dmi_vendor, *dmi_product, *dmi_sku;
+ char *cae_filename;
+ const struct firmware *cae_fw = NULL;
+ unsigned int cae_st_spk, cae_st_hp, cae_st_mic;
+ unsigned int func, value;
+ unsigned int combined_val;
+ unsigned int addr, size;
+ unsigned int fw_offset;
+ unsigned char mbq_high_val = 0;
+ unsigned char *param_data;
+ unsigned char *fw_data;
+ char tag[5];
+ char *space;
+ int v_len, p_len, s_len;
+ int ret = 0, i;
+ int retry = 50;
+
+ dmi_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+ dmi_product = dmi_get_system_info(DMI_PRODUCT_NAME);
+ dmi_sku = dmi_get_system_info(DMI_PRODUCT_SKU);
+
+ if (!dmi_vendor || !dmi_product || !dmi_sku) {
+ dev_warn(dev, "%s: Incomplete DMI info\n", __func__);
+ return -EINVAL;
+ }
+ space = strchr(dmi_vendor, ' ');
+ v_len = space ? space - dmi_vendor : strlen(dmi_vendor);
+
+ space = strchr(dmi_product, ' ');
+ p_len = space ? space - dmi_product : strlen(dmi_product);
+
+ space = strchr(dmi_sku, ' ');
+ s_len = space ? space - dmi_sku : strlen(dmi_sku);
+
+ cae_filename = kasprintf(GFP_KERNEL,
+ "realtek/rt722/rt722_RAE_%.*s_%.*s_%.*s.dat",
+ v_len, dmi_vendor,
+ p_len, dmi_product,
+ s_len, dmi_sku);
+ if (!cae_filename)
+ return -ENOMEM;
+ dev_dbg(dev, "%s: try to load CAE file %s\n", __func__, cae_filename);
+
+ regmap_write(rt722->regmap, RT722_SPK_CAE_PARAM1, 0x5f);
+ regmap_write(rt722->regmap, RT722_HP_CAE_PARAM39, 0x5f);
+ regmap_write(rt722->regmap, RT722_MIC_CAE_PARAM39, 0x5f);
+ usleep_range(50000, 60000);
+
+ request_firmware(&cae_fw, cae_filename, dev);
+ kfree(cae_filename);
+ if (!cae_fw) {
+ dev_err(dev, "%s: Failed to load CAE firmware\n", __func__);
+ return -ENOENT;
+ }
+
+ regmap_read(rt722->regmap, RT722_SPK_CAE_PARAM38, &cae_st_spk);
+ regmap_read(rt722->regmap, RT722_HP_CAE_PARAM68, &cae_st_hp);
+ regmap_read(rt722->regmap, RT722_MIC_CAE_PARAM99, &cae_st_mic);
+ cae_st_spk &= 0x80;
+ cae_st_hp &= 0x80;
+ cae_st_mic &= 0x80;
+
+ dev_dbg(dev, "%s(%d) spk_crc:%x, hp_crc:%x, mic_crc:%x\n",
+ __func__, __LINE__, cae_st_spk, cae_st_hp, cae_st_mic);
+
+ if (cae_st_spk)
+ rt722_sdca_index_update_bits(rt722, RT722_VENDOR_EQ_CAE,
+ RT722_EQ_CTRL_SPK, 0x0008, 0x0008);
+ else if (cae_st_hp)
+ rt722_sdca_index_update_bits(rt722, RT722_VENDOR_EQ_CAE,
+ RT722_EQ_CTRL_HP, 0x0008, 0x0008);
+ else if (cae_st_mic)
+ rt722_sdca_index_update_bits(rt722, RT722_VENDOR_EQ_CAE,
+ RT722_EQ_CTRL_DMIC, 0x0008, 0x0008);
+
+ rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
+ RT722_MISC_CTRL1, 0x8000, 0x8000);
+
+ regmap_update_bits(rt722->regmap, RT722_SPK_CAE_PARAM34, 0x1, 0x0);
+ regmap_update_bits(rt722->regmap, RT722_HP_CAE_PARAM64, 0x1, 0x0);
+ regmap_update_bits(rt722->regmap, RT722_MIC_CAE_PARAM95, 0x1, 0x0);
+
+ while (--retry) {
+ regmap_read(rt722->regmap, RT722_SPK_CAE_PARAM35, &cae_st_spk);
+ regmap_read(rt722->regmap, RT722_HP_CAE_PARAM65, &cae_st_hp);
+ regmap_read(rt722->regmap, RT722_MIC_CAE_PARAM96, &cae_st_mic);
+ dev_dbg(dev, "%s(%d) cae_st_spk:%x, cae_st_hp:%x, cae_st_mic:%x\n",
+ __func__, __LINE__, cae_st_spk, cae_st_hp, cae_st_mic);
+ if ((cae_st_spk & 0x40) && (cae_st_hp & 0x40) && (cae_st_mic & 0x40))
+ break;
+ usleep_range(1000, 1100);
+ }
+
+ if (!retry && !((cae_st_spk & 0x40) && (cae_st_hp & 0x40)
+ && (cae_st_mic & 0x40))) {
+ dev_err(dev, "%s: CAE is not ready to be loaded.\n", __func__);
+ ret = -ETIMEDOUT;
+ goto out_release;
+ }
+
+ dev_dbg(dev, "%s, cae_fw size=0x%zx, start\n", __func__, cae_fw->size);
+
+ rt722_sdca_index_write(rt722, RT722_VENDOR_EQ_CAE,
+ RT722_EQ_CTRL_AMIC, 0x8000);
+ rt722_sdca_index_write(rt722, RT722_VENDOR_EQ_CAE,
+ RT722_EQ_CTRL_DMIC, 0x8004);
+ rt722_sdca_index_write(rt722, RT722_VENDOR_EQ_CAE,
+ RT722_EQ_CTRL_HP, 0x8074);
+ rt722_sdca_index_write(rt722, RT722_VENDOR_EQ_CAE,
+ RT722_EQ_CTRL_SPK, 0xa074);
+
+ regcache_cache_bypass(rt722->regmap, true);
+ for (fw_offset = 0; fw_offset < cae_fw->size;) {
+
+ if (fw_offset + 12 > cae_fw->size) {
+ dev_err(dev, "%s: Unexpected end of firmware\n", __func__);
+ ret = -EINVAL;
+ goto verify_abort;
+ }
+
+ fw_data = (unsigned char *)&cae_fw->data[fw_offset];
+ memcpy(tag, fw_data, 4);
+ tag[4] = '\0';
+
+ if (strcmp(tag, xu_tag) == 0) {
+ dev_dbg(dev, "%s: This is a XU tag", __func__);
+ memcpy(&addr, (fw_data + 4), 4);
+ memcpy(&size, (fw_data + 8), 4);
+
+ if (size == 0 || size > cae_fw->size - fw_offset - 12) {
+ dev_err(dev, "%s: Invalid payload size: %u\n", __func__, size);
+ ret = -EINVAL;
+ goto verify_abort;
+ }
+
+ param_data = (unsigned char *)(fw_data + 12);
+
+ dev_dbg(dev, "%s: addr=0x%x, size=0x%x\n", __func__, addr, size);
+
+ if ((addr <= 0x05302300 && addr >= 0x05300000) ||
+ (addr <= 0x020020b4 && addr >= 0x020000b1)) {
+ if (addr & BIT(13)) {
+ mbq_high_val = param_data[0];
+ dev_dbg(dev, "MBQ: High Byte 0x%02x\n", mbq_high_val);
+ fw_offset += (size + 12);
+
+ continue;
+ } else {
+ regcache_cache_bypass(rt722->regmap, false);
+ combined_val = (mbq_high_val << 8) | param_data[0];
+ if (addr == 0x20000b1 || addr == 0x20000b4)
+ combined_val |= (0x2 << 8);
+ ret = regmap_write(rt722->regmap, addr, combined_val);
+ if (ret) {
+ dev_err(dev,
+ "MBQ fail: addr=0x%x ret=%d\n", addr, ret);
+ regcache_cache_bypass(rt722->regmap, true);
+ goto verify_abort;
+ }
+
+ dev_dbg(dev, "MBQ-reg=0x%x, value=0x%x\n",
+ addr, combined_val);
+
+ fw_offset += (size + 12);
+ regcache_cache_bypass(rt722->regmap, true);
+ continue;
+ }
+ }
+
+ for (i = 0; i < size; i++) {
+ ret = regmap_write(rt722->regmap, addr + i, param_data[i]);
+ if (ret) {
+ dev_err(dev,
+ "CAE write fail: addr=0x%x ret=%d\n",
+ addr + i, ret);
+ goto verify_abort;
+ }
+ }
+ fw_offset += (size + 12);
+ } else if (strcmp(tag, func_tag) == 0) {
+ dev_dbg(dev, "%s: This is a FUNC tag", __func__);
+
+ memcpy(&func, (fw_data + 4), 4);
+ memcpy(&value, (fw_data + 8), 4);
+ dev_dbg(dev, "%s: func=0x%x, value=0x%x\n",
+ __func__, func, value);
+
+ if (func == 1)
+ msleep(value);
+
+ fw_offset += 12;
+ } else {
+ dev_err(dev, "%s: No XU/FUNC tag at fw_offset=0x%x\n",
+ __func__, fw_offset);
+ ret = -EINVAL;
+ goto verify_abort;
+ }
+ }
+
+ rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
+ RT722_MISC_CTRL1, 0x8000, 0x0000);
+ regcache_cache_bypass(rt722->regmap, false);
+ rt722->cae_update_done = 1;
+ dev_dbg(dev, "%s: CAE FW update done.\n", __func__);
+ release_firmware(cae_fw);
+ return 0;
+
+verify_abort:
+ regcache_cache_bypass(rt722->regmap, false);
+ if (!ret)
+ ret = -EIO;
+out_release:
+ rt722_sdca_index_update_bits(rt722, RT722_VENDOR_REG,
+ RT722_MISC_CTRL1, 0x8000, 0x0000);
+ release_firmware(cae_fw);
+ dev_err(dev, "%s: CAE FW update aborted (ret=%d).\n", __func__, ret);
+ return ret;
+}
+
+static int rt722_cae_update_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component);
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
+ int ret, changed = 0;
+
+ if (!rt722->hw_init)
+ return 0;
+
+ ret = pm_runtime_resume_and_get(component->dev);
+ if (ret < 0 && ret != -EACCES)
+ return ret;
+
+ if (ucontrol->value.integer.value[0]) {
+ if (snd_soc_dapm_get_bias_level(dapm) == SND_SOC_BIAS_OFF) {
+ ret = rt722_cae_load(rt722);
+ if (ret) {
+ dev_err(component->dev, "CAE load failed: %d\n", ret);
+ goto out;
+ } else
+ changed = 1;
+ }
+ } else {
+ if (rt722->cae_update_done) {
+ rt722->cae_update_done = 0;
+ changed = 1;
+ }
+ }
+
+out:
+ pm_runtime_mark_last_busy(component->dev);
+ pm_runtime_put_autosuspend(component->dev);
+
+ return ret < 0 ? ret : changed;
+}
+
+static int rt722_cae_update_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = rt722->cae_update_done;
+
+ return 0;
+}
+
+
/* For SDCA control DAC/ADC Gain */
static int rt722_sdca_set_gain_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -517,6 +793,61 @@ static int rt722_sdca_fu1e_capture_put(struct snd_kcontrol *kcontrol,
return changed;
}
+static int rt722_sdca_set_fu06_playback_ctl(struct rt722_sdca_priv *rt722)
+{
+ int err;
+ unsigned int ch_l, ch_r;
+
+ ch_l = (rt722->fu06_dapm_mute || rt722->fu06_mixer_l_mute) ? 0x01 : 0x00;
+ ch_r = (rt722->fu06_dapm_mute || rt722->fu06_mixer_r_mute) ? 0x01 : 0x00;
+
+ err = regmap_write(rt722->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06,
+ RT722_SDCA_CTL_FU_MUTE, CH_L), ch_l);
+ if (err < 0)
+ return err;
+
+ err = regmap_write(rt722->regmap,
+ SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06,
+ RT722_SDCA_CTL_FU_MUTE, CH_R), ch_r);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
+static int rt722_sdca_fu06_playback_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component);
+
+ ucontrol->value.integer.value[0] = !rt722->fu06_mixer_l_mute;
+ ucontrol->value.integer.value[1] = !rt722->fu06_mixer_r_mute;
+ return 0;
+}
+
+static int rt722_sdca_fu06_playback_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
+ struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component);
+ int err, changed = 0;
+
+ if (rt722->fu06_mixer_l_mute != !ucontrol->value.integer.value[0] ||
+ rt722->fu06_mixer_r_mute != !ucontrol->value.integer.value[1])
+ changed = 1;
+
+ rt722->fu06_mixer_l_mute = !ucontrol->value.integer.value[0];
+ rt722->fu06_mixer_r_mute = !ucontrol->value.integer.value[1];
+
+ err = rt722_sdca_set_fu06_playback_ctl(rt722);
+ if (err < 0)
+ return err;
+
+ return changed;
+}
+
static int rt722_sdca_set_fu0f_capture_ctl(struct rt722_sdca_priv *rt722)
{
int err;
@@ -718,6 +1049,8 @@ static const struct snd_kcontrol_new rt722_sdca_controls[] = {
RT722_SDCA_CTL_FU_CH_GAIN, CH_R), 8, 3, 0,
rt722_sdca_set_gain_get, rt722_sdca_set_gain_put, boost_vol_tlv),
/* AMP playback settings */
+ SOC_DOUBLE_EXT("FU06 Playback Switch", SND_SOC_NOPM, 0, 1, 1, 0,
+ rt722_sdca_fu06_playback_get, rt722_sdca_fu06_playback_put),
SOC_DOUBLE_R_EXT_TLV("FU06 Playback Volume",
SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06,
RT722_SDCA_CTL_FU_VOLUME, CH_L),
@@ -738,6 +1071,9 @@ static const struct snd_kcontrol_new rt722_sdca_controls[] = {
RT722_SDCA_CTL_FU_CH_GAIN, CH_01),
rt722_sdca_dmic_set_gain_get, rt722_sdca_dmic_set_gain_put,
4, 3, boost_vol_tlv),
+ /* CAE firmware update */
+ SOC_SINGLE_EXT("CAE Update", SND_SOC_NOPM, 0, 1, 0,
+ rt722_cae_update_get, rt722_cae_update_put),
};
static const char * const adc22_mux_text[] = {
@@ -807,27 +1143,17 @@ static int rt722_sdca_fu21_event(struct snd_soc_dapm_widget *w,
struct snd_soc_component *component =
snd_soc_dapm_to_component(w->dapm);
struct rt722_sdca_priv *rt722 = snd_soc_component_get_drvdata(component);
- unsigned char unmute = 0x0, mute = 0x1;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
- regmap_write(rt722->regmap,
- SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06,
- RT722_SDCA_CTL_FU_MUTE, CH_L), unmute);
- regmap_write(rt722->regmap,
- SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06,
- RT722_SDCA_CTL_FU_MUTE, CH_R), unmute);
+ rt722->fu06_dapm_mute = false;
break;
case SND_SOC_DAPM_PRE_PMD:
- regmap_write(rt722->regmap,
- SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06,
- RT722_SDCA_CTL_FU_MUTE, CH_L), mute);
- regmap_write(rt722->regmap,
- SDW_SDCA_CTL(FUNC_NUM_AMP, RT722_SDCA_ENT_USER_FU06,
- RT722_SDCA_CTL_FU_MUTE, CH_R), mute);
+ rt722->fu06_dapm_mute = true;
break;
}
- return 0;
+
+ return rt722_sdca_set_fu06_playback_ctl(rt722);
}
static int rt722_sdca_fu113_event(struct snd_soc_dapm_widget *w,
@@ -1324,9 +1650,12 @@ int rt722_sdca_init(struct device *dev, struct regmap *regmap, struct sdw_slave
rt722->first_hw_init = false;
rt722->fu1e_dapm_mute = true;
rt722->fu0f_dapm_mute = true;
+ rt722->fu06_dapm_mute = true;
+ rt722->fu06_mixer_l_mute = rt722->fu06_mixer_r_mute = false;
rt722->fu0f_mixer_l_mute = rt722->fu0f_mixer_r_mute = true;
rt722->fu1e_mixer_mute[0] = rt722->fu1e_mixer_mute[1] =
rt722->fu1e_mixer_mute[2] = rt722->fu1e_mixer_mute[3] = true;
+ rt722->cae_update_done = 0;
return devm_snd_soc_register_component(dev,
&soc_sdca_dev_rt722, rt722_sdca_dai, ARRAY_SIZE(rt722_sdca_dai));
diff --git a/sound/soc/codecs/rt722-sdca.h b/sound/soc/codecs/rt722-sdca.h
index 823abee9ab76..b654b14334d4 100644
--- a/sound/soc/codecs/rt722-sdca.h
+++ b/sound/soc/codecs/rt722-sdca.h
@@ -36,10 +36,15 @@ struct rt722_sdca_priv {
bool fu0f_dapm_mute;
bool fu0f_mixer_l_mute;
bool fu0f_mixer_r_mute;
+ /* For AMP */
+ bool fu06_dapm_mute;
+ bool fu06_mixer_l_mute;
+ bool fu06_mixer_r_mute;
/* For DMIC */
bool fu1e_dapm_mute;
bool fu1e_mixer_mute[4];
int hw_vid;
+ int cae_update_done;
};
struct rt722_sdca_dmic_kctrl_priv {
@@ -51,6 +56,7 @@ struct rt722_sdca_dmic_kctrl_priv {
/* NID */
#define RT722_VENDOR_REG 0x20
+#define RT722_VENDOR_EQ_CAE 0x53
#define RT722_VENDOR_CALI 0x58
#define RT722_VENDOR_SPK_EFUSE 0x5c
#define RT722_VENDOR_IMS_DRE 0x5b
@@ -60,6 +66,7 @@ struct rt722_sdca_dmic_kctrl_priv {
/* Index (NID:20h) */
#define RT722_JD_PRODUCT_NUM 0x00
#define RT722_ANALOG_BIAS_CTL3 0x04
+#define RT722_MISC_CTRL1 0x07
#define RT722_JD_CTRL1 0x09
#define RT722_LDO2_3_CTL1 0x0e
#define RT722_LDO1_CTL 0x1a
@@ -75,6 +82,12 @@ struct rt722_sdca_dmic_kctrl_priv {
#define RT722_SW_CONFIG1 0x8a
#define RT722_SW_CONFIG2 0x8b
+/* Index (NID:53h) */
+#define RT722_EQ_CTRL_SPK 0x00
+#define RT722_EQ_CTRL_HP 0x100
+#define RT722_EQ_CTRL_DMIC 0x200
+#define RT722_EQ_CTRL_AMIC 0x300
+
/* Index (NID:58h) */
#define RT722_DAC_DC_CALI_CTL0 0x00
#define RT722_DAC_DC_CALI_CTL1 0x01
@@ -152,6 +165,20 @@ struct rt722_sdca_dmic_kctrl_priv {
#define RT722_BUF_ADDR_HID1 0x44030000
#define RT722_BUF_ADDR_HID2 0x44030020
+/* RT722 CAE parameter settings */
+#define RT722_SPK_CAE_PARAM1 0x44012000
+#define RT722_SPK_CAE_PARAM34 0x44012021
+#define RT722_SPK_CAE_PARAM35 0x44012022
+#define RT722_SPK_CAE_PARAM38 0x44012025
+#define RT722_HP_CAE_PARAM39 0x44022000
+#define RT722_HP_CAE_PARAM64 0x44022019
+#define RT722_HP_CAE_PARAM65 0x4402201a
+#define RT722_HP_CAE_PARAM68 0x4402201d
+#define RT722_MIC_CAE_PARAM39 0x44042000
+#define RT722_MIC_CAE_PARAM95 0x44042019
+#define RT722_MIC_CAE_PARAM96 0x4404201a
+#define RT722_MIC_CAE_PARAM99 0x4404201d
+
/* RT722 SDCA Control - function number */
#define FUNC_NUM_JACK_CODEC 0x01
#define FUNC_NUM_MIC_ARRAY 0x02
diff --git a/sound/soc/codecs/rt9123.c b/sound/soc/codecs/rt9123.c
index 84fd3d6861de..07eaf275c9e9 100644
--- a/sound/soc/codecs/rt9123.c
+++ b/sound/soc/codecs/rt9123.c
@@ -13,7 +13,6 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
diff --git a/sound/soc/codecs/rt9123p.c b/sound/soc/codecs/rt9123p.c
index d509659e735b..584fcb78cd3f 100644
--- a/sound/soc/codecs/rt9123p.c
+++ b/sound/soc/codecs/rt9123p.c
@@ -9,7 +9,6 @@
#include <linux/err.h>
#include <linux/gpio/consumer.h>
#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/sound/soc/codecs/rtq9124.c b/sound/soc/codecs/rtq9124.c
index 186904b31434..2a041894bc0c 100644
--- a/sound/soc/codecs/rtq9124.c
+++ b/sound/soc/codecs/rtq9124.c
@@ -12,7 +12,6 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
diff --git a/sound/soc/codecs/rtq9128.c b/sound/soc/codecs/rtq9128.c
index 14a2c0723d33..573200e5062f 100644
--- a/sound/soc/codecs/rtq9128.c
+++ b/sound/soc/codecs/rtq9128.c
@@ -11,7 +11,6 @@
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
diff --git a/sound/soc/codecs/sdw-mockup.c b/sound/soc/codecs/sdw-mockup.c
index b7e6546f1b5a..93f3fd1882a5 100644
--- a/sound/soc/codecs/sdw-mockup.c
+++ b/sound/soc/codecs/sdw-mockup.c
@@ -8,7 +8,6 @@
//
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/soundwire/sdw.h>
#include <linux/soundwire/sdw_type.h>
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 320312f8db92..59642673b4cb 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1809,8 +1809,8 @@ static void sgtl5000_i2c_shutdown(struct i2c_client *client)
}
static const struct i2c_device_id sgtl5000_id[] = {
- {"sgtl5000"},
- {},
+ { .name = "sgtl5000" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, sgtl5000_id);
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c
index 3343dbb63d2b..2e08fde3989c 100644
--- a/sound/soc/codecs/sigmadsp.c
+++ b/sound/soc/codecs/sigmadsp.c
@@ -35,7 +35,7 @@ struct sigmadsp_control {
struct snd_kcontrol *kcontrol;
bool is_readback;
bool cached;
- uint8_t cache[];
+ u8 cache[] __counted_by(num_bytes);
};
struct sigmadsp_data {
@@ -223,7 +223,7 @@ static int sigma_fw_load_control(struct sigmadsp *sigmadsp,
return -EINVAL;
num_bytes = le16_to_cpu(ctrl_chunk->num_bytes);
- ctrl = kzalloc(sizeof(*ctrl) + num_bytes, GFP_KERNEL);
+ ctrl = kzalloc_flex(*ctrl, cache, num_bytes);
if (!ctrl)
return -ENOMEM;
diff --git a/sound/soc/codecs/simple-amplifier.c b/sound/soc/codecs/simple-amplifier.c
index d306c585b52b..ca53b08c0b33 100644
--- a/sound/soc/codecs/simple-amplifier.c
+++ b/sound/soc/codecs/simple-amplifier.c
@@ -1,25 +1,100 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
- * Copyright (c) 2017 BayLibre, SAS.
- * Author: Jerome Brunet <jbrunet@baylibre.com>
+ * Support for gpio amplifier
+ * Copyright 2026 CS GROUP France
+ * Author: Herve Codina <herve.codina@bootlin.com>
+ *
+ * Basic simple amplifier driver
+ * Copyright (c) 2017 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
*/
+#include <linux/bitmap.h>
+#include <linux/bits.h>
#include <linux/gpio/consumer.h>
+#include <linux/math.h>
+#include <linux/minmax.h>
#include <linux/module.h>
+#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
#include <sound/soc.h>
+#include <linux/sort.h>
+#include <sound/tlv.h>
-#define DRV_NAME "simple-amplifier"
+struct simple_amp_single {
+ struct gpio_desc *gpio;
+ bool is_inverted;
+ int kctrl_val;
+ const char *control_name;
+};
+
+struct simple_amp_point {
+ u32 gpio_val;
+ int gain_db;
+};
+
+struct simple_amp_range {
+ unsigned int nb_points;
+ struct simple_amp_point min;
+ struct simple_amp_point max;
+};
+
+struct simple_amp_ranges {
+ unsigned int nb_ranges;
+ struct simple_amp_range *tab_ranges;
+};
+
+struct simple_amp_labels {
+ unsigned int nb_labels;
+ const char **tab_labels;
+};
+
+enum simple_amp_mode {
+ SIMPLE_AMP_MODE_NONE,
+ SIMPLE_AMP_MODE_RANGES,
+ SIMPLE_AMP_MODE_LABELS,
+};
+
+struct simple_amp_multi {
+ struct gpio_descs *gpios;
+ u32 kctrl_val;
+ u32 kctrl_max;
+ const char *control_name;
+ unsigned int *tlv_array;
+ enum simple_amp_mode mode;
+ union {
+ struct simple_amp_ranges ranges;
+ struct simple_amp_labels labels;
+ };
+};
+
+struct simple_amp_data {
+ unsigned int supports;
+#define SIMPLE_AUDIO_SUPPORT_PGA BIT(0)
+#define SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES BIT(1)
+#define SIMPLE_AUDIO_SUPPORT_MUTE BIT(2)
+#define SIMPLE_AUDIO_SUPPORT_BYPASS BIT(3)
+
+ const struct snd_soc_dapm_widget *dapm_widgets;
+ unsigned int num_dapm_widgets;
+ const struct snd_soc_dapm_route *dapm_routes;
+ unsigned int num_dapm_routes;
+};
struct simple_amp {
+ const struct simple_amp_data *data;
struct gpio_desc *gpiod_enable;
+ struct simple_amp_single mute;
+ struct simple_amp_single bypass;
+ struct simple_amp_multi gain;
};
-static int drv_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *control, int event)
+static int simple_amp_power_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *control, int event)
{
struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
- struct simple_amp *priv = snd_soc_component_get_drvdata(c);
+ struct simple_amp *simple_amp = snd_soc_component_get_drvdata(c);
int val;
switch (event) {
@@ -34,7 +109,7 @@ static int drv_event(struct snd_soc_dapm_widget *w,
return -EINVAL;
}
- gpiod_set_value_cansleep(priv->gpiod_enable, val);
+ gpiod_set_value_cansleep(simple_amp->gpiod_enable, val);
return 0;
}
@@ -42,7 +117,7 @@ static int drv_event(struct snd_soc_dapm_widget *w,
static const struct snd_soc_dapm_widget simple_amp_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("INL"),
SND_SOC_DAPM_INPUT("INR"),
- SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, drv_event,
+ SND_SOC_DAPM_OUT_DRV_E("DRV", SND_SOC_NOPM, 0, 0, NULL, 0, simple_amp_power_event,
(SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)),
SND_SOC_DAPM_OUTPUT("OUTL"),
SND_SOC_DAPM_OUTPUT("OUTR"),
@@ -58,47 +133,836 @@ static const struct snd_soc_dapm_route simple_amp_dapm_routes[] = {
{ "OUTR", NULL, "DRV" },
};
+static const struct snd_soc_dapm_widget simple_amp_mono_pga_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("IN"),
+ SND_SOC_DAPM_OUTPUT("OUT"),
+ SND_SOC_DAPM_PGA_E("PGA", SND_SOC_NOPM, 0, 0, NULL, 0, simple_amp_power_event,
+ (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)),
+ SND_SOC_DAPM_REGULATOR_SUPPLY("vdd", 0, 0),
+};
+
+static const struct snd_soc_dapm_route simple_amp_mono_pga_dapm_routes[] = {
+ { "PGA", NULL, "IN" },
+ { "PGA", NULL, "vdd" },
+ { "OUT", NULL, "PGA" },
+};
+
+static const struct snd_soc_dapm_widget simple_amp_stereo_pga_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("INL"),
+ SND_SOC_DAPM_INPUT("INR"),
+ SND_SOC_DAPM_OUTPUT("OUTL"),
+ SND_SOC_DAPM_OUTPUT("OUTR"),
+ SND_SOC_DAPM_PGA_E("PGA", SND_SOC_NOPM, 0, 0, NULL, 0, simple_amp_power_event,
+ (SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD)),
+ SND_SOC_DAPM_REGULATOR_SUPPLY("vdd", 0, 0),
+};
+
+static const struct snd_soc_dapm_route simple_amp_stereo_pga_dapm_routes[] = {
+ { "PGA", NULL, "INL" },
+ { "PGA", NULL, "INR" },
+ { "PGA", NULL, "vdd" },
+ { "OUTL", NULL, "PGA" },
+ { "OUTR", NULL, "PGA" },
+};
+
+static int simple_amp_single_kctrl_write_gpio(struct simple_amp_single *single,
+ int kctrl_val)
+{
+ int gpio_val;
+
+ gpio_val = single->is_inverted ? !kctrl_val : kctrl_val;
+
+ return gpiod_set_value_cansleep(single->gpio, gpio_val);
+}
+
+static int simple_amp_single_kctrl_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+ return 0;
+}
+
+static int simple_amp_single_kctrl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct simple_amp_single *single = (struct simple_amp_single *)kcontrol->private_value;
+
+ ucontrol->value.integer.value[0] = single->kctrl_val;
+
+ return 0;
+}
+
+static int simple_amp_single_kctrl_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct simple_amp_single *single = (struct simple_amp_single *)kcontrol->private_value;
+ int kctrl_val;
+ int err;
+
+ kctrl_val = ucontrol->value.integer.value[0] ? 1 : 0;
+
+ if (kctrl_val == single->kctrl_val)
+ return 0;
+
+ err = simple_amp_single_kctrl_write_gpio(single, kctrl_val);
+ if (err)
+ return err;
+
+ single->kctrl_val = kctrl_val;
+
+ return 1; /* The value changed */
+}
+
+static int simple_amp_single_add_kcontrol(struct snd_soc_component *component,
+ struct simple_amp_single *single)
+{
+ struct snd_kcontrol_new control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = single->control_name,
+ .info = simple_amp_single_kctrl_info,
+ .get = simple_amp_single_kctrl_get,
+ .put = simple_amp_single_kctrl_put,
+ .private_value = (unsigned long)single,
+ };
+ int ret;
+
+ /* Be consistent between single->kctrl_val value and the GPIO value */
+ ret = simple_amp_single_kctrl_write_gpio(single, single->kctrl_val);
+ if (ret)
+ return ret;
+
+ return snd_soc_add_component_controls(component, &control, 1);
+}
+
+static u32 simple_amp_multi_ranges_kctrl_to_gpio(u32 kctrl_val,
+ struct simple_amp_ranges *ranges)
+{
+ struct simple_amp_range *range;
+ u32 index = kctrl_val;
+ unsigned int i;
+
+ for (i = 0; i < ranges->nb_ranges; i++) {
+ range = &ranges->tab_ranges[i];
+
+ if (index < range->nb_points)
+ return (range->max.gpio_val >= range->min.gpio_val) ?
+ range->min.gpio_val + index :
+ range->min.gpio_val - index;
+
+ index -= range->nb_points;
+ }
+
+ /*
+ * Given index out of possible ranges. This is shouldn't happen.
+ * Signal the issue and return the maximum value
+ */
+ WARN(1, "kctrl_val %u out of ranges\n", kctrl_val);
+ return ranges->tab_ranges[ranges->nb_ranges - 1].max.gpio_val;
+}
+
+static int simple_amp_multi_kctrl_write_gpios(struct simple_amp_multi *multi,
+ u32 kctrl_val)
+{
+ DECLARE_BITMAP(bm, 32);
+ u32 gpio_val;
+
+ if (kctrl_val > multi->kctrl_max)
+ return -EINVAL;
+
+ if (multi->mode == SIMPLE_AMP_MODE_RANGES)
+ gpio_val = simple_amp_multi_ranges_kctrl_to_gpio(kctrl_val,
+ &multi->ranges);
+ else
+ gpio_val = kctrl_val;
+
+ bitmap_from_arr32(bm, &gpio_val, multi->gpios->ndescs);
+
+ return gpiod_multi_set_value_cansleep(multi->gpios, bm);
+}
+
+static int simple_amp_multi_kctrl_int_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
+
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = multi->kctrl_max;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ return 0;
+}
+
+static int simple_amp_multi_kctrl_int_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
+
+ ucontrol->value.integer.value[0] = multi->kctrl_val;
+ return 0;
+}
+
+static int simple_amp_multi_kctrl_int_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
+ u32 kctrl_val;
+ int ret;
+
+ kctrl_val = ucontrol->value.integer.value[0];
+
+ if (kctrl_val == multi->kctrl_val)
+ return 0;
+
+ ret = simple_amp_multi_kctrl_write_gpios(multi, kctrl_val);
+ if (ret)
+ return ret;
+
+ multi->kctrl_val = kctrl_val;
+
+ return 1; /* The value changed */
+}
+
+static int simple_amp_multi_kctrl_enum_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
+
+ return snd_ctl_enum_info(uinfo, 1, multi->labels.nb_labels,
+ multi->labels.tab_labels);
+}
+
+static int simple_amp_multi_kctrl_enum_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
+
+ ucontrol->value.enumerated.item[0] = multi->kctrl_val;
+ return 0;
+}
+
+static int simple_amp_multi_kctrl_enum_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct simple_amp_multi *multi = (struct simple_amp_multi *)kcontrol->private_value;
+ u32 kctrl_val;
+ int ret;
+
+ kctrl_val = ucontrol->value.enumerated.item[0];
+
+ if (kctrl_val == multi->kctrl_val)
+ return 0;
+
+ ret = simple_amp_multi_kctrl_write_gpios(multi, kctrl_val);
+ if (ret)
+ return ret;
+
+ multi->kctrl_val = kctrl_val;
+
+ return 1; /* The value changed */
+}
+
+static unsigned int *simple_amp_alloc_tlv_ranges(const struct simple_amp_ranges *ranges)
+{
+ unsigned int index;
+ unsigned int *tlv;
+ unsigned int *t;
+ unsigned int i;
+
+ tlv = kzalloc_objs(*tlv, 2 + ranges->nb_ranges * 6, GFP_KERNEL);
+ if (!tlv)
+ return NULL;
+
+ t = tlv;
+
+ /* Fill first TLV */
+ *t++ = SNDRV_CTL_TLVT_DB_RANGE; /* Tag */
+ *t++ = ranges->nb_ranges * 6 * sizeof(*tlv); /* Len */
+ /* Ranges are sorted from lower to higher value */
+ index = 0;
+ for (i = 0; i < ranges->nb_ranges; i++) {
+ /* Fill range item i */
+ *t++ = index; /* min */
+ index += ranges->tab_ranges[i].nb_points;
+ *t++ = index - 1; /* max */
+ *t++ = SNDRV_CTL_TLVT_DB_MINMAX; /* Tag */
+ *t++ = 2 * sizeof(*tlv); /* Len */
+ *t++ = ranges->tab_ranges[i].min.gain_db; /* min_dB */
+ *t++ = ranges->tab_ranges[i].max.gain_db; /* max_dB */
+ }
+
+ return tlv;
+}
+
+static int simple_amp_multi_add_kcontrol(struct snd_soc_component *component,
+ struct simple_amp_multi *multi)
+{
+ struct snd_kcontrol_new control = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = multi->control_name,
+ .info = simple_amp_multi_kctrl_int_info,
+ .get = simple_amp_multi_kctrl_int_get,
+ .put = simple_amp_multi_kctrl_int_put,
+ .private_value = (unsigned long)multi,
+ };
+ int ret;
+
+ switch (multi->mode) {
+ case SIMPLE_AMP_MODE_RANGES:
+ multi->tlv_array = simple_amp_alloc_tlv_ranges(&multi->ranges);
+ if (!multi->tlv_array)
+ return -ENOMEM;
+
+ control.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_READWRITE;
+ control.tlv.p = multi->tlv_array;
+ break;
+
+ case SIMPLE_AMP_MODE_LABELS:
+ /* Use enumerated values */
+ control.info = simple_amp_multi_kctrl_enum_info;
+ control.get = simple_amp_multi_kctrl_enum_get;
+ control.put = simple_amp_multi_kctrl_enum_put;
+ break;
+
+ case SIMPLE_AMP_MODE_NONE:
+ /* Already set control configuration is enough */
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ /* Be consistent between multi->kctrl_val value and the GPIOs value */
+ ret = simple_amp_multi_kctrl_write_gpios(multi, multi->kctrl_val);
+ if (ret)
+ goto err_free_tlv_array;
+
+ ret = snd_soc_add_component_controls(component, &control, 1);
+ if (ret)
+ goto err_free_tlv_array;
+
+ return 0;
+
+err_free_tlv_array:
+ kfree(multi->tlv_array);
+ return ret;
+}
+
+static int simple_amp_add_basic_dapm(struct snd_soc_component *component)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
+ struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component);
+ struct device *dev = component->dev;
+ int ret;
+
+ /* Add basic dapm widgets and routes */
+ ret = snd_soc_dapm_new_controls(dapm, simple_amp->data->dapm_widgets,
+ simple_amp->data->num_dapm_widgets);
+ if (ret) {
+ dev_err(dev, "Failed to add basic dapm widgets (%d)\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_add_routes(dapm, simple_amp->data->dapm_routes,
+ simple_amp->data->num_dapm_routes);
+ if (ret) {
+ dev_err(dev, "Failed to add basic dapm routes (%d)\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+struct simple_amp_supply {
+ const char *prop_name;
+ const struct snd_soc_dapm_widget dapm_widget;
+ const struct snd_soc_dapm_route dapm_route;
+};
+
+static const struct simple_amp_supply simple_amp_supplies[] = {
+ {
+ .prop_name = "vddio-supply",
+ .dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vddio", 0, 0),
+ .dapm_route = { "PGA", NULL, "vddio" },
+ }, {
+ .prop_name = "vdda1-supply",
+ .dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vdda1", 0, 0),
+ .dapm_route = { "PGA", NULL, "vdda1" },
+ }, {
+ .prop_name = "vdda2-supply",
+ .dapm_widget = SND_SOC_DAPM_REGULATOR_SUPPLY("vdda2", 0, 0),
+ .dapm_route = { "PGA", NULL, "vdda2" },
+ },
+ { /* End of list */}
+};
+
+static int simple_amp_add_power_supplies(struct snd_soc_component *component)
+{
+ struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
+ struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component);
+ const struct simple_amp_supply *supply;
+ struct device *dev = component->dev;
+ int ret;
+
+ /*
+ * Those additional power supplies are attached to the PGA.
+ * If PGA is not supported, simply skipped them.
+ */
+ if (!(simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_PGA)) {
+ dev_err(dev, "Extra power supplied need PGA\n");
+ return -EINVAL;
+ }
+
+ supply = simple_amp_supplies;
+ do {
+ if (!of_property_present(dev->of_node, supply->prop_name))
+ continue;
+
+ ret = snd_soc_dapm_new_controls(dapm, &supply->dapm_widget, 1);
+ if (ret) {
+ dev_err(dev, "Failed to add control for '%s' (%d)\n",
+ supply->prop_name, ret);
+ return ret;
+ }
+ ret = snd_soc_dapm_add_routes(dapm, &supply->dapm_route, 1);
+ if (ret) {
+ dev_err(dev, "Failed to add route for '%s' (%d)\n",
+ supply->prop_name, ret);
+ return ret;
+ }
+ } while ((++supply)->prop_name);
+
+ return 0;
+}
+
+static int simple_amp_component_probe(struct snd_soc_component *component)
+{
+ struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ /* Add basic dapm widgets and routes */
+ ret = simple_amp_add_basic_dapm(component);
+ if (ret)
+ return ret;
+
+ /* Add additional power supplies */
+ if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES) {
+ ret = simple_amp_add_power_supplies(component);
+ if (ret)
+ return ret;
+ }
+
+ if (simple_amp->mute.gpio) {
+ /*
+ * The name of the GPIO used is mute. According to this name, 1
+ * means muted and 0 means un-muted.
+ *
+ * An inversion is expected by ALSA. Indeed from ALSA point of
+ * view, 1 means 'on' (un-muted) and 0 means 'off' (muted).
+ */
+ simple_amp->mute.is_inverted = true;
+ simple_amp->mute.kctrl_val = 1; /* Un-muted */
+ ret = simple_amp_single_add_kcontrol(component, &simple_amp->mute);
+ if (ret)
+ return ret;
+ }
+
+ if (simple_amp->bypass.gpio) {
+ ret = simple_amp_single_add_kcontrol(component, &simple_amp->bypass);
+ if (ret)
+ return ret;
+ }
+
+ if (simple_amp->gain.gpios) {
+ ret = simple_amp_multi_add_kcontrol(component, &simple_amp->gain);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static void simple_amp_component_remove(struct snd_soc_component *component)
+{
+ struct simple_amp *simple_amp = snd_soc_component_get_drvdata(component);
+
+ kfree(simple_amp->gain.tlv_array);
+ simple_amp->gain.tlv_array = NULL;
+}
+
static const struct snd_soc_component_driver simple_amp_component_driver = {
- .dapm_widgets = simple_amp_dapm_widgets,
- .num_dapm_widgets = ARRAY_SIZE(simple_amp_dapm_widgets),
- .dapm_routes = simple_amp_dapm_routes,
- .num_dapm_routes = ARRAY_SIZE(simple_amp_dapm_routes),
+ .probe = simple_amp_component_probe,
+ .remove = simple_amp_component_remove,
};
+static int simple_amp_parse_single_gpio(struct device *dev,
+ struct simple_amp_single *single,
+ const char *gpio_property)
+{
+ /* Start with the inactive value */
+ single->is_inverted = false;
+ single->kctrl_val = 0;
+ single->gpio = devm_gpiod_get_optional(dev, gpio_property, GPIOD_OUT_LOW);
+ if (IS_ERR(single->gpio))
+ return dev_err_probe(dev, PTR_ERR(single->gpio),
+ "Failed to get '%s' gpio\n",
+ gpio_property);
+ return 0;
+}
+
+static int simple_amp_cmp_ranges(const void *a, const void *b)
+{
+ const struct simple_amp_range *a_range = a;
+ const struct simple_amp_range *b_range = b;
+
+ /* Ranges a and b don't overlap. This has been already checked */
+
+ return a_range->min.gain_db - b_range->max.gain_db;
+}
+
+static int simple_amp_check_new_range(const struct simple_amp_range *new_range,
+ const struct simple_amp_range *tab_ranges,
+ unsigned int nb_ranges)
+{
+ unsigned int i;
+
+ for (i = 0; i < nb_ranges; i++) {
+ /* Check for range overlaps */
+ if (new_range->min.gain_db >= tab_ranges[i].min.gain_db &&
+ new_range->min.gain_db <= tab_ranges[i].max.gain_db)
+ return -EINVAL;
+
+ if (new_range->max.gain_db >= tab_ranges[i].min.gain_db &&
+ new_range->max.gain_db <= tab_ranges[i].max.gain_db)
+ return -EINVAL;
+
+ if (new_range->min.gain_db <= tab_ranges[i].min.gain_db &&
+ new_range->max.gain_db >= tab_ranges[i].max.gain_db)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+static int simple_amp_parse_ranges(struct device *dev,
+ struct simple_amp_multi *multi,
+ const char *ranges_property)
+{
+ struct simple_amp_ranges *ranges = &multi->ranges;
+ struct simple_amp_range *range;
+ struct device_node *np = dev->of_node;
+ struct simple_amp_point first_point;
+ unsigned int max_gpio_val;
+ unsigned int i;
+ int ret;
+ u32 u;
+ s32 s;
+
+ max_gpio_val = (1 << multi->gpios->ndescs) - 1;
+
+ ret = of_property_count_u32_elems(np, ranges_property);
+ if (ret < 0)
+ return ret;
+
+ /* The ranges array cannot be empty */
+ if (ret == 0)
+ return -EINVAL;
+ /*
+ * One range item is composed of 2 points and each point is composed of
+ * 2 values.
+ */
+ if (ret % 4)
+ return -EINVAL;
+
+ ranges->nb_ranges = ret / 4;
+
+ /* The worst case is one range per possible gpio value */
+ if (ranges->nb_ranges > max_gpio_val + 1)
+ return -EINVAL;
+
+ ranges->tab_ranges = devm_kcalloc(dev, ranges->nb_ranges,
+ sizeof(*ranges->tab_ranges),
+ GFP_KERNEL);
+ if (!ranges->tab_ranges)
+ return -ENOMEM;
+
+ multi->kctrl_max = 0;
+ for (i = 0; i < ranges->nb_ranges; i++) {
+ range = &ranges->tab_ranges[i];
+
+ /* First gpios value */
+ ret = of_property_read_u32_index(np, ranges_property, i * 4, &u);
+ if (ret)
+ return ret;
+ if (u > max_gpio_val)
+ return -EINVAL;
+
+ range->min.gpio_val = u;
+
+ /* First Gain value */
+ ret = of_property_read_s32_index(np, ranges_property, i * 4 + 1, &s);
+ if (ret)
+ return ret;
+
+ range->min.gain_db = s;
+
+ /* Second gpios value */
+ ret = of_property_read_u32_index(np, ranges_property, i * 4 + 2, &u);
+ if (ret)
+ return ret;
+ if (u > max_gpio_val)
+ return -EINVAL;
+
+ range->max.gpio_val = u;
+
+ /* Second Gain value */
+ ret = of_property_read_s32_index(np, ranges_property, i * 4 + 3, &s);
+ if (ret)
+ return ret;
+
+ range->max.gain_db = s;
+
+ /* Save the first point for later usage */
+ if (i == 0)
+ first_point = range->min;
+
+ /* Fix min and max if needed */
+ if (range->min.gain_db > range->max.gain_db)
+ swap(range->min, range->max);
+
+ ret = simple_amp_check_new_range(range, ranges->tab_ranges, i);
+ if (ret)
+ return ret;
+
+ range->nb_points = abs_diff(range->min.gpio_val,
+ range->max.gpio_val) + 1;
+
+ multi->kctrl_max += range->nb_points;
+ }
+
+ multi->kctrl_max -= 1;
+
+ /* Sort the tab_range array by gain_db value */
+ sort(ranges->tab_ranges, ranges->nb_ranges, sizeof(*ranges->tab_ranges),
+ simple_amp_cmp_ranges, NULL);
+
+ /*
+ * multi->kctrl_val is the index in tab_ranges.
+ *
+ * Choose to have the initial amplification value set to the first point
+ * available in the first range available in the tab_ranges array before
+ * sorting.
+ *
+ * This first point has been identified before sorting. Search for it in
+ * the sorted array in order to set the multi->kctrl_val initial value.
+ */
+ multi->kctrl_val = 0;
+ for (i = 0; i < ranges->nb_ranges; i++) {
+ range = &ranges->tab_ranges[i];
+
+ if (range->min.gpio_val == first_point.gpio_val &&
+ range->min.gain_db == first_point.gain_db)
+ break;
+
+ multi->kctrl_val += range->nb_points;
+
+ if (range->max.gpio_val == first_point.gpio_val &&
+ range->max.gain_db == first_point.gain_db) {
+ multi->kctrl_val--;
+ break;
+ }
+ }
+
+ return 0;
+}
+
+static int simple_amp_parse_labels(struct device *dev,
+ struct simple_amp_multi *multi,
+ const char *labels_property)
+{
+ struct simple_amp_labels *labels = &multi->labels;
+ struct device_node *np = dev->of_node;
+ int ret;
+
+ ret = of_property_count_strings(np, labels_property);
+ if (ret < 0)
+ return ret;
+
+ /* The labels array cannot be empty */
+ if (ret == 0)
+ return -EINVAL;
+
+ labels->nb_labels = ret;
+ if (labels->nb_labels > (1 << multi->gpios->ndescs))
+ return -EINVAL;
+
+ labels->tab_labels = devm_kcalloc(dev, labels->nb_labels,
+ sizeof(*labels->tab_labels),
+ GFP_KERNEL);
+ if (!labels->tab_labels)
+ return -ENOMEM;
+
+ multi->kctrl_max = labels->nb_labels - 1;
+ multi->kctrl_val = 0;
+
+ return of_property_read_string_array(np, labels_property, labels->tab_labels,
+ labels->nb_labels);
+}
+
+static int simple_amp_parse_multi_gpio(struct device *dev,
+ struct simple_amp_multi *multi,
+ const char *gpios_property,
+ const char *ranges_property,
+ const char *labels_property)
+{
+ struct device_node *np = dev->of_node;
+ int ret;
+
+ /* Start with the value 0 (GPIO inactive). Can be changed later */
+ multi->kctrl_val = 0;
+ multi->gpios = devm_gpiod_get_array_optional(dev, gpios_property, GPIOD_OUT_LOW);
+ if (IS_ERR(multi->gpios))
+ return dev_err_probe(dev, PTR_ERR(multi->gpios),
+ "Failed to get '%s' gpios\n",
+ gpios_property);
+ if (!multi->gpios)
+ return 0;
+
+ if (multi->gpios->ndescs > 16)
+ return dev_err_probe(dev, -EINVAL,
+ "Number of '%s' gpios limited to 16\n",
+ gpios_property);
+
+ /* Set default value for the kctrl_max. Can be changed later */
+ multi->kctrl_max = (1 << multi->gpios->ndescs) - 1;
+
+ multi->mode = SIMPLE_AMP_MODE_NONE;
+ if (of_property_present(np, ranges_property)) {
+ ret = simple_amp_parse_ranges(dev, multi, ranges_property);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to parse '%s'\n",
+ ranges_property);
+ multi->mode = SIMPLE_AMP_MODE_RANGES;
+ } else if (of_property_present(np, labels_property)) {
+ ret = simple_amp_parse_labels(dev, multi, labels_property);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to parse '%s'\n",
+ labels_property);
+
+ multi->mode = SIMPLE_AMP_MODE_LABELS;
+ }
+
+ return 0;
+}
+
static int simple_amp_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
- struct simple_amp *priv;
+ struct simple_amp *simple_amp;
+ int ret;
- priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
- if (priv == NULL)
+ simple_amp = devm_kzalloc(dev, sizeof(*simple_amp), GFP_KERNEL);
+ if (!simple_amp)
return -ENOMEM;
- platform_set_drvdata(pdev, priv);
+ platform_set_drvdata(pdev, simple_amp);
- priv->gpiod_enable = devm_gpiod_get_optional(dev, "enable",
- GPIOD_OUT_LOW);
- if (IS_ERR(priv->gpiod_enable))
- return dev_err_probe(dev, PTR_ERR(priv->gpiod_enable),
+ simple_amp->data = of_device_get_match_data(dev);
+ if (!simple_amp->data)
+ return -EINVAL;
+
+ simple_amp->gpiod_enable = devm_gpiod_get_optional(dev, "enable",
+ GPIOD_OUT_LOW);
+ if (IS_ERR(simple_amp->gpiod_enable))
+ return dev_err_probe(dev, PTR_ERR(simple_amp->gpiod_enable),
"Failed to get 'enable' gpio");
+ if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_MUTE) {
+ ret = simple_amp_parse_single_gpio(dev, &simple_amp->mute, "mute");
+ if (ret)
+ return ret;
+ }
+
+ if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_BYPASS) {
+ ret = simple_amp_parse_single_gpio(dev, &simple_amp->bypass, "bypass");
+ if (ret)
+ return ret;
+ }
+
+ if (simple_amp->data->supports & SIMPLE_AUDIO_SUPPORT_PGA) {
+ ret = simple_amp_parse_multi_gpio(dev, &simple_amp->gain, "gain",
+ "gain-ranges", "gain-labels");
+ if (ret)
+ return ret;
+ }
+
+ /* Set controls name */
+ simple_amp->gain.control_name = "Volume";
+ simple_amp->mute.control_name = "Switch";
+ simple_amp->bypass.control_name = "Bypass Switch";
+
+ if (simple_amp->gain.mode == SIMPLE_AMP_MODE_LABELS) {
+ /*
+ * The gain widget control will use enumerated values.
+ *
+ * Having just "Voltage" and "Switch" widget names with
+ * enumerated values and boolean value can confuse ALSA in terms
+ * of possible values (strings).
+ *
+ * Make things clear and avoid the just "Switch" name in that
+ * case.
+ */
+ simple_amp->mute.control_name = "Out Switch";
+ }
+
return devm_snd_soc_register_component(dev,
&simple_amp_component_driver,
NULL, 0);
}
-#ifdef CONFIG_OF
+static const struct simple_amp_data simple_audio_amplifier_data = {
+ .dapm_widgets = simple_amp_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(simple_amp_dapm_widgets),
+ .dapm_routes = simple_amp_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(simple_amp_dapm_routes),
+};
+
+static const struct simple_amp_data simple_audio_mono_pga_data = {
+ .supports = SIMPLE_AUDIO_SUPPORT_PGA |
+ SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES |
+ SIMPLE_AUDIO_SUPPORT_MUTE |
+ SIMPLE_AUDIO_SUPPORT_BYPASS,
+ .dapm_widgets = simple_amp_mono_pga_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(simple_amp_mono_pga_dapm_widgets),
+ .dapm_routes = simple_amp_mono_pga_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(simple_amp_mono_pga_dapm_routes),
+};
+
+static const struct simple_amp_data simple_audio_stereo_pga_data = {
+ .supports = SIMPLE_AUDIO_SUPPORT_PGA |
+ SIMPLE_AUDIO_SUPPORT_POWER_SUPPLIES |
+ SIMPLE_AUDIO_SUPPORT_MUTE |
+ SIMPLE_AUDIO_SUPPORT_BYPASS,
+ .dapm_widgets = simple_amp_stereo_pga_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(simple_amp_stereo_pga_dapm_widgets),
+ .dapm_routes = simple_amp_stereo_pga_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(simple_amp_stereo_pga_dapm_routes),
+};
+
static const struct of_device_id simple_amp_ids[] = {
- { .compatible = "dioo,dio2125", },
- { .compatible = "simple-audio-amplifier", },
+ { .compatible = "dioo,dio2125", .data = &simple_audio_amplifier_data},
+ { .compatible = "simple-audio-amplifier", .data = &simple_audio_amplifier_data},
+ { .compatible = "gpio-audio-amp-mono", .data = &simple_audio_mono_pga_data},
+ { .compatible = "gpio-audio-amp-stereo", .data = &simple_audio_stereo_pga_data},
{ }
};
MODULE_DEVICE_TABLE(of, simple_amp_ids);
-#endif
static struct platform_driver simple_amp_driver = {
.driver = {
- .name = DRV_NAME,
- .of_match_table = of_match_ptr(simple_amp_ids),
+ .name = "simple-amplifier",
+ .of_match_table = simple_amp_ids,
},
.probe = simple_amp_probe,
};
@@ -107,4 +971,5 @@ module_platform_driver(simple_amp_driver);
MODULE_DESCRIPTION("ASoC Simple Audio Amplifier driver");
MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/simple-mux.c b/sound/soc/codecs/simple-mux.c
index 069555f35f73..c2f906a3f074 100644
--- a/sound/soc/codecs/simple-mux.c
+++ b/sound/soc/codecs/simple-mux.c
@@ -51,7 +51,7 @@ static int simple_mux_control_put(struct snd_kcontrol *kcontrol,
struct snd_soc_component *c = snd_soc_dapm_to_component(dapm);
struct simple_mux *priv = snd_soc_component_get_drvdata(c);
- if (ucontrol->value.enumerated.item[0] > e->items)
+ if (ucontrol->value.enumerated.item[0] >= e->items)
return -EINVAL;
if (priv->mux == ucontrol->value.enumerated.item[0])
diff --git a/sound/soc/codecs/sma1303.c b/sound/soc/codecs/sma1303.c
index 06de2b4fce5e..7fce60de5e5f 100644
--- a/sound/soc/codecs/sma1303.c
+++ b/sound/soc/codecs/sma1303.c
@@ -7,7 +7,6 @@
// Auther: Gyuhwa Park <gyuhwa.park@irondevice.com>
// Kiseok Jo <kiseok.jo@irondevice.com>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -1782,8 +1781,8 @@ static void sma1303_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id sma1303_i2c_id[] = {
- {"sma1303"},
- {}
+ { .name = "sma1303" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, sma1303_i2c_id);
diff --git a/sound/soc/codecs/sma1307.c b/sound/soc/codecs/sma1307.c
index 5850bf6e71ca..c52fe95b30c6 100644
--- a/sound/soc/codecs/sma1307.c
+++ b/sound/soc/codecs/sma1307.c
@@ -1592,6 +1592,7 @@ static void sma1307_check_fault_worker(struct work_struct *work)
struct sma1307_priv *sma1307 =
container_of(work, struct sma1307_priv, check_fault_work.work);
unsigned int status1_val, status2_val;
+ char volume[sizeof("VOLUME=0x12345678")];
char *envp[3] = { NULL, NULL, NULL };
if (sma1307->tsdw_cnt)
@@ -1607,7 +1608,7 @@ static void sma1307_check_fault_worker(struct work_struct *work)
if (~status1_val & SMA1307_OT1_OK_STATUS) {
dev_crit(sma1307->dev,
"%s: OT1(Over Temperature Level 1)\n", __func__);
- envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1");
+ envp[0] = "STATUS=OT1";
if (sma1307->sw_ot1_prot) {
/* Volume control (Current Volume -3dB) */
if ((sma1307->cur_vol + 6) <= 0xFA) {
@@ -1615,8 +1616,9 @@ static void sma1307_check_fault_worker(struct work_struct *work)
regmap_write(sma1307->regmap,
SMA1307_0A_SPK_VOL,
sma1307->cur_vol);
- envp[1] = kasprintf(GFP_KERNEL,
- "VOLUME=0x%02X", sma1307->cur_vol);
+ snprintf(volume, sizeof(volume),
+ "VOLUME=0x%02X", sma1307->cur_vol);
+ envp[1] = volume;
}
}
sma1307->tsdw_cnt++;
@@ -1625,48 +1627,53 @@ static void sma1307_check_fault_worker(struct work_struct *work)
SMA1307_0A_SPK_VOL, sma1307->init_vol);
sma1307->tsdw_cnt = 0;
sma1307->cur_vol = sma1307->init_vol;
- envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT1_CLEAR");
- envp[1] = kasprintf(GFP_KERNEL,
- "VOLUME=0x%02X", sma1307->cur_vol);
+ envp[0] = "STATUS=OT1_CLEAR";
+ snprintf(volume, sizeof(volume), "VOLUME=0x%02X",
+ sma1307->cur_vol);
+ envp[1] = volume;
}
if (~status1_val & SMA1307_OT2_OK_STATUS) {
dev_crit(sma1307->dev,
"%s: OT2(Over Temperature Level 2)\n", __func__);
- envp[0] = kasprintf(GFP_KERNEL, "STATUS=OT2");
+ envp[0] = "STATUS=OT2";
+ envp[1] = NULL;
}
if (status1_val & SMA1307_UVLO_STATUS) {
dev_crit(sma1307->dev,
"%s: UVLO(Under Voltage Lock Out)\n", __func__);
- envp[0] = kasprintf(GFP_KERNEL, "STATUS=UVLO");
+ envp[0] = "STATUS=UVLO";
+ envp[1] = NULL;
}
if (status1_val & SMA1307_OVP_BST_STATUS) {
dev_crit(sma1307->dev,
"%s: OVP_BST(Over Voltage Protection)\n", __func__);
- envp[0] = kasprintf(GFP_KERNEL, "STATUS=OVP_BST");
+ envp[0] = "STATUS=OVP_BST";
+ envp[1] = NULL;
}
if (status2_val & SMA1307_OCP_SPK_STATUS) {
dev_crit(sma1307->dev,
"%s: OCP_SPK(Over Current Protect SPK)\n", __func__);
- envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_SPK");
+ envp[0] = "STATUS=OCP_SPK";
+ envp[1] = NULL;
}
if (status2_val & SMA1307_OCP_BST_STATUS) {
dev_crit(sma1307->dev,
"%s: OCP_BST(Over Current Protect Boost)\n", __func__);
- envp[0] = kasprintf(GFP_KERNEL, "STATUS=OCP_BST");
+ envp[0] = "STATUS=OCP_BST";
+ envp[1] = NULL;
}
if (status2_val & SMA1307_CLK_MON_STATUS) {
dev_crit(sma1307->dev,
"%s: CLK_FAULT(No clock input)\n", __func__);
- envp[0] = kasprintf(GFP_KERNEL, "STATUS=CLK_FAULT");
+ envp[0] = "STATUS=CLK_FAULT";
+ envp[1] = NULL;
}
if (envp[0] != NULL) {
if (kobject_uevent_env(sma1307->kobj, KOBJ_CHANGE, envp))
dev_err(sma1307->dev,
"%s: Error sending uevent\n", __func__);
- kfree(envp[0]);
- kfree(envp[1]);
}
if (sma1307->check_fault_status) {
@@ -2008,8 +2015,8 @@ static void sma1307_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id sma1307_i2c_id[] = {
- { "sma1307a" },
- { "sma1307aq" },
+ { .name = "sma1307a" },
+ { .name = "sma1307aq" },
{ }
};
diff --git a/sound/soc/codecs/src4xxx-i2c.c b/sound/soc/codecs/src4xxx-i2c.c
index 55f00ce7c718..4157f7787801 100644
--- a/sound/soc/codecs/src4xxx-i2c.c
+++ b/sound/soc/codecs/src4xxx-i2c.c
@@ -6,7 +6,6 @@
// Author: Matt Flax <flatmax@flatmax.com>
#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/regmap.h>
@@ -19,7 +18,7 @@ static int src4xxx_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id src4xxx_i2c_ids[] = {
- { "src4392" },
+ { .name = "src4392" },
{ }
};
MODULE_DEVICE_TABLE(i2c, src4xxx_i2c_ids);
diff --git a/sound/soc/codecs/ssm2518.c b/sound/soc/codecs/ssm2518.c
index 9008e5416004..5192569ba6a8 100644
--- a/sound/soc/codecs/ssm2518.c
+++ b/sound/soc/codecs/ssm2518.c
@@ -794,7 +794,7 @@ MODULE_DEVICE_TABLE(of, ssm2518_dt_ids);
#endif
static const struct i2c_device_id ssm2518_i2c_ids[] = {
- { "ssm2518" },
+ { .name = "ssm2518" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ssm2518_i2c_ids);
diff --git a/sound/soc/codecs/ssm2602-i2c.c b/sound/soc/codecs/ssm2602-i2c.c
index 49c74cba17c7..23570d0a2f53 100644
--- a/sound/soc/codecs/ssm2602-i2c.c
+++ b/sound/soc/codecs/ssm2602-i2c.c
@@ -26,9 +26,9 @@ static int ssm2602_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id ssm2602_i2c_id[] = {
- { "ssm2602", SSM2602 },
- { "ssm2603", SSM2602 },
- { "ssm2604", SSM2604 },
+ { .name = "ssm2602", .driver_data = SSM2602 },
+ { .name = "ssm2603", .driver_data = SSM2602 },
+ { .name = "ssm2604", .driver_data = SSM2604 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ssm2602_i2c_id);
diff --git a/sound/soc/codecs/ssm4567.c b/sound/soc/codecs/ssm4567.c
index 15f88624faeb..8415dd163edd 100644
--- a/sound/soc/codecs/ssm4567.c
+++ b/sound/soc/codecs/ssm4567.c
@@ -472,7 +472,7 @@ static int ssm4567_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id ssm4567_i2c_ids[] = {
- { "ssm4567" },
+ { .name = "ssm4567" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ssm4567_i2c_ids);
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index b9f9784f5164..652c6e3a9e63 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -1154,9 +1154,9 @@ static int sta32x_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id sta32x_i2c_id[] = {
- { "sta326" },
- { "sta328" },
- { "sta329" },
+ { .name = "sta326" },
+ { .name = "sta328" },
+ { .name = "sta329" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sta32x_i2c_id);
diff --git a/sound/soc/codecs/sta350.c b/sound/soc/codecs/sta350.c
index 71af82b099c0..99c7f7ac807b 100644
--- a/sound/soc/codecs/sta350.c
+++ b/sound/soc/codecs/sta350.c
@@ -1236,11 +1236,8 @@ static int sta350_i2c_probe(struct i2c_client *i2c)
return ret;
}
-static void sta350_i2c_remove(struct i2c_client *client)
-{}
-
static const struct i2c_device_id sta350_i2c_id[] = {
- { "sta350" },
+ { .name = "sta350" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sta350_i2c_id);
@@ -1250,8 +1247,7 @@ static struct i2c_driver sta350_i2c_driver = {
.name = "sta350",
.of_match_table = of_match_ptr(st350_dt_ids),
},
- .probe = sta350_i2c_probe,
- .remove = sta350_i2c_remove,
+ .probe = sta350_i2c_probe,
.id_table = sta350_i2c_id,
};
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
index 946aa6a4e57c..7d57999f9cb1 100644
--- a/sound/soc/codecs/sta529.c
+++ b/sound/soc/codecs/sta529.c
@@ -361,7 +361,7 @@ static int sta529_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id sta529_i2c_id[] = {
- { "sta529" },
+ { .name = "sta529" },
{ }
};
MODULE_DEVICE_TABLE(i2c, sta529_i2c_id);
diff --git a/sound/soc/codecs/tac5xx2-sdw.c b/sound/soc/codecs/tac5xx2-sdw.c
new file mode 100644
index 000000000000..ace06f5ab58c
--- /dev/null
+++ b/sound/soc/codecs/tac5xx2-sdw.c
@@ -0,0 +1,2039 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// ALSA SoC Texas Instruments TAC5XX2 Audio Smart Amplifier
+//
+// Copyright (C) 2025 Texas Instruments Incorporated
+// https://www.ti.com
+//
+// Author: Niranjan H Y <niranjan.hy@ti.com>
+
+#include <linux/err.h>
+#include <linux/firmware.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_registers.h>
+#include <linux/soundwire/sdw_type.h>
+#include <linux/time.h>
+#include <linux/unaligned.h>
+#include <sound/pcm_params.h>
+#include <sound/sdw.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/sdca_asoc.h>
+#include <sound/sdca_function.h>
+#include <sound/sdca_regmap.h>
+#include <sound/jack.h>
+
+#include "tac5xx2.h"
+
+#define TAC5XX2_PROBE_TIMEOUT_MS 3000
+#define TAC5XX2_FW_CACHE_TIMEOUT_MS 300
+
+#define TAC5XX2_DEVICE_RATES (SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_96000 | \
+ SNDRV_PCM_RATE_88200)
+#define TAC5XX2_DEVICE_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE)
+/* Define channel constants */
+#define TAC_CHANNEL_LEFT 1
+#define TAC_CHANNEL_RIGHT 2
+#define TAC_JACK_MONO_CS 2
+
+#define TAC_MUTE_REG(func, fu, ch) \
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_##func, TAC_SDCA_ENT_##fu, \
+ TAC_SDCA_CHANNEL_MUTE, TAC_CHANNEL_##ch)
+#define TAC_USAGE_REG(func, ent) \
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_##func, TAC_SDCA_ENT_##ent, \
+ TAC_SDCA_CTL_USAGE, 0)
+#define TAC_XU_BYPASS_REG(func, xu) \
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_##func, TAC_SDCA_ENT_##xu, \
+ TAC_SDCA_CTL_XU_BYPASS, 0)
+
+/* mute registers */
+#define FU21_L_MUTE_REG TAC_MUTE_REG(SA, FU21, LEFT)
+#define FU21_R_MUTE_REG TAC_MUTE_REG(SA, FU21, RIGHT)
+#define FU23_L_MUTE_REG TAC_MUTE_REG(SA, FU23, LEFT)
+#define FU23_R_MUTE_REG TAC_MUTE_REG(SA, FU23, RIGHT)
+#define FU26_MUTE_REG TAC_MUTE_REG(SA, FU26, LEFT)
+#define FU11_L_MUTE_REG TAC_MUTE_REG(SM, FU11, LEFT)
+#define FU11_R_MUTE_REG TAC_MUTE_REG(SM, FU11, RIGHT)
+#define FU113_L_MUTE_REG TAC_MUTE_REG(SM, FU113, LEFT)
+#define FU113_R_MUTE_REG TAC_MUTE_REG(SM, FU113, RIGHT)
+#define FU41_L_MUTE_REG TAC_MUTE_REG(UAJ, FU41, LEFT)
+#define FU41_R_MUTE_REG TAC_MUTE_REG(UAJ, FU41, RIGHT)
+#define FU36_MUTE_REG TAC_MUTE_REG(UAJ, FU36, RIGHT)
+
+/* it/ot usage */
+#define IT11_USAGE_REG TAC_USAGE_REG(SM, IT11)
+#define IT41_USAGE_REG TAC_USAGE_REG(UAJ, IT41)
+#define IT33_USAGE_REG TAC_USAGE_REG(UAJ, IT33)
+#define OT113_USAGE_REG TAC_USAGE_REG(SM, OT113)
+#define OT45_USAGE_REG TAC_USAGE_REG(UAJ, OT45)
+#define OT36_USAGE_REG TAC_USAGE_REG(UAJ, OT36)
+
+/* xu bypass */
+#define XU12_BYPASS_REG TAC_XU_BYPASS_REG(SM, XU12)
+#define XU42_BYPASS_REG TAC_XU_BYPASS_REG(UAJ, XU42)
+
+#define TAC_DSP_ALGO_STATUS TAC_REG_SDW(0, 3, 12)
+#define TAC_DSP_ALGO_STATUS_RUNNING 0x20
+#define TAC_FW_HDR_SIZE 88
+#define TAC_FW_FILE_HDR 20
+#define TAC_MAX_FW_CHUNKS 512
+
+struct tac_fw_hdr {
+ u32 size;
+ u32 version_offset;
+ u32 plt_id;
+ u32 ppc3_ver;
+ u64 timestamp;
+ u8 ddc_name[64];
+};
+
+/* Firmware file/chunk structure */
+struct tac_fw_file {
+ u32 vendor_id;
+ u32 file_id;
+ u32 version;
+ u32 length;
+ u32 dest_addr;
+ u8 *fw_data;
+};
+
+/* TLV for volume control */
+static const DECLARE_TLV_DB_SCALE(tac5xx2_amp_tlv, 0, 50, 0);
+static const DECLARE_TLV_DB_SCALE(tac5xx2_dvc_tlv, -7200, 50, 0);
+
+/* Q7.8 volume control parameters: range -72dB to +6dB, step 0.5dB */
+#define TAC_DVC_STEP 128 /* 0.5 dB in Q7.8 format */
+#define TAC_DVC_MIN (-144) /* -72 dB / 0.5 dB step */
+#define TAC_DVC_MAX 12 /* +6 dB / 0.5 dB step */
+
+/* TAC-specific stereo volume control macro using SDW_SDCA_CTL (single control for L/R) */
+#define TAC_DOUBLE_Q78_TLV(name, func_id, ent_id) \
+ SDCA_DOUBLE_Q78_TLV(name, \
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_##func_id, TAC_SDCA_ENT_##ent_id, \
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), \
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_##func_id, TAC_SDCA_ENT_##ent_id, \
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), \
+ TAC_DVC_MIN, TAC_DVC_MAX, TAC_DVC_STEP, tac5xx2_dvc_tlv)
+
+struct tac5xx2_prv {
+ struct snd_soc_component *component;
+ struct sdw_slave *sdw_peripheral;
+ struct sdca_function_data *sa_func_data;
+ struct sdca_function_data *sm_func_data;
+ struct sdca_function_data *uaj_func_data;
+ struct sdca_function_data *hid_func_data;
+ enum sdw_slave_status status;
+ struct regmap *regmap;
+ struct device *dev;
+ bool hw_init;
+ bool first_hw_init_done;
+ u32 part_id;
+ struct snd_soc_jack *hs_jack;
+ int jack_type;
+ /* Custom fw binary. UMP File Download is not used. */
+ unsigned int fw_file_cnt;
+ struct tac_fw_file *fw_files;
+ struct completion fw_caching_complete;
+ bool fw_dl_success;
+ u8 fw_binaryname[64];
+};
+
+static const struct reg_default tac_reg_default[] = {
+ {TAC_SW_RESET, 0x0},
+ {TAC_SLEEP_MODEZ, 0x0},
+ {TAC_FEATURE_PDZ, 0x0},
+ {TAC_TX_CH_EN, 0xf0},
+ {TAC_REG_SDW(0, 0, 0x5), 0xcf},
+ {TAC_REG_SDW(0, 0, 0x6), 0xa},
+ {TAC_REG_SDW(0, 0, 0x7), 0x0},
+ {TAC_REG_SDW(0, 0, 0x8), 0xfe},
+ {TAC_REG_SDW(0, 0, 0x9), 0x9},
+ {TAC_REG_SDW(0, 0, 0xa), 0x28},
+ {TAC_REG_SDW(0, 0, 0xb), 0x1},
+ {TAC_REG_SDW(0, 0, 0xc), 0x11},
+ {TAC_REG_SDW(0, 0, 0xd), 0x11},
+ {TAC_REG_SDW(0, 0, 0xe), 0x61},
+ {TAC_REG_SDW(0, 0, 0xf), 0x0},
+ {TAC_REG_SDW(0, 0, 0x10), 0x50},
+ {TAC_REG_SDW(0, 0, 0x11), 0x70},
+ {TAC_REG_SDW(0, 0, 0x12), 0x60},
+ {TAC_REG_SDW(0, 0, 0x13), 0x28},
+ {TAC_REG_SDW(0, 0, 0x14), 0x0},
+ {TAC_REG_SDW(0, 0, 0x15), 0x18},
+ {TAC_REG_SDW(0, 0, 0x16), 0x20},
+ {TAC_REG_SDW(0, 0, 0x17), 0x0},
+ {TAC_REG_SDW(0, 0, 0x18), 0x18},
+ {TAC_REG_SDW(0, 0, 0x19), 0x54},
+ {TAC_REG_SDW(0, 0, 0x1a), 0x8},
+ {TAC_REG_SDW(0, 0, 0x1b), 0x0},
+ {TAC_REG_SDW(0, 0, 0x1c), 0x30},
+ {TAC_REG_SDW(0, 0, 0x1d), 0x0},
+ {TAC_REG_SDW(0, 0, 0x1e), 0x0},
+ {TAC_REG_SDW(0, 0, 0x1f), 0x0},
+ {TAC_REG_SDW(0, 0, 0x20), 0x0},
+ {TAC_REG_SDW(0, 0, 0x21), 0x20},
+ {TAC_REG_SDW(0, 0, 0x22), 0x21},
+ {TAC_REG_SDW(0, 0, 0x23), 0x22},
+ {TAC_REG_SDW(0, 0, 0x24), 0x23},
+ {TAC_REG_SDW(0, 0, 0x25), 0x4},
+ {TAC_REG_SDW(0, 0, 0x26), 0x5},
+ {TAC_REG_SDW(0, 0, 0x27), 0x6},
+ {TAC_REG_SDW(0, 0, 0x28), 0x7},
+ {TAC_REG_SDW(0, 0, 0x29), 0x0},
+ {TAC_REG_SDW(0, 0, 0x2a), 0x0},
+ {TAC_REG_SDW(0, 0, 0x2b), 0x0},
+ {TAC_REG_SDW(0, 0, 0x2c), 0x20},
+ {TAC_REG_SDW(0, 0, 0x2d), 0x21},
+ {TAC_REG_SDW(0, 0, 0x2e), 0x2},
+ {TAC_REG_SDW(0, 0, 0x2f), 0x3},
+ {TAC_REG_SDW(0, 0, 0x30), 0x4},
+ {TAC_REG_SDW(0, 0, 0x31), 0x5},
+ {TAC_REG_SDW(0, 0, 0x32), 0x6},
+ {TAC_REG_SDW(0, 0, 0x33), 0x7},
+ {TAC_REG_SDW(0, 0, 0x34), 0x0},
+ {TAC_REG_SDW(0, 0, 0x35), 0x90},
+ {TAC_REG_SDW(0, 0, 0x36), 0x80},
+ {TAC_REG_SDW(0, 0, 0x37), 0x0},
+ {TAC_REG_SDW(0, 0, 0x39), 0x0},
+ {TAC_REG_SDW(0, 0, 0x3a), 0x90},
+ {TAC_REG_SDW(0, 0, 0x3b), 0x80},
+ {TAC_REG_SDW(0, 0, 0x3c), 0x0},
+ {TAC_REG_SDW(0, 0, 0x3e), 0x0},
+ {TAC_REG_SDW(0, 0, 0x3f), 0x90},
+ {TAC_REG_SDW(0, 0, 0x40), 0x80},
+ {TAC_REG_SDW(0, 0, 0x41), 0x0},
+ {TAC_REG_SDW(0, 0, 0x43), 0x90},
+ {TAC_REG_SDW(0, 0, 0x44), 0x80},
+ {TAC_REG_SDW(0, 0, 0x45), 0x0},
+ {TAC_REG_SDW(0, 0, 0x47), 0x90},
+ {TAC_REG_SDW(0, 0, 0x48), 0x80},
+ {TAC_REG_SDW(0, 0, 0x49), 0x0},
+ {TAC_REG_SDW(0, 0, 0x4b), 0x90},
+ {TAC_REG_SDW(0, 0, 0x4c), 0x80},
+ {TAC_REG_SDW(0, 0, 0x4d), 0x0},
+ {TAC_REG_SDW(0, 0, 0x4f), 0x31},
+ {TAC_REG_SDW(0, 0, 0x50), 0x0},
+ {TAC_REG_SDW(0, 0, 0x51), 0x0},
+ {TAC_REG_SDW(0, 0, 0x52), 0x90},
+ {TAC_REG_SDW(0, 0, 0x53), 0x80},
+ {TAC_REG_SDW(0, 0, 0x55), 0x90},
+ {TAC_REG_SDW(0, 0, 0x56), 0x80},
+ {TAC_REG_SDW(0, 0, 0x58), 0x90},
+ {TAC_REG_SDW(0, 0, 0x59), 0x80},
+ {TAC_REG_SDW(0, 0, 0x5b), 0x90},
+ {TAC_REG_SDW(0, 0, 0x5c), 0x80},
+ {TAC_REG_SDW(0, 0, 0x5e), 0x8},
+ {TAC_REG_SDW(0, 0, 0x5f), 0x8},
+ {TAC_REG_SDW(0, 0, 0x60), 0x0},
+ {TAC_REG_SDW(0, 0, 0x61), 0x0},
+ {TAC_REG_SDW(0, 0, 0x62), 0xff},
+ {TAC_REG_SDW(0, 0, 0x63), 0xc0},
+ {TAC_REG_SDW(0, 0, 0x64), 0x5},
+ {TAC_REG_SDW(0, 0, 0x65), 0x3},
+ {TAC_REG_SDW(0, 0, 0x66), 0x0},
+ {TAC_REG_SDW(0, 0, 0x67), 0x0},
+ {TAC_REG_SDW(0, 0, 0x68), 0x0},
+ {TAC_REG_SDW(0, 0, 0x69), 0x8},
+ {TAC_REG_SDW(0, 0, 0x6a), 0x0},
+ {TAC_REG_SDW(0, 0, 0x6b), 0xa0},
+ {TAC_REG_SDW(0, 0, 0x6c), 0x18},
+ {TAC_REG_SDW(0, 0, 0x6d), 0x18},
+ {TAC_REG_SDW(0, 0, 0x6e), 0x18},
+ {TAC_REG_SDW(0, 0, 0x6f), 0x18},
+ {TAC_REG_SDW(0, 0, 0x70), 0x88},
+ {TAC_REG_SDW(0, 0, 0x71), 0xff},
+ {TAC_REG_SDW(0, 0, 0x72), 0x0},
+ {TAC_REG_SDW(0, 0, 0x73), 0x31},
+ {TAC_REG_SDW(0, 0, 0x74), 0xc0},
+ {TAC_REG_SDW(0, 0, 0x75), 0x0},
+ {TAC_REG_SDW(0, 0, 0x76), 0x0},
+ {TAC_REG_SDW(0, 0, 0x77), 0x0},
+ {TAC_REG_SDW(0, 0, 0x78), 0x0},
+ {TAC_REG_SDW(0, 0, 0x7b), 0x0},
+ {TAC_REG_SDW(0, 0, 0x7c), 0xd0},
+ {TAC_REG_SDW(0, 0, 0x7d), 0x0},
+ {TAC_REG_SDW(0, 0, 0x7e), 0x0},
+ {TAC_REG_SDW(0, 1, 0x1), 0x0},
+ {TAC_REG_SDW(0, 1, 0x2), 0x0},
+ {TAC_REG_SDW(0, 1, 0x3), 0x0},
+ {TAC_REG_SDW(0, 1, 0x4), 0x4},
+ {TAC_REG_SDW(0, 1, 0x5), 0x0},
+ {TAC_REG_SDW(0, 1, 0x6), 0x0},
+ {TAC_REG_SDW(0, 1, 0x7), 0x0},
+ {TAC_REG_SDW(0, 1, 0x8), 0x0},
+ {TAC_REG_SDW(0, 1, 0x9), 0x0},
+ {TAC_REG_SDW(0, 1, 0xa), 0x0},
+ {TAC_REG_SDW(0, 1, 0xb), 0x1},
+ {TAC_REG_SDW(0, 1, 0xc), 0x0},
+ {TAC_REG_SDW(0, 1, 0xd), 0x0},
+ {TAC_REG_SDW(0, 1, 0xe), 0x0},
+ {TAC_REG_SDW(0, 1, 0xf), 0x8},
+ {TAC_REG_SDW(0, 1, 0x10), 0x0},
+ {TAC_REG_SDW(0, 1, 0x11), 0x0},
+ {TAC_REG_SDW(0, 1, 0x12), 0x1},
+ {TAC_REG_SDW(0, 1, 0x13), 0x0},
+ {TAC_REG_SDW(0, 1, 0x14), 0x0},
+ {TAC_REG_SDW(0, 1, 0x15), 0x0},
+ {TAC_REG_SDW(0, 1, 0x16), 0x0},
+ {TAC_REG_SDW(0, 1, 0x17), 0x0},
+ {TAC_REG_SDW(0, 1, 0x18), 0x0},
+ {TAC_REG_SDW(0, 1, 0x19), 0x0},
+ {TAC_REG_SDW(0, 1, 0x1a), 0x0},
+ {TAC_REG_SDW(0, 1, 0x1b), 0x0},
+ {TAC_REG_SDW(0, 1, 0x1c), 0x0},
+ {TAC_REG_SDW(0, 1, 0x1d), 0x0},
+ {TAC_REG_SDW(0, 1, 0x1e), 0x2},
+ {TAC_REG_SDW(0, 1, 0x1f), 0x8},
+ {TAC_REG_SDW(0, 1, 0x20), 0x9},
+ {TAC_REG_SDW(0, 1, 0x21), 0xa},
+ {TAC_REG_SDW(0, 1, 0x22), 0xb},
+ {TAC_REG_SDW(0, 1, 0x23), 0xc},
+ {TAC_REG_SDW(0, 1, 0x24), 0xd},
+ {TAC_REG_SDW(0, 1, 0x25), 0xe},
+ {TAC_REG_SDW(0, 1, 0x26), 0xf},
+ {TAC_REG_SDW(0, 1, 0x27), 0x8},
+ {TAC_REG_SDW(0, 1, 0x28), 0x9},
+ {TAC_REG_SDW(0, 1, 0x29), 0xa},
+ {TAC_REG_SDW(0, 1, 0x2a), 0xb},
+ {TAC_REG_SDW(0, 1, 0x2b), 0xc},
+ {TAC_REG_SDW(0, 1, 0x2c), 0xd},
+ {TAC_REG_SDW(0, 1, 0x2d), 0xe},
+ {TAC_REG_SDW(0, 1, 0x2e), 0xf},
+ {TAC_REG_SDW(0, 1, 0x2f), 0x0},
+ {TAC_REG_SDW(0, 1, 0x30), 0x0},
+ {TAC_REG_SDW(0, 1, 0x31), 0x0},
+ {TAC_REG_SDW(0, 1, 0x32), 0x0},
+ {TAC_REG_SDW(0, 1, 0x33), 0x0},
+ {TAC_REG_SDW(0, 1, 0x34), 0x0},
+ {TAC_REG_SDW(0, 1, 0x35), 0x0},
+ {TAC_REG_SDW(0, 1, 0x36), 0x0},
+ {TAC_REG_SDW(0, 1, 0x37), 0x0},
+ {TAC_REG_SDW(0, 1, 0x38), 0x98},
+ {TAC_REG_SDW(0, 1, 0x39), 0x0},
+ {TAC_REG_SDW(0, 1, 0x3a), 0x0},
+ {TAC_REG_SDW(0, 1, 0x3b), 0x0},
+ {TAC_REG_SDW(0, 1, 0x3c), 0x1},
+ {TAC_REG_SDW(0, 1, 0x3d), 0x2},
+ {TAC_REG_SDW(0, 1, 0x3e), 0x3},
+ {TAC_REG_SDW(0, 1, 0x3f), 0x4},
+ {TAC_REG_SDW(0, 1, 0x40), 0x5},
+ {TAC_REG_SDW(0, 1, 0x41), 0x6},
+ {TAC_REG_SDW(0, 1, 0x42), 0x7},
+ {TAC_REG_SDW(0, 1, 0x43), 0x0},
+ {TAC_REG_SDW(0, 1, 0x44), 0x0},
+ {TAC_REG_SDW(0, 1, 0x45), 0x1},
+ {TAC_REG_SDW(0, 1, 0x46), 0x2},
+ {TAC_REG_SDW(0, 1, 0x47), 0x3},
+ {TAC_REG_SDW(0, 1, 0x48), 0x4},
+ {TAC_REG_SDW(0, 1, 0x49), 0x5},
+ {TAC_REG_SDW(0, 1, 0x4a), 0x6},
+ {TAC_REG_SDW(0, 1, 0x4b), 0x7},
+ {TAC_REG_SDW(0, 1, 0x4c), 0x98},
+ {TAC_REG_SDW(0, 1, 0x4d), 0x0},
+ {TAC_REG_SDW(0, 1, 0x4e), 0x0},
+ {TAC_REG_SDW(0, 1, 0x4f), 0x0},
+ {TAC_REG_SDW(0, 1, 0x50), 0x1},
+ {TAC_REG_SDW(0, 1, 0x51), 0x2},
+ {TAC_REG_SDW(0, 1, 0x52), 0x3},
+ {TAC_REG_SDW(0, 1, 0x53), 0x4},
+ {TAC_REG_SDW(0, 1, 0x54), 0x5},
+ {TAC_REG_SDW(0, 1, 0x55), 0x6},
+ {TAC_REG_SDW(0, 1, 0x56), 0x7},
+ {TAC_REG_SDW(0, 1, 0x57), 0x0},
+ {TAC_REG_SDW(0, 1, 0x58), 0x0},
+ {TAC_REG_SDW(0, 1, 0x59), 0x1},
+ {TAC_REG_SDW(0, 1, 0x5a), 0x2},
+ {TAC_REG_SDW(0, 1, 0x5b), 0x3},
+ {TAC_REG_SDW(0, 1, 0x5c), 0x4},
+ {TAC_REG_SDW(0, 1, 0x5d), 0x5},
+ {TAC_REG_SDW(0, 1, 0x5e), 0x6},
+ {TAC_REG_SDW(0, 1, 0x5f), 0x7},
+ {TAC_REG_SDW(0, 1, 0x60), 0x98},
+ {TAC_REG_SDW(0, 1, 0x61), 0x0},
+ {TAC_REG_SDW(0, 1, 0x62), 0x0},
+ {TAC_REG_SDW(0, 1, 0x63), 0x0},
+ {TAC_REG_SDW(0, 1, 0x64), 0x1},
+ {TAC_REG_SDW(0, 1, 0x65), 0x2},
+ {TAC_REG_SDW(0, 1, 0x66), 0x3},
+ {TAC_REG_SDW(0, 1, 0x67), 0x4},
+ {TAC_REG_SDW(0, 1, 0x68), 0x5},
+ {TAC_REG_SDW(0, 1, 0x69), 0x6},
+ {TAC_REG_SDW(0, 1, 0x6a), 0x7},
+ {TAC_REG_SDW(0, 1, 0x6b), 0x0},
+ {TAC_REG_SDW(0, 1, 0x6c), 0x0},
+ {TAC_REG_SDW(0, 1, 0x6d), 0x1},
+ {TAC_REG_SDW(0, 1, 0x6e), 0x2},
+ {TAC_REG_SDW(0, 1, 0x6f), 0x3},
+ {TAC_REG_SDW(0, 1, 0x70), 0x4},
+ {TAC_REG_SDW(0, 1, 0x71), 0x5},
+ {TAC_REG_SDW(0, 1, 0x72), 0x6},
+ {TAC_REG_SDW(0, 1, 0x73), 0x7},
+};
+
+static const struct reg_sequence tac_spk_seq[] = {
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
+};
+
+static const struct reg_sequence tac_sm_seq[] = {
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
+};
+
+static const struct reg_sequence tac_uaj_seq[] = {
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT), 0),
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT), 0),
+ REG_SEQ0(SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU36,
+ TAC_SDCA_CHANNEL_GAIN, TAC_JACK_MONO_CS), 0),
+};
+
+static bool tac_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TAC_REG_SDW(0, 0, 1) ... TAC_REG_SDW(0, 0, 5):
+ case TAC_REG_SDW(0, 2, 1) ... TAC_REG_SDW(0, 2, 6):
+ case TAC_REG_SDW(0, 2, 24) ... TAC_REG_SDW(0, 2, 55):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
+ TAC_SDCA_CTL_HIDTX_CURRENT_OWNER, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
+ TAC_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_GE35,
+ TAC_SDCA_CTL_DET_MODE, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_PDE23,
+ TAC_SDCA_REQUESTED_PS, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_PDE11,
+ TAC_SDCA_REQUESTED_PS, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE47,
+ TAC_SDCA_REQUESTED_PS, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE34,
+ TAC_SDCA_REQUESTED_PS, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_PDE23,
+ TAC_SDCA_ACTUAL_PS, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_PDE11,
+ TAC_SDCA_ACTUAL_PS, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE47,
+ TAC_SDCA_ACTUAL_PS, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_PDE34,
+ TAC_SDCA_ACTUAL_PS, 0):
+ case SDW_SCP_SDCA_INT1:
+ case SDW_SCP_SDCA_INT2:
+ case SDW_SCP_SDCA_INT3:
+ case SDW_SCP_SDCA_INT4:
+ case SDW_SDCA_CTL(1, 0, 0x10, 0):
+ case SDW_SDCA_CTL(2, 0, 0x10, 0):
+ case SDW_SDCA_CTL(3, 0, 0x10, 0):
+ case SDW_SDCA_CTL(4, 0, 0x1, 0):
+ case 0x44007F80 ... 0x44007F87:
+ case TAC_DSP_ALGO_STATUS: /* DSP algo status - always read from HW */
+ return true;
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static int tac_sdca_mbq_size(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21,
+ TAC_SDCA_CHANNEL_VOLUME, TAC_CHANNEL_LEFT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU21,
+ TAC_SDCA_CHANNEL_VOLUME, TAC_CHANNEL_RIGHT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SA, TAC_SDCA_ENT_FU23,
+ TAC_SDCA_MASTER_GAIN, 0):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU113,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_SM, TAC_SDCA_ENT_FU11,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_LEFT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU41,
+ TAC_SDCA_CHANNEL_GAIN, TAC_CHANNEL_RIGHT):
+ case SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU36,
+ TAC_SDCA_CHANNEL_GAIN, TAC_JACK_MONO_CS):
+ return 2;
+
+ default:
+ return 1;
+ }
+}
+
+static const struct regmap_sdw_mbq_cfg tac_mbq_cfg = {
+ .mbq_size = tac_sdca_mbq_size,
+};
+
+static const struct regmap_config tac_regmap = {
+ .reg_bits = 32,
+ .val_bits = 16, /* mbq support */
+ .reg_defaults = tac_reg_default,
+ .num_reg_defaults = ARRAY_SIZE(tac_reg_default),
+ .max_register = 0x47FFFFFF,
+ .cache_type = REGCACHE_MAPLE,
+ .volatile_reg = tac_volatile_reg,
+ .use_single_read = true,
+ .use_single_write = true,
+};
+
+/* Check if device has DSP algo that needs status monitoring */
+static bool tac_has_dsp_algo(struct tac5xx2_prv *tac_dev)
+{
+ switch (tac_dev->part_id) {
+ case 0x5682:
+ case 0x2883:
+ return true;
+ default:
+ return false;
+ }
+}
+
+/* Check if device has UAJ (Universal Audio Jack) support */
+static bool tac_has_uaj_support(struct tac5xx2_prv *tac_dev)
+{
+ return tac_dev->uaj_func_data;
+}
+
+/* Forward declaration for headset detection */
+static int tac5xx2_sdca_headset_detect(struct tac5xx2_prv *tac_dev);
+
+/* Volume controls for mic, hp and mic cap */
+static const struct snd_kcontrol_new tac5xx2_snd_controls[] = {
+ SOC_DOUBLE_R_RANGE_TLV("Amp Volume", TAC_AMP_LVL_CFG0, TAC_AMP_LVL_CFG1,
+ 2, 0, 44, 1, tac5xx2_amp_tlv),
+ TAC_DOUBLE_Q78_TLV("DMIC Capture Volume", SM, FU113),
+ TAC_DOUBLE_Q78_TLV("Speaker Volume", SA, FU21),
+};
+
+static const struct snd_kcontrol_new tac_uaj_controls[] = {
+ TAC_DOUBLE_Q78_TLV("UAJ Playback Volume", UAJ, FU41),
+ SDCA_SINGLE_Q78_TLV("UAJ Capture Volume",
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_FU36,
+ TAC_SDCA_CHANNEL_GAIN, TAC_JACK_MONO_CS),
+ TAC_DVC_MIN, TAC_DVC_MAX, TAC_DVC_STEP, tac5xx2_dvc_tlv),
+};
+
+static const struct snd_soc_dapm_widget tac5xx2_common_widgets[] = {
+ /* Port 1: Speaker Playback Path */
+ SND_SOC_DAPM_AIF_IN("AIF1 Playback", "DP1 Speaker Playback", 0,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_PGA("FU21_L", FU21_L_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("FU21_R", FU21_R_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("FU23_L", FU23_L_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("FU23_R", FU23_R_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_OUTPUT("SPK_L"),
+ SND_SOC_DAPM_OUTPUT("SPK_R"),
+
+ /* Port 3: Smart Mic (DMIC) Capture Path */
+ SND_SOC_DAPM_AIF_OUT("AIF3 Capture", "DP3 Mic Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_INPUT("DMIC_L"),
+ SND_SOC_DAPM_INPUT("DMIC_R"),
+ SND_SOC_DAPM_PGA("IT11", IT11_USAGE_REG, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("CS113", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("FU11_L", FU11_L_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("FU11_R", FU11_R_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("PPU11", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("XU12", XU12_BYPASS_REG, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("FU113_L", FU113_L_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("FU113_R", FU113_R_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("OT113", OT113_USAGE_REG, 0, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_widget tac_uaj_widgets[] = {
+ /* Port 4: UAJ (Headphone) Playback Path */
+ SND_SOC_DAPM_AIF_IN("AIF4 Playback", "DP4 UAJ Speaker Playback", 0,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_PGA("IT41", IT41_USAGE_REG, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("FU41_L", FU41_L_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("FU41_R", FU41_R_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("XU42", XU42_BYPASS_REG, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("CS41", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_DAC("OT45", "DP4 UAJ Speaker Playback", OT45_USAGE_REG, 0, 0),
+ SND_SOC_DAPM_OUTPUT("HP_L"),
+ SND_SOC_DAPM_OUTPUT("HP_R"),
+
+ /* Port 7: UAJ (Headset Mic) Capture Path */
+ SND_SOC_DAPM_AIF_OUT("AIF7 Capture", "DP7 UAJ Mic Capture", 0,
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_INPUT("UAJ_MIC"),
+ SND_SOC_DAPM_ADC("IT33", "DP7 UAJ Mic Capture", IT33_USAGE_REG, 0, 0),
+ SND_SOC_DAPM_PGA("FU36", FU36_MUTE_REG, 0, 1, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("CS36", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("OT36", OT36_USAGE_REG, 0, 0, NULL, 0),
+};
+
+static const struct snd_soc_dapm_route tac5xx2_common_routes[] = {
+ /* Speaker Playback Path */
+ {"FU21_L", NULL, "AIF1 Playback"},
+ {"FU21_R", NULL, "AIF1 Playback"},
+
+ {"FU23_L", NULL, "FU21_L"},
+ {"FU23_R", NULL, "FU21_R"},
+
+ {"SPK_L", NULL, "FU23_L"},
+ {"SPK_R", NULL, "FU23_R"},
+
+ /* Smart Mic DAPM Routes */
+ {"IT11", NULL, "DMIC_L"},
+ {"IT11", NULL, "DMIC_R"},
+ {"FU11_L", NULL, "IT11"},
+ {"FU11_R", NULL, "IT11"},
+ {"PPU11", NULL, "FU11_L"},
+ {"PPU11", NULL, "FU11_R"},
+ {"XU12", NULL, "PPU11"},
+ {"FU113_L", NULL, "XU12"},
+ {"FU113_R", NULL, "XU12"},
+ {"FU113_L", NULL, "CS113"},
+ {"FU113_R", NULL, "CS113"},
+ {"OT113", NULL, "FU113_L"},
+ {"OT113", NULL, "FU113_R"},
+ {"OT113", NULL, "CS113"},
+ {"AIF3 Capture", NULL, "OT113"},
+};
+
+static const struct snd_soc_dapm_route tac_uaj_routes[] = {
+ /* UAJ Playback routes */
+ {"IT41", NULL, "AIF4 Playback"},
+ {"IT41", NULL, "CS41"},
+ {"FU41_L", NULL, "IT41"},
+ {"FU41_R", NULL, "IT41"},
+ {"XU42", NULL, "FU41_L"},
+ {"XU42", NULL, "FU41_R"},
+ {"OT45", NULL, "XU42"},
+ {"OT45", NULL, "CS41"},
+ {"HP_L", NULL, "OT45"},
+ {"HP_R", NULL, "OT45"},
+
+ /* UAJ Capture routes */
+ {"IT33", NULL, "UAJ_MIC"},
+ {"IT33", NULL, "CS36"},
+ {"FU36", NULL, "IT33"},
+ {"OT36", NULL, "FU36"},
+ {"OT36", NULL, "CS36"},
+ {"AIF7 Capture", NULL, "OT36"},
+};
+
+static s32 tac_set_sdw_stream(struct snd_soc_dai *dai,
+ void *sdw_stream, s32 direction)
+{
+ if (sdw_stream)
+ snd_soc_dai_dma_data_set(dai, direction, sdw_stream);
+
+ return 0;
+}
+
+static void tac_sdw_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ snd_soc_dai_set_dma_data(dai, substream, NULL);
+}
+
+static int tac_clear_latch(struct tac5xx2_prv *priv)
+{
+ /* CLR_REG is a self-clearing bit */
+ return regmap_update_bits(priv->regmap, TAC_INT_CFG,
+ TAC_INT_CFG_CLR_REG, TAC_INT_CFG_CLR_REG);
+}
+
+static int tac_sdw_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 tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(component);
+ struct sdw_slave *sdw_peripheral = tac_dev->sdw_peripheral;
+ struct sdw_stream_runtime *sdw_stream;
+ struct sdw_stream_config stream_config = {0};
+ struct sdw_port_config port_config = {0};
+ u8 sample_rate_idx = 0;
+ int function_id;
+ int pde_entity;
+ int port_num;
+ int ret;
+
+ if (!tac_dev->hw_init) {
+ dev_err(tac_dev->dev,
+ "error: operation without hw initialization");
+ return -EINVAL;
+ }
+
+ sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
+ if (!sdw_stream) {
+ dev_err(tac_dev->dev, "failed to get dma data");
+ return -EINVAL;
+ }
+
+ ret = tac_clear_latch(tac_dev);
+ if (ret)
+ dev_warn(tac_dev->dev, "clear latch failed, err=%d", ret);
+
+ switch (dai->id) {
+ case TAC5XX2_DMIC:
+ function_id = TAC_FUNCTION_ID_SM;
+ pde_entity = TAC_SDCA_ENT_PDE11;
+ port_num = TAC_SDW_PORT_NUM_DMIC;
+ break;
+ case TAC5XX2_UAJ:
+ function_id = TAC_FUNCTION_ID_UAJ;
+ pde_entity = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ TAC_SDCA_ENT_PDE47 : TAC_SDCA_ENT_PDE34;
+ port_num = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ TAC_SDW_PORT_NUM_UAJ_PLAYBACK :
+ TAC_SDW_PORT_NUM_UAJ_CAPTURE;
+ break;
+ case TAC5XX2_SPK:
+ function_id = TAC_FUNCTION_ID_SA;
+ pde_entity = TAC_SDCA_ENT_PDE23;
+ port_num = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ TAC_SDW_PORT_NUM_SPK_PLAYBACK :
+ TAC_SDW_PORT_NUM_SPK_CAPTURE;
+ break;
+ default:
+ dev_err(tac_dev->dev, "Invalid dai id: %d for power up\n", dai->id);
+ return -EINVAL;
+ }
+
+ snd_sdw_params_to_config(substream, params, &stream_config, &port_config);
+ port_config.num = port_num;
+ ret = sdw_stream_add_slave(sdw_peripheral, &stream_config,
+ &port_config, 1, sdw_stream);
+ if (ret) {
+ dev_err(dai->dev,
+ "Unable to configure port %d: %d\n", port_num, ret);
+ return ret;
+ }
+
+ switch (params_rate(params)) {
+ case 48000:
+ sample_rate_idx = 0x01;
+ break;
+ case 44100:
+ sample_rate_idx = 0x02;
+ break;
+ case 96000:
+ sample_rate_idx = 0x03;
+ break;
+ case 88200:
+ sample_rate_idx = 0x04;
+ break;
+ default:
+ dev_dbg(tac_dev->dev, "Unsupported sample rate: %d Hz",
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ switch (function_id) {
+ case TAC_FUNCTION_ID_SM:
+ ret = regmap_write(tac_dev->regmap,
+ SDW_SDCA_CTL(function_id, TAC_SDCA_ENT_CS113,
+ TAC_SDCA_CTL_CS_SAMP_RATE_IDX, 0),
+ sample_rate_idx);
+ if (ret) {
+ dev_err(tac_dev->dev, "Failed to set CS113 sample rate: %d", ret);
+ return ret;
+ }
+
+ break;
+ case TAC_FUNCTION_ID_UAJ:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ ret = regmap_write(tac_dev->regmap,
+ SDW_SDCA_CTL(function_id, TAC_SDCA_ENT_CS41,
+ TAC_SDCA_CTL_CS_SAMP_RATE_IDX, 0),
+ sample_rate_idx);
+ if (ret) {
+ dev_err(tac_dev->dev, "Failed to set CS41 sample rate: %d", ret);
+ return ret;
+ }
+ } else {
+ ret = regmap_write(tac_dev->regmap,
+ SDW_SDCA_CTL(function_id, TAC_SDCA_ENT_CS36,
+ TAC_SDCA_CTL_CS_SAMP_RATE_IDX, 0),
+ sample_rate_idx);
+ if (ret) {
+ dev_err(tac_dev->dev, "Failed to set CS36 sample rate: %d", ret);
+ return ret;
+ }
+ }
+ break;
+ case TAC_FUNCTION_ID_SA:
+ /* SmartAmp: no additional sample rate configuration needed */
+ break;
+ }
+
+ ret = regmap_write(tac_dev->regmap, SDW_SDCA_CTL(function_id, pde_entity,
+ TAC_SDCA_REQUESTED_PS, 0), 0);
+ if (ret) {
+ dev_err(tac_dev->dev,
+ "failed to set func %d, entity %d's requested PS to 0: %d\n",
+ function_id, pde_entity, ret);
+ return ret;
+ }
+
+ ret = sdca_asoc_pde_poll_actual_ps(tac_dev->dev, tac_dev->regmap, function_id, pde_entity,
+ SDCA_PDE_PS3, SDCA_PDE_PS0, NULL, 0);
+ if (ret)
+ dev_err(tac_dev->dev, "failed to transition func %d, pde %d from PS3 -> PS0, err=%d\n",
+ function_id, pde_entity, ret);
+ return ret;
+}
+
+static int tac_sdw_pcm_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct sdw_stream_runtime *sdw_stream = snd_soc_dai_get_dma_data(dai, substream);
+ struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(dai->component);
+ int pde_entity, function_id;
+ int ret;
+
+ sdw_stream_remove_slave(tac_dev->sdw_peripheral, sdw_stream);
+
+ switch (dai->id) {
+ case TAC5XX2_DMIC:
+ pde_entity = TAC_SDCA_ENT_PDE11;
+ function_id = TAC_FUNCTION_ID_SM;
+ break;
+ case TAC5XX2_UAJ:
+ function_id = TAC_FUNCTION_ID_UAJ;
+ pde_entity = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ TAC_SDCA_ENT_PDE47 : TAC_SDCA_ENT_PDE34;
+ break;
+ case TAC5XX2_SPK:
+ function_id = TAC_FUNCTION_ID_SA;
+ pde_entity = TAC_SDCA_ENT_PDE23;
+ break;
+ default:
+ dev_err(tac_dev->dev, "unhandled dai %d for power down\n", dai->id);
+ return -EINVAL;
+ }
+
+ ret = regmap_write(tac_dev->regmap, SDW_SDCA_CTL(function_id, pde_entity,
+ TAC_SDCA_REQUESTED_PS, 0),
+ SDCA_PDE_PS3);
+ if (ret) {
+ dev_err(tac_dev->dev,
+ "failed to set func %d, entity %d's requested PS to 3: %d\n",
+ function_id, pde_entity, ret);
+ return ret;
+ }
+
+ ret = sdca_asoc_pde_poll_actual_ps(tac_dev->dev, tac_dev->regmap, function_id,
+ pde_entity, SDCA_PDE_PS0, SDCA_PDE_PS3,
+ NULL, 0);
+ if (ret)
+ dev_err(tac_dev->dev,
+ "failed to transition func %d, pde %d from PS0 -> PS3, err=%d\n",
+ function_id, pde_entity, ret);
+
+ return ret;
+}
+
+static const struct snd_soc_dai_ops tac_dai_ops = {
+ .hw_params = tac_sdw_hw_params,
+ .hw_free = tac_sdw_pcm_hw_free,
+ .set_stream = tac_set_sdw_stream,
+ .shutdown = tac_sdw_shutdown,
+};
+
+static int tac5xx2_sdca_btn_type(unsigned char *buffer, struct tac5xx2_prv *tac_dev)
+{
+ switch (*buffer) {
+ case 1: /* play pause */
+ return SND_JACK_BTN_0;
+ case 10: /* vol down */
+ return SND_JACK_BTN_3;
+ case 8: /* vol up */
+ return SND_JACK_BTN_2;
+ case 4: /* long press */
+ return SND_JACK_BTN_1;
+ case 2: /* next song */
+ case 32: /* next song */
+ return SND_JACK_BTN_4;
+ default:
+ return 0;
+ }
+}
+
+static int tac5xx2_sdca_button_detect(struct tac5xx2_prv *tac_dev)
+{
+ unsigned int btn_type, offset, idx;
+ int ret, value, owner;
+ u8 buf[2];
+
+ ret = regmap_read(tac_dev->regmap,
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
+ TAC_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), &owner);
+ if (ret) {
+ dev_err(tac_dev->dev,
+ "Failed to read current UMP message owner 0x%x", ret);
+ return ret;
+ }
+
+ if (owner == SDCA_UMP_OWNER_DEVICE) {
+ dev_dbg(tac_dev->dev, "skip button detect as current owner is not host\n");
+ return 0;
+ }
+
+ ret = regmap_read(tac_dev->regmap,
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
+ TAC_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), &offset);
+ if (ret) {
+ dev_err(tac_dev->dev,
+ "Failed to read current UMP message offset: %d", ret);
+ goto end_btn_det;
+ }
+
+ dev_dbg(tac_dev->dev, "button detect: message offset = %x", offset);
+
+ for (idx = 0; idx < sizeof(buf); idx++) {
+ ret = regmap_read(tac_dev->regmap,
+ TAC_BUF_ADDR_HID1 + offset + idx, &value);
+ if (ret) {
+ dev_err(tac_dev->dev,
+ "Failed to read HID buffer: %d", ret);
+ goto end_btn_det;
+ }
+ buf[idx] = value & 0xff;
+ }
+
+ if (buf[0] == 0x1) {
+ btn_type = tac5xx2_sdca_btn_type(&buf[1], tac_dev);
+ ret = btn_type;
+ }
+
+end_btn_det:
+ regmap_write(tac_dev->regmap,
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_HID, TAC_SDCA_ENT_HID1,
+ TAC_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), 0x01);
+
+ return ret;
+}
+
+static int tac5xx2_sdca_headset_detect(struct tac5xx2_prv *tac_dev)
+{
+ int val, ret;
+
+ ret = regmap_read(tac_dev->regmap,
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_GE35,
+ TAC_SDCA_CTL_DET_MODE, 0), &val);
+ if (ret) {
+ dev_err(tac_dev->dev, "Failed to read the detect mode");
+ return ret;
+ }
+
+ switch (val) {
+ case 4:
+ tac_dev->jack_type = SND_JACK_MICROPHONE;
+ break;
+ case 5:
+ tac_dev->jack_type = SND_JACK_HEADPHONE;
+ break;
+ case 6:
+ tac_dev->jack_type = SND_JACK_HEADSET;
+ break;
+ case 0:
+ default:
+ tac_dev->jack_type = 0;
+ break;
+ }
+
+ ret = regmap_write(tac_dev->regmap,
+ SDW_SDCA_CTL(TAC_FUNCTION_ID_UAJ, TAC_SDCA_ENT_GE35,
+ TAC_SDCA_CTL_SEL_MODE, 0), val);
+ if (ret)
+ dev_err(tac_dev->dev, "Failed to update the jack type to device");
+
+ return 0;
+}
+
+static int tac5xx2_jack_init(struct tac5xx2_prv *tac_dev)
+{
+ int ret = 0;
+
+ if (!tac_dev->hs_jack)
+ goto disable_interrupts;
+
+ ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK2,
+ SDW_SCP_SDCA_INTMASK_SDCA_11);
+ if (ret) {
+ dev_err(tac_dev->dev,
+ "Failed to register jack detection interrupt: %d\n", ret);
+ goto disable_interrupts;
+ }
+
+ ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK3,
+ SDW_SCP_SDCA_INTMASK_SDCA_16);
+ if (ret) {
+ dev_err(tac_dev->dev,
+ "Failed to register for button detect interrupt: %d\n", ret);
+ goto disable_interrupts;
+ }
+
+ return 0;
+
+disable_interrupts:
+ /* ignore errors while disabling interrupts */
+ regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK2, 0);
+ regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INTMASK3, 0);
+
+ return ret;
+}
+
+static int tac5xx2_set_jack(struct snd_soc_component *component,
+ struct snd_soc_jack *hs_jack, void *data)
+{
+ struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ tac_dev->hs_jack = hs_jack;
+
+ /* resume can happen only after first hw_init */
+ if (!tac_dev->first_hw_init_done)
+ return 0;
+
+ ret = pm_runtime_resume_and_get(component->dev);
+ if (ret < 0) {
+ if (ret != -EACCES) {
+ dev_err(component->dev,
+ "%s: failed to resume %d\n", __func__, ret);
+ return ret;
+ }
+
+ /* pm_runtime not enabled yet */
+ dev_dbg(component->dev,
+ "%s: skipping jack init for now\n", __func__);
+ return 0;
+ }
+
+ ret = tac5xx2_jack_init(tac_dev);
+ if (ret)
+ dev_err(tac_dev->dev, "jack init failed, err=%d\n", ret);
+
+ pm_runtime_mark_last_busy(component->dev);
+ pm_runtime_put_autosuspend(component->dev);
+
+ return ret;
+}
+
+static int tac_interrupt_callback(struct sdw_slave *slave,
+ struct sdw_slave_intr_status *status)
+{
+ unsigned int sdca_int2, sdca_int3, jack_report_mask = 0;
+ struct tac5xx2_prv *tac_dev = dev_get_drvdata(&slave->dev);
+ struct device *dev = &slave->dev;
+ int btn_type = 0;
+ int ret = 0;
+
+ if (status->control_port) {
+ if (status->control_port & SDW_SCP_INT1_PARITY)
+ dev_warn(dev, "SCP: Parity error interrupt");
+ if (status->control_port & SDW_SCP_INT1_BUS_CLASH)
+ dev_warn(dev, "SCP: Bus clash interrupt");
+ }
+
+ if (!tac_has_uaj_support(tac_dev))
+ return 0;
+
+ ret = regmap_read(tac_dev->regmap, SDW_SCP_SDCA_INT2, &sdca_int2);
+ if (ret) {
+ dev_err(dev, "Failed to read UAJ Interrupt, reg:%#x err=%d\n",
+ SDW_SCP_SDCA_INT2, ret);
+ return ret;
+ }
+
+ ret = regmap_read(tac_dev->regmap, SDW_SCP_SDCA_INT3, &sdca_int3);
+ if (ret) {
+ dev_err(dev, "Failed to read HID interrupt reg=%#x: err=%d",
+ SDW_SCP_SDCA_INT3, ret);
+ return ret;
+ }
+
+ dev_dbg(dev, "SDCA_INT2: 0x%02x, SDCA_INT3: 0x%02x\n",
+ sdca_int2, sdca_int3);
+
+ if (sdca_int2 & SDW_SCP_SDCA_INT_SDCA_11) {
+ ret = tac5xx2_sdca_headset_detect(tac_dev);
+ if (ret < 0)
+ goto clear;
+ jack_report_mask |= SND_JACK_HEADSET;
+ }
+
+ if (sdca_int3 & SDW_SCP_SDCA_INT_SDCA_16) {
+ btn_type = tac5xx2_sdca_button_detect(tac_dev);
+ if (btn_type < 0)
+ btn_type = 0;
+ jack_report_mask |= SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 | SND_JACK_BTN_4;
+ }
+
+ if (tac_dev->jack_type == 0)
+ btn_type = 0;
+
+ dev_dbg(tac_dev->dev, "in %s, jack_type=%d\n", __func__, tac_dev->jack_type);
+ dev_dbg(tac_dev->dev, "in %s, btn_type=0x%x\n", __func__, btn_type);
+
+ if (!tac_dev->hs_jack)
+ goto clear;
+
+ snd_soc_jack_report(tac_dev->hs_jack, tac_dev->jack_type | btn_type,
+ jack_report_mask);
+
+clear:
+ if (sdca_int2) {
+ ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INT2, sdca_int2);
+ if (ret)
+ dev_dbg(tac_dev->dev, "Failed to clear jack interrupt\n");
+ }
+
+ if (sdca_int3) {
+ ret = regmap_write(tac_dev->regmap, SDW_SCP_SDCA_INT3, sdca_int3);
+ if (ret)
+ dev_dbg(tac_dev->dev, "failed to clear hid interrupt\n");
+ }
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver tac5572_dai_driver[] = {
+ {
+ .name = "tac5xx2-aif1",
+ .id = TAC5XX2_SPK,
+ .playback = {
+ .stream_name = "DP1 Speaker Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ },
+ {
+ .name = "tac5xx2-aif2",
+ .id = TAC5XX2_DMIC,
+ .capture = {
+ .stream_name = "DP3 Mic Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ },
+ {
+ .name = "tac5xx2-aif3",
+ .id = TAC5XX2_UAJ,
+ .playback = {
+ .stream_name = "DP4 UAJ Speaker Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "DP7 UAJ Mic Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ },
+};
+
+static struct snd_soc_dai_driver tac5672_dai_driver[] = {
+ {
+ .name = "tac5xx2-aif1",
+ .id = TAC5XX2_SPK,
+ .playback = {
+ .stream_name = "DP1 Speaker Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "DP8 IV Sense Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ .symmetric_rate = 1,
+ },
+ {
+ .name = "tac5xx2-aif2",
+ .id = TAC5XX2_DMIC,
+ .capture = {
+ .stream_name = "DP3 Mic Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ },
+ {
+ .name = "tac5xx2-aif3",
+ .id = TAC5XX2_UAJ,
+ .playback = {
+ .stream_name = "DP4 UAJ Speaker Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "DP7 UAJ Mic Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ },
+};
+
+static struct snd_soc_dai_driver tac5682_dai_driver[] = {
+ {
+ .name = "tac5xx2-aif1",
+ .id = TAC5XX2_SPK,
+ .playback = {
+ .stream_name = "DP1 Speaker Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "DP2 Echo Reference Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ .symmetric_rate = 1,
+ },
+ {
+ .name = "tac5xx2-aif2",
+ .id = TAC5XX2_DMIC,
+ .capture = {
+ .stream_name = "DP3 Mic Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ },
+ {
+ .name = "tac5xx2-aif3",
+ .id = TAC5XX2_UAJ,
+ .playback = {
+ .stream_name = "DP4 UAJ Speaker Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .capture = {
+ .stream_name = "DP7 UAJ Mic Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ },
+};
+
+static struct snd_soc_dai_driver tas2883_dai_driver[] = {
+ {
+ .name = "tac5xx2-aif1",
+ .id = TAC5XX2_SPK,
+ .playback = {
+ .stream_name = "DP1 Speaker Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ .symmetric_rate = 1,
+ },
+ {
+ .name = "tac5xx2-aif2",
+ .id = TAC5XX2_DMIC,
+ .capture = {
+ .stream_name = "DP3 Mic Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = TAC5XX2_DEVICE_RATES,
+ .formats = TAC5XX2_DEVICE_FORMATS,
+ },
+ .ops = &tac_dai_ops,
+ },
+};
+
+static s32 tac_component_probe(struct snd_soc_component *component)
+{
+ struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ ret = pm_runtime_resume(component->dev);
+ if (ret < 0 && ret != -EACCES)
+ return ret;
+
+ if (!tac_has_uaj_support(tac_dev))
+ goto done_comp_probe;
+
+ ret = snd_soc_dapm_new_controls(snd_soc_component_to_dapm(component),
+ tac_uaj_widgets,
+ ARRAY_SIZE(tac_uaj_widgets));
+ if (ret) {
+ dev_err(component->dev, "Failed to add UAJ widgets: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dapm_add_routes(snd_soc_component_to_dapm(component),
+ tac_uaj_routes, ARRAY_SIZE(tac_uaj_routes));
+ if (ret) {
+ dev_err(component->dev, "Failed to add UAJ routes: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_add_component_controls(component, tac_uaj_controls,
+ ARRAY_SIZE(tac_uaj_controls));
+ if (ret) {
+ dev_err(component->dev, "Failed to add UAJ controls: %d\n", ret);
+ return ret;
+ }
+
+done_comp_probe:
+ tac_dev->component = component;
+ return 0;
+}
+
+static void tac_component_remove(struct snd_soc_component *codec)
+{
+ struct tac5xx2_prv *tac_dev = snd_soc_component_get_drvdata(codec);
+
+ tac_dev->component = NULL;
+}
+
+static const struct snd_soc_component_driver soc_codec_driver_tacdevice = {
+ .probe = tac_component_probe,
+ .remove = tac_component_remove,
+ .controls = tac5xx2_snd_controls,
+ .num_controls = ARRAY_SIZE(tac5xx2_snd_controls),
+ .dapm_widgets = tac5xx2_common_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tac5xx2_common_widgets),
+ .dapm_routes = tac5xx2_common_routes,
+ .num_dapm_routes = ARRAY_SIZE(tac5xx2_common_routes),
+ .idle_bias_on = 0,
+ .endianness = 1,
+};
+
+static s32 tac_init(struct tac5xx2_prv *tac_dev)
+{
+ struct snd_soc_component_driver *component_driver;
+ struct snd_soc_dai_driver *dai_drv;
+ int num_dais;
+ s32 ret;
+
+ dev_set_drvdata(tac_dev->dev, tac_dev);
+
+ switch (tac_dev->part_id) {
+ case 0x5572:
+ dai_drv = tac5572_dai_driver;
+ num_dais = ARRAY_SIZE(tac5572_dai_driver);
+ break;
+ case 0x5672:
+ dai_drv = tac5672_dai_driver;
+ num_dais = ARRAY_SIZE(tac5672_dai_driver);
+ break;
+ case 0x5682:
+ dai_drv = tac5682_dai_driver;
+ num_dais = ARRAY_SIZE(tac5682_dai_driver);
+ break;
+ case 0x2883:
+ dai_drv = tas2883_dai_driver;
+ num_dais = ARRAY_SIZE(tas2883_dai_driver);
+ break;
+ default:
+ dev_err(tac_dev->dev, "Unsupported device: 0x%x\n",
+ tac_dev->part_id);
+ return -EINVAL;
+ }
+
+ component_driver = devm_kzalloc(tac_dev->dev, sizeof(*component_driver),
+ GFP_KERNEL);
+ if (!component_driver)
+ return -ENOMEM;
+
+ memcpy(component_driver, &soc_codec_driver_tacdevice, sizeof(*component_driver));
+ if (tac_has_uaj_support(tac_dev))
+ component_driver->set_jack = tac5xx2_set_jack;
+
+ ret = devm_snd_soc_register_component(tac_dev->dev, component_driver,
+ dai_drv, num_dais);
+ if (ret) {
+ dev_err(tac_dev->dev, "%s: codec register error:%d.\n",
+ __func__, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static s32 tac5xx2_sdca_dev_suspend(struct device *dev)
+{
+ struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev);
+
+ if (!tac_dev->hw_init)
+ return 0;
+
+ regcache_cache_only(tac_dev->regmap, true);
+ return 0;
+}
+
+static s32 tac5xx2_sdca_dev_system_suspend(struct device *dev)
+{
+ return tac5xx2_sdca_dev_suspend(dev);
+}
+
+static s32 tac5xx2_sdca_dev_resume(struct device *dev)
+{
+ struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev);
+ struct sdw_slave *slave = dev_to_sdw_dev(dev);
+ int ret;
+
+ if (!tac_dev->first_hw_init_done) {
+ dev_dbg(dev, "Device not initialized yet, skipping resume sync\n");
+ return 0;
+ }
+
+ ret = sdw_slave_wait_for_init(slave, TAC5XX2_PROBE_TIMEOUT_MS);
+ if (ret) {
+ sdw_show_ping_status(slave->bus, true);
+ return ret;
+ }
+
+ regcache_cache_only(tac_dev->regmap, false);
+ regcache_mark_dirty(tac_dev->regmap);
+ ret = regcache_sync(tac_dev->regmap);
+ if (ret < 0)
+ dev_warn(dev, "Failed to sync regcache: %d\n", ret);
+
+ /* Detect and set jack type for UAJ path before playback.
+ * This is required as jack detection does not trigger interrupt
+ * when device is in runtime_pm suspend with bus in clock stop mode.
+ */
+ if (tac_has_uaj_support(tac_dev))
+ tac5xx2_sdca_headset_detect(tac_dev);
+
+ return 0;
+}
+
+static const struct dev_pm_ops tac5xx2_sdca_pm = {
+ SYSTEM_SLEEP_PM_OPS(tac5xx2_sdca_dev_system_suspend, tac5xx2_sdca_dev_resume)
+ RUNTIME_PM_OPS(tac5xx2_sdca_dev_suspend, tac5xx2_sdca_dev_resume, NULL)
+};
+
+static s32 tac_fw_read_hdr(const u8 *data, struct tac_fw_hdr *hdr)
+{
+ hdr->size = get_unaligned_le32(data);
+ hdr->version_offset = get_unaligned_le32(data + 4);
+ hdr->plt_id = get_unaligned_le32(data + 8);
+ hdr->ppc3_ver = get_unaligned_le32(data + 12);
+ memcpy(hdr->ddc_name, data + 16, 64);
+ hdr->ddc_name[63] = 0;
+ hdr->timestamp = get_unaligned_le64(data + 80);
+
+ return TAC_FW_HDR_SIZE;
+}
+
+static s32 tac_fw_get_next_file(const u8 *data, size_t data_size, struct tac_fw_file *file)
+{
+ u32 file_length;
+
+ /* Validate file header size */
+ if (data_size < TAC_FW_FILE_HDR)
+ return -EINVAL;
+
+ file->vendor_id = get_unaligned_le32(&data[0]);
+ file->file_id = get_unaligned_le32(&data[4]);
+ file->version = get_unaligned_le32(&data[8]);
+ file->length = get_unaligned_le32(&data[12]);
+ file->dest_addr = get_unaligned_le32(&data[16]);
+ file_length = file->length;
+
+ /* Validate file payload exists */
+ if (data_size < TAC_FW_FILE_HDR + file_length)
+ return -EINVAL;
+
+ file->fw_data = (u8 *)&data[20];
+
+ return file_length + sizeof(u32) * 5;
+}
+
+static void tac5xx2_fw_ready(const struct firmware *fmw, void *context)
+{
+ struct tac5xx2_prv *tac_dev = context;
+ struct tac_fw_file *files;
+ u32 fw_hdr_size;
+ u32 num_files = 0;
+ struct tac_fw_hdr hdr;
+ struct tm tm_time;
+ size_t img_sz;
+ u32 offset;
+ s32 ret = 0;
+ u8 *buf;
+
+ if (!fmw || !fmw->data || fmw->size == 0 || fmw->size < TAC_FW_HDR_SIZE + TAC_FW_FILE_HDR) {
+ dev_err(tac_dev->dev, "fw file: %s is empty or invalid\n",
+ tac_dev->fw_binaryname);
+ goto out;
+ }
+
+ /* Verify firmware size from header */
+ fw_hdr_size = get_unaligned_le32(fmw->data);
+ if (fw_hdr_size != fmw->size) {
+ dev_err(tac_dev->dev, "firmware size mismatch: hdr=%u, actual=%zu\n",
+ fw_hdr_size, fmw->size);
+ goto out;
+ }
+
+ files = devm_kzalloc(tac_dev->dev, sizeof(*files) * TAC_MAX_FW_CHUNKS, GFP_KERNEL);
+ buf = devm_kmemdup(tac_dev->dev, fmw->data, fmw->size, GFP_KERNEL);
+ if (!files || !buf)
+ goto out;
+
+ /* validate the cache the firmware */
+ img_sz = fmw->size;
+ offset = tac_fw_read_hdr(buf, &hdr);
+ while (offset < img_sz && num_files < TAC_MAX_FW_CHUNKS) {
+ u32 file_length;
+
+ if (offset + TAC_FW_FILE_HDR > img_sz) {
+ dev_warn(tac_dev->dev, "Incomplete block header at offset %d\n",
+ offset);
+ goto out;
+ }
+ /* Validate that the file payload doesn't exceed buffer */
+ file_length = get_unaligned_le32(&buf[offset + 12]);
+ /* Check for integer overflow and buffer bounds */
+ if (file_length > img_sz || offset > img_sz - TAC_FW_FILE_HDR ||
+ file_length > img_sz - offset - TAC_FW_FILE_HDR) {
+ dev_warn(tac_dev->dev, "File at offset %d exceeds buffer: length=%u, available=%zu\n",
+ offset, file_length, img_sz - offset - TAC_FW_FILE_HDR);
+ goto out;
+ }
+ ret = tac_fw_get_next_file(&buf[offset], img_sz - offset, &files[num_files]);
+ if (ret < 0) {
+ dev_err(tac_dev->dev, "Failed to parse file at offset %d\n", offset);
+ goto out;
+ }
+ offset += ret;
+ num_files++;
+ }
+
+ if (num_files == 0) {
+ dev_err(tac_dev->dev, "firmware with no files\n");
+ goto out;
+ }
+
+ /* cache ready to use validated firmware */
+ tac_dev->fw_file_cnt = num_files;
+ tac_dev->fw_files = files;
+
+ time64_to_tm(hdr.timestamp, 0, &tm_time);
+ dev_dbg(tac_dev->dev, "fw file: %s, num_files=%u, ts:%04ld-%02d-%02d %02d:%02d\n",
+ tac_dev->fw_binaryname, tac_dev->fw_file_cnt,
+ tm_time.tm_year + 1900, tm_time.tm_mon + 1, tm_time.tm_mday,
+ tm_time.tm_hour, tm_time.tm_min);
+ dev_dbg(tac_dev->dev, "fw file: DDC Name: %s\n", hdr.ddc_name);
+ dev_dbg(tac_dev->dev, "fw file: PPC3 Version: 3.%ld.%ld.%ld\n",
+ FIELD_GET(GENMASK(31, 24), hdr.ppc3_ver),
+ FIELD_GET(GENMASK(23, 16), hdr.ppc3_ver),
+ FIELD_GET(GENMASK(15, 8), hdr.ppc3_ver) & 0x3f);
+
+out:
+ complete_all(&tac_dev->fw_caching_complete);
+ if (fmw)
+ release_firmware(fmw);
+}
+
+static int tac_load_and_cache_firmware_async(struct tac5xx2_prv *tac_dev)
+{
+ tac_dev->fw_file_cnt = 0;
+ tac_dev->fw_files = NULL; /* ready to download files */
+
+ return request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
+ tac_dev->fw_binaryname, tac_dev->dev,
+ GFP_KERNEL, tac_dev, tac5xx2_fw_ready);
+}
+
+static int tac_download(struct tac5xx2_prv *tac_dev)
+{
+ struct tac_fw_file *files = tac_dev->fw_files;
+ u32 num_files = tac_dev->fw_file_cnt;
+ u32 i;
+ int ret = 0;
+
+ for (i = 0; i < num_files; i++) {
+ ret = sdw_nwrite_no_pm(tac_dev->sdw_peripheral, files[i].dest_addr,
+ files[i].length, files[i].fw_data);
+ if (ret < 0) {
+ dev_dbg(tac_dev->dev,
+ "FW write failed at addr 0x%x: %d\n",
+ files[i].dest_addr, ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+/*
+ * tac5xx2 uses custom firmware binary fw.
+ * This is not using UMP File Download.
+ */
+static s32 tac_download_fw_to_hw(struct tac5xx2_prv *tac_dev)
+{
+ int ret;
+
+ ret = tac_download(tac_dev);
+ if (ret < 0) {
+ dev_err(tac_dev->dev, "Firmware download failed: %d\n", ret);
+ return ret;
+ }
+
+ dev_dbg(tac_dev->dev, "Firmware download complete: %d chunks\n",
+ tac_dev->fw_file_cnt);
+ tac_dev->fw_dl_success = true;
+
+ return 0;
+}
+
+static struct pci_dev *tac_get_pci_dev(struct sdw_slave *peripheral)
+{
+ struct device *dev = &peripheral->dev;
+
+ for (; dev; dev = dev->parent) {
+ if (dev_is_pci(dev))
+ return to_pci_dev(dev);
+ }
+
+ return NULL;
+}
+
+static void tac_generate_fw_name(struct sdw_slave *slave, char *name, size_t size)
+{
+ struct sdw_bus *bus = slave->bus;
+ u16 part_id = slave->id.part_id;
+ u8 unique_id = slave->id.unique_id;
+ struct pci_dev *pci = tac_get_pci_dev(slave);
+
+ if (pci)
+ scnprintf(name, size, "%04X-%04X-%1X-%1X.bin", part_id,
+ pci->subsystem_device, bus->link_id, unique_id);
+ else
+ /* Default firmware name based on part ID */
+ scnprintf(name, size, "%s%04x-%1X-%1X.bin",
+ part_id == 0x2883 ? "tas" : "tac",
+ part_id, bus->link_id, unique_id);
+}
+
+static int tac_io_init(struct device *dev, struct sdw_slave *slave, bool first)
+{
+ struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev);
+ u64 time;
+ int ret;
+
+ if (tac_dev->hw_init) {
+ dev_dbg(dev, "early return hw_init already done..");
+ return 0;
+ }
+
+ time = wait_for_completion_timeout(&tac_dev->fw_caching_complete,
+ msecs_to_jiffies(TAC5XX2_FW_CACHE_TIMEOUT_MS));
+ if (!time) {
+ ret = -ETIMEDOUT;
+ dev_warn(tac_dev->dev, "%s: fw caching timeout\n", __func__);
+ goto io_init_err;
+ }
+
+ if (tac_dev->fw_files && tac_dev->fw_file_cnt > 0) {
+ ret = tac_download_fw_to_hw(tac_dev);
+ if (ret) {
+ dev_err(tac_dev->dev, "FW download failed, fw: %d\n", ret);
+ goto io_init_err;
+ }
+ }
+
+ if (tac_dev->sa_func_data) {
+ ret = sdca_regmap_write_init(dev, tac_dev->regmap,
+ tac_dev->sa_func_data);
+ if (ret) {
+ dev_err(dev, "smartamp init table update failed\n");
+ goto io_init_err;
+ }
+ dev_dbg(dev, "smartamp init done\n");
+
+ if (first) {
+ ret = regmap_multi_reg_write(tac_dev->regmap, tac_spk_seq,
+ ARRAY_SIZE(tac_spk_seq));
+ if (ret) {
+ dev_err(dev, "init writes failed, err=%d", ret);
+ goto io_init_err;
+ }
+ }
+ }
+
+ if (tac_dev->sm_func_data) {
+ ret = sdca_regmap_write_init(dev, tac_dev->regmap,
+ tac_dev->sm_func_data);
+ if (ret) {
+ dev_err(dev, "smartmic init table update failed\n");
+ goto io_init_err;
+ }
+ dev_dbg(dev, "smartmic init done\n");
+
+ if (first) {
+ ret = regmap_multi_reg_write(tac_dev->regmap, tac_sm_seq,
+ ARRAY_SIZE(tac_sm_seq));
+ if (ret) {
+ dev_err(tac_dev->dev,
+ "init writes failed, err=%d", ret);
+ goto io_init_err;
+ }
+ }
+ }
+
+ if (tac_dev->uaj_func_data) {
+ ret = sdca_regmap_write_init(dev, tac_dev->regmap,
+ tac_dev->uaj_func_data);
+ if (ret) {
+ dev_err(dev, "uaj init table update failed\n");
+ goto io_init_err;
+ }
+ dev_dbg(dev, "uaj init done\n");
+
+ if (first) {
+ ret = regmap_multi_reg_write(tac_dev->regmap, tac_uaj_seq,
+ ARRAY_SIZE(tac_uaj_seq));
+ if (ret) {
+ dev_err(tac_dev->dev,
+ "init writes failed, err=%d", ret);
+ goto io_init_err;
+ }
+
+ if (tac_dev->hs_jack) {
+ ret = tac5xx2_jack_init(tac_dev);
+ if (ret) {
+ dev_err(tac_dev->dev, "jack init failed");
+ goto io_init_err;
+ }
+ }
+ }
+ }
+
+ if (tac_dev->hid_func_data) {
+ ret = sdca_regmap_write_init(dev, tac_dev->regmap,
+ tac_dev->hid_func_data);
+ if (ret) {
+ dev_err(dev, "hid init table update failed\n");
+ goto io_init_err;
+ }
+ dev_dbg(dev, "hid init done\n");
+ }
+
+ tac_dev->hw_init = true;
+
+ return 0;
+
+io_init_err:
+ dev_err(dev, "init writes failed, err=%d", ret);
+ return ret;
+}
+
+static int tac_update_status(struct sdw_slave *slave,
+ enum sdw_slave_status status)
+{
+ struct tac5xx2_prv *tac_dev = dev_get_drvdata(&slave->dev);
+ struct device *dev = &slave->dev;
+ bool first = false;
+ int ret;
+
+ tac_dev->status = status;
+ if (status == SDW_SLAVE_UNATTACHED) {
+ tac_dev->hw_init = false;
+ tac_dev->fw_dl_success = false;
+ }
+
+ if (tac_dev->hw_init || tac_dev->status != SDW_SLAVE_ATTACHED) {
+ dev_dbg(dev, "%s: early return, hw_init=%d, status=%d",
+ __func__, tac_dev->hw_init, tac_dev->status);
+ return 0;
+ }
+
+ if (!tac_dev->first_hw_init_done) {
+ pm_runtime_set_active(tac_dev->dev);
+ tac_dev->first_hw_init_done = true;
+ first = true;
+ }
+
+ pm_runtime_get_noresume(tac_dev->dev);
+
+ regcache_mark_dirty(tac_dev->regmap);
+ regcache_cache_only(tac_dev->regmap, false);
+ ret = tac_io_init(&slave->dev, slave, first);
+ if (ret) {
+ dev_err(dev, "Device initialization failed: %d\n", ret);
+ goto err_out;
+ }
+
+ ret = regcache_sync(tac_dev->regmap);
+ if (ret)
+ dev_warn(dev, "Failed to sync regcache after init: %d\n", ret);
+
+err_out:
+ pm_runtime_mark_last_busy(tac_dev->dev);
+ pm_runtime_put_autosuspend(tac_dev->dev);
+
+ return ret;
+}
+
+static int tac5xx2_sdw_read_prop(struct sdw_slave *peripheral)
+{
+ struct device *dev = &peripheral->dev;
+ int ret;
+
+ ret = sdw_slave_read_prop(peripheral);
+ if (ret) {
+ dev_err(dev, "sdw_slave_read_prop failed: %d", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int tac_port_prep(struct sdw_slave *slave, struct sdw_prepare_ch *prep_ch,
+ enum sdw_port_prep_ops pre_ops)
+{
+ struct device *dev = &slave->dev;
+ struct tac5xx2_prv *tac_dev = dev_get_drvdata(dev);
+ unsigned int val;
+ int ret;
+
+ if (pre_ops != SDW_OPS_PORT_POST_PREP)
+ return 0;
+
+ if (!tac_dev->fw_dl_success)
+ return 0;
+
+ ret = regmap_read(tac_dev->regmap, TAC_DSP_ALGO_STATUS, &val);
+ if (ret) {
+ dev_err(dev, "Failed to read algo status: %d\n", ret);
+ return ret;
+ }
+
+ if (val != TAC_DSP_ALGO_STATUS_RUNNING) {
+ dev_dbg(dev, "Algo not running (0x%02x), re-enabling\n", val);
+ ret = regmap_write(tac_dev->regmap, TAC_DSP_ALGO_STATUS,
+ TAC_DSP_ALGO_STATUS_RUNNING);
+ if (ret) {
+ dev_err(dev, "Failed to re-enable algo: %d\n", ret);
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static const struct sdw_slave_ops tac_sdw_ops = {
+ .read_prop = tac5xx2_sdw_read_prop,
+ .update_status = tac_update_status,
+ .interrupt_callback = tac_interrupt_callback,
+ .port_prep = tac_port_prep,
+};
+
+static s32 tac_sdw_probe(struct sdw_slave *peripheral,
+ const struct sdw_device_id *id)
+{
+ struct sdca_function_data *function_data = NULL;
+ struct device *dev = &peripheral->dev;
+ struct tac5xx2_prv *tac_dev;
+ struct regmap *regmap;
+ int ret, i;
+
+ tac_dev = devm_kzalloc(dev, sizeof(*tac_dev), GFP_KERNEL);
+ if (!tac_dev)
+ return dev_err_probe(dev, -ENOMEM,
+ "Failed devm_kzalloc");
+
+ if (peripheral->sdca_data.num_functions > 0) {
+ dev_dbg(dev, "SDCA functions found: %d",
+ peripheral->sdca_data.num_functions);
+
+ for (i = 0; i < peripheral->sdca_data.num_functions; i++) {
+ struct sdca_function_data **func_ptr;
+ const char *func_name;
+
+ switch (peripheral->sdca_data.function[i].type) {
+ case SDCA_FUNCTION_TYPE_SMART_AMP:
+ func_ptr = &tac_dev->sa_func_data;
+ func_name = "smartamp";
+ break;
+ case SDCA_FUNCTION_TYPE_SMART_MIC:
+ func_ptr = &tac_dev->sm_func_data;
+ func_name = "smartmic";
+ break;
+ case SDCA_FUNCTION_TYPE_UAJ:
+ func_ptr = &tac_dev->uaj_func_data;
+ func_name = "uaj";
+ break;
+ case SDCA_FUNCTION_TYPE_HID:
+ func_ptr = &tac_dev->hid_func_data;
+ func_name = "hid";
+ break;
+ default:
+ continue;
+ }
+
+ function_data = devm_kzalloc(dev, sizeof(*function_data),
+ GFP_KERNEL);
+ if (!function_data)
+ return dev_err_probe(dev, -ENOMEM,
+ "failed to allocate %s function data",
+ func_name);
+ function_data->desc = &peripheral->sdca_data.function[i];
+ ret = sdca_parse_function(dev, peripheral, function_data);
+ if (!ret)
+ *func_ptr = function_data;
+ else
+ devm_kfree(dev, function_data);
+ }
+ }
+
+ dev_dbg(dev, "SDCA functions enabled: SA=%s SM=%s UAJ=%s HID=%s",
+ tac_dev->sa_func_data ? "yes" : "no",
+ tac_dev->sm_func_data ? "yes" : "no",
+ tac_dev->uaj_func_data ? "yes" : "no",
+ tac_dev->hid_func_data ? "yes" : "no");
+
+ tac_dev->dev = dev;
+ tac_dev->sdw_peripheral = peripheral;
+ tac_dev->hw_init = false;
+ tac_dev->first_hw_init_done = false;
+ tac_dev->part_id = id->part_id;
+ dev_set_drvdata(dev, tac_dev);
+
+ regmap = devm_regmap_init_sdw_mbq_cfg(&peripheral->dev, peripheral,
+ &tac_regmap, &tac_mbq_cfg);
+ if (IS_ERR(regmap))
+ return dev_err_probe(dev, PTR_ERR(regmap),
+ "Failed devm_regmap_init_sdw\n");
+
+ regcache_cache_only(regmap, true);
+ tac_dev->regmap = regmap;
+ tac_dev->jack_type = 0;
+ init_completion(&tac_dev->fw_caching_complete);
+
+ if (tac_has_dsp_algo(tac_dev)) {
+ tac_generate_fw_name(peripheral, tac_dev->fw_binaryname,
+ sizeof(tac_dev->fw_binaryname));
+
+ ret = tac_load_and_cache_firmware_async(tac_dev);
+ if (ret) {
+ complete_all(&tac_dev->fw_caching_complete);
+ dev_dbg(dev, "failed to load fw: %d, use rom mode\n", ret);
+ }
+ } else {
+ complete_all(&tac_dev->fw_caching_complete);
+ }
+
+ ret = tac_init(tac_dev);
+ if (ret)
+ return dev_err_probe(dev, ret,
+ "failed to initialize tac device\n");
+
+ /* set autosuspend parameters */
+ pm_runtime_set_autosuspend_delay(dev, 3000);
+ pm_runtime_use_autosuspend(dev);
+
+ /* make sure the device does not suspend immediately */
+ pm_runtime_mark_last_busy(dev);
+
+ pm_runtime_enable(dev);
+ /* the device is still not in active */
+
+ return 0;
+}
+
+static void tac_sdw_remove(struct sdw_slave *peripheral)
+{
+ struct tac5xx2_prv *tac_dev = dev_get_drvdata(&peripheral->dev);
+
+ pm_runtime_disable(tac_dev->dev);
+
+ dev_set_drvdata(&peripheral->dev, NULL);
+}
+
+static const struct sdw_device_id tac_sdw_id[] = {
+ SDW_SLAVE_ENTRY(0x0102, 0x5572, 0),
+ SDW_SLAVE_ENTRY(0x0102, 0x5672, 0),
+ SDW_SLAVE_ENTRY(0x0102, 0x5682, 0),
+ SDW_SLAVE_ENTRY(0x0102, 0x2883, 0),
+ {},
+};
+MODULE_DEVICE_TABLE(sdw, tac_sdw_id);
+
+static struct sdw_driver tac_sdw_driver = {
+ .driver = {
+ .name = "slave-tac5xx2",
+ .pm = pm_ptr(&tac5xx2_sdca_pm),
+ },
+ .probe = tac_sdw_probe,
+ .remove = tac_sdw_remove,
+ .ops = &tac_sdw_ops,
+ .id_table = tac_sdw_id,
+};
+module_sdw_driver(tac_sdw_driver);
+
+MODULE_IMPORT_NS("SND_SOC_SDCA");
+MODULE_AUTHOR("Texas Instruments Inc.");
+MODULE_DESCRIPTION("ASoC TAC5XX2 SoundWire Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tac5xx2.h b/sound/soc/codecs/tac5xx2.h
new file mode 100644
index 000000000000..eed8e6cf3498
--- /dev/null
+++ b/sound/soc/codecs/tac5xx2.h
@@ -0,0 +1,259 @@
+/* SPDX-License-Identifier: GPL-2.0
+ *
+ * ALSA SoC Texas Instruments TAC5XX2 Audio Smart Amplifier
+ *
+ * Copyright (C) 2025 Texas Instruments Incorporated
+ * https://www.ti.com
+ *
+ * This the header file for TAC5XX2 family of devices
+ * which includes TAC5572, TAC5672, TAC5682 and TAS2883
+ *
+ * Author: Niranjan H Y <niranjanhy@ti.com>
+ */
+#ifndef __RGL_TAC5XX2_H__
+#define __RGL_TAC5XX2_H__
+
+/* for soundwire */
+#define TAC_REG_SDW(book, page, reg) (((book) * 256 * 128) + \
+ 0x3000000 + ((page) * 128) + (reg))
+
+/* page 0 registers */
+#define TAC_SW_RESET TAC_REG_SDW(0, 0, 1)
+#define TAC_SLEEP_MODEZ TAC_REG_SDW(0, 0, 2)
+#define TAC_FEATURE_PDZ TAC_REG_SDW(0, 0, 3)
+#define TAC_TX_CH_EN TAC_REG_SDW(0, 0, 4)
+#define TAC_RX_CH_PD TAC_REG_SDW(0, 0, 5)
+#define TAC_SHDNZ_CFG TAC_REG_SDW(0, 0, 6)
+#define TAC_MISC_CFG0 TAC_REG_SDW(0, 0, 7)
+#define TAC_MISC_CFG1 TAC_REG_SDW(0, 0, 8)
+#define TAC_GPIO1_CFG0 TAC_REG_SDW(0, 0, 9)
+#define TAC_GPIO2_CFG0 TAC_REG_SDW(0, 0, 10)
+#define TAC_GPIO3_CFG0 TAC_REG_SDW(0, 0, 11)
+#define TAC_GPIO4_CFG0 TAC_REG_SDW(0, 0, 12)
+#define TAC_GPIO5_CFG0 TAC_REG_SDW(0, 0, 13)
+#define TAC_GPIO6_CFG0 TAC_REG_SDW(0, 0, 14)
+#define TAC_INTF_CFG1 TAC_REG_SDW(0, 0, 15)
+#define TAC_INTF_CFG5 TAC_REG_SDW(0, 0, 16)
+#define TAC_PASI_BCLK_CFG0 TAC_REG_SDW(0, 0, 17)
+#define TAC_PASI_FSYNC_CFG0 TAC_REG_SDW(0, 0, 18)
+#define TAC_PASI_DIN1_CFG0 TAC_REG_SDW(0, 0, 19)
+#define TAC_PASI_DIN2_CFG0 TAC_REG_SDW(0, 0, 20)
+#define TAC_PDM_DIN1_CFG0 TAC_REG_SDW(0, 0, 21)
+#define TAC_PDM_DIN2_CFG0 TAC_REG_SDW(0, 0, 22)
+#define TAC_MCLK_SEL TAC_REG_SDW(0, 0, 23)
+#define TAC_I2C2_CFG0 TAC_REG_SDW(0, 0, 24)
+#define TAC_SDW_IO_CFG0 TAC_REG_SDW(0, 0, 25)
+#define TAC_SDW_CLK_CFG0 TAC_REG_SDW(0, 0, 26)
+#define TAC_PASI_CFG0 TAC_REG_SDW(0, 0, 27)
+#define TAC_PASI_CFG1 TAC_REG_SDW(0, 0, 28)
+#define TAC_PASI_TX_CFG0 TAC_REG_SDW(0, 0, 29)
+#define TAC_PASI_TX_CFG1 TAC_REG_SDW(0, 0, 30)
+#define TAC_PASI_TX_CFG2 TAC_REG_SDW(0, 0, 31)
+#define TAC_PASI_TX_CFG3 TAC_REG_SDW(0, 0, 32)
+#define TAC_PASI_TX_CH1_CFG0 TAC_REG_SDW(0, 0, 33)
+#define TAC_PASI_TX_CH2_CFG0 TAC_REG_SDW(0, 0, 34)
+#define TAC_PASI_TX_CH3_CFG0 TAC_REG_SDW(0, 0, 35)
+#define TAC_PASI_TX_CH4_CFG0 TAC_REG_SDW(0, 0, 36)
+#define TAC_PASI_TX_CH5_CFG0 TAC_REG_SDW(0, 0, 37)
+#define TAC_PASI_TX_CH6_CFG0 TAC_REG_SDW(0, 0, 38)
+#define TAC_PASI_TX_CH7_CFG0 TAC_REG_SDW(0, 0, 39)
+#define TAC_PASI_TX_CH8_CFG0 TAC_REG_SDW(0, 0, 40)
+#define TAC_PASI_RX_CFG0 TAC_REG_SDW(0, 0, 41)
+#define TAC_PASI_RX_CFG1 TAC_REG_SDW(0, 0, 42)
+#define TAC_PASI_RX_CFG2 TAC_REG_SDW(0, 0, 43)
+#define TAC_PASI_RX_CH1_CFG0 TAC_REG_SDW(0, 0, 44)
+#define TAC_PASI_RX_CH2_CFG0 TAC_REG_SDW(0, 0, 45)
+#define TAC_PASI_RX_CH3_CFG0 TAC_REG_SDW(0, 0, 46)
+#define TAC_PASI_RX_CH4_CFG0 TAC_REG_SDW(0, 0, 47)
+#define TAC_PASI_RX_CH5_CFG0 TAC_REG_SDW(0, 0, 48)
+#define TAC_PASI_RX_CH6_CFG0 TAC_REG_SDW(0, 0, 49)
+#define TAC_PASI_RX_CH7_CFG0 TAC_REG_SDW(0, 0, 50)
+#define TAC_PASI_RX_CH8_CFG0 TAC_REG_SDW(0, 0, 51)
+#define TAC_ADC_CH1_CFG0 TAC_REG_SDW(0, 0, 52)
+#define TAC_ADC_DVOL_CFG0 TAC_REG_SDW(0, 0, 53)
+#define TAC_ADC_CH1_FGAIN TAC_REG_SDW(0, 0, 54)
+#define TAC_ADC_CH1_CFG1 TAC_REG_SDW(0, 0, 55)
+#define TAC_ADC_CH2_CFG0 TAC_REG_SDW(0, 0, 57)
+#define TAC_ADC_DVOL_CFG1 TAC_REG_SDW(0, 0, 58)
+#define TAC_ADC_CH2_FGAIN TAC_REG_SDW(0, 0, 59)
+#define TAC_ADC_CH2_CFG1 TAC_REG_SDW(0, 0, 60)
+#define TAC_ADC_CFG1 TAC_REG_SDW(0, 0, 62)
+#define TAC_PDM_CH1_DVOL TAC_REG_SDW(0, 0, 63)
+#define TAC_PDM_CH1_FGAIN TAC_REG_SDW(0, 0, 64)
+#define TAC_PDM_CH1_CFG0 TAC_REG_SDW(0, 0, 65)
+#define TAC_PDM_CH2_DVOL TAC_REG_SDW(0, 0, 67)
+#define TAC_PDM_CH2_FGAIN TAC_REG_SDW(0, 0, 68)
+#define TAC_PDM_CH2_CFG2 TAC_REG_SDW(0, 0, 69)
+#define TAC_PDM_CH3_DVOL TAC_REG_SDW(0, 0, 71)
+#define TAC_PDM_CH3_FGAIN TAC_REG_SDW(0, 0, 72)
+#define TAC_PDM_CH3_CFG0 TAC_REG_SDW(0, 0, 73)
+#define TAC_PDM_CH4_DVOL TAC_REG_SDW(0, 0, 75)
+#define TAC_PDM_CH4_FGAIN TAC_REG_SDW(0, 0, 76)
+#define TAC_PDM_CH4_CFG0 TAC_REG_SDW(0, 0, 77)
+#define TAC_MICBIAS_CFG0 TAC_REG_SDW(0, 0, 79)
+#define TAC_MICPREAMP_CFG TAC_REG_SDW(0, 0, 80)
+#define TAC_MICBIAS_CFG1 TAC_REG_SDW(0, 0, 81)
+#define TAC_CLASSD_CH1_DVOL TAC_REG_SDW(0, 0, 82)
+#define TAC_CLASSD_CH1_FGAIN TAC_REG_SDW(0, 0, 83)
+#define TAC_CLASSD_CH2_DVOL TAC_REG_SDW(0, 0, 85)
+#define TAC_CLASSD_CH2_FGAIN TAC_REG_SDW(0, 0, 86)
+#define TAC_GCHP_CH1_DVOL TAC_REG_SDW(0, 0, 88)
+#define TAC_GCHP_CH1_FGAIN TAC_REG_SDW(0, 0, 89)
+#define TAC_GCHP_CH2_DVOL TAC_REG_SDW(0, 0, 91)
+#define TAC_GCHP_CH2_FGAIN TAC_REG_SDW(0, 0, 92)
+#define TAC_AMP_LVL_CFG0 TAC_REG_SDW(0, 0, 94)
+#define TAC_AMP_LVL_CFG1 TAC_REG_SDW(0, 0, 95)
+#define TAC_AMP_LVL_CFG2 TAC_REG_SDW(0, 0, 96)
+#define TAC_AMP_LVL_CFG3 TAC_REG_SDW(0, 0, 97)
+#define TAC_EFF_MODE_CFG0 TAC_REG_SDW(0, 0, 98)
+#define TAC_EFF_MODE_CFG1 TAC_REG_SDW(0, 0, 99)
+#define TAC_CLASSD_CFG0 TAC_REG_SDW(0, 0, 100)
+#define TAC_CLASSD_CFG1 TAC_REG_SDW(0, 0, 101)
+#define TAC_CLASSD_CFG3 TAC_REG_SDW(0, 0, 102)
+#define TAC_CLASSD_CFG4 TAC_REG_SDW(0, 0, 103)
+#define TAC_CLASSD_CFG5 TAC_REG_SDW(0, 0, 104)
+#define TAC_CLASSD_CFG6 TAC_REG_SDW(0, 0, 105)
+#define TAC_CLASSD_CFG8 TAC_REG_SDW(0, 0, 106)
+#define TAC_ISNS_CFG TAC_REG_SDW(0, 0, 107)
+#define TAC_DSP_CFG0 TAC_REG_SDW(0, 0, 108)
+#define TAC_DSP_CFG1 TAC_REG_SDW(0, 0, 109)
+#define TAC_DSP_CFG2 TAC_REG_SDW(0, 0, 110)
+#define TAC_DSP_CFG3 TAC_REG_SDW(0, 0, 111)
+#define TAC_JACK_DET_CFG1 TAC_REG_SDW(0, 0, 112)
+#define TAC_JACK_DET_CFG2 TAC_REG_SDW(0, 0, 113)
+#define TAC_JACK_DET_CFG3 TAC_REG_SDW(0, 0, 114)
+#define TAC_JACK_DET_CFG4 TAC_REG_SDW(0, 0, 115)
+#define TAC_JACK_DET_CFG7 TAC_REG_SDW(0, 0, 116)
+#define TAC_UJ_IMPEDANCE_L TAC_REG_SDW(0, 0, 117)
+#define TAC_UJ_IMPEDANCE_R TAC_REG_SDW(0, 0, 118)
+#define UJ_IMPEDANCE_L TAC_REG_SDW(0, 0, 119)
+#define UJ_IMPEDANCE_R TAC_REG_SDW(0, 0, 120)
+#define TAC_GP_ANA_STS TAC_REG_SDW(0, 0, 123)
+#define TAC_DEV_ID TAC_REG_SDW(0, 0, 124)
+#define TAC_REV_ID TAC_REG_SDW(0, 0, 125)
+#define TAC_I2C_CKSUM TAC_REG_SDW(0, 0, 126)
+#define TAC_BOOK TAC_REG_SDW(0, 0, 127)
+
+#define TAC_INT_CFG TAC_REG_SDW(0, 2, 1)
+#define TAC_INT_CFG_CLR_REG BIT(3)
+
+/* smartamp function */
+#define TAC_FUNCTION_ID_SA 0x1
+
+#define TAC_SDCA_ENT_ENT0 0x0
+#define TAC_SDCA_ENT_PPU21 0x1
+#define TAC_SDCA_ENT_FU21 0x2
+#define TAC_SDCA_ENT_FU26 0x3
+#define TAC_SDCA_ENT_XU22 0x4
+#define TAC_SDCA_ENT_CS24 0x5
+#define TAC_SDCA_ENT_CS21 0x6
+#define TAC_SDCA_ENT_CS25 0x7
+#define TAC_SDCA_ENT_CS26 0x8
+#define TAC_SDCA_ENT_CS28 0x9
+#define TAC_SDCA_ENT_PPU26 0xa
+#define TAC_SDCA_ENT_FU23 0xb
+#define TAC_SDCA_ENT_PDE23 0xc
+#define TAC_SDCA_ENT_TG23 0x12
+#define TAC_SDCA_ENT_IT21 0x13
+#define TAC_SDCA_ENT_IT29 0x14
+#define TAC_SDCA_ENT_IT26 0x15
+#define TAC_SDCA_ENT_IT28 0x16
+#define TAC_SDCA_ENT_OT24 0x17
+#define TAC_SDCA_ENT_OT23 0x18
+#define TAC_SDCA_ENT_OT25 0x19
+#define TAC_SDCA_ENT_OT28 0x1a
+#define TAC_SDCA_ENT_OT27 0x1c
+#define TAC_SDCA_ENT_SPE199 0x21
+#define TAC_SDCA_ENT_OT20 0x24
+#define TAC_SDCA_ENT_FU27 0x26
+#define TAC_SDCA_ENT_FU20 0x27
+#define TAC_SDCA_ENT_PDE24 0x2e
+#define TAC_SDCA_ENT_PDE27 0x2f
+#define TAC_SDCA_ENT_PDE28 0x30
+#define TAC_SDCA_ENT_PDE20 0x31
+#define TAC_SDCA_ENT_SAPU29 0x35
+
+/* Control selector definitions */
+#define TAC_SDCA_MASTER_GAIN 0x0B
+#define TAC_SDCA_MASTER_MUTE 0x01
+#define TAC_SDCA_CHANNEL_MUTE 0x01
+#define TAC_SDCA_CHANNEL_GAIN 0x02
+#define TAC_SDCA_POSTURENUMBER 0x10
+#define TAC_SDCA_REQUESTED_PS 0x01
+#define TAC_SDCA_ACTUAL_PS 0x10
+#define TAC_SDCA_CHANNEL_VOLUME 0x02
+
+/* 2. smart mic function */
+#define TAC_FUNCTION_ID_SM 0x2
+
+#define TAC_SDCA_ENT_IT11 0x1
+#define TAC_SDCA_ENT_OT113 0x2
+#define TAC_SDCA_ENT_CS11 0x3
+#define TAC_SDCA_ENT_CS18 0x4
+#define TAC_SDCA_ENT_FU113 0x5
+#define TAC_SDCA_ENT_FU13 0x6
+#define TAC_SDCA_ENT_FU11 0x8
+#define TAC_SDCA_ENT_XU12 0xa
+#define TAC_SDCA_ENT_CS113 0xc
+#define TAC_SDCA_ENT_CX11 0xf
+#define TAC_SDCA_ENT_PDE11 0x12
+#define TAC_SDCA_ENT_PPU11 0x9
+
+/* controls */
+#define TAC_SDCA_CTL_USAGE 0x04
+#define TAC_SDCA_CTL_IT_CLUSTER 0x10
+#define TAC_SDCA_CTL_OT_DP_SEL 0x11
+#define TAC_SDCA_CTL_XU_BYPASS 0x01
+/* cx */
+#define TAC_SDCA_CTL_CX_CLK_SEL 0x01
+/* cs */
+#define TAC_SDCA_CTL_CS_CLKVLD 0x02
+#define TAC_SDCA_CTL_CS_SAMP_RATE_IDX 0x10
+/* cs113 end */
+/* ppu */
+#define TAC_SDCA_CTL_PPU_POSTURE_NUM 0x10
+
+/* 3. UAJ function */
+#define TAC_FUNCTION_ID_UAJ 0x3
+#define TAC_SDCA_ENT_PDE47 0x35
+#define TAC_SDCA_ENT_PDE34 0x32
+#define TAC_SDCA_ENT_FU41 0x26 /* user */
+#define TAC_SDCA_ENT_IT41 0x07
+#define TAC_SDCA_ENT_XU42 0x2C
+#define TAC_SDCA_ENT_CS41 0x30
+#define TAC_SDCA_ENT_OT45 0x0E
+#define TAC_SDCA_ENT_IT33 0x03
+#define TAC_SDCA_ENT_OT36 0x0A
+#define TAC_SDCA_ENT_FU36 0x28
+#define TAC_SDCA_ENT_CS36 0x2E
+#define TAC_SDCA_ENT_GE35 0x3B /* 59 */
+
+#define TAC_SDCA_CTL_SEL_MODE 0x1
+#define TAC_SDCA_CTL_DET_MODE 0x2
+
+/* 4. HID function */
+#define TAC_FUNCTION_ID_HID 0x4
+#define TAC_SDCA_ENT_HID1 0x1
+/* HID Control Selectors */
+#define TAC_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10
+#define TAC_SDCA_CTL_HIDTX_MESSAGE_OFFSET 0x12
+#define TAC_SDCA_CTL_HIDTX_MESSAGE_LENGTH 0x13
+#define TAC_SDCA_CTL_DETECTED_MODE 0x10
+#define TAC_SDCA_CTL_SELECTED_MODE 0x11
+
+#define TAC_BUF_ADDR_HID1 0x44007F80
+
+/* DAI interfaces */
+#define TAC5XX2_SPK 0
+#define TAC5XX2_DMIC 2
+#define TAC5XX2_UAJ 3
+
+/* Port numbers for DAIs */
+#define TAC_SDW_PORT_NUM_SPK_PLAYBACK 1
+#define TAC_SDW_PORT_NUM_SPK_CAPTURE 2
+#define TAC_SDW_PORT_NUM_DMIC 3
+#define TAC_SDW_PORT_NUM_UAJ_PLAYBACK 4
+#define TAC_SDW_PORT_NUM_UAJ_CAPTURE 7
+#define TAC_SDW_PORT_NUM_IV_SENSE 8
+
+#endif
diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c
index 80206c2e0946..1a7650b9b2a7 100644
--- a/sound/soc/codecs/tas2552.c
+++ b/sound/soc/codecs/tas2552.c
@@ -745,7 +745,7 @@ static void tas2552_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id tas2552_id[] = {
- { "tas2552" },
+ { .name = "tas2552" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas2552_id);
diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c
index ceb367ae05ba..2f7cfc2be970 100644
--- a/sound/soc/codecs/tas2562.c
+++ b/sound/soc/codecs/tas2562.c
@@ -711,9 +711,9 @@ static int tas2562_parse_dt(struct tas2562_data *tas2562)
}
static const struct i2c_device_id tas2562_id[] = {
- { "tas2562", TAS2562 },
- { "tas2564", TAS2564 },
- { "tas2110", TAS2110 },
+ { .name = "tas2562", .driver_data = TAS2562 },
+ { .name = "tas2564", .driver_data = TAS2564 },
+ { .name = "tas2110", .driver_data = TAS2110 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas2562_id);
diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c
index 55211266927d..b11b998aa32a 100644
--- a/sound/soc/codecs/tas2764.c
+++ b/sound/soc/codecs/tas2764.c
@@ -1036,7 +1036,7 @@ static int tas2764_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id tas2764_i2c_id[] = {
- { "tas2764"},
+ { .name = "tas2764" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas2764_i2c_id);
diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c
index dbda9f327535..e79754edac5c 100644
--- a/sound/soc/codecs/tas2770.c
+++ b/sound/soc/codecs/tas2770.c
@@ -958,7 +958,7 @@ static int tas2770_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id tas2770_i2c_id[] = {
- { "tas2770"},
+ { .name = "tas2770" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas2770_i2c_id);
diff --git a/sound/soc/codecs/tas2780.c b/sound/soc/codecs/tas2780.c
index cf3f6abd7e7b..1ec1c076204f 100644
--- a/sound/soc/codecs/tas2780.c
+++ b/sound/soc/codecs/tas2780.c
@@ -621,7 +621,7 @@ static int tas2780_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id tas2780_i2c_id[] = {
- { "tas2780"},
+ { .name = "tas2780" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas2780_i2c_id);
diff --git a/sound/soc/codecs/tas2781-fmwlib.c b/sound/soc/codecs/tas2781-fmwlib.c
index 885e0b6fed00..bd16d5326a23 100644
--- a/sound/soc/codecs/tas2781-fmwlib.c
+++ b/sound/soc/codecs/tas2781-fmwlib.c
@@ -921,7 +921,8 @@ static int tasdevice_process_block(void *context, unsigned char *data,
data[subblk_offset + 1],
data[subblk_offset + 2]),
data[subblk_offset + 3]);
- if (rc < 0) {
+ if (rc < 0 &&
+ !(tas_priv->isspi && rc == -EXDEV)) {
is_err = true;
dev_err(tas_priv->dev,
"process_block: single write error\n");
@@ -953,7 +954,7 @@ static int tasdevice_process_block(void *context, unsigned char *data,
data[subblk_offset + 1],
data[subblk_offset + 2]),
&(data[subblk_offset + 4]), len);
- if (rc < 0) {
+ if (rc < 0 && !(tas_priv->isspi && rc == -EXDEV)) {
is_err = true;
dev_err(tas_priv->dev,
"%s: bulk_write error = %d\n",
@@ -991,7 +992,7 @@ static int tasdevice_process_block(void *context, unsigned char *data,
data[subblk_offset + 4]),
data[subblk_offset + 1],
data[subblk_offset + 5]);
- if (rc < 0) {
+ if (rc < 0 && !(tas_priv->isspi && rc == -EXDEV)) {
is_err = true;
dev_err(tas_priv->dev,
"%s: update_bits error = %d\n",
diff --git a/sound/soc/codecs/tas2781-i2c.c b/sound/soc/codecs/tas2781-i2c.c
index a78a8f9b9833..9e6f0ad5f05d 100644
--- a/sound/soc/codecs/tas2781-i2c.c
+++ b/sound/soc/codecs/tas2781-i2c.c
@@ -100,27 +100,28 @@ static const struct bulk_reg_val tas2781_cali_start_reg[] = {
};
static const struct i2c_device_id tasdevice_id[] = {
- { "tas2020", TAS2020 },
- { "tas2118", TAS2118 },
- { "tas2120", TAS2120 },
- { "tas2320", TAS2320 },
- { "tas2563", TAS2563 },
- { "tas2568", TAS2568 },
- { "tas2570", TAS2570 },
- { "tas2572", TAS2572 },
- { "tas2574", TAS2574 },
- { "tas2781", TAS2781 },
- { "tas5802", TAS5802 },
- { "tas5806m", TAS5806M },
- { "tas5806md", TAS5806MD },
- { "tas5815", TAS5815 },
- { "tas5822", TAS5822 },
- { "tas5825", TAS5825 },
- { "tas5827", TAS5827 },
- { "tas5828", TAS5828 },
- { "tas5830", TAS5830 },
- { "tas5832", TAS5832 },
- {}
+ { .name = "tas2020", .driver_data = TAS2020 },
+ { .name = "tas2118", .driver_data = TAS2118 },
+ { .name = "tas2120", .driver_data = TAS2120 },
+ { .name = "tas2320", .driver_data = TAS2320 },
+ { .name = "tas2563", .driver_data = TAS2563 },
+ { .name = "tas2568", .driver_data = TAS2568 },
+ { .name = "tas2570", .driver_data = TAS2570 },
+ { .name = "tas2572", .driver_data = TAS2572 },
+ { .name = "tas2573", .driver_data = TAS2573 },
+ { .name = "tas2574", .driver_data = TAS2574 },
+ { .name = "tas2781", .driver_data = TAS2781 },
+ { .name = "tas5802", .driver_data = TAS5802 },
+ { .name = "tas5806m", .driver_data = TAS5806M },
+ { .name = "tas5806md", .driver_data = TAS5806MD },
+ { .name = "tas5815", .driver_data = TAS5815 },
+ { .name = "tas5822", .driver_data = TAS5822 },
+ { .name = "tas5825", .driver_data = TAS5825 },
+ { .name = "tas5827", .driver_data = TAS5827 },
+ { .name = "tas5828", .driver_data = TAS5828 },
+ { .name = "tas5830", .driver_data = TAS5830 },
+ { .name = "tas5832", .driver_data = TAS5832 },
+ { }
};
static const struct of_device_id tasdevice_of_match[] = {
@@ -132,6 +133,7 @@ static const struct of_device_id tasdevice_of_match[] = {
{ .compatible = "ti,tas2568", .data = &tasdevice_id[TAS2568] },
{ .compatible = "ti,tas2570", .data = &tasdevice_id[TAS2570] },
{ .compatible = "ti,tas2572", .data = &tasdevice_id[TAS2572] },
+ { .compatible = "ti,tas2573", .data = &tasdevice_id[TAS2573] },
{ .compatible = "ti,tas2574", .data = &tasdevice_id[TAS2574] },
{ .compatible = "ti,tas2781", .data = &tasdevice_id[TAS2781] },
{ .compatible = "ti,tas5802", .data = &tasdevice_id[TAS5802] },
@@ -1683,7 +1685,7 @@ static void tasdevice_fw_ready(const struct firmware *fmw,
tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
/* There is no calibration required for TAS58XX. */
- if (tas_priv->chip_id < TAS5802) {
+ if (tas_priv->chip_id == TAS2563 || tas_priv->chip_id == TAS2781) {
ret = tasdevice_create_cali_ctrls(tas_priv);
if (ret) {
dev_err(tas_priv->dev, "cali controls error\n");
@@ -1736,6 +1738,7 @@ out:
if (tas_priv->fw_state == TASDEVICE_RCA_FW_OK) {
switch (tas_priv->chip_id) {
case TAS2563:
+ case TAS2573:
case TAS2781:
case TAS5802:
case TAS5806M:
@@ -1900,6 +1903,7 @@ static int tasdevice_codec_probe(struct snd_soc_component *codec)
case TAS2568:
case TAS2570:
case TAS2572:
+ case TAS2573:
case TAS2574:
p = (struct snd_kcontrol_new *)tas2x20_snd_controls;
size = ARRAY_SIZE(tas2x20_snd_controls);
@@ -2094,6 +2098,7 @@ static const struct acpi_device_id tasdevice_acpi_match[] = {
{ "TXNW2568", (kernel_ulong_t)&tasdevice_id[TAS2568] },
{ "TXNW2570", (kernel_ulong_t)&tasdevice_id[TAS2570] },
{ "TXNW2572", (kernel_ulong_t)&tasdevice_id[TAS2572] },
+ { "TXNW2573", (kernel_ulong_t)&tasdevice_id[TAS2573] },
{ "TXNW2574", (kernel_ulong_t)&tasdevice_id[TAS2574] },
{ "TXNW2781", (kernel_ulong_t)&tasdevice_id[TAS2781] },
{ "TXNW5802", (kernel_ulong_t)&tasdevice_id[TAS5802] },
diff --git a/sound/soc/codecs/tas2783-sdw.c b/sound/soc/codecs/tas2783-sdw.c
index 90008d2d06e2..3d0b116544cc 100644
--- a/sound/soc/codecs/tas2783-sdw.c
+++ b/sound/soc/codecs/tas2783-sdw.c
@@ -100,6 +100,8 @@ struct tas2783_prv {
wait_queue_head_t fw_wait;
bool fw_dl_task_done;
bool fw_dl_success;
+ /* use fallback fw name */
+ bool fw_use_fallback;
};
static const struct reg_default tas2783_reg_default[] = {
@@ -740,11 +742,19 @@ static void tas2783_fw_ready(const struct firmware *fmw, void *context)
goto out;
}
+ /* firmware binary not found*/
if (!fmw || !fmw->data) {
- /* firmware binary not found*/
- dev_err(tas_dev->dev,
- "Failed to read fw binary %s\n",
- tas_dev->rca_binaryname);
+ if (!tas_dev->fw_use_fallback) {
+ tas_dev->fw_use_fallback = true;
+ dev_info(tas_dev->dev,
+ "Failed to read preferred fw binary: %s, attempting fallback binary load\n",
+ tas_dev->rca_binaryname);
+ } else {
+ dev_err(tas_dev->dev,
+ "Failed to read fallback fw binary %s\n",
+ tas_dev->rca_binaryname);
+ }
+
ret = -EINVAL;
goto out;
}
@@ -1011,7 +1021,6 @@ static s32 tas_component_probe(struct snd_soc_component *component)
snd_soc_component_get_drvdata(component);
tas_dev->component = component;
- tas25xx_register_misc(tas_dev->sdw_peripheral);
return 0;
}
@@ -1020,7 +1029,6 @@ static void tas_component_remove(struct snd_soc_component *codec)
{
struct tas2783_prv *tas_dev =
snd_soc_component_get_drvdata(codec);
- tas25xx_deregister_misc();
tas_dev->component = NULL;
}
@@ -1082,22 +1090,14 @@ static s32 tas2783_sdca_dev_resume(struct device *dev)
{
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct tas2783_prv *tas_dev = dev_get_drvdata(dev);
- unsigned long t;
-
- if (!slave->unattach_request)
- goto regmap_sync;
+ int ret;
- t = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(TAS2783_PROBE_TIMEOUT));
- if (!t) {
- dev_err(&slave->dev, "resume: initialization timed out\n");
+ ret = sdw_slave_wait_for_init(slave, TAS2783_PROBE_TIMEOUT);
+ if (ret) {
sdw_show_ping_status(slave->bus, true);
- return -ETIMEDOUT;
+ return ret;
}
- slave->unattach_request = 0;
-
-regmap_sync:
regcache_cache_only(tas_dev->regmap, false);
regcache_sync(tas_dev->regmap);
return 0;
@@ -1115,13 +1115,16 @@ static void tas_generate_fw_name(struct sdw_slave *slave, char *name, size_t siz
bool pci_found = false;
#if IS_ENABLED(CONFIG_PCI)
struct device *dev = &slave->dev;
+ struct tas2783_prv *tas_dev = dev_get_drvdata(&slave->dev);
struct pci_dev *pci = NULL;
+ const char *fw_uid_prefix = tas_dev->fw_use_fallback ? "" : "0x";
for (; dev; dev = dev->parent) {
if (dev->bus == &pci_bus_type) {
pci = to_pci_dev(dev);
- scnprintf(name, size, "%04X-%1X-%1X.bin",
- pci->subsystem_device, bus->link_id, unique_id);
+ scnprintf(name, size, "%04X-%1X-%s%1X.bin",
+ pci->subsystem_device, bus->link_id,
+ fw_uid_prefix, unique_id);
pci_found = true;
break;
}
@@ -1133,28 +1136,15 @@ static void tas_generate_fw_name(struct sdw_slave *slave, char *name, size_t siz
bus->link_id, unique_id);
}
-static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
+static s32 tas_fw_load(struct tas2783_prv *tas_dev, struct sdw_slave *slave)
{
- struct tas2783_prv *tas_dev = dev_get_drvdata(dev);
s32 ret;
u8 unique_id = tas_dev->sdw_peripheral->id.unique_id;
- if (tas_dev->hw_init)
- return 0;
-
- tas_dev->fw_dl_task_done = false;
- tas_dev->fw_dl_success = false;
-
- ret = regmap_write(tas_dev->regmap, TAS2783_SW_RESET, 0x1);
- if (ret) {
- dev_err(dev, "sw reset failed, err=%d", ret);
- return ret;
- }
- usleep_range(2000, 2200);
-
tas_generate_fw_name(slave, tas_dev->rca_binaryname,
sizeof(tas_dev->rca_binaryname));
+ tas_dev->fw_dl_task_done = false;
ret = request_firmware_nowait(THIS_MODULE, FW_ACTION_UEVENT,
tas_dev->rca_binaryname, tas_dev->dev,
GFP_KERNEL, tas_dev, tas2783_fw_ready);
@@ -1169,8 +1159,35 @@ static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
msecs_to_jiffies(TIMEOUT_FW_DL_MS));
if (!ret) {
dev_err(tas_dev->dev, "fw request, wait_event timeout\n");
- ret = -EAGAIN;
- } else {
+ return -EAGAIN;
+ }
+
+ return 0;
+}
+
+static s32 tas_io_init(struct device *dev, struct sdw_slave *slave)
+{
+ struct tas2783_prv *tas_dev = dev_get_drvdata(dev);
+ s32 ret;
+
+ if (tas_dev->hw_init)
+ return 0;
+
+ tas_dev->fw_dl_success = false;
+
+ ret = regmap_write(tas_dev->regmap, TAS2783_SW_RESET, 0x1);
+ if (ret) {
+ dev_err(dev, "sw reset failed, err=%d", ret);
+ return ret;
+ }
+ usleep_range(2000, 2200);
+
+ tas_dev->fw_use_fallback = false;
+ ret = tas_fw_load(tas_dev, slave);
+ if (!ret && tas_dev->fw_use_fallback)
+ ret = tas_fw_load(tas_dev, slave);
+
+ if (!ret) {
if (tas_dev->sa_func_data)
ret = sdca_regmap_write_init(dev, tas_dev->regmap,
tas_dev->sa_func_data);
@@ -1310,10 +1327,10 @@ static s32 tas_sdw_probe(struct sdw_slave *peripheral,
return dev_err_probe(dev, -ENOMEM,
"failed to parse sdca functions");
+ function_data->desc = &peripheral->sdca_data.function[i];
+
/* Parse the function */
- ret = sdca_parse_function(dev, peripheral,
- &peripheral->sdca_data.function[i],
- function_data);
+ ret = sdca_parse_function(dev, peripheral, function_data);
if (!ret)
tas_dev->sa_func_data = function_data;
else
diff --git a/sound/soc/codecs/tas2783.h b/sound/soc/codecs/tas2783.h
index bf34319c9a9f..d5996c73526c 100644
--- a/sound/soc/codecs/tas2783.h
+++ b/sound/soc/codecs/tas2783.h
@@ -100,12 +100,4 @@
#define TAS2783_CALIB_DATA_SZ ((TAS2783_CALIB_HDR_SZ) + TAS2783_CALIB_CRC_SZ + \
((TAS2783_CALIB_PARAMS) * 4 * (TAS2783_CALIB_MAX_SPK_COUNT)))
-#if IS_ENABLED(CONFIG_SND_SOC_TAS2783_UTIL)
-int32_t tas25xx_register_misc(struct sdw_slave *peripheral);
-int32_t tas25xx_deregister_misc(void);
-#else
-static void tas25xx_register_misc(struct sdw_slave *peripheral) {}
-static void tas25xx_deregister_misc(void) {}
-#endif
-
#endif /*__TAS2783_H__ */
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c
index 12bf6a89dbd8..4d1c122c8f04 100644
--- a/sound/soc/codecs/tas5086.c
+++ b/sound/soc/codecs/tas5086.c
@@ -891,7 +891,7 @@ static const struct snd_soc_component_driver soc_component_dev_tas5086 = {
};
static const struct i2c_device_id tas5086_i2c_id[] = {
- { "tas5086" },
+ { .name = "tas5086" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id);
@@ -975,17 +975,13 @@ static int tas5086_i2c_probe(struct i2c_client *i2c)
return ret;
}
-static void tas5086_i2c_remove(struct i2c_client *i2c)
-{}
-
static struct i2c_driver tas5086_i2c_driver = {
.driver = {
- .name = "tas5086",
+ .name = "tas5086",
.of_match_table = of_match_ptr(tas5086_dt_ids),
},
- .id_table = tas5086_i2c_id,
- .probe = tas5086_i2c_probe,
- .remove = tas5086_i2c_remove,
+ .id_table = tas5086_i2c_id,
+ .probe = tas5086_i2c_probe,
};
module_i2c_driver(tas5086_i2c_driver);
diff --git a/sound/soc/codecs/tas571x.c b/sound/soc/codecs/tas571x.c
index 19ccf8641e16..8b5f9accf120 100644
--- a/sound/soc/codecs/tas571x.c
+++ b/sound/soc/codecs/tas571x.c
@@ -1064,13 +1064,13 @@ static const struct of_device_id tas571x_of_match[] __maybe_unused = {
MODULE_DEVICE_TABLE(of, tas571x_of_match);
static const struct i2c_device_id tas571x_i2c_id[] = {
- { "tas5707", (kernel_ulong_t) &tas5707_chip },
- { "tas5711", (kernel_ulong_t) &tas5711_chip },
- { "tas5717", (kernel_ulong_t) &tas5717_chip },
- { "tas5719", (kernel_ulong_t) &tas5717_chip },
- { "tas5721", (kernel_ulong_t) &tas5721_chip },
- { "tas5733", (kernel_ulong_t) &tas5733_chip },
- { "tas5753", (kernel_ulong_t) &tas5753_chip },
+ { .name = "tas5707", .driver_data = (kernel_ulong_t)&tas5707_chip },
+ { .name = "tas5711", .driver_data = (kernel_ulong_t)&tas5711_chip },
+ { .name = "tas5717", .driver_data = (kernel_ulong_t)&tas5717_chip },
+ { .name = "tas5719", .driver_data = (kernel_ulong_t)&tas5717_chip },
+ { .name = "tas5721", .driver_data = (kernel_ulong_t)&tas5721_chip },
+ { .name = "tas5733", .driver_data = (kernel_ulong_t)&tas5733_chip },
+ { .name = "tas5753", .driver_data = (kernel_ulong_t)&tas5753_chip },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas571x_i2c_id);
diff --git a/sound/soc/codecs/tas5720.c b/sound/soc/codecs/tas5720.c
index 2dcdd0a4bf80..0bbcfaadf3f2 100644
--- a/sound/soc/codecs/tas5720.c
+++ b/sound/soc/codecs/tas5720.c
@@ -716,9 +716,9 @@ static struct snd_soc_dai_driver tas5720_dai[] = {
};
static const struct i2c_device_id tas5720_id[] = {
- { "tas5720", TAS5720 },
- { "tas5720a-q1", TAS5720A_Q1 },
- { "tas5722", TAS5722 },
+ { .name = "tas5720", .driver_data = TAS5720 },
+ { .name = "tas5720a-q1", .driver_data = TAS5720A_Q1 },
+ { .name = "tas5722", .driver_data = TAS5722 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas5720_id);
diff --git a/sound/soc/codecs/tas5805m.c b/sound/soc/codecs/tas5805m.c
index 867046b7aaa0..bcc8cab8d667 100644
--- a/sound/soc/codecs/tas5805m.c
+++ b/sound/soc/codecs/tas5805m.c
@@ -580,7 +580,7 @@ static void tas5805m_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id tas5805m_i2c_id[] = {
- { "tas5805m", },
+ { .name = "tas5805m" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas5805m_i2c_id);
diff --git a/sound/soc/codecs/tas6424.c b/sound/soc/codecs/tas6424.c
index 85ecc246896f..f5d50f8a1cfb 100644
--- a/sound/soc/codecs/tas6424.c
+++ b/sound/soc/codecs/tas6424.c
@@ -794,7 +794,7 @@ static void tas6424_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id tas6424_i2c_ids[] = {
- { "tas6424" },
+ { .name = "tas6424" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tas6424_i2c_ids);
diff --git a/sound/soc/codecs/tas675x.c b/sound/soc/codecs/tas675x.c
new file mode 100644
index 000000000000..82526362de7b
--- /dev/null
+++ b/sound/soc/codecs/tas675x.c
@@ -0,0 +1,2194 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * ALSA SoC Texas Instruments TAS67524 Quad-Channel Audio Amplifier
+ *
+ * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com/
+ * Author: Sen Wang <sen@ti.com>
+ */
+
+#include <linux/bitfield.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/gpio/consumer.h>
+#include <linux/regulator/consumer.h>
+#include <linux/delay.h>
+#include <linux/property.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/pm_runtime.h>
+#include <linux/iopoll.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/pcm_params.h>
+
+#include "tas675x.h"
+
+#define TAS675X_FAULT_CHECK_INTERVAL_MS 200
+
+enum tas675x_type {
+ TAS67524,
+};
+
+struct tas675x_reg_param {
+ u8 page;
+ u8 reg;
+ u32 val;
+};
+
+struct tas675x_priv {
+ struct device *dev;
+ struct regmap *regmap;
+ enum tas675x_type dev_type;
+ /* Custom regmap lock; protects writes across books */
+ struct mutex io_lock;
+
+ struct gpio_desc *pd_gpio;
+ struct gpio_desc *stby_gpio;
+ struct regulator_bulk_data supplies[2];
+ struct regulator *vbat;
+ bool fast_boot;
+
+ int audio_slot;
+ int llp_slot;
+ int vpredict_slot;
+ int isense_slot;
+ int bclk_offset;
+ int slot_width;
+ unsigned int tx_mask;
+
+ int gpio1_func;
+ int gpio2_func;
+
+ unsigned long active_playback_dais;
+ unsigned long active_capture_dais;
+ unsigned int rate;
+ unsigned int saved_rtldg_en;
+#define TAS675X_DSP_PARAM_NUM 2
+ struct tas675x_reg_param dsp_params[TAS675X_DSP_PARAM_NUM];
+
+ /* Fault monitor, disabled when Fault IRQ is used */
+ struct delayed_work fault_check_work;
+#define TAS675X_FAULT_REGS_NUM 9
+ unsigned int last_status[TAS675X_FAULT_REGS_NUM];
+};
+
+static const char * const tas675x_supply_names[] = {
+ "dvdd", /* Digital power supply */
+ "pvdd", /* Output powerstage supply */
+};
+
+/* Page 1 setup initialization defaults */
+static const struct reg_sequence tas675x_page1_init[] = {
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0xC8), 0x20), /* Charge pump clock */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0x2F), 0x90), /* VBAT idle */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0x29), 0x40), /* OC/CBC threshold */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0x2E), 0x0C), /* OC/CBC config */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0xC5), 0x02), /* OC/CBC config */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0xC6), 0x10), /* OC/CBC config */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0x1F), 0x20), /* OC/CBC config */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0x16), 0x01), /* OC/CBC config */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0x1E), 0x04), /* OC/CBC config */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0xC1), 0x00), /* CH1 DC fault */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0xC2), 0x04), /* CH2 DC fault */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0xC3), 0x00), /* CH3 DC fault */
+ REG_SEQ0(TAS675X_PAGE_REG(1, 0xC4), 0x00), /* CH4 DC fault */
+};
+
+static inline const char *tas675x_state_name(unsigned int state)
+{
+ switch (state & 0x0F) {
+ case TAS675X_STATE_DEEPSLEEP: return "DEEPSLEEP";
+ case TAS675X_STATE_LOAD_DIAG: return "LOAD_DIAG";
+ case TAS675X_STATE_SLEEP: return "SLEEP";
+ case TAS675X_STATE_HIZ: return "HIZ";
+ case TAS675X_STATE_PLAY: return "PLAY";
+ case TAS675X_STATE_FAULT: return "FAULT";
+ case TAS675X_STATE_AUTOREC: return "AUTOREC";
+ default: return "UNKNOWN";
+ }
+}
+
+static inline int tas675x_set_state_all(struct tas675x_priv *tas, u8 state)
+{
+ const struct reg_sequence seq[] = {
+ REG_SEQ0(TAS675X_STATE_CTRL_CH1_CH2_REG, state),
+ REG_SEQ0(TAS675X_STATE_CTRL_CH3_CH4_REG, state),
+ };
+
+ return regmap_multi_reg_write(tas->regmap, seq, ARRAY_SIZE(seq));
+}
+
+static inline int tas675x_select_book(struct regmap *regmap, u8 book)
+{
+ int ret;
+
+ /* Reset page to 0 before switching books */
+ ret = regmap_write(regmap, TAS675X_PAGE_CTRL_REG, 0x00);
+ if (!ret)
+ ret = regmap_write(regmap, TAS675X_BOOK_CTRL_REG, book);
+
+ return ret;
+}
+
+/* Raw I2C version of tas675x_select_book, must be called with io_lock held */
+static inline int __tas675x_select_book(struct tas675x_priv *tas, u8 book)
+{
+ struct i2c_client *client = to_i2c_client(tas->dev);
+ int ret;
+
+ /* Reset page to 0 before switching books */
+ ret = i2c_smbus_write_byte_data(client, TAS675X_PAGE_CTRL_REG, 0x00);
+ if (ret)
+ return ret;
+
+ return i2c_smbus_write_byte_data(client, TAS675X_BOOK_CTRL_REG, book);
+}
+
+static int tas675x_dsp_mem_write(struct tas675x_priv *tas, u8 page, u8 reg, u32 val)
+{
+ struct i2c_client *client = to_i2c_client(tas->dev);
+ u8 buf[4];
+ int ret;
+
+ /* DSP registers are 32 bit big-endian */
+ buf[0] = (val >> 24) & 0xFF;
+ buf[1] = (val >> 16) & 0xFF;
+ buf[2] = (val >> 8) & 0xFF;
+ buf[3] = val & 0xFF;
+
+ /*
+ * DSP regs in a different book, therefore block
+ * regmap access before completion.
+ */
+ mutex_lock(&tas->io_lock);
+
+ ret = __tas675x_select_book(tas, TAS675X_BOOK_DSP);
+ if (ret)
+ goto out;
+
+ ret = i2c_smbus_write_byte_data(client, TAS675X_PAGE_CTRL_REG, page);
+ if (ret)
+ goto out;
+
+ ret = i2c_smbus_write_i2c_block_data(client, reg, sizeof(buf), buf);
+
+out:
+ __tas675x_select_book(tas, TAS675X_BOOK_DEFAULT);
+ mutex_unlock(&tas->io_lock);
+
+ return ret;
+}
+
+static int tas675x_dsp_mem_read(struct tas675x_priv *tas, u8 page, u8 reg, u32 *val)
+{
+ struct i2c_client *client = to_i2c_client(tas->dev);
+ u8 buf[4];
+ int ret;
+
+ /*
+ * DSP regs in a different book, therefore block
+ * regmap access before completion.
+ */
+ mutex_lock(&tas->io_lock);
+
+ ret = __tas675x_select_book(tas, TAS675X_BOOK_DSP);
+ if (ret)
+ goto out;
+
+ ret = i2c_smbus_write_byte_data(client, TAS675X_PAGE_CTRL_REG, page);
+ if (ret)
+ goto out;
+
+ ret = i2c_smbus_read_i2c_block_data(client, reg, sizeof(buf), buf);
+ if (ret == sizeof(buf)) {
+ *val = (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ ret = 0;
+ } else if (ret >= 0) {
+ ret = -EIO;
+ }
+
+out:
+ __tas675x_select_book(tas, TAS675X_BOOK_DEFAULT);
+ mutex_unlock(&tas->io_lock);
+
+ return ret;
+}
+
+static const struct {
+ const char *name;
+ int val;
+} tas675x_gpio_func_map[] = {
+ /* Output functions */
+ { "low", TAS675X_GPIO_SEL_LOW },
+ { "auto-mute", TAS675X_GPIO_SEL_AUTO_MUTE_ALL },
+ { "auto-mute-ch4", TAS675X_GPIO_SEL_AUTO_MUTE_CH4 },
+ { "auto-mute-ch3", TAS675X_GPIO_SEL_AUTO_MUTE_CH3 },
+ { "auto-mute-ch2", TAS675X_GPIO_SEL_AUTO_MUTE_CH2 },
+ { "auto-mute-ch1", TAS675X_GPIO_SEL_AUTO_MUTE_CH1 },
+ { "sdout2", TAS675X_GPIO_SEL_SDOUT2 },
+ { "sdout1", TAS675X_GPIO_SEL_SDOUT1 },
+ { "warn", TAS675X_GPIO_SEL_WARN },
+ { "fault", TAS675X_GPIO_SEL_FAULT },
+ { "clock-sync", TAS675X_GPIO_SEL_CLOCK_SYNC },
+ { "invalid-clock", TAS675X_GPIO_SEL_INVALID_CLK },
+ { "high", TAS675X_GPIO_SEL_HIGH },
+ /* Input functions */
+ { "mute", TAS675X_GPIO_IN_MUTE },
+ { "phase-sync", TAS675X_GPIO_IN_PHASE_SYNC },
+ { "sdin2", TAS675X_GPIO_IN_SDIN2 },
+ { "deep-sleep", TAS675X_GPIO_IN_DEEP_SLEEP },
+ { "hiz", TAS675X_GPIO_IN_HIZ },
+ { "play", TAS675X_GPIO_IN_PLAY },
+ { "sleep", TAS675X_GPIO_IN_SLEEP },
+};
+
+static int tas675x_gpio_func_parse(struct device *dev, const char *propname)
+{
+ const char *str;
+ int i, ret;
+
+ ret = device_property_read_string(dev, propname, &str);
+ if (ret)
+ return -1;
+
+ for (i = 0; i < ARRAY_SIZE(tas675x_gpio_func_map); i++) {
+ if (!strcmp(str, tas675x_gpio_func_map[i].name))
+ return tas675x_gpio_func_map[i].val;
+ }
+
+ dev_warn(dev, "Invalid %s value '%s'\n", propname, str);
+ return -1;
+}
+
+static const struct {
+ unsigned int reg;
+ unsigned int mask;
+} tas675x_gpio_input_table[TAS675X_GPIO_IN_NUM] = {
+ [TAS675X_GPIO_IN_ID_MUTE] = {
+ TAS675X_GPIO_INPUT_MUTE_REG, TAS675X_GPIO_IN_MUTE_MASK },
+ [TAS675X_GPIO_IN_ID_PHASE_SYNC] = {
+ TAS675X_GPIO_INPUT_SYNC_REG, TAS675X_GPIO_IN_SYNC_MASK },
+ [TAS675X_GPIO_IN_ID_SDIN2] = {
+ TAS675X_GPIO_INPUT_SDIN2_REG, TAS675X_GPIO_IN_SDIN2_MASK },
+ [TAS675X_GPIO_IN_ID_DEEP_SLEEP] = {
+ TAS675X_GPIO_INPUT_SLEEP_HIZ_REG, TAS675X_GPIO_IN_DEEP_SLEEP_MASK },
+ [TAS675X_GPIO_IN_ID_HIZ] = {
+ TAS675X_GPIO_INPUT_SLEEP_HIZ_REG, TAS675X_GPIO_IN_HIZ_MASK },
+ [TAS675X_GPIO_IN_ID_PLAY] = {
+ TAS675X_GPIO_INPUT_PLAY_SLEEP_REG, TAS675X_GPIO_IN_PLAY_MASK },
+ [TAS675X_GPIO_IN_ID_SLEEP] = {
+ TAS675X_GPIO_INPUT_PLAY_SLEEP_REG, TAS675X_GPIO_IN_SLEEP_MASK },
+};
+
+static void tas675x_config_gpio_pin(struct regmap *regmap, int func_id,
+ unsigned int out_sel_reg,
+ unsigned int pin_idx,
+ unsigned int *gpio_ctrl)
+{
+ int id;
+
+ if (func_id < 0)
+ return;
+
+ if (func_id & TAS675X_GPIO_FUNC_INPUT) {
+ /* 3-bit mux: 0 = disabled, 0b1 = GPIO1, 0b10 = GPIO2 */
+ id = func_id & ~TAS675X_GPIO_FUNC_INPUT;
+ regmap_update_bits(regmap,
+ tas675x_gpio_input_table[id].reg,
+ tas675x_gpio_input_table[id].mask,
+ (pin_idx + 1) << __ffs(tas675x_gpio_input_table[id].mask));
+ } else {
+ /* Output GPIO, update selection register and enable bit */
+ regmap_write(regmap, out_sel_reg, func_id);
+ *gpio_ctrl |= pin_idx ? TAS675X_GPIO2_OUTPUT_EN : TAS675X_GPIO1_OUTPUT_EN;
+ }
+}
+
+static int tas675x_rtldg_thresh_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ /* threshold reg ranges up to 24bit */
+ uinfo->value.integer.max = 0x00FFFFFF;
+ return 0;
+}
+
+static int tas675x_set_rtldg_thresh(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp);
+ const struct tas675x_reg_param *t =
+ (const struct tas675x_reg_param *)kcontrol->private_value;
+ u32 val = ucontrol->value.integer.value[0];
+ int ret;
+
+ ret = tas675x_dsp_mem_write(tas, t->page, t->reg, val);
+
+ /* Cache the value */
+ if (!ret) {
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(tas->dsp_params); i++) {
+ if (tas->dsp_params[i].page == t->page &&
+ tas->dsp_params[i].reg == t->reg) {
+ tas->dsp_params[i].val = val;
+ break;
+ }
+ }
+ }
+
+ /* Return 1 to notify change, or propagate error */
+ return ret ? ret : 1;
+}
+
+static int tas675x_get_rtldg_thresh(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp);
+ const struct tas675x_reg_param *t =
+ (const struct tas675x_reg_param *)kcontrol->private_value;
+ u32 val = 0;
+ int ret;
+
+ ret = tas675x_dsp_mem_read(tas, t->page, t->reg, &val);
+ if (!ret)
+ ucontrol->value.integer.value[0] = val;
+
+ return ret;
+}
+
+static const struct tas675x_reg_param tas675x_dsp_defaults[] = {
+ [TAS675X_DSP_PARAM_ID_OL_THRESH] = {
+ TAS675X_DSP_PAGE_RTLDG, TAS675X_DSP_RTLDG_OL_THRESH_REG },
+ [TAS675X_DSP_PARAM_ID_SL_THRESH] = {
+ TAS675X_DSP_PAGE_RTLDG, TAS675X_DSP_RTLDG_SL_THRESH_REG },
+};
+
+static_assert(ARRAY_SIZE(tas675x_dsp_defaults) == TAS675X_DSP_PARAM_NUM);
+
+static int tas675x_set_dcldg_trigger(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp);
+ unsigned int state, state34;
+ int ret;
+
+ if (!ucontrol->value.integer.value[0])
+ return 0;
+
+ if (snd_soc_component_active(comp))
+ return -EBUSY;
+
+ ret = pm_runtime_resume_and_get(tas->dev);
+ if (ret < 0)
+ return ret;
+
+ /*
+ * Abort automatic DC LDG retry loops (startup or init-after-fault)
+ * and clear faults before manual diagnostics.
+ */
+ regmap_update_bits(tas->regmap, TAS675X_DC_LDG_CTRL_REG,
+ TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT,
+ TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT);
+ regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR);
+
+ /* Wait for LOAD_DIAG to exit */
+ ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH1_CH2_REG,
+ state, (state & 0x0F) != TAS675X_STATE_LOAD_DIAG &&
+ (state >> 4) != TAS675X_STATE_LOAD_DIAG,
+ TAS675X_POLL_INTERVAL_US,
+ TAS675X_STATE_TRANSITION_TIMEOUT_US);
+ ret |= regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH3_CH4_REG,
+ state34, (state34 & 0x0F) != TAS675X_STATE_LOAD_DIAG &&
+ (state34 >> 4) != TAS675X_STATE_LOAD_DIAG,
+ TAS675X_POLL_INTERVAL_US,
+ TAS675X_STATE_TRANSITION_TIMEOUT_US);
+ if (ret) {
+ dev_err(tas->dev,
+ "DC LDG: abort timeout (CH1/2=0x%02x [%s/%s], CH3/4=0x%02x [%s/%s])\n",
+ state, tas675x_state_name(state), tas675x_state_name(state >> 4),
+ state34, tas675x_state_name(state34), tas675x_state_name(state34 >> 4));
+ goto out_restore_ldg_ctrl;
+ }
+
+ /* Transition to HIZ state */
+ ret = tas675x_set_state_all(tas, TAS675X_STATE_HIZ_BOTH);
+ if (ret)
+ goto out_restore_ldg_ctrl;
+
+ /* Set LOAD_DIAG state for manual DC LDG */
+ ret = tas675x_set_state_all(tas, TAS675X_STATE_LOAD_DIAG_BOTH);
+ if (ret)
+ goto out_restore_ldg_ctrl;
+
+ /* Wait for device to transition to LOAD_DIAG state */
+ ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH1_CH2_REG,
+ state, state == TAS675X_STATE_LOAD_DIAG_BOTH,
+ TAS675X_POLL_INTERVAL_US,
+ TAS675X_STATE_TRANSITION_TIMEOUT_US);
+ ret |= regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH3_CH4_REG,
+ state34, state34 == TAS675X_STATE_LOAD_DIAG_BOTH,
+ TAS675X_POLL_INTERVAL_US,
+ TAS675X_STATE_TRANSITION_TIMEOUT_US);
+ if (ret) {
+ dev_err(tas->dev,
+ "DC LDG: LOAD_DIAG timeout (CH1/2=0x%02x [%s/%s], CH3/4=0x%02x [%s/%s])\n",
+ state, tas675x_state_name(state), tas675x_state_name(state >> 4),
+ state34, tas675x_state_name(state34), tas675x_state_name(state34 >> 4));
+ goto out_restore_hiz;
+ }
+
+ /* Clear ABORT and BYPASS bits to enable manual DC LDG */
+ ret = regmap_update_bits(tas->regmap, TAS675X_DC_LDG_CTRL_REG,
+ TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT,
+ 0);
+ if (ret)
+ goto out_restore_hiz;
+
+ dev_dbg(tas->dev, "DC LDG: Started\n");
+
+ /* Poll all channels for SLEEP state */
+ ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH1_CH2_REG,
+ state, state == TAS675X_STATE_SLEEP_BOTH,
+ TAS675X_POLL_INTERVAL_US,
+ TAS675X_DC_LDG_TIMEOUT_US);
+ ret |= regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH3_CH4_REG,
+ state34, state34 == TAS675X_STATE_SLEEP_BOTH,
+ TAS675X_POLL_INTERVAL_US,
+ TAS675X_DC_LDG_TIMEOUT_US);
+ if (ret) {
+ dev_err(tas->dev,
+ "DC LDG: SLEEP timeout (CH1/2=0x%02x [%s/%s], CH3/4=0x%02x [%s/%s])\n",
+ state, tas675x_state_name(state), tas675x_state_name(state >> 4),
+ state34, tas675x_state_name(state34), tas675x_state_name(state34 >> 4));
+ goto out_restore_hiz;
+ }
+
+ dev_dbg(tas->dev, "DC LDG: Completed successfully (CH1/2=0x%02x, CH3/4=0x%02x)\n",
+ state, state34);
+
+out_restore_hiz:
+ tas675x_set_state_all(tas, TAS675X_STATE_HIZ_BOTH);
+
+out_restore_ldg_ctrl:
+ regmap_update_bits(tas->regmap, TAS675X_DC_LDG_CTRL_REG,
+ TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT,
+ 0);
+
+ pm_runtime_mark_last_busy(tas->dev);
+ pm_runtime_put_autosuspend(tas->dev);
+
+ return ret;
+}
+
+static int tas675x_set_acldg_trigger(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp);
+ unsigned int state, state34;
+ int ret;
+
+ if (!ucontrol->value.integer.value[0])
+ return 0;
+
+ if (snd_soc_component_active(comp))
+ return -EBUSY;
+
+ ret = pm_runtime_resume_and_get(tas->dev);
+ if (ret < 0)
+ return ret;
+
+ /* AC Load Diagnostics requires SLEEP state */
+ ret = tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH);
+ if (ret) {
+ dev_err(tas->dev, "AC LDG: Failed to set SLEEP state: %d\n", ret);
+ goto out;
+ }
+
+ /* Start AC LDG on all 4 channels (0x0F) */
+ ret = regmap_write(tas->regmap, TAS675X_AC_LDG_CTRL_REG, 0x0F);
+ if (ret) {
+ dev_err(tas->dev, "AC LDG: Failed to start: %d\n", ret);
+ goto out;
+ }
+
+ dev_dbg(tas->dev, "AC LDG: Started\n");
+
+ /* Poll all channels for SLEEP state */
+ ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH1_CH2_REG,
+ state, (state == TAS675X_STATE_SLEEP_BOTH),
+ TAS675X_POLL_INTERVAL_US,
+ TAS675X_AC_LDG_TIMEOUT_US);
+ if (ret) {
+ dev_err(tas->dev,
+ "AC LDG: CH1/CH2 timeout: %d (state=0x%02x [%s/%s])\n",
+ ret, state, tas675x_state_name(state),
+ tas675x_state_name(state >> 4));
+ regmap_write(tas->regmap, TAS675X_AC_LDG_CTRL_REG, 0x00);
+ goto out;
+ }
+
+ ret = regmap_read_poll_timeout(tas->regmap, TAS675X_STATE_REPORT_CH3_CH4_REG,
+ state34, (state34 == TAS675X_STATE_SLEEP_BOTH),
+ TAS675X_POLL_INTERVAL_US,
+ TAS675X_AC_LDG_TIMEOUT_US);
+ if (ret) {
+ dev_err(tas->dev,
+ "AC LDG: CH3/CH4 timeout: %d (state=0x%02x [%s/%s])\n",
+ ret, state34, tas675x_state_name(state34),
+ tas675x_state_name(state34 >> 4));
+ regmap_write(tas->regmap, TAS675X_AC_LDG_CTRL_REG, 0x00);
+ goto out;
+ }
+
+ dev_dbg(tas->dev, "AC LDG: Completed successfully (CH1/2=0x%02x, CH3/4=0x%02x)\n",
+ state, state34);
+ regmap_write(tas->regmap, TAS675X_AC_LDG_CTRL_REG, 0x00);
+
+out:
+ pm_runtime_mark_last_busy(tas->dev);
+ pm_runtime_put_autosuspend(tas->dev);
+
+ return ret;
+}
+
+static int tas675x_rtldg_impedance_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 0xFFFF;
+ return 0;
+}
+
+static int tas675x_get_rtldg_impedance(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp);
+ unsigned int msb_reg = (unsigned int)kcontrol->private_value;
+ u8 buf[2];
+ int ret;
+
+ ret = regmap_bulk_read(tas->regmap, msb_reg, buf, 2);
+ if (ret)
+ return ret;
+
+ ucontrol->value.integer.value[0] = (buf[0] << 8) | buf[1];
+ return 0;
+}
+
+static int tas675x_dc_resistance_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ /* 10-bit: 2-bit MSB + 8-bit LSB, 0.1 ohm/code, 0-102.3 ohm */
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1023;
+ return 0;
+}
+
+static int tas675x_get_dc_resistance(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct tas675x_priv *tas = snd_soc_component_get_drvdata(comp);
+ unsigned int lsb_reg = (unsigned int)kcontrol->private_value;
+ unsigned int msb, lsb, shift;
+ int ret;
+
+ ret = regmap_read(tas->regmap, TAS675X_DC_LDG_DCR_MSB_REG, &msb);
+ if (ret)
+ return ret;
+
+ ret = regmap_read(tas->regmap, lsb_reg, &lsb);
+ if (ret)
+ return ret;
+
+ /* 2-bit MSB: CH1=[7:6], CH2=[5:4], CH3=[3:2], CH4=[1:0] */
+ shift = 6 - (lsb_reg - TAS675X_CH1_DC_LDG_DCR_LSB_REG) * 2;
+ msb = (msb >> shift) & 0x3;
+
+ ucontrol->value.integer.value[0] = (msb << 8) | lsb;
+ return 0;
+}
+
+/* Counterparts with read-only access */
+#define SOC_SINGLE_RO(xname, xreg, xshift, xmax) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = xname, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .info = snd_soc_info_volsw, \
+ .get = snd_soc_get_volsw, \
+ .private_value = SOC_SINGLE_VALUE(xreg, xshift, 0, xmax, 0, 0) }
+#define SOC_DC_RESIST_RO(xname, xlsb_reg) \
+{ .name = xname, \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .info = tas675x_dc_resistance_info, \
+ .get = tas675x_get_dc_resistance, \
+ .private_value = (xlsb_reg) }
+#define SOC_RTLDG_IMP_RO(xname, xreg) \
+{ .name = xname, \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
+ .info = tas675x_rtldg_impedance_info, \
+ .get = tas675x_get_rtldg_impedance, \
+ .private_value = (xreg) }
+
+#define SOC_DSP_THRESH_EXT(xname, xthresh) \
+{ .name = xname, \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .info = tas675x_rtldg_thresh_info, \
+ .get = tas675x_get_rtldg_thresh, \
+ .put = tas675x_set_rtldg_thresh, \
+ .private_value = (unsigned long)&(xthresh) }
+
+/*
+ * DAC digital volumes. From -103 to 0 dB in 0.5 dB steps, -103.5 dB means mute.
+ * DAC analog gain. From -15.5 to 0 dB in 0.5 dB steps, no mute.
+ */
+static const DECLARE_TLV_DB_SCALE(tas675x_dig_vol_tlv, -10350, 50, 1);
+static const DECLARE_TLV_DB_SCALE(tas675x_ana_gain_tlv, -1550, 50, 0);
+
+static const char * const tas675x_ss_texts[] = {
+ "Disabled", "Triangle", "Random", "Triangle and Random"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ss_enum, TAS675X_SS_CTRL_REG, 0, tas675x_ss_texts);
+
+static const char * const tas675x_ss_tri_range_texts[] = {
+ "6.5%", "13.5%", "5%", "10%"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ss_tri_range_enum,
+ TAS675X_SS_RANGE_CTRL_REG, 0,
+ tas675x_ss_tri_range_texts);
+
+static const char * const tas675x_ss_rdm_range_texts[] = {
+ "0.83%", "2.50%", "5.83%", "12.50%", "25.83%"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ss_rdm_range_enum,
+ TAS675X_SS_RANGE_CTRL_REG, 4,
+ tas675x_ss_rdm_range_texts);
+
+static const char * const tas675x_ss_rdm_dwell_texts[] = {
+ "1/FSS to 2/FSS", "1/FSS to 4/FSS", "1/FSS to 8/FSS", "1/FSS to 15/FSS"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ss_rdm_dwell_enum,
+ TAS675X_SS_RANGE_CTRL_REG, 2,
+ tas675x_ss_rdm_dwell_texts);
+
+static const char * const tas675x_oc_limit_texts[] = {
+ "Level 4", "Level 3", "Level 2", "Level 1"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_oc_limit_enum, TAS675X_CURRENT_LIMIT_CTRL_REG,
+ 0, tas675x_oc_limit_texts);
+
+static const char * const tas675x_otw_texts[] = {
+ "Disabled", ">95C", ">110C", ">125C", ">135C", ">145C", ">155C", ">165C"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ch1_otw_enum,
+ TAS675X_OTW_CTRL_CH1_CH2_REG, 4,
+ tas675x_otw_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ch2_otw_enum,
+ TAS675X_OTW_CTRL_CH1_CH2_REG, 0,
+ tas675x_otw_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ch3_otw_enum,
+ TAS675X_OTW_CTRL_CH3_CH4_REG, 4,
+ tas675x_otw_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ch4_otw_enum,
+ TAS675X_OTW_CTRL_CH3_CH4_REG, 0,
+ tas675x_otw_texts);
+
+static const char * const tas675x_dc_ldg_sl_texts[] = {
+ "0.5 Ohm", "1 Ohm", "1.5 Ohm", "2 Ohm", "2.5 Ohm",
+ "3 Ohm", "3.5 Ohm", "4 Ohm", "4.5 Ohm", "5 Ohm"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ch1_dc_ldg_sl_enum,
+ TAS675X_DC_LDG_SL_CH1_CH2_CTRL_REG, 4,
+ tas675x_dc_ldg_sl_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ch2_dc_ldg_sl_enum,
+ TAS675X_DC_LDG_SL_CH1_CH2_CTRL_REG, 0,
+ tas675x_dc_ldg_sl_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ch3_dc_ldg_sl_enum,
+ TAS675X_DC_LDG_SL_CH3_CH4_CTRL_REG, 4,
+ tas675x_dc_ldg_sl_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ch4_dc_ldg_sl_enum,
+ TAS675X_DC_LDG_SL_CH3_CH4_CTRL_REG, 0,
+ tas675x_dc_ldg_sl_texts);
+
+static const char * const tas675x_dc_slol_ramp_texts[] = {
+ "15 ms", "30 ms", "10 ms", "20 ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_dc_slol_ramp_enum,
+ TAS675X_DC_LDG_TIME_CTRL_REG, 6,
+ tas675x_dc_slol_ramp_texts);
+
+static const char * const tas675x_dc_slol_settling_texts[] = {
+ "10 ms", "5 ms", "20 ms", "15 ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_dc_slol_settling_enum,
+ TAS675X_DC_LDG_TIME_CTRL_REG, 4,
+ tas675x_dc_slol_settling_texts);
+
+static const char * const tas675x_dc_s2pg_ramp_texts[] = {
+ "5 ms", "2.5 ms", "10 ms", "15 ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_dc_s2pg_ramp_enum,
+ TAS675X_DC_LDG_TIME_CTRL_REG, 2,
+ tas675x_dc_s2pg_ramp_texts);
+
+static const char * const tas675x_dc_s2pg_settling_texts[] = {
+ "10 ms", "5 ms", "20 ms", "30 ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_dc_s2pg_settling_enum,
+ TAS675X_DC_LDG_TIME_CTRL_REG, 0,
+ tas675x_dc_s2pg_settling_texts);
+
+static const char * const tas675x_dsp_mode_texts[] = {
+ "Normal", "LLP", "FFLP"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_dsp_mode_enum,
+ TAS675X_LL_EN_REG, 0,
+ tas675x_dsp_mode_texts);
+
+static const char * const tas675x_ana_ramp_texts[] = {
+ "15us", "60us", "200us", "400us"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ana_ramp_enum,
+ TAS675X_ANALOG_GAIN_RAMP_CTRL_REG, 2,
+ tas675x_ana_ramp_texts);
+
+static const char * const tas675x_ramp_rate_texts[] = {
+ "4 FS", "16 FS", "32 FS", "Instant"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ramp_down_rate_enum,
+ TAS675X_DIG_VOL_RAMP_CTRL_REG, 6,
+ tas675x_ramp_rate_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ramp_up_rate_enum,
+ TAS675X_DIG_VOL_RAMP_CTRL_REG, 2,
+ tas675x_ramp_rate_texts);
+
+static const char * const tas675x_ramp_step_texts[] = {
+ "4dB", "2dB", "1dB", "0.5dB"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ramp_down_step_enum,
+ TAS675X_DIG_VOL_RAMP_CTRL_REG, 4,
+ tas675x_ramp_step_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ramp_up_step_enum,
+ TAS675X_DIG_VOL_RAMP_CTRL_REG, 0,
+ tas675x_ramp_step_texts);
+
+static const char * const tas675x_vol_combine_ch12_texts[] = {
+ "Independent", "CH2 follows CH1", "CH1 follows CH2"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_vol_combine_ch12_enum,
+ TAS675X_DIG_VOL_COMBINE_CTRL_REG, 0,
+ tas675x_vol_combine_ch12_texts);
+
+static const char * const tas675x_vol_combine_ch34_texts[] = {
+ "Independent", "CH4 follows CH3", "CH3 follows CH4"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_vol_combine_ch34_enum,
+ TAS675X_DIG_VOL_COMBINE_CTRL_REG, 2,
+ tas675x_vol_combine_ch34_texts);
+
+static const char * const tas675x_auto_mute_time_texts[] = {
+ "11.5ms", "53ms", "106.5ms", "266.5ms",
+ "535ms", "1065ms", "2665ms", "5330ms"
+};
+
+static SOC_ENUM_SINGLE_DECL(tas675x_ch1_mute_time_enum,
+ TAS675X_AUTO_MUTE_TIMING_CH1_CH2_REG, 4,
+ tas675x_auto_mute_time_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ch2_mute_time_enum,
+ TAS675X_AUTO_MUTE_TIMING_CH1_CH2_REG, 0,
+ tas675x_auto_mute_time_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ch3_mute_time_enum,
+ TAS675X_AUTO_MUTE_TIMING_CH3_CH4_REG, 4,
+ tas675x_auto_mute_time_texts);
+static SOC_ENUM_SINGLE_DECL(tas675x_ch4_mute_time_enum,
+ TAS675X_AUTO_MUTE_TIMING_CH3_CH4_REG, 0,
+ tas675x_auto_mute_time_texts);
+
+/*
+ * ALSA Mixer Controls
+ *
+ * For detailed documentation of each control see:
+ * Documentation/sound/codecs/tas675x.rst
+ */
+static const struct snd_kcontrol_new tas675x_snd_controls[] = {
+ /* Volume & Gain Control */
+ SOC_DOUBLE_R_TLV("Analog Playback Volume", TAS675X_ANALOG_GAIN_CH1_CH2_REG,
+ TAS675X_ANALOG_GAIN_CH3_CH4_REG, 1, 0x1F, 1, tas675x_ana_gain_tlv),
+ SOC_ENUM("Analog Gain Ramp Step", tas675x_ana_ramp_enum),
+ SOC_SINGLE_RANGE_TLV("CH1 Digital Playback Volume",
+ TAS675X_DIG_VOL_CH1_REG, 0, 0x30, 0xFF, 1,
+ tas675x_dig_vol_tlv),
+ SOC_SINGLE_RANGE_TLV("CH2 Digital Playback Volume",
+ TAS675X_DIG_VOL_CH2_REG, 0, 0x30, 0xFF, 1,
+ tas675x_dig_vol_tlv),
+ SOC_SINGLE_RANGE_TLV("CH3 Digital Playback Volume",
+ TAS675X_DIG_VOL_CH3_REG, 0, 0x30, 0xFF, 1,
+ tas675x_dig_vol_tlv),
+ SOC_SINGLE_RANGE_TLV("CH4 Digital Playback Volume",
+ TAS675X_DIG_VOL_CH4_REG, 0, 0x30, 0xFF, 1,
+ tas675x_dig_vol_tlv),
+ SOC_ENUM("Volume Ramp Down Rate", tas675x_ramp_down_rate_enum),
+ SOC_ENUM("Volume Ramp Down Step", tas675x_ramp_down_step_enum),
+ SOC_ENUM("Volume Ramp Up Rate", tas675x_ramp_up_rate_enum),
+ SOC_ENUM("Volume Ramp Up Step", tas675x_ramp_up_step_enum),
+ SOC_ENUM("CH1/2 Volume Combine", tas675x_vol_combine_ch12_enum),
+ SOC_ENUM("CH3/4 Volume Combine", tas675x_vol_combine_ch34_enum),
+
+ /* Auto Mute & Silence Detection */
+ SOC_SINGLE("CH1 Auto Mute Switch", TAS675X_AUTO_MUTE_EN_REG, 0, 1, 0),
+ SOC_SINGLE("CH2 Auto Mute Switch", TAS675X_AUTO_MUTE_EN_REG, 1, 1, 0),
+ SOC_SINGLE("CH3 Auto Mute Switch", TAS675X_AUTO_MUTE_EN_REG, 2, 1, 0),
+ SOC_SINGLE("CH4 Auto Mute Switch", TAS675X_AUTO_MUTE_EN_REG, 3, 1, 0),
+ SOC_SINGLE("Auto Mute Combine Switch", TAS675X_AUTO_MUTE_EN_REG, 4, 1, 0),
+ SOC_ENUM("CH1 Auto Mute Time", tas675x_ch1_mute_time_enum),
+ SOC_ENUM("CH2 Auto Mute Time", tas675x_ch2_mute_time_enum),
+ SOC_ENUM("CH3 Auto Mute Time", tas675x_ch3_mute_time_enum),
+ SOC_ENUM("CH4 Auto Mute Time", tas675x_ch4_mute_time_enum),
+
+ /* Clock & EMI Management */
+ SOC_ENUM("Spread Spectrum Mode", tas675x_ss_enum),
+ SOC_ENUM("SS Triangle Range", tas675x_ss_tri_range_enum),
+ SOC_ENUM("SS Random Range", tas675x_ss_rdm_range_enum),
+ SOC_ENUM("SS Random Dwell Range", tas675x_ss_rdm_dwell_enum),
+ SOC_SINGLE("SS Triangle Dwell Min", TAS675X_SS_DWELL_CTRL_REG, 4, 15, 0),
+ SOC_SINGLE("SS Triangle Dwell Max", TAS675X_SS_DWELL_CTRL_REG, 0, 15, 0),
+
+ /* Hardware Protection */
+ SOC_SINGLE("OTSD Auto Recovery Switch", TAS675X_OTSD_RECOVERY_EN_REG, 1, 1, 0),
+ SOC_ENUM("Overcurrent Limit Level", tas675x_oc_limit_enum),
+ SOC_ENUM("CH1 OTW Threshold", tas675x_ch1_otw_enum),
+ SOC_ENUM("CH2 OTW Threshold", tas675x_ch2_otw_enum),
+ SOC_ENUM("CH3 OTW Threshold", tas675x_ch3_otw_enum),
+ SOC_ENUM("CH4 OTW Threshold", tas675x_ch4_otw_enum),
+
+ /* DSP Signal Path & Mode */
+ SOC_ENUM("DSP Signal Path Mode", tas675x_dsp_mode_enum),
+
+ /* DC Load Diagnostics */
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "DC LDG Trigger",
+ .access = SNDRV_CTL_ELEM_ACCESS_WRITE,
+ .info = snd_ctl_boolean_mono_info,
+ .put = tas675x_set_dcldg_trigger,
+ },
+ SOC_SINGLE("DC LDG Auto Diagnostics Switch", TAS675X_DC_LDG_CTRL_REG, 0, 1, 1),
+ SOC_SINGLE("CH1 LO LDG Switch", TAS675X_DC_LDG_LO_CTRL_REG, 3, 1, 0),
+ SOC_SINGLE("CH2 LO LDG Switch", TAS675X_DC_LDG_LO_CTRL_REG, 2, 1, 0),
+ SOC_SINGLE("CH3 LO LDG Switch", TAS675X_DC_LDG_LO_CTRL_REG, 1, 1, 0),
+ SOC_SINGLE("CH4 LO LDG Switch", TAS675X_DC_LDG_LO_CTRL_REG, 0, 1, 0),
+ SOC_ENUM("DC LDG SLOL Ramp Time", tas675x_dc_slol_ramp_enum),
+ SOC_ENUM("DC LDG SLOL Settling Time", tas675x_dc_slol_settling_enum),
+ SOC_ENUM("DC LDG S2PG Ramp Time", tas675x_dc_s2pg_ramp_enum),
+ SOC_ENUM("DC LDG S2PG Settling Time", tas675x_dc_s2pg_settling_enum),
+ SOC_ENUM("CH1 DC LDG SL Threshold", tas675x_ch1_dc_ldg_sl_enum),
+ SOC_ENUM("CH2 DC LDG SL Threshold", tas675x_ch2_dc_ldg_sl_enum),
+ SOC_ENUM("CH3 DC LDG SL Threshold", tas675x_ch3_dc_ldg_sl_enum),
+ SOC_ENUM("CH4 DC LDG SL Threshold", tas675x_ch4_dc_ldg_sl_enum),
+ SOC_SINGLE_RO("DC LDG Result", TAS675X_DC_LDG_RESULT_REG, 0, 0xFF),
+ SOC_SINGLE_RO("CH1 DC LDG Report", TAS675X_DC_LDG_REPORT_CH1_CH2_REG, 4, 0x0F),
+ SOC_SINGLE_RO("CH2 DC LDG Report", TAS675X_DC_LDG_REPORT_CH1_CH2_REG, 0, 0x0F),
+ SOC_SINGLE_RO("CH3 DC LDG Report", TAS675X_DC_LDG_REPORT_CH3_CH4_REG, 4, 0x0F),
+ SOC_SINGLE_RO("CH4 DC LDG Report", TAS675X_DC_LDG_REPORT_CH3_CH4_REG, 0, 0x0F),
+ SOC_SINGLE_RO("CH1 LO LDG Report", TAS675X_DC_LDG_RESULT_REG, 7, 1),
+ SOC_SINGLE_RO("CH2 LO LDG Report", TAS675X_DC_LDG_RESULT_REG, 6, 1),
+ SOC_SINGLE_RO("CH3 LO LDG Report", TAS675X_DC_LDG_RESULT_REG, 5, 1),
+ SOC_SINGLE_RO("CH4 LO LDG Report", TAS675X_DC_LDG_RESULT_REG, 4, 1),
+ SOC_DC_RESIST_RO("CH1 DC Resistance", TAS675X_CH1_DC_LDG_DCR_LSB_REG),
+ SOC_DC_RESIST_RO("CH2 DC Resistance", TAS675X_CH2_DC_LDG_DCR_LSB_REG),
+ SOC_DC_RESIST_RO("CH3 DC Resistance", TAS675X_CH3_DC_LDG_DCR_LSB_REG),
+ SOC_DC_RESIST_RO("CH4 DC Resistance", TAS675X_CH4_DC_LDG_DCR_LSB_REG),
+
+ /* AC Load Diagnostics */
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "AC LDG Trigger",
+ .access = SNDRV_CTL_ELEM_ACCESS_WRITE,
+ .info = snd_ctl_boolean_mono_info,
+ .put = tas675x_set_acldg_trigger,
+ },
+ SOC_SINGLE("AC LDG Gain", TAS675X_AC_LDG_CTRL_REG, 4, 1, 0),
+ SOC_SINGLE("AC LDG Test Frequency", TAS675X_AC_LDG_FREQ_CTRL_REG, 0, 0xFF, 0),
+ SOC_SINGLE_RO("CH1 AC LDG Real", TAS675X_AC_LDG_REPORT_CH1_R_REG, 0, 0xFF),
+ SOC_SINGLE_RO("CH1 AC LDG Imag", TAS675X_AC_LDG_REPORT_CH1_I_REG, 0, 0xFF),
+ SOC_SINGLE_RO("CH2 AC LDG Real", TAS675X_AC_LDG_REPORT_CH2_R_REG, 0, 0xFF),
+ SOC_SINGLE_RO("CH2 AC LDG Imag", TAS675X_AC_LDG_REPORT_CH2_I_REG, 0, 0xFF),
+ SOC_SINGLE_RO("CH3 AC LDG Real", TAS675X_AC_LDG_REPORT_CH3_R_REG, 0, 0xFF),
+ SOC_SINGLE_RO("CH3 AC LDG Imag", TAS675X_AC_LDG_REPORT_CH3_I_REG, 0, 0xFF),
+ SOC_SINGLE_RO("CH4 AC LDG Real", TAS675X_AC_LDG_REPORT_CH4_R_REG, 0, 0xFF),
+ SOC_SINGLE_RO("CH4 AC LDG Imag", TAS675X_AC_LDG_REPORT_CH4_I_REG, 0, 0xFF),
+
+ /* Temperature and Voltage Monitoring */
+ SOC_SINGLE_RO("PVDD Sense", TAS675X_PVDD_SENSE_REG, 0, 0xFF),
+ SOC_SINGLE_RO("Global Temperature", TAS675X_TEMP_GLOBAL_REG, 0, 0xFF),
+ SOC_SINGLE_RO("CH1 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 0, 7),
+ SOC_SINGLE_RO("CH2 Temperature Range", TAS675X_TEMP_CH1_CH2_REG, 3, 7),
+ SOC_SINGLE_RO("CH3 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 0, 7),
+ SOC_SINGLE_RO("CH4 Temperature Range", TAS675X_TEMP_CH3_CH4_REG, 3, 7),
+
+ /* Speaker Protection & Detection */
+ SOC_SINGLE("Tweeter Detection Switch", TAS675X_TWEETER_DETECT_CTRL_REG, 0, 1, 1),
+ SOC_SINGLE("Tweeter Detect Threshold", TAS675X_TWEETER_DETECT_THRESH_REG, 0, 0xFF, 0),
+ SOC_SINGLE_RO("CH1 Tweeter Detect Report", TAS675X_TWEETER_REPORT_REG, 3, 1),
+ SOC_SINGLE_RO("CH2 Tweeter Detect Report", TAS675X_TWEETER_REPORT_REG, 2, 1),
+ SOC_SINGLE_RO("CH3 Tweeter Detect Report", TAS675X_TWEETER_REPORT_REG, 1, 1),
+ SOC_SINGLE_RO("CH4 Tweeter Detect Report", TAS675X_TWEETER_REPORT_REG, 0, 1),
+
+ /*
+ * Unavailable in LLP, available in Normal & FFLP
+ */
+ SOC_SINGLE("Thermal Foldback Switch", TAS675X_DSP_CTRL_REG, 0, 1, 0),
+ SOC_SINGLE("PVDD Foldback Switch", TAS675X_DSP_CTRL_REG, 4, 1, 0),
+ SOC_SINGLE("DC Blocker Bypass Switch", TAS675X_DC_BLOCK_BYP_REG, 0, 1, 0),
+ SOC_SINGLE("Clip Detect Switch", TAS675X_CLIP_DETECT_CTRL_REG, 6, 1, 0),
+ SOC_SINGLE("Audio SDOUT Switch", TAS675X_DSP_CTRL_REG, 5, 1, 0),
+
+ /*
+ * Unavailable in both FFLP and LLP, Normal mode only
+ */
+ /* Real-Time Load Diagnostics */
+ SOC_SINGLE("CH1 RTLDG Switch", TAS675X_RTLDG_EN_REG, 3, 1, 0),
+ SOC_SINGLE("CH2 RTLDG Switch", TAS675X_RTLDG_EN_REG, 2, 1, 0),
+ SOC_SINGLE("CH3 RTLDG Switch", TAS675X_RTLDG_EN_REG, 1, 1, 0),
+ SOC_SINGLE("CH4 RTLDG Switch", TAS675X_RTLDG_EN_REG, 0, 1, 0),
+ SOC_SINGLE("RTLDG Clip Mask Switch", TAS675X_RTLDG_EN_REG, 4, 1, 0),
+ SOC_SINGLE("ISENSE Calibration Switch", TAS675X_ISENSE_CAL_REG, 3, 1, 0),
+ SOC_DSP_THRESH_EXT("RTLDG Open Load Threshold",
+ tas675x_dsp_defaults[TAS675X_DSP_PARAM_ID_OL_THRESH]),
+ SOC_DSP_THRESH_EXT("RTLDG Short Load Threshold",
+ tas675x_dsp_defaults[TAS675X_DSP_PARAM_ID_SL_THRESH]),
+ SOC_RTLDG_IMP_RO("CH1 RTLDG Impedance", TAS675X_CH1_RTLDG_IMP_MSB_REG),
+ SOC_RTLDG_IMP_RO("CH2 RTLDG Impedance", TAS675X_CH2_RTLDG_IMP_MSB_REG),
+ SOC_RTLDG_IMP_RO("CH3 RTLDG Impedance", TAS675X_CH3_RTLDG_IMP_MSB_REG),
+ SOC_RTLDG_IMP_RO("CH4 RTLDG Impedance", TAS675X_CH4_RTLDG_IMP_MSB_REG),
+};
+
+static const struct snd_kcontrol_new tas675x_audio_path_switch =
+ SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1);
+
+static const struct snd_kcontrol_new tas675x_anc_path_switch =
+ SOC_DAPM_SINGLE("Switch", SND_SOC_NOPM, 0, 1, 1);
+
+static const struct snd_soc_dapm_widget tas675x_dapm_widgets[] = {
+ SND_SOC_DAPM_SUPPLY("Analog Core", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SDOUT Vpredict", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SDOUT Isense", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_DAC("Audio DAC", "Playback", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("ANC DAC", "ANC Playback", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_ADC("Feedback ADC", "Feedback Capture", SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_SWITCH("Audio Path", SND_SOC_NOPM, 0, 0,
+ &tas675x_audio_path_switch),
+ SND_SOC_DAPM_SWITCH("ANC Path", SND_SOC_NOPM, 0, 0,
+ &tas675x_anc_path_switch),
+
+ /*
+ * Even though all channels are coupled in terms of power control,
+ * use logical outputs for each channel to allow independent routing
+ * and DAPM controls if needed.
+ */
+ SND_SOC_DAPM_OUTPUT("OUT_CH1"),
+ SND_SOC_DAPM_OUTPUT("OUT_CH2"),
+ SND_SOC_DAPM_OUTPUT("OUT_CH3"),
+ SND_SOC_DAPM_OUTPUT("OUT_CH4"),
+ SND_SOC_DAPM_INPUT("SPEAKER_LOAD"),
+};
+
+static const struct snd_soc_dapm_route tas675x_dapm_routes[] = {
+ { "Audio DAC", NULL, "Analog Core" },
+ { "Audio Path", "Switch", "Audio DAC" },
+ { "OUT_CH1", NULL, "Audio Path" },
+ { "OUT_CH2", NULL, "Audio Path" },
+ { "OUT_CH3", NULL, "Audio Path" },
+ { "OUT_CH4", NULL, "Audio Path" },
+
+ { "ANC DAC", NULL, "Analog Core" },
+ { "ANC Path", "Switch", "ANC DAC" },
+ { "OUT_CH1", NULL, "ANC Path" },
+ { "OUT_CH2", NULL, "ANC Path" },
+ { "OUT_CH3", NULL, "ANC Path" },
+ { "OUT_CH4", NULL, "ANC Path" },
+
+ { "Feedback ADC", NULL, "Analog Core" },
+ { "Feedback ADC", NULL, "SDOUT Vpredict" },
+ { "Feedback ADC", NULL, "SDOUT Isense" },
+ { "Feedback ADC", NULL, "SPEAKER_LOAD" },
+};
+
+static void tas675x_program_slot_offsets(struct tas675x_priv *tas,
+ int dai_id, int slot_width)
+{
+ int offset = 0;
+
+ switch (dai_id) {
+ case 0:
+ /* Standard Audio on SDIN */
+ if (tas->audio_slot >= 0)
+ offset = tas->audio_slot * slot_width;
+ else if (tas->tx_mask)
+ offset = __ffs(tas->tx_mask) * slot_width;
+ else
+ return;
+ offset += tas->bclk_offset;
+ regmap_update_bits(tas->regmap, TAS675X_SDIN_OFFSET_MSB_REG,
+ TAS675X_SDIN_AUDIO_OFF_MSB_MASK,
+ FIELD_PREP(TAS675X_SDIN_AUDIO_OFF_MSB_MASK, offset >> 8));
+ regmap_write(tas->regmap, TAS675X_SDIN_AUDIO_OFFSET_REG,
+ offset & 0xFF);
+ break;
+ case 1:
+ /*
+ * Low-Latency Playback on SDIN, **only** enabled in LLP mode
+ * and to be mixed with main audio before output amplification
+ * to achieve ANC/RNC.
+ */
+ if (tas->llp_slot >= 0)
+ offset = tas->llp_slot * slot_width;
+ else if (tas->tx_mask)
+ offset = __ffs(tas->tx_mask) * slot_width;
+ else
+ return;
+ offset += tas->bclk_offset;
+ regmap_update_bits(tas->regmap, TAS675X_SDIN_OFFSET_MSB_REG,
+ TAS675X_SDIN_LL_OFF_MSB_MASK,
+ FIELD_PREP(TAS675X_SDIN_LL_OFF_MSB_MASK, offset >> 8));
+ regmap_write(tas->regmap, TAS675X_SDIN_LL_OFFSET_REG,
+ offset & 0xFF);
+ break;
+ case 2:
+ /* SDOUT Data Output (Vpredict + Isense feedback) */
+ if (!tas->slot_width)
+ break;
+ if (tas->vpredict_slot >= 0) {
+ offset = tas->vpredict_slot * slot_width;
+ offset += tas->bclk_offset;
+ regmap_update_bits(tas->regmap, TAS675X_SDOUT_OFFSET_MSB_REG,
+ TAS675X_SDOUT_VP_OFF_MSB_MASK,
+ FIELD_PREP(TAS675X_SDOUT_VP_OFF_MSB_MASK, offset >> 8));
+ regmap_write(tas->regmap, TAS675X_VPREDICT_OFFSET_REG,
+ offset & 0xFF);
+ }
+ if (tas->isense_slot >= 0) {
+ offset = tas->isense_slot * slot_width;
+ offset += tas->bclk_offset;
+ regmap_update_bits(tas->regmap, TAS675X_SDOUT_OFFSET_MSB_REG,
+ TAS675X_SDOUT_IS_OFF_MSB_MASK,
+ FIELD_PREP(TAS675X_SDOUT_IS_OFF_MSB_MASK, offset >> 8));
+ regmap_write(tas->regmap, TAS675X_ISENSE_OFFSET_REG,
+ offset & 0xFF);
+ }
+ break;
+ }
+
+ if (offset > 511)
+ dev_warn(tas->dev,
+ "DAI %d slot offset %d exceeds 511 SCLK limit\n",
+ dai_id, offset);
+}
+
+static int tas675x_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 tas675x_priv *tas = snd_soc_component_get_drvdata(component);
+ unsigned int rate = params_rate(params);
+ u8 word_length;
+
+ /*
+ * Single clock domain: SDIN and SDOUT share one SCLK/FSYNC pair,
+ * so all active DAIs must use the same sample rate.
+ */
+ if ((READ_ONCE(tas->active_playback_dais) || READ_ONCE(tas->active_capture_dais)) &&
+ tas->rate && tas->rate != rate) {
+ dev_err(component->dev,
+ "Rate %u conflicts with active rate %u\n",
+ rate, tas->rate);
+ return -EINVAL;
+ }
+
+ switch (params_width(params)) {
+ case 16:
+ word_length = TAS675X_WL_16BIT;
+ break;
+ case 20:
+ word_length = TAS675X_WL_20BIT;
+ break;
+ case 24:
+ word_length = TAS675X_WL_24BIT;
+ break;
+ case 32:
+ word_length = TAS675X_WL_32BIT;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /*
+ * RTLDG is not supported above 96kHz. Auto-disable to
+ * prevent DSP overload and restore when rate drops back.
+ */
+ if (rate > 96000) {
+ unsigned int val;
+
+ regmap_read(component->regmap, TAS675X_RTLDG_EN_REG,
+ &val);
+ if (val & TAS675X_RTLDG_CH_EN_MASK) {
+ tas->saved_rtldg_en = val;
+ dev_dbg(component->dev,
+ "Sample rate %dHz > 96kHz: Auto-disabling RTLDG\n",
+ rate);
+ regmap_update_bits(component->regmap,
+ TAS675X_RTLDG_EN_REG,
+ TAS675X_RTLDG_CH_EN_MASK,
+ 0x00);
+ }
+ } else if (tas->saved_rtldg_en) {
+ unsigned int cur;
+
+ /*
+ * Respect overrides and only restore if RTLDG is still auto-disabled
+ */
+ regmap_read(component->regmap, TAS675X_RTLDG_EN_REG,
+ &cur);
+ if (!(cur & TAS675X_RTLDG_CH_EN_MASK)) {
+ dev_dbg(component->dev,
+ "Restoring RTLDG config after high-rate stream\n");
+ regmap_update_bits(component->regmap,
+ TAS675X_RTLDG_EN_REG,
+ TAS675X_RTLDG_CH_EN_MASK,
+ TAS675X_RTLDG_CH_EN_MASK &
+ tas->saved_rtldg_en);
+ }
+ tas->saved_rtldg_en = 0;
+ }
+
+ /* Set SDIN word length (audio path + low-latency path) */
+ regmap_update_bits(component->regmap, TAS675X_SDIN_CTRL_REG,
+ TAS675X_SDIN_WL_MASK,
+ FIELD_PREP(TAS675X_SDIN_AUDIO_WL_MASK, word_length) |
+ FIELD_PREP(TAS675X_SDIN_LL_WL_MASK, word_length));
+ } else {
+ /* Set SDOUT word length (VPREDICT + ISENSE) for capture */
+ regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG,
+ TAS675X_SDOUT_WL_MASK,
+ FIELD_PREP(TAS675X_SDOUT_VP_WL_MASK, word_length) |
+ FIELD_PREP(TAS675X_SDOUT_IS_WL_MASK, word_length));
+ }
+
+ tas675x_program_slot_offsets(tas, dai->id,
+ tas->slot_width ?: params_width(params));
+
+ tas->rate = rate;
+
+ return 0;
+}
+
+static int tas675x_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_component *component = dai->component;
+ struct tas675x_priv *tas = snd_soc_component_get_drvdata(component);
+ bool tdm_mode = false, i2s_mode = false;
+
+ /* Enforce Clocking Direction (Codec is strictly a consumer) */
+ switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
+ case SND_SOC_DAIFMT_BC_FC:
+ break;
+ default:
+ dev_err(component->dev, "Unsupported clock provider format\n");
+ return -EINVAL;
+ }
+
+ /* SCLK polarity: NB_NF or IB_NF only (no FSYNC inversion support) */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ regmap_update_bits(component->regmap, TAS675X_SCLK_INV_CTRL_REG,
+ TAS675X_SCLK_INV_MASK, 0x00);
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ regmap_update_bits(component->regmap, TAS675X_SCLK_INV_CTRL_REG,
+ TAS675X_SCLK_INV_MASK, TAS675X_SCLK_INV_MASK);
+ break;
+ default:
+ dev_err(component->dev, "Unsupported clock inversion\n");
+ return -EINVAL;
+ }
+
+ /* Configure Audio Format and TDM Enable */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ i2s_mode = true;
+ tas->bclk_offset = 0;
+ regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG,
+ TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK |
+ TAS675X_FS_PULSE_MASK,
+ TAS675X_SAP_FMT_I2S);
+ regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG,
+ TAS675X_SDOUT_SELECT_MASK,
+ TAS675X_SDOUT_SELECT_NON_TDM);
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ tas->bclk_offset = 0;
+ regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG,
+ TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK |
+ TAS675X_FS_PULSE_MASK,
+ TAS675X_SAP_FMT_RIGHT_J);
+ regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG,
+ TAS675X_SDOUT_SELECT_MASK,
+ TAS675X_SDOUT_SELECT_NON_TDM);
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ tas->bclk_offset = 0;
+ regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG,
+ TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK |
+ TAS675X_FS_PULSE_MASK,
+ TAS675X_SAP_FMT_LEFT_J);
+ regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG,
+ TAS675X_SDOUT_SELECT_MASK,
+ TAS675X_SDOUT_SELECT_NON_TDM);
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ tdm_mode = true;
+ tas->bclk_offset = 1;
+ regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG,
+ TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK |
+ TAS675X_FS_PULSE_MASK,
+ TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_TDM |
+ TAS675X_FS_PULSE_SHORT);
+ regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG,
+ TAS675X_SDOUT_SELECT_MASK,
+ TAS675X_SDOUT_SELECT_TDM_SDOUT1);
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ tdm_mode = true;
+ tas->bclk_offset = 0;
+ regmap_update_bits(component->regmap, TAS675X_AUDIO_IF_CTRL_REG,
+ TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_MASK |
+ TAS675X_FS_PULSE_MASK,
+ TAS675X_TDM_EN_BIT | TAS675X_SAP_FMT_TDM |
+ TAS675X_FS_PULSE_SHORT);
+ regmap_update_bits(component->regmap, TAS675X_SDOUT_CTRL_REG,
+ TAS675X_SDOUT_SELECT_MASK,
+ TAS675X_SDOUT_SELECT_TDM_SDOUT1);
+ break;
+ default:
+ dev_err(component->dev, "Unsupported DAI format\n");
+ return -EINVAL;
+ }
+
+ /* Setup Vpredict and Isense outputs */
+ if (dai->id == 2) {
+ unsigned int sdout_en = 0;
+
+ if (tdm_mode) {
+ /* TDM: Vpredict and Isense may coexist on separate slots */
+ if (tas->vpredict_slot >= 0)
+ sdout_en |= TAS675X_SDOUT_EN_VPREDICT;
+ if (tas->isense_slot >= 0)
+ sdout_en |= TAS675X_SDOUT_EN_ISENSE;
+ regmap_update_bits(component->regmap,
+ TAS675X_SDOUT_EN_REG,
+ TAS675X_SDOUT_EN_VPREDICT |
+ TAS675X_SDOUT_EN_ISENSE,
+ sdout_en);
+ if (tas->vpredict_slot >= 0 && tas->isense_slot >= 0 &&
+ abs(tas->vpredict_slot - tas->isense_slot) < 4)
+ dev_warn(component->dev,
+ "ti,vpredict-slot-no and ti,isense-slot-no overlaps (each occupies 4 consecutive slots)\n");
+ } else if (i2s_mode) {
+ /* I2S: only one source at a time; Vpredict takes priority */
+ if (tas->vpredict_slot >= 0)
+ sdout_en = TAS675X_SDOUT_NON_TDM_SEL_VPREDICT |
+ TAS675X_SDOUT_EN_NON_TDM_ALL;
+ else if (tas->isense_slot >= 0)
+ sdout_en = TAS675X_SDOUT_NON_TDM_SEL_ISENSE |
+ TAS675X_SDOUT_EN_NON_TDM_ALL;
+ regmap_update_bits(component->regmap,
+ TAS675X_SDOUT_EN_REG,
+ TAS675X_SDOUT_NON_TDM_SEL_MASK |
+ TAS675X_SDOUT_EN_NON_TDM_ALL,
+ sdout_en);
+ if (sdout_en &&
+ tas->gpio1_func != TAS675X_GPIO_SEL_SDOUT2 &&
+ tas->gpio2_func != TAS675X_GPIO_SEL_SDOUT2)
+ dev_warn(component->dev,
+ "sdout enabled in I2S mode but no GPIO configured as SDOUT2; Ch3/Ch4 will be absent\n");
+ }
+ }
+
+ return 0;
+}
+
+static int tas675x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
+ unsigned int rx_mask, int slots, int slot_width)
+{
+ struct tas675x_priv *tas = snd_soc_component_get_drvdata(dai->component);
+
+ if (slots == 0) {
+ tas->slot_width = 0;
+ tas->tx_mask = 0;
+ return 0;
+ }
+
+ /* No rx_mask as hardware does not support channel muxing for capture */
+ tas->slot_width = slot_width;
+ tas->tx_mask = tx_mask;
+ return 0;
+}
+
+static int tas675x_mute_stream(struct snd_soc_dai *dai, int mute, int direction)
+{
+ struct snd_soc_component *component = dai->component;
+ struct tas675x_priv *tas = snd_soc_component_get_drvdata(component);
+ unsigned int discard;
+ int ret;
+
+ if (direction == SNDRV_PCM_STREAM_CAPTURE) {
+ if (mute)
+ clear_bit(dai->id, &tas->active_capture_dais);
+ else
+ set_bit(dai->id, &tas->active_capture_dais);
+ return 0;
+ }
+
+ /*
+ * Track which playback DAIs are active.
+ * The TAS675x has two playback DAIs (main audio and LLP).
+ * Only transition to SLEEP when ALL are muted.
+ */
+ if (mute)
+ clear_bit(dai->id, &tas->active_playback_dais);
+ else
+ set_bit(dai->id, &tas->active_playback_dais);
+
+ /* Last playback stream */
+ if (mute && !READ_ONCE(tas->active_playback_dais)) {
+ ret = tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH);
+ regmap_read(tas->regmap, TAS675X_CLK_FAULT_LATCHED_REG, &discard);
+ return ret;
+ }
+
+ return tas675x_set_state_all(tas,
+ READ_ONCE(tas->active_playback_dais) ?
+ TAS675X_STATE_PLAY_BOTH :
+ TAS675X_STATE_SLEEP_BOTH);
+}
+
+static const struct snd_soc_dai_ops tas675x_dai_ops = {
+ .hw_params = tas675x_hw_params,
+ .set_fmt = tas675x_set_fmt,
+ .set_tdm_slot = tas675x_set_tdm_slot,
+ .mute_stream = tas675x_mute_stream,
+};
+
+static struct snd_soc_dai_driver tas675x_dais[] = {
+ {
+ .name = "tas675x-audio",
+ .id = 0,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 4,
+ .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
+ SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_LE |
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &tas675x_dai_ops,
+ },
+ /* Only available when Low Latency Path (LLP) is enabled */
+ {
+ .name = "tas675x-anc",
+ .id = 1,
+ .playback = {
+ .stream_name = "ANC Playback",
+ .channels_min = 2,
+ .channels_max = 4,
+ .rates = SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_LE |
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &tas675x_dai_ops,
+ },
+ {
+ .name = "tas675x-feedback",
+ .id = 2,
+ .capture = {
+ .stream_name = "Feedback Capture",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_LE |
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE,
+ },
+ .ops = &tas675x_dai_ops,
+ }
+};
+
+/*
+ * Enable regulators and release hardware reset GPIOs.
+ * The device is not I2C-accessible until this returns.
+ */
+static int tas675x_hw_enable(struct tas675x_priv *tas)
+{
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(tas->supplies), tas->supplies);
+ if (ret) {
+ dev_err(tas->dev, "Failed to enable regulators: %d\n", ret);
+ return ret;
+ }
+
+ if (!IS_ERR(tas->vbat)) {
+ ret = regulator_enable(tas->vbat);
+ if (ret) {
+ dev_err(tas->dev, "Failed to enable vbat: %d\n", ret);
+ regulator_bulk_disable(ARRAY_SIZE(tas->supplies), tas->supplies);
+ return ret;
+ }
+ }
+
+ if (tas->pd_gpio && tas->stby_gpio) {
+ /*
+ * Independent Pin Control
+ * Deassert PD first to boot digital, then STBY for analog.
+ */
+ /* Min 4ms digital boot wait */
+ gpiod_set_value_cansleep(tas->pd_gpio, 0);
+ usleep_range(4000, 5000);
+
+ /* ~2ms analog stabilization */
+ gpiod_set_value_cansleep(tas->stby_gpio, 0);
+ usleep_range(2000, 3000);
+ } else if (tas->pd_gpio) {
+ /*
+ * Simultaneous Pin Release
+ * STBY tied to PD or hardwired HIGH.
+ */
+ /* 6ms wait for simultaneous release transition */
+ gpiod_set_value_cansleep(tas->pd_gpio, 0);
+ usleep_range(6000, 7000);
+ } else {
+ /*
+ * PD hardwired, device in DEEP_SLEEP.
+ * Digital core already booted, I2C active. Deassert STBY
+ * to bring up the analog output stage.
+ */
+ /* ~2ms analog stabilization */
+ gpiod_set_value_cansleep(tas->stby_gpio, 0);
+ usleep_range(2000, 3000);
+ }
+
+ return 0;
+}
+
+static void tas675x_hw_disable(struct tas675x_priv *tas)
+{
+ if (tas->stby_gpio)
+ gpiod_set_value_cansleep(tas->stby_gpio, 1);
+
+ if (tas->pd_gpio)
+ gpiod_set_value_cansleep(tas->pd_gpio, 1);
+
+ /*
+ * Hold PD/STBY asserted for at least 10ms
+ * before removing PVDD, VBAT or DVDD.
+ */
+ usleep_range(10000, 11000);
+
+ if (!IS_ERR(tas->vbat))
+ regulator_disable(tas->vbat);
+
+ regulator_bulk_disable(ARRAY_SIZE(tas->supplies), tas->supplies);
+}
+
+/*
+ * Write device start-up defaults.
+ * Must be called after tas675x_hw_enable() and after regcache is enabled.
+ */
+static int tas675x_init_device(struct tas675x_priv *tas)
+{
+ struct regmap *regmap = tas->regmap;
+ unsigned int val;
+ int ret, i;
+
+ /* Clear POR fault flag to prevent IRQ storm */
+ regmap_read(regmap, TAS675X_POWER_FAULT_LATCHED_REG, &val);
+
+ /* Bypass DC Load Diagnostics for fast boot */
+ if (tas->fast_boot)
+ regmap_update_bits(regmap, TAS675X_DC_LDG_CTRL_REG,
+ TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT,
+ TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT);
+
+ tas675x_select_book(regmap, TAS675X_BOOK_DEFAULT);
+
+ /* Enter setup mode */
+ ret = regmap_write(regmap, TAS675X_SETUP_REG1, TAS675X_SETUP_ENTER_VAL1);
+ if (ret)
+ goto err;
+ ret = regmap_write(regmap, TAS675X_SETUP_REG2, TAS675X_SETUP_ENTER_VAL2);
+ if (ret)
+ goto err;
+
+ /* Set all channels to Sleep (required before Page 1 config) */
+ tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH);
+
+ /* Set DAC clock per TRM startup script */
+ regmap_write(regmap, TAS675X_DAC_CLK_REG, 0x00);
+
+ /*
+ * Switch to Page 1 for safety-critical OC/CBC configuration,
+ * while bypassing regcache. (Page 1 not accessible post setup)
+ */
+ regcache_cache_bypass(regmap, true);
+ ret = regmap_multi_reg_write(regmap, tas675x_page1_init,
+ ARRAY_SIZE(tas675x_page1_init));
+ regcache_cache_bypass(regmap, false);
+ if (ret)
+ goto err_setup;
+
+ /* Resync regmap's cached page selector */
+ regmap_write(regmap, TAS675X_PAGE_CTRL_REG, 0x00);
+
+ /* Exit setup mode */
+ regmap_write(regmap, TAS675X_SETUP_REG1, TAS675X_SETUP_EXIT_VAL);
+ regmap_write(regmap, TAS675X_SETUP_REG2, TAS675X_SETUP_EXIT_VAL);
+
+ /* Write DSP parameters if cached */
+ for (i = 0; i < ARRAY_SIZE(tas->dsp_params); i++) {
+ if (tas->dsp_params[i].val)
+ tas675x_dsp_mem_write(tas,
+ tas->dsp_params[i].page,
+ tas->dsp_params[i].reg,
+ tas->dsp_params[i].val);
+ }
+
+ /*
+ * Configure fault and warning event routing:
+ *
+ * ROUTING_1: CP fault/UVLO latch, OUTM soft short latch
+ * ROUTING_2: CBC latch, OTSD latch, OTSD, power fault
+ * ROUTING_3: CBC latch, OTSD latch, power latch, DC LDG,
+ * OTSD, power warnings
+ * ROUTING_4: OC latch, DC latch, protection shutdown
+ * OTW latch, OTW, clip latch
+ * ROUTING_5: clock latch+non-latch, RTLDG latch
+ * CBC warning, clip warning
+ */
+ regmap_write(regmap, TAS675X_REPORT_ROUTING_1_REG, 0x70);
+ regmap_write(regmap, TAS675X_REPORT_ROUTING_2_REG, 0xA3);
+ regmap_write(regmap, TAS675X_REPORT_ROUTING_3_REG, 0xBB);
+ regmap_write(regmap, TAS675X_REPORT_ROUTING_4_REG, 0x7E);
+ regmap_write(regmap, TAS675X_REPORT_ROUTING_5_REG, 0xF3);
+
+ /* Configure GPIO pins if specified in DT */
+ if (tas->gpio1_func >= 0 || tas->gpio2_func >= 0) {
+ unsigned int gpio_ctrl = TAS675X_GPIO_CTRL_RSTVAL;
+
+ tas675x_config_gpio_pin(regmap, tas->gpio1_func,
+ TAS675X_GPIO1_OUTPUT_SEL_REG,
+ 0, &gpio_ctrl);
+ tas675x_config_gpio_pin(regmap, tas->gpio2_func,
+ TAS675X_GPIO2_OUTPUT_SEL_REG,
+ 1, &gpio_ctrl);
+ regmap_write(regmap, TAS675X_GPIO_CTRL_REG, gpio_ctrl);
+ }
+
+ /* Clear fast boot bits */
+ if (tas->fast_boot)
+ regmap_update_bits(regmap, TAS675X_DC_LDG_CTRL_REG,
+ TAS675X_LDG_ABORT_BIT | TAS675X_LDG_BYPASS_BIT,
+ 0);
+
+ /* Clear any stale faults from the boot sequence */
+ regmap_read(regmap, TAS675X_POWER_FAULT_STATUS_1_REG, &val);
+ regmap_read(regmap, TAS675X_POWER_FAULT_LATCHED_REG, &val);
+ regmap_read(regmap, TAS675X_CLK_FAULT_LATCHED_REG, &val);
+ regmap_write(regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR);
+
+ return 0;
+
+err_setup:
+ regmap_write(regmap, TAS675X_SETUP_REG1, TAS675X_SETUP_EXIT_VAL);
+ regmap_write(regmap, TAS675X_SETUP_REG2, TAS675X_SETUP_EXIT_VAL);
+err:
+ dev_err(tas->dev, "Init device failed: %d\n", ret);
+ return ret;
+}
+
+static void tas675x_power_off(struct tas675x_priv *tas)
+{
+ regcache_cache_only(tas->regmap, true);
+ regcache_mark_dirty(tas->regmap);
+ tas675x_hw_disable(tas);
+}
+
+static int tas675x_power_on(struct tas675x_priv *tas)
+{
+ int ret;
+
+ ret = tas675x_hw_enable(tas);
+ if (ret)
+ return ret;
+
+ regcache_cache_only(tas->regmap, false);
+ regcache_mark_dirty(tas->regmap);
+
+ ret = tas675x_init_device(tas);
+ if (ret)
+ goto err_disable;
+
+ ret = regcache_sync(tas->regmap);
+ if (ret) {
+ dev_err(tas->dev, "Failed to sync regcache: %d\n", ret);
+ goto err_disable;
+ }
+
+ /* Reset fault tracking */
+ memset(tas->last_status, 0, sizeof(tas->last_status));
+
+ return 0;
+
+err_disable:
+ tas675x_power_off(tas);
+ return ret;
+}
+
+static int tas675x_runtime_suspend(struct device *dev)
+{
+ struct tas675x_priv *tas = dev_get_drvdata(dev);
+
+ disable_delayed_work_sync(&tas->fault_check_work);
+ tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH);
+
+ return 0;
+}
+
+static int tas675x_runtime_resume(struct device *dev)
+{
+ struct tas675x_priv *tas = dev_get_drvdata(dev);
+
+ tas675x_set_state_all(tas, TAS675X_STATE_SLEEP_BOTH);
+
+ if (!to_i2c_client(dev)->irq) {
+ enable_delayed_work(&tas->fault_check_work);
+ schedule_delayed_work(&tas->fault_check_work,
+ msecs_to_jiffies(TAS675X_FAULT_CHECK_INTERVAL_MS));
+ }
+
+ return 0;
+}
+
+static int tas675x_system_suspend(struct device *dev)
+{
+ struct tas675x_priv *tas = dev_get_drvdata(dev);
+ int ret;
+
+ ret = tas675x_runtime_suspend(dev);
+ if (ret)
+ return ret;
+
+ if (to_i2c_client(dev)->irq)
+ disable_irq(to_i2c_client(dev)->irq);
+
+ tas675x_power_off(tas);
+ return 0;
+}
+
+static int tas675x_system_resume(struct device *dev)
+{
+ struct tas675x_priv *tas = dev_get_drvdata(dev);
+ int ret;
+
+ ret = tas675x_power_on(tas);
+ if (ret)
+ return ret;
+
+ if (to_i2c_client(dev)->irq)
+ enable_irq(to_i2c_client(dev)->irq);
+
+ return tas675x_runtime_resume(dev);
+}
+
+static const struct snd_soc_component_driver soc_codec_dev_tas675x = {
+ .controls = tas675x_snd_controls,
+ .num_controls = ARRAY_SIZE(tas675x_snd_controls),
+ .dapm_widgets = tas675x_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tas675x_dapm_widgets),
+ .dapm_routes = tas675x_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(tas675x_dapm_routes),
+ .endianness = 1,
+};
+
+/* Fault register flags */
+#define TAS675X_FAULT_CRITICAL BIT(0) /* causes FAULT state, FAULT_CLEAR required */
+#define TAS675X_FAULT_TRACK BIT(1) /* track last value, only log on change */
+#define TAS675X_FAULT_ACTIVE BIT(2) /* skip when no stream is active */
+
+struct tas675x_fault_reg {
+ unsigned int reg;
+ unsigned int flags;
+ const char *name;
+};
+
+static const struct tas675x_fault_reg tas675x_fault_table[] = {
+ /* Critical */
+ { TAS675X_OTSD_LATCHED_REG, TAS675X_FAULT_CRITICAL | TAS675X_FAULT_TRACK,
+ "Overtemperature Shutdown" },
+ { TAS675X_OC_DC_FAULT_LATCHED_REG, TAS675X_FAULT_CRITICAL | TAS675X_FAULT_TRACK,
+ "Overcurrent / DC Fault" },
+ { TAS675X_RTLDG_OL_SL_FAULT_LATCHED_REG, TAS675X_FAULT_CRITICAL | TAS675X_FAULT_TRACK,
+ "Real-Time Load Diagnostic Fault" },
+ { TAS675X_CBC_FAULT_WARN_LATCHED_REG, TAS675X_FAULT_CRITICAL | TAS675X_FAULT_TRACK,
+ "CBC Fault/Warning" },
+ /* Warning */
+ { TAS675X_POWER_FAULT_STATUS_1_REG, TAS675X_FAULT_TRACK,
+ "CP / OUTM Fault" },
+ { TAS675X_POWER_FAULT_LATCHED_REG, TAS675X_FAULT_TRACK,
+ "Power Fault" },
+ { TAS675X_CLK_FAULT_LATCHED_REG, TAS675X_FAULT_TRACK | TAS675X_FAULT_ACTIVE,
+ "Clock Fault" },
+ { TAS675X_OTW_LATCHED_REG, TAS675X_FAULT_TRACK,
+ "Overtemperature Warning" },
+ { TAS675X_CLIP_WARN_LATCHED_REG, TAS675X_FAULT_ACTIVE,
+ "Clip Warning" },
+};
+
+static_assert(ARRAY_SIZE(tas675x_fault_table) == TAS675X_FAULT_REGS_NUM);
+
+/*
+ * Read and log all latched fault registers.
+ * Shared by both the polled fault_check_work and IRQ handler paths
+ * (which are mutually exclusive, only one is active per device).
+ * Returns true if any fault register needs to be cleared.
+ *
+ * For deciphering fault messages, see "Fault Monitoring" in
+ * Documentation/sound/codecs/tas675x.rst
+ */
+static bool tas675x_check_faults(struct tas675x_priv *tas)
+{
+ struct device *dev = tas->dev;
+ bool needs_clear = false;
+ unsigned int reg;
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(tas675x_fault_table); i++) {
+ const struct tas675x_fault_reg *f = &tas675x_fault_table[i];
+
+ ret = regmap_read(tas->regmap, f->reg, &reg);
+ if (ret) {
+ if (f->flags & TAS675X_FAULT_CRITICAL) {
+ dev_err(dev, "failed to read %s: %d\n", f->name, ret);
+ return needs_clear;
+ }
+ continue;
+ }
+
+ if (reg)
+ needs_clear = true;
+
+ /* Skip logging stream-dependent events when no stream is active */
+ if ((f->flags & TAS675X_FAULT_ACTIVE) &&
+ !READ_ONCE(tas->active_playback_dais) &&
+ !READ_ONCE(tas->active_capture_dais))
+ continue;
+
+ /* Log on change or on every non-zero read */
+ if (reg && (!(f->flags & TAS675X_FAULT_TRACK) ||
+ reg != tas->last_status[i])) {
+ if (f->flags & TAS675X_FAULT_CRITICAL)
+ dev_crit(dev, "%s Latched: 0x%02x\n", f->name, reg);
+ else
+ dev_warn(dev, "%s Latched: 0x%02x\n", f->name, reg);
+ }
+
+ if (f->flags & TAS675X_FAULT_TRACK)
+ tas->last_status[i] = reg;
+ }
+
+ return needs_clear;
+}
+
+static void tas675x_fault_check_work(struct work_struct *work)
+{
+ struct tas675x_priv *tas = container_of(work, struct tas675x_priv,
+ fault_check_work.work);
+
+ if (tas675x_check_faults(tas))
+ regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR);
+
+ schedule_delayed_work(&tas->fault_check_work,
+ msecs_to_jiffies(TAS675X_FAULT_CHECK_INTERVAL_MS));
+}
+
+static irqreturn_t tas675x_irq_handler(int irq, void *data)
+{
+ struct tas675x_priv *tas = data;
+ irqreturn_t ret = IRQ_NONE;
+
+ if (pm_runtime_resume_and_get(tas->dev) < 0)
+ return IRQ_NONE;
+
+ if (tas675x_check_faults(tas)) {
+ regmap_write(tas->regmap, TAS675X_RESET_REG, TAS675X_FAULT_CLEAR);
+ ret = IRQ_HANDLED;
+ }
+
+ pm_runtime_mark_last_busy(tas->dev);
+ pm_runtime_put_autosuspend(tas->dev);
+ return ret;
+}
+
+static const struct reg_default tas675x_reg_defaults[] = {
+ { TAS675X_PAGE_CTRL_REG, 0x00 },
+ { TAS675X_OUTPUT_CTRL_REG, 0x00 },
+ { TAS675X_STATE_CTRL_CH1_CH2_REG, TAS675X_STATE_SLEEP_BOTH },
+ { TAS675X_STATE_CTRL_CH3_CH4_REG, TAS675X_STATE_SLEEP_BOTH },
+ { TAS675X_ISENSE_CTRL_REG, 0x0F },
+ { TAS675X_DC_DETECT_CTRL_REG, 0x00 },
+ { TAS675X_SCLK_INV_CTRL_REG, 0x00 },
+ { TAS675X_AUDIO_IF_CTRL_REG, 0x00 },
+ { TAS675X_SDIN_CTRL_REG, 0x0A },
+ { TAS675X_SDOUT_CTRL_REG, 0x1A },
+ { TAS675X_SDIN_OFFSET_MSB_REG, 0x00 },
+ { TAS675X_SDIN_AUDIO_OFFSET_REG, 0x00 },
+ { TAS675X_SDIN_LL_OFFSET_REG, 0x60 },
+ { TAS675X_SDIN_CH_SWAP_REG, 0x00 },
+ { TAS675X_SDOUT_OFFSET_MSB_REG, 0xCF },
+ { TAS675X_VPREDICT_OFFSET_REG, 0xFF },
+ { TAS675X_ISENSE_OFFSET_REG, 0x00 },
+ { TAS675X_SDOUT_EN_REG, 0x00 },
+ { TAS675X_LL_EN_REG, 0x00 },
+ { TAS675X_RTLDG_EN_REG, 0x10 },
+ { TAS675X_DC_BLOCK_BYP_REG, 0x00 },
+ { TAS675X_DSP_CTRL_REG, 0x00 },
+ { TAS675X_PAGE_AUTO_INC_REG, 0x00 },
+ { TAS675X_DIG_VOL_CH1_REG, 0x30 },
+ { TAS675X_DIG_VOL_CH2_REG, 0x30 },
+ { TAS675X_DIG_VOL_CH3_REG, 0x30 },
+ { TAS675X_DIG_VOL_CH4_REG, 0x30 },
+ { TAS675X_DIG_VOL_RAMP_CTRL_REG, 0x77 },
+ { TAS675X_DIG_VOL_COMBINE_CTRL_REG, 0x00 },
+ { TAS675X_AUTO_MUTE_EN_REG, 0x00 },
+ { TAS675X_AUTO_MUTE_TIMING_CH1_CH2_REG, 0x00 },
+ { TAS675X_AUTO_MUTE_TIMING_CH3_CH4_REG, 0x00 },
+ { TAS675X_ANALOG_GAIN_CH1_CH2_REG, 0x00 },
+ { TAS675X_ANALOG_GAIN_CH3_CH4_REG, 0x00 },
+ { TAS675X_ANALOG_GAIN_RAMP_CTRL_REG, 0x00 },
+ { TAS675X_PULSE_INJECTION_EN_REG, 0x03 },
+ { TAS675X_CBC_CTRL_REG, 0x07 },
+ { TAS675X_CURRENT_LIMIT_CTRL_REG, 0x00 },
+ { TAS675X_ISENSE_CAL_REG, 0x00 },
+ { TAS675X_PWM_PHASE_CTRL_REG, 0x00 },
+ { TAS675X_SS_CTRL_REG, 0x00 },
+ { TAS675X_SS_RANGE_CTRL_REG, 0x00 },
+ { TAS675X_SS_DWELL_CTRL_REG, 0x00 },
+ { TAS675X_RAMP_PHASE_CTRL_GPO_REG, 0x00 },
+ { TAS675X_PWM_PHASE_M_CTRL_CH1_REG, 0x00 },
+ { TAS675X_PWM_PHASE_M_CTRL_CH2_REG, 0x00 },
+ { TAS675X_PWM_PHASE_M_CTRL_CH3_REG, 0x00 },
+ { TAS675X_PWM_PHASE_M_CTRL_CH4_REG, 0x00 },
+ { TAS675X_DC_LDG_CTRL_REG, 0x00 },
+ { TAS675X_DC_LDG_LO_CTRL_REG, 0x00 },
+ { TAS675X_DC_LDG_TIME_CTRL_REG, 0x00 },
+ { TAS675X_DC_LDG_SL_CH1_CH2_CTRL_REG, 0x11 },
+ { TAS675X_DC_LDG_SL_CH3_CH4_CTRL_REG, 0x11 },
+ { TAS675X_AC_LDG_CTRL_REG, 0x10 },
+ { TAS675X_TWEETER_DETECT_CTRL_REG, 0x08 },
+ { TAS675X_TWEETER_DETECT_THRESH_REG, 0x00 },
+ { TAS675X_AC_LDG_FREQ_CTRL_REG, 0xC8 },
+ { TAS675X_REPORT_ROUTING_1_REG, 0x00 },
+ { TAS675X_OTSD_RECOVERY_EN_REG, 0x00 },
+ { TAS675X_REPORT_ROUTING_2_REG, 0xA2 },
+ { TAS675X_REPORT_ROUTING_3_REG, 0x00 },
+ { TAS675X_REPORT_ROUTING_4_REG, 0x06 },
+ { TAS675X_CLIP_DETECT_CTRL_REG, 0x00 },
+ { TAS675X_REPORT_ROUTING_5_REG, 0x00 },
+ { TAS675X_GPIO1_OUTPUT_SEL_REG, 0x00 },
+ { TAS675X_GPIO2_OUTPUT_SEL_REG, 0x00 },
+ { TAS675X_GPIO_CTRL_REG, TAS675X_GPIO_CTRL_RSTVAL },
+ { TAS675X_OTW_CTRL_CH1_CH2_REG, 0x11 },
+ { TAS675X_OTW_CTRL_CH3_CH4_REG, 0x11 },
+};
+
+static bool tas675x_is_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TAS675X_RESET_REG:
+ return false;
+ default:
+ return true;
+ }
+}
+
+static bool tas675x_is_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case TAS675X_RESET_REG:
+ case TAS675X_BOOK_CTRL_REG:
+ case TAS675X_AUTO_MUTE_STATUS_REG:
+ case TAS675X_STATE_REPORT_CH1_CH2_REG:
+ case TAS675X_STATE_REPORT_CH3_CH4_REG:
+ case TAS675X_PVDD_SENSE_REG:
+ case TAS675X_TEMP_GLOBAL_REG:
+ case TAS675X_TEMP_CH1_CH2_REG:
+ case TAS675X_TEMP_CH3_CH4_REG:
+ case TAS675X_FS_MON_REG:
+ case TAS675X_SCLK_MON_REG:
+ case TAS675X_POWER_FAULT_STATUS_1_REG:
+ case TAS675X_POWER_FAULT_STATUS_2_REG:
+ case TAS675X_OT_FAULT_REG:
+ case TAS675X_OTW_STATUS_REG:
+ case TAS675X_CLIP_WARN_STATUS_REG:
+ case TAS675X_CBC_WARNING_STATUS_REG:
+ case TAS675X_POWER_FAULT_LATCHED_REG:
+ case TAS675X_OTSD_LATCHED_REG:
+ case TAS675X_OTW_LATCHED_REG:
+ case TAS675X_CLIP_WARN_LATCHED_REG:
+ case TAS675X_CLK_FAULT_LATCHED_REG:
+ case TAS675X_RTLDG_OL_SL_FAULT_LATCHED_REG:
+ case TAS675X_CBC_FAULT_WARN_LATCHED_REG:
+ case TAS675X_OC_DC_FAULT_LATCHED_REG:
+ case TAS675X_WARN_OT_MAX_FLAG_REG:
+ case TAS675X_DC_LDG_REPORT_CH1_CH2_REG ... TAS675X_TWEETER_REPORT_REG:
+ case TAS675X_CH1_RTLDG_IMP_MSB_REG ... TAS675X_CH4_DC_LDG_DCR_LSB_REG:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct regmap_range_cfg tas675x_ranges[] = {
+ {
+ .name = "Pages",
+ .range_min = 0,
+ .range_max = TAS675X_PAGE_SIZE * TAS675X_PAGE_SIZE - 1,
+ .selector_reg = TAS675X_PAGE_CTRL_REG,
+ .selector_mask = 0xff,
+ .selector_shift = 0,
+ .window_start = 0,
+ .window_len = TAS675X_PAGE_SIZE,
+ },
+};
+
+static void tas675x_regmap_lock(void *lock_arg)
+{
+ struct tas675x_priv *tas = lock_arg;
+
+ mutex_lock(&tas->io_lock);
+}
+
+static void tas675x_regmap_unlock(void *lock_arg)
+{
+ struct tas675x_priv *tas = lock_arg;
+
+ mutex_unlock(&tas->io_lock);
+}
+
+static const struct regmap_config tas675x_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+ .max_register = TAS675X_PAGE_SIZE * TAS675X_PAGE_SIZE - 1,
+ .ranges = tas675x_ranges,
+ .num_ranges = ARRAY_SIZE(tas675x_ranges),
+ .cache_type = REGCACHE_MAPLE,
+ .reg_defaults = tas675x_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(tas675x_reg_defaults),
+ .readable_reg = tas675x_is_readable_register,
+ .volatile_reg = tas675x_is_volatile_register,
+};
+
+static int tas675x_i2c_probe(struct i2c_client *client)
+{
+ struct regmap_config cfg = tas675x_regmap_config;
+ struct tas675x_priv *tas;
+ u32 val;
+ int i, ret;
+
+ tas = devm_kzalloc(&client->dev, sizeof(*tas), GFP_KERNEL);
+ if (!tas)
+ return -ENOMEM;
+
+ tas->dev = &client->dev;
+ i2c_set_clientdata(client, tas);
+
+ mutex_init(&tas->io_lock);
+ cfg.lock = tas675x_regmap_lock;
+ cfg.unlock = tas675x_regmap_unlock;
+ cfg.lock_arg = tas;
+
+ memcpy(tas->dsp_params, tas675x_dsp_defaults, sizeof(tas->dsp_params));
+ INIT_DELAYED_WORK(&tas->fault_check_work, tas675x_fault_check_work);
+
+ tas->regmap = devm_regmap_init_i2c(client, &cfg);
+ if (IS_ERR(tas->regmap))
+ return PTR_ERR(tas->regmap);
+
+ /* Keep regmap cache-only until hardware is powered on */
+ regcache_cache_only(tas->regmap, true);
+
+ tas->dev_type = (enum tas675x_type)(unsigned long)device_get_match_data(tas->dev);
+ tas->fast_boot = device_property_read_bool(tas->dev, "ti,fast-boot");
+
+ tas->audio_slot = -1;
+ tas->llp_slot = -1;
+ tas->vpredict_slot = -1;
+ tas->isense_slot = -1;
+ if (!device_property_read_u32(tas->dev, "ti,audio-slot-no", &val))
+ tas->audio_slot = val;
+ if (!device_property_read_u32(tas->dev, "ti,llp-slot-no", &val))
+ tas->llp_slot = val;
+ if (!device_property_read_u32(tas->dev, "ti,vpredict-slot-no", &val))
+ tas->vpredict_slot = val;
+ if (!device_property_read_u32(tas->dev, "ti,isense-slot-no", &val))
+ tas->isense_slot = val;
+
+ tas->gpio1_func = tas675x_gpio_func_parse(tas->dev, "ti,gpio1-function");
+ tas->gpio2_func = tas675x_gpio_func_parse(tas->dev, "ti,gpio2-function");
+
+ for (i = 0; i < ARRAY_SIZE(tas675x_supply_names); i++)
+ tas->supplies[i].supply = tas675x_supply_names[i];
+
+ ret = devm_regulator_bulk_get(tas->dev, ARRAY_SIZE(tas->supplies), tas->supplies);
+ if (ret)
+ return dev_err_probe(tas->dev, ret, "Failed to request supplies\n");
+
+ tas->vbat = devm_regulator_get_optional(tas->dev, "vbat");
+ if (IS_ERR(tas->vbat) && PTR_ERR(tas->vbat) != -ENODEV)
+ return dev_err_probe(tas->dev, PTR_ERR(tas->vbat),
+ "Failed to get vbat supply\n");
+
+ tas->pd_gpio = devm_gpiod_get_optional(tas->dev, "powerdown", GPIOD_OUT_HIGH);
+ if (IS_ERR(tas->pd_gpio))
+ return dev_err_probe(tas->dev, PTR_ERR(tas->pd_gpio), "Failed powerdown-gpios\n");
+
+ tas->stby_gpio = devm_gpiod_get_optional(tas->dev, "standby", GPIOD_OUT_HIGH);
+ if (IS_ERR(tas->stby_gpio))
+ return dev_err_probe(tas->dev, PTR_ERR(tas->stby_gpio), "Failed standby-gpios\n");
+
+ if (!tas->pd_gpio && !tas->stby_gpio)
+ return dev_err_probe(tas->dev, -EINVAL,
+ "At least one of powerdown-gpios or standby-gpios is required\n");
+
+ ret = tas675x_power_on(tas);
+ if (ret)
+ return ret;
+
+ if (client->irq) {
+ ret = devm_request_threaded_irq(tas->dev, client->irq, NULL,
+ tas675x_irq_handler,
+ IRQF_ONESHOT | IRQF_TRIGGER_FALLING,
+ "tas675x-fault", tas);
+ if (ret) {
+ tas675x_power_off(tas);
+ return dev_err_probe(tas->dev, ret, "Failed to request IRQ\n");
+ }
+ } else {
+ /* Schedule delayed work for fault checking at probe and runtime resume */
+ schedule_delayed_work(&tas->fault_check_work,
+ msecs_to_jiffies(TAS675X_FAULT_CHECK_INTERVAL_MS));
+ }
+
+ /* Enable runtime PM with 2s autosuspend */
+ pm_runtime_set_autosuspend_delay(tas->dev, 2000);
+ pm_runtime_use_autosuspend(tas->dev);
+ pm_runtime_set_active(tas->dev);
+ pm_runtime_mark_last_busy(tas->dev);
+ pm_runtime_enable(tas->dev);
+
+ ret = devm_snd_soc_register_component(tas->dev, &soc_codec_dev_tas675x,
+ tas675x_dais, ARRAY_SIZE(tas675x_dais));
+ if (ret)
+ goto err_pm_disable;
+
+ return 0;
+
+err_pm_disable:
+ pm_runtime_force_suspend(tas->dev);
+ pm_runtime_disable(tas->dev);
+ tas675x_power_off(tas);
+ return ret;
+}
+
+static void tas675x_i2c_remove(struct i2c_client *client)
+{
+ struct tas675x_priv *tas = dev_get_drvdata(&client->dev);
+
+ disable_delayed_work_sync(&tas->fault_check_work);
+ if (client->irq)
+ disable_irq(client->irq);
+
+ pm_runtime_force_suspend(&client->dev);
+ pm_runtime_disable(&client->dev);
+ tas675x_power_off(tas);
+}
+
+static const struct dev_pm_ops tas675x_pm_ops = {
+ SYSTEM_SLEEP_PM_OPS(tas675x_system_suspend, tas675x_system_resume)
+ RUNTIME_PM_OPS(tas675x_runtime_suspend, tas675x_runtime_resume, NULL)
+};
+
+static const struct of_device_id tas675x_of_match[] = {
+ { .compatible = "ti,tas67524", .data = (void *)TAS67524 },
+ { }
+};
+MODULE_DEVICE_TABLE(of, tas675x_of_match);
+
+static const struct i2c_device_id tas675x_i2c_id[] = {
+ { "tas67524", TAS67524 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, tas675x_i2c_id);
+
+static struct i2c_driver tas675x_i2c_driver = {
+ .driver = {
+ .name = "tas675x",
+ .of_match_table = tas675x_of_match,
+ .pm = pm_ptr(&tas675x_pm_ops),
+ },
+ .probe = tas675x_i2c_probe,
+ .remove = tas675x_i2c_remove,
+ .id_table = tas675x_i2c_id,
+};
+
+module_i2c_driver(tas675x_i2c_driver);
+
+MODULE_AUTHOR("Sen Wang <sen@ti.com>");
+MODULE_DESCRIPTION("ASoC TAS675x Audio Amplifier Driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tas675x.h b/sound/soc/codecs/tas675x.h
new file mode 100644
index 000000000000..db29bb377336
--- /dev/null
+++ b/sound/soc/codecs/tas675x.h
@@ -0,0 +1,367 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * ALSA SoC Texas Instruments TAS675x Quad-Channel Audio Amplifier
+ *
+ * Copyright (C) 2026 Texas Instruments Incorporated - https://www.ti.com/
+ * Author: Sen Wang <sen@ti.com>
+ */
+
+#ifndef __TAS675X_H__
+#define __TAS675X_H__
+
+/*
+ * Book 0, Page 0 — Register Addresses
+ */
+
+#define TAS675X_PAGE_SIZE 256
+#define TAS675X_PAGE_REG(page, reg) ((page) * TAS675X_PAGE_SIZE + (reg))
+
+/* Page Control & Basic Config */
+#define TAS675X_PAGE_CTRL_REG 0x00
+#define TAS675X_RESET_REG 0x01
+#define TAS675X_OUTPUT_CTRL_REG 0x02
+#define TAS675X_STATE_CTRL_CH1_CH2_REG 0x03
+#define TAS675X_STATE_CTRL_CH3_CH4_REG 0x04
+#define TAS675X_ISENSE_CTRL_REG 0x05
+#define TAS675X_DC_DETECT_CTRL_REG 0x06
+
+/* Serial Audio Port */
+#define TAS675X_SCLK_INV_CTRL_REG 0x20
+#define TAS675X_AUDIO_IF_CTRL_REG 0x21
+#define TAS675X_SDIN_CTRL_REG 0x23
+#define TAS675X_SDOUT_CTRL_REG 0x25
+#define TAS675X_SDIN_OFFSET_MSB_REG 0x27
+#define TAS675X_SDIN_AUDIO_OFFSET_REG 0x28
+#define TAS675X_SDIN_LL_OFFSET_REG 0x29
+#define TAS675X_SDIN_CH_SWAP_REG 0x2A
+#define TAS675X_SDOUT_OFFSET_MSB_REG 0x2C
+#define TAS675X_VPREDICT_OFFSET_REG 0x2D
+#define TAS675X_ISENSE_OFFSET_REG 0x2E
+#define TAS675X_SDOUT_EN_REG 0x31
+#define TAS675X_LL_EN_REG 0x32
+
+/* DSP & Core Audio Control */
+#define TAS675X_RTLDG_EN_REG 0x37
+#define TAS675X_DC_BLOCK_BYP_REG 0x39
+#define TAS675X_DSP_CTRL_REG 0x3A
+#define TAS675X_PAGE_AUTO_INC_REG 0x3B
+
+/* Volume & Mute */
+#define TAS675X_DIG_VOL_CH1_REG 0x40
+#define TAS675X_DIG_VOL_CH2_REG 0x41
+#define TAS675X_DIG_VOL_CH3_REG 0x42
+#define TAS675X_DIG_VOL_CH4_REG 0x43
+#define TAS675X_DIG_VOL_RAMP_CTRL_REG 0x44
+#define TAS675X_DIG_VOL_COMBINE_CTRL_REG 0x46
+#define TAS675X_AUTO_MUTE_EN_REG 0x47
+#define TAS675X_AUTO_MUTE_TIMING_CH1_CH2_REG 0x48
+#define TAS675X_AUTO_MUTE_TIMING_CH3_CH4_REG 0x49
+
+/* Analog Gain & Power Stage */
+#define TAS675X_ANALOG_GAIN_CH1_CH2_REG 0x4A
+#define TAS675X_ANALOG_GAIN_CH3_CH4_REG 0x4B
+#define TAS675X_ANALOG_GAIN_RAMP_CTRL_REG 0x4E
+#define TAS675X_PULSE_INJECTION_EN_REG 0x52
+#define TAS675X_CBC_CTRL_REG 0x54
+#define TAS675X_CURRENT_LIMIT_CTRL_REG 0x55
+#define TAS675X_DAC_CLK_REG 0x5A
+#define TAS675X_ISENSE_CAL_REG 0x5B
+
+/* Spread Spectrum & PWM Phase */
+#define TAS675X_PWM_PHASE_CTRL_REG 0x60
+#define TAS675X_SS_CTRL_REG 0x61
+#define TAS675X_SS_RANGE_CTRL_REG 0x62
+#define TAS675X_SS_DWELL_CTRL_REG 0x66
+#define TAS675X_RAMP_PHASE_CTRL_GPO_REG 0x68
+#define TAS675X_PWM_PHASE_M_CTRL_CH1_REG 0x69
+#define TAS675X_PWM_PHASE_M_CTRL_CH2_REG 0x6A
+#define TAS675X_PWM_PHASE_M_CTRL_CH3_REG 0x6B
+#define TAS675X_PWM_PHASE_M_CTRL_CH4_REG 0x6C
+
+/* Status & Reporting */
+#define TAS675X_AUTO_MUTE_STATUS_REG 0x71
+#define TAS675X_STATE_REPORT_CH1_CH2_REG 0x72
+#define TAS675X_STATE_REPORT_CH3_CH4_REG 0x73
+#define TAS675X_PVDD_SENSE_REG 0x74
+#define TAS675X_TEMP_GLOBAL_REG 0x75
+#define TAS675X_FS_MON_REG 0x76
+#define TAS675X_SCLK_MON_REG 0x77
+#define TAS675X_REPORT_ROUTING_1_REG 0x7C
+
+/* Memory Paging & Book Control */
+#define TAS675X_SETUP_REG1 0x7D
+#define TAS675X_SETUP_REG2 0x7E
+#define TAS675X_BOOK_CTRL_REG 0x7F
+
+/* Fault Status */
+#define TAS675X_POWER_FAULT_STATUS_1_REG 0x7D
+#define TAS675X_POWER_FAULT_STATUS_2_REG 0x80
+#define TAS675X_OT_FAULT_REG 0x81
+#define TAS675X_OTW_STATUS_REG 0x82
+#define TAS675X_CLIP_WARN_STATUS_REG 0x83
+#define TAS675X_CBC_WARNING_STATUS_REG 0x85
+
+/* Latched Fault Registers */
+#define TAS675X_POWER_FAULT_LATCHED_REG 0x86
+#define TAS675X_OTSD_LATCHED_REG 0x87
+#define TAS675X_OTW_LATCHED_REG 0x88
+#define TAS675X_CLIP_WARN_LATCHED_REG 0x89
+#define TAS675X_CLK_FAULT_LATCHED_REG 0x8A
+#define TAS675X_RTLDG_OL_SL_FAULT_LATCHED_REG 0x8B
+#define TAS675X_CBC_FAULT_WARN_LATCHED_REG 0x8D
+#define TAS675X_OC_DC_FAULT_LATCHED_REG 0x8E
+#define TAS675X_OTSD_RECOVERY_EN_REG 0x8F
+
+/* Protection & Routing Controls */
+#define TAS675X_REPORT_ROUTING_2_REG 0x90
+#define TAS675X_REPORT_ROUTING_3_REG 0x91
+#define TAS675X_REPORT_ROUTING_4_REG 0x92
+#define TAS675X_CLIP_DETECT_CTRL_REG 0x93
+#define TAS675X_REPORT_ROUTING_5_REG 0x94
+
+/* GPIO Pin Configuration */
+#define TAS675X_GPIO1_OUTPUT_SEL_REG 0x95
+#define TAS675X_GPIO2_OUTPUT_SEL_REG 0x96
+#define TAS675X_GPIO_INPUT_SLEEP_HIZ_REG 0x9B
+#define TAS675X_GPIO_INPUT_PLAY_SLEEP_REG 0x9C
+#define TAS675X_GPIO_INPUT_MUTE_REG 0x9D
+#define TAS675X_GPIO_INPUT_SYNC_REG 0x9E
+#define TAS675X_GPIO_INPUT_SDIN2_REG 0x9F
+#define TAS675X_GPIO_CTRL_REG 0xA0
+#define TAS675X_GPIO_INVERT_REG 0xA1
+
+/* Load Diagnostics Config */
+#define TAS675X_DC_LDG_CTRL_REG 0xB0
+#define TAS675X_DC_LDG_LO_CTRL_REG 0xB1
+#define TAS675X_DC_LDG_TIME_CTRL_REG 0xB2
+#define TAS675X_DC_LDG_SL_CH1_CH2_CTRL_REG 0xB3
+#define TAS675X_DC_LDG_SL_CH3_CH4_CTRL_REG 0xB4
+#define TAS675X_AC_LDG_CTRL_REG 0xB5
+#define TAS675X_TWEETER_DETECT_CTRL_REG 0xB6
+#define TAS675X_TWEETER_DETECT_THRESH_REG 0xB7
+#define TAS675X_AC_LDG_FREQ_CTRL_REG 0xB8
+#define TAS675X_TEMP_CH1_CH2_REG 0xBB
+#define TAS675X_TEMP_CH3_CH4_REG 0xBC
+#define TAS675X_WARN_OT_MAX_FLAG_REG 0xBD
+
+/* DC Load Diagnostic Reports */
+#define TAS675X_DC_LDG_REPORT_CH1_CH2_REG 0xC0
+#define TAS675X_DC_LDG_REPORT_CH3_CH4_REG 0xC1
+#define TAS675X_DC_LDG_RESULT_REG 0xC2
+#define TAS675X_AC_LDG_REPORT_CH1_R_REG 0xC3
+#define TAS675X_AC_LDG_REPORT_CH1_I_REG 0xC4
+#define TAS675X_AC_LDG_REPORT_CH2_R_REG 0xC5
+#define TAS675X_AC_LDG_REPORT_CH2_I_REG 0xC6
+#define TAS675X_AC_LDG_REPORT_CH3_R_REG 0xC7
+#define TAS675X_AC_LDG_REPORT_CH3_I_REG 0xC8
+#define TAS675X_AC_LDG_REPORT_CH4_R_REG 0xC9
+#define TAS675X_AC_LDG_REPORT_CH4_I_REG 0xCA
+#define TAS675X_TWEETER_REPORT_REG 0xCB
+
+/* RTLDG Impedance */
+#define TAS675X_CH1_RTLDG_IMP_MSB_REG 0xD1
+#define TAS675X_CH1_RTLDG_IMP_LSB_REG 0xD2
+#define TAS675X_CH2_RTLDG_IMP_MSB_REG 0xD3
+#define TAS675X_CH2_RTLDG_IMP_LSB_REG 0xD4
+#define TAS675X_CH3_RTLDG_IMP_MSB_REG 0xD5
+#define TAS675X_CH3_RTLDG_IMP_LSB_REG 0xD6
+#define TAS675X_CH4_RTLDG_IMP_MSB_REG 0xD7
+#define TAS675X_CH4_RTLDG_IMP_LSB_REG 0xD8
+
+/* DC Load Diagnostic Resistance */
+#define TAS675X_DC_LDG_DCR_MSB_REG 0xD9
+#define TAS675X_CH1_DC_LDG_DCR_LSB_REG 0xDA
+#define TAS675X_CH2_DC_LDG_DCR_LSB_REG 0xDB
+#define TAS675X_CH3_DC_LDG_DCR_LSB_REG 0xDC
+#define TAS675X_CH4_DC_LDG_DCR_LSB_REG 0xDD
+
+/* Over-Temperature Warning */
+#define TAS675X_OTW_CTRL_CH1_CH2_REG 0xE2
+#define TAS675X_OTW_CTRL_CH3_CH4_REG 0xE3
+
+/* RESET_REG (all bits auto-clear) */
+#define TAS675X_DEVICE_RESET BIT(4)
+#define TAS675X_FAULT_CLEAR BIT(3)
+#define TAS675X_REGISTER_RESET BIT(0)
+
+/* STATE_CTRL and STATE_REPORT — Channel state values */
+#define TAS675X_STATE_DEEPSLEEP 0x00
+#define TAS675X_STATE_LOAD_DIAG 0x01
+#define TAS675X_STATE_SLEEP 0x02
+#define TAS675X_STATE_HIZ 0x03
+#define TAS675X_STATE_PLAY 0x04
+
+/* Additional STATE_REPORT values */
+#define TAS675X_STATE_FAULT 0x05
+#define TAS675X_STATE_AUTOREC 0x06
+
+/* Combined values for both channel pairs in one register */
+#define TAS675X_STATE_DEEPSLEEP_BOTH \
+ (TAS675X_STATE_DEEPSLEEP | (TAS675X_STATE_DEEPSLEEP << 4))
+#define TAS675X_STATE_LOAD_DIAG_BOTH \
+ (TAS675X_STATE_LOAD_DIAG | (TAS675X_STATE_LOAD_DIAG << 4))
+#define TAS675X_STATE_SLEEP_BOTH \
+ (TAS675X_STATE_SLEEP | (TAS675X_STATE_SLEEP << 4))
+#define TAS675X_STATE_HIZ_BOTH \
+ (TAS675X_STATE_HIZ | (TAS675X_STATE_HIZ << 4))
+#define TAS675X_STATE_PLAY_BOTH \
+ (TAS675X_STATE_PLAY | (TAS675X_STATE_PLAY << 4))
+#define TAS675X_STATE_FAULT_BOTH \
+ (TAS675X_STATE_FAULT | (TAS675X_STATE_FAULT << 4))
+
+/* STATE_CTRL_CH1_CH2 / STATE_CTRL_CH3_CH4 — mute bits */
+#define TAS675X_CH1_MUTE_BIT BIT(7)
+#define TAS675X_CH2_MUTE_BIT BIT(3)
+#define TAS675X_CH_MUTE_BOTH (TAS675X_CH1_MUTE_BIT | TAS675X_CH2_MUTE_BIT)
+
+/* SCLK_INV_CTRL_REG */
+#define TAS675X_SCLK_INV_TX_BIT BIT(5)
+#define TAS675X_SCLK_INV_RX_BIT BIT(4)
+#define TAS675X_SCLK_INV_MASK (TAS675X_SCLK_INV_TX_BIT | TAS675X_SCLK_INV_RX_BIT)
+
+/* AUDIO_IF_CTRL_REG */
+#define TAS675X_TDM_EN_BIT BIT(4)
+#define TAS675X_SAP_FMT_MASK GENMASK(3, 2)
+#define TAS675X_SAP_FMT_I2S (0x00 << 2)
+#define TAS675X_SAP_FMT_TDM (0x01 << 2)
+#define TAS675X_SAP_FMT_RIGHT_J (0x02 << 2)
+#define TAS675X_SAP_FMT_LEFT_J (0x03 << 2)
+#define TAS675X_FS_PULSE_MASK GENMASK(1, 0)
+#define TAS675X_FS_PULSE_SHORT 0x01
+
+/* SDIN_CTRL_REG */
+#define TAS675X_SDIN_AUDIO_WL_MASK GENMASK(3, 2)
+#define TAS675X_SDIN_LL_WL_MASK GENMASK(1, 0)
+#define TAS675X_SDIN_WL_MASK (TAS675X_SDIN_AUDIO_WL_MASK | TAS675X_SDIN_LL_WL_MASK)
+
+/* SDOUT_CTRL_REG */
+#define TAS675X_SDOUT_SELECT_MASK GENMASK(7, 4)
+#define TAS675X_SDOUT_SELECT_TDM_SDOUT1 0x00
+#define TAS675X_SDOUT_SELECT_NON_TDM 0x10
+#define TAS675X_SDOUT_VP_WL_MASK GENMASK(3, 2)
+#define TAS675X_SDOUT_IS_WL_MASK GENMASK(1, 0)
+#define TAS675X_SDOUT_WL_MASK (TAS675X_SDOUT_VP_WL_MASK | TAS675X_SDOUT_IS_WL_MASK)
+
+/* SDOUT_EN_REG */
+#define TAS675X_SDOUT_NON_TDM_SEL_MASK GENMASK(5, 4)
+#define TAS675X_SDOUT_NON_TDM_SEL_VPREDICT (0x0 << 4)
+#define TAS675X_SDOUT_NON_TDM_SEL_ISENSE (0x1 << 4)
+#define TAS675X_SDOUT_EN_VPREDICT BIT(0)
+#define TAS675X_SDOUT_EN_ISENSE BIT(1)
+#define TAS675X_SDOUT_EN_NON_TDM_ALL GENMASK(1, 0)
+
+/* Word length values (shared by SDIN_CTRL and SDOUT_CTRL) */
+#define TAS675X_WL_16BIT 0x00
+#define TAS675X_WL_20BIT 0x01
+#define TAS675X_WL_24BIT 0x02
+#define TAS675X_WL_32BIT 0x03
+
+/* SDIN_OFFSET_MSB_REG */
+#define TAS675X_SDIN_AUDIO_OFF_MSB_MASK GENMASK(7, 6)
+#define TAS675X_SDIN_LL_OFF_MSB_MASK GENMASK(5, 4)
+
+/* SDOUT_OFFSET_MSB_REG */
+#define TAS675X_SDOUT_VP_OFF_MSB_MASK GENMASK(7, 6)
+#define TAS675X_SDOUT_IS_OFF_MSB_MASK GENMASK(5, 4)
+
+/* RTLDG_EN_REG */
+#define TAS675X_RTLDG_CLIP_MASK_BIT BIT(4)
+#define TAS675X_RTLDG_CH_EN_MASK GENMASK(3, 0)
+
+/* DC_LDG_CTRL_REG */
+#define TAS675X_LDG_ABORT_BIT BIT(7)
+#define TAS675X_LDG_BUFFER_WAIT_MASK GENMASK(6, 5)
+#define TAS675X_LDG_WAIT_BYPASS_BIT BIT(2)
+#define TAS675X_SLOL_DISABLE_BIT BIT(1)
+#define TAS675X_LDG_BYPASS_BIT BIT(0)
+
+/* DC_LDG_TIME_CTRL_REG */
+#define TAS675X_LDG_RAMP_SLOL_MASK GENMASK(7, 6)
+#define TAS675X_LDG_SETTLING_SLOL_MASK GENMASK(5, 4)
+#define TAS675X_LDG_RAMP_S2PG_MASK GENMASK(3, 2)
+#define TAS675X_LDG_SETTLING_S2PG_MASK GENMASK(1, 0)
+
+/* AC_LDG_CTRL_REG */
+#define TAS675X_AC_DIAG_GAIN_BIT BIT(4)
+#define TAS675X_AC_DIAG_START_MASK GENMASK(3, 0)
+
+/* DC_LDG_RESULT_REG */
+#define TAS675X_DC_LDG_LO_RESULT_MASK GENMASK(7, 4)
+#define TAS675X_DC_LDG_PASS_MASK GENMASK(3, 0)
+
+/* Load Diagnostics Timing Constants */
+#define TAS675X_POLL_INTERVAL_US 10000
+#define TAS675X_STATE_TRANSITION_TIMEOUT_US 50000
+#define TAS675X_DC_LDG_TIMEOUT_US 300000
+#define TAS675X_AC_LDG_TIMEOUT_US 400000
+
+/* GPIO_CTRL_REG */
+#define TAS675X_GPIO1_OUTPUT_EN BIT(7)
+#define TAS675X_GPIO2_OUTPUT_EN BIT(6)
+#define TAS675X_GPIO_CTRL_RSTVAL 0x22
+
+/* GPIO output select values */
+#define TAS675X_GPIO_SEL_LOW 0x00
+#define TAS675X_GPIO_SEL_AUTO_MUTE_ALL 0x02
+#define TAS675X_GPIO_SEL_AUTO_MUTE_CH4 0x03
+#define TAS675X_GPIO_SEL_AUTO_MUTE_CH3 0x04
+#define TAS675X_GPIO_SEL_AUTO_MUTE_CH2 0x05
+#define TAS675X_GPIO_SEL_AUTO_MUTE_CH1 0x06
+#define TAS675X_GPIO_SEL_SDOUT2 0x08
+#define TAS675X_GPIO_SEL_SDOUT1 0x09
+#define TAS675X_GPIO_SEL_WARN 0x0A
+#define TAS675X_GPIO_SEL_FAULT 0x0B
+#define TAS675X_GPIO_SEL_CLOCK_SYNC 0x0E
+#define TAS675X_GPIO_SEL_INVALID_CLK 0x0F
+#define TAS675X_GPIO_SEL_HIGH 0x13
+
+/* GPIO input function encoding (flag bit | function ID) */
+#define TAS675X_GPIO_FUNC_INPUT 0x100
+
+/* Input Function IDs */
+#define TAS675X_GPIO_IN_ID_MUTE 0
+#define TAS675X_GPIO_IN_ID_PHASE_SYNC 1
+#define TAS675X_GPIO_IN_ID_SDIN2 2
+#define TAS675X_GPIO_IN_ID_DEEP_SLEEP 3
+#define TAS675X_GPIO_IN_ID_HIZ 4
+#define TAS675X_GPIO_IN_ID_PLAY 5
+#define TAS675X_GPIO_IN_ID_SLEEP 6
+#define TAS675X_GPIO_IN_NUM 7
+
+#define TAS675X_GPIO_IN_MUTE (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_MUTE)
+#define TAS675X_GPIO_IN_PHASE_SYNC \
+ (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_PHASE_SYNC)
+#define TAS675X_GPIO_IN_SDIN2 (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_SDIN2)
+#define TAS675X_GPIO_IN_DEEP_SLEEP \
+ (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_DEEP_SLEEP)
+#define TAS675X_GPIO_IN_HIZ (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_HIZ)
+#define TAS675X_GPIO_IN_PLAY (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_PLAY)
+#define TAS675X_GPIO_IN_SLEEP (TAS675X_GPIO_FUNC_INPUT | TAS675X_GPIO_IN_ID_SLEEP)
+
+/* GPIO input 3-bit mux field masks */
+#define TAS675X_GPIO_IN_MUTE_MASK GENMASK(2, 0)
+#define TAS675X_GPIO_IN_SYNC_MASK GENMASK(2, 0)
+#define TAS675X_GPIO_IN_SDIN2_MASK GENMASK(6, 4)
+#define TAS675X_GPIO_IN_DEEP_SLEEP_MASK GENMASK(6, 4)
+#define TAS675X_GPIO_IN_HIZ_MASK GENMASK(2, 0)
+#define TAS675X_GPIO_IN_PLAY_MASK GENMASK(6, 4)
+#define TAS675X_GPIO_IN_SLEEP_MASK GENMASK(2, 0)
+
+/* Book addresses for tas675x_select_book() */
+#define TAS675X_BOOK_DEFAULT 0x00
+#define TAS675X_BOOK_DSP 0x8C
+
+/* DSP memory addresses (DSP Book) */
+#define TAS675X_DSP_PAGE_RTLDG 0x22
+#define TAS675X_DSP_RTLDG_OL_THRESH_REG 0x98
+#define TAS675X_DSP_RTLDG_SL_THRESH_REG 0x9C
+
+#define TAS675X_DSP_PARAM_ID_OL_THRESH 0
+#define TAS675X_DSP_PARAM_ID_SL_THRESH 1
+
+/* Setup Mode Entry/Exit*/
+#define TAS675X_SETUP_ENTER_VAL1 0x11
+#define TAS675X_SETUP_ENTER_VAL2 0xFF
+#define TAS675X_SETUP_EXIT_VAL 0x00
+
+#endif /* __TAS675X_H__ */
diff --git a/sound/soc/codecs/tda7419.c b/sound/soc/codecs/tda7419.c
index 7d6fcba9986e..7ddea2fbe2d2 100644
--- a/sound/soc/codecs/tda7419.c
+++ b/sound/soc/codecs/tda7419.c
@@ -614,7 +614,7 @@ static int tda7419_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tda7419_i2c_id[] = {
- { "tda7419" },
+ { .name = "tda7419" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tda7419_i2c_id);
diff --git a/sound/soc/codecs/tfa9879.c b/sound/soc/codecs/tfa9879.c
index ac0c5c337677..f30479f1f53b 100644
--- a/sound/soc/codecs/tfa9879.c
+++ b/sound/soc/codecs/tfa9879.c
@@ -296,7 +296,7 @@ static int tfa9879_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tfa9879_i2c_id[] = {
- { "tfa9879" },
+ { .name = "tfa9879" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tfa9879_i2c_id);
diff --git a/sound/soc/codecs/tlv320adc3xxx.c b/sound/soc/codecs/tlv320adc3xxx.c
index 270eee1ea534..d7d958ecd8db 100644
--- a/sound/soc/codecs/tlv320adc3xxx.c
+++ b/sound/soc/codecs/tlv320adc3xxx.c
@@ -1391,9 +1391,9 @@ static const struct snd_soc_component_driver soc_component_dev_adc3xxx = {
};
static const struct i2c_device_id adc3xxx_i2c_id[] = {
- { "tlv320adc3001", ADC3001 },
- { "tlv320adc3101", ADC3101 },
- {}
+ { .name = "tlv320adc3001", .driver_data = ADC3001 },
+ { .name = "tlv320adc3101", .driver_data = ADC3101 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, adc3xxx_i2c_id);
diff --git a/sound/soc/codecs/tlv320adcx140.c b/sound/soc/codecs/tlv320adcx140.c
index e4f27a734501..4eb9cea27276 100644
--- a/sound/soc/codecs/tlv320adcx140.c
+++ b/sound/soc/codecs/tlv320adcx140.c
@@ -1326,10 +1326,10 @@ static int adcx140_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id adcx140_i2c_id[] = {
- { "tlv320adc3140", 0 },
- { "tlv320adc5140", 1 },
- { "tlv320adc6140", 2 },
- {}
+ { .name = "tlv320adc3140", .driver_data = 0 },
+ { .name = "tlv320adc5140", .driver_data = 1 },
+ { .name = "tlv320adc6140", .driver_data = 2 },
+ { }
};
MODULE_DEVICE_TABLE(i2c, adcx140_i2c_id);
diff --git a/sound/soc/codecs/tlv320aic23-i2c.c b/sound/soc/codecs/tlv320aic23-i2c.c
index a31fb95048b8..2f928ae23887 100644
--- a/sound/soc/codecs/tlv320aic23-i2c.c
+++ b/sound/soc/codecs/tlv320aic23-i2c.c
@@ -28,8 +28,8 @@ static int tlv320aic23_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tlv320aic23_id[] = {
- {"tlv320aic23"},
- {}
+ { .name = "tlv320aic23" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, tlv320aic23_id);
diff --git a/sound/soc/codecs/tlv320aic31xx.c b/sound/soc/codecs/tlv320aic31xx.c
index 4362c2c06ce8..1d2e0ea6d4fe 100644
--- a/sound/soc/codecs/tlv320aic31xx.c
+++ b/sound/soc/codecs/tlv320aic31xx.c
@@ -1630,14 +1630,14 @@ static void aic31xx_configure_ocmv(struct aic31xx_priv *priv)
}
static const struct i2c_device_id aic31xx_i2c_id[] = {
- { "tlv320aic310x", AIC3100 },
- { "tlv320aic311x", AIC3110 },
- { "tlv320aic3100", AIC3100 },
- { "tlv320aic3110", AIC3110 },
- { "tlv320aic3120", AIC3120 },
- { "tlv320aic3111", AIC3111 },
- { "tlv320dac3100", DAC3100 },
- { "tlv320dac3101", DAC3101 },
+ { .name = "tlv320aic310x", .driver_data = AIC3100 },
+ { .name = "tlv320aic311x", .driver_data = AIC3110 },
+ { .name = "tlv320aic3100", .driver_data = AIC3100 },
+ { .name = "tlv320aic3110", .driver_data = AIC3110 },
+ { .name = "tlv320aic3120", .driver_data = AIC3120 },
+ { .name = "tlv320aic3111", .driver_data = AIC3111 },
+ { .name = "tlv320dac3100", .driver_data = DAC3100 },
+ { .name = "tlv320dac3101", .driver_data = DAC3101 },
{ }
};
MODULE_DEVICE_TABLE(i2c, aic31xx_i2c_id);
diff --git a/sound/soc/codecs/tlv320aic32x4-i2c.c b/sound/soc/codecs/tlv320aic32x4-i2c.c
index b27b5ae1e4b2..449353d5f088 100644
--- a/sound/soc/codecs/tlv320aic32x4-i2c.c
+++ b/sound/soc/codecs/tlv320aic32x4-i2c.c
@@ -38,9 +38,9 @@ static void aic32x4_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id aic32x4_i2c_id[] = {
- { "tlv320aic32x4", (kernel_ulong_t)AIC32X4_TYPE_AIC32X4 },
- { "tlv320aic32x6", (kernel_ulong_t)AIC32X4_TYPE_AIC32X6 },
- { "tas2505", (kernel_ulong_t)AIC32X4_TYPE_TAS2505 },
+ { .name = "tlv320aic32x4", .driver_data = (kernel_ulong_t)AIC32X4_TYPE_AIC32X4 },
+ { .name = "tlv320aic32x6", .driver_data = (kernel_ulong_t)AIC32X4_TYPE_AIC32X6 },
+ { .name = "tas2505", .driver_data = (kernel_ulong_t)AIC32X4_TYPE_TAS2505 },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, aic32x4_i2c_id);
diff --git a/sound/soc/codecs/tlv320aic3x-i2c.c b/sound/soc/codecs/tlv320aic3x-i2c.c
index 0b585925c1ac..71528ad3a3b6 100644
--- a/sound/soc/codecs/tlv320aic3x-i2c.c
+++ b/sound/soc/codecs/tlv320aic3x-i2c.c
@@ -18,11 +18,11 @@
#include "tlv320aic3x.h"
static const struct i2c_device_id aic3x_i2c_id[] = {
- { "tlv320aic3x", AIC3X_MODEL_3X },
- { "tlv320aic33", AIC3X_MODEL_33 },
- { "tlv320aic3007", AIC3X_MODEL_3007 },
- { "tlv320aic3104", AIC3X_MODEL_3104 },
- { "tlv320aic3106", AIC3X_MODEL_3106 },
+ { .name = "tlv320aic3x", .driver_data = AIC3X_MODEL_3X },
+ { .name = "tlv320aic33", .driver_data = AIC3X_MODEL_33 },
+ { .name = "tlv320aic3007", .driver_data = AIC3X_MODEL_3007 },
+ { .name = "tlv320aic3104", .driver_data = AIC3X_MODEL_3104 },
+ { .name = "tlv320aic3106", .driver_data = AIC3X_MODEL_3106 },
{ }
};
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index ce22298b43ef..b38393a8130f 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -1049,11 +1049,13 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
+ static const u8 dual_rate_q[] = {4, 8, 9, 12, 16};
struct snd_soc_component *component = dai->component;
struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component);
int codec_clk = 0, bypass_pll = 0, fsref, last_clk = 0;
u8 data, j, r, p, pll_q, pll_p = 1, pll_r = 1, pll_j = 1;
u16 d, pll_d = 1;
+ bool dual_rate;
int clk;
int width = aic3x->slot_width;
@@ -1079,14 +1081,25 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
/* Fsref can be 44100 or 48000 */
fsref = (params_rate(params) % 11025 == 0) ? 44100 : 48000;
+ dual_rate = params_rate(params) >= 64000;
/* Try to find a value for Q which allows us to bypass the PLL and
* generate CODEC_CLK directly. */
- for (pll_q = 2; pll_q < 18; pll_q++)
- if (aic3x->sysclk / (128 * pll_q) == fsref) {
- bypass_pll = 1;
- break;
+ if (dual_rate) {
+ for (int i = 0; i < ARRAY_SIZE(dual_rate_q); i++) {
+ pll_q = dual_rate_q[i];
+ if (aic3x->sysclk / (128 * pll_q) == fsref) {
+ bypass_pll = 1;
+ break;
+ }
}
+ } else {
+ for (pll_q = 2; pll_q < 18; pll_q++)
+ if (aic3x->sysclk / (128 * pll_q) == fsref) {
+ bypass_pll = 1;
+ break;
+ }
+ }
if (bypass_pll) {
pll_q &= 0xf;
@@ -1106,13 +1119,13 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
* right DAC to right channel input */
data = (LDAC2LCH | RDAC2RCH);
data |= (fsref == 44100) ? FSREF_44100 : FSREF_48000;
- if (params_rate(params) >= 64000)
+ if (dual_rate)
data |= DUAL_RATE_MODE;
snd_soc_component_write(component, AIC3X_CODEC_DATAPATH_REG, data);
/* codec sample rate select */
data = (fsref * 20) / params_rate(params);
- if (params_rate(params) < 64000)
+ if (!dual_rate)
data /= 2;
data /= 5;
data -= 2;
@@ -1689,8 +1702,15 @@ static int aic3x_component_probe(struct snd_soc_component *component)
return 0;
}
+static int aic3x_of_xlate_dai_id(struct snd_soc_component *component,
+ struct device_node *endpoint)
+{
+ return 0;
+}
+
static const struct snd_soc_component_driver soc_component_dev_aic3x = {
.set_bias_level = aic3x_set_bias_level,
+ .of_xlate_dai_id = aic3x_of_xlate_dai_id,
.probe = aic3x_component_probe,
.controls = aic3x_snd_controls,
.num_controls = ARRAY_SIZE(aic3x_snd_controls),
diff --git a/sound/soc/codecs/ts3a227e.c b/sound/soc/codecs/ts3a227e.c
index 5a7beeadb009..39284e4d420e 100644
--- a/sound/soc/codecs/ts3a227e.c
+++ b/sound/soc/codecs/ts3a227e.c
@@ -423,7 +423,7 @@ static const struct dev_pm_ops ts3a227e_pm = {
};
static const struct i2c_device_id ts3a227e_i2c_ids[] = {
- { "ts3a227e" },
+ { .name = "ts3a227e" },
{ }
};
MODULE_DEVICE_TABLE(i2c, ts3a227e_i2c_ids);
diff --git a/sound/soc/codecs/tscs42xx.c b/sound/soc/codecs/tscs42xx.c
index 7390ab250ebb..dba581857920 100644
--- a/sound/soc/codecs/tscs42xx.c
+++ b/sound/soc/codecs/tscs42xx.c
@@ -1483,8 +1483,8 @@ static int tscs42xx_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tscs42xx_i2c_id[] = {
- { "tscs42A1" },
- { "tscs42A2" },
+ { .name = "tscs42A1" },
+ { .name = "tscs42A2" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tscs42xx_i2c_id);
diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c
index 64d0da40fbaf..aad394937ce6 100644
--- a/sound/soc/codecs/tscs454.c
+++ b/sound/soc/codecs/tscs454.c
@@ -3454,7 +3454,7 @@ static int tscs454_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id tscs454_i2c_id[] = {
- { "tscs454" },
+ { .name = "tscs454" },
{ }
};
MODULE_DEVICE_TABLE(i2c, tscs454_i2c_id);
diff --git a/sound/soc/codecs/uda1334.c b/sound/soc/codecs/uda1334.c
index f799772ff747..54c5cb5b3d4b 100644
--- a/sound/soc/codecs/uda1334.c
+++ b/sound/soc/codecs/uda1334.c
@@ -4,7 +4,6 @@
//
// Based on WM8523 ALSA SoC Audio driver written by Mark Brown
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
diff --git a/sound/soc/codecs/uda1342.c b/sound/soc/codecs/uda1342.c
index b0b29012842d..12f5757f4210 100644
--- a/sound/soc/codecs/uda1342.c
+++ b/sound/soc/codecs/uda1342.c
@@ -319,7 +319,7 @@ static DEFINE_RUNTIME_DEV_PM_OPS(uda1342_pm_ops,
uda1342_suspend, uda1342_resume, NULL);
static const struct i2c_device_id uda1342_i2c_id[] = {
- { "uda1342" },
+ { .name = "uda1342" },
{ }
};
MODULE_DEVICE_TABLE(i2c, uda1342_i2c_id);
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 55c83d95bfba..1dd09d10fc4a 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -38,9 +38,9 @@ struct uda1380_priv {
unsigned int dac_clk;
struct work_struct work;
struct i2c_client *i2c;
- u16 *reg_cache;
struct gpio_desc *power;
struct gpio_desc *reset;
+ u16 reg_cache[];
};
/*
@@ -767,11 +767,15 @@ static int uda1380_i2c_probe(struct i2c_client *i2c)
struct uda1380_priv *uda1380;
int ret;
- uda1380 = devm_kzalloc(&i2c->dev, sizeof(struct uda1380_priv),
+ uda1380 = devm_kzalloc(&i2c->dev,
+ struct_size(uda1380, reg_cache, ARRAY_SIZE(uda1380_reg)),
GFP_KERNEL);
if (uda1380 == NULL)
return -ENOMEM;
+ memcpy(uda1380->reg_cache, uda1380_reg,
+ ARRAY_SIZE(uda1380_reg) * sizeof(*uda1380->reg_cache));
+
uda1380->reset = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
if (IS_ERR(uda1380->reset))
return dev_err_probe(dev, PTR_ERR(uda1380->reset),
@@ -789,11 +793,6 @@ static int uda1380_i2c_probe(struct i2c_client *i2c)
if (device_property_match_string(dev, "dac-clk", "wspll") >= 0)
uda1380->dac_clk = UDA1380_DAC_CLK_WSPLL;
- uda1380->reg_cache = devm_kmemdup_array(&i2c->dev, uda1380_reg, ARRAY_SIZE(uda1380_reg),
- sizeof(uda1380_reg[0]), GFP_KERNEL);
- if (!uda1380->reg_cache)
- return -ENOMEM;
-
i2c_set_clientdata(i2c, uda1380);
uda1380->i2c = i2c;
@@ -803,7 +802,7 @@ static int uda1380_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id uda1380_i2c_id[] = {
- { "uda1380" },
+ { .name = "uda1380" },
{ }
};
MODULE_DEVICE_TABLE(i2c, uda1380_i2c_id);
diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c
index 72a53f95d688..e0169e783ee9 100644
--- a/sound/soc/codecs/wcd937x.c
+++ b/sound/soc/codecs/wcd937x.c
@@ -2499,18 +2499,13 @@ static int wcd937x_soc_codec_probe(struct snd_soc_component *component)
{
struct snd_soc_dapm_context *dapm = snd_soc_component_to_dapm(component);
struct wcd937x_priv *wcd937x = snd_soc_component_get_drvdata(component);
- struct sdw_slave *tx_sdw_dev = wcd937x->tx_sdw_dev;
struct device *dev = component->dev;
- unsigned long time_left;
int i, ret;
u32 chipid;
- time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
- msecs_to_jiffies(5000));
- if (!time_left) {
- dev_err(dev, "soundwire device init timeout\n");
- return -ETIMEDOUT;
- }
+ ret = sdw_slave_wait_for_init(wcd937x->tx_sdw_dev, 5000);
+ if (ret)
+ return ret;
snd_soc_component_init_regmap(component, wcd937x->regmap);
ret = pm_runtime_resume_and_get(dev);
diff --git a/sound/soc/codecs/wcd938x.c b/sound/soc/codecs/wcd938x.c
index cb0a0bfdb6e3..c69e18667a85 100644
--- a/sound/soc/codecs/wcd938x.c
+++ b/sound/soc/codecs/wcd938x.c
@@ -3016,18 +3016,13 @@ static int wcd938x_irq_init(struct wcd938x_priv *wcd, struct device *dev)
static int wcd938x_soc_codec_probe(struct snd_soc_component *component)
{
struct wcd938x_priv *wcd938x = snd_soc_component_get_drvdata(component);
- struct sdw_slave *tx_sdw_dev = wcd938x->tx_sdw_dev;
struct device *dev = component->dev;
- unsigned long time_left;
unsigned int variant;
int ret, i;
- time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
- msecs_to_jiffies(2000));
- if (!time_left) {
- dev_err(dev, "soundwire device init timeout\n");
- return -ETIMEDOUT;
- }
+ ret = sdw_slave_wait_for_init(wcd938x->tx_sdw_dev, 2000);
+ if (ret)
+ return ret;
snd_soc_component_init_regmap(component, wcd938x->regmap);
diff --git a/sound/soc/codecs/wcd939x.c b/sound/soc/codecs/wcd939x.c
index 01f1a08f48e6..010d12466722 100644
--- a/sound/soc/codecs/wcd939x.c
+++ b/sound/soc/codecs/wcd939x.c
@@ -2968,17 +2968,12 @@ static int wcd939x_irq_init(struct wcd939x_priv *wcd, struct device *dev)
static int wcd939x_soc_codec_probe(struct snd_soc_component *component)
{
struct wcd939x_priv *wcd939x = snd_soc_component_get_drvdata(component);
- struct sdw_slave *tx_sdw_dev = wcd939x->tx_sdw_dev;
struct device *dev = component->dev;
- unsigned long time_left;
int ret, i;
- time_left = wait_for_completion_timeout(&tx_sdw_dev->initialization_complete,
- msecs_to_jiffies(2000));
- if (!time_left) {
- dev_err(dev, "soundwire device init timeout\n");
- return -ETIMEDOUT;
- }
+ ret = sdw_slave_wait_for_init(wcd939x->tx_sdw_dev, 2000);
+ if (ret)
+ return ret;
snd_soc_component_init_regmap(component, wcd939x->regmap);
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index 1f59309d8c69..5c1b00acb5bf 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -204,7 +204,7 @@ static int wm1250_ev1_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm1250_ev1_i2c_id[] = {
- { "wm1250-ev1" },
+ { .name = "wm1250-ev1" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm1250_ev1_i2c_id);
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 126be2a2a8f3..9b68ee69324b 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -929,7 +929,7 @@ out:
}
static const struct i2c_device_id wm2000_i2c_id[] = {
- { "wm2000" },
+ { .name = "wm2000" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm2000_i2c_id);
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index 87418c838ca0..ba8ce2e6e615 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -2471,7 +2471,7 @@ static const struct dev_pm_ops wm2200_pm = {
};
static const struct i2c_device_id wm2200_i2c_id[] = {
- { "wm2200" },
+ { .name = "wm2200" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 96fd098a9d36..bd94fa53c362 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -2669,7 +2669,7 @@ static const struct dev_pm_ops wm5100_pm = {
};
static const struct i2c_device_id wm5100_i2c_id[] = {
- { "wm5100" },
+ { .name = "wm5100" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id);
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index bebee333d3fd..137dcd3d7487 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -7,7 +7,6 @@
* Author: Liam Girdwood <lrg@slimlogic.co.uk>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -669,7 +668,7 @@ static int wm8510_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8510_i2c_id[] = {
- { "wm8510" },
+ { .name = "wm8510" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index f003f19766e2..b8832a1d61fe 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -7,7 +7,6 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -518,7 +517,7 @@ err_enable:
}
static const struct i2c_device_id wm8523_i2c_id[] = {
- { "wm8523" },
+ { .name = "wm8523" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
diff --git a/sound/soc/codecs/wm8524.c b/sound/soc/codecs/wm8524.c
index 6b1a7450b0ac..23daf158f35f 100644
--- a/sound/soc/codecs/wm8524.c
+++ b/sound/soc/codecs/wm8524.c
@@ -8,7 +8,6 @@
* Based on WM8523 ALSA SoC Audio driver written by Mark Brown
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 2be265bb0751..eb374ba6e5b5 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -15,7 +15,6 @@
* the secondary audio interfaces are not.
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
@@ -1034,8 +1033,8 @@ static const struct of_device_id wm8580_of_match[] = {
MODULE_DEVICE_TABLE(of, wm8580_of_match);
static const struct i2c_device_id wm8580_i2c_id[] = {
- { "wm8580", (kernel_ulong_t)&wm8580_data },
- { "wm8581", (kernel_ulong_t)&wm8581_data },
+ { .name = "wm8580", .driver_data = (kernel_ulong_t)&wm8580_data },
+ { .name = "wm8581", .driver_data = (kernel_ulong_t)&wm8581_data },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index 2bab9d189519..2db8829661c3 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -9,7 +9,6 @@
* Based on wm8731.c by Richard Purdie
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -455,7 +454,7 @@ static int wm8711_i2c_probe(struct i2c_client *client)
}
static const struct i2c_device_id wm8711_i2c_id[] = {
- { "wm8711" },
+ { .name = "wm8711" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 4c1a80561f06..3109a6a0df74 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -7,7 +7,6 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -296,7 +295,7 @@ static int wm8728_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8728_i2c_id[] = {
- { "wm8728" },
+ { .name = "wm8728" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
diff --git a/sound/soc/codecs/wm8731-i2c.c b/sound/soc/codecs/wm8731-i2c.c
index 1254e583af51..f44f4d3d9394 100644
--- a/sound/soc/codecs/wm8731-i2c.c
+++ b/sound/soc/codecs/wm8731-i2c.c
@@ -11,7 +11,6 @@
*/
#include <linux/i2c.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include "wm8731.h"
@@ -47,7 +46,7 @@ static int wm8731_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8731_i2c_id[] = {
- { "wm8731" },
+ { .name = "wm8731" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8731_i2c_id);
diff --git a/sound/soc/codecs/wm8731-spi.c b/sound/soc/codecs/wm8731-spi.c
index c02086afa7fb..29e58e1e6b79 100644
--- a/sound/soc/codecs/wm8731-spi.c
+++ b/sound/soc/codecs/wm8731-spi.c
@@ -11,7 +11,6 @@
*/
#include <linux/spi/spi.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include "wm8731.h"
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index fee8a37ed1df..33a3f88fffb3 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -7,7 +7,6 @@
* Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -641,7 +640,7 @@ static int wm8737_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8737_i2c_id[] = {
- { "wm8737" },
+ { .name = "wm8737" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8737_i2c_id);
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 4dfbb33edb09..ca56fdfb5088 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -606,7 +606,7 @@ static int wm8741_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8741_i2c_id[] = {
- { "wm8741" },
+ { .name = "wm8741" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 0e1d3ebb15c4..d3f1178c2d34 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -803,8 +803,8 @@ static int wm8750_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8750_i2c_id[] = {
- { "wm8750" },
- { "wm8987" },
+ { .name = "wm8750" },
+ { .name = "wm8987" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index a532a95e8048..ac4008b4832d 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -26,7 +26,6 @@
* an alsa kcontrol. This allows the PCM to remain open.
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
@@ -1581,7 +1580,7 @@ static int wm8753_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8753_i2c_id[] = {
- { "wm8753" },
+ { .name = "wm8753" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index d382b476c89c..b8b4d1e823e6 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -7,7 +7,6 @@
* Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index c3f340657f0c..a8e4f71c77d1 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -9,7 +9,6 @@
* TODO: Input ALC/limiter support
*/
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
@@ -513,8 +512,8 @@ static int wm8776_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8776_i2c_id[] = {
- { "wm8775", WM8775 },
- { "wm8776", WM8776 },
+ { .name = "wm8775", .driver_data = WM8775 },
+ { .name = "wm8776", .driver_data = WM8776 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
diff --git a/sound/soc/codecs/wm8804-i2c.c b/sound/soc/codecs/wm8804-i2c.c
index 3380d7301b17..3c49abd33d28 100644
--- a/sound/soc/codecs/wm8804-i2c.c
+++ b/sound/soc/codecs/wm8804-i2c.c
@@ -31,7 +31,7 @@ static void wm8804_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8804_i2c_id[] = {
- { "wm8804" },
+ { .name = "wm8804" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8804_i2c_id);
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index fea629541acd..a9128cfa6ff1 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -1286,11 +1286,8 @@ static int wm8900_i2c_probe(struct i2c_client *i2c)
return ret;
}
-static void wm8900_i2c_remove(struct i2c_client *client)
-{}
-
static const struct i2c_device_id wm8900_i2c_id[] = {
- { "wm8900" },
+ { .name = "wm8900" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
@@ -1299,8 +1296,7 @@ static struct i2c_driver wm8900_i2c_driver = {
.driver = {
.name = "wm8900",
},
- .probe = wm8900_i2c_probe,
- .remove = wm8900_i2c_remove,
+ .probe = wm8900_i2c_probe,
.id_table = wm8900_i2c_id,
};
#endif
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index f73f6ad06b38..320d7737699d 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -2203,7 +2203,7 @@ static const struct of_device_id wm8903_of_match[] = {
MODULE_DEVICE_TABLE(of, wm8903_of_match);
static const struct i2c_device_id wm8903_i2c_id[] = {
- { "wm8903" },
+ { .name = "wm8903" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8903_i2c_id);
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index 4c73a340f25f..9e5782e50f47 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -2621,9 +2621,9 @@ err_enable:
}
static const struct i2c_device_id wm8904_i2c_id[] = {
- { "wm8904", WM8904 },
- { "wm8912", WM8912 },
- { "wm8918", WM8904 }, /* Actually a subset, updates to follow */
+ { .name = "wm8904", .driver_data = WM8904 },
+ { .name = "wm8912", .driver_data = WM8912 },
+ { .name = "wm8918", .driver_data = WM8904 }, /* Actually a subset, updates to follow */
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 2f55d0c572a4..e631ec072249 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -851,7 +851,7 @@ static int wm8940_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8940_i2c_id[] = {
- { "wm8940" },
+ { .name = "wm8940" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index e1c61e026cbc..c897a9ab764d 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -996,7 +996,7 @@ static int wm8955_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8955_i2c_id[] = {
- { "wm8955" },
+ { .name = "wm8955" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 384e8e703446..a810732c6af0 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -1551,7 +1551,7 @@ static void wm8960_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id wm8960_i2c_id[] = {
- { "wm8960" },
+ { .name = "wm8960" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index cfb8cfc91873..504fc59e4be2 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -967,7 +967,7 @@ static int wm8961_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8961_i2c_id[] = {
- { "wm8961" },
+ { .name = "wm8961" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 8d2435bf44ea..de18b1f85a32 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -3991,7 +3991,7 @@ static const struct dev_pm_ops wm8962_pm = {
};
static const struct i2c_device_id wm8962_i2c_id[] = {
- { "wm8962" },
+ { .name = "wm8962" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8962_i2c_id);
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 46aa556b44fa..a5d2e91b66bb 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -692,7 +692,7 @@ static int wm8971_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8971_i2c_id[] = {
- { "wm8971" },
+ { .name = "wm8971" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id);
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index 0bb5e947f46d..4656652b8e97 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -712,7 +712,7 @@ static int wm8974_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8974_i2c_id[] = {
- { "wm8974" },
+ { .name = "wm8974" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 935761e50865..ad8064bbaaac 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -1059,7 +1059,7 @@ static int wm8978_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8978_i2c_id[] = {
- { "wm8978" },
+ { .name = "wm8978" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8978_i2c_id);
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index cd34f71cf42a..fab25f35fd14 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -1060,7 +1060,7 @@ static int wm8983_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8983_i2c_id[] = {
- { "wm8983" },
+ { .name = "wm8983" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8983_i2c_id);
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index be23c0c608d1..2a64d5a851da 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -1195,8 +1195,8 @@ static int wm8985_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8985_i2c_id[] = {
- { "wm8985", WM8985 },
- { "wm8758", WM8758 },
+ { .name = "wm8985", .driver_data = WM8985 },
+ { .name = "wm8758", .driver_data = WM8758 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8985_i2c_id);
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index 9bffe7a6ccec..741aecc7641a 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -897,7 +897,7 @@ static int wm8988_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8988_i2c_id[] = {
- { "wm8988" },
+ { .name = "wm8988" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 9f2b42025ec9..11dfbbbdcd92 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -1241,7 +1241,7 @@ static int wm8990_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8990_i2c_id[] = {
- { "wm8990" },
+ { .name = "wm8990" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index b8ed2a3e699b..225c235d3d89 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -1315,7 +1315,7 @@ static int wm8991_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8991_i2c_id[] = {
- { "wm8991" },
+ { .name = "wm8991" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8991_i2c_id);
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 1c9299979898..2a94b23319b5 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -1735,7 +1735,7 @@ static void wm8993_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8993_i2c_id[] = {
- { "wm8993" },
+ { .name = "wm8993" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 104ce09c02e0..799989a5bf0f 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -2259,8 +2259,8 @@ static int wm8995_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm8995_i2c_id[] = {
- {"wm8995"},
- {}
+ { .name = "wm8995" },
+ { }
};
MODULE_DEVICE_TABLE(i2c, wm8995_i2c_id);
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 2d9cbf66f7d4..dface555f928 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -3072,7 +3072,7 @@ static void wm8996_i2c_remove(struct i2c_client *client)
}
static const struct i2c_device_id wm8996_i2c_id[] = {
- { "wm8996" },
+ { .name = "wm8996" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8996_i2c_id);
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index 5bfe43c6c1f4..2e4e0a76499d 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -1357,11 +1357,8 @@ static int wm9081_i2c_probe(struct i2c_client *i2c)
return 0;
}
-static void wm9081_i2c_remove(struct i2c_client *client)
-{}
-
static const struct i2c_device_id wm9081_i2c_id[] = {
- { "wm9081" },
+ { .name = "wm9081" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm9081_i2c_id);
@@ -1370,8 +1367,7 @@ static struct i2c_driver wm9081_i2c_driver = {
.driver = {
.name = "wm9081",
},
- .probe = wm9081_i2c_probe,
- .remove = wm9081_i2c_remove,
+ .probe = wm9081_i2c_probe,
.id_table = wm9081_i2c_id,
};
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 5182f0839b7c..8fc24b19313d 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -607,8 +607,8 @@ static int wm9090_i2c_probe(struct i2c_client *i2c)
}
static const struct i2c_device_id wm9090_id[] = {
- { "wm9090" },
- { "wm9093" },
+ { .name = "wm9090" },
+ { .name = "wm9093" },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm9090_id);
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index a637e22c3929..baa75e7ff53b 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -679,6 +679,9 @@ static void wm_adsp_control_remove(struct cs_dsp_coeff_ctl *cs_ctl)
{
struct wm_coeff_ctl *ctl = cs_ctl->priv;
+ if (!ctl)
+ return;
+
cancel_work_sync(&ctl->work);
kfree(ctl->name);
@@ -1167,7 +1170,14 @@ EXPORT_SYMBOL_GPL(wm_adsp2_component_probe);
int wm_adsp2_component_remove(struct wm_adsp *dsp, struct snd_soc_component *component)
{
+ if (!dsp)
+ return 0;
+
+ if (!dsp->component)
+ return 0;
+
cs_dsp_cleanup_debugfs(&dsp->cs_dsp);
+ dsp->component = NULL;
return 0;
}
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c
index 2fc234adca5f..5174614c3e83 100644
--- a/sound/soc/codecs/wsa881x.c
+++ b/sound/soc/codecs/wsa881x.c
@@ -3,7 +3,6 @@
// Copyright (c) 2019, Linaro Limited
#include <linux/bitops.h>
-#include <linux/gpio.h>
#include <linux/gpio/consumer.h>
#include <linux/module.h>
#include <linux/regmap.h>
@@ -672,11 +671,6 @@ struct wsa881x_priv {
struct sdw_stream_runtime *sruntime;
struct sdw_port_config port_config[WSA881X_MAX_SWR_PORTS];
struct gpio_desc *sd_n;
- /*
- * Logical state for SD_N GPIO: high for shutdown, low for enable.
- * For backwards compatibility.
- */
- unsigned int sd_n_val;
int active_ports;
bool hw_init;
bool port_prepared[WSA881X_MAX_SWR_PORTS];
@@ -1121,31 +1115,11 @@ static int wsa881x_probe(struct sdw_slave *pdev,
if (!wsa881x)
return -ENOMEM;
- wsa881x->sd_n = devm_gpiod_get_optional(dev, "powerdown", 0);
+ wsa881x->sd_n = devm_gpiod_get_optional(dev, "powerdown", GPIOD_OUT_LOW);
if (IS_ERR(wsa881x->sd_n))
return dev_err_probe(dev, PTR_ERR(wsa881x->sd_n),
"Shutdown Control GPIO not found\n");
- /*
- * Backwards compatibility work-around.
- *
- * The SD_N GPIO is active low, however upstream DTS used always active
- * high. Changing the flag in driver and DTS will break backwards
- * compatibility, so add a simple value inversion to work with both old
- * and new DTS.
- *
- * This won't work properly with DTS using the flags properly in cases:
- * 1. Old DTS with proper ACTIVE_LOW, however such case was broken
- * before as the driver required the active high.
- * 2. New DTS with proper ACTIVE_HIGH (intended), which is rare case
- * (not existing upstream) but possible. This is the price of
- * backwards compatibility, therefore this hack should be removed at
- * some point.
- */
- wsa881x->sd_n_val = gpiod_is_active_low(wsa881x->sd_n);
- if (!wsa881x->sd_n_val)
- dev_warn(dev, "Using ACTIVE_HIGH for shutdown GPIO. Your DTB might be outdated or you use unsupported configuration for the GPIO.");
-
dev_set_drvdata(dev, wsa881x);
wsa881x->slave = pdev;
wsa881x->dev = dev;
@@ -1158,7 +1132,6 @@ static int wsa881x_probe(struct sdw_slave *pdev,
pdev->prop.sink_dpn_prop = wsa_sink_dpn_prop;
pdev->prop.scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY;
pdev->prop.clk_stop_mode1 = true;
- gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
wsa881x->regmap = devm_regmap_init_sdw(pdev, &wsa881x_regmap_config);
if (IS_ERR(wsa881x->regmap))
@@ -1181,7 +1154,7 @@ static int wsa881x_runtime_suspend(struct device *dev)
struct regmap *regmap = dev_get_regmap(dev, NULL);
struct wsa881x_priv *wsa881x = dev_get_drvdata(dev);
- gpiod_direction_output(wsa881x->sd_n, wsa881x->sd_n_val);
+ gpiod_direction_output(wsa881x->sd_n, 1);
regcache_cache_only(regmap, true);
regcache_mark_dirty(regmap);
@@ -1194,16 +1167,14 @@ static int wsa881x_runtime_resume(struct device *dev)
struct sdw_slave *slave = dev_to_sdw_dev(dev);
struct regmap *regmap = dev_get_regmap(dev, NULL);
struct wsa881x_priv *wsa881x = dev_get_drvdata(dev);
- unsigned long time;
+ int ret;
- gpiod_direction_output(wsa881x->sd_n, !wsa881x->sd_n_val);
+ gpiod_direction_output(wsa881x->sd_n, 0);
- time = wait_for_completion_timeout(&slave->initialization_complete,
- msecs_to_jiffies(WSA881X_PROBE_TIMEOUT));
- if (!time) {
- dev_err(dev, "Initialization not complete, timed out\n");
- gpiod_direction_output(wsa881x->sd_n, wsa881x->sd_n_val);
- return -ETIMEDOUT;
+ ret = sdw_slave_wait_for_init(slave, WSA881X_PROBE_TIMEOUT);
+ if (ret) {
+ gpiod_direction_output(wsa881x->sd_n, 1);
+ return ret;
}
regcache_cache_only(regmap, false);
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 828524c90f17..8ae59c094878 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -165,7 +165,7 @@ config SND_SOC_IMX_AUDMUX
config SND_POWERPC_SOC
tristate "SoC Audio for Freescale PowerPC CPUs"
- depends on FSL_SOC || PPC_MPC52xx
+ depends on FSL_SOC || PPC_MPC52xx || (PPC && COMPILE_TEST)
help
Say Y or M if you want to add support for codecs attached to
the PowerPC CPUs.
@@ -226,7 +226,7 @@ config SND_SOC_P1022_RDK
config SND_SOC_MPC5200_I2S
tristate "Freescale MPC5200 PSC in I2S mode driver"
- depends on PPC_MPC52xx && PPC_BESTCOMM
+ depends on PPC_BESTCOMM
select SND_MPC52xx_DMA
select PPC_BESTCOMM_GEN_BD
help
@@ -234,7 +234,7 @@ config SND_SOC_MPC5200_I2S
config SND_SOC_MPC5200_AC97
tristate "Freescale MPC5200 PSC in AC97 mode driver"
- depends on PPC_MPC52xx && PPC_BESTCOMM
+ depends on PPC_BESTCOMM
select SND_SOC_AC97_BUS
select SND_MPC52xx_DMA
select PPC_BESTCOMM_GEN_BD
@@ -358,6 +358,7 @@ config SND_SOC_IMX_RPMSG
depends on OF && I2C
select SND_SOC_IMX_PCM_RPMSG
select SND_SOC_IMX_AUDIO_RPMSG
+ select SND_SIMPLE_CARD_UTILS
help
SoC Audio support for i.MX boards with rpmsg.
There should be rpmsg devices defined in other core (M core)
diff --git a/sound/soc/fsl/eukrea-tlv320.c b/sound/soc/fsl/eukrea-tlv320.c
index 6be074ea0b3f..5bb31a5cdf23 100644
--- a/sound/soc/fsl/eukrea-tlv320.c
+++ b/sound/soc/fsl/eukrea-tlv320.c
@@ -19,7 +19,6 @@
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
-#include <asm/mach-types.h>
#include "../codecs/tlv320aic23.h"
#include "imx-ssi.h"
@@ -142,7 +141,7 @@ static int eukrea_tlv320_probe(struct platform_device *pdev)
eukrea_tlv320.name = "cpuimx-audio";
}
- if (machine_is_eukrea_cpuimx27() ||
+ if (of_machine_is_compatible("eukrea,cpuimx27") ||
(tmp_np = of_find_compatible_node(NULL, NULL, "fsl,imx21-audmux"))) {
imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
IMX_AUDMUX_V1_PCR_SYN |
@@ -159,12 +158,12 @@ static int eukrea_tlv320_probe(struct platform_device *pdev)
IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
);
of_node_put(tmp_np);
- } else if (machine_is_eukrea_cpuimx25sd() ||
- machine_is_eukrea_cpuimx35sd() ||
- machine_is_eukrea_cpuimx51sd() ||
+ } else if (of_machine_is_compatible("eukrea,cpuimx25") ||
+ of_machine_is_compatible("eukrea,cpuimx35") ||
+ of_machine_is_compatible("eukrea,cpuimx51") ||
(tmp_np = of_find_compatible_node(NULL, NULL, "fsl,imx31-audmux"))) {
if (!np)
- ext_port = machine_is_eukrea_cpuimx25sd() ?
+ ext_port = of_machine_is_compatible("eukrea,cpuimx25") ?
4 : 3;
imx_audmux_v2_configure_port(int_port,
diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c
index 70a6159430ed..709543308fe9 100644
--- a/sound/soc/fsl/fsl-asoc-card.c
+++ b/sound/soc/fsl/fsl-asoc-card.c
@@ -40,6 +40,33 @@
/* Default DAI format without Master and Slave flag */
#define DAI_FMT_BASE (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF)
+static const u32 cs42888_rates_48k[] = {
+ 48000, 96000, 192000,
+};
+
+static const u32 cs42888_rates_44k[] = {
+ 44100, 88200, 176400,
+};
+
+static const u32 cs42888_channels[] = {
+ 1, 2, 4, 6, 8,
+};
+
+static const struct snd_pcm_hw_constraint_list cs42888_rate_48k_constraints = {
+ .list = cs42888_rates_48k,
+ .count = ARRAY_SIZE(cs42888_rates_48k),
+};
+
+static const struct snd_pcm_hw_constraint_list cs42888_rate_44k_constraints = {
+ .list = cs42888_rates_44k,
+ .count = ARRAY_SIZE(cs42888_rates_44k),
+};
+
+static const struct snd_pcm_hw_constraint_list cs42888_channel_constraints = {
+ .list = cs42888_channels,
+ .count = ARRAY_SIZE(cs42888_channels),
+};
+
/**
* struct codec_priv - CODEC private data
* @mclk: Main clock of the CODEC
@@ -48,6 +75,9 @@
* @mclk_id: MCLK (or main clock) id for set_sysclk()
* @fll_id: FLL (or secordary clock) id for set_sysclk()
* @pll_id: PLL id for set_pll()
+ * @pll_ratio_s24: PLL output ratio for S24_LE format (PLL_freq = sample_rate × ratio)
+ * Default is 384, but some codecs (e.g., WM8904) require lower values
+ * to stay within PLL frequency limits
*/
struct codec_priv {
struct clk *mclk;
@@ -56,6 +86,7 @@ struct codec_priv {
u32 mclk_id;
int fll_id;
int pll_id;
+ int pll_ratio_s24;
};
/**
@@ -87,12 +118,15 @@ struct cpu_priv {
* @codec_priv: CODEC private data
* @cpu_priv: CPU private data
* @card: ASoC card structure
+ * @constraint_rates: array of supported rates
+ * @constraint_channels: array of supported channels
* @streams: Mask of current active streams
* @sample_rate: Current sample rate
* @sample_format: Current sample format
* @asrc_rate: ASRC sample rate used by Back-Ends
* @asrc_format: ASRC sample format used by Back-Ends
* @dai_fmt: DAI format between CPU and CODEC
+ * @exclude_format: excluded format;
* @name: Card name
*/
@@ -104,12 +138,15 @@ struct fsl_asoc_card_priv {
struct codec_priv codec_priv[2];
struct cpu_priv cpu_priv;
struct snd_soc_card card;
+ const struct snd_pcm_hw_constraint_list *constraint_rates;
+ const struct snd_pcm_hw_constraint_list *constraint_channels;
u8 streams;
u32 sample_rate;
snd_pcm_format_t sample_format;
u32 asrc_rate;
snd_pcm_format_t asrc_format;
u32 dai_fmt;
+ u64 exclude_format;
char name[32];
};
@@ -222,7 +259,7 @@ static int fsl_asoc_card_hw_params(struct snd_pcm_substream *substream,
if (codec_priv->pll_id >= 0 && codec_priv->fll_id >= 0) {
if (priv->sample_format == SNDRV_PCM_FORMAT_S24_LE)
- pll_out = priv->sample_rate * 384;
+ pll_out = priv->sample_rate * codec_priv->pll_ratio_s24;
else
pll_out = priv->sample_rate * 256;
@@ -291,7 +328,47 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream)
return 0;
}
+static int fsl_asoc_card_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct fsl_asoc_card_priv *priv = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ if (priv->exclude_format && !rtd->dai_link->no_pcm) {
+ ret = snd_pcm_hw_constraint_mask64(runtime,
+ SNDRV_PCM_HW_PARAM_FORMAT,
+ ~priv->exclude_format);
+ if (ret)
+ return ret;
+ }
+
+ if (priv->constraint_channels) {
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ priv->constraint_channels);
+ if (ret)
+ return ret;
+ }
+
+ /*
+ * Apply rate constraints only to frontend DAI links (no_pcm = 0).
+ * Skip DPCM backend (no_pcm = 1) as rate is fixed by be_hw_params_fixup()
+ * and ASRC frontend handles rate conversion.
+ */
+ if (priv->constraint_rates && !rtd->dai_link->no_pcm) {
+ ret = snd_pcm_hw_constraint_list(runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ priv->constraint_rates);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
static const struct snd_soc_ops fsl_asoc_card_ops = {
+ .startup = fsl_asoc_card_startup,
.hw_params = fsl_asoc_card_hw_params,
.hw_free = fsl_asoc_card_hw_free,
};
@@ -742,6 +819,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
for (codec_idx = 0; codec_idx < 2; codec_idx++) {
priv->codec_priv[codec_idx].fll_id = -1;
priv->codec_priv[codec_idx].pll_id = -1;
+ priv->codec_priv[codec_idx].pll_ratio_s24 = 384;
}
/* Diversify the card configurations */
@@ -753,6 +831,14 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
priv->cpu_priv.sysclk_dir[RX] = SND_SOC_CLOCK_OUT;
priv->cpu_priv.slot_width = 32;
priv->dai_fmt |= SND_SOC_DAIFMT_CBC_CFC;
+ priv->constraint_channels = &cs42888_channel_constraints;
+ if (priv->codec_priv[0].mclk_freq % 12288000 == 0)
+ priv->constraint_rates = &cs42888_rate_48k_constraints;
+ else if (priv->codec_priv[0].mclk_freq % 11289600 == 0)
+ priv->constraint_rates = &cs42888_rate_44k_constraints;
+ else
+ dev_warn(&pdev->dev, "Unknown MCLK frequency %lu, no rate constraints\n",
+ priv->codec_priv[0].mclk_freq);
} else if (of_device_is_compatible(np, "fsl,imx-audio-cs427x")) {
codec_dai_name[0] = "cs4271-hifi";
priv->codec_priv[0].mclk_id = CS427x_SYSCLK_MCLK;
@@ -779,11 +865,30 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
priv->codec_priv[0].fll_id = WM8962_SYSCLK_FLL;
priv->codec_priv[0].pll_id = WM8962_FLL;
priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
+ /*
+ * WM8962 has same BCLK generation limitations as WM8960.
+ * See WM8960 section for detailed explanation.
+ */
+ if (of_node_name_eq(cpu_np, "sai"))
+ priv->exclude_format = SNDRV_PCM_FMTBIT_S20_3LE;
} else if (of_device_is_compatible(np, "fsl,imx-audio-wm8960")) {
codec_dai_name[0] = "wm8960-hifi";
priv->codec_priv[0].fll_id = WM8960_SYSCLK_AUTO;
priv->codec_priv[0].pll_id = WM8960_SYSCLK_AUTO;
priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
+ /*
+ * WM8960 in master mode cannot generate exact 1.92 MHz BCLK
+ * required for S20_3LE (48kHz × 2ch × 20bit). Closest available
+ * is 2.048 MHz (SYSCLK/6), which causes right channel corruption.
+ *
+ * In SAI master mode, SAI derive BCLK from MCLK using integer
+ * dividers only. S20_3LE requires non-integer divider ratios
+ * with standard MCLK frequencies. For example, 48kHz stereo
+ * needs 1.920 MHz BCLK, which requires a divider of 6.4 from
+ * 12.288 MHz MCLK (not an integer).
+ */
+ if (of_node_name_eq(cpu_np, "sai"))
+ priv->exclude_format = SNDRV_PCM_FMTBIT_S20_3LE;
} else if (of_device_is_compatible(np, "fsl,imx-audio-ac97")) {
codec_dai_name[0] = "ac97-hifi";
priv->dai_fmt = SND_SOC_DAIFMT_AC97;
@@ -835,6 +940,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
priv->codec_priv[0].mclk_id = WM8904_FLL_MCLK;
priv->codec_priv[0].fll_id = WM8904_CLK_FLL;
priv->codec_priv[0].pll_id = WM8904_FLL_MCLK;
+ priv->codec_priv[0].pll_ratio_s24 = 192;
priv->dai_fmt |= SND_SOC_DAIFMT_CBP_CFP;
} else if (of_device_is_compatible(np, "fsl,imx-audio-spdif")) {
ret = fsl_asoc_card_spdif_init(codec_np, cpu_np, codec_dai_name, priv);
@@ -989,6 +1095,8 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
if (asrc_pdev) {
/* DPCM DAI Links only if ASRC exists */
+ priv->dai_link[1].dpcm_merged_chan = 1;
+ priv->dai_link[1].ignore_pmdown_time = 1;
priv->dai_link[1].cpus->of_node = asrc_np;
priv->dai_link[1].platforms->of_node = asrc_np;
for_each_link_codecs((&(priv->dai_link[2])), codec_idx, codec_comp) {
@@ -998,6 +1106,7 @@ static int fsl_asoc_card_probe(struct platform_device *pdev)
}
priv->dai_link[2].cpus->of_node = cpu_np;
priv->dai_link[2].dai_fmt = priv->dai_fmt;
+ priv->dai_link[2].ignore_pmdown_time = 1;
priv->card.num_links = 3;
ret = of_property_read_u32(asrc_np, "fsl,asrc-rate",
diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c
index 5aa96af994c4..38f2b7c63133 100644
--- a/sound/soc/fsl/fsl_asrc_dma.c
+++ b/sound/soc/fsl/fsl_asrc_dma.c
@@ -288,6 +288,26 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component,
config_be.dst_addr_width = buswidth;
config_be.dst_maxburst = dma_params_be->maxburst;
+ /*
+ * For eDMA, the back-end may report a maxburst size that is not evenly
+ * divisible by the channel count. This causes the DMA transfer length
+ * to misalign with the FIFO boundary, resulting in wrong data and
+ * audible noise. Align maxburst to the nearest valid boundary:
+ * - If maxburst >= channel count, override to the channel count so
+ * each transfer equals exactly one audio frame.
+ * - If maxburst < channel count, override to 1 to avoid partial-frame
+ * transfers.
+ */
+ if (asrc->use_edma && (dma_params_be->maxburst % params_channels(params))) {
+ if (dma_params_be->maxburst >= params_channels(params)) {
+ config_be.src_maxburst = params_channels(params);
+ config_be.dst_maxburst = params_channels(params);
+ } else {
+ config_be.src_maxburst = 1;
+ config_be.dst_maxburst = 1;
+ }
+ }
+
memset(&audio_config, 0, sizeof(audio_config));
config_be.peripheral_config = &audio_config;
config_be.peripheral_size = sizeof(audio_config);
diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c
index da401561e2de..8f2aa8f7d4e8 100644
--- a/sound/soc/fsl/fsl_aud2htx.c
+++ b/sound/soc/fsl/fsl_aud2htx.c
@@ -5,7 +5,6 @@
#include <linux/clk-provider.h>
#include <linux/delay.h>
#include <linux/dmaengine.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c
index 40a3b7432174..f819f33ec46b 100644
--- a/sound/soc/fsl/fsl_audmix.c
+++ b/sound/soc/fsl/fsl_audmix.c
@@ -117,6 +117,9 @@ static int fsl_audmix_put_mix_clk_src(struct snd_kcontrol *kcontrol,
unsigned int *item = ucontrol->value.enumerated.item;
unsigned int reg_val, val, mix_clk;
+ if (item[0] >= e->items)
+ return -EINVAL;
+
/* Get current state */
reg_val = snd_soc_component_read(comp, FSL_AUDMIX_CTR);
mix_clk = ((reg_val & FSL_AUDMIX_CTR_MIXCLK_MASK)
@@ -157,6 +160,9 @@ static int fsl_audmix_put_out_src(struct snd_kcontrol *kcontrol,
unsigned int reg_val, val, mask = 0, ctr = 0;
int ret;
+ if (item[0] >= e->items)
+ return -EINVAL;
+
/* Get current state */
reg_val = snd_soc_component_read(comp, FSL_AUDMIX_CTR);
diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c
index 2e887f1f1f36..60ac8eabab9d 100644
--- a/sound/soc/fsl/fsl_micfil.c
+++ b/sound/soc/fsl/fsl_micfil.c
@@ -74,6 +74,7 @@ struct fsl_micfil {
int irq[MICFIL_IRQ_LINES];
enum quality quality;
int dc_remover;
+ int dc_out_remover;
int vad_init_mode;
int vad_enabled;
int vad_detected;
@@ -347,6 +348,11 @@ static const char * const micfil_dc_remover_texts[] = {
"Cut-off @152Hz", "Bypass",
};
+static const char * const micfil_dc_out_remover_texts[] = {
+ "Cut-off @20Hz", "Cut-off @13.3Hz",
+ "Cut-off @40Hz", "Bypass",
+};
+
static const struct soc_enum hwvad_enable_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_hwvad_enable),
micfil_hwvad_enable);
@@ -360,6 +366,9 @@ static const struct soc_enum hwvad_hpf_enum =
static const struct soc_enum fsl_micfil_dc_remover_enum =
SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_dc_remover_texts),
micfil_dc_remover_texts);
+static const struct soc_enum fsl_micfil_dc_out_remover_enum =
+ SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(micfil_dc_out_remover_texts),
+ micfil_dc_out_remover_texts);
static int micfil_put_dc_remover_state(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -405,6 +414,50 @@ static int micfil_get_dc_remover_state(struct snd_kcontrol *kcontrol,
return 0;
}
+static int micfil_put_dc_out_remover_state(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
+ unsigned int *item = ucontrol->value.enumerated.item;
+ int val = snd_soc_enum_item_to_val(e, item[0]);
+ int i = 0, ret = 0;
+ u32 reg_val = 0;
+
+ if (val < 0 || val > 3)
+ return -EINVAL;
+
+ ret = pm_runtime_resume_and_get(comp->dev);
+ if (ret)
+ return ret;
+
+ micfil->dc_out_remover = val;
+
+ /* Calculate total value for all channels */
+ for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++)
+ reg_val |= val << MICFIL_DC_CHX_SHIFT(i);
+
+ /* Update DC Remover mode for all channels */
+ ret = snd_soc_component_update_bits(comp, REG_MICFIL_DC_OUT_CTRL,
+ MICFIL_DC_CTRL_CONFIG, reg_val);
+
+ pm_runtime_put_autosuspend(comp->dev);
+
+ return ret;
+}
+
+static int micfil_get_dc_out_remover_state(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol);
+ struct fsl_micfil *micfil = snd_soc_component_get_drvdata(comp);
+
+ ucontrol->value.enumerated.item[0] = micfil->dc_out_remover;
+
+ return 0;
+}
+
static int hwvad_put_enable(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -525,6 +578,11 @@ static const struct snd_kcontrol_new fsl_micfil_volume_sx_controls[] = {
MICFIL_OUTGAIN_CHX_SHIFT(7), 0x8, 0xF, gain_tlv),
};
+static const struct snd_kcontrol_new fsl_micfil_dc_out_controls[] = {
+ SOC_ENUM_EXT("MICFIL DC Out Remover Control", fsl_micfil_dc_out_remover_enum,
+ micfil_get_dc_out_remover_state, micfil_put_dc_out_remover_state),
+};
+
static const struct snd_kcontrol_new fsl_micfil_snd_controls[] = {
SOC_ENUM_EXT("MICFIL Quality Select",
fsl_micfil_quality_enum,
@@ -1047,6 +1105,19 @@ static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai)
}
micfil->dc_remover = MICFIL_DC_BYPASS;
+ if (micfil->soc->use_verid) {
+ val = 0;
+ for (i = 0; i < MICFIL_OUTPUT_CHANNELS; i++)
+ val |= MICFIL_DC_BYPASS << MICFIL_DC_CHX_SHIFT(i);
+ ret = regmap_update_bits(micfil->regmap, REG_MICFIL_DC_OUT_CTRL,
+ MICFIL_DC_CTRL_CONFIG, val);
+ if (ret) {
+ dev_err(dev, "failed to set DC OUT Remover mode bits\n");
+ return ret;
+ }
+ micfil->dc_out_remover = MICFIL_DC_BYPASS;
+ }
+
snd_soc_dai_init_dma_data(cpu_dai, NULL,
&micfil->dma_params_rx);
@@ -1071,6 +1142,10 @@ static int fsl_micfil_component_probe(struct snd_soc_component *component)
snd_soc_add_component_controls(component, fsl_micfil_range_controls,
ARRAY_SIZE(fsl_micfil_range_controls));
+ if (micfil->soc->use_verid)
+ snd_soc_add_component_controls(component, fsl_micfil_dc_out_controls,
+ ARRAY_SIZE(fsl_micfil_dc_out_controls));
+
return 0;
}
@@ -1117,6 +1192,7 @@ static const struct reg_default fsl_micfil_reg_defaults[] = {
{REG_MICFIL_DATACH6, 0x00000000},
{REG_MICFIL_DATACH7, 0x00000000},
{REG_MICFIL_DC_CTRL, 0x00000000},
+ {REG_MICFIL_DC_OUT_CTRL, 0x00000000},
{REG_MICFIL_OUT_CTRL, 0x00000000},
{REG_MICFIL_OUT_STAT, 0x00000000},
{REG_MICFIL_VAD0_CTRL1, 0x00000000},
@@ -1143,6 +1219,7 @@ static const struct reg_default fsl_micfil_reg_defaults_v2[] = {
{REG_MICFIL_DATACH6 - 0x4, 0x00000000},
{REG_MICFIL_DATACH7 - 0x4, 0x00000000},
{REG_MICFIL_DC_CTRL, 0x00000000},
+ {REG_MICFIL_DC_OUT_CTRL, 0x00000000},
{REG_MICFIL_OUT_CTRL, 0x00000000},
{REG_MICFIL_OUT_STAT, 0x00000000},
{REG_MICFIL_VAD0_CTRL1, 0x00000000},
@@ -1179,6 +1256,7 @@ static bool fsl_micfil_readable_reg(struct device *dev, unsigned int reg)
case REG_MICFIL_VAD0_NDATA:
case REG_MICFIL_VAD0_ZCD:
return true;
+ case REG_MICFIL_DC_OUT_CTRL:
case REG_MICFIL_FSYNC_CTRL:
case REG_MICFIL_VERID:
case REG_MICFIL_PARAM:
@@ -1210,6 +1288,7 @@ static bool fsl_micfil_writeable_reg(struct device *dev, unsigned int reg)
case REG_MICFIL_VAD0_NCONFIG:
case REG_MICFIL_VAD0_ZCD:
return true;
+ case REG_MICFIL_DC_OUT_CTRL:
case REG_MICFIL_FSYNC_CTRL:
if (micfil->soc->use_verid)
return true;
diff --git a/sound/soc/fsl/fsl_micfil.h b/sound/soc/fsl/fsl_micfil.h
index fdfe4e7125bc..e271c6073f42 100644
--- a/sound/soc/fsl/fsl_micfil.h
+++ b/sound/soc/fsl/fsl_micfil.h
@@ -22,6 +22,7 @@
#define REG_MICFIL_DATACH6 0x3C
#define REG_MICFIL_DATACH7 0x40
#define REG_MICFIL_DC_CTRL 0x64
+#define REG_MICFIL_DC_OUT_CTRL 0x68
#define REG_MICFIL_OUT_CTRL 0x74
#define REG_MICFIL_OUT_STAT 0x7C
#define REG_MICFIL_FSYNC_CTRL 0x80
diff --git a/sound/soc/fsl/fsl_qmc_audio.c b/sound/soc/fsl/fsl_qmc_audio.c
index 76e014dfb6d7..d0f644573f49 100644
--- a/sound/soc/fsl/fsl_qmc_audio.c
+++ b/sound/soc/fsl/fsl_qmc_audio.c
@@ -905,7 +905,6 @@ static int qmc_audio_probe(struct platform_device *pdev)
{
struct device_node *np = pdev->dev.of_node;
struct qmc_audio *qmc_audio;
- struct device_node *child;
unsigned int i;
int ret;
@@ -931,14 +930,12 @@ static int qmc_audio_probe(struct platform_device *pdev)
}
i = 0;
- for_each_available_child_of_node(np, child) {
+ for_each_available_child_of_node_scoped(np, child) {
ret = qmc_audio_dai_parse(qmc_audio, child,
qmc_audio->dais + i,
qmc_audio->dai_drivers + i);
- if (ret) {
- of_node_put(child);
+ if (ret)
return ret;
- }
i++;
}
diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c
index bd336d2e4cb3..9661602b53c5 100644
--- a/sound/soc/fsl/fsl_sai.c
+++ b/sound/soc/fsl/fsl_sai.c
@@ -355,6 +355,9 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
unsigned int ofs = sai->soc_data->reg_offset;
u32 val_cr2 = 0, val_cr4 = 0;
+ if (sai->is_bit_clock_swap)
+ val_cr2 |= FSL_SAI_CR2_BCS;
+
if (!sai->is_lsb_first)
val_cr4 |= FSL_SAI_CR4_MF;
@@ -453,7 +456,8 @@ static int fsl_sai_set_dai_fmt_tr(struct snd_soc_dai *cpu_dai,
}
regmap_update_bits(sai->regmap, FSL_SAI_xCR2(tx, ofs),
- FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR, val_cr2);
+ FSL_SAI_CR2_BCS | FSL_SAI_CR2_BCP | FSL_SAI_CR2_BCD_MSTR,
+ val_cr2);
regmap_update_bits(sai->regmap, FSL_SAI_xCR4(tx, ofs),
FSL_SAI_CR4_MF | FSL_SAI_CR4_FSE |
FSL_SAI_CR4_FSP | FSL_SAI_CR4_FSD_MSTR, val_cr4);
@@ -793,7 +797,7 @@ static int fsl_sai_hw_params(struct snd_pcm_substream *substream,
FSL_SAI_CR4_FSD_MSTR, FSL_SAI_CR4_FSD_MSTR);
regmap_write(sai->regmap, FSL_SAI_xMR(tx),
- ~0UL - ((1 << min(channels, slots)) - 1));
+ ~GENMASK_U32(min(channels, slots) - 1, 0));
return 0;
}
@@ -1370,6 +1374,31 @@ static int fsl_sai_check_version(struct device *dev)
return 0;
}
+static int fsl_sai_reset_hw(struct device *dev)
+{
+ struct fsl_sai *sai = dev_get_drvdata(dev);
+ unsigned char ofs = sai->soc_data->reg_offset;
+ int ret;
+
+ /*
+ * Clear TCSR/RCSR to reset SAI and disable all interrupts.
+ * Bootloader may leave SAI running causing interrupt storm.
+ */
+ ret = regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), 0);
+ if (ret) {
+ dev_err(dev, "Failed to clear TCSR: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_write(sai->regmap, FSL_SAI_RCSR(ofs), 0);
+ if (ret) {
+ dev_err(dev, "Failed to clear RCSR: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
/*
* Calculate the offset between first two datalines, don't
* different offset in one case.
@@ -1507,6 +1536,7 @@ static int fsl_sai_probe(struct platform_device *pdev)
sai->soc_data = of_device_get_match_data(dev);
sai->is_lsb_first = of_property_read_bool(np, "lsb-first");
+ sai->is_bit_clock_swap = of_property_read_bool(np, "fsl,sai-bit-clock-swap");
base = devm_platform_get_and_ioremap_resource(pdev, 0, &sai->res);
if (IS_ERR(base))
@@ -1575,13 +1605,6 @@ static int fsl_sai_probe(struct platform_device *pdev)
if (irq < 0)
return irq;
- ret = devm_request_irq(dev, irq, fsl_sai_isr, IRQF_SHARED,
- np->name, sai);
- if (ret) {
- dev_err(dev, "failed to claim irq %u\n", irq);
- return ret;
- }
-
memcpy(&sai->cpu_dai_drv, fsl_sai_dai_template,
sizeof(*fsl_sai_dai_template) * ARRAY_SIZE(fsl_sai_dai_template));
@@ -1656,6 +1679,10 @@ static int fsl_sai_probe(struct platform_device *pdev)
if (ret < 0)
dev_warn(dev, "Error reading SAI version: %d\n", ret);
+ ret = fsl_sai_reset_hw(dev);
+ if (ret < 0)
+ dev_warn(dev, "Failed to reset hardware: %d\n", ret);
+
/* Select MCLK direction */
if (sai->mclk_direction_output &&
sai->soc_data->max_register >= FSL_SAI_MCTL) {
@@ -1667,6 +1694,13 @@ static int fsl_sai_probe(struct platform_device *pdev)
if (ret < 0 && ret != -ENOSYS)
goto err_pm_get_sync;
+ ret = devm_request_irq(dev, irq, fsl_sai_isr, IRQF_SHARED,
+ np->name, sai);
+ if (ret) {
+ dev_err(dev, "failed to claim irq %u\n", irq);
+ goto err_pm_get_sync;
+ }
+
if (of_device_is_compatible(np, "fsl,imx952-sai") &&
!of_property_read_string(np, "fsl,sai-amix-mode", &str)) {
if (!strcmp(str, "bypass"))
diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h
index af967833b6ed..6d84e5ff2258 100644
--- a/sound/soc/fsl/fsl_sai.h
+++ b/sound/soc/fsl/fsl_sai.h
@@ -118,6 +118,7 @@
/* SAI Transmit and Receive Configuration 2 Register */
#define FSL_SAI_CR2_SYNC BIT(30)
+#define FSL_SAI_CR2_BCS BIT(29)
#define FSL_SAI_CR2_BCI BIT(28)
#define FSL_SAI_CR2_MSEL_MASK (0x3 << 26)
#define FSL_SAI_CR2_MSEL_BUS 0
@@ -301,6 +302,7 @@ struct fsl_sai {
struct fsl_sai_dl_cfg *dl_cfg;
unsigned int dl_cfg_cnt;
bool mclk_direction_output;
+ bool is_bit_clock_swap;
unsigned int mclk_id[2];
unsigned int mclk_streams;
diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c
index 031e5272215d..2a4813c6cda9 100644
--- a/sound/soc/fsl/imx-pcm-rpmsg.c
+++ b/sound/soc/fsl/imx-pcm-rpmsg.c
@@ -632,6 +632,7 @@ static const struct snd_soc_component_driver imx_rpmsg_soc_component = {
.pointer = imx_rpmsg_pcm_pointer,
.ack = imx_rpmsg_pcm_ack,
.prepare = imx_rpmsg_pcm_prepare,
+ .debugfs_prefix = "rpmsg",
};
static void imx_rpmsg_pcm_work(struct work_struct *work)
@@ -689,7 +690,6 @@ static void imx_rpmsg_pcm_work(struct work_struct *work)
static int imx_rpmsg_pcm_probe(struct platform_device *pdev)
{
- struct snd_soc_component *component;
struct rpmsg_info *info;
int ret, i;
@@ -741,16 +741,6 @@ static int imx_rpmsg_pcm_probe(struct platform_device *pdev)
if (ret)
goto fail;
- component = snd_soc_lookup_component(&pdev->dev, NULL);
- if (!component) {
- ret = -EINVAL;
- goto fail;
- }
-
-#ifdef CONFIG_DEBUG_FS
- component->debugfs_prefix = "rpmsg";
-#endif
-
return 0;
fail:
diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c
index 40e0043cfe15..5f1af258caf2 100644
--- a/sound/soc/fsl/imx-rpmsg.c
+++ b/sound/soc/fsl/imx-rpmsg.c
@@ -12,6 +12,7 @@
#include <sound/control.h>
#include <sound/pcm_params.h>
#include <sound/soc-dapm.h>
+#include <sound/simple_card_utils.h>
#include "imx-pcm-rpmsg.h"
struct imx_rpmsg {
@@ -19,6 +20,7 @@ struct imx_rpmsg {
struct snd_soc_card card;
unsigned long sysclk;
bool lpa;
+ struct simple_util_jack hp_jack;
};
static struct dev_pm_ops lpa_pm;
@@ -86,8 +88,16 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card)
struct device *dev = card->dev;
int ret;
+ if (of_property_present(card->dev->of_node, "hp-det-gpios")) {
+ ret = simple_util_init_jack(card, &data->hp_jack,
+ 1, NULL, "Headphone Jack");
+ if (ret) {
+ dev_err(dev, "failed to init hp jack\n");
+ return ret;
+ }
+ }
+
if (data->lpa) {
- struct snd_soc_component *codec_comp;
struct device_node *codec_np;
struct device_driver *codec_drv;
struct device *codec_dev = NULL;
@@ -107,22 +117,6 @@ static int imx_rpmsg_late_probe(struct snd_soc_card *card)
}
}
if (codec_dev) {
- codec_comp = snd_soc_lookup_component_nolocked(codec_dev, NULL);
- if (codec_comp) {
- int i, num_widgets;
- const char *widgets;
- struct snd_soc_dapm_context *dapm;
-
- num_widgets = of_property_count_strings(data->card.dev->of_node,
- "ignore-suspend-widgets");
- for (i = 0; i < num_widgets; i++) {
- of_property_read_string_index(data->card.dev->of_node,
- "ignore-suspend-widgets",
- i, &widgets);
- dapm = snd_soc_component_to_dapm(codec_comp);
- snd_soc_dapm_ignore_suspend(dapm, widgets);
- }
- }
codec_drv = codec_dev->driver;
if (codec_drv->pm) {
memcpy(&lpa_pm, codec_drv->pm, sizeof(lpa_pm));
@@ -256,6 +250,7 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
data->card.dapm_widgets = imx_rpmsg_dapm_widgets;
data->card.num_dapm_widgets = ARRAY_SIZE(imx_rpmsg_dapm_widgets);
data->card.late_probe = imx_rpmsg_late_probe;
+ data->card.driver_name = "imx-audio-rpmsg";
/*
* Inoder to use common api to get card name and audio routing.
* Use parent of_node for this device, revert it after finishing using
@@ -274,6 +269,15 @@ static int imx_rpmsg_probe(struct platform_device *pdev)
}
}
+ if (data->lpa && of_property_present(np, "ignore-suspend-widgets")) {
+ ret = snd_soc_of_parse_ignore_suspend_widgets(&data->card,
+ "ignore-suspend-widgets");
+ if (ret) {
+ dev_err(&pdev->dev, "failed to parse ignore-suspend-widgets: %d\n", ret);
+ goto fail;
+ }
+ }
+
platform_set_drvdata(pdev, &data->card);
snd_soc_card_set_drvdata(&data->card, data);
ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index 8554fb690772..c21104355aa0 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -5,7 +5,6 @@
// Copyright (C) 2009 Jon Smirl, Digispeaker
// Author: Jon Smirl <jonsmirl@gmail.com>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/time.h>
diff --git a/sound/soc/generic/audio-graph-card2-custom-sample.c b/sound/soc/generic/audio-graph-card2-custom-sample.c
index 7151d426bee9..14b212675240 100644
--- a/sound/soc/generic/audio-graph-card2-custom-sample.c
+++ b/sound/soc/generic/audio-graph-card2-custom-sample.c
@@ -6,7 +6,6 @@
// Copyright (C) 2020 Kuninori Morimoto <kuninori.morimoto.gx@renesas.com>
//
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/graph_card.h>
diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c
index b24ba1330896..b4957e025211 100644
--- a/sound/soc/generic/simple-card.c
+++ b/sound/soc/generic/simple-card.c
@@ -13,9 +13,9 @@
#include <linux/of_platform.h>
#include <linux/platform_device.h>
#include <linux/string.h>
-#include <sound/simple_card.h>
-#include <sound/soc-dai.h>
+#include <sound/simple_card_utils.h>
#include <sound/soc.h>
+#include <sound/soc-dai.h>
#define DPCM_SELECTABLE 1
@@ -708,7 +708,6 @@ static int simple_probe(struct platform_device *pdev)
{
struct simple_util_priv *priv;
struct device *dev = &pdev->dev;
- struct device_node *np = dev->of_node;
struct snd_soc_card *card;
int ret;
@@ -740,58 +739,10 @@ static int simple_probe(struct platform_device *pdev)
if (ret < 0)
goto end;
- if (np && of_device_is_available(np)) {
-
- ret = simple_parse_of(priv, li);
- if (ret < 0) {
- dev_err_probe(dev, ret, "parse error\n");
- goto err;
- }
-
- } else {
- struct simple_util_info *cinfo;
- struct snd_soc_dai_link_component *cpus;
- struct snd_soc_dai_link_component *codecs;
- struct snd_soc_dai_link_component *platform;
- struct snd_soc_dai_link *dai_link = priv->dai_link;
- struct simple_dai_props *dai_props = priv->dai_props;
-
- ret = -EINVAL;
-
- cinfo = dev->platform_data;
- if (!cinfo) {
- dev_err(dev, "no info for asoc-simple-card\n");
- goto err;
- }
-
- if (!cinfo->name ||
- !cinfo->codec_dai.name ||
- !cinfo->codec ||
- !cinfo->platform ||
- !cinfo->cpu_dai.name) {
- dev_err(dev, "insufficient simple_util_info settings\n");
- goto err;
- }
-
- cpus = dai_link->cpus;
- cpus->dai_name = cinfo->cpu_dai.name;
-
- codecs = dai_link->codecs;
- codecs->name = cinfo->codec;
- codecs->dai_name = cinfo->codec_dai.name;
-
- platform = dai_link->platforms;
- platform->name = cinfo->platform;
-
- card->name = (cinfo->card) ? cinfo->card : cinfo->name;
- dai_link->name = cinfo->name;
- dai_link->stream_name = cinfo->name;
- dai_link->dai_fmt = cinfo->daifmt;
- dai_link->init = simple_util_dai_init;
- memcpy(dai_props->cpu_dai, &cinfo->cpu_dai,
- sizeof(*dai_props->cpu_dai));
- memcpy(dai_props->codec_dai, &cinfo->codec_dai,
- sizeof(*dai_props->codec_dai));
+ ret = simple_parse_of(priv, li);
+ if (ret < 0) {
+ dev_err_probe(dev, ret, "parse error\n");
+ goto err;
}
snd_soc_card_set_drvdata(card, priv);
diff --git a/sound/soc/generic/test-component.c b/sound/soc/generic/test-component.c
index fc40d024152e..6f9f498c4c5c 100644
--- a/sound/soc/generic/test-component.c
+++ b/sound/soc/generic/test-component.c
@@ -191,13 +191,6 @@ static int test_dai_trigger(struct snd_pcm_substream *substream, int cmd, struct
}
static const u64 test_dai_formats =
- /*
- * Select below from Sound Card, not auto
- * SND_SOC_POSSIBLE_DAIFMT_BP_FP
- * SND_SOC_POSSIBLE_DAIFMT_BC_FP
- * SND_SOC_POSSIBLE_DAIFMT_BP_FC
- * SND_SOC_POSSIBLE_DAIFMT_BC_FC
- */
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
diff --git a/sound/soc/hisilicon/hi6210-i2s.c b/sound/soc/hisilicon/hi6210-i2s.c
index 250ae3781d14..33b1dafb2540 100644
--- a/sound/soc/hisilicon/hi6210-i2s.c
+++ b/sound/soc/hisilicon/hi6210-i2s.c
@@ -185,7 +185,7 @@ static void hi6210_i2s_txctrl(struct snd_soc_dai *cpu_dai, int on)
struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);
u32 val;
- spin_lock(&i2s->lock);
+ guard(spinlock)(&i2s->lock);
if (on) {
/* enable S2 TX */
val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
@@ -197,7 +197,6 @@ static void hi6210_i2s_txctrl(struct snd_soc_dai *cpu_dai, int on)
val &= ~HII2S_I2S_CFG__S2_IF_TX_EN;
hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
}
- spin_unlock(&i2s->lock);
}
static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on)
@@ -205,7 +204,7 @@ static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on)
struct hi6210_i2s *i2s = dev_get_drvdata(cpu_dai->dev);
u32 val;
- spin_lock(&i2s->lock);
+ guard(spinlock)(&i2s->lock);
if (on) {
val = hi6210_read_reg(i2s, HII2S_I2S_CFG);
val |= HII2S_I2S_CFG__S2_IF_RX_EN;
@@ -215,7 +214,6 @@ static void hi6210_i2s_rxctrl(struct snd_soc_dai *cpu_dai, int on)
val &= ~HII2S_I2S_CFG__S2_IF_RX_EN;
hi6210_write_reg(i2s, HII2S_I2S_CFG, val);
}
- spin_unlock(&i2s->lock);
}
static int hi6210_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
diff --git a/sound/soc/img/img-spdif-in.c b/sound/soc/img/img-spdif-in.c
index 82295e2508fa..b630644f20cc 100644
--- a/sound/soc/img/img-spdif-in.c
+++ b/sound/soc/img/img-spdif-in.c
@@ -179,7 +179,7 @@ static int img_spdif_in_do_clkgen_single(struct img_spdif_in *spdif,
unsigned int rate)
{
unsigned int nom, hld;
- unsigned long flags, clk_rate;
+ unsigned long clk_rate;
int ret = 0;
u32 reg;
@@ -196,19 +196,15 @@ static int img_spdif_in_do_clkgen_single(struct img_spdif_in *spdif,
reg |= (hld << IMG_SPDIF_IN_CLKGEN_HLD_SHIFT) &
IMG_SPDIF_IN_CLKGEN_HLD_MASK;
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
- if (spdif->active) {
- spin_unlock_irqrestore(&spdif->lock, flags);
+ if (spdif->active)
return -EBUSY;
- }
img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CLKGEN);
spdif->single_freq = rate;
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
}
@@ -216,7 +212,7 @@ static int img_spdif_in_do_clkgen_multi(struct img_spdif_in *spdif,
unsigned int multi_freqs[])
{
unsigned int nom, hld, rate, max_rate = 0;
- unsigned long flags, clk_rate;
+ unsigned long clk_rate;
int i, ret = 0;
u32 reg, trk_reg, temp_regs[IMG_SPDIF_IN_NUM_ACLKGEN];
@@ -242,12 +238,10 @@ static int img_spdif_in_do_clkgen_multi(struct img_spdif_in *spdif,
temp_regs[i] = reg;
}
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
- if (spdif->active) {
- spin_unlock_irqrestore(&spdif->lock, flags);
+ if (spdif->active)
return -EBUSY;
- }
trk_reg = spdif->trk << IMG_SPDIF_IN_ACLKGEN_TRK_SHIFT;
@@ -262,8 +256,6 @@ static int img_spdif_in_do_clkgen_multi(struct img_spdif_in *spdif,
spdif->multi_freqs[2] = multi_freqs[2];
spdif->multi_freqs[3] = multi_freqs[3];
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
}
@@ -323,9 +315,8 @@ static int img_spdif_in_get_multi_freq(struct snd_kcontrol *kcontrol,
{
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long flags;
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
if (spdif->multi_freq) {
ucontrol->value.integer.value[0] = spdif->multi_freqs[0];
ucontrol->value.integer.value[1] = spdif->multi_freqs[1];
@@ -337,7 +328,6 @@ static int img_spdif_in_get_multi_freq(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[2] = 0;
ucontrol->value.integer.value[3] = 0;
}
- spin_unlock_irqrestore(&spdif->lock, flags);
return 0;
}
@@ -349,7 +339,6 @@ static int img_spdif_in_set_multi_freq(struct snd_kcontrol *kcontrol,
struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
unsigned int multi_freqs[IMG_SPDIF_IN_NUM_ACLKGEN];
bool multi_freq;
- unsigned long flags;
if ((ucontrol->value.integer.value[0] == 0) &&
(ucontrol->value.integer.value[1] == 0) &&
@@ -367,17 +356,13 @@ static int img_spdif_in_set_multi_freq(struct snd_kcontrol *kcontrol,
if (multi_freq)
return img_spdif_in_do_clkgen_multi(spdif, multi_freqs);
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
- if (spdif->active) {
- spin_unlock_irqrestore(&spdif->lock, flags);
+ if (spdif->active)
return -EBUSY;
- }
spdif->multi_freq = false;
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
}
@@ -399,9 +384,8 @@ static int img_spdif_in_get_lock_freq(struct snd_kcontrol *kcontrol,
struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
u32 reg;
int i;
- unsigned long flags;
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
reg = img_spdif_in_readl(spdif, IMG_SPDIF_IN_STATUS);
if (reg & IMG_SPDIF_IN_STATUS_LOCK_MASK) {
@@ -416,8 +400,6 @@ static int img_spdif_in_get_lock_freq(struct snd_kcontrol *kcontrol,
uc->value.integer.value[0] = 0;
}
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
}
@@ -448,16 +430,13 @@ static int img_spdif_in_set_trk(struct snd_kcontrol *kcontrol,
{
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long flags;
int i;
u32 reg;
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
- if (spdif->active) {
- spin_unlock_irqrestore(&spdif->lock, flags);
+ if (spdif->active)
return -EBUSY;
- }
spdif->trk = ucontrol->value.integer.value[0];
@@ -474,8 +453,6 @@ static int img_spdif_in_set_trk(struct snd_kcontrol *kcontrol,
img_spdif_in_aclkgen_writel(spdif, i);
}
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
}
@@ -506,15 +483,12 @@ static int img_spdif_in_set_lock_acquire(struct snd_kcontrol *kcontrol,
{
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long flags;
u32 reg;
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
- if (spdif->active) {
- spin_unlock_irqrestore(&spdif->lock, flags);
+ if (spdif->active)
return -EBUSY;
- }
spdif->lock_acquire = ucontrol->value.integer.value[0];
@@ -524,8 +498,6 @@ static int img_spdif_in_set_lock_acquire(struct snd_kcontrol *kcontrol,
IMG_SPDIF_IN_CTL_LOCKHI_MASK;
img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
}
@@ -545,15 +517,12 @@ static int img_spdif_in_set_lock_release(struct snd_kcontrol *kcontrol,
{
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long flags;
u32 reg;
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
- if (spdif->active) {
- spin_unlock_irqrestore(&spdif->lock, flags);
+ if (spdif->active)
return -EBUSY;
- }
spdif->lock_release = ucontrol->value.integer.value[0];
@@ -563,8 +532,6 @@ static int img_spdif_in_set_lock_release(struct snd_kcontrol *kcontrol,
IMG_SPDIF_IN_CTL_LOCKLO_MASK;
img_spdif_in_writel(spdif, reg, IMG_SPDIF_IN_CTL);
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
}
@@ -625,12 +592,11 @@ static struct snd_kcontrol_new img_spdif_in_controls[] = {
static int img_spdif_in_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
- unsigned long flags;
struct img_spdif_in *spdif = snd_soc_dai_get_drvdata(dai);
int ret = 0;
u32 reg;
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -657,8 +623,6 @@ static int img_spdif_in_trigger(struct snd_pcm_substream *substream, int cmd,
ret = -EINVAL;
}
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return ret;
}
diff --git a/sound/soc/img/img-spdif-out.c b/sound/soc/img/img-spdif-out.c
index 52f696219ef4..39a37e4830d8 100644
--- a/sound/soc/img/img-spdif-out.c
+++ b/sound/soc/img/img-spdif-out.c
@@ -135,9 +135,8 @@ static int img_spdif_out_get_status(struct snd_kcontrol *kcontrol,
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(cpu_dai);
u32 reg;
- unsigned long flags;
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
reg = img_spdif_out_readl(spdif, IMG_SPDIF_OUT_CSL);
ucontrol->value.iec958.status[0] = reg & 0xff;
@@ -150,8 +149,6 @@ static int img_spdif_out_get_status(struct snd_kcontrol *kcontrol,
(reg & IMG_SPDIF_OUT_CSH_UV_CSH_MASK) >>
IMG_SPDIF_OUT_CSH_UV_CSH_SHIFT;
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
}
@@ -161,14 +158,13 @@ static int img_spdif_out_set_status(struct snd_kcontrol *kcontrol,
struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(cpu_dai);
u32 reg;
- unsigned long flags;
reg = ((u32)ucontrol->value.iec958.status[3] << 24);
reg |= ((u32)ucontrol->value.iec958.status[2] << 16);
reg |= ((u32)ucontrol->value.iec958.status[1] << 8);
reg |= (u32)ucontrol->value.iec958.status[0];
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
img_spdif_out_writel(spdif, reg, IMG_SPDIF_OUT_CSL);
@@ -178,8 +174,6 @@ static int img_spdif_out_set_status(struct snd_kcontrol *kcontrol,
IMG_SPDIF_OUT_CSH_UV_CSH_SHIFT;
img_spdif_out_writel(spdif, reg, IMG_SPDIF_OUT_CSH_UV);
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
}
@@ -205,7 +199,6 @@ static int img_spdif_out_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct img_spdif_out *spdif = snd_soc_dai_get_drvdata(dai);
u32 reg;
- unsigned long flags;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -218,9 +211,8 @@ static int img_spdif_out_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- spin_lock_irqsave(&spdif->lock, flags);
- img_spdif_out_reset(spdif);
- spin_unlock_irqrestore(&spdif->lock, flags);
+ scoped_guard(spinlock_irqsave, &spdif->lock)
+ img_spdif_out_reset(spdif);
break;
default:
return -EINVAL;
diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig
index d53af8f7e55b..cddbd2aa424e 100644
--- a/sound/soc/intel/boards/Kconfig
+++ b/sound/soc/intel/boards/Kconfig
@@ -532,6 +532,7 @@ config SND_SOC_INTEL_SOUNDWIRE_SOF_MACH
select MFD_CS42L43_SDW
select SND_SOC_CS35L56_SPI
select SND_SOC_CS35L56_SDW
+ select SND_SOC_ES9356
select SND_SOC_DMIC
select SND_SOC_INTEL_HDA_DSP_COMMON
imply SND_SOC_SDW_MOCKUP
diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c
index 192e2a394ff3..ea387dc74273 100644
--- a/sound/soc/intel/boards/bytcht_es8316.c
+++ b/sound/soc/intel/boards/bytcht_es8316.c
@@ -40,6 +40,7 @@ struct byt_cht_es8316_private {
struct gpio_desc *speaker_en_gpio;
struct device *codec_dev;
bool speaker_en;
+ bool mclk_enabled;
};
enum {
@@ -170,6 +171,15 @@ static struct snd_soc_jack_pin byt_cht_es8316_jack_pins[] = {
},
};
+static void byt_cht_es8316_disable_mclk(struct byt_cht_es8316_private *priv)
+{
+ if (!priv->mclk_enabled)
+ return;
+
+ clk_disable_unprepare(priv->mclk);
+ priv->mclk_enabled = false;
+}
+
static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
{
struct snd_soc_component *codec = snd_soc_rtd_to_codec(runtime, 0)->component;
@@ -227,12 +237,14 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
ret = clk_prepare_enable(priv->mclk);
if (ret)
dev_err(card->dev, "unable to enable MCLK\n");
+ else
+ priv->mclk_enabled = true;
ret = snd_soc_dai_set_sysclk(snd_soc_rtd_to_codec(runtime, 0), 0, 19200000,
SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(card->dev, "can't set codec clock %d\n", ret);
- return ret;
+ goto err_disable_mclk;
}
ret = snd_soc_card_jack_new_pins(card, "Headset",
@@ -241,13 +253,25 @@ static int byt_cht_es8316_init(struct snd_soc_pcm_runtime *runtime)
ARRAY_SIZE(byt_cht_es8316_jack_pins));
if (ret) {
dev_err(card->dev, "jack creation failed %d\n", ret);
- return ret;
+ goto err_disable_mclk;
}
snd_jack_set_key(priv->jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
snd_soc_component_set_jack(codec, &priv->jack, NULL);
return 0;
+
+err_disable_mclk:
+ byt_cht_es8316_disable_mclk(priv);
+ return ret;
+}
+
+static void byt_cht_es8316_exit(struct snd_soc_pcm_runtime *runtime)
+{
+ struct snd_soc_card *card = runtime->card;
+ struct byt_cht_es8316_private *priv = snd_soc_card_get_drvdata(card);
+
+ byt_cht_es8316_disable_mclk(priv);
}
static int byt_cht_es8316_codec_fixup(struct snd_soc_pcm_runtime *rtd,
@@ -353,6 +377,7 @@ static struct snd_soc_dai_link byt_cht_es8316_dais[] = {
| SND_SOC_DAIFMT_CBC_CFC,
.be_hw_params_fixup = byt_cht_es8316_codec_fixup,
.init = byt_cht_es8316_init,
+ .exit = byt_cht_es8316_exit,
SND_SOC_DAILINK_REG(ssp2_port, ssp2_codec, platform),
},
};
diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c
index fd4cefd298d2..eddb179eaa21 100644
--- a/sound/soc/intel/boards/cht_bsw_rt5672.c
+++ b/sound/soc/intel/boards/cht_bsw_rt5672.c
@@ -63,13 +63,11 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
}
if (SND_SOC_DAPM_EVENT_ON(event)) {
- if (ctx->mclk) {
- ret = clk_prepare_enable(ctx->mclk);
- if (ret < 0) {
- dev_err(card->dev,
- "could not configure MCLK state: %d\n", ret);
- return ret;
- }
+ ret = clk_prepare_enable(ctx->mclk);
+ if (ret < 0) {
+ dev_err(card->dev,
+ "could not configure MCLK state: %d\n", ret);
+ return ret;
}
/* set codec PLL source to the 19.2MHz platform clock (MCLK) */
@@ -77,8 +75,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
CHT_PLAT_CLK_3_HZ, 48000 * 512);
if (ret < 0) {
dev_err(card->dev, "can't set codec pll: %d\n", ret);
- if (ctx->mclk)
- clk_disable_unprepare(ctx->mclk);
+ clk_disable_unprepare(ctx->mclk);
return ret;
}
@@ -87,8 +84,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
48000 * 512, SND_SOC_CLOCK_IN);
if (ret < 0) {
dev_err(card->dev, "can't set codec sysclk: %d\n", ret);
- if (ctx->mclk)
- clk_disable_unprepare(ctx->mclk);
+ clk_disable_unprepare(ctx->mclk);
return ret;
}
} else {
@@ -104,8 +100,7 @@ static int platform_clock_control(struct snd_soc_dapm_widget *w,
return ret;
}
- if (ctx->mclk)
- clk_disable_unprepare(ctx->mclk);
+ clk_disable_unprepare(ctx->mclk);
}
return 0;
}
@@ -244,28 +239,25 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime)
snd_jack_set_key(ctx->headset.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
rt5670_set_jack_detect(component, &ctx->headset);
- if (ctx->mclk) {
- /*
- * 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(ctx->mclk);
- if (!ret)
- clk_disable_unprepare(ctx->mclk);
- ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
+ /*
+ * 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(ctx->mclk);
+ if (!ret)
+ clk_disable_unprepare(ctx->mclk);
- if (ret) {
- dev_err(runtime->dev, "unable to set MCLK rate\n");
- return ret;
- }
+ ret = clk_set_rate(ctx->mclk, CHT_PLAT_CLK_3_HZ);
+ if (ret) {
+ dev_err(runtime->dev, "unable to set MCLK rate\n");
+ return ret;
}
+
return 0;
}
@@ -454,12 +446,13 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
struct cht_mc_private *drv;
struct snd_soc_acpi_mach *mach = pdev->dev.platform_data;
const char *platform_name;
+ struct device *dev = &pdev->dev;
struct acpi_device *adev;
bool sof_parent;
int dai_index = 0;
int i;
- drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL);
+ drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
return -ENOMEM;
@@ -481,7 +474,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
"i2c-%s", acpi_dev_name(adev));
cht_dailink[dai_index].codecs->name = drv->codec_name;
} else {
- dev_err(&pdev->dev, "Error cannot find '%s' dev\n", mach->id);
+ dev_err(dev, "Error cannot find '%s' dev\n", mach->id);
return -ENOENT;
}
@@ -494,7 +487,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
}
/* override platform name, if required */
- snd_soc_card_cht.dev = &pdev->dev;
+ snd_soc_card_cht.dev = dev;
platform_name = mach->mach_params.platform;
ret_val = snd_soc_fixup_dai_links_platform_name(&snd_soc_card_cht,
@@ -504,16 +497,16 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
snd_soc_card_cht.components = rt5670_components();
- drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3");
+ drv->mclk = devm_clk_get(dev, "pmc_plt_clk_3");
if (IS_ERR(drv->mclk)) {
- dev_err(&pdev->dev,
+ dev_err(dev,
"Failed to get MCLK from pmc_plt_clk_3: %ld\n",
PTR_ERR(drv->mclk));
return PTR_ERR(drv->mclk);
}
snd_soc_card_set_drvdata(&snd_soc_card_cht, drv);
- sof_parent = snd_soc_acpi_sof_parent(&pdev->dev);
+ sof_parent = snd_soc_acpi_sof_parent(dev);
/* set card and driver name */
if (sof_parent) {
@@ -529,9 +522,9 @@ static int snd_cht_mc_probe(struct platform_device *pdev)
pdev->dev.driver->pm = &snd_soc_pm_ops;
/* register the soc card */
- ret_val = devm_snd_soc_register_card(&pdev->dev, &snd_soc_card_cht);
+ ret_val = devm_snd_soc_register_card(dev, &snd_soc_card_cht);
if (ret_val) {
- dev_err(&pdev->dev,
+ dev_err(dev,
"snd_soc_register_card failed %d\n", ret_val);
return ret_val;
}
diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c
index c18ec607e029..d43daf9b025d 100644
--- a/sound/soc/intel/boards/sof_sdw.c
+++ b/sound/soc/intel/boards/sof_sdw.c
@@ -837,6 +837,14 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = {
SOF_BT_OFFLOAD_SSP(2) |
SOF_SSP_BT_OFFLOAD_PRESENT),
},
+ /* Novalake devices*/
+ {
+ .callback = sof_sdw_quirk_cb,
+ .matches = {
+ DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_nvlrvp"),
+ },
+ .driver_data = (void *)(SOC_SDW_PCH_DMIC),
+ },
{}
};
@@ -901,10 +909,16 @@ static int create_sdw_dailink(struct snd_soc_card *card,
}
}
+ /*
+ * The dai_type is used to select function topologies. Since the topology stream name
+ * and DAI link name use partial matching, unconditionally appending the dai_type provides
+ * necessary selection metadata without breaking existing topologies. Although
+ * ctx->append_dai_type is not checked here, we overwrite it to ensure consistency in case
+ * it is referenced elsewhere.
+ */
+ ctx->append_dai_type = true;
for_each_pcm_streams(stream) {
static const char * const sdw_stream_name[] = {
- "SDW%d-Playback",
- "SDW%d-Capture",
"SDW%d-Playback-%s",
"SDW%d-Capture-%s",
};
@@ -932,15 +946,10 @@ static int create_sdw_dailink(struct snd_soc_card *card,
}
/* create stream name according to first link id */
- if (ctx->append_dai_type)
- name = devm_kasprintf(dev, GFP_KERNEL,
- sdw_stream_name[stream + 2],
- ffs(sof_end->link_mask) - 1,
- type_strings[sof_end->dai_info->dai_type]);
- else
- name = devm_kasprintf(dev, GFP_KERNEL,
- sdw_stream_name[stream],
- ffs(sof_end->link_mask) - 1);
+ name = devm_kasprintf(dev, GFP_KERNEL,
+ sdw_stream_name[stream],
+ ffs(sof_end->link_mask) - 1,
+ type_strings[sof_end->dai_info->dai_type]);
if (!name)
return -ENOMEM;
diff --git a/sound/soc/intel/catpt/Makefile b/sound/soc/intel/catpt/Makefile
index e8316e33b820..8005fc677f28 100644
--- a/sound/soc/intel/catpt/Makefile
+++ b/sound/soc/intel/catpt/Makefile
@@ -1,7 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
snd-soc-catpt-y := device.o dsp.o loader.o ipc.o messages.o pcm.o sysfs.o
+snd-soc-catpt-y += trace.o
# tell define_trace.h where to find the trace header
-CFLAGS_device.o := -I$(src)
+CFLAGS_trace.o := -I$(src)
obj-$(CONFIG_SND_SOC_INTEL_CATPT) += snd-soc-catpt.o
diff --git a/sound/soc/intel/catpt/core.h b/sound/soc/intel/catpt/core.h
index 7e479ef89ad0..3881164422b8 100644
--- a/sound/soc/intel/catpt/core.h
+++ b/sound/soc/intel/catpt/core.h
@@ -17,7 +17,6 @@ struct catpt_dev;
extern const struct attribute_group *catpt_attr_groups[];
-void catpt_sram_init(struct resource *sram, u32 start, u32 size);
void catpt_sram_free(struct resource *sram);
struct resource *
catpt_request_region(struct resource *root, resource_size_t size);
diff --git a/sound/soc/intel/catpt/device.c b/sound/soc/intel/catpt/device.c
index ca4fd18b6a6e..b176aebea9d5 100644
--- a/sound/soc/intel/catpt/device.c
+++ b/sound/soc/intel/catpt/device.c
@@ -25,9 +25,6 @@
#include "core.h"
#include "registers.h"
-#define CREATE_TRACE_POINTS
-#include "trace.h"
-
static int catpt_do_suspend(struct device *dev)
{
struct catpt_dev *cdev = dev_get_drvdata(dev);
@@ -157,7 +154,7 @@ static int catpt_register_board(struct catpt_dev *cdev)
PLATFORM_DEVID_NONE,
(const void *)mach, sizeof(*mach));
if (IS_ERR(board)) {
- dev_err(cdev->dev, "board register failed\n");
+ dev_err(cdev->dev, "register board failed: %ld\n", PTR_ERR(board));
return PTR_ERR(board);
}
@@ -236,12 +233,9 @@ static void catpt_dev_init(struct catpt_dev *cdev, struct device *dev,
cdev->devfmt[CATPT_SSP_IFACE_0].iface = UINT_MAX;
cdev->devfmt[CATPT_SSP_IFACE_1].iface = UINT_MAX;
+ resource_set_range(&cdev->dram, spec->host_dram_offset, catpt_dram_size(cdev));
+ resource_set_range(&cdev->iram, spec->host_iram_offset, catpt_iram_size(cdev));
catpt_ipc_init(&cdev->ipc, dev);
-
- catpt_sram_init(&cdev->dram, spec->host_dram_offset,
- catpt_dram_size(cdev));
- catpt_sram_init(&cdev->iram, spec->host_iram_offset,
- catpt_iram_size(cdev));
}
static int catpt_acpi_probe(struct platform_device *pdev)
@@ -290,7 +284,7 @@ static int catpt_acpi_probe(struct platform_device *pdev)
if (ret)
return ret;
- cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev),
+ cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, resource_size(&cdev->dram),
&cdev->dxbuf_paddr, GFP_KERNEL);
if (!cdev->dxbuf_vaddr)
return -ENOMEM;
diff --git a/sound/soc/intel/catpt/dsp.c b/sound/soc/intel/catpt/dsp.c
index 677f348909c8..960344991b11 100644
--- a/sound/soc/intel/catpt/dsp.c
+++ b/sound/soc/intel/catpt/dsp.c
@@ -5,6 +5,7 @@
// Author: Cezary Rojewski <cezary.rojewski@intel.com>
//
+#include <linux/cleanup.h>
#include <linux/devcoredump.h>
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
@@ -43,7 +44,6 @@ struct dma_chan *catpt_dma_request_config_chan(struct catpt_dev *cdev)
}
memset(&config, 0, sizeof(config));
- config.direction = DMA_MEM_TO_DEV;
config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
config.src_maxburst = 16;
@@ -121,7 +121,7 @@ int catpt_dmac_probe(struct catpt_dev *cdev)
if (!dmac)
return -ENOMEM;
- dmac->regs = cdev->lpe_ba + cdev->spec->host_dma_offset[CATPT_DMA_DEVID];
+ dmac->regs = catpt_dma_addr(cdev, CATPT_DMA_DEVID);
dmac->dev = cdev->dev;
dmac->irq = cdev->irq;
@@ -256,17 +256,15 @@ static int catpt_dsp_select_lpclock(struct catpt_dev *cdev, bool lp, bool waiti)
u32 mask, reg, val;
int ret;
- mutex_lock(&cdev->clk_mutex);
+ guard(mutex)(&cdev->clk_mutex);
val = lp ? CATPT_CS_LPCS : 0;
reg = catpt_readl_shim(cdev, CS1) & CATPT_CS_LPCS;
dev_dbg(cdev->dev, "LPCS [0x%08lx] 0x%08x -> 0x%08x",
CATPT_CS_LPCS, reg, val);
- if (reg == val) {
- mutex_unlock(&cdev->clk_mutex);
+ if (reg == val)
return 0;
- }
if (waiti) {
/* wait for DSP to signal WAIT state */
@@ -276,10 +274,8 @@ static int catpt_dsp_select_lpclock(struct catpt_dev *cdev, bool lp, bool waiti)
if (ret) {
dev_warn(cdev->dev, "await WAITI timeout\n");
/* no signal - only high clock selection allowed */
- if (lp) {
- mutex_unlock(&cdev->clk_mutex);
+ if (lp)
return 0;
- }
}
}
@@ -303,7 +299,6 @@ static int catpt_dsp_select_lpclock(struct catpt_dev *cdev, bool lp, bool waiti)
/* update PLL accordingly */
cdev->spec->pll_shutdown(cdev, lp);
- mutex_unlock(&cdev->clk_mutex);
return 0;
}
@@ -502,7 +497,7 @@ int catpt_coredump(struct catpt_dev *cdev)
hdr->size = resource_size(&cdev->iram);
pos += sizeof(*hdr);
- memcpy_fromio(pos, cdev->lpe_ba + cdev->iram.start, hdr->size);
+ memcpy_fromio(pos, catpt_iram_addr(cdev), hdr->size);
pos += hdr->size;
hdr = (struct catpt_dump_section_hdr *)pos;
@@ -512,7 +507,7 @@ int catpt_coredump(struct catpt_dev *cdev)
hdr->size = resource_size(&cdev->dram);
pos += sizeof(*hdr);
- memcpy_fromio(pos, cdev->lpe_ba + cdev->dram.start, hdr->size);
+ memcpy_fromio(pos, catpt_dram_addr(cdev), hdr->size);
pos += hdr->size;
hdr = (struct catpt_dump_section_hdr *)pos;
diff --git a/sound/soc/intel/catpt/ipc.c b/sound/soc/intel/catpt/ipc.c
index 2e3b7a5cbb9b..8092944d6cb7 100644
--- a/sound/soc/intel/catpt/ipc.c
+++ b/sound/soc/intel/catpt/ipc.c
@@ -128,14 +128,9 @@ int catpt_dsp_send_msg_timeout(struct catpt_dev *cdev,
struct catpt_ipc_msg request,
struct catpt_ipc_msg *reply, int timeout, const char *name)
{
- struct catpt_ipc *ipc = &cdev->ipc;
- int ret;
+ guard(mutex)(&cdev->ipc.mutex);
- mutex_lock(&ipc->mutex);
- ret = catpt_dsp_do_send_msg(cdev, request, reply, timeout, name);
- mutex_unlock(&ipc->mutex);
-
- return ret;
+ return catpt_dsp_do_send_msg(cdev, request, reply, timeout, name);
}
int catpt_dsp_send_msg(struct catpt_dev *cdev, struct catpt_ipc_msg request,
@@ -210,6 +205,7 @@ static void catpt_dsp_process_response(struct catpt_dev *cdev, u32 header)
memcpy_fromio(&config, cdev->lpe_ba + off, sizeof(config));
trace_catpt_ipc_payload((u8 *)&config, sizeof(config));
+ dev_dbg(cdev->dev, "FW READY 0x%08x\n", header);
catpt_ipc_arm(ipc, &config);
complete(&cdev->fw_ready);
return;
@@ -220,6 +216,13 @@ static void catpt_dsp_process_response(struct catpt_dev *cdev, u32 header)
dev_err(cdev->dev, "ADSP device coredump received\n");
ipc->ready = false;
catpt_coredump(cdev);
+
+ if (catpt_readl_dram(cdev, COREDUMP) == CATPT_COREDUMP_REQUEST) {
+ dev_dbg(cdev->dev, "releasing firmware from the coredump state\n");
+ catpt_writel_dram(cdev, COREDUMP, CATPT_COREDUMP_RELEASE);
+ }
+
+ complete(&cdev->fw_ready);
/* TODO: attempt recovery */
break;
diff --git a/sound/soc/intel/catpt/loader.c b/sound/soc/intel/catpt/loader.c
index 432cb1f0ab4e..c577f2e17ddf 100644
--- a/sound/soc/intel/catpt/loader.c
+++ b/sound/soc/intel/catpt/loader.c
@@ -7,6 +7,7 @@
#include <linux/dma-mapping.h>
#include <linux/firmware.h>
+#include <linux/ioport.h>
#include <linux/slab.h>
#include "core.h"
#include "registers.h"
@@ -50,12 +51,6 @@ struct catpt_fw_block_hdr {
u32 rsvd;
} __packed;
-void catpt_sram_init(struct resource *sram, u32 start, u32 size)
-{
- sram->start = start;
- sram->end = start + size - 1;
-}
-
void catpt_sram_free(struct resource *sram)
{
struct resource *res, *save;
@@ -624,6 +619,9 @@ int catpt_boot_firmware(struct catpt_dev *cdev, bool restore)
if (!ret) {
dev_err(cdev->dev, "firmware ready timeout\n");
return -ETIMEDOUT;
+ /* Wake up does not mean FW is ready, an exception could occur. */
+ } else if (!cdev->ipc.ready) {
+ return -EREMOTEIO;
}
/* update sram pg & clock once done booting */
diff --git a/sound/soc/intel/catpt/pcm.c b/sound/soc/intel/catpt/pcm.c
index 7b2bab12c707..8fb0efb67eb1 100644
--- a/sound/soc/intel/catpt/pcm.c
+++ b/sound/soc/intel/catpt/pcm.c
@@ -99,19 +99,15 @@ catpt_get_stream_template(struct snd_pcm_substream *substream)
}
/* Caller responsible for holding ->stream_mutex. */
-struct catpt_stream_runtime *
-catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id)
+struct catpt_stream_runtime *catpt_stream_find(struct catpt_dev *cdev, u8 stream_hw_id)
{
- struct catpt_stream_runtime *pos, *result = NULL;
+ struct catpt_stream_runtime *stream;
- list_for_each_entry(pos, &cdev->stream_list, node) {
- if (pos->info.stream_hw_id == stream_hw_id) {
- result = pos;
- break;
- }
- }
+ list_for_each_entry(stream, &cdev->stream_list, node)
+ if (stream->info.stream_hw_id == stream_hw_id)
+ return stream;
- return result;
+ return NULL;
}
/* Caller responsible for holding ->stream_mutex. */
@@ -972,32 +968,7 @@ static int catpt_loopback_mute_put(struct snd_kcontrol *kctl, struct snd_ctl_ele
return 1;
}
-static int catpt_waves_switch_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return 0;
-}
-
-static int catpt_waves_switch_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return 0;
-}
-
-static int catpt_waves_param_get(struct snd_kcontrol *kcontrol,
- unsigned int __user *bytes,
- unsigned int size)
-{
- return 0;
-}
-
-static int catpt_waves_param_put(struct snd_kcontrol *kcontrol,
- const unsigned int __user *bytes,
- unsigned int size)
-{
- return 0;
-}
-
+static bool catpt_loopback_mute;
static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(catpt_volume_tlv, -9000, 300, 1);
#define CATPT_VOLUME_CTL(kname, pname) { \
@@ -1014,20 +985,12 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_SCALE(catpt_volume_tlv, -9000, 300, 1);
}
static const struct snd_kcontrol_new component_kcontrols[] = {
-/* Master volume (mixer stream) */
-CATPT_VOLUME_CTL("Master Playback Volume", MIXER),
-/* Individual volume controls for offload and capture */
-CATPT_VOLUME_CTL("Media0 Playback Volume", OFFLOAD1),
-CATPT_VOLUME_CTL("Media1 Playback Volume", OFFLOAD2),
-CATPT_VOLUME_CTL("Mic Capture Volume", CAPTURE1),
-SOC_SINGLE_BOOL_EXT("Loopback Mute", (unsigned long)&(bool[1]) {0},
- catpt_loopback_mute_get, catpt_loopback_mute_put),
-/* Enable or disable WAVES module */
-SOC_SINGLE_BOOL_EXT("Waves Switch", 0,
- catpt_waves_switch_get, catpt_waves_switch_put),
-/* WAVES module parameter control */
-SND_SOC_BYTES_TLV("Waves Set Param", 128,
- catpt_waves_param_get, catpt_waves_param_put),
+ CATPT_VOLUME_CTL("Master Playback Volume", MIXER),
+ CATPT_VOLUME_CTL("Media0 Playback Volume", OFFLOAD1),
+ CATPT_VOLUME_CTL("Media1 Playback Volume", OFFLOAD2),
+ CATPT_VOLUME_CTL("Mic Capture Volume", CAPTURE1),
+ SOC_SINGLE_BOOL_EXT("Loopback Mute", (unsigned long)&catpt_loopback_mute,
+ catpt_loopback_mute_get, catpt_loopback_mute_put),
};
static const struct snd_soc_dapm_widget component_widgets[] = {
diff --git a/sound/soc/intel/catpt/registers.h b/sound/soc/intel/catpt/registers.h
index 6c1ad28c6d69..864802bd7809 100644
--- a/sound/soc/intel/catpt/registers.h
+++ b/sound/soc/intel/catpt/registers.h
@@ -124,6 +124,11 @@
#define CATPT_SSCR2_DEFAULT 0x0
#define CATPT_SSPSP2_DEFAULT 0x0
+/* Coredump register and its states */
+#define CATPT_DRAM_COREDUMP 0x1F4
+#define CATPT_COREDUMP_REQUEST UINT_MAX
+#define CATPT_COREDUMP_RELEASE 0
+
/* Physically the same block, access address differs between host and dsp */
#define CATPT_DSP_DRAM_OFFSET 0x400000
#define catpt_to_host_offset(offset) ((offset) & ~(CATPT_DSP_DRAM_OFFSET))
@@ -137,6 +142,10 @@
/* registry I/O helpers */
+#define catpt_dram_addr(cdev) \
+ ((cdev)->lpe_ba + (cdev)->spec->host_dram_offset)
+#define catpt_iram_addr(cdev) \
+ ((cdev)->lpe_ba + (cdev)->spec->host_iram_offset)
#define catpt_shim_addr(cdev) \
((cdev)->lpe_ba + (cdev)->spec->host_shim_offset)
#define catpt_dma_addr(cdev, dma) \
@@ -151,6 +160,11 @@
#define catpt_writel_ssp(cdev, ssp, reg, val) \
writel(val, catpt_ssp_addr(cdev, ssp) + (reg))
+#define catpt_readl_dram(cdev, reg) \
+ readl(catpt_dram_addr(cdev) + CATPT_DRAM_##reg)
+#define catpt_writel_dram(cdev, reg, val) \
+ writel(val, catpt_dram_addr(cdev) + CATPT_DRAM_##reg)
+
#define catpt_readl_shim(cdev, reg) \
readl(catpt_shim_addr(cdev) + CATPT_SHIM_##reg)
#define catpt_writel_shim(cdev, reg, val) \
diff --git a/sound/soc/intel/catpt/trace.c b/sound/soc/intel/catpt/trace.c
new file mode 100644
index 000000000000..e97c372cc2af
--- /dev/null
+++ b/sound/soc/intel/catpt/trace.c
@@ -0,0 +1,27 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/types.h>
+
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
+#define BYTES_PER_LINE 16
+#define MAX_CHUNK_SIZE ((PAGE_SIZE - 150) /* Place for trace header */ \
+ / (2 * BYTES_PER_LINE + 4) /* chars per line */ \
+ * BYTES_PER_LINE)
+
+void trace_catpt_ipc_payload(const void *data, size_t size)
+{
+ size_t remaining = size;
+ size_t offset = 0;
+
+ while (remaining > 0) {
+ u32 chunk;
+
+ chunk = min_t(size_t, remaining, MAX_CHUNK_SIZE);
+ trace_catpt_ipc_payload_chunk(data, chunk, offset, size);
+
+ remaining -= chunk;
+ offset += chunk;
+ }
+}
diff --git a/sound/soc/intel/catpt/trace.h b/sound/soc/intel/catpt/trace.h
index 010f57b6a7a8..6b528d933734 100644
--- a/sound/soc/intel/catpt/trace.h
+++ b/sound/soc/intel/catpt/trace.h
@@ -51,29 +51,37 @@ DEFINE_EVENT(catpt_ipc_msg, catpt_ipc_notify,
TP_ARGS(header)
);
-TRACE_EVENT_CONDITION(catpt_ipc_payload,
+TRACE_EVENT_CONDITION(catpt_ipc_payload_chunk,
- TP_PROTO(const u8 *data, size_t size),
+ TP_PROTO(const u8 *data, size_t size, size_t offset, size_t total),
- TP_ARGS(data, size),
+ TP_ARGS(data, size, offset, total),
TP_CONDITION(data && size),
TP_STRUCT__entry(
- __dynamic_array(u8, buf, size)
+ __dynamic_array(u8, buf, size )
+ __field(size_t, offset )
+ __field(size_t, pos )
+ __field(size_t, total )
),
TP_fast_assign(
- memcpy(__get_dynamic_array(buf), data, size);
+ memcpy(__get_dynamic_array(buf), data + offset, size);
+ __entry->offset = offset;
+ __entry->pos = offset + size;
+ __entry->total = total;
),
- TP_printk("%u byte(s)%s",
- __get_dynamic_array_len(buf),
+ TP_printk("range %zu-%zu out of %zu bytes%s",
+ __entry->offset, __entry->pos, __entry->total,
__print_hex_dump("", DUMP_PREFIX_NONE, 16, 4,
__get_dynamic_array(buf),
__get_dynamic_array_len(buf), false))
);
+void trace_catpt_ipc_payload(const void *data, size_t size);
+
#endif /* __SND_SOC_INTEL_CATPT_TRACE_H */
/* This part must be outside protection */
diff --git a/sound/soc/intel/common/soc-acpi-intel-arl-match.c b/sound/soc/intel/common/soc-acpi-intel-arl-match.c
index c952f7d2b2c0..59bfd5248819 100644
--- a/sound/soc/intel/common/soc-acpi-intel-arl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-arl-match.c
@@ -8,6 +8,7 @@
#include <sound/soc-acpi.h>
#include <sound/soc-acpi-intel-match.h>
#include <sound/soc-acpi-intel-ssp-common.h>
+#include "soc-acpi-intel-sdca-quirks.h"
#include "sof-function-topology-lib.h"
static const struct snd_soc_acpi_endpoint single_endpoint = {
@@ -192,6 +193,42 @@ static const struct snd_soc_acpi_endpoint cs42l43_endpoints[] = {
},
};
+static const struct snd_soc_acpi_endpoint es9356_endpoints[] = {
+ { /* Jack Playback Endpoint */
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* DMIC Capture Endpoint */
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Jack Capture Endpoint */
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Speaker Playback Endpoint */
+ .num = 3,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
+static const struct snd_soc_acpi_adr_device es9356_adr[] = {
+ {
+ .adr = 0x00013004b3935601ull,
+ .num_endpoints = ARRAY_SIZE(es9356_endpoints),
+ .endpoints = es9356_endpoints,
+ .name_prefix = "es9356"
+ }
+};
+
static const struct snd_soc_acpi_adr_device cs42l43_0_adr[] = {
{
.adr = 0x00003001FA424301ull,
@@ -237,6 +274,15 @@ static const struct snd_soc_acpi_adr_device rt722_0_agg_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device rt712_0_agg_adr[] = {
+ {
+ .adr = 0x000030025D071201ull,
+ .num_endpoints = ARRAY_SIZE(jack_amp_g1_dmic_endpoints),
+ .endpoints = jack_amp_g1_dmic_endpoints,
+ .name_prefix = "rt712"
+ }
+};
+
static const struct snd_soc_acpi_adr_device rt1316_3_single_adr[] = {
{
.adr = 0x000330025D131601ull,
@@ -255,6 +301,24 @@ static const struct snd_soc_acpi_adr_device rt1320_2_single_adr[] = {
}
};
+static const struct snd_soc_acpi_link_adr arl_n_mrd_es9356_link1[] = {
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(es9356_adr),
+ .adr_d = es9356_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_adr_device rt1320_3_group1_adr[] = {
+ {
+ .adr = 0x000330025D132001ull,
+ .num_endpoints = 1,
+ .endpoints = &spk_r_endpoint,
+ .name_prefix = "rt1320-1"
+ }
+};
+
static const struct snd_soc_acpi_link_adr arl_cs42l43_l0[] = {
{
.mask = BIT(0),
@@ -404,6 +468,20 @@ static const struct snd_soc_acpi_link_adr arl_rt722_l0_rt1320_l2[] = {
{}
};
+static const struct snd_soc_acpi_link_adr arl_rt712_l0_rt1320_l3[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(rt712_0_agg_adr),
+ .adr_d = rt712_0_agg_adr,
+ },
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(rt1320_3_group1_adr),
+ .adr_d = rt1320_3_group1_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_codecs arl_essx_83x6 = {
.num_codecs = 3,
.codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
@@ -483,31 +561,39 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = {
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
- .link_mask = BIT(0),
- .links = arl_cs42l43_l0,
+ .link_mask = BIT(0) | BIT(2),
+ .links = arl_rt722_l0_rt1320_l2,
.drv_name = "sof_sdw",
- .sof_tplg_filename = "sof-arl-cs42l43-l0.tplg",
+ .sof_tplg_filename = "sof-arl-rt722-l0_rt1320-l2.tplg",
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
- .link_mask = BIT(2) | BIT(3),
- .links = arl_cs42l43_l2_cs35l56_l3,
+ .link_mask = BIT(0) | BIT(3),
+ .links = arl_rt711_l0_rt1316_l3,
.drv_name = "sof_sdw",
- .sof_tplg_filename = "sof-arl-cs42l43-l2-cs35l56-l3.tplg",
+ .sof_tplg_filename = "sof-arl-rt711-l0-rt1316-l3.tplg",
+ },
+ {
+ .link_mask = BIT(0) | BIT(3),
+ .links = arl_rt712_l0_rt1320_l3,
+ .drv_name = "sof_sdw",
+ .machine_check = snd_soc_acpi_intel_sdca_is_device_rt712_vb,
+ .sof_tplg_filename = "sof-arl-rt712-l0-rt1320-l3.tplg",
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
- .link_mask = BIT(2),
- .links = arl_cs42l43_l2,
+ .link_mask = BIT(2) | BIT(3),
+ .links = arl_cs42l43_l2_cs35l56_l3,
.drv_name = "sof_sdw",
- .sof_tplg_filename = "sof-arl-cs42l43-l2.tplg",
+ .sof_tplg_filename = "sof-arl-cs42l43-l2-cs35l56-l3.tplg",
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
- .link_mask = BIT(0) | BIT(3),
- .links = arl_rt711_l0_rt1316_l3,
+ .link_mask = BIT(0),
+ .links = arl_cs42l43_l0,
.drv_name = "sof_sdw",
- .sof_tplg_filename = "sof-arl-rt711-l0-rt1316-l3.tplg",
+ .sof_tplg_filename = "sof-arl-cs42l43-l0.tplg",
+ .get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
.link_mask = 0x1, /* link0 required */
@@ -522,10 +608,17 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_arl_sdw_machines[] = {
.sof_tplg_filename = "sof-arl-rt711-l0.tplg",
},
{
- .link_mask = BIT(0) | BIT(2),
- .links = arl_rt722_l0_rt1320_l2,
+ .link_mask = BIT(2),
+ .links = arl_cs42l43_l2,
.drv_name = "sof_sdw",
- .sof_tplg_filename = "sof-arl-rt722-l0_rt1320-l2.tplg",
+ .sof_tplg_filename = "sof-arl-cs42l43-l2.tplg",
+ .get_function_tplg_files = sof_sdw_get_tplg_files,
+ },
+ {
+ .link_mask = BIT(1),
+ .links = arl_n_mrd_es9356_link1,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-arl-es9356.tplg",
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{},
diff --git a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
index 72c35e73078e..2e4222456f27 100644
--- a/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-mtl-match.c
@@ -122,6 +122,42 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
.group_id = 1,
};
+static const struct snd_soc_acpi_endpoint tac5xx2_endpoints[] = {
+ { /* Playback Endpoint */
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Mic Capture Endpoint */
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* UAJ-HP with Mic Endpoint */
+ .num = 2,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
+static const struct snd_soc_acpi_endpoint tas2883_endpoints[] = {
+ { /* Playback Endpoint */
+ .num = 0,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+ { /* Mic Capture Endpoint */
+ .num = 1,
+ .aggregated = 0,
+ .group_position = 0,
+ .group_id = 0,
+ },
+};
+
static const struct snd_soc_acpi_endpoint rt712_endpoints[] = {
{
.num = 0,
@@ -1011,6 +1047,33 @@ static const struct snd_soc_acpi_adr_device cs42l42_0_adr[] = {
}
};
+static const struct snd_soc_acpi_adr_device tac5572_0_adr[] = {
+ {
+ .adr = 0x0000300102557201ull,
+ .num_endpoints = ARRAY_SIZE(tac5xx2_endpoints),
+ .endpoints = tac5xx2_endpoints,
+ .name_prefix = "tac5572"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device tac5672_0_adr[] = {
+ {
+ .adr = 0x0000300102567201ull,
+ .num_endpoints = ARRAY_SIZE(tac5xx2_endpoints),
+ .endpoints = tac5xx2_endpoints,
+ .name_prefix = "tac5672"
+ }
+};
+
+static const struct snd_soc_acpi_adr_device tac5682_0_adr[] = {
+ {
+ .adr = 0x0000300102568201ull,
+ .num_endpoints = ARRAY_SIZE(tac5xx2_endpoints),
+ .endpoints = tac5xx2_endpoints,
+ .name_prefix = "tac5682"
+ }
+};
+
static const struct snd_soc_acpi_adr_device tas2783_0_adr[] = {
{
.adr = 0x00003c0102000001ull,
@@ -1035,9 +1098,45 @@ static const struct snd_soc_acpi_adr_device tas2783_0_adr[] = {
.num_endpoints = 1,
.endpoints = &spk_r_endpoint,
.name_prefix = "tas2783-4"
+ },
+};
+
+static const struct snd_soc_acpi_adr_device tas2883_0_adr[] = {
+ {
+ .adr = 0x0000300102288301ull,
+ .num_endpoints = ARRAY_SIZE(tas2883_endpoints),
+ .endpoints = tas2883_endpoints,
+ .name_prefix = "tas2883"
}
};
+static const struct snd_soc_acpi_link_adr tac5572_l0[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(tac5572_0_adr),
+ .adr_d = tac5572_0_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr tac5672_l0[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(tac5672_0_adr),
+ .adr_d = tac5672_0_adr,
+ },
+ {}
+};
+
+static const struct snd_soc_acpi_link_adr tac5682_l0[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(tac5682_0_adr),
+ .adr_d = tac5682_0_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr tas2783_link0[] = {
{
.mask = BIT(0),
@@ -1047,6 +1146,15 @@ static const struct snd_soc_acpi_link_adr tas2783_link0[] = {
{}
};
+static const struct snd_soc_acpi_link_adr tas2883_l0[] = {
+ {
+ .mask = BIT(0),
+ .num_adr = ARRAY_SIZE(tas2883_0_adr),
+ .adr_d = tas2883_0_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr cs42l42_link0_max98363_link2[] = {
/* Expected order: jack -> amp */
{
@@ -1210,11 +1318,35 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_mtl_sdw_machines[] = {
},
{
.link_mask = BIT(0),
+ .links = tac5572_l0,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-tac5572.tplg",
+ },
+ {
+ .link_mask = BIT(0),
+ .links = tac5672_l0,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-tac5672.tplg",
+ },
+ {
+ .link_mask = BIT(0),
+ .links = tac5682_l0,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-tac5682.tplg",
+ },
+ {
+ .link_mask = BIT(0),
.links = tas2783_link0,
.drv_name = "sof_sdw",
.sof_tplg_filename = "sof-mtl-tas2783.tplg",
},
{
+ .link_mask = BIT(0),
+ .links = tas2883_l0,
+ .drv_name = "sof_sdw",
+ .sof_tplg_filename = "sof-mtl-tas2883.tplg",
+ },
+ {
.link_mask = GENMASK(3, 0),
.links = mtl_rt713_l0_rt1316_l12_rt1713_l3,
.drv_name = "sof_sdw",
diff --git a/sound/soc/intel/common/soc-acpi-intel-nvl-match.c b/sound/soc/intel/common/soc-acpi-intel-nvl-match.c
index b8695d47e55b..217272260803 100644
--- a/sound/soc/intel/common/soc-acpi-intel-nvl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-nvl-match.c
@@ -10,7 +10,20 @@
#include <sound/soc-acpi-intel-match.h>
#include "soc-acpi-intel-sdw-mockup-match.h"
+static const struct snd_soc_acpi_codecs nvl_essx_83x6 = {
+ .num_codecs = 3,
+ .codecs = { "ESSX8316", "ESSX8326", "ESSX8336"},
+};
+
struct snd_soc_acpi_mach snd_soc_acpi_intel_nvl_machines[] = {
+ {
+ .comp_ids = &nvl_essx_83x6,
+ .drv_name = "sof-essx8336",
+ .sof_tplg_filename = "sof-nvl-es8336", /* the tplg suffix is added at run time */
+ .tplg_quirk_mask = SND_SOC_ACPI_TPLG_INTEL_SSP_NUMBER |
+ SND_SOC_ACPI_TPLG_INTEL_SSP_MSB |
+ SND_SOC_ACPI_TPLG_INTEL_DMIC_NUMBER,
+ },
{},
};
EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_nvl_machines);
diff --git a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c
index 3b7818355ff6..f7694b2a2b02 100644
--- a/sound/soc/intel/common/soc-acpi-intel-ptl-match.c
+++ b/sound/soc/intel/common/soc-acpi-intel-ptl-match.c
@@ -92,48 +92,6 @@ static const struct snd_soc_acpi_endpoint spk_r_endpoint = {
.group_id = 1,
};
-static const struct snd_soc_acpi_endpoint spk_1_endpoint = {
- .num = 0,
- .aggregated = 1,
- .group_position = 1,
- .group_id = 1,
-};
-
-static const struct snd_soc_acpi_endpoint spk_2_endpoint = {
- .num = 0,
- .aggregated = 1,
- .group_position = 2,
- .group_id = 1,
-};
-
-static const struct snd_soc_acpi_endpoint spk_3_endpoint = {
- .num = 0,
- .aggregated = 1,
- .group_position = 3,
- .group_id = 1,
-};
-
-static const struct snd_soc_acpi_endpoint spk_4_endpoint = {
- .num = 0,
- .aggregated = 1,
- .group_position = 4,
- .group_id = 1,
-};
-
-static const struct snd_soc_acpi_endpoint spk_5_endpoint = {
- .num = 0,
- .aggregated = 1,
- .group_position = 5,
- .group_id = 1,
-};
-
-static const struct snd_soc_acpi_endpoint spk_6_endpoint = {
- .num = 0,
- .aggregated = 1,
- .group_position = 6,
- .group_id = 1,
-};
-
static const struct snd_soc_acpi_endpoint jack_dmic_endpoints[] = {
/* Jack Endpoint */
{
@@ -202,15 +160,6 @@ static const struct snd_soc_acpi_endpoint cs42l43_amp_spkagg_endpoints[] = {
},
};
-static const struct snd_soc_acpi_adr_device cs42l43_2_adr[] = {
- {
- .adr = 0x00023001fa424301ull,
- .num_endpoints = ARRAY_SIZE(cs42l43_amp_spkagg_endpoints),
- .endpoints = cs42l43_amp_spkagg_endpoints,
- .name_prefix = "cs42l43"
- }
-};
-
static const struct snd_soc_acpi_adr_device cs42l43_3_agg_adr[] = {
{
.adr = 0x00033001FA424301ull,
@@ -235,48 +184,6 @@ static const struct snd_soc_acpi_adr_device cs35l56_2_lr_adr[] = {
}
};
-static const struct snd_soc_acpi_adr_device cs35l56_1_3amp_adr[] = {
- {
- .adr = 0x00013001fa355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_1_endpoint,
- .name_prefix = "AMP1"
- },
- {
- .adr = 0x00013101fa355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_2_endpoint,
- .name_prefix = "AMP2"
- },
- {
- .adr = 0x00013201fa355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_3_endpoint,
- .name_prefix = "AMP3"
- }
-};
-
-static const struct snd_soc_acpi_adr_device cs35l56_3_3amp_adr[] = {
- {
- .adr = 0x00033301fa355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_4_endpoint,
- .name_prefix = "AMP4"
- },
- {
- .adr = 0x00033401fa355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_5_endpoint,
- .name_prefix = "AMP5"
- },
- {
- .adr = 0x00033501fa355601ull,
- .num_endpoints = 1,
- .endpoints = &spk_6_endpoint,
- .name_prefix = "AMP6"
- }
-};
-
static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = {
{
.adr = 0x000030025D071101ull,
@@ -408,25 +315,6 @@ static const struct snd_soc_acpi_link_adr ptl_cs42l43_agg_l3_cs35l56_l2[] = {
{}
};
-static const struct snd_soc_acpi_link_adr ptl_cs42l43_l2_cs35l56x6_l13[] = {
- {
- .mask = BIT(2),
- .num_adr = ARRAY_SIZE(cs42l43_2_adr),
- .adr_d = cs42l43_2_adr,
- },
- {
- .mask = BIT(1),
- .num_adr = ARRAY_SIZE(cs35l56_1_3amp_adr),
- .adr_d = cs35l56_1_3amp_adr,
- },
- {
- .mask = BIT(3),
- .num_adr = ARRAY_SIZE(cs35l56_3_3amp_adr),
- .adr_d = cs35l56_3_3amp_adr,
- },
- {}
-};
-
static const struct snd_soc_acpi_link_adr ptl_rt722_l0_rt1320_l23[] = {
{
.mask = BIT(0),
@@ -493,6 +381,20 @@ static const struct snd_soc_acpi_link_adr ptl_sdw_rt713_vb_l3_rt1320_l12[] = {
{}
};
+static const struct snd_soc_acpi_link_adr ptl_sdw_rt713_vb_l3_rt1320_l1[] = {
+ {
+ .mask = BIT(3),
+ .num_adr = ARRAY_SIZE(rt713_vb_3_adr),
+ .adr_d = rt713_vb_3_adr,
+ },
+ {
+ .mask = BIT(1),
+ .num_adr = ARRAY_SIZE(rt1320_1_group2_adr),
+ .adr_d = rt1320_1_group2_adr,
+ },
+ {}
+};
+
static const struct snd_soc_acpi_link_adr ptl_sdw_rt712_vb_l2_rt1320_l1[] = {
{
.mask = BIT(2),
@@ -579,10 +481,11 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = {
.get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
- .link_mask = BIT(1) | BIT(2) | BIT(3),
- .links = ptl_cs42l43_l2_cs35l56x6_l13,
+ .link_mask = BIT(1) | BIT(3),
+ .links = ptl_sdw_rt713_vb_l3_rt1320_l1,
.drv_name = "sof_sdw",
- .sof_tplg_filename = "sof-ptl-cs42l43-l2-cs35l56x6-l13.tplg",
+ .sof_tplg_filename = "sof-ptl-rt713-l3-rt1320-l1.tplg",
+ .get_function_tplg_files = sof_sdw_get_tplg_files,
},
{
.link_mask = BIT(0) | BIT(2) | BIT(3),
@@ -611,6 +514,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_ptl_sdw_machines[] = {
.link_mask = BIT(2) | BIT(3),
.links = ptl_cs42l43_agg_l3_cs35l56_l2,
.drv_name = "sof_sdw",
+ .machine_check = snd_soc_acpi_intel_no_function_topology,
.sof_tplg_filename = "sof-ptl-cs42l43-agg-l3-cs35l56-l2.tplg",
},
{
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
index 3eaa058f8460..7caabc501b16 100644
--- a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
+++ b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.c
@@ -6,6 +6,7 @@
*
*/
+#include <linux/dmi.h>
#include <linux/soundwire/sdw_intel.h>
#include <sound/sdca.h>
#include <sound/soc-acpi.h>
@@ -37,6 +38,21 @@ bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg)
}
EXPORT_SYMBOL_NS(snd_soc_acpi_intel_sdca_is_device_rt712_vb, "SND_SOC_ACPI_INTEL_SDCA_QUIRKS");
+static const struct dmi_system_id function_topology_quirk_table[] = {
+ {
+ .matches = {
+ DMI_MATCH(DMI_SYS_VENDOR, "Google"),
+ },
+ },
+ {}
+};
+
+bool snd_soc_acpi_intel_no_function_topology(void *arg)
+{
+ return !!dmi_check_system(function_topology_quirk_table);
+}
+EXPORT_SYMBOL_NS(snd_soc_acpi_intel_no_function_topology, "SND_SOC_ACPI_INTEL_SDCA_QUIRKS");
+
MODULE_DESCRIPTION("ASoC ACPI Intel SDCA quirks");
MODULE_LICENSE("GPL");
MODULE_IMPORT_NS("SND_SOC_SDCA");
diff --git a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h
index bead5ec6243f..2ea0a1881c4b 100644
--- a/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h
+++ b/sound/soc/intel/common/soc-acpi-intel-sdca-quirks.h
@@ -10,5 +10,6 @@
#define _SND_SOC_ACPI_INTEL_SDCA_QUIRKS
bool snd_soc_acpi_intel_sdca_is_device_rt712_vb(void *arg);
+bool snd_soc_acpi_intel_no_function_topology(void *arg);
#endif
diff --git a/sound/soc/intel/common/sof-function-topology-lib.c b/sound/soc/intel/common/sof-function-topology-lib.c
index 0daa7d83808b..2f2c902ef90c 100644
--- a/sound/soc/intel/common/sof-function-topology-lib.c
+++ b/sound/soc/intel/common/sof-function-topology-lib.c
@@ -19,6 +19,7 @@ enum tplg_device_id {
TPLG_DEVICE_SDCA_MIC,
TPLG_DEVICE_INTEL_PCH_DMIC,
TPLG_DEVICE_HDMI,
+ TPLG_DEVICE_LOOPBACK_VIRTUAL,
TPLG_DEVICE_MAX
};
@@ -81,7 +82,15 @@ int sof_sdw_get_tplg_files(struct snd_soc_card *card, const struct snd_soc_acpi_
} else if (strstr(dai_link->name, "iDisp")) {
tplg_dev = TPLG_DEVICE_HDMI;
tplg_dev_name = "hdmi-pcm5";
-
+ } else if (strstr(dai_link->name, "Loopback_Virtual")) {
+ tplg_dev = TPLG_DEVICE_LOOPBACK_VIRTUAL;
+ /*
+ * Mark the LOOPBACK_VIRTUAL device but no need to create the
+ * LOOPBACK_VIRTUAL topology. Just to avoid the dai_link is not supported
+ * error.
+ */
+ tplg_mask |= BIT(tplg_dev);
+ continue;
} else {
/* The dai link is not supported by separated tplg yet */
dev_dbg(card->dev,
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index 517619531615..d36bbc820618 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -11,7 +11,6 @@
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
#include <linux/slab.h>
diff --git a/sound/soc/loongson/Makefile b/sound/soc/loongson/Makefile
index 4c6d3130bcee..6e43672071fc 100644
--- a/sound/soc/loongson/Makefile
+++ b/sound/soc/loongson/Makefile
@@ -1,12 +1,12 @@
# SPDX-License-Identifier: GPL-2.0
#Platform Support
-snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o loongson_dma.o
+snd-soc-loongson-i2s-pci-y := loongson_i2s_pci.o
obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PCI) += snd-soc-loongson-i2s-pci.o snd-soc-loongson-i2s.o
snd-soc-loongson-i2s-plat-y := loongson_i2s_plat.o
obj-$(CONFIG_SND_SOC_LOONGSON_I2S_PLATFORM) += snd-soc-loongson-i2s-plat.o snd-soc-loongson-i2s.o
-snd-soc-loongson-i2s-y := loongson_i2s.o
+snd-soc-loongson-i2s-y := loongson_i2s.o loongson_dma.o
obj-$(CONFIG_SND_LOONGSON1_AC97) += loongson1_ac97.o
diff --git a/sound/soc/loongson/loongson_dma.c b/sound/soc/loongson/loongson_dma.c
index a149b643175c..44fdce22f58c 100644
--- a/sound/soc/loongson/loongson_dma.c
+++ b/sound/soc/loongson/loongson_dma.c
@@ -4,6 +4,7 @@
//
// Copyright (C) 2023 Loongson Technology Corporation Limited
// Author: Yingkun Meng <mengyingkun@loongson.cn>
+// Binbin ZHou <zhoubinbin@loongson.cn>
//
#include <linux/module.h>
@@ -16,7 +17,7 @@
#include <sound/pcm_params.h>
#include "loongson_i2s.h"
-/* DMA dma_order Register */
+/* Internal DMA dma_order Register */
#define DMA_ORDER_STOP BIT(4) /* DMA stop */
#define DMA_ORDER_START BIT(3) /* DMA start */
#define DMA_ORDER_ASK_VALID BIT(2) /* DMA ask valid flag */
@@ -27,9 +28,9 @@
#define DMA_ORDER_CTRL_MASK (0x0fUL) /* Control mask */
/*
- * DMA registers descriptor.
+ * Internal DMA registers descriptor.
*/
-struct loongson_dma_desc {
+struct loongson_idma_desc {
u32 order; /* Next descriptor address register */
u32 saddr; /* Source address register */
u32 daddr; /* Device address register */
@@ -44,17 +45,17 @@ struct loongson_dma_desc {
} __packed;
struct loongson_runtime_data {
- struct loongson_dma_data *dma_data;
+ struct loongson_idma_data *dma_data;
- struct loongson_dma_desc *dma_desc_arr;
+ struct loongson_idma_desc *dma_desc_arr;
dma_addr_t dma_desc_arr_phy;
int dma_desc_arr_size;
- struct loongson_dma_desc *dma_pos_desc;
+ struct loongson_idma_desc *dma_pos_desc;
dma_addr_t dma_pos_desc_phy;
};
-static const struct snd_pcm_hardware ls_pcm_hardware = {
+static const struct snd_pcm_hardware loongson_idma_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -67,12 +68,11 @@ static const struct snd_pcm_hardware ls_pcm_hardware = {
.period_bytes_min = 128,
.period_bytes_max = 128 * 1024,
.periods_min = 1,
- .periods_max = PAGE_SIZE / sizeof(struct loongson_dma_desc),
+ .periods_max = PAGE_SIZE / sizeof(struct loongson_idma_desc),
.buffer_bytes_max = 1024 * 1024,
};
-static struct
-loongson_dma_desc *dma_desc_save(struct loongson_runtime_data *prtd)
+static struct loongson_idma_desc *dma_desc_save(struct loongson_runtime_data *prtd)
{
void __iomem *order_reg = prtd->dma_data->order_addr;
u64 val;
@@ -88,8 +88,8 @@ loongson_dma_desc *dma_desc_save(struct loongson_runtime_data *prtd)
return prtd->dma_pos_desc;
}
-static int loongson_pcm_trigger(struct snd_soc_component *component,
- struct snd_pcm_substream *substream, int cmd)
+static int loongson_idma_pcm_trigger(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream, int cmd)
{
struct loongson_runtime_data *prtd = substream->runtime->private_data;
struct device *dev = substream->pcm->card->dev;
@@ -131,9 +131,9 @@ static int loongson_pcm_trigger(struct snd_soc_component *component,
return 0;
}
-static int loongson_pcm_hw_params(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+static int loongson_idma_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 device *dev = substream->pcm->card->dev;
@@ -141,7 +141,7 @@ static int loongson_pcm_hw_params(struct snd_soc_component *component,
size_t buf_len = params_buffer_bytes(params);
size_t period_len = params_period_bytes(params);
dma_addr_t order_addr, mem_addr;
- struct loongson_dma_desc *desc;
+ struct loongson_idma_desc *desc;
u32 num_periods;
int i;
@@ -195,25 +195,33 @@ static int loongson_pcm_hw_params(struct snd_soc_component *component,
}
static snd_pcm_uframes_t
-loongson_pcm_pointer(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
+loongson_idma_pcm_pointer(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct device *dev = substream->pcm->card->dev;
struct loongson_runtime_data *prtd = runtime->private_data;
- struct loongson_dma_desc *desc;
+ struct loongson_idma_desc *desc;
snd_pcm_uframes_t x;
u64 addr;
desc = dma_desc_save(prtd);
addr = ((u64)desc->saddr_hi << 32) | desc->saddr;
- x = bytes_to_frames(runtime, addr - runtime->dma_addr);
- if (x == runtime->buffer_size)
+ if (addr < runtime->dma_addr ||
+ addr > runtime->dma_addr + runtime->dma_bytes) {
+ dev_warn(dev, "WARNING! dma_addr:0x%llx\n", addr);
x = 0;
+ } else {
+ x = bytes_to_frames(runtime, addr - runtime->dma_addr);
+ if (x == runtime->buffer_size)
+ x = 0;
+ }
+
return x;
}
-static irqreturn_t loongson_pcm_dma_irq(int irq, void *devid)
+static irqreturn_t loongson_idma_pcm_dma_irq(int irq, void *devid)
{
struct snd_pcm_substream *substream = devid;
@@ -221,14 +229,14 @@ static irqreturn_t loongson_pcm_dma_irq(int irq, void *devid)
return IRQ_HANDLED;
}
-static int loongson_pcm_open(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
+static int loongson_idma_pcm_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_card *card = substream->pcm->card;
struct loongson_runtime_data *prtd;
- struct loongson_dma_data *dma_data;
+ struct loongson_idma_data *dma_data;
/*
* For mysterious reasons (and despite what the manual says)
@@ -241,7 +249,7 @@ static int loongson_pcm_open(struct snd_soc_component *component,
SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128);
snd_pcm_hw_constraint_integer(substream->runtime,
SNDRV_PCM_HW_PARAM_PERIODS);
- snd_soc_set_runtime_hwparams(substream, &ls_pcm_hardware);
+ snd_soc_set_runtime_hwparams(substream, &loongson_idma_hardware);
prtd = kzalloc_obj(*prtd);
if (!prtd)
@@ -277,8 +285,8 @@ desc_err:
return -ENOMEM;
}
-static int loongson_pcm_close(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
+static int loongson_idma_pcm_close(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
{
struct snd_card *card = substream->pcm->card;
struct loongson_runtime_data *prtd = substream->runtime->private_data;
@@ -293,21 +301,21 @@ static int loongson_pcm_close(struct snd_soc_component *component,
return 0;
}
-static int loongson_pcm_mmap(struct snd_soc_component *component,
- struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
+static int loongson_idma_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);
+ substream->dma_buffer.addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
}
-static int loongson_pcm_new(struct snd_soc_component *component,
- struct snd_soc_pcm_runtime *rtd)
+static int loongson_idma_pcm_new(struct snd_soc_component *component,
+ struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
struct snd_pcm_substream *substream;
- struct loongson_dma_data *dma_data;
+ struct loongson_idma_data *dma_data;
unsigned int i;
int ret;
@@ -319,7 +327,7 @@ static int loongson_pcm_new(struct snd_soc_component *component,
dma_data = snd_soc_dai_get_dma_data(snd_soc_rtd_to_cpu(rtd, 0),
substream);
ret = devm_request_irq(card->dev, dma_data->irq,
- loongson_pcm_dma_irq,
+ loongson_idma_pcm_dma_irq,
IRQF_TRIGGER_HIGH, LS_I2S_DRVNAME,
substream);
if (ret < 0) {
@@ -330,16 +338,76 @@ static int loongson_pcm_new(struct snd_soc_component *component,
return snd_pcm_set_fixed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
card->dev,
- ls_pcm_hardware.buffer_bytes_max);
+ loongson_idma_hardware.buffer_bytes_max);
}
-const struct snd_soc_component_driver loongson_i2s_component = {
+/* Internal DMA component */
+const struct snd_soc_component_driver loongson_i2s_idma_component = {
.name = LS_I2S_DRVNAME,
- .open = loongson_pcm_open,
- .close = loongson_pcm_close,
- .hw_params = loongson_pcm_hw_params,
- .trigger = loongson_pcm_trigger,
- .pointer = loongson_pcm_pointer,
- .mmap = loongson_pcm_mmap,
- .pcm_new = loongson_pcm_new,
+ .open = loongson_idma_pcm_open,
+ .close = loongson_idma_pcm_close,
+ .hw_params = loongson_idma_pcm_hw_params,
+ .trigger = loongson_idma_pcm_trigger,
+ .pointer = loongson_idma_pcm_pointer,
+ .mmap = loongson_idma_pcm_mmap,
+ .pcm_new = loongson_idma_pcm_new,
+};
+EXPORT_SYMBOL_GPL(loongson_i2s_idma_component);
+
+static const struct snd_pcm_hardware loongson_edma_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_PAUSE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE,
+ .period_bytes_min = 128,
+ .period_bytes_max = 128 * 1024,
+ .periods_min = 1,
+ .periods_max = 64,
+ .buffer_bytes_max = 1024 * 1024,
+};
+
+const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = {
+ .pcm_hardware = &loongson_edma_hardware,
+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+ .prealloc_buffer_size = 128 * 1024,
+};
+EXPORT_SYMBOL_GPL(loongson_dmaengine_pcm_config);
+
+/* External DMA component */
+static int loongson_edma_pcm_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if (substream->pcm->device & 1) {
+ runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
+ runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
+ }
+
+ if (substream->pcm->device & 2)
+ runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID);
+ /*
+ * For mysterious reasons (and despite what the manual says)
+ * playback samples are lost if the DMA count is not a multiple
+ * of the DMA burst size. Let's add a rule to enforce that.
+ */
+ snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
+ snd_pcm_hw_constraint_step(runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128);
+ snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+
+ return 0;
+}
+
+const struct snd_soc_component_driver loongson_i2s_edma_component = {
+ .name = LS_I2S_DRVNAME,
+ .open = loongson_edma_pcm_open,
};
+EXPORT_SYMBOL_GPL(loongson_i2s_edma_component);
diff --git a/sound/soc/loongson/loongson_dma.h b/sound/soc/loongson/loongson_dma.h
index 073ee8c0c046..a040681d2693 100644
--- a/sound/soc/loongson/loongson_dma.h
+++ b/sound/soc/loongson/loongson_dma.h
@@ -9,8 +9,8 @@
#ifndef _LOONGSON_DMA_H
#define _LOONGSON_DMA_H
-#include <sound/soc.h>
-
-extern const struct snd_soc_component_driver loongson_i2s_component;
+extern const struct snd_soc_component_driver loongson_i2s_idma_component;
+extern const struct snd_soc_component_driver loongson_i2s_edma_component;
+extern const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config;
#endif
diff --git a/sound/soc/loongson/loongson_i2s.c b/sound/soc/loongson/loongson_i2s.c
index e336656e13eb..cfe102a8b604 100644
--- a/sound/soc/loongson/loongson_i2s.c
+++ b/sound/soc/loongson/loongson_i2s.c
@@ -254,6 +254,7 @@ static int i2s_suspend(struct device *dev)
struct loongson_i2s *i2s = dev_get_drvdata(dev);
regcache_cache_only(i2s->regmap, true);
+ regcache_mark_dirty(i2s->regmap);
return 0;
}
@@ -263,7 +264,7 @@ static int i2s_resume(struct device *dev)
struct loongson_i2s *i2s = dev_get_drvdata(dev);
regcache_cache_only(i2s->regmap, false);
- regcache_mark_dirty(i2s->regmap);
+
return regcache_sync(i2s->regmap);
}
@@ -272,5 +273,58 @@ const struct dev_pm_ops loongson_i2s_pm = {
};
EXPORT_SYMBOL_GPL(loongson_i2s_pm);
+static bool loongson_i2s_rd_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case LS_I2S_VER:
+ case LS_I2S_CFG:
+ case LS_I2S_CTRL:
+ case LS_I2S_RX_DATA:
+ case LS_I2S_TX_DATA:
+ case LS_I2S_CFG1:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool loongson_i2s_wr_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case LS_I2S_CFG:
+ case LS_I2S_CTRL:
+ case LS_I2S_RX_DATA:
+ case LS_I2S_TX_DATA:
+ case LS_I2S_CFG1:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static bool loongson_i2s_volatile_reg(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case LS_I2S_CTRL:
+ case LS_I2S_RX_DATA:
+ case LS_I2S_TX_DATA:
+ return true;
+ default:
+ return false;
+ };
+}
+
+const struct regmap_config loongson_i2s_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+ .max_register = LS_I2S_CFG1,
+ .readable_reg = loongson_i2s_rd_reg,
+ .writeable_reg = loongson_i2s_wr_reg,
+ .volatile_reg = loongson_i2s_volatile_reg,
+ .cache_type = REGCACHE_MAPLE,
+};
+EXPORT_SYMBOL_GPL(loongson_i2s_regmap_config);
+
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Common functions for loongson I2S controller driver");
diff --git a/sound/soc/loongson/loongson_i2s.h b/sound/soc/loongson/loongson_i2s.h
index c8052a762c1b..8b4603c876c5 100644
--- a/sound/soc/loongson/loongson_i2s.h
+++ b/sound/soc/loongson/loongson_i2s.h
@@ -42,7 +42,7 @@
#define LS_I2S_DRVNAME "loongson-i2s"
-struct loongson_dma_data {
+struct loongson_idma_data {
dma_addr_t dev_addr; /* device physical address for DMA */
void __iomem *order_addr; /* DMA order register */
int irq; /* DMA irq */
@@ -52,11 +52,11 @@ struct loongson_i2s {
struct device *dev;
union {
struct snd_dmaengine_dai_dma_data playback_dma_data;
- struct loongson_dma_data tx_dma_data;
+ struct loongson_idma_data tx_dma_data;
};
union {
struct snd_dmaengine_dai_dma_data capture_dma_data;
- struct loongson_dma_data rx_dma_data;
+ struct loongson_idma_data rx_dma_data;
};
struct regmap *regmap;
void __iomem *reg_base;
@@ -65,6 +65,7 @@ struct loongson_i2s {
u32 sysclk;
};
+extern const struct regmap_config loongson_i2s_regmap_config;
extern const struct dev_pm_ops loongson_i2s_pm;
extern struct snd_soc_dai_driver loongson_i2s_dai;
diff --git a/sound/soc/loongson/loongson_i2s_pci.c b/sound/soc/loongson/loongson_i2s_pci.c
index 1ea5501a97f8..f5b560465706 100644
--- a/sound/soc/loongson/loongson_i2s_pci.c
+++ b/sound/soc/loongson/loongson_i2s_pci.c
@@ -13,70 +13,17 @@
#include <linux/acpi.h>
#include <linux/pci.h>
#include <sound/soc.h>
+
#include "loongson_i2s.h"
#include "loongson_dma.h"
#define DRIVER_NAME "loongson-i2s-pci"
-static bool loongson_i2s_wr_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case LS_I2S_CFG:
- case LS_I2S_CTRL:
- case LS_I2S_RX_DATA:
- case LS_I2S_TX_DATA:
- case LS_I2S_CFG1:
- return true;
- default:
- return false;
- };
-}
-
-static bool loongson_i2s_rd_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case LS_I2S_VER:
- case LS_I2S_CFG:
- case LS_I2S_CTRL:
- case LS_I2S_RX_DATA:
- case LS_I2S_TX_DATA:
- case LS_I2S_CFG1:
- return true;
- default:
- return false;
- };
-}
-
-static bool loongson_i2s_volatile_reg(struct device *dev, unsigned int reg)
-{
- switch (reg) {
- case LS_I2S_CFG:
- case LS_I2S_CTRL:
- case LS_I2S_RX_DATA:
- case LS_I2S_TX_DATA:
- case LS_I2S_CFG1:
- return true;
- default:
- return false;
- };
-}
-
-static const struct regmap_config loongson_i2s_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .max_register = LS_I2S_CFG1,
- .writeable_reg = loongson_i2s_wr_reg,
- .readable_reg = loongson_i2s_rd_reg,
- .volatile_reg = loongson_i2s_volatile_reg,
- .cache_type = REGCACHE_FLAT,
-};
-
static int loongson_i2s_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *pid)
{
const struct fwnode_handle *fwnode = pdev->dev.fwnode;
- struct loongson_dma_data *tx_data, *rx_data;
+ struct loongson_idma_data *tx_data, *rx_data;
struct device *dev = &pdev->dev;
struct loongson_i2s *i2s;
int ret;
@@ -133,7 +80,7 @@ static int loongson_i2s_pci_probe(struct pci_dev *pdev,
udelay(200);
}
- ret = devm_snd_soc_register_component(dev, &loongson_i2s_component,
+ ret = devm_snd_soc_register_component(dev, &loongson_i2s_idma_component,
&loongson_i2s_dai, 1);
if (ret)
return dev_err_probe(dev, ret, "register DAI failed\n");
diff --git a/sound/soc/loongson/loongson_i2s_plat.c b/sound/soc/loongson/loongson_i2s_plat.c
index fa2e450ff618..ac054b6ce632 100644
--- a/sound/soc/loongson/loongson_i2s_plat.c
+++ b/sound/soc/loongson/loongson_i2s_plat.c
@@ -19,6 +19,7 @@
#include <sound/soc.h>
#include "loongson_i2s.h"
+#include "loongson_dma.h"
#define LOONGSON_I2S_RX_DMA_OFFSET 21
#define LOONGSON_I2S_TX_DMA_OFFSET 18
@@ -29,70 +30,6 @@
#define LOONGSON_DMA3_CONF 0x3
#define LOONGSON_DMA4_CONF 0x4
-/* periods_max = PAGE_SIZE / sizeof(struct ls_dma_chan_reg) */
-static const struct snd_pcm_hardware loongson_pcm_hardware = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME |
- SNDRV_PCM_INFO_PAUSE,
- .formats = SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S20_3LE |
- SNDRV_PCM_FMTBIT_S24_LE,
- .period_bytes_min = 128,
- .period_bytes_max = 128 * 1024,
- .periods_min = 1,
- .periods_max = 64,
- .buffer_bytes_max = 1024 * 1024,
-};
-
-static const struct snd_dmaengine_pcm_config loongson_dmaengine_pcm_config = {
- .pcm_hardware = &loongson_pcm_hardware,
- .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
- .prealloc_buffer_size = 128 * 1024,
-};
-
-static int loongson_pcm_open(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
-
- if (substream->pcm->device & 1) {
- runtime->hw.info &= ~SNDRV_PCM_INFO_INTERLEAVED;
- runtime->hw.info |= SNDRV_PCM_INFO_NONINTERLEAVED;
- }
-
- if (substream->pcm->device & 2)
- runtime->hw.info &= ~(SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID);
- /*
- * For mysterious reasons (and despite what the manual says)
- * playback samples are lost if the DMA count is not a multiple
- * of the DMA burst size. Let's add a rule to enforce that.
- */
- snd_pcm_hw_constraint_step(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 128);
- snd_pcm_hw_constraint_step(runtime, 0,
- SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 128);
- snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
-
- return 0;
-}
-
-static const struct snd_soc_component_driver loongson_i2s_component_driver = {
- .name = LS_I2S_DRVNAME,
- .open = loongson_pcm_open,
-};
-
-static const struct regmap_config loongson_i2s_regmap_config = {
- .reg_bits = 32,
- .reg_stride = 4,
- .val_bits = 32,
- .max_register = 0x14,
- .cache_type = REGCACHE_FLAT,
-};
-
static int loongson_i2s_apbdma_config(struct platform_device *pdev)
{
int val;
@@ -155,7 +92,7 @@ static int loongson_i2s_plat_probe(struct platform_device *pdev)
dev_set_name(dev, LS_I2S_DRVNAME);
dev_set_drvdata(dev, i2s);
- ret = devm_snd_soc_register_component(dev, &loongson_i2s_component_driver,
+ ret = devm_snd_soc_register_component(dev, &loongson_i2s_edma_component,
&loongson_i2s_dai, 1);
if (ret)
return dev_err_probe(dev, ret, "failed to register DAI\n");
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
index 3a1e1fa3fe5c..4af7bbb58010 100644
--- a/sound/soc/mediatek/Kconfig
+++ b/sound/soc/mediatek/Kconfig
@@ -26,6 +26,16 @@ config SND_SOC_MT2701_CS42448
Select Y if you have such device.
If unsure select "N".
+config SND_SOC_MT2701_HDMI
+ tristate "ASoC Audio driver for MT2701 with on-chip HDMI codec"
+ depends on SND_SOC_MT2701
+ select SND_SOC_HDMI_CODEC
+ help
+ This adds the ASoC machine driver for MediaTek MT2701 and
+ MT7623N boards routing the AFE I2S back-end to the on-chip
+ HDMI transmitter via the generic HDMI codec.
+ If unsure select "N".
+
config SND_SOC_MT2701_WM8960
tristate "ASoc Audio driver for MT2701 with WM8960 codec"
depends on SND_SOC_MT2701 && I2C
@@ -353,4 +363,34 @@ config SND_SOC_MT8365_MT6357
Select Y if you have such device.
If unsure select "N".
+config SND_SOC_MT8196
+ tristate "ASoC support for Mediatek MT8196 chip"
+ depends on ARCH_MEDIATEK
+ select SND_SOC_MEDIATEK
+ help
+ This adds ASoC driver for Mediatek MT8196 boards
+ that can be used with other codecs.
+ Select Y if you have such device.
+ If unsure select "N".
+
+config SND_SOC_MT8196_NAU8825
+ tristate "ASoc Audio driver for MT8196 with NAU8825 and I2S codec"
+ depends on SND_SOC_MT8196
+ depends on I2C
+ select SND_SOC_HDMI_CODEC
+ select SND_SOC_DMIC
+ select SND_SOC_NAU8315
+ select SND_SOC_NAU8825
+ select SND_SOC_RT5645
+ select SND_SOC_RT5682_I2C
+ select SND_SOC_RT5682S
+ select SND_SOC_TAS2781_COMLIB
+ select SND_SOC_TAS2781_FMWLIB
+ select SND_SOC_TAS2781_I2C
+ help
+ This adds support for ASoC machine driver for MediaTek MT8196
+ boards with the NAU8825 and other I2S audio codecs.
+ Select Y if you have such device.
+ If unsure select "N".
+
endmenu
diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
index 7cd67bce92e9..a6815a3c5988 100644
--- a/sound/soc/mediatek/Makefile
+++ b/sound/soc/mediatek/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_SND_SOC_MT8192) += mt8192/
obj-$(CONFIG_SND_SOC_MT8195) += mt8195/
obj-$(CONFIG_SND_SOC_MT8365) += mt8365/
obj-$(CONFIG_SND_SOC_MT8189) += mt8189/
+obj-$(CONFIG_SND_SOC_MT8196) += mt8196/
diff --git a/sound/soc/mediatek/common/mtk-afe-fe-dai.c b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
index 3809068f5620..2a20fa5dba49 100644
--- a/sound/soc/mediatek/common/mtk-afe-fe-dai.c
+++ b/sound/soc/mediatek/common/mtk-afe-fe-dai.c
@@ -292,28 +292,24 @@ int mtk_dynamic_irq_acquire(struct mtk_base_afe *afe)
{
int i;
- mutex_lock(&afe->irq_alloc_lock);
+ guard(mutex)(&afe->irq_alloc_lock);
for (i = 0; i < afe->irqs_size; ++i) {
if (afe->irqs[i].irq_occupyed == 0) {
afe->irqs[i].irq_occupyed = 1;
- mutex_unlock(&afe->irq_alloc_lock);
return i;
}
}
- mutex_unlock(&afe->irq_alloc_lock);
return afe->irqs_size;
}
EXPORT_SYMBOL_GPL(mtk_dynamic_irq_acquire);
int mtk_dynamic_irq_release(struct mtk_base_afe *afe, int irq_id)
{
- mutex_lock(&afe->irq_alloc_lock);
+ guard(mutex)(&afe->irq_alloc_lock);
if (irq_id >= 0 && irq_id < afe->irqs_size) {
afe->irqs[irq_id].irq_occupyed = 0;
- mutex_unlock(&afe->irq_alloc_lock);
return 0;
}
- mutex_unlock(&afe->irq_alloc_lock);
return -EINVAL;
}
EXPORT_SYMBOL_GPL(mtk_dynamic_irq_release);
diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.c b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
index f2b39fc9ec81..477284e12396 100644
--- a/sound/soc/mediatek/common/mtk-afe-platform-driver.c
+++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.c
@@ -87,29 +87,49 @@ snd_pcm_uframes_t mtk_afe_pcm_pointer(struct snd_soc_component *component,
const struct mtk_base_memif_data *memif_data = memif->data;
struct regmap *regmap = afe->regmap;
struct device *dev = afe->dev;
- int reg_ofs_base = memif_data->reg_ofs_base;
- int reg_ofs_cur = memif_data->reg_ofs_cur;
- unsigned int hw_ptr = 0, hw_base = 0;
- int ret, pcm_ptr_bytes;
-
- ret = regmap_read(regmap, reg_ofs_cur, &hw_ptr);
- if (ret || hw_ptr == 0) {
- dev_err(dev, "%s hw_ptr err\n", __func__);
- pcm_ptr_bytes = 0;
- goto POINTER_RETURN_FRAMES;
+ unsigned int hw_ptr_lower32 = 0, hw_ptr_upper32 = 0;
+ unsigned int hw_base_lower32 = 0, hw_base_upper32 = 0;
+ unsigned long long hw_ptr = 0, hw_base = 0;
+ int ret;
+ unsigned long long pcm_ptr_bytes = 0;
+
+ ret = regmap_read(regmap, memif_data->reg_ofs_cur, &hw_ptr_lower32);
+ if (ret) {
+ dev_err(dev, "%s hw_ptr_lower32 err\n", __func__);
+ return 0;
}
- ret = regmap_read(regmap, reg_ofs_base, &hw_base);
- if (ret || hw_base == 0) {
- dev_err(dev, "%s hw_ptr err\n", __func__);
- pcm_ptr_bytes = 0;
- goto POINTER_RETURN_FRAMES;
+ if (memif_data->reg_ofs_cur_msb) {
+ ret = regmap_read(regmap, memif_data->reg_ofs_cur_msb, &hw_ptr_upper32);
+ if (ret) {
+ dev_err(dev, "%s hw_ptr_upper32 err\n", __func__);
+ return 0;
+ }
}
- pcm_ptr_bytes = hw_ptr - hw_base;
+ ret = regmap_read(regmap, memif_data->reg_ofs_base, &hw_base_lower32);
+ if (ret) {
+ dev_err(dev, "%s hw_base_lower32 err\n", __func__);
+ return 0;
+ }
+ if (memif_data->reg_ofs_base_msb) {
+ ret = regmap_read(regmap, memif_data->reg_ofs_base_msb, &hw_base_upper32);
+ if (ret) {
+ dev_err(dev, "%s hw_base_upper32 err\n", __func__);
+ return 0;
+ }
+ }
+
+ hw_ptr = ((unsigned long long)hw_ptr_upper32 << 32) | hw_ptr_lower32;
+ hw_base = ((unsigned long long)hw_base_upper32 << 32) | hw_base_lower32;
+
+ if (!hw_ptr || !hw_base) {
+ dev_err(dev, "hw_ptr or hw_base = 0 err\n");
+ return 0;
+ }
-POINTER_RETURN_FRAMES:
- return bytes_to_frames(substream->runtime, pcm_ptr_bytes);
+ pcm_ptr_bytes = MTK_ALIGN_16BYTES(hw_ptr - hw_base);
+ return bytes_to_frames(substream->runtime, (ssize_t)pcm_ptr_bytes);
}
EXPORT_SYMBOL_GPL(mtk_afe_pcm_pointer);
diff --git a/sound/soc/mediatek/common/mtk-afe-platform-driver.h b/sound/soc/mediatek/common/mtk-afe-platform-driver.h
index fcc923b88f12..71070b26f8f8 100644
--- a/sound/soc/mediatek/common/mtk-afe-platform-driver.h
+++ b/sound/soc/mediatek/common/mtk-afe-platform-driver.h
@@ -12,6 +12,8 @@
#define AFE_PCM_NAME "mtk-afe-pcm"
extern const struct snd_soc_component_driver mtk_afe_pcm_platform;
+#define MTK_ALIGN_16BYTES(x) ((x) & GENMASK_ULL(39, 4))
+
struct mtk_base_afe;
struct snd_pcm;
struct snd_soc_component;
diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c
index 5e7e85b4c98a..85cfc602dfd3 100644
--- a/sound/soc/mediatek/common/mtk-btcvsd.c
+++ b/sound/soc/mediatek/common/mtk-btcvsd.c
@@ -319,7 +319,6 @@ static int btcvsd_tx_clean_buffer(struct mtk_btcvsd_snd *bt)
{
unsigned int i;
unsigned int num_valid_addr;
- unsigned long flags;
enum BT_SCO_BAND band = bt->band;
/* prepare encoded mute data */
@@ -330,7 +329,7 @@ static int btcvsd_tx_clean_buffer(struct mtk_btcvsd_snd *bt)
table_msbc_silence, SCO_PACKET_180);
/* write mute data to bt tx sram buffer */
- spin_lock_irqsave(&bt->tx_lock, flags);
+ guard(spinlock_irqsave)(&bt->tx_lock);
num_valid_addr = bt->tx->buffer_info.num_valid_addr;
dev_info(bt->dev, "%s(), band %d, num_valid_addr %u\n",
@@ -349,7 +348,6 @@ static int btcvsd_tx_clean_buffer(struct mtk_btcvsd_snd *bt)
bt->tx->buffer_info.packet_length,
bt->tx->buffer_info.packet_num);
}
- spin_unlock_irqrestore(&bt->tx_lock, flags);
return 0;
}
@@ -365,7 +363,6 @@ static int mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd *bt,
int pv;
u8 *src;
unsigned int packet_buf_ofs;
- unsigned long flags;
unsigned long connsys_addr_rx, ap_addr_rx;
connsys_addr_rx = *bt->bt_reg_pkt_r;
@@ -385,7 +382,7 @@ static int mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd *bt,
bt->rx->temp_packet_buf, packet_length,
packet_num);
- spin_lock_irqsave(&bt->rx_lock, flags);
+ guard(spinlock_irqsave)(&bt->rx_lock);
for (i = 0; i < blk_size; i++) {
packet_buf_ofs = (bt->rx->packet_w & SCO_RX_PACKET_MASK) *
bt->rx->packet_size;
@@ -403,7 +400,7 @@ static int mtk_btcvsd_read_from_bt(struct mtk_btcvsd_snd *bt,
SCO_CVSD_PACKET_VALID_SIZE);
bt->rx->packet_w++;
}
- spin_unlock_irqrestore(&bt->rx_lock, flags);
+
return 0;
}
@@ -414,7 +411,6 @@ static int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt,
unsigned int blk_size)
{
unsigned int i;
- unsigned long flags;
u8 *dst;
unsigned long connsys_addr_tx, ap_addr_tx;
bool new_ap_addr_tx = true;
@@ -430,17 +426,17 @@ static int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt,
return -EIO;
}
- spin_lock_irqsave(&bt->tx_lock, flags);
- for (i = 0; i < blk_size; i++) {
- memcpy(bt->tx->temp_packet_buf + (bt->tx->packet_size * i),
- (bt->tx_packet_buf +
- (bt->tx->packet_r % SCO_TX_PACKER_BUF_NUM) *
- bt->tx->packet_size),
- bt->tx->packet_size);
+ scoped_guard(spinlock_irqsave, &bt->tx_lock) {
+ for (i = 0; i < blk_size; i++) {
+ memcpy(bt->tx->temp_packet_buf + (bt->tx->packet_size * i),
+ (bt->tx_packet_buf +
+ (bt->tx->packet_r % SCO_TX_PACKER_BUF_NUM) *
+ bt->tx->packet_size),
+ bt->tx->packet_size);
- bt->tx->packet_r++;
+ bt->tx->packet_r++;
+ }
}
- spin_unlock_irqrestore(&bt->tx_lock, flags);
dst = (u8 *)ap_addr_tx;
@@ -462,11 +458,11 @@ static int mtk_btcvsd_write_to_bt(struct mtk_btcvsd_snd *bt,
if (new_ap_addr_tx) {
unsigned int next_idx;
- spin_lock_irqsave(&bt->tx_lock, flags);
- bt->tx->buffer_info.num_valid_addr++;
- next_idx = bt->tx->buffer_info.num_valid_addr - 1;
- bt->tx->buffer_info.bt_sram_addr[next_idx] = ap_addr_tx;
- spin_unlock_irqrestore(&bt->tx_lock, flags);
+ scoped_guard(spinlock_irqsave, &bt->tx_lock) {
+ bt->tx->buffer_info.num_valid_addr++;
+ next_idx = bt->tx->buffer_info.num_valid_addr - 1;
+ bt->tx->buffer_info.bt_sram_addr[next_idx] = ap_addr_tx;
+ }
dev_info(bt->dev, "%s(), new ap_addr_tx = 0x%lx, num_valid_addr %d\n",
__func__, ap_addr_tx,
bt->tx->buffer_info.num_valid_addr);
@@ -701,17 +697,16 @@ static ssize_t mtk_btcvsd_snd_read(struct mtk_btcvsd_snd *bt,
{
ssize_t read_size = 0, read_count = 0, cur_read_idx, cont;
unsigned long avail;
- unsigned long flags;
unsigned int packet_size = bt->rx->packet_size;
while (count) {
- spin_lock_irqsave(&bt->rx_lock, flags);
- /* available data in RX packet buffer */
- avail = (bt->rx->packet_w - bt->rx->packet_r) * packet_size;
+ scoped_guard(spinlock_irqsave, &bt->rx_lock) {
+ /* available data in RX packet buffer */
+ avail = (bt->rx->packet_w - bt->rx->packet_r) * packet_size;
- cur_read_idx = (bt->rx->packet_r & SCO_RX_PACKET_MASK) *
- packet_size;
- spin_unlock_irqrestore(&bt->rx_lock, flags);
+ cur_read_idx = (bt->rx->packet_r & SCO_RX_PACKET_MASK) *
+ packet_size;
+ }
if (!avail) {
int ret = wait_for_bt_irq(bt, bt->rx);
@@ -749,9 +744,8 @@ static ssize_t mtk_btcvsd_snd_read(struct mtk_btcvsd_snd *bt,
return -EFAULT;
}
- spin_lock_irqsave(&bt->rx_lock, flags);
- bt->rx->packet_r += read_size / packet_size;
- spin_unlock_irqrestore(&bt->rx_lock, flags);
+ scoped_guard(spinlock_irqsave, &bt->rx_lock)
+ bt->rx->packet_r += read_size / packet_size;
read_count += read_size;
count -= read_size;
@@ -778,7 +772,6 @@ static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt,
size_t count)
{
int written_size = count, avail, cur_write_idx, write_size, cont;
- unsigned long flags;
unsigned int packet_size = bt->tx->packet_size;
/*
@@ -794,14 +787,14 @@ static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt,
bt->tx->buf_data_equivalent_time *= 1000;
while (count) {
- spin_lock_irqsave(&bt->tx_lock, flags);
- /* free space of TX packet buffer */
- avail = bt->tx->buf_size -
- (bt->tx->packet_w - bt->tx->packet_r) * packet_size;
+ scoped_guard(spinlock_irqsave, &bt->tx_lock) {
+ /* free space of TX packet buffer */
+ avail = bt->tx->buf_size -
+ (bt->tx->packet_w - bt->tx->packet_r) * packet_size;
- cur_write_idx = (bt->tx->packet_w % SCO_TX_PACKER_BUF_NUM) *
- packet_size;
- spin_unlock_irqrestore(&bt->tx_lock, flags);
+ cur_write_idx = (bt->tx->packet_w % SCO_TX_PACKER_BUF_NUM) *
+ packet_size;
+ }
if (!avail) {
int ret = wait_for_bt_irq(bt, bt->tx);
@@ -838,9 +831,8 @@ static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt,
return -EFAULT;
}
- spin_lock_irqsave(&bt->tx_lock, flags);
- bt->tx->packet_w += write_size / packet_size;
- spin_unlock_irqrestore(&bt->tx_lock, flags);
+ scoped_guard(spinlock_irqsave, &bt->tx_lock)
+ bt->tx->packet_w += write_size / packet_size;
count -= write_size;
}
@@ -985,7 +977,6 @@ static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer(
int hw_packet_ptr;
int packet_diff;
spinlock_t *lock; /* spinlock for bt stream control */
- unsigned long flags;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
lock = &bt->tx_lock;
@@ -995,7 +986,7 @@ static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer(
bt_stream = bt->rx;
}
- spin_lock_irqsave(lock, flags);
+ guard(spinlock_irqsave)(lock);
hw_packet_ptr = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
bt->tx->packet_r : bt->rx->packet_w;
@@ -1018,8 +1009,6 @@ static snd_pcm_uframes_t mtk_pcm_btcvsd_pointer(
bt_stream->prev_frame = frame;
- spin_unlock_irqrestore(lock, flags);
-
return frame;
}
diff --git a/sound/soc/mediatek/common/mtk-dsp-sof-common.c b/sound/soc/mediatek/common/mtk-dsp-sof-common.c
index fd10616a08a0..17b9ea6be604 100644
--- a/sound/soc/mediatek/common/mtk-dsp-sof-common.c
+++ b/sound/soc/mediatek/common/mtk-dsp-sof-common.c
@@ -228,11 +228,10 @@ int mtk_sof_card_late_probe(struct snd_soc_card *card)
}
EXPORT_SYMBOL_GPL(mtk_sof_card_late_probe);
-int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
- const char *propname, struct snd_soc_dai_link *pre_dai_links,
- int pre_num_links)
+int mtk_sof_dailink_parse_of(struct device *dev, struct snd_soc_card *card,
+ const char *propname)
{
- struct device *dev = card->dev;
+ struct device_node *np = dev->of_node;
struct snd_soc_dai_link *parsed_dai_link;
const char *dai_name = NULL;
int i, j, ret, num_links, parsed_num_links = 0;
@@ -255,9 +254,9 @@ int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
return ret;
}
dev_dbg(dev, "ASoC: Property get dai_name:%s\n", dai_name);
- for (j = 0; j < pre_num_links; j++) {
- if (!strcmp(dai_name, pre_dai_links[j].name)) {
- memcpy(&parsed_dai_link[parsed_num_links++], &pre_dai_links[j],
+ for (j = 0; j < card->num_links; j++) {
+ if (!strcmp(dai_name, card->dai_link[j].name)) {
+ memcpy(&parsed_dai_link[parsed_num_links++], &card->dai_link[j],
sizeof(struct snd_soc_dai_link));
break;
}
diff --git a/sound/soc/mediatek/common/mtk-dsp-sof-common.h b/sound/soc/mediatek/common/mtk-dsp-sof-common.h
index 8784ee471132..1a0a47d64761 100644
--- a/sound/soc/mediatek/common/mtk-dsp-sof-common.h
+++ b/sound/soc/mediatek/common/mtk-dsp-sof-common.h
@@ -36,8 +36,7 @@ int mtk_sof_dai_link_fixup(struct snd_soc_pcm_runtime *rtd,
struct snd_pcm_hw_params *params);
int mtk_sof_card_probe(struct snd_soc_card *card);
int mtk_sof_card_late_probe(struct snd_soc_card *card);
-int mtk_sof_dailink_parse_of(struct snd_soc_card *card, struct device_node *np,
- const char *propname, struct snd_soc_dai_link *pre_dai_links,
- int pre_num_links);
+int mtk_sof_dailink_parse_of(struct device *dev, struct snd_soc_card *card,
+ const char *propname);
#endif
diff --git a/sound/soc/mediatek/common/mtk-soundcard-driver.c b/sound/soc/mediatek/common/mtk-soundcard-driver.c
index a2a30a87a359..2d39ff23f854 100644
--- a/sound/soc/mediatek/common/mtk-soundcard-driver.c
+++ b/sound/soc/mediatek/common/mtk-soundcard-driver.c
@@ -15,11 +15,10 @@
#include "mtk-soc-card.h"
#include "mtk-soundcard-driver.h"
-static int set_card_codec_info(struct snd_soc_card *card,
+static int set_card_codec_info(struct device *dev,
struct device_node *sub_node,
struct snd_soc_dai_link *dai_link)
{
- struct device *dev = card->dev;
struct device_node *codec_node;
int ret;
@@ -45,8 +44,7 @@ static int set_card_codec_info(struct snd_soc_card *card,
return 0;
}
-static int set_dailink_daifmt(struct snd_soc_card *card,
- struct device_node *sub_node,
+static int set_dailink_daifmt(struct device_node *sub_node,
struct snd_soc_dai_link *dai_link)
{
unsigned int daifmt;
@@ -107,11 +105,11 @@ int parse_dai_link_info(struct snd_soc_card *card)
if (i >= card->num_links)
return -EINVAL;
- ret = set_card_codec_info(card, sub_node, dai_link);
+ ret = set_card_codec_info(dev, sub_node, dai_link);
if (ret < 0)
return ret;
- ret = set_dailink_daifmt(card, sub_node, dai_link);
+ ret = set_dailink_daifmt(sub_node, dai_link);
if (ret < 0)
return ret;
}
@@ -275,9 +273,8 @@ int mtk_soundcard_common_probe(struct platform_device *pdev)
if (adsp_node) {
if (of_property_present(pdev->dev.of_node, "mediatek,dai-link")) {
- ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node,
- "mediatek,dai-link",
- card->dai_link, card->num_links);
+ ret = mtk_sof_dailink_parse_of(&pdev->dev, card,
+ "mediatek,dai-link");
if (ret) {
of_node_put(adsp_node);
of_node_put(platform_node);
@@ -289,11 +286,8 @@ int mtk_soundcard_common_probe(struct platform_device *pdev)
soc_card_data->sof_priv = pdata->sof_priv;
card->probe = mtk_sof_card_probe;
card->late_probe = mtk_sof_card_late_probe;
- if (!card->topology_shortname_created) {
- snprintf(card->topology_shortname, 32, "sof-%s", card->name);
- card->topology_shortname_created = true;
- }
- card->name = card->topology_shortname;
+
+ snd_soc_card_set_topology_name(card, "sof");
}
/*
diff --git a/sound/soc/mediatek/mt2701/Makefile b/sound/soc/mediatek/mt2701/Makefile
index 507fa26c3945..59623d3d3a03 100644
--- a/sound/soc/mediatek/mt2701/Makefile
+++ b/sound/soc/mediatek/mt2701/Makefile
@@ -5,4 +5,5 @@ obj-$(CONFIG_SND_SOC_MT2701) += snd-soc-mt2701-afe.o
# machine driver
obj-$(CONFIG_SND_SOC_MT2701_CS42448) += mt2701-cs42448.o
+obj-$(CONFIG_SND_SOC_MT2701_HDMI) += mt2701-hdmi.o
obj-$(CONFIG_SND_SOC_MT2701_WM8960) += mt2701-wm8960.o
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
index ae620890bb3a..d217f9320ad2 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c
@@ -25,6 +25,7 @@ static const char *const base_clks[] = {
int mt2701_init_clock(struct mtk_base_afe *afe)
{
struct mt2701_afe_private *afe_priv = afe->platform_priv;
+ int i2s_num;
int i;
for (i = 0; i < MT2701_BASE_CLK_NUM; i++) {
@@ -35,8 +36,9 @@ int mt2701_init_clock(struct mtk_base_afe *afe)
}
}
+ i2s_num = min(afe_priv->soc->i2s_num, MT2701_BASE_CLK_NUM);
/* Get I2S related clocks */
- for (i = 0; i < afe_priv->soc->i2s_num; i++) {
+ for (i = 0; i < i2s_num; i++) {
struct mt2701_i2s_path *i2s_path = &afe_priv->i2s_path[i];
struct clk *i2s_ck;
char name[13];
@@ -95,6 +97,28 @@ int mt2701_init_clock(struct mtk_base_afe *afe)
afe_priv->mrgif_ck = NULL;
}
+ /*
+ * Optional HDMI audio clocks. Platforms that do not wire up the
+ * HDMI output (e.g. MT2701 devkits using only the I2S BE DAIs)
+ * may omit these; in that case the HDMI BE DAI simply cannot be
+ * enabled, but the rest of the AFE still probes.
+ */
+ afe_priv->hadds2pll_ck = devm_clk_get_optional(afe->dev, "hadds2pll_294m");
+ if (IS_ERR(afe_priv->hadds2pll_ck))
+ return PTR_ERR(afe_priv->hadds2pll_ck);
+
+ afe_priv->audio_hdmi_ck = devm_clk_get_optional(afe->dev, "audio_hdmi_pd");
+ if (IS_ERR(afe_priv->audio_hdmi_ck))
+ return PTR_ERR(afe_priv->audio_hdmi_ck);
+
+ afe_priv->audio_spdf_ck = devm_clk_get_optional(afe->dev, "audio_spdf_pd");
+ if (IS_ERR(afe_priv->audio_spdf_ck))
+ return PTR_ERR(afe_priv->audio_spdf_ck);
+
+ afe_priv->audio_apll_ck = devm_clk_get_optional(afe->dev, "audio_apll_pd");
+ if (IS_ERR(afe_priv->audio_apll_ck))
+ return PTR_ERR(afe_priv->audio_apll_ck);
+
return 0;
}
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-common.h b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
index 32bef5e2a56d..c9477bc24ee9 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-common.h
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-common.h
@@ -33,6 +33,7 @@ enum {
MT2701_MEMIF_UL5,
MT2701_MEMIF_DLBT,
MT2701_MEMIF_ULBT,
+ MT2701_MEMIF_HDMI,
MT2701_MEMIF_NUM,
MT2701_IO_I2S = MT2701_MEMIF_NUM,
MT2701_IO_2ND_I2S,
@@ -41,6 +42,7 @@ enum {
MT2701_IO_5TH_I2S,
MT2701_IO_6TH_I2S,
MT2701_IO_MRG,
+ MT2701_IO_HDMI,
};
enum {
@@ -87,12 +89,16 @@ struct mt2701_soc_variants {
};
struct mt2701_afe_private {
- struct mt2701_i2s_path *i2s_path;
struct clk *base_ck[MT2701_BASE_CLK_NUM];
struct clk *mrgif_ck;
+ struct clk *hadds2pll_ck;
+ struct clk *audio_hdmi_ck;
+ struct clk *audio_spdf_ck;
+ struct clk *audio_apll_ck;
bool mrg_enable[MTK_STREAM_NUM];
const struct mt2701_soc_variants *soc;
+ struct mt2701_i2s_path i2s_path[];
};
#endif
diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
index fcae38135d93..d56b498e8c0c 100644
--- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
+++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c
@@ -13,6 +13,7 @@
#include <linux/mfd/syscon.h>
#include <linux/of.h>
#include <linux/pm_runtime.h>
+#include <sound/pcm_params.h>
#include "mt2701-afe-common.h"
#include "mt2701-afe-clock-ctrl.h"
@@ -60,6 +61,7 @@ static const struct mt2701_afe_rate mt2701_afe_i2s_rates[] = {
static const unsigned int mt2701_afe_backup_list[] = {
AUDIO_TOP_CON0,
+ AUDIO_TOP_CON3,
AUDIO_TOP_CON4,
AUDIO_TOP_CON5,
ASYS_TOP_CON,
@@ -77,6 +79,9 @@ static const unsigned int mt2701_afe_backup_list[] = {
AFE_CONN22,
AFE_DAC_CON0,
AFE_MEMIF_PBUF_SIZE,
+ AFE_HDMI_OUT_CON0,
+ AFE_HDMI_CONN0,
+ AFE_8CH_I2S_OUT_CON,
};
static int mt2701_dai_num_to_i2s(struct mtk_base_afe *afe, int num)
@@ -542,6 +547,220 @@ static const struct snd_soc_dai_ops mt2701_btmrg_ops = {
.hw_params = mt2701_btmrg_hw_params,
};
+/*
+ * HDMI BE DAI -- drives the on-SoC 8-channel I2S engine whose output
+ * feeds the HDMI transmitter audio port.
+ *
+ * The HDMI audio hardware path is:
+ * HDMI memif DMA (AFE_HDMI_OUT_*) -> interconnect mux (AFE_HDMI_CONN0)
+ * -> 8-channel I2S engine (AFE_8CH_I2S_OUT_CON) -> HDMI TX audio port
+ *
+ * The I2S3 clock tree provides the bit/master clocks; we set its
+ * mclk_rate to 128*fs (matching HDMI_AUD_MCLK_128FS) and let
+ * mt2701_mclk_configuration program the PLL/divider path.
+ */
+#define MT2701_HDMI_I2S_PATH 3
+
+static int mt2701_afe_hdmi_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
+ int ret;
+
+ if (!afe_priv->hadds2pll_ck || !afe_priv->audio_hdmi_ck) {
+ dev_err(afe->dev, "HDMI audio clocks not available\n");
+ return -ENODEV;
+ }
+
+ ret = clk_prepare_enable(afe_priv->hadds2pll_ck);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(afe_priv->audio_hdmi_ck);
+ if (ret)
+ goto err_hdmi;
+
+ if (afe_priv->audio_spdf_ck) {
+ ret = clk_prepare_enable(afe_priv->audio_spdf_ck);
+ if (ret)
+ goto err_spdf;
+ }
+
+ if (afe_priv->audio_apll_ck) {
+ ret = clk_prepare_enable(afe_priv->audio_apll_ck);
+ if (ret)
+ goto err_apll;
+ }
+
+ ret = mt2701_afe_enable_mclk(afe, MT2701_HDMI_I2S_PATH);
+ if (ret)
+ goto err_mclk;
+
+ return 0;
+
+err_mclk:
+ if (afe_priv->audio_apll_ck)
+ clk_disable_unprepare(afe_priv->audio_apll_ck);
+err_apll:
+ if (afe_priv->audio_spdf_ck)
+ clk_disable_unprepare(afe_priv->audio_spdf_ck);
+err_spdf:
+ clk_disable_unprepare(afe_priv->audio_hdmi_ck);
+err_hdmi:
+ clk_disable_unprepare(afe_priv->hadds2pll_ck);
+ return ret;
+}
+
+static void mt2701_afe_hdmi_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
+
+ mt2701_afe_disable_mclk(afe, MT2701_HDMI_I2S_PATH);
+ if (afe_priv->audio_apll_ck)
+ clk_disable_unprepare(afe_priv->audio_apll_ck);
+ if (afe_priv->audio_spdf_ck)
+ clk_disable_unprepare(afe_priv->audio_spdf_ck);
+ clk_disable_unprepare(afe_priv->audio_hdmi_ck);
+ clk_disable_unprepare(afe_priv->hadds2pll_ck);
+}
+
+static int mt2701_afe_hdmi_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
+ unsigned int channels = params_channels(params);
+ unsigned int rate = params_rate(params);
+ unsigned int divp1;
+ unsigned int val;
+ unsigned int i;
+ int ret;
+
+ /*
+ * Compute AUDIO_TOP_CON3.HDMI_BCK_DIV up front. The divider
+ * drives an internal reference for the HDMI transmitter's
+ * audio packet engine; it must scale with the sample rate so
+ * that the packet engine's timing matches the data flowing in
+ * from the AFE memif/I2S3 side. Empirically, with audpll_sel
+ * parented to hadds2pll_98m (98.304 MHz), the correct value at
+ * 48 kHz is div = 44 (i.e. (div+1) = 45), giving 1.0923 MHz.
+ * Scaling inversely with rate: (div + 1) = 45 * 48000 / rate.
+ * Integer rounding introduces small (<1%) errors at 32 kHz;
+ * 44.1 kHz is nearly exact via round-to-nearest. Reject rates
+ * that fall outside the 6-bit divider range before touching
+ * any hardware so no side effects are left behind on error.
+ */
+ divp1 = (45U * 48000U + rate / 2) / rate;
+ if (divp1 == 0 || divp1 > 64)
+ return -EINVAL;
+
+ /*
+ * Park the I2S3 clock tree at 128*fs -- this is the MCLK that
+ * the ASYS I2S3 engine uses to derive its BCK/LRCK. The engine
+ * outputs BCK = 64*fs (stereo, 32-bit word length).
+ */
+ afe_priv->i2s_path[MT2701_HDMI_I2S_PATH].mclk_rate = rate * 128;
+ ret = mt2701_mclk_configuration(afe, MT2701_HDMI_I2S_PATH);
+ if (ret)
+ return ret;
+
+ /* Program and start the ASYS I2S3 engine (FS, I2S mode, enable). */
+ mt2701_i2s_path_enable(afe,
+ &afe_priv->i2s_path[MT2701_HDMI_I2S_PATH],
+ SNDRV_PCM_STREAM_PLAYBACK, rate);
+
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON3,
+ AUDIO_TOP_CON3_HDMI_BCK_DIV_MASK,
+ AUDIO_TOP_CON3_HDMI_BCK_DIV(divp1 - 1));
+
+ /*
+ * HDMI output memif: set channel count and confirm 16-bit
+ * sample width. Both fields must be written together so that
+ * stale reset-default or prior-stream values in BIT_WIDTH
+ * cannot persist.
+ */
+ regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
+ AFE_HDMI_OUT_CON0_CH_NUM_MASK |
+ AFE_HDMI_OUT_CON0_BIT_WIDTH_MASK,
+ AFE_HDMI_OUT_CON0_CH_NUM(channels) |
+ AFE_HDMI_OUT_CON0_BIT_WIDTH_16);
+
+ /*
+ * Interconnect mux -- map DMA input slots to HDMI output slots.
+ * Each output takes a 3-bit field at shift (i*3). Swap the first
+ * two inputs so that the DMA's interleaved L/R pair lands on the
+ * correct HDMI L/R output slots. Remaining slots are identity.
+ */
+ val = (1 << 0) | (0 << 3); /* O20 <- I21, O21 <- I20 */
+ for (i = 2; i < 8; i++)
+ val |= ((i & 0x7) << (i * 3));
+ regmap_write(afe->regmap, AFE_HDMI_CONN0, val);
+
+ /*
+ * 8-channel I2S framing: standard I2S, 32-bit slots,
+ * LRCK/BCK inverted. The wire protocol is fixed.
+ */
+ regmap_update_bits(afe->regmap, AFE_8CH_I2S_OUT_CON,
+ AFE_8CH_I2S_OUT_CON_WLEN_MASK |
+ AFE_8CH_I2S_OUT_CON_I2S_DELAY |
+ AFE_8CH_I2S_OUT_CON_LRCK_INV |
+ AFE_8CH_I2S_OUT_CON_BCK_INV,
+ AFE_8CH_I2S_OUT_CON_WLEN_32BIT |
+ AFE_8CH_I2S_OUT_CON_I2S_DELAY |
+ AFE_8CH_I2S_OUT_CON_LRCK_INV |
+ AFE_8CH_I2S_OUT_CON_BCK_INV);
+ return 0;
+}
+
+static int mt2701_afe_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ /* Enable HDMI output memif. */
+ regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0x1);
+ /* Enable 8-channel I2S engine. */
+ regmap_update_bits(afe->regmap, AFE_8CH_I2S_OUT_CON,
+ AFE_8CH_I2S_OUT_CON_EN,
+ AFE_8CH_I2S_OUT_CON_EN);
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ regmap_update_bits(afe->regmap, AFE_8CH_I2S_OUT_CON,
+ AFE_8CH_I2S_OUT_CON_EN, 0);
+ regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0);
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int mt2701_afe_hdmi_hw_free(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt2701_afe_private *afe_priv = afe->platform_priv;
+
+ mt2701_afe_i2s_path_disable(afe,
+ &afe_priv->i2s_path[MT2701_HDMI_I2S_PATH],
+ SNDRV_PCM_STREAM_PLAYBACK);
+ return 0;
+}
+
+static const struct snd_soc_dai_ops mt2701_afe_hdmi_ops = {
+ .startup = mt2701_afe_hdmi_startup,
+ .shutdown = mt2701_afe_hdmi_shutdown,
+ .hw_params = mt2701_afe_hdmi_hw_params,
+ .hw_free = mt2701_afe_hdmi_hw_free,
+ .trigger = mt2701_afe_hdmi_trigger,
+};
+
static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
/* FE DAIs: memory intefaces to CPU */
{
@@ -628,6 +847,19 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
},
.ops = &mt2701_single_memif_dai_ops,
},
+ {
+ .name = "PCM_HDMI",
+ .id = MT2701_MEMIF_HDMI,
+ .playback = {
+ .stream_name = "HDMI Multich",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = (SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &mt2701_single_memif_dai_ops,
+ },
/* BE DAIs */
{
.name = "I2S0",
@@ -748,7 +980,20 @@ static struct snd_soc_dai_driver mt2701_afe_pcm_dais[] = {
},
.ops = &mt2701_btmrg_ops,
.symmetric_rate = 1,
- }
+ },
+ {
+ .name = "HDMI I2S",
+ .id = MT2701_IO_HDMI,
+ .playback = {
+ .stream_name = "HDMI 8CH I2S Playback",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = (SNDRV_PCM_RATE_44100 |
+ SNDRV_PCM_RATE_48000),
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+ .ops = &mt2701_afe_hdmi_ops,
+ },
};
static const struct snd_kcontrol_new mt2701_afe_o00_mix[] = {
@@ -927,6 +1172,14 @@ static const struct snd_soc_dapm_route mt2701_afe_pcm_routes[] = {
{"I16I17", "Multich I2S2 Out Switch", "DLM"},
{"I18I19", "Multich I2S3 Out Switch", "DLM"},
+ /*
+ * HDMI FE -> BE direct route. The HDMI memif has its own DMA
+ * path that feeds the 8-channel internal I2S straight into the
+ * HDMI transmitter; no mixer/interconnect selection is exposed
+ * to the user.
+ */
+ {"HDMI 8CH I2S Playback", NULL, "HDMI Multich"},
+
{ "I12", NULL, "I12I13" },
{ "I13", NULL, "I12I13" },
{ "I14", NULL, "I14I15" },
@@ -1207,6 +1460,35 @@ static const struct mtk_base_memif_data memif_data_array[MT2701_MEMIF_NUM] = {
.agent_disable_shift = 16,
.msb_reg = -1,
},
+ {
+ /*
+ * HDMI memif feeds the on-SoC 8-channel internal I2S that
+ * drives the HDMI transmitter audio port. Unlike the
+ * standard memifs, the enable bit, channel count and bit
+ * width all live in AFE_HDMI_OUT_CON0, so mono/fs/hd/agent
+ * fields are left at -1 and programmed from the BE DAI ops
+ * instead.
+ */
+ .name = "HDMI",
+ .id = MT2701_MEMIF_HDMI,
+ .reg_ofs_base = AFE_HDMI_OUT_BASE,
+ .reg_ofs_cur = AFE_HDMI_OUT_CUR,
+ .reg_ofs_end = AFE_HDMI_OUT_END,
+ .fs_reg = -1,
+ .fs_shift = -1,
+ .fs_maskbit = 0,
+ .mono_reg = -1,
+ .mono_shift = -1,
+ .enable_reg = AFE_HDMI_OUT_CON0,
+ .enable_shift = 0,
+ .hd_reg = -1,
+ .hd_shift = -1,
+ .hd_align_reg = -1,
+ .hd_align_mshift = 0,
+ .agent_disable_reg = -1,
+ .agent_disable_shift = 0,
+ .msb_reg = -1,
+ },
};
static const struct mtk_base_irq_data irq_data[MT2701_IRQ_ASYS_END] = {
@@ -1311,6 +1593,7 @@ static int mt2701_afe_runtime_resume(struct device *dev)
static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
{
+ const struct mt2701_soc_variants *soc;
struct mtk_base_afe *afe;
struct mt2701_afe_private *afe_priv;
struct device *dev;
@@ -1320,23 +1603,19 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev)
if (!afe)
return -ENOMEM;
- afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
- GFP_KERNEL);
- if (!afe->platform_priv)
+ soc = of_device_get_match_data(&pdev->dev);
+ afe_priv = devm_kzalloc(&pdev->dev,
+ struct_size(afe_priv, i2s_path, soc->i2s_num),
+ GFP_KERNEL);
+ if (!afe_priv)
return -ENOMEM;
- afe_priv = afe->platform_priv;
- afe_priv->soc = of_device_get_match_data(&pdev->dev);
+ afe_priv->soc = soc;
+
+ afe->platform_priv = afe_priv;
afe->dev = &pdev->dev;
dev = afe->dev;
- afe_priv->i2s_path = devm_kcalloc(dev,
- afe_priv->soc->i2s_num,
- sizeof(struct mt2701_i2s_path),
- GFP_KERNEL);
- if (!afe_priv->i2s_path)
- return -ENOMEM;
-
irq_id = platform_get_irq_byname(pdev, "asys");
if (irq_id < 0)
return irq_id;
diff --git a/sound/soc/mediatek/mt2701/mt2701-hdmi.c b/sound/soc/mediatek/mt2701/mt2701-hdmi.c
new file mode 100644
index 000000000000..a84907879c04
--- /dev/null
+++ b/sound/soc/mediatek/mt2701/mt2701-hdmi.c
@@ -0,0 +1,114 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mt2701-hdmi.c -- MT2701 HDMI ALSA SoC machine driver
+ *
+ * Copyright (c) 2026 Daniel Golle <daniel@makrotopia.org>
+ *
+ * Based on mt2701-cs42448.c
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <sound/soc.h>
+
+enum {
+ DAI_LINK_FE_HDMI_OUT,
+ DAI_LINK_BE_HDMI_I2S,
+};
+
+SND_SOC_DAILINK_DEFS(fe_hdmi_out,
+ DAILINK_COMP_ARRAY(COMP_CPU("PCM_HDMI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+SND_SOC_DAILINK_DEFS(be_hdmi_i2s,
+ DAILINK_COMP_ARRAY(COMP_CPU("HDMI I2S")),
+ DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "i2s-hifi")),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+static struct snd_soc_dai_link mt2701_hdmi_dai_links[] = {
+ [DAI_LINK_FE_HDMI_OUT] = {
+ .name = "HDMI Playback",
+ .stream_name = "HDMI Playback",
+ .trigger = { SND_SOC_DPCM_TRIGGER_POST,
+ SND_SOC_DPCM_TRIGGER_POST },
+ .dynamic = 1,
+ .playback_only = 1,
+ SND_SOC_DAILINK_REG(fe_hdmi_out),
+ },
+ [DAI_LINK_BE_HDMI_I2S] = {
+ .name = "HDMI BE",
+ .no_pcm = 1,
+ .playback_only = 1,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBC_CFC,
+ SND_SOC_DAILINK_REG(be_hdmi_i2s),
+ },
+};
+
+static struct snd_soc_card mt2701_hdmi_soc_card = {
+ .name = "mt2701-hdmi",
+ .owner = THIS_MODULE,
+ .dai_link = mt2701_hdmi_dai_links,
+ .num_links = ARRAY_SIZE(mt2701_hdmi_dai_links),
+};
+
+static int mt2701_hdmi_machine_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &mt2701_hdmi_soc_card;
+ struct device *dev = &pdev->dev;
+ struct device_node *platform_node;
+ struct device_node *codec_node;
+ struct snd_soc_dai_link *dai_link;
+ int ret;
+ int i;
+
+ platform_node = of_parse_phandle(dev->of_node, "mediatek,platform", 0);
+ if (!platform_node)
+ return dev_err_probe(dev, -EINVAL,
+ "Property 'mediatek,platform' missing\n");
+
+ for_each_card_prelinks(card, i, dai_link) {
+ if (dai_link->platforms->name)
+ continue;
+ dai_link->platforms->of_node = platform_node;
+ }
+
+ codec_node = of_parse_phandle(dev->of_node, "mediatek,audio-codec", 0);
+ if (!codec_node) {
+ of_node_put(platform_node);
+ return dev_err_probe(dev, -EINVAL,
+ "Property 'mediatek,audio-codec' missing\n");
+ }
+ mt2701_hdmi_dai_links[DAI_LINK_BE_HDMI_I2S].codecs->of_node = codec_node;
+
+ card->dev = dev;
+
+ ret = devm_snd_soc_register_card(dev, card);
+
+ of_node_put(platform_node);
+ of_node_put(codec_node);
+ return ret;
+}
+
+static const struct of_device_id mt2701_hdmi_machine_dt_match[] = {
+ { .compatible = "mediatek,mt2701-hdmi-audio" },
+ { .compatible = "mediatek,mt7623n-hdmi-audio" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mt2701_hdmi_machine_dt_match);
+
+static struct platform_driver mt2701_hdmi_machine = {
+ .driver = {
+ .name = "mt2701-hdmi",
+ .of_match_table = mt2701_hdmi_machine_dt_match,
+ },
+ .probe = mt2701_hdmi_machine_probe,
+};
+module_platform_driver(mt2701_hdmi_machine);
+
+MODULE_DESCRIPTION("MT2701 HDMI ALSA SoC machine driver");
+MODULE_AUTHOR("Daniel Golle <daniel@makrotopia.org>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mt2701-hdmi");
diff --git a/sound/soc/mediatek/mt2701/mt2701-reg.h b/sound/soc/mediatek/mt2701/mt2701-reg.h
index c84d14cdd7ae..ca914df02c96 100644
--- a/sound/soc/mediatek/mt2701/mt2701-reg.h
+++ b/sound/soc/mediatek/mt2701/mt2701-reg.h
@@ -10,10 +10,17 @@
#define _MT2701_REG_H_
#define AUDIO_TOP_CON0 0x0000
+#define AUDIO_TOP_CON3 0x000c
#define AUDIO_TOP_CON4 0x0010
#define AUDIO_TOP_CON5 0x0014
#define AFE_DAIBT_CON0 0x001c
#define AFE_MRGIF_CON 0x003c
+#define AFE_HDMI_OUT_CON0 0x0370
+#define AFE_HDMI_OUT_BASE 0x0374
+#define AFE_HDMI_OUT_CUR 0x0378
+#define AFE_HDMI_OUT_END 0x037c
+#define AFE_HDMI_CONN0 0x0390
+#define AFE_8CH_I2S_OUT_CON 0x0394
#define ASMI_TIMING_CON1 0x0100
#define ASMO_TIMING_CON1 0x0104
#define PWR1_ASM_CON1 0x0108
@@ -125,6 +132,28 @@
#define AFE_MEMIF_PBUF_SIZE_DLM_BYTE_MASK (0x3 << 12)
#define AFE_MEMIF_PBUF_SIZE_DLM_32BYTES (0x1 << 12)
+/* AUDIO_TOP_CON3 (0x000c) -- HDMI BCK divider */
+#define AUDIO_TOP_CON3_HDMI_BCK_DIV_MASK (0x3f << 8)
+#define AUDIO_TOP_CON3_HDMI_BCK_DIV(x) (((x) & 0x3f) << 8)
+
+/* AFE_HDMI_OUT_CON0 (0x0370) */
+#define AFE_HDMI_OUT_CON0_OUT_ON (0x1 << 0)
+#define AFE_HDMI_OUT_CON0_BIT_WIDTH_MASK (0x1 << 1)
+#define AFE_HDMI_OUT_CON0_BIT_WIDTH_16 (0x0 << 1)
+#define AFE_HDMI_OUT_CON0_BIT_WIDTH_32 (0x1 << 1)
+#define AFE_HDMI_OUT_CON0_CH_NUM_MASK (0xf << 4)
+#define AFE_HDMI_OUT_CON0_CH_NUM(x) (((x) & 0xf) << 4)
+
+/* AFE_8CH_I2S_OUT_CON (0x0394) -- on-SoC 8-channel I2S that feeds HDMI TX */
+#define AFE_8CH_I2S_OUT_CON_EN (0x1 << 0)
+#define AFE_8CH_I2S_OUT_CON_BCK_INV (0x1 << 1)
+#define AFE_8CH_I2S_OUT_CON_LRCK_INV (0x1 << 2)
+#define AFE_8CH_I2S_OUT_CON_I2S_DELAY (0x1 << 3)
+#define AFE_8CH_I2S_OUT_CON_WLEN_MASK (0x3 << 4)
+#define AFE_8CH_I2S_OUT_CON_WLEN_16BIT (0x1 << 4)
+#define AFE_8CH_I2S_OUT_CON_WLEN_24BIT (0x2 << 4)
+#define AFE_8CH_I2S_OUT_CON_WLEN_32BIT (0x3 << 4)
+
/* I2S in/out register bit control */
#define ASYS_I2S_CON_FS (0x1f << 8)
#define ASYS_I2S_CON_FS_SET(x) ((x) << 8)
diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
index c0fa623e0b17..69cadc91c97f 100644
--- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
+++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c
@@ -676,6 +676,7 @@ static const struct snd_soc_component_driver mt8173_afe_pcm_dai_component = {
.num_dapm_routes = ARRAY_SIZE(mt8173_afe_pcm_routes),
.suspend = mtk_afe_suspend,
.resume = mtk_afe_resume,
+ .debugfs_prefix = "pcm",
};
static const struct snd_soc_component_driver mt8173_afe_hdmi_dai_component = {
@@ -684,6 +685,7 @@ static const struct snd_soc_component_driver mt8173_afe_hdmi_dai_component = {
.num_dapm_routes = ARRAY_SIZE(mt8173_afe_hdmi_routes),
.suspend = mtk_afe_suspend,
.resume = mtk_afe_resume,
+ .debugfs_prefix = "hdmi",
};
static const char *aud_clks[MT8173_CLK_NUM] = {
@@ -1053,7 +1055,6 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev)
int irq_id;
struct mtk_base_afe *afe;
struct mt8173_afe_private *afe_priv;
- struct snd_soc_component *comp_pcm, *comp_hdmi;
struct device *dev = &pdev->dev;
ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(33));
@@ -1141,45 +1142,13 @@ static int mt8173_afe_pcm_dev_probe(struct platform_device *pdev)
if (ret)
goto err_pm_disable;
- comp_pcm = devm_kzalloc(dev, sizeof(*comp_pcm), GFP_KERNEL);
- if (!comp_pcm) {
- ret = -ENOMEM;
- goto err_pm_disable;
- }
-
- ret = snd_soc_component_initialize(comp_pcm,
- &mt8173_afe_pcm_dai_component,
- dev);
- if (ret)
- goto err_pm_disable;
-
-#ifdef CONFIG_DEBUG_FS
- comp_pcm->debugfs_prefix = "pcm";
-#endif
-
- ret = snd_soc_add_component(comp_pcm,
+ ret = snd_soc_register_component(dev, &mt8173_afe_pcm_dai_component,
mt8173_afe_pcm_dais,
ARRAY_SIZE(mt8173_afe_pcm_dais));
if (ret)
goto err_pm_disable;
- comp_hdmi = devm_kzalloc(dev, sizeof(*comp_hdmi), GFP_KERNEL);
- if (!comp_hdmi) {
- ret = -ENOMEM;
- goto err_cleanup_components;
- }
-
- ret = snd_soc_component_initialize(comp_hdmi,
- &mt8173_afe_hdmi_dai_component,
- dev);
- if (ret)
- goto err_cleanup_components;
-
-#ifdef CONFIG_DEBUG_FS
- comp_hdmi->debugfs_prefix = "hdmi";
-#endif
-
- ret = snd_soc_add_component(comp_hdmi,
+ ret = snd_soc_register_component(dev, &mt8173_afe_hdmi_dai_component,
mt8173_afe_hdmi_dais,
ARRAY_SIZE(mt8173_afe_hdmi_dais));
if (ret)
diff --git a/sound/soc/mediatek/mt8173/mt8173-max98090.c b/sound/soc/mediatek/mt8173/mt8173-max98090.c
index 49ebb67c818a..7533c6e4955b 100644
--- a/sound/soc/mediatek/mt8173/mt8173-max98090.c
+++ b/sound/soc/mediatek/mt8173/mt8173-max98090.c
@@ -1,3 +1,4 @@
+
// SPDX-License-Identifier: GPL-2.0
/*
* mt8173-max98090.c -- MT8173 MAX98090 ALSA SoC machine driver
@@ -9,7 +10,6 @@
#include <linux/module.h>
#include <sound/soc.h>
#include <sound/jack.h>
-#include "../../codecs/max98090.h"
static struct snd_soc_jack mt8173_max98090_jack;
@@ -78,7 +78,7 @@ static int mt8173_max98090_init(struct snd_soc_pcm_runtime *runtime)
return ret;
}
- return max98090_mic_detect(component, &mt8173_max98090_jack);
+ return snd_soc_component_set_jack(component, &mt8173_max98090_jack, NULL);
}
SND_SOC_DAILINK_DEFS(playback,
diff --git a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
index a7fef772760a..2634699534db 100644
--- a/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
+++ b/sound/soc/mediatek/mt8183/mt8183-afe-pcm.c
@@ -766,6 +766,11 @@ static const dai_register_cb dai_register_cbs[] = {
mt8183_dai_memif_register,
};
+static void mt8183_afe_release_reserved_mem(void *data)
+{
+ of_reserved_mem_device_release(data);
+}
+
static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
{
struct mtk_base_afe *afe;
@@ -794,6 +799,12 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
if (ret) {
dev_info(dev, "no reserved memory found, pre-allocating buffers instead\n");
afe->preallocate_buffers = true;
+ } else {
+ ret = devm_add_action_or_reset(dev,
+ mt8183_afe_release_reserved_mem,
+ dev);
+ if (ret)
+ return ret;
}
/* initial audio related clock */
@@ -833,17 +844,21 @@ static int mt8183_afe_pcm_dev_probe(struct platform_device *pdev)
/* enable clock for regcache get default value from hw */
afe_priv->pm_runtime_bypass_reg_ctl = true;
- pm_runtime_get_sync(dev);
-
- ret = regmap_reinit_cache(afe->regmap, &mt8183_afe_regmap_config);
+ ret = pm_runtime_resume_and_get(dev);
if (ret) {
- dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret);
+ afe_priv->pm_runtime_bypass_reg_ctl = false;
goto err_pm_disable;
}
+ ret = regmap_reinit_cache(afe->regmap, &mt8183_afe_regmap_config);
pm_runtime_put_sync(dev);
afe_priv->pm_runtime_bypass_reg_ctl = false;
+ if (ret) {
+ dev_err(dev, "regmap_reinit_cache fail, ret %d\n", ret);
+ goto err_pm_disable;
+ }
+
regcache_cache_only(afe->regmap, true);
regcache_mark_dirty(afe->regmap);
diff --git a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
index 9e86e7079718..aced8e7e920c 100644
--- a/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
+++ b/sound/soc/mediatek/mt8186/mt8186-afe-gpio.c
@@ -201,7 +201,7 @@ int mt8186_afe_gpio_request(struct device *dev, bool enable,
enum mt8186_afe_gpio sel;
int ret = -EINVAL;
- mutex_lock(&gpio_request_mutex);
+ guard(mutex)(&gpio_request_mutex);
switch (dai) {
case MT8186_DAI_ADDA:
@@ -209,7 +209,7 @@ int mt8186_afe_gpio_request(struct device *dev, bool enable,
ret = mt8186_afe_gpio_adda_ul(dev, enable);
else
ret = mt8186_afe_gpio_adda_dl(dev, enable);
- goto unlock;
+ return ret;
case MT8186_DAI_I2S_0:
sel = enable ? MT8186_AFE_GPIO_I2S0_ON : MT8186_AFE_GPIO_I2S0_OFF;
break;
@@ -230,13 +230,8 @@ int mt8186_afe_gpio_request(struct device *dev, bool enable,
break;
default:
dev_dbg(dev, "%s(), invalid dai %d\n", __func__, dai);
- goto unlock;
+ return ret;
}
- ret = mt8186_afe_gpio_select(dev, sel);
-
-unlock:
- mutex_unlock(&gpio_request_mutex);
-
- return ret;
+ return mt8186_afe_gpio_select(dev, sel);
}
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c
index e325d216c008..5a34d3f7fa58 100644
--- a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.c
@@ -39,7 +39,7 @@ int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd)
}
EXPORT_SYMBOL_GPL(mt8186_mt6366_init);
-int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card,
+int mt8186_mt6366_card_set_be_link(struct device *dev,
struct snd_soc_dai_link *link,
struct device_node *node,
char *link_name)
@@ -47,9 +47,9 @@ int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card,
int ret;
if (node && strcmp(link->name, link_name) == 0) {
- ret = snd_soc_of_get_dai_link_codecs(card->dev, node, link);
+ ret = snd_soc_of_get_dai_link_codecs(dev, node, link);
if (ret < 0)
- return dev_err_probe(card->dev, ret, "get dai link codecs fail\n");
+ return dev_err_probe(dev, ret, "get dai link codecs fail\n");
}
return 0;
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h
index 907d8f5e46b1..2094e786c623 100644
--- a/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366-common.h
@@ -10,7 +10,7 @@
#define _MT8186_MT6366_COMMON_H_
int mt8186_mt6366_init(struct snd_soc_pcm_runtime *rtd);
-int mt8186_mt6366_card_set_be_link(struct snd_soc_card *card,
+int mt8186_mt6366_card_set_be_link(struct device *dev,
struct snd_soc_dai_link *link,
struct device_node *node,
char *link_name);
diff --git a/sound/soc/mediatek/mt8186/mt8186-mt6366.c b/sound/soc/mediatek/mt8186/mt8186-mt6366.c
index 2c3033f305ea..22123b087c3c 100644
--- a/sound/soc/mediatek/mt8186/mt8186-mt6366.c
+++ b/sound/soc/mediatek/mt8186/mt8186-mt6366.c
@@ -1178,21 +1178,21 @@ static int mt8186_mt6366_legacy_probe(struct mtk_soc_card_data *soc_card_data)
}
for_each_card_prelinks(card, i, dai_link) {
- ret = mt8186_mt6366_card_set_be_link(card, dai_link, playback_codec, "I2S3");
+ ret = mt8186_mt6366_card_set_be_link(dev, dai_link, playback_codec, "I2S3");
if (ret) {
dev_err_probe(dev, ret, "%s set playback_codec fail\n",
dai_link->name);
break;
}
- ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S0");
+ ret = mt8186_mt6366_card_set_be_link(dev, dai_link, headset_codec, "I2S0");
if (ret) {
dev_err_probe(dev, ret, "%s set headset_codec fail\n",
dai_link->name);
break;
}
- ret = mt8186_mt6366_card_set_be_link(card, dai_link, headset_codec, "I2S1");
+ ret = mt8186_mt6366_card_set_be_link(dev, dai_link, headset_codec, "I2S1");
if (ret) {
dev_err_probe(dev, ret, "%s set headset_codec fail\n",
dai_link->name);
@@ -1211,18 +1211,18 @@ static int mt8186_mt6366_soc_card_probe(struct mtk_soc_card_data *soc_card_data,
struct snd_soc_card *card = card_data->card;
struct snd_soc_dai_link *dai_link;
struct mt8186_mt6366_rt1019_rt5682s_priv *mach_priv;
+ struct device *dev = card->dev;
int i, ret;
- mach_priv = devm_kzalloc(card->dev, sizeof(*mach_priv), GFP_KERNEL);
+ mach_priv = devm_kzalloc(dev, sizeof(*mach_priv), GFP_KERNEL);
if (!mach_priv)
return -ENOMEM;
soc_card_data->mach_priv = mach_priv;
- mach_priv->dmic_sel = devm_gpiod_get_optional(card->dev,
- "dmic", GPIOD_OUT_LOW);
+ mach_priv->dmic_sel = devm_gpiod_get_optional(dev, "dmic", GPIOD_OUT_LOW);
if (IS_ERR(mach_priv->dmic_sel))
- return dev_err_probe(card->dev, PTR_ERR(mach_priv->dmic_sel),
+ return dev_err_probe(dev, PTR_ERR(mach_priv->dmic_sel),
"DMIC gpio failed\n");
for_each_card_prelinks(card, i, dai_link) {
@@ -1250,9 +1250,9 @@ static int mt8186_mt6366_soc_card_probe(struct mtk_soc_card_data *soc_card_data,
return ret;
}
- ret = mt8186_afe_gpio_init(card->dev);
+ ret = mt8186_afe_gpio_init(dev);
if (ret)
- return dev_err_probe(card->dev, ret, "init AFE gpio error\n");
+ return dev_err_probe(dev, ret, "init AFE gpio error\n");
return 0;
}
diff --git a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c
index 7f411b857782..fc6cb3f0469e 100644
--- a/sound/soc/mediatek/mt8188/mt8188-afe-clk.c
+++ b/sound/soc/mediatek/mt8188/mt8188-afe-clk.c
@@ -301,7 +301,6 @@ static int mt8188_afe_disable_tuner_clk(struct mtk_base_afe *afe,
static int mt8188_afe_enable_apll_tuner(struct mtk_base_afe *afe, unsigned int id)
{
struct mt8188_afe_tuner_cfg *cfg = mt8188_afe_found_apll_tuner(id);
- unsigned long flags;
int ret;
if (!cfg)
@@ -315,8 +314,7 @@ static int mt8188_afe_enable_apll_tuner(struct mtk_base_afe *afe, unsigned int i
if (ret)
return ret;
- spin_lock_irqsave(&cfg->ctrl_lock, flags);
-
+ guard(spinlock_irqsave)(&cfg->ctrl_lock);
cfg->ref_cnt++;
if (cfg->ref_cnt == 1)
regmap_update_bits(afe->regmap,
@@ -324,32 +322,27 @@ static int mt8188_afe_enable_apll_tuner(struct mtk_base_afe *afe, unsigned int i
cfg->tuner_en_maskbit << cfg->tuner_en_shift,
BIT(cfg->tuner_en_shift));
- spin_unlock_irqrestore(&cfg->ctrl_lock, flags);
-
return 0;
}
static int mt8188_afe_disable_apll_tuner(struct mtk_base_afe *afe, unsigned int id)
{
struct mt8188_afe_tuner_cfg *cfg = mt8188_afe_found_apll_tuner(id);
- unsigned long flags;
int ret;
if (!cfg)
return -EINVAL;
- spin_lock_irqsave(&cfg->ctrl_lock, flags);
-
- cfg->ref_cnt--;
- if (cfg->ref_cnt == 0)
- regmap_update_bits(afe->regmap,
- cfg->tuner_en_reg,
- cfg->tuner_en_maskbit << cfg->tuner_en_shift,
- 0 << cfg->tuner_en_shift);
- else if (cfg->ref_cnt < 0)
- cfg->ref_cnt = 0;
-
- spin_unlock_irqrestore(&cfg->ctrl_lock, flags);
+ scoped_guard(spinlock_irqsave, &cfg->ctrl_lock) {
+ cfg->ref_cnt--;
+ if (cfg->ref_cnt == 0)
+ regmap_update_bits(afe->regmap,
+ cfg->tuner_en_reg,
+ cfg->tuner_en_maskbit << cfg->tuner_en_shift,
+ 0 << cfg->tuner_en_shift);
+ else if (cfg->ref_cnt < 0)
+ cfg->ref_cnt = 0;
+ }
ret = mt8188_afe_disable_tuner_clk(afe, id);
if (ret)
diff --git a/sound/soc/mediatek/mt8189/mt8189-afe-pcm.c b/sound/soc/mediatek/mt8189/mt8189-afe-pcm.c
index 24b0c78815f6..77cf2b604f6c 100644
--- a/sound/soc/mediatek/mt8189/mt8189-afe-pcm.c
+++ b/sound/soc/mediatek/mt8189/mt8189-afe-pcm.c
@@ -2351,9 +2351,13 @@ static int mt8189_afe_runtime_resume(struct device *dev)
static int mt8189_afe_component_probe(struct snd_soc_component *component)
{
struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ int ret;
/* enable clock for regcache get default value from hw */
- pm_runtime_get_sync(afe->dev);
+ ret = pm_runtime_resume_and_get(afe->dev);
+ if (ret)
+ return dev_err_probe(afe->dev, ret, "failed to resume device\n");
+
mtk_afe_add_sub_dai_control(component);
pm_runtime_put_sync(afe->dev);
@@ -2417,6 +2421,11 @@ static const struct reg_sequence mt8189_cg_patch[] = {
{ AUDIO_TOP_CON4, 0x361c },
};
+static void mt8189_afe_release_reserved_mem(void *data)
+{
+ of_reserved_mem_device_release(data);
+}
+
static int mt8189_afe_pcm_dev_probe(struct platform_device *pdev)
{
int ret, i;
@@ -2431,8 +2440,15 @@ static int mt8189_afe_pcm_dev_probe(struct platform_device *pdev)
return ret;
ret = of_reserved_mem_device_init(dev);
- if (ret)
+ if (ret) {
dev_warn(dev, "failed to assign memory region: %d\n", ret);
+ } else {
+ ret = devm_add_action_or_reset(dev,
+ mt8189_afe_release_reserved_mem,
+ dev);
+ if (ret)
+ return ret;
+ }
afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL);
if (!afe)
@@ -2533,18 +2549,22 @@ static int mt8189_afe_pcm_dev_probe(struct platform_device *pdev)
dev_pm_syscore_device(dev, true);
/* enable clock for regcache get default value from hw */
- pm_runtime_get_sync(dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to resume device\n");
afe->regmap = devm_regmap_init_mmio(dev, afe->base_addr,
&mt8189_afe_regmap_config);
- if (IS_ERR(afe->regmap))
- return PTR_ERR(afe->regmap);
+ if (IS_ERR(afe->regmap)) {
+ ret = PTR_ERR(afe->regmap);
+ goto err_pm_put;
+ }
ret = regmap_register_patch(afe->regmap, mt8189_cg_patch,
ARRAY_SIZE(mt8189_cg_patch));
if (ret < 0) {
dev_err(dev, "Failed to apply cg patch\n");
- goto err_pm_disable;
+ goto err_pm_put;
}
regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg);
@@ -2563,12 +2583,12 @@ static int mt8189_afe_pcm_dev_probe(struct platform_device *pdev)
afe->num_dai_drivers);
if (ret) {
dev_err(dev, "afe component err: %d\n", ret);
- goto err_pm_disable;
+ return ret;
}
return 0;
-err_pm_disable:
+err_pm_put:
pm_runtime_put_sync(dev);
return ret;
}
@@ -2578,14 +2598,12 @@ static void mt8189_afe_pcm_dev_remove(struct platform_device *pdev)
struct mtk_base_afe *afe = platform_get_drvdata(pdev);
struct device *dev = &pdev->dev;
- pm_runtime_put_sync(dev);
if (!pm_runtime_status_suspended(dev))
mt8189_afe_runtime_suspend(dev);
mt8189_afe_disable_main_clock(afe);
/* disable afe clock */
mt8189_afe_disable_reg_rw_clk(afe);
- of_reserved_mem_device_release(dev);
}
static const struct of_device_id mt8189_afe_pcm_dt_match[] = {
diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-gpio.c b/sound/soc/mediatek/mt8192/mt8192-afe-gpio.c
index de5e1deaa167..b993ca2dbd7c 100644
--- a/sound/soc/mediatek/mt8192/mt8192-afe-gpio.c
+++ b/sound/soc/mediatek/mt8192/mt8192-afe-gpio.c
@@ -208,7 +208,7 @@ static int mt8192_afe_gpio_adda_ch34_ul(struct device *dev, bool enable)
int mt8192_afe_gpio_request(struct device *dev, bool enable,
int dai, int uplink)
{
- mutex_lock(&gpio_request_mutex);
+ guard(mutex)(&gpio_request_mutex);
switch (dai) {
case MT8192_DAI_ADDA:
if (uplink)
@@ -296,11 +296,9 @@ int mt8192_afe_gpio_request(struct device *dev, bool enable,
}
break;
default:
- mutex_unlock(&gpio_request_mutex);
dev_warn(dev, "%s(), invalid dai %d\n", __func__, dai);
return -EINVAL;
}
- mutex_unlock(&gpio_request_mutex);
return 0;
}
diff --git a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
index 3d32fe46118e..db0ae44a86af 100644
--- a/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
+++ b/sound/soc/mediatek/mt8192/mt8192-afe-pcm.c
@@ -2155,6 +2155,11 @@ static const dai_register_cb dai_register_cbs[] = {
mt8192_dai_memif_register,
};
+static void mt8192_afe_release_reserved_mem(void *data)
+{
+ of_reserved_mem_device_release(data);
+}
+
static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
{
struct mtk_base_afe *afe;
@@ -2184,6 +2189,10 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
if (ret) {
dev_info(dev, "no reserved memory found, pre-allocating buffers instead\n");
afe->preallocate_buffers = true;
+ } else {
+ ret = devm_add_action_or_reset(dev, mt8192_afe_release_reserved_mem, dev);
+ if (ret)
+ return ret;
}
/* init audio related clock */
@@ -2218,15 +2227,19 @@ static int mt8192_afe_pcm_dev_probe(struct platform_device *pdev)
/* enable clock for regcache get default value from hw */
afe_priv->pm_runtime_bypass_reg_ctl = true;
- pm_runtime_get_sync(dev);
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret) {
+ afe_priv->pm_runtime_bypass_reg_ctl = false;
+ return dev_err_probe(dev, ret, "failed to resume device\n");
+ }
ret = regmap_reinit_cache(afe->regmap, &mt8192_afe_regmap_config);
- if (ret)
- return dev_err_probe(dev, ret, "regmap_reinit_cache fail\n");
-
pm_runtime_put_sync(dev);
afe_priv->pm_runtime_bypass_reg_ctl = false;
+ if (ret)
+ return dev_err_probe(dev, ret, "regmap_reinit_cache fail\n");
+
regcache_cache_only(afe->regmap, true);
regcache_mark_dirty(afe->regmap);
diff --git a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
index f35318ae0739..618d8400913a 100644
--- a/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
+++ b/sound/soc/mediatek/mt8195/mt8195-afe-clk.c
@@ -283,7 +283,6 @@ static int mt8195_afe_enable_apll_tuner(struct mtk_base_afe *afe,
unsigned int id)
{
struct mt8195_afe_tuner_cfg *cfg = mt8195_afe_found_apll_tuner(id);
- unsigned long flags;
int ret;
if (!cfg)
@@ -297,16 +296,14 @@ static int mt8195_afe_enable_apll_tuner(struct mtk_base_afe *afe,
if (ret)
return ret;
- spin_lock_irqsave(&cfg->ctrl_lock, flags);
-
- cfg->ref_cnt++;
- if (cfg->ref_cnt == 1)
- regmap_update_bits(afe->regmap,
- cfg->tuner_en_reg,
- cfg->tuner_en_maskbit << cfg->tuner_en_shift,
- 1 << cfg->tuner_en_shift);
-
- spin_unlock_irqrestore(&cfg->ctrl_lock, flags);
+ scoped_guard(spinlock_irqsave, &cfg->ctrl_lock) {
+ cfg->ref_cnt++;
+ if (cfg->ref_cnt == 1)
+ regmap_update_bits(afe->regmap,
+ cfg->tuner_en_reg,
+ cfg->tuner_en_maskbit << cfg->tuner_en_shift,
+ 1 << cfg->tuner_en_shift);
+ }
return 0;
}
@@ -315,24 +312,21 @@ static int mt8195_afe_disable_apll_tuner(struct mtk_base_afe *afe,
unsigned int id)
{
struct mt8195_afe_tuner_cfg *cfg = mt8195_afe_found_apll_tuner(id);
- unsigned long flags;
int ret;
if (!cfg)
return -EINVAL;
- spin_lock_irqsave(&cfg->ctrl_lock, flags);
-
- cfg->ref_cnt--;
- if (cfg->ref_cnt == 0)
- regmap_update_bits(afe->regmap,
- cfg->tuner_en_reg,
- cfg->tuner_en_maskbit << cfg->tuner_en_shift,
- 0 << cfg->tuner_en_shift);
- else if (cfg->ref_cnt < 0)
- cfg->ref_cnt = 0;
-
- spin_unlock_irqrestore(&cfg->ctrl_lock, flags);
+ scoped_guard(spinlock_irqsave, &cfg->ctrl_lock) {
+ cfg->ref_cnt--;
+ if (cfg->ref_cnt == 0)
+ regmap_update_bits(afe->regmap,
+ cfg->tuner_en_reg,
+ cfg->tuner_en_maskbit << cfg->tuner_en_shift,
+ 0 << cfg->tuner_en_shift);
+ else if (cfg->ref_cnt < 0)
+ cfg->ref_cnt = 0;
+ }
ret = mt8195_afe_disable_tuner_clk(afe, id);
if (ret)
diff --git a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
index 5dcc8ed26e00..1a20adb2cbf5 100644
--- a/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
+++ b/sound/soc/mediatek/mt8195/mt8195-dai-etdm.c
@@ -1318,24 +1318,22 @@ static int mt8195_afe_enable_etdm(struct mtk_base_afe *afe, int dai_id)
struct etdm_con_reg etdm_reg;
struct mt8195_afe_private *afe_priv = afe->platform_priv;
struct mtk_dai_etdm_priv *etdm_data;
- unsigned long flags;
if (!mt8195_afe_etdm_is_valid(dai_id))
return -EINVAL;
etdm_data = afe_priv->dai_priv[dai_id];
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock);
etdm_data->en_ref_cnt++;
if (etdm_data->en_ref_cnt == 1) {
ret = get_etdm_reg(dai_id, &etdm_reg);
if (ret < 0)
- goto out;
+ return ret;
regmap_update_bits(afe->regmap, etdm_reg.con0,
ETDM_CON0_EN, ETDM_CON0_EN);
}
-out:
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+
return ret;
}
@@ -1345,26 +1343,24 @@ static int mt8195_afe_disable_etdm(struct mtk_base_afe *afe, int dai_id)
struct etdm_con_reg etdm_reg;
struct mt8195_afe_private *afe_priv = afe->platform_priv;
struct mtk_dai_etdm_priv *etdm_data;
- unsigned long flags;
if (!mt8195_afe_etdm_is_valid(dai_id))
return -EINVAL;
etdm_data = afe_priv->dai_priv[dai_id];
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock);
if (etdm_data->en_ref_cnt > 0) {
etdm_data->en_ref_cnt--;
if (etdm_data->en_ref_cnt == 0) {
ret = get_etdm_reg(dai_id, &etdm_reg);
if (ret < 0)
- goto out;
+ return ret;
regmap_update_bits(afe->regmap, etdm_reg.con0,
ETDM_CON0_EN, 0);
}
}
-out:
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
+
return ret;
}
diff --git a/sound/soc/mediatek/mt8196/Makefile b/sound/soc/mediatek/mt8196/Makefile
new file mode 100644
index 000000000000..91de200071d7
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/Makefile
@@ -0,0 +1,14 @@
+# SPDX-License-Identifier: GPL-2.0
+
+# platform driver
+snd-soc-mt8196-afe-objs += \
+ mt8196-afe-pcm.o \
+ mt8196-afe-clk.o \
+ mt8196-dai-adda.o \
+ mt8196-dai-i2s.o \
+ mt8196-dai-tdm.o
+
+obj-$(CONFIG_SND_SOC_MT8196) += snd-soc-mt8196-afe.o
+
+# machine driver
+obj-$(CONFIG_SND_SOC_MT8196_NAU8825) += mt8196-nau8825.o
diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-clk.c b/sound/soc/mediatek/mt8196/mt8196-afe-clk.c
new file mode 100644
index 000000000000..286e39f53ae0
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-clk.c
@@ -0,0 +1,581 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mt8196-afe-clk.c -- Mediatek 8196 afe clock ctrl
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#include <linux/clk.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "mt8196-afe-clk.h"
+#include "mt8196-afe-common.h"
+
+static const char *aud_clks[MT8196_CLK_NUM] = {
+ /* vlp clk */
+ [MT8196_CLK_VLP_MUX_AUDIOINTBUS] = "top_aud_intbus",
+ [MT8196_CLK_VLP_MUX_AUD_ENG1] = "top_aud_eng1",
+ [MT8196_CLK_VLP_MUX_AUD_ENG2] = "top_aud_eng2",
+ [MT8196_CLK_VLP_MUX_AUDIO_H] = "top_aud_h",
+ /* pll */
+ [MT8196_CLK_TOP_APLL1_CK] = "apll1",
+ [MT8196_CLK_TOP_APLL2_CK] = "apll2",
+ /* divider */
+ [MT8196_CLK_TOP_APLL12_DIV_I2SIN0] = "apll12_div_i2sin0",
+ [MT8196_CLK_TOP_APLL12_DIV_I2SIN1] = "apll12_div_i2sin1",
+ [MT8196_CLK_TOP_APLL12_DIV_FMI2S] = "apll12_div_fmi2s",
+ [MT8196_CLK_TOP_APLL12_DIV_TDMOUT_M] = "apll12_div_tdmout_m",
+ [MT8196_CLK_TOP_APLL12_DIV_TDMOUT_B] = "apll12_div_tdmout_b",
+ /* mux */
+ [MT8196_CLK_TOP_ADSP_SEL] = "top_adsp",
+};
+
+int mt8196_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+ int ret;
+
+ ret = clk_prepare_enable(clk);
+ if (ret) {
+ dev_err(afe->dev, "failed to enable clk\n");
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(mt8196_afe_enable_clk);
+
+void mt8196_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk)
+{
+ if (clk)
+ clk_disable_unprepare(clk);
+ else
+ dev_err(afe->dev, "NULL clk\n");
+}
+EXPORT_SYMBOL_GPL(mt8196_afe_disable_clk);
+
+static int mt8196_afe_set_clk_rate(struct mtk_base_afe *afe, struct clk *clk,
+ unsigned int rate)
+{
+ int ret;
+
+ if (clk) {
+ ret = clk_set_rate(clk, rate);
+ if (ret) {
+ dev_err(afe->dev, "failed to set clk rate\n");
+ return ret;
+ }
+ }
+
+ return 0;
+}
+
+static unsigned int get_top_cg_reg(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8196_AUDIO_26M_EN_ON:
+ case MT8196_AUDIO_F3P25M_EN_ON:
+ case MT8196_AUDIO_APLL1_EN_ON:
+ case MT8196_AUDIO_APLL2_EN_ON:
+ return AUDIO_ENGEN_CON0;
+ case MT8196_CG_AUDIO_HOPPING_CK:
+ case MT8196_CG_AUDIO_F26M_CK:
+ case MT8196_CG_APLL1_CK:
+ case MT8196_CG_APLL2_CK:
+ case MT8196_PDN_APLL_TUNER2:
+ case MT8196_PDN_APLL_TUNER1:
+ return AUDIO_TOP_CON4;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_top_cg_mask(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8196_AUDIO_26M_EN_ON:
+ return AUDIO_26M_EN_ON_MASK_SFT;
+ case MT8196_AUDIO_F3P25M_EN_ON:
+ return AUDIO_F3P25M_EN_ON_MASK_SFT;
+ case MT8196_AUDIO_APLL1_EN_ON:
+ return AUDIO_APLL1_EN_ON_MASK_SFT;
+ case MT8196_AUDIO_APLL2_EN_ON:
+ return AUDIO_APLL2_EN_ON_MASK_SFT;
+ case MT8196_CG_AUDIO_HOPPING_CK:
+ return CG_AUDIO_HOPPING_CK_MASK_SFT;
+ case MT8196_CG_AUDIO_F26M_CK:
+ return CG_AUDIO_F26M_CK_MASK_SFT;
+ case MT8196_CG_APLL1_CK:
+ return CG_APLL1_CK_MASK_SFT;
+ case MT8196_CG_APLL2_CK:
+ return CG_APLL2_CK_MASK_SFT;
+ case MT8196_PDN_APLL_TUNER2:
+ return PDN_APLL_TUNER2_MASK_SFT;
+ case MT8196_PDN_APLL_TUNER1:
+ return PDN_APLL_TUNER1_MASK_SFT;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_top_cg_on_val(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8196_AUDIO_26M_EN_ON:
+ case MT8196_AUDIO_F3P25M_EN_ON:
+ case MT8196_AUDIO_APLL1_EN_ON:
+ case MT8196_AUDIO_APLL2_EN_ON:
+ return get_top_cg_mask(cg_type);
+ case MT8196_CG_AUDIO_HOPPING_CK:
+ case MT8196_CG_AUDIO_F26M_CK:
+ case MT8196_CG_APLL1_CK:
+ case MT8196_CG_APLL2_CK:
+ case MT8196_PDN_APLL_TUNER2:
+ case MT8196_PDN_APLL_TUNER1:
+ return 0;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_top_cg_off_val(unsigned int cg_type)
+{
+ switch (cg_type) {
+ case MT8196_AUDIO_26M_EN_ON:
+ case MT8196_AUDIO_F3P25M_EN_ON:
+ case MT8196_AUDIO_APLL1_EN_ON:
+ case MT8196_AUDIO_APLL2_EN_ON:
+ return 0;
+ case MT8196_CG_AUDIO_HOPPING_CK:
+ case MT8196_CG_AUDIO_F26M_CK:
+ case MT8196_CG_APLL1_CK:
+ case MT8196_CG_APLL2_CK:
+ case MT8196_PDN_APLL_TUNER2:
+ case MT8196_PDN_APLL_TUNER1:
+ return get_top_cg_mask(cg_type);
+ default:
+ return get_top_cg_mask(cg_type);
+ }
+}
+
+static int mt8196_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+ int ret;
+ unsigned int reg = get_top_cg_reg(cg_type);
+ unsigned int mask = get_top_cg_mask(cg_type);
+ unsigned int val = get_top_cg_on_val(cg_type);
+
+ if (!afe->regmap) {
+ dev_err(afe->dev, "afe regmap is null !!!\n");
+ return 0;
+ }
+
+ dev_dbg(afe->dev, "reg: 0x%x, mask: 0x%x, val: 0x%x\n", reg, mask, val);
+
+ ret = regmap_update_bits(afe->regmap, reg, mask, val);
+ if (ret)
+ dev_err(afe->dev, "regmap_update_bits failed: %d\n", ret);
+
+ return ret;
+}
+
+static int mt8196_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
+{
+ int ret;
+ unsigned int reg = get_top_cg_reg(cg_type);
+ unsigned int mask = get_top_cg_mask(cg_type);
+ unsigned int val = get_top_cg_off_val(cg_type);
+
+ if (!afe->regmap) {
+ dev_err(afe->dev, "afe regmap is null !!!\n");
+ return 0;
+ }
+
+ dev_dbg(afe->dev, "reg: 0x%x, mask: 0x%x, val: 0x%x\n", reg, mask, val);
+
+ ret = regmap_update_bits(afe->regmap, reg, mask, val);
+ if (ret)
+ dev_err(afe->dev, "regmap_update_bits failed: %d\n", ret);
+
+ return ret;
+}
+
+static int apll1_mux_setting(struct mtk_base_afe *afe, bool enable)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int apll_rate;
+ int ret;
+
+ dev_dbg(afe->dev, "enable: %d\n", enable);
+
+ if (enable) {
+ apll_rate = mt8196_get_apll_rate(afe, MT8196_APLL1);
+
+ /* 180.6336 / 4 = 45.1584MHz */
+ ret = mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG1]);
+ if (ret)
+ return ret;
+
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG1],
+ MT8196_AUD_ENG1_CLK);
+ if (ret)
+ return ret;
+
+ ret = mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]);
+ if (ret)
+ return ret;
+
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H],
+ apll_rate);
+ if (ret)
+ return ret;
+ } else {
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG1],
+ MT8196_AFE_26M);
+ if (ret)
+ return ret;
+
+ mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG1]);
+
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H],
+ MT8196_AFE_26M);
+ if (ret)
+ return ret;
+
+ mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]);
+ }
+
+ return 0;
+}
+
+static int apll2_mux_setting(struct mtk_base_afe *afe, bool enable)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int apll_rate;
+ int ret;
+
+ dev_dbg(afe->dev, "enable: %d\n", enable);
+
+ if (enable) {
+ apll_rate = mt8196_get_apll_rate(afe, MT8196_APLL2);
+
+ /* 196.608 / 4 = 49.152MHz */
+ ret = mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG2]);
+ if (ret)
+ return ret;
+
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG2],
+ MT8196_AUD_ENG2_CLK);
+ if (ret)
+ return ret;
+
+ ret = mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]);
+ if (ret)
+ return ret;
+
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H],
+ apll_rate);
+ if (ret)
+ return ret;
+ } else {
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG2],
+ MT8196_AFE_26M);
+ if (ret)
+ return ret;
+
+ mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUD_ENG2]);
+
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H],
+ MT8196_AFE_26M);
+ if (ret)
+ return ret;
+
+ mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]);
+ }
+
+ return 0;
+}
+
+int mt8196_apll1_enable(struct mtk_base_afe *afe)
+{
+ int ret;
+
+ /* setting for APLL */
+ apll1_mux_setting(afe, true);
+
+ ret = mt8196_afe_enable_top_cg(afe, MT8196_CG_APLL1_CK);
+ if (ret)
+ goto err_clk_apll1;
+
+ ret = mt8196_afe_enable_top_cg(afe, MT8196_PDN_APLL_TUNER1);
+ if (ret)
+ goto err_clk_apll1_tuner;
+
+ /* sel 44.1kHz:1, apll_div:7, upper bound:3 */
+ regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
+ XTAL_EN_128FS_SEL_MASK_SFT | APLL_DIV_MASK_SFT | UPPER_BOUND_MASK_SFT,
+ (0x1 << XTAL_EN_128FS_SEL_SFT) | (7 << APLL_DIV_SFT) |
+ (3 << UPPER_BOUND_SFT));
+
+ /* apll1 freq tuner enable */
+ regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
+ FREQ_TUNER_EN_MASK_SFT,
+ 0x1 << FREQ_TUNER_EN_SFT);
+
+ /* audio apll1 on */
+ mt8196_afe_enable_top_cg(afe, MT8196_AUDIO_APLL1_EN_ON);
+
+ return 0;
+
+err_clk_apll1_tuner:
+ mt8196_afe_disable_top_cg(afe, MT8196_PDN_APLL_TUNER1);
+err_clk_apll1:
+ mt8196_afe_disable_top_cg(afe, MT8196_CG_APLL1_CK);
+ return ret;
+}
+
+void mt8196_apll1_disable(struct mtk_base_afe *afe)
+{
+ /* audio apll1 off */
+ mt8196_afe_disable_top_cg(afe, MT8196_AUDIO_APLL1_EN_ON);
+
+ /* apll1 freq tuner disable */
+ regmap_update_bits(afe->regmap, AFE_APLL1_TUNER_CFG,
+ FREQ_TUNER_EN_MASK_SFT,
+ 0x0);
+
+ mt8196_afe_disable_top_cg(afe, MT8196_PDN_APLL_TUNER1);
+ mt8196_afe_disable_top_cg(afe, MT8196_CG_APLL1_CK);
+ apll1_mux_setting(afe, false);
+}
+
+int mt8196_apll2_enable(struct mtk_base_afe *afe)
+{
+ int ret;
+
+ /* setting for APLL */
+ apll2_mux_setting(afe, true);
+
+ ret = mt8196_afe_enable_top_cg(afe, MT8196_CG_APLL2_CK);
+ if (ret)
+ goto err_clk_apll2;
+
+ ret = mt8196_afe_enable_top_cg(afe, MT8196_PDN_APLL_TUNER2);
+ if (ret)
+ goto err_clk_apll2_tuner;
+
+ /* sel 48kHz: 2, apll_div: 7, upper bound: 3*/
+ regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
+ XTAL_EN_128FS_SEL_MASK_SFT | APLL_DIV_MASK_SFT | UPPER_BOUND_MASK_SFT,
+ (0x2 << XTAL_EN_128FS_SEL_SFT) | (7 << APLL_DIV_SFT) |
+ (3 << UPPER_BOUND_SFT));
+
+ /* apll2 freq tuner enable */
+ regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
+ FREQ_TUNER_EN_MASK_SFT,
+ 0x1 << FREQ_TUNER_EN_SFT);
+
+ /* audio apll2 on */
+ mt8196_afe_enable_top_cg(afe, MT8196_AUDIO_APLL2_EN_ON);
+ return 0;
+
+err_clk_apll2_tuner:
+ mt8196_afe_disable_top_cg(afe, MT8196_PDN_APLL_TUNER2);
+err_clk_apll2:
+ mt8196_afe_disable_top_cg(afe, MT8196_CG_APLL2_CK);
+ return 0;
+}
+
+void mt8196_apll2_disable(struct mtk_base_afe *afe)
+{
+ /* audio apll2 off */
+ mt8196_afe_disable_top_cg(afe, MT8196_AUDIO_APLL2_EN_ON);
+
+ /* apll2 freq tuner disable */
+ regmap_update_bits(afe->regmap, AFE_APLL2_TUNER_CFG,
+ FREQ_TUNER_EN_MASK_SFT,
+ 0x0);
+
+ mt8196_afe_disable_top_cg(afe, MT8196_PDN_APLL_TUNER2);
+ mt8196_afe_disable_top_cg(afe, MT8196_CG_APLL2_CK);
+ apll2_mux_setting(afe, false);
+}
+
+int mt8196_get_apll_rate(struct mtk_base_afe *afe, int apll)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int clk_id = 0;
+
+ if (apll < MT8196_APLL1 || apll > MT8196_APLL2) {
+ dev_warn(afe->dev, "invalid clk id %d\n", apll);
+ return 0;
+ }
+
+ if (apll == MT8196_APLL1)
+ clk_id = MT8196_CLK_TOP_APLL1_CK;
+ else
+ clk_id = MT8196_CLK_TOP_APLL2_CK;
+
+ return clk_get_rate(afe_priv->clk[clk_id]);
+}
+
+/* 48K: select APLL2; 44.1k: select APLL1 */
+int mt8196_get_apll_by_rate(struct mtk_base_afe *afe, int rate)
+{
+ return (rate % 8000) ? MT8196_APLL1 : MT8196_APLL2;
+}
+
+int mt8196_get_apll_by_name(struct mtk_base_afe *afe, const char *name)
+{
+ if (strcmp(name, APLL1_W_NAME) == 0)
+ return MT8196_APLL1;
+
+ return MT8196_APLL2;
+}
+
+static const int mck_div[MT8196_MCK_NUM] = {
+ [MT8196_I2SIN0_MCK] = MT8196_CLK_TOP_APLL12_DIV_I2SIN0,
+ [MT8196_I2SIN1_MCK] = MT8196_CLK_TOP_APLL12_DIV_I2SIN1,
+ [MT8196_FMI2S_MCK] = MT8196_CLK_TOP_APLL12_DIV_FMI2S,
+ [MT8196_TDMOUT_MCK] = MT8196_CLK_TOP_APLL12_DIV_TDMOUT_M,
+ [MT8196_TDMOUT_BCK] = MT8196_CLK_TOP_APLL12_DIV_TDMOUT_B,
+};
+
+int mt8196_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int div_clk_id;
+ int ret;
+
+ dev_dbg(afe->dev, "mck_id: %d, rate: %d\n", mck_id, rate);
+
+ if (mck_id >= MT8196_MCK_NUM || mck_id < 0)
+ return -EINVAL;
+
+ div_clk_id = mck_div[mck_id];
+
+ /* enable div, set rate */
+ if (div_clk_id < 0) {
+ dev_err(afe->dev, "invalid div_clk_id %d\n", div_clk_id);
+ return -EINVAL;
+ }
+
+ if (div_clk_id == MT8196_CLK_TOP_APLL12_DIV_TDMOUT_B)
+ rate *= 16;
+
+ ret = mt8196_afe_enable_clk(afe, afe_priv->clk[div_clk_id]);
+ if (ret)
+ return ret;
+
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[div_clk_id], rate);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+int mt8196_mck_disable(struct mtk_base_afe *afe, int mck_id)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int div_clk_id;
+ int ret;
+
+ dev_dbg(afe->dev, "mck_id: %d.\n", mck_id);
+
+ if (mck_id < 0) {
+ dev_err(afe->dev, "mck_id = %d < 0\n", mck_id);
+ return -EINVAL;
+ }
+
+ div_clk_id = mck_div[mck_id];
+
+ if (div_clk_id < 0) {
+ dev_err(afe->dev, "div_clk_id = %d < 0\n",
+ div_clk_id);
+ return -EINVAL;
+ }
+
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[div_clk_id], MT8196_AFE_26M);
+ if (ret)
+ return ret;
+
+ mt8196_afe_disable_clk(afe, afe_priv->clk[div_clk_id]);
+
+ return 0;
+}
+
+int mt8196_afe_enable_reg_rw_clk(struct mtk_base_afe *afe)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int ret;
+
+ /* bus clock for AFE external access, like DRAM */
+ mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_TOP_ADSP_SEL]);
+
+ /* bus clock for AFE internal access, like AFE SRAM */
+ mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIOINTBUS]);
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIOINTBUS],
+ MT8196_AFE_26M);
+ if (ret)
+ return ret;
+
+ /* enable audio h clock */
+ mt8196_afe_enable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]);
+ ret = mt8196_afe_set_clk_rate(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H],
+ MT8196_AFE_26M);
+ if (ret)
+ return ret;
+
+ /* AFE hw clock */
+ /* IPM2.0: USE HOPPING & 26M */
+ /* set in the regmap_register_patch */
+ return 0;
+}
+
+int mt8196_afe_disable_reg_rw_clk(struct mtk_base_afe *afe)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+
+ /* IPM2.0: Use HOPPING & 26M */
+ /* set in the regmap_register_patch */
+
+ mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIO_H]);
+ mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_VLP_MUX_AUDIOINTBUS]);
+ mt8196_afe_disable_clk(afe, afe_priv->clk[MT8196_CLK_TOP_ADSP_SEL]);
+ return 0;
+}
+
+int mt8196_afe_enable_main_clock(struct mtk_base_afe *afe)
+{
+ mt8196_afe_enable_top_cg(afe, MT8196_AUDIO_26M_EN_ON);
+ return 0;
+}
+
+int mt8196_afe_disable_main_clock(struct mtk_base_afe *afe)
+{
+ mt8196_afe_disable_top_cg(afe, MT8196_AUDIO_26M_EN_ON);
+ return 0;
+}
+
+int mt8196_init_clock(struct mtk_base_afe *afe)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int i;
+
+ afe_priv->clk = devm_kcalloc(afe->dev, MT8196_CLK_NUM, sizeof(*afe_priv->clk),
+ GFP_KERNEL);
+ if (!afe_priv->clk)
+ return -ENOMEM;
+
+ for (i = 0; i < MT8196_CLK_NUM; i++) {
+ afe_priv->clk[i] = devm_clk_get(afe->dev, aud_clks[i]);
+ if (IS_ERR(afe_priv->clk[i])) {
+ dev_err(afe->dev, "devm_clk_get %s fail\n", aud_clks[i]);
+ return PTR_ERR(afe_priv->clk[i]);
+ }
+ }
+
+ return 0;
+}
+
diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-clk.h b/sound/soc/mediatek/mt8196/mt8196-afe-clk.h
new file mode 100644
index 000000000000..7d47dcff768b
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-clk.h
@@ -0,0 +1,64 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8196-afe-clk.h -- Mediatek MT8196 AFE Clock Control definitions
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#ifndef _MT8196_AFE_CLOCK_CTRL_H_
+#define _MT8196_AFE_CLOCK_CTRL_H_
+
+#define MT8196_AFE_26M 26000000
+#define MT8196_AUD_ENG1_CLK 45158400
+#define MT8196_AUD_ENG2_CLK 49152000
+
+/* APLL */
+#define APLL1_W_NAME "APLL1"
+#define APLL2_W_NAME "APLL2"
+
+enum {
+ MT8196_APLL1 = 0,
+ MT8196_APLL2,
+};
+
+enum {
+ /* vlp clk */
+ MT8196_CLK_VLP_MUX_AUDIOINTBUS,
+ MT8196_CLK_VLP_MUX_AUD_ENG1,
+ MT8196_CLK_VLP_MUX_AUD_ENG2,
+ MT8196_CLK_VLP_MUX_AUDIO_H,
+ /* pll */
+ MT8196_CLK_TOP_APLL1_CK,
+ MT8196_CLK_TOP_APLL2_CK,
+ /* divider */
+ MT8196_CLK_TOP_APLL12_DIV_I2SIN0,
+ MT8196_CLK_TOP_APLL12_DIV_I2SIN1,
+ MT8196_CLK_TOP_APLL12_DIV_FMI2S,
+ MT8196_CLK_TOP_APLL12_DIV_TDMOUT_M,
+ MT8196_CLK_TOP_APLL12_DIV_TDMOUT_B,
+ /* mux */
+ MT8196_CLK_TOP_ADSP_SEL,
+ MT8196_CLK_NUM,
+};
+
+struct mtk_base_afe;
+
+int mt8196_mck_enable(struct mtk_base_afe *afe, int mck_id, int rate);
+int mt8196_mck_disable(struct mtk_base_afe *afe, int mck_id);
+int mt8196_get_apll_rate(struct mtk_base_afe *afe, int apll);
+int mt8196_get_apll_by_rate(struct mtk_base_afe *afe, int rate);
+int mt8196_get_apll_by_name(struct mtk_base_afe *afe, const char *name);
+int mt8196_init_clock(struct mtk_base_afe *afe);
+int mt8196_afe_enable_clk(struct mtk_base_afe *afe, struct clk *clk);
+void mt8196_afe_disable_clk(struct mtk_base_afe *afe, struct clk *clk);
+int mt8196_apll1_enable(struct mtk_base_afe *afe);
+void mt8196_apll1_disable(struct mtk_base_afe *afe);
+int mt8196_apll2_enable(struct mtk_base_afe *afe);
+void mt8196_apll2_disable(struct mtk_base_afe *afe);
+int mt8196_afe_enable_main_clock(struct mtk_base_afe *afe);
+int mt8196_afe_disable_main_clock(struct mtk_base_afe *afe);
+int mt8196_afe_enable_reg_rw_clk(struct mtk_base_afe *afe);
+int mt8196_afe_disable_reg_rw_clk(struct mtk_base_afe *afe);
+
+#endif
diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-common.h b/sound/soc/mediatek/mt8196/mt8196-afe-common.h
new file mode 100644
index 000000000000..4951a6f32abb
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-common.h
@@ -0,0 +1,205 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8196-afe-common.h -- Mediatek 8196 audio driver definitions
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#ifndef _MT_8196_AFE_COMMON_H_
+#define _MT_8196_AFE_COMMON_H_
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include "mt8196-reg.h"
+#include "../common/mtk-base-afe.h"
+
+/* HW IPM 2.0 */
+enum {
+ MTK_AFE_IPM2P0_RATE_8K = 0x0,
+ MTK_AFE_IPM2P0_RATE_11K = 0x1,
+ MTK_AFE_IPM2P0_RATE_12K = 0x2,
+ MTK_AFE_IPM2P0_RATE_16K = 0x4,
+ MTK_AFE_IPM2P0_RATE_22K = 0x5,
+ MTK_AFE_IPM2P0_RATE_24K = 0x6,
+ MTK_AFE_IPM2P0_RATE_32K = 0x8,
+ MTK_AFE_IPM2P0_RATE_44K = 0x9,
+ MTK_AFE_IPM2P0_RATE_48K = 0xa,
+ MTK_AFE_IPM2P0_RATE_88K = 0xd,
+ MTK_AFE_IPM2P0_RATE_96K = 0xe,
+ MTK_AFE_IPM2P0_RATE_176K = 0x11,
+ MTK_AFE_IPM2P0_RATE_192K = 0x12,
+ MTK_AFE_IPM2P0_RATE_352K = 0x15,
+ MTK_AFE_IPM2P0_RATE_384K = 0x16,
+};
+
+enum {
+ MTKAIF_PROTOCOL_1,
+ MTKAIF_PROTOCOL_2,
+ MTKAIF_PROTOCOL_2_CLK_P2,
+};
+
+enum {
+ MT8196_MEMIF_DL0,
+ MT8196_MEMIF_DL1,
+ MT8196_MEMIF_DL2,
+ MT8196_MEMIF_DL3,
+ MT8196_MEMIF_DL4,
+ MT8196_MEMIF_DL5,
+ MT8196_MEMIF_DL6,
+ MT8196_MEMIF_DL7,
+ MT8196_MEMIF_DL8,
+ MT8196_MEMIF_DL23,
+ MT8196_MEMIF_DL24,
+ MT8196_MEMIF_DL25,
+ MT8196_MEMIF_DL26,
+ MT8196_MEMIF_DL_4CH,
+ MT8196_MEMIF_DL_24CH,
+ MT8196_MEMIF_VUL0,
+ MT8196_MEMIF_VUL1,
+ MT8196_MEMIF_VUL2,
+ MT8196_MEMIF_VUL3,
+ MT8196_MEMIF_VUL4,
+ MT8196_MEMIF_VUL5,
+ MT8196_MEMIF_VUL6,
+ MT8196_MEMIF_VUL7,
+ MT8196_MEMIF_VUL8,
+ MT8196_MEMIF_VUL9,
+ MT8196_MEMIF_VUL10,
+ MT8196_MEMIF_VUL24,
+ MT8196_MEMIF_VUL25,
+ MT8196_MEMIF_VUL26,
+ MT8196_MEMIF_VUL_CM0,
+ MT8196_MEMIF_VUL_CM1,
+ MT8196_MEMIF_VUL_CM2,
+ MT8196_MEMIF_ETDM_IN0,
+ MT8196_MEMIF_ETDM_IN1,
+ MT8196_MEMIF_ETDM_IN2,
+ MT8196_MEMIF_ETDM_IN3,
+ MT8196_MEMIF_ETDM_IN4,
+ MT8196_MEMIF_ETDM_IN6,
+ MT8196_MEMIF_HDMI,
+ MT8196_MEMIF_NUM,
+ MT8196_DAI_ADDA = MT8196_MEMIF_NUM,
+ MT8196_DAI_ADDA_CH34,
+ MT8196_DAI_ADDA_CH56,
+ MT8196_DAI_AP_DMIC,
+ MT8196_DAI_AP_DMIC_CH34,
+ MT8196_DAI_AP_DMIC_MULTICH,
+ MT8196_DAI_I2S_IN0,
+ MT8196_DAI_I2S_IN1,
+ MT8196_DAI_I2S_IN2,
+ MT8196_DAI_I2S_IN3,
+ MT8196_DAI_I2S_IN4,
+ MT8196_DAI_I2S_IN6,
+ MT8196_DAI_I2S_OUT0,
+ MT8196_DAI_I2S_OUT1,
+ MT8196_DAI_I2S_OUT2,
+ MT8196_DAI_I2S_OUT3,
+ MT8196_DAI_I2S_OUT4,
+ MT8196_DAI_I2S_OUT6,
+ MT8196_DAI_FM_I2S_MASTER,
+ MT8196_DAI_TDM,
+ MT8196_DAI_TDM_DPTX,
+ MT8196_DAI_NUM,
+};
+
+#define MT8196_DAI_I2S_MAX_NUM 13 //depends each platform's max i2s num
+
+/* update irq ID (= enum) from AFE_IRQ_MCU_STATUS */
+enum {
+ MT8196_IRQ_0,
+ MT8196_IRQ_1,
+ MT8196_IRQ_2,
+ MT8196_IRQ_3,
+ MT8196_IRQ_4,
+ MT8196_IRQ_5,
+ MT8196_IRQ_6,
+ MT8196_IRQ_7,
+ MT8196_IRQ_8,
+ MT8196_IRQ_9,
+ MT8196_IRQ_10,
+ MT8196_IRQ_11,
+ MT8196_IRQ_12,
+ MT8196_IRQ_13,
+ MT8196_IRQ_14,
+ MT8196_IRQ_15,
+ MT8196_IRQ_16,
+ MT8196_IRQ_17,
+ MT8196_IRQ_18,
+ MT8196_IRQ_19,
+ MT8196_IRQ_20,
+ MT8196_IRQ_21,
+ MT8196_IRQ_22,
+ MT8196_IRQ_23,
+ MT8196_IRQ_24,
+ MT8196_IRQ_25,
+ MT8196_IRQ_26,
+ MT8196_IRQ_31, /* used only for TDM */
+ MT8196_IRQ_NUM,
+};
+
+/* update irq ID (= enum) from AFE_IRQ_MCU_STATUS */
+enum {
+ MT8196_CUS_IRQ_TDM, /* used only for TDM */
+ MT8196_CUS_IRQ_NUM,
+};
+
+enum {
+ /* AUDIO_ENGEN_CON0 */
+ MT8196_AUDIO_26M_EN_ON,
+ MT8196_AUDIO_F3P25M_EN_ON,
+ MT8196_AUDIO_APLL1_EN_ON,
+ MT8196_AUDIO_APLL2_EN_ON,
+ MT8196_AUDIO_F26M_EN_RST,
+ MT8196_MULTI_USER_RST,
+ MT8196_MULTI_USER_BYPASS,
+ /* AUDIO_TOP_CON4 */
+ MT8196_CG_AUDIO_HOPPING_CK,
+ MT8196_CG_AUDIO_F26M_CK,
+ MT8196_CG_APLL1_CK,
+ MT8196_CG_APLL2_CK,
+ MT8196_PDN_APLL_TUNER2,
+ MT8196_PDN_APLL_TUNER1,
+ MT8196_AUDIO_CG_NUM,
+};
+
+/* MCLK */
+enum {
+ MT8196_I2SIN0_MCK,
+ MT8196_I2SIN1_MCK,
+ MT8196_FMI2S_MCK,
+ MT8196_TDMOUT_MCK,
+ MT8196_TDMOUT_BCK,
+ MT8196_MCK_NUM,
+};
+
+/* CM*/
+enum {
+ CM0,
+ CM1,
+ CM2,
+ CM_NUM,
+};
+
+struct clk;
+struct mtk_base_afe;
+
+struct mt8196_afe_private {
+ struct clk **clk;
+ /* dai */
+ void *dai_priv[MT8196_DAI_NUM];
+ /* mck */
+ int mck_rate[MT8196_MCK_NUM];
+ /* channel merge */
+ u32 cm_rate[CM_NUM];
+ u32 cm_channels;
+};
+
+int mt8196_dai_adda_register(struct mtk_base_afe *afe);
+int mt8196_dai_i2s_register(struct mtk_base_afe *afe);
+int mt8196_dai_tdm_register(struct mtk_base_afe *afe);
+int mt8196_dai_set_priv(struct mtk_base_afe *afe, int id,
+ int priv_size, const void *priv_data);
+
+#endif
diff --git a/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c b/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
new file mode 100644
index 000000000000..a1ae8322d8b6
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-afe-pcm.c
@@ -0,0 +1,2519 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Mediatek ALSA SoC AFE platform driver for 8196
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/of_device.h>
+#include <linux/of_reserved_mem.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
+
+#include <sound/pcm.h>
+#include <sound/soc.h>
+
+#include "mt8196-afe-clk.h"
+#include "mt8196-afe-common.h"
+#include "mt8196-interconnection.h"
+
+#include "../common/mtk-afe-fe-dai.h"
+#include "../common/mtk-afe-platform-driver.h"
+
+static const struct snd_pcm_hardware mt8196_afe_hardware = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_NO_PERIOD_WAKEUP |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID),
+ .formats = (SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S24_LE |
+ SNDRV_PCM_FMTBIT_S32_LE),
+ .period_bytes_min = 96,
+ .period_bytes_max = 4 * 48 * 1024,
+ .periods_min = 2,
+ .periods_max = 256,
+ .buffer_bytes_max = 256 * 1024,
+ .fifo_size = 0,
+};
+
+static unsigned int mt8196_rate_transform(struct device *dev,
+ unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return MTK_AFE_IPM2P0_RATE_8K;
+ case 11025:
+ return MTK_AFE_IPM2P0_RATE_11K;
+ case 12000:
+ return MTK_AFE_IPM2P0_RATE_12K;
+ case 16000:
+ return MTK_AFE_IPM2P0_RATE_16K;
+ case 22050:
+ return MTK_AFE_IPM2P0_RATE_22K;
+ case 24000:
+ return MTK_AFE_IPM2P0_RATE_24K;
+ case 32000:
+ return MTK_AFE_IPM2P0_RATE_32K;
+ case 44100:
+ return MTK_AFE_IPM2P0_RATE_44K;
+ case 48000:
+ return MTK_AFE_IPM2P0_RATE_48K;
+ case 88200:
+ return MTK_AFE_IPM2P0_RATE_88K;
+ case 96000:
+ return MTK_AFE_IPM2P0_RATE_96K;
+ case 176400:
+ return MTK_AFE_IPM2P0_RATE_176K;
+ case 192000:
+ return MTK_AFE_IPM2P0_RATE_192K;
+ /* not support 260K */
+ case 352800:
+ return MTK_AFE_IPM2P0_RATE_352K;
+ case 384000:
+ return MTK_AFE_IPM2P0_RATE_384K;
+ default:
+ dev_err(dev, "rate %u invalid, use %d!!!\n",
+ rate, MTK_AFE_IPM2P0_RATE_48K);
+ return MTK_AFE_IPM2P0_RATE_48K;
+ }
+}
+
+static int mt8196_set_cm(struct mtk_base_afe *afe, int id,
+ bool update, bool swap, unsigned int ch)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ unsigned int rate = afe_priv->cm_rate[id];
+ unsigned int rate_val = mt8196_rate_transform(afe->dev, rate);
+ unsigned int ch_pair = ch / 2;
+ unsigned int update_val;
+ int reg = AFE_CM0_CON0 + 0x10 * id;
+
+ if (update && ch_pair)
+ update_val = (26000000 / rate - 10) / ch_pair - 1;
+ else
+ update_val = 0x64;
+
+ dev_dbg(afe->dev, "CM%d, rate %d, update %d, swap %d, ch %d, update_val: %d\n",
+ id, rate, update, swap, ch, update_val);
+
+ /* update cnt */
+ regmap_update_bits(afe->regmap, reg,
+ AFE_CM_UPDATE_CNT_MASK << AFE_CM_UPDATE_CNT_SFT,
+ update_val << AFE_CM_UPDATE_CNT_SFT);
+
+ /* rate */
+ regmap_update_bits(afe->regmap, reg,
+ AFE_CM_1X_EN_SEL_FS_MASK << AFE_CM_1X_EN_SEL_FS_SFT,
+ rate_val << AFE_CM_1X_EN_SEL_FS_SFT);
+
+ /* ch num */
+ ch = ch - 1;
+ regmap_update_bits(afe->regmap, reg,
+ AFE_CM_CH_NUM_MASK << AFE_CM_CH_NUM_SFT,
+ ch << AFE_CM_CH_NUM_SFT);
+
+ /* swap */
+ regmap_update_bits(afe->regmap, reg,
+ AFE_CM_BYTE_SWAP_MASK << AFE_CM_BYTE_SWAP_SFT,
+ swap << AFE_CM_BYTE_SWAP_SFT);
+
+ return 0;
+}
+
+static int mt8196_enable_cm_bypass(struct mtk_base_afe *afe, int id, bool en)
+{
+ return regmap_update_bits(afe->regmap,
+ AFE_CM0_CON0 + 0x10 * id,
+ AFE_CM_BYPASS_MODE_MASK << AFE_CM_BYPASS_MODE_SFT,
+ en << AFE_CM_BYPASS_MODE_SFT);
+}
+
+static int mt8196_fe_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ int memif_num = cpu_dai->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
+ const struct snd_pcm_hardware *mtk_afe_hardware = afe->mtk_afe_hardware;
+ int ret;
+
+ dev_dbg(afe->dev, "memif_num: %d.\n", memif_num);
+
+ memif->substream = substream;
+
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 16);
+
+ if (memif_num == MT8196_MEMIF_VUL_CM0)
+ snd_pcm_hw_constraint_step(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 16);
+
+ snd_soc_set_runtime_hwparams(substream, mtk_afe_hardware);
+
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ dev_warn(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
+
+ /* dynamic allocate irq to memif */
+ if (memif->irq_usage < 0) {
+ int irq_id = mtk_dynamic_irq_acquire(afe);
+
+ if (irq_id != afe->irqs_size) {
+ /* link */
+ memif->irq_usage = irq_id;
+ } else {
+ dev_err(afe->dev, "no more asys irq\n");
+ ret = -EBUSY;
+ }
+ }
+ return ret;
+}
+
+static void mt8196_fe_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ int memif_num = cpu_dai->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[memif_num];
+ int irq_id = memif->irq_usage;
+
+ dev_dbg(afe->dev, "memif_num: %d.\n", memif_num);
+
+ memif->substream = NULL;
+
+ if (!memif->const_irq) {
+ mtk_dynamic_irq_release(afe, irq_id);
+ memif->irq_usage = -1;
+ memif->substream = NULL;
+ }
+}
+
+static int mt8196_fe_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ unsigned int channels = params_channels(params);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int id = snd_soc_rtd_to_cpu(rtd, 0)->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[id];
+ const struct mtk_base_memif_data *data = memif->data;
+ int cm;
+
+ afe_priv->cm_channels = channels;
+
+ /* set channels */
+ if (data->ch_num_shift >= 0) {
+ regmap_update_bits(afe->regmap, data->ch_num_reg,
+ data->ch_num_maskbit << data->ch_num_shift,
+ channels << data->ch_num_shift);
+ }
+
+ switch (id) {
+ case MT8196_MEMIF_VUL8:
+ case MT8196_MEMIF_VUL_CM0:
+ cm = CM0;
+ break;
+ case MT8196_MEMIF_VUL9:
+ case MT8196_MEMIF_VUL_CM1:
+ cm = CM1;
+ break;
+ case MT8196_MEMIF_VUL10:
+ case MT8196_MEMIF_VUL_CM2:
+ cm = CM2;
+ break;
+ default:
+ cm = CM0;
+ break;
+ }
+
+ afe_priv->cm_rate[cm] = params_rate(params);
+
+ return mtk_afe_fe_hw_params(substream, params, dai);
+}
+
+static int mt8196_fe_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_pcm_runtime *const runtime = substream->runtime;
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int id = snd_soc_rtd_to_cpu(rtd, 0)->id;
+ struct mtk_base_afe_memif *memif = &afe->memif[id];
+ int irq_id = memif->irq_usage;
+ struct mtk_base_afe_irq *irqs = &afe->irqs[irq_id];
+ const struct mtk_base_irq_data *irq_data = irqs->irq_data;
+ unsigned int counter = runtime->period_size;
+ unsigned int rate = runtime->rate;
+ unsigned int tmp_reg;
+ int fs;
+ int ret;
+
+ dev_dbg(afe->dev, "%s cmd %d, irq_id %d\n", memif->data->name, cmd, irq_id);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ dev_dbg(afe->dev, "%s cmd %d, id %d\n", memif->data->name, cmd, id);
+
+ ret = mtk_memif_set_enable(afe, id);
+ if (ret) {
+ dev_err(afe->dev, "id %d, memif enable fail.\n", id);
+ return ret;
+ }
+
+ /*
+ * for small latency record
+ * ul memif need read some data before irq enable.
+ * the context of this ops triger is atmoic, so it cannot sleep.
+ */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ if ((runtime->period_size * 1000) / rate <= 10)
+ udelay(300);
+
+ regmap_update_bits(afe->regmap,
+ irq_data->irq_cnt_reg,
+ irq_data->irq_cnt_maskbit << irq_data->irq_cnt_shift,
+ counter << irq_data->irq_cnt_shift);
+
+ /* set irq fs */
+ fs = afe->irq_fs(substream, rate);
+ if (fs < 0)
+ return -EINVAL;
+
+ if (irq_data->irq_fs_reg >= 0)
+ regmap_update_bits(afe->regmap,
+ irq_data->irq_fs_reg,
+ irq_data->irq_fs_maskbit << irq_data->irq_fs_shift,
+ fs << irq_data->irq_fs_shift);
+
+ /* enable interrupt */
+ regmap_update_bits(afe->regmap,
+ irq_data->irq_en_reg,
+ 1 << irq_data->irq_en_shift,
+ 1 << irq_data->irq_en_shift);
+
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ ret = mtk_memif_set_disable(afe, id);
+ if (ret)
+ dev_warn(afe->dev, "id %d, memif disable fail\n", id);
+
+ /* disable interrupt */
+ regmap_update_bits(afe->regmap,
+ irq_data->irq_en_reg,
+ 1 << irq_data->irq_en_shift,
+ 0 << irq_data->irq_en_shift);
+
+ /*
+ * clear pending IRQ, if the register read as one, there is no need to write
+ * one to clear operaton.
+ */
+ regmap_read(afe->regmap, irq_data->irq_clr_reg, &tmp_reg);
+ regmap_update_bits(afe->regmap, irq_data->irq_clr_reg,
+ AFE_IRQ_CLR_CFG_MASK_SFT | AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT,
+ tmp_reg ^ (AFE_IRQ_CLR_CFG_MASK_SFT |
+ AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT));
+
+ return ret;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int mt8196_memif_fs(struct snd_pcm_substream *substream,
+ unsigned int rate)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_component *component =
+ snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+ struct mtk_base_afe *afe = NULL;
+ unsigned int rate_reg;
+
+ if (!component)
+ return -EINVAL;
+
+ afe = snd_soc_component_get_drvdata(component);
+ if (!afe)
+ return -EINVAL;
+
+ rate_reg = mt8196_rate_transform(afe->dev, rate);
+
+ return rate_reg;
+}
+
+static int mt8196_get_dai_fs(struct mtk_base_afe *afe,
+ int dai_id, unsigned int rate)
+{
+ return mt8196_rate_transform(afe->dev, rate);
+}
+
+static int mt8196_irq_fs(struct snd_pcm_substream *substream, unsigned int rate)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_component *component =
+ snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
+ struct mtk_base_afe *afe = NULL;
+
+ if (!component)
+ return -EINVAL;
+ afe = snd_soc_component_get_drvdata(component);
+ return mt8196_rate_transform(afe->dev, rate);
+}
+
+static int mt8196_get_memif_pbuf_size(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ if ((runtime->period_size * 1000) / runtime->rate > 10)
+ return MT8196_MEMIF_PBUF_SIZE_256_BYTES;
+ else
+ return MT8196_MEMIF_PBUF_SIZE_32_BYTES;
+}
+
+/* FE DAIs */
+static const struct snd_soc_dai_ops mt8196_memif_dai_ops = {
+ .startup = mt8196_fe_startup,
+ .shutdown = mt8196_fe_shutdown,
+ .hw_params = mt8196_fe_hw_params,
+ .hw_free = mtk_afe_fe_hw_free,
+ .prepare = mtk_afe_fe_prepare,
+ .trigger = mt8196_fe_trigger,
+};
+
+#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\
+ SNDRV_PCM_RATE_88200 |\
+ SNDRV_PCM_RATE_96000 |\
+ SNDRV_PCM_RATE_176400 |\
+ SNDRV_PCM_RATE_192000)
+
+#define MTK_PCM_DAI_RATES (SNDRV_PCM_RATE_8000 |\
+ SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 |\
+ SNDRV_PCM_RATE_48000)
+
+#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define MT8196_FE_DAI(_name, _id, max_ch, dir) \
+{ \
+ .name = #_name, \
+ .id = _id, \
+ .dir = { \
+ .stream_name = #_name, \
+ .channels_min = 1, \
+ .channels_max = max_ch, \
+ .rates = MTK_PCM_RATES, \
+ .formats = MTK_PCM_FORMATS, \
+ }, \
+ .ops = &mt8196_memif_dai_ops, \
+}
+
+static struct snd_soc_dai_driver mt8196_memif_dai_driver[] = {
+ /* FE DAIs: memory intefaces to CPU */
+ /* Playback */
+ MT8196_FE_DAI(DL0, MT8196_MEMIF_DL0, 2, playback),
+ MT8196_FE_DAI(DL1, MT8196_MEMIF_DL1, 2, playback),
+ MT8196_FE_DAI(DL2, MT8196_MEMIF_DL2, 2, playback),
+ MT8196_FE_DAI(DL3, MT8196_MEMIF_DL3, 2, playback),
+ MT8196_FE_DAI(DL4, MT8196_MEMIF_DL4, 2, playback),
+ MT8196_FE_DAI(DL5, MT8196_MEMIF_DL5, 2, playback),
+ MT8196_FE_DAI(DL6, MT8196_MEMIF_DL6, 2, playback),
+ MT8196_FE_DAI(DL7, MT8196_MEMIF_DL7, 2, playback),
+ MT8196_FE_DAI(DL8, MT8196_MEMIF_DL8, 2, playback),
+ MT8196_FE_DAI(DL23, MT8196_MEMIF_DL23, 2, playback),
+ MT8196_FE_DAI(DL24, MT8196_MEMIF_DL24, 2, playback),
+ MT8196_FE_DAI(DL25, MT8196_MEMIF_DL25, 2, playback),
+ MT8196_FE_DAI(DL26, MT8196_MEMIF_DL26, 2, playback),
+ MT8196_FE_DAI(DL_4CH, MT8196_MEMIF_DL_4CH, 4, playback),
+ MT8196_FE_DAI(DL_24CH, MT8196_MEMIF_DL_24CH, 8, playback),
+ MT8196_FE_DAI(HDMI, MT8196_MEMIF_HDMI, 8, playback),
+ /* Capture */
+ MT8196_FE_DAI(UL0, MT8196_MEMIF_VUL0, 2, capture),
+ MT8196_FE_DAI(UL1, MT8196_MEMIF_VUL1, 2, capture),
+ MT8196_FE_DAI(UL2, MT8196_MEMIF_VUL2, 2, capture),
+ MT8196_FE_DAI(UL3, MT8196_MEMIF_VUL3, 2, capture),
+ MT8196_FE_DAI(UL4, MT8196_MEMIF_VUL4, 2, capture),
+ MT8196_FE_DAI(UL5, MT8196_MEMIF_VUL5, 2, capture),
+ MT8196_FE_DAI(UL6, MT8196_MEMIF_VUL6, 2, capture),
+ MT8196_FE_DAI(UL7, MT8196_MEMIF_VUL7, 2, capture),
+ MT8196_FE_DAI(UL8, MT8196_MEMIF_VUL8, 2, capture),
+ MT8196_FE_DAI(UL9, MT8196_MEMIF_VUL9, 16, capture),
+ MT8196_FE_DAI(UL10, MT8196_MEMIF_VUL10, 2, capture),
+ MT8196_FE_DAI(UL24, MT8196_MEMIF_VUL24, 2, capture),
+ MT8196_FE_DAI(UL25, MT8196_MEMIF_VUL25, 2, capture),
+ MT8196_FE_DAI(UL26, MT8196_MEMIF_VUL26, 2, capture),
+ MT8196_FE_DAI(UL_CM0, MT8196_MEMIF_VUL_CM0, 8, capture),
+ MT8196_FE_DAI(UL_CM1, MT8196_MEMIF_VUL_CM1, 16, capture),
+ MT8196_FE_DAI(UL_CM2, MT8196_MEMIF_VUL_CM2, 32, capture),
+ MT8196_FE_DAI(UL_ETDM_IN0, MT8196_MEMIF_ETDM_IN0, 2, capture),
+ MT8196_FE_DAI(UL_ETDM_IN1, MT8196_MEMIF_ETDM_IN1, 2, capture),
+ MT8196_FE_DAI(UL_ETDM_IN2, MT8196_MEMIF_ETDM_IN2, 2, capture),
+ MT8196_FE_DAI(UL_ETDM_IN3, MT8196_MEMIF_ETDM_IN3, 2, capture),
+ MT8196_FE_DAI(UL_ETDM_IN4, MT8196_MEMIF_ETDM_IN4, 2, capture),
+ MT8196_FE_DAI(UL_ETDM_IN6, MT8196_MEMIF_ETDM_IN6, 2, capture),
+};
+
+static int ul_cm0_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ unsigned int channels = afe_priv->cm_channels;
+
+ dev_dbg(afe->dev, "event 0x%x, name %s, channels %u\n",
+ event, w->name, channels);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mt8196_enable_cm_bypass(afe, CM0, false);
+ mt8196_set_cm(afe, CM0, true, false, channels);
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
+ PDN_CM0_MASK_SFT, 0 << PDN_CM0_SFT);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ mt8196_enable_cm_bypass(afe, CM0, true);
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
+ PDN_CM0_MASK_SFT, 1 << PDN_CM0_SFT);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int ul_cm1_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ unsigned int channels = afe_priv->cm_channels;
+
+ dev_dbg(afe->dev, "event 0x%x, name %s, channels %u\n",
+ event, w->name, channels);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mt8196_enable_cm_bypass(afe, CM1, false);
+ mt8196_set_cm(afe, CM1, true, false, channels);
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
+ PDN_CM1_MASK_SFT, 0 << PDN_CM1_SFT);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ mt8196_enable_cm_bypass(afe, CM1, true);
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
+ PDN_CM1_MASK_SFT, 1 << PDN_CM1_SFT);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int ul_cm2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ unsigned int channels = afe_priv->cm_channels;
+
+ dev_dbg(afe->dev, "event 0x%x, name %s, channels %u\n",
+ event, w->name, channels);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mt8196_enable_cm_bypass(afe, CM2, false);
+ mt8196_set_cm(afe, CM2, true, false, channels);
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
+ PDN_CM2_MASK_SFT, 0 << PDN_CM2_SFT);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ mt8196_enable_cm_bypass(afe, CM2, true);
+ regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
+ PDN_CM2_MASK_SFT, 1 << PDN_CM2_SFT);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * dma widget & routes
+ * The mixer controls and routes are by no means fully implemented,
+ * only the ones that are intended to be used are, as other wise a fully
+ * interconnected switch bar mixer would introduce way too many unused
+ * controls.
+ */
+static const struct snd_kcontrol_new memif_ul0_ch1_mix[] = {
+ /* Normal record */
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN018_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul0_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN019_0,
+ I_ADDA_UL_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul1_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN4_CH1", AFE_CONN020_4,
+ I_I2SIN4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH1", AFE_CONN020_5,
+ I_I2SIN6_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul1_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN4_CH2", AFE_CONN021_4,
+ I_I2SIN4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH2", AFE_CONN021_5,
+ I_I2SIN6_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul2_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN022_0,
+ I_ADDA_UL_CH3, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul2_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN023_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul3_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN024_4,
+ I_I2SIN0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN1_CH1", AFE_CONN024_4,
+ I_I2SIN1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN3_CH1", AFE_CONN024_4,
+ I_I2SIN3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN4_CH1", AFE_CONN024_4,
+ I_I2SIN4_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul3_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN025_4,
+ I_I2SIN0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN1_CH2", AFE_CONN025_4,
+ I_I2SIN1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN3_CH2", AFE_CONN025_4,
+ I_I2SIN3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN4_CH2", AFE_CONN025_4,
+ I_I2SIN4_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul4_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN026_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN026_1,
+ I_DL0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN026_1,
+ I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN026_1,
+ I_DL6_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN026_1,
+ I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN026_1,
+ I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN026_1,
+ I_DL_24CH_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN026_4,
+ I_I2SIN0_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul4_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN027_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN027_1,
+ I_DL0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN027_1,
+ I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN027_1,
+ I_DL6_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN027_1,
+ I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN027_1,
+ I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN027_1,
+ I_DL_24CH_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN027_4,
+ I_I2SIN0_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul5_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN3_CH1", AFE_CONN028_4,
+ I_I2SIN3_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul5_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN3_CH2", AFE_CONN029_4,
+ I_I2SIN3_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul6_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN030_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul6_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN031_0,
+ I_ADDA_UL_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul7_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN032_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul7_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN033_0,
+ I_ADDA_UL_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul8_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN034_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul8_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN035_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul9_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN036_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul9_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN037_0,
+ I_ADDA_UL_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul10_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN038_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul10_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN039_0,
+ I_ADDA_UL_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul24_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN066_4,
+ I_I2SIN0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH1", AFE_CONN066_5,
+ I_I2SIN6_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul24_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN067_4,
+ I_I2SIN0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH2", AFE_CONN067_5,
+ I_I2SIN6_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul25_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN068_4,
+ I_I2SIN0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH1", AFE_CONN068_5,
+ I_I2SIN6_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul25_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN069_4,
+ I_I2SIN0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH2", AFE_CONN069_5,
+ I_I2SIN6_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul26_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH1", AFE_CONN070_4,
+ I_I2SIN0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH1", AFE_CONN070_5,
+ I_I2SIN6_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul26_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN0_CH2", AFE_CONN071_4,
+ I_I2SIN0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("I2SIN6_CH2", AFE_CONN071_5,
+ I_I2SIN6_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm0_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN040_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm0_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN041_0,
+ I_ADDA_UL_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm0_ch3_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN042_0,
+ I_ADDA_UL_CH3, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm0_ch4_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN043_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm0_ch5_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN044_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm0_ch6_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN045_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm0_ch7_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN046_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm0_ch8_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN047_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN048_0,
+ I_ADDA_UL_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN049_0,
+ I_ADDA_UL_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch3_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN050_0,
+ I_ADDA_UL_CH3, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch4_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN051_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch5_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN052_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN052_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN052_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN052_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch6_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN053_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN053_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN053_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN053_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch7_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN054_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN054_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN054_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN054_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch8_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN055_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN055_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN055_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN055_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch9_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN056_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN056_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN056_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN056_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch10_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN057_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN057_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN057_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN057_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch11_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN058_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN058_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN058_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN058_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch12_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN059_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN059_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN059_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN059_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch13_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN060_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN060_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN060_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN060_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch14_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN061_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN061_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN061_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN061_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch15_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN062_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN062_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN062_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN062_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm1_ch16_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN063_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN063_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN063_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN063_0,
+ I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN064_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN064_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN064_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN064_0, I_ADDA_UL_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN064_0, I_ADDA_UL_CH5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN064_0, I_ADDA_UL_CH6, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN065_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN065_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN065_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN065_0, I_ADDA_UL_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN065_0, I_ADDA_UL_CH5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN065_0, I_ADDA_UL_CH6, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch3_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN066_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN066_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN066_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN066_0, I_ADDA_UL_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN066_0, I_ADDA_UL_CH5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN066_0, I_ADDA_UL_CH6, 1, 0)
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch4_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN067_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN067_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN067_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN067_0, I_ADDA_UL_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN067_0, I_ADDA_UL_CH5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN067_0, I_ADDA_UL_CH6, 1, 0)
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch5_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN068_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN068_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN068_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN068_0, I_ADDA_UL_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN068_0, I_ADDA_UL_CH5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN068_0, I_ADDA_UL_CH6, 1, 0)
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch6_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN069_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN069_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN069_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN069_0, I_ADDA_UL_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH5", AFE_CONN069_0, I_ADDA_UL_CH5, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH6", AFE_CONN069_0, I_ADDA_UL_CH6, 1, 0)
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch7_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN070_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN070_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN070_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN070_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch8_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN071_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN071_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN071_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN071_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch9_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN072_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN072_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN072_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN072_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch10_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN073_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN073_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN073_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN073_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch11_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN074_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN074_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN074_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN074_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch12_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN075_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN075_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN075_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN075_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch13_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN076_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN076_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN076_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN076_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch14_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN077_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN077_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN077_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN077_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch15_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN078_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN078_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN078_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN078_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch16_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN079_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN079_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN079_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN079_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch17_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN080_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN080_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN080_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN080_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch18_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN081_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN081_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN081_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN081_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch19_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN082_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN082_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN082_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN082_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch20_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN083_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN083_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN083_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN083_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch21_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN084_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN084_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN084_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN084_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch22_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN085_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN085_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN085_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN085_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch23_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN086_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN086_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN086_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN086_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch24_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN087_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN087_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN087_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN087_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch25_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN088_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN088_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN088_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN088_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch26_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN089_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN089_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN089_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN089_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch27_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN090_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN090_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN090_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN090_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch28_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN091_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN091_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN091_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN091_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch29_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN092_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN092_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN092_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN092_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch30_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN093_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN093_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN093_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN093_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch31_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN094_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN094_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN094_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN094_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const struct snd_kcontrol_new memif_ul_cm2_ch32_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN095_0, I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN095_0, I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN095_0, I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH4", AFE_CONN095_0, I_ADDA_UL_CH4, 1, 0),
+};
+
+static const char * const cm0_mux_map[] = {
+ "UL8_2CH_PATH",
+ "CM0_8CH_PATH",
+};
+
+static const char * const cm1_mux_map[] = {
+ "UL9_2CH_PATH",
+ "CM1_16CH_PATH",
+};
+
+static const char * const cm2_mux_map[] = {
+ "UL10_2CH_PATH",
+ "CM2_32CH_PATH",
+};
+
+static SOC_ENUM_SINGLE_DECL(ul_cm0_mux_map_enum, AFE_CM0_CON0,
+ AFE_CM0_OUTPUT_MUX_SFT, cm0_mux_map);
+
+static SOC_ENUM_SINGLE_DECL(ul_cm1_mux_map_enum, AFE_CM1_CON0,
+ AFE_CM1_OUTPUT_MUX_SFT, cm1_mux_map);
+
+static SOC_ENUM_SINGLE_DECL(ul_cm2_mux_map_enum, AFE_CM2_CON0,
+ AFE_CM2_OUTPUT_MUX_SFT, cm2_mux_map);
+
+static const struct snd_kcontrol_new ul_cm0_mux_control =
+ SOC_DAPM_ENUM("CM0_UL_MUX Route", ul_cm0_mux_map_enum);
+
+static const struct snd_kcontrol_new ul_cm1_mux_control =
+ SOC_DAPM_ENUM("CM1_UL_MUX Route", ul_cm1_mux_map_enum);
+
+static const struct snd_kcontrol_new ul_cm2_mux_control =
+ SOC_DAPM_ENUM("CM2_UL_MUX Route", ul_cm2_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mt8196_memif_widgets[] = {
+ /* inter-connections */
+ SND_SOC_DAPM_MIXER("UL0_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul0_ch1_mix, ARRAY_SIZE(memif_ul0_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL0_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul0_ch2_mix, ARRAY_SIZE(memif_ul0_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL1_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul1_ch1_mix, ARRAY_SIZE(memif_ul1_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL1_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul1_ch2_mix, ARRAY_SIZE(memif_ul1_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL2_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul2_ch1_mix, ARRAY_SIZE(memif_ul2_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL2_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul2_ch2_mix, ARRAY_SIZE(memif_ul2_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL3_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul3_ch1_mix, ARRAY_SIZE(memif_ul3_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL3_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul3_ch2_mix, ARRAY_SIZE(memif_ul3_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL4_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul4_ch1_mix, ARRAY_SIZE(memif_ul4_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL4_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul4_ch2_mix, ARRAY_SIZE(memif_ul4_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL5_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul5_ch1_mix, ARRAY_SIZE(memif_ul5_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL5_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul5_ch2_mix, ARRAY_SIZE(memif_ul5_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL6_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul6_ch1_mix, ARRAY_SIZE(memif_ul6_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL6_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul6_ch2_mix, ARRAY_SIZE(memif_ul6_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL7_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul7_ch1_mix, ARRAY_SIZE(memif_ul7_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL7_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul7_ch2_mix, ARRAY_SIZE(memif_ul7_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL8_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul8_ch1_mix, ARRAY_SIZE(memif_ul8_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL8_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul8_ch2_mix, ARRAY_SIZE(memif_ul8_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL9_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul9_ch1_mix, ARRAY_SIZE(memif_ul9_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL9_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul9_ch2_mix, ARRAY_SIZE(memif_ul9_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL10_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul10_ch1_mix, ARRAY_SIZE(memif_ul10_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL10_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul10_ch2_mix, ARRAY_SIZE(memif_ul10_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL24_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul24_ch1_mix, ARRAY_SIZE(memif_ul24_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL24_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul24_ch2_mix, ARRAY_SIZE(memif_ul24_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL25_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul25_ch1_mix, ARRAY_SIZE(memif_ul25_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL25_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul25_ch2_mix, ARRAY_SIZE(memif_ul25_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL26_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul26_ch1_mix, ARRAY_SIZE(memif_ul26_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL26_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul26_ch2_mix, ARRAY_SIZE(memif_ul26_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("UL_CM0_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm0_ch1_mix, ARRAY_SIZE(memif_ul_cm0_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM0_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm0_ch2_mix, ARRAY_SIZE(memif_ul_cm0_ch2_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM0_CH3", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm0_ch3_mix, ARRAY_SIZE(memif_ul_cm0_ch3_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM0_CH4", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm0_ch4_mix, ARRAY_SIZE(memif_ul_cm0_ch4_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM0_CH5", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm0_ch5_mix, ARRAY_SIZE(memif_ul_cm0_ch5_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM0_CH6", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm0_ch6_mix, ARRAY_SIZE(memif_ul_cm0_ch6_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM0_CH7", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm0_ch7_mix, ARRAY_SIZE(memif_ul_cm0_ch7_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM0_CH8", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm0_ch8_mix, ARRAY_SIZE(memif_ul_cm0_ch8_mix)),
+ SND_SOC_DAPM_MUX("CM0_UL_MUX", SND_SOC_NOPM, 0, 0,
+ &ul_cm0_mux_control),
+
+ SND_SOC_DAPM_MIXER("UL_CM1_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch1_mix, ARRAY_SIZE(memif_ul_cm1_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch2_mix, ARRAY_SIZE(memif_ul_cm1_ch2_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH3", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch3_mix, ARRAY_SIZE(memif_ul_cm1_ch3_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH4", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch4_mix, ARRAY_SIZE(memif_ul_cm1_ch4_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH5", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch5_mix, ARRAY_SIZE(memif_ul_cm1_ch5_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH6", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch6_mix, ARRAY_SIZE(memif_ul_cm1_ch6_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH7", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch7_mix, ARRAY_SIZE(memif_ul_cm1_ch7_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH8", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch8_mix, ARRAY_SIZE(memif_ul_cm1_ch8_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH9", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch9_mix, ARRAY_SIZE(memif_ul_cm1_ch9_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH10", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch10_mix, ARRAY_SIZE(memif_ul_cm1_ch10_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH11", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch11_mix, ARRAY_SIZE(memif_ul_cm1_ch11_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH12", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch12_mix, ARRAY_SIZE(memif_ul_cm1_ch12_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH13", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch13_mix, ARRAY_SIZE(memif_ul_cm1_ch13_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH14", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch14_mix, ARRAY_SIZE(memif_ul_cm1_ch14_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH15", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch15_mix, ARRAY_SIZE(memif_ul_cm1_ch15_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM1_CH16", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm1_ch16_mix, ARRAY_SIZE(memif_ul_cm1_ch16_mix)),
+ SND_SOC_DAPM_MUX("CM1_UL_MUX", SND_SOC_NOPM, 0, 0,
+ &ul_cm1_mux_control),
+
+ SND_SOC_DAPM_MIXER("UL_CM2_CH1", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch1_mix, ARRAY_SIZE(memif_ul_cm2_ch1_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH2", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch2_mix, ARRAY_SIZE(memif_ul_cm2_ch2_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH3", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch3_mix, ARRAY_SIZE(memif_ul_cm2_ch3_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH4", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch4_mix, ARRAY_SIZE(memif_ul_cm2_ch4_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH5", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch5_mix, ARRAY_SIZE(memif_ul_cm2_ch5_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH6", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch6_mix, ARRAY_SIZE(memif_ul_cm2_ch6_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH7", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch7_mix, ARRAY_SIZE(memif_ul_cm2_ch7_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH8", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch8_mix, ARRAY_SIZE(memif_ul_cm2_ch8_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH9", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch9_mix, ARRAY_SIZE(memif_ul_cm2_ch9_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH10", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch10_mix, ARRAY_SIZE(memif_ul_cm2_ch10_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH11", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch11_mix, ARRAY_SIZE(memif_ul_cm2_ch11_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH12", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch12_mix, ARRAY_SIZE(memif_ul_cm2_ch12_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH13", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch13_mix, ARRAY_SIZE(memif_ul_cm2_ch13_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH14", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch14_mix, ARRAY_SIZE(memif_ul_cm2_ch14_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH15", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch15_mix, ARRAY_SIZE(memif_ul_cm2_ch15_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH16", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch16_mix, ARRAY_SIZE(memif_ul_cm2_ch16_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH17", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch17_mix, ARRAY_SIZE(memif_ul_cm2_ch17_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH18", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch18_mix, ARRAY_SIZE(memif_ul_cm2_ch18_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH19", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch19_mix, ARRAY_SIZE(memif_ul_cm2_ch19_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH20", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch20_mix, ARRAY_SIZE(memif_ul_cm2_ch20_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH21", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch21_mix, ARRAY_SIZE(memif_ul_cm2_ch21_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH22", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch22_mix, ARRAY_SIZE(memif_ul_cm2_ch22_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH23", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch23_mix, ARRAY_SIZE(memif_ul_cm2_ch23_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH24", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch24_mix, ARRAY_SIZE(memif_ul_cm2_ch24_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH25", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch25_mix, ARRAY_SIZE(memif_ul_cm2_ch25_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH26", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch26_mix, ARRAY_SIZE(memif_ul_cm2_ch26_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH27", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch27_mix, ARRAY_SIZE(memif_ul_cm2_ch27_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH28", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch28_mix, ARRAY_SIZE(memif_ul_cm2_ch28_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH29", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch29_mix, ARRAY_SIZE(memif_ul_cm2_ch29_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH30", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch30_mix, ARRAY_SIZE(memif_ul_cm2_ch30_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH31", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch31_mix, ARRAY_SIZE(memif_ul_cm2_ch31_mix)),
+ SND_SOC_DAPM_MIXER("UL_CM2_CH32", SND_SOC_NOPM, 0, 0,
+ memif_ul_cm2_ch32_mix, ARRAY_SIZE(memif_ul_cm2_ch32_mix)),
+ SND_SOC_DAPM_MUX("CM2_UL_MUX", SND_SOC_NOPM, 0, 0,
+ &ul_cm2_mux_control),
+
+ SND_SOC_DAPM_SUPPLY("CM0_Enable",
+ AFE_CM0_CON0, AFE_CM0_ON_SFT, 0,
+ ul_cm0_event,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_SUPPLY("CM1_Enable",
+ AFE_CM1_CON0, AFE_CM1_ON_SFT, 0,
+ ul_cm1_event,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+
+ SND_SOC_DAPM_SUPPLY("CM2_Enable",
+ AFE_CM2_CON0, AFE_CM2_ON_SFT, 0,
+ ul_cm2_event,
+ SND_SOC_DAPM_PRE_PMU |
+ SND_SOC_DAPM_PRE_PMD),
+
+ /* dynamic pinctrl */
+ SND_SOC_DAPM_PINCTRL("I2S3_PIN", "aud-gpio-i2s3-on", "aud-gpio-i2s3-off"),
+ SND_SOC_DAPM_PINCTRL("I2S4_PIN", "aud-gpio-i2s4-on", "aud-gpio-i2s4-off"),
+ SND_SOC_DAPM_PINCTRL("I2S6_PIN", "aud-gpio-i2s6-on", "aud-gpio-i2s6-off"),
+ SND_SOC_DAPM_PINCTRL("AP_DMIC0_PIN", "aud-gpio-ap-dmic-on", "aud-gpio-ap-dmic-off"),
+ SND_SOC_DAPM_PINCTRL("AP_DMIC1_PIN", "aud-gpio-ap-dmic1-on", "aud-gpio-ap-dmic1-off"),
+};
+
+static const struct snd_soc_dapm_route mt8196_memif_routes[] = {
+ {"UL0", NULL, "UL0_CH1"},
+ {"UL0", NULL, "UL0_CH2"},
+ /* Normal record */
+ {"UL0_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
+ {"UL0_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
+
+ {"UL1", NULL, "UL1_CH1"},
+ {"UL1", NULL, "UL1_CH2"},
+ {"UL1_CH1", "I2SIN4_CH1", "I2SIN4"},
+ {"UL1_CH2", "I2SIN4_CH2", "I2SIN4"},
+ {"UL1_CH1", "I2SIN6_CH1", "I2SIN6"},
+ {"UL1_CH2", "I2SIN6_CH2", "I2SIN6"},
+
+ {"UL2", NULL, "UL2_CH1"},
+ {"UL2", NULL, "UL2_CH2"},
+ {"UL2_CH1", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"},
+ {"UL2_CH2", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"},
+
+ {"UL3", NULL, "UL3_CH1"},
+ {"UL3", NULL, "UL3_CH2"},
+ {"UL3_CH1", "I2SIN0_CH1", "I2SIN0"},
+ {"UL3_CH2", "I2SIN0_CH2", "I2SIN0"},
+ {"UL3_CH1", "I2SIN1_CH1", "I2SIN1"},
+ {"UL3_CH2", "I2SIN1_CH2", "I2SIN1"},
+ {"UL3_CH1", "I2SIN3_CH1", "I2SIN3"},
+ {"UL3_CH2", "I2SIN3_CH2", "I2SIN3"},
+ {"UL3_CH1", "I2SIN4_CH1", "I2SIN4"},
+ {"UL3_CH2", "I2SIN4_CH2", "I2SIN4"},
+
+ {"UL4", NULL, "UL4_CH1"},
+ {"UL4", NULL, "UL4_CH2"},
+ {"UL4_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
+ {"UL4_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
+ {"UL4_CH1", "I2SIN0_CH1", "I2SIN0"},
+ {"UL4_CH2", "I2SIN0_CH2", "I2SIN0"},
+
+ {"UL5", NULL, "UL5_CH1"},
+ {"UL5", NULL, "UL5_CH2"},
+ {"UL5_CH1", "I2SIN3_CH1", "I2SIN3"},
+ {"UL5_CH2", "I2SIN3_CH2", "I2SIN3"},
+
+ {"UL6", NULL, "UL6_CH1"},
+ {"UL6", NULL, "UL6_CH2"},
+ {"UL6_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
+ {"UL6_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
+
+ {"UL7", NULL, "UL7_CH1"},
+ {"UL7", NULL, "UL7_CH2"},
+ {"UL7_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
+ {"UL7_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
+
+ {"UL8", NULL, "CM0_UL_MUX"},
+ {"CM0_UL_MUX", "UL8_2CH_PATH", "UL8_CH1"},
+ {"CM0_UL_MUX", "UL8_2CH_PATH", "UL8_CH2"},
+ {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH1"},
+ {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH2"},
+ {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH3"},
+ {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH4"},
+ {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH5"},
+ {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH6"},
+ {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH7"},
+ {"CM0_UL_MUX", "CM0_8CH_PATH", "UL_CM0_CH8"},
+
+ {"UL_CM0", NULL, "CM0_Enable"},
+
+ /* UL9 */
+ {"UL9", NULL, "CM1_UL_MUX"},
+ {"CM1_UL_MUX", "UL9_2CH_PATH", "UL9_CH1"},
+ {"CM1_UL_MUX", "UL9_2CH_PATH", "UL9_CH2"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH1"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH2"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH3"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH4"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH5"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH6"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH7"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH8"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH9"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH10"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH11"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH12"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH13"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH14"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH15"},
+ {"CM1_UL_MUX", "CM1_16CH_PATH", "UL_CM1_CH16"},
+
+ {"UL_CM1", NULL, "CM1_Enable"},
+
+ {"UL9_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
+ {"UL9_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
+
+ {"UL10", NULL, "CM2_UL_MUX"},
+ {"CM2_UL_MUX", "UL10_2CH_PATH", "UL10_CH1"},
+ {"CM2_UL_MUX", "UL10_2CH_PATH", "UL10_CH2"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH1"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH2"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH3"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH4"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH5"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH6"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH7"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH8"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH9"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH10"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH11"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH12"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH13"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH14"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH15"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH16"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH17"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH18"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH19"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH20"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH21"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH22"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH23"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH24"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH25"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH26"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH27"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH28"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH29"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH30"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH31"},
+ {"CM2_UL_MUX", "CM2_32CH_PATH", "UL_CM2_CH32"},
+
+ {"UL_CM2", NULL, "CM2_Enable"},
+
+ {"UL10_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
+ {"UL10_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
+
+ {"UL24", NULL, "UL24_CH1"},
+ {"UL24", NULL, "UL24_CH2"},
+ {"UL24_CH1", "I2SIN6_CH1", "I2SIN6"},
+ {"UL24_CH2", "I2SIN6_CH2", "I2SIN6"},
+ {"UL24_CH1", "I2SIN0_CH1", "I2SIN0"},
+ {"UL24_CH2", "I2SIN0_CH2", "I2SIN0"},
+
+ {"UL25", NULL, "UL25_CH1"},
+ {"UL25", NULL, "UL25_CH2"},
+ {"UL25_CH1", "I2SIN6_CH1", "I2SIN6"},
+ {"UL25_CH2", "I2SIN6_CH2", "I2SIN6"},
+ {"UL25_CH1", "I2SIN0_CH1", "I2SIN0"},
+ {"UL25_CH2", "I2SIN0_CH2", "I2SIN0"},
+
+ {"UL26", NULL, "UL26_CH1"},
+ {"UL26", NULL, "UL26_CH2"},
+ {"UL26_CH1", "I2SIN6_CH1", "I2SIN6"},
+ {"UL26_CH2", "I2SIN6_CH2", "I2SIN6"},
+ {"UL26_CH1", "I2SIN0_CH1", "I2SIN0"},
+ {"UL26_CH2", "I2SIN0_CH2", "I2SIN0"},
+
+ {"UL_CM0", NULL, "UL_CM0_CH1"},
+ {"UL_CM0", NULL, "UL_CM0_CH2"},
+ {"UL_CM0", NULL, "UL_CM0_CH3"},
+ {"UL_CM0", NULL, "UL_CM0_CH4"},
+ {"UL_CM0", NULL, "UL_CM0_CH5"},
+ {"UL_CM0", NULL, "UL_CM0_CH6"},
+ {"UL_CM0", NULL, "UL_CM0_CH7"},
+ {"UL_CM0", NULL, "UL_CM0_CH8"},
+ {"UL_CM0_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
+ {"UL_CM0_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
+ {"UL_CM0_CH3", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"},
+ {"UL_CM0_CH4", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"},
+
+ {"UL_CM1", NULL, "UL_CM1_CH1"},
+ {"UL_CM1", NULL, "UL_CM1_CH2"},
+ {"UL_CM1", NULL, "UL_CM1_CH3"},
+ {"UL_CM1", NULL, "UL_CM1_CH4"},
+ {"UL_CM1", NULL, "UL_CM1_CH5"},
+ {"UL_CM1", NULL, "UL_CM1_CH6"},
+ {"UL_CM1", NULL, "UL_CM1_CH7"},
+ {"UL_CM1", NULL, "UL_CM1_CH8"},
+ {"UL_CM1", NULL, "UL_CM1_CH9"},
+ {"UL_CM1", NULL, "UL_CM1_CH10"},
+ {"UL_CM1", NULL, "UL_CM1_CH11"},
+ {"UL_CM1", NULL, "UL_CM1_CH12"},
+ {"UL_CM1", NULL, "UL_CM1_CH13"},
+ {"UL_CM1", NULL, "UL_CM1_CH14"},
+ {"UL_CM1", NULL, "UL_CM1_CH15"},
+ {"UL_CM1", NULL, "UL_CM1_CH16"},
+ {"UL_CM1_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
+ {"UL_CM1_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
+ {"UL_CM1_CH3", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"},
+ {"UL_CM1_CH4", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"},
+
+ {"UL_CM2", NULL, "UL_CM2_CH1"},
+ {"UL_CM2", NULL, "UL_CM2_CH2"},
+ {"UL_CM2", NULL, "UL_CM2_CH3"},
+ {"UL_CM2", NULL, "UL_CM2_CH4"},
+ {"UL_CM2", NULL, "UL_CM2_CH5"},
+ {"UL_CM2", NULL, "UL_CM2_CH6"},
+ {"UL_CM2", NULL, "UL_CM2_CH7"},
+ {"UL_CM2", NULL, "UL_CM2_CH8"},
+ {"UL_CM2", NULL, "UL_CM2_CH9"},
+ {"UL_CM2", NULL, "UL_CM2_CH10"},
+ {"UL_CM2", NULL, "UL_CM2_CH11"},
+ {"UL_CM2", NULL, "UL_CM2_CH12"},
+ {"UL_CM2", NULL, "UL_CM2_CH13"},
+ {"UL_CM2", NULL, "UL_CM2_CH14"},
+ {"UL_CM2", NULL, "UL_CM2_CH15"},
+ {"UL_CM2", NULL, "UL_CM2_CH16"},
+ {"UL_CM2", NULL, "UL_CM2_CH17"},
+ {"UL_CM2", NULL, "UL_CM2_CH18"},
+ {"UL_CM2", NULL, "UL_CM2_CH19"},
+ {"UL_CM2", NULL, "UL_CM2_CH20"},
+ {"UL_CM2", NULL, "UL_CM2_CH21"},
+ {"UL_CM2", NULL, "UL_CM2_CH22"},
+ {"UL_CM2", NULL, "UL_CM2_CH23"},
+ {"UL_CM2", NULL, "UL_CM2_CH24"},
+ {"UL_CM2", NULL, "UL_CM2_CH25"},
+ {"UL_CM2", NULL, "UL_CM2_CH26"},
+ {"UL_CM2", NULL, "UL_CM2_CH27"},
+ {"UL_CM2", NULL, "UL_CM2_CH28"},
+ {"UL_CM2", NULL, "UL_CM2_CH29"},
+ {"UL_CM2", NULL, "UL_CM2_CH30"},
+ {"UL_CM2", NULL, "UL_CM2_CH31"},
+ {"UL_CM2", NULL, "UL_CM2_CH32"},
+ {"UL_CM2_CH1", "ADDA_UL_CH1", "ADDA_UL_Mux"},
+ {"UL_CM2_CH2", "ADDA_UL_CH2", "ADDA_UL_Mux"},
+ {"UL_CM2_CH3", "ADDA_UL_CH3", "ADDA_CH34_UL_Mux"},
+ {"UL_CM2_CH4", "ADDA_UL_CH4", "ADDA_CH34_UL_Mux"},
+
+ /* Audio Pin */
+ {"I2SOUT4", NULL, "I2S4_PIN"},
+ {"I2SIN4", NULL, "I2S4_PIN"},
+ {"I2SOUT6", NULL, "I2S6_PIN"},
+ {"I2SIN6", NULL, "I2S6_PIN"},
+ {"I2SOUT3", NULL, "I2S3_PIN"},
+ {"I2SIN3", NULL, "I2S3_PIN"},
+ {"AP DMIC Capture", NULL, "AP_DMIC0_PIN"},
+ {"AP DMIC CH34 Capture", NULL, "AP_DMIC1_PIN"},
+};
+
+#define MT8196_DL_MEMIF(_id) \
+ [MT8196_MEMIF_##_id] = { \
+ .name = #_id, \
+ .id = MT8196_MEMIF_##_id, \
+ .reg_ofs_base = AFE_##_id##_BASE, \
+ .reg_ofs_cur = AFE_##_id##_CUR, \
+ .reg_ofs_end = AFE_##_id##_END, \
+ .reg_ofs_base_msb = AFE_##_id##_BASE_MSB, \
+ .reg_ofs_cur_msb = AFE_##_id##_CUR_MSB, \
+ .reg_ofs_end_msb = AFE_##_id##_END_MSB, \
+ .fs_reg = AFE_##_id##_CON0, \
+ .fs_shift = _id##_SEL_FS_SFT, \
+ .fs_maskbit = _id##_SEL_FS_MASK, \
+ .mono_reg = AFE_##_id##_CON0, \
+ .mono_shift = _id##_MONO_SFT, \
+ .enable_reg = AFE_##_id##_CON0, \
+ .enable_shift = _id##_ON_SFT, \
+ .hd_reg = AFE_##_id##_CON0, \
+ .hd_shift = _id##_HD_MODE_SFT, \
+ .hd_align_reg = AFE_##_id##_CON0, \
+ .hd_align_mshift = _id##_HALIGN_SFT, \
+ .agent_disable_reg = -1, \
+ .agent_disable_shift = -1, \
+ .msb_reg = -1, \
+ .msb_shift = -1, \
+ .pbuf_reg = AFE_##_id##_CON0, \
+ .pbuf_mask = _id##_PBUF_SIZE_MASK, \
+ .pbuf_shift = _id##_PBUF_SIZE_SFT, \
+ .minlen_reg = AFE_##_id##_CON0, \
+ .minlen_mask = _id##_MINLEN_MASK, \
+ .minlen_shift = _id##_MINLEN_SFT, \
+}
+
+#define MT8196_MULTI_DL_MEMIF(_id) \
+ [MT8196_MEMIF_##_id] = { \
+ .name = #_id, \
+ .id = MT8196_MEMIF_##_id, \
+ .reg_ofs_base = AFE_##_id##_BASE, \
+ .reg_ofs_cur = AFE_##_id##_CUR, \
+ .reg_ofs_end = AFE_##_id##_END, \
+ .reg_ofs_base_msb = AFE_##_id##_BASE_MSB, \
+ .reg_ofs_cur_msb = AFE_##_id##_CUR_MSB, \
+ .reg_ofs_end_msb = AFE_##_id##_END_MSB, \
+ .fs_reg = AFE_##_id##_CON0, \
+ .fs_shift = _id##_SEL_FS_SFT, \
+ .fs_maskbit = _id##_SEL_FS_MASK, \
+ .mono_reg = -1, \
+ .mono_shift = -1, \
+ .enable_reg = AFE_##_id##_CON0, \
+ .enable_shift = _id##_ON_SFT, \
+ .hd_reg = AFE_##_id##_CON0, \
+ .hd_shift = _id##_HD_MODE_SFT, \
+ .hd_align_reg = AFE_##_id##_CON0, \
+ .hd_align_mshift = _id##_HALIGN_SFT, \
+ .agent_disable_reg = -1, \
+ .agent_disable_shift = -1, \
+ .msb_reg = -1, \
+ .msb_shift = -1, \
+ .pbuf_reg = AFE_##_id##_CON0, \
+ .pbuf_mask = _id##_PBUF_SIZE_MASK, \
+ .pbuf_shift = _id##_PBUF_SIZE_SFT, \
+ .minlen_reg = AFE_##_id##_CON0, \
+ .minlen_mask = _id##_MINLEN_MASK, \
+ .minlen_shift = _id##_MINLEN_SFT, \
+ .ch_num_reg = AFE_##_id##_CON0, \
+ .ch_num_maskbit = _id##_NUM_MASK, \
+ .ch_num_shift = _id##_NUM_SFT, \
+}
+
+#define MT8196_UL_MEMIF(_id, _fs_shift, _fs_maskbit, _mono_shift) \
+ [MT8196_MEMIF_##_id] = { \
+ .name = #_id, \
+ .id = MT8196_MEMIF_##_id, \
+ .reg_ofs_base = AFE_##_id##_BASE, \
+ .reg_ofs_cur = AFE_##_id##_CUR, \
+ .reg_ofs_end = AFE_##_id##_END, \
+ .reg_ofs_base_msb = AFE_##_id##_BASE_MSB, \
+ .reg_ofs_cur_msb = AFE_##_id##_CUR_MSB, \
+ .reg_ofs_end_msb = AFE_##_id##_END_MSB, \
+ .fs_reg = AFE_##_id##_CON0, \
+ .fs_shift = _fs_shift, \
+ .fs_maskbit = _fs_maskbit, \
+ .mono_reg = AFE_##_id##_CON0, \
+ .mono_shift = _mono_shift, \
+ .enable_reg = AFE_##_id##_CON0, \
+ .enable_shift = _id##_ON_SFT, \
+ .hd_reg = AFE_##_id##_CON0, \
+ .hd_shift = _id##_HD_MODE_SFT, \
+ .hd_align_reg = AFE_##_id##_CON0, \
+ .hd_align_mshift = _id##_HALIGN_SFT, \
+ .agent_disable_reg = -1, \
+ .agent_disable_shift = -1, \
+ .msb_reg = -1, \
+ .msb_shift = -1, \
+ }
+
+/* For convenience with macros: missing register fields */
+#define HDMI_SEL_FS_SFT -1
+#define HDMI_SEL_FS_MASK -1
+
+/* For convenience with macros: register name differences */
+#define AFE_HDMI_BASE AFE_HDMI_OUT_BASE
+#define AFE_HDMI_CUR AFE_HDMI_OUT_CUR
+#define AFE_HDMI_END AFE_HDMI_OUT_END
+#define AFE_HDMI_BASE_MSB AFE_HDMI_OUT_BASE_MSB
+#define AFE_HDMI_CUR_MSB AFE_HDMI_OUT_CUR_MSB
+#define AFE_HDMI_END_MSB AFE_HDMI_OUT_END_MSB
+#define AFE_HDMI_CON0 AFE_HDMI_OUT_CON0
+#define HDMI_ON_SFT HDMI_OUT_ON_SFT
+#define HDMI_HD_MODE_SFT HDMI_OUT_HD_MODE_SFT
+#define HDMI_HALIGN_SFT HDMI_OUT_HALIGN_SFT
+#define HDMI_PBUF_SIZE_MASK HDMI_OUT_PBUF_SIZE_MASK
+#define HDMI_PBUF_SIZE_SFT HDMI_OUT_PBUF_SIZE_SFT
+#define HDMI_MINLEN_MASK HDMI_OUT_MINLEN_MASK
+#define HDMI_MINLEN_SFT HDMI_OUT_MINLEN_SFT
+#define HDMI_NUM_MASK HDMI_CH_NUM_MASK
+#define HDMI_NUM_SFT HDMI_CH_NUM_SFT
+
+static const struct mtk_base_memif_data memif_data[MT8196_MEMIF_NUM] = {
+ MT8196_DL_MEMIF(DL0),
+ MT8196_DL_MEMIF(DL1),
+ MT8196_DL_MEMIF(DL2),
+ MT8196_DL_MEMIF(DL3),
+ MT8196_DL_MEMIF(DL4),
+ MT8196_DL_MEMIF(DL5),
+ MT8196_DL_MEMIF(DL6),
+ MT8196_DL_MEMIF(DL7),
+ MT8196_DL_MEMIF(DL8),
+ MT8196_DL_MEMIF(DL23),
+ MT8196_DL_MEMIF(DL24),
+ MT8196_DL_MEMIF(DL25),
+ MT8196_DL_MEMIF(DL26),
+ MT8196_MULTI_DL_MEMIF(DL_4CH),
+ MT8196_MULTI_DL_MEMIF(DL_24CH),
+ MT8196_MULTI_DL_MEMIF(HDMI),
+ MT8196_UL_MEMIF(VUL0, VUL0_SEL_FS_SFT, VUL0_SEL_FS_MASK, VUL0_MONO_SFT),
+ MT8196_UL_MEMIF(VUL1, VUL1_SEL_FS_SFT, VUL1_SEL_FS_MASK, VUL1_MONO_SFT),
+ MT8196_UL_MEMIF(VUL2, VUL2_SEL_FS_SFT, VUL2_SEL_FS_MASK, VUL2_MONO_SFT),
+ MT8196_UL_MEMIF(VUL3, VUL3_SEL_FS_SFT, VUL3_SEL_FS_MASK, VUL3_MONO_SFT),
+ MT8196_UL_MEMIF(VUL4, VUL4_SEL_FS_SFT, VUL4_SEL_FS_MASK, VUL4_MONO_SFT),
+ MT8196_UL_MEMIF(VUL5, VUL5_SEL_FS_SFT, VUL5_SEL_FS_MASK, VUL5_MONO_SFT),
+ MT8196_UL_MEMIF(VUL6, VUL6_SEL_FS_SFT, VUL6_SEL_FS_MASK, VUL6_MONO_SFT),
+ MT8196_UL_MEMIF(VUL7, VUL7_SEL_FS_SFT, VUL7_SEL_FS_MASK, VUL7_MONO_SFT),
+ MT8196_UL_MEMIF(VUL8, VUL8_SEL_FS_SFT, VUL8_SEL_FS_MASK, VUL8_MONO_SFT),
+ MT8196_UL_MEMIF(VUL9, VUL9_SEL_FS_SFT, VUL9_SEL_FS_MASK, VUL9_MONO_SFT),
+ MT8196_UL_MEMIF(VUL10, VUL10_SEL_FS_SFT, VUL10_SEL_FS_MASK, VUL10_MONO_SFT),
+ MT8196_UL_MEMIF(VUL24, VUL24_SEL_FS_SFT, VUL24_SEL_FS_MASK, VUL24_MONO_SFT),
+ MT8196_UL_MEMIF(VUL25, VUL25_SEL_FS_SFT, VUL25_SEL_FS_MASK, VUL25_MONO_SFT),
+ MT8196_UL_MEMIF(VUL26, VUL26_SEL_FS_SFT, VUL26_SEL_FS_MASK, VUL26_MONO_SFT),
+ MT8196_UL_MEMIF(VUL_CM0, -1, -1, -1),
+ MT8196_UL_MEMIF(VUL_CM1, -1, -1, -1),
+ MT8196_UL_MEMIF(VUL_CM2, -1, -1, -1),
+ MT8196_UL_MEMIF(ETDM_IN0, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1),
+ MT8196_UL_MEMIF(ETDM_IN1, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1),
+ MT8196_UL_MEMIF(ETDM_IN2, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1),
+ MT8196_UL_MEMIF(ETDM_IN3, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1),
+ MT8196_UL_MEMIF(ETDM_IN4, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1),
+ MT8196_UL_MEMIF(ETDM_IN6, REG_FS_TIMING_SEL_SFT, REG_FS_TIMING_SEL_MASK, -1),
+};
+
+#define MT8196_AFE_IRQ(_id) \
+ [MT8196_IRQ_##_id] = { \
+ .id = MT8196_IRQ_##_id, \
+ .irq_cnt_reg = AFE_IRQ##_id##_MCU_CFG1, \
+ .irq_cnt_shift = AFE_IRQ_CNT_SHIFT, \
+ .irq_cnt_maskbit = AFE_IRQ_CNT_MASK, \
+ .irq_fs_reg = AFE_IRQ##_id##_MCU_CFG0, \
+ .irq_fs_shift = AFE_IRQ##_id##_MCU_FS_SFT, \
+ .irq_fs_maskbit = AFE_IRQ##_id##_MCU_FS_MASK, \
+ .irq_en_reg = AFE_IRQ##_id##_MCU_CFG0, \
+ .irq_en_shift = AFE_IRQ##_id##_MCU_ON_SFT, \
+ .irq_clr_reg = AFE_IRQ##_id##_MCU_CFG1, \
+ .irq_clr_shift = AFE_IRQ##_id##_CLR_CFG_SFT, \
+ }
+
+#define MT8196_AFE_TDM_IRQ(_id) \
+ [MT8196_IRQ_##_id] = { \
+ .id = MT8196_CUS_IRQ_TDM, \
+ .irq_cnt_reg = AFE_CUSTOM_IRQ0_MCU_CFG1, \
+ .irq_cnt_shift = AFE_CUSTOM_IRQ0_MCU_CNT_SFT, \
+ .irq_cnt_maskbit = AFE_CUSTOM_IRQ0_MCU_CNT_MASK, \
+ .irq_fs_reg = -1, \
+ .irq_fs_shift = -1, \
+ .irq_fs_maskbit = -1, \
+ .irq_en_reg = AFE_CUSTOM_IRQ0_MCU_CFG0, \
+ .irq_en_shift = AFE_CUSTOM_IRQ0_MCU_ON_SFT, \
+ .irq_clr_reg = AFE_CUSTOM_IRQ0_MCU_CFG1, \
+ .irq_clr_shift = AFE_CUSTOM_IRQ0_CLR_CFG_SFT, \
+ }
+
+static const struct mtk_base_irq_data irq_data[MT8196_IRQ_NUM] = {
+ MT8196_AFE_IRQ(0),
+ MT8196_AFE_IRQ(1),
+ MT8196_AFE_IRQ(2),
+ MT8196_AFE_IRQ(3),
+ MT8196_AFE_IRQ(4),
+ MT8196_AFE_IRQ(5),
+ MT8196_AFE_IRQ(6),
+ MT8196_AFE_IRQ(7),
+ MT8196_AFE_IRQ(8),
+ MT8196_AFE_IRQ(9),
+ MT8196_AFE_IRQ(10),
+ MT8196_AFE_IRQ(11),
+ MT8196_AFE_IRQ(12),
+ MT8196_AFE_IRQ(13),
+ MT8196_AFE_IRQ(14),
+ MT8196_AFE_IRQ(15),
+ MT8196_AFE_IRQ(16),
+ MT8196_AFE_IRQ(17),
+ MT8196_AFE_IRQ(18),
+ MT8196_AFE_IRQ(19),
+ MT8196_AFE_IRQ(20),
+ MT8196_AFE_IRQ(21),
+ MT8196_AFE_IRQ(22),
+ MT8196_AFE_IRQ(23),
+ MT8196_AFE_IRQ(24),
+ MT8196_AFE_IRQ(25),
+ MT8196_AFE_IRQ(26),
+ MT8196_AFE_TDM_IRQ(31),
+};
+
+static const int memif_irq_usage[MT8196_MEMIF_NUM] = {
+ /* TODO: verify each memif & irq */
+ [MT8196_MEMIF_DL0] = MT8196_IRQ_0,
+ [MT8196_MEMIF_DL1] = MT8196_IRQ_1,
+ [MT8196_MEMIF_DL2] = MT8196_IRQ_2,
+ [MT8196_MEMIF_DL3] = MT8196_IRQ_3,
+ [MT8196_MEMIF_DL4] = MT8196_IRQ_4,
+ [MT8196_MEMIF_DL5] = MT8196_IRQ_5,
+ [MT8196_MEMIF_DL6] = MT8196_IRQ_6,
+ [MT8196_MEMIF_DL7] = MT8196_IRQ_7,
+ [MT8196_MEMIF_DL8] = MT8196_IRQ_8,
+ [MT8196_MEMIF_DL23] = MT8196_IRQ_9,
+ [MT8196_MEMIF_DL24] = MT8196_IRQ_10,
+ [MT8196_MEMIF_DL25] = MT8196_IRQ_11,
+ [MT8196_MEMIF_DL26] = MT8196_IRQ_0,
+ [MT8196_MEMIF_DL_4CH] = MT8196_IRQ_0,
+ [MT8196_MEMIF_DL_24CH] = MT8196_IRQ_12,
+ [MT8196_MEMIF_VUL0] = MT8196_IRQ_13,
+ [MT8196_MEMIF_VUL1] = MT8196_IRQ_14,
+ [MT8196_MEMIF_VUL2] = MT8196_IRQ_15,
+ [MT8196_MEMIF_VUL3] = MT8196_IRQ_16,
+ [MT8196_MEMIF_VUL4] = MT8196_IRQ_17,
+ [MT8196_MEMIF_VUL5] = MT8196_IRQ_18,
+ [MT8196_MEMIF_VUL6] = MT8196_IRQ_19,
+ [MT8196_MEMIF_VUL7] = MT8196_IRQ_20,
+ [MT8196_MEMIF_VUL8] = MT8196_IRQ_21,
+ [MT8196_MEMIF_VUL9] = MT8196_IRQ_22,
+ [MT8196_MEMIF_VUL10] = MT8196_IRQ_23,
+ [MT8196_MEMIF_VUL24] = MT8196_IRQ_24,
+ [MT8196_MEMIF_VUL25] = MT8196_IRQ_25,
+ [MT8196_MEMIF_VUL26] = MT8196_IRQ_0,
+ [MT8196_MEMIF_VUL_CM0] = MT8196_IRQ_26,
+ [MT8196_MEMIF_VUL_CM1] = MT8196_IRQ_0,
+ [MT8196_MEMIF_VUL_CM2] = MT8196_IRQ_0,
+ [MT8196_MEMIF_ETDM_IN0] = MT8196_IRQ_0,
+ [MT8196_MEMIF_ETDM_IN1] = MT8196_IRQ_0,
+ [MT8196_MEMIF_ETDM_IN2] = MT8196_IRQ_0,
+ [MT8196_MEMIF_ETDM_IN3] = MT8196_IRQ_0,
+ [MT8196_MEMIF_ETDM_IN4] = MT8196_IRQ_0,
+ [MT8196_MEMIF_ETDM_IN6] = MT8196_IRQ_0,
+ [MT8196_MEMIF_HDMI] = MT8196_IRQ_31
+};
+
+static bool mt8196_is_volatile_reg(struct device *dev, unsigned int reg)
+{
+ /* these auto-gen reg has read-only bit, so put it as volatile */
+ /* volatile reg cannot be cached, so cannot be set when power off */
+ switch (reg) {
+ case AUDIO_TOP_CON0 ... AUDIO_TOP_CON4:
+ case AFE_APLL1_TUNER_MON0:
+ case AFE_APLL2_TUNER_MON0:
+ case AFE_SPM_CONTROL_ACK:
+ case AUDIO_TOP_IP_VERSION:
+ case AUDIO_ENGEN_CON0_MON:
+ case AUD_TOP_MON_RG:
+ case AFE_CONNSYS_I2S_IPM_VER_MON:
+ case AFE_CONNSYS_I2S_MON:
+ case AFE_PCM_INTF_MON:
+ case AFE_PCM_TOP_IP_VERSION:
+ case AFE_IRQ_MCU_STATUS:
+ case AFE_CUSTOM_IRQ_MCU_STATUS:
+ case AFE_IRQ_MCU_MON0 ... AFE_IRQ26_CNT_MON:
+ case AFE_CUSTOM_IRQ0_CNT_MON:
+ case AFE_STF_MON:
+ case AFE_STF_IP_VERSION:
+ case AFE_CM0_MON:
+ case AFE_CM0_IP_VERSION:
+ case AFE_CM1_MON:
+ case AFE_CM1_IP_VERSION:
+ case AFE_ADDA_UL0_SRC_DEBUG_MON0 ... AFE_ADDA_UL0_SRC_MON1:
+ case AFE_ADDA_UL0_IP_VERSION:
+ case AFE_ADDA_UL1_SRC_DEBUG_MON0 ... AFE_ADDA_UL1_SRC_MON1:
+ case AFE_ADDA_UL1_IP_VERSION:
+ case AFE_MTKAIF_IPM_VER_MON:
+ case AFE_MTKAIF_MON:
+ case AFE_AUD_PAD_TOP_MON:
+ case AFE_ADDA_MTKAIFV4_MON0 ... AFE_ADDA6_MTKAIFV4_MON0:
+ case ETDM_IN0_MON:
+ case ETDM_IN1_MON:
+ case ETDM_IN2_MON:
+ case ETDM_IN4_MON:
+ case ETDM_IN6_MON:
+ case ETDM_OUT0_MON:
+ case ETDM_OUT1_MON:
+ case ETDM_OUT2_MON:
+ case ETDM_OUT4_MON:
+ case ETDM_OUT6_MON:
+ case AFE_DPTX_MON:
+ case AFE_TDM_TOP_IP_VERSION:
+ case AFE_CONN_MON0 ... AFE_CONN_MON5:
+ case AFE_CBIP_SLV_DECODER_MON0 ... AFE_CBIP_SLV_MUX_MON1:
+ case AFE_DL0_CUR_MSB ... AFE_DL0_CUR:
+ case AFE_DL0_RCH_MON ... AFE_DL0_LCH_MON:
+ case AFE_DL1_CUR_MSB ... AFE_DL1_CUR:
+ case AFE_DL1_RCH_MON ... AFE_DL1_LCH_MON:
+ case AFE_DL2_CUR_MSB ... AFE_DL2_CUR:
+ case AFE_DL2_RCH_MON ... AFE_DL2_LCH_MON:
+ case AFE_DL3_CUR_MSB ... AFE_DL3_CUR:
+ case AFE_DL3_RCH_MON ... AFE_DL3_LCH_MON:
+ case AFE_DL4_CUR_MSB ... AFE_DL4_CUR:
+ case AFE_DL4_RCH_MON ... AFE_DL4_LCH_MON:
+ case AFE_DL5_CUR_MSB ... AFE_DL5_CUR:
+ case AFE_DL5_RCH_MON ... AFE_DL5_LCH_MON:
+ case AFE_DL6_CUR_MSB ... AFE_DL6_CUR:
+ case AFE_DL6_RCH_MON ... AFE_DL6_LCH_MON:
+ case AFE_DL7_CUR_MSB ... AFE_DL7_CUR:
+ case AFE_DL7_RCH_MON ... AFE_DL7_LCH_MON:
+ case AFE_DL8_CUR_MSB ... AFE_DL8_CUR:
+ case AFE_DL8_RCH_MON ... AFE_DL8_LCH_MON:
+ case AFE_DL_24CH_CUR_MSB ... AFE_DL_24CH_CUR:
+ case AFE_DL_4CH_CUR_MSB ... AFE_DL_4CH_CUR:
+ case AFE_DL23_CUR_MSB ... AFE_DL23_CUR:
+ case AFE_DL23_RCH_MON ... AFE_DL23_LCH_MON:
+ case AFE_DL24_CUR_MSB ... AFE_DL24_CUR:
+ case AFE_DL24_RCH_MON ... AFE_DL24_LCH_MON:
+ case AFE_DL25_CUR_MSB ... AFE_DL25_CUR:
+ case AFE_DL25_RCH_MON ... AFE_DL25_LCH_MON:
+ case AFE_DL26_CUR_MSB ... AFE_DL26_CUR:
+ case AFE_DL26_RCH_MON ... AFE_DL26_LCH_MON:
+ case AFE_VUL0_CUR_MSB ... AFE_VUL0_CUR:
+ case AFE_VUL1_CUR_MSB ... AFE_VUL1_CUR:
+ case AFE_VUL2_CUR_MSB ... AFE_VUL2_CUR:
+ case AFE_VUL3_CUR_MSB ... AFE_VUL3_CUR:
+ case AFE_VUL4_CUR_MSB ... AFE_VUL4_CUR:
+ case AFE_VUL5_CUR_MSB ... AFE_VUL5_CUR:
+ case AFE_VUL6_CUR_MSB ... AFE_VUL6_CUR:
+ case AFE_VUL7_CUR_MSB ... AFE_VUL7_CUR:
+ case AFE_VUL8_CUR_MSB ... AFE_VUL8_CUR:
+ case AFE_VUL9_CUR_MSB ... AFE_VUL9_CUR:
+ case AFE_VUL10_CUR_MSB ... AFE_VUL10_CUR:
+ case AFE_VUL24_CUR_MSB ... AFE_VUL24_CUR:
+ case AFE_VUL25_CUR_MSB ... AFE_VUL25_CUR:
+ case AFE_VUL25_RCH_MON ... AFE_VUL25_LCH_MON:
+ case AFE_VUL26_CUR_MSB ... AFE_VUL26_CUR:
+ case AFE_VUL_CM0_BASE_MSB ... AFE_VUL_CM0_CON0:
+ case AFE_VUL_CM1_CUR_MSB ... AFE_VUL_CM1_CUR:
+ case AFE_VUL_CM2_CUR_MSB ... AFE_VUL_CM2_CUR:
+ case AFE_ETDM_IN0_CUR_MSB ... AFE_ETDM_IN0_CUR:
+ case AFE_ETDM_IN1_CUR_MSB ... AFE_ETDM_IN1_CUR:
+ case AFE_ETDM_IN2_CUR_MSB ... AFE_ETDM_IN2_CUR:
+ case AFE_ETDM_IN3_CUR_MSB ... AFE_ETDM_IN3_CUR:
+ case AFE_ETDM_IN4_CUR_MSB ... AFE_ETDM_IN4_CUR:
+ case AFE_ETDM_IN6_CUR_MSB ... AFE_ETDM_IN6_CUR:
+ case AFE_HDMI_OUT_CUR_MSB ... AFE_HDMI_OUT_CUR:
+ case AFE_HDMI_OUT_END:
+ case AFE_PROT_SIDEBAND0_MON ... AFE_DOMAIN_SIDEBAND9_MON:
+ case AFE_PCM0_INTF_CON1_MASK_MON ... AFE_ADDA_UL1_SRC_CON0_MASK_MON:
+ case AFE_IRQ_MCU_EN ... AFE_IRQ_MCU_DSP2_EN:
+ case AFE_CUSTOM_IRQ_MCU_EN:
+ case AFE_DL5_CON0:
+ case AFE_DL6_CON0:
+ case AFE_DL23_CON0:
+ case AFE_DL_24CH_CON0:
+ case AFE_VUL1_CON0:
+ case AFE_VUL3_CON0:
+ case AFE_VUL4_CON0:
+ case AFE_VUL5_CON0:
+ case AFE_VUL9_CON0:
+ case AFE_VUL25_CON0:
+ case AFE_IRQ0_MCU_CFG0 ... AFE_IRQ26_MCU_CFG1:
+ return true;
+ default:
+ return false;
+ };
+}
+
+static const struct regmap_config mt8196_afe_regmap_config = {
+ .reg_bits = 32,
+ .reg_stride = 4,
+ .val_bits = 32,
+
+ .volatile_reg = mt8196_is_volatile_reg,
+
+ .max_register = AFE_MAX_REGISTER,
+ .num_reg_defaults_raw = AFE_MAX_REGISTER,
+
+ .cache_type = REGCACHE_FLAT,
+};
+
+static irqreturn_t mt8196_afe_irq_handler(int irq_id, void *dev)
+{
+ struct mtk_base_afe *afe = dev;
+ struct mtk_base_afe_irq *irq;
+ u32 status;
+ u32 status_mcu;
+ u32 mcu_en;
+ u32 cus_status;
+ u32 cus_status_mcu;
+ u32 cus_mcu_en;
+ u32 tmp_reg;
+ int ret, cus_ret;
+ int i;
+ struct timespec64 ts64;
+ u64 t1, t2;
+ /* one interrupt period = 5ms */
+ const u64 timeout_limit = 5000000;
+
+ /* get irq that is sent to MCU */
+ regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_en);
+ regmap_read(afe->regmap, AFE_CUSTOM_IRQ_MCU_EN, &cus_mcu_en);
+
+ ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &status);
+ cus_ret = regmap_read(afe->regmap, AFE_CUSTOM_IRQ_MCU_STATUS, &cus_status);
+ /* only care IRQ which is sent to MCU */
+ status_mcu = status & mcu_en & AFE_IRQ_STATUS_BITS;
+ cus_status_mcu = cus_status & cus_mcu_en & AFE_IRQ_STATUS_BITS;
+ if ((ret || !status_mcu) && (cus_ret || !cus_status_mcu)) {
+ dev_err(afe->dev, "ret %d, sat 0x%x, en 0x%x,csat 0x%x, cen 0x%x\n",
+ ret, status, mcu_en, cus_status_mcu, cus_mcu_en);
+ return IRQ_NONE;
+ }
+
+ ktime_get_ts64(&ts64);
+ t1 = ktime_get_ns();
+
+ for (i = 0; i < MT8196_MEMIF_NUM; i++) {
+ struct mtk_base_afe_memif *memif = &afe->memif[i];
+
+ if (!memif->substream)
+ continue;
+
+ if (memif->irq_usage < 0)
+ continue;
+ irq = &afe->irqs[memif->irq_usage];
+
+ if (i == MT8196_MEMIF_HDMI) {
+ if (cus_status_mcu & BIT(irq->irq_data->id))
+ snd_pcm_period_elapsed(memif->substream);
+ } else {
+ if (status_mcu & BIT(irq->irq_data->id))
+ snd_pcm_period_elapsed(memif->substream);
+ }
+ }
+
+ ktime_get_ts64(&ts64);
+ t2 = ktime_get_ns();
+ t2 = t2 - t1; /* in ns (10^9) */
+
+ if (t2 > timeout_limit)
+ dev_warn(afe->dev, "IRQ handler exceeded time limit by %llu ns\n",
+ t2 - timeout_limit);
+
+ /* clear irq */
+ for (i = 0; i < MT8196_IRQ_NUM; ++i) {
+ /* cus_status_mcu only bit0 is used for TDM */
+ if ((status_mcu & BIT(i)) || (cus_status_mcu & 0x1)) {
+ regmap_read(afe->regmap, irq_data[i].irq_clr_reg, &tmp_reg);
+ regmap_update_bits(afe->regmap, irq_data[i].irq_clr_reg,
+ AFE_IRQ_CLR_CFG_MASK_SFT |
+ AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT,
+ tmp_reg ^ (AFE_IRQ_CLR_CFG_MASK_SFT |
+ AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT));
+ }
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int mt8196_afe_runtime_suspend(struct device *dev)
+{
+ struct mtk_base_afe *afe = dev_get_drvdata(dev);
+ unsigned int value;
+ unsigned int tmp_reg;
+ int ret, i;
+
+ if (!afe->regmap) {
+ dev_err(afe->dev, "skip regmap\n");
+ goto skip_regmap;
+ }
+
+ /* disable AFE */
+ mt8196_afe_disable_main_clock(afe);
+
+ ret = regmap_read_poll_timeout(afe->regmap,
+ AUDIO_ENGEN_CON0_MON,
+ value,
+ (value & AUDIO_ENGEN_MON_SFT) == 0,
+ 20,
+ 1 * 1000 * 1000);
+ dev_dbg(afe->dev, "read_poll ret %d\n", ret);
+ if (ret)
+ dev_warn(afe->dev, "ret %d\n", ret);
+
+ /* make sure all irq status are cleared */
+ for (i = 0; i < MT8196_IRQ_NUM; ++i) {
+ regmap_read(afe->regmap, irq_data[i].irq_clr_reg, &tmp_reg);
+ regmap_update_bits(afe->regmap, irq_data[i].irq_clr_reg,
+ AFE_IRQ_CLR_CFG_MASK_SFT | AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT,
+ tmp_reg ^ (AFE_IRQ_CLR_CFG_MASK_SFT |
+ AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT));
+ }
+
+ /* reset audio 26M request */
+ regmap_update_bits(afe->regmap,
+ AFE_SPM_CONTROL_REQ, 0x1, 0x0);
+
+ /* cache only */
+ regcache_cache_only(afe->regmap, true);
+ regcache_mark_dirty(afe->regmap);
+
+skip_regmap:
+ mt8196_afe_disable_reg_rw_clk(afe);
+ return 0;
+}
+
+static int mt8196_afe_runtime_resume(struct device *dev)
+{
+ struct mtk_base_afe *afe = dev_get_drvdata(dev);
+ int ret = 0;
+
+ ret = mt8196_afe_enable_reg_rw_clk(afe);
+ if (ret)
+ return ret;
+
+ if (!afe->regmap) {
+ dev_warn(afe->dev, "skip regmap\n");
+ goto skip_regmap;
+ }
+ regcache_cache_only(afe->regmap, false);
+ regcache_sync(afe->regmap);
+
+ /* set audio 26M request */
+ regmap_update_bits(afe->regmap, AFE_SPM_CONTROL_REQ, 0x1, 0x1);
+ regmap_update_bits(afe->regmap, AFE_CBIP_CFG0, 0x1, 0x1);
+
+ /* force cpu use 8_24 format when writing 32bit data */
+ regmap_update_bits(afe->regmap, AFE_MEMIF_CON0,
+ CPU_HD_ALIGN_MASK_SFT, 0 << CPU_HD_ALIGN_SFT);
+
+ /* enable AFE */
+ mt8196_afe_enable_main_clock(afe);
+
+skip_regmap:
+ return 0;
+}
+
+static int mt8196_afe_component_probe(struct snd_soc_component *component)
+{
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
+ int ret;
+
+ /* enable clock for regcache get default value from hw */
+ ret = pm_runtime_resume_and_get(afe->dev);
+ if (ret)
+ return dev_err_probe(afe->dev, ret, "failed to resume device\n");
+
+ mtk_afe_add_sub_dai_control(component);
+ pm_runtime_put_sync(afe->dev);
+
+ return 0;
+}
+
+static int mt8196_afe_pcm_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ /* set the wait_for_avail to 2 sec*/
+ substream->wait_time = msecs_to_jiffies(2 * 1000);
+
+ return 0;
+}
+
+static void mt8196_afe_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm)
+{
+ snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static const struct snd_soc_component_driver mt8196_afe_component = {
+ .name = AFE_PCM_NAME,
+ .probe = mt8196_afe_component_probe,
+ .pcm_new = mtk_afe_pcm_new,
+ .pcm_free = mt8196_afe_pcm_free,
+ .open = mt8196_afe_pcm_open,
+ .pointer = mtk_afe_pcm_pointer,
+};
+
+static int mt8196_dai_memif_register(struct mtk_base_afe *afe)
+{
+ struct mtk_base_afe_dai *dai;
+
+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ list_add(&dai->list, &afe->sub_dais);
+
+ dai->dai_drivers = mt8196_memif_dai_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(mt8196_memif_dai_driver);
+ dai->dapm_widgets = mt8196_memif_widgets;
+ dai->num_dapm_widgets = ARRAY_SIZE(mt8196_memif_widgets);
+ dai->dapm_routes = mt8196_memif_routes;
+ dai->num_dapm_routes = ARRAY_SIZE(mt8196_memif_routes);
+ return 0;
+}
+
+typedef int (*dai_register_cb)(struct mtk_base_afe *);
+static const dai_register_cb dai_register_cbs[] = {
+ mt8196_dai_adda_register,
+ mt8196_dai_i2s_register,
+ mt8196_dai_tdm_register,
+ mt8196_dai_memif_register,
+};
+
+static const struct reg_sequence mt8196_cg_patch[] = {
+ { AUDIO_TOP_CON4, 0x361c },
+};
+
+static void mt8196_afe_release_reserved_mem(void *data)
+{
+ of_reserved_mem_device_release(data);
+}
+
+static int mt8196_afe_pcm_dev_probe(struct platform_device *pdev)
+{
+ int ret, i;
+ unsigned int tmp_reg;
+ int irq_id;
+ struct mtk_base_afe *afe;
+ struct mt8196_afe_private *afe_priv;
+ struct device *dev = &pdev->dev;
+
+ ret = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(34));
+ if (ret)
+ return ret;
+
+ ret = of_reserved_mem_device_init(dev);
+ if (ret) {
+ dev_err(dev, "failed to assign memory region: %d\n", ret);
+ } else {
+ ret = devm_add_action_or_reset(dev, mt8196_afe_release_reserved_mem, dev);
+ if (ret)
+ return ret;
+ }
+
+ afe = devm_kzalloc(dev, sizeof(*afe), GFP_KERNEL);
+ if (!afe)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, afe);
+
+ afe->platform_priv = devm_kzalloc(dev, sizeof(*afe_priv),
+ GFP_KERNEL);
+ if (!afe->platform_priv)
+ return -ENOMEM;
+
+ afe_priv = afe->platform_priv;
+ afe->dev = dev;
+
+ afe->base_addr = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(afe->base_addr))
+ return dev_err_probe(dev, PTR_ERR(afe->base_addr),
+ "AFE base_addr not found\n");
+
+ /* init audio related clock */
+ ret = mt8196_init_clock(afe);
+ if (ret)
+ return dev_err_probe(dev, ret, "init clock error.\n");
+
+ /* init memif */
+ /* IPM2.0 no need banding */
+ afe->memif_32bit_supported = 1;
+ afe->memif_size = MT8196_MEMIF_NUM;
+ afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
+ GFP_KERNEL);
+
+ if (!afe->memif)
+ return -ENOMEM;
+
+ for (i = 0; i < afe->memif_size; i++) {
+ afe->memif[i].data = &memif_data[i];
+ afe->memif[i].irq_usage = memif_irq_usage[i];
+ afe->memif[i].const_irq = 1;
+ }
+
+ mutex_init(&afe->irq_alloc_lock);
+
+ /* init irq */
+ afe->irqs_size = MT8196_IRQ_NUM;
+ afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
+ GFP_KERNEL);
+
+ if (!afe->irqs)
+ return -ENOMEM;
+
+ for (i = 0; i < afe->irqs_size; i++)
+ afe->irqs[i].irq_data = &irq_data[i];
+
+ /* request irq */
+ irq_id = platform_get_irq(pdev, 0);
+ if (irq_id < 0)
+ return dev_err_probe(dev, irq_id, "no irq found");
+
+ ret = devm_request_irq(dev, irq_id, mt8196_afe_irq_handler,
+ IRQF_TRIGGER_NONE,
+ "Afe_ISR_Handle", afe);
+ if (ret)
+ return dev_err_probe(dev, ret, "could not request_irq for Afe_ISR_Handle\n");
+
+ /* init sub_dais */
+ INIT_LIST_HEAD(&afe->sub_dais);
+
+ for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
+ ret = dai_register_cbs[i](afe);
+ if (ret)
+ return dev_err_probe(dev, ret, "dai register i %d fail\n", i);
+ }
+
+ /* init dai_driver and component_driver */
+ ret = mtk_afe_combine_sub_dai(afe);
+ if (ret)
+ return dev_err_probe(dev, ret, "mtk_afe_combine_sub_dai fail\n");
+
+ /* others */
+ afe->mtk_afe_hardware = &mt8196_afe_hardware;
+ afe->memif_fs = mt8196_memif_fs;
+ afe->irq_fs = mt8196_irq_fs;
+ afe->get_dai_fs = mt8196_get_dai_fs;
+ afe->get_memif_pbuf_size = mt8196_get_memif_pbuf_size;
+
+ afe->runtime_resume = mt8196_afe_runtime_resume;
+ afe->runtime_suspend = mt8196_afe_runtime_suspend;
+
+ ret = devm_pm_runtime_enable(dev);
+ if (ret)
+ return ret;
+
+/*
+ * Audio device is part of genpd. Registering it as a syscore device ensure
+ * the proper power-on sequence of the AFE device.
+ */
+ dev_pm_syscore_device(dev, true);
+
+ /* enable clock for regcache get default value from hw */
+ ret = pm_runtime_resume_and_get(dev);
+ if (ret)
+ return dev_err_probe(dev, ret, "failed to resume device\n");
+
+ afe->regmap = devm_regmap_init_mmio(dev, afe->base_addr,
+ &mt8196_afe_regmap_config);
+ if (IS_ERR(afe->regmap)) {
+ ret = PTR_ERR(afe->regmap);
+ goto err_pm_put;
+ }
+
+ ret = regmap_register_patch(afe->regmap, mt8196_cg_patch,
+ ARRAY_SIZE(mt8196_cg_patch));
+ if (ret < 0) {
+ dev_err(dev, "Failed to apply cg patch\n");
+ goto err_pm_put;
+ }
+
+ regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg);
+ regmap_write(afe->regmap, AFE_IRQ_MCU_EN, 0xffffffff);
+ regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &tmp_reg);
+
+ pm_runtime_put_sync(dev);
+
+ regcache_cache_only(afe->regmap, true);
+ regcache_mark_dirty(afe->regmap);
+
+ /* register component */
+ ret = devm_snd_soc_register_component(dev,
+ &mt8196_afe_component,
+ afe->dai_drivers,
+ afe->num_dai_drivers);
+ if (ret) {
+ dev_err(dev, "afe component err\n");
+ return ret;
+ }
+
+ return 0;
+
+err_pm_put:
+ pm_runtime_put_sync(dev);
+ return ret;
+}
+
+static void mt8196_afe_pcm_dev_remove(struct platform_device *pdev)
+{
+ struct mtk_base_afe *afe = platform_get_drvdata(pdev);
+ struct device *dev = &pdev->dev;
+
+ if (!pm_runtime_status_suspended(dev))
+ mt8196_afe_runtime_suspend(dev);
+
+ mt8196_afe_disable_main_clock(afe);
+ /* disable afe clock */
+ mt8196_afe_disable_reg_rw_clk(afe);
+}
+
+static const struct of_device_id mt8196_afe_pcm_dt_match[] = {
+ { .compatible = "mediatek,mt8196-afe", },
+ { /* sentinel */ },
+};
+MODULE_DEVICE_TABLE(of, mt8196_afe_pcm_dt_match);
+
+static const struct dev_pm_ops mt8196_afe_pm_ops = {
+ SET_RUNTIME_PM_OPS(mt8196_afe_runtime_suspend,
+ mt8196_afe_runtime_resume, NULL)
+};
+
+static struct platform_driver mt8196_afe_pcm_driver = {
+ .driver = {
+ .name = "mt8196-afe",
+ .of_match_table = mt8196_afe_pcm_dt_match,
+ .pm = &mt8196_afe_pm_ops,
+ },
+ .probe = mt8196_afe_pcm_dev_probe,
+ .remove = mt8196_afe_pcm_dev_remove,
+};
+module_platform_driver(mt8196_afe_pcm_driver);
+
+MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 8196");
+MODULE_AUTHOR("Darren Ye <darren.ye@mediatek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/mediatek/mt8196/mt8196-dai-adda.c b/sound/soc/mediatek/mt8196/mt8196-dai-adda.c
new file mode 100644
index 000000000000..9a91db4e79ae
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-dai-adda.c
@@ -0,0 +1,845 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI ADDA Control
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#include <linux/delay.h>
+#include <linux/regmap.h>
+
+#include "mt8196-afe-clk.h"
+#include "mt8196-afe-common.h"
+#include "mt8196-interconnection.h"
+
+enum {
+ UL_IIR_SW,
+ UL_IIR_5HZ,
+ UL_IIR_10HZ,
+ UL_IIR_25HZ,
+ UL_IIR_50HZ,
+ UL_IIR_75HZ,
+};
+
+enum {
+ MTK_AFE_ADDA_UL_RATE_8K,
+ MTK_AFE_ADDA_UL_RATE_16K,
+ MTK_AFE_ADDA_UL_RATE_32K,
+ MTK_AFE_ADDA_UL_RATE_48K,
+ MTK_AFE_ADDA_UL_RATE_96K,
+ MTK_AFE_ADDA_UL_RATE_192K,
+ MTK_AFE_ADDA_UL_RATE_48K_HD,
+};
+
+enum {
+ MTK_AFE_MTKAIF_RATE_8K,
+ MTK_AFE_MTKAIF_RATE_12K,
+ MTK_AFE_MTKAIF_RATE_16K,
+ MTK_AFE_MTKAIF_RATE_24K,
+ MTK_AFE_MTKAIF_RATE_32K,
+ MTK_AFE_MTKAIF_RATE_48K,
+ MTK_AFE_MTKAIF_RATE_64K,
+ MTK_AFE_MTKAIF_RATE_96K,
+ MTK_AFE_MTKAIF_RATE_128K,
+ MTK_AFE_MTKAIF_RATE_192K,
+ MTK_AFE_MTKAIF_RATE_256K,
+ MTK_AFE_MTKAIF_RATE_384K,
+ MTK_AFE_MTKAIF_RATE_11K = 0x10,
+ MTK_AFE_MTKAIF_RATE_22K,
+ MTK_AFE_MTKAIF_RATE_44K,
+ MTK_AFE_MTKAIF_RATE_88K,
+ MTK_AFE_MTKAIF_RATE_176K,
+ MTK_AFE_MTKAIF_RATE_352K,
+};
+
+struct mtk_afe_adda_priv {
+ int dl_rate;
+ int ul_rate;
+};
+
+static unsigned int adda_ul_rate_transform(struct mtk_base_afe *afe,
+ unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return MTK_AFE_ADDA_UL_RATE_8K;
+ case 16000:
+ return MTK_AFE_ADDA_UL_RATE_16K;
+ case 32000:
+ return MTK_AFE_ADDA_UL_RATE_32K;
+ case 48000:
+ return MTK_AFE_ADDA_UL_RATE_48K;
+ case 96000:
+ return MTK_AFE_ADDA_UL_RATE_96K;
+ case 192000:
+ return MTK_AFE_ADDA_UL_RATE_192K;
+ default:
+ dev_warn(afe->dev, "rate %d invalid, use 48kHz!!!\n", rate);
+ return MTK_AFE_ADDA_UL_RATE_48K;
+ }
+}
+
+static unsigned int mtkaif_rate_transform(struct mtk_base_afe *afe,
+ unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return MTK_AFE_MTKAIF_RATE_8K;
+ case 11025:
+ return MTK_AFE_MTKAIF_RATE_11K;
+ case 12000:
+ return MTK_AFE_MTKAIF_RATE_12K;
+ case 16000:
+ return MTK_AFE_MTKAIF_RATE_16K;
+ case 22050:
+ return MTK_AFE_MTKAIF_RATE_22K;
+ case 24000:
+ return MTK_AFE_MTKAIF_RATE_24K;
+ case 32000:
+ return MTK_AFE_MTKAIF_RATE_32K;
+ case 44100:
+ return MTK_AFE_MTKAIF_RATE_44K;
+ case 48000:
+ return MTK_AFE_MTKAIF_RATE_48K;
+ case 96000:
+ return MTK_AFE_MTKAIF_RATE_96K;
+ case 192000:
+ return MTK_AFE_MTKAIF_RATE_192K;
+ default:
+ dev_warn(afe->dev, "rate %d invalid, use 48kHz!!!\n", rate);
+ return MTK_AFE_MTKAIF_RATE_48K;
+ }
+}
+
+enum {
+ SUPPLY_SEQ_ADDA_AFE_ON,
+ SUPPLY_SEQ_ADDA_FIFO,
+ SUPPLY_SEQ_ADDA_AP_DMIC,
+ SUPPLY_SEQ_ADDA_UL_ON,
+};
+
+static int mtk_adda_ul_src_set_dmic_phase_sync(struct mtk_base_afe *afe)
+{
+ dev_dbg(afe->dev, "set dmic phase sync\n");
+ // ul0~1
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+ UL0_PHASE_SYNC_HCLK_SET_MASK_SFT,
+ 0x1 << UL0_PHASE_SYNC_HCLK_SET_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+ UL0_PHASE_SYNC_FCLK_SET_MASK_SFT,
+ 0x1 << UL0_PHASE_SYNC_FCLK_SET_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+ UL1_PHASE_SYNC_HCLK_SET_MASK_SFT,
+ 0x1 << UL1_PHASE_SYNC_HCLK_SET_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+ UL1_PHASE_SYNC_FCLK_SET_MASK_SFT,
+ 0x1 << UL1_PHASE_SYNC_FCLK_SET_SFT);
+ // dmic 0
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+ DMIC0_PHASE_SYNC_FCLK_SET_MASK_SFT,
+ 0x1 << DMIC0_PHASE_SYNC_FCLK_SET_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+ DMIC0_PHASE_SYNC_HCLK_SET_MASK_SFT,
+ 0x1 << DMIC0_PHASE_SYNC_HCLK_SET_SFT);
+ // dmic 1
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+ DMIC1_PHASE_SYNC_FCLK_SET_MASK_SFT,
+ 0x1 << DMIC1_PHASE_SYNC_FCLK_SET_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+ DMIC1_PHASE_SYNC_HCLK_SET_MASK_SFT,
+ 0x1 << DMIC1_PHASE_SYNC_HCLK_SET_SFT);
+ // ul0~1 phase sync clock
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ DMIC1_PHASE_HCLK_SEL_MASK_SFT,
+ 0x1 << DMIC1_PHASE_HCLK_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ DMIC1_PHASE_FCLK_SEL_MASK_SFT,
+ 0x1 << DMIC1_PHASE_FCLK_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ DMIC0_PHASE_HCLK_SEL_MASK_SFT,
+ 0x1 << DMIC0_PHASE_HCLK_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ DMIC0_PHASE_FCLK_SEL_MASK_SFT,
+ 0x1 << DMIC0_PHASE_FCLK_SEL_SFT);
+ // dmic 0
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ UL1_PHASE_HCLK_SEL_MASK_SFT,
+ 0x2 << UL1_PHASE_HCLK_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ UL1_PHASE_FCLK_SEL_MASK_SFT,
+ 0x2 << UL1_PHASE_FCLK_SEL_SFT);
+ // dmic 1
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ UL0_PHASE_HCLK_SEL_MASK_SFT,
+ 0x2 << UL0_PHASE_HCLK_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ UL0_PHASE_FCLK_SEL_MASK_SFT,
+ 0x2 << UL0_PHASE_FCLK_SEL_SFT);
+
+ return 0;
+}
+
+static int mtk_adda_ul_src_set_dmic_phase_sync_clock(struct mtk_base_afe *afe)
+{
+ dev_dbg(afe->dev, "dmic turn on phase sync clk\n");
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ UL_PHASE_SYNC_HCLK_1_ON_MASK_SFT,
+ 0x1 << UL_PHASE_SYNC_HCLK_1_ON_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ UL_PHASE_SYNC_HCLK_0_ON_MASK_SFT,
+ 0x1 << UL_PHASE_SYNC_HCLK_0_ON_SFT);
+
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ UL_PHASE_SYNC_FCLK_1_ON_MASK_SFT,
+ 0x1 << UL_PHASE_SYNC_FCLK_1_ON_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON0,
+ UL_PHASE_SYNC_FCLK_0_ON_MASK_SFT,
+ 0x1 << UL_PHASE_SYNC_FCLK_0_ON_SFT);
+
+ return 0;
+}
+
+static int mtk_adda_ul_src_enable_dmic(struct mtk_base_afe *afe, int id)
+{
+ unsigned int reg_con0 = 0, reg_con1 = 0;
+
+ dev_dbg(afe->dev, "id: %d\n", id);
+
+ switch (id) {
+ case MT8196_DAI_ADDA:
+ case MT8196_DAI_AP_DMIC:
+ reg_con0 = AFE_ADDA_UL0_SRC_CON0;
+ reg_con1 = AFE_ADDA_UL0_SRC_CON1;
+ break;
+ case MT8196_DAI_ADDA_CH34:
+ case MT8196_DAI_AP_DMIC_CH34:
+ reg_con0 = AFE_ADDA_UL1_SRC_CON0;
+ reg_con1 = AFE_ADDA_UL1_SRC_CON1;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (id) {
+ case MT8196_DAI_AP_DMIC:
+ dev_dbg(afe->dev, "clear mtkaifv4 ul ch1ch2 mux\n");
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT,
+ 0x0 << MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT);
+ break;
+ case MT8196_DAI_AP_DMIC_CH34:
+ dev_dbg(afe->dev, "clear mtkaifv4 ul ch3ch4 mux\n");
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT,
+ 0x0 << MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* choose Phase */
+ regmap_update_bits(afe->regmap, reg_con0,
+ UL_DMIC_PHASE_SEL_CH1_MASK_SFT,
+ 0x0 << UL_DMIC_PHASE_SEL_CH1_SFT);
+ regmap_update_bits(afe->regmap, reg_con0,
+ UL_DMIC_PHASE_SEL_CH2_MASK_SFT,
+ 0x4 << UL_DMIC_PHASE_SEL_CH2_SFT);
+
+ /* dmic mode, 3.25M*/
+ regmap_update_bits(afe->regmap, reg_con0,
+ DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT,
+ 0x0);
+ regmap_update_bits(afe->regmap, reg_con0,
+ DMIC_LOW_POWER_MODE_CTL_MASK_SFT,
+ 0x0);
+
+ /* turn on dmic, ch1, ch2 */
+ regmap_update_bits(afe->regmap, reg_con0,
+ UL_SDM_3_LEVEL_CTL_MASK_SFT,
+ 0x1 << UL_SDM_3_LEVEL_CTL_SFT);
+ regmap_update_bits(afe->regmap, reg_con0,
+ UL_MODE_3P25M_CH1_CTL_MASK_SFT,
+ 0x1 << UL_MODE_3P25M_CH1_CTL_SFT);
+ regmap_update_bits(afe->regmap, reg_con0,
+ UL_MODE_3P25M_CH2_CTL_MASK_SFT,
+ 0x1 << UL_MODE_3P25M_CH2_CTL_SFT);
+
+ /* ul gain: gain = 0x7fff/positive_gain = 0x0/gain_mode = 0x10 */
+ regmap_update_bits(afe->regmap, reg_con1,
+ ADDA_UL_GAIN_VALUE_MASK_SFT,
+ 0x7fff << ADDA_UL_GAIN_VALUE_SFT);
+ regmap_update_bits(afe->regmap, reg_con1,
+ ADDA_UL_POSTIVEGAIN_MASK_SFT,
+ 0x0 << ADDA_UL_POSTIVEGAIN_SFT);
+ /* gain_mode = 0x10: Add 0.5 gain at CIC output */
+ regmap_update_bits(afe->regmap, reg_con1,
+ GAIN_MODE_MASK_SFT,
+ 0x02 << GAIN_MODE_SFT);
+ return 0;
+}
+
+static int mtk_adda_sleep_on_pmd_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+ dev_dbg(afe->dev, "name %s, event 0x%x\n", w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ /* should delayed 1/fs(smallest is 8k) = 125us before afe off */
+ usleep_range(120, 130);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+/* ADDA UL MUX */
+#define ADDA_UL_MUX_MASK 0x3
+enum {
+ ADDA_UL_MUX_MTKAIF = 0,
+ ADDA_UL_MUX_AP_DMIC,
+ ADDA_UL_MUX_AP_DMIC_MULTICH,
+};
+
+static const char *const adda_ul_mux_map[] = {
+ "MTKAIF", "AP_DMIC", "AP_DMIC_MULTI_CH",
+};
+
+static int adda_ul_map_value[] = {
+ ADDA_UL_MUX_MTKAIF,
+ ADDA_UL_MUX_AP_DMIC,
+ ADDA_UL_MUX_AP_DMIC_MULTICH,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(adda_ul_mux_map_enum,
+ SND_SOC_NOPM,
+ 0,
+ ADDA_UL_MUX_MASK,
+ adda_ul_mux_map,
+ adda_ul_map_value);
+
+static const struct snd_kcontrol_new adda_ul_mux_control =
+ SOC_DAPM_ENUM("ADDA_UL_MUX Select", adda_ul_mux_map_enum);
+
+static const struct snd_kcontrol_new adda_ch34_ul_mux_control =
+ SOC_DAPM_ENUM("ADDA_CH34_UL_MUX Select", adda_ul_mux_map_enum);
+
+static const struct snd_soc_dapm_widget mtk_dai_adda_widgets[] = {
+ /* inter-connections */
+ SND_SOC_DAPM_SUPPLY_S("ADDA Enable", SUPPLY_SEQ_ADDA_AFE_ON,
+ AUDIO_ENGEN_CON0, AUDIO_F3P25M_EN_ON_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ADDA Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+ AFE_ADDA_UL0_SRC_CON0,
+ UL_SRC_ON_TMP_CTL_SFT, 0,
+ mtk_adda_sleep_on_pmd_event,
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("ADDA CH34 Capture Enable", SUPPLY_SEQ_ADDA_UL_ON,
+ AFE_ADDA_UL1_SRC_CON0,
+ UL_SRC_ON_TMP_CTL_SFT, 0,
+ mtk_adda_sleep_on_pmd_event,
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("AP_DMIC_EN", SUPPLY_SEQ_ADDA_AP_DMIC,
+ AFE_ADDA_UL0_SRC_CON0,
+ UL_AP_DMIC_ON_SFT, 0,
+ mtk_adda_sleep_on_pmd_event,
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("AP_DMIC_CH34_EN", SUPPLY_SEQ_ADDA_AP_DMIC,
+ AFE_ADDA_UL1_SRC_CON0,
+ UL_AP_DMIC_ON_SFT, 0,
+ mtk_adda_sleep_on_pmd_event,
+ SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S("ADDA_FIFO", SUPPLY_SEQ_ADDA_FIFO,
+ AFE_ADDA_UL0_SRC_CON1,
+ FIFO_SOFT_RST_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("ADDA_CH34_FIFO", SUPPLY_SEQ_ADDA_FIFO,
+ AFE_ADDA_UL1_SRC_CON1,
+ FIFO_SOFT_RST_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_MUX("ADDA_UL_Mux", SND_SOC_NOPM, 0, 0,
+ &adda_ul_mux_control),
+ SND_SOC_DAPM_MUX("ADDA_CH34_UL_Mux", SND_SOC_NOPM, 0, 0,
+ &adda_ch34_ul_mux_control),
+ SND_SOC_DAPM_INPUT("AP_DMIC_INPUT"),
+};
+
+static const struct snd_soc_dapm_route mtk_dai_adda_routes[] = {
+ /* capture */
+ {"ADDA_UL_Mux", "MTKAIF", "ADDA Capture"},
+ {"ADDA_UL_Mux", "AP_DMIC", "AP DMIC Capture"},
+ {"ADDA_UL_Mux", "AP_DMIC_MULTI_CH", "AP DMIC MULTICH Capture"},
+
+ {"ADDA_CH34_UL_Mux", "MTKAIF", "ADDA CH34 Capture"},
+ {"ADDA_CH34_UL_Mux", "AP_DMIC", "AP DMIC CH34 Capture"},
+ {"ADDA_CH34_UL_Mux", "AP_DMIC_MULTI_CH", "AP DMIC MULTICH Capture"},
+
+ {"AP DMIC Capture", NULL, "ADDA Enable"},
+ {"AP DMIC Capture", NULL, "ADDA Capture Enable"},
+ {"AP DMIC Capture", NULL, "ADDA_FIFO"},
+ {"AP DMIC Capture", NULL, "AP_DMIC_EN"},
+
+ {"AP DMIC CH34 Capture", NULL, "ADDA Enable"},
+ {"AP DMIC CH34 Capture", NULL, "ADDA CH34 Capture Enable"},
+ {"AP DMIC CH34 Capture", NULL, "ADDA_CH34_FIFO"},
+ {"AP DMIC CH34 Capture", NULL, "AP_DMIC_CH34_EN"},
+
+ {"AP DMIC MULTICH Capture", NULL, "ADDA Enable"},
+ {"AP DMIC MULTICH Capture", NULL, "ADDA Capture Enable"},
+ {"AP DMIC MULTICH Capture", NULL, "ADDA CH34 Capture Enable"},
+ {"AP DMIC MULTICH Capture", NULL, "ADDA_FIFO"},
+ {"AP DMIC MULTICH Capture", NULL, "ADDA_CH34_FIFO"},
+ {"AP DMIC MULTICH Capture", NULL, "AP_DMIC_EN"},
+ {"AP DMIC MULTICH Capture", NULL, "AP_DMIC_CH34_EN"},
+
+ {"AP DMIC Capture", NULL, "AP_DMIC_INPUT"},
+ {"AP DMIC CH34 Capture", NULL, "AP_DMIC_INPUT"},
+ {"AP DMIC MULTICH Capture", NULL, "AP_DMIC_INPUT"},
+};
+
+/* dai ops */
+static int set_playback_hw_params(struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ unsigned int rate = params_rate(params);
+ struct mtk_afe_adda_priv *adda_priv;
+ unsigned int mtkaif_rate = 0;
+ int id = dai->id;
+
+ adda_priv = afe_priv->dai_priv[id];
+ if (!adda_priv)
+ return -EINVAL;
+
+ adda_priv->dl_rate = rate;
+
+ /* get mtkaif dl rate */
+ mtkaif_rate = mtkaif_rate_transform(afe, adda_priv->dl_rate);
+
+ if (id == MT8196_DAI_ADDA) {
+ /* MTKAIF sample rate config */
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+ MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT,
+ mtkaif_rate << MTKAIFV4_TXIF_INPUT_MODE_SFT);
+ /* AFE_ADDA_MTKAIFV4_TX_CFG0 */
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+ MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT,
+ 0x0 << MTKAIFV4_TXIF_FOUR_CHANNEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+ MTKAIFV4_ADDA_OUT_EN_SEL_MASK_SFT,
+ 0x1 << MTKAIFV4_ADDA_OUT_EN_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+ MTKAIFV4_ADDA6_OUT_EN_SEL_MASK_SFT,
+ 0x1 << MTKAIFV4_ADDA6_OUT_EN_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+ MTKAIFV4_TXIF_V4_MASK_SFT,
+ 0x1 << MTKAIFV4_TXIF_V4_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_TX_CFG0,
+ MTKAIFV4_TXIF_EN_SEL_MASK_SFT,
+ 0x0 << MTKAIFV4_TXIF_EN_SEL_SFT);
+ /* clean predistortion */
+ } else {
+ /* MTKAIF sample rate config */
+ regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_TX_CFG0,
+ ADDA6_MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT,
+ mtkaif_rate << ADDA6_MTKAIFV4_TXIF_INPUT_MODE_SFT);
+ /* AFE_ADDA6_MTKAIFV4_TX_CFG0 */
+ regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_TX_CFG0,
+ ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT,
+ 0x0 << ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_TX_CFG0,
+ ADDA6_MTKAIFV4_TXIF_EN_SEL_MASK_SFT,
+ 0x1 << ADDA6_MTKAIFV4_TXIF_EN_SEL_SFT);
+ }
+
+ return 0;
+};
+
+static int set_capture_hw_params(struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ unsigned int rate = params_rate(params);
+ struct mtk_afe_adda_priv *adda_priv;
+ unsigned int voice_mode = 0;
+ unsigned int ul_src_con0 = 0;
+ unsigned int mtkaif_rate = 0;
+ int id = dai->id;
+
+ adda_priv = afe_priv->dai_priv[id];
+ if (!adda_priv)
+ return -EINVAL;
+
+ adda_priv->ul_rate = rate;
+
+ /* get mtkaif dl rate */
+ mtkaif_rate = mtkaif_rate_transform(afe, adda_priv->ul_rate);
+
+ voice_mode = adda_ul_rate_transform(afe, rate);
+
+ ul_src_con0 |= (voice_mode << 17) & (0x7 << 17);
+
+ /* enable iir */
+ ul_src_con0 |= (1 << UL_IIR_ON_TMP_CTL_SFT) &
+ UL_IIR_ON_TMP_CTL_MASK_SFT;
+ ul_src_con0 |= (UL_IIR_SW << UL_IIRMODE_CTL_SFT) &
+ UL_IIRMODE_CTL_MASK_SFT;
+
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT,
+ mtkaif_rate << MTKAIFV4_RXIF_INPUT_MODE_SFT);
+
+ regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+ ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT,
+ mtkaif_rate << ADDA6_MTKAIFV4_RXIF_INPUT_MODE_SFT);
+
+ switch (id) {
+ case MT8196_DAI_ADDA:
+ case MT8196_DAI_AP_DMIC:
+ case MT8196_DAI_AP_DMIC_MULTICH:
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT,
+ mtkaif_rate << MTKAIFV4_RXIF_INPUT_MODE_SFT);
+ /* AFE_ADDA_MTKAIFV4_RX_CFG0 */
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT,
+ 0x1 << MTKAIFV4_RXIF_FOUR_CHANNEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_RXIF_EN_SEL_MASK_SFT,
+ 0x0 << MTKAIFV4_RXIF_EN_SEL_SFT);
+ /* [28] loopback mode
+ * 0: loopback adda tx to adda rx
+ * 1: loopback adda6 tx to adda rx
+ */
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_TXIF_EN_SEL_MASK_SFT,
+ 0x0 << MTKAIFV4_TXIF_EN_SEL_SFT);
+
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT,
+ 0x1 << MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT,
+ 0x1 << MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT);
+
+ /* 35Hz @ 48k */
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_02_01, 0x00000000);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_04_03, 0x00003FB8);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_06_05, 0x3FB80000);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_08_07, 0x3FB80000);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_10_09, 0x0000C048);
+
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_SRC_CON0, ul_src_con0);
+
+ /* mtkaif_rxif_data_mode = 0, amic */
+ regmap_update_bits(afe->regmap,
+ AFE_MTKAIF1_RX_CFG0,
+ 0x1 << 0,
+ 0x0 << 0);
+
+ /* 35Hz @ 48k */
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL0_IIR_COEF_02_01, 0x00000000);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL0_IIR_COEF_04_03, 0x00003FB8);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL0_IIR_COEF_06_05, 0x3FB80000);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL0_IIR_COEF_08_07, 0x3FB80000);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL0_IIR_COEF_10_09, 0x0000C048);
+
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL0_SRC_CON0, ul_src_con0);
+
+ /* mtkaif_rxif_data_mode = 0, amic */
+ regmap_update_bits(afe->regmap,
+ AFE_MTKAIF0_RX_CFG0,
+ 0x1 << 0,
+ 0x0 << 0);
+ break;
+ case MT8196_DAI_ADDA_CH34:
+ case MT8196_DAI_AP_DMIC_CH34:
+ /* AFE_ADDA_MTKAIFV4_RX_CFG0 */
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT,
+ 0x1 << MTKAIFV4_RXIF_FOUR_CHANNEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_RXIF_EN_SEL_MASK_SFT,
+ 0x0 << MTKAIFV4_RXIF_EN_SEL_SFT);
+
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT,
+ 0x1 << MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT,
+ 0x1 << MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT);
+
+ /* 35Hz @ 48k */
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_02_01, 0x00000000);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_04_03, 0x00003FB8);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_06_05, 0x3FB80000);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_08_07, 0x3FB80000);
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_IIR_COEF_10_09, 0x0000C048);
+
+ regmap_write(afe->regmap,
+ AFE_ADDA_UL1_SRC_CON0, ul_src_con0);
+
+ /* mtkaif_rxif_data_mode = 0, amic */
+ regmap_update_bits(afe->regmap,
+ AFE_MTKAIF1_RX_CFG0,
+ 0x1 << 0,
+ 0x0 << 0);
+ break;
+ case MT8196_DAI_ADDA_CH56:
+ regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+ ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT,
+ mtkaif_rate << ADDA6_MTKAIFV4_RXIF_INPUT_MODE_SFT);
+ /* AFE_ADDA6_MTKAIFV4_RX_CFG0 */
+ regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+ ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT,
+ 0x1 << ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA_MTKAIFV4_RX_CFG0,
+ MTKAIFV4_UL_CH5CH6_IN_EN_SEL_MASK_SFT,
+ 0x1 << MTKAIFV4_UL_CH5CH6_IN_EN_SEL_SFT);
+ regmap_update_bits(afe->regmap, AFE_ADDA6_MTKAIFV4_RX_CFG0,
+ ADDA6_MTKAIFV4_RXIF_EN_SEL_MASK_SFT,
+ 0x1 << ADDA6_MTKAIFV4_RXIF_EN_SEL_SFT);
+ break;
+ default:
+ break;
+ }
+
+ /* ap dmic */
+ switch (id) {
+ case MT8196_DAI_AP_DMIC:
+ case MT8196_DAI_AP_DMIC_CH34:
+ mtk_adda_ul_src_enable_dmic(afe, id);
+ break;
+ case MT8196_DAI_AP_DMIC_MULTICH:
+ regmap_update_bits(afe->regmap, AFE_ADDA_ULSRC_PHASE_CON1,
+ DMIC_CLK_PHASE_SYNC_SET_MASK_SFT,
+ 0x1 << DMIC_CLK_PHASE_SYNC_SET_SFT);
+ mtk_adda_ul_src_set_dmic_phase_sync(afe);
+ mtk_adda_ul_src_enable_dmic(afe, MT8196_DAI_AP_DMIC);
+ mtk_adda_ul_src_enable_dmic(afe, MT8196_DAI_AP_DMIC_CH34);
+ mtk_adda_ul_src_set_dmic_phase_sync_clock(afe);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+};
+
+static int mtk_dai_adda_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int id = dai->id;
+
+ if (id >= MT8196_DAI_NUM || id < 0)
+ return -EINVAL;
+
+ dev_dbg(afe->dev, "id %d, stream %d, rate %d\n",
+ id, substream->stream, params_rate(params));
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ return set_playback_hw_params(params, dai);
+ else
+ return set_capture_hw_params(params, dai);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_adda_ops = {
+ .hw_params = mtk_dai_adda_hw_params,
+};
+
+/* dai driver */
+#define MTK_ADDA_PLAYBACK_RATES (SNDRV_PCM_RATE_8000_48000 |\
+ SNDRV_PCM_RATE_96000 |\
+ SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_CAPTURE_RATES (SNDRV_PCM_RATE_8000 |\
+ SNDRV_PCM_RATE_16000 |\
+ SNDRV_PCM_RATE_32000 |\
+ SNDRV_PCM_RATE_48000 |\
+ SNDRV_PCM_RATE_96000 |\
+ SNDRV_PCM_RATE_192000)
+
+#define MTK_ADDA_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_adda_driver[] = {
+ {
+ .name = "ADDA",
+ .id = MT8196_DAI_ADDA,
+ .playback = {
+ .stream_name = "ADDA Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_PLAYBACK_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .capture = {
+ .stream_name = "ADDA Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_CAPTURE_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .ops = &mtk_dai_adda_ops,
+ },
+ {
+ .name = "ADDA_CH34",
+ .id = MT8196_DAI_ADDA_CH34,
+ .playback = {
+ .stream_name = "ADDA CH34 Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_PLAYBACK_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .capture = {
+ .stream_name = "ADDA CH34 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_CAPTURE_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .ops = &mtk_dai_adda_ops,
+ },
+ {
+ .name = "ADDA_CH56",
+ .id = MT8196_DAI_ADDA_CH56,
+ .capture = {
+ .stream_name = "ADDA CH56 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_CAPTURE_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .ops = &mtk_dai_adda_ops,
+ },
+ {
+ .name = "AP_DMIC",
+ .id = MT8196_DAI_AP_DMIC,
+ .capture = {
+ .stream_name = "AP DMIC Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_CAPTURE_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .ops = &mtk_dai_adda_ops,
+ },
+ {
+ .name = "AP_DMIC_CH34",
+ .id = MT8196_DAI_AP_DMIC_CH34,
+ .capture = {
+ .stream_name = "AP DMIC CH34 Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = MTK_ADDA_CAPTURE_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .ops = &mtk_dai_adda_ops,
+ },
+ /*
+ * Multich DMIC combines two DMIC controllers for use together,
+ * so AP_DMIC and Multich DMIC cannot be used at the same time.
+ */
+ {
+ .name = "AP_DMIC_MULTICH",
+ .id = MT8196_DAI_AP_DMIC_MULTICH,
+ .capture = {
+ .stream_name = "AP DMIC MULTICH Capture",
+ .channels_min = 1,
+ .channels_max = 4,
+ .rates = MTK_ADDA_CAPTURE_RATES,
+ .formats = MTK_ADDA_FORMATS,
+ },
+ .ops = &mtk_dai_adda_ops,
+ },
+};
+
+static int init_adda_priv_data(struct mtk_base_afe *afe)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_afe_adda_priv *adda_priv;
+ static const int adda_dai_list[] = {
+ MT8196_DAI_ADDA,
+ MT8196_DAI_ADDA_CH34,
+ MT8196_DAI_ADDA_CH56,
+ MT8196_DAI_AP_DMIC_MULTICH
+ };
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(adda_dai_list); i++) {
+ adda_priv = devm_kzalloc(afe->dev,
+ sizeof(struct mtk_afe_adda_priv),
+ GFP_KERNEL);
+ if (!adda_priv)
+ return -ENOMEM;
+
+ afe_priv->dai_priv[adda_dai_list[i]] = adda_priv;
+ }
+
+ /* ap dmic priv share with adda */
+ afe_priv->dai_priv[MT8196_DAI_AP_DMIC] =
+ afe_priv->dai_priv[MT8196_DAI_ADDA];
+ afe_priv->dai_priv[MT8196_DAI_AP_DMIC_CH34] =
+ afe_priv->dai_priv[MT8196_DAI_ADDA_CH34];
+
+ return 0;
+}
+
+int mt8196_dai_adda_register(struct mtk_base_afe *afe)
+{
+ struct mtk_base_afe_dai *dai;
+ int ret;
+
+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ dai->dai_drivers = mtk_dai_adda_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_adda_driver);
+ dai->dapm_widgets = mtk_dai_adda_widgets;
+ dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_adda_widgets);
+ dai->dapm_routes = mtk_dai_adda_routes;
+ dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_adda_routes);
+
+ ret = init_adda_priv_data(afe);
+ if (ret)
+ return ret;
+
+ list_add(&dai->list, &afe->sub_dais);
+
+ return 0;
+}
+
diff --git a/sound/soc/mediatek/mt8196/mt8196-dai-i2s.c b/sound/soc/mediatek/mt8196/mt8196-dai-i2s.c
new file mode 100644
index 000000000000..ef5cde0ba829
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-dai-i2s.c
@@ -0,0 +1,2613 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI I2S Control
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#include <linux/bitops.h>
+#include <linux/regmap.h>
+
+#include <sound/pcm_params.h>
+
+#include "mt8196-afe-clk.h"
+#include "mt8196-afe-common.h"
+#include "mt8196-interconnection.h"
+
+#include "../common/mtk-afe-fe-dai.h"
+
+#define ETDM_22M_CLOCK_THRES 11289600
+
+enum {
+ ETDM_CLK_SOURCE_H26M,
+ ETDM_CLK_SOURCE_APLL,
+ ETDM_CLK_SOURCE_SPDIF,
+ ETDM_CLK_SOURCE_HDMI,
+ ETDM_CLK_SOURCE_EARC,
+ ETDM_CLK_SOURCE_LINEIN,
+};
+
+enum {
+ ETDM_RELATCH_SEL_H26M,
+ ETDM_RELATCH_SEL_APLL,
+};
+
+enum {
+ ETDM_RATE_8K,
+ ETDM_RATE_12K,
+ ETDM_RATE_16K,
+ ETDM_RATE_24K,
+ ETDM_RATE_32K,
+ ETDM_RATE_48K,
+ ETDM_RATE_64K,
+ ETDM_RATE_96K,
+ ETDM_RATE_128K,
+ ETDM_RATE_192K,
+ ETDM_RATE_256K,
+ ETDM_RATE_384K,
+ ETDM_RATE_11025 = 16,
+ ETDM_RATE_22050,
+ ETDM_RATE_44100,
+ ETDM_RATE_88200,
+ ETDM_RATE_176400,
+ ETDM_RATE_352800,
+};
+
+enum {
+ ETDM_CONN_8K,
+ ETDM_CONN_11K,
+ ETDM_CONN_12K,
+ ETDM_CONN_16K = 4,
+ ETDM_CONN_22K,
+ ETDM_CONN_24K,
+ ETDM_CONN_32K = 8,
+ ETDM_CONN_44K,
+ ETDM_CONN_48K,
+ ETDM_CONN_88K = 13,
+ ETDM_CONN_96K,
+ ETDM_CONN_176K = 17,
+ ETDM_CONN_192K,
+ ETDM_CONN_352K = 21,
+ ETDM_CONN_384K,
+};
+
+enum {
+ ETDM_WLEN_8_BIT = 0x7,
+ ETDM_WLEN_16_BIT = 0xf,
+ ETDM_WLEN_32_BIT = 0x1f,
+};
+
+enum {
+ ETDM_SLAVE_SEL_ETDMIN0_MASTER,
+ ETDM_SLAVE_SEL_ETDMIN0_SLAVE,
+ ETDM_SLAVE_SEL_ETDMIN1_MASTER,
+ ETDM_SLAVE_SEL_ETDMIN1_SLAVE,
+ ETDM_SLAVE_SEL_ETDMIN2_MASTER,
+ ETDM_SLAVE_SEL_ETDMIN2_SLAVE,
+ ETDM_SLAVE_SEL_ETDMIN3_MASTER,
+ ETDM_SLAVE_SEL_ETDMIN3_SLAVE,
+ ETDM_SLAVE_SEL_ETDMOUT0_MASTER,
+ ETDM_SLAVE_SEL_ETDMOUT0_SLAVE,
+ ETDM_SLAVE_SEL_ETDMOUT1_MASTER,
+ ETDM_SLAVE_SEL_ETDMOUT1_SLAVE,
+ ETDM_SLAVE_SEL_ETDMOUT2_MASTER,
+ ETDM_SLAVE_SEL_ETDMOUT2_SLAVE,
+ ETDM_SLAVE_SEL_ETDMOUT3_MASTER,
+ ETDM_SLAVE_SEL_ETDMOUT3_SLAVE,
+};
+
+enum {
+ ETDM_SLAVE_SEL_ETDMIN4_MASTER,
+ ETDM_SLAVE_SEL_ETDMIN4_SLAVE,
+ ETDM_SLAVE_SEL_ETDMIN5_MASTER,
+ ETDM_SLAVE_SEL_ETDMIN5_SLAVE,
+ ETDM_SLAVE_SEL_ETDMIN6_MASTER,
+ ETDM_SLAVE_SEL_ETDMIN6_SLAVE,
+ ETDM_SLAVE_SEL_ETDMIN7_MASTER,
+ ETDM_SLAVE_SEL_ETDMIN7_SLAVE,
+ ETDM_SLAVE_SEL_ETDMOUT4_MASTER,
+ ETDM_SLAVE_SEL_ETDMOUT4_SLAVE,
+ ETDM_SLAVE_SEL_ETDMOUT5_MASTER,
+ ETDM_SLAVE_SEL_ETDMOUT5_SLAVE,
+ ETDM_SLAVE_SEL_ETDMOUT6_MASTER,
+ ETDM_SLAVE_SEL_ETDMOUT6_SLAVE,
+ ETDM_SLAVE_SEL_ETDMOUT7_MASTER,
+ ETDM_SLAVE_SEL_ETDMOUT7_SLAVE,
+};
+
+enum {
+ MTK_DAI_ETDM_FORMAT_I2S,
+ MTK_DAI_ETDM_FORMAT_LJ,
+ MTK_DAI_ETDM_FORMAT_RJ,
+ MTK_DAI_ETDM_FORMAT_EIAJ,
+ MTK_DAI_ETDM_FORMAT_DSPA,
+ MTK_DAI_ETDM_FORMAT_DSPB,
+};
+
+static unsigned int get_etdm_wlen(snd_pcm_format_t format)
+{
+ return snd_pcm_format_physical_width(format) < 16 ?
+ ETDM_WLEN_16_BIT : ETDM_WLEN_32_BIT;
+}
+
+static unsigned int get_etdm_lrck_width(snd_pcm_format_t format)
+{
+ /* The valid data bit number should be large than 7 due to hardware limitation. */
+ return snd_pcm_format_physical_width(format) - 1;
+}
+
+static unsigned int get_etdm_rate(unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return ETDM_RATE_8K;
+ case 12000:
+ return ETDM_RATE_12K;
+ case 16000:
+ return ETDM_RATE_16K;
+ case 24000:
+ return ETDM_RATE_24K;
+ case 32000:
+ return ETDM_RATE_32K;
+ case 48000:
+ return ETDM_RATE_48K;
+ case 64000:
+ return ETDM_RATE_64K;
+ case 96000:
+ return ETDM_RATE_96K;
+ case 128000:
+ return ETDM_RATE_128K;
+ case 192000:
+ return ETDM_RATE_192K;
+ case 256000:
+ return ETDM_RATE_256K;
+ case 384000:
+ return ETDM_RATE_384K;
+ case 11025:
+ return ETDM_RATE_11025;
+ case 22050:
+ return ETDM_RATE_22050;
+ case 44100:
+ return ETDM_RATE_44100;
+ case 88200:
+ return ETDM_RATE_88200;
+ case 176400:
+ return ETDM_RATE_176400;
+ case 352800:
+ return ETDM_RATE_352800;
+ default:
+ return 0;
+ }
+}
+
+static unsigned int get_etdm_inconn_rate(unsigned int rate)
+{
+ switch (rate) {
+ case 8000:
+ return ETDM_CONN_8K;
+ case 12000:
+ return ETDM_CONN_12K;
+ case 16000:
+ return ETDM_CONN_16K;
+ case 24000:
+ return ETDM_CONN_24K;
+ case 32000:
+ return ETDM_CONN_32K;
+ case 48000:
+ return ETDM_CONN_48K;
+ case 96000:
+ return ETDM_CONN_96K;
+ case 192000:
+ return ETDM_CONN_192K;
+ case 384000:
+ return ETDM_CONN_384K;
+ case 11025:
+ return ETDM_CONN_11K;
+ case 22050:
+ return ETDM_CONN_22K;
+ case 44100:
+ return ETDM_CONN_44K;
+ case 88200:
+ return ETDM_CONN_88K;
+ case 176400:
+ return ETDM_CONN_176K;
+ case 352800:
+ return ETDM_CONN_352K;
+ default:
+ return 0;
+ }
+}
+
+struct mtk_afe_i2s_priv {
+ u8 id;
+ u32 rate; /* for determine which apll to use */
+ int low_jitter_en;
+ const char *share_property_name;
+ int share_i2s_id;
+ u32 mclk_rate;
+ u8 mclk_id;
+ u8 mclk_apll;
+ u8 ch_num;
+ u8 sync;
+ u8 ip_mode;
+ u8 format;
+};
+
+/* this enum is merely for mtk_afe_i2s_priv & mtk_base_etdm_data declare */
+enum {
+ DAI_I2SIN0,
+ DAI_I2SIN1,
+ DAI_I2SIN2,
+ DAI_I2SIN3,
+ DAI_I2SIN4,
+ DAI_I2SIN6,
+ DAI_I2SOUT0,
+ DAI_I2SOUT1,
+ DAI_I2SOUT2,
+ DAI_I2SOUT3,
+ DAI_I2SOUT4,
+ DAI_I2SOUT6,
+ DAI_FMI2S_MASTER,
+ DAI_I2S_NUM,
+};
+
+static bool is_etdm_in_pad_top(unsigned int dai_num)
+{
+ switch (dai_num) {
+ case DAI_I2SOUT4:
+ case DAI_I2SIN4:
+ return true;
+ default:
+ return false;
+ }
+}
+
+struct mtk_base_etdm_data {
+ u16 enable_reg;
+ u16 enable_mask;
+ u8 enable_shift;
+ u16 sync_reg;
+ u16 sync_mask;
+ u8 sync_shift;
+ u16 ch_reg;
+ u16 ch_mask;
+ u8 ch_shift;
+ u16 ip_mode_reg;
+ u16 ip_mode_mask;
+ u8 ip_mode_shift;
+ u16 init_count_reg;
+ u16 init_count_mask;
+ u8 init_count_shift;
+ u16 init_point_reg;
+ u16 init_point_mask;
+ u8 init_point_shift;
+ u16 lrck_reset_reg;
+ u16 lrck_reset_mask;
+ u8 lrck_reset_shift;
+ u16 clk_source_reg;
+ u16 clk_source_mask;
+ u8 clk_source_shift;
+ u16 ck_en_sel_reg;
+ u16 ck_en_sel_mask;
+ u8 ck_en_sel_shift;
+ u16 fs_timing_reg;
+ u16 fs_timing_mask;
+ u8 fs_timing_shift;
+ u16 relatch_en_sel_reg;
+ u16 relatch_en_sel_mask;
+ u8 relatch_en_sel_shift;
+ u16 use_afifo_reg;
+ u16 use_afifo_mask;
+ u8 use_afifo_shift;
+ u16 afifo_mode_reg;
+ u16 afifo_mode_mask;
+ u8 afifo_mode_shift;
+ u16 almost_end_ch_reg;
+ u16 almost_end_ch_mask;
+ u8 almost_end_ch_shift;
+ u16 almost_end_bit_reg;
+ u16 almost_end_bit_mask;
+ u8 almost_end_bit_shift;
+ u16 out2latch_time_reg;
+ u16 out2latch_time_mask;
+ u8 out2latch_time_shift;
+ u16 tdm_mode_reg;
+ u16 tdm_mode_mask;
+ u8 tdm_mode_shift;
+ u16 relatch_domain_sel_reg;
+ u16 relatch_domain_sel_mask;
+ u8 relatch_domain_sel_shift;
+ u16 bit_length_reg;
+ u16 bit_length_mask;
+ u8 bit_length_shift;
+ u16 word_length_reg;
+ u16 word_length_mask;
+ u8 word_length_shift;
+ u16 cowork_reg;
+ u16 cowork_mask;
+ u8 cowork_shift;
+ u32 cowork_val;
+ u16 in2latch_time_reg;
+ u16 in2latch_time_mask;
+ u8 in2latch_time_shift;
+ u16 pad_top_ck_en_reg;
+ u16 pad_top_ck_en_mask;
+ u8 pad_top_ck_en_shift;
+ u16 master_latch_reg;
+ u16 master_latch_mask;
+ u8 master_latch_shift;
+};
+
+/*
+ * _cfg_vlp_reg should be a variable or constant, not an expression
+ * with side effects.
+ */
+#define MTK_ETDM_IN_DATA(_id, _cowork, _cfg_vlp_reg) \
+ [DAI_I2SIN##_id] = { \
+ .enable_reg = ETDM_IN##_id##_CON0, \
+ .enable_mask = REG_ETDM_IN_EN_MASK, \
+ .enable_shift = REG_ETDM_IN_EN_SFT, \
+ .sync_reg = ETDM_IN##_id##_CON0, \
+ .sync_mask = REG_SYNC_MODE_MASK, \
+ .sync_shift = REG_SYNC_MODE_SFT, \
+ .ch_reg = ETDM_IN##_id##_CON0, \
+ .ch_mask = REG_CH_NUM_MASK, \
+ .ch_shift = REG_CH_NUM_SFT, \
+ .ip_mode_reg = ETDM_IN##_id##_CON2, \
+ .ip_mode_mask = REG_MULTI_IP_MODE_MASK, \
+ .ip_mode_shift = REG_MULTI_IP_MODE_SFT, \
+ .init_count_reg = ETDM_IN##_id##_CON1, \
+ .init_count_mask = REG_INITIAL_COUNT_MASK, \
+ .init_count_shift = REG_INITIAL_COUNT_SFT, \
+ .init_point_reg = ETDM_IN##_id##_CON1, \
+ .init_point_mask = REG_INITIAL_POINT_MASK, \
+ .init_point_shift = REG_INITIAL_POINT_SFT, \
+ .lrck_reset_reg = ETDM_IN##_id##_CON1, \
+ .lrck_reset_mask = REG_LRCK_RESET_MASK, \
+ .lrck_reset_shift = REG_LRCK_RESET_SFT, \
+ .clk_source_reg = ETDM_IN##_id##_CON2, \
+ .clk_source_mask = REG_CLOCK_SOURCE_SEL_MASK, \
+ .clk_source_shift = REG_CLOCK_SOURCE_SEL_SFT, \
+ .ck_en_sel_reg = ETDM_IN##_id##_CON2, \
+ .ck_en_sel_mask = REG_CK_EN_SEL_AUTO_MASK, \
+ .ck_en_sel_shift = REG_CK_EN_SEL_AUTO_SFT, \
+ .fs_timing_reg = ETDM_IN##_id##_CON3, \
+ .fs_timing_mask = REG_FS_TIMING_SEL_MASK, \
+ .fs_timing_shift = REG_FS_TIMING_SEL_SFT, \
+ .relatch_en_sel_reg = ETDM_IN##_id##_CON4, \
+ .relatch_en_sel_mask = REG_RELATCH_1X_EN_SEL_MASK, \
+ .relatch_en_sel_shift = REG_RELATCH_1X_EN_SEL_SFT, \
+ .use_afifo_reg = ETDM_IN##_id##_CON8, \
+ .use_afifo_mask = REG_ETDM_USE_AFIFO_MASK, \
+ .use_afifo_shift = REG_ETDM_USE_AFIFO_SFT, \
+ .afifo_mode_reg = ETDM_IN##_id##_CON8, \
+ .afifo_mode_mask = REG_AFIFO_MODE_MASK, \
+ .afifo_mode_shift = REG_AFIFO_MODE_SFT, \
+ .almost_end_ch_reg = ETDM_IN##_id##_CON9, \
+ .almost_end_ch_mask = REG_ALMOST_END_CH_COUNT_MASK, \
+ .almost_end_ch_shift = REG_ALMOST_END_CH_COUNT_SFT, \
+ .almost_end_bit_reg = ETDM_IN##_id##_CON9, \
+ .almost_end_bit_mask = REG_ALMOST_END_BIT_COUNT_MASK, \
+ .almost_end_bit_shift = REG_ALMOST_END_BIT_COUNT_SFT, \
+ .out2latch_time_reg = ETDM_IN##_id##_CON9, \
+ .out2latch_time_mask = REG_OUT2LATCH_TIME_MASK, \
+ .out2latch_time_shift = REG_OUT2LATCH_TIME_SFT, \
+ .tdm_mode_reg = ETDM_IN##_id##_CON0, \
+ .tdm_mode_mask = REG_FMT_MASK, \
+ .tdm_mode_shift = REG_FMT_SFT, \
+ .relatch_domain_sel_reg = ETDM_IN##_id##_CON0, \
+ .relatch_domain_sel_mask = REG_RELATCH_1X_EN_DOMAIN_SEL_MASK, \
+ .relatch_domain_sel_shift = REG_RELATCH_1X_EN_DOMAIN_SEL_SFT, \
+ .bit_length_reg = ETDM_IN##_id##_CON0, \
+ .bit_length_mask = REG_BIT_LENGTH_MASK, \
+ .bit_length_shift = REG_BIT_LENGTH_SFT, \
+ .word_length_reg = ETDM_IN##_id##_CON0, \
+ .word_length_mask = REG_WORD_LENGTH_MASK, \
+ .word_length_shift = REG_WORD_LENGTH_SFT, \
+ .cowork_reg = _cowork, \
+ .cowork_mask = ETDM_IN##_id##_SLAVE_SEL_MASK, \
+ .cowork_shift = ETDM_IN##_id##_SLAVE_SEL_SFT, \
+ .cowork_val = ETDM_SLAVE_SEL_ETDMOUT##_id##_MASTER, \
+ .pad_top_ck_en_reg = _cfg_vlp_reg, \
+ .pad_top_ck_en_mask = RG_I2S4_PAD_TOP_CK_EN_MASK, \
+ .pad_top_ck_en_shift = RG_I2S4_PAD_TOP_CK_EN_SFT, \
+ .master_latch_reg = _cfg_vlp_reg, \
+ .master_latch_mask = RG_I2S4_IN_BCK_NEG_EG_LATCH_MASK, \
+ .master_latch_shift = RG_I2S4_IN_BCK_NEG_EG_LATCH_SFT, \
+ }
+
+/*
+ * _cfg_vlp_reg should be a variable or constant, not an expression
+ * with side effects.
+ */
+#define MTK_ETDM_OUT_DATA(_id, _cowork, _cfg_vlp_reg) \
+ [DAI_I2SOUT##_id] = { \
+ .enable_reg = ETDM_OUT##_id##_CON0, \
+ .enable_mask = OUT_REG_ETDM_OUT_EN_MASK, \
+ .enable_shift = OUT_REG_ETDM_OUT_EN_SFT, \
+ .sync_reg = ETDM_OUT##_id##_CON0, \
+ .sync_mask = REG_SYNC_MODE_MASK, \
+ .sync_shift = REG_SYNC_MODE_SFT, \
+ .ch_reg = ETDM_OUT##_id##_CON0, \
+ .ch_mask = REG_CH_NUM_MASK, \
+ .ch_shift = REG_CH_NUM_SFT, \
+ .init_count_reg = ETDM_OUT##_id##_CON1, \
+ .init_count_mask = OUT_REG_INITIAL_COUNT_MASK, \
+ .init_count_shift = OUT_REG_INITIAL_COUNT_SFT, \
+ .init_point_reg = ETDM_OUT##_id##_CON1, \
+ .init_point_mask = OUT_REG_INITIAL_POINT_MASK, \
+ .init_point_shift = OUT_REG_INITIAL_POINT_SFT, \
+ .lrck_reset_reg = ETDM_OUT##_id##_CON1, \
+ .lrck_reset_mask = OUT_REG_LRCK_RESET_MASK, \
+ .lrck_reset_shift = OUT_REG_LRCK_RESET_SFT, \
+ .clk_source_reg = ETDM_OUT##_id##_CON4, \
+ .clk_source_mask = OUT_REG_CLOCK_SOURCE_SEL_MASK, \
+ .clk_source_shift = OUT_REG_CLOCK_SOURCE_SEL_SFT, \
+ .fs_timing_reg = ETDM_OUT##_id##_CON4, \
+ .fs_timing_mask = OUT_REG_FS_TIMING_SEL_MASK, \
+ .fs_timing_shift = OUT_REG_FS_TIMING_SEL_SFT, \
+ .relatch_en_sel_reg = ETDM_OUT##_id##_CON4, \
+ .relatch_en_sel_mask = OUT_REG_RELATCH_EN_SEL_MASK, \
+ .relatch_en_sel_shift = OUT_REG_RELATCH_EN_SEL_SFT, \
+ .tdm_mode_reg = ETDM_OUT##_id##_CON0, \
+ .tdm_mode_mask = OUT_REG_FMT_MASK, \
+ .tdm_mode_shift = OUT_REG_FMT_SFT, \
+ .relatch_domain_sel_reg = ETDM_OUT##_id##_CON0, \
+ .relatch_domain_sel_mask = OUT_REG_RELATCH_DOMAIN_SEL_MASK, \
+ .relatch_domain_sel_shift = OUT_REG_RELATCH_DOMAIN_SEL_SFT, \
+ .bit_length_reg = ETDM_OUT##_id##_CON0, \
+ .bit_length_mask = OUT_REG_BIT_LENGTH_MASK, \
+ .bit_length_shift = OUT_REG_BIT_LENGTH_SFT, \
+ .word_length_reg = ETDM_OUT##_id##_CON0, \
+ .word_length_mask = OUT_REG_WORD_LENGTH_MASK, \
+ .word_length_shift = OUT_REG_WORD_LENGTH_SFT, \
+ .cowork_reg = _cowork, \
+ .cowork_mask = ETDM_OUT##_id##_SLAVE_SEL_MASK, \
+ .cowork_shift = ETDM_OUT##_id##_SLAVE_SEL_SFT, \
+ .cowork_val = ETDM_SLAVE_SEL_ETDMIN##_id##_MASTER, \
+ .in2latch_time_reg = ETDM_OUT##_id##_CON2, \
+ .in2latch_time_mask = OUT_REG_IN2LATCH_TIME_MASK, \
+ .in2latch_time_shift = OUT_REG_IN2LATCH_TIME_SFT, \
+ .pad_top_ck_en_reg = _cfg_vlp_reg, \
+ .pad_top_ck_en_mask = RG_I2S4_PAD_TOP_CK_EN_MASK, \
+ .pad_top_ck_en_shift = RG_I2S4_PAD_TOP_CK_EN_SFT, \
+ .master_latch_reg = _cfg_vlp_reg, \
+ .master_latch_mask = RG_I2S4_OUT_BCK_NEG_EG_LATCH_MASK, \
+ .master_latch_shift = RG_I2S4_OUT_BCK_NEG_EG_LATCH_SFT, \
+ }
+
+static const struct mtk_base_etdm_data mtk_etdm_data[DAI_I2S_NUM] = {
+ MTK_ETDM_IN_DATA(0, ETDM_0_3_COWORK_CON0, 0),
+ MTK_ETDM_IN_DATA(1, ETDM_0_3_COWORK_CON1, 0),
+ MTK_ETDM_IN_DATA(2, ETDM_0_3_COWORK_CON2, 0),
+ MTK_ETDM_IN_DATA(3, ETDM_0_3_COWORK_CON3, 0),
+ MTK_ETDM_IN_DATA(4, ETDM_4_7_COWORK_CON0, AUD_TOP_CFG_VLP_RG),
+ MTK_ETDM_IN_DATA(6, ETDM_4_7_COWORK_CON2, 0),
+
+ MTK_ETDM_OUT_DATA(0, ETDM_0_3_COWORK_CON0, 0),
+ MTK_ETDM_OUT_DATA(1, ETDM_0_3_COWORK_CON0, 0),
+ MTK_ETDM_OUT_DATA(2, ETDM_0_3_COWORK_CON2, 0),
+ MTK_ETDM_OUT_DATA(3, ETDM_0_3_COWORK_CON2, 0),
+ MTK_ETDM_OUT_DATA(4, ETDM_4_7_COWORK_CON0, AUD_TOP_CFG_VLP_RG),
+ MTK_ETDM_OUT_DATA(6, ETDM_4_7_COWORK_CON2, 0),
+};
+
+enum {
+ I2S_FMT_EIAJ,
+ I2S_FMT_I2S,
+};
+
+enum {
+ I2S_WLEN_16_BIT,
+ I2S_WLEN_32_BIT,
+};
+
+enum {
+ I2S_IN_PAD_CONNSYS,
+ I2S_IN_PAD_IO_MUX,
+};
+
+static unsigned int get_i2s_wlen(snd_pcm_format_t format)
+{
+ return snd_pcm_format_physical_width(format) <= 16 ?
+ I2S_WLEN_16_BIT : I2S_WLEN_32_BIT;
+}
+
+#define I2SIN0_MCLK_EN_W_NAME "I2SIN0_MCLK_EN"
+#define I2SIN1_MCLK_EN_W_NAME "I2SIN1_MCLK_EN"
+#define I2SIN2_MCLK_EN_W_NAME "I2SIN2_MCLK_EN"
+#define I2SIN3_MCLK_EN_W_NAME "I2SIN3_MCLK_EN"
+#define I2SIN4_MCLK_EN_W_NAME "I2SIN4_MCLK_EN"
+#define I2SIN6_MCLK_EN_W_NAME "I2SIN6_MCLK_EN"
+#define I2SOUT0_MCLK_EN_W_NAME "I2SOUT0_MCLK_EN"
+#define I2SOUT1_MCLK_EN_W_NAME "I2SOUT1_MCLK_EN"
+#define I2SOUT2_MCLK_EN_W_NAME "I2SOUT2_MCLK_EN"
+#define I2SOUT3_MCLK_EN_W_NAME "I2SOUT3_MCLK_EN"
+#define I2SOUT4_MCLK_EN_W_NAME "I2SOUT4_MCLK_EN"
+#define I2SOUT6_MCLK_EN_W_NAME "I2SOUT6_MCLK_EN"
+#define FMI2S_MASTER_MCLK_EN_W_NAME "FMI2S_MASTER_MCLK_EN"
+
+static int get_i2s_id_by_name(struct mtk_base_afe *afe,
+ const char *name)
+{
+ if (strncmp(name, "I2SIN0", 6) == 0)
+ return MT8196_DAI_I2S_IN0;
+ else if (strncmp(name, "I2SIN1", 6) == 0)
+ return MT8196_DAI_I2S_IN1;
+ else if (strncmp(name, "I2SIN2", 6) == 0)
+ return MT8196_DAI_I2S_IN2;
+ else if (strncmp(name, "I2SIN3", 6) == 0)
+ return MT8196_DAI_I2S_IN3;
+ else if (strncmp(name, "I2SIN4", 6) == 0)
+ return MT8196_DAI_I2S_IN4;
+ else if (strncmp(name, "I2SIN6", 6) == 0)
+ return MT8196_DAI_I2S_IN6;
+ else if (strncmp(name, "I2SOUT0", 7) == 0)
+ return MT8196_DAI_I2S_OUT0;
+ else if (strncmp(name, "I2SOUT1", 7) == 0)
+ return MT8196_DAI_I2S_OUT1;
+ else if (strncmp(name, "I2SOUT2", 7) == 0)
+ return MT8196_DAI_I2S_OUT2;
+ else if (strncmp(name, "I2SOUT3", 7) == 0)
+ return MT8196_DAI_I2S_OUT3;
+ else if (strncmp(name, "I2SOUT4", 7) == 0)
+ return MT8196_DAI_I2S_OUT4;
+ else if (strncmp(name, "I2SOUT6", 7) == 0)
+ return MT8196_DAI_I2S_OUT6;
+ else if (strncmp(name, "FMI2S_MASTER", 12) == 0)
+ return MT8196_DAI_FM_I2S_MASTER;
+ else
+ return -EINVAL;
+}
+
+static struct mtk_afe_i2s_priv *get_i2s_priv_by_name(struct mtk_base_afe *afe,
+ const char *name)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int dai_id = get_i2s_id_by_name(afe, name);
+
+ if (dai_id < 0)
+ return NULL;
+
+ return afe_priv->dai_priv[dai_id];
+}
+
+static const char * const etdm_0_3_loopback_text[] = {
+ "etdmin0", "etdmin1",
+ "etdmin2", "etdmin3",
+ "etdmout0", "etdmout1",
+ "etdmout2", "etdmout3"
+};
+
+static const char * const etdm_4_7_loopback_text[] = {
+ "etdmin4", "etdmin5",
+ "etdmin6", "etdmin7",
+ "etdmout4", "etdmout5",
+ "etdmout6", "etdmout7"
+};
+
+static const u32 etdm_loopback_values[] = {
+ 0, 2, 4, 6, 8, 10, 12, 14
+};
+
+static const struct soc_enum i2sin0_loopback_enum =
+ SOC_VALUE_ENUM_SINGLE(ETDM_0_3_COWORK_CON1, ETDM_IN0_SDATA0_SEL_SFT,
+ ETDM_IN0_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_0_3_loopback_text),
+ etdm_0_3_loopback_text, etdm_loopback_values);
+
+static const struct soc_enum i2sin1_loopback_enum =
+ SOC_VALUE_ENUM_SINGLE(ETDM_0_3_COWORK_CON1, ETDM_IN1_SDATA0_SEL_SFT,
+ ETDM_IN1_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_0_3_loopback_text),
+ etdm_0_3_loopback_text, etdm_loopback_values);
+
+static const struct soc_enum i2sin2_loopback_enum =
+ SOC_VALUE_ENUM_SINGLE(ETDM_0_3_COWORK_CON3, ETDM_IN2_SDATA0_SEL_SFT,
+ ETDM_IN2_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_0_3_loopback_text),
+ etdm_0_3_loopback_text, etdm_loopback_values);
+
+static const struct soc_enum i2sin3_loopback_enum =
+ SOC_VALUE_ENUM_SINGLE(ETDM_0_3_COWORK_CON3, ETDM_IN3_SDATA0_SEL_SFT,
+ ETDM_IN3_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_0_3_loopback_text),
+ etdm_0_3_loopback_text, etdm_loopback_values);
+
+static const struct soc_enum i2sin4_loopback_enum =
+ SOC_VALUE_ENUM_SINGLE(ETDM_4_7_COWORK_CON1, ETDM_IN4_SDATA0_SEL_SFT,
+ ETDM_IN4_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_4_7_loopback_text),
+ etdm_4_7_loopback_text, etdm_loopback_values);
+
+static const struct soc_enum i2sin6_loopback_enum =
+ SOC_VALUE_ENUM_SINGLE(ETDM_4_7_COWORK_CON3, ETDM_IN6_SDATA0_SEL_SFT,
+ ETDM_IN6_SDATA0_SEL_MASK, ARRAY_SIZE(etdm_4_7_loopback_text),
+ etdm_4_7_loopback_text, etdm_loopback_values);
+
+static const struct snd_kcontrol_new mtk_dai_i2s_controls[] = {
+ SOC_ENUM("I2SIN0 LOOPBACK", i2sin0_loopback_enum),
+ SOC_ENUM("I2SIN1 LOOPBACK", i2sin1_loopback_enum),
+ SOC_ENUM("I2SIN2 LOOPBACK", i2sin2_loopback_enum),
+ SOC_ENUM("I2SIN3 LOOPBACK", i2sin3_loopback_enum),
+ /* The following I2S does not support multi-ip mode */
+ SOC_ENUM("I2SIN4 LOOPBACK", i2sin4_loopback_enum),
+ SOC_ENUM("I2SIN6 LOOPBACK", i2sin6_loopback_enum),
+};
+
+/* interconnection */
+static const struct snd_kcontrol_new mtk_i2sout0_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN108_1, I_DL0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN108_1, I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN108_1, I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN108_1, I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN108_1, I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN108_1, I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN108_1, I_DL6_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN108_1, I_DL7_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN108_1, I_DL8_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN108_1, I_DL_24CH_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL23_CH1", AFE_CONN108_2, I_DL23_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH1", AFE_CONN108_2, I_DL24_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN108_0,
+ I_GAIN0_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN108_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN108_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN108_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN108_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN108_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH1", AFE_CONN108_6,
+ I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout0_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN109_1, I_DL0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN109_1, I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN109_1, I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN109_1, I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN109_1, I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN109_1, I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN109_1, I_DL6_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN109_1, I_DL7_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN109_1, I_DL8_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN109_1, I_DL_24CH_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL23_CH2", AFE_CONN109_2, I_DL23_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH2", AFE_CONN109_2, I_DL24_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN109_0,
+ I_GAIN0_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN109_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN109_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN109_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN109_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN109_4,
+ I_PCM_0_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN109_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN109_4,
+ I_PCM_1_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH2", AFE_CONN109_6,
+ I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout1_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN110_1, I_DL0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN110_1, I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN110_1, I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN110_1, I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN110_1, I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN110_1, I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN110_1, I_DL6_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN110_1, I_DL7_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN110_1, I_DL8_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN110_1, I_DL_24CH_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN110_0,
+ I_GAIN0_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN110_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN110_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN110_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout1_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN111_1, I_DL0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN111_1, I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN111_1, I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN111_1, I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN111_1, I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN111_1, I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN111_1, I_DL6_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN111_1, I_DL7_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN111_1, I_DL8_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN111_1, I_DL_24CH_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN111_0,
+ I_GAIN0_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN111_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN111_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN111_4,
+ I_PCM_0_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN111_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN111_4,
+ I_PCM_1_CAP_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout2_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN112_1, I_DL0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN112_1, I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN112_1, I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN112_1, I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN112_1, I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN112_1, I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN112_1, I_DL6_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN112_1, I_DL7_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN112_1, I_DL8_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN112_1, I_DL_24CH_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN112_0,
+ I_GAIN0_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN112_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN112_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN112_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout2_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN113_1, I_DL0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN113_1, I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN113_1, I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN113_1, I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN113_1, I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN113_1, I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN113_1, I_DL6_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN113_1, I_DL7_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN113_1, I_DL8_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN113_1, I_DL_24CH_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN113_0,
+ I_GAIN0_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN113_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN113_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN113_4,
+ I_PCM_0_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN113_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN113_4,
+ I_PCM_1_CAP_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout3_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN114_1, I_DL0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN114_1, I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN114_1, I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN114_1, I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN114_1, I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN114_1, I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN114_1, I_DL6_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN114_1, I_DL7_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN114_1, I_DL8_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN114_1, I_DL_24CH_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN114_0,
+ I_GAIN0_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN114_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN114_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN114_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout3_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN115_1, I_DL0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN115_1, I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN115_1, I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN115_1, I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN115_1, I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN115_1, I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN115_1, I_DL6_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN115_1, I_DL7_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN115_1, I_DL8_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN115_1, I_DL_24CH_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN115_0,
+ I_GAIN0_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN115_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN115_4,
+ I_PCM_0_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN115_4,
+ I_PCM_1_CAP_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout4_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN116_1, I_DL0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN116_1, I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN116_1, I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN116_1, I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN116_1, I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN116_1, I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN116_1, I_DL6_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN116_1, I_DL7_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN116_1, I_DL8_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN116_1, I_DL_24CH_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH1", AFE_CONN116_2, I_DL24_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN116_0,
+ I_GAIN0_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN116_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN116_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN116_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN116_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN116_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH1", AFE_CONN116_6,
+ I_SRC_2_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout4_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN117_1, I_DL0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN117_1, I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN117_1, I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN117_1, I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN117_1, I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN117_1, I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN117_1, I_DL6_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN117_1, I_DL7_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN117_1, I_DL8_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN117_1, I_DL_24CH_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL24_CH2", AFE_CONN117_2, I_DL24_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN117_0,
+ I_GAIN0_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN117_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN117_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH3", AFE_CONN117_0,
+ I_ADDA_UL_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN117_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN117_4,
+ I_PCM_0_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN117_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN117_4,
+ I_PCM_1_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_2_OUT_CH2", AFE_CONN117_6,
+ I_SRC_2_OUT_CH2, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout4_ch3_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH3", AFE_CONN118_1, I_DL_24CH_CH3, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN118_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN118_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout4_ch4_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH4", AFE_CONN119_1, I_DL_24CH_CH4, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN118_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN118_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout4_ch5_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH5", AFE_CONN120_1, I_DL_24CH_CH5, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout4_ch6_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH6", AFE_CONN121_1, I_DL_24CH_CH6, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout4_ch7_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH7", AFE_CONN122_1, I_DL_24CH_CH7, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout4_ch8_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH8", AFE_CONN123_1, I_DL_24CH_CH8, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout6_ch1_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH1", AFE_CONN148_1, I_DL0_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH1", AFE_CONN148_1, I_DL1_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH1", AFE_CONN148_1, I_DL2_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH1", AFE_CONN148_1, I_DL3_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH1", AFE_CONN148_1, I_DL4_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH1", AFE_CONN148_1, I_DL5_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH1", AFE_CONN148_1, I_DL6_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH1", AFE_CONN148_1, I_DL7_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH1", AFE_CONN148_1, I_DL8_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL23_CH1", AFE_CONN148_2, I_DL23_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH1", AFE_CONN148_1, I_DL_24CH_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH1", AFE_CONN148_0,
+ I_GAIN0_OUT_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH1", AFE_CONN148_0,
+ I_ADDA_UL_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN148_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN148_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_1_OUT_CH1", AFE_CONN148_6,
+ I_SRC_1_OUT_CH1, 1, 0),
+};
+
+static const struct snd_kcontrol_new mtk_i2sout6_ch2_mix[] = {
+ SOC_DAPM_SINGLE_AUTODISABLE("DL0_CH2", AFE_CONN149_1, I_DL0_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL1_CH2", AFE_CONN149_1, I_DL1_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL2_CH2", AFE_CONN149_1, I_DL2_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL3_CH2", AFE_CONN149_1, I_DL3_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL4_CH2", AFE_CONN149_1, I_DL4_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL5_CH2", AFE_CONN149_1, I_DL5_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL6_CH2", AFE_CONN149_1, I_DL6_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL7_CH2", AFE_CONN149_1, I_DL7_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL8_CH2", AFE_CONN149_1, I_DL8_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL23_CH2", AFE_CONN149_2, I_DL23_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("DL_24CH_CH2", AFE_CONN149_1, I_DL_24CH_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_GAIN0_OUT_CH2", AFE_CONN149_0,
+ I_GAIN0_OUT_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("ADDA_UL_CH2", AFE_CONN149_0,
+ I_ADDA_UL_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH1", AFE_CONN149_4,
+ I_PCM_0_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_0_CAP_CH2", AFE_CONN149_4,
+ I_PCM_0_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH1", AFE_CONN149_4,
+ I_PCM_1_CAP_CH1, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("PCM_1_CAP_CH2", AFE_CONN149_4,
+ I_PCM_1_CAP_CH2, 1, 0),
+ SOC_DAPM_SINGLE_AUTODISABLE("HW_SRC_1_OUT_CH2", AFE_CONN148_6,
+ I_SRC_1_OUT_CH2, 1, 0),
+};
+
+enum {
+ SUPPLY_SEQ_APLL,
+ SUPPLY_SEQ_I2S_MCLK_EN,
+ SUPPLY_SEQ_I2S_CG_EN,
+ SUPPLY_SEQ_I2S_EN,
+};
+
+static int mtk_apll_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+
+ dev_dbg(cmpnt->dev, "name %s, event 0x%x\n", w->name, event);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ if (strcmp(w->name, APLL1_W_NAME) == 0)
+ mt8196_apll1_enable(afe);
+ else
+ mt8196_apll2_enable(afe);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ if (strcmp(w->name, APLL1_W_NAME) == 0)
+ mt8196_apll1_disable(afe);
+ else
+ mt8196_apll2_disable(afe);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mtk_mclk_en_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mtk_afe_i2s_priv *i2s_priv;
+
+ dev_dbg(cmpnt->dev, "name %s, event 0x%x\n", w->name, event);
+
+ i2s_priv = get_i2s_priv_by_name(afe, w->name);
+
+ if (!i2s_priv)
+ return -EINVAL;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mt8196_mck_enable(afe, i2s_priv->mclk_id, i2s_priv->mclk_rate);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ i2s_priv->mclk_rate = 0;
+ mt8196_mck_disable(afe, i2s_priv->mclk_id);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget mtk_dai_i2s_widgets[] = {
+ SND_SOC_DAPM_MIXER("I2SOUT0_CH1", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout0_ch1_mix,
+ ARRAY_SIZE(mtk_i2sout0_ch1_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT0_CH2", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout0_ch2_mix,
+ ARRAY_SIZE(mtk_i2sout0_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("I2SOUT1_CH1", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout1_ch1_mix,
+ ARRAY_SIZE(mtk_i2sout1_ch1_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT1_CH2", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout1_ch2_mix,
+ ARRAY_SIZE(mtk_i2sout1_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("I2SOUT2_CH1", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout2_ch1_mix,
+ ARRAY_SIZE(mtk_i2sout2_ch1_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT2_CH2", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout2_ch2_mix,
+ ARRAY_SIZE(mtk_i2sout2_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("I2SOUT3_CH1", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout3_ch1_mix,
+ ARRAY_SIZE(mtk_i2sout3_ch1_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT3_CH2", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout3_ch2_mix,
+ ARRAY_SIZE(mtk_i2sout3_ch2_mix)),
+
+ SND_SOC_DAPM_MIXER("I2SOUT4_CH1", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout4_ch1_mix,
+ ARRAY_SIZE(mtk_i2sout4_ch1_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT4_CH2", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout4_ch2_mix,
+ ARRAY_SIZE(mtk_i2sout4_ch2_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT4_CH3", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout4_ch3_mix,
+ ARRAY_SIZE(mtk_i2sout4_ch3_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT4_CH4", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout4_ch4_mix,
+ ARRAY_SIZE(mtk_i2sout4_ch4_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT4_CH5", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout4_ch5_mix,
+ ARRAY_SIZE(mtk_i2sout4_ch5_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT4_CH6", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout4_ch6_mix,
+ ARRAY_SIZE(mtk_i2sout4_ch6_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT4_CH7", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout4_ch7_mix,
+ ARRAY_SIZE(mtk_i2sout4_ch7_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT4_CH8", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout4_ch8_mix,
+ ARRAY_SIZE(mtk_i2sout4_ch8_mix)),
+
+ SND_SOC_DAPM_MIXER("I2SOUT6_CH1", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout6_ch1_mix,
+ ARRAY_SIZE(mtk_i2sout6_ch1_mix)),
+ SND_SOC_DAPM_MIXER("I2SOUT6_CH2", SND_SOC_NOPM, 0, 0,
+ mtk_i2sout6_ch2_mix,
+ ARRAY_SIZE(mtk_i2sout6_ch2_mix)),
+
+ /* i2s en*/
+ SND_SOC_DAPM_SUPPLY_S("I2SIN0_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_IN0_CON0, REG_ETDM_IN_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN1_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_IN1_CON0, REG_ETDM_IN_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN2_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_IN2_CON0, REG_ETDM_IN_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN3_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_IN3_CON0, REG_ETDM_IN_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN4_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_IN4_CON0, REG_ETDM_IN_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN6_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_IN6_CON0, REG_ETDM_IN_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT0_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_OUT0_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT1_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_OUT1_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT2_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_OUT2_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT3_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_OUT3_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT4_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_OUT4_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT6_EN", SUPPLY_SEQ_I2S_EN,
+ ETDM_OUT6_CON0, OUT_REG_ETDM_OUT_EN_SFT, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("FMI2S_MASTER_EN", SUPPLY_SEQ_I2S_EN,
+ AFE_CONNSYS_I2S_CON, I2S_EN_SFT, 0,
+ NULL, 0),
+
+ /* i2s mclk en */
+ SND_SOC_DAPM_SUPPLY_S(I2SIN0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SIN1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SIN2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SIN3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SIN4_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SIN6_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SOUT0_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SOUT1_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SOUT2_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SOUT3_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SOUT4_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(I2SOUT6_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(FMI2S_MASTER_MCLK_EN_W_NAME, SUPPLY_SEQ_I2S_MCLK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_mclk_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* cg */
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT0_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_OUT0_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT1_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_OUT1_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT2_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_OUT2_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT3_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_OUT3_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT4_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_OUT4_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SOUT6_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_OUT6_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN0_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_IN0_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN1_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_IN1_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN2_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_IN2_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN3_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_IN3_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN4_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_IN4_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("I2SIN6_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON2, PDN_ETDM_IN6_SFT, 1,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("FMI2S_MASTER_CG", SUPPLY_SEQ_I2S_CG_EN,
+ AUDIO_TOP_CON0, PDN_FM_I2S_SFT, 1,
+ NULL, 0),
+
+ /* apll */
+ SND_SOC_DAPM_SUPPLY_S(APLL1_W_NAME, SUPPLY_SEQ_APLL,
+ SND_SOC_NOPM, 0, 0,
+ mtk_apll_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY_S(APLL2_W_NAME, SUPPLY_SEQ_APLL,
+ SND_SOC_NOPM, 0, 0,
+ mtk_apll_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_MIXER("SOF_DMA_DL_24CH", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SOF_DMA_DL1", SND_SOC_NOPM, 0, 0, NULL, 0),
+};
+
+static int mtk_afe_i2s_share_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mtk_afe_i2s_priv *i2s_priv;
+
+ i2s_priv = get_i2s_priv_by_name(afe, sink->name);
+ if (!i2s_priv)
+ return 0;
+
+ if (i2s_priv->share_i2s_id < 0)
+ return 0;
+
+ return i2s_priv->share_i2s_id == get_i2s_id_by_name(afe, source->name);
+}
+
+static int mtk_afe_i2s_apll_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mtk_afe_i2s_priv *i2s_priv;
+ int cur_apll;
+ int needed_apll;
+
+ i2s_priv = get_i2s_priv_by_name(afe, sink->name);
+ if (!i2s_priv)
+ return 0;
+
+ /* which apll */
+ cur_apll = mt8196_get_apll_by_name(afe, source->name);
+
+ /* choose APLL from i2s rate */
+ needed_apll = mt8196_get_apll_by_rate(afe, i2s_priv->rate);
+
+ return needed_apll == cur_apll;
+}
+
+static int mtk_afe_i2s_mclk_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mtk_afe_i2s_priv *i2s_priv;
+ int i2s_num;
+
+ i2s_priv = get_i2s_priv_by_name(afe, sink->name);
+ if (!i2s_priv)
+ return 0;
+
+ i2s_num = get_i2s_id_by_name(afe, source->name);
+ if (get_i2s_id_by_name(afe, sink->name) == i2s_num)
+ return i2s_priv->mclk_rate > 0;
+
+ /* check if share i2s need mclk */
+ if (i2s_priv->share_i2s_id < 0)
+ return 0;
+
+ if (i2s_priv->share_i2s_id == i2s_num)
+ return i2s_priv->mclk_rate > 0;
+
+ return 0;
+}
+
+static int mtk_afe_mclk_apll_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mtk_afe_i2s_priv *i2s_priv;
+ int cur_apll;
+
+ i2s_priv = get_i2s_priv_by_name(afe, sink->name);
+ if (!i2s_priv)
+ return 0;
+
+ /* which apll */
+ cur_apll = mt8196_get_apll_by_name(afe, source->name);
+
+ return i2s_priv->mclk_apll == cur_apll;
+}
+
+static const struct snd_soc_dapm_route mtk_dai_i2s_routes[] = {
+ /* i2sin0 */
+ {"I2SIN0", NULL, "I2SIN0_EN"},
+ {"I2SIN0", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN0", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SIN0", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SIN0", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SIN0", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN0", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+
+ {I2SIN0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SIN0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SIN0", NULL, "I2SIN0_CG"},
+
+ /* i2sin1 */
+ {"I2SIN1", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SIN1_EN"},
+ {"I2SIN1", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN1", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SIN1", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SIN1", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SIN1", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN1", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SIN1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SIN1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SIN1", NULL, "I2SIN1_CG"},
+
+ /* i2sin2 */
+ {"I2SIN2", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SIN2_EN"},
+ {"I2SIN2", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN2", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SIN2", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SIN2", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SIN2", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN2", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SIN2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SIN2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SIN2", NULL, "I2SIN2_CG"},
+
+ /* i2sin3 */
+ {"I2SIN3", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SIN3_EN"},
+ {"I2SIN3", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN3", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SIN3", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SIN3", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SIN3", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN3", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SIN3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SIN3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SIN3", NULL, "I2SIN3_CG"},
+
+ /* i2sin4 */
+ {"I2SIN4", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SIN4_EN"},
+ {"I2SIN4", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN4", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SIN4", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SIN4", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SIN4", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN4", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SIN4_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SIN4_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SIN4", NULL, "I2SIN4_CG"},
+
+ /* i2sin6 */
+ {"I2SIN6", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SIN6_EN"},
+ {"I2SIN6", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SIN6", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SIN6", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SIN6", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SIN6", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SIN6", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SIN6_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SIN6_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SIN6", NULL, "I2SIN6_CG"},
+ {"I2SIN6", NULL, "I2SOUT6_CG"},
+
+ /* i2sout0 */
+ {"I2SOUT0_CH1", "DL0_CH1", "DL0"},
+ {"I2SOUT0_CH2", "DL0_CH2", "DL0"},
+ {"I2SOUT0_CH1", "DL1_CH1", "DL1"},
+ {"I2SOUT0_CH2", "DL1_CH2", "DL1"},
+ {"I2SOUT0_CH1", "DL2_CH1", "DL2"},
+ {"I2SOUT0_CH2", "DL2_CH2", "DL2"},
+ {"I2SOUT0_CH1", "DL3_CH1", "DL3"},
+ {"I2SOUT0_CH2", "DL3_CH2", "DL3"},
+ {"I2SOUT0_CH1", "DL4_CH1", "DL4"},
+ {"I2SOUT0_CH2", "DL4_CH2", "DL4"},
+ {"I2SOUT0_CH1", "DL5_CH1", "DL5"},
+ {"I2SOUT0_CH2", "DL5_CH2", "DL5"},
+ {"I2SOUT0_CH1", "DL6_CH1", "DL6"},
+ {"I2SOUT0_CH2", "DL6_CH2", "DL6"},
+ {"I2SOUT0_CH1", "DL7_CH1", "DL7"},
+ {"I2SOUT0_CH2", "DL7_CH2", "DL7"},
+ {"I2SOUT0_CH1", "DL8_CH1", "DL8"},
+ {"I2SOUT0_CH2", "DL8_CH2", "DL8"},
+ {"I2SOUT0_CH1", "DL23_CH1", "DL23"},
+ {"I2SOUT0_CH2", "DL23_CH2", "DL23"},
+ {"I2SOUT0_CH1", "DL_24CH_CH1", "DL_24CH"},
+ {"I2SOUT0_CH2", "DL_24CH_CH2", "DL_24CH"},
+
+ {"I2SOUT0_CH1", "DL24_CH1", "DL24"},
+ {"I2SOUT0_CH2", "DL24_CH2", "DL24"},
+
+ {"I2SOUT0", NULL, "I2SOUT0_CH1"},
+ {"I2SOUT0", NULL, "I2SOUT0_CH2"},
+
+ {"I2SOUT0", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SOUT0_EN"},
+ {"I2SOUT0", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT0", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SOUT0", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SOUT0", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SOUT0", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT0", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SOUT0_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SOUT0_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SOUT0", NULL, "I2SOUT0_CG"},
+ {"I2SOUT0", NULL, "I2SIN0_CG"},
+
+ /* i2sout1 */
+ {"I2SOUT1_CH1", "DL0_CH1", "DL0"},
+ {"I2SOUT1_CH2", "DL0_CH2", "DL0"},
+ {"I2SOUT1_CH1", "DL1_CH1", "DL1"},
+ {"I2SOUT1_CH2", "DL1_CH2", "DL1"},
+ {"I2SOUT1_CH1", "DL2_CH1", "DL2"},
+ {"I2SOUT1_CH2", "DL2_CH2", "DL2"},
+ {"I2SOUT1_CH1", "DL3_CH1", "DL3"},
+ {"I2SOUT1_CH2", "DL3_CH2", "DL3"},
+ {"I2SOUT1_CH1", "DL4_CH1", "DL4"},
+ {"I2SOUT1_CH2", "DL4_CH2", "DL4"},
+ {"I2SOUT1_CH1", "DL5_CH1", "DL5"},
+ {"I2SOUT1_CH2", "DL5_CH2", "DL5"},
+ {"I2SOUT1_CH1", "DL6_CH1", "DL6"},
+ {"I2SOUT1_CH2", "DL6_CH2", "DL6"},
+ {"I2SOUT1_CH1", "DL7_CH1", "DL7"},
+ {"I2SOUT1_CH2", "DL7_CH2", "DL7"},
+ {"I2SOUT1_CH1", "DL8_CH1", "DL8"},
+ {"I2SOUT1_CH2", "DL8_CH2", "DL8"},
+ {"I2SOUT1_CH1", "DL_24CH_CH1", "DL_24CH"},
+ {"I2SOUT1_CH2", "DL_24CH_CH2", "DL_24CH"},
+
+ {"I2SOUT1", NULL, "I2SOUT1_CH1"},
+ {"I2SOUT1", NULL, "I2SOUT1_CH2"},
+
+ {"I2SOUT1", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SOUT1_EN"},
+ {"I2SOUT1", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT1", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SOUT1", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SOUT1", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SOUT1", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT1", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SOUT1_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SOUT1_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SOUT1", NULL, "I2SOUT1_CG"},
+ {"I2SOUT1", NULL, "I2SIN1_CG"},
+
+ /* i2sout2 */
+ {"I2SOUT2_CH1", "DL0_CH1", "DL0"},
+ {"I2SOUT2_CH2", "DL0_CH2", "DL0"},
+ {"I2SOUT2_CH1", "DL1_CH1", "DL1"},
+ {"I2SOUT2_CH2", "DL1_CH2", "DL1"},
+ {"I2SOUT2_CH1", "DL2_CH1", "DL2"},
+ {"I2SOUT2_CH2", "DL2_CH2", "DL2"},
+ {"I2SOUT2_CH1", "DL3_CH1", "DL3"},
+ {"I2SOUT2_CH2", "DL3_CH2", "DL3"},
+ {"I2SOUT2_CH1", "DL4_CH1", "DL4"},
+ {"I2SOUT2_CH2", "DL4_CH2", "DL4"},
+ {"I2SOUT2_CH1", "DL5_CH1", "DL5"},
+ {"I2SOUT2_CH2", "DL5_CH2", "DL5"},
+ {"I2SOUT2_CH1", "DL6_CH1", "DL6"},
+ {"I2SOUT2_CH2", "DL6_CH2", "DL6"},
+ {"I2SOUT2_CH1", "DL7_CH1", "DL7"},
+ {"I2SOUT2_CH2", "DL7_CH2", "DL7"},
+ {"I2SOUT2_CH1", "DL8_CH1", "DL8"},
+ {"I2SOUT2_CH2", "DL8_CH2", "DL8"},
+ {"I2SOUT2_CH1", "DL_24CH_CH1", "DL_24CH"},
+ {"I2SOUT2_CH2", "DL_24CH_CH2", "DL_24CH"},
+
+ {"I2SOUT2", NULL, "I2SOUT2_CH1"},
+ {"I2SOUT2", NULL, "I2SOUT2_CH2"},
+
+ {"I2SOUT2", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SOUT2_EN"},
+ {"I2SOUT2", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT2", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SOUT2", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SOUT2", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SOUT2", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT2", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SOUT2_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SOUT2_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SOUT2", NULL, "I2SOUT2_CG"},
+ {"I2SOUT2", NULL, "I2SIN2_CG"},
+
+ /* i2sout3 */
+ {"I2SOUT3_CH1", "DL0_CH1", "DL0"},
+ {"I2SOUT3_CH2", "DL0_CH2", "DL0"},
+ {"I2SOUT3_CH1", "DL1_CH1", "DL1"},
+ {"I2SOUT3_CH2", "DL1_CH2", "DL1"},
+ {"I2SOUT3_CH1", "DL2_CH1", "DL2"},
+ {"I2SOUT3_CH2", "DL2_CH2", "DL2"},
+ {"I2SOUT3_CH1", "DL3_CH1", "DL3"},
+ {"I2SOUT3_CH2", "DL3_CH2", "DL3"},
+ {"I2SOUT3_CH1", "DL4_CH1", "DL4"},
+ {"I2SOUT3_CH2", "DL4_CH2", "DL4"},
+ {"I2SOUT3_CH1", "DL5_CH1", "DL5"},
+ {"I2SOUT3_CH2", "DL5_CH2", "DL5"},
+ {"I2SOUT3_CH1", "DL6_CH1", "DL6"},
+ {"I2SOUT3_CH2", "DL6_CH2", "DL6"},
+ {"I2SOUT3_CH1", "DL7_CH1", "DL7"},
+ {"I2SOUT3_CH2", "DL7_CH2", "DL7"},
+ {"I2SOUT3_CH1", "DL8_CH1", "DL8"},
+ {"I2SOUT3_CH2", "DL8_CH2", "DL8"},
+ {"I2SOUT3_CH1", "DL_24CH_CH1", "DL_24CH"},
+ {"I2SOUT3_CH2", "DL_24CH_CH2", "DL_24CH"},
+
+ {"I2SOUT3", NULL, "I2SOUT3_CH1"},
+ {"I2SOUT3", NULL, "I2SOUT3_CH2"},
+
+ {"I2SOUT3", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SOUT3_EN"},
+ {"I2SOUT3", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT3", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SOUT3", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SOUT3", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SOUT3", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT3", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SOUT3_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SOUT3_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ {"I2SOUT3", NULL, "I2SOUT3_CG"},
+ {"I2SOUT3", NULL, "I2SIN3_CG"},
+
+ /* i2sout4 */
+ {"I2SOUT4_CH1", "DL0_CH1", "DL0"},
+ {"I2SOUT4_CH2", "DL0_CH2", "DL0"},
+ {"I2SOUT4_CH1", "DL1_CH1", "DL1"},
+ {"I2SOUT4_CH2", "DL1_CH2", "DL1"},
+ {"I2SOUT4_CH1", "DL2_CH1", "DL2"},
+ {"I2SOUT4_CH2", "DL2_CH2", "DL2"},
+ {"I2SOUT4_CH1", "DL3_CH1", "DL3"},
+ {"I2SOUT4_CH2", "DL3_CH2", "DL3"},
+ {"I2SOUT4_CH1", "DL4_CH1", "DL4"},
+ {"I2SOUT4_CH2", "DL4_CH2", "DL4"},
+ {"I2SOUT4_CH1", "DL5_CH1", "DL5"},
+ {"I2SOUT4_CH2", "DL5_CH2", "DL5"},
+ {"I2SOUT4_CH1", "DL6_CH1", "DL6"},
+ {"I2SOUT4_CH2", "DL6_CH2", "DL6"},
+ {"I2SOUT4_CH1", "DL7_CH1", "DL7"},
+ {"I2SOUT4_CH2", "DL7_CH2", "DL7"},
+ {"I2SOUT4_CH1", "DL8_CH1", "DL8"},
+ {"I2SOUT4_CH2", "DL8_CH2", "DL8"},
+ {"I2SOUT4_CH1", "DL_24CH_CH1", "DL_24CH"},
+ {"I2SOUT4_CH2", "DL_24CH_CH2", "DL_24CH"},
+ {"I2SOUT4_CH3", "DL_24CH_CH3", "DL_24CH"},
+ {"I2SOUT4_CH4", "DL_24CH_CH4", "DL_24CH"},
+ {"I2SOUT4_CH5", "DL_24CH_CH5", "DL_24CH"},
+ {"I2SOUT4_CH6", "DL_24CH_CH6", "DL_24CH"},
+ {"I2SOUT4_CH7", "DL_24CH_CH7", "DL_24CH"},
+ {"I2SOUT4_CH8", "DL_24CH_CH8", "DL_24CH"},
+ {"I2SOUT4_CH1", "DL24_CH1", "DL24"},
+ {"I2SOUT4_CH2", "DL24_CH2", "DL24"},
+
+ /* SOF Downlink */
+ {"I2SOUT4_CH1", "DL_24CH_CH1", "SOF_DMA_DL_24CH"},
+ {"I2SOUT4_CH2", "DL_24CH_CH2", "SOF_DMA_DL_24CH"},
+ {"I2SOUT4_CH3", "DL_24CH_CH3", "SOF_DMA_DL_24CH"},
+ {"I2SOUT4_CH4", "DL_24CH_CH4", "SOF_DMA_DL_24CH"},
+
+ {"I2SOUT4", NULL, "I2SOUT4_CH1"},
+ {"I2SOUT4", NULL, "I2SOUT4_CH2"},
+ {"I2SOUT4", NULL, "I2SOUT4_CH3"},
+ {"I2SOUT4", NULL, "I2SOUT4_CH4"},
+ {"I2SOUT4", NULL, "I2SOUT4_CH5"},
+ {"I2SOUT4", NULL, "I2SOUT4_CH6"},
+ {"I2SOUT4", NULL, "I2SOUT4_CH7"},
+ {"I2SOUT4", NULL, "I2SOUT4_CH8"},
+
+ {"I2SOUT4", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "I2SOUT4_EN"},
+ {"I2SOUT4", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT4", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SOUT4", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SOUT4", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SOUT4", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT4", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SOUT4_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SOUT4_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ /* CG */
+ {"I2SOUT4", NULL, "I2SOUT4_CG"},
+ {"I2SOUT4", NULL, "I2SIN4_CG"},
+
+ /* i2sout6 */
+ {"I2SOUT6_CH1", "DL0_CH1", "DL0"},
+ {"I2SOUT6_CH2", "DL0_CH2", "DL0"},
+ {"I2SOUT6_CH1", "DL1_CH1", "DL1"},
+ {"I2SOUT6_CH2", "DL1_CH2", "DL1"},
+ {"I2SOUT6_CH1", "DL2_CH1", "DL2"},
+ {"I2SOUT6_CH2", "DL2_CH2", "DL2"},
+ {"I2SOUT6_CH1", "DL3_CH1", "DL3"},
+ {"I2SOUT6_CH2", "DL3_CH2", "DL3"},
+ {"I2SOUT6_CH1", "DL4_CH1", "DL4"},
+ {"I2SOUT6_CH2", "DL4_CH2", "DL4"},
+ {"I2SOUT6_CH1", "DL5_CH1", "DL5"},
+ {"I2SOUT6_CH2", "DL5_CH2", "DL5"},
+ {"I2SOUT6_CH1", "DL6_CH1", "DL6"},
+ {"I2SOUT6_CH2", "DL6_CH2", "DL6"},
+ {"I2SOUT6_CH1", "DL7_CH1", "DL7"},
+ {"I2SOUT6_CH2", "DL7_CH2", "DL7"},
+ {"I2SOUT6_CH1", "DL8_CH1", "DL8"},
+ {"I2SOUT6_CH2", "DL8_CH2", "DL8"},
+ {"I2SOUT6_CH1", "DL23_CH1", "DL23"},
+ {"I2SOUT6_CH2", "DL23_CH2", "DL23"},
+ {"I2SOUT6_CH1", "DL_24CH_CH1", "DL_24CH"},
+ {"I2SOUT6_CH2", "DL_24CH_CH2", "DL_24CH"},
+
+ /* SOF Downlink */
+ {"I2SOUT6_CH1", "DL1_CH1", "SOF_DMA_DL1"},
+ {"I2SOUT6_CH2", "DL1_CH2", "SOF_DMA_DL1"},
+ {"I2SOUT6_CH1", "DL_24CH_CH1", "SOF_DMA_DL_24CH"},
+ {"I2SOUT6_CH2", "DL_24CH_CH2", "SOF_DMA_DL_24CH"},
+
+ {"I2SOUT6", NULL, "I2SOUT6_CH1"},
+ {"I2SOUT6", NULL, "I2SOUT6_CH2"},
+
+ {"I2SOUT6", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"I2SOUT6", NULL, "I2SOUT6_EN"},
+ {"I2SOUT6", NULL, "FMI2S_MASTER_EN", mtk_afe_i2s_share_connect},
+
+ {"I2SOUT6", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"I2SOUT6", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"I2SOUT6", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"I2SOUT6", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {I2SOUT6_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {I2SOUT6_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ /* CG */
+ {"I2SOUT6", NULL, "I2SOUT6_CG"},
+ {"I2SOUT6", NULL, "I2SIN6_CG"},
+
+ /* fmi2s */
+ {"FMI2S_MASTER", NULL, "I2SIN0_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SIN1_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SIN2_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SIN3_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SIN4_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SIN6_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SOUT0_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SOUT1_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SOUT2_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SOUT3_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SOUT4_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "I2SOUT6_EN", mtk_afe_i2s_share_connect},
+ {"FMI2S_MASTER", NULL, "FMI2S_MASTER_EN"},
+
+ {"FMI2S_MASTER", NULL, APLL1_W_NAME, mtk_afe_i2s_apll_connect},
+ {"FMI2S_MASTER", NULL, APLL2_W_NAME, mtk_afe_i2s_apll_connect},
+
+ {"FMI2S_MASTER", NULL, I2SIN0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SIN1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SIN2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SIN3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SIN4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SIN6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SOUT0_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SOUT1_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SOUT2_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SOUT3_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SOUT4_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, I2SOUT6_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {"FMI2S_MASTER", NULL, FMI2S_MASTER_MCLK_EN_W_NAME, mtk_afe_i2s_mclk_connect},
+ {FMI2S_MASTER_MCLK_EN_W_NAME, NULL, APLL1_W_NAME, mtk_afe_mclk_apll_connect},
+ {FMI2S_MASTER_MCLK_EN_W_NAME, NULL, APLL2_W_NAME, mtk_afe_mclk_apll_connect},
+ /* CG */
+ {"FMI2S_MASTER", NULL, "FMI2S_MASTER_CG"},
+};
+
+/* i2s dai ops*/
+static int mtk_dai_i2s_config(struct mtk_base_afe *afe,
+ struct snd_pcm_hw_params *params,
+ int i2s_id)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_afe_i2s_priv *i2s_priv;
+ struct mtk_afe_i2s_priv *i2sin_priv = NULL;
+ int id = i2s_id - MT8196_DAI_I2S_IN0;
+ struct mtk_base_etdm_data etdm_data;
+ unsigned int rate = params_rate(params);
+ unsigned int rate_reg = get_etdm_inconn_rate(rate);
+ snd_pcm_format_t format = params_format(params);
+ unsigned int channels = params_channels(params);
+ int ret;
+ unsigned int i2s_con;
+ int pad_top;
+
+ if (i2s_id >= MT8196_DAI_NUM || i2s_id < 0 || id < 0 || id >= DAI_I2S_NUM)
+ return -EINVAL;
+
+ i2s_priv = afe_priv->dai_priv[i2s_id];
+ if (!i2s_priv)
+ return -EINVAL;
+
+ dev_dbg(afe->dev, "id: %d, rate: %d, pcm_fmt: %d, fmt: %d, ch: %d\n",
+ i2s_id, rate, format, i2s_priv->format, channels);
+
+ i2s_priv->rate = rate;
+ etdm_data = mtk_etdm_data[id];
+
+ if (is_etdm_in_pad_top(id))
+ pad_top = 0x3;
+ else
+ pad_top = 0x5;
+
+ switch (id) {
+ case DAI_FMI2S_MASTER:
+ i2s_con = I2S_IN_PAD_IO_MUX << I2SIN_PAD_SEL_SFT;
+ i2s_con |= rate_reg << I2S_MODE_SFT;
+ i2s_con |= I2S_FMT_I2S << I2S_FMT_SFT;
+ i2s_con |= get_i2s_wlen(format) << I2S_WLEN_SFT;
+ regmap_update_bits(afe->regmap, AFE_CONNSYS_I2S_CON,
+ 0xffffeffe, i2s_con);
+ break;
+
+ case DAI_I2SIN0:
+ case DAI_I2SIN1:
+ case DAI_I2SIN2:
+ case DAI_I2SIN3:
+ case DAI_I2SIN4:
+ case DAI_I2SIN6:
+ /* ---etdm in --- */
+ regmap_update_bits(afe->regmap,
+ etdm_data.init_count_reg,
+ etdm_data.init_count_mask << etdm_data.init_count_shift,
+ 0x5 << etdm_data.init_count_shift);
+
+ /* 3: pad top 5: no pad top */
+ regmap_update_bits(afe->regmap,
+ etdm_data.init_point_reg,
+ etdm_data.init_point_mask << etdm_data.init_point_shift,
+ pad_top << etdm_data.init_point_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.lrck_reset_reg,
+ etdm_data.lrck_reset_mask << etdm_data.lrck_reset_shift,
+ 0x1 << etdm_data.lrck_reset_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.clk_source_reg,
+ etdm_data.clk_source_mask << etdm_data.clk_source_shift,
+ ETDM_CLK_SOURCE_APLL << etdm_data.clk_source_shift);
+
+ /* 0: manual 1: auto */
+ regmap_update_bits(afe->regmap,
+ etdm_data.ck_en_sel_reg,
+ etdm_data.ck_en_sel_mask << etdm_data.ck_en_sel_shift,
+ 0x1 << etdm_data.ck_en_sel_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.fs_timing_reg,
+ etdm_data.fs_timing_mask << etdm_data.fs_timing_shift,
+ get_etdm_rate(rate) << etdm_data.fs_timing_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.relatch_en_sel_reg,
+ etdm_data.relatch_en_sel_mask << etdm_data.relatch_en_sel_shift,
+ get_etdm_inconn_rate(rate) << etdm_data.relatch_en_sel_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.use_afifo_reg,
+ etdm_data.use_afifo_mask << etdm_data.use_afifo_shift,
+ 0x0);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.afifo_mode_reg,
+ etdm_data.afifo_mode_mask << etdm_data.afifo_mode_shift,
+ 0x0);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.almost_end_ch_reg,
+ etdm_data.almost_end_ch_mask << etdm_data.almost_end_ch_shift,
+ 0x0);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.almost_end_bit_reg,
+ etdm_data.almost_end_bit_mask << etdm_data.almost_end_bit_shift,
+ 0x0);
+
+ if (is_etdm_in_pad_top(id)) {
+ regmap_update_bits(afe->regmap,
+ etdm_data.out2latch_time_reg,
+ etdm_data.out2latch_time_mask <<
+ etdm_data.out2latch_time_shift,
+ 0x6 << etdm_data.out2latch_time_shift);
+ } else {
+ regmap_update_bits(afe->regmap,
+ etdm_data.out2latch_time_reg,
+ etdm_data.out2latch_time_mask <<
+ etdm_data.out2latch_time_shift,
+ 0x4 << etdm_data.out2latch_time_shift);
+ }
+
+ if (id == DAI_I2SIN4) {
+ dev_dbg(afe->dev, "i2sin4, id: %d, fmt: %d, ch: %d, ip_mode: %d, sync: %d\n",
+ id, i2s_priv->format, channels, i2s_priv->ip_mode, i2s_priv->sync);
+
+ /* Fmt Mode: 0x00 i2s, 0x04 adsp_a, DSP_A mode for multi-channel */
+ regmap_update_bits(afe->regmap,
+ etdm_data.tdm_mode_reg,
+ etdm_data.tdm_mode_mask << etdm_data.tdm_mode_shift,
+ i2s_priv->format << etdm_data.tdm_mode_shift);
+
+ /* set etdm ch */
+ regmap_update_bits(afe->regmap,
+ etdm_data.ch_reg,
+ etdm_data.ch_mask << etdm_data.ch_shift,
+ (channels - 1) << etdm_data.ch_shift);
+
+ /* set etdm ip mode */
+ regmap_update_bits(afe->regmap,
+ etdm_data.ip_mode_reg,
+ etdm_data.ip_mode_mask << etdm_data.ip_mode_shift,
+ i2s_priv->ip_mode << etdm_data.ip_mode_shift);
+
+ /* set etdm sync */
+ regmap_update_bits(afe->regmap,
+ etdm_data.sync_reg,
+ etdm_data.sync_mask << etdm_data.sync_shift,
+ i2s_priv->sync << etdm_data.sync_shift);
+ } else {
+ /* default i2s */
+ regmap_update_bits(afe->regmap,
+ etdm_data.tdm_mode_reg,
+ etdm_data.tdm_mode_mask << etdm_data.tdm_mode_shift,
+ 0x0 << etdm_data.tdm_mode_shift);
+
+ /* set etdm sync */
+ regmap_update_bits(afe->regmap,
+ etdm_data.sync_reg,
+ etdm_data.sync_mask << etdm_data.sync_shift,
+ 0x0 << etdm_data.sync_shift);
+ }
+
+ /* APLL */
+ regmap_update_bits(afe->regmap,
+ etdm_data.relatch_domain_sel_reg,
+ etdm_data.relatch_domain_sel_mask <<
+ etdm_data.relatch_domain_sel_shift,
+ ETDM_RELATCH_SEL_APLL << etdm_data.relatch_domain_sel_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.bit_length_reg,
+ etdm_data.bit_length_mask << etdm_data.bit_length_shift,
+ get_etdm_lrck_width(format) << etdm_data.bit_length_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.word_length_reg,
+ etdm_data.word_length_mask << etdm_data.word_length_shift,
+ get_etdm_wlen(format) << etdm_data.word_length_shift);
+
+ /* ---etdm cowork --- */
+ regmap_update_bits(afe->regmap,
+ etdm_data.cowork_reg,
+ etdm_data.cowork_mask << etdm_data.cowork_shift,
+ etdm_data.cowork_val << etdm_data.cowork_shift);
+
+ /* i2s with pad top setting */
+ if (is_etdm_in_pad_top(id) && etdm_data.pad_top_ck_en_reg != 0) {
+ regmap_update_bits(afe->regmap,
+ etdm_data.pad_top_ck_en_reg,
+ etdm_data.pad_top_ck_en_mask <<
+ etdm_data.pad_top_ck_en_shift,
+ 0x1 << etdm_data.pad_top_ck_en_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.master_latch_reg,
+ etdm_data.master_latch_mask <<
+ etdm_data.master_latch_shift,
+ 0x0);
+ }
+ break;
+
+ case DAI_I2SOUT0:
+ case DAI_I2SOUT1:
+ case DAI_I2SOUT2:
+ case DAI_I2SOUT3:
+ case DAI_I2SOUT4:
+ case DAI_I2SOUT6:
+ /* ---etdm out --- */
+ regmap_update_bits(afe->regmap,
+ etdm_data.init_count_reg,
+ etdm_data.init_count_mask << etdm_data.init_count_shift,
+ 0x5 << etdm_data.init_count_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.init_point_reg,
+ etdm_data.init_point_mask << etdm_data.init_point_shift,
+ 0x6 << etdm_data.init_point_shift);
+
+ // clock speed > 22M need to set relatch time to avoid duplicate porint
+ if (rate * channels * (get_etdm_wlen(format) + 1) >= ETDM_22M_CLOCK_THRES &&
+ get_etdm_wlen(format) >= 2) {
+ regmap_update_bits(afe->regmap,
+ etdm_data.in2latch_time_reg,
+ etdm_data.in2latch_time_mask <<
+ etdm_data.in2latch_time_shift,
+ (get_etdm_wlen(format) - 2) <<
+ etdm_data.in2latch_time_shift);
+ } else {
+ regmap_update_bits(afe->regmap,
+ etdm_data.in2latch_time_reg,
+ etdm_data.in2latch_time_mask <<
+ etdm_data.in2latch_time_shift,
+ 0x6 << etdm_data.in2latch_time_shift);
+ }
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.lrck_reset_reg,
+ etdm_data.lrck_reset_mask << etdm_data.lrck_reset_shift,
+ 0x1 << etdm_data.lrck_reset_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.fs_timing_reg,
+ etdm_data.fs_timing_mask << etdm_data.fs_timing_shift,
+ get_etdm_rate(rate) << etdm_data.fs_timing_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.clk_source_reg,
+ etdm_data.clk_source_mask << etdm_data.clk_source_shift,
+ ETDM_CLK_SOURCE_APLL << etdm_data.clk_source_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.relatch_en_sel_reg,
+ etdm_data.relatch_en_sel_mask << etdm_data.relatch_en_sel_shift,
+ get_etdm_inconn_rate(rate) << etdm_data.relatch_en_sel_shift);
+
+ if (id == DAI_I2SOUT4) {
+ dev_dbg(afe->dev, "i2sout4, id: %d fmt: %d, ch: %d, sync: %d\n",
+ id, i2s_priv->format, channels, i2s_priv->sync);
+
+ /* Fmt Mode: 0x00 i2s, 0x04 adsp_a, DSP_A mode for multi-channel */
+ regmap_update_bits(afe->regmap,
+ etdm_data.tdm_mode_reg,
+ etdm_data.tdm_mode_mask << etdm_data.tdm_mode_shift,
+ i2s_priv->format << etdm_data.tdm_mode_shift);
+
+ /* set etdm ch */
+ regmap_update_bits(afe->regmap,
+ etdm_data.ch_reg,
+ etdm_data.ch_mask << etdm_data.ch_shift,
+ (channels - 1) << etdm_data.ch_shift);
+
+ /* set etdm sync */
+ regmap_update_bits(afe->regmap,
+ etdm_data.sync_reg,
+ etdm_data.sync_mask << etdm_data.sync_shift,
+ i2s_priv->sync << etdm_data.sync_shift);
+ } else {
+ regmap_update_bits(afe->regmap,
+ etdm_data.tdm_mode_reg,
+ etdm_data.tdm_mode_mask << etdm_data.tdm_mode_shift,
+ 0x0);
+ }
+
+ /* APLL */
+ regmap_update_bits(afe->regmap,
+ etdm_data.relatch_domain_sel_reg,
+ etdm_data.relatch_domain_sel_mask <<
+ etdm_data.relatch_domain_sel_shift,
+ ETDM_RELATCH_SEL_APLL << etdm_data.relatch_domain_sel_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.bit_length_reg,
+ etdm_data.bit_length_mask << etdm_data.bit_length_shift,
+ get_etdm_lrck_width(format) << etdm_data.bit_length_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.word_length_reg,
+ etdm_data.word_length_mask << etdm_data.word_length_shift,
+ get_etdm_wlen(format) << etdm_data.word_length_shift);
+
+ /* ---etdm cowork --- */
+ regmap_update_bits(afe->regmap,
+ etdm_data.cowork_reg,
+ etdm_data.cowork_mask << etdm_data.cowork_shift,
+ etdm_data.cowork_val << etdm_data.cowork_shift);
+
+ /* i2s with pad top setting */
+ if (is_etdm_in_pad_top(id) && etdm_data.pad_top_ck_en_reg != 0) {
+ regmap_update_bits(afe->regmap,
+ etdm_data.pad_top_ck_en_reg,
+ etdm_data.cowork_mask << etdm_data.pad_top_ck_en_shift,
+ 0x1 << etdm_data.pad_top_ck_en_shift);
+
+ regmap_update_bits(afe->regmap,
+ etdm_data.master_latch_reg,
+ etdm_data.master_latch_mask <<
+ etdm_data.master_latch_shift,
+ 0x0);
+ }
+ break;
+
+ default:
+ dev_err(afe->dev, "id %d not support\n", id);
+ return -EINVAL;
+ }
+
+ /* set share i2s */
+ if (i2s_priv && i2s_priv->share_i2s_id >= 0) {
+ i2sin_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id];
+ i2sin_priv->format = i2s_priv->format;
+ ret = mtk_dai_i2s_config(afe, params, i2s_priv->share_i2s_id);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mtk_dai_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+
+ return mtk_dai_i2s_config(afe, params, dai->id);
+}
+
+static int mtk_dai_i2s_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_afe_i2s_priv *i2s_priv;
+ int apll;
+ int apll_rate;
+
+ if (dai->id >= MT8196_DAI_NUM || dai->id < 0 || dir != SND_SOC_CLOCK_OUT)
+ return -EINVAL;
+
+ i2s_priv = afe_priv->dai_priv[dai->id];
+ if (!i2s_priv)
+ return -EINVAL;
+
+ dev_dbg(afe->dev, "freq: %u\n", freq);
+
+ apll = mt8196_get_apll_by_rate(afe, freq);
+ apll_rate = mt8196_get_apll_rate(afe, apll);
+
+ if (freq > apll_rate || apll_rate % freq)
+ return -EINVAL;
+
+ i2s_priv->mclk_rate = freq;
+ i2s_priv->mclk_apll = apll;
+
+ if (i2s_priv->share_i2s_id > 0) {
+ struct mtk_afe_i2s_priv *share_i2s_priv;
+
+ share_i2s_priv = afe_priv->dai_priv[i2s_priv->share_i2s_id];
+ if (!share_i2s_priv)
+ return -EINVAL;
+
+ share_i2s_priv->mclk_rate = i2s_priv->mclk_rate;
+ share_i2s_priv->mclk_apll = i2s_priv->mclk_apll;
+ }
+
+ return 0;
+}
+
+static int mtk_dai_i2s_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_afe_i2s_priv *i2s_priv;
+
+ if (dai->id >= MT8196_DAI_NUM || dai->id < 0)
+ return -EINVAL;
+
+ i2s_priv = afe_priv->dai_priv[dai->id];
+ if (!i2s_priv)
+ return -EINVAL;
+
+ dev_dbg(afe->dev, "dai->id: %d, fmt: 0x%x\n", dai->id, fmt);
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ i2s_priv->format = MTK_DAI_ETDM_FORMAT_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ i2s_priv->format = MTK_DAI_ETDM_FORMAT_LJ;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ i2s_priv->format = MTK_DAI_ETDM_FORMAT_RJ;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ i2s_priv->format = MTK_DAI_ETDM_FORMAT_DSPA;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ i2s_priv->format = MTK_DAI_ETDM_FORMAT_DSPB;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops mtk_dai_i2s_ops = {
+ .hw_params = mtk_dai_i2s_hw_params,
+ .set_sysclk = mtk_dai_i2s_set_sysclk,
+ .set_fmt = mtk_dai_i2s_set_fmt,
+};
+
+/* dai driver */
+#define MTK_ETDM_RATES (SNDRV_PCM_RATE_8000_384000)
+#define MTK_ETDM_FORMATS (SNDRV_PCM_FMTBIT_S8 |\
+ SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+#define MT8196_I2S_DAI(_name, _id, max_ch, dir) \
+{ \
+ .name = #_name, \
+ .id = _id, \
+ .dir = { \
+ .stream_name = #_name, \
+ .channels_min = 1, \
+ .channels_max = max_ch, \
+ .rates = MTK_ETDM_RATES, \
+ .formats = MTK_ETDM_FORMATS, \
+ }, \
+ .ops = &mtk_dai_i2s_ops, \
+}
+
+static struct snd_soc_dai_driver mtk_dai_i2s_driver[] = {
+ /* capture */
+ MT8196_I2S_DAI(I2SIN0, MT8196_DAI_I2S_IN0, 2, capture),
+ MT8196_I2S_DAI(I2SIN1, MT8196_DAI_I2S_IN1, 2, capture),
+ MT8196_I2S_DAI(I2SIN2, MT8196_DAI_I2S_IN2, 2, capture),
+ MT8196_I2S_DAI(I2SIN3, MT8196_DAI_I2S_IN3, 2, capture),
+ MT8196_I2S_DAI(I2SIN4, MT8196_DAI_I2S_IN4, 8, capture),
+ MT8196_I2S_DAI(I2SIN6, MT8196_DAI_I2S_IN6, 2, capture),
+ MT8196_I2S_DAI(FMI2S_MASTER, MT8196_DAI_FM_I2S_MASTER, 2, capture),
+ /* playback */
+ MT8196_I2S_DAI(I2SOUT0, MT8196_DAI_I2S_OUT0, 2, playback),
+ MT8196_I2S_DAI(I2SOUT1, MT8196_DAI_I2S_OUT1, 2, playback),
+ MT8196_I2S_DAI(I2SOUT2, MT8196_DAI_I2S_OUT2, 2, playback),
+ MT8196_I2S_DAI(I2SOUT3, MT8196_DAI_I2S_OUT3, 2, playback),
+ MT8196_I2S_DAI(I2SOUT4, MT8196_DAI_I2S_OUT4, 8, playback),
+ MT8196_I2S_DAI(I2SOUT6, MT8196_DAI_I2S_OUT6, 2, playback),
+};
+
+static const struct mtk_afe_i2s_priv mt8196_i2s_priv[DAI_I2S_NUM] = {
+ [DAI_I2SIN0] = {
+ .id = MT8196_DAI_I2S_IN0,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sin0-share",
+ .share_i2s_id = -1,
+ },
+ [DAI_I2SIN1] = {
+ .id = MT8196_DAI_I2S_IN1,
+ .mclk_id = MT8196_I2SIN1_MCK,
+ .share_property_name = "i2sin1-share",
+ .share_i2s_id = -1,
+ },
+ [DAI_I2SIN2] = {
+ .id = MT8196_DAI_I2S_IN2,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sin2-share",
+ .share_i2s_id = -1,
+ },
+ [DAI_I2SIN3] = {
+ .id = MT8196_DAI_I2S_IN3,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sin3-share",
+ .share_i2s_id = -1,
+ },
+ [DAI_I2SIN4] = {
+ .id = MT8196_DAI_I2S_IN4,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sin4-share",
+ .share_i2s_id = -1,
+ .sync = 0,
+ .ip_mode = 0,
+ },
+ [DAI_I2SIN6] = {
+ .id = MT8196_DAI_I2S_IN6,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sout6-share",
+ .share_i2s_id = -1,
+ },
+ [DAI_I2SOUT0] = {
+ .id = MT8196_DAI_I2S_OUT0,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sout0-share",
+ .share_i2s_id = MT8196_DAI_I2S_IN0,
+ },
+ [DAI_I2SOUT1] = {
+ .id = MT8196_DAI_I2S_OUT1,
+ .mclk_id = MT8196_I2SIN1_MCK,
+ .share_property_name = "i2sout1-share",
+ .share_i2s_id = MT8196_DAI_I2S_IN1,
+ },
+ [DAI_I2SOUT2] = {
+ .id = MT8196_DAI_I2S_OUT2,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sout2-share",
+ .share_i2s_id = MT8196_DAI_I2S_IN2,
+ },
+ [DAI_I2SOUT3] = {
+ .id = MT8196_DAI_I2S_OUT3,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sout3-share",
+ .share_i2s_id = MT8196_DAI_I2S_IN3,
+ },
+ [DAI_I2SOUT4] = {
+ .id = MT8196_DAI_I2S_OUT4,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sout4-share",
+ .share_i2s_id = MT8196_DAI_I2S_IN4,
+ .sync = 0,
+ },
+ [DAI_I2SOUT6] = {
+ .id = MT8196_DAI_I2S_OUT6,
+ .mclk_id = MT8196_I2SIN0_MCK,
+ .share_property_name = "i2sout6-share",
+ .share_i2s_id = MT8196_DAI_I2S_IN6,
+ },
+ [DAI_FMI2S_MASTER] = {
+ .id = MT8196_DAI_FM_I2S_MASTER,
+ .mclk_id = MT8196_FMI2S_MCK,
+ .share_property_name = "fmi2s-share",
+ .share_i2s_id = -1,
+ },
+};
+
+static int mt8196_dai_i2s_get_share(struct mtk_base_afe *afe)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ const struct device_node *of_node = afe->dev->of_node;
+
+ for (int i = 0; i < DAI_I2S_NUM; i++) {
+ const char *of_str;
+ struct mtk_afe_i2s_priv *i2s_priv = afe_priv->dai_priv[mt8196_i2s_priv[i].id];
+ const char *property_name = mt8196_i2s_priv[i].share_property_name;
+
+ if (of_property_read_string(of_node, property_name, &of_str))
+ continue;
+
+ i2s_priv->share_i2s_id = get_i2s_id_by_name(afe, of_str);
+ }
+
+ return 0;
+}
+
+static int init_i2s_priv_data(struct mtk_base_afe *afe)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_afe_i2s_priv *i2s_priv;
+
+ for (int i = 0; i < DAI_I2S_NUM; i++) {
+ int id = mt8196_i2s_priv[i].id;
+ size_t size = sizeof(struct mtk_afe_i2s_priv);
+
+ if (id >= MT8196_DAI_NUM || id < 0)
+ return -EINVAL;
+
+ i2s_priv = devm_kzalloc(afe->dev, size, GFP_KERNEL);
+ if (!i2s_priv)
+ return -ENOMEM;
+
+ memcpy(i2s_priv, &mt8196_i2s_priv[i], size);
+
+ afe_priv->dai_priv[id] = i2s_priv;
+ }
+
+ return 0;
+}
+
+int mt8196_dai_i2s_register(struct mtk_base_afe *afe)
+{
+ struct mtk_base_afe_dai *dai;
+ int ret;
+
+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ dai->dai_drivers = mtk_dai_i2s_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_i2s_driver);
+
+ dai->controls = mtk_dai_i2s_controls;
+ dai->num_controls = ARRAY_SIZE(mtk_dai_i2s_controls);
+ dai->dapm_widgets = mtk_dai_i2s_widgets;
+ dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_i2s_widgets);
+ dai->dapm_routes = mtk_dai_i2s_routes;
+ dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_i2s_routes);
+
+ /* set all dai i2s private data */
+ ret = init_i2s_priv_data(afe);
+ if (ret)
+ return ret;
+
+ /* parse share i2s */
+ ret = mt8196_dai_i2s_get_share(afe);
+ if (ret)
+ return ret;
+
+ list_add(&dai->list, &afe->sub_dais);
+
+ return 0;
+}
diff --git a/sound/soc/mediatek/mt8196/mt8196-dai-tdm.c b/sound/soc/mediatek/mt8196/mt8196-dai-tdm.c
new file mode 100644
index 000000000000..b7aeee939d88
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-dai-tdm.c
@@ -0,0 +1,675 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * MediaTek ALSA SoC Audio DAI TDM Control
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#include <linux/regmap.h>
+#include <sound/pcm_params.h>
+
+#include "mt8196-afe-clk.h"
+#include "mt8196-afe-common.h"
+#include "mt8196-interconnection.h"
+
+struct mtk_afe_tdm_priv {
+ int bck_id;
+ int bck_rate;
+
+ int mclk_id;
+ int mclk_multiple; /* according to sample rate */
+ int mclk_rate;
+ int mclk_apll;
+};
+
+enum {
+ TDM_WLEN_8_BIT,
+ TDM_WLEN_16_BIT,
+ TDM_WLEN_24_BIT,
+ TDM_WLEN_32_BIT,
+};
+
+enum {
+ TDM_CHANNEL_BCK_16,
+ TDM_CHANNEL_BCK_24,
+ TDM_CHANNEL_BCK_32,
+};
+
+enum {
+ TDM_CHANNEL_NUM_2,
+ TDM_CHANNEL_NUM_4,
+ TDM_CHANNEL_NUM_8,
+};
+
+enum {
+ TDM_CH_START_O30_O31,
+ TDM_CH_START_O32_O33,
+ TDM_CH_START_O34_O35,
+ TDM_CH_START_O36_O37,
+ TDM_CH_ZERO,
+};
+
+enum {
+ DPTX_CHANNEL_2,
+ DPTX_CHANNEL_8,
+};
+
+enum {
+ DPTX_WLEN_24_BIT,
+ DPTX_WLEN_16_BIT,
+};
+
+#define DPTX_CH_EN_MASK_2CH (0x3)
+#define DPTX_CH_EN_MASK_4CH (0xf)
+#define DPTX_CH_EN_MASK_6CH (0x3f)
+#define DPTX_CH_EN_MASK_8CH (0xff)
+
+static unsigned int get_tdm_wlen(snd_pcm_format_t format)
+{
+ return (snd_pcm_format_physical_width(format) / 8) - 1;
+}
+
+static unsigned int get_tdm_channel_bck(snd_pcm_format_t format)
+{
+ return snd_pcm_format_physical_width(format) <= 16 ?
+ TDM_CHANNEL_BCK_16 : TDM_CHANNEL_BCK_32;
+}
+
+static unsigned int get_tdm_lrck_width(snd_pcm_format_t format)
+{
+ return snd_pcm_format_physical_width(format) - 1;
+}
+
+static unsigned int get_tdm_ch(unsigned int ch)
+{
+ switch (ch) {
+ case 1:
+ case 2:
+ return TDM_CHANNEL_NUM_2;
+ case 3:
+ case 4:
+ return TDM_CHANNEL_NUM_4;
+ case 5:
+ case 6:
+ case 7:
+ case 8:
+ default:
+ return TDM_CHANNEL_NUM_8;
+ }
+}
+
+static unsigned int get_dptx_ch_enable_mask(struct device *dev, unsigned int ch)
+{
+ switch (ch) {
+ case 1:
+ case 2:
+ return DPTX_CH_EN_MASK_2CH;
+ case 3:
+ case 4:
+ return DPTX_CH_EN_MASK_4CH;
+ case 5:
+ case 6:
+ return DPTX_CH_EN_MASK_6CH;
+ case 7:
+ case 8:
+ return DPTX_CH_EN_MASK_8CH;
+ default:
+ dev_warn(dev, "invalid channel num, default use 2ch\n");
+ return DPTX_CH_EN_MASK_2CH;
+ }
+}
+
+static unsigned int get_dptx_ch(unsigned int ch)
+{
+ if (ch == 2)
+ return DPTX_CHANNEL_2;
+ else
+ return DPTX_CHANNEL_8;
+}
+
+static unsigned int get_dptx_wlen(snd_pcm_format_t format)
+{
+ return snd_pcm_format_physical_width(format) <= 16 ?
+ DPTX_WLEN_16_BIT : DPTX_WLEN_24_BIT;
+}
+
+/* interconnection */
+enum {
+ HDMI_CONN_CH0,
+ HDMI_CONN_CH1,
+ HDMI_CONN_CH2,
+ HDMI_CONN_CH3,
+ HDMI_CONN_CH4,
+ HDMI_CONN_CH5,
+ HDMI_CONN_CH6,
+ HDMI_CONN_CH7,
+};
+
+static const char *const hdmi_conn_mux_map[] = {
+ "CH0", "CH1", "CH2", "CH3", "CH4", "CH5", "CH6", "CH7",
+};
+
+static int hdmi_conn_mux_map_value[] = {
+ HDMI_CONN_CH0, HDMI_CONN_CH1, HDMI_CONN_CH2, HDMI_CONN_CH3,
+ HDMI_CONN_CH4, HDMI_CONN_CH5, HDMI_CONN_CH6, HDMI_CONN_CH7,
+};
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch0_mux_map_enum,
+ AFE_HDMI_CONN0, HDMI_O_0_SFT, HDMI_O_0_MASK,
+ hdmi_conn_mux_map, hdmi_conn_mux_map_value);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch1_mux_map_enum,
+ AFE_HDMI_CONN0,
+ HDMI_O_1_SFT,
+ HDMI_O_1_MASK,
+ hdmi_conn_mux_map,
+ hdmi_conn_mux_map_value);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch2_mux_map_enum,
+ AFE_HDMI_CONN0,
+ HDMI_O_2_SFT,
+ HDMI_O_2_MASK,
+ hdmi_conn_mux_map,
+ hdmi_conn_mux_map_value);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch3_mux_map_enum,
+ AFE_HDMI_CONN0,
+ HDMI_O_3_SFT,
+ HDMI_O_3_MASK,
+ hdmi_conn_mux_map,
+ hdmi_conn_mux_map_value);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch4_mux_map_enum,
+ AFE_HDMI_CONN0,
+ HDMI_O_4_SFT,
+ HDMI_O_4_MASK,
+ hdmi_conn_mux_map,
+ hdmi_conn_mux_map_value);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch5_mux_map_enum,
+ AFE_HDMI_CONN0,
+ HDMI_O_5_SFT,
+ HDMI_O_5_MASK,
+ hdmi_conn_mux_map,
+ hdmi_conn_mux_map_value);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch6_mux_map_enum,
+ AFE_HDMI_CONN0,
+ HDMI_O_6_SFT,
+ HDMI_O_6_MASK,
+ hdmi_conn_mux_map,
+ hdmi_conn_mux_map_value);
+
+static SOC_VALUE_ENUM_SINGLE_DECL(hdmi_ch7_mux_map_enum,
+ AFE_HDMI_CONN0,
+ HDMI_O_7_SFT,
+ HDMI_O_7_MASK,
+ hdmi_conn_mux_map,
+ hdmi_conn_mux_map_value);
+
+static const struct snd_kcontrol_new mtk_dai_tdm_controls[] = {
+ SOC_ENUM("HDMI_CH0_MUX", hdmi_ch0_mux_map_enum),
+ SOC_ENUM("HDMI_CH1_MUX", hdmi_ch1_mux_map_enum),
+ SOC_ENUM("HDMI_CH2_MUX", hdmi_ch2_mux_map_enum),
+ SOC_ENUM("HDMI_CH3_MUX", hdmi_ch3_mux_map_enum),
+ SOC_ENUM("HDMI_CH4_MUX", hdmi_ch4_mux_map_enum),
+ SOC_ENUM("HDMI_CH5_MUX", hdmi_ch5_mux_map_enum),
+ SOC_ENUM("HDMI_CH6_MUX", hdmi_ch6_mux_map_enum),
+ SOC_ENUM("HDMI_CH7_MUX", hdmi_ch7_mux_map_enum),
+};
+
+static const char *const tdm_out_demux_texts[] = {
+ "NONE", "TDMOUT", "DPTXOUT",
+};
+
+static SOC_ENUM_SINGLE_DECL(tdm_out_demux_enum,
+ SND_SOC_NOPM,
+ 0,
+ tdm_out_demux_texts);
+static const struct snd_kcontrol_new tdm_out_demux_control =
+ SOC_DAPM_ENUM("TDM DEMUX ROUTE", tdm_out_demux_enum);
+
+enum {
+ SUPPLY_SEQ_APLL,
+ SUPPLY_SEQ_TDM_MCK_EN,
+ SUPPLY_SEQ_TDM_BCK_EN,
+ SUPPLY_SEQ_TDM_DPTX_MCK_EN,
+ SUPPLY_SEQ_TDM_DPTX_BCK_EN,
+ SUPPLY_SEQ_TDM_CG_EN,
+};
+
+static int get_tdm_id_by_name(const char *name)
+{
+ if (strstr(name, "DPTX"))
+ return MT8196_DAI_TDM_DPTX;
+ else
+ return MT8196_DAI_TDM;
+}
+
+static int mtk_tdm_bck_en_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int dai_id = get_tdm_id_by_name(w->name);
+ struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
+
+ dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d\n",
+ w->name, event, dai_id);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mt8196_mck_enable(afe, tdm_priv->bck_id, tdm_priv->bck_rate);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ mt8196_mck_disable(afe, tdm_priv->bck_id);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int mtk_tdm_mck_en_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(w->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int dai_id = get_tdm_id_by_name(w->name);
+ struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
+
+ dev_dbg(cmpnt->dev, "name %s, event 0x%x, dai_id %d\n",
+ w->name, event, dai_id);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ mt8196_mck_enable(afe, tdm_priv->mclk_id, tdm_priv->mclk_rate);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ tdm_priv->mclk_rate = 0;
+ mt8196_mck_disable(afe, tdm_priv->mclk_id);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget mtk_dai_tdm_widgets[] = {
+ SND_SOC_DAPM_DEMUX("TDM_DEMUX", SND_SOC_NOPM, 0, 0,
+ &tdm_out_demux_control),
+
+ SND_SOC_DAPM_SUPPLY_S("TDM_BCK", SUPPLY_SEQ_TDM_BCK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_tdm_bck_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("TDM_MCK", SUPPLY_SEQ_TDM_MCK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_tdm_mck_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_BCK", SUPPLY_SEQ_TDM_DPTX_BCK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_tdm_bck_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ SND_SOC_DAPM_SUPPLY_S("TDM_DPTX_MCK", SUPPLY_SEQ_TDM_DPTX_MCK_EN,
+ SND_SOC_NOPM, 0, 0,
+ mtk_tdm_mck_en_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+
+ /* cg */
+ SND_SOC_DAPM_SUPPLY_S("TDM_CG", SUPPLY_SEQ_TDM_CG_EN,
+ AUDIO_TOP_CON2, PDN_TDM_OUT_SFT, 1,
+ NULL, 0),
+};
+
+static int mtk_afe_tdm_apll_connect(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_component *cmpnt = snd_soc_dapm_to_component(sink->dapm);
+ struct mtk_base_afe *afe = snd_soc_component_get_drvdata(cmpnt);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int dai_id = get_tdm_id_by_name(sink->name);
+ struct mtk_afe_tdm_priv *tdm_priv = afe_priv->dai_priv[dai_id];
+ int cur_apll;
+
+ /* which apll */
+ cur_apll = mt8196_get_apll_by_name(afe, source->name);
+
+ return (tdm_priv->mclk_apll == cur_apll) ? 1 : 0;
+}
+
+static const struct snd_soc_dapm_route mtk_dai_tdm_routes[] = {
+ {"TDM_DEMUX", NULL, "HDMI"},
+
+ {"TDM", "TDMOUT", "TDM_DEMUX"},
+ {"TDM", NULL, "TDM_BCK"},
+ {"TDM", NULL, "TDM_CG"},
+
+ {"TDM_DPTX", "DPTXOUT", "TDM_DEMUX"},
+ {"TDM_DPTX", NULL, "TDM_DPTX_BCK"},
+ {"TDM_DPTX", NULL, "TDM_CG"},
+
+ {"TDM_BCK", NULL, "TDM_MCK"},
+ {"TDM_DPTX_BCK", NULL, "TDM_DPTX_MCK"},
+ {"TDM_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
+ {"TDM_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
+ {"TDM_DPTX_MCK", NULL, APLL1_W_NAME, mtk_afe_tdm_apll_connect},
+ {"TDM_DPTX_MCK", NULL, APLL2_W_NAME, mtk_afe_tdm_apll_connect},
+};
+
+/* dai ops */
+static int mtk_dai_tdm_cal_mclk(struct mtk_base_afe *afe,
+ struct mtk_afe_tdm_priv *tdm_priv,
+ int freq)
+{
+ int apll;
+ int apll_rate;
+
+ apll = mt8196_get_apll_by_rate(afe, freq);
+ apll_rate = mt8196_get_apll_rate(afe, apll);
+
+ if (freq > apll_rate)
+ return -EINVAL;
+
+ if (apll_rate % freq != 0)
+ return -EINVAL;
+
+ tdm_priv->mclk_rate = freq;
+ tdm_priv->mclk_apll = apll;
+
+ return 0;
+}
+
+static int mtk_dai_tdm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ int tdm_id = dai->id;
+ struct mtk_afe_tdm_priv *tdm_priv;
+ unsigned int rate = params_rate(params);
+ unsigned int channels = params_channels(params);
+ snd_pcm_format_t format = params_format(params);
+ unsigned int tdm_con = 0;
+
+ if (tdm_id >= MT8196_DAI_NUM || tdm_id < 0)
+ return -EINVAL;
+
+ tdm_priv = afe_priv->dai_priv[tdm_id];
+
+ if (!tdm_priv)
+ return -EINVAL;
+
+ /* calculate mclk_rate, if not set explicitly */
+ if (!tdm_priv->mclk_rate) {
+ tdm_priv->mclk_rate = rate * tdm_priv->mclk_multiple;
+ mtk_dai_tdm_cal_mclk(afe,
+ tdm_priv,
+ tdm_priv->mclk_rate);
+ }
+
+ /* calculate bck */
+ tdm_priv->bck_rate = rate *
+ channels *
+ snd_pcm_format_physical_width(format);
+
+ if (tdm_priv->bck_rate > tdm_priv->mclk_rate)
+ return -EINVAL;
+
+ if (tdm_priv->mclk_rate % tdm_priv->bck_rate != 0)
+ return -EINVAL;
+
+ dev_dbg(afe->dev, "id %d, rate %d, ch %d, fmt %d, mclk %d, bck %d\n",
+ tdm_id, rate, channels, format, tdm_priv->mclk_rate, tdm_priv->bck_rate);
+
+ /* set tdm */
+ tdm_con = 0 << BCK_INVERSE_SFT;
+ tdm_con |= 0 << LRCK_INVERSE_SFT;
+ tdm_con |= 0 << DELAY_DATA_SFT;
+ tdm_con |= 1 << LEFT_ALIGN_SFT;
+ tdm_con |= get_tdm_wlen(format) << WLEN_SFT;
+ tdm_con |= get_tdm_ch(channels) << CHANNEL_NUM_SFT;
+ tdm_con |= get_tdm_channel_bck(format) << CHANNEL_BCK_CYCLES_SFT;
+ tdm_con |= get_tdm_lrck_width(format) << LRCK_TDM_WIDTH_SFT;
+ regmap_write(afe->regmap, AFE_TDM_CON1, tdm_con);
+
+ /* set dptx */
+ if (tdm_id == MT8196_DAI_TDM_DPTX) {
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ DPTX_CHANNEL_ENABLE_MASK_SFT,
+ get_dptx_ch_enable_mask(afe->dev, channels) <<
+ DPTX_CHANNEL_ENABLE_SFT);
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ DPTX_CHANNEL_NUMBER_MASK_SFT,
+ get_dptx_ch(channels) <<
+ DPTX_CHANNEL_NUMBER_SFT);
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ DPTX_16BIT_MASK_SFT,
+ get_dptx_wlen(format) << DPTX_16BIT_SFT);
+ }
+ switch (channels) {
+ case 1:
+ case 2:
+ tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
+ tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT1_SFT;
+ tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
+ tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
+ break;
+ case 3:
+ case 4:
+ tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
+ tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
+ tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT2_SFT;
+ tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
+ break;
+ case 5:
+ case 6:
+ tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
+ tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
+ tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
+ tdm_con |= TDM_CH_ZERO << ST_CH_PAIR_SOUT3_SFT;
+ break;
+ case 7:
+ case 8:
+ tdm_con = TDM_CH_START_O30_O31 << ST_CH_PAIR_SOUT0_SFT;
+ tdm_con |= TDM_CH_START_O32_O33 << ST_CH_PAIR_SOUT1_SFT;
+ tdm_con |= TDM_CH_START_O34_O35 << ST_CH_PAIR_SOUT2_SFT;
+ tdm_con |= TDM_CH_START_O36_O37 << ST_CH_PAIR_SOUT3_SFT;
+ break;
+ default:
+ tdm_con = 0;
+ }
+
+ regmap_write(afe->regmap, AFE_TDM_CON2, tdm_con);
+ regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
+ HDMI_CH_NUM_MASK_SFT,
+ channels << HDMI_CH_NUM_SFT);
+
+ return 0;
+}
+
+static int mtk_dai_tdm_trigger(struct snd_pcm_substream *substream,
+ int cmd,
+ struct snd_soc_dai *dai)
+{
+ struct mtk_base_afe *afe = snd_soc_dai_get_drvdata(dai);
+ int tdm_id = dai->id;
+
+ dev_dbg(afe->dev, "cmd %d, tdm_id %d\n", cmd, tdm_id);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ /* enable Out control */
+ regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
+ HDMI_OUT_ON_MASK_SFT,
+ 0x1 << HDMI_OUT_ON_SFT);
+
+ /* enable dptx */
+ if (tdm_id == MT8196_DAI_TDM_DPTX) {
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ DPTX_ON_MASK_SFT, 0x1 <<
+ DPTX_ON_SFT);
+ }
+
+ /* enable tdm */
+ regmap_update_bits(afe->regmap, AFE_TDM_CON1,
+ TDM_EN_MASK_SFT, 0x1 << TDM_EN_SFT);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ /* disable tdm */
+ regmap_update_bits(afe->regmap, AFE_TDM_CON1,
+ TDM_EN_MASK_SFT, 0);
+
+ /* disable dptx */
+ if (tdm_id == MT8196_DAI_TDM_DPTX) {
+ regmap_update_bits(afe->regmap, AFE_DPTX_CON,
+ DPTX_ON_MASK_SFT, 0);
+ }
+
+ /* disable Out control */
+ regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
+ HDMI_OUT_ON_MASK_SFT, 0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mtk_dai_tdm_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct mtk_base_afe *afe = dev_get_drvdata(dai->dev);
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_afe_tdm_priv *tdm_priv;
+
+ if (dai->id >= MT8196_DAI_NUM || dai->id < 0)
+ return -EINVAL;
+
+ tdm_priv = afe_priv->dai_priv[dai->id];
+
+ if (!tdm_priv)
+ return -EINVAL;
+
+ if (dir != SND_SOC_CLOCK_OUT)
+ return -EINVAL;
+
+ dev_dbg(afe->dev, "freq %d\n", freq);
+
+ return mtk_dai_tdm_cal_mclk(afe, tdm_priv, freq);
+}
+
+static const struct snd_soc_dai_ops mtk_dai_tdm_ops = {
+ .hw_params = mtk_dai_tdm_hw_params,
+ .trigger = mtk_dai_tdm_trigger,
+ .set_sysclk = mtk_dai_tdm_set_sysclk,
+};
+
+/* dai driver */
+#define MTK_TDM_RATES (SNDRV_PCM_RATE_8000_48000 |\
+ SNDRV_PCM_RATE_88200 |\
+ SNDRV_PCM_RATE_96000 |\
+ SNDRV_PCM_RATE_176400 |\
+ SNDRV_PCM_RATE_192000)
+
+#define MTK_TDM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE |\
+ SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver mtk_dai_tdm_driver[] = {
+ {
+ .name = "TDM",
+ .id = MT8196_DAI_TDM,
+ .playback = {
+ .stream_name = "TDM",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = MTK_TDM_RATES,
+ .formats = MTK_TDM_FORMATS,
+ },
+ .ops = &mtk_dai_tdm_ops,
+ },
+ {
+ .name = "TDM_DPTX",
+ .id = MT8196_DAI_TDM_DPTX,
+ .playback = {
+ .stream_name = "TDM_DPTX",
+ .channels_min = 2,
+ .channels_max = 8,
+ .rates = MTK_TDM_RATES,
+ .formats = MTK_TDM_FORMATS,
+ },
+ .ops = &mtk_dai_tdm_ops,
+ },
+};
+
+static struct mtk_afe_tdm_priv *init_tdm_priv_data(struct mtk_base_afe *afe,
+ int id)
+{
+ struct mtk_afe_tdm_priv *tdm_priv;
+
+ tdm_priv = devm_kzalloc(afe->dev, sizeof(struct mtk_afe_tdm_priv),
+ GFP_KERNEL);
+ if (!tdm_priv)
+ return NULL;
+
+ if (id == MT8196_DAI_TDM_DPTX)
+ tdm_priv->mclk_multiple = 256;
+ else
+ tdm_priv->mclk_multiple = 128;
+
+ tdm_priv->bck_id = MT8196_TDMOUT_BCK;
+ tdm_priv->mclk_id = MT8196_TDMOUT_MCK;
+
+ return tdm_priv;
+}
+
+int mt8196_dai_tdm_register(struct mtk_base_afe *afe)
+{
+ struct mt8196_afe_private *afe_priv = afe->platform_priv;
+ struct mtk_afe_tdm_priv *tdm_priv, *tdm_dptx_priv;
+ struct mtk_base_afe_dai *dai;
+
+ dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
+ if (!dai)
+ return -ENOMEM;
+
+ dai->dai_drivers = mtk_dai_tdm_driver;
+ dai->num_dai_drivers = ARRAY_SIZE(mtk_dai_tdm_driver);
+ dai->controls = mtk_dai_tdm_controls;
+ dai->num_controls = ARRAY_SIZE(mtk_dai_tdm_controls);
+ dai->dapm_widgets = mtk_dai_tdm_widgets;
+ dai->num_dapm_widgets = ARRAY_SIZE(mtk_dai_tdm_widgets);
+ dai->dapm_routes = mtk_dai_tdm_routes;
+ dai->num_dapm_routes = ARRAY_SIZE(mtk_dai_tdm_routes);
+
+ tdm_priv = init_tdm_priv_data(afe, MT8196_DAI_TDM);
+ if (!tdm_priv)
+ return -ENOMEM;
+
+ tdm_dptx_priv = init_tdm_priv_data(afe, MT8196_DAI_TDM_DPTX);
+ if (!tdm_dptx_priv)
+ return -ENOMEM;
+
+ list_add(&dai->list, &afe->sub_dais);
+
+ afe_priv->dai_priv[MT8196_DAI_TDM] = tdm_priv;
+ afe_priv->dai_priv[MT8196_DAI_TDM_DPTX] = tdm_dptx_priv;
+
+ return 0;
+}
+
diff --git a/sound/soc/mediatek/mt8196/mt8196-interconnection.h b/sound/soc/mediatek/mt8196/mt8196-interconnection.h
new file mode 100644
index 000000000000..acb91da3b4db
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-interconnection.h
@@ -0,0 +1,121 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Mediatek MT8196 audio driver interconnection definition
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#ifndef _MT8196_INTERCONNECTION_H_
+#define _MT8196_INTERCONNECTION_H_
+
+/* in port define */
+
+#define I_CONNSYS_I2S_CH1 0
+#define I_CONNSYS_I2S_CH2 1
+#define I_GAIN0_OUT_CH1 6
+#define I_GAIN0_OUT_CH2 7
+#define I_GAIN1_OUT_CH1 8
+#define I_GAIN1_OUT_CH2 9
+#define I_GAIN2_OUT_CH1 10
+#define I_GAIN2_OUT_CH2 11
+#define I_GAIN3_OUT_CH1 12
+#define I_GAIN3_OUT_CH2 13
+#define I_STF_CH1 14
+#define I_ADDA_UL_CH1 16
+#define I_ADDA_UL_CH2 17
+#define I_ADDA_UL_CH3 18
+#define I_ADDA_UL_CH4 19
+#define I_UL_PROX_CH1 20
+#define I_UL_PROX_CH2 21
+#define I_ADDA_UL_CH5 24
+#define I_ADDA_UL_CH6 25
+#define I_DMIC0_CH1 28
+#define I_DMIC0_CH2 29
+#define I_DMIC1_CH1 30
+#define I_DMIC1_CH2 31
+
+/* in port define >= 32 */
+#define I_32_OFFSET 32
+#define I_DL0_CH1 (32 - I_32_OFFSET)
+#define I_DL0_CH2 (33 - I_32_OFFSET)
+#define I_DL1_CH1 (34 - I_32_OFFSET)
+#define I_DL1_CH2 (35 - I_32_OFFSET)
+#define I_DL2_CH1 (36 - I_32_OFFSET)
+#define I_DL2_CH2 (37 - I_32_OFFSET)
+#define I_DL3_CH1 (38 - I_32_OFFSET)
+#define I_DL3_CH2 (39 - I_32_OFFSET)
+#define I_DL4_CH1 (40 - I_32_OFFSET)
+#define I_DL4_CH2 (41 - I_32_OFFSET)
+#define I_DL5_CH1 (42 - I_32_OFFSET)
+#define I_DL5_CH2 (43 - I_32_OFFSET)
+#define I_DL6_CH1 (44 - I_32_OFFSET)
+#define I_DL6_CH2 (45 - I_32_OFFSET)
+#define I_DL7_CH1 (46 - I_32_OFFSET)
+#define I_DL7_CH2 (47 - I_32_OFFSET)
+#define I_DL8_CH1 (48 - I_32_OFFSET)
+#define I_DL8_CH2 (49 - I_32_OFFSET)
+#define I_DL_4CH_CH1 (50 - I_32_OFFSET)
+#define I_DL_4CH_CH2 (51 - I_32_OFFSET)
+#define I_DL_4CH_CH3 (52 - I_32_OFFSET)
+#define I_DL_4CH_CH4 (53 - I_32_OFFSET)
+#define I_DL_24CH_CH1 (54 - I_32_OFFSET)
+#define I_DL_24CH_CH2 (55 - I_32_OFFSET)
+#define I_DL_24CH_CH3 (56 - I_32_OFFSET)
+#define I_DL_24CH_CH4 (57 - I_32_OFFSET)
+#define I_DL_24CH_CH5 (58 - I_32_OFFSET)
+#define I_DL_24CH_CH6 (59 - I_32_OFFSET)
+#define I_DL_24CH_CH7 (60 - I_32_OFFSET)
+#define I_DL_24CH_CH8 (61 - I_32_OFFSET)
+
+/* in port define >= 64 */
+#define I_64_OFFSET 64
+#define I_DL23_CH1 (78 - I_64_OFFSET)
+#define I_DL23_CH2 (79 - I_64_OFFSET)
+#define I_DL24_CH1 (80 - I_64_OFFSET)
+#define I_DL24_CH2 (81 - I_64_OFFSET)
+#define I_DL25_CH1 (82 - I_64_OFFSET)
+#define I_DL25_CH2 (83 - I_64_OFFSET)
+#define I_DL26_CH1 (84 - I_64_OFFSET)
+#define I_DL26_CH2 (85 - I_64_OFFSET)
+
+/* in port define >= 128 */
+#define I_128_OFFSET 128
+#define I_PCM_0_CAP_CH1 (130 - I_128_OFFSET)
+#define I_PCM_0_CAP_CH2 (131 - I_128_OFFSET)
+#define I_PCM_1_CAP_CH1 (132 - I_128_OFFSET)
+#define I_PCM_1_CAP_CH2 (133 - I_128_OFFSET)
+#define I_I2SIN0_CH1 (134 - I_128_OFFSET)
+#define I_I2SIN0_CH2 (135 - I_128_OFFSET)
+#define I_I2SIN1_CH1 (136 - I_128_OFFSET)
+#define I_I2SIN1_CH2 (137 - I_128_OFFSET)
+#define I_I2SIN2_CH1 (138 - I_128_OFFSET)
+#define I_I2SIN2_CH2 (139 - I_128_OFFSET)
+#define I_I2SIN3_CH1 (140 - I_128_OFFSET)
+#define I_I2SIN3_CH2 (141 - I_128_OFFSET)
+#define I_I2SIN4_CH1 (142 - I_128_OFFSET)
+#define I_I2SIN4_CH2 (143 - I_128_OFFSET)
+#define I_I2SIN4_CH3 (144 - I_128_OFFSET)
+#define I_I2SIN4_CH4 (145 - I_128_OFFSET)
+#define I_I2SIN4_CH5 (146 - I_128_OFFSET)
+#define I_I2SIN4_CH6 (147 - I_128_OFFSET)
+#define I_I2SIN4_CH7 (148 - I_128_OFFSET)
+#define I_I2SIN4_CH8 (149 - I_128_OFFSET)
+
+/* in port define >= 160 */
+#define I_160_OFFSET 160
+#define I_I2SIN6_CH1 (166 - I_160_OFFSET)
+#define I_I2SIN6_CH2 (167 - I_160_OFFSET)
+
+/* in port define >= 192 */
+#define I_192_OFFSET 192
+#define I_SRC_0_OUT_CH1 (198 - I_192_OFFSET)
+#define I_SRC_0_OUT_CH2 (199 - I_192_OFFSET)
+#define I_SRC_1_OUT_CH1 (200 - I_192_OFFSET)
+#define I_SRC_1_OUT_CH2 (201 - I_192_OFFSET)
+#define I_SRC_2_OUT_CH1 (202 - I_192_OFFSET)
+#define I_SRC_2_OUT_CH2 (203 - I_192_OFFSET)
+#define I_SRC_3_OUT_CH1 (204 - I_192_OFFSET)
+#define I_SRC_3_OUT_CH2 (205 - I_192_OFFSET)
+
+#endif
diff --git a/sound/soc/mediatek/mt8196/mt8196-nau8825.c b/sound/soc/mediatek/mt8196/mt8196-nau8825.c
new file mode 100644
index 000000000000..c9424786c53d
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-nau8825.c
@@ -0,0 +1,870 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * mt8196-nau8825.c -- mt8196 nau8825 ALSA SoC machine driver
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#include <linux/input.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/pm_runtime.h>
+
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/pcm_params.h>
+
+#include "mt8196-afe-common.h"
+
+#include "../../codecs/nau8825.h"
+#include "../../codecs/rt5682s.h"
+
+#include "../common/mtk-soc-card.h"
+#include "../common/mtk-dsp-sof-common.h"
+#include "../common/mtk-soundcard-driver.h"
+#include "../common/mtk-afe-platform-driver.h"
+
+#define NAU8825_HS_PRESENT BIT(0)
+#define RT5682S_HS_PRESENT BIT(1)
+#define RT5650_HS_PRESENT BIT(2)
+
+/*
+ * Nau88l25
+ */
+#define NAU8825_CODEC_DAI "nau8825-hifi"
+
+/*
+ * Rt5682s
+ */
+#define RT5682S_CODEC_DAI "rt5682s-aif1"
+
+/*
+ * Rt5650
+ */
+#define RT5650_CODEC_DAI "rt5645-aif1"
+
+#define SOF_DMA_DL1 "SOF_DMA_DL1"
+#define SOF_DMA_DL_24CH "SOF_DMA_DL_24CH"
+#define SOF_DMA_UL0 "SOF_DMA_UL0"
+#define SOF_DMA_UL1 "SOF_DMA_UL1"
+#define SOF_DMA_UL2 "SOF_DMA_UL2"
+
+enum mt8196_jacks {
+ MT8196_JACK_HEADSET,
+ MT8196_JACK_DP,
+ MT8196_JACK_HDMI,
+ MT8196_JACK_MAX,
+};
+
+static struct snd_soc_jack_pin mt8196_dp_jack_pins[] = {
+ {
+ .pin = "DP",
+ .mask = SND_JACK_AVOUT,
+ },
+};
+
+static struct snd_soc_jack_pin mt8196_hdmi_jack_pins[] = {
+ {
+ .pin = "HDMI",
+ .mask = SND_JACK_AVOUT,
+ },
+};
+
+static struct snd_soc_jack_pin nau8825_jack_pins[] = {
+ {
+ .pin = "Headphone Jack",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
+};
+
+static const struct snd_kcontrol_new mt8196_dumb_spk_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Ext Spk"),
+};
+
+static const struct snd_soc_dapm_widget mt8196_dumb_spk_widgets[] = {
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+};
+
+static const struct snd_soc_dapm_widget mt8196_nau8825_widgets[] = {
+ SND_SOC_DAPM_HP("Headphone Jack", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+ SND_SOC_DAPM_SINK("DP"),
+};
+
+static const struct snd_kcontrol_new mt8196_nau8825_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Headphone Jack"),
+ SOC_DAPM_PIN_SWITCH("Headset Mic"),
+};
+
+#define EXT_SPK_AMP_W_NAME "Ext_Speaker_Amp"
+
+static struct snd_soc_card mt8196_nau8825_soc_card;
+
+static const struct snd_soc_dapm_widget mt8196_nau8825_card_widgets[] = {
+ /* SOF Uplink */
+ SND_SOC_DAPM_MIXER("SOF_DMA_UL0", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SOF_DMA_UL1", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SOF_DMA_UL2", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /*
+ * SOF Downlink
+ * the widgets on the machine driver cannot use the parameter with kcontrol
+ * because the widget domain is its platform driver. so sof downlink route
+ * is written in the i2s dai driver.
+ */
+};
+
+static const struct snd_soc_dapm_route mt8196_nau8825_card_routes[] = {
+ /* SOF Uplink */
+ {"SOF_DMA_UL0", NULL, "UL0_CH1"},
+ {"SOF_DMA_UL0", NULL, "UL0_CH2"},
+ /* SOF Uplink */
+ {"SOF_DMA_UL1", NULL, "UL1_CH1"},
+ {"SOF_DMA_UL1", NULL, "UL1_CH2"},
+ /* SOF Uplink */
+ {"SOF_DMA_UL2", NULL, "UL2_CH1"},
+ {"SOF_DMA_UL2", NULL, "UL2_CH2"},
+};
+
+static const struct snd_kcontrol_new mt8196_nau8825_card_controls[] = {
+ SOC_DAPM_PIN_SWITCH(EXT_SPK_AMP_W_NAME),
+};
+
+/*
+ * define mtk_spk_i2s_mck node in dts when need mclk,
+ * BE i2s need assign snd_soc_ops = mt8196_nau8825_i2s_ops
+ */
+static int mt8196_nau8825_i2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ unsigned int rate = params_rate(params);
+ unsigned int mclk_fs_ratio = 128;
+ unsigned int mclk_fs = rate * mclk_fs_ratio;
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+
+ return snd_soc_dai_set_sysclk(cpu_dai,
+ 0, mclk_fs, SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8196_nau8825_i2s_ops = {
+ .hw_params = mt8196_nau8825_i2s_hw_params,
+};
+
+static int mt8196_dptx_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ unsigned int rate = params_rate(params);
+ unsigned int mclk_fs_ratio = 256;
+ unsigned int mclk_fs = rate * mclk_fs_ratio;
+ struct snd_soc_dai *dai = snd_soc_rtd_to_cpu(rtd, 0);
+
+ return snd_soc_dai_set_sysclk(dai, 0, mclk_fs, SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8196_dptx_ops = {
+ .hw_params = mt8196_dptx_hw_params,
+};
+
+static int mt8196_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+ struct snd_pcm_hw_params *params)
+{
+ dev_info(rtd->dev, "fix format to 32bit\n");
+
+ /* fix BE i2s format to 32bit, clean param mask first */
+ snd_mask_reset_range(hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT),
+ 0, (__force unsigned int)SNDRV_PCM_FORMAT_LAST);
+
+ params_set_format(params, SNDRV_PCM_FORMAT_S32_LE);
+ return 0;
+}
+
+static int mt8196_sof_be_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_component *cmpnt_afe = NULL;
+ struct snd_soc_pcm_runtime *runtime;
+
+ /* find afe component */
+ for_each_card_rtds(rtd->card, runtime) {
+ cmpnt_afe = snd_soc_rtdcom_lookup(runtime, AFE_PCM_NAME);
+ if (cmpnt_afe) {
+ dev_info(rtd->dev, "component->name: %s\n", cmpnt_afe->name);
+ break;
+ }
+ }
+
+ if (cmpnt_afe && !pm_runtime_active(cmpnt_afe->dev)) {
+ dev_err(rtd->dev, "afe pm runtime is not active!!\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8196_sof_be_ops = {
+ .hw_params = mt8196_sof_be_hw_params,
+};
+
+static const struct sof_conn_stream g_sof_conn_streams[] = {
+ {
+ .sof_link = "AFE_SOF_DL1",
+ .sof_dma = SOF_DMA_DL1,
+ .stream_dir = SNDRV_PCM_STREAM_PLAYBACK
+ },
+ {
+ .sof_link = "AFE_SOF_DL_24CH",
+ .sof_dma = SOF_DMA_DL_24CH,
+ .stream_dir = SNDRV_PCM_STREAM_PLAYBACK
+ },
+ {
+ .sof_link = "AFE_SOF_UL0",
+ .sof_dma = SOF_DMA_UL0,
+ .stream_dir = SNDRV_PCM_STREAM_CAPTURE
+ },
+ {
+ .sof_link = "AFE_SOF_UL1",
+ .sof_dma = SOF_DMA_UL1,
+ .stream_dir = SNDRV_PCM_STREAM_CAPTURE
+ },
+ {
+ .sof_link = "AFE_SOF_UL2",
+ .sof_dma = SOF_DMA_UL2,
+ .stream_dir = SNDRV_PCM_STREAM_CAPTURE
+ },
+};
+
+/* FE */
+SND_SOC_DAILINK_DEFS(playback1,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(playback_24ch,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL_24CH")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(capture0,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL0")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(capture1,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(capture2,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(playback_hdmi,
+ DAILINK_COMP_ARRAY(COMP_CPU("HDMI")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(playback2,
+ DAILINK_COMP_ARRAY(COMP_CPU("DL2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(capture_cm0,
+ DAILINK_COMP_ARRAY(COMP_CPU("UL_CM0")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+/* BE */
+SND_SOC_DAILINK_DEFS(ap_dmic,
+ DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(ap_dmic_ch34,
+ DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_CH34")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(ap_dmic_multich,
+ DAILINK_COMP_ARRAY(COMP_CPU("AP_DMIC_MULTICH")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2sin6,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2SIN6")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2sout3,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT3")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2sout4,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT4")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(i2sout6,
+ DAILINK_COMP_ARRAY(COMP_CPU("I2SOUT6")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(tdm_dptx,
+ DAILINK_COMP_ARRAY(COMP_CPU("TDM_DPTX")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_DL_24CH,
+ DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL_24CH")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_DL1,
+ DAILINK_COMP_ARRAY(COMP_CPU("SOF_DL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_UL0,
+ DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL0")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_UL1,
+ DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL1")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+SND_SOC_DAILINK_DEFS(AFE_SOF_UL2,
+ DAILINK_COMP_ARRAY(COMP_CPU("SOF_UL2")),
+ DAILINK_COMP_ARRAY(COMP_DUMMY()),
+ DAILINK_COMP_ARRAY(COMP_EMPTY()));
+
+static struct snd_soc_dai_link mt8196_nau8825_dai_links[] = {
+ /*
+ * The SOF topology expects PCM streams 0~4 to be available
+ * for the SOF PCM streams. Put the SOF BE definitions here
+ * so that the PCM device numbers are skipped over.
+ * (BE dailinks do not have PCM devices created.)
+ */
+ {
+ .name = "AFE_SOF_DL_24CH",
+ .no_pcm = 1,
+ .playback_only = 1,
+ .ops = &mt8196_sof_be_ops,
+ SND_SOC_DAILINK_REG(AFE_SOF_DL_24CH),
+ },
+ {
+ .name = "AFE_SOF_DL1",
+ .no_pcm = 1,
+ .playback_only = 1,
+ .ops = &mt8196_sof_be_ops,
+ SND_SOC_DAILINK_REG(AFE_SOF_DL1),
+ },
+ {
+ .name = "AFE_SOF_UL0",
+ .no_pcm = 1,
+ .capture_only = 1,
+ .ops = &mt8196_sof_be_ops,
+ SND_SOC_DAILINK_REG(AFE_SOF_UL0),
+ },
+ {
+ .name = "AFE_SOF_UL1",
+ .no_pcm = 1,
+ .capture_only = 1,
+ .ops = &mt8196_sof_be_ops,
+ SND_SOC_DAILINK_REG(AFE_SOF_UL1),
+ },
+ {
+ .name = "AFE_SOF_UL2",
+ .no_pcm = 1,
+ .capture_only = 1,
+ .ops = &mt8196_sof_be_ops,
+ SND_SOC_DAILINK_REG(AFE_SOF_UL2),
+ },
+ /* Front End DAI links */
+ {
+ .name = "HDMI_FE",
+ .stream_name = "HDMI Playback",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .playback_only = 1,
+ SND_SOC_DAILINK_REG(playback_hdmi),
+ },
+ {
+ .name = "DL2_FE",
+ .stream_name = "DL2 Playback",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .playback_only = 1,
+ SND_SOC_DAILINK_REG(playback2),
+ },
+ {
+ .name = "UL_CM0_FE",
+ .stream_name = "UL_CM0 Capture",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .capture_only = 1,
+ SND_SOC_DAILINK_REG(capture_cm0),
+ },
+ {
+ .name = "DL_24CH_FE",
+ .stream_name = "DL_24CH Playback",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .playback_only = 1,
+ SND_SOC_DAILINK_REG(playback_24ch),
+ },
+ {
+ .name = "DL1_FE",
+ .stream_name = "DL1 Playback",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .playback_only = 1,
+ SND_SOC_DAILINK_REG(playback1),
+ },
+ {
+ .name = "UL0_FE",
+ .stream_name = "UL0 Capture",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .capture_only = 1,
+ SND_SOC_DAILINK_REG(capture0),
+ },
+ {
+ .name = "UL1_FE",
+ .stream_name = "UL1 Capture",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .capture_only = 1,
+ SND_SOC_DAILINK_REG(capture1),
+ },
+ {
+ .name = "UL2_FE",
+ .stream_name = "UL2 Capture",
+ .trigger = {SND_SOC_DPCM_TRIGGER_PRE,
+ SND_SOC_DPCM_TRIGGER_PRE},
+ .dynamic = 1,
+ .capture_only = 1,
+ SND_SOC_DAILINK_REG(capture2),
+ },
+ /* Back End DAI links */
+ {
+ .name = "I2SIN6_BE",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC
+ | SND_SOC_DAIFMT_GATED,
+ .ops = &mt8196_nau8825_i2s_ops,
+ .no_pcm = 1,
+ .capture_only = 1,
+ .ignore_suspend = 1,
+ .be_hw_params_fixup = mt8196_hw_params_fixup,
+ SND_SOC_DAILINK_REG(i2sin6),
+ },
+ {
+ .name = "I2SOUT4_BE",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC
+ | SND_SOC_DAIFMT_GATED,
+ .ops = &mt8196_nau8825_i2s_ops,
+ .no_pcm = 1,
+ .playback_only = 1,
+ .ignore_suspend = 1,
+ .ignore_pmdown_time = 1,
+ .be_hw_params_fixup = mt8196_hw_params_fixup,
+ SND_SOC_DAILINK_REG(i2sout4),
+ },
+ {
+ .name = "I2SOUT6_BE",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC
+ | SND_SOC_DAIFMT_GATED,
+ .ops = &mt8196_nau8825_i2s_ops,
+ .no_pcm = 1,
+ .playback_only = 1,
+ .ignore_suspend = 1,
+ .be_hw_params_fixup = mt8196_hw_params_fixup,
+ SND_SOC_DAILINK_REG(i2sout6),
+ },
+ {
+ .name = "AP_DMIC_BE",
+ .no_pcm = 1,
+ .capture_only = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(ap_dmic),
+ },
+ {
+ .name = "AP_DMIC_CH34_BE",
+ .no_pcm = 1,
+ .capture_only = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(ap_dmic_ch34),
+ },
+ {
+ .name = "AP_DMIC_MULTICH_BE",
+ .no_pcm = 1,
+ .capture_only = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(ap_dmic_multich),
+ },
+ {
+ .name = "TDM_DPTX_BE",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC
+ | SND_SOC_DAIFMT_GATED,
+ .ops = &mt8196_dptx_ops,
+ .be_hw_params_fixup = mt8196_hw_params_fixup,
+ .no_pcm = 1,
+ .playback_only = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(tdm_dptx),
+ },
+ {
+ .name = "I2SOUT3_BE",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBC_CFC
+ | SND_SOC_DAIFMT_GATED,
+ .ops = &mt8196_nau8825_i2s_ops,
+ .no_pcm = 1,
+ .playback_only = 1,
+ .ignore_suspend = 1,
+ SND_SOC_DAILINK_REG(i2sout3),
+ },
+};
+
+static int mt8196_dumb_amp_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
+ int ret = 0;
+
+ ret = snd_soc_dapm_new_controls(dapm, mt8196_dumb_spk_widgets,
+ ARRAY_SIZE(mt8196_dumb_spk_widgets));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add Dumb Speaker dapm, ret %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_add_card_controls(card, mt8196_dumb_spk_controls,
+ ARRAY_SIZE(mt8196_dumb_spk_controls));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add Dumb card controls, ret %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mt8196_dptx_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_DP];
+ struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+ int ret = 0;
+
+ ret = snd_soc_card_jack_new_pins(rtd->card, "DP Jack", SND_JACK_AVOUT,
+ jack, mt8196_dp_jack_pins,
+ ARRAY_SIZE(mt8196_dp_jack_pins));
+ if (ret) {
+ dev_err(rtd->dev, "new jack failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_component_set_jack(component, jack, NULL);
+ if (ret) {
+ dev_err(rtd->dev, "set jack failed on %s (ret=%d)\n",
+ component->name, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mt8196_hdmi_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(rtd->card);
+ struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_HDMI];
+ struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+ int ret = 0;
+
+ ret = snd_soc_card_jack_new_pins(rtd->card, "HDMI Jack", SND_JACK_AVOUT,
+ jack, mt8196_hdmi_jack_pins,
+ ARRAY_SIZE(mt8196_hdmi_jack_pins));
+ if (ret) {
+ dev_err(rtd->dev, "new jack failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_component_set_jack(component, jack, NULL);
+ if (ret) {
+ dev_err(rtd->dev, "set jack failed on %s (ret=%d)\n",
+ component->name, ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int mt8196_headset_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
+ struct mtk_soc_card_data *soc_card_data = snd_soc_card_get_drvdata(card);
+ struct snd_soc_jack *jack = &soc_card_data->card_data->jacks[MT8196_JACK_HEADSET];
+ struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+ int ret;
+ int type;
+
+ ret = snd_soc_dapm_new_controls(dapm, mt8196_nau8825_widgets,
+ ARRAY_SIZE(mt8196_nau8825_widgets));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add nau8825 card widget, ret %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_add_card_controls(card, mt8196_nau8825_controls,
+ ARRAY_SIZE(mt8196_nau8825_controls));
+ if (ret) {
+ dev_err(rtd->dev, "unable to add nau8825 card controls, ret %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET | SND_JACK_BTN_0 |
+ SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+ SND_JACK_BTN_3,
+ jack,
+ nau8825_jack_pins,
+ ARRAY_SIZE(nau8825_jack_pins));
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack creation failed: %d\n", ret);
+ return ret;
+ }
+
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+
+ type = SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3;
+ ret = snd_soc_component_set_jack(component, jack, (void *)&type);
+
+ if (ret) {
+ dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+};
+
+static void mt8196_headset_codec_exit(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_component *component = snd_soc_rtd_to_codec(rtd, 0)->component;
+
+ snd_soc_component_set_jack(component, NULL, NULL);
+}
+
+static int mt8196_nau8825_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
+ unsigned int rate = params_rate(params);
+ unsigned int bit_width = params_width(params);
+ int clk_freq, ret;
+
+ clk_freq = rate * 2 * bit_width;
+
+ /* Configure clock for codec */
+ ret = snd_soc_dai_set_sysclk(codec_dai, NAU8825_CLK_FLL_BLK, 0,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ dev_err(codec_dai->dev, "can't set BCLK clock %d\n", ret);
+ return ret;
+ }
+
+ /* Configure pll for codec */
+ ret = snd_soc_dai_set_pll(codec_dai, 0, 0, clk_freq,
+ params_rate(params) * 256);
+ if (ret < 0) {
+ dev_err(codec_dai->dev, "can't set BCLK: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static const struct snd_soc_ops mt8196_nau8825_ops = {
+ .hw_params = mt8196_nau8825_hw_params,
+};
+
+static int mt8196_rt5682s_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_card *card = rtd->card;
+ struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
+ struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0);
+ unsigned int rate = params_rate(params);
+ int bitwidth;
+ int ret;
+
+ bitwidth = snd_pcm_format_width(params_format(params));
+ if (bitwidth < 0) {
+ dev_err(card->dev, "invalid bit width: %d\n", bitwidth);
+ return bitwidth;
+ }
+
+ ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x00, 0x0, 0x2, bitwidth);
+ if (ret) {
+ dev_err(card->dev, "failed to set tdm slot\n");
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_pll(codec_dai, RT5682S_PLL1, RT5682S_PLL_S_BCLK1,
+ rate * 32, rate * 512);
+ if (ret) {
+ dev_err(card->dev, "failed to set pll\n");
+ return ret;
+ }
+
+ dev_info(card->dev, "%s set mclk rate: %d\n", __func__, rate * 512);
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, RT5682S_SCLK_S_MCLK,
+ rate * 512, SND_SOC_CLOCK_IN);
+ if (ret) {
+ dev_err(card->dev, "failed to set sysclk\n");
+ return ret;
+ }
+
+ return snd_soc_dai_set_sysclk(cpu_dai, 0, rate * 512,
+ SND_SOC_CLOCK_OUT);
+}
+
+static const struct snd_soc_ops mt8196_rt5682s_i2s_ops = {
+ .hw_params = mt8196_rt5682s_i2s_hw_params,
+};
+
+static int mt8196_nau8825_soc_card_probe(struct mtk_soc_card_data *soc_card_data, bool legacy)
+{
+ struct snd_soc_card *card = soc_card_data->card_data->card;
+ struct snd_soc_dai_link *dai_link;
+ bool init_nau8825 = false;
+ bool init_rt5682s = false;
+ bool init_rt5650 = false;
+ bool init_dumb = false;
+ int i;
+
+ dev_info(card->dev, "legacy: %d\n", legacy);
+
+ for_each_card_prelinks(card, i, dai_link) {
+ if (strcmp(dai_link->name, "TDM_DPTX_BE") == 0) {
+ if (dai_link->num_codecs &&
+ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
+ dai_link->init = mt8196_dptx_codec_init;
+ } else if (strcmp(dai_link->name, "I2SOUT3_BE") == 0) {
+ if (dai_link->num_codecs &&
+ strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai"))
+ dai_link->init = mt8196_hdmi_codec_init;
+ } else if (strcmp(dai_link->name, "I2SOUT6_BE") == 0 ||
+ strcmp(dai_link->name, "I2SIN6_BE") == 0) {
+ if (!strcmp(dai_link->codecs->dai_name, NAU8825_CODEC_DAI)) {
+ dai_link->ops = &mt8196_nau8825_ops;
+ if (!init_nau8825) {
+ dai_link->init = mt8196_headset_codec_init;
+ dai_link->exit = mt8196_headset_codec_exit;
+ init_nau8825 = true;
+ }
+ } else if (!strcmp(dai_link->codecs->dai_name, RT5682S_CODEC_DAI)) {
+ dai_link->ops = &mt8196_rt5682s_i2s_ops;
+ if (!init_rt5682s) {
+ dai_link->init = mt8196_headset_codec_init;
+ dai_link->exit = mt8196_headset_codec_exit;
+ init_rt5682s = true;
+ }
+ } else if (!strcmp(dai_link->codecs->dai_name, RT5650_CODEC_DAI)) {
+ dai_link->ops = &mt8196_rt5682s_i2s_ops;
+ if (!init_rt5650) {
+ dai_link->init = mt8196_headset_codec_init;
+ dai_link->exit = mt8196_headset_codec_exit;
+ init_rt5650 = true;
+ }
+ } else {
+ if (strcmp(dai_link->codecs->dai_name, "snd-soc-dummy-dai")) {
+ if (!init_dumb) {
+ dai_link->init = mt8196_dumb_amp_init;
+ init_dumb = true;
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+static const struct mtk_sof_priv mt8196_sof_priv = {
+ .conn_streams = g_sof_conn_streams,
+ .num_streams = ARRAY_SIZE(g_sof_conn_streams),
+};
+
+static struct snd_soc_card mt8196_nau8825_soc_card = {
+ .owner = THIS_MODULE,
+ .dai_link = mt8196_nau8825_dai_links,
+ .num_links = ARRAY_SIZE(mt8196_nau8825_dai_links),
+ .dapm_widgets = mt8196_nau8825_card_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(mt8196_nau8825_card_widgets),
+ .dapm_routes = mt8196_nau8825_card_routes,
+ .num_dapm_routes = ARRAY_SIZE(mt8196_nau8825_card_routes),
+ .controls = mt8196_nau8825_card_controls,
+ .num_controls = ARRAY_SIZE(mt8196_nau8825_card_controls),
+};
+
+static const struct mtk_soundcard_pdata mt8196_nau8825_card = {
+ .card_name = "mt8196_nau8825",
+ .card_data = &(struct mtk_platform_card_data) {
+ .card = &mt8196_nau8825_soc_card,
+ .num_jacks = MT8196_JACK_MAX,
+ .flags = NAU8825_HS_PRESENT
+ },
+ .sof_priv = &mt8196_sof_priv,
+ .soc_probe = mt8196_nau8825_soc_card_probe,
+};
+
+static const struct mtk_soundcard_pdata mt8196_rt5682s_card = {
+ .card_name = "mt8196_rt5682s",
+ .card_data = &(struct mtk_platform_card_data) {
+ .card = &mt8196_nau8825_soc_card,
+ .num_jacks = MT8196_JACK_MAX,
+ .flags = RT5682S_HS_PRESENT
+ },
+ .sof_priv = &mt8196_sof_priv,
+ .soc_probe = mt8196_nau8825_soc_card_probe,
+};
+
+static const struct mtk_soundcard_pdata mt8196_rt5650_card = {
+ .card_name = "mt8196_rt5650",
+ .card_data = &(struct mtk_platform_card_data) {
+ .card = &mt8196_nau8825_soc_card,
+ .num_jacks = MT8196_JACK_MAX,
+ .flags = RT5650_HS_PRESENT
+ },
+ .sof_priv = &mt8196_sof_priv,
+ .soc_probe = mt8196_nau8825_soc_card_probe,
+};
+
+static const struct of_device_id mt8196_nau8825_dt_match[] = {
+ {.compatible = "mediatek,mt8196-nau8825-sound", .data = &mt8196_nau8825_card,},
+ {.compatible = "mediatek,mt8196-rt5682s-sound", .data = &mt8196_rt5682s_card,},
+ {.compatible = "mediatek,mt8196-rt5650-sound", .data = &mt8196_rt5650_card,},
+ {}
+};
+MODULE_DEVICE_TABLE(of, mt8196_nau8825_dt_match);
+
+static struct platform_driver mt8196_nau8825_driver = {
+ .driver = {
+ .name = "mt8196-nau8825",
+ .of_match_table = mt8196_nau8825_dt_match,
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = mtk_soundcard_common_probe,
+};
+module_platform_driver(mt8196_nau8825_driver);
+
+/* Module information */
+MODULE_DESCRIPTION("MT8196 nau8825 ALSA SoC machine driver");
+MODULE_AUTHOR("Darren Ye <darren.ye@mediatek.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("mt8196 nau8825 soc card");
+
diff --git a/sound/soc/mediatek/mt8196/mt8196-reg.h b/sound/soc/mediatek/mt8196/mt8196-reg.h
new file mode 100644
index 000000000000..eb689d2655be
--- /dev/null
+++ b/sound/soc/mediatek/mt8196/mt8196-reg.h
@@ -0,0 +1,12068 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * mt8196-reg.h -- Mediatek 8196 audio driver reg definition
+ *
+ * Copyright (c) 2025 MediaTek Inc.
+ * Author: Darren Ye <darren.ye@mediatek.com>
+ */
+
+#ifndef _MT8196_REG_H_
+#define _MT8196_REG_H_
+
+ /* reg bit enum */
+enum {
+ MT8196_MEMIF_PBUF_SIZE_32_BYTES,
+ MT8196_MEMIF_PBUF_SIZE_64_BYTES,
+ MT8196_MEMIF_PBUF_SIZE_128_BYTES,
+ MT8196_MEMIF_PBUF_SIZE_256_BYTES,
+ MT8196_MEMIF_PBUF_SIZE_NUM,
+};
+
+enum {
+ MT8196_MEMIF_MAX_LEN_0_BYTES,
+ MT8196_MEMIF_MAX_LEN_16_BYTES,
+ MT8196_MEMIF_MAX_LEN_32_BYTES,
+ MT8196_MEMIF_MAX_LEN_64_BYTES,
+};
+
+enum {
+ MT8196_MEMIF_MIN_LEN_NOT_SUPPORT,
+ MT8196_MEMIF_MIN_LEN_16_BYTES,
+ MT8196_MEMIF_MIN_LEN_32_BYTES,
+ MT8196_MEMIF_MIN_LEN_64_BYTES,
+};
+
+/*****************************************************************************
+ * R E G I S T E R D E F I N I T I O N
+ *****************************************************************************/
+/* AUDIO_TOP_CON0 */
+#define PDN_MTKAIFV4_SFT 25
+#define PDN_MTKAIFV4_MASK 0x1
+#define PDN_MTKAIFV4_MASK_SFT (0x1 << 25)
+#define PDN_FM_I2S_SFT 24
+#define PDN_FM_I2S_MASK 0x1
+#define PDN_FM_I2S_MASK_SFT (0x1 << 24)
+#define PDN_HW_GAIN01_SFT 21
+#define PDN_HW_GAIN01_MASK 0x1
+#define PDN_HW_GAIN01_MASK_SFT (0x1 << 21)
+#define PDN_HW_GAIN23_SFT 20
+#define PDN_HW_GAIN23_MASK 0x1
+#define PDN_HW_GAIN23_MASK_SFT (0x1 << 20)
+#define PDN_STF_SFT 19
+#define PDN_STF_MASK 0x1
+#define PDN_STF_MASK_SFT (0x1 << 19)
+#define PDN_CM0_SFT 18
+#define PDN_CM0_MASK 0x1
+#define PDN_CM0_MASK_SFT (0x1 << 18)
+#define PDN_CM1_SFT 17
+#define PDN_CM1_MASK 0x1
+#define PDN_CM1_MASK_SFT (0x1 << 17)
+#define PDN_CM2_SFT 16
+#define PDN_CM2_MASK 0x1
+#define PDN_CM2_MASK_SFT (0x1 << 16)
+#define PDN_PCM0_SFT 14
+#define PDN_PCM0_MASK 0x1
+#define PDN_PCM0_MASK_SFT (0x1 << 14)
+#define PDN_PCM1_SFT 13
+#define PDN_PCM1_MASK 0x1
+#define PDN_PCM1_MASK_SFT (0x1 << 13)
+
+/* AUDIO_TOP_CON1 */
+#define PDN_UL0_ADC_SFT 23
+#define PDN_UL0_ADC_MASK 0x1
+#define PDN_UL0_ADC_MASK_SFT (0x1 << 23)
+#define PDN_UL0_TML_SFT 22
+#define PDN_UL0_TML_MASK 0x1
+#define PDN_UL0_TML_MASK_SFT (0x1 << 22)
+#define PDN_UL0_ADC_HIRES_SFT 21
+#define PDN_UL0_ADC_HIRES_MASK 0x1
+#define PDN_UL0_ADC_HIRES_MASK_SFT (0x1 << 21)
+#define PDN_UL0_ADC_HIRES_TML_SFT 20
+#define PDN_UL0_ADC_HIRES_TML_MASK 0x1
+#define PDN_UL0_ADC_HIRES_TML_MASK_SFT (0x1 << 20)
+#define PDN_UL1_ADC_SFT 19
+#define PDN_UL1_ADC_MASK 0x1
+#define PDN_UL1_ADC_MASK_SFT (0x1 << 19)
+#define PDN_UL1_TML_SFT 18
+#define PDN_UL1_TML_MASK 0x1
+#define PDN_UL1_TML_MASK_SFT (0x1 << 18)
+#define PDN_UL1_ADC_HIRES_SFT 17
+#define PDN_UL1_ADC_HIRES_MASK 0x1
+#define PDN_UL1_ADC_HIRES_MASK_SFT (0x1 << 17)
+#define PDN_UL1_ADC_HIRES_TML_SFT 16
+#define PDN_UL1_ADC_HIRES_TML_MASK 0x1
+#define PDN_UL1_ADC_HIRES_TML_MASK_SFT (0x1 << 16)
+#define PDN_UL2_ADC_SFT 15
+#define PDN_UL2_ADC_MASK 0x1
+#define PDN_UL2_ADC_MASK_SFT (0x1 << 15)
+#define PDN_UL2_TML_SFT 14
+#define PDN_UL2_TML_MASK 0x1
+#define PDN_UL2_TML_MASK_SFT (0x1 << 14)
+#define PDN_UL2_ADC_HIRES_SFT 13
+#define PDN_UL2_ADC_HIRES_MASK 0x1
+#define PDN_UL2_ADC_HIRES_MASK_SFT (0x1 << 13)
+#define PDN_UL2_ADC_HIRES_TML_SFT 12
+#define PDN_UL2_ADC_HIRES_TML_MASK 0x1
+#define PDN_UL2_ADC_HIRES_TML_MASK_SFT (0x1 << 12)
+
+/* AUDIO_TOP_CON2 */
+#define PDN_TDM_OUT_SFT 24
+#define PDN_TDM_OUT_MASK 0x1
+#define PDN_TDM_OUT_MASK_SFT (0x1 << 24)
+#define PDN_ETDM_OUT0_SFT 21
+#define PDN_ETDM_OUT0_MASK 0x1
+#define PDN_ETDM_OUT0_MASK_SFT (0x1 << 21)
+#define PDN_ETDM_OUT1_SFT 20
+#define PDN_ETDM_OUT1_MASK 0x1
+#define PDN_ETDM_OUT1_MASK_SFT (0x1 << 20)
+#define PDN_ETDM_OUT2_SFT 19
+#define PDN_ETDM_OUT2_MASK 0x1
+#define PDN_ETDM_OUT2_MASK_SFT (0x1 << 19)
+#define PDN_ETDM_OUT3_SFT 18
+#define PDN_ETDM_OUT3_MASK 0x1
+#define PDN_ETDM_OUT3_MASK_SFT (0x1 << 18)
+#define PDN_ETDM_OUT4_SFT 17
+#define PDN_ETDM_OUT4_MASK 0x1
+#define PDN_ETDM_OUT4_MASK_SFT (0x1 << 17)
+#define PDN_ETDM_OUT5_SFT 16
+#define PDN_ETDM_OUT5_MASK 0x1
+#define PDN_ETDM_OUT5_MASK_SFT (0x1 << 16)
+#define PDN_ETDM_OUT6_SFT 15
+#define PDN_ETDM_OUT6_MASK 0x1
+#define PDN_ETDM_OUT6_MASK_SFT (0x1 << 15)
+#define PDN_ETDM_IN0_SFT 13
+#define PDN_ETDM_IN0_MASK 0x1
+#define PDN_ETDM_IN0_MASK_SFT (0x1 << 13)
+#define PDN_ETDM_IN1_SFT 12
+#define PDN_ETDM_IN1_MASK 0x1
+#define PDN_ETDM_IN1_MASK_SFT (0x1 << 12)
+#define PDN_ETDM_IN2_SFT 11
+#define PDN_ETDM_IN2_MASK 0x1
+#define PDN_ETDM_IN2_MASK_SFT (0x1 << 11)
+#define PDN_ETDM_IN3_SFT 10
+#define PDN_ETDM_IN3_MASK 0x1
+#define PDN_ETDM_IN3_MASK_SFT (0x1 << 10)
+#define PDN_ETDM_IN4_SFT 9
+#define PDN_ETDM_IN4_MASK 0x1
+#define PDN_ETDM_IN4_MASK_SFT (0x1 << 9)
+#define PDN_ETDM_IN5_SFT 8
+#define PDN_ETDM_IN5_MASK 0x1
+#define PDN_ETDM_IN5_MASK_SFT (0x1 << 8)
+#define PDN_ETDM_IN6_SFT 7
+#define PDN_ETDM_IN6_MASK 0x1
+#define PDN_ETDM_IN6_MASK_SFT (0x1 << 7)
+
+/* AUDIO_TOP_CON3 */
+#define PDN_CONNSYS_I2S_ASRC_SFT 25
+#define PDN_CONNSYS_I2S_ASRC_MASK 0x1
+#define PDN_CONNSYS_I2S_ASRC_MASK_SFT (0x1 << 25)
+#define PDN_GENERAL0_ASRC_SFT 24
+#define PDN_GENERAL0_ASRC_MASK 0x1
+#define PDN_GENERAL0_ASRC_MASK_SFT (0x1 << 24)
+#define PDN_GENERAL1_ASRC_SFT 23
+#define PDN_GENERAL1_ASRC_MASK 0x1
+#define PDN_GENERAL1_ASRC_MASK_SFT (0x1 << 23)
+#define PDN_GENERAL2_ASRC_SFT 22
+#define PDN_GENERAL2_ASRC_MASK 0x1
+#define PDN_GENERAL2_ASRC_MASK_SFT (0x1 << 22)
+#define PDN_GENERAL3_ASRC_SFT 21
+#define PDN_GENERAL3_ASRC_MASK 0x1
+#define PDN_GENERAL3_ASRC_MASK_SFT (0x1 << 21)
+#define PDN_GENERAL4_ASRC_SFT 20
+#define PDN_GENERAL4_ASRC_MASK 0x1
+#define PDN_GENERAL4_ASRC_MASK_SFT (0x1 << 20)
+#define PDN_GENERAL5_ASRC_SFT 19
+#define PDN_GENERAL5_ASRC_MASK 0x1
+#define PDN_GENERAL5_ASRC_MASK_SFT (0x1 << 19)
+#define PDN_GENERAL6_ASRC_SFT 18
+#define PDN_GENERAL6_ASRC_MASK 0x1
+#define PDN_GENERAL6_ASRC_MASK_SFT (0x1 << 18)
+#define PDN_GENERAL7_ASRC_SFT 17
+#define PDN_GENERAL7_ASRC_MASK 0x1
+#define PDN_GENERAL7_ASRC_MASK_SFT (0x1 << 17)
+#define PDN_GENERAL8_ASRC_SFT 16
+#define PDN_GENERAL8_ASRC_MASK 0x1
+#define PDN_GENERAL8_ASRC_MASK_SFT (0x1 << 16)
+#define PDN_GENERAL9_ASRC_SFT 15
+#define PDN_GENERAL9_ASRC_MASK 0x1
+#define PDN_GENERAL9_ASRC_MASK_SFT (0x1 << 15)
+#define PDN_GENERAL10_ASRC_SFT 14
+#define PDN_GENERAL10_ASRC_MASK 0x1
+#define PDN_GENERAL10_ASRC_MASK_SFT (0x1 << 14)
+#define PDN_GENERAL11_ASRC_SFT 13
+#define PDN_GENERAL11_ASRC_MASK 0x1
+#define PDN_GENERAL11_ASRC_MASK_SFT (0x1 << 13)
+#define PDN_GENERAL12_ASRC_SFT 12
+#define PDN_GENERAL12_ASRC_MASK 0x1
+#define PDN_GENERAL12_ASRC_MASK_SFT (0x1 << 12)
+#define PDN_GENERAL13_ASRC_SFT 11
+#define PDN_GENERAL13_ASRC_MASK 0x1
+#define PDN_GENERAL13_ASRC_MASK_SFT (0x1 << 11)
+#define PDN_GENERAL14_ASRC_SFT 10
+#define PDN_GENERAL14_ASRC_MASK 0x1
+#define PDN_GENERAL14_ASRC_MASK_SFT (0x1 << 10)
+#define PDN_GENERAL15_ASRC_SFT 9
+#define PDN_GENERAL15_ASRC_MASK 0x1
+#define PDN_GENERAL15_ASRC_MASK_SFT (0x1 << 9)
+
+/* AUDIO_TOP_CON4 */
+#define PDN_APLL_TUNER1_SFT 13
+#define PDN_APLL_TUNER1_MASK 0x1
+#define PDN_APLL_TUNER1_MASK_SFT (0x1 << 13)
+#define PDN_APLL_TUNER2_SFT 12
+#define PDN_APLL_TUNER2_MASK 0x1
+#define PDN_APLL_TUNER2_MASK_SFT (0x1 << 12)
+#define CG_H208M_CK_SFT 4
+#define CG_H208M_CK_MASK 0x1
+#define CG_H208M_CK_MASK_SFT (0x1 << 4)
+#define CG_APLL2_CK_SFT 3
+#define CG_APLL2_CK_MASK 0x1
+#define CG_APLL2_CK_MASK_SFT (0x1 << 3)
+#define CG_APLL1_CK_SFT 2
+#define CG_APLL1_CK_MASK 0x1
+#define CG_APLL1_CK_MASK_SFT (0x1 << 2)
+#define CG_AUDIO_F26M_CK_SFT 1
+#define CG_AUDIO_F26M_CK_MASK 0x1
+#define CG_AUDIO_F26M_CK_MASK_SFT (0x1 << 1)
+#define CG_AUDIO_HOPPING_CK_SFT 0
+#define CG_AUDIO_HOPPING_CK_MASK 0x1
+#define CG_AUDIO_HOPPING_CK_MASK_SFT (0x1 << 0)
+
+/* AUDIO_ENGEN_CON0 */
+/* AUDIO_ENGEN_CON0_USER1 */
+/* AUDIO_ENGEN_CON0_USER1 */
+#define MULTI_USER_BYPASS_SFT 17
+#define MULTI_USER_BYPASS_MASK 0x1
+#define MULTI_USER_BYPASS_MASK_SFT (0x1 << 17)
+#define MULTI_USER_RST_SFT 16
+#define MULTI_USER_RST_MASK 0x1
+#define MULTI_USER_RST_MASK_SFT (0x1 << 16)
+#define AUDIO_F26M_EN_RST_SFT 8
+#define AUDIO_F26M_EN_RST_MASK 0x1
+#define AUDIO_F26M_EN_RST_MASK_SFT (0x1 << 8)
+#define AUDIO_APLL2_EN_ON_SFT 3
+#define AUDIO_APLL2_EN_ON_MASK 0x1
+#define AUDIO_APLL2_EN_ON_MASK_SFT (0x1 << 3)
+#define AUDIO_APLL1_EN_ON_SFT 2
+#define AUDIO_APLL1_EN_ON_MASK 0x1
+#define AUDIO_APLL1_EN_ON_MASK_SFT (0x1 << 2)
+#define AUDIO_F3P25M_EN_ON_SFT 1
+#define AUDIO_F3P25M_EN_ON_MASK 0x1
+#define AUDIO_F3P25M_EN_ON_MASK_SFT (0x1 << 1)
+#define AUDIO_26M_EN_ON_SFT 0
+#define AUDIO_26M_EN_ON_MASK 0x1
+#define AUDIO_26M_EN_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_SINEGEN_CON0 */
+#define DAC_EN_SFT 26
+#define DAC_EN_MASK 0x1
+#define DAC_EN_MASK_SFT (0x1 << 26)
+#define TIE_SW_CH2_SFT 25
+#define TIE_SW_CH2_MASK 0x1
+#define TIE_SW_CH2_MASK_SFT (0x1 << 25)
+#define TIE_SW_CH1_SFT 24
+#define TIE_SW_CH1_MASK 0x1
+#define TIE_SW_CH1_MASK_SFT (0x1 << 24)
+#define AMP_DIV_CH2_SFT 20
+#define AMP_DIV_CH2_MASK 0xf
+#define AMP_DIV_CH2_MASK_SFT (0xf << 20)
+#define FREQ_DIV_CH2_SFT 12
+#define FREQ_DIV_CH2_MASK 0x1f
+#define FREQ_DIV_CH2_MASK_SFT (0x1f << 12)
+#define AMP_DIV_CH1_SFT 8
+#define AMP_DIV_CH1_MASK 0xf
+#define AMP_DIV_CH1_MASK_SFT (0xf << 8)
+#define FREQ_DIV_CH1_SFT 0
+#define FREQ_DIV_CH1_MASK 0x1f
+#define FREQ_DIV_CH1_MASK_SFT (0x1f << 0)
+
+/* AFE_SINEGEN_CON1 */
+#define SINE_DOMAIN_SFT 20
+#define SINE_DOMAIN_MASK 0x7
+#define SINE_DOMAIN_MASK_SFT (0x7 << 20)
+#define SINE_MODE_SFT 12
+#define SINE_MODE_MASK 0x1f
+#define SINE_MODE_MASK_SFT (0x1f << 12)
+#define INNER_LOOP_BACKI_SEL_SFT 8
+#define INNER_LOOP_BACKI_SEL_MASK 0x1
+#define INNER_LOOP_BACKI_SEL_MASK_SFT (0x1 << 8)
+#define INNER_LOOP_BACK_MODE_SFT 0
+#define INNER_LOOP_BACK_MODE_MASK 0xff
+#define INNER_LOOP_BACK_MODE_MASK_SFT (0xff << 0)
+
+/* AFE_SINEGEN_CON2 */
+#define TIE_CH1_CONSTANT_SFT 0
+#define TIE_CH1_CONSTANT_MASK 0xffffffff
+#define TIE_CH1_CONSTANT_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SINEGEN_CON3 */
+#define TIE_CH2_CONSTANT_SFT 0
+#define TIE_CH2_CONSTANT_MASK 0xffffffff
+#define TIE_CH2_CONSTANT_MASK_SFT (0xffffffff << 0)
+
+/* AFE_APLL1_TUNER_CFG */
+/* AFE_APLL2_TUNER_CFG */
+#define UPPER_BOUND_SFT 8
+#define UPPER_BOUND_MASK 0xff
+#define UPPER_BOUND_MASK_SFT (0xff << 8)
+#define APLL_DIV_SFT 4
+#define APLL_DIV_MASK 0xf
+#define APLL_DIV_MASK_SFT (0xf << 4)
+#define XTAL_EN_128FS_SEL_SFT 1
+#define XTAL_EN_128FS_SEL_MASK 0x3
+#define XTAL_EN_128FS_SEL_MASK_SFT (0x3 << 1)
+#define FREQ_TUNER_EN_SFT 0
+#define FREQ_TUNER_EN_MASK 0x1
+#define FREQ_TUNER_EN_MASK_SFT (0x1 << 0)
+
+/* AFE_APLL1_TUNER_MON0 */
+/* AFE_APLL2_TUNER_MON0 */
+#define TUNER_MON_SFT 0
+#define TUNER_MON_MASK 0xffffffff
+#define TUNER_MON_MASK_SFT (0xffffffff << 0)
+
+/* AUDIO_TOP_RG0 */
+/* AUDIO_TOP_RG1 */
+/* AUDIO_TOP_RG2 */
+/* AUDIO_TOP_RG3 */
+/* AUDIO_TOP_RG4 */
+#define RESERVE_RG_SFT 0
+#define RESERVE_RG_MASK 0xffffffff
+#define RESERVE_RG_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SPM_CONTROL_REQ */
+#define AFE_DDREN_REQ_SFT 4
+#define AFE_DDREN_REQ_MASK 0x1
+#define AFE_DDREN_REQ_MASK_SFT (0x1 << 4)
+#define AFE_INFRA_REQ_SFT 3
+#define AFE_INFRA_REQ_MASK 0x1
+#define AFE_INFRA_REQ_MASK_SFT (0x1 << 3)
+#define AFE_VRF18_REQ_SFT 2
+#define AFE_VRF18_REQ_MASK 0x1
+#define AFE_VRF18_REQ_MASK_SFT (0x1 << 2)
+#define AFE_APSRC_REQ_SFT 1
+#define AFE_APSRC_REQ_MASK 0x1
+#define AFE_APSRC_REQ_MASK_SFT (0x1 << 1)
+#define AFE_SRCCLKENA_REQ_SFT 0
+#define AFE_SRCCLKENA_REQ_MASK 0x1
+#define AFE_SRCCLKENA_REQ_MASK_SFT (0x1 << 0)
+
+/* AFE_SPM_CONTROL_ACK */
+#define SPM_RESOURCE_CONTROL_ACK_SFT 0
+#define SPM_RESOURCE_CONTROL_ACK_MASK 0xffffffff
+#define SPM_RESOURCE_CONTROL_ACK_MASK_SFT (0xffffffff << 0)
+
+/* AUD_TOP_CFG_VCORE_RG */
+#define AUD_TOP_CFG_SFT 0
+#define AUD_TOP_CFG_MASK 0xffffffff
+#define AUD_TOP_CFG_MASK_SFT (0xffffffff << 0)
+
+/* AUDIO_TOP_IP_VERSION */
+#define AUDIO_TOP_IP_VERSION_SFT 0
+#define AUDIO_TOP_IP_VERSION_MASK 0xffffffff
+#define AUDIO_TOP_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AUDIO_ENGEN_CON0_MON */
+#define AUDIO_ENGEN_MON_SFT 0
+#define AUDIO_ENGEN_MON_MASK 0xffffffff
+#define AUDIO_ENGEN_MON_MASK_SFT (0xffffffff << 0)
+
+/* AUD_TOP_CFG_VLP_RG */
+#define I2SIN1_DAT_SEL_SFT 31
+#define I2SIN1_DAT_SEL_MASK 0x1
+#define I2SIN1_DAT_SEL_MASK_SFT (0x1 << 31)
+#define FMI2S_IN_SEL_SFT 30
+#define FMI2S_IN_SEL_MASK 0x1
+#define FMI2S_IN_SEL_MASK_SFT (0x1 << 30)
+#define RG_I2S4_IN_BCK_NEG_EG_LATCH_SFT 21
+#define RG_I2S4_IN_BCK_NEG_EG_LATCH_MASK 0x1
+#define RG_I2S4_IN_BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 21)
+#define RG_I2S4_OUT_BCK_NEG_EG_LATCH_SFT 20
+#define RG_I2S4_OUT_BCK_NEG_EG_LATCH_MASK 0x1
+#define RG_I2S4_OUT_BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 20)
+#define RG_I2S4_IN_SLV_LRCK_LATCH_EDGE_SFT 19
+#define RG_I2S4_IN_SLV_LRCK_LATCH_EDGE_MASK 0x1
+#define RG_I2S4_IN_SLV_LRCK_LATCH_EDGE_MASK_SFT (0x1 << 19)
+#define RG_I2S4_IN_SLV_BCK_INV_SEL_SFT 18
+#define RG_I2S4_IN_SLV_BCK_INV_SEL_MASK 0x1
+#define RG_I2S4_IN_SLV_BCK_INV_SEL_MASK_SFT (0x1 << 18)
+#define RG_I2S4_OUT_SLV_LRCK_LATCH_EDGE_SFT 17
+#define RG_I2S4_OUT_SLV_LRCK_LATCH_EDGE_MASK 0x1
+#define RG_I2S4_OUT_SLV_LRCK_LATCH_EDGE_MASK_SFT (0x1 << 17)
+#define RG_I2S4_OUT_SLV_BCK_INV_SEL_SFT 16
+#define RG_I2S4_OUT_SLV_BCK_INV_SEL_MASK 0x1
+#define RG_I2S4_OUT_SLV_BCK_INV_SEL_MASK_SFT (0x1 << 16)
+#define RG_I2S5_IN_BCK_NEG_EG_LATCH_SFT 13
+#define RG_I2S5_IN_BCK_NEG_EG_LATCH_MASK 0x1
+#define RG_I2S5_IN_BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 13)
+#define RG_I2S5_OUT_BCK_NEG_EG_LATCH_SFT 12
+#define RG_I2S5_OUT_BCK_NEG_EG_LATCH_MASK 0x1
+#define RG_I2S5_OUT_BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 12)
+#define RG_I2S5_IN_SLV_LRCK_LATCH_EDGE_SFT 11
+#define RG_I2S5_IN_SLV_LRCK_LATCH_EDGE_MASK 0x1
+#define RG_I2S5_IN_SLV_LRCK_LATCH_EDGE_MASK_SFT (0x1 << 11)
+#define RG_I2S5_IN_SLV_BCK_INV_SEL_SFT 10
+#define RG_I2S5_IN_SLV_BCK_INV_SEL_MASK 0x1
+#define RG_I2S5_IN_SLV_BCK_INV_SEL_MASK_SFT (0x1 << 10)
+#define RG_I2S5_OUT_SLV_LRCK_LATCH_EDGE_SFT 9
+#define RG_I2S5_OUT_SLV_LRCK_LATCH_EDGE_MASK 0x1
+#define RG_I2S5_OUT_SLV_LRCK_LATCH_EDGE_MASK_SFT (0x1 << 9)
+#define RG_I2S5_OUT_SLV_BCK_INV_SEL_SFT 8
+#define RG_I2S5_OUT_SLV_BCK_INV_SEL_MASK 0x1
+#define RG_I2S5_OUT_SLV_BCK_INV_SEL_MASK_SFT (0x1 << 8)
+#define RG_I2S4_PAD_TOP_CK_EN_SFT 5
+#define RG_I2S4_PAD_TOP_CK_EN_MASK 0x1
+#define RG_I2S4_PAD_TOP_CK_EN_MASK_SFT (0x1 << 5)
+#define RG_I2S5_PAD_TOP_CK_EN_SFT 4
+#define RG_I2S5_PAD_TOP_CK_EN_MASK 0x1
+#define RG_I2S5_PAD_TOP_CK_EN_MASK_SFT (0x1 << 4)
+#define RG_TEST_TYPE_SFT 2
+#define RG_TEST_TYPE_MASK 0x1
+#define RG_TEST_TYPE_MASK_SFT (0x1 << 2)
+#define RG_SW_RESET_SFT 1
+#define RG_SW_RESET_MASK 0x1
+#define RG_SW_RESET_MASK_SFT (0x1 << 1)
+#define RG_TEST_ON_SFT 0
+#define RG_TEST_ON_MASK 0x1
+#define RG_TEST_ON_MASK_SFT (0x1 << 0)
+
+/* AUD_TOP_MON_RG */
+#define AUD_TOP_MON_SFT 0
+#define AUD_TOP_MON_MASK 0xffffffff
+#define AUD_TOP_MON_MASK_SFT (0xffffffff << 0)
+
+/* AUDIO_USE_DEFAULT_DELSEL0 */
+#define USE_DEFAULT_DELSEL_RG_SFT 0
+#define USE_DEFAULT_DELSEL_RG_MASK 0xffffffff
+#define USE_DEFAULT_DELSEL_RG_MASK_SFT (0xffffffff << 0)
+
+/* AUDIO_USE_DEFAULT_DELSEL1 */
+#define USE_DEFAULT_DELSEL_RG_SFT 0
+#define USE_DEFAULT_DELSEL_RG_MASK 0xffffffff
+#define USE_DEFAULT_DELSEL_RG_MASK_SFT (0xffffffff << 0)
+
+/* AUDIO_USE_DEFAULT_DELSEL2 */
+#define USE_DEFAULT_DELSEL_RG_SFT 0
+#define USE_DEFAULT_DELSEL_RG_MASK 0xffffffff
+#define USE_DEFAULT_DELSEL_RG_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CONNSYS_I2S_IPM_VER_MON */
+#define RG_CONNSYS_I2S_IPM_VER_MON_SFT 0
+#define RG_CONNSYS_I2S_IPM_VER_MON_MASK 0xffffffff
+#define RG_CONNSYS_I2S_IPM_VER_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CONNSYS_I2S_MON_SEL */
+#define RG_CONNSYS_I2S_MON_SEL_SFT 0
+#define RG_CONNSYS_I2S_MON_SEL_MASK 0xff
+#define RG_CONNSYS_I2S_MON_SEL_MASK_SFT (0xff << 0)
+
+/* AFE_CONNSYS_I2S_MON */
+#define RG_CONNSYS_I2S_MON_SFT 0
+#define RG_CONNSYS_I2S_MON_MASK 0xffffffff
+#define RG_CONNSYS_I2S_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CONNSYS_I2S_CON */
+#define I2S_SOFT_RST_SFT 31
+#define I2S_SOFT_RST_MASK 0x1
+#define I2S_SOFT_RST_MASK_SFT (0x1 << 31)
+#define BCK_NEG_EG_LATCH_SFT 30
+#define BCK_NEG_EG_LATCH_MASK 0x1
+#define BCK_NEG_EG_LATCH_MASK_SFT (0x1 << 30)
+#define BCK_INV_SFT 29
+#define BCK_INV_MASK 0x1
+#define BCK_INV_MASK_SFT (0x1 << 29)
+#define I2SIN_PAD_SEL_SFT 28
+#define I2SIN_PAD_SEL_MASK 0x1
+#define I2SIN_PAD_SEL_MASK_SFT (0x1 << 28)
+#define I2S_LOOPBACK_SFT 20
+#define I2S_LOOPBACK_MASK 0x1
+#define I2S_LOOPBACK_MASK_SFT (0x1 << 20)
+#define I2S_HDEN_SFT 12
+#define I2S_HDEN_MASK 0x1
+#define I2S_HDEN_MASK_SFT (0x1 << 12)
+#define I2S_MODE_SFT 8
+#define I2S_MODE_MASK 0xf
+#define I2S_MODE_MASK_SFT (0xf << 8)
+#define I2S_BYPSRC_SFT 6
+#define I2S_BYPSRC_MASK 0x1
+#define I2S_BYPSRC_MASK_SFT (0x1 << 6)
+#define INV_LRCK_SFT 5
+#define INV_LRCK_MASK 0x1
+#define INV_LRCK_MASK_SFT (0x1 << 5)
+#define I2S_FMT_SFT 3
+#define I2S_FMT_MASK 0x1
+#define I2S_FMT_MASK_SFT (0x1 << 3)
+#define I2S_SRC_SFT 2
+#define I2S_SRC_MASK 0x1
+#define I2S_SRC_MASK_SFT (0x1 << 2)
+#define I2S_WLEN_SFT 1
+#define I2S_WLEN_MASK 0x1
+#define I2S_WLEN_MASK_SFT (0x1 << 1)
+#define I2S_EN_SFT 0
+#define I2S_EN_MASK 0x1
+#define I2S_EN_MASK_SFT (0x1 << 0)
+
+/* AFE_PCM0_INTF_CON0 */
+#define PCM0_HDEN_SFT 26
+#define PCM0_HDEN_MASK 0x1
+#define PCM0_HDEN_MASK_SFT (0x1 << 26)
+#define PCM0_SYNC_DELSEL_SFT 25
+#define PCM0_SYNC_DELSEL_MASK 0x1
+#define PCM0_SYNC_DELSEL_MASK_SFT (0x1 << 25)
+#define PCM0_TX_LR_SWAP_SFT 24
+#define PCM0_TX_LR_SWAP_MASK 0x1
+#define PCM0_TX_LR_SWAP_MASK_SFT (0x1 << 24)
+#define PCM0_SYNC_OUT_INV_SFT 23
+#define PCM0_SYNC_OUT_INV_MASK 0x1
+#define PCM0_SYNC_OUT_INV_MASK_SFT (0x1 << 23)
+#define PCM0_BCLK_OUT_INV_SFT 22
+#define PCM0_BCLK_OUT_INV_MASK 0x1
+#define PCM0_BCLK_OUT_INV_MASK_SFT (0x1 << 22)
+#define PCM0_SYNC_IN_INV_SFT 21
+#define PCM0_SYNC_IN_INV_MASK 0x1
+#define PCM0_SYNC_IN_INV_MASK_SFT (0x1 << 21)
+#define PCM0_BCLK_IN_INV_SFT 20
+#define PCM0_BCLK_IN_INV_MASK 0x1
+#define PCM0_BCLK_IN_INV_MASK_SFT (0x1 << 20)
+#define PCM0_TX_LCH_RPT_SFT 19
+#define PCM0_TX_LCH_RPT_MASK 0x1
+#define PCM0_TX_LCH_RPT_MASK_SFT (0x1 << 19)
+#define PCM0_VBT_16K_MODE_SFT 18
+#define PCM0_VBT_16K_MODE_MASK 0x1
+#define PCM0_VBT_16K_MODE_MASK_SFT (0x1 << 18)
+#define PCM0_BIT_LENGTH_SFT 16
+#define PCM0_BIT_LENGTH_MASK 0x3
+#define PCM0_BIT_LENGTH_MASK_SFT (0x3 << 16)
+#define PCM0_WLEN_SFT 14
+#define PCM0_WLEN_MASK 0x3
+#define PCM0_WLEN_MASK_SFT (0x3 << 14)
+#define PCM0_SYNC_LENGTH_SFT 9
+#define PCM0_SYNC_LENGTH_MASK 0x1f
+#define PCM0_SYNC_LENGTH_MASK_SFT (0x1f << 9)
+#define PCM0_SYNC_TYPE_SFT 8
+#define PCM0_SYNC_TYPE_MASK 0x1
+#define PCM0_SYNC_TYPE_MASK_SFT (0x1 << 8)
+#define PCM0_BYP_ASRC_SFT 7
+#define PCM0_BYP_ASRC_MASK 0x1
+#define PCM0_BYP_ASRC_MASK_SFT (0x1 << 7)
+#define PCM0_SLAVE_SFT 6
+#define PCM0_SLAVE_MASK 0x1
+#define PCM0_SLAVE_MASK_SFT (0x1 << 6)
+#define PCM0_MODE_SFT 3
+#define PCM0_MODE_MASK 0x7
+#define PCM0_MODE_MASK_SFT (0x7 << 3)
+#define PCM0_FMT_SFT 1
+#define PCM0_FMT_MASK 0x3
+#define PCM0_FMT_MASK_SFT (0x3 << 1)
+#define PCM0_EN_SFT 0
+#define PCM0_EN_MASK 0x1
+#define PCM0_EN_MASK_SFT (0x1 << 0)
+
+/* AFE_PCM0_INTF_CON1 */
+#define PCM0_TX_RX_LOOPBACK_SFT 31
+#define PCM0_TX_RX_LOOPBACK_MASK 0x1
+#define PCM0_TX_RX_LOOPBACK_MASK_SFT (0x1 << 31)
+#define PCM0_BUFFER_LOOPBACK_SFT 30
+#define PCM0_BUFFER_LOOPBACK_MASK 0x1
+#define PCM0_BUFFER_LOOPBACK_MASK_SFT (0x1 << 30)
+#define PCM0_PARALLEL_LOOPBACK_SFT 29
+#define PCM0_PARALLEL_LOOPBACK_MASK 0x1
+#define PCM0_PARALLEL_LOOPBACK_MASK_SFT (0x1 << 29)
+#define PCM0_SERIAL_LOOPBACK_SFT 28
+#define PCM0_SERIAL_LOOPBACK_MASK 0x1
+#define PCM0_SERIAL_LOOPBACK_MASK_SFT (0x1 << 28)
+#define PCM0_DAI_LOOPBACK_SFT 27
+#define PCM0_DAI_LOOPBACK_MASK 0x1
+#define PCM0_DAI_LOOPBACK_MASK_SFT (0x1 << 27)
+#define PCM0_I2S_LOOPBACK_SFT 26
+#define PCM0_I2S_LOOPBACK_MASK 0x1
+#define PCM0_I2S_LOOPBACK_MASK_SFT (0x1 << 26)
+#define PCM0_1X_EN_DOMAIN_SFT 23
+#define PCM0_1X_EN_DOMAIN_MASK 0x7
+#define PCM0_1X_EN_DOMAIN_MASK_SFT (0x7 << 23)
+#define PCM0_1X_EN_MODE_SFT 18
+#define PCM0_1X_EN_MODE_MASK 0x1f
+#define PCM0_1X_EN_MODE_MASK_SFT (0x1f << 18)
+#define PCM0_TX3_RCH_DBG_MODE_SFT 17
+#define PCM0_TX3_RCH_DBG_MODE_MASK 0x1
+#define PCM0_TX3_RCH_DBG_MODE_MASK_SFT (0x1 << 17)
+#define PCM0_PCM1_LOOPBACK_SFT 16
+#define PCM0_PCM1_LOOPBACK_MASK 0x1
+#define PCM0_PCM1_LOOPBACK_MASK_SFT (0x1 << 16)
+#define PCM0_LOOPBACK_CH_SEL_SFT 12
+#define PCM0_LOOPBACK_CH_SEL_MASK 0x3
+#define PCM0_LOOPBACK_CH_SEL_MASK_SFT (0x3 << 12)
+#define PCM0_BT_MODE_SFT 11
+#define PCM0_BT_MODE_MASK 0x1
+#define PCM0_BT_MODE_MASK_SFT (0x1 << 11)
+#define PCM0_EXT_MODEM_SFT 10
+#define PCM0_EXT_MODEM_MASK 0x1
+#define PCM0_EXT_MODEM_MASK_SFT (0x1 << 10)
+#define PCM0_USE_MD3_SFT 9
+#define PCM0_USE_MD3_MASK 0x1
+#define PCM0_USE_MD3_MASK_SFT (0x1 << 9)
+#define PCM0_FIX_VALUE_SEL_SFT 8
+#define PCM0_FIX_VALUE_SEL_MASK 0x1
+#define PCM0_FIX_VALUE_SEL_MASK_SFT (0x1 << 8)
+#define PCM0_TX_FIX_VALUE_SFT 0
+#define PCM0_TX_FIX_VALUE_MASK 0xff
+#define PCM0_TX_FIX_VALUE_MASK_SFT (0xff << 0)
+
+/* AFE_PCM_INTF_MON */
+#define PCM0_TX_FIFO_OV_SFT 5
+#define PCM0_TX_FIFO_OV_MASK 0x1
+#define PCM0_TX_FIFO_OV_MASK_SFT (0x1 << 5)
+#define PCM0_RX_FIFO_OV_SFT 4
+#define PCM0_RX_FIFO_OV_MASK 0x1
+#define PCM0_RX_FIFO_OV_MASK_SFT (0x1 << 4)
+#define PCM1_TX_FIFO_OV_SFT 3
+#define PCM1_TX_FIFO_OV_MASK 0x1
+#define PCM1_TX_FIFO_OV_MASK_SFT (0x1 << 3)
+#define PCM1_RX_FIFO_OV_SFT 2
+#define PCM1_RX_FIFO_OV_MASK 0x1
+#define PCM1_RX_FIFO_OV_MASK_SFT (0x1 << 2)
+#define PCM0_SYNC_GLITCH_SFT 1
+#define PCM0_SYNC_GLITCH_MASK 0x1
+#define PCM0_SYNC_GLITCH_MASK_SFT (0x1 << 1)
+#define PCM1_SYNC_GLITCH_SFT 0
+#define PCM1_SYNC_GLITCH_MASK 0x1
+#define PCM1_SYNC_GLITCH_MASK_SFT (0x1 << 0)
+
+/* AFE_PCM1_INTF_CON0 */
+#define PCM1_TX_FIX_VALUE_SFT 24
+#define PCM1_TX_FIX_VALUE_MASK 0xff
+#define PCM1_TX_FIX_VALUE_MASK_SFT (0xff << 24)
+#define PCM1_FIX_VALUE_SEL_SFT 23
+#define PCM1_FIX_VALUE_SEL_MASK 0x1
+#define PCM1_FIX_VALUE_SEL_MASK_SFT (0x1 << 23)
+#define PCM1_BUFFER_LOOPBACK_SFT 22
+#define PCM1_BUFFER_LOOPBACK_MASK 0x1
+#define PCM1_BUFFER_LOOPBACK_MASK_SFT (0x1 << 22)
+#define PCM1_PARALLEL_LOOPBACK_SFT 21
+#define PCM1_PARALLEL_LOOPBACK_MASK 0x1
+#define PCM1_PARALLEL_LOOPBACK_MASK_SFT (0x1 << 21)
+#define PCM1_SERIAL_LOOPBACK_SFT 20
+#define PCM1_SERIAL_LOOPBACK_MASK 0x1
+#define PCM1_SERIAL_LOOPBACK_MASK_SFT (0x1 << 20)
+#define PCM1_DAI_PCM1_LOOPBACK_SFT 19
+#define PCM1_DAI_PCM1_LOOPBACK_MASK 0x1
+#define PCM1_DAI_PCM1_LOOPBACK_MASK_SFT (0x1 << 19)
+#define PCM1_I2S_PCM1_LOOPBACK_SFT 18
+#define PCM1_I2S_PCM1_LOOPBACK_MASK 0x1
+#define PCM1_I2S_PCM1_LOOPBACK_MASK_SFT (0x1 << 18)
+#define PCM1_SYNC_DELSEL_SFT 17
+#define PCM1_SYNC_DELSEL_MASK 0x1
+#define PCM1_SYNC_DELSEL_MASK_SFT (0x1 << 17)
+#define PCM1_TX_LR_SWAP_SFT 16
+#define PCM1_TX_LR_SWAP_MASK 0x1
+#define PCM1_TX_LR_SWAP_MASK_SFT (0x1 << 16)
+#define PCM1_SYNC_IN_INV_SFT 15
+#define PCM1_SYNC_IN_INV_MASK 0x1
+#define PCM1_SYNC_IN_INV_MASK_SFT (0x1 << 15)
+#define PCM1_BCLK_IN_INV_SFT 14
+#define PCM1_BCLK_IN_INV_MASK 0x1
+#define PCM1_BCLK_IN_INV_MASK_SFT (0x1 << 14)
+#define PCM1_TX_LCH_RPT_SFT 13
+#define PCM1_TX_LCH_RPT_MASK 0x1
+#define PCM1_TX_LCH_RPT_MASK_SFT (0x1 << 13)
+#define PCM1_VBT_16K_MODE_SFT 12
+#define PCM1_VBT_16K_MODE_MASK 0x1
+#define PCM1_VBT_16K_MODE_MASK_SFT (0x1 << 12)
+#define PCM1_LOOPBACK_CH_SEL_SFT 10
+#define PCM1_LOOPBACK_CH_SEL_MASK 0x3
+#define PCM1_LOOPBACK_CH_SEL_MASK_SFT (0x3 << 10)
+#define PCM1_TX2_BT_MODE_SFT 8
+#define PCM1_TX2_BT_MODE_MASK 0x1
+#define PCM1_TX2_BT_MODE_MASK_SFT (0x1 << 8)
+#define PCM1_BT_MODE_SFT 7
+#define PCM1_BT_MODE_MASK 0x1
+#define PCM1_BT_MODE_MASK_SFT (0x1 << 7)
+#define PCM1_AFIFO_SFT 6
+#define PCM1_AFIFO_MASK 0x1
+#define PCM1_AFIFO_MASK_SFT (0x1 << 6)
+#define PCM1_WLEN_SFT 5
+#define PCM1_WLEN_MASK 0x1
+#define PCM1_WLEN_MASK_SFT (0x1 << 5)
+#define PCM1_MODE_SFT 3
+#define PCM1_MODE_MASK 0x3
+#define PCM1_MODE_MASK_SFT (0x3 << 3)
+#define PCM1_FMT_SFT 1
+#define PCM1_FMT_MASK 0x3
+#define PCM1_FMT_MASK_SFT (0x3 << 1)
+#define PCM1_EN_SFT 0
+#define PCM1_EN_MASK 0x1
+#define PCM1_EN_MASK_SFT (0x1 << 0)
+
+/* AFE_PCM1_INTF_CON1 */
+#define PCM1_1X_EN_DOMAIN_SFT 23
+#define PCM1_1X_EN_DOMAIN_MASK 0x7
+#define PCM1_1X_EN_DOMAIN_MASK_SFT (0x7 << 23)
+#define PCM1_1X_EN_MODE_SFT 18
+#define PCM1_1X_EN_MODE_MASK 0x1f
+#define PCM1_1X_EN_MODE_MASK_SFT (0x1f << 18)
+
+/* AFE_PCM_TOP_IP_VERSION */
+#define AFE_PCM_TOP_IP_VERSION_SFT 0
+#define AFE_PCM_TOP_IP_VERSION_MASK 0xffffffff
+#define AFE_PCM_TOP_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AFE_IRQ_MCU_EN */
+#define AFE_IRQ_MCU_EN_SFT 0
+#define AFE_IRQ_MCU_EN_MASK 0xffffffff
+#define AFE_IRQ_MCU_EN_MASK_SFT (0xffffffff << 0)
+
+/* AFE_IRQ_MCU_DSP_EN */
+#define AFE_IRQ_DSP_EN_SFT 0
+#define AFE_IRQ_DSP_EN_MASK 0xffffffff
+#define AFE_IRQ_DSP_EN_MASK_SFT (0xffffffff << 0)
+
+/* AFE_IRQ_MCU_DSP2_EN */
+#define AFE_IRQ_DSP2_EN_SFT 0
+#define AFE_IRQ_DSP2_EN_MASK 0xffffffff
+#define AFE_IRQ_DSP2_EN_MASK_SFT (0xffffffff << 0)
+
+/* AFE_IRQ_MCU_SCP_EN */
+#define IRQ31_MCU_SCP_EN_SFT 31
+#define IRQ30_MCU_SCP_EN_SFT 30
+#define IRQ29_MCU_SCP_EN_SFT 29
+#define IRQ28_MCU_SCP_EN_SFT 28
+#define IRQ27_MCU_SCP_EN_SFT 27
+#define IRQ26_MCU_SCP_EN_SFT 26
+#define IRQ25_MCU_SCP_EN_SFT 25
+#define IRQ24_MCU_SCP_EN_SFT 24
+#define IRQ23_MCU_SCP_EN_SFT 23
+#define IRQ22_MCU_SCP_EN_SFT 22
+#define IRQ21_MCU_SCP_EN_SFT 21
+#define IRQ20_MCU_SCP_EN_SFT 20
+#define IRQ19_MCU_SCP_EN_SFT 19
+#define IRQ18_MCU_SCP_EN_SFT 18
+#define IRQ17_MCU_SCP_EN_SFT 17
+#define IRQ16_MCU_SCP_EN_SFT 16
+#define IRQ15_MCU_SCP_EN_SFT 15
+#define IRQ14_MCU_SCP_EN_SFT 14
+#define IRQ13_MCU_SCP_EN_SFT 13
+#define IRQ12_MCU_SCP_EN_SFT 12
+#define IRQ11_MCU_SCP_EN_SFT 11
+#define IRQ10_MCU_SCP_EN_SFT 10
+#define IRQ9_MCU_SCP_EN_SFT 9
+#define IRQ8_MCU_SCP_EN_SFT 8
+#define IRQ7_MCU_SCP_EN_SFT 7
+#define IRQ6_MCU_SCP_EN_SFT 6
+#define IRQ5_MCU_SCP_EN_SFT 5
+#define IRQ4_MCU_SCP_EN_SFT 4
+#define IRQ3_MCU_SCP_EN_SFT 3
+#define IRQ2_MCU_SCP_EN_SFT 2
+#define IRQ1_MCU_SCP_EN_SFT 1
+#define IRQ0_MCU_SCP_EN_SFT 0
+
+/* AFE_CUSTOM_IRQ_MCU_EN */
+#define AFE_CUSTOM_IRQ_MCU_EN_SFT 0
+#define AFE_CUSTOM_IRQ_MCU_EN_MASK 0xffffffff
+#define AFE_CUSTOM_IRQ_MCU_EN_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CUSTOM_IRQ_MCU_DSP_EN */
+#define AFE_CUSTOM_IRQ_DSP_EN_SFT 0
+#define AFE_CUSTOM_IRQ_DSP_EN_MASK 0xffffffff
+#define AFE_CUSTOM_IRQ_DSP_EN_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CUSTOM_IRQ_MCU_DSP2_EN */
+#define AFE_CUSTOM_IRQ_DSP2_EN_SFT 0
+#define AFE_CUSTOM_IRQ_DSP2_EN_MASK 0xffffffff
+#define AFE_CUSTOM_IRQ_DSP2_EN_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CUSTOM_IRQ_MCU_SCP_EN */
+#define AFE_CUSTOM_IRQ_SCP_EN_SFT 0
+#define AFE_CUSTOM_IRQ_SCP_EN_MASK 0xffffffff
+#define AFE_CUSTOM_IRQ_SCP_EN_MASK_SFT (0xffffffff << 0)
+
+/* AFE_IRQ_MCU_STATUS */
+#define IRQ26_MCU_SFT 26
+#define IRQ26_MCU_MASK 0x1
+#define IRQ26_MCU_MASK_SFT (0x1 << 26)
+#define IRQ25_MCU_SFT 25
+#define IRQ25_MCU_MASK 0x1
+#define IRQ25_MCU_MASK_SFT (0x1 << 25)
+#define IRQ24_MCU_SFT 24
+#define IRQ24_MCU_MASK 0x1
+#define IRQ24_MCU_MASK_SFT (0x1 << 24)
+#define IRQ23_MCU_SFT 23
+#define IRQ23_MCU_MASK 0x1
+#define IRQ23_MCU_MASK_SFT (0x1 << 23)
+#define IRQ22_MCU_SFT 22
+#define IRQ22_MCU_MASK 0x1
+#define IRQ22_MCU_MASK_SFT (0x1 << 22)
+#define IRQ21_MCU_SFT 21
+#define IRQ21_MCU_MASK 0x1
+#define IRQ21_MCU_MASK_SFT (0x1 << 21)
+#define IRQ20_MCU_SFT 20
+#define IRQ20_MCU_MASK 0x1
+#define IRQ20_MCU_MASK_SFT (0x1 << 20)
+#define IRQ19_MCU_SFT 19
+#define IRQ19_MCU_MASK 0x1
+#define IRQ19_MCU_MASK_SFT (0x1 << 19)
+#define IRQ18_MCU_SFT 18
+#define IRQ18_MCU_MASK 0x1
+#define IRQ18_MCU_MASK_SFT (0x1 << 18)
+#define IRQ17_MCU_SFT 17
+#define IRQ17_MCU_MASK 0x1
+#define IRQ17_MCU_MASK_SFT (0x1 << 17)
+#define IRQ16_MCU_SFT 16
+#define IRQ16_MCU_MASK 0x1
+#define IRQ16_MCU_MASK_SFT (0x1 << 16)
+#define IRQ15_MCU_SFT 15
+#define IRQ15_MCU_MASK 0x1
+#define IRQ15_MCU_MASK_SFT (0x1 << 15)
+#define IRQ14_MCU_SFT 14
+#define IRQ14_MCU_MASK 0x1
+#define IRQ14_MCU_MASK_SFT (0x1 << 14)
+#define IRQ13_MCU_SFT 13
+#define IRQ13_MCU_MASK 0x1
+#define IRQ13_MCU_MASK_SFT (0x1 << 13)
+#define IRQ12_MCU_SFT 12
+#define IRQ12_MCU_MASK 0x1
+#define IRQ12_MCU_MASK_SFT (0x1 << 12)
+#define IRQ11_MCU_SFT 11
+#define IRQ11_MCU_MASK 0x1
+#define IRQ11_MCU_MASK_SFT (0x1 << 11)
+#define IRQ10_MCU_SFT 10
+#define IRQ10_MCU_MASK 0x1
+#define IRQ10_MCU_MASK_SFT (0x1 << 10)
+#define IRQ9_MCU_SFT 9
+#define IRQ9_MCU_MASK 0x1
+#define IRQ9_MCU_MASK_SFT (0x1 << 9)
+#define IRQ8_MCU_SFT 8
+#define IRQ8_MCU_MASK 0x1
+#define IRQ8_MCU_MASK_SFT (0x1 << 8)
+#define IRQ7_MCU_SFT 7
+#define IRQ7_MCU_MASK 0x1
+#define IRQ7_MCU_MASK_SFT (0x1 << 7)
+#define IRQ6_MCU_SFT 6
+#define IRQ6_MCU_MASK 0x1
+#define IRQ6_MCU_MASK_SFT (0x1 << 6)
+#define IRQ5_MCU_SFT 5
+#define IRQ5_MCU_MASK 0x1
+#define IRQ5_MCU_MASK_SFT (0x1 << 5)
+#define IRQ4_MCU_SFT 4
+#define IRQ4_MCU_MASK 0x1
+#define IRQ4_MCU_MASK_SFT (0x1 << 4)
+#define IRQ3_MCU_SFT 3
+#define IRQ3_MCU_MASK 0x1
+#define IRQ3_MCU_MASK_SFT (0x1 << 3)
+#define IRQ2_MCU_SFT 2
+#define IRQ2_MCU_MASK 0x1
+#define IRQ2_MCU_MASK_SFT (0x1 << 2)
+#define IRQ1_MCU_SFT 1
+#define IRQ1_MCU_MASK 0x1
+#define IRQ1_MCU_MASK_SFT (0x1 << 1)
+#define IRQ0_MCU_SFT 0
+#define IRQ0_MCU_MASK 0x1
+#define IRQ0_MCU_MASK_SFT (0x1 << 0)
+
+/* AFE_CUSTOM_IRQ_MCU_STATUS */
+#define CUSTOM_IRQ21_MCU_SFT 21
+#define CUSTOM_IRQ21_MCU_MASK 0x1
+#define CUSTOM_IRQ21_MCU_MASK_SFT (0x1 << 21)
+#define CUSTOM_IRQ20_MCU_SFT 20
+#define CUSTOM_IRQ20_MCU_MASK 0x1
+#define CUSTOM_IRQ20_MCU_MASK_SFT (0x1 << 20)
+#define CUSTOM_IRQ19_MCU_SFT 19
+#define CUSTOM_IRQ19_MCU_MASK 0x1
+#define CUSTOM_IRQ19_MCU_MASK_SFT (0x1 << 19)
+#define CUSTOM_IRQ18_MCU_SFT 18
+#define CUSTOM_IRQ18_MCU_MASK 0x1
+#define CUSTOM_IRQ18_MCU_MASK_SFT (0x1 << 18)
+#define CUSTOM_IRQ17_MCU_SFT 17
+#define CUSTOM_IRQ17_MCU_MASK 0x1
+#define CUSTOM_IRQ17_MCU_MASK_SFT (0x1 << 17)
+#define CUSTOM_IRQ16_MCU_SFT 16
+#define CUSTOM_IRQ16_MCU_MASK 0x1
+#define CUSTOM_IRQ16_MCU_MASK_SFT (0x1 << 16)
+#define CUSTOM_IRQ9_MCU_SFT 9
+#define CUSTOM_IRQ9_MCU_MASK 0x1
+#define CUSTOM_IRQ9_MCU_MASK_SFT (0x1 << 9)
+#define CUSTOM_IRQ8_MCU_SFT 8
+#define CUSTOM_IRQ8_MCU_MASK 0x1
+#define CUSTOM_IRQ8_MCU_MASK_SFT (0x1 << 8)
+#define CUSTOM_IRQ7_MCU_SFT 7
+#define CUSTOM_IRQ7_MCU_MASK 0x1
+#define CUSTOM_IRQ7_MCU_MASK_SFT (0x1 << 7)
+#define CUSTOM_IRQ6_MCU_SFT 6
+#define CUSTOM_IRQ6_MCU_MASK 0x1
+#define CUSTOM_IRQ6_MCU_MASK_SFT (0x1 << 6)
+#define CUSTOM_IRQ5_MCU_SFT 5
+#define CUSTOM_IRQ5_MCU_MASK 0x1
+#define CUSTOM_IRQ5_MCU_MASK_SFT (0x1 << 5)
+#define CUSTOM_IRQ4_MCU_SFT 4
+#define CUSTOM_IRQ4_MCU_MASK 0x1
+#define CUSTOM_IRQ4_MCU_MASK_SFT (0x1 << 4)
+#define CUSTOM_IRQ3_MCU_SFT 3
+#define CUSTOM_IRQ3_MCU_MASK 0x1
+#define CUSTOM_IRQ3_MCU_MASK_SFT (0x1 << 3)
+#define CUSTOM_IRQ2_MCU_SFT 2
+#define CUSTOM_IRQ2_MCU_MASK 0x1
+#define CUSTOM_IRQ2_MCU_MASK_SFT (0x1 << 2)
+#define CUSTOM_IRQ1_MCU_SFT 1
+#define CUSTOM_IRQ1_MCU_MASK 0x1
+#define CUSTOM_IRQ1_MCU_MASK_SFT (0x1 << 1)
+#define CUSTOM_IRQ0_MCU_SFT 0
+#define CUSTOM_IRQ0_MCU_MASK 0x1
+#define CUSTOM_IRQ0_MCU_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ_MCU_CFG */
+#define AFE_IRQ_CLR_CFG_SFT 31
+#define AFE_IRQ_CLR_CFG_MASK 0x1
+#define AFE_IRQ_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ_MCU_CNT_SFT 0
+#define AFE_IRQ_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ0_MCU_CFG0 */
+#define AFE_IRQ0_MCU_DOMAIN_SFT 9
+#define AFE_IRQ0_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ0_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ0_MCU_FS_SFT 4
+#define AFE_IRQ0_MCU_FS_MASK 0x1f
+#define AFE_IRQ0_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ0_MCU_ON_SFT 0
+#define AFE_IRQ0_MCU_ON_MASK 0x1
+#define AFE_IRQ0_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ0_MCU_CFG1 */
+#define AFE_IRQ0_CLR_CFG_SFT 31
+#define AFE_IRQ0_CLR_CFG_MASK 0x1
+#define AFE_IRQ0_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ0_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ0_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ0_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ0_MCU_CNT_SFT 0
+#define AFE_IRQ0_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ0_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ1_MCU_CFG0 */
+#define AFE_IRQ1_MCU_DOMAIN_SFT 9
+#define AFE_IRQ1_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ1_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ1_MCU_FS_SFT 4
+#define AFE_IRQ1_MCU_FS_MASK 0x1f
+#define AFE_IRQ1_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ1_MCU_ON_SFT 0
+#define AFE_IRQ1_MCU_ON_MASK 0x1
+#define AFE_IRQ1_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ1_MCU_CFG1 */
+#define AFE_IRQ1_CLR_CFG_SFT 31
+#define AFE_IRQ1_CLR_CFG_MASK 0x1
+#define AFE_IRQ1_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ1_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ1_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ1_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ1_MCU_CNT_SFT 0
+#define AFE_IRQ1_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ1_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ2_MCU_CFG0 */
+#define AFE_IRQ2_MCU_DOMAIN_SFT 9
+#define AFE_IRQ2_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ2_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ2_MCU_FS_SFT 4
+#define AFE_IRQ2_MCU_FS_MASK 0x1f
+#define AFE_IRQ2_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ2_MCU_ON_SFT 0
+#define AFE_IRQ2_MCU_ON_MASK 0x1
+#define AFE_IRQ2_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ2_MCU_CFG1 */
+#define AFE_IRQ2_CLR_CFG_SFT 31
+#define AFE_IRQ2_CLR_CFG_MASK 0x1
+#define AFE_IRQ2_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ2_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ2_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ2_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ2_MCU_CNT_SFT 0
+#define AFE_IRQ2_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ2_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ3_MCU_CFG0 */
+#define AFE_IRQ3_MCU_DOMAIN_SFT 9
+#define AFE_IRQ3_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ3_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ3_MCU_FS_SFT 4
+#define AFE_IRQ3_MCU_FS_MASK 0x1f
+#define AFE_IRQ3_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ3_MCU_ON_SFT 0
+#define AFE_IRQ3_MCU_ON_MASK 0x1
+#define AFE_IRQ3_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ3_MCU_CFG1 */
+#define AFE_IRQ3_CLR_CFG_SFT 31
+#define AFE_IRQ3_CLR_CFG_MASK 0x1
+#define AFE_IRQ3_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ3_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ3_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ3_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ3_MCU_CNT_SFT 0
+#define AFE_IRQ3_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ3_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ4_MCU_CFG0 */
+#define AFE_IRQ4_MCU_DOMAIN_SFT 9
+#define AFE_IRQ4_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ4_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ4_MCU_FS_SFT 4
+#define AFE_IRQ4_MCU_FS_MASK 0x1f
+#define AFE_IRQ4_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ4_MCU_ON_SFT 0
+#define AFE_IRQ4_MCU_ON_MASK 0x1
+#define AFE_IRQ4_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ4_MCU_CFG1 */
+#define AFE_IRQ4_CLR_CFG_SFT 31
+#define AFE_IRQ4_CLR_CFG_MASK 0x1
+#define AFE_IRQ4_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ4_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ4_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ4_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ4_MCU_CNT_SFT 0
+#define AFE_IRQ4_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ4_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ5_MCU_CFG0 */
+#define AFE_IRQ5_MCU_DOMAIN_SFT 9
+#define AFE_IRQ5_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ5_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ5_MCU_FS_SFT 4
+#define AFE_IRQ5_MCU_FS_MASK 0x1f
+#define AFE_IRQ5_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ5_MCU_ON_SFT 0
+#define AFE_IRQ5_MCU_ON_MASK 0x1
+#define AFE_IRQ5_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ5_MCU_CFG1 */
+#define AFE_IRQ5_CLR_CFG_SFT 31
+#define AFE_IRQ5_CLR_CFG_MASK 0x1
+#define AFE_IRQ5_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ5_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ5_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ5_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ5_MCU_CNT_SFT 0
+#define AFE_IRQ5_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ5_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ6_MCU_CFG0 */
+#define AFE_IRQ6_MCU_DOMAIN_SFT 9
+#define AFE_IRQ6_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ6_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ6_MCU_FS_SFT 4
+#define AFE_IRQ6_MCU_FS_MASK 0x1f
+#define AFE_IRQ6_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ6_MCU_ON_SFT 0
+#define AFE_IRQ6_MCU_ON_MASK 0x1
+#define AFE_IRQ6_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ6_MCU_CFG1 */
+#define AFE_IRQ6_CLR_CFG_SFT 31
+#define AFE_IRQ6_CLR_CFG_MASK 0x1
+#define AFE_IRQ6_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ6_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ6_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ6_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ6_MCU_CNT_SFT 0
+#define AFE_IRQ6_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ6_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ7_MCU_CFG0 */
+#define AFE_IRQ7_MCU_DOMAIN_SFT 9
+#define AFE_IRQ7_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ7_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ7_MCU_FS_SFT 4
+#define AFE_IRQ7_MCU_FS_MASK 0x1f
+#define AFE_IRQ7_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ7_MCU_ON_SFT 0
+#define AFE_IRQ7_MCU_ON_MASK 0x1
+#define AFE_IRQ7_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ7_MCU_CFG1 */
+#define AFE_IRQ7_CLR_CFG_SFT 31
+#define AFE_IRQ7_CLR_CFG_MASK 0x1
+#define AFE_IRQ7_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ7_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ7_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ7_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ7_MCU_CNT_SFT 0
+#define AFE_IRQ7_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ7_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ8_MCU_CFG0 */
+#define AFE_IRQ8_MCU_DOMAIN_SFT 9
+#define AFE_IRQ8_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ8_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ8_MCU_FS_SFT 4
+#define AFE_IRQ8_MCU_FS_MASK 0x1f
+#define AFE_IRQ8_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ8_MCU_ON_SFT 0
+#define AFE_IRQ8_MCU_ON_MASK 0x1
+#define AFE_IRQ8_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ8_MCU_CFG1 */
+#define AFE_IRQ8_CLR_CFG_SFT 31
+#define AFE_IRQ8_CLR_CFG_MASK 0x1
+#define AFE_IRQ8_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ8_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ8_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ8_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ8_MCU_CNT_SFT 0
+#define AFE_IRQ8_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ8_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ9_MCU_CFG0 */
+#define AFE_IRQ9_MCU_DOMAIN_SFT 9
+#define AFE_IRQ9_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ9_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ9_MCU_FS_SFT 4
+#define AFE_IRQ9_MCU_FS_MASK 0x1f
+#define AFE_IRQ9_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ9_MCU_ON_SFT 0
+#define AFE_IRQ9_MCU_ON_MASK 0x1
+#define AFE_IRQ9_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ9_MCU_CFG1 */
+#define AFE_IRQ9_CLR_CFG_SFT 31
+#define AFE_IRQ9_CLR_CFG_MASK 0x1
+#define AFE_IRQ9_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ9_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ9_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ9_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ9_MCU_CNT_SFT 0
+#define AFE_IRQ9_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ9_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ10_MCU_CFG0 */
+#define AFE_IRQ10_MCU_DOMAIN_SFT 9
+#define AFE_IRQ10_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ10_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ10_MCU_FS_SFT 4
+#define AFE_IRQ10_MCU_FS_MASK 0x1f
+#define AFE_IRQ10_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ10_MCU_ON_SFT 0
+#define AFE_IRQ10_MCU_ON_MASK 0x1
+#define AFE_IRQ10_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ10_MCU_CFG1 */
+#define AFE_IRQ10_CLR_CFG_SFT 31
+#define AFE_IRQ10_CLR_CFG_MASK 0x1
+#define AFE_IRQ10_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ10_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ10_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ10_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ10_MCU_CNT_SFT 0
+#define AFE_IRQ10_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ10_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ11_MCU_CFG0 */
+#define AFE_IRQ11_MCU_DOMAIN_SFT 9
+#define AFE_IRQ11_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ11_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ11_MCU_FS_SFT 4
+#define AFE_IRQ11_MCU_FS_MASK 0x1f
+#define AFE_IRQ11_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ11_MCU_ON_SFT 0
+#define AFE_IRQ11_MCU_ON_MASK 0x1
+#define AFE_IRQ11_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ11_MCU_CFG1 */
+#define AFE_IRQ11_CLR_CFG_SFT 31
+#define AFE_IRQ11_CLR_CFG_MASK 0x1
+#define AFE_IRQ11_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ11_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ11_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ11_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ11_MCU_CNT_SFT 0
+#define AFE_IRQ11_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ11_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ12_MCU_CFG0 */
+#define AFE_IRQ12_MCU_DOMAIN_SFT 9
+#define AFE_IRQ12_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ12_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ12_MCU_FS_SFT 4
+#define AFE_IRQ12_MCU_FS_MASK 0x1f
+#define AFE_IRQ12_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ12_MCU_ON_SFT 0
+#define AFE_IRQ12_MCU_ON_MASK 0x1
+#define AFE_IRQ12_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ12_MCU_CFG1 */
+#define AFE_IRQ12_CLR_CFG_SFT 31
+#define AFE_IRQ12_CLR_CFG_MASK 0x1
+#define AFE_IRQ12_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ12_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ12_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ12_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ12_MCU_CNT_SFT 0
+#define AFE_IRQ12_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ12_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ13_MCU_CFG0 */
+#define AFE_IRQ13_MCU_DOMAIN_SFT 9
+#define AFE_IRQ13_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ13_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ13_MCU_FS_SFT 4
+#define AFE_IRQ13_MCU_FS_MASK 0x1f
+#define AFE_IRQ13_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ13_MCU_ON_SFT 0
+#define AFE_IRQ13_MCU_ON_MASK 0x1
+#define AFE_IRQ13_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ13_MCU_CFG1 */
+#define AFE_IRQ13_CLR_CFG_SFT 31
+#define AFE_IRQ13_CLR_CFG_MASK 0x1
+#define AFE_IRQ13_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ13_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ13_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ13_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ13_MCU_CNT_SFT 0
+#define AFE_IRQ13_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ13_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ14_MCU_CFG0 */
+#define AFE_IRQ14_MCU_DOMAIN_SFT 9
+#define AFE_IRQ14_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ14_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ14_MCU_FS_SFT 4
+#define AFE_IRQ14_MCU_FS_MASK 0x1f
+#define AFE_IRQ14_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ14_MCU_ON_SFT 0
+#define AFE_IRQ14_MCU_ON_MASK 0x1
+#define AFE_IRQ14_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ14_MCU_CFG1 */
+#define AFE_IRQ14_CLR_CFG_SFT 31
+#define AFE_IRQ14_CLR_CFG_MASK 0x1
+#define AFE_IRQ14_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ14_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ14_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ14_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ14_MCU_CNT_SFT 0
+#define AFE_IRQ14_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ14_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ15_MCU_CFG0 */
+#define AFE_IRQ15_MCU_DOMAIN_SFT 9
+#define AFE_IRQ15_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ15_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ15_MCU_FS_SFT 4
+#define AFE_IRQ15_MCU_FS_MASK 0x1f
+#define AFE_IRQ15_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ15_MCU_ON_SFT 0
+#define AFE_IRQ15_MCU_ON_MASK 0x1
+#define AFE_IRQ15_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ15_MCU_CFG1 */
+#define AFE_IRQ15_CLR_CFG_SFT 31
+#define AFE_IRQ15_CLR_CFG_MASK 0x1
+#define AFE_IRQ15_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ15_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ15_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ15_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ15_MCU_CNT_SFT 0
+#define AFE_IRQ15_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ15_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ16_MCU_CFG0 */
+#define AFE_IRQ16_MCU_DOMAIN_SFT 9
+#define AFE_IRQ16_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ16_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ16_MCU_FS_SFT 4
+#define AFE_IRQ16_MCU_FS_MASK 0x1f
+#define AFE_IRQ16_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ16_MCU_ON_SFT 0
+#define AFE_IRQ16_MCU_ON_MASK 0x1
+#define AFE_IRQ16_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ16_MCU_CFG1 */
+#define AFE_IRQ16_CLR_CFG_SFT 31
+#define AFE_IRQ16_CLR_CFG_MASK 0x1
+#define AFE_IRQ16_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ16_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ16_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ16_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ16_MCU_CNT_SFT 0
+#define AFE_IRQ16_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ16_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ17_MCU_CFG0 */
+#define AFE_IRQ17_MCU_DOMAIN_SFT 9
+#define AFE_IRQ17_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ17_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ17_MCU_FS_SFT 4
+#define AFE_IRQ17_MCU_FS_MASK 0x1f
+#define AFE_IRQ17_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ17_MCU_ON_SFT 0
+#define AFE_IRQ17_MCU_ON_MASK 0x1
+#define AFE_IRQ17_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ17_MCU_CFG1 */
+#define AFE_IRQ17_CLR_CFG_SFT 31
+#define AFE_IRQ17_CLR_CFG_MASK 0x1
+#define AFE_IRQ17_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ17_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ17_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ17_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ17_MCU_CNT_SFT 0
+#define AFE_IRQ17_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ17_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ18_MCU_CFG0 */
+#define AFE_IRQ18_MCU_DOMAIN_SFT 9
+#define AFE_IRQ18_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ18_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ18_MCU_FS_SFT 4
+#define AFE_IRQ18_MCU_FS_MASK 0x1f
+#define AFE_IRQ18_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ18_MCU_ON_SFT 0
+#define AFE_IRQ18_MCU_ON_MASK 0x1
+#define AFE_IRQ18_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ18_MCU_CFG1 */
+#define AFE_IRQ18_CLR_CFG_SFT 31
+#define AFE_IRQ18_CLR_CFG_MASK 0x1
+#define AFE_IRQ18_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ18_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ18_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ18_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ18_MCU_CNT_SFT 0
+#define AFE_IRQ18_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ18_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ19_MCU_CFG0 */
+#define AFE_IRQ19_MCU_DOMAIN_SFT 9
+#define AFE_IRQ19_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ19_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ19_MCU_FS_SFT 4
+#define AFE_IRQ19_MCU_FS_MASK 0x1f
+#define AFE_IRQ19_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ19_MCU_ON_SFT 0
+#define AFE_IRQ19_MCU_ON_MASK 0x1
+#define AFE_IRQ19_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ19_MCU_CFG1 */
+#define AFE_IRQ19_CLR_CFG_SFT 31
+#define AFE_IRQ19_CLR_CFG_MASK 0x1
+#define AFE_IRQ19_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ19_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ19_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ19_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ19_MCU_CNT_SFT 0
+#define AFE_IRQ19_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ19_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ20_MCU_CFG0 */
+#define AFE_IRQ20_MCU_DOMAIN_SFT 9
+#define AFE_IRQ20_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ20_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ20_MCU_FS_SFT 4
+#define AFE_IRQ20_MCU_FS_MASK 0x1f
+#define AFE_IRQ20_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ20_MCU_ON_SFT 0
+#define AFE_IRQ20_MCU_ON_MASK 0x1
+#define AFE_IRQ20_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ20_MCU_CFG1 */
+#define AFE_IRQ20_CLR_CFG_SFT 31
+#define AFE_IRQ20_CLR_CFG_MASK 0x1
+#define AFE_IRQ20_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ20_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ20_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ20_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ20_MCU_CNT_SFT 0
+#define AFE_IRQ20_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ20_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ21_MCU_CFG0 */
+#define AFE_IRQ21_MCU_DOMAIN_SFT 9
+#define AFE_IRQ21_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ21_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ21_MCU_FS_SFT 4
+#define AFE_IRQ21_MCU_FS_MASK 0x1f
+#define AFE_IRQ21_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ21_MCU_ON_SFT 0
+#define AFE_IRQ21_MCU_ON_MASK 0x1
+#define AFE_IRQ21_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ21_MCU_CFG1 */
+#define AFE_IRQ21_CLR_CFG_SFT 31
+#define AFE_IRQ21_CLR_CFG_MASK 0x1
+#define AFE_IRQ21_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ21_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ21_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ21_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ21_MCU_CNT_SFT 0
+#define AFE_IRQ21_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ21_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ22_MCU_CFG0 */
+#define AFE_IRQ22_MCU_DOMAIN_SFT 9
+#define AFE_IRQ22_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ22_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ22_MCU_FS_SFT 4
+#define AFE_IRQ22_MCU_FS_MASK 0x1f
+#define AFE_IRQ22_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ22_MCU_ON_SFT 0
+#define AFE_IRQ22_MCU_ON_MASK 0x1
+#define AFE_IRQ22_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ22_MCU_CFG1 */
+#define AFE_IRQ22_CLR_CFG_SFT 31
+#define AFE_IRQ22_CLR_CFG_MASK 0x1
+#define AFE_IRQ22_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ22_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ22_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ22_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ22_MCU_CNT_SFT 0
+#define AFE_IRQ22_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ22_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ23_MCU_CFG0 */
+#define AFE_IRQ23_MCU_DOMAIN_SFT 9
+#define AFE_IRQ23_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ23_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ23_MCU_FS_SFT 4
+#define AFE_IRQ23_MCU_FS_MASK 0x1f
+#define AFE_IRQ23_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ23_MCU_ON_SFT 0
+#define AFE_IRQ23_MCU_ON_MASK 0x1
+#define AFE_IRQ23_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ23_MCU_CFG1 */
+#define AFE_IRQ23_CLR_CFG_SFT 31
+#define AFE_IRQ23_CLR_CFG_MASK 0x1
+#define AFE_IRQ23_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ23_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ23_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ23_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ23_MCU_CNT_SFT 0
+#define AFE_IRQ23_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ23_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ24_MCU_CFG0 */
+#define AFE_IRQ24_MCU_DOMAIN_SFT 9
+#define AFE_IRQ24_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ24_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ24_MCU_FS_SFT 4
+#define AFE_IRQ24_MCU_FS_MASK 0x1f
+#define AFE_IRQ24_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ24_MCU_ON_SFT 0
+#define AFE_IRQ24_MCU_ON_MASK 0x1
+#define AFE_IRQ24_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ24_MCU_CFG1 */
+#define AFE_IRQ24_CLR_CFG_SFT 31
+#define AFE_IRQ24_CLR_CFG_MASK 0x1
+#define AFE_IRQ24_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ24_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ24_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ24_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ24_MCU_CNT_SFT 0
+#define AFE_IRQ24_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ24_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ25_MCU_CFG0 */
+#define AFE_IRQ25_MCU_DOMAIN_SFT 9
+#define AFE_IRQ25_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ25_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ25_MCU_FS_SFT 4
+#define AFE_IRQ25_MCU_FS_MASK 0x1f
+#define AFE_IRQ25_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ25_MCU_ON_SFT 0
+#define AFE_IRQ25_MCU_ON_MASK 0x1
+#define AFE_IRQ25_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ25_MCU_CFG1 */
+#define AFE_IRQ25_CLR_CFG_SFT 31
+#define AFE_IRQ25_CLR_CFG_MASK 0x1
+#define AFE_IRQ25_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ25_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ25_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ25_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ25_MCU_CNT_SFT 0
+#define AFE_IRQ25_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ25_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ26_MCU_CFG0 */
+#define AFE_IRQ26_MCU_DOMAIN_SFT 9
+#define AFE_IRQ26_MCU_DOMAIN_MASK 0x7
+#define AFE_IRQ26_MCU_DOMAIN_MASK_SFT (0x7 << 9)
+#define AFE_IRQ26_MCU_FS_SFT 4
+#define AFE_IRQ26_MCU_FS_MASK 0x1f
+#define AFE_IRQ26_MCU_FS_MASK_SFT (0x1f << 4)
+#define AFE_IRQ26_MCU_ON_SFT 0
+#define AFE_IRQ26_MCU_ON_MASK 0x1
+#define AFE_IRQ26_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ26_MCU_CFG1 */
+#define AFE_IRQ26_CLR_CFG_SFT 31
+#define AFE_IRQ26_CLR_CFG_MASK 0x1
+#define AFE_IRQ26_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_IRQ26_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_IRQ26_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_IRQ26_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_IRQ26_MCU_CNT_SFT 0
+#define AFE_IRQ26_MCU_CNT_MASK 0xffffff
+#define AFE_IRQ26_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_CUSTOM_IRQ0_MCU_CFG0 */
+#define AFE_CUSTOM_IRQ0_MCU_ON_SFT 0
+#define AFE_CUSTOM_IRQ0_MCU_ON_MASK 0x1
+#define AFE_CUSTOM_IRQ0_MCU_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ_MCU_MON0 */
+#define AFE_IRQ26_MISS_FLAG_SFT 26
+#define AFE_IRQ26_MISS_FLAG_MASK 0x1
+#define AFE_IRQ26_MISS_FLAG_MASK_SFT (0x1 << 26)
+#define AFE_IRQ25_MISS_FLAG_SFT 25
+#define AFE_IRQ25_MISS_FLAG_MASK 0x1
+#define AFE_IRQ25_MISS_FLAG_MASK_SFT (0x1 << 25)
+#define AFE_IRQ24_MISS_FLAG_SFT 24
+#define AFE_IRQ24_MISS_FLAG_MASK 0x1
+#define AFE_IRQ24_MISS_FLAG_MASK_SFT (0x1 << 24)
+#define AFE_IRQ23_MISS_FLAG_SFT 23
+#define AFE_IRQ23_MISS_FLAG_MASK 0x1
+#define AFE_IRQ23_MISS_FLAG_MASK_SFT (0x1 << 23)
+#define AFE_IRQ22_MISS_FLAG_SFT 22
+#define AFE_IRQ22_MISS_FLAG_MASK 0x1
+#define AFE_IRQ22_MISS_FLAG_MASK_SFT (0x1 << 22)
+#define AFE_IRQ21_MISS_FLAG_SFT 21
+#define AFE_IRQ21_MISS_FLAG_MASK 0x1
+#define AFE_IRQ21_MISS_FLAG_MASK_SFT (0x1 << 21)
+#define AFE_IRQ20_MISS_FLAG_SFT 20
+#define AFE_IRQ20_MISS_FLAG_MASK 0x1
+#define AFE_IRQ20_MISS_FLAG_MASK_SFT (0x1 << 20)
+#define AFE_IRQ19_MISS_FLAG_SFT 19
+#define AFE_IRQ19_MISS_FLAG_MASK 0x1
+#define AFE_IRQ19_MISS_FLAG_MASK_SFT (0x1 << 19)
+#define AFE_IRQ18_MISS_FLAG_SFT 18
+#define AFE_IRQ18_MISS_FLAG_MASK 0x1
+#define AFE_IRQ18_MISS_FLAG_MASK_SFT (0x1 << 18)
+#define AFE_IRQ17_MISS_FLAG_SFT 17
+#define AFE_IRQ17_MISS_FLAG_MASK 0x1
+#define AFE_IRQ17_MISS_FLAG_MASK_SFT (0x1 << 17)
+#define AFE_IRQ16_MISS_FLAG_SFT 16
+#define AFE_IRQ16_MISS_FLAG_MASK 0x1
+#define AFE_IRQ16_MISS_FLAG_MASK_SFT (0x1 << 16)
+#define AFE_IRQ15_MISS_FLAG_SFT 15
+#define AFE_IRQ15_MISS_FLAG_MASK 0x1
+#define AFE_IRQ15_MISS_FLAG_MASK_SFT (0x1 << 15)
+#define AFE_IRQ14_MISS_FLAG_SFT 14
+#define AFE_IRQ14_MISS_FLAG_MASK 0x1
+#define AFE_IRQ14_MISS_FLAG_MASK_SFT (0x1 << 14)
+#define AFE_IRQ13_MISS_FLAG_SFT 13
+#define AFE_IRQ13_MISS_FLAG_MASK 0x1
+#define AFE_IRQ13_MISS_FLAG_MASK_SFT (0x1 << 13)
+#define AFE_IRQ12_MISS_FLAG_SFT 12
+#define AFE_IRQ12_MISS_FLAG_MASK 0x1
+#define AFE_IRQ12_MISS_FLAG_MASK_SFT (0x1 << 12)
+#define AFE_IRQ11_MISS_FLAG_SFT 11
+#define AFE_IRQ11_MISS_FLAG_MASK 0x1
+#define AFE_IRQ11_MISS_FLAG_MASK_SFT (0x1 << 11)
+#define AFE_IRQ10_MISS_FLAG_SFT 10
+#define AFE_IRQ10_MISS_FLAG_MASK 0x1
+#define AFE_IRQ10_MISS_FLAG_MASK_SFT (0x1 << 10)
+#define AFE_IRQ9_MISS_FLAG_SFT 9
+#define AFE_IRQ9_MISS_FLAG_MASK 0x1
+#define AFE_IRQ9_MISS_FLAG_MASK_SFT (0x1 << 9)
+#define AFE_IRQ8_MISS_FLAG_SFT 8
+#define AFE_IRQ8_MISS_FLAG_MASK 0x1
+#define AFE_IRQ8_MISS_FLAG_MASK_SFT (0x1 << 8)
+#define AFE_IRQ7_MISS_FLAG_SFT 7
+#define AFE_IRQ7_MISS_FLAG_MASK 0x1
+#define AFE_IRQ7_MISS_FLAG_MASK_SFT (0x1 << 7)
+#define AFE_IRQ6_MISS_FLAG_SFT 6
+#define AFE_IRQ6_MISS_FLAG_MASK 0x1
+#define AFE_IRQ6_MISS_FLAG_MASK_SFT (0x1 << 6)
+#define AFE_IRQ5_MISS_FLAG_SFT 5
+#define AFE_IRQ5_MISS_FLAG_MASK 0x1
+#define AFE_IRQ5_MISS_FLAG_MASK_SFT (0x1 << 5)
+#define AFE_IRQ4_MISS_FLAG_SFT 4
+#define AFE_IRQ4_MISS_FLAG_MASK 0x1
+#define AFE_IRQ4_MISS_FLAG_MASK_SFT (0x1 << 4)
+#define AFE_IRQ3_MISS_FLAG_SFT 3
+#define AFE_IRQ3_MISS_FLAG_MASK 0x1
+#define AFE_IRQ3_MISS_FLAG_MASK_SFT (0x1 << 3)
+#define AFE_IRQ2_MISS_FLAG_SFT 2
+#define AFE_IRQ2_MISS_FLAG_MASK 0x1
+#define AFE_IRQ2_MISS_FLAG_MASK_SFT (0x1 << 2)
+#define AFE_IRQ1_MISS_FLAG_SFT 1
+#define AFE_IRQ1_MISS_FLAG_MASK 0x1
+#define AFE_IRQ1_MISS_FLAG_MASK_SFT (0x1 << 1)
+#define AFE_IRQ0_MISS_FLAG_SFT 0
+#define AFE_IRQ0_MISS_FLAG_MASK 0x1
+#define AFE_IRQ0_MISS_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ_MCU_MON1 */
+#define AFE_CUSTOM_IRQ21_MISS_FLAG_SFT 21
+#define AFE_CUSTOM_IRQ21_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ21_MISS_FLAG_MASK_SFT (0x1 << 21)
+#define AFE_CUSTOM_IRQ20_MISS_FLAG_SFT 20
+#define AFE_CUSTOM_IRQ20_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ20_MISS_FLAG_MASK_SFT (0x1 << 20)
+#define AFE_CUSTOM_IRQ19_MISS_FLAG_SFT 19
+#define AFE_CUSTOM_IRQ19_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ19_MISS_FLAG_MASK_SFT (0x1 << 19)
+#define AFE_CUSTOM_IRQ18_MISS_FLAG_SFT 18
+#define AFE_CUSTOM_IRQ18_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ18_MISS_FLAG_MASK_SFT (0x1 << 18)
+#define AFE_CUSTOM_IRQ17_MISS_FLAG_SFT 17
+#define AFE_CUSTOM_IRQ17_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ17_MISS_FLAG_MASK_SFT (0x1 << 17)
+#define AFE_CUSTOM_IRQ16_MISS_FLAG_SFT 16
+#define AFE_CUSTOM_IRQ16_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ16_MISS_FLAG_MASK_SFT (0x1 << 16)
+#define AFE_CUSTOM_IRQ9_MISS_FLAG_SFT 9
+#define AFE_CUSTOM_IRQ9_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ9_MISS_FLAG_MASK_SFT (0x1 << 9)
+#define AFE_CUSTOM_IRQ8_MISS_FLAG_SFT 8
+#define AFE_CUSTOM_IRQ8_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ8_MISS_FLAG_MASK_SFT (0x1 << 8)
+#define AFE_CUSTOM_IRQ7_MISS_FLAG_SFT 7
+#define AFE_CUSTOM_IRQ7_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ7_MISS_FLAG_MASK_SFT (0x1 << 7)
+#define AFE_CUSTOM_IRQ6_MISS_FLAG_SFT 6
+#define AFE_CUSTOM_IRQ6_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ6_MISS_FLAG_MASK_SFT (0x1 << 6)
+#define AFE_CUSTOM_IRQ5_MISS_FLAG_SFT 5
+#define AFE_CUSTOM_IRQ5_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ5_MISS_FLAG_MASK_SFT (0x1 << 5)
+#define AFE_CUSTOM_IRQ4_MISS_FLAG_SFT 4
+#define AFE_CUSTOM_IRQ4_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ4_MISS_FLAG_MASK_SFT (0x1 << 4)
+#define AFE_CUSTOM_IRQ3_MISS_FLAG_SFT 3
+#define AFE_CUSTOM_IRQ3_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ3_MISS_FLAG_MASK_SFT (0x1 << 3)
+#define AFE_CUSTOM_IRQ2_MISS_FLAG_SFT 2
+#define AFE_CUSTOM_IRQ2_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ2_MISS_FLAG_MASK_SFT (0x1 << 2)
+#define AFE_CUSTOM_IRQ1_MISS_FLAG_SFT 1
+#define AFE_CUSTOM_IRQ1_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ1_MISS_FLAG_MASK_SFT (0x1 << 1)
+#define AFE_CUSTOM_IRQ0_MISS_FLAG_SFT 0
+#define AFE_CUSTOM_IRQ0_MISS_FLAG_MASK 0x1
+#define AFE_CUSTOM_IRQ0_MISS_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_IRQ_MCU_MON2 */
+#define AFE_IRQ_B_R_CNT_SFT 8
+#define AFE_IRQ_B_R_CNT_MASK 0xff
+#define AFE_IRQ_B_R_CNT_MASK_SFT (0xff << 8)
+#define AFE_IRQ_B_F_CNT_SFT 0
+#define AFE_IRQ_B_F_CNT_MASK 0xff
+#define AFE_IRQ_B_F_CNT_MASK_SFT (0xff << 0)
+
+/* AFE_IRQ0_CNT_MON */
+#define AFE_IRQ0_CNT_MON_SFT 0
+#define AFE_IRQ0_CNT_MON_MASK 0xffffff
+#define AFE_IRQ0_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ1_CNT_MON */
+#define AFE_IRQ1_CNT_MON_SFT 0
+#define AFE_IRQ1_CNT_MON_MASK 0xffffff
+#define AFE_IRQ1_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ2_CNT_MON */
+#define AFE_IRQ2_CNT_MON_SFT 0
+#define AFE_IRQ2_CNT_MON_MASK 0xffffff
+#define AFE_IRQ2_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ3_CNT_MON */
+#define AFE_IRQ3_CNT_MON_SFT 0
+#define AFE_IRQ3_CNT_MON_MASK 0xffffff
+#define AFE_IRQ3_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ4_CNT_MON */
+#define AFE_IRQ4_CNT_MON_SFT 0
+#define AFE_IRQ4_CNT_MON_MASK 0xffffff
+#define AFE_IRQ4_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ5_CNT_MON */
+#define AFE_IRQ5_CNT_MON_SFT 0
+#define AFE_IRQ5_CNT_MON_MASK 0xffffff
+#define AFE_IRQ5_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ6_CNT_MON */
+#define AFE_IRQ6_CNT_MON_SFT 0
+#define AFE_IRQ6_CNT_MON_MASK 0xffffff
+#define AFE_IRQ6_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ7_CNT_MON */
+#define AFE_IRQ7_CNT_MON_SFT 0
+#define AFE_IRQ7_CNT_MON_MASK 0xffffff
+#define AFE_IRQ7_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ8_CNT_MON */
+#define AFE_IRQ8_CNT_MON_SFT 0
+#define AFE_IRQ8_CNT_MON_MASK 0xffffff
+#define AFE_IRQ8_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ9_CNT_MON */
+#define AFE_IRQ9_CNT_MON_SFT 0
+#define AFE_IRQ9_CNT_MON_MASK 0xffffff
+#define AFE_IRQ9_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ10_CNT_MON */
+#define AFE_IRQ10_CNT_MON_SFT 0
+#define AFE_IRQ10_CNT_MON_MASK 0xffffff
+#define AFE_IRQ10_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ11_CNT_MON */
+#define AFE_IRQ11_CNT_MON_SFT 0
+#define AFE_IRQ11_CNT_MON_MASK 0xffffff
+#define AFE_IRQ11_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ12_CNT_MON */
+#define AFE_IRQ12_CNT_MON_SFT 0
+#define AFE_IRQ12_CNT_MON_MASK 0xffffff
+#define AFE_IRQ12_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ13_CNT_MON */
+#define AFE_IRQ13_CNT_MON_SFT 0
+#define AFE_IRQ13_CNT_MON_MASK 0xffffff
+#define AFE_IRQ13_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ14_CNT_MON */
+#define AFE_IRQ14_CNT_MON_SFT 0
+#define AFE_IRQ14_CNT_MON_MASK 0xffffff
+#define AFE_IRQ14_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ15_CNT_MON */
+#define AFE_IRQ15_CNT_MON_SFT 0
+#define AFE_IRQ15_CNT_MON_MASK 0xffffff
+#define AFE_IRQ15_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ16_CNT_MON */
+#define AFE_IRQ16_CNT_MON_SFT 0
+#define AFE_IRQ16_CNT_MON_MASK 0xffffff
+#define AFE_IRQ16_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ17_CNT_MON */
+#define AFE_IRQ17_CNT_MON_SFT 0
+#define AFE_IRQ17_CNT_MON_MASK 0xffffff
+#define AFE_IRQ17_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ18_CNT_MON */
+#define AFE_IRQ18_CNT_MON_SFT 0
+#define AFE_IRQ18_CNT_MON_MASK 0xffffff
+#define AFE_IRQ18_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ19_CNT_MON */
+#define AFE_IRQ19_CNT_MON_SFT 0
+#define AFE_IRQ19_CNT_MON_MASK 0xffffff
+#define AFE_IRQ19_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ20_CNT_MON */
+#define AFE_IRQ20_CNT_MON_SFT 0
+#define AFE_IRQ20_CNT_MON_MASK 0xffffff
+#define AFE_IRQ20_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ21_CNT_MON */
+#define AFE_IRQ21_CNT_MON_SFT 0
+#define AFE_IRQ21_CNT_MON_MASK 0xffffff
+#define AFE_IRQ21_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ22_CNT_MON */
+#define AFE_IRQ22_CNT_MON_SFT 0
+#define AFE_IRQ22_CNT_MON_MASK 0xffffff
+#define AFE_IRQ22_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ23_CNT_MON */
+#define AFE_IRQ23_CNT_MON_SFT 0
+#define AFE_IRQ23_CNT_MON_MASK 0xffffff
+#define AFE_IRQ23_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ24_CNT_MON */
+#define AFE_IRQ24_CNT_MON_SFT 0
+#define AFE_IRQ24_CNT_MON_MASK 0xffffff
+#define AFE_IRQ24_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ25_CNT_MON */
+#define AFE_IRQ25_CNT_MON_SFT 0
+#define AFE_IRQ25_CNT_MON_MASK 0xffffff
+#define AFE_IRQ25_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_IRQ26_CNT_MON */
+#define AFE_IRQ26_CNT_MON_SFT 0
+#define AFE_IRQ26_CNT_MON_MASK 0xffffff
+#define AFE_IRQ26_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_CUSTOM_IRQ0_CNT_MON */
+#define AFE_CUSTOM_IRQ0_CNT_MON_SFT 0
+#define AFE_CUSTOM_IRQ0_CNT_MON_MASK 0xffffff
+#define AFE_CUSTOM_IRQ0_CNT_MON_MASK_SFT (0xffffff << 0)
+
+/* AFE_CUSTOM_IRQ0_MCU_CFG1 */
+#define AFE_CUSTOM_IRQ0_CLR_CFG_SFT 31
+#define AFE_CUSTOM_IRQ0_CLR_CFG_MASK 0x1
+#define AFE_CUSTOM_IRQ0_CLR_CFG_MASK_SFT (0x1 << 31)
+#define AFE_CUSTOM_IRQ0_MISS_FLAG_CLR_CFG_SFT 30
+#define AFE_CUSTOM_IRQ0_MISS_FLAG_CLR_CFG_MASK 0x1
+#define AFE_CUSTOM_IRQ0_MISS_FLAG_CLR_CFG_MASK_SFT (0x1 << 30)
+#define AFE_CUSTOM_IRQ0_MCU_CNT_SFT 0
+#define AFE_CUSTOM_IRQ0_MCU_CNT_MASK 0xffffff
+#define AFE_CUSTOM_IRQ0_MCU_CNT_MASK_SFT (0xffffff << 0)
+
+/* AFE_GAIN0_CON1_R */
+/* AFE_GAIN1_CON1_R */
+/* AFE_GAIN2_CON1_R */
+/* AFE_GAIN3_CON1_R */
+#define GAIN_TARGET_R_SFT 0
+#define GAIN_TARGET_R_MASK 0xffffffff
+#define GAIN_TARGET_R_MASK_SFT (0xffffffff << 0)
+
+/* AFE_GAIN0_CON1_L */
+/* AFE_GAIN1_CON1_L */
+/* AFE_GAIN2_CON1_L */
+/* AFE_GAIN3_CON1_L */
+#define GAIN_TARGET_L_SFT 0
+#define GAIN_TARGET_L_MASK 0xffffffff
+#define GAIN_TARGET_L_MASK_SFT (0xffffffff << 0)
+
+/* AFE_GAIN0_CON2 */
+#define GAIN0_DOWN_STEP_SFT 0
+#define GAIN0_DOWN_STEP_MASK 0x3fffff
+#define GAIN0_DOWN_STEP_MASK_SFT (0x3fffff << 0)
+
+/* AFE_GAIN0_CON3 */
+#define GAIN0_UP_STEP_SFT 0
+#define GAIN0_UP_STEP_MASK 0x3fffff
+#define GAIN0_UP_STEP_MASK_SFT (0x3fffff << 0)
+
+/* AFE_GAIN0_CUR_R */
+/* AFE_GAIN1_CUR_R */
+/* AFE_GAIN2_CUR_R */
+/* AFE_GAIN3_CUR_R */
+#define AFE_GAIN_CUR_R_SFT 0
+#define AFE_GAIN_CUR_R_MASK 0xffffffff
+#define AFE_GAIN_CUR_R_MASK_SFT (0xffffffff << 0)
+
+/* AFE_GAIN0_CUR_L */
+/* AFE_GAIN1_CUR_L */
+/* AFE_GAIN2_CUR_L */
+/* AFE_GAIN3_CUR_L */
+#define AFE_GAIN_CUR_L_SFT 0
+#define AFE_GAIN_CUR_L_MASK 0xffffffff
+#define AFE_GAIN_CUR_L_MASK_SFT (0xffffffff << 0)
+
+/* AFE_GAIN0_CON0 */
+/* AFE_GAIN1_CON0 */
+/* AFE_GAIN2_CON0 */
+/* AFE_GAIN3_CON0 */
+#define GAIN_TARGET_SYNC_ON_SFT 24
+#define GAIN_TARGET_SYNC_ON_MASK 0x1
+#define GAIN_TARGET_SYNC_ON_MASK_SFT (0x1 << 24)
+#define GAIN_TIMEOUT_SFT 18
+#define GAIN_TIMEOUT_MASK 0x3f
+#define GAIN_TIMEOUT_MASK_SFT (0x3f << 18)
+#define GAIN_TRIG_SFT 17
+#define GAIN_TRIG_MASK 0x1
+#define GAIN_TRIG_MASK_SFT (0x1 << 17)
+#define GAIN_ON_SFT 16
+#define GAIN_ON_MASK 0x1
+#define GAIN_ON_MASK_SFT (0x1 << 16)
+#define GAIN_SAMPLE_PER_STEP_SFT 8
+#define GAIN_SAMPLE_PER_STEP_MASK 0xff
+#define GAIN_SAMPLE_PER_STEP_MASK_SFT (0xff << 8)
+#define GAIN_SEL_DOMAIN_SFT 5
+#define GAIN_SEL_DOMAIN_MASK 0x7
+#define GAIN_SEL_DOMAIN_MASK_SFT (0x7 << 5)
+#define GAIN_SEL_FS_SFT 0
+#define GAIN_SEL_FS_MASK 0x1f
+#define GAIN_SEL_FS_MASK_SFT (0x1f << 0)
+
+/* AFE_GAIN1_CON2 */
+#define GAIN1_DOWN_STEP_SFT 0
+#define GAIN1_DOWN_STEP_MASK 0x3fffff
+#define GAIN1_DOWN_STEP_MASK_SFT (0x3fffff << 0)
+
+/* AFE_GAIN1_CON3 */
+#define GAIN1_UP_STEP_SFT 0
+#define GAIN1_UP_STEP_MASK 0x3fffff
+#define GAIN1_UP_STEP_MASK_SFT (0x3fffff << 0)
+
+/* AFE_GAIN2_CON2 */
+#define GAIN2_DOWN_STEP_SFT 0
+#define GAIN2_DOWN_STEP_MASK 0x3fffff
+#define GAIN2_DOWN_STEP_MASK_SFT (0x3fffff << 0)
+
+/* AFE_GAIN2_CON3 */
+#define GAIN2_UP_STEP_SFT 0
+#define GAIN2_UP_STEP_MASK 0x3fffff
+#define GAIN2_UP_STEP_MASK_SFT (0x3fffff << 0)
+
+/* AFE_GAIN3_CON2 */
+#define GAIN3_DOWN_STEP_SFT 0
+#define GAIN3_DOWN_STEP_MASK 0x3fffff
+#define GAIN3_DOWN_STEP_MASK_SFT (0x3fffff << 0)
+
+/* AFE_GAIN3_CON3 */
+#define GAIN3_UP_STEP_SFT 0
+#define GAIN3_UP_STEP_MASK 0x3fffff
+#define GAIN3_UP_STEP_MASK_SFT (0x3fffff << 0)
+
+/* AFE_STF_CON0 */
+#define SLT_CNT_FLAG_RESET_SFT 28
+#define SLT_CNT_FLAG_RESET_MASK 0x1
+#define SLT_CNT_FLAG_RESET_MASK_SFT (0x1 << 28)
+#define SLT_CNT_THD_SFT 16
+#define SLT_CNT_THD_MASK 0xfff
+#define SLT_CNT_THD_MASK_SFT (0xfff << 16)
+#define SIDE_TONE_HALF_TAP_NUM_SFT 4
+#define SIDE_TONE_HALF_TAP_NUM_MASK 0x7f
+#define SIDE_TONE_HALF_TAP_NUM_MASK_SFT (0x7f << 4)
+#define SIDE_TONE_ODD_MODE_SFT 1
+#define SIDE_TONE_ODD_MODE_MASK 0x1
+#define SIDE_TONE_ODD_MODE_MASK_SFT (0x1 << 1)
+#define SIDE_TONE_ON_SFT 0
+#define SIDE_TONE_ON_MASK 0x1
+#define SIDE_TONE_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_STF_CON1 */
+#define SIDE_TONE_IN_EN_SEL_DOMAIN_SFT 5
+#define SIDE_TONE_IN_EN_SEL_DOMAIN_MASK 0x7
+#define SIDE_TONE_IN_EN_SEL_DOMAIN_MASK_SFT (0x7 << 5)
+#define SIDE_TONE_IN_EN_SEL_FS_SFT 0
+#define SIDE_TONE_IN_EN_SEL_FS_MASK 0x1f
+#define SIDE_TONE_IN_EN_SEL_FS_MASK_SFT (0x1f << 0)
+
+/* AFE_STF_COEFF */
+#define SIDE_TONE_COEFFICIENT_R_W_SEL_SFT 24
+#define SIDE_TONE_COEFFICIENT_R_W_SEL_MASK 0x1
+#define SIDE_TONE_COEFFICIENT_R_W_SEL_MASK_SFT (0x1 << 24)
+#define SIDE_TONE_COEFFICIENT_ADDR_SFT 16
+#define SIDE_TONE_COEFFICIENT_ADDR_MASK 0x1f
+#define SIDE_TONE_COEFFICIENT_ADDR_MASK_SFT (0x1f << 16)
+#define SIDE_TONE_COEFFICIENT_SFT 0
+#define SIDE_TONE_COEFFICIENT_MASK 0xffff
+#define SIDE_TONE_COEFFICIENT_MASK_SFT (0xffff << 0)
+
+/* AFE_STF_GAIN */
+#define SIDE_TONE_POSITIVE_GAIN_SFT 16
+#define SIDE_TONE_POSITIVE_GAIN_MASK 0x7
+#define SIDE_TONE_POSITIVE_GAIN_MASK_SFT (0x7 << 16)
+#define SIDE_TONE_GAIN_SFT 0
+#define SIDE_TONE_GAIN_MASK 0xffff
+#define SIDE_TONE_GAIN_MASK_SFT (0xffff << 0)
+
+/* AFE_STF_MON */
+#define SIDE_TONE_R_RDY_SFT 30
+#define SIDE_TONE_R_RDY_MASK 0x1
+#define SIDE_TONE_R_RDY_MASK_SFT (0x1 << 30)
+#define SIDE_TONE_W_RDY_SFT 29
+#define SIDE_TONE_W_RDY_MASK 0x1
+#define SIDE_TONE_W_RDY_MASK_SFT (0x1 << 29)
+#define SLT_CNT_FLAG_SFT 28
+#define SLT_CNT_FLAG_MASK 0x1
+#define SLT_CNT_FLAG_MASK_SFT (0x1 << 28)
+#define SLT_CNT_SFT 16
+#define SLT_CNT_MASK 0xfff
+#define SLT_CNT_MASK_SFT (0xfff << 16)
+#define SIDE_TONE_COEFF_SFT 0
+#define SIDE_TONE_COEFF_MASK 0xffff
+#define SIDE_TONE_COEFF_MASK_SFT (0xffff << 0)
+
+/* AFE_STF_IP_VERSION */
+#define SIDE_TONE_IP_VERSION_SFT 0
+#define SIDE_TONE_IP_VERSION_MASK 0xffffffff
+#define SIDE_TONE_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CM_REG */
+#define AFE_CM_UPDATE_CNT_SFT 16
+#define AFE_CM_UPDATE_CNT_MASK 0x7fff
+#define AFE_CM_UPDATE_CNT_MASK_SFT (0x7fff << 16)
+#define AFE_CM_1X_EN_SEL_FS_SFT 8
+#define AFE_CM_1X_EN_SEL_FS_MASK 0x1f
+#define AFE_CM_1X_EN_SEL_FS_MASK_SFT (0x1f << 8)
+#define AFE_CM_CH_NUM_SFT 2
+#define AFE_CM_CH_NUM_MASK 0x1f
+#define AFE_CM_CH_NUM_MASK_SFT (0x1f << 2)
+#define AFE_CM_BYTE_SWAP_SFT 1
+#define AFE_CM_BYTE_SWAP_MASK 0x1
+#define AFE_CM_BYTE_SWAP_MASK_SFT (0x1 << 1)
+#define AFE_CM_BYPASS_MODE_SFT 31
+#define AFE_CM_BYPASS_MODE_MASK 0x1
+#define AFE_CM_BYPASS_MODE_MASK_SFT (0x1 << 31)
+
+/* AFE_CM0_CON0 */
+#define AFE_CM0_BYPASS_MODE_SFT 31
+#define AFE_CM0_BYPASS_MODE_MASK 0x1
+#define AFE_CM0_BYPASS_MODE_MASK_SFT (0x1 << 31)
+#define AFE_CM0_UPDATE_CNT_SFT 16
+#define AFE_CM0_UPDATE_CNT_MASK 0x7fff
+#define AFE_CM0_UPDATE_CNT_MASK_SFT (0x7fff << 16)
+#define AFE_CM0_1X_EN_SEL_DOMAIN_SFT 13
+#define AFE_CM0_1X_EN_SEL_DOMAIN_MASK 0x7
+#define AFE_CM0_1X_EN_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define AFE_CM0_1X_EN_SEL_FS_SFT 8
+#define AFE_CM0_1X_EN_SEL_FS_MASK 0x1f
+#define AFE_CM0_1X_EN_SEL_FS_MASK_SFT (0x1f << 8)
+#define AFE_CM0_OUTPUT_MUX_SFT 7
+#define AFE_CM0_OUTPUT_MUX_MASK 0x1
+#define AFE_CM0_OUTPUT_MUX_MASK_SFT (0x1 << 7)
+#define AFE_CM0_CH_NUM_SFT 2
+#define AFE_CM0_CH_NUM_MASK 0x1f
+#define AFE_CM0_CH_NUM_MASK_SFT (0x1f << 2)
+#define AFE_CM0_BYTE_SWAP_SFT 1
+#define AFE_CM0_BYTE_SWAP_MASK 0x1
+#define AFE_CM0_BYTE_SWAP_MASK_SFT (0x1 << 1)
+#define AFE_CM0_ON_SFT 0
+#define AFE_CM0_ON_MASK 0x1
+#define AFE_CM0_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_CM0_MON */
+#define AFE_CM0_BYPASS_MODE_MON_SFT 31
+#define AFE_CM0_BYPASS_MODE_MON_MASK 0x1
+#define AFE_CM0_BYPASS_MODE_MON_MASK_SFT (0x1 << 31)
+#define AFE_CM0_OUTPUT_CNT_MON_SFT 16
+#define AFE_CM0_OUTPUT_CNT_MON_MASK 0x7fff
+#define AFE_CM0_OUTPUT_CNT_MON_MASK_SFT (0x7fff << 16)
+#define AFE_CM0_CUR_CHSET_MON_SFT 5
+#define AFE_CM0_CUR_CHSET_MON_MASK 0xf
+#define AFE_CM0_CUR_CHSET_MON_MASK_SFT (0xf << 5)
+#define AFE_CM0_ODD_FLAG_MON_SFT 4
+#define AFE_CM0_ODD_FLAG_MON_MASK 0x1
+#define AFE_CM0_ODD_FLAG_MON_MASK_SFT (0x1 << 4)
+#define AFE_CM0_BYTE_SWAP_MON_SFT 1
+#define AFE_CM0_BYTE_SWAP_MON_MASK 0x1
+#define AFE_CM0_BYTE_SWAP_MON_MASK_SFT (0x1 << 1)
+#define AFE_CM0_ON_MON_SFT 0
+#define AFE_CM0_ON_MON_MASK 0x1
+#define AFE_CM0_ON_MON_MASK_SFT (0x1 << 0)
+
+/* AFE_CM0_IP_VERSION */
+#define AFE_CM0_IP_VERSION_SFT 0
+#define AFE_CM0_IP_VERSION_MASK 0xffffffff
+#define AFE_CM0_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CM1_CON0 */
+#define AFE_CM1_BYPASS_MODE_SFT 31
+#define AFE_CM1_BYPASS_MODE_MASK 0x1
+#define AFE_CM1_BYPASS_MODE_MASK_SFT (0x1 << 31)
+#define AFE_CM1_UPDATE_CNT_SFT 16
+#define AFE_CM1_UPDATE_CNT_MASK 0x7fff
+#define AFE_CM1_UPDATE_CNT_MASK_SFT (0x7fff << 16)
+#define AFE_CM1_1X_EN_SEL_DOMAIN_SFT 13
+#define AFE_CM1_1X_EN_SEL_DOMAIN_MASK 0x7
+#define AFE_CM1_1X_EN_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define AFE_CM1_1X_EN_SEL_FS_SFT 8
+#define AFE_CM1_1X_EN_SEL_FS_MASK 0x1f
+#define AFE_CM1_1X_EN_SEL_FS_MASK_SFT (0x1f << 8)
+#define AFE_CM1_OUTPUT_MUX_SFT 7
+#define AFE_CM1_OUTPUT_MUX_MASK 0x1
+#define AFE_CM1_OUTPUT_MUX_MASK_SFT (0x1 << 7)
+#define AFE_CM1_CH_NUM_SFT 2
+#define AFE_CM1_CH_NUM_MASK 0x1f
+#define AFE_CM1_CH_NUM_MASK_SFT (0x1f << 2)
+#define AFE_CM1_BYTE_SWAP_SFT 1
+#define AFE_CM1_BYTE_SWAP_MASK 0x1
+#define AFE_CM1_BYTE_SWAP_MASK_SFT (0x1 << 1)
+#define AFE_CM1_ON_SFT 0
+#define AFE_CM1_ON_MASK 0x1
+#define AFE_CM1_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_CM1_MON */
+#define AFE_CM1_BYPASS_MODE_MON_SFT 31
+#define AFE_CM1_BYPASS_MODE_MON_MASK 0x1
+#define AFE_CM1_BYPASS_MODE_MON_MASK_SFT (0x1 << 31)
+#define AFE_CM1_OUTPUT_CNT_MON_SFT 16
+#define AFE_CM1_OUTPUT_CNT_MON_MASK 0x7fff
+#define AFE_CM1_OUTPUT_CNT_MON_MASK_SFT (0x7fff << 16)
+#define AFE_CM1_CUR_CHSET_MON_SFT 5
+#define AFE_CM1_CUR_CHSET_MON_MASK 0xf
+#define AFE_CM1_CUR_CHSET_MON_MASK_SFT (0xf << 5)
+#define AFE_CM1_ODD_FLAG_MON_SFT 4
+#define AFE_CM1_ODD_FLAG_MON_MASK 0x1
+#define AFE_CM1_ODD_FLAG_MON_MASK_SFT (0x1 << 4)
+#define AFE_CM1_BYTE_SWAP_MON_SFT 1
+#define AFE_CM1_BYTE_SWAP_MON_MASK 0x1
+#define AFE_CM1_BYTE_SWAP_MON_MASK_SFT (0x1 << 1)
+#define AFE_CM1_ON_MON_SFT 0
+#define AFE_CM1_ON_MON_MASK 0x1
+#define AFE_CM1_ON_MON_MASK_SFT (0x1 << 0)
+
+/* AFE_CM1_IP_VERSION */
+#define AFE_CM1_IP_VERSION_SFT 0
+#define AFE_CM1_IP_VERSION_MASK 0xffffffff
+#define AFE_CM1_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CM2_CON0 */
+#define AFE_CM2_BYPASS_MODE_SFT 31
+#define AFE_CM2_BYPASS_MODE_MASK 0x1
+#define AFE_CM2_BYPASS_MODE_MASK_SFT (0x1 << 31)
+#define AFE_CM2_UPDATE_CNT_SFT 16
+#define AFE_CM2_UPDATE_CNT_MASK 0x7fff
+#define AFE_CM2_UPDATE_CNT_MASK_SFT (0x7fff << 16)
+#define AFE_CM2_1X_EN_SEL_DOMAIN_SFT 13
+#define AFE_CM2_1X_EN_SEL_DOMAIN_MASK 0x7
+#define AFE_CM2_1X_EN_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define AFE_CM2_1X_EN_SEL_FS_SFT 8
+#define AFE_CM2_1X_EN_SEL_FS_MASK 0x1f
+#define AFE_CM2_1X_EN_SEL_FS_MASK_SFT (0x1f << 8)
+#define AFE_CM2_OUTPUT_MUX_SFT 7
+#define AFE_CM2_OUTPUT_MUX_MASK 0x1
+#define AFE_CM2_OUTPUT_MUX_MASK_SFT (0x1 << 7)
+#define AFE_CM2_CH_NUM_SFT 2
+#define AFE_CM2_CH_NUM_MASK 0x1f
+#define AFE_CM2_CH_NUM_MASK_SFT (0x1f << 2)
+#define AFE_CM2_BYTE_SWAP_SFT 1
+#define AFE_CM2_BYTE_SWAP_MASK 0x1
+#define AFE_CM2_BYTE_SWAP_MASK_SFT (0x1 << 1)
+#define AFE_CM2_ON_SFT 0
+#define AFE_CM2_ON_MASK 0x1
+#define AFE_CM2_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_CM2_MON */
+#define AFE_CM2_BYPASS_MODE_MON_SFT 31
+#define AFE_CM2_BYPASS_MODE_MON_MASK 0x1
+#define AFE_CM2_BYPASS_MODE_MON_MASK_SFT (0x1 << 31)
+#define AFE_CM2_OUTPUT_CNT_MON_SFT 16
+#define AFE_CM2_OUTPUT_CNT_MON_MASK 0x7fff
+#define AFE_CM2_OUTPUT_CNT_MON_MASK_SFT (0x7fff << 16)
+#define AFE_CM2_CUR_CHSET_MON_SFT 5
+#define AFE_CM2_CUR_CHSET_MON_MASK 0xf
+#define AFE_CM2_CUR_CHSET_MON_MASK_SFT (0xf << 5)
+#define AFE_CM2_ODD_FLAG_MON_SFT 4
+#define AFE_CM2_ODD_FLAG_MON_MASK 0x1
+#define AFE_CM2_ODD_FLAG_MON_MASK_SFT (0x1 << 4)
+#define AFE_CM2_BYTE_SWAP_MON_SFT 1
+#define AFE_CM2_BYTE_SWAP_MON_MASK 0x1
+#define AFE_CM2_BYTE_SWAP_MON_MASK_SFT (0x1 << 1)
+#define AFE_CM2_ON_MON_SFT 0
+#define AFE_CM2_ON_MON_MASK 0x1
+#define AFE_CM2_ON_MON_MASK_SFT (0x1 << 0)
+
+/* AFE_CM2_IP_VERSION */
+#define AFE_CM2_IP_VERSION_SFT 0
+#define AFE_CM2_IP_VERSION_MASK 0xffffffff
+#define AFE_CM2_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_SRC_CON0 */
+#define ULCF_CFG_EN_CTL_SFT 31
+#define ULCF_CFG_EN_CTL_MASK 0x1
+#define ULCF_CFG_EN_CTL_MASK_SFT (0x1 << 31)
+#define UL_DMIC_PHASE_SEL_CH1_SFT 27
+#define UL_DMIC_PHASE_SEL_CH1_MASK 0x7
+#define UL_DMIC_PHASE_SEL_CH1_MASK_SFT (0x7 << 27)
+#define UL_DMIC_PHASE_SEL_CH2_SFT 24
+#define UL_DMIC_PHASE_SEL_CH2_MASK 0x7
+#define UL_DMIC_PHASE_SEL_CH2_MASK_SFT (0x7 << 24)
+#define UL_DMIC_TWO_WIRE_CTL_SFT 23
+#define UL_DMIC_TWO_WIRE_CTL_MASK 0x1
+#define UL_DMIC_TWO_WIRE_CTL_MASK_SFT (0x1 << 23)
+#define UL_MODE_3P25M_CH2_CTL_SFT 22
+#define UL_MODE_3P25M_CH2_CTL_MASK 0x1
+#define UL_MODE_3P25M_CH2_CTL_MASK_SFT (0x1 << 22)
+#define UL_MODE_3P25M_CH1_CTL_SFT 21
+#define UL_MODE_3P25M_CH1_CTL_MASK 0x1
+#define UL_MODE_3P25M_CH1_CTL_MASK_SFT (0x1 << 21)
+#define UL_VOICE_MODE_CH1_CH2_CTL_SFT 17
+#define UL_VOICE_MODE_CH1_CH2_CTL_MASK 0x7
+#define UL_VOICE_MODE_CH1_CH2_CTL_MASK_SFT (0x7 << 17)
+#define UL_AP_DMIC_ON_SFT 16
+#define UL_AP_DMIC_ON_MASK 0x1
+#define UL_AP_DMIC_ON_MASK_SFT (0x1 << 16)
+#define DMIC_LOW_POWER_MODE_CTL_SFT 14
+#define DMIC_LOW_POWER_MODE_CTL_MASK 0x3
+#define DMIC_LOW_POWER_MODE_CTL_MASK_SFT (0x3 << 14)
+#define UL_DISABLE_HW_CG_CTL_SFT 12
+#define UL_DISABLE_HW_CG_CTL_MASK 0x1
+#define UL_DISABLE_HW_CG_CTL_MASK_SFT (0x1 << 12)
+#define AMIC_26M_SEL_CTL_SFT 11
+#define AMIC_26M_SEL_CTL_MASK 0x1
+#define AMIC_26M_SEL_CTL_MASK_SFT (0x1 << 11)
+#define UL_IIR_ON_TMP_CTL_SFT 10
+#define UL_IIR_ON_TMP_CTL_MASK 0x1
+#define UL_IIR_ON_TMP_CTL_MASK_SFT (0x1 << 10)
+#define UL_IIRMODE_CTL_SFT 7
+#define UL_IIRMODE_CTL_MASK 0x7
+#define UL_IIRMODE_CTL_MASK_SFT (0x7 << 7)
+#define DIGMIC_4P33M_SEL_SFT 6
+#define DIGMIC_4P33M_SEL_MASK 0x1
+#define DIGMIC_4P33M_SEL_MASK_SFT (0x1 << 6)
+#define DIGMIC_3P25M_1P625M_SEL_CTL_SFT 5
+#define DIGMIC_3P25M_1P625M_SEL_CTL_MASK 0x1
+#define DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT (0x1 << 5)
+#define AMIC_6P5M_SEL_CTL_SFT 4
+#define AMIC_6P5M_SEL_CTL_MASK 0x1
+#define AMIC_6P5M_SEL_CTL_MASK_SFT (0x1 << 4)
+#define AMIC_1P625M_SEL_CTL_SFT 3
+#define AMIC_1P625M_SEL_CTL_MASK 0x1
+#define AMIC_1P625M_SEL_CTL_MASK_SFT (0x1 << 3)
+#define UL_LOOP_BACK_MODE_CTL_SFT 2
+#define UL_LOOP_BACK_MODE_CTL_MASK 0x1
+#define UL_LOOP_BACK_MODE_CTL_MASK_SFT (0x1 << 2)
+#define UL_SDM_3_LEVEL_CTL_SFT 1
+#define UL_SDM_3_LEVEL_CTL_MASK 0x1
+#define UL_SDM_3_LEVEL_CTL_MASK_SFT (0x1 << 1)
+#define UL_SRC_ON_TMP_CTL_SFT 0
+#define UL_SRC_ON_TMP_CTL_MASK 0x1
+#define UL_SRC_ON_TMP_CTL_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA_UL0_SRC_CON1 */
+#define ADDA_UL_GAIN_VALUE_SFT 16
+#define ADDA_UL_GAIN_VALUE_MASK 0xffff
+#define ADDA_UL_GAIN_VALUE_MASK_SFT (0xffff << 16)
+#define ADDA_UL_POSTIVEGAIN_SFT 12
+#define ADDA_UL_POSTIVEGAIN_MASK 0x7
+#define ADDA_UL_POSTIVEGAIN_MASK_SFT (0x7 << 12)
+#define ADDA_UL_ODDTAP_MODE_SFT 11
+#define ADDA_UL_ODDTAP_MODE_MASK 0x1
+#define ADDA_UL_ODDTAP_MODE_MASK_SFT (0x1 << 11)
+#define ADDA_UL_HALF_TAP_NUM_SFT 5
+#define ADDA_UL_HALF_TAP_NUM_MASK 0x3f
+#define ADDA_UL_HALF_TAP_NUM_MASK_SFT (0x3f << 5)
+#define FIFO_SOFT_RST_SFT 4
+#define FIFO_SOFT_RST_MASK 0x1
+#define FIFO_SOFT_RST_MASK_SFT (0x1 << 4)
+#define FIFO_SOFT_RST_EN_SFT 3
+#define FIFO_SOFT_RST_EN_MASK 0x1
+#define FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 3)
+#define LR_SWAP_SFT 2
+#define LR_SWAP_MASK 0x1
+#define LR_SWAP_MASK_SFT (0x1 << 2)
+#define GAIN_MODE_SFT 0
+#define GAIN_MODE_MASK 0x3
+#define GAIN_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_ADDA_UL0_SRC_CON2 */
+#define C_DAC_EN_CTL_SFT 27
+#define C_DAC_EN_CTL_MASK 0x1
+#define C_DAC_EN_CTL_MASK_SFT (0x1 << 27)
+#define C_MUTE_SW_CTL_SFT 26
+#define C_MUTE_SW_CTL_MASK 0x1
+#define C_MUTE_SW_CTL_MASK_SFT (0x1 << 26)
+#define C_AMP_DIV_CH2_CTL_SFT 21
+#define C_AMP_DIV_CH2_CTL_MASK 0x7
+#define C_AMP_DIV_CH2_CTL_MASK_SFT (0x7 << 21)
+#define C_FREQ_DIV_CH2_CTL_SFT 16
+#define C_FREQ_DIV_CH2_CTL_MASK 0x1f
+#define C_FREQ_DIV_CH2_CTL_MASK_SFT (0x1f << 16)
+#define C_SINE_MODE_CH2_CTL_SFT 12
+#define C_SINE_MODE_CH2_CTL_MASK 0xf
+#define C_SINE_MODE_CH2_CTL_MASK_SFT (0xf << 12)
+#define C_AMP_DIV_CH1_CTL_SFT 9
+#define C_AMP_DIV_CH1_CTL_MASK 0x7
+#define C_AMP_DIV_CH1_CTL_MASK_SFT (0x7 << 9)
+#define C_FREQ_DIV_CH1_CTL_SFT 4
+#define C_FREQ_DIV_CH1_CTL_MASK 0x1f
+#define C_FREQ_DIV_CH1_CTL_MASK_SFT (0x1f << 4)
+#define C_SINE_MODE_CH1_CTL_SFT 0
+#define C_SINE_MODE_CH1_CTL_MASK 0xf
+#define C_SINE_MODE_CH1_CTL_MASK_SFT (0xf << 0)
+
+/* AFE_ADDA_UL0_SRC_DEBUG */
+#define UL_SLT_CNT_FLAG_RESET_CTL_SFT 16
+#define UL_SLT_CNT_FLAG_RESET_CTL_MASK 0x1
+#define UL_SLT_CNT_FLAG_RESET_CTL_MASK_SFT (0x1 << 16)
+#define FIFO_DIGMIC_TESTIN_SFT 12
+#define FIFO_DIGMIC_TESTIN_MASK 0x3
+#define FIFO_DIGMIC_TESTIN_MASK_SFT (0x3 << 12)
+#define FIFO_DIGMIC_WDATA_TESTEN_SFT 11
+#define FIFO_DIGMIC_WDATA_TESTEN_MASK 0x1
+#define FIFO_DIGMIC_WDATA_TESTEN_MASK_SFT (0x1 << 11)
+#define SLT_CNT_THD_CTL_SFT 0
+#define SLT_CNT_THD_CTL_MASK 0x7ff
+#define SLT_CNT_THD_CTL_MASK_SFT (0x7ff << 0)
+
+/* AFE_ADDA_UL0_SRC_DEBUG_MON0 */
+#define SLT_CNT_FLAG_CTL_SFT 16
+#define SLT_CNT_FLAG_CTL_MASK 0x1
+#define SLT_CNT_FLAG_CTL_MASK_SFT (0x1 << 16)
+#define SLT_COUNTER_CTL_SFT 0
+#define SLT_COUNTER_CTL_MASK 0x7ff
+#define SLT_COUNTER_CTL_MASK_SFT (0x7ff << 0)
+
+/* AFE_ADDA_UL0_IIR_COEF_02_01 */
+#define ADDA_IIR_COEF_02_01_SFT 0
+#define ADDA_IIR_COEF_02_01_MASK 0xffffffff
+#define ADDA_IIR_COEF_02_01_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_IIR_COEF_04_03 */
+#define ADDA_IIR_COEF_04_03_SFT 0
+#define ADDA_IIR_COEF_04_03_MASK 0xffffffff
+#define ADDA_IIR_COEF_04_03_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_IIR_COEF_06_05 */
+#define ADDA_IIR_COEF_06_05_SFT 0
+#define ADDA_IIR_COEF_06_05_MASK 0xffffffff
+#define ADDA_IIR_COEF_06_05_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_IIR_COEF_08_07 */
+#define ADDA_IIR_COEF_08_07_SFT 0
+#define ADDA_IIR_COEF_08_07_MASK 0xffffffff
+#define ADDA_IIR_COEF_08_07_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_IIR_COEF_10_09 */
+#define ADDA_IIR_COEF_10_09_SFT 0
+#define ADDA_IIR_COEF_10_09_MASK 0xffffffff
+#define ADDA_IIR_COEF_10_09_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_02_01 */
+#define ADDA_ULCF_CFG_02_01_SFT 0
+#define ADDA_ULCF_CFG_02_01_MASK 0xffffffff
+#define ADDA_ULCF_CFG_02_01_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_04_03 */
+#define ADDA_ULCF_CFG_04_03_SFT 0
+#define ADDA_ULCF_CFG_04_03_MASK 0xffffffff
+#define ADDA_ULCF_CFG_04_03_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_06_05 */
+#define ADDA_ULCF_CFG_06_05_SFT 0
+#define ADDA_ULCF_CFG_06_05_MASK 0xffffffff
+#define ADDA_ULCF_CFG_06_05_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_08_07 */
+#define ADDA_ULCF_CFG_08_07_SFT 0
+#define ADDA_ULCF_CFG_08_07_MASK 0xffffffff
+#define ADDA_ULCF_CFG_08_07_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_10_09 */
+#define ADDA_ULCF_CFG_10_09_SFT 0
+#define ADDA_ULCF_CFG_10_09_MASK 0xffffffff
+#define ADDA_ULCF_CFG_10_09_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_12_11 */
+#define ADDA_ULCF_CFG_12_11_SFT 0
+#define ADDA_ULCF_CFG_12_11_MASK 0xffffffff
+#define ADDA_ULCF_CFG_12_11_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_14_13 */
+#define ADDA_ULCF_CFG_14_13_SFT 0
+#define ADDA_ULCF_CFG_14_13_MASK 0xffffffff
+#define ADDA_ULCF_CFG_14_13_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_16_15 */
+#define ADDA_ULCF_CFG_16_15_SFT 0
+#define ADDA_ULCF_CFG_16_15_MASK 0xffffffff
+#define ADDA_ULCF_CFG_16_15_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_18_17 */
+#define ADDA_ULCF_CFG_18_17_SFT 0
+#define ADDA_ULCF_CFG_18_17_MASK 0xffffffff
+#define ADDA_ULCF_CFG_18_17_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_20_19 */
+#define ADDA_ULCF_CFG_20_19_SFT 0
+#define ADDA_ULCF_CFG_20_19_MASK 0xffffffff
+#define ADDA_ULCF_CFG_20_19_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_22_21 */
+#define ADDA_ULCF_CFG_22_21_SFT 0
+#define ADDA_ULCF_CFG_22_21_MASK 0xffffffff
+#define ADDA_ULCF_CFG_22_21_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_24_23 */
+#define ADDA_ULCF_CFG_24_23_SFT 0
+#define ADDA_ULCF_CFG_24_23_MASK 0xffffffff
+#define ADDA_ULCF_CFG_24_23_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_26_25 */
+#define ADDA_ULCF_CFG_26_25_SFT 0
+#define ADDA_ULCF_CFG_26_25_MASK 0xffffffff
+#define ADDA_ULCF_CFG_26_25_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_28_27 */
+#define ADDA_ULCF_CFG_28_27_SFT 0
+#define ADDA_ULCF_CFG_28_27_MASK 0xffffffff
+#define ADDA_ULCF_CFG_28_27_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_30_29 */
+#define ADDA_ULCF_CFG_30_29_SFT 0
+#define ADDA_ULCF_CFG_30_29_MASK 0xffffffff
+#define ADDA_ULCF_CFG_30_29_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_ULCF_CFG_32_31 */
+#define ADDA_ULCF_CFG_32_31_SFT 0
+#define ADDA_ULCF_CFG_32_31_MASK 0xffffffff
+#define ADDA_ULCF_CFG_32_31_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_IP_VERSION */
+#define ADDA_ULCF_IP_VERSION_SFT 0
+#define ADDA_ULCF_IP_VERSION_MASK 0xffffffff
+#define ADDA_ULCF_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_SRC_CON0 */
+#define ULCF_CFG_EN_CTL_SFT 31
+#define ULCF_CFG_EN_CTL_MASK 0x1
+#define ULCF_CFG_EN_CTL_MASK_SFT (0x1 << 31)
+#define UL_DMIC_PHASE_SEL_CH1_SFT 27
+#define UL_DMIC_PHASE_SEL_CH1_MASK 0x7
+#define UL_DMIC_PHASE_SEL_CH1_MASK_SFT (0x7 << 27)
+#define UL_DMIC_PHASE_SEL_CH2_SFT 24
+#define UL_DMIC_PHASE_SEL_CH2_MASK 0x7
+#define UL_DMIC_PHASE_SEL_CH2_MASK_SFT (0x7 << 24)
+#define UL_DMIC_TWO_WIRE_CTL_SFT 23
+#define UL_DMIC_TWO_WIRE_CTL_MASK 0x1
+#define UL_DMIC_TWO_WIRE_CTL_MASK_SFT (0x1 << 23)
+#define UL_MODE_3P25M_CH2_CTL_SFT 22
+#define UL_MODE_3P25M_CH2_CTL_MASK 0x1
+#define UL_MODE_3P25M_CH2_CTL_MASK_SFT (0x1 << 22)
+#define UL_MODE_3P25M_CH1_CTL_SFT 21
+#define UL_MODE_3P25M_CH1_CTL_MASK 0x1
+#define UL_MODE_3P25M_CH1_CTL_MASK_SFT (0x1 << 21)
+#define UL_VOICE_MODE_CH1_CH2_CTL_SFT 17
+#define UL_VOICE_MODE_CH1_CH2_CTL_MASK 0x7
+#define UL_VOICE_MODE_CH1_CH2_CTL_MASK_SFT (0x7 << 17)
+#define UL_AP_DMIC_ON_SFT 16
+#define UL_AP_DMIC_ON_MASK 0x1
+#define UL_AP_DMIC_ON_MASK_SFT (0x1 << 16)
+#define DMIC_LOW_POWER_MODE_CTL_SFT 14
+#define DMIC_LOW_POWER_MODE_CTL_MASK 0x3
+#define DMIC_LOW_POWER_MODE_CTL_MASK_SFT (0x3 << 14)
+#define UL_DISABLE_HW_CG_CTL_SFT 12
+#define UL_DISABLE_HW_CG_CTL_MASK 0x1
+#define UL_DISABLE_HW_CG_CTL_MASK_SFT (0x1 << 12)
+#define AMIC_26M_SEL_CTL_SFT 11
+#define AMIC_26M_SEL_CTL_MASK 0x1
+#define AMIC_26M_SEL_CTL_MASK_SFT (0x1 << 11)
+#define UL_IIR_ON_TMP_CTL_SFT 10
+#define UL_IIR_ON_TMP_CTL_MASK 0x1
+#define UL_IIR_ON_TMP_CTL_MASK_SFT (0x1 << 10)
+#define UL_IIRMODE_CTL_SFT 7
+#define UL_IIRMODE_CTL_MASK 0x7
+#define UL_IIRMODE_CTL_MASK_SFT (0x7 << 7)
+#define DIGMIC_4P33M_SEL_SFT 6
+#define DIGMIC_4P33M_SEL_MASK 0x1
+#define DIGMIC_4P33M_SEL_MASK_SFT (0x1 << 6)
+#define DIGMIC_3P25M_1P625M_SEL_CTL_SFT 5
+#define DIGMIC_3P25M_1P625M_SEL_CTL_MASK 0x1
+#define DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT (0x1 << 5)
+#define AMIC_6P5M_SEL_CTL_SFT 4
+#define AMIC_6P5M_SEL_CTL_MASK 0x1
+#define AMIC_6P5M_SEL_CTL_MASK_SFT (0x1 << 4)
+#define AMIC_1P625M_SEL_CTL_SFT 3
+#define AMIC_1P625M_SEL_CTL_MASK 0x1
+#define AMIC_1P625M_SEL_CTL_MASK_SFT (0x1 << 3)
+#define UL_LOOP_BACK_MODE_CTL_SFT 2
+#define UL_LOOP_BACK_MODE_CTL_MASK 0x1
+#define UL_LOOP_BACK_MODE_CTL_MASK_SFT (0x1 << 2)
+#define UL_SDM_3_LEVEL_CTL_SFT 1
+#define UL_SDM_3_LEVEL_CTL_MASK 0x1
+#define UL_SDM_3_LEVEL_CTL_MASK_SFT (0x1 << 1)
+#define UL_SRC_ON_TMP_CTL_SFT 0
+#define UL_SRC_ON_TMP_CTL_MASK 0x1
+#define UL_SRC_ON_TMP_CTL_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA_UL1_SRC_CON1 */
+#define ADDA_UL_GAIN_VALUE_SFT 16
+#define ADDA_UL_GAIN_VALUE_MASK 0xffff
+#define ADDA_UL_GAIN_VALUE_MASK_SFT (0xffff << 16)
+#define ADDA_UL_POSTIVEGAIN_SFT 12
+#define ADDA_UL_POSTIVEGAIN_MASK 0x7
+#define ADDA_UL_POSTIVEGAIN_MASK_SFT (0x7 << 12)
+#define ADDA_UL_ODDTAP_MODE_SFT 11
+#define ADDA_UL_ODDTAP_MODE_MASK 0x1
+#define ADDA_UL_ODDTAP_MODE_MASK_SFT (0x1 << 11)
+#define ADDA_UL_HALF_TAP_NUM_SFT 5
+#define ADDA_UL_HALF_TAP_NUM_MASK 0x3f
+#define ADDA_UL_HALF_TAP_NUM_MASK_SFT (0x3f << 5)
+#define FIFO_SOFT_RST_SFT 4
+#define FIFO_SOFT_RST_MASK 0x1
+#define FIFO_SOFT_RST_MASK_SFT (0x1 << 4)
+#define FIFO_SOFT_RST_EN_SFT 3
+#define FIFO_SOFT_RST_EN_MASK 0x1
+#define FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 3)
+#define LR_SWAP_SFT 2
+#define LR_SWAP_MASK 0x1
+#define LR_SWAP_MASK_SFT (0x1 << 2)
+#define GAIN_MODE_SFT 0
+#define GAIN_MODE_MASK 0x3
+#define GAIN_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_ADDA_UL1_SRC_CON2 */
+#define C_DAC_EN_CTL_SFT 27
+#define C_DAC_EN_CTL_MASK 0x1
+#define C_DAC_EN_CTL_MASK_SFT (0x1 << 27)
+#define C_MUTE_SW_CTL_SFT 26
+#define C_MUTE_SW_CTL_MASK 0x1
+#define C_MUTE_SW_CTL_MASK_SFT (0x1 << 26)
+#define C_AMP_DIV_CH2_CTL_SFT 21
+#define C_AMP_DIV_CH2_CTL_MASK 0x7
+#define C_AMP_DIV_CH2_CTL_MASK_SFT (0x7 << 21)
+#define C_FREQ_DIV_CH2_CTL_SFT 16
+#define C_FREQ_DIV_CH2_CTL_MASK 0x1f
+#define C_FREQ_DIV_CH2_CTL_MASK_SFT (0x1f << 16)
+#define C_SINE_MODE_CH2_CTL_SFT 12
+#define C_SINE_MODE_CH2_CTL_MASK 0xf
+#define C_SINE_MODE_CH2_CTL_MASK_SFT (0xf << 12)
+#define C_AMP_DIV_CH1_CTL_SFT 9
+#define C_AMP_DIV_CH1_CTL_MASK 0x7
+#define C_AMP_DIV_CH1_CTL_MASK_SFT (0x7 << 9)
+#define C_FREQ_DIV_CH1_CTL_SFT 4
+#define C_FREQ_DIV_CH1_CTL_MASK 0x1f
+#define C_FREQ_DIV_CH1_CTL_MASK_SFT (0x1f << 4)
+#define C_SINE_MODE_CH1_CTL_SFT 0
+#define C_SINE_MODE_CH1_CTL_MASK 0xf
+#define C_SINE_MODE_CH1_CTL_MASK_SFT (0xf << 0)
+
+/* AFE_ADDA_UL1_SRC_DEBUG */
+#define UL_SLT_CNT_FLAG_RESET_CTL_SFT 16
+#define UL_SLT_CNT_FLAG_RESET_CTL_MASK 0x1
+#define UL_SLT_CNT_FLAG_RESET_CTL_MASK_SFT (0x1 << 16)
+#define FIFO_DIGMIC_TESTIN_SFT 12
+#define FIFO_DIGMIC_TESTIN_MASK 0x3
+#define FIFO_DIGMIC_TESTIN_MASK_SFT (0x3 << 12)
+#define FIFO_DIGMIC_WDATA_TESTEN_SFT 11
+#define FIFO_DIGMIC_WDATA_TESTEN_MASK 0x1
+#define FIFO_DIGMIC_WDATA_TESTEN_MASK_SFT (0x1 << 11)
+#define SLT_CNT_THD_CTL_SFT 0
+#define SLT_CNT_THD_CTL_MASK 0x7ff
+#define SLT_CNT_THD_CTL_MASK_SFT (0x7ff << 0)
+
+/* AFE_ADDA_UL1_SRC_DEBUG_MON0 */
+#define SLT_CNT_FLAG_CTL_SFT 16
+#define SLT_CNT_FLAG_CTL_MASK 0x1
+#define SLT_CNT_FLAG_CTL_MASK_SFT (0x1 << 16)
+#define SLT_COUNTER_CTL_SFT 0
+#define SLT_COUNTER_CTL_MASK 0x7ff
+#define SLT_COUNTER_CTL_MASK_SFT (0x7ff << 0)
+
+/* AFE_ADDA_UL1_IIR_COEF_02_01 */
+#define ADDA_IIR_COEF_02_01_SFT 0
+#define ADDA_IIR_COEF_02_01_MASK 0xffffffff
+#define ADDA_IIR_COEF_02_01_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_IIR_COEF_04_03 */
+#define ADDA_IIR_COEF_04_03_SFT 0
+#define ADDA_IIR_COEF_04_03_MASK 0xffffffff
+#define ADDA_IIR_COEF_04_03_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_IIR_COEF_06_05 */
+#define ADDA_IIR_COEF_06_05_SFT 0
+#define ADDA_IIR_COEF_06_05_MASK 0xffffffff
+#define ADDA_IIR_COEF_06_05_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_IIR_COEF_08_07 */
+#define ADDA_IIR_COEF_08_07_SFT 0
+#define ADDA_IIR_COEF_08_07_MASK 0xffffffff
+#define ADDA_IIR_COEF_08_07_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_IIR_COEF_10_09 */
+#define ADDA_IIR_COEF_10_09_SFT 0
+#define ADDA_IIR_COEF_10_09_MASK 0xffffffff
+#define ADDA_IIR_COEF_10_09_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_02_01 */
+#define ADDA_ULCF_CFG_02_01_SFT 0
+#define ADDA_ULCF_CFG_02_01_MASK 0xffffffff
+#define ADDA_ULCF_CFG_02_01_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_04_03 */
+#define ADDA_ULCF_CFG_04_03_SFT 0
+#define ADDA_ULCF_CFG_04_03_MASK 0xffffffff
+#define ADDA_ULCF_CFG_04_03_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_06_05 */
+#define ADDA_ULCF_CFG_06_05_SFT 0
+#define ADDA_ULCF_CFG_06_05_MASK 0xffffffff
+#define ADDA_ULCF_CFG_06_05_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_08_07 */
+#define ADDA_ULCF_CFG_08_07_SFT 0
+#define ADDA_ULCF_CFG_08_07_MASK 0xffffffff
+#define ADDA_ULCF_CFG_08_07_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_10_09 */
+#define ADDA_ULCF_CFG_10_09_SFT 0
+#define ADDA_ULCF_CFG_10_09_MASK 0xffffffff
+#define ADDA_ULCF_CFG_10_09_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_12_11 */
+#define ADDA_ULCF_CFG_12_11_SFT 0
+#define ADDA_ULCF_CFG_12_11_MASK 0xffffffff
+#define ADDA_ULCF_CFG_12_11_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_14_13 */
+#define ADDA_ULCF_CFG_14_13_SFT 0
+#define ADDA_ULCF_CFG_14_13_MASK 0xffffffff
+#define ADDA_ULCF_CFG_14_13_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_16_15 */
+#define ADDA_ULCF_CFG_16_15_SFT 0
+#define ADDA_ULCF_CFG_16_15_MASK 0xffffffff
+#define ADDA_ULCF_CFG_16_15_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_18_17 */
+#define ADDA_ULCF_CFG_18_17_SFT 0
+#define ADDA_ULCF_CFG_18_17_MASK 0xffffffff
+#define ADDA_ULCF_CFG_18_17_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_20_19 */
+#define ADDA_ULCF_CFG_20_19_SFT 0
+#define ADDA_ULCF_CFG_20_19_MASK 0xffffffff
+#define ADDA_ULCF_CFG_20_19_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_22_21 */
+#define ADDA_ULCF_CFG_22_21_SFT 0
+#define ADDA_ULCF_CFG_22_21_MASK 0xffffffff
+#define ADDA_ULCF_CFG_22_21_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_24_23 */
+#define ADDA_ULCF_CFG_24_23_SFT 0
+#define ADDA_ULCF_CFG_24_23_MASK 0xffffffff
+#define ADDA_ULCF_CFG_24_23_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_26_25 */
+#define ADDA_ULCF_CFG_26_25_SFT 0
+#define ADDA_ULCF_CFG_26_25_MASK 0xffffffff
+#define ADDA_ULCF_CFG_26_25_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_28_27 */
+#define ADDA_ULCF_CFG_28_27_SFT 0
+#define ADDA_ULCF_CFG_28_27_MASK 0xffffffff
+#define ADDA_ULCF_CFG_28_27_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_30_29 */
+#define ADDA_ULCF_CFG_30_29_SFT 0
+#define ADDA_ULCF_CFG_30_29_MASK 0xffffffff
+#define ADDA_ULCF_CFG_30_29_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_ULCF_CFG_32_31 */
+#define ADDA_ULCF_CFG_32_31_SFT 0
+#define ADDA_ULCF_CFG_32_31_MASK 0xffffffff
+#define ADDA_ULCF_CFG_32_31_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_IP_VERSION */
+#define ADDA_ULCF_IP_VERSION_SFT 0
+#define ADDA_ULCF_IP_VERSION_MASK 0xffffffff
+#define ADDA_ULCF_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_SRC_CON0 */
+#define ULCF_CFG_EN_CTL_SFT 31
+#define ULCF_CFG_EN_CTL_MASK 0x1
+#define ULCF_CFG_EN_CTL_MASK_SFT (0x1 << 31)
+#define UL_DMIC_PHASE_SEL_CH1_SFT 27
+#define UL_DMIC_PHASE_SEL_CH1_MASK 0x7
+#define UL_DMIC_PHASE_SEL_CH1_MASK_SFT (0x7 << 27)
+#define UL_DMIC_PHASE_SEL_CH2_SFT 24
+#define UL_DMIC_PHASE_SEL_CH2_MASK 0x7
+#define UL_DMIC_PHASE_SEL_CH2_MASK_SFT (0x7 << 24)
+#define UL_DMIC_TWO_WIRE_CTL_SFT 23
+#define UL_DMIC_TWO_WIRE_CTL_MASK 0x1
+#define UL_DMIC_TWO_WIRE_CTL_MASK_SFT (0x1 << 23)
+#define UL_MODE_3P25M_CH2_CTL_SFT 22
+#define UL_MODE_3P25M_CH2_CTL_MASK 0x1
+#define UL_MODE_3P25M_CH2_CTL_MASK_SFT (0x1 << 22)
+#define UL_MODE_3P25M_CH1_CTL_SFT 21
+#define UL_MODE_3P25M_CH1_CTL_MASK 0x1
+#define UL_MODE_3P25M_CH1_CTL_MASK_SFT (0x1 << 21)
+#define UL_VOICE_MODE_CH1_CH2_CTL_SFT 17
+#define UL_VOICE_MODE_CH1_CH2_CTL_MASK 0x7
+#define UL_VOICE_MODE_CH1_CH2_CTL_MASK_SFT (0x7 << 17)
+#define UL_AP_DMIC_ON_SFT 16
+#define UL_AP_DMIC_ON_MASK 0x1
+#define UL_AP_DMIC_ON_MASK_SFT (0x1 << 16)
+#define DMIC_LOW_POWER_MODE_CTL_SFT 14
+#define DMIC_LOW_POWER_MODE_CTL_MASK 0x3
+#define DMIC_LOW_POWER_MODE_CTL_MASK_SFT (0x3 << 14)
+#define UL_DISABLE_HW_CG_CTL_SFT 12
+#define UL_DISABLE_HW_CG_CTL_MASK 0x1
+#define UL_DISABLE_HW_CG_CTL_MASK_SFT (0x1 << 12)
+#define AMIC_26M_SEL_CTL_SFT 11
+#define AMIC_26M_SEL_CTL_MASK 0x1
+#define AMIC_26M_SEL_CTL_MASK_SFT (0x1 << 11)
+#define UL_IIR_ON_TMP_CTL_SFT 10
+#define UL_IIR_ON_TMP_CTL_MASK 0x1
+#define UL_IIR_ON_TMP_CTL_MASK_SFT (0x1 << 10)
+#define UL_IIRMODE_CTL_SFT 7
+#define UL_IIRMODE_CTL_MASK 0x7
+#define UL_IIRMODE_CTL_MASK_SFT (0x7 << 7)
+#define DIGMIC_4P33M_SEL_SFT 6
+#define DIGMIC_4P33M_SEL_MASK 0x1
+#define DIGMIC_4P33M_SEL_MASK_SFT (0x1 << 6)
+#define DIGMIC_3P25M_1P625M_SEL_CTL_SFT 5
+#define DIGMIC_3P25M_1P625M_SEL_CTL_MASK 0x1
+#define DIGMIC_3P25M_1P625M_SEL_CTL_MASK_SFT (0x1 << 5)
+#define AMIC_6P5M_SEL_CTL_SFT 4
+#define AMIC_6P5M_SEL_CTL_MASK 0x1
+#define AMIC_6P5M_SEL_CTL_MASK_SFT (0x1 << 4)
+#define AMIC_1P625M_SEL_CTL_SFT 3
+#define AMIC_1P625M_SEL_CTL_MASK 0x1
+#define AMIC_1P625M_SEL_CTL_MASK_SFT (0x1 << 3)
+#define UL_LOOP_BACK_MODE_CTL_SFT 2
+#define UL_LOOP_BACK_MODE_CTL_MASK 0x1
+#define UL_LOOP_BACK_MODE_CTL_MASK_SFT (0x1 << 2)
+#define UL_SDM_3_LEVEL_CTL_SFT 1
+#define UL_SDM_3_LEVEL_CTL_MASK 0x1
+#define UL_SDM_3_LEVEL_CTL_MASK_SFT (0x1 << 1)
+#define UL_SRC_ON_TMP_CTL_SFT 0
+#define UL_SRC_ON_TMP_CTL_MASK 0x1
+#define UL_SRC_ON_TMP_CTL_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA_UL2_SRC_CON1 */
+#define ADDA_UL_GAIN_VALUE_SFT 16
+#define ADDA_UL_GAIN_VALUE_MASK 0xffff
+#define ADDA_UL_GAIN_VALUE_MASK_SFT (0xffff << 16)
+#define ADDA_UL_POSTIVEGAIN_SFT 12
+#define ADDA_UL_POSTIVEGAIN_MASK 0x7
+#define ADDA_UL_POSTIVEGAIN_MASK_SFT (0x7 << 12)
+#define ADDA_UL_ODDTAP_MODE_SFT 11
+#define ADDA_UL_ODDTAP_MODE_MASK 0x1
+#define ADDA_UL_ODDTAP_MODE_MASK_SFT (0x1 << 11)
+#define ADDA_UL_HALF_TAP_NUM_SFT 5
+#define ADDA_UL_HALF_TAP_NUM_MASK 0x3f
+#define ADDA_UL_HALF_TAP_NUM_MASK_SFT (0x3f << 5)
+#define FIFO_SOFT_RST_SFT 4
+#define FIFO_SOFT_RST_MASK 0x1
+#define FIFO_SOFT_RST_MASK_SFT (0x1 << 4)
+#define FIFO_SOFT_RST_EN_SFT 3
+#define FIFO_SOFT_RST_EN_MASK 0x1
+#define FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 3)
+#define LR_SWAP_SFT 2
+#define LR_SWAP_MASK 0x1
+#define LR_SWAP_MASK_SFT (0x1 << 2)
+#define GAIN_MODE_SFT 0
+#define GAIN_MODE_MASK 0x3
+#define GAIN_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_ADDA_UL2_SRC_CON2 */
+#define C_DAC_EN_CTL_SFT 27
+#define C_DAC_EN_CTL_MASK 0x1
+#define C_DAC_EN_CTL_MASK_SFT (0x1 << 27)
+#define C_MUTE_SW_CTL_SFT 26
+#define C_MUTE_SW_CTL_MASK 0x1
+#define C_MUTE_SW_CTL_MASK_SFT (0x1 << 26)
+#define C_AMP_DIV_CH2_CTL_SFT 21
+#define C_AMP_DIV_CH2_CTL_MASK 0x7
+#define C_AMP_DIV_CH2_CTL_MASK_SFT (0x7 << 21)
+#define C_FREQ_DIV_CH2_CTL_SFT 16
+#define C_FREQ_DIV_CH2_CTL_MASK 0x1f
+#define C_FREQ_DIV_CH2_CTL_MASK_SFT (0x1f << 16)
+#define C_SINE_MODE_CH2_CTL_SFT 12
+#define C_SINE_MODE_CH2_CTL_MASK 0xf
+#define C_SINE_MODE_CH2_CTL_MASK_SFT (0xf << 12)
+#define C_AMP_DIV_CH1_CTL_SFT 9
+#define C_AMP_DIV_CH1_CTL_MASK 0x7
+#define C_AMP_DIV_CH1_CTL_MASK_SFT (0x7 << 9)
+#define C_FREQ_DIV_CH1_CTL_SFT 4
+#define C_FREQ_DIV_CH1_CTL_MASK 0x1f
+#define C_FREQ_DIV_CH1_CTL_MASK_SFT (0x1f << 4)
+#define C_SINE_MODE_CH1_CTL_SFT 0
+#define C_SINE_MODE_CH1_CTL_MASK 0xf
+#define C_SINE_MODE_CH1_CTL_MASK_SFT (0xf << 0)
+
+/* AFE_ADDA_UL2_SRC_DEBUG */
+#define UL_SLT_CNT_FLAG_RESET_CTL_SFT 16
+#define UL_SLT_CNT_FLAG_RESET_CTL_MASK 0x1
+#define UL_SLT_CNT_FLAG_RESET_CTL_MASK_SFT (0x1 << 16)
+#define FIFO_DIGMIC_TESTIN_SFT 12
+#define FIFO_DIGMIC_TESTIN_MASK 0x3
+#define FIFO_DIGMIC_TESTIN_MASK_SFT (0x3 << 12)
+#define FIFO_DIGMIC_WDATA_TESTEN_SFT 11
+#define FIFO_DIGMIC_WDATA_TESTEN_MASK 0x1
+#define FIFO_DIGMIC_WDATA_TESTEN_MASK_SFT (0x1 << 11)
+#define SLT_CNT_THD_CTL_SFT 0
+#define SLT_CNT_THD_CTL_MASK 0x7ff
+#define SLT_CNT_THD_CTL_MASK_SFT (0x7ff << 0)
+
+/* AFE_ADDA_UL2_SRC_DEBUG_MON0 */
+#define SLT_CNT_FLAG_CTL_SFT 16
+#define SLT_CNT_FLAG_CTL_MASK 0x1
+#define SLT_CNT_FLAG_CTL_MASK_SFT (0x1 << 16)
+#define SLT_COUNTER_CTL_SFT 0
+#define SLT_COUNTER_CTL_MASK 0x7ff
+#define SLT_COUNTER_CTL_MASK_SFT (0x7ff << 0)
+
+/* AFE_ADDA_UL2_IIR_COEF_02_01 */
+#define ADDA_IIR_COEF_02_01_SFT 0
+#define ADDA_IIR_COEF_02_01_MASK 0xffffffff
+#define ADDA_IIR_COEF_02_01_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_IIR_COEF_04_03 */
+#define ADDA_IIR_COEF_04_03_SFT 0
+#define ADDA_IIR_COEF_04_03_MASK 0xffffffff
+#define ADDA_IIR_COEF_04_03_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_IIR_COEF_06_05 */
+#define ADDA_IIR_COEF_06_05_SFT 0
+#define ADDA_IIR_COEF_06_05_MASK 0xffffffff
+#define ADDA_IIR_COEF_06_05_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_IIR_COEF_08_07 */
+#define ADDA_IIR_COEF_08_07_SFT 0
+#define ADDA_IIR_COEF_08_07_MASK 0xffffffff
+#define ADDA_IIR_COEF_08_07_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_IIR_COEF_10_09 */
+#define ADDA_IIR_COEF_10_09_SFT 0
+#define ADDA_IIR_COEF_10_09_MASK 0xffffffff
+#define ADDA_IIR_COEF_10_09_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_02_01 */
+#define ADDA_ULCF_CFG_02_01_SFT 0
+#define ADDA_ULCF_CFG_02_01_MASK 0xffffffff
+#define ADDA_ULCF_CFG_02_01_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_04_03 */
+#define ADDA_ULCF_CFG_04_03_SFT 0
+#define ADDA_ULCF_CFG_04_03_MASK 0xffffffff
+#define ADDA_ULCF_CFG_04_03_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_06_05 */
+#define ADDA_ULCF_CFG_06_05_SFT 0
+#define ADDA_ULCF_CFG_06_05_MASK 0xffffffff
+#define ADDA_ULCF_CFG_06_05_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_08_07 */
+#define ADDA_ULCF_CFG_08_07_SFT 0
+#define ADDA_ULCF_CFG_08_07_MASK 0xffffffff
+#define ADDA_ULCF_CFG_08_07_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_10_09 */
+#define ADDA_ULCF_CFG_10_09_SFT 0
+#define ADDA_ULCF_CFG_10_09_MASK 0xffffffff
+#define ADDA_ULCF_CFG_10_09_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_12_11 */
+#define ADDA_ULCF_CFG_12_11_SFT 0
+#define ADDA_ULCF_CFG_12_11_MASK 0xffffffff
+#define ADDA_ULCF_CFG_12_11_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_14_13 */
+#define ADDA_ULCF_CFG_14_13_SFT 0
+#define ADDA_ULCF_CFG_14_13_MASK 0xffffffff
+#define ADDA_ULCF_CFG_14_13_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_16_15 */
+#define ADDA_ULCF_CFG_16_15_SFT 0
+#define ADDA_ULCF_CFG_16_15_MASK 0xffffffff
+#define ADDA_ULCF_CFG_16_15_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_18_17 */
+#define ADDA_ULCF_CFG_18_17_SFT 0
+#define ADDA_ULCF_CFG_18_17_MASK 0xffffffff
+#define ADDA_ULCF_CFG_18_17_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_20_19 */
+#define ADDA_ULCF_CFG_20_19_SFT 0
+#define ADDA_ULCF_CFG_20_19_MASK 0xffffffff
+#define ADDA_ULCF_CFG_20_19_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_22_21 */
+#define ADDA_ULCF_CFG_22_21_SFT 0
+#define ADDA_ULCF_CFG_22_21_MASK 0xffffffff
+#define ADDA_ULCF_CFG_22_21_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_24_23 */
+#define ADDA_ULCF_CFG_24_23_SFT 0
+#define ADDA_ULCF_CFG_24_23_MASK 0xffffffff
+#define ADDA_ULCF_CFG_24_23_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_26_25 */
+#define ADDA_ULCF_CFG_26_25_SFT 0
+#define ADDA_ULCF_CFG_26_25_MASK 0xffffffff
+#define ADDA_ULCF_CFG_26_25_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_28_27 */
+#define ADDA_ULCF_CFG_28_27_SFT 0
+#define ADDA_ULCF_CFG_28_27_MASK 0xffffffff
+#define ADDA_ULCF_CFG_28_27_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_30_29 */
+#define ADDA_ULCF_CFG_30_29_SFT 0
+#define ADDA_ULCF_CFG_30_29_MASK 0xffffffff
+#define ADDA_ULCF_CFG_30_29_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_ULCF_CFG_32_31 */
+#define ADDA_ULCF_CFG_32_31_SFT 0
+#define ADDA_ULCF_CFG_32_31_MASK 0xffffffff
+#define ADDA_ULCF_CFG_32_31_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_IP_VERSION */
+#define ADDA_ULCF_IP_VERSION_SFT 0
+#define ADDA_ULCF_IP_VERSION_MASK 0xffffffff
+#define ADDA_ULCF_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_PROXIMITY_CON0 */
+#define PROXIMITY_CH1_ON_SFT 12
+#define PROXIMITY_CH1_ON_MASK 0x1
+#define PROXIMITY_CH1_ON_MASK_SFT (0x1 << 12)
+#define PROXIMITY_CH1_SEL_SFT 8
+#define PROXIMITY_CH1_SEL_MASK 0xf
+#define PROXIMITY_CH1_SEL_MASK_SFT (0xf << 8)
+#define PROXIMITY_CH2_ON_SFT 4
+#define PROXIMITY_CH2_ON_MASK 0x1
+#define PROXIMITY_CH2_ON_MASK_SFT (0x1 << 4)
+#define PROXIMITY_CH2_SEL_SFT 0
+#define PROXIMITY_CH2_SEL_MASK 0xf
+#define PROXIMITY_CH2_SEL_MASK_SFT (0xf << 0)
+
+/* AFE_ADDA_ULSRC_PHASE_CON0 */
+#define DMIC1_PHASE_FCLK_SEL_SFT 30
+#define DMIC1_PHASE_FCLK_SEL_MASK 0x3
+#define DMIC1_PHASE_FCLK_SEL_MASK_SFT (0x3 << 30)
+#define DMIC0_PHASE_FCLK_SEL_SFT 28
+#define DMIC0_PHASE_FCLK_SEL_MASK 0x3
+#define DMIC0_PHASE_FCLK_SEL_MASK_SFT (0x3 << 28)
+#define UL3_PHASE_FCLK_SEL_SFT 26
+#define UL3_PHASE_FCLK_SEL_MASK 0x3
+#define UL3_PHASE_FCLK_SEL_MASK_SFT (0x3 << 26)
+#define UL2_PHASE_FCLK_SEL_SFT 24
+#define UL2_PHASE_FCLK_SEL_MASK 0x3
+#define UL2_PHASE_FCLK_SEL_MASK_SFT (0x3 << 24)
+#define UL1_PHASE_FCLK_SEL_SFT 22
+#define UL1_PHASE_FCLK_SEL_MASK 0x3
+#define UL1_PHASE_FCLK_SEL_MASK_SFT (0x3 << 22)
+#define UL0_PHASE_FCLK_SEL_SFT 20
+#define UL0_PHASE_FCLK_SEL_MASK 0x3
+#define UL0_PHASE_FCLK_SEL_MASK_SFT (0x3 << 20)
+#define UL_PHASE_SYNC_FCLK_2_ON_SFT 18
+#define UL_PHASE_SYNC_FCLK_2_ON_MASK 0x1
+#define UL_PHASE_SYNC_FCLK_2_ON_MASK_SFT (0x1 << 18)
+#define UL_PHASE_SYNC_FCLK_1_ON_SFT 17
+#define UL_PHASE_SYNC_FCLK_1_ON_MASK 0x1
+#define UL_PHASE_SYNC_FCLK_1_ON_MASK_SFT (0x1 << 17)
+#define UL_PHASE_SYNC_FCLK_0_ON_SFT 16
+#define UL_PHASE_SYNC_FCLK_0_ON_MASK 0x1
+#define UL_PHASE_SYNC_FCLK_0_ON_MASK_SFT (0x1 << 16)
+#define DMIC1_PHASE_HCLK_SEL_SFT 14
+#define DMIC1_PHASE_HCLK_SEL_MASK 0x3
+#define DMIC1_PHASE_HCLK_SEL_MASK_SFT (0x3 << 14)
+#define DMIC0_PHASE_HCLK_SEL_SFT 12
+#define DMIC0_PHASE_HCLK_SEL_MASK 0x3
+#define DMIC0_PHASE_HCLK_SEL_MASK_SFT (0x3 << 12)
+#define UL3_PHASE_HCLK_SEL_SFT 10
+#define UL3_PHASE_HCLK_SEL_MASK 0x3
+#define UL3_PHASE_HCLK_SEL_MASK_SFT (0x3 << 10)
+#define UL2_PHASE_HCLK_SEL_SFT 8
+#define UL2_PHASE_HCLK_SEL_MASK 0x3
+#define UL2_PHASE_HCLK_SEL_MASK_SFT (0x3 << 8)
+#define UL1_PHASE_HCLK_SEL_SFT 6
+#define UL1_PHASE_HCLK_SEL_MASK 0x3
+#define UL1_PHASE_HCLK_SEL_MASK_SFT (0x3 << 6)
+#define UL0_PHASE_HCLK_SEL_SFT 4
+#define UL0_PHASE_HCLK_SEL_MASK 0x3
+#define UL0_PHASE_HCLK_SEL_MASK_SFT (0x3 << 4)
+#define UL_PHASE_SYNC_HCLK_2_ON_SFT 2
+#define UL_PHASE_SYNC_HCLK_2_ON_MASK 0x1
+#define UL_PHASE_SYNC_HCLK_2_ON_MASK_SFT (0x1 << 2)
+#define UL_PHASE_SYNC_HCLK_1_ON_SFT 1
+#define UL_PHASE_SYNC_HCLK_1_ON_MASK 0x1
+#define UL_PHASE_SYNC_HCLK_1_ON_MASK_SFT (0x1 << 1)
+#define UL_PHASE_SYNC_HCLK_0_ON_SFT 0
+#define UL_PHASE_SYNC_HCLK_0_ON_MASK 0x1
+#define UL_PHASE_SYNC_HCLK_0_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA_ULSRC_PHASE_CON1 */
+#define DMIC_CLK_PHASE_SYNC_SET_SFT 31
+#define DMIC_CLK_PHASE_SYNC_SET_MASK 0x1
+#define DMIC_CLK_PHASE_SYNC_SET_MASK_SFT (0x1 << 31)
+#define DMIC1_PHASE_SYNC_FCLK_SET_SFT 11
+#define DMIC1_PHASE_SYNC_FCLK_SET_MASK 0x1
+#define DMIC1_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 11)
+#define DMIC1_PHASE_SYNC_HCLK_SET_SFT 10
+#define DMIC1_PHASE_SYNC_HCLK_SET_MASK 0x1
+#define DMIC1_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 10)
+#define DMIC0_PHASE_SYNC_FCLK_SET_SFT 9
+#define DMIC0_PHASE_SYNC_FCLK_SET_MASK 0x1
+#define DMIC0_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 9)
+#define DMIC0_PHASE_SYNC_HCLK_SET_SFT 8
+#define DMIC0_PHASE_SYNC_HCLK_SET_MASK 0x1
+#define DMIC0_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 8)
+#define UL3_PHASE_SYNC_FCLK_SET_SFT 7
+#define UL3_PHASE_SYNC_FCLK_SET_MASK 0x1
+#define UL3_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 7)
+#define UL3_PHASE_SYNC_HCLK_SET_SFT 6
+#define UL3_PHASE_SYNC_HCLK_SET_MASK 0x1
+#define UL3_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 6)
+#define UL2_PHASE_SYNC_FCLK_SET_SFT 5
+#define UL2_PHASE_SYNC_FCLK_SET_MASK 0x1
+#define UL2_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 5)
+#define UL2_PHASE_SYNC_HCLK_SET_SFT 4
+#define UL2_PHASE_SYNC_HCLK_SET_MASK 0x1
+#define UL2_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 4)
+#define UL1_PHASE_SYNC_FCLK_SET_SFT 3
+#define UL1_PHASE_SYNC_FCLK_SET_MASK 0x1
+#define UL1_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 3)
+#define UL1_PHASE_SYNC_HCLK_SET_SFT 2
+#define UL1_PHASE_SYNC_HCLK_SET_MASK 0x1
+#define UL1_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 2)
+#define UL0_PHASE_SYNC_FCLK_SET_SFT 1
+#define UL0_PHASE_SYNC_FCLK_SET_MASK 0x1
+#define UL0_PHASE_SYNC_FCLK_SET_MASK_SFT (0x1 << 1)
+#define UL0_PHASE_SYNC_HCLK_SET_SFT 0
+#define UL0_PHASE_SYNC_HCLK_SET_MASK 0x1
+#define UL0_PHASE_SYNC_HCLK_SET_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA_ULSRC_PHASE_CON2 */
+#define DMIC1_PHASE_SYNC_1X_EN_SEL_SFT 26
+#define DMIC1_PHASE_SYNC_1X_EN_SEL_MASK 0x3
+#define DMIC1_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 26)
+#define DMIC0_PHASE_SYNC_1X_EN_SEL_SFT 24
+#define DMIC0_PHASE_SYNC_1X_EN_SEL_MASK 0x3
+#define DMIC0_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 24)
+#define UL3_PHASE_SYNC_1X_EN_SEL_SFT 22
+#define UL3_PHASE_SYNC_1X_EN_SEL_MASK 0x3
+#define UL3_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 22)
+#define UL2_PHASE_SYNC_1X_EN_SEL_SFT 20
+#define UL2_PHASE_SYNC_1X_EN_SEL_MASK 0x3
+#define UL2_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 20)
+#define UL1_PHASE_SYNC_1X_EN_SEL_SFT 18
+#define UL1_PHASE_SYNC_1X_EN_SEL_MASK 0x3
+#define UL1_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 18)
+#define UL0_PHASE_SYNC_1X_EN_SEL_SFT 16
+#define UL0_PHASE_SYNC_1X_EN_SEL_MASK 0x3
+#define UL0_PHASE_SYNC_1X_EN_SEL_MASK_SFT (0x3 << 16)
+#define UL_PHASE_SYNC_FCLK_1X_EN_2_ON_SFT 5
+#define UL_PHASE_SYNC_FCLK_1X_EN_2_ON_MASK 0x1
+#define UL_PHASE_SYNC_FCLK_1X_EN_2_ON_MASK_SFT (0x1 << 5)
+#define UL_PHASE_SYNC_FCLK_1X_EN_1_ON_SFT 4
+#define UL_PHASE_SYNC_FCLK_1X_EN_1_ON_MASK 0x1
+#define UL_PHASE_SYNC_FCLK_1X_EN_1_ON_MASK_SFT (0x1 << 4)
+#define UL_PHASE_SYNC_FCLK_1X_EN_0_ON_SFT 3
+#define UL_PHASE_SYNC_FCLK_1X_EN_0_ON_MASK 0x1
+#define UL_PHASE_SYNC_FCLK_1X_EN_0_ON_MASK_SFT (0x1 << 3)
+#define UL_PHASE_SYNC_HCLK_1X_EN_2_ON_SFT 2
+#define UL_PHASE_SYNC_HCLK_1X_EN_2_ON_MASK 0x1
+#define UL_PHASE_SYNC_HCLK_1X_EN_2_ON_MASK_SFT (0x1 << 2)
+#define UL_PHASE_SYNC_HCLK_1X_EN_1_ON_SFT 1
+#define UL_PHASE_SYNC_HCLK_1X_EN_1_ON_MASK 0x1
+#define UL_PHASE_SYNC_HCLK_1X_EN_1_ON_MASK_SFT (0x1 << 1)
+#define UL_PHASE_SYNC_HCLK_1X_EN_0_ON_SFT 0
+#define UL_PHASE_SYNC_HCLK_1X_EN_0_ON_MASK 0x1
+#define UL_PHASE_SYNC_HCLK_1X_EN_0_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA_ULSRC_PHASE_CON3 */
+#define DMIC1_PHASE_SYNC_SOFT_RST_SEL_SFT 26
+#define DMIC1_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3
+#define DMIC1_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 26)
+#define DMIC0_PHASE_SYNC_SOFT_RST_SEL_SFT 24
+#define DMIC0_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3
+#define DMIC0_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 24)
+#define UL3_PHASE_SYNC_SOFT_RST_SEL_SFT 22
+#define UL3_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3
+#define UL3_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 22)
+#define UL2_PHASE_SYNC_SOFT_RST_SEL_SFT 20
+#define UL2_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3
+#define UL2_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 20)
+#define UL1_PHASE_SYNC_SOFT_RST_SEL_SFT 18
+#define UL1_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3
+#define UL1_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 18)
+#define UL0_PHASE_SYNC_SOFT_RST_SEL_SFT 16
+#define UL0_PHASE_SYNC_SOFT_RST_SEL_MASK 0x3
+#define UL0_PHASE_SYNC_SOFT_RST_SEL_MASK_SFT (0x3 << 16)
+#define DMIC1_PHASE_SYNC_CH1_FIFO_SEL_SFT 13
+#define DMIC1_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1
+#define DMIC1_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 13)
+#define DMIC0_PHASE_SYNC_CH1_FIFO_SEL_SFT 12
+#define DMIC0_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1
+#define DMIC0_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 12)
+#define UL3_PHASE_SYNC_CH1_FIFO_SEL_SFT 11
+#define UL3_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1
+#define UL3_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 11)
+#define UL2_PHASE_SYNC_CH1_FIFO_SEL_SFT 10
+#define UL2_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1
+#define UL2_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 10)
+#define UL1_PHASE_SYNC_CH1_FIFO_SEL_SFT 9
+#define UL1_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1
+#define UL1_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 9)
+#define UL0_PHASE_SYNC_CH1_FIFO_SEL_SFT 8
+#define UL0_PHASE_SYNC_CH1_FIFO_SEL_MASK 0x1
+#define UL0_PHASE_SYNC_CH1_FIFO_SEL_MASK_SFT (0x1 << 8)
+#define UL_PHASE_SYNC_SOFT_RST_EN_2_ON_SFT 5
+#define UL_PHASE_SYNC_SOFT_RST_EN_2_ON_MASK 0x1
+#define UL_PHASE_SYNC_SOFT_RST_EN_2_ON_MASK_SFT (0x1 << 5)
+#define UL_PHASE_SYNC_SOFT_RST_EN_1_ON_SFT 4
+#define UL_PHASE_SYNC_SOFT_RST_EN_1_ON_MASK 0x1
+#define UL_PHASE_SYNC_SOFT_RST_EN_1_ON_MASK_SFT (0x1 << 4)
+#define UL_PHASE_SYNC_SOFT_RST_EN_0_ON_SFT 3
+#define UL_PHASE_SYNC_SOFT_RST_EN_0_ON_MASK 0x1
+#define UL_PHASE_SYNC_SOFT_RST_EN_0_ON_MASK_SFT (0x1 << 3)
+#define UL_PHASE_SYNC_SOFT_RST_2_ON_SFT 2
+#define UL_PHASE_SYNC_SOFT_RST_2_ON_MASK 0x1
+#define UL_PHASE_SYNC_SOFT_RST_2_ON_MASK_SFT (0x1 << 2)
+#define UL_PHASE_SYNC_SOFT_RST_1_ON_SFT 1
+#define UL_PHASE_SYNC_SOFT_RST_1_ON_MASK 0x1
+#define UL_PHASE_SYNC_SOFT_RST_1_ON_MASK_SFT (0x1 << 1)
+#define UL_PHASE_SYNC_SOFT_RST_0_ON_SFT 0
+#define UL_PHASE_SYNC_SOFT_RST_0_ON_MASK 0x1
+#define UL_PHASE_SYNC_SOFT_RST_0_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_MTKAIF_IPM_VER_MON */
+#define RG_MTKAIF_IPM_VER_MON_SFT 0
+#define RG_MTKAIF_IPM_VER_MON_MASK 0xffffffff
+#define RG_MTKAIF_IPM_VER_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_MTKAIF_MON_SEL */
+#define RG_MTKAIF_MON_SEL_SFT 0
+#define RG_MTKAIF_MON_SEL_MASK 0xff
+#define RG_MTKAIF_MON_SEL_MASK_SFT (0xff << 0)
+
+/* AFE_MTKAIF_MON */
+#define RG_MTKAIF_MON_SFT 0
+#define RG_MTKAIF_MON_MASK 0xffffffff
+#define RG_MTKAIF_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_MTKAIF0_CFG0 */
+#define RG_MTKAIF0_RXIF_CLKINV_SFT 31
+#define RG_MTKAIF0_RXIF_CLKINV_MASK 0x1
+#define RG_MTKAIF0_RXIF_CLKINV_MASK_SFT (0x1 << 31)
+#define RG_MTKAIF0_RXIF_BYPASS_SRC_SFT 17
+#define RG_MTKAIF0_RXIF_BYPASS_SRC_MASK 0x1
+#define RG_MTKAIF0_RXIF_BYPASS_SRC_MASK_SFT (0x1 << 17)
+#define RG_MTKAIF0_RXIF_PROTOCOL2_SFT 16
+#define RG_MTKAIF0_RXIF_PROTOCOL2_MASK 0x1
+#define RG_MTKAIF0_RXIF_PROTOCOL2_MASK_SFT (0x1 << 16)
+#define RG_MTKAIF0_TXIF_NLE_DEBUG_SFT 8
+#define RG_MTKAIF0_TXIF_NLE_DEBUG_MASK 0x1
+#define RG_MTKAIF0_TXIF_NLE_DEBUG_MASK_SFT (0x1 << 8)
+#define RG_MTKAIF0_TXIF_BYPASS_SRC_SFT 5
+#define RG_MTKAIF0_TXIF_BYPASS_SRC_MASK 0x1
+#define RG_MTKAIF0_TXIF_BYPASS_SRC_MASK_SFT (0x1 << 5)
+#define RG_MTKAIF0_TXIF_PROTOCOL2_SFT 4
+#define RG_MTKAIF0_TXIF_PROTOCOL2_MASK 0x1
+#define RG_MTKAIF0_TXIF_PROTOCOL2_MASK_SFT (0x1 << 4)
+#define RG_MTKAIF0_TXIF_8TO5_SFT 2
+#define RG_MTKAIF0_TXIF_8TO5_MASK 0x1
+#define RG_MTKAIF0_TXIF_8TO5_MASK_SFT (0x1 << 2)
+#define RG_MTKAIF0_RXIF_8TO5_SFT 1
+#define RG_MTKAIF0_RXIF_8TO5_MASK 0x1
+#define RG_MTKAIF0_RXIF_8TO5_MASK_SFT (0x1 << 1)
+#define RG_MTKAIF0_TX2RX_LOOPBACK1_SFT 0
+#define RG_MTKAIF0_TX2RX_LOOPBACK1_MASK 0x1
+#define RG_MTKAIF0_TX2RX_LOOPBACK1_MASK_SFT (0x1 << 0)
+
+/* AFE_MTKAIF0_TX_CFG0 */
+#define RG_MTKAIF0_TXIF_NLE_FIFO_SWAP_SFT 23
+#define RG_MTKAIF0_TXIF_NLE_FIFO_SWAP_MASK 0x1
+#define RG_MTKAIF0_TXIF_NLE_FIFO_SWAP_MASK_SFT (0x1 << 23)
+#define RG_MTKAIF0_TXIF_NLE_FIFO_RSP_SFT 20
+#define RG_MTKAIF0_TXIF_NLE_FIFO_RSP_MASK 0x7
+#define RG_MTKAIF0_TXIF_NLE_FIFO_RSP_MASK_SFT (0x7 << 20)
+#define RG_MTKAIF0_TXIF_FIFO_SWAP_SFT 15
+#define RG_MTKAIF0_TXIF_FIFO_SWAP_MASK 0x1
+#define RG_MTKAIF0_TXIF_FIFO_SWAP_MASK_SFT (0x1 << 15)
+#define RG_MTKAIF0_TXIF_FIFO_RSP_SFT 12
+#define RG_MTKAIF0_TXIF_FIFO_RSP_MASK 0x7
+#define RG_MTKAIF0_TXIF_FIFO_RSP_MASK_SFT (0x7 << 12)
+#define RG_MTKAIF0_TXIF_SYNC_WORD1_SFT 4
+#define RG_MTKAIF0_TXIF_SYNC_WORD1_MASK 0x7
+#define RG_MTKAIF0_TXIF_SYNC_WORD1_MASK_SFT (0x7 << 4)
+#define RG_MTKAIF0_TXIF_SYNC_WORD0_SFT 0
+#define RG_MTKAIF0_TXIF_SYNC_WORD0_MASK 0x7
+#define RG_MTKAIF0_TXIF_SYNC_WORD0_MASK_SFT (0x7 << 0)
+
+/* AFE_MTKAIF0_RX_CFG0 */
+#define RG_MTKAIF0_RXIF_VOICE_MODE_SFT 20
+#define RG_MTKAIF0_RXIF_VOICE_MODE_MASK 0xf
+#define RG_MTKAIF0_RXIF_VOICE_MODE_MASK_SFT (0xf << 20)
+#define RG_MTKAIF0_RXIF_DETECT_ON_SFT 16
+#define RG_MTKAIF0_RXIF_DETECT_ON_MASK 0x1
+#define RG_MTKAIF0_RXIF_DETECT_ON_MASK_SFT (0x1 << 16)
+#define RG_MTKAIF0_RXIF_DATA_BIT_SFT 8
+#define RG_MTKAIF0_RXIF_DATA_BIT_MASK 0x7
+#define RG_MTKAIF0_RXIF_DATA_BIT_MASK_SFT (0x7 << 8)
+#define RG_MTKAIF0_RXIF_FIFO_RSP_SFT 4
+#define RG_MTKAIF0_RXIF_FIFO_RSP_MASK 0x7
+#define RG_MTKAIF0_RXIF_FIFO_RSP_MASK_SFT (0x7 << 4)
+#define RG_MTKAIF0_RXIF_DATA_MODE_SFT 0
+#define RG_MTKAIF0_RXIF_DATA_MODE_MASK 0x1
+#define RG_MTKAIF0_RXIF_DATA_MODE_MASK_SFT (0x1 << 0)
+
+/* AFE_MTKAIF0_RX_CFG1 */
+#define RG_MTKAIF0_RXIF_CLEAR_SYNC_FAIL_SFT 28
+#define RG_MTKAIF0_RXIF_CLEAR_SYNC_FAIL_MASK 0x1
+#define RG_MTKAIF0_RXIF_CLEAR_SYNC_FAIL_MASK_SFT (0x1 << 28)
+#define RG_MTKAIF0_RXIF_SYNC_CNT_TABLE_SFT 16
+#define RG_MTKAIF0_RXIF_SYNC_CNT_TABLE_MASK 0xfff
+#define RG_MTKAIF0_RXIF_SYNC_CNT_TABLE_MASK_SFT (0xfff << 16)
+#define RG_MTKAIF0_RXIF_SYNC_SEARCH_TABLE_SFT 12
+#define RG_MTKAIF0_RXIF_SYNC_SEARCH_TABLE_MASK 0xf
+#define RG_MTKAIF0_RXIF_SYNC_SEARCH_TABLE_MASK_SFT (0xf << 12)
+#define RG_MTKAIF0_RXIF_INVALID_SYNC_CHECK_ROUND_SFT 8
+#define RG_MTKAIF0_RXIF_INVALID_SYNC_CHECK_ROUND_MASK 0xf
+#define RG_MTKAIF0_RXIF_INVALID_SYNC_CHECK_ROUND_MASK_SFT (0xf << 8)
+#define RG_MTKAIF0_RXIF_SYNC_CHECK_ROUND_SFT 4
+#define RG_MTKAIF0_RXIF_SYNC_CHECK_ROUND_MASK 0xf
+#define RG_MTKAIF0_RXIF_SYNC_CHECK_ROUND_MASK_SFT (0xf << 4)
+
+/* AFE_MTKAIF0_RX_CFG2 */
+#define RG_MTKAIF0_RXIF_SYNC_WORD1_DISABLE_SFT 27
+#define RG_MTKAIF0_RXIF_SYNC_WORD1_DISABLE_MASK 0x1
+#define RG_MTKAIF0_RXIF_SYNC_WORD1_DISABLE_MASK_SFT (0x1 << 27)
+#define RG_MTKAIF0_RXIF_SYNC_WORD1_SFT 24
+#define RG_MTKAIF0_RXIF_SYNC_WORD1_MASK 0x7
+#define RG_MTKAIF0_RXIF_SYNC_WORD1_MASK_SFT (0x7 << 24)
+#define RG_MTKAIF0_RXIF_SYNC_WORD0_DISABLE_SFT 23
+#define RG_MTKAIF0_RXIF_SYNC_WORD0_DISABLE_MASK 0x1
+#define RG_MTKAIF0_RXIF_SYNC_WORD0_DISABLE_MASK_SFT (0x1 << 23)
+#define RG_MTKAIF0_RXIF_SYNC_WORD0_SFT 20
+#define RG_MTKAIF0_RXIF_SYNC_WORD0_MASK 0x7
+#define RG_MTKAIF0_RXIF_SYNC_WORD0_MASK_SFT (0x7 << 20)
+#define RG_MTKAIF0_RXIF_DELAY_CYCLE_SFT 12
+#define RG_MTKAIF0_RXIF_DELAY_CYCLE_MASK 0xf
+#define RG_MTKAIF0_RXIF_DELAY_CYCLE_MASK_SFT (0xf << 12)
+#define RG_MTKAIF0_RXIF_DELAY_DATA_SFT 8
+#define RG_MTKAIF0_RXIF_DELAY_DATA_MASK 0x1
+#define RG_MTKAIF0_RXIF_DELAY_DATA_MASK_SFT (0x1 << 8)
+
+/* AFE_MTKAIF1_CFG0 */
+#define RG_MTKAIF1_RXIF_CLKINV_ADC_SFT 31
+#define RG_MTKAIF1_RXIF_CLKINV_ADC_MASK 0x1
+#define RG_MTKAIF1_RXIF_CLKINV_ADC_MASK_SFT (0x1 << 31)
+#define RG_MTKAIF1_RXIF_BYPASS_SRC_SFT 17
+#define RG_MTKAIF1_RXIF_BYPASS_SRC_MASK 0x1
+#define RG_MTKAIF1_RXIF_BYPASS_SRC_MASK_SFT (0x1 << 17)
+#define RG_MTKAIF1_RXIF_PROTOCOL2_SFT 16
+#define RG_MTKAIF1_RXIF_PROTOCOL2_MASK 0x1
+#define RG_MTKAIF1_RXIF_PROTOCOL2_MASK_SFT (0x1 << 16)
+#define RG_MTKAIF1_TXIF_NLE_DEBUG_SFT 8
+#define RG_MTKAIF1_TXIF_NLE_DEBUG_MASK 0x1
+#define RG_MTKAIF1_TXIF_NLE_DEBUG_MASK_SFT (0x1 << 8)
+#define RG_MTKAIF1_TXIF_BYPASS_SRC_SFT 5
+#define RG_MTKAIF1_TXIF_BYPASS_SRC_MASK 0x1
+#define RG_MTKAIF1_TXIF_BYPASS_SRC_MASK_SFT (0x1 << 5)
+#define RG_MTKAIF1_TXIF_PROTOCOL2_SFT 4
+#define RG_MTKAIF1_TXIF_PROTOCOL2_MASK 0x1
+#define RG_MTKAIF1_TXIF_PROTOCOL2_MASK_SFT (0x1 << 4)
+#define RG_MTKAIF1_TXIF_8TO5_SFT 2
+#define RG_MTKAIF1_TXIF_8TO5_MASK 0x1
+#define RG_MTKAIF1_TXIF_8TO5_MASK_SFT (0x1 << 2)
+#define RG_MTKAIF1_RXIF_8TO5_SFT 1
+#define RG_MTKAIF1_RXIF_8TO5_MASK 0x1
+#define RG_MTKAIF1_RXIF_8TO5_MASK_SFT (0x1 << 1)
+#define RG_MTKAIF1_IF_LOOPBACK1_SFT 0
+#define RG_MTKAIF1_IF_LOOPBACK1_MASK 0x1
+#define RG_MTKAIF1_IF_LOOPBACK1_MASK_SFT (0x1 << 0)
+
+/* AFE_MTKAIF1_TX_CFG0 */
+#define RG_MTKAIF1_TXIF_NLE_FIFO_SWAP_SFT 23
+#define RG_MTKAIF1_TXIF_NLE_FIFO_SWAP_MASK 0x1
+#define RG_MTKAIF1_TXIF_NLE_FIFO_SWAP_MASK_SFT (0x1 << 23)
+#define RG_MTKAIF1_TXIF_NLE_FIFO_RSP_SFT 20
+#define RG_MTKAIF1_TXIF_NLE_FIFO_RSP_MASK 0x7
+#define RG_MTKAIF1_TXIF_NLE_FIFO_RSP_MASK_SFT (0x7 << 20)
+#define RG_MTKAIF1_TXIF_FIFO_SWAP_SFT 15
+#define RG_MTKAIF1_TXIF_FIFO_SWAP_MASK 0x1
+#define RG_MTKAIF1_TXIF_FIFO_SWAP_MASK_SFT (0x1 << 15)
+#define RG_MTKAIF1_TXIF_FIFO_RSP_SFT 12
+#define RG_MTKAIF1_TXIF_FIFO_RSP_MASK 0x7
+#define RG_MTKAIF1_TXIF_FIFO_RSP_MASK_SFT (0x7 << 12)
+#define RG_MTKAIF1_TXIF_SYNC_WORD1_SFT 4
+#define RG_MTKAIF1_TXIF_SYNC_WORD1_MASK 0x7
+#define RG_MTKAIF1_TXIF_SYNC_WORD1_MASK_SFT (0x7 << 4)
+#define RG_MTKAIF1_TXIF_SYNC_WORD0_SFT 0
+#define RG_MTKAIF1_TXIF_SYNC_WORD0_MASK 0x7
+#define RG_MTKAIF1_TXIF_SYNC_WORD0_MASK_SFT (0x7 << 0)
+
+/* AFE_MTKAIF1_RX_CFG0 */
+#define RG_MTKAIF1_RXIF_VOICE_MODE_SFT 20
+#define RG_MTKAIF1_RXIF_VOICE_MODE_MASK 0xf
+#define RG_MTKAIF1_RXIF_VOICE_MODE_MASK_SFT (0xf << 20)
+#define RG_MTKAIF1_RXIF_DETECT_ON_SFT 16
+#define RG_MTKAIF1_RXIF_DETECT_ON_MASK 0x1
+#define RG_MTKAIF1_RXIF_DETECT_ON_MASK_SFT (0x1 << 16)
+#define RG_MTKAIF1_RXIF_DATA_BIT_SFT 8
+#define RG_MTKAIF1_RXIF_DATA_BIT_MASK 0x7
+#define RG_MTKAIF1_RXIF_DATA_BIT_MASK_SFT (0x7 << 8)
+#define RG_MTKAIF1_RXIF_FIFO_RSP_SFT 4
+#define RG_MTKAIF1_RXIF_FIFO_RSP_MASK 0x7
+#define RG_MTKAIF1_RXIF_FIFO_RSP_MASK_SFT (0x7 << 4)
+#define RG_MTKAIF1_RXIF_DATA_MODE_SFT 0
+#define RG_MTKAIF1_RXIF_DATA_MODE_MASK 0x1
+#define RG_MTKAIF1_RXIF_DATA_MODE_MASK_SFT (0x1 << 0)
+
+/* AFE_MTKAIF1_RX_CFG1 */
+#define RG_MTKAIF1_RXIF_CLEAR_SYNC_FAIL_SFT 28
+#define RG_MTKAIF1_RXIF_CLEAR_SYNC_FAIL_MASK 0x1
+#define RG_MTKAIF1_RXIF_CLEAR_SYNC_FAIL_MASK_SFT (0x1 << 28)
+#define RG_MTKAIF1_RXIF_SYNC_CNT_TABLE_SFT 16
+#define RG_MTKAIF1_RXIF_SYNC_CNT_TABLE_MASK 0xfff
+#define RG_MTKAIF1_RXIF_SYNC_CNT_TABLE_MASK_SFT (0xfff << 16)
+#define RG_MTKAIF1_RXIF_SYNC_SEARCH_TABLE_SFT 12
+#define RG_MTKAIF1_RXIF_SYNC_SEARCH_TABLE_MASK 0xf
+#define RG_MTKAIF1_RXIF_SYNC_SEARCH_TABLE_MASK_SFT (0xf << 12)
+#define RG_MTKAIF1_RXIF_INVALID_SYNC_CHECK_ROUND_SFT 8
+#define RG_MTKAIF1_RXIF_INVALID_SYNC_CHECK_ROUND_MASK 0xf
+#define RG_MTKAIF1_RXIF_INVALID_SYNC_CHECK_ROUND_MASK_SFT (0xf << 8)
+#define RG_MTKAIF1_RXIF_SYNC_CHECK_ROUND_SFT 4
+#define RG_MTKAIF1_RXIF_SYNC_CHECK_ROUND_MASK 0xf
+#define RG_MTKAIF1_RXIF_SYNC_CHECK_ROUND_MASK_SFT (0xf << 4)
+
+/* AFE_MTKAIF1_RX_CFG2 */
+#define RG_MTKAIF1_RXIF_SYNC_WORD1_DISABLE_SFT 27
+#define RG_MTKAIF1_RXIF_SYNC_WORD1_DISABLE_MASK 0x1
+#define RG_MTKAIF1_RXIF_SYNC_WORD1_DISABLE_MASK_SFT (0x1 << 27)
+#define RG_MTKAIF1_RXIF_SYNC_WORD1_SFT 24
+#define RG_MTKAIF1_RXIF_SYNC_WORD1_MASK 0x7
+#define RG_MTKAIF1_RXIF_SYNC_WORD1_MASK_SFT (0x7 << 24)
+#define RG_MTKAIF1_RXIF_SYNC_WORD0_DISABLE_SFT 23
+#define RG_MTKAIF1_RXIF_SYNC_WORD0_DISABLE_MASK 0x1
+#define RG_MTKAIF1_RXIF_SYNC_WORD0_DISABLE_MASK_SFT (0x1 << 23)
+#define RG_MTKAIF1_RXIF_SYNC_WORD0_SFT 20
+#define RG_MTKAIF1_RXIF_SYNC_WORD0_MASK 0x7
+#define RG_MTKAIF1_RXIF_SYNC_WORD0_MASK_SFT (0x7 << 20)
+#define RG_MTKAIF1_RXIF_DELAY_CYCLE_SFT 12
+#define RG_MTKAIF1_RXIF_DELAY_CYCLE_MASK 0xf
+#define RG_MTKAIF1_RXIF_DELAY_CYCLE_MASK_SFT (0xf << 12)
+#define RG_MTKAIF1_RXIF_DELAY_DATA_SFT 8
+#define RG_MTKAIF1_RXIF_DELAY_DATA_MASK 0x1
+#define RG_MTKAIF1_RXIF_DELAY_DATA_MASK_SFT (0x1 << 8)
+
+/* AFE_AUD_PAD_TOP_CFG0 */
+#define AUD_PAD_TOP_FIFO_RSP_SFT 4
+#define AUD_PAD_TOP_FIFO_RSP_MASK 0xf
+#define AUD_PAD_TOP_FIFO_RSP_MASK_SFT (0xf << 4)
+#define RG_RX_PROTOCOL2_SFT 3
+#define RG_RX_PROTOCOL2_MASK 0x1
+#define RG_RX_PROTOCOL2_MASK_SFT (0x1 << 3)
+#define RG_RX_FIFO_ON_SFT 0
+#define RG_RX_FIFO_ON_MASK 0x1
+#define RG_RX_FIFO_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_AUD_PAD_TOP_MON */
+#define AUD_PAD_TOP_MON_SFT 0
+#define AUD_PAD_TOP_MON_MASK 0xffff
+#define AUD_PAD_TOP_MON_MASK_SFT (0xffff << 0)
+
+/* AFE_ADDA_MTKAIFV4_TX_CFG0 */
+#define MTKAIFV4_TXIF_EN_SEL_SFT 12
+#define MTKAIFV4_TXIF_EN_SEL_MASK 0x1
+#define MTKAIFV4_TXIF_EN_SEL_MASK_SFT (0x1 << 12)
+#define MTKAIFV4_TXIF_V4_SFT 11
+#define MTKAIFV4_TXIF_V4_MASK 0x1
+#define MTKAIFV4_TXIF_V4_MASK_SFT (0x1 << 11)
+#define MTKAIFV4_ADDA6_OUT_EN_SEL_SFT 10
+#define MTKAIFV4_ADDA6_OUT_EN_SEL_MASK 0x1
+#define MTKAIFV4_ADDA6_OUT_EN_SEL_MASK_SFT (0x1 << 10)
+#define MTKAIFV4_ADDA_OUT_EN_SEL_SFT 9
+#define MTKAIFV4_ADDA_OUT_EN_SEL_MASK 0x1
+#define MTKAIFV4_ADDA_OUT_EN_SEL_MASK_SFT (0x1 << 9)
+#define MTKAIFV4_TXIF_INPUT_MODE_SFT 4
+#define MTKAIFV4_TXIF_INPUT_MODE_MASK 0x1f
+#define MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT (0x1f << 4)
+#define MTKAIFV4_TXIF_FOUR_CHANNEL_SFT 1
+#define MTKAIFV4_TXIF_FOUR_CHANNEL_MASK 0x1
+#define MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT (0x1 << 1)
+#define MTKAIFV4_TXIF_AFE_ON_SFT 0
+#define MTKAIFV4_TXIF_AFE_ON_MASK 0x1
+#define MTKAIFV4_TXIF_AFE_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA6_MTKAIFV4_TX_CFG0 */
+#define ADDA6_MTKAIFV4_TXIF_EN_SEL_SFT 12
+#define ADDA6_MTKAIFV4_TXIF_EN_SEL_MASK 0x1
+#define ADDA6_MTKAIFV4_TXIF_EN_SEL_MASK_SFT (0x1 << 12)
+#define ADDA6_MTKAIFV4_TXIF_INPUT_MODE_SFT 4
+#define ADDA6_MTKAIFV4_TXIF_INPUT_MODE_MASK 0x1f
+#define ADDA6_MTKAIFV4_TXIF_INPUT_MODE_MASK_SFT (0x1f << 4)
+#define ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_SFT 1
+#define ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_MASK 0x1
+#define ADDA6_MTKAIFV4_TXIF_FOUR_CHANNEL_MASK_SFT (0x1 << 1)
+#define ADDA6_MTKAIFV4_TXIF_AFE_ON_SFT 0
+#define ADDA6_MTKAIFV4_TXIF_AFE_ON_MASK 0x1
+#define ADDA6_MTKAIFV4_TXIF_AFE_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA_MTKAIFV4_RX_CFG0 */
+#define MTKAIFV4_RXIF_CLKINV_SFT 31
+#define MTKAIFV4_RXIF_CLKINV_MASK 0x1
+#define MTKAIFV4_RXIF_CLKINV_MASK_SFT (0x1 << 31)
+#define MTKAIFV4_RXIF_LOOPBACK_MODE_SFT 28
+#define MTKAIFV4_RXIF_LOOPBACK_MODE_MASK 0x1
+#define MTKAIFV4_RXIF_LOOPBACK_MODE_MASK_SFT (0x1 << 28)
+#define MTKAIFV4_UL_CH7CH8_IN_EN_SEL_SFT 19
+#define MTKAIFV4_UL_CH7CH8_IN_EN_SEL_MASK 0x1
+#define MTKAIFV4_UL_CH7CH8_IN_EN_SEL_MASK_SFT (0x1 << 19)
+#define MTKAIFV4_UL_CH5CH6_IN_EN_SEL_SFT 18
+#define MTKAIFV4_UL_CH5CH6_IN_EN_SEL_MASK 0x1
+#define MTKAIFV4_UL_CH5CH6_IN_EN_SEL_MASK_SFT (0x1 << 18)
+#define MTKAIFV4_UL_CH3CH4_IN_EN_SEL_SFT 17
+#define MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK 0x1
+#define MTKAIFV4_UL_CH3CH4_IN_EN_SEL_MASK_SFT (0x1 << 17)
+#define MTKAIFV4_UL_CH1CH2_IN_EN_SEL_SFT 16
+#define MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK 0x1
+#define MTKAIFV4_UL_CH1CH2_IN_EN_SEL_MASK_SFT (0x1 << 16)
+#define MTKAIFV4_RXIF_EN_SEL_SFT 12
+#define MTKAIFV4_RXIF_EN_SEL_MASK 0x1
+#define MTKAIFV4_RXIF_EN_SEL_MASK_SFT (0x1 << 12)
+#define MTKAIFV4_RXIF_INPUT_MODE_SFT 4
+#define MTKAIFV4_RXIF_INPUT_MODE_MASK 0x1f
+#define MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT (0x1f << 4)
+#define MTKAIFV4_RXIF_FOUR_CHANNEL_SFT 1
+#define MTKAIFV4_RXIF_FOUR_CHANNEL_MASK 0x1
+#define MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT (0x1 << 1)
+#define MTKAIFV4_RXIF_AFE_ON_SFT 0
+#define MTKAIFV4_RXIF_AFE_ON_MASK 0x1
+#define MTKAIFV4_RXIF_AFE_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA_MTKAIFV4_RX_CFG1 */
+#define MTKAIFV4_RXIF_SYNC_CNT_TABLE_SFT 17
+#define MTKAIFV4_RXIF_SYNC_CNT_TABLE_MASK 0xfff
+#define MTKAIFV4_RXIF_SYNC_CNT_TABLE_MASK_SFT (0xfff << 17)
+#define MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_SFT 12
+#define MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_MASK 0x1f
+#define MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_MASK_SFT (0x1f << 12)
+#define MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_SFT 8
+#define MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_MASK 0xf
+#define MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_MASK_SFT (0xf << 8)
+#define MTKAIFV4_RXIF_SYNC_CHECK_ROUND_SFT 4
+#define MTKAIFV4_RXIF_SYNC_CHECK_ROUND_MASK 0xf
+#define MTKAIFV4_RXIF_SYNC_CHECK_ROUND_MASK_SFT (0xf << 4)
+#define MTKAIFV4_RXIF_FIFO_RSP_SFT 1
+#define MTKAIFV4_RXIF_FIFO_RSP_MASK 0x7
+#define MTKAIFV4_RXIF_FIFO_RSP_MASK_SFT (0x7 << 1)
+#define MTKAIFV4_RXIF_SELF_DEFINE_TABLE_SFT 0
+#define MTKAIFV4_RXIF_SELF_DEFINE_TABLE_MASK 0x1
+#define MTKAIFV4_RXIF_SELF_DEFINE_TABLE_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA6_MTKAIFV4_RX_CFG0 */
+#define ADDA6_MTKAIFV4_RXIF_CLKINV_SFT 31
+#define ADDA6_MTKAIFV4_RXIF_CLKINV_MASK 0x1
+#define ADDA6_MTKAIFV4_RXIF_CLKINV_MASK_SFT (0x1 << 31)
+#define ADDA6_MTKAIFV4_RXIF_LOOPBACK_MODE_SFT 28
+#define ADDA6_MTKAIFV4_RXIF_LOOPBACK_MODE_MASK 0x1
+#define ADDA6_MTKAIFV4_RXIF_LOOPBACK_MODE_MASK_SFT (0x1 << 28)
+#define ADDA6_MTKAIFV4_RXIF_EN_SEL_SFT 12
+#define ADDA6_MTKAIFV4_RXIF_EN_SEL_MASK 0x1
+#define ADDA6_MTKAIFV4_RXIF_EN_SEL_MASK_SFT (0x1 << 12)
+#define ADDA6_MTKAIFV4_RXIF_INPUT_MODE_SFT 4
+#define ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK 0x1f
+#define ADDA6_MTKAIFV4_RXIF_INPUT_MODE_MASK_SFT (0x1f << 4)
+#define ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_SFT 1
+#define ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_MASK 0x1
+#define ADDA6_MTKAIFV4_RXIF_FOUR_CHANNEL_MASK_SFT (0x1 << 1)
+#define ADDA6_MTKAIFV4_RXIF_AFE_ON_SFT 0
+#define ADDA6_MTKAIFV4_RXIF_AFE_ON_MASK 0x1
+#define ADDA6_MTKAIFV4_RXIF_AFE_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA6_MTKAIFV4_RX_CFG1 */
+#define ADDA6_MTKAIFV4_RXIF_SYNC_CNT_TABLE_SFT 17
+#define ADDA6_MTKAIFV4_RXIF_SYNC_CNT_TABLE_MASK 0xfff
+#define ADDA6_MTKAIFV4_RXIF_SYNC_CNT_TABLE_MASK_SFT (0xfff << 17)
+#define ADDA6_MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_SFT 12
+#define ADDA6_MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_MASK 0x1f
+#define ADDA6_MTKAIFV4_RXIF_SYNC_SEARCH_TABLE_MASK_SFT (0x1f << 12)
+#define ADDA6_MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_SFT 8
+#define ADDA6_MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_MASK 0xf
+#define ADDA6_MTKAIFV4_RXIF_INVAILD_SYNC_CHECK_ROUND_MASK_SFT (0xf << 8)
+#define ADDA6_MTKAIFV4_RXIF_SYNC_CHECK_ROUND_SFT 4
+#define ADDA6_MTKAIFV4_RXIF_SYNC_CHECK_ROUND_MASK 0xf
+#define ADDA6_MTKAIFV4_RXIF_SYNC_CHECK_ROUND_MASK_SFT (0xf << 4)
+#define ADDA6_MTKAIFV4_RXIF_FIFO_RSP_SFT 1
+#define ADDA6_MTKAIFV4_RXIF_FIFO_RSP_MASK 0x7
+#define ADDA6_MTKAIFV4_RXIF_FIFO_RSP_MASK_SFT (0x7 << 1)
+#define ADDA6_MTKAIFV4_RXIF_SELF_DEFINE_TABLE_SFT 0
+#define ADDA6_MTKAIFV4_RXIF_SELF_DEFINE_TABLE_MASK 0x1
+#define ADDA6_MTKAIFV4_RXIF_SELF_DEFINE_TABLE_MASK_SFT (0x1 << 0)
+
+/* AFE_ADDA_MTKAIFV4_TX_SYNCWORD_CFG */
+#define ADDA6_MTKAIFV4_TXIF_SYNCWORD_SFT 16
+#define ADDA6_MTKAIFV4_TXIF_SYNCWORD_MASK 0xffff
+#define ADDA6_MTKAIFV4_TXIF_SYNCWORD_MASK_SFT (0xffff << 16)
+#define ADDA_MTKAIFV4_TXIF_SYNCWORD_SFT 0
+#define ADDA_MTKAIFV4_TXIF_SYNCWORD_MASK 0xffff
+#define ADDA_MTKAIFV4_TXIF_SYNCWORD_MASK_SFT (0xffff << 0)
+
+/* AFE_ADDA_MTKAIFV4_RX_SYNCWORD_CFG */
+#define ADDA6_MTKAIFV4_RXIF_SYNCWORD_SFT 16
+#define ADDA6_MTKAIFV4_RXIF_SYNCWORD_MASK 0xffff
+#define ADDA6_MTKAIFV4_RXIF_SYNCWORD_MASK_SFT (0xffff << 16)
+#define ADDA_MTKAIFV4_RXIF_SYNCWORD_SFT 0
+#define ADDA_MTKAIFV4_RXIF_SYNCWORD_MASK 0xffff
+#define ADDA_MTKAIFV4_RXIF_SYNCWORD_MASK_SFT (0xffff << 0)
+
+/* AFE_ADDA_MTKAIFV4_MON0 */
+#define MTKAIFV4_TXIF_SDATA_OUT_SFT 23
+#define MTKAIFV4_TXIF_SDATA_OUT_MASK 0x1
+#define MTKAIFV4_TXIF_SDATA_OUT_MASK_SFT (0x1 << 23)
+#define MTKAIFV4_RXIF_SDATA_IN_SFT 22
+#define MTKAIFV4_RXIF_SDATA_IN_MASK 0x1
+#define MTKAIFV4_RXIF_SDATA_IN_MASK_SFT (0x1 << 22)
+#define MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_SFT 21
+#define MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_MASK 0x1
+#define MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_MASK_SFT (0x1 << 21)
+#define MTKAIFV4_RXIF_ADC_FIFO_STATUS_SFT 0
+#define MTKAIFV4_RXIF_ADC_FIFO_STATUS_MASK 0xfff
+#define MTKAIFV4_RXIF_ADC_FIFO_STATUS_MASK_SFT (0xfff << 0)
+
+/* AFE_ADDA_MTKAIFV4_MON1 */
+#define MTKAIFV4_RXIF_OUT_CH4_SFT 24
+#define MTKAIFV4_RXIF_OUT_CH4_MASK 0xff
+#define MTKAIFV4_RXIF_OUT_CH4_MASK_SFT (0xff << 24)
+#define MTKAIFV4_RXIF_OUT_CH3_SFT 16
+#define MTKAIFV4_RXIF_OUT_CH3_MASK 0xff
+#define MTKAIFV4_RXIF_OUT_CH3_MASK_SFT (0xff << 16)
+#define MTKAIFV4_RXIF_OUT_CH2_SFT 8
+#define MTKAIFV4_RXIF_OUT_CH2_MASK 0xff
+#define MTKAIFV4_RXIF_OUT_CH2_MASK_SFT (0xff << 8)
+#define MTKAIFV4_RXIF_OUT_CH1_SFT 0
+#define MTKAIFV4_RXIF_OUT_CH1_MASK 0xff
+#define MTKAIFV4_RXIF_OUT_CH1_MASK_SFT (0xff << 0)
+
+/* AFE_ADDA6_MTKAIFV4_MON0 */
+#define ADDA6_MTKAIFV4_TXIF_SDATA_OUT_SFT 23
+#define ADDA6_MTKAIFV4_TXIF_SDATA_OUT_MASK 0x1
+#define ADDA6_MTKAIFV4_TXIF_SDATA_OUT_MASK_SFT (0x1 << 23)
+#define ADDA6_MTKAIFV4_RXIF_SDATA_IN_SFT 22
+#define ADDA6_MTKAIFV4_RXIF_SDATA_IN_MASK 0x1
+#define ADDA6_MTKAIFV4_RXIF_SDATA_IN_MASK_SFT (0x1 << 22)
+#define ADDA6_MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_SFT 21
+#define ADDA6_MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_MASK 0x1
+#define ADDA6_MTKAIFV4_RXIF_SEARCH_FAIL_FLAG_MASK_SFT (0x1 << 21)
+#define ADDA6_MTKAIFV3P3_RXIF_ADC_FIFO_STATUS_SFT 0
+#define ADDA6_MTKAIFV3P3_RXIF_ADC_FIFO_STATUS_MASK 0xfff
+#define ADDA6_MTKAIFV3P3_RXIF_ADC_FIFO_STATUS_MASK_SFT (0xfff << 0)
+
+/* ETDM_IN0_CON0 */
+#define REG_ETDM_IN_EN_SFT 0
+#define REG_ETDM_IN_EN_MASK 0x1
+#define REG_ETDM_IN_EN_MASK_SFT (0x1 << 0)
+#define REG_SYNC_MODE_SFT 1
+#define REG_SYNC_MODE_MASK 0x1
+#define REG_SYNC_MODE_MASK_SFT (0x1 << 1)
+#define REG_LSB_FIRST_SFT 3
+#define REG_LSB_FIRST_MASK 0x1
+#define REG_LSB_FIRST_MASK_SFT (0x1 << 3)
+#define REG_SOFT_RST_SFT 4
+#define REG_SOFT_RST_MASK 0x1
+#define REG_SOFT_RST_MASK_SFT (0x1 << 4)
+#define REG_SLAVE_MODE_SFT 5
+#define REG_SLAVE_MODE_MASK 0x1
+#define REG_SLAVE_MODE_MASK_SFT (0x1 << 5)
+#define REG_FMT_SFT 6
+#define REG_FMT_MASK 0x7
+#define REG_FMT_MASK_SFT (0x7 << 6)
+#define REG_LRCK_EDGE_SEL_SFT 10
+#define REG_LRCK_EDGE_SEL_MASK 0x1
+#define REG_LRCK_EDGE_SEL_MASK_SFT (0x1 << 10)
+#define REG_BIT_LENGTH_SFT 11
+#define REG_BIT_LENGTH_MASK 0x1f
+#define REG_BIT_LENGTH_MASK_SFT (0x1f << 11)
+#define REG_WORD_LENGTH_SFT 16
+#define REG_WORD_LENGTH_MASK 0x1f
+#define REG_WORD_LENGTH_MASK_SFT (0x1f << 16)
+#define REG_CH_NUM_SFT 23
+#define REG_CH_NUM_MASK 0x1f
+#define REG_CH_NUM_MASK_SFT (0x1f << 23)
+#define REG_RELATCH_1X_EN_DOMAIN_SEL_SFT 28
+#define REG_RELATCH_1X_EN_DOMAIN_SEL_MASK 0x7
+#define REG_RELATCH_1X_EN_DOMAIN_SEL_MASK_SFT (0x7 << 28)
+#define REG_VALID_TOGETHER_SFT 31
+#define REG_VALID_TOGETHER_MASK 0x1
+#define REG_VALID_TOGETHER_MASK_SFT (0x1 << 31)
+
+/* ETDM_IN0_CON1 */
+/* ETDM_IN1_CON1 */
+/* ETDM_IN2_CON1 */
+/* ETDM_IN3_CON1 */
+/* ETDM_IN4_CON1 */
+/* ETDM_IN5_CON1 */
+/* ETDM_IN6_CON1 */
+#define REG_INITIAL_COUNT_SFT 0
+#define REG_INITIAL_COUNT_MASK 0x1f
+#define REG_INITIAL_COUNT_MASK_SFT (0x1f << 0)
+#define REG_INITIAL_POINT_SFT 5
+#define REG_INITIAL_POINT_MASK 0x1f
+#define REG_INITIAL_POINT_MASK_SFT (0x1f << 5)
+#define REG_LRCK_AUTO_OFF_SFT 10
+#define REG_LRCK_AUTO_OFF_MASK 0x1
+#define REG_LRCK_AUTO_OFF_MASK_SFT (0x1 << 10)
+#define REG_BCK_AUTO_OFF_SFT 11
+#define REG_BCK_AUTO_OFF_MASK 0x1
+#define REG_BCK_AUTO_OFF_MASK_SFT (0x1 << 11)
+#define REG_INITIAL_LRCK_SFT 13
+#define REG_INITIAL_LRCK_MASK 0x1
+#define REG_INITIAL_LRCK_MASK_SFT (0x1 << 13)
+#define REG_NO_ALIGN_1X_EN_SFT 14
+#define REG_NO_ALIGN_1X_EN_MASK 0x1
+#define REG_NO_ALIGN_1X_EN_MASK_SFT (0x1 << 14)
+#define REG_LRCK_RESET_SFT 15
+#define REG_LRCK_RESET_MASK 0x1
+#define REG_LRCK_RESET_MASK_SFT (0x1 << 15)
+#define PINMUX_MCLK_CTRL_OE_SFT 16
+#define PINMUX_MCLK_CTRL_OE_MASK 0x1
+#define PINMUX_MCLK_CTRL_OE_MASK_SFT (0x1 << 16)
+#define REG_OUTPUT_CR_EN_SFT 18
+#define REG_OUTPUT_CR_EN_MASK 0x1
+#define REG_OUTPUT_CR_EN_MASK_SFT (0x1 << 18)
+#define REG_LR_ALIGN_SFT 19
+#define REG_LR_ALIGN_MASK 0x1
+#define REG_LR_ALIGN_MASK_SFT (0x1 << 19)
+#define REG_LRCK_WIDTH_SFT 20
+#define REG_LRCK_WIDTH_MASK 0x3ff
+#define REG_LRCK_WIDTH_MASK_SFT (0x3ff << 20)
+#define REG_DIRECT_INPUT_MASTER_BCK_SFT 30
+#define REG_DIRECT_INPUT_MASTER_BCK_MASK 0x1
+#define REG_DIRECT_INPUT_MASTER_BCK_MASK_SFT (0x1 << 30)
+#define REG_LRCK_AUTO_MODE_SFT 31
+#define REG_LRCK_AUTO_MODE_MASK 0x1
+#define REG_LRCK_AUTO_MODE_MASK_SFT (0x1 << 31)
+
+/* ETDM_IN0_CON2 */
+/* ETDM_IN1_CON2 */
+/* ETDM_IN2_CON2 */
+/* ETDM_IN3_CON2 */
+/* ETDM_IN4_CON2 */
+/* ETDM_IN5_CON2 */
+/* ETDM_IN6_CON2 */
+#define REG_UPDATE_POINT_SFT 0
+#define REG_UPDATE_POINT_MASK 0x1f
+#define REG_UPDATE_POINT_MASK_SFT (0x1f << 0)
+#define REG_UPDATE_GAP_SFT 5
+#define REG_UPDATE_GAP_MASK 0x1f
+#define REG_UPDATE_GAP_MASK_SFT (0x1f << 5)
+#define REG_CLOCK_SOURCE_SEL_SFT 10
+#define REG_CLOCK_SOURCE_SEL_MASK 0x7
+#define REG_CLOCK_SOURCE_SEL_MASK_SFT (0x7 << 10)
+#define REG_CK_EN_SEL_AUTO_SFT 14
+#define REG_CK_EN_SEL_AUTO_MASK 0x1
+#define REG_CK_EN_SEL_AUTO_MASK_SFT (0x1 << 14)
+#define REG_MULTI_IP_TOTAL_CHNUM_SFT 15
+#define REG_MULTI_IP_TOTAL_CHNUM_MASK 0x1f
+#define REG_MULTI_IP_TOTAL_CHNUM_MASK_SFT (0x1f << 15)
+#define REG_MASK_AUTO_SFT 20
+#define REG_MASK_AUTO_MASK 0x1
+#define REG_MASK_AUTO_MASK_SFT (0x1 << 20)
+#define REG_MASK_NUM_SFT 21
+#define REG_MASK_NUM_MASK 0x1f
+#define REG_MASK_NUM_MASK_SFT (0x1f << 21)
+#define REG_UPDATE_POINT_AUTO_SFT 26
+#define REG_UPDATE_POINT_AUTO_MASK 0x1
+#define REG_UPDATE_POINT_AUTO_MASK_SFT (0x1 << 26)
+#define REG_SDATA_DELAY_0P5T_EN_SFT 27
+#define REG_SDATA_DELAY_0P5T_EN_MASK 0x1
+#define REG_SDATA_DELAY_0P5T_EN_MASK_SFT (0x1 << 27)
+#define REG_SDATA_DELAY_BCK_INV_SFT 28
+#define REG_SDATA_DELAY_BCK_INV_MASK 0x1
+#define REG_SDATA_DELAY_BCK_INV_MASK_SFT (0x1 << 28)
+#define REG_LRCK_DELAY_0P5T_EN_SFT 29
+#define REG_LRCK_DELAY_0P5T_EN_MASK 0x1
+#define REG_LRCK_DELAY_0P5T_EN_MASK_SFT (0x1 << 29)
+#define REG_LRCK_DELAY_BCK_INV_SFT 30
+#define REG_LRCK_DELAY_BCK_INV_MASK 0x1
+#define REG_LRCK_DELAY_BCK_INV_MASK_SFT (0x1 << 30)
+#define REG_MULTI_IP_MODE_SFT 31
+#define REG_MULTI_IP_MODE_MASK 0x1
+#define REG_MULTI_IP_MODE_MASK_SFT (0x1 << 31)
+
+/* ETDM_IN0_CON3 */
+/* ETDM_IN1_CON3 */
+/* ETDM_IN2_CON3 */
+/* ETDM_IN3_CON3 */
+/* ETDM_IN4_CON3 */
+/* ETDM_IN5_CON3 */
+/* ETDM_IN6_CON3 */
+#define REG_DISABLE_OUT_SFT 0
+#define REG_DISABLE_OUT_MASK 0xffff
+#define REG_DISABLE_OUT_MASK_SFT (0xffff << 0)
+#define REG_RJ_DATA_RIGHT_ALIGN_SFT 16
+#define REG_RJ_DATA_RIGHT_ALIGN_MASK 0x1
+#define REG_RJ_DATA_RIGHT_ALIGN_MASK_SFT (0x1 << 16)
+#define REG_MONITOR_SEL_SFT 17
+#define REG_MONITOR_SEL_MASK 0x3
+#define REG_MONITOR_SEL_MASK_SFT (0x3 << 17)
+#define REG_CNT_UPPER_LIMIT_SFT 19
+#define REG_CNT_UPPER_LIMIT_MASK 0x3f
+#define REG_CNT_UPPER_LIMIT_MASK_SFT (0x3f << 19)
+#define REG_COMPACT_SAMPLE_END_DIS_SFT 25
+#define REG_COMPACT_SAMPLE_END_DIS_MASK 0x1
+#define REG_COMPACT_SAMPLE_END_DIS_MASK_SFT (0x1 << 25)
+#define REG_FS_TIMING_SEL_SFT 26
+#define REG_FS_TIMING_SEL_MASK 0x1f
+#define REG_FS_TIMING_SEL_MASK_SFT (0x1f << 26)
+#define REG_SAMPLE_END_MODE_SFT 31
+#define REG_SAMPLE_END_MODE_MASK 0x1
+#define REG_SAMPLE_END_MODE_MASK_SFT (0x1 << 31)
+
+/* ETDM_IN0_CON4 */
+/* ETDM_IN1_CON4 */
+/* ETDM_IN2_CON4 */
+/* ETDM_IN3_CON4 */
+/* ETDM_IN4_CON4 */
+/* ETDM_IN5_CON4 */
+/* ETDM_IN6_CON4 */
+#define REG_ALWAYS_OPEN_1X_EN_SFT 31
+#define REG_ALWAYS_OPEN_1X_EN_MASK 0x1
+#define REG_ALWAYS_OPEN_1X_EN_MASK_SFT (0x1 << 31)
+#define REG_WAIT_LAST_SAMPLE_SFT 30
+#define REG_WAIT_LAST_SAMPLE_MASK 0x1
+#define REG_WAIT_LAST_SAMPLE_MASK_SFT (0x1 << 30)
+#define REG_SAMPLE_END_POINT_SFT 25
+#define REG_SAMPLE_END_POINT_MASK 0x1f
+#define REG_SAMPLE_END_POINT_MASK_SFT (0x1f << 25)
+#define REG_RELATCH_1X_EN_SEL_SFT 20
+#define REG_RELATCH_1X_EN_SEL_MASK 0x1f
+#define REG_RELATCH_1X_EN_SEL_MASK_SFT (0x1f << 20)
+#define REG_MASTER_WS_INV_SFT 19
+#define REG_MASTER_WS_INV_MASK 0x1
+#define REG_MASTER_WS_INV_MASK_SFT (0x1 << 19)
+#define REG_MASTER_BCK_INV_SFT 18
+#define REG_MASTER_BCK_INV_MASK 0x1
+#define REG_MASTER_BCK_INV_MASK_SFT (0x1 << 18)
+#define REG_SLAVE_LRCK_INV_SFT 17
+#define REG_SLAVE_LRCK_INV_MASK 0x1
+#define REG_SLAVE_LRCK_INV_MASK_SFT (0x1 << 17)
+#define REG_SLAVE_BCK_INV_SFT 16
+#define REG_SLAVE_BCK_INV_MASK 0x1
+#define REG_SLAVE_BCK_INV_MASK_SFT (0x1 << 16)
+#define REG_REPACK_CHNUM_SFT 12
+#define REG_REPACK_CHNUM_MASK 0xf
+#define REG_REPACK_CHNUM_MASK_SFT (0xf << 12)
+#define REG_ASYNC_RESET_SFT 11
+#define REG_ASYNC_RESET_MASK 0x1
+#define REG_ASYNC_RESET_MASK_SFT (0x1 << 11)
+#define REG_REPACK_WORD_LENGTH_SFT 9
+#define REG_REPACK_WORD_LENGTH_MASK 0x3
+#define REG_REPACK_WORD_LENGTH_MASK_SFT (0x3 << 9)
+#define REG_REPACK_AUTO_MODE_SFT 8
+#define REG_REPACK_AUTO_MODE_MASK 0x1
+#define REG_REPACK_AUTO_MODE_MASK_SFT (0x1 << 8)
+#define REG_REPACK_MODE_SFT 0
+#define REG_REPACK_MODE_MASK 0x3f
+#define REG_REPACK_MODE_MASK_SFT (0x3f << 0)
+
+/* ETDM_IN0_CON5 */
+/* ETDM_IN1_CON5 */
+/* ETDM_IN2_CON5 */
+/* ETDM_IN3_CON5 */
+/* ETDM_IN4_CON5 */
+/* ETDM_IN5_CON5 */
+/* ETDM_IN6_CON5 */
+#define REG_LR_SWAP_SFT 16
+#define REG_LR_SWAP_MASK 0xffff
+#define REG_LR_SWAP_MASK_SFT (0xffff << 16)
+#define REG_ODD_FLAG_EN_SFT 0
+#define REG_ODD_FLAG_EN_MASK 0xffff
+#define REG_ODD_FLAG_EN_MASK_SFT (0xffff << 0)
+
+/* ETDM_IN0_CON6 */
+/* ETDM_IN1_CON6 */
+/* ETDM_IN2_CON6 */
+/* ETDM_IN3_CON6 */
+/* ETDM_IN4_CON6 */
+/* ETDM_IN5_CON6 */
+/* ETDM_IN6_CON6 */
+#define LCH_DATA_REG_SFT 0
+#define LCH_DATA_REG_MASK 0xffffffff
+#define LCH_DATA_REG_MASK_SFT (0xffffffff << 0)
+
+/* ETDM_IN0_CON7 */
+/* ETDM_IN1_CON7 */
+/* ETDM_IN2_CON7 */
+/* ETDM_IN3_CON7 */
+/* ETDM_IN4_CON7 */
+/* ETDM_IN5_CON7 */
+/* ETDM_IN6_CON7 */
+#define RCH_DATA_REG_SFT 0
+#define RCH_DATA_REG_MASK 0xffffffff
+#define RCH_DATA_REG_MASK_SFT (0xffffffff << 0)
+
+/* ETDM_IN0_CON8 */
+/* ETDM_IN1_CON8 */
+/* ETDM_IN2_CON8 */
+/* ETDM_IN3_CON8 */
+/* ETDM_IN4_CON8 */
+/* ETDM_IN5_CON8 */
+/* ETDM_IN6_CON8 */
+#define REG_AFIFO_THRESHOLD_SFT 29
+#define REG_AFIFO_THRESHOLD_MASK 0x3
+#define REG_AFIFO_THRESHOLD_MASK_SFT (0x3 << 29)
+#define REG_CK_EN_SEL_MANUAL_SFT 16
+#define REG_CK_EN_SEL_MANUAL_MASK 0x3ff
+#define REG_CK_EN_SEL_MANUAL_MASK_SFT (0x3ff << 16)
+#define REG_AFIFO_SW_RESET_SFT 15
+#define REG_AFIFO_SW_RESET_MASK 0x1
+#define REG_AFIFO_SW_RESET_MASK_SFT (0x1 << 15)
+#define REG_AFIFO_RESET_SEL_SFT 14
+#define REG_AFIFO_RESET_SEL_MASK 0x1
+#define REG_AFIFO_RESET_SEL_MASK_SFT (0x1 << 14)
+#define REG_AFIFO_AUTO_RESET_DIS_SFT 9
+#define REG_AFIFO_AUTO_RESET_DIS_MASK 0x1
+#define REG_AFIFO_AUTO_RESET_DIS_MASK_SFT (0x1 << 9)
+#define REG_ETDM_USE_AFIFO_SFT 8
+#define REG_ETDM_USE_AFIFO_MASK 0x1
+#define REG_ETDM_USE_AFIFO_MASK_SFT (0x1 << 8)
+#define REG_AFIFO_CLOCK_DOMAIN_SEL_SFT 5
+#define REG_AFIFO_CLOCK_DOMAIN_SEL_MASK 0x7
+#define REG_AFIFO_CLOCK_DOMAIN_SEL_MASK_SFT (0x7 << 5)
+#define REG_AFIFO_MODE_SFT 0
+#define REG_AFIFO_MODE_MASK 0x1f
+#define REG_AFIFO_MODE_MASK_SFT (0x1f << 0)
+
+/* ETDM_IN0_CON9 */
+/* ETDM_IN1_CON9 */
+/* ETDM_IN2_CON9 */
+/* ETDM_IN3_CON9 */
+/* ETDM_IN4_CON9 */
+/* ETDM_IN5_CON9 */
+/* ETDM_IN6_CON9 */
+#define REG_OUT2LATCH_TIME_SFT 10
+#define REG_OUT2LATCH_TIME_MASK 0x1f
+#define REG_OUT2LATCH_TIME_MASK_SFT (0x1f << 10)
+#define REG_ALMOST_END_BIT_COUNT_SFT 5
+#define REG_ALMOST_END_BIT_COUNT_MASK 0x1f
+#define REG_ALMOST_END_BIT_COUNT_MASK_SFT (0x1f << 5)
+#define REG_ALMOST_END_CH_COUNT_SFT 0
+#define REG_ALMOST_END_CH_COUNT_MASK 0x1f
+#define REG_ALMOST_END_CH_COUNT_MASK_SFT (0x1f << 0)
+
+/* ETDM_IN0_MON */
+/* ETDM_IN1_MON */
+/* ETDM_IN2_MON */
+/* ETDM_IN3_MON */
+/* ETDM_IN4_MON */
+/* ETDM_IN5_MON */
+/* ETDM_IN6_MON */
+#define LRCK_INV_SFT 30
+#define LRCK_INV_MASK 0x1
+#define LRCK_INV_MASK_SFT (0x1 << 30)
+#define EN_SYNC_OUT_SFT 29
+#define EN_SYNC_OUT_MASK 0x1
+#define EN_SYNC_OUT_MASK_SFT (0x1 << 29)
+#define HOPPING_EN_SYNC_OUT_PRE_SFT 28
+#define HOPPING_EN_SYNC_OUT_PRE_MASK 0x1
+#define HOPPING_EN_SYNC_OUT_PRE_MASK_SFT (0x1 << 28)
+#define WFULL_SFT 27
+#define WFULL_MASK 0x1
+#define WFULL_MASK_SFT (0x1 << 27)
+#define REMPTY_SFT 26
+#define REMPTY_MASK 0x1
+#define REMPTY_MASK_SFT (0x1 << 26)
+#define ETDM_2X_CK_EN_SFT 25
+#define ETDM_2X_CK_EN_MASK 0x1
+#define ETDM_2X_CK_EN_MASK_SFT (0x1 << 25)
+#define ETDM_1X_CK_EN_SFT 24
+#define ETDM_1X_CK_EN_MASK 0x1
+#define ETDM_1X_CK_EN_MASK_SFT (0x1 << 24)
+#define SDATA0_SFT 23
+#define SDATA0_MASK 0x1
+#define SDATA0_MASK_SFT (0x1 << 23)
+#define CURRENT_STATUS_SFT 21
+#define CURRENT_STATUS_MASK 0x3
+#define CURRENT_STATUS_MASK_SFT (0x3 << 21)
+#define BIT_POINT_SFT 16
+#define BIT_POINT_MASK 0x1f
+#define BIT_POINT_MASK_SFT (0x1f << 16)
+#define BIT_CH_COUNT_SFT 10
+#define BIT_CH_COUNT_MASK 0x3f
+#define BIT_CH_COUNT_MASK_SFT (0x3f << 10)
+#define BIT_COUNT_SFT 5
+#define BIT_COUNT_MASK 0x1f
+#define BIT_COUNT_MASK_SFT (0x1f << 5)
+#define CH_COUNT_SFT 0
+#define CH_COUNT_MASK 0x1f
+#define CH_COUNT_MASK_SFT (0x1f << 0)
+
+/* ETDM_OUT0_CON0 */
+/* ETDM_OUT1_CON0 */
+/* ETDM_OUT2_CON0 */
+/* ETDM_OUT3_CON0 */
+/* ETDM_OUT4_CON0 */
+/* ETDM_OUT5_CON0 */
+/* ETDM_OUT6_CON0 */
+#define OUT_REG_ETDM_OUT_EN_SFT 0
+#define OUT_REG_ETDM_OUT_EN_MASK 0x1
+#define OUT_REG_ETDM_OUT_EN_MASK_SFT (0x1 << 0)
+#define OUT_REG_SYNC_MODE_SFT 1
+#define OUT_REG_SYNC_MODE_MASK 0x1
+#define OUT_REG_SYNC_MODE_MASK_SFT (0x1 << 1)
+#define OUT_REG_LSB_FIRST_SFT 3
+#define OUT_REG_LSB_FIRST_MASK 0x1
+#define OUT_REG_LSB_FIRST_MASK_SFT (0x1 << 3)
+#define OUT_REG_SOFT_RST_SFT 4
+#define OUT_REG_SOFT_RST_MASK 0x1
+#define OUT_REG_SOFT_RST_MASK_SFT (0x1 << 4)
+#define OUT_REG_SLAVE_MODE_SFT 5
+#define OUT_REG_SLAVE_MODE_MASK 0x1
+#define OUT_REG_SLAVE_MODE_MASK_SFT (0x1 << 5)
+#define OUT_REG_FMT_SFT 6
+#define OUT_REG_FMT_MASK 0x7
+#define OUT_REG_FMT_MASK_SFT (0x7 << 6)
+#define OUT_REG_LRCK_EDGE_SEL_SFT 10
+#define OUT_REG_LRCK_EDGE_SEL_MASK 0x1
+#define OUT_REG_LRCK_EDGE_SEL_MASK_SFT (0x1 << 10)
+#define OUT_REG_BIT_LENGTH_SFT 11
+#define OUT_REG_BIT_LENGTH_MASK 0x1f
+#define OUT_REG_BIT_LENGTH_MASK_SFT (0x1f << 11)
+#define OUT_REG_WORD_LENGTH_SFT 16
+#define OUT_REG_WORD_LENGTH_MASK 0x1f
+#define OUT_REG_WORD_LENGTH_MASK_SFT (0x1f << 16)
+#define OUT_REG_CH_NUM_SFT 23
+#define OUT_REG_CH_NUM_MASK 0x1f
+#define OUT_REG_CH_NUM_MASK_SFT (0x1f << 23)
+#define OUT_REG_RELATCH_DOMAIN_SEL_SFT 28
+#define OUT_REG_RELATCH_DOMAIN_SEL_MASK 0x7
+#define OUT_REG_RELATCH_DOMAIN_SEL_MASK_SFT (0x7 << 28)
+#define OUT_REG_VALID_TOGETHER_SFT 31
+#define OUT_REG_VALID_TOGETHER_MASK 0x1
+#define OUT_REG_VALID_TOGETHER_MASK_SFT (0x1 << 31)
+
+/* ETDM_OUT0_CON1 */
+/* ETDM_OUT1_CON1 */
+/* ETDM_OUT2_CON1 */
+/* ETDM_OUT3_CON1 */
+/* ETDM_OUT4_CON1 */
+/* ETDM_OUT5_CON1 */
+/* ETDM_OUT6_CON1 */
+#define OUT_REG_INITIAL_COUNT_SFT 0
+#define OUT_REG_INITIAL_COUNT_MASK 0x1f
+#define OUT_REG_INITIAL_COUNT_MASK_SFT (0x1f << 0)
+#define OUT_REG_INITIAL_POINT_SFT 5
+#define OUT_REG_INITIAL_POINT_MASK 0x1f
+#define OUT_REG_INITIAL_POINT_MASK_SFT (0x1f << 5)
+#define OUT_REG_LRCK_AUTO_OFF_SFT 10
+#define OUT_REG_LRCK_AUTO_OFF_MASK 0x1
+#define OUT_REG_LRCK_AUTO_OFF_MASK_SFT (0x1 << 10)
+#define OUT_REG_BCK_AUTO_OFF_SFT 11
+#define OUT_REG_BCK_AUTO_OFF_MASK 0x1
+#define OUT_REG_BCK_AUTO_OFF_MASK_SFT (0x1 << 11)
+#define OUT_REG_INITIAL_LRCK_SFT 13
+#define OUT_REG_INITIAL_LRCK_MASK 0x1
+#define OUT_REG_INITIAL_LRCK_MASK_SFT (0x1 << 13)
+#define OUT_REG_NO_ALIGN_1X_EN_SFT 14
+#define OUT_REG_NO_ALIGN_1X_EN_MASK 0x1
+#define OUT_REG_NO_ALIGN_1X_EN_MASK_SFT (0x1 << 14)
+#define OUT_REG_LRCK_RESET_SFT 15
+#define OUT_REG_LRCK_RESET_MASK 0x1
+#define OUT_REG_LRCK_RESET_MASK_SFT (0x1 << 15)
+#define OUT_PINMUX_MCLK_CTRL_OE_SFT 16
+#define OUT_PINMUX_MCLK_CTRL_OE_MASK 0x1
+#define OUT_PINMUX_MCLK_CTRL_OE_MASK_SFT (0x1 << 16)
+#define OUT_REG_OUTPUT_CR_EN_SFT 18
+#define OUT_REG_OUTPUT_CR_EN_MASK 0x1
+#define OUT_REG_OUTPUT_CR_EN_MASK_SFT (0x1 << 18)
+#define OUT_REG_LRCK_WIDTH_SFT 19
+#define OUT_REG_LRCK_WIDTH_MASK 0x3ff
+#define OUT_REG_LRCK_WIDTH_MASK_SFT (0x3ff << 19)
+#define OUT_REG_LRCK_AUTO_MODE_SFT 29
+#define OUT_REG_LRCK_AUTO_MODE_MASK 0x1
+#define OUT_REG_LRCK_AUTO_MODE_MASK_SFT (0x1 << 29)
+#define OUT_REG_DIRECT_INPUT_MASTER_BCK_SFT 30
+#define OUT_REG_DIRECT_INPUT_MASTER_BCK_MASK 0x1
+#define OUT_REG_DIRECT_INPUT_MASTER_BCK_MASK_SFT (0x1 << 30)
+#define OUT_REG_16B_COMPACT_MODE_SFT 31
+#define OUT_REG_16B_COMPACT_MODE_MASK 0x1
+#define OUT_REG_16B_COMPACT_MODE_MASK_SFT (0x1 << 31)
+
+/* ETDM_OUT0_CON2 */
+/* ETDM_OUT1_CON2 */
+/* ETDM_OUT2_CON2 */
+/* ETDM_OUT3_CON2 */
+/* ETDM_OUT4_CON2 */
+/* ETDM_OUT5_CON2 */
+/* ETDM_OUT6_CON2 */
+#define OUT_REG_IN2LATCH_TIME_SFT 0
+#define OUT_REG_IN2LATCH_TIME_MASK 0x1f
+#define OUT_REG_IN2LATCH_TIME_MASK_SFT (0x1f << 0)
+#define OUT_REG_MASK_NUM_SFT 5
+#define OUT_REG_MASK_NUM_MASK 0x1f
+#define OUT_REG_MASK_NUM_MASK_SFT (0x1f << 5)
+#define OUT_REG_MASK_AUTO_SFT 10
+#define OUT_REG_MASK_AUTO_MASK 0x1
+#define OUT_REG_MASK_AUTO_MASK_SFT (0x1 << 10)
+#define OUT_REG_SDATA_SHIFT_SFT 11
+#define OUT_REG_SDATA_SHIFT_MASK 0x3
+#define OUT_REG_SDATA_SHIFT_MASK_SFT (0x3 << 11)
+#define OUT_REG_ALMOST_END_BIT_COUNT_SFT 13
+#define OUT_REG_ALMOST_END_BIT_COUNT_MASK 0x1f
+#define OUT_REG_ALMOST_END_BIT_COUNT_MASK_SFT (0x1f << 13)
+#define OUT_REG_SDATA_CON_SFT 18
+#define OUT_REG_SDATA_CON_MASK 0x3
+#define OUT_REG_SDATA_CON_MASK_SFT (0x3 << 18)
+#define OUT_REG_REDUNDANT_0_SFT 20
+#define OUT_REG_REDUNDANT_0_MASK 0x1
+#define OUT_REG_REDUNDANT_0_MASK_SFT (0x1 << 20)
+#define OUT_REG_SDATA_AUTO_OFF_SFT 21
+#define OUT_REG_SDATA_AUTO_OFF_MASK 0x1
+#define OUT_REG_SDATA_AUTO_OFF_MASK_SFT (0x1 << 21)
+#define OUT_REG_BCK_OFF_TIME_SFT 22
+#define OUT_REG_BCK_OFF_TIME_MASK 0x3
+#define OUT_REG_BCK_OFF_TIME_MASK_SFT (0x3 << 22)
+#define OUT_REG_MONITOR_SEL_SFT 24
+#define OUT_REG_MONITOR_SEL_MASK 0x3
+#define OUT_REG_MONITOR_SEL_MASK_SFT (0x3 << 24)
+#define OUT_REG_SHIFT_AUTO_SFT 26
+#define OUT_REG_SHIFT_AUTO_MASK 0x1
+#define OUT_REG_SHIFT_AUTO_MASK_SFT (0x1 << 26)
+#define OUT_REG_SDATA_DELAY_0P5T_EN_SFT 27
+#define OUT_REG_SDATA_DELAY_0P5T_EN_MASK 0x1
+#define OUT_REG_SDATA_DELAY_0P5T_EN_MASK_SFT (0x1 << 27)
+#define OUT_REG_SDATA_DELAY_BCK_INV_SFT 28
+#define OUT_REG_SDATA_DELAY_BCK_INV_MASK 0x1
+#define OUT_REG_SDATA_DELAY_BCK_INV_MASK_SFT (0x1 << 28)
+#define OUT_REG_LRCK_DELAY_0P5T_EN_SFT 29
+#define OUT_REG_LRCK_DELAY_0P5T_EN_MASK 0x1
+#define OUT_REG_LRCK_DELAY_0P5T_EN_MASK_SFT (0x1 << 29)
+#define OUT_REG_LRCK_DELAY_BCK_INV_SFT 30
+#define OUT_REG_LRCK_DELAY_BCK_INV_MASK 0x1
+#define OUT_REG_LRCK_DELAY_BCK_INV_MASK_SFT (0x1 << 30)
+#define OUT_REG_OFF_CR_EN_SFT 31
+#define OUT_REG_OFF_CR_EN_MASK 0x1
+#define OUT_REG_OFF_CR_EN_MASK_SFT (0x1 << 31)
+
+/* ETDM_OUT0_CON3 */
+/* ETDM_OUT1_CON3 */
+/* ETDM_OUT2_CON3 */
+/* ETDM_OUT3_CON3 */
+/* ETDM_OUT4_CON3 */
+/* ETDM_OUT5_CON3 */
+/* ETDM_OUT6_CON3 */
+#define OUT_REG_START_CH_PAIR0_SFT 0
+#define OUT_REG_START_CH_PAIR0_MASK 0xf
+#define OUT_REG_START_CH_PAIR0_MASK_SFT (0xf << 0)
+#define OUT_REG_START_CH_PAIR1_SFT 4
+#define OUT_REG_START_CH_PAIR1_MASK 0xf
+#define OUT_REG_START_CH_PAIR1_MASK_SFT (0xf << 4)
+#define OUT_REG_START_CH_PAIR2_SFT 8
+#define OUT_REG_START_CH_PAIR2_MASK 0xf
+#define OUT_REG_START_CH_PAIR2_MASK_SFT (0xf << 8)
+#define OUT_REG_START_CH_PAIR3_SFT 12
+#define OUT_REG_START_CH_PAIR3_MASK 0xf
+#define OUT_REG_START_CH_PAIR3_MASK_SFT (0xf << 12)
+#define OUT_REG_START_CH_PAIR4_SFT 16
+#define OUT_REG_START_CH_PAIR4_MASK 0xf
+#define OUT_REG_START_CH_PAIR4_MASK_SFT (0xf << 16)
+#define OUT_REG_START_CH_PAIR5_SFT 20
+#define OUT_REG_START_CH_PAIR5_MASK 0xf
+#define OUT_REG_START_CH_PAIR5_MASK_SFT (0xf << 20)
+#define OUT_REG_START_CH_PAIR6_SFT 24
+#define OUT_REG_START_CH_PAIR6_MASK 0xf
+#define OUT_REG_START_CH_PAIR6_MASK_SFT (0xf << 24)
+#define OUT_REG_START_CH_PAIR7_SFT 28
+#define OUT_REG_START_CH_PAIR7_MASK 0xf
+#define OUT_REG_START_CH_PAIR7_MASK_SFT (0xf << 28)
+
+/* ETDM_OUT0_CON4 */
+/* ETDM_OUT1_CON4 */
+/* ETDM_OUT2_CON4 */
+/* ETDM_OUT3_CON4 */
+/* ETDM_OUT4_CON4 */
+/* ETDM_OUT5_CON4 */
+/* ETDM_OUT6_CON4 */
+#define OUT_REG_FS_TIMING_SEL_SFT 0
+#define OUT_REG_FS_TIMING_SEL_MASK 0x1f
+#define OUT_REG_FS_TIMING_SEL_MASK_SFT (0x1f << 0)
+#define OUT_REG_CLOCK_SOURCE_SEL_SFT 6
+#define OUT_REG_CLOCK_SOURCE_SEL_MASK 0x7
+#define OUT_REG_CLOCK_SOURCE_SEL_MASK_SFT (0x7 << 6)
+#define OUT_REG_CK_EN_SEL_AUTO_SFT 10
+#define OUT_REG_CK_EN_SEL_AUTO_MASK 0x1
+#define OUT_REG_CK_EN_SEL_AUTO_MASK_SFT (0x1 << 10)
+#define OUT_REG_ASYNC_RESET_SFT 11
+#define OUT_REG_ASYNC_RESET_MASK 0x1
+#define OUT_REG_ASYNC_RESET_MASK_SFT (0x1 << 11)
+#define OUT_REG_CK_EN_SEL_MANUAL_SFT 14
+#define OUT_REG_CK_EN_SEL_MANUAL_MASK 0x3ff
+#define OUT_REG_CK_EN_SEL_MANUAL_MASK_SFT (0x3ff << 14)
+#define OUT_REG_RELATCH_EN_SEL_SFT 24
+#define OUT_REG_RELATCH_EN_SEL_MASK 0x1f
+#define OUT_REG_RELATCH_EN_SEL_MASK_SFT (0x1f << 24)
+#define OUT_REG_WAIT_LAST_SAMPLE_SFT 30
+#define OUT_REG_WAIT_LAST_SAMPLE_MASK 0x1
+#define OUT_REG_WAIT_LAST_SAMPLE_MASK_SFT (0x1 << 30)
+#define OUT_REG_ALWAYS_OPEN_1X_EN_SFT 31
+#define OUT_REG_ALWAYS_OPEN_1X_EN_MASK 0x1
+#define OUT_REG_ALWAYS_OPEN_1X_EN_MASK_SFT (0x1 << 31)
+
+/* ETDM_OUT0_CON5 */
+/* ETDM_OUT1_CON5 */
+/* ETDM_OUT2_CON5 */
+/* ETDM_OUT3_CON5 */
+/* ETDM_OUT4_CON5 */
+/* ETDM_OUT5_CON5 */
+/* ETDM_OUT6_CON5 */
+#define OUT_REG_REPACK_BITNUM_SFT 0
+#define OUT_REG_REPACK_BITNUM_MASK 0x3
+#define OUT_REG_REPACK_BITNUM_MASK_SFT (0x3 << 0)
+#define OUT_REG_REPACK_CHNUM_SFT 2
+#define OUT_REG_REPACK_CHNUM_MASK 0xf
+#define OUT_REG_REPACK_CHNUM_MASK_SFT (0xf << 2)
+#define OUT_REG_SLAVE_BCK_INV_SFT 7
+#define OUT_REG_SLAVE_BCK_INV_MASK 0x1
+#define OUT_REG_SLAVE_BCK_INV_MASK_SFT (0x1 << 7)
+#define OUT_REG_SLAVE_LRCK_INV_SFT 8
+#define OUT_REG_SLAVE_LRCK_INV_MASK 0x1
+#define OUT_REG_SLAVE_LRCK_INV_MASK_SFT (0x1 << 8)
+#define OUT_REG_MASTER_BCK_INV_SFT 9
+#define OUT_REG_MASTER_BCK_INV_MASK 0x1
+#define OUT_REG_MASTER_BCK_INV_MASK_SFT (0x1 << 9)
+#define OUT_REG_MASTER_WS_INV_SFT 10
+#define OUT_REG_MASTER_WS_INV_MASK 0x1
+#define OUT_REG_MASTER_WS_INV_MASK_SFT (0x1 << 10)
+#define OUT_REG_REPACK_24B_MSB_ALIGN_SFT 11
+#define OUT_REG_REPACK_24B_MSB_ALIGN_MASK 0x1
+#define OUT_REG_REPACK_24B_MSB_ALIGN_MASK_SFT (0x1 << 11)
+#define OUT_REG_LR_SWAP_SFT 16
+#define OUT_REG_LR_SWAP_MASK 0xffff
+#define OUT_REG_LR_SWAP_MASK_SFT (0xffff << 16)
+
+/* ETDM_OUT0_CON6 */
+/* ETDM_OUT1_CON6 */
+/* ETDM_OUT2_CON6 */
+/* ETDM_OUT3_CON6 */
+/* ETDM_OUT4_CON6 */
+/* ETDM_OUT5_CON6 */
+/* ETDM_OUT6_CON6 */
+#define OUT_LCH_DATA_REG_SFT 0
+#define OUT_LCH_DATA_REG_MASK 0xffffffff
+#define OUT_LCH_DATA_REG_MASK_SFT (0xffffffff << 0)
+
+/* ETDM_OUT0_CON7 */
+/* ETDM_OUT1_CON7 */
+/* ETDM_OUT2_CON7 */
+/* ETDM_OUT3_CON7 */
+/* ETDM_OUT4_CON7 */
+/* ETDM_OUT5_CON7 */
+/* ETDM_OUT6_CON7 */
+#define OUT_RCH_DATA_REG_SFT 0
+#define OUT_RCH_DATA_REG_MASK 0xffffffff
+#define OUT_RCH_DATA_REG_MASK_SFT (0xffffffff << 0)
+
+/* ETDM_OUT0_CON8 */
+/* ETDM_OUT1_CON8 */
+/* ETDM_OUT2_CON8 */
+/* ETDM_OUT3_CON8 */
+/* ETDM_OUT4_CON8 */
+/* ETDM_OUT5_CON8 */
+/* ETDM_OUT6_CON8 */
+#define OUT_REG_START_CH_PAIR8_SFT 0
+#define OUT_REG_START_CH_PAIR8_MASK 0xf
+#define OUT_REG_START_CH_PAIR8_MASK_SFT (0xf << 0)
+#define OUT_REG_START_CH_PAIR9_SFT 4
+#define OUT_REG_START_CH_PAIR9_MASK 0xf
+#define OUT_REG_START_CH_PAIR9_MASK_SFT (0xf << 4)
+#define OUT_REG_START_CH_PAIR10_SFT 8
+#define OUT_REG_START_CH_PAIR10_MASK 0xf
+#define OUT_REG_START_CH_PAIR10_MASK_SFT (0xf << 8)
+#define OUT_REG_START_CH_PAIR11_SFT 12
+#define OUT_REG_START_CH_PAIR11_MASK 0xf
+#define OUT_REG_START_CH_PAIR11_MASK_SFT (0xf << 12)
+#define OUT_REG_START_CH_PAIR12_SFT 16
+#define OUT_REG_START_CH_PAIR12_MASK 0xf
+#define OUT_REG_START_CH_PAIR12_MASK_SFT (0xf << 16)
+#define OUT_REG_START_CH_PAIR13_SFT 20
+#define OUT_REG_START_CH_PAIR13_MASK 0xf
+#define OUT_REG_START_CH_PAIR13_MASK_SFT (0xf << 20)
+#define OUT_REG_START_CH_PAIR14_SFT 24
+#define OUT_REG_START_CH_PAIR14_MASK 0xf
+#define OUT_REG_START_CH_PAIR14_MASK_SFT (0xf << 24)
+#define OUT_REG_START_CH_PAIR15_SFT 28
+#define OUT_REG_START_CH_PAIR15_MASK 0xf
+#define OUT_REG_START_CH_PAIR15_MASK_SFT (0xf << 28)
+
+/* ETDM_OUT0_CON9 */
+/* ETDM_OUT1_CON9 */
+/* ETDM_OUT2_CON9 */
+/* ETDM_OUT3_CON9 */
+/* ETDM_OUT4_CON9 */
+/* ETDM_OUT5_CON9 */
+/* ETDM_OUT6_CON9 */
+#define OUT_REG_AFIFO_THRESHOLD_SFT 29
+#define OUT_REG_AFIFO_THRESHOLD_MASK 0x3
+#define OUT_REG_AFIFO_THRESHOLD_MASK_SFT (0x3 << 29)
+#define OUT_REG_AFIFO_SW_RESET_SFT 15
+#define OUT_REG_AFIFO_SW_RESET_MASK 0x1
+#define OUT_REG_AFIFO_SW_RESET_MASK_SFT (0x1 << 15)
+#define OUT_REG_AFIFO_RESET_SEL_SFT 14
+#define OUT_REG_AFIFO_RESET_SEL_MASK 0x1
+#define OUT_REG_AFIFO_RESET_SEL_MASK_SFT (0x1 << 14)
+#define OUT_REG_AFIFO_AUTO_RESET_DIS_SFT 9
+#define OUT_REG_AFIFO_AUTO_RESET_DIS_MASK 0x1
+#define OUT_REG_AFIFO_AUTO_RESET_DIS_MASK_SFT (0x1 << 9)
+#define OUT_REG_ETDM_USE_AFIFO_SFT 8
+#define OUT_REG_ETDM_USE_AFIFO_MASK 0x1
+#define OUT_REG_ETDM_USE_AFIFO_MASK_SFT (0x1 << 8)
+#define OUT_REG_AFIFO_CLOCK_DOMAIN_SEL_SFT 5
+#define OUT_REG_AFIFO_CLOCK_DOMAIN_SEL_MASK 0x7
+#define OUT_REG_AFIFO_CLOCK_DOMAIN_SEL_MASK_SFT (0x7 << 5)
+#define OUT_REG_AFIFO_MODE_SFT 0
+#define OUT_REG_AFIFO_MODE_MASK 0x1f
+#define OUT_REG_AFIFO_MODE_MASK_SFT (0x1f << 0)
+
+/* ETDM_OUT0_MON */
+/* ETDM_OUT1_MON */
+/* ETDM_OUT2_MON */
+/* ETDM_OUT3_MON */
+/* ETDM_OUT4_MON */
+/* ETDM_OUT5_MON */
+/* ETDM_OUT6_MON */
+#define LRCK_INV_SFT 30
+#define LRCK_INV_MASK 0x1
+#define LRCK_INV_MASK_SFT (0x1 << 30)
+#define EN_SYNC_OUT_SFT 29
+#define EN_SYNC_OUT_MASK 0x1
+#define EN_SYNC_OUT_MASK_SFT (0x1 << 29)
+#define HOPPING_EN_SYNC_OUT_PRE_SFT 28
+#define HOPPING_EN_SYNC_OUT_PRE_MASK 0x1
+#define HOPPING_EN_SYNC_OUT_PRE_MASK_SFT (0x1 << 28)
+#define ETDM_2X_CK_EN_SFT 25
+#define ETDM_2X_CK_EN_MASK 0x1
+#define ETDM_2X_CK_EN_MASK_SFT (0x1 << 25)
+#define ETDM_1X_CK_EN_SFT 24
+#define ETDM_1X_CK_EN_MASK 0x1
+#define ETDM_1X_CK_EN_MASK_SFT (0x1 << 24)
+#define SDATA0_SFT 23
+#define SDATA0_MASK 0x1
+#define SDATA0_MASK_SFT (0x1 << 23)
+#define CURRENT_STATUS_SFT 21
+#define CURRENT_STATUS_MASK 0x3
+#define CURRENT_STATUS_MASK_SFT (0x3 << 21)
+#define BIT_POINT_SFT 16
+#define BIT_POINT_MASK 0x1f
+#define BIT_POINT_MASK_SFT (0x1f << 16)
+#define BIT_CH_COUNT_SFT 10
+#define BIT_CH_COUNT_MASK 0x3f
+#define BIT_CH_COUNT_MASK_SFT (0x3f << 10)
+#define BIT_COUNT_SFT 5
+#define BIT_COUNT_MASK 0x1f
+#define BIT_COUNT_MASK_SFT (0x1f << 5)
+#define CH_COUNT_SFT 0
+#define CH_COUNT_MASK 0x1f
+#define CH_COUNT_MASK_SFT (0x1f << 0)
+
+/* ETDM_0_3_COWORK_CON0 */
+#define ETDM_OUT0_DATA_SEL_SFT 0
+#define ETDM_OUT0_DATA_SEL_MASK 0xf
+#define ETDM_OUT0_DATA_SEL_MASK_SFT (0xf << 0)
+#define ETDM_OUT0_SYNC_SEL_SFT 4
+#define ETDM_OUT0_SYNC_SEL_MASK 0xf
+#define ETDM_OUT0_SYNC_SEL_MASK_SFT (0xf << 4)
+#define ETDM_OUT0_SLAVE_SEL_SFT 8
+#define ETDM_OUT0_SLAVE_SEL_MASK 0xf
+#define ETDM_OUT0_SLAVE_SEL_MASK_SFT (0xf << 8)
+#define ETDM_OUT1_DATA_SEL_SFT 12
+#define ETDM_OUT1_DATA_SEL_MASK 0xf
+#define ETDM_OUT1_DATA_SEL_MASK_SFT (0xf << 12)
+#define ETDM_OUT1_SYNC_SEL_SFT 16
+#define ETDM_OUT1_SYNC_SEL_MASK 0xf
+#define ETDM_OUT1_SYNC_SEL_MASK_SFT (0xf << 16)
+#define ETDM_OUT1_SLAVE_SEL_SFT 20
+#define ETDM_OUT1_SLAVE_SEL_MASK 0xf
+#define ETDM_OUT1_SLAVE_SEL_MASK_SFT (0xf << 20)
+#define ETDM_IN0_SLAVE_SEL_SFT 24
+#define ETDM_IN0_SLAVE_SEL_MASK 0xf
+#define ETDM_IN0_SLAVE_SEL_MASK_SFT (0xf << 24)
+#define ETDM_IN0_SYNC_SEL_SFT 28
+#define ETDM_IN0_SYNC_SEL_MASK 0xf
+#define ETDM_IN0_SYNC_SEL_MASK_SFT (0xf << 28)
+
+/* ETDM_0_3_COWORK_CON1 */
+#define ETDM_IN0_SDATA0_SEL_SFT 0
+#define ETDM_IN0_SDATA0_SEL_MASK 0xf
+#define ETDM_IN0_SDATA0_SEL_MASK_SFT (0xf << 0)
+#define ETDM_IN0_SDATA1_15_SEL_SFT 4
+#define ETDM_IN0_SDATA1_15_SEL_MASK 0xf
+#define ETDM_IN0_SDATA1_15_SEL_MASK_SFT (0xf << 4)
+#define ETDM_IN1_SLAVE_SEL_SFT 8
+#define ETDM_IN1_SLAVE_SEL_MASK 0xf
+#define ETDM_IN1_SLAVE_SEL_MASK_SFT (0xf << 8)
+#define ETDM_IN1_SYNC_SEL_SFT 12
+#define ETDM_IN1_SYNC_SEL_MASK 0xf
+#define ETDM_IN1_SYNC_SEL_MASK_SFT (0xf << 12)
+#define ETDM_IN1_SDATA0_SEL_SFT 16
+#define ETDM_IN1_SDATA0_SEL_MASK 0xf
+#define ETDM_IN1_SDATA0_SEL_MASK_SFT (0xf << 16)
+#define ETDM_IN1_SDATA1_15_SEL_SFT 20
+#define ETDM_IN1_SDATA1_15_SEL_MASK 0xf
+#define ETDM_IN1_SDATA1_15_SEL_MASK_SFT (0xf << 20)
+
+/* ETDM_0_3_COWORK_CON2 */
+#define ETDM_OUT2_DATA_SEL_SFT 0
+#define ETDM_OUT2_DATA_SEL_MASK 0xf
+#define ETDM_OUT2_DATA_SEL_MASK_SFT (0xf << 0)
+#define ETDM_OUT2_SYNC_SEL_SFT 4
+#define ETDM_OUT2_SYNC_SEL_MASK 0xf
+#define ETDM_OUT2_SYNC_SEL_MASK_SFT (0xf << 4)
+#define ETDM_OUT2_SLAVE_SEL_SFT 8
+#define ETDM_OUT2_SLAVE_SEL_MASK 0xf
+#define ETDM_OUT2_SLAVE_SEL_MASK_SFT (0xf << 8)
+#define ETDM_OUT3_DATA_SEL_SFT 12
+#define ETDM_OUT3_DATA_SEL_MASK 0xf
+#define ETDM_OUT3_DATA_SEL_MASK_SFT (0xf << 12)
+#define ETDM_OUT3_SYNC_SEL_SFT 16
+#define ETDM_OUT3_SYNC_SEL_MASK 0xf
+#define ETDM_OUT3_SYNC_SEL_MASK_SFT (0xf << 16)
+#define ETDM_OUT3_SLAVE_SEL_SFT 20
+#define ETDM_OUT3_SLAVE_SEL_MASK 0xf
+#define ETDM_OUT3_SLAVE_SEL_MASK_SFT (0xf << 20)
+#define ETDM_IN2_SLAVE_SEL_SFT 24
+#define ETDM_IN2_SLAVE_SEL_MASK 0xf
+#define ETDM_IN2_SLAVE_SEL_MASK_SFT (0xf << 24)
+#define ETDM_IN2_SYNC_SEL_SFT 28
+#define ETDM_IN2_SYNC_SEL_MASK 0xf
+#define ETDM_IN2_SYNC_SEL_MASK_SFT (0xf << 28)
+
+/* ETDM_0_3_COWORK_CON3 */
+#define ETDM_IN2_SDATA0_SEL_SFT 0
+#define ETDM_IN2_SDATA0_SEL_MASK 0xf
+#define ETDM_IN2_SDATA0_SEL_MASK_SFT (0xf << 0)
+#define ETDM_IN2_SDATA1_15_SEL_SFT 4
+#define ETDM_IN2_SDATA1_15_SEL_MASK 0xf
+#define ETDM_IN2_SDATA1_15_SEL_MASK_SFT (0xf << 4)
+#define ETDM_IN3_SLAVE_SEL_SFT 8
+#define ETDM_IN3_SLAVE_SEL_MASK 0xf
+#define ETDM_IN3_SLAVE_SEL_MASK_SFT (0xf << 8)
+#define ETDM_IN3_SYNC_SEL_SFT 12
+#define ETDM_IN3_SYNC_SEL_MASK 0xf
+#define ETDM_IN3_SYNC_SEL_MASK_SFT (0xf << 12)
+#define ETDM_IN3_SDATA0_SEL_SFT 16
+#define ETDM_IN3_SDATA0_SEL_MASK 0xf
+#define ETDM_IN3_SDATA0_SEL_MASK_SFT (0xf << 16)
+#define ETDM_IN3_SDATA1_15_SEL_SFT 20
+#define ETDM_IN3_SDATA1_15_SEL_MASK 0xf
+#define ETDM_IN3_SDATA1_15_SEL_MASK_SFT (0xf << 20)
+
+/* ETDM_4_7_COWORK_CON0 */
+#define ETDM_OUT4_DATA_SEL_SFT 0
+#define ETDM_OUT4_DATA_SEL_MASK 0xf
+#define ETDM_OUT4_DATA_SEL_MASK_SFT (0xf << 0)
+#define ETDM_OUT4_SYNC_SEL_SFT 4
+#define ETDM_OUT4_SYNC_SEL_MASK 0xf
+#define ETDM_OUT4_SYNC_SEL_MASK_SFT (0xf << 4)
+#define ETDM_OUT4_SLAVE_SEL_SFT 8
+#define ETDM_OUT4_SLAVE_SEL_MASK 0xf
+#define ETDM_OUT4_SLAVE_SEL_MASK_SFT (0xf << 8)
+#define ETDM_OUT5_DATA_SEL_SFT 12
+#define ETDM_OUT5_DATA_SEL_MASK 0xf
+#define ETDM_OUT5_DATA_SEL_MASK_SFT (0xf << 12)
+#define ETDM_OUT5_SYNC_SEL_SFT 16
+#define ETDM_OUT5_SYNC_SEL_MASK 0xf
+#define ETDM_OUT5_SYNC_SEL_MASK_SFT (0xf << 16)
+#define ETDM_OUT5_SLAVE_SEL_SFT 20
+#define ETDM_OUT5_SLAVE_SEL_MASK 0xf
+#define ETDM_OUT5_SLAVE_SEL_MASK_SFT (0xf << 20)
+#define ETDM_IN4_SLAVE_SEL_SFT 24
+#define ETDM_IN4_SLAVE_SEL_MASK 0xf
+#define ETDM_IN4_SLAVE_SEL_MASK_SFT (0xf << 24)
+#define ETDM_IN4_SYNC_SEL_SFT 28
+#define ETDM_IN4_SYNC_SEL_MASK 0xf
+#define ETDM_IN4_SYNC_SEL_MASK_SFT (0xf << 28)
+
+/* ETDM_4_7_COWORK_CON1 */
+#define ETDM_IN4_SDATA0_SEL_SFT 0
+#define ETDM_IN4_SDATA0_SEL_MASK 0xf
+#define ETDM_IN4_SDATA0_SEL_MASK_SFT (0xf << 0)
+#define ETDM_IN4_SDATA1_15_SEL_SFT 4
+#define ETDM_IN4_SDATA1_15_SEL_MASK 0xf
+#define ETDM_IN4_SDATA1_15_SEL_MASK_SFT (0xf << 4)
+#define ETDM_IN5_SLAVE_SEL_SFT 8
+#define ETDM_IN5_SLAVE_SEL_MASK 0xf
+#define ETDM_IN5_SLAVE_SEL_MASK_SFT (0xf << 8)
+#define ETDM_IN5_SYNC_SEL_SFT 12
+#define ETDM_IN5_SYNC_SEL_MASK 0xf
+#define ETDM_IN5_SYNC_SEL_MASK_SFT (0xf << 12)
+#define ETDM_IN5_SDATA0_SEL_SFT 16
+#define ETDM_IN5_SDATA0_SEL_MASK 0xf
+#define ETDM_IN5_SDATA0_SEL_MASK_SFT (0xf << 16)
+#define ETDM_IN5_SDATA1_15_SEL_SFT 20
+#define ETDM_IN5_SDATA1_15_SEL_MASK 0xf
+#define ETDM_IN5_SDATA1_15_SEL_MASK_SFT (0xf << 20)
+
+/* ETDM_4_7_COWORK_CON2 */
+#define ETDM_OUT6_DATA_SEL_SFT 0
+#define ETDM_OUT6_DATA_SEL_MASK 0xf
+#define ETDM_OUT6_DATA_SEL_MASK_SFT (0xf << 0)
+#define ETDM_OUT6_SYNC_SEL_SFT 4
+#define ETDM_OUT6_SYNC_SEL_MASK 0xf
+#define ETDM_OUT6_SYNC_SEL_MASK_SFT (0xf << 4)
+#define ETDM_OUT6_SLAVE_SEL_SFT 8
+#define ETDM_OUT6_SLAVE_SEL_MASK 0xf
+#define ETDM_OUT6_SLAVE_SEL_MASK_SFT (0xf << 8)
+#define ETDM_OUT7_DATA_SEL_SFT 12
+#define ETDM_OUT7_DATA_SEL_MASK 0xf
+#define ETDM_OUT7_DATA_SEL_MASK_SFT (0xf << 12)
+#define ETDM_OUT7_SYNC_SEL_SFT 16
+#define ETDM_OUT7_SYNC_SEL_MASK 0xf
+#define ETDM_OUT7_SYNC_SEL_MASK_SFT (0xf << 16)
+#define ETDM_OUT7_SLAVE_SEL_SFT 20
+#define ETDM_OUT7_SLAVE_SEL_MASK 0xf
+#define ETDM_OUT7_SLAVE_SEL_MASK_SFT (0xf << 20)
+#define ETDM_IN6_SLAVE_SEL_SFT 24
+#define ETDM_IN6_SLAVE_SEL_MASK 0xf
+#define ETDM_IN6_SLAVE_SEL_MASK_SFT (0xf << 24)
+#define ETDM_IN6_SYNC_SEL_SFT 28
+#define ETDM_IN6_SYNC_SEL_MASK 0xf
+#define ETDM_IN6_SYNC_SEL_MASK_SFT (0xf << 28)
+
+/* ETDM_4_7_COWORK_CON3 */
+#define ETDM_IN6_SDATA0_SEL_SFT 0
+#define ETDM_IN6_SDATA0_SEL_MASK 0xf
+#define ETDM_IN6_SDATA0_SEL_MASK_SFT (0xf << 0)
+#define ETDM_IN6_SDATA1_15_SEL_SFT 4
+#define ETDM_IN6_SDATA1_15_SEL_MASK 0xf
+#define ETDM_IN6_SDATA1_15_SEL_MASK_SFT (0xf << 4)
+#define ETDM_IN7_SLAVE_SEL_SFT 8
+#define ETDM_IN7_SLAVE_SEL_MASK 0xf
+#define ETDM_IN7_SLAVE_SEL_MASK_SFT (0xf << 8)
+#define ETDM_IN7_SYNC_SEL_SFT 12
+#define ETDM_IN7_SYNC_SEL_MASK 0xf
+#define ETDM_IN7_SYNC_SEL_MASK_SFT (0xf << 12)
+#define ETDM_IN7_SDATA0_SEL_SFT 16
+#define ETDM_IN7_SDATA0_SEL_MASK 0xf
+#define ETDM_IN7_SDATA0_SEL_MASK_SFT (0xf << 16)
+#define ETDM_IN7_SDATA1_15_SEL_SFT 20
+#define ETDM_IN7_SDATA1_15_SEL_MASK 0xf
+#define ETDM_IN7_SDATA1_15_SEL_MASK_SFT (0xf << 20)
+
+/* AFE_DPTX_CON */
+#define DPTX_CHANNEL_ENABLE_SFT 8
+#define DPTX_CHANNEL_ENABLE_MASK 0xff
+#define DPTX_CHANNEL_ENABLE_MASK_SFT (0xff << 8)
+#define DPTX_REGISTER_MONITOR_SELECT_SFT 3
+#define DPTX_REGISTER_MONITOR_SELECT_MASK 0xf
+#define DPTX_REGISTER_MONITOR_SELECT_MASK_SFT (0xf << 3)
+#define DPTX_16BIT_SFT 2
+#define DPTX_16BIT_MASK 0x1
+#define DPTX_16BIT_MASK_SFT (0x1 << 2)
+#define DPTX_CHANNEL_NUMBER_SFT 1
+#define DPTX_CHANNEL_NUMBER_MASK 0x1
+#define DPTX_CHANNEL_NUMBER_MASK_SFT (0x1 << 1)
+#define DPTX_ON_SFT 0
+#define DPTX_ON_MASK 0x1
+#define DPTX_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_DPTX_MON */
+#define AFE_DPTX_MON0_SFT 0
+#define AFE_DPTX_MON0_MASK 0xffffffff
+#define AFE_DPTX_MON0_MASK_SFT (0xffffffff << 0)
+
+/* AFE_TDM_CON1 */
+#define TDM_EN_SFT 0
+#define TDM_EN_MASK 0x1
+#define TDM_EN_MASK_SFT (0x1 << 0)
+#define BCK_INVERSE_SFT 1
+#define BCK_INVERSE_MASK 0x1
+#define BCK_INVERSE_MASK_SFT (0x1 << 1)
+#define LRCK_INVERSE_SFT 2
+#define LRCK_INVERSE_MASK 0x1
+#define LRCK_INVERSE_MASK_SFT (0x1 << 2)
+#define DELAY_DATA_SFT 3
+#define DELAY_DATA_MASK 0x1
+#define DELAY_DATA_MASK_SFT (0x1 << 3)
+#define LEFT_ALIGN_SFT 4
+#define LEFT_ALIGN_MASK 0x1
+#define LEFT_ALIGN_MASK_SFT (0x1 << 4)
+#define TDM_LRCK_D0P5T_SFT 5
+#define TDM_LRCK_D0P5T_MASK 0x1
+#define TDM_LRCK_D0P5T_MASK_SFT (0x1 << 5)
+#define TDM_SDATA_D0P5T_SFT 6
+#define TDM_SDATA_D0P5T_MASK 0x1
+#define TDM_SDATA_D0P5T_MASK_SFT (0x1 << 6)
+#define WLEN_SFT 8
+#define WLEN_MASK 0x3
+#define WLEN_MASK_SFT (0x3 << 8)
+#define CHANNEL_NUM_SFT 10
+#define CHANNEL_NUM_MASK 0x3
+#define CHANNEL_NUM_MASK_SFT (0x3 << 10)
+#define CHANNEL_BCK_CYCLES_SFT 12
+#define CHANNEL_BCK_CYCLES_MASK 0x3
+#define CHANNEL_BCK_CYCLES_MASK_SFT (0x3 << 12)
+#define HDMI_CLK_INV_SEL_SFT 15
+#define HDMI_CLK_INV_SEL_MASK 0x1
+#define HDMI_CLK_INV_SEL_MASK_SFT (0x1 << 15)
+#define DAC_BIT_NUM_SFT 16
+#define DAC_BIT_NUM_MASK 0x1f
+#define DAC_BIT_NUM_MASK_SFT (0x1f << 16)
+#define LRCK_TDM_WIDTH_SFT 24
+#define LRCK_TDM_WIDTH_MASK 0xff
+#define LRCK_TDM_WIDTH_MASK_SFT (0xff << 24)
+
+/* AFE_TDM_CON2 */
+#define ST_CH_PAIR_SOUT0_SFT 0
+#define ST_CH_PAIR_SOUT0_MASK 0x7
+#define ST_CH_PAIR_SOUT0_MASK_SFT (0x7 << 0)
+#define ST_CH_PAIR_SOUT1_SFT 4
+#define ST_CH_PAIR_SOUT1_MASK 0x7
+#define ST_CH_PAIR_SOUT1_MASK_SFT (0x7 << 4)
+#define ST_CH_PAIR_SOUT2_SFT 8
+#define ST_CH_PAIR_SOUT2_MASK 0x7
+#define ST_CH_PAIR_SOUT2_MASK_SFT (0x7 << 8)
+#define ST_CH_PAIR_SOUT3_SFT 12
+#define ST_CH_PAIR_SOUT3_MASK 0x7
+#define ST_CH_PAIR_SOUT3_MASK_SFT (0x7 << 12)
+#define TDM_FIX_VALUE_SEL_SFT 16
+#define TDM_FIX_VALUE_SEL_MASK 0x1
+#define TDM_FIX_VALUE_SEL_MASK_SFT (0x1 << 16)
+#define TDM_I2S_LOOPBACK_SFT 20
+#define TDM_I2S_LOOPBACK_MASK 0x1
+#define TDM_I2S_LOOPBACK_MASK_SFT (0x1 << 20)
+#define TDM_I2S_LOOPBACK_CH_SFT 21
+#define TDM_I2S_LOOPBACK_CH_MASK 0x3
+#define TDM_I2S_LOOPBACK_CH_MASK_SFT (0x3 << 21)
+#define TDM_USE_SINEGEN_INPUT_SFT 23
+#define TDM_USE_SINEGEN_INPUT_MASK 0x1
+#define TDM_USE_SINEGEN_INPUT_MASK_SFT (0x1 << 23)
+#define TDM_FIX_VALUE_SFT 24
+#define TDM_FIX_VALUE_MASK 0xff
+#define TDM_FIX_VALUE_MASK_SFT (0xff << 24)
+
+/* AFE_TDM_CON3 */
+#define TDM_OUT_SEL_DOMAIN_SFT 29
+#define TDM_OUT_SEL_DOMAIN_MASK 0x7
+#define TDM_OUT_SEL_DOMAIN_MASK_SFT (0x7 << 29)
+#define TDM_OUT_SEL_FS_SFT 24
+#define TDM_OUT_SEL_FS_MASK 0x1f
+#define TDM_OUT_SEL_FS_MASK_SFT (0x1f << 24)
+#define TDM_OUT_MON_SEL_SFT 3
+#define TDM_OUT_MON_SEL_MASK 0x1
+#define TDM_OUT_MON_SEL_MASK_SFT (0x1 << 3)
+#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_EN_SFT 2
+#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_EN_MASK 0x1
+#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_EN_MASK_SFT (0x1 << 2)
+#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_SFT 1
+#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_MASK 0x1
+#define RG_TDM_OUT_ASYNC_FIFO_SOFT_RST_MASK_SFT (0x1 << 1)
+#define TDM_UPDATE_EN_SEL_SFT 0
+#define TDM_UPDATE_EN_SEL_MASK 0x1
+#define TDM_UPDATE_EN_SEL_MASK_SFT (0x1 << 0)
+
+/* AFE_TDM_OUT_MON */
+#define AFE_TDM_OUT_MON_SFT 0
+#define AFE_TDM_OUT_MON_MASK 0xffffffff
+#define AFE_TDM_OUT_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_HDMI_CONN0 */
+#define HDMI_O_7_SFT 21
+#define HDMI_O_7_MASK 0x7
+#define HDMI_O_7_MASK_SFT (0x7 << 21)
+#define HDMI_O_6_SFT 18
+#define HDMI_O_6_MASK 0x7
+#define HDMI_O_6_MASK_SFT (0x7 << 18)
+#define HDMI_O_5_SFT 15
+#define HDMI_O_5_MASK 0x7
+#define HDMI_O_5_MASK_SFT (0x7 << 15)
+#define HDMI_O_4_SFT 12
+#define HDMI_O_4_MASK 0x7
+#define HDMI_O_4_MASK_SFT (0x7 << 12)
+#define HDMI_O_3_SFT 9
+#define HDMI_O_3_MASK 0x7
+#define HDMI_O_3_MASK_SFT (0x7 << 9)
+#define HDMI_O_2_SFT 6
+#define HDMI_O_2_MASK 0x7
+#define HDMI_O_2_MASK_SFT (0x7 << 6)
+#define HDMI_O_1_SFT 3
+#define HDMI_O_1_MASK 0x7
+#define HDMI_O_1_MASK_SFT (0x7 << 3)
+#define HDMI_O_0_SFT 0
+#define HDMI_O_0_MASK 0x7
+#define HDMI_O_0_MASK_SFT (0x7 << 0)
+
+/* AFE_TDM_TOP_IP_VERSION */
+#define AFE_TDM_TOP_IP_VERSION_SFT 0
+#define AFE_TDM_TOP_IP_VERSION_MASK 0xffffffff
+#define AFE_TDM_TOP_IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CBIP_CFG0 */
+#define CBIP_TOP_SLV_MUX_WAY_EN_SFT 16
+#define CBIP_TOP_SLV_MUX_WAY_EN_MASK 0xffff
+#define CBIP_TOP_SLV_MUX_WAY_EN_MASK_SFT (0xffff << 16)
+#define RESERVED_04_SFT 15
+#define RESERVED_04_MASK 0x1
+#define RESERVED_04_MASK_SFT (0x1 << 15)
+#define CBIP_ASYNC_MST_RG_FIFO_THRE_SFT 13
+#define CBIP_ASYNC_MST_RG_FIFO_THRE_MASK 0x3
+#define CBIP_ASYNC_MST_RG_FIFO_THRE_MASK_SFT (0x3 << 13)
+#define CBIP_ASYNC_MST_POSTWRITE_DIS_SFT 12
+#define CBIP_ASYNC_MST_POSTWRITE_DIS_MASK 0x1
+#define CBIP_ASYNC_MST_POSTWRITE_DIS_MASK_SFT (0x1 << 12)
+#define RESERVED_03_SFT 11
+#define RESERVED_03_MASK 0x1
+#define RESERVED_03_MASK_SFT (0x1 << 11)
+#define CBIP_ASYNC_SLV_RG_FIFO_THRE_SFT 9
+#define CBIP_ASYNC_SLV_RG_FIFO_THRE_MASK 0x3
+#define CBIP_ASYNC_SLV_RG_FIFO_THRE_MASK_SFT (0x3 << 9)
+#define CBIP_ASYNC_SLV_POSTWRITE_DIS_SFT 8
+#define CBIP_ASYNC_SLV_POSTWRITE_DIS_MASK 0x1
+#define CBIP_ASYNC_SLV_POSTWRITE_DIS_MASK_SFT (0x1 << 8)
+#define AUDIOSYS_BUSY_SFT 7
+#define AUDIOSYS_BUSY_MASK 0x1
+#define AUDIOSYS_BUSY_MASK_SFT (0x1 << 7)
+#define CBIP_SLV_DECODER_ERR_FLAG_EN_SFT 6
+#define CBIP_SLV_DECODER_ERR_FLAG_EN_MASK 0x1
+#define CBIP_SLV_DECODER_ERR_FLAG_EN_MASK_SFT (0x1 << 6)
+#define CBIP_SLV_DECODER_SLAVE_WAY_EN_SFT 5
+#define CBIP_SLV_DECODER_SLAVE_WAY_EN_MASK 0x1
+#define CBIP_SLV_DECODER_SLAVE_WAY_EN_MASK_SFT (0x1 << 5)
+#define APB_R2T_SFT 3
+#define APB_R2T_MASK 0x1
+#define APB_R2T_MASK_SFT (0x1 << 3)
+#define APB_W2T_SFT 2
+#define APB_W2T_MASK 0x1
+#define APB_W2T_MASK_SFT (0x1 << 2)
+#define AHB_IDLE_EN_INT_SFT 1
+#define AHB_IDLE_EN_INT_MASK 0x1
+#define AHB_IDLE_EN_INT_MASK_SFT (0x1 << 1)
+#define AHB_IDLE_EN_EXT_SFT 0
+#define AHB_IDLE_EN_EXT_MASK 0x1
+#define AHB_IDLE_EN_EXT_MASK_SFT (0x1 << 0)
+
+/* AFE_CBIP_SLV_DECODER_MON0 */
+#define CBIP_SLV_DECODER_ERR_DOMAIN_SFT 4
+#define CBIP_SLV_DECODER_ERR_DOMAIN_MASK 0x1
+#define CBIP_SLV_DECODER_ERR_DOMAIN_MASK_SFT (0x1 << 4)
+#define CBIP_SLV_DECODER_ERR_ID_SFT 3
+#define CBIP_SLV_DECODER_ERR_ID_MASK 0x1
+#define CBIP_SLV_DECODER_ERR_ID_MASK_SFT (0x1 << 3)
+#define CBIP_SLV_DECODER_ERR_RW_SFT 2
+#define CBIP_SLV_DECODER_ERR_RW_MASK 0x1
+#define CBIP_SLV_DECODER_ERR_RW_MASK_SFT (0x1 << 2)
+#define CBIP_SLV_DECODER_ERR_DECERR_SFT 1
+#define CBIP_SLV_DECODER_ERR_DECERR_MASK 0x1
+#define CBIP_SLV_DECODER_ERR_DECERR_MASK_SFT (0x1 << 1)
+#define CBIP_SLV_DECODER_CTRL_UPDATE_STATUS_SFT 0
+#define CBIP_SLV_DECODER_CTRL_UPDATE_STATUS_MASK 0x1
+#define CBIP_SLV_DECODER_CTRL_UPDATE_STATUS_MASK_SFT (0x1 << 0)
+
+/* AFE_CBIP_SLV_DECODER_MON1 */
+#define CBIP_SLV_DECODER_ERR_ADDR_SFT 0
+#define CBIP_SLV_DECODER_ERR_ADDR_MASK 0xffffffff
+#define CBIP_SLV_DECODER_ERR_ADDR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CBIP_SLV_MUX_MON_CFG */
+#define CBIP_SLV_MUX_ERR_FLAG_EN_SFT 3
+#define CBIP_SLV_MUX_ERR_FLAG_EN_MASK 0x1
+#define CBIP_SLV_MUX_ERR_FLAG_EN_MASK_SFT (0x1 << 3)
+#define CBIP_SLV_MUX_REG_SLAVE_WAY_EN_SFT 2
+#define CBIP_SLV_MUX_REG_SLAVE_WAY_EN_MASK 0x1
+#define CBIP_SLV_MUX_REG_SLAVE_WAY_EN_MASK_SFT (0x1 << 2)
+#define CBIP_SLV_MUX_REG_LAYER_WAY_EN_SFT 0
+#define CBIP_SLV_MUX_REG_LAYER_WAY_EN_MASK 0x3
+#define CBIP_SLV_MUX_REG_LAYER_WAY_EN_MASK_SFT (0x3 << 0)
+
+/* AFE_CBIP_SLV_MUX_MON0 */
+#define CBIP_SLV_MUX_ERR_DOMAIN_SFT 8
+#define CBIP_SLV_MUX_ERR_DOMAIN_MASK 0x1
+#define CBIP_SLV_MUX_ERR_DOMAIN_MASK_SFT (0x1 << 8)
+#define CBIP_SLV_MUX_ERR_ID_SFT 7
+#define CBIP_SLV_MUX_ERR_ID_MASK 0x1
+#define CBIP_SLV_MUX_ERR_ID_MASK_SFT (0x1 << 7)
+#define CBIP_SLV_MUX_ERR_RD_SFT 6
+#define CBIP_SLV_MUX_ERR_RD_MASK 0x1
+#define CBIP_SLV_MUX_ERR_RD_MASK_SFT (0x1 << 6)
+#define CBIP_SLV_MUX_ERR_WR_SFT 5
+#define CBIP_SLV_MUX_ERR_WR_MASK 0x1
+#define CBIP_SLV_MUX_ERR_WR_MASK_SFT (0x1 << 5)
+#define CBIP_SLV_MUX_ERR_EN_SLV_SFT 4
+#define CBIP_SLV_MUX_ERR_EN_SLV_MASK 0x1
+#define CBIP_SLV_MUX_ERR_EN_SLV_MASK_SFT (0x1 << 4)
+#define CBIP_SLV_MUX_ERR_EN_MST_SFT 2
+#define CBIP_SLV_MUX_ERR_EN_MST_MASK 0x3
+#define CBIP_SLV_MUX_ERR_EN_MST_MASK_SFT (0x3 << 2)
+#define CBIP_SLV_MUX_CTRL_UPDATE_STATUS_SFT 0
+#define CBIP_SLV_MUX_CTRL_UPDATE_STATUS_MASK 0x3
+#define CBIP_SLV_MUX_CTRL_UPDATE_STATUS_MASK_SFT (0x3 << 0)
+
+/* AFE_CBIP_SLV_MUX_MON1 */
+#define CBIP_SLV_MUX_ERR_ADDR_SFT 0
+#define CBIP_SLV_MUX_ERR_ADDR_MASK 0xffffffff
+#define CBIP_SLV_MUX_ERR_ADDR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_MEMIF_CON0 */
+#define CPU_COMPACT_MODE_SFT 2
+#define CPU_COMPACT_MODE_MASK 0x1
+#define CPU_COMPACT_MODE_MASK_SFT (0x1 << 2)
+#define CPU_HD_ALIGN_SFT 1
+#define CPU_HD_ALIGN_MASK 0x1
+#define CPU_HD_ALIGN_MASK_SFT (0x1 << 1)
+#define SYSRAM_SIGN_SFT 0
+#define SYSRAM_SIGN_MASK 0x1
+#define SYSRAM_SIGN_MASK_SFT (0x1 << 0)
+
+/* AFE_MEMIF_ONE_HEART */
+#define DL_ONE_HEART_ON_2_SFT 2
+#define DL_ONE_HEART_ON_2_MASK 0x1
+#define DL_ONE_HEART_ON_2_MASK_SFT (0x1 << 2)
+#define DL_ONE_HEART_ON_1_SFT 1
+#define DL_ONE_HEART_ON_1_MASK 0x1
+#define DL_ONE_HEART_ON_1_MASK_SFT (0x1 << 1)
+#define DL_ONE_HEART_ON_0_SFT 0
+#define DL_ONE_HEART_ON_0_MASK 0x1
+#define DL_ONE_HEART_ON_0_MASK_SFT (0x1 << 0)
+
+/* AFE_DL0_BASE_MSB */
+#define DL0_BASE_ADDR_MSB_SFT 0
+#define DL0_BASE_ADDR_MSB_MASK 0x1ff
+#define DL0_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL0_BASE */
+#define DL0_BASE_ADDR_SFT 4
+#define DL0_BASE_ADDR_MASK 0xfffffff
+#define DL0_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL0_CUR_MSB */
+#define DL0_CUR_PTR_MSB_SFT 0
+#define DL0_CUR_PTR_MSB_MASK 0x1ff
+#define DL0_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL0_CUR */
+#define DL0_CUR_PTR_SFT 0
+#define DL0_CUR_PTR_MASK 0xffffffff
+#define DL0_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL0_END_MSB */
+#define DL0_END_ADDR_MSB_SFT 0
+#define DL0_END_ADDR_MSB_MASK 0x1ff
+#define DL0_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL0_END */
+#define DL0_END_ADDR_SFT 4
+#define DL0_END_ADDR_MASK 0xfffffff
+#define DL0_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL0_RCH_MON */
+#define DL0_RCH_DATA_SFT 0
+#define DL0_RCH_DATA_MASK 0xffffffff
+#define DL0_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL0_LCH_MON */
+#define DL0_LCH_DATA_SFT 0
+#define DL0_LCH_DATA_MASK 0xffffffff
+#define DL0_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL0_CON0 */
+#define DL0_ON_SFT 28
+#define DL0_ON_MASK 0x1
+#define DL0_ON_MASK_SFT (0x1 << 28)
+#define DL0_ONE_HEART_SEL_SFT 22
+#define DL0_ONE_HEART_SEL_MASK 0x3
+#define DL0_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL0_MINLEN_SFT 20
+#define DL0_MINLEN_MASK 0x3
+#define DL0_MINLEN_MASK_SFT (0x3 << 20)
+#define DL0_MAXLEN_SFT 16
+#define DL0_MAXLEN_MASK 0x3
+#define DL0_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL0_SEL_DOMAIN_SFT 13
+#define DL0_SEL_DOMAIN_MASK 0x7
+#define DL0_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL0_SEL_FS_SFT 8
+#define DL0_SEL_FS_MASK 0x1f
+#define DL0_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL0_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL0_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL0_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL0_PBUF_SIZE_SFT 5
+#define DL0_PBUF_SIZE_MASK 0x3
+#define DL0_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL0_MONO_SFT 4
+#define DL0_MONO_MASK 0x1
+#define DL0_MONO_MASK_SFT (0x1 << 4)
+#define DL0_NORMAL_MODE_SFT 3
+#define DL0_NORMAL_MODE_MASK 0x1
+#define DL0_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL0_HALIGN_SFT 2
+#define DL0_HALIGN_MASK 0x1
+#define DL0_HALIGN_MASK_SFT (0x1 << 2)
+#define DL0_HD_MODE_SFT 0
+#define DL0_HD_MODE_MASK 0x3
+#define DL0_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL1_BASE_MSB */
+#define DL1_BASE_ADDR_MSB_SFT 0
+#define DL1_BASE_ADDR_MSB_MASK 0x1ff
+#define DL1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL1_BASE */
+#define DL1_BASE_ADDR_SFT 4
+#define DL1_BASE_ADDR_MASK 0xfffffff
+#define DL1_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL1_CUR_MSB */
+#define DL1_CUR_PTR_MSB_SFT 0
+#define DL1_CUR_PTR_MSB_MASK 0x1ff
+#define DL1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL1_CUR */
+#define DL1_CUR_PTR_SFT 0
+#define DL1_CUR_PTR_MASK 0xffffffff
+#define DL1_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL1_END_MSB */
+#define DL1_END_ADDR_MSB_SFT 0
+#define DL1_END_ADDR_MSB_MASK 0x1ff
+#define DL1_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL1_END */
+#define DL1_END_ADDR_SFT 4
+#define DL1_END_ADDR_MASK 0xfffffff
+#define DL1_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL1_RCH_MON */
+#define DL1_RCH_DATA_SFT 0
+#define DL1_RCH_DATA_MASK 0xffffffff
+#define DL1_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL1_LCH_MON */
+#define DL1_LCH_DATA_SFT 0
+#define DL1_LCH_DATA_MASK 0xffffffff
+#define DL1_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL1_CON0 */
+#define DL1_ON_SFT 28
+#define DL1_ON_MASK 0x1
+#define DL1_ON_MASK_SFT (0x1 << 28)
+#define DL1_ONE_HEART_SEL_SFT 22
+#define DL1_ONE_HEART_SEL_MASK 0x3
+#define DL1_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL1_MINLEN_SFT 20
+#define DL1_MINLEN_MASK 0x3
+#define DL1_MINLEN_MASK_SFT (0x3 << 20)
+#define DL1_MAXLEN_SFT 16
+#define DL1_MAXLEN_MASK 0x3
+#define DL1_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL1_SEL_DOMAIN_SFT 13
+#define DL1_SEL_DOMAIN_MASK 0x7
+#define DL1_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL1_SEL_FS_SFT 8
+#define DL1_SEL_FS_MASK 0x1f
+#define DL1_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL1_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL1_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL1_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL1_PBUF_SIZE_SFT 5
+#define DL1_PBUF_SIZE_MASK 0x3
+#define DL1_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL1_MONO_SFT 4
+#define DL1_MONO_MASK 0x1
+#define DL1_MONO_MASK_SFT (0x1 << 4)
+#define DL1_NORMAL_MODE_SFT 3
+#define DL1_NORMAL_MODE_MASK 0x1
+#define DL1_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL1_HALIGN_SFT 2
+#define DL1_HALIGN_MASK 0x1
+#define DL1_HALIGN_MASK_SFT (0x1 << 2)
+#define DL1_HD_MODE_SFT 0
+#define DL1_HD_MODE_MASK 0x3
+#define DL1_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL2_BASE_MSB */
+#define DL2_BASE__ADDR_MSB_SFT 0
+#define DL2_BASE__ADDR_MSB_MASK 0x1ff
+#define DL2_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL2_BASE */
+#define DL2_BASE_ADDR_SFT 4
+#define DL2_BASE_ADDR_MASK 0xfffffff
+#define DL2_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL2_CUR_MSB */
+#define DL2_CUR_PTR_MSB_SFT 0
+#define DL2_CUR_PTR_MSB_MASK 0x1ff
+#define DL2_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL2_CUR */
+#define DL2_CUR_PTR_SFT 0
+#define DL2_CUR_PTR_MASK 0xffffffff
+#define DL2_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL2_END_MSB */
+#define DL2_END_ADDR_MSB_SFT 0
+#define DL2_END_ADDR_MSB_MASK 0x1ff
+#define DL2_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL2_END */
+#define DL2_END_ADDR_SFT 4
+#define DL2_END_ADDR_MASK 0xfffffff
+#define DL2_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL2_RCH_MON */
+#define DL2_RCH_DATA_SFT 0
+#define DL2_RCH_DATA_MASK 0xffffffff
+#define DL2_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL2_LCH_MON */
+#define DL2_LCH_DATA_SFT 0
+#define DL2_LCH_DATA_MASK 0xffffffff
+#define DL2_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL2_CON0 */
+#define DL2_ON_SFT 28
+#define DL2_ON_MASK 0x1
+#define DL2_ON_MASK_SFT (0x1 << 28)
+#define DL2_ONE_HEART_SEL_SFT 22
+#define DL2_ONE_HEART_SEL_MASK 0x3
+#define DL2_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL2_MINLEN_SFT 20
+#define DL2_MINLEN_MASK 0x3
+#define DL2_MINLEN_MASK_SFT (0x3 << 20)
+#define DL2_MAXLEN_SFT 16
+#define DL2_MAXLEN_MASK 0x3
+#define DL2_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL2_SEL_DOMAIN_SFT 13
+#define DL2_SEL_DOMAIN_MASK 0x7
+#define DL2_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL2_SEL_FS_SFT 8
+#define DL2_SEL_FS_MASK 0x1f
+#define DL2_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL2_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL2_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL2_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL2_PBUF_SIZE_SFT 5
+#define DL2_PBUF_SIZE_MASK 0x3
+#define DL2_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL2_MONO_SFT 4
+#define DL2_MONO_MASK 0x1
+#define DL2_MONO_MASK_SFT (0x1 << 4)
+#define DL2_NORMAL_MODE_SFT 3
+#define DL2_NORMAL_MODE_MASK 0x1
+#define DL2_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL2_HALIGN_SFT 2
+#define DL2_HALIGN_MASK 0x1
+#define DL2_HALIGN_MASK_SFT (0x1 << 2)
+#define DL2_HD_MODE_SFT 0
+#define DL2_HD_MODE_MASK 0x3
+#define DL2_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL3_BASE_MSB */
+#define DL3_BASE__ADDR_MSB_SFT 0
+#define DL3_BASE__ADDR_MSB_MASK 0x1ff
+#define DL3_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL3_BASE */
+#define DL3_BASE_ADDR_SFT 4
+#define DL3_BASE_ADDR_MASK 0xfffffff
+#define DL3_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL3_CUR_MSB */
+#define DL3_CUR_PTR_MSB_SFT 0
+#define DL3_CUR_PTR_MSB_MASK 0x1ff
+#define DL3_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL3_CUR */
+#define DL3_CUR_PTR_SFT 0
+#define DL3_CUR_PTR_MASK 0xffffffff
+#define DL3_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL3_END_MSB */
+#define DL3_END_ADDR_MSB_SFT 0
+#define DL3_END_ADDR_MSB_MASK 0x1ff
+#define DL3_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL3_END */
+#define DL3_END_ADDR_SFT 4
+#define DL3_END_ADDR_MASK 0xfffffff
+#define DL3_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL3_RCH_MON */
+#define DL3_RCH_DATA_SFT 0
+#define DL3_RCH_DATA_MASK 0xffffffff
+#define DL3_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL3_LCH_MON */
+#define DL3_LCH_DATA_SFT 0
+#define DL3_LCH_DATA_MASK 0xffffffff
+#define DL3_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL3_CON0 */
+#define DL3_ON_SFT 28
+#define DL3_ON_MASK 0x1
+#define DL3_ON_MASK_SFT (0x1 << 28)
+#define DL3_ONE_HEART_SEL_SFT 22
+#define DL3_ONE_HEART_SEL_MASK 0x3
+#define DL3_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL3_MINLEN_SFT 20
+#define DL3_MINLEN_MASK 0x3
+#define DL3_MINLEN_MASK_SFT (0x3 << 20)
+#define DL3_MAXLEN_SFT 16
+#define DL3_MAXLEN_MASK 0x3
+#define DL3_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL3_SEL_DOMAIN_SFT 13
+#define DL3_SEL_DOMAIN_MASK 0x7
+#define DL3_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL3_SEL_FS_SFT 8
+#define DL3_SEL_FS_MASK 0x1f
+#define DL3_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL3_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL3_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL3_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL3_PBUF_SIZE_SFT 5
+#define DL3_PBUF_SIZE_MASK 0x3
+#define DL3_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL3_MONO_SFT 4
+#define DL3_MONO_MASK 0x1
+#define DL3_MONO_MASK_SFT (0x1 << 4)
+#define DL3_NORMAL_MODE_SFT 3
+#define DL3_NORMAL_MODE_MASK 0x1
+#define DL3_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL3_HALIGN_SFT 2
+#define DL3_HALIGN_MASK 0x1
+#define DL3_HALIGN_MASK_SFT (0x1 << 2)
+#define DL3_HD_MODE_SFT 0
+#define DL3_HD_MODE_MASK 0x3
+#define DL3_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL4_BASE_MSB */
+#define DL4_BASE__ADDR_MSB_SFT 0
+#define DL4_BASE__ADDR_MSB_MASK 0x1ff
+#define DL4_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL4_BASE */
+#define DL4_BASE_ADDR_SFT 4
+#define DL4_BASE_ADDR_MASK 0xfffffff
+#define DL4_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL4_CUR_MSB */
+#define DL4_CUR_PTR_MSB_SFT 0
+#define DL4_CUR_PTR_MSB_MASK 0x1ff
+#define DL4_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL4_CUR */
+#define DL4_CUR_PTR_SFT 0
+#define DL4_CUR_PTR_MASK 0xffffffff
+#define DL4_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL4_END_MSB */
+#define DL4_END_ADDR_MSB_SFT 0
+#define DL4_END_ADDR_MSB_MASK 0x1ff
+#define DL4_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL4_END */
+#define DL4_END_ADDR_SFT 4
+#define DL4_END_ADDR_MASK 0xfffffff
+#define DL4_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL4_RCH_MON */
+#define DL4_RCH_DATA_SFT 0
+#define DL4_RCH_DATA_MASK 0xffffffff
+#define DL4_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL4_LCH_MON */
+#define DL4_LCH_DATA_SFT 0
+#define DL4_LCH_DATA_MASK 0xffffffff
+#define DL4_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL4_CON0 */
+#define DL4_ON_SFT 28
+#define DL4_ON_MASK 0x1
+#define DL4_ON_MASK_SFT (0x1 << 28)
+#define DL4_ONE_HEART_SEL_SFT 22
+#define DL4_ONE_HEART_SEL_MASK 0x3
+#define DL4_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL4_MINLEN_SFT 20
+#define DL4_MINLEN_MASK 0x3
+#define DL4_MINLEN_MASK_SFT (0x3 << 20)
+#define DL4_MAXLEN_SFT 16
+#define DL4_MAXLEN_MASK 0x3
+#define DL4_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL4_SEL_DOMAIN_SFT 13
+#define DL4_SEL_DOMAIN_MASK 0x7
+#define DL4_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL4_SEL_FS_SFT 8
+#define DL4_SEL_FS_MASK 0x1f
+#define DL4_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL4_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL4_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL4_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL4_PBUF_SIZE_SFT 5
+#define DL4_PBUF_SIZE_MASK 0x3
+#define DL4_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL4_MONO_SFT 4
+#define DL4_MONO_MASK 0x1
+#define DL4_MONO_MASK_SFT (0x1 << 4)
+#define DL4_NORMAL_MODE_SFT 3
+#define DL4_NORMAL_MODE_MASK 0x1
+#define DL4_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL4_HALIGN_SFT 2
+#define DL4_HALIGN_MASK 0x1
+#define DL4_HALIGN_MASK_SFT (0x1 << 2)
+#define DL4_HD_MODE_SFT 0
+#define DL4_HD_MODE_MASK 0x3
+#define DL4_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL5_BASE_MSB */
+#define DL5_BASE__ADDR_MSB_SFT 0
+#define DL5_BASE__ADDR_MSB_MASK 0x1ff
+#define DL5_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL5_BASE */
+#define DL5_BASE_ADDR_SFT 4
+#define DL5_BASE_ADDR_MASK 0xfffffff
+#define DL5_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL5_CUR_MSB */
+#define DL5_CUR_PTR_MSB_SFT 0
+#define DL5_CUR_PTR_MSB_MASK 0x1ff
+#define DL5_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL5_CUR */
+#define DL5_CUR_PTR_SFT 0
+#define DL5_CUR_PTR_MASK 0xffffffff
+#define DL5_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL5_END_MSB */
+#define DL5_END_ADDR_MSB_SFT 0
+#define DL5_END_ADDR_MSB_MASK 0x1ff
+#define DL5_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL5_END */
+#define DL5_END_ADDR_SFT 4
+#define DL5_END_ADDR_MASK 0xfffffff
+#define DL5_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL5_RCH_MON */
+#define DL5_RCH_DATA_SFT 0
+#define DL5_RCH_DATA_MASK 0xffffffff
+#define DL5_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL5_LCH_MON */
+#define DL5_LCH_DATA_SFT 0
+#define DL5_LCH_DATA_MASK 0xffffffff
+#define DL5_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL5_CON0 */
+#define DL5_ON_SFT 28
+#define DL5_ON_MASK 0x1
+#define DL5_ON_MASK_SFT (0x1 << 28)
+#define DL5_ONE_HEART_SEL_SFT 22
+#define DL5_ONE_HEART_SEL_MASK 0x3
+#define DL5_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL5_MINLEN_SFT 20
+#define DL5_MINLEN_MASK 0x3
+#define DL5_MINLEN_MASK_SFT (0x3 << 20)
+#define DL5_MAXLEN_SFT 16
+#define DL5_MAXLEN_MASK 0x3
+#define DL5_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL5_SEL_DOMAIN_SFT 13
+#define DL5_SEL_DOMAIN_MASK 0x7
+#define DL5_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL5_SEL_FS_SFT 8
+#define DL5_SEL_FS_MASK 0x1f
+#define DL5_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL5_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL5_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL5_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL5_PBUF_SIZE_SFT 5
+#define DL5_PBUF_SIZE_MASK 0x3
+#define DL5_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL5_MONO_SFT 4
+#define DL5_MONO_MASK 0x1
+#define DL5_MONO_MASK_SFT (0x1 << 4)
+#define DL5_NORMAL_MODE_SFT 3
+#define DL5_NORMAL_MODE_MASK 0x1
+#define DL5_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL5_HALIGN_SFT 2
+#define DL5_HALIGN_MASK 0x1
+#define DL5_HALIGN_MASK_SFT (0x1 << 2)
+#define DL5_HD_MODE_SFT 0
+#define DL5_HD_MODE_MASK 0x3
+#define DL5_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL6_BASE_MSB */
+#define DL6_BASE__ADDR_MSB_SFT 0
+#define DL6_BASE__ADDR_MSB_MASK 0x1ff
+#define DL6_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL6_BASE */
+#define DL6_BASE_ADDR_SFT 4
+#define DL6_BASE_ADDR_MASK 0xfffffff
+#define DL6_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL6_CUR_MSB */
+#define DL6_CUR_PTR_MSB_SFT 0
+#define DL6_CUR_PTR_MSB_MASK 0x1ff
+#define DL6_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL6_CUR */
+#define DL6_CUR_PTR_SFT 0
+#define DL6_CUR_PTR_MASK 0xffffffff
+#define DL6_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL6_END_MSB */
+#define DL6_END_ADDR_MSB_SFT 0
+#define DL6_END_ADDR_MSB_MASK 0x1ff
+#define DL6_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL6_END */
+#define DL6_END_ADDR_SFT 4
+#define DL6_END_ADDR_MASK 0xfffffff
+#define DL6_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL6_RCH_MON */
+#define DL6_RCH_DATA_SFT 0
+#define DL6_RCH_DATA_MASK 0xffffffff
+#define DL6_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL6_LCH_MON */
+#define DL6_LCH_DATA_SFT 0
+#define DL6_LCH_DATA_MASK 0xffffffff
+#define DL6_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL6_CON0 */
+#define DL6_ON_SFT 28
+#define DL6_ON_MASK 0x1
+#define DL6_ON_MASK_SFT (0x1 << 28)
+#define DL6_ONE_HEART_SEL_SFT 22
+#define DL6_ONE_HEART_SEL_MASK 0x3
+#define DL6_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL6_MINLEN_SFT 20
+#define DL6_MINLEN_MASK 0x3
+#define DL6_MINLEN_MASK_SFT (0x3 << 20)
+#define DL6_MAXLEN_SFT 16
+#define DL6_MAXLEN_MASK 0x3
+#define DL6_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL6_SEL_DOMAIN_SFT 13
+#define DL6_SEL_DOMAIN_MASK 0x7
+#define DL6_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL6_SEL_FS_SFT 8
+#define DL6_SEL_FS_MASK 0x1f
+#define DL6_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL6_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL6_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL6_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL6_PBUF_SIZE_SFT 5
+#define DL6_PBUF_SIZE_MASK 0x3
+#define DL6_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL6_MONO_SFT 4
+#define DL6_MONO_MASK 0x1
+#define DL6_MONO_MASK_SFT (0x1 << 4)
+#define DL6_NORMAL_MODE_SFT 3
+#define DL6_NORMAL_MODE_MASK 0x1
+#define DL6_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL6_HALIGN_SFT 2
+#define DL6_HALIGN_MASK 0x1
+#define DL6_HALIGN_MASK_SFT (0x1 << 2)
+#define DL6_HD_MODE_SFT 0
+#define DL6_HD_MODE_MASK 0x3
+#define DL6_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL7_BASE_MSB */
+#define DL7_BASE__ADDR_MSB_SFT 0
+#define DL7_BASE__ADDR_MSB_MASK 0x1ff
+#define DL7_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL7_BASE */
+#define DL7_BASE_ADDR_SFT 4
+#define DL7_BASE_ADDR_MASK 0xfffffff
+#define DL7_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL7_CUR_MSB */
+#define DL7_CUR_PTR_MSB_SFT 0
+#define DL7_CUR_PTR_MSB_MASK 0x1ff
+#define DL7_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL7_CUR */
+#define DL7_CUR_PTR_SFT 0
+#define DL7_CUR_PTR_MASK 0xffffffff
+#define DL7_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL7_END_MSB */
+#define DL7_END_ADDR_MSB_SFT 0
+#define DL7_END_ADDR_MSB_MASK 0x1ff
+#define DL7_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL7_END */
+#define DL7_END_ADDR_SFT 4
+#define DL7_END_ADDR_MASK 0xfffffff
+#define DL7_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL7_RCH_MON */
+#define DL7_RCH_DATA_SFT 0
+#define DL7_RCH_DATA_MASK 0xffffffff
+#define DL7_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL7_LCH_MON */
+#define DL7_LCH_DATA_SFT 0
+#define DL7_LCH_DATA_MASK 0xffffffff
+#define DL7_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL7_CON0 */
+#define DL7_ON_SFT 28
+#define DL7_ON_MASK 0x1
+#define DL7_ON_MASK_SFT (0x1 << 28)
+#define DL7_ONE_HEART_SEL_SFT 22
+#define DL7_ONE_HEART_SEL_MASK 0x3
+#define DL7_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL7_MINLEN_SFT 20
+#define DL7_MINLEN_MASK 0x3
+#define DL7_MINLEN_MASK_SFT (0x3 << 20)
+#define DL7_MAXLEN_SFT 16
+#define DL7_MAXLEN_MASK 0x3
+#define DL7_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL7_SEL_DOMAIN_SFT 13
+#define DL7_SEL_DOMAIN_MASK 0x7
+#define DL7_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL7_SEL_FS_SFT 8
+#define DL7_SEL_FS_MASK 0x1f
+#define DL7_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL7_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL7_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL7_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL7_PBUF_SIZE_SFT 5
+#define DL7_PBUF_SIZE_MASK 0x3
+#define DL7_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL7_MONO_SFT 4
+#define DL7_MONO_MASK 0x1
+#define DL7_MONO_MASK_SFT (0x1 << 4)
+#define DL7_NORMAL_MODE_SFT 3
+#define DL7_NORMAL_MODE_MASK 0x1
+#define DL7_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL7_HALIGN_SFT 2
+#define DL7_HALIGN_MASK 0x1
+#define DL7_HALIGN_MASK_SFT (0x1 << 2)
+#define DL7_HD_MODE_SFT 0
+#define DL7_HD_MODE_MASK 0x3
+#define DL7_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL8_BASE_MSB */
+#define DL8_BASE__ADDR_MSB_SFT 0
+#define DL8_BASE__ADDR_MSB_MASK 0x1ff
+#define DL8_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL8_BASE */
+#define DL8_BASE_ADDR_SFT 4
+#define DL8_BASE_ADDR_MASK 0xfffffff
+#define DL8_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL8_CUR_MSB */
+#define DL8_CUR_PTR_MSB_SFT 0
+#define DL8_CUR_PTR_MSB_MASK 0x1ff
+#define DL8_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL8_CUR */
+#define DL8_CUR_PTR_SFT 0
+#define DL8_CUR_PTR_MASK 0xffffffff
+#define DL8_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL8_END_MSB */
+#define DL8_END_ADDR_MSB_SFT 0
+#define DL8_END_ADDR_MSB_MASK 0x1ff
+#define DL8_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL8_END */
+#define DL8_END_ADDR_SFT 4
+#define DL8_END_ADDR_MASK 0xfffffff
+#define DL8_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL8_RCH_MON */
+#define DL8_RCH_DATA_SFT 0
+#define DL8_RCH_DATA_MASK 0xffffffff
+#define DL8_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL8_LCH_MON */
+#define DL8_LCH_DATA_SFT 0
+#define DL8_LCH_DATA_MASK 0xffffffff
+#define DL8_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL8_CON0 */
+#define DL8_ON_SFT 28
+#define DL8_ON_MASK 0x1
+#define DL8_ON_MASK_SFT (0x1 << 28)
+#define DL8_ONE_HEART_SEL_SFT 22
+#define DL8_ONE_HEART_SEL_MASK 0x3
+#define DL8_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL8_MINLEN_SFT 20
+#define DL8_MINLEN_MASK 0x3
+#define DL8_MINLEN_MASK_SFT (0x3 << 20)
+#define DL8_MAXLEN_SFT 16
+#define DL8_MAXLEN_MASK 0x3
+#define DL8_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL8_SEL_DOMAIN_SFT 13
+#define DL8_SEL_DOMAIN_MASK 0x7
+#define DL8_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL8_SEL_FS_SFT 8
+#define DL8_SEL_FS_MASK 0x1f
+#define DL8_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL8_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL8_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL8_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL8_PBUF_SIZE_SFT 5
+#define DL8_PBUF_SIZE_MASK 0x3
+#define DL8_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL8_MONO_SFT 4
+#define DL8_MONO_MASK 0x1
+#define DL8_MONO_MASK_SFT (0x1 << 4)
+#define DL8_NORMAL_MODE_SFT 3
+#define DL8_NORMAL_MODE_MASK 0x1
+#define DL8_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL8_HALIGN_SFT 2
+#define DL8_HALIGN_MASK 0x1
+#define DL8_HALIGN_MASK_SFT (0x1 << 2)
+#define DL8_HD_MODE_SFT 0
+#define DL8_HD_MODE_MASK 0x3
+#define DL8_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL_4CH_BASE_MSB */
+#define DL_4CH_BASE__ADDR_MSB_SFT 0
+#define DL_4CH_BASE__ADDR_MSB_MASK 0x1ff
+#define DL_4CH_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL_4CH_BASE */
+#define DL_4CH_BASE_ADDR_SFT 4
+#define DL_4CH_BASE_ADDR_MASK 0xfffffff
+#define DL_4CH_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL_4CH_CUR_MSB */
+#define DL_4CH_CUR_PTR_MSB_SFT 0
+#define DL_4CH_CUR_PTR_MSB_MASK 0x1ff
+#define DL_4CH_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL_4CH_CUR */
+#define DL_4CH_CUR_PTR_SFT 0
+#define DL_4CH_CUR_PTR_MASK 0xffffffff
+#define DL_4CH_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_4CH_END_MSB */
+#define DL_4CH_END_ADDR_MSB_SFT 0
+#define DL_4CH_END_ADDR_MSB_MASK 0x1ff
+#define DL_4CH_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL_4CH_END */
+#define DL_4CH_END_ADDR_SFT 4
+#define DL_4CH_END_ADDR_MASK 0xfffffff
+#define DL_4CH_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL_4CH_CON0 */
+#define DL_4CH_ON_SFT 31
+#define DL_4CH_ON_MASK 0x1
+#define DL_4CH_ON_MASK_SFT (0x1 << 31)
+#define DL_4CH_NUM_SFT 24
+#define DL_4CH_NUM_MASK 0x1f
+#define DL_4CH_NUM_MASK_SFT (0x1f << 24)
+#define DL_4CH_ONE_HEART_SEL_SFT 22
+#define DL_4CH_ONE_HEART_SEL_MASK 0x3
+#define DL_4CH_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL_4CH_MINLEN_SFT 20
+#define DL_4CH_MINLEN_MASK 0x3
+#define DL_4CH_MINLEN_MASK_SFT (0x3 << 20)
+#define DL_4CH_MAXLEN_SFT 16
+#define DL_4CH_MAXLEN_MASK 0x3
+#define DL_4CH_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL_4CH_SEL_DOMAIN_SFT 13
+#define DL_4CH_SEL_DOMAIN_MASK 0x7
+#define DL_4CH_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL_4CH_SEL_FS_SFT 8
+#define DL_4CH_SEL_FS_MASK 0x1f
+#define DL_4CH_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL_4CH_BUF_EMPTY_CLR_SFT 7
+#define DL_4CH_BUF_EMPTY_CLR_MASK 0x1
+#define DL_4CH_BUF_EMPTY_CLR_MASK_SFT (0x1 << 7)
+#define DL_4CH_PBUF_SIZE_SFT 5
+#define DL_4CH_PBUF_SIZE_MASK 0x3
+#define DL_4CH_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL_4CH_HANG_CLR_SFT 4
+#define DL_4CH_HANG_CLR_MASK 0x1
+#define DL_4CH_HANG_CLR_MASK_SFT (0x1 << 4)
+#define DL_4CH_NORMAL_MODE_SFT 3
+#define DL_4CH_NORMAL_MODE_MASK 0x1
+#define DL_4CH_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL_4CH_HALIGN_SFT 2
+#define DL_4CH_HALIGN_MASK 0x1
+#define DL_4CH_HALIGN_MASK_SFT (0x1 << 2)
+#define DL_4CH_HD_MODE_SFT 0
+#define DL_4CH_HD_MODE_MASK 0x3
+#define DL_4CH_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL_24CH_BASE_MSB */
+#define DL_24CH_BASE__ADDR_MSB_SFT 0
+#define DL_24CH_BASE__ADDR_MSB_MASK 0x1ff
+#define DL_24CH_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL_24CH_BASE */
+#define DL_24CH_BASE_ADDR_SFT 4
+#define DL_24CH_BASE_ADDR_MASK 0xfffffff
+#define DL_24CH_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL_24CH_CUR_MSB */
+#define DL_24CH_CUR_PTR_MSB_SFT 0
+#define DL_24CH_CUR_PTR_MSB_MASK 0x1ff
+#define DL_24CH_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL_24CH_CUR */
+#define DL_24CH_CUR_PTR_SFT 0
+#define DL_24CH_CUR_PTR_MASK 0xffffffff
+#define DL_24CH_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_END_MSB */
+#define DL_24CH_END_ADDR_MSB_SFT 0
+#define DL_24CH_END_ADDR_MSB_MASK 0x1ff
+#define DL_24CH_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL_24CH_END */
+#define DL_24CH_END_ADDR_SFT 4
+#define DL_24CH_END_ADDR_MASK 0xfffffff
+#define DL_24CH_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL_24CH_CON0 */
+#define DL_24CH_ON_SFT 31
+#define DL_24CH_ON_MASK 0x1
+#define DL_24CH_ON_MASK_SFT (0x1 << 31)
+#define DL_24CH_NUM_SFT 24
+#define DL_24CH_NUM_MASK 0x3f
+#define DL_24CH_NUM_MASK_SFT (0x3f << 24)
+#define DL_24CH_ONE_HEART_SEL_SFT 22
+#define DL_24CH_ONE_HEART_SEL_MASK 0x3
+#define DL_24CH_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL_24CH_MINLEN_SFT 20
+#define DL_24CH_MINLEN_MASK 0x3
+#define DL_24CH_MINLEN_MASK_SFT (0x3 << 20)
+#define DL_24CH_MAXLEN_SFT 16
+#define DL_24CH_MAXLEN_MASK 0x3
+#define DL_24CH_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL_24CH_SEL_DOMAIN_SFT 13
+#define DL_24CH_SEL_DOMAIN_MASK 0x7
+#define DL_24CH_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL_24CH_SEL_FS_SFT 8
+#define DL_24CH_SEL_FS_MASK 0x1f
+#define DL_24CH_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL_24CH_BUF_EMPTY_CLR_SFT 7
+#define DL_24CH_BUF_EMPTY_CLR_MASK 0x1
+#define DL_24CH_BUF_EMPTY_CLR_MASK_SFT (0x1 << 7)
+#define DL_24CH_PBUF_SIZE_SFT 5
+#define DL_24CH_PBUF_SIZE_MASK 0x3
+#define DL_24CH_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL_24CH_HANG_CLR_SFT 4
+#define DL_24CH_HANG_CLR_MASK 0x1
+#define DL_24CH_HANG_CLR_MASK_SFT (0x1 << 4)
+#define DL_24CH_NORMAL_MODE_SFT 3
+#define DL_24CH_NORMAL_MODE_MASK 0x1
+#define DL_24CH_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL_24CH_HALIGN_SFT 2
+#define DL_24CH_HALIGN_MASK 0x1
+#define DL_24CH_HALIGN_MASK_SFT (0x1 << 2)
+#define DL_24CH_HD_MODE_SFT 0
+#define DL_24CH_HD_MODE_MASK 0x3
+#define DL_24CH_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL23_BASE_MSB */
+#define DL23_BASE__ADDR_MSB_SFT 0
+#define DL23_BASE__ADDR_MSB_MASK 0x1ff
+#define DL23_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL23_BASE */
+#define DL23_BASE_ADDR_SFT 4
+#define DL23_BASE_ADDR_MASK 0xfffffff
+#define DL23_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL23_CUR_MSB */
+#define DL23_CUR_PTR_MSB_SFT 0
+#define DL23_CUR_PTR_MSB_MASK 0x1ff
+#define DL23_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL23_CUR */
+#define DL23_CUR_PTR_SFT 0
+#define DL23_CUR_PTR_MASK 0xffffffff
+#define DL23_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL23_END_MSB */
+#define DL23_END_ADDR_MSB_SFT 0
+#define DL23_END_ADDR_MSB_MASK 0x1ff
+#define DL23_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL23_END */
+#define DL23_END_ADDR_SFT 4
+#define DL23_END_ADDR_MASK 0xfffffff
+#define DL23_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL23_RCH_MON */
+#define DL23_RCH_DATA_SFT 0
+#define DL23_RCH_DATA_MASK 0xffffffff
+#define DL23_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL23_LCH_MON */
+#define DL23_LCH_DATA_SFT 0
+#define DL23_LCH_DATA_MASK 0xffffffff
+#define DL23_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL23_CON0 */
+#define DL23_ON_SFT 28
+#define DL23_ON_MASK 0x1
+#define DL23_ON_MASK_SFT (0x1 << 28)
+#define DL23_ONE_HEART_SEL_SFT 22
+#define DL23_ONE_HEART_SEL_MASK 0x3
+#define DL23_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL23_MINLEN_SFT 20
+#define DL23_MINLEN_MASK 0x3
+#define DL23_MINLEN_MASK_SFT (0x3 << 20)
+#define DL23_MAXLEN_SFT 16
+#define DL23_MAXLEN_MASK 0x3
+#define DL23_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL23_SEL_DOMAIN_SFT 13
+#define DL23_SEL_DOMAIN_MASK 0x7
+#define DL23_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL23_SEL_FS_SFT 8
+#define DL23_SEL_FS_MASK 0x1f
+#define DL23_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL23_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL23_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL23_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL23_PBUF_SIZE_SFT 5
+#define DL23_PBUF_SIZE_MASK 0x3
+#define DL23_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL23_MONO_SFT 4
+#define DL23_MONO_MASK 0x1
+#define DL23_MONO_MASK_SFT (0x1 << 4)
+#define DL23_NORMAL_MODE_SFT 3
+#define DL23_NORMAL_MODE_MASK 0x1
+#define DL23_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL23_HALIGN_SFT 2
+#define DL23_HALIGN_MASK 0x1
+#define DL23_HALIGN_MASK_SFT (0x1 << 2)
+#define DL23_HD_MODE_SFT 0
+#define DL23_HD_MODE_MASK 0x3
+#define DL23_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL24_BASE_MSB */
+#define DL24_BASE__ADDR_MSB_SFT 0
+#define DL24_BASE__ADDR_MSB_MASK 0x1ff
+#define DL24_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL24_BASE */
+#define DL24_BASE_ADDR_SFT 4
+#define DL24_BASE_ADDR_MASK 0xfffffff
+#define DL24_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL24_CUR_MSB */
+#define DL24_CUR_PTR_MSB_SFT 0
+#define DL24_CUR_PTR_MSB_MASK 0x1ff
+#define DL24_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL24_CUR */
+#define DL24_CUR_PTR_SFT 0
+#define DL24_CUR_PTR_MASK 0xffffffff
+#define DL24_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL24_END_MSB */
+#define DL24_END_ADDR_MSB_SFT 0
+#define DL24_END_ADDR_MSB_MASK 0x1ff
+#define DL24_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL24_END */
+#define DL24_END_ADDR_SFT 4
+#define DL24_END_ADDR_MASK 0xfffffff
+#define DL24_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL24_RCH_MON */
+#define DL24_RCH_DATA_SFT 0
+#define DL24_RCH_DATA_MASK 0xffffffff
+#define DL24_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL24_LCH_MON */
+#define DL24_LCH_DATA_SFT 0
+#define DL24_LCH_DATA_MASK 0xffffffff
+#define DL24_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL24_CON0 */
+#define DL24_ON_SFT 28
+#define DL24_ON_MASK 0x1
+#define DL24_ON_MASK_SFT (0x1 << 28)
+#define DL24_ONE_HEART_SEL_SFT 22
+#define DL24_ONE_HEART_SEL_MASK 0x3
+#define DL24_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL24_MINLEN_SFT 20
+#define DL24_MINLEN_MASK 0x3
+#define DL24_MINLEN_MASK_SFT (0x3 << 20)
+#define DL24_MAXLEN_SFT 16
+#define DL24_MAXLEN_MASK 0x3
+#define DL24_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL24_SEL_DOMAIN_SFT 13
+#define DL24_SEL_DOMAIN_MASK 0x7
+#define DL24_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL24_SEL_FS_SFT 8
+#define DL24_SEL_FS_MASK 0x1f
+#define DL24_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL24_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL24_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL24_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL24_PBUF_SIZE_SFT 5
+#define DL24_PBUF_SIZE_MASK 0x3
+#define DL24_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL24_MONO_SFT 4
+#define DL24_MONO_MASK 0x1
+#define DL24_MONO_MASK_SFT (0x1 << 4)
+#define DL24_NORMAL_MODE_SFT 3
+#define DL24_NORMAL_MODE_MASK 0x1
+#define DL24_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL24_HALIGN_SFT 2
+#define DL24_HALIGN_MASK 0x1
+#define DL24_HALIGN_MASK_SFT (0x1 << 2)
+#define DL24_HD_MODE_SFT 0
+#define DL24_HD_MODE_MASK 0x3
+#define DL24_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL25_BASE_MSB */
+#define DL25_BASE__ADDR_MSB_SFT 0
+#define DL25_BASE__ADDR_MSB_MASK 0x1ff
+#define DL25_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL25_BASE */
+#define DL25_BASE_ADDR_SFT 4
+#define DL25_BASE_ADDR_MASK 0xfffffff
+#define DL25_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL25_CUR_MSB */
+#define DL25_CUR_PTR_MSB_SFT 0
+#define DL25_CUR_PTR_MSB_MASK 0x1ff
+#define DL25_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL25_CUR */
+#define DL25_CUR_PTR_SFT 0
+#define DL25_CUR_PTR_MASK 0xffffffff
+#define DL25_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL25_END_MSB */
+#define DL25_END_ADDR_MSB_SFT 0
+#define DL25_END_ADDR_MSB_MASK 0x1ff
+#define DL25_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL25_END */
+#define DL25_END_ADDR_SFT 4
+#define DL25_END_ADDR_MASK 0xfffffff
+#define DL25_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL25_RCH_MON */
+#define DL25_RCH_DATA_SFT 0
+#define DL25_RCH_DATA_MASK 0xffffffff
+#define DL25_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL25_LCH_MON */
+#define DL25_LCH_DATA_SFT 0
+#define DL25_LCH_DATA_MASK 0xffffffff
+#define DL25_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL25_CON0 */
+#define DL25_ON_SFT 28
+#define DL25_ON_MASK 0x1
+#define DL25_ON_MASK_SFT (0x1 << 28)
+#define DL25_ONE_HEART_SEL_SFT 22
+#define DL25_ONE_HEART_SEL_MASK 0x3
+#define DL25_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL25_MINLEN_SFT 20
+#define DL25_MINLEN_MASK 0x3
+#define DL25_MINLEN_MASK_SFT (0x3 << 20)
+#define DL25_MAXLEN_SFT 16
+#define DL25_MAXLEN_MASK 0x3
+#define DL25_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL25_SEL_DOMAIN_SFT 13
+#define DL25_SEL_DOMAIN_MASK 0x7
+#define DL25_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL25_SEL_FS_SFT 8
+#define DL25_SEL_FS_MASK 0x1f
+#define DL25_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL25_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL25_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL25_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL25_PBUF_SIZE_SFT 5
+#define DL25_PBUF_SIZE_MASK 0x3
+#define DL25_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL25_MONO_SFT 4
+#define DL25_MONO_MASK 0x1
+#define DL25_MONO_MASK_SFT (0x1 << 4)
+#define DL25_NORMAL_MODE_SFT 3
+#define DL25_NORMAL_MODE_MASK 0x1
+#define DL25_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL25_HALIGN_SFT 2
+#define DL25_HALIGN_MASK 0x1
+#define DL25_HALIGN_MASK_SFT (0x1 << 2)
+#define DL25_HD_MODE_SFT 0
+#define DL25_HD_MODE_MASK 0x3
+#define DL25_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_DL26_BASE_MSB */
+#define DL26_BASE__ADDR_MSB_SFT 0
+#define DL26_BASE__ADDR_MSB_MASK 0x1ff
+#define DL26_BASE__ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL26_BASE */
+#define DL26_BASE_ADDR_SFT 4
+#define DL26_BASE_ADDR_MASK 0xfffffff
+#define DL26_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL26_CUR_MSB */
+#define DL26_CUR_PTR_MSB_SFT 0
+#define DL26_CUR_PTR_MSB_MASK 0x1ff
+#define DL26_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL26_CUR */
+#define DL26_CUR_PTR_SFT 0
+#define DL26_CUR_PTR_MASK 0xffffffff
+#define DL26_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL26_END_MSB */
+#define DL26_END_ADDR_MSB_SFT 0
+#define DL26_END_ADDR_MSB_MASK 0x1ff
+#define DL26_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_DL26_END */
+#define DL26_END_ADDR_SFT 4
+#define DL26_END_ADDR_MASK 0xfffffff
+#define DL26_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_DL26_RCH_MON */
+#define DL26_RCH_DATA_SFT 0
+#define DL26_RCH_DATA_MASK 0xffffffff
+#define DL26_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL26_LCH_MON */
+#define DL26_LCH_DATA_SFT 0
+#define DL26_LCH_DATA_MASK 0xffffffff
+#define DL26_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL26_CON0 */
+#define DL26_ON_SFT 28
+#define DL26_ON_MASK 0x1
+#define DL26_ON_MASK_SFT (0x1 << 28)
+#define DL26_ONE_HEART_SEL_SFT 22
+#define DL26_ONE_HEART_SEL_MASK 0x3
+#define DL26_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define DL26_MINLEN_SFT 20
+#define DL26_MINLEN_MASK 0x3
+#define DL26_MINLEN_MASK_SFT (0x3 << 20)
+#define DL26_MAXLEN_SFT 16
+#define DL26_MAXLEN_MASK 0x3
+#define DL26_MAXLEN_MASK_SFT (0x3 << 16)
+#define DL26_SEL_DOMAIN_SFT 13
+#define DL26_SEL_DOMAIN_MASK 0x7
+#define DL26_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define DL26_SEL_FS_SFT 8
+#define DL26_SEL_FS_MASK 0x1f
+#define DL26_SEL_FS_MASK_SFT (0x1f << 8)
+#define DL26_SW_CLEAR_BUF_EMPTY_SFT 7
+#define DL26_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define DL26_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define DL26_PBUF_SIZE_SFT 5
+#define DL26_PBUF_SIZE_MASK 0x3
+#define DL26_PBUF_SIZE_MASK_SFT (0x3 << 5)
+#define DL26_MONO_SFT 4
+#define DL26_MONO_MASK 0x1
+#define DL26_MONO_MASK_SFT (0x1 << 4)
+#define DL26_NORMAL_MODE_SFT 3
+#define DL26_NORMAL_MODE_MASK 0x1
+#define DL26_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define DL26_HALIGN_SFT 2
+#define DL26_HALIGN_MASK 0x1
+#define DL26_HALIGN_MASK_SFT (0x1 << 2)
+#define DL26_HD_MODE_SFT 0
+#define DL26_HD_MODE_MASK 0x3
+#define DL26_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL0_BASE_MSB */
+#define VUL0_BASE_ADDR_MSB_SFT 0
+#define VUL0_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL0_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL0_BASE */
+#define VUL0_BASE_ADDR_SFT 4
+#define VUL0_BASE_ADDR_MASK 0xfffffff
+#define VUL0_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL0_CUR_MSB */
+#define VUL0_CUR_PTR_MSB_SFT 0
+#define VUL0_CUR_PTR_MSB_MASK 0x1ff
+#define VUL0_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL0_CUR */
+#define VUL0_CUR_PTR_SFT 0
+#define VUL0_CUR_PTR_MASK 0xffffffff
+#define VUL0_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL0_END_MSB */
+#define VUL0_END_ADDR_MSB_SFT 0
+#define VUL0_END_ADDR_MSB_MASK 0x1ff
+#define VUL0_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL0_END */
+#define VUL0_END_ADDR_SFT 4
+#define VUL0_END_ADDR_MASK 0xfffffff
+#define VUL0_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL0_RCH_MON */
+#define VUL0_RCH_DATA_SFT 0
+#define VUL0_RCH_DATA_MASK 0xffffffff
+#define VUL0_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL0_LCH_MON */
+#define VUL0_LCH_DATA_SFT 0
+#define VUL0_LCH_DATA_MASK 0xffffffff
+#define VUL0_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL0_CON0 */
+#define VUL0_ON_SFT 28
+#define VUL0_ON_MASK 0x1
+#define VUL0_ON_MASK_SFT (0x1 << 28)
+#define VUL0_MINLEN_SFT 20
+#define VUL0_MINLEN_MASK 0x3
+#define VUL0_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL0_MAXLEN_SFT 16
+#define VUL0_MAXLEN_MASK 0x3
+#define VUL0_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL0_SEL_DOMAIN_SFT 13
+#define VUL0_SEL_DOMAIN_MASK 0x7
+#define VUL0_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL0_SEL_FS_SFT 8
+#define VUL0_SEL_FS_MASK 0x1f
+#define VUL0_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL0_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL0_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL0_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL0_WR_SIGN_SFT 6
+#define VUL0_WR_SIGN_MASK 0x1
+#define VUL0_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL0_R_MONO_SFT 5
+#define VUL0_R_MONO_MASK 0x1
+#define VUL0_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL0_MONO_SFT 4
+#define VUL0_MONO_MASK 0x1
+#define VUL0_MONO_MASK_SFT (0x1 << 4)
+#define VUL0_NORMAL_MODE_SFT 3
+#define VUL0_NORMAL_MODE_MASK 0x1
+#define VUL0_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL0_HALIGN_SFT 2
+#define VUL0_HALIGN_MASK 0x1
+#define VUL0_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL0_HD_MODE_SFT 0
+#define VUL0_HD_MODE_MASK 0x3
+#define VUL0_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL1_BASE_MSB */
+#define VUL1_BASE_ADDR_MSB_SFT 0
+#define VUL1_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL1_BASE */
+#define VUL1_BASE_ADDR_SFT 4
+#define VUL1_BASE_ADDR_MASK 0xfffffff
+#define VUL1_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL1_CUR_MSB */
+#define VUL1_CUR_PTR_MSB_SFT 0
+#define VUL1_CUR_PTR_MSB_MASK 0x1ff
+#define VUL1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL1_CUR */
+#define VUL1_CUR_PTR_SFT 0
+#define VUL1_CUR_PTR_MASK 0xffffffff
+#define VUL1_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL1_END_MSB */
+#define VUL1_END_ADDR_MSB_SFT 0
+#define VUL1_END_ADDR_MSB_MASK 0x1ff
+#define VUL1_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL1_END */
+#define VUL1_END_ADDR_SFT 4
+#define VUL1_END_ADDR_MASK 0xfffffff
+#define VUL1_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL1_RCH_MON */
+#define VUL1_RCH_DATA_SFT 0
+#define VUL1_RCH_DATA_MASK 0xffffffff
+#define VUL1_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL1_LCH_MON */
+#define VUL1_LCH_DATA_SFT 0
+#define VUL1_LCH_DATA_MASK 0xffffffff
+#define VUL1_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL1_CON0 */
+#define VUL1_ON_SFT 28
+#define VUL1_ON_MASK 0x1
+#define VUL1_ON_MASK_SFT (0x1 << 28)
+#define VUL1_MINLEN_SFT 20
+#define VUL1_MINLEN_MASK 0x3
+#define VUL1_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL1_MAXLEN_SFT 16
+#define VUL1_MAXLEN_MASK 0x3
+#define VUL1_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL1_SEL_DOMAIN_SFT 13
+#define VUL1_SEL_DOMAIN_MASK 0x7
+#define VUL1_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL1_SEL_FS_SFT 8
+#define VUL1_SEL_FS_MASK 0x1f
+#define VUL1_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL1_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL1_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL1_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL1_WR_SIGN_SFT 6
+#define VUL1_WR_SIGN_MASK 0x1
+#define VUL1_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL1_R_MONO_SFT 5
+#define VUL1_R_MONO_MASK 0x1
+#define VUL1_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL1_MONO_SFT 4
+#define VUL1_MONO_MASK 0x1
+#define VUL1_MONO_MASK_SFT (0x1 << 4)
+#define VUL1_NORMAL_MODE_SFT 3
+#define VUL1_NORMAL_MODE_MASK 0x1
+#define VUL1_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL1_HALIGN_SFT 2
+#define VUL1_HALIGN_MASK 0x1
+#define VUL1_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL1_HD_MODE_SFT 0
+#define VUL1_HD_MODE_MASK 0x3
+#define VUL1_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL2_BASE_MSB */
+#define VUL2_BASE_ADDR_MSB_SFT 0
+#define VUL2_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL2_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL2_BASE */
+#define VUL2_BASE_ADDR_SFT 4
+#define VUL2_BASE_ADDR_MASK 0xfffffff
+#define VUL2_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL2_CUR_MSB */
+#define VUL2_CUR_PTR_MSB_SFT 0
+#define VUL2_CUR_PTR_MSB_MASK 0x1ff
+#define VUL2_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL2_CUR */
+#define VUL2_CUR_PTR_SFT 0
+#define VUL2_CUR_PTR_MASK 0xffffffff
+#define VUL2_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL2_END_MSB */
+#define VUL2_END_ADDR_MSB_SFT 0
+#define VUL2_END_ADDR_MSB_MASK 0x1ff
+#define VUL2_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL2_END */
+#define VUL2_END_ADDR_SFT 4
+#define VUL2_END_ADDR_MASK 0xfffffff
+#define VUL2_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL2_RCH_MON */
+#define VUL2_RCH_DATA_SFT 0
+#define VUL2_RCH_DATA_MASK 0xffffffff
+#define VUL2_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL2_LCH_MON */
+#define VUL2_LCH_DATA_SFT 0
+#define VUL2_LCH_DATA_MASK 0xffffffff
+#define VUL2_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL2_CON0 */
+#define VUL2_ON_SFT 28
+#define VUL2_ON_MASK 0x1
+#define VUL2_ON_MASK_SFT (0x1 << 28)
+#define VUL2_MINLEN_SFT 20
+#define VUL2_MINLEN_MASK 0x3
+#define VUL2_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL2_MAXLEN_SFT 16
+#define VUL2_MAXLEN_MASK 0x3
+#define VUL2_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL2_SEL_DOMAIN_SFT 13
+#define VUL2_SEL_DOMAIN_MASK 0x7
+#define VUL2_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL2_SEL_FS_SFT 8
+#define VUL2_SEL_FS_MASK 0x1f
+#define VUL2_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL2_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL2_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL2_WR_SIGN_SFT 6
+#define VUL2_WR_SIGN_MASK 0x1
+#define VUL2_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL2_R_MONO_SFT 5
+#define VUL2_R_MONO_MASK 0x1
+#define VUL2_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL2_MONO_SFT 4
+#define VUL2_MONO_MASK 0x1
+#define VUL2_MONO_MASK_SFT (0x1 << 4)
+#define VUL2_NORMAL_MODE_SFT 3
+#define VUL2_NORMAL_MODE_MASK 0x1
+#define VUL2_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL2_HALIGN_SFT 2
+#define VUL2_HALIGN_MASK 0x1
+#define VUL2_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL2_HD_MODE_SFT 0
+#define VUL2_HD_MODE_MASK 0x3
+#define VUL2_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL3_BASE_MSB */
+#define VUL3_BASE_ADDR_MSB_SFT 0
+#define VUL3_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL3_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL3_BASE */
+#define VUL3_BASE_ADDR_SFT 4
+#define VUL3_BASE_ADDR_MASK 0xfffffff
+#define VUL3_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL3_CUR_MSB */
+#define VUL3_CUR_PTR_MSB_SFT 0
+#define VUL3_CUR_PTR_MSB_MASK 0x1ff
+#define VUL3_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL3_CUR */
+#define VUL3_CUR_PTR_SFT 0
+#define VUL3_CUR_PTR_MASK 0xffffffff
+#define VUL3_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL3_END_MSB */
+#define VUL3_END_ADDR_MSB_SFT 0
+#define VUL3_END_ADDR_MSB_MASK 0x1ff
+#define VUL3_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL3_END */
+#define VUL3_END_ADDR_SFT 4
+#define VUL3_END_ADDR_MASK 0xfffffff
+#define VUL3_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL3_RCH_MON */
+#define VUL3_RCH_DATA_SFT 0
+#define VUL3_RCH_DATA_MASK 0xffffffff
+#define VUL3_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL3_LCH_MON */
+#define VUL3_LCH_DATA_SFT 0
+#define VUL3_LCH_DATA_MASK 0xffffffff
+#define VUL3_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL3_CON0 */
+#define VUL3_ON_SFT 28
+#define VUL3_ON_MASK 0x1
+#define VUL3_ON_MASK_SFT (0x1 << 28)
+#define VUL3_MINLEN_SFT 20
+#define VUL3_MINLEN_MASK 0x3
+#define VUL3_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL3_MAXLEN_SFT 16
+#define VUL3_MAXLEN_MASK 0x3
+#define VUL3_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL3_SEL_DOMAIN_SFT 13
+#define VUL3_SEL_DOMAIN_MASK 0x7
+#define VUL3_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL3_SEL_FS_SFT 8
+#define VUL3_SEL_FS_MASK 0x1f
+#define VUL3_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL3_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL3_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL3_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL3_WR_SIGN_SFT 6
+#define VUL3_WR_SIGN_MASK 0x1
+#define VUL3_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL3_R_MONO_SFT 5
+#define VUL3_R_MONO_MASK 0x1
+#define VUL3_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL3_MONO_SFT 4
+#define VUL3_MONO_MASK 0x1
+#define VUL3_MONO_MASK_SFT (0x1 << 4)
+#define VUL3_NORMAL_MODE_SFT 3
+#define VUL3_NORMAL_MODE_MASK 0x1
+#define VUL3_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL3_HALIGN_SFT 2
+#define VUL3_HALIGN_MASK 0x1
+#define VUL3_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL3_HD_MODE_SFT 0
+#define VUL3_HD_MODE_MASK 0x3
+#define VUL3_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL4_BASE_MSB */
+#define VUL4_BASE_ADDR_MSB_SFT 0
+#define VUL4_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL4_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL4_BASE */
+#define VUL4_BASE_ADDR_SFT 4
+#define VUL4_BASE_ADDR_MASK 0xfffffff
+#define VUL4_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL4_CUR_MSB */
+#define VUL4_CUR_PTR_MSB_SFT 0
+#define VUL4_CUR_PTR_MSB_MASK 0x1ff
+#define VUL4_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL4_CUR */
+#define VUL4_CUR_PTR_SFT 0
+#define VUL4_CUR_PTR_MASK 0xffffffff
+#define VUL4_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL4_END_MSB */
+#define VUL4_END_ADDR_MSB_SFT 0
+#define VUL4_END_ADDR_MSB_MASK 0x1ff
+#define VUL4_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL4_END */
+#define VUL4_END_ADDR_SFT 4
+#define VUL4_END_ADDR_MASK 0xfffffff
+#define VUL4_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL4_RCH_MON */
+#define VUL4_RCH_DATA_SFT 0
+#define VUL4_RCH_DATA_MASK 0xffffffff
+#define VUL4_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL4_LCH_MON */
+#define VUL4_LCH_DATA_SFT 0
+#define VUL4_LCH_DATA_MASK 0xffffffff
+#define VUL4_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL4_CON0 */
+#define VUL4_ON_SFT 28
+#define VUL4_ON_MASK 0x1
+#define VUL4_ON_MASK_SFT (0x1 << 28)
+#define VUL4_MINLEN_SFT 20
+#define VUL4_MINLEN_MASK 0x3
+#define VUL4_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL4_MAXLEN_SFT 16
+#define VUL4_MAXLEN_MASK 0x3
+#define VUL4_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL4_SEL_DOMAIN_SFT 13
+#define VUL4_SEL_DOMAIN_MASK 0x7
+#define VUL4_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL4_SEL_FS_SFT 8
+#define VUL4_SEL_FS_MASK 0x1f
+#define VUL4_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL4_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL4_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL4_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL4_WR_SIGN_SFT 6
+#define VUL4_WR_SIGN_MASK 0x1
+#define VUL4_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL4_R_MONO_SFT 5
+#define VUL4_R_MONO_MASK 0x1
+#define VUL4_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL4_MONO_SFT 4
+#define VUL4_MONO_MASK 0x1
+#define VUL4_MONO_MASK_SFT (0x1 << 4)
+#define VUL4_NORMAL_MODE_SFT 3
+#define VUL4_NORMAL_MODE_MASK 0x1
+#define VUL4_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL4_HALIGN_SFT 2
+#define VUL4_HALIGN_MASK 0x1
+#define VUL4_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL4_HD_MODE_SFT 0
+#define VUL4_HD_MODE_MASK 0x3
+#define VUL4_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL5_BASE_MSB */
+#define VUL5_BASE_ADDR_MSB_SFT 0
+#define VUL5_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL5_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL5_BASE */
+#define VUL5_BASE_ADDR_SFT 4
+#define VUL5_BASE_ADDR_MASK 0xfffffff
+#define VUL5_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL5_CUR_MSB */
+#define VUL5_CUR_PTR_MSB_SFT 0
+#define VUL5_CUR_PTR_MSB_MASK 0x1ff
+#define VUL5_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL5_CUR */
+#define VUL5_CUR_PTR_SFT 0
+#define VUL5_CUR_PTR_MASK 0xffffffff
+#define VUL5_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL5_END_MSB */
+#define VUL5_END_ADDR_MSB_SFT 0
+#define VUL5_END_ADDR_MSB_MASK 0x1ff
+#define VUL5_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL5_END */
+#define VUL5_END_ADDR_SFT 4
+#define VUL5_END_ADDR_MASK 0xfffffff
+#define VUL5_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL5_RCH_MON */
+#define VUL5_RCH_DATA_SFT 0
+#define VUL5_RCH_DATA_MASK 0xffffffff
+#define VUL5_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL5_LCH_MON */
+#define VUL5_LCH_DATA_SFT 0
+#define VUL5_LCH_DATA_MASK 0xffffffff
+#define VUL5_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL5_CON0 */
+#define VUL5_ON_SFT 28
+#define VUL5_ON_MASK 0x1
+#define VUL5_ON_MASK_SFT (0x1 << 28)
+#define VUL5_MINLEN_SFT 20
+#define VUL5_MINLEN_MASK 0x3
+#define VUL5_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL5_MAXLEN_SFT 16
+#define VUL5_MAXLEN_MASK 0x3
+#define VUL5_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL5_SEL_DOMAIN_SFT 13
+#define VUL5_SEL_DOMAIN_MASK 0x7
+#define VUL5_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL5_SEL_FS_SFT 8
+#define VUL5_SEL_FS_MASK 0x1f
+#define VUL5_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL5_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL5_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL5_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL5_WR_SIGN_SFT 6
+#define VUL5_WR_SIGN_MASK 0x1
+#define VUL5_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL5_R_MONO_SFT 5
+#define VUL5_R_MONO_MASK 0x1
+#define VUL5_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL5_MONO_SFT 4
+#define VUL5_MONO_MASK 0x1
+#define VUL5_MONO_MASK_SFT (0x1 << 4)
+#define VUL5_NORMAL_MODE_SFT 3
+#define VUL5_NORMAL_MODE_MASK 0x1
+#define VUL5_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL5_HALIGN_SFT 2
+#define VUL5_HALIGN_MASK 0x1
+#define VUL5_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL5_HD_MODE_SFT 0
+#define VUL5_HD_MODE_MASK 0x3
+#define VUL5_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL6_BASE_MSB */
+#define VUL6_BASE_ADDR_MSB_SFT 0
+#define VUL6_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL6_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL6_BASE */
+#define VUL6_BASE_ADDR_SFT 4
+#define VUL6_BASE_ADDR_MASK 0xfffffff
+#define VUL6_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL6_CUR_MSB */
+#define VUL6_CUR_PTR_MSB_SFT 0
+#define VUL6_CUR_PTR_MSB_MASK 0x1ff
+#define VUL6_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL6_CUR */
+#define VUL6_CUR_PTR_SFT 0
+#define VUL6_CUR_PTR_MASK 0xffffffff
+#define VUL6_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL6_END_MSB */
+#define VUL6_END_ADDR_MSB_SFT 0
+#define VUL6_END_ADDR_MSB_MASK 0x1ff
+#define VUL6_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL6_END */
+#define VUL6_END_ADDR_SFT 4
+#define VUL6_END_ADDR_MASK 0xfffffff
+#define VUL6_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL6_RCH_MON */
+#define VUL6_RCH_DATA_SFT 0
+#define VUL6_RCH_DATA_MASK 0xffffffff
+#define VUL6_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL6_LCH_MON */
+#define VUL6_LCH_DATA_SFT 0
+#define VUL6_LCH_DATA_MASK 0xffffffff
+#define VUL6_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL6_CON0 */
+#define VUL6_ON_SFT 28
+#define VUL6_ON_MASK 0x1
+#define VUL6_ON_MASK_SFT (0x1 << 28)
+#define VUL6_MINLEN_SFT 20
+#define VUL6_MINLEN_MASK 0x3
+#define VUL6_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL6_MAXLEN_SFT 16
+#define VUL6_MAXLEN_MASK 0x3
+#define VUL6_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL6_SEL_DOMAIN_SFT 13
+#define VUL6_SEL_DOMAIN_MASK 0x7
+#define VUL6_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL6_SEL_FS_SFT 8
+#define VUL6_SEL_FS_MASK 0x1f
+#define VUL6_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL6_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL6_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL6_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL6_WR_SIGN_SFT 6
+#define VUL6_WR_SIGN_MASK 0x1
+#define VUL6_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL6_R_MONO_SFT 5
+#define VUL6_R_MONO_MASK 0x1
+#define VUL6_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL6_MONO_SFT 4
+#define VUL6_MONO_MASK 0x1
+#define VUL6_MONO_MASK_SFT (0x1 << 4)
+#define VUL6_NORMAL_MODE_SFT 3
+#define VUL6_NORMAL_MODE_MASK 0x1
+#define VUL6_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL6_HALIGN_SFT 2
+#define VUL6_HALIGN_MASK 0x1
+#define VUL6_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL6_HD_MODE_SFT 0
+#define VUL6_HD_MODE_MASK 0x3
+#define VUL6_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL7_BASE_MSB */
+#define VUL7_BASE_ADDR_MSB_SFT 0
+#define VUL7_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL7_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL7_BASE */
+#define VUL7_BASE_ADDR_SFT 4
+#define VUL7_BASE_ADDR_MASK 0xfffffff
+#define VUL7_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL7_CUR_MSB */
+#define VUL7_CUR_PTR_MSB_SFT 0
+#define VUL7_CUR_PTR_MSB_MASK 0x1ff
+#define VUL7_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL7_CUR */
+#define VUL7_CUR_PTR_SFT 0
+#define VUL7_CUR_PTR_MASK 0xffffffff
+#define VUL7_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL7_END_MSB */
+#define VUL7_END_ADDR_MSB_SFT 0
+#define VUL7_END_ADDR_MSB_MASK 0x1ff
+#define VUL7_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL7_END */
+#define VUL7_END_ADDR_SFT 4
+#define VUL7_END_ADDR_MASK 0xfffffff
+#define VUL7_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL7_RCH_MON */
+#define VUL7_RCH_DATA_SFT 0
+#define VUL7_RCH_DATA_MASK 0xffffffff
+#define VUL7_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL7_LCH_MON */
+#define VUL7_LCH_DATA_SFT 0
+#define VUL7_LCH_DATA_MASK 0xffffffff
+#define VUL7_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL7_CON0 */
+#define VUL7_ON_SFT 28
+#define VUL7_ON_MASK 0x1
+#define VUL7_ON_MASK_SFT (0x1 << 28)
+#define VUL7_MINLEN_SFT 20
+#define VUL7_MINLEN_MASK 0x3
+#define VUL7_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL7_MAXLEN_SFT 16
+#define VUL7_MAXLEN_MASK 0x3
+#define VUL7_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL7_SEL_DOMAIN_SFT 13
+#define VUL7_SEL_DOMAIN_MASK 0x7
+#define VUL7_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL7_SEL_FS_SFT 8
+#define VUL7_SEL_FS_MASK 0x1f
+#define VUL7_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL7_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL7_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL7_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL7_WR_SIGN_SFT 6
+#define VUL7_WR_SIGN_MASK 0x1
+#define VUL7_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL7_R_MONO_SFT 5
+#define VUL7_R_MONO_MASK 0x1
+#define VUL7_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL7_MONO_SFT 4
+#define VUL7_MONO_MASK 0x1
+#define VUL7_MONO_MASK_SFT (0x1 << 4)
+#define VUL7_NORMAL_MODE_SFT 3
+#define VUL7_NORMAL_MODE_MASK 0x1
+#define VUL7_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL7_HALIGN_SFT 2
+#define VUL7_HALIGN_MASK 0x1
+#define VUL7_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL7_HD_MODE_SFT 0
+#define VUL7_HD_MODE_MASK 0x3
+#define VUL7_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL8_BASE_MSB */
+#define VUL8_BASE_ADDR_MSB_SFT 0
+#define VUL8_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL8_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL8_BASE */
+#define VUL8_BASE_ADDR_SFT 4
+#define VUL8_BASE_ADDR_MASK 0xfffffff
+#define VUL8_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL8_CUR_MSB */
+#define VUL8_CUR_PTR_MSB_SFT 0
+#define VUL8_CUR_PTR_MSB_MASK 0x1ff
+#define VUL8_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL8_CUR */
+#define VUL8_CUR_PTR_SFT 0
+#define VUL8_CUR_PTR_MASK 0xffffffff
+#define VUL8_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL8_END_MSB */
+#define VUL8_END_ADDR_MSB_SFT 0
+#define VUL8_END_ADDR_MSB_MASK 0x1ff
+#define VUL8_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL8_END */
+#define VUL8_END_ADDR_SFT 4
+#define VUL8_END_ADDR_MASK 0xfffffff
+#define VUL8_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL8_RCH_MON */
+#define VUL8_RCH_DATA_SFT 0
+#define VUL8_RCH_DATA_MASK 0xffffffff
+#define VUL8_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL8_LCH_MON */
+#define VUL8_LCH_DATA_SFT 0
+#define VUL8_LCH_DATA_MASK 0xffffffff
+#define VUL8_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL8_CON0 */
+#define VUL8_ON_SFT 28
+#define VUL8_ON_MASK 0x1
+#define VUL8_ON_MASK_SFT (0x1 << 28)
+#define VUL8_MINLEN_SFT 20
+#define VUL8_MINLEN_MASK 0x3
+#define VUL8_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL8_MAXLEN_SFT 16
+#define VUL8_MAXLEN_MASK 0x3
+#define VUL8_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL8_SEL_DOMAIN_SFT 13
+#define VUL8_SEL_DOMAIN_MASK 0x7
+#define VUL8_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL8_SEL_FS_SFT 8
+#define VUL8_SEL_FS_MASK 0x1f
+#define VUL8_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL8_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL8_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL8_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL8_WR_SIGN_SFT 6
+#define VUL8_WR_SIGN_MASK 0x1
+#define VUL8_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL8_R_MONO_SFT 5
+#define VUL8_R_MONO_MASK 0x1
+#define VUL8_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL8_MONO_SFT 4
+#define VUL8_MONO_MASK 0x1
+#define VUL8_MONO_MASK_SFT (0x1 << 4)
+#define VUL8_NORMAL_MODE_SFT 3
+#define VUL8_NORMAL_MODE_MASK 0x1
+#define VUL8_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL8_HALIGN_SFT 2
+#define VUL8_HALIGN_MASK 0x1
+#define VUL8_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL8_HD_MODE_SFT 0
+#define VUL8_HD_MODE_MASK 0x3
+#define VUL8_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL9_BASE_MSB */
+#define VUL9_BASE_ADDR_MSB_SFT 0
+#define VUL9_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL9_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL9_BASE */
+#define VUL9_BASE_ADDR_SFT 4
+#define VUL9_BASE_ADDR_MASK 0xfffffff
+#define VUL9_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL9_CUR_MSB */
+#define VUL9_CUR_PTR_MSB_SFT 0
+#define VUL9_CUR_PTR_MSB_MASK 0x1ff
+#define VUL9_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL9_CUR */
+#define VUL9_CUR_PTR_SFT 0
+#define VUL9_CUR_PTR_MASK 0xffffffff
+#define VUL9_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL9_END_MSB */
+#define VUL9_END_ADDR_MSB_SFT 0
+#define VUL9_END_ADDR_MSB_MASK 0x1ff
+#define VUL9_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL9_END */
+#define VUL9_END_ADDR_SFT 4
+#define VUL9_END_ADDR_MASK 0xfffffff
+#define VUL9_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL9_RCH_MON */
+#define VUL9_RCH_DATA_SFT 0
+#define VUL9_RCH_DATA_MASK 0xffffffff
+#define VUL9_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL9_LCH_MON */
+#define VUL9_LCH_DATA_SFT 0
+#define VUL9_LCH_DATA_MASK 0xffffffff
+#define VUL9_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL9_CON0 */
+#define VUL9_ON_SFT 28
+#define VUL9_ON_MASK 0x1
+#define VUL9_ON_MASK_SFT (0x1 << 28)
+#define VUL9_MINLEN_SFT 20
+#define VUL9_MINLEN_MASK 0x3
+#define VUL9_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL9_MAXLEN_SFT 16
+#define VUL9_MAXLEN_MASK 0x3
+#define VUL9_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL9_SEL_DOMAIN_SFT 13
+#define VUL9_SEL_DOMAIN_MASK 0x7
+#define VUL9_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL9_SEL_FS_SFT 8
+#define VUL9_SEL_FS_MASK 0x1f
+#define VUL9_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL9_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL9_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL9_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL9_WR_SIGN_SFT 6
+#define VUL9_WR_SIGN_MASK 0x1
+#define VUL9_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL9_R_MONO_SFT 5
+#define VUL9_R_MONO_MASK 0x1
+#define VUL9_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL9_MONO_SFT 4
+#define VUL9_MONO_MASK 0x1
+#define VUL9_MONO_MASK_SFT (0x1 << 4)
+#define VUL9_NORMAL_MODE_SFT 3
+#define VUL9_NORMAL_MODE_MASK 0x1
+#define VUL9_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL9_HALIGN_SFT 2
+#define VUL9_HALIGN_MASK 0x1
+#define VUL9_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL9_HD_MODE_SFT 0
+#define VUL9_HD_MODE_MASK 0x3
+#define VUL9_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL10_BASE_MSB */
+#define VUL10_BASE_ADDR_MSB_SFT 0
+#define VUL10_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL10_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL10_BASE */
+#define VUL10_BASE_ADDR_SFT 4
+#define VUL10_BASE_ADDR_MASK 0xfffffff
+#define VUL10_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL10_CUR_MSB */
+#define VUL10_CUR_PTR_MSB_SFT 0
+#define VUL10_CUR_PTR_MSB_MASK 0x1ff
+#define VUL10_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL10_CUR */
+#define VUL10_CUR_PTR_SFT 0
+#define VUL10_CUR_PTR_MASK 0xffffffff
+#define VUL10_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL10_END_MSB */
+#define VUL10_END_ADDR_MSB_SFT 0
+#define VUL10_END_ADDR_MSB_MASK 0x1ff
+#define VUL10_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL10_END */
+#define VUL10_END_ADDR_SFT 4
+#define VUL10_END_ADDR_MASK 0xfffffff
+#define VUL10_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL10_RCH_MON */
+#define VUL10_RCH_DATA_SFT 0
+#define VUL10_RCH_DATA_MASK 0xffffffff
+#define VUL10_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL10_LCH_MON */
+#define VUL10_LCH_DATA_SFT 0
+#define VUL10_LCH_DATA_MASK 0xffffffff
+#define VUL10_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL10_CON0 */
+#define VUL10_ON_SFT 28
+#define VUL10_ON_MASK 0x1
+#define VUL10_ON_MASK_SFT (0x1 << 28)
+#define VUL10_MINLEN_SFT 20
+#define VUL10_MINLEN_MASK 0x3
+#define VUL10_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL10_MAXLEN_SFT 16
+#define VUL10_MAXLEN_MASK 0x3
+#define VUL10_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL10_SEL_DOMAIN_SFT 13
+#define VUL10_SEL_DOMAIN_MASK 0x7
+#define VUL10_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL10_SEL_FS_SFT 8
+#define VUL10_SEL_FS_MASK 0x1f
+#define VUL10_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL10_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL10_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL10_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL10_WR_SIGN_SFT 6
+#define VUL10_WR_SIGN_MASK 0x1
+#define VUL10_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL10_R_MONO_SFT 5
+#define VUL10_R_MONO_MASK 0x1
+#define VUL10_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL10_MONO_SFT 4
+#define VUL10_MONO_MASK 0x1
+#define VUL10_MONO_MASK_SFT (0x1 << 4)
+#define VUL10_NORMAL_MODE_SFT 3
+#define VUL10_NORMAL_MODE_MASK 0x1
+#define VUL10_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL10_HALIGN_SFT 2
+#define VUL10_HALIGN_MASK 0x1
+#define VUL10_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL10_HD_MODE_SFT 0
+#define VUL10_HD_MODE_MASK 0x3
+#define VUL10_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL24_BASE_MSB */
+#define VUL24_BASE_ADDR_MSB_SFT 0
+#define VUL24_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL24_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL24_BASE */
+#define VUL24_BASE_ADDR_SFT 4
+#define VUL24_BASE_ADDR_MASK 0xfffffff
+#define VUL24_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL24_CUR_MSB */
+#define VUL24_CUR_PTR_MSB_SFT 0
+#define VUL24_CUR_PTR_MSB_MASK 0x1ff
+#define VUL24_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL24_CUR */
+#define VUL24_CUR_PTR_SFT 0
+#define VUL24_CUR_PTR_MASK 0xffffffff
+#define VUL24_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL24_END_MSB */
+#define VUL24_END_ADDR_MSB_SFT 0
+#define VUL24_END_ADDR_MSB_MASK 0x1ff
+#define VUL24_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL24_END */
+#define VUL24_END_ADDR_SFT 4
+#define VUL24_END_ADDR_MASK 0xfffffff
+#define VUL24_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL24_CON0 */
+#define OUT_ON_USE_VUL24_SFT 29
+#define OUT_ON_USE_VUL24_MASK 0x1
+#define OUT_ON_USE_VUL24_MASK_SFT (0x1 << 29)
+#define VUL24_ON_SFT 28
+#define VUL24_ON_MASK 0x1
+#define VUL24_ON_MASK_SFT (0x1 << 28)
+#define VUL24_MINLEN_SFT 20
+#define VUL24_MINLEN_MASK 0x3
+#define VUL24_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL24_MAXLEN_SFT 16
+#define VUL24_MAXLEN_MASK 0x3
+#define VUL24_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL24_SEL_DOMAIN_SFT 13
+#define VUL24_SEL_DOMAIN_MASK 0x7
+#define VUL24_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL24_SEL_FS_SFT 8
+#define VUL24_SEL_FS_MASK 0x1f
+#define VUL24_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL24_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL24_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL24_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL24_WR_SIGN_SFT 6
+#define VUL24_WR_SIGN_MASK 0x1
+#define VUL24_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL24_R_MONO_SFT 5
+#define VUL24_R_MONO_MASK 0x1
+#define VUL24_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL24_MONO_SFT 4
+#define VUL24_MONO_MASK 0x1
+#define VUL24_MONO_MASK_SFT (0x1 << 4)
+#define VUL24_NORMAL_MODE_SFT 3
+#define VUL24_NORMAL_MODE_MASK 0x1
+#define VUL24_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL24_HALIGN_SFT 2
+#define VUL24_HALIGN_MASK 0x1
+#define VUL24_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL24_HD_MODE_SFT 0
+#define VUL24_HD_MODE_MASK 0x3
+#define VUL24_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL25_BASE_MSB */
+#define VUL25_BASE_ADDR_MSB_SFT 0
+#define VUL25_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL25_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL25_BASE */
+#define VUL25_BASE_ADDR_SFT 4
+#define VUL25_BASE_ADDR_MASK 0xfffffff
+#define VUL25_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL25_CUR_MSB */
+#define VUL25_CUR_PTR_MSB_SFT 0
+#define VUL25_CUR_PTR_MSB_MASK 0x1ff
+#define VUL25_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL25_CUR */
+#define VUL25_CUR_PTR_SFT 0
+#define VUL25_CUR_PTR_MASK 0xffffffff
+#define VUL25_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL25_END_MSB */
+#define VUL25_END_ADDR_MSB_SFT 0
+#define VUL25_END_ADDR_MSB_MASK 0x1ff
+#define VUL25_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL25_END */
+#define VUL25_END_ADDR_SFT 4
+#define VUL25_END_ADDR_MASK 0xfffffff
+#define VUL25_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL25_CON0 */
+#define OUT_ON_USE_VUL25_SFT 29
+#define OUT_ON_USE_VUL25_MASK 0x1
+#define OUT_ON_USE_VUL25_MASK_SFT (0x1 << 29)
+#define VUL25_ON_SFT 28
+#define VUL25_ON_MASK 0x1
+#define VUL25_ON_MASK_SFT (0x1 << 28)
+#define VUL25_MINLEN_SFT 20
+#define VUL25_MINLEN_MASK 0x3
+#define VUL25_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL25_MAXLEN_SFT 16
+#define VUL25_MAXLEN_MASK 0x3
+#define VUL25_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL25_SEL_DOMAIN_SFT 13
+#define VUL25_SEL_DOMAIN_MASK 0x7
+#define VUL25_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL25_SEL_FS_SFT 8
+#define VUL25_SEL_FS_MASK 0x1f
+#define VUL25_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL25_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL25_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL25_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL25_WR_SIGN_SFT 6
+#define VUL25_WR_SIGN_MASK 0x1
+#define VUL25_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL25_R_MONO_SFT 5
+#define VUL25_R_MONO_MASK 0x1
+#define VUL25_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL25_MONO_SFT 4
+#define VUL25_MONO_MASK 0x1
+#define VUL25_MONO_MASK_SFT (0x1 << 4)
+#define VUL25_NORMAL_MODE_SFT 3
+#define VUL25_NORMAL_MODE_MASK 0x1
+#define VUL25_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL25_HALIGN_SFT 2
+#define VUL25_HALIGN_MASK 0x1
+#define VUL25_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL25_HD_MODE_SFT 0
+#define VUL25_HD_MODE_MASK 0x3
+#define VUL25_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL26_BASE_MSB */
+#define VUL26_BASE_ADDR_MSB_SFT 0
+#define VUL26_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL26_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL26_BASE */
+#define VUL26_BASE_ADDR_SFT 4
+#define VUL26_BASE_ADDR_MASK 0xfffffff
+#define VUL26_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL26_CUR_MSB */
+#define VUL26_CUR_PTR_MSB_SFT 0
+#define VUL26_CUR_PTR_MSB_MASK 0x1ff
+#define VUL26_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL26_CUR */
+#define VUL26_CUR_PTR_SFT 0
+#define VUL26_CUR_PTR_MASK 0xffffffff
+#define VUL26_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL26_END_MSB */
+#define VUL26_END_ADDR_MSB_SFT 0
+#define VUL26_END_ADDR_MSB_MASK 0x1ff
+#define VUL26_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL26_END */
+#define VUL26_END_ADDR_SFT 4
+#define VUL26_END_ADDR_MASK 0xfffffff
+#define VUL26_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL26_CON0 */
+#define OUT_ON_USE_VUL26_SFT 29
+#define OUT_ON_USE_VUL26_MASK 0x1
+#define OUT_ON_USE_VUL26_MASK_SFT (0x1 << 29)
+#define VUL26_ON_SFT 28
+#define VUL26_ON_MASK 0x1
+#define VUL26_ON_MASK_SFT (0x1 << 28)
+#define VUL26_MINLEN_SFT 20
+#define VUL26_MINLEN_MASK 0x3
+#define VUL26_MINLEN_MASK_SFT (0x3 << 20)
+#define VUL26_MAXLEN_SFT 16
+#define VUL26_MAXLEN_MASK 0x3
+#define VUL26_MAXLEN_MASK_SFT (0x3 << 16)
+#define VUL26_SEL_DOMAIN_SFT 13
+#define VUL26_SEL_DOMAIN_MASK 0x7
+#define VUL26_SEL_DOMAIN_MASK_SFT (0x7 << 13)
+#define VUL26_SEL_FS_SFT 8
+#define VUL26_SEL_FS_MASK 0x1f
+#define VUL26_SEL_FS_MASK_SFT (0x1f << 8)
+#define VUL26_SW_CLEAR_BUF_FULL_SFT 7
+#define VUL26_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL26_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 7)
+#define VUL26_WR_SIGN_SFT 6
+#define VUL26_WR_SIGN_MASK 0x1
+#define VUL26_WR_SIGN_MASK_SFT (0x1 << 6)
+#define VUL26_R_MONO_SFT 5
+#define VUL26_R_MONO_MASK 0x1
+#define VUL26_R_MONO_MASK_SFT (0x1 << 5)
+#define VUL26_MONO_SFT 4
+#define VUL26_MONO_MASK 0x1
+#define VUL26_MONO_MASK_SFT (0x1 << 4)
+#define VUL26_NORMAL_MODE_SFT 3
+#define VUL26_NORMAL_MODE_MASK 0x1
+#define VUL26_NORMAL_MODE_MASK_SFT (0x1 << 3)
+#define VUL26_HALIGN_SFT 2
+#define VUL26_HALIGN_MASK 0x1
+#define VUL26_HALIGN_MASK_SFT (0x1 << 2)
+#define VUL26_HD_MODE_SFT 0
+#define VUL26_HD_MODE_MASK 0x3
+#define VUL26_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL_CM0_BASE_MSB */
+#define VUL_CM0_BASE_ADDR_MSB_SFT 0
+#define VUL_CM0_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL_CM0_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL_CM0_BASE */
+#define VUL_CM0_BASE_ADDR_SFT 4
+#define VUL_CM0_BASE_ADDR_MASK 0xfffffff
+#define VUL_CM0_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL_CM0_CUR_MSB */
+#define VUL_CM0_CUR_PTR_MSB_SFT 0
+#define VUL_CM0_CUR_PTR_MSB_MASK 0x1ff
+#define VUL_CM0_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL_CM0_CUR */
+#define VUL_CM0_CUR_PTR_SFT 0
+#define VUL_CM0_CUR_PTR_MASK 0xffffffff
+#define VUL_CM0_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL_CM0_END_MSB */
+#define VUL_CM0_END_ADDR_MSB_SFT 0
+#define VUL_CM0_END_ADDR_MSB_MASK 0x1ff
+#define VUL_CM0_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL_CM0_END */
+#define VUL_CM0_END_ADDR_SFT 4
+#define VUL_CM0_END_ADDR_MASK 0xfffffff
+#define VUL_CM0_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL_CM0_CON0 */
+#define VUL_CM0_ON_SFT 28
+#define VUL_CM0_ON_MASK 0x1
+#define VUL_CM0_ON_MASK_SFT (0x1 << 28)
+#define VUL_CM0_REG_CH_SHIFT_MODE_SFT 26
+#define VUL_CM0_REG_CH_SHIFT_MODE_MASK 0x1
+#define VUL_CM0_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define VUL_CM0_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define VUL_CM0_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define VUL_CM0_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define VUL_CM0_SW_CLEAR_BUF_FULL_SFT 24
+#define VUL_CM0_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL_CM0_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define VUL_CM0_ULTRA_TH_SFT 20
+#define VUL_CM0_ULTRA_TH_MASK 0xf
+#define VUL_CM0_ULTRA_TH_MASK_SFT (0xf << 20)
+#define VUL_CM0_NORMAL_MODE_SFT 17
+#define VUL_CM0_NORMAL_MODE_MASK 0x1
+#define VUL_CM0_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define VUL_CM0_ODD_USE_EVEN_SFT 16
+#define VUL_CM0_ODD_USE_EVEN_MASK 0x1
+#define VUL_CM0_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define VUL_CM0_AXI_REQ_MAXLEN_SFT 12
+#define VUL_CM0_AXI_REQ_MAXLEN_MASK 0x3
+#define VUL_CM0_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define VUL_CM0_AXI_REQ_MINLEN_SFT 8
+#define VUL_CM0_AXI_REQ_MINLEN_MASK 0x3
+#define VUL_CM0_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define VUL_CM0_HALIGN_SFT 7
+#define VUL_CM0_HALIGN_MASK 0x1
+#define VUL_CM0_HALIGN_MASK_SFT (0x1 << 7)
+#define VUL_CM0_SIGN_EXT_SFT 6
+#define VUL_CM0_SIGN_EXT_MASK 0x1
+#define VUL_CM0_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define VUL_CM0_HD_MODE_SFT 4
+#define VUL_CM0_HD_MODE_MASK 0x3
+#define VUL_CM0_HD_MODE_MASK_SFT (0x3 << 4)
+#define VUL_CM0_MAKE_EXTRA_UPDATE_SFT 3
+#define VUL_CM0_MAKE_EXTRA_UPDATE_MASK 0x1
+#define VUL_CM0_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define VUL_CM0_AGENT_FREE_RUN_SFT 2
+#define VUL_CM0_AGENT_FREE_RUN_MASK 0x1
+#define VUL_CM0_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define VUL_CM0_USE_INT_ODD_SFT 1
+#define VUL_CM0_USE_INT_ODD_MASK 0x1
+#define VUL_CM0_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define VUL_CM0_INT_ODD_FLAG_SFT 0
+#define VUL_CM0_INT_ODD_FLAG_MASK 0x1
+#define VUL_CM0_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_VUL_CM1_BASE_MSB */
+#define VUL_CM1_BASE_ADDR_MSB_SFT 0
+#define VUL_CM1_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL_CM1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL_CM1_BASE */
+#define VUL_CM1_BASE_ADDR_SFT 4
+#define VUL_CM1_BASE_ADDR_MASK 0xfffffff
+#define VUL_CM1_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL_CM1_CUR_MSB */
+#define VUL_CM1_CUR_PTR_MSB_SFT 0
+#define VUL_CM1_CUR_PTR_MSB_MASK 0x1ff
+#define VUL_CM1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL_CM1_CUR */
+#define VUL_CM1_CUR_PTR_SFT 0
+#define VUL_CM1_CUR_PTR_MASK 0xffffffff
+#define VUL_CM1_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL_CM1_END_MSB */
+#define VUL_CM1_END_ADDR_MSB_SFT 0
+#define VUL_CM1_END_ADDR_MSB_MASK 0x1ff
+#define VUL_CM1_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL_CM1_END */
+#define VUL_CM1_END_ADDR_SFT 4
+#define VUL_CM1_END_ADDR_MASK 0xfffffff
+#define VUL_CM1_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL_CM1_CON0 */
+#define VUL_CM1_ON_SFT 28
+#define VUL_CM1_ON_MASK 0x1
+#define VUL_CM1_ON_MASK_SFT (0x1 << 28)
+#define VUL_CM1_REG_CH_SHIFT_MODE_SFT 26
+#define VUL_CM1_REG_CH_SHIFT_MODE_MASK 0x1
+#define VUL_CM1_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define VUL_CM1_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define VUL_CM1_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define VUL_CM1_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define VUL_CM1_SW_CLEAR_BUF_FULL_SFT 24
+#define VUL_CM1_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL_CM1_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define VUL_CM1_ULTRA_TH_SFT 20
+#define VUL_CM1_ULTRA_TH_MASK 0xf
+#define VUL_CM1_ULTRA_TH_MASK_SFT (0xf << 20)
+#define VUL_CM1_NORMAL_MODE_SFT 17
+#define VUL_CM1_NORMAL_MODE_MASK 0x1
+#define VUL_CM1_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define VUL_CM1_ODD_USE_EVEN_SFT 16
+#define VUL_CM1_ODD_USE_EVEN_MASK 0x1
+#define VUL_CM1_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define VUL_CM1_AXI_REQ_MAXLEN_SFT 12
+#define VUL_CM1_AXI_REQ_MAXLEN_MASK 0x3
+#define VUL_CM1_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define VUL_CM1_AXI_REQ_MINLEN_SFT 8
+#define VUL_CM1_AXI_REQ_MINLEN_MASK 0x3
+#define VUL_CM1_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define VUL_CM1_HALIGN_SFT 7
+#define VUL_CM1_HALIGN_MASK 0x1
+#define VUL_CM1_HALIGN_MASK_SFT (0x1 << 7)
+#define VUL_CM1_SIGN_EXT_SFT 6
+#define VUL_CM1_SIGN_EXT_MASK 0x1
+#define VUL_CM1_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define VUL_CM1_HD_MODE_SFT 4
+#define VUL_CM1_HD_MODE_MASK 0x3
+#define VUL_CM1_HD_MODE_MASK_SFT (0x3 << 4)
+#define VUL_CM1_MAKE_EXTRA_UPDATE_SFT 3
+#define VUL_CM1_MAKE_EXTRA_UPDATE_MASK 0x1
+#define VUL_CM1_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define VUL_CM1_AGENT_FREE_RUN_SFT 2
+#define VUL_CM1_AGENT_FREE_RUN_MASK 0x1
+#define VUL_CM1_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define VUL_CM1_USE_INT_ODD_SFT 1
+#define VUL_CM1_USE_INT_ODD_MASK 0x1
+#define VUL_CM1_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define VUL_CM1_INT_ODD_FLAG_SFT 0
+#define VUL_CM1_INT_ODD_FLAG_MASK 0x1
+#define VUL_CM1_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_VUL_CM2_BASE_MSB */
+#define VUL_CM2_BASE_ADDR_MSB_SFT 0
+#define VUL_CM2_BASE_ADDR_MSB_MASK 0x1ff
+#define VUL_CM2_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL_CM2_BASE */
+#define VUL_CM2_BASE_ADDR_SFT 4
+#define VUL_CM2_BASE_ADDR_MASK 0xfffffff
+#define VUL_CM2_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL_CM2_CUR_MSB */
+#define VUL_CM2_CUR_PTR_MSB_SFT 0
+#define VUL_CM2_CUR_PTR_MSB_MASK 0x1ff
+#define VUL_CM2_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL_CM2_CUR */
+#define VUL_CM2_CUR_PTR_SFT 0
+#define VUL_CM2_CUR_PTR_MASK 0xffffffff
+#define VUL_CM2_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL_CM2_END_MSB */
+#define VUL_CM2_END_ADDR_MSB_SFT 0
+#define VUL_CM2_END_ADDR_MSB_MASK 0x1ff
+#define VUL_CM2_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_VUL_CM2_END */
+#define VUL_CM2_END_ADDR_SFT 4
+#define VUL_CM2_END_ADDR_MASK 0xfffffff
+#define VUL_CM2_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_VUL_CM2_CON0 */
+#define VUL_CM2_ON_SFT 28
+#define VUL_CM2_ON_MASK 0x1
+#define VUL_CM2_ON_MASK_SFT (0x1 << 28)
+#define VUL_CM2_REG_CH_SHIFT_MODE_SFT 26
+#define VUL_CM2_REG_CH_SHIFT_MODE_MASK 0x1
+#define VUL_CM2_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define VUL_CM2_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define VUL_CM2_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define VUL_CM2_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define VUL_CM2_SW_CLEAR_BUF_FULL_SFT 24
+#define VUL_CM2_SW_CLEAR_BUF_FULL_MASK 0x1
+#define VUL_CM2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define VUL_CM2_ULTRA_TH_SFT 20
+#define VUL_CM2_ULTRA_TH_MASK 0xf
+#define VUL_CM2_ULTRA_TH_MASK_SFT (0xf << 20)
+#define VUL_CM2_NORMAL_MODE_SFT 17
+#define VUL_CM2_NORMAL_MODE_MASK 0x1
+#define VUL_CM2_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define VUL_CM2_ODD_USE_EVEN_SFT 16
+#define VUL_CM2_ODD_USE_EVEN_MASK 0x1
+#define VUL_CM2_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define VUL_CM2_AXI_REQ_MAXLEN_SFT 12
+#define VUL_CM2_AXI_REQ_MAXLEN_MASK 0x3
+#define VUL_CM2_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define VUL_CM2_AXI_REQ_MINLEN_SFT 8
+#define VUL_CM2_AXI_REQ_MINLEN_MASK 0x3
+#define VUL_CM2_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define VUL_CM2_HALIGN_SFT 7
+#define VUL_CM2_HALIGN_MASK 0x1
+#define VUL_CM2_HALIGN_MASK_SFT (0x1 << 7)
+#define VUL_CM2_SIGN_EXT_SFT 6
+#define VUL_CM2_SIGN_EXT_MASK 0x1
+#define VUL_CM2_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define VUL_CM2_HD_MODE_SFT 4
+#define VUL_CM2_HD_MODE_MASK 0x3
+#define VUL_CM2_HD_MODE_MASK_SFT (0x3 << 4)
+#define VUL_CM2_MAKE_EXTRA_UPDATE_SFT 3
+#define VUL_CM2_MAKE_EXTRA_UPDATE_MASK 0x1
+#define VUL_CM2_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define VUL_CM2_AGENT_FREE_RUN_SFT 2
+#define VUL_CM2_AGENT_FREE_RUN_MASK 0x1
+#define VUL_CM2_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define VUL_CM2_USE_INT_ODD_SFT 1
+#define VUL_CM2_USE_INT_ODD_MASK 0x1
+#define VUL_CM2_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define VUL_CM2_INT_ODD_FLAG_SFT 0
+#define VUL_CM2_INT_ODD_FLAG_MASK 0x1
+#define VUL_CM2_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_ETDM_IN0_BASE_MSB */
+#define ETDM_IN0_BASE_ADDR_MSB_SFT 0
+#define ETDM_IN0_BASE_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN0_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN0_BASE */
+#define ETDM_IN0_BASE_ADDR_SFT 4
+#define ETDM_IN0_BASE_ADDR_MASK 0xfffffff
+#define ETDM_IN0_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN0_CUR_MSB */
+#define ETDM_IN0_CUR_PTR_MSB_SFT 0
+#define ETDM_IN0_CUR_PTR_MSB_MASK 0x1ff
+#define ETDM_IN0_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN0_CUR */
+#define ETDM_IN0_CUR_PTR_SFT 0
+#define ETDM_IN0_CUR_PTR_MASK 0xffffffff
+#define ETDM_IN0_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ETDM_IN0_END_MSB */
+#define ETDM_IN0_END_ADDR_MSB_SFT 0
+#define ETDM_IN0_END_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN0_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN0_END */
+#define ETDM_IN0_END_ADDR_SFT 4
+#define ETDM_IN0_END_ADDR_MASK 0xfffffff
+#define ETDM_IN0_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN0_CON0 */
+#define ETDM_IN0_CH_NUM_SFT 28
+#define ETDM_IN0_CH_NUM_MASK 0xf
+#define ETDM_IN0_CH_NUM_MASK_SFT (0xf << 28)
+#define ETDM_IN0_ON_SFT 27
+#define ETDM_IN0_ON_MASK 0x1
+#define ETDM_IN0_ON_MASK_SFT (0x1 << 27)
+#define ETDM_IN0_REG_CH_SHIFT_MODE_SFT 26
+#define ETDM_IN0_REG_CH_SHIFT_MODE_MASK 0x1
+#define ETDM_IN0_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define ETDM_IN0_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define ETDM_IN0_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define ETDM_IN0_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define ETDM_IN0_SW_CLEAR_BUF_FULL_SFT 24
+#define ETDM_IN0_SW_CLEAR_BUF_FULL_MASK 0x1
+#define ETDM_IN0_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define ETDM_IN0_ULTRA_TH_SFT 20
+#define ETDM_IN0_ULTRA_TH_MASK 0xf
+#define ETDM_IN0_ULTRA_TH_MASK_SFT (0xf << 20)
+#define ETDM_IN0_NORMAL_MODE_SFT 17
+#define ETDM_IN0_NORMAL_MODE_MASK 0x1
+#define ETDM_IN0_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define ETDM_IN0_ODD_USE_EVEN_SFT 16
+#define ETDM_IN0_ODD_USE_EVEN_MASK 0x1
+#define ETDM_IN0_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define ETDM_IN0_AXI_REQ_MAXLEN_SFT 12
+#define ETDM_IN0_AXI_REQ_MAXLEN_MASK 0x3
+#define ETDM_IN0_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define ETDM_IN0_AXI_REQ_MINLEN_SFT 8
+#define ETDM_IN0_AXI_REQ_MINLEN_MASK 0x3
+#define ETDM_IN0_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define ETDM_IN0_HALIGN_SFT 7
+#define ETDM_IN0_HALIGN_MASK 0x1
+#define ETDM_IN0_HALIGN_MASK_SFT (0x1 << 7)
+#define ETDM_IN0_SIGN_EXT_SFT 6
+#define ETDM_IN0_SIGN_EXT_MASK 0x1
+#define ETDM_IN0_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define ETDM_IN0_HD_MODE_SFT 4
+#define ETDM_IN0_HD_MODE_MASK 0x3
+#define ETDM_IN0_HD_MODE_MASK_SFT (0x3 << 4)
+#define ETDM_IN0_MAKE_EXTRA_UPDATE_SFT 3
+#define ETDM_IN0_MAKE_EXTRA_UPDATE_MASK 0x1
+#define ETDM_IN0_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define ETDM_IN0_AGENT_FREE_RUN_SFT 2
+#define ETDM_IN0_AGENT_FREE_RUN_MASK 0x1
+#define ETDM_IN0_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define ETDM_IN0_USE_INT_ODD_SFT 1
+#define ETDM_IN0_USE_INT_ODD_MASK 0x1
+#define ETDM_IN0_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define ETDM_IN0_INT_ODD_FLAG_SFT 0
+#define ETDM_IN0_INT_ODD_FLAG_MASK 0x1
+#define ETDM_IN0_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_ETDM_IN1_BASE_MSB */
+#define ETDM_IN1_BASE_ADDR_MSB_SFT 0
+#define ETDM_IN1_BASE_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN1_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN1_BASE */
+#define ETDM_IN1_BASE_ADDR_SFT 4
+#define ETDM_IN1_BASE_ADDR_MASK 0xfffffff
+#define ETDM_IN1_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN1_CUR_MSB */
+#define ETDM_IN1_CUR_PTR_MSB_SFT 0
+#define ETDM_IN1_CUR_PTR_MSB_MASK 0x1ff
+#define ETDM_IN1_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN1_CUR */
+#define ETDM_IN1_CUR_PTR_SFT 0
+#define ETDM_IN1_CUR_PTR_MASK 0xffffffff
+#define ETDM_IN1_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ETDM_IN1_END_MSB */
+#define ETDM_IN1_END_ADDR_MSB_SFT 0
+#define ETDM_IN1_END_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN1_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN1_END */
+#define ETDM_IN1_END_ADDR_SFT 4
+#define ETDM_IN1_END_ADDR_MASK 0xfffffff
+#define ETDM_IN1_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN1_CON0 */
+#define ETDM_IN1_CH_NUM_SFT 28
+#define ETDM_IN1_CH_NUM_MASK 0xf
+#define ETDM_IN1_CH_NUM_MASK_SFT (0xf << 28)
+#define ETDM_IN1_ON_SFT 27
+#define ETDM_IN1_ON_MASK 0x1
+#define ETDM_IN1_ON_MASK_SFT (0x1 << 27)
+#define ETDM_IN1_REG_CH_SHIFT_MODE_SFT 26
+#define ETDM_IN1_REG_CH_SHIFT_MODE_MASK 0x1
+#define ETDM_IN1_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define ETDM_IN1_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define ETDM_IN1_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define ETDM_IN1_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define ETDM_IN1_SW_CLEAR_BUF_FULL_SFT 24
+#define ETDM_IN1_SW_CLEAR_BUF_FULL_MASK 0x1
+#define ETDM_IN1_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define ETDM_IN1_ULTRA_TH_SFT 20
+#define ETDM_IN1_ULTRA_TH_MASK 0xf
+#define ETDM_IN1_ULTRA_TH_MASK_SFT (0xf << 20)
+#define ETDM_IN1_NORMAL_MODE_SFT 17
+#define ETDM_IN1_NORMAL_MODE_MASK 0x1
+#define ETDM_IN1_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define ETDM_IN1_ODD_USE_EVEN_SFT 16
+#define ETDM_IN1_ODD_USE_EVEN_MASK 0x1
+#define ETDM_IN1_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define ETDM_IN1_AXI_REQ_MAXLEN_SFT 12
+#define ETDM_IN1_AXI_REQ_MAXLEN_MASK 0x3
+#define ETDM_IN1_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define ETDM_IN1_AXI_REQ_MINLEN_SFT 8
+#define ETDM_IN1_AXI_REQ_MINLEN_MASK 0x3
+#define ETDM_IN1_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define ETDM_IN1_HALIGN_SFT 7
+#define ETDM_IN1_HALIGN_MASK 0x1
+#define ETDM_IN1_HALIGN_MASK_SFT (0x1 << 7)
+#define ETDM_IN1_SIGN_EXT_SFT 6
+#define ETDM_IN1_SIGN_EXT_MASK 0x1
+#define ETDM_IN1_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define ETDM_IN1_HD_MODE_SFT 4
+#define ETDM_IN1_HD_MODE_MASK 0x3
+#define ETDM_IN1_HD_MODE_MASK_SFT (0x3 << 4)
+#define ETDM_IN1_MAKE_EXTRA_UPDATE_SFT 3
+#define ETDM_IN1_MAKE_EXTRA_UPDATE_MASK 0x1
+#define ETDM_IN1_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define ETDM_IN1_AGENT_FREE_RUN_SFT 2
+#define ETDM_IN1_AGENT_FREE_RUN_MASK 0x1
+#define ETDM_IN1_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define ETDM_IN1_USE_INT_ODD_SFT 1
+#define ETDM_IN1_USE_INT_ODD_MASK 0x1
+#define ETDM_IN1_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define ETDM_IN1_INT_ODD_FLAG_SFT 0
+#define ETDM_IN1_INT_ODD_FLAG_MASK 0x1
+#define ETDM_IN1_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_ETDM_IN2_BASE_MSB */
+#define ETDM_IN2_BASE_ADDR_MSB_SFT 0
+#define ETDM_IN2_BASE_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN2_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN2_BASE */
+#define ETDM_IN2_BASE_ADDR_SFT 4
+#define ETDM_IN2_BASE_ADDR_MASK 0xfffffff
+#define ETDM_IN2_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN2_CUR_MSB */
+#define ETDM_IN2_CUR_PTR_MSB_SFT 0
+#define ETDM_IN2_CUR_PTR_MSB_MASK 0x1ff
+#define ETDM_IN2_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN2_CUR */
+#define ETDM_IN2_CUR_PTR_SFT 0
+#define ETDM_IN2_CUR_PTR_MASK 0xffffffff
+#define ETDM_IN2_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ETDM_IN2_END_MSB */
+#define ETDM_IN2_END_ADDR_MSB_SFT 0
+#define ETDM_IN2_END_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN2_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN2_END */
+#define ETDM_IN2_END_ADDR_SFT 4
+#define ETDM_IN2_END_ADDR_MASK 0xfffffff
+#define ETDM_IN2_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN2_CON0 */
+#define ETDM_IN2_CH_NUM_SFT 28
+#define ETDM_IN2_CH_NUM_MASK 0xf
+#define ETDM_IN2_CH_NUM_MASK_SFT (0xf << 28)
+#define ETDM_IN2_ON_SFT 27
+#define ETDM_IN2_ON_MASK 0x1
+#define ETDM_IN2_ON_MASK_SFT (0x1 << 27)
+#define ETDM_IN2_REG_CH_SHIFT_MODE_SFT 26
+#define ETDM_IN2_REG_CH_SHIFT_MODE_MASK 0x1
+#define ETDM_IN2_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define ETDM_IN2_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define ETDM_IN2_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define ETDM_IN2_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define ETDM_IN2_SW_CLEAR_BUF_FULL_SFT 24
+#define ETDM_IN2_SW_CLEAR_BUF_FULL_MASK 0x1
+#define ETDM_IN2_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define ETDM_IN2_ULTRA_TH_SFT 20
+#define ETDM_IN2_ULTRA_TH_MASK 0xf
+#define ETDM_IN2_ULTRA_TH_MASK_SFT (0xf << 20)
+#define ETDM_IN2_NORMAL_MODE_SFT 17
+#define ETDM_IN2_NORMAL_MODE_MASK 0x1
+#define ETDM_IN2_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define ETDM_IN2_ODD_USE_EVEN_SFT 16
+#define ETDM_IN2_ODD_USE_EVEN_MASK 0x1
+#define ETDM_IN2_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define ETDM_IN2_AXI_REQ_MAXLEN_SFT 12
+#define ETDM_IN2_AXI_REQ_MAXLEN_MASK 0x3
+#define ETDM_IN2_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define ETDM_IN2_AXI_REQ_MINLEN_SFT 8
+#define ETDM_IN2_AXI_REQ_MINLEN_MASK 0x3
+#define ETDM_IN2_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define ETDM_IN2_HALIGN_SFT 7
+#define ETDM_IN2_HALIGN_MASK 0x1
+#define ETDM_IN2_HALIGN_MASK_SFT (0x1 << 7)
+#define ETDM_IN2_SIGN_EXT_SFT 6
+#define ETDM_IN2_SIGN_EXT_MASK 0x1
+#define ETDM_IN2_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define ETDM_IN2_HD_MODE_SFT 4
+#define ETDM_IN2_HD_MODE_MASK 0x3
+#define ETDM_IN2_HD_MODE_MASK_SFT (0x3 << 4)
+#define ETDM_IN2_MAKE_EXTRA_UPDATE_SFT 3
+#define ETDM_IN2_MAKE_EXTRA_UPDATE_MASK 0x1
+#define ETDM_IN2_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define ETDM_IN2_AGENT_FREE_RUN_SFT 2
+#define ETDM_IN2_AGENT_FREE_RUN_MASK 0x1
+#define ETDM_IN2_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define ETDM_IN2_USE_INT_ODD_SFT 1
+#define ETDM_IN2_USE_INT_ODD_MASK 0x1
+#define ETDM_IN2_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define ETDM_IN2_INT_ODD_FLAG_SFT 0
+#define ETDM_IN2_INT_ODD_FLAG_MASK 0x1
+#define ETDM_IN2_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_ETDM_IN3_BASE_MSB */
+#define ETDM_IN3_BASE_ADDR_MSB_SFT 0
+#define ETDM_IN3_BASE_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN3_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN3_BASE */
+#define ETDM_IN3_BASE_ADDR_SFT 4
+#define ETDM_IN3_BASE_ADDR_MASK 0xfffffff
+#define ETDM_IN3_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN3_CUR_MSB */
+#define ETDM_IN3_CUR_PTR_MSB_SFT 0
+#define ETDM_IN3_CUR_PTR_MSB_MASK 0x1ff
+#define ETDM_IN3_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN3_CUR */
+#define ETDM_IN3_CUR_PTR_SFT 0
+#define ETDM_IN3_CUR_PTR_MASK 0xffffffff
+#define ETDM_IN3_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ETDM_IN3_END_MSB */
+#define ETDM_IN3_END_ADDR_MSB_SFT 0
+#define ETDM_IN3_END_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN3_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN3_END */
+#define ETDM_IN3_END_ADDR_SFT 4
+#define ETDM_IN3_END_ADDR_MASK 0xfffffff
+#define ETDM_IN3_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN3_CON0 */
+#define ETDM_IN3_CH_NUM_SFT 28
+#define ETDM_IN3_CH_NUM_MASK 0xf
+#define ETDM_IN3_CH_NUM_MASK_SFT (0xf << 28)
+#define ETDM_IN3_ON_SFT 27
+#define ETDM_IN3_ON_MASK 0x1
+#define ETDM_IN3_ON_MASK_SFT (0x1 << 27)
+#define ETDM_IN3_REG_CH_SHIFT_MODE_SFT 26
+#define ETDM_IN3_REG_CH_SHIFT_MODE_MASK 0x1
+#define ETDM_IN3_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define ETDM_IN3_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define ETDM_IN3_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define ETDM_IN3_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define ETDM_IN3_SW_CLEAR_BUF_FULL_SFT 24
+#define ETDM_IN3_SW_CLEAR_BUF_FULL_MASK 0x1
+#define ETDM_IN3_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define ETDM_IN3_ULTRA_TH_SFT 20
+#define ETDM_IN3_ULTRA_TH_MASK 0xf
+#define ETDM_IN3_ULTRA_TH_MASK_SFT (0xf << 20)
+#define ETDM_IN3_NORMAL_MODE_SFT 17
+#define ETDM_IN3_NORMAL_MODE_MASK 0x1
+#define ETDM_IN3_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define ETDM_IN3_ODD_USE_EVEN_SFT 16
+#define ETDM_IN3_ODD_USE_EVEN_MASK 0x1
+#define ETDM_IN3_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define ETDM_IN3_AXI_REQ_MAXLEN_SFT 12
+#define ETDM_IN3_AXI_REQ_MAXLEN_MASK 0x3
+#define ETDM_IN3_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define ETDM_IN3_AXI_REQ_MINLEN_SFT 8
+#define ETDM_IN3_AXI_REQ_MINLEN_MASK 0x3
+#define ETDM_IN3_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define ETDM_IN3_HALIGN_SFT 7
+#define ETDM_IN3_HALIGN_MASK 0x1
+#define ETDM_IN3_HALIGN_MASK_SFT (0x1 << 7)
+#define ETDM_IN3_SIGN_EXT_SFT 6
+#define ETDM_IN3_SIGN_EXT_MASK 0x1
+#define ETDM_IN3_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define ETDM_IN3_HD_MODE_SFT 4
+#define ETDM_IN3_HD_MODE_MASK 0x3
+#define ETDM_IN3_HD_MODE_MASK_SFT (0x3 << 4)
+#define ETDM_IN3_MAKE_EXTRA_UPDATE_SFT 3
+#define ETDM_IN3_MAKE_EXTRA_UPDATE_MASK 0x1
+#define ETDM_IN3_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define ETDM_IN3_AGENT_FREE_RUN_SFT 2
+#define ETDM_IN3_AGENT_FREE_RUN_MASK 0x1
+#define ETDM_IN3_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define ETDM_IN3_USE_INT_ODD_SFT 1
+#define ETDM_IN3_USE_INT_ODD_MASK 0x1
+#define ETDM_IN3_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define ETDM_IN3_INT_ODD_FLAG_SFT 0
+#define ETDM_IN3_INT_ODD_FLAG_MASK 0x1
+#define ETDM_IN3_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_ETDM_IN4_BASE_MSB */
+#define ETDM_IN4_BASE_ADDR_MSB_SFT 0
+#define ETDM_IN4_BASE_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN4_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN4_BASE */
+#define ETDM_IN4_BASE_ADDR_SFT 4
+#define ETDM_IN4_BASE_ADDR_MASK 0xfffffff
+#define ETDM_IN4_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN4_CUR_MSB */
+#define ETDM_IN4_CUR_PTR_MSB_SFT 0
+#define ETDM_IN4_CUR_PTR_MSB_MASK 0x1ff
+#define ETDM_IN4_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN4_CUR */
+#define ETDM_IN4_CUR_PTR_SFT 0
+#define ETDM_IN4_CUR_PTR_MASK 0xffffffff
+#define ETDM_IN4_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ETDM_IN4_END_MSB */
+#define ETDM_IN4_END_ADDR_MSB_SFT 0
+#define ETDM_IN4_END_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN4_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN4_END */
+#define ETDM_IN4_END_ADDR_SFT 4
+#define ETDM_IN4_END_ADDR_MASK 0xfffffff
+#define ETDM_IN4_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN4_CON0 */
+#define ETDM_IN4_CH_NUM_SFT 28
+#define ETDM_IN4_CH_NUM_MASK 0xf
+#define ETDM_IN4_CH_NUM_MASK_SFT (0xf << 28)
+#define ETDM_IN4_ON_SFT 27
+#define ETDM_IN4_ON_MASK 0x1
+#define ETDM_IN4_ON_MASK_SFT (0x1 << 27)
+#define ETDM_IN4_REG_CH_SHIFT_MODE_SFT 26
+#define ETDM_IN4_REG_CH_SHIFT_MODE_MASK 0x1
+#define ETDM_IN4_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define ETDM_IN4_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define ETDM_IN4_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define ETDM_IN4_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define ETDM_IN4_SW_CLEAR_BUF_FULL_SFT 24
+#define ETDM_IN4_SW_CLEAR_BUF_FULL_MASK 0x1
+#define ETDM_IN4_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define ETDM_IN4_ULTRA_TH_SFT 20
+#define ETDM_IN4_ULTRA_TH_MASK 0xf
+#define ETDM_IN4_ULTRA_TH_MASK_SFT (0xf << 20)
+#define ETDM_IN4_NORMAL_MODE_SFT 17
+#define ETDM_IN4_NORMAL_MODE_MASK 0x1
+#define ETDM_IN4_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define ETDM_IN4_ODD_USE_EVEN_SFT 16
+#define ETDM_IN4_ODD_USE_EVEN_MASK 0x1
+#define ETDM_IN4_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define ETDM_IN4_AXI_REQ_MAXLEN_SFT 12
+#define ETDM_IN4_AXI_REQ_MAXLEN_MASK 0x3
+#define ETDM_IN4_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define ETDM_IN4_AXI_REQ_MINLEN_SFT 8
+#define ETDM_IN4_AXI_REQ_MINLEN_MASK 0x3
+#define ETDM_IN4_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define ETDM_IN4_HALIGN_SFT 7
+#define ETDM_IN4_HALIGN_MASK 0x1
+#define ETDM_IN4_HALIGN_MASK_SFT (0x1 << 7)
+#define ETDM_IN4_SIGN_EXT_SFT 6
+#define ETDM_IN4_SIGN_EXT_MASK 0x1
+#define ETDM_IN4_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define ETDM_IN4_HD_MODE_SFT 4
+#define ETDM_IN4_HD_MODE_MASK 0x3
+#define ETDM_IN4_HD_MODE_MASK_SFT (0x3 << 4)
+#define ETDM_IN4_MAKE_EXTRA_UPDATE_SFT 3
+#define ETDM_IN4_MAKE_EXTRA_UPDATE_MASK 0x1
+#define ETDM_IN4_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define ETDM_IN4_AGENT_FREE_RUN_SFT 2
+#define ETDM_IN4_AGENT_FREE_RUN_MASK 0x1
+#define ETDM_IN4_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define ETDM_IN4_USE_INT_ODD_SFT 1
+#define ETDM_IN4_USE_INT_ODD_MASK 0x1
+#define ETDM_IN4_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define ETDM_IN4_INT_ODD_FLAG_SFT 0
+#define ETDM_IN4_INT_ODD_FLAG_MASK 0x1
+#define ETDM_IN4_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_ETDM_IN5_BASE_MSB */
+#define ETDM_IN5_BASE_ADDR_MSB_SFT 0
+#define ETDM_IN5_BASE_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN5_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN5_BASE */
+#define ETDM_IN5_BASE_ADDR_SFT 4
+#define ETDM_IN5_BASE_ADDR_MASK 0xfffffff
+#define ETDM_IN5_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN5_CUR_MSB */
+#define ETDM_IN5_CUR_PTR_MSB_SFT 0
+#define ETDM_IN5_CUR_PTR_MSB_MASK 0x1ff
+#define ETDM_IN5_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN5_CUR */
+#define ETDM_IN5_CUR_PTR_SFT 0
+#define ETDM_IN5_CUR_PTR_MASK 0xffffffff
+#define ETDM_IN5_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ETDM_IN5_END_MSB */
+#define ETDM_IN5_END_ADDR_MSB_SFT 0
+#define ETDM_IN5_END_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN5_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN5_END */
+#define ETDM_IN5_END_ADDR_SFT 4
+#define ETDM_IN5_END_ADDR_MASK 0xfffffff
+#define ETDM_IN5_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN5_CON0 */
+#define ETDM_IN5_CH_NUM_SFT 28
+#define ETDM_IN5_CH_NUM_MASK 0xf
+#define ETDM_IN5_CH_NUM_MASK_SFT (0xf << 28)
+#define ETDM_IN5_ON_SFT 27
+#define ETDM_IN5_ON_MASK 0x1
+#define ETDM_IN5_ON_MASK_SFT (0x1 << 27)
+#define ETDM_IN5_REG_CH_SHIFT_MODE_SFT 26
+#define ETDM_IN5_REG_CH_SHIFT_MODE_MASK 0x1
+#define ETDM_IN5_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define ETDM_IN5_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define ETDM_IN5_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define ETDM_IN5_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define ETDM_IN5_SW_CLEAR_BUF_FULL_SFT 24
+#define ETDM_IN5_SW_CLEAR_BUF_FULL_MASK 0x1
+#define ETDM_IN5_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define ETDM_IN5_ULTRA_TH_SFT 20
+#define ETDM_IN5_ULTRA_TH_MASK 0xf
+#define ETDM_IN5_ULTRA_TH_MASK_SFT (0xf << 20)
+#define ETDM_IN5_NORMAL_MODE_SFT 17
+#define ETDM_IN5_NORMAL_MODE_MASK 0x1
+#define ETDM_IN5_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define ETDM_IN5_ODD_USE_EVEN_SFT 16
+#define ETDM_IN5_ODD_USE_EVEN_MASK 0x1
+#define ETDM_IN5_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define ETDM_IN5_AXI_REQ_MAXLEN_SFT 12
+#define ETDM_IN5_AXI_REQ_MAXLEN_MASK 0x3
+#define ETDM_IN5_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define ETDM_IN5_AXI_REQ_MINLEN_SFT 8
+#define ETDM_IN5_AXI_REQ_MINLEN_MASK 0x3
+#define ETDM_IN5_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define ETDM_IN5_HALIGN_SFT 7
+#define ETDM_IN5_HALIGN_MASK 0x1
+#define ETDM_IN5_HALIGN_MASK_SFT (0x1 << 7)
+#define ETDM_IN5_SIGN_EXT_SFT 6
+#define ETDM_IN5_SIGN_EXT_MASK 0x1
+#define ETDM_IN5_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define ETDM_IN5_HD_MODE_SFT 4
+#define ETDM_IN5_HD_MODE_MASK 0x3
+#define ETDM_IN5_HD_MODE_MASK_SFT (0x3 << 4)
+#define ETDM_IN5_MAKE_EXTRA_UPDATE_SFT 3
+#define ETDM_IN5_MAKE_EXTRA_UPDATE_MASK 0x1
+#define ETDM_IN5_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define ETDM_IN5_AGENT_FREE_RUN_SFT 2
+#define ETDM_IN5_AGENT_FREE_RUN_MASK 0x1
+#define ETDM_IN5_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define ETDM_IN5_USE_INT_ODD_SFT 1
+#define ETDM_IN5_USE_INT_ODD_MASK 0x1
+#define ETDM_IN5_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define ETDM_IN5_INT_ODD_FLAG_SFT 0
+#define ETDM_IN5_INT_ODD_FLAG_MASK 0x1
+#define ETDM_IN5_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_ETDM_IN6_BASE_MSB */
+#define ETDM_IN6_BASE_ADDR_MSB_SFT 0
+#define ETDM_IN6_BASE_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN6_BASE_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN6_BASE */
+#define ETDM_IN6_BASE_ADDR_SFT 4
+#define ETDM_IN6_BASE_ADDR_MASK 0xfffffff
+#define ETDM_IN6_BASE_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN6_CUR_MSB */
+#define ETDM_IN6_CUR_PTR_MSB_SFT 0
+#define ETDM_IN6_CUR_PTR_MSB_MASK 0x1ff
+#define ETDM_IN6_CUR_PTR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN6_CUR */
+#define ETDM_IN6_CUR_PTR_SFT 0
+#define ETDM_IN6_CUR_PTR_MASK 0xffffffff
+#define ETDM_IN6_CUR_PTR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ETDM_IN6_END_MSB */
+#define ETDM_IN6_END_ADDR_MSB_SFT 0
+#define ETDM_IN6_END_ADDR_MSB_MASK 0x1ff
+#define ETDM_IN6_END_ADDR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_ETDM_IN6_END */
+#define ETDM_IN6_END_ADDR_SFT 4
+#define ETDM_IN6_END_ADDR_MASK 0xfffffff
+#define ETDM_IN6_END_ADDR_MASK_SFT (0xfffffff << 4)
+
+/* AFE_ETDM_IN6_CON0 */
+#define ETDM_IN6_CH_NUM_SFT 28
+#define ETDM_IN6_CH_NUM_MASK 0xf
+#define ETDM_IN6_CH_NUM_MASK_SFT (0xf << 28)
+#define ETDM_IN6_ON_SFT 27
+#define ETDM_IN6_ON_MASK 0x1
+#define ETDM_IN6_ON_MASK_SFT (0x1 << 27)
+#define ETDM_IN6_REG_CH_SHIFT_MODE_SFT 26
+#define ETDM_IN6_REG_CH_SHIFT_MODE_MASK 0x1
+#define ETDM_IN6_REG_CH_SHIFT_MODE_MASK_SFT (0x1 << 26)
+#define ETDM_IN6_RG_FORCE_NO_MASK_EXTRA_SFT 25
+#define ETDM_IN6_RG_FORCE_NO_MASK_EXTRA_MASK 0x1
+#define ETDM_IN6_RG_FORCE_NO_MASK_EXTRA_MASK_SFT (0x1 << 25)
+#define ETDM_IN6_SW_CLEAR_BUF_FULL_SFT 24
+#define ETDM_IN6_SW_CLEAR_BUF_FULL_MASK 0x1
+#define ETDM_IN6_SW_CLEAR_BUF_FULL_MASK_SFT (0x1 << 24)
+#define ETDM_IN6_ULTRA_TH_SFT 20
+#define ETDM_IN6_ULTRA_TH_MASK 0xf
+#define ETDM_IN6_ULTRA_TH_MASK_SFT (0xf << 20)
+#define ETDM_IN6_NORMAL_MODE_SFT 17
+#define ETDM_IN6_NORMAL_MODE_MASK 0x1
+#define ETDM_IN6_NORMAL_MODE_MASK_SFT (0x1 << 17)
+#define ETDM_IN6_ODD_USE_EVEN_SFT 16
+#define ETDM_IN6_ODD_USE_EVEN_MASK 0x1
+#define ETDM_IN6_ODD_USE_EVEN_MASK_SFT (0x1 << 16)
+#define ETDM_IN6_AXI_REQ_MAXLEN_SFT 12
+#define ETDM_IN6_AXI_REQ_MAXLEN_MASK 0x3
+#define ETDM_IN6_AXI_REQ_MAXLEN_MASK_SFT (0x3 << 12)
+#define ETDM_IN6_AXI_REQ_MINLEN_SFT 8
+#define ETDM_IN6_AXI_REQ_MINLEN_MASK 0x3
+#define ETDM_IN6_AXI_REQ_MINLEN_MASK_SFT (0x3 << 8)
+#define ETDM_IN6_HALIGN_SFT 7
+#define ETDM_IN6_HALIGN_MASK 0x1
+#define ETDM_IN6_HALIGN_MASK_SFT (0x1 << 7)
+#define ETDM_IN6_SIGN_EXT_SFT 6
+#define ETDM_IN6_SIGN_EXT_MASK 0x1
+#define ETDM_IN6_SIGN_EXT_MASK_SFT (0x1 << 6)
+#define ETDM_IN6_HD_MODE_SFT 4
+#define ETDM_IN6_HD_MODE_MASK 0x3
+#define ETDM_IN6_HD_MODE_MASK_SFT (0x3 << 4)
+#define ETDM_IN6_MAKE_EXTRA_UPDATE_SFT 3
+#define ETDM_IN6_MAKE_EXTRA_UPDATE_MASK 0x1
+#define ETDM_IN6_MAKE_EXTRA_UPDATE_MASK_SFT (0x1 << 3)
+#define ETDM_IN6_AGENT_FREE_RUN_SFT 2
+#define ETDM_IN6_AGENT_FREE_RUN_MASK 0x1
+#define ETDM_IN6_AGENT_FREE_RUN_MASK_SFT (0x1 << 2)
+#define ETDM_IN6_USE_INT_ODD_SFT 1
+#define ETDM_IN6_USE_INT_ODD_MASK 0x1
+#define ETDM_IN6_USE_INT_ODD_MASK_SFT (0x1 << 1)
+#define ETDM_IN6_INT_ODD_FLAG_SFT 0
+#define ETDM_IN6_INT_ODD_FLAG_MASK 0x1
+#define ETDM_IN6_INT_ODD_FLAG_MASK_SFT (0x1 << 0)
+
+/* AFE_HDMI_OUT_BASE_MSB */
+#define AFE_HDMI_OUT_BASE_MSB_SFT 0
+#define AFE_HDMI_OUT_BASE_MSB_MASK 0x1ff
+#define AFE_HDMI_OUT_BASE_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_HDMI_OUT_BASE */
+#define AFE_HDMI_OUT_BASE_SFT 4
+#define AFE_HDMI_OUT_BASE_MASK 0xfffffff
+#define AFE_HDMI_OUT_BASE_MASK_SFT (0xfffffff << 4)
+
+/* AFE_HDMI_OUT_CUR_MSB */
+#define AFE_HDMI_OUT_CUR_MSB_SFT 0
+#define AFE_HDMI_OUT_CUR_MSB_MASK 0x1ff
+#define AFE_HDMI_OUT_CUR_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_HDMI_OUT_CUR */
+#define AFE_HDMI_OUT_CUR_SFT 0
+#define AFE_HDMI_OUT_CUR_MASK 0xffffffff
+#define AFE_HDMI_OUT_CUR_MASK_SFT (0xffffffff << 0)
+
+/* AFE_HDMI_OUT_END_MSB */
+#define AFE_HDMI_OUT_END_MSB_SFT 0
+#define AFE_HDMI_OUT_END_MSB_MASK 0x1ff
+#define AFE_HDMI_OUT_END_MSB_MASK_SFT (0x1ff << 0)
+
+/* AFE_HDMI_OUT_END */
+#define AFE_HDMI_OUT_END_SFT 4
+#define AFE_HDMI_OUT_END_MASK 0xfffffff
+#define AFE_HDMI_OUT_END_MASK_SFT (0xfffffff << 4)
+#define AFE_HDMI_OUT_END_LSB_SFT 0
+#define AFE_HDMI_OUT_END_LSB_MASK 0xf
+#define AFE_HDMI_OUT_END_LSB_MASK_SFT (0xf << 0)
+
+/* AFE_HDMI_OUT_CON0 */
+#define HDMI_OUT_ON_SFT 28
+#define HDMI_OUT_ON_MASK 0x1
+#define HDMI_OUT_ON_MASK_SFT (0x1 << 28)
+#define HDMI_CH_NUM_SFT 24
+#define HDMI_CH_NUM_MASK 0xf
+#define HDMI_CH_NUM_MASK_SFT (0xf << 24)
+#define HDMI_OUT_ONE_HEART_SEL_SFT 22
+#define HDMI_OUT_ONE_HEART_SEL_MASK 0x3
+#define HDMI_OUT_ONE_HEART_SEL_MASK_SFT (0x3 << 22)
+#define HDMI_OUT_MINLEN_SFT 20
+#define HDMI_OUT_MINLEN_MASK 0x3
+#define HDMI_OUT_MINLEN_MASK_SFT (0x3 << 20)
+#define HDMI_OUT_MAXLEN_SFT 16
+#define HDMI_OUT_MAXLEN_MASK 0x3
+#define HDMI_OUT_MAXLEN_MASK_SFT (0x3 << 16)
+#define HDMI_OUT_SW_CLEAR_BUF_EMPTY_SFT 15
+#define HDMI_OUT_SW_CLEAR_BUF_EMPTY_MASK 0x1
+#define HDMI_OUT_SW_CLEAR_BUF_EMPTY_MASK_SFT (0x1 << 15)
+#define HDMI_OUT_PBUF_SIZE_SFT 12
+#define HDMI_OUT_PBUF_SIZE_MASK 0x3
+#define HDMI_OUT_PBUF_SIZE_MASK_SFT (0x3 << 12)
+#define HDMI_OUT_SW_CLEAR_HDMI_BUF_EMPTY_SFT 7
+#define HDMI_OUT_SW_CLEAR_HDMI_BUF_EMPTY_MASK 0x1
+#define HDMI_OUT_SW_CLEAR_HDMI_BUF_EMPTY_MASK_SFT (0x1 << 7)
+#define HDMI_OUT_NORMAL_MODE_SFT 5
+#define HDMI_OUT_NORMAL_MODE_MASK 0x1
+#define HDMI_OUT_NORMAL_MODE_MASK_SFT (0x1 << 5)
+#define HDMI_OUT_HALIGN_SFT 4
+#define HDMI_OUT_HALIGN_MASK 0x1
+#define HDMI_OUT_HALIGN_MASK_SFT (0x1 << 4)
+#define HDMI_OUT_HD_MODE_SFT 0
+#define HDMI_OUT_HD_MODE_MASK 0x3
+#define HDMI_OUT_HD_MODE_MASK_SFT (0x3 << 0)
+
+/* AFE_VUL24_RCH_MON */
+#define VUL24_RCH_DATA_SFT 0
+#define VUL24_RCH_DATA_MASK 0xffffffff
+#define VUL24_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL24_LCH_MON */
+#define VUL24_LCH_DATA_SFT 0
+#define VUL24_LCH_DATA_MASK 0xffffffff
+#define VUL24_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL25_RCH_MON */
+#define VUL25_RCH_DATA_SFT 0
+#define VUL25_RCH_DATA_MASK 0xffffffff
+#define VUL25_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL25_LCH_MON */
+#define VUL25_LCH_DATA_SFT 0
+#define VUL25_LCH_DATA_MASK 0xffffffff
+#define VUL25_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL26_RCH_MON */
+#define VUL26_RCH_DATA_SFT 0
+#define VUL26_RCH_DATA_MASK 0xffffffff
+#define VUL26_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL26_LCH_MON */
+#define VUL26_LCH_DATA_SFT 0
+#define VUL26_LCH_DATA_MASK 0xffffffff
+#define VUL26_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL_CM0_RCH_MON */
+#define VUL_CM0_RCH_DATA_SFT 0
+#define VUL_CM0_RCH_DATA_MASK 0xffffffff
+#define VUL_CM0_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL_CM0_LCH_MON */
+#define VUL_CM0_LCH_DATA_SFT 0
+#define VUL_CM0_LCH_DATA_MASK 0xffffffff
+#define VUL_CM0_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL_CM1_RCH_MON */
+#define VUL_CM1_RCH_DATA_SFT 0
+#define VUL_CM1_RCH_DATA_MASK 0xffffffff
+#define VUL_CM1_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL_CM1_LCH_MON */
+#define VUL_CM1_LCH_DATA_SFT 0
+#define VUL_CM1_LCH_DATA_MASK 0xffffffff
+#define VUL_CM1_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL_CM2_RCH_MON */
+#define VUL_CM2_RCH_DATA_SFT 0
+#define VUL_CM2_RCH_DATA_MASK 0xffffffff
+#define VUL_CM2_RCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_VUL_CM2_LCH_MON */
+#define VUL_CM2_LCH_DATA_SFT 0
+#define VUL_CM2_LCH_DATA_MASK 0xffffffff
+#define VUL_CM2_LCH_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_4CH_CH0_MON */
+#define DL_4CH_CH0_DATA_SFT 0
+#define DL_4CH_CH0_DATA_MASK 0xffffffff
+#define DL_4CH_CH0_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_4CH_CH1_MON */
+#define DL_4CH_CH1_DATA_SFT 0
+#define DL_4CH_CH1_DATA_MASK 0xffffffff
+#define DL_4CH_CH1_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_4CH_CH2_MON */
+#define DL_4CH_CH2_DATA_SFT 0
+#define DL_4CH_CH2_DATA_MASK 0xffffffff
+#define DL_4CH_CH2_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_4CH_CH3_MON */
+#define DL_4CH_CH3_DATA_SFT 0
+#define DL_4CH_CH3_DATA_MASK 0xffffffff
+#define DL_4CH_CH3_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH0_MON */
+#define DL_24CH_CH0_DATA_SFT 0
+#define DL_24CH_CH0_DATA_MASK 0xffffffff
+#define DL_24CH_CH0_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH1_MON */
+#define DL_24CH_CH1_DATA_SFT 0
+#define DL_24CH_CH1_DATA_MASK 0xffffffff
+#define DL_24CH_CH1_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH2_MON */
+#define DL_24CH_CH2_DATA_SFT 0
+#define DL_24CH_CH2_DATA_MASK 0xffffffff
+#define DL_24CH_CH2_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH3_MON */
+#define DL_24CH_CH3_DATA_SFT 0
+#define DL_24CH_CH3_DATA_MASK 0xffffffff
+#define DL_24CH_CH3_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH4_MON */
+#define DL_24CH_CH4_DATA_SFT 0
+#define DL_24CH_CH4_DATA_MASK 0xffffffff
+#define DL_24CH_CH4_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH5_MON */
+#define DL_24CH_CH5_DATA_SFT 0
+#define DL_24CH_CH5_DATA_MASK 0xffffffff
+#define DL_24CH_CH5_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH6_MON */
+#define DL_24CH_CH6_DATA_SFT 0
+#define DL_24CH_CH6_DATA_MASK 0xffffffff
+#define DL_24CH_CH6_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH7_MON */
+#define DL_24CH_CH7_DATA_SFT 0
+#define DL_24CH_CH7_DATA_MASK 0xffffffff
+#define DL_24CH_CH7_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH8_MON */
+#define DL_24CH_CH8_DATA_SFT 0
+#define DL_24CH_CH8_DATA_MASK 0xffffffff
+#define DL_24CH_CH8_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH9_MON */
+#define DL_24CH_CH9_DATA_SFT 0
+#define DL_24CH_CH9_DATA_MASK 0xffffffff
+#define DL_24CH_CH9_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH10_MON */
+#define DL_24CH_CH10_DATA_SFT 0
+#define DL_24CH_CH10_DATA_MASK 0xffffffff
+#define DL_24CH_CH10_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH11_MON */
+#define DL_24CH_CH11_DATA_SFT 0
+#define DL_24CH_CH11_DATA_MASK 0xffffffff
+#define DL_24CH_CH11_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH12_MON */
+#define DL_24CH_CH12_DATA_SFT 0
+#define DL_24CH_CH12_DATA_MASK 0xffffffff
+#define DL_24CH_CH12_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH13_MON */
+#define DL_24CH_CH13_DATA_SFT 0
+#define DL_24CH_CH13_DATA_MASK 0xffffffff
+#define DL_24CH_CH13_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH14_MON */
+#define DL_24CH_CH14_DATA_SFT 0
+#define DL_24CH_CH14_DATA_MASK 0xffffffff
+#define DL_24CH_CH14_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DL_24CH_CH15_MON */
+#define DL_24CH_CH15_DATA_SFT 0
+#define DL_24CH_CH15_DATA_MASK 0xffffffff
+#define DL_24CH_CH15_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SRAM_BOUND */
+#define SECURE_BIT_SFT 19
+#define SECURE_BIT_MASK 0x1
+#define SECURE_BIT_MASK_SFT (0x1 << 19)
+#define SECURE_SRAM_BOUND_SFT 0
+#define SECURE_SRAM_BOUND_MASK 0x7ffff
+#define SECURE_SRAM_BOUND_MASK_SFT (0x7ffff << 0)
+
+/* AFE_SECURE_CON0 */
+#define READ_EN15_NS_SFT 31
+#define READ_EN15_NS_MASK 0x1
+#define READ_EN15_NS_MASK_SFT (0x1 << 31)
+#define WRITE_EN15_NS_SFT 30
+#define WRITE_EN15_NS_MASK 0x1
+#define WRITE_EN15_NS_MASK_SFT (0x1 << 30)
+#define READ_EN14_NS_SFT 29
+#define READ_EN14_NS_MASK 0x1
+#define READ_EN14_NS_MASK_SFT (0x1 << 29)
+#define WRITE_EN14_NS_SFT 28
+#define WRITE_EN14_NS_MASK 0x1
+#define WRITE_EN14_NS_MASK_SFT (0x1 << 28)
+#define READ_EN13_NS_SFT 27
+#define READ_EN13_NS_MASK 0x1
+#define READ_EN13_NS_MASK_SFT (0x1 << 27)
+#define WRITE_EN13_NS_SFT 26
+#define WRITE_EN13_NS_MASK 0x1
+#define WRITE_EN13_NS_MASK_SFT (0x1 << 26)
+#define READ_EN12_NS_SFT 25
+#define READ_EN12_NS_MASK 0x1
+#define READ_EN12_NS_MASK_SFT (0x1 << 25)
+#define WRITE_EN12_NS_SFT 24
+#define WRITE_EN12_NS_MASK 0x1
+#define WRITE_EN12_NS_MASK_SFT (0x1 << 24)
+#define READ_EN11_NS_SFT 23
+#define READ_EN11_NS_MASK 0x1
+#define READ_EN11_NS_MASK_SFT (0x1 << 23)
+#define WRITE_EN11_NS_SFT 22
+#define WRITE_EN11_NS_MASK 0x1
+#define WRITE_EN11_NS_MASK_SFT (0x1 << 22)
+#define READ_EN10_NS_SFT 21
+#define READ_EN10_NS_MASK 0x1
+#define READ_EN10_NS_MASK_SFT (0x1 << 21)
+#define WRITE_EN10_NS_SFT 20
+#define WRITE_EN10_NS_MASK 0x1
+#define WRITE_EN10_NS_MASK_SFT (0x1 << 20)
+#define READ_EN9_NS_SFT 19
+#define READ_EN9_NS_MASK 0x1
+#define READ_EN9_NS_MASK_SFT (0x1 << 19)
+#define WRITE_EN9_NS_SFT 18
+#define WRITE_EN9_NS_MASK 0x1
+#define WRITE_EN9_NS_MASK_SFT (0x1 << 18)
+#define READ_EN8_NS_SFT 17
+#define READ_EN8_NS_MASK 0x1
+#define READ_EN8_NS_MASK_SFT (0x1 << 17)
+#define WRITE_EN8_NS_SFT 16
+#define WRITE_EN8_NS_MASK 0x1
+#define WRITE_EN8_NS_MASK_SFT (0x1 << 16)
+#define READ_EN7_NS_SFT 15
+#define READ_EN7_NS_MASK 0x1
+#define READ_EN7_NS_MASK_SFT (0x1 << 15)
+#define WRITE_EN7_NS_SFT 14
+#define WRITE_EN7_NS_MASK 0x1
+#define WRITE_EN7_NS_MASK_SFT (0x1 << 14)
+#define READ_EN6_NS_SFT 13
+#define READ_EN6_NS_MASK 0x1
+#define READ_EN6_NS_MASK_SFT (0x1 << 13)
+#define WRITE_EN6_NS_SFT 12
+#define WRITE_EN6_NS_MASK 0x1
+#define WRITE_EN6_NS_MASK_SFT (0x1 << 12)
+#define READ_EN5_NS_SFT 11
+#define READ_EN5_NS_MASK 0x1
+#define READ_EN5_NS_MASK_SFT (0x1 << 11)
+#define WRITE_EN5_NS_SFT 10
+#define WRITE_EN5_NS_MASK 0x1
+#define WRITE_EN5_NS_MASK_SFT (0x1 << 10)
+#define READ_EN4_NS_SFT 9
+#define READ_EN4_NS_MASK 0x1
+#define READ_EN4_NS_MASK_SFT (0x1 << 9)
+#define WRITE_EN4_NS_SFT 8
+#define WRITE_EN4_NS_MASK 0x1
+#define WRITE_EN4_NS_MASK_SFT (0x1 << 8)
+#define READ_EN3_NS_SFT 7
+#define READ_EN3_NS_MASK 0x1
+#define READ_EN3_NS_MASK_SFT (0x1 << 7)
+#define WRITE_EN3_NS_SFT 6
+#define WRITE_EN3_NS_MASK 0x1
+#define WRITE_EN3_NS_MASK_SFT (0x1 << 6)
+#define READ_EN2_NS_SFT 5
+#define READ_EN2_NS_MASK 0x1
+#define READ_EN2_NS_MASK_SFT (0x1 << 5)
+#define WRITE_EN2_NS_SFT 4
+#define WRITE_EN2_NS_MASK 0x1
+#define WRITE_EN2_NS_MASK_SFT (0x1 << 4)
+#define READ_EN1_NS_SFT 3
+#define READ_EN1_NS_MASK 0x1
+#define READ_EN1_NS_MASK_SFT (0x1 << 3)
+#define WRITE_EN1_NS_SFT 2
+#define WRITE_EN1_NS_MASK 0x1
+#define WRITE_EN1_NS_MASK_SFT (0x1 << 2)
+#define READ_EN0_NS_SFT 1
+#define READ_EN0_NS_MASK 0x1
+#define READ_EN0_NS_MASK_SFT (0x1 << 1)
+#define WRITE_EN0_NS_SFT 0
+#define WRITE_EN0_NS_MASK 0x1
+#define WRITE_EN0_NS_MASK_SFT (0x1 << 0)
+
+/* AFE_SECURE_CON1 */
+#define READ_EN15_S_SFT 31
+#define READ_EN15_S_MASK 0x1
+#define READ_EN15_S_MASK_SFT (0x1 << 31)
+#define WRITE_EN15_S_SFT 30
+#define WRITE_EN15_S_MASK 0x1
+#define WRITE_EN15_S_MASK_SFT (0x1 << 30)
+#define READ_EN14_S_SFT 29
+#define READ_EN14_S_MASK 0x1
+#define READ_EN14_S_MASK_SFT (0x1 << 29)
+#define WRITE_EN14_S_SFT 28
+#define WRITE_EN14_S_MASK 0x1
+#define WRITE_EN14_S_MASK_SFT (0x1 << 28)
+#define READ_EN13_S_SFT 27
+#define READ_EN13_S_MASK 0x1
+#define READ_EN13_S_MASK_SFT (0x1 << 27)
+#define WRITE_EN13_S_SFT 26
+#define WRITE_EN13_S_MASK 0x1
+#define WRITE_EN13_S_MASK_SFT (0x1 << 26)
+#define READ_EN12_S_SFT 25
+#define READ_EN12_S_MASK 0x1
+#define READ_EN12_S_MASK_SFT (0x1 << 25)
+#define WRITE_EN12_S_SFT 24
+#define WRITE_EN12_S_MASK 0x1
+#define WRITE_EN12_S_MASK_SFT (0x1 << 24)
+#define READ_EN11_S_SFT 23
+#define READ_EN11_S_MASK 0x1
+#define READ_EN11_S_MASK_SFT (0x1 << 23)
+#define WRITE_EN11_S_SFT 22
+#define WRITE_EN11_S_MASK 0x1
+#define WRITE_EN11_S_MASK_SFT (0x1 << 22)
+#define READ_EN10_S_SFT 21
+#define READ_EN10_S_MASK 0x1
+#define READ_EN10_S_MASK_SFT (0x1 << 21)
+#define WRITE_EN10_S_SFT 20
+#define WRITE_EN10_S_MASK 0x1
+#define WRITE_EN10_S_MASK_SFT (0x1 << 20)
+#define READ_EN9_S_SFT 19
+#define READ_EN9_S_MASK 0x1
+#define READ_EN9_S_MASK_SFT (0x1 << 19)
+#define WRITE_EN9_S_SFT 18
+#define WRITE_EN9_S_MASK 0x1
+#define WRITE_EN9_S_MASK_SFT (0x1 << 18)
+#define READ_EN8_S_SFT 17
+#define READ_EN8_S_MASK 0x1
+#define READ_EN8_S_MASK_SFT (0x1 << 17)
+#define WRITE_EN8_S_SFT 16
+#define WRITE_EN8_S_MASK 0x1
+#define WRITE_EN8_S_MASK_SFT (0x1 << 16)
+#define READ_EN7_S_SFT 15
+#define READ_EN7_S_MASK 0x1
+#define READ_EN7_S_MASK_SFT (0x1 << 15)
+#define WRITE_EN7_S_SFT 14
+#define WRITE_EN7_S_MASK 0x1
+#define WRITE_EN7_S_MASK_SFT (0x1 << 14)
+#define READ_EN6_S_SFT 13
+#define READ_EN6_S_MASK 0x1
+#define READ_EN6_S_MASK_SFT (0x1 << 13)
+#define WRITE_EN6_S_SFT 12
+#define WRITE_EN6_S_MASK 0x1
+#define WRITE_EN6_S_MASK_SFT (0x1 << 12)
+#define READ_EN5_S_SFT 11
+#define READ_EN5_S_MASK 0x1
+#define READ_EN5_S_MASK_SFT (0x1 << 11)
+#define WRITE_EN5_S_SFT 10
+#define WRITE_EN5_S_MASK 0x1
+#define WRITE_EN5_S_MASK_SFT (0x1 << 10)
+#define READ_EN4_S_SFT 9
+#define READ_EN4_S_MASK 0x1
+#define READ_EN4_S_MASK_SFT (0x1 << 9)
+#define WRITE_EN4_S_SFT 8
+#define WRITE_EN4_S_MASK 0x1
+#define WRITE_EN4_S_MASK_SFT (0x1 << 8)
+#define READ_EN3_S_SFT 7
+#define READ_EN3_S_MASK 0x1
+#define READ_EN3_S_MASK_SFT (0x1 << 7)
+#define WRITE_EN3_S_SFT 6
+#define WRITE_EN3_S_MASK 0x1
+#define WRITE_EN3_S_MASK_SFT (0x1 << 6)
+#define READ_EN2_S_SFT 5
+#define READ_EN2_S_MASK 0x1
+#define READ_EN2_S_MASK_SFT (0x1 << 5)
+#define WRITE_EN2_S_SFT 4
+#define WRITE_EN2_S_MASK 0x1
+#define WRITE_EN2_S_MASK_SFT (0x1 << 4)
+#define READ_EN1_S_SFT 3
+#define READ_EN1_S_MASK 0x1
+#define READ_EN1_S_MASK_SFT (0x1 << 3)
+#define WRITE_EN1_S_SFT 2
+#define WRITE_EN1_S_MASK 0x1
+#define WRITE_EN1_S_MASK_SFT (0x1 << 2)
+#define READ_EN0_S_SFT 1
+#define READ_EN0_S_MASK 0x1
+#define READ_EN0_S_MASK_SFT (0x1 << 1)
+#define WRITE_EN0_S_SFT 0
+#define WRITE_EN0_S_MASK 0x1
+#define WRITE_EN0_S_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_SECURE_CON0 */
+#define AFE_HDMI_SE_SECURE_BIT_SFT 11
+#define AFE_HDMI_SE_SECURE_BIT_MASK 0x1
+#define AFE_HDMI_SE_SECURE_BIT_MASK_SFT (0x1 << 11)
+#define AFE_SPDIF2_OUT_SE_SECURE_BIT_SFT 10
+#define AFE_SPDIF2_OUT_SE_SECURE_BIT_MASK 0x1
+#define AFE_SPDIF2_OUT_SE_SECURE_BIT_MASK_SFT (0x1 << 10)
+#define AFE_SPDIF_OUT_SE_SECURE_BIT_SFT 9
+#define AFE_SPDIF_OUT_SE_SECURE_BIT_MASK 0x1
+#define AFE_SPDIF_OUT_SE_SECURE_BIT_MASK_SFT (0x1 << 9)
+#define AFE_DL8_SE_SECURE_BIT_SFT 8
+#define AFE_DL8_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL8_SE_SECURE_BIT_MASK_SFT (0x1 << 8)
+#define AFE_DL7_SE_SECURE_BIT_SFT 7
+#define AFE_DL7_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL7_SE_SECURE_BIT_MASK_SFT (0x1 << 7)
+#define AFE_DL6_SE_SECURE_BIT_SFT 6
+#define AFE_DL6_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL6_SE_SECURE_BIT_MASK_SFT (0x1 << 6)
+#define AFE_DL5_SE_SECURE_BIT_SFT 5
+#define AFE_DL5_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL5_SE_SECURE_BIT_MASK_SFT (0x1 << 5)
+#define AFE_DL4_SE_SECURE_BIT_SFT 4
+#define AFE_DL4_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL4_SE_SECURE_BIT_MASK_SFT (0x1 << 4)
+#define AFE_DL3_SE_SECURE_BIT_SFT 3
+#define AFE_DL3_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL3_SE_SECURE_BIT_MASK_SFT (0x1 << 3)
+#define AFE_DL2_SE_SECURE_BIT_SFT 2
+#define AFE_DL2_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL2_SE_SECURE_BIT_MASK_SFT (0x1 << 2)
+#define AFE_DL1_SE_SECURE_BIT_SFT 1
+#define AFE_DL1_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL1_SE_SECURE_BIT_MASK_SFT (0x1 << 1)
+#define AFE_DL0_SE_SECURE_BIT_SFT 0
+#define AFE_DL0_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL0_SE_SECURE_BIT_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_SECURE_CON1 */
+#define AFE_DL46_SE_SECURE_BIT_SFT 26
+#define AFE_DL46_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL46_SE_SECURE_BIT_MASK_SFT (0x1 << 26)
+#define AFE_DL45_SE_SECURE_BIT_SFT 25
+#define AFE_DL45_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL45_SE_SECURE_BIT_MASK_SFT (0x1 << 25)
+#define AFE_DL44_SE_SECURE_BIT_SFT 24
+#define AFE_DL44_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL44_SE_SECURE_BIT_MASK_SFT (0x1 << 24)
+#define AFE_DL43_SE_SECURE_BIT_SFT 23
+#define AFE_DL43_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL43_SE_SECURE_BIT_MASK_SFT (0x1 << 23)
+#define AFE_DL42_SE_SECURE_BIT_SFT 22
+#define AFE_DL42_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL42_SE_SECURE_BIT_MASK_SFT (0x1 << 22)
+#define AFE_DL41_SE_SECURE_BIT_SFT 21
+#define AFE_DL41_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL41_SE_SECURE_BIT_MASK_SFT (0x1 << 21)
+#define AFE_DL40_SE_SECURE_BIT_SFT 20
+#define AFE_DL40_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL40_SE_SECURE_BIT_MASK_SFT (0x1 << 20)
+#define AFE_DL39_SE_SECURE_BIT_SFT 19
+#define AFE_DL39_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL39_SE_SECURE_BIT_MASK_SFT (0x1 << 19)
+#define AFE_DL38_SE_SECURE_BIT_SFT 18
+#define AFE_DL38_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL38_SE_SECURE_BIT_MASK_SFT (0x1 << 18)
+#define AFE_DL37_SE_SECURE_BIT_SFT 17
+#define AFE_DL37_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL37_SE_SECURE_BIT_MASK_SFT (0x1 << 17)
+#define AFE_DL36_SE_SECURE_BIT_SFT 16
+#define AFE_DL36_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL36_SE_SECURE_BIT_MASK_SFT (0x1 << 16)
+#define AFE_DL35_SE_SECURE_BIT_SFT 15
+#define AFE_DL35_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL35_SE_SECURE_BIT_MASK_SFT (0x1 << 15)
+#define AFE_DL34_SE_SECURE_BIT_SFT 14
+#define AFE_DL34_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL34_SE_SECURE_BIT_MASK_SFT (0x1 << 14)
+#define AFE_DL33_SE_SECURE_BIT_SFT 13
+#define AFE_DL33_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL33_SE_SECURE_BIT_MASK_SFT (0x1 << 13)
+#define AFE_DL32_SE_SECURE_BIT_SFT 12
+#define AFE_DL32_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL32_SE_SECURE_BIT_MASK_SFT (0x1 << 12)
+#define AFE_DL31_SE_SECURE_BIT_SFT 11
+#define AFE_DL31_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL31_SE_SECURE_BIT_MASK_SFT (0x1 << 11)
+#define AFE_DL30_SE_SECURE_BIT_SFT 10
+#define AFE_DL30_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL30_SE_SECURE_BIT_MASK_SFT (0x1 << 10)
+#define AFE_DL29_SE_SECURE_BIT_SFT 9
+#define AFE_DL29_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL29_SE_SECURE_BIT_MASK_SFT (0x1 << 9)
+#define AFE_DL28_SE_SECURE_BIT_SFT 8
+#define AFE_DL28_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL28_SE_SECURE_BIT_MASK_SFT (0x1 << 8)
+#define AFE_DL27_SE_SECURE_BIT_SFT 7
+#define AFE_DL27_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL27_SE_SECURE_BIT_MASK_SFT (0x1 << 7)
+#define AFE_DL26_SE_SECURE_BIT_SFT 6
+#define AFE_DL26_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL26_SE_SECURE_BIT_MASK_SFT (0x1 << 6)
+#define AFE_DL25_SE_SECURE_BIT_SFT 5
+#define AFE_DL25_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL25_SE_SECURE_BIT_MASK_SFT (0x1 << 5)
+#define AFE_DL24_SE_SECURE_BIT_SFT 4
+#define AFE_DL24_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL24_SE_SECURE_BIT_MASK_SFT (0x1 << 4)
+#define AFE_DL23_SE_SECURE_BIT_SFT 3
+#define AFE_DL23_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL23_SE_SECURE_BIT_MASK_SFT (0x1 << 3)
+#define AFE_DL_48CH_SE_SECURE_BIT_SFT 2
+#define AFE_DL_48CH_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL_48CH_SE_SECURE_BIT_MASK_SFT (0x1 << 2)
+#define AFE_DL_24CH_SE_SECURE_BIT_SFT 1
+#define AFE_DL_24CH_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL_24CH_SE_SECURE_BIT_MASK_SFT (0x1 << 1)
+#define AFE_DL_4CH_SE_SECURE_BIT_SFT 0
+#define AFE_DL_4CH_SE_SECURE_BIT_MASK 0x1
+#define AFE_DL_4CH_SE_SECURE_BIT_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_SECURE_CON2 */
+#define AFE_VUL38_SE_SECURE_BIT_SFT 28
+#define AFE_VUL38_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL38_SE_SECURE_BIT_MASK_SFT (0x1 << 28)
+#define AFE_VUL37_SE_SECURE_BIT_SFT 27
+#define AFE_VUL37_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL37_SE_SECURE_BIT_MASK_SFT (0x1 << 27)
+#define AFE_VUL36_SE_SECURE_BIT_SFT 26
+#define AFE_VUL36_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL36_SE_SECURE_BIT_MASK_SFT (0x1 << 26)
+#define AFE_VUL35_SE_SECURE_BIT_SFT 25
+#define AFE_VUL35_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL35_SE_SECURE_BIT_MASK_SFT (0x1 << 25)
+#define AFE_VUL34_SE_SECURE_BIT_SFT 24
+#define AFE_VUL34_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL34_SE_SECURE_BIT_MASK_SFT (0x1 << 24)
+#define AFE_VUL33_SE_SECURE_BIT_SFT 23
+#define AFE_VUL33_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL33_SE_SECURE_BIT_MASK_SFT (0x1 << 23)
+#define AFE_VUL32_SE_SECURE_BIT_SFT 22
+#define AFE_VUL32_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL32_SE_SECURE_BIT_MASK_SFT (0x1 << 22)
+#define AFE_VUL31_SE_SECURE_BIT_SFT 21
+#define AFE_VUL31_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL31_SE_SECURE_BIT_MASK_SFT (0x1 << 21)
+#define AFE_VUL30_SE_SECURE_BIT_SFT 20
+#define AFE_VUL30_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL30_SE_SECURE_BIT_MASK_SFT (0x1 << 20)
+#define AFE_VUL29_SE_SECURE_BIT_SFT 19
+#define AFE_VUL29_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL29_SE_SECURE_BIT_MASK_SFT (0x1 << 19)
+#define AFE_VUL28_SE_SECURE_BIT_SFT 18
+#define AFE_VUL28_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL28_SE_SECURE_BIT_MASK_SFT (0x1 << 18)
+#define AFE_VUL27_SE_SECURE_BIT_SFT 17
+#define AFE_VUL27_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL27_SE_SECURE_BIT_MASK_SFT (0x1 << 17)
+#define AFE_VUL26_SE_SECURE_BIT_SFT 16
+#define AFE_VUL26_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL26_SE_SECURE_BIT_MASK_SFT (0x1 << 16)
+#define AFE_VUL25_SE_SECURE_BIT_SFT 15
+#define AFE_VUL25_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL25_SE_SECURE_BIT_MASK_SFT (0x1 << 15)
+#define AFE_VUL24_SE_SECURE_BIT_SFT 14
+#define AFE_VUL24_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL24_SE_SECURE_BIT_MASK_SFT (0x1 << 14)
+#define AFE_VUL_CM2_SE_SECURE_BIT_SFT 13
+#define AFE_VUL_CM2_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL_CM2_SE_SECURE_BIT_MASK_SFT (0x1 << 13)
+#define AFE_VUL_CM1_SE_SECURE_BIT_SFT 12
+#define AFE_VUL_CM1_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL_CM1_SE_SECURE_BIT_MASK_SFT (0x1 << 12)
+#define AFE_VUL_CM0_SE_SECURE_BIT_SFT 11
+#define AFE_VUL_CM0_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL_CM0_SE_SECURE_BIT_MASK_SFT (0x1 << 11)
+#define AFE_VUL10_SE_SECURE_BIT_SFT 10
+#define AFE_VUL10_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL10_SE_SECURE_BIT_MASK_SFT (0x1 << 10)
+#define AFE_VUL9_SE_SECURE_BIT_SFT 9
+#define AFE_VUL9_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL9_SE_SECURE_BIT_MASK_SFT (0x1 << 9)
+#define AFE_VUL8_SE_SECURE_BIT_SFT 8
+#define AFE_VUL8_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL8_SE_SECURE_BIT_MASK_SFT (0x1 << 8)
+#define AFE_VUL7_SE_SECURE_BIT_SFT 7
+#define AFE_VUL7_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL7_SE_SECURE_BIT_MASK_SFT (0x1 << 7)
+#define AFE_VUL6_SE_SECURE_BIT_SFT 6
+#define AFE_VUL6_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL6_SE_SECURE_BIT_MASK_SFT (0x1 << 6)
+#define AFE_VUL5_SE_SECURE_BIT_SFT 5
+#define AFE_VUL5_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL5_SE_SECURE_BIT_MASK_SFT (0x1 << 5)
+#define AFE_VUL4_SE_SECURE_BIT_SFT 4
+#define AFE_VUL4_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL4_SE_SECURE_BIT_MASK_SFT (0x1 << 4)
+#define AFE_VUL3_SE_SECURE_BIT_SFT 3
+#define AFE_VUL3_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL3_SE_SECURE_BIT_MASK_SFT (0x1 << 3)
+#define AFE_VUL2_SE_SECURE_BIT_SFT 2
+#define AFE_VUL2_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL2_SE_SECURE_BIT_MASK_SFT (0x1 << 2)
+#define AFE_VUL1_SE_SECURE_BIT_SFT 1
+#define AFE_VUL1_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL1_SE_SECURE_BIT_MASK_SFT (0x1 << 1)
+#define AFE_VUL0_SE_SECURE_BIT_SFT 0
+#define AFE_VUL0_SE_SECURE_BIT_MASK 0x1
+#define AFE_VUL0_SE_SECURE_BIT_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_SECURE_CON3 */
+#define AFE_SPDIFIN_SE_SECURE_BIT_SFT 10
+#define AFE_SPDIFIN_SE_SECURE_BIT_MASK 0x1
+#define AFE_SPDIFIN_SE_SECURE_BIT_MASK_SFT (0x1 << 10)
+#define AFE_TDM_IN_SE_SECURE_BIT_SFT 9
+#define AFE_TDM_IN_SE_SECURE_BIT_MASK 0x1
+#define AFE_TDM_IN_SE_SECURE_BIT_MASK_SFT (0x1 << 9)
+#define AFE_MPHONE_EARC_SE_SECURE_BIT_SFT 8
+#define AFE_MPHONE_EARC_SE_SECURE_BIT_MASK 0x1
+#define AFE_MPHONE_EARC_SE_SECURE_BIT_MASK_SFT (0x1 << 8)
+#define AFE_MPHONE_SPDIF_SE_SECURE_BIT_SFT 7
+#define AFE_MPHONE_SPDIF_SE_SECURE_BIT_MASK 0x1
+#define AFE_MPHONE_SPDIF_SE_SECURE_BIT_MASK_SFT (0x1 << 7)
+#define AFE_ETDM_IN6_SE_SECURE_BIT_SFT 6
+#define AFE_ETDM_IN6_SE_SECURE_BIT_MASK 0x1
+#define AFE_ETDM_IN6_SE_SECURE_BIT_MASK_SFT (0x1 << 6)
+#define AFE_ETDM_IN5_SE_SECURE_BIT_SFT 5
+#define AFE_ETDM_IN5_SE_SECURE_BIT_MASK 0x1
+#define AFE_ETDM_IN5_SE_SECURE_BIT_MASK_SFT (0x1 << 5)
+#define AFE_ETDM_IN4_SE_SECURE_BIT_SFT 4
+#define AFE_ETDM_IN4_SE_SECURE_BIT_MASK 0x1
+#define AFE_ETDM_IN4_SE_SECURE_BIT_MASK_SFT (0x1 << 4)
+#define AFE_ETDM_IN3_SE_SECURE_BIT_SFT 3
+#define AFE_ETDM_IN3_SE_SECURE_BIT_MASK 0x1
+#define AFE_ETDM_IN3_SE_SECURE_BIT_MASK_SFT (0x1 << 3)
+#define AFE_ETDM_IN2_SE_SECURE_BIT_SFT 2
+#define AFE_ETDM_IN2_SE_SECURE_BIT_MASK 0x1
+#define AFE_ETDM_IN2_SE_SECURE_BIT_MASK_SFT (0x1 << 2)
+#define AFE_ETDM_IN1_SE_SECURE_BIT_SFT 1
+#define AFE_ETDM_IN1_SE_SECURE_BIT_MASK 0x1
+#define AFE_ETDM_IN1_SE_SECURE_BIT_MASK_SFT (0x1 << 1)
+#define AFE_ETDM_IN0_SE_SECURE_BIT_SFT 0
+#define AFE_ETDM_IN0_SE_SECURE_BIT_MASK 0x1
+#define AFE_ETDM_IN0_SE_SECURE_BIT_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_PROT_SIDEBAND0 */
+#define HDMI_HPROT_SFT 11
+#define HDMI_HPROT_MASK 0x1
+#define HDMI_HPROT_MASK_SFT (0x1 << 11)
+#define SPDIF2_OUT_HPROT_SFT 10
+#define SPDIF2_OUT_HPROT_MASK 0x1
+#define SPDIF2_OUT_HPROT_MASK_SFT (0x1 << 10)
+#define SPDIF_OUT_HPROT_SFT 9
+#define SPDIF_OUT_HPROT_MASK 0x1
+#define SPDIF_OUT_HPROT_MASK_SFT (0x1 << 9)
+#define DL8_HPROT_SFT 8
+#define DL8_HPROT_MASK 0x1
+#define DL8_HPROT_MASK_SFT (0x1 << 8)
+#define DL7_HPROT_SFT 7
+#define DL7_HPROT_MASK 0x1
+#define DL7_HPROT_MASK_SFT (0x1 << 7)
+#define DL6_HPROT_SFT 6
+#define DL6_HPROT_MASK 0x1
+#define DL6_HPROT_MASK_SFT (0x1 << 6)
+#define DL5_HPROT_SFT 5
+#define DL5_HPROT_MASK 0x1
+#define DL5_HPROT_MASK_SFT (0x1 << 5)
+#define DL4_HPROT_SFT 4
+#define DL4_HPROT_MASK 0x1
+#define DL4_HPROT_MASK_SFT (0x1 << 4)
+#define DL3_HPROT_SFT 3
+#define DL3_HPROT_MASK 0x1
+#define DL3_HPROT_MASK_SFT (0x1 << 3)
+#define DL2_HPROT_SFT 2
+#define DL2_HPROT_MASK 0x1
+#define DL2_HPROT_MASK_SFT (0x1 << 2)
+#define DL1_HPROT_SFT 1
+#define DL1_HPROT_MASK 0x1
+#define DL1_HPROT_MASK_SFT (0x1 << 1)
+#define DL0_HPROT_SFT 0
+#define DL0_HPROT_MASK 0x1
+#define DL0_HPROT_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_PROT_SIDEBAND1 */
+#define DL46_HPROT_SFT 26
+#define DL46_HPROT_MASK 0x1
+#define DL46_HPROT_MASK_SFT (0x1 << 26)
+#define DL45_HPROT_SFT 25
+#define DL45_HPROT_MASK 0x1
+#define DL45_HPROT_MASK_SFT (0x1 << 25)
+#define DL44_HPROT_SFT 24
+#define DL44_HPROT_MASK 0x1
+#define DL44_HPROT_MASK_SFT (0x1 << 24)
+#define DL43_HPROT_SFT 23
+#define DL43_HPROT_MASK 0x1
+#define DL43_HPROT_MASK_SFT (0x1 << 23)
+#define DL42_HPROT_SFT 22
+#define DL42_HPROT_MASK 0x1
+#define DL42_HPROT_MASK_SFT (0x1 << 22)
+#define DL41_HPROT_SFT 21
+#define DL41_HPROT_MASK 0x1
+#define DL41_HPROT_MASK_SFT (0x1 << 21)
+#define DL40_HPROT_SFT 20
+#define DL40_HPROT_MASK 0x1
+#define DL40_HPROT_MASK_SFT (0x1 << 20)
+#define DL39_HPROT_SFT 19
+#define DL39_HPROT_MASK 0x1
+#define DL39_HPROT_MASK_SFT (0x1 << 19)
+#define DL38_HPROT_SFT 18
+#define DL38_HPROT_MASK 0x1
+#define DL38_HPROT_MASK_SFT (0x1 << 18)
+#define DL37_HPROT_SFT 17
+#define DL37_HPROT_MASK 0x1
+#define DL37_HPROT_MASK_SFT (0x1 << 17)
+#define DL36_HPROT_SFT 16
+#define DL36_HPROT_MASK 0x1
+#define DL36_HPROT_MASK_SFT (0x1 << 16)
+#define DL35_HPROT_SFT 15
+#define DL35_HPROT_MASK 0x1
+#define DL35_HPROT_MASK_SFT (0x1 << 15)
+#define DL34_HPROT_SFT 14
+#define DL34_HPROT_MASK 0x1
+#define DL34_HPROT_MASK_SFT (0x1 << 14)
+#define DL33_HPROT_SFT 13
+#define DL33_HPROT_MASK 0x1
+#define DL33_HPROT_MASK_SFT (0x1 << 13)
+#define DL32_HPROT_SFT 12
+#define DL32_HPROT_MASK 0x1
+#define DL32_HPROT_MASK_SFT (0x1 << 12)
+#define DL31_HPROT_SFT 11
+#define DL31_HPROT_MASK 0x1
+#define DL31_HPROT_MASK_SFT (0x1 << 11)
+#define DL30_HPROT_SFT 10
+#define DL30_HPROT_MASK 0x1
+#define DL30_HPROT_MASK_SFT (0x1 << 10)
+#define DL29_HPROT_SFT 9
+#define DL29_HPROT_MASK 0x1
+#define DL29_HPROT_MASK_SFT (0x1 << 9)
+#define DL28_HPROT_SFT 8
+#define DL28_HPROT_MASK 0x1
+#define DL28_HPROT_MASK_SFT (0x1 << 8)
+#define DL27_HPROT_SFT 7
+#define DL27_HPROT_MASK 0x1
+#define DL27_HPROT_MASK_SFT (0x1 << 7)
+#define DL26_HPROT_SFT 6
+#define DL26_HPROT_MASK 0x1
+#define DL26_HPROT_MASK_SFT (0x1 << 6)
+#define DL25_HPROT_SFT 5
+#define DL25_HPROT_MASK 0x1
+#define DL25_HPROT_MASK_SFT (0x1 << 5)
+#define DL24_HPROT_SFT 4
+#define DL24_HPROT_MASK 0x1
+#define DL24_HPROT_MASK_SFT (0x1 << 4)
+#define DL23_HPROT_SFT 3
+#define DL23_HPROT_MASK 0x1
+#define DL23_HPROT_MASK_SFT (0x1 << 3)
+#define DL_48CH_PROT_SFT 2
+#define DL_48CH_PROT_MASK 0x1
+#define DL_48CH_PROT_MASK_SFT (0x1 << 2)
+#define DL_24CH_PROT_SFT 1
+#define DL_24CH_PROT_MASK 0x1
+#define DL_24CH_PROT_MASK_SFT (0x1 << 1)
+#define DL_4CH_PROT_SFT 0
+#define DL_4CH_PROT_MASK 0x1
+#define DL_4CH_PROT_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_PROT_SIDEBAND2 */
+#define VUL38_HPROT_SFT 28
+#define VUL38_HPROT_MASK 0x1
+#define VUL38_HPROT_MASK_SFT (0x1 << 28)
+#define VUL37_HPROT_SFT 27
+#define VUL37_HPROT_MASK 0x1
+#define VUL37_HPROT_MASK_SFT (0x1 << 27)
+#define VUL36_HPROT_SFT 26
+#define VUL36_HPROT_MASK 0x1
+#define VUL36_HPROT_MASK_SFT (0x1 << 26)
+#define VUL35_HPROT_SFT 25
+#define VUL35_HPROT_MASK 0x1
+#define VUL35_HPROT_MASK_SFT (0x1 << 25)
+#define VUL34_HPROT_SFT 24
+#define VUL34_HPROT_MASK 0x1
+#define VUL34_HPROT_MASK_SFT (0x1 << 24)
+#define VUL33_HPROT_SFT 23
+#define VUL33_HPROT_MASK 0x1
+#define VUL33_HPROT_MASK_SFT (0x1 << 23)
+#define VUL32_HPROT_SFT 22
+#define VUL32_HPROT_MASK 0x1
+#define VUL32_HPROT_MASK_SFT (0x1 << 22)
+#define VUL31_HPROT_SFT 21
+#define VUL31_HPROT_MASK 0x1
+#define VUL31_HPROT_MASK_SFT (0x1 << 21)
+#define VUL30_HPROT_SFT 20
+#define VUL30_HPROT_MASK 0x1
+#define VUL30_HPROT_MASK_SFT (0x1 << 20)
+#define VUL29_HPROT_SFT 19
+#define VUL29_HPROT_MASK 0x1
+#define VUL29_HPROT_MASK_SFT (0x1 << 19)
+#define VUL28_HPROT_SFT 18
+#define VUL28_HPROT_MASK 0x1
+#define VUL28_HPROT_MASK_SFT (0x1 << 18)
+#define VUL27_HPROT_SFT 17
+#define VUL27_HPROT_MASK 0x1
+#define VUL27_HPROT_MASK_SFT (0x1 << 17)
+#define VUL26_HPROT_SFT 16
+#define VUL26_HPROT_MASK 0x1
+#define VUL26_HPROT_MASK_SFT (0x1 << 16)
+#define VUL25_HPROT_SFT 15
+#define VUL25_HPROT_MASK 0x1
+#define VUL25_HPROT_MASK_SFT (0x1 << 15)
+#define VUL24_HPROT_SFT 14
+#define VUL24_HPROT_MASK 0x1
+#define VUL24_HPROT_MASK_SFT (0x1 << 14)
+#define VUL_CM2_HPROT_SFT 13
+#define VUL_CM2_HPROT_MASK 0x1
+#define VUL_CM2_HPROT_MASK_SFT (0x1 << 13)
+#define VUL_CM1_HPROT_SFT 12
+#define VUL_CM1_HPROT_MASK 0x1
+#define VUL_CM1_HPROT_MASK_SFT (0x1 << 12)
+#define VUL_CM0_HPROT_SFT 11
+#define VUL_CM0_HPROT_MASK 0x1
+#define VUL_CM0_HPROT_MASK_SFT (0x1 << 11)
+#define VUL10_HPROT_SFT 10
+#define VUL10_HPROT_MASK 0x1
+#define VUL10_HPROT_MASK_SFT (0x1 << 10)
+#define VUL9_HPROT_SFT 9
+#define VUL9_HPROT_MASK 0x1
+#define VUL9_HPROT_MASK_SFT (0x1 << 9)
+#define VUL8_HPROT_SFT 8
+#define VUL8_HPROT_MASK 0x1
+#define VUL8_HPROT_MASK_SFT (0x1 << 8)
+#define VUL7_HPROT_SFT 7
+#define VUL7_HPROT_MASK 0x1
+#define VUL7_HPROT_MASK_SFT (0x1 << 7)
+#define VUL6_HPROT_SFT 6
+#define VUL6_HPROT_MASK 0x1
+#define VUL6_HPROT_MASK_SFT (0x1 << 6)
+#define VUL5_HPROT_SFT 5
+#define VUL5_HPROT_MASK 0x1
+#define VUL5_HPROT_MASK_SFT (0x1 << 5)
+#define VUL4_HPROT_SFT 4
+#define VUL4_HPROT_MASK 0x1
+#define VUL4_HPROT_MASK_SFT (0x1 << 4)
+#define VUL3_HPROT_SFT 3
+#define VUL3_HPROT_MASK 0x1
+#define VUL3_HPROT_MASK_SFT (0x1 << 3)
+#define VUL2_HPROT_SFT 2
+#define VUL2_HPROT_MASK 0x1
+#define VUL2_HPROT_MASK_SFT (0x1 << 2)
+#define VUL1_HPROT_SFT 1
+#define VUL1_HPROT_MASK 0x1
+#define VUL1_HPROT_MASK_SFT (0x1 << 1)
+#define VUL0_HPROT_SFT 0
+#define VUL0_HPROT_MASK 0x1
+#define VUL0_HPROT_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_PROT_SIDEBAND3 */
+#define MPHONE_EARC_HPROT_SFT 10
+#define MPHONE_EARC_HPROT_MASK 0x1
+#define MPHONE_EARC_HPROT_MASK_SFT (0x1 << 10)
+#define MPHONE_SPDIF_HPROT_SFT 9
+#define MPHONE_SPDIF_HPROT_MASK 0x1
+#define MPHONE_SPDIF_HPROT_MASK_SFT (0x1 << 9)
+#define SPDIFIN_HPROT_SFT 8
+#define SPDIFIN_HPROT_MASK 0x1
+#define SPDIFIN_HPROT_MASK_SFT (0x1 << 8)
+#define TDMIN_HPROT_SFT 7
+#define TDMIN_HPROT_MASK 0x1
+#define TDMIN_HPROT_MASK_SFT (0x1 << 7)
+#define ETDM_IN6_HPROT_SFT 6
+#define ETDM_IN6_HPROT_MASK 0x1
+#define ETDM_IN6_HPROT_MASK_SFT (0x1 << 6)
+#define ETDM_IN5_HPROT_SFT 5
+#define ETDM_IN5_HPROT_MASK 0x1
+#define ETDM_IN5_HPROT_MASK_SFT (0x1 << 5)
+#define ETDM_IN4_HPROT_SFT 4
+#define ETDM_IN4_HPROT_MASK 0x1
+#define ETDM_IN4_HPROT_MASK_SFT (0x1 << 4)
+#define ETDM_IN3_HPROT_SFT 3
+#define ETDM_IN3_HPROT_MASK 0x1
+#define ETDM_IN3_HPROT_MASK_SFT (0x1 << 3)
+#define ETDM_IN2_HPROT_SFT 2
+#define ETDM_IN2_HPROT_MASK 0x1
+#define ETDM_IN2_HPROT_MASK_SFT (0x1 << 2)
+#define ETDM_IN1_HPROT_SFT 1
+#define ETDM_IN1_HPROT_MASK 0x1
+#define ETDM_IN1_HPROT_MASK_SFT (0x1 << 1)
+#define ETDM_IN0_HPROT_SFT 0
+#define ETDM_IN0_HPROT_MASK 0x1
+#define ETDM_IN0_HPROT_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND0 */
+#define DL7_HDOMAIN_SFT 28
+#define DL7_HDOMAIN_MASK 0xf
+#define DL7_HDOMAIN_MASK_SFT (0xf << 28)
+#define DL6_HDOMAIN_SFT 24
+#define DL6_HDOMAIN_MASK 0xf
+#define DL6_HDOMAIN_MASK_SFT (0xf << 24)
+#define DL5_HDOMAIN_SFT 20
+#define DL5_HDOMAIN_MASK 0xf
+#define DL5_HDOMAIN_MASK_SFT (0xf << 20)
+#define DL4_HDOMAIN_SFT 16
+#define DL4_HDOMAIN_MASK 0xf
+#define DL4_HDOMAIN_MASK_SFT (0xf << 16)
+#define DL3_HDOMAIN_SFT 12
+#define DL3_HDOMAIN_MASK 0xf
+#define DL3_HDOMAIN_MASK_SFT (0xf << 12)
+#define DL2_HDOMAIN_SFT 8
+#define DL2_HDOMAIN_MASK 0xf
+#define DL2_HDOMAIN_MASK_SFT (0xf << 8)
+#define DL1_HDOMAIN_SFT 4
+#define DL1_HDOMAIN_MASK 0xf
+#define DL1_HDOMAIN_MASK_SFT (0xf << 4)
+#define DL0_HDOMAIN_SFT 0
+#define DL0_HDOMAIN_MASK 0xf
+#define DL0_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND1 */
+#define DL_48CH_HDOMAIN_SFT 24
+#define DL_48CH_HDOMAIN_MASK 0xf
+#define DL_48CH_HDOMAIN_MASK_SFT (0xf << 24)
+#define DL_24CH_HDOMAIN_SFT 20
+#define DL_24CH_HDOMAIN_MASK 0xf
+#define DL_24CH_HDOMAIN_MASK_SFT (0xf << 20)
+#define DL_4CH_HDOMAIN_SFT 16
+#define DL_4CH_HDOMAIN_MASK 0xf
+#define DL_4CH_HDOMAIN_MASK_SFT (0xf << 16)
+#define HDMI_HDOMAIN_SFT 12
+#define HDMI_HDOMAIN_MASK 0xf
+#define HDMI_HDOMAIN_MASK_SFT (0xf << 12)
+#define SPDIF2_OUT_HDOMAIN_SFT 8
+#define SPDIF2_OUT_HDOMAIN_MASK 0xf
+#define SPDIF2_OUT_HDOMAIN_MASK_SFT (0xf << 8)
+#define SPDIF_OUT_HDOMAIN_SFT 4
+#define SPDIF_OUT_HDOMAIN_MASK 0xf
+#define SPDIF_OUT_HDOMAIN_MASK_SFT (0xf << 4)
+#define DL8_HDOMAIN_SFT 0
+#define DL8_HDOMAIN_MASK 0xf
+#define DL8_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND2 */
+#define DL30_HDOMAIN_SFT 28
+#define DL30_HDOMAIN_MASK 0xf
+#define DL30_HDOMAIN_MASK_SFT (0xf << 28)
+#define DL29_HDOMAIN_SFT 24
+#define DL29_HDOMAIN_MASK 0xf
+#define DL29_HDOMAIN_MASK_SFT (0xf << 24)
+#define DL28_HDOMAIN_SFT 20
+#define DL28_HDOMAIN_MASK 0xf
+#define DL28_HDOMAIN_MASK_SFT (0xf << 20)
+#define DL27_HDOMAIN_SFT 16
+#define DL27_HDOMAIN_MASK 0xf
+#define DL27_HDOMAIN_MASK_SFT (0xf << 16)
+#define DL26_HDOMAIN_SFT 12
+#define DL26_HDOMAIN_MASK 0xf
+#define DL26_HDOMAIN_MASK_SFT (0xf << 12)
+#define DL25_HDOMAIN_SFT 8
+#define DL25_HDOMAIN_MASK 0xf
+#define DL25_HDOMAIN_MASK_SFT (0xf << 8)
+#define DL24_HDOMAIN_SFT 4
+#define DL24_HDOMAIN_MASK 0xf
+#define DL24_HDOMAIN_MASK_SFT (0xf << 4)
+#define DL23_HDOMAIN_SFT 0
+#define DL23_HDOMAIN_MASK 0xf
+#define DL23_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND3 */
+#define DL38_HDOMAIN_SFT 28
+#define DL38_HDOMAIN_MASK 0xf
+#define DL38_HDOMAIN_MASK_SFT (0xf << 28)
+#define DL37_HDOMAIN_SFT 24
+#define DL37_HDOMAIN_MASK 0xf
+#define DL37_HDOMAIN_MASK_SFT (0xf << 24)
+#define DL36_HDOMAIN_SFT 20
+#define DL36_HDOMAIN_MASK 0xf
+#define DL36_HDOMAIN_MASK_SFT (0xf << 20)
+#define DL35_HDOMAIN_SFT 16
+#define DL35_HDOMAIN_MASK 0xf
+#define DL35_HDOMAIN_MASK_SFT (0xf << 16)
+#define DL34_HDOMAIN_SFT 12
+#define DL34_HDOMAIN_MASK 0xf
+#define DL34_HDOMAIN_MASK_SFT (0xf << 12)
+#define DL33_HDOMAIN_SFT 8
+#define DL33_HDOMAIN_MASK 0xf
+#define DL33_HDOMAIN_MASK_SFT (0xf << 8)
+#define DL32_HDOMAIN_SFT 4
+#define DL32_HDOMAIN_MASK 0xf
+#define DL32_HDOMAIN_MASK_SFT (0xf << 4)
+#define DL31_HDOMAIN_SFT 0
+#define DL31_HDOMAIN_MASK 0xf
+#define DL31_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND4 */
+#define DL46_HDOMAIN_SFT 28
+#define DL46_HDOMAIN_MASK 0xf
+#define DL46_HDOMAIN_MASK_SFT (0xf << 28)
+#define DL45_HDOMAIN_SFT 24
+#define DL45_HDOMAIN_MASK 0xf
+#define DL45_HDOMAIN_MASK_SFT (0xf << 24)
+#define DL44_HDOMAIN_SFT 20
+#define DL44_HDOMAIN_MASK 0xf
+#define DL44_HDOMAIN_MASK_SFT (0xf << 20)
+#define DL43_HDOMAIN_SFT 16
+#define DL43_HDOMAIN_MASK 0xf
+#define DL43_HDOMAIN_MASK_SFT (0xf << 16)
+#define DL42_HDOMAIN_SFT 12
+#define DL42_HDOMAIN_MASK 0xf
+#define DL42_HDOMAIN_MASK_SFT (0xf << 12)
+#define DL41_HDOMAIN_SFT 8
+#define DL41_HDOMAIN_MASK 0xf
+#define DL41_HDOMAIN_MASK_SFT (0xf << 8)
+#define DL40_HDOMAIN_SFT 4
+#define DL40_HDOMAIN_MASK 0xf
+#define DL40_HDOMAIN_MASK_SFT (0xf << 4)
+#define DL39_HDOMAIN_SFT 0
+#define DL39_HDOMAIN_MASK 0xf
+#define DL39_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND5 */
+#define VUL7_HDOMAIN_SFT 28
+#define VUL7_HDOMAIN_MASK 0xf
+#define VUL7_HDOMAIN_MASK_SFT (0xf << 28)
+#define VUL6_HDOMAIN_SFT 24
+#define VUL6_HDOMAIN_MASK 0xf
+#define VUL6_HDOMAIN_MASK_SFT (0xf << 24)
+#define VUL5_HDOMAIN_SFT 20
+#define VUL5_HDOMAIN_MASK 0xf
+#define VUL5_HDOMAIN_MASK_SFT (0xf << 20)
+#define VUL4_HDOMAIN_SFT 16
+#define VUL4_HDOMAIN_MASK 0xf
+#define VUL4_HDOMAIN_MASK_SFT (0xf << 16)
+#define VUL3_HDOMAIN_SFT 12
+#define VUL3_HDOMAIN_MASK 0xf
+#define VUL3_HDOMAIN_MASK_SFT (0xf << 12)
+#define VUL2_HDOMAIN_SFT 8
+#define VUL2_HDOMAIN_MASK 0xf
+#define VUL2_HDOMAIN_MASK_SFT (0xf << 8)
+#define VUL1_HDOMAIN_SFT 4
+#define VUL1_HDOMAIN_MASK 0xf
+#define VUL1_HDOMAIN_MASK_SFT (0xf << 4)
+#define VUL0_HDOMAIN_SFT 0
+#define VUL0_HDOMAIN_MASK 0xf
+#define VUL0_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND6 */
+#define VU25_HDOMAIN_SFT 28
+#define VU25_HDOMAIN_MASK 0xf
+#define VU25_HDOMAIN_MASK_SFT (0xf << 28)
+#define VUL24_HDOMAIN_SFT 24
+#define VUL24_HDOMAIN_MASK 0xf
+#define VUL24_HDOMAIN_MASK_SFT (0xf << 24)
+#define VUL_CM2_HDOMAIN_SFT 20
+#define VUL_CM2_HDOMAIN_MASK 0xf
+#define VUL_CM2_HDOMAIN_MASK_SFT (0xf << 20)
+#define VUL_CM1_HDOMAIN_SFT 16
+#define VUL_CM1_HDOMAIN_MASK 0xf
+#define VUL_CM1_HDOMAIN_MASK_SFT (0xf << 16)
+#define VUL_CM0_HDOMAIN_SFT 12
+#define VUL_CM0_HDOMAIN_MASK 0xf
+#define VUL_CM0_HDOMAIN_MASK_SFT (0xf << 12)
+#define VUL10_HDOMAIN_SFT 8
+#define VUL10_HDOMAIN_MASK 0xf
+#define VUL10_HDOMAIN_MASK_SFT (0xf << 8)
+#define VUL9_HDOMAIN_SFT 4
+#define VUL9_HDOMAIN_MASK 0xf
+#define VUL9_HDOMAIN_MASK_SFT (0xf << 4)
+#define VUL8_HDOMAIN_SFT 0
+#define VUL8_HDOMAIN_MASK 0xf
+#define VUL8_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND7 */
+#define VUL33_HDOMAIN_SFT 28
+#define VUL33_HDOMAIN_MASK 0xf
+#define VUL33_HDOMAIN_MASK_SFT (0xf << 28)
+#define VUL32_HDOMAIN_SFT 24
+#define VUL32_HDOMAIN_MASK 0xf
+#define VUL32_HDOMAIN_MASK_SFT (0xf << 24)
+#define VUL31_HDOMAIN_SFT 20
+#define VUL31_HDOMAIN_MASK 0xf
+#define VUL31_HDOMAIN_MASK_SFT (0xf << 20)
+#define VUL30_HDOMAIN_SFT 16
+#define VUL30_HDOMAIN_MASK 0xf
+#define VUL30_HDOMAIN_MASK_SFT (0xf << 16)
+#define VUL29_HDOMAIN_SFT 12
+#define VUL29_HDOMAIN_MASK 0xf
+#define VUL29_HDOMAIN_MASK_SFT (0xf << 12)
+#define VUL28_HDOMAIN_SFT 8
+#define VUL28_HDOMAIN_MASK 0xf
+#define VUL28_HDOMAIN_MASK_SFT (0xf << 8)
+#define VUL27_HDOMAIN_SFT 4
+#define VUL27_HDOMAIN_MASK 0xf
+#define VUL27_HDOMAIN_MASK_SFT (0xf << 4)
+#define VUL26_HDOMAIN_SFT 0
+#define VUL26_HDOMAIN_MASK 0xf
+#define VUL26_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND8 */
+#define ETDM_IN2_HDOMAIN_SFT 28
+#define ETDM_IN2_HDOMAIN_MASK 0xf
+#define ETDM_IN2_HDOMAIN_MASK_SFT (0xf << 28)
+#define ETDM_IN1_HDOMAIN_SFT 24
+#define ETDM_IN1_HDOMAIN_MASK 0xf
+#define ETDM_IN1_HDOMAIN_MASK_SFT (0xf << 24)
+#define ETDM_IN0_HDOMAIN_SFT 20
+#define ETDM_IN0_HDOMAIN_MASK 0xf
+#define ETDM_IN0_HDOMAIN_MASK_SFT (0xf << 20)
+#define VUL38_HDOMAIN_SFT 16
+#define VUL38_HDOMAIN_MASK 0xf
+#define VUL38_HDOMAIN_MASK_SFT (0xf << 16)
+#define VUL37_HDOMAIN_SFT 12
+#define VUL37_HDOMAIN_MASK 0xf
+#define VUL37_HDOMAIN_MASK_SFT (0xf << 12)
+#define VUL36_HDOMAIN_SFT 8
+#define VUL36_HDOMAIN_MASK 0xf
+#define VUL36_HDOMAIN_MASK_SFT (0xf << 8)
+#define VUL35_HDOMAIN_SFT 4
+#define VUL35_HDOMAIN_MASK 0xf
+#define VUL35_HDOMAIN_MASK_SFT (0xf << 4)
+#define VUL34_HDOMAIN_SFT 0
+#define VUL34_HDOMAIN_MASK 0xf
+#define VUL34_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_SE_DOMAIN_SIDEBAND9 */
+#define MPHONE_EARC_HDOMAIN_SFT 28
+#define MPHONE_EARC_HDOMAIN_MASK 0xf
+#define MPHONE_EARC_HDOMAIN_MASK_SFT (0xf << 28)
+#define MPHONE_SPDIF_HDOMAIN_SFT 24
+#define MPHONE_SPDIF_HDOMAIN_MASK 0xf
+#define MPHONE_SPDIF_HDOMAIN_MASK_SFT (0xf << 24)
+#define SPDIFIN_HDOMAIN_SFT 20
+#define SPDIFIN_HDOMAIN_MASK 0xf
+#define SPDIFIN_HDOMAIN_MASK_SFT (0xf << 20)
+#define TDMIN_HDOMAIN_SFT 16
+#define TDMIN_HDOMAIN_MASK 0xf
+#define TDMIN_HDOMAIN_MASK_SFT (0xf << 16)
+#define ETDM_IN6_HDOMAIN_SFT 12
+#define ETDM_IN6_HDOMAIN_MASK 0xf
+#define ETDM_IN6_HDOMAIN_MASK_SFT (0xf << 12)
+#define ETDM_IN5_HDOMAIN_SFT 8
+#define ETDM_IN5_HDOMAIN_MASK 0xf
+#define ETDM_IN5_HDOMAIN_MASK_SFT (0xf << 8)
+#define ETDM_IN4_HDOMAIN_SFT 4
+#define ETDM_IN4_HDOMAIN_MASK 0xf
+#define ETDM_IN4_HDOMAIN_MASK_SFT (0xf << 4)
+#define ETDM_IN3_HDOMAIN_SFT 0
+#define ETDM_IN3_HDOMAIN_MASK 0xf
+#define ETDM_IN3_HDOMAIN_MASK_SFT (0xf << 0)
+
+/* AFE_PROT_SIDEBAND0_MON */
+#define AFE_DOMAIN_SIDEBAN0_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN0_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN0_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_PROT_SIDEBAND1_MON */
+#define AFE_DOMAIN_SIDEBAN1_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN1_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN1_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_PROT_SIDEBAND2_MON */
+#define AFE_DOMAIN_SIDEBAN2_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN2_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN2_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_PROT_SIDEBAND3_MON */
+#define AFE_DOMAIN_SIDEBAN3_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN3_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN3_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND0_MON */
+#define AFE_DOMAIN_SIDEBAN0_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN0_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN0_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND1_MON */
+#define AFE_DOMAIN_SIDEBAN1_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN1_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN1_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND2_MON */
+#define AFE_DOMAIN_SIDEBAN2_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN2_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN2_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND3_MON */
+#define AFE_DOMAIN_SIDEBAN3_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN3_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN3_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND4_MON */
+#define AFE_DOMAIN_SIDEBAN0_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN0_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN0_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND5_MON */
+#define AFE_DOMAIN_SIDEBAN1_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN1_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN1_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND6_MON */
+#define AFE_DOMAIN_SIDEBAN2_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN2_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN2_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND7_MON */
+#define AFE_DOMAIN_SIDEBAN3_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN3_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN3_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND8_MON */
+#define AFE_DOMAIN_SIDEBAN2_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN2_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN2_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_DOMAIN_SIDEBAND9_MON */
+#define AFE_DOMAIN_SIDEBAN3_MON_SFT 0
+#define AFE_DOMAIN_SIDEBAN3_MON_MASK 0xffffffff
+#define AFE_DOMAIN_SIDEBAN3_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SECURE_CONN0 */
+#define AFE_SPDIFIN_LPBK_CON_MASK_S_SFT 26
+#define AFE_SPDIFIN_LPBK_CON_MASK_S_MASK 0x3
+#define AFE_SPDIFIN_LPBK_CON_MASK_S_MASK_SFT (0x3 << 26)
+#define AFE_ADDA_DMIC1_SRC_CON0_MASK_S_SFT 25
+#define AFE_ADDA_DMIC1_SRC_CON0_MASK_S_MASK 0x1
+#define AFE_ADDA_DMIC1_SRC_CON0_MASK_S_MASK_SFT (0x1 << 25)
+#define AFE_ADDA_DMIC0_SRC_CON0_MASK_S_SFT 24
+#define AFE_ADDA_DMIC0_SRC_CON0_MASK_S_MASK 0x1
+#define AFE_ADDA_DMIC0_SRC_CON0_MASK_S_MASK_SFT (0x1 << 24)
+#define AFE_ADDA_UL3_SRC_CON0_MASK_S_SFT 23
+#define AFE_ADDA_UL3_SRC_CON0_MASK_S_MASK 0x1
+#define AFE_ADDA_UL3_SRC_CON0_MASK_S_MASK_SFT (0x1 << 23)
+#define AFE_ADDA_UL2_SRC_CON0_MASK_S_SFT 22
+#define AFE_ADDA_UL2_SRC_CON0_MASK_S_MASK 0x1
+#define AFE_ADDA_UL2_SRC_CON0_MASK_S_MASK_SFT (0x1 << 22)
+#define AFE_ADDA_UL1_SRC_CON0_MASK_S_SFT 21
+#define AFE_ADDA_UL1_SRC_CON0_MASK_S_MASK 0x1
+#define AFE_ADDA_UL1_SRC_CON0_MASK_S_MASK_SFT (0x1 << 21)
+#define AFE_ADDA_UL0_SRC_CON0_MASK_S_SFT 20
+#define AFE_ADDA_UL0_SRC_CON0_MASK_S_MASK 0x1
+#define AFE_ADDA_UL0_SRC_CON0_MASK_S_MASK_SFT (0x1 << 20)
+#define AFE_MRKAIF1_CFG0_MASK_S_SFT 19
+#define AFE_MRKAIF1_CFG0_MASK_S_MASK 0x1
+#define AFE_MRKAIF1_CFG0_MASK_S_MASK_SFT (0x1 << 19)
+#define AFE_MRKAIF0_CFG0_MASK_S_SFT 18
+#define AFE_MRKAIF0_CFG0_MASK_S_MASK 0x1
+#define AFE_MRKAIF0_CFG0_MASK_S_MASK_SFT (0x1 << 18)
+#define AFE_TDMIN_CON1_MASK_S_SFT 17
+#define AFE_TDMIN_CON1_MASK_S_MASK 0x1
+#define AFE_TDMIN_CON1_MASK_S_MASK_SFT (0x1 << 17)
+#define AFE_TDM_CON2_MASK_S_SFT 16
+#define AFE_TDM_CON2_MASK_S_MASK 0x1
+#define AFE_TDM_CON2_MASK_S_MASK_SFT (0x1 << 16)
+#define AFE_DAIBT_CON_MASK_S_SFT 14
+#define AFE_DAIBT_CON_MASK_S_MASK 0x3
+#define AFE_DAIBT_CON_MASK_S_MASK_SFT (0x3 << 14)
+#define AFE_MRGIF_CON_MASK_S_SFT 12
+#define AFE_MRGIF_CON_MASK_S_MASK 0x3
+#define AFE_MRGIF_CON_MASK_S_MASK_SFT (0x3 << 12)
+#define AFE_CONNSYS_I2S_CON_MASK_S_SFT 11
+#define AFE_CONNSYS_I2S_CON_MASK_S_MASK 0x1
+#define AFE_CONNSYS_I2S_CON_MASK_S_MASK_SFT (0x1 << 11)
+#define AFE_PCM1_INFT_CON0_MASK_S_SFT 6
+#define AFE_PCM1_INFT_CON0_MASK_S_MASK 0x1f
+#define AFE_PCM1_INFT_CON0_MASK_S_MASK_SFT (0x1f << 6)
+#define AFE_PCM0_INTF_CON1_MASK_S_SFT 0
+#define AFE_PCM0_INTF_CON1_MASK_S_MASK 0x3f
+#define AFE_PCM0_INTF_CON1_MASK_S_MASK_SFT (0x3f << 0)
+
+/* AFE_SECURE_CONN_ETDM0 */
+#define ETDM_0_3_COWORK_CON2_OUT3_DATA_SEL_SFT 28
+#define ETDM_0_3_COWORK_CON2_OUT3_DATA_SEL_MASK 0xf
+#define ETDM_0_3_COWORK_CON2_OUT3_DATA_SEL_MASK_SFT (0xf << 28)
+#define ETDM_0_3_COWORK_CON2_OUT2_DATA_SEL_SFT 24
+#define ETDM_0_3_COWORK_CON2_OUT2_DATA_SEL_MASK 0xf
+#define ETDM_0_3_COWORK_CON2_OUT2_DATA_SEL_MASK_SFT (0xf << 24)
+#define ETDM_0_3_COWORK_CON2_IN1_SDATA1_15_SEL_SFT 20
+#define ETDM_0_3_COWORK_CON2_IN1_SDATA1_15_SEL_MASK 0xf
+#define ETDM_0_3_COWORK_CON2_IN1_SDATA1_15_SEL_MASK_SFT (0xf << 20)
+#define ETDM_0_3_COWORK_CON2_IN1_SDATA0_SEL_SFT 16
+#define ETDM_0_3_COWORK_CON2_IN1_SDATA0_SEL_MASK 0xf
+#define ETDM_0_3_COWORK_CON2_IN1_SDATA0_SEL_MASK_SFT (0xf << 16)
+#define ETDM_0_3_COWORK_CON2_IN0_SDATA1_15_SEL_SFT 12
+#define ETDM_0_3_COWORK_CON2_IN0_SDATA1_15_SEL_MASK 0xf
+#define ETDM_0_3_COWORK_CON2_IN0_SDATA1_15_SEL_MASK_SFT (0xf << 12)
+#define ETDM_0_3_COWORK_CON2_IN0_SDATA0_SEL_SFT 8
+#define ETDM_0_3_COWORK_CON2_IN0_SDATA0_SEL_MASK 0xf
+#define ETDM_0_3_COWORK_CON2_IN0_SDATA0_SEL_MASK_SFT (0xf << 8)
+#define ETDM_0_3_COWORK_CON2_OUT1_DATA_SEL_SFT 4
+#define ETDM_0_3_COWORK_CON2_OUT1_DATA_SEL_MASK 0xf
+#define ETDM_0_3_COWORK_CON2_OUT1_DATA_SEL_MASK_SFT (0xf << 4)
+#define ETDM_0_3_COWORK_CON2_OUT0_DATA_SEL_SFT 0
+#define ETDM_0_3_COWORK_CON2_OUT0_DATA_SEL_MASK 0xf
+#define ETDM_0_3_COWORK_CON2_OUT0_DATA_SEL_MASK_SFT (0xf << 0)
+
+/* AFE_SECURE_CONN_ETDM1 */
+#define ETDM_4_7_COWORK_CON1_IN4_SDATA1_15_SEL_SFT 28
+#define ETDM_4_7_COWORK_CON1_IN4_SDATA1_15_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON1_IN4_SDATA1_15_SEL_MASK_SFT (0xf << 28)
+#define ETDM_4_7_COWORK_CON1_IN4_SDATA0_SEL_SFT 24
+#define ETDM_4_7_COWORK_CON1_IN4_SDATA0_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON1_IN4_SDATA0_SEL_MASK_SFT (0xf << 24)
+#define ETDM_4_7_COWORK_CON1_OUT5_DATA_SEL_SFT 20
+#define ETDM_4_7_COWORK_CON1_OUT5_DATA_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON1_OUT5_DATA_SEL_MASK_SFT (0xf << 20)
+#define ETDM_4_7_COWORK_CON1_OUT4_DATA_SEL_SFT 16
+#define ETDM_4_7_COWORK_CON1_OUT4_DATA_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON1_OUT4_DATA_SEL_MASK_SFT (0xf << 16)
+#define ETDM_4_7_COWORK_CON1_IN3_SDATA1_15_SEL_SFT 12
+#define ETDM_4_7_COWORK_CON1_IN3_SDATA1_15_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON1_IN3_SDATA1_15_SEL_MASK_SFT (0xf << 12)
+#define ETDM_4_7_COWORK_CON1_IN3_SDATA0_SEL_SFT 8
+#define ETDM_4_7_COWORK_CON1_IN3_SDATA0_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON1_IN3_SDATA0_SEL_MASK_SFT (0xf << 8)
+#define ETDM_4_7_COWORK_CON1_IN2_SDATA1_15_SEL_SFT 4
+#define ETDM_4_7_COWORK_CON1_IN2_SDATA1_15_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON1_IN2_SDATA1_15_SEL_MASK_SFT (0xf << 4)
+#define ETDM_4_7_COWORK_CON1_IN2_SDATA0_SEL_SFT 0
+#define ETDM_4_7_COWORK_CON1_IN2_SDATA0_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON1_IN2_SDATA0_SEL_MASK_SFT (0xf << 0)
+
+/* AFE_SECURE_CONN_ETDM2 */
+#define ETDM_4_7_COWORK_CON3_IN7_SDATA1_15_SEL_SFT 28
+#define ETDM_4_7_COWORK_CON3_IN7_SDATA1_15_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON3_IN7_SDATA1_15_SEL_MASK_SFT (0xf << 28)
+#define ETDM_4_7_COWORK_CON3_IN7_SDATA0_SEL_SFT 24
+#define ETDM_4_7_COWORK_CON3_IN7_SDATA0_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON3_IN7_SDATA0_SEL_MASK_SFT (0xf << 24)
+#define ETDM_4_7_COWORK_CON3_IN6_SDATA1_15_SEL_SFT 20
+#define ETDM_4_7_COWORK_CON3_IN6_SDATA1_15_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON3_IN6_SDATA1_15_SEL_MASK_SFT (0xf << 20)
+#define ETDM_4_7_COWORK_CON3_IN6_SDATA0_SEL_SFT 16
+#define ETDM_4_7_COWORK_CON3_IN6_SDATA0_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON3_IN6_SDATA0_SEL_MASK_SFT (0xf << 16)
+#define ETDM_4_7_COWORK_CON3_OUT7_DATA_SEL_SFT 12
+#define ETDM_4_7_COWORK_CON3_OUT7_DATA_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON3_OUT7_DATA_SEL_MASK_SFT (0xf << 12)
+#define ETDM_4_7_COWORK_CON3_OUT6_DATA_SEL_SFT 8
+#define ETDM_4_7_COWORK_CON3_OUT6_DATA_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON3_OUT6_DATA_SEL_MASK_SFT (0xf << 8)
+#define ETDM_4_7_COWORK_CON3_IN5_SDATA1_15_SEL_SFT 4
+#define ETDM_4_7_COWORK_CON3_IN5_SDATA1_15_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON3_IN5_SDATA1_15_SEL_MASK_SFT (0xf << 4)
+#define ETDM_4_7_COWORK_CON3_IN5_SDATA0_SEL_SFT 0
+#define ETDM_4_7_COWORK_CON3_IN5_SDATA0_SEL_MASK 0xf
+#define ETDM_4_7_COWORK_CON3_IN5_SDATA0_SEL_MASK_SFT (0xf << 0)
+
+/* AFE_SECURE_SRAM_CON0 */
+#define SRAM_READ_EN15_NS_SFT 31
+#define SRAM_READ_EN15_NS_MASK 0x1
+#define SRAM_READ_EN15_NS_MASK_SFT (0x1 << 31)
+#define SRAM_WRITE_EN15_NS_SFT 30
+#define SRAM_WRITE_EN15_NS_MASK 0x1
+#define SRAM_WRITE_EN15_NS_MASK_SFT (0x1 << 30)
+#define SRAM_READ_EN14_NS_SFT 29
+#define SRAM_READ_EN14_NS_MASK 0x1
+#define SRAM_READ_EN14_NS_MASK_SFT (0x1 << 29)
+#define SRAM_WRITE_EN14_NS_SFT 28
+#define SRAM_WRITE_EN14_NS_MASK 0x1
+#define SRAM_WRITE_EN14_NS_MASK_SFT (0x1 << 28)
+#define SRAM_READ_EN13_NS_SFT 27
+#define SRAM_READ_EN13_NS_MASK 0x1
+#define SRAM_READ_EN13_NS_MASK_SFT (0x1 << 27)
+#define SRAM_WRITE_EN13_NS_SFT 26
+#define SRAM_WRITE_EN13_NS_MASK 0x1
+#define SRAM_WRITE_EN13_NS_MASK_SFT (0x1 << 26)
+#define SRAM_READ_EN12_NS_SFT 25
+#define SRAM_READ_EN12_NS_MASK 0x1
+#define SRAM_READ_EN12_NS_MASK_SFT (0x1 << 25)
+#define SRAM_WRITE_EN12_NS_SFT 24
+#define SRAM_WRITE_EN12_NS_MASK 0x1
+#define SRAM_WRITE_EN12_NS_MASK_SFT (0x1 << 24)
+#define SRAM_READ_EN11_NS_SFT 23
+#define SRAM_READ_EN11_NS_MASK 0x1
+#define SRAM_READ_EN11_NS_MASK_SFT (0x1 << 23)
+#define SRAM_WRITE_EN11_NS_SFT 22
+#define SRAM_WRITE_EN11_NS_MASK 0x1
+#define SRAM_WRITE_EN11_NS_MASK_SFT (0x1 << 22)
+#define SRAM_READ_EN10_NS_SFT 21
+#define SRAM_READ_EN10_NS_MASK 0x1
+#define SRAM_READ_EN10_NS_MASK_SFT (0x1 << 21)
+#define SRAM_WRITE_EN10_NS_SFT 20
+#define SRAM_WRITE_EN10_NS_MASK 0x1
+#define SRAM_WRITE_EN10_NS_MASK_SFT (0x1 << 20)
+#define SRAM_READ_EN9_NS_SFT 19
+#define SRAM_READ_EN9_NS_MASK 0x1
+#define SRAM_READ_EN9_NS_MASK_SFT (0x1 << 19)
+#define SRAM_WRITE_EN9_NS_SFT 18
+#define SRAM_WRITE_EN9_NS_MASK 0x1
+#define SRAM_WRITE_EN9_NS_MASK_SFT (0x1 << 18)
+#define SRAM_READ_EN8_NS_SFT 17
+#define SRAM_READ_EN8_NS_MASK 0x1
+#define SRAM_READ_EN8_NS_MASK_SFT (0x1 << 17)
+#define SRAM_WRITE_EN8_NS_SFT 16
+#define SRAM_WRITE_EN8_NS_MASK 0x1
+#define SRAM_WRITE_EN8_NS_MASK_SFT (0x1 << 16)
+#define SRAM_READ_EN7_NS_SFT 15
+#define SRAM_READ_EN7_NS_MASK 0x1
+#define SRAM_READ_EN7_NS_MASK_SFT (0x1 << 15)
+#define SRAM_WRITE_EN7_NS_SFT 14
+#define SRAM_WRITE_EN7_NS_MASK 0x1
+#define SRAM_WRITE_EN7_NS_MASK_SFT (0x1 << 14)
+#define SRAM_READ_EN6_NS_SFT 13
+#define SRAM_READ_EN6_NS_MASK 0x1
+#define SRAM_READ_EN6_NS_MASK_SFT (0x1 << 13)
+#define SRAM_WRITE_EN6_NS_SFT 12
+#define SRAM_WRITE_EN6_NS_MASK 0x1
+#define SRAM_WRITE_EN6_NS_MASK_SFT (0x1 << 12)
+#define SRAM_READ_EN5_NS_SFT 11
+#define SRAM_READ_EN5_NS_MASK 0x1
+#define SRAM_READ_EN5_NS_MASK_SFT (0x1 << 11)
+#define SRAM_WRITE_EN5_NS_SFT 10
+#define SRAM_WRITE_EN5_NS_MASK 0x1
+#define SRAM_WRITE_EN5_NS_MASK_SFT (0x1 << 10)
+#define SRAM_READ_EN4_NS_SFT 9
+#define SRAM_READ_EN4_NS_MASK 0x1
+#define SRAM_READ_EN4_NS_MASK_SFT (0x1 << 9)
+#define SRAM_WRITE_EN4_NS_SFT 8
+#define SRAM_WRITE_EN4_NS_MASK 0x1
+#define SRAM_WRITE_EN4_NS_MASK_SFT (0x1 << 8)
+#define SRAM_READ_EN3_NS_SFT 7
+#define SRAM_READ_EN3_NS_MASK 0x1
+#define SRAM_READ_EN3_NS_MASK_SFT (0x1 << 7)
+#define SRAM_WRITE_EN3_NS_SFT 6
+#define SRAM_WRITE_EN3_NS_MASK 0x1
+#define SRAM_WRITE_EN3_NS_MASK_SFT (0x1 << 6)
+#define SRAM_READ_EN2_NS_SFT 5
+#define SRAM_READ_EN2_NS_MASK 0x1
+#define SRAM_READ_EN2_NS_MASK_SFT (0x1 << 5)
+#define SRAM_WRITE_EN2_NS_SFT 4
+#define SRAM_WRITE_EN2_NS_MASK 0x1
+#define SRAM_WRITE_EN2_NS_MASK_SFT (0x1 << 4)
+#define SRAM_READ_EN1_NS_SFT 3
+#define SRAM_READ_EN1_NS_MASK 0x1
+#define SRAM_READ_EN1_NS_MASK_SFT (0x1 << 3)
+#define SRAM_WRITE_EN1_NS_SFT 2
+#define SRAM_WRITE_EN1_NS_MASK 0x1
+#define SRAM_WRITE_EN1_NS_MASK_SFT (0x1 << 2)
+#define SRAM_READ_EN0_NS_SFT 1
+#define SRAM_READ_EN0_NS_MASK 0x1
+#define SRAM_READ_EN0_NS_MASK_SFT (0x1 << 1)
+#define SRAM_WRITE_EN0_NS_SFT 0
+#define SRAM_WRITE_EN0_NS_MASK 0x1
+#define SRAM_WRITE_EN0_NS_MASK_SFT (0x1 << 0)
+
+/* AFE_SECURE_SRAM_CON1 */
+#define SRAM_READ_EN15_S_SFT 31
+#define SRAM_READ_EN15_S_MASK 0x1
+#define SRAM_READ_EN15_S_MASK_SFT (0x1 << 31)
+#define SRAM_WRITE_EN15_S_SFT 30
+#define SRAM_WRITE_EN15_S_MASK 0x1
+#define SRAM_WRITE_EN15_S_MASK_SFT (0x1 << 30)
+#define SRAM_READ_EN14_S_SFT 29
+#define SRAM_READ_EN14_S_MASK 0x1
+#define SRAM_READ_EN14_S_MASK_SFT (0x1 << 29)
+#define SRAM_WRITE_EN14_S_SFT 28
+#define SRAM_WRITE_EN14_S_MASK 0x1
+#define SRAM_WRITE_EN14_S_MASK_SFT (0x1 << 28)
+#define SRAM_READ_EN13_S_SFT 27
+#define SRAM_READ_EN13_S_MASK 0x1
+#define SRAM_READ_EN13_S_MASK_SFT (0x1 << 27)
+#define SRAM_WRITE_EN13_S_SFT 26
+#define SRAM_WRITE_EN13_S_MASK 0x1
+#define SRAM_WRITE_EN13_S_MASK_SFT (0x1 << 26)
+#define SRAM_READ_EN12_S_SFT 25
+#define SRAM_READ_EN12_S_MASK 0x1
+#define SRAM_READ_EN12_S_MASK_SFT (0x1 << 25)
+#define SRAM_WRITE_EN12_S_SFT 24
+#define SRAM_WRITE_EN12_S_MASK 0x1
+#define SRAM_WRITE_EN12_S_MASK_SFT (0x1 << 24)
+#define SRAM_READ_EN11_S_SFT 23
+#define SRAM_READ_EN11_S_MASK 0x1
+#define SRAM_READ_EN11_S_MASK_SFT (0x1 << 23)
+#define SRAM_WRITE_EN11_S_SFT 22
+#define SRAM_WRITE_EN11_S_MASK 0x1
+#define SRAM_WRITE_EN11_S_MASK_SFT (0x1 << 22)
+#define SRAM_READ_EN10_S_SFT 21
+#define SRAM_READ_EN10_S_MASK 0x1
+#define SRAM_READ_EN10_S_MASK_SFT (0x1 << 21)
+#define SRAM_WRITE_EN10_S_SFT 20
+#define SRAM_WRITE_EN10_S_MASK 0x1
+#define SRAM_WRITE_EN10_S_MASK_SFT (0x1 << 20)
+#define SRAM_READ_EN9_S_SFT 19
+#define SRAM_READ_EN9_S_MASK 0x1
+#define SRAM_READ_EN9_S_MASK_SFT (0x1 << 19)
+#define SRAM_WRITE_EN9_S_SFT 18
+#define SRAM_WRITE_EN9_S_MASK 0x1
+#define SRAM_WRITE_EN9_S_MASK_SFT (0x1 << 18)
+#define SRAM_READ_EN8_S_SFT 17
+#define SRAM_READ_EN8_S_MASK 0x1
+#define SRAM_READ_EN8_S_MASK_SFT (0x1 << 17)
+#define SRAM_WRITE_EN8_S_SFT 16
+#define SRAM_WRITE_EN8_S_MASK 0x1
+#define SRAM_WRITE_EN8_S_MASK_SFT (0x1 << 16)
+#define SRAM_READ_EN7_S_SFT 15
+#define SRAM_READ_EN7_S_MASK 0x1
+#define SRAM_READ_EN7_S_MASK_SFT (0x1 << 15)
+#define SRAM_WRITE_EN7_S_SFT 14
+#define SRAM_WRITE_EN7_S_MASK 0x1
+#define SRAM_WRITE_EN7_S_MASK_SFT (0x1 << 14)
+#define SRAM_READ_EN6_S_SFT 13
+#define SRAM_READ_EN6_S_MASK 0x1
+#define SRAM_READ_EN6_S_MASK_SFT (0x1 << 13)
+#define SRAM_WRITE_EN6_S_SFT 12
+#define SRAM_WRITE_EN6_S_MASK 0x1
+#define SRAM_WRITE_EN6_S_MASK_SFT (0x1 << 12)
+#define SRAM_READ_EN5_S_SFT 11
+#define SRAM_READ_EN5_S_MASK 0x1
+#define SRAM_READ_EN5_S_MASK_SFT (0x1 << 11)
+#define SRAM_WRITE_EN5_S_SFT 10
+#define SRAM_WRITE_EN5_S_MASK 0x1
+#define SRAM_WRITE_EN5_S_MASK_SFT (0x1 << 10)
+#define SRAM_READ_EN4_S_SFT 9
+#define SRAM_READ_EN4_S_MASK 0x1
+#define SRAM_READ_EN4_S_MASK_SFT (0x1 << 9)
+#define SRAM_WRITE_EN4_S_SFT 8
+#define SRAM_WRITE_EN4_S_MASK 0x1
+#define SRAM_WRITE_EN4_S_MASK_SFT (0x1 << 8)
+#define SRAM_READ_EN3_S_SFT 7
+#define SRAM_READ_EN3_S_MASK 0x1
+#define SRAM_READ_EN3_S_MASK_SFT (0x1 << 7)
+#define SRAM_WRITE_EN3_S_SFT 6
+#define SRAM_WRITE_EN3_S_MASK 0x1
+#define SRAM_WRITE_EN3_S_MASK_SFT (0x1 << 6)
+#define SRAM_READ_EN2_S_SFT 5
+#define SRAM_READ_EN2_S_MASK 0x1
+#define SRAM_READ_EN2_S_MASK_SFT (0x1 << 5)
+#define SRAM_WRITE_EN2_S_SFT 4
+#define SRAM_WRITE_EN2_S_MASK 0x1
+#define SRAM_WRITE_EN2_S_MASK_SFT (0x1 << 4)
+#define SRAM_READ_EN1_S_SFT 3
+#define SRAM_READ_EN1_S_MASK 0x1
+#define SRAM_READ_EN1_S_MASK_SFT (0x1 << 3)
+#define SRAM_WRITE_EN1_S_SFT 2
+#define SRAM_WRITE_EN1_S_MASK 0x1
+#define SRAM_WRITE_EN1_S_MASK_SFT (0x1 << 2)
+#define SRAM_READ_EN0_S_SFT 1
+#define SRAM_READ_EN0_S_MASK 0x1
+#define SRAM_READ_EN0_S_MASK_SFT (0x1 << 1)
+#define SRAM_WRITE_EN0_S_SFT 0
+#define SRAM_WRITE_EN0_S_MASK 0x1
+#define SRAM_WRITE_EN0_S_MASK_SFT (0x1 << 0)
+
+/* AFE_SE_CONN_INPUT_MASK0 */
+#define SECURE_INTRCONN_I0_I31_S_SFT 0
+#define SECURE_INTRCONN_I0_I31_S_MASK 0xffffffff
+#define SECURE_INTRCONN_I0_I31_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_INPUT_MASK1 */
+#define SECURE_INTRCONN_I32_I63_S_SFT 0
+#define SECURE_INTRCONN_I32_I63_S_MASK 0xffffffff
+#define SECURE_INTRCONN_I32_I63_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_INPUT_MASK2 */
+#define SECURE_INTRCONN_I64_I95_S_SFT 0
+#define SECURE_INTRCONN_I64_I95_S_MASK 0xffffffff
+#define SECURE_INTRCONN_I64_I95_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_INPUT_MASK3 */
+#define SECURE_INTRCONN_I96_I127_S_SFT 0
+#define SECURE_INTRCONN_I96_I127_S_MASK 0xffffffff
+#define SECURE_INTRCONN_I96_I127_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_INPUT_MASK4 */
+#define SECURE_INTRCONN_I128_I159_S_SFT 0
+#define SECURE_INTRCONN_I128_I159_S_MASK 0xffffffff
+#define SECURE_INTRCONN_I128_I159_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_INPUT_MASK5 */
+#define SECURE_INTRCONN_I160_I191_S_SFT 0
+#define SECURE_INTRCONN_I160_I191_S_MASK 0xffffffff
+#define SECURE_INTRCONN_I160_I191_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_INPUT_MASK6 */
+#define SECURE_INTRCONN_I192_I223_S_SFT 0
+#define SECURE_INTRCONN_I192_I223_S_MASK 0xffffffff
+#define SECURE_INTRCONN_I192_I223_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_INPUT_MASK7 */
+#define SECURE_INTRCONN_I224_I256_S_SFT 0
+#define SECURE_INTRCONN_I224_I256_S_MASK 0xffffffff
+#define SECURE_INTRCONN_I224_I256_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_NON_SE_CONN_INPUT_MASK0 */
+#define NORMAL_INTRCONN_I0_I31_S_SFT 0
+#define NORMAL_INTRCONN_I0_I31_S_MASK 0xffffffff
+#define NORMAL_INTRCONN_I0_I31_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_NON_SE_CONN_INPUT_MASK1 */
+#define NORMAL_INTRCONN_I32_I63_S_SFT 0
+#define NORMAL_INTRCONN_I32_I63_S_MASK 0xffffffff
+#define NORMAL_INTRCONN_I32_I63_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_NON_SE_CONN_INPUT_MASK2 */
+#define NORMAL_INTRCONN_I64_I95_S_SFT 0
+#define NORMAL_INTRCONN_I64_I95_S_MASK 0xffffffff
+#define NORMAL_INTRCONN_I64_I95_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_NON_SE_CONN_INPUT_MASK3 */
+#define NORMAL_INTRCONN_I96_I127_S_SFT 0
+#define NORMAL_INTRCONN_I96_I127_S_MASK 0xffffffff
+#define NORMAL_INTRCONN_I96_I127_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_NON_SE_CONN_INPUT_MASK4 */
+#define NORMAL_INTRCONN_I128_I159_S_SFT 0
+#define NORMAL_INTRCONN_I128_I159_S_MASK 0xffffffff
+#define NORMAL_INTRCONN_I128_I159_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_NON_SE_CONN_INPUT_MASK5 */
+#define NORMAL_INTRCONN_I160_I191_S_SFT 0
+#define NORMAL_INTRCONN_I160_I191_S_MASK 0xffffffff
+#define NORMAL_INTRCONN_I160_I191_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_NON_SE_CONN_INPUT_MASK6 */
+#define NORMAL_INTRCONN_I192_I223_S_SFT 0
+#define NORMAL_INTRCONN_I192_I223_S_MASK 0xffffffff
+#define NORMAL_INTRCONN_I192_I223_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_NON_SE_CONN_INPUT_MASK7 */
+#define NORMAL_INTRCONN_I224_I256_S_SFT 0
+#define NORMAL_INTRCONN_I224_I256_S_MASK 0xffffffff
+#define NORMAL_INTRCONN_I224_I256_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_OUTPUT_SEL0 */
+#define SECURE_INTRCONN_O0_O31_S_SFT 0
+#define SECURE_INTRCONN_O0_O31_S_MASK 0xffffffff
+#define SECURE_INTRCONN_O0_O31_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_OUTPUT_SEL1 */
+#define SECURE_INTRCONN_O32_O63_S_SFT 0
+#define SECURE_INTRCONN_O32_O63_S_MASK 0xffffffff
+#define SECURE_INTRCONN_O32_O63_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_OUTPUT_SEL2 */
+#define SECURE_INTRCONN_O64_O95_S_SFT 0
+#define SECURE_INTRCONN_O64_O95_S_MASK 0xffffffff
+#define SECURE_INTRCONN_O64_O95_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_OUTPUT_SEL3 */
+#define SECURE_INTRCONN_O96_O127_S_SFT 0
+#define SECURE_INTRCONN_O96_O127_S_MASK 0xffffffff
+#define SECURE_INTRCONN_O96_O127_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_OUTPUT_SEL4 */
+#define SECURE_INTRCONN_O128_O159_S_SFT 0
+#define SECURE_INTRCONN_O128_O159_S_MASK 0xffffffff
+#define SECURE_INTRCONN_O128_O159_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_OUTPUT_SEL5 */
+#define SECURE_INTRCONN_O160_O191_S_SFT 0
+#define SECURE_INTRCONN_O160_O191_S_MASK 0xffffffff
+#define SECURE_INTRCONN_O160_O191_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_OUTPUT_SEL6 */
+#define SECURE_INTRCONN_O192_O223_S_SFT 0
+#define SECURE_INTRCONN_O192_O223_S_MASK 0xffffffff
+#define SECURE_INTRCONN_O192_O223_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_SE_CONN_OUTPUT_SEL7 */
+#define SECURE_INTRCONN_O224_O256_S_SFT 0
+#define SECURE_INTRCONN_O224_O256_S_MASK 0xffffffff
+#define SECURE_INTRCONN_O224_O256_S_MASK_SFT (0xffffffff << 0)
+
+/* AFE_PCM0_INTF_CON1_MASK_MON */
+#define AFE_PCM0_INTF_CON1_MASK_MON_SFT 0
+#define AFE_PCM0_INTF_CON1_MASK_MON_MASK 0xffffffff
+#define AFE_PCM0_INTF_CON1_MASK_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_PCM0_INTF_CON0_MASK_MON */
+#define AFE_PCM0_INTF_CON0_MASK_MON_SFT 0
+#define AFE_PCM0_INTF_CON0_MASK_MON_MASK 0xffffffff
+#define AFE_PCM0_INTF_CON0_MASK_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_CONNSYS_I2S_CON_MASK_MON */
+#define AFE_CONNSYS_I2S_CON_MASK_MON_SFT 0
+#define AFE_CONNSYS_I2S_CON_MASK_MON_MASK 0xffffffff
+#define AFE_CONNSYS_I2S_CON_MASK_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_TDM_CON2_MASK_MON */
+#define AFE_TDM_CON2_MASK_MON_SFT 0
+#define AFE_TDM_CON2_MASK_MON_MASK 0xffffffff
+#define AFE_TDM_CON2_MASK_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_MTKAIF0_CFG0_MASK_MON */
+#define AFE_MTKAIF0_CFG0_MASK_MON_SFT 0
+#define AFE_MTKAIF0_CFG0_MASK_MON_MASK 0xffffffff
+#define AFE_MTKAIF0_CFG0_MASK_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_MTKAIF1_CFG0_MASK_MON */
+#define AFE_MTKAIF1_CFG0_MASK_MON_SFT 0
+#define AFE_MTKAIF1_CFG0_MASK_MON_MASK 0xffffffff
+#define AFE_MTKAIF1_CFG0_MASK_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL0_SRC_CON0_MASK_MON */
+#define AFE_ADDA_UL0_SRC_CON0_MASK_MON_SFT 0
+#define AFE_ADDA_UL0_SRC_CON0_MASK_MON_MASK 0xffffffff
+#define AFE_ADDA_UL0_SRC_CON0_MASK_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL1_SRC_CON0_MASK_MON */
+#define AFE_ADDA_UL1_SRC_CON0_MASK_MON_SFT 0
+#define AFE_ADDA_UL1_SRC_CON0_MASK_MON_MASK 0xffffffff
+#define AFE_ADDA_UL1_SRC_CON0_MASK_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ADDA_UL2_SRC_CON0_MASK_MON */
+#define AFE_ADDA_UL2_SRC_CON0_MASK_MON_SFT 0
+#define AFE_ADDA_UL2_SRC_CON0_MASK_MON_MASK 0xffffffff
+#define AFE_ADDA_UL2_SRC_CON0_MASK_MON_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ASRC_NEW_CON0 */
+#define ONE_HEART_SFT 31
+#define ONE_HEART_MASK 0x1
+#define ONE_HEART_MASK_SFT (0x1 << 31)
+#define CHSET0_OFS_ONE_HEART_DISABLE_SFT 30
+#define CHSET0_OFS_ONE_HEART_DISABLE_MASK 0x1
+#define CHSET0_OFS_ONE_HEART_DISABLE_MASK_SFT (0x1 << 30)
+#define USE_SHORT_DELAY_COEFF_SFT 29
+#define USE_SHORT_DELAY_COEFF_MASK 0x1
+#define USE_SHORT_DELAY_COEFF_MASK_SFT (0x1 << 29)
+#define CHSET0_O16BIT_SFT 19
+#define CHSET0_O16BIT_MASK 0x1
+#define CHSET0_O16BIT_MASK_SFT (0x1 << 19)
+#define CHSET0_CLR_IIR_HISTORY_SFT 17
+#define CHSET0_CLR_IIR_HISTORY_MASK 0x1
+#define CHSET0_CLR_IIR_HISTORY_MASK_SFT (0x1 << 17)
+#define CHSET0_IS_MONO_SFT 16
+#define CHSET0_IS_MONO_MASK 0x1
+#define CHSET0_IS_MONO_MASK_SFT (0x1 << 16)
+#define CHSET0_OFS_SEL_SFT 14
+#define CHSET0_OFS_SEL_MASK 0x3
+#define CHSET0_OFS_SEL_MASK_SFT (0x3 << 14)
+#define CHSET0_IFS_SEL_SFT 12
+#define CHSET0_IFS_SEL_MASK 0x3
+#define CHSET0_IFS_SEL_MASK_SFT (0x3 << 12)
+#define CHSET0_IIR_EN_SFT 11
+#define CHSET0_IIR_EN_MASK 0x1
+#define CHSET0_IIR_EN_MASK_SFT (0x1 << 11)
+#define CHSET0_IIR_STAGE_SFT 8
+#define CHSET0_IIR_STAGE_MASK 0x7
+#define CHSET0_IIR_STAGE_MASK_SFT (0x7 << 8)
+#define ASM_ON_MOD_SFT 7
+#define ASM_ON_MOD_MASK 0x1
+#define ASM_ON_MOD_MASK_SFT (0x1 << 7)
+#define CHSET_STR_CLR_SFT 4
+#define CHSET_STR_CLR_MASK 0x1
+#define CHSET_STR_CLR_MASK_SFT (0x1 << 4)
+#define CHSET_ON_SFT 2
+#define CHSET_ON_MASK 0x1
+#define CHSET_ON_MASK_SFT (0x1 << 2)
+#define COEFF_SRAM_CTRL_SFT 1
+#define COEFF_SRAM_CTRL_MASK 0x1
+#define COEFF_SRAM_CTRL_MASK_SFT (0x1 << 1)
+#define ASM_ON_SFT 0
+#define ASM_ON_MASK 0x1
+#define ASM_ON_MASK_SFT (0x1 << 0)
+
+/* AFE_ASRC_NEW_CON1 */
+#define ASM_FREQ_0_SFT 0
+#define ASM_FREQ_0_MASK 0xffffff
+#define ASM_FREQ_0_MASK_SFT (0xffffff << 0)
+
+/* AFE_ASRC_NEW_CON2 */
+#define ASM_FREQ_1_SFT 0
+#define ASM_FREQ_1_MASK 0xffffff
+#define ASM_FREQ_1_MASK_SFT (0xffffff << 0)
+
+/* AFE_ASRC_NEW_CON3 */
+#define ASM_FREQ_2_SFT 0
+#define ASM_FREQ_2_MASK 0xffffff
+#define ASM_FREQ_2_MASK_SFT (0xffffff << 0)
+
+/* AFE_ASRC_NEW_CON4 */
+#define ASM_FREQ_3_SFT 0
+#define ASM_FREQ_3_MASK 0xffffff
+#define ASM_FREQ_3_MASK_SFT (0xffffff << 0)
+
+/* AFE_ASRC_NEW_CON5 */
+#define OUT_EN_SEL_DOMAIN_SFT 29
+#define OUT_EN_SEL_DOMAIN_MASK 0x7
+#define OUT_EN_SEL_DOMAIN_MASK_SFT (0x7 << 29)
+#define OUT_EN_SEL_FS_SFT 24
+#define OUT_EN_SEL_FS_MASK 0x1f
+#define OUT_EN_SEL_FS_MASK_SFT (0x1f << 24)
+#define IN_EN_SEL_DOMAIN_SFT 21
+#define IN_EN_SEL_DOMAIN_MASK 0x7
+#define IN_EN_SEL_DOMAIN_MASK_SFT (0x7 << 21)
+#define IN_EN_SEL_FS_SFT 16
+#define IN_EN_SEL_FS_MASK 0x1f
+#define IN_EN_SEL_FS_MASK_SFT (0x1f << 16)
+#define RESULT_SEL_SFT 8
+#define RESULT_SEL_MASK 0x7
+#define RESULT_SEL_MASK_SFT (0x7 << 8)
+#define CALI_CK_SEL_SFT 4
+#define CALI_CK_SEL_MASK 0x7
+#define CALI_CK_SEL_MASK_SFT (0x7 << 4)
+#define CALI_LRCK_SEL_SFT 1
+#define CALI_LRCK_SEL_MASK 0x7
+#define CALI_LRCK_SEL_MASK_SFT (0x7 << 1)
+#define SOFT_RESET_SFT 0
+#define SOFT_RESET_MASK 0x1
+#define SOFT_RESET_MASK_SFT (0x1 << 0)
+
+/* AFE_ASRC_NEW_CON6 */
+#define FREQ_CALI_CYCLE_SFT 16
+#define FREQ_CALI_CYCLE_MASK 0xffff
+#define FREQ_CALI_CYCLE_MASK_SFT (0xffff << 16)
+#define FREQ_CALI_AUTORST_EN_SFT 15
+#define FREQ_CALI_AUTORST_EN_MASK 0x1
+#define FREQ_CALI_AUTORST_EN_MASK_SFT (0x1 << 15)
+#define CALI_AUTORST_DETECT_SFT 14
+#define CALI_AUTORST_DETECT_MASK 0x1
+#define CALI_AUTORST_DETECT_MASK_SFT (0x1 << 14)
+#define FREQ_CALC_RUNNING_SFT 13
+#define FREQ_CALC_RUNNING_MASK 0x1
+#define FREQ_CALC_RUNNING_MASK_SFT (0x1 << 13)
+#define AUTO_TUNE_FREQ3_SFT 12
+#define AUTO_TUNE_FREQ3_MASK 0x1
+#define AUTO_TUNE_FREQ3_MASK_SFT (0x1 << 12)
+#define COMP_FREQ_RES_EN_SFT 11
+#define COMP_FREQ_RES_EN_MASK 0x1
+#define COMP_FREQ_RES_EN_MASK_SFT (0x1 << 11)
+#define FREQ_CALI_SEL_SFT 8
+#define FREQ_CALI_SEL_MASK 0x3
+#define FREQ_CALI_SEL_MASK_SFT (0x3 << 8)
+#define FREQ_CALI_BP_DGL_SFT 7
+#define FREQ_CALI_BP_DGL_MASK 0x1
+#define FREQ_CALI_BP_DGL_MASK_SFT (0x1 << 7)
+#define FREQ_CALI_MAX_GWIDTH_SFT 4
+#define FREQ_CALI_MAX_GWIDTH_MASK 0x7
+#define FREQ_CALI_MAX_GWIDTH_MASK_SFT (0x7 << 4)
+#define AUTO_TUNE_FREQ2_SFT 3
+#define AUTO_TUNE_FREQ2_MASK 0x1
+#define AUTO_TUNE_FREQ2_MASK_SFT (0x1 << 3)
+#define FREQ_CALI_AUTO_RESTART_SFT 2
+#define FREQ_CALI_AUTO_RESTART_MASK 0x1
+#define FREQ_CALI_AUTO_RESTART_MASK_SFT (0x1 << 2)
+#define CALI_USE_FREQ_OUT_SFT 1
+#define CALI_USE_FREQ_OUT_MASK 0x1
+#define CALI_USE_FREQ_OUT_MASK_SFT (0x1 << 1)
+#define CALI_EN_SFT 0
+#define CALI_EN_MASK 0x1
+#define CALI_EN_MASK_SFT (0x1 << 0)
+
+/* AFE_ASRC_NEW_CON7 */
+#define FREQ_CALC_DENOMINATOR_SFT 0
+#define FREQ_CALC_DENOMINATOR_MASK 0xffffff
+#define FREQ_CALC_DENOMINATOR_MASK_SFT (0xffffff << 0)
+
+/* AFE_ASRC_NEW_CON8 */
+#define PRD_CALI_RESULT_RECORD_SFT 0
+#define PRD_CALI_RESULT_RECORD_MASK 0xffffff
+#define PRD_CALI_RESULT_RECORD_MASK_SFT (0xffffff << 0)
+
+/* AFE_ASRC_NEW_CON9 */
+#define FREQ_CALI_RESULT_SFT 0
+#define FREQ_CALI_RESULT_MASK 0xffffff
+#define FREQ_CALI_RESULT_MASK_SFT (0xffffff << 0)
+
+/* AFE_ASRC_NEW_CON10 */
+#define COEFF_SRAM_DATA_SFT 0
+#define COEFF_SRAM_DATA_MASK 0xffffffff
+#define COEFF_SRAM_DATA_MASK_SFT (0xffffffff << 0)
+
+/* AFE_ASRC_NEW_CON11 */
+#define COEFF_SRAM_ADR_SFT 0
+#define COEFF_SRAM_ADR_MASK 0x3f
+#define COEFF_SRAM_ADR_MASK_SFT (0x3f << 0)
+
+/* AFE_ASRC_NEW_CON12 */
+#define RING_DBG_RD_SFT 0
+#define RING_DBG_RD_MASK 0x3ffffff
+#define RING_DBG_RD_MASK_SFT (0x3ffffff << 0)
+
+/* AFE_ASRC_NEW_CON13 */
+#define FREQ_CALI_AUTORST_TH_HIGH_SFT 0
+#define FREQ_CALI_AUTORST_TH_HIGH_MASK 0xffffff
+#define FREQ_CALI_AUTORST_TH_HIGH_MASK_SFT (0xffffff << 0)
+
+/* AFE_ASRC_NEW_CON14 */
+#define FREQ_CALI_AUTORST_TH_LOW_SFT 0
+#define FREQ_CALI_AUTORST_TH_LOW_MASK 0xffffff
+#define FREQ_CALI_AUTORST_TH_LOW_MASK_SFT (0xffffff << 0)
+
+/* AFE_ASRC_NEW_IP_VERSION */
+#define IP_VERSION_SFT 0
+#define IP_VERSION_MASK 0xffffffff
+#define IP_VERSION_MASK_SFT (0xffffffff << 0)
+
+#define AUDIO_TOP_CON0 0x0
+#define AUDIO_TOP_CON1 0x4
+#define AUDIO_TOP_CON2 0x8
+#define AUDIO_TOP_CON3 0xc
+#define AUDIO_TOP_CON4 0x10
+#define AUDIO_ENGEN_CON0 0x14
+#define AUDIO_ENGEN_CON0_USER1 0x18
+#define AUDIO_ENGEN_CON0_USER2 0x1c
+#define AFE_SINEGEN_CON0 0x20
+#define AFE_SINEGEN_CON1 0x24
+#define AFE_SINEGEN_CON2 0x28
+#define AFE_SINEGEN_CON3 0x2c
+#define AFE_APLL1_TUNER_CFG 0x30
+#define AFE_APLL1_TUNER_MON0 0x34
+#define AFE_APLL2_TUNER_CFG 0x38
+#define AFE_APLL2_TUNER_MON0 0x3c
+#define AUDIO_TOP_RG0 0x4c
+#define AUDIO_TOP_RG1 0x50
+#define AUDIO_TOP_RG2 0x54
+#define AUDIO_TOP_RG3 0x58
+#define AUDIO_TOP_RG4 0x5c
+#define AFE_SPM_CONTROL_REQ 0x60
+#define AFE_SPM_CONTROL_ACK 0x64
+#define AUD_TOP_CFG_VCORE_RG 0x68
+#define AUDIO_TOP_IP_VERSION 0x6c
+#define AUDIO_ENGEN_CON0_MON 0x7c
+#define AUD_TOP_CFG_VLP_RG 0x98
+#define AUD_TOP_MON_RG 0x9c
+#define AUDIO_USE_DEFAULT_DELSEL0 0xa0
+#define AUDIO_USE_DEFAULT_DELSEL1 0xa4
+#define AUDIO_USE_DEFAULT_DELSEL2 0xa8
+#define AFE_CONNSYS_I2S_IPM_VER_MON 0xb0
+#define AFE_CONNSYS_I2S_MON_SEL 0xb4
+#define AFE_CONNSYS_I2S_MON 0xb8
+#define AFE_CONNSYS_I2S_CON 0xbc
+#define AFE_PCM0_INTF_CON0 0xc0
+#define AFE_PCM0_INTF_CON1 0xc4
+#define AFE_PCM_INTF_MON 0xc8
+#define AFE_PCM1_INTF_CON0 0xd0
+#define AFE_PCM1_INTF_CON1 0xd4
+#define AFE_PCM_TOP_IP_VERSION 0xe8
+#define AFE_IRQ_MCU_EN 0x100
+#define AFE_IRQ_MCU_DSP_EN 0x104
+#define AFE_IRQ_MCU_DSP2_EN 0x108
+#define AFE_IRQ_MCU_SCP_EN 0x10c
+#define AFE_CUSTOM_IRQ_MCU_EN 0x110
+#define AFE_CUSTOM_IRQ_MCU_DSP_EN 0x114
+#define AFE_CUSTOM_IRQ_MCU_DSP2_EN 0x118
+#define AFE_CUSTOM_IRQ_MCU_SCP_EN 0x11c
+#define AFE_IRQ_MCU_STATUS 0x120
+#define AFE_CUSTOM_IRQ_MCU_STATUS 0x124
+#define AFE_IRQ0_MCU_CFG0 0x140
+#define AFE_IRQ0_MCU_CFG1 0x144
+#define AFE_IRQ1_MCU_CFG0 0x148
+#define AFE_IRQ1_MCU_CFG1 0x14c
+#define AFE_IRQ2_MCU_CFG0 0x150
+#define AFE_IRQ2_MCU_CFG1 0x154
+#define AFE_IRQ3_MCU_CFG0 0x158
+#define AFE_IRQ3_MCU_CFG1 0x15c
+#define AFE_IRQ4_MCU_CFG0 0x160
+#define AFE_IRQ4_MCU_CFG1 0x164
+#define AFE_IRQ5_MCU_CFG0 0x168
+#define AFE_IRQ5_MCU_CFG1 0x16c
+#define AFE_IRQ6_MCU_CFG0 0x170
+#define AFE_IRQ6_MCU_CFG1 0x174
+#define AFE_IRQ7_MCU_CFG0 0x178
+#define AFE_IRQ7_MCU_CFG1 0x17c
+#define AFE_IRQ8_MCU_CFG0 0x180
+#define AFE_IRQ8_MCU_CFG1 0x184
+#define AFE_IRQ9_MCU_CFG0 0x188
+#define AFE_IRQ9_MCU_CFG1 0x18c
+#define AFE_IRQ10_MCU_CFG0 0x190
+#define AFE_IRQ10_MCU_CFG1 0x194
+#define AFE_IRQ11_MCU_CFG0 0x198
+#define AFE_IRQ11_MCU_CFG1 0x19c
+#define AFE_IRQ12_MCU_CFG0 0x1a0
+#define AFE_IRQ12_MCU_CFG1 0x1a4
+#define AFE_IRQ13_MCU_CFG0 0x1a8
+#define AFE_IRQ13_MCU_CFG1 0x1ac
+#define AFE_IRQ14_MCU_CFG0 0x1b0
+#define AFE_IRQ14_MCU_CFG1 0x1b4
+#define AFE_IRQ15_MCU_CFG0 0x1b8
+#define AFE_IRQ15_MCU_CFG1 0x1bc
+#define AFE_IRQ16_MCU_CFG0 0x1c0
+#define AFE_IRQ16_MCU_CFG1 0x1c4
+#define AFE_IRQ17_MCU_CFG0 0x1c8
+#define AFE_IRQ17_MCU_CFG1 0x1cc
+#define AFE_IRQ18_MCU_CFG0 0x1d0
+#define AFE_IRQ18_MCU_CFG1 0x1d4
+#define AFE_IRQ19_MCU_CFG0 0x1d8
+#define AFE_IRQ19_MCU_CFG1 0x1dc
+#define AFE_IRQ20_MCU_CFG0 0x1e0
+#define AFE_IRQ20_MCU_CFG1 0x1e4
+#define AFE_IRQ21_MCU_CFG0 0x1e8
+#define AFE_IRQ21_MCU_CFG1 0x1ec
+#define AFE_IRQ22_MCU_CFG0 0x1f0
+#define AFE_IRQ22_MCU_CFG1 0x1f4
+#define AFE_IRQ23_MCU_CFG0 0x1f8
+#define AFE_IRQ23_MCU_CFG1 0x1fc
+#define AFE_IRQ24_MCU_CFG0 0x200
+#define AFE_IRQ24_MCU_CFG1 0x204
+#define AFE_IRQ25_MCU_CFG0 0x208
+#define AFE_IRQ25_MCU_CFG1 0x20c
+#define AFE_IRQ26_MCU_CFG0 0x210
+#define AFE_IRQ26_MCU_CFG1 0x214
+#define AFE_CUSTOM_IRQ0_MCU_CFG0 0x268
+#define AFE_IRQ_MCU_MON0 0x300
+#define AFE_IRQ_MCU_MON1 0x304
+#define AFE_IRQ_MCU_MON2 0x308
+#define AFE_IRQ0_CNT_MON 0x310
+#define AFE_IRQ1_CNT_MON 0x314
+#define AFE_IRQ2_CNT_MON 0x318
+#define AFE_IRQ3_CNT_MON 0x31c
+#define AFE_IRQ4_CNT_MON 0x320
+#define AFE_IRQ5_CNT_MON 0x324
+#define AFE_IRQ6_CNT_MON 0x328
+#define AFE_IRQ7_CNT_MON 0x32c
+#define AFE_IRQ8_CNT_MON 0x330
+#define AFE_IRQ9_CNT_MON 0x334
+#define AFE_IRQ10_CNT_MON 0x338
+#define AFE_IRQ11_CNT_MON 0x33c
+#define AFE_IRQ12_CNT_MON 0x340
+#define AFE_IRQ13_CNT_MON 0x344
+#define AFE_IRQ14_CNT_MON 0x348
+#define AFE_IRQ15_CNT_MON 0x34c
+#define AFE_IRQ16_CNT_MON 0x350
+#define AFE_IRQ17_CNT_MON 0x354
+#define AFE_IRQ18_CNT_MON 0x358
+#define AFE_IRQ19_CNT_MON 0x35c
+#define AFE_IRQ20_CNT_MON 0x360
+#define AFE_IRQ21_CNT_MON 0x364
+#define AFE_IRQ22_CNT_MON 0x368
+#define AFE_IRQ23_CNT_MON 0x36c
+#define AFE_IRQ24_CNT_MON 0x370
+#define AFE_IRQ25_CNT_MON 0x374
+#define AFE_IRQ26_CNT_MON 0x378
+#define AFE_CUSTOM_IRQ0_CNT_MON 0x390
+#define AFE_CUSTOM_IRQ0_MCU_CFG1 0x3dc
+#define AFE_GAIN0_CON0 0x400
+#define AFE_GAIN0_CON1_R 0x404
+#define AFE_GAIN0_CON1_L 0x408
+#define AFE_GAIN0_CON2 0x40c
+#define AFE_GAIN0_CON3 0x410
+#define AFE_GAIN0_CUR_R 0x414
+#define AFE_GAIN0_CUR_L 0x418
+#define AFE_GAIN1_CON0 0x41c
+#define AFE_GAIN1_CON1_R 0x420
+#define AFE_GAIN1_CON1_L 0x424
+#define AFE_GAIN1_CON2 0x428
+#define AFE_GAIN1_CON3 0x42c
+#define AFE_GAIN1_CUR_R 0x430
+#define AFE_GAIN1_CUR_L 0x434
+#define AFE_GAIN2_CON0 0x438
+#define AFE_GAIN2_CON1_R 0x43c
+#define AFE_GAIN2_CON1_L 0x440
+#define AFE_GAIN2_CON2 0x444
+#define AFE_GAIN2_CON3 0x448
+#define AFE_GAIN2_CUR_R 0x44c
+#define AFE_GAIN2_CUR_L 0x450
+#define AFE_GAIN3_CON0 0x454
+#define AFE_GAIN3_CON1_R 0x458
+#define AFE_GAIN3_CON1_L 0x45c
+#define AFE_GAIN3_CON2 0x460
+#define AFE_GAIN3_CON3 0x464
+#define AFE_GAIN3_CUR_R 0x468
+#define AFE_GAIN3_CUR_L 0x46c
+#define AFE_STF_CON0 0xb80
+#define AFE_STF_CON1 0xb84
+#define AFE_STF_COEFF 0xb88
+#define AFE_STF_GAIN 0xb8c
+#define AFE_STF_MON 0xb90
+#define AFE_STF_IP_VERSION 0xb94
+#define AFE_CM0_CON0 0xba0
+#define AFE_CM0_MON 0xba4
+#define AFE_CM0_IP_VERSION 0xba8
+#define AFE_CM1_CON0 0xbb0
+#define AFE_CM1_MON 0xbb4
+#define AFE_CM1_IP_VERSION 0xbb8
+#define AFE_CM2_CON0 0xbc0
+#define AFE_CM2_MON 0xbc4
+#define AFE_CM2_IP_VERSION 0xbc8
+#define AFE_ADDA_UL0_SRC_CON0 0xbd0
+#define AFE_ADDA_UL0_SRC_CON1 0xbd4
+#define AFE_ADDA_UL0_SRC_CON2 0xbd8
+#define AFE_ADDA_UL0_SRC_DEBUG 0xbdc
+#define AFE_ADDA_UL0_SRC_DEBUG_MON0 0xbe0
+#define AFE_ADDA_UL0_SRC_MON0 0xbe4
+#define AFE_ADDA_UL0_SRC_MON1 0xbe8
+#define AFE_ADDA_UL0_IIR_COEF_02_01 0xbec
+#define AFE_ADDA_UL0_IIR_COEF_04_03 0xbf0
+#define AFE_ADDA_UL0_IIR_COEF_06_05 0xbf4
+#define AFE_ADDA_UL0_IIR_COEF_08_07 0xbf8
+#define AFE_ADDA_UL0_IIR_COEF_10_09 0xbfc
+#define AFE_ADDA_UL0_ULCF_CFG_02_01 0xc00
+#define AFE_ADDA_UL0_ULCF_CFG_04_03 0xc04
+#define AFE_ADDA_UL0_ULCF_CFG_06_05 0xc08
+#define AFE_ADDA_UL0_ULCF_CFG_08_07 0xc0c
+#define AFE_ADDA_UL0_ULCF_CFG_10_09 0xc10
+#define AFE_ADDA_UL0_ULCF_CFG_12_11 0xc14
+#define AFE_ADDA_UL0_ULCF_CFG_14_13 0xc18
+#define AFE_ADDA_UL0_ULCF_CFG_16_15 0xc1c
+#define AFE_ADDA_UL0_ULCF_CFG_18_17 0xc20
+#define AFE_ADDA_UL0_ULCF_CFG_20_19 0xc24
+#define AFE_ADDA_UL0_ULCF_CFG_22_21 0xc28
+#define AFE_ADDA_UL0_ULCF_CFG_24_23 0xc2c
+#define AFE_ADDA_UL0_ULCF_CFG_26_25 0xc30
+#define AFE_ADDA_UL0_ULCF_CFG_28_27 0xc34
+#define AFE_ADDA_UL0_ULCF_CFG_30_29 0xc38
+#define AFE_ADDA_UL0_ULCF_CFG_32_31 0xc3c
+#define AFE_ADDA_UL0_IP_VERSION 0xc4c
+#define AFE_ADDA_UL1_SRC_CON0 0xc50
+#define AFE_ADDA_UL1_SRC_CON1 0xc54
+#define AFE_ADDA_UL1_SRC_CON2 0xc58
+#define AFE_ADDA_UL1_SRC_DEBUG 0xc5c
+#define AFE_ADDA_UL1_SRC_DEBUG_MON0 0xc60
+#define AFE_ADDA_UL1_SRC_MON0 0xc64
+#define AFE_ADDA_UL1_SRC_MON1 0xc68
+#define AFE_ADDA_UL1_IIR_COEF_02_01 0xc6c
+#define AFE_ADDA_UL1_IIR_COEF_04_03 0xc70
+#define AFE_ADDA_UL1_IIR_COEF_06_05 0xc74
+#define AFE_ADDA_UL1_IIR_COEF_08_07 0xc78
+#define AFE_ADDA_UL1_IIR_COEF_10_09 0xc7c
+#define AFE_ADDA_UL1_ULCF_CFG_02_01 0xc80
+#define AFE_ADDA_UL1_ULCF_CFG_04_03 0xc84
+#define AFE_ADDA_UL1_ULCF_CFG_06_05 0xc88
+#define AFE_ADDA_UL1_ULCF_CFG_08_07 0xc8c
+#define AFE_ADDA_UL1_ULCF_CFG_10_09 0xc90
+#define AFE_ADDA_UL1_ULCF_CFG_12_11 0xc94
+#define AFE_ADDA_UL1_ULCF_CFG_14_13 0xc98
+#define AFE_ADDA_UL1_ULCF_CFG_16_15 0xc9c
+#define AFE_ADDA_UL1_ULCF_CFG_18_17 0xca0
+#define AFE_ADDA_UL1_ULCF_CFG_20_19 0xca4
+#define AFE_ADDA_UL1_ULCF_CFG_22_21 0xca8
+#define AFE_ADDA_UL1_ULCF_CFG_24_23 0xcac
+#define AFE_ADDA_UL1_ULCF_CFG_26_25 0xcb0
+#define AFE_ADDA_UL1_ULCF_CFG_28_27 0xcb4
+#define AFE_ADDA_UL1_ULCF_CFG_30_29 0xcb8
+#define AFE_ADDA_UL1_ULCF_CFG_32_31 0xcbc
+#define AFE_ADDA_UL1_IP_VERSION 0xccc
+#define AFE_ADDA_UL2_SRC_CON0 0xcd0
+#define AFE_ADDA_UL2_SRC_CON1 0xcd4
+#define AFE_ADDA_UL2_SRC_CON2 0xcd8
+#define AFE_ADDA_UL2_SRC_DEBUG 0xcdc
+#define AFE_ADDA_UL2_SRC_DEBUG_MON0 0xce0
+#define AFE_ADDA_UL2_SRC_MON0 0xce4
+#define AFE_ADDA_UL2_SRC_MON1 0xce8
+#define AFE_ADDA_UL2_IIR_COEF_02_01 0xcec
+#define AFE_ADDA_UL2_IIR_COEF_04_03 0xcf0
+#define AFE_ADDA_UL2_IIR_COEF_06_05 0xcf4
+#define AFE_ADDA_UL2_IIR_COEF_08_07 0xcf8
+#define AFE_ADDA_UL2_IIR_COEF_10_09 0xcfc
+#define AFE_ADDA_UL2_ULCF_CFG_02_01 0xd00
+#define AFE_ADDA_UL2_ULCF_CFG_04_03 0xd04
+#define AFE_ADDA_UL2_ULCF_CFG_06_05 0xd08
+#define AFE_ADDA_UL2_ULCF_CFG_08_07 0xd0c
+#define AFE_ADDA_UL2_ULCF_CFG_10_09 0xd10
+#define AFE_ADDA_UL2_ULCF_CFG_12_11 0xd14
+#define AFE_ADDA_UL2_ULCF_CFG_14_13 0xd18
+#define AFE_ADDA_UL2_ULCF_CFG_16_15 0xd1c
+#define AFE_ADDA_UL2_ULCF_CFG_18_17 0xd20
+#define AFE_ADDA_UL2_ULCF_CFG_20_19 0xd24
+#define AFE_ADDA_UL2_ULCF_CFG_22_21 0xd28
+#define AFE_ADDA_UL2_ULCF_CFG_24_23 0xd2c
+#define AFE_ADDA_UL2_ULCF_CFG_26_25 0xd30
+#define AFE_ADDA_UL2_ULCF_CFG_28_27 0xd34
+#define AFE_ADDA_UL2_ULCF_CFG_30_29 0xd38
+#define AFE_ADDA_UL2_ULCF_CFG_32_31 0xd3c
+#define AFE_ADDA_UL2_IP_VERSION 0xd4c
+#define AFE_ADDA_PROXIMITY_CON0 0xed0
+#define AFE_ADDA_ULSRC_PHASE_CON0 0xf00
+#define AFE_ADDA_ULSRC_PHASE_CON1 0xf04
+#define AFE_ADDA_ULSRC_PHASE_CON2 0xf08
+#define AFE_ADDA_ULSRC_PHASE_CON3 0xf0c
+#define AFE_MTKAIF_IPM_VER_MON 0x1180
+#define AFE_MTKAIF_MON_SEL 0x1184
+#define AFE_MTKAIF_MON 0x1188
+#define AFE_MTKAIF0_CFG0 0x1190
+#define AFE_MTKAIF0_TX_CFG0 0x1194
+#define AFE_MTKAIF0_RX_CFG0 0x1198
+#define AFE_MTKAIF0_RX_CFG1 0x119c
+#define AFE_MTKAIF0_RX_CFG2 0x11a0
+#define AFE_MTKAIF1_CFG0 0x11f0
+#define AFE_MTKAIF1_TX_CFG0 0x11f4
+#define AFE_MTKAIF1_RX_CFG0 0x11f8
+#define AFE_MTKAIF1_RX_CFG1 0x11fc
+#define AFE_MTKAIF1_RX_CFG2 0x1200
+#define AFE_AUD_PAD_TOP_CFG0 0x1204
+#define AFE_AUD_PAD_TOP_MON 0x1208
+#define AFE_ADDA_MTKAIFV4_TX_CFG0 0x1280
+#define AFE_ADDA6_MTKAIFV4_TX_CFG0 0x1284
+#define AFE_ADDA_MTKAIFV4_RX_CFG0 0x1288
+#define AFE_ADDA_MTKAIFV4_RX_CFG1 0x128c
+#define AFE_ADDA6_MTKAIFV4_RX_CFG0 0x1290
+#define AFE_ADDA6_MTKAIFV4_RX_CFG1 0x1294
+#define AFE_ADDA_MTKAIFV4_TX_SYNCWORD_CFG 0x1298
+#define AFE_ADDA_MTKAIFV4_RX_SYNCWORD_CFG 0x129c
+#define AFE_ADDA_MTKAIFV4_MON0 0x12a0
+#define AFE_ADDA_MTKAIFV4_MON1 0x12a4
+#define AFE_ADDA6_MTKAIFV4_MON0 0x12a8
+#define ETDM_IN0_CON0 0x1300
+#define ETDM_IN0_CON1 0x1304
+#define ETDM_IN0_CON2 0x1308
+#define ETDM_IN0_CON3 0x130c
+#define ETDM_IN0_CON4 0x1310
+#define ETDM_IN0_CON5 0x1314
+#define ETDM_IN0_CON6 0x1318
+#define ETDM_IN0_CON7 0x131c
+#define ETDM_IN0_CON8 0x1320
+#define ETDM_IN0_CON9 0x1324
+#define ETDM_IN0_MON 0x1328
+#define ETDM_IN1_CON0 0x1330
+#define ETDM_IN1_CON1 0x1334
+#define ETDM_IN1_CON2 0x1338
+#define ETDM_IN1_CON3 0x133c
+#define ETDM_IN1_CON4 0x1340
+#define ETDM_IN1_CON5 0x1344
+#define ETDM_IN1_CON6 0x1348
+#define ETDM_IN1_CON7 0x134c
+#define ETDM_IN1_CON8 0x1350
+#define ETDM_IN1_CON9 0x1354
+#define ETDM_IN1_MON 0x1358
+#define ETDM_IN2_CON0 0x1360
+#define ETDM_IN2_CON1 0x1364
+#define ETDM_IN2_CON2 0x1368
+#define ETDM_IN2_CON3 0x136c
+#define ETDM_IN2_CON4 0x1370
+#define ETDM_IN2_CON5 0x1374
+#define ETDM_IN2_CON6 0x1378
+#define ETDM_IN2_CON7 0x137c
+#define ETDM_IN2_CON8 0x1380
+#define ETDM_IN2_CON9 0x1384
+#define ETDM_IN2_MON 0x1388
+#define ETDM_IN3_CON0 0x1390
+#define ETDM_IN3_CON1 0x1394
+#define ETDM_IN3_CON2 0x1398
+#define ETDM_IN3_CON3 0x139c
+#define ETDM_IN3_CON4 0x13a0
+#define ETDM_IN3_CON5 0x13a4
+#define ETDM_IN3_CON6 0x13a8
+#define ETDM_IN3_CON7 0x13ac
+#define ETDM_IN3_CON8 0x13b0
+#define ETDM_IN3_CON9 0x13b4
+#define ETDM_IN3_MON 0x13b8
+#define ETDM_IN4_CON0 0x13c0
+#define ETDM_IN4_CON1 0x13c4
+#define ETDM_IN4_CON2 0x13c8
+#define ETDM_IN4_CON3 0x13cc
+#define ETDM_IN4_CON4 0x13d0
+#define ETDM_IN4_CON5 0x13d4
+#define ETDM_IN4_CON6 0x13d8
+#define ETDM_IN4_CON7 0x13dc
+#define ETDM_IN4_CON8 0x13e0
+#define ETDM_IN4_CON9 0x13e4
+#define ETDM_IN4_MON 0x13e8
+#define ETDM_IN5_CON0 0x13f0
+#define ETDM_IN5_CON1 0x13f4
+#define ETDM_IN5_CON2 0x13f8
+#define ETDM_IN5_CON3 0x13fc
+#define ETDM_IN5_CON4 0x1400
+#define ETDM_IN5_CON5 0x1404
+#define ETDM_IN5_CON6 0x1408
+#define ETDM_IN5_CON7 0x140c
+#define ETDM_IN5_CON8 0x1410
+#define ETDM_IN5_CON9 0x1414
+#define ETDM_IN5_MON 0x1418
+#define ETDM_IN6_CON0 0x1420
+#define ETDM_IN6_CON1 0x1424
+#define ETDM_IN6_CON2 0x1428
+#define ETDM_IN6_CON3 0x142c
+#define ETDM_IN6_CON4 0x1430
+#define ETDM_IN6_CON5 0x1434
+#define ETDM_IN6_CON6 0x1438
+#define ETDM_IN6_CON7 0x143c
+#define ETDM_IN6_CON8 0x1440
+#define ETDM_IN6_CON9 0x1444
+#define ETDM_IN6_MON 0x1448
+#define ETDM_OUT0_CON0 0x1480
+#define ETDM_OUT0_CON1 0x1484
+#define ETDM_OUT0_CON2 0x1488
+#define ETDM_OUT0_CON3 0x148c
+#define ETDM_OUT0_CON4 0x1490
+#define ETDM_OUT0_CON5 0x1494
+#define ETDM_OUT0_CON6 0x1498
+#define ETDM_OUT0_CON7 0x149c
+#define ETDM_OUT0_CON8 0x14a0
+#define ETDM_OUT0_CON9 0x14a4
+#define ETDM_OUT0_MON 0x14a8
+#define ETDM_OUT1_CON0 0x14c0
+#define ETDM_OUT1_CON1 0x14c4
+#define ETDM_OUT1_CON2 0x14c8
+#define ETDM_OUT1_CON3 0x14cc
+#define ETDM_OUT1_CON4 0x14d0
+#define ETDM_OUT1_CON5 0x14d4
+#define ETDM_OUT1_CON6 0x14d8
+#define ETDM_OUT1_CON7 0x14dc
+#define ETDM_OUT1_CON8 0x14e0
+#define ETDM_OUT1_CON9 0x14e4
+#define ETDM_OUT1_MON 0x14e8
+#define ETDM_OUT2_CON0 0x1500
+#define ETDM_OUT2_CON1 0x1504
+#define ETDM_OUT2_CON2 0x1508
+#define ETDM_OUT2_CON3 0x150c
+#define ETDM_OUT2_CON4 0x1510
+#define ETDM_OUT2_CON5 0x1514
+#define ETDM_OUT2_CON6 0x1518
+#define ETDM_OUT2_CON7 0x151c
+#define ETDM_OUT2_CON8 0x1520
+#define ETDM_OUT2_CON9 0x1524
+#define ETDM_OUT2_MON 0x1528
+#define ETDM_OUT3_CON0 0x1540
+#define ETDM_OUT3_CON1 0x1544
+#define ETDM_OUT3_CON2 0x1548
+#define ETDM_OUT3_CON3 0x154c
+#define ETDM_OUT3_CON4 0x1550
+#define ETDM_OUT3_CON5 0x1554
+#define ETDM_OUT3_CON6 0x1558
+#define ETDM_OUT3_CON7 0x155c
+#define ETDM_OUT3_CON8 0x1560
+#define ETDM_OUT3_CON9 0x1564
+#define ETDM_OUT3_MON 0x1568
+#define ETDM_OUT4_CON0 0x1580
+#define ETDM_OUT4_CON1 0x1584
+#define ETDM_OUT4_CON2 0x1588
+#define ETDM_OUT4_CON3 0x158c
+#define ETDM_OUT4_CON4 0x1590
+#define ETDM_OUT4_CON5 0x1594
+#define ETDM_OUT4_CON6 0x1598
+#define ETDM_OUT4_CON7 0x159c
+#define ETDM_OUT4_CON8 0x15a0
+#define ETDM_OUT4_CON9 0x15a4
+#define ETDM_OUT4_MON 0x15a8
+#define ETDM_OUT5_CON0 0x15c0
+#define ETDM_OUT5_CON1 0x15c4
+#define ETDM_OUT5_CON2 0x15c8
+#define ETDM_OUT5_CON3 0x15cc
+#define ETDM_OUT5_CON4 0x15d0
+#define ETDM_OUT5_CON5 0x15d4
+#define ETDM_OUT5_CON6 0x15d8
+#define ETDM_OUT5_CON7 0x15dc
+#define ETDM_OUT5_CON8 0x15e0
+#define ETDM_OUT5_CON9 0x15e4
+#define ETDM_OUT5_MON 0x15e8
+#define ETDM_OUT6_CON0 0x1600
+#define ETDM_OUT6_CON1 0x1604
+#define ETDM_OUT6_CON2 0x1608
+#define ETDM_OUT6_CON3 0x160c
+#define ETDM_OUT6_CON4 0x1610
+#define ETDM_OUT6_CON5 0x1614
+#define ETDM_OUT6_CON6 0x1618
+#define ETDM_OUT6_CON7 0x161c
+#define ETDM_OUT6_CON8 0x1620
+#define ETDM_OUT6_CON9 0x1624
+#define ETDM_OUT6_MON 0x1628
+#define ETDM_0_3_COWORK_CON0 0x1680
+#define ETDM_0_3_COWORK_CON1 0x1684
+#define ETDM_0_3_COWORK_CON2 0x1688
+#define ETDM_0_3_COWORK_CON3 0x168c
+#define ETDM_4_7_COWORK_CON0 0x1690
+#define ETDM_4_7_COWORK_CON1 0x1694
+#define ETDM_4_7_COWORK_CON2 0x1698
+#define ETDM_4_7_COWORK_CON3 0x169c
+#define AFE_DPTX_CON 0x2040
+#define AFE_DPTX_MON 0x2044
+#define AFE_TDM_CON1 0x2048
+#define AFE_TDM_CON2 0x204c
+#define AFE_TDM_CON3 0x2050
+#define AFE_TDM_OUT_MON 0x2054
+#define AFE_HDMI_CONN0 0x2078
+#define AFE_TDM_TOP_IP_VERSION 0x207c
+#define AFE_CONN004_0 0x2100
+#define AFE_CONN004_1 0x2104
+#define AFE_CONN004_2 0x2108
+#define AFE_CONN004_4 0x2110
+#define AFE_CONN004_5 0x2114
+#define AFE_CONN004_6 0x2118
+#define AFE_CONN004_7 0x211c
+#define AFE_CONN005_0 0x2120
+#define AFE_CONN005_1 0x2124
+#define AFE_CONN005_2 0x2128
+#define AFE_CONN005_4 0x2130
+#define AFE_CONN005_5 0x2134
+#define AFE_CONN005_6 0x2138
+#define AFE_CONN005_7 0x213c
+#define AFE_CONN006_0 0x2140
+#define AFE_CONN006_1 0x2144
+#define AFE_CONN006_2 0x2148
+#define AFE_CONN006_4 0x2150
+#define AFE_CONN006_5 0x2154
+#define AFE_CONN006_6 0x2158
+#define AFE_CONN006_7 0x215c
+#define AFE_CONN007_0 0x2160
+#define AFE_CONN007_1 0x2164
+#define AFE_CONN007_2 0x2168
+#define AFE_CONN007_4 0x2170
+#define AFE_CONN007_5 0x2174
+#define AFE_CONN007_6 0x2178
+#define AFE_CONN007_7 0x217c
+#define AFE_CONN008_0 0x2180
+#define AFE_CONN008_1 0x2184
+#define AFE_CONN008_2 0x2188
+#define AFE_CONN008_4 0x2190
+#define AFE_CONN008_5 0x2194
+#define AFE_CONN008_6 0x2198
+#define AFE_CONN008_7 0x219c
+#define AFE_CONN009_0 0x21a0
+#define AFE_CONN009_1 0x21a4
+#define AFE_CONN009_2 0x21a8
+#define AFE_CONN009_4 0x21b0
+#define AFE_CONN009_5 0x21b4
+#define AFE_CONN009_6 0x21b8
+#define AFE_CONN009_7 0x21bc
+#define AFE_CONN010_0 0x21c0
+#define AFE_CONN010_1 0x21c4
+#define AFE_CONN010_2 0x21c8
+#define AFE_CONN010_4 0x21d0
+#define AFE_CONN010_5 0x21d4
+#define AFE_CONN010_6 0x21d8
+#define AFE_CONN010_7 0x21dc
+#define AFE_CONN011_0 0x21e0
+#define AFE_CONN011_1 0x21e4
+#define AFE_CONN011_2 0x21e8
+#define AFE_CONN011_4 0x21f0
+#define AFE_CONN011_5 0x21f4
+#define AFE_CONN011_6 0x21f8
+#define AFE_CONN011_7 0x21fc
+#define AFE_CONN012_0 0x2200
+#define AFE_CONN012_1 0x2204
+#define AFE_CONN012_2 0x2208
+#define AFE_CONN012_4 0x2210
+#define AFE_CONN012_5 0x2214
+#define AFE_CONN012_6 0x2218
+#define AFE_CONN012_7 0x221c
+#define AFE_CONN014_0 0x2240
+#define AFE_CONN014_1 0x2244
+#define AFE_CONN014_2 0x2248
+#define AFE_CONN014_4 0x2250
+#define AFE_CONN014_5 0x2254
+#define AFE_CONN014_6 0x2258
+#define AFE_CONN014_7 0x225c
+#define AFE_CONN015_0 0x2260
+#define AFE_CONN015_1 0x2264
+#define AFE_CONN015_2 0x2268
+#define AFE_CONN015_4 0x2270
+#define AFE_CONN015_5 0x2274
+#define AFE_CONN015_6 0x2278
+#define AFE_CONN015_7 0x227c
+#define AFE_CONN016_0 0x2280
+#define AFE_CONN016_1 0x2284
+#define AFE_CONN016_2 0x2288
+#define AFE_CONN016_4 0x2290
+#define AFE_CONN016_5 0x2294
+#define AFE_CONN016_6 0x2298
+#define AFE_CONN016_7 0x229c
+#define AFE_CONN017_0 0x22a0
+#define AFE_CONN017_1 0x22a4
+#define AFE_CONN017_2 0x22a8
+#define AFE_CONN017_4 0x22b0
+#define AFE_CONN017_5 0x22b4
+#define AFE_CONN017_6 0x22b8
+#define AFE_CONN017_7 0x22bc
+#define AFE_CONN018_0 0x22c0
+#define AFE_CONN018_1 0x22c4
+#define AFE_CONN018_2 0x22c8
+#define AFE_CONN018_4 0x22d0
+#define AFE_CONN018_5 0x22d4
+#define AFE_CONN018_6 0x22d8
+#define AFE_CONN018_7 0x22dc
+#define AFE_CONN019_0 0x22e0
+#define AFE_CONN019_1 0x22e4
+#define AFE_CONN019_2 0x22e8
+#define AFE_CONN019_4 0x22f0
+#define AFE_CONN019_5 0x22f4
+#define AFE_CONN019_6 0x22f8
+#define AFE_CONN019_7 0x22fc
+#define AFE_CONN020_0 0x2300
+#define AFE_CONN020_1 0x2304
+#define AFE_CONN020_2 0x2308
+#define AFE_CONN020_4 0x2310
+#define AFE_CONN020_5 0x2314
+#define AFE_CONN020_6 0x2318
+#define AFE_CONN020_7 0x231c
+#define AFE_CONN021_0 0x2320
+#define AFE_CONN021_1 0x2324
+#define AFE_CONN021_2 0x2328
+#define AFE_CONN021_4 0x2330
+#define AFE_CONN021_5 0x2334
+#define AFE_CONN021_6 0x2338
+#define AFE_CONN021_7 0x233c
+#define AFE_CONN022_0 0x2340
+#define AFE_CONN022_1 0x2344
+#define AFE_CONN022_2 0x2348
+#define AFE_CONN022_4 0x2350
+#define AFE_CONN022_5 0x2354
+#define AFE_CONN022_6 0x2358
+#define AFE_CONN022_7 0x235c
+#define AFE_CONN023_0 0x2360
+#define AFE_CONN023_1 0x2364
+#define AFE_CONN023_2 0x2368
+#define AFE_CONN023_4 0x2370
+#define AFE_CONN023_5 0x2374
+#define AFE_CONN023_6 0x2378
+#define AFE_CONN023_7 0x237c
+#define AFE_CONN024_0 0x2380
+#define AFE_CONN024_1 0x2384
+#define AFE_CONN024_2 0x2388
+#define AFE_CONN024_4 0x2390
+#define AFE_CONN024_5 0x2394
+#define AFE_CONN024_6 0x2398
+#define AFE_CONN024_7 0x239c
+#define AFE_CONN025_0 0x23a0
+#define AFE_CONN025_1 0x23a4
+#define AFE_CONN025_2 0x23a8
+#define AFE_CONN025_4 0x23b0
+#define AFE_CONN025_5 0x23b4
+#define AFE_CONN025_6 0x23b8
+#define AFE_CONN025_7 0x23bc
+#define AFE_CONN026_0 0x23c0
+#define AFE_CONN026_1 0x23c4
+#define AFE_CONN026_2 0x23c8
+#define AFE_CONN026_4 0x23d0
+#define AFE_CONN026_5 0x23d4
+#define AFE_CONN026_6 0x23d8
+#define AFE_CONN026_7 0x23dc
+#define AFE_CONN027_0 0x23e0
+#define AFE_CONN027_1 0x23e4
+#define AFE_CONN027_2 0x23e8
+#define AFE_CONN027_4 0x23f0
+#define AFE_CONN027_5 0x23f4
+#define AFE_CONN027_6 0x23f8
+#define AFE_CONN027_7 0x23fc
+#define AFE_CONN028_0 0x2400
+#define AFE_CONN028_1 0x2404
+#define AFE_CONN028_2 0x2408
+#define AFE_CONN028_4 0x2410
+#define AFE_CONN028_5 0x2414
+#define AFE_CONN028_6 0x2418
+#define AFE_CONN028_7 0x241c
+#define AFE_CONN029_0 0x2420
+#define AFE_CONN029_1 0x2424
+#define AFE_CONN029_2 0x2428
+#define AFE_CONN029_4 0x2430
+#define AFE_CONN029_5 0x2434
+#define AFE_CONN029_6 0x2438
+#define AFE_CONN029_7 0x243c
+#define AFE_CONN030_0 0x2440
+#define AFE_CONN030_1 0x2444
+#define AFE_CONN030_2 0x2448
+#define AFE_CONN030_4 0x2450
+#define AFE_CONN030_5 0x2454
+#define AFE_CONN030_6 0x2458
+#define AFE_CONN030_7 0x245c
+#define AFE_CONN031_0 0x2460
+#define AFE_CONN031_1 0x2464
+#define AFE_CONN031_2 0x2468
+#define AFE_CONN031_4 0x2470
+#define AFE_CONN031_5 0x2474
+#define AFE_CONN031_6 0x2478
+#define AFE_CONN031_7 0x247c
+#define AFE_CONN032_0 0x2480
+#define AFE_CONN032_1 0x2484
+#define AFE_CONN032_2 0x2488
+#define AFE_CONN032_4 0x2490
+#define AFE_CONN032_5 0x2494
+#define AFE_CONN032_6 0x2498
+#define AFE_CONN032_7 0x249c
+#define AFE_CONN033_0 0x24a0
+#define AFE_CONN033_1 0x24a4
+#define AFE_CONN033_2 0x24a8
+#define AFE_CONN033_4 0x24b0
+#define AFE_CONN033_5 0x24b4
+#define AFE_CONN033_6 0x24b8
+#define AFE_CONN033_7 0x24bc
+#define AFE_CONN034_0 0x24c0
+#define AFE_CONN034_1 0x24c4
+#define AFE_CONN034_2 0x24c8
+#define AFE_CONN034_4 0x24d0
+#define AFE_CONN034_5 0x24d4
+#define AFE_CONN034_6 0x24d8
+#define AFE_CONN034_7 0x24dc
+#define AFE_CONN035_0 0x24e0
+#define AFE_CONN035_1 0x24e4
+#define AFE_CONN035_2 0x24e8
+#define AFE_CONN035_4 0x24f0
+#define AFE_CONN035_5 0x24f4
+#define AFE_CONN035_6 0x24f8
+#define AFE_CONN035_7 0x24fc
+#define AFE_CONN036_0 0x2500
+#define AFE_CONN036_1 0x2504
+#define AFE_CONN036_2 0x2508
+#define AFE_CONN036_4 0x2510
+#define AFE_CONN036_5 0x2514
+#define AFE_CONN036_6 0x2518
+#define AFE_CONN036_7 0x251c
+#define AFE_CONN037_0 0x2520
+#define AFE_CONN037_1 0x2524
+#define AFE_CONN037_2 0x2528
+#define AFE_CONN037_4 0x2530
+#define AFE_CONN037_5 0x2534
+#define AFE_CONN037_6 0x2538
+#define AFE_CONN037_7 0x253c
+#define AFE_CONN038_0 0x2540
+#define AFE_CONN038_1 0x2544
+#define AFE_CONN038_2 0x2548
+#define AFE_CONN038_4 0x2550
+#define AFE_CONN038_5 0x2554
+#define AFE_CONN038_6 0x2558
+#define AFE_CONN038_7 0x255c
+#define AFE_CONN039_0 0x2560
+#define AFE_CONN039_1 0x2564
+#define AFE_CONN039_2 0x2568
+#define AFE_CONN039_4 0x2570
+#define AFE_CONN039_5 0x2574
+#define AFE_CONN039_6 0x2578
+#define AFE_CONN039_7 0x257c
+#define AFE_CONN040_0 0x2580
+#define AFE_CONN040_1 0x2584
+#define AFE_CONN040_2 0x2588
+#define AFE_CONN040_4 0x2590
+#define AFE_CONN040_5 0x2594
+#define AFE_CONN040_6 0x2598
+#define AFE_CONN040_7 0x259c
+#define AFE_CONN041_0 0x25a0
+#define AFE_CONN041_1 0x25a4
+#define AFE_CONN041_2 0x25a8
+#define AFE_CONN041_4 0x25b0
+#define AFE_CONN041_5 0x25b4
+#define AFE_CONN041_6 0x25b8
+#define AFE_CONN041_7 0x25bc
+#define AFE_CONN042_0 0x25c0
+#define AFE_CONN042_1 0x25c4
+#define AFE_CONN042_2 0x25c8
+#define AFE_CONN042_4 0x25d0
+#define AFE_CONN042_5 0x25d4
+#define AFE_CONN042_6 0x25d8
+#define AFE_CONN042_7 0x25dc
+#define AFE_CONN043_0 0x25e0
+#define AFE_CONN043_1 0x25e4
+#define AFE_CONN043_2 0x25e8
+#define AFE_CONN043_4 0x25f0
+#define AFE_CONN043_5 0x25f4
+#define AFE_CONN043_6 0x25f8
+#define AFE_CONN043_7 0x25fc
+#define AFE_CONN044_0 0x2600
+#define AFE_CONN044_1 0x2604
+#define AFE_CONN044_2 0x2608
+#define AFE_CONN044_4 0x2610
+#define AFE_CONN044_5 0x2614
+#define AFE_CONN044_6 0x2618
+#define AFE_CONN044_7 0x261c
+#define AFE_CONN045_0 0x2620
+#define AFE_CONN045_1 0x2624
+#define AFE_CONN045_2 0x2628
+#define AFE_CONN045_4 0x2630
+#define AFE_CONN045_5 0x2634
+#define AFE_CONN045_6 0x2638
+#define AFE_CONN045_7 0x263c
+#define AFE_CONN046_0 0x2640
+#define AFE_CONN046_1 0x2644
+#define AFE_CONN046_2 0x2648
+#define AFE_CONN046_4 0x2650
+#define AFE_CONN046_5 0x2654
+#define AFE_CONN046_6 0x2658
+#define AFE_CONN046_7 0x265c
+#define AFE_CONN047_0 0x2660
+#define AFE_CONN047_1 0x2664
+#define AFE_CONN047_2 0x2668
+#define AFE_CONN047_4 0x2670
+#define AFE_CONN047_5 0x2674
+#define AFE_CONN047_6 0x2678
+#define AFE_CONN047_7 0x267c
+#define AFE_CONN048_0 0x2680
+#define AFE_CONN048_1 0x2684
+#define AFE_CONN048_2 0x2688
+#define AFE_CONN048_4 0x2690
+#define AFE_CONN048_5 0x2694
+#define AFE_CONN048_6 0x2698
+#define AFE_CONN048_7 0x269c
+#define AFE_CONN049_0 0x26a0
+#define AFE_CONN049_1 0x26a4
+#define AFE_CONN049_2 0x26a8
+#define AFE_CONN049_4 0x26b0
+#define AFE_CONN049_5 0x26b4
+#define AFE_CONN049_6 0x26b8
+#define AFE_CONN049_7 0x26bc
+#define AFE_CONN050_0 0x26c0
+#define AFE_CONN050_1 0x26c4
+#define AFE_CONN050_2 0x26c8
+#define AFE_CONN050_4 0x26d0
+#define AFE_CONN050_5 0x26d4
+#define AFE_CONN050_6 0x26d8
+#define AFE_CONN050_7 0x26dc
+#define AFE_CONN051_0 0x26e0
+#define AFE_CONN051_1 0x26e4
+#define AFE_CONN051_2 0x26e8
+#define AFE_CONN051_4 0x26f0
+#define AFE_CONN051_5 0x26f4
+#define AFE_CONN051_6 0x26f8
+#define AFE_CONN051_7 0x26fc
+#define AFE_CONN052_0 0x2700
+#define AFE_CONN052_1 0x2704
+#define AFE_CONN052_2 0x2708
+#define AFE_CONN052_4 0x2710
+#define AFE_CONN052_5 0x2714
+#define AFE_CONN052_6 0x2718
+#define AFE_CONN052_7 0x271c
+#define AFE_CONN053_0 0x2720
+#define AFE_CONN053_1 0x2724
+#define AFE_CONN053_2 0x2728
+#define AFE_CONN053_4 0x2730
+#define AFE_CONN053_5 0x2734
+#define AFE_CONN053_6 0x2738
+#define AFE_CONN053_7 0x273c
+#define AFE_CONN054_0 0x2740
+#define AFE_CONN054_1 0x2744
+#define AFE_CONN054_2 0x2748
+#define AFE_CONN054_4 0x2750
+#define AFE_CONN054_5 0x2754
+#define AFE_CONN054_6 0x2758
+#define AFE_CONN054_7 0x275c
+#define AFE_CONN055_0 0x2760
+#define AFE_CONN055_1 0x2764
+#define AFE_CONN055_2 0x2768
+#define AFE_CONN055_4 0x2770
+#define AFE_CONN055_5 0x2774
+#define AFE_CONN055_6 0x2778
+#define AFE_CONN055_7 0x277c
+#define AFE_CONN056_0 0x2780
+#define AFE_CONN056_1 0x2784
+#define AFE_CONN056_2 0x2788
+#define AFE_CONN056_4 0x2790
+#define AFE_CONN056_5 0x2794
+#define AFE_CONN056_6 0x2798
+#define AFE_CONN056_7 0x279c
+#define AFE_CONN057_0 0x27a0
+#define AFE_CONN057_1 0x27a4
+#define AFE_CONN057_2 0x27a8
+#define AFE_CONN057_4 0x27b0
+#define AFE_CONN057_5 0x27b4
+#define AFE_CONN057_6 0x27b8
+#define AFE_CONN057_7 0x27bc
+#define AFE_CONN058_0 0x27c0
+#define AFE_CONN058_1 0x27c4
+#define AFE_CONN058_2 0x27c8
+#define AFE_CONN058_4 0x27d0
+#define AFE_CONN058_5 0x27d4
+#define AFE_CONN058_6 0x27d8
+#define AFE_CONN058_7 0x27dc
+#define AFE_CONN059_0 0x27e0
+#define AFE_CONN059_1 0x27e4
+#define AFE_CONN059_2 0x27e8
+#define AFE_CONN059_4 0x27f0
+#define AFE_CONN059_5 0x27f4
+#define AFE_CONN059_6 0x27f8
+#define AFE_CONN059_7 0x27fc
+#define AFE_CONN060_0 0x2800
+#define AFE_CONN060_1 0x2804
+#define AFE_CONN060_2 0x2808
+#define AFE_CONN060_4 0x2810
+#define AFE_CONN060_5 0x2814
+#define AFE_CONN060_6 0x2818
+#define AFE_CONN060_7 0x281c
+#define AFE_CONN061_0 0x2820
+#define AFE_CONN061_1 0x2824
+#define AFE_CONN061_2 0x2828
+#define AFE_CONN061_4 0x2830
+#define AFE_CONN061_5 0x2834
+#define AFE_CONN061_6 0x2838
+#define AFE_CONN061_7 0x283c
+#define AFE_CONN062_0 0x2840
+#define AFE_CONN062_1 0x2844
+#define AFE_CONN062_2 0x2848
+#define AFE_CONN062_4 0x2850
+#define AFE_CONN062_5 0x2854
+#define AFE_CONN062_6 0x2858
+#define AFE_CONN062_7 0x285c
+#define AFE_CONN063_0 0x2860
+#define AFE_CONN063_1 0x2864
+#define AFE_CONN063_2 0x2868
+#define AFE_CONN063_4 0x2870
+#define AFE_CONN063_5 0x2874
+#define AFE_CONN063_6 0x2878
+#define AFE_CONN063_7 0x287c
+#define AFE_CONN064_0 0x2880
+#define AFE_CONN064_1 0x2884
+#define AFE_CONN064_2 0x2888
+#define AFE_CONN064_4 0x2890
+#define AFE_CONN064_5 0x2894
+#define AFE_CONN064_6 0x2898
+#define AFE_CONN064_7 0x289c
+#define AFE_CONN065_0 0x28a0
+#define AFE_CONN065_1 0x28a4
+#define AFE_CONN065_2 0x28a8
+#define AFE_CONN065_4 0x28b0
+#define AFE_CONN065_5 0x28b4
+#define AFE_CONN065_6 0x28b8
+#define AFE_CONN065_7 0x28bc
+#define AFE_CONN066_0 0x28c0
+#define AFE_CONN066_1 0x28c4
+#define AFE_CONN066_2 0x28c8
+#define AFE_CONN066_4 0x28d0
+#define AFE_CONN066_5 0x28d4
+#define AFE_CONN066_6 0x28d8
+#define AFE_CONN066_7 0x28dc
+#define AFE_CONN067_0 0x28e0
+#define AFE_CONN067_1 0x28e4
+#define AFE_CONN067_2 0x28e8
+#define AFE_CONN067_4 0x28f0
+#define AFE_CONN067_5 0x28f4
+#define AFE_CONN067_6 0x28f8
+#define AFE_CONN067_7 0x28fc
+#define AFE_CONN068_0 0x2900
+#define AFE_CONN068_1 0x2904
+#define AFE_CONN068_2 0x2908
+#define AFE_CONN068_4 0x2910
+#define AFE_CONN068_5 0x2914
+#define AFE_CONN068_6 0x2918
+#define AFE_CONN068_7 0x291c
+#define AFE_CONN069_0 0x2920
+#define AFE_CONN069_1 0x2924
+#define AFE_CONN069_2 0x2928
+#define AFE_CONN069_4 0x2930
+#define AFE_CONN069_5 0x2934
+#define AFE_CONN069_6 0x2938
+#define AFE_CONN069_7 0x293c
+#define AFE_CONN070_0 0x2940
+#define AFE_CONN070_1 0x2944
+#define AFE_CONN070_2 0x2948
+#define AFE_CONN070_4 0x2950
+#define AFE_CONN070_5 0x2954
+#define AFE_CONN070_6 0x2958
+#define AFE_CONN070_7 0x295c
+#define AFE_CONN071_0 0x2960
+#define AFE_CONN071_1 0x2964
+#define AFE_CONN071_2 0x2968
+#define AFE_CONN071_4 0x2970
+#define AFE_CONN071_5 0x2974
+#define AFE_CONN071_6 0x2978
+#define AFE_CONN071_7 0x297c
+#define AFE_CONN072_0 0x2980
+#define AFE_CONN072_1 0x2984
+#define AFE_CONN072_2 0x2988
+#define AFE_CONN072_4 0x2990
+#define AFE_CONN072_5 0x2994
+#define AFE_CONN072_6 0x2998
+#define AFE_CONN072_7 0x299c
+#define AFE_CONN073_0 0x29a0
+#define AFE_CONN073_1 0x29a4
+#define AFE_CONN073_2 0x29a8
+#define AFE_CONN073_4 0x29b0
+#define AFE_CONN073_5 0x29b4
+#define AFE_CONN073_6 0x29b8
+#define AFE_CONN073_7 0x29bc
+#define AFE_CONN074_0 0x29c0
+#define AFE_CONN074_1 0x29c4
+#define AFE_CONN074_2 0x29c8
+#define AFE_CONN074_4 0x29d0
+#define AFE_CONN074_5 0x29d4
+#define AFE_CONN074_6 0x29d8
+#define AFE_CONN074_7 0x29dc
+#define AFE_CONN075_0 0x29e0
+#define AFE_CONN075_1 0x29e4
+#define AFE_CONN075_2 0x29e8
+#define AFE_CONN075_4 0x29f0
+#define AFE_CONN075_5 0x29f4
+#define AFE_CONN075_6 0x29f8
+#define AFE_CONN075_7 0x29fc
+#define AFE_CONN076_0 0x2a00
+#define AFE_CONN076_1 0x2a04
+#define AFE_CONN076_2 0x2a08
+#define AFE_CONN076_4 0x2a10
+#define AFE_CONN076_5 0x2a14
+#define AFE_CONN076_6 0x2a18
+#define AFE_CONN076_7 0x2a1c
+#define AFE_CONN077_0 0x2a20
+#define AFE_CONN077_1 0x2a24
+#define AFE_CONN077_2 0x2a28
+#define AFE_CONN077_4 0x2a30
+#define AFE_CONN077_5 0x2a34
+#define AFE_CONN077_6 0x2a38
+#define AFE_CONN077_7 0x2a3c
+#define AFE_CONN078_0 0x2a40
+#define AFE_CONN078_1 0x2a44
+#define AFE_CONN078_2 0x2a48
+#define AFE_CONN078_4 0x2a50
+#define AFE_CONN078_5 0x2a54
+#define AFE_CONN078_6 0x2a58
+#define AFE_CONN078_7 0x2a5c
+#define AFE_CONN079_0 0x2a60
+#define AFE_CONN079_1 0x2a64
+#define AFE_CONN079_2 0x2a68
+#define AFE_CONN079_4 0x2a70
+#define AFE_CONN079_5 0x2a74
+#define AFE_CONN079_6 0x2a78
+#define AFE_CONN079_7 0x2a7c
+#define AFE_CONN080_0 0x2a80
+#define AFE_CONN080_1 0x2a84
+#define AFE_CONN080_2 0x2a88
+#define AFE_CONN080_4 0x2a90
+#define AFE_CONN080_5 0x2a94
+#define AFE_CONN080_6 0x2a98
+#define AFE_CONN080_7 0x2a9c
+#define AFE_CONN081_0 0x2aa0
+#define AFE_CONN081_1 0x2aa4
+#define AFE_CONN081_2 0x2aa8
+#define AFE_CONN081_4 0x2ab0
+#define AFE_CONN081_5 0x2ab4
+#define AFE_CONN081_6 0x2ab8
+#define AFE_CONN081_7 0x2abc
+#define AFE_CONN082_0 0x2ac0
+#define AFE_CONN082_1 0x2ac4
+#define AFE_CONN082_2 0x2ac8
+#define AFE_CONN082_4 0x2ad0
+#define AFE_CONN082_5 0x2ad4
+#define AFE_CONN082_6 0x2ad8
+#define AFE_CONN082_7 0x2adc
+#define AFE_CONN083_0 0x2ae0
+#define AFE_CONN083_1 0x2ae4
+#define AFE_CONN083_2 0x2ae8
+#define AFE_CONN083_4 0x2af0
+#define AFE_CONN083_5 0x2af4
+#define AFE_CONN083_6 0x2af8
+#define AFE_CONN083_7 0x2afc
+#define AFE_CONN084_0 0x2b00
+#define AFE_CONN084_1 0x2b04
+#define AFE_CONN084_2 0x2b08
+#define AFE_CONN084_4 0x2b10
+#define AFE_CONN084_5 0x2b14
+#define AFE_CONN084_6 0x2b18
+#define AFE_CONN084_7 0x2b1c
+#define AFE_CONN085_0 0x2b20
+#define AFE_CONN085_1 0x2b24
+#define AFE_CONN085_2 0x2b28
+#define AFE_CONN085_4 0x2b30
+#define AFE_CONN085_5 0x2b34
+#define AFE_CONN085_6 0x2b38
+#define AFE_CONN085_7 0x2b3c
+#define AFE_CONN086_0 0x2b40
+#define AFE_CONN086_1 0x2b44
+#define AFE_CONN086_2 0x2b48
+#define AFE_CONN086_4 0x2b50
+#define AFE_CONN086_5 0x2b54
+#define AFE_CONN086_6 0x2b58
+#define AFE_CONN086_7 0x2b5c
+#define AFE_CONN087_0 0x2b60
+#define AFE_CONN087_1 0x2b64
+#define AFE_CONN087_2 0x2b68
+#define AFE_CONN087_4 0x2b70
+#define AFE_CONN087_5 0x2b74
+#define AFE_CONN087_6 0x2b78
+#define AFE_CONN087_7 0x2b7c
+#define AFE_CONN088_0 0x2b80
+#define AFE_CONN088_1 0x2b84
+#define AFE_CONN088_2 0x2b88
+#define AFE_CONN088_4 0x2b90
+#define AFE_CONN088_5 0x2b94
+#define AFE_CONN088_6 0x2b98
+#define AFE_CONN088_7 0x2b9c
+#define AFE_CONN089_0 0x2ba0
+#define AFE_CONN089_1 0x2ba4
+#define AFE_CONN089_2 0x2ba8
+#define AFE_CONN089_4 0x2bb0
+#define AFE_CONN089_5 0x2bb4
+#define AFE_CONN089_6 0x2bb8
+#define AFE_CONN089_7 0x2bbc
+#define AFE_CONN090_0 0x2bc0
+#define AFE_CONN090_1 0x2bc4
+#define AFE_CONN090_2 0x2bc8
+#define AFE_CONN090_4 0x2bd0
+#define AFE_CONN090_5 0x2bd4
+#define AFE_CONN090_6 0x2bd8
+#define AFE_CONN090_7 0x2bdc
+#define AFE_CONN091_0 0x2be0
+#define AFE_CONN091_1 0x2be4
+#define AFE_CONN091_2 0x2be8
+#define AFE_CONN091_4 0x2bf0
+#define AFE_CONN091_5 0x2bf4
+#define AFE_CONN091_6 0x2bf8
+#define AFE_CONN091_7 0x2bfc
+#define AFE_CONN092_0 0x2c00
+#define AFE_CONN092_1 0x2c04
+#define AFE_CONN092_2 0x2c08
+#define AFE_CONN092_4 0x2c10
+#define AFE_CONN092_5 0x2c14
+#define AFE_CONN092_6 0x2c18
+#define AFE_CONN092_7 0x2c1c
+#define AFE_CONN093_0 0x2c20
+#define AFE_CONN093_1 0x2c24
+#define AFE_CONN093_2 0x2c28
+#define AFE_CONN093_4 0x2c30
+#define AFE_CONN093_5 0x2c34
+#define AFE_CONN093_6 0x2c38
+#define AFE_CONN093_7 0x2c3c
+#define AFE_CONN094_0 0x2c40
+#define AFE_CONN094_1 0x2c44
+#define AFE_CONN094_2 0x2c48
+#define AFE_CONN094_4 0x2c50
+#define AFE_CONN094_5 0x2c54
+#define AFE_CONN094_6 0x2c58
+#define AFE_CONN094_7 0x2c5c
+#define AFE_CONN095_0 0x2c60
+#define AFE_CONN095_1 0x2c64
+#define AFE_CONN095_2 0x2c68
+#define AFE_CONN095_4 0x2c70
+#define AFE_CONN095_5 0x2c74
+#define AFE_CONN095_6 0x2c78
+#define AFE_CONN095_7 0x2c7c
+#define AFE_CONN096_0 0x2c80
+#define AFE_CONN096_1 0x2c84
+#define AFE_CONN096_2 0x2c88
+#define AFE_CONN096_4 0x2c90
+#define AFE_CONN096_5 0x2c94
+#define AFE_CONN096_6 0x2c98
+#define AFE_CONN096_7 0x2c9c
+#define AFE_CONN097_0 0x2ca0
+#define AFE_CONN097_1 0x2ca4
+#define AFE_CONN097_2 0x2ca8
+#define AFE_CONN097_4 0x2cb0
+#define AFE_CONN097_5 0x2cb4
+#define AFE_CONN097_6 0x2cb8
+#define AFE_CONN097_7 0x2cbc
+#define AFE_CONN098_0 0x2cc0
+#define AFE_CONN098_1 0x2cc4
+#define AFE_CONN098_2 0x2cc8
+#define AFE_CONN098_4 0x2cd0
+#define AFE_CONN098_5 0x2cd4
+#define AFE_CONN098_6 0x2cd8
+#define AFE_CONN098_7 0x2cdc
+#define AFE_CONN099_0 0x2ce0
+#define AFE_CONN099_1 0x2ce4
+#define AFE_CONN099_2 0x2ce8
+#define AFE_CONN099_4 0x2cf0
+#define AFE_CONN099_5 0x2cf4
+#define AFE_CONN099_6 0x2cf8
+#define AFE_CONN099_7 0x2cfc
+#define AFE_CONN100_0 0x2d00
+#define AFE_CONN100_1 0x2d04
+#define AFE_CONN100_2 0x2d08
+#define AFE_CONN100_4 0x2d10
+#define AFE_CONN100_5 0x2d14
+#define AFE_CONN100_6 0x2d18
+#define AFE_CONN100_7 0x2d1c
+#define AFE_CONN102_0 0x2d40
+#define AFE_CONN102_1 0x2d44
+#define AFE_CONN102_2 0x2d48
+#define AFE_CONN102_4 0x2d50
+#define AFE_CONN102_5 0x2d54
+#define AFE_CONN102_6 0x2d58
+#define AFE_CONN102_7 0x2d5c
+#define AFE_CONN103_0 0x2d60
+#define AFE_CONN103_1 0x2d64
+#define AFE_CONN103_2 0x2d68
+#define AFE_CONN103_4 0x2d70
+#define AFE_CONN103_5 0x2d74
+#define AFE_CONN103_6 0x2d78
+#define AFE_CONN103_7 0x2d7c
+#define AFE_CONN104_0 0x2d80
+#define AFE_CONN104_1 0x2d84
+#define AFE_CONN104_2 0x2d88
+#define AFE_CONN104_4 0x2d90
+#define AFE_CONN104_5 0x2d94
+#define AFE_CONN104_6 0x2d98
+#define AFE_CONN104_7 0x2d9c
+#define AFE_CONN105_0 0x2da0
+#define AFE_CONN105_1 0x2da4
+#define AFE_CONN105_2 0x2da8
+#define AFE_CONN105_4 0x2db0
+#define AFE_CONN105_5 0x2db4
+#define AFE_CONN105_6 0x2db8
+#define AFE_CONN105_7 0x2dbc
+#define AFE_CONN106_0 0x2dc0
+#define AFE_CONN106_1 0x2dc4
+#define AFE_CONN106_2 0x2dc8
+#define AFE_CONN106_4 0x2dd0
+#define AFE_CONN106_5 0x2dd4
+#define AFE_CONN106_6 0x2dd8
+#define AFE_CONN106_7 0x2ddc
+#define AFE_CONN108_0 0x2e00
+#define AFE_CONN108_1 0x2e04
+#define AFE_CONN108_2 0x2e08
+#define AFE_CONN108_4 0x2e10
+#define AFE_CONN108_5 0x2e14
+#define AFE_CONN108_6 0x2e18
+#define AFE_CONN108_7 0x2e1c
+#define AFE_CONN109_0 0x2e20
+#define AFE_CONN109_1 0x2e24
+#define AFE_CONN109_2 0x2e28
+#define AFE_CONN109_4 0x2e30
+#define AFE_CONN109_5 0x2e34
+#define AFE_CONN109_6 0x2e38
+#define AFE_CONN109_7 0x2e3c
+#define AFE_CONN110_0 0x2e40
+#define AFE_CONN110_1 0x2e44
+#define AFE_CONN110_2 0x2e48
+#define AFE_CONN110_4 0x2e50
+#define AFE_CONN110_5 0x2e54
+#define AFE_CONN110_6 0x2e58
+#define AFE_CONN110_7 0x2e5c
+#define AFE_CONN111_0 0x2e60
+#define AFE_CONN111_1 0x2e64
+#define AFE_CONN111_2 0x2e68
+#define AFE_CONN111_4 0x2e70
+#define AFE_CONN111_5 0x2e74
+#define AFE_CONN111_6 0x2e78
+#define AFE_CONN111_7 0x2e7c
+#define AFE_CONN112_0 0x2e80
+#define AFE_CONN112_1 0x2e84
+#define AFE_CONN112_2 0x2e88
+#define AFE_CONN112_4 0x2e90
+#define AFE_CONN112_5 0x2e94
+#define AFE_CONN112_6 0x2e98
+#define AFE_CONN112_7 0x2e9c
+#define AFE_CONN113_0 0x2ea0
+#define AFE_CONN113_1 0x2ea4
+#define AFE_CONN113_2 0x2ea8
+#define AFE_CONN113_4 0x2eb0
+#define AFE_CONN113_5 0x2eb4
+#define AFE_CONN113_6 0x2eb8
+#define AFE_CONN113_7 0x2ebc
+#define AFE_CONN114_0 0x2ec0
+#define AFE_CONN114_1 0x2ec4
+#define AFE_CONN114_2 0x2ec8
+#define AFE_CONN114_4 0x2ed0
+#define AFE_CONN114_5 0x2ed4
+#define AFE_CONN114_6 0x2ed8
+#define AFE_CONN114_7 0x2edc
+#define AFE_CONN115_0 0x2ee0
+#define AFE_CONN115_1 0x2ee4
+#define AFE_CONN115_2 0x2ee8
+#define AFE_CONN115_4 0x2ef0
+#define AFE_CONN115_5 0x2ef4
+#define AFE_CONN115_6 0x2ef8
+#define AFE_CONN115_7 0x2efc
+#define AFE_CONN116_0 0x2f00
+#define AFE_CONN116_1 0x2f04
+#define AFE_CONN116_2 0x2f08
+#define AFE_CONN116_4 0x2f10
+#define AFE_CONN116_5 0x2f14
+#define AFE_CONN116_6 0x2f18
+#define AFE_CONN116_7 0x2f1c
+#define AFE_CONN117_0 0x2f20
+#define AFE_CONN117_1 0x2f24
+#define AFE_CONN117_2 0x2f28
+#define AFE_CONN117_4 0x2f30
+#define AFE_CONN117_5 0x2f34
+#define AFE_CONN117_6 0x2f38
+#define AFE_CONN117_7 0x2f3c
+#define AFE_CONN118_0 0x2f40
+#define AFE_CONN118_1 0x2f44
+#define AFE_CONN118_2 0x2f48
+#define AFE_CONN118_4 0x2f50
+#define AFE_CONN118_5 0x2f54
+#define AFE_CONN118_6 0x2f58
+#define AFE_CONN118_7 0x2f5c
+#define AFE_CONN119_0 0x2f60
+#define AFE_CONN119_1 0x2f64
+#define AFE_CONN119_2 0x2f68
+#define AFE_CONN119_4 0x2f70
+#define AFE_CONN119_5 0x2f74
+#define AFE_CONN119_6 0x2f78
+#define AFE_CONN119_7 0x2f7c
+#define AFE_CONN120_0 0x2f80
+#define AFE_CONN120_1 0x2f84
+#define AFE_CONN120_2 0x2f88
+#define AFE_CONN120_4 0x2f90
+#define AFE_CONN120_5 0x2f94
+#define AFE_CONN120_6 0x2f98
+#define AFE_CONN120_7 0x2f9c
+#define AFE_CONN121_0 0x2fa0
+#define AFE_CONN121_1 0x2fa4
+#define AFE_CONN121_2 0x2fa8
+#define AFE_CONN121_4 0x2fb0
+#define AFE_CONN121_5 0x2fb4
+#define AFE_CONN121_6 0x2fb8
+#define AFE_CONN121_7 0x2fbc
+#define AFE_CONN122_0 0x2fc0
+#define AFE_CONN122_1 0x2fc4
+#define AFE_CONN122_2 0x2fc8
+#define AFE_CONN122_4 0x2fd0
+#define AFE_CONN122_5 0x2fd4
+#define AFE_CONN122_6 0x2fd8
+#define AFE_CONN122_7 0x2fdc
+#define AFE_CONN123_0 0x2fe0
+#define AFE_CONN123_1 0x2fe4
+#define AFE_CONN123_2 0x2fe8
+#define AFE_CONN123_4 0x2ff0
+#define AFE_CONN123_5 0x2ff4
+#define AFE_CONN123_6 0x2ff8
+#define AFE_CONN123_7 0x2ffc
+#define AFE_CONN124_0 0x3000
+#define AFE_CONN124_1 0x3004
+#define AFE_CONN124_2 0x3008
+#define AFE_CONN124_4 0x3010
+#define AFE_CONN124_5 0x3014
+#define AFE_CONN124_6 0x3018
+#define AFE_CONN124_7 0x301c
+#define AFE_CONN125_0 0x3020
+#define AFE_CONN125_1 0x3024
+#define AFE_CONN125_2 0x3028
+#define AFE_CONN125_4 0x3030
+#define AFE_CONN125_5 0x3034
+#define AFE_CONN125_6 0x3038
+#define AFE_CONN125_7 0x303c
+#define AFE_CONN126_0 0x3040
+#define AFE_CONN126_1 0x3044
+#define AFE_CONN126_2 0x3048
+#define AFE_CONN126_4 0x3050
+#define AFE_CONN126_5 0x3054
+#define AFE_CONN126_6 0x3058
+#define AFE_CONN126_7 0x305c
+#define AFE_CONN127_0 0x3060
+#define AFE_CONN127_1 0x3064
+#define AFE_CONN127_2 0x3068
+#define AFE_CONN127_4 0x3070
+#define AFE_CONN127_5 0x3074
+#define AFE_CONN127_6 0x3078
+#define AFE_CONN127_7 0x307c
+#define AFE_CONN128_0 0x3080
+#define AFE_CONN128_1 0x3084
+#define AFE_CONN128_2 0x3088
+#define AFE_CONN128_4 0x3090
+#define AFE_CONN128_5 0x3094
+#define AFE_CONN128_6 0x3098
+#define AFE_CONN128_7 0x309c
+#define AFE_CONN129_0 0x30a0
+#define AFE_CONN129_1 0x30a4
+#define AFE_CONN129_2 0x30a8
+#define AFE_CONN129_4 0x30b0
+#define AFE_CONN129_5 0x30b4
+#define AFE_CONN129_6 0x30b8
+#define AFE_CONN129_7 0x30bc
+#define AFE_CONN130_0 0x30c0
+#define AFE_CONN130_1 0x30c4
+#define AFE_CONN130_2 0x30c8
+#define AFE_CONN130_4 0x30d0
+#define AFE_CONN130_5 0x30d4
+#define AFE_CONN130_6 0x30d8
+#define AFE_CONN130_7 0x30dc
+#define AFE_CONN131_0 0x30e0
+#define AFE_CONN131_1 0x30e4
+#define AFE_CONN131_2 0x30e8
+#define AFE_CONN131_4 0x30f0
+#define AFE_CONN131_5 0x30f4
+#define AFE_CONN131_6 0x30f8
+#define AFE_CONN131_7 0x30fc
+#define AFE_CONN132_0 0x3100
+#define AFE_CONN132_1 0x3104
+#define AFE_CONN132_2 0x3108
+#define AFE_CONN132_4 0x3110
+#define AFE_CONN132_5 0x3114
+#define AFE_CONN132_6 0x3118
+#define AFE_CONN132_7 0x311c
+#define AFE_CONN133_0 0x3120
+#define AFE_CONN133_1 0x3124
+#define AFE_CONN133_2 0x3128
+#define AFE_CONN133_4 0x3130
+#define AFE_CONN133_5 0x3134
+#define AFE_CONN133_6 0x3138
+#define AFE_CONN133_7 0x313c
+#define AFE_CONN134_0 0x3140
+#define AFE_CONN134_1 0x3144
+#define AFE_CONN134_2 0x3148
+#define AFE_CONN134_4 0x3150
+#define AFE_CONN134_5 0x3154
+#define AFE_CONN134_6 0x3158
+#define AFE_CONN134_7 0x315c
+#define AFE_CONN135_0 0x3160
+#define AFE_CONN135_1 0x3164
+#define AFE_CONN135_2 0x3168
+#define AFE_CONN135_4 0x3170
+#define AFE_CONN135_5 0x3174
+#define AFE_CONN135_6 0x3178
+#define AFE_CONN135_7 0x317c
+#define AFE_CONN136_0 0x3180
+#define AFE_CONN136_1 0x3184
+#define AFE_CONN136_2 0x3188
+#define AFE_CONN136_4 0x3190
+#define AFE_CONN136_5 0x3194
+#define AFE_CONN136_6 0x3198
+#define AFE_CONN136_7 0x319c
+#define AFE_CONN137_0 0x31a0
+#define AFE_CONN137_1 0x31a4
+#define AFE_CONN137_2 0x31a8
+#define AFE_CONN137_4 0x31b0
+#define AFE_CONN137_5 0x31b4
+#define AFE_CONN137_6 0x31b8
+#define AFE_CONN137_7 0x31bc
+#define AFE_CONN138_0 0x31c0
+#define AFE_CONN138_1 0x31c4
+#define AFE_CONN138_2 0x31c8
+#define AFE_CONN138_4 0x31d0
+#define AFE_CONN138_5 0x31d4
+#define AFE_CONN138_6 0x31d8
+#define AFE_CONN138_7 0x31dc
+#define AFE_CONN139_0 0x31e0
+#define AFE_CONN139_1 0x31e4
+#define AFE_CONN139_2 0x31e8
+#define AFE_CONN139_4 0x31f0
+#define AFE_CONN139_5 0x31f4
+#define AFE_CONN139_6 0x31f8
+#define AFE_CONN139_7 0x31fc
+#define AFE_CONN148_0 0x3300
+#define AFE_CONN148_1 0x3304
+#define AFE_CONN148_2 0x3308
+#define AFE_CONN148_4 0x3310
+#define AFE_CONN148_5 0x3314
+#define AFE_CONN148_6 0x3318
+#define AFE_CONN148_7 0x331c
+#define AFE_CONN149_0 0x3320
+#define AFE_CONN149_1 0x3324
+#define AFE_CONN149_2 0x3328
+#define AFE_CONN149_4 0x3330
+#define AFE_CONN149_5 0x3334
+#define AFE_CONN149_6 0x3338
+#define AFE_CONN149_7 0x333c
+#define AFE_CONN180_0 0x3700
+#define AFE_CONN180_1 0x3704
+#define AFE_CONN180_2 0x3708
+#define AFE_CONN180_4 0x3710
+#define AFE_CONN180_5 0x3714
+#define AFE_CONN180_6 0x3718
+#define AFE_CONN180_7 0x371c
+#define AFE_CONN181_0 0x3720
+#define AFE_CONN181_1 0x3724
+#define AFE_CONN181_2 0x3728
+#define AFE_CONN181_4 0x3730
+#define AFE_CONN181_5 0x3734
+#define AFE_CONN181_6 0x3738
+#define AFE_CONN181_7 0x373c
+#define AFE_CONN182_0 0x3740
+#define AFE_CONN182_1 0x3744
+#define AFE_CONN182_2 0x3748
+#define AFE_CONN182_4 0x3750
+#define AFE_CONN182_5 0x3754
+#define AFE_CONN182_6 0x3758
+#define AFE_CONN182_7 0x375c
+#define AFE_CONN183_0 0x3760
+#define AFE_CONN183_1 0x3764
+#define AFE_CONN183_2 0x3768
+#define AFE_CONN183_4 0x3770
+#define AFE_CONN183_5 0x3774
+#define AFE_CONN183_6 0x3778
+#define AFE_CONN183_7 0x377c
+#define AFE_CONN184_0 0x3780
+#define AFE_CONN184_1 0x3784
+#define AFE_CONN184_2 0x3788
+#define AFE_CONN184_4 0x3790
+#define AFE_CONN184_5 0x3794
+#define AFE_CONN184_6 0x3798
+#define AFE_CONN184_7 0x379c
+#define AFE_CONN185_0 0x37a0
+#define AFE_CONN185_1 0x37a4
+#define AFE_CONN185_2 0x37a8
+#define AFE_CONN185_4 0x37b0
+#define AFE_CONN185_5 0x37b4
+#define AFE_CONN185_6 0x37b8
+#define AFE_CONN185_7 0x37bc
+#define AFE_CONN186_0 0x37c0
+#define AFE_CONN186_1 0x37c4
+#define AFE_CONN186_2 0x37c8
+#define AFE_CONN186_4 0x37d0
+#define AFE_CONN186_5 0x37d4
+#define AFE_CONN186_6 0x37d8
+#define AFE_CONN186_7 0x37dc
+#define AFE_CONN187_0 0x37e0
+#define AFE_CONN187_1 0x37e4
+#define AFE_CONN187_2 0x37e8
+#define AFE_CONN187_4 0x37f0
+#define AFE_CONN187_5 0x37f4
+#define AFE_CONN187_6 0x37f8
+#define AFE_CONN187_7 0x37fc
+#define AFE_CONN188_0 0x3800
+#define AFE_CONN188_1 0x3804
+#define AFE_CONN188_2 0x3808
+#define AFE_CONN188_4 0x3810
+#define AFE_CONN188_5 0x3814
+#define AFE_CONN188_6 0x3818
+#define AFE_CONN188_7 0x381c
+#define AFE_CONN189_0 0x3820
+#define AFE_CONN189_1 0x3824
+#define AFE_CONN189_2 0x3828
+#define AFE_CONN189_4 0x3830
+#define AFE_CONN189_5 0x3834
+#define AFE_CONN189_6 0x3838
+#define AFE_CONN189_7 0x383c
+#define AFE_CONN190_0 0x3840
+#define AFE_CONN190_1 0x3844
+#define AFE_CONN190_2 0x3848
+#define AFE_CONN190_4 0x3850
+#define AFE_CONN190_5 0x3854
+#define AFE_CONN190_6 0x3858
+#define AFE_CONN190_7 0x385c
+#define AFE_CONN191_0 0x3860
+#define AFE_CONN191_1 0x3864
+#define AFE_CONN191_2 0x3868
+#define AFE_CONN191_4 0x3870
+#define AFE_CONN191_5 0x3874
+#define AFE_CONN191_6 0x3878
+#define AFE_CONN191_7 0x387c
+#define AFE_CONN192_0 0x3880
+#define AFE_CONN192_1 0x3884
+#define AFE_CONN192_2 0x3888
+#define AFE_CONN192_4 0x3890
+#define AFE_CONN192_5 0x3894
+#define AFE_CONN192_6 0x3898
+#define AFE_CONN192_7 0x389c
+#define AFE_CONN193_0 0x38a0
+#define AFE_CONN193_1 0x38a4
+#define AFE_CONN193_2 0x38a8
+#define AFE_CONN193_4 0x38b0
+#define AFE_CONN193_5 0x38b4
+#define AFE_CONN193_6 0x38b8
+#define AFE_CONN193_7 0x38bc
+#define AFE_CONN194_0 0x38c0
+#define AFE_CONN194_1 0x38c4
+#define AFE_CONN194_2 0x38c8
+#define AFE_CONN194_4 0x38d0
+#define AFE_CONN194_5 0x38d4
+#define AFE_CONN194_6 0x38d8
+#define AFE_CONN194_7 0x38dc
+#define AFE_CONN195_0 0x38e0
+#define AFE_CONN195_1 0x38e4
+#define AFE_CONN195_2 0x38e8
+#define AFE_CONN195_4 0x38f0
+#define AFE_CONN195_5 0x38f4
+#define AFE_CONN195_6 0x38f8
+#define AFE_CONN195_7 0x38fc
+#define AFE_CONN196_0 0x3900
+#define AFE_CONN196_1 0x3904
+#define AFE_CONN196_2 0x3908
+#define AFE_CONN196_4 0x3910
+#define AFE_CONN196_5 0x3914
+#define AFE_CONN196_6 0x3918
+#define AFE_CONN196_7 0x391c
+#define AFE_CONN197_0 0x3920
+#define AFE_CONN197_1 0x3924
+#define AFE_CONN197_2 0x3928
+#define AFE_CONN197_4 0x3930
+#define AFE_CONN197_5 0x3934
+#define AFE_CONN197_6 0x3938
+#define AFE_CONN197_7 0x393c
+#define AFE_CONN198_0 0x3940
+#define AFE_CONN198_1 0x3944
+#define AFE_CONN198_2 0x3948
+#define AFE_CONN198_4 0x3950
+#define AFE_CONN198_5 0x3954
+#define AFE_CONN198_6 0x3958
+#define AFE_CONN198_7 0x395c
+#define AFE_CONN199_0 0x3960
+#define AFE_CONN199_1 0x3964
+#define AFE_CONN199_2 0x3968
+#define AFE_CONN199_4 0x3970
+#define AFE_CONN199_5 0x3974
+#define AFE_CONN199_6 0x3978
+#define AFE_CONN199_7 0x397c
+#define AFE_CONN200_0 0x3980
+#define AFE_CONN200_1 0x3984
+#define AFE_CONN200_2 0x3988
+#define AFE_CONN200_4 0x3990
+#define AFE_CONN200_5 0x3994
+#define AFE_CONN200_6 0x3998
+#define AFE_CONN200_7 0x399c
+#define AFE_CONN201_0 0x39a0
+#define AFE_CONN201_1 0x39a4
+#define AFE_CONN201_2 0x39a8
+#define AFE_CONN201_4 0x39b0
+#define AFE_CONN201_5 0x39b4
+#define AFE_CONN201_6 0x39b8
+#define AFE_CONN201_7 0x39bc
+#define AFE_CONN202_0 0x39c0
+#define AFE_CONN202_1 0x39c4
+#define AFE_CONN202_2 0x39c8
+#define AFE_CONN202_4 0x39d0
+#define AFE_CONN202_5 0x39d4
+#define AFE_CONN202_6 0x39d8
+#define AFE_CONN202_7 0x39dc
+#define AFE_CONN203_0 0x39e0
+#define AFE_CONN203_1 0x39e4
+#define AFE_CONN203_2 0x39e8
+#define AFE_CONN203_4 0x39f0
+#define AFE_CONN203_5 0x39f4
+#define AFE_CONN203_6 0x39f8
+#define AFE_CONN203_7 0x39fc
+#define AFE_CONN204_0 0x3a00
+#define AFE_CONN204_1 0x3a04
+#define AFE_CONN204_2 0x3a08
+#define AFE_CONN204_4 0x3a10
+#define AFE_CONN204_5 0x3a14
+#define AFE_CONN204_6 0x3a18
+#define AFE_CONN204_7 0x3a1c
+#define AFE_CONN205_0 0x3a20
+#define AFE_CONN205_1 0x3a24
+#define AFE_CONN205_2 0x3a28
+#define AFE_CONN205_4 0x3a30
+#define AFE_CONN205_5 0x3a34
+#define AFE_CONN205_6 0x3a38
+#define AFE_CONN205_7 0x3a3c
+#define AFE_CONN206_0 0x3a40
+#define AFE_CONN206_1 0x3a44
+#define AFE_CONN206_2 0x3a48
+#define AFE_CONN206_4 0x3a50
+#define AFE_CONN206_5 0x3a54
+#define AFE_CONN206_6 0x3a58
+#define AFE_CONN206_7 0x3a5c
+#define AFE_CONN207_0 0x3a60
+#define AFE_CONN207_1 0x3a64
+#define AFE_CONN207_2 0x3a68
+#define AFE_CONN207_4 0x3a70
+#define AFE_CONN207_5 0x3a74
+#define AFE_CONN207_6 0x3a78
+#define AFE_CONN207_7 0x3a7c
+#define AFE_CONN208_0 0x3a80
+#define AFE_CONN208_1 0x3a84
+#define AFE_CONN208_2 0x3a88
+#define AFE_CONN208_4 0x3a90
+#define AFE_CONN208_5 0x3a94
+#define AFE_CONN208_6 0x3a98
+#define AFE_CONN208_7 0x3a9c
+#define AFE_CONN209_0 0x3aa0
+#define AFE_CONN209_1 0x3aa4
+#define AFE_CONN209_2 0x3aa8
+#define AFE_CONN209_4 0x3ab0
+#define AFE_CONN209_5 0x3ab4
+#define AFE_CONN209_6 0x3ab8
+#define AFE_CONN209_7 0x3abc
+#define AFE_CONN210_0 0x3ac0
+#define AFE_CONN210_1 0x3ac4
+#define AFE_CONN210_2 0x3ac8
+#define AFE_CONN210_4 0x3ad0
+#define AFE_CONN210_5 0x3ad4
+#define AFE_CONN210_6 0x3ad8
+#define AFE_CONN210_7 0x3adc
+#define AFE_CONN211_0 0x3ae0
+#define AFE_CONN211_1 0x3ae4
+#define AFE_CONN211_2 0x3ae8
+#define AFE_CONN211_4 0x3af0
+#define AFE_CONN211_5 0x3af4
+#define AFE_CONN211_6 0x3af8
+#define AFE_CONN211_7 0x3afc
+#define AFE_CONN_MON_CFG 0x4080
+#define AFE_CONN_MON0 0x4084
+#define AFE_CONN_MON1 0x4088
+#define AFE_CONN_MON2 0x408c
+#define AFE_CONN_MON3 0x4090
+#define AFE_CONN_MON4 0x4094
+#define AFE_CONN_MON5 0x4098
+#define AFE_CONN_RS_0 0x40a0
+#define AFE_CONN_RS_1 0x40a4
+#define AFE_CONN_RS_2 0x40a8
+#define AFE_CONN_RS_3 0x40ac
+#define AFE_CONN_RS_4 0x40b0
+#define AFE_CONN_RS_5 0x40b4
+#define AFE_CONN_RS_6 0x40b8
+#define AFE_CONN_DI_0 0x40c0
+#define AFE_CONN_DI_1 0x40c4
+#define AFE_CONN_DI_2 0x40c8
+#define AFE_CONN_DI_3 0x40cc
+#define AFE_CONN_DI_4 0x40d0
+#define AFE_CONN_DI_5 0x40d4
+#define AFE_CONN_DI_6 0x40d8
+#define AFE_CONN_16BIT_0 0x40e0
+#define AFE_CONN_16BIT_1 0x40e4
+#define AFE_CONN_16BIT_2 0x40e8
+#define AFE_CONN_16BIT_3 0x40ec
+#define AFE_CONN_16BIT_4 0x40f0
+#define AFE_CONN_16BIT_5 0x40f4
+#define AFE_CONN_16BIT_6 0x40f8
+#define AFE_CONN_24BIT_0 0x4100
+#define AFE_CONN_24BIT_1 0x4104
+#define AFE_CONN_24BIT_2 0x4108
+#define AFE_CONN_24BIT_3 0x410c
+#define AFE_CONN_24BIT_4 0x4110
+#define AFE_CONN_24BIT_5 0x4114
+#define AFE_CONN_24BIT_6 0x4118
+#define AFE_CBIP_CFG0 0x4380
+#define AFE_CBIP_SLV_DECODER_MON0 0x4384
+#define AFE_CBIP_SLV_DECODER_MON1 0x4388
+#define AFE_CBIP_SLV_MUX_MON_CFG 0x438c
+#define AFE_CBIP_SLV_MUX_MON0 0x4390
+#define AFE_CBIP_SLV_MUX_MON1 0x4394
+#define AFE_MEMIF_CON0 0x4400
+#define AFE_MEMIF_ONE_HEART 0x4420
+#define AFE_DL0_BASE_MSB 0x4440
+#define AFE_DL0_BASE 0x4444
+#define AFE_DL0_CUR_MSB 0x4448
+#define AFE_DL0_CUR 0x444c
+#define AFE_DL0_END_MSB 0x4450
+#define AFE_DL0_END 0x4454
+#define AFE_DL0_RCH_MON 0x4458
+#define AFE_DL0_LCH_MON 0x445c
+#define AFE_DL0_CON0 0x4460
+#define AFE_DL0_MON0 0x4464
+#define AFE_DL1_BASE_MSB 0x4470
+#define AFE_DL1_BASE 0x4474
+#define AFE_DL1_CUR_MSB 0x4478
+#define AFE_DL1_CUR 0x447c
+#define AFE_DL1_END_MSB 0x4480
+#define AFE_DL1_END 0x4484
+#define AFE_DL1_RCH_MON 0x4488
+#define AFE_DL1_LCH_MON 0x448c
+#define AFE_DL1_CON0 0x4490
+#define AFE_DL1_MON0 0x4494
+#define AFE_DL2_BASE_MSB 0x44a0
+#define AFE_DL2_BASE 0x44a4
+#define AFE_DL2_CUR_MSB 0x44a8
+#define AFE_DL2_CUR 0x44ac
+#define AFE_DL2_END_MSB 0x44b0
+#define AFE_DL2_END 0x44b4
+#define AFE_DL2_RCH_MON 0x44b8
+#define AFE_DL2_LCH_MON 0x44bc
+#define AFE_DL2_CON0 0x44c0
+#define AFE_DL2_MON0 0x44c4
+#define AFE_DL3_BASE_MSB 0x44d0
+#define AFE_DL3_BASE 0x44d4
+#define AFE_DL3_CUR_MSB 0x44d8
+#define AFE_DL3_CUR 0x44dc
+#define AFE_DL3_END_MSB 0x44e0
+#define AFE_DL3_END 0x44e4
+#define AFE_DL3_RCH_MON 0x44e8
+#define AFE_DL3_LCH_MON 0x44ec
+#define AFE_DL3_CON0 0x44f0
+#define AFE_DL3_MON0 0x44f4
+#define AFE_DL4_BASE_MSB 0x4500
+#define AFE_DL4_BASE 0x4504
+#define AFE_DL4_CUR_MSB 0x4508
+#define AFE_DL4_CUR 0x450c
+#define AFE_DL4_END_MSB 0x4510
+#define AFE_DL4_END 0x4514
+#define AFE_DL4_RCH_MON 0x4518
+#define AFE_DL4_LCH_MON 0x451c
+#define AFE_DL4_CON0 0x4520
+#define AFE_DL4_MON0 0x4524
+#define AFE_DL5_BASE_MSB 0x4530
+#define AFE_DL5_BASE 0x4534
+#define AFE_DL5_CUR_MSB 0x4538
+#define AFE_DL5_CUR 0x453c
+#define AFE_DL5_END_MSB 0x4540
+#define AFE_DL5_END 0x4544
+#define AFE_DL5_RCH_MON 0x4548
+#define AFE_DL5_LCH_MON 0x454c
+#define AFE_DL5_CON0 0x4550
+#define AFE_DL5_MON0 0x4554
+#define AFE_DL6_BASE_MSB 0x4560
+#define AFE_DL6_BASE 0x4564
+#define AFE_DL6_CUR_MSB 0x4568
+#define AFE_DL6_CUR 0x456c
+#define AFE_DL6_END_MSB 0x4570
+#define AFE_DL6_END 0x4574
+#define AFE_DL6_RCH_MON 0x4578
+#define AFE_DL6_LCH_MON 0x457c
+#define AFE_DL6_CON0 0x4580
+#define AFE_DL6_MON0 0x4584
+#define AFE_DL7_BASE_MSB 0x4590
+#define AFE_DL7_BASE 0x4594
+#define AFE_DL7_CUR_MSB 0x4598
+#define AFE_DL7_CUR 0x459c
+#define AFE_DL7_END_MSB 0x45a0
+#define AFE_DL7_END 0x45a4
+#define AFE_DL7_RCH_MON 0x45a8
+#define AFE_DL7_LCH_MON 0x45ac
+#define AFE_DL7_CON0 0x45b0
+#define AFE_DL7_MON0 0x45b4
+#define AFE_DL8_BASE_MSB 0x45c0
+#define AFE_DL8_BASE 0x45c4
+#define AFE_DL8_CUR_MSB 0x45c8
+#define AFE_DL8_CUR 0x45cc
+#define AFE_DL8_END_MSB 0x45d0
+#define AFE_DL8_END 0x45d4
+#define AFE_DL8_RCH_MON 0x45d8
+#define AFE_DL8_LCH_MON 0x45dc
+#define AFE_DL8_CON0 0x45e0
+#define AFE_DL8_MON0 0x45e4
+#define AFE_DL_4CH_BASE_MSB 0x45f0
+#define AFE_DL_4CH_BASE 0x45f4
+#define AFE_DL_4CH_CUR_MSB 0x45f8
+#define AFE_DL_4CH_CUR 0x45fc
+#define AFE_DL_4CH_END_MSB 0x4600
+#define AFE_DL_4CH_END 0x4604
+#define AFE_DL_4CH_CON0 0x4610
+#define AFE_DL_4CH_MON0 0x4618
+#define AFE_DL_24CH_BASE_MSB 0x4620
+#define AFE_DL_24CH_BASE 0x4624
+#define AFE_DL_24CH_CUR_MSB 0x4628
+#define AFE_DL_24CH_CUR 0x462c
+#define AFE_DL_24CH_END_MSB 0x4630
+#define AFE_DL_24CH_END 0x4634
+#define AFE_DL_24CH_CON0 0x4640
+#define AFE_DL_24CH_MON0 0x4648
+#define AFE_DL23_BASE_MSB 0x4680
+#define AFE_DL23_BASE 0x4684
+#define AFE_DL23_CUR_MSB 0x4688
+#define AFE_DL23_CUR 0x468c
+#define AFE_DL23_END_MSB 0x4690
+#define AFE_DL23_END 0x4694
+#define AFE_DL23_RCH_MON 0x4698
+#define AFE_DL23_LCH_MON 0x469c
+#define AFE_DL23_CON0 0x46a0
+#define AFE_DL23_MON0 0x46a4
+#define AFE_DL24_BASE_MSB 0x46b0
+#define AFE_DL24_BASE 0x46b4
+#define AFE_DL24_CUR_MSB 0x46b8
+#define AFE_DL24_CUR 0x46bc
+#define AFE_DL24_END_MSB 0x46c0
+#define AFE_DL24_END 0x46c4
+#define AFE_DL24_RCH_MON 0x46c8
+#define AFE_DL24_LCH_MON 0x46cc
+#define AFE_DL24_CON0 0x46d0
+#define AFE_DL24_MON0 0x46d4
+#define AFE_DL25_BASE_MSB 0x46e0
+#define AFE_DL25_BASE 0x46e4
+#define AFE_DL25_CUR_MSB 0x46e8
+#define AFE_DL25_CUR 0x46ec
+#define AFE_DL25_END_MSB 0x46f0
+#define AFE_DL25_END 0x46f4
+#define AFE_DL25_RCH_MON 0x46f8
+#define AFE_DL25_LCH_MON 0x46fc
+#define AFE_DL25_CON0 0x4700
+#define AFE_DL25_MON0 0x4704
+#define AFE_DL26_BASE_MSB 0x4710
+#define AFE_DL26_BASE 0x4714
+#define AFE_DL26_CUR_MSB 0x4718
+#define AFE_DL26_CUR 0x471c
+#define AFE_DL26_END_MSB 0x4720
+#define AFE_DL26_END 0x4724
+#define AFE_DL26_RCH_MON 0x4728
+#define AFE_DL26_LCH_MON 0x472c
+#define AFE_DL26_CON0 0x4730
+#define AFE_DL26_MON0 0x4734
+#define AFE_VUL0_BASE_MSB 0x4d60
+#define AFE_VUL0_BASE 0x4d64
+#define AFE_VUL0_CUR_MSB 0x4d68
+#define AFE_VUL0_CUR 0x4d6c
+#define AFE_VUL0_END_MSB 0x4d70
+#define AFE_VUL0_END 0x4d74
+#define AFE_VUL0_RCH_MON 0x4d78
+#define AFE_VUL0_LCH_MON 0x4d7c
+#define AFE_VUL0_CON0 0x4d80
+#define AFE_VUL0_MON0 0x4d84
+#define AFE_VUL1_BASE_MSB 0x4d90
+#define AFE_VUL1_BASE 0x4d94
+#define AFE_VUL1_CUR_MSB 0x4d98
+#define AFE_VUL1_CUR 0x4d9c
+#define AFE_VUL1_END_MSB 0x4da0
+#define AFE_VUL1_END 0x4da4
+#define AFE_VUL1_RCH_MON 0x4da8
+#define AFE_VUL1_LCH_MON 0x4dac
+#define AFE_VUL1_CON0 0x4db0
+#define AFE_VUL1_MON0 0x4db4
+#define AFE_VUL2_BASE_MSB 0x4dc0
+#define AFE_VUL2_BASE 0x4dc4
+#define AFE_VUL2_CUR_MSB 0x4dc8
+#define AFE_VUL2_CUR 0x4dcc
+#define AFE_VUL2_END_MSB 0x4dd0
+#define AFE_VUL2_END 0x4dd4
+#define AFE_VUL2_RCH_MON 0x4dd8
+#define AFE_VUL2_LCH_MON 0x4ddc
+#define AFE_VUL2_CON0 0x4de0
+#define AFE_VUL2_MON0 0x4de4
+#define AFE_VUL3_BASE_MSB 0x4df0
+#define AFE_VUL3_BASE 0x4df4
+#define AFE_VUL3_CUR_MSB 0x4df8
+#define AFE_VUL3_CUR 0x4dfc
+#define AFE_VUL3_END_MSB 0x4e00
+#define AFE_VUL3_END 0x4e04
+#define AFE_VUL3_RCH_MON 0x4e08
+#define AFE_VUL3_LCH_MON 0x4e0c
+#define AFE_VUL3_CON0 0x4e10
+#define AFE_VUL3_MON0 0x4e14
+#define AFE_VUL4_BASE_MSB 0x4e20
+#define AFE_VUL4_BASE 0x4e24
+#define AFE_VUL4_CUR_MSB 0x4e28
+#define AFE_VUL4_CUR 0x4e2c
+#define AFE_VUL4_END_MSB 0x4e30
+#define AFE_VUL4_END 0x4e34
+#define AFE_VUL4_RCH_MON 0x4e38
+#define AFE_VUL4_LCH_MON 0x4e3c
+#define AFE_VUL4_CON0 0x4e40
+#define AFE_VUL4_MON0 0x4e44
+#define AFE_VUL5_BASE_MSB 0x4e50
+#define AFE_VUL5_BASE 0x4e54
+#define AFE_VUL5_CUR_MSB 0x4e58
+#define AFE_VUL5_CUR 0x4e5c
+#define AFE_VUL5_END_MSB 0x4e60
+#define AFE_VUL5_END 0x4e64
+#define AFE_VUL5_RCH_MON 0x4e68
+#define AFE_VUL5_LCH_MON 0x4e6c
+#define AFE_VUL5_CON0 0x4e70
+#define AFE_VUL5_MON0 0x4e74
+#define AFE_VUL6_BASE_MSB 0x4e80
+#define AFE_VUL6_BASE 0x4e84
+#define AFE_VUL6_CUR_MSB 0x4e88
+#define AFE_VUL6_CUR 0x4e8c
+#define AFE_VUL6_END_MSB 0x4e90
+#define AFE_VUL6_END 0x4e94
+#define AFE_VUL6_RCH_MON 0x4e98
+#define AFE_VUL6_LCH_MON 0x4e9c
+#define AFE_VUL6_CON0 0x4ea0
+#define AFE_VUL6_MON0 0x4ea4
+#define AFE_VUL7_BASE_MSB 0x4eb0
+#define AFE_VUL7_BASE 0x4eb4
+#define AFE_VUL7_CUR_MSB 0x4eb8
+#define AFE_VUL7_CUR 0x4ebc
+#define AFE_VUL7_END_MSB 0x4ec0
+#define AFE_VUL7_END 0x4ec4
+#define AFE_VUL7_RCH_MON 0x4ec8
+#define AFE_VUL7_LCH_MON 0x4ecc
+#define AFE_VUL7_CON0 0x4ed0
+#define AFE_VUL7_MON0 0x4ed4
+#define AFE_VUL8_BASE_MSB 0x4ee0
+#define AFE_VUL8_BASE 0x4ee4
+#define AFE_VUL8_CUR_MSB 0x4ee8
+#define AFE_VUL8_CUR 0x4eec
+#define AFE_VUL8_END_MSB 0x4ef0
+#define AFE_VUL8_END 0x4ef4
+#define AFE_VUL8_RCH_MON 0x4ef8
+#define AFE_VUL8_LCH_MON 0x4efc
+#define AFE_VUL8_CON0 0x4f00
+#define AFE_VUL8_MON0 0x4f04
+#define AFE_VUL9_BASE_MSB 0x4f10
+#define AFE_VUL9_BASE 0x4f14
+#define AFE_VUL9_CUR_MSB 0x4f18
+#define AFE_VUL9_CUR 0x4f1c
+#define AFE_VUL9_END_MSB 0x4f20
+#define AFE_VUL9_END 0x4f24
+#define AFE_VUL9_RCH_MON 0x4f28
+#define AFE_VUL9_LCH_MON 0x4f2c
+#define AFE_VUL9_CON0 0x4f30
+#define AFE_VUL9_MON0 0x4f34
+#define AFE_VUL10_BASE_MSB 0x4f40
+#define AFE_VUL10_BASE 0x4f44
+#define AFE_VUL10_CUR_MSB 0x4f48
+#define AFE_VUL10_CUR 0x4f4c
+#define AFE_VUL10_END_MSB 0x4f50
+#define AFE_VUL10_END 0x4f54
+#define AFE_VUL10_RCH_MON 0x4f58
+#define AFE_VUL10_LCH_MON 0x4f5c
+#define AFE_VUL10_CON0 0x4f60
+#define AFE_VUL10_MON0 0x4f64
+#define AFE_VUL24_BASE_MSB 0x4fa0
+#define AFE_VUL24_BASE 0x4fa4
+#define AFE_VUL24_CUR_MSB 0x4fa8
+#define AFE_VUL24_CUR 0x4fac
+#define AFE_VUL24_END_MSB 0x4fb0
+#define AFE_VUL24_END 0x4fb4
+#define AFE_VUL24_CON0 0x4fb8
+#define AFE_VUL24_MON0 0x4fbc
+#define AFE_VUL25_BASE_MSB 0x4fc0
+#define AFE_VUL25_BASE 0x4fc4
+#define AFE_VUL25_CUR_MSB 0x4fc8
+#define AFE_VUL25_CUR 0x4fcc
+#define AFE_VUL25_END_MSB 0x4fd0
+#define AFE_VUL25_END 0x4fd4
+#define AFE_VUL25_CON0 0x4fd8
+#define AFE_VUL25_MON0 0x4fdc
+#define AFE_VUL26_BASE_MSB 0x4fe0
+#define AFE_VUL26_BASE 0x4fe4
+#define AFE_VUL26_CUR_MSB 0x4fe8
+#define AFE_VUL26_CUR 0x4fec
+#define AFE_VUL26_END_MSB 0x4ff0
+#define AFE_VUL26_END 0x4ff4
+#define AFE_VUL26_CON0 0x4ff8
+#define AFE_VUL26_MON0 0x4ffc
+#define AFE_VUL_CM0_BASE_MSB 0x51c0
+#define AFE_VUL_CM0_BASE 0x51c4
+#define AFE_VUL_CM0_CUR_MSB 0x51c8
+#define AFE_VUL_CM0_CUR 0x51cc
+#define AFE_VUL_CM0_END_MSB 0x51d0
+#define AFE_VUL_CM0_END 0x51d4
+#define AFE_VUL_CM0_CON0 0x51d8
+#define AFE_VUL_CM1_BASE_MSB 0x51e0
+#define AFE_VUL_CM1_BASE 0x51e4
+#define AFE_VUL_CM1_CUR_MSB 0x51e8
+#define AFE_VUL_CM1_CUR 0x51ec
+#define AFE_VUL_CM1_END_MSB 0x51f0
+#define AFE_VUL_CM1_END 0x51f4
+#define AFE_VUL_CM1_CON0 0x51f8
+#define AFE_VUL_CM2_BASE_MSB 0x5200
+#define AFE_VUL_CM2_BASE 0x5204
+#define AFE_VUL_CM2_CUR_MSB 0x5208
+#define AFE_VUL_CM2_CUR 0x520c
+#define AFE_VUL_CM2_END_MSB 0x5210
+#define AFE_VUL_CM2_END 0x5214
+#define AFE_VUL_CM2_CON0 0x5218
+#define AFE_ETDM_IN0_BASE_MSB 0x5220
+#define AFE_ETDM_IN0_BASE 0x5224
+#define AFE_ETDM_IN0_CUR_MSB 0x5228
+#define AFE_ETDM_IN0_CUR 0x522c
+#define AFE_ETDM_IN0_END_MSB 0x5230
+#define AFE_ETDM_IN0_END 0x5234
+#define AFE_ETDM_IN0_CON0 0x5238
+#define AFE_ETDM_IN1_BASE_MSB 0x5240
+#define AFE_ETDM_IN1_BASE 0x5244
+#define AFE_ETDM_IN1_CUR_MSB 0x5248
+#define AFE_ETDM_IN1_CUR 0x524c
+#define AFE_ETDM_IN1_END_MSB 0x5250
+#define AFE_ETDM_IN1_END 0x5254
+#define AFE_ETDM_IN1_CON0 0x5258
+#define AFE_ETDM_IN2_BASE_MSB 0x5260
+#define AFE_ETDM_IN2_BASE 0x5264
+#define AFE_ETDM_IN2_CUR_MSB 0x5268
+#define AFE_ETDM_IN2_CUR 0x526c
+#define AFE_ETDM_IN2_END_MSB 0x5270
+#define AFE_ETDM_IN2_END 0x5274
+#define AFE_ETDM_IN2_CON0 0x5278
+#define AFE_ETDM_IN3_BASE_MSB 0x5280
+#define AFE_ETDM_IN3_BASE 0x5284
+#define AFE_ETDM_IN3_CUR_MSB 0x5288
+#define AFE_ETDM_IN3_CUR 0x528c
+#define AFE_ETDM_IN3_END_MSB 0x5290
+#define AFE_ETDM_IN3_END 0x5294
+#define AFE_ETDM_IN3_CON0 0x5298
+#define AFE_ETDM_IN4_BASE_MSB 0x52a0
+#define AFE_ETDM_IN4_BASE 0x52a4
+#define AFE_ETDM_IN4_CUR_MSB 0x52a8
+#define AFE_ETDM_IN4_CUR 0x52ac
+#define AFE_ETDM_IN4_END_MSB 0x52b0
+#define AFE_ETDM_IN4_END 0x52b4
+#define AFE_ETDM_IN4_CON0 0x52b8
+#define AFE_ETDM_IN5_BASE_MSB 0x52c0
+#define AFE_ETDM_IN5_BASE 0x52c4
+#define AFE_ETDM_IN5_CUR_MSB 0x52c8
+#define AFE_ETDM_IN5_CUR 0x52cc
+#define AFE_ETDM_IN5_END_MSB 0x52d0
+#define AFE_ETDM_IN5_END 0x52d4
+#define AFE_ETDM_IN5_CON0 0x52d8
+#define AFE_ETDM_IN6_BASE_MSB 0x52e0
+#define AFE_ETDM_IN6_BASE 0x52e4
+#define AFE_ETDM_IN6_CUR_MSB 0x52e8
+#define AFE_ETDM_IN6_CUR 0x52ec
+#define AFE_ETDM_IN6_END_MSB 0x52f0
+#define AFE_ETDM_IN6_END 0x52f4
+#define AFE_ETDM_IN6_CON0 0x52f8
+#define AFE_HDMI_OUT_BASE_MSB 0x5360
+#define AFE_HDMI_OUT_BASE 0x5364
+#define AFE_HDMI_OUT_CUR_MSB 0x5368
+#define AFE_HDMI_OUT_CUR 0x536c
+#define AFE_HDMI_OUT_END_MSB 0x5370
+#define AFE_HDMI_OUT_END 0x5374
+#define AFE_HDMI_OUT_CON0 0x5378
+#define AFE_VUL24_RCH_MON 0x53e0
+#define AFE_VUL24_LCH_MON 0x53e4
+#define AFE_VUL25_RCH_MON 0x53e8
+#define AFE_VUL25_LCH_MON 0x53ec
+#define AFE_VUL26_RCH_MON 0x53f0
+#define AFE_VUL26_LCH_MON 0x53f4
+#define AFE_VUL_CM0_RCH_MON 0x5458
+#define AFE_VUL_CM0_LCH_MON 0x545c
+#define AFE_VUL_CM1_RCH_MON 0x5460
+#define AFE_VUL_CM1_LCH_MON 0x5464
+#define AFE_VUL_CM2_RCH_MON 0x5468
+#define AFE_VUL_CM2_LCH_MON 0x546c
+#define AFE_DL_4CH_CH0_MON 0x54f4
+#define AFE_DL_4CH_CH1_MON 0x54f8
+#define AFE_DL_4CH_CH2_MON 0x54fc
+#define AFE_DL_4CH_CH3_MON 0x5500
+#define AFE_DL_24CH_CH0_MON 0x5504
+#define AFE_DL_24CH_CH1_MON 0x5508
+#define AFE_DL_24CH_CH2_MON 0x550c
+#define AFE_DL_24CH_CH3_MON 0x5510
+#define AFE_DL_24CH_CH4_MON 0x5514
+#define AFE_DL_24CH_CH5_MON 0x5518
+#define AFE_DL_24CH_CH6_MON 0x551c
+#define AFE_DL_24CH_CH7_MON 0x5520
+#define AFE_DL_24CH_CH8_MON 0x5524
+#define AFE_DL_24CH_CH9_MON 0x5528
+#define AFE_DL_24CH_CH10_MON 0x552c
+#define AFE_DL_24CH_CH11_MON 0x5530
+#define AFE_DL_24CH_CH12_MON 0x5534
+#define AFE_DL_24CH_CH13_MON 0x5538
+#define AFE_DL_24CH_CH14_MON 0x553c
+#define AFE_DL_24CH_CH15_MON 0x5540
+#define AFE_SRAM_BOUND 0x5620
+#define AFE_SECURE_CON0 0x5624
+#define AFE_SECURE_CON1 0x5628
+#define AFE_SE_SECURE_CON0 0x5630
+#define AFE_SE_SECURE_CON1 0x5634
+#define AFE_SE_SECURE_CON2 0x5638
+#define AFE_SE_SECURE_CON3 0x563c
+#define AFE_SE_PROT_SIDEBAND0 0x5640
+#define AFE_SE_PROT_SIDEBAND1 0x5644
+#define AFE_SE_PROT_SIDEBAND2 0x5648
+#define AFE_SE_PROT_SIDEBAND3 0x564c
+#define AFE_SE_DOMAIN_SIDEBAND0 0x5650
+#define AFE_SE_DOMAIN_SIDEBAND1 0x5654
+#define AFE_SE_DOMAIN_SIDEBAND2 0x5658
+#define AFE_SE_DOMAIN_SIDEBAND3 0x565c
+#define AFE_SE_DOMAIN_SIDEBAND4 0x5660
+#define AFE_SE_DOMAIN_SIDEBAND5 0x5664
+#define AFE_SE_DOMAIN_SIDEBAND6 0x5668
+#define AFE_SE_DOMAIN_SIDEBAND7 0x566c
+#define AFE_SE_DOMAIN_SIDEBAND8 0x5670
+#define AFE_SE_DOMAIN_SIDEBAND9 0x5674
+#define AFE_PROT_SIDEBAND0_MON 0x5678
+#define AFE_PROT_SIDEBAND1_MON 0x567c
+#define AFE_PROT_SIDEBAND2_MON 0x5680
+#define AFE_PROT_SIDEBAND3_MON 0x5684
+#define AFE_DOMAIN_SIDEBAND0_MON 0x5688
+#define AFE_DOMAIN_SIDEBAND1_MON 0x568c
+#define AFE_DOMAIN_SIDEBAND2_MON 0x5690
+#define AFE_DOMAIN_SIDEBAND3_MON 0x5694
+#define AFE_DOMAIN_SIDEBAND4_MON 0x5698
+#define AFE_DOMAIN_SIDEBAND5_MON 0x569c
+#define AFE_DOMAIN_SIDEBAND6_MON 0x56a0
+#define AFE_DOMAIN_SIDEBAND7_MON 0x56a4
+#define AFE_DOMAIN_SIDEBAND8_MON 0x56a8
+#define AFE_DOMAIN_SIDEBAND9_MON 0x56ac
+#define AFE_SECURE_CONN0 0x56b0
+#define AFE_SECURE_CONN_ETDM0 0x56b4
+#define AFE_SECURE_CONN_ETDM1 0x56b8
+#define AFE_SECURE_CONN_ETDM2 0x56bc
+#define AFE_SECURE_SRAM_CON0 0x56c0
+#define AFE_SECURE_SRAM_CON1 0x56c4
+#define AFE_SE_CONN_INPUT_MASK0 0x56d0
+#define AFE_SE_CONN_INPUT_MASK1 0x56d4
+#define AFE_SE_CONN_INPUT_MASK2 0x56d8
+#define AFE_SE_CONN_INPUT_MASK3 0x56dc
+#define AFE_SE_CONN_INPUT_MASK4 0x56e0
+#define AFE_SE_CONN_INPUT_MASK5 0x56e4
+#define AFE_SE_CONN_INPUT_MASK6 0x56e8
+#define AFE_SE_CONN_INPUT_MASK7 0x56ec
+#define AFE_NON_SE_CONN_INPUT_MASK0 0x56f0
+#define AFE_NON_SE_CONN_INPUT_MASK1 0x56f4
+#define AFE_NON_SE_CONN_INPUT_MASK2 0x56f8
+#define AFE_NON_SE_CONN_INPUT_MASK3 0x56fc
+#define AFE_NON_SE_CONN_INPUT_MASK4 0x5700
+#define AFE_NON_SE_CONN_INPUT_MASK5 0x5704
+#define AFE_NON_SE_CONN_INPUT_MASK6 0x5708
+#define AFE_NON_SE_CONN_INPUT_MASK7 0x570c
+#define AFE_SE_CONN_OUTPUT_SEL0 0x5710
+#define AFE_SE_CONN_OUTPUT_SEL1 0x5714
+#define AFE_SE_CONN_OUTPUT_SEL2 0x5718
+#define AFE_SE_CONN_OUTPUT_SEL3 0x571c
+#define AFE_SE_CONN_OUTPUT_SEL4 0x5720
+#define AFE_SE_CONN_OUTPUT_SEL5 0x5724
+#define AFE_SE_CONN_OUTPUT_SEL6 0x5728
+#define AFE_SE_CONN_OUTPUT_SEL7 0x572c
+#define AFE_PCM0_INTF_CON1_MASK_MON 0x5730
+#define AFE_PCM0_INTF_CON0_MASK_MON 0x5734
+#define AFE_CONNSYS_I2S_CON_MASK_MON 0x5738
+#define AFE_TDM_CON2_MASK_MON 0x5744
+#define AFE_MTKAIF0_CFG0_MASK_MON 0x574c
+#define AFE_MTKAIF1_CFG0_MASK_MON 0x5750
+#define AFE_ADDA_UL0_SRC_CON0_MASK_MON 0x5754
+#define AFE_ADDA_UL1_SRC_CON0_MASK_MON 0x5758
+#define AFE_ADDA_UL2_SRC_CON0_MASK_MON 0x575c
+#define AFE_ASRC_NEW_CON0 0x7800
+#define AFE_ASRC_NEW_CON1 0x7804
+#define AFE_ASRC_NEW_CON2 0x7808
+#define AFE_ASRC_NEW_CON3 0x780c
+#define AFE_ASRC_NEW_CON4 0x7810
+#define AFE_ASRC_NEW_CON5 0x7814
+#define AFE_ASRC_NEW_CON6 0x7818
+#define AFE_ASRC_NEW_CON7 0x781c
+#define AFE_ASRC_NEW_CON8 0x7820
+#define AFE_ASRC_NEW_CON9 0x7824
+#define AFE_ASRC_NEW_CON10 0x7828
+#define AFE_ASRC_NEW_CON11 0x782c
+#define AFE_ASRC_NEW_CON12 0x7830
+#define AFE_ASRC_NEW_CON13 0x7834
+#define AFE_ASRC_NEW_CON14 0x7838
+#define AFE_ASRC_NEW_IP_VERSION 0x783c
+#define AFE_GASRC0_NEW_CON0 0x7840
+#define AFE_GASRC0_NEW_CON1 0x7844
+#define AFE_GASRC0_NEW_CON2 0x7848
+#define AFE_GASRC0_NEW_CON3 0x784c
+#define AFE_GASRC0_NEW_CON4 0x7850
+#define AFE_GASRC0_NEW_CON5 0x7854
+#define AFE_GASRC0_NEW_CON6 0x7858
+#define AFE_GASRC0_NEW_CON7 0x785c
+#define AFE_GASRC0_NEW_CON8 0x7860
+#define AFE_GASRC0_NEW_CON9 0x7864
+#define AFE_GASRC0_NEW_CON10 0x7868
+#define AFE_GASRC0_NEW_CON11 0x786c
+#define AFE_GASRC0_NEW_CON12 0x7870
+#define AFE_GASRC0_NEW_CON13 0x7874
+#define AFE_GASRC0_NEW_CON14 0x7878
+#define AFE_GASRC0_NEW_IP_VERSION 0x787c
+#define AFE_GASRC1_NEW_CON0 0x7880
+#define AFE_GASRC1_NEW_CON1 0x7884
+#define AFE_GASRC1_NEW_CON2 0x7888
+#define AFE_GASRC1_NEW_CON3 0x788c
+#define AFE_GASRC1_NEW_CON4 0x7890
+#define AFE_GASRC1_NEW_CON5 0x7894
+#define AFE_GASRC1_NEW_CON6 0x7898
+#define AFE_GASRC1_NEW_CON7 0x789c
+#define AFE_GASRC1_NEW_CON8 0x78a0
+#define AFE_GASRC1_NEW_CON9 0x78a4
+#define AFE_GASRC1_NEW_CON10 0x78a8
+#define AFE_GASRC1_NEW_CON11 0x78ac
+#define AFE_GASRC1_NEW_CON12 0x78b0
+#define AFE_GASRC1_NEW_CON13 0x78b4
+#define AFE_GASRC1_NEW_CON14 0x78b8
+#define AFE_GASRC1_NEW_IP_VERSION 0x78bc
+#define AFE_GASRC2_NEW_CON0 0x78c0
+#define AFE_GASRC2_NEW_CON1 0x78c4
+#define AFE_GASRC2_NEW_CON2 0x78c8
+#define AFE_GASRC2_NEW_CON3 0x78cc
+#define AFE_GASRC2_NEW_CON4 0x78d0
+#define AFE_GASRC2_NEW_CON5 0x78d4
+#define AFE_GASRC2_NEW_CON6 0x78d8
+#define AFE_GASRC2_NEW_CON7 0x78dc
+#define AFE_GASRC2_NEW_CON8 0x78e0
+#define AFE_GASRC2_NEW_CON9 0x78e4
+#define AFE_GASRC2_NEW_CON10 0x78e8
+#define AFE_GASRC2_NEW_CON11 0x78ec
+#define AFE_GASRC2_NEW_CON12 0x78f0
+#define AFE_GASRC2_NEW_CON13 0x78f4
+#define AFE_GASRC2_NEW_CON14 0x78f8
+#define AFE_GASRC2_NEW_IP_VERSION 0x78fc
+#define AFE_GASRC3_NEW_CON0 0x7900
+#define AFE_GASRC3_NEW_CON1 0x7904
+#define AFE_GASRC3_NEW_CON2 0x7908
+#define AFE_GASRC3_NEW_CON3 0x790c
+#define AFE_GASRC3_NEW_CON4 0x7910
+#define AFE_GASRC3_NEW_CON5 0x7914
+#define AFE_GASRC3_NEW_CON6 0x7918
+#define AFE_GASRC3_NEW_CON7 0x791c
+#define AFE_GASRC3_NEW_CON8 0x7920
+#define AFE_GASRC3_NEW_CON9 0x7924
+#define AFE_GASRC3_NEW_CON10 0x7928
+#define AFE_GASRC3_NEW_CON11 0x792c
+#define AFE_GASRC3_NEW_CON12 0x7930
+#define AFE_GASRC3_NEW_CON13 0x7934
+#define AFE_GASRC3_NEW_CON14 0x7938
+#define AFE_GASRC3_NEW_IP_VERSION 0x793c
+#define AFE_GASRC4_NEW_CON0 0x7940
+#define AFE_GASRC4_NEW_CON1 0x7944
+#define AFE_GASRC4_NEW_CON2 0x7948
+#define AFE_GASRC4_NEW_CON3 0x794c
+#define AFE_GASRC4_NEW_CON4 0x7950
+#define AFE_GASRC4_NEW_CON5 0x7954
+#define AFE_GASRC4_NEW_CON6 0x7958
+#define AFE_GASRC4_NEW_CON7 0x795c
+#define AFE_GASRC4_NEW_CON8 0x7960
+#define AFE_GASRC4_NEW_CON9 0x7964
+#define AFE_GASRC4_NEW_CON10 0x7968
+#define AFE_GASRC4_NEW_CON11 0x796c
+#define AFE_GASRC4_NEW_CON12 0x7970
+#define AFE_GASRC4_NEW_CON13 0x7974
+#define AFE_GASRC4_NEW_CON14 0x7978
+#define AFE_GASRC4_NEW_IP_VERSION 0x797c
+#define AFE_GASRC5_NEW_CON0 0x7980
+#define AFE_GASRC5_NEW_CON1 0x7984
+#define AFE_GASRC5_NEW_CON2 0x7988
+#define AFE_GASRC5_NEW_CON3 0x798c
+#define AFE_GASRC5_NEW_CON4 0x7990
+#define AFE_GASRC5_NEW_CON5 0x7994
+#define AFE_GASRC5_NEW_CON6 0x7998
+#define AFE_GASRC5_NEW_CON7 0x799c
+#define AFE_GASRC5_NEW_CON8 0x79a0
+#define AFE_GASRC5_NEW_CON9 0x79a4
+#define AFE_GASRC5_NEW_CON10 0x79a8
+#define AFE_GASRC5_NEW_CON11 0x79ac
+#define AFE_GASRC5_NEW_CON12 0x79b0
+#define AFE_GASRC5_NEW_CON13 0x79b4
+#define AFE_GASRC5_NEW_CON14 0x79b8
+#define AFE_GASRC5_NEW_IP_VERSION 0x79bc
+#define AFE_GASRC6_NEW_CON0 0x79c0
+#define AFE_GASRC6_NEW_CON1 0x79c4
+#define AFE_GASRC6_NEW_CON2 0x79c8
+#define AFE_GASRC6_NEW_CON3 0x79cc
+#define AFE_GASRC6_NEW_CON4 0x79d0
+#define AFE_GASRC6_NEW_CON5 0x79d4
+#define AFE_GASRC6_NEW_CON6 0x79d8
+#define AFE_GASRC6_NEW_CON7 0x79dc
+#define AFE_GASRC6_NEW_CON8 0x79e0
+#define AFE_GASRC6_NEW_CON9 0x79e4
+#define AFE_GASRC6_NEW_CON10 0x79e8
+#define AFE_GASRC6_NEW_CON11 0x79ec
+#define AFE_GASRC6_NEW_CON12 0x79f0
+#define AFE_GASRC6_NEW_CON13 0x79f4
+#define AFE_GASRC6_NEW_CON14 0x79f8
+#define AFE_GASRC6_NEW_IP_VERSION 0x79fc
+#define AFE_GASRC7_NEW_CON0 0x7a00
+#define AFE_GASRC7_NEW_CON1 0x7a04
+#define AFE_GASRC7_NEW_CON2 0x7a08
+#define AFE_GASRC7_NEW_CON3 0x7a0c
+#define AFE_GASRC7_NEW_CON4 0x7a10
+#define AFE_GASRC7_NEW_CON5 0x7a14
+#define AFE_GASRC7_NEW_CON6 0x7a18
+#define AFE_GASRC7_NEW_CON7 0x7a1c
+#define AFE_GASRC7_NEW_CON8 0x7a20
+#define AFE_GASRC7_NEW_CON9 0x7a24
+#define AFE_GASRC7_NEW_CON10 0x7a28
+#define AFE_GASRC7_NEW_CON11 0x7a2c
+#define AFE_GASRC7_NEW_CON12 0x7a30
+#define AFE_GASRC7_NEW_CON13 0x7a34
+#define AFE_GASRC7_NEW_CON14 0x7a38
+#define AFE_GASRC7_NEW_IP_VERSION 0x7a3c
+#define AFE_GASRC8_NEW_CON0 0x7a40
+#define AFE_GASRC8_NEW_CON1 0x7a44
+#define AFE_GASRC8_NEW_CON2 0x7a48
+#define AFE_GASRC8_NEW_CON3 0x7a4c
+#define AFE_GASRC8_NEW_CON4 0x7a50
+#define AFE_GASRC8_NEW_CON5 0x7a54
+#define AFE_GASRC8_NEW_CON6 0x7a58
+#define AFE_GASRC8_NEW_CON7 0x7a5c
+#define AFE_GASRC8_NEW_CON8 0x7a60
+#define AFE_GASRC8_NEW_CON9 0x7a64
+#define AFE_GASRC8_NEW_CON10 0x7a68
+#define AFE_GASRC8_NEW_CON11 0x7a6c
+#define AFE_GASRC8_NEW_CON12 0x7a70
+#define AFE_GASRC8_NEW_CON13 0x7a74
+#define AFE_GASRC8_NEW_CON14 0x7a78
+#define AFE_GASRC8_NEW_IP_VERSION 0x7a7c
+#define AFE_GASRC9_NEW_CON0 0x7a80
+#define AFE_GASRC9_NEW_CON1 0x7a84
+#define AFE_GASRC9_NEW_CON2 0x7a88
+#define AFE_GASRC9_NEW_CON3 0x7a8c
+#define AFE_GASRC9_NEW_CON4 0x7a90
+#define AFE_GASRC9_NEW_CON5 0x7a94
+#define AFE_GASRC9_NEW_CON6 0x7a98
+#define AFE_GASRC9_NEW_CON7 0x7a9c
+#define AFE_GASRC9_NEW_CON8 0x7aa0
+#define AFE_GASRC9_NEW_CON9 0x7aa4
+#define AFE_GASRC9_NEW_CON10 0x7aa8
+#define AFE_GASRC9_NEW_CON11 0x7aac
+#define AFE_GASRC9_NEW_CON12 0x7ab0
+#define AFE_GASRC9_NEW_CON13 0x7ab4
+#define AFE_GASRC9_NEW_CON14 0x7ab8
+#define AFE_GASRC9_NEW_IP_VERSION 0x7abc
+#define AFE_GASRC10_NEW_CON0 0x7ac0
+#define AFE_GASRC10_NEW_CON1 0x7ac4
+#define AFE_GASRC10_NEW_CON2 0x7ac8
+#define AFE_GASRC10_NEW_CON3 0x7acc
+#define AFE_GASRC10_NEW_CON4 0x7ad0
+#define AFE_GASRC10_NEW_CON5 0x7ad4
+#define AFE_GASRC10_NEW_CON6 0x7ad8
+#define AFE_GASRC10_NEW_CON7 0x7adc
+#define AFE_GASRC10_NEW_CON8 0x7ae0
+#define AFE_GASRC10_NEW_CON9 0x7ae4
+#define AFE_GASRC10_NEW_CON10 0x7ae8
+#define AFE_GASRC10_NEW_CON11 0x7aec
+#define AFE_GASRC10_NEW_CON12 0x7af0
+#define AFE_GASRC10_NEW_CON13 0x7af4
+#define AFE_GASRC10_NEW_CON14 0x7af8
+#define AFE_GASRC10_NEW_IP_VERSION 0x7afc
+#define AFE_GASRC11_NEW_CON0 0x7b00
+#define AFE_GASRC11_NEW_CON1 0x7b04
+#define AFE_GASRC11_NEW_CON2 0x7b08
+#define AFE_GASRC11_NEW_CON3 0x7b0c
+#define AFE_GASRC11_NEW_CON4 0x7b10
+#define AFE_GASRC11_NEW_CON5 0x7b14
+#define AFE_GASRC11_NEW_CON6 0x7b18
+#define AFE_GASRC11_NEW_CON7 0x7b1c
+#define AFE_GASRC11_NEW_CON8 0x7b20
+#define AFE_GASRC11_NEW_CON9 0x7b24
+#define AFE_GASRC11_NEW_CON10 0x7b28
+#define AFE_GASRC11_NEW_CON11 0x7b2c
+#define AFE_GASRC11_NEW_CON12 0x7b30
+#define AFE_GASRC11_NEW_CON13 0x7b34
+#define AFE_GASRC11_NEW_CON14 0x7b38
+#define AFE_GASRC11_NEW_IP_VERSION 0x7b3c
+#define AFE_GASRC12_NEW_CON0 0x7b40
+#define AFE_GASRC12_NEW_CON1 0x7b44
+#define AFE_GASRC12_NEW_CON2 0x7b48
+#define AFE_GASRC12_NEW_CON3 0x7b4c
+#define AFE_GASRC12_NEW_CON4 0x7b50
+#define AFE_GASRC12_NEW_CON5 0x7b54
+#define AFE_GASRC12_NEW_CON6 0x7b58
+#define AFE_GASRC12_NEW_CON7 0x7b5c
+#define AFE_GASRC12_NEW_CON8 0x7b60
+#define AFE_GASRC12_NEW_CON9 0x7b64
+#define AFE_GASRC12_NEW_CON10 0x7b68
+#define AFE_GASRC12_NEW_CON11 0x7b6c
+#define AFE_GASRC12_NEW_CON12 0x7b70
+#define AFE_GASRC12_NEW_CON13 0x7b74
+#define AFE_GASRC12_NEW_CON14 0x7b78
+#define AFE_GASRC12_NEW_IP_VERSION 0x7b7c
+#define AFE_GASRC13_NEW_CON0 0x7b80
+#define AFE_GASRC13_NEW_CON1 0x7b84
+#define AFE_GASRC13_NEW_CON2 0x7b88
+#define AFE_GASRC13_NEW_CON3 0x7b8c
+#define AFE_GASRC13_NEW_CON4 0x7b90
+#define AFE_GASRC13_NEW_CON5 0x7b94
+#define AFE_GASRC13_NEW_CON6 0x7b98
+#define AFE_GASRC13_NEW_CON7 0x7b9c
+#define AFE_GASRC13_NEW_CON8 0x7ba0
+#define AFE_GASRC13_NEW_CON9 0x7ba4
+#define AFE_GASRC13_NEW_CON10 0x7ba8
+#define AFE_GASRC13_NEW_CON11 0x7bac
+#define AFE_GASRC13_NEW_CON12 0x7bb0
+#define AFE_GASRC13_NEW_CON13 0x7bb4
+#define AFE_GASRC13_NEW_CON14 0x7bb8
+#define AFE_GASRC13_NEW_IP_VERSION 0x7bbc
+#define AFE_GASRC14_NEW_CON0 0x7bc0
+#define AFE_GASRC14_NEW_CON1 0x7bc4
+#define AFE_GASRC14_NEW_CON2 0x7bc8
+#define AFE_GASRC14_NEW_CON3 0x7bcc
+#define AFE_GASRC14_NEW_CON4 0x7bd0
+#define AFE_GASRC14_NEW_CON5 0x7bd4
+#define AFE_GASRC14_NEW_CON6 0x7bd8
+#define AFE_GASRC14_NEW_CON7 0x7bdc
+#define AFE_GASRC14_NEW_CON8 0x7be0
+#define AFE_GASRC14_NEW_CON9 0x7be4
+#define AFE_GASRC14_NEW_CON10 0x7be8
+#define AFE_GASRC14_NEW_CON11 0x7bec
+#define AFE_GASRC14_NEW_CON12 0x7bf0
+#define AFE_GASRC14_NEW_CON13 0x7bf4
+#define AFE_GASRC14_NEW_CON14 0x7bf8
+#define AFE_GASRC14_NEW_IP_VERSION 0x7bfc
+#define AFE_GASRC15_NEW_CON0 0x7c00
+#define AFE_GASRC15_NEW_CON1 0x7c04
+#define AFE_GASRC15_NEW_CON2 0x7c08
+#define AFE_GASRC15_NEW_CON3 0x7c0c
+#define AFE_GASRC15_NEW_CON4 0x7c10
+#define AFE_GASRC15_NEW_CON5 0x7c14
+#define AFE_GASRC15_NEW_CON6 0x7c18
+#define AFE_GASRC15_NEW_CON7 0x7c1c
+#define AFE_GASRC15_NEW_CON8 0x7c20
+#define AFE_GASRC15_NEW_CON9 0x7c24
+#define AFE_GASRC15_NEW_CON10 0x7c28
+#define AFE_GASRC15_NEW_CON11 0x7c2c
+#define AFE_GASRC15_NEW_CON12 0x7c30
+#define AFE_GASRC15_NEW_CON13 0x7c34
+#define AFE_GASRC15_NEW_CON14 0x7c38
+#define AFE_GASRC15_NEW_IP_VERSION 0x7c3c
+
+#define AFE_MAX_REGISTER AFE_GASRC15_NEW_IP_VERSION
+
+#define AFE_IRQ_STATUS_BITS 0x87FFFFFF
+#define AFE_IRQ_CNT_SHIFT 0
+#define AFE_IRQ_CNT_MASK 0xffffff
+#endif
+
diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c
index 7078c01ba19b..af96aa446fe2 100644
--- a/sound/soc/mediatek/mt8365/mt8365-afe-clk.c
+++ b/sound/soc/mediatek/mt8365/mt8365-afe-clk.c
@@ -194,16 +194,13 @@ int mt8365_afe_enable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
unsigned int reg = get_top_cg_reg(cg_type);
unsigned int mask = get_top_cg_mask(cg_type);
unsigned int val = get_top_cg_on_val(cg_type);
- unsigned long flags;
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock);
afe_priv->top_cg_ref_cnt[cg_type]++;
if (afe_priv->top_cg_ref_cnt[cg_type] == 1)
regmap_update_bits(afe->regmap, reg, mask, val);
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
-
return 0;
}
@@ -213,9 +210,8 @@ int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
unsigned int reg = get_top_cg_reg(cg_type);
unsigned int mask = get_top_cg_mask(cg_type);
unsigned int val = get_top_cg_off_val(cg_type);
- unsigned long flags;
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock);
afe_priv->top_cg_ref_cnt[cg_type]--;
if (afe_priv->top_cg_ref_cnt[cg_type] == 0)
@@ -223,8 +219,6 @@ int mt8365_afe_disable_top_cg(struct mtk_base_afe *afe, unsigned int cg_type)
else if (afe_priv->top_cg_ref_cnt[cg_type] < 0)
afe_priv->top_cg_ref_cnt[cg_type] = 0;
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
-
return 0;
}
@@ -263,25 +257,21 @@ int mt8365_afe_emi_clk_off(struct mtk_base_afe *afe)
int mt8365_afe_enable_afe_on(struct mtk_base_afe *afe)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
- unsigned long flags;
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock);
afe_priv->afe_on_ref_cnt++;
if (afe_priv->afe_on_ref_cnt == 1)
regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
-
return 0;
}
int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe)
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
- unsigned long flags;
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock);
afe_priv->afe_on_ref_cnt--;
if (afe_priv->afe_on_ref_cnt == 0)
@@ -289,8 +279,6 @@ int mt8365_afe_disable_afe_on(struct mtk_base_afe *afe)
else if (afe_priv->afe_on_ref_cnt < 0)
afe_priv->afe_on_ref_cnt = 0;
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
-
return 0;
}
@@ -322,13 +310,11 @@ int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
- mutex_lock(&afe_priv->afe_clk_mutex);
+ guard(mutex)(&afe_priv->afe_clk_mutex);
afe_priv->apll_tuner_ref_cnt[apll]++;
- if (afe_priv->apll_tuner_ref_cnt[apll] != 1) {
- mutex_unlock(&afe_priv->afe_clk_mutex);
+ if (afe_priv->apll_tuner_ref_cnt[apll] != 1)
return 0;
- }
if (apll == MT8365_AFE_APLL1) {
regmap_update_bits(afe->regmap, AFE_APLL_TUNER_CFG,
@@ -342,7 +328,6 @@ int mt8365_afe_enable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apll
AFE_APLL_TUNER_CFG1_EN_MASK, 0x1);
}
- mutex_unlock(&afe_priv->afe_clk_mutex);
return 0;
}
@@ -350,7 +335,7 @@ int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apl
{
struct mt8365_afe_private *afe_priv = afe->platform_priv;
- mutex_lock(&afe_priv->afe_clk_mutex);
+ guard(mutex)(&afe_priv->afe_clk_mutex);
afe_priv->apll_tuner_ref_cnt[apll]--;
if (afe_priv->apll_tuner_ref_cnt[apll] == 0) {
@@ -365,7 +350,6 @@ int mt8365_afe_disable_apll_tuner_cfg(struct mtk_base_afe *afe, unsigned int apl
afe_priv->apll_tuner_ref_cnt[apll] = 0;
}
- mutex_unlock(&afe_priv->afe_clk_mutex);
return 0;
}
diff --git a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c
index d01793394f22..5966ca18c7c9 100644
--- a/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c
+++ b/sound/soc/mediatek/mt8365/mt8365-afe-pcm.c
@@ -1974,10 +1974,15 @@ static int mt8365_afe_suspend(struct device *dev)
mt8365_afe_enable_main_clk(afe);
- if (!afe->reg_back_up)
+ if (!afe->reg_back_up) {
afe->reg_back_up =
devm_kcalloc(dev, afe->reg_back_up_list_num,
sizeof(unsigned int), GFP_KERNEL);
+ if (!afe->reg_back_up) {
+ mt8365_afe_disable_main_clk(afe);
+ return -ENOMEM;
+ }
+ }
for (i = 0; i < afe->reg_back_up_list_num; i++)
regmap_read(regmap, afe->reg_back_up_list[i],
@@ -2011,11 +2016,15 @@ static int mt8365_afe_resume(struct device *dev)
static int mt8365_afe_dev_runtime_suspend(struct device *dev)
{
struct mtk_base_afe *afe = dev_get_drvdata(dev);
+ int ret;
if (pm_runtime_status_suspended(dev) || afe->suspended)
return 0;
- mt8365_afe_suspend(dev);
+ ret = mt8365_afe_suspend(dev);
+ if (ret)
+ return ret;
+
afe->suspended = true;
return 0;
}
diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-adda.c b/sound/soc/mediatek/mt8365/mt8365-dai-adda.c
index a04c24bbfcff..d8eda9e17eb8 100644
--- a/sound/soc/mediatek/mt8365/mt8365-dai-adda.c
+++ b/sound/soc/mediatek/mt8365/mt8365-dai-adda.c
@@ -63,10 +63,9 @@ static int mt8365_dai_set_adda_in(struct mtk_base_afe *afe, unsigned int rate)
int mt8365_dai_enable_adda_on(struct mtk_base_afe *afe)
{
- unsigned long flags;
struct mt8365_afe_private *afe_priv = afe->platform_priv;
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock);
adda_afe_on_ref_cnt++;
if (adda_afe_on_ref_cnt == 1)
@@ -74,17 +73,14 @@ int mt8365_dai_enable_adda_on(struct mtk_base_afe *afe)
AFE_ADDA_UL_DL_ADDA_AFE_ON,
AFE_ADDA_UL_DL_ADDA_AFE_ON);
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
-
return 0;
}
int mt8365_dai_disable_adda_on(struct mtk_base_afe *afe)
{
- unsigned long flags;
struct mt8365_afe_private *afe_priv = afe->platform_priv;
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock);
adda_afe_on_ref_cnt--;
if (adda_afe_on_ref_cnt == 0)
@@ -96,8 +92,6 @@ int mt8365_dai_disable_adda_on(struct mtk_base_afe *afe)
dev_warn(afe->dev, "Abnormal adda_on ref count. Force it to 0\n");
}
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
-
return 0;
}
diff --git a/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c
index cb9beb172ed5..a058973662b3 100644
--- a/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c
+++ b/sound/soc/mediatek/mt8365/mt8365-dai-i2s.c
@@ -463,7 +463,6 @@ static int mt8365_afe_set_2nd_i2s_asrc_enable(struct mtk_base_afe *afe,
void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable)
{
int i;
- unsigned long flags;
struct mt8365_afe_private *afe_priv = afe->platform_priv;
struct mtk_afe_i2s_priv *i2s_data = NULL;
@@ -475,7 +474,7 @@ void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable)
if (!i2s_data)
return;
- spin_lock_irqsave(&afe_priv->afe_ctrl_lock, flags);
+ guard(spinlock_irqsave)(&afe_priv->afe_ctrl_lock);
if (enable) {
i2s_data->i2s_out_on_ref_cnt++;
@@ -490,8 +489,6 @@ void mt8365_afe_set_i2s_out_enable(struct mtk_base_afe *afe, bool enable)
else if (i2s_data->i2s_out_on_ref_cnt < 0)
i2s_data->i2s_out_on_ref_cnt = 0;
}
-
- spin_unlock_irqrestore(&afe_priv->afe_ctrl_lock, flags);
}
static void mt8365_dai_set_enable(struct mtk_base_afe *afe,
diff --git a/sound/soc/mediatek/mt8365/mt8365-mt6357.c b/sound/soc/mediatek/mt8365/mt8365-mt6357.c
index a998fba82bfe..90448df6c0b2 100644
--- a/sound/soc/mediatek/mt8365/mt8365-mt6357.c
+++ b/sound/soc/mediatek/mt8365/mt8365-mt6357.c
@@ -9,7 +9,6 @@
#include <linux/array_size.h>
#include <linux/dev_printk.h>
#include <linux/err.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pinctrl/consumer.h>
#include <linux/platform_device.h>
@@ -247,26 +246,26 @@ static struct snd_soc_dai_link mt8365_mt6357_dais[] = {
static int mt8365_mt6357_gpio_probe(struct snd_soc_card *card)
{
struct mt8365_mt6357_priv *priv = snd_soc_card_get_drvdata(card);
+ struct device *dev = card->dev;
int ret, i;
- priv->pinctrl = devm_pinctrl_get(card->dev);
+ priv->pinctrl = devm_pinctrl_get(dev);
if (IS_ERR(priv->pinctrl)) {
ret = PTR_ERR(priv->pinctrl);
- return dev_err_probe(card->dev, ret,
- "Failed to get pinctrl\n");
+ return dev_err_probe(dev, ret, "Failed to get pinctrl\n");
}
for (i = PIN_STATE_DEFAULT ; i < PIN_STATE_MAX ; i++) {
priv->pin_states[i] = pinctrl_lookup_state(priv->pinctrl,
mt8365_mt6357_pin_str[i]);
if (IS_ERR(priv->pin_states[i])) {
- dev_info(card->dev, "No pin state for %s\n",
+ dev_info(dev, "No pin state for %s\n",
mt8365_mt6357_pin_str[i]);
} else {
ret = pinctrl_select_state(priv->pinctrl,
priv->pin_states[i]);
if (ret) {
- dev_err_probe(card->dev, ret,
+ dev_err_probe(dev, ret,
"Failed to select pin state %s\n",
mt8365_mt6357_pin_str[i]);
return ret;
diff --git a/sound/soc/meson/aiu-acodec-ctrl.c b/sound/soc/meson/aiu-acodec-ctrl.c
index 483772ba69cd..94c5d6533523 100644
--- a/sound/soc/meson/aiu-acodec-ctrl.c
+++ b/sound/soc/meson/aiu-acodec-ctrl.c
@@ -36,6 +36,9 @@ static int aiu_acodec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol,
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int mux, changed;
+ if (ucontrol->value.enumerated.item[0] >= e->items)
+ return -EINVAL;
+
mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
changed = snd_soc_component_test_bits(component, e->reg,
CTRL_DIN_LRCLK_SRC,
diff --git a/sound/soc/meson/aiu-codec-ctrl.c b/sound/soc/meson/aiu-codec-ctrl.c
index 396f815077e2..60bb4cdfee52 100644
--- a/sound/soc/meson/aiu-codec-ctrl.c
+++ b/sound/soc/meson/aiu-codec-ctrl.c
@@ -28,6 +28,9 @@ static int aiu_codec_ctrl_mux_put_enum(struct snd_kcontrol *kcontrol,
struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
unsigned int mux, changed;
+ if (ucontrol->value.enumerated.item[0] >= e->items)
+ return -EINVAL;
+
mux = snd_soc_enum_item_to_val(e, ucontrol->value.enumerated.item[0]);
changed = snd_soc_component_test_bits(component, e->reg,
CTRL_DATA_SEL,
diff --git a/sound/soc/meson/axg-tdm-formatter.c b/sound/soc/meson/axg-tdm-formatter.c
index f451e4dce442..a6ba401104d5 100644
--- a/sound/soc/meson/axg-tdm-formatter.c
+++ b/sound/soc/meson/axg-tdm-formatter.c
@@ -157,20 +157,19 @@ static int axg_tdm_formatter_attach(struct axg_tdm_formatter *formatter)
struct axg_tdm_stream *ts = formatter->stream;
int ret = 0;
- mutex_lock(&ts->lock);
+ guard(mutex)(&ts->lock);
/* Catch up if the stream is already running when we attach */
if (ts->ready) {
ret = axg_tdm_formatter_enable(formatter);
if (ret) {
pr_err("failed to enable formatter\n");
- goto out;
+ return ret;
}
}
list_add_tail(&formatter->list, &ts->formatter_list);
-out:
- mutex_unlock(&ts->lock);
+
return ret;
}
@@ -178,9 +177,8 @@ static void axg_tdm_formatter_dettach(struct axg_tdm_formatter *formatter)
{
struct axg_tdm_stream *ts = formatter->stream;
- mutex_lock(&ts->lock);
- list_del(&formatter->list);
- mutex_unlock(&ts->lock);
+ scoped_guard(mutex, &ts->lock)
+ list_del(&formatter->list);
axg_tdm_formatter_disable(formatter);
}
@@ -330,7 +328,7 @@ int axg_tdm_stream_start(struct axg_tdm_stream *ts)
struct axg_tdm_formatter *formatter;
int ret = 0;
- mutex_lock(&ts->lock);
+ guard(mutex)(&ts->lock);
ts->ready = true;
/* Start all the formatters attached to the stream */
@@ -338,12 +336,10 @@ int axg_tdm_stream_start(struct axg_tdm_stream *ts)
ret = axg_tdm_formatter_enable(formatter);
if (ret) {
pr_err("failed to start tdm stream\n");
- goto out;
+ return ret;
}
}
-out:
- mutex_unlock(&ts->lock);
return ret;
}
EXPORT_SYMBOL_GPL(axg_tdm_stream_start);
@@ -352,15 +348,13 @@ void axg_tdm_stream_stop(struct axg_tdm_stream *ts)
{
struct axg_tdm_formatter *formatter;
- mutex_lock(&ts->lock);
+ guard(mutex)(&ts->lock);
ts->ready = false;
/* Stop all the formatters attached to the stream */
list_for_each_entry(formatter, &ts->formatter_list, list) {
axg_tdm_formatter_disable(formatter);
}
-
- mutex_unlock(&ts->lock);
}
EXPORT_SYMBOL_GPL(axg_tdm_stream_stop);
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 4bd14ae330d5..2788514be6b1 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -54,4 +54,10 @@ config SND_PXA910_SOC
Say Y if you want to add support for SoC audio on the
Marvell PXA910 reference platform.
+config SND_PXA2XX_LIB
+ tristate
+ select SND_DMAENGINE_PCM
+
+config SND_PXA2XX_LIB_AC97
+ bool
endmenu
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 93b4e57eaa5c..bf504a85657c 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -1,8 +1,9 @@
# SPDX-License-Identifier: GPL-2.0
# PXA Platform Support
snd-soc-pxa2xx-y := pxa2xx-pcm.o
-snd-soc-pxa2xx-ac97-y := pxa2xx-ac97.o
+snd-soc-pxa2xx-ac97-y := pxa2xx-ac97.o pxa2xx-ac97-lib.o
snd-soc-pxa2xx-i2s-y := pxa2xx-i2s.o
+snd-soc-pxa2xx-lib-y := pxa2xx-pcm-lib.o
snd-soc-pxa-ssp-y := pxa-ssp.o
snd-soc-mmp-sspa-y := mmp-sspa.o
@@ -11,6 +12,7 @@ obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
obj-$(CONFIG_SND_MMP_SOC_SSPA) += snd-soc-mmp-sspa.o
+obj-$(CONFIG_SND_PXA2XX_LIB) += snd-soc-pxa2xx-lib.o
# PXA Machine Support
snd-soc-spitz-y := spitz.o
diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c
index 73f36c9dd35c..fbbce81680cf 100644
--- a/sound/soc/pxa/mmp-sspa.c
+++ b/sound/soc/pxa/mmp-sspa.c
@@ -20,8 +20,8 @@
#include <sound/initval.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
+#include "pxa2xx-lib.h"
#include "mmp-sspa.h"
/*
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 37bd8dbd541f..f8054c1c59fa 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -27,9 +27,9 @@
#include <sound/initval.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
+#include "pxa2xx-lib.h"
#include "pxa-ssp.h"
/*
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/soc/pxa/pxa2xx-ac97-lib.c
index 79eb557d4942..d9c3935636da 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/soc/pxa/pxa2xx-ac97-lib.c
@@ -23,13 +23,13 @@
#include <linux/platform_data/asoc-pxa.h>
#include "pxa2xx-ac97-regs.h"
+#include "pxa2xx-lib.h"
static DEFINE_MUTEX(car_mutex);
static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
static volatile long gsr_bits;
static struct clk *ac97_clk;
static struct clk *ac97conf_clk;
-static int reset_gpio;
struct gpio_desc *rst_gpio;
static void __iomem *ac97_reg_base;
@@ -83,7 +83,6 @@ int pxa2xx_ac97_read(int slot, unsigned short reg)
wait_event_timeout(gsr_wq, (readl(ac97_reg_base + GSR) | gsr_bits) & GSR_SDONE, 1);
return val;
}
-EXPORT_SYMBOL_GPL(pxa2xx_ac97_read);
int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val)
{
@@ -113,7 +112,6 @@ int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val)
return ret;
}
-EXPORT_SYMBOL_GPL(pxa2xx_ac97_write);
#ifdef CONFIG_PXA25x
static inline void pxa_ac97_warm_pxa25x(void)
@@ -140,10 +138,10 @@ static inline void pxa_ac97_warm_pxa27x(void)
gsr_bits = 0;
/* warm reset broken on Bulverde, so manually keep AC97 reset high */
- pxa27x_configure_ac97reset(reset_gpio, true);
+ pxa27x_configure_ac97reset(rst_gpio, true);
udelay(10);
writel(readl(ac97_reg_base + GCR) | (GCR_WARM_RST), ac97_reg_base + GCR);
- pxa27x_configure_ac97reset(reset_gpio, false);
+ pxa27x_configure_ac97reset(rst_gpio, false);
udelay(500);
}
@@ -226,7 +224,6 @@ bool pxa2xx_ac97_try_warm_reset(void)
return true;
}
-EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_warm_reset);
bool pxa2xx_ac97_try_cold_reset(void)
{
@@ -263,7 +260,6 @@ bool pxa2xx_ac97_try_cold_reset(void)
return true;
}
-EXPORT_SYMBOL_GPL(pxa2xx_ac97_try_cold_reset);
void pxa2xx_ac97_finish_reset(void)
@@ -273,7 +269,6 @@ void pxa2xx_ac97_finish_reset(void)
gcr |= GCR_SDONE_IE|GCR_CDONE_IE;
writel(gcr, ac97_reg_base + GCR);
}
-EXPORT_SYMBOL_GPL(pxa2xx_ac97_finish_reset);
static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
{
@@ -307,14 +302,12 @@ int pxa2xx_ac97_hw_suspend(void)
clk_disable_unprepare(ac97_clk);
return 0;
}
-EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_suspend);
int pxa2xx_ac97_hw_resume(void)
{
clk_prepare_enable(ac97_clk);
return 0;
}
-EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_resume);
#endif
int pxa2xx_ac97_hw_probe(struct platform_device *dev)
@@ -328,24 +321,14 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
return PTR_ERR(ac97_reg_base);
}
- if (dev->dev.of_node) {
+ if (cpu_is_pxa27x()) {
/* Assert reset using GPIOD_OUT_HIGH, because reset is GPIO_ACTIVE_LOW */
- rst_gpio = devm_gpiod_get(&dev->dev, "reset", GPIOD_OUT_HIGH);
- if (IS_ERR(rst_gpio)) {
- ret = PTR_ERR(rst_gpio);
- if (ret == -ENOENT)
- reset_gpio = -1;
- else if (ret)
- return ret;
- } else {
- reset_gpio = desc_to_gpio(rst_gpio);
- }
- } else {
- if (cpu_is_pxa27x())
- reset_gpio = 113;
- }
+ rst_gpio = devm_gpiod_get_optional(&dev->dev, "reset",
+ GPIOD_OUT_HIGH);
+ if (IS_ERR(rst_gpio))
+ return dev_err_probe(&dev->dev, PTR_ERR(rst_gpio),
+ "reset gpio failed\n");
- if (cpu_is_pxa27x()) {
/*
* This gpio is needed for a work-around to a bug in the ac97
* controller during warm reset. The direction and level is set
@@ -353,7 +336,7 @@ int pxa2xx_ac97_hw_probe(struct platform_device *dev)
* AC97_nRESET alt function to generic gpio.
*/
gpiod_set_consumer_name(rst_gpio, "pxa27x ac97 reset");
- pxa27x_configure_ac97reset(reset_gpio, false);
+ pxa27x_configure_ac97reset(rst_gpio, false);
ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
if (IS_ERR(ac97conf_clk)) {
@@ -399,7 +382,6 @@ err_clk:
err_conf:
return ret;
}
-EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_probe);
void pxa2xx_ac97_hw_remove(struct platform_device *dev)
{
@@ -413,7 +395,6 @@ void pxa2xx_ac97_hw_remove(struct platform_device *dev)
clk_put(ac97_clk);
ac97_clk = NULL;
}
-EXPORT_SYMBOL_GPL(pxa2xx_ac97_hw_remove);
u32 pxa2xx_ac97_read_modr(void)
{
diff --git a/sound/arm/pxa2xx-ac97-regs.h b/sound/soc/pxa/pxa2xx-ac97-regs.h
index ae638a1b919b..ae638a1b919b 100644
--- a/sound/arm/pxa2xx-ac97-regs.h
+++ b/sound/soc/pxa/pxa2xx-ac97-regs.h
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index a0c672602918..7b9036947dfc 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -18,11 +18,12 @@
#include <sound/core.h>
#include <sound/ac97_codec.h>
#include <sound/soc.h>
-#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
#include <linux/platform_data/asoc-pxa.h>
+#include "pxa2xx-lib.h"
+
#define PCDR 0x0040 /* PCM FIFO Data Register */
#define MODR 0x0140 /* Modem FIFO Data Register */
#define MCDR 0x0060 /* Mic-in FIFO Data Register */
@@ -246,8 +247,7 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
}
ctrl = snd_ac97_controller_register(&pxa2xx_ac97_ops, &pdev->dev,
- AC97_SLOTS_AVAILABLE_ALL,
- NULL);
+ AC97_SLOTS_AVAILABLE_ALL);
if (IS_ERR(ctrl))
return PTR_ERR(ctrl);
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index f6ada6cffc88..fe1df78926f5 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -18,11 +18,11 @@
#include <sound/pcm.h>
#include <sound/initval.h>
#include <sound/soc.h>
-#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
#include <linux/platform_data/asoc-pxa.h>
+#include "pxa2xx-lib.h"
#include "pxa2xx-i2s.h"
/*
diff --git a/sound/soc/pxa/pxa2xx-lib.h b/sound/soc/pxa/pxa2xx-lib.h
new file mode 100644
index 000000000000..3a9d6ac8d367
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-lib.h
@@ -0,0 +1,45 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __PXA2XX_LIB_H
+#define __PXA2XX_LIB_H
+
+#include <uapi/sound/asound.h>
+#include <linux/platform_device.h>
+
+/* PCM */
+struct snd_pcm_substream;
+struct snd_pcm_hw_params;
+struct snd_soc_pcm_runtime;
+struct snd_pcm;
+struct snd_soc_component;
+
+int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
+ struct snd_soc_pcm_runtime *rtd);
+int pxa2xx_soc_pcm_open(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream);
+int pxa2xx_soc_pcm_close(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream);
+int pxa2xx_soc_pcm_hw_params(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params);
+int pxa2xx_soc_pcm_prepare(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream);
+int pxa2xx_soc_pcm_trigger(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream, int cmd);
+snd_pcm_uframes_t pxa2xx_soc_pcm_pointer(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream);
+
+/* AC97 */
+int pxa2xx_ac97_read(int slot, unsigned short reg);
+int pxa2xx_ac97_write(int slot, unsigned short reg, unsigned short val);
+
+bool pxa2xx_ac97_try_warm_reset(void);
+bool pxa2xx_ac97_try_cold_reset(void);
+void pxa2xx_ac97_finish_reset(void);
+
+int pxa2xx_ac97_hw_suspend(void);
+int pxa2xx_ac97_hw_resume(void);
+
+int pxa2xx_ac97_hw_probe(struct platform_device *dev);
+void pxa2xx_ac97_hw_remove(struct platform_device *dev);
+
+#endif
diff --git a/sound/arm/pxa2xx-pcm-lib.c b/sound/soc/pxa/pxa2xx-pcm-lib.c
index 571e9d909cdf..88a9d3226302 100644
--- a/sound/arm/pxa2xx-pcm-lib.c
+++ b/sound/soc/pxa/pxa2xx-pcm-lib.c
@@ -9,9 +9,10 @@
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
-#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
+#include "pxa2xx-lib.h"
+
static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -29,8 +30,8 @@ static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
.fifo_size = 32,
};
-int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
+static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
{
struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
@@ -56,28 +57,24 @@ int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-EXPORT_SYMBOL(pxa2xx_pcm_hw_params);
-int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
return snd_dmaengine_pcm_trigger(substream, cmd);
}
-EXPORT_SYMBOL(pxa2xx_pcm_trigger);
-snd_pcm_uframes_t
+static snd_pcm_uframes_t
pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
{
return snd_dmaengine_pcm_pointer(substream);
}
-EXPORT_SYMBOL(pxa2xx_pcm_pointer);
-int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
+static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
{
return 0;
}
-EXPORT_SYMBOL(pxa2xx_pcm_prepare);
-int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
+static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -114,22 +111,19 @@ int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
substream, dma_request_slave_channel(snd_soc_rtd_to_cpu(rtd, 0)->dev,
dma_params->chan_name));
}
-EXPORT_SYMBOL(pxa2xx_pcm_open);
-int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
+static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
{
return snd_dmaengine_pcm_close_release_chan(substream);
}
-EXPORT_SYMBOL(pxa2xx_pcm_close);
-int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm)
+static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm)
{
size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
return snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV_WC,
pcm->card->dev, size);
}
-EXPORT_SYMBOL(pxa2xx_pcm_preallocate_dma_buffer);
int pxa2xx_soc_pcm_new(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd)
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index ff0fbb61dccd..71b7bd948b5e 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -14,9 +14,10 @@
#include <sound/core.h>
#include <sound/soc.h>
-#include <sound/pxa2xx-lib.h>
#include <sound/dmaengine_pcm.h>
+#include "pxa2xx-lib.h"
+
static const struct snd_soc_component_driver pxa2xx_soc_platform = {
.pcm_new = pxa2xx_soc_pcm_new,
.open = pxa2xx_soc_pcm_open,
diff --git a/sound/soc/qcom/apq8096.c b/sound/soc/qcom/apq8096.c
index 4f6594cc723c..cfd6438dbcb3 100644
--- a/sound/soc/qcom/apq8096.c
+++ b/sound/soc/qcom/apq8096.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
// Copyright (c) 2018, Linaro Limited
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/soc.h>
diff --git a/sound/soc/qcom/common.c b/sound/soc/qcom/common.c
index cf1f3a767cee..edc4611691f7 100644
--- a/sound/soc/qcom/common.c
+++ b/sound/soc/qcom/common.c
@@ -25,10 +25,6 @@ static const struct snd_soc_dapm_widget qcom_jack_snd_widgets[] = {
int qcom_snd_parse_of(struct snd_soc_card *card)
{
- struct device_node *np;
- struct device_node *codec = NULL;
- struct device_node *platform = NULL;
- struct device_node *cpu = NULL;
struct device *dev = card->dev;
struct snd_soc_dai_link *link;
struct of_phandle_args args;
@@ -82,12 +78,10 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
card->num_links = num_links;
link = card->dai_link;
- for_each_available_child_of_node(dev->of_node, np) {
+ for_each_available_child_of_node_scoped(dev->of_node, np) {
dlc = devm_kcalloc(dev, 2, sizeof(*dlc), GFP_KERNEL);
- if (!dlc) {
- ret = -ENOMEM;
- goto err_put_np;
- }
+ if (!dlc)
+ return -ENOMEM;
link->cpus = &dlc[0];
link->platforms = &dlc[1];
@@ -98,32 +92,33 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
ret = of_property_read_string(np, "link-name", &link->name);
if (ret) {
dev_err(card->dev, "error getting codec dai_link name\n");
- goto err_put_np;
+ return ret;
}
- cpu = of_get_child_by_name(np, "cpu");
- platform = of_get_child_by_name(np, "platform");
- codec = of_get_child_by_name(np, "codec");
+ struct device_node *cpu __free(device_node) =
+ of_get_child_by_name(np, "cpu");
+ struct device_node *platform __free(device_node) =
+ of_get_child_by_name(np, "platform");
+ struct device_node *codec __free(device_node) =
+ of_get_child_by_name(np, "codec");
if (!cpu) {
dev_err(dev, "%s: Can't find cpu DT node\n", link->name);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
ret = snd_soc_of_get_dlc(cpu, &args, link->cpus, 0);
if (ret) {
dev_err_probe(card->dev, ret,
"%s: error getting cpu dai name\n", link->name);
- goto err;
+ return ret;
}
link->id = args.args[0];
if (link->id >= LPASS_MAX_PORT) {
dev_err(dev, "%s: Invalid cpu dai id %d\n", link->name, link->id);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
if (platform) {
@@ -132,8 +127,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
0);
if (!link->platforms->of_node) {
dev_err(card->dev, "%s: platform dai not found\n", link->name);
- ret = -EINVAL;
- goto err;
+ return -EINVAL;
}
} else {
link->platforms->of_node = link->cpus->of_node;
@@ -144,7 +138,7 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
if (ret < 0) {
dev_err_probe(card->dev, ret,
"%s: codec dai not found\n", link->name);
- goto err;
+ return ret;
}
if (platform) {
@@ -167,10 +161,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
link->stream_name = link->name;
link++;
-
- of_node_put(cpu);
- of_node_put(codec);
- of_node_put(platform);
}
if (!card->dapm_widgets) {
@@ -179,13 +169,6 @@ int qcom_snd_parse_of(struct snd_soc_card *card)
}
return 0;
-err:
- of_node_put(cpu);
- of_node_put(codec);
- of_node_put(platform);
-err_put_np:
- of_node_put(np);
- return ret;
}
EXPORT_SYMBOL_GPL(qcom_snd_parse_of);
diff --git a/sound/soc/qcom/qdsp6/audioreach.c b/sound/soc/qcom/qdsp6/audioreach.c
index a13f753eff98..e6e9eb2e85aa 100644
--- a/sound/soc/qcom/qdsp6/audioreach.c
+++ b/sound/soc/qcom/qdsp6/audioreach.c
@@ -955,7 +955,7 @@ int audioreach_compr_set_param(struct q6apm_graph *graph,
struct media_format *header;
int rc;
void *p;
- int iid = q6apm_graph_get_rx_shmem_module_iid(graph);
+ int iid = graph->shm_iid;
int payload_size = sizeof(struct apm_sh_module_media_fmt_cmd);
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(payload_size,
@@ -1118,6 +1118,42 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
return q6apm_send_cmd_sync(graph->apm, pkt, 0);
}
+int audioreach_shmem_register_event(struct q6apm_graph *graph, int bytes, int num_levels)
+{
+ struct apm_module_register_events *event;
+ struct event_cfg_sh_mem_pull_push_mode_watermark_t *level;
+ int i, payload_size;
+ struct gpr_pkt *pkt __free(kfree) = NULL;
+ void *p;
+
+ if (num_levels <= 0 || bytes <= 0)
+ return -EINVAL;
+
+ payload_size = sizeof(*event) + sizeof(*level) + num_levels * sizeof(uint32_t);
+
+ pkt = audioreach_alloc_cmd_pkt(payload_size, APM_CMD_REGISTER_MODULE_EVENTS, 0,
+ graph->port->id, graph->shm_iid);
+ if (IS_ERR(pkt))
+ return PTR_ERR(pkt);
+
+ p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
+
+ event = p;
+ event->module_instance_id = graph->shm_iid;
+ event->event_id = EVENT_ID_SH_MEM_PULL_PUSH_MODE_WATERMARK;
+ event->is_register = 1;
+ event->event_config_payload_size = sizeof(*level) + num_levels * sizeof(uint32_t);
+ p += sizeof(*event);
+ level = p;
+ level->num_water_mark_levels = num_levels;
+
+ for (i = 0; i < num_levels; i++)
+ level->level[i] = (i + 1) * bytes;
+
+ return audioreach_graph_send_cmd_sync(graph, pkt, 0);
+}
+EXPORT_SYMBOL_GPL(audioreach_shmem_register_event);
+
static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
const struct audioreach_module *module,
const struct audioreach_module_config *mcfg)
@@ -1342,6 +1378,7 @@ int audioreach_set_media_format(struct q6apm_graph *graph,
rc = audioreach_i2s_set_media_format(graph, module, cfg);
break;
case MODULE_ID_WR_SHARED_MEM_EP:
+ case MODULE_ID_SH_MEM_PULL_MODE:
rc = audioreach_shmem_set_media_format(graph, module, cfg);
break;
case MODULE_ID_GAIN:
@@ -1401,10 +1438,48 @@ void audioreach_graph_free_buf(struct q6apm_graph *graph)
}
EXPORT_SYMBOL_GPL(audioreach_graph_free_buf);
+int audioreach_setup_push_pull(struct q6apm_graph *graph, phys_addr_t bphys,
+ phys_addr_t pphys, uint32_t mem_map_handle,
+ uint32_t pos_buf_mem_map_handle, uint32_t size)
+{
+ struct param_id_sh_mem_pull_push_mode_cfg *cfg;
+ struct apm_module_param_data *param_data;
+ int payload_size;
+ struct gpr_pkt *pkt __free(kfree) = NULL;
+ void *p;
+
+ payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE;
+ pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
+ if (IS_ERR(pkt))
+ return PTR_ERR(pkt);
+
+ p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
+
+ param_data = p;
+ param_data->module_instance_id = graph->shm_iid;
+ param_data->error_code = 0;
+ param_data->param_id = PARAM_ID_SH_MEM_PULL_PUSH_MODE_CFG;
+ param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
+
+ p = p + APM_MODULE_PARAM_DATA_SIZE;
+ cfg = p;
+
+ cfg->shared_circ_buf_addr_lsw = lower_32_bits(bphys);
+ cfg->shared_circ_buf_addr_msw = upper_32_bits(bphys);
+ cfg->shared_circ_buf_size = size;
+ cfg->circ_buf_mem_map_handle = mem_map_handle;
+ cfg->shared_pos_buf_addr_lsw = lower_32_bits(pphys);
+ cfg->shared_pos_buf_addr_msw = upper_32_bits(pphys);
+ cfg->pos_buf_mem_map_handle = pos_buf_mem_map_handle;
+
+ return q6apm_send_cmd_sync(graph->apm, pkt, 0);
+}
+EXPORT_SYMBOL_GPL(audioreach_setup_push_pull);
+
int audioreach_shared_memory_send_eos(struct q6apm_graph *graph)
{
struct data_cmd_wr_sh_mem_ep_eos *eos;
- int iid = q6apm_graph_get_rx_shmem_module_iid(graph);
+ int iid = graph->shm_iid;
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*eos),
DATA_CMD_WR_SH_MEM_EP_EOS, 0, graph->port->id, iid);
if (IS_ERR(pkt))
diff --git a/sound/soc/qcom/qdsp6/audioreach.h b/sound/soc/qcom/qdsp6/audioreach.h
index 6859770b38a6..62a2fd79bbcb 100644
--- a/sound/soc/qcom/qdsp6/audioreach.h
+++ b/sound/soc/qcom/qdsp6/audioreach.h
@@ -16,6 +16,8 @@ struct q6apm_graph;
#define MODULE_ID_PCM_CNV 0x07001003
#define MODULE_ID_PCM_ENC 0x07001004
#define MODULE_ID_PCM_DEC 0x07001005
+#define MODULE_ID_SH_MEM_PULL_MODE 0x07001006
+#define MODULE_ID_SH_MEM_PUSH_MODE 0x07001007
#define MODULE_ID_PLACEHOLDER_ENCODER 0x07001008
#define MODULE_ID_PLACEHOLDER_DECODER 0x07001009
#define MODULE_ID_I2S_SINK 0x0700100A
@@ -60,10 +62,57 @@ struct q6apm_graph;
#define APM_CMD_GET_CFG 0x01001007
#define APM_CMD_SHARED_MEM_MAP_REGIONS 0x0100100C
#define APM_CMD_SHARED_MEM_UNMAP_REGIONS 0x0100100D
+#define APM_CMD_REGISTER_MODULE_EVENTS 0x0100100E
+#define APM_EVENT_MODULE_TO_CLIENT 0x03001000
#define APM_CMD_RSP_SHARED_MEM_MAP_REGIONS 0x02001001
+#define APM_MMAP_TOKEN_GID_MASK GENMASK(15, 0)
+#define APM_MMAP_TOKEN_MAP_TYPE_POS_BUF BIT(16)
+#define APM_MMAP_TOKEN_MAP_TYPE_SHIFT 16
#define APM_CMD_RSP_GET_CFG 0x02001000
#define APM_CMD_CLOSE_ALL 0x01001013
#define APM_CMD_REGISTER_SHARED_CFG 0x0100100A
+#define EVENT_ID_SH_MEM_PULL_PUSH_MODE_WATERMARK 0x0800101C
+
+/**
+ * struct event_cfg_sh_mem_pull_push_mode_watermark_t - Watermark config
+ * @num_water_mark_levels: Number of watermark levels.
+ * @level: Watermark levels.
+ *
+ * If @num_water_mark_levels is zero, no watermark levels are specified
+ * and watermark events are not supported.
+ */
+struct event_cfg_sh_mem_pull_push_mode_watermark_t {
+ uint32_t num_water_mark_levels;
+ uint32_t level[];
+} __packed;
+
+/**
+ * struct apm_module_register_events - Register or unregister module events
+ * @module_instance_id: Module instance identifier.
+ * @event_id: Module event identifier.
+ * @is_register: 1 to register the event, 0 to unregister it.
+ * @error_code: Error code for out-of-band command mode.
+ * @event_config_payload_size: Event configuration payload size in bytes.
+ * @reserved: Reserved for alignment; must be zero.
+ */
+struct apm_module_register_events {
+ uint32_t module_instance_id;
+ uint32_t event_id;
+ uint32_t is_register;
+ uint32_t error_code;
+ uint32_t event_config_payload_size;
+ uint32_t reserved;
+} __packed;
+
+/**
+ * struct apm_module_event - Module event descriptor
+ * @event_id: Module event identifier.
+ * @event_payload_size: Event payload size in bytes.
+ */
+struct apm_module_event {
+ uint32_t event_id;
+ uint32_t event_payload_size;
+} __packed;
#define APM_MEMORY_MAP_SHMEM8_4K_POOL 3
@@ -710,6 +759,46 @@ struct param_id_placeholder_real_module_id {
uint32_t real_module_id;
} __packed;
+
+#define PARAM_ID_SH_MEM_PULL_PUSH_MODE_CFG 0x0800100A
+
+/**
+ * struct param_id_sh_mem_pull_push_mode_cfg - Shared memory push/pull config
+ * @shared_circ_buf_addr_lsw: Lower 32 bits of the circular buffer address.
+ * @shared_circ_buf_addr_msw: Upper 32 bits of the circular buffer address.
+ * @shared_circ_buf_size: Circular buffer size in bytes.
+ * @circ_buf_mem_map_handle: Circular buffer memory map handle.
+ * @shared_pos_buf_addr_lsw: Lower 32 bits of the position buffer address.
+ * @shared_pos_buf_addr_msw: Upper 32 bits of the position buffer address.
+ * @pos_buf_mem_map_handle: Position buffer memory map handle.
+ */
+struct param_id_sh_mem_pull_push_mode_cfg {
+ uint32_t shared_circ_buf_addr_lsw;
+ uint32_t shared_circ_buf_addr_msw;
+ uint32_t shared_circ_buf_size;
+ uint32_t circ_buf_mem_map_handle;
+ uint32_t shared_pos_buf_addr_lsw;
+ uint32_t shared_pos_buf_addr_msw;
+ uint32_t pos_buf_mem_map_handle;
+} __packed;
+
+/**
+ * struct sh_mem_pull_push_mode_position_buffer - Shared position buffer
+ * @frame_counter: Synchronization counter.
+ * @index: Current read/write index in bytes.
+ * @timestamp_us_lsw: Lower 32 bits of the timestamp in microseconds.
+ * @timestamp_us_msw: Upper 32 bits of the timestamp in microseconds.
+ *
+ * The frame counter should be read before and after the other fields to
+ * ensure the DSP did not update them while they were being read.
+ */
+struct sh_mem_pull_push_mode_position_buffer {
+ uint32_t frame_counter;
+ uint32_t index;
+ uint32_t timestamp_us_lsw;
+ uint32_t timestamp_us_msw;
+} __packed;
+
/* Graph */
struct audioreach_connection {
/* Connections */
@@ -723,8 +812,10 @@ struct audioreach_connection {
struct audioreach_graph_info {
int id;
uint32_t mem_map_handle;
+ uint32_t pos_buf_mem_map_handle;
uint32_t num_sub_graphs;
struct list_head sg_list;
+ bool is_push_pull_mode;
/* DPCM connection from FE Graph to BE graph */
uint32_t src_mod_inst_id;
uint32_t src_mod_op_port_id;
@@ -855,5 +946,10 @@ int audioreach_send_u32_param(struct q6apm_graph *graph,
uint32_t param_id, uint32_t param_val);
int audioreach_compr_set_param(struct q6apm_graph *graph,
const struct audioreach_module_config *mcfg);
+int audioreach_setup_push_pull(struct q6apm_graph *graph, phys_addr_t bphys,
+ phys_addr_t pphys, uint32_t mem_map_handle,
+ uint32_t pos_buf_mem_map_handle, uint32_t size);
+int audioreach_map_memory_position_buffer(struct q6apm_graph *graph, unsigned int dir);
+int audioreach_shmem_register_event(struct q6apm_graph *graph, int bytes, int num_levels);
#endif /* __AUDIOREACH_H__ */
diff --git a/sound/soc/qcom/qdsp6/q6apm-dai.c b/sound/soc/qcom/qdsp6/q6apm-dai.c
index ede19fdea6e9..bf1f872a09f4 100644
--- a/sound/soc/qcom/qdsp6/q6apm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6apm-dai.c
@@ -18,6 +18,7 @@
#include "q6apm.h"
#define DRV_NAME "q6apm-dai"
+#define POS_BUFFER_BYTES 4096
#define PLAYBACK_MIN_NUM_PERIODS 2
#define PLAYBACK_MAX_NUM_PERIODS 8
@@ -62,8 +63,12 @@ struct q6apm_dai_rtd {
struct snd_codec codec;
struct snd_compr_params codec_param;
struct snd_dma_buffer dma_buffer;
+ struct sh_mem_pull_push_mode_position_buffer *pos_buffer;
+ uint32_t last_pos_index;
phys_addr_t phys;
+ phys_addr_t pos_phys;
unsigned int pcm_size;
+ unsigned int push_pull_size;
unsigned int pcm_count;
unsigned int periods;
uint64_t bytes_sent;
@@ -128,6 +133,9 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void *
struct snd_pcm_substream *substream = prtd->substream;
switch (opcode) {
+ case APM_CLIENT_EVENT_WATERMARK_EVENT:
+ snd_pcm_period_elapsed(substream);
+ break;
case APM_CLIENT_EVENT_CMD_EOS_DONE:
prtd->state = Q6APM_STREAM_STOPPED;
break;
@@ -234,24 +242,47 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
q6apm_free_fragments(prtd->graph, substream->stream);
}
+ prtd->last_pos_index = 0;
prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
- /* rate and channels are sent to audio driver */
- ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
- if (ret < 0) {
- dev_err(dev, "%s: q6apm_open_write failed\n", __func__);
- return ret;
+ if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) {
+ if (prtd->pcm_size != prtd->push_pull_size) {
+ ret = q6apm_push_pull_config(prtd->graph, prtd->phys, prtd->pos_phys,
+ prtd->pcm_size);
+ if (ret < 0) {
+ dev_err(dev, "Push/Pull config failed rc = %d\n", ret);
+ return ret;
+ }
+
+ ret = q6apm_register_watermark_event(prtd->graph,
+ prtd->pcm_size / prtd->periods,
+ prtd->periods);
+ if (ret < 0) {
+ dev_err(dev, "WaterMark event config failed rc = %d\n", ret);
+ return ret;
+ }
+ prtd->push_pull_size = prtd->pcm_size;
+ }
+ } else {
+ ret = q6apm_alloc_fragments(prtd->graph, substream->stream, prtd->phys,
+ (prtd->pcm_size / prtd->periods), prtd->periods);
+ if (ret < 0) {
+ dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
+ return ret;
+ }
+
}
ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg);
- if (ret < 0)
+ if (ret < 0) {
dev_err(dev, "%s: CMD Format block failed\n", __func__);
+ return ret;
+ }
- ret = q6apm_alloc_fragments(prtd->graph, substream->stream, prtd->phys,
- (prtd->pcm_size / prtd->periods), prtd->periods);
-
+ /* rate and channels are sent to audio driver */
+ ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
if (ret < 0) {
- dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
- return -ENOMEM;
+ dev_err(dev, "Failed to set media format %d\n", ret);
+ return ret;
}
ret = q6apm_graph_prepare(prtd->graph);
@@ -265,13 +296,13 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
dev_err(dev, "Failed to Start Graph %d\n", ret);
return ret;
}
-
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- int i;
- /* Queue the buffers for Capture ONLY after graph is started */
- for (i = 0; i < runtime->periods; i++)
- q6apm_read(prtd->graph);
-
+ if (!q6apm_is_graph_in_push_pull_mode(prtd->graph)) {
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
+ int i;
+ /* Queue the buffers for Capture ONLY after graph is started */
+ for (i = 0; i < runtime->periods; i++)
+ q6apm_read(prtd->graph);
+ }
}
/* Now that graph as been prepared and started update the internal state accordingly */
@@ -286,6 +317,9 @@ static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_sub
struct q6apm_dai_rtd *prtd = runtime->private_data;
int i, ret = 0, avail_periods;
+ if (q6apm_is_graph_in_push_pull_mode(prtd->graph))
+ return 0;
+
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size;
for (i = 0; i < avail_periods; i++) {
@@ -317,6 +351,7 @@ static int q6apm_dai_trigger(struct snd_soc_component *component,
/* TODO support be handled via SoftPause Module */
prtd->state = Q6APM_STREAM_STOPPED;
prtd->queue_ptr = 0;
+ prtd->last_pos_index = 0;
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
@@ -402,6 +437,14 @@ static int q6apm_dai_open(struct snd_soc_component *component,
else
prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
+ if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) {
+ void *pos_buffer;
+
+ prtd->pos_phys = prtd->phys + BUFFER_BYTES_MAX;
+ pos_buffer = (void *)(substream->dma_buffer.area + BUFFER_BYTES_MAX);
+ prtd->pos_buffer = (struct sh_mem_pull_push_mode_position_buffer *)(pos_buffer);
+ }
+
return 0;
err:
kfree(prtd);
@@ -436,6 +479,25 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component,
struct q6apm_dai_rtd *prtd = runtime->private_data;
snd_pcm_uframes_t ptr;
+ if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) {
+ int retries = 10;
+ uint32_t index, fc1, fc2;
+
+ /* index is valid if frame_counter does not change while reading. */
+ do {
+ fc1 = READ_ONCE(prtd->pos_buffer->frame_counter);
+ index = READ_ONCE(prtd->pos_buffer->index);
+ fc2 = READ_ONCE(prtd->pos_buffer->frame_counter);
+ } while (fc1 != fc2 && --retries);
+
+ if (fc1 != fc2)
+ index = prtd->last_pos_index;
+ else
+ prtd->last_pos_index = index;
+
+ ptr = bytes_to_frames(runtime, index);
+ return ptr;
+ }
ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size;
if (ptr)
return ptr - 1;
@@ -468,7 +530,8 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component,
}
static int q6apm_dai_memory_map(struct snd_soc_component *component,
- struct snd_pcm_substream *substream, int graph_id)
+ struct snd_pcm_substream *substream,
+ int graph_id, bool is_push_pull)
{
struct q6apm_dai_data *pdata;
struct device *dev = component->dev;
@@ -490,6 +553,19 @@ static int q6apm_dai_memory_map(struct snd_soc_component *component,
if (ret < 0)
dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
+ if (is_push_pull) {
+ if (pdata->sid < 0)
+ phys = substream->dma_buffer.addr + BUFFER_BYTES_MAX;
+ else
+ phys = (substream->dma_buffer.addr + BUFFER_BYTES_MAX) | (pdata->sid << 32);
+
+ ret = q6apm_map_pos_buffer(dev, graph_id, phys, POS_BUFFER_BYTES);
+ if (ret < 0)
+ dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
+ } else {
+
+ }
+
return ret;
}
@@ -497,27 +573,37 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc
{
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
struct snd_pcm *pcm = rtd->pcm;
- int size = BUFFER_BYTES_MAX;
+ /*
+ * Allocate one extra page as a workaround for a DSP bug where 32-bit
+ * address arithmetic can overflow when the buffer is placed near the
+ * end of the addressable range.
+ */
+ int size = BUFFER_BYTES_MAX + PAGE_SIZE;
int graph_id, ret;
- struct snd_pcm_substream *substream;
+ bool is_push_pull;
+ struct snd_pcm_substream *substream = NULL;
graph_id = cpu_dai->driver->id;
- ret = snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, component->dev, size);
- if (ret)
- return ret;
-
/* Note: DSP backend dais are uni-directional ONLY(either playback or capture) */
- if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
- ret = q6apm_dai_memory_map(component, substream, graph_id);
+ else if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
+ substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+
+
+ if (substream) {
+ is_push_pull = q6apm_is_graph_in_push_pull_mode_from_id(component->dev,
+ graph_id,
+ substream->stream);
+ if (is_push_pull)
+ size += POS_BUFFER_BYTES;
+
+ ret = snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, component->dev, size);
if (ret)
return ret;
- }
- if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
- substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
- ret = q6apm_dai_memory_map(component, substream, graph_id);
+ ret = q6apm_dai_memory_map(component, substream, graph_id, is_push_pull);
if (ret)
return ret;
}
@@ -542,6 +628,9 @@ static void q6apm_dai_memory_unmap(struct snd_soc_component *component,
graph_id = cpu_dai->driver->id;
q6apm_unmap_memory_fixed_region(component->dev, graph_id);
+
+ if (q6apm_is_graph_in_push_pull_mode_from_id(component->dev, graph_id, substream->stream))
+ q6apm_unmap_pos_buffer(component->dev, graph_id);
}
static void q6apm_dai_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm)
diff --git a/sound/soc/qcom/qdsp6/q6apm.c b/sound/soc/qcom/qdsp6/q6apm.c
index 2ab378fb5032..641d6d243229 100644
--- a/sound/soc/qcom/qdsp6/q6apm.c
+++ b/sound/soc/qcom/qdsp6/q6apm.c
@@ -186,23 +186,27 @@ int q6apm_graph_media_format_shmem(struct q6apm_graph *graph,
{
struct audioreach_module *module;
- if (cfg->direction == SNDRV_PCM_STREAM_CAPTURE)
- module = q6apm_find_module_by_mid(graph, MODULE_ID_RD_SHARED_MEM_EP);
- else
- module = q6apm_find_module_by_mid(graph, MODULE_ID_WR_SHARED_MEM_EP);
+ if (cfg->direction == SNDRV_PCM_STREAM_CAPTURE) {
+ module = q6apm_find_module_by_mid(graph, MODULE_ID_SH_MEM_PUSH_MODE);
+ if (!module)
+ module = q6apm_find_module_by_mid(graph, MODULE_ID_RD_SHARED_MEM_EP);
+ } else {
+ module = q6apm_find_module_by_mid(graph, MODULE_ID_SH_MEM_PULL_MODE);
+ if (!module)
+ module = q6apm_find_module_by_mid(graph, MODULE_ID_WR_SHARED_MEM_EP);
+ }
- if (!module)
+ if (!module) {
+ dev_err(graph->dev, "No SHMEM module found in graph\n");
return -ENODEV;
+ }
- audioreach_set_media_format(graph, module, cfg);
-
- return 0;
-
+ return audioreach_set_media_format(graph, module, cfg);
}
EXPORT_SYMBOL_GPL(q6apm_graph_media_format_shmem);
-int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phys_addr_t phys,
- size_t sz)
+static int __q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id,
+ phys_addr_t phys, size_t sz, bool is_pos_buf)
{
struct audioreach_graph_info *info;
struct q6apm *apm = dev_get_drvdata(dev->parent);
@@ -211,8 +215,10 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy
int payload_size = sizeof(*cmd) + (sizeof(*mregions));
uint32_t buf_sz;
void *p;
+ uint32_t pos_mask = is_pos_buf ? APM_MMAP_TOKEN_MAP_TYPE_POS_BUF : 0;
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size,
- APM_CMD_SHARED_MEM_MAP_REGIONS, graph_id);
+ APM_CMD_SHARED_MEM_MAP_REGIONS, (graph_id | pos_mask));
+
if (IS_ERR(pkt))
return PTR_ERR(pkt);
@@ -220,8 +226,13 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy
if (!info)
return -ENODEV;
- if (info->mem_map_handle)
- return 0;
+ if (is_pos_buf) {
+ if (info->pos_buf_mem_map_handle)
+ return 0;
+ } else {
+ if (info->mem_map_handle)
+ return 0;
+ }
/* DSP expects size should be aligned to 4K */
buf_sz = ALIGN(sz, 4096);
@@ -230,7 +241,10 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy
cmd = p;
cmd->mem_pool_id = APM_MEMORY_MAP_SHMEM8_4K_POOL;
cmd->num_regions = 1;
- cmd->property_flag = 0x0;
+ if (is_pos_buf)
+ cmd->property_flag = 0x2;
+ else
+ cmd->property_flag = 0x0;
mregions = p + sizeof(*cmd);
@@ -240,6 +254,18 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy
return q6apm_send_cmd_sync(apm, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS);
}
+
+int q6apm_map_pos_buffer(struct device *dev, unsigned int graph_id, phys_addr_t phys, size_t sz)
+{
+ return __q6apm_map_memory_fixed_region(dev, graph_id, phys, sz, true);
+}
+EXPORT_SYMBOL_GPL(q6apm_map_pos_buffer);
+
+int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id,
+ phys_addr_t phys, size_t sz)
+{
+ return __q6apm_map_memory_fixed_region(dev, graph_id, phys, sz, false);
+}
EXPORT_SYMBOL_GPL(q6apm_map_memory_fixed_region);
int q6apm_alloc_fragments(struct q6apm_graph *graph, unsigned int dir, phys_addr_t phys,
@@ -293,11 +319,13 @@ int q6apm_alloc_fragments(struct q6apm_graph *graph, unsigned int dir, phys_addr
}
EXPORT_SYMBOL_GPL(q6apm_alloc_fragments);
-int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id)
+static int __q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id,
+ bool is_pos_buf)
{
struct apm_cmd_shared_mem_unmap_regions *cmd;
struct q6apm *apm = dev_get_drvdata(dev->parent);
struct audioreach_graph_info *info;
+ uint32_t mem_map_handle;
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(sizeof(*cmd),
APM_CMD_SHARED_MEM_UNMAP_REGIONS, graph_id);
if (IS_ERR(pkt))
@@ -307,16 +335,35 @@ int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id)
if (!info)
return -ENODEV;
- if (!info->mem_map_handle)
- return 0;
+ if (is_pos_buf) {
+ if (!info->pos_buf_mem_map_handle)
+ return 0;
+ mem_map_handle = info->pos_buf_mem_map_handle;
+ } else {
+
+ if (!info->mem_map_handle)
+ return 0;
+ mem_map_handle = info->mem_map_handle;
+ }
cmd = (void *)pkt + GPR_HDR_SIZE;
- cmd->mem_map_handle = info->mem_map_handle;
+ cmd->mem_map_handle = mem_map_handle;
return q6apm_send_cmd_sync(apm, pkt, APM_CMD_SHARED_MEM_UNMAP_REGIONS);
}
+
+int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id)
+{
+ return __q6apm_unmap_memory_fixed_region(dev, graph_id, false);
+}
EXPORT_SYMBOL_GPL(q6apm_unmap_memory_fixed_region);
+int q6apm_unmap_pos_buffer(struct device *dev, unsigned int graph_id)
+{
+ return __q6apm_unmap_memory_fixed_region(dev, graph_id, true);
+}
+EXPORT_SYMBOL_GPL(q6apm_unmap_pos_buffer);
+
int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir)
{
audioreach_graph_free_buf(graph);
@@ -399,15 +446,20 @@ int q6apm_graph_media_format_pcm(struct q6apm_graph *graph, struct audioreach_mo
struct audioreach_sub_graph *sgs;
struct audioreach_container *container;
struct audioreach_module *module;
+ int ret;
list_for_each_entry(sgs, &info->sg_list, node) {
list_for_each_entry(container, &sgs->container_list, node) {
list_for_each_entry(module, &container->modules_list, node) {
if ((module->module_id == MODULE_ID_WR_SHARED_MEM_EP) ||
- (module->module_id == MODULE_ID_RD_SHARED_MEM_EP))
+ (module->module_id == MODULE_ID_RD_SHARED_MEM_EP) ||
+ (module->module_id == MODULE_ID_SH_MEM_PULL_MODE) ||
+ (module->module_id == MODULE_ID_SH_MEM_PUSH_MODE))
continue;
- audioreach_set_media_format(graph, module, cfg);
+ ret = audioreach_set_media_format(graph, module, cfg);
+ if (ret)
+ return ret;
}
}
}
@@ -417,31 +469,6 @@ int q6apm_graph_media_format_pcm(struct q6apm_graph *graph, struct audioreach_mo
}
EXPORT_SYMBOL_GPL(q6apm_graph_media_format_pcm);
-static int q6apm_graph_get_tx_shmem_module_iid(struct q6apm_graph *graph)
-{
- struct audioreach_module *module;
-
- module = q6apm_find_module_by_mid(graph, MODULE_ID_RD_SHARED_MEM_EP);
- if (!module)
- return -ENODEV;
-
- return module->instance_id;
-
-}
-
-int q6apm_graph_get_rx_shmem_module_iid(struct q6apm_graph *graph)
-{
- struct audioreach_module *module;
-
- module = q6apm_find_module_by_mid(graph, MODULE_ID_WR_SHARED_MEM_EP);
- if (!module)
- return -ENODEV;
-
- return module->instance_id;
-
-}
-EXPORT_SYMBOL_GPL(q6apm_graph_get_rx_shmem_module_iid);
-
int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
uint32_t lsw_ts, uint32_t wflags)
{
@@ -530,6 +557,7 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
{
struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done;
struct data_cmd_rsp_wr_sh_mem_ep_data_buffer_done_v2 *done;
+ struct apm_module_event *event;
const struct gpr_ibasic_rsp_result_t *result;
struct q6apm_graph *graph = priv;
const struct gpr_hdr *hdr = &data->hdr;
@@ -541,6 +569,16 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
result = data->payload;
switch (hdr->opcode) {
+ case APM_EVENT_MODULE_TO_CLIENT:
+ event = data->payload;
+ switch (event->event_id) {
+ case EVENT_ID_SH_MEM_PULL_PUSH_MODE_WATERMARK:
+ client_event = APM_CLIENT_EVENT_WATERMARK_EVENT;
+ graph->cb(client_event, hdr->token, data->payload, graph->priv);
+ break;
+ }
+
+ break;
case DATA_CMD_RSP_WR_SH_MEM_EP_DATA_BUFFER_DONE_V2:
if (!graph->ar_graph)
break;
@@ -549,6 +587,10 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
token = hdr->token & APM_WRITE_TOKEN_MASK;
done = data->payload;
+ if (!graph->rx_data.buf) {
+ mutex_unlock(&graph->lock);
+ break;
+ }
phys = graph->rx_data.buf[token].phys;
mutex_unlock(&graph->lock);
/* token numbering starts at 0 */
@@ -571,6 +613,10 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
client_event = APM_CLIENT_EVENT_DATA_READ_DONE;
mutex_lock(&graph->lock);
rd_done = data->payload;
+ if (!graph->tx_data.buf) {
+ mutex_unlock(&graph->lock);
+ break;
+ }
phys = graph->tx_data.buf[hdr->token].phys;
mutex_unlock(&graph->lock);
/* token numbering starts at 0 */
@@ -596,6 +642,7 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
switch (result->opcode) {
case APM_CMD_SHARED_MEM_MAP_REGIONS:
case DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT:
+ case APM_CMD_REGISTER_MODULE_EVENTS:
case APM_CMD_SET_CFG:
graph->result.opcode = result->opcode;
graph->result.status = result->status;
@@ -614,13 +661,67 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
return 0;
}
+int q6apm_register_watermark_event(struct q6apm_graph *graph, int water_mark_level_bytes,
+ int num_levels)
+{
+ return audioreach_shmem_register_event(graph, water_mark_level_bytes, num_levels);
+}
+EXPORT_SYMBOL_GPL(q6apm_register_watermark_event);
+
+int q6apm_push_pull_config(struct q6apm_graph *graph, phys_addr_t bphys,
+ phys_addr_t pphys, uint32_t size)
+{
+ struct audioreach_graph_info *info = graph->info;
+
+ return audioreach_setup_push_pull(graph, bphys, pphys, info->mem_map_handle,
+ info->pos_buf_mem_map_handle, size);
+}
+EXPORT_SYMBOL_GPL(q6apm_push_pull_config);
+
+bool q6apm_is_graph_in_push_pull_mode_from_id(struct device *dev, unsigned int graph_id, int dir)
+{
+ struct audioreach_graph_info *info;
+ struct q6apm *apm = dev_get_drvdata(dev->parent);
+ struct audioreach_module *module;
+
+ info = idr_find(&apm->graph_info_idr, graph_id);
+ if (!info)
+ return false;
+
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK)
+ module = __q6apm_find_module_by_mid(apm, info, MODULE_ID_SH_MEM_PULL_MODE);
+ else
+ module = __q6apm_find_module_by_mid(apm, info, MODULE_ID_SH_MEM_PUSH_MODE);
+
+ return !!module;
+
+}
+EXPORT_SYMBOL_GPL(q6apm_is_graph_in_push_pull_mode_from_id);
+
+bool q6apm_is_graph_in_push_pull_mode(struct q6apm_graph *graph)
+{
+ return graph->info->is_push_pull_mode;
+}
+EXPORT_SYMBOL_GPL(q6apm_is_graph_in_push_pull_mode);
+
+static int q6apm_graph_get_module_iid(struct q6apm_graph *graph, uint32_t mid)
+{
+ struct audioreach_module *module;
+
+ module = q6apm_find_module_by_mid(graph, mid);
+ if (!module)
+ return -ENODEV;
+
+ return module->instance_id;
+}
+
struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb,
void *priv, int graph_id, int dir)
{
struct q6apm *apm = dev_get_drvdata(dev->parent);
struct audioreach_graph *ar_graph;
struct q6apm_graph *graph;
- int ret;
+ int ret, iid = 0;
ar_graph = q6apm_get_audioreach_graph(apm, graph_id);
if (IS_ERR(ar_graph)) {
@@ -642,11 +743,23 @@ struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb,
graph->id = ar_graph->id;
graph->dev = dev;
- if (dir == SNDRV_PCM_STREAM_PLAYBACK)
- graph->shm_iid = q6apm_graph_get_rx_shmem_module_iid(graph);
- else
- graph->shm_iid = q6apm_graph_get_tx_shmem_module_iid(graph);
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
+ iid = q6apm_graph_get_module_iid(graph, MODULE_ID_SH_MEM_PULL_MODE);
+ if (iid < 0)
+ iid = q6apm_graph_get_module_iid(graph, MODULE_ID_WR_SHARED_MEM_EP);
+ else
+ graph->info->is_push_pull_mode = true;
+
+ } else {
+ iid = q6apm_graph_get_module_iid(graph, MODULE_ID_SH_MEM_PUSH_MODE);
+ if (iid < 0)
+ iid = q6apm_graph_get_module_iid(graph, MODULE_ID_RD_SHARED_MEM_EP);
+ else
+ graph->info->is_push_pull_mode = true;
+ }
+ if (iid > 0)
+ graph->shm_iid = iid;
mutex_init(&graph->lock);
init_waitqueue_head(&graph->cmd_wait);
@@ -803,6 +916,7 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
struct device *dev = &gdev->dev;
struct gpr_ibasic_rsp_result_t *result;
const struct gpr_hdr *hdr = &data->hdr;
+ int graph_id, is_pos_buf;
result = data->payload;
@@ -853,13 +967,19 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
apm->result.opcode = hdr->opcode;
apm->result.status = 0;
rsp = data->payload;
+ graph_id = hdr->token & APM_MMAP_TOKEN_GID_MASK;
+ is_pos_buf = hdr->token & APM_MMAP_TOKEN_MAP_TYPE_POS_BUF;
- info = idr_find(&apm->graph_info_idr, hdr->token);
- if (info)
- info->mem_map_handle = rsp->mem_map_handle;
- else
+ info = idr_find(&apm->graph_info_idr, graph_id);
+ if (info) {
+ if (is_pos_buf)
+ info->pos_buf_mem_map_handle = rsp->mem_map_handle;
+ else
+ info->mem_map_handle = rsp->mem_map_handle;
+ } else {
dev_err(dev, "Error (%d) Processing 0x%08x cmd\n", result->status,
result->opcode);
+ }
wake_up(&apm->wait);
break;
diff --git a/sound/soc/qcom/qdsp6/q6apm.h b/sound/soc/qcom/qdsp6/q6apm.h
index 376a36700c53..5cb51ca491dc 100644
--- a/sound/soc/qcom/qdsp6/q6apm.h
+++ b/sound/soc/qcom/qdsp6/q6apm.h
@@ -41,6 +41,7 @@
#define APM_CLIENT_EVENT_CMD_RUN_DONE 0x1008
#define APM_CLIENT_EVENT_DATA_WRITE_DONE 0x1009
#define APM_CLIENT_EVENT_DATA_READ_DONE 0x100a
+#define APM_CLIENT_EVENT_WATERMARK_EVENT 0x100b
#define APM_WRITE_TOKEN_MASK GENMASK(15, 0)
#define APM_WRITE_TOKEN_LEN_MASK GENMASK(31, 16)
#define APM_WRITE_TOKEN_LEN_SHIFT 16
@@ -136,6 +137,10 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
int q6apm_map_memory_fixed_region(struct device *dev,
unsigned int graph_id, phys_addr_t phys,
size_t sz);
+int q6apm_map_pos_buffer(struct device *dev,
+ unsigned int graph_id, phys_addr_t phys,
+ size_t sz);
+int q6apm_unmap_pos_buffer(struct device *dev, unsigned int graph_id);
int q6apm_alloc_fragments(struct q6apm_graph *graph,
unsigned int dir, phys_addr_t phys,
size_t period_sz, unsigned int periods);
@@ -148,8 +153,6 @@ int q6apm_send_cmd_sync(struct q6apm *apm, const struct gpr_pkt *pkt,
/* Callback for graph specific */
struct audioreach_module *q6apm_find_module_by_mid(struct q6apm_graph *graph,
uint32_t mid);
-int q6apm_graph_get_rx_shmem_module_iid(struct q6apm_graph *graph);
-
bool q6apm_is_adsp_ready(void);
int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph, bool en);
@@ -157,4 +160,10 @@ int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph,
int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples);
int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id);
int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir);
+bool q6apm_is_graph_in_push_pull_mode(struct q6apm_graph *graph);
+bool q6apm_is_graph_in_push_pull_mode_from_id(struct device *dev, unsigned int graph_id, int dir);
+int q6apm_push_pull_config(struct q6apm_graph *graph, phys_addr_t bphys,
+ phys_addr_t pphys, uint32_t size);
+
+int q6apm_register_watermark_event(struct q6apm_graph *graph, int watermark_bytes, int num_levels);
#endif /* __APM_GRAPH_ */
diff --git a/sound/soc/qcom/qdsp6/q6asm-dai.c b/sound/soc/qcom/qdsp6/q6asm-dai.c
index 4f8f7db6c3d3..4f09fdd40905 100644
--- a/sound/soc/qcom/qdsp6/q6asm-dai.c
+++ b/sound/soc/qcom/qdsp6/q6asm-dai.c
@@ -186,12 +186,10 @@ static void event_handler(uint32_t opcode, uint32_t token,
case ASM_CLIENT_EVENT_CMD_RUN_DONE:
break;
case ASM_CLIENT_EVENT_CMD_EOS_DONE:
- prtd->state = Q6ASM_STREAM_STOPPED;
break;
- case ASM_CLIENT_EVENT_DATA_WRITE_DONE: {
+ case ASM_CLIENT_EVENT_DATA_WRITE_DONE:
snd_pcm_period_elapsed(substream);
break;
- }
case ASM_CLIENT_EVENT_DATA_READ_DONE:
snd_pcm_period_elapsed(substream);
if (prtd->state == Q6ASM_STREAM_RUNNING)
@@ -227,9 +225,19 @@ static int q6asm_dai_prepare(struct snd_soc_component *component,
/* rate and channels are sent to audio driver */
if (prtd->state == Q6ASM_STREAM_RUNNING) {
/* clear the previous setup if any */
- q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
- q6asm_unmap_memory_regions(substream->stream,
- prtd->audio_client);
+ ret = q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
+ if (ret < 0) {
+ dev_err(dev, "Failed to close q6asm stream %d\n", prtd->stream_id);
+ return ret;
+ }
+
+ ret = q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
+ if (ret < 0) {
+ dev_err(dev, "Failed to unmap memory regions for q6asm stream %d\n",
+ prtd->stream_id);
+ return ret;
+ }
+
q6routing_stream_close(soc_prtd->dai_link->id,
substream->stream);
prtd->state = Q6ASM_STREAM_STOPPED;
@@ -297,8 +305,6 @@ routing_err:
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
open_err:
q6asm_unmap_memory_regions(substream->stream, prtd->audio_client);
- q6asm_audio_client_free(prtd->audio_client);
- prtd->audio_client = NULL;
return ret;
}
@@ -341,7 +347,6 @@ static int q6asm_dai_trigger(struct snd_soc_component *component,
0, 0, 0);
break;
case SNDRV_PCM_TRIGGER_STOP:
- prtd->state = Q6ASM_STREAM_STOPPED;
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
CMD_EOS);
break;
@@ -378,7 +383,7 @@ static int q6asm_dai_open(struct snd_soc_component *component,
return -EINVAL;
}
- prtd = kzalloc_obj(struct q6asm_dai_rtd);
+ prtd = kzalloc_obj(*prtd);
if (prtd == NULL)
return -ENOMEM;
@@ -457,12 +462,12 @@ static int q6asm_dai_close(struct snd_soc_component *component,
struct q6asm_dai_rtd *prtd = runtime->private_data;
if (prtd->audio_client) {
- if (prtd->state)
+ if (prtd->state == Q6ASM_STREAM_RUNNING) {
q6asm_cmd(prtd->audio_client, prtd->stream_id,
CMD_CLOSE);
-
- q6asm_unmap_memory_regions(substream->stream,
+ q6asm_unmap_memory_regions(substream->stream,
prtd->audio_client);
+ }
q6asm_audio_client_free(prtd->audio_client);
prtd->audio_client = NULL;
}
@@ -555,8 +560,6 @@ static void compress_event_handler(uint32_t opcode, uint32_t token,
snd_compr_drain_notify(prtd->cstream);
prtd->notify_on_drain = false;
- } else {
- prtd->state = Q6ASM_STREAM_STOPPED;
}
break;
@@ -674,7 +677,7 @@ static int q6asm_dai_compr_free(struct snd_soc_component *component,
struct snd_soc_pcm_runtime *rtd = stream->private_data;
if (prtd->audio_client) {
- if (prtd->state) {
+ if (prtd->state == Q6ASM_STREAM_RUNNING) {
q6asm_cmd(prtd->audio_client, prtd->stream_id,
CMD_CLOSE);
if (prtd->next_track_stream_id) {
@@ -682,11 +685,11 @@ static int q6asm_dai_compr_free(struct snd_soc_component *component,
prtd->next_track_stream_id,
CMD_CLOSE);
}
- }
- snd_dma_free_pages(&prtd->dma_buffer);
- q6asm_unmap_memory_regions(stream->direction,
+ q6asm_unmap_memory_regions(stream->direction,
prtd->audio_client);
+ }
+ snd_dma_free_pages(&prtd->dma_buffer);
q6asm_audio_client_free(prtd->audio_client);
prtd->audio_client = NULL;
}
@@ -916,7 +919,7 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
prtd->session_id, dir);
if (ret) {
dev_err(dev, "Stream reg failed ret:%d\n", ret);
- goto q6_err;
+ goto routing_err;
}
ret = __q6asm_dai_compr_set_codec_params(component, stream,
@@ -942,11 +945,11 @@ static int q6asm_dai_compr_set_params(struct snd_soc_component *component,
return 0;
q6_err:
+ q6routing_stream_close(rtd->dai_link->id, dir);
+routing_err:
q6asm_cmd(prtd->audio_client, prtd->stream_id, CMD_CLOSE);
open_err:
- q6asm_audio_client_free(prtd->audio_client);
- prtd->audio_client = NULL;
return ret;
}
@@ -1014,7 +1017,6 @@ static int q6asm_dai_compr_trigger(struct snd_soc_component *component,
0, 0, 0);
break;
case SNDRV_PCM_TRIGGER_STOP:
- prtd->state = Q6ASM_STREAM_STOPPED;
ret = q6asm_cmd_nowait(prtd->audio_client, prtd->stream_id,
CMD_EOS);
break;
diff --git a/sound/soc/qcom/sc7280.c b/sound/soc/qcom/sc7280.c
index abdd58c1d0a4..d3d8a6e83268 100644
--- a/sound/soc/qcom/sc7280.c
+++ b/sound/soc/qcom/sc7280.c
@@ -7,7 +7,6 @@
#include <dt-bindings/sound/qcom,lpass.h>
#include <dt-bindings/sound/qcom,q6afe.h>
#include <linux/input.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/core.h>
diff --git a/sound/soc/qcom/storm.c b/sound/soc/qcom/storm.c
index c8d5ac43a176..1e0eda8c24c4 100644
--- a/sound/soc/qcom/storm.c
+++ b/sound/soc/qcom/storm.c
@@ -8,7 +8,6 @@
#include <linux/device.h>
#include <linux/module.h>
#include <linux/of.h>
-#include <linux/mod_devicetable.h>
#include <linux/platform_device.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
diff --git a/sound/soc/renesas/Kconfig b/sound/soc/renesas/Kconfig
index 11c2027c88a7..6520217e7407 100644
--- a/sound/soc/renesas/Kconfig
+++ b/sound/soc/renesas/Kconfig
@@ -56,6 +56,7 @@ config SND_SOC_MSIOF
config SND_SOC_RZ
tristate "RZ/G2L series SSIF-2 support"
depends on ARCH_RZG2L || COMPILE_TEST
+ select SND_SOC_GENERIC_DMAENGINE_PCM
help
This option enables RZ/G2L SSIF-2 sound support.
diff --git a/sound/soc/renesas/fsi.c b/sound/soc/renesas/fsi.c
index 8cbd7acc26f4..ae86014c3819 100644
--- a/sound/soc/renesas/fsi.c
+++ b/sound/soc/renesas/fsi.c
@@ -292,6 +292,7 @@ struct fsi_master {
void __iomem *base;
struct fsi_priv fsia;
struct fsi_priv fsib;
+ struct clk *clk_spu;
const struct fsi_core *core;
spinlock_t lock;
};
@@ -442,6 +443,16 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples)
return samples / fsi->chan_num;
}
+static int fsi_stream_is_working(struct fsi_priv *fsi,
+ struct fsi_stream *io)
+{
+ struct fsi_master *master = fsi_get_master(fsi);
+
+ guard(spinlock_irqsave)(&master->lock);
+
+ return !!(io->substream && io->substream->runtime);
+}
+
static int fsi_get_current_fifo_samples(struct fsi_priv *fsi,
struct fsi_stream *io)
{
@@ -460,6 +471,10 @@ static int fsi_get_current_fifo_samples(struct fsi_priv *fsi,
static void fsi_count_fifo_err(struct fsi_priv *fsi)
{
+ if (!fsi_stream_is_working(fsi, &fsi->playback) &&
+ !fsi_stream_is_working(fsi, &fsi->capture))
+ return;
+
u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
u32 istatus = fsi_reg_read(fsi, DIFF_ST);
@@ -488,16 +503,6 @@ static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi,
return fsi_is_play(substream) ? &fsi->playback : &fsi->capture;
}
-static int fsi_stream_is_working(struct fsi_priv *fsi,
- struct fsi_stream *io)
-{
- struct fsi_master *master = fsi_get_master(fsi);
-
- guard(spinlock_irqsave)(&master->lock);
-
- return !!(io->substream && io->substream->runtime);
-}
-
static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io)
{
return io->priv;
@@ -681,6 +686,10 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi)
u32 data = 0;
struct fsi_master *master = fsi_get_master(fsi);
+ if (!fsi_stream_is_working(fsi, &fsi->playback) &&
+ !fsi_stream_is_working(fsi, &fsi->capture))
+ return;
+
data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->playback));
data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->capture));
@@ -709,80 +718,64 @@ static void fsi_spdif_clk_ctrl(struct fsi_priv *fsi, int enable)
/*
* clock function
*/
-static int fsi_clk_init(struct device *dev,
- struct fsi_priv *fsi,
- int xck,
- int ick,
- int div,
- int (*set_rate)(struct device *dev,
- struct fsi_priv *fsi))
+#define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0)
+static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate)
{
- struct fsi_clk *clock = &fsi->clock;
- int is_porta = fsi_is_port_a(fsi);
+ fsi->clock.rate = rate;
+}
- clock->xck = NULL;
- clock->ick = NULL;
- clock->div = NULL;
- clock->rate = 0;
- clock->count = 0;
- clock->set_rate = set_rate;
+static int fsi_clk_is_valid(struct fsi_priv *fsi)
+{
+ return fsi->clock.set_rate &&
+ fsi->clock.rate;
+}
- clock->own = devm_clk_get(dev, NULL);
- if (IS_ERR(clock->own))
- return -EINVAL;
+static int fsi_clk_prepare(struct fsi_priv *fsi)
+{
+ struct fsi_clk *clock = &fsi->clock;
+ struct clk *spu = fsi->master->clk_spu;
+ struct clk *xck = clock->xck;
+ struct clk *ick = clock->ick;
+ struct clk *div = clock->div;
+ int ret;
- /* external clock */
- if (xck) {
- clock->xck = devm_clk_get(dev, is_porta ? "xcka" : "xckb");
- if (IS_ERR(clock->xck)) {
- dev_err(dev, "can't get xck clock\n");
- return -EINVAL;
- }
- if (clock->xck == clock->own) {
- dev_err(dev, "cpu doesn't support xck clock\n");
- return -EINVAL;
- }
- }
+ ret = clk_prepare(spu);
+ if (ret)
+ return ret;
+ ret = clk_prepare(xck);
+ if (ret)
+ goto err_spu;
+ ret = clk_prepare(ick);
+ if (ret)
+ goto err_xck;
+ ret = clk_prepare(div);
+ if (ret)
+ goto err_ick;
- /* FSIACLK/FSIBCLK */
- if (ick) {
- clock->ick = devm_clk_get(dev, is_porta ? "icka" : "ickb");
- if (IS_ERR(clock->ick)) {
- dev_err(dev, "can't get ick clock\n");
- return -EINVAL;
- }
- if (clock->ick == clock->own) {
- dev_err(dev, "cpu doesn't support ick clock\n");
- return -EINVAL;
- }
- }
+ return 0;
- /* FSI-DIV */
- if (div) {
- clock->div = devm_clk_get(dev, is_porta ? "diva" : "divb");
- if (IS_ERR(clock->div)) {
- dev_err(dev, "can't get div clock\n");
- return -EINVAL;
- }
- if (clock->div == clock->own) {
- dev_err(dev, "cpu doesn't support div clock\n");
- return -EINVAL;
- }
- }
+err_ick:
+ clk_unprepare(ick);
+err_xck:
+ clk_unprepare(xck);
+err_spu:
+ clk_unprepare(spu);
- return 0;
+ return ret;
}
-#define fsi_clk_invalid(fsi) fsi_clk_valid(fsi, 0)
-static void fsi_clk_valid(struct fsi_priv *fsi, unsigned long rate)
+static void fsi_clk_unprepare(struct fsi_priv *fsi)
{
- fsi->clock.rate = rate;
-}
+ struct fsi_clk *clock = &fsi->clock;
+ struct clk *spu = fsi->master->clk_spu;
+ struct clk *xck = clock->xck;
+ struct clk *ick = clock->ick;
+ struct clk *div = clock->div;
-static int fsi_clk_is_valid(struct fsi_priv *fsi)
-{
- return fsi->clock.set_rate &&
- fsi->clock.rate;
+ clk_unprepare(div);
+ clk_unprepare(ick);
+ clk_unprepare(xck);
+ clk_unprepare(spu);
}
static int fsi_clk_enable(struct device *dev,
@@ -918,6 +911,11 @@ static int fsi_clk_set_rate_external(struct device *dev,
int ackmd, bpfmd;
int ret = 0;
+ if (!xck || !ick) {
+ dev_err(dev, "xck clock or ick clock is missing\n");
+ return -EINVAL;
+ }
+
/* check clock rate */
xrate = clk_get_rate(xck);
if (xrate % rate) {
@@ -954,6 +952,11 @@ static int fsi_clk_set_rate_cpg(struct device *dev,
int ackmd, bpfmd;
int ret = -EINVAL;
+ if (!ick || !div) {
+ dev_err(dev, "ick clock or div clock is missing\n");
+ return -EINVAL;
+ }
+
if (!(12288000 % rate))
target = 12288000;
if (!(11289600 % rate))
@@ -1026,6 +1029,74 @@ static int fsi_clk_set_rate_cpg(struct device *dev,
return ret;
}
+static int fsi_clk_init(struct device *dev, struct fsi_priv *fsi)
+{
+ struct fsi_clk *clock = &fsi->clock;
+ struct fsi_master *master = fsi->master;
+ int is_porta = fsi_is_port_a(fsi);
+ int xck, ick, div;
+
+ if (fsi->clk_cpg) {
+ xck = 0; ick = 1; div = 1;
+ clock->set_rate = fsi_clk_set_rate_cpg;
+ } else {
+ xck = 1; ick = 1; div = 0;
+ clock->set_rate = fsi_clk_set_rate_external;
+ }
+
+ clock->xck = NULL;
+ clock->ick = NULL;
+ clock->div = NULL;
+ clock->rate = 0;
+ clock->count = 0;
+
+ clock->own = devm_clk_get(dev, NULL);
+ if (IS_ERR(clock->own))
+ return dev_err_probe(dev, PTR_ERR(clock->own), "Can't get fck clock\n");
+
+ if (!master->clk_spu) {
+ master->clk_spu = devm_clk_get_optional(dev, "spu");
+ if (IS_ERR(master->clk_spu))
+ return dev_err_probe(dev, PTR_ERR(master->clk_spu),
+ "Can't get spu clock\n");
+ }
+
+ /* external clock */
+ if (xck) {
+ clock->xck = devm_clk_get_optional(dev, is_porta ? "xcka" : "xckb");
+ if (IS_ERR(clock->xck))
+ return dev_err_probe(dev, PTR_ERR(clock->xck), "Can't get xck clock\n");
+ if (clock->xck == clock->own) {
+ dev_err(dev, "cpu doesn't support xck clock\n");
+ return -EINVAL;
+ }
+ }
+
+ /* FSIACLK/FSIBCLK */
+ if (ick) {
+ clock->ick = devm_clk_get_optional(dev, is_porta ? "icka" : "ickb");
+ if (IS_ERR(clock->ick))
+ return dev_err_probe(dev, PTR_ERR(clock->ick), "Can't get ick clock\n");
+ if (clock->ick == clock->own) {
+ dev_err(dev, "cpu doesn't support ick clock\n");
+ return -EINVAL;
+ }
+ }
+
+ /* FSI-DIV */
+ if (div) {
+ clock->div = devm_clk_get_optional(dev, is_porta ? "diva" : "divb");
+ if (IS_ERR(clock->div))
+ return dev_err_probe(dev, PTR_ERR(clock->div), "Can't get div clock\n");
+ if (clock->div == clock->own) {
+ dev_err(dev, "cpu doesn't support div clock\n");
+ return -EINVAL;
+ }
+ }
+
+ return 0;
+}
+
static void fsi_pointer_update(struct fsi_stream *io, int size)
{
io->buff_sample_pos += size;
@@ -1489,6 +1560,11 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
struct device *dev)
{
u32 data = 0;
+ int ret;
+ /* enable spu bus bridge clock */
+ ret = clk_enable(fsi->master->clk_spu);
+ if (ret)
+ return ret;
/* clock setting */
if (fsi_is_clk_master(fsi))
@@ -1534,8 +1610,13 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
fsi_fifo_init(fsi, io, dev);
/* start master clock */
- if (fsi_is_clk_master(fsi))
- return fsi_clk_enable(dev, fsi);
+ if (fsi_is_clk_master(fsi)) {
+ ret = fsi_clk_enable(dev, fsi);
+ if (ret) {
+ clk_disable(fsi->master->clk_spu);
+ return ret;
+ }
+ }
return 0;
}
@@ -1543,9 +1624,15 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
static int fsi_hw_shutdown(struct fsi_priv *fsi,
struct device *dev)
{
+ int ret;
/* stop master clock */
- if (fsi_is_clk_master(fsi))
- return fsi_clk_disable(dev, fsi);
+ if (fsi_is_clk_master(fsi)) {
+ ret = fsi_clk_disable(dev, fsi);
+ if (ret)
+ return ret;
+ }
+ /* stop spu bus bridge clock */
+ clk_disable(fsi->master->clk_spu);
return 0;
}
@@ -1557,7 +1644,7 @@ static int fsi_dai_startup(struct snd_pcm_substream *substream,
fsi_clk_invalid(fsi);
- return 0;
+ return fsi_clk_prepare(fsi);
}
static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
@@ -1565,6 +1652,7 @@ static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
{
struct fsi_priv *fsi = fsi_get_priv(substream);
+ fsi_clk_unprepare(fsi);
fsi_clk_invalid(fsi);
}
@@ -1586,10 +1674,10 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
ret = fsi_stream_transfer(io);
break;
case SNDRV_PCM_TRIGGER_STOP:
- if (!ret)
- ret = fsi_hw_shutdown(fsi, dai->dev);
fsi_stream_stop(fsi, io);
fsi_stream_quit(fsi, io);
+ if (!ret)
+ ret = fsi_hw_shutdown(fsi, dai->dev);
break;
}
@@ -1664,15 +1752,6 @@ static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
break;
}
- if (fsi_is_clk_master(fsi)) {
- if (fsi->clk_cpg)
- fsi_clk_init(dai->dev, fsi, 0, 1, 1,
- fsi_clk_set_rate_cpg);
- else
- fsi_clk_init(dai->dev, fsi, 1, 1, 0,
- fsi_clk_set_rate_external);
- }
-
/* set format */
if (fsi_is_spdif(fsi))
ret = fsi_set_fmt_spdif(fsi);
@@ -1694,11 +1773,6 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-/*
- * Select below from Sound Card, not auto
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
- */
static const u64 fsi_dai_formats =
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
@@ -1923,20 +1997,10 @@ static int fsi_probe(struct platform_device *pdev)
memset(&info, 0, sizeof(info));
- core = NULL;
- if (np) {
- core = of_device_get_match_data(&pdev->dev);
- fsi_of_parse("fsia", np, &info.port_a, &pdev->dev);
- fsi_of_parse("fsib", np, &info.port_b, &pdev->dev);
- } else {
- const struct platform_device_id *id_entry = pdev->id_entry;
- if (id_entry)
- core = (struct fsi_core *)id_entry->driver_data;
-
- if (pdev->dev.platform_data)
- memcpy(&info, pdev->dev.platform_data, sizeof(info));
- }
+ fsi_of_parse("fsia", np, &info.port_a, &pdev->dev);
+ fsi_of_parse("fsib", np, &info.port_b, &pdev->dev);
+ core = of_device_get_match_data(&pdev->dev);
if (!core) {
dev_err(&pdev->dev, "unknown fsi device\n");
return -ENODEV;
@@ -1970,6 +2034,11 @@ static int fsi_probe(struct platform_device *pdev)
fsi->master = master;
fsi_port_info_init(fsi, &info.port_a);
fsi_handler_init(fsi, &info.port_a);
+ ret = fsi_clk_init(&pdev->dev, fsi);
+ if (ret) {
+ dev_err(&pdev->dev, "FSIA clk init failed\n");
+ return ret;
+ }
ret = fsi_stream_probe(fsi, &pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "FSIA stream probe failed\n");
@@ -1983,6 +2052,11 @@ static int fsi_probe(struct platform_device *pdev)
fsi->master = master;
fsi_port_info_init(fsi, &info.port_b);
fsi_handler_init(fsi, &info.port_b);
+ ret = fsi_clk_init(&pdev->dev, fsi);
+ if (ret) {
+ dev_err(&pdev->dev, "FSIB clk init failed\n");
+ goto exit_fsia;
+ }
ret = fsi_stream_probe(fsi, &pdev->dev);
if (ret < 0) {
dev_err(&pdev->dev, "FSIB stream probe failed\n");
diff --git a/sound/soc/renesas/rcar/adg.c b/sound/soc/renesas/rcar/adg.c
index 8641b73d1f77..53efd1be5139 100644
--- a/sound/soc/renesas/rcar/adg.c
+++ b/sound/soc/renesas/rcar/adg.c
@@ -19,6 +19,9 @@
#define CLKOUT3 3
#define CLKOUTMAX 4
+/* Maximum SSI count for per-SSI clocks */
+#define ADG_SSI_MAX 10
+
#define BRGCKR_31 (1 << 31)
#define BRRx_MASK(x) (0x3FF & x)
@@ -34,10 +37,15 @@ struct rsnd_adg {
struct clk *adg;
struct clk *clkin[CLKINMAX];
struct clk *clkout[CLKOUTMAX];
+ /* RZ/G3E: per-SSI ADG clocks (adg-ssi-0 through adg-ssi-9) */
+ struct clk *clk_adg_ssi[ADG_SSI_MAX];
+ struct clk *clk_ssif_supply;
struct clk *null_clk;
struct clk_onecell_data onecell;
struct rsnd_mod mod;
int clkin_rate[CLKINMAX];
+ bool ssi_clk_prepared;
+ bool clk_enabled;
int clkin_size;
int clkout_size;
u32 ckr;
@@ -70,6 +78,13 @@ static const char * const clkin_name_gen2[] = {
[CLKI] = "clk_i",
};
+static const char * const clkin_name_rzg3e[] = {
+ [CLKA] = "audio-clka",
+ [CLKB] = "audio-clkb",
+ [CLKC] = "audio-clkc",
+ [CLKI] = "audio-clki",
+};
+
static const char * const clkout_name_gen2[] = {
[CLKOUT] = "audio_clkout",
[CLKOUT1] = "audio_clkout1",
@@ -343,8 +358,16 @@ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate)
int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod)
{
+ struct rsnd_priv *priv = rsnd_mod_to_priv(ssi_mod);
+ struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
+ int id = rsnd_mod_id(ssi_mod);
+
rsnd_adg_set_ssi_clk(ssi_mod, 0);
+ /* RZ/G3E: only disable here, unprepare is done in hw_free */
+ clk_disable(adg->clk_adg_ssi[id]);
+ clk_disable(adg->clk_ssif_supply);
+
return 0;
}
@@ -354,7 +377,8 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_mod *adg_mod = rsnd_mod_get(adg);
- int data;
+ int id = rsnd_mod_id(ssi_mod);
+ int ret, data;
u32 ckr = 0;
data = rsnd_adg_clk_query(priv, rate);
@@ -376,7 +400,61 @@ int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate)
(ckr) ? adg->brg_rate[ADG_HZ_48] :
adg->brg_rate[ADG_HZ_441]);
+ /*
+ * RZ/G3E: enable per-SSI and supply clocks
+ */
+ ret = clk_enable(adg->clk_adg_ssi[id]);
+ if (ret) {
+ dev_err(dev, "Cannot enable adg-ssi-%d ADG clock\n", id);
+ return ret;
+ }
+
+ ret = clk_enable(adg->clk_ssif_supply);
+ if (ret) {
+ dev_err(dev, "Cannot enable SSIF supply clock\n");
+ clk_disable(adg->clk_adg_ssi[id]);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int rsnd_adg_ssi_clk_prepare(struct rsnd_adg *adg)
+{
+ int i, ret;
+
+ if (adg->ssi_clk_prepared)
+ return 0;
+
+ for (i = 0; i < ADG_SSI_MAX; i++) {
+ ret = clk_prepare(adg->clk_adg_ssi[i]);
+ if (ret)
+ goto unwind;
+ }
+ ret = clk_prepare(adg->clk_ssif_supply);
+ if (ret)
+ goto unwind;
+
+ adg->ssi_clk_prepared = true;
return 0;
+
+unwind:
+ while (i--)
+ clk_unprepare(adg->clk_adg_ssi[i]);
+ return ret;
+}
+
+static void rsnd_adg_ssi_clk_unprepare(struct rsnd_adg *adg)
+{
+ int i;
+
+ if (!adg->ssi_clk_prepared)
+ return;
+ adg->ssi_clk_prepared = false;
+
+ clk_unprepare(adg->clk_ssif_supply);
+ for (i = 0; i < ADG_SSI_MAX; i++)
+ clk_unprepare(adg->clk_adg_ssi[i]);
}
int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
@@ -386,6 +464,22 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
struct clk *clk;
int ret = 0, i;
+ /*
+ * rsnd_adg_clk_enable() and rsnd_adg_clk_disable() can be called
+ * redundantly, for example when system suspend follows a resume
+ * whose enable failed. Make this function idempotent so that the
+ * "adg" clock, which has no clkin_rate[] style guard, is never
+ * disabled twice.
+ */
+ if (enable) {
+ if (adg->clk_enabled)
+ return 0;
+ } else {
+ if (!adg->clk_enabled)
+ return 0;
+ adg->clk_enabled = false;
+ }
+
if (enable) {
ret = clk_prepare_enable(adg->adg);
if (ret < 0)
@@ -421,12 +515,44 @@ int rsnd_adg_clk_control(struct rsnd_priv *priv, int enable)
* rsnd_adg_clk_enable() might return error (_disable() will not).
* We need to rollback in such case
*/
- if (ret < 0)
+ /*
+ * RZ/G3E per-SSI ADG and SSIF supply clocks.
+ *
+ * Follow the same style as for_each_rsnd_clkin() above: on enable,
+ * try to prepare every clock and accumulate the error. On disable,
+ * unprepare every clock. Absent optional clocks are NULL, for
+ * which clk_prepare() and clk_unprepare() are no-ops.
+ */
+ if (enable) {
+ int sub_ret = rsnd_adg_ssi_clk_prepare(adg);
+
+ /* Preserve the first error from the clkin loop above. */
+ if (sub_ret && !ret)
+ ret = sub_ret;
+ } else {
+ rsnd_adg_ssi_clk_unprepare(adg);
+ }
+
+ /*
+ * rsnd_adg_clk_enable() might return error (_disable() will not).
+ * We need to rollback in such case
+ */
+ if (ret < 0) {
+ /*
+ * Mark as enabled so that the rollback below is not
+ * short-circuited by the idempotency guard. It clears
+ * the flag again on its way through.
+ */
+ adg->clk_enabled = true;
rsnd_adg_clk_disable(priv);
+ return ret;
+ }
/* disable adg */
if (!enable)
clk_disable_unprepare(adg->adg);
+ else
+ adg->clk_enabled = true;
return ret;
}
@@ -482,6 +608,9 @@ static int rsnd_adg_get_clkin(struct rsnd_priv *priv)
if (rsnd_is_gen4(priv)) {
clkin_name = clkin_name_gen4;
clkin_size = ARRAY_SIZE(clkin_name_gen4);
+ } else if (rsnd_is_rzg3e(priv)) {
+ clkin_name = clkin_name_rzg3e;
+ clkin_size = ARRAY_SIZE(clkin_name_rzg3e);
}
/*
@@ -769,8 +898,34 @@ void rsnd_adg_clk_dbg_info(struct rsnd_priv *priv, struct seq_file *m)
#define rsnd_adg_clk_dbg_info(priv, m)
#endif
+static int rsnd_adg_get_ssi_clks(struct rsnd_priv *priv)
+{
+ struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
+ struct device *dev = rsnd_priv_to_dev(priv);
+ char name[16];
+ int i;
+
+ /* SSIF supply clock */
+ adg->clk_ssif_supply = devm_clk_get_optional(dev, "ssif_supply");
+ if (IS_ERR(adg->clk_ssif_supply))
+ return dev_err_probe(dev, PTR_ERR(adg->clk_ssif_supply),
+ "failed to get ssif_supply clock\n");
+
+ /* Per-SSI ADG clocks (RZ/G3E-only; no legacy dotted form exists) */
+ for (i = 0; i < ADG_SSI_MAX; i++) {
+ snprintf(name, sizeof(name), "adg-ssi-%d", i);
+ adg->clk_adg_ssi[i] = devm_clk_get_optional(dev, name);
+ if (IS_ERR(adg->clk_adg_ssi[i]))
+ return dev_err_probe(dev, PTR_ERR(adg->clk_adg_ssi[i]),
+ "failed to get %s clock\n", name);
+ }
+
+ return 0;
+}
+
int rsnd_adg_probe(struct rsnd_priv *priv)
{
+ struct reset_control *rstc;
struct rsnd_adg *adg;
struct device *dev = rsnd_priv_to_dev(priv);
int ret;
@@ -779,8 +934,11 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
if (!adg)
return -ENOMEM;
- ret = rsnd_mod_init(priv, &adg->mod, &adg_ops,
- NULL, 0, 0);
+ rstc = devm_reset_control_get_optional_exclusive(dev, "adg");
+ if (IS_ERR(rstc))
+ return dev_err_probe(dev, PTR_ERR(rstc), "failed to get adg reset\n");
+
+ ret = rsnd_mod_init(priv, &adg->mod, &adg_ops, NULL, rstc, 0, 0);
if (ret)
return ret;
@@ -794,6 +952,11 @@ int rsnd_adg_probe(struct rsnd_priv *priv)
if (ret)
return ret;
+ /* RZ/G3E-specific: per-SSI ADG and SSIF supply clocks */
+ ret = rsnd_adg_get_ssi_clks(priv);
+ if (ret)
+ return ret;
+
ret = rsnd_adg_clk_enable(priv);
if (ret)
return ret;
@@ -817,3 +980,29 @@ void rsnd_adg_remove(struct rsnd_priv *priv)
/* It should be called after rsnd_adg_clk_disable() */
rsnd_adg_null_clk_clean(priv);
}
+
+static struct rsnd_mod *rsnd_adg_mod_get(struct rsnd_priv *priv)
+{
+ struct rsnd_adg *adg = rsnd_priv_to_adg(priv);
+
+ if (!adg)
+ return NULL;
+
+ return rsnd_mod_get(adg);
+}
+
+void rsnd_adg_suspend(struct rsnd_priv *priv)
+{
+ struct rsnd_mod *mod = rsnd_adg_mod_get(priv);
+
+ if (mod)
+ rsnd_suspend_clk_reset(mod->clk, mod->rstc);
+}
+
+void rsnd_adg_resume(struct rsnd_priv *priv)
+{
+ struct rsnd_mod *mod = rsnd_adg_mod_get(priv);
+
+ if (mod)
+ rsnd_resume_clk_reset(mod->clk, mod->rstc);
+}
diff --git a/sound/soc/renesas/rcar/cmd.c b/sound/soc/renesas/rcar/cmd.c
index 8d9a1e345a22..13beef389797 100644
--- a/sound/soc/renesas/rcar/cmd.c
+++ b/sound/soc/renesas/rcar/cmd.c
@@ -171,7 +171,7 @@ int rsnd_cmd_probe(struct rsnd_priv *priv)
for_each_rsnd_cmd(cmd, priv, i) {
int ret = rsnd_mod_init(priv, rsnd_mod_get(cmd),
- &rsnd_cmd_ops, NULL,
+ &rsnd_cmd_ops, NULL, NULL,
RSND_MOD_CMD, i);
if (ret)
return ret;
diff --git a/sound/soc/renesas/rcar/core.c b/sound/soc/renesas/rcar/core.c
index 2dc078358612..b7954746e953 100644
--- a/sound/soc/renesas/rcar/core.c
+++ b/sound/soc/renesas/rcar/core.c
@@ -106,6 +106,8 @@ static const struct of_device_id rsnd_of_match[] = {
{ .compatible = "renesas,rcar_sound-gen4", .data = (void *)RSND_GEN4 },
/* Special Handling */
{ .compatible = "renesas,rcar_sound-r8a77990", .data = (void *)(RSND_GEN3 | RSND_SOC_E) },
+ { .compatible = "renesas,r9a09g047-sound",
+ .data = (void *)(RSND_RZ3 | RSND_RZG3E | RSND_SSIU_BUSIF_STATUS_COUNT_2) },
{},
};
MODULE_DEVICE_TABLE(of, rsnd_of_match);
@@ -196,18 +198,29 @@ int rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod,
struct rsnd_mod_ops *ops,
struct clk *clk,
+ struct reset_control *rstc,
enum rsnd_mod_type type,
int id)
{
- int ret = clk_prepare(clk);
+ int ret;
+ ret = clk_prepare_enable(clk);
if (ret)
return ret;
+ ret = reset_control_deassert(rstc);
+ if (ret) {
+ clk_disable_unprepare(clk);
+ return ret;
+ }
+
+ clk_disable(clk);
+
mod->id = id;
mod->ops = ops;
mod->type = type;
mod->clk = clk;
+ mod->rstc = rstc;
mod->priv = priv;
return 0;
@@ -215,6 +228,8 @@ int rsnd_mod_init(struct rsnd_priv *priv,
void rsnd_mod_quit(struct rsnd_mod *mod)
{
+ reset_control_assert(mod->rstc);
+ mod->rstc = NULL;
clk_unprepare(mod->clk);
mod->clk = NULL;
}
@@ -947,7 +962,8 @@ static int rsnd_soc_hw_rule_channels(struct snd_pcm_hw_params *params,
static const struct snd_pcm_hardware rsnd_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID,
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_RESUME,
.buffer_bytes_max = 64 * 1024,
.period_bytes_min = 32,
.period_bytes_max = 8192,
@@ -1042,9 +1058,6 @@ static const u64 rsnd_soc_dai_formats[] = {
* 1st Priority
*
* Well tested formats.
- * Select below from Sound Card, not auto
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
*/
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
@@ -1058,8 +1071,15 @@ static const u64 rsnd_soc_dai_formats[] = {
*
* Supported, but not well tested
*/
+ SND_SOC_POSSIBLE_DAIFMT_I2S |
+ SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
+ SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
SND_SOC_POSSIBLE_DAIFMT_DSP_A |
- SND_SOC_POSSIBLE_DAIFMT_DSP_B,
+ SND_SOC_POSSIBLE_DAIFMT_DSP_B |
+ SND_SOC_POSSIBLE_DAIFMT_NB_NF |
+ SND_SOC_POSSIBLE_DAIFMT_NB_IF |
+ SND_SOC_POSSIBLE_DAIFMT_IB_NF |
+ SND_SOC_POSSIBLE_DAIFMT_IB_IF,
};
static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv,
@@ -1219,6 +1239,107 @@ int rsnd_node_count(struct rsnd_priv *priv, struct device_node *node, char *name
return i;
}
+/*
+ * Build "<base>-<index>" or "<base>.<index>" and try the hyphen form first,
+ * falling back to the dot form if the hyphen form is not present. This lets
+ * the driver accept both the new DT convention ("ssi-0", "src-0", ...) and
+ * the legacy R-Car convention ("ssi.0", "src.0", ...) transparently.
+ *
+ * @base: name prefix ("ssi", "src", "ctu", "mix", "dvc", "adg.ssi", ...)
+ * @index: integer suffix
+ *
+ * On -ENOENT from the hyphen form, the dot form is tried. All other errors
+ * (including -EPROBE_DEFER) are returned to the caller unchanged, so
+ * behaviour against the clock and reset frameworks is preserved.
+ */
+#define RSND_INDEXED_NAME_MAX 32
+
+static void rsnd_format_indexed_name(char *buf, size_t buflen, char sep,
+ const char *base, int index)
+{
+ snprintf(buf, buflen, "%s%c%d", base, sep, index);
+}
+
+struct clk *rsnd_devm_clk_get_indexed(struct device *dev,
+ const char *base, int index)
+{
+ char name[RSND_INDEXED_NAME_MAX];
+ struct clk *clk;
+
+ rsnd_format_indexed_name(name, sizeof(name), '-', base, index);
+ clk = devm_clk_get(dev, name);
+ if (!IS_ERR(clk) || PTR_ERR(clk) != -ENOENT)
+ return clk;
+
+ rsnd_format_indexed_name(name, sizeof(name), '.', base, index);
+ return devm_clk_get(dev, name);
+}
+
+struct clk *rsnd_devm_clk_get_optional_indexed(struct device *dev,
+ const char *base, int index)
+{
+ char name[RSND_INDEXED_NAME_MAX];
+ struct clk *clk;
+
+ rsnd_format_indexed_name(name, sizeof(name), '-', base, index);
+ clk = devm_clk_get_optional(dev, name);
+ if (IS_ERR(clk) || clk)
+ return clk;
+
+ rsnd_format_indexed_name(name, sizeof(name), '.', base, index);
+ return devm_clk_get_optional(dev, name);
+}
+
+struct reset_control *
+rsnd_devm_reset_control_get_optional_indexed(struct device *dev,
+ const char *base, int index)
+{
+ char name[RSND_INDEXED_NAME_MAX];
+ struct reset_control *rstc;
+
+ rsnd_format_indexed_name(name, sizeof(name), '-', base, index);
+ rstc = devm_reset_control_get_optional(dev, name);
+ if (IS_ERR(rstc) || rstc)
+ return rstc;
+
+ rsnd_format_indexed_name(name, sizeof(name), '.', base, index);
+ return devm_reset_control_get_optional(dev, name);
+}
+
+/*
+ * Strip the "rcar_sound," prefix from a legacy node name.
+ *
+ * The RZ/G3E binding uses unprefixed sub-node names (e.g. "ssi",
+ * "ssiu") while earlier R-Car bindings use the legacy "rcar_sound,*"
+ * form. This helper returns the unprefixed portion (the part after
+ * the comma) or NULL if there is no prefix.
+ *
+ * Centralising the convention here keeps every call site consistent.
+ */
+static const char *rsnd_node_name_strip_prefix(const char *name)
+{
+ const char *comma = strchr(name, ',');
+
+ return comma ? comma + 1 : NULL;
+}
+
+struct device_node *rsnd_parse_of_node(struct rsnd_priv *priv, const char *name)
+{
+ struct device_node *np = rsnd_priv_to_dev(priv)->of_node;
+ struct device_node *node;
+ const char *unprefixed;
+
+ node = of_get_child_by_name(np, name);
+ if (node)
+ return node;
+
+ unprefixed = rsnd_node_name_strip_prefix(name);
+ if (unprefixed)
+ node = of_get_child_by_name(np, unprefixed);
+
+ return node;
+}
+
static struct device_node*
rsnd_pick_endpoint_node_for_ports(struct device_node *e_ports,
struct device_node *e_port)
@@ -2043,11 +2164,35 @@ static void rsnd_remove(struct platform_device *pdev)
remove_func[i](priv);
}
+void rsnd_suspend_clk_reset(struct clk *clk, struct reset_control *rstc)
+{
+ clk_unprepare(clk);
+ reset_control_assert(rstc);
+}
+
+void rsnd_resume_clk_reset(struct clk *clk, struct reset_control *rstc)
+{
+ reset_control_deassert(rstc);
+ clk_prepare(clk);
+}
+
static int rsnd_suspend(struct device *dev)
{
struct rsnd_priv *priv = dev_get_drvdata(dev);
+ /*
+ * Reverse order of probe:
+ * ADG -> DVC -> MIX -> CTU -> SRC -> SSIU -> SSI -> DMA
+ */
rsnd_adg_clk_disable(priv);
+ rsnd_adg_suspend(priv);
+ rsnd_dvc_suspend(priv);
+ rsnd_mix_suspend(priv);
+ rsnd_ctu_suspend(priv);
+ rsnd_src_suspend(priv);
+ rsnd_ssiu_suspend(priv);
+ rsnd_ssi_suspend(priv);
+ rsnd_dma_suspend(priv);
return 0;
}
@@ -2056,7 +2201,21 @@ static int rsnd_resume(struct device *dev)
{
struct rsnd_priv *priv = dev_get_drvdata(dev);
- return rsnd_adg_clk_enable(priv);
+ /*
+ * Same order as probe:
+ * DMA -> SSI -> SSIU -> SRC -> CTU -> MIX -> DVC -> ADG
+ */
+ rsnd_dma_resume(priv);
+ rsnd_ssi_resume(priv);
+ rsnd_ssiu_resume(priv);
+ rsnd_src_resume(priv);
+ rsnd_ctu_resume(priv);
+ rsnd_mix_resume(priv);
+ rsnd_dvc_resume(priv);
+ rsnd_adg_resume(priv);
+ rsnd_adg_clk_enable(priv);
+
+ return 0;
}
static const struct dev_pm_ops rsnd_pm_ops = {
diff --git a/sound/soc/renesas/rcar/ctu.c b/sound/soc/renesas/rcar/ctu.c
index bd4c61f9fb3c..7db0fb3612bc 100644
--- a/sound/soc/renesas/rcar/ctu.c
+++ b/sound/soc/renesas/rcar/ctu.c
@@ -6,7 +6,6 @@
#include "rsnd.h"
-#define CTU_NAME_SIZE 16
#define CTU_NAME "ctu"
/*
@@ -319,7 +318,6 @@ int rsnd_ctu_probe(struct rsnd_priv *priv)
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_ctu *ctu;
struct clk *clk;
- char name[CTU_NAME_SIZE];
int i, nr, ret;
node = rsnd_ctu_of_node(priv);
@@ -350,17 +348,14 @@ int rsnd_ctu_probe(struct rsnd_priv *priv)
* CTU00, CTU01, CTU02, CTU03 => CTU0
* CTU10, CTU11, CTU12, CTU13 => CTU1
*/
- snprintf(name, CTU_NAME_SIZE, "%s.%d",
- CTU_NAME, i / 4);
-
- clk = devm_clk_get(dev, name);
+ clk = rsnd_devm_clk_get_indexed(dev, CTU_NAME, i / 4);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
goto rsnd_ctu_probe_done;
}
ret = rsnd_mod_init(priv, rsnd_mod_get(ctu), &rsnd_ctu_ops,
- clk, RSND_MOD_CTU, i);
+ clk, NULL, RSND_MOD_CTU, i);
if (ret)
goto rsnd_ctu_probe_done;
@@ -383,3 +378,23 @@ void rsnd_ctu_remove(struct rsnd_priv *priv)
rsnd_mod_quit(rsnd_mod_get(ctu));
}
}
+
+void rsnd_ctu_suspend(struct rsnd_priv *priv)
+{
+ struct rsnd_ctu *ctu;
+ int i;
+
+ for_each_rsnd_ctu(ctu, priv, i)
+ rsnd_suspend_clk_reset(rsnd_mod_get(ctu)->clk,
+ rsnd_mod_get(ctu)->rstc);
+}
+
+void rsnd_ctu_resume(struct rsnd_priv *priv)
+{
+ struct rsnd_ctu *ctu;
+ int i;
+
+ for_each_rsnd_ctu(ctu, priv, i)
+ rsnd_resume_clk_reset(rsnd_mod_get(ctu)->clk,
+ rsnd_mod_get(ctu)->rstc);
+}
diff --git a/sound/soc/renesas/rcar/dma.c b/sound/soc/renesas/rcar/dma.c
index 2035ce06fe4c..793dd4adbe5c 100644
--- a/sound/soc/renesas/rcar/dma.c
+++ b/sound/soc/renesas/rcar/dma.c
@@ -47,6 +47,9 @@ struct rsnd_dma_ctrl {
phys_addr_t ppres;
int dmaen_num;
int dmapp_num;
+ /* RZ/G3E: Audio DMAC peri-peri clock and reset */
+ struct clk *audmapp_clk;
+ struct reset_control *audmapp_rstc;
};
#define rsnd_priv_to_dmac(p) ((struct rsnd_dma_ctrl *)(p)->dma)
@@ -478,6 +481,69 @@ static struct rsnd_mod_ops rsnd_dmapp_ops = {
DEBUG_INFO
};
+struct rsnd_dma_addr {
+ dma_addr_t out_addr;
+ dma_addr_t in_addr;
+};
+
+struct rsnd_dma_addr_dir {
+ struct rsnd_dma_addr capture[3];
+ struct rsnd_dma_addr playback[3];
+};
+
+struct rsnd_dma_addr_map {
+ struct rsnd_dma_addr_dir src;
+ struct rsnd_dma_addr_dir ssi;
+ struct rsnd_dma_addr_dir ssiu;
+};
+
+static dma_addr_t
+rsnd_dma_addr_lookup(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod,
+ struct rsnd_priv *priv,
+ const struct rsnd_dma_addr_map *map,
+ int is_play, int is_from)
+{
+ struct device *dev = rsnd_priv_to_dev(priv);
+ int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod) ||
+ !!(rsnd_io_to_mod_ssiu(io) == mod);
+ int use_src = !!rsnd_io_to_mod_src(io);
+ int use_cmd = !!rsnd_io_to_mod_dvc(io) ||
+ !!rsnd_io_to_mod_mix(io) ||
+ !!rsnd_io_to_mod_ctu(io);
+ int id = rsnd_mod_id(mod);
+ const struct rsnd_dma_addr_dir *dir;
+ const struct rsnd_dma_addr *addr;
+
+ /* it shouldn't happen */
+ if (use_cmd && !use_src)
+ dev_err(dev, "DVC is selected without SRC\n");
+
+ /* use SSIU or SSI? */
+ if (is_ssi && rsnd_ssi_use_busif(io))
+ is_ssi++;
+
+ dev_dbg(dev, "dma%d addr : is_ssi=%d use_src=%d use_cmd=%d\n",
+ id, is_ssi, use_src, use_cmd);
+
+ switch (is_ssi) {
+ case 2:
+ dir = &map->ssiu;
+ break;
+ case 1:
+ dir = &map->ssi;
+ break;
+ default:
+ dir = &map->src;
+ break;
+ }
+
+ addr = is_play ? &dir->playback[use_src + use_cmd]
+ : &dir->capture[use_src + use_cmd];
+
+ return is_from ? addr->out_addr : addr->in_addr;
+}
+
/*
* Common DMAC Interface
*/
@@ -524,47 +590,45 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
struct device *dev = rsnd_priv_to_dev(priv);
phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SSI);
phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SCU);
- int is_ssi = !!(rsnd_io_to_mod_ssi(io) == mod) ||
- !!(rsnd_io_to_mod_ssiu(io) == mod);
- int use_src = !!rsnd_io_to_mod_src(io);
- int use_cmd = !!rsnd_io_to_mod_dvc(io) ||
- !!rsnd_io_to_mod_mix(io) ||
- !!rsnd_io_to_mod_ctu(io);
int id = rsnd_mod_id(mod);
int busif = rsnd_mod_id_sub(rsnd_io_to_mod_ssiu(io));
- struct dma_addr {
- dma_addr_t out_addr;
- dma_addr_t in_addr;
- } dma_addrs[3][2][3] = {
- /* SRC */
- /* Capture */
- {{{ 0, 0 },
- { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) },
- { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) } },
- /* Playback */
- {{ 0, 0, },
- { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) },
- { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) } }
+ const struct rsnd_dma_addr_map map = {
+ .src = {
+ .capture = {
+ { 0, 0 },
+ { RDMA_SRC_O_N(src, id), RDMA_SRC_I_P(src, id) },
+ { RDMA_CMD_O_N(src, id), RDMA_SRC_I_P(src, id) },
+ },
+ .playback = {
+ { 0, 0 },
+ { RDMA_SRC_O_P(src, id), RDMA_SRC_I_N(src, id) },
+ { RDMA_CMD_O_P(src, id), RDMA_SRC_I_N(src, id) },
+ },
},
- /* SSI */
- /* Capture */
- {{{ RDMA_SSI_O_N(ssi, id), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 } },
- /* Playback */
- {{ 0, RDMA_SSI_I_N(ssi, id) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) } }
+ .ssi = {
+ .capture = {
+ { RDMA_SSI_O_N(ssi, id), 0 },
+ { RDMA_SSIU_O_P(ssi, id, busif), 0 },
+ { RDMA_SSIU_O_P(ssi, id, busif), 0 },
+ },
+ .playback = {
+ { 0, RDMA_SSI_I_N(ssi, id) },
+ { 0, RDMA_SSIU_I_P(ssi, id, busif) },
+ { 0, RDMA_SSIU_I_P(ssi, id, busif) },
+ },
+ },
+ .ssiu = {
+ .capture = {
+ { RDMA_SSIU_O_N(ssi, id, busif), 0 },
+ { RDMA_SSIU_O_P(ssi, id, busif), 0 },
+ { RDMA_SSIU_O_P(ssi, id, busif), 0 },
+ },
+ .playback = {
+ { 0, RDMA_SSIU_I_N(ssi, id, busif) },
+ { 0, RDMA_SSIU_I_P(ssi, id, busif) },
+ { 0, RDMA_SSIU_I_P(ssi, id, busif) },
+ },
},
- /* SSIU */
- /* Capture */
- {{{ RDMA_SSIU_O_N(ssi, id, busif), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 },
- { RDMA_SSIU_O_P(ssi, id, busif), 0 } },
- /* Playback */
- {{ 0, RDMA_SSIU_I_N(ssi, id, busif) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) },
- { 0, RDMA_SSIU_I_P(ssi, id, busif) } } },
};
/*
@@ -577,17 +641,86 @@ rsnd_gen2_dma_addr(struct rsnd_dai_stream *io,
dev_err(dev, "This driver doesn't support SSI%d-%d, so far",
id, busif);
- /* it shouldn't happen */
- if (use_cmd && !use_src)
- dev_err(dev, "DVC is selected without SRC\n");
+ return rsnd_dma_addr_lookup(io, mod, priv, &map, is_play, is_from);
+}
- /* use SSIU or SSI ? */
- if (is_ssi && rsnd_ssi_use_busif(io))
- is_ssi++;
+/*
+ * ex) G3E case
+ * mod / DMAC in / DMAC out / DMAC PP in / DMAC pp out
+ * SSI : 0x13C31000 / 0x13C40000 / 0x13C40000
+ * SSIU: 0x13C31000 / 0x13C40000 / 0x13C40000 / 0xEC400000 / 0xEC400000
+ * SCU : 0x13C00000 / 0x13C10000 / 0x13C14000 / 0xEC300000 / 0xEC304000
+ * CMD : 0x13C00000 / / 0x13C18000 0xEC308000
+ */
+
+/* RZ/G3E DMA address macros */
+#define RDMA_SSI_I_N_G3E(addr, i) (addr ##_reg + 0x0000F000 + (0x1000 * (i)))
+#define RDMA_SSI_O_N_G3E(addr, i) (addr ##_reg + 0x0000F000 + (0x1000 * (i)))
+
+#define RDMA_SSIU_I_N_G3E(addr, i, j) (addr ##_reg + 0x0000F000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
+#define RDMA_SSIU_O_N_G3E(addr, i, j) RDMA_SSIU_I_N_G3E(addr, i, j)
+
+#define RDMA_SSIU_I_P_G3E(addr, i, j) (addr ##_reg + 0xD87CF000 + (0x1000 * (i)) + (((j) / 4) * 0xA000) + (((j) % 4) * 0x400) - (0x4000 * ((i) / 9) * ((j) / 4)))
+#define RDMA_SSIU_O_P_G3E(addr, i, j) RDMA_SSIU_I_P_G3E(addr, i, j)
+
+#define RDMA_SRC_I_N_G3E(addr, i) (addr ##_reg + 0x00010000 + (0x400 * (i)))
+#define RDMA_SRC_O_N_G3E(addr, i) (addr ##_reg + 0x00014000 + (0x400 * (i)))
+
+#define RDMA_SRC_I_P_G3E(addr, i) (addr ##_reg + 0xD8700000 + (0x400 * (i)))
+#define RDMA_SRC_O_P_G3E(addr, i) (addr ##_reg + 0xD8704000 + (0x400 * (i)))
- return (is_from) ?
- dma_addrs[is_ssi][is_play][use_src + use_cmd].out_addr :
- dma_addrs[is_ssi][is_play][use_src + use_cmd].in_addr;
+#define RDMA_CMD_O_N_G3E(addr, i) (addr ##_reg + 0x00018000 + (0x400 * (i)))
+#define RDMA_CMD_O_P_G3E(addr, i) (addr ##_reg + 0xD8708000 + (0x400 * (i)))
+
+static dma_addr_t
+rsnd_rzg3e_dma_addr(struct rsnd_dai_stream *io,
+ struct rsnd_mod *mod, int is_play, int is_from)
+{
+ struct rsnd_priv *priv = rsnd_io_to_priv(io);
+ phys_addr_t ssi_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SSI);
+ phys_addr_t src_reg = rsnd_gen_get_phy_addr(priv, RSND_BASE_SCU);
+ int id = rsnd_mod_id(mod);
+ int busif = rsnd_mod_id_sub(rsnd_io_to_mod_ssiu(io));
+ const struct rsnd_dma_addr_map map = {
+ .src = {
+ .capture = {
+ { 0, 0 },
+ { RDMA_SRC_O_N_G3E(src, id), RDMA_SRC_I_P_G3E(src, id) },
+ { RDMA_CMD_O_N_G3E(src, id), RDMA_SRC_I_P_G3E(src, id) },
+ },
+ .playback = {
+ { 0, 0 },
+ { RDMA_SRC_O_P_G3E(src, id), RDMA_SRC_I_N_G3E(src, id) },
+ { RDMA_CMD_O_P_G3E(src, id), RDMA_SRC_I_N_G3E(src, id) },
+ },
+ },
+ .ssi = {
+ .capture = {
+ { RDMA_SSI_O_N_G3E(ssi, id), 0 },
+ { RDMA_SSIU_O_P_G3E(ssi, id, busif), 0 },
+ { RDMA_SSIU_O_P_G3E(ssi, id, busif), 0 },
+ },
+ .playback = {
+ { 0, RDMA_SSI_I_N_G3E(ssi, id) },
+ { 0, RDMA_SSIU_I_P_G3E(ssi, id, busif) },
+ { 0, RDMA_SSIU_I_P_G3E(ssi, id, busif) },
+ },
+ },
+ .ssiu = {
+ .capture = {
+ { RDMA_SSIU_O_N_G3E(ssi, id, busif), 0 },
+ { RDMA_SSIU_O_P_G3E(ssi, id, busif), 0 },
+ { RDMA_SSIU_O_P_G3E(ssi, id, busif), 0 },
+ },
+ .playback = {
+ { 0, RDMA_SSIU_I_N_G3E(ssi, id, busif) },
+ { 0, RDMA_SSIU_I_P_G3E(ssi, id, busif) },
+ { 0, RDMA_SSIU_I_P_G3E(ssi, id, busif) },
+ },
+ },
+ };
+
+ return rsnd_dma_addr_lookup(io, mod, priv, &map, is_play, is_from);
}
/*
@@ -636,6 +769,8 @@ static dma_addr_t rsnd_dma_addr(struct rsnd_dai_stream *io,
return 0;
else if (rsnd_is_gen4(priv))
return rsnd_gen4_dma_addr(io, mod, is_play, is_from);
+ else if (rsnd_is_rzg3e(priv))
+ return rsnd_rzg3e_dma_addr(io, mod, is_play, is_from);
else
return rsnd_gen2_dma_addr(io, mod, is_play, is_from);
}
@@ -659,11 +794,11 @@ static void rsnd_dma_of_path(struct rsnd_mod *this,
int nr, i, idx;
/*
- * It should use "rcar_sound,ssiu" on DT.
- * But, we need to keep compatibility for old version.
+ * It should use "rcar_sound,ssiu" (R-Car) or "ssiu" (RZ/G3E) on DT.
+ * We need to keep compatibility for old version.
*
- * If it has "rcar_sound.ssiu", it will be used.
- * If not, "rcar_sound.ssi" will be used.
+ * If it has "rcar_sound.ssiu" or "ssiu", it will be used.
+ * If not, "rcar_sound.ssi" or "ssi" will be used.
* see
* rsnd_ssiu_dma_req()
* rsnd_ssi_dma_req()
@@ -803,7 +938,7 @@ static int rsnd_dma_alloc(struct rsnd_dai_stream *io, struct rsnd_mod *mod,
*dma_mod = rsnd_mod_get(dma);
- ret = rsnd_mod_init(priv, *dma_mod, ops, NULL,
+ ret = rsnd_mod_init(priv, *dma_mod, ops, NULL, NULL,
type, dma_id);
if (ret < 0)
return ret;
@@ -870,6 +1005,25 @@ int rsnd_dma_probe(struct rsnd_priv *priv)
return 0; /* it will be PIO mode */
}
+ /*
+ * Audio DMAC peri-peri clock and reset for RZ/G3E.
+ * These use optional APIs, so they gracefully return NULL
+ * (no error) on platforms whose DT does not provide them.
+ *
+ * Enable the clock first so the block sees a stable clock on
+ * the way out of reset, then deassert the reset line.
+ */
+ dmac->audmapp_clk = devm_clk_get_optional_enabled(dev, "audmapp");
+ if (IS_ERR(dmac->audmapp_clk))
+ return dev_err_probe(dev, PTR_ERR(dmac->audmapp_clk),
+ "failed to get audmapp clock\n");
+
+ dmac->audmapp_rstc =
+ devm_reset_control_get_optional_exclusive_deasserted(dev, "audmapp");
+ if (IS_ERR(dmac->audmapp_rstc))
+ return dev_err_probe(dev, PTR_ERR(dmac->audmapp_rstc),
+ "failed to get audmapp reset\n");
+
dmac->dmapp_num = 0;
dmac->ppres = res->start;
dmac->ppbase = devm_ioremap_resource(dev, res);
@@ -879,5 +1033,27 @@ audmapp_end:
priv->dma = dmac;
/* dummy mem mod for debug */
- return rsnd_mod_init(NULL, &mem, &mem_ops, NULL, 0, 0);
+ return rsnd_mod_init(NULL, &mem, &mem_ops, NULL, NULL, 0, 0);
+}
+
+void rsnd_dma_suspend(struct rsnd_priv *priv)
+{
+ struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
+
+ if (dmac) {
+ /* Mirror probe (which enables clk before deasserting reset) */
+ rsnd_suspend_clk_reset(NULL, dmac->audmapp_rstc);
+ clk_disable_unprepare(dmac->audmapp_clk);
+ }
+}
+
+void rsnd_dma_resume(struct rsnd_priv *priv)
+{
+ struct rsnd_dma_ctrl *dmac = rsnd_priv_to_dmac(priv);
+
+ if (dmac) {
+ /* Clock must be stable before reset is deasserted */
+ clk_prepare_enable(dmac->audmapp_clk);
+ rsnd_resume_clk_reset(NULL, dmac->audmapp_rstc);
+ }
}
diff --git a/sound/soc/renesas/rcar/dvc.c b/sound/soc/renesas/rcar/dvc.c
index 988cbddbc611..7601dfb0810a 100644
--- a/sound/soc/renesas/rcar/dvc.c
+++ b/sound/soc/renesas/rcar/dvc.c
@@ -29,7 +29,6 @@
#include "rsnd.h"
-#define RSND_DVC_NAME_SIZE 16
#define DVC_NAME "dvc"
@@ -327,7 +326,6 @@ int rsnd_dvc_probe(struct rsnd_priv *priv)
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_dvc *dvc;
struct clk *clk;
- char name[RSND_DVC_NAME_SIZE];
int i, nr, ret;
node = rsnd_dvc_of_node(priv);
@@ -354,17 +352,14 @@ int rsnd_dvc_probe(struct rsnd_priv *priv)
for_each_child_of_node_scoped(node, np) {
dvc = rsnd_dvc_get(priv, i);
- snprintf(name, RSND_DVC_NAME_SIZE, "%s.%d",
- DVC_NAME, i);
-
- clk = devm_clk_get(dev, name);
+ clk = rsnd_devm_clk_get_indexed(dev, DVC_NAME, i);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
goto rsnd_dvc_probe_done;
}
ret = rsnd_mod_init(priv, rsnd_mod_get(dvc), &rsnd_dvc_ops,
- clk, RSND_MOD_DVC, i);
+ clk, NULL, RSND_MOD_DVC, i);
if (ret)
goto rsnd_dvc_probe_done;
@@ -386,3 +381,23 @@ void rsnd_dvc_remove(struct rsnd_priv *priv)
rsnd_mod_quit(rsnd_mod_get(dvc));
}
}
+
+void rsnd_dvc_suspend(struct rsnd_priv *priv)
+{
+ struct rsnd_dvc *dvc;
+ int i;
+
+ for_each_rsnd_dvc(dvc, priv, i)
+ rsnd_suspend_clk_reset(rsnd_mod_get(dvc)->clk,
+ rsnd_mod_get(dvc)->rstc);
+}
+
+void rsnd_dvc_resume(struct rsnd_priv *priv)
+{
+ struct rsnd_dvc *dvc;
+ int i;
+
+ for_each_rsnd_dvc(dvc, priv, i)
+ rsnd_resume_clk_reset(rsnd_mod_get(dvc)->clk,
+ rsnd_mod_get(dvc)->rstc);
+}
diff --git a/sound/soc/renesas/rcar/gen.c b/sound/soc/renesas/rcar/gen.c
index d1f20cde66be..05d5f656fb01 100644
--- a/sound/soc/renesas/rcar/gen.c
+++ b/sound/soc/renesas/rcar/gen.c
@@ -465,6 +465,184 @@ static int rsnd_gen1_probe(struct rsnd_priv *priv)
}
/*
+ * RZ/G3E Generation
+ */
+static int rsnd_rzg3e_probe(struct rsnd_priv *priv)
+{
+ static const struct rsnd_regmap_field_conf conf_ssiu[] = {
+ RSND_GEN_S_REG(SSI_MODE1, 0x804),
+ RSND_GEN_S_REG(SSI_MODE2, 0x808),
+ RSND_GEN_S_REG(SSI_MODE3, 0x80c),
+ RSND_GEN_S_REG(SSI_CONTROL, 0x810),
+ RSND_GEN_S_REG(SSI_CONTROL2, 0x814),
+ RSND_GEN_S_REG(SSI_SYS_STATUS0, 0x840),
+ RSND_GEN_S_REG(SSI_SYS_STATUS1, 0x844),
+ RSND_GEN_S_REG(SSI_SYS_STATUS2, 0x848),
+ RSND_GEN_S_REG(SSI_SYS_STATUS3, 0x84c),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE0, 0x850),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE1, 0x854),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE2, 0x858),
+ RSND_GEN_S_REG(SSI_SYS_INT_ENABLE3, 0x85c),
+ RSND_GEN_M_REG(SSI_BUSIF0_MODE, 0x0, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF0_ADINR, 0x4, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF0_DALIGN, 0x8, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF1_MODE, 0x20, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF1_ADINR, 0x24, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF1_DALIGN, 0x28, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF2_MODE, 0x40, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF2_ADINR, 0x44, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF2_DALIGN, 0x48, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF3_MODE, 0x60, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF3_ADINR, 0x64, 0x80),
+ RSND_GEN_M_REG(SSI_BUSIF3_DALIGN, 0x68, 0x80),
+ RSND_GEN_M_REG(SSI_MODE, 0xc, 0x80),
+ RSND_GEN_M_REG(SSI_CTRL, 0x10, 0x80),
+ RSND_GEN_M_REG(SSI_INT_ENABLE, 0x18, 0x80),
+ RSND_GEN_S_REG(SSI9_BUSIF0_MODE, 0x480),
+ RSND_GEN_S_REG(SSI9_BUSIF0_ADINR, 0x484),
+ RSND_GEN_S_REG(SSI9_BUSIF0_DALIGN, 0x488),
+ RSND_GEN_S_REG(SSI9_BUSIF1_MODE, 0x4a0),
+ RSND_GEN_S_REG(SSI9_BUSIF1_ADINR, 0x4a4),
+ RSND_GEN_S_REG(SSI9_BUSIF1_DALIGN, 0x4a8),
+ RSND_GEN_S_REG(SSI9_BUSIF2_MODE, 0x4c0),
+ RSND_GEN_S_REG(SSI9_BUSIF2_ADINR, 0x4c4),
+ RSND_GEN_S_REG(SSI9_BUSIF2_DALIGN, 0x4c8),
+ RSND_GEN_S_REG(SSI9_BUSIF3_MODE, 0x4e0),
+ RSND_GEN_S_REG(SSI9_BUSIF3_ADINR, 0x4e4),
+ RSND_GEN_S_REG(SSI9_BUSIF3_DALIGN, 0x4e8),
+ };
+ static const struct rsnd_regmap_field_conf conf_scu[] = {
+ RSND_GEN_M_REG(SRC_I_BUSIF_MODE, 0x0, 0x20),
+ RSND_GEN_M_REG(SRC_O_BUSIF_MODE, 0x4, 0x20),
+ RSND_GEN_M_REG(SRC_BUSIF_DALIGN, 0x8, 0x20),
+ RSND_GEN_M_REG(SRC_ROUTE_MODE0, 0xc, 0x20),
+ RSND_GEN_M_REG(SRC_CTRL, 0x10, 0x20),
+ RSND_GEN_M_REG(SRC_INT_ENABLE0, 0x18, 0x20),
+ RSND_GEN_M_REG(CMD_BUSIF_MODE, 0x184, 0x20),
+ RSND_GEN_M_REG(CMD_BUSIF_DALIGN, 0x188, 0x20),
+ RSND_GEN_M_REG(CMD_ROUTE_SLCT, 0x18c, 0x20),
+ RSND_GEN_M_REG(CMD_CTRL, 0x190, 0x20),
+ RSND_GEN_S_REG(SCU_SYS_STATUS0, 0x1c8),
+ RSND_GEN_S_REG(SCU_SYS_INT_EN0, 0x1cc),
+ RSND_GEN_S_REG(SCU_SYS_STATUS1, 0x1d0),
+ RSND_GEN_S_REG(SCU_SYS_INT_EN1, 0x1d4),
+ RSND_GEN_M_REG(SRC_SWRSR, 0x200, 0x40),
+ RSND_GEN_M_REG(SRC_SRCIR, 0x204, 0x40),
+ RSND_GEN_M_REG(SRC_ADINR, 0x214, 0x40),
+ RSND_GEN_M_REG(SRC_IFSCR, 0x21c, 0x40),
+ RSND_GEN_M_REG(SRC_IFSVR, 0x220, 0x40),
+ RSND_GEN_M_REG(SRC_SRCCR, 0x224, 0x40),
+ RSND_GEN_M_REG(SRC_BSDSR, 0x22c, 0x40),
+ RSND_GEN_M_REG(SRC_BSISR, 0x238, 0x40),
+ RSND_GEN_M_REG(CTU_SWRSR, 0x500, 0x100),
+ RSND_GEN_M_REG(CTU_CTUIR, 0x504, 0x100),
+ RSND_GEN_M_REG(CTU_ADINR, 0x508, 0x100),
+ RSND_GEN_M_REG(CTU_CPMDR, 0x510, 0x100),
+ RSND_GEN_M_REG(CTU_SCMDR, 0x514, 0x100),
+ RSND_GEN_M_REG(CTU_SV00R, 0x518, 0x100),
+ RSND_GEN_M_REG(CTU_SV01R, 0x51c, 0x100),
+ RSND_GEN_M_REG(CTU_SV02R, 0x520, 0x100),
+ RSND_GEN_M_REG(CTU_SV03R, 0x524, 0x100),
+ RSND_GEN_M_REG(CTU_SV04R, 0x528, 0x100),
+ RSND_GEN_M_REG(CTU_SV05R, 0x52c, 0x100),
+ RSND_GEN_M_REG(CTU_SV06R, 0x530, 0x100),
+ RSND_GEN_M_REG(CTU_SV07R, 0x534, 0x100),
+ RSND_GEN_M_REG(CTU_SV10R, 0x538, 0x100),
+ RSND_GEN_M_REG(CTU_SV11R, 0x53c, 0x100),
+ RSND_GEN_M_REG(CTU_SV12R, 0x540, 0x100),
+ RSND_GEN_M_REG(CTU_SV13R, 0x544, 0x100),
+ RSND_GEN_M_REG(CTU_SV14R, 0x548, 0x100),
+ RSND_GEN_M_REG(CTU_SV15R, 0x54c, 0x100),
+ RSND_GEN_M_REG(CTU_SV16R, 0x550, 0x100),
+ RSND_GEN_M_REG(CTU_SV17R, 0x554, 0x100),
+ RSND_GEN_M_REG(CTU_SV20R, 0x558, 0x100),
+ RSND_GEN_M_REG(CTU_SV21R, 0x55c, 0x100),
+ RSND_GEN_M_REG(CTU_SV22R, 0x560, 0x100),
+ RSND_GEN_M_REG(CTU_SV23R, 0x564, 0x100),
+ RSND_GEN_M_REG(CTU_SV24R, 0x568, 0x100),
+ RSND_GEN_M_REG(CTU_SV25R, 0x56c, 0x100),
+ RSND_GEN_M_REG(CTU_SV26R, 0x570, 0x100),
+ RSND_GEN_M_REG(CTU_SV27R, 0x574, 0x100),
+ RSND_GEN_M_REG(CTU_SV30R, 0x578, 0x100),
+ RSND_GEN_M_REG(CTU_SV31R, 0x57c, 0x100),
+ RSND_GEN_M_REG(CTU_SV32R, 0x580, 0x100),
+ RSND_GEN_M_REG(CTU_SV33R, 0x584, 0x100),
+ RSND_GEN_M_REG(CTU_SV34R, 0x588, 0x100),
+ RSND_GEN_M_REG(CTU_SV35R, 0x58c, 0x100),
+ RSND_GEN_M_REG(CTU_SV36R, 0x590, 0x100),
+ RSND_GEN_M_REG(CTU_SV37R, 0x594, 0x100),
+ RSND_GEN_M_REG(MIX_SWRSR, 0xd00, 0x40),
+ RSND_GEN_M_REG(MIX_MIXIR, 0xd04, 0x40),
+ RSND_GEN_M_REG(MIX_ADINR, 0xd08, 0x40),
+ RSND_GEN_M_REG(MIX_MIXMR, 0xd10, 0x40),
+ RSND_GEN_M_REG(MIX_MVPDR, 0xd14, 0x40),
+ RSND_GEN_M_REG(MIX_MDBAR, 0xd18, 0x40),
+ RSND_GEN_M_REG(MIX_MDBBR, 0xd1c, 0x40),
+ RSND_GEN_M_REG(MIX_MDBCR, 0xd20, 0x40),
+ RSND_GEN_M_REG(MIX_MDBDR, 0xd24, 0x40),
+ RSND_GEN_M_REG(MIX_MDBER, 0xd28, 0x40),
+ RSND_GEN_M_REG(DVC_SWRSR, 0xe00, 0x100),
+ RSND_GEN_M_REG(DVC_DVUIR, 0xe04, 0x100),
+ RSND_GEN_M_REG(DVC_ADINR, 0xe08, 0x100),
+ RSND_GEN_M_REG(DVC_DVUCR, 0xe10, 0x100),
+ RSND_GEN_M_REG(DVC_ZCMCR, 0xe14, 0x100),
+ RSND_GEN_M_REG(DVC_VRCTR, 0xe18, 0x100),
+ RSND_GEN_M_REG(DVC_VRPDR, 0xe1c, 0x100),
+ RSND_GEN_M_REG(DVC_VRDBR, 0xe20, 0x100),
+ RSND_GEN_M_REG(DVC_VOL0R, 0xe28, 0x100),
+ RSND_GEN_M_REG(DVC_VOL1R, 0xe2c, 0x100),
+ RSND_GEN_M_REG(DVC_VOL2R, 0xe30, 0x100),
+ RSND_GEN_M_REG(DVC_VOL3R, 0xe34, 0x100),
+ RSND_GEN_M_REG(DVC_VOL4R, 0xe38, 0x100),
+ RSND_GEN_M_REG(DVC_VOL5R, 0xe3c, 0x100),
+ RSND_GEN_M_REG(DVC_VOL6R, 0xe40, 0x100),
+ RSND_GEN_M_REG(DVC_VOL7R, 0xe44, 0x100),
+ RSND_GEN_M_REG(DVC_DVUER, 0xe48, 0x100),
+ };
+ static const struct rsnd_regmap_field_conf conf_adg[] = {
+ RSND_GEN_S_REG(BRRA, 0x00),
+ RSND_GEN_S_REG(BRRB, 0x04),
+ RSND_GEN_S_REG(BRGCKR, 0x08),
+ RSND_GEN_S_REG(AUDIO_CLK_SEL0, 0x0c),
+ RSND_GEN_S_REG(AUDIO_CLK_SEL1, 0x10),
+ RSND_GEN_S_REG(AUDIO_CLK_SEL2, 0x14),
+ RSND_GEN_S_REG(AUDIO_CLK_SEL3, 0x18),
+ RSND_GEN_S_REG(DIV_EN, 0x30),
+ RSND_GEN_S_REG(SRCIN_TIMSEL0, 0x34),
+ RSND_GEN_S_REG(SRCIN_TIMSEL1, 0x38),
+ RSND_GEN_S_REG(SRCIN_TIMSEL2, 0x3c),
+ RSND_GEN_S_REG(SRCIN_TIMSEL3, 0x40),
+ RSND_GEN_S_REG(SRCIN_TIMSEL4, 0x44),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL0, 0x48),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL1, 0x4c),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL2, 0x50),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL3, 0x54),
+ RSND_GEN_S_REG(SRCOUT_TIMSEL4, 0x58),
+ RSND_GEN_S_REG(CMDOUT_TIMSEL, 0x5c),
+ };
+ static const struct rsnd_regmap_field_conf conf_ssi[] = {
+ RSND_GEN_M_REG(SSICR, 0x00, 0x40),
+ RSND_GEN_M_REG(SSISR, 0x04, 0x40),
+ RSND_GEN_M_REG(SSIWSR, 0x20, 0x40),
+ };
+ int ret;
+
+ ret = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SCU, "scu", conf_scu);
+ if (ret < 0)
+ return ret;
+
+ ret = rsnd_gen_regmap_init(priv, 1, RSND_BASE_ADG, "adg", conf_adg);
+ if (ret < 0)
+ return ret;
+
+ ret = rsnd_gen_regmap_init(priv, 10, RSND_BASE_SSIU, "ssiu", conf_ssiu);
+ if (ret < 0)
+ return ret;
+
+ return rsnd_gen_regmap_init(priv, 10, RSND_BASE_SSI, "ssi", conf_ssi);
+}
+
+/*
* Gen
*/
int rsnd_gen_probe(struct rsnd_priv *priv)
@@ -487,6 +665,8 @@ int rsnd_gen_probe(struct rsnd_priv *priv)
ret = rsnd_gen2_probe(priv);
else if (rsnd_is_gen4(priv))
ret = rsnd_gen4_probe(priv);
+ else if (rsnd_is_rzg3e(priv))
+ ret = rsnd_rzg3e_probe(priv);
if (ret < 0)
dev_err(dev, "unknown generation R-Car sound device\n");
diff --git a/sound/soc/renesas/rcar/mix.c b/sound/soc/renesas/rcar/mix.c
index aea74e703305..c4da4c4bedb3 100644
--- a/sound/soc/renesas/rcar/mix.c
+++ b/sound/soc/renesas/rcar/mix.c
@@ -32,7 +32,6 @@
#include "rsnd.h"
-#define MIX_NAME_SIZE 16
#define MIX_NAME "mix"
struct rsnd_mix {
@@ -291,7 +290,6 @@ int rsnd_mix_probe(struct rsnd_priv *priv)
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_mix *mix;
struct clk *clk;
- char name[MIX_NAME_SIZE];
int i, nr, ret;
node = rsnd_mix_of_node(priv);
@@ -318,17 +316,14 @@ int rsnd_mix_probe(struct rsnd_priv *priv)
for_each_child_of_node_scoped(node, np) {
mix = rsnd_mix_get(priv, i);
- snprintf(name, MIX_NAME_SIZE, "%s.%d",
- MIX_NAME, i);
-
- clk = devm_clk_get(dev, name);
+ clk = rsnd_devm_clk_get_indexed(dev, MIX_NAME, i);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
goto rsnd_mix_probe_done;
}
ret = rsnd_mod_init(priv, rsnd_mod_get(mix), &rsnd_mix_ops,
- clk, RSND_MOD_MIX, i);
+ clk, NULL, RSND_MOD_MIX, i);
if (ret)
goto rsnd_mix_probe_done;
@@ -350,3 +345,23 @@ void rsnd_mix_remove(struct rsnd_priv *priv)
rsnd_mod_quit(rsnd_mod_get(mix));
}
}
+
+void rsnd_mix_suspend(struct rsnd_priv *priv)
+{
+ struct rsnd_mix *mix;
+ int i;
+
+ for_each_rsnd_mix(mix, priv, i)
+ rsnd_suspend_clk_reset(rsnd_mod_get(mix)->clk,
+ rsnd_mod_get(mix)->rstc);
+}
+
+void rsnd_mix_resume(struct rsnd_priv *priv)
+{
+ struct rsnd_mix *mix;
+ int i;
+
+ for_each_rsnd_mix(mix, priv, i)
+ rsnd_resume_clk_reset(rsnd_mod_get(mix)->clk,
+ rsnd_mod_get(mix)->rstc);
+}
diff --git a/sound/soc/renesas/rcar/msiof.c b/sound/soc/renesas/rcar/msiof.c
index 2671abc028cc..128543fc4fc9 100644
--- a/sound/soc/renesas/rcar/msiof.c
+++ b/sound/soc/renesas/rcar/msiof.c
@@ -363,11 +363,6 @@ static int msiof_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
return 0;
}
-/*
- * Select below from Sound Card, not auto
- * SND_SOC_DAIFMT_CBC_CFC
- * SND_SOC_DAIFMT_CBP_CFP
- */
static const u64 msiof_dai_formats = SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_LEFT_J |
SND_SOC_POSSIBLE_DAIFMT_NB_NF;
diff --git a/sound/soc/renesas/rcar/rsnd.h b/sound/soc/renesas/rcar/rsnd.h
index 04c70690f7a2..b480085fb0e7 100644
--- a/sound/soc/renesas/rcar/rsnd.h
+++ b/sound/soc/renesas/rcar/rsnd.h
@@ -15,6 +15,7 @@
#include <linux/list.h>
#include <linux/module.h>
#include <linux/of.h>
+#include <linux/reset.h>
#include <linux/sh_dma.h>
#include <linux/workqueue.h>
#include <sound/soc.h>
@@ -142,13 +143,16 @@ enum rsnd_reg {
AUDIO_CLK_SEL0,
AUDIO_CLK_SEL1,
AUDIO_CLK_SEL2,
+ AUDIO_CLK_SEL3,
/* SSIU */
SSI_MODE,
SSI_MODE0,
SSI_MODE1,
SSI_MODE2,
+ SSI_MODE3,
SSI_CONTROL,
+ SSI_CONTROL2,
SSI_CTRL,
SSI_BUSIF0_MODE,
SSI_BUSIF1_MODE,
@@ -263,6 +267,8 @@ u32 rsnd_get_busif_shift(struct rsnd_dai_stream *io, struct rsnd_mod *mod);
int rsnd_dma_attach(struct rsnd_dai_stream *io,
struct rsnd_mod *mod, struct rsnd_mod **dma_mod);
int rsnd_dma_probe(struct rsnd_priv *priv);
+void rsnd_dma_suspend(struct rsnd_priv *priv);
+void rsnd_dma_resume(struct rsnd_priv *priv);
struct dma_chan *rsnd_dma_request_channel(struct device_node *of_node, char *name,
struct rsnd_mod *mod, char *x);
@@ -353,6 +359,7 @@ struct rsnd_mod {
struct rsnd_mod_ops *ops;
struct rsnd_priv *priv;
struct clk *clk;
+ struct reset_control *rstc;
u32 status;
};
/*
@@ -420,9 +427,12 @@ int rsnd_mod_init(struct rsnd_priv *priv,
struct rsnd_mod *mod,
struct rsnd_mod_ops *ops,
struct clk *clk,
+ struct reset_control *rstc,
enum rsnd_mod_type type,
int id);
void rsnd_mod_quit(struct rsnd_mod *mod);
+void rsnd_suspend_clk_reset(struct clk *clk, struct reset_control *rstc);
+void rsnd_resume_clk_reset(struct clk *clk, struct reset_control *rstc);
struct dma_chan *rsnd_mod_dma_req(struct rsnd_dai_stream *io,
struct rsnd_mod *mod);
void rsnd_mod_interrupt(struct rsnd_mod *mod,
@@ -474,10 +484,29 @@ int rsnd_runtime_is_tdm(struct rsnd_dai_stream *io);
int rsnd_runtime_is_tdm_split(struct rsnd_dai_stream *io);
/*
+ * Indexed clock and reset name helpers.
+ *
+ * Historically the rsnd driver has looked up per-instance clocks and
+ * resets using dot-separated names (e.g. "ssi.0", "src.0", "adg.ssi.0").
+ * Newer Renesas SoC bindings (RZ/G3E and later) use hyphen-separated
+ * names ("ssi-0", "src-0", ...) to follow the standard Device Tree
+ * naming convention. These helpers look up the hyphenated name first
+ * and transparently fall back to the dotted name, so a single driver
+ * build supports both conventions.
+ */
+struct clk *rsnd_devm_clk_get_indexed(struct device *dev,
+ const char *base, int index);
+struct clk *rsnd_devm_clk_get_optional_indexed(struct device *dev,
+ const char *base, int index);
+struct reset_control *
+rsnd_devm_reset_control_get_optional_indexed(struct device *dev,
+ const char *base, int index);
+
+/*
* DT
*/
-#define rsnd_parse_of_node(priv, node) \
- of_get_child_by_name(rsnd_priv_to_dev(priv)->of_node, node)
+struct device_node *rsnd_parse_of_node(struct rsnd_priv *priv, const char *name);
+
#define RSND_NODE_DAI "rcar_sound,dai"
#define RSND_NODE_SSI "rcar_sound,ssi"
#define RSND_NODE_SSIU "rcar_sound,ssiu"
@@ -600,6 +629,8 @@ int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod);
int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate);
int rsnd_adg_probe(struct rsnd_priv *priv);
void rsnd_adg_remove(struct rsnd_priv *priv);
+void rsnd_adg_suspend(struct rsnd_priv *priv);
+void rsnd_adg_resume(struct rsnd_priv *priv);
int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod,
struct rsnd_dai_stream *io,
unsigned int in_rate,
@@ -619,14 +650,29 @@ struct rsnd_priv {
struct platform_device *pdev;
spinlock_t lock;
unsigned long flags;
+
+ /*
+ * Flags layout: 0xDCBA
+ *
+ * A: R-Car generation (Gen1/Gen2/Gen3/Gen4)
+ * B: R-Car SoC variant (e.g. SOC_E for E1/E2/E3)
+ * C: RZ series generation
+ * D: RZ series SoC identifier (e.g. RZG3E)
+ *
+ * Bits 16+ are used for capability flags.
+ */
#define RSND_GEN_MASK (0xF << 0)
#define RSND_GEN1 (1 << 0)
#define RSND_GEN2 (2 << 0)
#define RSND_GEN3 (3 << 0)
#define RSND_GEN4 (4 << 0)
-#define RSND_SOC_MASK (0xFF << 4)
-#define RSND_SOC_E (1 << 4) /* E1/E2/E3 */
-
+#define RSND_SOC_MASK (0xF << 4) /* nibble B */
+#define RSND_SOC_E (1 << 4) /* E1/E2/E3 */
+#define RSND_RZ_MASK (0xF << 8) /* nibble C */
+#define RSND_RZ3 (3 << 8)
+#define RSND_RZ_ID_MASK (0xF << 12) /* nibble D */
+#define RSND_RZG3E (1 << 12)
+#define RSND_SSIU_BUSIF_STATUS_COUNT_2 BIT(16) /* Only 2 BUSIF error-status register pairs */
/*
* below value will be filled on rsnd_gen_probe()
*/
@@ -651,12 +697,14 @@ struct rsnd_priv {
/*
* below value will be filled on rsnd_ssiu_probe()
*/
+ void *ssiu_ctrl;
void *ssiu;
int ssiu_nr;
/*
* below value will be filled on rsnd_src_probe()
*/
+ void *src_ctrl;
void *src;
int src_nr;
@@ -705,6 +753,9 @@ struct rsnd_priv {
#define rsnd_is_gen3_e3(priv) (((priv)->flags & \
(RSND_GEN_MASK | RSND_SOC_MASK)) == \
(RSND_GEN3 | RSND_SOC_E))
+#define rsnd_is_rzg3e(priv) (((priv)->flags & \
+ (RSND_RZ_MASK | RSND_RZ_ID_MASK)) == \
+ (RSND_RZ3 | RSND_RZG3E))
#define rsnd_flags_has(p, f) ((p)->flags & (f))
#define rsnd_flags_set(p, f) ((p)->flags |= (f))
@@ -777,6 +828,8 @@ extern const char * const volume_ramp_rate[];
*/
int rsnd_ssi_probe(struct rsnd_priv *priv);
void rsnd_ssi_remove(struct rsnd_priv *priv);
+void rsnd_ssi_suspend(struct rsnd_priv *priv);
+void rsnd_ssi_resume(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_ssi_mod_get(struct rsnd_priv *priv, int id);
int rsnd_ssi_use_busif(struct rsnd_dai_stream *io);
u32 rsnd_ssi_multi_secondaries_runtime(struct rsnd_dai_stream *io);
@@ -800,6 +853,8 @@ int rsnd_ssiu_attach(struct rsnd_dai_stream *io,
struct rsnd_mod *mod);
int rsnd_ssiu_probe(struct rsnd_priv *priv);
void rsnd_ssiu_remove(struct rsnd_priv *priv);
+void rsnd_ssiu_suspend(struct rsnd_priv *priv);
+void rsnd_ssiu_resume(struct rsnd_priv *priv);
void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai,
struct device_node *playback,
struct device_node *capture);
@@ -811,6 +866,8 @@ bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod);
*/
int rsnd_src_probe(struct rsnd_priv *priv);
void rsnd_src_remove(struct rsnd_priv *priv);
+void rsnd_src_suspend(struct rsnd_priv *priv);
+void rsnd_src_resume(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_src_mod_get(struct rsnd_priv *priv, int id);
#define rsnd_src_get_in_rate(priv, io) rsnd_src_get_rate(priv, io, 1)
@@ -830,6 +887,8 @@ unsigned int rsnd_src_get_rate(struct rsnd_priv *priv,
*/
int rsnd_ctu_probe(struct rsnd_priv *priv);
void rsnd_ctu_remove(struct rsnd_priv *priv);
+void rsnd_ctu_suspend(struct rsnd_priv *priv);
+void rsnd_ctu_resume(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
#define rsnd_ctu_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_CTU)
#define rsnd_parse_connect_ctu(rdai, playback, capture) \
@@ -842,6 +901,8 @@ struct rsnd_mod *rsnd_ctu_mod_get(struct rsnd_priv *priv, int id);
*/
int rsnd_mix_probe(struct rsnd_priv *priv);
void rsnd_mix_remove(struct rsnd_priv *priv);
+void rsnd_mix_suspend(struct rsnd_priv *priv);
+void rsnd_mix_resume(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
#define rsnd_mix_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_MIX)
#define rsnd_parse_connect_mix(rdai, playback, capture) \
@@ -854,6 +915,8 @@ struct rsnd_mod *rsnd_mix_mod_get(struct rsnd_priv *priv, int id);
*/
int rsnd_dvc_probe(struct rsnd_priv *priv);
void rsnd_dvc_remove(struct rsnd_priv *priv);
+void rsnd_dvc_suspend(struct rsnd_priv *priv);
+void rsnd_dvc_resume(struct rsnd_priv *priv);
struct rsnd_mod *rsnd_dvc_mod_get(struct rsnd_priv *priv, int id);
#define rsnd_dvc_of_node(priv) rsnd_parse_of_node(priv, RSND_NODE_DVC)
#define rsnd_parse_connect_dvc(rdai, playback, capture) \
diff --git a/sound/soc/renesas/rcar/src.c b/sound/soc/renesas/rcar/src.c
index 6a3dbc84f474..2cdb39e898af 100644
--- a/sound/soc/renesas/rcar/src.c
+++ b/sound/soc/renesas/rcar/src.c
@@ -39,7 +39,6 @@ struct rsnd_src {
int irq;
};
-#define RSND_SRC_NAME_SIZE 16
#define rsnd_src_get(priv, id) ((struct rsnd_src *)(priv->src) + id)
#define rsnd_src_nr(priv) ((priv)->src_nr)
@@ -54,6 +53,14 @@ struct rsnd_src {
((pos) = (struct rsnd_src *)(priv)->src + i); \
i++)
+struct rsnd_src_ctrl {
+ struct clk *scu;
+ struct clk *scu_x2;
+ struct clk *scu_supply;
+};
+
+#define rsnd_priv_to_src_ctrl(priv) \
+ ((struct rsnd_src_ctrl *)(priv)->src_ctrl)
/*
* image of SRC (Sampling Rate Converter)
@@ -713,9 +720,10 @@ int rsnd_src_probe(struct rsnd_priv *priv)
{
struct device_node *node;
struct device *dev = rsnd_priv_to_dev(priv);
+ struct reset_control *rstc;
+ struct rsnd_src_ctrl *src_ctrl;
struct rsnd_src *src;
struct clk *clk;
- char name[RSND_SRC_NAME_SIZE];
int i, nr, ret;
node = rsnd_src_of_node(priv);
@@ -728,6 +736,12 @@ int rsnd_src_probe(struct rsnd_priv *priv)
goto rsnd_src_probe_done;
}
+ src_ctrl = devm_kzalloc(dev, sizeof(*src_ctrl), GFP_KERNEL);
+ if (!src_ctrl) {
+ ret = -ENOMEM;
+ goto rsnd_src_probe_done;
+ }
+
src = devm_kcalloc(dev, nr, sizeof(*src), GFP_KERNEL);
if (!src) {
ret = -ENOMEM;
@@ -736,6 +750,38 @@ int rsnd_src_probe(struct rsnd_priv *priv)
priv->src_nr = nr;
priv->src = src;
+ priv->src_ctrl = src_ctrl;
+
+ src_ctrl->scu = devm_clk_get_optional_enabled(dev, "scu");
+ if (IS_ERR(src_ctrl->scu)) {
+ ret = dev_err_probe(dev, PTR_ERR(src_ctrl->scu),
+ "failed to get scu clock\n");
+ goto rsnd_src_probe_done;
+ }
+
+ src_ctrl->scu_x2 = devm_clk_get_optional_enabled(dev, "scu_x2");
+ if (IS_ERR(src_ctrl->scu_x2)) {
+ ret = dev_err_probe(dev, PTR_ERR(src_ctrl->scu_x2),
+ "failed to get scu_x2 clock\n");
+ goto rsnd_src_probe_done;
+ }
+
+ src_ctrl->scu_supply = devm_clk_get_optional_enabled(dev, "scu_supply");
+ if (IS_ERR(src_ctrl->scu_supply)) {
+ ret = dev_err_probe(dev, PTR_ERR(src_ctrl->scu_supply),
+ "failed to get scu_supply clock\n");
+ goto rsnd_src_probe_done;
+ }
+
+ /*
+ * Shared SCU reset for every SRC module; acquire once.
+ * R-Car platforms typically don't have SRC reset controls.
+ */
+ rstc = devm_reset_control_get_optional_shared(dev, "scu");
+ if (IS_ERR(rstc)) {
+ ret = PTR_ERR(rstc);
+ goto rsnd_src_probe_done;
+ }
i = 0;
for_each_child_of_node_scoped(node, np) {
@@ -750,23 +796,20 @@ int rsnd_src_probe(struct rsnd_priv *priv)
src = rsnd_src_get(priv, i);
- snprintf(name, RSND_SRC_NAME_SIZE, "%s.%d",
- SRC_NAME, i);
-
src->irq = irq_of_parse_and_map(np, 0);
if (!src->irq) {
ret = -EINVAL;
goto rsnd_src_probe_done;
}
- clk = devm_clk_get(dev, name);
+ clk = rsnd_devm_clk_get_indexed(dev, SRC_NAME, i);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
goto rsnd_src_probe_done;
}
ret = rsnd_mod_init(priv, rsnd_mod_get(src),
- &rsnd_src_ops, clk, RSND_MOD_SRC, i);
+ &rsnd_src_ops, clk, rstc, RSND_MOD_SRC, i);
if (ret)
goto rsnd_src_probe_done;
@@ -791,3 +834,39 @@ void rsnd_src_remove(struct rsnd_priv *priv)
rsnd_mod_quit(rsnd_mod_get(src));
}
}
+
+void rsnd_src_suspend(struct rsnd_priv *priv)
+{
+ struct rsnd_src_ctrl *src_ctrl = rsnd_priv_to_src_ctrl(priv);
+ struct rsnd_src *src;
+ int i;
+
+ if (!src_ctrl)
+ return;
+
+ for_each_rsnd_src(src, priv, i)
+ rsnd_suspend_clk_reset(rsnd_mod_get(src)->clk,
+ rsnd_mod_get(src)->rstc);
+
+ clk_disable_unprepare(src_ctrl->scu_x2);
+ clk_disable_unprepare(src_ctrl->scu);
+ clk_disable_unprepare(src_ctrl->scu_supply);
+}
+
+void rsnd_src_resume(struct rsnd_priv *priv)
+{
+ struct rsnd_src_ctrl *src_ctrl = rsnd_priv_to_src_ctrl(priv);
+ struct rsnd_src *src;
+ int i;
+
+ if (!src_ctrl)
+ return;
+
+ clk_prepare_enable(src_ctrl->scu_supply);
+ clk_prepare_enable(src_ctrl->scu);
+ clk_prepare_enable(src_ctrl->scu_x2);
+
+ for_each_rsnd_src(src, priv, i)
+ rsnd_resume_clk_reset(rsnd_mod_get(src)->clk,
+ rsnd_mod_get(src)->rstc);
+}
diff --git a/sound/soc/renesas/rcar/ssi.c b/sound/soc/renesas/rcar/ssi.c
index 0420041e282c..2fa76a079982 100644
--- a/sound/soc/renesas/rcar/ssi.c
+++ b/sound/soc/renesas/rcar/ssi.c
@@ -21,7 +21,6 @@
#include <linux/of_irq.h>
#include <linux/delay.h>
#include "rsnd.h"
-#define RSND_SSI_NAME_SIZE 16
/*
* SSICR
@@ -1010,11 +1009,11 @@ static struct dma_chan *rsnd_ssi_dma_req(struct rsnd_dai_stream *io,
char *name;
/*
- * It should use "rcar_sound,ssiu" on DT.
- * But, we need to keep compatibility for old version.
+ * It should use "rcar_sound,ssiu" (R-Car) or "ssiu" (RZ/G3E) on DT.
+ * We need to keep compatibility for old version.
*
- * If it has "rcar_sound.ssiu", it will be used.
- * If not, "rcar_sound.ssi" will be used.
+ * If it has "rcar_sound.ssiu" or "ssiu", it will be used.
+ * If not, "rcar_sound.ssi" or "ssi" will be used.
* see
* rsnd_ssiu_dma_req()
* rsnd_dma_of_path()
@@ -1158,12 +1157,12 @@ int __rsnd_ssi_is_pin_sharing(struct rsnd_mod *mod)
int rsnd_ssi_probe(struct rsnd_priv *priv)
{
+ struct reset_control *rstc;
struct device_node *node;
struct device *dev = rsnd_priv_to_dev(priv);
struct rsnd_mod_ops *ops;
struct clk *clk;
struct rsnd_ssi *ssi;
- char name[RSND_SSI_NAME_SIZE];
int i, nr, ret;
node = rsnd_ssi_of_node(priv);
@@ -1198,15 +1197,23 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
ssi = rsnd_ssi_get(priv, i);
- snprintf(name, RSND_SSI_NAME_SIZE, "%s.%d",
- SSI_NAME, i);
-
- clk = devm_clk_get(dev, name);
+ clk = rsnd_devm_clk_get_indexed(dev, SSI_NAME, i);
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
goto rsnd_ssi_probe_done;
}
+ /*
+ * RZ/G3E uses per-SSI reset controllers.
+ * R-Car platforms typically don't have SSI reset controls.
+ */
+ rstc = rsnd_devm_reset_control_get_optional_indexed(dev,
+ SSI_NAME, i);
+ if (IS_ERR(rstc)) {
+ ret = PTR_ERR(rstc);
+ goto rsnd_ssi_probe_done;
+ }
+
if (of_property_read_bool(np, "shared-pin"))
rsnd_flags_set(ssi, RSND_SSI_CLK_PIN_SHARE);
@@ -1225,7 +1232,7 @@ int rsnd_ssi_probe(struct rsnd_priv *priv)
ops = &rsnd_ssi_dma_ops;
ret = rsnd_mod_init(priv, rsnd_mod_get(ssi), ops, clk,
- RSND_MOD_SSI, i);
+ rstc, RSND_MOD_SSI, i);
if (ret)
goto rsnd_ssi_probe_done;
@@ -1250,3 +1257,23 @@ void rsnd_ssi_remove(struct rsnd_priv *priv)
rsnd_mod_quit(rsnd_mod_get(ssi));
}
}
+
+void rsnd_ssi_suspend(struct rsnd_priv *priv)
+{
+ struct rsnd_ssi *ssi;
+ int i;
+
+ for_each_rsnd_ssi(ssi, priv, i)
+ rsnd_suspend_clk_reset(rsnd_mod_get(ssi)->clk,
+ rsnd_mod_get(ssi)->rstc);
+}
+
+void rsnd_ssi_resume(struct rsnd_priv *priv)
+{
+ struct rsnd_ssi *ssi;
+ int i;
+
+ for_each_rsnd_ssi(ssi, priv, i)
+ rsnd_resume_clk_reset(rsnd_mod_get(ssi)->clk,
+ rsnd_mod_get(ssi)->rstc);
+}
diff --git a/sound/soc/renesas/rcar/ssiu.c b/sound/soc/renesas/rcar/ssiu.c
index 244fb833292a..2a8593a5d4a6 100644
--- a/sound/soc/renesas/rcar/ssiu.c
+++ b/sound/soc/renesas/rcar/ssiu.c
@@ -29,31 +29,39 @@ struct rsnd_ssiu {
i++)
/*
- * SSI Gen2 Gen3 Gen4
- * 0 BUSIF0-3 BUSIF0-7 BUSIF0-7
- * 1 BUSIF0-3 BUSIF0-7
- * 2 BUSIF0-3 BUSIF0-7
- * 3 BUSIF0 BUSIF0-7
- * 4 BUSIF0 BUSIF0-7
- * 5 BUSIF0 BUSIF0
- * 6 BUSIF0 BUSIF0
- * 7 BUSIF0 BUSIF0
- * 8 BUSIF0 BUSIF0
- * 9 BUSIF0-3 BUSIF0-7
- * total 22 52 8
+ * SSI Gen2 Gen3 Gen4 RZ/G3E
+ * 0 BUSIF0-3 BUSIF0-7 BUSIF0-7 BUSIF0-3
+ * 1 BUSIF0-3 BUSIF0-7 BUSIF0-3
+ * 2 BUSIF0-3 BUSIF0-7 BUSIF0-3
+ * 3 BUSIF0 BUSIF0-7 BUSIF0-3
+ * 4 BUSIF0 BUSIF0-7 BUSIF0-3
+ * 5 BUSIF0 BUSIF0 BUSIF0
+ * 6 BUSIF0 BUSIF0 BUSIF0
+ * 7 BUSIF0 BUSIF0 BUSIF0
+ * 8 BUSIF0 BUSIF0 BUSIF0
+ * 9 BUSIF0-3 BUSIF0-7 BUSIF0-3
+ * total 22 52 8 28
*/
static const int gen2_id[] = { 0, 4, 8, 12, 13, 14, 15, 16, 17, 18 };
static const int gen3_id[] = { 0, 8, 16, 24, 32, 40, 41, 42, 43, 44 };
static const int gen4_id[] = { 0 };
+static const int rzg3e_id[] = { 0, 4, 8, 12, 16, 20, 21, 22, 23, 24 };
+
+struct rsnd_ssiu_ctrl {
+ unsigned int busif_status_count;
+};
+
+#define rsnd_priv_to_ssiu_ctrl(priv) \
+ ((struct rsnd_ssiu_ctrl *)(priv)->ssiu_ctrl)
/* enable busif buffer over/under run interrupt. */
#define rsnd_ssiu_busif_err_irq_enable(mod) rsnd_ssiu_busif_err_irq_ctrl(mod, 1)
#define rsnd_ssiu_busif_err_irq_disable(mod) rsnd_ssiu_busif_err_irq_ctrl(mod, 0)
static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable)
{
+ struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
int id = rsnd_mod_id(mod);
int shift, offset;
- int i;
switch (id) {
case 0:
@@ -72,7 +80,7 @@ static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable)
return;
}
- for (i = 0; i < 4; i++) {
+ for (unsigned int i = 0; i < rsnd_priv_to_ssiu_ctrl(priv)->busif_status_count; i++) {
enum rsnd_reg reg = SSI_SYS_INT_ENABLE((i * 2) + offset);
u32 val = 0xf << (shift * 4);
u32 sys_int_enable = rsnd_mod_read(mod, reg);
@@ -87,10 +95,10 @@ static void rsnd_ssiu_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable)
bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod)
{
+ struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
bool error = false;
int id = rsnd_mod_id(mod);
int shift, offset;
- int i;
switch (id) {
case 0:
@@ -109,14 +117,13 @@ bool rsnd_ssiu_busif_err_status_clear(struct rsnd_mod *mod)
goto out;
}
- for (i = 0; i < 4; i++) {
+ for (unsigned int i = 0; i < rsnd_priv_to_ssiu_ctrl(priv)->busif_status_count; i++) {
u32 reg = SSI_SYS_STATUS(i * 2) + offset;
u32 status = rsnd_mod_read(mod, reg);
u32 val = 0xf << (shift * 4);
status &= val;
if (status) {
- struct rsnd_priv *priv = rsnd_mod_to_priv(mod);
struct device *dev = rsnd_priv_to_dev(priv);
rsnd_print_irq_status(dev, "%s err status : 0x%08x\n",
@@ -160,7 +167,8 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
/*
* SSI_MODE0
*/
- rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
+ if (!rsnd_is_rzg3e(priv))
+ rsnd_mod_bset(mod, SSI_MODE0, (1 << id), !use_busif << id);
/*
* SSI_MODE1 / SSI_MODE2
@@ -392,11 +400,11 @@ static struct dma_chan *rsnd_ssiu_dma_req(struct rsnd_dai_stream *io,
char *name;
/*
- * It should use "rcar_sound,ssiu" on DT.
- * But, we need to keep compatibility for old version.
+ * It should use "rcar_sound,ssiu" (R-Car) or "ssiu" (RZ/G3E) on DT.
+ * We need to keep compatibility for old versions.
*
- * If it has "rcar_sound.ssiu", it will be used.
- * If not, "rcar_sound.ssi" will be used.
+ * If it has "rcar_sound.ssiu" or "ssiu", it will be used.
+ * If not, "rcar_sound.ssi" or "ssi" will be used.
* see
* rsnd_ssi_dma_req()
* rsnd_dma_of_path()
@@ -510,6 +518,8 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
{
struct device *dev = rsnd_priv_to_dev(priv);
struct device_node *node __free(device_node) = rsnd_ssiu_of_node(priv);
+ struct reset_control *rstc;
+ struct rsnd_ssiu_ctrl *ctrl;
struct rsnd_ssiu *ssiu;
struct rsnd_mod_ops *ops;
const int *list = NULL;
@@ -534,8 +544,15 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
if (!ssiu)
return -ENOMEM;
+ ctrl = devm_kzalloc(dev, sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ ctrl->busif_status_count = rsnd_flags_has(priv, RSND_SSIU_BUSIF_STATUS_COUNT_2) ? 2 : 4;
+
priv->ssiu = ssiu;
priv->ssiu_nr = nr;
+ priv->ssiu_ctrl = ctrl;
if (rsnd_is_gen1(priv))
ops = &rsnd_ssiu_ops_gen1;
@@ -558,12 +575,21 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
} else if (rsnd_is_gen4(priv)) {
list = gen4_id;
nr = ARRAY_SIZE(gen4_id);
+ } else if (rsnd_is_rzg3e(priv)) {
+ list = rzg3e_id;
+ nr = ARRAY_SIZE(rzg3e_id);
} else {
dev_err(dev, "unknown SSIU\n");
return -ENODEV;
}
}
+ /* Acquire shared reset once for all SSIU modules */
+ rstc = devm_reset_control_get_optional_shared(dev, "ssi-all");
+ if (IS_ERR(rstc))
+ return dev_err_probe(dev, PTR_ERR(rstc),
+ "failed to get ssi-all reset\n");
+
for_each_rsnd_ssiu(ssiu, priv, i) {
int ret;
@@ -586,7 +612,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv)
}
ret = rsnd_mod_init(priv, rsnd_mod_get(ssiu),
- ops, NULL, RSND_MOD_SSIU, i);
+ ops, NULL, rstc, RSND_MOD_SSIU, i);
if (ret)
return ret;
}
@@ -603,3 +629,23 @@ void rsnd_ssiu_remove(struct rsnd_priv *priv)
rsnd_mod_quit(rsnd_mod_get(ssiu));
}
}
+
+void rsnd_ssiu_suspend(struct rsnd_priv *priv)
+{
+ struct rsnd_ssiu *ssiu;
+ int i;
+
+ for_each_rsnd_ssiu(ssiu, priv, i)
+ rsnd_suspend_clk_reset(rsnd_mod_get(ssiu)->clk,
+ rsnd_mod_get(ssiu)->rstc);
+}
+
+void rsnd_ssiu_resume(struct rsnd_priv *priv)
+{
+ struct rsnd_ssiu *ssiu;
+ int i;
+
+ for_each_rsnd_ssiu(ssiu, priv, i)
+ rsnd_resume_clk_reset(rsnd_mod_get(ssiu)->clk,
+ rsnd_mod_get(ssiu)->rstc);
+}
diff --git a/sound/soc/renesas/rz-ssi.c b/sound/soc/renesas/rz-ssi.c
index 71e434cfe07b..9fe8a639c47c 100644
--- a/sound/soc/renesas/rz-ssi.c
+++ b/sound/soc/renesas/rz-ssi.c
@@ -13,6 +13,8 @@
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
+#include <sound/dmaengine_pcm.h>
+#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -87,8 +89,6 @@ struct rz_ssi_stream {
struct rz_ssi_priv *priv;
struct snd_pcm_substream *substream;
int fifo_sample_size; /* sample capacity of SSI FIFO */
- int dma_buffer_pos; /* The address for the next DMA descriptor */
- int completed_dma_buf_pos; /* The address of the last completed DMA descriptor. */
int period_counter; /* for keeping track of periods transferred */
int buffer_pos; /* current frame position in the buffer */
int running; /* 0=stopped, 1=running */
@@ -96,8 +96,6 @@ struct rz_ssi_stream {
int uerr_num;
int oerr_num;
- struct dma_chan *dma_ch;
-
int (*transfer)(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm);
};
@@ -108,7 +106,6 @@ struct rz_ssi_priv {
struct clk *sfr_clk;
struct clk *clk;
- phys_addr_t phys;
int irq_int;
int irq_tx;
int irq_rx;
@@ -148,9 +145,10 @@ struct rz_ssi_priv {
unsigned int sample_width;
unsigned int sample_bits;
} hw_params_cache;
-};
-static void rz_ssi_dma_complete(void *data);
+ struct snd_dmaengine_dai_dma_data dma_dais[SNDRV_PCM_STREAM_LAST + 1];
+ struct dma_chan *dmas[SNDRV_PCM_STREAM_LAST + 1];
+};
static void rz_ssi_reg_writel(struct rz_ssi_priv *priv, uint reg, u32 data)
{
@@ -172,11 +170,6 @@ static void rz_ssi_reg_mask_setl(struct rz_ssi_priv *priv, uint reg,
writel(val, (priv->base + reg));
}
-static inline bool rz_ssi_stream_is_play(struct snd_pcm_substream *substream)
-{
- return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
-}
-
static inline struct rz_ssi_stream *
rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
{
@@ -185,7 +178,7 @@ rz_ssi_stream_get(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream)
static inline bool rz_ssi_is_dma_enabled(struct rz_ssi_priv *ssi)
{
- return (ssi->playback.dma_ch && (ssi->dma_rt || ssi->capture.dma_ch));
+ return !ssi->playback.transfer && !ssi->capture.transfer;
}
static void rz_ssi_set_substream(struct rz_ssi_stream *strm,
@@ -215,8 +208,6 @@ static void rz_ssi_stream_init(struct rz_ssi_stream *strm,
struct snd_pcm_substream *substream)
{
rz_ssi_set_substream(strm, substream);
- strm->dma_buffer_pos = 0;
- strm->completed_dma_buf_pos = 0;
strm->period_counter = 0;
strm->buffer_pos = 0;
@@ -242,12 +233,13 @@ static void rz_ssi_stream_quit(struct rz_ssi_priv *ssi,
dev_info(dev, "underrun = %d\n", strm->uerr_num);
}
-static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
- unsigned int channels)
+static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, struct snd_pcm_substream *substream,
+ unsigned int rate, unsigned int channels)
{
static u8 ckdv[] = { 1, 2, 4, 8, 16, 32, 64, 128, 6, 12, 24, 48, 96 };
unsigned int channel_bits = 32; /* System Word Length */
unsigned long bclk_rate = rate * channels * channel_bits;
+ struct snd_dmaengine_dai_dma_data *dma_dai;
unsigned int div;
unsigned int i;
u32 ssicr = 0;
@@ -290,6 +282,8 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
return -EINVAL;
}
+ dma_dai = &ssi->dma_dais[substream->stream];
+
/*
* DWL: Data Word Length = {16, 24, 32} bits
* SWL: System Word Length = 32 bits
@@ -298,12 +292,15 @@ static int rz_ssi_clk_setup(struct rz_ssi_priv *ssi, unsigned int rate,
switch (ssi->hw_params_cache.sample_width) {
case 16:
ssicr |= SSICR_DWL(1);
+ dma_dai->addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
break;
case 24:
ssicr |= SSICR_DWL(5) | SSICR_PDTA;
+ dma_dai->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
case 32:
ssicr |= SSICR_DWL(6);
+ dma_dai->addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
break;
default:
dev_err(ssi->dev, "Not support %u data width",
@@ -344,7 +341,7 @@ static void rz_ssi_set_idle(struct rz_ssi_priv *ssi)
static int rz_ssi_start(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
{
- bool is_play = rz_ssi_stream_is_play(strm->substream);
+ bool is_play = strm->substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
bool is_full_duplex;
u32 ssicr, ssifcr;
@@ -423,14 +420,6 @@ static int rz_ssi_stop(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
/* Disable TX/RX */
rz_ssi_reg_mask_setl(ssi, SSICR, SSICR_TEN | SSICR_REN, 0);
- /* Cancel all remaining DMA transactions */
- if (rz_ssi_is_dma_enabled(ssi)) {
- if (ssi->playback.dma_ch)
- dmaengine_terminate_async(ssi->playback.dma_ch);
- if (ssi->capture.dma_ch)
- dmaengine_terminate_async(ssi->capture.dma_ch);
- }
-
rz_ssi_set_idle(ssi);
return 0;
@@ -458,10 +447,6 @@ static void rz_ssi_pointer_update(struct rz_ssi_stream *strm, int frames)
snd_pcm_period_elapsed(strm->substream);
strm->period_counter = current_period;
}
-
- strm->completed_dma_buf_pos += runtime->period_size;
- if (strm->completed_dma_buf_pos >= runtime->buffer_size)
- strm->completed_dma_buf_pos = 0;
}
static int rz_ssi_pio_recv(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
@@ -606,12 +591,6 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data)
if (irq == ssi->irq_int) { /* error or idle */
bool is_stopped = !!(ssisr & (SSISR_RUIRQ | SSISR_ROIRQ |
SSISR_TUIRQ | SSISR_TOIRQ));
- int i, count;
-
- if (rz_ssi_is_dma_enabled(ssi))
- count = 4;
- else
- count = 1;
if (ssi->capture.substream && is_stopped) {
if (ssisr & SSISR_RUIRQ)
@@ -631,19 +610,41 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data)
rz_ssi_stop(ssi, strm_playback);
}
+ if (!rz_ssi_is_stream_running(&ssi->playback) &&
+ !rz_ssi_is_stream_running(&ssi->capture) &&
+ rz_ssi_is_dma_enabled(ssi) && is_stopped) {
+ if (ssi->playback.substream &&
+ ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK])
+ dmaengine_pause(ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK]);
+ if (ssi->capture.substream &&
+ ssi->dmas[SNDRV_PCM_STREAM_CAPTURE] &&
+ /* Avoid calling pause twice in case of half duplex. */
+ ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK] !=
+ ssi->dmas[SNDRV_PCM_STREAM_CAPTURE])
+ dmaengine_pause(ssi->dmas[SNDRV_PCM_STREAM_CAPTURE]);
+ }
+
/* Clear all flags */
rz_ssi_reg_mask_setl(ssi, SSISR, SSISR_TOIRQ | SSISR_TUIRQ |
SSISR_ROIRQ | SSISR_RUIRQ, 0);
/* Add/remove more data */
if (ssi->capture.substream && is_stopped) {
- for (i = 0; i < count; i++)
+ if (rz_ssi_is_dma_enabled(ssi)) {
+ if (ssi->dmas[SNDRV_PCM_STREAM_CAPTURE])
+ dmaengine_resume(ssi->dmas[SNDRV_PCM_STREAM_CAPTURE]);
+ } else {
strm_capture->transfer(ssi, strm_capture);
+ }
}
if (ssi->playback.substream && is_stopped) {
- for (i = 0; i < count; i++)
+ if (rz_ssi_is_dma_enabled(ssi)) {
+ if (ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK])
+ dmaengine_resume(ssi->dmas[SNDRV_PCM_STREAM_PLAYBACK]);
+ } else {
strm_playback->transfer(ssi, strm_playback);
+ }
}
/* Resume */
@@ -679,153 +680,11 @@ static irqreturn_t rz_ssi_interrupt(int irq, void *data)
return IRQ_HANDLED;
}
-static int rz_ssi_dma_slave_config(struct rz_ssi_priv *ssi,
- struct dma_chan *dma_ch, bool is_play)
-{
- struct dma_slave_config cfg;
-
- memset(&cfg, 0, sizeof(cfg));
-
- cfg.direction = is_play ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
- cfg.dst_addr = ssi->phys + SSIFTDR;
- cfg.src_addr = ssi->phys + SSIFRDR;
- if (ssi->hw_params_cache.sample_width == 16) {
- cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_2_BYTES;
- } else {
- cfg.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- cfg.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
- }
-
- return dmaengine_slave_config(dma_ch, &cfg);
-}
-
-static int rz_ssi_dma_transfer(struct rz_ssi_priv *ssi,
- struct rz_ssi_stream *strm)
-{
- struct snd_pcm_substream *substream = strm->substream;
- struct dma_async_tx_descriptor *desc;
- struct snd_pcm_runtime *runtime;
- enum dma_transfer_direction dir;
- u32 dma_paddr, dma_size;
- int amount;
-
- if (!rz_ssi_stream_is_valid(ssi, strm))
- return -EINVAL;
-
- runtime = substream->runtime;
- if (runtime->state == SNDRV_PCM_STATE_DRAINING)
- /*
- * Stream is ending, so do not queue up any more DMA
- * transfers otherwise we play partial sound clips
- * because we can't shut off the DMA quick enough.
- */
- return 0;
-
- dir = rz_ssi_stream_is_play(substream) ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM;
-
- /* Always transfer 1 period */
- amount = runtime->period_size;
-
- /* DMA physical address and size */
- dma_paddr = runtime->dma_addr + frames_to_bytes(runtime,
- strm->dma_buffer_pos);
- dma_size = frames_to_bytes(runtime, amount);
- desc = dmaengine_prep_slave_single(strm->dma_ch, dma_paddr, dma_size,
- dir,
- DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
- if (!desc) {
- dev_err(ssi->dev, "dmaengine_prep_slave_single() fail\n");
- return -ENOMEM;
- }
-
- desc->callback = rz_ssi_dma_complete;
- desc->callback_param = strm;
-
- if (dmaengine_submit(desc) < 0) {
- dev_err(ssi->dev, "dmaengine_submit() fail\n");
- return -EIO;
- }
-
- /* Update DMA pointer */
- strm->dma_buffer_pos += amount;
- if (strm->dma_buffer_pos >= runtime->buffer_size)
- strm->dma_buffer_pos = 0;
-
- /* Start DMA */
- dma_async_issue_pending(strm->dma_ch);
-
- return 0;
-}
-
-static void rz_ssi_dma_complete(void *data)
-{
- struct rz_ssi_stream *strm = (struct rz_ssi_stream *)data;
-
- if (!strm->running || !strm->substream || !strm->substream->runtime)
- return;
-
- /* Note that next DMA transaction has probably already started */
- rz_ssi_pointer_update(strm, strm->substream->runtime->period_size);
-
- /* Queue up another DMA transaction */
- rz_ssi_dma_transfer(strm->priv, strm);
-}
-
-static void rz_ssi_release_dma_channels(struct rz_ssi_priv *ssi)
-{
- if (ssi->playback.dma_ch) {
- dma_release_channel(ssi->playback.dma_ch);
- ssi->playback.dma_ch = NULL;
- if (ssi->dma_rt)
- ssi->dma_rt = false;
- }
-
- if (ssi->capture.dma_ch) {
- dma_release_channel(ssi->capture.dma_ch);
- ssi->capture.dma_ch = NULL;
- }
-}
-
-static int rz_ssi_dma_request(struct rz_ssi_priv *ssi, struct device *dev)
-{
- ssi->playback.dma_ch = dma_request_chan(dev, "tx");
- if (IS_ERR(ssi->playback.dma_ch))
- ssi->playback.dma_ch = NULL;
-
- ssi->capture.dma_ch = dma_request_chan(dev, "rx");
- if (IS_ERR(ssi->capture.dma_ch))
- ssi->capture.dma_ch = NULL;
-
- if (!ssi->playback.dma_ch && !ssi->capture.dma_ch) {
- ssi->playback.dma_ch = dma_request_chan(dev, "rt");
- if (IS_ERR(ssi->playback.dma_ch)) {
- ssi->playback.dma_ch = NULL;
- goto no_dma;
- }
-
- ssi->dma_rt = true;
- }
-
- if (!rz_ssi_is_dma_enabled(ssi))
- goto no_dma;
-
- return 0;
-
-no_dma:
- rz_ssi_release_dma_channels(ssi);
-
- return -ENODEV;
-}
-
static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi, struct rz_ssi_stream *strm)
{
struct snd_pcm_substream *substream = strm->substream;
- struct snd_pcm_runtime *runtime = substream->runtime;
int ret;
- strm->dma_buffer_pos = strm->completed_dma_buf_pos + runtime->period_size;
-
if (rz_ssi_is_stream_running(&ssi->playback) ||
rz_ssi_is_stream_running(&ssi->capture))
return 0;
@@ -834,7 +693,7 @@ static int rz_ssi_trigger_resume(struct rz_ssi_priv *ssi, struct rz_ssi_stream *
if (ret)
return ret;
- return rz_ssi_clk_setup(ssi, ssi->hw_params_cache.rate,
+ return rz_ssi_clk_setup(ssi, substream, ssi->hw_params_cache.rate,
ssi->hw_params_cache.channels);
}
@@ -843,10 +702,11 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
struct rz_ssi_stream *strm = rz_ssi_stream_get(ssi, substream);
- int ret = 0, i, num_transfer = 1;
+ int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
ret = rz_ssi_trigger_resume(ssi, strm);
if (ret)
return ret;
@@ -857,28 +717,7 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
if (cmd == SNDRV_PCM_TRIGGER_START)
rz_ssi_stream_init(strm, substream);
- if (rz_ssi_is_dma_enabled(ssi)) {
- bool is_playback = rz_ssi_stream_is_play(substream);
-
- if (ssi->dma_rt)
- ret = rz_ssi_dma_slave_config(ssi, ssi->playback.dma_ch,
- is_playback);
- else
- ret = rz_ssi_dma_slave_config(ssi, strm->dma_ch,
- is_playback);
-
- /* Fallback to pio */
- if (ret < 0) {
- ssi->playback.transfer = rz_ssi_pio_send;
- ssi->capture.transfer = rz_ssi_pio_recv;
- rz_ssi_release_dma_channels(ssi);
- } else {
- /* For DMA, queue up multiple DMA descriptors */
- num_transfer = 4;
- }
- }
-
- for (i = 0; i < num_transfer; i++) {
+ if (!rz_ssi_is_dma_enabled(ssi)) {
ret = strm->transfer(ssi, strm);
if (ret)
return ret;
@@ -888,6 +727,7 @@ static int rz_ssi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
rz_ssi_stop(ssi, strm);
break;
@@ -973,6 +813,8 @@ static void rz_ssi_shutdown(struct snd_pcm_substream *substream,
ssi->dup.tx_active = false;
else
ssi->dup.rx_active = false;
+
+ ssi->dmas[substream->stream] = NULL;
}
static bool rz_ssi_is_valid_hw_params(struct rz_ssi_priv *ssi, unsigned int rate,
@@ -1024,6 +866,12 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
+ /* Save the DMA channels for recovery. */
+ if (rz_ssi_is_dma_enabled(ssi))
+ ssi->dmas[substream->stream] = snd_dmaengine_pcm_get_chan(substream);
+ else
+ ssi->dmas[substream->stream] = NULL;
+
if (rz_ssi_is_stream_running(&ssi->playback) ||
rz_ssi_is_stream_running(&ssi->capture)) {
if (rz_ssi_is_valid_hw_params(ssi, rate, channels, sample_width, sample_bits))
@@ -1039,10 +887,21 @@ static int rz_ssi_dai_hw_params(struct snd_pcm_substream *substream,
if (ret)
return ret;
- return rz_ssi_clk_setup(ssi, rate, channels);
+ return rz_ssi_clk_setup(ssi, substream, rate, channels);
+}
+
+static int rz_ssi_dai_probe(struct snd_soc_dai *dai)
+{
+ struct rz_ssi_priv *ssi = snd_soc_dai_get_drvdata(dai);
+
+ snd_soc_dai_init_dma_data(dai, &ssi->dma_dais[SNDRV_PCM_STREAM_PLAYBACK],
+ &ssi->dma_dais[SNDRV_PCM_STREAM_CAPTURE]);
+
+ return 0;
}
static const struct snd_soc_dai_ops rz_ssi_dai_ops = {
+ .probe = rz_ssi_dai_probe,
.startup = rz_ssi_startup,
.shutdown = rz_ssi_shutdown,
.trigger = rz_ssi_dai_trigger,
@@ -1054,10 +913,11 @@ static const struct snd_pcm_hardware rz_ssi_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_RESUME,
- .buffer_bytes_max = PREALLOC_BUFFER,
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_PAUSE,
+ .buffer_bytes_max = 192 * 1024,
.period_bytes_min = 32,
- .period_bytes_max = 8192,
+ .period_bytes_max = 48 * 1024,
.channels_min = SSI_CHAN_MIN,
.channels_max = SSI_CHAN_MAX,
.periods_min = 1,
@@ -1065,8 +925,8 @@ static const struct snd_pcm_hardware rz_ssi_pcm_hardware = {
.fifo_size = 32 * 2,
};
-static int rz_ssi_pcm_open(struct snd_soc_component *component,
- struct snd_pcm_substream *substream)
+static int rz_ssi_pcm_open_pio(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
{
snd_soc_set_runtime_hwparams(substream, &rz_ssi_pcm_hardware);
@@ -1074,6 +934,13 @@ static int rz_ssi_pcm_open(struct snd_soc_component *component,
SNDRV_PCM_HW_PARAM_PERIODS);
}
+static int rz_ssi_pcm_open_dma(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream)
+{
+ return snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+}
+
static snd_pcm_uframes_t rz_ssi_pcm_pointer(struct snd_soc_component *component,
struct snd_pcm_substream *substream)
{
@@ -1090,7 +957,8 @@ static int rz_ssi_pcm_new(struct snd_soc_component *component,
{
snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV,
rtd->card->snd_card->dev,
- PREALLOC_BUFFER, PREALLOC_BUFFER_MAX);
+ rz_ssi_pcm_hardware.buffer_bytes_max,
+ rz_ssi_pcm_hardware.buffer_bytes_max);
return 0;
}
@@ -1113,16 +981,30 @@ static struct snd_soc_dai_driver rz_ssi_soc_dai[] = {
},
};
-static const struct snd_soc_component_driver rz_ssi_soc_component = {
+static const struct snd_soc_component_driver rz_ssi_soc_component_pio = {
.name = "rz-ssi",
- .open = rz_ssi_pcm_open,
+ .open = rz_ssi_pcm_open_pio,
.pointer = rz_ssi_pcm_pointer,
.pcm_new = rz_ssi_pcm_new,
.legacy_dai_naming = 1,
};
+static const struct snd_soc_component_driver rz_ssi_soc_component_dma = {
+ .name = "rz-ssi",
+ .open = rz_ssi_pcm_open_dma,
+ .legacy_dai_naming = 1,
+};
+
+static const struct snd_dmaengine_pcm_config rz_ssi_dmaengine_pcm_conf = {
+ .pcm_hardware = &rz_ssi_pcm_hardware,
+ .prealloc_buffer_size = 192 * 1024,
+ .prepare_slave_config = snd_dmaengine_pcm_prepare_slave_config,
+};
+
static int rz_ssi_probe(struct platform_device *pdev)
{
+ const struct snd_soc_component_driver *component_driver;
+ struct device_node *np = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct rz_ssi_priv *ssi;
struct clk *audio_clk;
@@ -1138,7 +1020,6 @@ static int rz_ssi_probe(struct platform_device *pdev)
if (IS_ERR(ssi->base))
return PTR_ERR(ssi->base);
- ssi->phys = res->start;
ssi->clk = devm_clk_get(dev, "ssi");
if (IS_ERR(ssi->clk))
return PTR_ERR(ssi->clk);
@@ -1162,16 +1043,43 @@ static int rz_ssi_probe(struct platform_device *pdev)
ssi->audio_mck = ssi->audio_clk_1 ? ssi->audio_clk_1 : ssi->audio_clk_2;
- /* Detect DMA support */
- ret = rz_ssi_dma_request(ssi, dev);
- if (ret < 0) {
+ ssi->dma_dais[SNDRV_PCM_STREAM_PLAYBACK].addr = (dma_addr_t)res->start + SSIFTDR;
+ ssi->dma_dais[SNDRV_PCM_STREAM_CAPTURE].addr = (dma_addr_t)res->start + SSIFRDR;
+
+ if (of_property_present(np, "dma-names")) {
+ struct snd_dmaengine_pcm_config *config;
+ unsigned int flags = 0;
+
+ config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL);
+ if (!config)
+ return -ENOMEM;
+
+ config->pcm_hardware = rz_ssi_dmaengine_pcm_conf.pcm_hardware;
+ config->prealloc_buffer_size = rz_ssi_dmaengine_pcm_conf.prealloc_buffer_size;
+ config->prepare_slave_config = rz_ssi_dmaengine_pcm_conf.prepare_slave_config;
+
+ if (of_property_match_string(np, "dma-names", "rt") == 0) {
+ flags = SND_DMAENGINE_PCM_FLAG_HALF_DUPLEX;
+ config->chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "rt";
+ } else {
+ config->chan_names[SNDRV_PCM_STREAM_PLAYBACK] = "tx";
+ config->chan_names[SNDRV_PCM_STREAM_CAPTURE] = "rx";
+ }
+ ret = devm_snd_dmaengine_pcm_register(&pdev->dev, config, flags);
+ } else {
+ ret = -ENODEV;
+ }
+
+ if (ret == -EPROBE_DEFER) {
+ return ret;
+ } else if (ret) {
dev_warn(dev, "DMA not available, using PIO\n");
ssi->playback.transfer = rz_ssi_pio_send;
ssi->capture.transfer = rz_ssi_pio_recv;
+ component_driver = &rz_ssi_soc_component_pio;
} else {
- dev_info(dev, "DMA enabled");
- ssi->playback.transfer = rz_ssi_dma_transfer;
- ssi->capture.transfer = rz_ssi_dma_transfer;
+ dev_info(dev, "DMA enabled\n");
+ component_driver = &rz_ssi_soc_component_dma;
}
ssi->playback.priv = ssi;
@@ -1182,17 +1090,13 @@ static int rz_ssi_probe(struct platform_device *pdev)
/* Error Interrupt */
ssi->irq_int = platform_get_irq_byname(pdev, "int_req");
- if (ssi->irq_int < 0) {
- ret = ssi->irq_int;
- goto err_release_dma_chs;
- }
+ if (ssi->irq_int < 0)
+ return ssi->irq_int;
ret = devm_request_irq(dev, ssi->irq_int, rz_ssi_interrupt,
0, dev_name(dev), ssi);
- if (ret < 0) {
- dev_err_probe(dev, ret, "irq request error (int_req)\n");
- goto err_release_dma_chs;
- }
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "irq request error (int_req)\n");
if (!rz_ssi_is_dma_enabled(ssi)) {
/* Tx and Rx interrupts (pio only) */
@@ -1233,43 +1137,19 @@ static int rz_ssi_probe(struct platform_device *pdev)
}
ssi->rstc = devm_reset_control_get_exclusive(dev, NULL);
- if (IS_ERR(ssi->rstc)) {
- ret = PTR_ERR(ssi->rstc);
- goto err_release_dma_chs;
- }
+ if (IS_ERR(ssi->rstc))
+ return dev_err_probe(dev, PTR_ERR(ssi->rstc), "Failed to get reset\n");
/* Default 0 for power saving. Can be overridden via sysfs. */
pm_runtime_set_autosuspend_delay(dev, 0);
pm_runtime_use_autosuspend(dev);
ret = devm_pm_runtime_enable(dev);
- if (ret < 0) {
- dev_err(dev, "Failed to enable runtime PM!\n");
- goto err_release_dma_chs;
- }
-
- ret = devm_snd_soc_register_component(dev, &rz_ssi_soc_component,
- rz_ssi_soc_dai,
- ARRAY_SIZE(rz_ssi_soc_dai));
- if (ret < 0) {
- dev_err(dev, "failed to register snd component\n");
- goto err_release_dma_chs;
- }
-
- return 0;
-
-err_release_dma_chs:
- rz_ssi_release_dma_channels(ssi);
-
- return ret;
-}
-
-static void rz_ssi_remove(struct platform_device *pdev)
-{
- struct rz_ssi_priv *ssi = dev_get_drvdata(&pdev->dev);
-
- rz_ssi_release_dma_channels(ssi);
+ if (ret < 0)
+ return dev_err_probe(dev, ret, "Failed to enable runtime PM!\n");
- reset_control_assert(ssi->rstc);
+ return devm_snd_soc_register_component(dev, component_driver,
+ rz_ssi_soc_dai,
+ ARRAY_SIZE(rz_ssi_soc_dai));
}
static const struct of_device_id rz_ssi_of_match[] = {
@@ -1304,7 +1184,6 @@ static struct platform_driver rz_ssi_driver = {
.pm = pm_ptr(&rz_ssi_pm_ops),
},
.probe = rz_ssi_probe,
- .remove = rz_ssi_remove,
};
module_platform_driver(rz_ssi_driver);
diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c
index c8137e8883c4..b80acb221d24 100644
--- a/sound/soc/rockchip/rk3399_gru_sound.c
+++ b/sound/soc/rockchip/rk3399_gru_sound.c
@@ -606,6 +606,7 @@ static const struct of_device_id rockchip_sound_of_match[] = {
{ .compatible = "rockchip,rk3399-gru-sound", },
{},
};
+MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);
static struct platform_driver rockchip_sound_driver = {
.probe = rockchip_sound_probe,
@@ -624,4 +625,3 @@ MODULE_AUTHOR("Xing Zheng <zhengxing@rock-chips.com>");
MODULE_DESCRIPTION("Rockchip ASoC Machine Driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, rockchip_sound_of_match);
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 0a0a95b4f520..64c90316fa02 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -127,52 +127,52 @@ static int rockchip_snd_txctrl(struct rk_i2s_dev *i2s, int on)
unsigned int val = 0;
int ret = 0;
- spin_lock(&i2s->lock);
- if (on) {
- ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
- I2S_DMACR_TDE_ENABLE,
- I2S_DMACR_TDE_ENABLE);
- if (ret < 0)
- goto end;
- ret = regmap_update_bits(i2s->regmap, I2S_XFER,
- I2S_XFER_TXS_START | I2S_XFER_RXS_START,
- I2S_XFER_TXS_START | I2S_XFER_RXS_START);
- if (ret < 0)
- goto end;
- i2s->tx_start = true;
- } else {
- i2s->tx_start = false;
-
- ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
- I2S_DMACR_TDE_ENABLE,
- I2S_DMACR_TDE_DISABLE);
- if (ret < 0)
- goto end;
-
- if (!i2s->rx_start) {
+ scoped_guard(spinlock, &i2s->lock) {
+ if (on) {
+ ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
+ I2S_DMACR_TDE_ENABLE,
+ I2S_DMACR_TDE_ENABLE);
+ if (ret < 0)
+ break;
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
- I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
+ I2S_XFER_TXS_START | I2S_XFER_RXS_START);
if (ret < 0)
- goto end;
- udelay(150);
- ret = regmap_update_bits(i2s->regmap, I2S_CLR,
- I2S_CLR_TXC | I2S_CLR_RXC,
- I2S_CLR_TXC | I2S_CLR_RXC);
- if (ret < 0)
- goto end;
- ret = regmap_read_poll_timeout_atomic(i2s->regmap,
- I2S_CLR,
- val,
- val == 0,
- 20,
- 200);
+ break;
+ i2s->tx_start = true;
+ } else {
+ i2s->tx_start = false;
+
+ ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
+ I2S_DMACR_TDE_ENABLE,
+ I2S_DMACR_TDE_DISABLE);
if (ret < 0)
- dev_warn(i2s->dev, "fail to clear: %d\n", ret);
+ break;
+
+ if (!i2s->rx_start) {
+ ret = regmap_update_bits(i2s->regmap, I2S_XFER,
+ I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+ I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
+ if (ret < 0)
+ break;
+ udelay(150);
+ ret = regmap_update_bits(i2s->regmap, I2S_CLR,
+ I2S_CLR_TXC | I2S_CLR_RXC,
+ I2S_CLR_TXC | I2S_CLR_RXC);
+ if (ret < 0)
+ break;
+ ret = regmap_read_poll_timeout_atomic(i2s->regmap,
+ I2S_CLR,
+ val,
+ val == 0,
+ 20,
+ 200);
+ if (ret < 0)
+ dev_warn(i2s->dev, "fail to clear: %d\n", ret);
+ }
}
}
-end:
- spin_unlock(&i2s->lock);
+
if (ret < 0)
dev_err(i2s->dev, "lrclk update failed\n");
@@ -184,53 +184,53 @@ static int rockchip_snd_rxctrl(struct rk_i2s_dev *i2s, int on)
unsigned int val = 0;
int ret = 0;
- spin_lock(&i2s->lock);
- if (on) {
- ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
- I2S_DMACR_RDE_ENABLE,
- I2S_DMACR_RDE_ENABLE);
- if (ret < 0)
- goto end;
-
- ret = regmap_update_bits(i2s->regmap, I2S_XFER,
- I2S_XFER_TXS_START | I2S_XFER_RXS_START,
- I2S_XFER_TXS_START | I2S_XFER_RXS_START);
- if (ret < 0)
- goto end;
- i2s->rx_start = true;
- } else {
- i2s->rx_start = false;
-
- ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
- I2S_DMACR_RDE_ENABLE,
- I2S_DMACR_RDE_DISABLE);
- if (ret < 0)
- goto end;
+ scoped_guard(spinlock, &i2s->lock) {
+ if (on) {
+ ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
+ I2S_DMACR_RDE_ENABLE,
+ I2S_DMACR_RDE_ENABLE);
+ if (ret < 0)
+ break;
- if (!i2s->tx_start) {
ret = regmap_update_bits(i2s->regmap, I2S_XFER,
I2S_XFER_TXS_START | I2S_XFER_RXS_START,
- I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
+ I2S_XFER_TXS_START | I2S_XFER_RXS_START);
if (ret < 0)
- goto end;
- udelay(150);
- ret = regmap_update_bits(i2s->regmap, I2S_CLR,
- I2S_CLR_TXC | I2S_CLR_RXC,
- I2S_CLR_TXC | I2S_CLR_RXC);
- if (ret < 0)
- goto end;
- ret = regmap_read_poll_timeout_atomic(i2s->regmap,
- I2S_CLR,
- val,
- val == 0,
- 20,
- 200);
+ break;
+ i2s->rx_start = true;
+ } else {
+ i2s->rx_start = false;
+
+ ret = regmap_update_bits(i2s->regmap, I2S_DMACR,
+ I2S_DMACR_RDE_ENABLE,
+ I2S_DMACR_RDE_DISABLE);
if (ret < 0)
- dev_warn(i2s->dev, "fail to clear: %d\n", ret);
+ break;
+
+ if (!i2s->tx_start) {
+ ret = regmap_update_bits(i2s->regmap, I2S_XFER,
+ I2S_XFER_TXS_START | I2S_XFER_RXS_START,
+ I2S_XFER_TXS_STOP | I2S_XFER_RXS_STOP);
+ if (ret < 0)
+ break;
+ udelay(150);
+ ret = regmap_update_bits(i2s->regmap, I2S_CLR,
+ I2S_CLR_TXC | I2S_CLR_RXC,
+ I2S_CLR_TXC | I2S_CLR_RXC);
+ if (ret < 0)
+ break;
+ ret = regmap_read_poll_timeout_atomic(i2s->regmap,
+ I2S_CLR,
+ val,
+ val == 0,
+ 20,
+ 200);
+ if (ret < 0)
+ dev_warn(i2s->dev, "fail to clear: %d\n", ret);
+ }
}
}
-end:
- spin_unlock(&i2s->lock);
+
if (ret < 0)
dev_err(i2s->dev, "lrclk update failed\n");
@@ -662,6 +662,15 @@ static const struct of_device_id rockchip_i2s_match[] __maybe_unused = {
{ .compatible = "rockchip,rv1126-i2s", },
{},
};
+MODULE_DEVICE_TABLE(of, rockchip_i2s_match);
+
+static void rockchip_i2s_suspend(void *data)
+{
+ struct device *dev = data;
+
+ if (!pm_runtime_status_suspended(dev))
+ i2s_runtime_suspend(dev);
+}
static int rockchip_i2s_init_dai(struct rk_i2s_dev *i2s, struct resource *res,
struct snd_soc_dai_driver **dp)
@@ -757,37 +766,28 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
}
/* try to prepare related clocks */
- i2s->hclk = devm_clk_get(&pdev->dev, "i2s_hclk");
+ i2s->hclk = devm_clk_get_enabled(&pdev->dev, "i2s_hclk");
if (IS_ERR(i2s->hclk)) {
dev_err(&pdev->dev, "Can't retrieve i2s bus clock\n");
return PTR_ERR(i2s->hclk);
}
- ret = clk_prepare_enable(i2s->hclk);
- if (ret) {
- dev_err(i2s->dev, "hclock enable failed %d\n", ret);
- return ret;
- }
i2s->mclk = devm_clk_get(&pdev->dev, "i2s_clk");
if (IS_ERR(i2s->mclk)) {
dev_err(&pdev->dev, "Can't retrieve i2s master clock\n");
- ret = PTR_ERR(i2s->mclk);
- goto err_clk;
+ return PTR_ERR(i2s->mclk);
}
regs = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
- if (IS_ERR(regs)) {
- ret = PTR_ERR(regs);
- goto err_clk;
- }
+ if (IS_ERR(regs))
+ return PTR_ERR(regs);
i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs,
&rockchip_i2s_regmap_config);
if (IS_ERR(i2s->regmap)) {
dev_err(&pdev->dev,
"Failed to initialise managed register map\n");
- ret = PTR_ERR(i2s->regmap);
- goto err_clk;
+ return PTR_ERR(i2s->regmap);
}
i2s->bclk_ratio = 64;
@@ -798,8 +798,7 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
i2s->bclk_off = pinctrl_lookup_state(i2s->pinctrl, "bclk_off");
if (IS_ERR_OR_NULL(i2s->bclk_off)) {
dev_err(&pdev->dev, "failed to find i2s bclk_off\n");
- ret = -EINVAL;
- goto err_clk;
+ return -EINVAL;
}
}
} else {
@@ -810,16 +809,23 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
dev_set_drvdata(&pdev->dev, i2s);
- pm_runtime_enable(&pdev->dev);
+ ret = devm_add_action(&pdev->dev, rockchip_i2s_suspend, &pdev->dev);
+ if (ret)
+ return ret;
+
+ ret = devm_pm_runtime_enable(&pdev->dev);
+ if (ret)
+ return ret;
+
if (!pm_runtime_enabled(&pdev->dev)) {
ret = i2s_runtime_resume(&pdev->dev);
if (ret)
- goto err_pm_disable;
+ return ret;
}
ret = rockchip_i2s_init_dai(i2s, res, &dai);
if (ret)
- goto err_pm_disable;
+ return ret;
ret = devm_snd_soc_register_component(&pdev->dev,
&rockchip_i2s_component,
@@ -827,36 +833,16 @@ static int rockchip_i2s_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "Could not register DAI\n");
- goto err_suspend;
+ return ret;
}
ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0);
if (ret) {
dev_err(&pdev->dev, "Could not register PCM\n");
- goto err_suspend;
+ return ret;
}
return 0;
-
-err_suspend:
- if (!pm_runtime_status_suspended(&pdev->dev))
- i2s_runtime_suspend(&pdev->dev);
-err_pm_disable:
- pm_runtime_disable(&pdev->dev);
-err_clk:
- clk_disable_unprepare(i2s->hclk);
- return ret;
-}
-
-static void rockchip_i2s_remove(struct platform_device *pdev)
-{
- struct rk_i2s_dev *i2s = dev_get_drvdata(&pdev->dev);
-
- pm_runtime_disable(&pdev->dev);
- if (!pm_runtime_status_suspended(&pdev->dev))
- i2s_runtime_suspend(&pdev->dev);
-
- clk_disable_unprepare(i2s->hclk);
}
static const struct dev_pm_ops rockchip_i2s_pm_ops = {
@@ -865,7 +851,6 @@ static const struct dev_pm_ops rockchip_i2s_pm_ops = {
static struct platform_driver rockchip_i2s_driver = {
.probe = rockchip_i2s_probe,
- .remove = rockchip_i2s_remove,
.driver = {
.name = DRV_NAME,
.of_match_table = of_match_ptr(rockchip_i2s_match),
@@ -878,4 +863,3 @@ MODULE_DESCRIPTION("ROCKCHIP IIS ASoC Interface");
MODULE_AUTHOR("jianqun <jay.xu@rock-chips.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, rockchip_i2s_match);
diff --git a/sound/soc/rockchip/rockchip_i2s_tdm.c b/sound/soc/rockchip/rockchip_i2s_tdm.c
index fc52149ed6ae..e6229a325ffe 100644
--- a/sound/soc/rockchip/rockchip_i2s_tdm.c
+++ b/sound/soc/rockchip/rockchip_i2s_tdm.c
@@ -285,9 +285,8 @@ static void rockchip_snd_txrxctrl(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai, int on)
{
struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);
- unsigned long flags;
- spin_lock_irqsave(&i2s_tdm->lock, flags);
+ guard(spinlock_irqsave)(&i2s_tdm->lock);
if (on) {
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
rockchip_enable_tde(i2s_tdm->regmap);
@@ -313,7 +312,6 @@ static void rockchip_snd_txrxctrl(struct snd_pcm_substream *substream,
I2S_CLR_TXC | I2S_CLR_RXC);
}
}
- spin_unlock_irqrestore(&i2s_tdm->lock, flags);
}
static void rockchip_snd_txctrl(struct rk_i2s_tdm_dev *i2s_tdm, int on)
@@ -587,12 +585,11 @@ static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream,
unsigned int fmt)
{
struct rk_i2s_tdm_dev *i2s_tdm = to_info(dai);
- unsigned long flags;
if (!i2s_tdm->clk_trcm)
return 0;
- spin_lock_irqsave(&i2s_tdm->lock, flags);
+ guard(spinlock_irqsave)(&i2s_tdm->lock);
if (i2s_tdm->refcount)
rockchip_i2s_tdm_xfer_pause(substream, i2s_tdm);
@@ -614,7 +611,6 @@ static int rockchip_i2s_trcm_mode(struct snd_pcm_substream *substream,
if (i2s_tdm->refcount)
rockchip_i2s_tdm_xfer_resume(substream, i2s_tdm);
- spin_unlock_irqrestore(&i2s_tdm->lock, flags);
return 0;
}
@@ -1040,6 +1036,7 @@ static const struct of_device_id rockchip_i2s_tdm_match[] = {
{ .compatible = "rockchip,rv1126-i2s-tdm", .data = &rv1126_i2s_soc_data },
{},
};
+MODULE_DEVICE_TABLE(of, rockchip_i2s_tdm_match);
static const struct snd_soc_dai_driver i2s_tdm_dai = {
.ops = &rockchip_i2s_tdm_dai_ops,
@@ -1442,4 +1439,3 @@ MODULE_DESCRIPTION("ROCKCHIP I2S/TDM ASoC Interface");
MODULE_AUTHOR("Sugar Zhang <sugar.zhang@rock-chips.com>");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, rockchip_i2s_tdm_match);
diff --git a/sound/soc/rockchip/rockchip_pdm.c b/sound/soc/rockchip/rockchip_pdm.c
index c69cdd6f2499..115e90d3bbfe 100644
--- a/sound/soc/rockchip/rockchip_pdm.c
+++ b/sound/soc/rockchip/rockchip_pdm.c
@@ -321,6 +321,7 @@ static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai,
{
struct rk_pdm_dev *pdm = to_info(cpu_dai);
unsigned int mask = 0, val = 0;
+ int ret;
mask = PDM_CKP_MSK;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -334,7 +335,10 @@ static int rockchip_pdm_set_fmt(struct snd_soc_dai *cpu_dai,
return -EINVAL;
}
- pm_runtime_get_sync(cpu_dai->dev);
+ ret = pm_runtime_resume_and_get(cpu_dai->dev);
+ if (ret)
+ return ret;
+
regmap_update_bits(pdm->regmap, PDM_CLK_CTRL, mask, val);
pm_runtime_put(cpu_dai->dev);
@@ -422,16 +426,16 @@ static int rockchip_pdm_runtime_resume(struct device *dev)
struct rk_pdm_dev *pdm = dev_get_drvdata(dev);
int ret;
- ret = clk_prepare_enable(pdm->clk);
+ ret = clk_prepare_enable(pdm->hclk);
if (ret) {
- dev_err(pdm->dev, "clock enable failed %d\n", ret);
+ dev_err(pdm->dev, "hclock enable failed %d\n", ret);
return ret;
}
- ret = clk_prepare_enable(pdm->hclk);
+ ret = clk_prepare_enable(pdm->clk);
if (ret) {
- clk_disable_unprepare(pdm->clk);
- dev_err(pdm->dev, "hclock enable failed %d\n", ret);
+ clk_disable_unprepare(pdm->hclk);
+ dev_err(pdm->dev, "clock enable failed %d\n", ret);
return ret;
}
diff --git a/sound/soc/rockchip/rockchip_sai.c b/sound/soc/rockchip/rockchip_sai.c
index ed393e5034a4..585e89f61f0d 100644
--- a/sound/soc/rockchip/rockchip_sai.c
+++ b/sound/soc/rockchip/rockchip_sai.c
@@ -11,6 +11,7 @@
#include <linux/delay.h>
#include <linux/of_device.h>
#include <linux/clk.h>
+#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
#include <linux/reset.h>
diff --git a/sound/soc/rockchip/rockchip_spdif.c b/sound/soc/rockchip/rockchip_spdif.c
index 581624f2682e..7f15bc7f8f35 100644
--- a/sound/soc/rockchip/rockchip_spdif.c
+++ b/sound/soc/rockchip/rockchip_spdif.c
@@ -76,16 +76,16 @@ static int rk_spdif_runtime_resume(struct device *dev)
struct rk_spdif_dev *spdif = dev_get_drvdata(dev);
int ret;
- ret = clk_prepare_enable(spdif->mclk);
+ ret = clk_prepare_enable(spdif->hclk);
if (ret) {
- dev_err(spdif->dev, "mclk clock enable failed %d\n", ret);
+ dev_err(spdif->dev, "hclk clock enable failed %d\n", ret);
return ret;
}
- ret = clk_prepare_enable(spdif->hclk);
+ ret = clk_prepare_enable(spdif->mclk);
if (ret) {
- clk_disable_unprepare(spdif->mclk);
- dev_err(spdif->dev, "hclk clock enable failed %d\n", ret);
+ clk_disable_unprepare(spdif->hclk);
+ dev_err(spdif->dev, "mclk clock enable failed %d\n", ret);
return ret;
}
@@ -94,6 +94,7 @@ static int rk_spdif_runtime_resume(struct device *dev)
ret = regcache_sync(spdif->regmap);
if (ret) {
+ regcache_cache_only(spdif->regmap, true);
clk_disable_unprepare(spdif->mclk);
clk_disable_unprepare(spdif->hclk);
}
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index 140907a41a70..f80f697a5d55 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -510,14 +510,13 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs,
unsigned int cdcon_mask = 1 << i2s_regs->cdclkcon_off;
unsigned int rsrc_mask = 1 << i2s_regs->rclksrc_off;
u32 mod, mask, val = 0;
- unsigned long flags;
int ret = 0;
pm_runtime_get_sync(dai->dev);
- spin_lock_irqsave(&priv->lock, flags);
- mod = readl(priv->addr + I2SMOD);
- spin_unlock_irqrestore(&priv->lock, flags);
+ scoped_guard(spinlock_irqsave, &priv->lock)
+ mod = readl(priv->addr + I2SMOD);
+
switch (clk_id) {
case SAMSUNG_I2S_OPCLK:
@@ -612,11 +611,11 @@ static int i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int rfs,
goto err;
}
- spin_lock_irqsave(&priv->lock, flags);
- mod = readl(priv->addr + I2SMOD);
- mod = (mod & ~mask) | val;
- writel(mod, priv->addr + I2SMOD);
- spin_unlock_irqrestore(&priv->lock, flags);
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ mod = readl(priv->addr + I2SMOD);
+ mod = (mod & ~mask) | val;
+ writel(mod, priv->addr + I2SMOD);
+ }
done:
pm_runtime_put(dai->dev);
@@ -729,7 +728,6 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
struct i2s_dai *i2s = to_info(dai);
u32 mod, mask = 0, val = 0;
struct clk *rclksrc;
- unsigned long flags;
WARN_ON(!pm_runtime_active(dai->dev));
@@ -801,11 +799,11 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- spin_lock_irqsave(&priv->lock, flags);
- mod = readl(priv->addr + I2SMOD);
- mod = (mod & ~mask) | val;
- writel(mod, priv->addr + I2SMOD);
- spin_unlock_irqrestore(&priv->lock, flags);
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ mod = readl(priv->addr + I2SMOD);
+ mod = (mod & ~mask) | val;
+ writel(mod, priv->addr + I2SMOD);
+ }
snd_soc_dai_init_dma_data(dai, &i2s->dma_playback, &i2s->dma_capture);
@@ -825,11 +823,10 @@ static int i2s_startup(struct snd_pcm_substream *substream,
struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
struct i2s_dai *i2s = to_info(dai);
struct i2s_dai *other = get_other_dai(i2s);
- unsigned long flags;
pm_runtime_get_sync(dai->dev);
- spin_lock_irqsave(&priv->pcm_lock, flags);
+ guard(spinlock_irqsave)(&priv->pcm_lock);
i2s->mode |= DAI_OPENED;
@@ -841,8 +838,6 @@ static int i2s_startup(struct snd_pcm_substream *substream,
if (!any_active(i2s) && (priv->quirks & QUIRK_NEED_RSTCLR))
writel(CON_RSTCLR, i2s->priv->addr + I2SCON);
- spin_unlock_irqrestore(&priv->pcm_lock, flags);
-
return 0;
}
@@ -852,21 +847,18 @@ static void i2s_shutdown(struct snd_pcm_substream *substream,
struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
struct i2s_dai *i2s = to_info(dai);
struct i2s_dai *other = get_other_dai(i2s);
- unsigned long flags;
-
- spin_lock_irqsave(&priv->pcm_lock, flags);
- i2s->mode &= ~DAI_OPENED;
- i2s->mode &= ~DAI_MANAGER;
+ scoped_guard(spinlock_irqsave, &priv->pcm_lock) {
+ i2s->mode &= ~DAI_OPENED;
+ i2s->mode &= ~DAI_MANAGER;
- if (is_opened(other))
- other->mode |= DAI_MANAGER;
+ if (is_opened(other))
+ other->mode |= DAI_MANAGER;
- /* Reset any constraint on RFS and BFS */
- i2s->rfs = 0;
- i2s->bfs = 0;
-
- spin_unlock_irqrestore(&priv->pcm_lock, flags);
+ /* Reset any constraint on RFS and BFS */
+ i2s->rfs = 0;
+ i2s->bfs = 0;
+ }
pm_runtime_put(dai->dev);
}
@@ -939,7 +931,6 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct i2s_dai *i2s = to_info(snd_soc_rtd_to_cpu(rtd, 0));
- unsigned long flags;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -950,37 +941,31 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
if (priv->fixup_early)
priv->fixup_early(substream, dai);
- spin_lock_irqsave(&priv->lock, flags);
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ if (config_setup(i2s))
+ return -EINVAL;
- if (config_setup(i2s)) {
- spin_unlock_irqrestore(&priv->lock, flags);
- return -EINVAL;
- }
+ if (priv->fixup_late)
+ priv->fixup_late(substream, dai);
- if (priv->fixup_late)
- priv->fixup_late(substream, dai);
-
- if (capture)
- i2s_rxctrl(i2s, 1);
- else
- i2s_txctrl(i2s, 1);
-
- spin_unlock_irqrestore(&priv->lock, flags);
+ if (capture)
+ i2s_rxctrl(i2s, 1);
+ else
+ i2s_txctrl(i2s, 1);
+ }
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- spin_lock_irqsave(&priv->lock, flags);
-
- if (capture) {
- i2s_rxctrl(i2s, 0);
- i2s_fifo(i2s, FIC_RXFLUSH);
- } else {
- i2s_txctrl(i2s, 0);
- i2s_fifo(i2s, FIC_TXFLUSH);
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ if (capture) {
+ i2s_rxctrl(i2s, 0);
+ i2s_fifo(i2s, FIC_RXFLUSH);
+ } else {
+ i2s_txctrl(i2s, 0);
+ i2s_fifo(i2s, FIC_TXFLUSH);
+ }
}
-
- spin_unlock_irqrestore(&priv->lock, flags);
pm_runtime_put(dai->dev);
break;
}
@@ -1056,7 +1041,6 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
struct i2s_dai *i2s = to_info(dai);
struct i2s_dai *other = get_other_dai(i2s);
- unsigned long flags;
pm_runtime_get_sync(dai->dev);
@@ -1079,13 +1063,13 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
i2s->rfs = 0;
i2s->bfs = 0;
- spin_lock_irqsave(&priv->lock, flags);
- i2s_txctrl(i2s, 0);
- i2s_rxctrl(i2s, 0);
- i2s_fifo(i2s, FIC_TXFLUSH);
- i2s_fifo(other, FIC_TXFLUSH);
- i2s_fifo(i2s, FIC_RXFLUSH);
- spin_unlock_irqrestore(&priv->lock, flags);
+ scoped_guard(spinlock_irqsave, &priv->lock) {
+ i2s_txctrl(i2s, 0);
+ i2s_rxctrl(i2s, 0);
+ i2s_fifo(i2s, FIC_TXFLUSH);
+ i2s_fifo(other, FIC_TXFLUSH);
+ i2s_fifo(i2s, FIC_RXFLUSH);
+ }
/* Gate CDCLK by default */
if (!is_opened(other))
@@ -1100,15 +1084,13 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
{
struct samsung_i2s_priv *priv = snd_soc_dai_get_drvdata(dai);
struct i2s_dai *i2s = to_info(dai);
- unsigned long flags;
pm_runtime_get_sync(dai->dev);
if (!is_secondary(i2s)) {
if (priv->quirks & QUIRK_NEED_RSTCLR) {
- spin_lock_irqsave(&priv->lock, flags);
- writel(0, priv->addr + I2SCON);
- spin_unlock_irqrestore(&priv->lock, flags);
+ scoped_guard(spinlock_irqsave, &priv->lock)
+ writel(0, priv->addr + I2SCON);
}
}
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index cb455ddce253..d362136e1069 100644
--- a/sound/soc/samsung/idma.c
+++ b/sound/soc/samsung/idma.c
@@ -67,9 +67,8 @@ static int idma_enqueue(struct snd_pcm_substream *substream)
struct idma_ctrl *prtd = substream->runtime->private_data;
u32 val;
- spin_lock(&prtd->lock);
- prtd->token = (void *) substream;
- spin_unlock(&prtd->lock);
+ scoped_guard(spinlock, &prtd->lock)
+ prtd->token = (void *) substream;
/* Internal DMA Level0 Interrupt Address */
val = idma.lp_tx_addr + prtd->periodsz;
@@ -101,16 +100,15 @@ static void idma_setcallbk(struct snd_pcm_substream *substream,
{
struct idma_ctrl *prtd = substream->runtime->private_data;
- spin_lock(&prtd->lock);
+ guard(spinlock)(&prtd->lock);
prtd->cb = cb;
- spin_unlock(&prtd->lock);
}
static void idma_control(int op)
{
u32 val = readl(idma.regs + I2SAHB);
- spin_lock(&idma.lock);
+ guard(spinlock)(&idma.lock);
switch (op) {
case LPAM_DMA_START:
@@ -120,12 +118,10 @@ static void idma_control(int op)
val &= ~(AHB_INTENLVL0 | AHB_DMAEN);
break;
default:
- spin_unlock(&idma.lock);
return;
}
writel(val, idma.regs + I2SAHB);
- spin_unlock(&idma.lock);
}
static void idma_done(void *id, int bytes_xfer)
@@ -192,7 +188,7 @@ static int idma_trigger(struct snd_soc_component *component,
struct idma_ctrl *prtd = substream->runtime->private_data;
int ret = 0;
- spin_lock(&prtd->lock);
+ guard(spinlock)(&prtd->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_RESUME:
@@ -214,8 +210,6 @@ static int idma_trigger(struct snd_soc_component *component,
break;
}
- spin_unlock(&prtd->lock);
-
return ret;
}
@@ -228,12 +222,10 @@ idma_pointer(struct snd_soc_component *component,
dma_addr_t src;
unsigned long res;
- spin_lock(&prtd->lock);
-
- idma_getpos(&src);
- res = src - prtd->start;
-
- spin_unlock(&prtd->lock);
+ scoped_guard(spinlock, &prtd->lock) {
+ idma_getpos(&src);
+ res = src - prtd->start;
+ }
return bytes_to_frames(substream->runtime, res);
}
diff --git a/sound/soc/samsung/odroid.c b/sound/soc/samsung/odroid.c
index ab3398f39f4a..5c5ecbea5331 100644
--- a/sound/soc/samsung/odroid.c
+++ b/sound/soc/samsung/odroid.c
@@ -36,15 +36,12 @@ static int odroid_card_fe_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
- unsigned long flags;
- int ret = 0;
- spin_lock_irqsave(&priv->lock, flags);
+ guard(spinlock_irqsave)(&priv->lock);
if (priv->be_active && priv->be_sample_rate != params_rate(params))
- ret = -EINVAL;
- spin_unlock_irqrestore(&priv->lock, flags);
+ return -EINVAL;
- return ret;
+ return 0;
}
static const struct snd_soc_ops odroid_card_fe_ops = {
@@ -58,7 +55,6 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
unsigned int pll_freq, rclk_freq, rfs;
- unsigned long flags;
int ret;
switch (params_rate(params)) {
@@ -105,10 +101,8 @@ static int odroid_card_be_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- spin_lock_irqsave(&priv->lock, flags);
- priv->be_sample_rate = params_rate(params);
- spin_unlock_irqrestore(&priv->lock, flags);
-
+ scoped_guard(spinlock_irqsave, &priv->lock)
+ priv->be_sample_rate = params_rate(params);
return 0;
}
@@ -116,9 +110,8 @@ static int odroid_card_be_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct odroid_priv *priv = snd_soc_card_get_drvdata(rtd->card);
- unsigned long flags;
- spin_lock_irqsave(&priv->lock, flags);
+ guard(spinlock_irqsave)(&priv->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -134,8 +127,6 @@ static int odroid_card_be_trigger(struct snd_pcm_substream *substream, int cmd)
break;
}
- spin_unlock_irqrestore(&priv->lock, flags);
-
return 0;
}
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index a03ba9374c2e..309f024bf2a4 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -218,7 +218,6 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(snd_soc_rtd_to_cpu(rtd, 0));
- unsigned long flags;
dev_dbg(pcm->dev, "Entered %s\n", __func__);
@@ -226,27 +225,23 @@ static int s3c_pcm_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- spin_lock_irqsave(&pcm->lock, flags);
-
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- s3c_pcm_snd_rxctrl(pcm, 1);
- else
- s3c_pcm_snd_txctrl(pcm, 1);
-
- spin_unlock_irqrestore(&pcm->lock, flags);
+ scoped_guard(spinlock_irqsave, &pcm->lock) {
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ s3c_pcm_snd_rxctrl(pcm, 1);
+ else
+ s3c_pcm_snd_txctrl(pcm, 1);
+ }
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- spin_lock_irqsave(&pcm->lock, flags);
-
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- s3c_pcm_snd_rxctrl(pcm, 0);
- else
- s3c_pcm_snd_txctrl(pcm, 0);
-
- spin_unlock_irqrestore(&pcm->lock, flags);
+ scoped_guard(spinlock_irqsave, &pcm->lock) {
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ s3c_pcm_snd_rxctrl(pcm, 0);
+ else
+ s3c_pcm_snd_txctrl(pcm, 0);
+ }
break;
default:
@@ -265,7 +260,6 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
void __iomem *regs = pcm->regs;
struct clk *clk;
int sclk_div, sync_div;
- unsigned long flags;
u32 clkctl;
dev_dbg(pcm->dev, "Entered %s\n", __func__);
@@ -278,36 +272,33 @@ static int s3c_pcm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- spin_lock_irqsave(&pcm->lock, flags);
-
- /* Get hold of the PCMSOURCE_CLK */
- clkctl = readl(regs + S3C_PCM_CLKCTL);
- if (clkctl & S3C_PCM_CLKCTL_SERCLKSEL_PCLK)
- clk = pcm->pclk;
- else
- clk = pcm->cclk;
-
- /* Set the SCLK divider */
- sclk_div = clk_get_rate(clk) / pcm->sclk_per_fs /
- params_rate(params) / 2 - 1;
-
- clkctl &= ~(S3C_PCM_CLKCTL_SCLKDIV_MASK
- << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
- clkctl |= ((sclk_div & S3C_PCM_CLKCTL_SCLKDIV_MASK)
- << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
+ scoped_guard(spinlock_irqsave, &pcm->lock) {
+ /* Get hold of the PCMSOURCE_CLK */
+ clkctl = readl(regs + S3C_PCM_CLKCTL);
+ if (clkctl & S3C_PCM_CLKCTL_SERCLKSEL_PCLK)
+ clk = pcm->pclk;
+ else
+ clk = pcm->cclk;
- /* Set the SYNC divider */
- sync_div = pcm->sclk_per_fs - 1;
+ /* Set the SCLK divider */
+ sclk_div = clk_get_rate(clk) / pcm->sclk_per_fs /
+ params_rate(params) / 2 - 1;
- clkctl &= ~(S3C_PCM_CLKCTL_SYNCDIV_MASK
- << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
- clkctl |= ((sync_div & S3C_PCM_CLKCTL_SYNCDIV_MASK)
- << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
+ clkctl &= ~(S3C_PCM_CLKCTL_SCLKDIV_MASK
+ << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
+ clkctl |= ((sclk_div & S3C_PCM_CLKCTL_SCLKDIV_MASK)
+ << S3C_PCM_CLKCTL_SCLKDIV_SHIFT);
- writel(clkctl, regs + S3C_PCM_CLKCTL);
+ /* Set the SYNC divider */
+ sync_div = pcm->sclk_per_fs - 1;
- spin_unlock_irqrestore(&pcm->lock, flags);
+ clkctl &= ~(S3C_PCM_CLKCTL_SYNCDIV_MASK
+ << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
+ clkctl |= ((sync_div & S3C_PCM_CLKCTL_SYNCDIV_MASK)
+ << S3C_PCM_CLKCTL_SYNCDIV_SHIFT);
+ writel(clkctl, regs + S3C_PCM_CLKCTL);
+ }
dev_dbg(pcm->dev, "PCMSOURCE_CLK-%lu SCLK=%ufs SCLK_DIV=%d SYNC_DIV=%d\n",
clk_get_rate(clk), pcm->sclk_per_fs,
sclk_div, sync_div);
@@ -320,13 +311,11 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
{
struct s3c_pcm_info *pcm = snd_soc_dai_get_drvdata(cpu_dai);
void __iomem *regs = pcm->regs;
- unsigned long flags;
- int ret = 0;
u32 ctl;
dev_dbg(pcm->dev, "Entered %s\n", __func__);
- spin_lock_irqsave(&pcm->lock, flags);
+ guard(spinlock_irqsave)(&pcm->lock);
ctl = readl(regs + S3C_PCM_CTL);
@@ -336,8 +325,7 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
break;
default:
dev_err(pcm->dev, "Unsupported clock inversion!\n");
- ret = -EINVAL;
- goto exit;
+ return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) {
@@ -346,8 +334,7 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
break;
default:
dev_err(pcm->dev, "Unsupported master/slave format!\n");
- ret = -EINVAL;
- goto exit;
+ return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_CLOCK_MASK) {
@@ -359,8 +346,7 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
break;
default:
dev_err(pcm->dev, "Invalid Clock gating request!\n");
- ret = -EINVAL;
- goto exit;
+ return -EINVAL;
}
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -374,16 +360,11 @@ static int s3c_pcm_set_fmt(struct snd_soc_dai *cpu_dai,
break;
default:
dev_err(pcm->dev, "Unsupported data format!\n");
- ret = -EINVAL;
- goto exit;
+ return -EINVAL;
}
writel(ctl, regs + S3C_PCM_CTL);
-
-exit:
- spin_unlock_irqrestore(&pcm->lock, flags);
-
- return ret;
+ return 0;
}
static int s3c_pcm_set_clkdiv(struct snd_soc_dai *cpu_dai,
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index fb30f6b637a0..7fc46d55c522 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -143,7 +143,6 @@ static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
{
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct samsung_spdif_info *spdif = to_info(snd_soc_rtd_to_cpu(rtd, 0));
- unsigned long flags;
dev_dbg(spdif->dev, "Entered %s\n", __func__);
@@ -151,16 +150,14 @@ static int spdif_trigger(struct snd_pcm_substream *substream, int cmd,
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- spin_lock_irqsave(&spdif->lock, flags);
- spdif_snd_txctrl(spdif, 1);
- spin_unlock_irqrestore(&spdif->lock, flags);
+ scoped_guard(spinlock_irqsave, &spdif->lock)
+ spdif_snd_txctrl(spdif, 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- spin_lock_irqsave(&spdif->lock, flags);
- spdif_snd_txctrl(spdif, 0);
- spin_unlock_irqrestore(&spdif->lock, flags);
+ scoped_guard(spinlock_irqsave, &spdif->lock)
+ spdif_snd_txctrl(spdif, 0);
break;
default:
return -EINVAL;
@@ -182,7 +179,6 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
void __iomem *regs = spdif->regs;
struct snd_dmaengine_dai_dma_data *dma_data;
u32 con, clkcon, cstas;
- unsigned long flags;
int i, ratio;
dev_dbg(spdif->dev, "Entered %s\n", __func__);
@@ -196,7 +192,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
snd_soc_dai_set_dma_data(snd_soc_rtd_to_cpu(rtd, 0), substream, dma_data);
- spin_lock_irqsave(&spdif->lock, flags);
+ guard(spinlock_irqsave)(&spdif->lock);
con = readl(regs + CON) & CON_MASK;
cstas = readl(regs + CSTAS) & CSTAS_MASK;
@@ -214,7 +210,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
break;
default:
dev_err(spdif->dev, "Unsupported data size.\n");
- goto err;
+ return -EINVAL;
}
ratio = spdif->clk_rate / params_rate(params);
@@ -224,7 +220,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
if (i == ARRAY_SIZE(spdif_sysclk_ratios)) {
dev_err(spdif->dev, "Invalid clock ratio %ld/%d\n",
spdif->clk_rate, params_rate(params));
- goto err;
+ return -EINVAL;
}
con &= ~CON_MCLKDIV_MASK;
@@ -257,7 +253,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
default:
dev_err(spdif->dev, "Invalid sampling rate %d\n",
params_rate(params));
- goto err;
+ return -EINVAL;
}
cstas &= ~CSTAS_CATEGORY_MASK;
@@ -268,12 +264,7 @@ static int spdif_hw_params(struct snd_pcm_substream *substream,
writel(cstas, regs + CSTAS);
writel(clkcon, regs + CLKCON);
- spin_unlock_irqrestore(&spdif->lock, flags);
-
return 0;
-err:
- spin_unlock_irqrestore(&spdif->lock, flags);
- return -EINVAL;
}
static void spdif_shutdown(struct snd_pcm_substream *substream,
diff --git a/sound/soc/sdca/Kconfig b/sound/soc/sdca/Kconfig
index 87ab2895096c..4c0dcb9ff3b9 100644
--- a/sound/soc/sdca/Kconfig
+++ b/sound/soc/sdca/Kconfig
@@ -2,7 +2,7 @@
menu "SoundWire (SDCA)"
config SND_SOC_SDCA
- tristate
+ tristate "SDCA core support"
depends on ACPI
select AUXILIARY_BUS
help
diff --git a/sound/soc/sdca/sdca_asoc.c b/sound/soc/sdca/sdca_asoc.c
index 2bfc8e5aee31..b4dedba719dc 100644
--- a/sound/soc/sdca/sdca_asoc.c
+++ b/sound/soc/sdca/sdca_asoc.c
@@ -160,6 +160,9 @@ static int ge_put_enum_double(struct snd_kcontrol *kcontrol,
unsigned int reg = e->reg;
int ret;
+ if (item[0] >= e->items)
+ return -EINVAL;
+
reg &= ~SDW_SDCA_CTL_CSEL(0x3F);
reg |= SDW_SDCA_CTL_CSEL(SDCA_CTL_GE_DETECTED_MODE);
@@ -359,15 +362,77 @@ static int entity_parse_ot(struct device *dev,
return 0;
}
+/**
+ * sdca_asoc_pde_poll_actual_ps - Verify PDE power state reached target state
+ * @dev: Pointer to the device for error logging.
+ * @regmap: Register map for reading ACTUAL_PS register.
+ * @function_id: SDCA function identifier.
+ * @entity_id: SDCA entity identifier for the power domain.
+ * @from_ps: Source power state (SDCA_PDE_PSn value).
+ * @to_ps: Target power state (SDCA_PDE_PSn value).
+ * @pde_delays: Pointer to array of PDE delay specifications for this device,
+ * or NULL to use default polling interval.
+ * @num_delays: Number of entries in pde_delays array.
+ *
+ * This function polls the ACTUAL_PS register to verify that a PDE power state
+ * transition has completed. Per SDCA specification, after writing REQUESTED_PS,
+ * the caller must poll ACTUAL_PS until it reflects the requested state.
+ *
+ * This function implements the polling logic but does NOT modify the power state.
+ * The caller is responsible for writing REQUESTED_PS before invoking this function.
+ *
+ * If a delay table is provided, appropriate polling intervals are extracted based
+ * on the from_ps and to_ps transition. If no table is provided or no matching entry
+ * is found, a default polling interval is used.
+ *
+ * Return: Returns zero when ACTUAL_PS reaches the target state, -ETIMEDOUT if the
+ * polling times out before reaching the target state, or a negative error code if
+ * a register read fails.
+ */
+int sdca_asoc_pde_poll_actual_ps(struct device *dev, struct regmap *regmap,
+ int function_id, int entity_id,
+ int from_ps, int to_ps,
+ const struct sdca_pde_delay *pde_delays,
+ int num_delays)
+{
+ static const int polls = 100;
+ static const int default_poll_us = 1000;
+ unsigned int reg, val;
+ int i, poll_us = default_poll_us;
+ int ret;
+
+ if (pde_delays && num_delays > 0) {
+ for (i = 0; i < num_delays; i++) {
+ if (pde_delays[i].from_ps == from_ps && pde_delays[i].to_ps == to_ps) {
+ poll_us = pde_delays[i].us / polls;
+ break;
+ }
+ }
+ }
+
+ reg = SDW_SDCA_CTL(function_id, entity_id, SDCA_CTL_PDE_ACTUAL_PS, 0);
+
+ for (i = 0; i < polls; i++) {
+ if (i)
+ fsleep(poll_us);
+
+ ret = regmap_read(regmap, reg, &val);
+ if (ret)
+ return ret;
+ else if (val == to_ps)
+ return 0;
+ }
+
+ return -ETIMEDOUT;
+}
+EXPORT_SYMBOL_NS(sdca_asoc_pde_poll_actual_ps, "SND_SOC_SDCA");
+
static int entity_pde_event(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kctl, int event)
{
struct snd_soc_component *component = snd_soc_dapm_to_component(widget->dapm);
struct sdca_entity *entity = widget->priv;
- static const int polls = 100;
- unsigned int reg, val;
- int from, to, i;
- int poll_us;
+ int from, to;
int ret;
if (!component)
@@ -386,33 +451,17 @@ static int entity_pde_event(struct snd_soc_dapm_widget *widget,
return 0;
}
- for (i = 0; i < entity->pde.num_max_delay; i++) {
- struct sdca_pde_delay *delay = &entity->pde.max_delay[i];
-
- if (delay->from_ps == from && delay->to_ps == to) {
- poll_us = delay->us / polls;
- break;
- }
- }
-
- reg = SDW_SDCA_CTL(SDW_SDCA_CTL_FUNC(widget->reg),
- SDW_SDCA_CTL_ENT(widget->reg),
- SDCA_CTL_PDE_ACTUAL_PS, 0);
-
- for (i = 0; i < polls; i++) {
- if (i)
- fsleep(poll_us);
-
- ret = regmap_read(component->regmap, reg, &val);
- if (ret)
- return ret;
- else if (val == to)
- return 0;
- }
+ ret = sdca_asoc_pde_poll_actual_ps(component->dev, component->regmap,
+ SDW_SDCA_CTL_FUNC(widget->reg),
+ SDW_SDCA_CTL_ENT(widget->reg),
+ from, to,
+ entity->pde.max_delay,
+ entity->pde.num_max_delay);
+ if (ret)
+ dev_err(component->dev, "%s: PDE transition %x -> %x failed, err=%d\n",
+ entity->label, from, to, ret);
- dev_err(component->dev, "%s: power transition failed: %x\n",
- entity->label, val);
- return -ETIMEDOUT;
+ return ret;
}
static int entity_parse_pde(struct device *dev,
diff --git a/sound/soc/sdca/sdca_class.c b/sound/soc/sdca/sdca_class.c
index 6e9b66f71801..8d7b007a068f 100644
--- a/sound/soc/sdca/sdca_class.c
+++ b/sound/soc/sdca/sdca_class.c
@@ -9,7 +9,6 @@
#include <linux/device.h>
#include <linux/err.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
@@ -38,35 +37,8 @@ static int class_read_prop(struct sdw_slave *sdw)
return 0;
}
-static int class_sdw_update_status(struct sdw_slave *sdw, enum sdw_slave_status status)
-{
- struct sdca_class_drv *drv = dev_get_drvdata(&sdw->dev);
-
- switch (status) {
- case SDW_SLAVE_ATTACHED:
- dev_dbg(drv->dev, "device attach\n");
-
- drv->attached = true;
-
- complete(&drv->device_attach);
- break;
- case SDW_SLAVE_UNATTACHED:
- dev_dbg(drv->dev, "device detach\n");
-
- drv->attached = false;
-
- reinit_completion(&drv->device_attach);
- break;
- default:
- break;
- }
-
- return 0;
-}
-
static const struct sdw_slave_ops class_sdw_ops = {
.read_prop = class_read_prop,
- .update_status = class_sdw_update_status,
};
static void class_regmap_lock(void *data)
@@ -83,24 +55,6 @@ static void class_regmap_unlock(void *data)
mutex_unlock(lock);
}
-static int class_wait_for_attach(struct sdca_class_drv *drv)
-{
- if (!drv->attached) {
- unsigned long timeout = msecs_to_jiffies(CLASS_SDW_ATTACH_TIMEOUT_MS);
- unsigned long time;
-
- time = wait_for_completion_timeout(&drv->device_attach, timeout);
- if (!time) {
- dev_err(drv->dev, "timed out waiting for device re-attach\n");
- return -ETIMEDOUT;
- }
- }
-
- regcache_cache_only(drv->dev_regmap, false);
-
- return 0;
-}
-
static bool class_dev_regmap_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
@@ -151,10 +105,12 @@ static void class_boot_work(struct work_struct *work)
boot_work);
int ret;
- ret = class_wait_for_attach(drv);
+ ret = sdw_slave_wait_for_init(drv->sdw, CLASS_SDW_ATTACH_TIMEOUT_MS);
if (ret)
goto err;
+ regcache_cache_only(drv->dev_regmap, false);
+
drv->irq_info = sdca_irq_allocate(drv->dev, drv->dev_regmap,
drv->sdw->irq);
if (IS_ERR(drv->irq_info))
@@ -183,7 +139,6 @@ err:
static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id)
{
struct device *dev = &sdw->dev;
- struct sdca_device_data *data = &sdw->sdca_data;
struct regmap_config *dev_config;
struct sdca_class_drv *drv;
int ret;
@@ -199,12 +154,6 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id
if (!dev_config)
return -ENOMEM;
- drv->functions = devm_kcalloc(dev, data->num_functions,
- sizeof(*drv->functions),
- GFP_KERNEL);
- if (!drv->functions)
- return -ENOMEM;
-
drv->dev = dev;
drv->sdw = sdw;
mutex_init(&drv->regmap_lock);
@@ -213,7 +162,6 @@ static int class_sdw_probe(struct sdw_slave *sdw, const struct sdw_device_id *id
dev_set_drvdata(drv->dev, drv);
INIT_WORK(&drv->boot_work, class_boot_work);
- init_completion(&drv->device_attach);
dev_config->lock_arg = &drv->regmap_lock;
@@ -297,10 +245,11 @@ static int class_runtime_resume(struct device *dev)
struct sdca_class_drv *drv = dev_get_drvdata(dev);
int ret;
- ret = class_wait_for_attach(drv);
+ ret = sdw_slave_wait_for_init(drv->sdw, CLASS_SDW_ATTACH_TIMEOUT_MS);
if (ret)
goto err;
+ regcache_cache_only(drv->dev_regmap, false);
regcache_mark_dirty(drv->dev_regmap);
ret = regcache_sync(drv->dev_regmap);
diff --git a/sound/soc/sdca/sdca_class.h b/sound/soc/sdca/sdca_class.h
index 6f24ea2bbd38..57f7f8d08f49 100644
--- a/sound/soc/sdca/sdca_class.h
+++ b/sound/soc/sdca/sdca_class.h
@@ -24,16 +24,12 @@ struct sdca_class_drv {
struct regmap *dev_regmap;
struct sdw_slave *sdw;
- struct sdca_function_data *functions;
struct sdca_interrupt_info *irq_info;
struct mutex regmap_lock;
/* Serialise function initialisations */
struct mutex init_lock;
struct work_struct boot_work;
- struct completion device_attach;
-
- bool attached;
};
#endif /* __SDCA_CLASS_H__ */
diff --git a/sound/soc/sdca/sdca_class_function.c b/sound/soc/sdca/sdca_class_function.c
index 31fc08d51307..1496a15f7d2a 100644
--- a/sound/soc/sdca/sdca_class_function.c
+++ b/sound/soc/sdca/sdca_class_function.c
@@ -27,6 +27,7 @@
#include <sound/soc-dai.h>
#include <sound/soc.h>
#include "sdca_class.h"
+#include "sdca_function_device.h"
struct class_function_drv {
struct device *dev;
@@ -294,8 +295,7 @@ static int class_function_probe(struct auxiliary_device *auxdev,
{
struct device *dev = &auxdev->dev;
struct sdca_class_drv *core = dev_get_drvdata(dev->parent);
- struct sdca_device_data *data = &core->sdw->sdca_data;
- struct sdca_function_desc *desc;
+ struct sdca_dev *sdev = auxiliary_dev_to_sdca_dev(auxdev);
struct snd_soc_component_driver *cmp_drv;
struct snd_soc_dai_driver *dais;
struct class_function_drv *drv;
@@ -305,7 +305,6 @@ static int class_function_probe(struct auxiliary_device *auxdev,
int ndefaults;
int num_dais;
int ret;
- int i;
drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL);
if (!drv)
@@ -328,21 +327,9 @@ static int class_function_probe(struct auxiliary_device *auxdev,
drv->dev = dev;
drv->core = core;
+ drv->function = &sdev->function;
- for (i = 0; i < data->num_functions; i++) {
- desc = &data->function[i];
-
- if (desc->type == aux_dev_id->driver_data)
- break;
- }
- if (i == core->sdw->sdca_data.num_functions) {
- dev_err(dev, "failed to locate function\n");
- return -EINVAL;
- }
-
- drv->function = &core->functions[i];
-
- ret = sdca_parse_function(dev, core->sdw, desc, drv->function);
+ ret = sdca_parse_function(dev, core->sdw, drv->function);
if (ret)
return ret;
@@ -377,7 +364,7 @@ static int class_function_probe(struct auxiliary_device *auxdev,
return dev_err_probe(dev, PTR_ERR(drv->regmap),
"failed to create regmap");
- switch (desc->type) {
+ switch (drv->function->desc->type) {
case SDCA_FUNCTION_TYPE_UAJ:
case SDCA_FUNCTION_TYPE_RJ:
cmp_drv->set_jack = class_function_set_jack;
diff --git a/sound/soc/sdca/sdca_function_device.c b/sound/soc/sdca/sdca_function_device.c
index feacfbc6a518..b5ca98283a88 100644
--- a/sound/soc/sdca/sdca_function_device.c
+++ b/sound/soc/sdca/sdca_function_device.c
@@ -82,6 +82,9 @@ static struct sdca_dev *sdca_dev_register(struct device *parent,
static void sdca_dev_unregister(struct sdca_dev *sdev)
{
+ if (!sdev)
+ return;
+
auxiliary_device_delete(&sdev->auxdev);
auxiliary_device_uninit(&sdev->auxdev);
}
@@ -90,14 +93,24 @@ int sdca_dev_register_functions(struct sdw_slave *slave)
{
struct sdca_device_data *sdca_data = &slave->sdca_data;
int i;
+ int ret;
for (i = 0; i < sdca_data->num_functions; i++) {
struct sdca_dev *func_dev;
func_dev = sdca_dev_register(&slave->dev,
&sdca_data->function[i]);
- if (IS_ERR(func_dev))
- return PTR_ERR(func_dev);
+ if (IS_ERR(func_dev)) {
+ ret = PTR_ERR(func_dev);
+ /*
+ * Unregister functions that were successfully
+ * registered before this failure. This also
+ * sets func_dev to NULL so the caller will not
+ * try to unregister them again.
+ */
+ sdca_dev_unregister_functions(slave);
+ return ret;
+ }
sdca_data->function[i].func_dev = func_dev;
}
@@ -111,7 +124,12 @@ void sdca_dev_unregister_functions(struct sdw_slave *slave)
struct sdca_device_data *sdca_data = &slave->sdca_data;
int i;
- for (i = 0; i < sdca_data->num_functions; i++)
+ for (i = 0; i < sdca_data->num_functions; i++) {
+ if (!sdca_data->function[i].func_dev)
+ continue;
+
sdca_dev_unregister(sdca_data->function[i].func_dev);
+ sdca_data->function[i].func_dev = NULL;
+ }
}
EXPORT_SYMBOL_NS(sdca_dev_unregister_functions, "SND_SOC_SDCA");
diff --git a/sound/soc/sdca/sdca_functions.c b/sound/soc/sdca/sdca_functions.c
index 196bade11ab5..77940bd6b33c 100644
--- a/sound/soc/sdca/sdca_functions.c
+++ b/sound/soc/sdca/sdca_functions.c
@@ -98,7 +98,7 @@ static int find_sdca_function(struct acpi_device *adev, void *data)
u32 function_type;
int function_index;
u64 addr;
- int ret;
+ int i, ret;
if (sdca_data->num_functions >= SDCA_MAX_FUNCTION_COUNT) {
dev_err(dev, "maximum number of functions exceeded\n");
@@ -159,6 +159,14 @@ static int find_sdca_function(struct acpi_device *adev, void *data)
/* store results */
function_index = sdca_data->num_functions;
+
+ for (i = 0; i < function_index; i++) {
+ if (sdca_data->function[i].type == function_type) {
+ sdca_data->function[function_index].duplicate = true;
+ break;
+ }
+ }
+
sdca_data->function[function_index].adr = addr;
sdca_data->function[function_index].type = function_type;
sdca_data->function[function_index].name = function_name;
@@ -1466,6 +1474,7 @@ static int find_sdca_entity_xu(struct device *dev,
}
static int find_sdca_entity(struct device *dev, struct sdw_slave *sdw,
+ struct sdca_function_data *function,
struct fwnode_handle *function_node,
struct fwnode_handle *entity_node,
struct sdca_entity *entity)
@@ -1481,6 +1490,13 @@ static int find_sdca_entity(struct device *dev, struct sdw_slave *sdw,
return ret;
}
+ if (function->desc->duplicate) {
+ entity->label = devm_kasprintf(dev, GFP_KERNEL, "%d %s",
+ function->desc->adr, entity->label);
+ if (!entity->label)
+ return -ENOMEM;
+ }
+
ret = fwnode_property_read_u32(entity_node, "mipi-sdca-entity-type", &tmp);
if (ret) {
dev_err(dev, "%s: type missing: %d\n", entity->label, ret);
@@ -1578,7 +1594,7 @@ static int find_sdca_entities(struct device *dev, struct sdw_slave *sdw,
return -EINVAL;
}
- ret = find_sdca_entity(dev, sdw, function_node,
+ ret = find_sdca_entity(dev, sdw, function, function_node,
entity_node, &entities[i]);
fwnode_handle_put(entity_node);
if (ret)
@@ -1605,8 +1621,14 @@ static struct sdca_entity *find_sdca_entity_by_label(struct sdca_function_data *
const char *entity_label)
{
struct sdca_entity *entity = NULL;
+ char tmp[64];
int i;
+ if (function->desc->duplicate) {
+ snprintf(tmp, sizeof(tmp), "%d %s", function->desc->adr, entity_label);
+ entity_label = tmp;
+ }
+
for (i = 0; i < function->num_entities; i++) {
entity = &function->entities[i];
@@ -2158,27 +2180,22 @@ static int find_sdca_filesets(struct device *dev, struct sdw_slave *sdw,
* sdca_parse_function - parse ACPI DisCo for a Function
* @dev: Pointer to device against which function data will be allocated.
* @sdw: SoundWire slave device to be processed.
- * @function_desc: Pointer to the Function short descriptor.
* @function: Pointer to the Function information, to be populated.
*
* Return: Returns 0 for success.
*/
int sdca_parse_function(struct device *dev, struct sdw_slave *sdw,
- struct sdca_function_desc *function_desc,
struct sdca_function_data *function)
{
+ struct fwnode_handle *node = function->desc->node;
u32 tmp;
int ret;
- function->desc = function_desc;
-
- ret = fwnode_property_read_u32(function_desc->node,
- "mipi-sdca-function-busy-max-delay", &tmp);
+ ret = fwnode_property_read_u32(node, "mipi-sdca-function-busy-max-delay", &tmp);
if (!ret)
function->busy_max_delay = tmp;
- ret = fwnode_property_read_u32(function_desc->node,
- "mipi-sdca-function-reset-max-delay", &tmp);
+ ret = fwnode_property_read_u32(node, "mipi-sdca-function-reset-max-delay", &tmp);
if (ret || tmp == 0) {
dev_dbg(dev, "reset delay missing, defaulting to 100mS\n");
function->reset_max_delay = 100000;
@@ -2187,26 +2204,26 @@ int sdca_parse_function(struct device *dev, struct sdw_slave *sdw,
}
dev_dbg(dev, "%pfwP: name %s busy delay %dus reset delay %dus\n",
- function->desc->node, function->desc->name,
- function->busy_max_delay, function->reset_max_delay);
+ node, function->desc->name, function->busy_max_delay,
+ function->reset_max_delay);
- ret = find_sdca_init_table(dev, function_desc->node, function);
+ ret = find_sdca_init_table(dev, node, function);
if (ret)
return ret;
- ret = find_sdca_entities(dev, sdw, function_desc->node, function);
+ ret = find_sdca_entities(dev, sdw, node, function);
if (ret)
return ret;
- ret = find_sdca_connections(dev, function_desc->node, function);
+ ret = find_sdca_connections(dev, node, function);
if (ret)
return ret;
- ret = find_sdca_clusters(dev, function_desc->node, function);
+ ret = find_sdca_clusters(dev, node, function);
if (ret < 0)
return ret;
- ret = find_sdca_filesets(dev, sdw, function_desc->node, function);
+ ret = find_sdca_filesets(dev, sdw, node, function);
if (ret)
return ret;
diff --git a/sound/soc/sdca/sdca_interrupts.c b/sound/soc/sdca/sdca_interrupts.c
index 6e10b4e660d9..4539a52a8e32 100644
--- a/sound/soc/sdca/sdca_interrupts.c
+++ b/sound/soc/sdca/sdca_interrupts.c
@@ -375,8 +375,7 @@ int sdca_irq_data_populate(struct device *dev, struct regmap *regmap,
if (!dev)
return -ENODEV;
- name = kasprintf(GFP_KERNEL, "%s %s %s", function->desc->name,
- entity->label, control->label);
+ name = kasprintf(GFP_KERNEL, "%s %s", entity->label, control->label);
if (!name)
return -ENOMEM;
diff --git a/sound/soc/sdca/sdca_jack.c b/sound/soc/sdca/sdca_jack.c
index 49d317d3b8c8..ae9636622a84 100644
--- a/sound/soc/sdca/sdca_jack.c
+++ b/sound/soc/sdca/sdca_jack.c
@@ -145,6 +145,32 @@ int sdca_jack_alloc_state(struct sdca_interrupt *interrupt)
}
EXPORT_SYMBOL_NS_GPL(sdca_jack_alloc_state, "SND_SOC_SDCA");
+static int type_get_mask(enum sdca_terminal_type type)
+{
+ switch (type) {
+ case SDCA_TERM_TYPE_LINEIN_STEREO:
+ case SDCA_TERM_TYPE_LINEIN_FRONT_LR:
+ case SDCA_TERM_TYPE_LINEIN_CENTER_LFE:
+ case SDCA_TERM_TYPE_LINEIN_SURROUND_LR:
+ case SDCA_TERM_TYPE_LINEIN_REAR_LR:
+ return SND_JACK_LINEIN;
+ case SDCA_TERM_TYPE_LINEOUT_STEREO:
+ case SDCA_TERM_TYPE_LINEOUT_FRONT_LR:
+ case SDCA_TERM_TYPE_LINEOUT_CENTER_LFE:
+ case SDCA_TERM_TYPE_LINEOUT_SURROUND_LR:
+ case SDCA_TERM_TYPE_LINEOUT_REAR_LR:
+ return SND_JACK_LINEOUT;
+ case SDCA_TERM_TYPE_MIC_JACK:
+ return SND_JACK_MICROPHONE;
+ case SDCA_TERM_TYPE_HEADPHONE_JACK:
+ return SND_JACK_HEADPHONE;
+ case SDCA_TERM_TYPE_HEADSET_JACK:
+ return SND_JACK_HEADSET;
+ default:
+ return 0;
+ }
+}
+
/**
* sdca_jack_set_jack - attach an ASoC jack to SDCA
* @info: SDCA interrupt information.
@@ -154,7 +180,8 @@ EXPORT_SYMBOL_NS_GPL(sdca_jack_alloc_state, "SND_SOC_SDCA");
*/
int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *jack)
{
- int i, ret;
+ int i, j;
+ int ret;
guard(mutex)(&info->irq_lock);
@@ -162,6 +189,7 @@ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *ja
struct sdca_interrupt *interrupt = &info->irqs[i];
struct sdca_control *control = interrupt->control;
struct sdca_entity *entity = interrupt->entity;
+ struct sdca_control_range *range;
struct jack_state *jack_state;
if (!interrupt->irq)
@@ -169,7 +197,22 @@ int sdca_jack_set_jack(struct sdca_interrupt_info *info, struct snd_soc_jack *ja
switch (SDCA_CTL_TYPE(entity->type, control->sel)) {
case SDCA_CTL_TYPE_S(GE, DETECTED_MODE):
+ range = sdca_selector_find_range(interrupt->dev, entity,
+ SDCA_CTL_GE_SELECTED_MODE,
+ SDCA_SELECTED_MODE_NCOLS, 0);
+ if (!range)
+ return -EINVAL;
+
jack_state = interrupt->priv;
+
+ for (j = 0; j < range->rows; j++) {
+ enum sdca_terminal_type type;
+
+ type = sdca_range(range, SDCA_SELECTED_MODE_TERM_TYPE, j);
+
+ jack_state->mask |= type_get_mask(type);
+ }
+
jack_state->jack = jack;
/* Report initial state in case IRQ was already handled */
@@ -191,7 +234,6 @@ int sdca_jack_report(struct sdca_interrupt *interrupt)
struct jack_state *jack_state = interrupt->priv;
struct sdca_control_range *range;
enum sdca_terminal_type type;
- unsigned int report = 0;
unsigned int reg, val;
int ret;
@@ -213,35 +255,7 @@ int sdca_jack_report(struct sdca_interrupt *interrupt)
type = sdca_range_search(range, SDCA_SELECTED_MODE_INDEX,
val, SDCA_SELECTED_MODE_TERM_TYPE);
- switch (type) {
- case SDCA_TERM_TYPE_LINEIN_STEREO:
- case SDCA_TERM_TYPE_LINEIN_FRONT_LR:
- case SDCA_TERM_TYPE_LINEIN_CENTER_LFE:
- case SDCA_TERM_TYPE_LINEIN_SURROUND_LR:
- case SDCA_TERM_TYPE_LINEIN_REAR_LR:
- report = SND_JACK_LINEIN;
- break;
- case SDCA_TERM_TYPE_LINEOUT_STEREO:
- case SDCA_TERM_TYPE_LINEOUT_FRONT_LR:
- case SDCA_TERM_TYPE_LINEOUT_CENTER_LFE:
- case SDCA_TERM_TYPE_LINEOUT_SURROUND_LR:
- case SDCA_TERM_TYPE_LINEOUT_REAR_LR:
- report = SND_JACK_LINEOUT;
- break;
- case SDCA_TERM_TYPE_MIC_JACK:
- report = SND_JACK_MICROPHONE;
- break;
- case SDCA_TERM_TYPE_HEADPHONE_JACK:
- report = SND_JACK_HEADPHONE;
- break;
- case SDCA_TERM_TYPE_HEADSET_JACK:
- report = SND_JACK_HEADSET;
- break;
- default:
- break;
- }
-
- snd_soc_jack_report(jack_state->jack, report, 0xFFFF);
+ snd_soc_jack_report(jack_state->jack, type_get_mask(type), jack_state->mask);
return 0;
}
diff --git a/sound/soc/sdw_utils/Makefile b/sound/soc/sdw_utils/Makefile
index a8d091fd374b..5ae8c69b8b98 100644
--- a/sound/soc/sdw_utils/Makefile
+++ b/sound/soc/sdw_utils/Makefile
@@ -8,6 +8,7 @@ snd-soc-sdw-utils-y := soc_sdw_utils.o soc_sdw_dmic.o soc_sdw_rt_dmic.o \
soc_sdw_cs42l45.o \
soc_sdw_cs47l47.o \
soc_sdw_cs_amp.o \
+ soc_sdw_es9356.o \
soc_sdw_maxim.o \
soc_sdw_ti_amp.o
obj-$(CONFIG_SND_SOC_SDW_UTILS) += snd-soc-sdw-utils.o
diff --git a/sound/soc/sdw_utils/soc_sdw_es9356.c b/sound/soc/sdw_utils/soc_sdw_es9356.c
new file mode 100644
index 000000000000..aa405e7dad99
--- /dev/null
+++ b/sound/soc/sdw_utils/soc_sdw_es9356.c
@@ -0,0 +1,230 @@
+// SPDX-License-Identifier: GPL-2.0-only
+// Based on sof_sdw_rt5682.c
+// This file incorporates work covered by the following copyright notice:
+// Copyright (c) 2023 Intel Corporation
+// Copyright (c) 2024 Advanced Micro Devices, Inc.
+// Copyright (c) 2025 Everest Semiconductor Co., Ltd
+
+/*
+ * soc_sdw_es9356 - Helpers to handle ES9356 from generic machine driver
+ */
+
+#include <linux/device.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/soundwire/sdw.h>
+#include <linux/soundwire/sdw_type.h>
+#include <sound/control.h>
+#include <sound/soc.h>
+#include <sound/soc-acpi.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <sound/soc_sdw_utils.h>
+
+/*
+ * Note this MUST be called before snd_soc_register_card(), so that the props
+ * are in place before the codec component driver's probe function parses them.
+ */
+static int es9356_add_codec_device_props(struct device *sdw_dev, unsigned long quirk)
+{
+ struct property_entry props[SOC_SDW_MAX_NO_PROPS] = {};
+ struct fwnode_handle *fwnode;
+ int ret;
+
+ if (!SOC_SDW_JACK_JDSRC(quirk))
+ return 0;
+ props[0] = PROPERTY_ENTRY_U32("everest,jd-src", SOC_SDW_JACK_JDSRC(quirk));
+
+ fwnode = fwnode_create_software_node(props, NULL);
+ if (IS_ERR(fwnode))
+ return PTR_ERR(fwnode);
+
+ ret = device_add_software_node(sdw_dev, to_software_node(fwnode));
+
+ fwnode_handle_put(fwnode);
+
+ return ret;
+}
+
+static const struct snd_soc_dapm_route es9356_map[] = {
+ /* Headphones */
+ { "Headphone", NULL, "es9356 HP" },
+ { "es9356 MIC1", NULL, "Headset Mic" },
+};
+
+static const struct snd_soc_dapm_route es9356_spk_map[] = {
+ /* Speaker */
+ { "Speaker", NULL, "es9356 SPK" },
+};
+
+static const struct snd_soc_dapm_route es9356_dmic_map[] = {
+ /* DMIC */
+ { "es9356 PDM_DIN", NULL, "DMIC" },
+};
+
+static struct snd_soc_jack_pin es9356_jack_pins[] = {
+ {
+ .pin = "Headphone",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
+};
+
+int asoc_sdw_es9356_spk_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
+ int ret;
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s spk:es9356-spk",
+ card->components);
+ if (!card->components)
+ return -ENOMEM;
+
+ ret = snd_soc_dapm_add_routes(dapm, es9356_spk_map,
+ ARRAY_SIZE(es9356_spk_map));
+ if (ret)
+ dev_err(card->dev, "es9356 map addition failed: %d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_es9356_spk_rtd_init, "SND_SOC_SDW_UTILS");
+
+int asoc_sdw_es9356_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
+ int ret;
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s mic:es9356-dmic",
+ card->components);
+ if (!card->components)
+ return -ENOMEM;
+
+ ret = snd_soc_dapm_add_routes(dapm, es9356_dmic_map,
+ ARRAY_SIZE(es9356_dmic_map));
+ if (ret)
+ dev_err(card->dev, "es9356 map addition failed: %d\n", ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_es9356_dmic_rtd_init, "SND_SOC_SDW_UTILS");
+
+int asoc_sdw_es9356_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct snd_soc_component *component;
+ struct snd_soc_jack *jack;
+ int ret;
+
+ component = dai->component;
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s hs:es9356",
+ card->components);
+ if (!card->components)
+ return -ENOMEM;
+
+ ret = snd_soc_dapm_add_routes(dapm, es9356_map,
+ ARRAY_SIZE(es9356_map));
+
+ if (ret) {
+ dev_err(card->dev, "es9356 map addition failed: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET | SND_JACK_BTN_0 |
+ SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+ SND_JACK_BTN_3 | SND_JACK_BTN_4,
+ &ctx->sdw_headset,
+ es9356_jack_pins,
+ ARRAY_SIZE(es9356_jack_pins));
+ if (ret) {
+ dev_err(rtd->card->dev, "Headset Jack creation failed: %d\n",
+ ret);
+ return ret;
+ }
+
+ jack = &ctx->sdw_headset;
+
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEUP);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_NEXTSONG);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_4, KEY_PREVIOUSSONG);
+
+ ret = snd_soc_component_set_jack(component, jack, NULL);
+
+ if (ret)
+ dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n",
+ ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_es9356_rtd_init, "SND_SOC_SDW_UTILS");
+
+int asoc_sdw_es9356_exit(struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
+{
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+
+ if (!ctx->headset_codec_dev)
+ return 0;
+
+ device_remove_software_node(ctx->headset_codec_dev);
+ put_device(ctx->headset_codec_dev);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_es9356_exit, "SND_SOC_SDW_UTILS");
+
+int asoc_sdw_es9356_init(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_links,
+ struct asoc_sdw_codec_info *info,
+ bool playback)
+{
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct device *sdw_dev;
+ int ret;
+
+ /*
+ * headset should be initialized once.
+ * Do it with dai link for playback.
+ */
+ if (!playback)
+ return 0;
+
+ sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, dai_links->codecs[0].name);
+ if (!sdw_dev)
+ return -EPROBE_DEFER;
+
+ ret = es9356_add_codec_device_props(sdw_dev, ctx->mc_quirk);
+ if (ret < 0) {
+ put_device(sdw_dev);
+ return ret;
+ }
+ ctx->headset_codec_dev = sdw_dev;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_es9356_init, "SND_SOC_SDW_UTILS");
+
+int asoc_sdw_es9356_amp_init(struct snd_soc_card *card,
+ struct snd_soc_dai_link *dai_links,
+ struct asoc_sdw_codec_info *info,
+ bool playback)
+{
+ if (!playback)
+ return 0;
+
+ info->amp_num++;
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_es9356_amp_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_ti_amp.c b/sound/soc/sdw_utils/soc_sdw_ti_amp.c
index 488ef2ef45d4..d0ae5d7efe8f 100644
--- a/sound/soc/sdw_utils/soc_sdw_ti_amp.c
+++ b/sound/soc/sdw_utils/soc_sdw_ti_amp.c
@@ -7,12 +7,15 @@
#include <linux/device.h>
#include <linux/errno.h>
-#include <sound/soc.h>
+#include <linux/input.h>
+#include <sound/jack.h>
#include <sound/soc-acpi.h>
#include <sound/soc-dai.h>
+#include <sound/soc.h>
#include <sound/soc_sdw_utils.h>
#define TIAMP_SPK_VOLUME_0DB 200
+#define TAC5XX2_WIDGET_NAME_MAX 32
int asoc_sdw_ti_amp_initial_settings(struct snd_soc_card *card,
const char *name_prefix)
@@ -95,3 +98,132 @@ int asoc_sdw_ti_amp_init(struct snd_soc_card *card,
return 0;
}
EXPORT_SYMBOL_NS(asoc_sdw_ti_amp_init, "SND_SOC_SDW_UTILS");
+
+static int asoc_sdw_ti_add_tac5xx2_routes(struct snd_soc_dapm_context *dapm,
+ const char *name_prefix)
+{
+ struct snd_soc_dapm_route routes[2];
+ char left_widget[TAC5XX2_WIDGET_NAME_MAX];
+ char right_widget[TAC5XX2_WIDGET_NAME_MAX];
+
+ if (strlen(name_prefix) > (TAC5XX2_WIDGET_NAME_MAX - 7))
+ return -ENAMETOOLONG;
+
+ scnprintf(left_widget, sizeof(left_widget), "%s SPK_L", name_prefix);
+ scnprintf(right_widget, sizeof(right_widget), "%s SPK_R", name_prefix);
+
+ routes[0] = (struct snd_soc_dapm_route){"Left Spk", NULL, left_widget};
+ routes[1] = (struct snd_soc_dapm_route){"Right Spk", NULL, right_widget};
+
+ return snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
+}
+
+int asoc_sdw_ti_tac5xx2_spk_rtd_init(struct snd_soc_pcm_runtime *rtd,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_dapm_context *dapm = snd_soc_card_to_dapm(card);
+ int ret, i;
+ struct snd_soc_dai *codec_dai;
+ const char *prefix;
+
+ for_each_rtd_codec_dais(rtd, i, codec_dai) {
+ if (!strstr(codec_dai->name, "tac5") &&
+ !strstr(codec_dai->name, "tas2883"))
+ continue;
+
+ prefix = codec_dai->component->name_prefix;
+ if (!prefix) {
+ dev_warn(card->dev,
+ "No name prefix found for codec DAI: %s\n",
+ codec_dai->name);
+ continue;
+ }
+ ret = asoc_sdw_ti_add_tac5xx2_routes(dapm, prefix);
+ if (ret) {
+ dev_err(card->dev, "Failed to add routes for %s: %d\n",
+ prefix, ret);
+ return ret;
+ }
+ }
+
+ dev_dbg(card->dev, "Added TAC5XX2 speaker routes\n");
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_ti_tac5xx2_spk_rtd_init, "SND_SOC_SDW_UTILS");
+
+int asoc_sdw_ti_dmic_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct snd_soc_component *component;
+
+ component = dai->component;
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s mic:%s", card->components,
+ component->name_prefix);
+ if (!card->components)
+ return -ENOMEM;
+
+ dev_dbg(card->dev, "card->components: %s\n", card->components);
+
+ return 0;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_ti_dmic_rtd_init, "SND_SOC_SDW_UTILS");
+
+static struct snd_soc_jack_pin ti_sdca_jack_pins[] = {
+ {
+ .pin = "Headphone",
+ .mask = SND_JACK_HEADPHONE,
+ },
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
+};
+
+int asoc_sdw_ti_sdca_jack_rtd_init(struct snd_soc_pcm_runtime *rtd, struct snd_soc_dai *dai)
+{
+ struct snd_soc_card *card = rtd->card;
+ struct asoc_sdw_mc_private *ctx = snd_soc_card_get_drvdata(card);
+ struct snd_soc_component *component;
+ struct snd_soc_jack *jack;
+ int ret;
+
+ component = dai->component;
+
+ card->components = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s hs:%s", card->components,
+ component->name_prefix);
+ if (!card->components)
+ return -ENOMEM;
+
+ ret = snd_soc_card_jack_new_pins(rtd->card, "Headset Jack",
+ SND_JACK_HEADSET | SND_JACK_BTN_0 |
+ SND_JACK_BTN_1 | SND_JACK_BTN_2 |
+ SND_JACK_BTN_3 | SND_JACK_BTN_4,
+ &ctx->sdw_headset,
+ ti_sdca_jack_pins,
+ ARRAY_SIZE(ti_sdca_jack_pins));
+ if (ret) {
+ dev_err(rtd->card->dev, "Jack create failed%d\n", ret);
+ return ret;
+ }
+
+ jack = &ctx->sdw_headset;
+
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOICECOMMAND);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOLUMEDOWN);
+ snd_jack_set_key(jack->jack, SND_JACK_BTN_4, KEY_NEXTSONG);
+
+ ret = snd_soc_component_set_jack(component, jack, NULL);
+ if (ret)
+ dev_err(rtd->card->dev, "Headset Jack call-back failed: %d\n",
+ ret);
+
+ return ret;
+}
+EXPORT_SYMBOL_NS(asoc_sdw_ti_sdca_jack_rtd_init, "SND_SOC_SDW_UTILS");
diff --git a/sound/soc/sdw_utils/soc_sdw_utils.c b/sound/soc/sdw_utils/soc_sdw_utils.c
index 849ae876d7a4..d8db8fc5313e 100644
--- a/sound/soc/sdw_utils/soc_sdw_utils.c
+++ b/sound/soc/sdw_utils/soc_sdw_utils.c
@@ -74,12 +74,165 @@ static const struct snd_kcontrol_new rt700_controls[] = {
struct asoc_sdw_codec_info codec_info_list[] = {
{
.vendor_id = 0x0102,
+ .part_id = 0x5572,
+ .name_prefix = "tac5572",
+ .dais = {
+ {
+ /* speaker */
+ .direction = {true, false},
+ .dai_name = "tac5xx2-aif1",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .init = asoc_sdw_ti_amp_init,
+ .rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init,
+ .controls = lr_spk_controls,
+ .num_controls = ARRAY_SIZE(lr_spk_controls),
+ .widgets = lr_spk_widgets,
+ .num_widgets = ARRAY_SIZE(lr_spk_widgets),
+ },
+ {
+ /* mic */
+ .direction = {false, true},
+ .dai_name = "tac5xx2-aif2",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_ti_dmic_rtd_init,
+ },
+ {
+ /* UAJ */
+ .direction = {true, true},
+ .dai_name = "tac5xx2-aif3",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ .controls = generic_jack_controls,
+ .num_controls = ARRAY_SIZE(generic_jack_controls),
+ .widgets = generic_jack_widgets,
+ .num_widgets = ARRAY_SIZE(generic_jack_widgets),
+ .rtd_init = asoc_sdw_ti_sdca_jack_rtd_init,
+ },
+ },
+ .dai_num = 3,
+ },
+ {
+ .vendor_id = 0x0102,
+ .part_id = 0x5672,
+ .name_prefix = "tac5672",
+ .dais = {
+ {
+ /* speaker with IV sense feedback */
+ .direction = {true, true},
+ .dai_name = "tac5xx2-aif1",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
+ .init = asoc_sdw_ti_amp_init,
+ .rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init,
+ .controls = lr_spk_controls,
+ .num_controls = ARRAY_SIZE(lr_spk_controls),
+ .widgets = lr_spk_widgets,
+ .num_widgets = ARRAY_SIZE(lr_spk_widgets),
+ },
+ {
+ /* mic */
+ .direction = {false, true},
+ .dai_name = "tac5xx2-aif2",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_ti_dmic_rtd_init,
+ },
+ {
+ /* UAJ */
+ .direction = {true, true},
+ .dai_name = "tac5xx2-aif3",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ .controls = generic_jack_controls,
+ .num_controls = ARRAY_SIZE(generic_jack_controls),
+ .widgets = generic_jack_widgets,
+ .num_widgets = ARRAY_SIZE(generic_jack_widgets),
+ .rtd_init = asoc_sdw_ti_sdca_jack_rtd_init,
+ },
+ },
+ .dai_num = 3,
+ },
+ {
+ .vendor_id = 0x0102,
+ .part_id = 0x5682,
+ .name_prefix = "tac5682",
+ .dais = {
+ {
+ /* speaker with echo reference feedback */
+ .direction = {true, true},
+ .dai_name = "tac5xx2-aif1",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
+ .init = asoc_sdw_ti_amp_init,
+ .rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init,
+ .controls = lr_spk_controls,
+ .num_controls = ARRAY_SIZE(lr_spk_controls),
+ .widgets = lr_spk_widgets,
+ .num_widgets = ARRAY_SIZE(lr_spk_widgets),
+ },
+ {
+ /* mic */
+ .direction = {false, true},
+ .dai_name = "tac5xx2-aif2",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_ti_dmic_rtd_init,
+ },
+ {
+ /* UAJ */
+ .direction = {true, true},
+ .dai_name = "tac5xx2-aif3",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ .controls = generic_jack_controls,
+ .num_controls = ARRAY_SIZE(generic_jack_controls),
+ .widgets = generic_jack_widgets,
+ .num_widgets = ARRAY_SIZE(generic_jack_widgets),
+ .rtd_init = asoc_sdw_ti_sdca_jack_rtd_init,
+ },
+ },
+ .dai_num = 3,
+ },
+ {
+ .vendor_id = 0x0102,
+ .part_id = 0x2883,
+ .name_prefix = "tas2883",
+ .dais = {
+ {
+ .direction = {true, false},
+ .dai_name = "tac5xx2-aif1",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .init = asoc_sdw_ti_amp_init,
+ .rtd_init = asoc_sdw_ti_tac5xx2_spk_rtd_init,
+ .controls = lr_spk_controls,
+ .num_controls = ARRAY_SIZE(lr_spk_controls),
+ .widgets = lr_spk_widgets,
+ .num_widgets = ARRAY_SIZE(lr_spk_widgets),
+ },
+ {
+ /* mic */
+ .direction = {false, true},
+ .dai_name = "tac5xx2-aif2",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_ti_dmic_rtd_init,
+ },
+ },
+ .dai_num = 2,
+ },
+ {
+ .vendor_id = 0x0102,
.part_id = 0x0000, /* TAS2783A */
.name_prefix = "tas2783",
+ .is_amp = true,
.dais = {
{
.direction = {true, true},
.dai_name = "tas2783-codec",
+ .component_name = "tas2783",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_AMP_IN_DAI_ID},
.init = asoc_sdw_ti_amp_init,
@@ -194,6 +347,8 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_type = SOC_SDW_DAI_TYPE_MIC,
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ .quirk = SOC_SDW_CODEC_MIC,
+ .quirk_exclude = true,
},
},
.dai_num = 3,
@@ -264,6 +419,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.part_id = 0x1308,
.name_prefix = "rt1308",
.acpi_id = "10EC1308",
+ .is_amp = true,
.dais = {
{
.direction = {true, false},
@@ -287,6 +443,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.vendor_id = 0x025d,
.part_id = 0x1316,
.name_prefix = "rt1316",
+ .is_amp = true,
.dais = {
{
.direction = {true, true},
@@ -309,6 +466,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.vendor_id = 0x025d,
.part_id = 0x1318,
.name_prefix = "rt1318",
+ .is_amp = true,
.dais = {
{
.direction = {true, true},
@@ -501,6 +659,8 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.dai_type = SOC_SDW_DAI_TYPE_MIC,
.dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
.rtd_init = asoc_sdw_rt_dmic_rtd_init,
+ .quirk = SOC_SDW_CODEC_MIC,
+ .quirk_exclude = true,
},
},
.dai_num = 3,
@@ -557,6 +717,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.vendor_id = 0x019f,
.part_id = 0x8373,
.name_prefix = "Left",
+ .is_amp = true,
.dais = {
{
.direction = {true, true},
@@ -578,6 +739,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.vendor_id = 0x019f,
.part_id = 0x8363,
.name_prefix = "Left",
+ .is_amp = true,
.dais = {
{
.direction = {true, false},
@@ -618,6 +780,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.vendor_id = 0x01fa,
.part_id = 0x3556,
.name_prefix = "AMP",
+ .is_amp = true,
.dais = {
{
.direction = {true, false},
@@ -646,6 +809,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.vendor_id = 0x01fa,
.part_id = 0x3557,
.name_prefix = "AMP",
+ .is_amp = true,
.dais = {
{
.direction = {true, false},
@@ -674,6 +838,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.vendor_id = 0x01fa,
.part_id = 0x3563,
.name_prefix = "AMP",
+ .is_amp = true,
.dais = {
{
.direction = {true, false},
@@ -814,6 +979,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
{
.direction = {true, false},
.codec_name = "cs42l43-codec",
+ .component_name = "cs42l43-spk",
.dai_name = "cs42l43-dp6",
.dai_type = SOC_SDW_DAI_TYPE_AMP,
.dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
@@ -940,6 +1106,56 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.aux_num = 1,
},
{
+ .vendor_id = 0x04b3,
+ .part_id = 0x9356,
+ .name_prefix = "es9356",
+ .version_id = 3,
+ .dais = {
+ {
+ .direction = {true, false},
+ .dai_name = "es9356-sdp-aif1",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_JACK_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .init = asoc_sdw_es9356_init,
+ .exit = asoc_sdw_es9356_exit,
+ .rtd_init = asoc_sdw_es9356_rtd_init,
+ .controls = generic_jack_controls,
+ .num_controls = ARRAY_SIZE(generic_jack_controls),
+ .widgets = generic_jack_widgets,
+ .num_widgets = ARRAY_SIZE(generic_jack_widgets),
+ },
+ {
+ .direction = {false, true},
+ .dai_name = "es9356-sdp-aif4",
+ .dai_type = SOC_SDW_DAI_TYPE_MIC,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_DMIC_DAI_ID},
+ .rtd_init = asoc_sdw_es9356_dmic_rtd_init,
+ .widgets = generic_dmic_widgets,
+ .num_widgets = ARRAY_SIZE(generic_dmic_widgets),
+ },
+ {
+ .direction = {false, true},
+ .dai_name = "es9356-sdp-aif2",
+ .dai_type = SOC_SDW_DAI_TYPE_JACK,
+ .dailink = {SOC_SDW_UNUSED_DAI_ID, SOC_SDW_JACK_IN_DAI_ID},
+ },
+ {
+ .direction = {true, false},
+ .dai_name = "es9356-sdp-aif3",
+ .component_name = "es9356",
+ .dai_type = SOC_SDW_DAI_TYPE_AMP,
+ .dailink = {SOC_SDW_AMP_OUT_DAI_ID, SOC_SDW_UNUSED_DAI_ID},
+ .init = asoc_sdw_es9356_amp_init,
+ .rtd_init = asoc_sdw_es9356_spk_rtd_init,
+ .controls = generic_spk_controls,
+ .num_controls = ARRAY_SIZE(generic_spk_controls),
+ .widgets = generic_spk_widgets,
+ .num_widgets = ARRAY_SIZE(generic_spk_widgets),
+ },
+ },
+ .dai_num = 4,
+ },
+ {
.vendor_id = 0x0105,
.part_id = 0xaaaa, /* generic codec mockup */
.name_prefix = "sdw_mockup_mmulti-function",
@@ -985,6 +1201,7 @@ struct asoc_sdw_codec_info codec_info_list[] = {
.vendor_id = 0x0105,
.part_id = 0x55aa, /* amplifier mockup */
.name_prefix = "sdw_mockup_amp1",
+ .is_amp = true,
.version_id = 0,
.dais = {
{
@@ -1110,7 +1327,7 @@ int asoc_sdw_rtd_init(struct snd_soc_pcm_runtime *rtd)
struct asoc_sdw_codec_info *codec_info;
struct snd_soc_dai *dai;
struct sdw_slave *sdw_peripheral;
- const char *spk_components="";
+ const char *spk_components = NULL;
int dai_index;
int ret;
int i;
@@ -1193,7 +1410,7 @@ skip_add_controls_widgets:
else
component = codec_info->dais[dai_index].component_name;
- if (strlen (spk_components) == 0)
+ if (!spk_components)
spk_components =
devm_kasprintf(card->dev, GFP_KERNEL, "%s", component);
else
@@ -1201,13 +1418,15 @@ skip_add_controls_widgets:
spk_components =
devm_kasprintf(card->dev, GFP_KERNEL,
"%s+%s", spk_components, component);
+
+ if (!spk_components)
+ return -ENOMEM;
}
codec_info->dais[dai_index].rtd_init_done = true;
-
}
- if (strlen (spk_components) > 0) {
+ if (spk_components) {
/* Update card components for speaker components */
card->components = devm_kasprintf(card->dev, GFP_KERNEL, "%s spk:%s",
card->components, spk_components);
@@ -1422,7 +1641,9 @@ const char *asoc_sdw_get_codec_name(struct device *dev,
__func__, component->name, dai_info->codec_name);
return devm_kstrdup(dev, component->name, GFP_KERNEL);
} else {
- return devm_kstrdup(dev, dai_info->codec_name, GFP_KERNEL);
+ dev_dbg(dev, "%s component %s is not registered yet\n",
+ __func__, dai_info->codec_name);
+ return ERR_PTR(-EPROBE_DEFER);
}
}
@@ -1553,6 +1774,63 @@ int asoc_sdw_init_simple_dai_link(struct device *dev, struct snd_soc_dai_link *d
}
EXPORT_SYMBOL_NS(asoc_sdw_init_simple_dai_link, "SND_SOC_SDW_UTILS");
+/**
+ * is_sdca_aux_dev_present - Check if an SDCA aux device is present on the SDW peripheral
+ * @dev: Device pointer
+ * @aux_codec_name: Aux codec name from the codec info (e.g. "snd_soc_sdca.HID.2")
+ * @adr_link: ACPI link address
+ * @adr_index: Index of the ACPI link address
+ *
+ * Return: 1 if the aux is present, 0 if the aux is not present, or negative error code.
+ */
+static int is_sdca_aux_dev_present(struct device *dev,
+ const char *aux_codec_name,
+ const struct snd_soc_acpi_link_adr *adr_link,
+ int adr_index)
+{
+ struct sdw_slave *slave;
+ struct device *sdw_dev;
+ const char *sdw_codec_name;
+ int ret = 0;
+ int i;
+
+ if (!aux_codec_name)
+ return 0;
+
+ sdw_codec_name = _asoc_sdw_get_codec_name(dev, adr_link, adr_index);
+ if (!sdw_codec_name)
+ return -ENOMEM;
+
+ sdw_dev = bus_find_device_by_name(&sdw_bus_type, NULL, sdw_codec_name);
+ if (!sdw_dev) {
+ dev_err(dev, "codec %s not found\n", sdw_codec_name);
+ return -EINVAL;
+ }
+
+ slave = dev_to_sdw_dev(sdw_dev);
+
+ if (!slave->sdca_data.interface_revision) {
+ dev_warn(dev, "No SDCA properties, assuming aux '%s' present\n", aux_codec_name);
+ ret = 1;
+ goto put_dev;
+ }
+
+ for (i = 0; i < slave->sdca_data.num_functions; i++) {
+ const char *fname = slave->sdca_data.function[i].name;
+
+ if (fname && strstr(aux_codec_name, fname)) {
+ ret = 1;
+ goto put_dev;
+ }
+ }
+
+ dev_dbg(dev, "SDCA function for aux '%s' NOT FOUND on slave, skipping\n", aux_codec_name);
+
+put_dev:
+ put_device(sdw_dev);
+ return ret;
+}
+
int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card,
int *num_devs, int *num_ends, int *num_aux)
{
@@ -1560,7 +1838,7 @@ int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card,
struct snd_soc_acpi_mach *mach = dev_get_platdata(dev);
struct snd_soc_acpi_mach_params *mach_params = &mach->mach_params;
const struct snd_soc_acpi_link_adr *adr_link;
- int i;
+ int i, j, ret;
for (adr_link = mach_params->links; adr_link->num_adr; adr_link++) {
*num_devs += adr_link->num_adr;
@@ -1575,7 +1853,14 @@ int asoc_sdw_count_sdw_endpoints(struct snd_soc_card *card,
if (!codec_info)
return -EINVAL;
- *num_aux += codec_info->aux_num;
+ for (j = 0; j < codec_info->aux_num; j++) {
+ ret = is_sdca_aux_dev_present(dev, codec_info->auxs[j].codec_name,
+ adr_link, i);
+ if (ret < 0)
+ return ret;
+ if (ret)
+ (*num_aux)++;
+ }
}
}
@@ -1624,20 +1909,16 @@ int asoc_sdw_get_dai_type(u32 type)
}
EXPORT_SYMBOL_NS(asoc_sdw_get_dai_type, "SND_SOC_SDW_UTILS");
-/*
- * Check if the SDCA endpoint is present by the SDW peripheral
- *
+/**
+ * is_sdca_endpoint_present - Check if an SDCA endpoint is present on the SDW peripheral
* @dev: Device pointer
* @codec_info: Codec info pointer
* @adr_link: ACPI link address
* @adr_index: Index of the ACPI link address
* @end_index: Index of the endpoint
*
- * Return: 1 if the endpoint is present,
- * 0 if the endpoint is not present,
- * negative error code.
+ * Return: 1 if the endpoint is present, 0 if the endpoint is not present, or negative error code.
*/
-
static int is_sdca_endpoint_present(struct device *dev,
struct asoc_sdw_codec_info *codec_info,
const struct snd_soc_acpi_link_adr *adr_link,
@@ -1739,6 +2020,14 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
for (j = 0; j < codec_info->aux_num; j++) {
struct snd_soc_component *component;
+ ret = is_sdca_aux_dev_present(dev, codec_info->auxs[j].codec_name,
+ adr_link, i);
+ if (ret < 0)
+ return ret;
+
+ if (ret == 0)
+ continue;
+
component = snd_soc_lookup_component_by_name(codec_info->auxs[j].codec_name);
if (component) {
dev_dbg(dev, "%s found component %s for aux name %s\n",
@@ -1746,7 +2035,9 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
codec_info->auxs[j].codec_name);
soc_aux->dlc.name = component->name;
} else {
- soc_aux->dlc.name = codec_info->auxs[j].codec_name;
+ dev_dbg(dev, "%s the aux component %s is not registered yet\n",
+ __func__, codec_info->auxs[j].codec_name);
+ return -EPROBE_DEFER;
}
soc_aux++;
}
@@ -1846,6 +2137,8 @@ int asoc_sdw_parse_sdw_endpoints(struct snd_soc_card *card,
codec_name = asoc_sdw_get_codec_name(dev, dai_info,
adr_link, i);
+ if (IS_ERR(codec_name))
+ return PTR_ERR(codec_name);
if (!codec_name)
return -ENOMEM;
diff --git a/sound/soc/soc-card.c b/sound/soc/soc-card.c
index 235427d69061..282d666dae9e 100644
--- a/sound/soc/soc-card.c
+++ b/sound/soc/soc-card.c
@@ -246,3 +246,16 @@ void snd_soc_card_remove_dai_link(struct snd_soc_card *card,
card->remove_dai_link(card, dai_link);
}
EXPORT_SYMBOL_GPL(snd_soc_card_remove_dai_link);
+
+void snd_soc_card_set_topology_name(struct snd_soc_card *card, const char *prefix)
+{
+ if (!prefix || !card->name)
+ return;
+
+ if (!card->topology_shortname)
+ card->topology_shortname = devm_kasprintf(card->dev, GFP_KERNEL,
+ "%s-%s", prefix, card->name);
+
+ card->name = card->topology_shortname;
+}
+EXPORT_SYMBOL_GPL(snd_soc_card_set_topology_name);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 3fecf9fc903c..7817beea5b3b 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -136,11 +136,11 @@ static void soc_init_component_debugfs(struct snd_soc_component *component)
if (!component->card->debugfs_card_root)
return;
- if (component->debugfs_prefix) {
+ if (component->driver->debugfs_prefix) {
char *name;
name = kasprintf(GFP_KERNEL, "%s:%s",
- component->debugfs_prefix, component->name);
+ component->driver->debugfs_prefix, component->name);
if (name) {
component->debugfs_root = debugfs_create_dir(name,
component->card->debugfs_card_root);
@@ -194,9 +194,6 @@ static void soc_init_card_debugfs(struct snd_soc_card *card)
card->debugfs_card_root = debugfs_create_dir(card->name,
snd_soc_debugfs_root);
- debugfs_create_u32("dapm_pop_time", 0644, card->debugfs_card_root,
- &card->pop_time);
-
snd_soc_dapm_debugfs_init(snd_soc_card_to_dapm(card), card->debugfs_card_root);
}
@@ -215,6 +212,8 @@ static void snd_soc_debugfs_init(void)
debugfs_create_file("components", 0444, snd_soc_debugfs_root, NULL,
&component_list_fops);
+
+ snd_soc_dapm_debugfs_pop_time(snd_soc_debugfs_root);
}
static void snd_soc_debugfs_exit(void)
@@ -1285,163 +1284,6 @@ int snd_soc_add_pcm_runtimes(struct snd_soc_card *card,
}
EXPORT_SYMBOL_GPL(snd_soc_add_pcm_runtimes);
-static void snd_soc_runtime_get_dai_fmt(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_dai_link *dai_link = rtd->dai_link;
- struct snd_soc_dai *dai, *not_used;
- u64 pos, possible_fmt;
- unsigned int mask = 0, dai_fmt = 0;
- int i, j, priority, pri, until;
-
- /*
- * Get selectable format from each DAIs.
- *
- ****************************
- * NOTE
- * Using .auto_selectable_formats is not mandatory,
- * we can select format manually from Sound Card.
- * When use it, driver should list well tested format only.
- ****************************
- *
- * ex)
- * auto_selectable_formats (= SND_SOC_POSSIBLE_xxx)
- * (A) (B) (C)
- * DAI0_: { 0x000F, 0x00F0, 0x0F00 };
- * DAI1 : { 0xF000, 0x0F00 };
- * (X) (Y)
- *
- * "until" will be 3 in this case (MAX array size from DAI0 and DAI1)
- * Here is dev_dbg() message and comments
- *
- * priority = 1
- * DAI0: (pri, fmt) = (1, 000000000000000F) // 1st check (A) DAI1 is not selected
- * DAI1: (pri, fmt) = (0, 0000000000000000) // Necessary Waste
- * DAI0: (pri, fmt) = (1, 000000000000000F) // 2nd check (A)
- * DAI1: (pri, fmt) = (1, 000000000000F000) // (X)
- * priority = 2
- * DAI0: (pri, fmt) = (2, 00000000000000FF) // 3rd check (A) + (B)
- * DAI1: (pri, fmt) = (1, 000000000000F000) // (X)
- * DAI0: (pri, fmt) = (2, 00000000000000FF) // 4th check (A) + (B)
- * DAI1: (pri, fmt) = (2, 000000000000FF00) // (X) + (Y)
- * priority = 3
- * DAI0: (pri, fmt) = (3, 0000000000000FFF) // 5th check (A) + (B) + (C)
- * DAI1: (pri, fmt) = (2, 000000000000FF00) // (X) + (Y)
- * found auto selected format: 0000000000000F00
- */
- until = snd_soc_dai_get_fmt_max_priority(rtd);
- for (priority = 1; priority <= until; priority++) {
- for_each_rtd_dais(rtd, j, not_used) {
-
- possible_fmt = ULLONG_MAX;
- for_each_rtd_dais(rtd, i, dai) {
- u64 fmt = 0;
-
- pri = (j >= i) ? priority : priority - 1;
- fmt = snd_soc_dai_get_fmt(dai, pri);
- possible_fmt &= fmt;
- }
- if (possible_fmt)
- goto found;
- }
- }
- /* Not Found */
- return;
-found:
- /*
- * convert POSSIBLE_DAIFMT to DAIFMT
- *
- * Some basic/default settings on each is defined as 0.
- * see
- * SND_SOC_DAIFMT_NB_NF
- * SND_SOC_DAIFMT_GATED
- *
- * SND_SOC_DAIFMT_xxx_MASK can't notice it if Sound Card specify
- * these value, and will be overwrite to auto selected value.
- *
- * To avoid such issue, loop from 63 to 0 here.
- * Small number of SND_SOC_POSSIBLE_xxx will be Hi priority.
- * Basic/Default settings of each part and above are defined
- * as Hi priority (= small number) of SND_SOC_POSSIBLE_xxx.
- */
- for (i = 63; i >= 0; i--) {
- pos = 1ULL << i;
- switch (possible_fmt & pos) {
- /*
- * for format
- */
- case SND_SOC_POSSIBLE_DAIFMT_I2S:
- case SND_SOC_POSSIBLE_DAIFMT_RIGHT_J:
- case SND_SOC_POSSIBLE_DAIFMT_LEFT_J:
- case SND_SOC_POSSIBLE_DAIFMT_DSP_A:
- case SND_SOC_POSSIBLE_DAIFMT_DSP_B:
- case SND_SOC_POSSIBLE_DAIFMT_AC97:
- case SND_SOC_POSSIBLE_DAIFMT_PDM:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | i;
- break;
- /*
- * for clock
- */
- case SND_SOC_POSSIBLE_DAIFMT_CONT:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_CONT;
- break;
- case SND_SOC_POSSIBLE_DAIFMT_GATED:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_GATED;
- break;
- /*
- * for clock invert
- */
- case SND_SOC_POSSIBLE_DAIFMT_NB_NF:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_NF;
- break;
- case SND_SOC_POSSIBLE_DAIFMT_NB_IF:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_IF;
- break;
- case SND_SOC_POSSIBLE_DAIFMT_IB_NF:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_NF;
- break;
- case SND_SOC_POSSIBLE_DAIFMT_IB_IF:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_IF;
- break;
- /*
- * for clock provider / consumer
- */
- case SND_SOC_POSSIBLE_DAIFMT_CBP_CFP:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) | SND_SOC_DAIFMT_CBP_CFP;
- break;
- case SND_SOC_POSSIBLE_DAIFMT_CBC_CFP:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) | SND_SOC_DAIFMT_CBC_CFP;
- break;
- case SND_SOC_POSSIBLE_DAIFMT_CBP_CFC:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) | SND_SOC_DAIFMT_CBP_CFC;
- break;
- case SND_SOC_POSSIBLE_DAIFMT_CBC_CFC:
- dai_fmt = (dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK) | SND_SOC_DAIFMT_CBC_CFC;
- break;
- }
- }
-
- /*
- * Some driver might have very complex limitation.
- * In such case, user want to auto-select non-limitation part,
- * and want to manually specify complex part.
- *
- * Or for example, if both CPU and Codec can be clock provider,
- * but because of its quality, user want to specify it manually.
- *
- * Use manually specified settings if sound card did.
- */
- if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK))
- mask |= SND_SOC_DAIFMT_FORMAT_MASK;
- if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_CLOCK_MASK))
- mask |= SND_SOC_DAIFMT_CLOCK_MASK;
- if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_INV_MASK))
- mask |= SND_SOC_DAIFMT_INV_MASK;
- if (!(dai_link->dai_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK))
- mask |= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
-
- dai_link->dai_fmt |= (dai_fmt & mask);
-}
-
/**
* snd_soc_runtime_set_dai_fmt() - Change DAI link format for a ASoC runtime
* @rtd: The runtime for which the DAI link format should be changed
@@ -1520,8 +1362,7 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card,
if (ret < 0)
return ret;
- snd_soc_runtime_get_dai_fmt(rtd);
- ret = snd_soc_runtime_set_dai_fmt(rtd, dai_link->dai_fmt);
+ ret = snd_soc_runtime_set_dai_fmt(rtd, snd_soc_dai_auto_select_format(rtd));
if (ret)
goto err;
@@ -1881,12 +1722,12 @@ static int is_dmi_valid(const char *field)
}
/*
- * Append a string to card->dmi_longname with character cleanups.
+ * Append a string to dmi_longname with character cleanups.
*/
-static void append_dmi_string(struct snd_soc_card *card, const char *str)
+#define DMI_LONGNAME_LEN 80
+static void append_dmi_string(char *dst, const char *str)
{
- char *dst = card->dmi_longname;
- size_t dst_len = sizeof(card->dmi_longname);
+ size_t dst_len = DMI_LONGNAME_LEN;
size_t len;
len = strlen(dst);
@@ -1930,6 +1771,7 @@ static void append_dmi_string(struct snd_soc_card *card, const char *str)
static int snd_soc_set_dmi_name(struct snd_soc_card *card)
{
const char *vendor, *product, *board;
+ char *dmi_longname;
if (card->long_name)
return 0; /* long name already set by driver or from DMI */
@@ -1944,27 +1786,31 @@ static int snd_soc_set_dmi_name(struct snd_soc_card *card)
return 0;
}
- snprintf(card->dmi_longname, sizeof(card->dmi_longname), "%s", vendor);
- cleanup_dmi_name(card->dmi_longname);
+ dmi_longname = devm_kzalloc(card->dev, DMI_LONGNAME_LEN, GFP_KERNEL);
+ if (!dmi_longname)
+ return -ENOMEM;
+
+ snprintf(dmi_longname, DMI_LONGNAME_LEN, "%s", vendor);
+ cleanup_dmi_name(dmi_longname);
product = dmi_get_system_info(DMI_PRODUCT_NAME);
if (product && is_dmi_valid(product)) {
const char *product_version = dmi_get_system_info(DMI_PRODUCT_VERSION);
- append_dmi_string(card, product);
+ append_dmi_string(dmi_longname, product);
/*
* some vendors like Lenovo may only put a self-explanatory
* name in the product version field
*/
if (product_version && is_dmi_valid(product_version))
- append_dmi_string(card, product_version);
+ append_dmi_string(dmi_longname, product_version);
}
board = dmi_get_system_info(DMI_BOARD_NAME);
if (board && is_dmi_valid(board)) {
if (!product || strcasecmp(board, product))
- append_dmi_string(card, board);
+ append_dmi_string(dmi_longname, board);
} else if (!product) {
/* fall back to using legacy name */
dev_warn(card->dev, "ASoC: no DMI board/product name!\n");
@@ -1972,7 +1818,7 @@ static int snd_soc_set_dmi_name(struct snd_soc_card *card)
}
/* set the card long name */
- card->long_name = card->dmi_longname;
+ card->long_name = dmi_longname;
return 0;
}
@@ -1986,7 +1832,6 @@ static inline int snd_soc_set_dmi_name(struct snd_soc_card *card)
static void soc_check_tplg_fes(struct snd_soc_card *card)
{
struct snd_soc_component *component;
- const struct snd_soc_component_driver *comp_drv;
struct snd_soc_dai_link *dai_link;
int i;
@@ -2047,21 +1892,7 @@ match:
}
/* Inform userspace we are using alternate topology */
- if (component->driver->topology_name_prefix) {
-
- /* topology shortname created? */
- if (!card->topology_shortname_created) {
- comp_drv = component->driver;
-
- snprintf(card->topology_shortname, 32, "%s-%s",
- comp_drv->topology_name_prefix,
- card->name);
- card->topology_shortname_created = true;
- }
-
- /* use topology shortname */
- card->name = card->topology_shortname;
- }
+ snd_soc_card_set_topology_name(card, component->driver->topology_name_prefix);
}
}
@@ -2149,10 +1980,25 @@ static void soc_cleanup_card_resources(struct snd_soc_card *card)
}
}
+static void snd_soc_remove_device_links(struct snd_soc_card *card)
+{
+ struct snd_soc_component *component;
+
+ for_each_card_components(card, component) {
+ if (component->card_device_link) {
+ device_link_del(component->card_device_link);
+ component->card_device_link = NULL;
+ }
+ }
+}
+
static void snd_soc_unbind_card(struct snd_soc_card *card)
{
if (snd_soc_card_is_instantiated(card)) {
card->instantiated = false;
+
+ snd_soc_remove_device_links(card);
+
soc_cleanup_card_resources(card);
}
}
@@ -2168,6 +2014,7 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
snd_soc_fill_dummy_dai(card);
snd_soc_dapm_init(dapm, card, NULL);
+ list_del_init(&card->list);
/* check whether any platform is ignore machine FE and using topology */
soc_check_tplg_fes(card);
@@ -2285,10 +2132,35 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
}
}
+ /*
+ * Add device_link from card to component so that system_suspend
+ * will be done in the correct order. The card must suspend first
+ * to stop audio activity before the components suspend.
+ *
+ * If a driver pair already have a link in the opposite direction
+ * they must manage their own suspend order.
+ */
+ for_each_card_components(card, component) {
+ if (card->dev == component->dev)
+ continue;
+
+ component->card_device_link = device_link_add(card->dev,
+ component->dev,
+ DL_FLAG_STATELESS);
+ if (!component->card_device_link) {
+ dev_warn(card->dev, "Could not create device link to %s\n",
+ dev_name(component->dev));
+ }
+ }
+
ret = snd_soc_card_late_probe(card);
if (ret < 0)
goto probe_end;
+ ret = snd_soc_dapm_ignore_suspend_widgets(card);
+ if (ret < 0)
+ goto probe_end;
+
snd_soc_dapm_new_widgets(card);
snd_soc_card_fixup_controls(card);
@@ -2309,8 +2181,15 @@ static int snd_soc_bind_card(struct snd_soc_card *card)
pinctrl_pm_select_sleep_state(component->dev);
probe_end:
- if (ret < 0)
+ if (ret < 0) {
+ snd_soc_remove_device_links(card);
soc_cleanup_card_resources(card);
+ }
+
+ if (ret == -EPROBE_DEFER) {
+ list_add(&card->list, &unbind_card_list);
+ ret = 0;
+ }
snd_soc_card_mutex_unlock(card);
return ret;
@@ -2326,12 +2205,15 @@ static int devm_snd_soc_bind_card(struct device *dev, struct snd_soc_card *card)
struct snd_soc_card **ptr;
int ret;
+ /* The procedure may be called many times during the lifetime of the card. */
+ devres_destroy(dev, devm_card_bind_release, NULL, NULL);
+
ptr = devres_alloc(devm_card_bind_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return -ENOMEM;
ret = snd_soc_bind_card(card);
- if (ret == 0 || ret == -EPROBE_DEFER) {
+ if (ret == 0) {
*ptr = card;
devres_add(dev, ptr);
} else {
@@ -2341,21 +2223,11 @@ static int devm_snd_soc_bind_card(struct device *dev, struct snd_soc_card *card)
return ret;
}
-static int snd_soc_rebind_card(struct snd_soc_card *card)
+static int call_soc_bind_card(struct snd_soc_card *card)
{
- int ret;
-
- if (card->devres_dev) {
- devres_destroy(card->devres_dev, devm_card_bind_release, NULL, NULL);
- ret = devm_snd_soc_bind_card(card->devres_dev, card);
- } else {
- ret = snd_soc_bind_card(card);
- }
-
- if (ret != -EPROBE_DEFER)
- list_del_init(&card->list);
-
- return ret;
+ if (card->devres_dev)
+ return devm_snd_soc_bind_card(card->devres_dev, card);
+ return snd_soc_bind_card(card);
}
/* probes a new socdev */
@@ -2553,8 +2425,6 @@ EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
*/
int snd_soc_register_card(struct snd_soc_card *card)
{
- int ret;
-
if (!card->name || !card->dev)
return -EINVAL;
@@ -2580,17 +2450,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
guard(mutex)(&client_mutex);
- if (card->devres_dev) {
- ret = devm_snd_soc_bind_card(card->devres_dev, card);
- if (ret == -EPROBE_DEFER) {
- list_add(&card->list, &unbind_card_list);
- ret = 0;
- }
- } else {
- ret = snd_soc_bind_card(card);
- }
-
- return ret;
+ return call_soc_bind_card(card);
}
EXPORT_SYMBOL_GPL(snd_soc_register_card);
@@ -2868,11 +2728,6 @@ int snd_soc_component_initialize(struct snd_soc_component *component,
component->dev = dev;
component->driver = driver;
-#ifdef CONFIG_DEBUG_FS
- if (!component->debugfs_prefix)
- component->debugfs_prefix = driver->debugfs_prefix;
-#endif
-
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_component_initialize);
@@ -2910,7 +2765,7 @@ int snd_soc_add_component(struct snd_soc_component *component,
list_add(&component->list, &component_list);
list_for_each_entry_safe(card, c, &unbind_card_list, list)
- snd_soc_rebind_card(card);
+ call_soc_bind_card(card);
err_cleanup:
if (ret < 0)
@@ -3294,6 +3149,45 @@ int snd_soc_of_parse_aux_devs(struct snd_soc_card *card, const char *propname)
}
EXPORT_SYMBOL_GPL(snd_soc_of_parse_aux_devs);
+int snd_soc_of_parse_ignore_suspend_widgets(struct snd_soc_card *card,
+ const char *propname)
+{
+ struct device_node *np = card->dev->of_node;
+ int num_widgets;
+ const char **widgets;
+ int i;
+
+ num_widgets = of_property_count_strings(np, propname);
+ if (num_widgets < 0) {
+ dev_err(card->dev,
+ "ASoC: Property '%s' does not exist\n", propname);
+ return -EINVAL;
+ }
+
+ widgets = devm_kcalloc(card->dev, num_widgets, sizeof(char *), GFP_KERNEL);
+ if (!widgets)
+ return -ENOMEM;
+
+ for (i = 0; i < num_widgets; i++) {
+ const char *name;
+ int ret = of_property_read_string_index(np, propname, i, &name);
+
+ if (ret) {
+ dev_err(card->dev,
+ "ASoC: Property '%s' could not be read: %d\n",
+ propname, ret);
+ return -EINVAL;
+ }
+ widgets[i] = name;
+ }
+
+ card->num_of_ignore_suspend_widgets = num_widgets;
+ card->of_ignore_suspend_widgets = widgets;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_ignore_suspend_widgets);
+
unsigned int snd_soc_daifmt_clock_provider_flipped(unsigned int dai_fmt)
{
unsigned int inv_dai_fmt = dai_fmt & ~SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c
index 2f370fda1266..b098d1100b4b 100644
--- a/sound/soc/soc-dai.c
+++ b/sound/soc/soc-dai.c
@@ -116,72 +116,207 @@ int snd_soc_dai_set_bclk_ratio(struct snd_soc_dai *dai, unsigned int ratio)
dai->driver->ops->set_bclk_ratio)
ret = dai->driver->ops->set_bclk_ratio(dai, ratio);
+ if (!ret)
+ dai->bclk_ratio = ratio;
+
return soc_dai_ret(dai, ret);
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_ratio);
-int snd_soc_dai_get_fmt_max_priority(const struct snd_soc_pcm_runtime *rtd)
+/**
+ * snd_soc_dai_set_bclk_clk - set the BCLK clock for shared clock detection
+ * @dai: DAI
+ * @bclk: BCLK clock pointer (or NULL to clear)
+ *
+ * When multiple DAIs share the same physical BCLK (detected via
+ * clk_is_match()), the ASoC core will automatically constrain their
+ * hw_params so that the resulting BCLK rates are compatible.
+ */
+void snd_soc_dai_set_bclk_clk(struct snd_soc_dai *dai, struct clk *bclk)
+{
+ dai->bclk = bclk;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dai_set_bclk_clk);
+
+static int soc_dai_fmt_match_cnt(u64 fmt)
+{
+ int cnt = 0;
+
+ if (fmt & SND_SOC_POSSIBLE_DAIFMT_FORMAT_MASK)
+ cnt++;
+ if (fmt & SND_SOC_POSSIBLE_DAIFMT_CLOCK_MASK)
+ cnt++;
+ if (fmt & SND_SOC_POSSIBLE_DAIFMT_INV_MASK)
+ cnt++;
+
+ return cnt;
+}
+
+static void soc_dai_auto_select_format(u64 fmt, const struct snd_soc_pcm_runtime *rtd,
+ int idx, u64 *best_fmt)
{
struct snd_soc_dai *dai;
- int i, max = 0;
+ const struct snd_soc_dai_ops *ops;
+ int max_idx = rtd->dai_link->num_cpus + rtd->dai_link->num_codecs;
+ u64 available_fmt;
/*
- * return max num if *ALL* DAIs have .auto_selectable_formats
+ * NOTE
+ * It doesn't support Multi CPU/Codec for now
*/
- for_each_rtd_dais(rtd, i, dai) {
- if (dai->driver->ops &&
- dai->driver->ops->num_auto_selectable_formats)
- max = max(max, dai->driver->ops->num_auto_selectable_formats);
- else
- return 0;
- }
+ if (rtd->dai_link->num_cpus != 1 ||
+ rtd->dai_link->num_codecs != 1)
+ return;
- return max;
-}
+ if (idx >= max_idx)
+ return;
-/**
- * snd_soc_dai_get_fmt - get supported audio format.
- * @dai: DAI
- * @priority: priority level of supported audio format.
- *
- * This should return only formats implemented with high
- * quality by the DAI so that the core can configure a
- * format which will work well with other devices.
- * For example devices which don't support both edges of the
- * LRCLK signal in I2S style formats should only list DSP
- * modes. This will mean that sometimes fewer formats
- * are reported here than are supported by set_fmt().
- */
-u64 snd_soc_dai_get_fmt(const struct snd_soc_dai *dai, int priority)
-{
- const struct snd_soc_dai_ops *ops = dai->driver->ops;
- u64 fmt = 0;
- int i, max = 0, until = priority;
+ dai = rtd->dais[idx];
+ ops = dai->driver->ops;
+
+ /* zero chance of auto select format */
+ if (!ops || !ops->num_auto_selectable_formats)
+ return;
/*
- * Collect auto_selectable_formats until priority
+ ****************************
+ * NOTE
+ ****************************
+ * Using .auto_selectable_formats is not mandatory,
+ * It try to find best formats as much as possible, but automatically selecting the
+ * perfect format is impossible. So you can select full or missing format manually
+ * from Sound Card.
*
* ex)
- * auto_selectable_formats[] = { A, B, C };
- * (A, B, C = SND_SOC_POSSIBLE_DAIFMT_xxx)
+ * CPU Codec
+ * (A)[0] I2S/LEFT_J : IB_NF/IB_IF (X)[0] I2S/DSP_A: NB_NF : GATED
+ * (B)[1] DSP_A/DSP_B: NB_NF/IB_NF (Y)[1] LEFT_J: NB_NF : GATED
+ * (C)[2] ...
*
- * priority = 1 : A
- * priority = 2 : A | B
- * priority = 3 : A | B | C
- * priority = 4 : A | B | C
+ * 1. (A) -> (X) : I2S :update best format
+ * 2. (A) -> (Y) : LEFT_J
+ * 3. (B) -> (X) : DSP_A/NB_NF :update best format
+ * 4. (B) -> (Y) : NB_NF
+ * 5. (C) -> (X) ...
+ * 6. (C) -> (Y) ...
* ...
+ *
+ * In above case GATED will not be selected
+ */
+
+ /* find best formats */
+ for (int i = 0; i < ops->num_auto_selectable_formats; i++) {
+ available_fmt = fmt & ops->auto_selectable_formats[i];
+
+ /* In case of last DAI */
+ if (idx + 1 >= max_idx) {
+ int cnt1 = soc_dai_fmt_match_cnt(*best_fmt);
+ int cnt2 = soc_dai_fmt_match_cnt(available_fmt);
+
+ if (cnt1 < cnt2)
+ *best_fmt = available_fmt;
+ }
+ /* parse with next DAI */
+ else {
+ soc_dai_auto_select_format(available_fmt, rtd, idx + 1, best_fmt);
+ }
+ }
+}
+
+static unsigned int soc_dai_convert_possiblefmt_to_daifmt(u64 possible_fmt, unsigned int configured_fmt)
+{
+ unsigned int fmt = 0;
+ unsigned int mask = 0;
+
+ /*
+ * convert POSSIBLE_DAIFMT to DAIFMT
+ *
+ * Some basic/default settings on each is defined as 0.
+ * see
+ * SND_SOC_DAIFMT_NB_NF
+ * SND_SOC_DAIFMT_GATED
+ *
+ * SND_SOC_DAIFMT_xxx_MASK can't notice it if Sound Card specify
+ * these value, and will be overwrite to auto selected value.
+ *
+ * To avoid such issue, loop from 63 to 0 here.
+ * Small number of SND_SOC_POSSIBLE_xxx will be Hi priority.
+ * Basic/Default settings of each part and above are defined
+ * as Hi priority (= small number) of SND_SOC_POSSIBLE_xxx.
*/
- if (ops)
- max = ops->num_auto_selectable_formats;
+ for (int i = 63; i >= 0; i--) {
+ u64 pos = 1ULL << i;
+
+ switch (possible_fmt & pos) {
+ /*
+ * for format
+ */
+ case SND_SOC_POSSIBLE_DAIFMT_I2S:
+ case SND_SOC_POSSIBLE_DAIFMT_RIGHT_J:
+ case SND_SOC_POSSIBLE_DAIFMT_LEFT_J:
+ case SND_SOC_POSSIBLE_DAIFMT_DSP_A:
+ case SND_SOC_POSSIBLE_DAIFMT_DSP_B:
+ case SND_SOC_POSSIBLE_DAIFMT_AC97:
+ case SND_SOC_POSSIBLE_DAIFMT_PDM:
+ fmt = (fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) | i;
+ break;
+ /*
+ * for clock
+ */
+ case SND_SOC_POSSIBLE_DAIFMT_CONT:
+ fmt = (fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_CONT;
+ break;
+ case SND_SOC_POSSIBLE_DAIFMT_GATED:
+ fmt = (fmt & ~SND_SOC_DAIFMT_CLOCK_MASK) | SND_SOC_DAIFMT_GATED;
+ break;
+ /*
+ * for clock invert
+ */
+ case SND_SOC_POSSIBLE_DAIFMT_NB_NF:
+ fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_NF;
+ break;
+ case SND_SOC_POSSIBLE_DAIFMT_NB_IF:
+ fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_NB_IF;
+ break;
+ case SND_SOC_POSSIBLE_DAIFMT_IB_NF:
+ fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_NF;
+ break;
+ case SND_SOC_POSSIBLE_DAIFMT_IB_IF:
+ fmt = (fmt & ~SND_SOC_DAIFMT_INV_MASK) | SND_SOC_DAIFMT_IB_IF;
+ break;
+ }
+ }
- if (max < until)
- until = max;
+ /*
+ * Some driver might have very complex limitation.
+ * In such case, user want to auto-select non-limitation part,
+ * and want to manually specify complex part.
+ *
+ * Or for example, if both CPU and Codec can be clock provider,
+ * but because of its quality, user want to specify it manually.
+ *
+ * Ignore already configured format if exist
+ */
+ if (!(configured_fmt & SND_SOC_DAIFMT_FORMAT_MASK))
+ mask |= SND_SOC_DAIFMT_FORMAT_MASK;
+ if (!(configured_fmt & SND_SOC_DAIFMT_CLOCK_MASK))
+ mask |= SND_SOC_DAIFMT_CLOCK_MASK;
+ if (!(configured_fmt & SND_SOC_DAIFMT_INV_MASK))
+ mask |= SND_SOC_DAIFMT_INV_MASK;
+ if (!(configured_fmt & SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK))
+ mask |= SND_SOC_DAIFMT_CLOCK_PROVIDER_MASK;
+
+ return configured_fmt | (fmt & mask);
+}
+
+unsigned int snd_soc_dai_auto_select_format(const struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dai_link *dai_link = rtd->dai_link;
+ u64 possible_fmt = 0;
- if (ops && ops->auto_selectable_formats)
- for (i = 0; i < until; i++)
- fmt |= ops->auto_selectable_formats[i];
+ soc_dai_auto_select_format(~0, rtd, 0, &possible_fmt);
- return fmt;
+ return soc_dai_convert_possiblefmt_to_daifmt(possible_fmt, dai_link->dai_fmt);
}
/**
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index d6192204e613..4ad126bd4f70 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -40,6 +40,8 @@
#include <trace/events/asoc.h>
+static u32 pop_time;
+
/* DAPM context */
struct snd_soc_dapm_context {
enum snd_soc_bias_level bias_level;
@@ -161,14 +163,14 @@ static void dapm_assert_locked(struct snd_soc_dapm_context *dapm)
snd_soc_dapm_mutex_assert_held(dapm);
}
-static void dapm_pop_wait(u32 pop_time)
+static void dapm_pop_wait(void)
{
if (pop_time)
schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
}
-__printf(3, 4)
-static void dapm_pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
+__printf(2, 3)
+static void dapm_pop_dbg(struct device *dev, const char *fmt, ...)
{
va_list args;
char *buf;
@@ -1872,8 +1874,7 @@ static void dapm_seq_check_event(struct snd_soc_card *card,
if (w->event && (w->event_flags & event)) {
int ret;
- dapm_pop_dbg(dev, card->pop_time, "pop test : %s %s\n",
- w->name, ev_name);
+ dapm_pop_dbg(dev, "pop test : %s %s\n", w->name, ev_name);
dapm_async_complete(w->dapm);
trace_snd_soc_dapm_widget_event_start(w, event);
ret = w->event(w, NULL, event);
@@ -1909,7 +1910,7 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card,
else
value |= w->off_val << w->shift;
- dapm_pop_dbg(dev, card->pop_time,
+ dapm_pop_dbg(dev,
"pop test : Queue %s: reg=0x%x, 0x%x/0x%x\n",
w->name, reg, value, mask);
@@ -1923,10 +1924,10 @@ static void dapm_seq_run_coalesced(struct snd_soc_card *card,
* same register.
*/
- dapm_pop_dbg(dev, card->pop_time,
+ dapm_pop_dbg(dev,
"pop test : Applying 0x%x/0x%x to %x in %dms\n",
- value, mask, reg, card->pop_time);
- dapm_pop_wait(card->pop_time);
+ value, mask, reg, pop_time);
+ dapm_pop_wait();
dapm_update_bits(dapm, reg, mask, value);
}
@@ -2392,9 +2393,9 @@ static int dapm_power_widgets(struct snd_soc_card *card, int event,
return ret;
}
- dapm_pop_dbg(card->dev, card->pop_time,
- "DAPM sequencing finished, waiting %dms\n", card->pop_time);
- dapm_pop_wait(card->pop_time);
+ dapm_pop_dbg(card->dev,
+ "DAPM sequencing finished, waiting %dms\n", pop_time);
+ dapm_pop_wait();
trace_snd_soc_dapm_done(card, event);
@@ -2561,6 +2562,11 @@ static const struct file_operations dapm_bias_fops = {
.llseek = default_llseek,
};
+void snd_soc_dapm_debugfs_pop_time(struct dentry *parent)
+{
+ debugfs_create_u32("dapm_pop_time", 0644, parent, &pop_time);
+}
+
void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
struct dentry *parent)
{
@@ -2906,20 +2912,18 @@ 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 = dapm_prefix(dapm);
-
- if (prefix) {
- snprintf(prefixed_pin, sizeof(prefixed_pin), "%s %s",
- prefix, pin);
- pin_name = prefixed_pin;
- } else {
- pin_name = pin;
- }
+ bool pin_has_prefix = snd_soc_dapm_pin_has_prefix(dapm->card, pin);
+ bool match;
for_each_card_widgets(dapm->card, w) {
- if (!strcmp(w->name, pin_name)) {
+ match = false;
+
+ if (!strcmp(pin, w->name))
+ match = true;
+ else if (!pin_has_prefix && !snd_soc_dapm_widget_name_cmp(w, pin))
+ match = true;
+
+ if (match) {
if (w->dapm == dapm)
return w;
else
@@ -4606,6 +4610,36 @@ void snd_soc_dapm_connect_dai_link_widgets(struct snd_soc_card *card)
}
}
+int snd_soc_dapm_ignore_suspend_widgets(struct snd_soc_card *card)
+{
+ struct snd_soc_dapm_widget *w;
+ int i;
+
+ for (i = 0; i < card->num_ignore_suspend_widgets; i++) {
+ w = dapm_find_widget(snd_soc_card_to_dapm(card),
+ card->ignore_suspend_widgets[i], true);
+ if (!w) {
+ dev_err(card->dev, "ASoC: DAPM unknown ignore suspend widget %s\n",
+ card->ignore_suspend_widgets[i]);
+ return -EINVAL;
+ }
+ w->ignore_suspend = 1;
+ }
+
+ for (i = 0; i < card->num_of_ignore_suspend_widgets; i++) {
+ w = dapm_find_widget(snd_soc_card_to_dapm(card),
+ card->of_ignore_suspend_widgets[i], true);
+ if (!w) {
+ dev_err(card->dev, "ASoC: DAPM unknown ignore suspend widget %s\n",
+ card->of_ignore_suspend_widgets[i]);
+ return -EINVAL;
+ }
+ w->ignore_suspend = 1;
+ }
+
+ return 0;
+}
+
static void dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream, int event)
{
struct snd_soc_dai *dai;
@@ -4873,6 +4907,33 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
/**
+ * snd_soc_dapm_pin_has_prefix - check if given pin has a known prefix
+ * @card: card to be checked
+ * @pin: pin name
+ *
+ * Returns true if given pin has a known prefix
+ */
+bool snd_soc_dapm_pin_has_prefix(struct snd_soc_card *card, const char *pin)
+{
+ struct snd_soc_component *component;
+ const char *prefix;
+ size_t prefix_len;
+
+ for_each_card_components(card, component) {
+ prefix = component->name_prefix;
+ if (!prefix)
+ continue;
+
+ prefix_len = strlen(prefix);
+ if (!strncmp(pin, prefix, prefix_len) && pin[prefix_len] == ' ')
+ return true;
+ }
+
+ return false;
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_pin_has_prefix);
+
+/**
* snd_soc_dapm_free - free dapm resources
* @dapm: DAPM context
*
diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c
index d33f83ec24f2..718165ba84ac 100644
--- a/sound/soc/soc-devres.c
+++ b/sound/soc/soc-devres.c
@@ -49,11 +49,6 @@ int devm_snd_soc_register_component(struct device *dev,
}
EXPORT_SYMBOL_GPL(devm_snd_soc_register_component);
-static void devm_card_release(struct device *dev, void *res)
-{
- snd_soc_unregister_card(*(struct snd_soc_card **)res);
-}
-
/**
* devm_snd_soc_register_card - resource managed card registration
* @dev: Device used to manage card
@@ -64,31 +59,10 @@ static void devm_card_release(struct device *dev, void *res)
*/
int devm_snd_soc_register_card(struct device *dev, struct snd_soc_card *card)
{
- struct snd_soc_card **ptr;
- int ret;
-
- ptr = devres_alloc(devm_card_release, sizeof(*ptr), GFP_KERNEL);
- if (!ptr)
- return -ENOMEM;
-
- ret = snd_soc_register_card(card);
- if (ret == 0) {
- *ptr = card;
- devres_add(dev, ptr);
- } else {
- devres_free(ptr);
- }
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
-
-int devm_snd_soc_register_deferrable_card(struct device *dev, struct snd_soc_card *card)
-{
card->devres_dev = dev;
return snd_soc_register_card(card);
}
-EXPORT_SYMBOL_GPL(devm_snd_soc_register_deferrable_card);
+EXPORT_SYMBOL_GPL(devm_snd_soc_register_card);
#ifdef CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c
index 6b8c65763c82..467426d2b5e4 100644
--- a/sound/soc/soc-generic-dmaengine-pcm.c
+++ b/sound/soc/soc-generic-dmaengine-pcm.c
@@ -334,6 +334,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component = {
.pointer = dmaengine_pcm_pointer,
.pcm_new = dmaengine_pcm_new,
.sync_stop = dmaengine_pcm_sync_stop,
+ .debugfs_prefix = "dma",
};
static const struct snd_soc_component_driver dmaengine_pcm_component_process = {
@@ -347,6 +348,7 @@ static const struct snd_soc_component_driver dmaengine_pcm_component_process = {
.copy = dmaengine_copy,
.pcm_new = dmaengine_pcm_new,
.sync_stop = dmaengine_pcm_sync_stop,
+ .debugfs_prefix = "dma",
};
static const char * const dmaengine_pcm_dma_channel_names[] = {
@@ -441,9 +443,6 @@ int snd_dmaengine_pcm_register(struct device *dev,
if (!pcm)
return -ENOMEM;
-#ifdef CONFIG_DEBUG_FS
- pcm->component.debugfs_prefix = "dma";
-#endif
if (!config)
config = &snd_dmaengine_pcm_default_config;
pcm->config = config;
diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c
index bbf277670718..c935571d43e9 100644
--- a/sound/soc/soc-ops.c
+++ b/sound/soc/soc-ops.c
@@ -461,6 +461,10 @@ int snd_soc_limit_volume(struct snd_soc_card *card, const char *name, int max)
mc->platform_max = max;
ret = snd_soc_clip_to_platform_max(kctl);
}
+ } else {
+ /* Some cards blindly add limits for multiple variants. */
+ dev_dbg(card->dev, "Volume limit for unknown control '%s'\n",
+ name);
}
return ret;
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 9b12eedb77c3..0e49290a8c90 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -12,6 +12,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
+#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/pinctrl/consumer.h>
#include <linux/slab.h>
@@ -26,6 +27,9 @@
#include <sound/soc-link.h>
#include <sound/initval.h>
+
+DEFINE_GUARD(snd_soc_card_mutex, struct snd_soc_card *,
+ snd_soc_card_mutex_lock(_T), snd_soc_card_mutex_unlock(_T))
#define soc_pcm_ret(rtd, ret) _soc_pcm_ret(rtd, __func__, ret)
static inline int _soc_pcm_ret(struct snd_soc_pcm_runtime *rtd,
const char *func, int ret)
@@ -467,6 +471,114 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
return 0;
}
+/*
+ * Shared BCLK constraint: when multiple DAIs share the same physical BCLK,
+ * constrain hw_params so that the BCLK rate (rate * channels * sample_bits,
+ * or rate * slots * slot_width for TDM) remains consistent.
+ */
+
+static int soc_pcm_shared_bclk_rule_rate(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ struct snd_soc_dai *dai = rule->private;
+ struct snd_soc_card *card = dai->component->card;
+ struct snd_soc_pcm_runtime *rtd;
+ struct snd_soc_dai *other_dai;
+ unsigned long active_bclk_rate = 0;
+ struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ struct snd_interval constraint = { .empty = 1 };
+ unsigned int target_rate;
+ int i;
+
+ /* Protect the rtd list traversal with the ASoC card mutex helper. */
+ guard(snd_soc_card_mutex)(card);
+
+ /* Scan all DAIs on the card for an active peer sharing the same BCLK */
+ for_each_card_rtds(card, rtd) {
+ for_each_rtd_cpu_dais(rtd, i, other_dai) {
+ if (other_dai == dai)
+ continue;
+ if (!other_dai->bclk)
+ continue;
+ if (!snd_soc_dai_active(other_dai))
+ continue;
+ /*
+ * Skip peers whose hw_params hasn't run yet.
+ * symmetric_rate is set by soc_pcm_set_dai_params()
+ * after snd_soc_dai_hw_params(), so non-zero means
+ * the DAI's clk_set_rate() has already executed.
+ */
+ if (!other_dai->symmetric_rate)
+ continue;
+ if (!clk_is_match(dai->bclk, other_dai->bclk))
+ continue;
+
+ active_bclk_rate = clk_get_rate(other_dai->bclk);
+ if (active_bclk_rate)
+ goto found;
+ }
+ }
+
+ return 0;
+
+found:
+ if (dai->bclk_ratio) {
+ /*
+ * Driver has set an explicit BCLK ratio (e.g. for TDM where
+ * BCLK = rate * slots * slot_width). The only valid rate is
+ * active_bclk_rate / bclk_ratio.
+ */
+ target_rate = active_bclk_rate / dai->bclk_ratio;
+
+ constraint.min = target_rate;
+ constraint.max = target_rate;
+ } else {
+ struct snd_interval *channels = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_CHANNELS);
+ struct snd_interval *sample_bits = hw_param_interval(params,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
+
+ /*
+ * Default: BCLK = rate * channels * sample_bits.
+ * Calculate the range of valid rates given the current
+ * channel and sample_bits intervals.
+ */
+ if (!channels->min || !sample_bits->min)
+ return 0;
+
+ constraint.max = active_bclk_rate /
+ ((unsigned long)channels->min * sample_bits->min);
+
+ if (channels->max && sample_bits->max)
+ constraint.min = active_bclk_rate /
+ ((unsigned long)channels->max * sample_bits->max);
+ else
+ constraint.min = constraint.max;
+ }
+
+ constraint.integer = 1;
+ constraint.empty = 0;
+
+ return snd_interval_refine(rate, &constraint);
+}
+
+static int soc_pcm_apply_shared_bclk(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ if (!dai->bclk)
+ return 0;
+
+ dev_dbg(dai->dev,
+ "ASoC: registering shared BCLK rate constraint\n");
+
+ return snd_pcm_hw_rule_add(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ soc_pcm_shared_bclk_rule_rate, dai,
+ SNDRV_PCM_HW_PARAM_CHANNELS,
+ SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
+ -1);
+}
+
static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -903,6 +1015,13 @@ static int __soc_pcm_open(struct snd_soc_pcm_runtime *rtd,
if (ret != 0)
goto err;
}
+
+ /* Shared BCLK constraint across DAIs on the same card */
+ for_each_rtd_cpu_dais(rtd, i, dai) {
+ ret = soc_pcm_apply_shared_bclk(substream, dai);
+ if (ret != 0)
+ goto err;
+ }
dynamic:
snd_soc_runtime_activate(rtd, substream->stream);
ret = 0;
diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c
index 85679c8e0229..35cbe29d2275 100644
--- a/sound/soc/soc-topology.c
+++ b/sound/soc/soc-topology.c
@@ -1326,9 +1326,24 @@ static int soc_tplg_dapm_complete(struct soc_tplg *tplg)
return ret;
}
+static int soc_tplg_check_name(const char *name)
+{
+ if (strnlen(name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
+ SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
+ return -EINVAL;
+
+ return 0;
+}
+
static int set_stream_info(struct soc_tplg *tplg, struct snd_soc_pcm_stream *stream,
struct snd_soc_tplg_stream_caps *caps)
{
+ int ret;
+
+ ret = soc_tplg_check_name(caps->name);
+ if (ret)
+ return ret;
+
stream->stream_name = devm_kstrdup(tplg->dev, caps->name, GFP_KERNEL);
if (!stream->stream_name)
return -ENOMEM;
@@ -1380,7 +1395,11 @@ static int soc_tplg_dai_create(struct soc_tplg *tplg,
if (dai_drv == NULL)
return -ENOMEM;
- if (strlen(pcm->dai_name)) {
+ ret = soc_tplg_check_name(pcm->dai_name);
+ if (ret)
+ goto err;
+
+ if (pcm->dai_name[0]) {
dai_drv->name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL);
if (!dai_drv->name) {
ret = -ENOMEM;
@@ -1486,7 +1505,11 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
if (tplg->ops)
link->dobj.unload = tplg->ops->link_unload;
- if (strlen(pcm->pcm_name)) {
+ ret = soc_tplg_check_name(pcm->pcm_name);
+ if (ret)
+ goto err;
+
+ if (pcm->pcm_name[0]) {
link->name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL);
link->stream_name = devm_kstrdup(tplg->dev, pcm->pcm_name, GFP_KERNEL);
if (!link->name || !link->stream_name) {
@@ -1496,7 +1519,11 @@ static int soc_tplg_fe_link_create(struct soc_tplg *tplg,
}
link->id = le32_to_cpu(pcm->pcm_id);
- if (strlen(pcm->dai_name)) {
+ ret = soc_tplg_check_name(pcm->dai_name);
+ if (ret)
+ goto err;
+
+ if (pcm->dai_name[0]) {
link->cpus->dai_name = devm_kstrdup(tplg->dev, pcm->dai_name, GFP_KERNEL);
if (!link->cpus->dai_name) {
ret = -ENOMEM;
@@ -1848,6 +1875,10 @@ static int soc_tplg_dai_config(struct soc_tplg *tplg,
memset(&dai_component, 0, sizeof(dai_component));
+ ret = soc_tplg_check_name(d->dai_name);
+ if (ret)
+ return ret;
+
dai_component.dai_name = d->dai_name;
dai = snd_soc_find_dai(&dai_component);
if (!dai) {
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index c8adfff826bd..87e9c86ca4f8 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -36,6 +36,7 @@ int snd_soc_ret(const struct device *dev, int ret, const char *fmt, ...)
vaf.va = &args;
dev_err(dev, "ASoC error (%d): %pV", ret, &vaf);
+ va_end(args);
}
return ret;
@@ -182,13 +183,6 @@ static const struct snd_soc_component_driver dummy_codec = {
SNDRV_PCM_FMTBIT_U32_LE | \
SNDRV_PCM_FMTBIT_IEC958_SUBFRAME_LE)
-/*
- * Select these from Sound Card Manually
- * SND_SOC_POSSIBLE_DAIFMT_CBP_CFP
- * SND_SOC_POSSIBLE_DAIFMT_CBP_CFC
- * SND_SOC_POSSIBLE_DAIFMT_CBC_CFP
- * SND_SOC_POSSIBLE_DAIFMT_CBC_CFC
- */
static const u64 dummy_dai_formats =
SND_SOC_POSSIBLE_DAIFMT_I2S |
SND_SOC_POSSIBLE_DAIFMT_RIGHT_J |
diff --git a/sound/soc/sof/amd/acp-common.c b/sound/soc/sof/amd/acp-common.c
index 0c3a92f5f942..df656cdc1527 100644
--- a/sound/soc/sof/amd/acp-common.c
+++ b/sound/soc/sof/amd/acp-common.c
@@ -149,7 +149,8 @@ static struct snd_soc_acpi_mach *amd_sof_sdw_machine_select(struct snd_sof_dev *
break;
}
if (i == acp_data->info.count || !link->num_adr)
- break;
+ if (!mach->machine_check || mach->machine_check(acp_data->sdw))
+ break;
}
if (mach && mach->link_mask) {
mach->mach_params.subsystem_rev = acp_data->pci_rev;
diff --git a/sound/soc/sof/amd/acp-ipc.c b/sound/soc/sof/amd/acp-ipc.c
index 3cd4674dd800..94025bc799ea 100644
--- a/sound/soc/sof/amd/acp-ipc.c
+++ b/sound/soc/sof/amd/acp-ipc.c
@@ -181,14 +181,14 @@ irqreturn_t acp_sof_ipc_irq_thread(int irq, void *context)
}
dsp_msg = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_msg_write);
- if (dsp_msg) {
+ if (dsp_msg == ACP_DSP_MSG_SET) {
snd_sof_ipc_msgs_rx(sdev);
acp_dsp_ipc_host_done(sdev);
ipc_irq = true;
}
dsp_ack = snd_sof_dsp_read(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write);
- if (dsp_ack) {
+ if (dsp_ack == ACP_DSP_ACK_SET) {
if (likely(sdev->fw_state == SOF_FW_BOOT_COMPLETE)) {
guard(spinlock_irq)(&sdev->ipc_lock);
diff --git a/sound/soc/sof/amd/acp.c b/sound/soc/sof/amd/acp.c
index 71a18f156de2..e6af8927baa0 100644
--- a/sound/soc/sof/amd/acp.c
+++ b/sound/soc/sof/amd/acp.c
@@ -223,7 +223,7 @@ static int psp_send_cmd(struct acp_dev_data *adata, int cmd)
{
struct snd_sof_dev *sdev = adata->dev;
int ret;
- u32 data;
+ int data;
if (!cmd)
return -EINVAL;
@@ -377,6 +377,33 @@ void memcpy_to_scratch(struct snd_sof_dev *sdev, u32 offset, unsigned int *src,
snd_sof_dsp_write(sdev, ACP_DSP_BAR, reg_offset + i, src[j]);
}
+static int acp_init_scratch_mem_ipc_flags(struct snd_sof_dev *sdev)
+{
+ u32 dsp_msg_write, dsp_ack_write, host_msg_write, host_ack_write;
+
+ dsp_msg_write = sdev->debug_box.offset +
+ offsetof(struct scratch_ipc_conf, sof_dsp_msg_write);
+ dsp_ack_write = sdev->debug_box.offset +
+ offsetof(struct scratch_ipc_conf, sof_dsp_ack_write);
+ host_msg_write = sdev->debug_box.offset +
+ offsetof(struct scratch_ipc_conf, sof_host_msg_write);
+ host_ack_write = sdev->debug_box.offset +
+ offsetof(struct scratch_ipc_conf, sof_host_ack_write);
+ /* Initialize host message write flag */
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + host_msg_write, 0);
+
+ /* Initialize host ack write flag */
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + host_ack_write, 0);
+
+ /* Initialize DSP message write flag */
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_msg_write, 0);
+
+ /* Initialize DSP ack write flag */
+ snd_sof_dsp_write(sdev, ACP_DSP_BAR, ACP_SCRATCH_REG_0 + dsp_ack_write, 0);
+
+ return 0;
+}
+
static int acp_memory_init(struct snd_sof_dev *sdev)
{
struct acp_dev_data *adata = sdev->pdata->hw_pdata;
@@ -384,6 +411,7 @@ static int acp_memory_init(struct snd_sof_dev *sdev)
snd_sof_dsp_update_bits(sdev, ACP_DSP_BAR, desc->dsp_intr_base + DSP_SW_INTR_CNTL_OFFSET,
ACP_DSP_INTR_EN_MASK, ACP_DSP_INTR_EN_MASK);
+ acp_init_scratch_mem_ipc_flags(sdev);
init_dma_descriptor(adata);
return 0;
diff --git a/sound/soc/sof/amd/acp.h b/sound/soc/sof/amd/acp.h
index 2b7ea8c64106..7bcb76676a98 100644
--- a/sound/soc/sof/amd/acp.h
+++ b/sound/soc/sof/amd/acp.h
@@ -116,6 +116,8 @@
#define ACP_SRAM_PAGE_COUNT 128
#define ACP6X_SDW_MAX_MANAGER_COUNT 2
#define ACP70_SDW_MAX_MANAGER_COUNT ACP6X_SDW_MAX_MANAGER_COUNT
+#define ACP_DSP_MSG_SET 1
+#define ACP_DSP_ACK_SET 1
enum clock_source {
ACP_CLOCK_96M = 0,
diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig
index e31f4c4061d8..915abbef398d 100644
--- a/sound/soc/sof/intel/Kconfig
+++ b/sound/soc/sof/intel/Kconfig
@@ -266,10 +266,8 @@ config SND_SOC_SOF_METEORLAKE
config SND_SOC_SOF_INTEL_LNL
tristate
- select SOUNDWIRE_INTEL if SND_SOC_SOF_INTEL_SOUNDWIRE != n
select SND_SOC_SOF_HDA_GENERIC
select SND_SOC_SOF_INTEL_SOUNDWIRE_LINK_BASELINE
- select SND_SOF_SOF_HDA_SDW_BPT if SND_SOC_SOF_INTEL_SOUNDWIRE != n
select SND_SOC_SOF_IPC4
select SND_SOC_SOF_INTEL_MTL
@@ -329,8 +327,10 @@ config SND_SOC_SOF_HDA_GENERIC
select SND_INTEL_DSP_CONFIG
select SND_SOC_SOF_HDA_LINK_BASELINE
select SND_SOC_SOF_HDA_PROBES
- select SND_SOC_SDW_UTILS if SND_SOC_SOF_INTEL_SOUNDWIRE
+ select SND_SOC_SDW_UTILS if SND_SOC_SOF_INTEL_SOUNDWIRE !=n
select SND_SOC_SOF_HDA_MLINK if SND_SOC_SOF_HDA_LINK
+ select SND_SOF_SOF_HDA_SDW_BPT if SND_SOC_SOF_INTEL_LNL != n && \
+ SND_SOC_SOF_INTEL_SOUNDWIRE !=n
help
This option is not user-selectable but automagically handled by
'select' statements at a higher level.
diff --git a/sound/soc/sof/intel/hda-mlink.c b/sound/soc/sof/intel/hda-mlink.c
index ce603a2343de..92314e3b568a 100644
--- a/sound/soc/sof/intel/hda-mlink.c
+++ b/sound/soc/sof/intel/hda-mlink.c
@@ -988,24 +988,19 @@ struct hdac_ext_link *hdac_bus_eml_sdw_get_hlink(struct hdac_bus *bus)
}
EXPORT_SYMBOL_NS(hdac_bus_eml_sdw_get_hlink, "SND_SOC_SOF_HDA_MLINK");
-int hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable)
+void hdac_bus_eml_enable_offload(struct hdac_bus *bus, bool alt, int elid, bool enable)
{
struct hdac_ext2_link *h2link;
struct hdac_ext_link *hlink;
h2link = find_ext2_link(bus, alt, elid);
- if (!h2link)
- return -ENODEV;
-
- if (!h2link->ofls)
- return 0;
+ if (!h2link || !h2link->ofls)
+ return;
hlink = &h2link->hext_link;
scoped_guard(mutex, &h2link->eml_lock)
hdaml_lctl_offload_enable(hlink->ml_addr + AZX_REG_ML_LCTL, enable);
-
- return 0;
}
EXPORT_SYMBOL_NS(hdac_bus_eml_enable_offload, "SND_SOC_SOF_HDA_MLINK");
diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c
index 8662b422eb80..dc85903b8d46 100644
--- a/sound/soc/sof/intel/hda.c
+++ b/sound/soc/sof/intel/hda.c
@@ -1159,7 +1159,6 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
struct snd_soc_acpi_adr_device *adr_dev;
const char *name_prefix = "";
int index = link->num_adr;
- bool is_amp = true; /* Set it to false if the codec wiah any NON-AMP DAI type */
int ep_index = 0;
int i, j;
@@ -1216,7 +1215,6 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
endpoints[ep_index].aggregated = 0;
endpoints[ep_index].group_id = 0;
endpoints[ep_index].group_position = 0;
- is_amp = false;
}
ep_index++;
}
@@ -1230,16 +1228,6 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
return NULL;
}
- /*
- * codec_info_list[].is_amp is a codec-level override: for multi-function
- * codecs we must treat the whole codec as an AMP when it is described as
- * such in the codec info table, even if some endpoints were detected as
- * non-AMP above. Callers/UCM rely on this to keep name_prefix and AMP
- * indexing stable and backwards compatible.
- */
- if (codec_info_list[i].is_amp)
- is_amp = true;
-
adr_dev[index].adr = ((u64)sdw_device->id.class_id & 0xFF) |
((u64)sdw_device->id.part_id & 0xFFFF) << 8 |
((u64)sdw_device->id.mfg_id & 0xFFFF) << 24 |
@@ -1247,7 +1235,7 @@ static struct snd_soc_acpi_adr_device *find_acpi_adr_device(struct device *dev,
((u64)(sdw_device->id.sdw_version & 0xF) << 44) |
((u64)(sdw_device->bus->link_id & 0xF) << 48);
- if (!is_amp) {
+ if (!codec_info_list[i].is_amp) {
/* For non-amp codecs, get name_prefix from codec_info_list[] */
adr_dev[index].name_prefix = devm_kasprintf(dev, GFP_KERNEL, "%s", name_prefix);
goto done_name_prefix;
diff --git a/sound/soc/sof/intel/lnl.c b/sound/soc/sof/intel/lnl.c
index c01ea7e731aa..83703ebc6385 100644
--- a/sound/soc/sof/intel/lnl.c
+++ b/sound/soc/sof/intel/lnl.c
@@ -20,22 +20,12 @@
#include "lnl.h"
#include <sound/hda-mlink.h>
-/* this helps allows the DSP to setup DMIC/SSP */
-static int hdac_bus_offload_dmic_ssp(struct hdac_bus *bus, bool enable)
+/* Configure DSP offload for DMIC/SSP/UAOL */
+static void hdac_bus_set_dsp_offload(struct hdac_bus *bus, bool enable)
{
- int ret;
-
- ret = hdac_bus_eml_enable_offload(bus, true,
- AZX_REG_ML_LEPTR_ID_INTEL_SSP, enable);
- if (ret < 0)
- return ret;
-
- ret = hdac_bus_eml_enable_offload(bus, true,
- AZX_REG_ML_LEPTR_ID_INTEL_DMIC, enable);
- if (ret < 0)
- return ret;
-
- return 0;
+ hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_SSP, enable);
+ hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_DMIC, enable);
+ hdac_bus_eml_enable_offload(bus, true, AZX_REG_ML_LEPTR_ID_INTEL_UAOL, enable);
}
static int lnl_hda_dsp_probe(struct snd_sof_dev *sdev)
@@ -46,18 +36,14 @@ static int lnl_hda_dsp_probe(struct snd_sof_dev *sdev)
if (ret < 0)
return ret;
- return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true);
+ hdac_bus_set_dsp_offload(sof_to_bus(sdev), true);
+
+ return 0;
}
static void lnl_hda_dsp_remove(struct snd_sof_dev *sdev)
{
- int ret;
-
- ret = hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), false);
- if (ret < 0)
- dev_warn(sdev->dev,
- "Failed to disable offload for DMIC/SSP: %d\n", ret);
-
+ hdac_bus_set_dsp_offload(sof_to_bus(sdev), false);
hda_dsp_remove(sdev);
}
@@ -69,7 +55,9 @@ static int lnl_hda_dsp_resume(struct snd_sof_dev *sdev)
if (ret < 0)
return ret;
- return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true);
+ hdac_bus_set_dsp_offload(sof_to_bus(sdev), true);
+
+ return 0;
}
static int lnl_hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
@@ -80,7 +68,9 @@ static int lnl_hda_dsp_runtime_resume(struct snd_sof_dev *sdev)
if (ret < 0)
return ret;
- return hdac_bus_offload_dmic_ssp(sof_to_bus(sdev), true);
+ hdac_bus_set_dsp_offload(sof_to_bus(sdev), true);
+
+ return 0;
}
static int lnl_dsp_post_fw_run(struct snd_sof_dev *sdev)
diff --git a/sound/soc/sof/ipc3-control.c b/sound/soc/sof/ipc3-control.c
index 2b1befad6d5c..d1697401b1da 100644
--- a/sound/soc/sof/ipc3-control.c
+++ b/sound/soc/sof/ipc3-control.c
@@ -315,10 +315,13 @@ static int sof_ipc3_bytes_get(struct snd_sof_control *scontrol,
}
/* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
- if (data->size > scontrol->max_size - sizeof(*data)) {
+ if (data->size > scontrol->max_size - sizeof(*cdata) -
+ sizeof(*data)) {
dev_err_ratelimited(scomp->dev,
"%u bytes of control data is invalid, max is %zu\n",
- data->size, scontrol->max_size - sizeof(*data));
+ data->size,
+ scontrol->max_size - sizeof(*cdata) -
+ sizeof(*data));
return -EINVAL;
}
@@ -336,6 +339,8 @@ static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol,
struct sof_ipc_ctrl_data *cdata = scontrol->ipc_control_data;
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_abi_hdr *data = cdata->data;
+ const struct sof_abi_hdr *new_hdr =
+ (const struct sof_abi_hdr *)ucontrol->value.bytes.data;
size_t size;
if (scontrol->max_size > sizeof(ucontrol->value.bytes.data)) {
@@ -344,14 +349,18 @@ static int sof_ipc3_bytes_put(struct snd_sof_control *scontrol,
return -EINVAL;
}
- /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */
- if (data->size > scontrol->max_size - sizeof(*data)) {
- dev_err_ratelimited(scomp->dev, "data size too big %u bytes max is %zu\n",
- data->size, scontrol->max_size - sizeof(*data));
+ /* Validate the new data's size, not the old one */
+ if (new_hdr->size > scontrol->max_size - sizeof(*cdata) -
+ sizeof(*new_hdr)) {
+ dev_err_ratelimited(scomp->dev,
+ "data size too big %u bytes max is %zu\n",
+ new_hdr->size,
+ scontrol->max_size - sizeof(*cdata) -
+ sizeof(*new_hdr));
return -EINVAL;
}
- size = data->size + sizeof(*data);
+ size = new_hdr->size + sizeof(*new_hdr);
/* copy from kcontrol */
memcpy(data, ucontrol->value.bytes.data, size);
@@ -389,9 +398,17 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
}
/* be->max is coming from topology */
- if (header.length > scontrol->max_size) {
- dev_err_ratelimited(scomp->dev, "Bytes data size %d exceeds max %zu\n",
- header.length, scontrol->max_size);
+ if (header.length > scontrol->max_size - sizeof(*cdata)) {
+ dev_err_ratelimited(scomp->dev, "Bytes data size %u exceeds max %zu\n",
+ header.length, scontrol->max_size - sizeof(*cdata));
+ return -EINVAL;
+ }
+
+ /* Ensure the data is large enough to contain the ABI header */
+ if (header.length < sizeof(struct sof_abi_hdr)) {
+ dev_err_ratelimited(scomp->dev,
+ "Bytes data size %u less than ABI header %zu\n",
+ header.length, sizeof(struct sof_abi_hdr));
return -EINVAL;
}
@@ -427,7 +444,7 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
}
/* be->max has been verified to be >= sizeof(struct sof_abi_hdr) */
- if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) {
+ if (cdata->data->size > scontrol->max_size - sizeof(*cdata) - sizeof(struct sof_abi_hdr)) {
dev_err_ratelimited(scomp->dev, "Mismatch in ABI data size (truncated?)\n");
goto err_restore;
}
@@ -443,7 +460,7 @@ static int sof_ipc3_bytes_ext_put(struct snd_sof_control *scontrol,
err_restore:
/* If we have an issue, we restore the old, valid bytes control data */
if (scontrol->old_ipc_control_data) {
- memcpy(cdata->data, scontrol->old_ipc_control_data, scontrol->max_size);
+ memcpy(cdata, scontrol->old_ipc_control_data, scontrol->max_size);
kfree(scontrol->old_ipc_control_data);
scontrol->old_ipc_control_data = NULL;
}
@@ -482,10 +499,13 @@ static int _sof_ipc3_bytes_ext_get(struct snd_sof_control *scontrol,
}
/* check data size doesn't exceed max coming from topology */
- if (cdata->data->size > scontrol->max_size - sizeof(struct sof_abi_hdr)) {
- dev_err_ratelimited(scomp->dev, "User data size %d exceeds max size %zu\n",
+ if (cdata->data->size > scontrol->max_size - sizeof(*cdata) -
+ sizeof(struct sof_abi_hdr)) {
+ dev_err_ratelimited(scomp->dev,
+ "User data size %u exceeds max size %zu\n",
cdata->data->size,
- scontrol->max_size - sizeof(struct sof_abi_hdr));
+ scontrol->max_size - sizeof(*cdata) -
+ sizeof(struct sof_abi_hdr));
return -EINVAL;
}
@@ -535,6 +555,15 @@ static void snd_sof_update_control(struct snd_sof_control *scontrol,
return;
}
+ /* Verify the size fits within the allocation */
+ if (cdata->num_elems > scontrol->max_size - sizeof(*local_cdata) -
+ sizeof(*local_cdata->data)) {
+ dev_err(scomp->dev,
+ "cdata binary size %u exceeds buffer\n",
+ cdata->num_elems);
+ return;
+ }
+
/* copy the new binary data */
memcpy(local_cdata->data, cdata->data, cdata->num_elems);
} else if (cdata->num_elems != scontrol->num_channels) {
@@ -626,16 +655,28 @@ static void sof_ipc3_control_update(struct snd_sof_dev *sdev, void *ipc_control_
return;
}
- expected_size = sizeof(struct sof_ipc_ctrl_data);
switch (cdata->type) {
case SOF_CTRL_TYPE_VALUE_CHAN_GET:
case SOF_CTRL_TYPE_VALUE_CHAN_SET:
- expected_size += cdata->num_elems *
- sizeof(struct sof_ipc_ctrl_value_chan);
+ if (check_mul_overflow((size_t)cdata->num_elems,
+ sizeof(struct sof_ipc_ctrl_value_chan),
+ &expected_size))
+ return;
+ if (check_add_overflow(expected_size,
+ sizeof(struct sof_ipc_ctrl_data),
+ &expected_size))
+ return;
break;
case SOF_CTRL_TYPE_DATA_GET:
case SOF_CTRL_TYPE_DATA_SET:
- expected_size += cdata->num_elems + sizeof(struct sof_abi_hdr);
+ if (check_add_overflow((size_t)cdata->num_elems,
+ sizeof(struct sof_abi_hdr),
+ &expected_size))
+ return;
+ if (check_add_overflow(expected_size,
+ sizeof(struct sof_ipc_ctrl_data),
+ &expected_size))
+ return;
break;
default:
return;
diff --git a/sound/soc/sof/ipc3-topology.c b/sound/soc/sof/ipc3-topology.c
index 8006777f2f64..4e066bbded91 100644
--- a/sound/soc/sof/ipc3-topology.c
+++ b/sound/soc/sof/ipc3-topology.c
@@ -519,6 +519,7 @@ static int sof_ipc3_widget_setup_comp_mixer(struct snd_sof_widget *swidget)
static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
{
struct snd_soc_component *scomp = swidget->scomp;
+ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct snd_sof_pipeline *spipe = swidget->spipe;
struct sof_ipc_pipe_new *pipeline;
struct snd_sof_widget *comp_swidget;
@@ -559,8 +560,15 @@ static int sof_ipc3_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
if (ret < 0)
goto err;
- if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE))
+ if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) {
+ pipeline->core = SOF_DSP_PRIMARY_CORE;
+ } else if (pipeline->core > sdev->num_cores - 1) {
+ dev_info(scomp->dev,
+ "out of range core id for %s, moving it %d -> %d\n",
+ swidget->widget->name, pipeline->core,
+ SOF_DSP_PRIMARY_CORE);
pipeline->core = SOF_DSP_PRIMARY_CORE;
+ }
if (sof_debug_check_flag(SOF_DBG_DYNAMIC_PIPELINES_OVERRIDE))
swidget->dynamic_pipeline_widget =
diff --git a/sound/soc/sof/ipc4-control.c b/sound/soc/sof/ipc4-control.c
index 596c3d77a34e..8d86d32a16ca 100644
--- a/sound/soc/sof/ipc4-control.c
+++ b/sound/soc/sof/ipc4-control.c
@@ -13,13 +13,12 @@
#include "ipc4-topology.h"
static int sof_ipc4_set_get_kcontrol_data(struct snd_sof_control *scontrol,
+ struct sof_ipc4_msg *msg,
bool set, bool lock)
{
- struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
struct snd_soc_component *scomp = scontrol->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
const struct sof_ipc_ops *iops = sdev->ipc->ops;
- struct sof_ipc4_msg *msg = &cdata->msg;
struct snd_sof_widget *swidget;
bool widget_found = false;
int ret = 0;
@@ -88,9 +87,9 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge
{
struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
struct sof_ipc4_gain *gain = swidget->private;
- struct sof_ipc4_msg *msg = &cdata->msg;
struct sof_ipc4_gain_params params;
bool all_channels_equal = true;
+ struct sof_ipc4_msg msg;
u32 value;
int ret, i;
@@ -107,6 +106,7 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge
* notify DSP with a single IPC message if all channel values are equal. Otherwise send
* a separate IPC for each channel.
*/
+ memcpy(&msg, &cdata->msg, sizeof(msg));
for (i = 0; i < scontrol->num_channels; i++) {
if (all_channels_equal) {
params.channels = SOF_IPC4_GAIN_ALL_CHANNELS_MASK;
@@ -121,12 +121,10 @@ sof_ipc4_set_volume_data(struct snd_sof_dev *sdev, struct snd_sof_widget *swidge
params.curve_duration_h = gain->data.params.curve_duration_h;
params.curve_type = gain->data.params.curve_type;
- msg->data_ptr = &params;
- msg->data_size = sizeof(params);
+ msg.data_ptr = &params;
+ msg.data_size = sizeof(params);
- ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock);
- msg->data_ptr = NULL;
- msg->data_size = 0;
+ ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, true, lock);
if (ret < 0) {
dev_err(sdev->dev, "Failed to set volume update for %s\n",
scontrol->name);
@@ -208,7 +206,7 @@ sof_ipc4_set_generic_control_data(struct snd_sof_dev *sdev,
{
struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
struct sof_ipc4_control_msg_payload *data;
- struct sof_ipc4_msg *msg = &cdata->msg;
+ struct sof_ipc4_msg msg;
size_t data_size;
unsigned int i;
int ret;
@@ -225,12 +223,11 @@ sof_ipc4_set_generic_control_data(struct snd_sof_dev *sdev,
data->chanv[i].value = cdata->chanv[i].value;
}
- msg->data_ptr = data;
- msg->data_size = data_size;
+ memcpy(&msg, &cdata->msg, sizeof(msg));
+ msg.data_ptr = data;
+ msg.data_size = data_size;
- ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock);
- msg->data_ptr = NULL;
- msg->data_size = 0;
+ ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, true, lock);
if (ret < 0)
dev_err(sdev->dev, "Failed to set control update for %s\n",
scontrol->name);
@@ -245,7 +242,7 @@ static void sof_ipc4_refresh_generic_control(struct snd_sof_control *scontrol)
struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc4_control_msg_payload *data;
- struct sof_ipc4_msg *msg = &cdata->msg;
+ struct sof_ipc4_msg msg;
size_t data_size;
unsigned int i;
int ret;
@@ -263,13 +260,13 @@ static void sof_ipc4_refresh_generic_control(struct snd_sof_control *scontrol)
data->id = cdata->index;
data->num_elems = scontrol->num_channels;
- msg->data_ptr = data;
- msg->data_size = data_size;
+
+ memcpy(&msg, &cdata->msg, sizeof(msg));
+ msg.data_ptr = data;
+ msg.data_size = data_size;
scontrol->comp_data_dirty = false;
- ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, true);
- msg->data_ptr = NULL;
- msg->data_size = 0;
+ ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, false, true);
if (!ret) {
for (i = 0; i < scontrol->num_channels; i++) {
cdata->chanv[i].channel = data->chanv[i].channel;
@@ -291,7 +288,7 @@ sof_ipc4_set_bytes_control_data(struct snd_sof_control *scontrol, bool lock)
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc4_control_msg_payload *msg_data;
struct sof_abi_hdr *data = cdata->data;
- struct sof_ipc4_msg *msg = &cdata->msg;
+ struct sof_ipc4_msg msg;
size_t data_size;
int ret;
@@ -304,14 +301,13 @@ sof_ipc4_set_bytes_control_data(struct snd_sof_control *scontrol, bool lock)
msg_data->num_elems = data->size;
memcpy(msg_data->data, data->data, data->size);
- msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type);
+ memcpy(&msg, &cdata->msg, sizeof(msg));
+ msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type);
- msg->data_ptr = msg_data;
- msg->data_size = data_size;
+ msg.data_ptr = msg_data;
+ msg.data_size = data_size;
- ret = sof_ipc4_set_get_kcontrol_data(scontrol, true, lock);
- msg->data_ptr = NULL;
- msg->data_size = 0;
+ ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, true, lock);
if (ret < 0)
dev_err(scomp->dev, "%s: Failed to set control update for %s\n",
__func__, scontrol->name);
@@ -328,7 +324,7 @@ sof_ipc4_refresh_bytes_control(struct snd_sof_control *scontrol, bool lock)
struct snd_soc_component *scomp = scontrol->scomp;
struct sof_ipc4_control_msg_payload *msg_data;
struct sof_abi_hdr *data = cdata->data;
- struct sof_ipc4_msg *msg = &cdata->msg;
+ struct sof_ipc4_msg msg;
size_t data_size;
int ret = 0;
@@ -346,29 +342,30 @@ sof_ipc4_refresh_bytes_control(struct snd_sof_control *scontrol, bool lock)
if (!msg_data)
return -ENOMEM;
- msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type);
+ memcpy(&msg, &cdata->msg, sizeof(msg));
+ msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type);
msg_data->id = cdata->index;
msg_data->num_elems = 0; /* ignored for bytes */
- msg->data_ptr = msg_data;
- msg->data_size = data_size;
+ msg.data_ptr = msg_data;
+ msg.data_size = data_size;
scontrol->comp_data_dirty = false;
- ret = sof_ipc4_set_get_kcontrol_data(scontrol, false, lock);
+ ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, false, lock);
if (!ret) {
- if (msg->data_size > scontrol->max_size - sizeof(*data)) {
+ if (msg.data_size > scontrol->max_size - sizeof(*data)) {
dev_err(scomp->dev,
"%s: no space for data in %s (%zu, %zu)\n",
- __func__, scontrol->name, msg->data_size,
+ __func__, scontrol->name, msg.data_size,
scontrol->max_size - sizeof(*data));
ret = -EINVAL;
goto out;
}
- data->size = msg->data_size;
+ data->size = msg.data_size;
scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size;
- memcpy(data->data, msg->data_ptr, data->size);
+ memcpy(data->data, msg.data_ptr, data->size);
} else {
dev_err(scomp->dev, "Failed to read control data for %s\n",
scontrol->name);
@@ -376,9 +373,6 @@ sof_ipc4_refresh_bytes_control(struct snd_sof_control *scontrol, bool lock)
}
out:
- msg->data_ptr = NULL;
- msg->data_size = 0;
-
kfree(msg_data);
return ret;
@@ -508,7 +502,7 @@ static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev,
{
struct sof_ipc4_control_data *cdata = scontrol->ipc_control_data;
struct sof_abi_hdr *data = cdata->data;
- struct sof_ipc4_msg *msg = &cdata->msg;
+ struct sof_ipc4_msg msg;
int ret = 0;
/* Send the new data to the firmware only if it is powered up */
@@ -530,28 +524,26 @@ static int sof_ipc4_set_get_bytes_data(struct snd_sof_dev *sdev,
return sof_ipc4_refresh_bytes_control(scontrol, lock);
}
- msg->extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type);
+ memcpy(&msg, &cdata->msg, sizeof(msg));
+ msg.extension = SOF_IPC4_MOD_EXT_MSG_PARAM_ID(data->type);
- msg->data_ptr = data->data;
+ msg.data_ptr = data->data;
if (set)
- msg->data_size = data->size;
+ msg.data_size = data->size;
else
- msg->data_size = scontrol->max_size - sizeof(*data);
+ msg.data_size = scontrol->max_size - sizeof(*data);
- ret = sof_ipc4_set_get_kcontrol_data(scontrol, set, lock);
+ ret = sof_ipc4_set_get_kcontrol_data(scontrol, &msg, set, lock);
if (ret < 0) {
dev_err(sdev->dev, "Failed to %s for %s\n",
set ? "set bytes update" : "get bytes",
scontrol->name);
} else if (!set) {
/* Update the sizes according to the received payload data */
- data->size = msg->data_size;
+ data->size = msg.data_size;
scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size;
}
- msg->data_ptr = NULL;
- msg->data_size = 0;
-
return ret;
}
@@ -562,6 +554,8 @@ static int sof_ipc4_bytes_put(struct snd_sof_control *scontrol,
struct snd_soc_component *scomp = scontrol->scomp;
struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_abi_hdr *data = cdata->data;
+ const struct sof_abi_hdr *new_hdr =
+ (const struct sof_abi_hdr *)ucontrol->value.bytes.data;
size_t size;
int ret;
@@ -572,15 +566,16 @@ static int sof_ipc4_bytes_put(struct snd_sof_control *scontrol,
return -EINVAL;
}
- /* scontrol->max_size has been verified to be >= sizeof(struct sof_abi_hdr) */
- if (data->size > scontrol->max_size - sizeof(*data)) {
+ /* Validate the new data's size, not the old one */
+ if (new_hdr->size > scontrol->max_size - sizeof(*new_hdr)) {
dev_err_ratelimited(scomp->dev,
"data size too big %u bytes max is %zu\n",
- data->size, scontrol->max_size - sizeof(*data));
+ new_hdr->size,
+ scontrol->max_size - sizeof(*new_hdr));
return -EINVAL;
}
- size = data->size + sizeof(*data);
+ size = new_hdr->size + sizeof(*new_hdr);
/* copy from kcontrol */
memcpy(data, ucontrol->value.bytes.data, size);
@@ -880,6 +875,16 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message)
*/
if (type == SND_SOC_TPLG_TYPE_BYTES) {
struct sof_abi_hdr *data = cdata->data;
+ size_t source_size = struct_size(msg_data, data, msg_data->num_elems);
+
+ if (source_size > ndata->event_data_size) {
+ dev_warn(sdev->dev,
+ "%s: invalid bytes notification size for %s (%zu, %u)\n",
+ __func__, scontrol->name, source_size,
+ ndata->event_data_size);
+ scontrol->comp_data_dirty = true;
+ goto notify;
+ }
if (msg_data->num_elems > scontrol->max_size - sizeof(*data)) {
dev_warn(sdev->dev,
@@ -892,6 +897,17 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message)
scontrol->size = sizeof(*cdata) + sizeof(*data) + data->size;
}
} else {
+ size_t source_size = struct_size(msg_data, chanv, msg_data->num_elems);
+
+ if (source_size > ndata->event_data_size) {
+ dev_warn(sdev->dev,
+ "%s: invalid channel notification size for %s (%zu, %u)\n",
+ __func__, scontrol->name, source_size,
+ ndata->event_data_size);
+ scontrol->comp_data_dirty = true;
+ goto notify;
+ }
+
for (i = 0; i < msg_data->num_elems; i++) {
u32 channel = msg_data->chanv[i].channel;
@@ -919,6 +935,8 @@ static void sof_ipc4_control_update(struct snd_sof_dev *sdev, void *ipc_message)
scontrol->comp_data_dirty = true;
}
+notify:
+
/*
* Look up the ALSA kcontrol of the scontrol to be able to send a
* notification to user space
diff --git a/sound/soc/sof/ipc4-topology.c b/sound/soc/sof/ipc4-topology.c
index 76812d8fb567..95ad5266b0c6 100644
--- a/sound/soc/sof/ipc4-topology.c
+++ b/sound/soc/sof/ipc4-topology.c
@@ -238,6 +238,23 @@ struct snd_sof_widget *sof_ipc4_find_swidget_by_ids(struct snd_sof_dev *sdev,
return NULL;
}
+static u32 sof_ipc4_fmt_cfg_to_type(u32 fmt_cfg)
+{
+ /* Fetch the sample type from the fmt for 8 and 32 bit formats */
+ u32 __bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt_cfg);
+
+ if (__bits == 8 || __bits == 32)
+ return SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt_cfg);
+
+ /*
+ * Return LSB integer type for 16, 20 and 24 formats as the firmware is
+ * handling the LSB/MSB alignment internally, for the kernel this
+ * should not be taken into account, we treat them as LSB to match with
+ * the format we support on the PCM side.
+ */
+ return SOF_IPC4_TYPE_LSB_INTEGER;
+}
+
static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_format *pin_fmt,
int num_formats)
{
@@ -246,8 +263,9 @@ static void sof_ipc4_dbg_audio_format(struct device *dev, struct sof_ipc4_pin_fo
for (i = 0; i < num_formats; i++) {
struct sof_ipc4_audio_format *fmt = &pin_fmt[i].audio_fmt;
dev_dbg(dev,
- "Pin #%d: %uHz, %ubit, %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n",
+ "Pin #%d: %uHz, %ubit (type: %u), %luch (ch_map %#x ch_cfg %u interleaving_style %u fmt_cfg %#x) buffer size %d\n",
pin_fmt[i].pin_index, fmt->sampling_frequency, fmt->bit_depth,
+ sof_ipc4_fmt_cfg_to_type(fmt->fmt_cfg),
SOF_IPC4_AUDIO_FORMAT_CFG_CHANNELS_COUNT(fmt->fmt_cfg),
fmt->ch_map, fmt->ch_cfg, fmt->interleaving_style, fmt->fmt_cfg,
pin_fmt[i].buffer_size);
@@ -624,6 +642,7 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
struct sof_ipc4_available_audio_format *available_fmt;
struct snd_soc_component *scomp = swidget->scomp;
struct sof_ipc4_copier *ipc4_copier;
+ struct snd_sof_pcm_stream *sps;
struct snd_sof_pcm *spcm;
int node_type = 0;
int ret, dir;
@@ -668,24 +687,23 @@ static int sof_ipc4_widget_setup_pcm(struct snd_sof_widget *swidget)
if (ret)
goto free_available_fmt;
- if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
- struct snd_sof_pcm_stream *sps = &spcm->stream[dir];
+ sps = &spcm->stream[dir];
+ sof_update_ipc_object(scomp, &sps->dsp_max_burst_size_in_ms,
+ SOF_COPIER_DEEP_BUFFER_TOKENS,
+ swidget->tuples,
+ swidget->num_tuples, sizeof(u32), 1);
- sof_update_ipc_object(scomp, &sps->dsp_max_burst_size_in_ms,
- SOF_COPIER_DEEP_BUFFER_TOKENS,
- swidget->tuples,
- swidget->num_tuples, sizeof(u32), 1);
- /* Set default DMA buffer size if it is not specified in topology */
- if (!sps->dsp_max_burst_size_in_ms) {
- struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
- struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
+ /* Set default DMA buffer size if it is not specified in topology */
+ if (!sps->dsp_max_burst_size_in_ms) {
+ struct snd_sof_widget *pipe_widget = swidget->spipe->pipe_widget;
+ struct sof_ipc4_pipeline *pipeline = pipe_widget->private;
+ if (dir == SNDRV_PCM_STREAM_PLAYBACK)
sps->dsp_max_burst_size_in_ms = pipeline->use_chain_dma ?
SOF_IPC4_CHAIN_DMA_BUFFER_SIZE : SOF_IPC4_MIN_DMA_BUFFER_SIZE;
- }
- } else {
- /* Capture data is copied from DSP to host in 1ms bursts */
- spcm->stream[dir].dsp_max_burst_size_in_ms = 1;
+ else
+ /* Capture data is copied from DSP to host in 1ms bursts */
+ sps->dsp_max_burst_size_in_ms = 1;
}
skip_gtw_cfg:
@@ -927,6 +945,7 @@ static void sof_ipc4_widget_free_comp_dai(struct snd_sof_widget *swidget)
static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
{
struct snd_soc_component *scomp = swidget->scomp;
+ struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
struct sof_ipc4_pipeline *pipeline;
struct snd_sof_pipeline *spipe = swidget->spipe;
int ret;
@@ -942,6 +961,16 @@ static int sof_ipc4_widget_setup_comp_pipeline(struct snd_sof_widget *swidget)
goto err;
}
+ if (sof_debug_check_flag(SOF_DBG_DISABLE_MULTICORE)) {
+ pipeline->core_id = SOF_DSP_PRIMARY_CORE;
+ } else if (pipeline->core_id > sdev->num_cores - 1) {
+ dev_info(scomp->dev,
+ "out of range core id for %s, moving it %d -> %d\n",
+ swidget->widget->name, pipeline->core_id,
+ SOF_DSP_PRIMARY_CORE);
+ pipeline->core_id = SOF_DSP_PRIMARY_CORE;
+ }
+
swidget->core = pipeline->core_id;
spipe->core_mask |= BIT(pipeline->core_id);
if (pipeline->direction_valid) {
@@ -1092,6 +1121,15 @@ static int sof_ipc4_widget_setup_comp_src(struct snd_sof_widget *swidget)
if (ret)
goto err;
+ if (!src->available_fmt.num_input_formats ||
+ !src->available_fmt.num_output_formats) {
+ dev_err(scomp->dev,
+ "Invalid number of formats: input: %d, output: %d\n",
+ src->available_fmt.num_input_formats,
+ src->available_fmt.num_output_formats);
+ goto err;
+ }
+
ret = sof_update_ipc_object(scomp, &src->data, SOF_SRC_TOKENS, swidget->tuples,
swidget->num_tuples, sizeof(*src), 1);
if (ret) {
@@ -1135,6 +1173,15 @@ static int sof_ipc4_widget_setup_comp_asrc(struct snd_sof_widget *swidget)
if (ret)
goto err;
+ if (!asrc->available_fmt.num_input_formats ||
+ !asrc->available_fmt.num_output_formats) {
+ dev_err(scomp->dev,
+ "Invalid number of formats: input: %d, output: %d\n",
+ asrc->available_fmt.num_input_formats,
+ asrc->available_fmt.num_output_formats);
+ goto err;
+ }
+
ret = sof_update_ipc_object(scomp, &asrc->data, SOF_ASRC_TOKENS, swidget->tuples,
swidget->num_tuples, sizeof(*asrc), 1);
if (ret) {
@@ -1353,23 +1400,6 @@ static int sof_ipc4_widget_assign_instance_id(struct snd_sof_dev *sdev,
return 0;
}
-static u32 sof_ipc4_fmt_cfg_to_type(u32 fmt_cfg)
-{
- /* Fetch the sample type from the fmt for 8 and 32 bit formats */
- u32 __bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(fmt_cfg);
-
- if (__bits == 8 || __bits == 32)
- return SOF_IPC4_AUDIO_FORMAT_CFG_SAMPLE_TYPE(fmt_cfg);
-
- /*
- * Return LSB integer type for 20 and 24 formats as the firmware is
- * handling the LSB/MSB alignment internally, for the kernel this
- * should not be taken into account, we treat them as LSB to match with
- * the format we support on the PCM side.
- */
- return SOF_IPC4_TYPE_LSB_INTEGER;
-}
-
/* update hw_params based on the audio stream format */
static int sof_ipc4_update_hw_params(struct snd_sof_dev *sdev, struct snd_pcm_hw_params *params,
struct sof_ipc4_audio_format *fmt, u32 param_to_update)
@@ -2430,10 +2460,19 @@ sof_ipc4_prepare_copier_module(struct snd_sof_widget *swidget,
copier_data->gtw_cfg.dma_buffer_size);
break;
case snd_soc_dapm_dai_out:
- case snd_soc_dapm_aif_out:
copier_data->gtw_cfg.dma_buffer_size =
SOF_IPC4_MIN_DMA_BUFFER_SIZE * copier_data->base_config.obs;
break;
+ case snd_soc_dapm_aif_out:
+ copier_data->gtw_cfg.dma_buffer_size =
+ max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms) *
+ copier_data->base_config.obs;
+ dev_dbg(sdev->dev, "copier %s, dma buffer%s: %u ms (%u bytes)",
+ swidget->widget->name,
+ deep_buffer_dma_ms ? " (using Deep Buffer)" : "",
+ max((u32)SOF_IPC4_MIN_DMA_BUFFER_SIZE, deep_buffer_dma_ms),
+ copier_data->gtw_cfg.dma_buffer_size);
+ break;
default:
break;
}
@@ -2611,16 +2650,6 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
return input_fmt_index;
/*
- * For playback, the SRC sink rate will be configured based on the requested output
- * format, which is restricted to only deal with DAI's with a single format for now.
- */
- if (dir == SNDRV_PCM_STREAM_PLAYBACK && available_fmt->num_output_formats > 1) {
- dev_err(sdev->dev, "Invalid number of output formats: %d for SRC %s\n",
- available_fmt->num_output_formats, swidget->widget->name);
- return -EINVAL;
- }
-
- /*
* SRC does not perform format conversion, so the output channels and valid bit depth must
* be the same as that of the input.
*/
@@ -2629,12 +2658,36 @@ static int sof_ipc4_prepare_src_module(struct snd_sof_widget *swidget,
out_ref_valid_bits = SOF_IPC4_AUDIO_FORMAT_CFG_V_BIT_DEPTH(in_audio_fmt->fmt_cfg);
out_ref_type = sof_ipc4_fmt_cfg_to_type(in_audio_fmt->fmt_cfg);
- /*
- * For capture, the SRC module should convert the rate to match the rate requested by the
- * PCM hw_params. Set the reference params based on the fe_params unconditionally as it
- * will be ignored for playback anyway.
- */
- out_ref_rate = params_rate(fe_params);
+ if (src->data.sink_rate) {
+ /* Use the sink rate as reference */
+ out_ref_rate = src->data.sink_rate;
+ } else if (dir == SNDRV_PCM_STREAM_CAPTURE) {
+ /*
+ * Use the fe rate as reference for capture if the sink rate is
+ * not set since we need to convert to the rate the PCM device
+ * is openned with
+ */
+ out_ref_rate = params_rate(fe_params);
+ } else {
+ /*
+ * Otherwise try to guess what the rate should be:
+ * The output formats must have single rate specified if the
+ * sink rate is not set for an SRC in playback path.
+ */
+ int i;
+
+ out_audio_fmt = &available_fmt->output_pin_fmts[0].audio_fmt;
+ out_ref_rate = out_audio_fmt->sampling_frequency;
+ for (i = 1; i < available_fmt->num_output_formats; i++) {
+ out_audio_fmt = &available_fmt->output_pin_fmts[i].audio_fmt;
+ if (out_ref_rate != out_audio_fmt->sampling_frequency) {
+ dev_err(sdev->dev,
+ "Cannot determine the output rate for SRC: %s\n",
+ swidget->widget->name);
+ return -EINVAL;
+ }
+ }
+ }
output_fmt_index = sof_ipc4_init_output_audio_fmt(sdev, swidget,
&src->data.base_config,
diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c
index c0c906a78eba..11a95dba3c9c 100644
--- a/sound/soc/sof/nocodec.c
+++ b/sound/soc/sof/nocodec.c
@@ -15,7 +15,6 @@
static struct snd_soc_card sof_nocodec_card = {
.name = "nocodec", /* the sof- prefix is added by the core */
- .topology_shortname = "sof-nocodec",
.owner = THIS_MODULE
};
@@ -89,9 +88,10 @@ static int sof_nocodec_probe(struct platform_device *pdev)
int ret;
card->dev = &pdev->dev;
- card->topology_shortname_created = true;
mach = pdev->dev.platform_data;
+ snd_soc_card_set_topology_name(card, "sof");
+
ret = sof_nocodec_setup(card->dev, mach->mach_params.num_dai_drivers,
mach->mach_params.dai_drivers);
if (ret < 0)
diff --git a/sound/soc/sof/sof-client-ipc-flood-test.c b/sound/soc/sof/sof-client-ipc-flood-test.c
index 7b72d1c9c739..2396cc35489a 100644
--- a/sound/soc/sof/sof-client-ipc-flood-test.c
+++ b/sound/soc/sof/sof-client-ipc-flood-test.c
@@ -10,7 +10,6 @@
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/ktime.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
diff --git a/sound/soc/sof/sof-client-ipc-kernel-injector.c b/sound/soc/sof/sof-client-ipc-kernel-injector.c
index d5984990098a..02d0d97ad1a0 100644
--- a/sound/soc/sof/sof-client-ipc-kernel-injector.c
+++ b/sound/soc/sof/sof-client-ipc-kernel-injector.c
@@ -7,7 +7,6 @@
#include <linux/auxiliary_bus.h>
#include <linux/debugfs.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <sound/sof/header.h>
diff --git a/sound/soc/sof/sof-client-ipc-msg-injector.c b/sound/soc/sof/sof-client-ipc-msg-injector.c
index c28f106de6ba..932ab459c079 100644
--- a/sound/soc/sof/sof-client-ipc-msg-injector.c
+++ b/sound/soc/sof/sof-client-ipc-msg-injector.c
@@ -9,7 +9,6 @@
#include <linux/completion.h>
#include <linux/debugfs.h>
#include <linux/ktime.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
diff --git a/sound/soc/sof/sof-client-probes-ipc3.c b/sound/soc/sof/sof-client-probes-ipc3.c
index a78ec0954a61..a3e382d6161f 100644
--- a/sound/soc/sof/sof-client-probes-ipc3.c
+++ b/sound/soc/sof/sof-client-probes-ipc3.c
@@ -107,7 +107,7 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
struct device *dev = &cdev->auxdev.dev;
struct sof_ipc_probe_info_params msg = {{{0}}};
struct sof_ipc_probe_info_params *reply;
- size_t bytes;
+ size_t bytes, elem_size, payload_size;
int ret;
*params = NULL;
@@ -128,14 +128,29 @@ static int ipc3_probes_info(struct sof_client_dev *cdev, unsigned int cmd,
if (ret < 0 || reply->rhdr.error < 0)
goto exit;
+ payload_size = reply->rhdr.hdr.size;
+ if (payload_size < offsetof(struct sof_ipc_probe_info_params, dma)) {
+ ret = -EINVAL;
+ goto exit;
+ }
+
if (!reply->num_elems)
goto exit;
if (cmd == SOF_IPC_PROBE_DMA_INFO)
- bytes = sizeof(reply->dma[0]);
+ elem_size = sizeof(reply->dma[0]);
else
- bytes = sizeof(reply->desc[0]);
- bytes *= reply->num_elems;
+ elem_size = sizeof(reply->desc[0]);
+
+ payload_size -= offsetof(struct sof_ipc_probe_info_params, dma);
+ if (reply->num_elems > payload_size / elem_size) {
+ dev_err(dev, "%s: invalid probe info element count %u\n",
+ __func__, reply->num_elems);
+ ret = -EINVAL;
+ goto exit;
+ }
+
+ bytes = reply->num_elems * elem_size;
*params = kmemdup(&reply->dma[0], bytes, GFP_KERNEL);
if (!*params) {
ret = -ENOMEM;
diff --git a/sound/soc/sof/sof-client-probes-ipc4.c b/sound/soc/sof/sof-client-probes-ipc4.c
index 88397c7dc4c3..2eef32b55395 100644
--- a/sound/soc/sof/sof-client-probes-ipc4.c
+++ b/sound/soc/sof/sof-client-probes-ipc4.c
@@ -248,10 +248,19 @@ static int ipc4_probes_points_info(struct sof_client_dev *cdev,
return ret;
}
info = msg.data_ptr;
+ if (msg.data_size < sizeof(*info) ||
+ info->num_elems > (msg.data_size - sizeof(*info)) /
+ sizeof(info->points[0])) {
+ dev_err(dev, "%s: invalid probe info element count %u\n",
+ __func__, info->num_elems);
+ kfree(msg.data_ptr);
+ return -EINVAL;
+ }
+
*num_desc = info->num_elems;
dev_dbg(dev, "%s: got %zu probe points", __func__, *num_desc);
- *desc = kzalloc(*num_desc * sizeof(**desc), GFP_KERNEL);
+ *desc = kcalloc(*num_desc, sizeof(**desc), GFP_KERNEL);
if (!*desc) {
kfree(msg.data_ptr);
return -ENOMEM;
diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c
index 63d582c65891..42a2d90bb705 100644
--- a/sound/soc/sof/topology.c
+++ b/sound/soc/sof/topology.c
@@ -23,6 +23,13 @@ static bool disable_function_topology;
module_param(disable_function_topology, bool, 0444);
MODULE_PARM_DESC(disable_function_topology, "Disable function topology loading");
+#define MAX_FEATURE_TPLG_COUNT 16
+
+static char *feature_topologies[MAX_FEATURE_TPLG_COUNT];
+static int feature_tplg_cnt;
+module_param_array(feature_topologies, charp, &feature_tplg_cnt, 0444);
+MODULE_PARM_DESC(feature_topologies, "Topology list for virtual loop DAI link");
+
#define COMP_ID_UNASSIGNED 0xffffffff
/*
* Constants used in the computation of linear volume gain
@@ -733,10 +740,13 @@ static int sof_parse_token_sets(struct snd_soc_component *scomp,
int ret;
while (array_size > 0 && total < count * token_instance_num) {
+ if (array_size < (int)sizeof(*array))
+ return -EINVAL;
+
asize = le32_to_cpu(array->size);
/* validate asize */
- if (asize < sizeof(*array)) {
+ if (asize < (int)sizeof(*array)) {
dev_err(scomp->dev, "error: invalid array size 0x%x\n",
asize);
return -EINVAL;
@@ -1567,8 +1577,15 @@ static int sof_widget_ready(struct snd_soc_component *scomp, int index,
int core = sof_get_token_value(SOF_TKN_COMP_CORE_ID, swidget->tuples,
swidget->num_tuples);
- if (core >= 0)
+ if (core >= 0) {
+ if (core > sdev->num_cores - 1) {
+ dev_info(scomp->dev,
+ "out of range core id for %s, moving it %d -> %d\n",
+ swidget->widget->name, core, SOF_DSP_PRIMARY_CORE);
+ core = SOF_DSP_PRIMARY_CORE;
+ }
swidget->core = core;
+ }
}
/* bind widget to external event */
@@ -2534,6 +2551,8 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
if (strstr(file, "dummy")) {
dev_err(scomp->dev,
"Function topology is required, please upgrade sof-firmware\n");
+
+ kfree(tplg_files);
return -EINVAL;
}
tplg_files[0] = file;
@@ -2575,6 +2594,54 @@ int snd_sof_load_topology(struct snd_soc_component *scomp, const char *file)
}
}
+ /* Loading user defined topologies */
+ for (i = 0; i < feature_tplg_cnt; i++) {
+ const char *feature_topology = devm_kasprintf(scomp->dev, GFP_KERNEL, "%s/%s",
+ tplg_filename_prefix,
+ feature_topologies[i]);
+
+ if (!feature_topology) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ dev_info(scomp->dev, "loading feature topology %d: %s\n", i, feature_topology);
+ ret = request_firmware(&fw, feature_topology, scomp->dev);
+ if (ret < 0) {
+ /*
+ * snd_soc_tplg_component_remove(scomp) will be called
+ * if snd_soc_tplg_component_load(scomp) failed and all
+ * objects in the scomp will be removed. No need to call
+ * snd_soc_tplg_component_remove(scomp) here.
+ */
+ dev_warn(scomp->dev, "feature tplg request firmware %s failed err: %d\n",
+ feature_topologies[i], ret);
+ /*
+ * We don't return error here because we can still have the basic
+ * audio feature when the function topology load complete. No need
+ * to convert the error code because we will get new 'ret' out of the
+ * loop.
+ */
+ continue;
+ }
+
+ if (sdev->dspless_mode_selected)
+ ret = snd_soc_tplg_component_load(scomp, &sof_dspless_tplg_ops, fw);
+ else
+ ret = snd_soc_tplg_component_load(scomp, &sof_tplg_ops, fw);
+
+ release_firmware(fw);
+
+ if (ret < 0) {
+ dev_err(scomp->dev, "feature tplg %s component load failed %d\n",
+ feature_topologies[i], ret);
+ /*
+ * We need to return error here because it may lead to kernel NULL pointer
+ * dereference if we continue the remaining tasks.
+ */
+ goto out;
+ }
+ }
+
/* call sof_complete when topologies are loaded successfully */
ret = sof_complete(scomp);
diff --git a/sound/soc/spacemit/k1_i2s.c b/sound/soc/spacemit/k1_i2s.c
index 5420ca2aefbd..8871fc15b29c 100644
--- a/sound/soc/spacemit/k1_i2s.c
+++ b/sound/soc/spacemit/k1_i2s.c
@@ -53,6 +53,9 @@ struct spacemit_i2s_dev {
struct clk *sysclk;
struct clk *bclk;
struct clk *sspa_clk;
+ struct clk *sysclk_div;
+ struct clk *c_sysclk;
+ struct clk *c_bclk;
struct snd_dmaengine_dai_dma_data capture_dma_data;
struct snd_dmaengine_dai_dma_data playback_dma_data;
@@ -206,6 +209,14 @@ static int spacemit_i2s_hw_params(struct snd_pcm_substream *substream,
params_rate(params) *
data_bits;
+ ret = clk_set_rate(i2s->c_sysclk, bclk_rate * 2);
+ if (ret)
+ return ret;
+
+ ret = clk_set_rate(i2s->c_bclk, bclk_rate);
+ if (ret)
+ return ret;
+
ret = clk_set_rate(i2s->bclk, bclk_rate);
if (ret)
return ret;
@@ -217,10 +228,17 @@ static int spacemit_i2s_set_sysclk(struct snd_soc_dai *cpu_dai, int clk_id,
unsigned int freq, int dir)
{
struct spacemit_i2s_dev *i2s = dev_get_drvdata(cpu_dai->dev);
+ int ret;
if (freq == 0)
return 0;
+ if (i2s->sysclk_div) {
+ ret = clk_set_rate(i2s->sysclk_div, freq);
+ if (ret)
+ return ret;
+ }
+
return clk_set_rate(i2s->sysclk, freq);
}
@@ -436,6 +454,21 @@ static int spacemit_i2s_probe(struct platform_device *pdev)
return dev_err_probe(i2s->dev, PTR_ERR(i2s->sspa_clk),
"failed to enable sspa clock\n");
+ i2s->sysclk_div = devm_clk_get_optional_enabled(i2s->dev, "sysclk_div");
+ if (IS_ERR(i2s->sysclk_div))
+ return dev_err_probe(i2s->dev, PTR_ERR(i2s->sysclk_div),
+ "failed to enable sysclk_div clock\n");
+
+ i2s->c_sysclk = devm_clk_get_optional_enabled(i2s->dev, "c_sysclk");
+ if (IS_ERR(i2s->c_sysclk))
+ return dev_err_probe(i2s->dev, PTR_ERR(i2s->c_sysclk),
+ "failed to enable c_sysclk clock\n");
+
+ i2s->c_bclk = devm_clk_get_optional_enabled(i2s->dev, "c_bclk");
+ if (IS_ERR(i2s->c_bclk))
+ return dev_err_probe(i2s->dev, PTR_ERR(i2s->c_bclk),
+ "failed to enable c_bclk clock\n");
+
i2s->base = devm_platform_get_and_ioremap_resource(pdev, 0, &res);
if (IS_ERR(i2s->base))
return dev_err_probe(i2s->dev, PTR_ERR(i2s->base), "failed to map registers\n");
@@ -462,6 +495,7 @@ static int spacemit_i2s_probe(struct platform_device *pdev)
static const struct of_device_id spacemit_i2s_of_match[] = {
{ .compatible = "spacemit,k1-i2s", },
+ { .compatible = "spacemit,k3-i2s", },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, spacemit_i2s_of_match);
@@ -476,4 +510,4 @@ static struct platform_driver spacemit_i2s_driver = {
module_platform_driver(spacemit_i2s_driver);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("I2S bus driver for SpacemiT K1 SoC");
+MODULE_DESCRIPTION("I2S bus driver for SpacemiT K1/K3 SoC");
diff --git a/sound/soc/sprd/sprd-mcdt.c b/sound/soc/sprd/sprd-mcdt.c
index 814a1cde1d35..5f3a2a7bce31 100644
--- a/sound/soc/sprd/sprd-mcdt.c
+++ b/sound/soc/sprd/sprd-mcdt.c
@@ -524,7 +524,7 @@ static irqreturn_t sprd_mcdt_irq_handler(int irq, void *dev_id)
struct sprd_mcdt_dev *mcdt = (struct sprd_mcdt_dev *)dev_id;
int i;
- spin_lock(&mcdt->lock);
+ guard(spinlock)(&mcdt->lock);
for (i = 0; i < MCDT_ADC_CHANNEL_NUM; i++) {
if (sprd_mcdt_chan_int_sts(mcdt, i, MCDT_ADC_FIFO_AF_INT)) {
@@ -547,8 +547,6 @@ static irqreturn_t sprd_mcdt_irq_handler(int irq, void *dev_id)
}
}
- spin_unlock(&mcdt->lock);
-
return IRQ_HANDLED;
}
@@ -569,22 +567,19 @@ static irqreturn_t sprd_mcdt_irq_handler(int irq, void *dev_id)
int sprd_mcdt_chan_write(struct sprd_mcdt_chan *chan, char *tx_buf, u32 size)
{
struct sprd_mcdt_dev *mcdt = chan->mcdt;
- unsigned long flags;
int avail, i = 0, words = size / 4;
u32 *buf = (u32 *)tx_buf;
- spin_lock_irqsave(&mcdt->lock, flags);
+ guard(spinlock_irqsave)(&mcdt->lock);
if (chan->dma_enable) {
dev_err(mcdt->dev,
"Can not write data when DMA mode enabled\n");
- spin_unlock_irqrestore(&mcdt->lock, flags);
return -EINVAL;
}
if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_DAC_FIFO_REAL_FULL)) {
dev_err(mcdt->dev, "Channel fifo is full now\n");
- spin_unlock_irqrestore(&mcdt->lock, flags);
return -EBUSY;
}
@@ -592,14 +587,12 @@ int sprd_mcdt_chan_write(struct sprd_mcdt_chan *chan, char *tx_buf, u32 size)
if (size > avail) {
dev_err(mcdt->dev,
"Data size is larger than the available fifo size\n");
- spin_unlock_irqrestore(&mcdt->lock, flags);
return -EBUSY;
}
while (i++ < words)
sprd_mcdt_dac_write_fifo(mcdt, chan->id, *buf++);
- spin_unlock_irqrestore(&mcdt->lock, flags);
return 0;
}
EXPORT_SYMBOL_GPL(sprd_mcdt_chan_write);
@@ -620,21 +613,18 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_write);
int sprd_mcdt_chan_read(struct sprd_mcdt_chan *chan, char *rx_buf, u32 size)
{
struct sprd_mcdt_dev *mcdt = chan->mcdt;
- unsigned long flags;
int i = 0, avail, words = size / 4;
u32 *buf = (u32 *)rx_buf;
- spin_lock_irqsave(&mcdt->lock, flags);
+ guard(spinlock_irqsave)(&mcdt->lock);
if (chan->dma_enable) {
dev_err(mcdt->dev, "Can not read data when DMA mode enabled\n");
- spin_unlock_irqrestore(&mcdt->lock, flags);
return -EINVAL;
}
if (sprd_mcdt_chan_fifo_sts(mcdt, chan->id, MCDT_ADC_FIFO_REAL_EMPTY)) {
dev_err(mcdt->dev, "Channel fifo is empty\n");
- spin_unlock_irqrestore(&mcdt->lock, flags);
return -EBUSY;
}
@@ -645,7 +635,6 @@ int sprd_mcdt_chan_read(struct sprd_mcdt_chan *chan, char *rx_buf, u32 size)
while (i++ < words)
sprd_mcdt_adc_read_fifo(mcdt, chan->id, buf++);
- spin_unlock_irqrestore(&mcdt->lock, flags);
return words * 4;
}
EXPORT_SYMBOL_GPL(sprd_mcdt_chan_read);
@@ -672,14 +661,12 @@ int sprd_mcdt_chan_int_enable(struct sprd_mcdt_chan *chan, u32 water_mark,
struct sprd_mcdt_chan_callback *cb)
{
struct sprd_mcdt_dev *mcdt = chan->mcdt;
- unsigned long flags;
int ret = 0;
- spin_lock_irqsave(&mcdt->lock, flags);
+ guard(spinlock_irqsave)(&mcdt->lock);
if (chan->dma_enable || chan->int_enable) {
dev_err(mcdt->dev, "Failed to set interrupt mode.\n");
- spin_unlock_irqrestore(&mcdt->lock, flags);
return -EINVAL;
}
@@ -712,8 +699,6 @@ int sprd_mcdt_chan_int_enable(struct sprd_mcdt_chan *chan, u32 water_mark,
chan->int_enable = true;
}
- spin_unlock_irqrestore(&mcdt->lock, flags);
-
return ret;
}
EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_enable);
@@ -725,14 +710,12 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_enable);
void sprd_mcdt_chan_int_disable(struct sprd_mcdt_chan *chan)
{
struct sprd_mcdt_dev *mcdt = chan->mcdt;
- unsigned long flags;
- spin_lock_irqsave(&mcdt->lock, flags);
+ guard(spinlock_irqsave)(&mcdt->lock);
- if (!chan->int_enable) {
- spin_unlock_irqrestore(&mcdt->lock, flags);
+ if (!chan->int_enable)
return;
- }
+
switch (chan->type) {
case SPRD_MCDT_ADC_CHAN:
@@ -754,7 +737,6 @@ void sprd_mcdt_chan_int_disable(struct sprd_mcdt_chan *chan)
}
chan->int_enable = false;
- spin_unlock_irqrestore(&mcdt->lock, flags);
}
EXPORT_SYMBOL_GPL(sprd_mcdt_chan_int_disable);
@@ -775,15 +757,13 @@ int sprd_mcdt_chan_dma_enable(struct sprd_mcdt_chan *chan,
u32 water_mark)
{
struct sprd_mcdt_dev *mcdt = chan->mcdt;
- unsigned long flags;
int ret = 0;
- spin_lock_irqsave(&mcdt->lock, flags);
+ guard(spinlock_irqsave)(&mcdt->lock);
if (chan->dma_enable || chan->int_enable ||
dma_chan > SPRD_MCDT_DMA_CH4) {
dev_err(mcdt->dev, "Failed to set DMA mode\n");
- spin_unlock_irqrestore(&mcdt->lock, flags);
return -EINVAL;
}
@@ -814,8 +794,6 @@ int sprd_mcdt_chan_dma_enable(struct sprd_mcdt_chan *chan,
if (!ret)
chan->dma_enable = true;
- spin_unlock_irqrestore(&mcdt->lock, flags);
-
return ret;
}
EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_enable);
@@ -827,14 +805,11 @@ EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_enable);
void sprd_mcdt_chan_dma_disable(struct sprd_mcdt_chan *chan)
{
struct sprd_mcdt_dev *mcdt = chan->mcdt;
- unsigned long flags;
- spin_lock_irqsave(&mcdt->lock, flags);
+ guard(spinlock_irqsave)(&mcdt->lock);
- if (!chan->dma_enable) {
- spin_unlock_irqrestore(&mcdt->lock, flags);
+ if (!chan->dma_enable)
return;
- }
switch (chan->type) {
case SPRD_MCDT_ADC_CHAN:
@@ -852,7 +827,6 @@ void sprd_mcdt_chan_dma_disable(struct sprd_mcdt_chan *chan)
}
chan->dma_enable = false;
- spin_unlock_irqrestore(&mcdt->lock, flags);
}
EXPORT_SYMBOL_GPL(sprd_mcdt_chan_dma_disable);
@@ -868,7 +842,7 @@ struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel,
{
struct sprd_mcdt_chan *temp;
- mutex_lock(&sprd_mcdt_list_mutex);
+ guard(mutex)(&sprd_mcdt_list_mutex);
list_for_each_entry(temp, &sprd_mcdt_chan_list, list) {
if (temp->type == type && temp->id == channel) {
@@ -880,8 +854,6 @@ struct sprd_mcdt_chan *sprd_mcdt_request_chan(u8 channel,
if (list_entry_is_head(temp, &sprd_mcdt_chan_list, list))
temp = NULL;
- mutex_unlock(&sprd_mcdt_list_mutex);
-
return temp;
}
EXPORT_SYMBOL_GPL(sprd_mcdt_request_chan);
@@ -897,17 +869,14 @@ void sprd_mcdt_free_chan(struct sprd_mcdt_chan *chan)
sprd_mcdt_chan_dma_disable(chan);
sprd_mcdt_chan_int_disable(chan);
- mutex_lock(&sprd_mcdt_list_mutex);
+ guard(mutex)(&sprd_mcdt_list_mutex);
list_for_each_entry(temp, &sprd_mcdt_chan_list, list) {
- if (temp == chan) {
- mutex_unlock(&sprd_mcdt_list_mutex);
+ if (temp == chan)
return;
- }
}
list_add_tail(&chan->list, &sprd_mcdt_chan_list);
- mutex_unlock(&sprd_mcdt_list_mutex);
}
EXPORT_SYMBOL_GPL(sprd_mcdt_free_chan);
@@ -933,9 +902,8 @@ static void sprd_mcdt_init_chans(struct sprd_mcdt_dev *mcdt,
chan->mcdt = mcdt;
INIT_LIST_HEAD(&chan->list);
- mutex_lock(&sprd_mcdt_list_mutex);
- list_add_tail(&chan->list, &sprd_mcdt_chan_list);
- mutex_unlock(&sprd_mcdt_list_mutex);
+ scoped_guard(mutex, &sprd_mcdt_list_mutex)
+ list_add_tail(&chan->list, &sprd_mcdt_chan_list);
}
}
@@ -977,12 +945,10 @@ static void sprd_mcdt_remove(struct platform_device *pdev)
{
struct sprd_mcdt_chan *chan, *temp;
- mutex_lock(&sprd_mcdt_list_mutex);
+ guard(mutex)(&sprd_mcdt_list_mutex);
list_for_each_entry_safe(chan, temp, &sprd_mcdt_chan_list, list)
list_del(&chan->list);
-
- mutex_unlock(&sprd_mcdt_list_mutex);
}
static const struct of_device_id sprd_mcdt_of_match[] = {
diff --git a/sound/soc/sti/uniperif_player.c b/sound/soc/sti/uniperif_player.c
index 45d35b887e4e..e4b9799ad9b2 100644
--- a/sound/soc/sti/uniperif_player.c
+++ b/sound/soc/sti/uniperif_player.c
@@ -65,13 +65,15 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
unsigned int status;
unsigned int tmp;
- spin_lock(&player->irq_lock);
+ guard(spinlock)(&player->irq_lock);
if (!player->substream)
- goto irq_spin_unlock;
+ return ret;
snd_pcm_stream_lock(player->substream);
- if (player->state == UNIPERIF_STATE_STOPPED)
- goto stream_unlock;
+ if (player->state == UNIPERIF_STATE_STOPPED) {
+ snd_pcm_stream_unlock(player->substream);
+ return ret;
+ }
/* Get interrupt status & clear them immediately */
status = GET_UNIPERIF_ITS(player);
@@ -116,7 +118,8 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
dev_err(player->dev,
"unexpected Underflow recovering\n");
ret = -EPERM;
- goto stream_unlock;
+ snd_pcm_stream_unlock(player->substream);
+ return ret;
}
/* Read the underflow recovery duration */
tmp = GET_UNIPERIF_STATUS_1_UNDERFLOW_DURATION(player);
@@ -143,10 +146,7 @@ static irqreturn_t uni_player_irq_handler(int irq, void *dev_id)
ret = IRQ_HANDLED;
}
-stream_unlock:
snd_pcm_stream_unlock(player->substream);
-irq_spin_unlock:
- spin_unlock(&player->irq_lock);
return ret;
}
@@ -363,10 +363,10 @@ static int uni_player_prepare_iec958(struct uniperif *player,
SET_UNIPERIF_CTRL_ZERO_STUFF_HW(player);
- mutex_lock(&player->ctrl_lock);
/* Update the channel status */
- uni_player_set_channel_status(player, runtime);
- mutex_unlock(&player->ctrl_lock);
+ scoped_guard(mutex, &player->ctrl_lock)
+ uni_player_set_channel_status(player, runtime);
+
/* Clear the user validity user bits */
SET_UNIPERIF_USER_VALIDITY_VALIDITY_LR(player, 0);
@@ -546,11 +546,11 @@ static int uni_player_prepare_tdm(struct uniperif *player,
/* set unip clk rate (not done vai set_sysclk ops) */
freq = runtime->rate * tdm_frame_size * 8;
- mutex_lock(&player->ctrl_lock);
- ret = uni_player_clk_set_rate(player, freq);
- if (!ret)
- player->mclk = freq;
- mutex_unlock(&player->ctrl_lock);
+ scoped_guard(mutex, &player->ctrl_lock) {
+ ret = uni_player_clk_set_rate(player, freq);
+ if (!ret)
+ player->mclk = freq;
+ }
return 0;
}
@@ -575,12 +575,11 @@ static int uni_player_ctl_iec958_get(struct snd_kcontrol *kcontrol,
struct uniperif *player = priv->dai_data.uni;
struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958;
- mutex_lock(&player->ctrl_lock);
+ guard(mutex)(&player->ctrl_lock);
ucontrol->value.iec958.status[0] = iec958->status[0];
ucontrol->value.iec958.status[1] = iec958->status[1];
ucontrol->value.iec958.status[2] = iec958->status[2];
ucontrol->value.iec958.status[3] = iec958->status[3];
- mutex_unlock(&player->ctrl_lock);
return 0;
}
@@ -591,23 +590,20 @@ static int uni_player_ctl_iec958_put(struct snd_kcontrol *kcontrol,
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
struct uniperif *player = priv->dai_data.uni;
struct snd_aes_iec958 *iec958 = &player->stream_settings.iec958;
- unsigned long flags;
- mutex_lock(&player->ctrl_lock);
+ guard(mutex)(&player->ctrl_lock);
iec958->status[0] = ucontrol->value.iec958.status[0];
iec958->status[1] = ucontrol->value.iec958.status[1];
iec958->status[2] = ucontrol->value.iec958.status[2];
iec958->status[3] = ucontrol->value.iec958.status[3];
- spin_lock_irqsave(&player->irq_lock, flags);
- if (player->substream && player->substream->runtime)
- uni_player_set_channel_status(player,
- player->substream->runtime);
- else
- uni_player_set_channel_status(player, NULL);
-
- spin_unlock_irqrestore(&player->irq_lock, flags);
- mutex_unlock(&player->ctrl_lock);
+ scoped_guard(spinlock_irqsave, &player->irq_lock) {
+ if (player->substream && player->substream->runtime)
+ uni_player_set_channel_status(player,
+ player->substream->runtime);
+ else
+ uni_player_set_channel_status(player, NULL);
+ }
return 0;
}
@@ -642,9 +638,8 @@ static int snd_sti_clk_adjustment_get(struct snd_kcontrol *kcontrol,
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
struct uniperif *player = priv->dai_data.uni;
- mutex_lock(&player->ctrl_lock);
+ guard(mutex)(&player->ctrl_lock);
ucontrol->value.integer.value[0] = player->clk_adj;
- mutex_unlock(&player->ctrl_lock);
return 0;
}
@@ -661,12 +656,11 @@ static int snd_sti_clk_adjustment_put(struct snd_kcontrol *kcontrol,
(ucontrol->value.integer.value[0] > UNIPERIF_PLAYER_CLK_ADJ_MAX))
return -EINVAL;
- mutex_lock(&player->ctrl_lock);
+ guard(mutex)(&player->ctrl_lock);
player->clk_adj = ucontrol->value.integer.value[0];
if (player->mclk)
ret = uni_player_clk_set_rate(player, player->mclk);
- mutex_unlock(&player->ctrl_lock);
return ret;
}
@@ -693,12 +687,10 @@ static int uni_player_startup(struct snd_pcm_substream *substream,
{
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
struct uniperif *player = priv->dai_data.uni;
- unsigned long flags;
int ret;
- spin_lock_irqsave(&player->irq_lock, flags);
- player->substream = substream;
- spin_unlock_irqrestore(&player->irq_lock, flags);
+ scoped_guard(spinlock_irqsave, &player->irq_lock)
+ player->substream = substream;
player->clk_adj = 0;
@@ -734,11 +726,10 @@ static int uni_player_set_sysclk(struct snd_soc_dai *dai, int clk_id,
if (clk_id != 0)
return -EINVAL;
- mutex_lock(&player->ctrl_lock);
+ guard(mutex)(&player->ctrl_lock);
ret = uni_player_clk_set_rate(player, freq);
if (!ret)
player->mclk = freq;
- mutex_unlock(&player->ctrl_lock);
return ret;
}
@@ -996,15 +987,13 @@ static void uni_player_shutdown(struct snd_pcm_substream *substream,
{
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
struct uniperif *player = priv->dai_data.uni;
- unsigned long flags;
- spin_lock_irqsave(&player->irq_lock, flags);
+ guard(spinlock_irqsave)(&player->irq_lock);
if (player->state != UNIPERIF_STATE_STOPPED)
/* Stop the player */
uni_player_stop(player);
player->substream = NULL;
- spin_unlock_irqrestore(&player->irq_lock, flags);
}
static int uni_player_parse_dt_audio_glue(struct platform_device *pdev,
diff --git a/sound/soc/sti/uniperif_reader.c b/sound/soc/sti/uniperif_reader.c
index 05ea2b794eb9..45d7613f595c 100644
--- a/sound/soc/sti/uniperif_reader.c
+++ b/sound/soc/sti/uniperif_reader.c
@@ -46,15 +46,16 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
struct uniperif *reader = dev_id;
unsigned int status;
- spin_lock(&reader->irq_lock);
+ guard(spinlock)(&reader->irq_lock);
if (!reader->substream)
- goto irq_spin_unlock;
+ return ret;
snd_pcm_stream_lock(reader->substream);
if (reader->state == UNIPERIF_STATE_STOPPED) {
/* Unexpected IRQ: do nothing */
dev_warn(reader->dev, "unexpected IRQ\n");
- goto stream_unlock;
+ snd_pcm_stream_unlock(reader->substream);
+ return ret;
}
/* Get interrupt status & clear them immediately */
@@ -70,10 +71,7 @@ static irqreturn_t uni_reader_irq_handler(int irq, void *dev_id)
ret = IRQ_HANDLED;
}
-stream_unlock:
snd_pcm_stream_unlock(reader->substream);
-irq_spin_unlock:
- spin_unlock(&reader->irq_lock);
return ret;
}
@@ -355,12 +353,10 @@ static int uni_reader_startup(struct snd_pcm_substream *substream,
{
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
struct uniperif *reader = priv->dai_data.uni;
- unsigned long flags;
int ret;
- spin_lock_irqsave(&reader->irq_lock, flags);
- reader->substream = substream;
- spin_unlock_irqrestore(&reader->irq_lock, flags);
+ scoped_guard(spinlock_irqsave, &reader->irq_lock)
+ reader->substream = substream;
if (!UNIPERIF_TYPE_IS_TDM(reader))
return 0;
@@ -386,15 +382,13 @@ static void uni_reader_shutdown(struct snd_pcm_substream *substream,
{
struct sti_uniperiph_data *priv = snd_soc_dai_get_drvdata(dai);
struct uniperif *reader = priv->dai_data.uni;
- unsigned long flags;
- spin_lock_irqsave(&reader->irq_lock, flags);
+ guard(spinlock_irqsave)(&reader->irq_lock);
if (reader->state != UNIPERIF_STATE_STOPPED) {
/* Stop the reader */
uni_reader_stop(reader);
}
reader->substream = NULL;
- spin_unlock_irqrestore(&reader->irq_lock, flags);
}
static const struct snd_soc_dai_ops uni_reader_dai_ops = {
diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c
index 0f6d32814c22..66efb9a0acb9 100644
--- a/sound/soc/stm/stm32_adfsdm.c
+++ b/sound/soc/stm/stm32_adfsdm.c
@@ -62,12 +62,11 @@ static void stm32_adfsdm_shutdown(struct snd_pcm_substream *substream,
{
struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
- mutex_lock(&priv->lock);
+ guard(mutex)(&priv->lock);
if (priv->iio_active) {
iio_channel_stop_all_cb(priv->iio_cb);
priv->iio_active = false;
}
- mutex_unlock(&priv->lock);
}
static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
@@ -76,7 +75,7 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
struct stm32_adfsdm_priv *priv = snd_soc_dai_get_drvdata(dai);
int ret;
- mutex_lock(&priv->lock);
+ guard(mutex)(&priv->lock);
if (priv->iio_active) {
iio_channel_stop_all_cb(priv->iio_cb);
priv->iio_active = false;
@@ -88,7 +87,7 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
if (ret < 0) {
dev_err(dai->dev, "%s: Failed to set %d sampling rate\n",
__func__, substream->runtime->rate);
- goto out;
+ return ret;
}
if (!priv->iio_active) {
@@ -100,9 +99,6 @@ static int stm32_adfsdm_dai_prepare(struct snd_pcm_substream *substream,
__func__, ret);
}
-out:
- mutex_unlock(&priv->lock);
-
return ret;
}
@@ -316,6 +312,7 @@ static const struct snd_soc_component_driver stm32_adfsdm_soc_platform = {
.trigger = stm32_adfsdm_trigger,
.pointer = stm32_adfsdm_pcm_pointer,
.pcm_new = stm32_adfsdm_pcm_new,
+ .debugfs_prefix = "pcm",
};
static const struct of_device_id stm32_adfsdm_of_match[] = {
@@ -327,7 +324,6 @@ MODULE_DEVICE_TABLE(of, stm32_adfsdm_of_match);
static int stm32_adfsdm_probe(struct platform_device *pdev)
{
struct stm32_adfsdm_priv *priv;
- struct snd_soc_component *component;
int ret;
priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
@@ -361,20 +357,9 @@ static int stm32_adfsdm_probe(struct platform_device *pdev)
return ret;
}
- component = devm_kzalloc(&pdev->dev, sizeof(*component), GFP_KERNEL);
- if (!component)
- return -ENOMEM;
-
- ret = snd_soc_component_initialize(component,
- &stm32_adfsdm_soc_platform,
- &pdev->dev);
- if (ret < 0)
- return ret;
-#ifdef CONFIG_DEBUG_FS
- component->debugfs_prefix = "pcm";
-#endif
-
- ret = snd_soc_add_component(component, NULL, 0);
+ ret = devm_snd_soc_register_component(&pdev->dev,
+ &stm32_adfsdm_soc_platform,
+ NULL, 0);
if (ret < 0) {
dev_err(&pdev->dev, "%s: Failed to register PCM platform\n",
__func__);
diff --git a/sound/soc/stm/stm32_i2s.c b/sound/soc/stm/stm32_i2s.c
index 6ca21780f21d..ae9e25657f3f 100644
--- a/sound/soc/stm/stm32_i2s.c
+++ b/sound/soc/stm/stm32_i2s.c
@@ -615,10 +615,10 @@ static irqreturn_t stm32_i2s_isr(int irq, void *devid)
if (flags & I2S_SR_TIFRE)
dev_dbg(&pdev->dev, "Frame error\n");
- spin_lock(&i2s->irq_lock);
- if (err && i2s->substream)
- snd_pcm_stop_xrun(i2s->substream);
- spin_unlock(&i2s->irq_lock);
+ scoped_guard(spinlock, &i2s->irq_lock) {
+ if (err && i2s->substream)
+ snd_pcm_stop_xrun(i2s->substream);
+ }
return IRQ_HANDLED;
}
@@ -905,12 +905,10 @@ static int stm32_i2s_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long flags;
int ret;
- spin_lock_irqsave(&i2s->irq_lock, flags);
- i2s->substream = substream;
- spin_unlock_irqrestore(&i2s->irq_lock, flags);
+ scoped_guard(spinlock_irqsave, &i2s->irq_lock)
+ i2s->substream = substream;
if ((i2s->fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_DSP_A)
snd_pcm_hw_constraint_single(substream->runtime,
@@ -982,19 +980,19 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
regmap_write_bits(i2s->regmap, STM32_I2S_IFCR_REG,
I2S_IFCR_MASK, I2S_IFCR_MASK);
- spin_lock(&i2s->lock_fd);
- i2s->refcount++;
- if (playback_flg) {
- ier = I2S_IER_UDRIE;
- } else {
- ier = I2S_IER_OVRIE;
-
- if (STM32_I2S_IS_MASTER(i2s) && i2s->refcount == 1)
- /* dummy write to gate bus clocks */
- regmap_write(i2s->regmap,
- STM32_I2S_TXDR_REG, 0);
+ scoped_guard(spinlock, &i2s->lock_fd) {
+ i2s->refcount++;
+ if (playback_flg) {
+ ier = I2S_IER_UDRIE;
+ } else {
+ ier = I2S_IER_OVRIE;
+
+ if (STM32_I2S_IS_MASTER(i2s) && i2s->refcount == 1)
+ /* dummy write to gate bus clocks */
+ regmap_write(i2s->regmap,
+ STM32_I2S_TXDR_REG, 0);
+ }
}
- spin_unlock(&i2s->lock_fd);
if (STM32_I2S_IS_SLAVE(i2s))
ier |= I2S_IER_TIFREIE;
@@ -1016,21 +1014,18 @@ static int stm32_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
I2S_IER_OVRIE,
(unsigned int)~I2S_IER_OVRIE);
- spin_lock(&i2s->lock_fd);
- i2s->refcount--;
- if (i2s->refcount) {
- spin_unlock(&i2s->lock_fd);
- break;
- }
+ scoped_guard(spinlock, &i2s->lock_fd) {
+ i2s->refcount--;
+ if (i2s->refcount)
+ return 0;
- ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG,
- I2S_CR1_SPE, 0);
- if (ret < 0) {
- dev_err(cpu_dai->dev, "Error %d disabling I2S\n", ret);
- spin_unlock(&i2s->lock_fd);
- return ret;
+ ret = regmap_update_bits(i2s->regmap, STM32_I2S_CR1_REG,
+ I2S_CR1_SPE, 0);
+ if (ret < 0) {
+ dev_err(cpu_dai->dev, "Error %d disabling I2S\n", ret);
+ return ret;
+ }
}
- spin_unlock(&i2s->lock_fd);
cfg1_mask = I2S_CFG1_RXDMAEN | I2S_CFG1_TXDMAEN;
regmap_update_bits(i2s->regmap, STM32_I2S_CFG1_REG,
@@ -1047,7 +1042,6 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct stm32_i2s_data *i2s = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long flags;
clk_disable_unprepare(i2s->i2sclk);
@@ -1059,9 +1053,8 @@ static void stm32_i2s_shutdown(struct snd_pcm_substream *substream,
if (!i2s->i2smclk && i2s->put_i2s_clk_rate)
i2s->put_i2s_clk_rate(i2s);
- spin_lock_irqsave(&i2s->irq_lock, flags);
- i2s->substream = NULL;
- spin_unlock_irqrestore(&i2s->irq_lock, flags);
+ scoped_guard(spinlock_irqsave, &i2s->irq_lock)
+ i2s->substream = NULL;
}
static int stm32_i2s_dai_probe(struct snd_soc_dai *cpu_dai)
diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c
index 3e82fa90e719..ea9e8bddd63f 100644
--- a/sound/soc/stm/stm32_sai_sub.c
+++ b/sound/soc/stm/stm32_sai_sub.c
@@ -280,9 +280,8 @@ static int snd_pcm_iec958_get(struct snd_kcontrol *kcontrol,
{
struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol);
- mutex_lock(&sai->ctrl_lock);
+ guard(mutex)(&sai->ctrl_lock);
memcpy(uctl->value.iec958.status, sai->iec958.status, 4);
- mutex_unlock(&sai->ctrl_lock);
return 0;
}
@@ -292,9 +291,8 @@ static int snd_pcm_iec958_put(struct snd_kcontrol *kcontrol,
{
struct stm32_sai_sub_data *sai = snd_kcontrol_chip(kcontrol);
- mutex_lock(&sai->ctrl_lock);
+ guard(mutex)(&sai->ctrl_lock);
memcpy(sai->iec958.status, uctl->value.iec958.status, 4);
- mutex_unlock(&sai->ctrl_lock);
return 0;
}
@@ -658,10 +656,10 @@ static irqreturn_t stm32_sai_isr(int irq, void *devid)
status = SNDRV_PCM_STATE_XRUN;
}
- spin_lock(&sai->irq_lock);
- if (status != SNDRV_PCM_STATE_RUNNING && sai->substream)
- snd_pcm_stop_xrun(sai->substream);
- spin_unlock(&sai->irq_lock);
+ scoped_guard(spinlock, &sai->irq_lock) {
+ if (status != SNDRV_PCM_STATE_RUNNING && sai->substream)
+ snd_pcm_stop_xrun(sai->substream);
+ }
return IRQ_HANDLED;
}
@@ -894,11 +892,9 @@ static int stm32_sai_startup(struct snd_pcm_substream *substream,
{
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
int imr, cr2, ret;
- unsigned long flags;
- spin_lock_irqsave(&sai->irq_lock, flags);
- sai->substream = substream;
- spin_unlock_irqrestore(&sai->irq_lock, flags);
+ scoped_guard(spinlock_irqsave, &sai->irq_lock)
+ sai->substream = substream;
if (STM_SAI_PROTOCOL_IS_SPDIF(sai)) {
snd_pcm_hw_constraint_mask64(substream->runtime,
@@ -1083,7 +1079,7 @@ static void stm32_sai_set_iec958_status(struct stm32_sai_sub_data *sai,
return;
/* Force the sample rate according to runtime rate */
- mutex_lock(&sai->ctrl_lock);
+ guard(mutex)(&sai->ctrl_lock);
switch (runtime->rate) {
case 22050:
sai->iec958.status[3] = IEC958_AES3_CON_FS_22050;
@@ -1116,7 +1112,6 @@ static void stm32_sai_set_iec958_status(struct stm32_sai_sub_data *sai,
sai->iec958.status[3] = IEC958_AES3_CON_FS_NOTID;
break;
}
- mutex_unlock(&sai->ctrl_lock);
}
static int stm32_sai_configure_clock(struct snd_soc_dai *cpu_dai,
@@ -1284,7 +1279,6 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct stm32_sai_sub_data *sai = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long flags;
stm32_sai_sub_reg_up(sai, STM_SAI_IMR_REGX, SAI_XIMR_MASK, 0);
@@ -1298,9 +1292,8 @@ static void stm32_sai_shutdown(struct snd_pcm_substream *substream,
if (!sai->sai_mclk && sai->put_sai_ck_rate)
sai->put_sai_ck_rate(sai);
- spin_lock_irqsave(&sai->irq_lock, flags);
- sai->substream = NULL;
- spin_unlock_irqrestore(&sai->irq_lock, flags);
+ scoped_guard(spinlock_irqsave, &sai->irq_lock)
+ sai->substream = NULL;
}
static int stm32_sai_pcm_new(struct snd_soc_pcm_runtime *rtd,
diff --git a/sound/soc/stm/stm32_spdifrx.c b/sound/soc/stm/stm32_spdifrx.c
index 57b711c44278..2f83ca989e68 100644
--- a/sound/soc/stm/stm32_spdifrx.c
+++ b/sound/soc/stm/stm32_spdifrx.c
@@ -322,7 +322,6 @@ static void stm32_spdifrx_dma_ctrl_stop(struct stm32_spdifrx_data *spdifrx)
static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
{
int cr, cr_mask, imr, ret;
- unsigned long flags;
/* Enable IRQs */
imr = SPDIFRX_IMR_IFEIE | SPDIFRX_IMR_SYNCDIE | SPDIFRX_IMR_PERRIE;
@@ -330,7 +329,7 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
if (ret)
return ret;
- spin_lock_irqsave(&spdifrx->lock, flags);
+ guard(spinlock_irqsave)(&spdifrx->lock);
spdifrx->refcount++;
@@ -365,22 +364,17 @@ static int stm32_spdifrx_start_sync(struct stm32_spdifrx_data *spdifrx)
"Failed to start synchronization\n");
}
- spin_unlock_irqrestore(&spdifrx->lock, flags);
-
return ret;
}
static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx)
{
int cr, cr_mask, reg;
- unsigned long flags;
- spin_lock_irqsave(&spdifrx->lock, flags);
+ guard(spinlock_irqsave)(&spdifrx->lock);
- if (--spdifrx->refcount) {
- spin_unlock_irqrestore(&spdifrx->lock, flags);
+ if (--spdifrx->refcount)
return;
- }
cr = SPDIFRX_CR_SPDIFENSET(SPDIFRX_SPDIFEN_DISABLE);
cr_mask = SPDIFRX_CR_SPDIFEN_MASK | SPDIFRX_CR_RXDMAEN;
@@ -396,8 +390,6 @@ static void stm32_spdifrx_stop(struct stm32_spdifrx_data *spdifrx)
/* dummy read to clear CSRNE and RXNE in status register */
regmap_read(spdifrx->regmap, STM32_SPDIFRX_DR, &reg);
regmap_read(spdifrx->regmap, STM32_SPDIFRX_CSR, &reg);
-
- spin_unlock_irqrestore(&spdifrx->lock, flags);
}
static int stm32_spdifrx_dma_ctrl_register(struct device *dev,
@@ -744,19 +736,19 @@ static irqreturn_t stm32_spdifrx_isr(int irq, void *devid)
return IRQ_HANDLED;
}
- spin_lock(&spdifrx->irq_lock);
- if (spdifrx->substream)
- snd_pcm_stop(spdifrx->substream,
- SNDRV_PCM_STATE_DISCONNECTED);
- spin_unlock(&spdifrx->irq_lock);
+ scoped_guard(spinlock, &spdifrx->irq_lock) {
+ if (spdifrx->substream)
+ snd_pcm_stop(spdifrx->substream,
+ SNDRV_PCM_STATE_DISCONNECTED);
+ }
return IRQ_HANDLED;
}
- spin_lock(&spdifrx->irq_lock);
- if (err_xrun && spdifrx->substream)
- snd_pcm_stop_xrun(spdifrx->substream);
- spin_unlock(&spdifrx->irq_lock);
+ scoped_guard(spinlock, &spdifrx->irq_lock) {
+ if (err_xrun && spdifrx->substream)
+ snd_pcm_stop_xrun(spdifrx->substream);
+ }
return IRQ_HANDLED;
}
@@ -765,12 +757,10 @@ static int stm32_spdifrx_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long flags;
int ret;
- spin_lock_irqsave(&spdifrx->irq_lock, flags);
- spdifrx->substream = substream;
- spin_unlock_irqrestore(&spdifrx->irq_lock, flags);
+ scoped_guard(spinlock_irqsave, &spdifrx->irq_lock)
+ spdifrx->substream = substream;
ret = clk_prepare_enable(spdifrx->kclk);
if (ret)
@@ -846,11 +836,9 @@ static void stm32_spdifrx_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct stm32_spdifrx_data *spdifrx = snd_soc_dai_get_drvdata(cpu_dai);
- unsigned long flags;
- spin_lock_irqsave(&spdifrx->irq_lock, flags);
- spdifrx->substream = NULL;
- spin_unlock_irqrestore(&spdifrx->irq_lock, flags);
+ scoped_guard(spinlock_irqsave, &spdifrx->irq_lock)
+ spdifrx->substream = NULL;
clk_disable_unprepare(spdifrx->kclk);
}
diff --git a/sound/soc/sunxi/sun50i-codec-analog.c b/sound/soc/sunxi/sun50i-codec-analog.c
index a19f8aaaf1c4..9f5b067a8ccc 100644
--- a/sound/soc/sunxi/sun50i-codec-analog.c
+++ b/sound/soc/sunxi/sun50i-codec-analog.c
@@ -13,7 +13,6 @@
#include <linux/io.h>
#include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>
diff --git a/sound/soc/sunxi/sun50i-dmic.c b/sound/soc/sunxi/sun50i-dmic.c
index eddfebe16616..5c784b1f6846 100644
--- a/sound/soc/sunxi/sun50i-dmic.c
+++ b/sound/soc/sunxi/sun50i-dmic.c
@@ -6,7 +6,6 @@
#include <linux/clk.h>
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
diff --git a/sound/soc/tegra/tegra186_asrc.c b/sound/soc/tegra/tegra186_asrc.c
index 7135aa23a7fc..7f360dfaf8b1 100644
--- a/sound/soc/tegra/tegra186_asrc.c
+++ b/sound/soc/tegra/tegra186_asrc.c
@@ -7,7 +7,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/io.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
diff --git a/sound/soc/tegra/tegra186_dspk.c b/sound/soc/tegra/tegra186_dspk.c
index 7cf7d6dbfc35..0d3807b231f3 100644
--- a/sound/soc/tegra/tegra186_dspk.c
+++ b/sound/soc/tegra/tegra186_dspk.c
@@ -5,7 +5,6 @@
#include <linux/clk.h>
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c
index 08c58e8f3c22..0df1fc64f532 100644
--- a/sound/soc/tegra/tegra20_ac97.c
+++ b/sound/soc/tegra/tegra20_ac97.c
@@ -441,6 +441,7 @@ static const struct of_device_id tegra20_ac97_of_match[] = {
{ .compatible = "nvidia,tegra20-ac97", },
{},
};
+MODULE_DEVICE_TABLE(of, tegra20_ac97_of_match);
static struct platform_driver tegra20_ac97_driver = {
.driver = {
@@ -456,4 +457,3 @@ MODULE_AUTHOR("Lucas Stach");
MODULE_DESCRIPTION("Tegra20 AC97 ASoC driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, tegra20_ac97_of_match);
diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c
index c620ab0c601f..b48cc4a6967b 100644
--- a/sound/soc/tegra/tegra20_das.c
+++ b/sound/soc/tegra/tegra20_das.c
@@ -188,6 +188,7 @@ static const struct of_device_id tegra20_das_of_match[] = {
{ .compatible = "nvidia,tegra20-das", },
{},
};
+MODULE_DEVICE_TABLE(of, tegra20_das_of_match);
static struct platform_driver tegra20_das_driver = {
.probe = tegra20_das_probe,
@@ -202,4 +203,3 @@ MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra20 DAS driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, tegra20_das_of_match);
diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c
index 51df0835ce3e..d9ab210ad69a 100644
--- a/sound/soc/tegra/tegra20_i2s.c
+++ b/sound/soc/tegra/tegra20_i2s.c
@@ -485,6 +485,7 @@ static const struct of_device_id tegra20_i2s_of_match[] = {
{ .compatible = "nvidia,tegra20-i2s", },
{},
};
+MODULE_DEVICE_TABLE(of, tegra20_i2s_of_match);
static const struct dev_pm_ops tegra20_i2s_pm_ops = {
RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend,
@@ -507,4 +508,3 @@ MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra20 I2S ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, tegra20_i2s_of_match);
diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c
index 38661d9b4a7c..5eefcf149ae3 100644
--- a/sound/soc/tegra/tegra20_spdif.c
+++ b/sound/soc/tegra/tegra20_spdif.c
@@ -10,7 +10,6 @@
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/io.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
diff --git a/sound/soc/tegra/tegra210_admaif.c b/sound/soc/tegra/tegra210_admaif.c
index a1c2757a3932..7299c6bfcf15 100644
--- a/sound/soc/tegra/tegra210_admaif.c
+++ b/sound/soc/tegra/tegra210_admaif.c
@@ -11,6 +11,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/regmap.h>
+#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "tegra_isomgr_bw.h"
@@ -912,35 +913,26 @@ MODULE_DEVICE_TABLE(of, tegra_admaif_of_match);
static int tegra_admaif_probe(struct platform_device *pdev)
{
+ const struct tegra_admaif_soc_data *soc_data;
struct tegra_admaif *admaif;
void __iomem *regs;
struct resource *res;
+ size_t alloc_size;
int err, i;
- admaif = devm_kzalloc(&pdev->dev, sizeof(*admaif), GFP_KERNEL);
+ soc_data = of_device_get_match_data(&pdev->dev);
+
+ alloc_size = struct_size(admaif, capture_dma_data, soc_data->num_ch);
+ alloc_size += sizeof(*admaif->playback_dma_data) * soc_data->num_ch;
+ admaif = devm_kzalloc(&pdev->dev, alloc_size, GFP_KERNEL);
if (!admaif)
return -ENOMEM;
- admaif->soc_data = of_device_get_match_data(&pdev->dev);
+ admaif->playback_dma_data = admaif->capture_dma_data + soc_data->num_ch;
+ admaif->soc_data = soc_data;
dev_set_drvdata(&pdev->dev, admaif);
- admaif->capture_dma_data =
- devm_kcalloc(&pdev->dev,
- admaif->soc_data->num_ch,
- sizeof(struct snd_dmaengine_dai_dma_data),
- GFP_KERNEL);
- if (!admaif->capture_dma_data)
- return -ENOMEM;
-
- admaif->playback_dma_data =
- devm_kcalloc(&pdev->dev,
- admaif->soc_data->num_ch,
- sizeof(struct snd_dmaengine_dai_dma_data),
- GFP_KERNEL);
- if (!admaif->playback_dma_data)
- return -ENOMEM;
-
for (i = 0; i < ADMAIF_PATHS; i++) {
admaif->mono_to_stereo[i] =
devm_kcalloc(&pdev->dev, admaif->soc_data->num_ch,
diff --git a/sound/soc/tegra/tegra210_admaif.h b/sound/soc/tegra/tegra210_admaif.h
index 304d45c76a9a..fd9877aa95d3 100644
--- a/sound/soc/tegra/tegra210_admaif.h
+++ b/sound/soc/tegra/tegra210_admaif.h
@@ -229,13 +229,13 @@ struct tegra_admaif_soc_data {
};
struct tegra_admaif {
- struct snd_dmaengine_dai_dma_data *capture_dma_data;
struct snd_dmaengine_dai_dma_data *playback_dma_data;
const struct tegra_admaif_soc_data *soc_data;
unsigned int *mono_to_stereo[ADMAIF_PATHS];
unsigned int *stereo_to_mono[ADMAIF_PATHS];
struct regmap *regmap;
struct tegra_adma_isomgr *adma_isomgr;
+ struct snd_dmaengine_dai_dma_data capture_dma_data[];
};
#endif
diff --git a/sound/soc/tegra/tegra210_adx.c b/sound/soc/tegra/tegra210_adx.c
index d2f742ffc59d..15a94196ee1a 100644
--- a/sound/soc/tegra/tegra210_adx.c
+++ b/sound/soc/tegra/tegra210_adx.c
@@ -4,10 +4,10 @@
//
// tegra210_adx.c - Tegra210 ADX driver
+#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/platform_device.h>
@@ -47,18 +47,36 @@ static const struct reg_default tegra264_adx_reg_defaults[] = {
static void tegra210_adx_write_map_ram(struct tegra210_adx *adx)
{
+ const unsigned int bits_per_mask = BITS_PER_TYPE(*adx->byte_mask);
int i;
+ memset(adx->byte_mask, 0,
+ adx->soc_data->byte_mask_size * sizeof(*adx->byte_mask));
+
regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_CTRL +
adx->soc_data->cya_offset,
TEGRA210_ADX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
TEGRA210_ADX_CFG_RAM_CTRL_ADDR_INIT_EN |
TEGRA210_ADX_CFG_RAM_CTRL_RW_WRITE);
- for (i = 0; i < adx->soc_data->ram_depth; i++)
+ for (i = 0; i < adx->soc_data->ram_depth; i++) {
+ u32 word = 0;
+ int b;
+
+ for (b = 0; b < TEGRA_ADX_SLOTS_PER_WORD; b++) {
+ unsigned int slot = i * TEGRA_ADX_SLOTS_PER_WORD + b;
+ u16 val = adx->map[slot];
+
+ if (val >= 256)
+ continue;
+
+ word |= (u32)val << (b * BITS_PER_BYTE);
+ adx->byte_mask[slot / bits_per_mask] |=
+ 1U << (slot % bits_per_mask);
+ }
regmap_write(adx->regmap, TEGRA210_ADX_CFG_RAM_DATA +
- adx->soc_data->cya_offset,
- adx->map[i]);
+ adx->soc_data->cya_offset, word);
+ }
for (i = 0; i < adx->soc_data->byte_mask_size; i++)
regmap_write(adx->regmap,
@@ -192,27 +210,10 @@ static int tegra210_adx_get_byte_map(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
- struct soc_mixer_control *mc;
- unsigned char *bytes_map = (unsigned char *)adx->map;
- int enabled;
-
- mc = (struct soc_mixer_control *)kcontrol->private_value;
- enabled = adx->byte_mask[mc->reg / 32] & (1 << (mc->reg % 32));
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
- /*
- * TODO: Simplify this logic to just return from bytes_map[]
- *
- * Presently below is required since bytes_map[] is
- * tightly packed and cannot store the control value of 256.
- * Byte mask state is used to know if 256 needs to be returned.
- * Note that for control value of 256, the put() call stores 0
- * in the bytes_map[] and disables the corresponding bit in
- * byte_mask[].
- */
- if (enabled)
- ucontrol->value.integer.value[0] = bytes_map[mc->reg];
- else
- ucontrol->value.integer.value[0] = 256;
+ ucontrol->value.integer.value[0] = adx->map[mc->reg];
return 0;
}
@@ -222,23 +223,22 @@ static int tegra210_adx_put_byte_map(struct snd_kcontrol *kcontrol,
{
struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
struct tegra210_adx *adx = snd_soc_component_get_drvdata(cmpnt);
- unsigned char *bytes_map = (unsigned char *)adx->map;
- int value = ucontrol->value.integer.value[0];
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- unsigned int mask_val = adx->byte_mask[mc->reg / 32];
+ unsigned int value = ucontrol->value.integer.value[0];
- if (value >= 0 && value <= 255)
- mask_val |= (1 << (mc->reg % 32));
- else
- mask_val &= ~(1 << (mc->reg % 32));
+ /*
+ * Match the previous behaviour: any value outside [0, 255] is
+ * treated as the "disabled" sentinel (256). Negative values from
+ * userspace fold in through the unsigned cast and are caught here.
+ */
+ if (value > 255)
+ value = 256;
- if (mask_val == adx->byte_mask[mc->reg / 32])
+ if (adx->map[mc->reg] == value)
return 0;
- /* Update byte map and slot */
- bytes_map[mc->reg] = value % 256;
- adx->byte_mask[mc->reg / 32] = mask_val;
+ adx->map[mc->reg] = value;
return 1;
}
@@ -676,17 +676,15 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev)
{
struct device *dev = &pdev->dev;
struct tegra210_adx *adx;
- const struct of_device_id *match;
- struct tegra210_adx_soc_data *soc_data;
+ const struct tegra210_adx_soc_data *soc_data;
void __iomem *regs;
- int err;
+ int err, i;
adx = devm_kzalloc(dev, sizeof(*adx), GFP_KERNEL);
if (!adx)
return -ENOMEM;
- match = of_match_device(tegra210_adx_of_match, dev);
- soc_data = (struct tegra210_adx_soc_data *)match->data;
+ soc_data = of_device_get_match_data(dev);
adx->soc_data = soc_data;
dev_set_drvdata(dev, adx);
@@ -703,17 +701,21 @@ static int tegra210_adx_platform_probe(struct platform_device *pdev)
regcache_cache_only(adx->regmap, true);
- adx->map = devm_kzalloc(dev, soc_data->ram_depth * sizeof(*adx->map),
- GFP_KERNEL);
+ adx->map = devm_kcalloc(dev,
+ soc_data->ram_depth * TEGRA_ADX_SLOTS_PER_WORD,
+ sizeof(*adx->map), GFP_KERNEL);
if (!adx->map)
return -ENOMEM;
- adx->byte_mask = devm_kzalloc(dev,
- soc_data->byte_mask_size * sizeof(*adx->byte_mask),
- GFP_KERNEL);
+ adx->byte_mask = devm_kcalloc(dev, soc_data->byte_mask_size,
+ sizeof(*adx->byte_mask), GFP_KERNEL);
if (!adx->byte_mask)
return -ENOMEM;
+ /* Initialise all byte map slots as disabled (value 256). */
+ for (i = 0; i < soc_data->ram_depth * TEGRA_ADX_SLOTS_PER_WORD; i++)
+ adx->map[i] = 256;
+
tegra210_adx_dais[TEGRA_ADX_IN_DAI_ID].playback.channels_max =
adx->soc_data->max_ch;
diff --git a/sound/soc/tegra/tegra210_adx.h b/sound/soc/tegra/tegra210_adx.h
index 176a4e40de0a..a6298c3dcca5 100644
--- a/sound/soc/tegra/tegra210_adx.h
+++ b/sound/soc/tegra/tegra210_adx.h
@@ -8,6 +8,8 @@
#ifndef __TEGRA210_ADX_H__
#define __TEGRA210_ADX_H__
+#include <linux/types.h>
+
/* Register offsets from TEGRA210_ADX*_BASE */
#define TEGRA210_ADX_RX_STATUS 0x0c
#define TEGRA210_ADX_RX_INT_STATUS 0x10
@@ -61,6 +63,7 @@
#define TEGRA210_ADX_SOFT_RESET_SOFT_DEFAULT (0 << TEGRA210_ADX_SOFT_RESET_SOFT_RESET_SHIFT)
#define TEGRA210_ADX_AUDIOCIF_CH_STRIDE 4
+#define TEGRA_ADX_SLOTS_PER_WORD 4
#define TEGRA210_ADX_RAM_DEPTH 16
#define TEGRA210_ADX_MAP_STREAM_NUMBER_SHIFT 6
#define TEGRA210_ADX_MAP_WORD_NUMBER_SHIFT 2
@@ -88,8 +91,8 @@ struct tegra210_adx_soc_data {
struct tegra210_adx {
struct regmap *regmap;
- unsigned int *map;
unsigned int *byte_mask;
+ u16 *map;
const struct tegra210_adx_soc_data *soc_data;
};
diff --git a/sound/soc/tegra/tegra210_ahub.c b/sound/soc/tegra/tegra210_ahub.c
index ece33b7ff190..efc8f3388668 100644
--- a/sound/soc/tegra/tegra210_ahub.c
+++ b/sound/soc/tegra/tegra210_ahub.c
@@ -62,13 +62,15 @@ static int tegra_ahub_put_value_enum(struct snd_kcontrol *kctl,
struct snd_soc_dapm_update update[TEGRA_XBAR_UPDATE_MAX_REG] = { };
int val_bytes = snd_soc_component_regmap_val_bytes(cmpnt);
unsigned int *item = uctl->value.enumerated.item;
- unsigned int value = e->values[item[0]];
+ unsigned int value;
unsigned int i, bit_pos, reg_idx = 0, reg_val = 0;
int change = 0;
if (item[0] >= e->items)
return -EINVAL;
+ value = e->values[item[0]];
+
if (value) {
/* Get the register index and value to set */
reg_idx = (value - 1) / (8 * val_bytes);
diff --git a/sound/soc/tegra/tegra210_amx.c b/sound/soc/tegra/tegra210_amx.c
index d635046bbe81..cc1f9c158191 100644
--- a/sound/soc/tegra/tegra210_amx.c
+++ b/sound/soc/tegra/tegra210_amx.c
@@ -4,10 +4,10 @@
//
// tegra210_amx.c - Tegra210 AMX driver
+#include <linux/bits.h>
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -60,16 +60,35 @@ static const struct reg_default tegra264_amx_reg_defaults[] = {
static void tegra210_amx_write_map_ram(struct tegra210_amx *amx)
{
+ const unsigned int bits_per_mask = BITS_PER_TYPE(*amx->byte_mask);
int i;
+ memset(amx->byte_mask, 0,
+ amx->soc_data->byte_mask_size * sizeof(*amx->byte_mask));
+
regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_CTRL + amx->soc_data->reg_offset,
TEGRA210_AMX_CFG_RAM_CTRL_SEQ_ACCESS_EN |
TEGRA210_AMX_CFG_RAM_CTRL_ADDR_INIT_EN |
TEGRA210_AMX_CFG_RAM_CTRL_RW_WRITE);
- for (i = 0; i < amx->soc_data->ram_depth; i++)
+ for (i = 0; i < amx->soc_data->ram_depth; i++) {
+ u32 word = 0;
+ int b;
+
+ for (b = 0; b < TEGRA_AMX_SLOTS_PER_WORD; b++) {
+ unsigned int slot = i * TEGRA_AMX_SLOTS_PER_WORD + b;
+ u16 val = amx->map[slot];
+
+ if (val >= 256)
+ continue;
+
+ word |= (u32)val << (b * BITS_PER_BYTE);
+ amx->byte_mask[slot / bits_per_mask] |=
+ 1U << (slot % bits_per_mask);
+ }
regmap_write(amx->regmap, TEGRA210_AMX_CFG_RAM_DATA + amx->soc_data->reg_offset,
- amx->map[i]);
+ word);
+ }
for (i = 0; i < amx->soc_data->byte_mask_size; i++)
regmap_write(amx->regmap,
@@ -214,26 +233,8 @@ static int tegra210_amx_get_byte_map(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt);
- unsigned char *bytes_map = (unsigned char *)amx->map;
- int reg = mc->reg;
- int enabled;
-
- enabled = amx->byte_mask[reg / 32] & (1 << (reg % 32));
- /*
- * TODO: Simplify this logic to just return from bytes_map[]
- *
- * Presently below is required since bytes_map[] is
- * tightly packed and cannot store the control value of 256.
- * Byte mask state is used to know if 256 needs to be returned.
- * Note that for control value of 256, the put() call stores 0
- * in the bytes_map[] and disables the corresponding bit in
- * byte_mask[].
- */
- if (enabled)
- ucontrol->value.integer.value[0] = bytes_map[reg];
- else
- ucontrol->value.integer.value[0] = 256;
+ ucontrol->value.integer.value[0] = amx->map[mc->reg];
return 0;
}
@@ -245,22 +246,20 @@ static int tegra210_amx_put_byte_map(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
struct tegra210_amx *amx = snd_soc_component_get_drvdata(cmpnt);
- unsigned char *bytes_map = (unsigned char *)amx->map;
- int reg = mc->reg;
- int value = ucontrol->value.integer.value[0];
- unsigned int mask_val = amx->byte_mask[reg / 32];
+ unsigned int value = ucontrol->value.integer.value[0];
- if (value >= 0 && value <= 255)
- mask_val |= (1 << (reg % 32));
- else
- mask_val &= ~(1 << (reg % 32));
+ /*
+ * Match the previous behaviour: any value outside [0, 255] is
+ * treated as the "disabled" sentinel (256). Negative values from
+ * userspace fold in through the unsigned cast and are caught here.
+ */
+ if (value > 255)
+ value = 256;
- if (mask_val == amx->byte_mask[reg / 32])
+ if (amx->map[mc->reg] == value)
return 0;
- /* Update byte map and slot */
- bytes_map[reg] = value % 256;
- amx->byte_mask[reg / 32] = mask_val;
+ amx->map[mc->reg] = value;
return 1;
}
@@ -729,7 +728,7 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev)
struct device *dev = &pdev->dev;
struct tegra210_amx *amx;
void __iomem *regs;
- int err;
+ int err, i;
amx = devm_kzalloc(dev, sizeof(*amx), GFP_KERNEL);
if (!amx)
@@ -751,17 +750,21 @@ static int tegra210_amx_platform_probe(struct platform_device *pdev)
regcache_cache_only(amx->regmap, true);
- amx->map = devm_kzalloc(dev, amx->soc_data->ram_depth * sizeof(*amx->map),
- GFP_KERNEL);
+ amx->map = devm_kcalloc(dev,
+ amx->soc_data->ram_depth * TEGRA_AMX_SLOTS_PER_WORD,
+ sizeof(*amx->map), GFP_KERNEL);
if (!amx->map)
return -ENOMEM;
- amx->byte_mask = devm_kzalloc(dev,
- amx->soc_data->byte_mask_size * sizeof(*amx->byte_mask),
- GFP_KERNEL);
+ amx->byte_mask = devm_kcalloc(dev, amx->soc_data->byte_mask_size,
+ sizeof(*amx->byte_mask), GFP_KERNEL);
if (!amx->byte_mask)
return -ENOMEM;
+ /* Initialise all byte map slots as disabled (value 256). */
+ for (i = 0; i < amx->soc_data->ram_depth * TEGRA_AMX_SLOTS_PER_WORD; i++)
+ amx->map[i] = 256;
+
tegra210_amx_dais[TEGRA_AMX_OUT_DAI_ID].capture.channels_max =
amx->soc_data->max_ch;
diff --git a/sound/soc/tegra/tegra210_amx.h b/sound/soc/tegra/tegra210_amx.h
index 50a237b197ba..420b62f0cf35 100644
--- a/sound/soc/tegra/tegra210_amx.h
+++ b/sound/soc/tegra/tegra210_amx.h
@@ -8,6 +8,8 @@
#ifndef __TEGRA210_AMX_H__
#define __TEGRA210_AMX_H__
+#include <linux/types.h>
+
/* Register offsets from TEGRA210_AMX*_BASE */
#define TEGRA210_AMX_RX_STATUS 0x0c
#define TEGRA210_AMX_RX_INT_STATUS 0x10
@@ -73,6 +75,7 @@
#define TEGRA210_AMX_SOFT_RESET_SOFT_RESET_MASK TEGRA210_AMX_SOFT_RESET_SOFT_EN
#define TEGRA210_AMX_AUDIOCIF_CH_STRIDE 4
+#define TEGRA_AMX_SLOTS_PER_WORD 4
#define TEGRA210_AMX_RAM_DEPTH 16
#define TEGRA210_AMX_MAP_STREAM_NUM_SHIFT 6
#define TEGRA210_AMX_MAP_WORD_NUM_SHIFT 2
@@ -105,8 +108,8 @@ struct tegra210_amx_soc_data {
struct tegra210_amx {
const struct tegra210_amx_soc_data *soc_data;
- unsigned int *map;
unsigned int *byte_mask;
+ u16 *map;
struct regmap *regmap;
};
diff --git a/sound/soc/tegra/tegra210_dmic.c b/sound/soc/tegra/tegra210_dmic.c
index 3e42e2c75eb9..6098ad056ba9 100644
--- a/sound/soc/tegra/tegra210_dmic.c
+++ b/sound/soc/tegra/tegra210_dmic.c
@@ -7,7 +7,6 @@
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/math64.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
diff --git a/sound/soc/tegra/tegra210_i2s.c b/sound/soc/tegra/tegra210_i2s.c
index 0259b137547c..ff8c72fc38c5 100644
--- a/sound/soc/tegra/tegra210_i2s.c
+++ b/sound/soc/tegra/tegra210_i2s.c
@@ -6,7 +6,6 @@
#include <linux/clk.h>
#include <linux/device.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/of_graph.h>
#include <linux/platform_device.h>
diff --git a/sound/soc/tegra/tegra210_mixer.c b/sound/soc/tegra/tegra210_mixer.c
index ce44117a0b9c..a69774578d69 100644
--- a/sound/soc/tegra/tegra210_mixer.c
+++ b/sound/soc/tegra/tegra210_mixer.c
@@ -7,7 +7,7 @@
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
-#include <linux/mod_devicetable.h>
+#include <linux/math64.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -149,12 +149,19 @@ static int tegra210_mixer_configure_gain(struct snd_soc_component *cmpnt,
/* Write duration parameters */
for (i = 0; i < NUM_DURATION_PARMS; i++) {
- int val;
+ u32 val;
- if (instant_gain)
+ if (instant_gain) {
val = 1;
- else
- val = gain_params.duration[i];
+ } else {
+ if (i == DURATION_N3_ID)
+ val = mixer->duration[id];
+ else if (i == DURATION_INV_N3_ID)
+ val = div_u64(BIT_ULL(31 + TEGRA210_MIXER_PRESCALAR),
+ mixer->duration[id]);
+ else
+ val = gain_params.duration[i];
+ }
err = tegra210_mixer_write_ram(mixer,
REG_DURATION_PARAM(reg, i),
@@ -173,6 +180,216 @@ rpm_put:
return err;
}
+static int tegra210_mixer_fade_duration_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = TEGRA210_MIXER_FADE_DURATION_MIN;
+ uinfo->value.integer.max = TEGRA210_MIXER_FADE_DURATION_MAX;
+
+ return 0;
+}
+
+static int tegra210_mixer_get_fade_duration(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
+ struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
+
+ ucontrol->value.integer.value[0] = mixer->duration[mc->reg];
+
+ return 0;
+}
+
+static int tegra210_mixer_put_fade_duration(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
+ struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
+ unsigned int id = mc->reg;
+ long duration = ucontrol->value.integer.value[0];
+
+ if (duration < (long)TEGRA210_MIXER_FADE_DURATION_MIN ||
+ duration > TEGRA210_MIXER_FADE_DURATION_MAX)
+ return -EINVAL;
+
+ if (mixer->duration[id] == duration)
+ return 0;
+
+ mixer->duration[id] = duration;
+ mixer->fade_pending[id] = true;
+
+ return 1;
+}
+
+static int tegra210_mixer_get_fade_gain(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
+ struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
+
+ ucontrol->value.integer.value[0] = mixer->fade_gain[mc->reg];
+
+ return 0;
+}
+
+static int tegra210_mixer_put_fade_gain(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
+ struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
+ unsigned int id = mc->reg;
+
+ if (ucontrol->value.integer.value[0] < 0 ||
+ ucontrol->value.integer.value[0] > TEGRA210_MIXER_GAIN_MAX)
+ return -EINVAL;
+
+ if (mixer->fade_gain[id] == ucontrol->value.integer.value[0])
+ return 0;
+
+ mixer->fade_gain[id] = ucontrol->value.integer.value[0];
+ mixer->fade_pending[id] = true;
+
+ return 1;
+}
+
+static int tegra210_mixer_get_fade_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = 0;
+
+ return 0;
+}
+
+static int tegra210_mixer_put_fade_switch(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
+ struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
+ int id, err, changed = 0;
+
+ err = pm_runtime_resume_and_get(cmpnt->dev);
+ if (err < 0)
+ return err;
+
+ /* Switch off: disable sample count for all active fades */
+ if (!ucontrol->value.integer.value[0]) {
+ for (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) {
+ if (!mixer->in_fade[id])
+ continue;
+
+ regmap_update_bits(mixer->regmap,
+ MIXER_REG(TEGRA210_MIXER_RX1_CTRL,
+ id),
+ TEGRA210_MIXER_SAMPLE_COUNT_ENABLE,
+ 0);
+ mixer->in_fade[id] = false;
+ changed = 1;
+ }
+
+ pm_runtime_put(cmpnt->dev);
+ return changed;
+ }
+
+ /* Stop active fades on pending streams before reconfiguring */
+ for (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) {
+ if (!mixer->fade_pending[id])
+ continue;
+
+ if (mixer->in_fade[id]) {
+ regmap_update_bits(mixer->regmap,
+ MIXER_REG(TEGRA210_MIXER_RX1_CTRL,
+ id),
+ TEGRA210_MIXER_SAMPLE_COUNT_ENABLE,
+ 0);
+ mixer->in_fade[id] = false;
+ }
+
+ mixer->gain_value[id] = mixer->fade_gain[id];
+ err = tegra210_mixer_configure_gain(cmpnt, id, false);
+ if (err) {
+ dev_err(cmpnt->dev,
+ "Failed to configure fade for RX%d\n", id + 1);
+ pm_runtime_put(cmpnt->dev);
+ return err;
+ }
+
+ changed = 1;
+ }
+
+ if (!changed) {
+ pm_runtime_put(cmpnt->dev);
+ return 0;
+ }
+
+ /* Enable sample count for all pending streams */
+ for (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) {
+ if (!mixer->fade_pending[id])
+ continue;
+
+ err = regmap_update_bits(mixer->regmap,
+ MIXER_REG(TEGRA210_MIXER_RX1_CTRL, id),
+ TEGRA210_MIXER_SAMPLE_COUNT_ENABLE,
+ TEGRA210_MIXER_SAMPLE_COUNT_ENABLE);
+ if (err) {
+ dev_err(cmpnt->dev,
+ "Failed to enable sample count for RX%d\n",
+ id + 1);
+ pm_runtime_put(cmpnt->dev);
+ return err;
+ }
+
+ mixer->in_fade[id] = true;
+ mixer->fade_pending[id] = false;
+ }
+
+ pm_runtime_put(cmpnt->dev);
+
+ return 1;
+}
+
+static int tegra210_mixer_get_fade_status(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_component *cmpnt = snd_kcontrol_chip(kcontrol);
+ struct tegra210_mixer *mixer = snd_soc_component_get_drvdata(cmpnt);
+ u32 count;
+ int id, err;
+
+ err = pm_runtime_resume_and_get(cmpnt->dev);
+ if (err < 0)
+ return err;
+
+ for (id = 0; id < TEGRA210_MIXER_RX_MAX; id++) {
+ if (!mixer->in_fade[id]) {
+ ucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_IDLE;
+ continue;
+ }
+
+ regmap_read(mixer->regmap,
+ MIXER_REG(TEGRA210_MIXER_RX1_SAMPLE_COUNT, id),
+ &count);
+
+ if (count >= mixer->duration[id])
+ ucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_IDLE;
+ else
+ ucontrol->value.integer.value[id] = TEGRA210_MIXER_FADE_ACTIVE;
+ }
+
+ pm_runtime_put(cmpnt->dev);
+
+ return 0;
+}
+
static int tegra210_mixer_get_gain(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -396,14 +613,44 @@ ADDER_CTRL_DECL(adder3, TEGRA210_MIXER_TX3_ADDER_CONFIG);
ADDER_CTRL_DECL(adder4, TEGRA210_MIXER_TX4_ADDER_CONFIG);
ADDER_CTRL_DECL(adder5, TEGRA210_MIXER_TX5_ADDER_CONFIG);
+static int tegra210_mixer_fade_status_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = TEGRA210_MIXER_RX_MAX;
+ uinfo->value.integer.min = TEGRA210_MIXER_FADE_IDLE;
+ uinfo->value.integer.max = TEGRA210_MIXER_FADE_ACTIVE;
+
+ return 0;
+}
+
+#define FADE_CTRL(id) \
+ { \
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
+ .name = "RX" #id " Fade Duration", \
+ .info = tegra210_mixer_fade_duration_info, \
+ .get = tegra210_mixer_get_fade_duration, \
+ .put = tegra210_mixer_put_fade_duration, \
+ .private_value = SOC_SINGLE_VALUE((id) - 1, 0, \
+ TEGRA210_MIXER_FADE_DURATION_MIN, \
+ TEGRA210_MIXER_FADE_DURATION_MAX, \
+ 0, 0), \
+ }, \
+ SOC_SINGLE_EXT("RX" #id " Fade Gain", (id) - 1, 0, \
+ TEGRA210_MIXER_GAIN_MAX, 0, \
+ tegra210_mixer_get_fade_gain, \
+ tegra210_mixer_put_fade_gain),
+
#define GAIN_CTRL(id) \
SOC_SINGLE_EXT("RX" #id " Gain Volume", \
MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0, \
- 0x20000, 0, tegra210_mixer_get_gain, \
+ TEGRA210_MIXER_GAIN_MAX, 0, \
+ tegra210_mixer_get_gain, \
tegra210_mixer_put_gain), \
SOC_SINGLE_EXT("RX" #id " Instant Gain Volume", \
MIXER_GAIN_CFG_RAM_ADDR((id) - 1), 0, \
- 0x20000, 0, tegra210_mixer_get_gain, \
+ TEGRA210_MIXER_GAIN_MAX, 0, \
+ tegra210_mixer_get_gain, \
tegra210_mixer_put_instant_gain),
/* Volume controls for all MIXER inputs */
@@ -418,6 +665,28 @@ static const struct snd_kcontrol_new tegra210_mixer_gain_ctls[] = {
GAIN_CTRL(8)
GAIN_CTRL(9)
GAIN_CTRL(10)
+
+ FADE_CTRL(1)
+ FADE_CTRL(2)
+ FADE_CTRL(3)
+ FADE_CTRL(4)
+ FADE_CTRL(5)
+ FADE_CTRL(6)
+ FADE_CTRL(7)
+ FADE_CTRL(8)
+ FADE_CTRL(9)
+ FADE_CTRL(10)
+ SOC_SINGLE_EXT("Fade Switch", SND_SOC_NOPM, 0, 1, 0,
+ tegra210_mixer_get_fade_switch,
+ tegra210_mixer_put_fade_switch),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Fade Status",
+ .info = tegra210_mixer_fade_status_info,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ |
+ SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .get = tegra210_mixer_get_fade_status,
+ },
};
static const struct snd_soc_dapm_widget tegra210_mixer_widgets[] = {
@@ -579,6 +848,7 @@ static bool tegra210_mixer_volatile_reg(struct device *dev,
case TEGRA210_MIXER_GAIN_CFG_RAM_DATA:
case TEGRA210_MIXER_PEAKM_RAM_CTRL:
case TEGRA210_MIXER_PEAKM_RAM_DATA:
+ case TEGRA210_MIXER_RX1_SAMPLE_COUNT:
return true;
default:
return false;
@@ -632,8 +902,11 @@ static int tegra210_mixer_platform_probe(struct platform_device *pdev)
dev_set_drvdata(dev, mixer);
/* Use default gain value for all MIXER inputs */
- for (i = 0; i < TEGRA210_MIXER_RX_MAX; i++)
+ for (i = 0; i < TEGRA210_MIXER_RX_MAX; i++) {
mixer->gain_value[i] = gain_params.gain_value;
+ mixer->fade_gain[i] = gain_params.gain_value;
+ mixer->duration[i] = gain_params.duration[DURATION_N3_ID];
+ }
regs = devm_platform_ioremap_resource(pdev, 0);
if (IS_ERR(regs))
diff --git a/sound/soc/tegra/tegra210_mixer.h b/sound/soc/tegra/tegra210_mixer.h
index a330530fbc61..d9c8fa6124de 100644
--- a/sound/soc/tegra/tegra210_mixer.h
+++ b/sound/soc/tegra/tegra210_mixer.h
@@ -79,12 +79,27 @@
#define TEGRA210_MIXER_RX_LIMIT (TEGRA210_MIXER_RX_MAX * TEGRA210_MIXER_REG_STRIDE)
#define TEGRA210_MIXER_TX_MAX 5
#define TEGRA210_MIXER_TX_LIMIT (TEGRA210_MIXER_RX_LIMIT + (TEGRA210_MIXER_TX_MAX * TEGRA210_MIXER_REG_STRIDE))
+#define TEGRA210_MIXER_SAMPLE_COUNT_SHIFT 24
+#define TEGRA210_MIXER_SAMPLE_COUNT_ENABLE BIT(TEGRA210_MIXER_SAMPLE_COUNT_SHIFT)
#define REG_CFG_DONE_TRIGGER 0xf
#define VAL_CFG_DONE_TRIGGER 0x1
#define NUM_GAIN_POLY_COEFFS 9
-#define NUM_DURATION_PARMS 4
+#define TEGRA210_MIXER_GAIN_MAX 0x20000
+
+#define TEGRA210_MIXER_PRESCALAR 6
+#define TEGRA210_MIXER_FADE_DURATION_MIN \
+ (BIT(TEGRA210_MIXER_PRESCALAR - 1) + 1)
+#define TEGRA210_MIXER_FADE_DURATION_MAX 0x7fffffff
+#define TEGRA210_MIXER_FADE_IDLE 0
+#define TEGRA210_MIXER_FADE_ACTIVE 1
+
+enum {
+ DURATION_N3_ID = 2,
+ DURATION_INV_N3_ID,
+ NUM_DURATION_PARMS,
+};
struct tegra210_mixer_gain_params {
int poly_coeff[NUM_GAIN_POLY_COEFFS];
@@ -94,6 +109,10 @@ struct tegra210_mixer_gain_params {
struct tegra210_mixer {
int gain_value[TEGRA210_MIXER_RX_MAX];
+ int fade_gain[TEGRA210_MIXER_RX_MAX];
+ u32 duration[TEGRA210_MIXER_RX_MAX];
+ bool in_fade[TEGRA210_MIXER_RX_MAX];
+ bool fade_pending[TEGRA210_MIXER_RX_MAX];
struct regmap *regmap;
};
diff --git a/sound/soc/tegra/tegra210_mvc.c b/sound/soc/tegra/tegra210_mvc.c
index 2c299704ef4f..ac04350107c4 100644
--- a/sound/soc/tegra/tegra210_mvc.c
+++ b/sound/soc/tegra/tegra210_mvc.c
@@ -7,7 +7,6 @@
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
@@ -438,6 +437,9 @@ static int tegra210_mvc_set_audio_cif(struct tegra210_mvc *mvc,
channels = params_channels(params);
switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ audio_bits = TEGRA_ACIF_BITS_8;
+ break;
case SNDRV_PCM_FORMAT_S16_LE:
audio_bits = TEGRA_ACIF_BITS_16;
break;
diff --git a/sound/soc/tegra/tegra210_ope.c b/sound/soc/tegra/tegra210_ope.c
index ad4c400281e8..30a54b1222d9 100644
--- a/sound/soc/tegra/tegra210_ope.c
+++ b/sound/soc/tegra/tegra210_ope.c
@@ -7,7 +7,6 @@
#include <linux/clk.h>
#include <linux/device.h>
#include <linux/io.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index 51e5ab6c276b..ee68f28852c4 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -509,6 +509,7 @@ static const struct of_device_id tegra30_ahub_of_match[] = {
{ .compatible = "nvidia,tegra30-ahub", .data = &soc_data_tegra30 },
{},
};
+MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match);
static int tegra30_ahub_probe(struct platform_device *pdev)
{
@@ -684,4 +685,3 @@ MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra30 AHUB driver");
MODULE_LICENSE("GPL v2");
MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, tegra30_ahub_of_match);
diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c
index b121af9ef8ed..1d7b3aed51fd 100644
--- a/sound/soc/tegra/tegra30_i2s.c
+++ b/sound/soc/tegra/tegra30_i2s.c
@@ -402,6 +402,7 @@ static const struct of_device_id tegra30_i2s_of_match[] = {
{ .compatible = "nvidia,tegra30-i2s", .data = &tegra30_i2s_config },
{},
};
+MODULE_DEVICE_TABLE(of, tegra30_i2s_of_match);
static int tegra30_i2s_platform_probe(struct platform_device *pdev)
{
@@ -567,4 +568,3 @@ MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra30 I2S ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
-MODULE_DEVICE_TABLE(of, tegra30_i2s_of_match);
diff --git a/sound/soc/tegra/tegra_isomgr_bw.c b/sound/soc/tegra/tegra_isomgr_bw.c
index fa979960bc09..1c007f870759 100644
--- a/sound/soc/tegra/tegra_isomgr_bw.c
+++ b/sound/soc/tegra/tegra_isomgr_bw.c
@@ -6,6 +6,7 @@
#include <linux/interconnect.h>
#include <linux/module.h>
+#include <sound/dmaengine_pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
#include "tegra_isomgr_bw.h"
@@ -55,19 +56,18 @@ int tegra_isomgr_adma_setbw(struct snd_pcm_substream *substream,
sample_bytes;
}
- mutex_lock(&adma_isomgr->mutex);
+ scoped_guard(mutex, &adma_isomgr->mutex) {
+ if (is_running) {
+ if (bandwidth + adma_isomgr->current_bandwidth > adma_isomgr->max_bw)
+ bandwidth = adma_isomgr->max_bw - adma_isomgr->current_bandwidth;
- if (is_running) {
- if (bandwidth + adma_isomgr->current_bandwidth > adma_isomgr->max_bw)
- bandwidth = adma_isomgr->max_bw - adma_isomgr->current_bandwidth;
-
- adma_isomgr->current_bandwidth += bandwidth;
- } else {
- adma_isomgr->current_bandwidth -= adma_isomgr->bw_per_dev[type][pcm->device];
+ adma_isomgr->current_bandwidth += bandwidth;
+ } else {
+ adma_isomgr->current_bandwidth -=
+ adma_isomgr->bw_per_dev[type][pcm->device];
+ }
}
- mutex_unlock(&adma_isomgr->mutex);
-
adma_isomgr->bw_per_dev[type][pcm->device] = bandwidth;
dev_dbg(dev, "Setting up bandwidth to %d KBps\n", adma_isomgr->current_bandwidth);
diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c
index ba173d9fcba9..61252359d5cb 100644
--- a/sound/soc/ti/ams-delta.c
+++ b/sound/soc/ti/ams-delta.c
@@ -93,7 +93,7 @@ static unsigned short ams_delta_audio_agc;
* Used for passing a codec structure pointer
* from the board initialization code to the tty line discipline.
*/
-static struct snd_soc_component *cx20442_codec;
+static struct cx20442_codec cx20442_codec;
static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -105,7 +105,7 @@ static int ams_delta_set_audio_mode(struct snd_kcontrol *kcontrol,
int pin, changed = 0;
/* Refuse any mode changes if we are not able to control the codec. */
- if (!cx20442_codec->card->pop_time)
+ if (!cx20442_codec.ready)
return -EUNATCH;
if (ucontrol->value.enumerated.item[0] >= control->items)
@@ -264,10 +264,10 @@ static void cx81801_timeout(struct timer_list *unused)
{
int muted;
- spin_lock(&ams_delta_lock);
- cx81801_cmd_pending = 0;
- muted = ams_delta_muted;
- spin_unlock(&ams_delta_lock);
+ scoped_guard(spinlock, &ams_delta_lock) {
+ cx81801_cmd_pending = 0;
+ muted = ams_delta_muted;
+ }
/* Reconnect the codec DAI back from the modem to the CPU DAI
* only if digital mute still off */
@@ -280,14 +280,14 @@ static int cx81801_open(struct tty_struct *tty)
{
int ret;
- if (!cx20442_codec)
+ if (!cx20442_codec.component)
return -ENODEV;
/*
* Pass the codec structure pointer for use by other ldisc callbacks,
* both the card and the codec specific parts.
*/
- tty->disc_data = cx20442_codec;
+ tty->disc_data = &cx20442_codec;
ret = v253_ops.open(tty);
@@ -300,9 +300,12 @@ static int cx81801_open(struct tty_struct *tty)
/* Line discipline .close() */
static void cx81801_close(struct tty_struct *tty)
{
- struct snd_soc_component *component = tty->disc_data;
+ struct snd_soc_component *component = cx20442_codec.component;
struct snd_soc_dapm_context *dapm;
+ if (WARN_ON(tty->disc_data != &cx20442_codec))
+ return;
+
timer_delete_sync(&cx81801_timer);
/* Prevent the hook switch from further changing the DAPM pins */
@@ -339,14 +342,14 @@ static void cx81801_hangup(struct tty_struct *tty)
static void cx81801_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp,
size_t count)
{
- struct snd_soc_component *component = tty->disc_data;
+ struct snd_soc_component *component = cx20442_codec.component;
const unsigned char *c;
int apply, ret;
- if (!component)
+ if (WARN_ON(tty->disc_data != &cx20442_codec))
return;
- if (!component->card->pop_time) {
+ if (!cx20442_codec.ready) {
/* First modem response, complete setup procedure */
/* Initialize timer used for config pulse generation */
@@ -373,11 +376,11 @@ static void cx81801_receive(struct tty_struct *tty, const u8 *cp, const u8 *fp,
continue;
/* Complete modem response received, apply config to codec */
- spin_lock_bh(&ams_delta_lock);
- mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150));
- apply = !ams_delta_muted && !cx81801_cmd_pending;
- cx81801_cmd_pending = 1;
- spin_unlock_bh(&ams_delta_lock);
+ scoped_guard(spinlock_bh, &ams_delta_lock) {
+ mod_timer(&cx81801_timer, jiffies + msecs_to_jiffies(150));
+ apply = !ams_delta_muted && !cx81801_cmd_pending;
+ cx81801_cmd_pending = 1;
+ }
/* Apply config pulse by connecting the codec to the modem
* if not already done */
@@ -426,10 +429,10 @@ static int ams_delta_mute(struct snd_soc_dai *dai, int mute, int direction)
if (ams_delta_muted == mute)
return 0;
- spin_lock_bh(&ams_delta_lock);
- ams_delta_muted = mute;
- apply = !cx81801_cmd_pending;
- spin_unlock_bh(&ams_delta_lock);
+ scoped_guard(spinlock_bh, &ams_delta_lock) {
+ ams_delta_muted = mute;
+ apply = !cx81801_cmd_pending;
+ }
if (apply)
gpiod_set_value(gpiod_modem_codec, !!mute);
@@ -467,7 +470,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
/* Codec is ready, now add/activate board specific controls */
/* Store a pointer to the codec structure for tty ldisc use */
- cx20442_codec = snd_soc_rtd_to_codec(rtd, 0)->component;
+ cx20442_codec.component = snd_soc_rtd_to_codec(rtd, 0)->component;
/* Add hook switch - can be used to control the codec from userspace
* even if line discipline fails */
diff --git a/sound/soc/ti/davinci-mcasp.c b/sound/soc/ti/davinci-mcasp.c
index f229f847eaf4..79239131b659 100644
--- a/sound/soc/ti/davinci-mcasp.c
+++ b/sound/soc/ti/davinci-mcasp.c
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/of.h>
+#include <linux/of_graph.h>
#include <linux/platform_data/davinci_asp.h>
#include <linux/math64.h>
#include <linux/bitmap.h>
@@ -74,6 +75,14 @@ struct davinci_mcasp_ruledata {
int stream;
};
+enum mcasp_graph_mode {
+ MCASP_GRAPH_NONE, /* 1:1, simple-audio-card, no of-graph endpoints */
+ MCASP_GRAPH_PORT, /* 1:1, audio-graph-card: port { endpoint } */
+ MCASP_GRAPH_PORTS, /* 1:N, audio-graph-card2 non-DPCM: ports { port@0; ... } */
+ MCASP_GRAPH_DPCM, /* N:M, audio-graph-card2 DPCM: N FE DAIs, detected via */
+ /* remote "dpcm" node in the sound card DT */
+};
+
struct davinci_mcasp {
struct snd_dmaengine_dai_dma_data dma_data[2];
struct davinci_mcasp_pdata *pdata;
@@ -124,6 +133,10 @@ struct davinci_mcasp {
int max_format_width;
u8 active_serializers[2];
+ /* Audio graph support */
+ enum mcasp_graph_mode graph_mode;
+ int num_dais;
+
#ifdef CONFIG_GPIOLIB
struct gpio_chip gpio_chip;
#endif
@@ -1486,7 +1499,18 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- ret = davinci_mcasp_set_dai_fmt(cpu_dai, mcasp->dai_fmt);
+ struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
+ unsigned int cpu_fmt;
+
+ if (mcasp->graph_mode != MCASP_GRAPH_NONE && rtd->dai_link->dai_fmt)
+ /* clock provider bits stored separately in ext_fmt */
+ cpu_fmt = snd_soc_daifmt_clock_provider_flipped(
+ rtd->dai_link->dai_fmt) |
+ rtd->dai_link->cpus[0].ext_fmt;
+ else
+ cpu_fmt = mcasp->dai_fmt;
+
+ ret = davinci_mcasp_set_dai_fmt(cpu_dai, cpu_fmt);
if (ret)
return ret;
@@ -2029,8 +2053,31 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
};
+/* Translate of-graph endpoint to DAI ID (DPCM: port reg; else 0). */
+static int davinci_mcasp_of_xlate_dai_id(struct snd_soc_component *component,
+ struct device_node *endpoint)
+{
+ struct davinci_mcasp *mcasp = snd_soc_component_get_drvdata(component);
+ struct device_node *port;
+ u32 port_reg = 0;
+
+ if (mcasp->graph_mode != MCASP_GRAPH_DPCM)
+ return 0;
+
+ /* endpoint is inside mcasp/ports/port@N — read port's reg */
+ port = of_get_parent(endpoint);
+ if (!port)
+ return -EINVAL;
+
+ of_property_read_u32(port, "reg", &port_reg);
+ of_node_put(port);
+
+ return port_reg;
+}
+
static const struct snd_soc_component_driver davinci_mcasp_component = {
.name = "davinci-mcasp",
+ .of_xlate_dai_id = davinci_mcasp_of_xlate_dai_id,
.legacy_dai_naming = 1,
};
@@ -2138,6 +2185,88 @@ static bool davinci_mcasp_have_gpiochip(struct davinci_mcasp *mcasp)
return device_property_present(mcasp->dev, "gpio-controller");
}
+/* Return true if the remote sound card uses a "dpcm" container. */
+static bool mcasp_detect_dpcm(struct device_node *np)
+{
+ struct device_node *ep, *remote_ep;
+ struct device_node *port, *container, *parent;
+ bool is_dpcm = false;
+
+ /* Grab the first endpoint under this McASP node */
+ ep = of_graph_get_next_endpoint(np, NULL);
+ if (!ep)
+ return false;
+
+ /* Follow remote-endpoint phandle into the card node */
+ remote_ep = of_graph_get_remote_endpoint(ep);
+ of_node_put(ep);
+ if (!remote_ep)
+ return false;
+
+ /* Traverse the remote: remote_ep -> port -> ports@N -> dpcm */
+ port = of_get_parent(remote_ep);
+ of_node_put(remote_ep);
+ if (!port)
+ return false;
+
+ container = of_get_parent(port);
+ of_node_put(port);
+ if (!container)
+ return false;
+
+ if (of_node_name_eq(container, "ports")) {
+ parent = of_get_parent(container);
+ of_node_put(container);
+ if (parent) {
+ is_dpcm = of_node_name_eq(parent, "dpcm");
+ of_node_put(parent);
+ }
+ } else {
+ of_node_put(container);
+ }
+
+ return is_dpcm;
+}
+
+/* Detect audio-graph topology and return the number of DAIs to register. */
+static int davinci_mcasp_parse_of_graph(struct davinci_mcasp *mcasp,
+ struct device_node *np)
+{
+ struct device_node *port, *ports;
+ int num_dais = 0;
+
+ mcasp->graph_mode = MCASP_GRAPH_NONE;
+
+ /* audio-graph-card2: ports { port@0 ... }; DPCM -> N DAIs, else 1 */
+ ports = of_get_child_by_name(np, "ports");
+ if (ports) {
+ int port_count = of_get_child_count(ports);
+
+ of_node_put(ports);
+
+ if (mcasp_detect_dpcm(np)) {
+ num_dais = port_count;
+ mcasp->graph_mode = MCASP_GRAPH_DPCM;
+ } else {
+ num_dais = 1;
+ mcasp->graph_mode = MCASP_GRAPH_PORTS;
+ }
+
+ return num_dais;
+ }
+
+ /* audio-graph-card: single port { endpoint } */
+ port = of_get_child_by_name(np, "port");
+ if (port) {
+ num_dais = of_graph_get_endpoint_count(port);
+ if (num_dais > 0)
+ mcasp->graph_mode = MCASP_GRAPH_PORT;
+ of_node_put(port);
+ }
+
+ return num_dais ? num_dais : 1;
+}
+
static int davinci_mcasp_get_config(struct davinci_mcasp *mcasp,
struct platform_device *pdev)
{
@@ -2555,6 +2684,53 @@ static inline int davinci_mcasp_init_gpiochip(struct davinci_mcasp *mcasp)
}
#endif /* CONFIG_GPIOLIB */
+static int davinci_mcasp_register_component(struct davinci_mcasp *mcasp,
+ struct platform_device *pdev)
+{
+ struct snd_soc_dai_driver *dais;
+ int i;
+
+ if (mcasp->graph_mode == MCASP_GRAPH_NONE || mcasp->num_dais <= 1)
+ return devm_snd_soc_register_component(&pdev->dev,
+ &davinci_mcasp_component,
+ &davinci_mcasp_dai[mcasp->op_mode], 1);
+
+ dais = devm_kcalloc(&pdev->dev, mcasp->num_dais, sizeof(*dais),
+ GFP_KERNEL);
+ if (!dais)
+ return -ENOMEM;
+
+ for (i = 0; i < mcasp->num_dais; i++) {
+ memcpy(&dais[i], &davinci_mcasp_dai[mcasp->op_mode],
+ sizeof(*dais));
+ dais[i].id = i;
+ dais[i].name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "davinci-mcasp.%d", i);
+ if (!dais[i].name)
+ return -ENOMEM;
+
+ /* Unique stream names per DAI */
+ if (dais[i].playback.channels_min) {
+ dais[i].playback.stream_name =
+ devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "Playback Port %d", i);
+ if (!dais[i].playback.stream_name)
+ return -ENOMEM;
+ }
+ if (dais[i].capture.channels_min) {
+ dais[i].capture.stream_name =
+ devm_kasprintf(&pdev->dev, GFP_KERNEL,
+ "Capture Port %d", i);
+ if (!dais[i].capture.stream_name)
+ return -ENOMEM;
+ }
+ }
+
+ return devm_snd_soc_register_component(&pdev->dev,
+ &davinci_mcasp_component,
+ dais, mcasp->num_dais);
+}
+
static int davinci_mcasp_probe(struct platform_device *pdev)
{
struct snd_dmaengine_dai_dma_data *dma_data;
@@ -2760,9 +2936,10 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
goto err;
}
- ret = devm_snd_soc_register_component(&pdev->dev, &davinci_mcasp_component,
- &davinci_mcasp_dai[mcasp->op_mode], 1);
+ /* Parse audio-graph structure and register DAIs */
+ mcasp->num_dais = davinci_mcasp_parse_of_graph(mcasp, pdev->dev.of_node);
+ ret = davinci_mcasp_register_component(mcasp, pdev);
if (ret != 0)
goto err;
diff --git a/sound/soc/ti/j721e-evm.c b/sound/soc/ti/j721e-evm.c
index faa62c1a9b8e..c214ae0d7b95 100644
--- a/sound/soc/ti/j721e-evm.c
+++ b/sound/soc/ti/j721e-evm.c
@@ -74,7 +74,6 @@ struct j721e_audio_domain {
struct j721e_priv {
struct device *dev;
struct snd_soc_card card;
- struct snd_soc_dai_link *dai_links;
struct snd_soc_codec_conf codec_conf[J721E_CODEC_CONF_COUNT];
struct snd_interval rate_range;
const struct j721e_audio_match_data *match_data;
@@ -84,6 +83,7 @@ struct j721e_priv {
struct j721e_audio_domain audio_domains[J721E_AUDIO_DOMAIN_LAST];
struct mutex mutex;
+ struct snd_soc_dai_link dai_links[];
};
static const struct snd_soc_dapm_widget j721e_cpb_dapm_widgets[] = {
@@ -263,7 +263,7 @@ static int j721e_audio_startup(struct snd_pcm_substream *substream)
int ret = 0;
int i;
- mutex_lock(&priv->mutex);
+ guard(mutex)(&priv->mutex);
domain->active++;
@@ -303,7 +303,6 @@ static int j721e_audio_startup(struct snd_pcm_substream *substream)
out:
if (ret)
domain->active--;
- mutex_unlock(&priv->mutex);
return ret;
}
@@ -323,30 +322,28 @@ static int j721e_audio_hw_params(struct snd_pcm_substream *substream,
int ret;
int i;
- mutex_lock(&priv->mutex);
+ guard(mutex)(&priv->mutex);
- if (domain->rate && domain->rate != params_rate(params)) {
- ret = -EINVAL;
- goto out;
- }
+ if (domain->rate && domain->rate != params_rate(params))
+ return -EINVAL;
if (params_width(params) == 16)
slot_width = 16;
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 0x3, 0x3, 2, slot_width);
if (ret && ret != -ENOTSUPP)
- goto out;
+ return ret;
for_each_rtd_codec_dais(rtd, i, codec_dai) {
ret = snd_soc_dai_set_tdm_slot(codec_dai, 0x3, 0x3, 2,
slot_width);
if (ret && ret != -ENOTSUPP)
- goto out;
+ return ret;
}
ret = j721e_configure_refclk(priv, domain_id, params_rate(params));
if (ret)
- goto out;
+ return ret;
sysclk_rate = priv->hsdiv_rates[domain->parent_clk_id];
for_each_rtd_codec_dais(rtd, i, codec_dai) {
@@ -356,7 +353,7 @@ static int j721e_audio_hw_params(struct snd_pcm_substream *substream,
dev_err(priv->dev,
"codec set_sysclk failed for %u Hz\n",
sysclk_rate);
- goto out;
+ return ret;
}
}
@@ -371,8 +368,6 @@ static int j721e_audio_hw_params(struct snd_pcm_substream *substream,
ret = 0;
}
-out:
- mutex_unlock(&priv->mutex);
return ret;
}
@@ -383,15 +378,13 @@ static void j721e_audio_shutdown(struct snd_pcm_substream *substream)
unsigned int domain_id = rtd->dai_link->id;
struct j721e_audio_domain *domain = &priv->audio_domains[domain_id];
- mutex_lock(&priv->mutex);
+ guard(mutex)(&priv->mutex);
domain->active--;
if (!domain->active) {
domain->rate = 0;
domain->active_link = 0;
}
-
- mutex_unlock(&priv->mutex);
}
static const struct snd_soc_ops j721e_audio_ops = {
@@ -844,33 +837,23 @@ put_dai_node:
static int j721e_soc_probe(struct platform_device *pdev)
{
- struct device_node *node = pdev->dev.of_node;
+ const struct j721e_audio_match_data *match;
struct snd_soc_card *card;
- const struct of_device_id *match;
struct j721e_priv *priv;
int link_cnt, conf_cnt, ret, i;
- if (!node) {
- dev_err(&pdev->dev, "of node is missing.\n");
- return -ENODEV;
- }
-
- match = of_match_node(j721e_audio_of_match, node);
+ match = of_device_get_match_data(&pdev->dev);
if (!match) {
dev_err(&pdev->dev, "No compatible match found\n");
return -ENODEV;
}
- priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
+ priv = devm_kzalloc(&pdev->dev,
+ struct_size(priv, dai_links, match->num_links), GFP_KERNEL);
if (!priv)
return -ENOMEM;
- priv->match_data = match->data;
-
- priv->dai_links = devm_kcalloc(&pdev->dev, priv->match_data->num_links,
- sizeof(*priv->dai_links), GFP_KERNEL);
- if (!priv->dai_links)
- return -ENOMEM;
+ priv->match_data = match;
for (i = 0; i < J721E_AUDIO_DOMAIN_LAST; i++)
priv->audio_domains[i].parent_clk_id = -1;
diff --git a/sound/soc/ti/omap-dmic.c b/sound/soc/ti/omap-dmic.c
index fb92bb88eb5c..b795b9f66b0e 100644
--- a/sound/soc/ti/omap-dmic.c
+++ b/sound/soc/ti/omap-dmic.c
@@ -11,7 +11,6 @@
*/
#include <linux/init.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/err.h>
@@ -91,18 +90,14 @@ static int omap_dmic_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
- int ret = 0;
-
- mutex_lock(&dmic->mutex);
- if (!snd_soc_dai_active(dai))
- dmic->active = 1;
- else
- ret = -EBUSY;
+ guard(mutex)(&dmic->mutex);
- mutex_unlock(&dmic->mutex);
+ if (snd_soc_dai_active(dai))
+ return -EBUSY;
- return ret;
+ dmic->active = 1;
+ return 0;
}
static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
@@ -110,14 +105,12 @@ static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
{
struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
- mutex_lock(&dmic->mutex);
+ guard(mutex)(&dmic->mutex);
cpu_latency_qos_remove_request(&dmic->pm_qos_req);
if (!snd_soc_dai_active(dai))
dmic->active = 0;
-
- mutex_unlock(&dmic->mutex);
}
static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate)
@@ -328,32 +321,30 @@ static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
}
mux = clk_get_parent(dmic->fclk);
- if (IS_ERR(mux)) {
+ if (!mux) {
dev_err(dmic->dev, "can't get fck mux parent\n");
clk_put(parent_clk);
return -ENODEV;
}
- mutex_lock(&dmic->mutex);
- if (dmic->active) {
- /* disable clock while reparenting */
- pm_runtime_put_sync(dmic->dev);
- ret = clk_set_parent(mux, parent_clk);
- pm_runtime_get_sync(dmic->dev);
- } else {
- ret = clk_set_parent(mux, parent_clk);
+ scoped_guard(mutex, &dmic->mutex) {
+ if (dmic->active) {
+ /* disable clock while reparenting */
+ pm_runtime_put_sync(dmic->dev);
+ ret = clk_set_parent(mux, parent_clk);
+ pm_runtime_get_sync(dmic->dev);
+ } else {
+ ret = clk_set_parent(mux, parent_clk);
+ }
}
- mutex_unlock(&dmic->mutex);
if (ret < 0) {
dev_err(dmic->dev, "re-parent failed\n");
- goto err_busy;
+ } else {
+ dmic->sysclk = clk_id;
+ dmic->fclk_freq = freq;
}
- dmic->sysclk = clk_id;
- dmic->fclk_freq = freq;
-
-err_busy:
clk_put(mux);
clk_put(parent_clk);
diff --git a/sound/soc/ti/omap-hdmi.c b/sound/soc/ti/omap-hdmi.c
index 55e7cb96858f..e60f5b483fc5 100644
--- a/sound/soc/ti/omap-hdmi.c
+++ b/sound/soc/ti/omap-hdmi.c
@@ -49,7 +49,7 @@ static void hdmi_dai_abort(struct device *dev)
{
struct hdmi_audio_data *ad = dev_get_drvdata(dev);
- mutex_lock(&ad->current_stream_lock);
+ guard(mutex)(&ad->current_stream_lock);
if (ad->current_stream && ad->current_stream->runtime &&
snd_pcm_running(ad->current_stream)) {
dev_err(dev, "HDMI display disabled, aborting playback\n");
@@ -57,7 +57,6 @@ static void hdmi_dai_abort(struct device *dev)
snd_pcm_stop(ad->current_stream, SNDRV_PCM_STATE_DISCONNECTED);
snd_pcm_stream_unlock_irq(ad->current_stream);
}
- mutex_unlock(&ad->current_stream_lock);
}
static int hdmi_dai_startup(struct snd_pcm_substream *substream,
@@ -86,16 +85,14 @@ static int hdmi_dai_startup(struct snd_pcm_substream *substream,
snd_soc_dai_set_dma_data(dai, substream, &ad->dma_data);
- mutex_lock(&ad->current_stream_lock);
- ad->current_stream = substream;
- mutex_unlock(&ad->current_stream_lock);
+ scoped_guard(mutex, &ad->current_stream_lock)
+ ad->current_stream = substream;
ret = ad->ops->audio_startup(ad->dssdev, hdmi_dai_abort);
if (ret) {
- mutex_lock(&ad->current_stream_lock);
- ad->current_stream = NULL;
- mutex_unlock(&ad->current_stream_lock);
+ scoped_guard(mutex, &ad->current_stream_lock)
+ ad->current_stream = NULL;
}
return ret;
@@ -261,9 +258,8 @@ static void hdmi_dai_shutdown(struct snd_pcm_substream *substream,
ad->ops->audio_shutdown(ad->dssdev);
- mutex_lock(&ad->current_stream_lock);
- ad->current_stream = NULL;
- mutex_unlock(&ad->current_stream_lock);
+ scoped_guard(mutex, &ad->current_stream_lock)
+ ad->current_stream = NULL;
}
static const struct snd_soc_dai_ops hdmi_dai_ops = {
diff --git a/sound/soc/ti/omap-mcbsp-st.c b/sound/soc/ti/omap-mcbsp-st.c
index 901578896ef3..b762d5d3e33b 100644
--- a/sound/soc/ti/omap-mcbsp-st.c
+++ b/sound/soc/ti/omap-mcbsp-st.c
@@ -156,7 +156,7 @@ static int omap_mcbsp_st_set_chgain(struct omap_mcbsp *mcbsp, int channel,
if (!st_data)
return -ENOENT;
- spin_lock_irq(&mcbsp->lock);
+ guard(spinlock_irq)(&mcbsp->lock);
if (channel == 0)
st_data->ch0gain = chgain;
else if (channel == 1)
@@ -166,7 +166,6 @@ static int omap_mcbsp_st_set_chgain(struct omap_mcbsp *mcbsp, int channel,
if (st_data->enabled)
omap_mcbsp_st_chgain(mcbsp);
- spin_unlock_irq(&mcbsp->lock);
return ret;
}
@@ -180,14 +179,13 @@ static int omap_mcbsp_st_get_chgain(struct omap_mcbsp *mcbsp, int channel,
if (!st_data)
return -ENOENT;
- spin_lock_irq(&mcbsp->lock);
+ guard(spinlock_irq)(&mcbsp->lock);
if (channel == 0)
*chgain = st_data->ch0gain;
else if (channel == 1)
*chgain = st_data->ch1gain;
else
ret = -EINVAL;
- spin_unlock_irq(&mcbsp->lock);
return ret;
}
@@ -199,10 +197,9 @@ static int omap_mcbsp_st_enable(struct omap_mcbsp *mcbsp)
if (!st_data)
return -ENODEV;
- spin_lock_irq(&mcbsp->lock);
+ guard(spinlock_irq)(&mcbsp->lock);
st_data->enabled = 1;
omap_mcbsp_st_start(mcbsp);
- spin_unlock_irq(&mcbsp->lock);
return 0;
}
@@ -215,10 +212,9 @@ static int omap_mcbsp_st_disable(struct omap_mcbsp *mcbsp)
if (!st_data)
return -ENODEV;
- spin_lock_irq(&mcbsp->lock);
+ guard(spinlock_irq)(&mcbsp->lock);
omap_mcbsp_st_stop(mcbsp);
st_data->enabled = 0;
- spin_unlock_irq(&mcbsp->lock);
return ret;
}
@@ -241,13 +237,12 @@ static ssize_t st_taps_show(struct device *dev,
ssize_t status = 0;
int i;
- spin_lock_irq(&mcbsp->lock);
+ guard(spinlock_irq)(&mcbsp->lock);
for (i = 0; i < st_data->nr_taps; i++)
status += sysfs_emit_at(buf, status, (i ? ", %d" : "%d"),
st_data->taps[i]);
if (i)
status += sysfs_emit_at(buf, status, "\n");
- spin_unlock_irq(&mcbsp->lock);
return status;
}
@@ -260,19 +255,17 @@ static ssize_t st_taps_store(struct device *dev,
struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
int val, tmp, status, i = 0;
- spin_lock_irq(&mcbsp->lock);
+ guard(spinlock_irq)(&mcbsp->lock);
memset(st_data->taps, 0, sizeof(st_data->taps));
st_data->nr_taps = 0;
do {
status = sscanf(buf, "%d%n", &val, &tmp);
if (status < 0 || status == 0) {
- size = -EINVAL;
- goto out;
+ return -EINVAL;
}
if (val < -32768 || val > 32767) {
- size = -EINVAL;
- goto out;
+ return -EINVAL;
}
st_data->taps[i++] = val;
buf += tmp;
@@ -283,9 +276,6 @@ static ssize_t st_taps_store(struct device *dev,
st_data->nr_taps = i;
-out:
- spin_unlock_irq(&mcbsp->lock);
-
return size;
}
diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c
index 411970399271..26af616c33f5 100644
--- a/sound/soc/ti/omap-mcbsp.c
+++ b/sound/soc/ti/omap-mcbsp.c
@@ -290,25 +290,24 @@ static u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp)
static int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
{
- void *reg_cache;
+ void *reg_cache __free(kfree) = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
int err;
- reg_cache = kzalloc(mcbsp->reg_cache_size, GFP_KERNEL);
if (!reg_cache)
return -ENOMEM;
- spin_lock(&mcbsp->lock);
- if (!mcbsp->free) {
- dev_err(mcbsp->dev, "McBSP%d is currently in use\n", mcbsp->id);
- err = -EBUSY;
- goto err_kfree;
- }
+ scoped_guard(spinlock, &mcbsp->lock) {
+ if (!mcbsp->free) {
+ dev_err(mcbsp->dev, "McBSP%d is currently in use\n", mcbsp->id);
+ return -EBUSY;
+ }
- mcbsp->free = false;
- mcbsp->reg_cache = reg_cache;
- spin_unlock(&mcbsp->lock);
+ mcbsp->free = false;
+ mcbsp->reg_cache = reg_cache;
+ reg_cache = NULL;
+ }
- if(mcbsp->pdata->ops && mcbsp->pdata->ops->request)
+ if (mcbsp->pdata->ops && mcbsp->pdata->ops->request)
mcbsp->pdata->ops->request(mcbsp->id - 1);
/*
@@ -323,43 +322,40 @@ static int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
"McBSP", (void *)mcbsp);
if (err != 0) {
dev_err(mcbsp->dev, "Unable to request IRQ\n");
- goto err_clk_disable;
}
} else {
err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler, 0,
"McBSP TX", (void *)mcbsp);
if (err != 0) {
dev_err(mcbsp->dev, "Unable to request TX IRQ\n");
- goto err_clk_disable;
- }
-
- err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0,
- "McBSP RX", (void *)mcbsp);
- if (err != 0) {
- dev_err(mcbsp->dev, "Unable to request RX IRQ\n");
- goto err_free_irq;
+ } else {
+ err = request_irq(mcbsp->rx_irq, omap_mcbsp_rx_irq_handler, 0,
+ "McBSP RX", (void *)mcbsp);
+ if (err != 0) {
+ dev_err(mcbsp->dev, "Unable to request RX IRQ\n");
+ free_irq(mcbsp->tx_irq, (void *)mcbsp);
+ }
}
}
- return 0;
-err_free_irq:
- free_irq(mcbsp->tx_irq, (void *)mcbsp);
-err_clk_disable:
- if(mcbsp->pdata->ops && mcbsp->pdata->ops->free)
- mcbsp->pdata->ops->free(mcbsp->id - 1);
+ if (err != 0) {
+ if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
+ mcbsp->pdata->ops->free(mcbsp->id - 1);
- /* Disable wakeup behavior */
- if (mcbsp->pdata->has_wakeup)
- MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
+ /* Disable wakeup behavior */
+ if (mcbsp->pdata->has_wakeup)
+ MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
- spin_lock(&mcbsp->lock);
- mcbsp->free = true;
- mcbsp->reg_cache = NULL;
-err_kfree:
- spin_unlock(&mcbsp->lock);
- kfree(reg_cache);
+ scoped_guard(spinlock, &mcbsp->lock) {
+ reg_cache = mcbsp->reg_cache;
+ mcbsp->free = true;
+ mcbsp->reg_cache = NULL;
+ }
- return err;
+ return err;
+ }
+
+ return 0;
}
static void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
@@ -395,13 +391,13 @@ static void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
if (!mcbsp_omap1())
omap2_mcbsp_set_clks_src(mcbsp, MCBSP_CLKS_PRCM_SRC);
- spin_lock(&mcbsp->lock);
- if (mcbsp->free)
- dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id);
- else
- mcbsp->free = true;
- mcbsp->reg_cache = NULL;
- spin_unlock(&mcbsp->lock);
+ scoped_guard(spinlock, &mcbsp->lock) {
+ if (mcbsp->free)
+ dev_err(mcbsp->dev, "McBSP%d was not reserved\n", mcbsp->id);
+ else
+ mcbsp->free = true;
+ mcbsp->reg_cache = NULL;
+ }
kfree(reg_cache);
}
@@ -581,16 +577,12 @@ static ssize_t dma_op_mode_store(struct device *dev,
if (i < 0)
return i;
- spin_lock_irq(&mcbsp->lock);
+ guard(spinlock_irq)(&mcbsp->lock);
if (!mcbsp->free) {
- size = -EBUSY;
- goto unlock;
+ return -EBUSY;
}
mcbsp->dma_op_mode = i;
-unlock:
- spin_unlock_irq(&mcbsp->lock);
-
return size;
}
diff --git a/sound/soc/ti/omap-mcpdm.c b/sound/soc/ti/omap-mcpdm.c
index 1a5d19937c64..5698d2f26973 100644
--- a/sound/soc/ti/omap-mcpdm.c
+++ b/sound/soc/ti/omap-mcpdm.c
@@ -11,7 +11,6 @@
*/
#include <linux/init.h>
-#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/interrupt.h>
@@ -251,13 +250,11 @@ static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
{
struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
- mutex_lock(&mcpdm->mutex);
+ guard(mutex)(&mcpdm->mutex);
if (!snd_soc_dai_active(dai))
omap_mcpdm_open_streams(mcpdm);
- mutex_unlock(&mcpdm->mutex);
-
return 0;
}
@@ -269,7 +266,7 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
int stream1 = tx ? SNDRV_PCM_STREAM_PLAYBACK : SNDRV_PCM_STREAM_CAPTURE;
int stream2 = tx ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
- mutex_lock(&mcpdm->mutex);
+ guard(mutex)(&mcpdm->mutex);
if (!snd_soc_dai_active(dai)) {
if (omap_mcpdm_active(mcpdm)) {
@@ -287,8 +284,6 @@ static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
cpu_latency_qos_remove_request(&mcpdm->pm_qos_req);
mcpdm->latency[stream1] = 0;
-
- mutex_unlock(&mcpdm->mutex);
}
static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
diff --git a/sound/soc/ti/omap3pandora.c b/sound/soc/ti/omap3pandora.c
index f11b1d8a1306..6c9c184cd9d6 100644
--- a/sound/soc/ti/omap3pandora.c
+++ b/sound/soc/ti/omap3pandora.c
@@ -11,12 +11,12 @@
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
-#include <asm/mach-types.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
#include "omap-mcbsp.h"
@@ -225,7 +225,8 @@ static int __init omap3pandora_soc_init(void)
{
int ret;
- if (!machine_is_omap3_pandora())
+ if (!of_machine_is_compatible("openpandora,omap3-pandora-600mhz") &&
+ !of_machine_is_compatible("openpandora,omap3-pandora-1ghz"))
return -ENODEV;
pr_info("OMAP3 Pandora SoC init\n");
diff --git a/sound/soc/ti/rx51.c b/sound/soc/ti/rx51.c
index 7eeb12e5066c..cfc23e0838c2 100644
--- a/sound/soc/ti/rx51.c
+++ b/sound/soc/ti/rx51.c
@@ -19,8 +19,6 @@
#include <sound/soc.h>
#include <linux/platform_data/asoc-ti-mcbsp.h>
-#include <asm/mach-types.h>
-
#include "omap-mcbsp.h"
enum {
@@ -364,7 +362,7 @@ static int rx51_soc_probe(struct platform_device *pdev)
struct snd_soc_card *card = &rx51_sound_card;
int err;
- if (!machine_is_nokia_rx51() && !of_machine_is_compatible("nokia,omap3-n900"))
+ if (!of_machine_is_compatible("nokia,omap3-n900"))
return -ENODEV;
card->dev = &pdev->dev;
diff --git a/sound/soc/uniphier/aio-compress.c b/sound/soc/uniphier/aio-compress.c
index b18af98a552b..57247a03b5c9 100644
--- a/sound/soc/uniphier/aio-compress.c
+++ b/sound/soc/uniphier/aio-compress.c
@@ -183,18 +183,16 @@ static int uniphier_aio_compr_prepare(struct snd_soc_component *component,
struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
int bytes = runtime->fragment_size;
- unsigned long flags;
int ret;
ret = aiodma_ch_set_param(sub);
if (ret)
return ret;
- spin_lock_irqsave(&sub->lock, flags);
- ret = aiodma_rb_set_buffer(sub, sub->compr_addr,
- sub->compr_addr + sub->compr_bytes,
- bytes);
- spin_unlock_irqrestore(&sub->lock, flags);
+ scoped_guard(spinlock_irqsave, &sub->lock)
+ ret = aiodma_rb_set_buffer(sub, sub->compr_addr,
+ sub->compr_addr + sub->compr_bytes,
+ bytes);
if (ret)
return ret;
@@ -223,9 +221,8 @@ static int uniphier_aio_compr_trigger(struct snd_soc_component *component,
struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
struct device *dev = &aio->chip->pdev->dev;
int bytes = runtime->fragment_size, ret = 0;
- unsigned long flags;
- spin_lock_irqsave(&sub->lock, flags);
+ guard(spinlock_irqsave)(&sub->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes);
@@ -242,7 +239,6 @@ static int uniphier_aio_compr_trigger(struct snd_soc_component *component,
dev_warn(dev, "Unknown trigger(%d)\n", cmd);
ret = -EINVAL;
}
- spin_unlock_irqrestore(&sub->lock, flags);
return ret;
}
@@ -256,10 +252,9 @@ static int uniphier_aio_compr_pointer(struct snd_soc_component *component,
struct uniphier_aio *aio = uniphier_priv(snd_soc_rtd_to_cpu(rtd, 0));
struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
int bytes = runtime->fragment_size;
- unsigned long flags;
u32 pos;
- spin_lock_irqsave(&sub->lock, flags);
+ guard(spinlock_irqsave)(&sub->lock);
aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes);
@@ -273,8 +268,6 @@ static int uniphier_aio_compr_pointer(struct snd_soc_component *component,
}
tstamp->byte_offset = pos;
- spin_unlock_irqrestore(&sub->lock, flags);
-
return 0;
}
@@ -332,7 +325,6 @@ static int uniphier_aio_compr_copy(struct snd_soc_component *component,
struct uniphier_aio_sub *sub = &aio->sub[cstream->direction];
size_t cnt = min_t(size_t, count, aio_rb_space_to_end(sub) / 2);
int bytes = runtime->fragment_size;
- unsigned long flags;
size_t s;
int ret;
@@ -360,7 +352,7 @@ static int uniphier_aio_compr_copy(struct snd_soc_component *component,
if (ret)
return -EFAULT;
- spin_lock_irqsave(&sub->lock, flags);
+ guard(spinlock_irqsave)(&sub->lock);
sub->threshold = 2 * bytes;
aiodma_rb_set_threshold(sub, sub->compr_bytes, 2 * bytes);
@@ -376,8 +368,6 @@ static int uniphier_aio_compr_copy(struct snd_soc_component *component,
}
aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes);
- spin_unlock_irqrestore(&sub->lock, flags);
-
return cnt;
}
diff --git a/sound/soc/uniphier/aio-dma.c b/sound/soc/uniphier/aio-dma.c
index c1ca55997103..c01eae55d4fc 100644
--- a/sound/soc/uniphier/aio-dma.c
+++ b/sound/soc/uniphier/aio-dma.c
@@ -32,15 +32,15 @@ static void aiodma_pcm_irq(struct uniphier_aio_sub *sub)
runtime->channels * samples_to_bytes(runtime, 1);
int ret;
- spin_lock(&sub->lock);
- ret = aiodma_rb_set_threshold(sub, runtime->dma_bytes,
- sub->threshold + bytes);
- if (!ret)
- sub->threshold += bytes;
-
- aiodma_rb_sync(sub, runtime->dma_addr, runtime->dma_bytes, bytes);
- aiodma_rb_clear_irq(sub);
- spin_unlock(&sub->lock);
+ scoped_guard(spinlock, &sub->lock) {
+ ret = aiodma_rb_set_threshold(sub, runtime->dma_bytes,
+ sub->threshold + bytes);
+ if (!ret)
+ sub->threshold += bytes;
+
+ aiodma_rb_sync(sub, runtime->dma_addr, runtime->dma_bytes, bytes);
+ aiodma_rb_clear_irq(sub);
+ }
snd_pcm_period_elapsed(sub->substream);
}
@@ -51,15 +51,15 @@ static void aiodma_compr_irq(struct uniphier_aio_sub *sub)
int bytes = runtime->fragment_size;
int ret;
- spin_lock(&sub->lock);
- ret = aiodma_rb_set_threshold(sub, sub->compr_bytes,
- sub->threshold + bytes);
- if (!ret)
- sub->threshold += bytes;
+ scoped_guard(spinlock, &sub->lock) {
+ ret = aiodma_rb_set_threshold(sub, sub->compr_bytes,
+ sub->threshold + bytes);
+ if (!ret)
+ sub->threshold += bytes;
- aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes);
- aiodma_rb_clear_irq(sub);
- spin_unlock(&sub->lock);
+ aiodma_rb_sync(sub, sub->compr_addr, sub->compr_bytes, bytes);
+ aiodma_rb_clear_irq(sub);
+ }
snd_compr_fragment_elapsed(sub->cstream);
}
@@ -113,18 +113,16 @@ static int uniphier_aiodma_prepare(struct snd_soc_component *component,
struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
int bytes = runtime->period_size *
runtime->channels * samples_to_bytes(runtime, 1);
- unsigned long flags;
int ret;
ret = aiodma_ch_set_param(sub);
if (ret)
return ret;
- spin_lock_irqsave(&sub->lock, flags);
- ret = aiodma_rb_set_buffer(sub, runtime->dma_addr,
- runtime->dma_addr + runtime->dma_bytes,
- bytes);
- spin_unlock_irqrestore(&sub->lock, flags);
+ scoped_guard(spinlock_irqsave, &sub->lock)
+ ret = aiodma_rb_set_buffer(sub, runtime->dma_addr,
+ runtime->dma_addr + runtime->dma_bytes,
+ bytes);
if (ret)
return ret;
@@ -141,9 +139,8 @@ static int uniphier_aiodma_trigger(struct snd_soc_component *component,
struct device *dev = &aio->chip->pdev->dev;
int bytes = runtime->period_size *
runtime->channels * samples_to_bytes(runtime, 1);
- unsigned long flags;
- spin_lock_irqsave(&sub->lock, flags);
+ guard(spinlock_irqsave)(&sub->lock);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
aiodma_rb_sync(sub, runtime->dma_addr, runtime->dma_bytes,
@@ -161,7 +158,6 @@ static int uniphier_aiodma_trigger(struct snd_soc_component *component,
dev_warn(dev, "Unknown trigger(%d) ignored\n", cmd);
break;
}
- spin_unlock_irqrestore(&sub->lock, flags);
return 0;
}
@@ -176,17 +172,15 @@ static snd_pcm_uframes_t uniphier_aiodma_pointer(
struct uniphier_aio_sub *sub = &aio->sub[substream->stream];
int bytes = runtime->period_size *
runtime->channels * samples_to_bytes(runtime, 1);
- unsigned long flags;
snd_pcm_uframes_t pos;
- spin_lock_irqsave(&sub->lock, flags);
+ guard(spinlock_irqsave)(&sub->lock);
aiodma_rb_sync(sub, runtime->dma_addr, runtime->dma_bytes, bytes);
if (sub->swm->dir == PORT_DIR_OUTPUT)
pos = bytes_to_frames(runtime, sub->rd_offs);
else
pos = bytes_to_frames(runtime, sub->wr_offs);
- spin_unlock_irqrestore(&sub->lock, flags);
return pos;
}
diff --git a/sound/soc/ux500/mop500_ab8500.c b/sound/soc/ux500/mop500_ab8500.c
index 2e6ed19a18cd..2a459267f0f9 100644
--- a/sound/soc/ux500/mop500_ab8500.c
+++ b/sound/soc/ux500/mop500_ab8500.c
@@ -234,19 +234,18 @@ static int mop500_ab8500_hw_params(struct snd_pcm_substream *substream,
substream->number);
/* Ensure configuration consistency between DAIs */
- mutex_lock(&mop500_ab8500_params_lock);
- if (mop500_ab8500_usage) {
- if (mop500_ab8500_rate != params_rate(params) ||
- mop500_ab8500_channels != params_channels(params)) {
- mutex_unlock(&mop500_ab8500_params_lock);
- return -EBUSY;
+ scoped_guard(mutex, &mop500_ab8500_params_lock) {
+ if (mop500_ab8500_usage) {
+ if (mop500_ab8500_rate != params_rate(params) ||
+ mop500_ab8500_channels != params_channels(params)) {
+ return -EBUSY;
+ }
+ } else {
+ mop500_ab8500_rate = params_rate(params);
+ mop500_ab8500_channels = params_channels(params);
}
- } else {
- mop500_ab8500_rate = params_rate(params);
- mop500_ab8500_channels = params_channels(params);
+ __set_bit(cpu_dai->id, &mop500_ab8500_usage);
}
- __set_bit(cpu_dai->id, &mop500_ab8500_usage);
- mutex_unlock(&mop500_ab8500_params_lock);
channels = params_channels(params);
@@ -339,9 +338,8 @@ static int mop500_ab8500_hw_free(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream);
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
- mutex_lock(&mop500_ab8500_params_lock);
+ guard(mutex)(&mop500_ab8500_params_lock);
__clear_bit(cpu_dai->id, &mop500_ab8500_usage);
- mutex_unlock(&mop500_ab8500_params_lock);
return 0;
}
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index 2ed01e9d79bb..01ad5b12b680 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -132,19 +132,15 @@ snd_emux_create_port(struct snd_emux *emu, char *name,
int i, type, cap;
/* Allocate structures for this channel */
- p = kzalloc_obj(*p);
+ p = kzalloc_flex(*p, chset.channels, max_channels);
if (!p)
return NULL;
- p->chset.channels = kzalloc_objs(*p->chset.channels, max_channels);
- if (!p->chset.channels) {
- kfree(p);
- return NULL;
- }
+ p->chset.max_channels = max_channels;
+
for (i = 0; i < max_channels; i++)
p->chset.channels[i].number = i;
p->chset.private_data = p;
- p->chset.max_channels = max_channels;
p->emu = emu;
p->chset.client = emu->client;
#ifdef SNDRV_EMUX_USE_RAW_EFFECT
@@ -182,7 +178,6 @@ free_port(void *private_data)
#ifdef SNDRV_EMUX_USE_RAW_EFFECT
snd_emux_delete_effect(p);
#endif
- kfree(p->chset.channels);
kfree(p);
}
}
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
index c77a21a9acd7..10104cb42165 100644
--- a/sound/usb/6fire/control.c
+++ b/sound/usb/6fire/control.c
@@ -582,30 +582,31 @@ int usb6fire_control_init(struct sfire_chip *chip)
"Master Playback Volume", vol_elements);
if (ret) {
dev_err(&chip->dev->dev, "cannot add control.\n");
- kfree(rt);
- return ret;
+ goto free_rt;
}
ret = usb6fire_control_add_virtual(rt, chip->card,
"Master Playback Switch", mute_elements);
if (ret) {
dev_err(&chip->dev->dev, "cannot add control.\n");
- kfree(rt);
- return ret;
+ goto free_rt;
}
i = 0;
while (elements[i].name) {
ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt));
if (ret < 0) {
- kfree(rt);
dev_err(&chip->dev->dev, "cannot add control.\n");
- return ret;
+ goto free_rt;
}
i++;
}
chip->control = rt;
return 0;
+
+free_rt:
+ kfree(rt);
+ return ret;
}
void usb6fire_control_abort(struct sfire_chip *chip)
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index 5c70fdf61cc1..eabbf41fdfb2 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -237,12 +237,16 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *cdev,
switch (cdev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
+ if (len < 2)
+ return;
i = decode_erp(buf[0], buf[1]);
input_report_abs(input_dev, ABS_X, i);
input_sync(input_dev);
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
+ if (len < 16)
+ return;
i = decode_erp(buf[7], buf[5]);
input_report_abs(input_dev, ABS_HAT0X, i);
i = decode_erp(buf[12], buf[14]);
@@ -263,6 +267,8 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *cdev,
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
+ if (len < 22)
+ return;
/* 4 under the left screen */
input_report_abs(input_dev, ABS_HAT0X, decode_erp(buf[21], buf[20]));
input_report_abs(input_dev, ABS_HAT0Y, decode_erp(buf[15], buf[14]));
@@ -308,9 +314,13 @@ static void snd_caiaq_input_read_io(struct snd_usb_caiaqdev *cdev,
switch (cdev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
+ if (len < 5)
+ return;
input_report_abs(cdev->input_dev, ABS_MISC, 255 - buf[4]);
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
+ if (len < 7)
+ return;
/* rotary encoders */
input_report_abs(cdev->input_dev, ABS_X, buf[5] & 0xf);
input_report_abs(cdev->input_dev, ABS_Y, buf[5] >> 4);
@@ -330,7 +340,7 @@ static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *cdev,
{
struct device *dev = caiaqdev_to_dev(cdev);
- while (len) {
+ while (len >= TKS4_MSGBLOCK_SIZE) {
unsigned int i, block_id = (buf[0] << 8) | buf[1];
switch (block_id) {
diff --git a/sound/usb/card.c b/sound/usb/card.c
index f42d72cd0378..6a3b576fb067 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -769,7 +769,6 @@ static int snd_usb_audio_create(struct usb_interface *intf,
chip = card->private_data;
mutex_init(&chip->mutex);
- init_waitqueue_head(&chip->shutdown_wait);
chip->index = idx;
chip->dev = dev;
chip->card = card;
@@ -778,7 +777,7 @@ static int snd_usb_audio_create(struct usb_interface *intf,
chip->autoclock = autoclock;
chip->lowlatency = lowlatency;
atomic_set(&chip->active, 1); /* avoid autopm during probing */
- atomic_set(&chip->usage_count, 0);
+ snd_refcount_init(&chip->usage_count);
atomic_set(&chip->shutdown, 0);
chip->usb_id = usb_id;
@@ -1107,8 +1106,7 @@ static bool __usb_audio_disconnect(struct usb_interface *intf,
/* wait until all pending tasks done;
* they are protected by snd_usb_lock_shutdown()
*/
- wait_event(chip->shutdown_wait,
- !atomic_read(&chip->usage_count));
+ snd_refcount_sync(&chip->usage_count);
snd_card_disconnect(card);
/* release the pcm resources */
list_for_each_entry(as, &chip->pcm_list, list) {
@@ -1166,7 +1164,7 @@ int snd_usb_lock_shutdown(struct snd_usb_audio *chip)
{
int err;
- atomic_inc(&chip->usage_count);
+ snd_refcount_get(&chip->usage_count);
if (atomic_read(&chip->shutdown)) {
err = -EIO;
goto error;
@@ -1177,8 +1175,7 @@ int snd_usb_lock_shutdown(struct snd_usb_audio *chip)
return 0;
error:
- if (atomic_dec_and_test(&chip->usage_count))
- wake_up(&chip->shutdown_wait);
+ snd_refcount_put(&chip->usage_count);
return err;
}
EXPORT_SYMBOL_GPL(snd_usb_lock_shutdown);
@@ -1187,8 +1184,7 @@ EXPORT_SYMBOL_GPL(snd_usb_lock_shutdown);
void snd_usb_unlock_shutdown(struct snd_usb_audio *chip)
{
snd_usb_autosuspend(chip);
- if (atomic_dec_and_test(&chip->usage_count))
- wake_up(&chip->shutdown_wait);
+ snd_refcount_put(&chip->usage_count);
}
EXPORT_SYMBOL_GPL(snd_usb_unlock_shutdown);
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 6fbcb117555c..24cd7692bd01 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -1780,8 +1780,16 @@ static void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
/*
* skip empty packets. At least M-Audio's Fast Track Ultra stops
* streaming once it received a 0-byte OUT URB
+ *
+ * However, on devices where bytes==0 means every sync-source
+ * packet errored (e.g. Behringer Flow 8 returning -EXDEV bursts
+ * for entire capture URBs), an unconditional return starves the
+ * IFB-fed OUT ring permanently. Such devices set
+ * QUIRK_FLAG_IFB_SILENCE_ON_EMPTY to fall through and enqueue a
+ * packet_info with size 0 packets, so playback emits silence
+ * and the OUT ring keeps moving.
*/
- if (bytes == 0)
+ if (bytes == 0 && !(ep->chip->quirk_flags & QUIRK_FLAG_IFB_SILENCE_ON_EMPTY))
return;
spin_lock_irqsave(&ep->lock, flags);
diff --git a/sound/usb/fcp.c b/sound/usb/fcp.c
index 0fc4d063c48a..6f5dcd35e1d4 100644
--- a/sound/usb/fcp.c
+++ b/sound/usb/fcp.c
@@ -191,13 +191,13 @@ static int fcp_usb(struct usb_mixer_interface *mixer, u32 opcode,
struct fcp_usb_packet *req __free(kfree) = NULL;
size_t req_buf_size = struct_size(req, data, req_size);
- req = kmalloc(req_buf_size, GFP_KERNEL);
+ req = kmalloc_flex(*req, data, req_size);
if (!req)
return -ENOMEM;
struct fcp_usb_packet *resp __free(kfree) = NULL;
size_t resp_buf_size = struct_size(resp, data, resp_size);
- resp = kmalloc(resp_buf_size, GFP_KERNEL);
+ resp = kmalloc_flex(*resp, data, resp_size);
if (!resp)
return -ENOMEM;
@@ -1083,6 +1083,8 @@ static int fcp_find_fc_interface(struct usb_mixer_interface *mixer)
if (desc->bInterfaceClass != 255)
continue;
+ if (desc->bNumEndpoints < 1)
+ continue;
epd = get_endpoint(intf->altsetting, 0);
private->bInterfaceNumber = desc->bInterfaceNumber;
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 0a5b8941ebda..d87e3f357cf7 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -1951,15 +1951,17 @@ static struct usb_ms_endpoint_descriptor *find_usb_ms_endpoint_descriptor(
while (extralen > 3) {
struct usb_ms_endpoint_descriptor *ms_ep =
(struct usb_ms_endpoint_descriptor *)extra;
+ int length = ms_ep->bLength;
- if (ms_ep->bLength > 3 &&
+ if (!length || length > extralen)
+ break;
+
+ if (length > 3 &&
ms_ep->bDescriptorType == USB_DT_CS_ENDPOINT &&
ms_ep->bDescriptorSubtype == UAC_MS_GENERAL)
return ms_ep;
- if (!extra[0])
- break;
- extralen -= extra[0];
- extra += extra[0];
+ extralen -= length;
+ extra += length;
}
return NULL;
}
diff --git a/sound/usb/midi2.c b/sound/usb/midi2.c
index 2785600d2312..3ec633291772 100644
--- a/sound/usb/midi2.c
+++ b/sound/usb/midi2.c
@@ -470,6 +470,11 @@ static int create_midi2_endpoint(struct snd_usb_midi2_interface *umidi,
static void free_midi2_endpoint(struct snd_usb_midi2_endpoint *ep)
{
list_del(&ep->list);
+ if (!ep->disconnected) {
+ ep->disconnected = 1;
+ kill_midi_urbs(ep, false);
+ drain_urb_queue(ep);
+ }
free_midi_urbs(ep);
kfree(ep);
}
@@ -496,15 +501,17 @@ static void *find_usb_ms_endpoint_descriptor(struct usb_host_endpoint *hostep,
while (extralen > 3) {
struct usb_ms_endpoint_descriptor *ms_ep =
(struct usb_ms_endpoint_descriptor *)extra;
+ int length = ms_ep->bLength;
- if (ms_ep->bLength > 3 &&
+ if (!length || length > extralen)
+ break;
+
+ if (length > 3 &&
ms_ep->bDescriptorType == USB_DT_CS_ENDPOINT &&
ms_ep->bDescriptorSubtype == subtype)
return ms_ep;
- if (!extra[0])
- break;
- extralen -= extra[0];
- extra += extra[0];
+ extralen -= length;
+ extra += length;
}
return NULL;
}
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index d129b42eb979..b9a62e94e06c 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -894,8 +894,9 @@ find_format_descriptor(struct usb_interface *interface)
struct uac_format_type_i_discrete_descriptor *desc;
desc = (struct uac_format_type_i_discrete_descriptor *)extra;
- if (desc->bLength > extralen) {
- dev_err(&interface->dev, "descriptor overflow\n");
+ if (desc->bLength < sizeof(struct usb_descriptor_header) ||
+ desc->bLength > extralen) {
+ dev_err(&interface->dev, "invalid descriptor length\n");
return NULL;
}
if (desc->bLength == UAC_FORMAT_TYPE_I_DISCRETE_DESC_SIZE(1) &&
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index 5fba456eb4a9..b4c855c25eef 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -434,6 +434,11 @@ int snd_usb_get_cur_mix_value(struct usb_mixer_elem_info *cval,
*value = cval->cache_val[index];
return 0;
}
+
+ /* The current value is always provided by the cache after initialization. */
+ if (cval->get_cur_broken)
+ return -ENXIO;
+
err = get_cur_mix_raw(cval, channel, value);
if (err < 0) {
if (!cval->head.mixer->ignore_ctl_error)
@@ -665,17 +670,13 @@ static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iter
return 0;
switch (iterm->type >> 16) {
case UAC3_SELECTOR_UNIT:
- strscpy(name, "Selector", maxlen);
- return 8;
+ return strscpy(name, "Selector", maxlen);
case UAC3_PROCESSING_UNIT:
- strscpy(name, "Process Unit", maxlen);
- return 12;
+ return strscpy(name, "Process Unit", maxlen);
case UAC3_EXTENSION_UNIT:
- strscpy(name, "Ext Unit", maxlen);
- return 8;
+ return strscpy(name, "Ext Unit", maxlen);
case UAC3_MIXER_UNIT:
- strscpy(name, "Mixer", maxlen);
- return 5;
+ return strscpy(name, "Mixer", maxlen);
default:
return scnprintf(name, maxlen, "Unit %d", iterm->id);
}
@@ -683,25 +684,18 @@ static int get_term_name(struct snd_usb_audio *chip, struct usb_audio_term *iter
switch (iterm->type & 0xff00) {
case 0x0100:
- strscpy(name, "PCM", maxlen);
- return 3;
+ return strscpy(name, "PCM", maxlen);
case 0x0200:
- strscpy(name, "Mic", maxlen);
- return 3;
+ return strscpy(name, "Mic", maxlen);
case 0x0400:
- strscpy(name, "Headset", maxlen);
- return 7;
+ return strscpy(name, "Headset", maxlen);
case 0x0500:
- strscpy(name, "Phone", maxlen);
- return 5;
+ return strscpy(name, "Phone", maxlen);
}
- for (names = iterm_names; names->type; names++) {
- if (names->type == iterm->type) {
- strscpy(name, names->name, maxlen);
- return strlen(names->name);
- }
- }
+ for (names = iterm_names; names->type; names++)
+ if (names->type == iterm->type)
+ return strscpy(name, names->name, maxlen);
return 0;
}
@@ -1234,7 +1228,7 @@ static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx)
err = snd_usb_get_cur_mix_value(cval, ch, idx, &val);
if (!err)
return;
- if (!cval->head.mixer->ignore_ctl_error)
+ if (!cval->head.mixer->ignore_ctl_error && !cval->get_cur_broken)
usb_audio_warn(cval->head.mixer->chip,
"%d:%d: failed to get current value for ch %d (%d)\n",
cval->head.id, mixer_ctrl_intf(cval->head.mixer),
@@ -1248,8 +1242,16 @@ static void init_cur_mix_raw(struct usb_mixer_elem_info *cval, int ch, int idx)
* Some devices' volume control mixers are sticky, which accept SET_CUR but
* do absolutely nothing.
*
- * Prevent sticky mixers from being registered, otherwise they confuses
- * userspace and results in ineffective volume control.
+ * Check the return values of GET_CUR with different SET_CUR values. Consider
+ * the mixer as sticky if GET_CUR always returns a constant value.
+ *
+ * Some devices have effective SET_CUR despite GET_CUR being constant. Do not
+ * consider the mixer as sticky if a quirk flag indicates that.
+ *
+ * Gate the registration of sticky mixers to prevent confusing userspace, so
+ * that they won't cause ineffective volume control. However, for mixers with
+ * effective SET_CUR but broken GET_CUR, the registration can continue normally
+ * but further GET_CUR requests will be gated.
*/
static int check_sticky_volume_control(struct usb_mixer_elem_info *cval,
int channel, int saved)
@@ -1269,10 +1271,22 @@ static int check_sticky_volume_control(struct usb_mixer_elem_info *cval,
return 0;
}
+ if (cval->head.mixer->chip->quirk_flags & QUIRK_FLAG_MIXER_GET_CUR_BROKEN) {
+ usb_audio_info(cval->head.mixer->chip,
+ "%d:%d: broken mixer GET_CUR (%d/%d/%d => %d)\n",
+ cval->head.id, mixer_ctrl_intf(cval->head.mixer),
+ cval->min, cval->max, cval->res, saved);
+
+ cval->get_cur_broken = 1;
+ return -ENXIO;
+ }
+
usb_audio_err(cval->head.mixer->chip,
"%d:%d: sticky mixer values (%d/%d/%d => %d), disabling\n",
cval->head.id, mixer_ctrl_intf(cval->head.mixer),
cval->min, cval->max, cval->res, saved);
+ usb_audio_info(cval->head.mixer->chip,
+ "check MIXER_GET_CUR_BROKEN if you believe the mixer is non-sticky");
return -ENODEV;
}
@@ -1315,7 +1329,7 @@ static void check_volume_control_res(struct usb_mixer_elem_info *cval,
static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
int default_min, struct snd_kcontrol *kctl)
{
- int i, idx, ret;
+ int i, idx, ret = 0;
/* for failsafe */
cval->min = default_min;
@@ -1371,10 +1385,10 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
goto no_checks;
ret = check_sticky_volume_control(cval, minchn, saved);
- if (ret < 0) {
- snd_usb_set_cur_mix_value(cval, minchn, 0, saved);
- return ret;
- }
+ if (ret == -ENODEV)
+ goto sticky;
+ if (ret)
+ goto no_checks;
if (cval->min + cval->res < cval->max)
check_volume_control_res(cval, minchn, saved);
@@ -1383,6 +1397,16 @@ static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
}
no_checks:
+ /*
+ * Got a non-fatal failure during sanity checks.
+ *
+ * Do not propagate mixer values written by sanity checks.
+ * Instead, rely on init_cur_mix_raw() to initialize the mixer
+ * properly.
+ */
+ if (ret)
+ cval->cached = 0;
+
cval->initialized = 1;
}
@@ -1431,6 +1455,33 @@ no_checks:
}
return 0;
+
+sticky:
+ /*
+ * It makes no sense to restore the saved value for a sticky mixer,
+ * since setting any value is a no-op.
+ *
+ * However, in some rare cases, SET_CUR is effective despite GET_CUR
+ * always returns a constant value. These mixers are not sticky, but
+ * there's no way to distinguish them. Without any additional
+ * information, the best thing we can do is to set the mixer value to
+ * the maximum before bailing out, so that a soft mixer can still reach
+ * the maximum hardware volume if the mixer turns out to be non-sticky.
+ * Meanwhile, all channels must be synchronized to prevent imbalance
+ * volume.
+ */
+ if (!cval->cmask) {
+ snd_usb_set_cur_mix_value(cval, 0, 0, cval->max);
+ } else {
+ for (i = 0; i < MAX_CHANNELS; i++) {
+ idx = 0;
+ if (cval->cmask & BIT(i)) {
+ snd_usb_set_cur_mix_value(cval, i + 1, idx, cval->max);
+ idx++;
+ }
+ }
+ }
+ return ret;
}
#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL)
@@ -1536,7 +1587,10 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
return -EINVAL;
val = get_abs_value(cval, val);
if (oval != val) {
- snd_usb_set_cur_mix_value(cval, c + 1, cnt, val);
+ err = snd_usb_set_cur_mix_value(cval, c + 1,
+ cnt, val);
+ if (err < 0)
+ return filter_error(cval, err);
changed = 1;
}
cnt++;
@@ -1551,7 +1605,9 @@ static int mixer_ctl_feature_put(struct snd_kcontrol *kcontrol,
return -EINVAL;
val = get_abs_value(cval, val);
if (val != oval) {
- snd_usb_set_cur_mix_value(cval, 0, 0, val);
+ err = snd_usb_set_cur_mix_value(cval, 0, 0, val);
+ if (err < 0)
+ return filter_error(cval, err);
changed = 1;
}
}
@@ -1988,7 +2044,9 @@ 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)
- strscpy(name, "Unknown", name_size);
+ name_len = strscpy(name, "Unknown", name_size);
+ if (name_len < 0)
+ return;
/*
* sound/core/ctljack.c has a convention of naming jack controls
@@ -1996,9 +2054,9 @@ static void get_connector_control_name(struct usb_mixer_interface *mixer,
* indicating Input or Output after the terminal name.
*/
if (is_input)
- strlcat(name, " - Input Jack", name_size);
+ strscpy(name + name_len, " - Input Jack", name_size - name_len);
else
- strlcat(name, " - Output Jack", name_size);
+ strscpy(name + name_len, " - Output Jack", name_size - name_len);
}
/* get connector value to "wake up" the USB audio */
@@ -2476,7 +2534,9 @@ static int mixer_ctl_procunit_put(struct snd_kcontrol *kcontrol,
return -EINVAL;
val = get_abs_value(cval, val);
if (val != oval) {
- set_cur_ctl_value(cval, cval->control << 8, val);
+ err = set_cur_ctl_value(cval, cval->control << 8, val);
+ if (err < 0)
+ return filter_error(cval, err);
return 1;
}
return 0;
@@ -2842,7 +2902,9 @@ static int mixer_ctl_selector_put(struct snd_kcontrol *kcontrol,
return -EINVAL;
val = get_abs_value(cval, val);
if (val != oval) {
- set_cur_ctl_value(cval, cval->control << 8, val);
+ err = set_cur_ctl_value(cval, cval->control << 8, val);
+ if (err < 0)
+ return filter_error(cval, err);
return 1;
}
return 0;
@@ -3513,7 +3575,8 @@ void snd_usb_mixer_notify_id(struct usb_mixer_interface *mixer, int unitid)
continue;
info = mixer_elem_list_to_info(list);
/* invalidate cache, so the value is read from the device */
- info->cached = 0;
+ if (!info->get_cur_broken)
+ info->cached = 0;
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&list->kctl->id);
}
@@ -3610,10 +3673,12 @@ static void snd_usb_mixer_interrupt_v2(struct usb_mixer_interface *mixer,
switch (attribute) {
case UAC2_CS_CUR:
/* invalidate cache, so the value is read from the device */
- if (channel)
- info->cached &= ~BIT(channel);
- else /* master channel */
- info->cached = 0;
+ if (!info->get_cur_broken) {
+ if (channel)
+ info->cached &= ~BIT(channel);
+ else /* master channel */
+ info->cached = 0;
+ }
snd_ctl_notify(mixer->chip->card, SNDRV_CTL_EVENT_MASK_VALUE,
&info->head.kctl->id);
diff --git a/sound/usb/mixer.h b/sound/usb/mixer.h
index afbb3dd9f177..3fa1bd96f858 100644
--- a/sound/usb/mixer.h
+++ b/sound/usb/mixer.h
@@ -94,6 +94,7 @@ struct usb_mixer_elem_info {
int cache_val[MAX_CHANNELS];
u8 initialized;
u8 min_mute;
+ u8 get_cur_broken;
void *private_data;
};
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 1bdaa46d4fe1..10792d26fa94 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -333,6 +333,7 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol,
int index = kcontrol->private_value & 0xff;
unsigned int value = ucontrol->value.integer.value[0];
int old_value = kcontrol->private_value >> 8;
+ unsigned long old_pval = kcontrol->private_value;
int err;
if (value > 1)
@@ -341,7 +342,11 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol,
return 0;
kcontrol->private_value = (value << 8) | index;
err = snd_audigy2nx_led_update(mixer, value, index);
- return err < 0 ? err : 1;
+ if (err < 0) {
+ kcontrol->private_value = old_pval;
+ return err;
+ }
+ return 1;
}
static int snd_audigy2nx_led_resume(struct usb_mixer_elem_list *list)
@@ -487,6 +492,7 @@ static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol,
struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
struct usb_mixer_interface *mixer = list->mixer;
unsigned int value = ucontrol->value.enumerated.item[0];
+ unsigned long old_pval = kcontrol->private_value;
int err;
if (value > 1)
@@ -497,7 +503,11 @@ static int snd_emu0204_ch_switch_put(struct snd_kcontrol *kcontrol,
kcontrol->private_value = value;
err = snd_emu0204_ch_switch_update(mixer, value);
- return err < 0 ? err : 1;
+ if (err < 0) {
+ kcontrol->private_value = old_pval;
+ return err;
+ }
+ return 1;
}
static int snd_emu0204_ch_switch_resume(struct usb_mixer_elem_list *list)
@@ -567,46 +577,30 @@ static bool snd_dualsense_ih_match(struct input_handler *handler,
{
struct dualsense_mixer_elem_info *mei;
struct usb_device *snd_dev;
- char *input_dev_path, *usb_dev_path;
- size_t usb_dev_path_len;
- bool match = false;
+ struct device *parent;
mei = container_of(handler, struct dualsense_mixer_elem_info, ih);
snd_dev = mei->info.head.mixer->chip->dev;
- input_dev_path = kobject_get_path(&dev->dev.kobj, GFP_KERNEL);
- if (!input_dev_path) {
- dev_warn(&snd_dev->dev, "Failed to get input dev path\n");
- return false;
- }
-
- usb_dev_path = kobject_get_path(&snd_dev->dev.kobj, GFP_KERNEL);
- if (!usb_dev_path) {
- dev_warn(&snd_dev->dev, "Failed to get USB dev path\n");
- goto free_paths;
- }
-
/*
* Ensure the VID:PID matched input device supposedly owned by the
* hid-playstation driver belongs to the actual hardware handled by
- * the current USB audio device, which implies input_dev_path being
- * a subpath of usb_dev_path.
+ * the current USB audio device.
*
* This verification is necessary when there is more than one identical
* controller attached to the host system.
+ *
+ * The input device is registered below the HID device, USB interface and
+ * USB device, so compare the parent chain directly instead of building
+ * kobject path strings. This avoids dereferencing kobject names while the
+ * USB device hierarchy is being torn down during disconnect.
*/
- usb_dev_path_len = strlen(usb_dev_path);
- if (usb_dev_path_len >= strlen(input_dev_path))
- goto free_paths;
-
- usb_dev_path[usb_dev_path_len] = '/';
- match = !memcmp(input_dev_path, usb_dev_path, usb_dev_path_len + 1);
-
-free_paths:
- kfree(input_dev_path);
- kfree(usb_dev_path);
+ for (parent = dev->dev.parent; parent; parent = parent->parent) {
+ if (parent == &snd_dev->dev)
+ return true;
+ }
- return match;
+ return false;
}
static int snd_dualsense_ih_connect(struct input_handler *handler,
@@ -821,7 +815,11 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
kcontrol->private_value = new_status;
err = snd_xonar_u1_switch_update(list->mixer, new_status);
- return err < 0 ? err : 1;
+ if (err < 0) {
+ kcontrol->private_value = old_status;
+ return err;
+ }
+ return 1;
}
static int snd_xonar_u1_switch_resume(struct usb_mixer_elem_list *list)
@@ -1159,7 +1157,8 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
- u8 oldval = (kcontrol->private_value >> 24) & 0xff;
+ unsigned long old_pval = kcontrol->private_value;
+ u8 oldval = (old_pval >> 24) & 0xff;
u8 newval = ucontrol->value.integer.value[0];
int err;
@@ -1169,7 +1168,11 @@ static int snd_nativeinstruments_control_put(struct snd_kcontrol *kcontrol,
kcontrol->private_value &= ~(0xff << 24);
kcontrol->private_value |= (unsigned int)newval << 24;
err = snd_ni_update_cur_val(list);
- return err < 0 ? err : 1;
+ if (err < 0) {
+ kcontrol->private_value = old_pval;
+ return err;
+ }
+ return 1;
}
static const struct snd_kcontrol_new snd_nativeinstruments_ta6_mixers[] = {
@@ -1282,7 +1285,7 @@ static int snd_ftu_eff_switch_init(struct usb_mixer_interface *mixer,
err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
- pval & 0xff00,
+ (pval & 0xff00) | ((pval & 0xff0000) >> 16),
snd_usb_ctrl_intf(mixer->hostif) | ((pval & 0xff) << 8),
value, 2);
if (err < 0)
@@ -1315,7 +1318,7 @@ static int snd_ftu_eff_switch_update(struct usb_mixer_elem_list *list)
usb_sndctrlpipe(chip->dev, 0),
UAC_SET_CUR,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
- pval & 0xff00,
+ (pval & 0xff00) | ((pval & 0xff0000) >> 16),
snd_usb_ctrl_intf(list->mixer->hostif) | ((pval & 0xff) << 8),
value, 2);
}
@@ -1324,7 +1327,8 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
struct snd_ctl_elem_value *ucontrol)
{
struct usb_mixer_elem_list *list = snd_kcontrol_chip(kctl);
- unsigned int pval = list->kctl->private_value;
+ unsigned long old_pval = list->kctl->private_value;
+ unsigned int pval = old_pval;
int cur_val, err, new_val;
cur_val = pval >> 24;
@@ -1335,7 +1339,11 @@ static int snd_ftu_eff_switch_put(struct snd_kcontrol *kctl,
kctl->private_value &= ~(0xff << 24);
kctl->private_value |= new_val << 24;
err = snd_ftu_eff_switch_update(list);
- return err < 0 ? err : 1;
+ if (err < 0) {
+ kctl->private_value = old_pval;
+ return err;
+ }
+ return 1;
}
static int snd_ftu_create_effect_switch(struct usb_mixer_interface *mixer,
@@ -1730,6 +1738,44 @@ static int snd_c400_create_effect_ret_vol_ctls(struct usb_mixer_interface *mixer
return 0;
}
+/* output gain knob selectively adjusts outputs as stereo pairs */
+/* reuses functions from FTU effect switch */
+static int snd_c400_knob_switch_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char *const texts[8] = {
+ "None", "1/2", "3/4", "1/2 3/4",
+ "5/6", "1/2 5/6", "3/4 5/6", "1/2 3/4 5/6"
+ };
+
+ return snd_ctl_enum_info(uinfo, 1, ARRAY_SIZE(texts), texts);
+}
+
+static int snd_c400_create_knob_switch(struct usb_mixer_interface *mixer,
+ int validx, int bUnitID)
+{
+ static struct snd_kcontrol_new template = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Output Gain Knob",
+ .index = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_c400_knob_switch_info,
+ .get = snd_ftu_eff_switch_get,
+ .put = snd_ftu_eff_switch_put
+ };
+ struct usb_mixer_elem_list *list;
+ int err;
+
+ err = add_single_ctl_with_resume(mixer, bUnitID,
+ snd_ftu_eff_switch_update,
+ &template, &list);
+ if (err < 0)
+ return err;
+ list->kctl->private_value = (validx << 8) | bUnitID;
+ snd_ftu_eff_switch_init(mixer, list->kctl);
+ return 0;
+}
+
static int snd_c400_create_mixer(struct usb_mixer_interface *mixer)
{
int err;
@@ -1762,6 +1808,10 @@ static int snd_c400_create_mixer(struct usb_mixer_interface *mixer)
if (err < 0)
return err;
+ err = snd_c400_create_knob_switch(mixer, 0x0900, 0x20);
+ if (err < 0)
+ return err;
+
return 0;
}
@@ -2114,13 +2164,18 @@ static int snd_soundblaster_e1_switch_put(struct snd_kcontrol *kcontrol,
{
struct usb_mixer_elem_list *list = snd_kcontrol_chip(kcontrol);
unsigned char value = !!ucontrol->value.integer.value[0];
+ unsigned long old_pval = kcontrol->private_value;
int err;
if (kcontrol->private_value == value)
return 0;
kcontrol->private_value = value;
err = snd_soundblaster_e1_switch_update(list->mixer, value);
- return err < 0 ? err : 1;
+ if (err < 0) {
+ kcontrol->private_value = old_pval;
+ return err;
+ }
+ return 1;
}
static int snd_soundblaster_e1_switch_resume(struct usb_mixer_elem_list *list)
@@ -2998,12 +3053,14 @@ static int snd_bbfpro_ctl_put(struct snd_kcontrol *kcontrol,
if (val == old_value)
return 0;
+ err = snd_bbfpro_ctl_update(mixer, reg, idx, val);
+ if (err < 0)
+ return err;
+
kcontrol->private_value = reg
| ((idx & SND_BBFPRO_CTL_IDX_MASK) << SND_BBFPRO_CTL_IDX_SHIFT)
| ((val & SND_BBFPRO_CTL_VAL_MASK) << SND_BBFPRO_CTL_VAL_SHIFT);
-
- err = snd_bbfpro_ctl_update(mixer, reg, idx, val);
- return err < 0 ? err : 1;
+ return 1;
}
static int snd_bbfpro_ctl_resume(struct usb_mixer_elem_list *list)
@@ -3188,11 +3245,13 @@ static int snd_bbfpro_vol_put(struct snd_kcontrol *kcontrol,
new_val = uvalue & SND_BBFPRO_MIXER_VAL_MASK;
+ err = snd_bbfpro_vol_update(mixer, idx, new_val);
+ if (err < 0)
+ return err;
+
kcontrol->private_value = idx
| (new_val << SND_BBFPRO_MIXER_VAL_SHIFT);
-
- err = snd_bbfpro_vol_update(mixer, idx, new_val);
- return err < 0 ? err : 1;
+ return 1;
}
static int snd_bbfpro_vol_resume(struct usb_mixer_elem_list *list)
@@ -4451,6 +4510,7 @@ int snd_usb_mixer_apply_create_quirk(struct usb_mixer_interface *mixer)
case USB_ID(0x1235, 0x821b): /* Focusrite Scarlett 16i16 4th Gen */
case USB_ID(0x1235, 0x821c): /* Focusrite Scarlett 18i16 4th Gen */
case USB_ID(0x1235, 0x821d): /* Focusrite Scarlett 18i20 4th Gen */
+ case USB_ID(0x1235, 0x821e): /* Focusrite ISA C8X */
err = snd_fcp_init(mixer);
break;
diff --git a/sound/usb/mixer_scarlett.c b/sound/usb/mixer_scarlett.c
index 1bb01e827654..673eb8d8724d 100644
--- a/sound/usb/mixer_scarlett.c
+++ b/sound/usb/mixer_scarlett.c
@@ -680,7 +680,9 @@ static int scarlett_ctl_enum_put(struct snd_kcontrol *kctl,
val = ucontrol->value.integer.value[0];
val = val + opt->start;
if (val != oval) {
- snd_usb_set_cur_mix_value(elem, 0, 0, val);
+ err = snd_usb_set_cur_mix_value(elem, 0, 0, val);
+ if (err < 0)
+ return err;
return 1;
}
return 0;
diff --git a/sound/usb/mixer_scarlett2.c b/sound/usb/mixer_scarlett2.c
index 8eaa96222759..78fb72e626ca 100644
--- a/sound/usb/mixer_scarlett2.c
+++ b/sound/usb/mixer_scarlett2.c
@@ -192,6 +192,9 @@
/* maximum Bluetooth volume value */
#define SCARLETT2_MAX_BLUETOOTH_VOLUME 30
+/* maximum front-panel sleep time in seconds (24 hours) */
+#define SCARLETT2_MAX_FP_SLEEP_TIME 86400
+
/* mixer range from -80dB to +12dB in 0.5dB steps */
#define SCARLETT2_MIXER_MIN_DB -80
#define SCARLETT2_MIXER_BIAS (-SCARLETT2_MIXER_MIN_DB * 2)
@@ -398,6 +401,7 @@ static const char *const scarlett2_autogain_status_gen4[] = {
"FailMaxGainLimit",
"FailClipped",
"Cancelled",
+ "Root",
"Invalid",
NULL
};
@@ -567,6 +571,8 @@ enum {
SCARLETT2_CONFIG_BLUETOOTH_VOLUME,
SCARLETT2_CONFIG_SPDIF_MODE,
SCARLETT2_CONFIG_SP_HP_MUTE,
+ SCARLETT2_CONFIG_FP_BRIGHTNESS,
+ SCARLETT2_CONFIG_FP_SLEEP_TIME,
SCARLETT2_CONFIG_COUNT
};
@@ -612,6 +618,20 @@ struct scarlett2_config_set {
const struct scarlett2_config items[SCARLETT2_CONFIG_COUNT];
};
+/* Map firmware versions to config sets per-device.
+ *
+ * Each device lists one or more entries, sorted in ascending order of
+ * from_firmware_version. At probe time the running firmware version
+ * is looked up against this list and the last entry whose
+ * from_firmware_version is <= the running version is selected.
+ *
+ * The list is terminated by a sentinel entry with config_set == NULL.
+ */
+struct scarlett2_config_set_entry {
+ u16 from_firmware_version;
+ const struct scarlett2_config_set *config_set;
+};
+
/* Input gain TLV dB ranges */
static const DECLARE_TLV_DB_MINMAX(
@@ -870,6 +890,42 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_solo = {
}
};
+/* Solo Gen 4, firmware version 2417 and above */
+static const struct scarlett2_config_set scarlett2_config_set_gen4_solo_2417 = {
+ .notifications = scarlett4_solo_notifications,
+ .param_buf_addr = 0xd8,
+ .items = {
+ [SCARLETT2_CONFIG_MSD_SWITCH] = {
+ .offset = 0x47, .size = 8, .activate = 4 },
+
+ [SCARLETT2_CONFIG_DIRECT_MONITOR] = {
+ .offset = 0x108, .size = 8, .activate = 12, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
+ .offset = 0x46, .size = 8, .activate = 9, .pbuf = 1,
+ .mute = 1 },
+
+ [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
+ .offset = 0x3d, .size = 8, .activate = 10, .pbuf = 1,
+ .mute = 1 },
+
+ [SCARLETT2_CONFIG_AIR_SWITCH] = {
+ .offset = 0x3e, .size = 8, .activate = 11, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_PCM_INPUT_SWITCH] = {
+ .offset = 0x206, .size = 8, .activate = 25, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = {
+ .offset = 0x232, .size = 16, .activate = 26 },
+
+ [SCARLETT2_CONFIG_FP_BRIGHTNESS] = {
+ .offset = 0x243, .size = 8, .activate = 27, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_FP_SLEEP_TIME] = {
+ .offset = 0x248, .size = 32, .activate = 29 }
+ }
+};
+
/* 2i2 Gen 4 */
static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = {
.notifications = scarlett4_2i2_notifications,
@@ -923,6 +979,70 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2 = {
}
};
+/* 2i2 Gen 4, firmware version 2417 and above
+ *
+ * Firmware 2417 shifted DIRECT_MONITOR_GAIN by 4 bytes and added
+ * front-panel brightness and sleep controls; all other offsets are
+ * unchanged from scarlett2_config_set_gen4_2i2.
+ */
+static const struct scarlett2_config_set scarlett2_config_set_gen4_2i2_2417 = {
+ .notifications = scarlett4_2i2_notifications,
+ .param_buf_addr = 0xfc,
+ .input_gain_tlv = db_scale_gen4_gain,
+ .autogain_status_texts = scarlett2_autogain_status_gen4,
+ .items = {
+ [SCARLETT2_CONFIG_MSD_SWITCH] = {
+ .offset = 0x49, .size = 8, .activate = 4 },
+
+ [SCARLETT2_CONFIG_DIRECT_MONITOR] = {
+ .offset = 0x14a, .size = 8, .activate = 16, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_AUTOGAIN_SWITCH] = {
+ .offset = 0x135, .size = 8, .activate = 10, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_AUTOGAIN_STATUS] = {
+ .offset = 0x137, .size = 8 },
+
+ [SCARLETT2_CONFIG_AG_MEAN_TARGET] = {
+ .offset = 0x131, .size = 8, .activate = 29, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_AG_PEAK_TARGET] = {
+ .offset = 0x132, .size = 8, .activate = 30, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
+ .offset = 0x48, .size = 8, .activate = 11, .pbuf = 1,
+ .mute = 1 },
+
+ [SCARLETT2_CONFIG_INPUT_GAIN] = {
+ .offset = 0x4b, .size = 8, .activate = 12, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
+ .offset = 0x3c, .size = 8, .activate = 13, .pbuf = 1,
+ .mute = 1 },
+
+ [SCARLETT2_CONFIG_SAFE_SWITCH] = {
+ .offset = 0x147, .size = 8, .activate = 14, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_AIR_SWITCH] = {
+ .offset = 0x3e, .size = 8, .activate = 15, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_INPUT_SELECT_SWITCH] = {
+ .offset = 0x14b, .size = 8, .activate = 17, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_INPUT_LINK_SWITCH] = {
+ .offset = 0x14e, .size = 8, .activate = 18, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_DIRECT_MONITOR_GAIN] = {
+ .offset = 0x2a4, .size = 16, .activate = 36 },
+
+ [SCARLETT2_CONFIG_FP_BRIGHTNESS] = {
+ .offset = 0x2c7, .size = 8, .activate = 37, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_FP_SLEEP_TIME] = {
+ .offset = 0x2cc, .size = 32, .activate = 39 }
+ }
+};
+
/* 4i4 Gen 4 */
static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = {
.notifications = scarlett4_4i4_notifications,
@@ -982,6 +1102,71 @@ static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4 = {
}
};
+/* 4i4 Gen 4, firmware version 2417 and above */
+static const struct scarlett2_config_set scarlett2_config_set_gen4_4i4_2417 = {
+ .notifications = scarlett4_4i4_notifications,
+ .param_buf_addr = 0x130,
+ .input_gain_tlv = db_scale_gen4_gain,
+ .autogain_status_texts = scarlett2_autogain_status_gen4,
+ .items = {
+ [SCARLETT2_CONFIG_MSD_SWITCH] = {
+ .offset = 0x5c, .size = 8, .activate = 4 },
+
+ [SCARLETT2_CONFIG_AUTOGAIN_SWITCH] = {
+ .offset = 0x13e, .size = 8, .activate = 10, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_AUTOGAIN_STATUS] = {
+ .offset = 0x140, .size = 8 },
+
+ [SCARLETT2_CONFIG_AG_MEAN_TARGET] = {
+ .offset = 0x13a, .size = 8, .activate = 23, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_AG_PEAK_TARGET] = {
+ .offset = 0x13b, .size = 8, .activate = 24, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_PHANTOM_SWITCH] = {
+ .offset = 0x5a, .size = 8, .activate = 11, .pbuf = 1,
+ .mute = 1 },
+
+ [SCARLETT2_CONFIG_INPUT_GAIN] = {
+ .offset = 0x5e, .size = 8, .activate = 12, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_LEVEL_SWITCH] = {
+ .offset = 0x4e, .size = 8, .activate = 13, .pbuf = 1,
+ .mute = 1 },
+
+ [SCARLETT2_CONFIG_SAFE_SWITCH] = {
+ .offset = 0x150, .size = 8, .activate = 14, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_AIR_SWITCH] = {
+ .offset = 0x50, .size = 8, .activate = 15, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_INPUT_SELECT_SWITCH] = {
+ .offset = 0x153, .size = 8, .activate = 16, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_INPUT_LINK_SWITCH] = {
+ .offset = 0x156, .size = 8, .activate = 17, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_MASTER_VOLUME] = {
+ .offset = 0x32, .size = 16 },
+
+ [SCARLETT2_CONFIG_HEADPHONE_VOLUME] = {
+ .offset = 0x3a, .size = 16 },
+
+ [SCARLETT2_CONFIG_POWER_EXT] = {
+ .offset = 0x168, .size = 8 },
+
+ [SCARLETT2_CONFIG_POWER_LOW] = {
+ .offset = 0x16d, .size = 8 },
+
+ [SCARLETT2_CONFIG_FP_BRIGHTNESS] = {
+ .offset = 0x3a9, .size = 8, .activate = 36, .pbuf = 1 },
+
+ [SCARLETT2_CONFIG_FP_SLEEP_TIME] = {
+ .offset = 0x3ac, .size = 32, .activate = 38 }
+ }
+};
+
/* Clarett USB and Clarett+ devices: 2Pre, 4Pre, 8Pre */
static const struct scarlett2_config_set scarlett2_config_set_clarett = {
.notifications = scarlett2_notifications,
@@ -1100,11 +1285,8 @@ struct scarlett2_meter_entry {
};
struct scarlett2_device_info {
- /* which set of configuration parameters the device uses */
- const struct scarlett2_config_set *config_set;
-
- /* minimum firmware version required */
- u16 min_firmware_version;
+ /* which sets of configuration parameters the device uses */
+ const struct scarlett2_config_set_entry *config_sets;
/* has a downloadable device map */
u8 has_devmap;
@@ -1335,6 +1517,8 @@ struct scarlett2_data {
struct snd_kcontrol *talkback_ctl;
struct snd_kcontrol *power_status_ctl;
struct snd_kcontrol *bluetooth_volume_ctl;
+ u8 fp_brightness;
+ u32 fp_sleep_time;
u8 mux[SCARLETT2_MUX_MAX];
u8 mix[SCARLETT2_MIX_MAX];
u8 monitor_mix[SCARLETT2_MONITOR_MIX_MAX];
@@ -1343,7 +1527,10 @@ struct scarlett2_data {
/*** Model-specific data ***/
static const struct scarlett2_device_info s6i6_gen2_info = {
- .config_set = &scarlett2_config_set_gen2a,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen2a },
+ { }
+ },
.level_input_count = 2,
.pad_input_count = 2,
@@ -1393,7 +1580,10 @@ static const struct scarlett2_device_info s6i6_gen2_info = {
};
static const struct scarlett2_device_info s18i8_gen2_info = {
- .config_set = &scarlett2_config_set_gen2a,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen2a },
+ { }
+ },
.level_input_count = 2,
.pad_input_count = 4,
@@ -1446,7 +1636,10 @@ static const struct scarlett2_device_info s18i8_gen2_info = {
};
static const struct scarlett2_device_info s18i20_gen2_info = {
- .config_set = &scarlett2_config_set_gen2b,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen2b },
+ { }
+ },
.line_out_descrs = {
"Monitor L",
@@ -1503,7 +1696,10 @@ static const struct scarlett2_device_info s18i20_gen2_info = {
};
static const struct scarlett2_device_info solo_gen3_info = {
- .config_set = &scarlett2_config_set_gen3a,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3a },
+ { }
+ },
.level_input_count = 1,
.level_input_first = 1,
.air_input_count = 1,
@@ -1513,7 +1709,10 @@ static const struct scarlett2_device_info solo_gen3_info = {
};
static const struct scarlett2_device_info s2i2_gen3_info = {
- .config_set = &scarlett2_config_set_gen3a,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3a },
+ { }
+ },
.level_input_count = 2,
.air_input_count = 2,
.phantom_count = 1,
@@ -1522,7 +1721,10 @@ static const struct scarlett2_device_info s2i2_gen3_info = {
};
static const struct scarlett2_device_info s4i4_gen3_info = {
- .config_set = &scarlett2_config_set_gen3b,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3b },
+ { }
+ },
.level_input_count = 2,
.pad_input_count = 2,
.air_input_count = 2,
@@ -1571,7 +1773,10 @@ static const struct scarlett2_device_info s4i4_gen3_info = {
};
static const struct scarlett2_device_info s8i6_gen3_info = {
- .config_set = &scarlett2_config_set_gen3b,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3b },
+ { }
+ },
.level_input_count = 2,
.pad_input_count = 2,
.air_input_count = 2,
@@ -1637,7 +1842,10 @@ static const char * const scarlett2_spdif_s18i8_gen3_texts[] = {
};
static const struct scarlett2_device_info s18i8_gen3_info = {
- .config_set = &scarlett2_config_set_gen3c,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3c },
+ { }
+ },
.has_speaker_switching = 1,
.level_input_count = 2,
.pad_input_count = 4,
@@ -1729,7 +1937,10 @@ static const char * const scarlett2_spdif_s18i20_gen3_texts[] = {
};
static const struct scarlett2_device_info s18i20_gen3_info = {
- .config_set = &scarlett2_config_set_gen3c,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_gen3c },
+ { }
+ },
.has_speaker_switching = 1,
.has_talkback = 1,
.level_input_count = 2,
@@ -1803,8 +2014,10 @@ static const struct scarlett2_device_info s18i20_gen3_info = {
};
static const struct scarlett2_device_info vocaster_one_info = {
- .config_set = &scarlett2_config_set_vocaster,
- .min_firmware_version = 1769,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 1769, &scarlett2_config_set_vocaster },
+ { }
+ },
.has_devmap = 1,
.phantom_count = 1,
@@ -1847,8 +2060,10 @@ static const struct scarlett2_device_info vocaster_one_info = {
};
static const struct scarlett2_device_info vocaster_two_info = {
- .config_set = &scarlett2_config_set_vocaster,
- .min_firmware_version = 1769,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 1769, &scarlett2_config_set_vocaster },
+ { }
+ },
.has_devmap = 1,
.phantom_count = 2,
@@ -1892,8 +2107,11 @@ static const struct scarlett2_device_info vocaster_two_info = {
};
static const struct scarlett2_device_info solo_gen4_info = {
- .config_set = &scarlett2_config_set_gen4_solo,
- .min_firmware_version = 2115,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 2115, &scarlett2_config_set_gen4_solo },
+ { 2417, &scarlett2_config_set_gen4_solo_2417 },
+ { }
+ },
.has_devmap = 1,
.level_input_count = 1,
@@ -1947,8 +2165,11 @@ static const struct scarlett2_device_info solo_gen4_info = {
};
static const struct scarlett2_device_info s2i2_gen4_info = {
- .config_set = &scarlett2_config_set_gen4_2i2,
- .min_firmware_version = 2115,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 2115, &scarlett2_config_set_gen4_2i2 },
+ { 2417, &scarlett2_config_set_gen4_2i2_2417 },
+ { }
+ },
.has_devmap = 1,
.level_input_count = 2,
@@ -2002,8 +2223,11 @@ static const struct scarlett2_device_info s2i2_gen4_info = {
};
static const struct scarlett2_device_info s4i4_gen4_info = {
- .config_set = &scarlett2_config_set_gen4_4i4,
- .min_firmware_version = 2089,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 2089, &scarlett2_config_set_gen4_4i4 },
+ { 2417, &scarlett2_config_set_gen4_4i4_2417 },
+ { }
+ },
.has_devmap = 1,
.level_input_count = 2,
@@ -2051,7 +2275,10 @@ static const struct scarlett2_device_info s4i4_gen4_info = {
};
static const struct scarlett2_device_info clarett_2pre_info = {
- .config_set = &scarlett2_config_set_clarett,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_clarett },
+ { }
+ },
.level_input_count = 2,
.air_input_count = 2,
@@ -2107,7 +2334,10 @@ static const char * const scarlett2_spdif_clarett_texts[] = {
};
static const struct scarlett2_device_info clarett_4pre_info = {
- .config_set = &scarlett2_config_set_clarett,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_clarett },
+ { }
+ },
.level_input_count = 2,
.air_input_count = 4,
@@ -2163,7 +2393,10 @@ static const struct scarlett2_device_info clarett_4pre_info = {
};
static const struct scarlett2_device_info clarett_8pre_info = {
- .config_set = &scarlett2_config_set_clarett,
+ .config_sets = (const struct scarlett2_config_set_entry[]) {
+ { 0, &scarlett2_config_set_clarett },
+ { }
+ },
.level_input_count = 2,
.air_input_count = 8,
@@ -2381,13 +2614,13 @@ static int scarlett2_usb(
struct scarlett2_usb_packet *req __free(kfree) = NULL;
size_t req_buf_size = struct_size(req, data, req_size);
- req = kmalloc(req_buf_size, GFP_KERNEL);
+ req = kmalloc_flex(*req, data, req_size);
if (!req)
return -ENOMEM;
struct scarlett2_usb_packet *resp __free(kfree) = NULL;
size_t resp_buf_size = struct_size(resp, data, resp_size);
- resp = kmalloc(resp_buf_size, GFP_KERNEL);
+ resp = kmalloc_flex(*resp, data, resp_size);
if (!resp)
return -ENOMEM;
@@ -2597,9 +2830,9 @@ static int scarlett2_usb_set_data_buf(
u8 data[];
} __packed *req;
int err;
- int buf_size = struct_size(req, data, bytes);
+ size_t buf_size = struct_size(req, data, bytes);
- req = kmalloc(buf_size, GFP_KERNEL);
+ req = kmalloc_flex(*req, data, bytes);
if (!req)
return -ENOMEM;
@@ -3276,7 +3509,8 @@ static int scarlett2_min_firmware_version_ctl_get(
struct usb_mixer_elem_info *elem = kctl->private_data;
struct scarlett2_data *private = elem->head.mixer->private_data;
- ucontrol->value.integer.value[0] = private->info->min_firmware_version;
+ ucontrol->value.integer.value[0] =
+ private->info->config_sets[0].from_firmware_version;
return 0;
}
@@ -6707,6 +6941,8 @@ static int scarlett2_add_line_in_ctls(struct usb_mixer_interface *mixer)
err = scarlett2_add_new_ctl(
mixer, &scarlett2_autogain_status_ctl,
i, 1, s, &private->autogain_status_ctls[i]);
+ if (err < 0)
+ return err;
}
/* Add autogain target controls */
@@ -7626,6 +7862,172 @@ static int scarlett2_add_bluetooth_volume_ctl(
&private->bluetooth_volume_ctl);
}
+/*** Front Panel Brightness/Sleep Controls ***/
+
+static int scarlett2_update_fp(struct usb_mixer_interface *mixer)
+{
+ struct scarlett2_data *private = mixer->private_data;
+ int err;
+
+ if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_BRIGHTNESS)) {
+ err = scarlett2_usb_get_config(
+ mixer, SCARLETT2_CONFIG_FP_BRIGHTNESS,
+ 1, &private->fp_brightness);
+ if (err < 0)
+ return err;
+ }
+
+ if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_SLEEP_TIME)) {
+ err = scarlett2_usb_get_config(
+ mixer, SCARLETT2_CONFIG_FP_SLEEP_TIME,
+ 1, &private->fp_sleep_time);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+static const char * const scarlett2_fp_brightness_texts[] = {
+ "High", "Medium", "Low"
+};
+
+static int scarlett2_fp_brightness_ctl_info(
+ struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
+{
+ return snd_ctl_enum_info(uinfo, 1,
+ ARRAY_SIZE(scarlett2_fp_brightness_texts),
+ scarlett2_fp_brightness_texts);
+}
+
+static int scarlett2_fp_brightness_ctl_get(
+ struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
+{
+ struct usb_mixer_elem_info *elem = kctl->private_data;
+ struct scarlett2_data *private = elem->head.mixer->private_data;
+
+ ucontrol->value.enumerated.item[0] = private->fp_brightness;
+ return 0;
+}
+
+static int scarlett2_fp_brightness_ctl_put(
+ struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
+{
+ struct usb_mixer_elem_info *elem = kctl->private_data;
+ struct usb_mixer_interface *mixer = elem->head.mixer;
+ struct scarlett2_data *private = mixer->private_data;
+ int oval, val, err;
+
+ guard(mutex)(&private->data_mutex);
+
+ if (private->hwdep_in_use)
+ return -EBUSY;
+
+ oval = private->fp_brightness;
+ val = min(ucontrol->value.enumerated.item[0],
+ ARRAY_SIZE(scarlett2_fp_brightness_texts) - 1);
+
+ if (oval == val)
+ return 0;
+
+ private->fp_brightness = val;
+
+ err = scarlett2_usb_set_config(
+ mixer, SCARLETT2_CONFIG_FP_BRIGHTNESS, 0, val);
+
+ return err < 0 ? err : 1;
+}
+
+static const struct snd_kcontrol_new scarlett2_fp_brightness_ctl = {
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ .name = "",
+ .info = scarlett2_fp_brightness_ctl_info,
+ .get = scarlett2_fp_brightness_ctl_get,
+ .put = scarlett2_fp_brightness_ctl_put,
+};
+
+static int scarlett2_fp_sleep_time_ctl_info(
+ struct snd_kcontrol *kctl, struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = SCARLETT2_MAX_FP_SLEEP_TIME;
+ uinfo->value.integer.step = 1;
+ return 0;
+}
+
+static int scarlett2_fp_sleep_time_ctl_get(
+ struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
+{
+ struct usb_mixer_elem_info *elem = kctl->private_data;
+ struct scarlett2_data *private = elem->head.mixer->private_data;
+
+ ucontrol->value.integer.value[0] = private->fp_sleep_time;
+ return 0;
+}
+
+static int scarlett2_fp_sleep_time_ctl_put(
+ struct snd_kcontrol *kctl, struct snd_ctl_elem_value *ucontrol)
+{
+ struct usb_mixer_elem_info *elem = kctl->private_data;
+ struct usb_mixer_interface *mixer = elem->head.mixer;
+ struct scarlett2_data *private = mixer->private_data;
+ u32 oval, val;
+ int err;
+
+ guard(mutex)(&private->data_mutex);
+
+ if (private->hwdep_in_use)
+ return -EBUSY;
+
+ oval = private->fp_sleep_time;
+ val = clamp(ucontrol->value.integer.value[0],
+ 0L, (long)SCARLETT2_MAX_FP_SLEEP_TIME);
+
+ if (oval == val)
+ return 0;
+
+ private->fp_sleep_time = val;
+
+ err = scarlett2_usb_set_config(
+ mixer, SCARLETT2_CONFIG_FP_SLEEP_TIME, 0, val);
+
+ return err < 0 ? err : 1;
+}
+
+static const struct snd_kcontrol_new scarlett2_fp_sleep_time_ctl = {
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ .name = "",
+ .info = scarlett2_fp_sleep_time_ctl_info,
+ .get = scarlett2_fp_sleep_time_ctl_get,
+ .put = scarlett2_fp_sleep_time_ctl_put,
+};
+
+static int scarlett2_add_fp_ctls(struct usb_mixer_interface *mixer)
+{
+ struct scarlett2_data *private = mixer->private_data;
+ int err;
+
+ if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_BRIGHTNESS)) {
+ err = scarlett2_add_new_ctl(
+ mixer, &scarlett2_fp_brightness_ctl, 0, 1,
+ "Front Panel Brightness", NULL);
+ if (err < 0)
+ return err;
+ }
+
+ if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_FP_SLEEP_TIME)) {
+ err = scarlett2_add_new_ctl(
+ mixer, &scarlett2_fp_sleep_time_ctl, 0, 1,
+ "Front Panel Sleep Time", NULL);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
/*** S/PDIF Mode Controls ***/
static int scarlett2_update_spdif_mode(struct usb_mixer_interface *mixer)
@@ -8184,10 +8586,32 @@ static void scarlett2_private_suspend(struct usb_mixer_interface *mixer)
/*** Initialisation ***/
+/* Select the config_set matching the running firmware version.
+ *
+ * The device info's config_sets array is ordered by ascending
+ * from_firmware_version; pick the last entry whose version is <= the
+ * running firmware version. If the running firmware is older than the
+ * first entry's from_firmware_version (i.e. older than the driver's
+ * minimum supported version for this device), the first entry's
+ * config_set is selected anyway so firmware updates can still be done
+ * (requires only the ACK handler), but the usual mixer controls
+ * aren't created.
+ */
+static void scarlett2_resolve_config_set(struct scarlett2_data *private)
+{
+ const struct scarlett2_config_set_entry *entry =
+ private->info->config_sets;
+
+ private->config_set = entry->config_set;
+ for (entry++; entry->config_set; entry++)
+ if (entry->from_firmware_version <= private->firmware_version)
+ private->config_set = entry->config_set;
+}
+
static void scarlett2_count_io(struct scarlett2_data *private)
{
const struct scarlett2_device_info *info = private->info;
- const struct scarlett2_config_set *config_set = info->config_set;
+ const struct scarlett2_config_set *config_set = private->config_set;
const int (*port_count)[SCARLETT2_PORT_DIRNS] = info->port_count;
int port_type, srcs = 0, dsts = 0, i;
@@ -8284,9 +8708,14 @@ static int scarlett2_init_private(struct usb_mixer_interface *mixer,
mixer->private_suspend = scarlett2_private_suspend;
private->info = entry->info;
- private->config_set = entry->info->config_set;
+
+ /* Set config_set to the first entry's config_set so the
+ * notify handler has a valid pointer while USB init runs; it
+ * is re-resolved once the firmware version has been read.
+ */
+ private->config_set = entry->info->config_sets[0].config_set;
+
private->series_name = entry->series_name;
- scarlett2_count_io(private);
private->scarlett2_seq = 0;
private->mixer = mixer;
@@ -8476,6 +8905,7 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
{
struct scarlett2_data *private = mixer->private_data;
const struct scarlett2_device_info *info = private->info;
+ u16 min_firmware_version = info->config_sets[0].from_firmware_version;
int err, i;
if (scarlett2_has_config_item(private, SCARLETT2_CONFIG_MSD_SWITCH)) {
@@ -8486,13 +8916,13 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
return err;
}
- if (private->firmware_version < info->min_firmware_version) {
+ if (private->firmware_version < min_firmware_version) {
usb_audio_err(mixer->chip,
"Focusrite %s firmware version %d is too old; "
"need %d",
private->series_name,
private->firmware_version,
- info->min_firmware_version);
+ min_firmware_version);
return 0;
}
@@ -8646,6 +9076,10 @@ static int scarlett2_read_configs(struct usb_mixer_interface *mixer)
if (err < 0)
return err;
+ err = scarlett2_update_fp(mixer);
+ if (err < 0)
+ return err;
+
err = scarlett2_update_spdif_mode(mixer);
if (err < 0)
return err;
@@ -8676,6 +9110,7 @@ static int snd_scarlett2_controls_create(
const struct scarlett2_device_entry *entry)
{
struct scarlett2_data *private;
+ u16 min_firmware_version;
int err;
/* Initialise private data */
@@ -8684,12 +9119,21 @@ static int snd_scarlett2_controls_create(
return err;
private = mixer->private_data;
+ min_firmware_version =
+ private->info->config_sets[0].from_firmware_version;
/* Send proprietary USB initialisation sequence */
err = scarlett2_usb_init(mixer);
if (err < 0)
return err;
+ /* Now that the firmware version is known, pick the matching
+ * config_set
+ */
+ scarlett2_resolve_config_set(private);
+
+ scarlett2_count_io(private);
+
/* Get the upgrade & settings flash segment numbers */
err = scarlett2_get_flash_segment_nums(mixer);
if (err < 0)
@@ -8719,7 +9163,7 @@ static int snd_scarlett2_controls_create(
* old, don't create any other controls
*/
if (private->msd_switch ||
- private->firmware_version < private->info->min_firmware_version)
+ private->firmware_version < min_firmware_version)
return 0;
/* Create the analogue output controls */
@@ -8782,6 +9226,11 @@ static int snd_scarlett2_controls_create(
if (err < 0)
return err;
+ /* Create the front-panel brightness/sleep controls */
+ err = scarlett2_add_fp_ctls(mixer);
+ if (err < 0)
+ return err;
+
/* Create the S/PDIF mode control */
err = scarlett2_add_spdif_mode_ctl(mixer);
if (err < 0)
@@ -9185,19 +9634,22 @@ static long scarlett2_hwdep_write(struct snd_hwdep *hw,
flash_size = private->flash_segment_blocks[segment_id] *
SCARLETT2_FLASH_BLOCK_SIZE;
- if (count < 0 || *offset < 0 || *offset + count >= flash_size)
- return -ENOSPC;
+ if (count < 0 || *offset < 0)
+ return -EINVAL;
if (!count)
return 0;
+ if (*offset >= flash_size || count > flash_size - *offset)
+ return -ENOSPC;
+
/* Limit the *req size to SCARLETT2_FLASH_RW_MAX */
if (count > max_data_size)
count = max_data_size;
/* Create and send the request */
len = struct_size(req, data, count);
- req = kzalloc(len, GFP_KERNEL);
+ req = kzalloc_flex(*req, data, count);
if (!req)
return -ENOMEM;
diff --git a/sound/usb/mixer_us16x08.c b/sound/usb/mixer_us16x08.c
index 8a02964e5d7b..ebff185cbd2c 100644
--- a/sound/usb/mixer_us16x08.c
+++ b/sound/usb/mixer_us16x08.c
@@ -224,14 +224,14 @@ static int snd_us16x08_route_put(struct snd_kcontrol *kcontrol,
err = snd_us16x08_send_urb(chip, buf, sizeof(route_msg));
- if (err > 0) {
- elem->cached |= 1 << index;
- elem->cache_val[index] = val;
- } else {
+ if (err < 0) {
usb_audio_dbg(chip, "Failed to set routing, err:%d\n", err);
+ return err;
}
- return err > 0 ? 1 : 0;
+ elem->cached |= 1 << index;
+ elem->cache_val[index] = val;
+ return 1;
}
static int snd_us16x08_master_info(struct snd_kcontrol *kcontrol,
@@ -283,14 +283,14 @@ static int snd_us16x08_master_put(struct snd_kcontrol *kcontrol,
buf[5] = index + 1;
err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_out));
- if (err > 0) {
- elem->cached |= 1 << index;
- elem->cache_val[index] = val;
- } else {
+ if (err < 0) {
usb_audio_dbg(chip, "Failed to set master, err:%d\n", err);
+ return err;
}
- return err > 0 ? 1 : 0;
+ elem->cached |= 1 << index;
+ elem->cache_val[index] = val;
+ return 1;
}
static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol,
@@ -324,14 +324,14 @@ static int snd_us16x08_bus_put(struct snd_kcontrol *kcontrol,
break;
}
- if (err > 0) {
- elem->cached |= 1;
- elem->cache_val[0] = val;
- } else {
+ if (err < 0) {
usb_audio_dbg(chip, "Failed to set bus parameter, err:%d\n", err);
+ return err;
}
- return err > 0 ? 1 : 0;
+ elem->cached |= 1;
+ elem->cache_val[0] = val;
+ return 1;
}
static int snd_us16x08_bus_get(struct snd_kcontrol *kcontrol,
@@ -392,14 +392,14 @@ static int snd_us16x08_channel_put(struct snd_kcontrol *kcontrol,
err = snd_us16x08_send_urb(chip, buf, sizeof(mix_msg_in));
- if (err > 0) {
- elem->cached |= 1 << index;
- elem->cache_val[index] = val;
- } else {
+ if (err < 0) {
usb_audio_dbg(chip, "Failed to set channel, err:%d\n", err);
+ return err;
}
- return err > 0 ? 1 : 0;
+ elem->cached |= 1 << index;
+ elem->cache_val[index] = val;
+ return 1;
}
static int snd_us16x08_mix_info(struct snd_kcontrol *kcontrol,
@@ -435,6 +435,7 @@ static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol,
int index = ucontrol->id.index;
char buf[sizeof(comp_msg)];
int val_idx, val;
+ int threshold, ratio, attack, release, gain, switch_on;
int err;
val = ucontrol->value.integer.value[0];
@@ -447,36 +448,61 @@ static int snd_us16x08_comp_put(struct snd_kcontrol *kcontrol,
/* new control value incl. bias*/
val_idx = elem->head.id - SND_US16X08_ID_COMP_BASE;
- store->val[val_idx][index] = ucontrol->value.integer.value[0];
+ threshold = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)]
+ [index];
+ ratio = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index];
+ attack = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index];
+ release = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)]
+ [index];
+ gain = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index];
+ switch_on = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)]
+ [index];
+
+ switch (val_idx) {
+ case COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD):
+ threshold = val;
+ break;
+ case COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO):
+ ratio = val;
+ break;
+ case COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK):
+ attack = val;
+ break;
+ case COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE):
+ release = val;
+ break;
+ case COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN):
+ gain = val;
+ break;
+ case COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH):
+ switch_on = val;
+ break;
+ }
/* prepare compressor URB message from template */
memcpy(buf, comp_msg, sizeof(comp_msg));
/* place comp values in message buffer watch bias! */
- buf[8] = store->val[
- COMP_STORE_IDX(SND_US16X08_ID_COMP_THRESHOLD)][index]
- - SND_US16X08_COMP_THRESHOLD_BIAS;
- buf[11] = ratio_map[store->val[
- COMP_STORE_IDX(SND_US16X08_ID_COMP_RATIO)][index]];
- buf[14] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_ATTACK)][index]
- + SND_US16X08_COMP_ATTACK_BIAS;
- buf[17] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_RELEASE)][index]
- + SND_US16X08_COMP_RELEASE_BIAS;
- buf[20] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_GAIN)][index];
- buf[26] = store->val[COMP_STORE_IDX(SND_US16X08_ID_COMP_SWITCH)][index];
+ buf[8] = threshold - SND_US16X08_COMP_THRESHOLD_BIAS;
+ buf[11] = ratio_map[ratio];
+ buf[14] = attack + SND_US16X08_COMP_ATTACK_BIAS;
+ buf[17] = release + SND_US16X08_COMP_RELEASE_BIAS;
+ buf[20] = gain;
+ buf[26] = switch_on;
/* place channel selector in message buffer */
buf[5] = index + 1;
err = snd_us16x08_send_urb(chip, buf, sizeof(comp_msg));
- if (err > 0) {
- elem->cached |= 1 << index;
- elem->cache_val[index] = val;
- } else {
+ if (err < 0) {
usb_audio_dbg(chip, "Failed to set compressor, err:%d\n", err);
+ return err;
}
+ store->val[val_idx][index] = val;
+ elem->cached |= 1 << index;
+ elem->cache_val[index] = val;
return 1;
}
@@ -529,13 +555,13 @@ static int snd_us16x08_eqswitch_put(struct snd_kcontrol *kcontrol,
msleep(15);
}
- if (err > 0) {
- elem->cached |= 1 << index;
- elem->cache_val[index] = val;
- } else {
+ if (err < 0) {
usb_audio_dbg(chip, "Failed to set eq switch, err:%d\n", err);
+ return err;
}
+ elem->cached |= 1 << index;
+ elem->cache_val[index] = val;
return 1;
}
@@ -578,11 +604,10 @@ static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
/* copy URB buffer from EQ template */
memcpy(buf, eqs_msq, sizeof(eqs_msq));
- store->val[b_idx][p_idx][index] = val;
- buf[20] = store->val[b_idx][3][index];
- buf[17] = store->val[b_idx][2][index];
- buf[14] = store->val[b_idx][1][index];
- buf[11] = store->val[b_idx][0][index];
+ buf[20] = p_idx == 3 ? val : store->val[b_idx][3][index];
+ buf[17] = p_idx == 2 ? val : store->val[b_idx][2][index];
+ buf[14] = p_idx == 1 ? val : store->val[b_idx][1][index];
+ buf[11] = p_idx == 0 ? val : store->val[b_idx][0][index];
/* place channel index in URB buffer */
buf[5] = index + 1;
@@ -592,14 +617,15 @@ static int snd_us16x08_eq_put(struct snd_kcontrol *kcontrol,
err = snd_us16x08_send_urb(chip, buf, sizeof(eqs_msq));
- if (err > 0) {
- /* store new value in EQ band cache */
- elem->cached |= 1 << index;
- elem->cache_val[index] = val;
- } else {
+ if (err < 0) {
usb_audio_dbg(chip, "Failed to set eq param, err:%d\n", err);
+ return err;
}
+ store->val[b_idx][p_idx][index] = val;
+ /* store new value in EQ band cache */
+ elem->cached |= 1 << index;
+ elem->cache_val[index] = val;
return 1;
}
@@ -1418,4 +1444,3 @@ int snd_us16x08_controls_create(struct usb_mixer_interface *mixer)
return 0;
}
-
diff --git a/sound/usb/qcom/mixer_usb_offload.c b/sound/usb/qcom/mixer_usb_offload.c
index 2adeb64f4d33..b1591361e76c 100644
--- a/sound/usb/qcom/mixer_usb_offload.c
+++ b/sound/usb/qcom/mixer_usb_offload.c
@@ -113,7 +113,7 @@ int snd_usb_offload_create_ctl(struct snd_usb_audio *chip, struct device *bedev)
struct snd_usb_substream *subs;
struct snd_usb_stream *as;
char ctl_name[48];
- int ret;
+ int ret = 0;
list_for_each_entry(as, &chip->pcm_list, list) {
subs = &as->substream[SNDRV_PCM_STREAM_PLAYBACK];
@@ -128,7 +128,7 @@ int snd_usb_offload_create_ctl(struct snd_usb_audio *chip, struct device *bedev)
*/
chip_kctl->private_value = as->pcm_index |
chip->card->number << 16;
- sprintf(ctl_name, "USB Offload Playback Card Route PCM#%d",
+ snprintf(ctl_name, sizeof(ctl_name), "USB Offload Playback Card Route PCM#%d",
as->pcm_index);
chip_kctl->name = ctl_name;
ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, bedev));
@@ -143,7 +143,7 @@ int snd_usb_offload_create_ctl(struct snd_usb_audio *chip, struct device *bedev)
*/
chip_kctl->private_value = as->pcm_index |
chip->card->number << 16;
- sprintf(ctl_name, "USB Offload Playback PCM Route PCM#%d",
+ snprintf(ctl_name, sizeof(ctl_name), "USB Offload Playback PCM Route PCM#%d",
as->pcm_index);
chip_kctl->name = ctl_name;
ret = snd_ctl_add(chip->card, snd_ctl_new1(chip_kctl, bedev));
diff --git a/sound/usb/qcom/qc_audio_offload.c b/sound/usb/qcom/qc_audio_offload.c
index 5f993b88448c..e4bfd43a2488 100644
--- a/sound/usb/qcom/qc_audio_offload.c
+++ b/sound/usb/qcom/qc_audio_offload.c
@@ -565,6 +565,7 @@ static unsigned long uaudio_iommu_map_pa(enum mem_type mtype, bool dma_coherent,
unsigned long iova = 0;
bool map = true;
int prot = uaudio_iommu_map_prot(dma_coherent);
+ int ret;
switch (mtype) {
case MEM_EVENT_RING:
@@ -582,10 +583,24 @@ static unsigned long uaudio_iommu_map_pa(enum mem_type mtype, bool dma_coherent,
dev_err(uaudio_qdev->data->dev, "unknown mem type %d\n", mtype);
}
- if (!iova || !map)
+ if (!iova)
return 0;
- iommu_map(uaudio_qdev->data->domain, iova, pa, size, prot, GFP_KERNEL);
+ if (!map)
+ return iova;
+
+ ret = iommu_map(uaudio_qdev->data->domain, iova, pa, size, prot,
+ GFP_KERNEL);
+ if (ret) {
+ dev_err(uaudio_qdev->data->dev,
+ "failed to map %zu bytes at iova 0x%08lx: %d\n",
+ size, iova, ret);
+ if (mtype == MEM_XFER_RING)
+ uaudio_put_iova(iova, size,
+ &uaudio_qdev->xfer_ring_list,
+ &uaudio_qdev->xfer_ring_iova_size);
+ return 0;
+ }
return iova;
}
@@ -779,15 +794,23 @@ static void qmi_stop_session(void)
continue;
}
/* Release XHCI endpoints */
- if (info->data_ep_pipe)
+ if (info->data_ep_pipe) {
ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
info->data_ep_pipe);
- xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb, ep);
+ if (ep)
+ xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb,
+ ep);
+ info->data_ep_pipe = 0;
+ }
- if (info->sync_ep_pipe)
+ if (info->sync_ep_pipe) {
ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
info->sync_ep_pipe);
- xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb, ep);
+ if (ep)
+ xhci_sideband_remove_endpoint(uadev[pcm_card_num].sb,
+ ep);
+ info->sync_ep_pipe = 0;
+ }
disable_audio_stream(subs);
}
@@ -1027,8 +1050,6 @@ static int uaudio_transfer_buffer_setup(struct snd_usb_substream *subs,
u32 len = xfer_buf_len;
bool dma_coherent;
dma_addr_t xfer_buf_dma_sysdev;
- u32 remainder;
- u32 mult;
int ret;
dma_coherent = dev_is_dma_coherent(subs->dev->bus->sysdev);
@@ -1037,10 +1058,7 @@ static int uaudio_transfer_buffer_setup(struct snd_usb_substream *subs,
if (!len)
len = PAGE_SIZE;
- mult = len / PAGE_SIZE;
- remainder = len % PAGE_SIZE;
- len = mult * PAGE_SIZE;
- len += remainder ? PAGE_SIZE : 0;
+ len = PAGE_ALIGN(len);
if (len > MAX_XFER_BUFF_LEN) {
dev_err(uaudio_qdev->data->dev,
@@ -1054,15 +1072,17 @@ static int uaudio_transfer_buffer_setup(struct snd_usb_substream *subs,
if (!xfer_buf)
return -ENOMEM;
- dma_get_sgtable(subs->dev->bus->sysdev, &xfer_buf_sgt, xfer_buf,
- xfer_buf_dma, len);
+ ret = dma_get_sgtable(subs->dev->bus->sysdev, &xfer_buf_sgt, xfer_buf,
+ xfer_buf_dma, len);
+ if (ret)
+ goto free_xfer_buf;
/* map the physical buffer into sysdev as well */
xfer_buf_dma_sysdev = uaudio_iommu_map_xfer_buf(dma_coherent,
len, &xfer_buf_sgt);
if (!xfer_buf_dma_sysdev) {
ret = -ENOMEM;
- goto unmap_sync;
+ goto free_sgt;
}
mem_info->dma = xfer_buf_dma;
@@ -1073,7 +1093,9 @@ static int uaudio_transfer_buffer_setup(struct snd_usb_substream *subs,
return 0;
-unmap_sync:
+free_sgt:
+ sg_free_table(&xfer_buf_sgt);
+free_xfer_buf:
usb_free_coherent(subs->dev, len, xfer_buf, xfer_buf_dma);
return ret;
@@ -1121,7 +1143,7 @@ uaudio_endpoint_setup(struct snd_usb_substream *subs,
ret = xhci_sideband_add_endpoint(uadev[card_num].sb, ep);
if (ret < 0) {
dev_err(&subs->dev->dev,
- "failed to add data ep to sec intr\n");
+ "failed to add data ep to sec intr: %d\n", ret);
ret = -ENODEV;
goto exit;
}
@@ -1129,7 +1151,7 @@ uaudio_endpoint_setup(struct snd_usb_substream *subs,
sgt = xhci_sideband_get_endpoint_buffer(uadev[card_num].sb, ep);
if (!sgt) {
dev_err(&subs->dev->dev,
- "failed to get data ep ring address\n");
+ "failed to get data ep ring address: %d\n", ret);
ret = -ENODEV;
goto remove_ep;
}
@@ -1138,6 +1160,7 @@ uaudio_endpoint_setup(struct snd_usb_substream *subs,
tr_pa = page_to_phys(pg);
mem_info->dma = sg_dma_address(sgt->sgl);
sg_free_table(sgt);
+ kfree(sgt);
/* data transfer ring */
iova = uaudio_iommu_map_pa(MEM_XFER_RING, dma_coherent, tr_pa,
@@ -1207,6 +1230,7 @@ static int uaudio_event_ring_setup(struct snd_usb_substream *subs,
er_pa = page_to_phys(pg);
mem_info->dma = sg_dma_address(sgt->sgl);
sg_free_table(sgt);
+ kfree(sgt);
iova = uaudio_iommu_map_pa(MEM_EVENT_RING, dma_coherent, er_pa,
PAGE_SIZE);
@@ -1596,8 +1620,13 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle,
if (req_msg->service_interval_valid) {
ret = get_data_interval_from_si(subs,
req_msg->service_interval);
- if (ret == -EINVAL)
+ if (ret == -EINVAL) {
+ if (req_msg->enable) {
+ guard(mutex)(&chip->mutex);
+ subs->opened = 0;
+ }
goto response;
+ }
datainterval = ret;
}
@@ -1618,6 +1647,11 @@ static void handle_uaudio_stream_req(struct qmi_handle *handle,
subs->opened = 0;
}
} else {
+ if (info_idx < 0) {
+ ret = -EINVAL;
+ goto response;
+ }
+
info = &uadev[pcm_card_num].info[info_idx];
if (info->data_ep_pipe) {
ep = usb_pipe_endpoint(uadev[pcm_card_num].udev,
@@ -1734,7 +1768,7 @@ static int qc_usb_audio_offload_fill_avail_pcms(struct snd_usb_audio *chip,
break;
}
- return -1;
+ return idx;
}
/**
@@ -1954,6 +1988,7 @@ static int qc_usb_audio_probe(struct auxiliary_device *auxdev,
release_qmi:
qc_usb_audio_cleanup_qmi_dev();
qmi_handle_release(svc->uaudio_svc_hdl);
+ kfree(svc->uaudio_svc_hdl);
free_svc:
kfree(svc);
@@ -1978,6 +2013,7 @@ static void qc_usb_audio_remove(struct auxiliary_device *auxdev)
qc_usb_audio_cleanup_qmi_dev();
qmi_handle_release(svc->uaudio_svc_hdl);
+ kfree(svc->uaudio_svc_hdl);
kfree(svc);
uaudio_svc = NULL;
}
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 4e9cfff4047f..71444c2898b4 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -391,6 +391,20 @@ YAMAHA_DEVICE(0x105d, NULL),
}
},
{
+ USB_DEVICE(0x0499, 0x150d),
+ QUIRK_DRIVER_INFO {
+ /* .vendor_name = "Yamaha", */
+ /* .product_name = "CDS3000", */
+ QUIRK_DATA_COMPOSITE {
+ { QUIRK_DATA_STANDARD_AUDIO(1) },
+ { QUIRK_DATA_STANDARD_AUDIO(2) },
+ { QUIRK_DATA_MIDI_YAMAHA(3) },
+ { QUIRK_DATA_IGNORE(4) },
+ QUIRK_COMPOSITE_END
+ }
+ }
+},
+{
USB_DEVICE(0x0499, 0x1718),
QUIRK_DRIVER_INFO {
/* .vendor_name = "Yamaha", */
@@ -2132,6 +2146,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ USB_DEVICE(0x1235, 0x001e),
+ QUIRK_DRIVER_INFO {
+ /* .vendor_name = "Novation", */
+ /* .product_name = "Mininova", */
+ QUIRK_DATA_RAW_BYTES(0)
+ }
+},
+{
USB_DEVICE_VENDOR_SPEC(0x1235, 0x4661),
QUIRK_DRIVER_INFO {
.vendor_name = "Novation",
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 17983d9774f8..1cb588691e16 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -2357,6 +2357,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x1224, 0x2a25, /* Jieli Technology USB PHY 2.0 */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
+ DEVICE_FLG(0x1377, 0x6004, /* Sennheiser MOMENTUM 3 */
+ QUIRK_FLAG_MIXER_GET_CUR_BROKEN),
DEVICE_FLG(0x1395, 0x740a, /* Sennheiser DECT */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x1397, 0x0507, /* Behringer UMC202HD */
@@ -2365,6 +2367,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
DEVICE_FLG(0x1397, 0x0509, /* Behringer UMC404HD */
QUIRK_FLAG_PLAYBACK_FIRST | QUIRK_FLAG_GENERIC_IMPLICIT_FB),
+ DEVICE_FLG(0x1397, 0x050c, /* Behringer Flow 8 */
+ QUIRK_FLAG_IFB_SILENCE_ON_EMPTY),
DEVICE_FLG(0x13e5, 0x0001, /* Serato Phono */
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x152a, 0x880a, /* NeuralDSP Quad Cortex */
@@ -2409,6 +2413,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
DEVICE_FLG(0x1bcf, 0x2283, /* NexiGo N930AF FHD Webcam */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
+ DEVICE_FLG(0x1ff7, 0x0f81, /* SC13A Webcam */
+ QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x2040, 0x7200, /* Hauppauge HVR-950Q */
QUIRK_FLAG_SHARE_MEDIA_DEVICE | QUIRK_FLAG_ALIGN_TRANSFER),
DEVICE_FLG(0x2040, 0x7201, /* Hauppauge HVR-950Q-MXL */
@@ -2449,6 +2455,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_DSD_RAW),
DEVICE_FLG(0x2522, 0x0007, /* LH Labs Geek Out HD Audio 1V5 */
QUIRK_FLAG_SET_IFACE_FIRST),
+ DEVICE_FLG(0x25aa, 0x600b, /* TAE1159 */
+ QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x262a, 0x9302, /* ddHiFi TC44C */
QUIRK_FLAG_DSD_RAW),
DEVICE_FLG(0x2708, 0x0002, /* Audient iD14 */
@@ -2471,6 +2479,8 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_CTL_MSG_DELAY_1M),
DEVICE_FLG(0x2d99, 0x0026, /* HECATE G2 GAMING HEADSET */
QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
+ DEVICE_FLG(0x2d99, 0xa024, /* Edifier MF200 */
+ QUIRK_FLAG_MIXER_GET_CUR_BROKEN),
DEVICE_FLG(0x2fc6, 0xf06b, /* MOONDROP Moonriver2 Ti */
QUIRK_FLAG_CTL_MSG_DELAY),
DEVICE_FLG(0x2fc6, 0xf0b7, /* iBasso DC07 Pro */
@@ -2479,10 +2489,16 @@ static const struct usb_audio_quirk_flags_table quirk_flags_table[] = {
QUIRK_FLAG_IGNORE_CTL_ERROR),
DEVICE_FLG(0x3255, 0x0000, /* Luxman D-10X */
QUIRK_FLAG_ITF_USB_DSD_DAC | QUIRK_FLAG_CTL_MSG_DELAY),
+ DEVICE_FLG(0x3302, 0x17c2, /* TTGK Technology USB-C Audio */
+ QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x339b, 0x3a07, /* Synaptics HONOR USB-C HEADSET */
QUIRK_FLAG_MIXER_PLAYBACK_MIN_MUTE),
DEVICE_FLG(0x3443, 0x930d, /* NexiGo N930W 60fps Webcam */
QUIRK_FLAG_GET_SAMPLE_RATE | QUIRK_FLAG_MIC_RES_16),
+ DEVICE_FLG(0x36f9, 0xc009, /* XIBERIA K03S */
+ QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
+ DEVICE_FLG(0x3c20, 0x3d21, /* AB13X USB Audio */
+ QUIRK_FLAG_FORCE_IFACE_RESET | QUIRK_FLAG_IFACE_DELAY),
DEVICE_FLG(0x413c, 0xa506, /* Dell AE515 sound bar */
QUIRK_FLAG_GET_SAMPLE_RATE),
DEVICE_FLG(0x534d, 0x0021, /* MacroSilicon MS2100/MS2106 */
@@ -2600,6 +2616,8 @@ static const char *const snd_usb_audio_quirk_flag_names[] = {
QUIRK_STRING_ENTRY(SKIP_IFACE_SETUP),
QUIRK_STRING_ENTRY(MIXER_PLAYBACK_LINEAR_VOL),
QUIRK_STRING_ENTRY(MIXER_CAPTURE_LINEAR_VOL),
+ QUIRK_STRING_ENTRY(IFB_SILENCE_ON_EMPTY),
+ QUIRK_STRING_ENTRY(MIXER_GET_CUR_BROKEN),
NULL
};
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 58fd07f8c3c9..e26f9092417e 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -7,6 +7,8 @@
* Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
*/
+#include <sound/core.h>
+
/* handling of USB vendor/product ID pairs as 32-bit numbers */
#define USB_ID(vendor, product) (((unsigned int)(vendor) << 16) | (product))
#define USB_ID_VENDOR(id) ((id) >> 16)
@@ -41,8 +43,7 @@ struct snd_usb_audio {
unsigned int system_suspend;
atomic_t active;
atomic_t shutdown;
- atomic_t usage_count;
- wait_queue_head_t shutdown_wait;
+ struct snd_refcount usage_count;
unsigned int quirk_flags;
unsigned int need_delayed_register:1; /* warn for delayed registration */
int num_interfaces;
@@ -236,6 +237,23 @@ extern bool snd_usb_skip_validation;
* QUIRK_FLAG_MIXER_CAPTURE_LINEAR_VOL
* Similar to QUIRK_FLAG_MIXER_PLAYBACK_LINEAR_VOL, but for capture streams.
* Overrides QUIRK_FLAG_MIXER_CAPTURE_MIN_MUTE
+ * QUIRK_FLAG_IFB_SILENCE_ON_EMPTY
+ * In implicit feedback mode, when an entire capture URB returns with
+ * all iso_frame_desc[i].status != 0 (bytes==0), do not silently return
+ * from snd_usb_handle_sync_urb. Instead fall through and enqueue a
+ * packet_info containing only size-0 packets, so the OUT ring keeps
+ * moving (emits silence). Needed by Behringer Flow 8 (1397:050c).
+ * QUIRK_FLAG_MIXER_GET_CUR_BROKEN
+ * Some mixers are sticky, which means that setting their current volume is a
+ * no-op, and reading the current volume returns a constant value. The sticky
+ * check disables these mixers to prevent confusing userspace. However, some
+ * devices do have a tunable volume despite the reported current volume being
+ * constant. As the sticky check can't distinguish between the two categories,
+ * setting this flag tells that the device should fall into the second
+ * category when GET_CUR returns a constant value, resulting in the sticky
+ * check being non-fatal and only disabling GET_CUR instead of the whole mixer.
+ * The current volume will then be provided by the internal cache that stores
+ * the last set volume
*/
enum {
@@ -268,6 +286,8 @@ enum {
QUIRK_TYPE_SKIP_IFACE_SETUP = 26,
QUIRK_TYPE_MIXER_PLAYBACK_LINEAR_VOL = 27,
QUIRK_TYPE_MIXER_CAPTURE_LINEAR_VOL = 28,
+ QUIRK_TYPE_IFB_SILENCE_ON_EMPTY = 29,
+ QUIRK_TYPE_MIXER_GET_CUR_BROKEN = 30,
/* Please also edit snd_usb_audio_quirk_flag_names */
};
@@ -302,5 +322,7 @@ enum {
#define QUIRK_FLAG_SKIP_IFACE_SETUP QUIRK_FLAG(SKIP_IFACE_SETUP)
#define QUIRK_FLAG_MIXER_PLAYBACK_LINEAR_VOL QUIRK_FLAG(MIXER_PLAYBACK_LINEAR_VOL)
#define QUIRK_FLAG_MIXER_CAPTURE_LINEAR_VOL QUIRK_FLAG(MIXER_CAPTURE_LINEAR_VOL)
+#define QUIRK_FLAG_IFB_SILENCE_ON_EMPTY QUIRK_FLAG(IFB_SILENCE_ON_EMPTY)
+#define QUIRK_FLAG_MIXER_GET_CUR_BROKEN QUIRK_FLAG(MIXER_GET_CUR_BROKEN)
#endif /* __USBAUDIO_H */
diff --git a/sound/usb/usx2y/us144mkii.c b/sound/usb/usx2y/us144mkii.c
index 94553b61013c..58ef23146f20 100644
--- a/sound/usb/usx2y/us144mkii.c
+++ b/sound/usb/usx2y/us144mkii.c
@@ -585,19 +585,24 @@ static void tascam_disconnect(struct usb_interface *intf)
return;
if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
- /* Ensure all deferred work is complete before freeing resources */
snd_card_disconnect(tascam->card);
- cancel_work_sync(&tascam->stop_work);
- cancel_work_sync(&tascam->capture_work);
- cancel_work_sync(&tascam->midi_in_work);
- cancel_work_sync(&tascam->midi_out_work);
- cancel_work_sync(&tascam->stop_pcm_work);
+ /*
+ * Kill the URBs before cancelling the work, so a late URB
+ * completion cannot re-arm a work that then runs after
+ * snd_card_free().
+ */
usb_kill_anchored_urbs(&tascam->playback_anchor);
usb_kill_anchored_urbs(&tascam->capture_anchor);
usb_kill_anchored_urbs(&tascam->feedback_anchor);
usb_kill_anchored_urbs(&tascam->midi_in_anchor);
usb_kill_anchored_urbs(&tascam->midi_out_anchor);
+
+ cancel_work_sync(&tascam->stop_work);
+ cancel_work_sync(&tascam->capture_work);
+ cancel_work_sync(&tascam->midi_in_work);
+ cancel_work_sync(&tascam->midi_out_work);
+ cancel_work_sync(&tascam->stop_pcm_work);
timer_delete_sync(&tascam->error_timer);
tascam_free_urbs(tascam);
snd_card_free(tascam->card);
diff --git a/sound/usb/usx2y/us144mkii_capture.c b/sound/usb/usx2y/us144mkii_capture.c
index af120bf62173..fa01da98151a 100644
--- a/sound/usb/usx2y/us144mkii_capture.c
+++ b/sound/usb/usx2y/us144mkii_capture.c
@@ -302,7 +302,6 @@ void capture_urb_complete(struct urb *urb)
}
usb_get_urb(urb);
- usb_anchor_urb(urb, &tascam->capture_anchor);
ret = usb_submit_urb(urb, GFP_ATOMIC);
if (ret < 0) {
dev_err_ratelimited(tascam->card->dev,
@@ -312,6 +311,7 @@ void capture_urb_complete(struct urb *urb)
usb_put_urb(urb);
atomic_dec(
&tascam->active_urbs); /* Decrement on failed resubmission */
+ return;
}
out:
usb_put_urb(urb);
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index f34e78910200..4190227c5a2a 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -180,7 +180,7 @@ static void i_usx2y_in04_int(struct urb *urb)
struct usx2ydev *usx2y = urb->context;
struct us428ctls_sharedmem *us428ctls = usx2y->us428ctls_sharedmem;
struct us428_p4out *p4out;
- int i, j, n, diff, send;
+ int i, j, n, diff, send, len;
usx2y->in04_int_calls++;
@@ -222,24 +222,31 @@ static void i_usx2y_in04_int(struct urb *urb)
} while (!err && usx2y->us04->submitted < usx2y->us04->len);
}
} else {
- if (us428ctls && us428ctls->p4out_last >= 0 && us428ctls->p4out_last < N_US428_P4OUT_BUFS) {
- if (us428ctls->p4out_last != us428ctls->p4out_sent) {
- send = us428ctls->p4out_sent + 1;
- if (send >= N_US428_P4OUT_BUFS)
- send = 0;
- for (j = 0; j < URBS_ASYNC_SEQ && !err; ++j) {
- if (!usx2y->as04.urb[j]->status) {
- p4out = us428ctls->p4out + send; // FIXME if more than 1 p4out is new, 1 gets lost.
- usb_fill_bulk_urb(usx2y->as04.urb[j], usx2y->dev,
- usb_sndbulkpipe(usx2y->dev, 0x04), &p4out->val.vol,
- p4out->type == ELT_LIGHT ? sizeof(struct us428_lights) : 5,
- i_usx2y_out04_int, usx2y);
- err = usb_submit_urb(usx2y->as04.urb[j], GFP_ATOMIC);
+ while (us428ctls &&
+ us428ctls->p4out_last >= 0 &&
+ us428ctls->p4out_last < N_US428_P4OUT_BUFS &&
+ us428ctls->p4out_last != us428ctls->p4out_sent) {
+ for (j = 0; j < URBS_ASYNC_SEQ && !err; ++j) {
+ if (!usx2y->as04.urb[j]->status) {
+ send = us428ctls->p4out_sent + 1;
+ if (send >= N_US428_P4OUT_BUFS)
+ send = 0;
+
+ p4out = us428ctls->p4out + send;
+ len = p4out->type == ELT_LIGHT ?
+ sizeof(struct us428_lights) : 5;
+ memcpy(usx2y->as04.urb[j]->transfer_buffer,
+ &p4out->val.vol, len);
+ usx2y->as04.urb[j]->transfer_buffer_length = len;
+ err = usb_submit_urb(usx2y->as04.urb[j], GFP_ATOMIC);
+ if (!err)
us428ctls->p4out_sent = send;
- break;
- }
+
+ break;
}
}
+ if (j >= URBS_ASYNC_SEQ || err)
+ break;
}
}
diff --git a/sound/virtio/virtio_kctl.c b/sound/virtio/virtio_kctl.c
index ffb903d56297..45f7b6a5b308 100644
--- a/sound/virtio/virtio_kctl.c
+++ b/sound/virtio/virtio_kctl.c
@@ -18,6 +18,21 @@ static const snd_ctl_elem_type_t g_v2a_type_map[] = {
[VIRTIO_SND_CTL_TYPE_IEC958] = SNDRV_CTL_ELEM_TYPE_IEC958
};
+/* Map for converting VirtIO types to maximum value counts. */
+static const unsigned int g_v2a_count_map[] = {
+ [VIRTIO_SND_CTL_TYPE_BOOLEAN] =
+ ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer),
+ [VIRTIO_SND_CTL_TYPE_INTEGER] =
+ ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer),
+ [VIRTIO_SND_CTL_TYPE_INTEGER64] =
+ ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.integer64),
+ [VIRTIO_SND_CTL_TYPE_ENUMERATED] =
+ ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.enumerated),
+ [VIRTIO_SND_CTL_TYPE_BYTES] =
+ ARRAY_SIZE(((struct virtio_snd_ctl_value *)0)->value.bytes),
+ [VIRTIO_SND_CTL_TYPE_IEC958] = 1
+};
+
/* Map for converting VirtIO access rights to ALSA access rights. */
static const unsigned int g_v2a_access_map[] = {
[VIRTIO_SND_CTL_ACCESS_READ] = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -36,6 +51,37 @@ static const unsigned int g_v2a_mask_map[] = {
[VIRTIO_SND_CTL_EVT_MASK_TLV] = SNDRV_CTL_EVENT_MASK_TLV
};
+static int virtsnd_kctl_validate_info(struct virtio_snd *snd, u32 cid,
+ struct virtio_snd_ctl_info *kinfo)
+{
+ struct virtio_device *vdev = snd->vdev;
+ unsigned int type = le32_to_cpu(kinfo->type);
+ unsigned int count = le32_to_cpu(kinfo->count);
+
+ if (type >= ARRAY_SIZE(g_v2a_type_map)) {
+ dev_err(&vdev->dev, "control #%u: unknown type %u\n",
+ cid, type);
+ return -EINVAL;
+ }
+
+ if (count > g_v2a_count_map[type] ||
+ (type == VIRTIO_SND_CTL_TYPE_IEC958 && count != 1)) {
+ dev_err(&vdev->dev, "control #%u: invalid count %u for type %u\n",
+ cid, count, type);
+ return -EINVAL;
+ }
+
+ if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED &&
+ !le32_to_cpu(kinfo->value.enumerated.items)) {
+ dev_err(&vdev->dev,
+ "control #%u: no items for enumerated control\n",
+ cid);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
/**
* virtsnd_kctl_info() - Returns information about the control.
* @kcontrol: ALSA control element.
@@ -385,6 +431,10 @@ int virtsnd_kctl_parse_cfg(struct virtio_snd *snd)
struct virtio_snd_ctl_info *kinfo = &snd->kctl_infos[i];
unsigned int type = le32_to_cpu(kinfo->type);
+ rc = virtsnd_kctl_validate_info(snd, i, kinfo);
+ if (rc)
+ return rc;
+
if (type == VIRTIO_SND_CTL_TYPE_ENUMERATED) {
rc = virtsnd_kctl_get_enum_items(snd, i);
if (rc)
diff --git a/sound/virtio/virtio_pcm.c b/sound/virtio/virtio_pcm.c
index eb9cc8131905..be3893de40a5 100644
--- a/sound/virtio/virtio_pcm.c
+++ b/sound/virtio/virtio_pcm.c
@@ -77,7 +77,8 @@ static const struct virtsnd_v2a_rate g_v2a_rate_map[] = {
[VIRTIO_SND_PCM_RATE_88200] = { SNDRV_PCM_RATE_88200, 88200 },
[VIRTIO_SND_PCM_RATE_96000] = { SNDRV_PCM_RATE_96000, 96000 },
[VIRTIO_SND_PCM_RATE_176400] = { SNDRV_PCM_RATE_176400, 176400 },
- [VIRTIO_SND_PCM_RATE_192000] = { SNDRV_PCM_RATE_192000, 192000 }
+ [VIRTIO_SND_PCM_RATE_192000] = { SNDRV_PCM_RATE_192000, 192000 },
+ [VIRTIO_SND_PCM_RATE_384000] = { SNDRV_PCM_RATE_384000, 384000 }
};
/**
diff --git a/sound/virtio/virtio_pcm_ops.c b/sound/virtio/virtio_pcm_ops.c
index 6297a9c61e70..1105e7ff3523 100644
--- a/sound/virtio/virtio_pcm_ops.c
+++ b/sound/virtio/virtio_pcm_ops.c
@@ -90,7 +90,8 @@ static const struct virtsnd_a2v_rate g_a2v_rate_map[] = {
{ 88200, VIRTIO_SND_PCM_RATE_88200 },
{ 96000, VIRTIO_SND_PCM_RATE_96000 },
{ 176400, VIRTIO_SND_PCM_RATE_176400 },
- { 192000, VIRTIO_SND_PCM_RATE_192000 }
+ { 192000, VIRTIO_SND_PCM_RATE_192000 },
+ { 384000, VIRTIO_SND_PCM_RATE_384000 }
};
static int virtsnd_pcm_sync_stop(struct snd_pcm_substream *substream);
diff --git a/sound/xen/xen_snd_front_alsa.c b/sound/xen/xen_snd_front_alsa.c
index dc626480123a..a6dd196f73d6 100644
--- a/sound/xen/xen_snd_front_alsa.c
+++ b/sound/xen/xen_snd_front_alsa.c
@@ -378,7 +378,7 @@ static int alsa_open(struct snd_pcm_substream *substream)
stream_clear(stream);
- xen_snd_front_evtchnl_pair_set_connected(stream->evt_pair, true);
+ xen_snd_front_evtchnl_set_connected(&stream->evt_pair->req, true);
ret = snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT,
alsa_hw_rule, stream,
@@ -498,6 +498,8 @@ static int alsa_hw_free(struct snd_pcm_substream *substream)
struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
int ret;
+ xen_snd_front_evtchnl_set_connected(&stream->evt_pair->evt, false);
+
ret = xen_snd_front_stream_close(&stream->evt_pair->req);
stream_free(stream);
return ret;
@@ -532,6 +534,7 @@ static int alsa_prepare(struct snd_pcm_substream *substream)
return ret;
stream->is_open = true;
+ xen_snd_front_evtchnl_set_connected(&stream->evt_pair->evt, true);
}
return 0;
@@ -571,20 +574,24 @@ void xen_snd_front_alsa_handle_cur_pos(struct xen_snd_front_evtchnl *evtchnl,
{
struct snd_pcm_substream *substream = evtchnl->u.evt.substream;
struct xen_snd_front_pcm_stream_info *stream = stream_get(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
snd_pcm_uframes_t delta, new_hw_ptr, cur_frame;
- cur_frame = bytes_to_frames(substream->runtime, pos_bytes);
+ if (!runtime->buffer_size || !runtime->period_size)
+ return;
+
+ cur_frame = bytes_to_frames(runtime, pos_bytes);
delta = cur_frame - stream->be_cur_frame;
stream->be_cur_frame = cur_frame;
new_hw_ptr = (snd_pcm_uframes_t)atomic_read(&stream->hw_ptr);
- new_hw_ptr = (new_hw_ptr + delta) % substream->runtime->buffer_size;
+ new_hw_ptr = (new_hw_ptr + delta) % runtime->buffer_size;
atomic_set(&stream->hw_ptr, (int)new_hw_ptr);
stream->out_frames += delta;
- if (stream->out_frames > substream->runtime->period_size) {
- stream->out_frames %= substream->runtime->period_size;
+ if (stream->out_frames > runtime->period_size) {
+ stream->out_frames %= runtime->period_size;
snd_pcm_period_elapsed(substream);
}
}
diff --git a/sound/xen/xen_snd_front_evtchnl.c b/sound/xen/xen_snd_front_evtchnl.c
index bc03f71bf16e..17a30452c0cc 100644
--- a/sound/xen/xen_snd_front_evtchnl.c
+++ b/sound/xen/xen_snd_front_evtchnl.c
@@ -94,6 +94,9 @@ static irqreturn_t evtchnl_interrupt_evt(int irq, void *dev_id)
guard(mutex)(&channel->ring_io_lock);
+ if (unlikely(channel->state != EVTCHNL_STATE_CONNECTED))
+ return IRQ_HANDLED;
+
prod = page->in_prod;
/* Ensure we see ring contents up to prod. */
virt_rmb();
@@ -430,8 +433,8 @@ fail_to_end:
return ret;
}
-void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair *evt_pair,
- bool is_connected)
+void xen_snd_front_evtchnl_set_connected(struct xen_snd_front_evtchnl *channel,
+ bool is_connected)
{
enum xen_snd_front_evtchnl_state state;
@@ -440,13 +443,16 @@ void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair
else
state = EVTCHNL_STATE_DISCONNECTED;
- scoped_guard(mutex, &evt_pair->req.ring_io_lock) {
- evt_pair->req.state = state;
+ scoped_guard(mutex, &channel->ring_io_lock) {
+ channel->state = state;
}
+}
- scoped_guard(mutex, &evt_pair->evt.ring_io_lock) {
- evt_pair->evt.state = state;
- }
+void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair *evt_pair,
+ bool is_connected)
+{
+ xen_snd_front_evtchnl_set_connected(&evt_pair->req, is_connected);
+ xen_snd_front_evtchnl_set_connected(&evt_pair->evt, is_connected);
}
void xen_snd_front_evtchnl_pair_clear(struct xen_snd_front_evtchnl_pair *evt_pair)
@@ -456,7 +462,11 @@ void xen_snd_front_evtchnl_pair_clear(struct xen_snd_front_evtchnl_pair *evt_pai
}
scoped_guard(mutex, &evt_pair->evt.ring_io_lock) {
- evt_pair->evt.evt_next_id = 0;
+ evt_pair->evt.evt_id = 0;
+ /* Drop obsolete events queued for the previous stream instance. */
+ evt_pair->evt.u.evt.page->in_cons =
+ evt_pair->evt.u.evt.page->in_prod;
+ /* Ensure the consumer index is visible before stream reuse. */
+ virt_wmb();
}
}
-
diff --git a/sound/xen/xen_snd_front_evtchnl.h b/sound/xen/xen_snd_front_evtchnl.h
index 3675fba70564..f6ebdb09c029 100644
--- a/sound/xen/xen_snd_front_evtchnl.h
+++ b/sound/xen/xen_snd_front_evtchnl.h
@@ -37,9 +37,9 @@ struct xen_snd_front_evtchnl {
/* State of the event channel. */
enum xen_snd_front_evtchnl_state state;
enum xen_snd_front_evtchnl_type type;
- /* Either response id or incoming event id. */
+ /* Current response id or next expected incoming event id. */
u16 evt_id;
- /* Next request id or next expected event id. */
+ /* Next request id. */
u16 evt_next_id;
/* Shared ring access lock. */
struct mutex ring_io_lock;
@@ -77,6 +77,8 @@ void xen_snd_front_evtchnl_free_all(struct xen_snd_front_info *front_info);
int xen_snd_front_evtchnl_publish_all(struct xen_snd_front_info *front_info);
void xen_snd_front_evtchnl_flush(struct xen_snd_front_evtchnl *evtchnl);
+void xen_snd_front_evtchnl_set_connected(struct xen_snd_front_evtchnl *channel,
+ bool is_connected);
void xen_snd_front_evtchnl_pair_set_connected(struct xen_snd_front_evtchnl_pair *evt_pair,
bool is_connected);