summaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/Kconfig2
-rw-r--r--sound/aoa/codecs/Kconfig8
-rw-r--r--sound/aoa/codecs/onyx.c17
-rw-r--r--sound/aoa/codecs/tas.c13
-rw-r--r--sound/aoa/soundbus/i2sbus/pcm.c1
-rw-r--r--sound/arm/aaci.c4
-rw-r--r--sound/arm/pxa2xx-ac97-lib.c3
-rw-r--r--sound/arm/pxa2xx-ac97.c13
-rw-r--r--sound/arm/pxa2xx-pcm.c1
-rw-r--r--sound/atmel/abdac.c2
-rw-r--r--sound/atmel/ac97c.c14
-rw-r--r--sound/core/Kconfig7
-rw-r--r--sound/core/Makefile5
-rw-r--r--sound/core/compress_offload.c768
-rw-r--r--sound/core/control.c87
-rw-r--r--sound/core/control_compat.c4
-rw-r--r--sound/core/ctljack.c56
-rw-r--r--sound/core/device.c1
-rw-r--r--sound/core/hwdep.c10
-rw-r--r--sound/core/info.c1
-rw-r--r--sound/core/info_oss.c1
-rw-r--r--sound/core/init.c170
-rw-r--r--sound/core/isadma.c1
-rw-r--r--sound/core/jack.c6
-rw-r--r--sound/core/memalloc.c4
-rw-r--r--sound/core/memory.c1
-rw-r--r--sound/core/misc.c4
-rw-r--r--sound/core/oss/mixer_oss.c3
-rw-r--r--sound/core/oss/pcm_oss.c4
-rw-r--r--sound/core/pcm.c100
-rw-r--r--sound/core/pcm_lib.c63
-rw-r--r--sound/core/pcm_memory.c1
-rw-r--r--sound/core/pcm_misc.c1
-rw-r--r--sound/core/pcm_native.c37
-rw-r--r--sound/core/rawmidi.c2
-rw-r--r--sound/core/seq/oss/seq_oss.c2
-rw-r--r--sound/core/seq/oss/seq_oss_init.c1
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c1
-rw-r--r--sound/core/seq/seq.c2
-rw-r--r--sound/core/seq/seq_clientmgr.c1
-rw-r--r--sound/core/seq/seq_device.c1
-rw-r--r--sound/core/seq/seq_dummy.c4
-rw-r--r--sound/core/seq/seq_info.c1
-rw-r--r--sound/core/seq/seq_lock.c1
-rw-r--r--sound/core/seq/seq_memory.c1
-rw-r--r--sound/core/seq/seq_midi.c2
-rw-r--r--sound/core/seq/seq_midi_emul.c1
-rw-r--r--sound/core/seq/seq_midi_event.c1
-rw-r--r--sound/core/seq/seq_ports.c1
-rw-r--r--sound/core/seq/seq_system.c1
-rw-r--r--sound/core/seq/seq_virmidi.c1
-rw-r--r--sound/core/sound.c3
-rw-r--r--sound/core/sound_oss.c1
-rw-r--r--sound/core/timer.c2
-rw-r--r--sound/core/vmaster.c65
-rw-r--r--sound/drivers/aloop.c17
-rw-r--r--sound/drivers/dummy.c8
-rw-r--r--sound/drivers/ml403-ac97cr.c21
-rw-r--r--sound/drivers/mpu401/mpu401.c11
-rw-r--r--sound/drivers/mpu401/mpu401_uart.c21
-rw-r--r--sound/drivers/mtpav.c3
-rw-r--r--sound/drivers/mts64.c3
-rw-r--r--sound/drivers/opl3/opl3_lib.c1
-rw-r--r--sound/drivers/opl3/opl3_midi.c2
-rw-r--r--sound/drivers/opl3/opl3_oss.c1
-rw-r--r--sound/drivers/opl3/opl3_seq.c3
-rw-r--r--sound/drivers/opl3/opl3_synth.c1
-rw-r--r--sound/drivers/opl4/opl4_lib.c1
-rw-r--r--sound/drivers/opl4/opl4_proc.c1
-rw-r--r--sound/drivers/opl4/opl4_seq.c1
-rw-r--r--sound/drivers/pcsp/pcsp.c6
-rw-r--r--sound/drivers/pcsp/pcsp_lib.c2
-rw-r--r--sound/drivers/portman2x4.c3
-rw-r--r--sound/drivers/serial-u16550.c8
-rw-r--r--sound/drivers/virmidi.c4
-rw-r--r--sound/drivers/vx/vx_core.c1
-rw-r--r--sound/drivers/vx/vx_hwdep.c1
-rw-r--r--sound/firewire/cmp.c2
-rw-r--r--sound/firewire/isight.c1
-rw-r--r--sound/firewire/iso-resources.c1
-rw-r--r--sound/firewire/packets-buffer.c1
-rw-r--r--sound/firewire/speakers.c5
-rw-r--r--sound/i2c/cs8427.c1
-rw-r--r--sound/i2c/i2c.c1
-rw-r--r--sound/i2c/other/ak4113.c1
-rw-r--r--sound/i2c/other/ak4114.c1
-rw-r--r--sound/i2c/other/ak4117.c1
-rw-r--r--sound/i2c/other/ak4xxx-adda.c1
-rw-r--r--sound/i2c/other/pt2258.c1
-rw-r--r--sound/i2c/other/tea575x-tuner.c1
-rw-r--r--sound/i2c/tea6330t.c1
-rw-r--r--sound/isa/ad1816a/ad1816a.c6
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c2
-rw-r--r--sound/isa/ad1848/ad1848.c6
-rw-r--r--sound/isa/adlib.c2
-rw-r--r--sound/isa/als100.c5
-rw-r--r--sound/isa/azt2320.c7
-rw-r--r--sound/isa/cmi8330.c8
-rw-r--r--sound/isa/cs423x/cs4231.c5
-rw-r--r--sound/isa/cs423x/cs4236.c9
-rw-r--r--sound/isa/es1688/es1688.c8
-rw-r--r--sound/isa/es1688/es1688_lib.c3
-rw-r--r--sound/isa/es18xx.c12
-rw-r--r--sound/isa/galaxy/galaxy.c5
-rw-r--r--sound/isa/gus/gus_main.c3
-rw-r--r--sound/isa/gus/gus_volume.c1
-rw-r--r--sound/isa/gus/gusclassic.c4
-rw-r--r--sound/isa/gus/gusextreme.c7
-rw-r--r--sound/isa/gus/gusmax.c6
-rw-r--r--sound/isa/gus/interwave.c8
-rw-r--r--sound/isa/msnd/msnd.c1
-rw-r--r--sound/isa/msnd/msnd_midi.c1
-rw-r--r--sound/isa/msnd/msnd_pinnacle.c4
-rw-r--r--sound/isa/msnd/msnd_pinnacle_mixer.c1
-rw-r--r--sound/isa/opl3sa2.c13
-rw-r--r--sound/isa/opti9xx/miro.c7
-rw-r--r--sound/isa/opti9xx/opti92x-ad1848.c8
-rw-r--r--sound/isa/sb/emu8000.c1
-rw-r--r--sound/isa/sb/emu8000_callback.c1
-rw-r--r--sound/isa/sb/emu8000_synth.c1
-rw-r--r--sound/isa/sb/jazz16.c3
-rw-r--r--sound/isa/sb/sb16.c11
-rw-r--r--sound/isa/sb/sb16_csp.c1
-rw-r--r--sound/isa/sb/sb16_main.c1
-rw-r--r--sound/isa/sb/sb8.c4
-rw-r--r--sound/isa/sb/sb8_main.c1
-rw-r--r--sound/isa/sb/sb_common.c3
-rw-r--r--sound/isa/sc6000.c5
-rw-r--r--sound/isa/sscape.c5
-rw-r--r--sound/isa/wavefront/wavefront.c13
-rw-r--r--sound/isa/wavefront/wavefront_fx.c1
-rw-r--r--sound/isa/wavefront/wavefront_synth.c1
-rw-r--r--sound/isa/wss/wss_lib.c3
-rw-r--r--sound/mips/Kconfig7
-rw-r--r--sound/mips/au1x00.c5
-rw-r--r--sound/mips/hal2.c14
-rw-r--r--sound/mips/sgio2audio.c14
-rw-r--r--sound/oss/Kconfig6
-rw-r--r--sound/oss/ad1848.c8
-rw-r--r--sound/oss/msnd_pinnacle.c2
-rw-r--r--sound/oss/pas2_card.c12
-rw-r--r--sound/oss/pss.c10
-rw-r--r--sound/oss/sound_timer.c2
-rw-r--r--sound/oss/trix.c2
-rw-r--r--sound/pci/ac97/ac97_codec.c4
-rw-r--r--sound/pci/ac97/ac97_pcm.c1
-rw-r--r--sound/pci/ad1889.c3
-rw-r--r--sound/pci/ak4531_codec.c1
-rw-r--r--sound/pci/ali5451/ali5451.c6
-rw-r--r--sound/pci/als300.c11
-rw-r--r--sound/pci/als4000.c9
-rw-r--r--sound/pci/asihpi/asihpi.c295
-rw-r--r--sound/pci/asihpi/hpi.h74
-rw-r--r--sound/pci/asihpi/hpi6000.c61
-rw-r--r--sound/pci/asihpi/hpi6000.h2
-rw-r--r--sound/pci/asihpi/hpi6205.c57
-rw-r--r--sound/pci/asihpi/hpi_internal.h115
-rw-r--r--sound/pci/asihpi/hpi_version.h32
-rw-r--r--sound/pci/asihpi/hpicmn.c32
-rw-r--r--sound/pci/asihpi/hpicmn.h13
-rw-r--r--sound/pci/asihpi/hpidebug.c2
-rw-r--r--sound/pci/asihpi/hpidebug.h2
-rw-r--r--sound/pci/asihpi/hpidspcd.c30
-rw-r--r--sound/pci/asihpi/hpidspcd.h4
-rw-r--r--sound/pci/asihpi/hpifunc.c10
-rw-r--r--sound/pci/asihpi/hpimsginit.c2
-rw-r--r--sound/pci/asihpi/hpimsginit.h2
-rw-r--r--sound/pci/asihpi/hpimsgx.c3
-rw-r--r--sound/pci/asihpi/hpimsgx.h2
-rw-r--r--sound/pci/asihpi/hpioctl.c64
-rw-r--r--sound/pci/asihpi/hpioctl.h2
-rw-r--r--sound/pci/asihpi/hpios.c2
-rw-r--r--sound/pci/asihpi/hpios.h16
-rw-r--r--sound/pci/asihpi/hpipcida.h2
-rw-r--r--sound/pci/atiixp.c6
-rw-r--r--sound/pci/atiixp_modem.c4
-rw-r--r--sound/pci/au88x0/au88x0.c17
-rw-r--r--sound/pci/au88x0/au88x0.h14
-rw-r--r--sound/pci/au88x0/au88x0_core.c30
-rw-r--r--sound/pci/au88x0/au88x0_game.c1
-rw-r--r--sound/pci/au88x0/au88x0_mpu401.c6
-rw-r--r--sound/pci/au88x0/au88x0_pcm.c135
-rw-r--r--sound/pci/au88x0/au88x0_xtalk.c151
-rw-r--r--sound/pci/aw2/aw2-alsa.c3
-rw-r--r--sound/pci/azt3328.c12
-rw-r--r--sound/pci/bt87x.c6
-rw-r--r--sound/pci/ca0106/ca0106_main.c4
-rw-r--r--sound/pci/cmipci.c11
-rw-r--r--sound/pci/cs4281.c6
-rw-r--r--sound/pci/cs46xx/cs46xx.c10
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c1
-rw-r--r--sound/pci/cs5530.c11
-rw-r--r--sound/pci/cs5535audio/cs5535audio.c4
-rw-r--r--sound/pci/cs5535audio/cs5535audio_pcm.c2
-rw-r--r--sound/pci/ctxfi/ctpcm.c2
-rw-r--r--sound/pci/ctxfi/ctsrc.c4
-rw-r--r--sound/pci/ctxfi/cttimer.c4
-rw-r--r--sound/pci/ctxfi/ctvmem.c2
-rw-r--r--sound/pci/ctxfi/ctvmem.h2
-rw-r--r--sound/pci/ctxfi/xfi.c3
-rw-r--r--sound/pci/echoaudio/darla20.c2
-rw-r--r--sound/pci/echoaudio/darla24.c2
-rw-r--r--sound/pci/echoaudio/echo3g.c2
-rw-r--r--sound/pci/echoaudio/echoaudio.c4
-rw-r--r--sound/pci/echoaudio/gina20.c2
-rw-r--r--sound/pci/echoaudio/gina24.c2
-rw-r--r--sound/pci/echoaudio/indigo.c2
-rw-r--r--sound/pci/echoaudio/indigodj.c2
-rw-r--r--sound/pci/echoaudio/indigodjx.c2
-rw-r--r--sound/pci/echoaudio/indigoio.c2
-rw-r--r--sound/pci/echoaudio/indigoiox.c2
-rw-r--r--sound/pci/echoaudio/layla20.c2
-rw-r--r--sound/pci/echoaudio/layla24.c2
-rw-r--r--sound/pci/echoaudio/mia.c2
-rw-r--r--sound/pci/echoaudio/mona.c2
-rw-r--r--sound/pci/emu10k1/emu10k1.c6
-rw-r--r--sound/pci/emu10k1/emu10k1_callback.c1
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c13
-rw-r--r--sound/pci/emu10k1/emu10k1_synth.c1
-rw-r--r--sound/pci/emu10k1/emu10k1x.c4
-rw-r--r--sound/pci/emu10k1/emupcm.c5
-rw-r--r--sound/pci/emu10k1/io.c1
-rw-r--r--sound/pci/emu10k1/memory.c1
-rw-r--r--sound/pci/emu10k1/voice.c1
-rw-r--r--sound/pci/ens1370.c6
-rw-r--r--sound/pci/es1938.c9
-rw-r--r--sound/pci/es1968.c11
-rw-r--r--sound/pci/fm801.c33
-rw-r--r--sound/pci/hda/Kconfig1
-rw-r--r--sound/pci/hda/Makefile5
-rw-r--r--sound/pci/hda/alc260_quirks.c1272
-rw-r--r--sound/pci/hda/alc262_quirks.c1353
-rw-r--r--sound/pci/hda/alc268_quirks.c636
-rw-r--r--sound/pci/hda/alc269_quirks.c674
-rw-r--r--sound/pci/hda/alc662_quirks.c1408
-rw-r--r--sound/pci/hda/alc680_quirks.c222
-rw-r--r--sound/pci/hda/alc861_quirks.c725
-rw-r--r--sound/pci/hda/alc861vd_quirks.c605
-rw-r--r--sound/pci/hda/alc880_quirks.c1898
-rw-r--r--sound/pci/hda/alc882_quirks.c3755
-rw-r--r--sound/pci/hda/alc_quirks.c467
-rw-r--r--sound/pci/hda/hda_beep.c1
-rw-r--r--sound/pci/hda/hda_codec.c696
-rw-r--r--sound/pci/hda/hda_codec.h11
-rw-r--r--sound/pci/hda/hda_eld.c78
-rw-r--r--sound/pci/hda/hda_generic.c1
-rw-r--r--sound/pci/hda/hda_hwdep.c9
-rw-r--r--sound/pci/hda/hda_intel.c375
-rw-r--r--sound/pci/hda/hda_jack.c375
-rw-r--r--sound/pci/hda/hda_jack.h75
-rw-r--r--sound/pci/hda/hda_local.h111
-rw-r--r--sound/pci/hda/hda_proc.c14
-rw-r--r--sound/pci/hda/hda_trace.h117
-rw-r--r--sound/pci/hda/patch_analog.c246
-rw-r--r--sound/pci/hda/patch_ca0110.c7
-rw-r--r--sound/pci/hda/patch_ca0132.c34
-rw-r--r--sound/pci/hda/patch_cirrus.c253
-rw-r--r--sound/pci/hda/patch_cmedia.c1
-rw-r--r--sound/pci/hda/patch_conexant.c397
-rw-r--r--sound/pci/hda/patch_hdmi.c202
-rw-r--r--sound/pci/hda/patch_realtek.c3781
-rw-r--r--sound/pci/hda/patch_si3054.c1
-rw-r--r--sound/pci/hda/patch_sigmatel.c697
-rw-r--r--sound/pci/hda/patch_via.c515
-rw-r--r--sound/pci/ice1712/ak4xxx.c1
-rw-r--r--sound/pci/ice1712/amp.c7
-rw-r--r--sound/pci/ice1712/envy24ht.h1
-rw-r--r--sound/pci/ice1712/ice1712.c16
-rw-r--r--sound/pci/ice1712/ice1724.c90
-rw-r--r--sound/pci/intel8x0.c81
-rw-r--r--sound/pci/intel8x0m.c4
-rw-r--r--sound/pci/korg1212/korg1212.c4
-rw-r--r--sound/pci/lola/lola.c4
-rw-r--r--sound/pci/lx6464es/lx6464es.c2
-rw-r--r--sound/pci/lx6464es/lx_core.c23
-rw-r--r--sound/pci/lx6464es/lx_core.h3
-rw-r--r--sound/pci/maestro3.c10
-rw-r--r--sound/pci/mixart/mixart.c4
-rw-r--r--sound/pci/mixart/mixart_hwdep.c1
-rw-r--r--sound/pci/nm256/nm256.c14
-rw-r--r--sound/pci/oxygen/oxygen.c3
-rw-r--r--sound/pci/oxygen/oxygen_io.c1
-rw-r--r--sound/pci/oxygen/oxygen_lib.c7
-rw-r--r--sound/pci/oxygen/oxygen_mixer.c25
-rw-r--r--sound/pci/oxygen/virtuoso.c3
-rw-r--r--sound/pci/oxygen/xonar_cs43xx.c1
-rw-r--r--sound/pci/oxygen/xonar_dg.c3
-rw-r--r--sound/pci/oxygen/xonar_pcm179x.c1
-rw-r--r--sound/pci/oxygen/xonar_wm87x6.c7
-rw-r--r--sound/pci/pcxhr/pcxhr.c6
-rw-r--r--sound/pci/pcxhr/pcxhr_hwdep.c1
-rw-r--r--sound/pci/riptide/riptide.c5
-rw-r--r--sound/pci/rme32.c6
-rw-r--r--sound/pci/rme96.c4
-rw-r--r--sound/pci/rme9652/hdsp.c9
-rw-r--r--sound/pci/rme9652/hdspm.c230
-rw-r--r--sound/pci/rme9652/rme9652.c6
-rw-r--r--sound/pci/sis7019.c93
-rw-r--r--sound/pci/sonicvibes.c15
-rw-r--r--sound/pci/trident/trident.c9
-rw-r--r--sound/pci/trident/trident_main.c1
-rw-r--r--sound/pci/via82xx.c19
-rw-r--r--sound/pci/via82xx_modem.c4
-rw-r--r--sound/pci/vx222/vx222.c6
-rw-r--r--sound/pci/ymfpci/ymfpci.c32
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c63
-rw-r--r--sound/pcmcia/pdaudiocf/pdaudiocf.c4
-rw-r--r--sound/pcmcia/vx/vxpocket.c4
-rw-r--r--sound/ppc/keywest.c1
-rw-r--r--sound/ppc/powermac.c4
-rw-r--r--sound/ppc/snd_ps3.c5
-rw-r--r--sound/sh/aica.c4
-rw-r--r--sound/sh/sh_dac_audio.c14
-rw-r--r--sound/soc/Kconfig21
-rw-r--r--sound/soc/Makefile4
-rw-r--r--sound/soc/atmel/Kconfig23
-rw-r--r--sound/soc/atmel/Makefile4
-rw-r--r--sound/soc/atmel/atmel-pcm.c21
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c14
-rw-r--r--sound/soc/atmel/playpaq_wm8510.c471
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c3
-rw-r--r--sound/soc/atmel/snd-soc-afeb9260.c40
-rw-r--r--sound/soc/au1x/Kconfig44
-rw-r--r--sound/soc/au1x/Makefile10
-rw-r--r--sound/soc/au1x/ac97c.c352
-rw-r--r--sound/soc/au1x/db1000.c65
-rw-r--r--sound/soc/au1x/db1200.c138
-rw-r--r--sound/soc/au1x/dbdma2.c116
-rw-r--r--sound/soc/au1x/dma.c358
-rw-r--r--sound/soc/au1x/i2sc.c319
-rw-r--r--sound/soc/au1x/psc-ac97.c84
-rw-r--r--sound/soc/au1x/psc-i2s.c92
-rw-r--r--sound/soc/au1x/psc.h16
-rw-r--r--sound/soc/blackfin/Kconfig13
-rw-r--r--sound/soc/blackfin/Makefile2
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c19
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c13
-rw-r--r--sound/soc/blackfin/bf5xx-ad1836.c18
-rw-r--r--sound/soc/blackfin/bf5xx-ad193x.c22
-rw-r--r--sound/soc/blackfin/bf5xx-ad1980.c1
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c32
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c19
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c15
-rw-r--r--sound/soc/blackfin/bf5xx-sport.c1
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c21
-rw-r--r--sound/soc/blackfin/bf5xx-tdm-pcm.c17
-rw-r--r--sound/soc/blackfin/bf5xx-tdm.c14
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1373.c184
-rw-r--r--sound/soc/blackfin/bfin-eval-adau1701.c29
-rw-r--r--sound/soc/blackfin/bfin-eval-adav80x.c27
-rw-r--r--sound/soc/codecs/88pm860x-codec.c52
-rw-r--r--sound/soc/codecs/Kconfig51
-rw-r--r--sound/soc/codecs/Makefile34
-rw-r--r--sound/soc/codecs/ac97.c17
-rw-r--r--sound/soc/codecs/ad1836.c17
-rw-r--r--sound/soc/codecs/ad1836.h2
-rw-r--r--sound/soc/codecs/ad193x.c277
-rw-r--r--sound/soc/codecs/ad193x.h53
-rw-r--r--sound/soc/codecs/ad1980.c25
-rw-r--r--sound/soc/codecs/ad73311.c12
-rw-r--r--sound/soc/codecs/adau1373.c1409
-rw-r--r--sound/soc/codecs/adau1373.h29
-rw-r--r--sound/soc/codecs/adau1701.c13
-rw-r--r--sound/soc/codecs/adav80x.c5
-rw-r--r--sound/soc/codecs/ads117x.c13
-rw-r--r--sound/soc/codecs/ads117x.h13
-rw-r--r--sound/soc/codecs/ak4104.c182
-rw-r--r--sound/soc/codecs/ak4535.c201
-rw-r--r--sound/soc/codecs/ak4535.h2
-rw-r--r--sound/soc/codecs/ak4641.c24
-rw-r--r--sound/soc/codecs/ak4642.c250
-rw-r--r--sound/soc/codecs/ak4671.c32
-rw-r--r--sound/soc/codecs/alc5623.c44
-rw-r--r--sound/soc/codecs/alc5632.c1234
-rw-r--r--sound/soc/codecs/alc5632.h252
-rw-r--r--sound/soc/codecs/cq93vc.c18
-rw-r--r--sound/soc/codecs/cs4270.c37
-rw-r--r--sound/soc/codecs/cs4271.c19
-rw-r--r--sound/soc/codecs/cs42l51.c58
-rw-r--r--sound/soc/codecs/cs42l73.c1453
-rw-r--r--sound/soc/codecs/cs42l73.h227
-rw-r--r--sound/soc/codecs/cx20442.c61
-rw-r--r--sound/soc/codecs/da7210.c839
-rw-r--r--sound/soc/codecs/dfbmcs320.c12
-rw-r--r--sound/soc/codecs/dmic.c13
-rw-r--r--sound/soc/codecs/jz4740.c29
-rw-r--r--sound/soc/codecs/lm4857.c17
-rw-r--r--sound/soc/codecs/max9768.c247
-rw-r--r--sound/soc/codecs/max98088.c53
-rw-r--r--sound/soc/codecs/max98095.c69
-rw-r--r--sound/soc/codecs/max9850.c27
-rw-r--r--sound/soc/codecs/max9877.c12
-rw-r--r--sound/soc/codecs/pcm3008.c15
-rw-r--r--sound/soc/codecs/rt5631.c1769
-rw-r--r--sound/soc/codecs/rt5631.h701
-rw-r--r--sound/soc/codecs/sgtl5000.c100
-rw-r--r--sound/soc/codecs/sgtl5000.h2
-rw-r--r--sound/soc/codecs/sigmadsp.c246
-rw-r--r--sound/soc/codecs/sigmadsp.h21
-rw-r--r--sound/soc/codecs/sn95031.c44
-rw-r--r--sound/soc/codecs/spdif_transciever.c13
-rw-r--r--sound/soc/codecs/ssm2602.c125
-rw-r--r--sound/soc/codecs/ssm2602.h6
-rw-r--r--sound/soc/codecs/sta32x.c218
-rw-r--r--sound/soc/codecs/sta32x.h1
-rw-r--r--sound/soc/codecs/stac9766.c23
-rw-r--r--sound/soc/codecs/tlv320aic23.c195
-rw-r--r--sound/soc/codecs/tlv320aic26.c12
-rw-r--r--sound/soc/codecs/tlv320aic32x4.c140
-rw-r--r--sound/soc/codecs/tlv320aic3x.c141
-rw-r--r--sound/soc/codecs/tlv320aic3x.h9
-rw-r--r--sound/soc/codecs/tlv320dac33.c52
-rw-r--r--sound/soc/codecs/tpa6130a2.c22
-rw-r--r--sound/soc/codecs/twl4030.c129
-rw-r--r--sound/soc/codecs/twl6040.c873
-rw-r--r--sound/soc/codecs/twl6040.h15
-rw-r--r--sound/soc/codecs/uda134x.c23
-rw-r--r--sound/soc/codecs/uda1380.c70
-rw-r--r--sound/soc/codecs/wl1273.c18
-rw-r--r--sound/soc/codecs/wm1250-ev1.c136
-rw-r--r--sound/soc/codecs/wm2000.c240
-rw-r--r--sound/soc/codecs/wm2000.h7
-rw-r--r--sound/soc/codecs/wm2200.c2286
-rw-r--r--sound/soc/codecs/wm2200.h3674
-rw-r--r--sound/soc/codecs/wm5100-tables.c1364
-rw-r--r--sound/soc/codecs/wm5100.c2766
-rw-r--r--sound/soc/codecs/wm5100.h5156
-rw-r--r--sound/soc/codecs/wm8350.c106
-rw-r--r--sound/soc/codecs/wm8400.c62
-rw-r--r--sound/soc/codecs/wm8510.c51
-rw-r--r--sound/soc/codecs/wm8523.c41
-rw-r--r--sound/soc/codecs/wm8580.c106
-rw-r--r--sound/soc/codecs/wm8711.c52
-rw-r--r--sound/soc/codecs/wm8727.c14
-rw-r--r--sound/soc/codecs/wm8728.c22
-rw-r--r--sound/soc/codecs/wm8731.c141
-rw-r--r--sound/soc/codecs/wm8737.c17
-rw-r--r--sound/soc/codecs/wm8741.c180
-rw-r--r--sound/soc/codecs/wm8750.c98
-rw-r--r--sound/soc/codecs/wm8753.c246
-rw-r--r--sound/soc/codecs/wm8770.c31
-rw-r--r--sound/soc/codecs/wm8776.c109
-rw-r--r--sound/soc/codecs/wm8782.c14
-rw-r--r--sound/soc/codecs/wm8804.c172
-rw-r--r--sound/soc/codecs/wm8900.c150
-rw-r--r--sound/soc/codecs/wm8903.c664
-rw-r--r--sound/soc/codecs/wm8904.c869
-rw-r--r--sound/soc/codecs/wm8904.h11
-rw-r--r--sound/soc/codecs/wm8940.c80
-rw-r--r--sound/soc/codecs/wm8955.c254
-rw-r--r--sound/soc/codecs/wm8958-dsp2.c19
-rw-r--r--sound/soc/codecs/wm8960.c113
-rw-r--r--sound/soc/codecs/wm8961.c46
-rw-r--r--sound/soc/codecs/wm8962.c3961
-rw-r--r--sound/soc/codecs/wm8971.c88
-rw-r--r--sound/soc/codecs/wm8974.c69
-rw-r--r--sound/soc/codecs/wm8978.c193
-rw-r--r--sound/soc/codecs/wm8978.h2
-rw-r--r--sound/soc/codecs/wm8983.c14
-rw-r--r--sound/soc/codecs/wm8985.c322
-rw-r--r--sound/soc/codecs/wm8988.c211
-rw-r--r--sound/soc/codecs/wm8990.c118
-rw-r--r--sound/soc/codecs/wm8991.c35
-rw-r--r--sound/soc/codecs/wm8993.c687
-rw-r--r--sound/soc/codecs/wm8993.h9
-rw-r--r--sound/soc/codecs/wm8994-tables.c3147
-rw-r--r--sound/soc/codecs/wm8994.c1438
-rw-r--r--sound/soc/codecs/wm8994.h35
-rw-r--r--sound/soc/codecs/wm8995.c758
-rw-r--r--sound/soc/codecs/wm8996.c1391
-rw-r--r--sound/soc/codecs/wm8996.h4
-rw-r--r--sound/soc/codecs/wm9081.c456
-rw-r--r--sound/soc/codecs/wm9090.c305
-rw-r--r--sound/soc/codecs/wm9705.c18
-rw-r--r--sound/soc/codecs/wm9712.c35
-rw-r--r--sound/soc/codecs/wm9713.c23
-rw-r--r--sound/soc/codecs/wm_hubs.c236
-rw-r--r--sound/soc/codecs/wm_hubs.h15
-rw-r--r--sound/soc/davinci/Kconfig1
-rw-r--r--sound/soc/davinci/davinci-evm.c8
-rw-r--r--sound/soc/davinci/davinci-i2s.c58
-rw-r--r--sound/soc/davinci/davinci-mcasp.c74
-rw-r--r--sound/soc/davinci/davinci-pcm.c144
-rw-r--r--sound/soc/davinci/davinci-sffsdr.c1
-rw-r--r--sound/soc/davinci/davinci-vcif.c28
-rw-r--r--sound/soc/ep93xx/Kconfig1
-rw-r--r--sound/soc/ep93xx/edb93xx.c78
-rw-r--r--sound/soc/ep93xx/ep93xx-ac97.c16
-rw-r--r--sound/soc/ep93xx/ep93xx-i2s.c15
-rw-r--r--sound/soc/ep93xx/ep93xx-pcm.c171
-rw-r--r--sound/soc/ep93xx/simone.c63
-rw-r--r--sound/soc/ep93xx/snappercl15.c64
-rw-r--r--sound/soc/fsl/efika-audio-fabric.c14
-rw-r--r--sound/soc/fsl/fsl_dma.c26
-rw-r--r--sound/soc/fsl/fsl_ssi.c230
-rw-r--r--sound/soc/fsl/mpc5200_dma.c35
-rw-r--r--sound/soc/fsl/mpc5200_psc_ac97.c20
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c18
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c55
-rw-r--r--sound/soc/fsl/p1022_ds.c57
-rw-r--r--sound/soc/fsl/pcm030-audio-fabric.c14
-rw-r--r--sound/soc/imx/Kconfig30
-rw-r--r--sound/soc/imx/Makefile15
-rw-r--r--sound/soc/imx/eukrea-tlv320.c41
-rw-r--r--sound/soc/imx/imx-audmux.c314
-rw-r--r--sound/soc/imx/imx-audmux.h60
-rw-r--r--sound/soc/imx/imx-pcm-dma-mx2.c233
-rw-r--r--sound/soc/imx/imx-pcm-fiq.c25
-rw-r--r--sound/soc/imx/imx-pcm.c105
-rw-r--r--sound/soc/imx/imx-pcm.h32
-rw-r--r--sound/soc/imx/imx-ssi.c136
-rw-r--r--sound/soc/imx/imx-ssi.h22
-rw-r--r--sound/soc/imx/mx27vis-aic32x4.c160
-rw-r--r--sound/soc/imx/phycore-ac97.c28
-rw-r--r--sound/soc/imx/wm1133-ev1.c27
-rw-r--r--sound/soc/jz4740/jz4740-i2s.c14
-rw-r--r--sound/soc/jz4740/jz4740-pcm.c19
-rw-r--r--sound/soc/jz4740/qi_lb60.c57
-rw-r--r--sound/soc/kirkwood/Kconfig3
-rw-r--r--sound/soc/kirkwood/kirkwood-dma.c36
-rw-r--r--sound/soc/kirkwood/kirkwood-i2s.c21
-rw-r--r--sound/soc/kirkwood/kirkwood-openrd.c61
-rw-r--r--sound/soc/kirkwood/kirkwood-t5325.c74
-rw-r--r--sound/soc/kirkwood/kirkwood.h1
-rw-r--r--sound/soc/mid-x86/Kconfig1
-rw-r--r--sound/soc/mid-x86/mfld_machine.c24
-rw-r--r--sound/soc/mid-x86/sst_platform.c172
-rw-r--r--sound/soc/mid-x86/sst_platform.h82
-rw-r--r--sound/soc/mxs/Kconfig20
-rw-r--r--sound/soc/mxs/Makefile10
-rw-r--r--sound/soc/mxs/mxs-pcm.c247
-rw-r--r--sound/soc/mxs/mxs-pcm.h27
-rw-r--r--sound/soc/mxs/mxs-saif.c762
-rw-r--r--sound/soc/mxs/mxs-saif.h134
-rw-r--r--sound/soc/mxs/mxs-sgtl5000.c165
-rw-r--r--sound/soc/nuc900/nuc900-ac97.c18
-rw-r--r--sound/soc/nuc900/nuc900-audio.c1
-rw-r--r--sound/soc/nuc900/nuc900-pcm.c17
-rw-r--r--sound/soc/omap/Kconfig20
-rw-r--r--sound/soc/omap/Makefile10
-rw-r--r--sound/soc/omap/am3517evm.c54
-rw-r--r--sound/soc/omap/ams-delta.c17
-rw-r--r--sound/soc/omap/igep0020.c27
-rw-r--r--sound/soc/omap/mcbsp.c1040
-rw-r--r--sound/soc/omap/mcbsp.h346
-rw-r--r--sound/soc/omap/mcpdm.c470
-rw-r--r--sound/soc/omap/mcpdm.h153
-rw-r--r--sound/soc/omap/n810.c63
-rw-r--r--sound/soc/omap/omap-abe-twl6040.c349
-rw-r--r--sound/soc/omap/omap-dmic.c545
-rw-r--r--sound/soc/omap/omap-dmic.h69
-rw-r--r--sound/soc/omap/omap-hdmi.c14
-rw-r--r--sound/soc/omap/omap-mcbsp.c354
-rw-r--r--sound/soc/omap/omap-mcbsp.h2
-rw-r--r--sound/soc/omap/omap-mcpdm.c492
-rw-r--r--sound/soc/omap/omap-mcpdm.h107
-rw-r--r--sound/soc/omap/omap-pcm.c26
-rw-r--r--sound/soc/omap/omap-pcm.h2
-rw-r--r--sound/soc/omap/omap3beagle.c3
-rw-r--r--sound/soc/omap/omap3evm.c27
-rw-r--r--sound/soc/omap/omap3pandora.c34
-rw-r--r--sound/soc/omap/omap4-hdmi-card.c14
-rw-r--r--sound/soc/omap/osk5912.c54
-rw-r--r--sound/soc/omap/overo.c27
-rw-r--r--sound/soc/omap/rx51.c53
-rw-r--r--sound/soc/omap/sdp3430.c94
-rw-r--r--sound/soc/omap/sdp4430.c223
-rw-r--r--sound/soc/omap/zoom2.c102
-rw-r--r--sound/soc/pxa/Kconfig5
-rw-r--r--sound/soc/pxa/corgi.c96
-rw-r--r--sound/soc/pxa/e740_wm9705.c86
-rw-r--r--sound/soc/pxa/e750_wm9705.c75
-rw-r--r--sound/soc/pxa/e800_wm9712.c74
-rw-r--r--sound/soc/pxa/em-x270.c1
-rw-r--r--sound/soc/pxa/hx4700.c35
-rw-r--r--sound/soc/pxa/imote2.c58
-rw-r--r--sound/soc/pxa/magician.c7
-rw-r--r--sound/soc/pxa/mioa701_wm9713.c15
-rw-r--r--sound/soc/pxa/palm27x.c18
-rw-r--r--sound/soc/pxa/poodle.c94
-rw-r--r--sound/soc/pxa/pxa-ssp.c78
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c28
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c2
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c13
-rw-r--r--sound/soc/pxa/raumfeld.c8
-rw-r--r--sound/soc/pxa/saarb.c28
-rw-r--r--sound/soc/pxa/spitz.c55
-rw-r--r--sound/soc/pxa/tavorevb3.c29
-rw-r--r--sound/soc/pxa/tosa.c81
-rw-r--r--sound/soc/pxa/z2.c35
-rw-r--r--sound/soc/pxa/zylonite.c10
-rw-r--r--sound/soc/s6000/s6000-i2s.c14
-rw-r--r--sound/soc/s6000/s6000-pcm.c18
-rw-r--r--sound/soc/s6000/s6105-ipcam.c1
-rw-r--r--sound/soc/samsung/Kconfig30
-rw-r--r--sound/soc/samsung/Makefile8
-rw-r--r--sound/soc/samsung/ac97.c35
-rw-r--r--sound/soc/samsung/dma.c168
-rw-r--r--sound/soc/samsung/dma.h4
-rw-r--r--sound/soc/samsung/goni_wm8994.c17
-rw-r--r--sound/soc/samsung/h1940_uda1380.c21
-rw-r--r--sound/soc/samsung/i2s.c72
-rw-r--r--sound/soc/samsung/i2s.h2
-rw-r--r--sound/soc/samsung/idma.c21
-rw-r--r--sound/soc/samsung/idma.h2
-rw-r--r--sound/soc/samsung/jive_wm8750.c22
-rw-r--r--sound/soc/samsung/littlemill.c256
-rw-r--r--sound/soc/samsung/ln2440sbc_alc650.c2
-rw-r--r--sound/soc/samsung/lowland.c237
-rw-r--r--sound/soc/samsung/neo1973_wm8753.c78
-rw-r--r--sound/soc/samsung/pcm.c41
-rw-r--r--sound/soc/samsung/rx1950_uda1380.c35
-rw-r--r--sound/soc/samsung/s3c-i2s-v2.c1
-rw-r--r--sound/soc/samsung/s3c2412-i2s.c21
-rw-r--r--sound/soc/samsung/s3c24xx-i2s.c21
-rw-r--r--sound/soc/samsung/s3c24xx_simtec.c9
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_hermes.c29
-rw-r--r--sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c31
-rw-r--r--sound/soc/samsung/s3c24xx_uda134x.c24
-rw-r--r--sound/soc/samsung/smartq_wm8987.c29
-rw-r--r--sound/soc/samsung/smdk2443_wm9710.c2
-rw-r--r--sound/soc/samsung/smdk_spdif.c2
-rw-r--r--sound/soc/samsung/smdk_wm8580.c57
-rw-r--r--sound/soc/samsung/smdk_wm8580pcm.c20
-rw-r--r--sound/soc/samsung/smdk_wm8994.c4
-rw-r--r--sound/soc/samsung/smdk_wm8994pcm.c16
-rw-r--r--sound/soc/samsung/smdk_wm9713.c6
-rw-r--r--sound/soc/samsung/spdif.c19
-rw-r--r--sound/soc/samsung/speyside.c36
-rw-r--r--sound/soc/samsung/tobermory.c (renamed from sound/soc/samsung/speyside_wm8962.c)120
-rw-r--r--sound/soc/sh/dma-sh7760.c12
-rw-r--r--sound/soc/sh/fsi-ak4642.c129
-rw-r--r--sound/soc/sh/fsi-da7210.c2
-rw-r--r--sound/soc/sh/fsi-hdmi.c15
-rw-r--r--sound/soc/sh/fsi.c971
-rw-r--r--sound/soc/sh/hac.c14
-rw-r--r--sound/soc/sh/migor.c1
-rw-r--r--sound/soc/sh/sh7760-ac97.c12
-rw-r--r--sound/soc/sh/siu_dai.c22
-rw-r--r--sound/soc/sh/siu_pcm.c4
-rw-r--r--sound/soc/sh/ssi.c16
-rw-r--r--sound/soc/soc-cache.c779
-rw-r--r--sound/soc/soc-core.c885
-rw-r--r--sound/soc/soc-dapm.c892
-rw-r--r--sound/soc/soc-dmaengine-pcm.c288
-rw-r--r--sound/soc/soc-io.c365
-rw-r--r--sound/soc/soc-jack.c9
-rw-r--r--sound/soc/soc-pcm.c209
-rw-r--r--sound/soc/soc-utils.c52
-rw-r--r--sound/soc/tegra/Kconfig9
-rw-r--r--sound/soc/tegra/Makefile2
-rw-r--r--sound/soc/tegra/tegra_alc5632.c289
-rw-r--r--sound/soc/tegra/tegra_asoc_utils.c1
-rw-r--r--sound/soc/tegra/tegra_das.c70
-rw-r--r--sound/soc/tegra/tegra_i2s.c164
-rw-r--r--sound/soc/tegra/tegra_i2s.h1
-rw-r--r--sound/soc/tegra/tegra_pcm.c22
-rw-r--r--sound/soc/tegra/tegra_spdif.c19
-rw-r--r--sound/soc/tegra/tegra_wm8903.c195
-rw-r--r--sound/soc/tegra/trimslice.c43
-rw-r--r--sound/soc/txx9/txx9aclc-ac97.c15
-rw-r--r--sound/soc/txx9/txx9aclc-generic.c3
-rw-r--r--sound/soc/txx9/txx9aclc.c14
-rw-r--r--sound/sound_core.c2
-rw-r--r--sound/sparc/amd7930.c4
-rw-r--r--sound/sparc/cs4231.c15
-rw-r--r--sound/sparc/dbri.c17
-rw-r--r--sound/spi/at73c213.c12
-rw-r--r--sound/synth/emux/emux.c1
-rw-r--r--sound/synth/emux/emux_oss.c1
-rw-r--r--sound/synth/emux/emux_seq.c2
-rw-r--r--sound/synth/emux/emux_synth.c1
-rw-r--r--sound/synth/emux/soundfont.c1
-rw-r--r--sound/synth/util_mem.c1
-rw-r--r--sound/usb/6fire/chip.c20
-rw-r--r--sound/usb/6fire/chip.h1
-rw-r--r--sound/usb/6fire/comm.c1
-rw-r--r--sound/usb/6fire/comm.h1
-rw-r--r--sound/usb/6fire/common.h1
-rw-r--r--sound/usb/6fire/control.c341
-rw-r--r--sound/usb/6fire/control.h7
-rw-r--r--sound/usb/6fire/firmware.c27
-rw-r--r--sound/usb/6fire/midi.c1
-rw-r--r--sound/usb/6fire/midi.h1
-rw-r--r--sound/usb/6fire/pcm.c1
-rw-r--r--sound/usb/6fire/pcm.h1
-rw-r--r--sound/usb/Kconfig3
-rw-r--r--sound/usb/Makefile12
-rw-r--r--sound/usb/caiaq/audio.c5
-rw-r--r--sound/usb/caiaq/device.c23
-rw-r--r--sound/usb/caiaq/device.h1
-rw-r--r--sound/usb/caiaq/input.c155
-rw-r--r--sound/usb/card.c20
-rw-r--r--sound/usb/card.h3
-rw-r--r--sound/usb/clock.c12
-rw-r--r--sound/usb/endpoint.c1200
-rw-r--r--sound/usb/endpoint.h20
-rw-r--r--sound/usb/format.c10
-rw-r--r--sound/usb/helper.c4
-rw-r--r--sound/usb/helper.h2
-rw-r--r--sound/usb/midi.c28
-rw-r--r--sound/usb/misc/ua101.c44
-rw-r--r--sound/usb/mixer.c129
-rw-r--r--sound/usb/mixer_quirks.c10
-rw-r--r--sound/usb/pcm.c40
-rw-r--r--sound/usb/pcm.h3
-rw-r--r--sound/usb/quirks-table.h100
-rw-r--r--sound/usb/quirks.c29
-rw-r--r--sound/usb/stream.c452
-rw-r--r--sound/usb/stream.h12
-rw-r--r--sound/usb/urb.c941
-rw-r--r--sound/usb/urb.h21
-rw-r--r--sound/usb/usbaudio.h1
-rw-r--r--sound/usb/usx2y/us122l.c17
-rw-r--r--sound/usb/usx2y/usb_stream.c6
-rw-r--r--sound/usb/usx2y/usbusx2y.c15
-rw-r--r--sound/usb/usx2y/usbusx2yaudio.c5
-rw-r--r--sound/usb/usx2y/usx2yhwdeppcm.c2
718 files changed, 55909 insertions, 38203 deletions
diff --git a/sound/Kconfig b/sound/Kconfig
index 1fef141ef8e7..261a03c8a209 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -59,7 +59,7 @@ config SOUND_OSS_CORE_PRECLAIM
source "sound/oss/dmasound/Kconfig"
-if !M68K
+if !M68K && !UML
menuconfig SND
tristate "Advanced Linux Sound Architecture"
diff --git a/sound/aoa/codecs/Kconfig b/sound/aoa/codecs/Kconfig
index 808eb11ebacd..0c68e32834c3 100644
--- a/sound/aoa/codecs/Kconfig
+++ b/sound/aoa/codecs/Kconfig
@@ -7,14 +7,6 @@ config SND_AOA_ONYX
codec chip found in the latest Apple machines
(most of those with digital audio output).
-#config SND_AOA_TOPAZ
-# tristate "support Topaz chips"
-# ---help---
-# This option enables support for the Topaz (CS84xx)
-# codec chips found in the latest Apple machines,
-# these chips do the digital input and output on
-# some PowerMacs.
-
config SND_AOA_TAS
tristate "support TAS chips"
select I2C
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/onyx.c
index 3687a6cc9881..270790d384e2 100644
--- a/sound/aoa/codecs/onyx.c
+++ b/sound/aoa/codecs/onyx.c
@@ -1067,7 +1067,6 @@ static int onyx_i2c_probe(struct i2c_client *client,
printk(KERN_DEBUG PFX "created and attached onyx instance\n");
return 0;
fail:
- i2c_set_clientdata(client, NULL);
kfree(onyx);
return -ENODEV;
}
@@ -1112,8 +1111,7 @@ static int onyx_i2c_remove(struct i2c_client *client)
aoa_codec_unregister(&onyx->codec);
of_node_put(onyx->codec.node);
- if (onyx->codec_info)
- kfree(onyx->codec_info);
+ kfree(onyx->codec_info);
kfree(onyx);
return 0;
}
@@ -1134,15 +1132,4 @@ static struct i2c_driver onyx_driver = {
.id_table = onyx_i2c_id,
};
-static int __init onyx_init(void)
-{
- return i2c_add_driver(&onyx_driver);
-}
-
-static void __exit onyx_exit(void)
-{
- i2c_del_driver(&onyx_driver);
-}
-
-module_init(onyx_init);
-module_exit(onyx_exit);
+module_i2c_driver(onyx_driver);
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/tas.c
index fd2188c3df2b..8e63d1f35ce1 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/tas.c
@@ -1026,15 +1026,4 @@ static struct i2c_driver tas_driver = {
.id_table = tas_i2c_id,
};
-static int __init tas_init(void)
-{
- return i2c_add_driver(&tas_driver);
-}
-
-static void __exit tas_exit(void)
-{
- i2c_del_driver(&tas_driver);
-}
-
-module_init(tas_init);
-module_exit(tas_exit);
+module_i2c_driver(tas_driver);
diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/pcm.c
index be838993926d..19491ed9292f 100644
--- a/sound/aoa/soundbus/i2sbus/pcm.c
+++ b/sound/aoa/soundbus/i2sbus/pcm.c
@@ -12,6 +12,7 @@
#include <sound/core.h>
#include <asm/macio.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include "../soundbus.h"
#include "i2sbus.h"
diff --git a/sound/arm/aaci.c b/sound/arm/aaci.c
index d0cead38d5fb..b37b702a3a6a 100644
--- a/sound/arm/aaci.c
+++ b/sound/arm/aaci.c
@@ -443,7 +443,7 @@ static int aaci_pcm_open(struct snd_pcm_substream *substream)
mutex_lock(&aaci->irq_lock);
if (!aaci->users++) {
ret = request_irq(aaci->dev->irq[0], aaci_irq,
- IRQF_SHARED | IRQF_DISABLED, DRIVER_NAME, aaci);
+ IRQF_SHARED, DRIVER_NAME, aaci);
if (ret != 0)
aaci->users--;
}
@@ -1097,6 +1097,8 @@ static struct amba_id aaci_ids[] = {
{ 0, 0 },
};
+MODULE_DEVICE_TABLE(amba, aaci_ids);
+
static struct amba_driver aaci_driver = {
.drv = {
.name = DRIVER_NAME,
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 88eec3847df2..d1aa4218f129 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -16,6 +16,7 @@
#include <linux/interrupt.h>
#include <linux/clk.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <sound/ac97_codec.h>
#include <sound/pxa2xx-lib.h>
@@ -359,7 +360,7 @@ int __devinit pxa2xx_ac97_hw_probe(struct platform_device *dev)
if (ret)
goto err_clk2;
- ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
+ ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, 0, "AC97", NULL);
if (ret < 0)
goto err_irq;
diff --git a/sound/arm/pxa2xx-ac97.c b/sound/arm/pxa2xx-ac97.c
index 5d9411839cd7..3a39626a82d6 100644
--- a/sound/arm/pxa2xx-ac97.c
+++ b/sound/arm/pxa2xx-ac97.c
@@ -251,18 +251,7 @@ static struct platform_driver pxa2xx_ac97_driver = {
},
};
-static int __init pxa2xx_ac97_init(void)
-{
- return platform_driver_register(&pxa2xx_ac97_driver);
-}
-
-static void __exit pxa2xx_ac97_exit(void)
-{
- platform_driver_unregister(&pxa2xx_ac97_driver);
-}
-
-module_init(pxa2xx_ac97_init);
-module_exit(pxa2xx_ac97_exit);
+module_platform_driver(pxa2xx_ac97_driver);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
diff --git a/sound/arm/pxa2xx-pcm.c b/sound/arm/pxa2xx-pcm.c
index 535704f77496..26422a3584ea 100644
--- a/sound/arm/pxa2xx-pcm.c
+++ b/sound/arm/pxa2xx-pcm.c
@@ -10,6 +10,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pxa2xx-lib.h>
diff --git a/sound/atmel/abdac.c b/sound/atmel/abdac.c
index 6fd9391b3a6c..4fa1dbd8ee83 100644
--- a/sound/atmel/abdac.c
+++ b/sound/atmel/abdac.c
@@ -133,7 +133,7 @@ static int atmel_abdac_prepare_dma(struct atmel_abdac *dac,
period_len = frames_to_bytes(runtime, runtime->period_size);
cdesc = dw_dma_cyclic_prep(chan, runtime->dma_addr, buffer_len,
- period_len, DMA_TO_DEVICE);
+ period_len, DMA_MEM_TO_DEV);
if (IS_ERR(cdesc)) {
dev_dbg(&dac->pdev->dev, "could not prepare cyclic DMA\n");
return PTR_ERR(cdesc);
diff --git a/sound/atmel/ac97c.c b/sound/atmel/ac97c.c
index 6e5addeb236b..61dade698358 100644
--- a/sound/atmel/ac97c.c
+++ b/sound/atmel/ac97c.c
@@ -102,7 +102,7 @@ static void atmel_ac97c_dma_capture_period_done(void *arg)
static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
struct snd_pcm_substream *substream,
- enum dma_data_direction direction)
+ enum dma_transfer_direction direction)
{
struct dma_chan *chan;
struct dw_cyclic_desc *cdesc;
@@ -118,7 +118,7 @@ static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
return -EINVAL;
}
- if (direction == DMA_TO_DEVICE)
+ if (direction == DMA_MEM_TO_DEV)
chan = chip->dma.tx_chan;
else
chan = chip->dma.rx_chan;
@@ -133,7 +133,7 @@ static int atmel_ac97c_prepare_dma(struct atmel_ac97c *chip,
return PTR_ERR(cdesc);
}
- if (direction == DMA_TO_DEVICE) {
+ if (direction == DMA_MEM_TO_DEV) {
cdesc->period_callback = atmel_ac97c_dma_playback_period_done;
set_bit(DMA_TX_READY, &chip->flags);
} else {
@@ -393,7 +393,7 @@ static int atmel_ac97c_playback_prepare(struct snd_pcm_substream *substream)
if (cpu_is_at32ap7000()) {
if (!test_bit(DMA_TX_READY, &chip->flags))
retval = atmel_ac97c_prepare_dma(chip, substream,
- DMA_TO_DEVICE);
+ DMA_MEM_TO_DEV);
} else {
/* Initialize and start the PDC */
writel(runtime->dma_addr, chip->regs + ATMEL_PDC_TPR);
@@ -484,7 +484,7 @@ static int atmel_ac97c_capture_prepare(struct snd_pcm_substream *substream)
if (cpu_is_at32ap7000()) {
if (!test_bit(DMA_RX_READY, &chip->flags))
retval = atmel_ac97c_prepare_dma(chip, substream,
- DMA_FROM_DEVICE);
+ DMA_DEV_TO_MEM);
} else {
/* Initialize and start the PDC */
writel(runtime->dma_addr, chip->regs + ATMEL_PDC_RPR);
@@ -899,6 +899,10 @@ static void atmel_ac97c_reset(struct atmel_ac97c *chip)
/* AC97 v2.2 specifications says minimum 1 us. */
udelay(2);
gpio_set_value(chip->reset_pin, 1);
+ } else {
+ ac97c_writel(chip, MR, AC97C_MR_WRST | AC97C_MR_ENA);
+ udelay(2);
+ ac97c_writel(chip, MR, AC97C_MR_ENA);
}
}
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 475455c76610..b413ed05e74d 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -5,7 +5,6 @@ config SND_TIMER
config SND_PCM
tristate
select SND_TIMER
- select GCD
config SND_HWDEP
tristate
@@ -13,6 +12,9 @@ config SND_HWDEP
config SND_RAWMIDI
tristate
+config SND_COMPRESS_OFFLOAD
+ tristate
+
# To be effective this also requires INPUT - users should say:
# select SND_JACK if INPUT=y || INPUT=SND
# to avoid having to force INPUT on.
@@ -207,6 +209,9 @@ config SND_PCM_XRUN_DEBUG
config SND_VMASTER
bool
+config SND_KCTL_JACK
+ bool
+
config SND_DMA_SGBUF
def_bool y
depends on X86
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 350a08d277f4..43d4117428ac 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -7,6 +7,7 @@ snd-y := sound.o init.o memory.o info.o control.o misc.o device.o
snd-$(CONFIG_ISA_DMA_API) += isadma.o
snd-$(CONFIG_SND_OSSEMUL) += sound_oss.o info_oss.o
snd-$(CONFIG_SND_VMASTER) += vmaster.o
+snd-$(CONFIG_SND_KCTL_JACK) += ctljack.o
snd-$(CONFIG_SND_JACK) += jack.o
snd-pcm-objs := pcm.o pcm_native.o pcm_lib.o pcm_timer.o pcm_misc.o \
@@ -21,6 +22,8 @@ snd-hrtimer-objs := hrtimer.o
snd-rtctimer-objs := rtctimer.o
snd-hwdep-objs := hwdep.o
+snd-compress-objs := compress_offload.o
+
obj-$(CONFIG_SND) += snd.o
obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o
obj-$(CONFIG_SND_TIMER) += snd-timer.o
@@ -31,3 +34,5 @@ obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
obj-$(CONFIG_SND_OSSEMUL) += oss/
obj-$(CONFIG_SND_SEQUENCER) += seq/
+
+obj-$(CONFIG_SND_COMPRESS_OFFLOAD) += snd-compress.o
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
new file mode 100644
index 000000000000..a68aed7fce02
--- /dev/null
+++ b/sound/core/compress_offload.c
@@ -0,0 +1,768 @@
+/*
+ * compress_core.c - compress offload core
+ *
+ * Copyright (C) 2011 Intel Corporation
+ * Authors: Vinod Koul <vinod.koul@linux.intel.com>
+ * Pierre-Louis Bossart <pierre-louis.bossart@linux.intel.com>
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ */
+#define FORMAT(fmt) "%s: %d: " fmt, __func__, __LINE__
+#define pr_fmt(fmt) KBUILD_MODNAME ": " FORMAT(fmt)
+
+#include <linux/file.h>
+#include <linux/fs.h>
+#include <linux/list.h>
+#include <linux/mm.h>
+#include <linux/mutex.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/uio.h>
+#include <linux/uaccess.h>
+#include <linux/module.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/compress_params.h>
+#include <sound/compress_offload.h>
+#include <sound/compress_driver.h>
+
+/* TODO:
+ * - add substream support for multiple devices in case of
+ * SND_DYNAMIC_MINORS is not used
+ * - Multiple node representation
+ * driver should be able to register multiple nodes
+ */
+
+static DEFINE_MUTEX(device_mutex);
+
+struct snd_compr_file {
+ unsigned long caps;
+ struct snd_compr_stream stream;
+};
+
+/*
+ * a note on stream states used:
+ * we use follwing states in the compressed core
+ * SNDRV_PCM_STATE_OPEN: When stream has been opened.
+ * SNDRV_PCM_STATE_SETUP: When stream has been initialized. This is done by
+ * calling SNDRV_COMPRESS_SET_PARAMS. running streams will come to this
+ * state at stop by calling SNDRV_COMPRESS_STOP, or at end of drain.
+ * SNDRV_PCM_STATE_RUNNING: When stream has been started and is
+ * decoding/encoding and rendering/capturing data.
+ * SNDRV_PCM_STATE_DRAINING: When stream is draining current data. This is done
+ * by calling SNDRV_COMPRESS_DRAIN.
+ * SNDRV_PCM_STATE_PAUSED: When stream is paused. This is done by calling
+ * SNDRV_COMPRESS_PAUSE. It can be stopped or resumed by calling
+ * SNDRV_COMPRESS_STOP or SNDRV_COMPRESS_RESUME respectively.
+ */
+static int snd_compr_open(struct inode *inode, struct file *f)
+{
+ struct snd_compr *compr;
+ struct snd_compr_file *data;
+ struct snd_compr_runtime *runtime;
+ enum snd_compr_direction dirn;
+ int maj = imajor(inode);
+ int ret;
+
+ if (f->f_flags & O_WRONLY)
+ dirn = SND_COMPRESS_PLAYBACK;
+ else if (f->f_flags & O_RDONLY)
+ dirn = SND_COMPRESS_CAPTURE;
+ else {
+ pr_err("invalid direction\n");
+ return -EINVAL;
+ }
+
+ if (maj == snd_major)
+ compr = snd_lookup_minor_data(iminor(inode),
+ SNDRV_DEVICE_TYPE_COMPRESS);
+ else
+ return -EBADFD;
+
+ if (compr == NULL) {
+ pr_err("no device data!!!\n");
+ return -ENODEV;
+ }
+
+ if (dirn != compr->direction) {
+ pr_err("this device doesn't support this direction\n");
+ return -EINVAL;
+ }
+
+ data = kzalloc(sizeof(*data), GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+ data->stream.ops = compr->ops;
+ data->stream.direction = dirn;
+ data->stream.private_data = compr->private_data;
+ data->stream.device = compr;
+ runtime = kzalloc(sizeof(*runtime), GFP_KERNEL);
+ if (!runtime) {
+ kfree(data);
+ return -ENOMEM;
+ }
+ runtime->state = SNDRV_PCM_STATE_OPEN;
+ init_waitqueue_head(&runtime->sleep);
+ data->stream.runtime = runtime;
+ f->private_data = (void *)data;
+ mutex_lock(&compr->lock);
+ ret = compr->ops->open(&data->stream);
+ mutex_unlock(&compr->lock);
+ if (ret) {
+ kfree(runtime);
+ kfree(data);
+ }
+ return ret;
+}
+
+static int snd_compr_free(struct inode *inode, struct file *f)
+{
+ struct snd_compr_file *data = f->private_data;
+ data->stream.ops->free(&data->stream);
+ kfree(data->stream.runtime->buffer);
+ kfree(data->stream.runtime);
+ kfree(data);
+ return 0;
+}
+
+static void snd_compr_update_tstamp(struct snd_compr_stream *stream,
+ struct snd_compr_tstamp *tstamp)
+{
+ if (!stream->ops->pointer)
+ return;
+ stream->ops->pointer(stream, tstamp);
+ pr_debug("dsp consumed till %d total %d bytes\n",
+ tstamp->byte_offset, tstamp->copied_total);
+ stream->runtime->hw_pointer = tstamp->byte_offset;
+ stream->runtime->total_bytes_transferred = tstamp->copied_total;
+}
+
+static size_t snd_compr_calc_avail(struct snd_compr_stream *stream,
+ struct snd_compr_avail *avail)
+{
+ long avail_calc; /*this needs to be signed variable */
+
+ snd_compr_update_tstamp(stream, &avail->tstamp);
+
+ /* FIXME: This needs to be different for capture stream,
+ available is # of compressed data, for playback it's
+ remainder of buffer */
+
+ if (stream->runtime->total_bytes_available == 0 &&
+ stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+ pr_debug("detected init and someone forgot to do a write\n");
+ return stream->runtime->buffer_size;
+ }
+ pr_debug("app wrote %lld, DSP consumed %lld\n",
+ stream->runtime->total_bytes_available,
+ stream->runtime->total_bytes_transferred);
+ if (stream->runtime->total_bytes_available ==
+ stream->runtime->total_bytes_transferred) {
+ pr_debug("both pointers are same, returning full avail\n");
+ return stream->runtime->buffer_size;
+ }
+
+ /* FIXME: this routine isn't consistent, in one test we use
+ * cumulative values and in the other byte offsets. Do we
+ * really need the byte offsets if the cumulative values have
+ * been updated? In the PCM interface app_ptr and hw_ptr are
+ * already cumulative */
+
+ avail_calc = stream->runtime->buffer_size -
+ (stream->runtime->app_pointer - stream->runtime->hw_pointer);
+ pr_debug("calc avail as %ld, app_ptr %lld, hw+ptr %lld\n", avail_calc,
+ stream->runtime->app_pointer,
+ stream->runtime->hw_pointer);
+ if (avail_calc >= stream->runtime->buffer_size)
+ avail_calc -= stream->runtime->buffer_size;
+ pr_debug("ret avail as %ld\n", avail_calc);
+ avail->avail = avail_calc;
+ return avail_calc;
+}
+
+static inline size_t snd_compr_get_avail(struct snd_compr_stream *stream)
+{
+ struct snd_compr_avail avail;
+
+ return snd_compr_calc_avail(stream, &avail);
+}
+
+static int
+snd_compr_ioctl_avail(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_avail ioctl_avail;
+ size_t avail;
+
+ avail = snd_compr_calc_avail(stream, &ioctl_avail);
+ ioctl_avail.avail = avail;
+
+ if (copy_to_user((__u64 __user *)arg,
+ &ioctl_avail, sizeof(ioctl_avail)))
+ return -EFAULT;
+ return 0;
+}
+
+static int snd_compr_write_data(struct snd_compr_stream *stream,
+ const char __user *buf, size_t count)
+{
+ void *dstn;
+ size_t copy;
+ struct snd_compr_runtime *runtime = stream->runtime;
+
+ dstn = runtime->buffer + runtime->app_pointer;
+ pr_debug("copying %ld at %lld\n",
+ (unsigned long)count, runtime->app_pointer);
+ if (count < runtime->buffer_size - runtime->app_pointer) {
+ if (copy_from_user(dstn, buf, count))
+ return -EFAULT;
+ runtime->app_pointer += count;
+ } else {
+ copy = runtime->buffer_size - runtime->app_pointer;
+ if (copy_from_user(dstn, buf, copy))
+ return -EFAULT;
+ if (copy_from_user(runtime->buffer, buf + copy, count - copy))
+ return -EFAULT;
+ runtime->app_pointer = count - copy;
+ }
+ /* if DSP cares, let it know data has been written */
+ if (stream->ops->ack)
+ stream->ops->ack(stream, count);
+ return count;
+}
+
+static ssize_t snd_compr_write(struct file *f, const char __user *buf,
+ size_t count, loff_t *offset)
+{
+ struct snd_compr_file *data = f->private_data;
+ struct snd_compr_stream *stream;
+ size_t avail;
+ int retval;
+
+ if (snd_BUG_ON(!data))
+ return -EFAULT;
+
+ stream = &data->stream;
+ mutex_lock(&stream->device->lock);
+ /* write is allowed when stream is running or has been steup */
+ if (stream->runtime->state != SNDRV_PCM_STATE_SETUP &&
+ stream->runtime->state != SNDRV_PCM_STATE_RUNNING) {
+ mutex_unlock(&stream->device->lock);
+ return -EBADFD;
+ }
+
+ avail = snd_compr_get_avail(stream);
+ pr_debug("avail returned %ld\n", (unsigned long)avail);
+ /* calculate how much we can write to buffer */
+ if (avail > count)
+ avail = count;
+
+ if (stream->ops->copy)
+ retval = stream->ops->copy(stream, buf, avail);
+ else
+ retval = snd_compr_write_data(stream, buf, avail);
+ if (retval > 0)
+ stream->runtime->total_bytes_available += retval;
+
+ /* while initiating the stream, write should be called before START
+ * call, so in setup move state */
+ if (stream->runtime->state == SNDRV_PCM_STATE_SETUP) {
+ stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+ pr_debug("stream prepared, Houston we are good to go\n");
+ }
+
+ mutex_unlock(&stream->device->lock);
+ return retval;
+}
+
+
+static ssize_t snd_compr_read(struct file *f, char __user *buf,
+ size_t count, loff_t *offset)
+{
+ return -ENXIO;
+}
+
+static int snd_compr_mmap(struct file *f, struct vm_area_struct *vma)
+{
+ return -ENXIO;
+}
+
+static inline int snd_compr_get_poll(struct snd_compr_stream *stream)
+{
+ if (stream->direction == SND_COMPRESS_PLAYBACK)
+ return POLLOUT | POLLWRNORM;
+ else
+ return POLLIN | POLLRDNORM;
+}
+
+static unsigned int snd_compr_poll(struct file *f, poll_table *wait)
+{
+ struct snd_compr_file *data = f->private_data;
+ struct snd_compr_stream *stream;
+ size_t avail;
+ int retval = 0;
+
+ if (snd_BUG_ON(!data))
+ return -EFAULT;
+ stream = &data->stream;
+ if (snd_BUG_ON(!stream))
+ return -EFAULT;
+
+ mutex_lock(&stream->device->lock);
+ if (stream->runtime->state == SNDRV_PCM_STATE_PAUSED ||
+ stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+ retval = -EBADFD;
+ goto out;
+ }
+ poll_wait(f, &stream->runtime->sleep, wait);
+
+ avail = snd_compr_get_avail(stream);
+ pr_debug("avail is %ld\n", (unsigned long)avail);
+ /* check if we have at least one fragment to fill */
+ switch (stream->runtime->state) {
+ case SNDRV_PCM_STATE_DRAINING:
+ /* stream has been woken up after drain is complete
+ * draining done so set stream state to stopped
+ */
+ retval = snd_compr_get_poll(stream);
+ stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+ break;
+ case SNDRV_PCM_STATE_RUNNING:
+ case SNDRV_PCM_STATE_PREPARED:
+ case SNDRV_PCM_STATE_PAUSED:
+ if (avail >= stream->runtime->fragment_size)
+ retval = snd_compr_get_poll(stream);
+ break;
+ default:
+ if (stream->direction == SND_COMPRESS_PLAYBACK)
+ retval = POLLOUT | POLLWRNORM | POLLERR;
+ else
+ retval = POLLIN | POLLRDNORM | POLLERR;
+ break;
+ }
+out:
+ mutex_unlock(&stream->device->lock);
+ return retval;
+}
+
+static int
+snd_compr_get_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+ int retval;
+ struct snd_compr_caps caps;
+
+ if (!stream->ops->get_caps)
+ return -ENXIO;
+
+ retval = stream->ops->get_caps(stream, &caps);
+ if (retval)
+ goto out;
+ if (copy_to_user((void __user *)arg, &caps, sizeof(caps)))
+ retval = -EFAULT;
+out:
+ return retval;
+}
+
+static int
+snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
+{
+ int retval;
+ struct snd_compr_codec_caps *caps;
+
+ if (!stream->ops->get_codec_caps)
+ return -ENXIO;
+
+ caps = kmalloc(sizeof(*caps), GFP_KERNEL);
+ if (!caps)
+ return -ENOMEM;
+
+ retval = stream->ops->get_codec_caps(stream, caps);
+ if (retval)
+ goto out;
+ if (copy_to_user((void __user *)arg, caps, sizeof(*caps)))
+ retval = -EFAULT;
+
+out:
+ kfree(caps);
+ return retval;
+}
+
+/* revisit this with snd_pcm_preallocate_xxx */
+static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
+ struct snd_compr_params *params)
+{
+ unsigned int buffer_size;
+ void *buffer;
+
+ buffer_size = params->buffer.fragment_size * params->buffer.fragments;
+ if (stream->ops->copy) {
+ buffer = NULL;
+ /* if copy is defined the driver will be required to copy
+ * the data from core
+ */
+ } else {
+ buffer = kmalloc(buffer_size, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ }
+ stream->runtime->fragment_size = params->buffer.fragment_size;
+ stream->runtime->fragments = params->buffer.fragments;
+ stream->runtime->buffer = buffer;
+ stream->runtime->buffer_size = buffer_size;
+ return 0;
+}
+
+static int
+snd_compr_set_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_params *params;
+ int retval;
+
+ if (stream->runtime->state == SNDRV_PCM_STATE_OPEN) {
+ /*
+ * we should allow parameter change only when stream has been
+ * opened not in other cases
+ */
+ params = kmalloc(sizeof(*params), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+ if (copy_from_user(params, (void __user *)arg, sizeof(*params))) {
+ retval = -EFAULT;
+ goto out;
+ }
+ retval = snd_compr_allocate_buffer(stream, params);
+ if (retval) {
+ retval = -ENOMEM;
+ goto out;
+ }
+ retval = stream->ops->set_params(stream, params);
+ if (retval)
+ goto out;
+ stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+ } else {
+ return -EPERM;
+ }
+out:
+ kfree(params);
+ return retval;
+}
+
+static int
+snd_compr_get_params(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_codec *params;
+ int retval;
+
+ if (!stream->ops->get_params)
+ return -EBADFD;
+
+ params = kmalloc(sizeof(*params), GFP_KERNEL);
+ if (!params)
+ return -ENOMEM;
+ retval = stream->ops->get_params(stream, params);
+ if (retval)
+ goto out;
+ if (copy_to_user((char __user *)arg, params, sizeof(*params)))
+ retval = -EFAULT;
+
+out:
+ kfree(params);
+ return retval;
+}
+
+static inline int
+snd_compr_tstamp(struct snd_compr_stream *stream, unsigned long arg)
+{
+ struct snd_compr_tstamp tstamp;
+
+ snd_compr_update_tstamp(stream, &tstamp);
+ return copy_to_user((struct snd_compr_tstamp __user *)arg,
+ &tstamp, sizeof(tstamp)) ? -EFAULT : 0;
+}
+
+static int snd_compr_pause(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_RUNNING)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_PUSH);
+ if (!retval) {
+ stream->runtime->state = SNDRV_PCM_STATE_PAUSED;
+ wake_up(&stream->runtime->sleep);
+ }
+ return retval;
+}
+
+static int snd_compr_resume(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_PAUSED)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_PAUSE_RELEASE);
+ if (!retval)
+ stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+ return retval;
+}
+
+static int snd_compr_start(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state != SNDRV_PCM_STATE_PREPARED)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_START);
+ if (!retval)
+ stream->runtime->state = SNDRV_PCM_STATE_RUNNING;
+ return retval;
+}
+
+static int snd_compr_stop(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
+ stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SNDRV_PCM_TRIGGER_STOP);
+ if (!retval) {
+ stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+ wake_up(&stream->runtime->sleep);
+ }
+ return retval;
+}
+
+static int snd_compr_drain(struct snd_compr_stream *stream)
+{
+ int retval;
+
+ if (stream->runtime->state == SNDRV_PCM_STATE_PREPARED ||
+ stream->runtime->state == SNDRV_PCM_STATE_SETUP)
+ return -EPERM;
+ retval = stream->ops->trigger(stream, SND_COMPR_TRIGGER_DRAIN);
+ if (!retval) {
+ stream->runtime->state = SNDRV_PCM_STATE_DRAINING;
+ wake_up(&stream->runtime->sleep);
+ }
+ return retval;
+}
+
+static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
+{
+ struct snd_compr_file *data = f->private_data;
+ struct snd_compr_stream *stream;
+ int retval = -ENOTTY;
+
+ if (snd_BUG_ON(!data))
+ return -EFAULT;
+ stream = &data->stream;
+ if (snd_BUG_ON(!stream))
+ return -EFAULT;
+ mutex_lock(&stream->device->lock);
+ switch (_IOC_NR(cmd)) {
+ case _IOC_NR(SNDRV_COMPRESS_IOCTL_VERSION):
+ put_user(SNDRV_COMPRESS_VERSION,
+ (int __user *)arg) ? -EFAULT : 0;
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
+ retval = snd_compr_get_caps(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
+ retval = snd_compr_get_codec_caps(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
+ retval = snd_compr_set_params(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_GET_PARAMS):
+ retval = snd_compr_get_params(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_TSTAMP):
+ retval = snd_compr_tstamp(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_AVAIL):
+ retval = snd_compr_ioctl_avail(stream, arg);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_PAUSE):
+ retval = snd_compr_pause(stream);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_RESUME):
+ retval = snd_compr_resume(stream);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_START):
+ retval = snd_compr_start(stream);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_STOP):
+ retval = snd_compr_stop(stream);
+ break;
+ case _IOC_NR(SNDRV_COMPRESS_DRAIN):
+ retval = snd_compr_drain(stream);
+ break;
+ }
+ mutex_unlock(&stream->device->lock);
+ return retval;
+}
+
+static const struct file_operations snd_compr_file_ops = {
+ .owner = THIS_MODULE,
+ .open = snd_compr_open,
+ .release = snd_compr_free,
+ .write = snd_compr_write,
+ .read = snd_compr_read,
+ .unlocked_ioctl = snd_compr_ioctl,
+ .mmap = snd_compr_mmap,
+ .poll = snd_compr_poll,
+};
+
+static int snd_compress_dev_register(struct snd_device *device)
+{
+ int ret = -EINVAL;
+ char str[16];
+ struct snd_compr *compr;
+
+ if (snd_BUG_ON(!device || !device->device_data))
+ return -EBADFD;
+ compr = device->device_data;
+
+ sprintf(str, "comprC%iD%i", compr->card->number, compr->device);
+ pr_debug("reg %s for device %s, direction %d\n", str, compr->name,
+ compr->direction);
+ /* register compressed device */
+ ret = snd_register_device(SNDRV_DEVICE_TYPE_COMPRESS, compr->card,
+ compr->device, &snd_compr_file_ops, compr, str);
+ if (ret < 0) {
+ pr_err("snd_register_device failed\n %d", ret);
+ return ret;
+ }
+ return ret;
+
+}
+
+static int snd_compress_dev_disconnect(struct snd_device *device)
+{
+ struct snd_compr *compr;
+
+ compr = device->device_data;
+ snd_unregister_device(compr->direction, compr->card, compr->device);
+ return 0;
+}
+
+/*
+ * snd_compress_new: create new compress device
+ * @card: sound card pointer
+ * @device: device number
+ * @dirn: device direction, should be of type enum snd_compr_direction
+ * @compr: compress device pointer
+ */
+int snd_compress_new(struct snd_card *card, int device,
+ int dirn, struct snd_compr *compr)
+{
+ static struct snd_device_ops ops = {
+ .dev_free = NULL,
+ .dev_register = snd_compress_dev_register,
+ .dev_disconnect = snd_compress_dev_disconnect,
+ };
+
+ compr->card = card;
+ compr->device = device;
+ compr->direction = dirn;
+ return snd_device_new(card, SNDRV_DEV_COMPRESS, compr, &ops);
+}
+EXPORT_SYMBOL_GPL(snd_compress_new);
+
+static int snd_compress_add_device(struct snd_compr *device)
+{
+ int ret;
+
+ if (!device->card)
+ return -EINVAL;
+
+ /* register the card */
+ ret = snd_card_register(device->card);
+ if (ret)
+ goto out;
+ return 0;
+
+out:
+ pr_err("failed with %d\n", ret);
+ return ret;
+
+}
+
+static int snd_compress_remove_device(struct snd_compr *device)
+{
+ return snd_card_free(device->card);
+}
+
+/**
+ * snd_compress_register - register compressed device
+ *
+ * @device: compressed device to register
+ */
+int snd_compress_register(struct snd_compr *device)
+{
+ int retval;
+
+ if (device->name == NULL || device->dev == NULL || device->ops == NULL)
+ return -EINVAL;
+
+ pr_debug("Registering compressed device %s\n", device->name);
+ if (snd_BUG_ON(!device->ops->open))
+ return -EINVAL;
+ if (snd_BUG_ON(!device->ops->free))
+ return -EINVAL;
+ if (snd_BUG_ON(!device->ops->set_params))
+ return -EINVAL;
+ if (snd_BUG_ON(!device->ops->trigger))
+ return -EINVAL;
+
+ mutex_init(&device->lock);
+
+ /* register a compressed card */
+ mutex_lock(&device_mutex);
+ retval = snd_compress_add_device(device);
+ mutex_unlock(&device_mutex);
+ return retval;
+}
+EXPORT_SYMBOL_GPL(snd_compress_register);
+
+int snd_compress_deregister(struct snd_compr *device)
+{
+ pr_debug("Removing compressed device %s\n", device->name);
+ mutex_lock(&device_mutex);
+ snd_compress_remove_device(device);
+ mutex_unlock(&device_mutex);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_compress_deregister);
+
+static int __init snd_compress_init(void)
+{
+ return 0;
+}
+
+static void __exit snd_compress_exit(void)
+{
+}
+
+module_init(snd_compress_init);
+module_exit(snd_compress_exit);
+
+MODULE_DESCRIPTION("ALSA Compressed offload framework");
+MODULE_AUTHOR("Vinod Koul <vinod.koul@linux.intel.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/core/control.c b/sound/core/control.c
index f8c5be464510..2487a6bb1c54 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -21,6 +21,7 @@
#include <linux/threads.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/time.h>
@@ -989,7 +990,6 @@ struct user_element {
void *tlv_data; /* TLV data */
unsigned long tlv_data_size; /* TLV data size */
void *priv_data; /* private data (like strings for enumerated type) */
- unsigned long priv_data_size; /* size of private data in bytes */
};
static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
@@ -1001,6 +1001,28 @@ static int snd_ctl_elem_user_info(struct snd_kcontrol *kcontrol,
return 0;
}
+static int snd_ctl_elem_user_enum_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct user_element *ue = kcontrol->private_data;
+ const char *names;
+ unsigned int item;
+
+ item = uinfo->value.enumerated.item;
+
+ *uinfo = ue->info;
+
+ item = min(item, uinfo->value.enumerated.items - 1);
+ uinfo->value.enumerated.item = item;
+
+ names = ue->priv_data;
+ for (; item > 0; --item)
+ names += strlen(names) + 1;
+ strcpy(uinfo->value.enumerated.name, names);
+
+ return 0;
+}
+
static int snd_ctl_elem_user_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1055,11 +1077,46 @@ static int snd_ctl_elem_user_tlv(struct snd_kcontrol *kcontrol,
return change;
}
+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;
+
+ if (ue->info.value.enumerated.names_length > 64 * 1024)
+ return -EINVAL;
+
+ names = memdup_user((const void __user *)user_ptrval,
+ ue->info.value.enumerated.names_length);
+ if (IS_ERR(names))
+ return PTR_ERR(names);
+
+ /* check that there are enough valid names */
+ buf_len = ue->info.value.enumerated.names_length;
+ p = names;
+ for (i = 0; i < ue->info.value.enumerated.items; ++i) {
+ name_len = strnlen(p, buf_len);
+ if (name_len == 0 || name_len >= 64 || name_len == buf_len) {
+ kfree(names);
+ return -EINVAL;
+ }
+ p += name_len + 1;
+ buf_len -= name_len + 1;
+ }
+
+ ue->priv_data = names;
+ ue->info.value.enumerated.names_ptr = 0;
+
+ return 0;
+}
+
static void snd_ctl_elem_user_free(struct snd_kcontrol *kcontrol)
{
struct user_element *ue = kcontrol->private_data;
- if (ue->tlv_data)
- kfree(ue->tlv_data);
+
+ kfree(ue->tlv_data);
+ kfree(ue->priv_data);
kfree(ue);
}
@@ -1072,8 +1129,8 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
long private_size;
struct user_element *ue;
int idx, err;
-
- if (card->user_ctl_count >= MAX_USER_CONTROLS)
+
+ if (!replace && card->user_ctl_count >= MAX_USER_CONTROLS)
return -ENOMEM;
if (info->count < 1)
return -EINVAL;
@@ -1101,7 +1158,10 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
memcpy(&kctl.id, &info->id, sizeof(info->id));
kctl.count = info->owner ? info->owner : 1;
access |= SNDRV_CTL_ELEM_ACCESS_USER;
- kctl.info = snd_ctl_elem_user_info;
+ if (info->type == SNDRV_CTL_ELEM_TYPE_ENUMERATED)
+ kctl.info = snd_ctl_elem_user_enum_info;
+ else
+ kctl.info = snd_ctl_elem_user_info;
if (access & SNDRV_CTL_ELEM_ACCESS_READ)
kctl.get = snd_ctl_elem_user_get;
if (access & SNDRV_CTL_ELEM_ACCESS_WRITE)
@@ -1122,6 +1182,11 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
if (info->count > 64)
return -EINVAL;
break;
+ case SNDRV_CTL_ELEM_TYPE_ENUMERATED:
+ private_size = sizeof(unsigned int);
+ if (info->count > 128 || info->value.enumerated.items == 0)
+ return -EINVAL;
+ break;
case SNDRV_CTL_ELEM_TYPE_BYTES:
private_size = sizeof(unsigned char);
if (info->count > 512)
@@ -1143,9 +1208,17 @@ static int snd_ctl_elem_add(struct snd_ctl_file *file,
ue->info.access = 0;
ue->elem_data = (char *)ue + sizeof(*ue);
ue->elem_data_size = private_size;
+ if (ue->info.type == SNDRV_CTL_ELEM_TYPE_ENUMERATED) {
+ err = snd_ctl_elem_init_enum_names(ue);
+ if (err < 0) {
+ kfree(ue);
+ return err;
+ }
+ }
kctl.private_free = snd_ctl_elem_user_free;
_kctl = snd_ctl_new(&kctl, access);
if (_kctl == NULL) {
+ kfree(ue->priv_data);
kfree(ue);
return -ENOMEM;
}
@@ -1240,7 +1313,7 @@ static int snd_ctl_tlv_ioctl(struct snd_ctl_file *file,
err = -EPERM;
goto __kctl_end;
}
- err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
+ err = kctl->tlv.c(kctl, op_flag, tlv.length, _tlv->tlv);
if (err > 0) {
up_read(&card->controls_rwsem);
snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_TLV, &kctl->id);
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index 426874429a5e..2bb95a7a8809 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -83,6 +83,8 @@ struct snd_ctl_elem_info32 {
u32 items;
u32 item;
char name[64];
+ u64 names_ptr;
+ u32 names_length;
} enumerated;
unsigned char reserved[128];
} value;
@@ -372,6 +374,8 @@ static int snd_ctl_elem_add_compat(struct snd_ctl_file *file,
&data32->value.enumerated,
sizeof(data->value.enumerated)))
goto error;
+ data->value.enumerated.names_ptr =
+ (uintptr_t)compat_ptr(data->value.enumerated.names_ptr);
break;
default:
break;
diff --git a/sound/core/ctljack.c b/sound/core/ctljack.c
new file mode 100644
index 000000000000..e4b38fbe51da
--- /dev/null
+++ b/sound/core/ctljack.c
@@ -0,0 +1,56 @@
+/*
+ * Helper functions for jack-detection kcontrols
+ *
+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 2 of the License, or (at your option)
+ * any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/export.h>
+#include <sound/core.h>
+#include <sound/control.h>
+
+#define jack_detect_kctl_info snd_ctl_boolean_mono_info
+
+static int jack_detect_kctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ ucontrol->value.integer.value[0] = kcontrol->private_value;
+ return 0;
+}
+
+static struct snd_kcontrol_new jack_detect_kctl = {
+ /* name is filled later */
+ .iface = SNDRV_CTL_ELEM_IFACE_CARD,
+ .access = SNDRV_CTL_ELEM_ACCESS_READ,
+ .info = jack_detect_kctl_info,
+ .get = jack_detect_kctl_get,
+};
+
+struct snd_kcontrol *
+snd_kctl_jack_new(const char *name, int idx, void *private_data)
+{
+ struct snd_kcontrol *kctl;
+ kctl = snd_ctl_new1(&jack_detect_kctl, private_data);
+ if (!kctl)
+ return NULL;
+ snprintf(kctl->id.name, sizeof(kctl->id.name), "%s Jack", name);
+ kctl->id.index = idx;
+ kctl->private_value = 0;
+ return kctl;
+}
+EXPORT_SYMBOL_GPL(snd_kctl_jack_new);
+
+void snd_kctl_jack_report(struct snd_card *card,
+ struct snd_kcontrol *kctl, bool status)
+{
+ if (kctl->private_value == status)
+ return;
+ kctl->private_value = status;
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE, &kctl->id);
+}
+EXPORT_SYMBOL_GPL(snd_kctl_jack_report);
diff --git a/sound/core/device.c b/sound/core/device.c
index 2d1ad4b0cd65..f03cb5444a5a 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -21,6 +21,7 @@
#include <linux/slab.h>
#include <linux/time.h>
+#include <linux/export.h>
#include <linux/errno.h>
#include <sound/core.h>
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index a70ee7f1ed98..75ea16f35b1a 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -24,6 +24,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/mutex.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/minors.h>
@@ -272,7 +273,14 @@ static int snd_hwdep_control_ioctl(struct snd_card *card,
if (get_user(device, (int __user *)arg))
return -EFAULT;
mutex_lock(&register_mutex);
- device = device < 0 ? 0 : device + 1;
+
+ if (device < 0)
+ device = 0;
+ else if (device < SNDRV_MINOR_HWDEPS)
+ device++;
+ else
+ device = SNDRV_MINOR_HWDEPS;
+
while (device < SNDRV_MINOR_HWDEPS) {
if (snd_hwdep_search(card, device))
break;
diff --git a/sound/core/info.c b/sound/core/info.c
index 601f0ebb677b..c1e611c65c8f 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -24,6 +24,7 @@
#include <linux/mm.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/info.h>
diff --git a/sound/core/info_oss.c b/sound/core/info_oss.c
index e4af138d651a..cf42ab5080eb 100644
--- a/sound/core/info_oss.c
+++ b/sound/core/info_oss.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/string.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/info.h>
diff --git a/sound/core/init.c b/sound/core/init.c
index 2c041bb36ab3..068cf08d3ffb 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/sched.h>
+#include <linux/module.h>
#include <linux/file.h>
#include <linux/slab.h>
#include <linux/time.h>
@@ -479,74 +480,104 @@ int snd_card_free(struct snd_card *card)
EXPORT_SYMBOL(snd_card_free);
-static void snd_card_set_id_no_lock(struct snd_card *card, const char *nid)
+/* retrieve the last word of shortname or longname */
+static const char *retrieve_id_from_card_name(const char *name)
{
- int i, len, idx_flag = 0, loops = SNDRV_CARDS;
- const char *spos, *src;
- char *id;
-
- if (nid == NULL) {
- id = card->shortname;
- spos = src = id;
- while (*id != '\0') {
- if (*id == ' ')
- spos = id + 1;
- id++;
- }
- } else {
- spos = src = nid;
+ const char *spos = name;
+
+ while (*name) {
+ if (isspace(*name) && isalnum(name[1]))
+ spos = name + 1;
+ name++;
}
- id = card->id;
- while (*spos != '\0' && !isalnum(*spos))
- spos++;
- if (isdigit(*spos))
- *id++ = isalpha(src[0]) ? src[0] : 'D';
- while (*spos != '\0' && (size_t)(id - card->id) < sizeof(card->id) - 1) {
- if (isalnum(*spos))
- *id++ = *spos;
- spos++;
+ return spos;
+}
+
+/* return true if the given id string doesn't conflict any other card ids */
+static bool card_id_ok(struct snd_card *card, const char *id)
+{
+ int i;
+ if (!snd_info_check_reserved_words(id))
+ return false;
+ for (i = 0; i < snd_ecards_limit; i++) {
+ if (snd_cards[i] && snd_cards[i] != card &&
+ !strcmp(snd_cards[i]->id, id))
+ return false;
}
- *id = '\0';
+ return true;
+}
- id = card->id;
+/* copy to card->id only with valid letters from nid */
+static void copy_valid_id_string(struct snd_card *card, const char *src,
+ const char *nid)
+{
+ char *id = card->id;
+
+ while (*nid && !isalnum(*nid))
+ nid++;
+ if (isdigit(*nid))
+ *id++ = isalpha(*src) ? *src : 'D';
+ while (*nid && (size_t)(id - card->id) < sizeof(card->id) - 1) {
+ if (isalnum(*nid))
+ *id++ = *nid;
+ nid++;
+ }
+ *id = 0;
+}
+
+/* Set card->id from the given string
+ * If the string conflicts with other ids, add a suffix to make it unique.
+ */
+static void snd_card_set_id_no_lock(struct snd_card *card, const char *src,
+ const char *nid)
+{
+ int len, loops;
+ bool with_suffix;
+ bool is_default = false;
+ char *id;
- if (*id == '\0')
+ copy_valid_id_string(card, src, nid);
+ id = card->id;
+
+ again:
+ /* use "Default" for obviously invalid strings
+ * ("card" conflicts with proc directories)
+ */
+ if (!*id || !strncmp(id, "card", 4)) {
strcpy(id, "Default");
+ is_default = true;
+ }
- while (1) {
- if (loops-- == 0) {
- snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
- strcpy(card->id, card->proc_root->name);
- return;
- }
- if (!snd_info_check_reserved_words(id))
- goto __change;
- for (i = 0; i < snd_ecards_limit; i++) {
- if (snd_cards[i] && !strcmp(snd_cards[i]->id, id))
- goto __change;
- }
- break;
+ with_suffix = false;
+ for (loops = 0; loops < SNDRV_CARDS; loops++) {
+ if (card_id_ok(card, id))
+ return; /* OK */
- __change:
len = strlen(id);
- if (idx_flag) {
- if (id[len-1] != '9')
- id[len-1]++;
- else
- id[len-1] = 'A';
- } else if ((size_t)len <= sizeof(card->id) - 3) {
- strcat(id, "_1");
- idx_flag++;
+ if (!with_suffix) {
+ /* add the "_X" suffix */
+ char *spos = id + len;
+ if (len > sizeof(card->id) - 3)
+ spos = id + sizeof(card->id) - 3;
+ strcpy(spos, "_1");
+ with_suffix = true;
} else {
- spos = id + len - 2;
- if ((size_t)len <= sizeof(card->id) - 2)
- spos++;
- *(char *)spos++ = '_';
- *(char *)spos++ = '1';
- *(char *)spos++ = '\0';
- idx_flag++;
+ /* modify the existing suffix */
+ if (id[len - 1] != '9')
+ id[len - 1]++;
+ else
+ id[len - 1] = 'A';
}
}
+ /* fallback to the default id */
+ if (!is_default) {
+ *id = 0;
+ goto again;
+ }
+ /* last resort... */
+ snd_printk(KERN_ERR "unable to set card id (%s)\n", id);
+ if (card->proc_root->name)
+ strcpy(card->id, card->proc_root->name);
}
/**
@@ -563,7 +594,7 @@ void snd_card_set_id(struct snd_card *card, const char *nid)
if (card->id[0] != '\0')
return;
mutex_lock(&snd_card_mutex);
- snd_card_set_id_no_lock(card, nid);
+ snd_card_set_id_no_lock(card, nid, nid);
mutex_unlock(&snd_card_mutex);
}
EXPORT_SYMBOL(snd_card_set_id);
@@ -595,22 +626,12 @@ card_id_store_attr(struct device *dev, struct device_attribute *attr,
memcpy(buf1, buf, copy);
buf1[copy] = '\0';
mutex_lock(&snd_card_mutex);
- if (!snd_info_check_reserved_words(buf1)) {
- __exist:
+ if (!card_id_ok(NULL, buf1)) {
mutex_unlock(&snd_card_mutex);
return -EEXIST;
}
- for (idx = 0; idx < snd_ecards_limit; idx++) {
- if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1)) {
- if (card == snd_cards[idx])
- goto __ok;
- else
- goto __exist;
- }
- }
strcpy(card->id, buf1);
snd_info_card_id_change(card);
-__ok:
mutex_unlock(&snd_card_mutex);
return count;
@@ -664,7 +685,18 @@ int snd_card_register(struct snd_card *card)
mutex_unlock(&snd_card_mutex);
return 0;
}
- snd_card_set_id_no_lock(card, card->id[0] == '\0' ? NULL : card->id);
+ if (*card->id) {
+ /* make a unique id name from the given string */
+ char tmpid[sizeof(card->id)];
+ memcpy(tmpid, card->id, sizeof(card->id));
+ snd_card_set_id_no_lock(card, tmpid, tmpid);
+ } else {
+ /* create an id from either shortname or longname */
+ const char *src;
+ src = *card->shortname ? card->shortname : card->longname;
+ snd_card_set_id_no_lock(card, src,
+ retrieve_id_from_card_name(src));
+ }
snd_cards[card->number] = card;
mutex_unlock(&snd_card_mutex);
init_info_for_card(card);
diff --git a/sound/core/isadma.c b/sound/core/isadma.c
index 950e19ba91fc..c0f1208bb7df 100644
--- a/sound/core/isadma.c
+++ b/sound/core/isadma.c
@@ -26,6 +26,7 @@
#undef HAVE_REALLY_SLOW_DMA_CONTROLLER
+#include <linux/export.h>
#include <sound/core.h>
#include <asm/dma.h>
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 53b53e97c896..471e1e3b0a99 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -21,15 +21,17 @@
#include <linux/input.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/jack.h>
#include <sound/core.h>
-static int jack_switch_types[] = {
+static int jack_switch_types[SND_JACK_SWITCH_TYPES] = {
SW_HEADPHONE_INSERT,
SW_MICROPHONE_INSERT,
SW_LINEOUT_INSERT,
SW_JACK_PHYSICAL_INSERT,
SW_VIDEOOUT_INSERT,
+ SW_LINEIN_INSERT,
};
static int snd_jack_dev_free(struct snd_device *device)
@@ -126,7 +128,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
jack->type = type;
- for (i = 0; i < ARRAY_SIZE(jack_switch_types); i++)
+ for (i = 0; i < SND_JACK_SWITCH_TYPES; i++)
if (type & (1 << i))
input_set_capability(jack->input_dev, EV_SW,
jack_switch_types[i]);
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index 16bd9c03679b..691569238435 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -176,7 +176,7 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr,
* Calls the memory-allocator function for the corresponding
* buffer type.
*
- * Returns zero if the buffer with the given size is allocated successfuly,
+ * Returns zero if the buffer with the given size is allocated successfully,
* other a negative value at error.
*/
int snd_dma_alloc_pages(int type, struct device *device, size_t size,
@@ -230,7 +230,7 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size,
* tries to allocate again. The size actually allocated is stored in
* res_size argument.
*
- * Returns zero if the buffer with the given size is allocated successfuly,
+ * Returns zero if the buffer with the given size is allocated successfully,
* other a negative value at error.
*/
int snd_dma_alloc_pages_fallback(int type, struct device *device, size_t size,
diff --git a/sound/core/memory.c b/sound/core/memory.c
index 1161158582a6..66a278d0b04e 100644
--- a/sound/core/memory.c
+++ b/sound/core/memory.c
@@ -20,6 +20,7 @@
*
*/
+#include <linux/export.h>
#include <asm/io.h>
#include <asm/uaccess.h>
#include <sound/core.h>
diff --git a/sound/core/misc.c b/sound/core/misc.c
index eb9fe2e1d291..768167925409 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -20,6 +20,8 @@
*/
#include <linux/init.h>
+#include <linux/export.h>
+#include <linux/moduleparam.h>
#include <linux/time.h>
#include <linux/slab.h>
#include <linux/ioport.h>
@@ -70,7 +72,7 @@ void __snd_printk(unsigned int level, const char *path, int line,
char verbose_fmt[] = KERN_DEFAULT "ALSA %s:%d %pV";
#endif
-#ifdef CONFIG_SND_DEBUG
+#ifdef CONFIG_SND_DEBUG
if (debug < level)
return;
#endif
diff --git a/sound/core/oss/mixer_oss.c b/sound/core/oss/mixer_oss.c
index d8359cfeca15..18297f7f2c55 100644
--- a/sound/core/oss/mixer_oss.c
+++ b/sound/core/oss/mixer_oss.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/string.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/control.h>
@@ -499,7 +500,7 @@ static struct snd_kcontrol *snd_mixer_oss_test_id(struct snd_mixer_oss *mixer, c
memset(&id, 0, sizeof(id));
id.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
- strcpy(id.name, name);
+ strlcpy(id.name, name, sizeof(id.name));
id.index = index;
return snd_ctl_find_id(card, &id);
}
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 23c34a02894b..08fde0060fd9 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -30,7 +30,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/vmalloc.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/math64.h>
#include <linux/string.h>
#include <sound/core.h>
@@ -47,7 +47,7 @@
static int dsp_map[SNDRV_CARDS];
static int adsp_map[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 1};
-static int nonblock_open = 1;
+static bool nonblock_open = 1;
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>, Abramo Bagnara <abramo@alsa-project.org>");
MODULE_DESCRIPTION("PCM OSS emulation for ALSA.");
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index ee9abb2d9001..6e4bfcc14254 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -21,6 +21,7 @@
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/time.h>
#include <linux/mutex.h>
#include <sound/core.h>
@@ -649,7 +650,7 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
pstr->stream = stream;
pstr->pcm = pcm;
pstr->substream_count = substream_count;
- if (substream_count > 0) {
+ if (substream_count > 0 && !pcm->internal) {
err = snd_pcm_stream_proc_init(pstr);
if (err < 0) {
snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
@@ -673,15 +674,18 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
pstr->substream = substream;
else
prev->next = substream;
- err = snd_pcm_substream_proc_init(substream);
- if (err < 0) {
- snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
- if (prev == NULL)
- pstr->substream = NULL;
- else
- prev->next = NULL;
- kfree(substream);
- return err;
+
+ if (!pcm->internal) {
+ err = snd_pcm_substream_proc_init(substream);
+ if (err < 0) {
+ snd_printk(KERN_ERR "Error in snd_pcm_stream_proc_init\n");
+ if (prev == NULL)
+ pstr->substream = NULL;
+ else
+ prev->next = NULL;
+ kfree(substream);
+ return err;
+ }
}
substream->group = &substream->self_group;
spin_lock_init(&substream->self_group.lock);
@@ -695,25 +699,9 @@ int snd_pcm_new_stream(struct snd_pcm *pcm, int stream, int substream_count)
EXPORT_SYMBOL(snd_pcm_new_stream);
-/**
- * snd_pcm_new - create a new PCM instance
- * @card: the card instance
- * @id: the id string
- * @device: the device index (zero based)
- * @playback_count: the number of substreams for playback
- * @capture_count: the number of substreams for capture
- * @rpcm: the pointer to store the new pcm instance
- *
- * Creates a new PCM instance.
- *
- * The pcm operators have to be set afterwards to the new instance
- * via snd_pcm_set_ops().
- *
- * Returns zero if successful, or a negative error code on failure.
- */
-int snd_pcm_new(struct snd_card *card, const char *id, int device,
- int playback_count, int capture_count,
- struct snd_pcm ** rpcm)
+static int _snd_pcm_new(struct snd_card *card, const char *id, int device,
+ int playback_count, int capture_count, bool internal,
+ struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
int err;
@@ -734,6 +722,7 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
}
pcm->card = card;
pcm->device = device;
+ pcm->internal = internal;
if (id)
strlcpy(pcm->id, id, sizeof(pcm->id));
if ((err = snd_pcm_new_stream(pcm, SNDRV_PCM_STREAM_PLAYBACK, playback_count)) < 0) {
@@ -755,8 +744,59 @@ int snd_pcm_new(struct snd_card *card, const char *id, int device,
return 0;
}
+/**
+ * snd_pcm_new - create a new PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new PCM instance.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new(struct snd_card *card, const char *id, int device,
+ int playback_count, int capture_count, struct snd_pcm **rpcm)
+{
+ return _snd_pcm_new(card, id, device, playback_count, capture_count,
+ false, rpcm);
+}
EXPORT_SYMBOL(snd_pcm_new);
+/**
+ * snd_pcm_new_internal - create a new internal PCM instance
+ * @card: the card instance
+ * @id: the id string
+ * @device: the device index (zero based - shared with normal PCMs)
+ * @playback_count: the number of substreams for playback
+ * @capture_count: the number of substreams for capture
+ * @rpcm: the pointer to store the new pcm instance
+ *
+ * Creates a new internal PCM instance with no userspace device or procfs
+ * entries. This is used by ASoC Back End PCMs in order to create a PCM that
+ * will only be used internally by kernel drivers. i.e. it cannot be opened
+ * by userspace. It provides existing ASoC components drivers with a substream
+ * and access to any private data.
+ *
+ * The pcm operators have to be set afterwards to the new instance
+ * via snd_pcm_set_ops().
+ *
+ * Returns zero if successful, or a negative error code on failure.
+ */
+int snd_pcm_new_internal(struct snd_card *card, const char *id, int device,
+ int playback_count, int capture_count,
+ struct snd_pcm **rpcm)
+{
+ return _snd_pcm_new(card, id, device, playback_count, capture_count,
+ true, rpcm);
+}
+EXPORT_SYMBOL(snd_pcm_new_internal);
+
static void snd_pcm_free_stream(struct snd_pcm_str * pstr)
{
struct snd_pcm_substream *substream, *substream_next;
@@ -993,7 +1033,7 @@ static int snd_pcm_dev_register(struct snd_device *device)
}
for (cidx = 0; cidx < 2; cidx++) {
int devtype = -1;
- if (pcm->streams[cidx].substream == NULL)
+ if (pcm->streams[cidx].substream == NULL || pcm->internal)
continue;
switch (cidx) {
case SNDRV_PCM_STREAM_PLAYBACK:
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index 86d0caf91b35..4d18941178e6 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/math64.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/info.h>
@@ -1028,7 +1029,8 @@ static int snd_interval_ratden(struct snd_interval *i,
*
* Returns non-zero if the value is changed, zero if not changed.
*/
-int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *list, unsigned int mask)
+int snd_interval_list(struct snd_interval *i, unsigned int count,
+ const unsigned int *list, unsigned int mask)
{
unsigned int k;
struct snd_interval list_range;
@@ -1399,6 +1401,32 @@ int snd_pcm_hw_constraint_pow2(struct snd_pcm_runtime *runtime,
EXPORT_SYMBOL(snd_pcm_hw_constraint_pow2);
+static int snd_pcm_hw_rule_noresample_func(struct snd_pcm_hw_params *params,
+ struct snd_pcm_hw_rule *rule)
+{
+ unsigned int base_rate = (unsigned int)(uintptr_t)rule->private;
+ struct snd_interval *rate;
+
+ rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+ return snd_interval_list(rate, 1, &base_rate, 0);
+}
+
+/**
+ * snd_pcm_hw_rule_noresample - add a rule to allow disabling hw resampling
+ * @runtime: PCM runtime instance
+ * @base_rate: the rate at which the hardware does not resample
+ */
+int snd_pcm_hw_rule_noresample(struct snd_pcm_runtime *runtime,
+ unsigned int base_rate)
+{
+ return snd_pcm_hw_rule_add(runtime, SNDRV_PCM_HW_PARAMS_NORESAMPLE,
+ SNDRV_PCM_HW_PARAM_RATE,
+ snd_pcm_hw_rule_noresample_func,
+ (void *)(uintptr_t)base_rate,
+ SNDRV_PCM_HW_PARAM_RATE, -1);
+}
+EXPORT_SYMBOL(snd_pcm_hw_rule_noresample);
+
static void _snd_pcm_hw_param_any(struct snd_pcm_hw_params *params,
snd_pcm_hw_param_t var)
{
@@ -1761,6 +1789,10 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
snd_pcm_uframes_t avail = 0;
long wait_time, tout;
+ init_waitqueue_entry(&wait, current);
+ set_current_state(TASK_INTERRUPTIBLE);
+ add_wait_queue(&runtime->tsleep, &wait);
+
if (runtime->no_period_wakeup)
wait_time = MAX_SCHEDULE_TIMEOUT;
else {
@@ -1771,16 +1803,32 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
}
wait_time = msecs_to_jiffies(wait_time * 1000);
}
- init_waitqueue_entry(&wait, current);
- add_wait_queue(&runtime->tsleep, &wait);
+
for (;;) {
if (signal_pending(current)) {
err = -ERESTARTSYS;
break;
}
+
+ /*
+ * We need to check if space became available already
+ * (and thus the wakeup happened already) first to close
+ * the race of space already having become available.
+ * This check must happen after been added to the waitqueue
+ * and having current state be INTERRUPTIBLE.
+ */
+ if (is_playback)
+ avail = snd_pcm_playback_avail(runtime);
+ else
+ avail = snd_pcm_capture_avail(runtime);
+ if (avail >= runtime->twake)
+ break;
snd_pcm_stream_unlock_irq(substream);
- tout = schedule_timeout_interruptible(wait_time);
+
+ tout = schedule_timeout(wait_time);
+
snd_pcm_stream_lock_irq(substream);
+ set_current_state(TASK_INTERRUPTIBLE);
switch (runtime->status->state) {
case SNDRV_PCM_STATE_SUSPENDED:
err = -ESTRPIPE;
@@ -1806,14 +1854,9 @@ static int wait_for_avail(struct snd_pcm_substream *substream,
err = -EIO;
break;
}
- if (is_playback)
- avail = snd_pcm_playback_avail(runtime);
- else
- avail = snd_pcm_capture_avail(runtime);
- if (avail >= runtime->twake)
- break;
}
_endloop:
+ set_current_state(TASK_RUNNING);
remove_wait_queue(&runtime->tsleep, &wait);
*availp = avail;
return err;
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index 150cb7edffee..957131366dd9 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/moduleparam.h>
#include <linux/vmalloc.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/info.h>
diff --git a/sound/core/pcm_misc.c b/sound/core/pcm_misc.c
index 88f02e3866e0..9c9eff9afbac 100644
--- a/sound/core/pcm_misc.c
+++ b/sound/core/pcm_misc.c
@@ -20,6 +20,7 @@
*/
#include <linux/time.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/pcm.h>
#define SND_PCM_FORMAT_UNKNOWN (-1)
diff --git a/sound/core/pcm_native.c b/sound/core/pcm_native.c
index 1c6be91dfb98..3fe99e644eb8 100644
--- a/sound/core/pcm_native.c
+++ b/sound/core/pcm_native.c
@@ -20,10 +20,11 @@
*/
#include <linux/mm.h>
+#include <linux/module.h>
#include <linux/file.h>
#include <linux/slab.h>
#include <linux/time.h>
-#include <linux/pm_qos_params.h>
+#include <linux/pm_qos.h>
#include <linux/uio.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
@@ -1585,12 +1586,18 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
struct file *file;
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream1;
+ struct snd_pcm_group *group;
file = snd_pcm_file_fd(fd);
if (!file)
return -EBADFD;
pcm_file = file->private_data;
substream1 = pcm_file->substream;
+ group = kmalloc(sizeof(*group), GFP_KERNEL);
+ if (!group) {
+ res = -ENOMEM;
+ goto _nolock;
+ }
down_write(&snd_pcm_link_rwsem);
write_lock_irq(&snd_pcm_link_rwlock);
if (substream->runtime->status->state == SNDRV_PCM_STATE_OPEN ||
@@ -1603,11 +1610,7 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
goto _end;
}
if (!snd_pcm_stream_linked(substream)) {
- substream->group = kmalloc(sizeof(struct snd_pcm_group), GFP_ATOMIC);
- if (substream->group == NULL) {
- res = -ENOMEM;
- goto _end;
- }
+ substream->group = group;
spin_lock_init(&substream->group->lock);
INIT_LIST_HEAD(&substream->group->substreams);
list_add_tail(&substream->link_list, &substream->group->substreams);
@@ -1619,7 +1622,10 @@ static int snd_pcm_link(struct snd_pcm_substream *substream, int fd)
_end:
write_unlock_irq(&snd_pcm_link_rwlock);
up_write(&snd_pcm_link_rwsem);
+ _nolock:
fput(file);
+ if (res < 0)
+ kfree(group);
return res;
}
@@ -2058,16 +2064,12 @@ EXPORT_SYMBOL(snd_pcm_open_substream);
static int snd_pcm_open_file(struct file *file,
struct snd_pcm *pcm,
- int stream,
- struct snd_pcm_file **rpcm_file)
+ int stream)
{
struct snd_pcm_file *pcm_file;
struct snd_pcm_substream *substream;
int err;
- if (rpcm_file)
- *rpcm_file = NULL;
-
err = snd_pcm_open_substream(pcm, stream, file, &substream);
if (err < 0)
return err;
@@ -2083,8 +2085,7 @@ static int snd_pcm_open_file(struct file *file,
substream->pcm_release = pcm_release_private;
}
file->private_data = pcm_file;
- if (rpcm_file)
- *rpcm_file = pcm_file;
+
return 0;
}
@@ -2113,7 +2114,6 @@ static int snd_pcm_capture_open(struct inode *inode, struct file *file)
static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
{
int err;
- struct snd_pcm_file *pcm_file;
wait_queue_t wait;
if (pcm == NULL) {
@@ -2131,7 +2131,7 @@ static int snd_pcm_open(struct file *file, struct snd_pcm *pcm, int stream)
add_wait_queue(&pcm->open_wait, &wait);
mutex_lock(&pcm->open_mutex);
while (1) {
- err = snd_pcm_open_file(file, pcm, stream, &pcm_file);
+ err = snd_pcm_open_file(file, pcm, stream);
if (err >= 0)
break;
if (err == -EAGAIN) {
@@ -3156,8 +3156,8 @@ static const struct vm_operations_struct snd_pcm_vm_ops_data_fault = {
/*
* mmap the DMA buffer on RAM
*/
-static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *area)
+int snd_pcm_lib_default_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *area)
{
area->vm_flags |= VM_RESERVED;
#ifdef ARCH_HAS_DMA_MMAP_COHERENT
@@ -3177,6 +3177,7 @@ static int snd_pcm_default_mmap(struct snd_pcm_substream *substream,
area->vm_ops = &snd_pcm_vm_ops_data_fault;
return 0;
}
+EXPORT_SYMBOL_GPL(snd_pcm_lib_default_mmap);
/*
* mmap the DMA buffer on I/O memory area
@@ -3242,7 +3243,7 @@ int snd_pcm_mmap_data(struct snd_pcm_substream *substream, struct file *file,
if (substream->ops->mmap)
err = substream->ops->mmap(substream, area);
else
- err = snd_pcm_default_mmap(substream, area);
+ err = snd_pcm_lib_default_mmap(substream, area);
if (!err)
atomic_inc(&substream->mmap_count);
return err;
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 849a0ed95054..ebf6e49ad3d4 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -27,7 +27,7 @@
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/mutex.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/delay.h>
#include <sound/rawmidi.h>
#include <sound/info.h>
diff --git a/sound/core/seq/oss/seq_oss.c b/sound/core/seq/oss/seq_oss.c
index a1f1a2f00ccb..8d4d5e853efe 100644
--- a/sound/core/seq/oss/seq_oss.c
+++ b/sound/core/seq/oss/seq_oss.c
@@ -21,7 +21,7 @@
*/
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/minors.h>
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index 69cd7b3c362d..e3cb46fef2c7 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -28,6 +28,7 @@
#include "seq_oss_timer.h"
#include "seq_oss_event.h"
#include <linux/init.h>
+#include <linux/export.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index ee44ab9593c0..c5b773a1eea9 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -24,6 +24,7 @@
#include "seq_oss_midi.h"
#include "../seq_lock.h"
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/slab.h>
/*
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index 119fddb6fc99..9d8379aedf40 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -20,7 +20,7 @@
*/
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index f2436d33fbf7..4dc6bae80e15 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -22,6 +22,7 @@
*/
#include <linux/init.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/minors.h>
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index 1f997675c893..5cf8d65ed5ef 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -37,6 +37,7 @@
*/
#include <linux/init.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/seq_device.h>
diff --git a/sound/core/seq/seq_dummy.c b/sound/core/seq/seq_dummy.c
index 1d7d90ca455e..bbe32d2177d9 100644
--- a/sound/core/seq/seq_dummy.c
+++ b/sound/core/seq/seq_dummy.c
@@ -20,7 +20,7 @@
#include <linux/init.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include "seq_clientmgr.h"
#include <sound/initval.h>
@@ -65,7 +65,7 @@ MODULE_LICENSE("GPL");
MODULE_ALIAS("snd-seq-client-" __stringify(SNDRV_SEQ_CLIENT_DUMMY));
static int ports = 1;
-static int duplex;
+static bool duplex;
module_param(ports, int, 0444);
MODULE_PARM_DESC(ports, "number of ports to be created");
diff --git a/sound/core/seq/seq_info.c b/sound/core/seq/seq_info.c
index 201f8106ffdd..acf7769419f0 100644
--- a/sound/core/seq/seq_info.c
+++ b/sound/core/seq/seq_info.c
@@ -20,6 +20,7 @@
*/
#include <linux/init.h>
+#include <linux/export.h>
#include <sound/core.h>
#include "seq_info.h"
diff --git a/sound/core/seq/seq_lock.c b/sound/core/seq/seq_lock.c
index 54f921edda79..2cfe50c71a9d 100644
--- a/sound/core/seq/seq_lock.c
+++ b/sound/core/seq/seq_lock.c
@@ -19,6 +19,7 @@
*
*/
+#include <linux/export.h>
#include <sound/core.h>
#include "seq_lock.h"
diff --git a/sound/core/seq/seq_memory.c b/sound/core/seq/seq_memory.c
index 7f50c1437675..f478f770bf52 100644
--- a/sound/core/seq/seq_memory.c
+++ b/sound/core/seq/seq_memory.c
@@ -21,6 +21,7 @@
*/
#include <linux/init.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <sound/core.h>
diff --git a/sound/core/seq/seq_midi.c b/sound/core/seq/seq_midi.c
index ebaf1b541dcd..64069dbf89ca 100644
--- a/sound/core/seq/seq_midi.c
+++ b/sound/core/seq/seq_midi.c
@@ -30,7 +30,7 @@ Possible options for midisynth module:
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/string.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
diff --git a/sound/core/seq/seq_midi_emul.c b/sound/core/seq/seq_midi_emul.c
index 07c663135c62..6f64471ddde3 100644
--- a/sound/core/seq/seq_midi_emul.c
+++ b/sound/core/seq/seq_midi_emul.c
@@ -32,6 +32,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/string.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/seq_kernel.h>
#include <sound/seq_midi_emul.h>
diff --git a/sound/core/seq/seq_midi_event.c b/sound/core/seq/seq_midi_event.c
index b5d6ea4904c0..37db7ba492a6 100644
--- a/sound/core/seq/seq_midi_event.c
+++ b/sound/core/seq/seq_midi_event.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/string.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/seq_kernel.h>
#include <sound/seq_midi_event.h>
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index e12bcd94b6db..9516e5ce3aad 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -22,6 +22,7 @@
#include <sound/core.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include "seq_system.h"
#include "seq_ports.h"
#include "seq_clientmgr.h"
diff --git a/sound/core/seq/seq_system.c b/sound/core/seq/seq_system.c
index c38b90cf3cb0..8ce1d0b40dce 100644
--- a/sound/core/seq/seq_system.c
+++ b/sound/core/seq/seq_system.c
@@ -20,6 +20,7 @@
*/
#include <linux/init.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <sound/core.h>
#include "seq_system.h"
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 86e7739269ca..4b50e604276d 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -37,6 +37,7 @@
#include <linux/init.h>
#include <linux/wait.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 1c7a3efe1778..28f35593a750 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -23,7 +23,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/device.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/minors.h>
#include <sound/info.h>
@@ -229,6 +229,7 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
case SNDRV_DEVICE_TYPE_RAWMIDI:
case SNDRV_DEVICE_TYPE_PCM_PLAYBACK:
case SNDRV_DEVICE_TYPE_PCM_CAPTURE:
+ case SNDRV_DEVICE_TYPE_COMPRESS:
if (snd_BUG_ON(!card))
return -EINVAL;
minor = SNDRV_MINOR(card->number, type + dev);
diff --git a/sound/core/sound_oss.c b/sound/core/sound_oss.c
index 0c164e5e4322..c70092043061 100644
--- a/sound/core/sound_oss.c
+++ b/sound/core/sound_oss.c
@@ -26,6 +26,7 @@
#endif
#include <linux/init.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include <linux/time.h>
#include <sound/core.h>
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 67ebf1c21c04..8e7561dfc5fc 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -24,7 +24,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/mutex.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/string.h>
#include <sound/core.h>
#include <sound/timer.h>
diff --git a/sound/core/vmaster.c b/sound/core/vmaster.c
index a39d3d8c2f9c..14a286a7bf2b 100644
--- a/sound/core/vmaster.c
+++ b/sound/core/vmaster.c
@@ -10,6 +10,7 @@
*/
#include <linux/slab.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/tlv.h>
@@ -36,6 +37,8 @@ struct link_master {
struct link_ctl_info info;
int val; /* the master value */
unsigned int tlv[4];
+ void (*hook)(void *private_data, int);
+ void *hook_private_data;
};
/*
@@ -51,6 +54,7 @@ struct link_slave {
struct link_ctl_info info;
int vals[2]; /* current values */
unsigned int flags;
+ struct snd_kcontrol *kctl; /* original kcontrol pointer */
struct snd_kcontrol slave; /* the copy of original control entry */
};
@@ -124,7 +128,9 @@ static int master_init(struct link_master *master)
master->info.count = 1; /* always mono */
/* set full volume as default (= no attenuation) */
master->val = master->info.max_val;
- return 0;
+ if (master->hook)
+ master->hook(master->hook_private_data, master->val);
+ return 1;
}
return -ENOENT;
}
@@ -251,6 +257,7 @@ int _snd_ctl_add_slave(struct snd_kcontrol *master, struct snd_kcontrol *slave,
slave->count * sizeof(*slave->vd), GFP_KERNEL);
if (!srec)
return -ENOMEM;
+ srec->kctl = slave;
srec->slave = *slave;
memcpy(srec->slave.vd, slave->vd, slave->count * sizeof(*slave->vd));
srec->master = master_link;
@@ -326,16 +333,26 @@ static int master_put(struct snd_kcontrol *kcontrol,
slave_put_val(slave, uval);
}
kfree(uval);
+ if (master->hook && !err)
+ master->hook(master->hook_private_data, master->val);
return 1;
}
static void master_free(struct snd_kcontrol *kcontrol)
{
struct link_master *master = snd_kcontrol_chip(kcontrol);
- struct link_slave *slave;
-
- list_for_each_entry(slave, &master->slaves, list)
- slave->master = NULL;
+ struct link_slave *slave, *n;
+
+ /* free all slave links and retore the original slave kctls */
+ list_for_each_entry_safe(slave, n, &master->slaves, list) {
+ struct snd_kcontrol *sctl = slave->kctl;
+ struct list_head olist = sctl->list;
+ memcpy(sctl, &slave->slave, sizeof(*sctl));
+ memcpy(sctl->vd, slave->slave.vd,
+ sctl->count * sizeof(*sctl->vd));
+ sctl->list = olist; /* keep the current linked-list */
+ kfree(slave);
+ }
kfree(master);
}
@@ -397,3 +414,41 @@ struct snd_kcontrol *snd_ctl_make_virtual_master(char *name,
return kctl;
}
EXPORT_SYMBOL(snd_ctl_make_virtual_master);
+
+/**
+ * snd_ctl_add_vmaster_hook - Add a hook to a vmaster control
+ * @kcontrol: vmaster kctl element
+ * @hook: the hook function
+ *
+ * Adds the given hook to the vmaster control element so that it's called
+ * at each time when the value is changed.
+ */
+int snd_ctl_add_vmaster_hook(struct snd_kcontrol *kcontrol,
+ void (*hook)(void *private_data, int),
+ void *private_data)
+{
+ struct link_master *master = snd_kcontrol_chip(kcontrol);
+ master->hook = hook;
+ master->hook_private_data = private_data;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_ctl_add_vmaster_hook);
+
+/**
+ * snd_ctl_sync_vmaster_hook - Sync the vmaster hook
+ * @kcontrol: vmaster kctl element
+ *
+ * Call the hook function to synchronize with the current value of the given
+ * vmaster element. NOP when NULL is passed to @kcontrol or the hook doesn't
+ * exist.
+ */
+void snd_ctl_sync_vmaster_hook(struct snd_kcontrol *kcontrol)
+{
+ struct link_master *master;
+ if (!kcontrol)
+ return;
+ master = snd_kcontrol_chip(kcontrol);
+ if (master->hook)
+ master->hook(master->hook_private_data, master->val);
+}
+EXPORT_SYMBOL_GPL(snd_ctl_sync_vmaster_hook);
diff --git a/sound/drivers/aloop.c b/sound/drivers/aloop.c
index a0da7755fcea..ad079b63b8ba 100644
--- a/sound/drivers/aloop.c
+++ b/sound/drivers/aloop.c
@@ -34,7 +34,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -51,7 +51,7 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Loopback soundcard}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
+static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
static int pcm_notify[SNDRV_CARDS];
@@ -575,7 +575,8 @@ static void loopback_runtime_free(struct snd_pcm_runtime *runtime)
static int loopback_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+ return snd_pcm_lib_alloc_vmalloc_buffer(substream,
+ params_buffer_bytes(params));
}
static int loopback_hw_free(struct snd_pcm_substream *substream)
@@ -587,7 +588,7 @@ static int loopback_hw_free(struct snd_pcm_substream *substream)
mutex_lock(&dpcm->loopback->cable_lock);
cable->valid &= ~(1 << substream->stream);
mutex_unlock(&dpcm->loopback->cable_lock);
- return snd_pcm_lib_free_pages(substream);
+ return snd_pcm_lib_free_vmalloc_buffer(substream);
}
static unsigned int get_cable_index(struct snd_pcm_substream *substream)
@@ -740,6 +741,8 @@ static struct snd_pcm_ops loopback_playback_ops = {
.prepare = loopback_prepare,
.trigger = loopback_trigger,
.pointer = loopback_pointer,
+ .page = snd_pcm_lib_get_vmalloc_page,
+ .mmap = snd_pcm_lib_mmap_vmalloc,
};
static struct snd_pcm_ops loopback_capture_ops = {
@@ -751,6 +754,8 @@ static struct snd_pcm_ops loopback_capture_ops = {
.prepare = loopback_prepare,
.trigger = loopback_trigger,
.pointer = loopback_pointer,
+ .page = snd_pcm_lib_get_vmalloc_page,
+ .mmap = snd_pcm_lib_mmap_vmalloc,
};
static int __devinit loopback_pcm_new(struct loopback *loopback,
@@ -771,10 +776,6 @@ static int __devinit loopback_pcm_new(struct loopback *loopback,
strcpy(pcm->name, "Loopback PCM");
loopback->pcm[device] = pcm;
-
- snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
- snd_dma_continuous_data(GFP_KERNEL),
- 0, 2 * 1024 * 1024);
return 0;
}
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 7f41990ed68b..ad9434fd6370 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -27,7 +27,7 @@
#include <linux/wait.h>
#include <linux/hrtimer.h>
#include <linux/math64.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/tlv.h>
@@ -60,15 +60,15 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Dummy soundcard}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
+static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
static char *model[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = NULL};
static int pcm_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
static int pcm_substreams[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8};
//static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
#ifdef CONFIG_HIGH_RES_TIMERS
-static int hrtimer = 1;
+static bool hrtimer = 1;
#endif
-static int fake_buffer = 1;
+static bool fake_buffer = 1;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for dummy soundcard.");
diff --git a/sound/drivers/ml403-ac97cr.c b/sound/drivers/ml403-ac97cr.c
index 5cfcb908c430..6c83b1aed288 100644
--- a/sound/drivers/ml403-ac97cr.c
+++ b/sound/drivers/ml403-ac97cr.c
@@ -34,7 +34,7 @@
*/
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
@@ -73,7 +73,7 @@ MODULE_SUPPORTED_DEVICE("{{Xilinx,ML403 AC97 Controller Reference}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for ML403 AC97 Controller Reference.");
@@ -1153,7 +1153,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
"0x%x done\n", (unsigned int)ml403_ac97cr->port);
/* get irq */
irq = platform_get_irq(pfdev, 0);
- if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED,
+ if (request_irq(irq, snd_ml403_ac97cr_irq, 0,
dev_name(&pfdev->dev), (void *)ml403_ac97cr)) {
snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": "
"unable to grab IRQ %d\n",
@@ -1166,7 +1166,7 @@ snd_ml403_ac97cr_create(struct snd_card *card, struct platform_device *pfdev,
"request (playback) irq %d done\n",
ml403_ac97cr->irq);
irq = platform_get_irq(pfdev, 1);
- if (request_irq(irq, snd_ml403_ac97cr_irq, IRQF_DISABLED,
+ if (request_irq(irq, snd_ml403_ac97cr_irq, 0,
dev_name(&pfdev->dev), (void *)ml403_ac97cr)) {
snd_printk(KERN_ERR SND_ML403_AC97CR_DRIVER ": "
"unable to grab IRQ %d\n",
@@ -1341,15 +1341,4 @@ static struct platform_driver snd_ml403_ac97cr_driver = {
},
};
-static int __init alsa_card_ml403_ac97cr_init(void)
-{
- return platform_driver_register(&snd_ml403_ac97cr_driver);
-}
-
-static void __exit alsa_card_ml403_ac97cr_exit(void)
-{
- platform_driver_unregister(&snd_ml403_ac97cr_driver);
-}
-
-module_init(alsa_card_ml403_ac97cr_init)
-module_exit(alsa_card_ml403_ac97cr_exit)
+module_platform_driver(snd_ml403_ac97cr_driver);
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index 149d05a8202d..86f5fbc2da72 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -24,7 +24,7 @@
#include <linux/pnp.h>
#include <linux/err.h>
#include <linux/platform_device.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/mpu401.h>
#include <sound/initval.h>
@@ -35,13 +35,13 @@ MODULE_LICENSE("GPL");
static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* exclude the first card */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
#ifdef CONFIG_PNP
-static int pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool pnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
#endif
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* MPU-401 port number */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* MPU-401 IRQ */
-static int uart_enter[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool uart_enter[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for MPU-401 device.");
@@ -86,8 +86,7 @@ static int snd_mpu401_create(int dev, struct snd_card **rcard)
}
err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401, port[dev], 0,
- irq[dev], irq[dev] >= 0 ? IRQF_DISABLED : 0,
- NULL);
+ irq[dev], NULL);
if (err < 0) {
printk(KERN_ERR "MPU401 not detected at 0x%lx\n", port[dev]);
goto _err;
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 2af09996a3d0..1cff331a228e 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -3,7 +3,7 @@
* Routines for control of MPU-401 in UART mode
*
* MPU-401 supports UART mode which is not capable generate transmit
- * interrupts thus output is done via polling. Also, if irq < 0, then
+ * interrupts thus output is done via polling. Without interrupt,
* input is done also via polling. Do not expect good performance.
*
*
@@ -33,6 +33,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/errno.h>
#include <sound/core.h>
@@ -374,7 +375,7 @@ snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
/* first time - flush FIFO */
while (max-- > 0)
mpu->read(mpu, MPU401D(mpu));
- if (mpu->irq < 0)
+ if (mpu->info_flags & MPU401_INFO_USE_TIMER)
snd_mpu401_uart_add_timer(mpu, 1);
}
@@ -383,7 +384,7 @@ snd_mpu401_uart_input_trigger(struct snd_rawmidi_substream *substream, int up)
snd_mpu401_uart_input_read(mpu);
spin_unlock_irqrestore(&mpu->input_lock, flags);
} else {
- if (mpu->irq < 0)
+ if (mpu->info_flags & MPU401_INFO_USE_TIMER)
snd_mpu401_uart_remove_timer(mpu, 1);
clear_bit(MPU401_MODE_BIT_INPUT_TRIGGER, &mpu->mode);
}
@@ -496,7 +497,7 @@ static struct snd_rawmidi_ops snd_mpu401_uart_input =
static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
{
struct snd_mpu401 *mpu = rmidi->private_data;
- if (mpu->irq_flags && mpu->irq >= 0)
+ if (mpu->irq >= 0)
free_irq(mpu->irq, (void *) mpu);
release_and_free_resource(mpu->res);
kfree(mpu);
@@ -509,8 +510,7 @@ static void snd_mpu401_uart_free(struct snd_rawmidi *rmidi)
* @hardware: the hardware type, MPU401_HW_XXXX
* @port: the base address of MPU401 port
* @info_flags: bitflags MPU401_INFO_XXX
- * @irq: the irq number, -1 if no interrupt for mpu
- * @irq_flags: the irq request flags (SA_XXX), 0 if irq was already reserved.
+ * @irq: the ISA irq number, -1 if not to be allocated
* @rrawmidi: the pointer to store the new rawmidi instance
*
* Creates a new MPU-401 instance.
@@ -525,7 +525,7 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
unsigned short hardware,
unsigned long port,
unsigned int info_flags,
- int irq, int irq_flags,
+ int irq,
struct snd_rawmidi ** rrawmidi)
{
struct snd_mpu401 *mpu;
@@ -577,8 +577,8 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
mpu->cport = port + 2;
else
mpu->cport = port + 1;
- if (irq >= 0 && irq_flags) {
- if (request_irq(irq, snd_mpu401_uart_interrupt, irq_flags,
+ if (irq >= 0) {
+ if (request_irq(irq, snd_mpu401_uart_interrupt, 0,
"MPU401 UART", (void *) mpu)) {
snd_printk(KERN_ERR "mpu401_uart: "
"unable to grab IRQ %d\n", irq);
@@ -586,9 +586,10 @@ int snd_mpu401_uart_new(struct snd_card *card, int device,
return -EBUSY;
}
}
+ if (irq < 0 && !(info_flags & MPU401_INFO_IRQ_HOOK))
+ info_flags |= MPU401_INFO_USE_TIMER;
mpu->info_flags = info_flags;
mpu->irq = irq;
- mpu->irq_flags = irq_flags;
if (card->shortname[0])
snprintf(rmidi->name, sizeof(rmidi->name), "%s MIDI",
card->shortname);
diff --git a/sound/drivers/mtpav.c b/sound/drivers/mtpav.c
index 5c426df87678..76930793fb69 100644
--- a/sound/drivers/mtpav.c
+++ b/sound/drivers/mtpav.c
@@ -52,6 +52,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
+#include <linux/module.h>
#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
@@ -589,7 +590,7 @@ static int __devinit snd_mtpav_get_ISA(struct mtpav * mcard)
return -EBUSY;
}
mcard->port = port;
- if (request_irq(irq, snd_mtpav_irqh, IRQF_DISABLED, "MOTU MTPAV", mcard)) {
+ if (request_irq(irq, snd_mtpav_irqh, 0, "MOTU MTPAV", mcard)) {
snd_printk(KERN_ERR "MTVAP IRQ %d busy\n", irq);
return -EBUSY;
}
diff --git a/sound/drivers/mts64.c b/sound/drivers/mts64.c
index 8539ab0a0893..621e60e2029f 100644
--- a/sound/drivers/mts64.c
+++ b/sound/drivers/mts64.c
@@ -22,6 +22,7 @@
#include <linux/platform_device.h>
#include <linux/parport.h>
#include <linux/spinlock.h>
+#include <linux/module.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -35,7 +36,7 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static struct platform_device *platform_devices[SNDRV_CARDS];
static int device_count;
diff --git a/sound/drivers/opl3/opl3_lib.c b/sound/drivers/opl3/opl3_lib.c
index 6e31e46ca393..33d9a857a262 100644
--- a/sound/drivers/opl3/opl3_lib.c
+++ b/sound/drivers/opl3/opl3_lib.c
@@ -26,6 +26,7 @@
#include <sound/opl3.h>
#include <asm/io.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/ioport.h>
diff --git a/sound/drivers/opl3/opl3_midi.c b/sound/drivers/opl3/opl3_midi.c
index 7d722a025d0d..2bfe4bcb7a7d 100644
--- a/sound/drivers/opl3/opl3_midi.c
+++ b/sound/drivers/opl3/opl3_midi.c
@@ -27,7 +27,7 @@
extern char snd_opl3_regmap[MAX_OPL2_VOICES][4];
-extern int use_internal_drums;
+extern bool use_internal_drums;
static void snd_opl3_note_off_unsafe(void *p, int note, int vel,
struct snd_midi_channel *chan);
diff --git a/sound/drivers/opl3/opl3_oss.c b/sound/drivers/opl3/opl3_oss.c
index ade3ca52422e..c1cb249acfaa 100644
--- a/sound/drivers/opl3/opl3_oss.c
+++ b/sound/drivers/opl3/opl3_oss.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/export.h>
#include "opl3_voice.h"
static int snd_opl3_open_seq_oss(struct snd_seq_oss_arg *arg, void *closure);
diff --git a/sound/drivers/opl3/opl3_seq.c b/sound/drivers/opl3/opl3_seq.c
index 2d33f53d36b8..68399538e435 100644
--- a/sound/drivers/opl3/opl3_seq.c
+++ b/sound/drivers/opl3/opl3_seq.c
@@ -25,13 +25,14 @@
#include "opl3_voice.h"
#include <linux/init.h>
#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/initval.h>
MODULE_AUTHOR("Uros Bizjak <uros@kss-loka.si>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("ALSA driver for OPL3 FM synth");
-int use_internal_drums = 0;
+bool use_internal_drums = 0;
module_param(use_internal_drums, bool, 0444);
MODULE_PARM_DESC(use_internal_drums, "Enable internal OPL2/3 drums.");
diff --git a/sound/drivers/opl3/opl3_synth.c b/sound/drivers/opl3/opl3_synth.c
index 301acb6b9cf9..742a4b642fd9 100644
--- a/sound/drivers/opl3/opl3_synth.c
+++ b/sound/drivers/opl3/opl3_synth.c
@@ -20,6 +20,7 @@
*/
#include <linux/slab.h>
+#include <linux/export.h>
#include <sound/opl3.h>
#include <sound/asound_fm.h>
diff --git a/sound/drivers/opl4/opl4_lib.c b/sound/drivers/opl4/opl4_lib.c
index f07e38da59b8..b953fb4aa298 100644
--- a/sound/drivers/opl4/opl4_lib.c
+++ b/sound/drivers/opl4/opl4_lib.c
@@ -22,6 +22,7 @@
#include <linux/ioport.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <asm/io.h>
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
diff --git a/sound/drivers/opl4/opl4_proc.c b/sound/drivers/opl4/opl4_proc.c
index df850b8830a5..9b824bfc919d 100644
--- a/sound/drivers/opl4/opl4_proc.c
+++ b/sound/drivers/opl4/opl4_proc.c
@@ -19,6 +19,7 @@
#include "opl4_local.h"
#include <linux/vmalloc.h>
+#include <linux/export.h>
#include <sound/info.h>
#ifdef CONFIG_PROC_FS
diff --git a/sound/drivers/opl4/opl4_seq.c b/sound/drivers/opl4/opl4_seq.c
index 43d8a2bdd280..99197699c55a 100644
--- a/sound/drivers/opl4/opl4_seq.c
+++ b/sound/drivers/opl4/opl4_seq.c
@@ -34,6 +34,7 @@
#include "opl4_local.h"
#include <linux/init.h>
#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/initval.h>
MODULE_AUTHOR("Clemens Ladisch <clemens@ladisch.de>");
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index f165c77d6273..99704e6a2e26 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -6,7 +6,7 @@
*/
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -25,8 +25,8 @@ MODULE_ALIAS("platform:pcspkr");
static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
-static int enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */
-static int nopcm; /* Disable PCM capability of the driver */
+static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */
+static bool nopcm; /* Disable PCM capability of the driver */
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for pcsp soundcard.");
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index ce9e7d170c0d..434981dd4a61 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -14,7 +14,7 @@
#include <asm/io.h>
#include "pcsp.h"
-static int nforce_wa;
+static bool nforce_wa;
module_param(nforce_wa, bool, 0444);
MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
"(expect bad sound)");
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
index f2b0ba22d9ce..3e32bd3d95d9 100644
--- a/sound/drivers/portman2x4.c
+++ b/sound/drivers/portman2x4.c
@@ -43,6 +43,7 @@
#include <linux/spinlock.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/rawmidi.h>
@@ -54,7 +55,7 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static struct platform_device *platform_devices[SNDRV_CARDS];
static int device_count;
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index a25fb7b1f441..b2d0e8e49bed 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -36,7 +36,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/ioport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
#include <sound/initval.h>
@@ -69,7 +69,7 @@ static char *adaptor_names[] = {
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x3f8,0x2f8,0x3e8,0x2e8 */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 3,4,5,7,9,10,11,14,15 */
static int speed[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 38400}; /* 9600,19200,38400,57600,115200 */
@@ -77,7 +77,7 @@ static int base[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 115200}; /* baud bas
static int outs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */
static int ins[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1}; /* 1 to 16 */
static int adaptor[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = SNDRV_SERIAL_SOUNDCANVAS};
-static int droponfull[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS -1)] = SNDRV_SERIAL_NORMALBUFF };
+static bool droponfull[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS -1)] = SNDRV_SERIAL_NORMALBUFF };
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Serial MIDI.");
@@ -816,7 +816,7 @@ static int __devinit snd_uart16550_create(struct snd_card *card,
if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
if (request_irq(irq, snd_uart16550_interrupt,
- IRQF_DISABLED, "Serial MIDI", uart)) {
+ 0, "Serial MIDI", uart)) {
snd_printk(KERN_WARNING
"irq %d busy. Using Polling.\n", irq);
} else {
diff --git a/sound/drivers/virmidi.c b/sound/drivers/virmidi.c
index f4cd49336f33..9d97478a18b3 100644
--- a/sound/drivers/virmidi.c
+++ b/sound/drivers/virmidi.c
@@ -45,7 +45,7 @@
#include <linux/wait.h>
#include <linux/err.h>
#include <linux/platform_device.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/seq_kernel.h>
#include <sound/seq_virmidi.h>
@@ -63,7 +63,7 @@ MODULE_SUPPORTED_DEVICE("{{ALSA,Virtual rawmidi device}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
+static bool enable[SNDRV_CARDS] = {1, [1 ... (SNDRV_CARDS - 1)] = 0};
static int midi_devs[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
module_param_array(index, int, NULL, 0444);
diff --git a/sound/drivers/vx/vx_core.c b/sound/drivers/vx/vx_core.c
index 19c6e376c7c7..b8e515999bc2 100644
--- a/sound/drivers/vx/vx_core.c
+++ b/sound/drivers/vx/vx_core.c
@@ -26,6 +26,7 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/firmware.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/asoundef.h>
diff --git a/sound/drivers/vx/vx_hwdep.c b/sound/drivers/vx/vx_hwdep.c
index f7a6fbd313e3..4a1fae99ac55 100644
--- a/sound/drivers/vx/vx_hwdep.c
+++ b/sound/drivers/vx/vx_hwdep.c
@@ -24,6 +24,7 @@
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/hwdep.h>
#include <sound/vx_core.h>
diff --git a/sound/firewire/cmp.c b/sound/firewire/cmp.c
index 14cacbc655dd..76294f2ae47f 100644
--- a/sound/firewire/cmp.c
+++ b/sound/firewire/cmp.c
@@ -32,7 +32,7 @@ enum bus_reset_handling {
SUCCEED_ON_BUS_RESET,
};
-static __attribute__((format(printf, 2, 3)))
+static __printf(2, 3)
void cmp_error(struct cmp_connection *c, const char *fmt, ...)
{
va_list va;
diff --git a/sound/firewire/isight.c b/sound/firewire/isight.c
index 412b65f740d9..d428ffede4f3 100644
--- a/sound/firewire/isight.c
+++ b/sound/firewire/isight.c
@@ -51,7 +51,6 @@ struct isight {
struct fw_unit *unit;
struct fw_device *device;
u64 audio_base;
- struct fw_address_handler iris_handler;
struct snd_pcm_substream *pcm;
struct mutex mutex;
struct iso_packets_buffer buffer;
diff --git a/sound/firewire/iso-resources.c b/sound/firewire/iso-resources.c
index ffe20b877e9f..5f17b77ee152 100644
--- a/sound/firewire/iso-resources.c
+++ b/sound/firewire/iso-resources.c
@@ -8,6 +8,7 @@
#include <linux/device.h>
#include <linux/firewire.h>
#include <linux/firewire-constants.h>
+#include <linux/export.h>
#include <linux/jiffies.h>
#include <linux/mutex.h>
#include <linux/sched.h>
diff --git a/sound/firewire/packets-buffer.c b/sound/firewire/packets-buffer.c
index 3c61ca2e6152..ea1506679c66 100644
--- a/sound/firewire/packets-buffer.c
+++ b/sound/firewire/packets-buffer.c
@@ -6,6 +6,7 @@
*/
#include <linux/firewire.h>
+#include <linux/export.h>
#include <linux/slab.h>
#include "packets-buffer.h"
diff --git a/sound/firewire/speakers.c b/sound/firewire/speakers.c
index 18b9b5607f3c..297244e658d9 100644
--- a/sound/firewire/speakers.c
+++ b/sound/firewire/speakers.c
@@ -774,9 +774,10 @@ static int __devexit fwspk_remove(struct device *dev)
{
struct fwspk *fwspk = dev_get_drvdata(dev);
- mutex_lock(&fwspk->mutex);
amdtp_out_stream_pcm_abort(&fwspk->stream);
snd_card_disconnect(fwspk->card);
+
+ mutex_lock(&fwspk->mutex);
fwspk_stop_stream(fwspk);
mutex_unlock(&fwspk->mutex);
@@ -792,8 +793,8 @@ static void fwspk_bus_reset(struct fw_unit *unit)
fcp_bus_reset(fwspk->unit);
if (cmp_connection_update(&fwspk->connection) < 0) {
- mutex_lock(&fwspk->mutex);
amdtp_out_stream_pcm_abort(&fwspk->stream);
+ mutex_lock(&fwspk->mutex);
fwspk_stop_stream(fwspk);
mutex_unlock(&fwspk->mutex);
return;
diff --git a/sound/i2c/cs8427.c b/sound/i2c/cs8427.c
index 04ae8704cdcd..6c2dc3863ac0 100644
--- a/sound/i2c/cs8427.c
+++ b/sound/i2c/cs8427.c
@@ -24,6 +24,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/bitrev.h>
+#include <linux/module.h>
#include <asm/unaligned.h>
#include <sound/core.h>
#include <sound/control.h>
diff --git a/sound/i2c/i2c.c b/sound/i2c/i2c.c
index eb7c7d05a7c1..4677037f0c8e 100644
--- a/sound/i2c/i2c.c
+++ b/sound/i2c/i2c.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/string.h>
#include <linux/errno.h>
#include <sound/core.h>
diff --git a/sound/i2c/other/ak4113.c b/sound/i2c/other/ak4113.c
index c424d329f806..dde5c9c92132 100644
--- a/sound/i2c/other/ak4113.c
+++ b/sound/i2c/other/ak4113.c
@@ -23,6 +23,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index d9fb537b0b94..fdf3c1b65e38 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 2cad2d612518..b4b2a51fc117 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -22,6 +22,7 @@
#include <linux/slab.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 57ccba88700d..cef813d23641 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/tlv.h>
diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c
index 797d3a6687eb..9fa390ba1718 100644
--- a/sound/i2c/other/pt2258.c
+++ b/sound/i2c/other/pt2258.c
@@ -24,6 +24,7 @@
#include <sound/tlv.h>
#include <sound/i2c.h>
#include <sound/pt2258.h>
+#include <linux/module.h>
MODULE_AUTHOR("Jochen Voss <voss@seehuhn.de>");
MODULE_DESCRIPTION("PT2258 volume controller (Princeton Technology Corp.)");
diff --git a/sound/i2c/other/tea575x-tuner.c b/sound/i2c/other/tea575x-tuner.c
index 484a35b3715f..6b68c8206805 100644
--- a/sound/i2c/other/tea575x-tuner.c
+++ b/sound/i2c/other/tea575x-tuner.c
@@ -22,6 +22,7 @@
#include <asm/io.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/version.h>
diff --git a/sound/i2c/tea6330t.c b/sound/i2c/tea6330t.c
index 0e3a9f2c5297..2d22310dce05 100644
--- a/sound/i2c/tea6330t.c
+++ b/sound/i2c/tea6330t.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/tea6330t.h>
diff --git a/sound/isa/ad1816a/ad1816a.c b/sound/isa/ad1816a/ad1816a.c
index 3cb75bc97699..94b83b6e46a3 100644
--- a/sound/isa/ad1816a/ad1816a.c
+++ b/sound/isa/ad1816a/ad1816a.c
@@ -22,7 +22,7 @@
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/pnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/ad1816a.h>
@@ -44,7 +44,7 @@ MODULE_SUPPORTED_DEVICE("{{Highscreen,Sound-Boostar 16 3D},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 1-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
@@ -204,7 +204,7 @@ static int __devinit snd_card_ad1816a_probe(int dev, struct pnp_card_link *pcard
if (mpu_port[dev] > 0) {
if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
- mpu_port[dev], 0, mpu_irq[dev], IRQF_DISABLED,
+ mpu_port[dev], 0, mpu_irq[dev],
NULL) < 0)
printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n", mpu_port[dev]);
}
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index 05aef8b97e96..177eed3271bc 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -595,7 +595,7 @@ int __devinit snd_ad1816a_create(struct snd_card *card,
snd_ad1816a_free(chip);
return -EBUSY;
}
- if (request_irq(irq, snd_ad1816a_interrupt, IRQF_DISABLED, "AD1816A", (void *) chip)) {
+ if (request_irq(irq, snd_ad1816a_interrupt, 0, "AD1816A", (void *) chip)) {
snd_printk(KERN_ERR "ad1816a: can't grab IRQ %d\n", irq);
snd_ad1816a_free(chip);
return -EBUSY;
diff --git a/sound/isa/ad1848/ad1848.c b/sound/isa/ad1848/ad1848.c
index 4beeb6f98e0e..2af77faefbb1 100644
--- a/sound/isa/ad1848/ad1848.c
+++ b/sound/isa/ad1848/ad1848.c
@@ -26,7 +26,7 @@
#include <linux/isa.h>
#include <linux/time.h>
#include <linux/wait.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/wss.h>
#include <sound/initval.h>
@@ -43,11 +43,11 @@ MODULE_SUPPORTED_DEVICE("{{Analog Devices,AD1848},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
-static int thinkpad[SNDRV_CARDS]; /* Thinkpad special case */
+static bool thinkpad[SNDRV_CARDS]; /* Thinkpad special case */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
index 7465ae036e0b..4d50c69f3290 100644
--- a/sound/isa/adlib.c
+++ b/sound/isa/adlib.c
@@ -18,7 +18,7 @@ MODULE_LICENSE("GPL");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
module_param_array(index, int, NULL, 0444);
diff --git a/sound/isa/als100.c b/sound/isa/als100.c
index 20becc89f6f6..d1f4351fb6ee 100644
--- a/sound/isa/als100.c
+++ b/sound/isa/als100.c
@@ -28,7 +28,7 @@
#include <linux/wait.h>
#include <linux/time.h>
#include <linux/pnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/mpu401.h>
@@ -54,7 +54,7 @@ MODULE_LICENSE("GPL");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
@@ -256,7 +256,6 @@ static int __devinit snd_card_als100_probe(int dev,
mpu_type,
mpu_port[dev], 0,
mpu_irq[dev],
- mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0,
NULL) < 0)
snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
}
diff --git a/sound/isa/azt2320.c b/sound/isa/azt2320.c
index aac8dc15c2fe..6a2c78ef1d8f 100644
--- a/sound/isa/azt2320.c
+++ b/sound/isa/azt2320.c
@@ -35,7 +35,7 @@
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/pnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/wss.h>
@@ -55,7 +55,7 @@ MODULE_SUPPORTED_DEVICE("{{Aztech Systems,PRO16V},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
@@ -234,8 +234,7 @@ static int __devinit snd_card_azt2320_probe(int dev,
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320,
mpu_port[dev], 0,
- mpu_irq[dev], IRQF_DISABLED,
- NULL) < 0)
+ mpu_irq[dev], NULL) < 0)
snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
}
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index fe79a169acb5..7bd5e337ee93 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -47,7 +47,7 @@
#include <linux/err.h>
#include <linux/isa.h>
#include <linux/pnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/wss.h>
#include <sound/opl3.h>
@@ -69,9 +69,9 @@ MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8330,isapnp:{CMI0001,@@@0001,@X@0001}}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
#ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
#endif
static long sbport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
static int sbirq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
@@ -597,7 +597,7 @@ static int __devinit snd_cmi8330_probe(struct snd_card *card, int dev)
if (mpuport[dev] != SNDRV_AUTO_PORT) {
if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
mpuport[dev], 0, mpuirq[dev],
- IRQF_DISABLED, NULL) < 0)
+ NULL) < 0)
printk(KERN_ERR PFX "no MPU-401 device at 0x%lx.\n",
mpuport[dev]);
}
diff --git a/sound/isa/cs423x/cs4231.c b/sound/isa/cs423x/cs4231.c
index cb9153e75b82..99dda45e82f5 100644
--- a/sound/isa/cs423x/cs4231.c
+++ b/sound/isa/cs423x/cs4231.c
@@ -25,7 +25,7 @@
#include <linux/isa.h>
#include <linux/time.h>
#include <linux/wait.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/wss.h>
#include <sound/mpu401.h>
@@ -41,7 +41,7 @@ MODULE_SUPPORTED_DEVICE("{{Crystal Semiconductors,CS4231}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
@@ -131,7 +131,6 @@ static int __devinit snd_cs4231_probe(struct device *dev, unsigned int n)
mpu_irq[n] = -1;
if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
mpu_port[n], 0, mpu_irq[n],
- mpu_irq[n] >= 0 ? IRQF_DISABLED : 0,
NULL) < 0)
dev_warn(dev, "MPU401 not detected\n");
}
diff --git a/sound/isa/cs423x/cs4236.c b/sound/isa/cs423x/cs4236.c
index 999dc1e0fdbd..740c51a1ed7b 100644
--- a/sound/isa/cs423x/cs4236.c
+++ b/sound/isa/cs423x/cs4236.c
@@ -23,7 +23,7 @@
#include <linux/err.h>
#include <linux/isa.h>
#include <linux/pnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/wss.h>
#include <sound/mpu401.h>
@@ -74,9 +74,9 @@ MODULE_ALIAS("snd_cs4232");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
#ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
#endif
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static long cport[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
@@ -449,8 +449,7 @@ static int __devinit snd_cs423x_probe(struct snd_card *card, int dev)
mpu_irq[dev] = -1;
if (snd_mpu401_uart_new(card, 0, MPU401_HW_CS4232,
mpu_port[dev], 0,
- mpu_irq[dev],
- mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0, NULL) < 0)
+ mpu_irq[dev], NULL) < 0)
printk(KERN_WARNING IDENT ": MPU401 not detected\n");
}
diff --git a/sound/isa/es1688/es1688.c b/sound/isa/es1688/es1688.c
index 0cde8131a575..b036e60f62d1 100644
--- a/sound/isa/es1688/es1688.c
+++ b/sound/isa/es1688/es1688.c
@@ -25,7 +25,7 @@
#include <linux/isapnp.h>
#include <linux/time.h>
#include <linux/wait.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/es1688.h>
@@ -51,9 +51,9 @@ MODULE_ALIAS("snd_es968");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
#ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
+static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
#endif
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */
static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* Usually 0x388 */
static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
@@ -174,7 +174,7 @@ static int __devinit snd_es1688_probe(struct snd_card *card, unsigned int n)
chip->mpu_port > 0) {
error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
chip->mpu_port, 0,
- mpu_irq[n], IRQF_DISABLED, NULL);
+ mpu_irq[n], NULL);
if (error < 0)
return error;
}
diff --git a/sound/isa/es1688/es1688_lib.c b/sound/isa/es1688/es1688_lib.c
index 07676200496a..1d47be8170b5 100644
--- a/sound/isa/es1688/es1688_lib.c
+++ b/sound/isa/es1688/es1688_lib.c
@@ -24,6 +24,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/es1688.h>
#include <sound/initval.h>
@@ -661,7 +662,7 @@ int snd_es1688_create(struct snd_card *card,
snd_printk(KERN_ERR "es1688: can't grab port 0x%lx\n", port + 4);
return -EBUSY;
}
- if (request_irq(irq, snd_es1688_interrupt, IRQF_DISABLED, "ES1688", (void *) chip)) {
+ if (request_irq(irq, snd_es1688_interrupt, 0, "ES1688", (void *) chip)) {
snd_printk(KERN_ERR "es1688: can't grab IRQ %d\n", irq);
return -EBUSY;
}
diff --git a/sound/isa/es18xx.c b/sound/isa/es18xx.c
index fb4d6b34bbca..c20baafd9b7c 100644
--- a/sound/isa/es18xx.c
+++ b/sound/isa/es18xx.c
@@ -82,7 +82,7 @@
#include <linux/isa.h>
#include <linux/pnp.h>
#include <linux/isapnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/delay.h>
#include <asm/io.h>
@@ -1805,7 +1805,7 @@ static int __devinit snd_es18xx_new_device(struct snd_card *card,
return -EBUSY;
}
- if (request_irq(irq, snd_es18xx_interrupt, IRQF_DISABLED, "ES18xx",
+ if (request_irq(irq, snd_es18xx_interrupt, 0, "ES18xx",
(void *) card)) {
snd_es18xx_free(card);
snd_printk(KERN_ERR PFX "unable to grap IRQ %d\n", irq);
@@ -1964,9 +1964,9 @@ MODULE_SUPPORTED_DEVICE("{{ESS,ES1868 PnP AudioDrive},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
#ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
+static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
#endif
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */
#ifndef CONFIG_PNP
@@ -2160,8 +2160,8 @@ static int __devinit snd_audiodrive_probe(struct snd_card *card, int dev)
if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
- mpu_port[dev], 0,
- irq[dev], 0, &chip->rmidi);
+ mpu_port[dev], MPU401_INFO_IRQ_HOOK,
+ -1, &chip->rmidi);
if (err < 0)
return err;
}
diff --git a/sound/isa/galaxy/galaxy.c b/sound/isa/galaxy/galaxy.c
index ee54df082b9c..55e20782858d 100644
--- a/sound/isa/galaxy/galaxy.c
+++ b/sound/isa/galaxy/galaxy.c
@@ -35,7 +35,7 @@ MODULE_LICENSE("GPL");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
@@ -585,8 +585,7 @@ static int __devinit snd_galaxy_probe(struct device *dev, unsigned int n)
if (mpu_port[n] >= 0) {
err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
- mpu_port[n], 0, mpu_irq[n],
- IRQF_DISABLED, NULL);
+ mpu_port[n], 0, mpu_irq[n], NULL);
if (err < 0)
goto error;
}
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index 12eb98f2f931..4490ee442ff4 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -24,6 +24,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/gus.h>
#include <sound/control.h>
@@ -180,7 +181,7 @@ int snd_gus_create(struct snd_card *card,
snd_gus_free(gus);
return -EBUSY;
}
- if (irq >= 0 && request_irq(irq, snd_gus_interrupt, IRQF_DISABLED, "GUS GF1", (void *) gus)) {
+ if (irq >= 0 && request_irq(irq, snd_gus_interrupt, 0, "GUS GF1", (void *) gus)) {
snd_printk(KERN_ERR "gus: can't grab irq %d\n", irq);
snd_gus_free(gus);
return -EBUSY;
diff --git a/sound/isa/gus/gus_volume.c b/sound/isa/gus/gus_volume.c
index c3c028a4a46b..3dd841ae708a 100644
--- a/sound/isa/gus/gus_volume.c
+++ b/sound/isa/gus/gus_volume.c
@@ -19,6 +19,7 @@
*/
#include <linux/time.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/gus.h>
#define __GUS_TABLES_ALLOC__
diff --git a/sound/isa/gus/gusclassic.c b/sound/isa/gus/gusclassic.c
index 086b8f0e0f94..bf6333671613 100644
--- a/sound/isa/gus/gusclassic.c
+++ b/sound/isa/gus/gusclassic.c
@@ -24,7 +24,7 @@
#include <linux/isa.h>
#include <linux/delay.h>
#include <linux/time.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/gus.h>
@@ -42,7 +42,7 @@ MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Classic}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x230,0x240,0x250,0x260 */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 3,5,9,11,12,15 */
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
diff --git a/sound/isa/gus/gusextreme.c b/sound/isa/gus/gusextreme.c
index 008e8e5bfa37..bc10cc26e5f9 100644
--- a/sound/isa/gus/gusextreme.c
+++ b/sound/isa/gus/gusextreme.c
@@ -24,7 +24,7 @@
#include <linux/isa.h>
#include <linux/delay.h>
#include <linux/time.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/gus.h>
@@ -46,7 +46,7 @@ MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound Extreme}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */
static long gf1_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS) - 1] = -1}; /* 0x210,0x220,0x230,0x240,0x250,0x260,0x270 */
static long mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS) - 1] = -1}; /* 0x300,0x310,0x320 */
@@ -317,8 +317,7 @@ static int __devinit snd_gusextreme_probe(struct device *dev, unsigned int n)
if (es1688->mpu_port >= 0x300) {
error = snd_mpu401_uart_new(card, 0, MPU401_HW_ES1688,
- es1688->mpu_port, 0,
- mpu_irq[n], IRQF_DISABLED, NULL);
+ es1688->mpu_port, 0, mpu_irq[n], NULL);
if (error < 0)
goto out;
}
diff --git a/sound/isa/gus/gusmax.c b/sound/isa/gus/gusmax.c
index 3e4a58b72913..41c3f448745f 100644
--- a/sound/isa/gus/gusmax.c
+++ b/sound/isa/gus/gusmax.c
@@ -24,7 +24,7 @@
#include <linux/isa.h>
#include <linux/delay.h>
#include <linux/time.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/gus.h>
@@ -40,7 +40,7 @@ MODULE_SUPPORTED_DEVICE("{{Gravis,UltraSound MAX}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x230,0x240,0x250,0x260 */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,3,5,9,11,12,15 */
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3,5,6,7 */
@@ -291,7 +291,7 @@ static int __devinit snd_gusmax_probe(struct device *pdev, unsigned int dev)
goto _err;
}
- if (request_irq(xirq, snd_gusmax_interrupt, IRQF_DISABLED, "GUS MAX", (void *)maxcard)) {
+ if (request_irq(xirq, snd_gusmax_interrupt, 0, "GUS MAX", (void *)maxcard)) {
snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
err = -EBUSY;
goto _err;
diff --git a/sound/isa/gus/interwave.c b/sound/isa/gus/interwave.c
index c7b80e4730fc..a76bc8d27c1d 100644
--- a/sound/isa/gus/interwave.c
+++ b/sound/isa/gus/interwave.c
@@ -27,7 +27,7 @@
#include <linux/isa.h>
#include <linux/delay.h>
#include <linux/pnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/gus.h>
@@ -55,9 +55,9 @@ MODULE_SUPPORTED_DEVICE("{{AMD,InterWave STB with TEA6330T}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
#ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
#endif
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x210,0x220,0x230,0x240,0x250,0x260 */
#ifdef SNDRV_STB
@@ -684,7 +684,7 @@ static int __devinit snd_interwave_probe(struct snd_card *card, int dev)
if ((err = snd_gus_initialize(gus)) < 0)
return err;
- if (request_irq(xirq, snd_interwave_interrupt, IRQF_DISABLED,
+ if (request_irq(xirq, snd_interwave_interrupt, 0,
"InterWave", iwcard)) {
snd_printk(KERN_ERR PFX "unable to grab IRQ %d\n", xirq);
return -EBUSY;
diff --git a/sound/isa/msnd/msnd.c b/sound/isa/msnd/msnd.c
index 3a1526ae1729..1cee18fb28a8 100644
--- a/sound/isa/msnd/msnd.c
+++ b/sound/isa/msnd/msnd.c
@@ -41,6 +41,7 @@
#include <linux/io.h>
#include <linux/fs.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
diff --git a/sound/isa/msnd/msnd_midi.c b/sound/isa/msnd/msnd_midi.c
index 787495674235..ffc67fd80c23 100644
--- a/sound/isa/msnd/msnd_midi.c
+++ b/sound/isa/msnd/msnd_midi.c
@@ -29,6 +29,7 @@
#include <linux/delay.h>
#include <linux/ioport.h>
#include <linux/errno.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/rawmidi.h>
diff --git a/sound/isa/msnd/msnd_pinnacle.c b/sound/isa/msnd/msnd_pinnacle.c
index 91d6023a63e5..29cc8e162b02 100644
--- a/sound/isa/msnd/msnd_pinnacle.c
+++ b/sound/isa/msnd/msnd_pinnacle.c
@@ -600,7 +600,7 @@ static int __devinit snd_msnd_attach(struct snd_card *card)
mpu_io[0],
MPU401_MODE_INPUT |
MPU401_MODE_OUTPUT,
- mpu_irq[0], IRQF_DISABLED,
+ mpu_irq[0],
&chip->rmidi);
if (err < 0) {
printk(KERN_ERR LOGNAME
@@ -785,7 +785,7 @@ static int write_ndelay[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 };
static int calibrate_signal;
#ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(isapnp, bool, NULL, 0444);
MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
#define has_isapnp(x) isapnp[x]
diff --git a/sound/isa/msnd/msnd_pinnacle_mixer.c b/sound/isa/msnd/msnd_pinnacle_mixer.c
index 494058a1a502..1de59d441426 100644
--- a/sound/isa/msnd/msnd_pinnacle_mixer.c
+++ b/sound/isa/msnd/msnd_pinnacle_mixer.c
@@ -16,6 +16,7 @@
***************************************************************************/
#include <linux/io.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/control.h>
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 9b915e27b5bd..f6cc0b917ef0 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -25,7 +25,7 @@
#include <linux/interrupt.h>
#include <linux/pm.h>
#include <linux/pnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/wss.h>
#include <sound/mpu401.h>
@@ -46,9 +46,9 @@ MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF719E-S},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
#ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
#endif
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0xf86,0x370,0x100 */
static long sb_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */
@@ -667,7 +667,7 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
err = snd_opl3sa2_detect(card);
if (err < 0)
return err;
- err = request_irq(xirq, snd_opl3sa2_interrupt, IRQF_DISABLED,
+ err = request_irq(xirq, snd_opl3sa2_interrupt, 0,
"OPL3-SA2", card);
if (err) {
snd_printk(KERN_ERR PFX "can't grab IRQ %d\n", xirq);
@@ -707,8 +707,9 @@ static int __devinit snd_opl3sa2_probe(struct snd_card *card, int dev)
}
if (midi_port[dev] >= 0x300 && midi_port[dev] < 0x340) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_OPL3SA2,
- midi_port[dev], 0,
- xirq, 0, &chip->rmidi)) < 0)
+ midi_port[dev],
+ MPU401_INFO_IRQ_HOOK, -1,
+ &chip->rmidi)) < 0)
return err;
}
sprintf(card->longname, "%s at 0x%lx, irq %d, dma %d",
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
index 8c24102d0d93..c24594c866f4 100644
--- a/sound/isa/opti9xx/miro.c
+++ b/sound/isa/opti9xx/miro.c
@@ -28,7 +28,7 @@
#include <linux/pnp.h>
#include <linux/delay.h>
#include <linux/ioport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <sound/core.h>
@@ -61,7 +61,7 @@ static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
static int wss;
static int ide;
#ifdef CONFIG_PNP
-static int isapnp = 1; /* Enable ISA PnP detection */
+static bool isapnp = 1; /* Enable ISA PnP detection */
#endif
module_param(index, int, 0444);
@@ -1377,8 +1377,7 @@ static int __devinit snd_miro_probe(struct snd_card *card)
rmidi = NULL;
else {
error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
- mpu_port, 0, miro->mpu_irq, IRQF_DISABLED,
- &rmidi);
+ mpu_port, 0, miro->mpu_irq, &rmidi);
if (error < 0)
snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
mpu_port);
diff --git a/sound/isa/opti9xx/opti92x-ad1848.c b/sound/isa/opti9xx/opti92x-ad1848.c
index c35dc68930dc..babaedd242f7 100644
--- a/sound/isa/opti9xx/opti92x-ad1848.c
+++ b/sound/isa/opti9xx/opti92x-ad1848.c
@@ -28,7 +28,7 @@
#include <linux/isa.h>
#include <linux/delay.h>
#include <linux/pnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <asm/dma.h>
#include <sound/core.h>
@@ -63,7 +63,7 @@ MODULE_SUPPORTED_DEVICE("{{OPTi,82C924 (AD1848)},"
static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
-//static int enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */
+//static bool enable = SNDRV_DEFAULT_ENABLE1; /* Enable this card */
#ifdef CONFIG_PNP
static int isapnp = 1; /* Enable ISA PnP detection */
#endif
@@ -892,7 +892,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
#endif
#ifdef OPTi93X
error = request_irq(irq, snd_opti93x_interrupt,
- IRQF_DISABLED, DEV_NAME" - WSS", chip);
+ 0, DEV_NAME" - WSS", chip);
if (error < 0) {
snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq);
return error;
@@ -914,7 +914,7 @@ static int __devinit snd_opti9xx_probe(struct snd_card *card)
rmidi = NULL;
else {
error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
- mpu_port, 0, mpu_irq, IRQF_DISABLED, &rmidi);
+ mpu_port, 0, mpu_irq, &rmidi);
if (error)
snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
mpu_port);
diff --git a/sound/isa/sb/emu8000.c b/sound/isa/sb/emu8000.c
index 5d61f5a29130..71887874679c 100644
--- a/sound/isa/sb/emu8000.c
+++ b/sound/isa/sb/emu8000.c
@@ -24,6 +24,7 @@
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/export.h>
#include <linux/delay.h>
#include <sound/core.h>
#include <sound/emu8000.h>
diff --git a/sound/isa/sb/emu8000_callback.c b/sound/isa/sb/emu8000_callback.c
index 9a3c71cc2e07..344b4355be1c 100644
--- a/sound/isa/sb/emu8000_callback.c
+++ b/sound/isa/sb/emu8000_callback.c
@@ -20,6 +20,7 @@
*/
#include "emu8000_local.h"
+#include <linux/export.h>
#include <sound/asoundef.h>
/*
diff --git a/sound/isa/sb/emu8000_synth.c b/sound/isa/sb/emu8000_synth.c
index 0c7905c85b76..4e3fcfb15ad4 100644
--- a/sound/isa/sb/emu8000_synth.c
+++ b/sound/isa/sb/emu8000_synth.c
@@ -22,6 +22,7 @@
#include "emu8000_local.h"
#include <linux/init.h>
+#include <linux/module.h>
#include <sound/initval.h>
MODULE_AUTHOR("Takashi Iwai, Steve Ratcliffe");
diff --git a/sound/isa/sb/jazz16.c b/sound/isa/sb/jazz16.c
index 8ccbcddf08e1..410758c68090 100644
--- a/sound/isa/sb/jazz16.c
+++ b/sound/isa/sb/jazz16.c
@@ -36,7 +36,7 @@ MODULE_LICENSE("GPL");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static unsigned long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
static unsigned long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
@@ -322,7 +322,6 @@ static int __devinit snd_jazz16_probe(struct device *devptr, unsigned int dev)
MPU401_HW_MPU401,
mpu_port[dev], 0,
mpu_irq[dev],
- mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0,
NULL) < 0)
snd_printk(KERN_ERR "no MPU-401 device at 0x%lx\n",
mpu_port[dev]);
diff --git a/sound/isa/sb/sb16.c b/sound/isa/sb/sb16.c
index 4d1c5a300ff8..39b8eca15213 100644
--- a/sound/isa/sb/sb16.c
+++ b/sound/isa/sb/sb16.c
@@ -24,7 +24,7 @@
#include <linux/pnp.h>
#include <linux/err.h>
#include <linux/isa.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/sb16_csp.h>
@@ -68,9 +68,9 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB AWE 32},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP; /* Enable this card */
#ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
#endif
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */
static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x330,0x300 */
@@ -394,8 +394,9 @@ static int __devinit snd_sb16_probe(struct snd_card *card, int dev)
if (chip->mpu_port > 0 && chip->mpu_port != SNDRV_AUTO_PORT) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SB,
- chip->mpu_port, 0,
- xirq, 0, &chip->rmidi)) < 0)
+ chip->mpu_port,
+ MPU401_INFO_IRQ_HOOK, -1,
+ &chip->rmidi)) < 0)
return err;
chip->rmidi_callback = snd_mpu401_uart_interrupt;
}
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index bdc8dde4e4a2..c1aa21edcb65 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/info.h>
diff --git a/sound/isa/sb/sb16_main.c b/sound/isa/sb/sb16_main.c
index 2a6cc1cfe945..0bbcd4714d28 100644
--- a/sound/isa/sb/sb16_main.c
+++ b/sound/isa/sb/sb16_main.c
@@ -37,6 +37,7 @@
#include <asm/dma.h>
#include <linux/init.h>
#include <linux/time.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/sb16_csp.h>
diff --git a/sound/isa/sb/sb8.c b/sound/isa/sb/sb8.c
index 2259e3f726a7..ab5cebea52e1 100644
--- a/sound/isa/sb/sb8.c
+++ b/sound/isa/sb/sb8.c
@@ -23,7 +23,7 @@
#include <linux/err.h>
#include <linux/isa.h>
#include <linux/ioport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/opl3.h>
@@ -36,7 +36,7 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB 1.0/SB 2.0/SB Pro}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260 */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 1,3 */
diff --git a/sound/isa/sb/sb8_main.c b/sound/isa/sb/sb8_main.c
index 7d84c9f34dc9..24d4121ab0e0 100644
--- a/sound/isa/sb/sb8_main.c
+++ b/sound/isa/sb/sb8_main.c
@@ -34,6 +34,7 @@
#include <asm/dma.h>
#include <linux/init.h>
#include <linux/time.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/sb.h>
diff --git a/sound/isa/sb/sb_common.c b/sound/isa/sb/sb_common.c
index eae6c1c0eff9..3ef990602cdd 100644
--- a/sound/isa/sb/sb_common.c
+++ b/sound/isa/sb/sb_common.c
@@ -25,6 +25,7 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/sb.h>
#include <sound/initval.h>
@@ -240,7 +241,7 @@ int snd_sbdsp_create(struct snd_card *card,
if (request_irq(irq, irq_handler,
(hardware == SB_HW_ALS4000 ||
hardware == SB_HW_CS5530) ?
- IRQF_SHARED : IRQF_DISABLED,
+ IRQF_SHARED : 0,
"SoundBlaster", (void *) chip)) {
snd_printk(KERN_ERR "sb: can't grab irq %d\n", irq);
snd_sbdsp_free(chip);
diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c
index 9a8bbf6dd62a..d97d0f381817 100644
--- a/sound/isa/sc6000.c
+++ b/sound/isa/sc6000.c
@@ -48,7 +48,7 @@ MODULE_SUPPORTED_DEVICE("{{Gallant, SC-6000},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220, 0x240 */
static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 11 */
static long mss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x530, 0xe80 */
@@ -658,8 +658,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev)
if (snd_mpu401_uart_new(card, 0,
MPU401_HW_MPU401,
mpu_port[dev], 0,
- mpu_irq[dev], IRQF_DISABLED,
- NULL) < 0)
+ mpu_irq[dev], NULL) < 0)
snd_printk(KERN_ERR "no MPU-401 device at 0x%lx ?\n",
mpu_port[dev]);
}
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index e2d5d2d3ed96..b4a6aa960f4b 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -28,7 +28,7 @@
#include <linux/firmware.h>
#include <linux/pnp.h>
#include <linux/spinlock.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <asm/dma.h>
#include <sound/core.h>
#include <sound/wss.h>
@@ -825,8 +825,7 @@ static int __devinit create_mpu401(struct snd_card *card, int devnum,
int err;
err = snd_mpu401_uart_new(card, devnum, MPU401_HW_MPU401, port,
- MPU401_INFO_INTEGRATED, irq, IRQF_DISABLED,
- &rawmidi);
+ MPU401_INFO_INTEGRATED, irq, &rawmidi);
if (err == 0) {
struct snd_mpu401 *mpu = rawmidi->private_data;
mpu->open_input = mpu401_open;
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 711670e4a425..e0a73271cb91 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -24,7 +24,7 @@
#include <linux/err.h>
#include <linux/isa.h>
#include <linux/pnp.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/opl3.h>
@@ -38,9 +38,9 @@ MODULE_SUPPORTED_DEVICE("{{Turtle Beach,Maui/Tropez/Tropez+}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
#ifdef CONFIG_PNP
-static int isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
#endif
static long cs4232_pcm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static int cs4232_pcm_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,11,12,15 */
@@ -51,7 +51,7 @@ static int ics2115_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 2,9,11,12,15 */
static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* PnP setup */
static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3,5,6,7 */
-static int use_cs4232_midi[SNDRV_CARDS];
+static bool use_cs4232_midi[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for WaveFront soundcard.");
@@ -418,7 +418,7 @@ snd_wavefront_probe (struct snd_card *card, int dev)
return -EBUSY;
}
if (request_irq(ics2115_irq[dev], snd_wavefront_ics2115_interrupt,
- IRQF_DISABLED, "ICS2115", acard)) {
+ 0, "ICS2115", acard)) {
snd_printk(KERN_ERR "unable to use ICS2115 IRQ %d\n", ics2115_irq[dev]);
return -EBUSY;
}
@@ -449,8 +449,7 @@ snd_wavefront_probe (struct snd_card *card, int dev)
if (cs4232_mpu_port[dev] > 0 && cs4232_mpu_port[dev] != SNDRV_AUTO_PORT) {
err = snd_mpu401_uart_new(card, midi_dev, MPU401_HW_CS4232,
cs4232_mpu_port[dev], 0,
- cs4232_mpu_irq[dev], IRQF_DISABLED,
- NULL);
+ cs4232_mpu_irq[dev], NULL);
if (err < 0) {
snd_printk (KERN_ERR "can't allocate CS4232 MPU-401 device\n");
return err;
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index 657e2d6c01ac..e51e0906050b 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -21,6 +21,7 @@
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <sound/core.h>
#include <sound/snd_wavefront.h>
diff --git a/sound/isa/wavefront/wavefront_synth.c b/sound/isa/wavefront/wavefront_synth.c
index 4fb7b19ff393..405f8b6a58b5 100644
--- a/sound/isa/wavefront/wavefront_synth.c
+++ b/sound/isa/wavefront/wavefront_synth.c
@@ -29,6 +29,7 @@
#include <linux/firmware.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/snd_wavefront.h>
#include <sound/initval.h>
diff --git a/sound/isa/wss/wss_lib.c b/sound/isa/wss/wss_lib.c
index 2a42cc377957..49c8a0c2442c 100644
--- a/sound/isa/wss/wss_lib.c
+++ b/sound/isa/wss/wss_lib.c
@@ -30,6 +30,7 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/ioport.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/wss.h>
#include <sound/pcm_params.h>
@@ -1833,7 +1834,7 @@ int snd_wss_create(struct snd_card *card,
}
chip->cport = cport;
if (!(hwshare & WSS_HWSHARE_IRQ))
- if (request_irq(irq, snd_wss_interrupt, IRQF_DISABLED,
+ if (request_irq(irq, snd_wss_interrupt, 0,
"WSS", (void *) chip)) {
snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
snd_wss_free(chip);
diff --git a/sound/mips/Kconfig b/sound/mips/Kconfig
index a9823fad85c2..d2f615ab177a 100644
--- a/sound/mips/Kconfig
+++ b/sound/mips/Kconfig
@@ -23,12 +23,15 @@ config SND_SGI_HAL2
config SND_AU1X00
- tristate "Au1x00 AC97 Port Driver"
- depends on SOC_AU1000 || SOC_AU1100 || SOC_AU1500
+ tristate "Au1x00 AC97 Port Driver (DEPRECATED)"
+ depends on MIPS_ALCHEMY
select SND_PCM
select SND_AC97_CODEC
help
ALSA Sound driver for the Au1x00's AC97 port.
+ Newer drivers for ASoC are available, please do not use
+ this driver as it will be removed in the future.
+
endif # SND_MIPS
diff --git a/sound/mips/au1x00.c b/sound/mips/au1x00.c
index 446cf9748664..3f3ec0bec067 100644
--- a/sound/mips/au1x00.c
+++ b/sound/mips/au1x00.c
@@ -38,6 +38,7 @@
#include <linux/interrupt.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
@@ -465,13 +466,13 @@ snd_au1000_pcm_new(struct snd_au1000 *au1000)
flags = claim_dma_lock();
if ((au1000->stream[PLAYBACK]->dma = request_au1000_dma(DMA_ID_AC97C_TX,
- "AC97 TX", au1000_dma_interrupt, IRQF_DISABLED,
+ "AC97 TX", au1000_dma_interrupt, 0,
au1000->stream[PLAYBACK])) < 0) {
release_dma_lock(flags);
return -EBUSY;
}
if ((au1000->stream[CAPTURE]->dma = request_au1000_dma(DMA_ID_AC97C_RX,
- "AC97 RX", au1000_dma_interrupt, IRQF_DISABLED,
+ "AC97 RX", au1000_dma_interrupt, 0,
au1000->stream[CAPTURE])) < 0){
release_dma_lock(flags);
return -EBUSY;
diff --git a/sound/mips/hal2.c b/sound/mips/hal2.c
index 453d343550a8..5f88d1f09ffe 100644
--- a/sound/mips/hal2.c
+++ b/sound/mips/hal2.c
@@ -26,6 +26,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <asm/sgi/hpc3.h>
#include <asm/sgi/ip22.h>
@@ -934,15 +935,4 @@ static struct platform_driver hal2_driver = {
}
};
-static int __init alsa_card_hal2_init(void)
-{
- return platform_driver_register(&hal2_driver);
-}
-
-static void __exit alsa_card_hal2_exit(void)
-{
- platform_driver_unregister(&hal2_driver);
-}
-
-module_init(alsa_card_hal2_init);
-module_exit(alsa_card_hal2_exit);
+module_platform_driver(hal2_driver);
diff --git a/sound/mips/sgio2audio.c b/sound/mips/sgio2audio.c
index 717604c00f0a..ceaa593ea4ef 100644
--- a/sound/mips/sgio2audio.c
+++ b/sound/mips/sgio2audio.c
@@ -30,6 +30,7 @@
#include <linux/platform_device.h>
#include <linux/io.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <asm/ip32/ip32_ints.h>
#include <asm/ip32/mace.h>
@@ -975,15 +976,4 @@ static struct platform_driver sgio2audio_driver = {
}
};
-static int __init alsa_card_sgio2audio_init(void)
-{
- return platform_driver_register(&sgio2audio_driver);
-}
-
-static void __exit alsa_card_sgio2audio_exit(void)
-{
- platform_driver_unregister(&sgio2audio_driver);
-}
-
-module_init(alsa_card_sgio2audio_init)
-module_exit(alsa_card_sgio2audio_exit)
+module_platform_driver(sgio2audio_driver);
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig
index 6c93e051f9ae..5849b129e50d 100644
--- a/sound/oss/Kconfig
+++ b/sound/oss/Kconfig
@@ -432,9 +432,7 @@ config SOUND_SB
ALS-007 and ALS-1X0 chips (read <file:Documentation/sound/oss/ALS>) and
for cards based on ESS chips (read
<file:Documentation/sound/oss/ESS1868> and
- <file:Documentation/sound/oss/ESS>). If you have an SB AWE 32 or SB AWE
- 64, say Y here and also to "AWE32 synth" below and read
- <file:Documentation/sound/oss/INSTALL.awe>. If you have an IBM Mwave
+ <file:Documentation/sound/oss/ESS>). If you have an IBM Mwave
card, say Y here and read <file:Documentation/sound/oss/mwave>.
If you compile the driver into the kernel and don't want to use
@@ -523,7 +521,7 @@ config SC6600_CDROMBASE
config SOUND_VIDC
tristate "VIDC 16-bit sound"
- depends on ARM && (ARCH_ACORN || ARCH_CLPS7500)
+ depends on ARM && ARCH_ACORN
help
16-bit support for the VIDC onboard sound hardware found on Acorn
machines.
diff --git a/sound/oss/ad1848.c b/sound/oss/ad1848.c
index 8a197fd3c57e..98d23bdcaf21 100644
--- a/sound/oss/ad1848.c
+++ b/sound/oss/ad1848.c
@@ -119,9 +119,9 @@ ad1848_port_info;
static struct address_info cfg;
static int nr_ad1848_devs;
-static int deskpro_xl;
-static int deskpro_m;
-static int soundpro;
+static bool deskpro_xl;
+static bool deskpro_m;
+static bool soundpro;
static volatile signed char irq2dev[17] = {
-1, -1, -1, -1, -1, -1, -1, -1,
@@ -177,7 +177,7 @@ static struct {
#ifdef CONFIG_PNP
static int isapnp = 1;
static int isapnpjump;
-static int reverse;
+static bool reverse;
static int audio_activated;
#else
diff --git a/sound/oss/msnd_pinnacle.c b/sound/oss/msnd_pinnacle.c
index 7b5c77b32a90..eba734560f6f 100644
--- a/sound/oss/msnd_pinnacle.c
+++ b/sound/oss/msnd_pinnacle.c
@@ -1701,7 +1701,7 @@ static int joystick_io __initdata = CONFIG_MSNDPIN_JOYSTICK_IO;
#ifndef CONFIG_MSNDPIN_DIGITAL
# define CONFIG_MSNDPIN_DIGITAL 0
#endif
-static int digital __initdata = CONFIG_MSNDPIN_DIGITAL;
+static bool digital __initdata = CONFIG_MSNDPIN_DIGITAL;
#endif /* MSND_CLASSIC */
diff --git a/sound/oss/pas2_card.c b/sound/oss/pas2_card.c
index 7f377ec3486d..dabf8a871dcc 100644
--- a/sound/oss/pas2_card.c
+++ b/sound/oss/pas2_card.c
@@ -41,19 +41,19 @@ static int pas_irq;
static int pas_sb_base;
DEFINE_SPINLOCK(pas_lock);
#ifndef CONFIG_PAS_JOYSTICK
-static int joystick;
+static bool joystick;
#else
-static int joystick = 1;
+static bool joystick = 1;
#endif
#ifdef SYMPHONY_PAS
-static int symphony = 1;
+static bool symphony = 1;
#else
-static int symphony;
+static bool symphony;
#endif
#ifdef BROKEN_BUS_CLOCK
-static int broken_bus_clock = 1;
+static bool broken_bus_clock = 1;
#else
-static int broken_bus_clock;
+static bool broken_bus_clock;
#endif
static struct address_info cfg;
diff --git a/sound/oss/pss.c b/sound/oss/pss.c
index 2fc0624024b5..0f32a561f15f 100644
--- a/sound/oss/pss.c
+++ b/sound/oss/pss.c
@@ -117,9 +117,9 @@
/* If compiled into kernel, it enable or disable pss mixer */
#ifdef CONFIG_PSS_MIXER
-static int pss_mixer = 1;
+static bool pss_mixer = 1;
#else
-static int pss_mixer;
+static bool pss_mixer;
#endif
@@ -147,7 +147,7 @@ static DEFINE_SPINLOCK(lock);
static int pss_initialized;
static int nonstandard_microcode;
static int pss_cdrom_port = -1; /* Parameter for the PSS cdrom port */
-static int pss_enable_joystick; /* Parameter for enabling the joystick */
+static bool pss_enable_joystick; /* Parameter for enabling the joystick */
static coproc_operations pss_coproc_operations;
static void pss_write(pss_confdata *devc, int data)
@@ -1133,8 +1133,8 @@ static int mss_irq __initdata = -1;
static int mss_dma __initdata = -1;
static int mpu_io __initdata = -1;
static int mpu_irq __initdata = -1;
-static int pss_no_sound = 0; /* Just configure non-sound components */
-static int pss_keep_settings = 1; /* Keep hardware settings at module exit */
+static bool pss_no_sound = 0; /* Just configure non-sound components */
+static bool pss_keep_settings = 1; /* Keep hardware settings at module exit */
static char *pss_firmware = "/etc/sound/pss_synth";
module_param(pss_io, int, 0);
diff --git a/sound/oss/sound_timer.c b/sound/oss/sound_timer.c
index 48cda6c4c257..8021c85f076d 100644
--- a/sound/oss/sound_timer.c
+++ b/sound/oss/sound_timer.c
@@ -320,7 +320,7 @@ void sound_timer_init(struct sound_lowlev_timer *t, char *name)
n = sound_alloc_timerdev();
if (n == -1)
n = 0; /* Overwrite the system timer */
- strcpy(sound_timer.info.name, name);
+ strlcpy(sound_timer.info.name, name, sizeof(sound_timer.info.name));
sound_timer_devs[n] = &sound_timer;
}
EXPORT_SYMBOL(sound_timer_init);
diff --git a/sound/oss/trix.c b/sound/oss/trix.c
index e04169e8e3f8..944e0c015485 100644
--- a/sound/oss/trix.c
+++ b/sound/oss/trix.c
@@ -31,7 +31,7 @@
static int mpu;
-static int joystick;
+static bool joystick;
static unsigned char trix_read(int addr)
{
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index 7f4d619f4ddb..9473fca9681d 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -26,7 +26,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -42,7 +42,7 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Universal interface for Audio Codec '97");
MODULE_LICENSE("GPL");
-static int enable_loopback;
+static bool enable_loopback;
module_param(enable_loopback, bool, 0444);
MODULE_PARM_DESC(enable_loopback, "Enable AC97 ADC/DAC Loopback Control");
diff --git a/sound/pci/ac97/ac97_pcm.c b/sound/pci/ac97/ac97_pcm.c
index 48cbda9378c5..f1488fc176d5 100644
--- a/sound/pci/ac97/ac97_pcm.c
+++ b/sound/pci/ac97/ac97_pcm.c
@@ -27,6 +27,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mutex.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/pcm.h>
diff --git a/sound/pci/ad1889.c b/sound/pci/ad1889.c
index 201503673f25..9d91d61902b4 100644
--- a/sound/pci/ad1889.c
+++ b/sound/pci/ad1889.c
@@ -39,6 +39,7 @@
#include <linux/interrupt.h>
#include <linux/compiler.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -65,7 +66,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for the AD1889 soundcard.");
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable AD1889 soundcard.");
diff --git a/sound/pci/ak4531_codec.c b/sound/pci/ak4531_codec.c
index fd135e3d8a84..cadf7b962e30 100644
--- a/sound/pci/ak4531_codec.c
+++ b/sound/pci/ak4531_codec.c
@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/slab.h>
#include <linux/mutex.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/ak4531_codec.h>
diff --git a/sound/pci/ali5451/ali5451.c b/sound/pci/ali5451/ali5451.c
index b444b74d9dcf..bdd6164e9c7e 100644
--- a/sound/pci/ali5451/ali5451.c
+++ b/sound/pci/ali5451/ali5451.c
@@ -31,7 +31,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -48,7 +48,7 @@ MODULE_SUPPORTED_DEVICE("{{ALI,M5451,pci},{ALI,M5451}}");
static int index = SNDRV_DEFAULT_IDX1; /* Index */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
static int pcm_channels = 32;
-static int spdif;
+static bool spdif;
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for ALI M5451 PCI Audio.");
@@ -60,7 +60,7 @@ module_param(spdif, bool, 0444);
MODULE_PARM_DESC(spdif, "Support SPDIF I/O");
/* just for backward compatibility */
-static int enable;
+static bool enable;
module_param(enable, bool, 0444);
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 736c8e93db1f..8196e229b2df 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -32,7 +32,7 @@
#include <linux/delay.h>
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/interrupt.h>
@@ -115,7 +115,14 @@ MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS300},{Avance Logic,ALS300+}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for ALS300 sound card.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for ALS300 sound card.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable ALS300 sound card.");
struct snd_als300 {
unsigned long port;
diff --git a/sound/pci/als4000.c b/sound/pci/als4000.c
index a9c1af33f276..3269b8011ea9 100644
--- a/sound/pci/als4000.c
+++ b/sound/pci/als4000.c
@@ -69,7 +69,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/gameport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -90,7 +90,7 @@ MODULE_SUPPORTED_DEVICE("{{Avance Logic,ALS4000}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
#ifdef SUPPORT_JOYSTICK
static int joystick_port[SNDRV_CARDS];
#endif
@@ -931,8 +931,9 @@ static int __devinit snd_card_als4000_probe(struct pci_dev *pci,
if ((err = snd_mpu401_uart_new( card, 0, MPU401_HW_ALS4000,
iobase + ALS4K_IOB_30_MIDI_DATA,
- MPU401_INFO_INTEGRATED,
- pci->irq, 0, &chip->rmidi)) < 0) {
+ MPU401_INFO_INTEGRATED |
+ MPU401_INFO_IRQ_HOOK,
+ -1, &chip->rmidi)) < 0) {
printk(KERN_ERR "als4000: no MPU-401 device at 0x%lx?\n",
iobase + ALS4K_IOB_30_MIDI_DATA);
goto out_err;
diff --git a/sound/pci/asihpi/asihpi.c b/sound/pci/asihpi/asihpi.c
index eae62ebbd295..e8de831f98bc 100644
--- a/sound/pci/asihpi/asihpi.c
+++ b/sound/pci/asihpi/asihpi.c
@@ -23,8 +23,11 @@
*/
#include "hpi_internal.h"
+#include "hpi_version.h"
#include "hpimsginit.h"
#include "hpioctl.h"
+#include "hpicmn.h"
+
#include <linux/pci.h>
#include <linux/init.h>
@@ -32,6 +35,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -43,7 +47,8 @@
MODULE_LICENSE("GPL");
MODULE_AUTHOR("AudioScience inc. <support@audioscience.com>");
-MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
+MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx "
+ HPI_VER_STRING);
#if defined CONFIG_SND_DEBUG_VERBOSE
/**
@@ -62,8 +67,8 @@ MODULE_DESCRIPTION("AudioScience ALSA ASI5000 ASI6000 ASI87xx ASI89xx");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
-static int enable_hpi_hwdep = 1;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable_hpi_hwdep = 1;
module_param_array(index, int, NULL, S_IRUGO);
MODULE_PARM_DESC(index, "ALSA index value for AudioScience soundcard.");
@@ -118,12 +123,7 @@ struct clk_cache {
struct snd_card_asihpi {
struct snd_card *card;
struct pci_dev *pci;
- u16 adapter_index;
- u32 serial_number;
- u16 type;
- u16 version;
- u16 num_outstreams;
- u16 num_instreams;
+ struct hpi_adapter *hpi;
u32 h_mixer;
struct clk_cache cc;
@@ -134,6 +134,8 @@ struct snd_card_asihpi {
u16 update_interval_frames;
u16 in_max_chans;
u16 out_max_chans;
+ u16 in_min_chans;
+ u16 out_min_chans;
};
/* Per stream data */
@@ -494,6 +496,7 @@ static int snd_card_asihpi_pcm_hw_params(struct snd_pcm_substream *substream,
snd_printdd("stream_host_buffer_attach status 0x%x\n",
dpcm->hpi_buffer_attached);
+
}
bytes_per_sec = params_rate(params) * params_channels(params);
width = snd_pcm_format_width(params_format(params));
@@ -756,8 +759,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
if (s->stream == SNDRV_PCM_STREAM_PLAYBACK) {
pcm_buf_dma_ofs = ds->pcm_buf_host_rw_ofs - bytes_avail;
if (state == HPI_STATE_STOPPED) {
- if ((bytes_avail == 0) &&
- (on_card_bytes < ds->pcm_buf_host_rw_ofs)) {
+ if (bytes_avail == 0) {
hpi_handle_error(hpi_stream_start(ds->h_stream));
snd_printdd("P%d start\n", s->number);
ds->drained_count = 0;
@@ -766,7 +768,7 @@ static void snd_card_asihpi_timer_function(unsigned long data)
snd_printd(KERN_WARNING "P%d drained\n",
s->number);
ds->drained_count++;
- if (ds->drained_count > 2) {
+ if (ds->drained_count > 20) {
snd_pcm_stop(s, SNDRV_PCM_STATE_XRUN);
continue;
}
@@ -887,8 +889,8 @@ static void snd_card_asihpi_timer_function(unsigned long data)
pd, xfer2));
}
}
- ds->pcm_buf_host_rw_ofs = ds->pcm_buf_host_rw_ofs + xfercount;
- ds->pcm_buf_elapsed_dma_ofs = pcm_buf_dma_ofs;
+ ds->pcm_buf_host_rw_ofs += xfercount;
+ ds->pcm_buf_elapsed_dma_ofs += xfercount;
snd_pcm_period_elapsed(s);
}
}
@@ -901,7 +903,9 @@ static void snd_card_asihpi_timer_function(unsigned long data)
static int snd_card_asihpi_playback_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
- snd_printddd(KERN_INFO "P%d ioctl %d\n", substream->number, cmd);
+ char name[16];
+ snd_pcm_debug_name(substream, name, sizeof(name));
+ snd_printddd(KERN_INFO "%s ioctl %d\n", name, cmd);
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
@@ -926,21 +930,23 @@ snd_card_asihpi_playback_pointer(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_card_asihpi_pcm *dpcm = runtime->private_data;
snd_pcm_uframes_t ptr;
+ char name[16];
+ snd_pcm_debug_name(substream, name, sizeof(name));
ptr = bytes_to_frames(runtime, dpcm->pcm_buf_dma_ofs % dpcm->buffer_bytes);
- snd_printddd("P%d pointer = 0x%04lx\n", substream->number, (unsigned long)ptr);
+ snd_printddd("%s pointer = 0x%04lx\n", name, (unsigned long)ptr);
return ptr;
}
-static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi,
- u32 h_stream,
- struct snd_pcm_hardware *pcmhw)
+static u64 snd_card_asihpi_playback_formats(struct snd_card_asihpi *asihpi,
+ u32 h_stream)
{
struct hpi_format hpi_format;
u16 format;
u16 err;
u32 h_control;
u32 sample_rate = 48000;
+ u64 formats = 0;
/* on cards without SRC, must query at valid rate,
* maybe set by external sync
@@ -955,41 +961,29 @@ static void snd_card_asihpi_playback_format(struct snd_card_asihpi *asihpi,
for (format = HPI_FORMAT_PCM8_UNSIGNED;
format <= HPI_FORMAT_PCM24_SIGNED; format++) {
- err = hpi_format_create(&hpi_format,
- 2, format, sample_rate, 128000, 0);
+ err = hpi_format_create(&hpi_format, asihpi->out_max_chans,
+ format, sample_rate, 128000, 0);
if (!err)
- err = hpi_outstream_query_format(h_stream,
- &hpi_format);
+ err = hpi_outstream_query_format(h_stream, &hpi_format);
if (!err && (hpi_to_alsa_formats[format] != -1))
- pcmhw->formats |=
- (1ULL << hpi_to_alsa_formats[format]);
+ formats |= (1ULL << hpi_to_alsa_formats[format]);
}
+ return formats;
}
-static struct snd_pcm_hardware snd_card_asihpi_playback = {
- .channels_min = 1,
- .channels_max = 2,
- .buffer_bytes_max = BUFFER_BYTES_MAX,
- .period_bytes_min = PERIOD_BYTES_MIN,
- .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
- .periods_min = PERIODS_MIN,
- .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
- .fifo_size = 0,
-};
-
static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_card_asihpi_pcm *dpcm;
struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
+ struct snd_pcm_hardware snd_card_asihpi_playback;
int err;
dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
if (dpcm == NULL)
return -ENOMEM;
- err =
- hpi_outstream_open(card->adapter_index,
+ err = hpi_outstream_open(card->hpi->adapter->index,
substream->number, &dpcm->h_stream);
hpi_handle_error(err);
if (err)
@@ -1011,12 +1005,19 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
runtime->private_data = dpcm;
runtime->private_free = snd_card_asihpi_runtime_free;
- snd_card_asihpi_playback.channels_max = card->out_max_chans;
+ memset(&snd_card_asihpi_playback, 0, sizeof(snd_card_asihpi_playback));
+ snd_card_asihpi_playback.buffer_bytes_max = BUFFER_BYTES_MAX;
+ snd_card_asihpi_playback.period_bytes_min = PERIOD_BYTES_MIN;
/*?snd_card_asihpi_playback.period_bytes_min =
card->out_max_chans * 4096; */
-
- snd_card_asihpi_playback_format(card, dpcm->h_stream,
- &snd_card_asihpi_playback);
+ snd_card_asihpi_playback.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN;
+ snd_card_asihpi_playback.periods_min = PERIODS_MIN;
+ snd_card_asihpi_playback.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN;
+ /* snd_card_asihpi_playback.fifo_size = 0; */
+ snd_card_asihpi_playback.channels_max = card->out_max_chans;
+ snd_card_asihpi_playback.channels_min = card->out_min_chans;
+ snd_card_asihpi_playback.formats =
+ snd_card_asihpi_playback_formats(card, dpcm->h_stream);
snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_playback);
@@ -1028,8 +1029,10 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID;
- if (card->support_grouping)
+ if (card->support_grouping) {
snd_card_asihpi_playback.info |= SNDRV_PCM_INFO_SYNC_START;
+ snd_pcm_set_sync(substream);
+ }
/* struct is copied, so can create initializer dynamically */
runtime->hw = snd_card_asihpi_playback;
@@ -1046,8 +1049,6 @@ static int snd_card_asihpi_playback_open(struct snd_pcm_substream *substream)
snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
card->update_interval_frames * 2, UINT_MAX);
- snd_pcm_set_sync(substream);
-
snd_printdd("playback open\n");
return 0;
@@ -1113,15 +1114,15 @@ static int snd_card_asihpi_capture_prepare(struct snd_pcm_substream *substream)
-static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi,
- u32 h_stream,
- struct snd_pcm_hardware *pcmhw)
+static u64 snd_card_asihpi_capture_formats(struct snd_card_asihpi *asihpi,
+ u32 h_stream)
{
struct hpi_format hpi_format;
u16 format;
u16 err;
u32 h_control;
u32 sample_rate = 48000;
+ u64 formats = 0;
/* on cards without SRC, must query at valid rate,
maybe set by external sync */
@@ -1136,34 +1137,22 @@ static void snd_card_asihpi_capture_format(struct snd_card_asihpi *asihpi,
for (format = HPI_FORMAT_PCM8_UNSIGNED;
format <= HPI_FORMAT_PCM24_SIGNED; format++) {
- err = hpi_format_create(&hpi_format, 2, format,
- sample_rate, 128000, 0);
+ err = hpi_format_create(&hpi_format, asihpi->in_max_chans,
+ format, sample_rate, 128000, 0);
if (!err)
- err = hpi_instream_query_format(h_stream,
- &hpi_format);
+ err = hpi_instream_query_format(h_stream, &hpi_format);
if (!err)
- pcmhw->formats |=
- (1ULL << hpi_to_alsa_formats[format]);
+ formats |= (1ULL << hpi_to_alsa_formats[format]);
}
+ return formats;
}
-
-static struct snd_pcm_hardware snd_card_asihpi_capture = {
- .channels_min = 1,
- .channels_max = 2,
- .buffer_bytes_max = BUFFER_BYTES_MAX,
- .period_bytes_min = PERIOD_BYTES_MIN,
- .period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN,
- .periods_min = PERIODS_MIN,
- .periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN,
- .fifo_size = 0,
-};
-
static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_card_asihpi *card = snd_pcm_substream_chip(substream);
struct snd_card_asihpi_pcm *dpcm;
+ struct snd_pcm_hardware snd_card_asihpi_capture;
int err;
dpcm = kzalloc(sizeof(*dpcm), GFP_KERNEL);
@@ -1171,10 +1160,10 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
return -ENOMEM;
snd_printdd("capture open adapter %d stream %d\n",
- card->adapter_index, substream->number);
+ card->hpi->adapter->index, substream->number);
err = hpi_handle_error(
- hpi_instream_open(card->adapter_index,
+ hpi_instream_open(card->hpi->adapter->index,
substream->number, &dpcm->h_stream));
if (err)
kfree(dpcm);
@@ -1183,7 +1172,6 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
if (err)
return -EIO;
-
init_timer(&dpcm->timer);
dpcm->timer.data = (unsigned long) dpcm;
dpcm->timer.function = snd_card_asihpi_timer_function;
@@ -1191,9 +1179,17 @@ static int snd_card_asihpi_capture_open(struct snd_pcm_substream *substream)
runtime->private_data = dpcm;
runtime->private_free = snd_card_asihpi_runtime_free;
+ memset(&snd_card_asihpi_capture, 0, sizeof(snd_card_asihpi_capture));
+ snd_card_asihpi_capture.buffer_bytes_max = BUFFER_BYTES_MAX;
+ snd_card_asihpi_capture.period_bytes_min = PERIOD_BYTES_MIN;
+ snd_card_asihpi_capture.period_bytes_max = BUFFER_BYTES_MAX / PERIODS_MIN;
+ snd_card_asihpi_capture.periods_min = PERIODS_MIN;
+ snd_card_asihpi_capture.periods_max = BUFFER_BYTES_MAX / PERIOD_BYTES_MIN;
+ /* snd_card_asihpi_capture.fifo_size = 0; */
snd_card_asihpi_capture.channels_max = card->in_max_chans;
- snd_card_asihpi_capture_format(card, dpcm->h_stream,
- &snd_card_asihpi_capture);
+ snd_card_asihpi_capture.channels_min = card->in_min_chans;
+ snd_card_asihpi_capture.formats =
+ snd_card_asihpi_capture_formats(card, dpcm->h_stream);
snd_card_asihpi_pcm_samplerates(card, &snd_card_asihpi_capture);
snd_card_asihpi_capture.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_MMAP |
@@ -1239,15 +1235,20 @@ static struct snd_pcm_ops snd_card_asihpi_capture_mmap_ops = {
.pointer = snd_card_asihpi_capture_pointer,
};
-static int __devinit snd_card_asihpi_pcm_new(struct snd_card_asihpi *asihpi,
- int device, int substreams)
+static int __devinit snd_card_asihpi_pcm_new(
+ struct snd_card_asihpi *asihpi, int device)
{
struct snd_pcm *pcm;
int err;
+ u16 num_instreams, num_outstreams, x16;
+ u32 x32;
+
+ err = hpi_adapter_get_info(asihpi->hpi->adapter->index,
+ &num_outstreams, &num_instreams,
+ &x16, &x32, &x16);
err = snd_pcm_new(asihpi->card, "Asihpi PCM", device,
- asihpi->num_outstreams, asihpi->num_instreams,
- &pcm);
+ num_outstreams, num_instreams, &pcm);
if (err < 0)
return err;
/* pointer to ops struct is stored, dont change ops afterwards! */
@@ -1313,7 +1314,7 @@ static const char * const asihpi_src_names[] = {
"Analog",
"Adapter",
"RTP",
- "GPI",
+ "Internal"
};
compile_time_assert(
@@ -1331,7 +1332,6 @@ static const char * const asihpi_dst_names[] = {
"Net",
"Analog",
"RTP",
- "GPO",
};
compile_time_assert(
@@ -1409,6 +1409,7 @@ static int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
u32 h_control = kcontrol->private_value;
+ u32 count;
u16 err;
/* native gains are in millibels */
short min_gain_mB;
@@ -1423,8 +1424,12 @@ static int snd_asihpi_volume_info(struct snd_kcontrol *kcontrol,
step_gain_mB = VOL_STEP_mB;
}
+ err = hpi_meter_query_channels(h_control, &count);
+ if (err)
+ count = HPI_MAX_CHANNELS;
+
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 2;
+ uinfo->count = count;
uinfo->value.integer.min = min_gain_mB / VOL_STEP_mB;
uinfo->value.integer.max = max_gain_mB / VOL_STEP_mB;
uinfo->value.integer.step = step_gain_mB / VOL_STEP_mB;
@@ -2032,8 +2037,15 @@ static int __devinit snd_asihpi_tuner_add(struct snd_card_asihpi *asihpi,
static int snd_asihpi_meter_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
+ u32 h_control = kcontrol->private_value;
+ u32 count;
+ u16 err;
+ err = hpi_meter_query_channels(h_control, &count);
+ if (err)
+ count = HPI_MAX_CHANNELS;
+
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = HPI_MAX_CHANNELS;
+ uinfo->count = count;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 0x7FFFFFFF;
return 0;
@@ -2247,6 +2259,9 @@ static int snd_asihpi_cmode_info(struct snd_kcontrol *kcontrol,
valid_modes++;
}
+ if (!valid_modes)
+ return -EINVAL;
+
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = valid_modes;
@@ -2546,7 +2561,7 @@ static int __devinit snd_card_asihpi_mixer_new(struct snd_card_asihpi *asihpi)
strcpy(card->mixername, "Asihpi Mixer");
err =
- hpi_mixer_open(asihpi->adapter_index,
+ hpi_mixer_open(asihpi->hpi->adapter->index,
&asihpi->h_mixer);
hpi_handle_error(err);
if (err)
@@ -2664,24 +2679,33 @@ snd_asihpi_proc_read(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct snd_card_asihpi *asihpi = entry->private_data;
- u16 version;
u32 h_control;
u32 rate = 0;
u16 source = 0;
+
+ u16 num_outstreams;
+ u16 num_instreams;
+ u16 version;
+ u32 serial_number;
+ u16 type;
+
int err;
snd_iprintf(buffer, "ASIHPI driver proc file\n");
+
+ hpi_handle_error(hpi_adapter_get_info(asihpi->hpi->adapter->index,
+ &num_outstreams, &num_instreams,
+ &version, &serial_number, &type));
+
snd_iprintf(buffer,
- "adapter ID=%4X\n_index=%d\n"
- "num_outstreams=%d\n_num_instreams=%d\n",
- asihpi->type, asihpi->adapter_index,
- asihpi->num_outstreams, asihpi->num_instreams);
+ "Adapter type ASI%4X\nHardware Index %d\n"
+ "%d outstreams\n%d instreams\n",
+ type, asihpi->hpi->adapter->index,
+ num_outstreams, num_instreams);
- version = asihpi->version;
snd_iprintf(buffer,
- "serial#=%d\n_hw version %c%d\nDSP code version %03d\n",
- asihpi->serial_number, ((version >> 3) & 0xf) + 'A',
- version & 0x7,
+ "Serial#%d\nHardware version %c%d\nDSP code version %03d\n",
+ serial_number, ((version >> 3) & 0xf) + 'A', version & 0x7,
((version >> 13) * 100) + ((version >> 7) & 0x3f));
err = hpi_mixer_get_control(asihpi->h_mixer,
@@ -2689,18 +2713,15 @@ snd_asihpi_proc_read(struct snd_info_entry *entry,
HPI_CONTROL_SAMPLECLOCK, &h_control);
if (!err) {
- err = hpi_sample_clock_get_sample_rate(
- h_control, &rate);
+ err = hpi_sample_clock_get_sample_rate(h_control, &rate);
err += hpi_sample_clock_get_source(h_control, &source);
if (!err)
- snd_iprintf(buffer, "sample_clock=%d_hz, source %s\n",
+ snd_iprintf(buffer, "Sample Clock %dHz, source %s\n",
rate, sampleclock_sources[source]);
}
-
}
-
static void __devinit snd_asihpi_proc_init(struct snd_card_asihpi *asihpi)
{
struct snd_info_entry *entry;
@@ -2772,35 +2793,34 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
int err;
-
- u16 version;
- int pcm_substreams;
-
- struct hpi_adapter *hpi_card;
+ struct hpi_adapter *hpi;
struct snd_card *card;
struct snd_card_asihpi *asihpi;
u32 h_control;
u32 h_stream;
+ u32 adapter_index;
static int dev;
if (dev >= SNDRV_CARDS)
return -ENODEV;
- /* Should this be enable[hpi_card->index] ? */
+ /* Should this be enable[hpi->index] ? */
if (!enable[dev]) {
dev++;
return -ENOENT;
}
+ /* Initialise low-level HPI driver */
err = asihpi_adapter_probe(pci_dev, pci_id);
if (err < 0)
return err;
- hpi_card = pci_get_drvdata(pci_dev);
+ hpi = pci_get_drvdata(pci_dev);
+ adapter_index = hpi->adapter->index;
/* first try to give the card the same index as its hardware index */
- err = snd_card_create(hpi_card->index,
- id[hpi_card->index], THIS_MODULE,
+ err = snd_card_create(adapter_index,
+ id[adapter_index], THIS_MODULE,
sizeof(struct snd_card_asihpi),
&card);
if (err < 0) {
@@ -2814,50 +2834,32 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
return err;
snd_printk(KERN_WARNING
"**** WARNING **** Adapter index %d->ALSA index %d\n",
- hpi_card->index, card->number);
+ adapter_index, card->number);
}
snd_card_set_dev(card, &pci_dev->dev);
- asihpi = (struct snd_card_asihpi *) card->private_data;
+ asihpi = card->private_data;
asihpi->card = card;
asihpi->pci = pci_dev;
- asihpi->adapter_index = hpi_card->index;
- hpi_handle_error(hpi_adapter_get_info(
- asihpi->adapter_index,
- &asihpi->num_outstreams,
- &asihpi->num_instreams,
- &asihpi->version,
- &asihpi->serial_number, &asihpi->type));
-
- version = asihpi->version;
- snd_printk(KERN_INFO "adapter ID=%4X index=%d num_outstreams=%d "
- "num_instreams=%d S/N=%d\n"
- "Hw Version %c%d DSP code version %03d\n",
- asihpi->type, asihpi->adapter_index,
- asihpi->num_outstreams,
- asihpi->num_instreams, asihpi->serial_number,
- ((version >> 3) & 0xf) + 'A',
- version & 0x7,
- ((version >> 13) * 100) + ((version >> 7) & 0x3f));
-
- pcm_substreams = asihpi->num_outstreams;
- if (pcm_substreams < asihpi->num_instreams)
- pcm_substreams = asihpi->num_instreams;
-
- err = hpi_adapter_get_property(asihpi->adapter_index,
+ asihpi->hpi = hpi;
+
+ snd_printk(KERN_INFO "adapter ID=%4X index=%d\n",
+ asihpi->hpi->adapter->type, adapter_index);
+
+ err = hpi_adapter_get_property(adapter_index,
HPI_ADAPTER_PROPERTY_CAPS1,
NULL, &asihpi->support_grouping);
if (err)
asihpi->support_grouping = 0;
- err = hpi_adapter_get_property(asihpi->adapter_index,
+ err = hpi_adapter_get_property(adapter_index,
HPI_ADAPTER_PROPERTY_CAPS2,
&asihpi->support_mrx, NULL);
if (err)
asihpi->support_mrx = 0;
- err = hpi_adapter_get_property(asihpi->adapter_index,
+ err = hpi_adapter_get_property(adapter_index,
HPI_ADAPTER_PROPERTY_INTERVAL,
NULL, &asihpi->update_interval_frames);
if (err)
@@ -2866,7 +2868,7 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
if (!asihpi->can_dma)
asihpi->update_interval_frames *= 2;
- hpi_handle_error(hpi_instream_open(asihpi->adapter_index,
+ hpi_handle_error(hpi_instream_open(adapter_index,
0, &h_stream));
err = hpi_instream_host_buffer_free(h_stream);
@@ -2874,7 +2876,7 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
hpi_handle_error(hpi_instream_close(h_stream));
- err = hpi_adapter_get_property(asihpi->adapter_index,
+ err = hpi_adapter_get_property(adapter_index,
HPI_ADAPTER_PROPERTY_CURCHANNELS,
&asihpi->in_max_chans, &asihpi->out_max_chans);
if (err) {
@@ -2882,13 +2884,22 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
asihpi->out_max_chans = 2;
}
- snd_printk(KERN_INFO "has dma:%d, grouping:%d, mrx:%d\n",
+ if (asihpi->out_max_chans > 2) { /* assume LL mode */
+ asihpi->out_min_chans = asihpi->out_max_chans;
+ asihpi->in_min_chans = asihpi->in_max_chans;
+ asihpi->support_grouping = 0;
+ } else {
+ asihpi->out_min_chans = 1;
+ asihpi->in_min_chans = 1;
+ }
+
+ snd_printk(KERN_INFO "Has dma:%d, grouping:%d, mrx:%d\n",
asihpi->can_dma,
asihpi->support_grouping,
asihpi->support_mrx
);
- err = snd_card_asihpi_pcm_new(asihpi, 0, pcm_substreams);
+ err = snd_card_asihpi_pcm_new(asihpi, 0);
if (err < 0) {
snd_printk(KERN_ERR "pcm_new failed\n");
goto __nodev;
@@ -2915,13 +2926,14 @@ static int __devinit snd_asihpi_probe(struct pci_dev *pci_dev,
strcpy(card->driver, "ASIHPI");
- sprintf(card->shortname, "AudioScience ASI%4X", asihpi->type);
+ sprintf(card->shortname, "AudioScience ASI%4X",
+ asihpi->hpi->adapter->type);
sprintf(card->longname, "%s %i",
- card->shortname, asihpi->adapter_index);
+ card->shortname, adapter_index);
err = snd_card_register(card);
if (!err) {
- hpi_card->snd_card_asihpi = card;
+ hpi->snd_card = card;
dev++;
return 0;
}
@@ -2934,10 +2946,9 @@ __nodev:
static void __devexit snd_asihpi_remove(struct pci_dev *pci_dev)
{
- struct hpi_adapter *hpi_card = pci_get_drvdata(pci_dev);
-
- snd_card_free(hpi_card->snd_card_asihpi);
- hpi_card->snd_card_asihpi = NULL;
+ struct hpi_adapter *hpi = pci_get_drvdata(pci_dev);
+ snd_card_free(hpi->snd_card);
+ hpi->snd_card = NULL;
asihpi_adapter_remove(pci_dev);
}
diff --git a/sound/pci/asihpi/hpi.h b/sound/pci/asihpi/hpi.h
index f20727288994..20887241a3ae 100644
--- a/sound/pci/asihpi/hpi.h
+++ b/sound/pci/asihpi/hpi.h
@@ -30,26 +30,8 @@
#ifndef _HPI_H_
#define _HPI_H_
-/* HPI Version
-If HPI_VER_MINOR is odd then its a development release not intended for the
-public. If HPI_VER_MINOR is even then is a release version
-i.e 3.05.02 is a development version
-*/
-#define HPI_VERSION_CONSTRUCTOR(maj, min, rel) \
- ((maj << 16) + (min << 8) + rel)
-
-#define HPI_VER_MAJOR(v) ((int)(v >> 16))
-#define HPI_VER_MINOR(v) ((int)((v >> 8) & 0xFF))
-#define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
-
-#define HPI_VER HPI_VERSION_CONSTRUCTOR(4L, 8, 0)
-#define HPI_VER_STRING "4.08.00"
-
-/* Library version as documented in hpi-api-versions.txt */
-#define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(10, 0, 0)
#include <linux/types.h>
-#define HPI_BUILD_EXCLUDE_DEPRECATED
#define HPI_BUILD_KERNEL_MODE
/******************************************************************************/
@@ -213,7 +195,7 @@ enum HPI_SOURCENODES {
/** RTP stream input node - This node is a destination for
packets of RTP audio samples from other devices. */
HPI_SOURCENODE_RTP_DESTINATION = 112,
- HPI_SOURCENODE_GP_IN = 113, /**< general purpose input. */
+ HPI_SOURCENODE_INTERNAL = 113, /**< node internal to the device. */
/* !!!Update this AND hpidebug.h if you add a new sourcenode type!!! */
HPI_SOURCENODE_LAST_INDEX = 113 /**< largest ID */
/* AX6 max sourcenode types = 15 */
@@ -242,9 +224,8 @@ enum HPI_DESTNODES {
/** RTP stream output node - This node is a source for
packets of RTP audio samples that are sent to other devices. */
HPI_DESTNODE_RTP_SOURCE = 208,
- HPI_DESTNODE_GP_OUT = 209, /**< general purpose output node. */
/* !!!Update this AND hpidebug.h if you add a new destnode type!!! */
- HPI_DESTNODE_LAST_INDEX = 209 /**< largest ID */
+ HPI_DESTNODE_LAST_INDEX = 208 /**< largest ID */
/* AX6 max destnode types = 15 */
};
@@ -450,7 +431,19 @@ Indicates that the adapter in it's current mode supports interrupts
across the host bus. Note, this does not imply that interrupts are
enabled. Instead it indicates that they can be enabled.
*/
- HPI_ADAPTER_PROPERTY_SUPPORTS_IRQ = 272
+ HPI_ADAPTER_PROPERTY_SUPPORTS_IRQ = 272,
+/** Readonly supports firmware updating.
+Indicates that the adapter implements an interface to update firmware
+on the adapter.
+*/
+ HPI_ADAPTER_PROPERTY_SUPPORTS_FW_UPDATE = 273,
+/** Readonly Firmware IDs
+Identifiy firmware independent of individual adapter type.
+May be used as a filter for firmware update images.
+Property 1 = Bootloader ID
+Property 2 = Main program ID
+*/
+ HPI_ADAPTER_PROPERTY_FIRMWARE_ID = 274
};
/** Adapter mode commands
@@ -638,7 +631,7 @@ enum HPI_MIXER_STORE_COMMAND {
HPI_MIXER_STORE_ENABLE = 4,
/** Disable auto storage of some control settings. */
HPI_MIXER_STORE_DISABLE = 5,
-/** Save the attributes of a single control. */
+/** Unimplemented - save the attributes of a single control. */
HPI_MIXER_STORE_SAVE_SINGLE = 6
};
@@ -941,7 +934,7 @@ enum HPI_ERROR_CODES {
HPI_ERROR_BAD_ADAPTER_NUMBER = 202,
/** 2 adapters with the same adapter number. */
HPI_ERROR_DUPLICATE_ADAPTER_NUMBER = 203,
- /** DSP code failed to bootload. (unused?) */
+ /** DSP code failed to bootload. Usually a DSP memory test failure. */
HPI_ERROR_DSP_BOOTLOAD = 204,
/** Couldn't find or open the DSP code file. */
HPI_ERROR_DSP_FILE_NOT_FOUND = 206,
@@ -978,6 +971,9 @@ enum HPI_ERROR_CODES {
HPI_ERROR_FLASH_VERIFY = 225,
HPI_ERROR_FLASH_TYPE = 226,
HPI_ERROR_FLASH_START = 227,
+ HPI_ERROR_FLASH_READ = 228,
+ HPI_ERROR_FLASH_READ_NO_FILE = 229,
+ HPI_ERROR_FLASH_SIZE = 230,
/** Reserved for OEMs. */
HPI_ERROR_RESERVED_1 = 290,
@@ -1020,6 +1016,8 @@ enum HPI_ERROR_CODES {
HPI_ERROR_NO_INTERDSP_GROUPS = 315,
/** Stream wait cancelled before threshold reached. */
HPI_ERROR_WAIT_CANCELLED = 316,
+ /** A character string is invalid. */
+ HPI_ERROR_INVALID_STRING = 317,
/** Invalid mixer node for this adapter. */
HPI_ERROR_INVALID_NODE = 400,
@@ -1046,11 +1044,15 @@ enum HPI_ERROR_CODES {
/** I2C */
HPI_ERROR_I2C_BAD_ADR = 460,
- /** Entity errors */
+ /** Entity type did not match requested type */
HPI_ERROR_ENTITY_TYPE_MISMATCH = 470,
+ /** Entity item count did not match requested count */
HPI_ERROR_ENTITY_ITEM_COUNT = 471,
+ /** Entity type is not one of the valid types */
HPI_ERROR_ENTITY_TYPE_INVALID = 472,
+ /** Entity role is not one of the valid roles */
HPI_ERROR_ENTITY_ROLE_INVALID = 473,
+ /** Entity size doesn't match target size */
HPI_ERROR_ENTITY_SIZE_MISMATCH = 474,
/* AES18 specific errors were 500..507 */
@@ -1078,8 +1080,7 @@ enum HPI_ERROR_CODES {
/** \defgroup maximums HPI maximum values
\{
*/
-/** Maximum number of adapters per HPI sub-system
- WARNING: modifying this value changes the response structure size.*/
+/** Maximum number of PCI HPI adapters */
#define HPI_MAX_ADAPTERS 20
/** Maximum number of in or out streams per adapter */
#define HPI_MAX_STREAMS 16
@@ -1090,6 +1091,9 @@ enum HPI_ERROR_CODES {
#define HPI_MAX_ANC_BYTES_PER_FRAME (64)
#define HPI_STRING_LEN 16
+/** Networked adapters have index >= 100 */
+#define HPI_MIN_NETWORK_ADAPTER_IDX 100
+
/** Velocity units */
#define HPI_OSTREAM_VELOCITY_UNITS 4096
/** OutStream timescale units */
@@ -1111,14 +1115,14 @@ enum HPI_ERROR_CODES {
struct hpi_format {
u32 sample_rate;
/**< 11025, 32000, 44100 ... */
- u32 bit_rate; /**< for MPEG */
+ u32 bit_rate; /**< for MPEG */
u32 attributes;
/**< Stereo/JointStereo/Mono */
u16 mode_legacy;
/**< Legacy ancillary mode or idle bit */
- u16 unused; /**< Unused */
- u16 channels; /**< 1,2..., (or ancillary mode or idle bit */
- u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see #HPI_FORMATS. */
+ u16 unused; /**< Unused */
+ u16 channels; /**< 1,2..., (or ancillary mode or idle bit */
+ u16 format; /**< HPI_FORMAT_PCM16, _MPEG etc. see #HPI_FORMATS. */
};
struct hpi_anc_frame {
@@ -1144,9 +1148,6 @@ struct hpi_async_event {
} u;
};
-/* skip host side function declarations for
- DSP compile and documentation extraction */
-
#ifndef DISABLE_PRAGMA_PACK1
#pragma pack(pop)
#endif
@@ -1357,7 +1358,7 @@ u16 hpi_volume_get_mute(u32 h_control, u32 *mute);
u16 hpi_volume_query_range(u32 h_control, short *min_gain_01dB,
short *max_gain_01dB, short *step_gain_01dB);
-u16 hpi_volume_query_channels(const u32 h_volume, u32 *p_channels);
+u16 hpi_volume_query_channels(const u32 h_control, u32 *p_channels);
u16 hpi_volume_auto_fade(u32 h_control,
short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms);
@@ -1366,6 +1367,9 @@ u16 hpi_volume_auto_fade_profile(u32 h_control,
short an_stop_gain0_01dB[HPI_MAX_CHANNELS], u32 duration_ms,
u16 profile);
+u16 hpi_volume_query_auto_fade_profile(const u32 h_control, const u32 i,
+ u16 *profile);
+
/*****************/
/* Level control */
/*****************/
diff --git a/sound/pci/asihpi/hpi6000.c b/sound/pci/asihpi/hpi6000.c
index 3cc6f11c20aa..2414d7a2239d 100644
--- a/sound/pci/asihpi/hpi6000.c
+++ b/sound/pci/asihpi/hpi6000.c
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -231,6 +231,8 @@ static void subsys_message(struct hpi_message *phm, struct hpi_response *phr)
static void control_message(struct hpi_adapter_obj *pao,
struct hpi_message *phm, struct hpi_response *phr)
{
+ struct hpi_hw_obj *phw = pao->priv;
+
switch (phm->function) {
case HPI_CONTROL_GET_STATE:
if (pao->has_control_cache) {
@@ -248,17 +250,14 @@ static void control_message(struct hpi_adapter_obj *pao,
break;
}
- if (hpi_check_control_cache(((struct hpi_hw_obj *)
- pao->priv)->p_cache, phm,
- phr))
+ if (hpi_check_control_cache(phw->p_cache, phm, phr))
break;
}
hw_message(pao, phm, phr);
break;
case HPI_CONTROL_SET_STATE:
hw_message(pao, phm, phr);
- hpi_cmn_control_cache_sync_to_msg(((struct hpi_hw_obj *)pao->
- priv)->p_cache, phm, phr);
+ hpi_cmn_control_cache_sync_to_msg(phw->p_cache, phm, phr);
break;
case HPI_CONTROL_GET_INFO:
@@ -451,11 +450,11 @@ static void subsys_create_adapter(struct hpi_message *phm,
}
for (dsp_index = 0; dsp_index < MAX_DSPS; dsp_index++) {
- struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
+ struct hpi_hw_obj *phw = pao->priv;
phw->ado[dsp_index].pa_parent_adapter = pao;
}
- phr->u.s.adapter_type = ao.adapter_type;
+ phr->u.s.adapter_type = ao.type;
phr->u.s.adapter_index = ao.index;
phr->error = 0;
}
@@ -476,7 +475,7 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
u32 dsp_index = 0;
u32 control_cache_size = 0;
u32 control_cache_count = 0;
- struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
+ struct hpi_hw_obj *phw = pao->priv;
/* The PCI2040 has the following address map */
/* BAR0 - 4K = HPI control and status registers on PCI2040 (HPI CSR) */
@@ -559,7 +558,7 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
if (error)
return error;
}
- pao->adapter_type = hr0.u.ax.info.adapter_type;
+ pao->type = hr0.u.ax.info.adapter_type;
pao->index = hr0.u.ax.info.adapter_index;
}
@@ -584,9 +583,8 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
pao->has_control_cache = 1;
}
- HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n",
- pao->adapter_type, pao->index);
- pao->open = 0; /* upon creation the adapter is closed */
+ HPI_DEBUG_LOG(DEBUG, "get adapter info ASI%04X index %d\n", pao->type,
+ pao->index);
if (phw->p_cache)
phw->p_cache->adap_idx = pao->index;
@@ -596,7 +594,7 @@ static short create_adapter_obj(struct hpi_adapter_obj *pao,
static void delete_adapter_obj(struct hpi_adapter_obj *pao)
{
- struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
+ struct hpi_hw_obj *phw = pao->priv;
if (pao->has_control_cache)
hpi_free_control_cache(phw->p_cache);
@@ -639,7 +637,7 @@ static void adapter_get_asserts(struct hpi_adapter_obj *pao,
static short hpi6000_adapter_boot_load_dsp(struct hpi_adapter_obj *pao,
u32 *pos_error_code)
{
- struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
+ struct hpi_hw_obj *phw = pao->priv;
short error;
u32 timeout;
u32 read = 0;
@@ -1220,8 +1218,8 @@ static void hpi_read_block(struct dsp_obj *pdo, u32 address, u32 *pdata,
static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao,
u16 dsp_index, u32 hpi_address, u32 *source, u32 count)
{
- struct dsp_obj *pdo =
- &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
+ struct hpi_hw_obj *phw = pao->priv;
+ struct dsp_obj *pdo = &phw->ado[dsp_index];
u32 time_out = PCI_TIMEOUT;
int c6711_burst_size = 128;
u32 local_hpi_address = hpi_address;
@@ -1258,8 +1256,8 @@ static u16 hpi6000_dsp_block_write32(struct hpi_adapter_obj *pao,
static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao,
u16 dsp_index, u32 hpi_address, u32 *dest, u32 count)
{
- struct dsp_obj *pdo =
- &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
+ struct hpi_hw_obj *phw = pao->priv;
+ struct dsp_obj *pdo = &phw->ado[dsp_index];
u32 time_out = PCI_TIMEOUT;
int c6711_burst_size = 16;
u32 local_hpi_address = hpi_address;
@@ -1298,7 +1296,7 @@ static u16 hpi6000_dsp_block_read32(struct hpi_adapter_obj *pao,
static short hpi6000_message_response_sequence(struct hpi_adapter_obj *pao,
u16 dsp_index, struct hpi_message *phm, struct hpi_response *phr)
{
- struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
+ struct hpi_hw_obj *phw = pao->priv;
struct dsp_obj *pdo = &phw->ado[dsp_index];
u32 timeout;
u16 ack;
@@ -1414,8 +1412,8 @@ static short hpi6000_send_data_check_adr(u32 address, u32 length_in_dwords)
static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index,
struct hpi_message *phm, struct hpi_response *phr)
{
- struct dsp_obj *pdo =
- &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
+ struct hpi_hw_obj *phw = pao->priv;
+ struct dsp_obj *pdo = &phw->ado[dsp_index];
u32 data_sent = 0;
u16 ack;
u32 length, address;
@@ -1487,8 +1485,8 @@ static short hpi6000_send_data(struct hpi_adapter_obj *pao, u16 dsp_index,
static short hpi6000_get_data(struct hpi_adapter_obj *pao, u16 dsp_index,
struct hpi_message *phm, struct hpi_response *phr)
{
- struct dsp_obj *pdo =
- &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
+ struct hpi_hw_obj *phw = pao->priv;
+ struct dsp_obj *pdo = &phw->ado[dsp_index];
u32 data_got = 0;
u16 ack;
u32 length, address;
@@ -1551,8 +1549,8 @@ static void hpi6000_send_dsp_interrupt(struct dsp_obj *pdo)
static short hpi6000_send_host_command(struct hpi_adapter_obj *pao,
u16 dsp_index, u32 host_cmd)
{
- struct dsp_obj *pdo =
- &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
+ struct hpi_hw_obj *phw = pao->priv;
+ struct dsp_obj *pdo = &phw->ado[dsp_index];
u32 timeout = TIMEOUT;
/* set command */
@@ -1577,7 +1575,7 @@ static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao,
{
u32 hPI_error;
- struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
+ struct hpi_hw_obj *phw = pao->priv;
/* read the error bits from the PCI2040 */
hPI_error = ioread32(phw->dw2040_HPICSR + HPI_ERROR_REPORT);
@@ -1597,8 +1595,8 @@ static short hpi6000_check_PCI2040_error_flag(struct hpi_adapter_obj *pao,
static short hpi6000_wait_dsp_ack(struct hpi_adapter_obj *pao, u16 dsp_index,
u32 ack_value)
{
- struct dsp_obj *pdo =
- &(*(struct hpi_hw_obj *)pao->priv).ado[dsp_index];
+ struct hpi_hw_obj *phw = pao->priv;
+ struct dsp_obj *pdo = &phw->ado[dsp_index];
u32 ack = 0L;
u32 timeout;
u32 hPIC = 0L;
@@ -1640,7 +1638,7 @@ static short hpi6000_update_control_cache(struct hpi_adapter_obj *pao,
struct hpi_message *phm)
{
const u16 dsp_index = 0;
- struct hpi_hw_obj *phw = (struct hpi_hw_obj *)pao->priv;
+ struct hpi_hw_obj *phw = pao->priv;
struct dsp_obj *pdo = &phw->ado[dsp_index];
u32 timeout;
u32 cache_dirty_flag;
@@ -1740,7 +1738,8 @@ static void hw_message(struct hpi_adapter_obj *pao, struct hpi_message *phm,
{
u16 error = 0;
u16 dsp_index = 0;
- u16 num_dsp = ((struct hpi_hw_obj *)pao->priv)->num_dsp;
+ struct hpi_hw_obj *phw = pao->priv;
+ u16 num_dsp = phw->num_dsp;
if (num_dsp < 2)
dsp_index = 0;
diff --git a/sound/pci/asihpi/hpi6000.h b/sound/pci/asihpi/hpi6000.h
index 4c7d507c0ecd..7e0deeff5e7c 100644
--- a/sound/pci/asihpi/hpi6000.h
+++ b/sound/pci/asihpi/hpi6000.h
@@ -1,7 +1,7 @@
/*****************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
diff --git a/sound/pci/asihpi/hpi6205.c b/sound/pci/asihpi/hpi6205.c
index e041a6ae1c5a..4f2873880b16 100644
--- a/sound/pci/asihpi/hpi6205.c
+++ b/sound/pci/asihpi/hpi6205.c
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -45,18 +45,21 @@
#define HPI6205_ERROR_MSG_RESP_TIMEOUT 1016
/* initialization/bootload errors */
-#define HPI6205_ERROR_6205_NO_IRQ 1002
-#define HPI6205_ERROR_6205_INIT_FAILED 1003
-#define HPI6205_ERROR_6205_REG 1006
-#define HPI6205_ERROR_6205_DSPPAGE 1007
-#define HPI6205_ERROR_C6713_HPIC 1009
-#define HPI6205_ERROR_C6713_HPIA 1010
-#define HPI6205_ERROR_C6713_PLL 1011
-#define HPI6205_ERROR_DSP_INTMEM 1012
-#define HPI6205_ERROR_DSP_EXTMEM 1013
-#define HPI6205_ERROR_DSP_PLD 1014
-#define HPI6205_ERROR_6205_EEPROM 1017
-#define HPI6205_ERROR_DSP_EMIF 1018
+#define HPI6205_ERROR_6205_NO_IRQ 1002
+#define HPI6205_ERROR_6205_INIT_FAILED 1003
+#define HPI6205_ERROR_6205_REG 1006
+#define HPI6205_ERROR_6205_DSPPAGE 1007
+#define HPI6205_ERROR_C6713_HPIC 1009
+#define HPI6205_ERROR_C6713_HPIA 1010
+#define HPI6205_ERROR_C6713_PLL 1011
+#define HPI6205_ERROR_DSP_INTMEM 1012
+#define HPI6205_ERROR_DSP_EXTMEM 1013
+#define HPI6205_ERROR_DSP_PLD 1014
+#define HPI6205_ERROR_6205_EEPROM 1017
+#define HPI6205_ERROR_DSP_EMIF1 1018
+#define HPI6205_ERROR_DSP_EMIF2 1019
+#define HPI6205_ERROR_DSP_EMIF3 1020
+#define HPI6205_ERROR_DSP_EMIF4 1021
/*****************************************************************************/
/* for C6205 PCI i/f */
@@ -488,7 +491,7 @@ static void subsys_create_adapter(struct hpi_message *phm,
return;
}
- phr->u.s.adapter_type = ao.adapter_type;
+ phr->u.s.adapter_type = ao.type;
phr->u.s.adapter_index = ao.index;
phr->error = 0;
}
@@ -503,7 +506,7 @@ static void adapter_delete(struct hpi_adapter_obj *pao,
phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
return;
}
- phw = (struct hpi_hw_obj *)pao->priv;
+ phw = pao->priv;
/* reset adapter h/w */
/* Reset C6713 #1 */
boot_loader_write_mem32(pao, 0, C6205_BAR0_TIMER1_CTL, 0);
@@ -652,7 +655,7 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
if (hr.error)
return hr.error;
- pao->adapter_type = hr.u.ax.info.adapter_type;
+ pao->type = hr.u.ax.info.adapter_type;
pao->index = hr.u.ax.info.adapter_index;
max_streams =
@@ -665,8 +668,6 @@ static u16 create_adapter_obj(struct hpi_adapter_obj *pao,
hr.u.ax.info.serial_number);
}
- pao->open = 0; /* upon creation the adapter is closed */
-
if (phw->p_cache)
phw->p_cache->adap_idx = pao->index;
@@ -803,8 +804,8 @@ static void outstream_host_buffer_allocate(struct hpi_adapter_obj *pao,
obj_index];
status->samples_processed = 0;
status->stream_state = HPI_STATE_STOPPED;
- status->dSP_index = 0;
- status->host_index = status->dSP_index;
+ status->dsp_index = 0;
+ status->host_index = status->dsp_index;
status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
status->auxiliary_data_available = 0;
@@ -878,7 +879,7 @@ static void outstream_host_buffer_free(struct hpi_adapter_obj *pao,
static u32 outstream_get_space_available(struct hpi_hostbuffer_status *status)
{
return status->size_in_bytes - (status->host_index -
- status->dSP_index);
+ status->dsp_index);
}
static void outstream_write(struct hpi_adapter_obj *pao,
@@ -1080,8 +1081,8 @@ static void instream_host_buffer_allocate(struct hpi_adapter_obj *pao,
obj_index];
status->samples_processed = 0;
status->stream_state = HPI_STATE_STOPPED;
- status->dSP_index = 0;
- status->host_index = status->dSP_index;
+ status->dsp_index = 0;
+ status->host_index = status->dsp_index;
status->size_in_bytes = phm->u.d.u.buffer.buffer_size;
status->auxiliary_data_available = 0;
@@ -1162,7 +1163,7 @@ static void instream_start(struct hpi_adapter_obj *pao,
static u32 instream_get_bytes_available(struct hpi_hostbuffer_status *status)
{
- return status->dSP_index - status->host_index;
+ return status->dsp_index - status->host_index;
}
static void instream_read(struct hpi_adapter_obj *pao,
@@ -1614,7 +1615,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
boot_loader_write_mem32(pao, dsp_index, 0x01800008, setting);
if (setting != boot_loader_read_mem32(pao, dsp_index,
0x01800008))
- return HPI6205_ERROR_DSP_EMIF;
+ return HPI6205_ERROR_DSP_EMIF1;
/* EMIF CE1 setup - 32 bit async. This is 6713 #1 HPI, */
/* which occupies D15..0. 6713 starts at 27MHz, so need */
@@ -1627,7 +1628,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
boot_loader_write_mem32(pao, dsp_index, 0x01800004, setting);
if (setting != boot_loader_read_mem32(pao, dsp_index,
0x01800004))
- return HPI6205_ERROR_DSP_EMIF;
+ return HPI6205_ERROR_DSP_EMIF2;
/* EMIF CE2 setup - 32 bit async. This is 6713 #2 HPI, */
/* which occupies D15..0. 6713 starts at 27MHz, so need */
@@ -1639,7 +1640,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
boot_loader_write_mem32(pao, dsp_index, 0x01800010, setting);
if (setting != boot_loader_read_mem32(pao, dsp_index,
0x01800010))
- return HPI6205_ERROR_DSP_EMIF;
+ return HPI6205_ERROR_DSP_EMIF3;
/* EMIF CE3 setup - 32 bit async. */
/* This is the PLD on the ASI5000 cards only */
@@ -1650,7 +1651,7 @@ static u16 boot_loader_config_emif(struct hpi_adapter_obj *pao, int dsp_index)
boot_loader_write_mem32(pao, dsp_index, 0x01800014, setting);
if (setting != boot_loader_read_mem32(pao, dsp_index,
0x01800014))
- return HPI6205_ERROR_DSP_EMIF;
+ return HPI6205_ERROR_DSP_EMIF4;
/* set EMIF SDRAM control for 2Mx32 SDRAM (512x32x4 bank) */
/* need to use this else DSP code crashes? */
diff --git a/sound/pci/asihpi/hpi_internal.h b/sound/pci/asihpi/hpi_internal.h
index d497030c160f..4cc315daeda0 100644
--- a/sound/pci/asihpi/hpi_internal.h
+++ b/sound/pci/asihpi/hpi_internal.h
@@ -25,6 +25,7 @@ HPI internal definitions
#define _HPI_INTERNAL_H_
#include "hpi.h"
+
/** maximum number of memory regions mapped to an adapter */
#define HPI_MAX_ADAPTER_MEM_SPACES (2)
@@ -220,8 +221,6 @@ enum HPI_CONTROL_ATTRIBUTES {
HPI_COBRANET_SET = HPI_CTL_ATTR(COBRANET, 1),
HPI_COBRANET_GET = HPI_CTL_ATTR(COBRANET, 2),
- /*HPI_COBRANET_SET_DATA = HPI_CTL_ATTR(COBRANET, 3), */
- /*HPI_COBRANET_GET_DATA = HPI_CTL_ATTR(COBRANET, 4), */
HPI_COBRANET_GET_STATUS = HPI_CTL_ATTR(COBRANET, 5),
HPI_COBRANET_SEND_PACKET = HPI_CTL_ATTR(COBRANET, 6),
HPI_COBRANET_GET_PACKET = HPI_CTL_ATTR(COBRANET, 7),
@@ -241,7 +240,9 @@ enum HPI_CONTROL_ATTRIBUTES {
HPI_PAD_PROGRAM_TYPE = HPI_CTL_ATTR(PAD, 5),
HPI_PAD_PROGRAM_ID = HPI_CTL_ATTR(PAD, 6),
HPI_PAD_TA_SUPPORT = HPI_CTL_ATTR(PAD, 7),
- HPI_PAD_TA_ACTIVE = HPI_CTL_ATTR(PAD, 8)
+ HPI_PAD_TA_ACTIVE = HPI_CTL_ATTR(PAD, 8),
+
+ HPI_UNIVERSAL_ENTITY = HPI_CTL_ATTR(UNIVERSAL, 1)
};
#define HPI_POLARITY_POSITIVE 0
@@ -393,14 +394,10 @@ enum HPI_FUNCTION_IDS {
HPI_SUBSYS_OPEN = HPI_FUNC_ID(SUBSYSTEM, 1),
HPI_SUBSYS_GET_VERSION = HPI_FUNC_ID(SUBSYSTEM, 2),
HPI_SUBSYS_GET_INFO = HPI_FUNC_ID(SUBSYSTEM, 3),
- /* HPI_SUBSYS_FIND_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 4), */
HPI_SUBSYS_CREATE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 5),
HPI_SUBSYS_CLOSE = HPI_FUNC_ID(SUBSYSTEM, 6),
- /* HPI_SUBSYS_DELETE_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 7), */
HPI_SUBSYS_DRIVER_LOAD = HPI_FUNC_ID(SUBSYSTEM, 8),
HPI_SUBSYS_DRIVER_UNLOAD = HPI_FUNC_ID(SUBSYSTEM, 9),
- /* HPI_SUBSYS_READ_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 10), */
- /* HPI_SUBSYS_WRITE_PORT_8 = HPI_FUNC_ID(SUBSYSTEM, 11), */
HPI_SUBSYS_GET_NUM_ADAPTERS = HPI_FUNC_ID(SUBSYSTEM, 12),
HPI_SUBSYS_GET_ADAPTER = HPI_FUNC_ID(SUBSYSTEM, 13),
HPI_SUBSYS_SET_NETWORK_INTERFACE = HPI_FUNC_ID(SUBSYSTEM, 14),
@@ -430,7 +427,10 @@ enum HPI_FUNCTION_IDS {
HPI_ADAPTER_IRQ_QUERY_AND_CLEAR = HPI_FUNC_ID(ADAPTER, 19),
HPI_ADAPTER_IRQ_CALLBACK = HPI_FUNC_ID(ADAPTER, 20),
HPI_ADAPTER_DELETE = HPI_FUNC_ID(ADAPTER, 21),
-#define HPI_ADAPTER_FUNCTION_COUNT 21
+ HPI_ADAPTER_READ_FLASH = HPI_FUNC_ID(ADAPTER, 22),
+ HPI_ADAPTER_END_FLASH = HPI_FUNC_ID(ADAPTER, 23),
+ HPI_ADAPTER_FILESTORE_DELETE_ALL = HPI_FUNC_ID(ADAPTER, 24),
+#define HPI_ADAPTER_FUNCTION_COUNT 24
HPI_OSTREAM_OPEN = HPI_FUNC_ID(OSTREAM, 1),
HPI_OSTREAM_CLOSE = HPI_FUNC_ID(OSTREAM, 2),
@@ -495,7 +495,9 @@ enum HPI_FUNCTION_IDS {
HPI_MIXER_GET_CONTROL_MULTIPLE_VALUES = HPI_FUNC_ID(MIXER, 10),
HPI_MIXER_STORE = HPI_FUNC_ID(MIXER, 11),
HPI_MIXER_GET_CACHE_INFO = HPI_FUNC_ID(MIXER, 12),
-#define HPI_MIXER_FUNCTION_COUNT 12
+ HPI_MIXER_GET_BLOCK_HANDLE = HPI_FUNC_ID(MIXER, 13),
+ HPI_MIXER_GET_PARAMETER_HANDLE = HPI_FUNC_ID(MIXER, 14),
+#define HPI_MIXER_FUNCTION_COUNT 14
HPI_CONTROL_GET_INFO = HPI_FUNC_ID(CONTROL, 1),
HPI_CONTROL_GET_STATE = HPI_FUNC_ID(CONTROL, 2),
@@ -618,7 +620,7 @@ struct hpi_hostbuffer_status {
u32 auxiliary_data_available;
u32 stream_state;
/* DSP index in to the host bus master buffer. */
- u32 dSP_index;
+ u32 dsp_index;
/* Host index in to the host bus master buffer. */
u32 host_index;
u32 size_in_bytes;
@@ -661,13 +663,6 @@ union hpi_adapterx_msg {
u16 index;
} module_info;
struct {
- u32 checksum;
- u16 sequence;
- u16 length;
- u16 offset; /**< offset from start of msg to data */
- u16 unused;
- } program_flash;
- struct {
u16 index;
u16 what;
u16 property_index;
@@ -678,25 +673,18 @@ union hpi_adapterx_msg {
u16 parameter2;
} property_set;
struct {
- u32 offset;
- } query_flash;
- struct {
u32 pad32;
u16 key1;
u16 key2;
} restart;
struct {
- u32 offset;
- u32 length;
- u32 key;
- } start_flash;
- struct {
u32 pad32;
u16 value;
} test_assert;
struct {
u32 yes;
} irq_query;
+ u32 pad[3];
};
struct hpi_adapter_res {
@@ -724,18 +712,10 @@ union hpi_adapterx_res {
u32 adapter_mode;
} mode;
struct {
- u16 sequence;
- } program_flash;
- struct {
u16 parameter1;
u16 parameter2;
} property_get;
struct {
- u32 checksum;
- u32 length;
- u32 version;
- } query_flash;
- struct {
u32 yes;
} irq_query;
};
@@ -1150,74 +1130,9 @@ struct hpi_res_adapter_get_info {
struct hpi_adapter_res p;
};
-/* padding is so these are same size as v0 hpi_message */
-struct hpi_msg_adapter_query_flash {
- struct hpi_message_header h;
- u32 offset;
- u8 pad_to_version0_size[sizeof(struct hpi_message) - /* V0 res */
- sizeof(struct hpi_message_header) - 1 * sizeof(u32)];
-};
-
-/* padding is so these are same size as v0 hpi_response */
-struct hpi_res_adapter_query_flash {
- struct hpi_response_header h;
- u32 checksum;
- u32 length;
- u32 version;
- u8 pad_to_version0_size[sizeof(struct hpi_response) - /* V0 res */
- sizeof(struct hpi_response_header) - 3 * sizeof(u32)];
-};
-
-struct hpi_msg_adapter_start_flash {
- struct hpi_message_header h;
- u32 offset;
- u32 length;
- u32 key;
- u8 pad_to_version0_size[sizeof(struct hpi_message) - /* V0 res */
- sizeof(struct hpi_message_header) - 3 * sizeof(u32)];
-};
-
-struct hpi_res_adapter_start_flash {
- struct hpi_response_header h;
- u8 pad_to_version0_size[sizeof(struct hpi_response) - /* V0 res */
- sizeof(struct hpi_response_header)];
-};
-
-struct hpi_msg_adapter_program_flash_payload {
- u32 checksum;
- u16 sequence;
- u16 length;
- u16 offset; /**< offset from start of msg to data */
- u16 unused;
- /* ensure sizeof(header + payload) == sizeof(hpi_message_V0)
- because old firmware expects data after message of this size */
- u8 pad_to_version0_size[sizeof(struct hpi_message) - /* V0 message */
- sizeof(struct hpi_message_header) - sizeof(u32) -
- 4 * sizeof(u16)];
-};
-
-struct hpi_msg_adapter_program_flash {
- struct hpi_message_header h;
- struct hpi_msg_adapter_program_flash_payload p;
- u32 data[256];
-};
-
-struct hpi_res_adapter_program_flash {
- struct hpi_response_header h;
- u16 sequence;
- u8 pad_to_version0_size[sizeof(struct hpi_response) - /* V0 res */
- sizeof(struct hpi_response_header) - sizeof(u16)];
-};
-
-struct hpi_msg_adapter_debug_read {
- struct hpi_message_header h;
- u32 dsp_address;
- u32 count_bytes;
-};
-
struct hpi_res_adapter_debug_read {
struct hpi_response_header h;
- u8 bytes[256];
+ u8 bytes[1024];
};
struct hpi_msg_cobranet_hmi {
@@ -1461,7 +1376,7 @@ struct hpi_control_cache_pad {
/* 2^N sized FIFO buffer (internal to HPI<->DSP interaction) */
struct hpi_fifo_buffer {
u32 size;
- u32 dSP_index;
+ u32 dsp_index;
u32 host_index;
};
diff --git a/sound/pci/asihpi/hpi_version.h b/sound/pci/asihpi/hpi_version.h
new file mode 100644
index 000000000000..e9146e53bd50
--- /dev/null
+++ b/sound/pci/asihpi/hpi_version.h
@@ -0,0 +1,32 @@
+/** HPI Version Definitions
+Development releases have odd minor version.
+Production releases have even minor version.
+
+\file hpi_version.h
+*/
+
+#ifndef _HPI_VERSION_H
+#define _HPI_VERSION_H
+
+/* Use single digits for versions less that 10 to avoid octal. */
+/* *** HPI_VER is the only edit required to update version *** */
+/** HPI version */
+#define HPI_VER HPI_VERSION_CONSTRUCTOR(4, 10, 1)
+
+/** HPI version string in dotted decimal format */
+#define HPI_VER_STRING "4.10.01"
+
+/** Library version as documented in hpi-api-versions.txt */
+#define HPI_LIB_VER HPI_VERSION_CONSTRUCTOR(10, 2, 0)
+
+/** Construct hpi version number from major, minor, release numbers */
+#define HPI_VERSION_CONSTRUCTOR(maj, min, r) ((maj << 16) + (min << 8) + r)
+
+/** Extract major version from hpi version number */
+#define HPI_VER_MAJOR(v) ((int)(v >> 16))
+/** Extract minor version from hpi version number */
+#define HPI_VER_MINOR(v) ((int)((v >> 8) & 0xFF))
+/** Extract release from hpi version number */
+#define HPI_VER_RELEASE(v) ((int)(v & 0xFF))
+
+#endif
diff --git a/sound/pci/asihpi/hpicmn.c b/sound/pci/asihpi/hpicmn.c
index bd47521b24ec..7ed5c26c3737 100644
--- a/sound/pci/asihpi/hpicmn.c
+++ b/sound/pci/asihpi/hpicmn.c
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -68,7 +68,7 @@ u16 hpi_validate_response(struct hpi_message *phm, struct hpi_response *phr)
u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
{
u16 retval = 0;
- /*HPI_ASSERT(pao->wAdapterType); */
+ /*HPI_ASSERT(pao->type); */
hpios_alistlock_lock(&adapters);
@@ -77,13 +77,13 @@ u16 hpi_add_adapter(struct hpi_adapter_obj *pao)
goto unlock;
}
- if (adapters.adapter[pao->index].adapter_type) {
+ if (adapters.adapter[pao->index].type) {
int a;
for (a = HPI_MAX_ADAPTERS - 1; a >= 0; a--) {
- if (!adapters.adapter[a].adapter_type) {
+ if (!adapters.adapter[a].type) {
HPI_DEBUG_LOG(WARNING,
"ASI%X duplicate index %d moved to %d\n",
- pao->adapter_type, pao->index, a);
+ pao->type, pao->index, a);
pao->index = a;
break;
}
@@ -104,13 +104,13 @@ unlock:
void hpi_delete_adapter(struct hpi_adapter_obj *pao)
{
- if (!pao->adapter_type) {
+ if (!pao->type) {
HPI_DEBUG_LOG(ERROR, "removing null adapter?\n");
return;
}
hpios_alistlock_lock(&adapters);
- if (adapters.adapter[pao->index].adapter_type)
+ if (adapters.adapter[pao->index].type)
adapters.gw_num_adapters--;
memset(&adapters.adapter[pao->index], 0, sizeof(adapters.adapter[0]));
hpios_alistlock_unlock(&adapters);
@@ -132,7 +132,7 @@ struct hpi_adapter_obj *hpi_find_adapter(u16 adapter_index)
}
pao = &adapters.adapter[adapter_index];
- if (pao->adapter_type != 0) {
+ if (pao->type != 0) {
/*
HPI_DEBUG_LOG(VERBOSE, "Found adapter index %d\n",
wAdapterIndex);
@@ -165,7 +165,7 @@ static void subsys_get_adapter(struct hpi_message *phm,
/* find the nCount'th nonzero adapter in array */
for (index = 0; index < HPI_MAX_ADAPTERS; index++) {
- if (adapters.adapter[index].adapter_type) {
+ if (adapters.adapter[index].type) {
if (!count)
break;
count--;
@@ -174,11 +174,11 @@ static void subsys_get_adapter(struct hpi_message *phm,
if (index < HPI_MAX_ADAPTERS) {
phr->u.s.adapter_index = adapters.adapter[index].index;
- phr->u.s.adapter_type = adapters.adapter[index].adapter_type;
+ phr->u.s.adapter_type = adapters.adapter[index].type;
} else {
phr->u.s.adapter_index = 0;
phr->u.s.adapter_type = 0;
- phr->error = HPI_ERROR_BAD_ADAPTER_NUMBER;
+ phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
}
}
@@ -324,6 +324,8 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
}
phr->error = 0;
+ phr->specific_error = 0;
+ phr->version = 0;
/* set the default response size */
response_size =
@@ -531,8 +533,12 @@ short hpi_check_control_cache(struct hpi_control_cache *p_cache,
found ? "Cached" : "Uncached", phm->adapter_index,
pI->control_index, pI->control_type, phm->u.c.attribute);
- if (found)
+ if (found) {
phr->size = (u16)response_size;
+ phr->type = HPI_TYPE_RESPONSE;
+ phr->object = phm->object;
+ phr->function = phm->function;
+ }
return found;
}
@@ -631,7 +637,7 @@ struct hpi_control_cache *hpi_alloc_control_cache(const u32 control_count,
if (!p_cache)
return NULL;
- p_cache->p_info = kzalloc(sizeof(*p_cache->p_info) * control_count,
+ p_cache->p_info = kcalloc(control_count, sizeof(*p_cache->p_info),
GFP_KERNEL);
if (!p_cache->p_info) {
kfree(p_cache);
diff --git a/sound/pci/asihpi/hpicmn.h b/sound/pci/asihpi/hpicmn.h
index d53cdf6e535f..e44121283047 100644
--- a/sound/pci/asihpi/hpicmn.h
+++ b/sound/pci/asihpi/hpicmn.h
@@ -1,7 +1,7 @@
/**
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -18,12 +18,15 @@
*/
+struct hpi_adapter_obj;
+
+/* a function that takes an adapter obj and returns an int */
+typedef int adapter_int_func(struct hpi_adapter_obj *pao);
+
struct hpi_adapter_obj {
struct hpi_pci pci; /* PCI info - bus#,dev#,address etc */
- u16 adapter_type; /* ASI6701 etc */
- u16 index; /* */
- u16 open; /* =1 when adapter open */
- u16 mixer_open;
+ u16 type; /* 0x6644 == ASI6644 etc */
+ u16 index;
struct hpios_spinlock dsp_lock;
diff --git a/sound/pci/asihpi/hpidebug.c b/sound/pci/asihpi/hpidebug.c
index b52baf62791e..ac86a1f1d3bf 100644
--- a/sound/pci/asihpi/hpidebug.c
+++ b/sound/pci/asihpi/hpidebug.c
@@ -1,7 +1,7 @@
/************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
diff --git a/sound/pci/asihpi/hpidebug.h b/sound/pci/asihpi/hpidebug.h
index 940f54c3c538..2c9af2329d36 100644
--- a/sound/pci/asihpi/hpidebug.h
+++ b/sound/pci/asihpi/hpidebug.h
@@ -1,7 +1,7 @@
/*****************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
diff --git a/sound/pci/asihpi/hpidspcd.c b/sound/pci/asihpi/hpidspcd.c
index 71d32c868c92..456a758f04f6 100644
--- a/sound/pci/asihpi/hpidspcd.c
+++ b/sound/pci/asihpi/hpidspcd.c
@@ -25,6 +25,7 @@ hotplug firmware loader from individual dsp code files
#define SOURCEFILE_NAME "hpidspcd.c"
#include "hpidspcd.h"
#include "hpidebug.h"
+#include "hpi_version.h"
struct dsp_code_private {
/** Firmware descriptor */
@@ -32,9 +33,6 @@ struct dsp_code_private {
struct pci_dev *dev;
};
-#define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \
- HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER)))
-
/*-------------------------------------------------------------------*/
short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
u32 *os_error_code)
@@ -66,22 +64,25 @@ short hpi_dsp_code_open(u32 adapter, void *os_data, struct dsp_code *dsp_code,
if ((header.type != 0x45444F43) || /* "CODE" */
(header.adapter != adapter)
|| (header.size != firmware->size)) {
- dev_printk(KERN_ERR, &dev->dev, "Invalid firmware file\n");
+ dev_printk(KERN_ERR, &dev->dev,
+ "Invalid firmware header size %d != file %zd\n",
+ header.size, firmware->size);
goto error2;
}
- if ((header.version / 100 & ~1) != (HPI_VER_DECIMAL / 100 & ~1)) {
+ if ((header.version >> 9) != (HPI_VER >> 9)) {
+ /* Consider even and subsequent odd minor versions to be compatible */
dev_printk(KERN_ERR, &dev->dev,
"Incompatible firmware version "
- "DSP image %d != Driver %d\n", header.version,
- HPI_VER_DECIMAL);
+ "DSP image %X != Driver %X\n", header.version,
+ HPI_VER);
goto error2;
}
- if (header.version != HPI_VER_DECIMAL) {
- dev_printk(KERN_WARNING, &dev->dev,
- "Firmware: release version mismatch DSP image %d != Driver %d\n",
- header.version, HPI_VER_DECIMAL);
+ if (header.version != HPI_VER) {
+ dev_printk(KERN_INFO, &dev->dev,
+ "Firmware: release version mismatch DSP image %X != Driver %X\n",
+ header.version, HPI_VER);
}
HPI_DEBUG_LOG(DEBUG, "dsp code %s opened\n", fw_name);
@@ -108,11 +109,8 @@ error1:
/*-------------------------------------------------------------------*/
void hpi_dsp_code_close(struct dsp_code *dsp_code)
{
- if (dsp_code->pvt->firmware) {
- HPI_DEBUG_LOG(DEBUG, "dsp code closed\n");
- release_firmware(dsp_code->pvt->firmware);
- dsp_code->pvt->firmware = NULL;
- }
+ HPI_DEBUG_LOG(DEBUG, "dsp code closed\n");
+ release_firmware(dsp_code->pvt->firmware);
kfree(dsp_code->pvt);
}
diff --git a/sound/pci/asihpi/hpidspcd.h b/sound/pci/asihpi/hpidspcd.h
index b22881122f19..659d19ca6d42 100644
--- a/sound/pci/asihpi/hpidspcd.h
+++ b/sound/pci/asihpi/hpidspcd.h
@@ -27,10 +27,6 @@ Functions for reading DSP code to load into DSP
#include "hpi_internal.h"
-/** Code header version is decimal encoded e.g. 4.06.10 is 40601 */
-#define HPI_VER_DECIMAL ((int)(HPI_VER_MAJOR(HPI_VER) * 10000 + \
-HPI_VER_MINOR(HPI_VER) * 100 + HPI_VER_RELEASE(HPI_VER)))
-
/** Header structure for dsp firmware file
This structure must match that used in s2bin.c for generation of asidsp.bin
*/
diff --git a/sound/pci/asihpi/hpifunc.c b/sound/pci/asihpi/hpifunc.c
index ebb568d695f1..510e56cffd31 100644
--- a/sound/pci/asihpi/hpifunc.c
+++ b/sound/pci/asihpi/hpifunc.c
@@ -2826,6 +2826,16 @@ u16 hpi_volume_auto_fade(u32 h_control,
duration_ms, HPI_VOLUME_AUTOFADE_LOG);
}
+u16 hpi_volume_query_auto_fade_profile(const u32 h_volume, const u32 i,
+ u16 *profile)
+{
+ u16 e;
+ u32 u;
+ e = hpi_control_query(h_volume, HPI_VOLUME_AUTOFADE, i, 0, &u);
+ *profile = (u16)u;
+ return e;
+}
+
u16 hpi_vox_set_threshold(u32 h_control, short an_gain0_01dB)
{
struct hpi_message hm;
diff --git a/sound/pci/asihpi/hpimsginit.c b/sound/pci/asihpi/hpimsginit.c
index 52400a6b5f15..032d563e3708 100644
--- a/sound/pci/asihpi/hpimsginit.c
+++ b/sound/pci/asihpi/hpimsginit.c
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
diff --git a/sound/pci/asihpi/hpimsginit.h b/sound/pci/asihpi/hpimsginit.h
index bfd330d78b58..5b48708c7d1e 100644
--- a/sound/pci/asihpi/hpimsginit.h
+++ b/sound/pci/asihpi/hpimsginit.h
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
diff --git a/sound/pci/asihpi/hpimsgx.c b/sound/pci/asihpi/hpimsgx.c
index 2e779421a618..d4790ddc225c 100644
--- a/sound/pci/asihpi/hpimsgx.c
+++ b/sound/pci/asihpi/hpimsgx.c
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -22,6 +22,7 @@ Extended Message Function With Response Caching
*****************************************************************************/
#define SOURCEFILE_NAME "hpimsgx.c"
#include "hpi_internal.h"
+#include "hpi_version.h"
#include "hpimsginit.h"
#include "hpicmn.h"
#include "hpimsgx.h"
diff --git a/sound/pci/asihpi/hpimsgx.h b/sound/pci/asihpi/hpimsgx.h
index fd49e7542a88..37f3efd95a70 100644
--- a/sound/pci/asihpi/hpimsgx.h
+++ b/sound/pci/asihpi/hpimsgx.h
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
diff --git a/sound/pci/asihpi/hpioctl.c b/sound/pci/asihpi/hpioctl.c
index a32502e796de..609156205562 100644
--- a/sound/pci/asihpi/hpioctl.c
+++ b/sound/pci/asihpi/hpioctl.c
@@ -21,6 +21,7 @@ Common Linux HPI ioctl and module probe/remove functions
#define SOURCEFILE_NAME "hpioctl.c"
#include "hpi_internal.h"
+#include "hpi_version.h"
#include "hpimsginit.h"
#include "hpidebug.h"
#include "hpimsgx.h"
@@ -33,6 +34,7 @@ Common Linux HPI ioctl and module probe/remove functions
#include <asm/uaccess.h>
#include <linux/pci.h>
#include <linux/stringify.h>
+#include <linux/module.h>
#ifdef MODULE_FIRMWARE
MODULE_FIRMWARE("asihpi/dsp5000.bin");
@@ -64,9 +66,7 @@ static struct hpi_adapter adapters[HPI_MAX_ADAPTERS];
static void hpi_send_recv_f(struct hpi_message *phm, struct hpi_response *phr,
struct file *file)
{
- int adapter = phm->adapter_index;
-
- if ((adapter >= HPI_MAX_ADAPTERS || adapter < 0)
+ if ((phm->adapter_index >= HPI_MAX_ADAPTERS)
&& (phm->object != HPI_OBJ_SUBSYSTEM))
phr->error = HPI_ERROR_INVALID_OBJ_INDEX;
else
@@ -177,19 +177,14 @@ long asihpi_hpi_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
} else {
u16 __user *ptr = NULL;
u32 size = 0;
- u32 adapter_present;
/* -1=no data 0=read from user mem, 1=write to user mem */
int wrflag = -1;
- struct hpi_adapter *pa;
+ struct hpi_adapter *pa = NULL;
- if (hm->h.adapter_index < HPI_MAX_ADAPTERS) {
+ if (hm->h.adapter_index < ARRAY_SIZE(adapters))
pa = &adapters[hm->h.adapter_index];
- adapter_present = pa->type;
- } else {
- adapter_present = 0;
- }
- if (!adapter_present) {
+ if (!pa || !pa->adapter || !pa->adapter->type) {
hpi_init_response(&hr->r0, hm->h.object,
hm->h.function, HPI_ERROR_BAD_ADAPTER_NUMBER);
@@ -316,6 +311,7 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
const struct pci_device_id *pci_id)
{
int idx, nm;
+ int adapter_index;
unsigned int memlen;
struct hpi_message hm;
struct hpi_response hr;
@@ -344,8 +340,6 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
hm.adapter_index = HPI_ADAPTER_INDEX_INVALID;
- adapter.pci = pci_dev;
-
nm = HPI_MAX_ADAPTER_MEM_SPACES;
for (idx = 0; idx < nm; idx++) {
@@ -354,18 +348,16 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
if (pci_resource_flags(pci_dev, idx) & IORESOURCE_MEM) {
memlen = pci_resource_len(pci_dev, idx);
- adapter.ap_remapped_mem_base[idx] =
+ pci.ap_mem_base[idx] =
ioremap(pci_resource_start(pci_dev, idx),
memlen);
- if (!adapter.ap_remapped_mem_base[idx]) {
+ if (!pci.ap_mem_base[idx]) {
HPI_DEBUG_LOG(ERROR,
"ioremap failed, aborting\n");
/* unmap previously mapped pci mem space */
goto err;
}
}
-
- pci.ap_mem_base[idx] = adapter.ap_remapped_mem_base[idx];
}
pci.pci_dev = pci_dev;
@@ -377,6 +369,9 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
if (hr.error)
goto err;
+ adapter_index = hr.u.s.adapter_index;
+ adapter.adapter = hpi_find_adapter(adapter_index);
+
if (prealloc_stream_buf) {
adapter.p_buffer = vmalloc(prealloc_stream_buf);
if (!adapter.p_buffer) {
@@ -388,36 +383,32 @@ int __devinit asihpi_adapter_probe(struct pci_dev *pci_dev,
}
}
- adapter.index = hr.u.s.adapter_index;
- adapter.type = hr.u.s.adapter_type;
-
hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
HPI_ADAPTER_OPEN);
- hm.adapter_index = adapter.index;
+ hm.adapter_index = adapter.adapter->index;
hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
if (hr.error)
goto err;
- adapter.snd_card_asihpi = NULL;
/* WARNING can't init mutex in 'adapter'
* and then copy it to adapters[] ?!?!
*/
- adapters[adapter.index] = adapter;
- mutex_init(&adapters[adapter.index].mutex);
- pci_set_drvdata(pci_dev, &adapters[adapter.index]);
+ adapters[adapter_index] = adapter;
+ mutex_init(&adapters[adapter_index].mutex);
+ pci_set_drvdata(pci_dev, &adapters[adapter_index]);
dev_printk(KERN_INFO, &pci_dev->dev,
- "probe succeeded for ASI%04X HPI index %d\n", adapter.type,
- adapter.index);
+ "probe succeeded for ASI%04X HPI index %d\n",
+ adapter.adapter->type, adapter_index);
return 0;
err:
for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
- if (adapter.ap_remapped_mem_base[idx]) {
- iounmap(adapter.ap_remapped_mem_base[idx]);
- adapter.ap_remapped_mem_base[idx] = NULL;
+ if (pci.ap_mem_base[idx]) {
+ iounmap(pci.ap_mem_base[idx]);
+ pci.ap_mem_base[idx] = NULL;
}
}
@@ -436,19 +427,20 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
struct hpi_message hm;
struct hpi_response hr;
struct hpi_adapter *pa;
+ struct hpi_pci pci;
+
pa = pci_get_drvdata(pci_dev);
+ pci = pa->adapter->pci;
hpi_init_message_response(&hm, &hr, HPI_OBJ_ADAPTER,
HPI_ADAPTER_DELETE);
- hm.adapter_index = pa->index;
+ hm.adapter_index = pa->adapter->index;
hpi_send_recv_ex(&hm, &hr, HOWNER_KERNEL);
/* unmap PCI memory space, mapped during device init. */
for (idx = 0; idx < HPI_MAX_ADAPTER_MEM_SPACES; idx++) {
- if (pa->ap_remapped_mem_base[idx]) {
- iounmap(pa->ap_remapped_mem_base[idx]);
- pa->ap_remapped_mem_base[idx] = NULL;
- }
+ if (pci.ap_mem_base[idx])
+ iounmap(pci.ap_mem_base[idx]);
}
if (pa->p_buffer)
@@ -460,7 +452,7 @@ void __devexit asihpi_adapter_remove(struct pci_dev *pci_dev)
"remove %04x:%04x,%04x:%04x,%04x," " HPI index %d.\n",
pci_dev->vendor, pci_dev->device,
pci_dev->subsystem_vendor, pci_dev->subsystem_device,
- pci_dev->devfn, pa->index);
+ pci_dev->devfn, pa->adapter->index);
memset(pa, 0, sizeof(*pa));
}
diff --git a/sound/pci/asihpi/hpioctl.h b/sound/pci/asihpi/hpioctl.h
index 847f72f03fe1..2614aff672e2 100644
--- a/sound/pci/asihpi/hpioctl.h
+++ b/sound/pci/asihpi/hpioctl.h
@@ -1,7 +1,7 @@
/*******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
diff --git a/sound/pci/asihpi/hpios.c b/sound/pci/asihpi/hpios.c
index ff2a19b544fa..2d7d1c2e1d0d 100644
--- a/sound/pci/asihpi/hpios.c
+++ b/sound/pci/asihpi/hpios.c
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
diff --git a/sound/pci/asihpi/hpios.h b/sound/pci/asihpi/hpios.h
index 2f605e34bad0..c5cef113c209 100644
--- a/sound/pci/asihpi/hpios.h
+++ b/sound/pci/asihpi/hpios.h
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
@@ -149,20 +149,18 @@ static inline void cond_unlock(struct hpios_spinlock *l)
#define hpios_alistlock_lock(obj) spin_lock(&((obj)->list_lock.lock))
#define hpios_alistlock_unlock(obj) spin_unlock(&((obj)->list_lock.lock))
+struct snd_card;
+
+/** pci drvdata points to an instance of this struct */
struct hpi_adapter {
+ struct hpi_adapter_obj *adapter;
+ struct snd_card *snd_card;
+
/* mutex prevents contention for one card
between multiple user programs (via ioctl) */
struct mutex mutex;
- u16 index;
- u16 type;
-
- /* ALSA card structure */
- void *snd_card_asihpi;
-
char *p_buffer;
size_t buffer_size;
- struct pci_dev *pci;
- void __iomem *ap_remapped_mem_base[HPI_MAX_ADAPTER_MEM_SPACES];
};
#endif
diff --git a/sound/pci/asihpi/hpipcida.h b/sound/pci/asihpi/hpipcida.h
index bb30868ce1a3..db570ddf64b3 100644
--- a/sound/pci/asihpi/hpipcida.h
+++ b/sound/pci/asihpi/hpipcida.h
@@ -1,7 +1,7 @@
/******************************************************************************
AudioScience HPI driver
- Copyright (C) 1997-2010 AudioScience Inc. <support@audioscience.com>
+ Copyright (C) 1997-2011 AudioScience Inc. <support@audioscience.com>
This program is free software; you can redistribute it and/or modify
it under the terms of version 2 of the GNU General Public License as
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 537e0a2cc68a..590682f115ef 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -25,7 +25,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -43,7 +43,7 @@ static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
static int ac97_clock = 48000;
static char *ac97_quirk;
-static int spdif_aclink = 1;
+static bool spdif_aclink = 1;
static int ac97_codec = -1;
module_param(index, int, 0444);
@@ -60,7 +60,7 @@ module_param(spdif_aclink, bool, 0444);
MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
/* just for backward compatibility */
-static int enable;
+static bool enable;
module_param(enable, bool, 0444);
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index 45df275c8248..524d35f31232 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -25,7 +25,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -51,7 +51,7 @@ module_param(ac97_clock, int, 0444);
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
/* just for backward compatibility */
-static int enable;
+static bool enable;
module_param(enable, bool, 0444);
diff --git a/sound/pci/au88x0/au88x0.c b/sound/pci/au88x0/au88x0.c
index a38469986885..f13ad536b2d5 100644
--- a/sound/pci/au88x0/au88x0.c
+++ b/sound/pci/au88x0/au88x0.c
@@ -19,14 +19,14 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <sound/initval.h>
// module parameters (see "Module Parameters")
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static int pcifix[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 255 };
module_param_array(index, int, NULL, 0444);
@@ -268,8 +268,14 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
card->shortname, chip->io, chip->irq);
// (4) Alloc components.
+ err = snd_vortex_mixer(chip);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
// ADB pcm.
- if ((err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_ADB)) < 0) {
+ err = snd_vortex_new_pcm(chip, VORTEX_PCM_ADB, NR_PCM);
+ if (err < 0) {
snd_card_free(card);
return err;
}
@@ -299,11 +305,6 @@ snd_vortex_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
return err;
}
#endif
- // snd_ac97_mixer and Vortex mixer.
- if ((err = snd_vortex_mixer(chip)) < 0) {
- snd_card_free(card);
- return err;
- }
if ((err = snd_vortex_midi(chip)) < 0) {
snd_card_free(card);
return err;
diff --git a/sound/pci/au88x0/au88x0.h b/sound/pci/au88x0/au88x0.h
index 02f6e08f7592..466a5c8e8354 100644
--- a/sound/pci/au88x0/au88x0.h
+++ b/sound/pci/au88x0/au88x0.h
@@ -26,7 +26,7 @@
#include <sound/mpu401.h>
#include <sound/hwdep.h>
#include <sound/ac97_codec.h>
-
+#include <sound/tlv.h>
#endif
#ifndef CHIP_AU8820
@@ -105,6 +105,15 @@
#define MIX_SPDIF(x) (vortex->mixspdif[x])
#define NR_WTPB 0x20 /* WT channels per each bank. */
+#define NR_PCM 0x10
+
+struct pcm_vol {
+ struct snd_kcontrol *kctl;
+ int active;
+ int dma;
+ int mixin[4];
+ int vol[4];
+};
/* Structs */
typedef struct {
@@ -167,6 +176,7 @@ struct snd_vortex {
/* Xtalk canceler */
int xt_mode; /* 1: speakers, 0:headphones. */
#endif
+ struct pcm_vol pcm_vol[NR_PCM];
int isquad; /* cache of extended ID codec flag. */
@@ -238,7 +248,7 @@ static int vortex_alsafmt_aspfmt(int alsafmt);
/* Connection stuff. */
static void vortex_connect_default(vortex_t * vortex, int en);
static int vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch,
- int dir, int type);
+ int dir, int type, int subdev);
static char vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out,
int restype);
#ifndef CHIP_AU8810
diff --git a/sound/pci/au88x0/au88x0_core.c b/sound/pci/au88x0/au88x0_core.c
index 489150380eac..525f881f0409 100644
--- a/sound/pci/au88x0/au88x0_core.c
+++ b/sound/pci/au88x0/au88x0_core.c
@@ -805,7 +805,7 @@ static void vortex_fifo_setadbvalid(vortex_t * vortex, int fifo, int en)
}
static void
-vortex_fifo_setadbctrl(vortex_t * vortex, int fifo, int b, int priority,
+vortex_fifo_setadbctrl(vortex_t * vortex, int fifo, int stereo, int priority,
int empty, int valid, int f)
{
int temp, lifeboat = 0;
@@ -837,7 +837,7 @@ vortex_fifo_setadbctrl(vortex_t * vortex, int fifo, int b, int priority,
#else
temp = (this_4 & 0x3f) << 0xc;
#endif
- temp = (temp & 0xfffffffd) | ((b & 1) << 1);
+ temp = (temp & 0xfffffffd) | ((stereo & 1) << 1);
temp = (temp & 0xfffffff3) | ((priority & 3) << 2);
temp = (temp & 0xffffffef) | ((valid & 1) << 4);
temp |= FIFO_U1;
@@ -1148,11 +1148,11 @@ vortex_adbdma_setbuffers(vortex_t * vortex, int adbdma,
static void
vortex_adbdma_setmode(vortex_t * vortex, int adbdma, int ie, int dir,
- int fmt, int d, u32 offset)
+ int fmt, int stereo, u32 offset)
{
stream_t *dma = &vortex->dma_adb[adbdma];
- dma->dma_unknown = d;
+ dma->dma_unknown = stereo;
dma->dma_ctrl =
((offset & OFFSET_MASK) | (dma->dma_ctrl & ~OFFSET_MASK));
/* Enable PCMOUT interrupts. */
@@ -1336,7 +1336,6 @@ static void vortex_adbdma_pausefifo(vortex_t * vortex, int adbdma)
dma->fifo_status = FIFO_PAUSE;
}
-#if 0 // Using pause instead
static void vortex_adbdma_stopfifo(vortex_t * vortex, int adbdma)
{
stream_t *dma = &vortex->dma_adb[adbdma];
@@ -1351,7 +1350,6 @@ static void vortex_adbdma_stopfifo(vortex_t * vortex, int adbdma)
dma->fifo_enabled = 0;
}
-#endif
/* WTDMA */
#ifndef CHIP_AU8810
@@ -2052,8 +2050,6 @@ vortex_adb_checkinout(vortex_t * vortex, int resmap[], int out, int restype)
}
/* Default Connections */
-static int
-vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type);
static void vortex_connect_default(vortex_t * vortex, int en)
{
@@ -2113,15 +2109,13 @@ static void vortex_connect_default(vortex_t * vortex, int en)
Return: Return allocated DMA or same DMA passed as "dma" when dma >= 0.
*/
static int
-vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
+vortex_adb_allocroute(vortex_t *vortex, int dma, int nr_ch, int dir,
+ int type, int subdev)
{
stream_t *stream;
int i, en;
+ struct pcm_vol *p;
- if ((nr_ch == 3)
- || ((dir == SNDRV_PCM_STREAM_CAPTURE) && (nr_ch > 2)))
- return -EBUSY;
-
if (dma >= 0) {
en = 0;
vortex_adb_checkinout(vortex,
@@ -2252,6 +2246,14 @@ vortex_adb_allocroute(vortex_t * vortex, int dma, int nr_ch, int dir, int type)
MIX_DEFIGAIN);
#endif
}
+ if (stream->type == VORTEX_PCM_ADB && en) {
+ p = &vortex->pcm_vol[subdev];
+ p->dma = dma;
+ for (i = 0; i < nr_ch; i++)
+ p->mixin[i] = mix[i];
+ for (i = 0; i < ch_top; i++)
+ p->vol[i] = 0;
+ }
}
#ifndef CHIP_AU8820
else {
@@ -2475,7 +2477,7 @@ static irqreturn_t vortex_interrupt(int irq, void *dev_id)
hwread(vortex->mmio, VORTEX_IRQ_STAT);
handled = 1;
}
- if (source & IRQ_MIDI) {
+ if ((source & IRQ_MIDI) && vortex->rmidi) {
snd_mpu401_uart_interrupt(vortex->irq,
vortex->rmidi->private_data);
handled = 1;
diff --git a/sound/pci/au88x0/au88x0_game.c b/sound/pci/au88x0/au88x0_game.c
index e291aa59742e..c07c792bde8d 100644
--- a/sound/pci/au88x0/au88x0_game.c
+++ b/sound/pci/au88x0/au88x0_game.c
@@ -34,6 +34,7 @@
#include <sound/core.h>
#include "au88x0.h"
#include <linux/gameport.h>
+#include <linux/export.h>
#if defined(CONFIG_GAMEPORT) || (defined(MODULE) && defined(CONFIG_GAMEPORT_MODULE))
diff --git a/sound/pci/au88x0/au88x0_mpu401.c b/sound/pci/au88x0/au88x0_mpu401.c
index 0dc8d259d1ed..e6c6a0febb75 100644
--- a/sound/pci/au88x0/au88x0_mpu401.c
+++ b/sound/pci/au88x0/au88x0_mpu401.c
@@ -84,7 +84,7 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
#ifdef VORTEX_MPU401_LEGACY
if ((temp =
snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_MPU401, 0x330,
- 0, 0, 0, &rmidi)) != 0) {
+ MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) {
hwwrite(vortex->mmio, VORTEX_CTRL,
(hwread(vortex->mmio, VORTEX_CTRL) &
~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
@@ -94,8 +94,8 @@ static int __devinit snd_vortex_midi(vortex_t * vortex)
port = (unsigned long)(vortex->mmio + VORTEX_MIDI_DATA);
if ((temp =
snd_mpu401_uart_new(vortex->card, 0, MPU401_HW_AUREAL, port,
- MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO,
- 0, 0, &rmidi)) != 0) {
+ MPU401_INFO_INTEGRATED | MPU401_INFO_MMIO |
+ MPU401_INFO_IRQ_HOOK, -1, &rmidi)) != 0) {
hwwrite(vortex->mmio, VORTEX_CTRL,
(hwread(vortex->mmio, VORTEX_CTRL) &
~CTRL_MIDI_PORT) & ~CTRL_MIDI_EN);
diff --git a/sound/pci/au88x0/au88x0_pcm.c b/sound/pci/au88x0/au88x0_pcm.c
index c5f7ae46afef..e59f120742a4 100644
--- a/sound/pci/au88x0/au88x0_pcm.c
+++ b/sound/pci/au88x0/au88x0_pcm.c
@@ -122,6 +122,18 @@ static struct snd_pcm_hw_constraint_list hw_constraints_au8830_channels = {
.mask = 0,
};
#endif
+
+static void vortex_notify_pcm_vol_change(struct snd_card *card,
+ struct snd_kcontrol *kctl, int activate)
+{
+ if (activate)
+ kctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ else
+ kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ snd_ctl_notify(card, SNDRV_CTL_EVENT_MASK_VALUE |
+ SNDRV_CTL_EVENT_MASK_INFO, &(kctl->id));
+}
+
/* open callback */
static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
{
@@ -168,6 +180,7 @@ static int snd_vortex_pcm_open(struct snd_pcm_substream *substream)
runtime->hw = snd_vortex_playback_hw_adb;
#ifdef CHIP_AU8830
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
+ VORTEX_IS_QUAD(vortex) &&
VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
runtime->hw.channels_max = 4;
snd_pcm_hw_constraint_list(runtime, 0,
@@ -229,12 +242,14 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
if (stream != NULL)
vortex_adb_allocroute(chip, stream->dma,
stream->nr_ch, stream->dir,
- stream->type);
+ stream->type,
+ substream->number);
/* Alloc routes. */
dma =
vortex_adb_allocroute(chip, -1,
params_channels(hw_params),
- substream->stream, type);
+ substream->stream, type,
+ substream->number);
if (dma < 0) {
spin_unlock_irq(&chip->lock);
return dma;
@@ -245,6 +260,11 @@ snd_vortex_pcm_hw_params(struct snd_pcm_substream *substream,
vortex_adbdma_setbuffers(chip, dma,
params_period_bytes(hw_params),
params_periods(hw_params));
+ if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
+ chip->pcm_vol[substream->number].active = 1;
+ vortex_notify_pcm_vol_change(chip->card,
+ chip->pcm_vol[substream->number].kctl, 1);
+ }
}
#ifndef CHIP_AU8810
else {
@@ -274,10 +294,18 @@ static int snd_vortex_pcm_hw_free(struct snd_pcm_substream *substream)
spin_lock_irq(&chip->lock);
// Delete audio routes.
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
- if (stream != NULL)
+ if (stream != NULL) {
+ if (VORTEX_PCM_TYPE(substream->pcm) == VORTEX_PCM_ADB) {
+ chip->pcm_vol[substream->number].active = 0;
+ vortex_notify_pcm_vol_change(chip->card,
+ chip->pcm_vol[substream->number].kctl,
+ 0);
+ }
vortex_adb_allocroute(chip, stream->dma,
stream->nr_ch, stream->dir,
- stream->type);
+ stream->type,
+ substream->number);
+ }
}
#ifndef CHIP_AU8810
else {
@@ -307,8 +335,8 @@ static int snd_vortex_pcm_prepare(struct snd_pcm_substream *substream)
fmt = vortex_alsafmt_aspfmt(runtime->format);
spin_lock_irq(&chip->lock);
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT) {
- vortex_adbdma_setmode(chip, dma, 1, dir, fmt, 0 /*? */ ,
- 0);
+ vortex_adbdma_setmode(chip, dma, 1, dir, fmt,
+ runtime->channels == 1 ? 0 : 1, 0);
vortex_adbdma_setstartbuffer(chip, dma, 0);
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_SPDIF)
vortex_adb_setsrc(chip, dma, runtime->rate, dir);
@@ -353,8 +381,7 @@ static int snd_vortex_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
//printk(KERN_INFO "vortex: stop %d\n", dma);
stream->fifo_enabled = 0;
if (VORTEX_PCM_TYPE(substream->pcm) != VORTEX_PCM_WT)
- vortex_adbdma_pausefifo(chip, dma);
- //vortex_adbdma_stopfifo(chip, dma);
+ vortex_adbdma_stopfifo(chip, dma);
#ifndef CHIP_AU8810
else {
printk(KERN_INFO "vortex: wt stop %d\n", dma);
@@ -506,6 +533,83 @@ static struct snd_kcontrol_new snd_vortex_mixer_spdif[] __devinitdata = {
},
};
+/* subdevice PCM Volume control */
+
+static int snd_vortex_pcm_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
+ uinfo->value.integer.min = -128;
+ uinfo->value.integer.max = 32;
+ return 0;
+}
+
+static int snd_vortex_pcm_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int i;
+ vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+ int subdev = kcontrol->id.subdevice;
+ struct pcm_vol *p = &vortex->pcm_vol[subdev];
+ int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
+ for (i = 0; i < max_chn; i++)
+ ucontrol->value.integer.value[i] = p->vol[i];
+ return 0;
+}
+
+static int snd_vortex_pcm_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int i;
+ int changed = 0;
+ int mixin;
+ unsigned char vol;
+ vortex_t *vortex = snd_kcontrol_chip(kcontrol);
+ int subdev = kcontrol->id.subdevice;
+ struct pcm_vol *p = &vortex->pcm_vol[subdev];
+ int max_chn = (VORTEX_IS_QUAD(vortex) ? 4 : 2);
+ for (i = 0; i < max_chn; i++) {
+ if (p->vol[i] != ucontrol->value.integer.value[i]) {
+ p->vol[i] = ucontrol->value.integer.value[i];
+ if (p->active) {
+ switch (vortex->dma_adb[p->dma].nr_ch) {
+ case 1:
+ mixin = p->mixin[0];
+ break;
+ case 2:
+ default:
+ mixin = p->mixin[(i < 2) ? i : (i - 2)];
+ break;
+ case 4:
+ mixin = p->mixin[i];
+ break;
+ };
+ vol = p->vol[i];
+ vortex_mix_setinputvolumebyte(vortex,
+ vortex->mixplayb[i], mixin, vol);
+ }
+ changed = 1;
+ }
+ }
+ return changed;
+}
+
+static const DECLARE_TLV_DB_MINMAX(vortex_pcm_vol_db_scale, -9600, 2400);
+
+static struct snd_kcontrol_new snd_vortex_pcm_vol __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "PCM Playback Volume",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE,
+ .info = snd_vortex_pcm_vol_info,
+ .get = snd_vortex_pcm_vol_get,
+ .put = snd_vortex_pcm_vol_put,
+ .tlv = { .p = vortex_pcm_vol_db_scale },
+};
+
/* create a pcm device */
static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
{
@@ -555,5 +659,20 @@ static int __devinit snd_vortex_new_pcm(vortex_t *chip, int idx, int nr)
return err;
}
}
+ if (VORTEX_PCM_TYPE(pcm) == VORTEX_PCM_ADB) {
+ for (i = 0; i < NR_PCM; i++) {
+ chip->pcm_vol[i].active = 0;
+ chip->pcm_vol[i].dma = -1;
+ kctl = snd_ctl_new1(&snd_vortex_pcm_vol, chip);
+ if (!kctl)
+ return -ENOMEM;
+ chip->pcm_vol[i].kctl = kctl;
+ kctl->id.device = 0;
+ kctl->id.subdevice = i;
+ err = snd_ctl_add(chip->card, kctl);
+ if (err < 0)
+ return err;
+ }
+ }
return 0;
}
diff --git a/sound/pci/au88x0/au88x0_xtalk.c b/sound/pci/au88x0/au88x0_xtalk.c
index b4151e208b71..b278e285fd40 100644
--- a/sound/pci/au88x0/au88x0_xtalk.c
+++ b/sound/pci/au88x0/au88x0_xtalk.c
@@ -48,43 +48,61 @@ static unsigned short const wXtalkNarrowLeftDelay = 0x7;
static unsigned short const wXtalkNarrowRightDelay = 0x7;
static xtalk_gains_t const asXtalkGainsDefault = {
- 0x4000, 0x4000, 4000, 0x4000, 4000, 0x4000, 4000, 0x4000, 4000,
- 0x4000
+ 0x4000, 0x4000, 0x4000, 0x4000, 0x4000,
+ 0x4000, 0x4000, 0x4000, 0x4000, 0x4000
};
static xtalk_gains_t const asXtalkGainsTest = {
- 0x8000, 0x7FFF, 0, 0xFFFF, 0x0001, 0xC000, 0x4000, 0xFFFE, 0x0002,
- 0
+ 0x7fff, 0x8000, 0x0000, 0x0000, 0x0001,
+ 0xffff, 0x4000, 0xc000, 0x0002, 0xfffe
};
+
static xtalk_gains_t const asXtalkGains1Chan = {
- 0x7FFF, 0, 0, 0, 0x7FFF, 0, 0, 0, 0, 0
+ 0x7FFF, 0, 0, 0, 0,
+ 0x7FFF, 0, 0, 0, 0,
};
// Input gain for 4 A3D slices. One possible input pair is left zero.
static xtalk_gains_t const asXtalkGainsAllChan = {
- 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0, 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF,
- 0
- //0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff,0x7FFF,0x7FFF,0x7FFF,0x7FFF,0x7fff
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0,
+ 0x7FFF, 0x7FFF, 0x7FFF, 0x7FFF, 0
+};
+
+static xtalk_gains_t const asXtalkGainsZeros = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-static xtalk_gains_t const asXtalkGainsZeros;
-static xtalk_dline_t const alXtalkDlineZeros;
+static xtalk_dline_t const alXtalkDlineZeros = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
static xtalk_dline_t const alXtalkDlineTest = {
- 0xFC18, 0x03E8FFFF, 0x186A0, 0x7960FFFE, 1, 0xFFFFFFFF,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0x0000fc18, 0xfff03e8, 0x000186a0, 0xfffe7960, 1, 0xffffffff, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+static xtalk_instate_t const asXtalkInStateZeros = {
0, 0, 0, 0
};
-static xtalk_instate_t const asXtalkInStateZeros;
-static xtalk_instate_t const asXtalkInStateTest =
- { 0xFF80, 0x0080, 0xFFFF, 0x0001 };
-static xtalk_state_t const asXtalkOutStateZeros;
+static xtalk_instate_t const asXtalkInStateTest = {
+ 0x0080, 0xff80, 0x0001, 0xffff
+};
+
+static xtalk_state_t const asXtalkOutStateZeros = {
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0},
+ {0, 0, 0, 0}
+};
static short const sDiamondKLeftEq = 0x401d;
static short const sDiamondKRightEq = 0x401d;
static short const sDiamondKLeftXt = 0xF90E;
static short const sDiamondKRightXt = 0xF90E;
-static short const sDiamondShiftLeftEq = 1; /* 0xF90E Is this a bug ??? */
+static short const sDiamondShiftLeftEq = 1;
static short const sDiamondShiftRightEq = 1;
static short const sDiamondShiftLeftXt = 0;
static short const sDiamondShiftRightXt = 0;
@@ -94,29 +112,29 @@ static unsigned short const wDiamondRightDelay = 0xb;
static xtalk_coefs_t const asXtalkWideCoefsLeftEq = {
{0xEC4C, 0xDCE9, 0xFDC2, 0xFEEC, 0},
{0x5F60, 0xCBCB, 0xFC26, 0x0305, 0},
- {0x340B, 0xf504, 0x6CE8, 0x0D23, 0x00E4},
- {0xD500, 0x8D76, 0xACC7, 0x5B05, 0x00FA},
+ {0x340B, 0xe8f5, 0x236c, 0xe40d, 0},
+ {0x76d5, 0xc78d, 0x05ac, 0xfa5b, 0},
{0x7F04, 0xC0FA, 0x0263, 0xFDA2, 0}
};
static xtalk_coefs_t const asXtalkWideCoefsRightEq = {
{0xEC4C, 0xDCE9, 0xFDC2, 0xFEEC, 0},
{0x5F60, 0xCBCB, 0xFC26, 0x0305, 0},
- {0x340B, 0xF504, 0x6CE8, 0x0D23, 0x00E4},
- {0xD500, 0x8D76, 0xACC7, 0x5B05, 0x00FA},
+ {0x340B, 0xe8f5, 0x236c, 0xe40d, 0},
+ {0x76d5, 0xc78d, 0x05ac, 0xfa5b, 0},
{0x7F04, 0xC0FA, 0x0263, 0xFDA2, 0}
};
static xtalk_coefs_t const asXtalkWideCoefsLeftXt = {
- {0x86C3, 0x7B55, 0x89C3, 0x005B, 0x0047},
- {0x6000, 0x206A, 0xC6CA, 0x40FF, 0},
- {0x1100, 0x1164, 0xA1D7, 0x90FC, 0x0001},
- {0xDC00, 0x9E77, 0xB8C7, 0x0AFF, 0},
+ {0x55c6, 0xc97b, 0x005b, 0x0047, 0},
+ {0x6a60, 0xca20, 0xffc6, 0x0040, 0},
+ {0x6411, 0xd711, 0xfca1, 0x0190, 0},
+ {0x77dc, 0xc79e, 0xffb8, 0x000a, 0},
{0, 0, 0, 0, 0}
};
static xtalk_coefs_t const asXtalkWideCoefsRightXt = {
- {0x86C3, 0x7B55, 0x89C3, 0x005B, 0x0047},
- {0x6000, 0x206A, 0xC6CA, 0x40FF, 0},
- {0x1100, 0x1164, 0xA1D7, 0x90FC, 0x0001},
- {0xDC00, 0x9E77, 0xB8C7, 0x0AFF, 0},
+ {0x55c6, 0xc97b, 0x005b, 0x0047, 0},
+ {0x6a60, 0xca20, 0xffc6, 0x0040, 0},
+ {0x6411, 0xd711, 0xfca1, 0x0190, 0},
+ {0x77dc, 0xc79e, 0xffb8, 0x000a, 0},
{0, 0, 0, 0, 0}
};
static xtalk_coefs_t const asXtalkNarrowCoefsLeftEq = {
@@ -151,7 +169,14 @@ static xtalk_coefs_t const asXtalkNarrowCoefsRightXt = {
{0, 0, 0, 0, 0}
};
-static xtalk_coefs_t const asXtalkCoefsZeros;
+static xtalk_coefs_t const asXtalkCoefsZeros = {
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0}
+};
+
static xtalk_coefs_t const asXtalkCoefsPipe = {
{0, 0, 0x0FA0, 0, 0},
{0, 0, 0x0FA0, 0, 0},
@@ -186,7 +211,7 @@ static xtalk_coefs_t const asXtalkCoefsDenTest = {
static xtalk_state_t const asXtalkOutStateTest = {
{0x7FFF, 0x0004, 0xFFFC, 0},
{0xFE00, 0x0008, 0xFFF8, 0x4000},
- {0x200, 0x0010, 0xFFF0, 0xC000},
+ {0x0200, 0x0010, 0xFFF0, 0xC000},
{0x8000, 0x0020, 0xFFE0, 0},
{0, 0, 0, 0}
};
@@ -306,10 +331,10 @@ vortex_XtalkHw_SetLeftEQStates(vortex_t * vortex,
hwwrite(vortex->mmio, 0x2421C + i * 0x24, coefs[i][2]);
hwwrite(vortex->mmio, 0x24220 + i * 0x24, coefs[i][3]);
}
- hwwrite(vortex->mmio, 0x244F8 + i * 0x24, arg_0[0]);
- hwwrite(vortex->mmio, 0x244FC + i * 0x24, arg_0[1]);
- hwwrite(vortex->mmio, 0x24500 + i * 0x24, arg_0[2]);
- hwwrite(vortex->mmio, 0x24504 + i * 0x24, arg_0[3]);
+ hwwrite(vortex->mmio, 0x244F8, arg_0[0]);
+ hwwrite(vortex->mmio, 0x244FC, arg_0[1]);
+ hwwrite(vortex->mmio, 0x24500, arg_0[2]);
+ hwwrite(vortex->mmio, 0x24504, arg_0[3]);
}
static void
@@ -325,10 +350,10 @@ vortex_XtalkHw_SetRightEQStates(vortex_t * vortex,
hwwrite(vortex->mmio, 0x242D0 + i * 0x24, coefs[i][2]);
hwwrite(vortex->mmio, 0x244D4 + i * 0x24, coefs[i][3]);
}
- hwwrite(vortex->mmio, 0x24508 + i * 0x24, arg_0[0]);
- hwwrite(vortex->mmio, 0x2450C + i * 0x24, arg_0[1]);
- hwwrite(vortex->mmio, 0x24510 + i * 0x24, arg_0[2]);
- hwwrite(vortex->mmio, 0x24514 + i * 0x24, arg_0[3]);
+ hwwrite(vortex->mmio, 0x24508, arg_0[0]);
+ hwwrite(vortex->mmio, 0x2450C, arg_0[1]);
+ hwwrite(vortex->mmio, 0x24510, arg_0[2]);
+ hwwrite(vortex->mmio, 0x24514, arg_0[3]);
}
static void
@@ -344,10 +369,10 @@ vortex_XtalkHw_SetLeftXTStates(vortex_t * vortex,
hwwrite(vortex->mmio, 0x24384 + i * 0x24, coefs[i][2]);
hwwrite(vortex->mmio, 0x24388 + i * 0x24, coefs[i][3]);
}
- hwwrite(vortex->mmio, 0x24518 + i * 0x24, arg_0[0]);
- hwwrite(vortex->mmio, 0x2451C + i * 0x24, arg_0[1]);
- hwwrite(vortex->mmio, 0x24520 + i * 0x24, arg_0[2]);
- hwwrite(vortex->mmio, 0x24524 + i * 0x24, arg_0[3]);
+ hwwrite(vortex->mmio, 0x24518, arg_0[0]);
+ hwwrite(vortex->mmio, 0x2451C, arg_0[1]);
+ hwwrite(vortex->mmio, 0x24520, arg_0[2]);
+ hwwrite(vortex->mmio, 0x24524, arg_0[3]);
}
static void
@@ -363,10 +388,10 @@ vortex_XtalkHw_SetRightXTStates(vortex_t * vortex,
hwwrite(vortex->mmio, 0x24438 + i * 0x24, coefs[i][2]);
hwwrite(vortex->mmio, 0x2443C + i * 0x24, coefs[i][3]);
}
- hwwrite(vortex->mmio, 0x24528 + i * 0x24, arg_0[0]);
- hwwrite(vortex->mmio, 0x2452C + i * 0x24, arg_0[1]);
- hwwrite(vortex->mmio, 0x24530 + i * 0x24, arg_0[2]);
- hwwrite(vortex->mmio, 0x24534 + i * 0x24, arg_0[3]);
+ hwwrite(vortex->mmio, 0x24528, arg_0[0]);
+ hwwrite(vortex->mmio, 0x2452C, arg_0[1]);
+ hwwrite(vortex->mmio, 0x24530, arg_0[2]);
+ hwwrite(vortex->mmio, 0x24534, arg_0[3]);
}
#if 0
@@ -450,10 +475,10 @@ vortex_XtalkHw_GetLeftEQStates(vortex_t * vortex, xtalk_instate_t arg_0,
coefs[i][2] = hwread(vortex->mmio, 0x2421C + i * 0x24);
coefs[i][3] = hwread(vortex->mmio, 0x24220 + i * 0x24);
}
- arg_0[0] = hwread(vortex->mmio, 0x244F8 + i * 0x24);
- arg_0[1] = hwread(vortex->mmio, 0x244FC + i * 0x24);
- arg_0[2] = hwread(vortex->mmio, 0x24500 + i * 0x24);
- arg_0[3] = hwread(vortex->mmio, 0x24504 + i * 0x24);
+ arg_0[0] = hwread(vortex->mmio, 0x244F8);
+ arg_0[1] = hwread(vortex->mmio, 0x244FC);
+ arg_0[2] = hwread(vortex->mmio, 0x24500);
+ arg_0[3] = hwread(vortex->mmio, 0x24504);
}
static void
@@ -468,10 +493,10 @@ vortex_XtalkHw_GetRightEQStates(vortex_t * vortex, xtalk_instate_t arg_0,
coefs[i][2] = hwread(vortex->mmio, 0x242D0 + i * 0x24);
coefs[i][3] = hwread(vortex->mmio, 0x242D4 + i * 0x24);
}
- arg_0[0] = hwread(vortex->mmio, 0x24508 + i * 0x24);
- arg_0[1] = hwread(vortex->mmio, 0x2450C + i * 0x24);
- arg_0[2] = hwread(vortex->mmio, 0x24510 + i * 0x24);
- arg_0[3] = hwread(vortex->mmio, 0x24514 + i * 0x24);
+ arg_0[0] = hwread(vortex->mmio, 0x24508);
+ arg_0[1] = hwread(vortex->mmio, 0x2450C);
+ arg_0[2] = hwread(vortex->mmio, 0x24510);
+ arg_0[3] = hwread(vortex->mmio, 0x24514);
}
static void
@@ -486,10 +511,10 @@ vortex_XtalkHw_GetLeftXTStates(vortex_t * vortex, xtalk_instate_t arg_0,
coefs[i][2] = hwread(vortex->mmio, 0x24384 + i * 0x24);
coefs[i][3] = hwread(vortex->mmio, 0x24388 + i * 0x24);
}
- arg_0[0] = hwread(vortex->mmio, 0x24518 + i * 0x24);
- arg_0[1] = hwread(vortex->mmio, 0x2451C + i * 0x24);
- arg_0[2] = hwread(vortex->mmio, 0x24520 + i * 0x24);
- arg_0[3] = hwread(vortex->mmio, 0x24524 + i * 0x24);
+ arg_0[0] = hwread(vortex->mmio, 0x24518);
+ arg_0[1] = hwread(vortex->mmio, 0x2451C);
+ arg_0[2] = hwread(vortex->mmio, 0x24520);
+ arg_0[3] = hwread(vortex->mmio, 0x24524);
}
static void
@@ -504,10 +529,10 @@ vortex_XtalkHw_GetRightXTStates(vortex_t * vortex, xtalk_instate_t arg_0,
coefs[i][2] = hwread(vortex->mmio, 0x24438 + i * 0x24);
coefs[i][3] = hwread(vortex->mmio, 0x2443C + i * 0x24);
}
- arg_0[0] = hwread(vortex->mmio, 0x24528 + i * 0x24);
- arg_0[1] = hwread(vortex->mmio, 0x2452C + i * 0x24);
- arg_0[2] = hwread(vortex->mmio, 0x24530 + i * 0x24);
- arg_0[3] = hwread(vortex->mmio, 0x24534 + i * 0x24);
+ arg_0[0] = hwread(vortex->mmio, 0x24528);
+ arg_0[1] = hwread(vortex->mmio, 0x2452C);
+ arg_0[2] = hwread(vortex->mmio, 0x24530);
+ arg_0[3] = hwread(vortex->mmio, 0x24534);
}
#endif
diff --git a/sound/pci/aw2/aw2-alsa.c b/sound/pci/aw2/aw2-alsa.c
index f8569b11331b..1c5231931462 100644
--- a/sound/pci/aw2/aw2-alsa.c
+++ b/sound/pci/aw2/aw2-alsa.c
@@ -27,6 +27,7 @@
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
@@ -152,7 +153,7 @@ static int snd_aw2_control_switch_capture_put(struct snd_kcontrol *kcontrol,
********************************/
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Audiowerk2 soundcard.");
diff --git a/sound/pci/azt3328.c b/sound/pci/azt3328.c
index 579fc0dce128..496f14c1a731 100644
--- a/sound/pci/azt3328.c
+++ b/sound/pci/azt3328.c
@@ -186,7 +186,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/gameport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -301,7 +301,7 @@ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
module_param_array(id, charp, NULL, 0444);
MODULE_PARM_DESC(id, "ID string for AZF3328 soundcard.");
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable AZF3328 soundcard.");
@@ -2652,8 +2652,9 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
since our hardware ought to be similar, thus use same ID. */
err = snd_mpu401_uart_new(
card, 0,
- MPU401_HW_AZT2320, chip->mpu_io, MPU401_INFO_INTEGRATED,
- pci->irq, 0, &chip->rmidi
+ MPU401_HW_AZT2320, chip->mpu_io,
+ MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+ -1, &chip->rmidi
);
if (err < 0) {
snd_printk(KERN_ERR "azf3328: no MPU-401 device at 0x%lx?\n",
@@ -2683,10 +2684,9 @@ snd_azf3328_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
if (err < 0)
goto out_err;
+ opl3->private_data = chip;
}
- opl3->private_data = chip;
-
sprintf(card->longname, "%s at 0x%lx, irq %i",
card->shortname, chip->ctrl_io, chip->irq);
diff --git a/sound/pci/bt87x.c b/sound/pci/bt87x.c
index 39180335c237..62d6163fc9d9 100644
--- a/sound/pci/bt87x.c
+++ b/sound/pci/bt87x.c
@@ -25,7 +25,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/bitops.h>
#include <asm/io.h>
#include <sound/core.h>
@@ -42,9 +42,9 @@ MODULE_SUPPORTED_DEVICE("{{Brooktree,Bt878},"
static int index[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -2}; /* Exclude the first card */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int digital_rate[SNDRV_CARDS]; /* digital input rate */
-static int load_all; /* allow to load the non-whitelisted cards */
+static bool load_all; /* allow to load the non-whitelisted cards */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Bt87x soundcard");
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index 061b7e654586..08d6ebfe5a61 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -140,7 +140,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -156,7 +156,7 @@ MODULE_SUPPORTED_DEVICE("{{Creative,SB CA0106 chip}}");
// module parameters (see "Module Parameters")
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */
module_param_array(index, int, NULL, 0444);
diff --git a/sound/pci/cmipci.c b/sound/pci/cmipci.c
index 9cf99fb7eb9c..19b06269adc2 100644
--- a/sound/pci/cmipci.c
+++ b/sound/pci/cmipci.c
@@ -27,7 +27,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/info.h>
@@ -54,10 +54,10 @@ MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8738},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
static long mpu_port[SNDRV_CARDS];
static long fm_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1};
-static int soft_ac3[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1};
+static bool soft_ac3[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)]=1};
#ifdef SUPPORT_JOYSTICK
static int joystick_port[SNDRV_CARDS];
#endif
@@ -3228,8 +3228,9 @@ static int __devinit snd_cmipci_create(struct snd_card *card, struct pci_dev *pc
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
iomidi,
(integrated_midi ?
- MPU401_INFO_INTEGRATED : 0),
- cm->irq, 0, &cm->rmidi)) < 0) {
+ MPU401_INFO_INTEGRATED : 0) |
+ MPU401_INFO_IRQ_HOOK,
+ -1, &cm->rmidi)) < 0) {
printk(KERN_ERR "cmipci: no UART401 device at 0x%lx\n", iomidi);
}
}
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 07f04e390aa1..a9f368f60df6 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -26,7 +26,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
#include <sound/pcm.h>
@@ -44,8 +44,8 @@ MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,CS4281}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
-static int dual_codec[SNDRV_CARDS]; /* dual codec */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
+static bool dual_codec[SNDRV_CARDS]; /* dual codec */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for CS4281 soundcard.");
diff --git a/sound/pci/cs46xx/cs46xx.c b/sound/pci/cs46xx/cs46xx.c
index 1af95559aaaa..819d79d0586d 100644
--- a/sound/pci/cs46xx/cs46xx.c
+++ b/sound/pci/cs46xx/cs46xx.c
@@ -28,7 +28,7 @@
#include <linux/pci.h>
#include <linux/time.h>
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/cs46xx.h>
#include <sound/initval.h>
@@ -46,10 +46,10 @@ MODULE_SUPPORTED_DEVICE("{{Cirrus Logic,Sound Fusion (CS4280)},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
-static int external_amp[SNDRV_CARDS];
-static int thinkpad[SNDRV_CARDS];
-static int mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool external_amp[SNDRV_CARDS];
+static bool thinkpad[SNDRV_CARDS];
+static bool mmap_valid[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for the CS46xx soundcard.");
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 9546bf07f0d1..4fa53161b094 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -53,6 +53,7 @@
#include <linux/slab.h>
#include <linux/gameport.h>
#include <linux/mutex.h>
+#include <linux/export.h>
#include <sound/core.h>
diff --git a/sound/pci/cs5530.c b/sound/pci/cs5530.c
index a4669346d146..c47cabff2bfa 100644
--- a/sound/pci/cs5530.c
+++ b/sound/pci/cs5530.c
@@ -37,7 +37,7 @@
*/
#include <linux/delay.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/pci.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -50,7 +50,14 @@ MODULE_LICENSE("GPL");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+
+module_param_array(index, int, NULL, 0444);
+MODULE_PARM_DESC(index, "Index value for CS5530 Audio driver.");
+module_param_array(id, charp, NULL, 0444);
+MODULE_PARM_DESC(id, "ID string for CS5530 Audio driver.");
+module_param_array(enable, bool, NULL, 0444);
+MODULE_PARM_DESC(enable, "Enable CS5530 Audio driver.");
struct snd_cs5530 {
struct snd_card *card;
diff --git a/sound/pci/cs5535audio/cs5535audio.c b/sound/pci/cs5535audio/cs5535audio.c
index 10d22ed5fece..a2fb2173e980 100644
--- a/sound/pci/cs5535audio/cs5535audio.c
+++ b/sound/pci/cs5535audio/cs5535audio.c
@@ -26,7 +26,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -57,7 +57,7 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " DRIVER_NAME);
diff --git a/sound/pci/cs5535audio/cs5535audio_pcm.c b/sound/pci/cs5535audio/cs5535audio_pcm.c
index e083122ca55a..dbf94b189e75 100644
--- a/sound/pci/cs5535audio/cs5535audio_pcm.c
+++ b/sound/pci/cs5535audio/cs5535audio_pcm.c
@@ -148,7 +148,7 @@ static int cs5535audio_build_dma_packets(struct cs5535audio *cs5535au,
struct cs5535audio_dma_desc *desc =
&((struct cs5535audio_dma_desc *) dma->desc_buf.area)[i];
desc->addr = cpu_to_le32(addr);
- desc->size = cpu_to_le32(period_bytes);
+ desc->size = cpu_to_le16(period_bytes);
desc->ctlreserved = cpu_to_le16(PRD_EOP);
desc_addr += sizeof(struct cs5535audio_dma_desc);
addr += period_bytes;
diff --git a/sound/pci/ctxfi/ctpcm.c b/sound/pci/ctxfi/ctpcm.c
index 457d21189b0d..2c8622617c8c 100644
--- a/sound/pci/ctxfi/ctpcm.c
+++ b/sound/pci/ctxfi/ctpcm.c
@@ -404,7 +404,7 @@ int ct_alsa_pcm_create(struct ct_atc *atc,
int err;
int playback_count, capture_count;
- playback_count = (IEC958 == device) ? 1 : 8;
+ playback_count = (IEC958 == device) ? 1 : 256;
capture_count = (FRONT == device) ? 1 : 0;
err = snd_pcm_new(atc->card, "ctxfi", device,
playback_count, capture_count, &pcm);
diff --git a/sound/pci/ctxfi/ctsrc.c b/sound/pci/ctxfi/ctsrc.c
index c749fa720889..6e77e86307c2 100644
--- a/sound/pci/ctxfi/ctsrc.c
+++ b/sound/pci/ctxfi/ctsrc.c
@@ -20,7 +20,7 @@
#include "cthardware.h"
#include <linux/slab.h>
-#define SRC_RESOURCE_NUM 64
+#define SRC_RESOURCE_NUM 256
#define SRCIMP_RESOURCE_NUM 256
static unsigned int conj_mask;
@@ -437,7 +437,7 @@ get_src_rsc(struct src_mgr *mgr, const struct src_desc *desc, struct src **rsrc)
/* Allocate mem for master src resource */
if (MEMRD == desc->mode)
- src = kzalloc(sizeof(*src)*desc->multi, GFP_KERNEL);
+ src = kcalloc(desc->multi, sizeof(*src), GFP_KERNEL);
else
src = kzalloc(sizeof(*src), GFP_KERNEL);
diff --git a/sound/pci/ctxfi/cttimer.c b/sound/pci/ctxfi/cttimer.c
index 93b0aedc36d4..03fb909085af 100644
--- a/sound/pci/ctxfi/cttimer.c
+++ b/sound/pci/ctxfi/cttimer.c
@@ -15,8 +15,8 @@
#include "cthardware.h"
#include "cttimer.h"
-static int use_system_timer;
-MODULE_PARM_DESC(use_system_timer, "Foce to use system-timer");
+static bool use_system_timer;
+MODULE_PARM_DESC(use_system_timer, "Force to use system-timer");
module_param(use_system_timer, bool, S_IRUGO);
struct ct_timer_ops {
diff --git a/sound/pci/ctxfi/ctvmem.c b/sound/pci/ctxfi/ctvmem.c
index b78f3fc3c33c..6109490b83e8 100644
--- a/sound/pci/ctxfi/ctvmem.c
+++ b/sound/pci/ctxfi/ctvmem.c
@@ -36,7 +36,7 @@ get_vm_block(struct ct_vm *vm, unsigned int size)
size = CT_PAGE_ALIGN(size);
if (size > vm->size) {
- printk(KERN_ERR "ctxfi: Fail! No sufficient device virtural "
+ printk(KERN_ERR "ctxfi: Fail! No sufficient device virtual "
"memory space available!\n");
return NULL;
}
diff --git a/sound/pci/ctxfi/ctvmem.h b/sound/pci/ctxfi/ctvmem.h
index b23adfca4de6..e6da60eb19ce 100644
--- a/sound/pci/ctxfi/ctvmem.h
+++ b/sound/pci/ctxfi/ctvmem.h
@@ -18,7 +18,7 @@
#ifndef CTVMEM_H
#define CTVMEM_H
-#define CT_PTP_NUM 1 /* num of device page table pages */
+#define CT_PTP_NUM 4 /* num of device page table pages */
#include <linux/mutex.h>
#include <linux/list.h>
diff --git a/sound/pci/ctxfi/xfi.c b/sound/pci/ctxfi/xfi.c
index b259aa03a3a9..15d95d2bacee 100644
--- a/sound/pci/ctxfi/xfi.c
+++ b/sound/pci/ctxfi/xfi.c
@@ -12,6 +12,7 @@
#include <linux/pci.h>
#include <linux/moduleparam.h>
#include <linux/pci_ids.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include "ctatc.h"
@@ -31,7 +32,7 @@ module_param(multiple, uint, S_IRUGO);
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static unsigned int subsystem[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c
index 43c7e12bc05d..d47e72ae2ab3 100644
--- a/sound/pci/echoaudio/darla20.c
+++ b/sound/pci/echoaudio/darla20.c
@@ -40,7 +40,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c
index 95b03306e026..413acf702e3b 100644
--- a/sound/pci/echoaudio/darla24.c
+++ b/sound/pci/echoaudio/darla24.c
@@ -44,7 +44,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c
index 8723c40183e6..1ec4edca060d 100644
--- a/sound/pci/echoaudio/echo3g.c
+++ b/sound/pci/echoaudio/echo3g.c
@@ -51,7 +51,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index d7306980d0f1..595c11f904bb 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -16,6 +16,8 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+#include <linux/module.h>
+
MODULE_AUTHOR("Giuliano Pochini <pochini@shiny.it>");
MODULE_LICENSE("GPL v2");
MODULE_DESCRIPTION("Echoaudio " ECHOCARD_NAME " soundcards driver");
@@ -24,7 +26,7 @@ MODULE_DEVICE_TABLE(pci, snd_echo_ids);
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " ECHOCARD_NAME " soundcard.");
diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c
index 0058c67115df..039125b7e475 100644
--- a/sound/pci/echoaudio/gina20.c
+++ b/sound/pci/echoaudio/gina20.c
@@ -44,7 +44,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c
index 14e4925e76cc..5e966f6ffaa3 100644
--- a/sound/pci/echoaudio/gina24.c
+++ b/sound/pci/echoaudio/gina24.c
@@ -50,7 +50,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c
index f416b154f146..c166b7eea268 100644
--- a/sound/pci/echoaudio/indigo.c
+++ b/sound/pci/echoaudio/indigo.c
@@ -42,7 +42,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c
index e594a3b2766e..a3ef3b992f40 100644
--- a/sound/pci/echoaudio/indigodj.c
+++ b/sound/pci/echoaudio/indigodj.c
@@ -42,7 +42,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/indigodjx.c b/sound/pci/echoaudio/indigodjx.c
index f0d00bfceee5..f516444fc02d 100644
--- a/sound/pci/echoaudio/indigodjx.c
+++ b/sound/pci/echoaudio/indigodjx.c
@@ -42,7 +42,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/io.h>
#include <linux/slab.h>
diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c
index 1af0037304c6..c22c82fd1f99 100644
--- a/sound/pci/echoaudio/indigoio.c
+++ b/sound/pci/echoaudio/indigoio.c
@@ -43,7 +43,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/indigoiox.c b/sound/pci/echoaudio/indigoiox.c
index 0b51163452b5..86cf2d071758 100644
--- a/sound/pci/echoaudio/indigoiox.c
+++ b/sound/pci/echoaudio/indigoiox.c
@@ -43,7 +43,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/io.h>
#include <linux/slab.h>
diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c
index 3f63ab8dfff3..6a027f3931cc 100644
--- a/sound/pci/echoaudio/layla20.c
+++ b/sound/pci/echoaudio/layla20.c
@@ -49,7 +49,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c
index 283137244472..96a5991aca8f 100644
--- a/sound/pci/echoaudio/layla24.c
+++ b/sound/pci/echoaudio/layla24.c
@@ -51,7 +51,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c
index eddaeb4da50e..b8ce27e67e3a 100644
--- a/sound/pci/echoaudio/mia.c
+++ b/sound/pci/echoaudio/mia.c
@@ -50,7 +50,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c
index 0364011c237d..1283bfb26b2e 100644
--- a/sound/pci/echoaudio/mona.c
+++ b/sound/pci/echoaudio/mona.c
@@ -48,7 +48,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/slab.h>
#include <sound/core.h>
diff --git a/sound/pci/emu10k1/emu10k1.c b/sound/pci/emu10k1/emu10k1.c
index a9c45d2cdb13..790c65d980c8 100644
--- a/sound/pci/emu10k1/emu10k1.c
+++ b/sound/pci/emu10k1/emu10k1.c
@@ -26,7 +26,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/time.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/emu10k1.h>
#include <sound/initval.h>
@@ -44,13 +44,13 @@ MODULE_SUPPORTED_DEVICE("{{Creative Labs,SB Live!/PCI512/E-mu APS},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int extin[SNDRV_CARDS];
static int extout[SNDRV_CARDS];
static int seq_ports[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4};
static int max_synth_voices[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 64};
static int max_buffer_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 128};
-static int enable_ir[SNDRV_CARDS];
+static bool enable_ir[SNDRV_CARDS];
static uint subsystem[SNDRV_CARDS]; /* Force card subsystem model */
static uint delay_pcm_irq[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
diff --git a/sound/pci/emu10k1/emu10k1_callback.c b/sound/pci/emu10k1/emu10k1_callback.c
index 7ef949d99a50..a0afa5057488 100644
--- a/sound/pci/emu10k1/emu10k1_callback.c
+++ b/sound/pci/emu10k1/emu10k1_callback.c
@@ -18,6 +18,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/export.h>
#include "emu10k1_synth_local.h"
#include <sound/asoundef.h>
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index fcd4935766b2..754924081d0a 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -35,6 +35,7 @@
#include <linux/kthread.h>
#include <linux/delay.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
@@ -1479,6 +1480,18 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spdif_bug = 1,
.invert_shared_spdif = 1, /* digital/analog switch swapped */
.ac97_chip = 1} ,
+ /* 0x20051102 also has SB0350 written on it, treated as Audigy 2 ZS by
+ Creative's Windows driver */
+ {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20051102,
+ .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350a]",
+ .id = "Audigy2",
+ .emu10k2_chip = 1,
+ .ca0102_chip = 1,
+ .ca0151_chip = 1,
+ .spk71 = 1,
+ .spdif_bug = 1,
+ .invert_shared_spdif = 1, /* digital/analog switch swapped */
+ .ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
.driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350]",
.id = "Audigy2",
diff --git a/sound/pci/emu10k1/emu10k1_synth.c b/sound/pci/emu10k1/emu10k1_synth.c
index ad7b71491fc4..4c41c903a840 100644
--- a/sound/pci/emu10k1/emu10k1_synth.c
+++ b/sound/pci/emu10k1/emu10k1_synth.c
@@ -20,6 +20,7 @@
#include "emu10k1_synth_local.h"
#include <linux/init.h>
+#include <linux/module.h>
MODULE_AUTHOR("Takashi Iwai");
MODULE_DESCRIPTION("Routines for control of EMU10K1 WaveTable synth");
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index d4fde1b4b093..47a651cb6e84 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -34,7 +34,7 @@
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
@@ -50,7 +50,7 @@ MODULE_SUPPORTED_DEVICE("{{Dell Creative Labs,SB Live!}");
// module parameters (see "Module Parameters")
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for the EMU10K1X soundcard.");
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 622bace148e3..e22b8e2bbd88 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -1146,6 +1146,11 @@ static int snd_emu10k1_playback_open(struct snd_pcm_substream *substream)
kfree(epcm);
return err;
}
+ err = snd_pcm_hw_rule_noresample(runtime, 48000);
+ if (err < 0) {
+ kfree(epcm);
+ return err;
+ }
mix = &emu->pcm_mixer[substream->number];
for (i = 0; i < 4; i++)
mix->send_routing[0][i] = mix->send_routing[1][i] = mix->send_routing[2][i] = i;
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index 5ef7080e14d0..e4fba49fee4a 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -29,6 +29,7 @@
#include <sound/core.h>
#include <sound/emu10k1.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include "p17v.h"
unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
diff --git a/sound/pci/emu10k1/memory.c b/sound/pci/emu10k1/memory.c
index c250614dadd0..4f502a2bdc3c 100644
--- a/sound/pci/emu10k1/memory.c
+++ b/sound/pci/emu10k1/memory.c
@@ -25,6 +25,7 @@
#include <linux/gfp.h>
#include <linux/time.h>
#include <linux/mutex.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/emu10k1.h>
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index 20b8da250bd0..101e7cb79cb2 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -29,6 +29,7 @@
*/
#include <linux/time.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/emu10k1.h>
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index f02e2f8d7122..47a245e84190 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -33,7 +33,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
@@ -83,12 +83,12 @@ MODULE_SUPPORTED_DEVICE("{{Ensoniq,AudioPCI ES1371/73},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
#ifdef SUPPORT_JOYSTICK
#ifdef CHIP1371
static int joystick_port[SNDRV_CARDS];
#else
-static int joystick[SNDRV_CARDS];
+static bool joystick[SNDRV_CARDS];
#endif
#endif
#ifdef CHIP1371
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 26a5a2f25d4b..53eb76b41108 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -52,7 +52,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
@@ -79,7 +79,7 @@ MODULE_SUPPORTED_DEVICE("{{ESS,ES1938},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for ESS Solo-1 soundcard.");
@@ -1854,8 +1854,9 @@ static int __devinit snd_es1938_probe(struct pci_dev *pci,
}
}
if (snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
- chip->mpu_port, MPU401_INFO_INTEGRATED,
- chip->irq, 0, &chip->rmidi) < 0) {
+ chip->mpu_port,
+ MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+ -1, &chip->rmidi) < 0) {
printk(KERN_ERR "es1938: unable to initialize MPU-401\n");
} else {
// this line is vital for MIDI interrupt handling on ess-solo1
diff --git a/sound/pci/es1968.c b/sound/pci/es1968.c
index 99ea9320c6b5..cb557c603a80 100644
--- a/sound/pci/es1968.c
+++ b/sound/pci/es1968.c
@@ -102,7 +102,7 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/gameport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/input.h>
@@ -132,7 +132,7 @@ MODULE_SUPPORTED_DEVICE("{{ESS,Maestro 2e},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 1-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int total_bufsize[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1024 };
static int pcm_substreams_p[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 4 };
static int pcm_substreams_c[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1 };
@@ -140,7 +140,7 @@ static int clock[SNDRV_CARDS];
static int use_pm[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
static int enable_mpu[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 2};
#ifdef SUPPORT_JOYSTICK
-static int joystick[SNDRV_CARDS];
+static bool joystick[SNDRV_CARDS];
#endif
module_param_array(index, int, NULL, 0444);
@@ -2843,8 +2843,9 @@ static int __devinit snd_es1968_probe(struct pci_dev *pci,
if (enable_mpu[dev]) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
chip->io_port + ESM_MPU401_PORT,
- MPU401_INFO_INTEGRATED,
- chip->irq, 0, &chip->rmidi)) < 0) {
+ MPU401_INFO_INTEGRATED |
+ MPU401_INFO_IRQ_HOOK,
+ -1, &chip->rmidi)) < 0) {
printk(KERN_WARNING "es1968: skipping MPU-401 MIDI support..\n");
}
}
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index f9123f09e83e..9597ef1eccca 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -25,7 +25,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/tlv.h>
@@ -48,7 +48,7 @@ MODULE_SUPPORTED_DEVICE("{{ForteMedia,FM801},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
/*
* Enable TEA575x tuner
* 1 = MediaForte 256-PCS
@@ -68,6 +68,7 @@ MODULE_PARM_DESC(enable, "Enable FM801 soundcard.");
module_param_array(tea575x_tuner, int, NULL, 0444);
MODULE_PARM_DESC(tea575x_tuner, "TEA575x tuner access method (0 = auto, 1 = SF256-PCS, 2=SF256-PCP, 3=SF64-PCR, 8=disable, +16=tuner-only).");
+#define TUNER_DISABLED (1<<3)
#define TUNER_ONLY (1<<4)
#define TUNER_TYPE_MASK (~TUNER_ONLY & 0xFFFF)
@@ -728,11 +729,14 @@ static struct snd_fm801_tea575x_gpio snd_fm801_tea575x_gpios[] = {
{ .data = 2, .clk = 0, .wren = 1, .most = 3, .name = "SF64-PCR" },
};
+#define get_tea575x_gpio(chip) \
+ (&snd_fm801_tea575x_gpios[((chip)->tea575x_tuner & TUNER_TYPE_MASK) - 1])
+
static void snd_fm801_tea575x_set_pins(struct snd_tea575x *tea, u8 pins)
{
struct fm801 *chip = tea->private_data;
unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
- struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
+ struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip);
reg &= ~(FM801_GPIO_GP(gpio.data) |
FM801_GPIO_GP(gpio.clk) |
@@ -750,7 +754,7 @@ static u8 snd_fm801_tea575x_get_pins(struct snd_tea575x *tea)
{
struct fm801 *chip = tea->private_data;
unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
- struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
+ struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip);
return (reg & FM801_GPIO_GP(gpio.data)) ? TEA575X_DATA : 0 |
(reg & FM801_GPIO_GP(gpio.most)) ? TEA575X_MOST : 0;
@@ -760,7 +764,7 @@ static void snd_fm801_tea575x_set_direction(struct snd_tea575x *tea, bool output
{
struct fm801 *chip = tea->private_data;
unsigned short reg = inw(FM801_REG(chip, GPIO_CTRL));
- struct snd_fm801_tea575x_gpio gpio = snd_fm801_tea575x_gpios[(chip->tea575x_tuner & TUNER_TYPE_MASK) - 1];
+ struct snd_fm801_tea575x_gpio gpio = *get_tea575x_gpio(chip);
/* use GPIO lines and set write enable bit */
reg |= FM801_GPIO_GS(gpio.data) |
@@ -1150,7 +1154,8 @@ static int snd_fm801_free(struct fm801 *chip)
__end_hw:
#ifdef CONFIG_SND_FM801_TEA575X_BOOL
- snd_tea575x_exit(&chip->tea);
+ if (!(chip->tea575x_tuner & TUNER_DISABLED))
+ snd_tea575x_exit(&chip->tea);
#endif
if (chip->irq >= 0)
free_irq(chip->irq, chip);
@@ -1236,7 +1241,6 @@ static int __devinit snd_fm801_create(struct snd_card *card,
(tea575x_tuner & TUNER_TYPE_MASK) < 4) {
if (snd_tea575x_init(&chip->tea)) {
snd_printk(KERN_ERR "TEA575x radio not found\n");
- snd_fm801_free(chip);
return -ENODEV;
}
} else if ((tea575x_tuner & TUNER_TYPE_MASK) == 0) {
@@ -1245,17 +1249,19 @@ static int __devinit snd_fm801_create(struct snd_card *card,
chip->tea575x_tuner = tea575x_tuner;
if (!snd_tea575x_init(&chip->tea)) {
snd_printk(KERN_INFO "detected TEA575x radio type %s\n",
- snd_fm801_tea575x_gpios[tea575x_tuner - 1].name);
+ get_tea575x_gpio(chip)->name);
break;
}
}
if (tea575x_tuner == 4) {
snd_printk(KERN_ERR "TEA575x radio not found\n");
- snd_fm801_free(chip);
- return -ENODEV;
+ chip->tea575x_tuner = TUNER_DISABLED;
}
}
- strlcpy(chip->tea.card, snd_fm801_tea575x_gpios[(tea575x_tuner & TUNER_TYPE_MASK) - 1].name, sizeof(chip->tea.card));
+ if (!(chip->tea575x_tuner & TUNER_DISABLED)) {
+ strlcpy(chip->tea.card, get_tea575x_gpio(chip)->name,
+ sizeof(chip->tea.card));
+ }
#endif
*rchip = chip;
@@ -1306,8 +1312,9 @@ static int __devinit snd_card_fm801_probe(struct pci_dev *pci,
}
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_FM801,
FM801_REG(chip, MPU401_DATA),
- MPU401_INFO_INTEGRATED,
- chip->irq, 0, &chip->rmidi)) < 0) {
+ MPU401_INFO_INTEGRATED |
+ MPU401_INFO_IRQ_HOOK,
+ -1, &chip->rmidi)) < 0) {
snd_card_free(card);
return err;
}
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
index bb7e102d6726..163b6b5de3eb 100644
--- a/sound/pci/hda/Kconfig
+++ b/sound/pci/hda/Kconfig
@@ -2,6 +2,7 @@ menuconfig SND_HDA_INTEL
tristate "Intel HD Audio"
select SND_PCM
select SND_VMASTER
+ select SND_KCTL_JACK
help
Say Y here to include support for Intel "High Definition
Audio" (Azalia) and its compatible devices.
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 87365d5ea2a9..ace157cc3d15 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,11 +1,14 @@
snd-hda-intel-objs := hda_intel.o
-snd-hda-codec-y := hda_codec.o
+snd-hda-codec-y := hda_codec.o hda_jack.o
snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
+# for trace-points
+CFLAGS_hda_codec.o := -I$(src)
+
snd-hda-codec-realtek-objs := patch_realtek.o
snd-hda-codec-cmedia-objs := patch_cmedia.o
snd-hda-codec-analog-objs := patch_analog.o
diff --git a/sound/pci/hda/alc260_quirks.c b/sound/pci/hda/alc260_quirks.c
deleted file mode 100644
index 21ec2cb100b0..000000000000
--- a/sound/pci/hda/alc260_quirks.c
+++ /dev/null
@@ -1,1272 +0,0 @@
-/*
- * ALC260 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC260 models */
-enum {
- ALC260_AUTO,
- ALC260_BASIC,
- ALC260_HP,
- ALC260_HP_DC7600,
- ALC260_HP_3013,
- ALC260_FUJITSU_S702X,
- ALC260_ACER,
- ALC260_WILL,
- ALC260_REPLACER_672V,
- ALC260_FAVORIT100,
-#ifdef CONFIG_SND_DEBUG
- ALC260_TEST,
-#endif
- ALC260_MODEL_LAST /* last tag */
-};
-
-static const hda_nid_t alc260_dac_nids[1] = {
- /* front */
- 0x02,
-};
-
-static const hda_nid_t alc260_adc_nids[1] = {
- /* ADC0 */
- 0x04,
-};
-
-static const hda_nid_t alc260_adc_nids_alt[1] = {
- /* ADC1 */
- 0x05,
-};
-
-/* NIDs used when simultaneous access to both ADCs makes sense. Note that
- * alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
- */
-static const hda_nid_t alc260_dual_adc_nids[2] = {
- /* ADC0, ADC1 */
- 0x04, 0x05
-};
-
-#define ALC260_DIGOUT_NID 0x03
-#define ALC260_DIGIN_NID 0x06
-
-static const struct hda_input_mux alc260_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-/* On Fujitsu S702x laptops capture only makes sense from Mic/LineIn jack,
- * headphone jack and the internal CD lines since these are the only pins at
- * which audio can appear. For flexibility, also allow the option of
- * recording the mixer output on the second ADC (ADC0 doesn't have a
- * connection to the mixer output).
- */
-static const struct hda_input_mux alc260_fujitsu_capture_sources[2] = {
- {
- .num_items = 3,
- .items = {
- { "Mic/Line", 0x0 },
- { "CD", 0x4 },
- { "Headphone", 0x2 },
- },
- },
- {
- .num_items = 4,
- .items = {
- { "Mic/Line", 0x0 },
- { "CD", 0x4 },
- { "Headphone", 0x2 },
- { "Mixer", 0x5 },
- },
- },
-
-};
-
-/* Acer TravelMate(/Extensa/Aspire) notebooks have similar configuration to
- * the Fujitsu S702x, but jacks are marked differently.
- */
-static const struct hda_input_mux alc260_acer_capture_sources[2] = {
- {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "Headphone", 0x5 },
- },
- },
- {
- .num_items = 5,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "Headphone", 0x6 },
- { "Mixer", 0x5 },
- },
- },
-};
-
-/* Maxdata Favorit 100XS */
-static const struct hda_input_mux alc260_favorit100_capture_sources[2] = {
- {
- .num_items = 2,
- .items = {
- { "Line/Mic", 0x0 },
- { "CD", 0x4 },
- },
- },
- {
- .num_items = 3,
- .items = {
- { "Line/Mic", 0x0 },
- { "CD", 0x4 },
- { "Mixer", 0x5 },
- },
- },
-};
-
-/*
- * This is just place-holder, so there's something for alc_build_pcms to look
- * at when it calculates the maximum number of channels. ALC260 has no mixer
- * element which allows changing the channel mode, so the verb list is
- * never used.
- */
-static const struct hda_channel_mode alc260_modes[1] = {
- { 2, NULL },
-};
-
-
-/* Mixer combinations
- *
- * basic: base_output + input + pc_beep + capture
- * HP: base_output + input + capture_alt
- * HP_3013: hp_3013 + input + capture
- * fujitsu: fujitsu + capture
- * acer: acer + capture
- */
-
-static const struct snd_kcontrol_new alc260_base_output_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc260_input_mixer[] = {
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x07, 0x01, HDA_INPUT),
- { } /* end */
-};
-
-/* update HP, line and mono out pins according to the master switch */
-static void alc260_hp_master_update(struct hda_codec *codec)
-{
- update_speakers(codec);
-}
-
-static int alc260_hp_master_sw_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- *ucontrol->value.integer.value = !spec->master_mute;
- return 0;
-}
-
-static int alc260_hp_master_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int val = !*ucontrol->value.integer.value;
-
- if (val == spec->master_mute)
- return 0;
- spec->master_mute = val;
- alc260_hp_master_update(codec);
- return 1;
-}
-
-static const struct snd_kcontrol_new alc260_hp_output_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
- .info = snd_ctl_boolean_mono_info,
- .get = alc260_hp_master_sw_get,
- .put = alc260_hp_master_sw_put,
- },
- HDA_CODEC_VOLUME("Front Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x08, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x09, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
- HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_verb alc260_hp_unsol_verbs[] = {
- {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {},
-};
-
-static void alc260_hp_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x0f;
- spec->autocfg.speaker_pins[0] = 0x10;
- spec->autocfg.speaker_pins[1] = 0x11;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static const struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_NID_FLAG | 0x11,
- .info = snd_ctl_boolean_mono_info,
- .get = alc260_hp_master_sw_get,
- .put = alc260_hp_master_sw_put,
- },
- HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Aux-In Playback Volume", 0x07, 0x06, HDA_INPUT),
- HDA_CODEC_MUTE("Aux-In Playback Switch", 0x07, 0x06, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x11, 1, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-static void alc260_hp_3013_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x10;
- spec->autocfg.speaker_pins[1] = 0x11;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static const struct hda_bind_ctls alc260_dc7600_bind_master_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x0a, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct hda_bind_ctls alc260_dc7600_bind_switch = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct snd_kcontrol_new alc260_hp_dc7600_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &alc260_dc7600_bind_master_vol),
- HDA_BIND_SW("LineOut Playback Switch", &alc260_dc7600_bind_switch),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x0f, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x10, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-static const struct hda_verb alc260_hp_3013_unsol_verbs[] = {
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {},
-};
-
-static void alc260_hp_3012_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x10;
- spec->autocfg.speaker_pins[0] = 0x0f;
- spec->autocfg.speaker_pins[1] = 0x11;
- spec->autocfg.speaker_pins[2] = 0x15;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-/* Fujitsu S702x series laptops. ALC260 pin usage: Mic/Line jack = 0x12,
- * HP jack = 0x14, CD audio = 0x16, internal speaker = 0x10.
- */
-static const struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x08, 2, HDA_INPUT),
- ALC_PIN_MODE("Headphone Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic/Line Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic/Line Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Mic/Line Jack Mode", 0x12, ALC_PIN_DIR_IN),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x09, 2, HDA_INPUT),
- { } /* end */
-};
-
-/* Mixer for Acer TravelMate(/Extensa/Aspire) notebooks. Note that current
- * versions of the ALC260 don't act on requests to enable mic bias from NID
- * 0x0f (used to drive the headphone jack in these laptops). The ALC260
- * datasheet doesn't mention this restriction. At this stage it's not clear
- * whether this behaviour is intentional or is a hardware bug in chip
- * revisions available in early 2006. Therefore for now allow the
- * "Headphone Jack Mode" control to span all choices, but if it turns out
- * that the lack of mic bias for this NID is intentional we could change the
- * mode from ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
- *
- * In addition, Acer TravelMate(/Extensa/Aspire) notebooks in early 2006
- * don't appear to make the mic bias available from the "line" jack, even
- * though the NID used for this jack (0x14) can supply it. The theory is
- * that perhaps Acer have included blocking capacitors between the ALC260
- * and the output jack. If this turns out to be the case for all such
- * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
- * to ALC_PIN_DIR_INOUT_NOMICBIAS.
- *
- * The C20x Tablet series have a mono internal speaker which is controlled
- * via the chip's Mono sum widget and pin complex, so include the necessary
- * controls for such models. On models without a "mono speaker" the control
- * won't do anything.
- */
-static const struct snd_kcontrol_new alc260_acer_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
- ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
- HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0a, 1, 0x0,
- HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Speaker Playback Switch", 0x0a, 1, 2,
- HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
- { } /* end */
-};
-
-/* Maxdata Favorit 100XS: one output and one input (0x12) jack
- */
-static const struct snd_kcontrol_new alc260_favorit100_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
- ALC_PIN_MODE("Output Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
- HDA_CODEC_VOLUME("Line/Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Line/Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Line/Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
- { } /* end */
-};
-
-/* Packard bell V7900 ALC260 pin usage: HP = 0x0f, Mic jack = 0x12,
- * Line In jack = 0x14, CD audio = 0x16, pc beep = 0x17.
- */
-static const struct snd_kcontrol_new alc260_will_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- { } /* end */
-};
-
-/* Replacer 672V ALC260 pin usage: Mic jack = 0x12,
- * Line In jack = 0x14, ATAPI Mic = 0x13, speaker = 0x0f.
- */
-static const struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x08, 0x2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x07, 0x0, HDA_INPUT),
- ALC_PIN_MODE("Mic Jack Mode", 0x12, ALC_PIN_DIR_IN),
- HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x07, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("ATATI Mic Playback Switch", 0x07, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x07, 0x02, HDA_INPUT),
- ALC_PIN_MODE("Line Jack Mode", 0x14, ALC_PIN_DIR_INOUT),
- { } /* end */
-};
-
-/*
- * initialization verbs
- */
-static const struct hda_verb alc260_init_verbs[] = {
- /* Line In pin widget for input */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* CD pin widget for input */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- /* Mic2 (front panel) pin widget for input and vref at 80% */
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- /* LINE-2 is used for line-out in rear */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* select line-out */
- {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* LINE-OUT pin */
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* enable HP */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* enable Mono */
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* set connection select to line in (default select for this ADC) */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* mute capture amp left and right */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* set connection select to line in (default select for this ADC) */
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* set vol=0 Line-Out mixer amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* unmute pin widget amp left and right (no gain on this amp) */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* set vol=0 HP mixer amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* unmute pin widget amp left and right (no gain on this amp) */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* set vol=0 Mono mixer amp left and right */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* unmute pin widget amp left and right (no gain on this amp) */
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* unmute LINE-2 out pin */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
- * Line In 2 = 0x03
- */
- /* mute analog inputs */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
- /* mute Front out path */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* mute Headphone out path */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* mute Mono out path */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- { }
-};
-
-#if 0 /* should be identical with alc260_init_verbs? */
-static const struct hda_verb alc260_hp_init_verbs[] = {
- /* Headphone and output */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
- /* mono output */
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* Mic2 (front panel) pin widget for input and vref at 80% */
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* Line In pin widget for input */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- /* Line-2 pin widget for output */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* CD pin widget for input */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- /* unmute amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
- /* set connection select to line in (default select for this ADC) */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* unmute Line-Out mixer amp left and right (volume = 0) */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* unmute HP mixer amp left and right (volume = 0) */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
- * Line In 2 = 0x03
- */
- /* mute analog inputs */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
- /* Unmute Front out path */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute Headphone out path */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute Mono out path */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- { }
-};
-#endif
-
-static const struct hda_verb alc260_hp_3013_init_verbs[] = {
- /* Line out and output */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* mono output */
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* Mic2 (front panel) pin widget for input and vref at 80% */
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- /* Line In pin widget for input */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- /* Headphone pin widget for output */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
- /* CD pin widget for input */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- /* unmute amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000},
- /* set connection select to line in (default select for this ADC) */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* unmute Line-Out mixer amp left and right (volume = 0) */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* unmute HP mixer amp left and right (volume = 0) */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
- /* mute pin widget amp left and right (no gain on this amp) */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- /* Amp Indexes: CD = 0x04, Line In 1 = 0x02, Mic 1 = 0x00 &
- * Line In 2 = 0x03
- */
- /* mute analog inputs */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Amp Indexes: DAC = 0x01 & mixer = 0x00 */
- /* Unmute Front out path */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute Headphone out path */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- /* Unmute Mono out path */
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- { }
-};
-
-/* Initialisation sequence for ALC260 as configured in Fujitsu S702x
- * laptops. ALC260 pin usage: Mic/Line jack = 0x12, HP jack = 0x14, CD
- * audio = 0x16, internal speaker = 0x10.
- */
-static const struct hda_verb alc260_fujitsu_init_verbs[] = {
- /* Disable all GPIOs */
- {0x01, AC_VERB_SET_GPIO_MASK, 0},
- /* Internal speaker is connected to headphone pin */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Headphone/Line-out jack connects to Line1 pin; make it an output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* Mic/Line-in jack is connected to mic1 pin, so make it an input */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Ensure all other unused pins are disabled and muted. */
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
- /* Disable digital (SPDIF) pins */
- {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
- {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
- /* Ensure Line1 pin widget takes its input from the OUT1 sum bus
- * when acting as an output.
- */
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
- /* Start with output sum widgets muted and their output gains at min */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* Unmute HP pin widget amp left and right (no equiv mixer ctrl) */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute Line1 pin widget output buffer since it starts as an output.
- * If the pin mode is changed by the user the pin mode control will
- * take care of enabling the pin's input/output buffers as needed.
- * Therefore there's no need to enable the input buffer at this
- * stage.
- */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute input buffer of pin widget used for Line-in (no equiv
- * mixer ctrl)
- */
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Set ADC connection select to match default mixer setting - line
- * in (on mic1 pin)
- */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Do the same for the second ADC: mute capture input amp and
- * set ADC connection to line in (on mic1 pin)
- */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Mute all inputs to mixer widget (even unconnected ones) */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
- { }
-};
-
-/* Initialisation sequence for ALC260 as configured in Acer TravelMate and
- * similar laptops (adapted from Fujitsu init verbs).
- */
-static const struct hda_verb alc260_acer_init_verbs[] = {
- /* On TravelMate laptops, GPIO 0 enables the internal speaker and
- * the headphone jack. Turn this on and rely on the standard mute
- * methods whenever the user wants to turn these outputs off.
- */
- {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
- /* Internal speaker/Headphone jack is connected to Line-out pin */
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Internal microphone/Mic jack is connected to Mic1 pin */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
- /* Line In jack is connected to Line1 pin */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Ensure all other unused pins are disabled and muted. */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Disable digital (SPDIF) pins */
- {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
- {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
- /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
- * bus when acting as outputs.
- */
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
- /* Start with output sum widgets muted and their output gains at min */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* Unmute Line-out pin widget amp left and right
- * (no equiv mixer ctrl)
- */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute mono pin widget amp output (no equiv mixer ctrl) */
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute Mic1 and Line1 pin widget input buffers since they start as
- * inputs. If the pin mode is changed by the user the pin mode control
- * will take care of enabling the pin's input/output buffers as needed.
- * Therefore there's no need to enable the input buffer at this
- * stage.
- */
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Set ADC connection select to match default mixer setting - mic
- * (on mic1 pin)
- */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Do similar with the second ADC: mute capture input amp and
- * set ADC connection to mic to match ALSA's default state.
- */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Mute all inputs to mixer widget (even unconnected ones) */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
- { }
-};
-
-/* Initialisation sequence for Maxdata Favorit 100XS
- * (adapted from Acer init verbs).
- */
-static const struct hda_verb alc260_favorit100_init_verbs[] = {
- /* GPIO 0 enables the output jack.
- * Turn this on and rely on the standard mute
- * methods whenever the user wants to turn these outputs off.
- */
- {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x01},
- /* Line/Mic input jack is connected to Mic1 pin */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
- /* Ensure all other unused pins are disabled and muted. */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Disable digital (SPDIF) pins */
- {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
- {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
- /* Ensure Mic1 and Line1 pin widgets take input from the OUT1 sum
- * bus when acting as outputs.
- */
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
-
- /* Start with output sum widgets muted and their output gains at min */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* Unmute Line-out pin widget amp left and right
- * (no equiv mixer ctrl)
- */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute Mic1 and Line1 pin widget input buffers since they start as
- * inputs. If the pin mode is changed by the user the pin mode control
- * will take care of enabling the pin's input/output buffers as needed.
- * Therefore there's no need to enable the input buffer at this
- * stage.
- */
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Set ADC connection select to match default mixer setting - mic
- * (on mic1 pin)
- */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Do similar with the second ADC: mute capture input amp and
- * set ADC connection to mic to match ALSA's default state.
- */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Mute all inputs to mixer widget (even unconnected ones) */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
- { }
-};
-
-static const struct hda_verb alc260_will_verbs[] = {
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
- {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x1a, AC_VERB_SET_PROC_COEF, 0x3040},
- {}
-};
-
-static const struct hda_verb alc260_replacer_672v_verbs[] = {
- {0x0f, AC_VERB_SET_EAPD_BTLENABLE, 0x02},
- {0x1a, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x1a, AC_VERB_SET_PROC_COEF, 0x3050},
-
- {0x01, AC_VERB_SET_GPIO_MASK, 0x01},
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
-
- {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc260_replacer_672v_automute(struct hda_codec *codec)
-{
- unsigned int present;
-
- /* speaker --> GPIO Data 0, hp or spdif --> GPIO data 1 */
- present = snd_hda_jack_detect(codec, 0x0f);
- if (present) {
- snd_hda_codec_write_cache(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, 1);
- snd_hda_codec_write_cache(codec, 0x0f, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- PIN_HP);
- } else {
- snd_hda_codec_write_cache(codec, 0x01, 0,
- AC_VERB_SET_GPIO_DATA, 0);
- snd_hda_codec_write_cache(codec, 0x0f, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- PIN_OUT);
- }
-}
-
-static void alc260_replacer_672v_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC_HP_EVENT)
- alc260_replacer_672v_automute(codec);
-}
-
-static const struct hda_verb alc260_hp_dc7600_verbs[] = {
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x10, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-/* Test configuration for debugging, modelled after the ALC880 test
- * configuration.
- */
-#ifdef CONFIG_SND_DEBUG
-static const hda_nid_t alc260_test_dac_nids[1] = {
- 0x02,
-};
-static const hda_nid_t alc260_test_adc_nids[2] = {
- 0x04, 0x05,
-};
-/* For testing the ALC260, each input MUX needs its own definition since
- * the signal assignments are different. This assumes that the first ADC
- * is NID 0x04.
- */
-static const struct hda_input_mux alc260_test_capture_sources[2] = {
- {
- .num_items = 7,
- .items = {
- { "MIC1 pin", 0x0 },
- { "MIC2 pin", 0x1 },
- { "LINE1 pin", 0x2 },
- { "LINE2 pin", 0x3 },
- { "CD pin", 0x4 },
- { "LINE-OUT pin", 0x5 },
- { "HP-OUT pin", 0x6 },
- },
- },
- {
- .num_items = 8,
- .items = {
- { "MIC1 pin", 0x0 },
- { "MIC2 pin", 0x1 },
- { "LINE1 pin", 0x2 },
- { "LINE2 pin", 0x3 },
- { "CD pin", 0x4 },
- { "Mixer", 0x5 },
- { "LINE-OUT pin", 0x6 },
- { "HP-OUT pin", 0x7 },
- },
- },
-};
-static const struct snd_kcontrol_new alc260_test_mixer[] = {
- /* Output driver widgets */
- HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0a, 1, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Mono Playback Switch", 0x0a, 1, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x09, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("LOUT2 Playback Switch", 0x09, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x08, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("LOUT1 Playback Switch", 0x08, 2, HDA_INPUT),
-
- /* Modes for retasking pin widgets
- * Note: the ALC260 doesn't seem to act on requests to enable mic
- * bias from NIDs 0x0f and 0x10. The ALC260 datasheet doesn't
- * mention this restriction. At this stage it's not clear whether
- * this behaviour is intentional or is a hardware bug in chip
- * revisions available at least up until early 2006. Therefore for
- * now allow the "HP-OUT" and "LINE-OUT" Mode controls to span all
- * choices, but if it turns out that the lack of mic bias for these
- * NIDs is intentional we could change their modes from
- * ALC_PIN_DIR_INOUT to ALC_PIN_DIR_INOUT_NOMICBIAS.
- */
- ALC_PIN_MODE("HP-OUT pin mode", 0x10, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("LINE-OUT pin mode", 0x0f, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("LINE2 pin mode", 0x15, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("LINE1 pin mode", 0x14, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("MIC2 pin mode", 0x13, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("MIC1 pin mode", 0x12, ALC_PIN_DIR_INOUT),
-
- /* Loopback mixer controls */
- HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x07, 0x00, HDA_INPUT),
- HDA_CODEC_MUTE("MIC1 Playback Switch", 0x07, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("MIC2 Playback Switch", 0x07, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("LINE1 Playback Volume", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("LINE1 Playback Switch", 0x07, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("LINE2 Playback Volume", 0x07, 0x03, HDA_INPUT),
- HDA_CODEC_MUTE("LINE2 Playback Switch", 0x07, 0x03, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("LINE-OUT loopback Playback Volume", 0x07, 0x06, HDA_INPUT),
- HDA_CODEC_MUTE("LINE-OUT loopback Playback Switch", 0x07, 0x06, HDA_INPUT),
- HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x07, 0x7, HDA_INPUT),
- HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x07, 0x7, HDA_INPUT),
-
- /* Controls for GPIO pins, assuming they are configured as outputs */
- ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
- ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
- ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
- ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
-
- /* Switches to allow the digital IO pins to be enabled. The datasheet
- * is ambigious as to which NID is which; testing on laptops which
- * make this output available should provide clarification.
- */
- ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x03, 0x01),
- ALC_SPDIF_CTRL_SWITCH("SPDIF Capture Switch", 0x06, 0x01),
-
- /* A switch allowing EAPD to be enabled. Some laptops seem to use
- * this output to turn on an external amplifier.
- */
- ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
- ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
-
- { } /* end */
-};
-static const struct hda_verb alc260_test_init_verbs[] = {
- /* Enable all GPIOs as outputs with an initial value of 0 */
- {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
- {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
- {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
-
- /* Enable retasking pins as output, initially without power amp */
- {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- /* Disable digital (SPDIF) pins initially, but users can enable
- * them via a mixer switch. In the case of SPDIF-out, this initverb
- * payload also sets the generation to 0, output to be in "consumer"
- * PCM format, copyright asserted, no pre-emphasis and no validity
- * control.
- */
- {0x03, AC_VERB_SET_DIGI_CONVERT_1, 0},
- {0x06, AC_VERB_SET_DIGI_CONVERT_1, 0},
-
- /* Ensure mic1, mic2, line1 and line2 pin widgets take input from the
- * OUT1 sum bus when acting as an output.
- */
- {0x0b, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0c, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0d, AC_VERB_SET_CONNECT_SEL, 0},
- {0x0e, AC_VERB_SET_CONNECT_SEL, 0},
-
- /* Start with output sum widgets muted and their output gains at min */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* Unmute retasking pin widget output buffers since the default
- * state appears to be output. As the pin mode is changed by the
- * user the pin mode control will take care of enabling the pin's
- * input/output buffers as needed.
- */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Also unmute the mono-out pin widget */
- {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Mute capture amp left and right */
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* Set ADC connection select to match default mixer setting (mic1
- * pin)
- */
- {0x04, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Do the same for the second ADC: mute capture input amp and
- * set ADC connection to mic1 pin
- */
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x05, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Mute all inputs to mixer widget (even unconnected ones) */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
-
- { }
-};
-#endif
-
-/*
- * ALC260 configurations
- */
-static const char * const alc260_models[ALC260_MODEL_LAST] = {
- [ALC260_BASIC] = "basic",
- [ALC260_HP] = "hp",
- [ALC260_HP_3013] = "hp-3013",
- [ALC260_HP_DC7600] = "hp-dc7600",
- [ALC260_FUJITSU_S702X] = "fujitsu",
- [ALC260_ACER] = "acer",
- [ALC260_WILL] = "will",
- [ALC260_REPLACER_672V] = "replacer",
- [ALC260_FAVORIT100] = "favorit100",
-#ifdef CONFIG_SND_DEBUG
- [ALC260_TEST] = "test",
-#endif
- [ALC260_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc260_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
- SND_PCI_QUIRK(0x1025, 0x007f, "Acer", ALC260_WILL),
- SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
- SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FAVORIT100),
- SND_PCI_QUIRK(0x103c, 0x2808, "HP d5700", ALC260_HP_3013),
- SND_PCI_QUIRK(0x103c, 0x280a, "HP d5750", ALC260_AUTO), /* no quirk */
- SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
- SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP_3013),
- SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_DC7600),
- SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
- SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
- SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
- SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
- SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
- SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
- SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
- SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
- SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
- SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_REPLACER_672V),
- SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_WILL),
- {}
-};
-
-static const struct alc_config_preset alc260_presets[] = {
- [ALC260_BASIC] = {
- .mixers = { alc260_base_output_mixer,
- alc260_input_mixer },
- .init_verbs = { alc260_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
- .adc_nids = alc260_dual_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .input_mux = &alc260_capture_source,
- },
- [ALC260_HP] = {
- .mixers = { alc260_hp_output_mixer,
- alc260_input_mixer },
- .init_verbs = { alc260_init_verbs,
- alc260_hp_unsol_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
- .adc_nids = alc260_adc_nids_alt,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .input_mux = &alc260_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc260_hp_setup,
- .init_hook = alc_inithook,
- },
- [ALC260_HP_DC7600] = {
- .mixers = { alc260_hp_dc7600_mixer,
- alc260_input_mixer },
- .init_verbs = { alc260_init_verbs,
- alc260_hp_dc7600_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
- .adc_nids = alc260_adc_nids_alt,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .input_mux = &alc260_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc260_hp_3012_setup,
- .init_hook = alc_inithook,
- },
- [ALC260_HP_3013] = {
- .mixers = { alc260_hp_3013_mixer,
- alc260_input_mixer },
- .init_verbs = { alc260_hp_3013_init_verbs,
- alc260_hp_3013_unsol_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
- .adc_nids = alc260_adc_nids_alt,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .input_mux = &alc260_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc260_hp_3013_setup,
- .init_hook = alc_inithook,
- },
- [ALC260_FUJITSU_S702X] = {
- .mixers = { alc260_fujitsu_mixer },
- .init_verbs = { alc260_fujitsu_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
- .adc_nids = alc260_dual_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .num_mux_defs = ARRAY_SIZE(alc260_fujitsu_capture_sources),
- .input_mux = alc260_fujitsu_capture_sources,
- },
- [ALC260_ACER] = {
- .mixers = { alc260_acer_mixer },
- .init_verbs = { alc260_acer_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
- .adc_nids = alc260_dual_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .num_mux_defs = ARRAY_SIZE(alc260_acer_capture_sources),
- .input_mux = alc260_acer_capture_sources,
- },
- [ALC260_FAVORIT100] = {
- .mixers = { alc260_favorit100_mixer },
- .init_verbs = { alc260_favorit100_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
- .adc_nids = alc260_dual_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .num_mux_defs = ARRAY_SIZE(alc260_favorit100_capture_sources),
- .input_mux = alc260_favorit100_capture_sources,
- },
- [ALC260_WILL] = {
- .mixers = { alc260_will_mixer },
- .init_verbs = { alc260_init_verbs, alc260_will_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
- .adc_nids = alc260_adc_nids,
- .dig_out_nid = ALC260_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .input_mux = &alc260_capture_source,
- },
- [ALC260_REPLACER_672V] = {
- .mixers = { alc260_replacer_672v_mixer },
- .init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
- .num_dacs = ARRAY_SIZE(alc260_dac_nids),
- .dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
- .adc_nids = alc260_adc_nids,
- .dig_out_nid = ALC260_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .input_mux = &alc260_capture_source,
- .unsol_event = alc260_replacer_672v_unsol_event,
- .init_hook = alc260_replacer_672v_automute,
- },
-#ifdef CONFIG_SND_DEBUG
- [ALC260_TEST] = {
- .mixers = { alc260_test_mixer },
- .init_verbs = { alc260_test_init_verbs },
- .num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
- .dac_nids = alc260_test_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_test_adc_nids),
- .adc_nids = alc260_test_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc260_modes),
- .channel_mode = alc260_modes,
- .num_mux_defs = ARRAY_SIZE(alc260_test_capture_sources),
- .input_mux = alc260_test_capture_sources,
- },
-#endif
-};
-
diff --git a/sound/pci/hda/alc262_quirks.c b/sound/pci/hda/alc262_quirks.c
deleted file mode 100644
index 8d2097d77642..000000000000
--- a/sound/pci/hda/alc262_quirks.c
+++ /dev/null
@@ -1,1353 +0,0 @@
-/*
- * ALC262 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC262 models */
-enum {
- ALC262_AUTO,
- ALC262_BASIC,
- ALC262_HIPPO,
- ALC262_HIPPO_1,
- ALC262_FUJITSU,
- ALC262_HP_BPC,
- ALC262_HP_BPC_D7000_WL,
- ALC262_HP_BPC_D7000_WF,
- ALC262_HP_TC_T5735,
- ALC262_HP_RP5700,
- ALC262_BENQ_ED8,
- ALC262_SONY_ASSAMD,
- ALC262_BENQ_T31,
- ALC262_ULTRA,
- ALC262_LENOVO_3000,
- ALC262_NEC,
- ALC262_TOSHIBA_S06,
- ALC262_TOSHIBA_RX1,
- ALC262_TYAN,
- ALC262_MODEL_LAST /* last tag */
-};
-
-#define ALC262_DIGOUT_NID ALC880_DIGOUT_NID
-#define ALC262_DIGIN_NID ALC880_DIGIN_NID
-
-#define alc262_dac_nids alc260_dac_nids
-#define alc262_adc_nids alc882_adc_nids
-#define alc262_adc_nids_alt alc882_adc_nids_alt
-#define alc262_capsrc_nids alc882_capsrc_nids
-#define alc262_capsrc_nids_alt alc882_capsrc_nids_alt
-
-#define alc262_modes alc260_modes
-#define alc262_capture_source alc882_capture_source
-
-static const hda_nid_t alc262_dmic_adc_nids[1] = {
- /* ADC0 */
- 0x09
-};
-
-static const hda_nid_t alc262_dmic_capsrc_nids[1] = { 0x22 };
-
-static const struct snd_kcontrol_new alc262_base_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-/* update HP, line and mono-out pins according to the master switch */
-#define alc262_hp_master_update alc260_hp_master_update
-
-static void alc262_hp_bpc_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x16;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static void alc262_hp_wildwest_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x16;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-#define alc262_hp_master_sw_get alc260_hp_master_sw_get
-#define alc262_hp_master_sw_put alc260_hp_master_sw_put
-
-#define ALC262_HP_MASTER_SWITCH \
- { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = "Master Playback Switch", \
- .info = snd_ctl_boolean_mono_info, \
- .get = alc262_hp_master_sw_get, \
- .put = alc262_hp_master_sw_put, \
- }, \
- { \
- .iface = NID_MAPPING, \
- .name = "Master Playback Switch", \
- .private_value = 0x15 | (0x16 << 8) | (0x1b << 16), \
- }
-
-
-static const struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
- ALC262_HP_MASTER_SWITCH,
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("AUX IN Playback Volume", 0x0b, 0x06, HDA_INPUT),
- HDA_CODEC_MUTE("AUX IN Playback Switch", 0x0b, 0x06, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
- ALC262_HP_MASTER_SWITCH,
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 2, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 2, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x1a, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
- HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Rear Mic Boost Volume", 0x18, 0, HDA_INPUT),
- { } /* end */
-};
-
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hp_t5735_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static const struct snd_kcontrol_new alc262_hp_t5735_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_verb alc262_hp_t5735_verbs[] = {
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { }
-};
-
-static const struct snd_kcontrol_new alc262_hp_rp5700_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x16, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_verb alc262_hp_rp5700_verbs[] = {
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x00 << 8))},
- {}
-};
-
-static const struct hda_input_mux alc262_hp_rp5700_capture_source = {
- .num_items = 1,
- .items = {
- { "Line", 0x1 },
- },
-};
-
-/* bind hp and internal speaker mute (with plug check) as master switch */
-#define alc262_hippo_master_update alc262_hp_master_update
-#define alc262_hippo_master_sw_get alc262_hp_master_sw_get
-#define alc262_hippo_master_sw_put alc262_hp_master_sw_put
-
-#define ALC262_HIPPO_MASTER_SWITCH \
- { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = "Master Playback Switch", \
- .info = snd_ctl_boolean_mono_info, \
- .get = alc262_hippo_master_sw_get, \
- .put = alc262_hippo_master_sw_put, \
- }, \
- { \
- .iface = NID_MAPPING, \
- .name = "Master Playback Switch", \
- .subdevice = SUBDEV_HP(0) | (SUBDEV_LINE(0) << 8) | \
- (SUBDEV_SPEAKER(0) << 16), \
- }
-
-static const struct snd_kcontrol_new alc262_hippo_mixer[] = {
- ALC262_HIPPO_MASTER_SWITCH,
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_hippo1_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC262_HIPPO_MASTER_SWITCH,
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { } /* end */
-};
-
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_hippo_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc262_hippo1_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-
-static const struct snd_kcontrol_new alc262_sony_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC262_HIPPO_MASTER_SWITCH,
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_benq_t31_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- ALC262_HIPPO_MASTER_SWITCH,
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_tyan_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Aux Playback Volume", 0x0b, 0x06, HDA_INPUT),
- HDA_CODEC_MUTE("Aux Playback Switch", 0x0b, 0x06, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_verb alc262_tyan_verbs[] = {
- /* Headphone automute */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* P11 AUX_IN, white 4-pin connector */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_1, 0xe1},
- {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_2, 0x93},
- {0x14, AC_VERB_SET_CONFIG_DEFAULT_BYTES_3, 0x19},
-
- {}
-};
-
-/* unsolicited event for HP jack sensing */
-static void alc262_tyan_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-
-#define alc262_capture_mixer alc882_capture_mixer
-#define alc262_capture_alt_mixer alc882_capture_alt_mixer
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc262_init_verbs[] = {
- /*
- * Unmute ADC0-2 and set the default input to mic-in
- */
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
- * mixer widget
- * Note: PASD motherboards uses the Line In 2 as the input for
- * front panel mic (mic 2)
- */
- /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
- /*
- * Set up output mixers (0x0c - 0x0e)
- */
- /* set vol=0 to output mixers */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* set up input amps for analog loopback */
- /* Amp Indices: DAC = 0, mixer = 1 */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-
- /* FIXME: use matrix-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
- /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
- /* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
- /* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
-
- { }
-};
-
-static const struct hda_verb alc262_eapd_verbs[] = {
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-static const struct hda_verb alc262_hippo1_unsol_verbs[] = {
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
-
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {}
-};
-
-static const struct hda_verb alc262_sony_unsol_verbs[] = {
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24}, // Front Mic
-
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {}
-};
-
-static const struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_verb alc262_toshiba_s06_verbs[] = {
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x22, AC_VERB_SET_CONNECT_SEL, 0x09},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static void alc262_toshiba_s06_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x12;
- spec->auto_mic = 1;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-/*
- * nec model
- * 0x15 = headphone
- * 0x16 = internal speaker
- * 0x18 = external mic
- */
-
-static const struct snd_kcontrol_new alc262_nec_mixer[] = {
- HDA_CODEC_VOLUME_MONO("Speaker Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Speaker Playback Switch", 0x16, 0, 0x0, HDA_OUTPUT),
-
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-static const struct hda_verb alc262_nec_verbs[] = {
- /* Unmute Speaker */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Headphone */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- /* External mic to headphone */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* External mic to speaker */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {}
-};
-
-/*
- * fujitsu model
- * 0x14 = headphone/spdif-out, 0x15 = internal speaker,
- * 0x1b = port replicator headphone out
- */
-
-static const struct hda_verb alc262_fujitsu_unsol_verbs[] = {
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {}
-};
-
-static const struct hda_verb alc262_lenovo_3000_unsol_verbs[] = {
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {}
-};
-
-static const struct hda_verb alc262_lenovo_3000_init_verbs[] = {
- /* Front Mic pin: input vref at 50% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {}
-};
-
-static const struct hda_input_mux alc262_fujitsu_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Internal Mic", 0x1 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux alc262_HP_capture_source = {
- .num_items = 5,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "AUX IN", 0x6 },
- },
-};
-
-static const struct hda_input_mux alc262_HP_D7000_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x2 },
- { "Line", 0x1 },
- { "CD", 0x4 },
- },
-};
-
-static void alc262_fujitsu_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.hp_pins[1] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/* bind volumes of both NID 0x0c and 0x0d */
-static const struct hda_bind_ctls alc262_fujitsu_bind_master_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x0d, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct snd_kcontrol_new alc262_fujitsu_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
- .info = snd_ctl_boolean_mono_info,
- .get = alc262_hp_master_sw_get,
- .put = alc262_hp_master_sw_put,
- },
- {
- .iface = NID_MAPPING,
- .name = "Master Playback Switch",
- .private_value = 0x1b,
- },
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static void alc262_lenovo_3000_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct snd_kcontrol_new alc262_lenovo_3000_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_NID_FLAG | 0x1b,
- .info = snd_ctl_boolean_mono_info,
- .get = alc262_hp_master_sw_get,
- .put = alc262_hp_master_sw_put,
- },
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc262_toshiba_rx1_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &alc262_fujitsu_bind_master_vol),
- ALC262_HIPPO_MASTER_SWITCH,
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { } /* end */
-};
-
-/* additional init verbs for Benq laptops */
-static const struct hda_verb alc262_EAPD_verbs[] = {
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
- {}
-};
-
-static const struct hda_verb alc262_benq_t31_EAPD_verbs[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
-
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
- {}
-};
-
-/* Samsung Q1 Ultra Vista model setup */
-static const struct snd_kcontrol_new alc262_ultra_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Mic Boost Volume", 0x15, 0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_verb alc262_ultra_verbs[] = {
- /* output mixer */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* speaker */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- /* internal mic */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* ADC, choose mic */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(8)},
- {}
-};
-
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc262_ultra_automute(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- unsigned int mute;
-
- mute = 0;
- /* auto-mute only when HP is used as HP */
- if (!spec->cur_mux[0]) {
- spec->jack_present = snd_hda_jack_detect(codec, 0x15);
- if (spec->jack_present)
- mute = HDA_AMP_MUTE;
- }
- /* mute/unmute internal speaker */
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute);
- /* mute/unmute HP */
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, mute ? 0 : HDA_AMP_MUTE);
-}
-
-/* unsolicited event for HP jack sensing */
-static void alc262_ultra_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) != ALC_HP_EVENT)
- return;
- alc262_ultra_automute(codec);
-}
-
-static const struct hda_input_mux alc262_ultra_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x1 },
- { "Headphone", 0x7 },
- },
-};
-
-static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int ret;
-
- ret = alc_mux_enum_put(kcontrol, ucontrol);
- if (!ret)
- return 0;
- /* reprogram the HP pin as mic or HP according to the input source */
- snd_hda_codec_write_cache(codec, 0x15, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- spec->cur_mux[0] ? PIN_VREF80 : PIN_HP);
- alc262_ultra_automute(codec); /* mute/unmute HP */
- return ret;
-}
-
-static const struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc262_ultra_mux_enum_put,
- },
- {
- .iface = NID_MAPPING,
- .name = "Capture Source",
- .private_value = 0x15,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc262_HP_BPC_init_verbs[] = {
- /*
- * Unmute ADC0-2 and set the default input to mic-in
- */
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
- * mixer widget
- * Note: PASD motherboards uses the Line In 2 as the input for
- * front panel mic (mic 2)
- */
- /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
-
- /*
- * Set up output mixers (0x0c - 0x0e)
- */
- /* set vol=0 to output mixers */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* set up input amps for analog loopback */
- /* Amp Indices: DAC = 0, mixer = 1 */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
-
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
- {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
- {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-
-
- /* FIXME: use matrix-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 0b, 12 */
- /* Input mixer1: only unmute Mic */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
- /* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
- /* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x03 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x04 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x05 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x06 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x07 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x08 << 8))},
-
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-
- { }
-};
-
-static const struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
- /*
- * Unmute ADC0-2 and set the default input to mic-in
- */
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Mute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
- * mixer widget
- * Note: PASD motherboards uses the Line In 2 as the input for front
- * panel mic (mic 2)
- */
- /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
- /*
- * Set up output mixers (0x0c - 0x0e)
- */
- /* set vol=0 to output mixers */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* set up input amps for analog loopback */
- /* Amp Indices: DAC = 0, mixer = 1 */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
-
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */
-
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
-
- /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
- {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
- {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
-
- /* FIXME: use matrix-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
- /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
- /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
- /* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
- /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
- /* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
- /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
-
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-
- { }
-};
-
-static const struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = {
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Front Speaker */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* MIC jack */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) },
-
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP jack */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-/*
- * configuration and preset
- */
-static const char * const alc262_models[ALC262_MODEL_LAST] = {
- [ALC262_BASIC] = "basic",
- [ALC262_HIPPO] = "hippo",
- [ALC262_HIPPO_1] = "hippo_1",
- [ALC262_FUJITSU] = "fujitsu",
- [ALC262_HP_BPC] = "hp-bpc",
- [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
- [ALC262_HP_TC_T5735] = "hp-tc-t5735",
- [ALC262_HP_RP5700] = "hp-rp5700",
- [ALC262_BENQ_ED8] = "benq",
- [ALC262_BENQ_T31] = "benq-t31",
- [ALC262_SONY_ASSAMD] = "sony-assamd",
- [ALC262_TOSHIBA_S06] = "toshiba-s06",
- [ALC262_TOSHIBA_RX1] = "toshiba-rx1",
- [ALC262_ULTRA] = "ultra",
- [ALC262_LENOVO_3000] = "lenovo-3000",
- [ALC262_NEC] = "nec",
- [ALC262_TYAN] = "tyan",
- [ALC262_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc262_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
- SND_PCI_QUIRK(0x1033, 0x8895, "NEC Versa S9100", ALC262_NEC),
- SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1200, "HP xw series",
- ALC262_HP_BPC),
- SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1300, "HP xw series",
- ALC262_HP_BPC),
- SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1500, "HP z series",
- ALC262_HP_BPC),
- SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200",
- ALC262_AUTO),
- SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x1700, "HP xw series",
- ALC262_HP_BPC),
- SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
- SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
- SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
- SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
- SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
- SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
- SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
- SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
- SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
- SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
- SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
- SND_PCI_QUIRK(0x103c, 0x302f, "HP Thin Client T5735",
- ALC262_HP_TC_T5735),
- SND_PCI_QUIRK(0x103c, 0x2817, "HP RP5700", ALC262_HP_RP5700),
- SND_PCI_QUIRK(0x104d, 0x1f00, "Sony ASSAMD", ALC262_SONY_ASSAMD),
- SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
- SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
- SND_PCI_QUIRK(0x104d, 0x9016, "Sony VAIO", ALC262_AUTO), /* dig-only */
- SND_PCI_QUIRK(0x104d, 0x9025, "Sony VAIO Z21MN", ALC262_TOSHIBA_S06),
- SND_PCI_QUIRK(0x104d, 0x9035, "Sony VAIO VGN-FW170J", ALC262_AUTO),
- SND_PCI_QUIRK(0x104d, 0x9047, "Sony VAIO Type G", ALC262_AUTO),
-#if 0 /* disable the quirk since model=auto works better in recent versions */
- SND_PCI_QUIRK_MASK(0x104d, 0xff00, 0x9000, "Sony VAIO",
- ALC262_SONY_ASSAMD),
-#endif
- SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
- ALC262_TOSHIBA_RX1),
- SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
- SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
- SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FUJITSU),
- SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_TYAN),
- SND_PCI_QUIRK_MASK(0x144d, 0xff00, 0xc032, "Samsung Q1",
- ALC262_ULTRA),
- SND_PCI_QUIRK(0x144d, 0xc510, "Samsung Q45", ALC262_HIPPO),
- SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000 y410", ALC262_LENOVO_3000),
- SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
- SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_BENQ_T31),
- SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
- {}
-};
-
-static const struct alc_config_preset alc262_presets[] = {
- [ALC262_BASIC] = {
- .mixers = { alc262_base_mixer },
- .init_verbs = { alc262_init_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- },
- [ALC262_HIPPO] = {
- .mixers = { alc262_hippo_mixer },
- .init_verbs = { alc262_init_verbs, alc_hp15_unsol_verbs},
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .dig_out_nid = ALC262_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_hippo_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_HIPPO_1] = {
- .mixers = { alc262_hippo1_mixer },
- .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x02,
- .dig_out_nid = ALC262_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_hippo1_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_FUJITSU] = {
- .mixers = { alc262_fujitsu_mixer },
- .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
- alc262_fujitsu_unsol_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .dig_out_nid = ALC262_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_fujitsu_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_fujitsu_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_HP_BPC] = {
- .mixers = { alc262_HP_BPC_mixer },
- .init_verbs = { alc262_HP_BPC_init_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_HP_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_hp_bpc_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_HP_BPC_D7000_WF] = {
- .mixers = { alc262_HP_BPC_WildWest_mixer },
- .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_HP_D7000_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_hp_wildwest_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_HP_BPC_D7000_WL] = {
- .mixers = { alc262_HP_BPC_WildWest_mixer,
- alc262_HP_BPC_WildWest_option_mixer },
- .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_HP_D7000_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_hp_wildwest_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_HP_TC_T5735] = {
- .mixers = { alc262_hp_t5735_mixer },
- .init_verbs = { alc262_init_verbs, alc262_hp_t5735_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_hp_t5735_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_HP_RP5700] = {
- .mixers = { alc262_hp_rp5700_mixer },
- .init_verbs = { alc262_init_verbs, alc262_hp_rp5700_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_hp_rp5700_capture_source,
- },
- [ALC262_BENQ_ED8] = {
- .mixers = { alc262_base_mixer },
- .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- },
- [ALC262_SONY_ASSAMD] = {
- .mixers = { alc262_sony_mixer },
- .init_verbs = { alc262_init_verbs, alc262_sony_unsol_verbs},
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x02,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_hippo_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_BENQ_T31] = {
- .mixers = { alc262_benq_t31_mixer },
- .init_verbs = { alc262_init_verbs, alc262_benq_t31_EAPD_verbs,
- alc_hp15_unsol_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_hippo_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_ULTRA] = {
- .mixers = { alc262_ultra_mixer },
- .cap_mixer = alc262_ultra_capture_mixer,
- .init_verbs = { alc262_ultra_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_ultra_capture_source,
- .adc_nids = alc262_adc_nids, /* ADC0 */
- .capsrc_nids = alc262_capsrc_nids,
- .num_adc_nids = 1, /* single ADC */
- .unsol_event = alc262_ultra_unsol_event,
- .init_hook = alc262_ultra_automute,
- },
- [ALC262_LENOVO_3000] = {
- .mixers = { alc262_lenovo_3000_mixer },
- .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs,
- alc262_lenovo_3000_unsol_verbs,
- alc262_lenovo_3000_init_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .dig_out_nid = ALC262_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_fujitsu_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_lenovo_3000_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_NEC] = {
- .mixers = { alc262_nec_mixer },
- .init_verbs = { alc262_nec_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- },
- [ALC262_TOSHIBA_S06] = {
- .mixers = { alc262_toshiba_s06_mixer },
- .init_verbs = { alc262_init_verbs, alc262_toshiba_s06_verbs,
- alc262_eapd_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .capsrc_nids = alc262_dmic_capsrc_nids,
- .dac_nids = alc262_dac_nids,
- .adc_nids = alc262_dmic_adc_nids, /* ADC0 */
- .num_adc_nids = 1, /* single ADC */
- .dig_out_nid = ALC262_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_toshiba_s06_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_TOSHIBA_RX1] = {
- .mixers = { alc262_toshiba_rx1_mixer },
- .init_verbs = { alc262_init_verbs, alc262_toshiba_rx1_unsol_verbs },
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_hippo_setup,
- .init_hook = alc_inithook,
- },
- [ALC262_TYAN] = {
- .mixers = { alc262_tyan_mixer },
- .init_verbs = { alc262_init_verbs, alc262_tyan_verbs},
- .num_dacs = ARRAY_SIZE(alc262_dac_nids),
- .dac_nids = alc262_dac_nids,
- .hp_nid = 0x02,
- .dig_out_nid = ALC262_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc262_modes),
- .channel_mode = alc262_modes,
- .input_mux = &alc262_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc262_tyan_setup,
- .init_hook = alc_hp_automute,
- },
-};
-
diff --git a/sound/pci/hda/alc268_quirks.c b/sound/pci/hda/alc268_quirks.c
deleted file mode 100644
index 2e5876ce71fe..000000000000
--- a/sound/pci/hda/alc268_quirks.c
+++ /dev/null
@@ -1,636 +0,0 @@
-/*
- * ALC267/ALC268 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC268 models */
-enum {
- ALC268_AUTO,
- ALC267_QUANTA_IL1,
- ALC268_3ST,
- ALC268_TOSHIBA,
- ALC268_ACER,
- ALC268_ACER_DMIC,
- ALC268_ACER_ASPIRE_ONE,
- ALC268_DELL,
- ALC268_ZEPTO,
-#ifdef CONFIG_SND_DEBUG
- ALC268_TEST,
-#endif
- ALC268_MODEL_LAST /* last tag */
-};
-
-/*
- * ALC268 channel source setting (2 channel)
- */
-#define ALC268_DIGOUT_NID ALC880_DIGOUT_NID
-#define alc268_modes alc260_modes
-
-static const hda_nid_t alc268_dac_nids[2] = {
- /* front, hp */
- 0x02, 0x03
-};
-
-static const hda_nid_t alc268_adc_nids[2] = {
- /* ADC0-1 */
- 0x08, 0x07
-};
-
-static const hda_nid_t alc268_adc_nids_alt[1] = {
- /* ADC0 */
- 0x08
-};
-
-static const hda_nid_t alc268_capsrc_nids[2] = { 0x23, 0x24 };
-
-static const struct snd_kcontrol_new alc268_base_mixer[] = {
- /* output mixer control */
- HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
- { }
-};
-
-static const struct snd_kcontrol_new alc268_toshiba_mixer[] = {
- /* output mixer control */
- HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
- ALC262_HIPPO_MASTER_SWITCH,
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
- { }
-};
-
-static const struct hda_verb alc268_eapd_verbs[] = {
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-/* Toshiba specific */
-static const struct hda_verb alc268_toshiba_verbs[] = {
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { } /* end */
-};
-
-/* Acer specific */
-/* bind volumes of both NID 0x02 and 0x03 */
-static const struct hda_bind_ctls alc268_acer_bind_master_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static void alc268_acer_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-#define alc268_acer_master_sw_get alc262_hp_master_sw_get
-#define alc268_acer_master_sw_put alc262_hp_master_sw_put
-
-static const struct snd_kcontrol_new alc268_acer_aspire_one_mixer[] = {
- /* output mixer control */
- HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_NID_FLAG | 0x15,
- .info = snd_ctl_boolean_mono_info,
- .get = alc268_acer_master_sw_get,
- .put = alc268_acer_master_sw_put,
- },
- HDA_CODEC_VOLUME("Mic Boost Capture Volume", 0x18, 0, HDA_INPUT),
- { }
-};
-
-static const struct snd_kcontrol_new alc268_acer_mixer[] = {
- /* output mixer control */
- HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
- .info = snd_ctl_boolean_mono_info,
- .get = alc268_acer_master_sw_get,
- .put = alc268_acer_master_sw_put,
- },
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
- { }
-};
-
-static const struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
- /* output mixer control */
- HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_NID_FLAG | 0x14,
- .info = snd_ctl_boolean_mono_info,
- .get = alc268_acer_master_sw_get,
- .put = alc268_acer_master_sw_put,
- },
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line In Boost Volume", 0x1a, 0, HDA_INPUT),
- { }
-};
-
-static const struct hda_verb alc268_acer_aspire_one_verbs[] = {
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x23, AC_VERB_SET_CONNECT_SEL, 0x06},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, 0xa017},
- { }
-};
-
-static const struct hda_verb alc268_acer_verbs[] = {
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* internal dmic? */
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { }
-};
-
-/* unsolicited event for HP jack sensing */
-#define alc268_toshiba_setup alc262_hippo_setup
-
-static void alc268_acer_lc_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x12;
- spec->auto_mic = 1;
-}
-
-static const struct snd_kcontrol_new alc268_dell_mixer[] = {
- /* output mixer control */
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { }
-};
-
-static const struct hda_verb alc268_dell_verbs[] = {
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
- { }
-};
-
-/* mute/unmute internal speaker according to the hp jack and mute state */
-static void alc268_dell_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-static const struct snd_kcontrol_new alc267_quanta_il1_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x3, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Capture Volume", 0x23, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Mic Capture Switch", 0x23, 2, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { }
-};
-
-static const struct hda_verb alc267_quanta_il1_verbs[] = {
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
- { }
-};
-
-static void alc267_quanta_il1_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
-}
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc268_base_init_verbs[] = {
- /* Unmute DAC0-1 and set vol = 0 */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /*
- * Set up output mixers (0x0c - 0x0e)
- */
- /* set vol=0 to output mixers */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- /* set PCBEEP vol = 0, mute connections */
- {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
- /* Unmute Selector 23h,24h and set the default input to mic-in */
-
- {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- { }
-};
-
-/* only for model=test */
-#ifdef CONFIG_SND_DEBUG
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc268_volume_init_verbs[] = {
- /* set output DAC */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
- {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20},
-
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- { }
-};
-#endif /* CONFIG_SND_DEBUG */
-
-static const struct snd_kcontrol_new alc268_capture_nosrc_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
- _DEFINE_CAPSRC(1),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc268_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x24, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x24, 0x0, HDA_OUTPUT),
- _DEFINE_CAPSRC(2),
- { } /* end */
-};
-
-static const struct hda_input_mux alc268_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x3 },
- },
-};
-
-static const struct hda_input_mux alc268_acer_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Internal Mic", 0x1 },
- { "Line", 0x2 },
- },
-};
-
-static const struct hda_input_mux alc268_acer_dmic_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Internal Mic", 0x6 },
- { "Line", 0x2 },
- },
-};
-
-#ifdef CONFIG_SND_DEBUG
-static const struct snd_kcontrol_new alc268_test_mixer[] = {
- /* Volume widgets */
- HDA_CODEC_VOLUME("LOUT1 Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("LOUT2 Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Mono sum Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE("LINE-OUT sum Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_BIND_MUTE("HP-OUT sum Playback Switch", 0x10, 2, HDA_INPUT),
- HDA_BIND_MUTE("LINE-OUT Playback Switch", 0x14, 2, HDA_OUTPUT),
- HDA_BIND_MUTE("HP-OUT Playback Switch", 0x15, 2, HDA_OUTPUT),
- HDA_BIND_MUTE("Mono Playback Switch", 0x16, 2, HDA_OUTPUT),
- HDA_CODEC_VOLUME("MIC1 Capture Volume", 0x18, 0x0, HDA_INPUT),
- HDA_BIND_MUTE("MIC1 Capture Switch", 0x18, 2, HDA_OUTPUT),
- HDA_CODEC_VOLUME("MIC2 Capture Volume", 0x19, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("LINE1 Capture Volume", 0x1a, 0x0, HDA_INPUT),
- HDA_BIND_MUTE("LINE1 Capture Switch", 0x1a, 2, HDA_OUTPUT),
- /* The below appears problematic on some hardwares */
- /*HDA_CODEC_VOLUME("PCBEEP Playback Volume", 0x1d, 0x0, HDA_INPUT),*/
- HDA_CODEC_VOLUME("PCM-IN1 Capture Volume", 0x23, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("PCM-IN1 Capture Switch", 0x23, 2, HDA_OUTPUT),
- HDA_CODEC_VOLUME("PCM-IN2 Capture Volume", 0x24, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("PCM-IN2 Capture Switch", 0x24, 2, HDA_OUTPUT),
-
- /* Modes for retasking pin widgets */
- ALC_PIN_MODE("LINE-OUT pin mode", 0x14, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("HP-OUT pin mode", 0x15, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("MIC1 pin mode", 0x18, ALC_PIN_DIR_INOUT),
- ALC_PIN_MODE("LINE1 pin mode", 0x1a, ALC_PIN_DIR_INOUT),
-
- /* Controls for GPIO pins, assuming they are configured as outputs */
- ALC_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
- ALC_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
- ALC_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
- ALC_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
-
- /* Switches to allow the digital SPDIF output pin to be enabled.
- * The ALC268 does not have an SPDIF input.
- */
- ALC_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x06, 0x01),
-
- /* A switch allowing EAPD to be enabled. Some laptops seem to use
- * this output to turn on an external amplifier.
- */
- ALC_EAPD_CTRL_SWITCH("LINE-OUT EAPD Enable Switch", 0x0f, 0x02),
- ALC_EAPD_CTRL_SWITCH("HP-OUT EAPD Enable Switch", 0x10, 0x02),
-
- { } /* end */
-};
-#endif
-
-/*
- * configuration and preset
- */
-static const char * const alc268_models[ALC268_MODEL_LAST] = {
- [ALC267_QUANTA_IL1] = "quanta-il1",
- [ALC268_3ST] = "3stack",
- [ALC268_TOSHIBA] = "toshiba",
- [ALC268_ACER] = "acer",
- [ALC268_ACER_DMIC] = "acer-dmic",
- [ALC268_ACER_ASPIRE_ONE] = "acer-aspire",
- [ALC268_DELL] = "dell",
- [ALC268_ZEPTO] = "zepto",
-#ifdef CONFIG_SND_DEBUG
- [ALC268_TEST] = "test",
-#endif
- [ALC268_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc268_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1025, 0x011e, "Acer Aspire 5720z", ALC268_ACER),
- SND_PCI_QUIRK(0x1025, 0x0126, "Acer", ALC268_ACER),
- SND_PCI_QUIRK(0x1025, 0x012e, "Acer Aspire 5310", ALC268_ACER),
- SND_PCI_QUIRK(0x1025, 0x0130, "Acer Extensa 5210", ALC268_ACER),
- SND_PCI_QUIRK(0x1025, 0x0136, "Acer Aspire 5315", ALC268_ACER),
- SND_PCI_QUIRK(0x1025, 0x015b, "Acer Aspire One",
- ALC268_ACER_ASPIRE_ONE),
- SND_PCI_QUIRK(0x1028, 0x0253, "Dell OEM", ALC268_DELL),
- SND_PCI_QUIRK(0x1028, 0x02b0, "Dell Inspiron 910", ALC268_AUTO),
- SND_PCI_QUIRK_MASK(0x1028, 0xfff0, 0x02b0,
- "Dell Inspiron Mini9/Vostro A90", ALC268_DELL),
- /* almost compatible with toshiba but with optional digital outs;
- * auto-probing seems working fine
- */
- SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP TX25xx series",
- ALC268_AUTO),
- SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC268_3ST),
- SND_PCI_QUIRK(0x1170, 0x0040, "ZEPTO", ALC268_ZEPTO),
- SND_PCI_QUIRK(0x14c0, 0x0025, "COMPAL IFL90/JFL-92", ALC268_TOSHIBA),
- SND_PCI_QUIRK(0x152d, 0x0771, "Quanta IL1", ALC267_QUANTA_IL1),
- {}
-};
-
-/* Toshiba laptops have no unique PCI SSID but only codec SSID */
-static const struct snd_pci_quirk alc268_ssid_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1179, 0xff0a, "TOSHIBA X-200", ALC268_AUTO),
- SND_PCI_QUIRK(0x1179, 0xff0e, "TOSHIBA X-200 HDMI", ALC268_AUTO),
- SND_PCI_QUIRK_MASK(0x1179, 0xff00, 0xff00, "TOSHIBA A/Lx05",
- ALC268_TOSHIBA),
- {}
-};
-
-static const struct alc_config_preset alc268_presets[] = {
- [ALC267_QUANTA_IL1] = {
- .mixers = { alc267_quanta_il1_mixer, alc268_beep_mixer },
- .cap_mixer = alc268_capture_nosrc_mixer,
- .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
- alc267_quanta_il1_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc267_quanta_il1_setup,
- .init_hook = alc_inithook,
- },
- [ALC268_3ST] = {
- .mixers = { alc268_base_mixer, alc268_beep_mixer },
- .cap_mixer = alc268_capture_alt_mixer,
- .init_verbs = { alc268_base_init_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .capsrc_nids = alc268_capsrc_nids,
- .hp_nid = 0x03,
- .dig_out_nid = ALC268_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .input_mux = &alc268_capture_source,
- },
- [ALC268_TOSHIBA] = {
- .mixers = { alc268_toshiba_mixer, alc268_beep_mixer },
- .cap_mixer = alc268_capture_alt_mixer,
- .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
- alc268_toshiba_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .capsrc_nids = alc268_capsrc_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .input_mux = &alc268_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc268_toshiba_setup,
- .init_hook = alc_inithook,
- },
- [ALC268_ACER] = {
- .mixers = { alc268_acer_mixer, alc268_beep_mixer },
- .cap_mixer = alc268_capture_alt_mixer,
- .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
- alc268_acer_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .capsrc_nids = alc268_capsrc_nids,
- .hp_nid = 0x02,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .input_mux = &alc268_acer_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc268_acer_setup,
- .init_hook = alc_inithook,
- },
- [ALC268_ACER_DMIC] = {
- .mixers = { alc268_acer_dmic_mixer, alc268_beep_mixer },
- .cap_mixer = alc268_capture_alt_mixer,
- .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
- alc268_acer_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .capsrc_nids = alc268_capsrc_nids,
- .hp_nid = 0x02,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .input_mux = &alc268_acer_dmic_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc268_acer_setup,
- .init_hook = alc_inithook,
- },
- [ALC268_ACER_ASPIRE_ONE] = {
- .mixers = { alc268_acer_aspire_one_mixer, alc268_beep_mixer},
- .cap_mixer = alc268_capture_nosrc_mixer,
- .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
- alc268_acer_aspire_one_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .capsrc_nids = alc268_capsrc_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc268_acer_lc_setup,
- .init_hook = alc_inithook,
- },
- [ALC268_DELL] = {
- .mixers = { alc268_dell_mixer, alc268_beep_mixer},
- .cap_mixer = alc268_capture_nosrc_mixer,
- .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
- alc268_dell_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .capsrc_nids = alc268_capsrc_nids,
- .hp_nid = 0x02,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc268_dell_setup,
- .init_hook = alc_inithook,
- },
- [ALC268_ZEPTO] = {
- .mixers = { alc268_base_mixer, alc268_beep_mixer },
- .cap_mixer = alc268_capture_alt_mixer,
- .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
- alc268_toshiba_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .capsrc_nids = alc268_capsrc_nids,
- .hp_nid = 0x03,
- .dig_out_nid = ALC268_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .input_mux = &alc268_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc268_toshiba_setup,
- .init_hook = alc_inithook,
- },
-#ifdef CONFIG_SND_DEBUG
- [ALC268_TEST] = {
- .mixers = { alc268_test_mixer },
- .cap_mixer = alc268_capture_mixer,
- .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
- alc268_volume_init_verbs,
- alc268_beep_init_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .capsrc_nids = alc268_capsrc_nids,
- .hp_nid = 0x03,
- .dig_out_nid = ALC268_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .input_mux = &alc268_capture_source,
- },
-#endif
-};
-
diff --git a/sound/pci/hda/alc269_quirks.c b/sound/pci/hda/alc269_quirks.c
deleted file mode 100644
index 5ac0e2162a46..000000000000
--- a/sound/pci/hda/alc269_quirks.c
+++ /dev/null
@@ -1,674 +0,0 @@
-/*
- * ALC269/ALC270/ALC275/ALC276 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC269 models */
-enum {
- ALC269_AUTO,
- ALC269_BASIC,
- ALC269_QUANTA_FL1,
- ALC269_AMIC,
- ALC269_DMIC,
- ALC269VB_AMIC,
- ALC269VB_DMIC,
- ALC269_FUJITSU,
- ALC269_LIFEBOOK,
- ALC271_ACER,
- ALC269_MODEL_LAST /* last tag */
-};
-
-/*
- * ALC269 channel source setting (2 channel)
- */
-#define ALC269_DIGOUT_NID ALC880_DIGOUT_NID
-
-#define alc269_dac_nids alc260_dac_nids
-
-static const hda_nid_t alc269_adc_nids[1] = {
- /* ADC1 */
- 0x08,
-};
-
-static const hda_nid_t alc269_capsrc_nids[1] = {
- 0x23,
-};
-
-static const hda_nid_t alc269vb_adc_nids[1] = {
- /* ADC1 */
- 0x09,
-};
-
-static const hda_nid_t alc269vb_capsrc_nids[1] = {
- 0x22,
-};
-
-#define alc269_modes alc260_modes
-#define alc269_capture_source alc880_lg_lw_capture_source
-
-static const struct snd_kcontrol_new alc269_base_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
- /* output mixer control */
- HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- },
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { }
-};
-
-static const struct snd_kcontrol_new alc269_lifebook_mixer[] = {
- /* output mixer control */
- HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .subdevice = HDA_SUBDEV_AMP_FLAG,
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- },
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
- HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
- HDA_CODEC_VOLUME("Dock Mic Boost Volume", 0x1b, 0, HDA_INPUT),
- { }
-};
-
-static const struct snd_kcontrol_new alc269_laptop_mixer[] = {
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc269vb_laptop_mixer[] = {
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc269_asus_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-/* capture mixer elements */
-static const struct snd_kcontrol_new alc269_laptop_analog_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc269_laptop_digital_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc269vb_laptop_analog_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc269vb_laptop_digital_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- { } /* end */
-};
-
-/* FSC amilo */
-#define alc269_fujitsu_mixer alc269_laptop_mixer
-
-static const struct hda_verb alc269_quanta_fl1_verbs[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- { }
-};
-
-static const struct hda_verb alc269_lifebook_verbs[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- { }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
-{
- alc_hp_automute(codec);
-
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_COEF_INDEX, 0x0c);
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_PROC_COEF, 0x680);
-
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_COEF_INDEX, 0x0c);
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_PROC_COEF, 0x480);
-}
-
-#define alc269_lifebook_speaker_automute \
- alc269_quanta_fl1_speaker_automute
-
-static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
-{
- unsigned int present_laptop;
- unsigned int present_dock;
-
- present_laptop = snd_hda_jack_detect(codec, 0x18);
- present_dock = snd_hda_jack_detect(codec, 0x1b);
-
- /* Laptop mic port overrides dock mic port, design decision */
- if (present_dock)
- snd_hda_codec_write(codec, 0x23, 0,
- AC_VERB_SET_CONNECT_SEL, 0x3);
- if (present_laptop)
- snd_hda_codec_write(codec, 0x23, 0,
- AC_VERB_SET_CONNECT_SEL, 0x0);
- if (!present_dock && !present_laptop)
- snd_hda_codec_write(codec, 0x23, 0,
- AC_VERB_SET_CONNECT_SEL, 0x1);
-}
-
-static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC_HP_EVENT:
- alc269_quanta_fl1_speaker_automute(codec);
- break;
- case ALC_MIC_EVENT:
- alc_mic_automute(codec);
- break;
- }
-}
-
-static void alc269_lifebook_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC_HP_EVENT)
- alc269_lifebook_speaker_automute(codec);
- if ((res >> 26) == ALC_MIC_EVENT)
- alc269_lifebook_mic_autoswitch(codec);
-}
-
-static void alc269_quanta_fl1_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
-{
- alc269_quanta_fl1_speaker_automute(codec);
- alc_mic_automute(codec);
-}
-
-static void alc269_lifebook_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.hp_pins[1] = 0x1a;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
-}
-
-static void alc269_lifebook_init_hook(struct hda_codec *codec)
-{
- alc269_lifebook_speaker_automute(codec);
- alc269_lifebook_mic_autoswitch(codec);
-}
-
-static const struct hda_verb alc269_laptop_dmic_init_verbs[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc269_laptop_amic_init_verbs[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x23, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, (0x701b | (0x00 << 8))},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc269vb_laptop_dmic_init_verbs[] = {
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x22, AC_VERB_SET_CONNECT_SEL, 0x06},
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc269vb_laptop_amic_init_verbs[] = {
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x22, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, 0xb026 },
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, (0x7019 | (0x00 << 8))},
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc271_acer_dmic_verbs[] = {
- {0x20, AC_VERB_SET_COEF_INDEX, 0x0d},
- {0x20, AC_VERB_SET_PROC_COEF, 0x4000},
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x22, AC_VERB_SET_CONNECT_SEL, 6},
- { }
-};
-
-static void alc269_laptop_amic_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-static void alc269_laptop_dmic_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x12;
- spec->auto_mic = 1;
-}
-
-static void alc269vb_laptop_amic_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x21;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-static void alc269vb_laptop_dmic_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x21;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x12;
- spec->auto_mic = 1;
-}
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc269_init_verbs[] = {
- /*
- * Unmute ADC0 and set the default input to mic-in
- */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /*
- * Set up output mixers (0x02 - 0x03)
- */
- /* set vol=0 to output mixers */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* set up input amps for analog loopback */
- /* Amp Indices: DAC = 0, mixer = 1 */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* FIXME: use Mux-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
- /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x23, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* set EAPD */
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-static const struct hda_verb alc269vb_init_verbs[] = {
- /*
- * Unmute ADC0 and set the default input to mic-in
- */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /*
- * Set up output mixers (0x02 - 0x03)
- */
- /* set vol=0 to output mixers */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* set up input amps for analog loopback */
- /* Amp Indices: DAC = 0, mixer = 1 */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* FIXME: use Mux-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1d, 0b */
- /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x22, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* set EAPD */
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-/*
- * configuration and preset
- */
-static const char * const alc269_models[ALC269_MODEL_LAST] = {
- [ALC269_BASIC] = "basic",
- [ALC269_QUANTA_FL1] = "quanta",
- [ALC269_AMIC] = "laptop-amic",
- [ALC269_DMIC] = "laptop-dmic",
- [ALC269_FUJITSU] = "fujitsu",
- [ALC269_LIFEBOOK] = "lifebook",
- [ALC269_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc269_cfg_tbl[] = {
- SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_QUANTA_FL1),
- SND_PCI_QUIRK(0x1025, 0x047c, "ACER ZGA", ALC271_ACER),
- SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
- ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269VB_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1113, "ASUS N63Jn", ALC269VB_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269VB_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269VB_AMIC),
- SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269VB_AMIC),
- SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269VB_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269VB_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269VB_AMIC),
- SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_AMIC),
- SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_AMIC),
- SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_AUTO),
- SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
- SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_DMIC),
- SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
- SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_AMIC),
- SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_AMIC),
- SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_DMIC),
- SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_DMIC),
- {}
-};
-
-static const struct alc_config_preset alc269_presets[] = {
- [ALC269_BASIC] = {
- .mixers = { alc269_base_mixer },
- .init_verbs = { alc269_init_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .input_mux = &alc269_capture_source,
- },
- [ALC269_QUANTA_FL1] = {
- .mixers = { alc269_quanta_fl1_mixer },
- .init_verbs = { alc269_init_verbs, alc269_quanta_fl1_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .input_mux = &alc269_capture_source,
- .unsol_event = alc269_quanta_fl1_unsol_event,
- .setup = alc269_quanta_fl1_setup,
- .init_hook = alc269_quanta_fl1_init_hook,
- },
- [ALC269_AMIC] = {
- .mixers = { alc269_laptop_mixer },
- .cap_mixer = alc269_laptop_analog_capture_mixer,
- .init_verbs = { alc269_init_verbs,
- alc269_laptop_amic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc269_laptop_amic_setup,
- .init_hook = alc_inithook,
- },
- [ALC269_DMIC] = {
- .mixers = { alc269_laptop_mixer },
- .cap_mixer = alc269_laptop_digital_capture_mixer,
- .init_verbs = { alc269_init_verbs,
- alc269_laptop_dmic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc269_laptop_dmic_setup,
- .init_hook = alc_inithook,
- },
- [ALC269VB_AMIC] = {
- .mixers = { alc269vb_laptop_mixer },
- .cap_mixer = alc269vb_laptop_analog_capture_mixer,
- .init_verbs = { alc269vb_init_verbs,
- alc269vb_laptop_amic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc269vb_laptop_amic_setup,
- .init_hook = alc_inithook,
- },
- [ALC269VB_DMIC] = {
- .mixers = { alc269vb_laptop_mixer },
- .cap_mixer = alc269vb_laptop_digital_capture_mixer,
- .init_verbs = { alc269vb_init_verbs,
- alc269vb_laptop_dmic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc269vb_laptop_dmic_setup,
- .init_hook = alc_inithook,
- },
- [ALC269_FUJITSU] = {
- .mixers = { alc269_fujitsu_mixer },
- .cap_mixer = alc269_laptop_digital_capture_mixer,
- .init_verbs = { alc269_init_verbs,
- alc269_laptop_dmic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc269_laptop_dmic_setup,
- .init_hook = alc_inithook,
- },
- [ALC269_LIFEBOOK] = {
- .mixers = { alc269_lifebook_mixer },
- .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .input_mux = &alc269_capture_source,
- .unsol_event = alc269_lifebook_unsol_event,
- .setup = alc269_lifebook_setup,
- .init_hook = alc269_lifebook_init_hook,
- },
- [ALC271_ACER] = {
- .mixers = { alc269_asus_mixer },
- .cap_mixer = alc269vb_laptop_digital_capture_mixer,
- .init_verbs = { alc269_init_verbs, alc271_acer_dmic_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .adc_nids = alc262_dmic_adc_nids,
- .num_adc_nids = ARRAY_SIZE(alc262_dmic_adc_nids),
- .capsrc_nids = alc262_dmic_capsrc_nids,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .input_mux = &alc269_capture_source,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc269vb_laptop_dmic_setup,
- .init_hook = alc_inithook,
- },
-};
-
diff --git a/sound/pci/hda/alc662_quirks.c b/sound/pci/hda/alc662_quirks.c
deleted file mode 100644
index e69a6ea3083a..000000000000
--- a/sound/pci/hda/alc662_quirks.c
+++ /dev/null
@@ -1,1408 +0,0 @@
-/*
- * ALC662/ALC663/ALC665/ALC670 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC662 models */
-enum {
- ALC662_AUTO,
- ALC662_3ST_2ch_DIG,
- ALC662_3ST_6ch_DIG,
- ALC662_3ST_6ch,
- ALC662_5ST_DIG,
- ALC662_LENOVO_101E,
- ALC662_ASUS_EEEPC_P701,
- ALC662_ASUS_EEEPC_EP20,
- ALC663_ASUS_M51VA,
- ALC663_ASUS_G71V,
- ALC663_ASUS_H13,
- ALC663_ASUS_G50V,
- ALC662_ECS,
- ALC663_ASUS_MODE1,
- ALC662_ASUS_MODE2,
- ALC663_ASUS_MODE3,
- ALC663_ASUS_MODE4,
- ALC663_ASUS_MODE5,
- ALC663_ASUS_MODE6,
- ALC663_ASUS_MODE7,
- ALC663_ASUS_MODE8,
- ALC272_DELL,
- ALC272_DELL_ZM1,
- ALC272_SAMSUNG_NC10,
- ALC662_MODEL_LAST,
-};
-
-#define ALC662_DIGOUT_NID 0x06
-#define ALC662_DIGIN_NID 0x0a
-
-static const hda_nid_t alc662_dac_nids[3] = {
- /* front, rear, clfe */
- 0x02, 0x03, 0x04
-};
-
-static const hda_nid_t alc272_dac_nids[2] = {
- 0x02, 0x03
-};
-
-static const hda_nid_t alc662_adc_nids[2] = {
- /* ADC1-2 */
- 0x09, 0x08
-};
-
-static const hda_nid_t alc272_adc_nids[1] = {
- /* ADC1-2 */
- 0x08,
-};
-
-static const hda_nid_t alc662_capsrc_nids[2] = { 0x22, 0x23 };
-static const hda_nid_t alc272_capsrc_nids[1] = { 0x23 };
-
-
-/* input MUX */
-/* FIXME: should be a matrix-type input source selection */
-static const struct hda_input_mux alc662_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux alc662_lenovo_101e_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x1 },
- { "Line", 0x2 },
- },
-};
-
-static const struct hda_input_mux alc663_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- },
-};
-
-#if 0 /* set to 1 for testing other input sources below */
-static const struct hda_input_mux alc272_nc10_capture_source = {
- .num_items = 16,
- .items = {
- { "Autoselect Mic", 0x0 },
- { "Internal Mic", 0x1 },
- { "In-0x02", 0x2 },
- { "In-0x03", 0x3 },
- { "In-0x04", 0x4 },
- { "In-0x05", 0x5 },
- { "In-0x06", 0x6 },
- { "In-0x07", 0x7 },
- { "In-0x08", 0x8 },
- { "In-0x09", 0x9 },
- { "In-0x0a", 0x0a },
- { "In-0x0b", 0x0b },
- { "In-0x0c", 0x0c },
- { "In-0x0d", 0x0d },
- { "In-0x0e", 0x0e },
- { "In-0x0f", 0x0f },
- },
-};
-#endif
-
-/*
- * 2ch mode
- */
-static const struct hda_channel_mode alc662_3ST_2ch_modes[1] = {
- { 2, NULL }
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc662_3ST_ch2_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc662_3ST_ch6_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc662_3ST_6ch_modes[2] = {
- { 2, alc662_3ST_ch2_init },
- { 6, alc662_3ST_ch6_init },
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc662_sixstack_ch6_init[] = {
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc662_sixstack_ch8_init[] = {
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc662_5stack_modes[2] = {
- { 2, alc662_sixstack_ch6_init },
- { 6, alc662_sixstack_ch8_init },
-};
-
-/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
- * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
- */
-
-static const struct snd_kcontrol_new alc662_base_mixer[] = {
- /* output mixer control */
- HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x3, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-
- /*Input mixer control */
- HDA_CODEC_VOLUME("CD Playback Volume", 0xb, 0x4, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0xb, 0x4, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0xb, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0xb, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0xb, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0xb, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0xb, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0xb, 0x01, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_3ST_2ch_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_3ST_6ch_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x0c, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x0d, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_lenovo_101e_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x02, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x03, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_eeepc_p701_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- ALC262_HIPPO_MASTER_SWITCH,
-
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_eeepc_ep20_mixer[] = {
- ALC262_HIPPO_MASTER_SWITCH,
- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("MuteCtrl Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_bind_ctls alc663_asus_bind_master_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x03, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct hda_bind_ctls alc663_asus_one_bind_switch = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct snd_kcontrol_new alc663_m51va_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
- HDA_BIND_SW("Master Playback Switch", &alc663_asus_one_bind_switch),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_bind_ctls alc663_asus_tree_bind_switch = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct snd_kcontrol_new alc663_two_hp_m1_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
- HDA_BIND_SW("Master Playback Switch", &alc663_asus_tree_bind_switch),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-
- { } /* end */
-};
-
-static const struct hda_bind_ctls alc663_asus_four_bind_switch = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct snd_kcontrol_new alc663_two_hp_m2_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
- HDA_BIND_SW("Master Playback Switch", &alc663_asus_four_bind_switch),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc662_1bjd_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("F-Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("F-Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_bind_ctls alc663_asus_two_bind_master_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x04, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct hda_bind_ctls alc663_asus_two_bind_switch = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x16, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct snd_kcontrol_new alc663_asus_21jd_clfe_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume",
- &alc663_asus_two_bind_master_vol),
- HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc663_asus_15jd_clfe_mixer[] = {
- HDA_BIND_VOL("Master Playback Volume", &alc663_asus_bind_master_vol),
- HDA_BIND_SW("Master Playback Switch", &alc663_asus_two_bind_switch),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc663_g71v_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Front Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc663_g50v_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_bind_ctls alc663_asus_mode7_8_all_bind_switch = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x15, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x1b, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x21, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct hda_bind_ctls alc663_asus_mode7_8_sp_bind_switch = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT),
- 0
- },
-};
-
-static const struct snd_kcontrol_new alc663_mode7_mixer[] = {
- HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
- HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
- HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
- HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("IntMic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("IntMic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc663_mode8_mixer[] = {
- HDA_BIND_SW("Master Playback Switch", &alc663_asus_mode7_8_all_bind_switch),
- HDA_BIND_VOL("Speaker Playback Volume", &alc663_asus_bind_master_vol),
- HDA_BIND_SW("Speaker Playback Switch", &alc663_asus_mode7_8_sp_bind_switch),
- HDA_CODEC_MUTE("Headphone1 Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone2 Playback Switch", 0x21, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-
-static const struct snd_kcontrol_new alc662_chmode_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc662_init_verbs[] = {
- /* ADC: mute amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- /* Front Pin: output 0 (0x0c) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Rear Pin: output 1 (0x0d) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* CLFE Pin: output 2 (0x0e) */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Mic (rear) pin: input vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin: input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line-2 In: Headphone output (output 0 - 0x0c) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- /* FIXME: use matrix-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
- /* Input mixer */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- { }
-};
-
-static const struct hda_verb alc662_eapd_init_verbs[] = {
- /* always trun on EAPD */
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-static const struct hda_verb alc662_sue_init_verbs[] = {
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_FRONT_EVENT},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc662_eeepc_sue_init_verbs[] = {
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-/* Set Unsolicited Event*/
-static const struct hda_verb alc662_eeepc_ep20_sue_init_verbs[] = {
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc663_m51va_init_verbs[] = {
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc663_21jd_amic_init_verbs[] = {
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc662_1bjd_amic_init_verbs[] = {
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc663_15jd_amic_init_verbs[] = {
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc663_two_hp_amic_m1_init_verbs[] = {
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x0}, /* Headphone */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc663_two_hp_amic_m2_init_verbs[] = {
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc663_g71v_init_verbs[] = {
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
- /* {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, */ /* Headphone */
-
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
-
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_FRONT_EVENT},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc663_g50v_init_verbs[] = {
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Headphone */
-
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc662_ecs_init_verbs[] = {
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, 0x701f},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc272_dell_zm1_init_verbs[] = {
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc272_dell_init_verbs[] = {
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc663_mode7_init_verbs[] = {
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
- {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct hda_verb alc663_mode8_init_verbs[] = {
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x21, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x21, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x21, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Headphone */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(9)},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {}
-};
-
-static const struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc272_auto_capture_mixer[] = {
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static void alc662_lenovo_101e_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.line_out_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->detect_line = 1;
- spec->automute_lines = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc662_eeepc_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- alc262_hippo1_setup(codec);
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-static void alc662_eeepc_ep20_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x1b;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc663_m51va_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x21;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x12;
- spec->auto_mic = 1;
-}
-
-/* ***************** Mode1 ******************************/
-static void alc663_mode1_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x21;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-/* ***************** Mode2 ******************************/
-static void alc662_mode2_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-/* ***************** Mode3 ******************************/
-static void alc663_mode3_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x21;
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-/* ***************** Mode4 ******************************/
-static void alc663_mode4_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x21;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute_mixer_nid[1] = 0x0e;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-/* ***************** Mode5 ******************************/
-static void alc663_mode5_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute_mixer_nid[1] = 0x0e;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-/* ***************** Mode6 ******************************/
-static void alc663_mode6_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute_mixer_nid[0] = 0x0c;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_MIXER;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-/* ***************** Mode7 ******************************/
-static void alc663_mode7_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.hp_pins[0] = 0x21;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x17;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
-}
-
-/* ***************** Mode8 ******************************/
-static void alc663_mode8_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x21;
- spec->autocfg.hp_pins[1] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x17;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x12;
- spec->auto_mic = 1;
-}
-
-static void alc663_g71v_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x21;
- spec->autocfg.line_out_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
- spec->detect_line = 1;
- spec->automute_lines = 1;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x12;
- spec->auto_mic = 1;
-}
-
-#define alc663_g50v_setup alc663_m51va_setup
-
-static const struct snd_kcontrol_new alc662_ecs_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- ALC262_HIPPO_MASTER_SWITCH,
-
- HDA_CODEC_VOLUME("Mic/LineIn Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic/LineIn Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic/LineIn Playback Switch", 0x0b, 0x0, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc272_nc10_mixer[] = {
- /* Master Playback automatically created from Speaker and Headphone */
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x21, 0x0, HDA_OUTPUT),
-
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { } /* end */
-};
-
-
-/*
- * configuration and preset
- */
-static const char * const alc662_models[ALC662_MODEL_LAST] = {
- [ALC662_3ST_2ch_DIG] = "3stack-dig",
- [ALC662_3ST_6ch_DIG] = "3stack-6ch-dig",
- [ALC662_3ST_6ch] = "3stack-6ch",
- [ALC662_5ST_DIG] = "5stack-dig",
- [ALC662_LENOVO_101E] = "lenovo-101e",
- [ALC662_ASUS_EEEPC_P701] = "eeepc-p701",
- [ALC662_ASUS_EEEPC_EP20] = "eeepc-ep20",
- [ALC662_ECS] = "ecs",
- [ALC663_ASUS_M51VA] = "m51va",
- [ALC663_ASUS_G71V] = "g71v",
- [ALC663_ASUS_H13] = "h13",
- [ALC663_ASUS_G50V] = "g50v",
- [ALC663_ASUS_MODE1] = "asus-mode1",
- [ALC662_ASUS_MODE2] = "asus-mode2",
- [ALC663_ASUS_MODE3] = "asus-mode3",
- [ALC663_ASUS_MODE4] = "asus-mode4",
- [ALC663_ASUS_MODE5] = "asus-mode5",
- [ALC663_ASUS_MODE6] = "asus-mode6",
- [ALC663_ASUS_MODE7] = "asus-mode7",
- [ALC663_ASUS_MODE8] = "asus-mode8",
- [ALC272_DELL] = "dell",
- [ALC272_DELL_ZM1] = "dell-zm1",
- [ALC272_SAMSUNG_NC10] = "samsung-nc10",
- [ALC662_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc662_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_ECS),
- SND_PCI_QUIRK(0x1028, 0x02d6, "DELL", ALC272_DELL),
- SND_PCI_QUIRK(0x1028, 0x02f4, "DELL ZM1", ALC272_DELL_ZM1),
- SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC663_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC663_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC663_ASUS_MODE7),
- SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC663_ASUS_MODE7),
- SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC663_ASUS_MODE8),
- SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC663_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC663_ASUS_MODE6),
- SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC663_ASUS_MODE6),
- SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC663_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x17c3, "ASUS UX20", ALC663_ASUS_M51VA),
- SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC663_ASUS_MODE5),
- SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC663_ASUS_MODE6),
- SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M51VA", ALC663_ASUS_M51VA),
- /*SND_PCI_QUIRK(0x1043, 0x1878, "ASUS M50Vr", ALC663_ASUS_MODE1),*/
- SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC663_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC663_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC663_ASUS_MODE3),
- SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS G50V", ALC663_ASUS_G50V),
- /*SND_PCI_QUIRK(0x1043, 0x19a3, "ASUS NB", ALC663_ASUS_MODE1),*/
- SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_ASUS_MODE2),
- SND_PCI_QUIRK(0x1043, 0x19d3, "ASUS NB", ALC663_ASUS_M51VA),
- SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC663_ASUS_MODE1),
- SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC663_ASUS_MODE4),
- SND_PCI_QUIRK(0x1043, 0x8290, "ASUS P5GC-MX", ALC662_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x1043, 0x82a1, "ASUS Eeepc", ALC662_ASUS_EEEPC_P701),
- SND_PCI_QUIRK(0x1043, 0x82d1, "ASUS Eeepc EP20", ALC662_ASUS_EEEPC_EP20),
- SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_ECS),
- SND_PCI_QUIRK(0x105b, 0x0d47, "Foxconn 45CMX/45GMX/45CMX-K",
- ALC662_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x1179, 0xff6e, "Toshiba NB20x", ALC662_AUTO),
- SND_PCI_QUIRK(0x144d, 0xca00, "Samsung NC10", ALC272_SAMSUNG_NC10),
- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte 945GCM-S2L",
- ALC662_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x152d, 0x2304, "Quanta WH1", ALC663_ASUS_H13),
- SND_PCI_QUIRK(0x1565, 0x820f, "Biostar TA780G M2+", ALC662_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x1631, 0xc10c, "PB RS65", ALC663_ASUS_M51VA),
- SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo", ALC662_LENOVO_101E),
- SND_PCI_QUIRK(0x1849, 0x3662, "ASROCK K10N78FullHD-hSLI R3.0",
- ALC662_3ST_6ch_DIG),
- SND_PCI_QUIRK_MASK(0x1854, 0xf000, 0x2000, "ASUS H13-200x",
- ALC663_ASUS_H13),
- SND_PCI_QUIRK(0x1991, 0x5628, "Ordissimo EVE", ALC662_LENOVO_101E),
- {}
-};
-
-static const struct alc_config_preset alc662_presets[] = {
- [ALC662_3ST_2ch_DIG] = {
- .mixers = { alc662_3ST_2ch_mixer },
- .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .dig_in_nid = ALC662_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .input_mux = &alc662_capture_source,
- },
- [ALC662_3ST_6ch_DIG] = {
- .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .dig_in_nid = ALC662_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
- .channel_mode = alc662_3ST_6ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc662_capture_source,
- },
- [ALC662_3ST_6ch] = {
- .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
- .channel_mode = alc662_3ST_6ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc662_capture_source,
- },
- [ALC662_5ST_DIG] = {
- .mixers = { alc662_base_mixer, alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs, alc662_eapd_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .dig_in_nid = ALC662_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_5stack_modes),
- .channel_mode = alc662_5stack_modes,
- .input_mux = &alc662_capture_source,
- },
- [ALC662_LENOVO_101E] = {
- .mixers = { alc662_lenovo_101e_mixer },
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc662_sue_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .input_mux = &alc662_lenovo_101e_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc662_lenovo_101e_setup,
- .init_hook = alc_inithook,
- },
- [ALC662_ASUS_EEEPC_P701] = {
- .mixers = { alc662_eeepc_p701_mixer },
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc662_eeepc_sue_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc662_eeepc_setup,
- .init_hook = alc_inithook,
- },
- [ALC662_ASUS_EEEPC_EP20] = {
- .mixers = { alc662_eeepc_ep20_mixer,
- alc662_chmode_mixer },
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc662_eeepc_ep20_sue_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
- .channel_mode = alc662_3ST_6ch_modes,
- .input_mux = &alc662_lenovo_101e_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc662_eeepc_ep20_setup,
- .init_hook = alc_inithook,
- },
- [ALC662_ECS] = {
- .mixers = { alc662_ecs_mixer },
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc662_ecs_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc662_eeepc_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_M51VA] = {
- .mixers = { alc663_m51va_mixer },
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_m51va_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_m51va_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_G71V] = {
- .mixers = { alc663_g71v_mixer },
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_g71v_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_g71v_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_H13] = {
- .mixers = { alc663_m51va_mixer },
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_m51va_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .setup = alc663_m51va_setup,
- .unsol_event = alc_sku_unsol_event,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_G50V] = {
- .mixers = { alc663_g50v_mixer },
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_g50v_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_6ch_modes),
- .channel_mode = alc662_3ST_6ch_modes,
- .input_mux = &alc663_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_g50v_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_MODE1] = {
- .mixers = { alc663_m51va_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_21jd_amic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .hp_nid = 0x03,
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_mode1_setup,
- .init_hook = alc_inithook,
- },
- [ALC662_ASUS_MODE2] = {
- .mixers = { alc662_1bjd_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc662_1bjd_amic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc662_mode2_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_MODE3] = {
- .mixers = { alc663_two_hp_m1_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_two_hp_amic_m1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .hp_nid = 0x03,
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_mode3_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_MODE4] = {
- .mixers = { alc663_asus_21jd_clfe_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_21jd_amic_init_verbs},
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .hp_nid = 0x03,
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_mode4_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_MODE5] = {
- .mixers = { alc663_asus_15jd_clfe_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_15jd_amic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .hp_nid = 0x03,
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_mode5_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_MODE6] = {
- .mixers = { alc663_two_hp_m2_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_two_hp_amic_m2_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .hp_nid = 0x03,
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_mode6_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_MODE7] = {
- .mixers = { alc663_mode7_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_mode7_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .hp_nid = 0x03,
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_mode7_setup,
- .init_hook = alc_inithook,
- },
- [ALC663_ASUS_MODE8] = {
- .mixers = { alc663_mode8_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_mode8_init_verbs },
- .num_dacs = ARRAY_SIZE(alc662_dac_nids),
- .hp_nid = 0x03,
- .dac_nids = alc662_dac_nids,
- .dig_out_nid = ALC662_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_mode8_setup,
- .init_hook = alc_inithook,
- },
- [ALC272_DELL] = {
- .mixers = { alc663_m51va_mixer },
- .cap_mixer = alc272_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc272_dell_init_verbs },
- .num_dacs = ARRAY_SIZE(alc272_dac_nids),
- .dac_nids = alc272_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .adc_nids = alc272_adc_nids,
- .num_adc_nids = ARRAY_SIZE(alc272_adc_nids),
- .capsrc_nids = alc272_capsrc_nids,
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_m51va_setup,
- .init_hook = alc_inithook,
- },
- [ALC272_DELL_ZM1] = {
- .mixers = { alc663_m51va_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc272_dell_zm1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc272_dac_nids),
- .dac_nids = alc272_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .adc_nids = alc662_adc_nids,
- .num_adc_nids = 1,
- .capsrc_nids = alc662_capsrc_nids,
- .channel_mode = alc662_3ST_2ch_modes,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_m51va_setup,
- .init_hook = alc_inithook,
- },
- [ALC272_SAMSUNG_NC10] = {
- .mixers = { alc272_nc10_mixer },
- .init_verbs = { alc662_init_verbs,
- alc662_eapd_init_verbs,
- alc663_21jd_amic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc272_dac_nids),
- .dac_nids = alc272_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc662_3ST_2ch_modes),
- .channel_mode = alc662_3ST_2ch_modes,
- /*.input_mux = &alc272_nc10_capture_source,*/
- .unsol_event = alc_sku_unsol_event,
- .setup = alc663_mode4_setup,
- .init_hook = alc_inithook,
- },
-};
-
-
diff --git a/sound/pci/hda/alc680_quirks.c b/sound/pci/hda/alc680_quirks.c
deleted file mode 100644
index 0eeb227c7bc2..000000000000
--- a/sound/pci/hda/alc680_quirks.c
+++ /dev/null
@@ -1,222 +0,0 @@
-/*
- * ALC680 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC680 models */
-enum {
- ALC680_AUTO,
- ALC680_BASE,
- ALC680_MODEL_LAST,
-};
-
-#define ALC680_DIGIN_NID ALC880_DIGIN_NID
-#define ALC680_DIGOUT_NID ALC880_DIGOUT_NID
-#define alc680_modes alc260_modes
-
-static const hda_nid_t alc680_dac_nids[3] = {
- /* Lout1, Lout2, hp */
- 0x02, 0x03, 0x04
-};
-
-static const hda_nid_t alc680_adc_nids[3] = {
- /* ADC0-2 */
- /* DMIC, MIC, Line-in*/
- 0x07, 0x08, 0x09
-};
-
-/*
- * Analog capture ADC cgange
- */
-static hda_nid_t alc680_get_cur_adc(struct hda_codec *codec)
-{
- static hda_nid_t pins[] = {0x18, 0x19};
- static hda_nid_t adcs[] = {0x08, 0x09};
- int i;
-
- for (i = 0; i < ARRAY_SIZE(pins); i++) {
- if (!is_jack_detectable(codec, pins[i]))
- continue;
- if (snd_hda_jack_detect(codec, pins[i]))
- return adcs[i];
- }
- return 0x07;
-}
-
-static void alc680_rec_autoswitch(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t nid = alc680_get_cur_adc(codec);
- if (spec->cur_adc && nid != spec->cur_adc) {
- __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1);
- spec->cur_adc = nid;
- snd_hda_codec_setup_stream(codec, nid,
- spec->cur_adc_stream_tag, 0,
- spec->cur_adc_format);
- }
-}
-
-static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- struct alc_spec *spec = codec->spec;
- hda_nid_t nid = alc680_get_cur_adc(codec);
-
- spec->cur_adc = nid;
- spec->cur_adc_stream_tag = stream_tag;
- spec->cur_adc_format = format;
- snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
- return 0;
-}
-
-static int alc680_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct alc_spec *spec = codec->spec;
- snd_hda_codec_cleanup_stream(codec, spec->cur_adc);
- spec->cur_adc = 0;
- return 0;
-}
-
-static const struct hda_pcm_stream alc680_pcm_analog_auto_capture = {
- .substreams = 1, /* can be overridden */
- .channels_min = 2,
- .channels_max = 2,
- /* NID is set in alc_build_pcms */
- .ops = {
- .prepare = alc680_capture_pcm_prepare,
- .cleanup = alc680_capture_pcm_cleanup
- },
-};
-
-static const struct snd_kcontrol_new alc680_base_mixer[] = {
- /* output mixer control */
- HDA_CODEC_VOLUME("Front Playback Volume", 0x2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x4, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x16, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x12, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line In Boost Volume", 0x19, 0, HDA_INPUT),
- { }
-};
-
-static const struct hda_bind_ctls alc680_bind_cap_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
- HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
- HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
- 0
- },
-};
-
-static const struct hda_bind_ctls alc680_bind_cap_switch = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x07, 3, 0, HDA_INPUT),
- HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
- HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
- 0
- },
-};
-
-static const struct snd_kcontrol_new alc680_master_capture_mixer[] = {
- HDA_BIND_VOL("Capture Volume", &alc680_bind_cap_vol),
- HDA_BIND_SW("Capture Switch", &alc680_bind_cap_switch),
- { } /* end */
-};
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc680_init_verbs[] = {
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
- {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
-
- { }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc680_base_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x16;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x15;
- spec->autocfg.num_inputs = 2;
- spec->autocfg.inputs[0].pin = 0x18;
- spec->autocfg.inputs[0].type = AUTO_PIN_MIC;
- spec->autocfg.inputs[1].pin = 0x19;
- spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc680_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC_HP_EVENT)
- alc_hp_automute(codec);
- if ((res >> 26) == ALC_MIC_EVENT)
- alc680_rec_autoswitch(codec);
-}
-
-static void alc680_inithook(struct hda_codec *codec)
-{
- alc_hp_automute(codec);
- alc680_rec_autoswitch(codec);
-}
-
-/*
- * configuration and preset
- */
-static const char * const alc680_models[ALC680_MODEL_LAST] = {
- [ALC680_BASE] = "base",
- [ALC680_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc680_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1043, 0x12f3, "ASUS NX90", ALC680_BASE),
- {}
-};
-
-static const struct alc_config_preset alc680_presets[] = {
- [ALC680_BASE] = {
- .mixers = { alc680_base_mixer },
- .cap_mixer = alc680_master_capture_mixer,
- .init_verbs = { alc680_init_verbs },
- .num_dacs = ARRAY_SIZE(alc680_dac_nids),
- .dac_nids = alc680_dac_nids,
- .dig_out_nid = ALC680_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc680_modes),
- .channel_mode = alc680_modes,
- .unsol_event = alc680_unsol_event,
- .setup = alc680_base_setup,
- .init_hook = alc680_inithook,
-
- },
-};
diff --git a/sound/pci/hda/alc861_quirks.c b/sound/pci/hda/alc861_quirks.c
deleted file mode 100644
index d719ec6350eb..000000000000
--- a/sound/pci/hda/alc861_quirks.c
+++ /dev/null
@@ -1,725 +0,0 @@
-/*
- * ALC660/ALC861 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC861 models */
-enum {
- ALC861_AUTO,
- ALC861_3ST,
- ALC660_3ST,
- ALC861_3ST_DIG,
- ALC861_6ST_DIG,
- ALC861_UNIWILL_M31,
- ALC861_TOSHIBA,
- ALC861_ASUS,
- ALC861_ASUS_LAPTOP,
- ALC861_MODEL_LAST,
-};
-
-/*
- * ALC861 channel source setting (2/6 channel selection for 3-stack)
- */
-
-/*
- * set the path ways for 2 channel output
- * need to set the codec line out and mic 1 pin widgets to inputs
- */
-static const struct hda_verb alc861_threestack_ch2_init[] = {
- /* set pin widget 1Ah (line in) for input */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* set pin widget 18h (mic1/2) for input, for mic also enable
- * the vref
- */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
-#if 0
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
-#endif
- { } /* end */
-};
-/*
- * 6ch mode
- * need to set the codec line out and mic 1 pin widgets to outputs
- */
-static const struct hda_verb alc861_threestack_ch6_init[] = {
- /* set pin widget 1Ah (line in) for output (Back Surround)*/
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* set pin widget 18h (mic1) for output (CLFE)*/
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
-
- { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
-
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-#if 0
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
-#endif
- { } /* end */
-};
-
-static const struct hda_channel_mode alc861_threestack_modes[2] = {
- { 2, alc861_threestack_ch2_init },
- { 6, alc861_threestack_ch6_init },
-};
-/* Set mic1 as input and unmute the mixer */
-static const struct hda_verb alc861_uniwill_m31_ch2_init[] = {
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
- { } /* end */
-};
-/* Set mic1 as output and mute mixer */
-static const struct hda_verb alc861_uniwill_m31_ch4_init[] = {
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
- { } /* end */
-};
-
-static const struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
- { 2, alc861_uniwill_m31_ch2_init },
- { 4, alc861_uniwill_m31_ch4_init },
-};
-
-/* Set mic1 and line-in as input and unmute the mixer */
-static const struct hda_verb alc861_asus_ch2_init[] = {
- /* set pin widget 1Ah (line in) for input */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* set pin widget 18h (mic1/2) for input, for mic also enable
- * the vref
- */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
-
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
-#if 0
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
-#endif
- { } /* end */
-};
-/* Set mic1 nad line-in as output and mute mixer */
-static const struct hda_verb alc861_asus_ch6_init[] = {
- /* set pin widget 1Ah (line in) for output (Back Surround)*/
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
- /* set pin widget 18h (mic1) for output (CLFE)*/
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
- { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
- { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
-
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
-#if 0
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
-#endif
- { } /* end */
-};
-
-static const struct hda_channel_mode alc861_asus_modes[2] = {
- { 2, alc861_asus_ch2_init },
- { 6, alc861_asus_ch6_init },
-};
-
-/* patch-ALC861 */
-
-static const struct snd_kcontrol_new alc861_base_mixer[] = {
- /* output mixer control */
- HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
-
- /*Input mixer control */
- /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
- HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
-
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc861_3ST_mixer[] = {
- /* output mixer control */
- HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
- /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
-
- /* Input mixer control */
- /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
- HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
-
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- .private_value = ARRAY_SIZE(alc861_threestack_modes),
- },
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc861_toshiba_mixer[] = {
- /* output mixer control */
- HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
-
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
- /* output mixer control */
- HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
- /*HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT), */
-
- /* Input mixer control */
- /* HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT), */
- HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
-
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- .private_value = ARRAY_SIZE(alc861_uniwill_m31_modes),
- },
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc861_asus_mixer[] = {
- /* output mixer control */
- HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
-
- /* Input mixer control */
- HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
-
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- .private_value = ARRAY_SIZE(alc861_asus_modes),
- },
- { }
-};
-
-/* additional mixer */
-static const struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
- HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
- { }
-};
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc861_base_init_verbs[] = {
- /*
- * Unmute ADC0 and set the default input to mic-in
- */
- /* port-A for surround (rear panel) */
- { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-B for mic-in (rear panel) with vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* port-C for line-in (rear panel) */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* port-D for Front */
- { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-E for HP out (front panel) */
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
- /* route front PCM to HP */
- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-F for mic-in (front panel) with vref */
- { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* port-G for CLFE (rear panel) */
- { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- { 0x1f, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-H for side (rear panel) */
- { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- { 0x20, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* CD-in */
- { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* route front mic to ADC1*/
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Unmute DAC0~3 & spdif out*/
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Unmute Mixer 14 (mic) 1c (Line in)*/
- {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- /* Unmute Stereo Mixer 15 */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
-
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* hp used DAC 3 (Front) */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
-
- { }
-};
-
-static const struct hda_verb alc861_threestack_init_verbs[] = {
- /*
- * Unmute ADC0 and set the default input to mic-in
- */
- /* port-A for surround (rear panel) */
- { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- /* port-B for mic-in (rear panel) with vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* port-C for line-in (rear panel) */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* port-D for Front */
- { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-E for HP out (front panel) */
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
- /* route front PCM to HP */
- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-F for mic-in (front panel) with vref */
- { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* port-G for CLFE (rear panel) */
- { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- /* port-H for side (rear panel) */
- { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- /* CD-in */
- { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* route front mic to ADC1*/
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute DAC0~3 & spdif out*/
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Unmute Mixer 14 (mic) 1c (Line in)*/
- {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- /* Unmute Stereo Mixer 15 */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
-
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* hp used DAC 3 (Front) */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- { }
-};
-
-static const struct hda_verb alc861_uniwill_m31_init_verbs[] = {
- /*
- * Unmute ADC0 and set the default input to mic-in
- */
- /* port-A for surround (rear panel) */
- { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- /* port-B for mic-in (rear panel) with vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* port-C for line-in (rear panel) */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* port-D for Front */
- { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-E for HP out (front panel) */
- /* this has to be set to VREF80 */
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* route front PCM to HP */
- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-F for mic-in (front panel) with vref */
- { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* port-G for CLFE (rear panel) */
- { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- /* port-H for side (rear panel) */
- { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- /* CD-in */
- { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* route front mic to ADC1*/
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute DAC0~3 & spdif out*/
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Unmute Mixer 14 (mic) 1c (Line in)*/
- {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- /* Unmute Stereo Mixer 15 */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
-
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* hp used DAC 3 (Front) */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- { }
-};
-
-static const struct hda_verb alc861_asus_init_verbs[] = {
- /*
- * Unmute ADC0 and set the default input to mic-in
- */
- /* port-A for surround (rear panel)
- * according to codec#0 this is the HP jack
- */
- { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
- /* route front PCM to HP */
- { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
- /* port-B for mic-in (rear panel) with vref */
- { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* port-C for line-in (rear panel) */
- { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* port-D for Front */
- { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-E for HP out (front panel) */
- /* this has to be set to VREF80 */
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* route front PCM to HP */
- { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
- /* port-F for mic-in (front panel) with vref */
- { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
- /* port-G for CLFE (rear panel) */
- { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* port-H for side (rear panel) */
- { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
- /* CD-in */
- { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
- /* route front mic to ADC1*/
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Unmute DAC0~3 & spdif out*/
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Unmute Mixer 14 (mic) 1c (Line in)*/
- {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- /* Unmute Stereo Mixer 15 */
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c}, /* Output 0~12 step */
-
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* hp used DAC 3 (Front) */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- { }
-};
-
-/* additional init verbs for ASUS laptops */
-static const struct hda_verb alc861_asus_laptop_init_verbs[] = {
- { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
- { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
- { }
-};
-
-static const struct hda_verb alc861_toshiba_init_verbs[] = {
- {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-
- { }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc861_toshiba_automute(struct hda_codec *codec)
-{
- unsigned int present = snd_hda_jack_detect(codec, 0x0f);
-
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_INPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
- snd_hda_codec_amp_stereo(codec, 0x1a, HDA_INPUT, 3,
- HDA_AMP_MUTE, present ? 0 : HDA_AMP_MUTE);
-}
-
-static void alc861_toshiba_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC_HP_EVENT)
- alc861_toshiba_automute(codec);
-}
-
-#define ALC861_DIGOUT_NID 0x07
-
-static const struct hda_channel_mode alc861_8ch_modes[1] = {
- { 8, NULL }
-};
-
-static const hda_nid_t alc861_dac_nids[4] = {
- /* front, surround, clfe, side */
- 0x03, 0x06, 0x05, 0x04
-};
-
-static const hda_nid_t alc660_dac_nids[3] = {
- /* front, clfe, surround */
- 0x03, 0x05, 0x06
-};
-
-static const hda_nid_t alc861_adc_nids[1] = {
- /* ADC0-2 */
- 0x08,
-};
-
-static const struct hda_input_mux alc861_capture_source = {
- .num_items = 5,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x3 },
- { "Line", 0x1 },
- { "CD", 0x4 },
- { "Mixer", 0x5 },
- },
-};
-
-/*
- * configuration and preset
- */
-static const char * const alc861_models[ALC861_MODEL_LAST] = {
- [ALC861_3ST] = "3stack",
- [ALC660_3ST] = "3stack-660",
- [ALC861_3ST_DIG] = "3stack-dig",
- [ALC861_6ST_DIG] = "6stack-dig",
- [ALC861_UNIWILL_M31] = "uniwill-m31",
- [ALC861_TOSHIBA] = "toshiba",
- [ALC861_ASUS] = "asus",
- [ALC861_ASUS_LAPTOP] = "asus-laptop",
- [ALC861_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc861_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
- SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
- SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
- SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
- SND_PCI_QUIRK(0x1043, 0x13d7, "ASUS A9rp", ALC861_ASUS_LAPTOP),
- SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS P1-AH2", ALC861_3ST_DIG),
- SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
- /* FIXME: the entry below breaks Toshiba A100 (model=auto works!)
- * Any other models that need this preset?
- */
- /* SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA), */
- SND_PCI_QUIRK(0x1462, 0x7254, "HP dx2200 (MSI MS-7254)", ALC861_3ST),
- SND_PCI_QUIRK(0x1462, 0x7297, "HP dx2250 (MSI MS-7297)", ALC861_3ST),
- SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
- SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
- SND_PCI_QUIRK(0x1584, 0x9075, "Airis Praxis N1212", ALC861_ASUS_LAPTOP),
- /* FIXME: the below seems conflict */
- /* SND_PCI_QUIRK(0x1584, 0x9075, "Uniwill", ALC861_UNIWILL_M31), */
- SND_PCI_QUIRK(0x1849, 0x0660, "Asrock 939SLI32", ALC660_3ST),
- SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
- {}
-};
-
-static const struct alc_config_preset alc861_presets[] = {
- [ALC861_3ST] = {
- .mixers = { alc861_3ST_mixer },
- .init_verbs = { alc861_threestack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861_dac_nids),
- .dac_nids = alc861_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
- .channel_mode = alc861_threestack_modes,
- .need_dac_fix = 1,
- .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
- .adc_nids = alc861_adc_nids,
- .input_mux = &alc861_capture_source,
- },
- [ALC861_3ST_DIG] = {
- .mixers = { alc861_base_mixer },
- .init_verbs = { alc861_threestack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861_dac_nids),
- .dac_nids = alc861_dac_nids,
- .dig_out_nid = ALC861_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
- .channel_mode = alc861_threestack_modes,
- .need_dac_fix = 1,
- .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
- .adc_nids = alc861_adc_nids,
- .input_mux = &alc861_capture_source,
- },
- [ALC861_6ST_DIG] = {
- .mixers = { alc861_base_mixer },
- .init_verbs = { alc861_base_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861_dac_nids),
- .dac_nids = alc861_dac_nids,
- .dig_out_nid = ALC861_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861_8ch_modes),
- .channel_mode = alc861_8ch_modes,
- .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
- .adc_nids = alc861_adc_nids,
- .input_mux = &alc861_capture_source,
- },
- [ALC660_3ST] = {
- .mixers = { alc861_3ST_mixer },
- .init_verbs = { alc861_threestack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc660_dac_nids),
- .dac_nids = alc660_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc861_threestack_modes),
- .channel_mode = alc861_threestack_modes,
- .need_dac_fix = 1,
- .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
- .adc_nids = alc861_adc_nids,
- .input_mux = &alc861_capture_source,
- },
- [ALC861_UNIWILL_M31] = {
- .mixers = { alc861_uniwill_m31_mixer },
- .init_verbs = { alc861_uniwill_m31_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861_dac_nids),
- .dac_nids = alc861_dac_nids,
- .dig_out_nid = ALC861_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861_uniwill_m31_modes),
- .channel_mode = alc861_uniwill_m31_modes,
- .need_dac_fix = 1,
- .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
- .adc_nids = alc861_adc_nids,
- .input_mux = &alc861_capture_source,
- },
- [ALC861_TOSHIBA] = {
- .mixers = { alc861_toshiba_mixer },
- .init_verbs = { alc861_base_init_verbs,
- alc861_toshiba_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861_dac_nids),
- .dac_nids = alc861_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
- .adc_nids = alc861_adc_nids,
- .input_mux = &alc861_capture_source,
- .unsol_event = alc861_toshiba_unsol_event,
- .init_hook = alc861_toshiba_automute,
- },
- [ALC861_ASUS] = {
- .mixers = { alc861_asus_mixer },
- .init_verbs = { alc861_asus_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861_dac_nids),
- .dac_nids = alc861_dac_nids,
- .dig_out_nid = ALC861_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
- .channel_mode = alc861_asus_modes,
- .need_dac_fix = 1,
- .hp_nid = 0x06,
- .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
- .adc_nids = alc861_adc_nids,
- .input_mux = &alc861_capture_source,
- },
- [ALC861_ASUS_LAPTOP] = {
- .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
- .init_verbs = { alc861_asus_init_verbs,
- alc861_asus_laptop_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861_dac_nids),
- .dac_nids = alc861_dac_nids,
- .dig_out_nid = ALC861_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .need_dac_fix = 1,
- .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
- .adc_nids = alc861_adc_nids,
- .input_mux = &alc861_capture_source,
- },
-};
-
diff --git a/sound/pci/hda/alc861vd_quirks.c b/sound/pci/hda/alc861vd_quirks.c
deleted file mode 100644
index 8f28450f41f8..000000000000
--- a/sound/pci/hda/alc861vd_quirks.c
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * ALC660-VD/ALC861-VD quirk models
- * included by patch_realtek.c
- */
-
-/* ALC861-VD models */
-enum {
- ALC861VD_AUTO,
- ALC660VD_3ST,
- ALC660VD_3ST_DIG,
- ALC660VD_ASUS_V1S,
- ALC861VD_3ST,
- ALC861VD_3ST_DIG,
- ALC861VD_6ST_DIG,
- ALC861VD_LENOVO,
- ALC861VD_DALLAS,
- ALC861VD_HP,
- ALC861VD_MODEL_LAST,
-};
-
-#define ALC861VD_DIGOUT_NID 0x06
-
-static const hda_nid_t alc861vd_dac_nids[4] = {
- /* front, surr, clfe, side surr */
- 0x02, 0x03, 0x04, 0x05
-};
-
-/* dac_nids for ALC660vd are in a different order - according to
- * Realtek's driver.
- * This should probably result in a different mixer for 6stack models
- * of ALC660vd codecs, but for now there is only 3stack mixer
- * - and it is the same as in 861vd.
- * adc_nids in ALC660vd are (is) the same as in 861vd
- */
-static const hda_nid_t alc660vd_dac_nids[3] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x04, 0x03
-};
-
-static const hda_nid_t alc861vd_adc_nids[1] = {
- /* ADC0 */
- 0x09,
-};
-
-static const hda_nid_t alc861vd_capsrc_nids[1] = { 0x22 };
-
-/* input MUX */
-/* FIXME: should be a matrix-type input source selection */
-static const struct hda_input_mux alc861vd_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux alc861vd_dallas_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x0 },
- { "Internal Mic", 0x1 },
- },
-};
-
-static const struct hda_input_mux alc861vd_hp_capture_source = {
- .num_items = 2,
- .items = {
- { "Front Mic", 0x0 },
- { "ATAPI Mic", 0x1 },
- },
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
- { 2, NULL }
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc861vd_6stack_ch6_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc861vd_6stack_ch8_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc861vd_6stack_modes[2] = {
- { 6, alc861vd_6stack_ch6_init },
- { 8, alc861vd_6stack_ch8_init },
-};
-
-static const struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
- * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
- */
-static const struct snd_kcontrol_new alc861vd_6st_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
-
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
- HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
-
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc861vd_3st_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
-
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
-
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc861vd_lenovo_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- /*HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),*/
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
-
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
-
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
-
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
-
- { } /* end */
-};
-
-/* Pin assignment: Speaker=0x14, HP = 0x15,
- * Mic=0x18, Internal Mic = 0x19, CD = 0x1c, PC Beep = 0x1d
- */
-static const struct snd_kcontrol_new alc861vd_dallas_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-/* Pin assignment: Speaker=0x14, Line-out = 0x15,
- * Front Mic=0x18, ATAPI Mic = 0x19,
- */
-static const struct snd_kcontrol_new alc861vd_hp_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("ATAPI Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("ATAPI Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
-
- { } /* end */
-};
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc861vd_volume_init_verbs[] = {
- /*
- * Unmute ADC0 and set the default input to mic-in
- */
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
- * the analog-loopback mixer widget
- */
- /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
- /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
-
- /*
- * Set up output mixers (0x02 - 0x05)
- */
- /* set vol=0 to output mixers */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- /* set up input amps for analog loopback */
- /* Amp Indices: DAC = 0, mixer = 1 */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
- { }
-};
-
-/*
- * 3-stack pin configuration:
- * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc861vd_3stack_init_verbs[] = {
- /*
- * Set pin mode and muting
- */
- /* set front pin widgets 0x14 for output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Mic (rear) pin: input vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin: input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line-2 In: Headphone output (output 0 - 0x0c) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/*
- * 6-stack pin configuration:
- */
-static const struct hda_verb alc861vd_6stack_init_verbs[] = {
- /*
- * Set pin mode and muting
- */
- /* set front pin widgets 0x14 for output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Rear Pin: output 1 (0x0d) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* CLFE Pin: output 2 (0x0e) */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* Side Pin: output 3 (0x0f) */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-
- /* Mic (rear) pin: input vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin: input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line-2 In: Headphone output (output 0 - 0x0c) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-static const struct hda_verb alc861vd_eapd_verbs[] = {
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-static const struct hda_verb alc861vd_lenovo_unsol_verbs[] = {
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
- {}
-};
-
-static void alc861vd_lenovo_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc861vd_lenovo_init_hook(struct hda_codec *codec)
-{
- alc_hp_automute(codec);
- alc88x_simple_mic_automute(codec);
-}
-
-static void alc861vd_lenovo_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC_MIC_EVENT:
- alc88x_simple_mic_automute(codec);
- break;
- default:
- alc_sku_unsol_event(codec, res);
- break;
- }
-}
-
-static const struct hda_verb alc861vd_dallas_verbs[] = {
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
-
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
-
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
-
- { } /* end */
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc861vd_dallas_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/*
- * configuration and preset
- */
-static const char * const alc861vd_models[ALC861VD_MODEL_LAST] = {
- [ALC660VD_3ST] = "3stack-660",
- [ALC660VD_3ST_DIG] = "3stack-660-digout",
- [ALC660VD_ASUS_V1S] = "asus-v1s",
- [ALC861VD_3ST] = "3stack",
- [ALC861VD_3ST_DIG] = "3stack-digout",
- [ALC861VD_6ST_DIG] = "6stack-digout",
- [ALC861VD_LENOVO] = "lenovo",
- [ALC861VD_DALLAS] = "dallas",
- [ALC861VD_HP] = "hp",
- [ALC861VD_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc861vd_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
- SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
- SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
- /*SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),*/ /* auto */
- SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
- SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
- SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
- SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
- /*SND_PCI_QUIRK(0x1179, 0xff00, "DALLAS", ALC861VD_DALLAS),*/ /*lenovo*/
- SND_PCI_QUIRK(0x1179, 0xff01, "Toshiba A135", ALC861VD_LENOVO),
- SND_PCI_QUIRK(0x1179, 0xff03, "Toshiba P205", ALC861VD_LENOVO),
- SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_DALLAS),
- SND_PCI_QUIRK(0x1565, 0x820d, "Biostar NF61S SE", ALC861VD_6ST_DIG),
- SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", ALC861VD_LENOVO),
- SND_PCI_QUIRK(0x1849, 0x0862, "ASRock K8NF6G-VSTA", ALC861VD_6ST_DIG),
- {}
-};
-
-static const struct alc_config_preset alc861vd_presets[] = {
- [ALC660VD_3ST] = {
- .mixers = { alc861vd_3st_mixer },
- .init_verbs = { alc861vd_volume_init_verbs,
- alc861vd_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
- .dac_nids = alc660vd_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
- .channel_mode = alc861vd_3stack_2ch_modes,
- .input_mux = &alc861vd_capture_source,
- },
- [ALC660VD_3ST_DIG] = {
- .mixers = { alc861vd_3st_mixer },
- .init_verbs = { alc861vd_volume_init_verbs,
- alc861vd_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
- .dac_nids = alc660vd_dac_nids,
- .dig_out_nid = ALC861VD_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
- .channel_mode = alc861vd_3stack_2ch_modes,
- .input_mux = &alc861vd_capture_source,
- },
- [ALC861VD_3ST] = {
- .mixers = { alc861vd_3st_mixer },
- .init_verbs = { alc861vd_volume_init_verbs,
- alc861vd_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
- .dac_nids = alc861vd_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
- .channel_mode = alc861vd_3stack_2ch_modes,
- .input_mux = &alc861vd_capture_source,
- },
- [ALC861VD_3ST_DIG] = {
- .mixers = { alc861vd_3st_mixer },
- .init_verbs = { alc861vd_volume_init_verbs,
- alc861vd_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
- .dac_nids = alc861vd_dac_nids,
- .dig_out_nid = ALC861VD_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
- .channel_mode = alc861vd_3stack_2ch_modes,
- .input_mux = &alc861vd_capture_source,
- },
- [ALC861VD_6ST_DIG] = {
- .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
- .init_verbs = { alc861vd_volume_init_verbs,
- alc861vd_6stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
- .dac_nids = alc861vd_dac_nids,
- .dig_out_nid = ALC861VD_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
- .channel_mode = alc861vd_6stack_modes,
- .input_mux = &alc861vd_capture_source,
- },
- [ALC861VD_LENOVO] = {
- .mixers = { alc861vd_lenovo_mixer },
- .init_verbs = { alc861vd_volume_init_verbs,
- alc861vd_3stack_init_verbs,
- alc861vd_eapd_verbs,
- alc861vd_lenovo_unsol_verbs },
- .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
- .dac_nids = alc660vd_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
- .channel_mode = alc861vd_3stack_2ch_modes,
- .input_mux = &alc861vd_capture_source,
- .unsol_event = alc861vd_lenovo_unsol_event,
- .setup = alc861vd_lenovo_setup,
- .init_hook = alc861vd_lenovo_init_hook,
- },
- [ALC861VD_DALLAS] = {
- .mixers = { alc861vd_dallas_mixer },
- .init_verbs = { alc861vd_dallas_verbs },
- .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
- .dac_nids = alc861vd_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
- .channel_mode = alc861vd_3stack_2ch_modes,
- .input_mux = &alc861vd_dallas_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc861vd_dallas_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC861VD_HP] = {
- .mixers = { alc861vd_hp_mixer },
- .init_verbs = { alc861vd_dallas_verbs, alc861vd_eapd_verbs },
- .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
- .dac_nids = alc861vd_dac_nids,
- .dig_out_nid = ALC861VD_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
- .channel_mode = alc861vd_3stack_2ch_modes,
- .input_mux = &alc861vd_hp_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc861vd_dallas_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC660VD_ASUS_V1S] = {
- .mixers = { alc861vd_lenovo_mixer },
- .init_verbs = { alc861vd_volume_init_verbs,
- alc861vd_3stack_init_verbs,
- alc861vd_eapd_verbs,
- alc861vd_lenovo_unsol_verbs },
- .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
- .dac_nids = alc660vd_dac_nids,
- .dig_out_nid = ALC861VD_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
- .channel_mode = alc861vd_3stack_2ch_modes,
- .input_mux = &alc861vd_capture_source,
- .unsol_event = alc861vd_lenovo_unsol_event,
- .setup = alc861vd_lenovo_setup,
- .init_hook = alc861vd_lenovo_init_hook,
- },
-};
-
diff --git a/sound/pci/hda/alc880_quirks.c b/sound/pci/hda/alc880_quirks.c
deleted file mode 100644
index c844d2b59988..000000000000
--- a/sound/pci/hda/alc880_quirks.c
+++ /dev/null
@@ -1,1898 +0,0 @@
-/*
- * ALC880 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC880 board config type */
-enum {
- ALC880_AUTO,
- ALC880_3ST,
- ALC880_3ST_DIG,
- ALC880_5ST,
- ALC880_5ST_DIG,
- ALC880_W810,
- ALC880_Z71V,
- ALC880_6ST,
- ALC880_6ST_DIG,
- ALC880_F1734,
- ALC880_ASUS,
- ALC880_ASUS_DIG,
- ALC880_ASUS_W1V,
- ALC880_ASUS_DIG2,
- ALC880_FUJITSU,
- ALC880_UNIWILL_DIG,
- ALC880_UNIWILL,
- ALC880_UNIWILL_P53,
- ALC880_CLEVO,
- ALC880_TCL_S700,
- ALC880_LG,
- ALC880_LG_LW,
- ALC880_MEDION_RIM,
-#ifdef CONFIG_SND_DEBUG
- ALC880_TEST,
-#endif
- ALC880_MODEL_LAST /* last tag */
-};
-
-/*
- * ALC880 3-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
- * Pin assignment: Front = 0x14, Line-In/Surr = 0x1a, Mic/CLFE = 0x18,
- * F-Mic = 0x1b, HP = 0x19
- */
-
-static const hda_nid_t alc880_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x05, 0x04, 0x03
-};
-
-static const hda_nid_t alc880_adc_nids[3] = {
- /* ADC0-2 */
- 0x07, 0x08, 0x09,
-};
-
-/* The datasheet says the node 0x07 is connected from inputs,
- * but it shows zero connection in the real implementation on some devices.
- * Note: this is a 915GAV bug, fixed on 915GLV
- */
-static const hda_nid_t alc880_adc_nids_alt[2] = {
- /* ADC1-2 */
- 0x08, 0x09,
-};
-
-#define ALC880_DIGOUT_NID 0x06
-#define ALC880_DIGIN_NID 0x0a
-#define ALC880_PIN_CD_NID 0x1c
-
-static const struct hda_input_mux alc880_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x3 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-/* channel source setting (2/6 channel selection for 3-stack) */
-/* 2ch mode */
-static const struct hda_verb alc880_threestack_ch2_init[] = {
- /* set line-in to input, mute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- /* set mic-in to input vref 80%, mute it */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/* 6ch mode */
-static const struct hda_verb alc880_threestack_ch6_init[] = {
- /* set line-in to output, unmute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- /* set mic-in to output, unmute it */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc880_threestack_modes[2] = {
- { 2, alc880_threestack_ch2_init },
- { 6, alc880_threestack_ch6_init },
-};
-
-static const struct snd_kcontrol_new alc880_three_stack_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x19, 0x0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-/*
- * ALC880 5-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0d),
- * Side = 0x02 (0xd)
- * Pin assignment: Front = 0x14, Surr = 0x17, CLFE = 0x16
- * Line-In/Side = 0x1a, Mic = 0x18, F-Mic = 0x1b, HP = 0x19
- */
-
-/* additional mixers to alc880_three_stack_mixer */
-static const struct snd_kcontrol_new alc880_five_stack_mixer[] = {
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0d, 2, HDA_INPUT),
- { } /* end */
-};
-
-/* channel source setting (6/8 channel selection for 5-stack) */
-/* 6ch mode */
-static const struct hda_verb alc880_fivestack_ch6_init[] = {
- /* set line-in to input, mute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/* 8ch mode */
-static const struct hda_verb alc880_fivestack_ch8_init[] = {
- /* set line-in to output, unmute it */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc880_fivestack_modes[2] = {
- { 6, alc880_fivestack_ch6_init },
- { 8, alc880_fivestack_ch8_init },
-};
-
-
-/*
- * ALC880 6-stack model
- *
- * DAC: Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e),
- * Side = 0x05 (0x0f)
- * Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, Side = 0x17,
- * Mic = 0x18, F-Mic = 0x19, Line = 0x1a, HP = 0x1b
- */
-
-static const hda_nid_t alc880_6st_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x03, 0x04, 0x05
-};
-
-static const struct hda_input_mux alc880_6stack_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-/* fixed 8-channels */
-static const struct hda_channel_mode alc880_sixstack_modes[1] = {
- { 8, NULL },
-};
-
-static const struct snd_kcontrol_new alc880_six_stack_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-
-/*
- * ALC880 W810 model
- *
- * W810 has rear IO for:
- * Front (DAC 02)
- * Surround (DAC 03)
- * Center/LFE (DAC 04)
- * Digital out (06)
- *
- * The system also has a pair of internal speakers, and a headphone jack.
- * These are both connected to Line2 on the codec, hence to DAC 02.
- *
- * There is a variable resistor to control the speaker or headphone
- * volume. This is a hardware-only device without a software API.
- *
- * Plugging headphones in will disable the internal speakers. This is
- * implemented in hardware, not via the driver using jack sense. In
- * a similar fashion, plugging into the rear socket marked "front" will
- * disable both the speakers and headphones.
- *
- * For input, there's a microphone jack, and an "audio in" jack.
- * These may not do anything useful with this driver yet, because I
- * haven't setup any initialization verbs for these yet...
- */
-
-static const hda_nid_t alc880_w810_dac_nids[3] = {
- /* front, rear/surround, clfe */
- 0x02, 0x03, 0x04
-};
-
-/* fixed 6 channels */
-static const struct hda_channel_mode alc880_w810_modes[1] = {
- { 6, NULL }
-};
-
-/* Pin assignment: Front = 0x14, Surr = 0x15, CLFE = 0x16, HP = 0x1b */
-static const struct snd_kcontrol_new alc880_w810_base_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- { } /* end */
-};
-
-
-/*
- * Z710V model
- *
- * DAC: Front = 0x02 (0x0c), HP = 0x03 (0x0d)
- * Pin assignment: Front = 0x14, HP = 0x15, Mic = 0x18, Mic2 = 0x19(?),
- * Line = 0x1a
- */
-
-static const hda_nid_t alc880_z71v_dac_nids[1] = {
- 0x02
-};
-#define ALC880_Z71V_HP_DAC 0x03
-
-/* fixed 2 channels */
-static const struct hda_channel_mode alc880_2_jack_modes[1] = {
- { 2, NULL }
-};
-
-static const struct snd_kcontrol_new alc880_z71v_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-
-/*
- * ALC880 F1734 model
- *
- * DAC: HP = 0x02 (0x0c), Front = 0x03 (0x0d)
- * Pin assignment: HP = 0x14, Front = 0x15, Mic = 0x18
- */
-
-static const hda_nid_t alc880_f1734_dac_nids[1] = {
- 0x03
-};
-#define ALC880_F1734_HP_DAC 0x02
-
-static const struct snd_kcontrol_new alc880_f1734_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_input_mux alc880_f1734_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x1 },
- { "CD", 0x4 },
- },
-};
-
-
-/*
- * ALC880 ASUS model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- * Mic = 0x18, Line = 0x1a
- */
-
-#define alc880_asus_dac_nids alc880_w810_dac_nids /* identical with w810 */
-#define alc880_asus_modes alc880_threestack_modes /* 2/6 channel mode */
-
-static const struct snd_kcontrol_new alc880_asus_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-/*
- * ALC880 ASUS W1V model
- *
- * DAC: HP/Front = 0x02 (0x0c), Surr = 0x03 (0x0d), CLFE = 0x04 (0x0e)
- * Pin assignment: HP/Front = 0x14, Surr = 0x15, CLFE = 0x16,
- * Mic = 0x18, Line = 0x1a, Line2 = 0x1b
- */
-
-/* additional mixers to alc880_asus_mixer */
-static const struct snd_kcontrol_new alc880_asus_w1v_mixer[] = {
- HDA_CODEC_VOLUME("Line2 Playback Volume", 0x0b, 0x03, HDA_INPUT),
- HDA_CODEC_MUTE("Line2 Playback Switch", 0x0b, 0x03, HDA_INPUT),
- { } /* end */
-};
-
-/* TCL S700 */
-static const struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0B, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0B, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0B, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-/* Uniwill */
-static const struct snd_kcontrol_new alc880_uniwill_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-/*
- * initialize the codec volumes, etc
- */
-
-/*
- * generic initialization of ADC, input mixers and output mixers
- */
-static const struct hda_verb alc880_volume_init_verbs[] = {
- /*
- * Unmute ADC0-2 and set the default input to mic-in
- */
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
-
- /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
- * mixer widget
- * Note: PASD motherboards uses the Line In 2 as the input for front
- * panel mic (mic 2)
- */
- /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
-
- /*
- * Set up output mixers (0x0c - 0x0f)
- */
- /* set vol=0 to output mixers */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* set up input amps for analog loopback */
- /* Amp Indices: DAC = 0, mixer = 1 */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
- { }
-};
-
-/*
- * 3-stack pin configuration:
- * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc880_pin_3stack_init_verbs[] = {
- /*
- * preset connection lists of input pins
- * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
- */
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
-
- /*
- * Set pin mode and muting
- */
- /* set front pin widgets 0x14 for output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Mic2 (as headphone out) for HP output */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line2 (as front mic) pin widget for input and vref at 80% */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/*
- * 5-stack pin configuration:
- * front = 0x14, surround = 0x17, clfe = 0x16, mic = 0x18, HP = 0x19,
- * line-in/side = 0x1a, f-mic = 0x1b
- */
-static const struct hda_verb alc880_pin_5stack_init_verbs[] = {
- /*
- * preset connection lists of input pins
- * 0 = front, 1 = rear_surr, 2 = CLFE, 3 = surround
- */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/side */
-
- /*
- * Set pin mode and muting
- */
- /* set pin widgets 0x14-0x17 for output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* unmute pins for output (no gain on this amp) */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Mic2 (as headphone out) for HP output */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line2 (as front mic) pin widget for input and vref at 80% */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/*
- * W810 pin configuration:
- * front = 0x14, surround = 0x15, clfe = 0x16, HP = 0x1b
- */
-static const struct hda_verb alc880_pin_w810_init_verbs[] = {
- /* hphone/speaker input selector: front DAC */
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x0},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- { }
-};
-
-/*
- * Z71V pin configuration:
- * Speaker-out = 0x14, HP = 0x15, Mic = 0x18, Line-in = 0x1a, Mic2 = 0x1b (?)
- */
-static const struct hda_verb alc880_pin_z71v_init_verbs[] = {
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/*
- * 6-stack pin configuration:
- * front = 0x14, surr = 0x15, clfe = 0x16, side = 0x17, mic = 0x18,
- * f-mic = 0x19, line = 0x1a, HP = 0x1b
- */
-static const struct hda_verb alc880_pin_6stack_init_verbs[] = {
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/*
- * Uniwill pin configuration:
- * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
- * line = 0x1a
- */
-static const struct hda_verb alc880_uniwill_init_verbs[] = {
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
- /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_MIC_EVENT},
-
- { }
-};
-
-/*
-* Uniwill P53
-* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
- */
-static const struct hda_verb alc880_uniwill_p53_init_verbs[] = {
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_DCVOL_EVENT},
-
- { }
-};
-
-static const struct hda_verb alc880_beep_init_verbs[] = {
- { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
- { }
-};
-
-static void alc880_uniwill_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x16;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc880_uniwill_init_hook(struct hda_codec *codec)
-{
- alc_hp_automute(codec);
- alc88x_simple_mic_automute(codec);
-}
-
-static void alc880_uniwill_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- /* Looks like the unsol event is incompatible with the standard
- * definition. 4bit tag is placed at 28 bit!
- */
- switch (res >> 28) {
- case ALC_MIC_EVENT:
- alc88x_simple_mic_automute(codec);
- break;
- default:
- alc_sku_unsol_event(codec, res);
- break;
- }
-}
-
-static void alc880_uniwill_p53_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
-{
- unsigned int present;
-
- present = snd_hda_codec_read(codec, 0x21, 0,
- AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
- present &= HDA_AMP_VOLMASK;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_OUTPUT, 0,
- HDA_AMP_VOLMASK, present);
- snd_hda_codec_amp_stereo(codec, 0x0d, HDA_OUTPUT, 0,
- HDA_AMP_VOLMASK, present);
-}
-
-static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- /* Looks like the unsol event is incompatible with the standard
- * definition. 4bit tag is placed at 28 bit!
- */
- if ((res >> 28) == ALC_DCVOL_EVENT)
- alc880_uniwill_p53_dcvol_automute(codec);
- else
- alc_sku_unsol_event(codec, res);
-}
-
-/*
- * F1734 pin configuration:
- * HP = 0x14, speaker-out = 0x15, mic = 0x18
- */
-static const struct hda_verb alc880_pin_f1734_init_verbs[] = {
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_HP_EVENT},
- {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|ALC_DCVOL_EVENT},
-
- { }
-};
-
-/*
- * ASUS pin configuration:
- * HP/front = 0x14, surr = 0x15, clfe = 0x16, mic = 0x18, line = 0x1a
- */
-static const struct hda_verb alc880_pin_asus_init_verbs[] = {
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- { }
-};
-
-/* Enable GPIO mask and set output */
-#define alc880_gpio1_init_verbs alc_gpio1_init_verbs
-#define alc880_gpio2_init_verbs alc_gpio2_init_verbs
-#define alc880_gpio3_init_verbs alc_gpio3_init_verbs
-
-/* Clevo m520g init */
-static const struct hda_verb alc880_pin_clevo_init_verbs[] = {
- /* headphone output */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* line-out */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Line-in */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* CD */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Mic1 (rear panel) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Mic2 (front panel) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* headphone */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* change to EAPD mode */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
-
- { }
-};
-
-static const struct hda_verb alc880_pin_tcl_S700_init_verbs[] = {
- /* change to EAPD mode */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
-
- /* Headphone output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Front output*/
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Line In pin widget for input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
-
- /* change to EAPD mode */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
-
- { }
-};
-
-/*
- * LG m1 express dual
- *
- * Pin assignment:
- * Rear Line-In/Out (blue): 0x14
- * Build-in Mic-In: 0x15
- * Speaker-out: 0x17
- * HP-Out (green): 0x1b
- * Mic-In/Out (red): 0x19
- * SPDIF-Out: 0x1e
- */
-
-/* To make 5.1 output working (green=Front, blue=Surr, red=CLFE) */
-static const hda_nid_t alc880_lg_dac_nids[3] = {
- 0x05, 0x02, 0x03
-};
-
-/* seems analog CD is not working */
-static const struct hda_input_mux alc880_lg_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x1 },
- { "Line", 0x5 },
- { "Internal Mic", 0x6 },
- },
-};
-
-/* 2,4,6 channel modes */
-static const struct hda_verb alc880_lg_ch2_init[] = {
- /* set line-in and mic-in to input */
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { }
-};
-
-static const struct hda_verb alc880_lg_ch4_init[] = {
- /* set line-in to out and mic-in to input */
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { }
-};
-
-static const struct hda_verb alc880_lg_ch6_init[] = {
- /* set line-in and mic-in to output */
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { }
-};
-
-static const struct hda_channel_mode alc880_lg_ch_modes[3] = {
- { 2, alc880_lg_ch2_init },
- { 4, alc880_lg_ch4_init },
- { 6, alc880_lg_ch6_init },
-};
-
-static const struct snd_kcontrol_new alc880_lg_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0d, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x06, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x06, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x07, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc880_lg_init_verbs[] = {
- /* set capture source to mic-in */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* mute all amp mixer inputs */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
- /* line-in to input */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* built-in mic */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* speaker-out */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* mic-in to input */
- {0x11, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* HP-out */
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x03},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* jack sense */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- { }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x17;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/*
- * LG LW20
- *
- * Pin assignment:
- * Speaker-out: 0x14
- * Mic-In: 0x18
- * Built-in Mic-In: 0x19
- * Line-In: 0x1b
- * HP-Out: 0x1a
- * SPDIF-Out: 0x1e
- */
-
-static const struct hda_input_mux alc880_lg_lw_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Internal Mic", 0x1 },
- { "Line In", 0x2 },
- },
-};
-
-#define alc880_lg_lw_modes alc880_threestack_modes
-
-static const struct snd_kcontrol_new alc880_lg_lw_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc880_lg_lw_init_verbs[] = {
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- {0x10, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
- {0x12, AC_VERB_SET_CONNECT_SEL, 0x03}, /* line/surround */
-
- /* set capture source to mic-in */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)},
- /* speaker-out */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* HP-out */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* mic-in to input */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* built-in mic */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* jack sense */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- { }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc880_lg_lw_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct snd_kcontrol_new alc880_medion_rim_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Master Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_input_mux alc880_medion_rim_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x0 },
- { "Internal Mic", 0x1 },
- },
-};
-
-static const struct hda_verb alc880_medion_rim_init_verbs[] = {
- {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- /* Mic1 (rear panel) pin widget for input and vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Mic2 (as headphone out) for HP output */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Internal Speaker */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
-
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
-
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- { }
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc880_medion_rim_automute(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- alc_hp_automute(codec);
- /* toggle EAPD */
- if (spec->jack_present)
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 0);
- else
- snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA, 2);
-}
-
-static void alc880_medion_rim_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- /* Looks like the unsol event is incompatible with the standard
- * definition. 4bit tag is placed at 28 bit!
- */
- if ((res >> 28) == ALC_HP_EVENT)
- alc880_medion_rim_automute(codec);
-}
-
-static void alc880_medion_rim_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x1b;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc880_lg_loopbacks[] = {
- { 0x0b, HDA_INPUT, 1 },
- { 0x0b, HDA_INPUT, 6 },
- { 0x0b, HDA_INPUT, 7 },
- { } /* end */
-};
-#endif
-
-/*
- * Test configuration for debugging
- *
- * Almost all inputs/outputs are enabled. I/O pins can be configured via
- * enum controls.
- */
-#ifdef CONFIG_SND_DEBUG
-static const hda_nid_t alc880_test_dac_nids[4] = {
- 0x02, 0x03, 0x04, 0x05
-};
-
-static const struct hda_input_mux alc880_test_capture_source = {
- .num_items = 7,
- .items = {
- { "In-1", 0x0 },
- { "In-2", 0x1 },
- { "In-3", 0x2 },
- { "In-4", 0x3 },
- { "CD", 0x4 },
- { "Front", 0x5 },
- { "Surround", 0x6 },
- },
-};
-
-static const struct hda_channel_mode alc880_test_modes[4] = {
- { 2, NULL },
- { 4, NULL },
- { 6, NULL },
- { 8, NULL },
-};
-
-static int alc_test_pin_ctl_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- static const char * const texts[] = {
- "N/A", "Line Out", "HP Out",
- "In Hi-Z", "In 50%", "In Grd", "In 80%", "In 100%"
- };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 8;
- if (uinfo->value.enumerated.item >= 8)
- uinfo->value.enumerated.item = 7;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int alc_test_pin_ctl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- unsigned int pin_ctl, item = 0;
-
- pin_ctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- if (pin_ctl & AC_PINCTL_OUT_EN) {
- if (pin_ctl & AC_PINCTL_HP_EN)
- item = 2;
- else
- item = 1;
- } else if (pin_ctl & AC_PINCTL_IN_EN) {
- switch (pin_ctl & AC_PINCTL_VREFEN) {
- case AC_PINCTL_VREF_HIZ: item = 3; break;
- case AC_PINCTL_VREF_50: item = 4; break;
- case AC_PINCTL_VREF_GRD: item = 5; break;
- case AC_PINCTL_VREF_80: item = 6; break;
- case AC_PINCTL_VREF_100: item = 7; break;
- }
- }
- ucontrol->value.enumerated.item[0] = item;
- return 0;
-}
-
-static int alc_test_pin_ctl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- static const unsigned int ctls[] = {
- 0, AC_PINCTL_OUT_EN, AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_50,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_80,
- AC_PINCTL_IN_EN | AC_PINCTL_VREF_100,
- };
- unsigned int old_ctl, new_ctl;
-
- old_ctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- new_ctl = ctls[ucontrol->value.enumerated.item[0]];
- if (old_ctl != new_ctl) {
- int val;
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- new_ctl);
- val = ucontrol->value.enumerated.item[0] >= 3 ?
- HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, val);
- return 1;
- }
- return 0;
-}
-
-static int alc_test_pin_src_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- static const char * const texts[] = {
- "Front", "Surround", "CLFE", "Side"
- };
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = 4;
- if (uinfo->value.enumerated.item >= 4)
- uinfo->value.enumerated.item = 3;
- strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
- return 0;
-}
-
-static int alc_test_pin_src_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- unsigned int sel;
-
- sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0);
- ucontrol->value.enumerated.item[0] = sel & 3;
- return 0;
-}
-
-static int alc_test_pin_src_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = (hda_nid_t)kcontrol->private_value;
- unsigned int sel;
-
- sel = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONNECT_SEL, 0) & 3;
- if (ucontrol->value.enumerated.item[0] != sel) {
- sel = ucontrol->value.enumerated.item[0] & 3;
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_CONNECT_SEL, sel);
- return 1;
- }
- return 0;
-}
-
-#define PIN_CTL_TEST(xname,nid) { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_test_pin_ctl_info, \
- .get = alc_test_pin_ctl_get, \
- .put = alc_test_pin_ctl_put, \
- .private_value = nid \
- }
-
-#define PIN_SRC_TEST(xname,nid) { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = xname, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_test_pin_src_info, \
- .get = alc_test_pin_src_get, \
- .put = alc_test_pin_src_put, \
- .private_value = nid \
- }
-
-static const struct snd_kcontrol_new alc880_test_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CLFE Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_BIND_MUTE("CLFE Playback Switch", 0x0e, 2, HDA_INPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- PIN_CTL_TEST("Front Pin Mode", 0x14),
- PIN_CTL_TEST("Surround Pin Mode", 0x15),
- PIN_CTL_TEST("CLFE Pin Mode", 0x16),
- PIN_CTL_TEST("Side Pin Mode", 0x17),
- PIN_CTL_TEST("In-1 Pin Mode", 0x18),
- PIN_CTL_TEST("In-2 Pin Mode", 0x19),
- PIN_CTL_TEST("In-3 Pin Mode", 0x1a),
- PIN_CTL_TEST("In-4 Pin Mode", 0x1b),
- PIN_SRC_TEST("In-1 Pin Source", 0x18),
- PIN_SRC_TEST("In-2 Pin Source", 0x19),
- PIN_SRC_TEST("In-3 Pin Source", 0x1a),
- PIN_SRC_TEST("In-4 Pin Source", 0x1b),
- HDA_CODEC_VOLUME("In-1 Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("In-1 Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("In-2 Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("In-2 Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("In-3 Playback Volume", 0x0b, 0x2, HDA_INPUT),
- HDA_CODEC_MUTE("In-3 Playback Switch", 0x0b, 0x2, HDA_INPUT),
- HDA_CODEC_VOLUME("In-4 Playback Volume", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_MUTE("In-4 Playback Switch", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x4, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x4, HDA_INPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc880_test_init_verbs[] = {
- /* Unmute inputs of 0x0c - 0x0f */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* Vol output for 0x0c-0x0f */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- /* Set output pins 0x14-0x17 */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- /* Unmute output pins 0x14-0x17 */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Set input pins 0x18-0x1c */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- /* Mute input pins 0x18-0x1b */
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* ADC set up */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Analog input/passthru */
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- { }
-};
-#endif
-
-/*
- */
-
-static const char * const alc880_models[ALC880_MODEL_LAST] = {
- [ALC880_3ST] = "3stack",
- [ALC880_TCL_S700] = "tcl",
- [ALC880_3ST_DIG] = "3stack-digout",
- [ALC880_CLEVO] = "clevo",
- [ALC880_5ST] = "5stack",
- [ALC880_5ST_DIG] = "5stack-digout",
- [ALC880_W810] = "w810",
- [ALC880_Z71V] = "z71v",
- [ALC880_6ST] = "6stack",
- [ALC880_6ST_DIG] = "6stack-digout",
- [ALC880_ASUS] = "asus",
- [ALC880_ASUS_W1V] = "asus-w1v",
- [ALC880_ASUS_DIG] = "asus-dig",
- [ALC880_ASUS_DIG2] = "asus-dig2",
- [ALC880_UNIWILL_DIG] = "uniwill",
- [ALC880_UNIWILL_P53] = "uniwill-p53",
- [ALC880_FUJITSU] = "fujitsu",
- [ALC880_F1734] = "F1734",
- [ALC880_LG] = "lg",
- [ALC880_LG_LW] = "lg-lw",
- [ALC880_MEDION_RIM] = "medion",
-#ifdef CONFIG_SND_DEBUG
- [ALC880_TEST] = "test",
-#endif
- [ALC880_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc880_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
- SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
- SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
- SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
- SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
- /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
- SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x814e, "ASUS P5GD1 w/SPDIF", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
- SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
- SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
- SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_ASUS), /* default ASUS */
- SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
- SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
- SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
- SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
- SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
- SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
- SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
- SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
- SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
- SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_F1734),
- SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
- SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
- SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
- SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_MEDION_RIM),
- SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
- SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FUJITSU),
- SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_F1734),
- SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
- SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
- SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
- SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_LG),
- SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
- SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
- SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
- SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG), /* broken BIOS */
- SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
- /* default Intel */
- SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_3ST),
- SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
- SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
- {}
-};
-
-/*
- * ALC880 codec presets
- */
-static const struct alc_config_preset alc880_presets[] = {
- [ALC880_3ST] = {
- .mixers = { alc880_three_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_3ST_DIG] = {
- .mixers = { alc880_three_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_3stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_TCL_S700] = {
- .mixers = { alc880_tcl_s700_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_tcl_S700_init_verbs,
- alc880_gpio2_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
- .num_adc_nids = 1, /* single ADC */
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_5ST] = {
- .mixers = { alc880_three_stack_mixer,
- alc880_five_stack_mixer},
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_5stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
- .channel_mode = alc880_fivestack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_5ST_DIG] = {
- .mixers = { alc880_three_stack_mixer,
- alc880_five_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_5stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_fivestack_modes),
- .channel_mode = alc880_fivestack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_6ST] = {
- .mixers = { alc880_six_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_6stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
- .dac_nids = alc880_6st_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
- .channel_mode = alc880_sixstack_modes,
- .input_mux = &alc880_6stack_capture_source,
- },
- [ALC880_6ST_DIG] = {
- .mixers = { alc880_six_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_6stack_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_6st_dac_nids),
- .dac_nids = alc880_6st_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_sixstack_modes),
- .channel_mode = alc880_sixstack_modes,
- .input_mux = &alc880_6stack_capture_source,
- },
- [ALC880_W810] = {
- .mixers = { alc880_w810_base_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_w810_init_verbs,
- alc880_gpio2_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_w810_dac_nids),
- .dac_nids = alc880_w810_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
- .channel_mode = alc880_w810_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_Z71V] = {
- .mixers = { alc880_z71v_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_z71v_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_z71v_dac_nids),
- .dac_nids = alc880_z71v_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_F1734] = {
- .mixers = { alc880_f1734_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_f1734_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_f1734_dac_nids),
- .dac_nids = alc880_f1734_dac_nids,
- .hp_nid = 0x02,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_f1734_capture_source,
- .unsol_event = alc880_uniwill_p53_unsol_event,
- .setup = alc880_uniwill_p53_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC880_ASUS] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_ASUS_DIG] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_ASUS_DIG2] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs,
- alc880_gpio2_init_verbs }, /* use GPIO2 */
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_ASUS_W1V] = {
- .mixers = { alc880_asus_mixer, alc880_asus_w1v_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_UNIWILL_DIG] = {
- .mixers = { alc880_asus_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_asus_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_asus_modes),
- .channel_mode = alc880_asus_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_UNIWILL] = {
- .mixers = { alc880_uniwill_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_uniwill_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- .unsol_event = alc880_uniwill_unsol_event,
- .setup = alc880_uniwill_setup,
- .init_hook = alc880_uniwill_init_hook,
- },
- [ALC880_UNIWILL_P53] = {
- .mixers = { alc880_uniwill_p53_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_uniwill_p53_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
- .dac_nids = alc880_asus_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
- .channel_mode = alc880_threestack_modes,
- .input_mux = &alc880_capture_source,
- .unsol_event = alc880_uniwill_p53_unsol_event,
- .setup = alc880_uniwill_p53_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC880_FUJITSU] = {
- .mixers = { alc880_fujitsu_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_uniwill_p53_init_verbs,
- alc880_beep_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_capture_source,
- .unsol_event = alc880_uniwill_p53_unsol_event,
- .setup = alc880_uniwill_p53_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC880_CLEVO] = {
- .mixers = { alc880_three_stack_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_pin_clevo_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_capture_source,
- },
- [ALC880_LG] = {
- .mixers = { alc880_lg_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_lg_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_lg_dac_nids),
- .dac_nids = alc880_lg_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_lg_ch_modes),
- .channel_mode = alc880_lg_ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc880_lg_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc880_lg_setup,
- .init_hook = alc_hp_automute,
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- .loopbacks = alc880_lg_loopbacks,
-#endif
- },
- [ALC880_LG_LW] = {
- .mixers = { alc880_lg_lw_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_lg_lw_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_lg_lw_modes),
- .channel_mode = alc880_lg_lw_modes,
- .input_mux = &alc880_lg_lw_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc880_lg_lw_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC880_MEDION_RIM] = {
- .mixers = { alc880_medion_rim_mixer },
- .init_verbs = { alc880_volume_init_verbs,
- alc880_medion_rim_init_verbs,
- alc_gpio2_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_dac_nids),
- .dac_nids = alc880_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
- .channel_mode = alc880_2_jack_modes,
- .input_mux = &alc880_medion_rim_capture_source,
- .unsol_event = alc880_medion_rim_unsol_event,
- .setup = alc880_medion_rim_setup,
- .init_hook = alc880_medion_rim_automute,
- },
-#ifdef CONFIG_SND_DEBUG
- [ALC880_TEST] = {
- .mixers = { alc880_test_mixer },
- .init_verbs = { alc880_test_init_verbs },
- .num_dacs = ARRAY_SIZE(alc880_test_dac_nids),
- .dac_nids = alc880_test_dac_nids,
- .dig_out_nid = ALC880_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_test_modes),
- .channel_mode = alc880_test_modes,
- .input_mux = &alc880_test_capture_source,
- },
-#endif
-};
-
diff --git a/sound/pci/hda/alc882_quirks.c b/sound/pci/hda/alc882_quirks.c
deleted file mode 100644
index 617d04723b82..000000000000
--- a/sound/pci/hda/alc882_quirks.c
+++ /dev/null
@@ -1,3755 +0,0 @@
-/*
- * ALC882/ALC883/ALC888/ALC889 quirk models
- * included by patch_realtek.c
- */
-
-/* ALC882 models */
-enum {
- ALC882_AUTO,
- ALC882_3ST_DIG,
- ALC882_6ST_DIG,
- ALC882_ARIMA,
- ALC882_W2JC,
- ALC882_TARGA,
- ALC882_ASUS_A7J,
- ALC882_ASUS_A7M,
- ALC885_MACPRO,
- ALC885_MBA21,
- ALC885_MBP3,
- ALC885_MB5,
- ALC885_MACMINI3,
- ALC885_IMAC24,
- ALC885_IMAC91,
- ALC883_3ST_2ch_DIG,
- ALC883_3ST_6ch_DIG,
- ALC883_3ST_6ch,
- ALC883_6ST_DIG,
- ALC883_TARGA_DIG,
- ALC883_TARGA_2ch_DIG,
- ALC883_TARGA_8ch_DIG,
- ALC883_ACER,
- ALC883_ACER_ASPIRE,
- ALC888_ACER_ASPIRE_4930G,
- ALC888_ACER_ASPIRE_6530G,
- ALC888_ACER_ASPIRE_8930G,
- ALC888_ACER_ASPIRE_7730G,
- ALC883_MEDION,
- ALC883_MEDION_WIM2160,
- ALC883_LAPTOP_EAPD,
- ALC883_LENOVO_101E_2ch,
- ALC883_LENOVO_NB0763,
- ALC888_LENOVO_MS7195_DIG,
- ALC888_LENOVO_SKY,
- ALC883_HAIER_W66,
- ALC888_3ST_HP,
- ALC888_6ST_DELL,
- ALC883_MITAC,
- ALC883_CLEVO_M540R,
- ALC883_CLEVO_M720,
- ALC883_FUJITSU_PI2515,
- ALC888_FUJITSU_XA3530,
- ALC883_3ST_6ch_INTEL,
- ALC889A_INTEL,
- ALC889_INTEL,
- ALC888_ASUS_M90V,
- ALC888_ASUS_EEE1601,
- ALC889A_MB31,
- ALC1200_ASUS_P5Q,
- ALC883_SONY_VAIO_TT,
- ALC882_MODEL_LAST,
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc888_4ST_ch2_intel_init[] = {
-/* Mic-in jack as mic in */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-/* Line-in jack as Line in */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-/* Line-Out as Front */
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
- { } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc888_4ST_ch4_intel_init[] = {
-/* Mic-in jack as mic in */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-/* Line-in jack as Surround */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-Out as Front */
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc888_4ST_ch6_intel_init[] = {
-/* Mic-in jack as CLFE */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-in jack as Surround */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
- { } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc888_4ST_ch8_intel_init[] = {
-/* Mic-in jack as CLFE */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-in jack as Surround */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-Out as Side */
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
- { } /* end */
-};
-
-static const struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
- { 2, alc888_4ST_ch2_intel_init },
- { 4, alc888_4ST_ch4_intel_init },
- { 6, alc888_4ST_ch6_intel_init },
- { 8, alc888_4ST_ch8_intel_init },
-};
-
-/*
- * ALC888 Fujitsu Siemens Amillo xa3530
- */
-
-static const struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
-/* Front Mic: set to PIN_IN (empty by default) */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Connect Internal HP to Front */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect Bass HP to Front */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect Line-Out side jack (SPDIF) to Side */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-/* Connect Mic jack to CLFE */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
-/* Connect Line-in jack to Surround */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-/* Connect HP out jack to Front */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Enable unsolicited event for HP jack and Line-out jack */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {}
-};
-
-static void alc889_automute_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->autocfg.speaker_pins[2] = 0x17;
- spec->autocfg.speaker_pins[3] = 0x19;
- spec->autocfg.speaker_pins[4] = 0x1a;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc889_intel_init_hook(struct hda_codec *codec)
-{
- alc889_coef_init(codec);
- alc_hp_automute(codec);
-}
-
-static void alc888_fujitsu_xa3530_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x17; /* line-out */
- spec->autocfg.hp_pins[1] = 0x1b; /* hp */
- spec->autocfg.speaker_pins[0] = 0x14; /* speaker */
- spec->autocfg.speaker_pins[1] = 0x15; /* bass */
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/*
- * ALC888 Acer Aspire 4930G model
- */
-
-static const struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
-/* Front Mic: set to PIN_IN (empty by default) */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Unselect Front Mic by default in input mixer 3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
-/* Enable unsolicited event for HP jack */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-/* Connect Internal HP to front */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect HP out to front */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-/*
- * ALC888 Acer Aspire 6530G model
- */
-
-static const struct hda_verb alc888_acer_aspire_6530g_verbs[] = {
-/* Route to built-in subwoofer as well as speakers */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-/* Bias voltage on for external mic port */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
-/* Front Mic: set to PIN_IN (empty by default) */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Unselect Front Mic by default in input mixer 3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
-/* Enable unsolicited event for HP jack */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-/* Enable speaker output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-/* Enable headphone output */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-/*
- *ALC888 Acer Aspire 7730G model
- */
-
-static const struct hda_verb alc888_acer_aspire_7730G_verbs[] = {
-/* Bias voltage on for external mic port */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN | PIN_VREF80},
-/* Front Mic: set to PIN_IN (empty by default) */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Unselect Front Mic by default in input mixer 3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
-/* Enable unsolicited event for HP jack */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-/* Enable speaker output */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
-/* Enable headphone output */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
-/*Enable internal subwoofer */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x17, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-/*
- * ALC889 Acer Aspire 8930G model
- */
-
-static const struct hda_verb alc889_acer_aspire_8930g_verbs[] = {
-/* Front Mic: set to PIN_IN (empty by default) */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Unselect Front Mic by default in input mixer 3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
-/* Enable unsolicited event for HP jack */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-/* Connect Internal Front to Front */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect Internal Rear to Rear */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x01},
-/* Connect Internal CLFE to CLFE */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
-/* Connect HP out to Front */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Enable all DACs */
-/* DAC DISABLE/MUTE 1? */
-/* setting bits 1-5 disables DAC nids 0x02-0x06 apparently. Init=0x38 */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x03},
- {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
-/* DAC DISABLE/MUTE 2? */
-/* some bit here disables the other DACs. Init=0x4900 */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x08},
- {0x20, AC_VERB_SET_PROC_COEF, 0x0000},
-/* DMIC fix
- * This laptop has a stereo digital microphone. The mics are only 1cm apart
- * which makes the stereo useless. However, either the mic or the ALC889
- * makes the signal become a difference/sum signal instead of standard
- * stereo, which is annoying. So instead we flip this bit which makes the
- * codec replicate the sum signal to both channels, turning it into a
- * normal mono mic.
- */
-/* DMIC_CONTROL? Init value = 0x0001 */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
- {0x20, AC_VERB_SET_PROC_COEF, 0x0003},
- { }
-};
-
-static const struct hda_input_mux alc888_2_capture_sources[2] = {
- /* Front mic only available on one ADC */
- {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "Front Mic", 0xb },
- },
- },
- {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
- }
-};
-
-static const struct hda_input_mux alc888_acer_aspire_6530_sources[2] = {
- /* Interal mic only available on one ADC */
- {
- .num_items = 5,
- .items = {
- { "Mic", 0x0 },
- { "Line In", 0x2 },
- { "CD", 0x4 },
- { "Input Mix", 0xa },
- { "Internal Mic", 0xb },
- },
- },
- {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Line In", 0x2 },
- { "CD", 0x4 },
- { "Input Mix", 0xa },
- },
- }
-};
-
-static const struct hda_input_mux alc889_capture_sources[3] = {
- /* Digital mic only available on first "ADC" */
- {
- .num_items = 5,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "Front Mic", 0xb },
- { "Input Mix", 0xa },
- },
- },
- {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "Input Mix", 0xa },
- },
- },
- {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "Input Mix", 0xa },
- },
- }
-};
-
-static const struct snd_kcontrol_new alc888_base_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc888_acer_aspire_4930g_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
- HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Internal LFE Playback Volume", 0x0f, 1, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Internal LFE Playback Switch", 0x0f, 1, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc889_acer_aspire_8930g_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-
-static void alc888_acer_aspire_4930g_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->autocfg.speaker_pins[2] = 0x17;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc888_acer_aspire_6530g_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->autocfg.speaker_pins[2] = 0x17;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc888_acer_aspire_7730g_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->autocfg.speaker_pins[2] = 0x17;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc889_acer_aspire_8930g_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->autocfg.speaker_pins[2] = 0x1b;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-#define ALC882_DIGOUT_NID 0x06
-#define ALC882_DIGIN_NID 0x0a
-#define ALC883_DIGOUT_NID ALC882_DIGOUT_NID
-#define ALC883_DIGIN_NID ALC882_DIGIN_NID
-#define ALC1200_DIGOUT_NID 0x10
-
-
-static const struct hda_channel_mode alc882_ch_modes[1] = {
- { 8, NULL }
-};
-
-/* DACs */
-static const hda_nid_t alc882_dac_nids[4] = {
- /* front, rear, clfe, rear_surr */
- 0x02, 0x03, 0x04, 0x05
-};
-#define alc883_dac_nids alc882_dac_nids
-
-/* ADCs */
-#define alc882_adc_nids alc880_adc_nids
-#define alc882_adc_nids_alt alc880_adc_nids_alt
-#define alc883_adc_nids alc882_adc_nids_alt
-static const hda_nid_t alc883_adc_nids_alt[1] = { 0x08 };
-static const hda_nid_t alc883_adc_nids_rev[2] = { 0x09, 0x08 };
-#define alc889_adc_nids alc880_adc_nids
-
-static const hda_nid_t alc882_capsrc_nids[3] = { 0x24, 0x23, 0x22 };
-static const hda_nid_t alc882_capsrc_nids_alt[2] = { 0x23, 0x22 };
-#define alc883_capsrc_nids alc882_capsrc_nids_alt
-static const hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
-#define alc889_capsrc_nids alc882_capsrc_nids
-
-/* input MUX */
-/* FIXME: should be a matrix-type input source selection */
-
-static const struct hda_input_mux alc882_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-#define alc883_capture_source alc882_capture_source
-
-static const struct hda_input_mux alc889_capture_source = {
- .num_items = 3,
- .items = {
- { "Front Mic", 0x0 },
- { "Mic", 0x3 },
- { "Line", 0x2 },
- },
-};
-
-static const struct hda_input_mux mb5_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x1 },
- { "Line", 0x7 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux macmini3_capture_source = {
- .num_items = 2,
- .items = {
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux alc883_3stack_6ch_intel = {
- .num_items = 4,
- .items = {
- { "Mic", 0x1 },
- { "Front Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux alc883_lenovo_101e_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x1 },
- { "Line", 0x2 },
- },
-};
-
-static const struct hda_input_mux alc883_lenovo_nb0763_capture_source = {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Internal Mic", 0x1 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
-};
-
-static const struct hda_input_mux alc883_fujitsu_pi2515_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x0 },
- { "Internal Mic", 0x1 },
- },
-};
-
-static const struct hda_input_mux alc883_lenovo_sky_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Front Mic", 0x1 },
- { "Line", 0x4 },
- },
-};
-
-static const struct hda_input_mux alc883_asus_eee1601_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- },
-};
-
-static const struct hda_input_mux alc889A_mb31_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x0 },
- /* Front Mic (0x01) unused */
- { "Line", 0x2 },
- /* Line 2 (0x03) unused */
- /* CD (0x04) unused? */
- },
-};
-
-static const struct hda_input_mux alc889A_imac91_capture_source = {
- .num_items = 2,
- .items = {
- { "Mic", 0x01 },
- { "Line", 0x2 }, /* Not sure! */
- },
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_channel_mode alc883_3ST_2ch_modes[1] = {
- { 2, NULL }
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc882_3ST_ch2_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc882_3ST_ch4_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc882_3ST_ch6_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc882_3ST_6ch_modes[3] = {
- { 2, alc882_3ST_ch2_init },
- { 4, alc882_3ST_ch4_init },
- { 6, alc882_3ST_ch6_init },
-};
-
-#define alc883_3ST_6ch_modes alc882_3ST_6ch_modes
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc883_3ST_ch2_clevo_init[] = {
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP },
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc883_3ST_ch4_clevo_init[] = {
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc883_3ST_ch6_clevo_init[] = {
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc883_3ST_6ch_clevo_modes[3] = {
- { 2, alc883_3ST_ch2_clevo_init },
- { 4, alc883_3ST_ch4_clevo_init },
- { 6, alc883_3ST_ch6_clevo_init },
-};
-
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc882_sixstack_ch6_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc882_sixstack_ch8_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc882_sixstack_modes[2] = {
- { 6, alc882_sixstack_ch6_init },
- { 8, alc882_sixstack_ch8_init },
-};
-
-
-/* Macbook Air 2,1 */
-
-static const struct hda_channel_mode alc885_mba21_ch_modes[1] = {
- { 2, NULL },
-};
-
-/*
- * macbook pro ALC885 can switch LineIn to LineOut without losing Mic
- */
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc885_mbp_ch2_init[] = {
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- { } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc885_mbp_ch4_init[] = {
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- { } /* end */
-};
-
-static const struct hda_channel_mode alc885_mbp_4ch_modes[2] = {
- { 2, alc885_mbp_ch2_init },
- { 4, alc885_mbp_ch4_init },
-};
-
-/*
- * 2ch
- * Speakers/Woofer/HP = Front
- * LineIn = Input
- */
-static const struct hda_verb alc885_mb5_ch2_init[] = {
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- { } /* end */
-};
-
-/*
- * 6ch mode
- * Speakers/HP = Front
- * Woofer = LFE
- * LineIn = Surround
- */
-static const struct hda_verb alc885_mb5_ch6_init[] = {
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- { } /* end */
-};
-
-static const struct hda_channel_mode alc885_mb5_6ch_modes[2] = {
- { 2, alc885_mb5_ch2_init },
- { 6, alc885_mb5_ch6_init },
-};
-
-#define alc885_macmini3_6ch_modes alc885_mb5_6ch_modes
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc883_4ST_ch2_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc883_4ST_ch4_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc883_4ST_ch6_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc883_4ST_ch8_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc883_4ST_8ch_modes[4] = {
- { 2, alc883_4ST_ch2_init },
- { 4, alc883_4ST_ch4_init },
- { 6, alc883_4ST_ch6_init },
- { 8, alc883_4ST_ch8_init },
-};
-
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc883_3ST_ch2_intel_init[] = {
- { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc883_3ST_ch4_intel_init[] = {
- { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc883_3ST_ch6_intel_init[] = {
- { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x19, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc883_3ST_6ch_intel_modes[3] = {
- { 2, alc883_3ST_ch2_intel_init },
- { 4, alc883_3ST_ch4_intel_init },
- { 6, alc883_3ST_ch6_intel_init },
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc889_ch2_intel_init[] = {
- { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
- { 0x19, AC_VERB_SET_CONNECT_SEL, 0x00 },
- { 0x16, AC_VERB_SET_CONNECT_SEL, 0x00 },
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00 },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc889_ch6_intel_init[] = {
- { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
- { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc889_ch8_intel_init[] = {
- { 0x14, AC_VERB_SET_CONNECT_SEL, 0x00 },
- { 0x19, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { 0x16, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03 },
- { 0x1a, AC_VERB_SET_CONNECT_SEL, 0x03 },
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc889_8ch_intel_modes[3] = {
- { 2, alc889_ch2_intel_init },
- { 6, alc889_ch6_intel_init },
- { 8, alc889_ch8_intel_init },
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc883_sixstack_ch6_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { } /* end */
-};
-
-/*
- * 8ch mode
- */
-static const struct hda_verb alc883_sixstack_ch8_init[] = {
- { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc883_sixstack_modes[2] = {
- { 6, alc883_sixstack_ch6_init },
- { 8, alc883_sixstack_ch8_init },
-};
-
-
-/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
- * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
- */
-static const struct snd_kcontrol_new alc882_base_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-/* Macbook Air 2,1 same control for HP and internal Speaker */
-
-static const struct snd_kcontrol_new alc885_mba21_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_OUTPUT),
- { }
-};
-
-
-static const struct snd_kcontrol_new alc885_mbp3_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Headphone Playback Switch", 0x0e, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
- HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_mb5_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE ("Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0x00, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_macmini3_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("LFE Playback Volume", 0x0e, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("LFE Playback Switch", 0x0e, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0f, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE ("Headphone Playback Switch", 0x0f, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_MUTE ("Line Playback Switch", 0x0b, 0x07, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Boost Volume", 0x15, 0x00, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_imac91_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 0x02, HDA_INPUT),
- { } /* end */
-};
-
-
-static const struct snd_kcontrol_new alc882_w2jc_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc882_targa_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- { } /* end */
-};
-
-/* Pin assignment: Front=0x14, HP = 0x15, Front = 0x16, ???
- * Front Mic=0x18, Line In = 0x1a, Line In = 0x1b, CD = 0x1c
- */
-static const struct snd_kcontrol_new alc882_asus_a7j_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Mobile Front Playback Switch", 0x16, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mobile Line Playback Volume", 0x0b, 0x03, HDA_INPUT),
- HDA_CODEC_MUTE("Mobile Line Playback Switch", 0x0b, 0x03, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc882_asus_a7m_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc882_chmode_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-static const struct hda_verb alc882_base_init_verbs[] = {
- /* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Rear mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* CLFE mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Side mixer */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
-
- /* Front Pin: output 0 (0x0c) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Rear Pin: output 1 (0x0d) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* CLFE Pin: output 2 (0x0e) */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* Side Pin: output 3 (0x0f) */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
- /* Mic (rear) pin: input vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin: input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line-2 In: Headphone output (output 0 - 0x0c) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* CD pin widget for input */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-
- /* FIXME: use matrix-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
- /* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* ADC2: mute amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC3: mute amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- { }
-};
-
-static const struct hda_verb alc882_adc1_init_verbs[] = {
- /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* ADC1: mute amp left and right */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- { }
-};
-
-static const struct hda_verb alc882_eapd_verbs[] = {
- /* change to EAPD mode */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3060},
- { }
-};
-
-static const struct hda_verb alc889_eapd_verbs[] = {
- {0x14, AC_VERB_SET_EAPD_BTLENABLE, 2},
- {0x15, AC_VERB_SET_EAPD_BTLENABLE, 2},
- { }
-};
-
-static const struct hda_verb alc_hp15_unsol_verbs[] = {
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC_HP_EVENT},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {}
-};
-
-static const struct hda_verb alc885_init_verbs[] = {
- /* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* Rear mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* CLFE mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* Side mixer */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- /* Front HP Pin: output 0 (0x0c) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Front Pin: output 0 (0x0c) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Rear Pin: output 1 (0x0d) */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x19, AC_VERB_SET_CONNECT_SEL, 0x01},
- /* CLFE Pin: output 2 (0x0e) */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* Side Pin: output 3 (0x0f) */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
- /* Mic (rear) pin: input vref at 80% */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin: input */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- /* Mixer elements: 0x18, , 0x1a, 0x1b */
- /* Input mixer1 */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- /* ADC2: mute amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- /* ADC3: mute amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
-
- { }
-};
-
-static const struct hda_verb alc885_init_input_verbs[] = {
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
- { }
-};
-
-
-/* Unmute Selector 24h and set the default input to front mic */
-static const struct hda_verb alc889_init_input_verbs[] = {
- {0x24, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- { }
-};
-
-
-#define alc883_init_verbs alc882_base_init_verbs
-
-/* Mac Pro test */
-static const struct snd_kcontrol_new alc882_macpro_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
- /* FIXME: this looks suspicious...
- HDA_CODEC_VOLUME("Beep Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Beep Playback Switch", 0x0b, 0x02, HDA_INPUT),
- */
- { } /* end */
-};
-
-static const struct hda_verb alc882_macpro_init_verbs[] = {
- /* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Front Pin: output 0 (0x0c) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Speaker: output */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
- /* Headphone output (output 0 - 0x0c) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* FIXME: use matrix-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
- /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* ADC1: mute amp left and right */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC2: mute amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC3: mute amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- { }
-};
-
-/* Macbook 5,1 */
-static const struct hda_verb alc885_mb5_init_verbs[] = {
- /* DACs */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Front mixer */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Surround mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* LFE mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* HP mixer */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Front Pin (0x0c) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* LFE Pin (0x0e) */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* HP Pin (0x0f) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0x1)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x7)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0x4)},
- { }
-};
-
-/* Macmini 3,1 */
-static const struct hda_verb alc885_macmini3_init_verbs[] = {
- /* DACs */
- {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Front mixer */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Surround mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* LFE mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* HP mixer */
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Front Pin (0x0c) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* LFE Pin (0x0e) */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x01},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02},
- /* HP Pin (0x0f) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x03},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* Line In pin */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- { }
-};
-
-
-static const struct hda_verb alc885_mba21_init_verbs[] = {
- /*Internal and HP Speaker Mixer*/
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /*Internal Speaker Pin (0x0c)*/
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP Pin: output 0 (0x0e) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)},
- /* Line in (is hp when jack connected)*/
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
-
- { }
- };
-
-
-/* Macbook Pro rev3 */
-static const struct hda_verb alc885_mbp3_init_verbs[] = {
- /* Front mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Rear mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* HP mixer */
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Front Pin: output 0 (0x0c) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP Pin: output 0 (0x0e) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* Mic (rear) pin: input vref at 80% */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Line In pin: use output 1 when in LineOut mode */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-
- /* FIXME: use matrix-type input source selection */
- /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
- /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Input mixer2 */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* Input mixer3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* ADC1: mute amp left and right */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC2: mute amp left and right */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* ADC3: mute amp left and right */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- { }
-};
-
-/* iMac 9,1 */
-static const struct hda_verb alc885_imac91_init_verbs[] = {
- /* Internal Speaker Pin (0x0c) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, (PIN_OUT | AC_PINCTL_VREF_50) },
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP Pin: Rear */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, (ALC_HP_EVENT | AC_USRSP_EN)},
- /* Line in Rear */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, AC_PINCTL_VREF_50},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Front Mic pin: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- /* Rear mixer */
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* Line-Out mixer: unmute input/output amp left and right (volume = 0) */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- /* 0x24 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* 0x23 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* 0x22 [Audio Mixer] wcaps 0x20010b: Stereo Amp-In */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
- /* 0x07 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
- {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* 0x08 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
- {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* 0x09 [Audio Input] wcaps 0x10011b: Stereo Amp-In */
- {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
- { }
-};
-
-/* iMac 24 mixer. */
-static const struct snd_kcontrol_new alc885_imac24_mixer[] = {
- HDA_CODEC_VOLUME("Master Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_CODEC_MUTE("Master Playback Switch", 0x0c, 0x00, HDA_INPUT),
- { } /* end */
-};
-
-/* iMac 24 init verbs. */
-static const struct hda_verb alc885_imac24_init_verbs[] = {
- /* Internal speakers: output 0 (0x0c) */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Internal speakers: output 0 (0x0c) */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Headphone: output 0 (0x0c) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* Front Mic: input vref at 80% */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
- { }
-};
-
-/* Toggle speaker-output according to the hp-jack state */
-static void alc885_imac24_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x18;
- spec->autocfg.speaker_pins[1] = 0x1a;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-#define alc885_mb5_setup alc885_imac24_setup
-#define alc885_macmini3_setup alc885_imac24_setup
-
-/* Macbook Air 2,1 */
-static void alc885_mba21_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x18;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-
-
-static void alc885_mbp3_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc885_imac91_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x18;
- spec->autocfg.speaker_pins[1] = 0x1a;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc882_targa_verbs[] = {
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
-
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { } /* end */
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc882_targa_automute(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- alc_hp_automute(codec);
- snd_hda_codec_write_cache(codec, 1, 0, AC_VERB_SET_GPIO_DATA,
- spec->jack_present ? 1 : 3);
-}
-
-static void alc882_targa_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x1b;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc882_targa_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) == ALC_HP_EVENT)
- alc882_targa_automute(codec);
-}
-
-static const struct hda_verb alc882_asus_a7j_verbs[] = {
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
-
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- { } /* end */
-};
-
-static const struct hda_verb alc882_asus_a7m_verbs[] = {
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front */
-
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
- { } /* end */
-};
-
-static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
-{
- unsigned int gpiostate, gpiomask, gpiodir;
-
- gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
- AC_VERB_GET_GPIO_DATA, 0);
-
- if (!muted)
- gpiostate |= (1 << pin);
- else
- gpiostate &= ~(1 << pin);
-
- gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
- AC_VERB_GET_GPIO_MASK, 0);
- gpiomask |= (1 << pin);
-
- gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
- AC_VERB_GET_GPIO_DIRECTION, 0);
- gpiodir |= (1 << pin);
-
-
- snd_hda_codec_write(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_MASK, gpiomask);
- snd_hda_codec_write(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_DIRECTION, gpiodir);
-
- msleep(1);
-
- snd_hda_codec_write(codec, codec->afg, 0,
- AC_VERB_SET_GPIO_DATA, gpiostate);
-}
-
-/* set up GPIO at initialization */
-static void alc885_macpro_init_hook(struct hda_codec *codec)
-{
- alc882_gpio_mute(codec, 0, 0);
- alc882_gpio_mute(codec, 1, 0);
-}
-
-/* set up GPIO and update auto-muting at initialization */
-static void alc885_imac24_init_hook(struct hda_codec *codec)
-{
- alc885_macpro_init_hook(codec);
- alc_hp_automute(codec);
-}
-
-/* 2ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:front) */
-static const struct hda_verb alc889A_mb31_ch2_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
- { } /* end */
-};
-
-/* 4ch mode (Speaker:front, Subwoofer:CLFE, Line:CLFE, Headphones:front) */
-static const struct hda_verb alc889A_mb31_ch4_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP as front */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
- { } /* end */
-};
-
-/* 5ch mode (Speaker:front, Subwoofer:CLFE, Line:input, Headphones:rear) */
-static const struct hda_verb alc889A_mb31_ch5_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as rear */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Subwoofer on */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Line as input */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Line off */
- { } /* end */
-};
-
-/* 6ch mode (Speaker:front, Subwoofer:off, Line:CLFE, Headphones:Rear) */
-static const struct hda_verb alc889A_mb31_ch6_init[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01}, /* HP as front */
- {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Subwoofer off */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* Line as output */
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, /* Line on */
- { } /* end */
-};
-
-static const struct hda_channel_mode alc889A_mb31_6ch_modes[4] = {
- { 2, alc889A_mb31_ch2_init },
- { 4, alc889A_mb31_ch4_init },
- { 5, alc889A_mb31_ch5_init },
- { 6, alc889A_mb31_ch6_init },
-};
-
-static const struct hda_verb alc883_medion_eapd_verbs[] = {
- /* eanable EAPD on medion laptop */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
- { }
-};
-
-#define alc883_base_mixer alc882_base_mixer
-
-static const struct snd_kcontrol_new alc883_mitac_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc885_8ch_intel_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x1b, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x3, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_fivestack_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_targa_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_targa_2ch_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_targa_8ch_mixer[] = {
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Speaker Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_medion_wim2160_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x08, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_verb alc883_medion_wim2160_verbs[] = {
- /* Unmute front mixer */
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- /* Set speaker pin to front mixer */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- /* Init headphone pin */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-
- { } /* end */
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_medion_wim2160_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1a;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc888_acer_aspire_6530_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("LFE Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0e, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0e, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume",
- 0x0d, 1, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0d, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0d, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0d, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc889A_mb31_mixer[] = {
- /* Output mixers */
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x00,
- HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x00, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 0x02, HDA_INPUT),
- /* Output switches */
- HDA_CODEC_MUTE("Enable Speaker", 0x14, 0x00, HDA_OUTPUT),
- HDA_CODEC_MUTE("Enable Headphones", 0x15, 0x00, HDA_OUTPUT),
- HDA_CODEC_MUTE_MONO("Enable LFE", 0x16, 2, 0x00, HDA_OUTPUT),
- /* Boost mixers */
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Boost Volume", 0x1a, 0x00, HDA_INPUT),
- /* Input mixers */
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x00, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x00, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_vaiott_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x19, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
- { } /* end */
-};
-
-static const struct hda_bind_ctls alc883_bind_cap_vol = {
- .ops = &snd_hda_bind_vol,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
- HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
- 0
- },
-};
-
-static const struct hda_bind_ctls alc883_bind_cap_switch = {
- .ops = &snd_hda_bind_sw,
- .values = {
- HDA_COMPOSE_AMP_VAL(0x08, 3, 0, HDA_INPUT),
- HDA_COMPOSE_AMP_VAL(0x09, 3, 0, HDA_INPUT),
- 0
- },
-};
-
-static const struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost Volume", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
- HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
- HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- /* .name = "Capture Source", */
- .name = "Input Source",
- .count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
- },
- { } /* end */
-};
-
-static const struct snd_kcontrol_new alc883_chmode_mixer[] = {
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Channel Mode",
- .info = alc_ch_mode_info,
- .get = alc_ch_mode_get,
- .put = alc_ch_mode_put,
- },
- { } /* end */
-};
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_mitac_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x17;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc883_mitac_verbs[] = {
- /* HP */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Subwoofer */
- {0x17, AC_VERB_SET_CONNECT_SEL, 0x02},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- /* enable unsolicited event */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN}, */
-
- { } /* end */
-};
-
-static const struct hda_verb alc883_clevo_m540r_verbs[] = {
- /* HP */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Int speaker */
- /*{0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},*/
-
- /* enable unsolicited event */
- /*
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
- */
-
- { } /* end */
-};
-
-static const struct hda_verb alc883_clevo_m720_verbs[] = {
- /* HP */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Int speaker */
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- /* enable unsolicited event */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
-
- { } /* end */
-};
-
-static const struct hda_verb alc883_2ch_fujitsu_pi2515_verbs[] = {
- /* HP */
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- /* Subwoofer */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- /* enable unsolicited event */
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-
- { } /* end */
-};
-
-static const struct hda_verb alc883_targa_verbs[] = {
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
-/* Connect Line-Out side jack (SPDIF) to Side */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-/* Connect Mic jack to CLFE */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
-/* Connect Line-in jack to Surround */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-/* Connect HP out jack to Front */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-
- { } /* end */
-};
-
-static const struct hda_verb alc883_lenovo_101e_verbs[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_FRONT_EVENT|AC_USRSP_EN},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT|AC_USRSP_EN},
- { } /* end */
-};
-
-static const struct hda_verb alc883_lenovo_nb0763_verbs[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- { } /* end */
-};
-
-static const struct hda_verb alc888_lenovo_ms7195_verbs[] = {
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_FRONT_EVENT | AC_USRSP_EN},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { } /* end */
-};
-
-static const struct hda_verb alc883_haier_w66_verbs[] = {
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
-
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
-
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- { } /* end */
-};
-
-static const struct hda_verb alc888_lenovo_sky_verbs[] = {
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { } /* end */
-};
-
-static const struct hda_verb alc888_6st_dell_verbs[] = {
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { }
-};
-
-static const struct hda_verb alc883_vaiott_verbs[] = {
- /* HP */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
-
- /* enable unsolicited event */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
-
- { } /* end */
-};
-
-static void alc888_3st_hp_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->autocfg.speaker_pins[2] = 0x18;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc888_3st_hp_verbs[] = {
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Front: output 0 (0x0c) */
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x01}, /* Rear : output 1 (0x0d) */
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* CLFE : output 2 (0x0e) */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { } /* end */
-};
-
-/*
- * 2ch mode
- */
-static const struct hda_verb alc888_3st_hp_2ch_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { } /* end */
-};
-
-/*
- * 4ch mode
- */
-static const struct hda_verb alc888_3st_hp_4ch_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static const struct hda_verb alc888_3st_hp_6ch_init[] = {
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x18, AC_VERB_SET_CONNECT_SEL, 0x02 },
- { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
- { 0x16, AC_VERB_SET_CONNECT_SEL, 0x01 },
- { } /* end */
-};
-
-static const struct hda_channel_mode alc888_3st_hp_modes[3] = {
- { 2, alc888_3st_hp_2ch_init },
- { 4, alc888_3st_hp_4ch_init },
- { 6, alc888_3st_hp_6ch_init },
-};
-
-static void alc888_lenovo_ms7195_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.line_out_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_lenovo_nb0763_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/* toggle speaker-output according to the hp-jack state */
-#define alc883_targa_init_hook alc882_targa_init_hook
-#define alc883_targa_unsol_event alc882_targa_unsol_event
-
-static void alc883_clevo_m720_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc883_clevo_m720_init_hook(struct hda_codec *codec)
-{
- alc_hp_automute(codec);
- alc88x_simple_mic_automute(codec);
-}
-
-static void alc883_clevo_m720_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- switch (res >> 26) {
- case ALC_MIC_EVENT:
- alc88x_simple_mic_automute(codec);
- break;
- default:
- alc_sku_unsol_event(codec, res);
- break;
- }
-}
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_2ch_fujitsu_pi2515_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc883_haier_w66_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc883_lenovo_101e_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.line_out_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->automute = 1;
- spec->detect_line = 1;
- spec->automute_lines = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-/* toggle speaker-output according to the hp-jack state */
-static void alc883_acer_aspire_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x15;
- spec->autocfg.speaker_pins[1] = 0x16;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc883_acer_eapd_verbs[] = {
- /* HP Pin: output 0 (0x0c) */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Front Pin: output 0 (0x0c) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* eanable EAPD on medion laptop */
- {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
- {0x20, AC_VERB_SET_PROC_COEF, 0x3050},
- /* enable unsolicited event */
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { }
-};
-
-static void alc888_6st_dell_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x15;
- spec->autocfg.speaker_pins[2] = 0x16;
- spec->autocfg.speaker_pins[3] = 0x17;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc888_lenovo_sky_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x15;
- spec->autocfg.speaker_pins[2] = 0x16;
- spec->autocfg.speaker_pins[3] = 0x17;
- spec->autocfg.speaker_pins[4] = 0x1a;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static void alc883_vaiott_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x15;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x17;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc888_asus_m90v_verbs[] = {
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
- /* enable unsolicited event */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_MIC_EVENT | AC_USRSP_EN},
- { } /* end */
-};
-
-static void alc883_mode2_setup(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x1b;
- spec->autocfg.speaker_pins[0] = 0x14;
- spec->autocfg.speaker_pins[1] = 0x15;
- spec->autocfg.speaker_pins[2] = 0x16;
- spec->ext_mic_pin = 0x18;
- spec->int_mic_pin = 0x19;
- spec->auto_mic = 1;
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_AMP;
-}
-
-static const struct hda_verb alc888_asus_eee1601_verbs[] = {
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
- {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
- {0x20, AC_VERB_SET_COEF_INDEX, 0x0b},
- {0x20, AC_VERB_SET_PROC_COEF, 0x0838},
- /* enable unsolicited event */
- {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- { } /* end */
-};
-
-static void alc883_eee1601_inithook(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- spec->autocfg.hp_pins[0] = 0x14;
- spec->autocfg.speaker_pins[0] = 0x1b;
- alc_hp_automute(codec);
-}
-
-static const struct hda_verb alc889A_mb31_verbs[] = {
- /* Init rear pin (used as headphone output) */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc4}, /* Apple Headphones */
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00}, /* Connect to front */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC_HP_EVENT | AC_USRSP_EN},
- /* Init line pin (used as output in 4ch and 6ch mode) */
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x02}, /* Connect to CLFE */
- /* Init line 2 pin (used as headphone out by default) */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, /* Use as input */
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE}, /* Mute output */
- { } /* end */
-};
-
-/* Mute speakers according to the headphone jack state */
-static void alc889A_mb31_automute(struct hda_codec *codec)
-{
- unsigned int present;
-
- /* Mute only in 2ch or 4ch mode */
- if (snd_hda_codec_read(codec, 0x15, 0, AC_VERB_GET_CONNECT_SEL, 0)
- == 0x00) {
- present = snd_hda_jack_detect(codec, 0x15);
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
- snd_hda_codec_amp_stereo(codec, 0x16, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, present ? HDA_AMP_MUTE : 0);
- }
-}
-
-static void alc889A_mb31_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- if ((res >> 26) == ALC_HP_EVENT)
- alc889A_mb31_automute(codec);
-}
-
-static const hda_nid_t alc883_slave_dig_outs[] = {
- ALC1200_DIGOUT_NID, 0,
-};
-
-static const hda_nid_t alc1200_slave_dig_outs[] = {
- ALC883_DIGOUT_NID, 0,
-};
-
-/*
- * configuration and preset
- */
-static const char * const alc882_models[ALC882_MODEL_LAST] = {
- [ALC882_3ST_DIG] = "3stack-dig",
- [ALC882_6ST_DIG] = "6stack-dig",
- [ALC882_ARIMA] = "arima",
- [ALC882_W2JC] = "w2jc",
- [ALC882_TARGA] = "targa",
- [ALC882_ASUS_A7J] = "asus-a7j",
- [ALC882_ASUS_A7M] = "asus-a7m",
- [ALC885_MACPRO] = "macpro",
- [ALC885_MB5] = "mb5",
- [ALC885_MACMINI3] = "macmini3",
- [ALC885_MBA21] = "mba21",
- [ALC885_MBP3] = "mbp3",
- [ALC885_IMAC24] = "imac24",
- [ALC885_IMAC91] = "imac91",
- [ALC883_3ST_2ch_DIG] = "3stack-2ch-dig",
- [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",
- [ALC883_3ST_6ch] = "3stack-6ch",
- [ALC883_6ST_DIG] = "alc883-6stack-dig",
- [ALC883_TARGA_DIG] = "targa-dig",
- [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
- [ALC883_TARGA_8ch_DIG] = "targa-8ch-dig",
- [ALC883_ACER] = "acer",
- [ALC883_ACER_ASPIRE] = "acer-aspire",
- [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g",
- [ALC888_ACER_ASPIRE_6530G] = "acer-aspire-6530g",
- [ALC888_ACER_ASPIRE_8930G] = "acer-aspire-8930g",
- [ALC888_ACER_ASPIRE_7730G] = "acer-aspire-7730g",
- [ALC883_MEDION] = "medion",
- [ALC883_MEDION_WIM2160] = "medion-wim2160",
- [ALC883_LAPTOP_EAPD] = "laptop-eapd",
- [ALC883_LENOVO_101E_2ch] = "lenovo-101e",
- [ALC883_LENOVO_NB0763] = "lenovo-nb0763",
- [ALC888_LENOVO_MS7195_DIG] = "lenovo-ms7195-dig",
- [ALC888_LENOVO_SKY] = "lenovo-sky",
- [ALC883_HAIER_W66] = "haier-w66",
- [ALC888_3ST_HP] = "3stack-hp",
- [ALC888_6ST_DELL] = "6stack-dell",
- [ALC883_MITAC] = "mitac",
- [ALC883_CLEVO_M540R] = "clevo-m540r",
- [ALC883_CLEVO_M720] = "clevo-m720",
- [ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
- [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
- [ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
- [ALC889A_INTEL] = "intel-alc889a",
- [ALC889_INTEL] = "intel-x58",
- [ALC1200_ASUS_P5Q] = "asus-p5q",
- [ALC889A_MB31] = "mb31",
- [ALC883_SONY_VAIO_TT] = "sony-vaio-tt",
- [ALC882_AUTO] = "auto",
-};
-
-static const struct snd_pci_quirk alc882_cfg_tbl[] = {
- SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
-
- SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_ACER_ASPIRE),
- SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_ACER_ASPIRE),
- SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_ACER_ASPIRE),
- SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
- SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
- SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
- SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
- ALC888_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
- ALC888_ACER_ASPIRE_4930G),
- SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
- ALC888_ACER_ASPIRE_8930G),
- SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
- ALC888_ACER_ASPIRE_8930G),
- SND_PCI_QUIRK(0x1025, 0x0157, "Acer X3200", ALC882_AUTO),
- SND_PCI_QUIRK(0x1025, 0x0158, "Acer AX1700-U3700A", ALC882_AUTO),
- SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
- ALC888_ACER_ASPIRE_6530G),
- SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
- ALC888_ACER_ASPIRE_6530G),
- SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
- ALC888_ACER_ASPIRE_7730G),
- /* default Acer -- disabled as it causes more problems.
- * model=auto should work fine now
- */
- /* SND_PCI_QUIRK_VENDOR(0x1025, "Acer laptop", ALC883_ACER), */
-
- SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
-
- SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavilion", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x103c, 0x2a4f, "HP Samba", ALC888_3ST_HP),
- SND_PCI_QUIRK(0x103c, 0x2a60, "HP Lucknow", ALC888_3ST_HP),
- SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x103c, 0x2a66, "HP Acacia", ALC888_3ST_HP),
- SND_PCI_QUIRK(0x103c, 0x2a72, "HP Educ.ar", ALC888_3ST_HP),
-
- SND_PCI_QUIRK(0x1043, 0x060d, "Asus A7J", ALC882_ASUS_A7J),
- SND_PCI_QUIRK(0x1043, 0x1243, "Asus A7J", ALC882_ASUS_A7J),
- SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_ASUS_A7M),
- SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
- SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_W2JC),
- SND_PCI_QUIRK(0x1043, 0x817f, "Asus P5LD2", ALC882_6ST_DIG),
- SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
- SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x1043, 0x8284, "Asus Z37E", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
- SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
-
- SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC883_SONY_VAIO_TT),
- SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
- SND_PCI_QUIRK(0x1071, 0x8227, "Mitac 82801H", ALC883_MITAC),
- SND_PCI_QUIRK(0x1071, 0x8253, "Mitac 8252d", ALC883_MITAC),
- SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
- SND_PCI_QUIRK(0x10f1, 0x2350, "TYAN-S2350", ALC888_6ST_DELL),
- SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
- SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte P35 DS3R", ALC882_6ST_DIG),
-
- SND_PCI_QUIRK(0x1462, 0x0349, "MSI", ALC883_TARGA_2ch_DIG),
- SND_PCI_QUIRK(0x1462, 0x040d, "MSI", ALC883_TARGA_2ch_DIG),
- SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
- SND_PCI_QUIRK(0x1462, 0x28fb, "Targa T8", ALC882_TARGA), /* MSI-1049 T8 */
- SND_PCI_QUIRK(0x1462, 0x2fb3, "MSI", ALC882_AUTO),
- SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x3729, "MSI S420", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x3783, "NEC S970", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
- SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x3fdf, "MSI", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x42cd, "MSI", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x4570, "MSI Wind Top AE2220", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x6510, "MSI GX620", ALC883_TARGA_8ch_DIG),
- SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x7350, "MSI", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x7437, "MSI NetOn AP1900", ALC883_TARGA_DIG),
- SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
- SND_PCI_QUIRK(0x1462, 0xaa08, "MSI", ALC883_TARGA_2ch_DIG),
-
- SND_PCI_QUIRK(0x147b, 0x1083, "Abit IP35-PRO", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1558, 0x0571, "Clevo laptop M570U", ALC883_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x1558, 0x0721, "Clevo laptop M720R", ALC883_CLEVO_M720),
- SND_PCI_QUIRK(0x1558, 0x0722, "Clevo laptop M720SR", ALC883_CLEVO_M720),
- SND_PCI_QUIRK(0x1558, 0x5409, "Clevo laptop M540R", ALC883_CLEVO_M540R),
- SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC883_LAPTOP_EAPD),
- SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
- /* SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA), */
- SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
- SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1100, "FSC AMILO Xi/Pi25xx",
- ALC883_FUJITSU_PI2515),
- SND_PCI_QUIRK_MASK(0x1734, 0xfff0, 0x1130, "Fujitsu AMILO Xa35xx",
- ALC888_FUJITSU_XA3530),
- SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
- SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
- SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
- SND_PCI_QUIRK(0x17aa, 0x3bfd, "Lenovo NB0763", ALC883_LENOVO_NB0763),
- SND_PCI_QUIRK(0x17aa, 0x101d, "Lenovo Sky", ALC888_LENOVO_SKY),
- SND_PCI_QUIRK(0x17c0, 0x4085, "MEDION MD96630", ALC888_LENOVO_MS7195_DIG),
- SND_PCI_QUIRK(0x17f2, 0x5000, "Albatron KI690-AM2", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1991, 0x5625, "Haier W66", ALC883_HAIER_W66),
-
- SND_PCI_QUIRK(0x8086, 0x0001, "DG33BUC", ALC883_3ST_6ch_INTEL),
- SND_PCI_QUIRK(0x8086, 0x0002, "DG33FBC", ALC883_3ST_6ch_INTEL),
- SND_PCI_QUIRK(0x8086, 0x2503, "82801H", ALC883_MITAC),
- SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_INTEL),
- SND_PCI_QUIRK(0x8086, 0x0021, "Intel IbexPeak", ALC889A_INTEL),
- SND_PCI_QUIRK(0x8086, 0x3b56, "Intel IbexPeak", ALC889A_INTEL),
- SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC882_6ST_DIG),
-
- {}
-};
-
-/* codec SSID table for Intel Mac */
-static const struct snd_pci_quirk alc882_ssid_cfg_tbl[] = {
- SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_MACPRO),
- SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_IMAC24),
- SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_IMAC24),
- SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889A_MB31),
- SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_ASUS_A7M),
- SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC885_MBA21),
- SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889A_MB31),
- SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC885_MBP3),
- SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_IMAC24),
- SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC885_IMAC91),
- SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC885_MB5),
- SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC885_MB5),
- /* FIXME: HP jack sense seems not working for MBP 5,1 or 5,2,
- * so apparently no perfect solution yet
- */
- SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC885_MB5),
- SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC885_MB5),
- SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC885_MACMINI3),
- {} /* terminator */
-};
-
-static const struct alc_config_preset alc882_presets[] = {
- [ALC882_3ST_DIG] = {
- .mixers = { alc882_base_mixer },
- .init_verbs = { alc882_base_init_verbs,
- alc882_adc1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
- .channel_mode = alc882_ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc882_capture_source,
- },
- [ALC882_6ST_DIG] = {
- .mixers = { alc882_base_mixer, alc882_chmode_mixer },
- .init_verbs = { alc882_base_init_verbs,
- alc882_adc1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
- .channel_mode = alc882_sixstack_modes,
- .input_mux = &alc882_capture_source,
- },
- [ALC882_ARIMA] = {
- .mixers = { alc882_base_mixer, alc882_chmode_mixer },
- .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
- alc882_eapd_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc882_sixstack_modes),
- .channel_mode = alc882_sixstack_modes,
- .input_mux = &alc882_capture_source,
- },
- [ALC882_W2JC] = {
- .mixers = { alc882_w2jc_mixer, alc882_chmode_mixer },
- .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
- alc882_eapd_verbs, alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc882_capture_source,
- .dig_out_nid = ALC882_DIGOUT_NID,
- },
- [ALC885_MBA21] = {
- .mixers = { alc885_mba21_mixer },
- .init_verbs = { alc885_mba21_init_verbs, alc880_gpio1_init_verbs },
- .num_dacs = 2,
- .dac_nids = alc882_dac_nids,
- .channel_mode = alc885_mba21_ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
- .input_mux = &alc882_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc885_mba21_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC885_MBP3] = {
- .mixers = { alc885_mbp3_mixer, alc882_chmode_mixer },
- .init_verbs = { alc885_mbp3_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = 2,
- .dac_nids = alc882_dac_nids,
- .hp_nid = 0x04,
- .channel_mode = alc885_mbp_4ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mbp_4ch_modes),
- .input_mux = &alc882_capture_source,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc885_mbp3_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC885_MB5] = {
- .mixers = { alc885_mb5_mixer, alc882_chmode_mixer },
- .init_verbs = { alc885_mb5_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .channel_mode = alc885_mb5_6ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mb5_6ch_modes),
- .input_mux = &mb5_capture_source,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc885_mb5_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC885_MACMINI3] = {
- .mixers = { alc885_macmini3_mixer, alc882_chmode_mixer },
- .init_verbs = { alc885_macmini3_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .channel_mode = alc885_macmini3_6ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_macmini3_6ch_modes),
- .input_mux = &macmini3_capture_source,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc885_macmini3_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC885_MACPRO] = {
- .mixers = { alc882_macpro_mixer },
- .init_verbs = { alc882_macpro_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
- .channel_mode = alc882_ch_modes,
- .input_mux = &alc882_capture_source,
- .init_hook = alc885_macpro_init_hook,
- },
- [ALC885_IMAC24] = {
- .mixers = { alc885_imac24_mixer },
- .init_verbs = { alc885_imac24_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
- .channel_mode = alc882_ch_modes,
- .input_mux = &alc882_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc885_imac24_setup,
- .init_hook = alc885_imac24_init_hook,
- },
- [ALC885_IMAC91] = {
- .mixers = {alc885_imac91_mixer},
- .init_verbs = { alc885_imac91_init_verbs,
- alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .channel_mode = alc885_mba21_ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc885_mba21_ch_modes),
- .input_mux = &alc889A_imac91_capture_source,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .dig_in_nid = ALC882_DIGIN_NID,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc885_imac91_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC882_TARGA] = {
- .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
- .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
- alc880_gpio3_init_verbs, alc882_targa_verbs},
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
- .adc_nids = alc882_adc_nids,
- .capsrc_nids = alc882_capsrc_nids,
- .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
- .channel_mode = alc882_3ST_6ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc882_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc882_targa_setup,
- .init_hook = alc882_targa_automute,
- },
- [ALC882_ASUS_A7J] = {
- .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
- .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
- alc882_asus_a7j_verbs},
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .num_adc_nids = ARRAY_SIZE(alc882_adc_nids),
- .adc_nids = alc882_adc_nids,
- .capsrc_nids = alc882_capsrc_nids,
- .num_channel_mode = ARRAY_SIZE(alc882_3ST_6ch_modes),
- .channel_mode = alc882_3ST_6ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc882_capture_source,
- },
- [ALC882_ASUS_A7M] = {
- .mixers = { alc882_asus_a7m_mixer, alc882_chmode_mixer },
- .init_verbs = { alc882_base_init_verbs, alc882_adc1_init_verbs,
- alc882_eapd_verbs, alc880_gpio1_init_verbs,
- alc882_asus_a7m_verbs },
- .num_dacs = ARRAY_SIZE(alc882_dac_nids),
- .dac_nids = alc882_dac_nids,
- .dig_out_nid = ALC882_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
- .channel_mode = alc880_threestack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc882_capture_source,
- },
- [ALC883_3ST_2ch_DIG] = {
- .mixers = { alc883_3ST_2ch_mixer },
- .init_verbs = { alc883_init_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- },
- [ALC883_3ST_6ch_DIG] = {
- .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
- .channel_mode = alc883_3ST_6ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_capture_source,
- },
- [ALC883_3ST_6ch] = {
- .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
- .channel_mode = alc883_3ST_6ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_capture_source,
- },
- [ALC883_3ST_6ch_INTEL] = {
- .mixers = { alc883_3ST_6ch_intel_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .slave_dig_outs = alc883_slave_dig_outs,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_intel_modes),
- .channel_mode = alc883_3ST_6ch_intel_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_3stack_6ch_intel,
- },
- [ALC889A_INTEL] = {
- .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
- .init_verbs = { alc885_init_verbs, alc885_init_input_verbs,
- alc_hp15_unsol_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
- .adc_nids = alc889_adc_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .slave_dig_outs = alc883_slave_dig_outs,
- .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
- .channel_mode = alc889_8ch_intel_modes,
- .capsrc_nids = alc889_capsrc_nids,
- .input_mux = &alc889_capture_source,
- .setup = alc889_automute_setup,
- .init_hook = alc_hp_automute,
- .unsol_event = alc_sku_unsol_event,
- .need_dac_fix = 1,
- },
- [ALC889_INTEL] = {
- .mixers = { alc885_8ch_intel_mixer, alc883_chmode_mixer },
- .init_verbs = { alc885_init_verbs, alc889_init_input_verbs,
- alc889_eapd_verbs, alc_hp15_unsol_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
- .adc_nids = alc889_adc_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .slave_dig_outs = alc883_slave_dig_outs,
- .num_channel_mode = ARRAY_SIZE(alc889_8ch_intel_modes),
- .channel_mode = alc889_8ch_intel_modes,
- .capsrc_nids = alc889_capsrc_nids,
- .input_mux = &alc889_capture_source,
- .setup = alc889_automute_setup,
- .init_hook = alc889_intel_init_hook,
- .unsol_event = alc_sku_unsol_event,
- .need_dac_fix = 1,
- },
- [ALC883_6ST_DIG] = {
- .mixers = { alc883_base_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
- .channel_mode = alc883_sixstack_modes,
- .input_mux = &alc883_capture_source,
- },
- [ALC883_TARGA_DIG] = {
- .mixers = { alc883_targa_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
- alc883_targa_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
- .channel_mode = alc883_3ST_6ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc883_targa_unsol_event,
- .setup = alc882_targa_setup,
- .init_hook = alc882_targa_automute,
- },
- [ALC883_TARGA_2ch_DIG] = {
- .mixers = { alc883_targa_2ch_mixer},
- .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
- alc883_targa_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .adc_nids = alc883_adc_nids_alt,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
- .capsrc_nids = alc883_capsrc_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc883_targa_unsol_event,
- .setup = alc882_targa_setup,
- .init_hook = alc882_targa_automute,
- },
- [ALC883_TARGA_8ch_DIG] = {
- .mixers = { alc883_targa_mixer, alc883_targa_8ch_mixer,
- alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc880_gpio3_init_verbs,
- alc883_targa_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
- .adc_nids = alc883_adc_nids_rev,
- .capsrc_nids = alc883_capsrc_nids_rev,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_4ST_8ch_modes),
- .channel_mode = alc883_4ST_8ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc883_targa_unsol_event,
- .setup = alc882_targa_setup,
- .init_hook = alc882_targa_automute,
- },
- [ALC883_ACER] = {
- .mixers = { alc883_base_mixer },
- /* On TravelMate laptops, GPIO 0 enables the internal speaker
- * and the headphone jack. Turn this on and rely on the
- * standard mute methods whenever the user wants to turn
- * these outputs off.
- */
- .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- },
- [ALC883_ACER_ASPIRE] = {
- .mixers = { alc883_acer_aspire_mixer },
- .init_verbs = { alc883_init_verbs, alc883_acer_eapd_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc883_acer_aspire_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC888_ACER_ASPIRE_4930G] = {
- .mixers = { alc888_acer_aspire_4930g_mixer,
- alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
- alc888_acer_aspire_4930g_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
- .adc_nids = alc883_adc_nids_rev,
- .capsrc_nids = alc883_capsrc_nids_rev,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
- .channel_mode = alc883_3ST_6ch_modes,
- .need_dac_fix = 1,
- .const_channel_count = 6,
- .num_mux_defs =
- ARRAY_SIZE(alc888_2_capture_sources),
- .input_mux = alc888_2_capture_sources,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc888_acer_aspire_4930g_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC888_ACER_ASPIRE_6530G] = {
- .mixers = { alc888_acer_aspire_6530_mixer },
- .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
- alc888_acer_aspire_6530g_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
- .adc_nids = alc883_adc_nids_rev,
- .capsrc_nids = alc883_capsrc_nids_rev,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .num_mux_defs =
- ARRAY_SIZE(alc888_2_capture_sources),
- .input_mux = alc888_acer_aspire_6530_sources,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc888_acer_aspire_6530g_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC888_ACER_ASPIRE_8930G] = {
- .mixers = { alc889_acer_aspire_8930g_mixer,
- alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
- alc889_acer_aspire_8930g_verbs,
- alc889_eapd_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc889_adc_nids),
- .adc_nids = alc889_adc_nids,
- .capsrc_nids = alc889_capsrc_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
- .channel_mode = alc883_3ST_6ch_modes,
- .need_dac_fix = 1,
- .const_channel_count = 6,
- .num_mux_defs =
- ARRAY_SIZE(alc889_capture_sources),
- .input_mux = alc889_capture_sources,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc889_acer_aspire_8930g_setup,
- .init_hook = alc_hp_automute,
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- .power_hook = alc_power_eapd,
-#endif
- },
- [ALC888_ACER_ASPIRE_7730G] = {
- .mixers = { alc883_3ST_6ch_mixer,
- alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
- alc888_acer_aspire_7730G_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
- .adc_nids = alc883_adc_nids_rev,
- .capsrc_nids = alc883_capsrc_nids_rev,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
- .channel_mode = alc883_3ST_6ch_modes,
- .need_dac_fix = 1,
- .const_channel_count = 6,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc888_acer_aspire_7730g_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC883_MEDION] = {
- .mixers = { alc883_fivestack_mixer,
- alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs,
- alc883_medion_eapd_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .adc_nids = alc883_adc_nids_alt,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
- .capsrc_nids = alc883_capsrc_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
- .channel_mode = alc883_sixstack_modes,
- .input_mux = &alc883_capture_source,
- },
- [ALC883_MEDION_WIM2160] = {
- .mixers = { alc883_medion_wim2160_mixer },
- .init_verbs = { alc883_init_verbs, alc883_medion_wim2160_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
- .adc_nids = alc883_adc_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc883_medion_wim2160_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC883_LAPTOP_EAPD] = {
- .mixers = { alc883_base_mixer },
- .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- },
- [ALC883_CLEVO_M540R] = {
- .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc883_clevo_m540r_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_clevo_modes),
- .channel_mode = alc883_3ST_6ch_clevo_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_capture_source,
- /* This machine has the hardware HP auto-muting, thus
- * we need no software mute via unsol event
- */
- },
- [ALC883_CLEVO_M720] = {
- .mixers = { alc883_clevo_m720_mixer },
- .init_verbs = { alc883_init_verbs, alc883_clevo_m720_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc883_clevo_m720_unsol_event,
- .setup = alc883_clevo_m720_setup,
- .init_hook = alc883_clevo_m720_init_hook,
- },
- [ALC883_LENOVO_101E_2ch] = {
- .mixers = { alc883_lenovo_101e_2ch_mixer},
- .init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .adc_nids = alc883_adc_nids_alt,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
- .capsrc_nids = alc883_capsrc_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_lenovo_101e_capture_source,
- .setup = alc883_lenovo_101e_setup,
- .unsol_event = alc_sku_unsol_event,
- .init_hook = alc_inithook,
- },
- [ALC883_LENOVO_NB0763] = {
- .mixers = { alc883_lenovo_nb0763_mixer },
- .init_verbs = { alc883_init_verbs, alc883_lenovo_nb0763_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_lenovo_nb0763_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc883_lenovo_nb0763_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC888_LENOVO_MS7195_DIG] = {
- .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc888_lenovo_ms7195_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
- .channel_mode = alc883_3ST_6ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc888_lenovo_ms7195_setup,
- .init_hook = alc_inithook,
- },
- [ALC883_HAIER_W66] = {
- .mixers = { alc883_targa_2ch_mixer},
- .init_verbs = { alc883_init_verbs, alc883_haier_w66_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc883_haier_w66_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC888_3ST_HP] = {
- .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc888_3st_hp_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc888_3st_hp_modes),
- .channel_mode = alc888_3st_hp_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc888_3st_hp_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC888_6ST_DELL] = {
- .mixers = { alc883_base_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc888_6st_dell_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
- .channel_mode = alc883_sixstack_modes,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc888_6st_dell_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC883_MITAC] = {
- .mixers = { alc883_mitac_mixer },
- .init_verbs = { alc883_init_verbs, alc883_mitac_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc883_mitac_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC883_FUJITSU_PI2515] = {
- .mixers = { alc883_2ch_fujitsu_pi2515_mixer },
- .init_verbs = { alc883_init_verbs,
- alc883_2ch_fujitsu_pi2515_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_fujitsu_pi2515_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc883_2ch_fujitsu_pi2515_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC888_FUJITSU_XA3530] = {
- .mixers = { alc888_base_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs,
- alc888_fujitsu_xa3530_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
- .adc_nids = alc883_adc_nids_rev,
- .capsrc_nids = alc883_capsrc_nids_rev,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
- .channel_mode = alc888_4ST_8ch_intel_modes,
- .num_mux_defs =
- ARRAY_SIZE(alc888_2_capture_sources),
- .input_mux = alc888_2_capture_sources,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc888_fujitsu_xa3530_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC888_LENOVO_SKY] = {
- .mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs},
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
- .channel_mode = alc883_sixstack_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_lenovo_sky_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc888_lenovo_sky_setup,
- .init_hook = alc_hp_automute,
- },
- [ALC888_ASUS_M90V] = {
- .mixers = { alc883_3ST_6ch_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc888_asus_m90v_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
- .channel_mode = alc883_3ST_6ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_fujitsu_pi2515_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc883_mode2_setup,
- .init_hook = alc_inithook,
- },
- [ALC888_ASUS_EEE1601] = {
- .mixers = { alc883_asus_eee1601_mixer },
- .cap_mixer = alc883_asus_eee1601_cap_mixer,
- .init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .need_dac_fix = 1,
- .input_mux = &alc883_asus_eee1601_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .init_hook = alc883_eee1601_inithook,
- },
- [ALC1200_ASUS_P5Q] = {
- .mixers = { alc883_base_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC1200_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .slave_dig_outs = alc1200_slave_dig_outs,
- .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
- .channel_mode = alc883_sixstack_modes,
- .input_mux = &alc883_capture_source,
- },
- [ALC889A_MB31] = {
- .mixers = { alc889A_mb31_mixer, alc883_chmode_mixer},
- .init_verbs = { alc883_init_verbs, alc889A_mb31_verbs,
- alc880_gpio1_init_verbs },
- .adc_nids = alc883_adc_nids,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
- .capsrc_nids = alc883_capsrc_nids,
- .dac_nids = alc883_dac_nids,
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .channel_mode = alc889A_mb31_6ch_modes,
- .num_channel_mode = ARRAY_SIZE(alc889A_mb31_6ch_modes),
- .input_mux = &alc889A_mb31_capture_source,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .unsol_event = alc889A_mb31_unsol_event,
- .init_hook = alc889A_mb31_automute,
- },
- [ALC883_SONY_VAIO_TT] = {
- .mixers = { alc883_vaiott_mixer },
- .init_verbs = { alc883_init_verbs, alc883_vaiott_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
- .channel_mode = alc883_3ST_2ch_modes,
- .input_mux = &alc883_capture_source,
- .unsol_event = alc_sku_unsol_event,
- .setup = alc883_vaiott_setup,
- .init_hook = alc_hp_automute,
- },
-};
-
-
diff --git a/sound/pci/hda/alc_quirks.c b/sound/pci/hda/alc_quirks.c
deleted file mode 100644
index 2be1129cf458..000000000000
--- a/sound/pci/hda/alc_quirks.c
+++ /dev/null
@@ -1,467 +0,0 @@
-/*
- * Common codes for Realtek codec quirks
- * included by patch_realtek.c
- */
-
-/*
- * configuration template - to be copied to the spec instance
- */
-struct alc_config_preset {
- const struct snd_kcontrol_new *mixers[5]; /* should be identical size
- * with spec
- */
- const struct snd_kcontrol_new *cap_mixer; /* capture mixer */
- const struct hda_verb *init_verbs[5];
- unsigned int num_dacs;
- const hda_nid_t *dac_nids;
- hda_nid_t dig_out_nid; /* optional */
- hda_nid_t hp_nid; /* optional */
- const hda_nid_t *slave_dig_outs;
- unsigned int num_adc_nids;
- const hda_nid_t *adc_nids;
- const hda_nid_t *capsrc_nids;
- hda_nid_t dig_in_nid;
- unsigned int num_channel_mode;
- const struct hda_channel_mode *channel_mode;
- int need_dac_fix;
- int const_channel_count;
- unsigned int num_mux_defs;
- const struct hda_input_mux *input_mux;
- void (*unsol_event)(struct hda_codec *, unsigned int);
- void (*setup)(struct hda_codec *);
- void (*init_hook)(struct hda_codec *);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- const struct hda_amp_list *loopbacks;
- void (*power_hook)(struct hda_codec *codec);
-#endif
-};
-
-/*
- * channel mode setting
- */
-static int alc_ch_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
- spec->num_channel_mode);
-}
-
-static int alc_ch_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
- spec->num_channel_mode,
- spec->ext_channel_count);
-}
-
-static int alc_ch_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
- spec->num_channel_mode,
- &spec->ext_channel_count);
- if (err >= 0 && !spec->const_channel_count) {
- spec->multiout.max_channels = spec->ext_channel_count;
- if (spec->need_dac_fix)
- spec->multiout.num_dacs = spec->multiout.max_channels / 2;
- }
- return err;
-}
-
-/*
- * Control the mode of pin widget settings via the mixer. "pc" is used
- * instead of "%" to avoid consequences of accidentally treating the % as
- * being part of a format specifier. Maximum allowed length of a value is
- * 63 characters plus NULL terminator.
- *
- * Note: some retasking pin complexes seem to ignore requests for input
- * states other than HiZ (eg: PIN_VREFxx) and revert to HiZ if any of these
- * are requested. Therefore order this list so that this behaviour will not
- * cause problems when mixer clients move through the enum sequentially.
- * NIDs 0x0f and 0x10 have been observed to have this behaviour as of
- * March 2006.
- */
-static const char * const alc_pin_mode_names[] = {
- "Mic 50pc bias", "Mic 80pc bias",
- "Line in", "Line out", "Headphone out",
-};
-static const unsigned char alc_pin_mode_values[] = {
- PIN_VREF50, PIN_VREF80, PIN_IN, PIN_OUT, PIN_HP,
-};
-/* The control can present all 5 options, or it can limit the options based
- * in the pin being assumed to be exclusively an input or an output pin. In
- * addition, "input" pins may or may not process the mic bias option
- * depending on actual widget capability (NIDs 0x0f and 0x10 don't seem to
- * accept requests for bias as of chip versions up to March 2006) and/or
- * wiring in the computer.
- */
-#define ALC_PIN_DIR_IN 0x00
-#define ALC_PIN_DIR_OUT 0x01
-#define ALC_PIN_DIR_INOUT 0x02
-#define ALC_PIN_DIR_IN_NOMICBIAS 0x03
-#define ALC_PIN_DIR_INOUT_NOMICBIAS 0x04
-
-/* Info about the pin modes supported by the different pin direction modes.
- * For each direction the minimum and maximum values are given.
- */
-static const signed char alc_pin_mode_dir_info[5][2] = {
- { 0, 2 }, /* ALC_PIN_DIR_IN */
- { 3, 4 }, /* ALC_PIN_DIR_OUT */
- { 0, 4 }, /* ALC_PIN_DIR_INOUT */
- { 2, 2 }, /* ALC_PIN_DIR_IN_NOMICBIAS */
- { 2, 4 }, /* ALC_PIN_DIR_INOUT_NOMICBIAS */
-};
-#define alc_pin_mode_min(_dir) (alc_pin_mode_dir_info[_dir][0])
-#define alc_pin_mode_max(_dir) (alc_pin_mode_dir_info[_dir][1])
-#define alc_pin_mode_n_items(_dir) \
- (alc_pin_mode_max(_dir)-alc_pin_mode_min(_dir)+1)
-
-static int alc_pin_mode_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- unsigned int item_num = uinfo->value.enumerated.item;
- unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
-
- uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
- uinfo->count = 1;
- uinfo->value.enumerated.items = alc_pin_mode_n_items(dir);
-
- if (item_num<alc_pin_mode_min(dir) || item_num>alc_pin_mode_max(dir))
- item_num = alc_pin_mode_min(dir);
- strcpy(uinfo->value.enumerated.name, alc_pin_mode_names[item_num]);
- return 0;
-}
-
-static int alc_pin_mode_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- unsigned int i;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
- long *valp = ucontrol->value.integer.value;
- unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL,
- 0x00);
-
- /* Find enumerated value for current pinctl setting */
- i = alc_pin_mode_min(dir);
- while (i <= alc_pin_mode_max(dir) && alc_pin_mode_values[i] != pinctl)
- i++;
- *valp = i <= alc_pin_mode_max(dir) ? i: alc_pin_mode_min(dir);
- return 0;
-}
-
-static int alc_pin_mode_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- signed int change;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char dir = (kcontrol->private_value >> 16) & 0xff;
- long val = *ucontrol->value.integer.value;
- unsigned int pinctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL,
- 0x00);
-
- if (val < alc_pin_mode_min(dir) || val > alc_pin_mode_max(dir))
- val = alc_pin_mode_min(dir);
-
- change = pinctl != alc_pin_mode_values[val];
- if (change) {
- /* Set pin mode to that requested */
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- alc_pin_mode_values[val]);
-
- /* Also enable the retasking pin's input/output as required
- * for the requested pin mode. Enum values of 2 or less are
- * input modes.
- *
- * Dynamically switching the input/output buffers probably
- * reduces noise slightly (particularly on input) so we'll
- * do it. However, having both input and output buffers
- * enabled simultaneously doesn't seem to be problematic if
- * this turns out to be necessary in the future.
- */
- if (val <= 2) {
- snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
- HDA_AMP_MUTE, 0);
- } else {
- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, 0,
- HDA_AMP_MUTE, HDA_AMP_MUTE);
- snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, 0);
- }
- }
- return change;
-}
-
-#define ALC_PIN_MODE(xname, nid, dir) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_pin_mode_info, \
- .get = alc_pin_mode_get, \
- .put = alc_pin_mode_put, \
- .private_value = nid | (dir<<16) }
-
-/* A switch control for ALC260 GPIO pins. Multiple GPIOs can be ganged
- * together using a mask with more than one bit set. This control is
- * currently used only by the ALC260 test model. At this stage they are not
- * needed for any "production" models.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_gpio_data_info snd_ctl_boolean_mono_info
-
-static int alc_gpio_data_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long *valp = ucontrol->value.integer.value;
- unsigned int val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_DATA, 0x00);
-
- *valp = (val & mask) != 0;
- return 0;
-}
-static int alc_gpio_data_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- signed int change;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long val = *ucontrol->value.integer.value;
- unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_GPIO_DATA,
- 0x00);
-
- /* Set/unset the masked GPIO bit(s) as needed */
- change = (val == 0 ? 0 : mask) != (gpio_data & mask);
- if (val == 0)
- gpio_data &= ~mask;
- else
- gpio_data |= mask;
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_GPIO_DATA, gpio_data);
-
- return change;
-}
-#define ALC_GPIO_DATA_SWITCH(xname, nid, mask) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_gpio_data_info, \
- .get = alc_gpio_data_get, \
- .put = alc_gpio_data_put, \
- .private_value = nid | (mask<<16) }
-#endif /* CONFIG_SND_DEBUG */
-
-/* A switch control to allow the enabling of the digital IO pins on the
- * ALC260. This is incredibly simplistic; the intention of this control is
- * to provide something in the test model allowing digital outputs to be
- * identified if present. If models are found which can utilise these
- * outputs a more complete mixer control can be devised for those models if
- * necessary.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_spdif_ctrl_info snd_ctl_boolean_mono_info
-
-static int alc_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long *valp = ucontrol->value.integer.value;
- unsigned int val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_DIGI_CONVERT_1, 0x00);
-
- *valp = (val & mask) != 0;
- return 0;
-}
-static int alc_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- signed int change;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long val = *ucontrol->value.integer.value;
- unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_DIGI_CONVERT_1,
- 0x00);
-
- /* Set/unset the masked control bit(s) as needed */
- change = (val == 0 ? 0 : mask) != (ctrl_data & mask);
- if (val==0)
- ctrl_data &= ~mask;
- else
- ctrl_data |= mask;
- snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
- ctrl_data);
-
- return change;
-}
-#define ALC_SPDIF_CTRL_SWITCH(xname, nid, mask) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_spdif_ctrl_info, \
- .get = alc_spdif_ctrl_get, \
- .put = alc_spdif_ctrl_put, \
- .private_value = nid | (mask<<16) }
-#endif /* CONFIG_SND_DEBUG */
-
-/* A switch control to allow the enabling EAPD digital outputs on the ALC26x.
- * Again, this is only used in the ALC26x test models to help identify when
- * the EAPD line must be asserted for features to work.
- */
-#ifdef CONFIG_SND_DEBUG
-#define alc_eapd_ctrl_info snd_ctl_boolean_mono_info
-
-static int alc_eapd_ctrl_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long *valp = ucontrol->value.integer.value;
- unsigned int val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_EAPD_BTLENABLE, 0x00);
-
- *valp = (val & mask) != 0;
- return 0;
-}
-
-static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- int change;
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- hda_nid_t nid = kcontrol->private_value & 0xffff;
- unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
- long val = *ucontrol->value.integer.value;
- unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_EAPD_BTLENABLE,
- 0x00);
-
- /* Set/unset the masked control bit(s) as needed */
- change = (!val ? 0 : mask) != (ctrl_data & mask);
- if (!val)
- ctrl_data &= ~mask;
- else
- ctrl_data |= mask;
- snd_hda_codec_write_cache(codec, nid, 0, AC_VERB_SET_EAPD_BTLENABLE,
- ctrl_data);
-
- return change;
-}
-
-#define ALC_EAPD_CTRL_SWITCH(xname, nid, mask) \
- { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
- .subdevice = HDA_SUBDEV_NID_FLAG | nid, \
- .info = alc_eapd_ctrl_info, \
- .get = alc_eapd_ctrl_get, \
- .put = alc_eapd_ctrl_put, \
- .private_value = nid | (mask<<16) }
-#endif /* CONFIG_SND_DEBUG */
-
-static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
-
- if (!cfg->line_outs) {
- while (cfg->line_outs < AUTO_CFG_MAX_OUTS &&
- cfg->line_out_pins[cfg->line_outs])
- cfg->line_outs++;
- }
- if (!cfg->speaker_outs) {
- while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS &&
- cfg->speaker_pins[cfg->speaker_outs])
- cfg->speaker_outs++;
- }
- if (!cfg->hp_outs) {
- while (cfg->hp_outs < AUTO_CFG_MAX_OUTS &&
- cfg->hp_pins[cfg->hp_outs])
- cfg->hp_outs++;
- }
-}
-
-/*
- * set up from the preset table
- */
-static void setup_preset(struct hda_codec *codec,
- const struct alc_config_preset *preset)
-{
- struct alc_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
- add_mixer(spec, preset->mixers[i]);
- spec->cap_mixer = preset->cap_mixer;
- for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
- i++)
- add_verb(spec, preset->init_verbs[i]);
-
- spec->channel_mode = preset->channel_mode;
- spec->num_channel_mode = preset->num_channel_mode;
- spec->need_dac_fix = preset->need_dac_fix;
- spec->const_channel_count = preset->const_channel_count;
-
- if (preset->const_channel_count)
- spec->multiout.max_channels = preset->const_channel_count;
- else
- spec->multiout.max_channels = spec->channel_mode[0].channels;
- spec->ext_channel_count = spec->channel_mode[0].channels;
-
- spec->multiout.num_dacs = preset->num_dacs;
- spec->multiout.dac_nids = preset->dac_nids;
- spec->multiout.dig_out_nid = preset->dig_out_nid;
- spec->multiout.slave_dig_outs = preset->slave_dig_outs;
- spec->multiout.hp_nid = preset->hp_nid;
-
- spec->num_mux_defs = preset->num_mux_defs;
- if (!spec->num_mux_defs)
- spec->num_mux_defs = 1;
- spec->input_mux = preset->input_mux;
-
- spec->num_adc_nids = preset->num_adc_nids;
- spec->adc_nids = preset->adc_nids;
- spec->capsrc_nids = preset->capsrc_nids;
- spec->dig_in_nid = preset->dig_in_nid;
-
- spec->unsol_event = preset->unsol_event;
- spec->init_hook = preset->init_hook;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- spec->power_hook = preset->power_hook;
- spec->loopback.amplist = preset->loopbacks;
-#endif
-
- if (preset->setup)
- preset->setup(codec);
-
- alc_fixup_autocfg_pin_nums(codec);
-}
-
-
-/* auto-toggle front mic */
-static void alc88x_simple_mic_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- present = snd_hda_jack_detect(codec, 0x18);
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x0b, HDA_INPUT, 1, HDA_AMP_MUTE, bits);
-}
-
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index 29714c818b53..60738e52b8f9 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -23,6 +23,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
+#include <linux/export.h>
#include <sound/core.h>
#include "hda_beep.h"
#include "hda_local.h"
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 3e7850c238c3..7a8fcc4c15f8 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -19,11 +19,13 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
+#include <linux/mm.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/mutex.h>
+#include <linux/module.h>
#include <sound/core.h>
#include "hda_codec.h"
#include <sound/asoundef.h>
@@ -32,8 +34,12 @@
#include <sound/jack.h>
#include "hda_local.h"
#include "hda_beep.h"
+#include "hda_jack.h"
#include <sound/hda_hwdep.h>
+#define CREATE_TRACE_POINTS
+#include "hda_trace.h"
+
/*
* vendor / preset table
*/
@@ -208,15 +214,19 @@ static int codec_exec_verb(struct hda_codec *codec, unsigned int cmd,
again:
snd_hda_power_up(codec);
mutex_lock(&bus->cmd_mutex);
+ trace_hda_send_cmd(codec, cmd);
err = bus->ops.command(bus, cmd);
- if (!err && res)
+ if (!err && res) {
*res = bus->ops.get_response(bus, codec->addr);
+ trace_hda_get_response(codec, *res);
+ }
mutex_unlock(&bus->cmd_mutex);
snd_hda_power_down(codec);
if (res && *res == -1 && bus->rirb_error) {
if (bus->response_reset) {
snd_printd("hda_codec: resetting BUS due to "
"fatal communication error\n");
+ trace_hda_bus_reset(bus);
bus->ops.bus_reset(bus);
}
goto again;
@@ -579,9 +589,13 @@ int snd_hda_get_conn_index(struct hda_codec *codec, hda_nid_t mux,
return -1;
}
recursive++;
- for (i = 0; i < nums; i++)
+ for (i = 0; i < nums; i++) {
+ unsigned int type = get_wcaps_type(get_wcaps(codec, conn[i]));
+ if (type == AC_WID_PIN || type == AC_WID_AUD_OUT)
+ continue;
if (snd_hda_get_conn_index(codec, conn[i], nid, recursive) >= 0)
return i;
+ }
return -1;
}
EXPORT_SYMBOL_HDA(snd_hda_get_conn_index);
@@ -603,6 +617,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
struct hda_bus_unsolicited *unsol;
unsigned int wp;
+ trace_hda_unsol_event(bus, res, res_ex);
unsol = bus->unsol;
if (!unsol)
return 0;
@@ -1433,7 +1448,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
for (i = 0; i < c->cvt_setups.used; i++) {
p = snd_array_elem(&c->cvt_setups, i);
if (!p->active && p->stream_tag == stream_tag &&
- get_wcaps_type(get_wcaps(codec, p->nid)) == type)
+ get_wcaps_type(get_wcaps(c, p->nid)) == type)
p->dirty = 1;
}
}
@@ -1479,8 +1494,11 @@ static void really_cleanup_stream(struct hda_codec *codec,
struct hda_cvt_setup *q)
{
hda_nid_t nid = q->nid;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
+ if (q->stream_tag || q->channel_id)
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_CHANNEL_STREAMID, 0);
+ if (q->format_id)
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0
+);
memset(q, 0, sizeof(*q));
q->nid = nid;
}
@@ -1685,41 +1703,27 @@ u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid)
EXPORT_SYMBOL_HDA(snd_hda_query_pin_caps);
/**
- * snd_hda_pin_sense - execute pin sense measurement
- * @codec: the CODEC to sense
- * @nid: the pin NID to sense
+ * snd_hda_override_pin_caps - Override the pin capabilities
+ * @codec: the CODEC
+ * @nid: the NID to override
+ * @caps: the capability bits to set
*
- * Execute necessary pin sense measurement and return its Presence Detect,
- * Impedance, ELD Valid etc. status bits.
- */
-u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
-{
- u32 pincap;
-
- if (!codec->no_trigger_sense) {
- pincap = snd_hda_query_pin_caps(codec, nid);
- if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
- snd_hda_codec_read(codec, nid, 0,
- AC_VERB_SET_PIN_SENSE, 0);
- }
- return snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_SENSE, 0);
-}
-EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
-
-/**
- * snd_hda_jack_detect - query pin Presence Detect status
- * @codec: the CODEC to sense
- * @nid: the pin NID to sense
+ * Override the cached PIN capabilitiy bits value by the given one.
*
- * Query and return the pin's Presence Detect status.
+ * Returns zero if successful or a negative error code.
*/
-int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
+int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int caps)
{
- u32 sense = snd_hda_pin_sense(codec, nid);
- return !!(sense & AC_PINSENSE_PRESENCE);
+ struct hda_amp_info *info;
+ info = get_alloc_amp_hash(codec, HDA_HASH_PINCAP_KEY(nid));
+ if (!info)
+ return -ENOMEM;
+ info->amp_caps = caps;
+ info->head.val |= INFO_AMP_CAPS;
+ return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
+EXPORT_SYMBOL_HDA(snd_hda_override_pin_caps);
/*
* read the current volume to info
@@ -1756,7 +1760,11 @@ static void put_vol_mute(struct hda_codec *codec, struct hda_amp_info *info,
parm = ch ? AC_AMP_SET_RIGHT : AC_AMP_SET_LEFT;
parm |= direction == HDA_OUTPUT ? AC_AMP_SET_OUTPUT : AC_AMP_SET_INPUT;
parm |= index << AC_AMP_SET_INDEX_SHIFT;
- parm |= val;
+ if ((val & HDA_AMP_MUTE) && !(info->amp_caps & AC_AMPCAP_MUTE) &&
+ (info->amp_caps & AC_AMPCAP_MIN_MUTE))
+ ; /* set the zero value as a fake mute */
+ else
+ parm |= val;
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, parm);
info->vol[ch] = val;
}
@@ -2023,7 +2031,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT);
val1 += ofs;
val1 = ((int)val1) * ((int)val2);
- if (min_mute)
+ if (min_mute || (caps & AC_AMPCAP_MIN_MUTE))
val2 |= TLV_DB_SCALE_MUTE;
if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv))
return -EFAULT;
@@ -2269,6 +2277,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
}
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
+ snd_hda_jack_tbl_clear(codec);
codec->proc_widget_hook = NULL;
codec->spec = NULL;
free_hda_cache(&codec->amp_cache);
@@ -2292,12 +2301,105 @@ int snd_hda_codec_reset(struct hda_codec *codec)
return 0;
}
+typedef int (*map_slave_func_t)(void *, struct snd_kcontrol *);
+
+/* apply the function to all matching slave ctls in the mixer list */
+static int map_slaves(struct hda_codec *codec, const char * const *slaves,
+ const char *suffix, map_slave_func_t func, void *data)
+{
+ struct hda_nid_item *items;
+ const char * const *s;
+ int i, err;
+
+ items = codec->mixers.list;
+ for (i = 0; i < codec->mixers.used; i++) {
+ struct snd_kcontrol *sctl = items[i].kctl;
+ if (!sctl || !sctl->id.name ||
+ sctl->id.iface != SNDRV_CTL_ELEM_IFACE_MIXER)
+ continue;
+ for (s = slaves; *s; s++) {
+ char tmpname[sizeof(sctl->id.name)];
+ const char *name = *s;
+ if (suffix) {
+ snprintf(tmpname, sizeof(tmpname), "%s %s",
+ name, suffix);
+ name = tmpname;
+ }
+ if (!strcmp(sctl->id.name, name)) {
+ err = func(data, sctl);
+ if (err)
+ return err;
+ break;
+ }
+ }
+ }
+ return 0;
+}
+
+static int check_slave_present(void *data, struct snd_kcontrol *sctl)
+{
+ return 1;
+}
+
+/* guess the value corresponding to 0dB */
+static int get_kctl_0dB_offset(struct snd_kcontrol *kctl)
+{
+ int _tlv[4];
+ const int *tlv = NULL;
+ int val = -1;
+
+ if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK) {
+ /* FIXME: set_fs() hack for obtaining user-space TLV data */
+ mm_segment_t fs = get_fs();
+ set_fs(get_ds());
+ if (!kctl->tlv.c(kctl, 0, sizeof(_tlv), _tlv))
+ tlv = _tlv;
+ set_fs(fs);
+ } else if (kctl->vd[0].access & SNDRV_CTL_ELEM_ACCESS_TLV_READ)
+ tlv = kctl->tlv.p;
+ if (tlv && tlv[0] == SNDRV_CTL_TLVT_DB_SCALE)
+ val = -tlv[2] / tlv[3];
+ return val;
+}
+
+/* call kctl->put with the given value(s) */
+static int put_kctl_with_value(struct snd_kcontrol *kctl, int val)
+{
+ struct snd_ctl_elem_value *ucontrol;
+ ucontrol = kzalloc(sizeof(*ucontrol), GFP_KERNEL);
+ if (!ucontrol)
+ return -ENOMEM;
+ ucontrol->value.integer.value[0] = val;
+ ucontrol->value.integer.value[1] = val;
+ kctl->put(kctl, ucontrol);
+ kfree(ucontrol);
+ return 0;
+}
+
+/* initialize the slave volume with 0dB */
+static int init_slave_0dB(void *data, struct snd_kcontrol *slave)
+{
+ int offset = get_kctl_0dB_offset(slave);
+ if (offset > 0)
+ put_kctl_with_value(slave, offset);
+ return 0;
+}
+
+/* unmute the slave */
+static int init_slave_unmute(void *data, struct snd_kcontrol *slave)
+{
+ return put_kctl_with_value(slave, 1);
+}
+
/**
* snd_hda_add_vmaster - create a virtual master control and add slaves
* @codec: HD-audio codec
* @name: vmaster control name
* @tlv: TLV data (optional)
* @slaves: slave control names (optional)
+ * @suffix: suffix string to each slave name (optional)
+ * @init_slave_vol: initialize slaves to unmute/0dB
+ * @ctl_ret: store the vmaster kcontrol in return
*
* Create a virtual master control with the given name. The TLV data
* must be either NULL or a valid data.
@@ -2308,16 +2410,19 @@ int snd_hda_codec_reset(struct hda_codec *codec)
*
* This function returns zero if successful or a negative error code.
*/
-int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
- unsigned int *tlv, const char * const *slaves)
+int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
+ unsigned int *tlv, const char * const *slaves,
+ const char *suffix, bool init_slave_vol,
+ struct snd_kcontrol **ctl_ret)
{
struct snd_kcontrol *kctl;
- const char * const *s;
int err;
- for (s = slaves; *s && !snd_hda_find_mixer_ctl(codec, *s); s++)
- ;
- if (!*s) {
+ if (ctl_ret)
+ *ctl_ret = NULL;
+
+ err = map_slaves(codec, slaves, suffix, check_slave_present, NULL);
+ if (err != 1) {
snd_printdd("No slave found for %s\n", name);
return 0;
}
@@ -2328,26 +2433,119 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
if (err < 0)
return err;
- for (s = slaves; *s; s++) {
- struct snd_kcontrol *sctl;
- int i = 0;
- for (;;) {
- sctl = _snd_hda_find_mixer_ctl(codec, *s, i);
- if (!sctl) {
- if (!i)
- snd_printdd("Cannot find slave %s, "
- "skipped\n", *s);
- break;
- }
- err = snd_ctl_add_slave(kctl, sctl);
- if (err < 0)
- return err;
- i++;
- }
- }
+ err = map_slaves(codec, slaves, suffix,
+ (map_slave_func_t)snd_ctl_add_slave, kctl);
+ if (err < 0)
+ return err;
+
+ /* init with master mute & zero volume */
+ put_kctl_with_value(kctl, 0);
+ if (init_slave_vol)
+ map_slaves(codec, slaves, suffix,
+ tlv ? init_slave_0dB : init_slave_unmute, kctl);
+
+ if (ctl_ret)
+ *ctl_ret = kctl;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
+EXPORT_SYMBOL_HDA(__snd_hda_add_vmaster);
+
+/*
+ * mute-LED control using vmaster
+ */
+static int vmaster_mute_mode_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char * const texts[] = {
+ "Off", "On", "Follow Master"
+ };
+ unsigned int index;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 3;
+ index = uinfo->value.enumerated.item;
+ if (index >= 3)
+ index = 2;
+ strcpy(uinfo->value.enumerated.name, texts[index]);
+ return 0;
+}
+
+static int vmaster_mute_mode_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
+ ucontrol->value.enumerated.item[0] = hook->mute_mode;
+ return 0;
+}
+
+static int vmaster_mute_mode_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_vmaster_mute_hook *hook = snd_kcontrol_chip(kcontrol);
+ unsigned int old_mode = hook->mute_mode;
+
+ hook->mute_mode = ucontrol->value.enumerated.item[0];
+ if (hook->mute_mode > HDA_VMUTE_FOLLOW_MASTER)
+ hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
+ if (old_mode == hook->mute_mode)
+ return 0;
+ snd_hda_sync_vmaster_hook(hook);
+ return 1;
+}
+
+static struct snd_kcontrol_new vmaster_mute_mode = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Mute-LED Mode",
+ .info = vmaster_mute_mode_info,
+ .get = vmaster_mute_mode_get,
+ .put = vmaster_mute_mode_put,
+};
+
+/*
+ * Add a mute-LED hook with the given vmaster switch kctl
+ * "Mute-LED Mode" control is automatically created and associated with
+ * the given hook.
+ */
+int snd_hda_add_vmaster_hook(struct hda_codec *codec,
+ struct hda_vmaster_mute_hook *hook,
+ bool expose_enum_ctl)
+{
+ struct snd_kcontrol *kctl;
+
+ if (!hook->hook || !hook->sw_kctl)
+ return 0;
+ snd_ctl_add_vmaster_hook(hook->sw_kctl, hook->hook, codec);
+ hook->codec = codec;
+ hook->mute_mode = HDA_VMUTE_FOLLOW_MASTER;
+ if (!expose_enum_ctl)
+ return 0;
+ kctl = snd_ctl_new1(&vmaster_mute_mode, hook);
+ if (!kctl)
+ return -ENOMEM;
+ return snd_hda_ctl_add(codec, 0, kctl);
+}
+EXPORT_SYMBOL_HDA(snd_hda_add_vmaster_hook);
+
+/*
+ * Call the hook with the current value for synchronization
+ * Should be called in init callback
+ */
+void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook)
+{
+ if (!hook->hook || !hook->codec)
+ return;
+ switch (hook->mute_mode) {
+ case HDA_VMUTE_FOLLOW_MASTER:
+ snd_ctl_sync_vmaster_hook(hook->sw_kctl);
+ break;
+ default:
+ hook->hook(hook->codec, hook->mute_mode);
+ break;
+ }
+}
+EXPORT_SYMBOL_HDA(snd_hda_sync_vmaster_hook);
+
/**
* snd_hda_mixer_amp_switch_info - Info callback for a standard AMP mixer switch
@@ -3307,6 +3505,7 @@ static void hda_call_codec_resume(struct hda_codec *codec)
restore_pincfgs(codec); /* restore all current pin configs */
restore_shutup_pins(codec);
hda_exec_init_verbs(codec);
+ snd_hda_jack_set_dirty_all(codec);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
else {
@@ -3793,6 +3992,12 @@ static int get_empty_pcm_device(struct hda_bus *bus, int type)
if (!test_and_set_bit(audio_idx[type][i], bus->pcm_dev_bits))
return audio_idx[type][i];
+ /* non-fixed slots starting from 10 */
+ for (i = 10; i < 32; i++) {
+ if (!test_and_set_bit(i, bus->pcm_dev_bits))
+ return i;
+ }
+
snd_printk(KERN_WARNING "Too many %s devices\n",
snd_hda_pcm_type_name[type]);
return -EAGAIN;
@@ -3989,9 +4194,9 @@ int snd_hda_check_board_codec_sid_config(struct hda_codec *codec,
/* Search for codec ID */
for (q = tbl; q->subvendor; q++) {
- unsigned long vendorid = (q->subdevice) | (q->subvendor << 16);
-
- if (vendorid == codec->subsystem_id)
+ unsigned int mask = 0xffff0000 | q->subdevice_mask;
+ unsigned int id = (q->subdevice | (q->subvendor << 16)) & mask;
+ if ((codec->subsystem_id & mask) == id)
break;
}
@@ -4083,6 +4288,7 @@ static void hda_power_work(struct work_struct *work)
return;
}
+ trace_hda_power_down(codec);
hda_call_codec_suspend(codec);
if (bus->ops.pm_notify)
bus->ops.pm_notify(bus);
@@ -4121,6 +4327,7 @@ void snd_hda_power_up(struct hda_codec *codec)
if (codec->power_on || codec->power_transition)
return;
+ trace_hda_power_up(codec);
snd_hda_update_power_acct(codec);
codec->power_on = 1;
codec->power_jiffies = jiffies;
@@ -4533,6 +4740,11 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
snd_hda_codec_setup_stream(codec, mout->hp_nid, stream_tag,
0, format);
/* extra outputs copied from front */
+ for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++)
+ if (!mout->no_share_stream && mout->hp_out_nid[i])
+ snd_hda_codec_setup_stream(codec,
+ mout->hp_out_nid[i],
+ stream_tag, 0, format);
for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
if (!mout->no_share_stream && mout->extra_out_nid[i])
snd_hda_codec_setup_stream(codec,
@@ -4565,6 +4777,10 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
snd_hda_codec_cleanup_stream(codec, nids[i]);
if (mout->hp_nid)
snd_hda_codec_cleanup_stream(codec, mout->hp_nid);
+ for (i = 0; i < ARRAY_SIZE(mout->hp_out_nid); i++)
+ if (mout->hp_out_nid[i])
+ snd_hda_codec_cleanup_stream(codec,
+ mout->hp_out_nid[i]);
for (i = 0; i < ARRAY_SIZE(mout->extra_out_nid); i++)
if (mout->extra_out_nid[i])
snd_hda_codec_cleanup_stream(codec,
@@ -4645,6 +4861,27 @@ static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
}
}
+/* Reorder the surround channels
+ * ALSA sequence is front/surr/clfe/side
+ * HDA sequence is:
+ * 4-ch: front/surr => OK as it is
+ * 6-ch: front/clfe/surr
+ * 8-ch: front/clfe/rear/side|fc
+ */
+static void reorder_outputs(unsigned int nums, hda_nid_t *pins)
+{
+ hda_nid_t nid;
+
+ switch (nums) {
+ case 3:
+ case 4:
+ nid = pins[1];
+ pins[1] = pins[2];
+ pins[2] = nid;
+ break;
+ }
+}
+
/*
* Parse all pin widgets and store the useful pin nids to cfg
*
@@ -4662,12 +4899,13 @@ static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg)
* The digital input/output pins are assigned to dig_in_pin and dig_out_pin,
* respectively.
*/
-int snd_hda_parse_pin_def_config(struct hda_codec *codec,
- struct auto_pin_cfg *cfg,
- const hda_nid_t *ignore_nids)
+int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
+ struct auto_pin_cfg *cfg,
+ const hda_nid_t *ignore_nids,
+ unsigned int cond_flags)
{
hda_nid_t nid, end_nid;
- short seq, assoc_line_out, assoc_speaker;
+ short seq, assoc_line_out;
short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)];
short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)];
short sequences_hp[ARRAY_SIZE(cfg->hp_pins)];
@@ -4678,8 +4916,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
memset(sequences_line_out, 0, sizeof(sequences_line_out));
memset(sequences_speaker, 0, sizeof(sequences_speaker));
memset(sequences_hp, 0, sizeof(sequences_hp));
- assoc_line_out = assoc_speaker = 0;
+ assoc_line_out = 0;
+ codec->ignore_misc_bit = true;
end_nid = codec->start_nid + codec->num_nodes;
for (nid = codec->start_nid; nid < end_nid; nid++) {
unsigned int wid_caps = get_wcaps(codec, nid);
@@ -4695,6 +4934,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
continue;
def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ if (!(get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
+ AC_DEFCFG_MISC_NO_PRESENCE))
+ codec->ignore_misc_bit = false;
conn = get_defcfg_connect(def_conf);
if (conn == AC_JACK_PORT_NONE)
continue;
@@ -4730,16 +4972,10 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
case AC_JACK_SPEAKER:
seq = get_defcfg_sequence(def_conf);
assoc = get_defcfg_association(def_conf);
- if (!assoc)
- continue;
- if (!assoc_speaker)
- assoc_speaker = assoc;
- else if (assoc_speaker != assoc)
- continue;
if (cfg->speaker_outs >= ARRAY_SIZE(cfg->speaker_pins))
continue;
cfg->speaker_pins[cfg->speaker_outs] = nid;
- sequences_speaker[cfg->speaker_outs] = seq;
+ sequences_speaker[cfg->speaker_outs] = (assoc << 4) | seq;
cfg->speaker_outs++;
break;
case AC_JACK_HP_OUT:
@@ -4788,7 +5024,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
* If no line-out is defined but multiple HPs are found,
* some of them might be the real line-outs.
*/
- if (!cfg->line_outs && cfg->hp_outs > 1) {
+ if (!cfg->line_outs && cfg->hp_outs > 1 &&
+ !(cond_flags & HDA_PINCFG_NO_HP_FIXUP)) {
int i = 0;
while (i < cfg->hp_outs) {
/* The real HPs should have the sequence 0x0f */
@@ -4825,7 +5062,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
* FIX-UP: if no line-outs are detected, try to use speaker or HP pin
* as a primary output
*/
- if (!cfg->line_outs) {
+ if (!cfg->line_outs &&
+ !(cond_flags & HDA_PINCFG_NO_LO_FIXUP)) {
if (cfg->speaker_outs) {
cfg->line_outs = cfg->speaker_outs;
memcpy(cfg->line_out_pins, cfg->speaker_pins,
@@ -4843,21 +5081,9 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
}
}
- /* Reorder the surround channels
- * ALSA sequence is front/surr/clfe/side
- * HDA sequence is:
- * 4-ch: front/surr => OK as it is
- * 6-ch: front/clfe/surr
- * 8-ch: front/clfe/rear/side|fc
- */
- switch (cfg->line_outs) {
- case 3:
- case 4:
- nid = cfg->line_out_pins[1];
- cfg->line_out_pins[1] = cfg->line_out_pins[2];
- cfg->line_out_pins[2] = nid;
- break;
- }
+ reorder_outputs(cfg->line_outs, cfg->line_out_pins);
+ reorder_outputs(cfg->hp_outs, cfg->hp_pins);
+ reorder_outputs(cfg->speaker_outs, cfg->speaker_pins);
sort_autocfg_input_pins(cfg);
@@ -4895,7 +5121,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
+EXPORT_SYMBOL_HDA(snd_hda_parse_pin_defcfg);
int snd_hda_get_input_pin_attr(unsigned int def_conf)
{
@@ -4926,8 +5152,8 @@ EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr);
* "Rear", "Internal".
*/
-const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
- int check_location)
+static const char *hda_get_input_pin_label(struct hda_codec *codec,
+ hda_nid_t pin, bool check_location)
{
unsigned int def_conf;
static const char * const mic_names[] = {
@@ -4966,7 +5192,6 @@ const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
return "Misc";
}
}
-EXPORT_SYMBOL_HDA(hda_get_input_pin_label);
/* Check whether the location prefix needs to be added to the label.
* If all mic-jacks are in the same location (e.g. rear panel), we don't
@@ -5023,6 +5248,149 @@ const char *hda_get_autocfg_input_label(struct hda_codec *codec,
}
EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label);
+/* return the position of NID in the list, or -1 if not found */
+static int find_idx_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
+{
+ int i;
+ for (i = 0; i < nums; i++)
+ if (list[i] == nid)
+ return i;
+ return -1;
+}
+
+/* get a unique suffix or an index number */
+static const char *check_output_sfx(hda_nid_t nid, const hda_nid_t *pins,
+ int num_pins, int *indexp)
+{
+ static const char * const channel_sfx[] = {
+ " Front", " Surround", " CLFE", " Side"
+ };
+ int i;
+
+ i = find_idx_in_nid_list(nid, pins, num_pins);
+ if (i < 0)
+ return NULL;
+ if (num_pins == 1)
+ return "";
+ if (num_pins > ARRAY_SIZE(channel_sfx)) {
+ if (indexp)
+ *indexp = i;
+ return "";
+ }
+ return channel_sfx[i];
+}
+
+static int fill_audio_out_name(struct hda_codec *codec, hda_nid_t nid,
+ const struct auto_pin_cfg *cfg,
+ const char *name, char *label, int maxlen,
+ int *indexp)
+{
+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ int attr = snd_hda_get_input_pin_attr(def_conf);
+ const char *pfx = "", *sfx = "";
+
+ /* handle as a speaker if it's a fixed line-out */
+ if (!strcmp(name, "Line Out") && attr == INPUT_PIN_ATTR_INT)
+ name = "Speaker";
+ /* check the location */
+ switch (attr) {
+ case INPUT_PIN_ATTR_DOCK:
+ pfx = "Dock ";
+ break;
+ case INPUT_PIN_ATTR_FRONT:
+ pfx = "Front ";
+ break;
+ }
+ if (cfg) {
+ /* try to give a unique suffix if needed */
+ sfx = check_output_sfx(nid, cfg->line_out_pins, cfg->line_outs,
+ indexp);
+ if (!sfx)
+ sfx = check_output_sfx(nid, cfg->speaker_pins, cfg->speaker_outs,
+ indexp);
+ if (!sfx) {
+ /* don't add channel suffix for Headphone controls */
+ int idx = find_idx_in_nid_list(nid, cfg->hp_pins,
+ cfg->hp_outs);
+ if (idx >= 0)
+ *indexp = idx;
+ sfx = "";
+ }
+ }
+ snprintf(label, maxlen, "%s%s%s", pfx, name, sfx);
+ return 1;
+}
+
+/**
+ * snd_hda_get_pin_label - Get a label for the given I/O pin
+ *
+ * Get a label for the given pin. This function works for both input and
+ * output pins. When @cfg is given as non-NULL, the function tries to get
+ * an optimized label using hda_get_autocfg_input_label().
+ *
+ * This function tries to give a unique label string for the pin as much as
+ * possible. For example, when the multiple line-outs are present, it adds
+ * the channel suffix like "Front", "Surround", etc (only when @cfg is given).
+ * If no unique name with a suffix is available and @indexp is non-NULL, the
+ * index number is stored in the pointer.
+ */
+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
+ const struct auto_pin_cfg *cfg,
+ char *label, int maxlen, int *indexp)
+{
+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ const char *name = NULL;
+ int i;
+
+ if (indexp)
+ *indexp = 0;
+ if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
+ return 0;
+
+ switch (get_defcfg_device(def_conf)) {
+ case AC_JACK_LINE_OUT:
+ return fill_audio_out_name(codec, nid, cfg, "Line Out",
+ label, maxlen, indexp);
+ case AC_JACK_SPEAKER:
+ return fill_audio_out_name(codec, nid, cfg, "Speaker",
+ label, maxlen, indexp);
+ case AC_JACK_HP_OUT:
+ return fill_audio_out_name(codec, nid, cfg, "Headphone",
+ label, maxlen, indexp);
+ case AC_JACK_SPDIF_OUT:
+ case AC_JACK_DIG_OTHER_OUT:
+ if (get_defcfg_location(def_conf) == AC_JACK_LOC_HDMI)
+ name = "HDMI";
+ else
+ name = "SPDIF";
+ if (cfg && indexp) {
+ i = find_idx_in_nid_list(nid, cfg->dig_out_pins,
+ cfg->dig_outs);
+ if (i >= 0)
+ *indexp = i;
+ }
+ break;
+ default:
+ if (cfg) {
+ for (i = 0; i < cfg->num_inputs; i++) {
+ if (cfg->inputs[i].pin != nid)
+ continue;
+ name = hda_get_autocfg_input_label(codec, cfg, i);
+ if (name)
+ break;
+ }
+ }
+ if (!name)
+ name = hda_get_input_pin_label(codec, nid, true);
+ break;
+ }
+ if (!name)
+ return 0;
+ strlcpy(label, name, maxlen);
+ return 1;
+}
+EXPORT_SYMBOL_HDA(snd_hda_get_pin_label);
+
/**
* snd_hda_add_imux_item - Add an item to input_mux
*
@@ -5076,6 +5444,10 @@ int snd_hda_suspend(struct hda_bus *bus)
list_for_each_entry(codec, &bus->codec_list, list) {
if (hda_codec_is_power_on(codec))
hda_call_codec_suspend(codec);
+ else /* forcibly change the power to D3 even if not used */
+ hda_set_power_state(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_D3);
if (codec->patch_ops.post_suspend)
codec->patch_ops.post_suspend(codec);
}
@@ -5154,30 +5526,6 @@ void snd_array_free(struct snd_array *array)
EXPORT_SYMBOL_HDA(snd_array_free);
/**
- * snd_print_pcm_rates - Print the supported PCM rates to the string buffer
- * @pcm: PCM caps bits
- * @buf: the string buffer to write
- * @buflen: the max buffer length
- *
- * used by hda_proc.c and hda_eld.c
- */
-void snd_print_pcm_rates(int pcm, char *buf, int buflen)
-{
- static unsigned int rates[] = {
- 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
- 96000, 176400, 192000, 384000
- };
- int i, j;
-
- for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
- if (pcm & (1 << i))
- j += snprintf(buf + j, buflen - j, " %d", rates[i]);
-
- buf[j] = '\0'; /* necessary when j == 0 */
-}
-EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
-
-/**
* snd_print_pcm_bits - Print the supported PCM fmt bits to the string buffer
* @pcm: PCM caps bits
* @buf: the string buffer to write
@@ -5198,111 +5546,5 @@ void snd_print_pcm_bits(int pcm, char *buf, int buflen)
}
EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
-#ifdef CONFIG_SND_HDA_INPUT_JACK
-/*
- * Input-jack notification support
- */
-struct hda_jack_item {
- hda_nid_t nid;
- int type;
- struct snd_jack *jack;
-};
-
-static const char *get_jack_default_name(struct hda_codec *codec, hda_nid_t nid,
- int type)
-{
- switch (type) {
- case SND_JACK_HEADPHONE:
- return "Headphone";
- case SND_JACK_MICROPHONE:
- return "Mic";
- case SND_JACK_LINEOUT:
- return "Line-out";
- case SND_JACK_HEADSET:
- return "Headset";
- case SND_JACK_VIDEOOUT:
- return "HDMI/DP";
- default:
- return "Misc";
- }
-}
-
-static void hda_free_jack_priv(struct snd_jack *jack)
-{
- struct hda_jack_item *jacks = jack->private_data;
- jacks->nid = 0;
- jacks->jack = NULL;
-}
-
-int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type,
- const char *name)
-{
- struct hda_jack_item *jack;
- int err;
-
- snd_array_init(&codec->jacks, sizeof(*jack), 32);
- jack = snd_array_new(&codec->jacks);
- if (!jack)
- return -ENOMEM;
-
- jack->nid = nid;
- jack->type = type;
- if (!name)
- name = get_jack_default_name(codec, nid, type);
- err = snd_jack_new(codec->bus->card, name, type, &jack->jack);
- if (err < 0) {
- jack->nid = 0;
- return err;
- }
- jack->jack->private_data = jack;
- jack->jack->private_free = hda_free_jack_priv;
- return 0;
-}
-EXPORT_SYMBOL_HDA(snd_hda_input_jack_add);
-
-void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid)
-{
- struct hda_jack_item *jacks = codec->jacks.list;
- int i;
-
- if (!jacks)
- return;
-
- for (i = 0; i < codec->jacks.used; i++, jacks++) {
- unsigned int pin_ctl;
- unsigned int present;
- int type;
-
- if (jacks->nid != nid)
- continue;
- present = snd_hda_jack_detect(codec, nid);
- type = jacks->type;
- if (type == (SND_JACK_HEADPHONE | SND_JACK_LINEOUT)) {
- pin_ctl = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- type = (pin_ctl & AC_PINCTL_HP_EN) ?
- SND_JACK_HEADPHONE : SND_JACK_LINEOUT;
- }
- snd_jack_report(jacks->jack, present ? type : 0);
- }
-}
-EXPORT_SYMBOL_HDA(snd_hda_input_jack_report);
-
-/* free jack instances manually when clearing/reconfiguring */
-void snd_hda_input_jack_free(struct hda_codec *codec)
-{
- if (!codec->bus->shutdown && codec->jacks.list) {
- struct hda_jack_item *jacks = codec->jacks.list;
- int i;
- for (i = 0; i < codec->jacks.used; i++, jacks++) {
- if (jacks->jack)
- snd_device_free(codec->bus->card, jacks->jack);
- }
- }
- snd_array_free(&codec->jacks);
-}
-EXPORT_SYMBOL_HDA(snd_hda_input_jack_free);
-#endif /* CONFIG_SND_HDA_INPUT_JACK */
-
MODULE_DESCRIPTION("HDA codec core");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 755f2b0f9d8e..9a9f372e1be4 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -298,6 +298,9 @@ enum {
#define AC_AMPCAP_MUTE (1<<31) /* mute capable */
#define AC_AMPCAP_MUTE_SHIFT 31
+/* driver-specific amp-caps: using bits 24-30 */
+#define AC_AMPCAP_MIN_MUTE (1 << 30) /* min-volume = mute */
+
/* Connection list */
#define AC_CLIST_LENGTH (0x7f<<0)
#define AC_CLIST_LONG (1<<7)
@@ -547,9 +550,6 @@ enum {
/* max. codec address */
#define HDA_MAX_CODEC_ADDRESS 0x0f
-/* max number of PCM devics per card */
-#define HDA_MAX_PCMS 10
-
/*
* generic arrays
*/
@@ -854,6 +854,8 @@ struct hda_codec {
unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */
unsigned int pins_shutup:1; /* pins are shut up */
unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */
+ unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */
+ unsigned int no_jack_detect:1; /* Machine has no jack-detection */
#ifdef CONFIG_SND_HDA_POWER_SAVE
unsigned int power_on :1; /* current (global) power-state */
unsigned int power_transition :1; /* power-state in transition */
@@ -868,6 +870,9 @@ struct hda_codec {
void (*proc_widget_hook)(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid);
+ /* jack detection */
+ struct snd_array jacktbl;
+
#ifdef CONFIG_SND_HDA_INPUT_JACK
/* jack detection */
struct snd_array jacks;
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
index c34f730f4815..b58b4b1687fa 100644
--- a/sound/pci/hda/hda_eld.c
+++ b/sound/pci/hda/hda_eld.c
@@ -297,10 +297,18 @@ static int hdmi_update_eld(struct hdmi_eld *e,
buf + ELD_FIXED_BYTES + mnl + 3 * i);
}
+ /*
+ * HDMI sink's ELD info cannot always be retrieved for now, e.g.
+ * in console or for audio devices. Assume the highest speakers
+ * configuration, to _not_ prohibit multi-channel audio playback.
+ */
+ if (!e->spk_alloc)
+ e->spk_alloc = 0xffff;
+
+ e->eld_valid = true;
return 0;
out_fail:
- e->eld_ver = 0;
return -EINVAL;
}
@@ -318,8 +326,10 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
int size;
unsigned char *buf;
- if (!eld->eld_valid)
- return -ENOENT;
+ /*
+ * ELD size is initialized to zero in caller function. If no errors and
+ * ELD is valid, actual eld_size is assigned in hdmi_update_eld()
+ */
size = snd_hdmi_get_eld_size(codec, nid);
if (size == 0) {
@@ -327,39 +337,69 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld,
snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n");
size = 128;
}
- if (size < ELD_FIXED_BYTES || size > PAGE_SIZE) {
+ if (size < ELD_FIXED_BYTES || size > ELD_MAX_SIZE) {
snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size);
return -ERANGE;
}
- buf = kmalloc(size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
+ /* set ELD buffer */
+ buf = eld->eld_buffer;
for (i = 0; i < size; i++) {
unsigned int val = hdmi_get_eld_data(codec, nid, i);
+ /*
+ * Graphics driver might be writing to ELD buffer right now.
+ * Just abort. The caller will repoll after a while.
+ */
if (!(val & AC_ELDD_ELD_VALID)) {
- if (!i) {
- snd_printd(KERN_INFO
- "HDMI: invalid ELD data\n");
- ret = -EINVAL;
- goto error;
- }
snd_printd(KERN_INFO
"HDMI: invalid ELD data byte %d\n", i);
- val = 0;
- } else
- val &= AC_ELDD_ELD_DATA;
+ ret = -EINVAL;
+ goto error;
+ }
+ val &= AC_ELDD_ELD_DATA;
+ /*
+ * The first byte cannot be zero. This can happen on some DVI
+ * connections. Some Intel chips may also need some 250ms delay
+ * to return non-zero ELD data, even when the graphics driver
+ * correctly writes ELD content before setting ELD_valid bit.
+ */
+ if (!val && !i) {
+ snd_printdd(KERN_INFO "HDMI: 0 ELD data\n");
+ ret = -EINVAL;
+ goto error;
+ }
buf[i] = val;
}
ret = hdmi_update_eld(eld, buf, size);
error:
- kfree(buf);
return ret;
}
+/**
+ * SNDRV_PCM_RATE_* and AC_PAR_PCM values don't match, print correct rates with
+ * hdmi-specific routine.
+ */
+static void hdmi_print_pcm_rates(int pcm, char *buf, int buflen)
+{
+ static unsigned int alsa_rates[] = {
+ 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 64000,
+ 88200, 96000, 176400, 192000, 384000
+ };
+ int i, j;
+
+ for (i = 0, j = 0; i < ARRAY_SIZE(alsa_rates); i++)
+ if (pcm & (1 << i))
+ j += snprintf(buf + j, buflen - j, " %d",
+ alsa_rates[i]);
+
+ buf[j] = '\0'; /* necessary when j == 0 */
+}
+
+#define SND_PRINT_RATES_ADVISED_BUFSIZE 80
+
static void hdmi_show_short_audio_desc(struct cea_sad *a)
{
char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
@@ -368,7 +408,7 @@ static void hdmi_show_short_audio_desc(struct cea_sad *a)
if (!a->format)
return;
- snd_print_pcm_rates(a->rates, buf, sizeof(buf));
+ hdmi_print_pcm_rates(a->rates, buf, sizeof(buf));
if (a->format == AUDIO_CODING_TYPE_LPCM)
snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2) - 8);
@@ -427,7 +467,7 @@ static void hdmi_print_sad_info(int i, struct cea_sad *a,
i, a->format, cea_audio_coding_type_names[a->format]);
snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels);
- snd_print_pcm_rates(a->rates, buf, sizeof(buf));
+ hdmi_print_pcm_rates(a->rates, buf, sizeof(buf));
snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf);
if (a->format == AUDIO_CODING_TYPE_LPCM) {
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index a63c54d9d767..431bf868711e 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -22,6 +22,7 @@
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index bf3ced51e0f8..6b2efb8cb1f9 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -26,6 +26,7 @@
#include <linux/ctype.h>
#include <linux/string.h>
#include <linux/firmware.h>
+#include <linux/export.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
@@ -643,14 +644,14 @@ static inline int strmatch(const char *a, const char *b)
static void parse_codec_mode(char *buf, struct hda_bus *bus,
struct hda_codec **codecp)
{
- unsigned int vendorid, subid, caddr;
+ int vendorid, subid, caddr;
struct hda_codec *codec;
*codecp = NULL;
if (sscanf(buf, "%i %i %i", &vendorid, &subid, &caddr) == 3) {
list_for_each_entry(codec, &bus->codec_list, list) {
- if (codec->vendor_id == vendorid &&
- codec->subsystem_id == subid &&
+ if ((vendorid <= 0 || codec->vendor_id == vendorid) &&
+ (subid <= 0 || codec->subsystem_id == subid) &&
codec->addr == caddr) {
*codecp = codec;
break;
@@ -756,8 +757,6 @@ static int get_line_from_fw(char *buf, int size, struct firmware *fw)
}
if (!fw->size)
return 0;
- if (size < fw->size)
- size = fw->size;
for (len = 0; len < fw->size; len++) {
if (!*p)
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index be6982289c0d..c19e71a94e1b 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -34,7 +34,6 @@
*
*/
-#include <asm/io.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/kernel.h>
@@ -46,6 +45,12 @@
#include <linux/pci.h>
#include <linux/mutex.h>
#include <linux/reboot.h>
+#include <linux/io.h>
+#ifdef CONFIG_X86
+/* for snoop control */
+#include <asm/pgtable.h>
+#include <asm/cacheflush.h>
+#endif
#include <sound/core.h>
#include <sound/initval.h>
#include "hda_codec.h"
@@ -53,13 +58,13 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static char *model[SNDRV_CARDS];
static int position_fix[SNDRV_CARDS];
static int bdl_pos_adj[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int probe_mask[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = -1};
static int probe_only[SNDRV_CARDS];
-static int single_cmd;
+static bool single_cmd;
static int enable_msi = -1;
#ifdef CONFIG_SND_HDA_PATCH_LOADER
static char *patch[SNDRV_CARDS];
@@ -79,7 +84,7 @@ module_param_array(model, charp, NULL, 0444);
MODULE_PARM_DESC(model, "Use the given board model.");
module_param_array(position_fix, int, NULL, 0444);
MODULE_PARM_DESC(position_fix, "DMA pointer read method."
- "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO).");
+ "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO, 4 = COMBO).");
module_param_array(bdl_pos_adj, int, NULL, 0644);
MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset.");
module_param_array(probe_mask, int, NULL, 0444);
@@ -89,7 +94,7 @@ MODULE_PARM_DESC(probe_only, "Only probing and no codec initialization.");
module_param(single_cmd, bool, 0444);
MODULE_PARM_DESC(single_cmd, "Use single command to communicate with codecs "
"(for debugging only).");
-module_param(enable_msi, int, 0444);
+module_param(enable_msi, bint, 0444);
MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
#ifdef CONFIG_SND_HDA_PATCH_LOADER
module_param_array(patch, charp, NULL, 0444);
@@ -111,11 +116,27 @@ MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
* this may give more power-saving, but will take longer time to
* wake up.
*/
-static int power_save_controller = 1;
+static bool power_save_controller = 1;
module_param(power_save_controller, bool, 0644);
MODULE_PARM_DESC(power_save_controller, "Reset controller in power save mode.");
#endif
+static int align_buffer_size = -1;
+module_param(align_buffer_size, bint, 0644);
+MODULE_PARM_DESC(align_buffer_size,
+ "Force buffer and period sizes to be multiple of 128 bytes.");
+
+#ifdef CONFIG_X86
+static bool hda_snoop = true;
+module_param_named(snoop, hda_snoop, bool, 0444);
+MODULE_PARM_DESC(snoop, "Enable/disable snooping");
+#define azx_snoop(chip) (chip)->snoop
+#else
+#define hda_snoop true
+#define azx_snoop(chip) true
+#endif
+
+
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, ICH6M},"
@@ -127,6 +148,7 @@ MODULE_SUPPORTED_DEVICE("{{Intel, ICH6},"
"{Intel, PCH},"
"{Intel, CPT},"
"{Intel, PPT},"
+ "{Intel, LPT},"
"{Intel, PBG},"
"{Intel, SCH},"
"{ATI, SB450},"
@@ -308,6 +330,7 @@ enum {
POS_FIX_LPIB,
POS_FIX_POSBUF,
POS_FIX_VIACOMBO,
+ POS_FIX_COMBO,
};
/* Defines for ATI HD Audio support in SB450 south bridge */
@@ -360,7 +383,7 @@ struct azx_dev {
*/
unsigned char stream_tag; /* assigned stream */
unsigned char index; /* stream index */
- int device; /* last device number assigned to */
+ int assigned_key; /* last device# key assigned to */
unsigned int opened :1;
unsigned int running :1;
@@ -371,6 +394,7 @@ struct azx_dev {
* when link position is not greater than FIFO size
*/
unsigned int insufficient :1;
+ unsigned int wc_marked:1;
};
/* CORB/RIRB */
@@ -385,6 +409,14 @@ struct azx_rb {
u32 res[AZX_MAX_CODECS]; /* last read value */
};
+struct azx_pcm {
+ struct azx *chip;
+ struct snd_pcm *pcm;
+ struct hda_codec *codec;
+ struct hda_pcm_stream *hinfo[2];
+ struct list_head list;
+};
+
struct azx {
struct snd_card *card;
struct pci_dev *pci;
@@ -412,7 +444,7 @@ struct azx {
struct azx_dev *azx_dev;
/* PCM */
- struct snd_pcm *pcm[HDA_MAX_PCMS];
+ struct list_head pcm_list; /* azx_pcm list */
/* HD codec */
unsigned short codec_mask;
@@ -438,6 +470,8 @@ struct azx {
unsigned int msi :1;
unsigned int irq_pending_warned :1;
unsigned int probing :1; /* codec probing phase */
+ unsigned int snoop:1;
+ unsigned int align_buffer_size:1;
/* for debugging */
unsigned int last_cmd[AZX_MAX_CODECS];
@@ -456,6 +490,7 @@ enum {
AZX_DRIVER_SCH,
AZX_DRIVER_ATI,
AZX_DRIVER_ATIHDMI,
+ AZX_DRIVER_ATIHDMI_NS,
AZX_DRIVER_VIA,
AZX_DRIVER_SIS,
AZX_DRIVER_ULI,
@@ -481,6 +516,8 @@ enum {
#define AZX_DCAPS_NO_64BIT (1 << 18) /* No 64bit address */
#define AZX_DCAPS_SYNC_WRITE (1 << 19) /* sync each cmd write */
#define AZX_DCAPS_OLD_SSYNC (1 << 20) /* Old SSYNC reg for ICH */
+#define AZX_DCAPS_BUFSIZE (1 << 21) /* no buffer size alignment */
+#define AZX_DCAPS_ALIGN_BUFSIZE (1 << 22) /* buffer size alignment */
/* quirks for ATI SB / AMD Hudson */
#define AZX_DCAPS_PRESET_ATI_SB \
@@ -493,7 +530,8 @@ enum {
/* quirks for Nvidia */
#define AZX_DCAPS_PRESET_NVIDIA \
- (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI)
+ (AZX_DCAPS_NVIDIA_SNOOP | AZX_DCAPS_RIRB_DELAY | AZX_DCAPS_NO_MSI |\
+ AZX_DCAPS_ALIGN_BUFSIZE)
static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ICH] = "HDA Intel",
@@ -501,6 +539,7 @@ static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_SCH] = "HDA Intel MID",
[AZX_DRIVER_ATI] = "HDA ATI SB",
[AZX_DRIVER_ATIHDMI] = "HDA ATI HDMI",
+ [AZX_DRIVER_ATIHDMI_NS] = "HDA ATI HDMI",
[AZX_DRIVER_VIA] = "HDA VIA VT82xx",
[AZX_DRIVER_SIS] = "HDA SIS966",
[AZX_DRIVER_ULI] = "HDA ULI M5461",
@@ -542,6 +581,45 @@ static char *driver_short_names[] __devinitdata = {
/* for pcm support */
#define get_azx_dev(substream) (substream->runtime->private_data)
+#ifdef CONFIG_X86
+static void __mark_pages_wc(struct azx *chip, void *addr, size_t size, bool on)
+{
+ if (azx_snoop(chip))
+ return;
+ if (addr && size) {
+ int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ if (on)
+ set_memory_wc((unsigned long)addr, pages);
+ else
+ set_memory_wb((unsigned long)addr, pages);
+ }
+}
+
+static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf,
+ bool on)
+{
+ __mark_pages_wc(chip, buf->area, buf->bytes, on);
+}
+static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
+ struct snd_pcm_runtime *runtime, bool on)
+{
+ if (azx_dev->wc_marked != on) {
+ __mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, on);
+ azx_dev->wc_marked = on;
+ }
+}
+#else
+/* NOP for other archs */
+static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf,
+ bool on)
+{
+}
+static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
+ struct snd_pcm_runtime *runtime, bool on)
+{
+}
+#endif
+
static int azx_acquire_irq(struct azx *chip, int do_disconnect);
static int azx_send_cmd(struct hda_bus *bus, unsigned int val);
/*
@@ -563,6 +641,7 @@ static int azx_alloc_cmd_io(struct azx *chip)
snd_printk(KERN_ERR SFX "cannot allocate CORB/RIRB\n");
return err;
}
+ mark_pages_wc(chip, &chip->rb, true);
return 0;
}
@@ -1079,8 +1158,6 @@ static void update_pci_byte(struct pci_dev *pci, unsigned int reg,
static void azx_init_pci(struct azx *chip)
{
- unsigned short snoop;
-
/* Clear bits 0-2 of PCI register TCSEL (at offset 0x44)
* TCSEL == Traffic Class Select Register, which sets PCI express QOS
* Ensuring these bits are 0 clears playback static on some HD Audio
@@ -1096,15 +1173,15 @@ static void azx_init_pci(struct azx *chip)
* we need to enable snoop.
*/
if (chip->driver_caps & AZX_DCAPS_ATI_SNOOP) {
- snd_printdd(SFX "Enabling ATI snoop\n");
+ snd_printdd(SFX "Setting ATI snoop: %d\n", azx_snoop(chip));
update_pci_byte(chip->pci,
- ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR,
- 0x07, ATI_SB450_HDAUDIO_ENABLE_SNOOP);
+ ATI_SB450_HDAUDIO_MISC_CNTR2_ADDR, 0x07,
+ azx_snoop(chip) ? ATI_SB450_HDAUDIO_ENABLE_SNOOP : 0);
}
/* For NVIDIA HDA, enable snoop */
if (chip->driver_caps & AZX_DCAPS_NVIDIA_SNOOP) {
- snd_printdd(SFX "Enabling Nvidia snoop\n");
+ snd_printdd(SFX "Setting Nvidia snoop: %d\n", azx_snoop(chip));
update_pci_byte(chip->pci,
NVIDIA_HDA_TRANSREG_ADDR,
0x0f, NVIDIA_HDA_ENABLE_COHBITS);
@@ -1118,16 +1195,20 @@ static void azx_init_pci(struct azx *chip)
/* Enable SCH/PCH snoop if needed */
if (chip->driver_caps & AZX_DCAPS_SCH_SNOOP) {
+ unsigned short snoop;
pci_read_config_word(chip->pci, INTEL_SCH_HDA_DEVC, &snoop);
- if (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP) {
- pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC,
- snoop & (~INTEL_SCH_HDA_DEVC_NOSNOOP));
+ if ((!azx_snoop(chip) && !(snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)) ||
+ (azx_snoop(chip) && (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP))) {
+ snoop &= ~INTEL_SCH_HDA_DEVC_NOSNOOP;
+ if (!azx_snoop(chip))
+ snoop |= INTEL_SCH_HDA_DEVC_NOSNOOP;
+ pci_write_config_word(chip->pci, INTEL_SCH_HDA_DEVC, snoop);
pci_read_config_word(chip->pci,
INTEL_SCH_HDA_DEVC, &snoop);
- snd_printdd(SFX "HDA snoop disabled, enabling ... %s\n",
- (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
- ? "Failed" : "OK");
}
+ snd_printdd(SFX "SCH snoop: %s\n",
+ (snoop & INTEL_SCH_HDA_DEVC_NOSNOOP)
+ ? "Disabled" : "Enabled");
}
}
@@ -1334,12 +1415,16 @@ static void azx_stream_reset(struct azx *chip, struct azx_dev *azx_dev)
*/
static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
{
+ unsigned int val;
/* make sure the run bit is zero for SD */
azx_stream_clear(chip, azx_dev);
/* program the stream_tag */
- azx_sd_writel(azx_dev, SD_CTL,
- (azx_sd_readl(azx_dev, SD_CTL) & ~SD_CTL_STREAM_TAG_MASK)|
- (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT));
+ val = azx_sd_readl(azx_dev, SD_CTL);
+ val = (val & ~SD_CTL_STREAM_TAG_MASK) |
+ (azx_dev->stream_tag << SD_CTL_STREAM_TAG_SHIFT);
+ if (!azx_snoop(chip))
+ val |= SD_CTL_TRAFFIC_PRIO;
+ azx_sd_writel(azx_dev, SD_CTL, val);
/* program the length of samples in cyclic buffer */
azx_sd_writel(azx_dev, SD_CBL, azx_dev->bufsize);
@@ -1406,10 +1491,9 @@ static void azx_bus_reset(struct hda_bus *bus)
azx_init_chip(chip, 1);
#ifdef CONFIG_PM
if (chip->initialized) {
- int i;
-
- for (i = 0; i < HDA_MAX_PCMS; i++)
- snd_pcm_suspend_all(chip->pcm[i]);
+ struct azx_pcm *p;
+ list_for_each_entry(p, &chip->pcm_list, list)
+ snd_pcm_suspend_all(p->pcm);
snd_hda_suspend(chip->bus);
snd_hda_resume(chip->bus);
}
@@ -1533,6 +1617,9 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
{
int dev, i, nums;
struct azx_dev *res = NULL;
+ /* make a non-zero unique key for the substream */
+ int key = (substream->pcm->device << 16) | (substream->number << 2) |
+ (substream->stream + 1);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
dev = chip->playback_index_offset;
@@ -1544,12 +1631,12 @@ azx_assign_device(struct azx *chip, struct snd_pcm_substream *substream)
for (i = 0; i < nums; i++, dev++)
if (!chip->azx_dev[dev].opened) {
res = &chip->azx_dev[dev];
- if (res->device == substream->pcm->device)
+ if (res->assigned_key == key)
break;
}
if (res) {
res->opened = 1;
- res->device = substream->pcm->device;
+ res->assigned_key = key;
}
return res;
}
@@ -1584,12 +1671,6 @@ static struct snd_pcm_hardware azx_pcm_hw = {
.fifo_size = 0,
};
-struct azx_pcm {
- struct azx *chip;
- struct hda_codec *codec;
- struct hda_pcm_stream *hinfo[2];
-};
-
static int azx_pcm_open(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
@@ -1599,6 +1680,7 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
unsigned long flags;
int err;
+ int buff_step;
mutex_lock(&chip->open_mutex);
azx_dev = azx_assign_device(chip, substream);
@@ -1613,10 +1695,25 @@ static int azx_pcm_open(struct snd_pcm_substream *substream)
runtime->hw.rates = hinfo->rates;
snd_pcm_limit_hw_rates(runtime);
snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (chip->align_buffer_size)
+ /* constrain buffer sizes to be multiple of 128
+ bytes. This is more efficient in terms of memory
+ access but isn't required by the HDA spec and
+ prevents users from specifying exact period/buffer
+ sizes. For example for 44.1kHz, a period size set
+ to 20ms will be rounded to 19.59ms. */
+ buff_step = 128;
+ else
+ /* Don't enforce steps on buffer sizes, still need to
+ be multiple of 4 bytes (HDA spec). Tested on Intel
+ HDA controllers, may not work on all devices where
+ option needs to be disabled */
+ buff_step = 4;
+
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
- 128);
+ buff_step);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES,
- 128);
+ buff_step);
snd_hda_power_up(apcm->codec);
err = hinfo->ops.open(hinfo, apcm->codec, substream);
if (err < 0) {
@@ -1671,19 +1768,30 @@ static int azx_pcm_close(struct snd_pcm_substream *substream)
static int azx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
+ struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+ struct azx *chip = apcm->chip;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct azx_dev *azx_dev = get_azx_dev(substream);
+ int ret;
+ mark_runtime_wc(chip, azx_dev, runtime, false);
azx_dev->bufsize = 0;
azx_dev->period_bytes = 0;
azx_dev->format_val = 0;
- return snd_pcm_lib_malloc_pages(substream,
+ ret = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
+ if (ret < 0)
+ return ret;
+ mark_runtime_wc(chip, azx_dev, runtime, true);
+ return ret;
}
static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
struct azx_dev *azx_dev = get_azx_dev(substream);
+ struct azx *chip = apcm->chip;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
/* reset BDL address */
@@ -1696,6 +1804,7 @@ static int azx_pcm_hw_free(struct snd_pcm_substream *substream)
snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
+ mark_runtime_wc(chip, azx_dev, runtime, false);
return snd_pcm_lib_free_pages(substream);
}
@@ -1924,7 +2033,8 @@ static unsigned int azx_via_get_position(struct azx *chip,
}
static unsigned int azx_get_position(struct azx *chip,
- struct azx_dev *azx_dev)
+ struct azx_dev *azx_dev,
+ bool with_check)
{
unsigned int pos;
int stream = azx_dev->substream->stream;
@@ -1940,7 +2050,7 @@ static unsigned int azx_get_position(struct azx *chip,
default:
/* use the position buffer */
pos = le32_to_cpu(*azx_dev->posbuf);
- if (chip->position_fix[stream] == POS_FIX_AUTO) {
+ if (with_check && chip->position_fix[stream] == POS_FIX_AUTO) {
if (!pos || pos == (u32)-1) {
printk(KERN_WARNING
"hda-intel: Invalid position buffer, "
@@ -1964,7 +2074,7 @@ static snd_pcm_uframes_t azx_pcm_pointer(struct snd_pcm_substream *substream)
struct azx *chip = apcm->chip;
struct azx_dev *azx_dev = get_azx_dev(substream);
return bytes_to_frames(substream->runtime,
- azx_get_position(chip, azx_dev));
+ azx_get_position(chip, azx_dev, false));
}
/*
@@ -1987,7 +2097,7 @@ static int azx_position_ok(struct azx *chip, struct azx_dev *azx_dev)
return -1; /* bogus (too early) interrupt */
stream = azx_dev->substream->stream;
- pos = azx_get_position(chip, azx_dev);
+ pos = azx_get_position(chip, azx_dev, true);
if (WARN_ONCE(!azx_dev->period_bytes,
"hda-intel: zero azx_dev->period_bytes"))
@@ -2054,6 +2164,20 @@ static void azx_clear_irq_pending(struct azx *chip)
spin_unlock_irq(&chip->reg_lock);
}
+#ifdef CONFIG_X86
+static int azx_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *area)
+{
+ struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
+ struct azx *chip = apcm->chip;
+ if (!azx_snoop(chip))
+ area->vm_page_prot = pgprot_writecombine(area->vm_page_prot);
+ return snd_pcm_lib_default_mmap(substream, area);
+}
+#else
+#define azx_pcm_mmap NULL
+#endif
+
static struct snd_pcm_ops azx_pcm_ops = {
.open = azx_pcm_open,
.close = azx_pcm_close,
@@ -2063,6 +2187,7 @@ static struct snd_pcm_ops azx_pcm_ops = {
.prepare = azx_pcm_prepare,
.trigger = azx_pcm_trigger,
.pointer = azx_pcm_pointer,
+ .mmap = azx_pcm_mmap,
.page = snd_pcm_sgbuf_ops_page,
};
@@ -2070,7 +2195,7 @@ static void azx_pcm_free(struct snd_pcm *pcm)
{
struct azx_pcm *apcm = pcm->private_data;
if (apcm) {
- apcm->chip->pcm[pcm->device] = NULL;
+ list_del(&apcm->list);
kfree(apcm);
}
}
@@ -2088,14 +2213,11 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
unsigned int size;
int s, err;
- if (pcm_dev >= HDA_MAX_PCMS) {
- snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n",
- pcm_dev);
- return -EINVAL;
- }
- if (chip->pcm[pcm_dev]) {
- snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev);
- return -EBUSY;
+ list_for_each_entry(apcm, &chip->pcm_list, list) {
+ if (apcm->pcm->device == pcm_dev) {
+ snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev);
+ return -EBUSY;
+ }
}
err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams,
@@ -2108,12 +2230,13 @@ azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
if (apcm == NULL)
return -ENOMEM;
apcm->chip = chip;
+ apcm->pcm = pcm;
apcm->codec = codec;
pcm->private_data = apcm;
pcm->private_free = azx_pcm_free;
if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM)
pcm->dev_class = SNDRV_PCM_CLASS_MODEM;
- chip->pcm[pcm_dev] = pcm;
+ list_add_tail(&apcm->list, &chip->pcm_list);
cpcm->pcm = pcm;
for (s = 0; s < 2; s++) {
apcm->hinfo[s] = &cpcm->stream[s];
@@ -2228,27 +2351,16 @@ static void azx_power_notify(struct hda_bus *bus)
* power management
*/
-static int snd_hda_codecs_inuse(struct hda_bus *bus)
-{
- struct hda_codec *codec;
-
- list_for_each_entry(codec, &bus->codec_list, list) {
- if (snd_hda_codec_needs_resume(codec))
- return 1;
- }
- return 0;
-}
-
static int azx_suspend(struct pci_dev *pci, pm_message_t state)
{
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
- int i;
+ struct azx_pcm *p;
snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
azx_clear_irq_pending(chip);
- for (i = 0; i < HDA_MAX_PCMS; i++)
- snd_pcm_suspend_all(chip->pcm[i]);
+ list_for_each_entry(p, &chip->pcm_list, list)
+ snd_pcm_suspend_all(p->pcm);
if (chip->initialized)
snd_hda_suspend(chip->bus);
azx_stop_chip(chip);
@@ -2285,8 +2397,7 @@ static int azx_resume(struct pci_dev *pci)
return -EIO;
azx_init_pci(chip);
- if (snd_hda_codecs_inuse(chip->bus))
- azx_init_chip(chip, 1);
+ azx_init_chip(chip, 1);
snd_hda_resume(chip->bus);
snd_power_change_state(card, SNDRV_CTL_POWER_D0);
@@ -2343,13 +2454,19 @@ static int azx_free(struct azx *chip)
if (chip->azx_dev) {
for (i = 0; i < chip->num_streams; i++)
- if (chip->azx_dev[i].bdl.area)
+ if (chip->azx_dev[i].bdl.area) {
+ mark_pages_wc(chip, &chip->azx_dev[i].bdl, false);
snd_dma_free_pages(&chip->azx_dev[i].bdl);
+ }
}
- if (chip->rb.area)
+ if (chip->rb.area) {
+ mark_pages_wc(chip, &chip->rb, false);
snd_dma_free_pages(&chip->rb);
- if (chip->posbuf.area)
+ }
+ if (chip->posbuf.area) {
+ mark_pages_wc(chip, &chip->posbuf, false);
snd_dma_free_pages(&chip->posbuf);
+ }
pci_release_regions(chip->pci);
pci_disable_device(chip->pci);
kfree(chip->azx_dev);
@@ -2374,7 +2491,7 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
- SND_PCI_QUIRK(0x1106, 0x3288, "ASUS M2V-MX SE", POS_FIX_LPIB),
+ SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1458, 0xa022, "ga-ma770-ud3", POS_FIX_LPIB),
SND_PCI_QUIRK(0x1462, 0x1002, "MSI Wind U115", POS_FIX_LPIB),
@@ -2392,6 +2509,7 @@ static int __devinit check_position_fix(struct azx *chip, int fix)
case POS_FIX_LPIB:
case POS_FIX_POSBUF:
case POS_FIX_VIACOMBO:
+ case POS_FIX_COMBO:
return fix;
}
@@ -2500,6 +2618,35 @@ static void __devinit check_msi(struct azx *chip)
}
}
+/* check the snoop mode availability */
+static void __devinit azx_check_snoop_available(struct azx *chip)
+{
+ bool snoop = chip->snoop;
+
+ switch (chip->driver_type) {
+ case AZX_DRIVER_VIA:
+ /* force to non-snoop mode for a new VIA controller
+ * when BIOS is set
+ */
+ if (snoop) {
+ u8 val;
+ pci_read_config_byte(chip->pci, 0x42, &val);
+ if (!(val & 0x80) && chip->pci->revision == 0x30)
+ snoop = false;
+ }
+ break;
+ case AZX_DRIVER_ATIHDMI_NS:
+ /* new ATI HDMI requires non-snoop */
+ snoop = false;
+ break;
+ }
+
+ if (snoop != chip->snoop) {
+ snd_printk(KERN_INFO SFX "Force to %s mode\n",
+ snoop ? "snoop" : "non-snoop");
+ chip->snoop = snoop;
+ }
+}
/*
* constructor
@@ -2538,12 +2685,21 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
check_msi(chip);
chip->dev_index = dev;
INIT_WORK(&chip->irq_pending_work, azx_irq_pending_work);
+ INIT_LIST_HEAD(&chip->pcm_list);
chip->position_fix[0] = chip->position_fix[1] =
check_position_fix(chip, position_fix[dev]);
+ /* combo mode uses LPIB for playback */
+ if (chip->position_fix[0] == POS_FIX_COMBO) {
+ chip->position_fix[0] = POS_FIX_LPIB;
+ chip->position_fix[1] = POS_FIX_AUTO;
+ }
+
check_probe_mask(chip, dev);
chip->single_cmd = single_cmd;
+ chip->snoop = hda_snoop;
+ azx_check_snoop_available(chip);
if (bdl_pos_adj[dev] < 0) {
switch (chip->driver_type) {
@@ -2616,6 +2772,18 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
gcap &= ~ICH6_GCAP_64OK;
}
+ /* disable buffer size rounding to 128-byte multiples if supported */
+ if (align_buffer_size >= 0)
+ chip->align_buffer_size = !!align_buffer_size;
+ else {
+ if (chip->driver_caps & AZX_DCAPS_BUFSIZE)
+ chip->align_buffer_size = 0;
+ else if (chip->driver_caps & AZX_DCAPS_ALIGN_BUFSIZE)
+ chip->align_buffer_size = 1;
+ else
+ chip->align_buffer_size = 1;
+ }
+
/* allow 64bit DMA address if supported by H/W */
if ((gcap & ICH6_GCAP_64OK) && !pci_set_dma_mask(pci, DMA_BIT_MASK(64)))
pci_set_consistent_dma_mask(pci, DMA_BIT_MASK(64));
@@ -2638,6 +2806,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
chip->capture_streams = ULI_NUM_CAPTURE;
break;
case AZX_DRIVER_ATIHDMI:
+ case AZX_DRIVER_ATIHDMI_NS:
chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
chip->capture_streams = ATIHDMI_NUM_CAPTURE;
break;
@@ -2667,6 +2836,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
snd_printk(KERN_ERR SFX "cannot allocate BDL\n");
goto errout;
}
+ mark_pages_wc(chip, &chip->azx_dev[i].bdl, true);
}
/* allocate memory for the position buffer */
err = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV,
@@ -2676,6 +2846,7 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
snd_printk(KERN_ERR SFX "cannot allocate posbuf\n");
goto errout;
}
+ mark_pages_wc(chip, &chip->posbuf, true);
/* allocate CORB/RIRB */
err = azx_alloc_cmd_io(chip);
if (err < 0)
@@ -2817,37 +2988,57 @@ static void __devexit azx_remove(struct pci_dev *pci)
static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
/* CPT */
{ PCI_DEVICE(0x8086, 0x1c20),
- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
+ AZX_DCAPS_BUFSIZE },
/* PBG */
{ PCI_DEVICE(0x8086, 0x1d20),
- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
+ AZX_DCAPS_BUFSIZE},
/* Panther Point */
{ PCI_DEVICE(0x8086, 0x1e20),
- .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP },
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
+ AZX_DCAPS_BUFSIZE},
+ /* Lynx Point */
+ { PCI_DEVICE(0x8086, 0x8c20),
+ .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_SCH_SNOOP |
+ AZX_DCAPS_BUFSIZE},
/* SCH */
{ PCI_DEVICE(0x8086, 0x811b),
- .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP },
+ .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */
+ { PCI_DEVICE(0x8086, 0x080a),
+ .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
+ AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */
+ /* ICH */
{ PCI_DEVICE(0x8086, 0x2668),
- .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH6 */
+ .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
+ AZX_DCAPS_BUFSIZE }, /* ICH6 */
{ PCI_DEVICE(0x8086, 0x27d8),
- .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH7 */
+ .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
+ AZX_DCAPS_BUFSIZE }, /* ICH7 */
{ PCI_DEVICE(0x8086, 0x269a),
- .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ESB2 */
+ .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
+ AZX_DCAPS_BUFSIZE }, /* ESB2 */
{ PCI_DEVICE(0x8086, 0x284b),
- .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH8 */
+ .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
+ AZX_DCAPS_BUFSIZE }, /* ICH8 */
{ PCI_DEVICE(0x8086, 0x293e),
- .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH9 */
+ .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
+ AZX_DCAPS_BUFSIZE }, /* ICH9 */
{ PCI_DEVICE(0x8086, 0x293f),
- .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH9 */
+ .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
+ AZX_DCAPS_BUFSIZE }, /* ICH9 */
{ PCI_DEVICE(0x8086, 0x3a3e),
- .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH10 */
+ .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
+ AZX_DCAPS_BUFSIZE }, /* ICH10 */
{ PCI_DEVICE(0x8086, 0x3a6e),
- .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC }, /* ICH10 */
+ .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
+ AZX_DCAPS_BUFSIZE }, /* ICH10 */
/* Generic Intel */
{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID),
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_ICH },
+ .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_BUFSIZE },
/* ATI SB 450/600/700/800/900 */
{ PCI_DEVICE(0x1002, 0x437b),
.driver_data = AZX_DRIVER_ATI | AZX_DCAPS_PRESET_ATI_SB },
@@ -2885,6 +3076,14 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
.driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
{ PCI_DEVICE(0x1002, 0xaa48),
.driver_data = AZX_DRIVER_ATIHDMI | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0x9902),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaaa0),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaaa8),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI },
+ { PCI_DEVICE(0x1002, 0xaab0),
+ .driver_data = AZX_DRIVER_ATIHDMI_NS | AZX_DCAPS_PRESET_ATI_HDMI },
/* VIA VT8251/VT8237A */
{ PCI_DEVICE(0x1106, 0x3288),
.driver_data = AZX_DRIVER_VIA | AZX_DCAPS_POSFIX_VIA },
@@ -2910,12 +3109,12 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
.class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
.class_mask = 0xffffff,
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
- AZX_DCAPS_RIRB_PRE_DELAY },
+ AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
#else
/* this entry seems still valid -- i.e. without emu20kx chip */
{ PCI_DEVICE(0x1102, 0x0009),
.driver_data = AZX_DRIVER_CTX | AZX_DCAPS_CTX_WORKAROUND |
- AZX_DCAPS_RIRB_PRE_DELAY },
+ AZX_DCAPS_RIRB_PRE_DELAY | AZX_DCAPS_POSFIX_LPIB },
#endif
/* Vortex86MX */
{ PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC },
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
new file mode 100644
index 000000000000..d68948499fbc
--- /dev/null
+++ b/sound/pci/hda/hda_jack.c
@@ -0,0 +1,375 @@
+/*
+ * Jack-detection handling for HD-audio
+ *
+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/export.h>
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/jack.h>
+#include "hda_codec.h"
+#include "hda_local.h"
+#include "hda_jack.h"
+
+bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
+{
+ if (codec->no_jack_detect)
+ return false;
+ if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT))
+ return false;
+ if (!codec->ignore_misc_bit &&
+ (get_defcfg_misc(snd_hda_codec_get_pincfg(codec, nid)) &
+ AC_DEFCFG_MISC_NO_PRESENCE))
+ return false;
+ if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
+ return false;
+ return true;
+}
+EXPORT_SYMBOL_HDA(is_jack_detectable);
+
+/* execute pin sense measurement */
+static u32 read_pin_sense(struct hda_codec *codec, hda_nid_t nid)
+{
+ u32 pincap;
+
+ if (!codec->no_trigger_sense) {
+ pincap = snd_hda_query_pin_caps(codec, nid);
+ if (pincap & AC_PINCAP_TRIG_REQ) /* need trigger? */
+ snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_SET_PIN_SENSE, 0);
+ }
+ return snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_SENSE, 0);
+}
+
+/**
+ * snd_hda_jack_tbl_get - query the jack-table entry for the given NID
+ */
+struct hda_jack_tbl *
+snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct hda_jack_tbl *jack = codec->jacktbl.list;
+ int i;
+
+ if (!nid || !jack)
+ return NULL;
+ for (i = 0; i < codec->jacktbl.used; i++, jack++)
+ if (jack->nid == nid)
+ return jack;
+ return NULL;
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get);
+
+/**
+ * snd_hda_jack_tbl_get_from_tag - query the jack-table entry for the given tag
+ */
+struct hda_jack_tbl *
+snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag)
+{
+ struct hda_jack_tbl *jack = codec->jacktbl.list;
+ int i;
+
+ if (!tag || !jack)
+ return NULL;
+ for (i = 0; i < codec->jacktbl.used; i++, jack++)
+ if (jack->tag == tag)
+ return jack;
+ return NULL;
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_get_from_tag);
+
+/**
+ * snd_hda_jack_tbl_new - create a jack-table entry for the given NID
+ */
+struct hda_jack_tbl *
+snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
+ if (jack)
+ return jack;
+ snd_array_init(&codec->jacktbl, sizeof(*jack), 16);
+ jack = snd_array_new(&codec->jacktbl);
+ if (!jack)
+ return NULL;
+ jack->nid = nid;
+ jack->jack_dirty = 1;
+ jack->tag = codec->jacktbl.used;
+ return jack;
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_tbl_new);
+
+void snd_hda_jack_tbl_clear(struct hda_codec *codec)
+{
+#ifdef CONFIG_SND_HDA_INPUT_JACK
+ /* free jack instances manually when clearing/reconfiguring */
+ if (!codec->bus->shutdown && codec->jacktbl.list) {
+ struct hda_jack_tbl *jack = codec->jacktbl.list;
+ int i;
+ for (i = 0; i < codec->jacktbl.used; i++, jack++) {
+ if (jack->jack)
+ snd_device_free(codec->bus->card, jack->jack);
+ }
+ }
+#endif
+ snd_array_free(&codec->jacktbl);
+}
+
+/* update the cached value and notification flag if needed */
+static void jack_detect_update(struct hda_codec *codec,
+ struct hda_jack_tbl *jack)
+{
+ if (jack->jack_dirty || !jack->jack_detect) {
+ jack->pin_sense = read_pin_sense(codec, jack->nid);
+ jack->jack_dirty = 0;
+ }
+}
+
+/**
+ * snd_hda_set_dirty_all - Mark all the cached as dirty
+ *
+ * This function sets the dirty flag to all entries of jack table.
+ * It's called from the resume path in hda_codec.c.
+ */
+void snd_hda_jack_set_dirty_all(struct hda_codec *codec)
+{
+ struct hda_jack_tbl *jack = codec->jacktbl.list;
+ int i;
+
+ for (i = 0; i < codec->jacktbl.used; i++, jack++)
+ if (jack->nid)
+ jack->jack_dirty = 1;
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_set_dirty_all);
+
+/**
+ * snd_hda_pin_sense - execute pin sense measurement
+ * @codec: the CODEC to sense
+ * @nid: the pin NID to sense
+ *
+ * Execute necessary pin sense measurement and return its Presence Detect,
+ * Impedance, ELD Valid etc. status bits.
+ */
+u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct hda_jack_tbl *jack = snd_hda_jack_tbl_get(codec, nid);
+ if (jack) {
+ jack_detect_update(codec, jack);
+ return jack->pin_sense;
+ }
+ return read_pin_sense(codec, nid);
+}
+EXPORT_SYMBOL_HDA(snd_hda_pin_sense);
+
+#define get_jack_plug_state(sense) !!(sense & AC_PINSENSE_PRESENCE)
+
+/**
+ * snd_hda_jack_detect - query pin Presence Detect status
+ * @codec: the CODEC to sense
+ * @nid: the pin NID to sense
+ *
+ * Query and return the pin's Presence Detect status.
+ */
+int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid)
+{
+ u32 sense = snd_hda_pin_sense(codec, nid);
+ return get_jack_plug_state(sense);
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_detect);
+
+/**
+ * snd_hda_jack_detect_enable - enable the jack-detection
+ */
+int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
+ unsigned char action)
+{
+ struct hda_jack_tbl *jack = snd_hda_jack_tbl_new(codec, nid);
+ if (!jack)
+ return -ENOMEM;
+ if (jack->jack_detect)
+ return 0; /* already registered */
+ jack->jack_detect = 1;
+ if (action)
+ jack->action = action;
+ return snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ AC_USRSP_EN | jack->tag);
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_detect_enable);
+
+/**
+ * snd_hda_jack_report_sync - sync the states of all jacks and report if changed
+ */
+void snd_hda_jack_report_sync(struct hda_codec *codec)
+{
+ struct hda_jack_tbl *jack = codec->jacktbl.list;
+ int i, state;
+
+ for (i = 0; i < codec->jacktbl.used; i++, jack++)
+ if (jack->nid) {
+ jack_detect_update(codec, jack);
+ if (!jack->kctl)
+ continue;
+ state = get_jack_plug_state(jack->pin_sense);
+ snd_kctl_jack_report(codec->bus->card, jack->kctl, state);
+#ifdef CONFIG_SND_HDA_INPUT_JACK
+ if (jack->jack)
+ snd_jack_report(jack->jack,
+ state ? jack->type : 0);
+#endif
+ }
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_report_sync);
+
+#ifdef CONFIG_SND_HDA_INPUT_JACK
+/* guess the jack type from the pin-config */
+static int get_input_jack_type(struct hda_codec *codec, hda_nid_t nid)
+{
+ unsigned int def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ switch (get_defcfg_device(def_conf)) {
+ case AC_JACK_LINE_OUT:
+ case AC_JACK_SPEAKER:
+ return SND_JACK_LINEOUT;
+ case AC_JACK_HP_OUT:
+ return SND_JACK_HEADPHONE;
+ case AC_JACK_SPDIF_OUT:
+ case AC_JACK_DIG_OTHER_OUT:
+ return SND_JACK_AVOUT;
+ case AC_JACK_MIC_IN:
+ return SND_JACK_MICROPHONE;
+ default:
+ return SND_JACK_LINEIN;
+ }
+}
+
+static void hda_free_jack_priv(struct snd_jack *jack)
+{
+ struct hda_jack_tbl *jacks = jack->private_data;
+ jacks->nid = 0;
+ jacks->jack = NULL;
+}
+#endif
+
+/**
+ * snd_hda_jack_add_kctl - Add a kctl for the given pin
+ *
+ * This assigns a jack-detection kctl to the given pin. The kcontrol
+ * will have the given name and index.
+ */
+int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
+ const char *name, int idx)
+{
+ struct hda_jack_tbl *jack;
+ struct snd_kcontrol *kctl;
+ int err, state;
+
+ jack = snd_hda_jack_tbl_new(codec, nid);
+ if (!jack)
+ return 0;
+ if (jack->kctl)
+ return 0; /* already created */
+ kctl = snd_kctl_jack_new(name, idx, codec);
+ if (!kctl)
+ return -ENOMEM;
+ err = snd_hda_ctl_add(codec, nid, kctl);
+ if (err < 0)
+ return err;
+ jack->kctl = kctl;
+ state = snd_hda_jack_detect(codec, nid);
+ snd_kctl_jack_report(codec->bus->card, kctl, state);
+#ifdef CONFIG_SND_HDA_INPUT_JACK
+ jack->type = get_input_jack_type(codec, nid);
+ err = snd_jack_new(codec->bus->card, name, jack->type, &jack->jack);
+ if (err < 0)
+ return err;
+ jack->jack->private_data = jack;
+ jack->jack->private_free = hda_free_jack_priv;
+ snd_jack_report(jack->jack, state ? jack->type : 0);
+#endif
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctl);
+
+static int add_jack_kctl(struct hda_codec *codec, hda_nid_t nid,
+ const struct auto_pin_cfg *cfg,
+ char *lastname, int *lastidx)
+{
+ unsigned int def_conf, conn;
+ char name[44];
+ int idx, err;
+
+ if (!nid)
+ return 0;
+ if (!is_jack_detectable(codec, nid))
+ return 0;
+ def_conf = snd_hda_codec_get_pincfg(codec, nid);
+ conn = get_defcfg_connect(def_conf);
+ if (conn != AC_JACK_PORT_COMPLEX)
+ return 0;
+
+ snd_hda_get_pin_label(codec, nid, cfg, name, sizeof(name), &idx);
+ if (!strcmp(name, lastname) && idx == *lastidx)
+ idx++;
+ strncpy(lastname, name, 44);
+ *lastidx = idx;
+ err = snd_hda_jack_add_kctl(codec, nid, name, idx);
+ if (err < 0)
+ return err;
+ return snd_hda_jack_detect_enable(codec, nid, 0);
+}
+
+/**
+ * snd_hda_jack_add_kctls - Add kctls for all pins included in the given pincfg
+ */
+int snd_hda_jack_add_kctls(struct hda_codec *codec,
+ const struct auto_pin_cfg *cfg)
+{
+ const hda_nid_t *p;
+ int i, err, lastidx = 0;
+ char lastname[44] = "";
+
+ for (i = 0, p = cfg->line_out_pins; i < cfg->line_outs; i++, p++) {
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
+ if (err < 0)
+ return err;
+ }
+ for (i = 0, p = cfg->hp_pins; i < cfg->hp_outs; i++, p++) {
+ if (*p == *cfg->line_out_pins) /* might be duplicated */
+ break;
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
+ if (err < 0)
+ return err;
+ }
+ for (i = 0, p = cfg->speaker_pins; i < cfg->speaker_outs; i++, p++) {
+ if (*p == *cfg->line_out_pins) /* might be duplicated */
+ break;
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
+ if (err < 0)
+ return err;
+ }
+ for (i = 0; i < cfg->num_inputs; i++) {
+ err = add_jack_kctl(codec, cfg->inputs[i].pin, cfg, lastname, &lastidx);
+ if (err < 0)
+ return err;
+ }
+ for (i = 0, p = cfg->dig_out_pins; i < cfg->dig_outs; i++, p++) {
+ err = add_jack_kctl(codec, *p, cfg, lastname, &lastidx);
+ if (err < 0)
+ return err;
+ }
+ err = add_jack_kctl(codec, cfg->dig_in_pin, cfg, lastname, &lastidx);
+ if (err < 0)
+ return err;
+ err = add_jack_kctl(codec, cfg->mono_out_pin, cfg, lastname, &lastidx);
+ if (err < 0)
+ return err;
+ return 0;
+}
+EXPORT_SYMBOL_HDA(snd_hda_jack_add_kctls);
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
new file mode 100644
index 000000000000..c66655cf413a
--- /dev/null
+++ b/sound/pci/hda/hda_jack.h
@@ -0,0 +1,75 @@
+/*
+ * Jack-detection handling for HD-audio
+ *
+ * Copyright (c) 2011 Takashi Iwai <tiwai@suse.de>
+ *
+ * This driver is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef __SOUND_HDA_JACK_H
+#define __SOUND_HDA_JACK_H
+
+struct hda_jack_tbl {
+ hda_nid_t nid;
+ unsigned char action; /* event action (0 = none) */
+ unsigned char tag; /* unsol event tag */
+ unsigned int private_data; /* arbitrary data */
+ /* jack-detection stuff */
+ unsigned int pin_sense; /* cached pin-sense value */
+ unsigned int jack_detect:1; /* capable of jack-detection? */
+ unsigned int jack_dirty:1; /* needs to update? */
+ struct snd_kcontrol *kctl; /* assigned kctl for jack-detection */
+#ifdef CONFIG_SND_HDA_INPUT_JACK
+ int type;
+ struct snd_jack *jack;
+#endif
+};
+
+struct hda_jack_tbl *
+snd_hda_jack_tbl_get(struct hda_codec *codec, hda_nid_t nid);
+struct hda_jack_tbl *
+snd_hda_jack_tbl_get_from_tag(struct hda_codec *codec, unsigned char tag);
+
+struct hda_jack_tbl *
+snd_hda_jack_tbl_new(struct hda_codec *codec, hda_nid_t nid);
+void snd_hda_jack_tbl_clear(struct hda_codec *codec);
+
+/**
+ * snd_hda_jack_get_action - get jack-tbl entry for the tag
+ *
+ * Call this from the unsol event handler to get the assigned action for the
+ * event. This will mark the dirty flag for the later reporting, too.
+ */
+static inline unsigned char
+snd_hda_jack_get_action(struct hda_codec *codec, unsigned int tag)
+{
+ struct hda_jack_tbl *jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
+ if (jack) {
+ jack->jack_dirty = 1;
+ return jack->action;
+ }
+ return 0;
+}
+
+void snd_hda_jack_set_dirty_all(struct hda_codec *codec);
+
+int snd_hda_jack_detect_enable(struct hda_codec *codec, hda_nid_t nid,
+ unsigned char action);
+
+u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
+int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
+
+bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid);
+
+int snd_hda_jack_add_kctl(struct hda_codec *codec, hda_nid_t nid,
+ const char *name, int idx);
+int snd_hda_jack_add_kctls(struct hda_codec *codec,
+ const struct auto_pin_cfg *cfg);
+
+void snd_hda_jack_report_sync(struct hda_codec *codec);
+
+
+#endif /* __SOUND_HDA_JACK_H */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 2e7ac31afa8d..0ec9248165bc 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -139,10 +139,36 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int *tlv);
struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name);
-int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
- unsigned int *tlv, const char * const *slaves);
+int __snd_hda_add_vmaster(struct hda_codec *codec, char *name,
+ unsigned int *tlv, const char * const *slaves,
+ const char *suffix, bool init_slave_vol,
+ struct snd_kcontrol **ctl_ret);
+#define snd_hda_add_vmaster(codec, name, tlv, slaves, suffix) \
+ __snd_hda_add_vmaster(codec, name, tlv, slaves, suffix, true, NULL)
int snd_hda_codec_reset(struct hda_codec *codec);
+enum {
+ HDA_VMUTE_OFF,
+ HDA_VMUTE_ON,
+ HDA_VMUTE_FOLLOW_MASTER,
+};
+
+struct hda_vmaster_mute_hook {
+ /* below two fields must be filled by the caller of
+ * snd_hda_add_vmaster_hook() beforehand
+ */
+ struct snd_kcontrol *sw_kctl;
+ void (*hook)(void *, int);
+ /* below are initialized automatically */
+ unsigned int mute_mode; /* HDA_VMUTE_XXX */
+ struct hda_codec *codec;
+};
+
+int snd_hda_add_vmaster_hook(struct hda_codec *codec,
+ struct hda_vmaster_mute_hook *hook,
+ bool expose_enum_ctl);
+void snd_hda_sync_vmaster_hook(struct hda_vmaster_mute_hook *hook);
+
/* amp value bits */
#define HDA_AMP_MUTE 0x80
#define HDA_AMP_UNMUTE 0x00
@@ -267,11 +293,14 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
enum { HDA_FRONT, HDA_REAR, HDA_CLFE, HDA_SIDE }; /* index for dac_nidx */
enum { HDA_DIG_NONE, HDA_DIG_EXCLUSIVE, HDA_DIG_ANALOG_DUP }; /* dig_out_used */
+#define HDA_MAX_OUTS 5
+
struct hda_multi_out {
int num_dacs; /* # of DACs, must be more than 1 */
const hda_nid_t *dac_nids; /* DAC list */
hda_nid_t hp_nid; /* optional DAC for HP, 0 when not exists */
- hda_nid_t extra_out_nid[3]; /* optional DACs, 0 when not exists */
+ hda_nid_t hp_out_nid[HDA_MAX_OUTS]; /* DACs for multiple HPs */
+ hda_nid_t extra_out_nid[HDA_MAX_OUTS]; /* other (e.g. speaker) DACs */
hda_nid_t dig_out_nid; /* digital out audio widget */
const hda_nid_t *slave_dig_outs;
int max_channels; /* currently supported analog channels */
@@ -333,9 +362,6 @@ int snd_hda_codec_proc_new(struct hda_codec *codec);
static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
#endif
-#define SND_PRINT_RATES_ADVISED_BUFSIZE 80
-void snd_print_pcm_rates(int pcm, char *buf, int buflen);
-
#define SND_PRINT_BITS_ADVISED_BUFSIZE 16
void snd_print_pcm_bits(int pcm, char *buf, int buflen);
@@ -385,7 +411,7 @@ enum {
AUTO_PIN_HP_OUT
};
-#define AUTO_CFG_MAX_OUTS 5
+#define AUTO_CFG_MAX_OUTS HDA_MAX_OUTS
#define AUTO_CFG_MAX_INS 8
struct auto_pin_cfg_item {
@@ -394,11 +420,12 @@ struct auto_pin_cfg_item {
};
struct auto_pin_cfg;
-const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin,
- int check_location);
const char *hda_get_autocfg_input_label(struct hda_codec *codec,
const struct auto_pin_cfg *cfg,
int input);
+int snd_hda_get_pin_label(struct hda_codec *codec, hda_nid_t nid,
+ const struct auto_pin_cfg *cfg,
+ char *label, int maxlen, int *indexp);
int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label,
int index, int *type_index_ret);
@@ -442,10 +469,21 @@ struct auto_pin_cfg {
(cfg & AC_DEFCFG_SEQUENCE)
#define get_defcfg_device(cfg) \
((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
+#define get_defcfg_misc(cfg) \
+ ((cfg & AC_DEFCFG_MISC) >> AC_DEFCFG_MISC_SHIFT)
+
+/* bit-flags for snd_hda_parse_pin_def_config() behavior */
+#define HDA_PINCFG_NO_HP_FIXUP (1 << 0) /* no HP-split */
+#define HDA_PINCFG_NO_LO_FIXUP (1 << 1) /* don't take other outs as LO */
+
+int snd_hda_parse_pin_defcfg(struct hda_codec *codec,
+ struct auto_pin_cfg *cfg,
+ const hda_nid_t *ignore_nids,
+ unsigned int cond_flags);
-int snd_hda_parse_pin_def_config(struct hda_codec *codec,
- struct auto_pin_cfg *cfg,
- const hda_nid_t *ignore_nids);
+/* older function */
+#define snd_hda_parse_pin_def_config(codec, cfg, ignore) \
+ snd_hda_parse_pin_defcfg(codec, cfg, ignore, 0)
/* amp values */
#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
@@ -476,7 +514,12 @@ static inline u32 get_wcaps(struct hda_codec *codec, hda_nid_t nid)
}
/* get the widget type from widget capability bits */
-#define get_wcaps_type(wcaps) (((wcaps) & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT)
+static inline int get_wcaps_type(unsigned int wcaps)
+{
+ if (!wcaps)
+ return -1; /* invalid type */
+ return (wcaps & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
+}
static inline unsigned int get_wcaps_channels(u32 wcaps)
{
@@ -492,14 +535,8 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps);
u32 snd_hda_query_pin_caps(struct hda_codec *codec, hda_nid_t nid);
-u32 snd_hda_pin_sense(struct hda_codec *codec, hda_nid_t nid);
-int snd_hda_jack_detect(struct hda_codec *codec, hda_nid_t nid);
-
-static inline bool is_jack_detectable(struct hda_codec *codec, hda_nid_t nid)
-{
- return (snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_PRES_DETECT) &&
- (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP);
-}
+int snd_hda_override_pin_caps(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int caps);
/* flags for hda_nid_item */
#define HDA_NID_ITEM_AMP (1<<0)
@@ -589,7 +626,8 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
#define get_amp_nid_(pv) ((pv) & 0xffff)
#define get_amp_nid(kc) get_amp_nid_((kc)->private_value)
#define get_amp_channels(kc) (((kc)->private_value >> 16) & 0x3)
-#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
+#define get_amp_direction_(pv) (((pv) >> 18) & 0x1)
+#define get_amp_direction(kc) get_amp_direction_((kc)->private_value)
#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
#define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f)
#define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1)
@@ -607,6 +645,7 @@ struct cea_sad {
};
#define ELD_FIXED_BYTES 20
+#define ELD_MAX_SIZE 256
#define ELD_MAX_MNL 16
#define ELD_MAX_SAD 16
@@ -631,6 +670,10 @@ struct hdmi_eld {
int spk_alloc;
int sad_count;
struct cea_sad sad[ELD_MAX_SAD];
+ /*
+ * all fields above eld_buffer will be cleared before updating ELD
+ */
+ char eld_buffer[ELD_MAX_SIZE];
#ifdef CONFIG_PROC_FS
struct snd_info_entry *proc_entry;
#endif
@@ -662,28 +705,4 @@ static inline void snd_hda_eld_proc_free(struct hda_codec *codec,
#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
-/*
- * Input-jack notification support
- */
-#ifdef CONFIG_SND_HDA_INPUT_JACK
-int snd_hda_input_jack_add(struct hda_codec *codec, hda_nid_t nid, int type,
- const char *name);
-void snd_hda_input_jack_report(struct hda_codec *codec, hda_nid_t nid);
-void snd_hda_input_jack_free(struct hda_codec *codec);
-#else /* CONFIG_SND_HDA_INPUT_JACK */
-static inline int snd_hda_input_jack_add(struct hda_codec *codec,
- hda_nid_t nid, int type,
- const char *name)
-{
- return 0;
-}
-static inline void snd_hda_input_jack_report(struct hda_codec *codec,
- hda_nid_t nid)
-{
-}
-static inline void snd_hda_input_jack_free(struct hda_codec *codec)
-{
-}
-#endif /* CONFIG_SND_HDA_INPUT_JACK */
-
#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 2be57b051aa2..254ab5204603 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -54,6 +54,8 @@ static const char *get_wid_type_name(unsigned int wid_value)
[AC_WID_BEEP] = "Beep Generator Widget",
[AC_WID_VENDOR] = "Vendor Defined Widget",
};
+ if (wid_value == -1)
+ return "UNKNOWN Widget";
wid_value &= 0xf;
if (names[wid_value])
return names[wid_value];
@@ -152,12 +154,18 @@ static void print_amp_vals(struct snd_info_buffer *buffer,
static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
{
- char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
+ static unsigned int rates[] = {
+ 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
+ 96000, 176400, 192000, 384000
+ };
+ int i;
pcm &= AC_SUPPCM_RATES;
snd_iprintf(buffer, " rates [0x%x]:", pcm);
- snd_print_pcm_rates(pcm, buf, sizeof(buf));
- snd_iprintf(buffer, "%s\n", buf);
+ for (i = 0; i < ARRAY_SIZE(rates); i++)
+ if (pcm & (1 << i))
+ snd_iprintf(buffer, " %d", rates[i]);
+ snd_iprintf(buffer, "\n");
}
static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
diff --git a/sound/pci/hda/hda_trace.h b/sound/pci/hda/hda_trace.h
new file mode 100644
index 000000000000..9884871ddb00
--- /dev/null
+++ b/sound/pci/hda/hda_trace.h
@@ -0,0 +1,117 @@
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM hda
+#define TRACE_INCLUDE_FILE hda_trace
+
+#if !defined(_TRACE_HDA_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_HDA_H
+
+#include <linux/tracepoint.h>
+
+struct hda_bus;
+struct hda_codec;
+
+DECLARE_EVENT_CLASS(hda_cmd,
+
+ TP_PROTO(struct hda_codec *codec, unsigned int val),
+
+ TP_ARGS(codec, val),
+
+ TP_STRUCT__entry(
+ __field( unsigned int, card )
+ __field( unsigned int, addr )
+ __field( unsigned int, val )
+ ),
+
+ TP_fast_assign(
+ __entry->card = (codec)->bus->card->number;
+ __entry->addr = (codec)->addr;
+ __entry->val = (val);
+ ),
+
+ TP_printk("[%d:%d] val=%x", __entry->card, __entry->addr, __entry->val)
+);
+
+DEFINE_EVENT(hda_cmd, hda_send_cmd,
+ TP_PROTO(struct hda_codec *codec, unsigned int val),
+ TP_ARGS(codec, val)
+);
+
+DEFINE_EVENT(hda_cmd, hda_get_response,
+ TP_PROTO(struct hda_codec *codec, unsigned int val),
+ TP_ARGS(codec, val)
+);
+
+TRACE_EVENT(hda_bus_reset,
+
+ TP_PROTO(struct hda_bus *bus),
+
+ TP_ARGS(bus),
+
+ TP_STRUCT__entry(
+ __field( unsigned int, card )
+ ),
+
+ TP_fast_assign(
+ __entry->card = (bus)->card->number;
+ ),
+
+ TP_printk("[%d]", __entry->card)
+);
+
+DECLARE_EVENT_CLASS(hda_power,
+
+ TP_PROTO(struct hda_codec *codec),
+
+ TP_ARGS(codec),
+
+ TP_STRUCT__entry(
+ __field( unsigned int, card )
+ __field( unsigned int, addr )
+ ),
+
+ TP_fast_assign(
+ __entry->card = (codec)->bus->card->number;
+ __entry->addr = (codec)->addr;
+ ),
+
+ TP_printk("[%d:%d]", __entry->card, __entry->addr)
+);
+
+DEFINE_EVENT(hda_power, hda_power_down,
+ TP_PROTO(struct hda_codec *codec),
+ TP_ARGS(codec)
+);
+
+DEFINE_EVENT(hda_power, hda_power_up,
+ TP_PROTO(struct hda_codec *codec),
+ TP_ARGS(codec)
+);
+
+TRACE_EVENT(hda_unsol_event,
+
+ TP_PROTO(struct hda_bus *bus, u32 res, u32 res_ex),
+
+ TP_ARGS(bus, res, res_ex),
+
+ TP_STRUCT__entry(
+ __field( unsigned int, card )
+ __field( u32, res )
+ __field( u32, res_ex )
+ ),
+
+ TP_fast_assign(
+ __entry->card = (bus)->card->number;
+ __entry->res = res;
+ __entry->res_ex = res_ex;
+ ),
+
+ TP_printk("[%d] res=%x, res_ex=%x", __entry->card,
+ __entry->res, __entry->res_ex)
+);
+
+#endif /* _TRACE_HDA_H */
+
+/* This part must be outside protection */
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#include <trace/define_trace.h>
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 8648917acffb..7143393927da 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -23,11 +23,13 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
#include "hda_beep.h"
+#include "hda_jack.h"
struct ad198x_spec {
const struct snd_kcontrol_new *mixers[6];
@@ -48,6 +50,8 @@ struct ad198x_spec {
const hda_nid_t *alt_dac_nid;
const struct hda_pcm_stream *stream_analog_alt_playback;
+ int independent_hp;
+ int num_active_streams;
/* capture */
unsigned int num_adc_nids;
@@ -78,6 +82,7 @@ struct ad198x_spec {
unsigned int inv_jack_detect: 1;/* inverted jack-detection */
unsigned int inv_eapd: 1; /* inverted EAPD implementation */
unsigned int analog_beep: 1; /* analog beep input present */
+ unsigned int avoid_init_slave_vol:1;
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
@@ -133,51 +138,17 @@ static int ad198x_init(struct hda_codec *codec)
return 0;
}
-static const char * const ad_slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "Headphone Playback Volume",
- "Mono Playback Volume",
- "Speaker Playback Volume",
- "IEC958 Playback Volume",
+static const char * const ad_slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side",
+ "Headphone", "Mono", "Speaker", "IEC958",
NULL
};
-static const char * const ad_slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "Headphone Playback Switch",
- "Mono Playback Switch",
- "Speaker Playback Switch",
- "IEC958 Playback Switch",
+static const char * const ad1988_6stack_fp_slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side", "IEC958",
NULL
};
-static const char * const ad1988_6stack_fp_slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "IEC958 Playback Volume",
- NULL
-};
-
-static const char * const ad1988_6stack_fp_slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "IEC958 Playback Switch",
- NULL
-};
static void ad198x_free_kctls(struct hda_codec *codec);
#ifdef CONFIG_SND_HDA_INPUT_BEEP
@@ -253,10 +224,12 @@ static int ad198x_build_controls(struct hda_codec *codec)
unsigned int vmaster_tlv[4];
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
HDA_OUTPUT, vmaster_tlv);
- err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+ err = __snd_hda_add_vmaster(codec, "Master Playback Volume",
vmaster_tlv,
(spec->slave_vols ?
- spec->slave_vols : ad_slave_vols));
+ spec->slave_vols : ad_slave_pfxs),
+ "Playback Volume",
+ !spec->avoid_init_slave_vol, NULL);
if (err < 0)
return err;
}
@@ -264,7 +237,8 @@ static int ad198x_build_controls(struct hda_codec *codec)
err = snd_hda_add_vmaster(codec, "Master Playback Switch",
NULL,
(spec->slave_sws ?
- spec->slave_sws : ad_slave_sws));
+ spec->slave_sws : ad_slave_pfxs),
+ "Playback Switch");
if (err < 0)
return err;
}
@@ -302,6 +276,72 @@ static int ad198x_check_power_status(struct hda_codec *codec, hda_nid_t nid)
}
#endif
+static void activate_ctl(struct hda_codec *codec, const char *name, int active)
+{
+ struct snd_kcontrol *ctl = snd_hda_find_mixer_ctl(codec, name);
+ if (ctl) {
+ ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ ctl->vd[0].access |= active ? 0 :
+ SNDRV_CTL_ELEM_ACCESS_INACTIVE;
+ ctl->vd[0].access &= ~SNDRV_CTL_ELEM_ACCESS_WRITE;
+ ctl->vd[0].access |= active ?
+ SNDRV_CTL_ELEM_ACCESS_WRITE : 0;
+ snd_ctl_notify(codec->bus->card,
+ SNDRV_CTL_EVENT_MASK_INFO, &ctl->id);
+ }
+}
+
+static void set_stream_active(struct hda_codec *codec, bool active)
+{
+ struct ad198x_spec *spec = codec->spec;
+ if (active)
+ spec->num_active_streams++;
+ else
+ spec->num_active_streams--;
+ activate_ctl(codec, "Independent HP", spec->num_active_streams == 0);
+}
+
+static int ad1988_independent_hp_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ static const char * const texts[] = { "OFF", "ON", NULL};
+ int index;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
+ uinfo->count = 1;
+ uinfo->value.enumerated.items = 2;
+ index = uinfo->value.enumerated.item;
+ if (index >= 2)
+ index = 1;
+ strcpy(uinfo->value.enumerated.name, texts[index]);
+ return 0;
+}
+
+static int ad1988_independent_hp_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+ ucontrol->value.enumerated.item[0] = spec->independent_hp;
+ return 0;
+}
+
+static int ad1988_independent_hp_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct ad198x_spec *spec = codec->spec;
+ unsigned int select = ucontrol->value.enumerated.item[0];
+ if (spec->independent_hp != select) {
+ spec->independent_hp = select;
+ if (spec->independent_hp)
+ spec->multiout.hp_nid = 0;
+ else
+ spec->multiout.hp_nid = spec->alt_dac_nid[0];
+ return 1;
+ }
+ return 0;
+}
+
/*
* Analog playback callbacks
*/
@@ -310,8 +350,15 @@ static int ad198x_playback_pcm_open(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream)
{
struct ad198x_spec *spec = codec->spec;
- return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
+ int err;
+ set_stream_active(codec, true);
+ err = snd_hda_multi_out_analog_open(codec, &spec->multiout, substream,
hinfo);
+ if (err < 0) {
+ set_stream_active(codec, false);
+ return err;
+ }
+ return 0;
}
static int ad198x_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -333,11 +380,41 @@ static int ad198x_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
}
+static int ad198x_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ set_stream_active(codec, false);
+ return 0;
+}
+
+static int ad1988_alt_playback_pcm_open(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ struct ad198x_spec *spec = codec->spec;
+ if (!spec->independent_hp)
+ return -EBUSY;
+ set_stream_active(codec, true);
+ return 0;
+}
+
+static int ad1988_alt_playback_pcm_close(struct hda_pcm_stream *hinfo,
+ struct hda_codec *codec,
+ struct snd_pcm_substream *substream)
+{
+ set_stream_active(codec, false);
+ return 0;
+}
+
static const struct hda_pcm_stream ad198x_pcm_analog_alt_playback = {
.substreams = 1,
.channels_min = 2,
.channels_max = 2,
- /* NID is set in ad198x_build_pcms */
+ .ops = {
+ .open = ad1988_alt_playback_pcm_open,
+ .close = ad1988_alt_playback_pcm_close
+ },
};
/*
@@ -402,7 +479,6 @@ static int ad198x_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
-
/*
*/
static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
@@ -413,7 +489,8 @@ static const struct hda_pcm_stream ad198x_pcm_analog_playback = {
.ops = {
.open = ad198x_playback_pcm_open,
.prepare = ad198x_playback_pcm_prepare,
- .cleanup = ad198x_playback_pcm_cleanup
+ .cleanup = ad198x_playback_pcm_cleanup,
+ .close = ad198x_playback_pcm_close
},
};
@@ -2058,7 +2135,6 @@ static int patch_ad1981(struct hda_codec *codec)
enum {
AD1988_6STACK,
AD1988_6STACK_DIG,
- AD1988_6STACK_DIG_FP,
AD1988_3STACK,
AD1988_3STACK_DIG,
AD1988_LAPTOP,
@@ -2168,6 +2244,17 @@ static int ad198x_ch_mode_put(struct snd_kcontrol *kcontrol,
return err;
}
+static const struct snd_kcontrol_new ad1988_hp_mixers[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Independent HP",
+ .info = ad1988_independent_hp_info,
+ .get = ad1988_independent_hp_get,
+ .put = ad1988_independent_hp_put,
+ },
+ { } /* end */
+};
+
/* 6-stack mode */
static const struct snd_kcontrol_new ad1988_6stack_mixers1[] = {
HDA_CODEC_VOLUME("Front Playback Volume", 0x04, 0x0, HDA_OUTPUT),
@@ -2188,6 +2275,7 @@ static const struct snd_kcontrol_new ad1988_6stack_mixers1_rev2[] = {
};
static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
HDA_BIND_MUTE("Surround Playback Switch", 0x2a, 2, HDA_INPUT),
HDA_BIND_MUTE_MONO("Center Playback Switch", 0x27, 1, 2, HDA_INPUT),
@@ -2210,13 +2298,6 @@ static const struct snd_kcontrol_new ad1988_6stack_mixers2[] = {
HDA_CODEC_VOLUME("Front Mic Boost Volume", 0x39, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Boost Volume", 0x3c, 0x0, HDA_OUTPUT),
-
- { } /* end */
-};
-
-static const struct snd_kcontrol_new ad1988_6stack_fp_mixers[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
-
{ } /* end */
};
@@ -2238,6 +2319,7 @@ static const struct snd_kcontrol_new ad1988_3stack_mixers1_rev2[] = {
};
static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_BIND_MUTE("Front Playback Switch", 0x29, 2, HDA_INPUT),
HDA_BIND_MUTE("Surround Playback Switch", 0x2c, 2, HDA_INPUT),
HDA_BIND_MUTE_MONO("Center Playback Switch", 0x26, 1, 2, HDA_INPUT),
@@ -2272,6 +2354,7 @@ static const struct snd_kcontrol_new ad1988_3stack_mixers2[] = {
/* laptop mode */
static const struct snd_kcontrol_new ad1988_laptop_mixers[] = {
+ HDA_CODEC_VOLUME("Headphone Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("PCM Playback Volume", 0x04, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x29, 0x0, HDA_INPUT),
HDA_BIND_MUTE("Mono Playback Switch", 0x1e, 2, HDA_INPUT),
@@ -2446,7 +2529,7 @@ static const struct hda_verb ad1988_6stack_init_verbs[] = {
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* Port-A front headphon path */
- {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
+ {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -2594,7 +2677,7 @@ static const struct hda_verb ad1988_3stack_init_verbs[] = {
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* Port-A front headphon path */
- {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
+ {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -2669,7 +2752,7 @@ static const struct hda_verb ad1988_laptop_init_verbs[] = {
{0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
{0x0a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
/* Port-A front headphon path */
- {0x37, AC_VERB_SET_CONNECT_SEL, 0x01}, /* DAC1:04h */
+ {0x37, AC_VERB_SET_CONNECT_SEL, 0x00}, /* DAC0:03h */
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
{0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
@@ -2782,11 +2865,11 @@ static inline hda_nid_t ad1988_idx_to_dac(struct hda_codec *codec, int idx)
{
static const hda_nid_t idx_to_dac[8] = {
/* A B C D E F G H */
- 0x04, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
+ 0x03, 0x06, 0x05, 0x04, 0x0a, 0x06, 0x05, 0x0a
};
static const hda_nid_t idx_to_dac_rev2[8] = {
/* A B C D E F G H */
- 0x04, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
+ 0x03, 0x05, 0x0a, 0x04, 0x06, 0x05, 0x0a, 0x06
};
if (is_rev2(codec))
return idx_to_dac_rev2[idx];
@@ -3023,8 +3106,8 @@ static void ad1988_auto_set_output_and_unmute(struct hda_codec *codec,
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
switch (nid) {
- case 0x11: /* port-A - DAC 04 */
- snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x01);
+ case 0x11: /* port-A - DAC 03 */
+ snd_hda_codec_write(codec, 0x37, 0, AC_VERB_SET_CONNECT_SEL, 0x00);
break;
case 0x14: /* port-B - DAC 06 */
snd_hda_codec_write(codec, 0x30, 0, AC_VERB_SET_CONNECT_SEL, 0x02);
@@ -3150,7 +3233,6 @@ static int ad1988_auto_init(struct hda_codec *codec)
static const char * const ad1988_models[AD1988_MODEL_LAST] = {
[AD1988_6STACK] = "6stack",
[AD1988_6STACK_DIG] = "6stack-dig",
- [AD1988_6STACK_DIG_FP] = "6stack-dig-fp",
[AD1988_3STACK] = "3stack",
[AD1988_3STACK_DIG] = "3stack-dig",
[AD1988_LAPTOP] = "laptop",
@@ -3208,10 +3290,11 @@ static int patch_ad1988(struct hda_codec *codec)
}
set_beep_amp(spec, 0x10, 0, HDA_OUTPUT);
+ if (!spec->multiout.hp_nid)
+ spec->multiout.hp_nid = ad1988_alt_dac_nid[0];
switch (board_config) {
case AD1988_6STACK:
case AD1988_6STACK_DIG:
- case AD1988_6STACK_DIG_FP:
spec->multiout.max_channels = 8;
spec->multiout.num_dacs = 4;
if (is_rev2(codec))
@@ -3227,19 +3310,7 @@ static int patch_ad1988(struct hda_codec *codec)
spec->mixers[1] = ad1988_6stack_mixers2;
spec->num_init_verbs = 1;
spec->init_verbs[0] = ad1988_6stack_init_verbs;
- if (board_config == AD1988_6STACK_DIG_FP) {
- spec->num_mixers++;
- spec->mixers[2] = ad1988_6stack_fp_mixers;
- spec->num_init_verbs++;
- spec->init_verbs[1] = ad1988_6stack_fp_init_verbs;
- spec->slave_vols = ad1988_6stack_fp_slave_vols;
- spec->slave_sws = ad1988_6stack_fp_slave_sws;
- spec->alt_dac_nid = ad1988_alt_dac_nid;
- spec->stream_analog_alt_playback =
- &ad198x_pcm_analog_alt_playback;
- }
- if ((board_config == AD1988_6STACK_DIG) ||
- (board_config == AD1988_6STACK_DIG_FP)) {
+ if (board_config == AD1988_6STACK_DIG) {
spec->multiout.dig_out_nid = AD1988_SPDIF_OUT;
spec->dig_in_nid = AD1988_SPDIF_IN;
}
@@ -3282,6 +3353,15 @@ static int patch_ad1988(struct hda_codec *codec)
break;
}
+ if (spec->autocfg.hp_pins[0]) {
+ spec->mixers[spec->num_mixers++] = ad1988_hp_mixers;
+ spec->slave_vols = ad1988_6stack_fp_slave_pfxs;
+ spec->slave_sws = ad1988_6stack_fp_slave_pfxs;
+ spec->alt_dac_nid = ad1988_alt_dac_nid;
+ spec->stream_analog_alt_playback =
+ &ad198x_pcm_analog_alt_playback;
+ }
+
spec->num_adc_nids = ARRAY_SIZE(ad1988_adc_nids);
spec->adc_nids = ad1988_adc_nids;
spec->capsrc_nids = ad1988_capsrc_nids;
@@ -3484,16 +3564,8 @@ static const struct hda_amp_list ad1884_loopbacks[] = {
#endif
static const char * const ad1884_slave_vols[] = {
- "PCM Playback Volume",
- "Mic Playback Volume",
- "Mono Playback Volume",
- "Front Mic Playback Volume",
- "Mic Playback Volume",
- "CD Playback Volume",
- "Internal Mic Playback Volume",
- "Docking Mic Playback Volume",
- /* "Beep Playback Volume", */
- "IEC958 Playback Volume",
+ "PCM", "Mic", "Mono", "Front Mic", "Mic", "CD",
+ "Internal Mic", "Docking Mic", /* "Beep", */ "IEC958",
NULL
};
@@ -3534,6 +3606,8 @@ static int patch_ad1884(struct hda_codec *codec)
spec->vmaster_nid = 0x04;
/* we need to cover all playback volumes */
spec->slave_vols = ad1884_slave_vols;
+ /* slaves may contain input volumes, so we can't raise to 0dB blindly */
+ spec->avoid_init_slave_vol = 1;
codec->patch_ops = ad198x_patch_ops;
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c
index 6b406840846e..09ccfabb4a17 100644
--- a/sound/pci/hda/patch_ca0110.c
+++ b/sound/pci/hda/patch_ca0110.c
@@ -22,6 +22,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
@@ -40,7 +41,7 @@ struct ca0110_spec {
hda_nid_t dig_out;
hda_nid_t dig_in;
unsigned int num_inputs;
- const char *input_labels[AUTO_PIN_LAST];
+ char input_labels[AUTO_PIN_LAST][32];
struct hda_pcm pcm_rec[2]; /* PCM information */
};
@@ -475,7 +476,9 @@ static void parse_input(struct hda_codec *codec)
if (j >= cfg->num_inputs)
continue;
spec->input_pins[n] = pin;
- spec->input_labels[n] = hda_get_input_pin_label(codec, pin, 1);
+ snd_hda_get_pin_label(codec, pin, cfg,
+ spec->input_labels[n],
+ sizeof(spec->input_labels[n]), NULL);
spec->adcs[n] = nid;
n++;
}
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index d9a2254ceef6..21d91d580da8 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -26,6 +26,7 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/mutex.h>
+#include <linux/module.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
@@ -727,18 +728,19 @@ static int ca0132_hp_switch_put(struct snd_kcontrol *kcontrol,
err = chipio_read(codec, REG_CODEC_MUTE, &data);
if (err < 0)
- return err;
+ goto exit;
/* *valp 0 is mute, 1 is unmute */
data = (data & 0x7f) | (*valp ? 0 : 0x80);
- chipio_write(codec, REG_CODEC_MUTE, data);
+ err = chipio_write(codec, REG_CODEC_MUTE, data);
if (err < 0)
- return err;
+ goto exit;
spec->curr_hp_switch = *valp;
+ exit:
snd_hda_power_down(codec);
- return 1;
+ return err < 0 ? err : 1;
}
static int ca0132_speaker_switch_get(struct snd_kcontrol *kcontrol,
@@ -769,18 +771,19 @@ static int ca0132_speaker_switch_put(struct snd_kcontrol *kcontrol,
err = chipio_read(codec, REG_CODEC_MUTE, &data);
if (err < 0)
- return err;
+ goto exit;
/* *valp 0 is mute, 1 is unmute */
data = (data & 0xef) | (*valp ? 0 : 0x10);
- chipio_write(codec, REG_CODEC_MUTE, data);
+ err = chipio_write(codec, REG_CODEC_MUTE, data);
if (err < 0)
- return err;
+ goto exit;
spec->curr_speaker_switch = *valp;
+ exit:
snd_hda_power_down(codec);
- return 1;
+ return err < 0 ? err : 1;
}
static int ca0132_hp_volume_get(struct snd_kcontrol *kcontrol,
@@ -818,25 +821,26 @@ static int ca0132_hp_volume_put(struct snd_kcontrol *kcontrol,
err = chipio_read(codec, REG_CODEC_HP_VOL_L, &data);
if (err < 0)
- return err;
+ goto exit;
val = 31 - left_vol;
data = (data & 0xe0) | val;
- chipio_write(codec, REG_CODEC_HP_VOL_L, data);
+ err = chipio_write(codec, REG_CODEC_HP_VOL_L, data);
if (err < 0)
- return err;
+ goto exit;
val = 31 - right_vol;
data = (data & 0xe0) | val;
- chipio_write(codec, REG_CODEC_HP_VOL_R, data);
+ err = chipio_write(codec, REG_CODEC_HP_VOL_R, data);
if (err < 0)
- return err;
+ goto exit;
spec->curr_hp_volume[0] = left_vol;
spec->curr_hp_volume[1] = right_vol;
+ exit:
snd_hda_power_down(codec);
- return 1;
+ return err < 0 ? err : 1;
}
static int add_hp_switch(struct hda_codec *codec, hda_nid_t nid)
@@ -935,6 +939,8 @@ static int ca0132_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
err = add_in_volume(codec, spec->dig_in, "IEC958");
+ if (err < 0)
+ return err;
}
return 0;
}
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index d6c93d92b550..c83ccdba1e5a 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -22,9 +22,11 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_jack.h"
#include <sound/tlv.h>
/*
@@ -57,6 +59,8 @@ struct cs_spec {
unsigned int gpio_mask;
unsigned int gpio_dir;
unsigned int gpio_data;
+ unsigned int gpio_eapd_hp; /* EAPD GPIO bit for headphones */
+ unsigned int gpio_eapd_speaker; /* EAPD GPIO bit for speakers */
struct hda_pcm pcm_rec[2]; /* PCM information */
@@ -75,6 +79,8 @@ enum {
CS420X_MBP53,
CS420X_MBP55,
CS420X_IMAC27,
+ CS420X_IMAC27_122,
+ CS420X_APPLE,
CS420X_AUTO,
CS420X_MODELS
};
@@ -133,7 +139,7 @@ enum {
*/
#define CS4210_DAC_NID 0x02
#define CS4210_ADC_NID 0x03
-#define CS421X_VENDOR_NID 0x0B
+#define CS4210_VENDOR_NID 0x0B
#define CS421X_DMIC_PIN_NID 0x09 /* Port E */
#define CS421X_SPDIF_PIN_NID 0x0A /* Port H */
@@ -144,6 +150,10 @@ enum {
#define SPDIF_EVENT 0x04
+/* Cirrus Logic CS4213 is like CS4210 but does not have SPDIF input/output */
+#define CS4213_VENDOR_NID 0x09
+
+
static inline int cs_vendor_coef_get(struct hda_codec *codec, unsigned int idx)
{
struct cs_spec *spec = codec->spec;
@@ -236,6 +246,15 @@ static int cs_dig_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
return snd_hda_multi_out_dig_cleanup(codec, &spec->multiout);
}
+static void cs_update_input_select(struct hda_codec *codec)
+{
+ struct cs_spec *spec = codec->spec;
+ if (spec->cur_adc)
+ snd_hda_codec_write(codec, spec->cur_adc, 0,
+ AC_VERB_SET_CONNECT_SEL,
+ spec->adc_idx[spec->cur_input]);
+}
+
/*
* Analog capture
*/
@@ -249,6 +268,7 @@ static int cs_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
spec->cur_adc = spec->adc_nid[spec->cur_input];
spec->cur_adc_stream_tag = stream_tag;
spec->cur_adc_format = format;
+ cs_update_input_select(codec);
snd_hda_codec_setup_stream(codec, spec->cur_adc, stream_tag, 0, format);
return 0;
}
@@ -535,7 +555,7 @@ static int add_volume(struct hda_codec *codec, const char *name,
int index, unsigned int pval, int dir,
struct snd_kcontrol **kctlp)
{
- char tmp[32];
+ char tmp[44];
struct snd_kcontrol_new knew =
HDA_CODEC_VOLUME_IDX(tmp, index, 0, 0, HDA_OUTPUT);
knew.private_value = pval;
@@ -589,7 +609,7 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx,
"Front Speaker", "Surround Speaker", "Bass Speaker"
};
static const char * const line_outs[] = {
- "Front Line-Out", "Surround Line-Out", "Bass Line-Out"
+ "Front Line Out", "Surround Line Out", "Bass Line Out"
};
fix_volume_caps(codec, dac);
@@ -615,7 +635,7 @@ static int add_output(struct hda_codec *codec, hda_nid_t dac, int idx,
if (num_ctls > 1)
name = line_outs[idx];
else
- name = "Line-Out";
+ name = "Line Out";
break;
}
@@ -688,10 +708,8 @@ static int change_cur_input(struct hda_codec *codec, unsigned int idx,
spec->cur_adc_stream_tag, 0,
spec->cur_adc_format);
}
- snd_hda_codec_write(codec, spec->cur_adc, 0,
- AC_VERB_SET_CONNECT_SEL,
- spec->adc_idx[idx]);
spec->cur_input = idx;
+ cs_update_input_select(codec);
return 1;
}
@@ -709,8 +727,9 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol,
if (uinfo->value.enumerated.item >= spec->num_inputs)
uinfo->value.enumerated.item = spec->num_inputs - 1;
idx = spec->input_idx[uinfo->value.enumerated.item];
- strcpy(uinfo->value.enumerated.name,
- hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1));
+ snd_hda_get_pin_label(codec, cfg->inputs[idx].pin, cfg,
+ uinfo->value.enumerated.name,
+ sizeof(uinfo->value.enumerated.name), NULL);
return 0;
}
@@ -908,27 +927,24 @@ static void cs_automute(struct hda_codec *codec)
/* mute speakers if spdif or hp jack is plugged in */
for (i = 0; i < cfg->speaker_outs; i++) {
+ int pin_ctl = hp_present ? 0 : PIN_OUT;
+ /* detect on spdif is specific to CS4210 */
+ if (spdif_present && (spec->vendor_nid == CS4210_VENDOR_NID))
+ pin_ctl = 0;
+
nid = cfg->speaker_pins[i];
snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- hp_present ? 0 : PIN_OUT);
- /* detect on spdif is specific to CS421x */
- if (spec->vendor_nid == CS421X_VENDOR_NID) {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- spdif_present ? 0 : PIN_OUT);
- }
+ AC_VERB_SET_PIN_WIDGET_CONTROL, pin_ctl);
}
- if (spec->board_config == CS420X_MBP53 ||
- spec->board_config == CS420X_MBP55 ||
- spec->board_config == CS420X_IMAC27) {
- unsigned int gpio = hp_present ? 0x02 : 0x08;
+ if (spec->gpio_eapd_hp) {
+ unsigned int gpio = hp_present ?
+ spec->gpio_eapd_hp : spec->gpio_eapd_speaker;
snd_hda_codec_write(codec, 0x01, 0,
AC_VERB_SET_GPIO_DATA, gpio);
}
- /* specific to CS421x */
- if (spec->vendor_nid == CS421X_VENDOR_NID) {
+ /* specific to CS4210 */
+ if (spec->vendor_nid == CS4210_VENDOR_NID) {
/* mute HPs if spdif jack (SENSE_B) is present */
for (i = 0; i < cfg->hp_outs; i++) {
nid = cfg->hp_pins[i];
@@ -965,22 +981,21 @@ static void cs_automic(struct hda_codec *codec)
present = snd_hda_jack_detect(codec, nid);
/* specific to CS421x, single ADC */
- if (spec->vendor_nid == CS421X_VENDOR_NID) {
- if (present) {
- spec->last_input = spec->cur_input;
- spec->cur_input = spec->automic_idx;
- } else {
- spec->cur_input = spec->last_input;
- }
-
- snd_hda_codec_write_cache(codec, spec->cur_adc, 0,
- AC_VERB_SET_CONNECT_SEL,
- spec->adc_idx[spec->cur_input]);
- } else {
+ if (spec->vendor_nid == CS420X_VENDOR_NID) {
if (present)
change_cur_input(codec, spec->automic_idx, 0);
else
change_cur_input(codec, !spec->automic_idx, 0);
+ } else {
+ if (present) {
+ if (spec->cur_input != spec->automic_idx) {
+ spec->last_input = spec->cur_input;
+ spec->cur_input = spec->automic_idx;
+ }
+ } else {
+ spec->cur_input = spec->last_input;
+ }
+ cs_update_input_select(codec);
}
}
@@ -1019,9 +1034,7 @@ static void init_output(struct hda_codec *codec)
if (!cfg->speaker_outs)
continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | HP_EVENT);
+ snd_hda_jack_detect_enable(codec, nid, HP_EVENT);
spec->hp_detect = 1;
}
}
@@ -1062,21 +1075,10 @@ static void init_input(struct hda_codec *codec)
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_IN_MUTE(spec->adc_idx[i]));
if (spec->mic_detect && spec->automic_idx == i)
- snd_hda_codec_write(codec, pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | MIC_EVENT);
+ snd_hda_jack_detect_enable(codec, pin, MIC_EVENT);
}
- /* specific to CS421x */
- if (spec->vendor_nid == CS421X_VENDOR_NID) {
- if (spec->mic_detect)
- cs_automic(codec);
- else {
- spec->cur_adc = spec->adc_nid[spec->cur_input];
- snd_hda_codec_write(codec, spec->cur_adc, 0,
- AC_VERB_SET_CONNECT_SEL,
- spec->adc_idx[spec->cur_input]);
- }
- } else {
+ /* CS420x has multiple ADC, CS421x has single ADC */
+ if (spec->vendor_nid == CS420X_VENDOR_NID) {
change_cur_input(codec, spec->cur_input, 1);
if (spec->mic_detect)
cs_automic(codec);
@@ -1090,6 +1092,13 @@ static void init_input(struct hda_codec *codec)
* selected in IDX_SPDIF_CTL.
*/
cs_vendor_coef_set(codec, IDX_ADC_CFG, coef);
+ } else {
+ if (spec->mic_detect)
+ cs_automic(codec);
+ else {
+ spec->cur_adc = spec->adc_nid[spec->cur_input];
+ cs_update_input_select(codec);
+ }
}
}
@@ -1194,11 +1203,14 @@ static int cs_init(struct hda_codec *codec)
init_output(codec);
init_input(codec);
init_digital(codec);
+ snd_hda_jack_report_sync(codec);
+
return 0;
}
static int cs_build_controls(struct hda_codec *codec)
{
+ struct cs_spec *spec = codec->spec;
int err;
err = build_output(codec);
@@ -1213,7 +1225,15 @@ static int cs_build_controls(struct hda_codec *codec)
err = build_digital_input(codec);
if (err < 0)
return err;
- return cs_init(codec);
+ err = cs_init(codec);
+ if (err < 0)
+ return err;
+
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
+
+ return 0;
}
static void cs_free(struct hda_codec *codec)
@@ -1226,7 +1246,7 @@ static void cs_free(struct hda_codec *codec)
static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
{
- switch ((res >> 26) & 0x7f) {
+ switch (snd_hda_jack_get_action(codec, res >> 26)) {
case HP_EVENT:
cs_automute(codec);
break;
@@ -1234,6 +1254,7 @@ static void cs_unsol_event(struct hda_codec *codec, unsigned int res)
cs_automic(codec);
break;
}
+ snd_hda_jack_report_sync(codec);
}
static const struct hda_codec_ops cs_patch_ops = {
@@ -1272,6 +1293,8 @@ static const char * const cs420x_models[CS420X_MODELS] = {
[CS420X_MBP53] = "mbp53",
[CS420X_MBP55] = "mbp55",
[CS420X_IMAC27] = "imac27",
+ [CS420X_IMAC27_122] = "imac27_122",
+ [CS420X_APPLE] = "apple",
[CS420X_AUTO] = "auto",
};
@@ -1281,7 +1304,14 @@ static const struct snd_pci_quirk cs420x_cfg_tbl[] = {
SND_PCI_QUIRK(0x10de, 0x0d94, "MacBookAir 3,1(2)", CS420X_MBP55),
SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55),
SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55),
- SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),
+ /* this conflicts with too many other models */
+ /*SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27),*/
+ {} /* terminator */
+};
+
+static const struct snd_pci_quirk cs420x_codec_cfg_tbl[] = {
+ SND_PCI_QUIRK(0x106b, 0x2000, "iMac 12,2", CS420X_IMAC27_122),
+ SND_PCI_QUIRK_VENDOR(0x106b, "Apple", CS420X_APPLE),
{} /* terminator */
};
@@ -1363,6 +1393,10 @@ static int patch_cs420x(struct hda_codec *codec)
spec->board_config =
snd_hda_check_board_config(codec, CS420X_MODELS,
cs420x_models, cs420x_cfg_tbl);
+ if (spec->board_config < 0)
+ spec->board_config =
+ snd_hda_check_board_codec_sid_config(codec,
+ CS420X_MODELS, NULL, cs420x_codec_cfg_tbl);
if (spec->board_config >= 0)
fix_pincfg(codec, spec->board_config, cs_pincfgs);
@@ -1370,10 +1404,17 @@ static int patch_cs420x(struct hda_codec *codec)
case CS420X_IMAC27:
case CS420X_MBP53:
case CS420X_MBP55:
- /* GPIO1 = headphones */
- /* GPIO3 = speakers */
- spec->gpio_mask = 0x0a;
- spec->gpio_dir = 0x0a;
+ case CS420X_APPLE:
+ spec->gpio_eapd_hp = 2; /* GPIO1 = headphones */
+ spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */
+ spec->gpio_mask = spec->gpio_dir =
+ spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
+ break;
+ case CS420X_IMAC27_122:
+ spec->gpio_eapd_hp = 4; /* GPIO2 = headphones */
+ spec->gpio_eapd_speaker = 8; /* GPIO3 = speakers */
+ spec->gpio_mask = spec->gpio_dir =
+ spec->gpio_eapd_hp | spec->gpio_eapd_speaker;
break;
}
@@ -1539,7 +1580,7 @@ static const struct snd_kcontrol_new cs421x_speaker_bost_ctl = {
.tlv = { .p = cs421x_speaker_boost_db_scale },
};
-static void cs421x_pinmux_init(struct hda_codec *codec)
+static void cs4210_pinmux_init(struct hda_codec *codec)
{
struct cs_spec *spec = codec->spec;
unsigned int def_conf, coef;
@@ -1584,10 +1625,7 @@ static void init_cs421x_digital(struct hda_codec *codec)
if (!cfg->speaker_outs)
continue;
if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP) {
-
- snd_hda_codec_write(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | SPDIF_EVENT);
+ snd_hda_jack_detect_enable(codec, nid, SPDIF_EVENT);
spec->spdif_detect = 1;
}
}
@@ -1597,10 +1635,11 @@ static int cs421x_init(struct hda_codec *codec)
{
struct cs_spec *spec = codec->spec;
- snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
- snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
-
- cs421x_pinmux_init(codec);
+ if (spec->vendor_nid == CS4210_VENDOR_NID) {
+ snd_hda_sequence_write(codec, cs421x_coef_init_verbs);
+ snd_hda_sequence_write(codec, cs421x_coef_init_verbs_A1_silicon_fixes);
+ cs4210_pinmux_init(codec);
+ }
if (spec->gpio_mask) {
snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_MASK,
@@ -1614,6 +1653,7 @@ static int cs421x_init(struct hda_codec *codec)
init_output(codec);
init_input(codec);
init_cs421x_digital(codec);
+ snd_hda_jack_report_sync(codec);
return 0;
}
@@ -1753,32 +1793,21 @@ static int build_cs421x_output(struct hda_codec *codec)
struct auto_pin_cfg *cfg = &spec->autocfg;
struct snd_kcontrol *kctl;
int err;
- char *name = "HP/Speakers";
+ char *name = "Master";
fix_volume_caps(codec, dac);
- if (!spec->vmaster_sw) {
- err = add_vmaster(codec, dac);
- if (err < 0)
- return err;
- }
err = add_mute(codec, name, 0,
HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
if (err < 0)
return err;
- err = snd_ctl_add_slave(spec->vmaster_sw, kctl);
- if (err < 0)
- return err;
err = add_volume(codec, name, 0,
HDA_COMPOSE_AMP_VAL(dac, 3, 0, HDA_OUTPUT), 0, &kctl);
if (err < 0)
return err;
- err = snd_ctl_add_slave(spec->vmaster_vol, kctl);
- if (err < 0)
- return err;
- if (cfg->speaker_outs) {
+ if (cfg->speaker_outs && (spec->vendor_nid == CS4210_VENDOR_NID)) {
err = snd_hda_ctl_add(codec, 0,
snd_ctl_new1(&cs421x_speaker_bost_ctl, codec));
if (err < 0)
@@ -1789,6 +1818,7 @@ static int build_cs421x_output(struct hda_codec *codec)
static int cs421x_build_controls(struct hda_codec *codec)
{
+ struct cs_spec *spec = codec->spec;
int err;
err = build_cs421x_output(codec);
@@ -1800,12 +1830,20 @@ static int cs421x_build_controls(struct hda_codec *codec)
err = build_digital_output(codec);
if (err < 0)
return err;
- return cs421x_init(codec);
+ err = cs421x_init(codec);
+ if (err < 0)
+ return err;
+
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
+
+ return 0;
}
static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
{
- switch ((res >> 26) & 0x3f) {
+ switch (snd_hda_jack_get_action(codec, res >> 26)) {
case HP_EVENT:
case SPDIF_EVENT:
cs_automute(codec);
@@ -1815,6 +1853,7 @@ static void cs421x_unsol_event(struct hda_codec *codec, unsigned int res)
cs_automic(codec);
break;
}
+ snd_hda_jack_report_sync(codec);
}
static int parse_cs421x_input(struct hda_codec *codec)
@@ -1865,6 +1904,7 @@ static int cs421x_parse_auto_config(struct hda_codec *codec)
*/
static int cs421x_suspend(struct hda_codec *codec, pm_message_t state)
{
+ struct cs_spec *spec = codec->spec;
unsigned int coef;
snd_hda_shutup_pins(codec);
@@ -1874,15 +1914,17 @@ static int cs421x_suspend(struct hda_codec *codec, pm_message_t state)
snd_hda_codec_write(codec, CS4210_ADC_NID, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
- coef |= 0x0004; /* PDREF */
- cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
+ if (spec->vendor_nid == CS4210_VENDOR_NID) {
+ coef = cs_vendor_coef_get(codec, CS421X_IDX_DEV_CFG);
+ coef |= 0x0004; /* PDREF */
+ cs_vendor_coef_set(codec, CS421X_IDX_DEV_CFG, coef);
+ }
return 0;
}
#endif
-static struct hda_codec_ops cs4210_patch_ops = {
+static struct hda_codec_ops cs421x_patch_ops = {
.build_controls = cs421x_build_controls,
.build_pcms = cs_build_pcms,
.init = cs421x_init,
@@ -1893,7 +1935,7 @@ static struct hda_codec_ops cs4210_patch_ops = {
#endif
};
-static int patch_cs421x(struct hda_codec *codec)
+static int patch_cs4210(struct hda_codec *codec)
{
struct cs_spec *spec;
int err;
@@ -1903,7 +1945,7 @@ static int patch_cs421x(struct hda_codec *codec)
return -ENOMEM;
codec->spec = spec;
- spec->vendor_nid = CS421X_VENDOR_NID;
+ spec->vendor_nid = CS4210_VENDOR_NID;
spec->board_config =
snd_hda_check_board_config(codec, CS421X_MODELS,
@@ -1931,14 +1973,39 @@ static int patch_cs421x(struct hda_codec *codec)
is auto-parsed. If GPIO or SENSE_B is forced, DMIC input
is disabled.
*/
- cs421x_pinmux_init(codec);
+ cs4210_pinmux_init(codec);
err = cs421x_parse_auto_config(codec);
if (err < 0)
goto error;
- codec->patch_ops = cs4210_patch_ops;
+ codec->patch_ops = cs421x_patch_ops;
+
+ return 0;
+
+ error:
+ kfree(codec->spec);
+ codec->spec = NULL;
+ return err;
+}
+
+static int patch_cs4213(struct hda_codec *codec)
+{
+ struct cs_spec *spec;
+ int err;
+
+ spec = kzalloc(sizeof(*spec), GFP_KERNEL);
+ if (!spec)
+ return -ENOMEM;
+ codec->spec = spec;
+
+ spec->vendor_nid = CS4213_VENDOR_NID;
+
+ err = cs421x_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
+ codec->patch_ops = cs421x_patch_ops;
return 0;
error:
@@ -1954,13 +2021,15 @@ static int patch_cs421x(struct hda_codec *codec)
static const struct hda_codec_preset snd_hda_preset_cirrus[] = {
{ .id = 0x10134206, .name = "CS4206", .patch = patch_cs420x },
{ .id = 0x10134207, .name = "CS4207", .patch = patch_cs420x },
- { .id = 0x10134210, .name = "CS4210", .patch = patch_cs421x },
+ { .id = 0x10134210, .name = "CS4210", .patch = patch_cs4210 },
+ { .id = 0x10134213, .name = "CS4213", .patch = patch_cs4213 },
{} /* terminator */
};
MODULE_ALIAS("snd-hda-codec-id:10134206");
MODULE_ALIAS("snd-hda-codec-id:10134207");
MODULE_ALIAS("snd-hda-codec-id:10134210");
+MODULE_ALIAS("snd-hda-codec-id:10134213");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Cirrus Logic HD-audio codec");
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index cd2cf5e94e81..b6767b4ced44 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -25,6 +25,7 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 7696d05b9356..8c6523bbc797 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -24,12 +24,14 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
#include "hda_beep.h"
+#include "hda_jack.h"
#define CXT_PIN_DIR_IN 0x00
#define CXT_PIN_DIR_OUT 0x01
@@ -68,6 +70,8 @@ struct conexant_spec {
const struct snd_kcontrol_new *mixers[5];
int num_mixers;
hda_nid_t vmaster_nid;
+ struct hda_vmaster_mute_hook vmaster_mute;
+ bool vmaster_mute_led;
const struct hda_verb *init_verbs[5]; /* initialization verbs
* don't forget NULL
@@ -136,6 +140,8 @@ struct conexant_spec {
unsigned int thinkpad:1;
unsigned int hp_laptop:1;
unsigned int asus:1;
+ unsigned int pin_eapd_ctrls:1;
+ unsigned int single_adc_amp:1;
unsigned int adc_switching:1;
@@ -412,40 +418,6 @@ static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
&spec->cur_mux[adc_idx]);
}
-static int conexant_init_jacks(struct hda_codec *codec)
-{
-#ifdef CONFIG_SND_HDA_INPUT_JACK
- struct conexant_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < spec->num_init_verbs; i++) {
- const struct hda_verb *hv;
-
- hv = spec->init_verbs[i];
- while (hv->nid) {
- int err = 0;
- switch (hv->param ^ AC_USRSP_EN) {
- case CONEXANT_HP_EVENT:
- err = snd_hda_input_jack_add(codec, hv->nid,
- SND_JACK_HEADPHONE, NULL);
- snd_hda_input_jack_report(codec, hv->nid);
- break;
- case CXT5051_PORTC_EVENT:
- case CONEXANT_MIC_EVENT:
- err = snd_hda_input_jack_add(codec, hv->nid,
- SND_JACK_MICROPHONE, NULL);
- snd_hda_input_jack_report(codec, hv->nid);
- break;
- }
- if (err < 0)
- return err;
- ++hv;
- }
- }
-#endif /* CONFIG_SND_HDA_INPUT_JACK */
- return 0;
-}
-
static void conexant_set_power(struct hda_codec *codec, hda_nid_t fg,
unsigned int power_state)
{
@@ -471,7 +443,6 @@ static int conexant_init(struct hda_codec *codec)
static void conexant_free(struct hda_codec *codec)
{
- snd_hda_input_jack_free(codec);
snd_hda_detach_beep_device(codec);
kfree(codec->spec);
}
@@ -496,21 +467,8 @@ static const struct snd_kcontrol_new cxt_beep_mixer[] = {
};
#endif
-static const char * const slave_vols[] = {
- "Headphone Playback Volume",
- "Speaker Playback Volume",
- "Front Playback Volume",
- "Surround Playback Volume",
- "CLFE Playback Volume",
- NULL
-};
-
-static const char * const slave_sws[] = {
- "Headphone Playback Switch",
- "Speaker Playback Switch",
- "Front Playback Switch",
- "Surround Playback Switch",
- "CLFE Playback Switch",
+static const char * const slave_pfxs[] = {
+ "Headphone", "Speaker", "Front", "Surround", "CLFE",
NULL
};
@@ -550,14 +508,17 @@ static int conexant_build_controls(struct hda_codec *codec)
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
HDA_OUTPUT, vmaster_tlv);
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
- vmaster_tlv, slave_vols);
+ vmaster_tlv, slave_pfxs,
+ "Playback Volume");
if (err < 0)
return err;
}
if (spec->vmaster_nid &&
!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
- err = snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, slave_sws);
+ err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+ NULL, slave_pfxs,
+ "Playback Switch", true,
+ &spec->vmaster_mute.sw_kctl);
if (err < 0)
return err;
}
@@ -1117,8 +1078,6 @@ static const char * const cxt5045_models[CXT5045_MODELS] = {
static const struct snd_pci_quirk cxt5045_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30d5, "HP 530", CXT5045_LAPTOP_HP530),
- SND_PCI_QUIRK_MASK(0x103c, 0xff00, 0x3000, "HP DV Series",
- CXT5045_LAPTOP_HPSENSE),
SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P105", CXT5045_LAPTOP_MICSENSE),
SND_PCI_QUIRK(0x152d, 0x0753, "Benq R55E", CXT5045_BENQ),
SND_PCI_QUIRK(0x1734, 0x10ad, "Fujitsu Si1520", CXT5045_LAPTOP_MICSENSE),
@@ -1676,7 +1635,7 @@ static void cxt5051_update_speaker(struct hda_codec *codec)
pinctl = (!spec->hp_present && spec->cur_eapd) ? PIN_OUT : 0;
snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
pinctl);
- /* on ideapad there is an aditional speaker (subwoofer) to mute */
+ /* on ideapad there is an additional speaker (subwoofer) to mute */
if (spec->ideapad)
snd_hda_codec_write(codec, 0x1b, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
@@ -1747,7 +1706,6 @@ static void cxt5051_hp_automute(struct hda_codec *codec)
static void cxt5051_hp_unsol_event(struct hda_codec *codec,
unsigned int res)
{
- int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
switch (res >> 26) {
case CONEXANT_HP_EVENT:
cxt5051_hp_automute(codec);
@@ -1759,7 +1717,6 @@ static void cxt5051_hp_unsol_event(struct hda_codec *codec,
cxt5051_portc_automic(codec);
break;
}
- snd_hda_input_jack_report(codec, nid);
}
static const struct snd_kcontrol_new cxt5051_playback_mixers[] = {
@@ -1867,39 +1824,6 @@ static const struct hda_verb cxt5051_hp_dv6736_init_verbs[] = {
{ } /* end */
};
-static const struct hda_verb cxt5051_lenovo_x200_init_verbs[] = {
- /* Line in, Mic */
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
- {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
- /* SPK */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* HP, Amp */
- {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x16, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* Docking HP */
- {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x19, AC_VERB_SET_CONNECT_SEL, 0x00},
- /* DAC1 */
- {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- /* Record selector: Internal mic */
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1) | 0x44},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x44},
- /* SPDIF route: PCM */
- {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT}, /* needed for W500 Advanced Mini Dock 250410 */
- {0x1c, AC_VERB_SET_CONNECT_SEL, 0x0},
- /* EAPD */
- {0x1a, AC_VERB_SET_EAPD_BTLENABLE, 0x2}, /* default on */
- {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
- {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN|CONEXANT_HP_EVENT},
- { } /* end */
-};
-
static const struct hda_verb cxt5051_f700_init_verbs[] = {
/* Line in, Mic */
{0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0) | 0x03},
@@ -1931,8 +1855,6 @@ static void cxt5051_init_mic_port(struct hda_codec *codec, hda_nid_t nid,
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
AC_USRSP_EN | event);
- snd_hda_input_jack_add(codec, nid, SND_JACK_MICROPHONE, NULL);
- snd_hda_input_jack_report(codec, nid);
}
static const struct hda_verb cxt5051_ideapad_init_verbs[] = {
@@ -1948,7 +1870,6 @@ static int cxt5051_init(struct hda_codec *codec)
struct conexant_spec *spec = codec->spec;
conexant_init(codec);
- conexant_init_jacks(codec);
if (spec->auto_mic & AUTO_MIC_PORTB)
cxt5051_init_mic_port(codec, 0x17, CXT5051_PORTB_EVENT);
@@ -1968,7 +1889,6 @@ enum {
CXT5051_LAPTOP, /* Laptops w/ EAPD support */
CXT5051_HP, /* no docking */
CXT5051_HP_DV6736, /* HP without mic switch */
- CXT5051_LENOVO_X200, /* Lenovo X200 laptop, also used for Advanced Mini Dock 250410 */
CXT5051_F700, /* HP Compaq Presario F700 */
CXT5051_TOSHIBA, /* Toshiba M300 & co */
CXT5051_IDEAPAD, /* Lenovo IdeaPad Y430 */
@@ -1980,7 +1900,6 @@ static const char *const cxt5051_models[CXT5051_MODELS] = {
[CXT5051_LAPTOP] = "laptop",
[CXT5051_HP] = "hp",
[CXT5051_HP_DV6736] = "hp-dv6736",
- [CXT5051_LENOVO_X200] = "lenovo-x200",
[CXT5051_F700] = "hp-700",
[CXT5051_TOSHIBA] = "toshiba",
[CXT5051_IDEAPAD] = "ideapad",
@@ -1995,7 +1914,6 @@ static const struct snd_pci_quirk cxt5051_cfg_tbl[] = {
SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
CXT5051_LAPTOP),
SND_PCI_QUIRK(0x14f1, 0x5051, "HP Spartan 1.1", CXT5051_HP),
- SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT5051_LENOVO_X200),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo IdeaPad", CXT5051_IDEAPAD),
{}
};
@@ -2053,13 +1971,6 @@ static int patch_cxt5051(struct hda_codec *codec)
spec->mixers[0] = cxt5051_hp_dv6736_mixers;
spec->auto_mic = 0;
break;
- case CXT5051_LENOVO_X200:
- spec->init_verbs[0] = cxt5051_lenovo_x200_init_verbs;
- /* Thinkpad X301 does not have S/PDIF wired and no ability
- to use a docking station. */
- if (codec->subsystem_id == 0x17aa211f)
- spec->multiout.dig_out_nid = 0;
- break;
case CXT5051_F700:
spec->init_verbs[0] = cxt5051_f700_init_verbs;
spec->mixers[0] = cxt5051_f700_mixers;
@@ -3102,20 +3013,19 @@ static const struct snd_pci_quirk cxt5066_cfg_tbl[] = {
SND_PCI_QUIRK(0x1043, 0x1993, "Asus U50F", CXT5066_ASUS),
SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD),
SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5),
- SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board",
CXT5066_LAPTOP),
SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21c5, "Thinkpad Edge 13", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21c6, "Thinkpad Edge 13", CXT5066_ASUS),
- SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo Thinkpad", CXT5066_THINKPAD),
+ SND_PCI_QUIRK(0x17aa, 0x215e, "Lenovo T510", CXT5066_AUTO),
+ SND_PCI_QUIRK(0x17aa, 0x21cf, "Lenovo T520 & W520", CXT5066_AUTO),
SND_PCI_QUIRK(0x17aa, 0x21da, "Lenovo X220", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x21db, "Lenovo X220-tablet", CXT5066_THINKPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo U350", CXT5066_ASUS),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo G560", CXT5066_ASUS),
SND_PCI_QUIRK(0x17aa, 0x3938, "Lenovo G565", CXT5066_AUTO),
- SND_PCI_QUIRK_VENDOR(0x17aa, "Lenovo", CXT5066_IDEAPAD), /* Fallback for Lenovos without dock mic */
SND_PCI_QUIRK(0x1b0a, 0x2092, "CyberpowerPC Gamer Xplorer N57001", CXT5066_AUTO),
{}
};
@@ -3472,12 +3382,14 @@ static void cx_auto_turn_eapd(struct hda_codec *codec, int num_pins,
static void do_automute(struct hda_codec *codec, int num_pins,
hda_nid_t *pins, bool on)
{
+ struct conexant_spec *spec = codec->spec;
int i;
for (i = 0; i < num_pins; i++)
snd_hda_codec_write(codec, pins[i], 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
on ? PIN_OUT : 0);
- cx_auto_turn_eapd(codec, num_pins, pins, on);
+ if (spec->pin_eapd_ctrls)
+ cx_auto_turn_eapd(codec, num_pins, pins, on);
}
static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
@@ -3488,7 +3400,6 @@ static int detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
hda_nid_t nid = pins[i];
if (!nid || !is_jack_detectable(codec, nid))
break;
- snd_hda_input_jack_report(codec, nid);
present |= snd_hda_jack_detect(codec, nid);
}
return present;
@@ -3502,9 +3413,12 @@ static void cx_auto_update_speakers(struct hda_codec *codec)
int on = 1;
/* turn on HP EAPD when HP jacks are present */
- if (spec->auto_mute)
- on = spec->hp_present;
- cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
+ if (spec->pin_eapd_ctrls) {
+ if (spec->auto_mute)
+ on = spec->hp_present;
+ cx_auto_turn_eapd(codec, cfg->hp_outs, cfg->hp_pins, on);
+ }
+
/* mute speakers in auto-mode if HP or LO jacks are plugged */
if (spec->auto_mute)
on = !(spec->hp_present ||
@@ -3559,7 +3473,7 @@ static int cx_automute_mode_info(struct snd_kcontrol *kcontrol,
"Disabled", "Enabled"
};
static const char * const texts3[] = {
- "Disabled", "Speaker Only", "Line-Out+Speaker"
+ "Disabled", "Speaker Only", "Line Out+Speaker"
};
const char * const *texts;
@@ -3790,8 +3704,7 @@ static void cx_auto_automic(struct hda_codec *codec)
static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
{
- int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20;
- switch (res >> 26) {
+ switch (snd_hda_jack_get_action(codec, res >> 26)) {
case CONEXANT_HP_EVENT:
cx_auto_hp_automute(codec);
break;
@@ -3800,9 +3713,9 @@ static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res)
break;
case CONEXANT_MIC_EVENT:
cx_auto_automic(codec);
- snd_hda_input_jack_report(codec, nid);
break;
}
+ snd_hda_jack_report_sync(codec);
}
/* check whether the pin config is suitable for auto-mic switching;
@@ -3931,20 +3844,10 @@ static void cx_auto_parse_beep(struct hda_codec *codec)
#define cx_auto_parse_beep(codec)
#endif
-static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
-{
- int i;
- for (i = 0; i < nums; i++)
- if (list[i] == nid)
- return true;
- return false;
-}
-
-/* parse extra-EAPD that aren't assigned to any pins */
+/* parse EAPDs */
static void cx_auto_parse_eapd(struct hda_codec *codec)
{
struct conexant_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
hda_nid_t nid, end_nid;
end_nid = codec->start_nid + codec->num_nodes;
@@ -3953,14 +3856,18 @@ static void cx_auto_parse_eapd(struct hda_codec *codec)
continue;
if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_EAPD))
continue;
- if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) ||
- found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) ||
- found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs))
- continue;
spec->eapds[spec->num_eapds++] = nid;
if (spec->num_eapds >= ARRAY_SIZE(spec->eapds))
break;
}
+
+ /* NOTE: below is a wild guess; if we have more than two EAPDs,
+ * it's a new chip, where EAPDs are supposed to be associated to
+ * pins, and we can control EAPD per pin.
+ * OTOH, if only one or two EAPDs are found, it's an old chip,
+ * thus it might control over all pins.
+ */
+ spec->pin_eapd_ctrls = spec->num_eapds > 2;
}
static int cx_auto_parse_auto_config(struct hda_codec *codec)
@@ -4020,13 +3927,68 @@ static void mute_outputs(struct hda_codec *codec, int num_nids,
}
static void enable_unsol_pins(struct hda_codec *codec, int num_pins,
- hda_nid_t *pins, unsigned int tag)
+ hda_nid_t *pins, unsigned int action)
{
int i;
for (i = 0; i < num_pins; i++)
- snd_hda_codec_write(codec, pins[i], 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | tag);
+ snd_hda_jack_detect_enable(codec, pins[i], action);
+}
+
+static bool found_in_nid_list(hda_nid_t nid, const hda_nid_t *list, int nums)
+{
+ int i;
+ for (i = 0; i < nums; i++)
+ if (list[i] == nid)
+ return true;
+ return false;
+}
+
+/* is the given NID found in any of autocfg items? */
+static bool found_in_autocfg(struct auto_pin_cfg *cfg, hda_nid_t nid)
+{
+ int i;
+
+ if (found_in_nid_list(nid, cfg->line_out_pins, cfg->line_outs) ||
+ found_in_nid_list(nid, cfg->hp_pins, cfg->hp_outs) ||
+ found_in_nid_list(nid, cfg->speaker_pins, cfg->speaker_outs) ||
+ found_in_nid_list(nid, cfg->dig_out_pins, cfg->dig_outs))
+ return true;
+ for (i = 0; i < cfg->num_inputs; i++)
+ if (cfg->inputs[i].pin == nid)
+ return true;
+ if (cfg->dig_in_pin == nid)
+ return true;
+ return false;
+}
+
+/* clear unsol-event tags on unused pins; Conexant codecs seem to leave
+ * invalid unsol tags by some reason
+ */
+static void clear_unsol_on_unused_pins(struct hda_codec *codec)
+{
+ struct conexant_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int i;
+
+ for (i = 0; i < codec->init_pins.used; i++) {
+ struct hda_pincfg *pin = snd_array_elem(&codec->init_pins, i);
+ if (!found_in_autocfg(cfg, pin->nid))
+ snd_hda_codec_write(codec, pin->nid, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE, 0);
+ }
+}
+
+/* turn on/off EAPD according to Master switch */
+static void cx_auto_vmaster_hook(void *private_data, int enabled)
+{
+ struct hda_codec *codec = private_data;
+ struct conexant_spec *spec = codec->spec;
+
+ if (enabled && spec->pin_eapd_ctrls) {
+ cx_auto_update_speakers(codec);
+ return;
+ }
+ cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, enabled);
}
static void cx_auto_init_output(struct hda_codec *codec)
@@ -4066,8 +4028,10 @@ static void cx_auto_init_output(struct hda_codec *codec)
}
}
cx_auto_update_speakers(codec);
- /* turn on/off extra EAPDs, too */
- cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
+ /* turn on all EAPDs if no individual EAPD control is available */
+ if (!spec->pin_eapd_ctrls)
+ cx_auto_turn_eapd(codec, spec->num_eapds, spec->eapds, true);
+ clear_unsol_on_unused_pins(codec);
}
static void cx_auto_init_input(struct hda_codec *codec)
@@ -4100,16 +4064,14 @@ static void cx_auto_init_input(struct hda_codec *codec)
if (spec->auto_mic) {
if (spec->auto_mic_ext >= 0) {
- snd_hda_codec_write(codec,
- cfg->inputs[spec->auto_mic_ext].pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | CONEXANT_MIC_EVENT);
+ snd_hda_jack_detect_enable(codec,
+ cfg->inputs[spec->auto_mic_ext].pin,
+ CONEXANT_MIC_EVENT);
}
if (spec->auto_mic_dock >= 0) {
- snd_hda_codec_write(codec,
- cfg->inputs[spec->auto_mic_dock].pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | CONEXANT_MIC_EVENT);
+ snd_hda_jack_detect_enable(codec,
+ cfg->inputs[spec->auto_mic_dock].pin,
+ CONEXANT_MIC_EVENT);
}
cx_auto_automic(codec);
} else {
@@ -4133,10 +4095,13 @@ static void cx_auto_init_digital(struct hda_codec *codec)
static int cx_auto_init(struct hda_codec *codec)
{
+ struct conexant_spec *spec = codec->spec;
/*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/
cx_auto_init_output(codec);
cx_auto_init_input(codec);
cx_auto_init_digital(codec);
+ snd_hda_jack_report_sync(codec);
+ snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
return 0;
}
@@ -4165,7 +4130,8 @@ static int cx_auto_add_volume_idx(struct hda_codec *codec, const char *basename,
err = snd_hda_ctl_add(codec, nid, kctl);
if (err < 0)
return err;
- if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE))
+ if (!(query_amp_caps(codec, nid, hda_dir) &
+ (AC_AMPCAP_MUTE | AC_AMPCAP_MIN_MUTE)))
break;
}
return 0;
@@ -4254,6 +4220,8 @@ static int cx_auto_add_capture_volume(struct hda_codec *codec, hda_nid_t nid,
int idx = get_input_connection(codec, adc_nid, nid);
if (idx < 0)
continue;
+ if (spec->single_adc_amp)
+ idx = 0;
return cx_auto_add_volume_idx(codec, label, pfx,
cidx, adc_nid, HDA_INPUT, idx);
}
@@ -4294,14 +4262,21 @@ static int cx_auto_build_input_controls(struct hda_codec *codec)
struct hda_input_mux *imux = &spec->private_imux;
const char *prev_label;
int input_conn[HDA_MAX_NUM_INPUTS];
- int i, err, cidx;
+ int i, j, err, cidx;
int multi_connection;
+ if (!imux->num_items)
+ return 0;
+
multi_connection = 0;
for (i = 0; i < imux->num_items; i++) {
cidx = get_input_connection(codec, spec->imux_info[i].adc,
spec->imux_info[i].pin);
- input_conn[i] = (spec->imux_info[i].adc << 8) | cidx;
+ if (cidx < 0)
+ continue;
+ input_conn[i] = spec->imux_info[i].adc;
+ if (!spec->single_adc_amp)
+ input_conn[i] |= cidx << 8;
if (i > 0 && input_conn[i] != input_conn[0])
multi_connection = 1;
}
@@ -4330,6 +4305,15 @@ static int cx_auto_build_input_controls(struct hda_codec *codec)
err = cx_auto_add_capture_volume(codec, nid,
"Capture", "", cidx);
} else {
+ bool dup_found = false;
+ for (j = 0; j < i; j++) {
+ if (input_conn[j] == input_conn[i]) {
+ dup_found = true;
+ break;
+ }
+ }
+ if (dup_found)
+ continue;
err = cx_auto_add_capture_volume(codec, nid,
label, " Capture", cidx);
}
@@ -4348,6 +4332,7 @@ static int cx_auto_build_input_controls(struct hda_codec *codec)
static int cx_auto_build_controls(struct hda_codec *codec)
{
+ struct conexant_spec *spec = codec->spec;
int err;
err = cx_auto_build_output_controls(codec);
@@ -4356,7 +4341,20 @@ static int cx_auto_build_controls(struct hda_codec *codec)
err = cx_auto_build_input_controls(codec);
if (err < 0)
return err;
- return conexant_build_controls(codec);
+ err = conexant_build_controls(codec);
+ if (err < 0)
+ return err;
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
+ if (spec->vmaster_mute.sw_kctl) {
+ spec->vmaster_mute.hook = cx_auto_vmaster_hook;
+ err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute,
+ spec->vmaster_mute_led);
+ if (err < 0)
+ return err;
+ }
+ return 0;
}
static int cx_auto_search_adcs(struct hda_codec *codec)
@@ -4380,7 +4378,6 @@ static int cx_auto_search_adcs(struct hda_codec *codec)
return 0;
}
-
static const struct hda_codec_ops cx_auto_patch_ops = {
.build_controls = cx_auto_build_controls,
.build_pcms = conexant_build_pcms,
@@ -4393,6 +4390,70 @@ static const struct hda_codec_ops cx_auto_patch_ops = {
.reboot_notify = snd_hda_shutup_pins,
};
+/*
+ * pin fix-up
+ */
+struct cxt_pincfg {
+ hda_nid_t nid;
+ u32 val;
+};
+
+static void apply_pincfg(struct hda_codec *codec, const struct cxt_pincfg *cfg)
+{
+ for (; cfg->nid; cfg++)
+ snd_hda_codec_set_pincfg(codec, cfg->nid, cfg->val);
+
+}
+
+static void apply_pin_fixup(struct hda_codec *codec,
+ const struct snd_pci_quirk *quirk,
+ const struct cxt_pincfg **table)
+{
+ quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+ if (quirk) {
+ snd_printdd(KERN_INFO "hda_codec: applying pincfg for %s\n",
+ quirk->name);
+ apply_pincfg(codec, table[quirk->value]);
+ }
+}
+
+enum {
+ CXT_PINCFG_LENOVO_X200,
+};
+
+static const struct cxt_pincfg cxt_pincfg_lenovo_x200[] = {
+ { 0x16, 0x042140ff }, /* HP (seq# overridden) */
+ { 0x17, 0x21a11000 }, /* dock-mic */
+ { 0x19, 0x2121103f }, /* dock-HP */
+ { 0x1c, 0x21440100 }, /* dock SPDIF out */
+ {}
+};
+
+static const struct cxt_pincfg *cxt_pincfg_tbl[] = {
+ [CXT_PINCFG_LENOVO_X200] = cxt_pincfg_lenovo_x200,
+};
+
+static const struct snd_pci_quirk cxt_fixups[] = {
+ SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo X200", CXT_PINCFG_LENOVO_X200),
+ {}
+};
+
+/* add "fake" mute amp-caps to DACs on cx5051 so that mixer mute switches
+ * can be created (bko#42825)
+ */
+static void add_cx5051_fake_mutes(struct hda_codec *codec)
+{
+ static hda_nid_t out_nids[] = {
+ 0x10, 0x11, 0
+ };
+ hda_nid_t *p;
+
+ for (p = out_nids; *p; p++)
+ snd_hda_override_amp_caps(codec, *p, HDA_OUTPUT,
+ AC_AMPCAP_MIN_MUTE |
+ query_amp_caps(codec, *p, HDA_OUTPUT));
+}
+
static int patch_conexant_auto(struct hda_codec *codec)
{
struct conexant_spec *spec;
@@ -4406,6 +4467,30 @@ static int patch_conexant_auto(struct hda_codec *codec)
return -ENOMEM;
codec->spec = spec;
codec->pin_amp_workaround = 1;
+
+ switch (codec->vendor_id) {
+ case 0x14f15045:
+ spec->single_adc_amp = 1;
+ break;
+ case 0x14f15051:
+ add_cx5051_fake_mutes(codec);
+ break;
+ }
+
+ apply_pin_fixup(codec, cxt_fixups, cxt_pincfg_tbl);
+
+ /* Show mute-led control only on HP laptops
+ * This is a sort of white-list: on HP laptops, EAPD corresponds
+ * only to the mute-LED without actualy amp function. Meanwhile,
+ * others may use EAPD really as an amp switch, so it might be
+ * not good to expose it blindly.
+ */
+ switch (codec->subsystem_id >> 16) {
+ case 0x103c:
+ spec->vmaster_mute_led = 1;
+ break;
+ }
+
err = cx_auto_search_adcs(codec);
if (err < 0)
return err;
@@ -4419,6 +4504,18 @@ static int patch_conexant_auto(struct hda_codec *codec)
codec->patch_ops = cx_auto_patch_ops;
if (spec->beep_amp)
snd_hda_attach_beep_device(codec, spec->beep_amp);
+
+ /* Some laptops with Conexant chips show stalls in S3 resume,
+ * which falls into the single-cmd mode.
+ * Better to make reset, then.
+ */
+ if (!codec->bus->sync_write) {
+ snd_printd("hda_codec: "
+ "Enable sync_write for stable communication\n");
+ codec->bus->sync_write = 1;
+ codec->bus->allow_bus_reset = 1;
+ }
+
return 0;
}
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 19cb72db9c38..540cd13f7f15 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -31,11 +31,12 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_jack.h"
static bool static_hdmi_pcm;
module_param(static_hdmi_pcm, bool, 0644);
@@ -48,8 +49,8 @@ MODULE_PARM_DESC(static_hdmi_pcm, "Don't restrict PCM parameters per ELD info");
*
* The HDA correspondence of pipes/ports are converter/pin nodes.
*/
-#define MAX_HDMI_CVTS 4
-#define MAX_HDMI_PINS 4
+#define MAX_HDMI_CVTS 8
+#define MAX_HDMI_PINS 8
struct hdmi_spec_per_cvt {
hda_nid_t cvt_nid;
@@ -65,7 +66,11 @@ struct hdmi_spec_per_pin {
hda_nid_t pin_nid;
int num_mux_nids;
hda_nid_t mux_nids[HDA_MAX_CONNECTIONS];
+
+ struct hda_codec *codec;
struct hdmi_eld sink_eld;
+ struct delayed_work work;
+ int repoll_count;
};
struct hdmi_spec {
@@ -324,6 +329,66 @@ static int cvt_nid_to_cvt_index(struct hdmi_spec *spec, hda_nid_t cvt_nid)
return -EINVAL;
}
+static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hdmi_spec *spec;
+ int pin_idx;
+
+ spec = codec->spec;
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+
+ pin_idx = kcontrol->private_value;
+ uinfo->count = spec->pins[pin_idx].sink_eld.eld_size;
+
+ return 0;
+}
+
+static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct hdmi_spec *spec;
+ int pin_idx;
+
+ spec = codec->spec;
+ pin_idx = kcontrol->private_value;
+
+ memcpy(ucontrol->value.bytes.data,
+ spec->pins[pin_idx].sink_eld.eld_buffer, ELD_MAX_SIZE);
+
+ return 0;
+}
+
+static struct snd_kcontrol_new eld_bytes_ctl = {
+ .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
+ .iface = SNDRV_CTL_ELEM_IFACE_PCM,
+ .name = "ELD",
+ .info = hdmi_eld_ctl_info,
+ .get = hdmi_eld_ctl_get,
+};
+
+static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx,
+ int device)
+{
+ struct snd_kcontrol *kctl;
+ struct hdmi_spec *spec = codec->spec;
+ int err;
+
+ kctl = snd_ctl_new1(&eld_bytes_ctl, codec);
+ if (!kctl)
+ return -ENOMEM;
+ kctl->private_value = pin_idx;
+ kctl->id.device = device;
+
+ err = snd_hda_ctl_add(codec, spec->pins[pin_idx].pin_nid, kctl);
+ if (err < 0)
+ return err;
+
+ return 0;
+}
+
#ifdef BE_PARANOID
static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t pin_nid,
int *packet_index, int *byte_index)
@@ -685,17 +750,23 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, int pin_idx,
* Unsolicited events
*/
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
- struct hdmi_eld *eld);
+static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll);
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
{
struct hdmi_spec *spec = codec->spec;
- int pin_nid = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
+ int pin_nid;
int pd = !!(res & AC_UNSOL_RES_PD);
int eldv = !!(res & AC_UNSOL_RES_ELDV);
int pin_idx;
- struct hdmi_eld *eld;
+ struct hda_jack_tbl *jack;
+
+ jack = snd_hda_jack_tbl_get_from_tag(codec, tag);
+ if (!jack)
+ return;
+ pin_nid = jack->nid;
+ jack->jack_dirty = 1;
printk(KERN_INFO
"HDMI hot plug event: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
@@ -704,17 +775,9 @@ static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
pin_idx = pin_nid_to_pin_index(spec, pin_nid);
if (pin_idx < 0)
return;
- eld = &spec->pins[pin_idx].sink_eld;
-
- hdmi_present_sense(codec, pin_nid, eld);
- /*
- * HDMI sink's ELD info cannot always be retrieved for now, e.g.
- * in console or for audio devices. Assume the highest speakers
- * configuration, to _not_ prohibit multi-channel audio playback.
- */
- if (!eld->spk_alloc)
- eld->spk_alloc = 0xffff;
+ hdmi_present_sense(&spec->pins[pin_idx], 1);
+ snd_hda_jack_report_sync(codec);
}
static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
@@ -742,11 +805,10 @@ static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
static void hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
{
- struct hdmi_spec *spec = codec->spec;
int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
- if (pin_nid_to_pin_index(spec, tag) < 0) {
+ if (!snd_hda_jack_tbl_get_from_tag(codec, tag)) {
snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
return;
}
@@ -908,9 +970,11 @@ static int hdmi_read_pin_conn(struct hda_codec *codec, int pin_idx)
return 0;
}
-static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
- struct hdmi_eld *eld)
+static void hdmi_present_sense(struct hdmi_spec_per_pin *per_pin, int repoll)
{
+ struct hda_codec *codec = per_pin->codec;
+ struct hdmi_eld *eld = &per_pin->sink_eld;
+ hda_nid_t pin_nid = per_pin->pin_nid;
/*
* Always execute a GetPinSense verb here, even when called from
* hdmi_intrinsic_event; for some NVIDIA HW, the unsolicited
@@ -920,24 +984,38 @@ static void hdmi_present_sense(struct hda_codec *codec, hda_nid_t pin_nid,
* the unsolicited response to avoid custom WARs.
*/
int present = snd_hda_pin_sense(codec, pin_nid);
+ bool eld_valid = false;
- memset(eld, 0, sizeof(*eld));
+ memset(eld, 0, offsetof(struct hdmi_eld, eld_buffer));
eld->monitor_present = !!(present & AC_PINSENSE_PRESENCE);
if (eld->monitor_present)
- eld->eld_valid = !!(present & AC_PINSENSE_ELDV);
- else
- eld->eld_valid = 0;
+ eld_valid = !!(present & AC_PINSENSE_ELDV);
printk(KERN_INFO
"HDMI status: Codec=%d Pin=%d Presence_Detect=%d ELD_Valid=%d\n",
- codec->addr, pin_nid, eld->monitor_present, eld->eld_valid);
+ codec->addr, pin_nid, eld->monitor_present, eld_valid);
- if (eld->eld_valid)
+ if (eld_valid) {
if (!snd_hdmi_get_eld(eld, codec, pin_nid))
snd_hdmi_show_eld(eld);
+ else if (repoll) {
+ queue_delayed_work(codec->bus->workq,
+ &per_pin->work,
+ msecs_to_jiffies(300));
+ }
+ }
+}
- snd_hda_input_jack_report(codec, pin_nid);
+static void hdmi_repoll_eld(struct work_struct *work)
+{
+ struct hdmi_spec_per_pin *per_pin =
+ container_of(to_delayed_work(work), struct hdmi_spec_per_pin, work);
+
+ if (per_pin->repoll_count++ > 6)
+ per_pin->repoll_count = 0;
+
+ hdmi_present_sense(per_pin, per_pin->repoll_count);
}
static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
@@ -946,7 +1024,6 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
unsigned int caps, config;
int pin_idx;
struct hdmi_spec_per_pin *per_pin;
- struct hdmi_eld *eld;
int err;
caps = snd_hda_param_read(codec, pin_nid, AC_PAR_PIN_CAP);
@@ -963,23 +1040,15 @@ static int hdmi_add_pin(struct hda_codec *codec, hda_nid_t pin_nid)
pin_idx = spec->num_pins;
per_pin = &spec->pins[pin_idx];
- eld = &per_pin->sink_eld;
per_pin->pin_nid = pin_nid;
- err = snd_hda_input_jack_add(codec, pin_nid,
- SND_JACK_VIDEOOUT, NULL);
- if (err < 0)
- return err;
-
err = hdmi_read_pin_conn(codec, pin_idx);
if (err < 0)
return err;
spec->num_pins++;
- hdmi_present_sense(codec, pin_nid, eld);
-
return 0;
}
@@ -1064,12 +1133,12 @@ static int hdmi_parse_codec(struct hda_codec *codec)
/*
*/
-static char *generic_hdmi_pcm_names[MAX_HDMI_PINS] = {
- "HDMI 0",
- "HDMI 1",
- "HDMI 2",
- "HDMI 3",
-};
+static char *get_hdmi_pcm_name(int idx)
+{
+ static char names[MAX_HDMI_PINS][8];
+ sprintf(&names[idx][0], "HDMI %d", idx);
+ return &names[idx][0];
+}
/*
* HDMI callbacks
@@ -1147,7 +1216,7 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
struct hda_pcm_stream *pstr;
info = &spec->pcm_rec[pin_idx];
- info->name = generic_hdmi_pcm_names[pin_idx];
+ info->name = get_hdmi_pcm_name(pin_idx);
info->pcm_type = HDA_PCM_TYPE_HDMI;
pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
@@ -1162,6 +1231,19 @@ static int generic_hdmi_build_pcms(struct hda_codec *codec)
return 0;
}
+static int generic_hdmi_build_jack(struct hda_codec *codec, int pin_idx)
+{
+ char hdmi_str[32] = "HDMI/DP";
+ struct hdmi_spec *spec = codec->spec;
+ struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+ int pcmdev = spec->pcm_rec[pin_idx].device;
+
+ if (pcmdev > 0)
+ sprintf(hdmi_str + strlen(hdmi_str), ",pcm=%d", pcmdev);
+
+ return snd_hda_jack_add_kctl(codec, per_pin->pin_nid, hdmi_str, 0);
+}
+
static int generic_hdmi_build_controls(struct hda_codec *codec)
{
struct hdmi_spec *spec = codec->spec;
@@ -1170,12 +1252,27 @@ static int generic_hdmi_build_controls(struct hda_codec *codec)
for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) {
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
+
+ err = generic_hdmi_build_jack(codec, pin_idx);
+ if (err < 0)
+ return err;
+
err = snd_hda_create_spdif_out_ctls(codec,
per_pin->pin_nid,
per_pin->mux_nids[0]);
if (err < 0)
return err;
snd_hda_spdif_ctls_unassign(codec, pin_idx);
+
+ /* add control for ELD Bytes */
+ err = hdmi_create_eld_ctl(codec,
+ pin_idx,
+ spec->pcm_rec[pin_idx].device);
+
+ if (err < 0)
+ return err;
+
+ hdmi_present_sense(per_pin, 0);
}
return 0;
@@ -1192,12 +1289,13 @@ static int generic_hdmi_init(struct hda_codec *codec)
struct hdmi_eld *eld = &per_pin->sink_eld;
hdmi_init_pin(codec, pin_nid);
- snd_hda_codec_write(codec, pin_nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | pin_nid);
+ snd_hda_jack_detect_enable(codec, pin_nid, pin_nid);
+ per_pin->codec = codec;
+ INIT_DELAYED_WORK(&per_pin->work, hdmi_repoll_eld);
snd_hda_eld_proc_new(codec, eld, pin_idx);
}
+ snd_hda_jack_report_sync(codec);
return 0;
}
@@ -1210,10 +1308,11 @@ static void generic_hdmi_free(struct hda_codec *codec)
struct hdmi_spec_per_pin *per_pin = &spec->pins[pin_idx];
struct hdmi_eld *eld = &per_pin->sink_eld;
+ cancel_delayed_work(&per_pin->work);
snd_hda_eld_proc_free(codec, eld);
}
- snd_hda_input_jack_free(codec);
+ flush_workqueue(codec->bus->workq);
kfree(spec);
}
@@ -1266,7 +1365,7 @@ static int simple_playback_build_pcms(struct hda_codec *codec)
chans = get_wcaps(codec, spec->cvts[i].cvt_nid);
chans = get_wcaps_channels(chans);
- info->name = generic_hdmi_pcm_names[i];
+ info->name = get_hdmi_pcm_name(i);
info->pcm_type = HDA_PCM_TYPE_HDMI;
pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK];
snd_BUG_ON(!spec->pcm_playback);
@@ -1491,7 +1590,7 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
struct snd_pcm_substream *substream)
{
int chs;
- unsigned int dataDCC1, dataDCC2, channel_id;
+ unsigned int dataDCC2, channel_id;
int i;
struct hdmi_spec *spec = codec->spec;
struct hda_spdif_out *spdif =
@@ -1501,7 +1600,6 @@ static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo,
chs = substream->runtime->channels;
- dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT;
dataDCC2 = 0x2;
/* turn off SPDIF once; otherwise the IEC958 bits won't be updated */
@@ -1814,6 +1912,7 @@ static const struct hda_codec_preset snd_hda_preset_hdmi[] = {
{ .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi },
{ .id = 0x80862806, .name = "PantherPoint HDMI", .patch = patch_generic_hdmi },
+{ .id = 0x80862880, .name = "CedarTrail HDMI", .patch = patch_generic_hdmi },
{ .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi },
{} /* terminator */
};
@@ -1860,6 +1959,7 @@ MODULE_ALIAS("snd-hda-codec-id:80862803");
MODULE_ALIAS("snd-hda-codec-id:80862804");
MODULE_ALIAS("snd-hda-codec-id:80862805");
MODULE_ALIAS("snd-hda-codec-id:80862806");
+MODULE_ALIAS("snd-hda-codec-id:80862880");
MODULE_ALIAS("snd-hda-codec-id:808629fb");
MODULE_LICENSE("GPL");
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 7cabd7317163..8ea2fd654327 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -27,11 +27,13 @@
#include <linux/delay.h>
#include <linux/slab.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
#include "hda_beep.h"
+#include "hda_jack.h"
/* unsol event tags */
#define ALC_FRONT_EVENT 0x01
@@ -78,6 +80,8 @@ enum {
ALC_AUTOMUTE_MIXER, /* mute/unmute mixer widget AMP */
};
+#define MAX_VOL_NIDS 0x40
+
struct alc_spec {
/* codec parameterization */
const struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
@@ -116,6 +120,8 @@ struct alc_spec {
const hda_nid_t *capsrc_nids;
hda_nid_t dig_in_nid; /* digital-in NID; optional */
hda_nid_t mixer_nid; /* analog-mixer NID */
+ DECLARE_BITMAP(vol_ctls, MAX_VOL_NIDS << 1);
+ DECLARE_BITMAP(sw_ctls, MAX_VOL_NIDS << 1);
/* capture setup for dynamic dual-adc switch */
hda_nid_t cur_adc;
@@ -159,23 +165,29 @@ struct alc_spec {
void (*power_hook)(struct hda_codec *codec);
#endif
void (*shutup)(struct hda_codec *codec);
+ void (*automute_hook)(struct hda_codec *codec);
/* for pin sensing */
- unsigned int jack_present: 1;
+ unsigned int hp_jack_present:1;
unsigned int line_jack_present:1;
unsigned int master_mute:1;
unsigned int auto_mic:1;
unsigned int auto_mic_valid_imux:1; /* valid imux for auto-mic */
- unsigned int automute:1; /* HP automute enabled */
- unsigned int detect_line:1; /* Line-out detection enabled */
- unsigned int automute_lines:1; /* automute line-out as well */
- unsigned int automute_hp_lo:1; /* both HP and LO available */
+ unsigned int automute_speaker:1; /* automute speaker outputs */
+ unsigned int automute_lo:1; /* automute LO outputs */
+ unsigned int detect_hp:1; /* Headphone detection enabled */
+ unsigned int detect_lo:1; /* Line-out detection enabled */
+ unsigned int automute_speaker_possible:1; /* there are speakers and either LO or HP */
+ unsigned int automute_lo_possible:1; /* there are line outs and HP */
+ unsigned int keep_vref_in_automute:1; /* Don't clear VREF in automute */
/* other flags */
unsigned int no_analog :1; /* digital I/O only */
unsigned int dyn_adc_switch:1; /* switch ADCs (for ALC275) */
unsigned int single_input_src:1;
unsigned int vol_in_capsrc:1; /* use capsrc volume (ADC has no vol) */
+ unsigned int parse_flags; /* passed to snd_hda_parse_pin_defcfg() */
+ unsigned int shared_mic_hp:1; /* HP/Mic-in sharing */
/* auto-mute control */
int automute_mode;
@@ -186,13 +198,17 @@ struct alc_spec {
/* for virtual master */
hda_nid_t vmaster_nid;
+ struct hda_vmaster_mute_hook vmaster_mute;
#ifdef CONFIG_SND_HDA_POWER_SAVE
struct hda_loopback_check loopback;
+ int num_loopbacks;
+ struct hda_amp_list loopback_list[8];
#endif
/* for PLL fix */
hda_nid_t pll_nid;
unsigned int pll_coef_idx, pll_coef_bit;
+ unsigned int coef0;
/* fix-up list */
int fixup_id;
@@ -202,9 +218,10 @@ struct alc_spec {
/* multi-io */
int multi_ios;
struct alc_multi_io multi_io[4];
-};
-#define ALC_MODEL_AUTO 0 /* common for all chips */
+ /* bind volumes */
+ struct snd_array bind_ctls;
+};
static bool check_amp_caps(struct hda_codec *codec, hda_nid_t nid,
int dir, unsigned int bits)
@@ -266,6 +283,14 @@ static bool alc_dyn_adc_pcm_resetup(struct hda_codec *codec, int cur)
return false;
}
+static inline hda_nid_t get_capsrc(struct alc_spec *spec, int idx)
+{
+ return spec->capsrc_nids ?
+ spec->capsrc_nids[idx] : spec->adc_nids[idx];
+}
+
+static void call_update_outputs(struct hda_codec *codec);
+
/* select the given imux item; either unmute exclusively or select the route */
static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
unsigned int idx, bool force)
@@ -273,13 +298,18 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
struct alc_spec *spec = codec->spec;
const struct hda_input_mux *imux;
unsigned int mux_idx;
- int i, type;
+ int i, type, num_conns;
hda_nid_t nid;
+ if (!spec->input_mux)
+ return 0;
+
mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
imux = &spec->input_mux[mux_idx];
if (!imux->num_items && mux_idx > 0)
imux = &spec->input_mux[0];
+ if (!imux->num_items)
+ return 0;
if (idx >= imux->num_items)
idx = imux->num_items - 1;
@@ -287,25 +317,38 @@ static int alc_mux_select(struct hda_codec *codec, unsigned int adc_idx,
return 0;
spec->cur_mux[adc_idx] = idx;
+ /* for shared I/O, change the pin-control accordingly */
+ if (spec->shared_mic_hp) {
+ /* NOTE: this assumes that there are only two inputs, the
+ * first is the real internal mic and the second is HP jack.
+ */
+ snd_hda_codec_write(codec, spec->autocfg.inputs[1].pin, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ spec->cur_mux[adc_idx] ?
+ PIN_VREF80 : PIN_HP);
+ spec->automute_speaker = !spec->cur_mux[adc_idx];
+ call_update_outputs(codec);
+ }
+
if (spec->dyn_adc_switch) {
alc_dyn_adc_pcm_resetup(codec, idx);
adc_idx = spec->dyn_adc_idx[idx];
}
- nid = spec->capsrc_nids ?
- spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
+ nid = get_capsrc(spec, adc_idx);
/* no selection? */
- if (snd_hda_get_conn_list(codec, nid, NULL) <= 1)
+ num_conns = snd_hda_get_conn_list(codec, nid, NULL);
+ if (num_conns <= 1)
return 1;
type = get_wcaps_type(get_wcaps(codec, nid));
if (type == AC_WID_AUD_MIX) {
/* Matrix-mixer style (e.g. ALC882) */
- for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
- imux->items[i].index,
+ int active = imux->items[idx].index;
+ for (i = 0; i < num_conns; i++) {
+ unsigned int v = (i == active) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT, i,
HDA_AMP_MUTE, v);
}
} else {
@@ -431,46 +474,6 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid,
}
/*
- * Jack-reporting via input-jack layer
- */
-
-/* initialization of jacks; currently checks only a few known pins */
-static int alc_init_jacks(struct hda_codec *codec)
-{
-#ifdef CONFIG_SND_HDA_INPUT_JACK
- struct alc_spec *spec = codec->spec;
- int err;
- unsigned int hp_nid = spec->autocfg.hp_pins[0];
- unsigned int mic_nid = spec->ext_mic_pin;
- unsigned int dock_nid = spec->dock_mic_pin;
-
- if (hp_nid) {
- err = snd_hda_input_jack_add(codec, hp_nid,
- SND_JACK_HEADPHONE, NULL);
- if (err < 0)
- return err;
- snd_hda_input_jack_report(codec, hp_nid);
- }
-
- if (mic_nid) {
- err = snd_hda_input_jack_add(codec, mic_nid,
- SND_JACK_MICROPHONE, NULL);
- if (err < 0)
- return err;
- snd_hda_input_jack_report(codec, mic_nid);
- }
- if (dock_nid) {
- err = snd_hda_input_jack_add(codec, dock_nid,
- SND_JACK_MICROPHONE, NULL);
- if (err < 0)
- return err;
- snd_hda_input_jack_report(codec, dock_nid);
- }
-#endif /* CONFIG_SND_HDA_INPUT_JACK */
- return 0;
-}
-
-/*
* Jack detections for HP auto-mute and mic-switch
*/
@@ -483,7 +486,6 @@ static bool detect_jacks(struct hda_codec *codec, int num_pins, hda_nid_t *pins)
hda_nid_t nid = pins[i];
if (!nid)
break;
- snd_hda_input_jack_report(codec, nid);
present |= snd_hda_jack_detect(codec, nid);
}
return present;
@@ -500,13 +502,24 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
for (i = 0; i < num_pins; i++) {
hda_nid_t nid = pins[i];
+ unsigned int val;
if (!nid)
break;
switch (spec->automute_mode) {
case ALC_AUTOMUTE_PIN:
+ /* don't reset VREF value in case it's controlling
+ * the amp (see alc861_fixup_asus_amp_vref_0f())
+ */
+ if (spec->keep_vref_in_automute) {
+ val = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ val &= ~PIN_HP;
+ } else
+ val = 0;
+ val |= pin_bits;
snd_hda_codec_write(codec, nid, 0,
AC_VERB_SET_PIN_WIDGET_CONTROL,
- pin_bits);
+ val);
break;
case ALC_AUTOMUTE_AMP:
snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
@@ -525,8 +538,8 @@ static void do_automute(struct hda_codec *codec, int num_pins, hda_nid_t *pins,
}
}
-/* Toggle internal speakers muting */
-static void update_speakers(struct hda_codec *codec)
+/* Toggle outputs muting */
+static void update_outputs(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
int on;
@@ -535,13 +548,14 @@ static void update_speakers(struct hda_codec *codec)
* in general, HP pins/amps control should be enabled in all cases,
* but currently set only for master_mute, just to be safe
*/
- do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
+ if (!spec->shared_mic_hp) /* don't change HP-pin when shared with mic */
+ do_automute(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
spec->autocfg.hp_pins, spec->master_mute, true);
- if (!spec->automute)
+ if (!spec->automute_speaker)
on = 0;
else
- on = spec->jack_present | spec->line_jack_present;
+ on = spec->hp_jack_present | spec->line_jack_present;
on |= spec->master_mute;
do_automute(codec, ARRAY_SIZE(spec->autocfg.speaker_pins),
spec->autocfg.speaker_pins, on, false);
@@ -551,26 +565,35 @@ static void update_speakers(struct hda_codec *codec)
if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0] ||
spec->autocfg.line_out_pins[0] == spec->autocfg.speaker_pins[0])
return;
- if (!spec->automute_lines || !spec->automute)
+ if (!spec->automute_lo)
on = 0;
else
- on = spec->jack_present;
+ on = spec->hp_jack_present;
on |= spec->master_mute;
do_automute(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
spec->autocfg.line_out_pins, on, false);
}
+static void call_update_outputs(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ if (spec->automute_hook)
+ spec->automute_hook(codec);
+ else
+ update_outputs(codec);
+}
+
/* standard HP-automute helper */
static void alc_hp_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- spec->jack_present =
+ spec->hp_jack_present =
detect_jacks(codec, ARRAY_SIZE(spec->autocfg.hp_pins),
spec->autocfg.hp_pins);
- if (!spec->automute)
+ if (!spec->detect_hp || (!spec->automute_speaker && !spec->automute_lo))
return;
- update_speakers(codec);
+ call_update_outputs(codec);
}
/* standard line-out-automute helper */
@@ -578,12 +601,16 @@ static void alc_line_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ /* check LO jack only when it's different from HP */
+ if (spec->autocfg.line_out_pins[0] == spec->autocfg.hp_pins[0])
+ return;
+
spec->line_jack_present =
detect_jacks(codec, ARRAY_SIZE(spec->autocfg.line_out_pins),
spec->autocfg.line_out_pins);
- if (!spec->automute || !spec->detect_line)
+ if (!spec->automute_speaker || !spec->detect_lo)
return;
- update_speakers(codec);
+ call_update_outputs(codec);
}
#define get_connection_index(codec, mux, nid) \
@@ -609,20 +636,12 @@ static void alc_mic_automute(struct hda_codec *codec)
alc_mux_select(codec, 0, spec->dock_mic_idx, false);
else
alc_mux_select(codec, 0, spec->int_mic_idx, false);
-
- snd_hda_input_jack_report(codec, pins[spec->ext_mic_idx]);
- if (spec->dock_mic_idx >= 0)
- snd_hda_input_jack_report(codec, pins[spec->dock_mic_idx]);
}
-/* unsolicited event for HP jack sensing */
-static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
+/* handle the specified unsol action (ALC_XXX_EVENT) */
+static void alc_exec_unsol_event(struct hda_codec *codec, int action)
{
- if (codec->vendor_id == 0x10ec0880)
- res >>= 28;
- else
- res >>= 26;
- switch (res) {
+ switch (action) {
case ALC_HP_EVENT:
alc_hp_automute(codec);
break;
@@ -633,6 +652,54 @@ static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
alc_mic_automute(codec);
break;
}
+ snd_hda_jack_report_sync(codec);
+}
+
+/* update the master volume per volume-knob's unsol event */
+static void alc_update_knob_master(struct hda_codec *codec, hda_nid_t nid)
+{
+ unsigned int val;
+ struct snd_kcontrol *kctl;
+ struct snd_ctl_elem_value *uctl;
+
+ kctl = snd_hda_find_mixer_ctl(codec, "Master Playback Volume");
+ if (!kctl)
+ return;
+ uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
+ if (!uctl)
+ return;
+ val = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
+ val &= HDA_AMP_VOLMASK;
+ uctl->value.integer.value[0] = val;
+ uctl->value.integer.value[1] = val;
+ kctl->put(kctl, uctl);
+ kfree(uctl);
+}
+
+/* unsolicited event for HP jack sensing */
+static void alc_sku_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ int action;
+
+ if (codec->vendor_id == 0x10ec0880)
+ res >>= 28;
+ else
+ res >>= 26;
+ action = snd_hda_jack_get_action(codec, res);
+ if (action == ALC_DCVOL_EVENT) {
+ /* Execute the dc-vol event here as it requires the NID
+ * but we don't pass NID to alc_exec_unsol_event().
+ * Once when we convert all static quirks to the auto-parser,
+ * this can be integerated into there.
+ */
+ struct hda_jack_tbl *jack;
+ jack = snd_hda_jack_tbl_get_from_tag(codec, res);
+ if (jack)
+ alc_update_knob_master(codec, jack->nid);
+ return;
+ }
+ alc_exec_unsol_event(codec, action);
}
/* call init functions of standard auto-mute helpers */
@@ -775,13 +842,13 @@ static int alc_automute_mode_info(struct snd_kcontrol *kcontrol,
"Disabled", "Enabled"
};
static const char * const texts3[] = {
- "Disabled", "Speaker Only", "Line-Out+Speaker"
+ "Disabled", "Speaker Only", "Line Out+Speaker"
};
const char * const *texts;
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- if (spec->automute_hp_lo) {
+ if (spec->automute_speaker_possible && spec->automute_lo_possible) {
uinfo->value.enumerated.items = 3;
texts = texts3;
} else {
@@ -800,13 +867,12 @@ static int alc_automute_mode_get(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- unsigned int val;
- if (!spec->automute)
- val = 0;
- else if (!spec->automute_lines)
- val = 1;
- else
- val = 2;
+ unsigned int val = 0;
+ if (spec->automute_speaker)
+ val++;
+ if (spec->automute_lo)
+ val++;
+
ucontrol->value.enumerated.item[0] = val;
return 0;
}
@@ -819,28 +885,36 @@ static int alc_automute_mode_put(struct snd_kcontrol *kcontrol,
switch (ucontrol->value.enumerated.item[0]) {
case 0:
- if (!spec->automute)
+ if (!spec->automute_speaker && !spec->automute_lo)
return 0;
- spec->automute = 0;
+ spec->automute_speaker = 0;
+ spec->automute_lo = 0;
break;
case 1:
- if (spec->automute && !spec->automute_lines)
- return 0;
- spec->automute = 1;
- spec->automute_lines = 0;
+ if (spec->automute_speaker_possible) {
+ if (!spec->automute_lo && spec->automute_speaker)
+ return 0;
+ spec->automute_speaker = 1;
+ spec->automute_lo = 0;
+ } else if (spec->automute_lo_possible) {
+ if (spec->automute_lo)
+ return 0;
+ spec->automute_lo = 1;
+ } else
+ return -EINVAL;
break;
case 2:
- if (!spec->automute_hp_lo)
+ if (!spec->automute_lo_possible || !spec->automute_speaker_possible)
return -EINVAL;
- if (spec->automute && spec->automute_lines)
+ if (spec->automute_speaker && spec->automute_lo)
return 0;
- spec->automute = 1;
- spec->automute_lines = 1;
+ spec->automute_speaker = 1;
+ spec->automute_lo = 1;
break;
default:
return -EINVAL;
}
- update_speakers(codec);
+ call_update_outputs(codec);
return 1;
}
@@ -877,7 +951,7 @@ static int alc_add_automute_mode_enum(struct hda_codec *codec)
* Check the availability of HP/line-out auto-mute;
* Set up appropriately if really supported
*/
-static void alc_init_auto_hp(struct hda_codec *codec)
+static void alc_init_automute(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -892,8 +966,6 @@ static void alc_init_auto_hp(struct hda_codec *codec)
present++;
if (present < 2) /* need two different output types */
return;
- if (present == 3)
- spec->automute_hp_lo = 1; /* both HP and LO automute */
if (!cfg->speaker_pins[0] &&
cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
@@ -909,37 +981,40 @@ static void alc_init_auto_hp(struct hda_codec *codec)
cfg->hp_outs = cfg->line_outs;
}
+ spec->automute_mode = ALC_AUTOMUTE_PIN;
+
for (i = 0; i < cfg->hp_outs; i++) {
hda_nid_t nid = cfg->hp_pins[i];
if (!is_jack_detectable(codec, nid))
continue;
snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n",
nid);
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | ALC_HP_EVENT);
- spec->automute = 1;
- spec->automute_mode = ALC_AUTOMUTE_PIN;
- }
- if (spec->automute && cfg->line_out_pins[0] &&
- cfg->speaker_pins[0] &&
- cfg->line_out_pins[0] != cfg->hp_pins[0] &&
- cfg->line_out_pins[0] != cfg->speaker_pins[0]) {
- for (i = 0; i < cfg->line_outs; i++) {
- hda_nid_t nid = cfg->line_out_pins[i];
- if (!is_jack_detectable(codec, nid))
- continue;
- snd_printdd("realtek: Enable Line-Out auto-muting "
- "on NID 0x%x\n", nid);
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | ALC_FRONT_EVENT);
- spec->detect_line = 1;
+ snd_hda_jack_detect_enable(codec, nid, ALC_HP_EVENT);
+ spec->detect_hp = 1;
+ }
+
+ if (cfg->line_out_type == AUTO_PIN_LINE_OUT && cfg->line_outs) {
+ if (cfg->speaker_outs)
+ for (i = 0; i < cfg->line_outs; i++) {
+ hda_nid_t nid = cfg->line_out_pins[i];
+ if (!is_jack_detectable(codec, nid))
+ continue;
+ snd_printdd("realtek: Enable Line-Out "
+ "auto-muting on NID 0x%x\n", nid);
+ snd_hda_jack_detect_enable(codec, nid,
+ ALC_FRONT_EVENT);
+ spec->detect_lo = 1;
}
- spec->automute_lines = spec->detect_line;
+ spec->automute_lo_possible = spec->detect_hp;
}
- if (spec->automute) {
+ spec->automute_speaker_possible = cfg->speaker_outs &&
+ (spec->detect_hp || spec->detect_lo);
+
+ spec->automute_lo = spec->automute_lo_possible;
+ spec->automute_speaker = spec->automute_speaker_possible;
+
+ if (spec->automute_speaker_possible || spec->automute_lo_possible) {
/* create a control for automute mode */
alc_add_automute_mode_enum(codec);
spec->unsol_event = alc_sku_unsol_event;
@@ -998,34 +1073,6 @@ static bool alc_check_dyn_adc_switch(struct hda_codec *codec)
return true;
}
-/* rebuild imux for matching with the given auto-mic pins (if not yet) */
-static bool alc_rebuild_imux_for_auto_mic(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
- struct hda_input_mux *imux;
- static char * const texts[3] = {
- "Mic", "Internal Mic", "Dock Mic"
- };
- int i;
-
- if (!spec->auto_mic)
- return false;
- imux = &spec->private_imux[0];
- if (spec->input_mux == imux)
- return true;
- spec->imux_pins[0] = spec->ext_mic_pin;
- spec->imux_pins[1] = spec->int_mic_pin;
- spec->imux_pins[2] = spec->dock_mic_pin;
- for (i = 0; i < 3; i++) {
- strcpy(imux->items[i].label, texts[i]);
- if (spec->imux_pins[i])
- imux->num_items = i + 1;
- }
- spec->num_mux_defs = 1;
- spec->input_mux = imux;
- return true;
-}
-
/* check whether all auto-mic pins are valid; setup indices if OK */
static bool alc_auto_mic_check_imux(struct hda_codec *codec)
{
@@ -1055,13 +1102,10 @@ static bool alc_auto_mic_check_imux(struct hda_codec *codec)
return false; /* no corresponding imux */
}
- snd_hda_codec_write_cache(codec, spec->ext_mic_pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | ALC_MIC_EVENT);
+ snd_hda_jack_detect_enable(codec, spec->ext_mic_pin, ALC_MIC_EVENT);
if (spec->dock_mic_pin)
- snd_hda_codec_write_cache(codec, spec->dock_mic_pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | ALC_MIC_EVENT);
+ snd_hda_jack_detect_enable(codec, spec->dock_mic_pin,
+ ALC_MIC_EVENT);
spec->auto_mic_valid_imux = 1;
spec->auto_mic = 1;
@@ -1079,6 +1123,9 @@ static void alc_init_auto_mic(struct hda_codec *codec)
hda_nid_t fixed, ext, dock;
int i;
+ if (spec->shared_mic_hp)
+ return; /* no auto-mic for the shared I/O */
+
spec->ext_mic_idx = spec->int_mic_idx = spec->dock_mic_idx = -1;
fixed = ext = dock = 0;
@@ -1140,7 +1187,7 @@ static void alc_init_auto_mic(struct hda_codec *codec)
/* check the availabilities of auto-mute and auto-mic switches */
static void alc_auto_check_switches(struct hda_codec *codec)
{
- alc_init_auto_hp(codec);
+ alc_init_automute(codec);
alc_init_auto_mic(codec);
}
@@ -1320,7 +1367,9 @@ do_sku:
* 15 : 1 --> enable the function "Mute internal speaker
* when the external headphone out jack is plugged"
*/
- if (!spec->autocfg.hp_pins[0]) {
+ if (!spec->autocfg.hp_pins[0] &&
+ !(spec->autocfg.line_out_pins[0] &&
+ spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
hda_nid_t nid;
tmp = (ass >> 11) & 0x3; /* HP to chassis */
if (tmp == 0)
@@ -1393,6 +1442,7 @@ enum {
ALC_FIXUP_ACT_PRE_PROBE,
ALC_FIXUP_ACT_PROBE,
ALC_FIXUP_ACT_INIT,
+ ALC_FIXUP_ACT_BUILD,
};
static void alc_apply_fixup(struct hda_codec *codec, int action)
@@ -1414,7 +1464,7 @@ static void alc_apply_fixup(struct hda_codec *codec, int action)
switch (fix->type) {
case ALC_FIXUP_SKU:
if (action != ALC_FIXUP_ACT_PRE_PROBE || !fix->v.sku)
- break;;
+ break;
snd_printdd(KERN_INFO "hda_codec: %s: "
"Apply sku override for %s\n",
codec->chip_name, modelname);
@@ -1468,9 +1518,17 @@ static void alc_pick_fixup(struct hda_codec *codec,
const struct alc_fixup *fixlist)
{
struct alc_spec *spec = codec->spec;
+ const struct snd_pci_quirk *q;
int id = -1;
const char *name = NULL;
+ /* when model=nofixup is given, don't pick up any fixups */
+ if (codec->modelname && !strcmp(codec->modelname, "nofixup")) {
+ spec->fixup_list = NULL;
+ spec->fixup_id = -1;
+ return;
+ }
+
if (codec->modelname && models) {
while (models->name) {
if (!strcmp(codec->modelname, models->name)) {
@@ -1482,12 +1540,25 @@ static void alc_pick_fixup(struct hda_codec *codec,
}
}
if (id < 0) {
- quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk);
- if (quirk) {
- id = quirk->value;
+ q = snd_pci_quirk_lookup(codec->bus->pci, quirk);
+ if (q) {
+ id = q->value;
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ name = q->name;
+#endif
+ }
+ }
+ if (id < 0) {
+ for (q = quirk; q->subvendor; q++) {
+ unsigned int vendorid =
+ q->subdevice | (q->subvendor << 16);
+ if (vendorid == codec->subsystem_id) {
+ id = q->value;
#ifdef CONFIG_SND_DEBUG_VERBOSE
- name = quirk->name;
+ name = q->name;
#endif
+ break;
+ }
}
}
@@ -1521,6 +1592,15 @@ static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx,
coef_val);
}
+/* a special bypass for COEF 0; read the cached value at the second time */
+static unsigned int alc_get_coef0(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ if (!spec->coef0)
+ spec->coef0 = alc_read_coef_idx(codec, 0);
+ return spec->coef0;
+}
+
/*
* Digital I/O handling
*/
@@ -1559,27 +1639,29 @@ static void alc_auto_init_digital(struct hda_codec *codec)
static void alc_auto_parse_digital(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- int i, err;
+ int i, err, nums;
hda_nid_t dig_nid;
/* support multiple SPDIFs; the secondary is set up as a slave */
+ nums = 0;
for (i = 0; i < spec->autocfg.dig_outs; i++) {
hda_nid_t conn[4];
err = snd_hda_get_connections(codec,
spec->autocfg.dig_out_pins[i],
conn, ARRAY_SIZE(conn));
- if (err < 0)
+ if (err <= 0)
continue;
dig_nid = conn[0]; /* assume the first element is audio-out */
- if (!i) {
+ if (!nums) {
spec->multiout.dig_out_nid = dig_nid;
spec->dig_out_type = spec->autocfg.dig_out_type[0];
} else {
spec->multiout.slave_dig_outs = spec->slave_dig_outs;
- if (i >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
+ if (nums >= ARRAY_SIZE(spec->slave_dig_outs) - 1)
break;
- spec->slave_dig_outs[i - 1] = dig_nid;
+ spec->slave_dig_outs[nums - 1] = dig_nid;
}
+ nums++;
}
if (spec->autocfg.dig_in_pin) {
@@ -1774,32 +1856,10 @@ DEFINE_CAPMIX_NOSRC(3);
/*
* slave controls for virtual master
*/
-static const char * const alc_slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "Headphone Playback Volume",
- "Speaker Playback Volume",
- "Mono Playback Volume",
- "Line-Out Playback Volume",
- "PCM Playback Volume",
- NULL,
-};
-
-static const char * const alc_slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "Headphone Playback Switch",
- "Speaker Playback Switch",
- "Mono Playback Switch",
- "IEC958 Playback Switch",
- "Line-Out Playback Switch",
- "PCM Playback Switch",
+static const char * const alc_slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side",
+ "Headphone", "Speaker", "Mono", "Line Out",
+ "CLFE", "Bass Speaker", "PCM",
NULL,
};
@@ -1827,7 +1887,7 @@ static const struct snd_kcontrol_new alc_beep_mixer[] = {
};
#endif
-static int alc_build_controls(struct hda_codec *codec)
+static int __alc_build_controls(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
struct snd_kcontrol *kctl = NULL;
@@ -1890,14 +1950,17 @@ static int alc_build_controls(struct hda_codec *codec)
snd_hda_set_vmaster_tlv(codec, spec->vmaster_nid,
HDA_OUTPUT, vmaster_tlv);
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
- vmaster_tlv, alc_slave_vols);
+ vmaster_tlv, alc_slave_pfxs,
+ "Playback Volume");
if (err < 0)
return err;
}
if (!spec->no_analog &&
!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
- err = snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, alc_slave_sws);
+ err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+ NULL, alc_slave_pfxs,
+ "Playback Switch",
+ true, &spec->vmaster_mute.sw_kctl);
if (err < 0)
return err;
}
@@ -1908,10 +1971,8 @@ static int alc_build_controls(struct hda_codec *codec)
if (!kctl)
kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
for (i = 0; kctl && i < kctl->count; i++) {
- const hda_nid_t *nids = spec->capsrc_nids;
- if (!nids)
- nids = spec->adc_nids;
- err = snd_hda_add_nid(codec, kctl, i, nids[i]);
+ err = snd_hda_add_nid(codec, kctl, i,
+ get_capsrc(spec, i));
if (err < 0)
return err;
}
@@ -1978,30 +2039,47 @@ static int alc_build_controls(struct hda_codec *codec)
return 0;
}
+static int alc_build_controls(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ int err = __alc_build_controls(codec);
+ if (err < 0)
+ return err;
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_BUILD);
+ return 0;
+}
+
/*
* Common callbacks
*/
static void alc_init_special_input_src(struct hda_codec *codec);
+static void alc_auto_init_std(struct hda_codec *codec);
static int alc_init(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
unsigned int i;
+ if (spec->init_hook)
+ spec->init_hook(codec);
+
alc_fix_pll(codec);
alc_auto_init_amp(codec, spec->init_amp);
for (i = 0; i < spec->num_init_verbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
alc_init_special_input_src(codec);
-
- if (spec->init_hook)
- spec->init_hook(codec);
+ alc_auto_init_std(codec);
alc_apply_fixup(codec, ALC_FIXUP_ACT_INIT);
+ snd_hda_jack_report_sync(codec);
+
hda_call_check_power_status(codec, 0x01);
return 0;
}
@@ -2225,6 +2303,7 @@ static int alc_build_pcms(struct hda_codec *codec)
struct alc_spec *spec = codec->spec;
struct hda_pcm *info = spec->pcm_rec;
const struct hda_pcm_stream *p;
+ bool have_multi_adcs;
int i;
codec->num_pcms = 1;
@@ -2237,7 +2316,7 @@ static int alc_build_pcms(struct hda_codec *codec)
"%s Analog", codec->chip_name);
info->name = spec->stream_name_analog;
- if (spec->multiout.dac_nids > 0) {
+ if (spec->multiout.num_dacs > 0) {
p = spec->stream_analog_playback;
if (!p)
p = &alc_pcm_analog_playback;
@@ -2303,8 +2382,11 @@ static int alc_build_pcms(struct hda_codec *codec)
/* If the use of more than one ADC is requested for the current
* model, configure a second analog capture-only PCM.
*/
+ have_multi_adcs = (spec->num_adc_nids > 1) &&
+ !spec->dyn_adc_switch && !spec->auto_mic &&
+ (!spec->input_mux || spec->input_mux->num_items > 1);
/* Additional Analaog capture for index #2 */
- if (spec->alt_dac_nid || spec->num_adc_nids > 1) {
+ if (spec->alt_dac_nid || have_multi_adcs) {
codec->num_pcms = 3;
info = spec->pcm_rec + 2;
info->name = spec->stream_name_analog;
@@ -2320,7 +2402,7 @@ static int alc_build_pcms(struct hda_codec *codec)
alc_pcm_null_stream;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = 0;
}
- if (spec->num_adc_nids > 1) {
+ if (have_multi_adcs) {
p = spec->stream_analog_alt_capture;
if (!p)
p = &alc_pcm_analog_alt_capture;
@@ -2361,6 +2443,18 @@ static void alc_free_kctls(struct hda_codec *codec)
snd_array_free(&spec->kctls);
}
+static void alc_free_bind_ctls(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ if (spec->bind_ctls.list) {
+ struct hda_bind_ctls **ctl = spec->bind_ctls.list;
+ int i;
+ for (i = 0; i < spec->bind_ctls.used; i++)
+ kfree(ctl[i]);
+ }
+ snd_array_free(&spec->bind_ctls);
+}
+
static void alc_free(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -2369,8 +2463,8 @@ static void alc_free(struct hda_codec *codec)
return;
alc_shutup(codec);
- snd_hda_input_jack_free(codec);
alc_free_kctls(codec);
+ alc_free_bind_ctls(codec);
kfree(spec);
snd_hda_detach_beep_device(codec);
}
@@ -2434,6 +2528,47 @@ static int alc_codec_rename(struct hda_codec *codec, const char *name)
}
/*
+ * Rename codecs appropriately from COEF value
+ */
+struct alc_codec_rename_table {
+ unsigned int vendor_id;
+ unsigned short coef_mask;
+ unsigned short coef_bits;
+ const char *name;
+};
+
+static struct alc_codec_rename_table rename_tbl[] = {
+ { 0x10ec0269, 0xfff0, 0x3010, "ALC277" },
+ { 0x10ec0269, 0xf0f0, 0x2010, "ALC259" },
+ { 0x10ec0269, 0xf0f0, 0x3010, "ALC258" },
+ { 0x10ec0269, 0x00f0, 0x0010, "ALC269VB" },
+ { 0x10ec0269, 0xffff, 0xa023, "ALC259" },
+ { 0x10ec0269, 0xffff, 0x6023, "ALC281X" },
+ { 0x10ec0269, 0x00f0, 0x0020, "ALC269VC" },
+ { 0x10ec0887, 0x00f0, 0x0030, "ALC887-VD" },
+ { 0x10ec0888, 0x00f0, 0x0030, "ALC888-VD" },
+ { 0x10ec0888, 0xf0f0, 0x3020, "ALC886" },
+ { 0x10ec0899, 0x2000, 0x2000, "ALC899" },
+ { 0x10ec0892, 0xffff, 0x8020, "ALC661" },
+ { 0x10ec0892, 0xffff, 0x8011, "ALC661" },
+ { 0x10ec0892, 0xffff, 0x4011, "ALC656" },
+ { } /* terminator */
+};
+
+static int alc_codec_rename_from_preset(struct hda_codec *codec)
+{
+ const struct alc_codec_rename_table *p;
+
+ for (p = rename_tbl; p->vendor_id; p++) {
+ if (p->vendor_id != codec->vendor_id)
+ continue;
+ if ((alc_get_coef0(codec) & p->coef_mask) == p->coef_bits)
+ return alc_codec_rename(codec, p->name);
+ }
+ return 0;
+}
+
+/*
* Automatic parse of I/O pins from the BIOS configuration
*/
@@ -2441,11 +2576,15 @@ enum {
ALC_CTL_WIDGET_VOL,
ALC_CTL_WIDGET_MUTE,
ALC_CTL_BIND_MUTE,
+ ALC_CTL_BIND_VOL,
+ ALC_CTL_BIND_SW,
};
static const struct snd_kcontrol_new alc_control_templates[] = {
HDA_CODEC_VOLUME(NULL, 0, 0, 0),
HDA_CODEC_MUTE(NULL, 0, 0, 0),
HDA_BIND_MUTE(NULL, 0, 0, 0),
+ HDA_BIND_VOL(NULL, 0),
+ HDA_BIND_SW(NULL, 0),
};
/* add dynamic controls */
@@ -2486,13 +2625,14 @@ static int add_control_with_pfx(struct alc_spec *spec, int type,
#define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \
add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val)
+static const char * const channel_name[4] = {
+ "Front", "Surround", "CLFE", "Side"
+};
+
static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
bool can_be_master, int *index)
{
struct auto_pin_cfg *cfg = &spec->autocfg;
- static const char * const chname[4] = {
- "Front", "Surround", NULL /*CLFE*/, "Side"
- };
*index = 0;
if (cfg->line_outs == 1 && !spec->multi_ios &&
@@ -2503,6 +2643,8 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
case AUTO_PIN_SPEAKER_OUT:
if (cfg->line_outs == 1)
return "Speaker";
+ if (cfg->line_outs == 2)
+ return ch ? "Bass Speaker" : "Speaker";
break;
case AUTO_PIN_HP_OUT:
/* for multi-io case, only the primary out */
@@ -2515,9 +2657,31 @@ static const char *alc_get_line_out_pfx(struct alc_spec *spec, int ch,
return "PCM";
break;
}
- return chname[ch];
+ if (snd_BUG_ON(ch >= ARRAY_SIZE(channel_name)))
+ return "PCM";
+
+ return channel_name[ch];
}
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+/* add the powersave loopback-list entry */
+static void add_loopback_list(struct alc_spec *spec, hda_nid_t mix, int idx)
+{
+ struct hda_amp_list *list;
+
+ if (spec->num_loopbacks >= ARRAY_SIZE(spec->loopback_list) - 1)
+ return;
+ list = spec->loopback_list + spec->num_loopbacks;
+ list->nid = mix;
+ list->dir = HDA_INPUT;
+ list->idx = idx;
+ spec->num_loopbacks++;
+ spec->loopback.amplist = spec->loopback_list;
+}
+#else
+#define add_loopback_list(spec, mix, idx) /* NOP */
+#endif
+
/* create input playback/capture controls for the given pin */
static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
const char *ctlname, int ctlidx,
@@ -2533,6 +2697,7 @@ static int new_analog_input(struct alc_spec *spec, hda_nid_t pin,
HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
if (err < 0)
return err;
+ add_loopback_list(spec, mix_nid, idx);
return 0;
}
@@ -2550,9 +2715,11 @@ static int alc_auto_fill_adc_caps(struct hda_codec *codec)
hda_nid_t *adc_nids = spec->private_adc_nids;
hda_nid_t *cap_nids = spec->private_capsrc_nids;
int max_nums = ARRAY_SIZE(spec->private_adc_nids);
- bool indep_capsrc = false;
int i, nums = 0;
+ if (spec->shared_mic_hp)
+ max_nums = 1; /* no multi streams with the shared HP/mic */
+
nid = codec->start_nid;
for (i = 0; i < codec->num_nodes; i++, nid++) {
hda_nid_t src;
@@ -2572,13 +2739,11 @@ static int alc_auto_fill_adc_caps(struct hda_codec *codec)
break;
if (type == AC_WID_AUD_SEL) {
cap_nids[nums] = src;
- indep_capsrc = true;
break;
}
n = snd_hda_get_conn_list(codec, src, &list);
if (n > 1) {
cap_nids[nums] = src;
- indep_capsrc = true;
break;
} else if (n != 1)
break;
@@ -2617,6 +2782,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
continue;
label = hda_get_autocfg_input_label(codec, cfg, i);
+ if (spec->shared_mic_hp && !strcmp(label, "Misc"))
+ label = "Headphone Mic";
if (prev_label && !strcmp(label, prev_label))
type_idx++;
else
@@ -2635,8 +2802,7 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
}
for (c = 0; c < num_adcs; c++) {
- hda_nid_t cap = spec->capsrc_nids ?
- spec->capsrc_nids[c] : spec->adc_nids[c];
+ hda_nid_t cap = get_capsrc(spec, c);
idx = get_connection_index(codec, cap, pin);
if (idx >= 0) {
spec->imux_pins[imux->num_items] = pin;
@@ -2652,6 +2818,39 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec)
return 0;
}
+/* create a shared input with the headphone out */
+static int alc_auto_create_shared_input(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ unsigned int defcfg;
+ hda_nid_t nid;
+
+ /* only one internal input pin? */
+ if (cfg->num_inputs != 1)
+ return 0;
+ defcfg = snd_hda_codec_get_pincfg(codec, cfg->inputs[0].pin);
+ if (snd_hda_get_input_pin_attr(defcfg) != INPUT_PIN_ATTR_INT)
+ return 0;
+
+ if (cfg->hp_outs == 1 && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
+ nid = cfg->hp_pins[0]; /* OK, we have a single HP-out */
+ else if (cfg->line_outs == 1 && cfg->line_out_type == AUTO_PIN_HP_OUT)
+ nid = cfg->line_out_pins[0]; /* OK, we have a single line-out */
+ else
+ return 0; /* both not available */
+
+ if (!(snd_hda_query_pin_caps(codec, nid) & AC_PINCAP_IN))
+ return 0; /* no input */
+
+ cfg->inputs[1].pin = nid;
+ cfg->inputs[1].type = AUTO_PIN_MIC;
+ cfg->num_inputs = 2;
+ spec->shared_mic_hp = 1;
+ snd_printdd("realtek: Enable shared I/O jack on NID 0x%x\n", nid);
+ return 0;
+}
+
static void alc_set_pin_output(struct hda_codec *codec, hda_nid_t nid,
unsigned int pin_type)
{
@@ -2763,10 +2962,27 @@ static int alc_auto_select_dac(struct hda_codec *codec, hda_nid_t pin,
return 0;
}
+static bool alc_is_dac_already_used(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct alc_spec *spec = codec->spec;
+ int i;
+ if (found_in_nid_list(nid, spec->multiout.dac_nids,
+ ARRAY_SIZE(spec->private_dac_nids)) ||
+ found_in_nid_list(nid, spec->multiout.hp_out_nid,
+ ARRAY_SIZE(spec->multiout.hp_out_nid)) ||
+ found_in_nid_list(nid, spec->multiout.extra_out_nid,
+ ARRAY_SIZE(spec->multiout.extra_out_nid)))
+ return true;
+ for (i = 0; i < spec->multi_ios; i++) {
+ if (spec->multi_io[i].dac == nid)
+ return true;
+ }
+ return false;
+}
+
/* look for an empty DAC slot */
static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
{
- struct alc_spec *spec = codec->spec;
hda_nid_t srcs[5];
int i, num;
@@ -2776,88 +2992,485 @@ static hda_nid_t alc_auto_look_for_dac(struct hda_codec *codec, hda_nid_t pin)
hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
if (!nid)
continue;
- if (found_in_nid_list(nid, spec->multiout.dac_nids,
- spec->multiout.num_dacs))
- continue;
- if (spec->multiout.hp_nid == nid)
- continue;
- if (found_in_nid_list(nid, spec->multiout.extra_out_nid,
- ARRAY_SIZE(spec->multiout.extra_out_nid)))
- continue;
- return nid;
+ if (!alc_is_dac_already_used(codec, nid))
+ return nid;
}
return 0;
}
+/* check whether the DAC is reachable from the pin */
+static bool alc_auto_is_dac_reachable(struct hda_codec *codec,
+ hda_nid_t pin, hda_nid_t dac)
+{
+ hda_nid_t srcs[5];
+ int i, num;
+
+ if (!pin || !dac)
+ return false;
+ pin = alc_go_down_to_selector(codec, pin);
+ num = snd_hda_get_connections(codec, pin, srcs, ARRAY_SIZE(srcs));
+ for (i = 0; i < num; i++) {
+ hda_nid_t nid = alc_auto_mix_to_dac(codec, srcs[i]);
+ if (nid == dac)
+ return true;
+ }
+ return false;
+}
+
static hda_nid_t get_dac_if_single(struct hda_codec *codec, hda_nid_t pin)
{
+ struct alc_spec *spec = codec->spec;
hda_nid_t sel = alc_go_down_to_selector(codec, pin);
- if (snd_hda_get_conn_list(codec, sel, NULL) == 1)
+ hda_nid_t nid, nid_found, srcs[5];
+ int i, num = snd_hda_get_connections(codec, sel, srcs,
+ ARRAY_SIZE(srcs));
+ if (num == 1)
return alc_auto_look_for_dac(codec, pin);
- return 0;
+ nid_found = 0;
+ for (i = 0; i < num; i++) {
+ if (srcs[i] == spec->mixer_nid)
+ continue;
+ nid = alc_auto_mix_to_dac(codec, srcs[i]);
+ if (nid && !alc_is_dac_already_used(codec, nid)) {
+ if (nid_found)
+ return 0;
+ nid_found = nid;
+ }
+ }
+ return nid_found;
}
-/* fill in the dac_nids table from the parsed pin configuration */
-static int alc_auto_fill_dac_nids(struct hda_codec *codec)
+/* mark up volume and mute control NIDs: used during badness parsing and
+ * at creating actual controls
+ */
+static inline unsigned int get_ctl_pos(unsigned int data)
+{
+ hda_nid_t nid = get_amp_nid_(data);
+ unsigned int dir;
+ if (snd_BUG_ON(nid >= MAX_VOL_NIDS))
+ return 0;
+ dir = get_amp_direction_(data);
+ return (nid << 1) | dir;
+}
+
+#define is_ctl_used(bits, data) \
+ test_bit(get_ctl_pos(data), bits)
+#define mark_ctl_usage(bits, data) \
+ set_bit(get_ctl_pos(data), bits)
+
+static void clear_vol_marks(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- const struct auto_pin_cfg *cfg = &spec->autocfg;
- bool redone = false;
+ memset(spec->vol_ctls, 0, sizeof(spec->vol_ctls));
+ memset(spec->sw_ctls, 0, sizeof(spec->sw_ctls));
+}
+
+/* badness definition */
+enum {
+ /* No primary DAC is found for the main output */
+ BAD_NO_PRIMARY_DAC = 0x10000,
+ /* No DAC is found for the extra output */
+ BAD_NO_DAC = 0x4000,
+ /* No possible multi-ios */
+ BAD_MULTI_IO = 0x103,
+ /* No individual DAC for extra output */
+ BAD_NO_EXTRA_DAC = 0x102,
+ /* No individual DAC for extra surrounds */
+ BAD_NO_EXTRA_SURR_DAC = 0x101,
+ /* Primary DAC shared with main surrounds */
+ BAD_SHARED_SURROUND = 0x100,
+ /* Primary DAC shared with main CLFE */
+ BAD_SHARED_CLFE = 0x10,
+ /* Primary DAC shared with extra surrounds */
+ BAD_SHARED_EXTRA_SURROUND = 0x10,
+ /* Volume widget is shared */
+ BAD_SHARED_VOL = 0x10,
+};
+
+static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
+ hda_nid_t pin, hda_nid_t dac);
+static hda_nid_t alc_look_for_out_vol_nid(struct hda_codec *codec,
+ hda_nid_t pin, hda_nid_t dac);
+
+static int eval_shared_vol_badness(struct hda_codec *codec, hda_nid_t pin,
+ hda_nid_t dac)
+{
+ struct alc_spec *spec = codec->spec;
+ hda_nid_t nid;
+ unsigned int val;
+ int badness = 0;
+
+ nid = alc_look_for_out_vol_nid(codec, pin, dac);
+ if (nid) {
+ val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+ if (is_ctl_used(spec->vol_ctls, nid))
+ badness += BAD_SHARED_VOL;
+ else
+ mark_ctl_usage(spec->vol_ctls, val);
+ } else
+ badness += BAD_SHARED_VOL;
+ nid = alc_look_for_out_mute_nid(codec, pin, dac);
+ if (nid) {
+ unsigned int wid_type = get_wcaps_type(get_wcaps(codec, nid));
+ if (wid_type == AC_WID_PIN || wid_type == AC_WID_AUD_OUT)
+ val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT);
+ else
+ val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT);
+ if (is_ctl_used(spec->sw_ctls, val))
+ badness += BAD_SHARED_VOL;
+ else
+ mark_ctl_usage(spec->sw_ctls, val);
+ } else
+ badness += BAD_SHARED_VOL;
+ return badness;
+}
+
+struct badness_table {
+ int no_primary_dac; /* no primary DAC */
+ int no_dac; /* no secondary DACs */
+ int shared_primary; /* primary DAC is shared with main output */
+ int shared_surr; /* secondary DAC shared with main or primary */
+ int shared_clfe; /* third DAC shared with main or primary */
+ int shared_surr_main; /* secondary DAC sahred with main/DAC0 */
+};
+
+static struct badness_table main_out_badness = {
+ .no_primary_dac = BAD_NO_PRIMARY_DAC,
+ .no_dac = BAD_NO_DAC,
+ .shared_primary = BAD_NO_PRIMARY_DAC,
+ .shared_surr = BAD_SHARED_SURROUND,
+ .shared_clfe = BAD_SHARED_CLFE,
+ .shared_surr_main = BAD_SHARED_SURROUND,
+};
+
+static struct badness_table extra_out_badness = {
+ .no_primary_dac = BAD_NO_DAC,
+ .no_dac = BAD_NO_DAC,
+ .shared_primary = BAD_NO_EXTRA_DAC,
+ .shared_surr = BAD_SHARED_EXTRA_SURROUND,
+ .shared_clfe = BAD_SHARED_EXTRA_SURROUND,
+ .shared_surr_main = BAD_NO_EXTRA_SURR_DAC,
+};
+
+/* try to assign DACs to pins and return the resultant badness */
+static int alc_auto_fill_dacs(struct hda_codec *codec, int num_outs,
+ const hda_nid_t *pins, hda_nid_t *dacs,
+ const struct badness_table *bad)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int i, j;
+ int badness = 0;
+ hda_nid_t dac;
+
+ if (!num_outs)
+ return 0;
+
+ for (i = 0; i < num_outs; i++) {
+ hda_nid_t pin = pins[i];
+ if (!dacs[i])
+ dacs[i] = alc_auto_look_for_dac(codec, pin);
+ if (!dacs[i] && !i) {
+ for (j = 1; j < num_outs; j++) {
+ if (alc_auto_is_dac_reachable(codec, pin, dacs[j])) {
+ dacs[0] = dacs[j];
+ dacs[j] = 0;
+ break;
+ }
+ }
+ }
+ dac = dacs[i];
+ if (!dac) {
+ if (alc_auto_is_dac_reachable(codec, pin, dacs[0]))
+ dac = dacs[0];
+ else if (cfg->line_outs > i &&
+ alc_auto_is_dac_reachable(codec, pin,
+ spec->private_dac_nids[i]))
+ dac = spec->private_dac_nids[i];
+ if (dac) {
+ if (!i)
+ badness += bad->shared_primary;
+ else if (i == 1)
+ badness += bad->shared_surr;
+ else
+ badness += bad->shared_clfe;
+ } else if (alc_auto_is_dac_reachable(codec, pin,
+ spec->private_dac_nids[0])) {
+ dac = spec->private_dac_nids[0];
+ badness += bad->shared_surr_main;
+ } else if (!i)
+ badness += bad->no_primary_dac;
+ else
+ badness += bad->no_dac;
+ }
+ if (dac)
+ badness += eval_shared_vol_badness(codec, pin, dac);
+ }
+
+ return badness;
+}
+
+static int alc_auto_fill_multi_ios(struct hda_codec *codec,
+ hda_nid_t reference_pin,
+ bool hardwired, int offset);
+
+static bool alc_map_singles(struct hda_codec *codec, int outs,
+ const hda_nid_t *pins, hda_nid_t *dacs)
+{
int i;
+ bool found = false;
+ for (i = 0; i < outs; i++) {
+ if (dacs[i])
+ continue;
+ dacs[i] = get_dac_if_single(codec, pins[i]);
+ if (dacs[i])
+ found = true;
+ }
+ return found;
+}
+
+/* fill in the dac_nids table from the parsed pin configuration */
+static int fill_and_eval_dacs(struct hda_codec *codec,
+ bool fill_hardwired,
+ bool fill_mio_first)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ int i, err, badness;
- again:
/* set num_dacs once to full for alc_auto_look_for_dac() */
spec->multiout.num_dacs = cfg->line_outs;
- spec->multiout.hp_nid = 0;
- spec->multiout.extra_out_nid[0] = 0;
- memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
spec->multiout.dac_nids = spec->private_dac_nids;
+ memset(spec->private_dac_nids, 0, sizeof(spec->private_dac_nids));
+ memset(spec->multiout.hp_out_nid, 0, sizeof(spec->multiout.hp_out_nid));
+ memset(spec->multiout.extra_out_nid, 0, sizeof(spec->multiout.extra_out_nid));
+ spec->multi_ios = 0;
+ clear_vol_marks(codec);
+ badness = 0;
/* fill hard-wired DACs first */
- if (!redone) {
- for (i = 0; i < cfg->line_outs; i++)
- spec->private_dac_nids[i] =
- get_dac_if_single(codec, cfg->line_out_pins[i]);
- if (cfg->hp_outs)
- spec->multiout.hp_nid =
- get_dac_if_single(codec, cfg->hp_pins[0]);
- if (cfg->speaker_outs)
- spec->multiout.extra_out_nid[0] =
- get_dac_if_single(codec, cfg->speaker_pins[0]);
+ if (fill_hardwired) {
+ bool mapped;
+ do {
+ mapped = alc_map_singles(codec, cfg->line_outs,
+ cfg->line_out_pins,
+ spec->private_dac_nids);
+ mapped |= alc_map_singles(codec, cfg->hp_outs,
+ cfg->hp_pins,
+ spec->multiout.hp_out_nid);
+ mapped |= alc_map_singles(codec, cfg->speaker_outs,
+ cfg->speaker_pins,
+ spec->multiout.extra_out_nid);
+ if (fill_mio_first && cfg->line_outs == 1 &&
+ cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+ err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], true, 0);
+ if (!err)
+ mapped = true;
+ }
+ } while (mapped);
}
- for (i = 0; i < cfg->line_outs; i++) {
- hda_nid_t pin = cfg->line_out_pins[i];
- if (spec->private_dac_nids[i])
- continue;
- spec->private_dac_nids[i] = alc_auto_look_for_dac(codec, pin);
- if (!spec->private_dac_nids[i] && !redone) {
- /* if we can't find primary DACs, re-probe without
- * checking the hard-wired DACs
- */
- redone = true;
- goto again;
- }
- }
+ badness += alc_auto_fill_dacs(codec, cfg->line_outs, cfg->line_out_pins,
+ spec->private_dac_nids,
+ &main_out_badness);
/* re-count num_dacs and squash invalid entries */
spec->multiout.num_dacs = 0;
for (i = 0; i < cfg->line_outs; i++) {
if (spec->private_dac_nids[i])
spec->multiout.num_dacs++;
- else
+ else {
memmove(spec->private_dac_nids + i,
spec->private_dac_nids + i + 1,
sizeof(hda_nid_t) * (cfg->line_outs - i - 1));
+ spec->private_dac_nids[cfg->line_outs - 1] = 0;
+ }
+ }
+
+ if (fill_mio_first &&
+ cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+ /* try to fill multi-io first */
+ err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
+ if (err < 0)
+ return err;
+ /* we don't count badness at this stage yet */
+ }
+
+ if (cfg->line_out_type != AUTO_PIN_HP_OUT) {
+ err = alc_auto_fill_dacs(codec, cfg->hp_outs, cfg->hp_pins,
+ spec->multiout.hp_out_nid,
+ &extra_out_badness);
+ if (err < 0)
+ return err;
+ badness += err;
+ }
+ if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+ err = alc_auto_fill_dacs(codec, cfg->speaker_outs,
+ cfg->speaker_pins,
+ spec->multiout.extra_out_nid,
+ &extra_out_badness);
+ if (err < 0)
+ return err;
+ badness += err;
+ }
+ if (cfg->line_outs == 1 && cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) {
+ err = alc_auto_fill_multi_ios(codec, cfg->line_out_pins[0], false, 0);
+ if (err < 0)
+ return err;
+ badness += err;
+ }
+ if (cfg->hp_outs && cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
+ /* try multi-ios with HP + inputs */
+ int offset = 0;
+ if (cfg->line_outs >= 3)
+ offset = 1;
+ err = alc_auto_fill_multi_ios(codec, cfg->hp_pins[0], false,
+ offset);
+ if (err < 0)
+ return err;
+ badness += err;
+ }
+
+ if (spec->multi_ios == 2) {
+ for (i = 0; i < 2; i++)
+ spec->private_dac_nids[spec->multiout.num_dacs++] =
+ spec->multi_io[i].dac;
+ spec->ext_channel_count = 2;
+ } else if (spec->multi_ios) {
+ spec->multi_ios = 0;
+ badness += BAD_MULTI_IO;
+ }
+
+ return badness;
+}
+
+#define DEBUG_BADNESS
+
+#ifdef DEBUG_BADNESS
+#define debug_badness snd_printdd
+#else
+#define debug_badness(...)
+#endif
+
+static void debug_show_configs(struct alc_spec *spec, struct auto_pin_cfg *cfg)
+{
+ debug_badness("multi_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+ cfg->line_out_pins[0], cfg->line_out_pins[1],
+ cfg->line_out_pins[2], cfg->line_out_pins[2],
+ spec->multiout.dac_nids[0],
+ spec->multiout.dac_nids[1],
+ spec->multiout.dac_nids[2],
+ spec->multiout.dac_nids[3]);
+ if (spec->multi_ios > 0)
+ debug_badness("multi_ios(%d) = %x/%x : %x/%x\n",
+ spec->multi_ios,
+ spec->multi_io[0].pin, spec->multi_io[1].pin,
+ spec->multi_io[0].dac, spec->multi_io[1].dac);
+ debug_badness("hp_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+ cfg->hp_pins[0], cfg->hp_pins[1],
+ cfg->hp_pins[2], cfg->hp_pins[2],
+ spec->multiout.hp_out_nid[0],
+ spec->multiout.hp_out_nid[1],
+ spec->multiout.hp_out_nid[2],
+ spec->multiout.hp_out_nid[3]);
+ debug_badness("spk_outs = %x/%x/%x/%x : %x/%x/%x/%x\n",
+ cfg->speaker_pins[0], cfg->speaker_pins[1],
+ cfg->speaker_pins[2], cfg->speaker_pins[3],
+ spec->multiout.extra_out_nid[0],
+ spec->multiout.extra_out_nid[1],
+ spec->multiout.extra_out_nid[2],
+ spec->multiout.extra_out_nid[3]);
+}
+
+static int alc_auto_fill_dac_nids(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
+ struct auto_pin_cfg *best_cfg;
+ int best_badness = INT_MAX;
+ int badness;
+ bool fill_hardwired = true, fill_mio_first = true;
+ bool best_wired = true, best_mio = true;
+ bool hp_spk_swapped = false;
+
+ best_cfg = kmalloc(sizeof(*best_cfg), GFP_KERNEL);
+ if (!best_cfg)
+ return -ENOMEM;
+ *best_cfg = *cfg;
+
+ for (;;) {
+ badness = fill_and_eval_dacs(codec, fill_hardwired,
+ fill_mio_first);
+ if (badness < 0)
+ return badness;
+ debug_badness("==> lo_type=%d, wired=%d, mio=%d, badness=0x%x\n",
+ cfg->line_out_type, fill_hardwired, fill_mio_first,
+ badness);
+ debug_show_configs(spec, cfg);
+ if (badness < best_badness) {
+ best_badness = badness;
+ *best_cfg = *cfg;
+ best_wired = fill_hardwired;
+ best_mio = fill_mio_first;
+ }
+ if (!badness)
+ break;
+ fill_mio_first = !fill_mio_first;
+ if (!fill_mio_first)
+ continue;
+ fill_hardwired = !fill_hardwired;
+ if (!fill_hardwired)
+ continue;
+ if (hp_spk_swapped)
+ break;
+ hp_spk_swapped = true;
+ if (cfg->speaker_outs > 0 &&
+ cfg->line_out_type == AUTO_PIN_HP_OUT) {
+ cfg->hp_outs = cfg->line_outs;
+ memcpy(cfg->hp_pins, cfg->line_out_pins,
+ sizeof(cfg->hp_pins));
+ cfg->line_outs = cfg->speaker_outs;
+ memcpy(cfg->line_out_pins, cfg->speaker_pins,
+ sizeof(cfg->speaker_pins));
+ cfg->speaker_outs = 0;
+ memset(cfg->speaker_pins, 0, sizeof(cfg->speaker_pins));
+ cfg->line_out_type = AUTO_PIN_SPEAKER_OUT;
+ fill_hardwired = true;
+ continue;
+ }
+ if (cfg->hp_outs > 0 &&
+ cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) {
+ cfg->speaker_outs = cfg->line_outs;
+ memcpy(cfg->speaker_pins, cfg->line_out_pins,
+ sizeof(cfg->speaker_pins));
+ cfg->line_outs = cfg->hp_outs;
+ memcpy(cfg->line_out_pins, cfg->hp_pins,
+ sizeof(cfg->hp_pins));
+ cfg->hp_outs = 0;
+ memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
+ cfg->line_out_type = AUTO_PIN_HP_OUT;
+ fill_hardwired = true;
+ continue;
+ }
+ break;
}
- if (cfg->hp_outs && !spec->multiout.hp_nid)
- spec->multiout.hp_nid =
- alc_auto_look_for_dac(codec, cfg->hp_pins[0]);
- if (cfg->speaker_outs && !spec->multiout.extra_out_nid[0])
- spec->multiout.extra_out_nid[0] =
- alc_auto_look_for_dac(codec, cfg->speaker_pins[0]);
+ if (badness) {
+ *cfg = *best_cfg;
+ fill_and_eval_dacs(codec, best_wired, best_mio);
+ }
+ debug_badness("==> Best config: lo_type=%d, wired=%d, mio=%d\n",
+ cfg->line_out_type, best_wired, best_mio);
+ debug_show_configs(spec, cfg);
+ if (cfg->line_out_pins[0])
+ spec->vmaster_nid =
+ alc_look_for_out_vol_nid(codec, cfg->line_out_pins[0],
+ spec->multiout.dac_nids[0]);
+
+ /* clear the bitmap flags for creating controls */
+ clear_vol_marks(codec);
+ kfree(best_cfg);
return 0;
}
@@ -2865,14 +3478,27 @@ static int alc_auto_add_vol_ctl(struct hda_codec *codec,
const char *pfx, int cidx,
hda_nid_t nid, unsigned int chs)
{
+ struct alc_spec *spec = codec->spec;
+ unsigned int val;
if (!nid)
return 0;
+ val = HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT);
+ if (is_ctl_used(spec->vol_ctls, val) && chs != 2) /* exclude LFE */
+ return 0;
+ mark_ctl_usage(spec->vol_ctls, val);
return __add_pb_vol_ctrl(codec->spec, ALC_CTL_WIDGET_VOL, pfx, cidx,
- HDA_COMPOSE_AMP_VAL(nid, chs, 0, HDA_OUTPUT));
+ val);
}
-#define alc_auto_add_stereo_vol(codec, pfx, cidx, nid) \
- alc_auto_add_vol_ctl(codec, pfx, cidx, nid, 3)
+static int alc_auto_add_stereo_vol(struct hda_codec *codec,
+ const char *pfx, int cidx,
+ hda_nid_t nid)
+{
+ int chs = 1;
+ if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
+ chs = 3;
+ return alc_auto_add_vol_ctl(codec, pfx, cidx, nid, chs);
+}
/* create a mute-switch for the given mixer widget;
* if it has multiple sources (e.g. DAC and loopback), create a bind-mute
@@ -2881,6 +3507,7 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec,
const char *pfx, int cidx,
hda_nid_t nid, unsigned int chs)
{
+ struct alc_spec *spec = codec->spec;
int wid_type;
int type;
unsigned long val;
@@ -2897,11 +3524,20 @@ static int alc_auto_add_sw_ctl(struct hda_codec *codec,
type = ALC_CTL_BIND_MUTE;
val = HDA_COMPOSE_AMP_VAL(nid, chs, 2, HDA_INPUT);
}
+ if (is_ctl_used(spec->sw_ctls, val) && chs != 2) /* exclude LFE */
+ return 0;
+ mark_ctl_usage(spec->sw_ctls, val);
return __add_pb_sw_ctrl(codec->spec, type, pfx, cidx, val);
}
-#define alc_auto_add_stereo_sw(codec, pfx, cidx, nid) \
- alc_auto_add_sw_ctl(codec, pfx, cidx, nid, 3)
+static int alc_auto_add_stereo_sw(struct hda_codec *codec, const char *pfx,
+ int cidx, hda_nid_t nid)
+{
+ int chs = 1;
+ if (get_wcaps(codec, nid) & AC_WCAP_STEREO)
+ chs = 3;
+ return alc_auto_add_sw_ctl(codec, pfx, cidx, nid, chs);
+}
static hda_nid_t alc_look_for_out_mute_nid(struct hda_codec *codec,
hda_nid_t pin, hda_nid_t dac)
@@ -2937,7 +3573,7 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
int i, err, noutputs;
noutputs = cfg->line_outs;
- if (spec->multi_ios > 0)
+ if (spec->multi_ios > 0 && cfg->line_outs < 3)
noutputs += spec->multi_ios;
for (i = 0; i < noutputs; i++) {
@@ -2949,15 +3585,18 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
dac = spec->multiout.dac_nids[i];
if (!dac)
continue;
- if (i >= cfg->line_outs)
+ if (i >= cfg->line_outs) {
pin = spec->multi_io[i - 1].pin;
- else
+ index = 0;
+ name = channel_name[i];
+ } else {
pin = cfg->line_out_pins[i];
+ name = alc_get_line_out_pfx(spec, i, true, &index);
+ }
sw = alc_look_for_out_mute_nid(codec, pin, dac);
vol = alc_look_for_out_vol_nid(codec, pin, dac);
- name = alc_get_line_out_pfx(spec, i, true, &index);
- if (!name) {
+ if (!name || !strcmp(name, "CLFE")) {
/* Center/LFE */
err = alc_auto_add_vol_ctl(codec, "Center", 0, vol, 1);
if (err < 0)
@@ -2983,50 +3622,139 @@ static int alc_auto_create_multi_out_ctls(struct hda_codec *codec,
return 0;
}
-/* add playback controls for speaker and HP outputs */
static int alc_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin,
- hda_nid_t dac, const char *pfx)
+ hda_nid_t dac, const char *pfx,
+ int cidx)
{
struct alc_spec *spec = codec->spec;
hda_nid_t sw, vol;
int err;
- if (!pin)
- return 0;
if (!dac) {
+ unsigned int val;
/* the corresponding DAC is already occupied */
if (!(get_wcaps(codec, pin) & AC_WCAP_OUT_AMP))
return 0; /* no way */
/* create a switch only */
- return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx,
- HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
+ val = HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT);
+ if (is_ctl_used(spec->sw_ctls, val))
+ return 0; /* already created */
+ mark_ctl_usage(spec->sw_ctls, val);
+ return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, cidx, val);
}
sw = alc_look_for_out_mute_nid(codec, pin, dac);
vol = alc_look_for_out_vol_nid(codec, pin, dac);
- err = alc_auto_add_stereo_vol(codec, pfx, 0, vol);
+ err = alc_auto_add_stereo_vol(codec, pfx, cidx, vol);
if (err < 0)
return err;
- err = alc_auto_add_stereo_sw(codec, pfx, 0, sw);
+ err = alc_auto_add_stereo_sw(codec, pfx, cidx, sw);
if (err < 0)
return err;
return 0;
}
+static struct hda_bind_ctls *new_bind_ctl(struct hda_codec *codec,
+ unsigned int nums,
+ struct hda_ctl_ops *ops)
+{
+ struct alc_spec *spec = codec->spec;
+ struct hda_bind_ctls **ctlp, *ctl;
+ snd_array_init(&spec->bind_ctls, sizeof(ctl), 8);
+ ctlp = snd_array_new(&spec->bind_ctls);
+ if (!ctlp)
+ return NULL;
+ ctl = kzalloc(sizeof(*ctl) + sizeof(long) * (nums + 1), GFP_KERNEL);
+ *ctlp = ctl;
+ if (ctl)
+ ctl->ops = ops;
+ return ctl;
+}
+
+/* add playback controls for speaker and HP outputs */
+static int alc_auto_create_extra_outs(struct hda_codec *codec, int num_pins,
+ const hda_nid_t *pins,
+ const hda_nid_t *dacs,
+ const char *pfx)
+{
+ struct alc_spec *spec = codec->spec;
+ struct hda_bind_ctls *ctl;
+ char name[32];
+ int i, n, err;
+
+ if (!num_pins || !pins[0])
+ return 0;
+
+ if (num_pins == 1) {
+ hda_nid_t dac = *dacs;
+ if (!dac)
+ dac = spec->multiout.dac_nids[0];
+ return alc_auto_create_extra_out(codec, *pins, dac, pfx, 0);
+ }
+
+ for (i = 0; i < num_pins; i++) {
+ hda_nid_t dac;
+ if (dacs[num_pins - 1])
+ dac = dacs[i]; /* with individual volumes */
+ else
+ dac = 0;
+ if (num_pins == 2 && i == 1 && !strcmp(pfx, "Speaker")) {
+ err = alc_auto_create_extra_out(codec, pins[i], dac,
+ "Bass Speaker", 0);
+ } else if (num_pins >= 3) {
+ snprintf(name, sizeof(name), "%s %s",
+ pfx, channel_name[i]);
+ err = alc_auto_create_extra_out(codec, pins[i], dac,
+ name, 0);
+ } else {
+ err = alc_auto_create_extra_out(codec, pins[i], dac,
+ pfx, i);
+ }
+ if (err < 0)
+ return err;
+ }
+ if (dacs[num_pins - 1])
+ return 0;
+
+ /* Let's create a bind-controls for volumes */
+ ctl = new_bind_ctl(codec, num_pins, &snd_hda_bind_vol);
+ if (!ctl)
+ return -ENOMEM;
+ n = 0;
+ for (i = 0; i < num_pins; i++) {
+ hda_nid_t vol;
+ if (!pins[i] || !dacs[i])
+ continue;
+ vol = alc_look_for_out_vol_nid(codec, pins[i], dacs[i]);
+ if (vol)
+ ctl->values[n++] =
+ HDA_COMPOSE_AMP_VAL(vol, 3, 0, HDA_OUTPUT);
+ }
+ if (n) {
+ snprintf(name, sizeof(name), "%s Playback Volume", pfx);
+ err = add_control(spec, ALC_CTL_BIND_VOL, name, 0, (long)ctl);
+ if (err < 0)
+ return err;
+ }
+ return 0;
+}
+
static int alc_auto_create_hp_out(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- return alc_auto_create_extra_out(codec, spec->autocfg.hp_pins[0],
- spec->multiout.hp_nid,
- "Headphone");
+ return alc_auto_create_extra_outs(codec, spec->autocfg.hp_outs,
+ spec->autocfg.hp_pins,
+ spec->multiout.hp_out_nid,
+ "Headphone");
}
static int alc_auto_create_speaker_out(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- return alc_auto_create_extra_out(codec, spec->autocfg.speaker_pins[0],
- spec->multiout.extra_out_nid[0],
- "Speaker");
+ return alc_auto_create_extra_outs(codec, spec->autocfg.speaker_outs,
+ spec->autocfg.speaker_pins,
+ spec->multiout.extra_out_nid,
+ "Speaker");
}
static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
@@ -3064,6 +3792,12 @@ static void alc_auto_set_output_and_unmute(struct hda_codec *codec,
if (nid)
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
AMP_OUT_ZERO);
+
+ /* unmute DAC if it's not assigned to a mixer */
+ nid = alc_look_for_out_mute_nid(codec, pin, dac);
+ if (nid == mix && nid_has_mute(codec, dac, HDA_OUTPUT))
+ snd_hda_codec_write(codec, dac, 0, AC_VERB_SET_AMP_GAIN_MUTE,
+ AMP_OUT_ZERO);
}
static void alc_auto_init_multi_out(struct hda_codec *codec)
@@ -3083,62 +3817,146 @@ static void alc_auto_init_multi_out(struct hda_codec *codec)
static void alc_auto_init_extra_out(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ int i;
hda_nid_t pin, dac;
- pin = spec->autocfg.hp_pins[0];
- if (pin) {
- dac = spec->multiout.hp_nid;
- if (!dac)
- dac = spec->multiout.dac_nids[0];
+ for (i = 0; i < spec->autocfg.hp_outs; i++) {
+ if (spec->autocfg.line_out_type == AUTO_PIN_HP_OUT)
+ break;
+ pin = spec->autocfg.hp_pins[i];
+ if (!pin)
+ break;
+ dac = spec->multiout.hp_out_nid[i];
+ if (!dac) {
+ if (i > 0 && spec->multiout.hp_out_nid[0])
+ dac = spec->multiout.hp_out_nid[0];
+ else
+ dac = spec->multiout.dac_nids[0];
+ }
alc_auto_set_output_and_unmute(codec, pin, PIN_HP, dac);
}
- pin = spec->autocfg.speaker_pins[0];
- if (pin) {
- dac = spec->multiout.extra_out_nid[0];
- if (!dac)
- dac = spec->multiout.dac_nids[0];
+ for (i = 0; i < spec->autocfg.speaker_outs; i++) {
+ if (spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT)
+ break;
+ pin = spec->autocfg.speaker_pins[i];
+ if (!pin)
+ break;
+ dac = spec->multiout.extra_out_nid[i];
+ if (!dac) {
+ if (i > 0 && spec->multiout.extra_out_nid[0])
+ dac = spec->multiout.extra_out_nid[0];
+ else
+ dac = spec->multiout.dac_nids[0];
+ }
alc_auto_set_output_and_unmute(codec, pin, PIN_OUT, dac);
}
}
+/* check whether the given pin can be a multi-io pin */
+static bool can_be_multiio_pin(struct hda_codec *codec,
+ unsigned int location, hda_nid_t nid)
+{
+ unsigned int defcfg, caps;
+
+ defcfg = snd_hda_codec_get_pincfg(codec, nid);
+ if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+ return false;
+ if (location && get_defcfg_location(defcfg) != location)
+ return false;
+ caps = snd_hda_query_pin_caps(codec, nid);
+ if (!(caps & AC_PINCAP_OUT))
+ return false;
+ return true;
+}
+
/*
* multi-io helper
+ *
+ * When hardwired is set, try to fill ony hardwired pins, and returns
+ * zero if any pins are filled, non-zero if nothing found.
+ * When hardwired is off, try to fill possible input pins, and returns
+ * the badness value.
*/
static int alc_auto_fill_multi_ios(struct hda_codec *codec,
- unsigned int location)
+ hda_nid_t reference_pin,
+ bool hardwired, int offset)
{
struct alc_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
- int type, i, num_pins = 0;
+ int type, i, j, dacs, num_pins, old_pins;
+ unsigned int defcfg = snd_hda_codec_get_pincfg(codec, reference_pin);
+ unsigned int location = get_defcfg_location(defcfg);
+ int badness = 0;
+ old_pins = spec->multi_ios;
+ if (old_pins >= 2)
+ goto end_fill;
+
+ num_pins = 0;
for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
for (i = 0; i < cfg->num_inputs; i++) {
- hda_nid_t nid = cfg->inputs[i].pin;
- hda_nid_t dac;
- unsigned int defcfg, caps;
if (cfg->inputs[i].type != type)
continue;
- defcfg = snd_hda_codec_get_pincfg(codec, nid);
- if (get_defcfg_connect(defcfg) != AC_JACK_PORT_COMPLEX)
+ if (can_be_multiio_pin(codec, location,
+ cfg->inputs[i].pin))
+ num_pins++;
+ }
+ }
+ if (num_pins < 2)
+ goto end_fill;
+
+ dacs = spec->multiout.num_dacs;
+ for (type = AUTO_PIN_LINE_IN; type >= AUTO_PIN_MIC; type--) {
+ for (i = 0; i < cfg->num_inputs; i++) {
+ hda_nid_t nid = cfg->inputs[i].pin;
+ hda_nid_t dac = 0;
+
+ if (cfg->inputs[i].type != type)
continue;
- if (location && get_defcfg_location(defcfg) != location)
+ if (!can_be_multiio_pin(codec, location, nid))
continue;
- caps = snd_hda_query_pin_caps(codec, nid);
- if (!(caps & AC_PINCAP_OUT))
+ for (j = 0; j < spec->multi_ios; j++) {
+ if (nid == spec->multi_io[j].pin)
+ break;
+ }
+ if (j < spec->multi_ios)
continue;
- dac = alc_auto_look_for_dac(codec, nid);
- if (!dac)
+
+ if (offset && offset + spec->multi_ios < dacs) {
+ dac = spec->private_dac_nids[offset + spec->multi_ios];
+ if (!alc_auto_is_dac_reachable(codec, nid, dac))
+ dac = 0;
+ }
+ if (hardwired)
+ dac = get_dac_if_single(codec, nid);
+ else if (!dac)
+ dac = alc_auto_look_for_dac(codec, nid);
+ if (!dac) {
+ badness++;
continue;
- spec->multi_io[num_pins].pin = nid;
- spec->multi_io[num_pins].dac = dac;
- num_pins++;
- spec->private_dac_nids[spec->multiout.num_dacs++] = dac;
+ }
+ spec->multi_io[spec->multi_ios].pin = nid;
+ spec->multi_io[spec->multi_ios].dac = dac;
+ spec->multi_ios++;
+ if (spec->multi_ios >= 2)
+ break;
}
}
- spec->multiout.num_dacs = 1;
- if (num_pins < 2)
- return 0;
- return num_pins;
+ end_fill:
+ if (badness)
+ badness = BAD_MULTI_IO;
+ if (old_pins == spec->multi_ios) {
+ if (hardwired)
+ return 1; /* nothing found */
+ else
+ return badness; /* no badness if nothing found */
+ }
+ if (!hardwired && spec->multi_ios < 2) {
+ spec->multi_ios = old_pins;
+ return badness;
+ }
+
+ return 0;
}
static int alc_auto_ch_mode_info(struct snd_kcontrol *kcontrol,
@@ -3223,36 +4041,11 @@ static const struct snd_kcontrol_new alc_auto_channel_mode_enum = {
.put = alc_auto_ch_mode_put,
};
-static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
- int (*fill_dac)(struct hda_codec *))
+static int alc_auto_add_multi_channel_mode(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- unsigned int location, defcfg;
- int num_pins;
- if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT && cfg->hp_outs == 1) {
- /* use HP as primary out */
- cfg->speaker_outs = cfg->line_outs;
- memcpy(cfg->speaker_pins, cfg->line_out_pins,
- sizeof(cfg->speaker_pins));
- cfg->line_outs = cfg->hp_outs;
- memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
- cfg->hp_outs = 0;
- memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
- cfg->line_out_type = AUTO_PIN_HP_OUT;
- if (fill_dac)
- fill_dac(codec);
- }
- if (cfg->line_outs != 1 ||
- cfg->line_out_type == AUTO_PIN_SPEAKER_OUT)
- return 0;
-
- defcfg = snd_hda_codec_get_pincfg(codec, cfg->line_out_pins[0]);
- location = get_defcfg_location(defcfg);
-
- num_pins = alc_auto_fill_multi_ios(codec, location);
- if (num_pins > 0) {
+ if (spec->multi_ios > 0) {
struct snd_kcontrol_new *knew;
knew = alc_kcontrol_new(spec);
@@ -3262,10 +4055,6 @@ static int alc_auto_add_multi_channel_mode(struct hda_codec *codec,
knew->name = kstrdup("Channel Mode", GFP_KERNEL);
if (!knew->name)
return -ENOMEM;
-
- spec->multi_ios = num_pins;
- spec->ext_channel_count = 2;
- spec->multiout.num_dacs = num_pins + 1;
}
return 0;
}
@@ -3365,7 +4154,7 @@ static void alc_auto_init_input_src(struct hda_codec *codec)
else
nums = spec->num_adc_nids;
for (c = 0; c < nums; c++)
- alc_mux_select(codec, 0, spec->cur_mux[c], true);
+ alc_mux_select(codec, c, spec->cur_mux[c], true);
}
/* add mic boosts if needed */
@@ -3387,6 +4176,8 @@ static int alc_auto_add_mic_boost(struct hda_codec *codec)
char boost_label[32];
label = hda_get_autocfg_input_label(codec, cfg, i);
+ if (spec->shared_mic_hp && !strcmp(label, "Misc"))
+ label = "Headphone Mic";
if (prev_label && !strcmp(label, prev_label))
type_idx++;
else
@@ -3427,8 +4218,7 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin)
if (!pin)
return 0;
for (i = 0; i < spec->num_adc_nids; i++) {
- hda_nid_t cap = spec->capsrc_nids ?
- spec->capsrc_nids[i] : spec->adc_nids[i];
+ hda_nid_t cap = get_capsrc(spec, i);
int idx;
idx = get_connection_index(codec, cap, pin);
@@ -3521,6 +4311,7 @@ static const struct snd_pci_quirk beep_white_list[] = {
SND_PCI_QUIRK(0x1043, 0x83ce, "EeePC", 1),
SND_PCI_QUIRK(0x1043, 0x831a, "EeePC", 1),
SND_PCI_QUIRK(0x1043, 0x834a, "EeePC", 1),
+ SND_PCI_QUIRK(0x1458, 0xa002, "GA-MA790X", 1),
SND_PCI_QUIRK(0x8086, 0xd613, "Intel", 1),
{}
};
@@ -3548,27 +4339,42 @@ static int alc_parse_auto_config(struct hda_codec *codec,
const hda_nid_t *ssid_nids)
{
struct alc_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
int err;
- err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
- ignore_nids);
+ err = snd_hda_parse_pin_defcfg(codec, cfg, ignore_nids,
+ spec->parse_flags);
if (err < 0)
return err;
- if (!spec->autocfg.line_outs) {
- if (spec->autocfg.dig_outs || spec->autocfg.dig_in_pin) {
+ if (!cfg->line_outs) {
+ if (cfg->dig_outs || cfg->dig_in_pin) {
spec->multiout.max_channels = 2;
spec->no_analog = 1;
goto dig_only;
}
return 0; /* can't find valid BIOS pin config */
}
+
+ if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT &&
+ cfg->line_outs <= cfg->hp_outs) {
+ /* use HP as primary out */
+ cfg->speaker_outs = cfg->line_outs;
+ memcpy(cfg->speaker_pins, cfg->line_out_pins,
+ sizeof(cfg->speaker_pins));
+ cfg->line_outs = cfg->hp_outs;
+ memcpy(cfg->line_out_pins, cfg->hp_pins, sizeof(cfg->hp_pins));
+ cfg->hp_outs = 0;
+ memset(cfg->hp_pins, 0, sizeof(cfg->hp_pins));
+ cfg->line_out_type = AUTO_PIN_HP_OUT;
+ }
+
err = alc_auto_fill_dac_nids(codec);
if (err < 0)
return err;
- err = alc_auto_add_multi_channel_mode(codec, alc_auto_fill_dac_nids);
+ err = alc_auto_add_multi_channel_mode(codec);
if (err < 0)
return err;
- err = alc_auto_create_multi_out_ctls(codec, &spec->autocfg);
+ err = alc_auto_create_multi_out_ctls(codec, cfg);
if (err < 0)
return err;
err = alc_auto_create_hp_out(codec);
@@ -3577,6 +4383,9 @@ static int alc_parse_auto_config(struct hda_codec *codec,
err = alc_auto_create_speaker_out(codec);
if (err < 0)
return err;
+ err = alc_auto_create_shared_input(codec);
+ if (err < 0)
+ return err;
err = alc_auto_create_input_ctls(codec);
if (err < 0)
return err;
@@ -3602,6 +4411,9 @@ static int alc_parse_auto_config(struct hda_codec *codec,
if (spec->kctls.list)
add_mixer(spec, spec->kctls.list);
+ if (!spec->no_analog && !spec->cap_mixer)
+ set_capture_mixer(codec);
+
return 1;
}
@@ -3612,43 +4424,378 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
return alc_parse_auto_config(codec, alc880_ignore, alc880_ssids);
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc880_loopbacks[] = {
- { 0x0b, HDA_INPUT, 0 },
- { 0x0b, HDA_INPUT, 1 },
- { 0x0b, HDA_INPUT, 2 },
- { 0x0b, HDA_INPUT, 3 },
- { 0x0b, HDA_INPUT, 4 },
- { } /* end */
-};
-#endif
-
/*
- * board setups
+ * ALC880 fix-ups
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#define alc_board_config \
- snd_hda_check_board_config
-#define alc_board_codec_sid_config \
- snd_hda_check_board_codec_sid_config
-#include "alc_quirks.c"
-#else
-#define alc_board_config(codec, nums, models, tbl) -1
-#define alc_board_codec_sid_config(codec, nums, models, tbl) -1
-#define setup_preset(codec, x) /* NOP */
-#endif
+enum {
+ ALC880_FIXUP_GPIO1,
+ ALC880_FIXUP_GPIO2,
+ ALC880_FIXUP_MEDION_RIM,
+ ALC880_FIXUP_LG,
+ ALC880_FIXUP_W810,
+ ALC880_FIXUP_EAPD_COEF,
+ ALC880_FIXUP_TCL_S700,
+ ALC880_FIXUP_VOL_KNOB,
+ ALC880_FIXUP_FUJITSU,
+ ALC880_FIXUP_F1734,
+ ALC880_FIXUP_UNIWILL,
+ ALC880_FIXUP_UNIWILL_DIG,
+ ALC880_FIXUP_Z71V,
+ ALC880_FIXUP_3ST_BASE,
+ ALC880_FIXUP_3ST,
+ ALC880_FIXUP_3ST_DIG,
+ ALC880_FIXUP_5ST_BASE,
+ ALC880_FIXUP_5ST,
+ ALC880_FIXUP_5ST_DIG,
+ ALC880_FIXUP_6ST_BASE,
+ ALC880_FIXUP_6ST,
+ ALC880_FIXUP_6ST_DIG,
+};
+
+/* enable the volume-knob widget support on NID 0x21 */
+static void alc880_fixup_vol_knob(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ if (action == ALC_FIXUP_ACT_PROBE)
+ snd_hda_jack_detect_enable(codec, 0x21, ALC_DCVOL_EVENT);
+}
+
+static const struct alc_fixup alc880_fixups[] = {
+ [ALC880_FIXUP_GPIO1] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio1_init_verbs,
+ },
+ [ALC880_FIXUP_GPIO2] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio2_init_verbs,
+ },
+ [ALC880_FIXUP_MEDION_RIM] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_GPIO2,
+ },
+ [ALC880_FIXUP_LG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ /* disable bogus unused pins */
+ { 0x16, 0x411111f0 },
+ { 0x18, 0x411111f0 },
+ { 0x1a, 0x411111f0 },
+ { }
+ }
+ },
+ [ALC880_FIXUP_W810] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ /* disable bogus unused pins */
+ { 0x17, 0x411111f0 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_GPIO2,
+ },
+ [ALC880_FIXUP_EAPD_COEF] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* change to EAPD mode */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
+ {}
+ },
+ },
+ [ALC880_FIXUP_TCL_S700] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* change to EAPD mode */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
+ {}
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_GPIO2,
+ },
+ [ALC880_FIXUP_VOL_KNOB] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc880_fixup_vol_knob,
+ },
+ [ALC880_FIXUP_FUJITSU] = {
+ /* override all pins as BIOS on old Amilo is broken */
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x0121411f }, /* HP */
+ { 0x15, 0x99030120 }, /* speaker */
+ { 0x16, 0x99030130 }, /* bass speaker */
+ { 0x17, 0x411111f0 }, /* N/A */
+ { 0x18, 0x411111f0 }, /* N/A */
+ { 0x19, 0x01a19950 }, /* mic-in */
+ { 0x1a, 0x411111f0 }, /* N/A */
+ { 0x1b, 0x411111f0 }, /* N/A */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ { 0x1e, 0x01454140 }, /* SPDIF out */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_VOL_KNOB,
+ },
+ [ALC880_FIXUP_F1734] = {
+ /* almost compatible with FUJITSU, but no bass and SPDIF */
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x0121411f }, /* HP */
+ { 0x15, 0x99030120 }, /* speaker */
+ { 0x16, 0x411111f0 }, /* N/A */
+ { 0x17, 0x411111f0 }, /* N/A */
+ { 0x18, 0x411111f0 }, /* N/A */
+ { 0x19, 0x01a19950 }, /* mic-in */
+ { 0x1a, 0x411111f0 }, /* N/A */
+ { 0x1b, 0x411111f0 }, /* N/A */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ { 0x1e, 0x411111f0 }, /* N/A */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_VOL_KNOB,
+ },
+ [ALC880_FIXUP_UNIWILL] = {
+ /* need to fix HP and speaker pins to be parsed correctly */
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x0121411f }, /* HP */
+ { 0x15, 0x99030120 }, /* speaker */
+ { 0x16, 0x99030130 }, /* bass speaker */
+ { }
+ },
+ },
+ [ALC880_FIXUP_UNIWILL_DIG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ /* disable bogus unused pins */
+ { 0x17, 0x411111f0 },
+ { 0x19, 0x411111f0 },
+ { 0x1b, 0x411111f0 },
+ { 0x1f, 0x411111f0 },
+ { }
+ }
+ },
+ [ALC880_FIXUP_Z71V] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ /* set up the whole pins as BIOS is utterly broken */
+ { 0x14, 0x99030120 }, /* speaker */
+ { 0x15, 0x0121411f }, /* HP */
+ { 0x16, 0x411111f0 }, /* N/A */
+ { 0x17, 0x411111f0 }, /* N/A */
+ { 0x18, 0x01a19950 }, /* mic-in */
+ { 0x19, 0x411111f0 }, /* N/A */
+ { 0x1a, 0x01813031 }, /* line-in */
+ { 0x1b, 0x411111f0 }, /* N/A */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ { 0x1e, 0x0144111e }, /* SPDIF */
+ { }
+ }
+ },
+ [ALC880_FIXUP_3ST_BASE] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x01014010 }, /* line-out */
+ { 0x15, 0x411111f0 }, /* N/A */
+ { 0x16, 0x411111f0 }, /* N/A */
+ { 0x17, 0x411111f0 }, /* N/A */
+ { 0x18, 0x01a19c30 }, /* mic-in */
+ { 0x19, 0x0121411f }, /* HP */
+ { 0x1a, 0x01813031 }, /* line-in */
+ { 0x1b, 0x02a19c40 }, /* front-mic */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ /* 0x1e is filled in below */
+ { 0x1f, 0x411111f0 }, /* N/A */
+ { }
+ }
+ },
+ [ALC880_FIXUP_3ST] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x411111f0 }, /* N/A */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_3ST_BASE,
+ },
+ [ALC880_FIXUP_3ST_DIG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x0144111e }, /* SPDIF */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_3ST_BASE,
+ },
+ [ALC880_FIXUP_5ST_BASE] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x01014010 }, /* front */
+ { 0x15, 0x411111f0 }, /* N/A */
+ { 0x16, 0x01011411 }, /* CLFE */
+ { 0x17, 0x01016412 }, /* surr */
+ { 0x18, 0x01a19c30 }, /* mic-in */
+ { 0x19, 0x0121411f }, /* HP */
+ { 0x1a, 0x01813031 }, /* line-in */
+ { 0x1b, 0x02a19c40 }, /* front-mic */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ /* 0x1e is filled in below */
+ { 0x1f, 0x411111f0 }, /* N/A */
+ { }
+ }
+ },
+ [ALC880_FIXUP_5ST] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x411111f0 }, /* N/A */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_5ST_BASE,
+ },
+ [ALC880_FIXUP_5ST_DIG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x0144111e }, /* SPDIF */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_5ST_BASE,
+ },
+ [ALC880_FIXUP_6ST_BASE] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x01014010 }, /* front */
+ { 0x15, 0x01016412 }, /* surr */
+ { 0x16, 0x01011411 }, /* CLFE */
+ { 0x17, 0x01012414 }, /* side */
+ { 0x18, 0x01a19c30 }, /* mic-in */
+ { 0x19, 0x02a19c40 }, /* front-mic */
+ { 0x1a, 0x01813031 }, /* line-in */
+ { 0x1b, 0x0121411f }, /* HP */
+ { 0x1c, 0x411111f0 }, /* N/A */
+ { 0x1d, 0x411111f0 }, /* N/A */
+ /* 0x1e is filled in below */
+ { 0x1f, 0x411111f0 }, /* N/A */
+ { }
+ }
+ },
+ [ALC880_FIXUP_6ST] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x411111f0 }, /* N/A */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_6ST_BASE,
+ },
+ [ALC880_FIXUP_6ST_DIG] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1e, 0x0144111e }, /* SPDIF */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC880_FIXUP_6ST_BASE,
+ },
+};
+
+static const struct snd_pci_quirk alc880_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_FIXUP_W810),
+ SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_FIXUP_Z71V),
+ SND_PCI_QUIRK_VENDOR(0x1043, "ASUS", ALC880_FIXUP_GPIO1),
+ SND_PCI_QUIRK(0x1558, 0x5401, "Clevo GPIO2", ALC880_FIXUP_GPIO2),
+ SND_PCI_QUIRK_VENDOR(0x1558, "Clevo", ALC880_FIXUP_EAPD_COEF),
+ SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_FIXUP_UNIWILL_DIG),
+ SND_PCI_QUIRK(0x1584, 0x9054, "Uniwill", ALC880_FIXUP_F1734),
+ SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_FIXUP_UNIWILL),
+ SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
+ SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
+ SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
+ SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734),
+ SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
+ SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
+ SND_PCI_QUIRK(0x1734, 0x10b0, "FSC Amilo Pi1556", ALC880_FIXUP_FUJITSU),
+ SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_FIXUP_LG),
+ SND_PCI_QUIRK(0x1854, 0x005f, "LG P1 Express", ALC880_FIXUP_LG),
+ SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_FIXUP_LG),
+ SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_FIXUP_TCL_S700),
+
+ /* Below is the copied entries from alc880_quirks.c.
+ * It's not quite sure whether BIOS sets the correct pin-config table
+ * on these machines, thus they are kept to be compatible with
+ * the old static quirks. Once when it's confirmed to work without
+ * these overrides, it'd be better to remove.
+ */
+ SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_FIXUP_6ST),
+ SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_FIXUP_3ST),
+ SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_FIXUP_3ST),
+ SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_FIXUP_3ST),
+ SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_FIXUP_5ST),
+ SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_FIXUP_5ST),
+ SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_FIXUP_5ST),
+ SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_FIXUP_6ST_DIG), /* broken BIOS */
+ SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_FIXUP_6ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_FIXUP_3ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_FIXUP_5ST_DIG),
+ /* default Intel */
+ SND_PCI_QUIRK_VENDOR(0x8086, "Intel mobo", ALC880_FIXUP_3ST),
+ SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_FIXUP_5ST_DIG),
+ SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_FIXUP_6ST_DIG),
+ {}
+};
+
+static const struct alc_model_fixup alc880_fixup_models[] = {
+ {.id = ALC880_FIXUP_3ST, .name = "3stack"},
+ {.id = ALC880_FIXUP_3ST_DIG, .name = "3stack-digout"},
+ {.id = ALC880_FIXUP_5ST, .name = "5stack"},
+ {.id = ALC880_FIXUP_5ST_DIG, .name = "5stack-digout"},
+ {.id = ALC880_FIXUP_6ST, .name = "6stack"},
+ {.id = ALC880_FIXUP_6ST_DIG, .name = "6stack-digout"},
+ {}
+};
+
/*
* OK, here we have finally the patch for ALC880
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc880_quirks.c"
-#endif
-
static int patch_alc880(struct hda_codec *codec)
{
struct alc_spec *spec;
- int board_config;
int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -3660,63 +4807,31 @@ static int patch_alc880(struct hda_codec *codec)
spec->mixer_nid = 0x0b;
spec->need_dac_fix = 1;
- board_config = alc_board_config(codec, ALC880_MODEL_LAST,
- alc880_models, alc880_cfg_tbl);
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc880_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using 3-stack mode...\n");
- board_config = ALC880_3ST;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO)
- setup_preset(codec, &alc880_presets[board_config]);
-
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
+ alc_pick_fixup(codec, alc880_fixup_models, alc880_fixup_tbl,
+ alc880_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ /* automatic parse from the BIOS config */
+ err = alc880_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog) {
err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
}
- spec->vmaster_nid = 0x0c;
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc880_loopbacks;
-#endif
+
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
+
+ error:
+ alc_free(codec);
+ return err;
}
@@ -3730,49 +4845,115 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
return alc_parse_auto_config(codec, alc260_ignore, alc260_ssids);
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc260_loopbacks[] = {
- { 0x07, HDA_INPUT, 0 },
- { 0x07, HDA_INPUT, 1 },
- { 0x07, HDA_INPUT, 2 },
- { 0x07, HDA_INPUT, 3 },
- { 0x07, HDA_INPUT, 4 },
- { } /* end */
-};
-#endif
-
/*
* Pin config fixes
*/
enum {
- PINFIX_HP_DC5750,
+ ALC260_FIXUP_HP_DC5750,
+ ALC260_FIXUP_HP_PIN_0F,
+ ALC260_FIXUP_COEF,
+ ALC260_FIXUP_GPIO1,
+ ALC260_FIXUP_GPIO1_TOGGLE,
+ ALC260_FIXUP_REPLACER,
+ ALC260_FIXUP_HP_B1900,
};
+static void alc260_gpio1_automute(struct hda_codec *codec)
+{
+ struct alc_spec *spec = codec->spec;
+ snd_hda_codec_write(codec, 0x01, 0, AC_VERB_SET_GPIO_DATA,
+ spec->hp_jack_present);
+}
+
+static void alc260_fixup_gpio1_toggle(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ if (action == ALC_FIXUP_ACT_PROBE) {
+ /* although the machine has only one output pin, we need to
+ * toggle GPIO1 according to the jack state
+ */
+ spec->automute_hook = alc260_gpio1_automute;
+ spec->detect_hp = 1;
+ spec->automute_speaker = 1;
+ spec->autocfg.hp_pins[0] = 0x0f; /* copy it for automute */
+ snd_hda_jack_detect_enable(codec, 0x0f, ALC_HP_EVENT);
+ spec->unsol_event = alc_sku_unsol_event;
+ add_verb(codec->spec, alc_gpio1_init_verbs);
+ }
+}
+
static const struct alc_fixup alc260_fixups[] = {
- [PINFIX_HP_DC5750] = {
+ [ALC260_FIXUP_HP_DC5750] = {
.type = ALC_FIXUP_PINS,
.v.pins = (const struct alc_pincfg[]) {
{ 0x11, 0x90130110 }, /* speaker */
{ }
}
},
+ [ALC260_FIXUP_HP_PIN_0F] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x0f, 0x01214000 }, /* HP */
+ { }
+ }
+ },
+ [ALC260_FIXUP_COEF] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3040 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC260_FIXUP_HP_PIN_0F,
+ },
+ [ALC260_FIXUP_GPIO1] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio1_init_verbs,
+ },
+ [ALC260_FIXUP_GPIO1_TOGGLE] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc260_fixup_gpio1_toggle,
+ .chained = true,
+ .chain_id = ALC260_FIXUP_HP_PIN_0F,
+ },
+ [ALC260_FIXUP_REPLACER] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC260_FIXUP_GPIO1_TOGGLE,
+ },
+ [ALC260_FIXUP_HP_B1900] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc260_fixup_gpio1_toggle,
+ .chained = true,
+ .chain_id = ALC260_FIXUP_COEF,
+ }
};
static const struct snd_pci_quirk alc260_fixup_tbl[] = {
- SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", PINFIX_HP_DC5750),
+ SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_FIXUP_GPIO1),
+ SND_PCI_QUIRK(0x1025, 0x007f, "Acer Aspire 9500", ALC260_FIXUP_COEF),
+ SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_FIXUP_GPIO1),
+ SND_PCI_QUIRK(0x103c, 0x280a, "HP dc5750", ALC260_FIXUP_HP_DC5750),
+ SND_PCI_QUIRK(0x103c, 0x30ba, "HP Presario B1900", ALC260_FIXUP_HP_B1900),
+ SND_PCI_QUIRK(0x1509, 0x4540, "Favorit 100XS", ALC260_FIXUP_GPIO1),
+ SND_PCI_QUIRK(0x161f, 0x2057, "Replacer 672V", ALC260_FIXUP_REPLACER),
+ SND_PCI_QUIRK(0x1631, 0xc017, "PB V7900", ALC260_FIXUP_COEF),
{}
};
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc260_quirks.c"
-#endif
-
static int patch_alc260(struct hda_codec *codec)
{
struct alc_spec *spec;
- int err, board_config;
+ int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -3782,71 +4963,31 @@ static int patch_alc260(struct hda_codec *codec)
spec->mixer_nid = 0x07;
- board_config = alc_board_config(codec, ALC260_MODEL_LAST,
- alc260_models, alc260_cfg_tbl);
- if (board_config < 0) {
- snd_printd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc260_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC260_BASIC;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO)
- setup_preset(codec, &alc260_presets[board_config]);
+ alc_pick_fixup(codec, NULL, alc260_fixup_tbl, alc260_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ /* automatic parse from the BIOS config */
+ err = alc260_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog) {
err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
set_beep_amp(spec, 0x07, 0x05, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
- spec->vmaster_nid = 0x08;
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc_eapd_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc260_loopbacks;
-#endif
+
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
+
+ error:
+ alc_free(codec);
+ return err;
}
@@ -3861,22 +5002,159 @@ static int patch_alc260(struct hda_codec *codec)
* In addition, an independent DAC for the multi-playback (not used in this
* driver yet).
*/
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc882_loopbacks alc880_loopbacks
-#endif
/*
* Pin config fixes
*/
enum {
- PINFIX_ABIT_AW9D_MAX,
- PINFIX_LENOVO_Y530,
- PINFIX_PB_M5210,
- PINFIX_ACER_ASPIRE_7736,
+ ALC882_FIXUP_ABIT_AW9D_MAX,
+ ALC882_FIXUP_LENOVO_Y530,
+ ALC882_FIXUP_PB_M5210,
+ ALC882_FIXUP_ACER_ASPIRE_7736,
+ ALC882_FIXUP_ASUS_W90V,
+ ALC889_FIXUP_CD,
+ ALC889_FIXUP_VAIO_TT,
+ ALC888_FIXUP_EEE1601,
+ ALC882_FIXUP_EAPD,
+ ALC883_FIXUP_EAPD,
+ ALC883_FIXUP_ACER_EAPD,
+ ALC882_FIXUP_GPIO1,
+ ALC882_FIXUP_GPIO2,
+ ALC882_FIXUP_GPIO3,
+ ALC889_FIXUP_COEF,
+ ALC882_FIXUP_ASUS_W2JC,
+ ALC882_FIXUP_ACER_ASPIRE_4930G,
+ ALC882_FIXUP_ACER_ASPIRE_8930G,
+ ALC882_FIXUP_ASPIRE_8930G_VERBS,
+ ALC885_FIXUP_MACPRO_GPIO,
+ ALC889_FIXUP_DAC_ROUTE,
+ ALC889_FIXUP_MBP_VREF,
+ ALC889_FIXUP_IMAC91_VREF,
};
+static void alc889_fixup_coef(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ if (action != ALC_FIXUP_ACT_INIT)
+ return;
+ alc889_coef_init(codec);
+}
+
+/* toggle speaker-output according to the hp-jack state */
+static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
+{
+ unsigned int gpiostate, gpiomask, gpiodir;
+
+ gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
+ AC_VERB_GET_GPIO_DATA, 0);
+
+ if (!muted)
+ gpiostate |= (1 << pin);
+ else
+ gpiostate &= ~(1 << pin);
+
+ gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
+ AC_VERB_GET_GPIO_MASK, 0);
+ gpiomask |= (1 << pin);
+
+ gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
+ AC_VERB_GET_GPIO_DIRECTION, 0);
+ gpiodir |= (1 << pin);
+
+
+ snd_hda_codec_write(codec, codec->afg, 0,
+ AC_VERB_SET_GPIO_MASK, gpiomask);
+ snd_hda_codec_write(codec, codec->afg, 0,
+ AC_VERB_SET_GPIO_DIRECTION, gpiodir);
+
+ msleep(1);
+
+ snd_hda_codec_write(codec, codec->afg, 0,
+ AC_VERB_SET_GPIO_DATA, gpiostate);
+}
+
+/* set up GPIO at initialization */
+static void alc885_fixup_macpro_gpio(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ if (action != ALC_FIXUP_ACT_INIT)
+ return;
+ alc882_gpio_mute(codec, 0, 0);
+ alc882_gpio_mute(codec, 1, 0);
+}
+
+/* Fix the connection of some pins for ALC889:
+ * At least, Acer Aspire 5935 shows the connections to DAC3/4 don't
+ * work correctly (bko#42740)
+ */
+static void alc889_fixup_dac_route(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ if (action == ALC_FIXUP_ACT_PRE_PROBE) {
+ /* fake the connections during parsing the tree */
+ hda_nid_t conn1[2] = { 0x0c, 0x0d };
+ hda_nid_t conn2[2] = { 0x0e, 0x0f };
+ snd_hda_override_conn_list(codec, 0x14, 2, conn1);
+ snd_hda_override_conn_list(codec, 0x15, 2, conn1);
+ snd_hda_override_conn_list(codec, 0x18, 2, conn2);
+ snd_hda_override_conn_list(codec, 0x1a, 2, conn2);
+ } else if (action == ALC_FIXUP_ACT_PROBE) {
+ /* restore the connections */
+ hda_nid_t conn[5] = { 0x0c, 0x0d, 0x0e, 0x0f, 0x26 };
+ snd_hda_override_conn_list(codec, 0x14, 5, conn);
+ snd_hda_override_conn_list(codec, 0x15, 5, conn);
+ snd_hda_override_conn_list(codec, 0x18, 5, conn);
+ snd_hda_override_conn_list(codec, 0x1a, 5, conn);
+ }
+}
+
+/* Set VREF on HP pin */
+static void alc889_fixup_mbp_vref(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ static hda_nid_t nids[2] = { 0x14, 0x15 };
+ int i;
+
+ if (action != ALC_FIXUP_ACT_INIT)
+ return;
+ for (i = 0; i < ARRAY_SIZE(nids); i++) {
+ unsigned int val = snd_hda_codec_get_pincfg(codec, nids[i]);
+ if (get_defcfg_device(val) != AC_JACK_HP_OUT)
+ continue;
+ val = snd_hda_codec_read(codec, nids[i], 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ val |= AC_PINCTL_VREF_80;
+ snd_hda_codec_write(codec, nids[i], 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ spec->keep_vref_in_automute = 1;
+ break;
+ }
+}
+
+/* Set VREF on speaker pins on imac91 */
+static void alc889_fixup_imac91_vref(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ static hda_nid_t nids[2] = { 0x18, 0x1a };
+ int i;
+
+ if (action != ALC_FIXUP_ACT_INIT)
+ return;
+ for (i = 0; i < ARRAY_SIZE(nids); i++) {
+ unsigned int val;
+ val = snd_hda_codec_read(codec, nids[i], 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ val |= AC_PINCTL_VREF_50;
+ snd_hda_codec_write(codec, nids[i], 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ }
+ spec->keep_vref_in_automute = 1;
+}
+
static const struct alc_fixup alc882_fixups[] = {
- [PINFIX_ABIT_AW9D_MAX] = {
+ [ALC882_FIXUP_ABIT_AW9D_MAX] = {
.type = ALC_FIXUP_PINS,
.v.pins = (const struct alc_pincfg[]) {
{ 0x15, 0x01080104 }, /* side */
@@ -3885,7 +5163,7 @@ static const struct alc_fixup alc882_fixups[] = {
{ }
}
},
- [PINFIX_LENOVO_Y530] = {
+ [ALC882_FIXUP_LENOVO_Y530] = {
.type = ALC_FIXUP_PINS,
.v.pins = (const struct alc_pincfg[]) {
{ 0x15, 0x99130112 }, /* rear int speakers */
@@ -3893,24 +5171,228 @@ static const struct alc_fixup alc882_fixups[] = {
{ }
}
},
- [PINFIX_PB_M5210] = {
+ [ALC882_FIXUP_PB_M5210] = {
.type = ALC_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
{ 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
{}
}
},
- [PINFIX_ACER_ASPIRE_7736] = {
+ [ALC882_FIXUP_ACER_ASPIRE_7736] = {
.type = ALC_FIXUP_SKU,
.v.sku = ALC_FIXUP_SKU_IGNORE,
},
+ [ALC882_FIXUP_ASUS_W90V] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x16, 0x99130110 }, /* fix sequence for CLFE */
+ { }
+ }
+ },
+ [ALC889_FIXUP_CD] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1c, 0x993301f0 }, /* CD */
+ { }
+ }
+ },
+ [ALC889_FIXUP_VAIO_TT] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x17, 0x90170111 }, /* hidden surround speaker */
+ { }
+ }
+ },
+ [ALC888_FIXUP_EEE1601] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0838 },
+ { }
+ }
+ },
+ [ALC882_FIXUP_EAPD] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* change to EAPD mode */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3060 },
+ { }
+ }
+ },
+ [ALC883_FIXUP_EAPD] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* change to EAPD mode */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
+ { }
+ }
+ },
+ [ALC883_FIXUP_ACER_EAPD] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* eanable EAPD on Acer laptops */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
+ { }
+ }
+ },
+ [ALC882_FIXUP_GPIO1] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio1_init_verbs,
+ },
+ [ALC882_FIXUP_GPIO2] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio2_init_verbs,
+ },
+ [ALC882_FIXUP_GPIO3] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio3_init_verbs,
+ },
+ [ALC882_FIXUP_ASUS_W2JC] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = alc_gpio1_init_verbs,
+ .chained = true,
+ .chain_id = ALC882_FIXUP_EAPD,
+ },
+ [ALC889_FIXUP_COEF] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc889_fixup_coef,
+ },
+ [ALC882_FIXUP_ACER_ASPIRE_4930G] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x16, 0x99130111 }, /* CLFE speaker */
+ { 0x17, 0x99130112 }, /* surround speaker */
+ { }
+ }
+ },
+ [ALC882_FIXUP_ACER_ASPIRE_8930G] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x16, 0x99130111 }, /* CLFE speaker */
+ { 0x1b, 0x99130112 }, /* surround speaker */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC882_FIXUP_ASPIRE_8930G_VERBS,
+ },
+ [ALC882_FIXUP_ASPIRE_8930G_VERBS] = {
+ /* additional init verbs for Acer Aspire 8930G */
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ /* Enable all DACs */
+ /* DAC DISABLE/MUTE 1? */
+ /* setting bits 1-5 disables DAC nids 0x02-0x06
+ * apparently. Init=0x38 */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x03 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
+ /* DAC DISABLE/MUTE 2? */
+ /* some bit here disables the other DACs.
+ * Init=0x4900 */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x08 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0000 },
+ /* DMIC fix
+ * This laptop has a stereo digital microphone.
+ * The mics are only 1cm apart which makes the stereo
+ * useless. However, either the mic or the ALC889
+ * makes the signal become a difference/sum signal
+ * instead of standard stereo, which is annoying.
+ * So instead we flip this bit which makes the
+ * codec replicate the sum signal to both channels,
+ * turning it into a normal mono mic.
+ */
+ /* DMIC_CONTROL? Init value = 0x0001 */
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x0b },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x0003 },
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
+ { }
+ }
+ },
+ [ALC885_FIXUP_MACPRO_GPIO] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc885_fixup_macpro_gpio,
+ },
+ [ALC889_FIXUP_DAC_ROUTE] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc889_fixup_dac_route,
+ },
+ [ALC889_FIXUP_MBP_VREF] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc889_fixup_mbp_vref,
+ .chained = true,
+ .chain_id = ALC882_FIXUP_GPIO1,
+ },
+ [ALC889_FIXUP_IMAC91_VREF] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc889_fixup_imac91_vref,
+ .chained = true,
+ .chain_id = ALC882_FIXUP_GPIO1,
+ },
};
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210),
- SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", PINFIX_LENOVO_Y530),
- SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX),
- SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736),
+ SND_PCI_QUIRK(0x1025, 0x006c, "Acer Aspire 9810", ALC883_FIXUP_ACER_EAPD),
+ SND_PCI_QUIRK(0x1025, 0x0090, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
+ SND_PCI_QUIRK(0x1025, 0x010a, "Acer Ferrari 5000", ALC883_FIXUP_ACER_EAPD),
+ SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_FIXUP_ACER_EAPD),
+ SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_FIXUP_ACER_EAPD),
+ SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_FIXUP_ACER_EAPD),
+ SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
+ ALC882_FIXUP_ACER_ASPIRE_4930G),
+ SND_PCI_QUIRK(0x1025, 0x013f, "Acer Aspire 5930G",
+ ALC882_FIXUP_ACER_ASPIRE_4930G),
+ SND_PCI_QUIRK(0x1025, 0x0145, "Acer Aspire 8930G",
+ ALC882_FIXUP_ACER_ASPIRE_8930G),
+ SND_PCI_QUIRK(0x1025, 0x0146, "Acer Aspire 6935G",
+ ALC882_FIXUP_ACER_ASPIRE_8930G),
+ SND_PCI_QUIRK(0x1025, 0x015e, "Acer Aspire 6930G",
+ ALC882_FIXUP_ACER_ASPIRE_4930G),
+ SND_PCI_QUIRK(0x1025, 0x0166, "Acer Aspire 6530G",
+ ALC882_FIXUP_ACER_ASPIRE_4930G),
+ SND_PCI_QUIRK(0x1025, 0x0142, "Acer Aspire 7730G",
+ ALC882_FIXUP_ACER_ASPIRE_4930G),
+ SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", ALC882_FIXUP_PB_M5210),
+ SND_PCI_QUIRK(0x1025, 0x0259, "Acer Aspire 5935", ALC889_FIXUP_DAC_ROUTE),
+ SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", ALC882_FIXUP_ACER_ASPIRE_7736),
+ SND_PCI_QUIRK(0x1043, 0x13c2, "Asus A7M", ALC882_FIXUP_EAPD),
+ SND_PCI_QUIRK(0x1043, 0x1873, "ASUS W90V", ALC882_FIXUP_ASUS_W90V),
+ SND_PCI_QUIRK(0x1043, 0x1971, "Asus W2JC", ALC882_FIXUP_ASUS_W2JC),
+ SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_FIXUP_EEE1601),
+ SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
+
+ /* All Apple entries are in codec SSIDs */
+ SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x00a1, "Macbook", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x00a4, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x0c00, "Mac Pro", ALC885_FIXUP_MACPRO_GPIO),
+ SND_PCI_QUIRK(0x106b, 0x1000, "iMac 24", ALC885_FIXUP_MACPRO_GPIO),
+ SND_PCI_QUIRK(0x106b, 0x2800, "AppleTV", ALC885_FIXUP_MACPRO_GPIO),
+ SND_PCI_QUIRK(0x106b, 0x2c00, "MacbookPro rev3", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3000, "iMac", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3200, "iMac 7,1 Aluminum", ALC882_FIXUP_EAPD),
+ SND_PCI_QUIRK(0x106b, 0x3400, "MacBookAir 1,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3500, "MacBookAir 2,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3600, "Macbook 3,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3800, "MacbookPro 4,1", ALC889_FIXUP_MBP_VREF),
+ SND_PCI_QUIRK(0x106b, 0x3e00, "iMac 24 Aluminum", ALC885_FIXUP_MACPRO_GPIO),
+ SND_PCI_QUIRK(0x106b, 0x3f00, "Macbook 5,1", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4000, "MacbookPro 5,1", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4100, "Macmini 3,1", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4600, "MacbookPro 5,2", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4900, "iMac 9,1 Aluminum", ALC889_FIXUP_IMAC91_VREF),
+ SND_PCI_QUIRK(0x106b, 0x4a00, "Macbook 5,2", ALC889_FIXUP_IMAC91_VREF),
+
+ SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC882_FIXUP_EAPD),
+ SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
+ SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3", ALC889_FIXUP_CD),
+ SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
+ SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
+ SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
+ SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
+ SND_PCI_QUIRK(0x8086, 0x0022, "DX58SO", ALC889_FIXUP_COEF),
{}
};
@@ -3927,14 +5409,10 @@ static int alc882_parse_auto_config(struct hda_codec *codec)
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc882_quirks.c"
-#endif
-
static int patch_alc882(struct hda_codec *codec)
{
struct alc_spec *spec;
- int err, board_config;
+ int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -3954,79 +5432,36 @@ static int patch_alc882(struct hda_codec *codec)
break;
}
- board_config = alc_board_config(codec, ALC882_MODEL_LAST,
- alc882_models, alc882_cfg_tbl);
-
- if (board_config < 0)
- board_config = alc_board_codec_sid_config(codec,
- ALC882_MODEL_LAST, alc882_models, alc882_ssid_cfg_tbl);
+ err = alc_codec_rename_from_preset(codec);
+ if (err < 0)
+ goto error;
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- }
+ alc_pick_fixup(codec, NULL, alc882_fixup_tbl, alc882_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
alc_auto_parse_customize_define(codec);
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc882_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC882_3ST_DIG;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO)
- setup_preset(codec, &alc882_presets[board_config]);
-
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ /* automatic parse from the BIOS config */
+ err = alc882_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
- spec->vmaster_nid = 0x0c;
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
- alc_init_jacks(codec);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc882_loopbacks;
-#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
+
+ error:
+ alc_free(codec);
+ return err;
}
@@ -4044,12 +5479,16 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
* Pin config fixes
*/
enum {
- PINFIX_FSC_H270,
- PINFIX_HP_Z200,
+ ALC262_FIXUP_FSC_H270,
+ ALC262_FIXUP_HP_Z200,
+ ALC262_FIXUP_TYAN,
+ ALC262_FIXUP_LENOVO_3000,
+ ALC262_FIXUP_BENQ,
+ ALC262_FIXUP_BENQ_T31,
};
static const struct alc_fixup alc262_fixups[] = {
- [PINFIX_FSC_H270] = {
+ [ALC262_FIXUP_FSC_H270] = {
.type = ALC_FIXUP_PINS,
.v.pins = (const struct alc_pincfg[]) {
{ 0x14, 0x99130110 }, /* speaker */
@@ -4058,36 +5497,65 @@ static const struct alc_fixup alc262_fixups[] = {
{ }
}
},
- [PINFIX_HP_Z200] = {
+ [ALC262_FIXUP_HP_Z200] = {
.type = ALC_FIXUP_PINS,
.v.pins = (const struct alc_pincfg[]) {
{ 0x16, 0x99130120 }, /* internal speaker */
{ }
}
},
+ [ALC262_FIXUP_TYAN] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x1993e1f0 }, /* int AUX */
+ { }
+ }
+ },
+ [ALC262_FIXUP_LENOVO_3000] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 },
+ {}
+ },
+ .chained = true,
+ .chain_id = ALC262_FIXUP_BENQ,
+ },
+ [ALC262_FIXUP_BENQ] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3070 },
+ {}
+ }
+ },
+ [ALC262_FIXUP_BENQ_T31] = {
+ .type = ALC_FIXUP_VERBS,
+ .v.verbs = (const struct hda_verb[]) {
+ { 0x20, AC_VERB_SET_COEF_INDEX, 0x07 },
+ { 0x20, AC_VERB_SET_PROC_COEF, 0x3050 },
+ {}
+ }
+ },
};
static const struct snd_pci_quirk alc262_fixup_tbl[] = {
- SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", PINFIX_HP_Z200),
- SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270),
+ SND_PCI_QUIRK(0x103c, 0x170b, "HP Z200", ALC262_FIXUP_HP_Z200),
+ SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FIXUP_BENQ),
+ SND_PCI_QUIRK(0x10cf, 0x142d, "Fujitsu Lifebook E8410", ALC262_FIXUP_BENQ),
+ SND_PCI_QUIRK(0x10f1, 0x2915, "Tyan Thunder n6650W", ALC262_FIXUP_TYAN),
+ SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", ALC262_FIXUP_FSC_H270),
+ SND_PCI_QUIRK(0x17aa, 0x384e, "Lenovo 3000", ALC262_FIXUP_LENOVO_3000),
+ SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_FIXUP_BENQ),
+ SND_PCI_QUIRK(0x17ff, 0x058d, "Benq T31-16", ALC262_FIXUP_BENQ_T31),
{}
};
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc262_loopbacks alc880_loopbacks
-#endif
-
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc262_quirks.c"
-#endif
-
static int patch_alc262(struct hda_codec *codec)
{
struct alc_spec *spec;
- int board_config;
int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -4114,74 +5582,31 @@ static int patch_alc262(struct hda_codec *codec)
alc_fix_pll_init(codec, 0x20, 0x0a, 10);
- board_config = alc_board_config(codec, ALC262_MODEL_LAST,
- alc262_models, alc262_cfg_tbl);
-
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- }
+ alc_pick_fixup(codec, NULL, alc262_fixup_tbl, alc262_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc262_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC262_BASIC;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO)
- setup_preset(codec, &alc262_presets[board_config]);
-
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ /* automatic parse from the BIOS config */
+ err = alc262_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
- spec->vmaster_nid = 0x0c;
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc_eapd_shutup;
- alc_init_jacks(codec);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc262_loopbacks;
-#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
+
+ error:
+ alc_free(codec);
+ return err;
}
/*
@@ -4230,14 +5655,9 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc268_quirks.c"
-#endif
-
static int patch_alc268(struct hda_codec *codec)
{
struct alc_spec *spec;
- int board_config;
int i, has_beep, err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -4248,38 +5668,10 @@ static int patch_alc268(struct hda_codec *codec)
/* ALC268 has no aa-loopback mixer */
- board_config = alc_board_config(codec, ALC268_MODEL_LAST,
- alc268_models, alc268_cfg_tbl);
-
- if (board_config < 0)
- board_config = alc_board_codec_sid_config(codec,
- ALC268_MODEL_LAST, alc268_models, alc268_ssid_cfg_tbl);
-
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc268_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC268_3ST;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO)
- setup_preset(codec, &alc268_presets[board_config]);
+ /* automatic parse from the BIOS config */
+ err = alc268_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
has_beep = 0;
for (i = 0; i < spec->num_mixers; i++) {
@@ -4291,10 +5683,8 @@ static int patch_alc268(struct hda_codec *codec)
if (has_beep) {
err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
if (!query_amp_caps(codec, 0x1d, HDA_INPUT))
/* override the amp caps for beep generator */
snd_hda_override_amp_caps(codec, 0x1d, HDA_INPUT,
@@ -4304,34 +5694,19 @@ static int patch_alc268(struct hda_codec *codec)
(0 << AC_AMPCAP_MUTE_SHIFT));
}
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
- spec->vmaster_nid = 0x02;
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc_eapd_shutup;
- alc_init_jacks(codec);
-
return 0;
+
+ error:
+ alc_free(codec);
+ return err;
}
/*
* ALC269
*/
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc269_loopbacks alc880_loopbacks
-#endif
-
static const struct hda_pcm_stream alc269_44k_pcm_analog_playback = {
.substreams = 1,
.channels_min = 2,
@@ -4353,35 +5728,6 @@ static const struct hda_pcm_stream alc269_44k_pcm_analog_capture = {
/* NID is set in alc_build_pcms */
};
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int alc269_mic2_for_mute_led(struct hda_codec *codec)
-{
- switch (codec->subsystem_id) {
- case 0x103c1586:
- return 1;
- }
- return 0;
-}
-
-static int alc269_mic2_mute_check_ps(struct hda_codec *codec, hda_nid_t nid)
-{
- /* update mute-LED according to the speaker mute state */
- if (nid == 0x01 || nid == 0x14) {
- int pinval;
- if (snd_hda_codec_amp_read(codec, 0x14, 0, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)
- pinval = 0x24;
- else
- pinval = 0x20;
- /* mic2 vref pin is used for mute LED control */
- snd_hda_codec_update_cache(codec, 0x19, 0,
- AC_VERB_SET_PIN_WIDGET_CONTROL,
- pinval);
- }
- return alc_check_power_status(codec, nid);
-}
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
-
/* different alc269-variants */
enum {
ALC269_TYPE_ALC269VA,
@@ -4416,9 +5762,9 @@ static void alc269_toggle_power_output(struct hda_codec *codec, int power_up)
static void alc269_shutup(struct hda_codec *codec)
{
- if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017)
+ if ((alc_get_coef0(codec) & 0x00ff) == 0x017)
alc269_toggle_power_output(codec, 0);
- if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+ if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
alc269_toggle_power_output(codec, 0);
msleep(150);
}
@@ -4427,19 +5773,19 @@ static void alc269_shutup(struct hda_codec *codec)
#ifdef CONFIG_PM
static int alc269_resume(struct hda_codec *codec)
{
- if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+ if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
alc269_toggle_power_output(codec, 0);
msleep(150);
}
codec->patch_ops.init(codec);
- if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
+ if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
alc269_toggle_power_output(codec, 1);
msleep(200);
}
- if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018)
+ if ((alc_get_coef0(codec) & 0x00ff) == 0x018)
alc269_toggle_power_output(codec, 1);
snd_hda_codec_resume_amp(codec);
@@ -4508,6 +5854,55 @@ static void alc269_fixup_stereo_dmic(struct hda_codec *codec,
alc_write_coef_idx(codec, 0x07, coef | 0x80);
}
+static void alc269_quanta_automute(struct hda_codec *codec)
+{
+ update_outputs(codec);
+
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_COEF_INDEX, 0x0c);
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_PROC_COEF, 0x680);
+
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_COEF_INDEX, 0x0c);
+ snd_hda_codec_write(codec, 0x20, 0,
+ AC_VERB_SET_PROC_COEF, 0x480);
+}
+
+static void alc269_fixup_quanta_mute(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ if (action != ALC_FIXUP_ACT_PROBE)
+ return;
+ spec->automute_hook = alc269_quanta_automute;
+}
+
+/* update mute-LED according to the speaker mute state via mic2 VREF pin */
+static void alc269_fixup_mic2_mute_hook(void *private_data, int enabled)
+{
+ struct hda_codec *codec = private_data;
+ unsigned int pinval = enabled ? 0x20 : 0x24;
+ snd_hda_codec_update_cache(codec, 0x19, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL,
+ pinval);
+}
+
+static void alc269_fixup_mic2_mute(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ switch (action) {
+ case ALC_FIXUP_ACT_BUILD:
+ spec->vmaster_mute.hook = alc269_fixup_mic2_mute_hook;
+ snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true);
+ /* fallthru */
+ case ALC_FIXUP_ACT_INIT:
+ snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
+ break;
+ }
+}
+
enum {
ALC269_FIXUP_SONY_VAIO,
ALC275_FIXUP_SONY_VAIO_GPIO2,
@@ -4519,6 +5914,13 @@ enum {
ALC271_FIXUP_DMIC,
ALC269_FIXUP_PCM_44K,
ALC269_FIXUP_STEREO_DMIC,
+ ALC269_FIXUP_QUANTA_MUTE,
+ ALC269_FIXUP_LIFEBOOK,
+ ALC269_FIXUP_AMIC,
+ ALC269_FIXUP_DMIC,
+ ALC269VB_FIXUP_AMIC,
+ ALC269VB_FIXUP_DMIC,
+ ALC269_FIXUP_MIC2_MUTE_LED,
};
static const struct alc_fixup alc269_fixups[] = {
@@ -4585,9 +5987,68 @@ static const struct alc_fixup alc269_fixups[] = {
.type = ALC_FIXUP_FUNC,
.v.func = alc269_fixup_stereo_dmic,
},
+ [ALC269_FIXUP_QUANTA_MUTE] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc269_fixup_quanta_mute,
+ },
+ [ALC269_FIXUP_LIFEBOOK] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x1a, 0x2101103f }, /* dock line-out */
+ { 0x1b, 0x23a11040 }, /* dock mic-in */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC269_FIXUP_QUANTA_MUTE
+ },
+ [ALC269_FIXUP_AMIC] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x15, 0x0121401f }, /* HP out */
+ { 0x18, 0x01a19c20 }, /* mic */
+ { 0x19, 0x99a3092f }, /* int-mic */
+ { }
+ },
+ },
+ [ALC269_FIXUP_DMIC] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x12, 0x99a3092f }, /* int-mic */
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x15, 0x0121401f }, /* HP out */
+ { 0x18, 0x01a19c20 }, /* mic */
+ { }
+ },
+ },
+ [ALC269VB_FIXUP_AMIC] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x18, 0x01a19c20 }, /* mic */
+ { 0x19, 0x99a3092f }, /* int-mic */
+ { 0x21, 0x0121401f }, /* HP out */
+ { }
+ },
+ },
+ [ALC269VB_FIXUP_DMIC] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x12, 0x99a3092f }, /* int-mic */
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x18, 0x01a19c20 }, /* mic */
+ { 0x21, 0x0121401f }, /* HP out */
+ { }
+ },
+ },
+ [ALC269_FIXUP_MIC2_MUTE_LED] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc269_fixup_mic2_mute,
+ },
};
static const struct snd_pci_quirk alc269_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED),
SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
SND_PCI_QUIRK(0x1043, 0x16e3, "ASUS UX50", ALC269_FIXUP_STEREO_DMIC),
SND_PCI_QUIRK(0x1043, 0x831a, "ASUS P901", ALC269_FIXUP_STEREO_DMIC),
@@ -4600,38 +6061,99 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
+ SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x17aa, 0x21b8, "Thinkpad Edge 14", ALC269_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x17aa, 0x21ca, "Thinkpad L412", ALC269_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x17aa, 0x21e9, "Thinkpad Edge 15", ALC269_FIXUP_SKU_IGNORE),
+ SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_QUANTA_MUTE),
SND_PCI_QUIRK(0x17aa, 0x3bf8, "Lenovo Ideapd", ALC269_FIXUP_PCM_44K),
SND_PCI_QUIRK(0x17aa, 0x9e54, "LENOVO NB", ALC269_FIXUP_LENOVO_EAPD),
+
+#if 0
+ /* Below is a quirk table taken from the old code.
+ * Basically the device should work as is without the fixup table.
+ * If BIOS doesn't give a proper info, enable the corresponding
+ * fixup entry.
+ */
+ SND_PCI_QUIRK(0x1043, 0x8330, "ASUS Eeepc P703 P900A",
+ ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1013, "ASUS N61Da", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1143, "ASUS B53f", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1133, "ASUS UJ20ft", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1183, "ASUS K72DR", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x11b3, "ASUS K52DR", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x11e3, "ASUS U33Jc", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1273, "ASUS UL80Jt", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1283, "ASUS U53Jc", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS N82JV", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x12d3, "ASUS N61Jv", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x13a3, "ASUS UL30Vt", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1373, "ASUS G73JX", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1383, "ASUS UJ30Jc", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x13d3, "ASUS N61JA", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1413, "ASUS UL50", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1443, "ASUS UL30", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1453, "ASUS M60Jv", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1483, "ASUS UL80", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x14f3, "ASUS F83Vf", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x14e3, "ASUS UL20", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1513, "ASUS UX30", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1593, "ASUS N51Vn", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x15a3, "ASUS N60Jv", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x15b3, "ASUS N60Dp", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x15c3, "ASUS N70De", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x15e3, "ASUS F83T", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1643, "ASUS M60J", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1653, "ASUS U50", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1693, "ASUS F50N", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x16a3, "ASUS F5Q", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1723, "ASUS P80", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1743, "ASUS U80", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1773, "ASUS U20A", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x1043, 0x1883, "ASUS F81Se", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x152d, 0x1778, "Quanta ON1", ALC269_FIXUP_DMIC),
+ SND_PCI_QUIRK(0x17aa, 0x3be9, "Quanta Wistron", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x17aa, 0x3bf8, "Quanta FL1", ALC269_FIXUP_AMIC),
+ SND_PCI_QUIRK(0x17ff, 0x059a, "Quanta EL3", ALC269_FIXUP_DMIC),
+ SND_PCI_QUIRK(0x17ff, 0x059b, "Quanta JR1", ALC269_FIXUP_DMIC),
+#endif
+ {}
+};
+
+static const struct alc_model_fixup alc269_fixup_models[] = {
+ {.id = ALC269_FIXUP_AMIC, .name = "laptop-amic"},
+ {.id = ALC269_FIXUP_DMIC, .name = "laptop-dmic"},
{}
};
-static int alc269_fill_coef(struct hda_codec *codec)
+static void alc269_fill_coef(struct hda_codec *codec)
{
+ struct alc_spec *spec = codec->spec;
int val;
- if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) {
+ if (spec->codec_variant != ALC269_TYPE_ALC269VB)
+ return;
+
+ if ((alc_get_coef0(codec) & 0x00ff) < 0x015) {
alc_write_coef_idx(codec, 0xf, 0x960b);
alc_write_coef_idx(codec, 0xe, 0x8817);
}
- if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) {
+ if ((alc_get_coef0(codec) & 0x00ff) == 0x016) {
alc_write_coef_idx(codec, 0xf, 0x960b);
alc_write_coef_idx(codec, 0xe, 0x8814);
}
- if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) {
+ if ((alc_get_coef0(codec) & 0x00ff) == 0x017) {
val = alc_read_coef_idx(codec, 0x04);
/* Power up output pin */
alc_write_coef_idx(codec, 0x04, val | (1<<11));
}
- if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) {
+ if ((alc_get_coef0(codec) & 0x00ff) == 0x018) {
val = alc_read_coef_idx(codec, 0xd);
if ((val & 0x0c00) >> 10 != 0x1) {
/* Capless ramp up clock control */
@@ -4649,21 +6171,14 @@ static int alc269_fill_coef(struct hda_codec *codec)
val = alc_read_coef_idx(codec, 0x4); /* HP */
alc_write_coef_idx(codec, 0x4, val | (1<<11));
-
- return 0;
}
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc269_quirks.c"
-#endif
-
static int patch_alc269(struct hda_codec *codec)
{
struct alc_spec *spec;
- int board_config, coef;
- int err;
+ int err = 0;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -4675,112 +6190,63 @@ static int patch_alc269(struct hda_codec *codec)
alc_auto_parse_customize_define(codec);
+ err = alc_codec_rename_from_preset(codec);
+ if (err < 0)
+ goto error;
+
if (codec->vendor_id == 0x10ec0269) {
spec->codec_variant = ALC269_TYPE_ALC269VA;
- coef = alc_read_coef_idx(codec, 0);
- if ((coef & 0x00f0) == 0x0010) {
+ switch (alc_get_coef0(codec) & 0x00f0) {
+ case 0x0010:
if (codec->bus->pci->subsystem_vendor == 0x1025 &&
- spec->cdefine.platform_type == 1) {
- alc_codec_rename(codec, "ALC271X");
- } else if ((coef & 0xf000) == 0x2000) {
- alc_codec_rename(codec, "ALC259");
- } else if ((coef & 0xf000) == 0x3000) {
- alc_codec_rename(codec, "ALC258");
- } else if ((coef & 0xfff0) == 0x3010) {
- alc_codec_rename(codec, "ALC277");
- } else {
- alc_codec_rename(codec, "ALC269VB");
- }
+ spec->cdefine.platform_type == 1)
+ err = alc_codec_rename(codec, "ALC271X");
spec->codec_variant = ALC269_TYPE_ALC269VB;
- } else if ((coef & 0x00f0) == 0x0020) {
- if (coef == 0xa023)
- alc_codec_rename(codec, "ALC259");
- else if (coef == 0x6023)
- alc_codec_rename(codec, "ALC281X");
- else if (codec->bus->pci->subsystem_vendor == 0x17aa &&
- codec->bus->pci->subsystem_device == 0x21f3)
- alc_codec_rename(codec, "ALC3202");
- else
- alc_codec_rename(codec, "ALC269VC");
+ break;
+ case 0x0020:
+ if (codec->bus->pci->subsystem_vendor == 0x17aa &&
+ codec->bus->pci->subsystem_device == 0x21f3)
+ err = alc_codec_rename(codec, "ALC3202");
spec->codec_variant = ALC269_TYPE_ALC269VC;
- } else
+ break;
+ default:
alc_fix_pll_init(codec, 0x20, 0x04, 15);
- alc269_fill_coef(codec);
- }
-
- board_config = alc_board_config(codec, ALC269_MODEL_LAST,
- alc269_models, alc269_cfg_tbl);
-
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, NULL, alc269_fixup_tbl, alc269_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc269_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
}
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC269_BASIC;
- }
-#endif
+ if (err < 0)
+ goto error;
+ spec->init_hook = alc269_fill_coef;
+ alc269_fill_coef(codec);
}
- if (board_config != ALC_MODEL_AUTO)
- setup_preset(codec, &alc269_presets[board_config]);
-
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
+ alc_pick_fixup(codec, alc269_fixup_models,
+ alc269_fixup_tbl, alc269_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ /* automatic parse from the BIOS config */
+ err = alc269_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
set_beep_amp(spec, 0x0b, 0x04, HDA_INPUT);
}
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
- spec->vmaster_nid = 0x02;
-
codec->patch_ops = alc_patch_ops;
#ifdef CONFIG_PM
codec->patch_ops.resume = alc269_resume;
#endif
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc269_shutup;
- alc_init_jacks(codec);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc269_loopbacks;
- if (alc269_mic2_for_mute_led(codec))
- codec->patch_ops.check_power_status = alc269_mic2_mute_check_ps;
-#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
+
+ error:
+ alc_free(codec);
+ return err;
}
/*
@@ -4794,24 +6260,43 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
return alc_parse_auto_config(codec, alc861_ignore, alc861_ssids);
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-static const struct hda_amp_list alc861_loopbacks[] = {
- { 0x15, HDA_INPUT, 0 },
- { 0x15, HDA_INPUT, 1 },
- { 0x15, HDA_INPUT, 2 },
- { 0x15, HDA_INPUT, 3 },
- { } /* end */
-};
-#endif
-
-
/* Pin config fixes */
enum {
- PINFIX_FSC_AMILO_PI1505,
+ ALC861_FIXUP_FSC_AMILO_PI1505,
+ ALC861_FIXUP_AMP_VREF_0F,
+ ALC861_FIXUP_NO_JACK_DETECT,
+ ALC861_FIXUP_ASUS_A6RP,
};
+/* On some laptops, VREF of pin 0x0f is abused for controlling the main amp */
+static void alc861_fixup_asus_amp_vref_0f(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ struct alc_spec *spec = codec->spec;
+ unsigned int val;
+
+ if (action != ALC_FIXUP_ACT_INIT)
+ return;
+ val = snd_hda_codec_read(codec, 0x0f, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ if (!(val & (AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN)))
+ val |= AC_PINCTL_IN_EN;
+ val |= AC_PINCTL_VREF_50;
+ snd_hda_codec_write(codec, 0x0f, 0,
+ AC_VERB_SET_PIN_WIDGET_CONTROL, val);
+ spec->keep_vref_in_automute = 1;
+}
+
+/* suppress the jack-detection */
+static void alc_fixup_no_jack_detect(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ if (action == ALC_FIXUP_ACT_PRE_PROBE)
+ codec->no_jack_detect = 1;
+}
+
static const struct alc_fixup alc861_fixups[] = {
- [PINFIX_FSC_AMILO_PI1505] = {
+ [ALC861_FIXUP_FSC_AMILO_PI1505] = {
.type = ALC_FIXUP_PINS,
.v.pins = (const struct alc_pincfg[]) {
{ 0x0b, 0x0221101f }, /* HP */
@@ -4819,23 +6304,37 @@ static const struct alc_fixup alc861_fixups[] = {
{ }
}
},
+ [ALC861_FIXUP_AMP_VREF_0F] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc861_fixup_asus_amp_vref_0f,
+ },
+ [ALC861_FIXUP_NO_JACK_DETECT] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc_fixup_no_jack_detect,
+ },
+ [ALC861_FIXUP_ASUS_A6RP] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc861_fixup_asus_amp_vref_0f,
+ .chained = true,
+ .chain_id = ALC861_FIXUP_NO_JACK_DETECT,
+ }
};
static const struct snd_pci_quirk alc861_fixup_tbl[] = {
- SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", PINFIX_FSC_AMILO_PI1505),
+ SND_PCI_QUIRK(0x1043, 0x1393, "ASUS A6Rp", ALC861_FIXUP_ASUS_A6RP),
+ SND_PCI_QUIRK_VENDOR(0x1043, "ASUS laptop", ALC861_FIXUP_AMP_VREF_0F),
+ SND_PCI_QUIRK(0x1462, 0x7254, "HP DX2200", ALC861_FIXUP_NO_JACK_DETECT),
+ SND_PCI_QUIRK(0x1584, 0x2b01, "Haier W18", ALC861_FIXUP_AMP_VREF_0F),
+ SND_PCI_QUIRK(0x1584, 0x0000, "Uniwill ECS M31EI", ALC861_FIXUP_AMP_VREF_0F),
+ SND_PCI_QUIRK(0x1734, 0x10c7, "FSC Amilo Pi1505", ALC861_FIXUP_FSC_AMILO_PI1505),
{}
};
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc861_quirks.c"
-#endif
-
static int patch_alc861(struct hda_codec *codec)
{
struct alc_spec *spec;
- int board_config;
int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -4846,75 +6345,33 @@ static int patch_alc861(struct hda_codec *codec)
spec->mixer_nid = 0x15;
- board_config = alc_board_config(codec, ALC861_MODEL_LAST,
- alc861_models, alc861_cfg_tbl);
-
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc861_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC861_3ST_DIG;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO)
- setup_preset(codec, &alc861_presets[board_config]);
+ alc_pick_fixup(codec, NULL, alc861_fixup_tbl, alc861_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ /* automatic parse from the BIOS config */
+ err = alc861_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog) {
err = snd_hda_attach_beep_device(codec, 0x23);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
set_beep_amp(spec, 0x23, 0, HDA_OUTPUT);
}
- spec->vmaster_nid = 0x03;
-
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO) {
- spec->init_hook = alc_auto_init_std;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- spec->power_hook = alc_power_eapd;
-#endif
- }
#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc861_loopbacks;
+ spec->power_hook = alc_power_eapd;
#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
+
return 0;
+
+ error:
+ alc_free(codec);
+ return err;
}
/*
@@ -4924,10 +6381,6 @@ static int patch_alc861(struct hda_codec *codec)
*
* In addition, an independent DAC
*/
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc861vd_loopbacks alc880_loopbacks
-#endif
-
static int alc861vd_parse_auto_config(struct hda_codec *codec)
{
static const hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
@@ -4936,24 +6389,41 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
}
enum {
- ALC660VD_FIX_ASUS_GPIO1
+ ALC660VD_FIX_ASUS_GPIO1,
+ ALC861VD_FIX_DALLAS,
};
-/* reset GPIO1 */
+/* exclude VREF80 */
+static void alc861vd_fixup_dallas(struct hda_codec *codec,
+ const struct alc_fixup *fix, int action)
+{
+ if (action == ALC_FIXUP_ACT_PRE_PROBE) {
+ snd_hda_override_pin_caps(codec, 0x18, 0x00001714);
+ snd_hda_override_pin_caps(codec, 0x19, 0x0000171c);
+ }
+}
+
static const struct alc_fixup alc861vd_fixups[] = {
[ALC660VD_FIX_ASUS_GPIO1] = {
.type = ALC_FIXUP_VERBS,
.v.verbs = (const struct hda_verb[]) {
+ /* reset GPIO1 */
{0x01, AC_VERB_SET_GPIO_MASK, 0x03},
{0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01},
{0x01, AC_VERB_SET_GPIO_DATA, 0x01},
{ }
}
},
+ [ALC861VD_FIX_DALLAS] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc861vd_fixup_dallas,
+ },
};
static const struct snd_pci_quirk alc861vd_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_FIX_DALLAS),
SND_PCI_QUIRK(0x1043, 0x1339, "ASUS A7-K", ALC660VD_FIX_ASUS_GPIO1),
+ SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba L30-149", ALC861VD_FIX_DALLAS),
{}
};
@@ -4965,14 +6435,10 @@ static const struct hda_verb alc660vd_eapd_verbs[] = {
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc861vd_quirks.c"
-#endif
-
static int patch_alc861vd(struct hda_codec *codec)
{
struct alc_spec *spec;
- int err, board_config;
+ int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -4982,78 +6448,37 @@ static int patch_alc861vd(struct hda_codec *codec)
spec->mixer_nid = 0x0b;
- board_config = alc_board_config(codec, ALC861VD_MODEL_LAST,
- alc861vd_models, alc861vd_cfg_tbl);
-
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- }
+ alc_pick_fixup(codec, NULL, alc861vd_fixup_tbl, alc861vd_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc861vd_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC861VD_3ST;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO)
- setup_preset(codec, &alc861vd_presets[board_config]);
+ /* automatic parse from the BIOS config */
+ err = alc861vd_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (codec->vendor_id == 0x10ec0660) {
/* always turn on EAPD */
add_verb(spec, alc660vd_eapd_verbs);
}
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
- }
-
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
if (!spec->no_analog) {
err = snd_hda_attach_beep_device(codec, 0x23);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
}
- spec->vmaster_nid = 0x02;
-
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc_eapd_shutup;
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc861vd_loopbacks;
-#endif
+
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
+
+ error:
+ alc_free(codec);
+ return err;
}
/*
@@ -5067,9 +6492,6 @@ static int patch_alc861vd(struct hda_codec *codec)
* In addition, an independent DAC for the multi-playback (not used in this
* driver yet).
*/
-#ifdef CONFIG_SND_HDA_POWER_SAVE
-#define alc662_loopbacks alc880_loopbacks
-#endif
/*
* BIOS auto configuration
@@ -5111,6 +6533,15 @@ enum {
ALC662_FIXUP_CZC_P10T,
ALC662_FIXUP_SKU_IGNORE,
ALC662_FIXUP_HP_RP5800,
+ ALC662_FIXUP_ASUS_MODE1,
+ ALC662_FIXUP_ASUS_MODE2,
+ ALC662_FIXUP_ASUS_MODE3,
+ ALC662_FIXUP_ASUS_MODE4,
+ ALC662_FIXUP_ASUS_MODE5,
+ ALC662_FIXUP_ASUS_MODE6,
+ ALC662_FIXUP_ASUS_MODE7,
+ ALC662_FIXUP_ASUS_MODE8,
+ ALC662_FIXUP_NO_JACK_DETECT,
};
static const struct alc_fixup alc662_fixups[] = {
@@ -5152,37 +6583,209 @@ static const struct alc_fixup alc662_fixups[] = {
.chained = true,
.chain_id = ALC662_FIXUP_SKU_IGNORE
},
+ [ALC662_FIXUP_ASUS_MODE1] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x18, 0x01a19c20 }, /* mic */
+ { 0x19, 0x99a3092f }, /* int-mic */
+ { 0x21, 0x0121401f }, /* HP out */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC662_FIXUP_SKU_IGNORE
+ },
+ [ALC662_FIXUP_ASUS_MODE2] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x18, 0x01a19820 }, /* mic */
+ { 0x19, 0x99a3092f }, /* int-mic */
+ { 0x1b, 0x0121401f }, /* HP out */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC662_FIXUP_SKU_IGNORE
+ },
+ [ALC662_FIXUP_ASUS_MODE3] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x15, 0x0121441f }, /* HP */
+ { 0x18, 0x01a19840 }, /* mic */
+ { 0x19, 0x99a3094f }, /* int-mic */
+ { 0x21, 0x01211420 }, /* HP2 */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC662_FIXUP_SKU_IGNORE
+ },
+ [ALC662_FIXUP_ASUS_MODE4] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x16, 0x99130111 }, /* speaker */
+ { 0x18, 0x01a19840 }, /* mic */
+ { 0x19, 0x99a3094f }, /* int-mic */
+ { 0x21, 0x0121441f }, /* HP */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC662_FIXUP_SKU_IGNORE
+ },
+ [ALC662_FIXUP_ASUS_MODE5] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x15, 0x0121441f }, /* HP */
+ { 0x16, 0x99130111 }, /* speaker */
+ { 0x18, 0x01a19840 }, /* mic */
+ { 0x19, 0x99a3094f }, /* int-mic */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC662_FIXUP_SKU_IGNORE
+ },
+ [ALC662_FIXUP_ASUS_MODE6] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x15, 0x01211420 }, /* HP2 */
+ { 0x18, 0x01a19840 }, /* mic */
+ { 0x19, 0x99a3094f }, /* int-mic */
+ { 0x1b, 0x0121441f }, /* HP */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC662_FIXUP_SKU_IGNORE
+ },
+ [ALC662_FIXUP_ASUS_MODE7] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x17, 0x99130111 }, /* speaker */
+ { 0x18, 0x01a19840 }, /* mic */
+ { 0x19, 0x99a3094f }, /* int-mic */
+ { 0x1b, 0x01214020 }, /* HP */
+ { 0x21, 0x0121401f }, /* HP */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC662_FIXUP_SKU_IGNORE
+ },
+ [ALC662_FIXUP_ASUS_MODE8] = {
+ .type = ALC_FIXUP_PINS,
+ .v.pins = (const struct alc_pincfg[]) {
+ { 0x14, 0x99130110 }, /* speaker */
+ { 0x12, 0x99a30970 }, /* int-mic */
+ { 0x15, 0x01214020 }, /* HP */
+ { 0x17, 0x99130111 }, /* speaker */
+ { 0x18, 0x01a19840 }, /* mic */
+ { 0x21, 0x0121401f }, /* HP */
+ { }
+ },
+ .chained = true,
+ .chain_id = ALC662_FIXUP_SKU_IGNORE
+ },
+ [ALC662_FIXUP_NO_JACK_DETECT] = {
+ .type = ALC_FIXUP_FUNC,
+ .v.func = alc_fixup_no_jack_detect,
+ },
};
static const struct snd_pci_quirk alc662_fixup_tbl[] = {
+ SND_PCI_QUIRK(0x1019, 0x9087, "ECS", ALC662_FIXUP_ASUS_MODE2),
SND_PCI_QUIRK(0x1025, 0x0308, "Acer Aspire 8942G", ALC662_FIXUP_ASPIRE),
SND_PCI_QUIRK(0x1025, 0x031c, "Gateway NV79", ALC662_FIXUP_SKU_IGNORE),
SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE),
SND_PCI_QUIRK(0x103c, 0x1632, "HP RP5800", ALC662_FIXUP_HP_RP5800),
+ SND_PCI_QUIRK(0x1043, 0x8469, "ASUS mobo", ALC662_FIXUP_NO_JACK_DETECT),
+ SND_PCI_QUIRK(0x105b, 0x0cd6, "Foxconn", ALC662_FIXUP_ASUS_MODE2),
SND_PCI_QUIRK(0x144d, 0xc051, "Samsung R720", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD),
SND_PCI_QUIRK(0x1b35, 0x2206, "CZC P10T", ALC662_FIXUP_CZC_P10T),
+
+#if 0
+ /* Below is a quirk table taken from the old code.
+ * Basically the device should work as is without the fixup table.
+ * If BIOS doesn't give a proper info, enable the corresponding
+ * fixup entry.
+ */
+ SND_PCI_QUIRK(0x1043, 0x1000, "ASUS N50Vm", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1092, "ASUS NB", ALC662_FIXUP_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x1173, "ASUS K73Jn", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x11c3, "ASUS M70V", ALC662_FIXUP_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x11d3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x11f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1203, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1303, "ASUS G60J", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1333, "ASUS G60Jx", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1339, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x13e3, "ASUS N71JA", ALC662_FIXUP_ASUS_MODE7),
+ SND_PCI_QUIRK(0x1043, 0x1463, "ASUS N71", ALC662_FIXUP_ASUS_MODE7),
+ SND_PCI_QUIRK(0x1043, 0x14d3, "ASUS G72", ALC662_FIXUP_ASUS_MODE8),
+ SND_PCI_QUIRK(0x1043, 0x1563, "ASUS N90", ALC662_FIXUP_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x15d3, "ASUS N50SF F50SF", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x16c3, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x16f3, "ASUS K40C K50C", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1733, "ASUS N81De", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1753, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1763, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
+ SND_PCI_QUIRK(0x1043, 0x1765, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
+ SND_PCI_QUIRK(0x1043, 0x1783, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1793, "ASUS F50GX", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x17b3, "ASUS F70SL", ALC662_FIXUP_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x17f3, "ASUS X58LE", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1813, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1823, "ASUS NB", ALC662_FIXUP_ASUS_MODE5),
+ SND_PCI_QUIRK(0x1043, 0x1833, "ASUS NB", ALC662_FIXUP_ASUS_MODE6),
+ SND_PCI_QUIRK(0x1043, 0x1843, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1853, "ASUS F50Z", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1864, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1876, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1893, "ASUS M50Vm", ALC662_FIXUP_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x1894, "ASUS X55", ALC662_FIXUP_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x18b3, "ASUS N80Vc", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x18c3, "ASUS VX5", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x18d3, "ASUS N81Te", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x18f3, "ASUS N505Tp", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1903, "ASUS F5GL", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1913, "ASUS NB", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1933, "ASUS F80Q", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x1943, "ASUS Vx3V", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1953, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1963, "ASUS X71C", ALC662_FIXUP_ASUS_MODE3),
+ SND_PCI_QUIRK(0x1043, 0x1983, "ASUS N5051A", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x1993, "ASUS N20", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS F7Z", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x19c3, "ASUS F5Z/F6x", ALC662_FIXUP_ASUS_MODE2),
+ SND_PCI_QUIRK(0x1043, 0x19e3, "ASUS NB", ALC662_FIXUP_ASUS_MODE1),
+ SND_PCI_QUIRK(0x1043, 0x19f3, "ASUS NB", ALC662_FIXUP_ASUS_MODE4),
+#endif
{}
};
static const struct alc_model_fixup alc662_fixup_models[] = {
{.id = ALC272_FIXUP_MARIO, .name = "mario"},
+ {.id = ALC662_FIXUP_ASUS_MODE1, .name = "asus-mode1"},
+ {.id = ALC662_FIXUP_ASUS_MODE2, .name = "asus-mode2"},
+ {.id = ALC662_FIXUP_ASUS_MODE3, .name = "asus-mode3"},
+ {.id = ALC662_FIXUP_ASUS_MODE4, .name = "asus-mode4"},
+ {.id = ALC662_FIXUP_ASUS_MODE5, .name = "asus-mode5"},
+ {.id = ALC662_FIXUP_ASUS_MODE6, .name = "asus-mode6"},
+ {.id = ALC662_FIXUP_ASUS_MODE7, .name = "asus-mode7"},
+ {.id = ALC662_FIXUP_ASUS_MODE8, .name = "asus-mode8"},
{}
};
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc662_quirks.c"
-#endif
-
static int patch_alc662(struct hda_codec *codec)
{
struct alc_spec *spec;
- int err, board_config;
- int coef;
+ int err = 0;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (!spec)
@@ -5192,66 +6795,36 @@ static int patch_alc662(struct hda_codec *codec)
spec->mixer_nid = 0x0b;
+ /* handle multiple HPs as is */
+ spec->parse_flags = HDA_PINCFG_NO_HP_FIXUP;
+
alc_auto_parse_customize_define(codec);
alc_fix_pll_init(codec, 0x20, 0x04, 15);
- coef = alc_read_coef_idx(codec, 0);
- if (coef == 0x8020 || coef == 0x8011)
- alc_codec_rename(codec, "ALC661");
- else if (coef & (1 << 14) &&
- codec->bus->pci->subsystem_vendor == 0x1025 &&
- spec->cdefine.platform_type == 1)
- alc_codec_rename(codec, "ALC272X");
- else if (coef == 0x4011)
- alc_codec_rename(codec, "ALC656");
-
- board_config = alc_board_config(codec, ALC662_MODEL_LAST,
- alc662_models, alc662_cfg_tbl);
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- alc_pick_fixup(codec, alc662_fixup_models,
- alc662_fixup_tbl, alc662_fixups);
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
- /* automatic parse from the BIOS config */
- err = alc662_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC662_3ST_2ch_DIG;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO)
- setup_preset(codec, &alc662_presets[board_config]);
+ err = alc_codec_rename_from_preset(codec);
+ if (err < 0)
+ goto error;
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
+ if ((alc_get_coef0(codec) & (1 << 14)) &&
+ codec->bus->pci->subsystem_vendor == 0x1025 &&
+ spec->cdefine.platform_type == 1) {
+ if (alc_codec_rename(codec, "ALC272X") < 0)
+ goto error;
}
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
+ alc_pick_fixup(codec, alc662_fixup_models,
+ alc662_fixup_tbl, alc662_fixups);
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PRE_PROBE);
+ /* automatic parse from the BIOS config */
+ err = alc662_parse_auto_config(codec);
+ if (err < 0)
+ goto error;
if (!spec->no_analog && has_cdefine_beep(codec)) {
err = snd_hda_attach_beep_device(codec, 0x1);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
+ if (err < 0)
+ goto error;
switch (codec->vendor_id) {
case 0x10ec0662:
set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT);
@@ -5266,49 +6839,17 @@ static int patch_alc662(struct hda_codec *codec)
break;
}
}
- spec->vmaster_nid = 0x02;
-
- alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
spec->shutup = alc_eapd_shutup;
- alc_init_jacks(codec);
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- if (!spec->loopback.amplist)
- spec->loopback.amplist = alc662_loopbacks;
-#endif
+ alc_apply_fixup(codec, ALC_FIXUP_ACT_PROBE);
return 0;
-}
-
-static int patch_alc888(struct hda_codec *codec)
-{
- if ((alc_read_coef_idx(codec, 0) & 0x00f0)==0x0030){
- kfree(codec->chip_name);
- if (codec->vendor_id == 0x10ec0887)
- codec->chip_name = kstrdup("ALC887-VD", GFP_KERNEL);
- else
- codec->chip_name = kstrdup("ALC888-VD", GFP_KERNEL);
- if (!codec->chip_name) {
- alc_free(codec);
- return -ENOMEM;
- }
- return patch_alc662(codec);
- }
- return patch_alc882(codec);
-}
-static int patch_alc899(struct hda_codec *codec)
-{
- if ((alc_read_coef_idx(codec, 0) & 0x2000) != 0x2000) {
- kfree(codec->chip_name);
- codec->chip_name = kstrdup("ALC898", GFP_KERNEL);
- }
- return patch_alc882(codec);
+ error:
+ alc_free(codec);
+ return err;
}
/*
@@ -5322,14 +6863,9 @@ static int alc680_parse_auto_config(struct hda_codec *codec)
/*
*/
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
-#include "alc680_quirks.c"
-#endif
-
static int patch_alc680(struct hda_codec *codec)
{
struct alc_spec *spec;
- int board_config;
int err;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
@@ -5340,53 +6876,14 @@ static int patch_alc680(struct hda_codec *codec)
/* ALC680 has no aa-loopback mixer */
- board_config = alc_board_config(codec, ALC680_MODEL_LAST,
- alc680_models, alc680_cfg_tbl);
-
- if (board_config < 0) {
- printk(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
- codec->chip_name);
- board_config = ALC_MODEL_AUTO;
- }
-
- if (board_config == ALC_MODEL_AUTO) {
- /* automatic parse from the BIOS config */
- err = alc680_parse_auto_config(codec);
- if (err < 0) {
- alc_free(codec);
- return err;
- }
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- else if (!err) {
- printk(KERN_INFO
- "hda_codec: Cannot set up configuration "
- "from BIOS. Using base mode...\n");
- board_config = ALC680_BASE;
- }
-#endif
- }
-
- if (board_config != ALC_MODEL_AUTO) {
- setup_preset(codec, &alc680_presets[board_config]);
-#ifdef CONFIG_SND_HDA_ENABLE_REALTEK_QUIRKS
- spec->stream_analog_capture = &alc680_pcm_analog_auto_capture;
-#endif
- }
-
- if (!spec->no_analog && !spec->adc_nids) {
- alc_auto_fill_adc_caps(codec);
- alc_rebuild_imux_for_auto_mic(codec);
- alc_remove_invalid_adc_nids(codec);
+ /* automatic parse from the BIOS config */
+ err = alc680_parse_auto_config(codec);
+ if (err < 0) {
+ alc_free(codec);
+ return err;
}
- if (!spec->no_analog && !spec->cap_mixer)
- set_capture_mixer(codec);
-
- spec->vmaster_nid = 0x02;
-
codec->patch_ops = alc_patch_ops;
- if (board_config == ALC_MODEL_AUTO)
- spec->init_hook = alc_auto_init_std;
return 0;
}
@@ -5414,6 +6911,8 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
.patch = patch_alc882 },
{ .id = 0x10ec0662, .rev = 0x100101, .name = "ALC662 rev1",
.patch = patch_alc662 },
+ { .id = 0x10ec0662, .rev = 0x100300, .name = "ALC662 rev3",
+ .patch = patch_alc662 },
{ .id = 0x10ec0663, .name = "ALC663", .patch = patch_alc662 },
{ .id = 0x10ec0665, .name = "ALC665", .patch = patch_alc662 },
{ .id = 0x10ec0670, .name = "ALC670", .patch = patch_alc662 },
@@ -5426,13 +6925,13 @@ static const struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0885, .rev = 0x100103, .name = "ALC889A",
.patch = patch_alc882 },
{ .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
- { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc888 },
+ { .id = 0x10ec0887, .name = "ALC887", .patch = patch_alc882 },
{ .id = 0x10ec0888, .rev = 0x100101, .name = "ALC1200",
.patch = patch_alc882 },
- { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc888 },
+ { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc882 },
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc882 },
{ .id = 0x10ec0892, .name = "ALC892", .patch = patch_alc662 },
- { .id = 0x10ec0899, .name = "ALC899", .patch = patch_alc899 },
+ { .id = 0x10ec0899, .name = "ALC898", .patch = patch_alc882 },
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 2f55f32876fa..6679a5095e55 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 5145b663ef6e..33a9946b492c 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -29,6 +29,7 @@
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/dmi.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/asoundef.h>
#include <sound/jack.h>
@@ -36,6 +37,7 @@
#include "hda_codec.h"
#include "hda_local.h"
#include "hda_beep.h"
+#include "hda_jack.h"
enum {
STAC_VREF_EVENT = 1,
@@ -94,9 +96,10 @@ enum {
STAC_92HD83XXX_REF,
STAC_92HD83XXX_PWR_REF,
STAC_DELL_S14,
- STAC_92HD83XXX_HP,
+ STAC_DELL_VOSTRO_3500,
STAC_92HD83XXX_HP_cNB11_INTQUAD,
STAC_HP_DV7_4000,
+ STAC_HP_ZEPHYR,
STAC_92HD83XXX_MODELS
};
@@ -174,13 +177,6 @@ enum {
STAC_9872_MODELS
};
-struct sigmatel_event {
- hda_nid_t nid;
- unsigned char type;
- unsigned char tag;
- int data;
-};
-
struct sigmatel_mic_route {
hda_nid_t pin;
signed char mux_idx;
@@ -213,6 +209,7 @@ struct sigmatel_spec {
unsigned int gpio_mute;
unsigned int gpio_led;
unsigned int gpio_led_polarity;
+ unsigned int vref_mute_led_nid; /* pin NID for mute-LED vref control */
unsigned int vref_led;
/* stream */
@@ -225,13 +222,9 @@ struct sigmatel_spec {
/* power management */
unsigned int num_pwrs;
- const unsigned int *pwr_mapping;
const hda_nid_t *pwr_nids;
const hda_nid_t *dac_list;
- /* events */
- struct snd_array events;
-
/* playback */
struct hda_input_mux *mono_mux;
unsigned int cur_mmux;
@@ -317,6 +310,8 @@ struct sigmatel_spec {
unsigned long auto_capvols[MAX_ADCS_NUM];
unsigned auto_dmic_cnt;
hda_nid_t auto_dmic_nids[MAX_DMICS_NUM];
+
+ struct hda_vmaster_mute_hook vmaster_mute;
};
static const hda_nid_t stac9200_adc_nids[1] = {
@@ -372,18 +367,15 @@ static const unsigned long stac92hd73xx_capvols[] = {
#define STAC92HD83_DAC_COUNT 3
-static const hda_nid_t stac92hd83xxx_pwr_nids[4] = {
- 0xa, 0xb, 0xd, 0xe,
+static const hda_nid_t stac92hd83xxx_pwr_nids[7] = {
+ 0x0a, 0x0b, 0x0c, 0xd, 0x0e,
+ 0x0f, 0x10
};
static const hda_nid_t stac92hd83xxx_slave_dig_outs[2] = {
0x1e, 0,
};
-static const unsigned int stac92hd83xxx_pwr_mapping[4] = {
- 0x03, 0x0c, 0x20, 0x40,
-};
-
static const hda_nid_t stac92hd83xxx_dmic_nids[] = {
0x11, 0x20,
};
@@ -673,7 +665,6 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
return 0;
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
static int stac_vrefout_set(struct hda_codec *codec,
hda_nid_t nid, unsigned int new_vref)
{
@@ -697,7 +688,6 @@ static int stac_vrefout_set(struct hda_codec *codec,
return 1;
}
-#endif
static unsigned int stac92xx_vref_set(struct hda_codec *codec,
hda_nid_t nid, unsigned int new_vref)
@@ -905,6 +895,13 @@ static const struct hda_verb stac92hd83xxx_core_init[] = {
{}
};
+static const struct hda_verb stac92hd83xxx_hp_zephyr_init[] = {
+ { 0x22, 0x785, 0x43 },
+ { 0x22, 0x782, 0xe0 },
+ { 0x22, 0x795, 0x00 },
+ {}
+};
+
static const struct hda_verb stac92hd71bxx_core_init[] = {
/* set master volume and direct control */
{ 0x28, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
@@ -1010,8 +1007,8 @@ static const struct hda_verb stac9205_core_init[] = {
}
static const struct snd_kcontrol_new stac9200_mixer[] = {
- HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xb, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0xb, 0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT),
{ } /* end */
@@ -1038,8 +1035,8 @@ static const struct snd_kcontrol_new stac92hd71bxx_loopback[] = {
};
static const struct snd_kcontrol_new stac925x_mixer[] = {
- HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT),
+ HDA_CODEC_VOLUME_MIN_MUTE("PCM Playback Volume", 0xe, 0, HDA_OUTPUT),
+ HDA_CODEC_MUTE("PCM Playback Switch", 0x0e, 0, HDA_OUTPUT),
{ } /* end */
};
@@ -1071,37 +1068,25 @@ static struct snd_kcontrol_new stac_smux_mixer = {
.put = stac92xx_smux_enum_put,
};
-static const char * const slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "Headphone Playback Volume",
- "Speaker Playback Volume",
+static const char * const slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side",
+ "Headphone", "Speaker", "IEC958",
NULL
};
-static const char * const slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "Headphone Playback Switch",
- "Speaker Playback Switch",
- "IEC958 Playback Switch",
- NULL
-};
+static void stac92xx_update_led_status(struct hda_codec *codec, int enabled);
+
+static void stac92xx_vmaster_hook(void *private_data, int val)
+{
+ stac92xx_update_led_status(private_data, val);
+}
static void stac92xx_free_kctls(struct hda_codec *codec);
-static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type);
static int stac92xx_build_controls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- hda_nid_t nid;
+ unsigned int vmaster_tlv[4];
int err;
int i;
@@ -1158,22 +1143,28 @@ static int stac92xx_build_controls(struct hda_codec *codec)
}
/* if we have no master control, let's create it */
- if (!snd_hda_find_mixer_ctl(codec, "Master Playback Volume")) {
- unsigned int vmaster_tlv[4];
- snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
- HDA_OUTPUT, vmaster_tlv);
- /* correct volume offset */
- vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
- /* minimum value is actually mute */
- vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
- err = snd_hda_add_vmaster(codec, "Master Playback Volume",
- vmaster_tlv, slave_vols);
- if (err < 0)
- return err;
- }
- if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
- err = snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, slave_sws);
+ snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
+ HDA_OUTPUT, vmaster_tlv);
+ /* correct volume offset */
+ vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset;
+ /* minimum value is actually mute */
+ vmaster_tlv[3] |= TLV_DB_SCALE_MUTE;
+ err = snd_hda_add_vmaster(codec, "Master Playback Volume",
+ vmaster_tlv, slave_pfxs,
+ "Playback Volume");
+ if (err < 0)
+ return err;
+
+ err = __snd_hda_add_vmaster(codec, "Master Playback Switch",
+ NULL, slave_pfxs,
+ "Playback Switch", true,
+ &spec->vmaster_mute.sw_kctl);
+ if (err < 0)
+ return err;
+
+ if (spec->gpio_led) {
+ spec->vmaster_mute.hook = stac92xx_vmaster_hook;
+ err = snd_hda_add_vmaster_hook(codec, &spec->vmaster_mute, true);
if (err < 0)
return err;
}
@@ -1187,31 +1178,9 @@ static int stac92xx_build_controls(struct hda_codec *codec)
stac92xx_free_kctls(codec); /* no longer needed */
- /* create jack input elements */
- if (spec->hp_detect) {
- for (i = 0; i < cfg->hp_outs; i++) {
- int type = SND_JACK_HEADPHONE;
- nid = cfg->hp_pins[i];
- /* jack detection */
- if (cfg->hp_outs == i)
- type |= SND_JACK_LINEOUT;
- err = stac92xx_add_jack(codec, nid, type);
- if (err < 0)
- return err;
- }
- }
- for (i = 0; i < cfg->line_outs; i++) {
- err = stac92xx_add_jack(codec, cfg->line_out_pins[i],
- SND_JACK_LINEOUT);
- if (err < 0)
- return err;
- }
- for (i = 0; i < cfg->num_inputs; i++) {
- nid = cfg->inputs[i].pin;
- err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE);
- if (err < 0)
- return err;
- }
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
return 0;
}
@@ -1632,7 +1601,7 @@ static const struct snd_pci_quirk stac92hd73xx_cfg_tbl[] = {
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02bd,
"Dell Studio 1557", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02fe,
- "Dell Studio XPS 1645", STAC_DELL_M6_BOTH),
+ "Dell Studio XPS 1645", STAC_DELL_M6_DMIC),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0413,
"Dell Studio 1558", STAC_DELL_M6_DMIC),
{} /* terminator */
@@ -1643,6 +1612,8 @@ static const struct snd_pci_quirk stac92hd73xx_codec_id_cfg_tbl[] = {
"Alienware M17x", STAC_ALIENWARE_M17X),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x043a,
"Alienware M17x", STAC_ALIENWARE_M17X),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x0490,
+ "Alienware M17x R3", STAC_DELL_EQ),
{} /* terminator */
};
@@ -1658,12 +1629,24 @@ static const unsigned int dell_s14_pin_configs[10] = {
0x40f000f0, 0x40f000f0,
};
+static const unsigned int dell_vostro_3500_pin_configs[10] = {
+ 0x02a11020, 0x0221101f, 0x400000f0, 0x90170110,
+ 0x400000f1, 0x400000f2, 0x400000f3, 0x90a60160,
+ 0x400000f4, 0x400000f5,
+};
+
static const unsigned int hp_dv7_4000_pin_configs[10] = {
0x03a12050, 0x0321201f, 0x40f000f0, 0x90170110,
0x40f000f0, 0x40f000f0, 0x90170110, 0xd5a30140,
0x40f000f0, 0x40f000f0,
};
+static const unsigned int hp_zephyr_pin_configs[10] = {
+ 0x01813050, 0x0421201f, 0x04a1205e, 0x96130310,
+ 0x96130310, 0x0101401f, 0x1111611f, 0xd5a30130,
+ 0, 0,
+};
+
static const unsigned int hp_cNB11_intquad_pin_configs[10] = {
0x40f000f0, 0x0221101f, 0x02a11020, 0x92170110,
0x40f000f0, 0x92170110, 0x40f000f0, 0xd5a30130,
@@ -1674,8 +1657,10 @@ static const unsigned int *stac92hd83xxx_brd_tbl[STAC_92HD83XXX_MODELS] = {
[STAC_92HD83XXX_REF] = ref92hd83xxx_pin_configs,
[STAC_92HD83XXX_PWR_REF] = ref92hd83xxx_pin_configs,
[STAC_DELL_S14] = dell_s14_pin_configs,
+ [STAC_DELL_VOSTRO_3500] = dell_vostro_3500_pin_configs,
[STAC_92HD83XXX_HP_cNB11_INTQUAD] = hp_cNB11_intquad_pin_configs,
[STAC_HP_DV7_4000] = hp_dv7_4000_pin_configs,
+ [STAC_HP_ZEPHYR] = hp_zephyr_pin_configs,
};
static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
@@ -1683,9 +1668,10 @@ static const char * const stac92hd83xxx_models[STAC_92HD83XXX_MODELS] = {
[STAC_92HD83XXX_REF] = "ref",
[STAC_92HD83XXX_PWR_REF] = "mic-ref",
[STAC_DELL_S14] = "dell-s14",
- [STAC_92HD83XXX_HP] = "hp",
+ [STAC_DELL_VOSTRO_3500] = "dell-vostro-3500",
[STAC_92HD83XXX_HP_cNB11_INTQUAD] = "hp_cNB11_intquad",
[STAC_HP_DV7_4000] = "hp-dv7-4000",
+ [STAC_HP_ZEPHYR] = "hp-zephyr",
};
static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
@@ -1696,8 +1682,8 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
"DFI LanParty", STAC_92HD83XXX_REF),
SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x02ba,
"unknown Dell", STAC_DELL_S14),
- SND_PCI_QUIRK_MASK(PCI_VENDOR_ID_HP, 0xff00, 0x3600,
- "HP", STAC_92HD83XXX_HP),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x1028,
+ "Dell Vostro 3500", STAC_DELL_VOSTRO_3500),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1656,
"HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x1657,
@@ -1738,6 +1724,14 @@ static const struct snd_pci_quirk stac92hd83xxx_cfg_tbl[] = {
"HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3593,
"HP", STAC_92HD83XXX_HP_cNB11_INTQUAD),
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561,
+ "HP", STAC_HP_ZEPHYR),
+ {} /* terminator */
+};
+
+static const struct snd_pci_quirk stac92hd83xxx_codec_id_cfg_tbl[] = {
+ SND_PCI_QUIRK(PCI_VENDOR_ID_HP, 0x3561,
+ "HP", STAC_HP_ZEPHYR),
{} /* terminator */
};
@@ -2864,7 +2858,8 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec,
}
if (control) {
- strcpy(name, hda_get_input_pin_label(codec, nid, 1));
+ snd_hda_get_pin_label(codec, nid, &spec->autocfg,
+ name, sizeof(name), NULL);
return stac92xx_add_control(codec->spec, control,
strcat(name, " Jack Mode"), nid);
}
@@ -2972,8 +2967,9 @@ static int check_all_dac_nids(struct sigmatel_spec *spec, hda_nid_t nid)
static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid)
{
struct sigmatel_spec *spec = codec->spec;
+ struct auto_pin_cfg *cfg = &spec->autocfg;
int j, conn_len;
- hda_nid_t conn[HDA_MAX_CONNECTIONS];
+ hda_nid_t conn[HDA_MAX_CONNECTIONS], fallback_dac;
unsigned int wcaps, wtype;
conn_len = snd_hda_get_connections(codec, nid, conn,
@@ -3001,10 +2997,21 @@ static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid)
return conn[j];
}
}
- /* if all DACs are already assigned, connect to the primary DAC */
+
+ /* if all DACs are already assigned, connect to the primary DAC,
+ unless we're assigning a secondary headphone */
+ fallback_dac = spec->multiout.dac_nids[0];
+ if (spec->multiout.hp_nid) {
+ for (j = 0; j < cfg->hp_outs; j++)
+ if (cfg->hp_pins[j] == nid) {
+ fallback_dac = spec->multiout.hp_nid;
+ break;
+ }
+ }
+
if (conn_len > 1) {
for (j = 0; j < conn_len; j++) {
- if (conn[j] == spec->multiout.dac_nids[0]) {
+ if (conn[j] == fallback_dac) {
snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_CONNECT_SEL, j);
break;
@@ -3530,7 +3537,7 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
for (i = 0; i < spec->num_dmics; i++) {
hda_nid_t nid;
int index, type_idx;
- const char *label;
+ char label[32];
nid = spec->dmic_nids[i];
if (get_wcaps_type(get_wcaps(codec, nid)) != AC_WID_PIN)
@@ -3543,7 +3550,8 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
if (index < 0)
continue;
- label = hda_get_input_pin_label(codec, nid, 1);
+ snd_hda_get_pin_label(codec, nid, &spec->autocfg,
+ label, sizeof(label), NULL);
snd_hda_add_imux_item(dimux, label, index, &type_idx);
if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1)
snd_hda_add_imux_item(imux, label, index, &type_idx);
@@ -3779,9 +3787,10 @@ static int is_dual_headphones(struct hda_codec *codec)
}
-static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out, hda_nid_t dig_in)
+static int stac92xx_parse_auto_config(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
+ hda_nid_t dig_out = 0, dig_in = 0;
int hp_swap = 0;
int i, err;
@@ -3964,6 +3973,22 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
if (spec->multiout.max_channels > 2)
spec->surr_switch = 1;
+ /* find digital out and in converters */
+ for (i = codec->start_nid; i < codec->start_nid + codec->num_nodes; i++) {
+ unsigned int wid_caps = get_wcaps(codec, i);
+ if (wid_caps & AC_WCAP_DIGITAL) {
+ switch (get_wcaps_type(wid_caps)) {
+ case AC_WID_AUD_OUT:
+ if (!dig_out)
+ dig_out = i;
+ break;
+ case AC_WID_AUD_IN:
+ if (!dig_in)
+ dig_in = i;
+ break;
+ }
+ }
+ }
if (spec->autocfg.dig_outs)
spec->multiout.dig_out_nid = dig_out;
if (dig_in && spec->autocfg.dig_in_pin)
@@ -4124,73 +4149,18 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
}
-static int stac92xx_add_jack(struct hda_codec *codec,
- hda_nid_t nid, int type)
-{
-#ifdef CONFIG_SND_HDA_INPUT_JACK
- int def_conf = snd_hda_codec_get_pincfg(codec, nid);
- int connectivity = get_defcfg_connect(def_conf);
- char name[32];
- int err;
-
- if (connectivity && connectivity != AC_JACK_PORT_FIXED)
- return 0;
-
- snprintf(name, sizeof(name), "%s at %s %s Jack",
- snd_hda_get_jack_type(def_conf),
- snd_hda_get_jack_connectivity(def_conf),
- snd_hda_get_jack_location(def_conf));
-
- err = snd_hda_input_jack_add(codec, nid, type, name);
- if (err < 0)
- return err;
-#endif /* CONFIG_SND_HDA_INPUT_JACK */
- return 0;
-}
-
-static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
+static int stac_add_event(struct hda_codec *codec, hda_nid_t nid,
unsigned char type, int data)
{
- struct sigmatel_event *event;
+ struct hda_jack_tbl *event;
- snd_array_init(&spec->events, sizeof(*event), 32);
- event = snd_array_new(&spec->events);
+ event = snd_hda_jack_tbl_new(codec, nid);
if (!event)
return -ENOMEM;
- event->nid = nid;
- event->type = type;
- event->tag = spec->events.used;
- event->data = data;
-
- return event->tag;
-}
-
-static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
- hda_nid_t nid)
-{
- struct sigmatel_spec *spec = codec->spec;
- struct sigmatel_event *event = spec->events.list;
- int i;
-
- for (i = 0; i < spec->events.used; i++, event++) {
- if (event->nid == nid)
- return event;
- }
- return NULL;
-}
-
-static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
- unsigned char tag)
-{
- struct sigmatel_spec *spec = codec->spec;
- struct sigmatel_event *event = spec->events.list;
- int i;
+ event->action = type;
+ event->private_data = data;
- for (i = 0; i < spec->events.used; i++, event++) {
- if (event->tag == tag)
- return event;
- }
- return NULL;
+ return 0;
}
/* check if given nid is a valid pin and no other events are assigned
@@ -4200,34 +4170,29 @@ static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
static int enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
unsigned int type)
{
- struct sigmatel_event *event;
- int tag;
+ struct hda_jack_tbl *event;
if (!is_jack_detectable(codec, nid))
return 0;
- event = stac_get_event(codec, nid);
- if (event) {
- if (event->type != type)
- return 0;
- tag = event->tag;
- } else {
- tag = stac_add_event(codec->spec, nid, type, 0);
- if (tag < 0)
- return 0;
- }
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | tag);
+ event = snd_hda_jack_tbl_new(codec, nid);
+ if (!event)
+ return -ENOMEM;
+ if (event->action && event->action != type)
+ return 0;
+ event->action = type;
+ snd_hda_jack_detect_enable(codec, nid, 0);
return 1;
}
-static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
+static int is_nid_out_jack_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
{
int i;
for (i = 0; i < cfg->hp_outs; i++)
if (cfg->hp_pins[i] == nid)
return 1; /* nid is a HP-Out */
-
+ for (i = 0; i < cfg->line_outs; i++)
+ if (cfg->line_out_pins[i] == nid)
+ return 1; /* nid is a line-Out */
return 0; /* nid is not a HP-Out */
};
@@ -4287,15 +4252,34 @@ static void stac_store_hints(struct hda_codec *codec)
spec->eapd_switch = val;
get_int_hint(codec, "gpio_led_polarity", &spec->gpio_led_polarity);
if (get_int_hint(codec, "gpio_led", &spec->gpio_led)) {
- if (spec->gpio_led <= 8) {
- spec->gpio_mask |= spec->gpio_led;
- spec->gpio_dir |= spec->gpio_led;
- if (spec->gpio_led_polarity)
- spec->gpio_data |= spec->gpio_led;
- }
+ spec->gpio_mask |= spec->gpio_led;
+ spec->gpio_dir |= spec->gpio_led;
+ if (spec->gpio_led_polarity)
+ spec->gpio_data |= spec->gpio_led;
}
}
+static void stac_issue_unsol_events(struct hda_codec *codec, int num_pins,
+ const hda_nid_t *pins)
+{
+ while (num_pins--)
+ stac_issue_unsol_event(codec, *pins++);
+}
+
+/* fake event to set up pins */
+static void stac_fake_hp_events(struct hda_codec *codec)
+{
+ struct sigmatel_spec *spec = codec->spec;
+
+ if (spec->autocfg.hp_outs)
+ stac_issue_unsol_events(codec, spec->autocfg.hp_outs,
+ spec->autocfg.hp_pins);
+ if (spec->autocfg.line_outs &&
+ spec->autocfg.line_out_pins[0] != spec->autocfg.hp_pins[0])
+ stac_issue_unsol_events(codec, spec->autocfg.line_outs,
+ spec->autocfg.line_out_pins);
+}
+
static int stac92xx_init(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
@@ -4346,10 +4330,7 @@ static int stac92xx_init(struct hda_codec *codec)
stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0],
AC_PINCTL_OUT_EN);
/* fake event to set up pins */
- if (cfg->hp_pins[0])
- stac_issue_unsol_event(codec, cfg->hp_pins[0]);
- else if (cfg->line_out_pins[0])
- stac_issue_unsol_event(codec, cfg->line_out_pins[0]);
+ stac_fake_hp_events(codec);
} else {
stac92xx_auto_init_multi_out(codec);
stac92xx_auto_init_hp_out(codec);
@@ -4410,12 +4391,14 @@ static int stac92xx_init(struct hda_codec *codec)
int pinctl, def_conf;
/* power on when no jack detection is available */
- if (!spec->hp_detect) {
+ /* or when the VREF is used for controlling LED */
+ if (!spec->hp_detect ||
+ spec->vref_mute_led_nid == nid) {
stac_toggle_power_map(codec, nid, 1);
continue;
}
- if (is_nid_hp_pin(cfg, nid))
+ if (is_nid_out_jack_pin(cfg, nid))
continue; /* already has an unsol event */
pinctl = snd_hda_codec_read(codec, nid, 0,
@@ -4437,13 +4420,18 @@ static int stac92xx_init(struct hda_codec *codec)
stac_toggle_power_map(codec, nid, 1);
continue;
}
- if (enable_pin_detect(codec, nid, STAC_PWR_EVENT))
+ if (enable_pin_detect(codec, nid, STAC_PWR_EVENT)) {
stac_issue_unsol_event(codec, nid);
+ continue;
+ }
+ /* none of the above, turn the port OFF */
+ stac_toggle_power_map(codec, nid, 0);
}
+ snd_hda_jack_report_sync(codec);
+
/* sync mute LED */
- if (spec->gpio_led)
- hda_call_check_power_status(codec, 0x01);
+ snd_hda_sync_vmaster_hook(&spec->vmaster_mute);
if (spec->dac_list)
stac92xx_power_down(codec);
return 0;
@@ -4497,8 +4485,6 @@ static void stac92xx_free(struct hda_codec *codec)
return;
stac92xx_shutup(codec);
- snd_hda_input_jack_free(codec);
- snd_array_free(&spec->events);
kfree(spec);
snd_hda_detach_beep_device(codec);
@@ -4663,7 +4649,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
unsigned int val = AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN;
if (no_hp_sensing(spec, i))
continue;
- if (presence)
+ if (1 /*presence*/)
stac92xx_set_pinctl(codec, cfg->hp_pins[i], val);
#if 0 /* FIXME */
/* Resetting the pinctl like below may lead to (a sort of) regressions
@@ -4694,11 +4680,7 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
if (idx >= spec->num_pwrs)
return;
- /* several codecs have two power down bits */
- if (spec->pwr_mapping)
- idx = spec->pwr_mapping[idx];
- else
- idx = 1 << idx;
+ idx = 1 << idx;
val = snd_hda_codec_read(codec, codec->afg, 0, 0x0fec, 0x0) & 0xff;
if (enable)
@@ -4766,26 +4748,13 @@ static void stac92xx_mic_detect(struct hda_codec *codec)
mic->mux_idx);
}
-static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
-{
- struct sigmatel_event *event = stac_get_event(codec, nid);
- if (!event)
- return;
- codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26);
-}
-
-static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
+static void handle_unsol_event(struct hda_codec *codec,
+ struct hda_jack_tbl *event)
{
struct sigmatel_spec *spec = codec->spec;
- struct sigmatel_event *event;
- int tag, data;
-
- tag = (res >> 26) & 0x7f;
- event = stac_get_event_from_tag(codec, tag);
- if (!event)
- return;
+ int data;
- switch (event->type) {
+ switch (event->action) {
case STAC_HP_EVENT:
case STAC_LO_EVENT:
stac92xx_hp_detect(codec);
@@ -4795,7 +4764,7 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
break;
}
- switch (event->type) {
+ switch (event->action) {
case STAC_HP_EVENT:
case STAC_LO_EVENT:
case STAC_MIC_EVENT:
@@ -4803,7 +4772,6 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
case STAC_PWR_EVENT:
if (spec->num_pwrs > 0)
stac92xx_pin_sense(codec, event->nid);
- snd_hda_input_jack_report(codec, event->nid);
switch (codec->subsystem_id) {
case 0x103c308f:
@@ -4828,11 +4796,33 @@ static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
AC_VERB_GET_GPIO_DATA, 0);
/* toggle VREF state based on GPIOx status */
snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
- !!(data & (1 << event->data)));
+ !!(data & (1 << event->private_data)));
break;
}
}
+static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid)
+{
+ struct hda_jack_tbl *event = snd_hda_jack_tbl_get(codec, nid);
+ if (!event)
+ return;
+ handle_unsol_event(codec, event);
+}
+
+static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
+{
+ struct hda_jack_tbl *event;
+ int tag;
+
+ tag = (res >> 26) & 0x7f;
+ event = snd_hda_jack_tbl_get_from_tag(codec, tag);
+ if (!event)
+ return;
+ event->jack_dirty = 1;
+ handle_unsol_event(codec, event);
+ snd_hda_jack_report_sync(codec);
+}
+
static int hp_blike_system(u32 subsystem_id);
static void set_hp_led_gpio(struct hda_codec *codec)
@@ -4871,7 +4861,7 @@ static void set_hp_led_gpio(struct hda_codec *codec)
* Need more information on whether it is true across the entire series.
* -- kunal
*/
-static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
+static int find_mute_led_cfg(struct hda_codec *codec, int default_polarity)
{
struct sigmatel_spec *spec = codec->spec;
const struct dmi_device *dev = NULL;
@@ -4882,8 +4872,14 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
if (sscanf(dev->name, "HP_Mute_LED_%d_%x",
&spec->gpio_led_polarity,
&spec->gpio_led) == 2) {
- if (spec->gpio_led < 4)
+ unsigned int max_gpio;
+ max_gpio = snd_hda_param_read(codec, codec->afg,
+ AC_PAR_GPIO_CAP);
+ max_gpio &= AC_GPIO_IO_COUNT;
+ if (spec->gpio_led < max_gpio)
spec->gpio_led = 1 << spec->gpio_led;
+ else
+ spec->vref_mute_led_nid = spec->gpio_led;
return 1;
}
if (sscanf(dev->name, "HP_Mute_LED_%d",
@@ -4891,13 +4887,28 @@ static int find_mute_led_gpio(struct hda_codec *codec, int default_polarity)
set_hp_led_gpio(codec);
return 1;
}
+ /* BIOS bug: unfilled OEM string */
+ if (strstr(dev->name, "HP_Mute_LED_P_G")) {
+ set_hp_led_gpio(codec);
+ switch (codec->subsystem_id) {
+ case 0x103c148a:
+ spec->gpio_led_polarity = 0;
+ break;
+ default:
+ spec->gpio_led_polarity = 1;
+ break;
+ }
+ return 1;
+ }
}
/*
* Fallback case - if we don't find the DMI strings,
- * we statically set the GPIO - if not a B-series system.
+ * we statically set the GPIO - if not a B-series system
+ * and default polarity is provided
*/
- if (!hp_blike_system(codec->subsystem_id)) {
+ if (!hp_blike_system(codec->subsystem_id) &&
+ (default_polarity == 0 || default_polarity == 1)) {
set_hp_led_gpio(codec);
spec->gpio_led_polarity = default_polarity;
return 1;
@@ -4984,19 +4995,11 @@ static void stac927x_proc_hook(struct snd_info_buffer *buffer,
#ifdef CONFIG_PM
static int stac92xx_resume(struct hda_codec *codec)
{
- struct sigmatel_spec *spec = codec->spec;
-
stac92xx_init(codec);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
/* fake event to set up pins again to override cached values */
- if (spec->hp_detect) {
- if (spec->autocfg.hp_pins[0])
- stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0]);
- else if (spec->autocfg.line_out_pins[0])
- stac_issue_unsol_event(codec,
- spec->autocfg.line_out_pins[0]);
- }
+ stac_fake_hp_events(codec);
return 0;
}
@@ -5006,35 +5009,17 @@ static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
return 0;
}
-#ifdef CONFIG_SND_HDA_POWER_SAVE
static int stac92xx_pre_resume(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
/* sync mute LED */
- if (spec->gpio_led) {
- if (spec->gpio_led <= 8) {
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data);
- } else {
- stac_vrefout_set(codec,
- spec->gpio_led, spec->vref_led);
- }
- }
- return 0;
-}
-
-static int stac92xx_post_suspend(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
- if (spec->gpio_led > 8) {
- /* with vref-out pin used for mute led control
- * codec AFG is prevented from D3 state, but on
- * system suspend it can (and should) be used
- */
- snd_hda_codec_read(codec, codec->afg, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- }
+ if (spec->vref_mute_led_nid)
+ stac_vrefout_set(codec, spec->vref_mute_led_nid,
+ spec->vref_led);
+ else if (spec->gpio_led)
+ stac_gpio_set(codec, spec->gpio_mask,
+ spec->gpio_dir, spec->gpio_data);
return 0;
}
@@ -5045,7 +5030,7 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
struct sigmatel_spec *spec = codec->spec;
if (power_state == AC_PWRST_D3) {
- if (spec->gpio_led > 8) {
+ if (spec->vref_mute_led_nid) {
/* with vref-out pin used for mute led control
* codec AFG is prevented from D3 state
*/
@@ -5058,81 +5043,40 @@ static void stac92xx_set_power_state(struct hda_codec *codec, hda_nid_t fg,
afg_power_state);
snd_hda_codec_set_power_to_all(codec, fg, power_state, true);
}
+#else
+#define stac92xx_suspend NULL
+#define stac92xx_resume NULL
+#define stac92xx_pre_resume NULL
+#define stac92xx_set_power_state NULL
+#endif /* CONFIG_PM */
-/*
- * For this feature CONFIG_SND_HDA_POWER_SAVE is needed
- * as mute LED state is updated in check_power_status hook
- */
-static int stac92xx_update_led_status(struct hda_codec *codec)
+/* update mute-LED accoring to the master switch */
+static void stac92xx_update_led_status(struct hda_codec *codec, int enabled)
{
struct sigmatel_spec *spec = codec->spec;
- int i, num_ext_dacs, muted = 1;
- unsigned int muted_lvl, notmtd_lvl;
- hda_nid_t nid;
+ int muted = !enabled;
if (!spec->gpio_led)
- return 0;
+ return;
+
+ /* LED state is inverted on these systems */
+ if (spec->gpio_led_polarity)
+ muted = !muted;
- for (i = 0; i < spec->multiout.num_dacs; i++) {
- nid = spec->multiout.dac_nids[i];
- if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)) {
- muted = 0; /* something heard */
- break;
- }
- }
- if (muted && spec->multiout.hp_nid)
- if (!(snd_hda_codec_amp_read(codec,
- spec->multiout.hp_nid, 0, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)) {
- muted = 0; /* HP is not muted */
- }
- num_ext_dacs = ARRAY_SIZE(spec->multiout.extra_out_nid);
- for (i = 0; muted && i < num_ext_dacs; i++) {
- nid = spec->multiout.extra_out_nid[i];
- if (nid == 0)
- break;
- if (!(snd_hda_codec_amp_read(codec, nid, 0, HDA_OUTPUT, 0) &
- HDA_AMP_MUTE)) {
- muted = 0; /* extra output is not muted */
- }
- }
/*polarity defines *not* muted state level*/
- if (spec->gpio_led <= 8) {
+ if (!spec->vref_mute_led_nid) {
if (muted)
spec->gpio_data &= ~spec->gpio_led; /* orange */
else
spec->gpio_data |= spec->gpio_led; /* white */
-
- if (!spec->gpio_led_polarity) {
- /* LED state is inverted on these systems */
- spec->gpio_data ^= spec->gpio_led;
- }
stac_gpio_set(codec, spec->gpio_mask,
spec->gpio_dir, spec->gpio_data);
} else {
- notmtd_lvl = spec->gpio_led_polarity ?
- AC_PINCTL_VREF_HIZ : AC_PINCTL_VREF_GRD;
- muted_lvl = spec->gpio_led_polarity ?
- AC_PINCTL_VREF_GRD : AC_PINCTL_VREF_HIZ;
- spec->vref_led = muted ? muted_lvl : notmtd_lvl;
- stac_vrefout_set(codec, spec->gpio_led, spec->vref_led);
+ spec->vref_led = muted ? AC_PINCTL_VREF_50 : AC_PINCTL_VREF_GRD;
+ stac_vrefout_set(codec, spec->vref_mute_led_nid,
+ spec->vref_led);
}
- return 0;
-}
-
-/*
- * use power check for controlling mute led of HP notebooks
- */
-static int stac92xx_check_power_status(struct hda_codec *codec,
- hda_nid_t nid)
-{
- stac92xx_update_led_status(codec);
-
- return 0;
}
-#endif /* CONFIG_SND_HDA_POWER_SAVE */
-#endif /* CONFIG_PM */
static const struct hda_codec_ops stac92xx_patch_ops = {
.build_controls = stac92xx_build_controls,
@@ -5275,7 +5219,7 @@ static int patch_stac925x(struct hda_codec *codec)
spec->capvols = stac925x_capvols;
spec->capsws = stac925x_capsws;
- err = stac92xx_parse_auto_config(codec, 0x8, 0x7);
+ err = stac92xx_parse_auto_config(codec);
if (!err) {
if (spec->board_config < 0) {
printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -5416,7 +5360,7 @@ again:
spec->num_pwrs = ARRAY_SIZE(stac92hd73xx_pwr_nids);
spec->pwr_nids = stac92hd73xx_pwr_nids;
- err = stac92xx_parse_auto_config(codec, 0x25, 0x27);
+ err = stac92xx_parse_auto_config(codec);
if (!err) {
if (spec->board_config < 0) {
@@ -5585,9 +5529,7 @@ static void stac92hd8x_fill_auto_spec(struct hda_codec *codec)
static int patch_stac92hd83xxx(struct hda_codec *codec)
{
struct sigmatel_spec *spec;
- hda_nid_t conn[STAC92HD83_DAC_COUNT + 1];
int err;
- int num_dacs;
spec = kzalloc(sizeof(*spec), GFP_KERNEL);
if (spec == NULL)
@@ -5598,9 +5540,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e);
}
- /* reset pin power-down; Windows may leave these bits after reboot */
- snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7EC, 0);
- snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0);
codec->no_trigger_sense = 1;
codec->spec = spec;
@@ -5610,7 +5549,6 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs;
spec->digbeep_nid = 0x21;
spec->pwr_nids = stac92hd83xxx_pwr_nids;
- spec->pwr_mapping = stac92hd83xxx_pwr_mapping;
spec->num_pwrs = ARRAY_SIZE(stac92hd83xxx_pwr_nids);
spec->multiout.dac_nids = spec->dac_nids;
spec->init = stac92hd83xxx_core_init;
@@ -5619,6 +5557,12 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
STAC_92HD83XXX_MODELS,
stac92hd83xxx_models,
stac92hd83xxx_cfg_tbl);
+ /* check codec subsystem id if not found */
+ if (spec->board_config < 0)
+ spec->board_config =
+ snd_hda_check_board_codec_sid_config(codec,
+ STAC_92HD83XXX_MODELS, stac92hd83xxx_models,
+ stac92hd83xxx_codec_id_cfg_tbl);
again:
if (spec->board_config < 0)
snd_printdd(KERN_INFO "hda_codec: %s: BIOS auto-probing.\n",
@@ -5627,52 +5571,34 @@ again:
stac92xx_set_config_regs(codec,
stac92hd83xxx_brd_tbl[spec->board_config]);
- switch (codec->vendor_id) {
- case 0x111d76d1:
- case 0x111d76d9:
- case 0x111d76e5:
- case 0x111d7666:
- case 0x111d7667:
- case 0x111d7668:
- case 0x111d7669:
- case 0x111d76e3:
- case 0x111d7604:
- case 0x111d76d4:
- case 0x111d7605:
- case 0x111d76d5:
- case 0x111d76e7:
- if (spec->board_config == STAC_92HD83XXX_PWR_REF)
- break;
- spec->num_pwrs = 0;
+ codec->patch_ops = stac92xx_patch_ops;
+
+ switch (spec->board_config) {
+ case STAC_HP_ZEPHYR:
+ spec->init = stac92hd83xxx_hp_zephyr_init;
break;
}
- codec->patch_ops = stac92xx_patch_ops;
-
- if (find_mute_led_gpio(codec, 0))
+ if (find_mute_led_cfg(codec, -1/*no default cfg*/))
snd_printd("mute LED gpio %d polarity %d\n",
spec->gpio_led,
spec->gpio_led_polarity);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec->gpio_led) {
- if (spec->gpio_led <= 8) {
+ if (!spec->vref_mute_led_nid) {
spec->gpio_mask |= spec->gpio_led;
spec->gpio_dir |= spec->gpio_led;
spec->gpio_data |= spec->gpio_led;
} else {
codec->patch_ops.set_power_state =
stac92xx_set_power_state;
- codec->patch_ops.post_suspend =
- stac92xx_post_suspend;
}
+#ifdef CONFIG_PM
codec->patch_ops.pre_resume = stac92xx_pre_resume;
- codec->patch_ops.check_power_status =
- stac92xx_check_power_status;
+#endif
}
-#endif
- err = stac92xx_parse_auto_config(codec, 0x1d, 0);
+ err = stac92xx_parse_auto_config(codec);
if (!err) {
if (spec->board_config < 0) {
printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -5688,22 +5614,6 @@ again:
return err;
}
- /* docking output support */
- num_dacs = snd_hda_get_connections(codec, 0xF,
- conn, STAC92HD83_DAC_COUNT + 1) - 1;
- /* skip non-DAC connections */
- while (num_dacs >= 0 &&
- (get_wcaps_type(get_wcaps(codec, conn[num_dacs]))
- != AC_WID_AUD_OUT))
- num_dacs--;
- /* set port E and F to select the last DAC */
- if (num_dacs >= 0) {
- snd_hda_codec_write_cache(codec, 0xE, 0,
- AC_VERB_SET_CONNECT_SEL, num_dacs);
- snd_hda_codec_write_cache(codec, 0xF, 0,
- AC_VERB_SET_CONNECT_SEL, num_dacs);
- }
-
codec->proc_widget_hook = stac92hd_proc_hook;
return 0;
@@ -5855,15 +5765,13 @@ again:
switch (spec->board_config) {
case STAC_HP_M4:
/* Enable VREF power saving on GPIO1 detect */
- err = stac_add_event(spec, codec->afg,
+ err = stac_add_event(codec, codec->afg,
STAC_VREF_EVENT, 0x02);
if (err < 0)
return err;
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
- snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | err);
+ snd_hda_jack_detect_enable(codec, codec->afg, 0);
spec->gpio_mask |= 0x02;
break;
}
@@ -5871,8 +5779,6 @@ again:
(codec->revision_id & 0xf) == 1)
spec->stream_delay = 40; /* 40 milliseconds */
- /* no output amps */
- spec->num_pwrs = 0;
/* disable VSW */
spec->init = stac92hd71bxx_core_init;
unmute_init++;
@@ -5887,8 +5793,6 @@ again:
if ((codec->revision_id & 0xf) == 1)
spec->stream_delay = 40; /* 40 milliseconds */
- /* no output amps */
- spec->num_pwrs = 0;
/* fallthru */
default:
spec->init = stac92hd71bxx_core_init;
@@ -5984,32 +5888,28 @@ again:
}
}
- if (find_mute_led_gpio(codec, 1))
+ if (find_mute_led_cfg(codec, 1))
snd_printd("mute LED gpio %d polarity %d\n",
spec->gpio_led,
spec->gpio_led_polarity);
-#ifdef CONFIG_SND_HDA_POWER_SAVE
if (spec->gpio_led) {
- if (spec->gpio_led <= 8) {
+ if (!spec->vref_mute_led_nid) {
spec->gpio_mask |= spec->gpio_led;
spec->gpio_dir |= spec->gpio_led;
spec->gpio_data |= spec->gpio_led;
} else {
codec->patch_ops.set_power_state =
stac92xx_set_power_state;
- codec->patch_ops.post_suspend =
- stac92xx_post_suspend;
}
+#ifdef CONFIG_PM
codec->patch_ops.pre_resume = stac92xx_pre_resume;
- codec->patch_ops.check_power_status =
- stac92xx_check_power_status;
+#endif
}
-#endif
spec->multiout.dac_nids = spec->dac_nids;
- err = stac92xx_parse_auto_config(codec, 0x21, 0);
+ err = stac92xx_parse_auto_config(codec);
if (!err) {
if (spec->board_config < 0) {
printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -6118,7 +6018,7 @@ static int patch_stac922x(struct hda_codec *codec)
spec->multiout.dac_nids = spec->dac_nids;
- err = stac92xx_parse_auto_config(codec, 0x08, 0x09);
+ err = stac92xx_parse_auto_config(codec);
if (!err) {
if (spec->board_config < 0) {
printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -6243,7 +6143,7 @@ static int patch_stac927x(struct hda_codec *codec)
spec->aloopback_shift = 0;
spec->eapd_switch = 1;
- err = stac92xx_parse_auto_config(codec, 0x1e, 0x20);
+ err = stac92xx_parse_auto_config(codec);
if (!err) {
if (spec->board_config < 0) {
printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -6340,14 +6240,12 @@ static int patch_stac9205(struct hda_codec *codec)
snd_hda_codec_set_pincfg(codec, 0x20, 0x1c410030);
/* Enable unsol response for GPIO4/Dock HP connection */
- err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
+ err = stac_add_event(codec, codec->afg, STAC_VREF_EVENT, 0x01);
if (err < 0)
return err;
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
- snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | err);
+ snd_hda_jack_detect_enable(codec, codec->afg, 0);
spec->gpio_dir = 0x0b;
spec->eapd_mask = 0x01;
@@ -6368,7 +6266,7 @@ static int patch_stac9205(struct hda_codec *codec)
break;
}
- err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
+ err = stac92xx_parse_auto_config(codec);
if (!err) {
if (spec->board_config < 0) {
printk(KERN_WARNING "hda_codec: No auto-config is "
@@ -6473,7 +6371,7 @@ static int patch_stac9872(struct hda_codec *codec)
spec->capvols = stac9872_capvols;
spec->capsws = stac9872_capsws;
- err = stac92xx_parse_auto_config(codec, 0x10, 0x12);
+ err = stac92xx_parse_auto_config(codec);
if (err < 0) {
stac92xx_free(codec);
return -EINVAL;
@@ -6573,10 +6471,23 @@ static const struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx },
{ .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx },
{ .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx },
+ { .id = 0x111d76df, .name = "92HD93BXX", .patch = patch_stac92hd83xxx},
{ .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx},
{ .id = 0x111d76e3, .name = "92HD98BXX", .patch = patch_stac92hd83xxx},
{ .id = 0x111d76e5, .name = "92HD99BXX", .patch = patch_stac92hd83xxx},
{ .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76e8, .name = "92HD66B1X5", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76e9, .name = "92HD66B2X5", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76ea, .name = "92HD66B3X5", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76eb, .name = "92HD66C1X5", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76ec, .name = "92HD66C2X5", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76ed, .name = "92HD66C3X5", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76ee, .name = "92HD66B1X3", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76ef, .name = "92HD66B2X3", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76f0, .name = "92HD66B3X3", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76f1, .name = "92HD66C1X3", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76f2, .name = "92HD66C2X3", .patch = patch_stac92hd83xxx},
+ { .id = 0x111d76f3, .name = "92HD66C3/65", .patch = patch_stac92hd83xxx},
{} /* terminator */
};
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 4ebfbd874c9a..06214fdc9486 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -49,10 +49,12 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/asoundef.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_jack.h"
/* Pin Widget NID */
#define VT1708_HP_PIN_NID 0x20
@@ -197,6 +199,9 @@ struct via_spec {
unsigned int no_pin_power_ctl;
enum VIA_HDA_CODEC codec_type;
+ /* analog low-power control */
+ bool alc_mode;
+
/* smart51 setup */
unsigned int smart51_nums;
hda_nid_t smart51_pins[2];
@@ -207,6 +212,7 @@ struct via_spec {
/* work to check hp jack state */
struct hda_codec *codec;
struct delayed_work vt1708_hp_work;
+ int hp_work_active;
int vt1708_jack_detect;
int vt1708_hp_present;
@@ -304,27 +310,35 @@ enum {
static void analog_low_current_mode(struct hda_codec *codec);
static bool is_aa_path_mute(struct hda_codec *codec);
-static void vt1708_start_hp_work(struct via_spec *spec)
+#define hp_detect_with_aa(codec) \
+ (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1 && \
+ !is_aa_path_mute(codec))
+
+static void vt1708_stop_hp_work(struct via_spec *spec)
{
if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
return;
- snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
- !spec->vt1708_jack_detect);
- if (!delayed_work_pending(&spec->vt1708_hp_work))
- schedule_delayed_work(&spec->vt1708_hp_work,
- msecs_to_jiffies(100));
+ if (spec->hp_work_active) {
+ snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 1);
+ cancel_delayed_work_sync(&spec->vt1708_hp_work);
+ spec->hp_work_active = 0;
+ }
}
-static void vt1708_stop_hp_work(struct via_spec *spec)
+static void vt1708_update_hp_work(struct via_spec *spec)
{
if (spec->codec_type != VT1708 || spec->autocfg.hp_pins[0] == 0)
return;
- if (snd_hda_get_bool_hint(spec->codec, "analog_loopback_hp_detect") == 1
- && !is_aa_path_mute(spec->codec))
- return;
- snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81,
- !spec->vt1708_jack_detect);
- cancel_delayed_work_sync(&spec->vt1708_hp_work);
+ if (spec->vt1708_jack_detect &&
+ (spec->active_streams || hp_detect_with_aa(spec->codec))) {
+ if (!spec->hp_work_active) {
+ snd_hda_codec_write(spec->codec, 0x1, 0, 0xf81, 0);
+ schedule_delayed_work(&spec->vt1708_hp_work,
+ msecs_to_jiffies(100));
+ spec->hp_work_active = 1;
+ }
+ } else if (!hp_detect_with_aa(spec->codec))
+ vt1708_stop_hp_work(spec);
}
static void set_widgets_power_state(struct hda_codec *codec)
@@ -342,12 +356,7 @@ static int analog_input_switch_put(struct snd_kcontrol *kcontrol,
set_widgets_power_state(codec);
analog_low_current_mode(snd_kcontrol_chip(kcontrol));
- if (snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") == 1) {
- if (is_aa_path_mute(codec))
- vt1708_start_hp_work(codec->spec);
- else
- vt1708_stop_hp_work(codec->spec);
- }
+ vt1708_update_hp_work(codec->spec);
return change;
}
@@ -541,7 +550,10 @@ static void via_auto_init_output(struct hda_codec *codec,
pin = path->path[path->depth - 1];
init_output_pin(codec, pin, pin_type);
- caps = query_amp_caps(codec, pin, HDA_OUTPUT);
+ if (get_wcaps(codec, pin) & AC_WCAP_OUT_AMP)
+ caps = query_amp_caps(codec, pin, HDA_OUTPUT);
+ else
+ caps = 0;
if (caps & AC_AMPCAP_MUTE) {
unsigned int val;
val = (caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT;
@@ -636,6 +648,10 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
/* init ADCs */
for (i = 0; i < spec->num_adc_nids; i++) {
+ hda_nid_t nid = spec->adc_nids[i];
+ if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP) ||
+ !(query_amp_caps(codec, nid, HDA_INPUT) & AC_AMPCAP_MUTE))
+ continue;
snd_hda_codec_write(codec, spec->adc_nids[i], 0,
AC_VERB_SET_AMP_GAIN_MUTE,
AMP_IN_UNMUTE(0));
@@ -657,6 +673,9 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
/* init input-src */
for (i = 0; i < spec->num_adc_nids; i++) {
int adc_idx = spec->inputs[spec->cur_mux[i]].adc_idx;
+ /* secondary ADCs must have the unique MUX */
+ if (i > 0 && !spec->mux_nids[i])
+ break;
if (spec->mux_nids[adc_idx]) {
int mux_idx = spec->inputs[spec->cur_mux[i]].mux_idx;
snd_hda_codec_write(codec, spec->mux_nids[adc_idx], 0,
@@ -681,6 +700,15 @@ static void via_auto_init_analog_input(struct hda_codec *codec)
}
}
+static void update_power_state(struct hda_codec *codec, hda_nid_t nid,
+ unsigned int parm)
+{
+ if (snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_POWER_STATE, 0) == parm)
+ return;
+ snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+}
+
static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
unsigned int *affected_parm)
{
@@ -703,7 +731,7 @@ static void set_pin_power_state(struct hda_codec *codec, hda_nid_t nid,
} else
parm = AC_PWRST_D3;
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, nid, parm);
}
static int via_pin_power_ctl_info(struct snd_kcontrol *kcontrol,
@@ -743,6 +771,7 @@ static int via_pin_power_ctl_put(struct snd_kcontrol *kcontrol,
return 0;
spec->no_pin_power_ctl = val;
set_widgets_power_state(codec);
+ analog_low_current_mode(codec);
return 1;
}
@@ -1030,13 +1059,19 @@ static bool is_aa_path_mute(struct hda_codec *codec)
}
/* enter/exit analog low-current mode */
-static void analog_low_current_mode(struct hda_codec *codec)
+static void __analog_low_current_mode(struct hda_codec *codec, bool force)
{
struct via_spec *spec = codec->spec;
bool enable;
unsigned int verb, parm;
- enable = is_aa_path_mute(codec) && (spec->opened_streams != 0);
+ if (spec->no_pin_power_ctl)
+ enable = false;
+ else
+ enable = is_aa_path_mute(codec) && !spec->opened_streams;
+ if (enable == spec->alc_mode && !force)
+ return;
+ spec->alc_mode = enable;
/* decide low current mode's verb & parameter */
switch (spec->codec_type) {
@@ -1068,6 +1103,11 @@ static void analog_low_current_mode(struct hda_codec *codec)
snd_hda_codec_write(codec, codec->afg, 0, verb, parm);
}
+static void analog_low_current_mode(struct hda_codec *codec)
+{
+ return __analog_low_current_mode(codec, false);
+}
+
/*
* generic initialization of ADC, input mixers and output mixers
*/
@@ -1153,7 +1193,7 @@ static int via_playback_multi_pcm_prepare(struct hda_pcm_stream *hinfo,
spec->cur_dac_stream_tag = stream_tag;
spec->cur_dac_format = format;
mutex_unlock(&spec->config_mutex);
- vt1708_start_hp_work(spec);
+ vt1708_update_hp_work(spec);
return 0;
}
@@ -1173,7 +1213,7 @@ static int via_playback_hp_pcm_prepare(struct hda_pcm_stream *hinfo,
spec->cur_hp_stream_tag = stream_tag;
spec->cur_hp_format = format;
mutex_unlock(&spec->config_mutex);
- vt1708_start_hp_work(spec);
+ vt1708_update_hp_work(spec);
return 0;
}
@@ -1187,7 +1227,7 @@ static int via_playback_multi_pcm_cleanup(struct hda_pcm_stream *hinfo,
snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
spec->active_streams &= ~STREAM_MULTI_OUT;
mutex_unlock(&spec->config_mutex);
- vt1708_stop_hp_work(spec);
+ vt1708_update_hp_work(spec);
return 0;
}
@@ -1202,7 +1242,7 @@ static int via_playback_hp_pcm_cleanup(struct hda_pcm_stream *hinfo,
snd_hda_codec_setup_stream(codec, spec->hp_dac_nid, 0, 0, 0);
spec->active_streams &= ~STREAM_INDEP_HP;
mutex_unlock(&spec->config_mutex);
- vt1708_stop_hp_work(spec);
+ vt1708_update_hp_work(spec);
return 0;
}
@@ -1412,25 +1452,9 @@ static const struct hda_pcm_stream via_pcm_digital_capture = {
/*
* slave controls for virtual master
*/
-static const char * const via_slave_vols[] = {
- "Front Playback Volume",
- "Surround Playback Volume",
- "Center Playback Volume",
- "LFE Playback Volume",
- "Side Playback Volume",
- "Headphone Playback Volume",
- "Speaker Playback Volume",
- NULL,
-};
-
-static const char * const via_slave_sws[] = {
- "Front Playback Switch",
- "Surround Playback Switch",
- "Center Playback Switch",
- "LFE Playback Switch",
- "Side Playback Switch",
- "Headphone Playback Switch",
- "Speaker Playback Switch",
+static const char * const via_slave_pfxs[] = {
+ "Front", "Surround", "Center", "LFE", "Side",
+ "Headphone", "Speaker",
NULL,
};
@@ -1440,6 +1464,7 @@ static int via_build_controls(struct hda_codec *codec)
struct snd_kcontrol *kctl;
int err, i;
+ spec->no_pin_power_ctl = 1;
if (spec->set_widgets_power_state)
if (!via_clone_control(spec, &via_pin_power_ctl_enum))
return -ENOMEM;
@@ -1474,13 +1499,15 @@ static int via_build_controls(struct hda_codec *codec)
snd_hda_set_vmaster_tlv(codec, spec->multiout.dac_nids[0],
HDA_OUTPUT, vmaster_tlv);
err = snd_hda_add_vmaster(codec, "Master Playback Volume",
- vmaster_tlv, via_slave_vols);
+ vmaster_tlv, via_slave_pfxs,
+ "Playback Volume");
if (err < 0)
return err;
}
if (!snd_hda_find_mixer_ctl(codec, "Master Playback Switch")) {
err = snd_hda_add_vmaster(codec, "Master Playback Switch",
- NULL, via_slave_sws);
+ NULL, via_slave_pfxs,
+ "Playback Switch");
if (err < 0)
return err;
}
@@ -1488,16 +1515,19 @@ static int via_build_controls(struct hda_codec *codec)
/* assign Capture Source enums to NID */
kctl = snd_hda_find_mixer_ctl(codec, "Input Source");
for (i = 0; kctl && i < kctl->count; i++) {
+ if (!spec->mux_nids[i])
+ continue;
err = snd_hda_add_nid(codec, kctl, i, spec->mux_nids[i]);
if (err < 0)
return err;
}
- /* init power states */
- set_widgets_power_state(codec);
- analog_low_current_mode(codec);
-
via_free_kctls(codec); /* no longer needed */
+
+ err = snd_hda_jack_add_kctls(codec, &spec->autocfg);
+ if (err < 0)
+ return err;
+
return 0;
}
@@ -1506,39 +1536,49 @@ static int via_build_pcms(struct hda_codec *codec)
struct via_spec *spec = codec->spec;
struct hda_pcm *info = spec->pcm_rec;
- codec->num_pcms = 1;
+ codec->num_pcms = 0;
codec->pcm_info = info;
- snprintf(spec->stream_name_analog, sizeof(spec->stream_name_analog),
- "%s Analog", codec->chip_name);
- info->name = spec->stream_name_analog;
+ if (spec->multiout.num_dacs || spec->num_adc_nids) {
+ snprintf(spec->stream_name_analog,
+ sizeof(spec->stream_name_analog),
+ "%s Analog", codec->chip_name);
+ info->name = spec->stream_name_analog;
- if (!spec->stream_analog_playback)
- spec->stream_analog_playback = &via_pcm_analog_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
- *spec->stream_analog_playback;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
- spec->multiout.dac_nids[0];
- info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
- spec->multiout.max_channels;
+ if (spec->multiout.num_dacs) {
+ if (!spec->stream_analog_playback)
+ spec->stream_analog_playback =
+ &via_pcm_analog_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
+ *spec->stream_analog_playback;
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
+ spec->multiout.dac_nids[0];
+ info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
+ spec->multiout.max_channels;
+ }
- if (!spec->stream_analog_capture) {
- if (spec->dyn_adc_switch)
- spec->stream_analog_capture =
- &via_pcm_dyn_adc_analog_capture;
- else
- spec->stream_analog_capture = &via_pcm_analog_capture;
+ if (!spec->stream_analog_capture) {
+ if (spec->dyn_adc_switch)
+ spec->stream_analog_capture =
+ &via_pcm_dyn_adc_analog_capture;
+ else
+ spec->stream_analog_capture =
+ &via_pcm_analog_capture;
+ }
+ if (spec->num_adc_nids) {
+ info->stream[SNDRV_PCM_STREAM_CAPTURE] =
+ *spec->stream_analog_capture;
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
+ spec->adc_nids[0];
+ if (!spec->dyn_adc_switch)
+ info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
+ spec->num_adc_nids;
+ }
+ codec->num_pcms++;
+ info++;
}
- info->stream[SNDRV_PCM_STREAM_CAPTURE] =
- *spec->stream_analog_capture;
- info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
- if (!spec->dyn_adc_switch)
- info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams =
- spec->num_adc_nids;
if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
- codec->num_pcms++;
- info++;
snprintf(spec->stream_name_digital,
sizeof(spec->stream_name_digital),
"%s Digital", codec->chip_name);
@@ -1562,17 +1602,19 @@ static int via_build_pcms(struct hda_codec *codec)
info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
spec->dig_in_nid;
}
+ codec->num_pcms++;
+ info++;
}
if (spec->hp_dac_nid) {
- codec->num_pcms++;
- info++;
snprintf(spec->stream_name_hp, sizeof(spec->stream_name_hp),
"%s HP", codec->chip_name);
info->name = spec->stream_name_hp;
info->stream[SNDRV_PCM_STREAM_PLAYBACK] = via_pcm_hp_playback;
info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
spec->hp_dac_nid;
+ codec->num_pcms++;
+ info++;
}
return 0;
}
@@ -1632,7 +1674,8 @@ static void via_hp_automute(struct hda_codec *codec)
int nums;
struct via_spec *spec = codec->spec;
- if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0])
+ if (!spec->hp_independent_mode && spec->autocfg.hp_pins[0] &&
+ (spec->codec_type != VT1708 || spec->vt1708_jack_detect))
present = snd_hda_jack_detect(codec, spec->autocfg.hp_pins[0]);
if (spec->smart51_enabled)
@@ -1696,6 +1739,7 @@ static void via_unsol_event(struct hda_codec *codec,
unsigned int res)
{
res >>= 26;
+ res = snd_hda_jack_get_action(codec, res);
if (res & VIA_JACK_EVENT)
set_widgets_power_state(codec);
@@ -1706,6 +1750,7 @@ static void via_unsol_event(struct hda_codec *codec,
via_hp_automute(codec);
else if (res == VIA_GPIO_EVENT)
via_gpio_control(codec);
+ snd_hda_jack_report_sync(codec);
}
#ifdef CONFIG_PM
@@ -2182,7 +2227,10 @@ static int via_auto_create_loopback_switch(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
- if (!spec->aa_mix_nid || !spec->out_mix_path.depth)
+ if (!spec->aa_mix_nid)
+ return 0; /* no loopback switching available */
+ if (!(spec->out_mix_path.depth || spec->hp_mix_path.depth ||
+ spec->speaker_path.depth))
return 0; /* no loopback switching available */
if (!via_clone_control(spec, &via_aamix_ctl_enum))
return -ENOMEM;
@@ -2266,10 +2314,7 @@ static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
if (mux) {
/* switch to D0 beofre change index */
- if (snd_hda_codec_read(codec, mux, 0,
- AC_VERB_GET_POWER_STATE, 0x00) != AC_PWRST_D0)
- snd_hda_codec_write(codec, mux, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, mux, AC_PWRST_D0);
snd_hda_codec_write(codec, mux, 0,
AC_VERB_SET_CONNECT_SEL,
spec->inputs[cur].mux_idx);
@@ -2438,6 +2483,8 @@ static int create_mic_boost_ctls(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
const struct auto_pin_cfg *cfg = &spec->autocfg;
+ const char *prev_label = NULL;
+ int type_idx = 0;
int i, err;
for (i = 0; i < cfg->num_inputs; i++) {
@@ -2452,8 +2499,13 @@ static int create_mic_boost_ctls(struct hda_codec *codec)
if (caps == -1 || !(caps & AC_AMPCAP_NUM_STEPS))
continue;
label = hda_get_autocfg_input_label(codec, cfg, i);
+ if (prev_label && !strcmp(label, prev_label))
+ type_idx++;
+ else
+ type_idx = 0;
+ prev_label = label;
snprintf(name, sizeof(name), "%s Boost Volume", label);
- err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
+ err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx,
HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT));
if (err < 0)
return err;
@@ -2599,8 +2651,6 @@ static int vt1708_jack_detect_get(struct snd_kcontrol *kcontrol,
if (spec->codec_type != VT1708)
return 0;
- spec->vt1708_jack_detect =
- !((snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8) & 0x1);
ucontrol->value.integer.value[0] = spec->vt1708_jack_detect;
return 0;
}
@@ -2610,18 +2660,22 @@ static int vt1708_jack_detect_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct via_spec *spec = codec->spec;
- int change;
+ int val;
if (spec->codec_type != VT1708)
return 0;
- spec->vt1708_jack_detect = ucontrol->value.integer.value[0];
- change = (0x1 & (snd_hda_codec_read(codec, 0x1, 0, 0xf84, 0) >> 8))
- == !spec->vt1708_jack_detect;
- if (spec->vt1708_jack_detect) {
+ val = !!ucontrol->value.integer.value[0];
+ if (spec->vt1708_jack_detect == val)
+ return 0;
+ spec->vt1708_jack_detect = val;
+ if (spec->vt1708_jack_detect &&
+ snd_hda_get_bool_hint(codec, "analog_loopback_hp_detect") != 1) {
mute_aa_path(codec, 1);
notify_aa_path_ctls(codec);
}
- return change;
+ via_hp_automute(codec);
+ vt1708_update_hp_work(spec);
+ return 1;
}
static const struct snd_kcontrol_new vt1708_jack_detect_ctl = {
@@ -2716,9 +2770,8 @@ static void via_auto_init_unsol_event(struct hda_codec *codec)
int i;
if (cfg->hp_pins[0] && is_jack_detectable(codec, cfg->hp_pins[0]))
- snd_hda_codec_write(codec, cfg->hp_pins[0], 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | VIA_HP_EVENT | VIA_JACK_EVENT);
+ snd_hda_jack_detect_enable(codec, cfg->hp_pins[0],
+ VIA_HP_EVENT | VIA_JACK_EVENT);
if (cfg->speaker_pins[0])
ev = VIA_LINE_EVENT;
@@ -2727,16 +2780,14 @@ static void via_auto_init_unsol_event(struct hda_codec *codec)
for (i = 0; i < cfg->line_outs; i++) {
if (cfg->line_out_pins[i] &&
is_jack_detectable(codec, cfg->line_out_pins[i]))
- snd_hda_codec_write(codec, cfg->line_out_pins[i], 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | ev | VIA_JACK_EVENT);
+ snd_hda_jack_detect_enable(codec, cfg->line_out_pins[i],
+ ev | VIA_JACK_EVENT);
}
for (i = 0; i < cfg->num_inputs; i++) {
if (is_jack_detectable(codec, cfg->inputs[i].pin))
- snd_hda_codec_write(codec, cfg->inputs[i].pin, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | VIA_JACK_EVENT);
+ snd_hda_jack_detect_enable(codec, cfg->inputs[i].pin,
+ VIA_JACK_EVENT);
}
}
@@ -2748,6 +2799,10 @@ static int via_init(struct hda_codec *codec)
for (i = 0; i < spec->num_iverbs; i++)
snd_hda_sequence_write(codec, spec->init_verbs[i]);
+ /* init power states */
+ set_widgets_power_state(codec);
+ __analog_low_current_mode(codec, true);
+
via_auto_init_multi_out(codec);
via_auto_init_hp_out(codec);
via_auto_init_speaker_out(codec);
@@ -2758,6 +2813,8 @@ static int via_init(struct hda_codec *codec)
via_auto_init_unsol_event(codec);
via_hp_automute(codec);
+ vt1708_update_hp_work(spec);
+ snd_hda_jack_report_sync(codec);
return 0;
}
@@ -2768,13 +2825,16 @@ static void vt1708_update_hp_jack_state(struct work_struct *work)
vt1708_hp_work.work);
if (spec->codec_type != VT1708)
return;
+ snd_hda_jack_set_dirty_all(spec->codec);
/* if jack state toggled */
if (spec->vt1708_hp_present
!= snd_hda_jack_detect(spec->codec, spec->autocfg.hp_pins[0])) {
spec->vt1708_hp_present ^= 1;
via_hp_automute(spec->codec);
}
- vt1708_start_hp_work(spec);
+ if (spec->vt1708_jack_detect)
+ schedule_delayed_work(&spec->vt1708_hp_work,
+ msecs_to_jiffies(100));
}
static int get_mux_nids(struct hda_codec *codec)
@@ -2889,9 +2949,9 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
if (imux_is_smixer)
parm = AC_PWRST_D0;
/* SW0 (17h), AIW 0/1 (13h/14h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x17, parm);
+ update_power_state(codec, 0x13, parm);
+ update_power_state(codec, 0x14, parm);
/* outputs */
/* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -2899,8 +2959,8 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
set_pin_power_state(codec, 0x19, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1b, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x11, parm);
/* PW6 (22h), SW2 (26h), AOW2 (24h) */
if (is_8ch) {
@@ -2908,20 +2968,16 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
set_pin_power_state(codec, 0x22, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x26, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x24, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x26, parm);
+ update_power_state(codec, 0x24, parm);
} else if (codec->vendor_id == 0x11064397) {
/* PW7(23h), SW2(27h), AOW2(25h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x23, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x27, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x27, parm);
+ update_power_state(codec, 0x25, parm);
}
/* PW 3/4/7 (1ch/1dh/23h) */
@@ -2933,17 +2989,13 @@ static void set_widgets_power_state_vt1708B(struct hda_codec *codec)
set_pin_power_state(codec, 0x23, &parm);
/* MW0 (16h), Sw3 (27h), AOW 0/3 (10h/25h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x10, parm);
if (is_8ch) {
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x27, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
+ update_power_state(codec, 0x27, parm);
} else if (codec->vendor_id == 0x11064397 && spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
}
static int patch_vt1708S(struct hda_codec *codec);
@@ -3116,10 +3168,10 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)
if (imux_is_smixer)
parm = AC_PWRST_D0; /* SW0 (13h) = stereo mixer (idx 3) */
/* SW0 (13h), AIW 0/1/2 (12h/1fh/20h) */
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x12, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x13, parm);
+ update_power_state(codec, 0x12, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x20, parm);
/* outputs */
/* PW 3/4 (16h/17h) */
@@ -3127,10 +3179,9 @@ static void set_widgets_power_state_vt1702(struct hda_codec *codec)
set_pin_power_state(codec, 0x17, &parm);
set_pin_power_state(codec, 0x16, &parm);
/* MW0 (1ah), AOW 0/1 (10h/1dh) */
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1a, imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x1d, parm);
}
static int patch_vt1702(struct hda_codec *codec)
@@ -3195,52 +3246,48 @@ static void set_widgets_power_state_vt1718S(struct hda_codec *codec)
if (imux_is_smixer)
parm = AC_PWRST_D0;
/* MUX6/7 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
/* outputs */
/* PW3 (27h), MW2 (1ah), AOW3 (bh) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x27, &parm);
- snd_hda_codec_write(codec, 0x1a, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xb, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1a, parm);
+ update_power_state(codec, 0xb, parm);
/* PW2 (26h), AOW2 (ah) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x26, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x2b, &parm);
- snd_hda_codec_write(codec, 0xa, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0xa, parm);
/* PW0 (24h), AOW0 (8h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x24, &parm);
if (!spec->hp_independent_mode) /* check for redirected HP */
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x8, parm);
/* MW9 (21h), Mw2 (1ah), AOW0 (8h) */
- snd_hda_codec_write(codec, 0x21, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x21, imux_is_smixer ? AC_PWRST_D0 : parm);
/* PW1 (25h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x2a, &parm);
- snd_hda_codec_write(codec, 0x9, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x9, parm);
if (spec->hp_independent_mode) {
/* PW4 (28h), MW3 (1bh), MUX1(34h), AOW4 (ch) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x1b, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0xc, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1b, parm);
+ update_power_state(codec, 0x34, parm);
+ update_power_state(codec, 0xc, parm);
}
}
@@ -3400,8 +3447,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
if (imux_is_smixer)
parm = AC_PWRST_D0;
/* SW0 (17h), AIW0(13h) */
- snd_hda_codec_write(codec, 0x17, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x13, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x17, parm);
+ update_power_state(codec, 0x13, parm);
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x1e, &parm);
@@ -3409,12 +3456,11 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
if (spec->dmic_enabled)
set_pin_power_state(codec, 0x22, &parm);
else
- snd_hda_codec_write(codec, 0x22, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x22, AC_PWRST_D3);
/* SW2(26h), AIW1(14h) */
- snd_hda_codec_write(codec, 0x26, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x14, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x26, parm);
+ update_power_state(codec, 0x14, parm);
/* outputs */
/* PW0 (19h), SW1 (18h), AOW1 (11h) */
@@ -3423,8 +3469,8 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
/* Smart 5.1 PW2(1bh) */
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1b, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x11, parm);
/* PW7 (23h), SW3 (27h), AOW3 (25h) */
parm = AC_PWRST_D3;
@@ -3432,12 +3478,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
/* Smart 5.1 PW1(1ah) */
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1a, &parm);
- snd_hda_codec_write(codec, 0x27, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x27, parm);
/* Smart 5.1 PW5(1eh) */
if (spec->smart51_enabled)
set_pin_power_state(codec, 0x1e, &parm);
- snd_hda_codec_write(codec, 0x25, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
/* Mono out */
/* SW4(28h)->MW1(29h)-> PW12 (2ah)*/
@@ -3453,9 +3499,9 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
mono_out = 1;
}
parm = mono_out ? AC_PWRST_D0 : AC_PWRST_D3;
- snd_hda_codec_write(codec, 0x28, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x29, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x2a, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x28, parm);
+ update_power_state(codec, 0x29, parm);
+ update_power_state(codec, 0x2a, parm);
/* PW 3/4 (1ch/1dh) */
parm = AC_PWRST_D3;
@@ -3463,15 +3509,12 @@ static void set_widgets_power_state_vt1716S(struct hda_codec *codec)
set_pin_power_state(codec, 0x1d, &parm);
/* HP Independent Mode, power on AOW3 */
if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x25, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x25, parm);
/* force to D0 for internal Speaker */
/* MW0 (16h), AOW0 (10h) */
- snd_hda_codec_write(codec, 0x16, 0, AC_VERB_SET_POWER_STATE,
- imux_is_smixer ? AC_PWRST_D0 : parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE,
- mono_out ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x16, imux_is_smixer ? AC_PWRST_D0 : parm);
+ update_power_state(codec, 0x10, mono_out ? AC_PWRST_D0 : parm);
}
static int patch_vt1716S(struct hda_codec *codec)
@@ -3547,54 +3590,45 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
set_pin_power_state(codec, 0x2b, &parm);
parm = AC_PWRST_D0;
/* MUX9/10 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
/* outputs */
/* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x8, parm);
if (spec->codec_type == VT1802) {
/* PW4 (28h), MW4 (18h), MUX4(38h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x38, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x38, parm);
} else {
/* PW4 (26h), MW4 (1ch), MUX4(37h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x26, &parm);
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x37, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1c, parm);
+ update_power_state(codec, 0x37, parm);
}
if (spec->codec_type == VT1802) {
/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x15, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x15, parm);
+ update_power_state(codec, 0x35, parm);
} else {
/* PW1 (25h), MW1 (19h), MUX1(35h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x19, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x19, parm);
+ update_power_state(codec, 0x35, parm);
}
if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x9, AC_PWRST_D0);
/* Class-D */
/* PW0 (24h), MW0(18h/14h), MUX0(34h) */
@@ -3604,12 +3638,10 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
set_pin_power_state(codec, 0x24, &parm);
parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
if (spec->codec_type == VT1802)
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x14, parm);
else
- snd_hda_codec_write(codec, 0x18, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x34, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x34, parm);
/* Mono Out */
present = snd_hda_jack_detect(codec, 0x26);
@@ -3617,28 +3649,20 @@ static void set_widgets_power_state_vt2002P(struct hda_codec *codec)
parm = present ? AC_PWRST_D3 : AC_PWRST_D0;
if (spec->codec_type == VT1802) {
/* PW15 (33h), MW8(1ch), MUX8(3ch) */
- snd_hda_codec_write(codec, 0x33, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x33, parm);
+ update_power_state(codec, 0x1c, parm);
+ update_power_state(codec, 0x3c, parm);
} else {
/* PW15 (31h), MW8(17h), MUX8(3bh) */
- snd_hda_codec_write(codec, 0x31, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x17, 0,
- AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3b, 0,
- AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x31, parm);
+ update_power_state(codec, 0x17, parm);
+ update_power_state(codec, 0x3b, parm);
}
/* MW9 (21h) */
if (imux_is_smixer || !is_aa_path_mute(codec))
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x21, AC_PWRST_D0);
else
- snd_hda_codec_write(codec, 0x21, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x21, AC_PWRST_D3);
}
/* patch for vt2002P */
@@ -3688,13 +3712,8 @@ static const struct hda_verb vt1812_init_verbs[] = {
static void set_widgets_power_state_vt1812(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
- int imux_is_smixer =
- snd_hda_codec_read(codec, 0x13, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 3;
unsigned int parm;
unsigned int present;
- /* MUX10 (1eh) = stereo mixer */
- imux_is_smixer =
- snd_hda_codec_read(codec, 0x1e, 0, AC_VERB_GET_CONNECT_SEL, 0x00) == 5;
/* inputs */
/* PW 5/6/7 (29h/2ah/2bh) */
parm = AC_PWRST_D3;
@@ -3703,30 +3722,28 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
set_pin_power_state(codec, 0x2b, &parm);
parm = AC_PWRST_D0;
/* MUX10/11 (1eh/1fh), AIW 0/1 (10h/11h) */
- snd_hda_codec_write(codec, 0x1e, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x1f, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1e, parm);
+ update_power_state(codec, 0x1f, parm);
+ update_power_state(codec, 0x10, parm);
+ update_power_state(codec, 0x11, parm);
/* outputs */
/* AOW0 (8h)*/
- snd_hda_codec_write(codec, 0x8, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x8, AC_PWRST_D0);
/* PW4 (28h), MW4 (18h), MUX4(38h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x28, &parm);
- snd_hda_codec_write(codec, 0x18, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x38, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x18, parm);
+ update_power_state(codec, 0x38, parm);
/* PW1 (25h), MW1 (15h), MUX1(35h), AOW1 (9h) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x25, &parm);
- snd_hda_codec_write(codec, 0x15, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x35, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x15, parm);
+ update_power_state(codec, 0x35, parm);
if (spec->hp_independent_mode)
- snd_hda_codec_write(codec, 0x9, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x9, AC_PWRST_D0);
/* Internal Speaker */
/* PW0 (24h), MW0(14h), MUX0(34h) */
@@ -3735,15 +3752,11 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x24, &parm);
if (present) {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x14, AC_PWRST_D3);
+ update_power_state(codec, 0x34, AC_PWRST_D3);
} else {
- snd_hda_codec_write(codec, 0x14, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x34, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x14, AC_PWRST_D0);
+ update_power_state(codec, 0x34, AC_PWRST_D0);
}
@@ -3754,26 +3767,20 @@ static void set_widgets_power_state_vt1812(struct hda_codec *codec)
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x31, &parm);
if (present) {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
+ update_power_state(codec, 0x1c, AC_PWRST_D3);
+ update_power_state(codec, 0x3c, AC_PWRST_D3);
+ update_power_state(codec, 0x3e, AC_PWRST_D3);
} else {
- snd_hda_codec_write(codec, 0x1c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3c, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
- snd_hda_codec_write(codec, 0x3e, 0,
- AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
+ update_power_state(codec, 0x1c, AC_PWRST_D0);
+ update_power_state(codec, 0x3c, AC_PWRST_D0);
+ update_power_state(codec, 0x3e, AC_PWRST_D0);
}
/* PW15 (33h), MW15 (1dh), MUX15(3dh) */
parm = AC_PWRST_D3;
set_pin_power_state(codec, 0x33, &parm);
- snd_hda_codec_write(codec, 0x1d, 0, AC_VERB_SET_POWER_STATE, parm);
- snd_hda_codec_write(codec, 0x3d, 0, AC_VERB_SET_POWER_STATE, parm);
+ update_power_state(codec, 0x1d, parm);
+ update_power_state(codec, 0x3d, parm);
}
diff --git a/sound/pci/ice1712/ak4xxx.c b/sound/pci/ice1712/ak4xxx.c
index 90d560c3df13..3981823f9094 100644
--- a/sound/pci/ice1712/ak4xxx.c
+++ b/sound/pci/ice1712/ak4xxx.c
@@ -26,6 +26,7 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/init.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include "ice1712.h"
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index e328cfb7620c..e525da2673be 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -68,8 +68,11 @@ static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
{
- /* we use pins 39 and 41 of the VT1616 for left and right read outputs */
- snd_ac97_write_cache(ice->ac97, 0x5a, snd_ac97_read(ice->ac97, 0x5a) & ~0x8000);
+ if (ice->ac97)
+ /* we use pins 39 and 41 of the VT1616 for left and right
+ read outputs */
+ snd_ac97_write_cache(ice->ac97, 0x5a,
+ snd_ac97_read(ice->ac97, 0x5a) & ~0x8000);
return 0;
}
diff --git a/sound/pci/ice1712/envy24ht.h b/sound/pci/ice1712/envy24ht.h
index a0c5e009bb4a..4ca33a800bc8 100644
--- a/sound/pci/ice1712/envy24ht.h
+++ b/sound/pci/ice1712/envy24ht.h
@@ -66,6 +66,7 @@ enum {
#define VT1724_CFG_CLOCK384 0x40 /* 16.9344Mhz, 44.1kHz*384 */
#define VT1724_CFG_MPU401 0x20 /* MPU401 UARTs */
#define VT1724_CFG_ADC_MASK 0x0c /* one, two or one and S/PDIF, stereo ADCs */
+#define VT1724_CFG_ADC_NONE 0x0c /* no ADCs */
#define VT1724_CFG_DAC_MASK 0x03 /* one, two, three, four stereo DACs */
#define VT1724_REG_AC97_CFG 0x05 /* byte */
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 0ccc0eb75775..132a86e09d07 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -54,7 +54,7 @@
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
@@ -84,9 +84,9 @@ MODULE_SUPPORTED_DEVICE("{"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
static char *model[SNDRV_CARDS];
-static int omni[SNDRV_CARDS]; /* Delta44 & 66 Omni I/O support */
+static bool omni[SNDRV_CARDS]; /* Delta44 & 66 Omni I/O support */
static int cs8427_timeout[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS-1)] = 500}; /* CS8427 S/PDIF transceiver reset timeout value in msec */
static int dxr_enable[SNDRV_CARDS]; /* DXR enable for DMX6FIRE */
@@ -2748,8 +2748,9 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
if (!c->no_mpu401) {
err = snd_mpu401_uart_new(card, 0, MPU401_HW_ICE1712,
ICEREG(ice, MPU1_CTRL),
- (c->mpu401_1_info_flags | MPU401_INFO_INTEGRATED),
- ice->irq, 0, &ice->rmidi[0]);
+ c->mpu401_1_info_flags |
+ MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+ -1, &ice->rmidi[0]);
if (err < 0) {
snd_card_free(card);
return err;
@@ -2764,8 +2765,9 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
/* 2nd port used */
err = snd_mpu401_uart_new(card, 1, MPU401_HW_ICE1712,
ICEREG(ice, MPU2_CTRL),
- (c->mpu401_2_info_flags | MPU401_INFO_INTEGRATED),
- ice->irq, 0, &ice->rmidi[1]);
+ c->mpu401_2_info_flags |
+ MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+ -1, &ice->rmidi[1]);
if (err < 0) {
snd_card_free(card);
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index c2b7f8bc41e4..812d10e43ae0 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -28,7 +28,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
#include <sound/info.h>
@@ -80,7 +80,7 @@ MODULE_SUPPORTED_DEVICE("{"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static char *model[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
@@ -1013,6 +1013,25 @@ static int set_rate_constraints(struct snd_ice1712 *ice,
ice->hw_rates);
}
+/* if the card has the internal rate locked (is_pro_locked), limit runtime
+ hw rates to the current internal rate only.
+*/
+static void constrain_rate_if_locked(struct snd_pcm_substream *substream)
+{
+ struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ unsigned int rate;
+ if (is_pro_rate_locked(ice)) {
+ rate = ice->get_rate(ice);
+ if (rate >= runtime->hw.rate_min
+ && rate <= runtime->hw.rate_max) {
+ runtime->hw.rate_min = rate;
+ runtime->hw.rate_max = rate;
+ }
+ }
+}
+
+
/* multi-channel playback needs alignment 8x32bit regardless of the channels
* actually used
*/
@@ -1046,6 +1065,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ constrain_rate_if_locked(substream);
if (ice->pro_open)
ice->pro_open(ice, substream);
return 0;
@@ -1066,6 +1086,7 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ constrain_rate_if_locked(substream);
if (ice->pro_open)
ice->pro_open(ice, substream);
return 0;
@@ -1117,14 +1138,21 @@ static struct snd_pcm_ops snd_vt1724_capture_pro_ops = {
static int __devinit snd_vt1724_pcm_profi(struct snd_ice1712 *ice, int device)
{
struct snd_pcm *pcm;
- int err;
+ int capt, err;
- err = snd_pcm_new(ice->card, "ICE1724", device, 1, 1, &pcm);
+ if ((ice->eeprom.data[ICE_EEP2_SYSCONF] & VT1724_CFG_ADC_MASK) ==
+ VT1724_CFG_ADC_NONE)
+ capt = 0;
+ else
+ capt = 1;
+ err = snd_pcm_new(ice->card, "ICE1724", device, 1, capt, &pcm);
if (err < 0)
return err;
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_vt1724_playback_pro_ops);
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_vt1724_capture_pro_ops);
+ if (capt)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE,
+ &snd_vt1724_capture_pro_ops);
pcm->private_data = ice;
pcm->info_flags = 0;
@@ -1208,6 +1236,7 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ constrain_rate_if_locked(substream);
if (ice->spdif.ops.open)
ice->spdif.ops.open(ice, substream);
return 0;
@@ -1244,6 +1273,7 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
VT1724_BUFFER_ALIGN);
snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
VT1724_BUFFER_ALIGN);
+ constrain_rate_if_locked(substream);
if (ice->spdif.ops.open)
ice->spdif.ops.open(ice, substream);
return 0;
@@ -1825,7 +1855,12 @@ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = hw_rates_count + ice->ext_clock_count;
+ /* internal clocks */
+ uinfo->value.enumerated.items = hw_rates_count;
+ /* external clocks */
+ if (ice->force_rdma1 ||
+ (ice->eeprom.data[ICE_EEP2_SPDIF] & VT1724_CFG_SPDIF_IN))
+ uinfo->value.enumerated.items += ice->ext_clock_count;
/* upper limit - keep at top */
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
@@ -2173,6 +2208,40 @@ static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
static struct snd_ice1712_card_info no_matched __devinitdata;
+
+/*
+ ooAoo cards with no controls
+*/
+static unsigned char ooaoo_sq210_eeprom[] __devinitdata = {
+ [ICE_EEP2_SYSCONF] = 0x4c, /* 49MHz crystal, no mpu401, no ADC,
+ 1xDACs */
+ [ICE_EEP2_ACLINK] = 0x80, /* I2S */
+ [ICE_EEP2_I2S] = 0x78, /* no volume, 96k, 24bit, 192k */
+ [ICE_EEP2_SPDIF] = 0xc1, /* out-en, out-int, out-ext */
+ [ICE_EEP2_GPIO_DIR] = 0x00, /* no GPIOs are used */
+ [ICE_EEP2_GPIO_DIR1] = 0x00,
+ [ICE_EEP2_GPIO_DIR2] = 0x00,
+ [ICE_EEP2_GPIO_MASK] = 0xff,
+ [ICE_EEP2_GPIO_MASK1] = 0xff,
+ [ICE_EEP2_GPIO_MASK2] = 0xff,
+
+ [ICE_EEP2_GPIO_STATE] = 0x00, /* inputs */
+ [ICE_EEP2_GPIO_STATE1] = 0x00, /* all 1, but GPIO_CPLD_RW
+ and GPIO15 always zero */
+ [ICE_EEP2_GPIO_STATE2] = 0x00, /* inputs */
+};
+
+
+struct snd_ice1712_card_info snd_vt1724_ooaoo_cards[] __devinitdata = {
+ {
+ .name = "ooAoo SQ210a",
+ .model = "sq210a",
+ .eeprom_size = sizeof(ooaoo_sq210_eeprom),
+ .eeprom_data = ooaoo_sq210_eeprom,
+ },
+ { } /* terminator */
+};
+
static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
snd_vt1724_revo_cards,
snd_vt1724_amp_cards,
@@ -2187,6 +2256,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
snd_vt1724_wtm_cards,
snd_vt1724_se_cards,
snd_vt1724_qtet_cards,
+ snd_vt1724_ooaoo_cards,
NULL,
};
@@ -2270,7 +2340,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
}
}
for (tbl = card_tables; *tbl; tbl++) {
- for (c = *tbl; c->subvendor; c++) {
+ for (c = *tbl; c->name; c++) {
if (modelname && c->model &&
!strcmp(modelname, c->model)) {
printk(KERN_INFO "ice1724: Using board model %s\n",
@@ -2579,8 +2649,10 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
ice->ext_clock_count = 0;
for (tbl = card_tables; *tbl; tbl++) {
- for (c = *tbl; c->subvendor; c++) {
- if (c->subvendor == ice->eeprom.subvendor) {
+ for (c = *tbl; c->name; c++) {
+ if ((model[dev] && c->model &&
+ !strcmp(model[dev], c->model)) ||
+ (c->subvendor == ice->eeprom.subvendor)) {
strcpy(card->shortname, c->name);
if (c->driver) /* specific driver? */
strcpy(card->driver, c->driver);
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 6a5b387b97fd..e0a4263baa20 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -32,7 +32,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
@@ -42,6 +42,12 @@
#include <asm/pgtable.h>
#include <asm/cacheflush.h>
+#ifdef CONFIG_KVM_GUEST
+#include <linux/kvm_para.h>
+#else
+#define kvm_para_available() (0)
+#endif
+
MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
MODULE_DESCRIPTION("Intel 82801AA,82901AB,i810,i820,i830,i840,i845,MX440; SiS 7012; Ali 5455");
MODULE_LICENSE("GPL");
@@ -73,10 +79,11 @@ static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
static int ac97_clock;
static char *ac97_quirk;
-static int buggy_semaphore;
+static bool buggy_semaphore;
static int buggy_irq = -1; /* auto-check */
-static int xbox;
+static bool xbox;
static int spdif_aclink = -1;
+static int inside_vm = -1;
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
@@ -88,15 +95,17 @@ module_param(ac97_quirk, charp, 0444);
MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
module_param(buggy_semaphore, bool, 0444);
MODULE_PARM_DESC(buggy_semaphore, "Enable workaround for hardwares with problematic codec semaphores.");
-module_param(buggy_irq, bool, 0444);
+module_param(buggy_irq, bint, 0444);
MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
module_param(xbox, bool, 0444);
MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
module_param(spdif_aclink, int, 0444);
MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
+module_param(inside_vm, bint, 0444);
+MODULE_PARM_DESC(inside_vm, "KVM/Parallels optimization.");
/* just for backward compatibility */
-static int enable;
+static bool enable;
module_param(enable, bool, 0444);
static int joystick;
module_param(joystick, int, 0444);
@@ -400,6 +409,7 @@ struct intel8x0 {
unsigned buggy_irq: 1; /* workaround for buggy mobos */
unsigned xbox: 1; /* workaround for Xbox AC'97 detection */
unsigned buggy_semaphore: 1; /* workaround for buggy codec semaphore */
+ unsigned inside_vm: 1; /* enable VM optimization */
int spdif_idx; /* SPDIF BAR index; *_SPBAR or -1 if use PCMOUT */
unsigned int sdm_saved; /* SDM reg value */
@@ -1065,8 +1075,18 @@ static snd_pcm_uframes_t snd_intel8x0_pcm_pointer(struct snd_pcm_substream *subs
udelay(10);
continue;
}
- if (civ == igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV) &&
- ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
+ if (civ != igetbyte(chip, ichdev->reg_offset + ICH_REG_OFF_CIV))
+ continue;
+
+ /* IO read operation is very expensive inside virtual machine
+ * as it is emulated. The probability that subsequent PICB read
+ * will return different result is high enough to loop till
+ * timeout here.
+ * Same CIV is strict enough condition to be sure that PICB
+ * is valid inside VM on emulated card. */
+ if (chip->inside_vm)
+ break;
+ if (ptr1 == igetword(chip, ichdev->reg_offset + ichdev->roff_picb))
break;
} while (timeout--);
ptr = ichdev->last_pos;
@@ -2082,6 +2102,12 @@ static struct ac97_quirk ac97_quirks[] __devinitdata = {
},
{
.subvendor = 0x161f,
+ .subdevice = 0x202f,
+ .name = "Gateway M520",
+ .type = AC97_TUNE_INV_EAPD
+ },
+ {
+ .subvendor = 0x161f,
.subdevice = 0x203a,
.name = "Gateway 4525GZ", /* AD1981B */
.type = AC97_TUNE_INV_EAPD
@@ -2917,6 +2943,45 @@ static unsigned int sis_codec_bits[3] = {
ICH_PCR, ICH_SCR, ICH_SIS_TCR
};
+static int __devinit snd_intel8x0_inside_vm(struct pci_dev *pci)
+{
+ int result = inside_vm;
+ char *msg = NULL;
+
+ /* check module parameter first (override detection) */
+ if (result >= 0) {
+ msg = result ? "enable (forced) VM" : "disable (forced) VM";
+ goto fini;
+ }
+
+ /* detect KVM and Parallels virtual environments */
+ result = kvm_para_available();
+#ifdef X86_FEATURE_HYPERVISOR
+ result = result || boot_cpu_has(X86_FEATURE_HYPERVISOR);
+#endif
+ if (!result)
+ goto fini;
+
+ /* check for known (emulated) devices */
+ if (pci->subsystem_vendor == 0x1af4 &&
+ pci->subsystem_device == 0x1100) {
+ /* KVM emulated sound, PCI SSID: 1af4:1100 */
+ msg = "enable KVM";
+ } else if (pci->subsystem_vendor == 0x1ab8) {
+ /* Parallels VM emulated sound, PCI SSID: 1ab8:xxxx */
+ msg = "enable Parallels VM";
+ } else {
+ msg = "disable (unknown or VT-d) VM";
+ result = 0;
+ }
+
+fini:
+ if (msg != NULL)
+ printk(KERN_INFO "intel8x0: %s optimization\n", msg);
+
+ return result;
+}
+
static int __devinit snd_intel8x0_create(struct snd_card *card,
struct pci_dev *pci,
unsigned long device_type,
@@ -2984,6 +3049,8 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
if (xbox)
chip->xbox = 1;
+ chip->inside_vm = snd_intel8x0_inside_vm(pci);
+
if (pci->vendor == PCI_VENDOR_ID_INTEL &&
pci->device == PCI_DEVICE_ID_INTEL_440MX)
chip->fix_nocache = 1; /* enable workaround */
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 7c161645d865..d689913a61be 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -29,7 +29,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
@@ -68,7 +68,7 @@ module_param(ac97_clock, int, 0444);
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (0 = auto-detect).");
/* just for backward compatibility */
-static int enable;
+static bool enable;
module_param(enable, bool, 0444);
/*
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index fc1d573cf306..8fea45ab5882 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -25,7 +25,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/wait.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/firmware.h>
@@ -408,7 +408,7 @@ MODULE_FIRMWARE("korg/k1212.dsp");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Korg 1212 soundcard.");
diff --git a/sound/pci/lola/lola.c b/sound/pci/lola/lola.c
index 3e92e5b5ec3d..375982736858 100644
--- a/sound/pci/lola/lola.c
+++ b/sound/pci/lola/lola.c
@@ -20,7 +20,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
@@ -35,7 +35,7 @@
/* Standard options */
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Digigram Lola driver.");
diff --git a/sound/pci/lx6464es/lx6464es.c b/sound/pci/lx6464es/lx6464es.c
index 04ae84b2a107..d94c0c292bd0 100644
--- a/sound/pci/lx6464es/lx6464es.c
+++ b/sound/pci/lx6464es/lx6464es.c
@@ -42,7 +42,7 @@ MODULE_SUPPORTED_DEVICE("{digigram lx6464es{}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Digigram LX6464ES interface.");
diff --git a/sound/pci/lx6464es/lx_core.c b/sound/pci/lx6464es/lx_core.c
index 5c8717e29eeb..8c3e7fcefd99 100644
--- a/sound/pci/lx6464es/lx_core.c
+++ b/sound/pci/lx6464es/lx_core.c
@@ -78,10 +78,15 @@ unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port)
return ioread32(address);
}
-void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len)
+static void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data,
+ u32 len)
{
- void __iomem *address = lx_dsp_register(chip, port);
- memcpy_fromio(data, address, len*sizeof(u32));
+ u32 __iomem *address = lx_dsp_register(chip, port);
+ int i;
+
+ /* we cannot use memcpy_fromio */
+ for (i = 0; i != len; ++i)
+ data[i] = ioread32(address + i);
}
@@ -91,11 +96,15 @@ void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data)
iowrite32(data, address);
}
-void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data,
- u32 len)
+static void lx_dsp_reg_writebuf(struct lx6464es *chip, int port,
+ const u32 *data, u32 len)
{
- void __iomem *address = lx_dsp_register(chip, port);
- memcpy_toio(address, data, len*sizeof(u32));
+ u32 __iomem *address = lx_dsp_register(chip, port);
+ int i;
+
+ /* we cannot use memcpy_to */
+ for (i = 0; i != len; ++i)
+ iowrite32(data[i], address + i);
}
diff --git a/sound/pci/lx6464es/lx_core.h b/sound/pci/lx6464es/lx_core.h
index 1dd562980b6c..4d7ff797a646 100644
--- a/sound/pci/lx6464es/lx_core.h
+++ b/sound/pci/lx6464es/lx_core.h
@@ -72,10 +72,7 @@ enum {
};
unsigned long lx_dsp_reg_read(struct lx6464es *chip, int port);
-void lx_dsp_reg_readbuf(struct lx6464es *chip, int port, u32 *data, u32 len);
void lx_dsp_reg_write(struct lx6464es *chip, int port, unsigned data);
-void lx_dsp_reg_writebuf(struct lx6464es *chip, int port, const u32 *data,
- u32 len);
/* plx register access */
enum {
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 0378126e6272..78229b0dad2b 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -39,7 +39,7 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/vmalloc.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/firmware.h>
#include <linux/input.h>
#include <sound/core.h>
@@ -64,8 +64,8 @@ MODULE_FIRMWARE("ess/maestro3_assp_minisrc.fw");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* all enabled */
-static int external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* all enabled */
+static bool external_amp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
static int amp_gpio[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
module_param_array(index, int, NULL, 0444);
@@ -2820,8 +2820,8 @@ snd_m3_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
/* TODO enable MIDI IRQ and I/O */
err = snd_mpu401_uart_new(chip->card, 0, MPU401_HW_MPU401,
chip->iobase + MPU401_DATA_PORT,
- MPU401_INFO_INTEGRATED,
- chip->irq, 0, &chip->rmidi);
+ MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK,
+ -1, &chip->rmidi);
if (err < 0)
printk(KERN_WARNING "maestro3: no MIDI support.\n");
#endif
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index dbee59906ae1..487837c01c9f 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -25,7 +25,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/dma-mapping.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/slab.h>
@@ -49,7 +49,7 @@ MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Digigram " CARD_NAME " soundcard.");
diff --git a/sound/pci/mixart/mixart_hwdep.c b/sound/pci/mixart/mixart_hwdep.c
index bf2696aa5d49..bfbdc91e4cb3 100644
--- a/sound/pci/mixart/mixart_hwdep.c
+++ b/sound/pci/mixart/mixart_hwdep.c
@@ -25,6 +25,7 @@
#include <linux/firmware.h>
#include <linux/vmalloc.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <sound/core.h>
#include "mixart.h"
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 83ea7a7d3eec..ade2c64bd606 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -30,7 +30,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
@@ -57,12 +57,12 @@ static int index = SNDRV_DEFAULT_IDX1; /* Index */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
static int playback_bufsize = 16;
static int capture_bufsize = 16;
-static int force_ac97; /* disabled as default */
+static bool force_ac97; /* disabled as default */
static int buffer_top; /* not specified */
-static int use_cache; /* disabled */
-static int vaio_hack; /* disabled */
-static int reset_workaround;
-static int reset_workaround_2;
+static bool use_cache; /* disabled */
+static bool vaio_hack; /* disabled */
+static bool reset_workaround;
+static bool reset_workaround_2;
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
@@ -86,7 +86,7 @@ module_param(reset_workaround_2, bool, 0444);
MODULE_PARM_DESC(reset_workaround_2, "Enable extended AC97 RESET workaround for some other laptops.");
/* just for backward compatibility */
-static int enable;
+static bool enable;
module_param(enable, bool, 0444);
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index 218d9854e5cb..eab663eef117 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -51,6 +51,7 @@
#include <linux/delay.h>
#include <linux/mutex.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <sound/ac97_codec.h>
#include <sound/control.h>
#include <sound/core.h>
@@ -73,7 +74,7 @@ MODULE_SUPPORTED_DEVICE("{{C-Media,CMI8786}"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "card index");
diff --git a/sound/pci/oxygen/oxygen_io.c b/sound/pci/oxygen/oxygen_io.c
index f5164b1e1c80..521eae458348 100644
--- a/sound/pci/oxygen/oxygen_io.c
+++ b/sound/pci/oxygen/oxygen_io.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/sched.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/mpu401.h>
#include <asm/io.h>
diff --git a/sound/pci/oxygen/oxygen_lib.c b/sound/pci/oxygen/oxygen_lib.c
index 82311fcb86f6..92e2d67f16a1 100644
--- a/sound/pci/oxygen/oxygen_lib.c
+++ b/sound/pci/oxygen/oxygen_lib.c
@@ -22,6 +22,7 @@
#include <linux/mutex.h>
#include <linux/pci.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/ac97_codec.h>
#include <sound/asoundef.h>
#include <sound/core.h>
@@ -678,15 +679,15 @@ int oxygen_pci_probe(struct pci_dev *pci, int index, char *id,
goto err_card;
if (chip->model.device_config & (MIDI_OUTPUT | MIDI_INPUT)) {
- unsigned int info_flags = MPU401_INFO_INTEGRATED;
+ unsigned int info_flags =
+ MPU401_INFO_INTEGRATED | MPU401_INFO_IRQ_HOOK;
if (chip->model.device_config & MIDI_OUTPUT)
info_flags |= MPU401_INFO_OUTPUT;
if (chip->model.device_config & MIDI_INPUT)
info_flags |= MPU401_INFO_INPUT;
err = snd_mpu401_uart_new(card, 0, MPU401_HW_CMIPCI,
chip->addr + OXYGEN_MPU401,
- info_flags, 0, 0,
- &chip->midi);
+ info_flags, -1, &chip->midi);
if (err < 0)
goto err_card;
}
diff --git a/sound/pci/oxygen/oxygen_mixer.c b/sound/pci/oxygen/oxygen_mixer.c
index 26c7e8bcb229..c0dbb52d45be 100644
--- a/sound/pci/oxygen/oxygen_mixer.c
+++ b/sound/pci/oxygen/oxygen_mixer.c
@@ -618,9 +618,12 @@ static int ac97_volume_get(struct snd_kcontrol *ctl,
mutex_lock(&chip->mutex);
reg = oxygen_read_ac97(chip, codec, index);
mutex_unlock(&chip->mutex);
- value->value.integer.value[0] = 31 - (reg & 0x1f);
- if (stereo)
- value->value.integer.value[1] = 31 - ((reg >> 8) & 0x1f);
+ if (!stereo) {
+ value->value.integer.value[0] = 31 - (reg & 0x1f);
+ } else {
+ value->value.integer.value[0] = 31 - ((reg >> 8) & 0x1f);
+ value->value.integer.value[1] = 31 - (reg & 0x1f);
+ }
return 0;
}
@@ -636,14 +639,14 @@ static int ac97_volume_put(struct snd_kcontrol *ctl,
mutex_lock(&chip->mutex);
oldreg = oxygen_read_ac97(chip, codec, index);
- newreg = oldreg;
- newreg = (newreg & ~0x1f) |
- (31 - (value->value.integer.value[0] & 0x1f));
- if (stereo)
- newreg = (newreg & ~0x1f00) |
- ((31 - (value->value.integer.value[1] & 0x1f)) << 8);
- else
- newreg = (newreg & ~0x1f00) | ((newreg & 0x1f) << 8);
+ if (!stereo) {
+ newreg = oldreg & ~0x1f;
+ newreg |= 31 - (value->value.integer.value[0] & 0x1f);
+ } else {
+ newreg = oldreg & ~0x1f1f;
+ newreg |= (31 - (value->value.integer.value[0] & 0x1f)) << 8;
+ newreg |= 31 - (value->value.integer.value[1] & 0x1f);
+ }
change = newreg != oldreg;
if (change)
oxygen_write_ac97(chip, codec, index, newreg);
diff --git a/sound/pci/oxygen/virtuoso.c b/sound/pci/oxygen/virtuoso.c
index 773db794b43f..3fdee4950174 100644
--- a/sound/pci/oxygen/virtuoso.c
+++ b/sound/pci/oxygen/virtuoso.c
@@ -19,6 +19,7 @@
#include <linux/pci.h>
#include <linux/delay.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
@@ -31,7 +32,7 @@ MODULE_SUPPORTED_DEVICE("{{Asus,AV66},{Asus,AV100},{Asus,AV200}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "card index");
diff --git a/sound/pci/oxygen/xonar_cs43xx.c b/sound/pci/oxygen/xonar_cs43xx.c
index 252719101c42..c8febf4b9bd6 100644
--- a/sound/pci/oxygen/xonar_cs43xx.c
+++ b/sound/pci/oxygen/xonar_cs43xx.c
@@ -418,6 +418,7 @@ static const struct oxygen_model model_xonar_d1 = {
.device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF |
CAPTURE_0_FROM_I2S_2 |
+ CAPTURE_1_FROM_SPDIF |
AC97_FMIC_SWITCH,
.dac_channels_pcm = 8,
.dac_channels_mixer = 8,
diff --git a/sound/pci/oxygen/xonar_dg.c b/sound/pci/oxygen/xonar_dg.c
index bc6eb58be380..793bdf03d7e0 100644
--- a/sound/pci/oxygen/xonar_dg.c
+++ b/sound/pci/oxygen/xonar_dg.c
@@ -597,7 +597,8 @@ struct oxygen_model model_xonar_dg = {
.model_data_size = sizeof(struct dg),
.device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF |
- CAPTURE_0_FROM_I2S_2,
+ CAPTURE_0_FROM_I2S_2 |
+ CAPTURE_1_FROM_SPDIF,
.dac_channels_pcm = 6,
.dac_channels_mixer = 0,
.function_flags = OXYGEN_FUNCTION_SPI,
diff --git a/sound/pci/oxygen/xonar_pcm179x.c b/sound/pci/oxygen/xonar_pcm179x.c
index 32d096c98f5b..8433aa7c3d75 100644
--- a/sound/pci/oxygen/xonar_pcm179x.c
+++ b/sound/pci/oxygen/xonar_pcm179x.c
@@ -1074,6 +1074,7 @@ static const struct oxygen_model model_xonar_st = {
.device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF |
CAPTURE_0_FROM_I2S_2 |
+ CAPTURE_1_FROM_SPDIF |
AC97_FMIC_SWITCH,
.dac_channels_pcm = 2,
.dac_channels_mixer = 2,
diff --git a/sound/pci/oxygen/xonar_wm87x6.c b/sound/pci/oxygen/xonar_wm87x6.c
index 42d1ab136217..63cff90706bf 100644
--- a/sound/pci/oxygen/xonar_wm87x6.c
+++ b/sound/pci/oxygen/xonar_wm87x6.c
@@ -177,6 +177,7 @@ static void wm8776_registers_init(struct oxygen *chip)
struct xonar_wm87x6 *data = chip->model_data;
wm8776_write(chip, WM8776_RESET, 0);
+ wm8776_write(chip, WM8776_PHASESWAP, WM8776_PH_MASK);
wm8776_write(chip, WM8776_DACCTRL1, WM8776_DZCEN |
WM8776_PL_LEFT_LEFT | WM8776_PL_RIGHT_RIGHT);
wm8776_write(chip, WM8776_DACMUTE, chip->dac_mute ? WM8776_DMUTE : 0);
@@ -1274,7 +1275,8 @@ static const struct oxygen_model model_xonar_ds = {
.model_data_size = sizeof(struct xonar_wm87x6),
.device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF |
- CAPTURE_0_FROM_I2S_1,
+ CAPTURE_0_FROM_I2S_1 |
+ CAPTURE_1_FROM_SPDIF,
.dac_channels_pcm = 8,
.dac_channels_mixer = 8,
.dac_volume_min = 255 - 2*60,
@@ -1306,7 +1308,8 @@ static const struct oxygen_model model_xonar_hdav_slim = {
.model_data_size = sizeof(struct xonar_wm87x6),
.device_config = PLAYBACK_0_TO_I2S |
PLAYBACK_1_TO_SPDIF |
- CAPTURE_0_FROM_I2S_1,
+ CAPTURE_0_FROM_I2S_1 |
+ CAPTURE_1_FROM_SPDIF,
.dac_channels_pcm = 8,
.dac_channels_mixer = 2,
.dac_volume_min = 255 - 2*60,
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 046578d26f98..fd1809ab73b4 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -27,7 +27,7 @@
#include <linux/pci.h>
#include <linux/dma-mapping.h>
#include <linux/delay.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/mutex.h>
#include <sound/core.h>
@@ -52,8 +52,8 @@ MODULE_SUPPORTED_DEVICE("{{Digigram," DRIVER_NAME "}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
-static int mono[SNDRV_CARDS]; /* capture mono only */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+static bool mono[SNDRV_CARDS]; /* capture mono only */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Digigram " DRIVER_NAME " soundcard");
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
index 17cb1233a903..ec1587cddb0c 100644
--- a/sound/pci/pcxhr/pcxhr_hwdep.c
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -24,6 +24,7 @@
#include <linux/vmalloc.h>
#include <linux/firmware.h>
#include <linux/pci.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <sound/core.h>
#include <sound/hwdep.h>
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index e34ae14908b3..0481d94aac9b 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -98,6 +98,7 @@
#include <linux/device.h>
#include <linux/firmware.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include <asm/io.h>
#include <sound/core.h>
#include <sound/info.h>
@@ -121,7 +122,7 @@ MODULE_FIRMWARE("riptide.hex");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
#ifdef SUPPORT_JOYSTICK
static int joystick_port[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS - 1)] = 0x200 };
@@ -2109,7 +2110,7 @@ snd_card_riptide_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
val = mpu_port[dev];
pci_write_config_word(chip->pci, PCI_EXT_MPU_Base, val);
err = snd_mpu401_uart_new(card, 0, MPU401_HW_RIPTIDE,
- val, 0, chip->irq, 0,
+ val, MPU401_INFO_IRQ_HOOK, -1,
&chip->rmidi);
if (err < 0)
snd_printk(KERN_WARNING
diff --git a/sound/pci/rme32.c b/sound/pci/rme32.c
index 6be77a264d47..b4819d5e41db 100644
--- a/sound/pci/rme32.c
+++ b/sound/pci/rme32.c
@@ -74,7 +74,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/info.h>
@@ -89,8 +89,8 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
-static int fullduplex[SNDRV_CARDS]; // = {[0 ... (SNDRV_CARDS - 1)] = 1};
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool fullduplex[SNDRV_CARDS]; // = {[0 ... (SNDRV_CARDS - 1)] = 1};
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for RME Digi32 soundcard.");
diff --git a/sound/pci/rme96.c b/sound/pci/rme96.c
index 409e5b89519d..ba894158e76c 100644
--- a/sound/pci/rme96.c
+++ b/sound/pci/rme96.c
@@ -27,7 +27,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/info.h>
@@ -53,7 +53,7 @@ MODULE_SUPPORTED_DEVICE("{{RME,Digi96},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for RME Digi96 soundcard.");
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 1c6d1e1c27c1..b68cdec03b9e 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -26,7 +26,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/firmware.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/math64.h>
#include <sound/core.h>
@@ -45,7 +45,7 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for RME Hammerfall DSP interface.");
@@ -151,7 +151,7 @@ MODULE_FIRMWARE("digiface_firmware_rev11.bin");
#define HDSP_PROGRAM 0x020
#define HDSP_CONFIG_MODE_0 0x040
#define HDSP_CONFIG_MODE_1 0x080
-#define HDSP_VERSION_BIT 0x100
+#define HDSP_VERSION_BIT (0x100 | HDSP_S_LOAD)
#define HDSP_BIGENDIAN_MODE 0x200
#define HDSP_RD_MULTIPLE 0x400
#define HDSP_9652_ENABLE_MIXER 0x800
@@ -2640,8 +2640,7 @@ static int snd_hdsp_info_pref_sync_ref(struct snd_kcontrol *kcontrol, struct snd
uinfo->value.enumerated.items = 3;
break;
default:
- uinfo->value.enumerated.items = 0;
- break;
+ return -EINVAL;
}
if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 493e3946756f..bc030a2088da 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -41,7 +41,7 @@
#include <linux/init.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <linux/pci.h>
#include <linux/math64.h>
@@ -61,7 +61,7 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for RME HDSPM interface.");
@@ -520,16 +520,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
-/* revisions >= 230 indicate AES32 card */
-#define HDSPM_MADI_ANCIENT_REV 204
-#define HDSPM_MADI_OLD_REV 207
-#define HDSPM_MADI_REV 210
#define HDSPM_RAYDAT_REV 211
#define HDSPM_AIO_REV 212
#define HDSPM_MADIFACE_REV 213
-#define HDSPM_AES_REV 240
-#define HDSPM_AES32_REV 234
-#define HDSPM_AES32_OLD_REV 233
/* speed factor modes */
#define HDSPM_SPEED_SINGLE 0
@@ -948,6 +941,8 @@ struct hdspm {
cycles_t last_interrupt;
+ unsigned int serial;
+
struct hdspm_peak_rms peak_rms;
};
@@ -1241,10 +1236,30 @@ static int hdspm_external_sample_rate(struct hdspm *hdspm)
return rate;
}
+/* return latency in samples per period */
+static int hdspm_get_latency(struct hdspm *hdspm)
+{
+ int n;
+
+ n = hdspm_decode_latency(hdspm->control_register);
+
+ /* Special case for new RME cards with 32 samples period size.
+ * The three latency bits in the control register
+ * (HDSP_LatencyMask) encode latency values of 64 samples as
+ * 0, 128 samples as 1 ... 4096 samples as 6. For old cards, 7
+ * denotes 8192 samples, but on new cards like RayDAT or AIO,
+ * it corresponds to 32 samples.
+ */
+ if ((7 == n) && (RayDAT == hdspm->io_type || AIO == hdspm->io_type))
+ n = -1;
+
+ return 1 << (n + 6);
+}
+
/* Latency function */
static inline void hdspm_compute_period_size(struct hdspm *hdspm)
{
- hdspm->period_bytes = 1 << ((hdspm_decode_latency(hdspm->control_register) + 8));
+ hdspm->period_bytes = 4 * hdspm_get_latency(hdspm);
}
@@ -1303,12 +1318,27 @@ static int hdspm_set_interrupt_interval(struct hdspm *s, unsigned int frames)
spin_lock_irq(&s->lock);
- frames >>= 7;
- n = 0;
- while (frames) {
- n++;
- frames >>= 1;
+ if (32 == frames) {
+ /* Special case for new RME cards like RayDAT/AIO which
+ * support period sizes of 32 samples. Since latency is
+ * encoded in the three bits of HDSP_LatencyMask, we can only
+ * have values from 0 .. 7. While 0 still means 64 samples and
+ * 6 represents 4096 samples on all cards, 7 represents 8192
+ * on older cards and 32 samples on new cards.
+ *
+ * In other words, period size in samples is calculated by
+ * 2^(n+6) with n ranging from 0 .. 7.
+ */
+ n = 7;
+ } else {
+ frames >>= 7;
+ n = 0;
+ while (frames) {
+ n++;
+ frames >>= 1;
+ }
}
+
s->control_register &= ~HDSPM_LatencyMask;
s->control_register |= hdspm_encode_latency(n);
@@ -4666,7 +4696,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
snd_iprintf(buffer, "HW Serial: 0x%06x%06x\n",
(hdspm_read(hdspm, HDSPM_midiStatusIn1)>>8) & 0xFFFFFF,
- (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
+ hdspm->serial);
snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
@@ -4801,8 +4831,7 @@ snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
snd_iprintf(buffer, "--- Settings ---\n");
- x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
- HDSPM_LatencyMask));
+ x = hdspm_get_latency(hdspm);
snd_iprintf(buffer,
"Size (Latency): %d samples (2 periods of %lu bytes)\n",
@@ -4965,8 +4994,7 @@ snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
snd_iprintf(buffer, "--- Settings ---\n");
- x = 1 << (6 + hdspm_decode_latency(hdspm->control_register &
- HDSPM_LatencyMask));
+ x = hdspm_get_latency(hdspm);
snd_iprintf(buffer,
"Size (Latency): %d samples (2 periods of %lu bytes)\n",
@@ -5672,19 +5700,6 @@ static int snd_hdspm_prepare(struct snd_pcm_substream *substream)
return 0;
}
-static unsigned int period_sizes_old[] = {
- 64, 128, 256, 512, 1024, 2048, 4096
-};
-
-static unsigned int period_sizes_new[] = {
- 32, 64, 128, 256, 512, 1024, 2048, 4096
-};
-
-/* RayDAT and AIO always have a buffer of 16384 samples per channel */
-static unsigned int raydat_aio_buffer_sizes[] = {
- 16384
-};
-
static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
.info = (SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
@@ -5703,8 +5718,8 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
.channels_max = HDSPM_MAX_CHANNELS,
.buffer_bytes_max =
HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
- .period_bytes_min = (64 * 4),
- .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
+ .period_bytes_min = (32 * 4),
+ .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
.periods_min = 2,
.periods_max = 512,
.fifo_size = 0
@@ -5728,31 +5743,13 @@ static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
.channels_max = HDSPM_MAX_CHANNELS,
.buffer_bytes_max =
HDSPM_CHANNEL_BUFFER_BYTES * HDSPM_MAX_CHANNELS,
- .period_bytes_min = (64 * 4),
- .period_bytes_max = (4096 * 4) * HDSPM_MAX_CHANNELS,
+ .period_bytes_min = (32 * 4),
+ .period_bytes_max = (8192 * 4) * HDSPM_MAX_CHANNELS,
.periods_min = 2,
.periods_max = 512,
.fifo_size = 0
};
-static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_old = {
- .count = ARRAY_SIZE(period_sizes_old),
- .list = period_sizes_old,
- .mask = 0
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_period_sizes_new = {
- .count = ARRAY_SIZE(period_sizes_new),
- .list = period_sizes_new,
- .mask = 0
-};
-
-static struct snd_pcm_hw_constraint_list hw_constraints_raydat_io_buffer = {
- .count = ARRAY_SIZE(raydat_aio_buffer_sizes),
- .list = raydat_aio_buffer_sizes,
- .mask = 0
-};
-
static int snd_hdspm_hw_rule_in_channels_rate(struct snd_pcm_hw_params *params,
struct snd_pcm_hw_rule *rule)
{
@@ -5953,26 +5950,29 @@ static int snd_hdspm_playback_open(struct snd_pcm_substream *substream)
spin_unlock_irq(&hdspm->lock);
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+ snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
switch (hdspm->io_type) {
case AIO:
case RayDAT:
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes_new);
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
- &hw_constraints_raydat_io_buffer);
-
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ 32, 4096);
+ /* RayDAT & AIO have a fixed buffer of 16384 samples per channel */
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ 16384, 16384);
break;
default:
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes_old);
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ 64, 8192);
+ break;
}
if (AES32 == hdspm->io_type) {
+ runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&hdspm_hw_constraints_aes32_sample_rates);
} else {
@@ -6025,24 +6025,28 @@ static int snd_hdspm_capture_open(struct snd_pcm_substream *substream)
spin_unlock_irq(&hdspm->lock);
snd_pcm_hw_constraint_msbits(runtime, 0, 32, 24);
+ snd_pcm_hw_constraint_pow2(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_SIZE);
+
switch (hdspm->io_type) {
case AIO:
case RayDAT:
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes_new);
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
- &hw_constraints_raydat_io_buffer);
- break;
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ 32, 4096);
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
+ 16384, 16384);
+ break;
default:
- snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
- &hw_constraints_period_sizes_old);
+ snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_SIZE,
+ 64, 8192);
+ break;
}
if (AES32 == hdspm->io_type) {
+ runtime->hw.rates |= SNDRV_PCM_RATE_KNOT;
snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&hdspm_hw_constraints_aes32_sample_rates);
} else {
@@ -6088,7 +6092,7 @@ static inline int copy_u32_le(void __user *dest, void __iomem *src)
}
static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
- unsigned int cmd, unsigned long __user arg)
+ unsigned int cmd, unsigned long arg)
{
void __user *argp = (void __user *)arg;
struct hdspm *hdspm = hw->private_data;
@@ -6213,11 +6217,13 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
info.line_out = hdspm_line_out(hdspm);
info.passthru = 0;
spin_unlock_irq(&hdspm->lock);
- if (copy_to_user((void __user *) arg, &info, sizeof(info)))
+ if (copy_to_user(argp, &info, sizeof(info)))
return -EFAULT;
break;
case SNDRV_HDSPM_IOCTL_GET_STATUS:
+ memset(&status, 0, sizeof(status));
+
status.card_type = hdspm->io_type;
status.autosync_source = hdspm_autosync_ref(hdspm);
@@ -6242,7 +6248,7 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
status.card_specific.madi.madi_input =
(statusregister & HDSPM_AB_int) ? 1 : 0;
status.card_specific.madi.channel_format =
- (statusregister & HDSPM_TX_64ch) ? 1 : 0;
+ (statusregister & HDSPM_RX_64ch) ? 1 : 0;
/* TODO: Mac driver sets it when f_s>48kHz */
status.card_specific.madi.frame_format = 0;
@@ -6250,30 +6256,31 @@ static int snd_hdspm_hwdep_ioctl(struct snd_hwdep *hw, struct file *file,
break;
}
- if (copy_to_user((void __user *) arg, &status, sizeof(status)))
+ if (copy_to_user(argp, &status, sizeof(status)))
return -EFAULT;
break;
case SNDRV_HDSPM_IOCTL_GET_VERSION:
+ memset(&hdspm_version, 0, sizeof(hdspm_version));
+
hdspm_version.card_type = hdspm->io_type;
strncpy(hdspm_version.cardname, hdspm->card_name,
sizeof(hdspm_version.cardname));
- hdspm_version.serial = (hdspm_read(hdspm,
- HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
+ hdspm_version.serial = hdspm->serial;
hdspm_version.firmware_rev = hdspm->firmware_rev;
hdspm_version.addons = 0;
if (hdspm->tco)
hdspm_version.addons |= HDSPM_ADDON_TCO;
- if (copy_to_user((void __user *) arg, &hdspm_version,
+ if (copy_to_user(argp, &hdspm_version,
sizeof(hdspm_version)))
return -EFAULT;
break;
case SNDRV_HDSPM_IOCTL_GET_MIXER:
- if (copy_from_user(&mixer, (void __user *)arg, sizeof(mixer)))
+ if (copy_from_user(&mixer, argp, sizeof(mixer)))
return -EFAULT;
if (copy_to_user((void __user *)mixer.mixer, hdspm->mixer,
sizeof(struct hdspm_mixer)))
@@ -6326,6 +6333,7 @@ static int __devinit snd_hdspm_create_hwdep(struct snd_card *card,
hw->ops.open = snd_hdspm_hwdep_dummy_op;
hw->ops.ioctl = snd_hdspm_hwdep_ioctl;
+ hw->ops.ioctl_compat = snd_hdspm_hwdep_ioctl;
hw->ops.release = snd_hdspm_hwdep_dummy_op;
return 0;
@@ -6490,13 +6498,6 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
strcpy(card->driver, "HDSPM");
switch (hdspm->firmware_rev) {
- case HDSPM_MADI_REV:
- case HDSPM_MADI_OLD_REV:
- case HDSPM_MADI_ANCIENT_REV:
- hdspm->io_type = MADI;
- hdspm->card_name = "RME MADI";
- hdspm->midiPorts = 3;
- break;
case HDSPM_RAYDAT_REV:
hdspm->io_type = RayDAT;
hdspm->card_name = "RME RayDAT";
@@ -6512,17 +6513,25 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
hdspm->card_name = "RME MADIface";
hdspm->midiPorts = 1;
break;
- case HDSPM_AES_REV:
- case HDSPM_AES32_REV:
- case HDSPM_AES32_OLD_REV:
- hdspm->io_type = AES32;
- hdspm->card_name = "RME AES32";
- hdspm->midiPorts = 2;
- break;
default:
- snd_printk(KERN_ERR "HDSPM: unknown firmware revision %x\n",
+ if ((hdspm->firmware_rev == 0xf0) ||
+ ((hdspm->firmware_rev >= 0xe6) &&
+ (hdspm->firmware_rev <= 0xea))) {
+ hdspm->io_type = AES32;
+ hdspm->card_name = "RME AES32";
+ hdspm->midiPorts = 2;
+ } else if ((hdspm->firmware_rev == 0xd2) ||
+ ((hdspm->firmware_rev >= 0xc8) &&
+ (hdspm->firmware_rev <= 0xcf))) {
+ hdspm->io_type = MADI;
+ hdspm->card_name = "RME MADI";
+ hdspm->midiPorts = 3;
+ } else {
+ snd_printk(KERN_ERR
+ "HDSPM: unknown firmware revision %x\n",
hdspm->firmware_rev);
- return -ENODEV;
+ return -ENODEV;
+ }
}
err = pci_enable_device(pci);
@@ -6775,6 +6784,25 @@ static int __devinit snd_hdspm_create(struct snd_card *card,
tasklet_init(&hdspm->midi_tasklet,
hdspm_midi_tasklet, (unsigned long) hdspm);
+
+ if (hdspm->io_type != MADIface) {
+ hdspm->serial = (hdspm_read(hdspm,
+ HDSPM_midiStatusIn0)>>8) & 0xFFFFFF;
+ /* id contains either a user-provided value or the default
+ * NULL. If it's the default, we're safe to
+ * fill card->id with the serial number.
+ *
+ * If the serial number is 0xFFFFFF, then we're dealing with
+ * an old PCI revision that comes without a sane number. In
+ * this case, we don't set card->id to avoid collisions
+ * when running with multiple cards.
+ */
+ if (NULL == id[hdspm->dev] && hdspm->serial != 0xFFFFFF) {
+ sprintf(card->id, "HDSPMx%06x", hdspm->serial);
+ snd_card_set_id(card, card->id);
+ }
+ }
+
snd_printdd("create alsa devices.\n");
err = snd_hdspm_create_alsa_devices(card, hdspm);
if (err < 0)
@@ -6861,10 +6889,10 @@ static int __devinit snd_hdspm_probe(struct pci_dev *pci,
if (hdspm->io_type != MADIface) {
sprintf(card->shortname, "%s_%x",
hdspm->card_name,
- (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF);
+ hdspm->serial);
sprintf(card->longname, "%s S/N 0x%x at 0x%lx, irq %d",
hdspm->card_name,
- (hdspm_read(hdspm, HDSPM_midiStatusIn0)>>8) & 0xFFFFFF,
+ hdspm->serial,
hdspm->port, hdspm->irq);
} else {
sprintf(card->shortname, "%s", hdspm->card_name);
diff --git a/sound/pci/rme9652/rme9652.c b/sound/pci/rme9652/rme9652.c
index 1c7bc1ef8186..b737d1619cc7 100644
--- a/sound/pci/rme9652/rme9652.c
+++ b/sound/pci/rme9652/rme9652.c
@@ -24,7 +24,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/pci.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -38,8 +38,8 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
-static int precise_ptr[SNDRV_CARDS]; /* Enable precise pointer */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool precise_ptr[SNDRV_CARDS]; /* Enable precise pointer */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for RME Digi9652 (Hammerfall) soundcard.");
diff --git a/sound/pci/sis7019.c b/sound/pci/sis7019.c
index bcf61524a13f..ff500a87f769 100644
--- a/sound/pci/sis7019.c
+++ b/sound/pci/sis7019.c
@@ -25,7 +25,7 @@
#include <linux/pci.h>
#include <linux/time.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/delay.h>
#include <sound/core.h>
@@ -40,7 +40,8 @@ MODULE_SUPPORTED_DEVICE("{{SiS,SiS7019 Audio Accelerator}}");
static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
-static int enable = 1;
+static bool enable = 1;
+static int codecs = 1;
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for SiS7019 Audio Accelerator.");
@@ -48,6 +49,8 @@ module_param(id, charp, 0444);
MODULE_PARM_DESC(id, "ID string for SiS7019 Audio Accelerator.");
module_param(enable, bool, 0444);
MODULE_PARM_DESC(enable, "Enable SiS7019 Audio Accelerator.");
+module_param(codecs, int, 0444);
+MODULE_PARM_DESC(codecs, "Set bit to indicate that codec number is expected to be present (default 1)");
static DEFINE_PCI_DEVICE_TABLE(snd_sis7019_ids) = {
{ PCI_DEVICE(PCI_VENDOR_ID_SI, 0x7019) },
@@ -140,6 +143,9 @@ struct sis7019 {
dma_addr_t silence_dma_addr;
};
+/* These values are also used by the module param 'codecs' to indicate
+ * which codecs should be present.
+ */
#define SIS_PRIMARY_CODEC_PRESENT 0x0001
#define SIS_SECONDARY_CODEC_PRESENT 0x0002
#define SIS_TERTIARY_CODEC_PRESENT 0x0004
@@ -977,7 +983,7 @@ timeout:
mutex_unlock(&sis->ac97_mutex);
if (!count) {
- printk(KERN_ERR "sis7019: ac97 codec %d timeout cmd 0x%08x\n",
+ dev_err(&sis->pci->dev, "ac97 codec %d timeout cmd 0x%08x\n",
codec, cmd);
}
@@ -1078,6 +1084,7 @@ static int sis_chip_init(struct sis7019 *sis)
{
unsigned long io = sis->ioport;
void __iomem *ioaddr = sis->ioaddr;
+ unsigned long timeout;
u16 status;
int count;
int i;
@@ -1104,21 +1111,45 @@ static int sis_chip_init(struct sis7019 *sis)
while ((inw(io + SIS_AC97_STATUS) & SIS_AC97_STATUS_BUSY) && --count)
udelay(1);
+ /* Command complete, we can let go of the semaphore now.
+ */
+ outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA);
+ if (!count)
+ return -EIO;
+
/* Now that we've finished the reset, find out what's attached.
+ * There are some codec/board combinations that take an extremely
+ * long time to come up. 350+ ms has been observed in the field,
+ * so we'll give them up to 500ms.
*/
- status = inl(io + SIS_AC97_STATUS);
- if (status & SIS_AC97_STATUS_CODEC_READY)
- sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT;
- if (status & SIS_AC97_STATUS_CODEC2_READY)
- sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT;
- if (status & SIS_AC97_STATUS_CODEC3_READY)
- sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT;
-
- /* All done, let go of the semaphore, and check for errors
+ sis->codecs_present = 0;
+ timeout = msecs_to_jiffies(500) + jiffies;
+ while (time_before_eq(jiffies, timeout)) {
+ status = inl(io + SIS_AC97_STATUS);
+ if (status & SIS_AC97_STATUS_CODEC_READY)
+ sis->codecs_present |= SIS_PRIMARY_CODEC_PRESENT;
+ if (status & SIS_AC97_STATUS_CODEC2_READY)
+ sis->codecs_present |= SIS_SECONDARY_CODEC_PRESENT;
+ if (status & SIS_AC97_STATUS_CODEC3_READY)
+ sis->codecs_present |= SIS_TERTIARY_CODEC_PRESENT;
+
+ if (sis->codecs_present == codecs)
+ break;
+
+ msleep(1);
+ }
+
+ /* All done, check for errors.
*/
- outl(SIS_AC97_SEMA_RELEASE, io + SIS_AC97_SEMA);
- if (!sis->codecs_present || !count)
+ if (!sis->codecs_present) {
+ dev_err(&sis->pci->dev, "could not find any codecs\n");
return -EIO;
+ }
+
+ if (sis->codecs_present != codecs) {
+ dev_warn(&sis->pci->dev, "missing codecs, found %0x, expected %0x\n",
+ sis->codecs_present, codecs);
+ }
/* Let the hardware know that the audio driver is alive,
* and enable PCM slots on the AC-link for L/R playback (3 & 4) and
@@ -1225,18 +1256,18 @@ static int sis_resume(struct pci_dev *pci)
pci_restore_state(pci);
if (pci_enable_device(pci) < 0) {
- printk(KERN_ERR "sis7019: unable to re-enable device\n");
+ dev_err(&pci->dev, "unable to re-enable device\n");
goto error;
}
if (sis_chip_init(sis)) {
- printk(KERN_ERR "sis7019: unable to re-init controller\n");
+ dev_err(&pci->dev, "unable to re-init controller\n");
goto error;
}
- if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED,
+ if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED,
KBUILD_MODNAME, sis)) {
- printk(KERN_ERR "sis7019: unable to regain IRQ %d\n", pci->irq);
+ dev_err(&pci->dev, "unable to regain IRQ %d\n", pci->irq);
goto error;
}
@@ -1304,8 +1335,7 @@ static int __devinit sis_chip_create(struct snd_card *card,
goto error_out;
if (pci_set_dma_mask(pci, DMA_BIT_MASK(30)) < 0) {
- printk(KERN_ERR "sis7019: architecture does not support "
- "30-bit PCI busmaster DMA");
+ dev_err(&pci->dev, "architecture does not support 30-bit PCI busmaster DMA");
goto error_out_enabled;
}
@@ -1319,20 +1349,20 @@ static int __devinit sis_chip_create(struct snd_card *card,
rc = pci_request_regions(pci, "SiS7019");
if (rc) {
- printk(KERN_ERR "sis7019: unable request regions\n");
+ dev_err(&pci->dev, "unable request regions\n");
goto error_out_enabled;
}
rc = -EIO;
sis->ioaddr = ioremap_nocache(pci_resource_start(pci, 1), 0x4000);
if (!sis->ioaddr) {
- printk(KERN_ERR "sis7019: unable to remap MMIO, aborting\n");
+ dev_err(&pci->dev, "unable to remap MMIO, aborting\n");
goto error_out_cleanup;
}
rc = sis_alloc_suspend(sis);
if (rc < 0) {
- printk(KERN_ERR "sis7019: unable to allocate state storage\n");
+ dev_err(&pci->dev, "unable to allocate state storage\n");
goto error_out_cleanup;
}
@@ -1340,9 +1370,9 @@ static int __devinit sis_chip_create(struct snd_card *card,
if (rc)
goto error_out_cleanup;
- if (request_irq(pci->irq, sis_interrupt, IRQF_DISABLED|IRQF_SHARED,
- KBUILD_MODNAME, sis)) {
- printk(KERN_ERR "unable to allocate irq %d\n", sis->irq);
+ if (request_irq(pci->irq, sis_interrupt, IRQF_SHARED, KBUILD_MODNAME,
+ sis)) {
+ dev_err(&pci->dev, "unable to allocate irq %d\n", sis->irq);
goto error_out_cleanup;
}
@@ -1390,6 +1420,17 @@ static int __devinit snd_sis7019_probe(struct pci_dev *pci,
if (!enable)
goto error_out;
+ /* The user can specify which codecs should be present so that we
+ * can wait for them to show up if they are slow to recover from
+ * the AC97 cold reset. We default to a single codec, the primary.
+ *
+ * We assume that SIS_PRIMARY_*_PRESENT matches bits 0-2.
+ */
+ codecs &= SIS_PRIMARY_CODEC_PRESENT | SIS_SECONDARY_CODEC_PRESENT |
+ SIS_TERTIARY_CODEC_PRESENT;
+ if (!codecs)
+ codecs = SIS_PRIMARY_CODEC_PRESENT;
+
rc = snd_card_create(index, id, THIS_MODULE, sizeof(*sis), &card);
if (rc < 0)
goto error_out;
diff --git a/sound/pci/sonicvibes.c b/sound/pci/sonicvibes.c
index 2571a67b389a..54cc802050f7 100644
--- a/sound/pci/sonicvibes.c
+++ b/sound/pci/sonicvibes.c
@@ -28,7 +28,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <sound/core.h>
@@ -52,9 +52,9 @@ MODULE_SUPPORTED_DEVICE("{{S3,SonicVibes PCI}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
-static int reverb[SNDRV_CARDS];
-static int mge[SNDRV_CARDS];
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool reverb[SNDRV_CARDS];
+static bool mge[SNDRV_CARDS];
static unsigned int dmaio = 0x7a00; /* DDMA i/o address */
module_param_array(index, int, NULL, 0444);
@@ -1493,9 +1493,10 @@ static int __devinit snd_sonic_probe(struct pci_dev *pci,
return err;
}
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_SONICVIBES,
- sonic->midi_port, MPU401_INFO_INTEGRATED,
- sonic->irq, 0,
- &midi_uart)) < 0) {
+ sonic->midi_port,
+ MPU401_INFO_INTEGRATED |
+ MPU401_INFO_IRQ_HOOK,
+ -1, &midi_uart)) < 0) {
snd_card_free(card);
return err;
}
diff --git a/sound/pci/trident/trident.c b/sound/pci/trident/trident.c
index d8a128f6fc02..5f1def7f45e5 100644
--- a/sound/pci/trident/trident.c
+++ b/sound/pci/trident/trident.c
@@ -24,7 +24,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/time.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/trident.h>
#include <sound/initval.h>
@@ -47,7 +47,7 @@ MODULE_SUPPORTED_DEVICE("{{Trident,4DWave DX},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int pcm_channels[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 32};
static int wavetable_size[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 8192};
@@ -148,8 +148,9 @@ static int __devinit snd_trident_probe(struct pci_dev *pci,
if (trident->device != TRIDENT_DEVICE_ID_SI7018 &&
(err = snd_mpu401_uart_new(card, 0, MPU401_HW_TRID4DWAVE,
trident->midi_port,
- MPU401_INFO_INTEGRATED,
- trident->irq, 0, &trident->rmidi)) < 0) {
+ MPU401_INFO_INTEGRATED |
+ MPU401_INFO_IRQ_HOOK,
+ -1, &trident->rmidi)) < 0) {
snd_card_free(card);
return err;
}
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 5bd57a7c52d2..61d3c0e8d4ce 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -35,6 +35,7 @@
#include <linux/vmalloc.h>
#include <linux/gameport.h>
#include <linux/dma-mapping.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/info.h>
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index f03fd620a2a0..75630408c6db 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -53,7 +53,7 @@
#include <linux/pci.h>
#include <linux/slab.h>
#include <linux/gameport.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -80,7 +80,7 @@ static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
static long mpu_port;
#ifdef SUPPORT_JOYSTICK
-static int joystick;
+static bool joystick;
#endif
static int ac97_clock = 48000;
static char *ac97_quirk;
@@ -110,7 +110,7 @@ module_param(nodelay, int, 0444);
MODULE_PARM_DESC(nodelay, "Disable 500ms init delay");
/* just for backward compatibility */
-static int enable;
+static bool enable;
module_param(enable, bool, 0444);
@@ -1175,6 +1175,7 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev,
struct snd_pcm_runtime *runtime = substream->runtime;
int err;
struct via_rate_lock *ratep;
+ bool use_src = false;
runtime->hw = snd_via82xx_hw;
@@ -1196,6 +1197,7 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev,
SNDRV_PCM_RATE_8000_48000);
runtime->hw.rate_min = 8000;
runtime->hw.rate_max = 48000;
+ use_src = true;
} else if (! ratep->rate) {
int idx = viadev->direction ? AC97_RATES_ADC : AC97_RATES_FRONT_DAC;
runtime->hw.rates = chip->ac97->rates[idx];
@@ -1212,6 +1214,12 @@ static int snd_via82xx_pcm_open(struct via82xx *chip, struct viadev *viadev,
if ((err = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS)) < 0)
return err;
+ if (use_src) {
+ err = snd_pcm_hw_rule_noresample(runtime, 48000);
+ if (err < 0)
+ return err;
+ }
+
runtime->private_data = viadev;
viadev->substream = substream;
@@ -2068,8 +2076,9 @@ static int __devinit snd_via686_init_misc(struct via82xx *chip)
pci_write_config_byte(chip->pci, VIA_PNP_CONTROL, legacy_cfg);
if (chip->mpu_res) {
if (snd_mpu401_uart_new(chip->card, 0, MPU401_HW_VIA686A,
- mpu_port, MPU401_INFO_INTEGRATED,
- chip->irq, 0, &chip->rmidi) < 0) {
+ mpu_port, MPU401_INFO_INTEGRATED |
+ MPU401_INFO_IRQ_HOOK, -1,
+ &chip->rmidi) < 0) {
printk(KERN_WARNING "unable to initialize MPU-401"
" at 0x%lx, skipping\n", mpu_port);
legacy &= ~VIA_FUNC_ENABLE_MIDI;
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index a386dd9f6732..5efcbcac506a 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -37,7 +37,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -66,7 +66,7 @@ module_param(ac97_clock, int, 0444);
MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
/* just for backward compatibility */
-static int enable;
+static bool enable;
module_param(enable, bool, 0444);
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 5342d5e1366a..6a534bfe1274 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -22,7 +22,7 @@
#include <linux/interrupt.h>
#include <linux/pci.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/tlv.h>
@@ -37,8 +37,8 @@ MODULE_SUPPORTED_DEVICE("{{Digigram," CARD_NAME "}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
-static int mic[SNDRV_CARDS]; /* microphone */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool mic[SNDRV_CARDS]; /* microphone */
static int ibl[SNDRV_CARDS]; /* microphone */
module_param_array(index, int, NULL, 0444);
diff --git a/sound/pci/ymfpci/ymfpci.c b/sound/pci/ymfpci/ymfpci.c
index 511d57653124..94ab728f5ca8 100644
--- a/sound/pci/ymfpci/ymfpci.c
+++ b/sound/pci/ymfpci/ymfpci.c
@@ -22,7 +22,7 @@
#include <linux/init.h>
#include <linux/pci.h>
#include <linux/time.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/ymfpci.h>
#include <sound/mpu401.h>
@@ -41,13 +41,13 @@ MODULE_SUPPORTED_DEVICE("{{Yamaha,YMF724},"
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static long fm_port[SNDRV_CARDS];
static long mpu_port[SNDRV_CARDS];
#ifdef SUPPORT_JOYSTICK
static long joystick_port[SNDRV_CARDS];
#endif
-static int rear_switch[SNDRV_CARDS];
+static bool rear_switch[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for the Yamaha DS-1 PCI soundcard.");
@@ -286,17 +286,22 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
snd_card_free(card);
return err;
}
- if ((err = snd_ymfpci_pcm_4ch(chip, 2, NULL)) < 0) {
+ err = snd_ymfpci_mixer(chip, rear_switch[dev]);
+ if (err < 0) {
snd_card_free(card);
return err;
}
- if ((err = snd_ymfpci_pcm2(chip, 3, NULL)) < 0) {
- snd_card_free(card);
- return err;
- }
- if ((err = snd_ymfpci_mixer(chip, rear_switch[dev])) < 0) {
- snd_card_free(card);
- return err;
+ if (chip->ac97->ext_id & AC97_EI_SDAC) {
+ err = snd_ymfpci_pcm_4ch(chip, 2, NULL);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ err = snd_ymfpci_pcm2(chip, 3, NULL);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
}
if ((err = snd_ymfpci_timer(chip, 0)) < 0) {
snd_card_free(card);
@@ -305,8 +310,9 @@ static int __devinit snd_card_ymfpci_probe(struct pci_dev *pci,
if (chip->mpu_res) {
if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_YMFPCI,
mpu_port[dev],
- MPU401_INFO_INTEGRATED,
- pci->irq, 0, &chip->rawmidi)) < 0) {
+ MPU401_INFO_INTEGRATED |
+ MPU401_INFO_IRQ_HOOK,
+ -1, &chip->rawmidi)) < 0) {
printk(KERN_WARNING "ymfpci: cannot initialize MPU401 at 0x%lx, skipping...\n", mpu_port[dev]);
legacy_ctrl &= ~YMFPCI_LEGACY_MIEN; /* disable MPU401 irq */
pci_write_config_word(pci, PCIR_DSXG_LEGACY, legacy_ctrl);
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index f3260e658b8a..a8159b81e9c4 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/vmalloc.h>
#include <linux/mutex.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -897,6 +898,18 @@ static int snd_ymfpci_playback_open_1(struct snd_pcm_substream *substream)
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_ymfpci_pcm *ypcm;
+ int err;
+
+ runtime->hw = snd_ymfpci_playback;
+ /* FIXME? True value is 256/48 = 5.33333 ms */
+ err = snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+ 5334, UINT_MAX);
+ if (err < 0)
+ return err;
+ err = snd_pcm_hw_rule_noresample(runtime, 48000);
+ if (err < 0)
+ return err;
ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
if (ypcm == NULL)
@@ -904,11 +917,8 @@ static int snd_ymfpci_playback_open_1(struct snd_pcm_substream *substream)
ypcm->chip = chip;
ypcm->type = PLAYBACK_VOICE;
ypcm->substream = substream;
- runtime->hw = snd_ymfpci_playback;
runtime->private_data = ypcm;
runtime->private_free = snd_ymfpci_pcm_free_substream;
- /* FIXME? True value is 256/48 = 5.33333 ms */
- snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);
return 0;
}
@@ -1013,6 +1023,18 @@ static int snd_ymfpci_capture_open(struct snd_pcm_substream *substream,
struct snd_ymfpci *chip = snd_pcm_substream_chip(substream);
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_ymfpci_pcm *ypcm;
+ int err;
+
+ runtime->hw = snd_ymfpci_capture;
+ /* FIXME? True value is 256/48 = 5.33333 ms */
+ err = snd_pcm_hw_constraint_minmax(runtime,
+ SNDRV_PCM_HW_PARAM_PERIOD_TIME,
+ 5334, UINT_MAX);
+ if (err < 0)
+ return err;
+ err = snd_pcm_hw_rule_noresample(runtime, 48000);
+ if (err < 0)
+ return err;
ypcm = kzalloc(sizeof(*ypcm), GFP_KERNEL);
if (ypcm == NULL)
@@ -1022,9 +1044,6 @@ static int snd_ymfpci_capture_open(struct snd_pcm_substream *substream,
ypcm->substream = substream;
ypcm->capture_bank_number = capture_bank_number;
chip->capture_substream[capture_bank_number] = substream;
- runtime->hw = snd_ymfpci_capture;
- /* FIXME? True value is 256/48 = 5.33333 ms */
- snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_PERIOD_TIME, 5333, UINT_MAX);
runtime->private_data = ypcm;
runtime->private_free = snd_ymfpci_pcm_free_substream;
snd_ymfpci_hw_start(chip);
@@ -1595,6 +1614,14 @@ static int snd_ymfpci_put_dup4ch(struct snd_kcontrol *kcontrol, struct snd_ctl_e
return change;
}
+static struct snd_kcontrol_new snd_ymfpci_dup4ch __devinitdata = {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "4ch Duplication",
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ymfpci_info_dup4ch,
+ .get = snd_ymfpci_get_dup4ch,
+ .put = snd_ymfpci_put_dup4ch,
+};
static struct snd_kcontrol_new snd_ymfpci_controls[] __devinitdata = {
{
@@ -1615,7 +1642,7 @@ YMFPCI_DOUBLE("ADC Playback Volume", 0, YDSXGR_PRIADCOUTVOL),
YMFPCI_DOUBLE("ADC Capture Volume", 0, YDSXGR_PRIADCLOOPVOL),
YMFPCI_DOUBLE("ADC Playback Volume", 1, YDSXGR_SECADCOUTVOL),
YMFPCI_DOUBLE("ADC Capture Volume", 1, YDSXGR_SECADCLOOPVOL),
-YMFPCI_DOUBLE("FM Legacy Volume", 0, YDSXGR_LEGACYOUTVOL),
+YMFPCI_DOUBLE("FM Legacy Playback Volume", 0, YDSXGR_LEGACYOUTVOL),
YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ", PLAYBACK,VOLUME), 0, YDSXGR_ZVOUTVOL),
YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("", CAPTURE,VOLUME), 0, YDSXGR_ZVLOOPVOL),
YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("AC97 ",PLAYBACK,VOLUME), 1, YDSXGR_SPDIFOUTVOL),
@@ -1623,13 +1650,6 @@ YMFPCI_DOUBLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,VOLUME), 1, YDSXGR_SPDIFLOOPVOL),
YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",PLAYBACK,SWITCH), 0, YDSXGR_SPDIFOUTCTRL, 0),
YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 0, YDSXGR_SPDIFINCTRL, 0),
YMFPCI_SINGLE(SNDRV_CTL_NAME_IEC958("Loop",NONE,NONE), 0, YDSXGR_SPDIFINCTRL, 4),
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "4ch Duplication",
- .info = snd_ymfpci_info_dup4ch,
- .get = snd_ymfpci_get_dup4ch,
- .put = snd_ymfpci_put_dup4ch,
-},
};
@@ -1819,6 +1839,12 @@ int __devinit snd_ymfpci_mixer(struct snd_ymfpci *chip, int rear_switch)
if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&snd_ymfpci_controls[idx], chip))) < 0)
return err;
}
+ if (chip->ac97->ext_id & AC97_EI_SDAC) {
+ kctl = snd_ctl_new1(&snd_ymfpci_dup4ch, chip);
+ err = snd_ctl_add(chip->card, kctl);
+ if (err < 0)
+ return err;
+ }
/* add S/PDIF control */
if (snd_BUG_ON(!chip->pcm_spdif))
@@ -2291,6 +2317,10 @@ int snd_ymfpci_suspend(struct pci_dev *pci, pm_message_t state)
for (i = 0; i < YDSXGR_NUM_SAVED_REGS; i++)
chip->saved_regs[i] = snd_ymfpci_readl(chip, saved_regs_index[i]);
chip->saved_ydsxgr_mode = snd_ymfpci_readl(chip, YDSXGR_MODE);
+ pci_read_config_word(chip->pci, PCIR_DSXG_LEGACY,
+ &chip->saved_dsxg_legacy);
+ pci_read_config_word(chip->pci, PCIR_DSXG_ELEGACY,
+ &chip->saved_dsxg_elegacy);
snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0);
snd_ymfpci_writel(chip, YDSXGR_BUF441OUTVOL, 0);
snd_ymfpci_disable_dsp(chip);
@@ -2325,6 +2355,11 @@ int snd_ymfpci_resume(struct pci_dev *pci)
snd_ac97_resume(chip->ac97);
+ pci_write_config_word(chip->pci, PCIR_DSXG_LEGACY,
+ chip->saved_dsxg_legacy);
+ pci_write_config_word(chip->pci, PCIR_DSXG_ELEGACY,
+ chip->saved_dsxg_elegacy);
+
/* start hw again */
if (chip->start_count > 0) {
spin_lock_irq(&chip->reg_lock);
diff --git a/sound/pcmcia/pdaudiocf/pdaudiocf.c b/sound/pcmcia/pdaudiocf/pdaudiocf.c
index 66488a7a5706..830839a874b6 100644
--- a/sound/pcmcia/pdaudiocf/pdaudiocf.c
+++ b/sound/pcmcia/pdaudiocf/pdaudiocf.c
@@ -20,7 +20,7 @@
#include <sound/core.h>
#include <linux/slab.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <pcmcia/ciscode.h>
#include <pcmcia/cisreg.h>
#include "pdaudiocf.h"
@@ -39,7 +39,7 @@ MODULE_SUPPORTED_DEVICE("{{Sound Core," CARD_NAME "}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index 31777d1ea49f..512f0b472375 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -20,7 +20,7 @@
#include <linux/init.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/slab.h>
#include <sound/core.h>
#include "vxpocket.h"
@@ -39,7 +39,7 @@ MODULE_SUPPORTED_DEVICE("{{Digigram,VXPocket},{Digigram,VXPocket440}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */
static int ibl[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
diff --git a/sound/ppc/keywest.c b/sound/ppc/keywest.c
index 8f064c7ce745..4080becf4cef 100644
--- a/sound/ppc/keywest.c
+++ b/sound/ppc/keywest.c
@@ -82,7 +82,6 @@ static int keywest_attach_adapter(struct i2c_adapter *adapter)
static int keywest_remove(struct i2c_client *client)
{
- i2c_set_clientdata(client, NULL);
if (! keywest_ctx)
return 0;
if (client == keywest_ctx->client)
diff --git a/sound/ppc/powermac.c b/sound/ppc/powermac.c
index a2b69b8cff43..5a4e263b5b0f 100644
--- a/sound/ppc/powermac.c
+++ b/sound/ppc/powermac.c
@@ -21,7 +21,7 @@
#include <linux/init.h>
#include <linux/err.h>
#include <linux/platform_device.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include "pmac.h"
@@ -36,7 +36,7 @@ MODULE_LICENSE("GPL");
static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
-static int enable_beep = 1;
+static bool enable_beep = 1;
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for " CHIP_NAME " soundchip.");
diff --git a/sound/ppc/snd_ps3.c b/sound/ppc/snd_ps3.c
index bc823a547550..1aa52eff526a 100644
--- a/sound/ppc/snd_ps3.c
+++ b/sound/ppc/snd_ps3.c
@@ -24,6 +24,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <sound/asound.h>
#include <sound/control.h>
@@ -845,7 +846,7 @@ static int __devinit snd_ps3_allocate_irq(void)
return ret;
}
- ret = request_irq(the_card.irq_no, snd_ps3_interrupt, IRQF_DISABLED,
+ ret = request_irq(the_card.irq_no, snd_ps3_interrupt, 0,
SND_PS3_DRIVER_NAME, &the_card);
if (ret) {
pr_info("%s: request_irq failed (%d)\n", __func__, ret);
@@ -875,7 +876,7 @@ static void __devinit snd_ps3_audio_set_base_addr(uint64_t ioaddr_start)
(0x0fUL << 12) |
(PS3_AUDIO_IOID);
- ret = lv1_gpu_attribute(0x100, 0x007, val, 0, 0);
+ ret = lv1_gpu_attribute(0x100, 0x007, val);
if (ret)
pr_info("%s: gpu_attribute failed %d\n", __func__,
ret);
diff --git a/sound/sh/aica.c b/sound/sh/aica.c
index 94c6ea7fa7c2..391a38ca58bc 100644
--- a/sound/sh/aica.c
+++ b/sound/sh/aica.c
@@ -29,7 +29,7 @@
#include <linux/slab.h>
#include <linux/time.h>
#include <linux/wait.h>
-#include <linux/moduleparam.h>
+#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/firmware.h>
#include <linux/timer.h>
@@ -55,7 +55,7 @@ MODULE_FIRMWARE("aica_firmware.bin");
#define CARD_NAME "AICA"
static int index = -1;
static char *id;
-static int enable = 1;
+static bool enable = 1;
module_param(index, int, 0444);
MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
module_param(id, charp, 0444);
diff --git a/sound/sh/sh_dac_audio.c b/sound/sh/sh_dac_audio.c
index 68e0dee4ff05..b11f82b5718f 100644
--- a/sound/sh/sh_dac_audio.c
+++ b/sound/sh/sh_dac_audio.c
@@ -27,6 +27,7 @@
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/initval.h>
#include <sound/pcm.h>
@@ -440,15 +441,4 @@ static struct platform_driver driver = {
},
};
-static int __init sh_dac_init(void)
-{
- return platform_driver_register(&driver);
-}
-
-static void __exit sh_dac_exit(void)
-{
- platform_driver_unregister(&driver);
-}
-
-module_init(sh_dac_init);
-module_exit(sh_dac_exit);
+module_platform_driver(driver);
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 8224db5f0434..91c985599d32 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -7,6 +7,8 @@ menuconfig SND_SOC
select SND_PCM
select AC97_BUS if SND_SOC_AC97_BUS
select SND_JACK if INPUT=y || INPUT=SND
+ select REGMAP_I2C if I2C
+ select REGMAP_SPI if SPI_MASTER
---help---
If you want ASoC support, you should say Y here and also to the
@@ -20,24 +22,12 @@ menuconfig SND_SOC
if SND_SOC
-config SND_SOC_CACHE_LZO
- bool "Support LZO compression for register caches"
- select LZO_COMPRESS
- select LZO_DECOMPRESS
- ---help---
- Select this to enable LZO compression for register caches.
- This will allow machine or CODEC drivers to compress register
- caches in memory, reducing the memory consumption at the
- expense of performance. If this is not present and is used
- the system will fall back to uncompressed caches.
-
- Usually it is safe to disable this option, where cache
- compression in used the rbtree option will typically perform
- better.
-
config SND_SOC_AC97_BUS
bool
+config SND_SOC_DMAENGINE_PCM
+ bool
+
# All the supported SoCs
source "sound/soc/atmel/Kconfig"
source "sound/soc/au1x/Kconfig"
@@ -51,6 +41,7 @@ source "sound/soc/nuc900/Kconfig"
source "sound/soc/omap/Kconfig"
source "sound/soc/kirkwood/Kconfig"
source "sound/soc/mid-x86/Kconfig"
+source "sound/soc/mxs/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/samsung/Kconfig"
source "sound/soc/s6000/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 4f913876f332..2feaf376e94b 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,6 +1,9 @@
snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o
snd-soc-core-objs += soc-pcm.o soc-io.o
+snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o
+obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o
+
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
obj-$(CONFIG_SND_SOC) += codecs/
obj-$(CONFIG_SND_SOC) += atmel/
@@ -12,6 +15,7 @@ obj-$(CONFIG_SND_SOC) += fsl/
obj-$(CONFIG_SND_SOC) += imx/
obj-$(CONFIG_SND_SOC) += jz4740/
obj-$(CONFIG_SND_SOC) += mid-x86/
+obj-$(CONFIG_SND_SOC) += mxs/
obj-$(CONFIG_SND_SOC) += nuc900/
obj-$(CONFIG_SND_SOC) += omap/
obj-$(CONFIG_SND_SOC) += kirkwood/
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
index bee3c94f58b0..72b09cfd3dc3 100644
--- a/sound/soc/atmel/Kconfig
+++ b/sound/soc/atmel/Kconfig
@@ -1,6 +1,6 @@
config SND_ATMEL_SOC
tristate "SoC Audio for the Atmel System-on-Chip"
- depends on ARCH_AT91 || AVR32
+ depends on ARCH_AT91
help
Say Y or M if you want to add support for codecs attached to
the ATMEL SSC interface. You will also need
@@ -24,28 +24,9 @@ config SND_AT91_SOC_SAM9G20_WM8731
Say Y if you want to add support for SoC audio on WM8731-based
AT91sam9g20 evaluation board.
-config SND_AT32_SOC_PLAYPAQ
- tristate "SoC Audio support for PlayPaq with WM8510"
- depends on SND_ATMEL_SOC && BOARD_PLAYPAQ && AT91_PROGRAMMABLE_CLOCKS
- select SND_ATMEL_SOC_SSC
- select SND_SOC_WM8510
- help
- Say Y or M here if you want to add support for SoC audio
- on the LRS PlayPaq.
-
-config SND_AT32_SOC_PLAYPAQ_SLAVE
- bool "Run CODEC on PlayPaq in slave mode"
- depends on SND_AT32_SOC_PLAYPAQ
- default n
- help
- Say Y if you want to run with the AT32 SSC generating the BCLK
- and FRAME signals on the PlayPaq. Unless you want to play
- with the AT32 as the SSC master, you probably want to say N here,
- as this will give you better sound quality.
-
config SND_AT91_SOC_AFEB9260
tristate "SoC Audio support for AFEB9260 board"
- depends on ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
+ depends on ATMEL_SSC && ARCH_AT91 && MACH_AFEB9260 && SND_ATMEL_SOC
select SND_ATMEL_SOC_SSC
select SND_SOC_TLV320AIC23
help
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
index e7ea56bd5f82..a5c0bf19da78 100644
--- a/sound/soc/atmel/Makefile
+++ b/sound/soc/atmel/Makefile
@@ -8,9 +8,5 @@ obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
# AT91 Machine Support
snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
-# AT32 Machine Support
-snd-soc-playpaq-objs := playpaq_wm8510.o
-
obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
-obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
obj-$(CONFIG_SND_AT91_SOC_AFEB9260) += snd-soc-afeb9260.o
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
index f81d4c3f8956..9b84f985770e 100644
--- a/sound/soc/atmel/atmel-pcm.c
+++ b/sound/soc/atmel/atmel-pcm.c
@@ -362,28 +362,27 @@ static struct snd_pcm_ops atmel_pcm_ops = {
/*--------------------------------------------------------------------------*\
* ASoC platform driver
\*--------------------------------------------------------------------------*/
-static u64 atmel_pcm_dmamask = 0xffffffff;
+static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
static int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
card->dev->dma_mask = &atmel_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = atmel_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
pr_debug("atmel-pcm:"
"Allocating PCM capture DMA buffer\n");
ret = atmel_pcm_preallocate_dma_buffer(pcm,
@@ -495,17 +494,7 @@ static struct platform_driver atmel_pcm_driver = {
.remove = __devexit_p(atmel_soc_platform_remove),
};
-static int __init snd_atmel_pcm_init(void)
-{
- return platform_driver_register(&atmel_pcm_driver);
-}
-module_init(snd_atmel_pcm_init);
-
-static void __exit snd_atmel_pcm_exit(void)
-{
- platform_driver_unregister(&atmel_pcm_driver);
-}
-module_exit(snd_atmel_pcm_exit);
+module_platform_driver(atmel_pcm_driver);
MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
MODULE_DESCRIPTION("Atmel PCM module");
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
index 71225090c49f..354341ec0f42 100644
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ b/sound/soc/atmel/atmel_ssc_dai.c
@@ -719,7 +719,7 @@ static int atmel_ssc_remove(struct snd_soc_dai *dai)
#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops atmel_ssc_dai_ops = {
+static const struct snd_soc_dai_ops atmel_ssc_dai_ops = {
.startup = atmel_ssc_startup,
.shutdown = atmel_ssc_shutdown,
.prepare = atmel_ssc_prepare,
@@ -859,17 +859,7 @@ int atmel_ssc_set_audio(int ssc_id)
}
EXPORT_SYMBOL_GPL(atmel_ssc_set_audio);
-static int __init snd_atmel_ssc_init(void)
-{
- return platform_driver_register(&asoc_ssc_driver);
-}
-module_init(snd_atmel_ssc_init);
-
-static void __exit snd_atmel_ssc_exit(void)
-{
- platform_driver_unregister(&asoc_ssc_driver);
-}
-module_exit(snd_atmel_ssc_exit);
+module_platform_driver(asoc_ssc_driver);
/* Module information */
MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/atmel/playpaq_wm8510.c
deleted file mode 100644
index 1aac2f4dbcf6..000000000000
--- a/sound/soc/atmel/playpaq_wm8510.c
+++ /dev/null
@@ -1,471 +0,0 @@
-/* sound/soc/at32/playpaq_wm8510.c
- * ASoC machine driver for PlayPaq using WM8510 codec
- *
- * Copyright (C) 2008 Long Range Systems
- * Geoffrey Wossum <gwossum@acm.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * This code is largely inspired by sound/soc/at91/eti_b1_wm8731.c
- *
- * NOTE: If you don't have the AT32 enhanced portmux configured (which
- * isn't currently in the mainline or Atmel patched kernel), you will
- * need to set the MCLK pin (PA30) to peripheral A in your board initialization
- * code. Something like:
- * at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0);
- *
- */
-
-/* #define DEBUG */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/clk.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <mach/at32ap700x.h>
-#include <mach/portmux.h>
-
-#include "../codecs/wm8510.h"
-#include "atmel-pcm.h"
-#include "atmel_ssc_dai.h"
-
-
-/*-------------------------------------------------------------------------*\
- * constants
-\*-------------------------------------------------------------------------*/
-#define MCLK_PIN GPIO_PIN_PA(30)
-#define MCLK_PERIPH GPIO_PERIPH_A
-
-
-/*-------------------------------------------------------------------------*\
- * data types
-\*-------------------------------------------------------------------------*/
-/* SSC clocking data */
-struct ssc_clock_data {
- /* CMR div */
- unsigned int cmr_div;
-
- /* Frame period (as needed by xCMR.PERIOD) */
- unsigned int period;
-
- /* The SSC clock rate these settings where calculated for */
- unsigned long ssc_rate;
-};
-
-
-/*-------------------------------------------------------------------------*\
- * module data
-\*-------------------------------------------------------------------------*/
-static struct clk *_gclk0;
-static struct clk *_pll0;
-
-#define CODEC_CLK (_gclk0)
-
-
-/*-------------------------------------------------------------------------*\
- * Sound SOC operations
-\*-------------------------------------------------------------------------*/
-#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
-static struct ssc_clock_data playpaq_wm8510_calc_ssc_clock(
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *cpu_dai)
-{
- struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
- struct ssc_device *ssc = ssc_p->ssc;
- struct ssc_clock_data cd;
- unsigned int rate, width_bits, channels;
- unsigned int bitrate, ssc_div;
- unsigned actual_rate;
-
-
- /*
- * Figure out required bitrate
- */
- rate = params_rate(params);
- channels = params_channels(params);
- width_bits = snd_pcm_format_physical_width(params_format(params));
- bitrate = rate * width_bits * channels;
-
-
- /*
- * Figure out required SSC divider and period for required bitrate
- */
- cd.ssc_rate = clk_get_rate(ssc->clk);
- ssc_div = cd.ssc_rate / bitrate;
- cd.cmr_div = ssc_div / 2;
- if (ssc_div & 1) {
- /* round cmr_div up */
- cd.cmr_div++;
- }
- cd.period = width_bits - 1;
-
-
- /*
- * Find actual rate, compare to requested rate
- */
- actual_rate = (cd.ssc_rate / (cd.cmr_div * 2)) / (2 * (cd.period + 1));
- pr_debug("playpaq_wm8510: Request rate = %u, actual rate = %u\n",
- rate, actual_rate);
-
-
- return cd;
-}
-#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
-
-
-
-static int playpaq_wm8510_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct at32_ssc_info *ssc_p = snd_soc_dai_get_drvdata(cpu_dai);
- struct ssc_device *ssc = ssc_p->ssc;
- unsigned int pll_out = 0, bclk = 0, mclk_div = 0;
- int ret;
-
-
- /* Due to difficulties with getting the correct clocks from the AT32's
- * PLL0, we're going to let the CODEC be in charge of all the clocks
- */
-#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
- const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
-#else
- struct ssc_clock_data cd;
- const unsigned int fmt = (SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
-#endif
-
- if (ssc == NULL) {
- pr_warning("playpaq_wm8510_hw_params: ssc is NULL!\n");
- return -EINVAL;
- }
-
-
- /*
- * Figure out PLL and BCLK dividers for WM8510
- */
- switch (params_rate(params)) {
- case 48000:
- pll_out = 24576000;
- mclk_div = WM8510_MCLKDIV_2;
- bclk = WM8510_BCLKDIV_8;
- break;
-
- case 44100:
- pll_out = 22579200;
- mclk_div = WM8510_MCLKDIV_2;
- bclk = WM8510_BCLKDIV_8;
- break;
-
- case 22050:
- pll_out = 22579200;
- mclk_div = WM8510_MCLKDIV_4;
- bclk = WM8510_BCLKDIV_8;
- break;
-
- case 16000:
- pll_out = 24576000;
- mclk_div = WM8510_MCLKDIV_6;
- bclk = WM8510_BCLKDIV_8;
- break;
-
- case 11025:
- pll_out = 22579200;
- mclk_div = WM8510_MCLKDIV_8;
- bclk = WM8510_BCLKDIV_8;
- break;
-
- case 8000:
- pll_out = 24576000;
- mclk_div = WM8510_MCLKDIV_12;
- bclk = WM8510_BCLKDIV_8;
- break;
-
- default:
- pr_warning("playpaq_wm8510: Unsupported sample rate %d\n",
- params_rate(params));
- return -EINVAL;
- }
-
-
- /*
- * set CPU and CODEC DAI configuration
- */
- ret = snd_soc_dai_set_fmt(codec_dai, fmt);
- if (ret < 0) {
- pr_warning("playpaq_wm8510: "
- "Failed to set CODEC DAI format (%d)\n",
- ret);
- return ret;
- }
- ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
- if (ret < 0) {
- pr_warning("playpaq_wm8510: "
- "Failed to set CPU DAI format (%d)\n",
- ret);
- return ret;
- }
-
-
- /*
- * Set CPU clock configuration
- */
-#if defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
- cd = playpaq_wm8510_calc_ssc_clock(params, cpu_dai);
- pr_debug("playpaq_wm8510: cmr_div = %d, period = %d\n",
- cd.cmr_div, cd.period);
- ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_CMR_DIV, cd.cmr_div);
- if (ret < 0) {
- pr_warning("playpaq_wm8510: Failed to set CPU CMR_DIV (%d)\n",
- ret);
- return ret;
- }
- ret = snd_soc_dai_set_clkdiv(cpu_dai, AT32_SSC_TCMR_PERIOD,
- cd.period);
- if (ret < 0) {
- pr_warning("playpaq_wm8510: "
- "Failed to set CPU transmit period (%d)\n",
- ret);
- return ret;
- }
-#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
-
-
- /*
- * Set CODEC clock configuration
- */
- pr_debug("playpaq_wm8510: "
- "pll_in = %ld, pll_out = %u, bclk = %x, mclk = %x\n",
- clk_get_rate(CODEC_CLK), pll_out, bclk, mclk_div);
-
-
-#if !defined CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE
- ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_BCLKDIV, bclk);
- if (ret < 0) {
- pr_warning
- ("playpaq_wm8510: Failed to set CODEC DAI BCLKDIV (%d)\n",
- ret);
- return ret;
- }
-#endif /* CONFIG_SND_AT32_SOC_PLAYPAQ_SLAVE */
-
-
- ret = snd_soc_dai_set_pll(codec_dai, 0, 0,
- clk_get_rate(CODEC_CLK), pll_out);
- if (ret < 0) {
- pr_warning("playpaq_wm8510: Failed to set CODEC DAI PLL (%d)\n",
- ret);
- return ret;
- }
-
-
- ret = snd_soc_dai_set_clkdiv(codec_dai, WM8510_MCLKDIV, mclk_div);
- if (ret < 0) {
- pr_warning("playpaq_wm8510: Failed to set CODEC MCLKDIV (%d)\n",
- ret);
- return ret;
- }
-
-
- return 0;
-}
-
-
-
-static struct snd_soc_ops playpaq_wm8510_ops = {
- .hw_params = playpaq_wm8510_hw_params,
-};
-
-
-
-static const struct snd_soc_dapm_widget playpaq_dapm_widgets[] = {
- SND_SOC_DAPM_MIC("Int Mic", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
-};
-
-
-
-static const struct snd_soc_dapm_route intercon[] = {
- /* speaker connected to SPKOUT */
- {"Ext Spk", NULL, "SPKOUTP"},
- {"Ext Spk", NULL, "SPKOUTN"},
-
- {"Mic Bias", NULL, "Int Mic"},
- {"MICN", NULL, "Mic Bias"},
- {"MICP", NULL, "Mic Bias"},
-};
-
-
-
-static int playpaq_wm8510_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_codec *codec = rtd->codec;
- struct snd_soc_dapm_context *dapm = &codec->dapm;
- int i;
-
- /*
- * Add DAPM widgets
- */
- for (i = 0; i < ARRAY_SIZE(playpaq_dapm_widgets); i++)
- snd_soc_dapm_new_control(dapm, &playpaq_dapm_widgets[i]);
-
-
-
- /*
- * Setup audio path interconnects
- */
- snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
-
-
- /* always connected pins */
- snd_soc_dapm_enable_pin(dapm, "Int Mic");
- snd_soc_dapm_enable_pin(dapm, "Ext Spk");
- snd_soc_dapm_sync(dapm);
-
-
-
- /* Make CSB show PLL rate */
- snd_soc_dai_set_clkdiv(rtd->codec_dai, WM8510_OPCLKDIV,
- WM8510_OPCLKDIV_1 | 4);
-
- return 0;
-}
-
-
-
-static struct snd_soc_dai_link playpaq_wm8510_dai = {
- .name = "WM8510",
- .stream_name = "WM8510 PCM",
- .cpu_dai_name= "atmel-ssc-dai.0",
- .platform_name = "atmel-pcm-audio",
- .codec_name = "wm8510-codec.0-0x1a",
- .codec_dai_name = "wm8510-hifi",
- .init = playpaq_wm8510_init,
- .ops = &playpaq_wm8510_ops,
-};
-
-
-
-static struct snd_soc_card snd_soc_playpaq = {
- .name = "LRS_PlayPaq_WM8510",
- .dai_link = &playpaq_wm8510_dai,
- .num_links = 1,
-};
-
-static struct platform_device *playpaq_snd_device;
-
-
-static int __init playpaq_asoc_init(void)
-{
- int ret = 0;
-
- /*
- * Configure MCLK for WM8510
- */
- _gclk0 = clk_get(NULL, "gclk0");
- if (IS_ERR(_gclk0)) {
- _gclk0 = NULL;
- goto err_gclk0;
- }
- _pll0 = clk_get(NULL, "pll0");
- if (IS_ERR(_pll0)) {
- _pll0 = NULL;
- goto err_pll0;
- }
- if (clk_set_parent(_gclk0, _pll0)) {
- pr_warning("snd-soc-playpaq: "
- "Failed to set PLL0 as parent for DAC clock\n");
- goto err_set_clk;
- }
- clk_set_rate(CODEC_CLK, 12000000);
- clk_enable(CODEC_CLK);
-
-#if defined CONFIG_AT32_ENHANCED_PORTMUX
- at32_select_periph(MCLK_PIN, MCLK_PERIPH, 0);
-#endif
-
-
- /*
- * Create and register platform device
- */
- playpaq_snd_device = platform_device_alloc("soc-audio", 0);
- if (playpaq_snd_device == NULL) {
- ret = -ENOMEM;
- goto err_device_alloc;
- }
-
- platform_set_drvdata(playpaq_snd_device, &snd_soc_playpaq);
-
- ret = platform_device_add(playpaq_snd_device);
- if (ret) {
- pr_warning("playpaq_wm8510: platform_device_add failed (%d)\n",
- ret);
- goto err_device_add;
- }
-
- return 0;
-
-
-err_device_add:
- if (playpaq_snd_device != NULL) {
- platform_device_put(playpaq_snd_device);
- playpaq_snd_device = NULL;
- }
-err_device_alloc:
-err_set_clk:
- if (_pll0 != NULL) {
- clk_put(_pll0);
- _pll0 = NULL;
- }
-err_pll0:
- if (_gclk0 != NULL) {
- clk_put(_gclk0);
- _gclk0 = NULL;
- }
- return ret;
-}
-
-
-static void __exit playpaq_asoc_exit(void)
-{
- if (_gclk0 != NULL) {
- clk_put(_gclk0);
- _gclk0 = NULL;
- }
- if (_pll0 != NULL) {
- clk_put(_pll0);
- _pll0 = NULL;
- }
-
-#if defined CONFIG_AT32_ENHANCED_PORTMUX
- at32_free_pin(MCLK_PIN);
-#endif
-
- platform_device_unregister(playpaq_snd_device);
- playpaq_snd_device = NULL;
-}
-
-module_init(playpaq_asoc_init);
-module_exit(playpaq_asoc_exit);
-
-MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
-MODULE_DESCRIPTION("ASoC machine driver for LRS PlayPaq");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
index bad3aa14d5b3..c88351488f45 100644
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ b/sound/soc/atmel/sam9g20_wm8731.c
@@ -173,8 +173,6 @@ static int at91sam9g20ek_wm8731_init(struct snd_soc_pcm_runtime *rtd)
/* always connected */
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -191,6 +189,7 @@ static struct snd_soc_dai_link at91sam9g20ek_dai = {
static struct snd_soc_card snd_soc_at91sam9g20ek = {
.name = "AT91SAMG20-EK",
+ .owner = THIS_MODULE,
.dai_link = &at91sam9g20ek_dai,
.num_links = 1,
.set_bias_level = at91sam9g20ek_set_bias_level,
diff --git a/sound/soc/atmel/snd-soc-afeb9260.c b/sound/soc/atmel/snd-soc-afeb9260.c
index 5e4d499d8434..f65f08beac31 100644
--- a/sound/soc/atmel/snd-soc-afeb9260.c
+++ b/sound/soc/atmel/snd-soc-afeb9260.c
@@ -46,29 +46,8 @@ static int afeb9260_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int err;
- /* Set codec DAI configuration */
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S|
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return err;
- }
-
- /* Set cpu DAI configuration */
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return err;
- }
-
/* Set the codec system clock for DAC and ADC */
err =
snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -91,7 +70,7 @@ static const struct snd_soc_dapm_widget tlv320aic23_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Mic Jack", NULL),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route afeb9260_audio_map[] = {
{"Headphone Jack", NULL, "LHPOUT"},
{"Headphone Jack", NULL, "RHPOUT"},
@@ -106,19 +85,10 @@ static int afeb9260_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- /* Add afeb9260 specific widgets */
- snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
- ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
- /* Set up afeb9260 specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Line In");
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -131,14 +101,22 @@ static struct snd_soc_dai_link afeb9260_dai = {
.platform_name = "atmel_pcm-audio",
.codec_name = "tlv320aic23-codec.0-001a",
.init = afeb9260_tlv320aic23_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &afeb9260_ops,
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_machine_afeb9260 = {
.name = "AFEB9260",
+ .owner = THIS_MODULE,
.dai_link = &afeb9260_dai,
.num_links = 1,
+
+ .dapm_widgets = tlv320aic23_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+ .dapm_routes = afeb9260_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(afeb9260_audio_map),
};
static struct platform_device *afeb9260_snd_device;
diff --git a/sound/soc/au1x/Kconfig b/sound/soc/au1x/Kconfig
index 4b67140fdec3..a56104040e83 100644
--- a/sound/soc/au1x/Kconfig
+++ b/sound/soc/au1x/Kconfig
@@ -1,13 +1,13 @@
##
-## Au1200/Au1550 PSC + DBDMA
+## Au1200/Au1550/Au1300 PSC + DBDMA
##
config SND_SOC_AU1XPSC
- tristate "SoC Audio for Au1200/Au1250/Au1550"
- depends on SOC_AU1200 || SOC_AU1550
+ tristate "SoC Audio for Au12xx/Au13xx/Au1550"
+ depends on MIPS_ALCHEMY
help
This option enables support for the Programmable Serial
Controllers in AC97 and I2S mode, and the Descriptor-Based DMA
- Controller (DBDMA) as found on the Au1200/Au1250/Au1550 SoC.
+ Controller (DBDMA) as found on the Au12xx/Au13xx/Au1550 SoC.
config SND_SOC_AU1XPSC_I2S
tristate
@@ -18,17 +18,47 @@ config SND_SOC_AU1XPSC_AC97
select SND_AC97_CODEC
select SND_SOC_AC97_BUS
+##
+## Au1000/1500/1100 DMA + AC97C/I2SC
+##
+config SND_SOC_AU1XAUDIO
+ tristate "SoC Audio for Au1000/Au1500/Au1100"
+ depends on MIPS_ALCHEMY
+ help
+ This is a driver set for the AC97 unit and the
+ old DMA controller as found on the Au1000/Au1500/Au1100 chips.
+
+config SND_SOC_AU1XAC97C
+ tristate
+ select AC97_BUS
+ select SND_AC97_CODEC
+ select SND_SOC_AC97_BUS
+
+config SND_SOC_AU1XI2SC
+ tristate
+
##
## Boards
##
+config SND_SOC_DB1000
+ tristate "DB1000 Audio support"
+ depends on SND_SOC_AU1XAUDIO
+ select SND_SOC_AU1XAC97C
+ select SND_SOC_AC97_CODEC
+ help
+ Select this option to enable AC97 audio on the early DB1x00 series
+ of boards (DB1000/DB1500/DB1100).
+
config SND_SOC_DB1200
- tristate "DB1200 AC97+I2S audio support"
+ tristate "DB1200/DB1300/DB1550 Audio support"
depends on SND_SOC_AU1XPSC
select SND_SOC_AU1XPSC_AC97
select SND_SOC_AC97_CODEC
+ select SND_SOC_WM9712
select SND_SOC_AU1XPSC_I2S
select SND_SOC_WM8731
help
- Select this option to enable audio (AC97 or I2S) on the
- Alchemy/AMD/RMI DB1200 demoboard.
+ Select this option to enable audio (AC97 and I2S) on the
+ Alchemy/AMD/RMI/NetLogic Db1200, Db1550 and Db1300 evaluation boards.
+ If you need Db1300 touchscreen support, you definitely want to say Y.
diff --git a/sound/soc/au1x/Makefile b/sound/soc/au1x/Makefile
index 16873076e8c4..920710514ea0 100644
--- a/sound/soc/au1x/Makefile
+++ b/sound/soc/au1x/Makefile
@@ -3,11 +3,21 @@ snd-soc-au1xpsc-dbdma-objs := dbdma2.o
snd-soc-au1xpsc-i2s-objs := psc-i2s.o
snd-soc-au1xpsc-ac97-objs := psc-ac97.o
+# Au1000/1500/1100 Audio units
+snd-soc-au1x-dma-objs := dma.o
+snd-soc-au1x-ac97c-objs := ac97c.o
+snd-soc-au1x-i2sc-objs := i2sc.o
+
obj-$(CONFIG_SND_SOC_AU1XPSC) += snd-soc-au1xpsc-dbdma.o
obj-$(CONFIG_SND_SOC_AU1XPSC_I2S) += snd-soc-au1xpsc-i2s.o
obj-$(CONFIG_SND_SOC_AU1XPSC_AC97) += snd-soc-au1xpsc-ac97.o
+obj-$(CONFIG_SND_SOC_AU1XAUDIO) += snd-soc-au1x-dma.o
+obj-$(CONFIG_SND_SOC_AU1XAC97C) += snd-soc-au1x-ac97c.o
+obj-$(CONFIG_SND_SOC_AU1XI2SC) += snd-soc-au1x-i2sc.o
# Boards
+snd-soc-db1000-objs := db1000.o
snd-soc-db1200-objs := db1200.o
+obj-$(CONFIG_SND_SOC_DB1000) += snd-soc-db1000.o
obj-$(CONFIG_SND_SOC_DB1200) += snd-soc-db1200.o
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c
new file mode 100644
index 000000000000..c5ac2449563a
--- /dev/null
+++ b/sound/soc/au1x/ac97c.c
@@ -0,0 +1,352 @@
+/*
+ * Au1000/Au1500/Au1100 AC97C controller driver for ASoC
+ *
+ * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
+ *
+ * based on the old ALSA driver originally written by
+ * Charles Eidsness <charles@cooper-street.com>
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/platform_device.h>
+#include <linux/suspend.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#include "psc.h"
+
+/* register offsets and bits */
+#define AC97_CONFIG 0x00
+#define AC97_STATUS 0x04
+#define AC97_DATA 0x08
+#define AC97_CMDRESP 0x0c
+#define AC97_ENABLE 0x10
+
+#define CFG_RC(x) (((x) & 0x3ff) << 13) /* valid rx slots mask */
+#define CFG_XS(x) (((x) & 0x3ff) << 3) /* valid tx slots mask */
+#define CFG_SG (1 << 2) /* sync gate */
+#define CFG_SN (1 << 1) /* sync control */
+#define CFG_RS (1 << 0) /* acrst# control */
+#define STAT_XU (1 << 11) /* tx underflow */
+#define STAT_XO (1 << 10) /* tx overflow */
+#define STAT_RU (1 << 9) /* rx underflow */
+#define STAT_RO (1 << 8) /* rx overflow */
+#define STAT_RD (1 << 7) /* codec ready */
+#define STAT_CP (1 << 6) /* command pending */
+#define STAT_TE (1 << 4) /* tx fifo empty */
+#define STAT_TF (1 << 3) /* tx fifo full */
+#define STAT_RE (1 << 1) /* rx fifo empty */
+#define STAT_RF (1 << 0) /* rx fifo full */
+#define CMD_SET_DATA(x) (((x) & 0xffff) << 16)
+#define CMD_GET_DATA(x) ((x) & 0xffff)
+#define CMD_READ (1 << 7)
+#define CMD_WRITE (0 << 7)
+#define CMD_IDX(x) ((x) & 0x7f)
+#define EN_D (1 << 1) /* DISable bit */
+#define EN_CE (1 << 0) /* clock enable bit */
+
+/* how often to retry failed codec register reads/writes */
+#define AC97_RW_RETRIES 5
+
+#define AC97_RATES \
+ SNDRV_PCM_RATE_CONTINUOUS
+
+#define AC97_FMTS \
+ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE)
+
+/* instance data. There can be only one, MacLeod!!!!, fortunately there IS only
+ * once AC97C on early Alchemy chips. The newer ones aren't so lucky.
+ */
+static struct au1xpsc_audio_data *ac97c_workdata;
+#define ac97_to_ctx(x) ac97c_workdata
+
+static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg)
+{
+ return __raw_readl(ctx->mmio + reg);
+}
+
+static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v)
+{
+ __raw_writel(v, ctx->mmio + reg);
+ wmb();
+}
+
+static unsigned short au1xac97c_ac97_read(struct snd_ac97 *ac97,
+ unsigned short r)
+{
+ struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
+ unsigned int tmo, retry;
+ unsigned long data;
+
+ data = ~0;
+ retry = AC97_RW_RETRIES;
+ do {
+ mutex_lock(&ctx->lock);
+
+ tmo = 5;
+ while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--)
+ udelay(21); /* wait an ac97 frame time */
+ if (!tmo) {
+ pr_debug("ac97rd timeout #1\n");
+ goto next;
+ }
+
+ WR(ctx, AC97_CMDRESP, CMD_IDX(r) | CMD_READ);
+
+ /* stupid errata: data is only valid for 21us, so
+ * poll, Forrest, poll...
+ */
+ tmo = 0x10000;
+ while ((RD(ctx, AC97_STATUS) & STAT_CP) && tmo--)
+ asm volatile ("nop");
+ data = RD(ctx, AC97_CMDRESP);
+
+ if (!tmo)
+ pr_debug("ac97rd timeout #2\n");
+
+next:
+ mutex_unlock(&ctx->lock);
+ } while (--retry && !tmo);
+
+ pr_debug("AC97RD %04x %04lx %d\n", r, data, retry);
+
+ return retry ? data & 0xffff : 0xffff;
+}
+
+static void au1xac97c_ac97_write(struct snd_ac97 *ac97, unsigned short r,
+ unsigned short v)
+{
+ struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
+ unsigned int tmo, retry;
+
+ retry = AC97_RW_RETRIES;
+ do {
+ mutex_lock(&ctx->lock);
+
+ for (tmo = 5; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--)
+ udelay(21);
+ if (!tmo) {
+ pr_debug("ac97wr timeout #1\n");
+ goto next;
+ }
+
+ WR(ctx, AC97_CMDRESP, CMD_WRITE | CMD_IDX(r) | CMD_SET_DATA(v));
+
+ for (tmo = 10; (RD(ctx, AC97_STATUS) & STAT_CP) && tmo; tmo--)
+ udelay(21);
+ if (!tmo)
+ pr_debug("ac97wr timeout #2\n");
+next:
+ mutex_unlock(&ctx->lock);
+ } while (--retry && !tmo);
+
+ pr_debug("AC97WR %04x %04x %d\n", r, v, retry);
+}
+
+static void au1xac97c_ac97_warm_reset(struct snd_ac97 *ac97)
+{
+ struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
+
+ WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG | CFG_SN);
+ msleep(20);
+ WR(ctx, AC97_CONFIG, ctx->cfg | CFG_SG);
+ WR(ctx, AC97_CONFIG, ctx->cfg);
+}
+
+static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97)
+{
+ struct au1xpsc_audio_data *ctx = ac97_to_ctx(ac97);
+ int i;
+
+ WR(ctx, AC97_CONFIG, ctx->cfg | CFG_RS);
+ msleep(500);
+ WR(ctx, AC97_CONFIG, ctx->cfg);
+
+ /* wait for codec ready */
+ i = 50;
+ while (((RD(ctx, AC97_STATUS) & STAT_RD) == 0) && --i)
+ msleep(20);
+ if (!i)
+ printk(KERN_ERR "ac97c: codec not ready after cold reset\n");
+}
+
+/* AC97 controller operations */
+struct snd_ac97_bus_ops soc_ac97_ops = {
+ .read = au1xac97c_ac97_read,
+ .write = au1xac97c_ac97_write,
+ .reset = au1xac97c_ac97_cold_reset,
+ .warm_reset = au1xac97c_ac97_warm_reset,
+};
+EXPORT_SYMBOL_GPL(soc_ac97_ops); /* globals be gone! */
+
+static int alchemy_ac97c_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
+ snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]);
+ return 0;
+}
+
+static const struct snd_soc_dai_ops alchemy_ac97c_ops = {
+ .startup = alchemy_ac97c_startup,
+};
+
+static int au1xac97c_dai_probe(struct snd_soc_dai *dai)
+{
+ return ac97c_workdata ? 0 : -ENODEV;
+}
+
+static struct snd_soc_dai_driver au1xac97c_dai_driver = {
+ .name = "alchemy-ac97c",
+ .ac97_control = 1,
+ .probe = au1xac97c_dai_probe,
+ .playback = {
+ .rates = AC97_RATES,
+ .formats = AC97_FMTS,
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .capture = {
+ .rates = AC97_RATES,
+ .formats = AC97_FMTS,
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .ops = &alchemy_ac97c_ops,
+};
+
+static int __devinit au1xac97c_drvprobe(struct platform_device *pdev)
+{
+ int ret;
+ struct resource *iores, *dmares;
+ struct au1xpsc_audio_data *ctx;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ mutex_init(&ctx->lock);
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores)
+ return -ENODEV;
+
+ if (!devm_request_mem_region(&pdev->dev, iores->start,
+ resource_size(iores),
+ pdev->name))
+ return -EBUSY;
+
+ ctx->mmio = devm_ioremap_nocache(&pdev->dev, iores->start,
+ resource_size(iores));
+ if (!ctx->mmio)
+ return -EBUSY;
+
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dmares)
+ return -EBUSY;
+ ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
+
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!dmares)
+ return -EBUSY;
+ ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
+
+ /* switch it on */
+ WR(ctx, AC97_ENABLE, EN_D | EN_CE);
+ WR(ctx, AC97_ENABLE, EN_CE);
+
+ ctx->cfg = CFG_RC(3) | CFG_XS(3);
+ WR(ctx, AC97_CONFIG, ctx->cfg);
+
+ platform_set_drvdata(pdev, ctx);
+
+ ret = snd_soc_register_dai(&pdev->dev, &au1xac97c_dai_driver);
+ if (ret)
+ return ret;
+
+ ac97c_workdata = ctx;
+ return 0;
+}
+
+static int __devexit au1xac97c_drvremove(struct platform_device *pdev)
+{
+ struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_dai(&pdev->dev);
+
+ WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */
+
+ ac97c_workdata = NULL; /* MDEV */
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int au1xac97c_drvsuspend(struct device *dev)
+{
+ struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev);
+
+ WR(ctx, AC97_ENABLE, EN_D); /* clock off, disable */
+
+ return 0;
+}
+
+static int au1xac97c_drvresume(struct device *dev)
+{
+ struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev);
+
+ WR(ctx, AC97_ENABLE, EN_D | EN_CE);
+ WR(ctx, AC97_ENABLE, EN_CE);
+ WR(ctx, AC97_CONFIG, ctx->cfg);
+
+ return 0;
+}
+
+static const struct dev_pm_ops au1xpscac97_pmops = {
+ .suspend = au1xac97c_drvsuspend,
+ .resume = au1xac97c_drvresume,
+};
+
+#define AU1XPSCAC97_PMOPS (&au1xpscac97_pmops)
+
+#else
+
+#define AU1XPSCAC97_PMOPS NULL
+
+#endif
+
+static struct platform_driver au1xac97c_driver = {
+ .driver = {
+ .name = "alchemy-ac97c",
+ .owner = THIS_MODULE,
+ .pm = AU1XPSCAC97_PMOPS,
+ },
+ .probe = au1xac97c_drvprobe,
+ .remove = __devexit_p(au1xac97c_drvremove),
+};
+
+static int __init au1xac97c_load(void)
+{
+ ac97c_workdata = NULL;
+ return platform_driver_register(&au1xac97c_driver);
+}
+
+static void __exit au1xac97c_unload(void)
+{
+ platform_driver_unregister(&au1xac97c_driver);
+}
+
+module_init(au1xac97c_load);
+module_exit(au1xac97c_unload);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver");
+MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/db1000.c b/sound/soc/au1x/db1000.c
new file mode 100644
index 000000000000..511d83c11a9a
--- /dev/null
+++ b/sound/soc/au1x/db1000.c
@@ -0,0 +1,65 @@
+/*
+ * DB1000/DB1500/DB1100 ASoC audio fabric support code.
+ *
+ * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-db1x00/bcsr.h>
+
+#include "psc.h"
+
+static struct snd_soc_dai_link db1000_ac97_dai = {
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .codec_dai_name = "ac97-hifi",
+ .cpu_dai_name = "alchemy-ac97c",
+ .platform_name = "alchemy-pcm-dma.0",
+ .codec_name = "ac97-codec",
+};
+
+static struct snd_soc_card db1000_ac97 = {
+ .name = "DB1000_AC97",
+ .owner = THIS_MODULE,
+ .dai_link = &db1000_ac97_dai,
+ .num_links = 1,
+};
+
+static int __devinit db1000_audio_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &db1000_ac97;
+ card->dev = &pdev->dev;
+ return snd_soc_register_card(card);
+}
+
+static int __devexit db1000_audio_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ snd_soc_unregister_card(card);
+ return 0;
+}
+
+static struct platform_driver db1000_audio_driver = {
+ .driver = {
+ .name = "db1000-audio",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = db1000_audio_probe,
+ .remove = __devexit_p(db1000_audio_remove),
+};
+
+module_platform_driver(db1000_audio_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DB1000/DB1500/DB1100 ASoC audio");
+MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/db1200.c b/sound/soc/au1x/db1200.c
index 1d3e258c9ea8..30ea513d81d7 100644
--- a/sound/soc/au1x/db1200.c
+++ b/sound/soc/au1x/db1200.c
@@ -1,7 +1,7 @@
/*
- * DB1200 ASoC audio fabric support code.
+ * DB1200/DB1300/DB1550 ASoC audio fabric support code.
*
- * (c) 2008-9 Manuel Lauss <manuel.lauss@gmail.com>
+ * (c) 2008-2011 Manuel Lauss <manuel.lauss@googlemail.com>
*
*/
@@ -21,6 +21,29 @@
#include "../codecs/wm8731.h"
#include "psc.h"
+static struct platform_device_id db1200_pids[] = {
+ {
+ .name = "db1200-ac97",
+ .driver_data = 0,
+ }, {
+ .name = "db1200-i2s",
+ .driver_data = 1,
+ }, {
+ .name = "db1300-ac97",
+ .driver_data = 2,
+ }, {
+ .name = "db1300-i2s",
+ .driver_data = 3,
+ }, {
+ .name = "db1550-ac97",
+ .driver_data = 4,
+ }, {
+ .name = "db1550-i2s",
+ .driver_data = 5,
+ },
+ {},
+};
+
/*------------------------- AC97 PART ---------------------------*/
static struct snd_soc_dai_link db1200_ac97_dai = {
@@ -34,6 +57,28 @@ static struct snd_soc_dai_link db1200_ac97_dai = {
static struct snd_soc_card db1200_ac97_machine = {
.name = "DB1200_AC97",
+ .owner = THIS_MODULE,
+ .dai_link = &db1200_ac97_dai,
+ .num_links = 1,
+};
+
+static struct snd_soc_dai_link db1300_ac97_dai = {
+ .name = "AC97",
+ .stream_name = "AC97 HiFi",
+ .codec_dai_name = "wm9712-hifi",
+ .cpu_dai_name = "au1xpsc_ac97.1",
+ .platform_name = "au1xpsc-pcm.1",
+ .codec_name = "wm9712-codec.1",
+};
+
+static struct snd_soc_card db1300_ac97_machine = {
+ .name = "DB1300_AC97",
+ .dai_link = &db1300_ac97_dai,
+ .num_links = 1,
+};
+
+static struct snd_soc_card db1550_ac97_machine = {
+ .name = "DB1550_AC97",
.dai_link = &db1200_ac97_dai,
.num_links = 1,
};
@@ -83,47 +128,84 @@ static struct snd_soc_dai_link db1200_i2s_dai = {
static struct snd_soc_card db1200_i2s_machine = {
.name = "DB1200_I2S",
+ .owner = THIS_MODULE,
.dai_link = &db1200_i2s_dai,
.num_links = 1,
};
-/*------------------------- COMMON PART ---------------------------*/
+static struct snd_soc_dai_link db1300_i2s_dai = {
+ .name = "WM8731",
+ .stream_name = "WM8731 PCM",
+ .codec_dai_name = "wm8731-hifi",
+ .cpu_dai_name = "au1xpsc_i2s.2",
+ .platform_name = "au1xpsc-pcm.2",
+ .codec_name = "wm8731.0-001b",
+ .ops = &db1200_i2s_wm8731_ops,
+};
-static struct platform_device *db1200_asoc_dev;
+static struct snd_soc_card db1300_i2s_machine = {
+ .name = "DB1300_I2S",
+ .dai_link = &db1300_i2s_dai,
+ .num_links = 1,
+};
-static int __init db1200_audio_load(void)
-{
- int ret;
+static struct snd_soc_dai_link db1550_i2s_dai = {
+ .name = "WM8731",
+ .stream_name = "WM8731 PCM",
+ .codec_dai_name = "wm8731-hifi",
+ .cpu_dai_name = "au1xpsc_i2s.3",
+ .platform_name = "au1xpsc-pcm.3",
+ .codec_name = "wm8731.0-001b",
+ .ops = &db1200_i2s_wm8731_ops,
+};
- ret = -ENOMEM;
- db1200_asoc_dev = platform_device_alloc("soc-audio", 1); /* PSC1 */
- if (!db1200_asoc_dev)
- goto out;
+static struct snd_soc_card db1550_i2s_machine = {
+ .name = "DB1550_I2S",
+ .dai_link = &db1550_i2s_dai,
+ .num_links = 1,
+};
- /* DB1200 board setup set PSC1MUX to preferred audio device */
- if (bcsr_read(BCSR_RESETS) & BCSR_RESETS_PSC1MUX)
- platform_set_drvdata(db1200_asoc_dev, &db1200_i2s_machine);
- else
- platform_set_drvdata(db1200_asoc_dev, &db1200_ac97_machine);
+/*------------------------- COMMON PART ---------------------------*/
- ret = platform_device_add(db1200_asoc_dev);
+static struct snd_soc_card *db1200_cards[] __devinitdata = {
+ &db1200_ac97_machine,
+ &db1200_i2s_machine,
+ &db1300_ac97_machine,
+ &db1300_i2s_machine,
+ &db1550_ac97_machine,
+ &db1550_i2s_machine,
+};
- if (ret) {
- platform_device_put(db1200_asoc_dev);
- db1200_asoc_dev = NULL;
- }
-out:
- return ret;
+static int __devinit db1200_audio_probe(struct platform_device *pdev)
+{
+ const struct platform_device_id *pid = platform_get_device_id(pdev);
+ struct snd_soc_card *card;
+
+ card = db1200_cards[pid->driver_data];
+ card->dev = &pdev->dev;
+ return snd_soc_register_card(card);
}
-static void __exit db1200_audio_unload(void)
+static int __devexit db1200_audio_remove(struct platform_device *pdev)
{
- platform_device_unregister(db1200_asoc_dev);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(db1200_audio_load);
-module_exit(db1200_audio_unload);
+static struct platform_driver db1200_audio_driver = {
+ .driver = {
+ .name = "db1200-ac97",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+ .id_table = db1200_pids,
+ .probe = db1200_audio_probe,
+ .remove = __devexit_p(db1200_audio_remove),
+};
+
+module_platform_driver(db1200_audio_driver);
MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("DB1200 ASoC audio support");
+MODULE_DESCRIPTION("DB1200/DB1300/DB1550 ASoC audio support");
MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 20bb53a837b1..8372cd35f0d6 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -169,7 +169,7 @@ static int au1x_pcm_dbdma_realloc(struct au1xpsc_audio_dmadata *pcd,
au1x_pcm_dbdma_free(pcd);
- if (stype == PCM_RX)
+ if (stype == SNDRV_PCM_STREAM_CAPTURE)
pcd->ddma_chan = au1xxx_dbdma_chan_alloc(pcd->ddma_id,
DSCR_CMD0_ALWAYS,
au1x_pcm_dmarx_cb, (void *)pcd);
@@ -198,7 +198,7 @@ static inline struct au1xpsc_audio_dmadata *to_dmadata(struct snd_pcm_substream
struct snd_soc_pcm_runtime *rtd = ss->private_data;
struct au1xpsc_audio_dmadata *pcd =
snd_soc_platform_get_drvdata(rtd->platform);
- return &pcd[SUBSTREAM_TYPE(ss)];
+ return &pcd[ss->stream];
}
static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
@@ -212,7 +212,7 @@ static int au1xpsc_pcm_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
goto out;
- stype = SUBSTREAM_TYPE(substream);
+ stype = substream->stream;
pcd = to_dmadata(substream);
DBG("runtime->dma_area = 0x%08lx dma_addr_t = 0x%08lx dma_size = %d "
@@ -255,7 +255,7 @@ static int au1xpsc_pcm_prepare(struct snd_pcm_substream *substream)
au1xxx_dbdma_reset(pcd->ddma_chan);
- if (SUBSTREAM_TYPE(substream) == PCM_RX) {
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
au1x_pcm_queue_rx(pcd);
au1x_pcm_queue_rx(pcd);
} else {
@@ -293,6 +293,16 @@ au1xpsc_pcm_pointer(struct snd_pcm_substream *substream)
static int au1xpsc_pcm_open(struct snd_pcm_substream *substream)
{
+ struct au1xpsc_audio_dmadata *pcd = to_dmadata(substream);
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int stype = substream->stream, *dmaids;
+
+ dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ if (!dmaids)
+ return -ENODEV; /* whoa, has ordering changed? */
+
+ pcd->ddma_id = dmaids[stype];
+
snd_soc_set_runtime_hwparams(substream, &au1xpsc_pcm_hardware);
return 0;
}
@@ -331,7 +341,7 @@ static int au1xpsc_pcm_new(struct snd_soc_pcm_runtime *rtd)
}
/* au1xpsc audio platform */
-struct snd_soc_platform_driver au1xpsc_soc_platform = {
+static struct snd_soc_platform_driver au1xpsc_soc_platform = {
.ops = &au1xpsc_pcm_ops,
.pcm_new = au1xpsc_pcm_new,
.pcm_free = au1xpsc_pcm_free_dma_buffers,
@@ -340,45 +350,21 @@ struct snd_soc_platform_driver au1xpsc_soc_platform = {
static int __devinit au1xpsc_pcm_drvprobe(struct platform_device *pdev)
{
struct au1xpsc_audio_dmadata *dmadata;
- struct resource *r;
- int ret;
- dmadata = kzalloc(2 * sizeof(struct au1xpsc_audio_dmadata), GFP_KERNEL);
+ dmadata = devm_kzalloc(&pdev->dev,
+ 2 * sizeof(struct au1xpsc_audio_dmadata),
+ GFP_KERNEL);
if (!dmadata)
return -ENOMEM;
- r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!r) {
- ret = -ENODEV;
- goto out1;
- }
- dmadata[PCM_TX].ddma_id = r->start;
-
- /* RX DMA */
- r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (!r) {
- ret = -ENODEV;
- goto out1;
- }
- dmadata[PCM_RX].ddma_id = r->start;
-
platform_set_drvdata(pdev, dmadata);
- ret = snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
- if (!ret)
- return ret;
-
-out1:
- kfree(dmadata);
- return ret;
+ return snd_soc_register_platform(&pdev->dev, &au1xpsc_soc_platform);
}
static int __devexit au1xpsc_pcm_drvremove(struct platform_device *pdev)
{
- struct au1xpsc_audio_dmadata *dmadata = platform_get_drvdata(pdev);
-
snd_soc_unregister_platform(&pdev->dev);
- kfree(dmadata);
return 0;
}
@@ -392,69 +378,7 @@ static struct platform_driver au1xpsc_pcm_driver = {
.remove = __devexit_p(au1xpsc_pcm_drvremove),
};
-static int __init au1xpsc_audio_dbdma_load(void)
-{
- return platform_driver_register(&au1xpsc_pcm_driver);
-}
-
-static void __exit au1xpsc_audio_dbdma_unload(void)
-{
- platform_driver_unregister(&au1xpsc_pcm_driver);
-}
-
-module_init(au1xpsc_audio_dbdma_load);
-module_exit(au1xpsc_audio_dbdma_unload);
-
-
-struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev)
-{
- struct resource *res, *r;
- struct platform_device *pd;
- int id[2];
- int ret;
-
- r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
- if (!r)
- return NULL;
- id[0] = r->start;
-
- r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
- if (!r)
- return NULL;
- id[1] = r->start;
-
- res = kzalloc(sizeof(struct resource) * 2, GFP_KERNEL);
- if (!res)
- return NULL;
-
- res[0].start = res[0].end = id[0];
- res[1].start = res[1].end = id[1];
- res[0].flags = res[1].flags = IORESOURCE_DMA;
-
- pd = platform_device_alloc("au1xpsc-pcm", pdev->id);
- if (!pd)
- goto out;
-
- pd->resource = res;
- pd->num_resources = 2;
-
- ret = platform_device_add(pd);
- if (!ret)
- return pd;
-
- platform_device_put(pd);
-out:
- kfree(res);
- return NULL;
-}
-EXPORT_SYMBOL_GPL(au1xpsc_pcm_add);
-
-void au1xpsc_pcm_destroy(struct platform_device *dmapd)
-{
- if (dmapd)
- platform_device_unregister(dmapd);
-}
-EXPORT_SYMBOL_GPL(au1xpsc_pcm_destroy);
+module_platform_driver(au1xpsc_pcm_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Au12x0/Au1550 PSC Audio DMA driver");
diff --git a/sound/soc/au1x/dma.c b/sound/soc/au1x/dma.c
new file mode 100644
index 000000000000..0a91b186a86f
--- /dev/null
+++ b/sound/soc/au1x/dma.c
@@ -0,0 +1,358 @@
+/*
+ * Au1000/Au1500/Au1100 Audio DMA support.
+ *
+ * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
+ *
+ * copied almost verbatim from the old ALSA driver, written by
+ * Charles Eidsness <charles@cooper-street.com>
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+#include <asm/mach-au1x00/au1000_dma.h>
+
+#include "psc.h"
+
+#define ALCHEMY_PCM_FMTS \
+ (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \
+ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
+ SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \
+ SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_S32_BE | \
+ SNDRV_PCM_FMTBIT_U32_LE | SNDRV_PCM_FMTBIT_U32_BE | \
+ 0)
+
+struct pcm_period {
+ u32 start;
+ u32 relative_end; /* relative to start of buffer */
+ struct pcm_period *next;
+};
+
+struct audio_stream {
+ struct snd_pcm_substream *substream;
+ int dma;
+ struct pcm_period *buffer;
+ unsigned int period_size;
+ unsigned int periods;
+};
+
+struct alchemy_pcm_ctx {
+ struct audio_stream stream[2]; /* playback & capture */
+};
+
+static void au1000_release_dma_link(struct audio_stream *stream)
+{
+ struct pcm_period *pointer;
+ struct pcm_period *pointer_next;
+
+ stream->period_size = 0;
+ stream->periods = 0;
+ pointer = stream->buffer;
+ if (!pointer)
+ return;
+ do {
+ pointer_next = pointer->next;
+ kfree(pointer);
+ pointer = pointer_next;
+ } while (pointer != stream->buffer);
+ stream->buffer = NULL;
+}
+
+static int au1000_setup_dma_link(struct audio_stream *stream,
+ unsigned int period_bytes,
+ unsigned int periods)
+{
+ struct snd_pcm_substream *substream = stream->substream;
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct pcm_period *pointer;
+ unsigned long dma_start;
+ int i;
+
+ dma_start = virt_to_phys(runtime->dma_area);
+
+ if (stream->period_size == period_bytes &&
+ stream->periods == periods)
+ return 0; /* not changed */
+
+ au1000_release_dma_link(stream);
+
+ stream->period_size = period_bytes;
+ stream->periods = periods;
+
+ stream->buffer = kmalloc(sizeof(struct pcm_period), GFP_KERNEL);
+ if (!stream->buffer)
+ return -ENOMEM;
+ pointer = stream->buffer;
+ for (i = 0; i < periods; i++) {
+ pointer->start = (u32)(dma_start + (i * period_bytes));
+ pointer->relative_end = (u32) (((i+1) * period_bytes) - 0x1);
+ if (i < periods - 1) {
+ pointer->next = kmalloc(sizeof(struct pcm_period),
+ GFP_KERNEL);
+ if (!pointer->next) {
+ au1000_release_dma_link(stream);
+ return -ENOMEM;
+ }
+ pointer = pointer->next;
+ }
+ }
+ pointer->next = stream->buffer;
+ return 0;
+}
+
+static void au1000_dma_stop(struct audio_stream *stream)
+{
+ if (stream->buffer)
+ disable_dma(stream->dma);
+}
+
+static void au1000_dma_start(struct audio_stream *stream)
+{
+ if (!stream->buffer)
+ return;
+
+ init_dma(stream->dma);
+ if (get_dma_active_buffer(stream->dma) == 0) {
+ clear_dma_done0(stream->dma);
+ set_dma_addr0(stream->dma, stream->buffer->start);
+ set_dma_count0(stream->dma, stream->period_size >> 1);
+ set_dma_addr1(stream->dma, stream->buffer->next->start);
+ set_dma_count1(stream->dma, stream->period_size >> 1);
+ } else {
+ clear_dma_done1(stream->dma);
+ set_dma_addr1(stream->dma, stream->buffer->start);
+ set_dma_count1(stream->dma, stream->period_size >> 1);
+ set_dma_addr0(stream->dma, stream->buffer->next->start);
+ set_dma_count0(stream->dma, stream->period_size >> 1);
+ }
+ enable_dma_buffers(stream->dma);
+ start_dma(stream->dma);
+}
+
+static irqreturn_t au1000_dma_interrupt(int irq, void *ptr)
+{
+ struct audio_stream *stream = (struct audio_stream *)ptr;
+ struct snd_pcm_substream *substream = stream->substream;
+
+ switch (get_dma_buffer_done(stream->dma)) {
+ case DMA_D0:
+ stream->buffer = stream->buffer->next;
+ clear_dma_done0(stream->dma);
+ set_dma_addr0(stream->dma, stream->buffer->next->start);
+ set_dma_count0(stream->dma, stream->period_size >> 1);
+ enable_dma_buffer0(stream->dma);
+ break;
+ case DMA_D1:
+ stream->buffer = stream->buffer->next;
+ clear_dma_done1(stream->dma);
+ set_dma_addr1(stream->dma, stream->buffer->next->start);
+ set_dma_count1(stream->dma, stream->period_size >> 1);
+ enable_dma_buffer1(stream->dma);
+ break;
+ case (DMA_D0 | DMA_D1):
+ pr_debug("DMA %d missed interrupt.\n", stream->dma);
+ au1000_dma_stop(stream);
+ au1000_dma_start(stream);
+ break;
+ case (~DMA_D0 & ~DMA_D1):
+ pr_debug("DMA %d empty irq.\n", stream->dma);
+ }
+ snd_pcm_period_elapsed(substream);
+ return IRQ_HANDLED;
+}
+
+static const struct snd_pcm_hardware alchemy_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_BATCH,
+ .formats = ALCHEMY_PCM_FMTS,
+ .rates = SNDRV_PCM_RATE_8000_192000,
+ .rate_min = SNDRV_PCM_RATE_8000,
+ .rate_max = SNDRV_PCM_RATE_192000,
+ .channels_min = 2,
+ .channels_max = 2,
+ .period_bytes_min = 1024,
+ .period_bytes_max = 16 * 1024 - 1,
+ .periods_min = 4,
+ .periods_max = 255,
+ .buffer_bytes_max = 128 * 1024,
+ .fifo_size = 16,
+};
+
+static inline struct alchemy_pcm_ctx *ss_to_ctx(struct snd_pcm_substream *ss)
+{
+ struct snd_soc_pcm_runtime *rtd = ss->private_data;
+ return snd_soc_platform_get_drvdata(rtd->platform);
+}
+
+static inline struct audio_stream *ss_to_as(struct snd_pcm_substream *ss)
+{
+ struct alchemy_pcm_ctx *ctx = ss_to_ctx(ss);
+ return &(ctx->stream[ss->stream]);
+}
+
+static int alchemy_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream);
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int *dmaids, s = substream->stream;
+ char *name;
+
+ dmaids = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ if (!dmaids)
+ return -ENODEV; /* whoa, has ordering changed? */
+
+ /* DMA setup */
+ name = (s == SNDRV_PCM_STREAM_PLAYBACK) ? "audio-tx" : "audio-rx";
+ ctx->stream[s].dma = request_au1000_dma(dmaids[s], name,
+ au1000_dma_interrupt, 0,
+ &ctx->stream[s]);
+ set_dma_mode(ctx->stream[s].dma,
+ get_dma_mode(ctx->stream[s].dma) & ~DMA_NC);
+
+ ctx->stream[s].substream = substream;
+ ctx->stream[s].buffer = NULL;
+ snd_soc_set_runtime_hwparams(substream, &alchemy_pcm_hardware);
+
+ return 0;
+}
+
+static int alchemy_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct alchemy_pcm_ctx *ctx = ss_to_ctx(substream);
+ int stype = substream->stream;
+
+ ctx->stream[stype].substream = NULL;
+ free_au1000_dma(ctx->stream[stype].dma);
+
+ return 0;
+}
+
+static int alchemy_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *hw_params)
+{
+ struct audio_stream *stream = ss_to_as(substream);
+ int err;
+
+ err = snd_pcm_lib_malloc_pages(substream,
+ params_buffer_bytes(hw_params));
+ if (err < 0)
+ return err;
+ err = au1000_setup_dma_link(stream,
+ params_period_bytes(hw_params),
+ params_periods(hw_params));
+ if (err)
+ snd_pcm_lib_free_pages(substream);
+
+ return err;
+}
+
+static int alchemy_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct audio_stream *stream = ss_to_as(substream);
+ au1000_release_dma_link(stream);
+ return snd_pcm_lib_free_pages(substream);
+}
+
+static int alchemy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct audio_stream *stream = ss_to_as(substream);
+ int err = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ au1000_dma_start(stream);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ au1000_dma_stop(stream);
+ break;
+ default:
+ err = -EINVAL;
+ break;
+ }
+ return err;
+}
+
+static snd_pcm_uframes_t alchemy_pcm_pointer(struct snd_pcm_substream *ss)
+{
+ struct audio_stream *stream = ss_to_as(ss);
+ long location;
+
+ location = get_dma_residue(stream->dma);
+ location = stream->buffer->relative_end - location;
+ if (location == -1)
+ location = 0;
+ return bytes_to_frames(ss->runtime, location);
+}
+
+static struct snd_pcm_ops alchemy_pcm_ops = {
+ .open = alchemy_pcm_open,
+ .close = alchemy_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = alchemy_pcm_hw_params,
+ .hw_free = alchemy_pcm_hw_free,
+ .trigger = alchemy_pcm_trigger,
+ .pointer = alchemy_pcm_pointer,
+};
+
+static void alchemy_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+ snd_pcm_lib_preallocate_free_for_all(pcm);
+}
+
+static int alchemy_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_pcm *pcm = rtd->pcm;
+
+ snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
+ snd_dma_continuous_data(GFP_KERNEL), 65536, (4096 * 1024) - 1);
+
+ return 0;
+}
+
+static struct snd_soc_platform_driver alchemy_pcm_soc_platform = {
+ .ops = &alchemy_pcm_ops,
+ .pcm_new = alchemy_pcm_new,
+ .pcm_free = alchemy_pcm_free_dma_buffers,
+};
+
+static int __devinit alchemy_pcm_drvprobe(struct platform_device *pdev)
+{
+ struct alchemy_pcm_ctx *ctx;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, ctx);
+
+ return snd_soc_register_platform(&pdev->dev, &alchemy_pcm_soc_platform);
+}
+
+static int __devexit alchemy_pcm_drvremove(struct platform_device *pdev)
+{
+ snd_soc_unregister_platform(&pdev->dev);
+
+ return 0;
+}
+
+static struct platform_driver alchemy_pcmdma_driver = {
+ .driver = {
+ .name = "alchemy-pcm-dma",
+ .owner = THIS_MODULE,
+ },
+ .probe = alchemy_pcm_drvprobe,
+ .remove = __devexit_p(alchemy_pcm_drvremove),
+};
+
+module_platform_driver(alchemy_pcmdma_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au1000/Au1500/Au1100 Audio DMA driver");
+MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/i2sc.c b/sound/soc/au1x/i2sc.c
new file mode 100644
index 000000000000..d4b9e364a47a
--- /dev/null
+++ b/sound/soc/au1x/i2sc.c
@@ -0,0 +1,319 @@
+/*
+ * Au1000/Au1500/Au1100 I2S controller driver for ASoC
+ *
+ * (c) 2011 Manuel Lauss <manuel.lauss@googlemail.com>
+ *
+ * Note: clock supplied to the I2S controller must be 256x samplerate.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/suspend.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+#include <asm/mach-au1x00/au1000.h>
+
+#include "psc.h"
+
+#define I2S_RXTX 0x00
+#define I2S_CFG 0x04
+#define I2S_ENABLE 0x08
+
+#define CFG_XU (1 << 25) /* tx underflow */
+#define CFG_XO (1 << 24)
+#define CFG_RU (1 << 23)
+#define CFG_RO (1 << 22)
+#define CFG_TR (1 << 21)
+#define CFG_TE (1 << 20)
+#define CFG_TF (1 << 19)
+#define CFG_RR (1 << 18)
+#define CFG_RF (1 << 17)
+#define CFG_ICK (1 << 12) /* clock invert */
+#define CFG_PD (1 << 11) /* set to make I2SDIO INPUT */
+#define CFG_LB (1 << 10) /* loopback */
+#define CFG_IC (1 << 9) /* word select invert */
+#define CFG_FM_I2S (0 << 7) /* I2S format */
+#define CFG_FM_LJ (1 << 7) /* left-justified */
+#define CFG_FM_RJ (2 << 7) /* right-justified */
+#define CFG_FM_MASK (3 << 7)
+#define CFG_TN (1 << 6) /* tx fifo en */
+#define CFG_RN (1 << 5) /* rx fifo en */
+#define CFG_SZ_8 (0x08)
+#define CFG_SZ_16 (0x10)
+#define CFG_SZ_18 (0x12)
+#define CFG_SZ_20 (0x14)
+#define CFG_SZ_24 (0x18)
+#define CFG_SZ_MASK (0x1f)
+#define EN_D (1 << 1) /* DISable */
+#define EN_CE (1 << 0) /* clock enable */
+
+/* only limited by clock generator and board design */
+#define AU1XI2SC_RATES \
+ SNDRV_PCM_RATE_CONTINUOUS
+
+#define AU1XI2SC_FMTS \
+ (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_U8 | \
+ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE | \
+ SNDRV_PCM_FMTBIT_U16_LE | SNDRV_PCM_FMTBIT_U16_BE | \
+ SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_U18_3LE | \
+ SNDRV_PCM_FMTBIT_S18_3BE | SNDRV_PCM_FMTBIT_U18_3BE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_U20_3LE | \
+ SNDRV_PCM_FMTBIT_S20_3BE | SNDRV_PCM_FMTBIT_U20_3BE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S24_BE | \
+ SNDRV_PCM_FMTBIT_U24_LE | SNDRV_PCM_FMTBIT_U24_BE | \
+ 0)
+
+static inline unsigned long RD(struct au1xpsc_audio_data *ctx, int reg)
+{
+ return __raw_readl(ctx->mmio + reg);
+}
+
+static inline void WR(struct au1xpsc_audio_data *ctx, int reg, unsigned long v)
+{
+ __raw_writel(v, ctx->mmio + reg);
+ wmb();
+}
+
+static int au1xi2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+ struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(cpu_dai);
+ unsigned long c;
+ int ret;
+
+ ret = -EINVAL;
+ c = ctx->cfg;
+
+ c &= ~CFG_FM_MASK;
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ c |= CFG_FM_I2S;
+ break;
+ case SND_SOC_DAIFMT_MSB:
+ c |= CFG_FM_RJ;
+ break;
+ case SND_SOC_DAIFMT_LSB:
+ c |= CFG_FM_LJ;
+ break;
+ default:
+ goto out;
+ }
+
+ c &= ~(CFG_IC | CFG_ICK); /* IB-IF */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ c |= CFG_IC | CFG_ICK;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ c |= CFG_IC;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ c |= CFG_ICK;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ break;
+ default:
+ goto out;
+ }
+
+ /* I2S controller only supports master */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS: /* CODEC slave */
+ break;
+ default:
+ goto out;
+ }
+
+ ret = 0;
+ ctx->cfg = c;
+out:
+ return ret;
+}
+
+static int au1xi2s_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
+ int stype = SUBSTREAM_TYPE(substream);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ /* power up */
+ WR(ctx, I2S_ENABLE, EN_D | EN_CE);
+ WR(ctx, I2S_ENABLE, EN_CE);
+ ctx->cfg |= (stype == PCM_TX) ? CFG_TN : CFG_RN;
+ WR(ctx, I2S_CFG, ctx->cfg);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ ctx->cfg &= ~((stype == PCM_TX) ? CFG_TN : CFG_RN);
+ WR(ctx, I2S_CFG, ctx->cfg);
+ WR(ctx, I2S_ENABLE, EN_D); /* power off */
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static unsigned long msbits_to_reg(int msbits)
+{
+ switch (msbits) {
+ case 8:
+ return CFG_SZ_8;
+ case 16:
+ return CFG_SZ_16;
+ case 18:
+ return CFG_SZ_18;
+ case 20:
+ return CFG_SZ_20;
+ case 24:
+ return CFG_SZ_24;
+ }
+ return 0;
+}
+
+static int au1xi2s_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
+ unsigned long v;
+
+ v = msbits_to_reg(params->msbits);
+ if (!v)
+ return -EINVAL;
+
+ ctx->cfg &= ~CFG_SZ_MASK;
+ ctx->cfg |= v;
+ return 0;
+}
+
+static int au1xi2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct au1xpsc_audio_data *ctx = snd_soc_dai_get_drvdata(dai);
+ snd_soc_dai_set_dma_data(dai, substream, &ctx->dmaids[0]);
+ return 0;
+}
+
+static const struct snd_soc_dai_ops au1xi2s_dai_ops = {
+ .startup = au1xi2s_startup,
+ .trigger = au1xi2s_trigger,
+ .hw_params = au1xi2s_hw_params,
+ .set_fmt = au1xi2s_set_fmt,
+};
+
+static struct snd_soc_dai_driver au1xi2s_dai_driver = {
+ .symmetric_rates = 1,
+ .playback = {
+ .rates = AU1XI2SC_RATES,
+ .formats = AU1XI2SC_FMTS,
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .capture = {
+ .rates = AU1XI2SC_RATES,
+ .formats = AU1XI2SC_FMTS,
+ .channels_min = 2,
+ .channels_max = 2,
+ },
+ .ops = &au1xi2s_dai_ops,
+};
+
+static int __devinit au1xi2s_drvprobe(struct platform_device *pdev)
+{
+ struct resource *iores, *dmares;
+ struct au1xpsc_audio_data *ctx;
+
+ ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
+ if (!ctx)
+ return -ENOMEM;
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores)
+ return -ENODEV;
+
+ if (!devm_request_mem_region(&pdev->dev, iores->start,
+ resource_size(iores),
+ pdev->name))
+ return -EBUSY;
+
+ ctx->mmio = devm_ioremap_nocache(&pdev->dev, iores->start,
+ resource_size(iores));
+ if (!ctx->mmio)
+ return -EBUSY;
+
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dmares)
+ return -EBUSY;
+ ctx->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
+
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!dmares)
+ return -EBUSY;
+ ctx->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
+
+ platform_set_drvdata(pdev, ctx);
+
+ return snd_soc_register_dai(&pdev->dev, &au1xi2s_dai_driver);
+}
+
+static int __devexit au1xi2s_drvremove(struct platform_device *pdev)
+{
+ struct au1xpsc_audio_data *ctx = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_dai(&pdev->dev);
+
+ WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */
+
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int au1xi2s_drvsuspend(struct device *dev)
+{
+ struct au1xpsc_audio_data *ctx = dev_get_drvdata(dev);
+
+ WR(ctx, I2S_ENABLE, EN_D); /* clock off, disable */
+
+ return 0;
+}
+
+static int au1xi2s_drvresume(struct device *dev)
+{
+ return 0;
+}
+
+static const struct dev_pm_ops au1xi2sc_pmops = {
+ .suspend = au1xi2s_drvsuspend,
+ .resume = au1xi2s_drvresume,
+};
+
+#define AU1XI2SC_PMOPS (&au1xi2sc_pmops)
+
+#else
+
+#define AU1XI2SC_PMOPS NULL
+
+#endif
+
+static struct platform_driver au1xi2s_driver = {
+ .driver = {
+ .name = "alchemy-i2sc",
+ .owner = THIS_MODULE,
+ .pm = AU1XI2SC_PMOPS,
+ },
+ .probe = au1xi2s_drvprobe,
+ .remove = __devexit_p(au1xi2s_drvremove),
+};
+
+module_platform_driver(au1xi2s_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Au1000/1500/1100 I2S ASoC driver");
+MODULE_AUTHOR("Manuel Lauss");
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index d0db66f24a00..476b79a1c11a 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -41,14 +41,14 @@
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3BE)
#define AC97PCR_START(stype) \
- ((stype) == PCM_TX ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)
+ ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TS : PSC_AC97PCR_RS)
#define AC97PCR_STOP(stype) \
- ((stype) == PCM_TX ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)
+ ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TP : PSC_AC97PCR_RP)
#define AC97PCR_CLRFIFO(stype) \
- ((stype) == PCM_TX ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
+ ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97PCR_TC : PSC_AC97PCR_RC)
#define AC97STAT_BUSY(stype) \
- ((stype) == PCM_TX ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)
+ ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_AC97STAT_TB : PSC_AC97STAT_RB)
/* instance data. There can be only one, MacLeod!!!! */
static struct au1xpsc_audio_data *au1xpsc_ac97_workdata;
@@ -215,7 +215,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
{
struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
unsigned long r, ro, stat;
- int chans, t, stype = SUBSTREAM_TYPE(substream);
+ int chans, t, stype = substream->stream;
chans = params_channels(params);
@@ -235,7 +235,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
r |= PSC_AC97CFG_SET_LEN(params->msbits);
/* channels: enable slots for front L/R channel */
- if (stype == PCM_TX) {
+ if (stype == SNDRV_PCM_STREAM_PLAYBACK) {
r &= ~PSC_AC97CFG_TXSLOT_MASK;
r |= PSC_AC97CFG_TXSLOT_ENA(3);
r |= PSC_AC97CFG_TXSLOT_ENA(4);
@@ -294,7 +294,7 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
int cmd, struct snd_soc_dai *dai)
{
struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
- int ret, stype = SUBSTREAM_TYPE(substream);
+ int ret, stype = substream->stream;
ret = 0;
@@ -324,12 +324,21 @@ static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
return ret;
}
+static int au1xpsc_ac97_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
+ snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);
+ return 0;
+}
+
static int au1xpsc_ac97_probe(struct snd_soc_dai *dai)
{
return au1xpsc_ac97_workdata ? 0 : -ENODEV;
}
-static struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
+static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = {
+ .startup = au1xpsc_ac97_startup,
.trigger = au1xpsc_ac97_trigger,
.hw_params = au1xpsc_ac97_hw_params,
};
@@ -355,29 +364,40 @@ static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = {
static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
{
int ret;
- struct resource *r;
+ struct resource *iores, *dmares;
unsigned long sel;
struct au1xpsc_audio_data *wd;
- wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
+ wd = devm_kzalloc(&pdev->dev, sizeof(struct au1xpsc_audio_data),
+ GFP_KERNEL);
if (!wd)
return -ENOMEM;
mutex_init(&wd->lock);
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- ret = -ENODEV;
- goto out0;
- }
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores)
+ return -ENODEV;
- ret = -EBUSY;
- if (!request_mem_region(r->start, resource_size(r), pdev->name))
- goto out0;
+ if (!devm_request_mem_region(&pdev->dev, iores->start,
+ resource_size(iores),
+ pdev->name))
+ return -EBUSY;
- wd->mmio = ioremap(r->start, resource_size(r));
+ wd->mmio = devm_ioremap(&pdev->dev, iores->start,
+ resource_size(iores));
if (!wd->mmio)
- goto out1;
+ return -EBUSY;
+
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dmares)
+ return -EBUSY;
+ wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
+
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!dmares)
+ return -EBUSY;
+ wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
/* configuration: max dma trigger threshold, enable ac97 */
wd->cfg = PSC_AC97CFG_RT_FIFO8 | PSC_AC97CFG_TT_FIFO8 |
@@ -401,29 +421,15 @@ static int __devinit au1xpsc_ac97_drvprobe(struct platform_device *pdev)
ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
if (ret)
- goto out1;
+ return ret;
- wd->dmapd = au1xpsc_pcm_add(pdev);
- if (wd->dmapd) {
- au1xpsc_ac97_workdata = wd;
- return 0;
- }
-
- snd_soc_unregister_dai(&pdev->dev);
-out1:
- release_mem_region(r->start, resource_size(r));
-out0:
- kfree(wd);
- return ret;
+ au1xpsc_ac97_workdata = wd;
+ return 0;
}
static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
{
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
- struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- if (wd->dmapd)
- au1xpsc_pcm_destroy(wd->dmapd);
snd_soc_unregister_dai(&pdev->dev);
@@ -433,10 +439,6 @@ static int __devexit au1xpsc_ac97_drvremove(struct platform_device *pdev)
au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
au_sync();
- iounmap(wd->mmio);
- release_mem_region(r->start, resource_size(r));
- kfree(wd);
-
au1xpsc_ac97_workdata = NULL; /* MDEV */
return 0;
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index fca091276320..0607ba3d9258 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -42,13 +42,13 @@
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
#define I2SSTAT_BUSY(stype) \
- ((stype) == PCM_TX ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB)
+ ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SSTAT_TB : PSC_I2SSTAT_RB)
#define I2SPCR_START(stype) \
- ((stype) == PCM_TX ? PSC_I2SPCR_TS : PSC_I2SPCR_RS)
+ ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TS : PSC_I2SPCR_RS)
#define I2SPCR_STOP(stype) \
- ((stype) == PCM_TX ? PSC_I2SPCR_TP : PSC_I2SPCR_RP)
+ ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TP : PSC_I2SPCR_RP)
#define I2SPCR_CLRFIFO(stype) \
- ((stype) == PCM_TX ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
+ ((stype) == SNDRV_PCM_STREAM_PLAYBACK ? PSC_I2SPCR_TC : PSC_I2SPCR_RC)
static int au1xpsc_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
@@ -240,7 +240,7 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
- int ret, stype = SUBSTREAM_TYPE(substream);
+ int ret, stype = substream->stream;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
@@ -257,7 +257,16 @@ static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
return ret;
}
-static struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
+static int au1xpsc_i2s_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct au1xpsc_audio_data *pscdata = snd_soc_dai_get_drvdata(dai);
+ snd_soc_dai_set_dma_data(dai, substream, &pscdata->dmaids[0]);
+ return 0;
+}
+
+static const struct snd_soc_dai_ops au1xpsc_i2s_dai_ops = {
+ .startup = au1xpsc_i2s_startup,
.trigger = au1xpsc_i2s_trigger,
.hw_params = au1xpsc_i2s_hw_params,
.set_fmt = au1xpsc_i2s_set_fmt,
@@ -281,28 +290,40 @@ static const struct snd_soc_dai_driver au1xpsc_i2s_dai_template = {
static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
{
- struct resource *r;
+ struct resource *iores, *dmares;
unsigned long sel;
int ret;
struct au1xpsc_audio_data *wd;
- wd = kzalloc(sizeof(struct au1xpsc_audio_data), GFP_KERNEL);
+ wd = devm_kzalloc(&pdev->dev, sizeof(struct au1xpsc_audio_data),
+ GFP_KERNEL);
if (!wd)
return -ENOMEM;
- r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!r) {
- ret = -ENODEV;
- goto out0;
- }
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!iores)
+ return -ENODEV;
ret = -EBUSY;
- if (!request_mem_region(r->start, resource_size(r), pdev->name))
- goto out0;
+ if (!devm_request_mem_region(&pdev->dev, iores->start,
+ resource_size(iores),
+ pdev->name))
+ return -EBUSY;
- wd->mmio = ioremap(r->start, resource_size(r));
+ wd->mmio = devm_ioremap(&pdev->dev, iores->start,
+ resource_size(iores));
if (!wd->mmio)
- goto out1;
+ return -EBUSY;
+
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dmares)
+ return -EBUSY;
+ wd->dmaids[SNDRV_PCM_STREAM_PLAYBACK] = dmares->start;
+
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 1);
+ if (!dmares)
+ return -EBUSY;
+ wd->dmaids[SNDRV_PCM_STREAM_CAPTURE] = dmares->start;
/* preserve PSC clock source set up by platform (dev.platform_data
* is already occupied by soc layer)
@@ -329,30 +350,12 @@ static int __devinit au1xpsc_i2s_drvprobe(struct platform_device *pdev)
platform_set_drvdata(pdev, wd);
- ret = snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
- if (ret)
- goto out1;
-
- /* finally add the DMA device for this PSC */
- wd->dmapd = au1xpsc_pcm_add(pdev);
- if (wd->dmapd)
- return 0;
-
- snd_soc_unregister_dai(&pdev->dev);
-out1:
- release_mem_region(r->start, resource_size(r));
-out0:
- kfree(wd);
- return ret;
+ return snd_soc_register_dai(&pdev->dev, &wd->dai_drv);
}
static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
{
struct au1xpsc_audio_data *wd = platform_get_drvdata(pdev);
- struct resource *r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-
- if (wd->dmapd)
- au1xpsc_pcm_destroy(wd->dmapd);
snd_soc_unregister_dai(&pdev->dev);
@@ -361,10 +364,6 @@ static int __devexit au1xpsc_i2s_drvremove(struct platform_device *pdev)
au_writel(PSC_CTRL_DISABLE, PSC_CTRL(wd));
au_sync();
- iounmap(wd->mmio);
- release_mem_region(r->start, resource_size(r));
- kfree(wd);
-
return 0;
}
@@ -422,18 +421,7 @@ static struct platform_driver au1xpsc_i2s_driver = {
.remove = __devexit_p(au1xpsc_i2s_drvremove),
};
-static int __init au1xpsc_i2s_load(void)
-{
- return platform_driver_register(&au1xpsc_i2s_driver);
-}
-
-static void __exit au1xpsc_i2s_unload(void)
-{
- platform_driver_unregister(&au1xpsc_i2s_driver);
-}
-
-module_init(au1xpsc_i2s_load);
-module_exit(au1xpsc_i2s_unload);
+module_platform_driver(au1xpsc_i2s_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Au12x0/Au1550 PSC I2S ALSA ASoC audio driver");
diff --git a/sound/soc/au1x/psc.h b/sound/soc/au1x/psc.h
index b30eadd422a7..b16b2e02e0c9 100644
--- a/sound/soc/au1x/psc.h
+++ b/sound/soc/au1x/psc.h
@@ -1,7 +1,7 @@
/*
- * Au12x0/Au1550 PSC ALSA ASoC audio support.
+ * Alchemy ALSA ASoC audio support.
*
- * (c) 2007-2008 MSC Vertriebsges.m.b.H.,
+ * (c) 2007-2011 MSC Vertriebsges.m.b.H.,
* Manuel Lauss <manuel.lauss@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
@@ -13,10 +13,6 @@
#ifndef _AU1X_PCM_H
#define _AU1X_PCM_H
-/* DBDMA helpers */
-extern struct platform_device *au1xpsc_pcm_add(struct platform_device *pdev);
-extern void au1xpsc_pcm_destroy(struct platform_device *dmapd);
-
struct au1xpsc_audio_data {
void __iomem *mmio;
@@ -27,15 +23,9 @@ struct au1xpsc_audio_data {
unsigned long pm[2];
struct mutex lock;
- struct platform_device *dmapd;
+ int dmaids[2];
};
-#define PCM_TX 0
-#define PCM_RX 1
-
-#define SUBSTREAM_TYPE(substream) \
- ((substream)->stream == SNDRV_PCM_STREAM_PLAYBACK ? PCM_TX : PCM_RX)
-
/* easy access macros */
#define PSC_CTRL(x) ((unsigned long)((x)->mmio) + PSC_CTRL_OFFSET)
#define PSC_SEL(x) ((unsigned long)((x)->mmio) + PSC_SEL_OFFSET)
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index fe9d548a6837..9f6bc55fc399 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -27,6 +27,19 @@ config SND_SOC_BFIN_EVAL_ADAU1701
board connected to one of the Blackfin evaluation boards like the
BF5XX-STAMP or BF5XX-EZKIT.
+config SND_SOC_BFIN_EVAL_ADAU1373
+ tristate "Support for the EVAL-ADAU1373 board on Blackfin eval boards"
+ depends on SND_BF5XX_I2S && I2C
+ select SND_BF5XX_SOC_I2S
+ select SND_SOC_ADAU1373
+ help
+ Say Y if you want to add support for the Analog Devices EVAL-ADAU1373
+ board connected to one of the Blackfin evaluation boards like the
+ BF5XX-STAMP or BF5XX-EZKIT.
+
+ Note: This driver assumes that first ADAU1373 DAI is connected to the
+ first SPORT port on the BF5XX board.
+
config SND_SOC_BFIN_EVAL_ADAV80X
tristate "Support for the EVAL-ADAV80X boards on Blackfin eval boards"
depends on SND_BF5XX_I2S && (SPI_MASTER || I2C)
diff --git a/sound/soc/blackfin/Makefile b/sound/soc/blackfin/Makefile
index 6018bf52a234..1bf86ccaa8de 100644
--- a/sound/soc/blackfin/Makefile
+++ b/sound/soc/blackfin/Makefile
@@ -21,6 +21,7 @@ snd-ad1980-objs := bf5xx-ad1980.o
snd-ssm2602-objs := bf5xx-ssm2602.o
snd-ad73311-objs := bf5xx-ad73311.o
snd-ad193x-objs := bf5xx-ad193x.o
+snd-soc-bfin-eval-adau1373-objs := bfin-eval-adau1373.o
snd-soc-bfin-eval-adau1701-objs := bfin-eval-adau1701.o
snd-soc-bfin-eval-adav80x-objs := bfin-eval-adav80x.o
@@ -29,5 +30,6 @@ obj-$(CONFIG_SND_BF5XX_SOC_AD1980) += snd-ad1980.o
obj-$(CONFIG_SND_BF5XX_SOC_SSM2602) += snd-ssm2602.o
obj-$(CONFIG_SND_BF5XX_SOC_AD73311) += snd-ad73311.o
obj-$(CONFIG_SND_BF5XX_SOC_AD193X) += snd-ad193x.o
+obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1373) += snd-soc-bfin-eval-adau1373.o
obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAU1701) += snd-soc-bfin-eval-adau1701.o
obj-$(CONFIG_SND_SOC_BFIN_EVAL_ADAV80X) += snd-soc-bfin-eval-adav80x.o
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 9e59f680bc19..d7dc9bde0976 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -418,10 +418,9 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
-int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
+static int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
@@ -431,14 +430,14 @@ int bf5xx_pcm_ac97_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -475,17 +474,7 @@ static struct platform_driver bf5xx_pcm_driver = {
.remove = __devexit_p(bf5xx_soc_platform_remove),
};
-static int __init snd_bf5xx_pcm_init(void)
-{
- return platform_driver_register(&bf5xx_pcm_driver);
-}
-module_init(snd_bf5xx_pcm_init);
-
-static void __exit snd_bf5xx_pcm_exit(void)
-{
- platform_driver_unregister(&bf5xx_pcm_driver);
-}
-module_exit(snd_bf5xx_pcm_exit);
+module_platform_driver(bf5xx_pcm_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index 6d2162590889..f4e9dc4e262e 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -375,18 +375,7 @@ static struct platform_driver asoc_bfin_ac97_driver = {
.remove = __devexit_p(asoc_bfin_ac97_remove),
};
-static int __init bfin_ac97_init(void)
-{
- return platform_driver_register(&asoc_bfin_ac97_driver);
-}
-module_init(bfin_ac97_init);
-
-static void __exit bfin_ac97_exit(void)
-{
- platform_driver_unregister(&asoc_bfin_ac97_driver);
-}
-module_exit(bfin_ac97_exit);
-
+module_platform_driver(asoc_bfin_ac97_driver);
MODULE_AUTHOR("Roy Huang");
MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c
index f79d1655e035..d542d4063771 100644
--- a/sound/soc/blackfin/bf5xx-ad1836.c
+++ b/sound/soc/blackfin/bf5xx-ad1836.c
@@ -40,20 +40,8 @@ static int bf5xx_ad1836_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
unsigned int channel_map[] = {0, 4, 1, 5, 2, 6, 3, 7};
int ret = 0;
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
/* set cpu DAI channel mapping */
ret = snd_soc_dai_set_channel_map(cpu_dai, ARRAY_SIZE(channel_map),
@@ -68,6 +56,9 @@ static struct snd_soc_ops bf5xx_ad1836_ops = {
.hw_params = bf5xx_ad1836_hw_params,
};
+#define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
{
.name = "ad1836",
@@ -77,6 +68,7 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.4",
.ops = &bf5xx_ad1836_ops,
+ .dai_fmt = BF5XX_AD1836_DAIFMT,
},
{
.name = "ad1836",
@@ -86,11 +78,13 @@ static struct snd_soc_dai_link bf5xx_ad1836_dai[] = {
.platform_name = "bfin-tdm-pcm-audio",
.codec_name = "spi0.4",
.ops = &bf5xx_ad1836_ops,
+ .dai_fmt = BF5XX_AD1836_DAIFMT,
},
};
static struct snd_soc_card bf5xx_ad1836 = {
.name = "bfin-ad1836",
+ .owner = THIS_MODULE,
.dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
};
diff --git a/sound/soc/blackfin/bf5xx-ad193x.c b/sound/soc/blackfin/bf5xx-ad193x.c
index a118a0fb9d81..0e55e9f2a514 100644
--- a/sound/soc/blackfin/bf5xx-ad193x.c
+++ b/sound/soc/blackfin/bf5xx-ad193x.c
@@ -60,18 +60,6 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
break;
}
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_IF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
/* set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
SND_SOC_CLOCK_IN);
@@ -92,6 +80,9 @@ static int bf5xx_ad193x_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+#define BF5XX_AD193X_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_ops bf5xx_ad193x_ops = {
.hw_params = bf5xx_ad193x_hw_params,
};
@@ -103,8 +94,9 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
.cpu_dai_name = "bfin-tdm.0",
.codec_dai_name ="ad193x-hifi",
.platform_name = "bfin-tdm-pcm-audio",
- .codec_name = "ad193x.5",
+ .codec_name = "spi0.5",
.ops = &bf5xx_ad193x_ops,
+ .dai_fmt = BF5XX_AD193X_DAIFMT,
},
{
.name = "ad193x",
@@ -112,13 +104,15 @@ static struct snd_soc_dai_link bf5xx_ad193x_dai[] = {
.cpu_dai_name = "bfin-tdm.1",
.codec_dai_name ="ad193x-hifi",
.platform_name = "bfin-tdm-pcm-audio",
- .codec_name = "ad193x.5",
+ .codec_name = "spi0.5",
.ops = &bf5xx_ad193x_ops,
+ .dai_fmt = BF5XX_AD193X_DAIFMT,
},
};
static struct snd_soc_card bf5xx_ad193x = {
.name = "bfin-ad193x",
+ .owner = THIS_MODULE,
.dai_link = &bf5xx_ad193x_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
};
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c
index 06a84b211b52..b30f88bbd703 100644
--- a/sound/soc/blackfin/bf5xx-ad1980.c
+++ b/sound/soc/blackfin/bf5xx-ad1980.c
@@ -74,6 +74,7 @@ static struct snd_soc_dai_link bf5xx_board_dai[] = {
static struct snd_soc_card bf5xx_board = {
.name = "bfin-ad1980",
+ .owner = THIS_MODULE,
.dai_link = &bf5xx_board_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
};
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 732a247f2527..61cc91d4a028 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -128,7 +128,7 @@ static int snd_ad73311_configure(void)
return 0;
}
-static int bf5xx_probe(struct platform_device *pdev)
+static int bf5xx_probe(struct snd_soc_card *card)
{
int err;
if (gpio_request(GPIO_SE, "AD73311_SE")) {
@@ -145,29 +145,8 @@ static int bf5xx_probe(struct platform_device *pdev)
return 0;
}
-static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret = 0;
-
- pr_debug("%s rate %d format %x\n", __func__, params_rate(params),
- params_format(params));
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-
-static struct snd_soc_ops bf5xx_ad73311_ops = {
- .hw_params = bf5xx_ad73311_hw_params,
-};
+#define BF5XX_AD7311_DAI_FMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_NB_NF | \
+ SND_SOC_DAIFMT_CBM_CFM)
static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
{
@@ -177,7 +156,7 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
.codec_dai_name = "ad73311-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "ad73311",
- .ops = &bf5xx_ad73311_ops,
+ .dai_fmt = BF5XX_AD7311_DAI_FMT,
},
{
.name = "ad73311",
@@ -186,12 +165,13 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai[] = {
.codec_dai_name = "ad73311-hifi",
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "ad73311",
- .ops = &bf5xx_ad73311_ops,
+ .dai_fmt = BF5XX_AD7311_DAI_FMT,
},
};
static struct snd_soc_card bf5xx_ad73311 = {
.name = "bfin-ad73311",
+ .owner = THIS_MODULE,
.probe = bf5xx_probe,
.dai_link = &bf5xx_ad73311_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index 61ddf942fd4d..63205d723eab 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -257,10 +257,9 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
-int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
+static int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
@@ -270,14 +269,14 @@ int bf5xx_pcm_i2s_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -314,17 +313,7 @@ static struct platform_driver bfin_i2s_pcm_driver = {
.remove = __devexit_p(bfin_i2s_soc_platform_remove),
};
-static int __init snd_bfin_i2s_pcm_init(void)
-{
- return platform_driver_register(&bfin_i2s_pcm_driver);
-}
-module_init(snd_bfin_i2s_pcm_init);
-
-static void __exit snd_bfin_i2s_pcm_exit(void)
-{
- platform_driver_unregister(&bfin_i2s_pcm_driver);
-}
-module_exit(snd_bfin_i2s_pcm_exit);
+module_platform_driver(bfin_i2s_pcm_driver);
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 00cc3e00b2fe..4dccf0374fe7 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -223,7 +223,7 @@ static int bf5xx_i2s_resume(struct snd_soc_dai *dai)
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
+static const struct snd_soc_dai_ops bf5xx_i2s_dai_ops = {
.shutdown = bf5xx_i2s_shutdown,
.hw_params = bf5xx_i2s_hw_params,
.set_fmt = bf5xx_i2s_set_dai_fmt,
@@ -288,18 +288,7 @@ static struct platform_driver bfin_i2s_driver = {
},
};
-static int __init bfin_i2s_init(void)
-{
- return platform_driver_register(&bfin_i2s_driver);
-}
-
-static void __exit bfin_i2s_exit(void)
-{
- platform_driver_unregister(&bfin_i2s_driver);
-}
-
-module_init(bfin_i2s_init);
-module_exit(bfin_i2s_exit);
+module_platform_driver(bfin_i2s_driver);
/* Module information */
MODULE_AUTHOR("Cliff Cai");
diff --git a/sound/soc/blackfin/bf5xx-sport.c b/sound/soc/blackfin/bf5xx-sport.c
index a2d40349fcc4..2fd9f2a06968 100644
--- a/sound/soc/blackfin/bf5xx-sport.c
+++ b/sound/soc/blackfin/bf5xx-sport.c
@@ -33,6 +33,7 @@
#include <linux/dma-mapping.h>
#include <linux/gpio.h>
#include <linux/bug.h>
+#include <linux/module.h>
#include <asm/portmux.h>
#include <asm/dma.h>
#include <asm/blackfin.h>
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index 767e772a815d..df3ac73f8778 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -49,7 +49,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
unsigned int clk = 0;
int ret = 0;
@@ -75,21 +74,6 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
break;
}
- /*
- * CODEC is master for BCLK and LRC in this configuration.
- */
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
SND_SOC_CLOCK_IN);
if (ret < 0)
@@ -102,6 +86,10 @@ static struct snd_soc_ops bf5xx_ssm2602_ops = {
.hw_params = bf5xx_ssm2602_hw_params,
};
+/* CODEC is master for BCLK and LRC in this configuration. */
+#define BF5XX_SSM2602_DAIFMT (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | \
+ SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = {
{
.name = "ssm2602",
@@ -125,6 +113,7 @@ static struct snd_soc_dai_link bf5xx_ssm2602_dai[] = {
static struct snd_soc_card bf5xx_ssm2602 = {
.name = "bfin-ssm2602",
+ .owner = THIS_MODULE,
.dai_link = &bf5xx_ssm2602_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
};
diff --git a/sound/soc/blackfin/bf5xx-tdm-pcm.c b/sound/soc/blackfin/bf5xx-tdm-pcm.c
index c95cc03d583d..254490cf1876 100644
--- a/sound/soc/blackfin/bf5xx-tdm-pcm.c
+++ b/sound/soc/blackfin/bf5xx-tdm-pcm.c
@@ -286,7 +286,6 @@ static u64 bf5xx_pcm_dmamask = DMA_BIT_MASK(32);
static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
@@ -295,14 +294,14 @@ static int bf5xx_pcm_tdm_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = bf5xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -339,17 +338,7 @@ static struct platform_driver bfin_tdm_driver = {
.remove = __devexit_p(bf5xx_soc_platform_remove),
};
-static int __init snd_bfin_tdm_init(void)
-{
- return platform_driver_register(&bfin_tdm_driver);
-}
-module_init(snd_bfin_tdm_init);
-
-static void __exit snd_bfin_tdm_exit(void)
-{
- platform_driver_unregister(&bfin_tdm_driver);
-}
-module_exit(snd_bfin_tdm_exit);
+module_platform_driver(bfin_tdm_driver);
MODULE_AUTHOR("Barry Song");
MODULE_DESCRIPTION("ADI Blackfin TDM PCM DMA module");
diff --git a/sound/soc/blackfin/bf5xx-tdm.c b/sound/soc/blackfin/bf5xx-tdm.c
index a822d1ee1380..594f88217c74 100644
--- a/sound/soc/blackfin/bf5xx-tdm.c
+++ b/sound/soc/blackfin/bf5xx-tdm.c
@@ -226,7 +226,7 @@ static int bf5xx_tdm_resume(struct snd_soc_dai *dai)
#define bf5xx_tdm_resume NULL
#endif
-static struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
+static const struct snd_soc_dai_ops bf5xx_tdm_dai_ops = {
.hw_params = bf5xx_tdm_hw_params,
.set_fmt = bf5xx_tdm_set_dai_fmt,
.shutdown = bf5xx_tdm_shutdown,
@@ -314,17 +314,7 @@ static struct platform_driver bfin_tdm_driver = {
},
};
-static int __init bfin_tdm_init(void)
-{
- return platform_driver_register(&bfin_tdm_driver);
-}
-module_init(bfin_tdm_init);
-
-static void __exit bfin_tdm_exit(void)
-{
- platform_driver_unregister(&bfin_tdm_driver);
-}
-module_exit(bfin_tdm_exit);
+module_platform_driver(bfin_tdm_driver);
/* Module information */
MODULE_AUTHOR("Barry Song");
diff --git a/sound/soc/blackfin/bfin-eval-adau1373.c b/sound/soc/blackfin/bfin-eval-adau1373.c
new file mode 100644
index 000000000000..f3adbdbdd5e1
--- /dev/null
+++ b/sound/soc/blackfin/bfin-eval-adau1373.c
@@ -0,0 +1,184 @@
+/*
+ * Machine driver for EVAL-ADAU1373 on Analog Devices bfin
+ * evaluation boards.
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+
+#include "../codecs/adau1373.h"
+
+static const struct snd_soc_dapm_widget bfin_eval_adau1373_dapm_widgets[] = {
+ SND_SOC_DAPM_LINE("Line In1", NULL),
+ SND_SOC_DAPM_LINE("Line In2", NULL),
+ SND_SOC_DAPM_LINE("Line In3", NULL),
+ SND_SOC_DAPM_LINE("Line In4", NULL),
+
+ SND_SOC_DAPM_LINE("Line Out1", NULL),
+ SND_SOC_DAPM_LINE("Line Out2", NULL),
+ SND_SOC_DAPM_LINE("Stereo Out", NULL),
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_HP("Earpiece", NULL),
+ SND_SOC_DAPM_SPK("Speaker", NULL),
+};
+
+static const struct snd_soc_dapm_route bfin_eval_adau1373_dapm_routes[] = {
+ { "AIN1L", NULL, "Line In1" },
+ { "AIN1R", NULL, "Line In1" },
+ { "AIN2L", NULL, "Line In2" },
+ { "AIN2R", NULL, "Line In2" },
+ { "AIN3L", NULL, "Line In3" },
+ { "AIN3R", NULL, "Line In3" },
+ { "AIN4L", NULL, "Line In4" },
+ { "AIN4R", NULL, "Line In4" },
+
+ /* MICBIAS can be connected via a jumper to the line-in jack, since w
+ don't know which one is going to be used, just power both. */
+ { "Line In1", NULL, "MICBIAS1" },
+ { "Line In2", NULL, "MICBIAS1" },
+ { "Line In3", NULL, "MICBIAS1" },
+ { "Line In4", NULL, "MICBIAS1" },
+ { "Line In1", NULL, "MICBIAS2" },
+ { "Line In2", NULL, "MICBIAS2" },
+ { "Line In3", NULL, "MICBIAS2" },
+ { "Line In4", NULL, "MICBIAS2" },
+
+ { "Line Out1", NULL, "LOUT1L" },
+ { "Line Out1", NULL, "LOUT1R" },
+ { "Line Out2", NULL, "LOUT2L" },
+ { "Line Out2", NULL, "LOUT2R" },
+ { "Headphone", NULL, "HPL" },
+ { "Headphone", NULL, "HPR" },
+ { "Earpiece", NULL, "EP" },
+ { "Speaker", NULL, "SPKL" },
+ { "Stereo Out", NULL, "SPKR" },
+};
+
+static int bfin_eval_adau1373_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+ int pll_rate;
+
+ switch (params_rate(params)) {
+ case 48000:
+ case 8000:
+ case 12000:
+ case 16000:
+ case 24000:
+ case 32000:
+ pll_rate = 48000 * 1024;
+ break;
+ case 44100:
+ case 7350:
+ case 11025:
+ case 14700:
+ case 22050:
+ case 29400:
+ pll_rate = 44100 * 1024;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = snd_soc_dai_set_pll(codec_dai, ADAU1373_PLL1,
+ ADAU1373_PLL_SRC_MCLK1, 12288000, pll_rate);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1373_CLK_SRC_PLL1, pll_rate,
+ SND_SOC_CLOCK_IN);
+
+ return ret;
+}
+
+static int bfin_eval_adau1373_codec_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ unsigned int pll_rate = 48000 * 1024;
+ int ret;
+
+ ret = snd_soc_dai_set_pll(codec_dai, ADAU1373_PLL1,
+ ADAU1373_PLL_SRC_MCLK1, 12288000, pll_rate);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1373_CLK_SRC_PLL1, pll_rate,
+ SND_SOC_CLOCK_IN);
+
+ return ret;
+}
+static struct snd_soc_ops bfin_eval_adau1373_ops = {
+ .hw_params = bfin_eval_adau1373_hw_params,
+};
+
+static struct snd_soc_dai_link bfin_eval_adau1373_dai = {
+ .name = "adau1373",
+ .stream_name = "adau1373",
+ .cpu_dai_name = "bfin-i2s.0",
+ .codec_dai_name = "adau1373-aif1",
+ .platform_name = "bfin-i2s-pcm-audio",
+ .codec_name = "adau1373.0-001a",
+ .ops = &bfin_eval_adau1373_ops,
+ .init = bfin_eval_adau1373_codec_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
+};
+
+static struct snd_soc_card bfin_eval_adau1373 = {
+ .name = "bfin-eval-adau1373",
+ .owner = THIS_MODULE,
+ .dai_link = &bfin_eval_adau1373_dai,
+ .num_links = 1,
+
+ .dapm_widgets = bfin_eval_adau1373_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(bfin_eval_adau1373_dapm_widgets),
+ .dapm_routes = bfin_eval_adau1373_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(bfin_eval_adau1373_dapm_routes),
+};
+
+static int bfin_eval_adau1373_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &bfin_eval_adau1373;
+
+ card->dev = &pdev->dev;
+
+ return snd_soc_register_card(&bfin_eval_adau1373);
+}
+
+static int __devexit bfin_eval_adau1373_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static struct platform_driver bfin_eval_adau1373_driver = {
+ .driver = {
+ .name = "bfin-eval-adau1373",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = bfin_eval_adau1373_probe,
+ .remove = __devexit_p(bfin_eval_adau1373_remove),
+};
+
+module_platform_driver(bfin_eval_adau1373_driver);
+
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_DESCRIPTION("ALSA SoC bfin adau1373 driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:bfin-eval-adau1373");
diff --git a/sound/soc/blackfin/bfin-eval-adau1701.c b/sound/soc/blackfin/bfin-eval-adau1701.c
index e5550acba2c2..b0531fc9d814 100644
--- a/sound/soc/blackfin/bfin-eval-adau1701.c
+++ b/sound/soc/blackfin/bfin-eval-adau1701.c
@@ -37,20 +37,9 @@ static int bfin_eval_adau1701_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret;
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
ret = snd_soc_dai_set_sysclk(codec_dai, ADAU1701_CLK_SRC_OSC, 12288000,
SND_SOC_CLOCK_IN);
@@ -61,6 +50,9 @@ static struct snd_soc_ops bfin_eval_adau1701_ops = {
.hw_params = bfin_eval_adau1701_hw_params,
};
+#define BFIN_EVAL_ADAU1701_DAI_FMT (SND_SOC_DAIFMT_I2S | \
+ SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM)
+
static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
{
.name = "adau1701",
@@ -70,6 +62,7 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "adau1701.0-0034",
.ops = &bfin_eval_adau1701_ops,
+ .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
},
{
.name = "adau1701",
@@ -79,11 +72,13 @@ static struct snd_soc_dai_link bfin_eval_adau1701_dai[] = {
.platform_name = "bfin-i2s-pcm-audio",
.codec_name = "adau1701.0-0034",
.ops = &bfin_eval_adau1701_ops,
+ .dai_fmt = BFIN_EVAL_ADAU1701_DAI_FMT,
},
};
static struct snd_soc_card bfin_eval_adau1701 = {
.name = "bfin-eval-adau1701",
+ .owner = THIS_MODULE,
.dai_link = &bfin_eval_adau1701_dai[CONFIG_SND_BF5XX_SPORT_NUM],
.num_links = 1,
@@ -121,17 +116,7 @@ static struct platform_driver bfin_eval_adau1701_driver = {
.remove = __devexit_p(bfin_eval_adau1701_remove),
};
-static int __init bfin_eval_adau1701_init(void)
-{
- return platform_driver_register(&bfin_eval_adau1701_driver);
-}
-module_init(bfin_eval_adau1701_init);
-
-static void __exit bfin_eval_adau1701_exit(void)
-{
- platform_driver_unregister(&bfin_eval_adau1701_driver);
-}
-module_exit(bfin_eval_adau1701_exit);
+module_platform_driver(bfin_eval_adau1701_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ALSA SoC bfin ADAU1701 driver");
diff --git a/sound/soc/blackfin/bfin-eval-adav80x.c b/sound/soc/blackfin/bfin-eval-adav80x.c
index 8d014d01626e..84b09987b7f3 100644
--- a/sound/soc/blackfin/bfin-eval-adav80x.c
+++ b/sound/soc/blackfin/bfin-eval-adav80x.c
@@ -10,6 +10,7 @@
#include <linux/init.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -33,20 +34,9 @@ static int bfin_eval_adav80x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret;
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret)
- return ret;
-
ret = snd_soc_dai_set_pll(codec_dai, ADAV80X_PLL1, ADAV80X_PLL_SRC_XTAL,
27000000, params_rate(params) * 256);
if (ret)
@@ -87,11 +77,14 @@ static struct snd_soc_dai_link bfin_eval_adav80x_dais[] = {
.platform_name = "bfin-i2s-pcm-audio",
.init = bfin_eval_adav80x_codec_init,
.ops = &bfin_eval_adav80x_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
},
};
static struct snd_soc_card bfin_eval_adav80x = {
.name = "bfin-eval-adav80x",
+ .owner = THIS_MODULE,
.dai_link = bfin_eval_adav80x_dais,
.num_links = ARRAY_SIZE(bfin_eval_adav80x_dais),
@@ -156,17 +149,7 @@ static struct platform_driver bfin_eval_adav80x_driver = {
.id_table = bfin_eval_adav80x_ids,
};
-static int __init bfin_eval_adav80x_init(void)
-{
- return platform_driver_register(&bfin_eval_adav80x_driver);
-}
-module_init(bfin_eval_adav80x_init);
-
-static void __exit bfin_eval_adav80x_exit(void)
-{
- platform_driver_unregister(&bfin_eval_adav80x_driver);
-}
-module_exit(bfin_eval_adav80x_exit);
+module_platform_driver(bfin_eval_adav80x_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ALSA SoC bfin adav80x driver");
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c
index 19241576b6b5..9fd3b6827bba 100644
--- a/sound/soc/codecs/88pm860x-codec.c
+++ b/sound/soc/codecs/88pm860x-codec.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/mfd/88pm860x.h>
#include <linux/slab.h>
+#include <linux/delay.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -772,11 +773,12 @@ static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
SND_SOC_DAPM_AIF_IN("I2S DIN", "I2S Playback", 0,
- PM860X_DAC_EN_2, 0, 0),
+ SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_IN("I2S DIN1", "I2S Playback", 0,
- PM860X_DAC_EN_2, 0, 0),
+ SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_AIF_OUT("I2S DOUT", "I2S Capture", 0,
PM860X_I2S_IFACE_3, 5, 1),
+ SND_SOC_DAPM_SUPPLY("I2S CLK", PM860X_DAC_EN_2, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("I2S Mic Mux", SND_SOC_NOPM, 0, 0, &i2s_mic_mux),
SND_SOC_DAPM_MUX("ADC Left Mux", SND_SOC_NOPM, 0, 0, &adcl_mux),
SND_SOC_DAPM_MUX("ADC Right Mux", SND_SOC_NOPM, 0, 0, &adcr_mux),
@@ -859,7 +861,7 @@ static const struct snd_soc_dapm_widget pm860x_dapm_widgets[] = {
PM860X_DAPM_OUTPUT("RSYNC", pm860x_rsync_event),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route pm860x_dapm_routes[] = {
/* supply */
{"Left DAC", NULL, "VCODEC"},
{"Right DAC", NULL, "VCODEC"},
@@ -868,6 +870,11 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Left ADC", NULL, "Left ADC MOD"},
{"Right ADC", NULL, "Right ADC MOD"},
+ /* I2S Clock */
+ {"I2S DIN", NULL, "I2S CLK"},
+ {"I2S DIN1", NULL, "I2S CLK"},
+ {"I2S DOUT", NULL, "I2S CLK"},
+
/* PCM/AIF1 Inputs */
{"PCM SDO", NULL, "ADC Left Mux"},
{"PCM SDO", NULL, "ADCR EC Mux"},
@@ -1173,6 +1180,9 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
/* Enable Audio PLL & Audio section */
+ data = AUDIO_PLL | AUDIO_SECTION_ON;
+ pm860x_reg_write(codec->control_data, REG_MISC2, data);
+ udelay(300);
data = AUDIO_PLL | AUDIO_SECTION_RESET
| AUDIO_SECTION_ON;
pm860x_reg_write(codec->control_data, REG_MISC2, data);
@@ -1188,14 +1198,14 @@ static int pm860x_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
+static const struct snd_soc_dai_ops pm860x_pcm_dai_ops = {
.digital_mute = pm860x_digital_mute,
.hw_params = pm860x_pcm_hw_params,
.set_fmt = pm860x_pcm_set_dai_fmt,
.set_sysclk = pm860x_set_dai_sysclk,
};
-static struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
+static const struct snd_soc_dai_ops pm860x_i2s_dai_ops = {
.digital_mute = pm860x_digital_mute,
.hw_params = pm860x_i2s_hw_params,
.set_fmt = pm860x_i2s_set_dai_fmt,
@@ -1351,7 +1361,6 @@ EXPORT_SYMBOL_GPL(pm860x_mic_jack_detect);
static int pm860x_probe(struct snd_soc_codec *codec)
{
struct pm860x_priv *pm860x = snd_soc_codec_get_drvdata(codec);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int i, ret;
pm860x->codec = codec;
@@ -1378,11 +1387,6 @@ static int pm860x_probe(struct snd_soc_codec *codec)
goto out;
}
- snd_soc_add_controls(codec, pm860x_snd_controls,
- ARRAY_SIZE(pm860x_snd_controls));
- snd_soc_dapm_new_controls(dapm, pm860x_dapm_widgets,
- ARRAY_SIZE(pm860x_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
return 0;
out:
@@ -1410,6 +1414,13 @@ static struct snd_soc_codec_driver soc_codec_dev_pm860x = {
.reg_cache_size = REG_CACHE_SIZE,
.reg_word_size = sizeof(u8),
.set_bias_level = pm860x_set_bias_level,
+
+ .controls = pm860x_snd_controls,
+ .num_controls = ARRAY_SIZE(pm860x_snd_controls),
+ .dapm_widgets = pm860x_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(pm860x_dapm_widgets),
+ .dapm_routes = pm860x_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(pm860x_dapm_routes),
};
static int __devinit pm860x_codec_probe(struct platform_device *pdev)
@@ -1419,7 +1430,8 @@ static int __devinit pm860x_codec_probe(struct platform_device *pdev)
struct resource *res;
int i, ret;
- pm860x = kzalloc(sizeof(struct pm860x_priv), GFP_KERNEL);
+ pm860x = devm_kzalloc(&pdev->dev, sizeof(struct pm860x_priv),
+ GFP_KERNEL);
if (pm860x == NULL)
return -ENOMEM;
@@ -1448,17 +1460,13 @@ static int __devinit pm860x_codec_probe(struct platform_device *pdev)
out:
platform_set_drvdata(pdev, NULL);
- kfree(pm860x);
return -EINVAL;
}
static int __devexit pm860x_codec_remove(struct platform_device *pdev)
{
- struct pm860x_priv *pm860x = platform_get_drvdata(pdev);
-
snd_soc_unregister_codec(&pdev->dev);
platform_set_drvdata(pdev, NULL);
- kfree(pm860x);
return 0;
}
@@ -1471,17 +1479,7 @@ static struct platform_driver pm860x_codec_driver = {
.remove = __devexit_p(pm860x_codec_remove),
};
-static __init int pm860x_init(void)
-{
- return platform_driver_register(&pm860x_codec_driver);
-}
-module_init(pm860x_init);
-
-static __exit void pm860x_exit(void)
-{
- platform_driver_unregister(&pm860x_codec_driver);
-}
-module_exit(pm860x_exit);
+module_platform_driver(pm860x_codec_driver);
MODULE_DESCRIPTION("ASoC 88PM860x driver");
MODULE_AUTHOR("Haojian Zhuang <haojian.zhuang@marvell.com>");
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 665d9240c4ae..6508e8b790bb 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -17,6 +17,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI
select SND_SOC_AD1980 if SND_SOC_AC97_BUS
select SND_SOC_AD73311
+ select SND_SOC_ADAU1373 if I2C
select SND_SOC_ADAV80X
select SND_SOC_ADS117X
select SND_SOC_AK4104 if SPI_MASTER
@@ -25,20 +26,24 @@ config SND_SOC_ALL_CODECS
select SND_SOC_AK4642 if I2C
select SND_SOC_AK4671 if I2C
select SND_SOC_ALC5623 if I2C
+ select SND_SOC_ALC5632 if I2C
select SND_SOC_CQ0093VC if MFD_DAVINCI_VOICECODEC
select SND_SOC_CS42L51 if I2C
+ select SND_SOC_CS42L73 if I2C
select SND_SOC_CS4270 if I2C
select SND_SOC_CS4271 if SND_SOC_I2C_AND_SPI
select SND_SOC_CX20442
select SND_SOC_DA7210 if I2C
select SND_SOC_DFBMCS320
- select SND_SOC_JZ4740_CODEC if SOC_JZ4740
+ select SND_SOC_JZ4740_CODEC
select SND_SOC_LM4857 if I2C
select SND_SOC_MAX98088 if I2C
select SND_SOC_MAX98095 if I2C
select SND_SOC_MAX9850 if I2C
+ select SND_SOC_MAX9768 if I2C
select SND_SOC_MAX9877 if I2C
select SND_SOC_PCM3008
+ select SND_SOC_RT5631 if I2C
select SND_SOC_SGTL5000 if I2C
select SND_SOC_SN95031 if INTEL_SCU_IPC
select SND_SOC_SPDIF
@@ -47,7 +52,7 @@ config SND_SOC_ALL_CODECS
select SND_SOC_STAC9766 if SND_SOC_AC97_BUS
select SND_SOC_TLV320AIC23 if I2C
select SND_SOC_TLV320AIC26 if SPI_MASTER
- select SND_SOC_TVL320AIC32X4 if I2C
+ select SND_SOC_TLV320AIC32X4 if I2C
select SND_SOC_TLV320AIC3X if I2C
select SND_SOC_TPA6130A2 if I2C
select SND_SOC_TLV320DAC33 if I2C
@@ -58,6 +63,8 @@ config SND_SOC_ALL_CODECS
select SND_SOC_WL1273 if MFD_WL1273_CORE
select SND_SOC_WM1250_EV1 if I2C
select SND_SOC_WM2000 if I2C
+ select SND_SOC_WM2200 if I2C
+ select SND_SOC_WM5100 if I2C
select SND_SOC_WM8350 if MFD_WM8350
select SND_SOC_WM8400 if MFD_WM8400
select SND_SOC_WM8510 if SND_SOC_I2C_AND_SPI
@@ -136,7 +143,10 @@ config SND_SOC_AD73311
tristate
config SND_SOC_ADAU1701
- select SIGMA
+ select SND_SOC_SIGMADSP
+ tristate
+
+config SND_SOC_ADAU1373
tristate
config SND_SOC_ADAV80X
@@ -162,6 +172,8 @@ config SND_SOC_AK4671
config SND_SOC_ALC5623
tristate
+config SND_SOC_ALC5632
+ tristate
config SND_SOC_CQ0093VC
tristate
@@ -169,6 +181,9 @@ config SND_SOC_CQ0093VC
config SND_SOC_CS42L51
tristate
+config SND_SOC_CS42L73
+ tristate
+
# Cirrus Logic CS4270 Codec
config SND_SOC_CS4270
tristate
@@ -214,10 +229,17 @@ config SND_SOC_MAX9850
config SND_SOC_PCM3008
tristate
+config SND_SOC_RT5631
+ tristate
+
#Freescale sgtl5000 codec
config SND_SOC_SGTL5000
tristate
+config SND_SOC_SIGMADSP
+ tristate
+ select CRC32
+
config SND_SOC_SN95031
tristate
@@ -240,7 +262,7 @@ config SND_SOC_TLV320AIC26
tristate "TI TLV320AIC26 Codec support" if SND_SOC_OF_SIMPLE
depends on SPI
-config SND_SOC_TVL320AIC32X4
+config SND_SOC_TLV320AIC32X4
tristate
config SND_SOC_TLV320AIC3X
@@ -269,6 +291,15 @@ config SND_SOC_WL1273
config SND_SOC_WM1250_EV1
tristate
+config SND_SOC_WM2000
+ tristate
+
+config SND_SOC_WM2200
+ tristate
+
+config SND_SOC_WM5100
+ tristate
+
config SND_SOC_WM8350
tristate
@@ -383,6 +414,9 @@ config SND_SOC_WM8996
config SND_SOC_WM9081
tristate
+config SND_SOC_WM9090
+ tristate
+
config SND_SOC_WM9705
tristate
@@ -396,14 +430,11 @@ config SND_SOC_WM9713
config SND_SOC_LM4857
tristate
-config SND_SOC_MAX9877
+config SND_SOC_MAX9768
tristate
-config SND_SOC_TPA6130A2
- tristate
-
-config SND_SOC_WM2000
+config SND_SOC_MAX9877
tristate
-config SND_SOC_WM9090
+config SND_SOC_TPA6130A2
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 5119a7e2c1a8..6662eb0cdcc0 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -5,6 +5,7 @@ snd-soc-ad193x-objs := ad193x.o
snd-soc-ad1980-objs := ad1980.o
snd-soc-ad73311-objs := ad73311.o
snd-soc-adau1701-objs := adau1701.o
+snd-soc-adau1373-objs := adau1373.o
snd-soc-adav80x-objs := adav80x.o
snd-soc-ads117x-objs := ads117x.o
snd-soc-ak4104-objs := ak4104.o
@@ -14,19 +15,26 @@ snd-soc-ak4642-objs := ak4642.o
snd-soc-ak4671-objs := ak4671.o
snd-soc-cq93vc-objs := cq93vc.o
snd-soc-cs42l51-objs := cs42l51.o
+snd-soc-cs42l73-objs := cs42l73.o
snd-soc-cs4270-objs := cs4270.o
snd-soc-cs4271-objs := cs4271.o
snd-soc-cx20442-objs := cx20442.o
snd-soc-da7210-objs := da7210.o
snd-soc-dfbmcs320-objs := dfbmcs320.o
snd-soc-dmic-objs := dmic.o
+snd-soc-jz4740-codec-objs := jz4740.o
snd-soc-l3-objs := l3.o
+snd-soc-lm4857-objs := lm4857.o
+snd-soc-max9768-objs := max9768.o
snd-soc-max98088-objs := max98088.o
snd-soc-max98095-objs := max98095.o
snd-soc-max9850-objs := max9850.o
snd-soc-pcm3008-objs := pcm3008.o
+snd-soc-rt5631-objs := rt5631.o
snd-soc-sgtl5000-objs := sgtl5000.o
snd-soc-alc5623-objs := alc5623.o
+snd-soc-alc5632-objs := alc5632.o
+snd-soc-sigmadsp-objs := sigmadsp.o
snd-soc-sn95031-objs := sn95031.o
snd-soc-spdif-objs := spdif_transciever.o
snd-soc-ssm2602-objs := ssm2602.o
@@ -43,6 +51,9 @@ snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
snd-soc-wl1273-objs := wl1273.o
snd-soc-wm1250-ev1-objs := wm1250-ev1.o
+snd-soc-wm2000-objs := wm2000.o
+snd-soc-wm2200-objs := wm2200.o
+snd-soc-wm5100-objs := wm5100.o wm5100-tables.o
snd-soc-wm8350-objs := wm8350.o
snd-soc-wm8400-objs := wm8400.o
snd-soc-wm8510-objs := wm8510.o
@@ -78,21 +89,18 @@ snd-soc-wm8988-objs := wm8988.o
snd-soc-wm8990-objs := wm8990.o
snd-soc-wm8991-objs := wm8991.o
snd-soc-wm8993-objs := wm8993.o
-snd-soc-wm8994-objs := wm8994.o wm8994-tables.o wm8958-dsp2.o
+snd-soc-wm8994-objs := wm8994.o wm8958-dsp2.o
snd-soc-wm8995-objs := wm8995.o
snd-soc-wm9081-objs := wm9081.o
+snd-soc-wm9090-objs := wm9090.o
snd-soc-wm9705-objs := wm9705.o
snd-soc-wm9712-objs := wm9712.o
snd-soc-wm9713-objs := wm9713.o
snd-soc-wm-hubs-objs := wm_hubs.o
-snd-soc-jz4740-codec-objs := jz4740.o
# Amp
-snd-soc-lm4857-objs := lm4857.o
snd-soc-max9877-objs := max9877.o
snd-soc-tpa6130a2-objs := tpa6130a2.o
-snd-soc-wm2000-objs := wm2000.o
-snd-soc-wm9090-objs := wm9090.o
obj-$(CONFIG_SND_SOC_88PM860X) += snd-soc-88pm860x.o
obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
@@ -100,6 +108,7 @@ obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o
obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o
obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
+obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o
obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o
obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o
obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o
@@ -109,8 +118,10 @@ obj-$(CONFIG_SND_SOC_AK4641) += snd-soc-ak4641.o
obj-$(CONFIG_SND_SOC_AK4642) += snd-soc-ak4642.o
obj-$(CONFIG_SND_SOC_AK4671) += snd-soc-ak4671.o
obj-$(CONFIG_SND_SOC_ALC5623) += snd-soc-alc5623.o
+obj-$(CONFIG_SND_SOC_ALC5632) += snd-soc-alc5632.o
obj-$(CONFIG_SND_SOC_CQ0093VC) += snd-soc-cq93vc.o
obj-$(CONFIG_SND_SOC_CS42L51) += snd-soc-cs42l51.o
+obj-$(CONFIG_SND_SOC_CS42L73) += snd-soc-cs42l73.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
obj-$(CONFIG_SND_SOC_CS4271) += snd-soc-cs4271.o
obj-$(CONFIG_SND_SOC_CX20442) += snd-soc-cx20442.o
@@ -118,12 +129,16 @@ obj-$(CONFIG_SND_SOC_DA7210) += snd-soc-da7210.o
obj-$(CONFIG_SND_SOC_DFBMCS320) += snd-soc-dfbmcs320.o
obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o
obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
+obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o
+obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o
obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o
obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o
obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o
obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
+obj-$(CONFIG_SND_SOC_RT5631) += snd-soc-rt5631.o
obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o
+obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o
obj-$(CONFIG_SND_SOC_SN95031) +=snd-soc-sn95031.o
obj-$(CONFIG_SND_SOC_SPDIF) += snd-soc-spdif.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
@@ -132,7 +147,7 @@ obj-$(CONFIG_SND_SOC_STAC9766) += snd-soc-stac9766.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
-obj-$(CONFIG_SND_SOC_TVL320AIC32X4) += snd-soc-tlv320aic32x4.o
+obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o
obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o
obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
@@ -140,6 +155,9 @@ obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
+obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
+obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o
+obj-$(CONFIG_SND_SOC_WM5100) += snd-soc-wm5100.o
obj-$(CONFIG_SND_SOC_WM8350) += snd-soc-wm8350.o
obj-$(CONFIG_SND_SOC_WM8400) += snd-soc-wm8400.o
obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
@@ -178,14 +196,12 @@ obj-$(CONFIG_SND_SOC_WM8993) += snd-soc-wm8993.o
obj-$(CONFIG_SND_SOC_WM8994) += snd-soc-wm8994.o
obj-$(CONFIG_SND_SOC_WM8995) += snd-soc-wm8995.o
obj-$(CONFIG_SND_SOC_WM9081) += snd-soc-wm9081.o
+obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
obj-$(CONFIG_SND_SOC_WM9705) += snd-soc-wm9705.o
obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
obj-$(CONFIG_SND_SOC_WM9713) += snd-soc-wm9713.o
obj-$(CONFIG_SND_SOC_WM_HUBS) += snd-soc-wm-hubs.o
# Amp
-obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o
obj-$(CONFIG_SND_SOC_MAX9877) += snd-soc-max9877.o
obj-$(CONFIG_SND_SOC_TPA6130A2) += snd-soc-tpa6130a2.o
-obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
-obj-$(CONFIG_SND_SOC_WM9090) += snd-soc-wm9090.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index 3c087936aa57..1bbad4c16d28 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/kernel.h>
#include <linux/device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/ac97_codec.h>
@@ -38,7 +39,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000)
-static struct snd_soc_dai_ops ac97_dai_ops = {
+static const struct snd_soc_dai_ops ac97_dai_ops = {
.prepare = ac97_prepare,
};
@@ -98,7 +99,7 @@ static int ac97_soc_remove(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int ac97_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
+static int ac97_soc_suspend(struct snd_soc_codec *codec)
{
snd_ac97_suspend(codec->ac97);
@@ -147,17 +148,7 @@ static struct platform_driver ac97_codec_driver = {
.remove = __devexit_p(ac97_remove),
};
-static int __init ac97_init(void)
-{
- return platform_driver_register(&ac97_codec_driver);
-}
-module_init(ac97_init);
-
-static void __exit ac97_exit(void)
-{
- platform_driver_unregister(&ac97_codec_driver);
-}
-module_exit(ac97_exit);
+module_platform_driver(ac97_codec_driver);
MODULE_DESCRIPTION("Soc Generic AC97 driver");
MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c
index 4e5c5726366b..12e3b4118557 100644
--- a/sound/soc/codecs/ad1836.c
+++ b/sound/soc/codecs/ad1836.c
@@ -189,7 +189,7 @@ static int ad1836_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_dai_ops ad1836_dai_ops = {
+static const struct snd_soc_dai_ops ad1836_dai_ops = {
.hw_params = ad1836_hw_params,
.set_fmt = ad1836_set_dai_fmt,
};
@@ -223,7 +223,7 @@ static struct snd_soc_dai_driver ad183x_dais[] = {
};
#ifdef CONFIG_PM
-static int ad1836_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ad1836_suspend(struct snd_soc_codec *codec)
{
/* reset clock control mode */
return snd_soc_update_bits(codec, AD1836_ADC_CTRL2,
@@ -277,7 +277,7 @@ static int ad1836_probe(struct snd_soc_codec *codec)
if (ad1836->type == AD1836) {
/* left/right diff:PGA/MUX */
snd_soc_write(codec, AD1836_ADC_CTRL3, 0x3A);
- ret = snd_soc_add_controls(codec, ad1836_controls,
+ ret = snd_soc_add_codec_controls(codec, ad1836_controls,
ARRAY_SIZE(ad1836_controls));
if (ret)
return ret;
@@ -285,11 +285,11 @@ static int ad1836_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, AD1836_ADC_CTRL3, 0x00);
}
- ret = snd_soc_add_controls(codec, ad183x_dac_controls, num_dacs * 2);
+ ret = snd_soc_add_codec_controls(codec, ad183x_dac_controls, num_dacs * 2);
if (ret)
return ret;
- ret = snd_soc_add_controls(codec, ad183x_adc_controls, num_adcs);
+ ret = snd_soc_add_codec_controls(codec, ad183x_adc_controls, num_adcs);
if (ret)
return ret;
@@ -341,7 +341,8 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi)
struct ad1836_priv *ad1836;
int ret;
- ad1836 = kzalloc(sizeof(struct ad1836_priv), GFP_KERNEL);
+ ad1836 = devm_kzalloc(&spi->dev, sizeof(struct ad1836_priv),
+ GFP_KERNEL);
if (ad1836 == NULL)
return -ENOMEM;
@@ -351,17 +352,15 @@ static int __devinit ad1836_spi_probe(struct spi_device *spi)
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_ad1836, &ad183x_dais[ad1836->type], 1);
- if (ret < 0)
- kfree(ad1836);
return ret;
}
static int __devexit ad1836_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
return 0;
}
+
static const struct spi_device_id ad1836_ids[] = {
{ "ad1835", AD1835 },
{ "ad1836", AD1836 },
diff --git a/sound/soc/codecs/ad1836.h b/sound/soc/codecs/ad1836.h
index 444747f0db26..dd7be0dbbc58 100644
--- a/sound/soc/codecs/ad1836.h
+++ b/sound/soc/codecs/ad1836.h
@@ -34,7 +34,7 @@
#define AD1836_ADC_CTRL2 13
#define AD1836_ADC_WORD_LEN_MASK 0x30
-#define AD1836_ADC_WORD_OFFSET 5
+#define AD1836_ADC_WORD_OFFSET 4
#define AD1836_ADC_SERFMT_MASK (7 << 6)
#define AD1836_ADC_SERFMT_PCK256 (0x4 << 6)
#define AD1836_ADC_SERFMT_PCK128 (0x5 << 6)
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c
index eedb6f5e5823..a4a6bef2c0bb 100644
--- a/sound/soc/codecs/ad193x.c
+++ b/sound/soc/codecs/ad193x.c
@@ -23,28 +23,30 @@
/* codec private data */
struct ad193x_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
int sysclk;
};
/*
* AD193X volume/mute/de-emphasis etc. controls
*/
-static const char *ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
+static const char * const ad193x_deemp[] = {"None", "48kHz", "44.1kHz", "32kHz"};
static const struct soc_enum ad193x_deemp_enum =
SOC_ENUM_SINGLE(AD193X_DAC_CTRL2, 1, 4, ad193x_deemp);
+static const DECLARE_TLV_DB_MINMAX(adau193x_tlv, -9563, 0);
+
static const struct snd_kcontrol_new ad193x_snd_controls[] = {
/* DAC volume control */
- SOC_DOUBLE_R("DAC1 Volume", AD193X_DAC_L1_VOL,
- AD193X_DAC_R1_VOL, 0, 0xFF, 1),
- SOC_DOUBLE_R("DAC2 Volume", AD193X_DAC_L2_VOL,
- AD193X_DAC_R2_VOL, 0, 0xFF, 1),
- SOC_DOUBLE_R("DAC3 Volume", AD193X_DAC_L3_VOL,
- AD193X_DAC_R3_VOL, 0, 0xFF, 1),
- SOC_DOUBLE_R("DAC4 Volume", AD193X_DAC_L4_VOL,
- AD193X_DAC_R4_VOL, 0, 0xFF, 1),
+ SOC_DOUBLE_R_TLV("DAC1 Volume", AD193X_DAC_L1_VOL,
+ AD193X_DAC_R1_VOL, 0, 0xFF, 1, adau193x_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Volume", AD193X_DAC_L2_VOL,
+ AD193X_DAC_R2_VOL, 0, 0xFF, 1, adau193x_tlv),
+ SOC_DOUBLE_R_TLV("DAC3 Volume", AD193X_DAC_L3_VOL,
+ AD193X_DAC_R3_VOL, 0, 0xFF, 1, adau193x_tlv),
+ SOC_DOUBLE_R_TLV("DAC4 Volume", AD193X_DAC_L4_VOL,
+ AD193X_DAC_R4_VOL, 0, 0xFF, 1, adau193x_tlv),
/* ADC switch control */
SOC_DOUBLE("ADC1 Switch", AD193X_ADC_CTRL0, AD193X_ADCL1_MUTE,
@@ -75,6 +77,7 @@ static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = {
SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0),
SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("DAC1OUT"),
SND_SOC_DAPM_OUTPUT("DAC2OUT"),
SND_SOC_DAPM_OUTPUT("DAC3OUT"),
@@ -84,16 +87,17 @@ static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = {
};
static const struct snd_soc_dapm_route audio_paths[] = {
- { "DAC", NULL, "PLL_PWR" },
- { "ADC", NULL, "PLL_PWR" },
+ { "DAC", NULL, "SYSCLK" },
+ { "ADC", NULL, "SYSCLK" },
{ "DAC", NULL, "ADC_PWR" },
{ "ADC", NULL, "ADC_PWR" },
- { "DAC1OUT", "DAC1 Switch", "DAC" },
- { "DAC2OUT", "DAC2 Switch", "DAC" },
- { "DAC3OUT", "DAC3 Switch", "DAC" },
- { "DAC4OUT", "DAC4 Switch", "DAC" },
- { "ADC", "ADC1 Switch", "ADC1IN" },
- { "ADC", "ADC2 Switch", "ADC2IN" },
+ { "DAC1OUT", NULL, "DAC" },
+ { "DAC2OUT", NULL, "DAC" },
+ { "DAC3OUT", NULL, "DAC" },
+ { "DAC4OUT", NULL, "DAC" },
+ { "ADC", NULL, "ADC1IN" },
+ { "ADC", NULL, "ADC2IN" },
+ { "SYSCLK", NULL, "PLL_PWR" },
};
/*
@@ -102,13 +106,15 @@ static const struct snd_soc_dapm_route audio_paths[] = {
static int ad193x_mute(struct snd_soc_dai *dai, int mute)
{
- struct snd_soc_codec *codec = dai->codec;
- int reg;
+ struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec);
- reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
- reg = (mute > 0) ? reg | AD193X_DAC_MASTER_MUTE : reg &
- (~AD193X_DAC_MASTER_MUTE);
- snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
+ if (mute)
+ regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
+ AD193X_DAC_MASTER_MUTE,
+ AD193X_DAC_MASTER_MUTE);
+ else
+ regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
+ AD193X_DAC_MASTER_MUTE, 0);
return 0;
}
@@ -116,36 +122,30 @@ static int ad193x_mute(struct snd_soc_dai *dai, int mute)
static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
unsigned int rx_mask, int slots, int width)
{
- struct snd_soc_codec *codec = dai->codec;
- int dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
- int adc_reg = snd_soc_read(codec, AD193X_ADC_CTRL2);
-
- dac_reg &= ~AD193X_DAC_CHAN_MASK;
- adc_reg &= ~AD193X_ADC_CHAN_MASK;
+ struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(dai->codec);
+ unsigned int channels;
switch (slots) {
case 2:
- dac_reg |= AD193X_DAC_2_CHANNELS << AD193X_DAC_CHAN_SHFT;
- adc_reg |= AD193X_ADC_2_CHANNELS << AD193X_ADC_CHAN_SHFT;
+ channels = AD193X_2_CHANNELS;
break;
case 4:
- dac_reg |= AD193X_DAC_4_CHANNELS << AD193X_DAC_CHAN_SHFT;
- adc_reg |= AD193X_ADC_4_CHANNELS << AD193X_ADC_CHAN_SHFT;
+ channels = AD193X_4_CHANNELS;
break;
case 8:
- dac_reg |= AD193X_DAC_8_CHANNELS << AD193X_DAC_CHAN_SHFT;
- adc_reg |= AD193X_ADC_8_CHANNELS << AD193X_ADC_CHAN_SHFT;
+ channels = AD193X_8_CHANNELS;
break;
case 16:
- dac_reg |= AD193X_DAC_16_CHANNELS << AD193X_DAC_CHAN_SHFT;
- adc_reg |= AD193X_ADC_16_CHANNELS << AD193X_ADC_CHAN_SHFT;
+ channels = AD193X_16_CHANNELS;
break;
default:
return -EINVAL;
}
- snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
- snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg);
+ regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
+ AD193X_DAC_CHAN_MASK, channels << AD193X_DAC_CHAN_SHFT);
+ regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
+ AD193X_ADC_CHAN_MASK, channels << AD193X_ADC_CHAN_SHFT);
return 0;
}
@@ -153,24 +153,20 @@ static int ad193x_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask,
static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
- struct snd_soc_codec *codec = codec_dai->codec;
- int adc_reg1, adc_reg2, dac_reg;
-
- adc_reg1 = snd_soc_read(codec, AD193X_ADC_CTRL1);
- adc_reg2 = snd_soc_read(codec, AD193X_ADC_CTRL2);
- dac_reg = snd_soc_read(codec, AD193X_DAC_CTRL1);
+ struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec_dai->codec);
+ unsigned int adc_serfmt = 0;
+ unsigned int adc_fmt = 0;
+ unsigned int dac_fmt = 0;
/* At present, the driver only support AUX ADC mode(SND_SOC_DAIFMT_I2S
* with TDM) and ADC&DAC TDM mode(SND_SOC_DAIFMT_DSP_A)
*/
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
- adc_reg1 &= ~AD193X_ADC_SERFMT_MASK;
- adc_reg1 |= AD193X_ADC_SERFMT_TDM;
+ adc_serfmt |= AD193X_ADC_SERFMT_TDM;
break;
case SND_SOC_DAIFMT_DSP_A:
- adc_reg1 &= ~AD193X_ADC_SERFMT_MASK;
- adc_reg1 |= AD193X_ADC_SERFMT_AUX;
+ adc_serfmt |= AD193X_ADC_SERFMT_AUX;
break;
default:
return -EINVAL;
@@ -178,29 +174,20 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF: /* normal bit clock + frame */
- adc_reg2 &= ~AD193X_ADC_LEFT_HIGH;
- adc_reg2 &= ~AD193X_ADC_BCLK_INV;
- dac_reg &= ~AD193X_DAC_LEFT_HIGH;
- dac_reg &= ~AD193X_DAC_BCLK_INV;
break;
case SND_SOC_DAIFMT_NB_IF: /* normal bclk + invert frm */
- adc_reg2 |= AD193X_ADC_LEFT_HIGH;
- adc_reg2 &= ~AD193X_ADC_BCLK_INV;
- dac_reg |= AD193X_DAC_LEFT_HIGH;
- dac_reg &= ~AD193X_DAC_BCLK_INV;
+ adc_fmt |= AD193X_ADC_LEFT_HIGH;
+ dac_fmt |= AD193X_DAC_LEFT_HIGH;
break;
case SND_SOC_DAIFMT_IB_NF: /* invert bclk + normal frm */
- adc_reg2 &= ~AD193X_ADC_LEFT_HIGH;
- adc_reg2 |= AD193X_ADC_BCLK_INV;
- dac_reg &= ~AD193X_DAC_LEFT_HIGH;
- dac_reg |= AD193X_DAC_BCLK_INV;
+ adc_fmt |= AD193X_ADC_BCLK_INV;
+ dac_fmt |= AD193X_DAC_BCLK_INV;
break;
-
case SND_SOC_DAIFMT_IB_IF: /* invert bclk + frm */
- adc_reg2 |= AD193X_ADC_LEFT_HIGH;
- adc_reg2 |= AD193X_ADC_BCLK_INV;
- dac_reg |= AD193X_DAC_LEFT_HIGH;
- dac_reg |= AD193X_DAC_BCLK_INV;
+ adc_fmt |= AD193X_ADC_LEFT_HIGH;
+ adc_fmt |= AD193X_ADC_BCLK_INV;
+ dac_fmt |= AD193X_DAC_LEFT_HIGH;
+ dac_fmt |= AD193X_DAC_BCLK_INV;
break;
default:
return -EINVAL;
@@ -208,36 +195,31 @@ static int ad193x_set_dai_fmt(struct snd_soc_dai *codec_dai,
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM: /* codec clk & frm master */
- adc_reg2 |= AD193X_ADC_LCR_MASTER;
- adc_reg2 |= AD193X_ADC_BCLK_MASTER;
- dac_reg |= AD193X_DAC_LCR_MASTER;
- dac_reg |= AD193X_DAC_BCLK_MASTER;
+ adc_fmt |= AD193X_ADC_LCR_MASTER;
+ adc_fmt |= AD193X_ADC_BCLK_MASTER;
+ dac_fmt |= AD193X_DAC_LCR_MASTER;
+ dac_fmt |= AD193X_DAC_BCLK_MASTER;
break;
case SND_SOC_DAIFMT_CBS_CFM: /* codec clk slave & frm master */
- adc_reg2 |= AD193X_ADC_LCR_MASTER;
- adc_reg2 &= ~AD193X_ADC_BCLK_MASTER;
- dac_reg |= AD193X_DAC_LCR_MASTER;
- dac_reg &= ~AD193X_DAC_BCLK_MASTER;
+ adc_fmt |= AD193X_ADC_LCR_MASTER;
+ dac_fmt |= AD193X_DAC_LCR_MASTER;
break;
case SND_SOC_DAIFMT_CBM_CFS: /* codec clk master & frame slave */
- adc_reg2 &= ~AD193X_ADC_LCR_MASTER;
- adc_reg2 |= AD193X_ADC_BCLK_MASTER;
- dac_reg &= ~AD193X_DAC_LCR_MASTER;
- dac_reg |= AD193X_DAC_BCLK_MASTER;
+ adc_fmt |= AD193X_ADC_BCLK_MASTER;
+ dac_fmt |= AD193X_DAC_BCLK_MASTER;
break;
case SND_SOC_DAIFMT_CBS_CFS: /* codec clk & frm slave */
- adc_reg2 &= ~AD193X_ADC_LCR_MASTER;
- adc_reg2 &= ~AD193X_ADC_BCLK_MASTER;
- dac_reg &= ~AD193X_DAC_LCR_MASTER;
- dac_reg &= ~AD193X_DAC_BCLK_MASTER;
break;
default:
return -EINVAL;
}
- snd_soc_write(codec, AD193X_ADC_CTRL1, adc_reg1);
- snd_soc_write(codec, AD193X_ADC_CTRL2, adc_reg2);
- snd_soc_write(codec, AD193X_DAC_CTRL1, dac_reg);
+ regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1,
+ AD193X_ADC_SERFMT_MASK, adc_serfmt);
+ regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL2,
+ AD193X_ADC_FMT_MASK, adc_fmt);
+ regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL1,
+ AD193X_DAC_FMT_MASK, dac_fmt);
return 0;
}
@@ -262,7 +244,7 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- int word_len = 0, reg = 0, master_rate = 0;
+ int word_len = 0, master_rate = 0;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
@@ -297,23 +279,20 @@ static int ad193x_hw_params(struct snd_pcm_substream *substream,
break;
}
- reg = snd_soc_read(codec, AD193X_PLL_CLK_CTRL0);
- reg = (reg & AD193X_PLL_INPUT_MASK) | master_rate;
- snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, reg);
+ regmap_update_bits(ad193x->regmap, AD193X_PLL_CLK_CTRL0,
+ AD193X_PLL_INPUT_MASK, master_rate);
- reg = snd_soc_read(codec, AD193X_DAC_CTRL2);
- reg = (reg & (~AD193X_DAC_WORD_LEN_MASK))
- | (word_len << AD193X_DAC_WORD_LEN_SHFT);
- snd_soc_write(codec, AD193X_DAC_CTRL2, reg);
+ regmap_update_bits(ad193x->regmap, AD193X_DAC_CTRL2,
+ AD193X_DAC_WORD_LEN_MASK,
+ word_len << AD193X_DAC_WORD_LEN_SHFT);
- reg = snd_soc_read(codec, AD193X_ADC_CTRL1);
- reg = (reg & (~AD193X_ADC_WORD_LEN_MASK)) | word_len;
- snd_soc_write(codec, AD193X_ADC_CTRL1, reg);
+ regmap_update_bits(ad193x->regmap, AD193X_ADC_CTRL1,
+ AD193X_ADC_WORD_LEN_MASK, word_len);
return 0;
}
-static struct snd_soc_dai_ops ad193x_dai_ops = {
+static const struct snd_soc_dai_ops ad193x_dai_ops = {
.hw_params = ad193x_hw_params,
.digital_mute = ad193x_mute,
.set_tdm_slot = ad193x_set_tdm_slot,
@@ -346,13 +325,10 @@ static struct snd_soc_dai_driver ad193x_dai = {
static int ad193x_probe(struct snd_soc_codec *codec)
{
struct ad193x_priv *ad193x = snd_soc_codec_get_drvdata(codec);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
- if (ad193x->control_type == SND_SOC_I2C)
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->control_type);
- else
- ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->control_type);
+ codec->control_data = ad193x->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
return ret;
@@ -361,56 +337,86 @@ static int ad193x_probe(struct snd_soc_codec *codec)
/* default setting for ad193x */
/* unmute dac channels */
- snd_soc_write(codec, AD193X_DAC_CHNL_MUTE, 0x0);
+ regmap_write(ad193x->regmap, AD193X_DAC_CHNL_MUTE, 0x0);
/* de-emphasis: 48kHz, powedown dac */
- snd_soc_write(codec, AD193X_DAC_CTRL2, 0x1A);
+ regmap_write(ad193x->regmap, AD193X_DAC_CTRL2, 0x1A);
/* powerdown dac, dac in tdm mode */
- snd_soc_write(codec, AD193X_DAC_CTRL0, 0x41);
+ regmap_write(ad193x->regmap, AD193X_DAC_CTRL0, 0x41);
/* high-pass filter enable */
- snd_soc_write(codec, AD193X_ADC_CTRL0, 0x3);
+ regmap_write(ad193x->regmap, AD193X_ADC_CTRL0, 0x3);
/* sata delay=1, adc aux mode */
- snd_soc_write(codec, AD193X_ADC_CTRL1, 0x43);
+ regmap_write(ad193x->regmap, AD193X_ADC_CTRL1, 0x43);
/* pll input: mclki/xi */
- snd_soc_write(codec, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
- snd_soc_write(codec, AD193X_PLL_CLK_CTRL1, 0x04);
-
- snd_soc_add_controls(codec, ad193x_snd_controls,
- ARRAY_SIZE(ad193x_snd_controls));
- snd_soc_dapm_new_controls(dapm, ad193x_dapm_widgets,
- ARRAY_SIZE(ad193x_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_paths, ARRAY_SIZE(audio_paths));
+ regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL0, 0x99); /* mclk=24.576Mhz: 0x9D; mclk=12.288Mhz: 0x99 */
+ regmap_write(ad193x->regmap, AD193X_PLL_CLK_CTRL1, 0x04);
return ret;
}
static struct snd_soc_codec_driver soc_codec_dev_ad193x = {
.probe = ad193x_probe,
+ .controls = ad193x_snd_controls,
+ .num_controls = ARRAY_SIZE(ad193x_snd_controls),
+ .dapm_widgets = ad193x_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(ad193x_dapm_widgets),
+ .dapm_routes = audio_paths,
+ .num_dapm_routes = ARRAY_SIZE(audio_paths),
};
+static bool adau193x_reg_volatile(struct device *dev, unsigned int reg)
+{
+ return false;
+}
+
#if defined(CONFIG_SPI_MASTER)
+
+static const struct regmap_config ad193x_spi_regmap_config = {
+ .val_bits = 8,
+ .reg_bits = 16,
+ .read_flag_mask = 0x09,
+ .write_flag_mask = 0x08,
+
+ .max_register = AD193X_NUM_REGS - 1,
+ .volatile_reg = adau193x_reg_volatile,
+};
+
static int __devinit ad193x_spi_probe(struct spi_device *spi)
{
struct ad193x_priv *ad193x;
int ret;
- ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
+ ad193x = devm_kzalloc(&spi->dev, sizeof(struct ad193x_priv),
+ GFP_KERNEL);
if (ad193x == NULL)
return -ENOMEM;
+ ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config);
+ if (IS_ERR(ad193x->regmap)) {
+ ret = PTR_ERR(ad193x->regmap);
+ goto err_out;
+ }
+
spi_set_drvdata(spi, ad193x);
- ad193x->control_type = SND_SOC_SPI;
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_ad193x, &ad193x_dai, 1);
if (ret < 0)
- kfree(ad193x);
+ goto err_regmap_exit;
+
+ return 0;
+
+err_regmap_exit:
+ regmap_exit(ad193x->regmap);
+err_out:
return ret;
}
static int __devexit ad193x_spi_remove(struct spi_device *spi)
{
+ struct ad193x_priv *ad193x = spi_get_drvdata(spi);
+
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(ad193x->regmap);
return 0;
}
@@ -425,6 +431,15 @@ static struct spi_driver ad193x_spi_driver = {
#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+static const struct regmap_config ad193x_i2c_regmap_config = {
+ .val_bits = 8,
+ .reg_bits = 8,
+
+ .max_register = AD193X_NUM_REGS - 1,
+ .volatile_reg = adau193x_reg_volatile,
+};
+
static const struct i2c_device_id ad193x_id[] = {
{ "ad1936", 0 },
{ "ad1937", 0 },
@@ -438,24 +453,38 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client,
struct ad193x_priv *ad193x;
int ret;
- ad193x = kzalloc(sizeof(struct ad193x_priv), GFP_KERNEL);
+ ad193x = devm_kzalloc(&client->dev, sizeof(struct ad193x_priv),
+ GFP_KERNEL);
if (ad193x == NULL)
return -ENOMEM;
+ ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config);
+ if (IS_ERR(ad193x->regmap)) {
+ ret = PTR_ERR(ad193x->regmap);
+ goto err_out;
+ }
+
i2c_set_clientdata(client, ad193x);
- ad193x->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&client->dev,
&soc_codec_dev_ad193x, &ad193x_dai, 1);
if (ret < 0)
- kfree(ad193x);
+ goto err_regmap_exit;
+
+ return 0;
+
+err_regmap_exit:
+ regmap_exit(ad193x->regmap);
+err_out:
return ret;
}
static int __devexit ad193x_i2c_remove(struct i2c_client *client)
{
+ struct ad193x_priv *ad193x = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(ad193x->regmap);
return 0;
}
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h
index cccc2e8e5fbd..473388049992 100644
--- a/sound/soc/codecs/ad193x.h
+++ b/sound/soc/codecs/ad193x.h
@@ -9,35 +9,33 @@
#ifndef __AD193X_H__
#define __AD193X_H__
-#define AD193X_PLL_CLK_CTRL0 0x800
+#define AD193X_PLL_CLK_CTRL0 0x00
#define AD193X_PLL_POWERDOWN 0x01
-#define AD193X_PLL_INPUT_MASK (~0x6)
+#define AD193X_PLL_INPUT_MASK 0x6
#define AD193X_PLL_INPUT_256 (0 << 1)
#define AD193X_PLL_INPUT_384 (1 << 1)
#define AD193X_PLL_INPUT_512 (2 << 1)
#define AD193X_PLL_INPUT_768 (3 << 1)
-#define AD193X_PLL_CLK_CTRL1 0x801
-#define AD193X_DAC_CTRL0 0x802
+#define AD193X_PLL_CLK_CTRL1 0x01
+#define AD193X_DAC_CTRL0 0x02
#define AD193X_DAC_POWERDOWN 0x01
#define AD193X_DAC_SERFMT_MASK 0xC0
#define AD193X_DAC_SERFMT_STEREO (0 << 6)
#define AD193X_DAC_SERFMT_TDM (1 << 6)
-#define AD193X_DAC_CTRL1 0x803
-#define AD193X_DAC_2_CHANNELS 0
-#define AD193X_DAC_4_CHANNELS 1
-#define AD193X_DAC_8_CHANNELS 2
-#define AD193X_DAC_16_CHANNELS 3
+#define AD193X_DAC_CTRL1 0x03
#define AD193X_DAC_CHAN_SHFT 1
#define AD193X_DAC_CHAN_MASK (3 << AD193X_DAC_CHAN_SHFT)
#define AD193X_DAC_LCR_MASTER (1 << 4)
#define AD193X_DAC_BCLK_MASTER (1 << 5)
#define AD193X_DAC_LEFT_HIGH (1 << 3)
#define AD193X_DAC_BCLK_INV (1 << 7)
-#define AD193X_DAC_CTRL2 0x804
+#define AD193X_DAC_FMT_MASK (AD193X_DAC_LCR_MASTER | \
+ AD193X_DAC_BCLK_MASTER | AD193X_DAC_LEFT_HIGH | AD193X_DAC_BCLK_INV)
+#define AD193X_DAC_CTRL2 0x04
#define AD193X_DAC_WORD_LEN_SHFT 3
#define AD193X_DAC_WORD_LEN_MASK 0x18
#define AD193X_DAC_MASTER_MUTE 1
-#define AD193X_DAC_CHNL_MUTE 0x805
+#define AD193X_DAC_CHNL_MUTE 0x05
#define AD193X_DACL1_MUTE 0
#define AD193X_DACR1_MUTE 1
#define AD193X_DACL2_MUTE 2
@@ -46,38 +44,41 @@
#define AD193X_DACR3_MUTE 5
#define AD193X_DACL4_MUTE 6
#define AD193X_DACR4_MUTE 7
-#define AD193X_DAC_L1_VOL 0x806
-#define AD193X_DAC_R1_VOL 0x807
-#define AD193X_DAC_L2_VOL 0x808
-#define AD193X_DAC_R2_VOL 0x809
-#define AD193X_DAC_L3_VOL 0x80a
-#define AD193X_DAC_R3_VOL 0x80b
-#define AD193X_DAC_L4_VOL 0x80c
-#define AD193X_DAC_R4_VOL 0x80d
-#define AD193X_ADC_CTRL0 0x80e
+#define AD193X_DAC_L1_VOL 0x06
+#define AD193X_DAC_R1_VOL 0x07
+#define AD193X_DAC_L2_VOL 0x08
+#define AD193X_DAC_R2_VOL 0x09
+#define AD193X_DAC_L3_VOL 0x0a
+#define AD193X_DAC_R3_VOL 0x0b
+#define AD193X_DAC_L4_VOL 0x0c
+#define AD193X_DAC_R4_VOL 0x0d
+#define AD193X_ADC_CTRL0 0x0e
#define AD193X_ADC_POWERDOWN 0x01
#define AD193X_ADC_HIGHPASS_FILTER 1
#define AD193X_ADCL1_MUTE 2
#define AD193X_ADCR1_MUTE 3
#define AD193X_ADCL2_MUTE 4
#define AD193X_ADCR2_MUTE 5
-#define AD193X_ADC_CTRL1 0x80f
+#define AD193X_ADC_CTRL1 0x0f
#define AD193X_ADC_SERFMT_MASK 0x60
#define AD193X_ADC_SERFMT_STEREO (0 << 5)
#define AD193X_ADC_SERFMT_TDM (1 << 5)
#define AD193X_ADC_SERFMT_AUX (2 << 5)
#define AD193X_ADC_WORD_LEN_MASK 0x3
-#define AD193X_ADC_CTRL2 0x810
-#define AD193X_ADC_2_CHANNELS 0
-#define AD193X_ADC_4_CHANNELS 1
-#define AD193X_ADC_8_CHANNELS 2
-#define AD193X_ADC_16_CHANNELS 3
+#define AD193X_ADC_CTRL2 0x10
#define AD193X_ADC_CHAN_SHFT 4
#define AD193X_ADC_CHAN_MASK (3 << AD193X_ADC_CHAN_SHFT)
#define AD193X_ADC_LCR_MASTER (1 << 3)
#define AD193X_ADC_BCLK_MASTER (1 << 6)
#define AD193X_ADC_LEFT_HIGH (1 << 2)
#define AD193X_ADC_BCLK_INV (1 << 1)
+#define AD193X_ADC_FMT_MASK (AD193X_ADC_LCR_MASTER | \
+ AD193X_ADC_BCLK_MASTER | AD193X_ADC_LEFT_HIGH | AD193X_ADC_BCLK_INV)
+
+#define AD193X_2_CHANNELS 0
+#define AD193X_4_CHANNELS 1
+#define AD193X_8_CHANNELS 2
+#define AD193X_16_CHANNELS 3
#define AD193X_NUM_REGS 17
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 923b364a3e41..8c39dddd7d00 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -148,7 +148,6 @@ static struct snd_soc_dai_driver ad1980_dai = {
.rates = SNDRV_PCM_RATE_48000,
.formats = SND_SOC_STD_AC97_FMTS, },
};
-EXPORT_SYMBOL_GPL(ad1980_dai);
static int ad1980_reset(struct snd_soc_codec *codec, int try_warm)
{
@@ -200,18 +199,22 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
}
/* Read out vendor ID to make sure it is ad1980 */
- if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144)
+ if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) {
+ ret = -ENODEV;
goto reset_err;
+ }
vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2);
if (vendor_id2 != 0x5370) {
- if (vendor_id2 != 0x5374)
+ if (vendor_id2 != 0x5374) {
+ ret = -ENODEV;
goto reset_err;
- else
+ } else {
printk(KERN_WARNING "ad1980: "
"Found AD1981 - only 2/2 IN/OUT Channels "
"supported\n");
+ }
}
/* unmute captures and playbacks volume */
@@ -225,7 +228,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec)
ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
- snd_soc_add_controls(codec, ad1980_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, ad1980_snd_ac97_controls,
ARRAY_SIZE(ad1980_snd_ac97_controls));
return 0;
@@ -274,17 +277,7 @@ static struct platform_driver ad1980_codec_driver = {
.remove = __devexit_p(ad1980_remove),
};
-static int __init ad1980_init(void)
-{
- return platform_driver_register(&ad1980_codec_driver);
-}
-module_init(ad1980_init);
-
-static void __exit ad1980_exit(void)
-{
- platform_driver_unregister(&ad1980_codec_driver);
-}
-module_exit(ad1980_exit);
+module_platform_driver(ad1980_codec_driver);
MODULE_DESCRIPTION("ASoC ad1980 driver (Obsolete)");
MODULE_AUTHOR("Roy Huang, Cliff Cai");
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index 8d793e993e9a..ee7a68dcefd2 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -63,17 +63,7 @@ static struct platform_driver ad73311_codec_driver = {
.remove = __devexit_p(ad73311_remove),
};
-static int __init ad73311_init(void)
-{
- return platform_driver_register(&ad73311_codec_driver);
-}
-module_init(ad73311_init);
-
-static void __exit ad73311_exit(void)
-{
- platform_driver_unregister(&ad73311_codec_driver);
-}
-module_exit(ad73311_exit);
+module_platform_driver(ad73311_codec_driver);
MODULE_DESCRIPTION("ASoC ad73311 driver");
MODULE_AUTHOR("Cliff Cai ");
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c
new file mode 100644
index 000000000000..44f59064d8de
--- /dev/null
+++ b/sound/soc/codecs/adau1373.c
@@ -0,0 +1,1409 @@
+/*
+ * Analog Devices ADAU1373 Audio Codec drive
+ *
+ * Copyright 2011 Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/gcd.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/adau1373.h>
+
+#include "adau1373.h"
+
+struct adau1373_dai {
+ unsigned int clk_src;
+ unsigned int sysclk;
+ bool enable_src;
+ bool master;
+};
+
+struct adau1373 {
+ struct adau1373_dai dais[3];
+};
+
+#define ADAU1373_INPUT_MODE 0x00
+#define ADAU1373_AINL_CTRL(x) (0x01 + (x) * 2)
+#define ADAU1373_AINR_CTRL(x) (0x02 + (x) * 2)
+#define ADAU1373_LLINE_OUT(x) (0x9 + (x) * 2)
+#define ADAU1373_RLINE_OUT(x) (0xa + (x) * 2)
+#define ADAU1373_LSPK_OUT 0x0d
+#define ADAU1373_RSPK_OUT 0x0e
+#define ADAU1373_LHP_OUT 0x0f
+#define ADAU1373_RHP_OUT 0x10
+#define ADAU1373_ADC_GAIN 0x11
+#define ADAU1373_LADC_MIXER 0x12
+#define ADAU1373_RADC_MIXER 0x13
+#define ADAU1373_LLINE1_MIX 0x14
+#define ADAU1373_RLINE1_MIX 0x15
+#define ADAU1373_LLINE2_MIX 0x16
+#define ADAU1373_RLINE2_MIX 0x17
+#define ADAU1373_LSPK_MIX 0x18
+#define ADAU1373_RSPK_MIX 0x19
+#define ADAU1373_LHP_MIX 0x1a
+#define ADAU1373_RHP_MIX 0x1b
+#define ADAU1373_EP_MIX 0x1c
+#define ADAU1373_HP_CTRL 0x1d
+#define ADAU1373_HP_CTRL2 0x1e
+#define ADAU1373_LS_CTRL 0x1f
+#define ADAU1373_EP_CTRL 0x21
+#define ADAU1373_MICBIAS_CTRL1 0x22
+#define ADAU1373_MICBIAS_CTRL2 0x23
+#define ADAU1373_OUTPUT_CTRL 0x24
+#define ADAU1373_PWDN_CTRL1 0x25
+#define ADAU1373_PWDN_CTRL2 0x26
+#define ADAU1373_PWDN_CTRL3 0x27
+#define ADAU1373_DPLL_CTRL(x) (0x28 + (x) * 7)
+#define ADAU1373_PLL_CTRL1(x) (0x29 + (x) * 7)
+#define ADAU1373_PLL_CTRL2(x) (0x2a + (x) * 7)
+#define ADAU1373_PLL_CTRL3(x) (0x2b + (x) * 7)
+#define ADAU1373_PLL_CTRL4(x) (0x2c + (x) * 7)
+#define ADAU1373_PLL_CTRL5(x) (0x2d + (x) * 7)
+#define ADAU1373_PLL_CTRL6(x) (0x2e + (x) * 7)
+#define ADAU1373_PLL_CTRL7(x) (0x2f + (x) * 7)
+#define ADAU1373_HEADDECT 0x36
+#define ADAU1373_ADC_DAC_STATUS 0x37
+#define ADAU1373_ADC_CTRL 0x3c
+#define ADAU1373_DAI(x) (0x44 + (x))
+#define ADAU1373_CLK_SRC_DIV(x) (0x40 + (x) * 2)
+#define ADAU1373_BCLKDIV(x) (0x47 + (x))
+#define ADAU1373_SRC_RATIOA(x) (0x4a + (x) * 2)
+#define ADAU1373_SRC_RATIOB(x) (0x4b + (x) * 2)
+#define ADAU1373_DEEMP_CTRL 0x50
+#define ADAU1373_SRC_DAI_CTRL(x) (0x51 + (x))
+#define ADAU1373_DIN_MIX_CTRL(x) (0x56 + (x))
+#define ADAU1373_DOUT_MIX_CTRL(x) (0x5b + (x))
+#define ADAU1373_DAI_PBL_VOL(x) (0x62 + (x) * 2)
+#define ADAU1373_DAI_PBR_VOL(x) (0x63 + (x) * 2)
+#define ADAU1373_DAI_RECL_VOL(x) (0x68 + (x) * 2)
+#define ADAU1373_DAI_RECR_VOL(x) (0x69 + (x) * 2)
+#define ADAU1373_DAC1_PBL_VOL 0x6e
+#define ADAU1373_DAC1_PBR_VOL 0x6f
+#define ADAU1373_DAC2_PBL_VOL 0x70
+#define ADAU1373_DAC2_PBR_VOL 0x71
+#define ADAU1373_ADC_RECL_VOL 0x72
+#define ADAU1373_ADC_RECR_VOL 0x73
+#define ADAU1373_DMIC_RECL_VOL 0x74
+#define ADAU1373_DMIC_RECR_VOL 0x75
+#define ADAU1373_VOL_GAIN1 0x76
+#define ADAU1373_VOL_GAIN2 0x77
+#define ADAU1373_VOL_GAIN3 0x78
+#define ADAU1373_HPF_CTRL 0x7d
+#define ADAU1373_BASS1 0x7e
+#define ADAU1373_BASS2 0x7f
+#define ADAU1373_DRC(x) (0x80 + (x) * 0x10)
+#define ADAU1373_3D_CTRL1 0xc0
+#define ADAU1373_3D_CTRL2 0xc1
+#define ADAU1373_FDSP_SEL1 0xdc
+#define ADAU1373_FDSP_SEL2 0xdd
+#define ADAU1373_FDSP_SEL3 0xde
+#define ADAU1373_FDSP_SEL4 0xdf
+#define ADAU1373_DIGMICCTRL 0xe2
+#define ADAU1373_DIGEN 0xeb
+#define ADAU1373_SOFT_RESET 0xff
+
+
+#define ADAU1373_PLL_CTRL6_DPLL_BYPASS BIT(1)
+#define ADAU1373_PLL_CTRL6_PLL_EN BIT(0)
+
+#define ADAU1373_DAI_INVERT_BCLK BIT(7)
+#define ADAU1373_DAI_MASTER BIT(6)
+#define ADAU1373_DAI_INVERT_LRCLK BIT(4)
+#define ADAU1373_DAI_WLEN_16 0x0
+#define ADAU1373_DAI_WLEN_20 0x4
+#define ADAU1373_DAI_WLEN_24 0x8
+#define ADAU1373_DAI_WLEN_32 0xc
+#define ADAU1373_DAI_WLEN_MASK 0xc
+#define ADAU1373_DAI_FORMAT_RIGHT_J 0x0
+#define ADAU1373_DAI_FORMAT_LEFT_J 0x1
+#define ADAU1373_DAI_FORMAT_I2S 0x2
+#define ADAU1373_DAI_FORMAT_DSP 0x3
+
+#define ADAU1373_BCLKDIV_SOURCE BIT(5)
+#define ADAU1373_BCLKDIV_32 0x03
+#define ADAU1373_BCLKDIV_64 0x02
+#define ADAU1373_BCLKDIV_128 0x01
+#define ADAU1373_BCLKDIV_256 0x00
+
+#define ADAU1373_ADC_CTRL_PEAK_DETECT BIT(0)
+#define ADAU1373_ADC_CTRL_RESET BIT(1)
+#define ADAU1373_ADC_CTRL_RESET_FORCE BIT(2)
+
+#define ADAU1373_OUTPUT_CTRL_LDIFF BIT(3)
+#define ADAU1373_OUTPUT_CTRL_LNFBEN BIT(2)
+
+#define ADAU1373_PWDN_CTRL3_PWR_EN BIT(0)
+
+#define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4
+#define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2
+
+static const uint8_t adau1373_default_regs[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */
+ 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
+ 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */
+ 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
+ 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */
+ 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */
+ 0x00, 0x1f, 0x0f, 0x00, 0x00,
+};
+
+static const unsigned int adau1373_out_tlv[] = {
+ TLV_DB_RANGE_HEAD(4),
+ 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1),
+ 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0),
+ 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0),
+ 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0),
+};
+
+static const DECLARE_TLV_DB_MINMAX(adau1373_digital_tlv, -9563, 0);
+static const DECLARE_TLV_DB_SCALE(adau1373_in_pga_tlv, -1300, 100, 1);
+static const DECLARE_TLV_DB_SCALE(adau1373_ep_tlv, -600, 600, 1);
+
+static const DECLARE_TLV_DB_SCALE(adau1373_input_boost_tlv, 0, 2000, 0);
+static const DECLARE_TLV_DB_SCALE(adau1373_gain_boost_tlv, 0, 600, 0);
+static const DECLARE_TLV_DB_SCALE(adau1373_speaker_boost_tlv, 1200, 600, 0);
+
+static const char *adau1373_fdsp_sel_text[] = {
+ "None",
+ "Channel 1",
+ "Channel 2",
+ "Channel 3",
+ "Channel 4",
+ "Channel 5",
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum,
+ ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum,
+ ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum,
+ ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum,
+ ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum,
+ ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text);
+
+static const char *adau1373_hpf_cutoff_text[] = {
+ "3.7Hz", "50Hz", "100Hz", "150Hz", "200Hz", "250Hz", "300Hz", "350Hz",
+ "400Hz", "450Hz", "500Hz", "550Hz", "600Hz", "650Hz", "700Hz", "750Hz",
+ "800Hz",
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum,
+ ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text);
+
+static const char *adau1373_bass_lpf_cutoff_text[] = {
+ "801Hz", "1001Hz",
+};
+
+static const char *adau1373_bass_clip_level_text[] = {
+ "0.125", "0.250", "0.370", "0.500", "0.625", "0.750", "0.875",
+};
+
+static const unsigned int adau1373_bass_clip_level_values[] = {
+ 1, 2, 3, 4, 5, 6, 7,
+};
+
+static const char *adau1373_bass_hpf_cutoff_text[] = {
+ "158Hz", "232Hz", "347Hz", "520Hz",
+};
+
+static const unsigned int adau1373_bass_tlv[] = {
+ TLV_DB_RANGE_HEAD(3),
+ 0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1),
+ 3, 4, TLV_DB_SCALE_ITEM(950, 250, 0),
+ 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0),
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum,
+ ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text);
+
+static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum,
+ ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text,
+ adau1373_bass_clip_level_values);
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum,
+ ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text);
+
+static const char *adau1373_3d_level_text[] = {
+ "0%", "6.67%", "13.33%", "20%", "26.67%", "33.33%",
+ "40%", "46.67%", "53.33%", "60%", "66.67%", "73.33%",
+ "80%", "86.67", "99.33%", "100%"
+};
+
+static const char *adau1373_3d_cutoff_text[] = {
+ "No 3D", "0.03125 fs", "0.04583 fs", "0.075 fs", "0.11458 fs",
+ "0.16875 fs", "0.27083 fs"
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum,
+ ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum,
+ ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text);
+
+static const unsigned int adau1373_3d_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 1, 7, TLV_DB_LINEAR_ITEM(-1800, -120),
+};
+
+static const char *adau1373_lr_mux_text[] = {
+ "Mute",
+ "Right Channel (L+R)",
+ "Left Channel (L+R)",
+ "Stereo",
+};
+
+static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum,
+ ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum,
+ ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text);
+static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum,
+ ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text);
+
+static const struct snd_kcontrol_new adau1373_controls[] = {
+ SOC_DOUBLE_R_TLV("AIF1 Capture Volume", ADAU1373_DAI_RECL_VOL(0),
+ ADAU1373_DAI_RECR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv),
+ SOC_DOUBLE_R_TLV("AIF2 Capture Volume", ADAU1373_DAI_RECL_VOL(1),
+ ADAU1373_DAI_RECR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv),
+ SOC_DOUBLE_R_TLV("AIF3 Capture Volume", ADAU1373_DAI_RECL_VOL(2),
+ ADAU1373_DAI_RECR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv),
+
+ SOC_DOUBLE_R_TLV("ADC Capture Volume", ADAU1373_ADC_RECL_VOL,
+ ADAU1373_ADC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv),
+ SOC_DOUBLE_R_TLV("DMIC Capture Volume", ADAU1373_DMIC_RECL_VOL,
+ ADAU1373_DMIC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv),
+
+ SOC_DOUBLE_R_TLV("AIF1 Playback Volume", ADAU1373_DAI_PBL_VOL(0),
+ ADAU1373_DAI_PBR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv),
+ SOC_DOUBLE_R_TLV("AIF2 Playback Volume", ADAU1373_DAI_PBL_VOL(1),
+ ADAU1373_DAI_PBR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv),
+ SOC_DOUBLE_R_TLV("AIF3 Playback Volume", ADAU1373_DAI_PBL_VOL(2),
+ ADAU1373_DAI_PBR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv),
+
+ SOC_DOUBLE_R_TLV("DAC1 Playback Volume", ADAU1373_DAC1_PBL_VOL,
+ ADAU1373_DAC1_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv),
+ SOC_DOUBLE_R_TLV("DAC2 Playback Volume", ADAU1373_DAC2_PBL_VOL,
+ ADAU1373_DAC2_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv),
+
+ SOC_DOUBLE_R_TLV("Lineout1 Playback Volume", ADAU1373_LLINE_OUT(0),
+ ADAU1373_RLINE_OUT(0), 0, 0x1f, 0, adau1373_out_tlv),
+ SOC_DOUBLE_R_TLV("Speaker Playback Volume", ADAU1373_LSPK_OUT,
+ ADAU1373_RSPK_OUT, 0, 0x1f, 0, adau1373_out_tlv),
+ SOC_DOUBLE_R_TLV("Headphone Playback Volume", ADAU1373_LHP_OUT,
+ ADAU1373_RHP_OUT, 0, 0x1f, 0, adau1373_out_tlv),
+
+ SOC_DOUBLE_R_TLV("Input 1 Capture Volume", ADAU1373_AINL_CTRL(0),
+ ADAU1373_AINR_CTRL(0), 0, 0x1f, 0, adau1373_in_pga_tlv),
+ SOC_DOUBLE_R_TLV("Input 2 Capture Volume", ADAU1373_AINL_CTRL(1),
+ ADAU1373_AINR_CTRL(1), 0, 0x1f, 0, adau1373_in_pga_tlv),
+ SOC_DOUBLE_R_TLV("Input 3 Capture Volume", ADAU1373_AINL_CTRL(2),
+ ADAU1373_AINR_CTRL(2), 0, 0x1f, 0, adau1373_in_pga_tlv),
+ SOC_DOUBLE_R_TLV("Input 4 Capture Volume", ADAU1373_AINL_CTRL(3),
+ ADAU1373_AINR_CTRL(3), 0, 0x1f, 0, adau1373_in_pga_tlv),
+
+ SOC_SINGLE_TLV("Earpiece Playback Volume", ADAU1373_EP_CTRL, 0, 3, 0,
+ adau1373_ep_tlv),
+
+ SOC_DOUBLE_TLV("AIF3 Boost Playback Volume", ADAU1373_VOL_GAIN1, 4, 5,
+ 1, 0, adau1373_gain_boost_tlv),
+ SOC_DOUBLE_TLV("AIF2 Boost Playback Volume", ADAU1373_VOL_GAIN1, 2, 3,
+ 1, 0, adau1373_gain_boost_tlv),
+ SOC_DOUBLE_TLV("AIF1 Boost Playback Volume", ADAU1373_VOL_GAIN1, 0, 1,
+ 1, 0, adau1373_gain_boost_tlv),
+ SOC_DOUBLE_TLV("AIF3 Boost Capture Volume", ADAU1373_VOL_GAIN2, 4, 5,
+ 1, 0, adau1373_gain_boost_tlv),
+ SOC_DOUBLE_TLV("AIF2 Boost Capture Volume", ADAU1373_VOL_GAIN2, 2, 3,
+ 1, 0, adau1373_gain_boost_tlv),
+ SOC_DOUBLE_TLV("AIF1 Boost Capture Volume", ADAU1373_VOL_GAIN2, 0, 1,
+ 1, 0, adau1373_gain_boost_tlv),
+ SOC_DOUBLE_TLV("DMIC Boost Capture Volume", ADAU1373_VOL_GAIN3, 6, 7,
+ 1, 0, adau1373_gain_boost_tlv),
+ SOC_DOUBLE_TLV("ADC Boost Capture Volume", ADAU1373_VOL_GAIN3, 4, 5,
+ 1, 0, adau1373_gain_boost_tlv),
+ SOC_DOUBLE_TLV("DAC2 Boost Playback Volume", ADAU1373_VOL_GAIN3, 2, 3,
+ 1, 0, adau1373_gain_boost_tlv),
+ SOC_DOUBLE_TLV("DAC1 Boost Playback Volume", ADAU1373_VOL_GAIN3, 0, 1,
+ 1, 0, adau1373_gain_boost_tlv),
+
+ SOC_DOUBLE_TLV("Input 1 Boost Capture Volume", ADAU1373_ADC_GAIN, 0, 4,
+ 1, 0, adau1373_input_boost_tlv),
+ SOC_DOUBLE_TLV("Input 2 Boost Capture Volume", ADAU1373_ADC_GAIN, 1, 5,
+ 1, 0, adau1373_input_boost_tlv),
+ SOC_DOUBLE_TLV("Input 3 Boost Capture Volume", ADAU1373_ADC_GAIN, 2, 6,
+ 1, 0, adau1373_input_boost_tlv),
+ SOC_DOUBLE_TLV("Input 4 Boost Capture Volume", ADAU1373_ADC_GAIN, 3, 7,
+ 1, 0, adau1373_input_boost_tlv),
+
+ SOC_DOUBLE_TLV("Speaker Boost Playback Volume", ADAU1373_LS_CTRL, 2, 3,
+ 1, 0, adau1373_speaker_boost_tlv),
+
+ SOC_ENUM("Lineout1 LR Mux", adau1373_lineout1_lr_mux_enum),
+ SOC_ENUM("Speaker LR Mux", adau1373_speaker_lr_mux_enum),
+
+ SOC_ENUM("HPF Cutoff", adau1373_hpf_cutoff_enum),
+ SOC_DOUBLE("HPF Switch", ADAU1373_HPF_CTRL, 1, 0, 1, 0),
+ SOC_ENUM("HPF Channel", adau1373_hpf_channel_enum),
+
+ SOC_ENUM("Bass HPF Cutoff", adau1373_bass_hpf_cutoff_enum),
+ SOC_VALUE_ENUM("Bass Clip Level Threshold",
+ adau1373_bass_clip_level_enum),
+ SOC_ENUM("Bass LPF Cutoff", adau1373_bass_lpf_cutoff_enum),
+ SOC_DOUBLE("Bass Playback Switch", ADAU1373_BASS2, 0, 1, 1, 0),
+ SOC_SINGLE_TLV("Bass Playback Volume", ADAU1373_BASS2, 2, 7, 0,
+ adau1373_bass_tlv),
+ SOC_ENUM("Bass Channel", adau1373_bass_channel_enum),
+
+ SOC_ENUM("3D Freq", adau1373_3d_cutoff_enum),
+ SOC_ENUM("3D Level", adau1373_3d_level_enum),
+ SOC_SINGLE("3D Playback Switch", ADAU1373_3D_CTRL2, 0, 1, 0),
+ SOC_SINGLE_TLV("3D Playback Volume", ADAU1373_3D_CTRL2, 2, 7, 0,
+ adau1373_3d_tlv),
+ SOC_ENUM("3D Channel", adau1373_bass_channel_enum),
+
+ SOC_SINGLE("Zero Cross Switch", ADAU1373_PWDN_CTRL3, 7, 1, 0),
+};
+
+static const struct snd_kcontrol_new adau1373_lineout2_controls[] = {
+ SOC_DOUBLE_R_TLV("Lineout2 Playback Volume", ADAU1373_LLINE_OUT(1),
+ ADAU1373_RLINE_OUT(1), 0, 0x1f, 0, adau1373_out_tlv),
+ SOC_ENUM("Lineout2 LR Mux", adau1373_lineout2_lr_mux_enum),
+};
+
+static const struct snd_kcontrol_new adau1373_drc_controls[] = {
+ SOC_ENUM("DRC1 Channel", adau1373_drc1_channel_enum),
+ SOC_ENUM("DRC2 Channel", adau1373_drc2_channel_enum),
+ SOC_ENUM("DRC3 Channel", adau1373_drc3_channel_enum),
+};
+
+static int adau1373_pll_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ unsigned int pll_id = w->name[3] - '1';
+ unsigned int val;
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ val = ADAU1373_PLL_CTRL6_PLL_EN;
+ else
+ val = 0;
+
+ snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
+ ADAU1373_PLL_CTRL6_PLL_EN, val);
+
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ mdelay(5);
+
+ return 0;
+}
+
+static const char *adau1373_decimator_text[] = {
+ "ADC",
+ "DMIC1",
+};
+
+static const struct soc_enum adau1373_decimator_enum =
+ SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text);
+
+static const struct snd_kcontrol_new adau1373_decimator_mux =
+ SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum);
+
+static const struct snd_kcontrol_new adau1373_left_adc_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_LADC_MIXER, 4, 1, 0),
+ SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_LADC_MIXER, 3, 1, 0),
+ SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_LADC_MIXER, 2, 1, 0),
+ SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_LADC_MIXER, 1, 1, 0),
+ SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_LADC_MIXER, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new adau1373_right_adc_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_RADC_MIXER, 4, 1, 0),
+ SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_RADC_MIXER, 3, 1, 0),
+ SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_RADC_MIXER, 2, 1, 0),
+ SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_RADC_MIXER, 1, 1, 0),
+ SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_RADC_MIXER, 0, 1, 0),
+};
+
+#define DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(_name, _reg) \
+const struct snd_kcontrol_new _name[] = { \
+ SOC_DAPM_SINGLE("Left DAC2 Switch", _reg, 7, 1, 0), \
+ SOC_DAPM_SINGLE("Right DAC2 Switch", _reg, 6, 1, 0), \
+ SOC_DAPM_SINGLE("Left DAC1 Switch", _reg, 5, 1, 0), \
+ SOC_DAPM_SINGLE("Right DAC1 Switch", _reg, 4, 1, 0), \
+ SOC_DAPM_SINGLE("Input 4 Bypass Switch", _reg, 3, 1, 0), \
+ SOC_DAPM_SINGLE("Input 3 Bypass Switch", _reg, 2, 1, 0), \
+ SOC_DAPM_SINGLE("Input 2 Bypass Switch", _reg, 1, 1, 0), \
+ SOC_DAPM_SINGLE("Input 1 Bypass Switch", _reg, 0, 1, 0), \
+}
+
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line1_mixer_controls,
+ ADAU1373_LLINE1_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line1_mixer_controls,
+ ADAU1373_RLINE1_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line2_mixer_controls,
+ ADAU1373_LLINE2_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line2_mixer_controls,
+ ADAU1373_RLINE2_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_spk_mixer_controls,
+ ADAU1373_LSPK_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_spk_mixer_controls,
+ ADAU1373_RSPK_MIX);
+static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_ep_mixer_controls,
+ ADAU1373_EP_MIX);
+
+static const struct snd_kcontrol_new adau1373_left_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Left DAC1 Switch", ADAU1373_LHP_MIX, 5, 1, 0),
+ SOC_DAPM_SINGLE("Left DAC2 Switch", ADAU1373_LHP_MIX, 4, 1, 0),
+ SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_LHP_MIX, 3, 1, 0),
+ SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_LHP_MIX, 2, 1, 0),
+ SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_LHP_MIX, 1, 1, 0),
+ SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_LHP_MIX, 0, 1, 0),
+};
+
+static const struct snd_kcontrol_new adau1373_right_hp_mixer_controls[] = {
+ SOC_DAPM_SINGLE("Right DAC1 Switch", ADAU1373_RHP_MIX, 5, 1, 0),
+ SOC_DAPM_SINGLE("Right DAC2 Switch", ADAU1373_RHP_MIX, 4, 1, 0),
+ SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_RHP_MIX, 3, 1, 0),
+ SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_RHP_MIX, 2, 1, 0),
+ SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_RHP_MIX, 1, 1, 0),
+ SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_RHP_MIX, 0, 1, 0),
+};
+
+#define DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(_name, _reg) \
+const struct snd_kcontrol_new _name[] = { \
+ SOC_DAPM_SINGLE("DMIC2 Swapped Switch", _reg, 6, 1, 0), \
+ SOC_DAPM_SINGLE("DMIC2 Switch", _reg, 5, 1, 0), \
+ SOC_DAPM_SINGLE("ADC/DMIC1 Swapped Switch", _reg, 4, 1, 0), \
+ SOC_DAPM_SINGLE("ADC/DMIC1 Switch", _reg, 3, 1, 0), \
+ SOC_DAPM_SINGLE("AIF3 Switch", _reg, 2, 1, 0), \
+ SOC_DAPM_SINGLE("AIF2 Switch", _reg, 1, 1, 0), \
+ SOC_DAPM_SINGLE("AIF1 Switch", _reg, 0, 1, 0), \
+}
+
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel1_mixer_controls,
+ ADAU1373_DIN_MIX_CTRL(0));
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel2_mixer_controls,
+ ADAU1373_DIN_MIX_CTRL(1));
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel3_mixer_controls,
+ ADAU1373_DIN_MIX_CTRL(2));
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel4_mixer_controls,
+ ADAU1373_DIN_MIX_CTRL(3));
+static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel5_mixer_controls,
+ ADAU1373_DIN_MIX_CTRL(4));
+
+#define DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(_name, _reg) \
+const struct snd_kcontrol_new _name[] = { \
+ SOC_DAPM_SINGLE("DSP Channel5 Switch", _reg, 4, 1, 0), \
+ SOC_DAPM_SINGLE("DSP Channel4 Switch", _reg, 3, 1, 0), \
+ SOC_DAPM_SINGLE("DSP Channel3 Switch", _reg, 2, 1, 0), \
+ SOC_DAPM_SINGLE("DSP Channel2 Switch", _reg, 1, 1, 0), \
+ SOC_DAPM_SINGLE("DSP Channel1 Switch", _reg, 0, 1, 0), \
+}
+
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif1_mixer_controls,
+ ADAU1373_DOUT_MIX_CTRL(0));
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif2_mixer_controls,
+ ADAU1373_DOUT_MIX_CTRL(1));
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif3_mixer_controls,
+ ADAU1373_DOUT_MIX_CTRL(2));
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac1_mixer_controls,
+ ADAU1373_DOUT_MIX_CTRL(3));
+static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac2_mixer_controls,
+ ADAU1373_DOUT_MIX_CTRL(4));
+
+static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = {
+ /* Datasheet claims Left ADC is bit 6 and Right ADC is bit 7, but that
+ * doesn't seem to be the case. */
+ SND_SOC_DAPM_ADC("Left ADC", NULL, ADAU1373_PWDN_CTRL1, 7, 0),
+ SND_SOC_DAPM_ADC("Right ADC", NULL, ADAU1373_PWDN_CTRL1, 6, 0),
+
+ SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1373_DIGMICCTRL, 0, 0),
+ SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1373_DIGMICCTRL, 2, 0),
+
+ SND_SOC_DAPM_VIRT_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0,
+ &adau1373_decimator_mux),
+
+ SND_SOC_DAPM_SUPPLY("MICBIAS2", ADAU1373_PWDN_CTRL1, 5, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MICBIAS1", ADAU1373_PWDN_CTRL1, 4, 0, NULL, 0),
+
+ SND_SOC_DAPM_PGA("IN4PGA", ADAU1373_PWDN_CTRL1, 3, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IN3PGA", ADAU1373_PWDN_CTRL1, 2, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IN2PGA", ADAU1373_PWDN_CTRL1, 1, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("IN1PGA", ADAU1373_PWDN_CTRL1, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_DAC("Left DAC2", NULL, ADAU1373_PWDN_CTRL2, 7, 0),
+ SND_SOC_DAPM_DAC("Right DAC2", NULL, ADAU1373_PWDN_CTRL2, 6, 0),
+ SND_SOC_DAPM_DAC("Left DAC1", NULL, ADAU1373_PWDN_CTRL2, 5, 0),
+ SND_SOC_DAPM_DAC("Right DAC1", NULL, ADAU1373_PWDN_CTRL2, 4, 0),
+
+ SOC_MIXER_ARRAY("Left ADC Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_left_adc_mixer_controls),
+ SOC_MIXER_ARRAY("Right ADC Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_right_adc_mixer_controls),
+
+ SOC_MIXER_ARRAY("Left Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 3, 0,
+ adau1373_left_line2_mixer_controls),
+ SOC_MIXER_ARRAY("Right Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 2, 0,
+ adau1373_right_line2_mixer_controls),
+ SOC_MIXER_ARRAY("Left Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 1, 0,
+ adau1373_left_line1_mixer_controls),
+ SOC_MIXER_ARRAY("Right Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 0, 0,
+ adau1373_right_line1_mixer_controls),
+
+ SOC_MIXER_ARRAY("Earpiece Mixer", ADAU1373_PWDN_CTRL3, 4, 0,
+ adau1373_ep_mixer_controls),
+ SOC_MIXER_ARRAY("Left Speaker Mixer", ADAU1373_PWDN_CTRL3, 3, 0,
+ adau1373_left_spk_mixer_controls),
+ SOC_MIXER_ARRAY("Right Speaker Mixer", ADAU1373_PWDN_CTRL3, 2, 0,
+ adau1373_right_spk_mixer_controls),
+ SOC_MIXER_ARRAY("Left Headphone Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_left_hp_mixer_controls),
+ SOC_MIXER_ARRAY("Right Headphone Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_right_hp_mixer_controls),
+ SND_SOC_DAPM_SUPPLY("Headphone Enable", ADAU1373_PWDN_CTRL3, 1, 0,
+ NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("AIF1 CLK", ADAU1373_SRC_DAI_CTRL(0), 0, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AIF2 CLK", ADAU1373_SRC_DAI_CTRL(1), 0, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AIF3 CLK", ADAU1373_SRC_DAI_CTRL(2), 0, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AIF1 IN SRC", ADAU1373_SRC_DAI_CTRL(0), 2, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AIF1 OUT SRC", ADAU1373_SRC_DAI_CTRL(0), 1, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AIF2 IN SRC", ADAU1373_SRC_DAI_CTRL(1), 2, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AIF2 OUT SRC", ADAU1373_SRC_DAI_CTRL(1), 1, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AIF3 IN SRC", ADAU1373_SRC_DAI_CTRL(2), 2, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("AIF3 OUT SRC", ADAU1373_SRC_DAI_CTRL(2), 1, 0,
+ NULL, 0),
+
+ SND_SOC_DAPM_AIF_IN("AIF1 IN", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF1 OUT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF2 IN", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF2 OUT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_IN("AIF3 IN", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_AIF_OUT("AIF3 OUT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+
+ SOC_MIXER_ARRAY("DSP Channel1 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_dsp_channel1_mixer_controls),
+ SOC_MIXER_ARRAY("DSP Channel2 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_dsp_channel2_mixer_controls),
+ SOC_MIXER_ARRAY("DSP Channel3 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_dsp_channel3_mixer_controls),
+ SOC_MIXER_ARRAY("DSP Channel4 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_dsp_channel4_mixer_controls),
+ SOC_MIXER_ARRAY("DSP Channel5 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_dsp_channel5_mixer_controls),
+
+ SOC_MIXER_ARRAY("AIF1 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_aif1_mixer_controls),
+ SOC_MIXER_ARRAY("AIF2 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_aif2_mixer_controls),
+ SOC_MIXER_ARRAY("AIF3 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_aif3_mixer_controls),
+ SOC_MIXER_ARRAY("DAC1 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_dac1_mixer_controls),
+ SOC_MIXER_ARRAY("DAC2 Mixer", SND_SOC_NOPM, 0, 0,
+ adau1373_dac2_mixer_controls),
+
+ SND_SOC_DAPM_SUPPLY("DSP", ADAU1373_DIGEN, 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Recording Engine B", ADAU1373_DIGEN, 3, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Recording Engine A", ADAU1373_DIGEN, 2, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Playback Engine B", ADAU1373_DIGEN, 1, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Playback Engine A", ADAU1373_DIGEN, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("PLL1", SND_SOC_NOPM, 0, 0, adau1373_pll_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("PLL2", SND_SOC_NOPM, 0, 0, adau1373_pll_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_SUPPLY("SYSCLK1", ADAU1373_CLK_SRC_DIV(0), 7, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("SYSCLK2", ADAU1373_CLK_SRC_DIV(1), 7, 0, NULL, 0),
+
+ SND_SOC_DAPM_INPUT("AIN1L"),
+ SND_SOC_DAPM_INPUT("AIN1R"),
+ SND_SOC_DAPM_INPUT("AIN2L"),
+ SND_SOC_DAPM_INPUT("AIN2R"),
+ SND_SOC_DAPM_INPUT("AIN3L"),
+ SND_SOC_DAPM_INPUT("AIN3R"),
+ SND_SOC_DAPM_INPUT("AIN4L"),
+ SND_SOC_DAPM_INPUT("AIN4R"),
+
+ SND_SOC_DAPM_INPUT("DMIC1DAT"),
+ SND_SOC_DAPM_INPUT("DMIC2DAT"),
+
+ SND_SOC_DAPM_OUTPUT("LOUT1L"),
+ SND_SOC_DAPM_OUTPUT("LOUT1R"),
+ SND_SOC_DAPM_OUTPUT("LOUT2L"),
+ SND_SOC_DAPM_OUTPUT("LOUT2R"),
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+ SND_SOC_DAPM_OUTPUT("SPKL"),
+ SND_SOC_DAPM_OUTPUT("SPKR"),
+ SND_SOC_DAPM_OUTPUT("EP"),
+};
+
+static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_codec *codec = source->codec;
+ struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+ unsigned int dai;
+ const char *clk;
+
+ dai = sink->name[3] - '1';
+
+ if (!adau1373->dais[dai].master)
+ return 0;
+
+ if (adau1373->dais[dai].clk_src == ADAU1373_CLK_SRC_PLL1)
+ clk = "SYSCLK1";
+ else
+ clk = "SYSCLK2";
+
+ return strcmp(source->name, clk) == 0;
+}
+
+static int adau1373_check_src(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct snd_soc_codec *codec = source->codec;
+ struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+ unsigned int dai;
+
+ dai = sink->name[3] - '1';
+
+ return adau1373->dais[dai].enable_src;
+}
+
+#define DSP_CHANNEL_MIXER_ROUTES(_sink) \
+ { _sink, "DMIC2 Swapped Switch", "DMIC2" }, \
+ { _sink, "DMIC2 Switch", "DMIC2" }, \
+ { _sink, "ADC/DMIC1 Swapped Switch", "Decimator Mux" }, \
+ { _sink, "ADC/DMIC1 Switch", "Decimator Mux" }, \
+ { _sink, "AIF1 Switch", "AIF1 IN" }, \
+ { _sink, "AIF2 Switch", "AIF2 IN" }, \
+ { _sink, "AIF3 Switch", "AIF3 IN" }
+
+#define DSP_OUTPUT_MIXER_ROUTES(_sink) \
+ { _sink, "DSP Channel1 Switch", "DSP Channel1 Mixer" }, \
+ { _sink, "DSP Channel2 Switch", "DSP Channel2 Mixer" }, \
+ { _sink, "DSP Channel3 Switch", "DSP Channel3 Mixer" }, \
+ { _sink, "DSP Channel4 Switch", "DSP Channel4 Mixer" }, \
+ { _sink, "DSP Channel5 Switch", "DSP Channel5 Mixer" }
+
+#define LEFT_OUTPUT_MIXER_ROUTES(_sink) \
+ { _sink, "Right DAC2 Switch", "Right DAC2" }, \
+ { _sink, "Left DAC2 Switch", "Left DAC2" }, \
+ { _sink, "Right DAC1 Switch", "Right DAC1" }, \
+ { _sink, "Left DAC1 Switch", "Left DAC1" }, \
+ { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \
+ { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \
+ { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \
+ { _sink, "Input 4 Bypass Switch", "IN4PGA" }
+
+#define RIGHT_OUTPUT_MIXER_ROUTES(_sink) \
+ { _sink, "Right DAC2 Switch", "Right DAC2" }, \
+ { _sink, "Left DAC2 Switch", "Left DAC2" }, \
+ { _sink, "Right DAC1 Switch", "Right DAC1" }, \
+ { _sink, "Left DAC1 Switch", "Left DAC1" }, \
+ { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \
+ { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \
+ { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \
+ { _sink, "Input 4 Bypass Switch", "IN4PGA" }
+
+static const struct snd_soc_dapm_route adau1373_dapm_routes[] = {
+ { "Left ADC Mixer", "DAC1 Switch", "Left DAC1" },
+ { "Left ADC Mixer", "Input 1 Switch", "IN1PGA" },
+ { "Left ADC Mixer", "Input 2 Switch", "IN2PGA" },
+ { "Left ADC Mixer", "Input 3 Switch", "IN3PGA" },
+ { "Left ADC Mixer", "Input 4 Switch", "IN4PGA" },
+
+ { "Right ADC Mixer", "DAC1 Switch", "Right DAC1" },
+ { "Right ADC Mixer", "Input 1 Switch", "IN1PGA" },
+ { "Right ADC Mixer", "Input 2 Switch", "IN2PGA" },
+ { "Right ADC Mixer", "Input 3 Switch", "IN3PGA" },
+ { "Right ADC Mixer", "Input 4 Switch", "IN4PGA" },
+
+ { "Left ADC", NULL, "Left ADC Mixer" },
+ { "Right ADC", NULL, "Right ADC Mixer" },
+
+ { "Decimator Mux", "ADC", "Left ADC" },
+ { "Decimator Mux", "ADC", "Right ADC" },
+ { "Decimator Mux", "DMIC1", "DMIC1" },
+
+ DSP_CHANNEL_MIXER_ROUTES("DSP Channel1 Mixer"),
+ DSP_CHANNEL_MIXER_ROUTES("DSP Channel2 Mixer"),
+ DSP_CHANNEL_MIXER_ROUTES("DSP Channel3 Mixer"),
+ DSP_CHANNEL_MIXER_ROUTES("DSP Channel4 Mixer"),
+ DSP_CHANNEL_MIXER_ROUTES("DSP Channel5 Mixer"),
+
+ DSP_OUTPUT_MIXER_ROUTES("AIF1 Mixer"),
+ DSP_OUTPUT_MIXER_ROUTES("AIF2 Mixer"),
+ DSP_OUTPUT_MIXER_ROUTES("AIF3 Mixer"),
+ DSP_OUTPUT_MIXER_ROUTES("DAC1 Mixer"),
+ DSP_OUTPUT_MIXER_ROUTES("DAC2 Mixer"),
+
+ { "AIF1 OUT", NULL, "AIF1 Mixer" },
+ { "AIF2 OUT", NULL, "AIF2 Mixer" },
+ { "AIF3 OUT", NULL, "AIF3 Mixer" },
+ { "Left DAC1", NULL, "DAC1 Mixer" },
+ { "Right DAC1", NULL, "DAC1 Mixer" },
+ { "Left DAC2", NULL, "DAC2 Mixer" },
+ { "Right DAC2", NULL, "DAC2 Mixer" },
+
+ LEFT_OUTPUT_MIXER_ROUTES("Left Lineout1 Mixer"),
+ RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout1 Mixer"),
+ LEFT_OUTPUT_MIXER_ROUTES("Left Lineout2 Mixer"),
+ RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout2 Mixer"),
+ LEFT_OUTPUT_MIXER_ROUTES("Left Speaker Mixer"),
+ RIGHT_OUTPUT_MIXER_ROUTES("Right Speaker Mixer"),
+
+ { "Left Headphone Mixer", "Left DAC2 Switch", "Left DAC2" },
+ { "Left Headphone Mixer", "Left DAC1 Switch", "Left DAC1" },
+ { "Left Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" },
+ { "Left Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" },
+ { "Left Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" },
+ { "Left Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" },
+ { "Right Headphone Mixer", "Right DAC2 Switch", "Right DAC2" },
+ { "Right Headphone Mixer", "Right DAC1 Switch", "Right DAC1" },
+ { "Right Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" },
+ { "Right Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" },
+ { "Right Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" },
+ { "Right Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" },
+
+ { "Left Headphone Mixer", NULL, "Headphone Enable" },
+ { "Right Headphone Mixer", NULL, "Headphone Enable" },
+
+ { "Earpiece Mixer", "Right DAC2 Switch", "Right DAC2" },
+ { "Earpiece Mixer", "Left DAC2 Switch", "Left DAC2" },
+ { "Earpiece Mixer", "Right DAC1 Switch", "Right DAC1" },
+ { "Earpiece Mixer", "Left DAC1 Switch", "Left DAC1" },
+ { "Earpiece Mixer", "Input 1 Bypass Switch", "IN1PGA" },
+ { "Earpiece Mixer", "Input 2 Bypass Switch", "IN2PGA" },
+ { "Earpiece Mixer", "Input 3 Bypass Switch", "IN3PGA" },
+ { "Earpiece Mixer", "Input 4 Bypass Switch", "IN4PGA" },
+
+ { "LOUT1L", NULL, "Left Lineout1 Mixer" },
+ { "LOUT1R", NULL, "Right Lineout1 Mixer" },
+ { "LOUT2L", NULL, "Left Lineout2 Mixer" },
+ { "LOUT2R", NULL, "Right Lineout2 Mixer" },
+ { "SPKL", NULL, "Left Speaker Mixer" },
+ { "SPKR", NULL, "Right Speaker Mixer" },
+ { "HPL", NULL, "Left Headphone Mixer" },
+ { "HPR", NULL, "Right Headphone Mixer" },
+ { "EP", NULL, "Earpiece Mixer" },
+
+ { "IN1PGA", NULL, "AIN1L" },
+ { "IN2PGA", NULL, "AIN2L" },
+ { "IN3PGA", NULL, "AIN3L" },
+ { "IN4PGA", NULL, "AIN4L" },
+ { "IN1PGA", NULL, "AIN1R" },
+ { "IN2PGA", NULL, "AIN2R" },
+ { "IN3PGA", NULL, "AIN3R" },
+ { "IN4PGA", NULL, "AIN4R" },
+
+ { "SYSCLK1", NULL, "PLL1" },
+ { "SYSCLK2", NULL, "PLL2" },
+
+ { "Left DAC1", NULL, "SYSCLK1" },
+ { "Right DAC1", NULL, "SYSCLK1" },
+ { "Left DAC2", NULL, "SYSCLK1" },
+ { "Right DAC2", NULL, "SYSCLK1" },
+ { "Left ADC", NULL, "SYSCLK1" },
+ { "Right ADC", NULL, "SYSCLK1" },
+
+ { "DSP", NULL, "SYSCLK1" },
+
+ { "AIF1 Mixer", NULL, "DSP" },
+ { "AIF2 Mixer", NULL, "DSP" },
+ { "AIF3 Mixer", NULL, "DSP" },
+ { "DAC1 Mixer", NULL, "DSP" },
+ { "DAC2 Mixer", NULL, "DSP" },
+ { "DAC1 Mixer", NULL, "Playback Engine A" },
+ { "DAC2 Mixer", NULL, "Playback Engine B" },
+ { "Left ADC Mixer", NULL, "Recording Engine A" },
+ { "Right ADC Mixer", NULL, "Recording Engine A" },
+
+ { "AIF1 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk },
+ { "AIF2 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk },
+ { "AIF3 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk },
+ { "AIF1 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk },
+ { "AIF2 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk },
+ { "AIF3 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk },
+
+ { "AIF1 IN", NULL, "AIF1 CLK" },
+ { "AIF1 OUT", NULL, "AIF1 CLK" },
+ { "AIF2 IN", NULL, "AIF2 CLK" },
+ { "AIF2 OUT", NULL, "AIF2 CLK" },
+ { "AIF3 IN", NULL, "AIF3 CLK" },
+ { "AIF3 OUT", NULL, "AIF3 CLK" },
+ { "AIF1 IN", NULL, "AIF1 IN SRC", adau1373_check_src },
+ { "AIF1 OUT", NULL, "AIF1 OUT SRC", adau1373_check_src },
+ { "AIF2 IN", NULL, "AIF2 IN SRC", adau1373_check_src },
+ { "AIF2 OUT", NULL, "AIF2 OUT SRC", adau1373_check_src },
+ { "AIF3 IN", NULL, "AIF3 IN SRC", adau1373_check_src },
+ { "AIF3 OUT", NULL, "AIF3 OUT SRC", adau1373_check_src },
+
+ { "DMIC1", NULL, "DMIC1DAT" },
+ { "DMIC1", NULL, "SYSCLK1" },
+ { "DMIC1", NULL, "Recording Engine A" },
+ { "DMIC2", NULL, "DMIC2DAT" },
+ { "DMIC2", NULL, "SYSCLK1" },
+ { "DMIC2", NULL, "Recording Engine B" },
+};
+
+static int adau1373_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+ struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id];
+ unsigned int div;
+ unsigned int freq;
+ unsigned int ctrl;
+
+ freq = adau1373_dai->sysclk;
+
+ if (freq % params_rate(params) != 0)
+ return -EINVAL;
+
+ switch (freq / params_rate(params)) {
+ case 1024: /* sysclk / 256 */
+ div = 0;
+ break;
+ case 1536: /* 2/3 sysclk / 256 */
+ div = 1;
+ break;
+ case 2048: /* 1/2 sysclk / 256 */
+ div = 2;
+ break;
+ case 3072: /* 1/3 sysclk / 256 */
+ div = 3;
+ break;
+ case 4096: /* 1/4 sysclk / 256 */
+ div = 4;
+ break;
+ case 6144: /* 1/6 sysclk / 256 */
+ div = 5;
+ break;
+ case 5632: /* 2/11 sysclk / 256 */
+ div = 6;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ adau1373_dai->enable_src = (div != 0);
+
+ snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id),
+ ~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64);
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ ctrl = ADAU1373_DAI_WLEN_16;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ ctrl = ADAU1373_DAI_WLEN_20;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ ctrl = ADAU1373_DAI_WLEN_24;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ ctrl = ADAU1373_DAI_WLEN_32;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
+ ADAU1373_DAI_WLEN_MASK, ctrl);
+}
+
+static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec);
+ struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id];
+ unsigned int ctrl;
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ ctrl = ADAU1373_DAI_MASTER;
+ adau1373_dai->master = true;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ ctrl = 0;
+ adau1373_dai->master = false;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ ctrl |= ADAU1373_DAI_FORMAT_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ ctrl |= ADAU1373_DAI_FORMAT_LEFT_J;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ ctrl |= ADAU1373_DAI_FORMAT_RIGHT_J;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ ctrl |= ADAU1373_DAI_FORMAT_DSP;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ ctrl |= ADAU1373_DAI_INVERT_BCLK;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ ctrl |= ADAU1373_DAI_INVERT_LRCLK;
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ ctrl |= ADAU1373_DAI_INVERT_LRCLK | ADAU1373_DAI_INVERT_BCLK;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, ADAU1373_DAI(dai->id),
+ ~ADAU1373_DAI_WLEN_MASK, ctrl);
+
+ return 0;
+}
+
+static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(dai->codec);
+ struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id];
+
+ switch (clk_id) {
+ case ADAU1373_CLK_SRC_PLL1:
+ case ADAU1373_CLK_SRC_PLL2:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ adau1373_dai->sysclk = freq;
+ adau1373_dai->clk_src = clk_id;
+
+ snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id),
+ ADAU1373_BCLKDIV_SOURCE, clk_id << 5);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops adau1373_dai_ops = {
+ .hw_params = adau1373_hw_params,
+ .set_sysclk = adau1373_set_dai_sysclk,
+ .set_fmt = adau1373_set_dai_fmt,
+};
+
+#define ADAU1373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver adau1373_dai_driver[] = {
+ {
+ .id = 0,
+ .name = "adau1373-aif1",
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = ADAU1373_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = ADAU1373_FORMATS,
+ },
+ .ops = &adau1373_dai_ops,
+ .symmetric_rates = 1,
+ },
+ {
+ .id = 1,
+ .name = "adau1373-aif2",
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = ADAU1373_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = ADAU1373_FORMATS,
+ },
+ .ops = &adau1373_dai_ops,
+ .symmetric_rates = 1,
+ },
+ {
+ .id = 2,
+ .name = "adau1373-aif3",
+ .playback = {
+ .stream_name = "AIF3 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = ADAU1373_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF3 Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = ADAU1373_FORMATS,
+ },
+ .ops = &adau1373_dai_ops,
+ .symmetric_rates = 1,
+ },
+};
+
+static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id,
+ int source, unsigned int freq_in, unsigned int freq_out)
+{
+ unsigned int dpll_div = 0;
+ unsigned int x, r, n, m, i, j, mode;
+
+ switch (pll_id) {
+ case ADAU1373_PLL1:
+ case ADAU1373_PLL2:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (source) {
+ case ADAU1373_PLL_SRC_BCLK1:
+ case ADAU1373_PLL_SRC_BCLK2:
+ case ADAU1373_PLL_SRC_BCLK3:
+ case ADAU1373_PLL_SRC_LRCLK1:
+ case ADAU1373_PLL_SRC_LRCLK2:
+ case ADAU1373_PLL_SRC_LRCLK3:
+ case ADAU1373_PLL_SRC_MCLK1:
+ case ADAU1373_PLL_SRC_MCLK2:
+ case ADAU1373_PLL_SRC_GPIO1:
+ case ADAU1373_PLL_SRC_GPIO2:
+ case ADAU1373_PLL_SRC_GPIO3:
+ case ADAU1373_PLL_SRC_GPIO4:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (freq_in < 7813 || freq_in > 27000000)
+ return -EINVAL;
+
+ if (freq_out < 45158000 || freq_out > 49152000)
+ return -EINVAL;
+
+ /* APLL input needs to be >= 8Mhz, so in case freq_in is less we use the
+ * DPLL to get it there. DPLL_out = (DPLL_in / div) * 1024 */
+ while (freq_in < 8000000) {
+ freq_in *= 2;
+ dpll_div++;
+ }
+
+ if (freq_out % freq_in != 0) {
+ /* fout = fin * (r + (n/m)) / x */
+ x = DIV_ROUND_UP(freq_in, 13500000);
+ freq_in /= x;
+ r = freq_out / freq_in;
+ i = freq_out % freq_in;
+ j = gcd(i, freq_in);
+ n = i / j;
+ m = freq_in / j;
+ x--;
+ mode = 1;
+ } else {
+ /* fout = fin / r */
+ r = freq_out / freq_in;
+ n = 0;
+ m = 0;
+ x = 0;
+ mode = 0;
+ }
+
+ if (r < 2 || r > 8 || x > 3 || m > 0xffff || n > 0xffff)
+ return -EINVAL;
+
+ if (dpll_div) {
+ dpll_div = 11 - dpll_div;
+ snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
+ ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0);
+ } else {
+ snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id),
+ ADAU1373_PLL_CTRL6_DPLL_BYPASS,
+ ADAU1373_PLL_CTRL6_DPLL_BYPASS);
+ }
+
+ snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id),
+ (source << 4) | dpll_div);
+ snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff);
+ snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff);
+ snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff);
+ snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff);
+ snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id),
+ (r << 3) | (x << 1) | mode);
+
+ /* Set sysclk to pll_rate / 4 */
+ snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09);
+
+ return 0;
+}
+
+static void adau1373_load_drc_settings(struct snd_soc_codec *codec,
+ unsigned int nr, uint8_t *drc)
+{
+ unsigned int i;
+
+ for (i = 0; i < ADAU1373_DRC_SIZE; ++i)
+ snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]);
+}
+
+static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias)
+{
+ switch (micbias) {
+ case ADAU1373_MICBIAS_2_9V:
+ case ADAU1373_MICBIAS_2_2V:
+ case ADAU1373_MICBIAS_2_6V:
+ case ADAU1373_MICBIAS_1_8V:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
+
+static int adau1373_probe(struct snd_soc_codec *codec)
+{
+ struct adau1373_platform_data *pdata = codec->dev->platform_data;
+ bool lineout_differential = false;
+ unsigned int val;
+ int ret;
+ int i;
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
+ if (ret) {
+ dev_err(codec->dev, "failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ if (pdata) {
+ if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting))
+ return -EINVAL;
+
+ if (!adau1373_valid_micbias(pdata->micbias1) ||
+ !adau1373_valid_micbias(pdata->micbias2))
+ return -EINVAL;
+
+ for (i = 0; i < pdata->num_drc; ++i) {
+ adau1373_load_drc_settings(codec, i,
+ pdata->drc_setting[i]);
+ }
+
+ snd_soc_add_codec_controls(codec, adau1373_drc_controls,
+ pdata->num_drc);
+
+ val = 0;
+ for (i = 0; i < 4; ++i) {
+ if (pdata->input_differential[i])
+ val |= BIT(i);
+ }
+ snd_soc_write(codec, ADAU1373_INPUT_MODE, val);
+
+ val = 0;
+ if (pdata->lineout_differential)
+ val |= ADAU1373_OUTPUT_CTRL_LDIFF;
+ if (pdata->lineout_ground_sense)
+ val |= ADAU1373_OUTPUT_CTRL_LNFBEN;
+ snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val);
+
+ lineout_differential = pdata->lineout_differential;
+
+ snd_soc_write(codec, ADAU1373_EP_CTRL,
+ (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) |
+ (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET));
+ }
+
+ if (!lineout_differential) {
+ snd_soc_add_codec_controls(codec, adau1373_lineout2_controls,
+ ARRAY_SIZE(adau1373_lineout2_controls));
+ }
+
+ snd_soc_write(codec, ADAU1373_ADC_CTRL,
+ ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT);
+
+ return 0;
+}
+
+static int adau1373_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
+ ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN);
+ break;
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3,
+ ADAU1373_PWDN_CTRL3_PWR_EN, 0);
+ break;
+ }
+ codec->dapm.bias_level = level;
+ return 0;
+}
+
+static int adau1373_remove(struct snd_soc_codec *codec)
+{
+ adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int adau1373_suspend(struct snd_soc_codec *codec)
+{
+ return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF);
+}
+
+static int adau1373_resume(struct snd_soc_codec *codec)
+{
+ adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ snd_soc_cache_sync(codec);
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver adau1373_codec_driver = {
+ .probe = adau1373_probe,
+ .remove = adau1373_remove,
+ .suspend = adau1373_suspend,
+ .resume = adau1373_resume,
+ .set_bias_level = adau1373_set_bias_level,
+ .idle_bias_off = true,
+ .reg_cache_size = ARRAY_SIZE(adau1373_default_regs),
+ .reg_cache_default = adau1373_default_regs,
+ .reg_word_size = sizeof(uint8_t),
+
+ .set_pll = adau1373_set_pll,
+
+ .controls = adau1373_controls,
+ .num_controls = ARRAY_SIZE(adau1373_controls),
+ .dapm_widgets = adau1373_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets),
+ .dapm_routes = adau1373_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes),
+};
+
+static int __devinit adau1373_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct adau1373 *adau1373;
+ int ret;
+
+ adau1373 = devm_kzalloc(&client->dev, sizeof(*adau1373), GFP_KERNEL);
+ if (!adau1373)
+ return -ENOMEM;
+
+ dev_set_drvdata(&client->dev, adau1373);
+
+ ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver,
+ adau1373_dai_driver, ARRAY_SIZE(adau1373_dai_driver));
+ return ret;
+}
+
+static int __devexit adau1373_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static const struct i2c_device_id adau1373_i2c_id[] = {
+ { "adau1373", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id);
+
+static struct i2c_driver adau1373_i2c_driver = {
+ .driver = {
+ .name = "adau1373",
+ .owner = THIS_MODULE,
+ },
+ .probe = adau1373_i2c_probe,
+ .remove = __devexit_p(adau1373_i2c_remove),
+ .id_table = adau1373_i2c_id,
+};
+
+static int __init adau1373_init(void)
+{
+ return i2c_add_driver(&adau1373_i2c_driver);
+}
+module_init(adau1373_init);
+
+static void __exit adau1373_exit(void)
+{
+ i2c_del_driver(&adau1373_i2c_driver);
+}
+module_exit(adau1373_exit);
+
+MODULE_DESCRIPTION("ASoC ADAU1373 driver");
+MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/adau1373.h b/sound/soc/codecs/adau1373.h
new file mode 100644
index 000000000000..c6ab5530760c
--- /dev/null
+++ b/sound/soc/codecs/adau1373.h
@@ -0,0 +1,29 @@
+#ifndef __ADAU1373_H__
+#define __ADAU1373_H__
+
+enum adau1373_pll_src {
+ ADAU1373_PLL_SRC_MCLK1 = 0,
+ ADAU1373_PLL_SRC_BCLK1 = 1,
+ ADAU1373_PLL_SRC_BCLK2 = 2,
+ ADAU1373_PLL_SRC_BCLK3 = 3,
+ ADAU1373_PLL_SRC_LRCLK1 = 4,
+ ADAU1373_PLL_SRC_LRCLK2 = 5,
+ ADAU1373_PLL_SRC_LRCLK3 = 6,
+ ADAU1373_PLL_SRC_GPIO1 = 7,
+ ADAU1373_PLL_SRC_GPIO2 = 8,
+ ADAU1373_PLL_SRC_GPIO3 = 9,
+ ADAU1373_PLL_SRC_GPIO4 = 10,
+ ADAU1373_PLL_SRC_MCLK2 = 11,
+};
+
+enum adau1373_pll {
+ ADAU1373_PLL1 = 0,
+ ADAU1373_PLL2 = 1,
+};
+
+enum adau1373_clk_src {
+ ADAU1373_CLK_SRC_PLL1 = 0,
+ ADAU1373_CLK_SRC_PLL2 = 1,
+};
+
+#endif
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c
index 2758d5fc60d6..78e9ce48bb99 100644
--- a/sound/soc/codecs/adau1701.c
+++ b/sound/soc/codecs/adau1701.c
@@ -12,13 +12,13 @@
#include <linux/init.h>
#include <linux/i2c.h>
#include <linux/delay.h>
-#include <linux/sigma.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include "sigmadsp.h"
#include "adau1701.h"
#define ADAU1701_DSPCTRL 0x1c
@@ -401,7 +401,7 @@ static int adau1701_digital_mute(struct snd_soc_dai *dai, int mute)
}
static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id,
- unsigned int freq, int dir)
+ int source, unsigned int freq, int dir)
{
unsigned int val;
@@ -457,7 +457,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
{
int ret;
- codec->dapm.idle_bias_off = 1;
+ codec->control_data = to_i2c_client(codec->dev);
ret = adau1701_load_firmware(codec);
if (ret)
@@ -472,6 +472,7 @@ static int adau1701_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver adau1701_codec_drv = {
.probe = adau1701_probe,
.set_bias_level = adau1701_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ADAU1701_NUM_REGS,
.reg_word_size = sizeof(u16),
@@ -495,23 +496,19 @@ static __devinit int adau1701_i2c_probe(struct i2c_client *client,
struct adau1701 *adau1701;
int ret;
- adau1701 = kzalloc(sizeof(*adau1701), GFP_KERNEL);
+ adau1701 = devm_kzalloc(&client->dev, sizeof(*adau1701), GFP_KERNEL);
if (!adau1701)
return -ENOMEM;
i2c_set_clientdata(client, adau1701);
ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv,
&adau1701_dai, 1);
- if (ret < 0)
- kfree(adau1701);
-
return ret;
}
static __devexit int adau1701_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c
index 300c04b70e71..ebd7b37b902b 100644
--- a/sound/soc/codecs/adav80x.c
+++ b/sound/soc/codecs/adav80x.c
@@ -523,7 +523,8 @@ static int adav80x_hw_params(struct snd_pcm_substream *substream,
}
static int adav80x_set_sysclk(struct snd_soc_codec *codec,
- int clk_id, unsigned int freq, int dir)
+ int clk_id, int source,
+ unsigned int freq, int dir)
{
struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec);
@@ -797,7 +798,7 @@ static int adav80x_probe(struct snd_soc_codec *codec)
return adav80x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
}
-static int adav80x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int adav80x_suspend(struct snd_soc_codec *codec)
{
return adav80x_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
diff --git a/sound/soc/codecs/ads117x.c b/sound/soc/codecs/ads117x.c
index 8402854ec15e..8103b938b8c0 100644
--- a/sound/soc/codecs/ads117x.c
+++ b/sound/soc/codecs/ads117x.c
@@ -14,6 +14,7 @@
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/initval.h>
@@ -57,17 +58,7 @@ static struct platform_driver ads117x_codec_driver = {
.remove = __devexit_p(ads117x_remove),
};
-static int __init ads117x_init(void)
-{
- return platform_driver_register(&ads117x_codec_driver);
-}
-module_init(ads117x_init);
-
-static void __exit ads117x_exit(void)
-{
- platform_driver_unregister(&ads117x_codec_driver);
-}
-module_exit(ads117x_exit);
+module_platform_driver(ads117x_codec_driver);
MODULE_DESCRIPTION("ASoC ads117x driver");
MODULE_AUTHOR("Graeme Gregory");
diff --git a/sound/soc/codecs/ads117x.h b/sound/soc/codecs/ads117x.h
deleted file mode 100644
index 3ce028614002..000000000000
--- a/sound/soc/codecs/ads117x.h
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * ads117x.h -- Driver for ads1174/8 ADC chips
- *
- * Copyright 2009 ShotSpotter Inc.
- * Author: Graeme Gregory <gg@slimlogic.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- */
-extern struct snd_soc_dai_driver ads117x_dai;
-extern struct snd_soc_codec_driver soc_codec_dev_ads117x;
diff --git a/sound/soc/codecs/ak4104.c b/sound/soc/codecs/ak4104.c
index cbf0b6d400b8..ceb96ecf5588 100644
--- a/sound/soc/codecs/ak4104.c
+++ b/sound/soc/codecs/ak4104.c
@@ -46,75 +46,15 @@
#define DRV_NAME "ak4104-codec"
struct ak4104_private {
- enum snd_soc_control_type control_type;
- void *control_data;
+ struct regmap *regmap;
};
-static int ak4104_fill_cache(struct snd_soc_codec *codec)
-{
- int i;
- u8 *reg_cache = codec->reg_cache;
- struct spi_device *spi = codec->control_data;
-
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- int ret = spi_w8r8(spi, i | AK4104_READ);
- if (ret < 0) {
- dev_err(&spi->dev, "SPI write failure\n");
- return ret;
- }
-
- reg_cache[i] = ret;
- }
-
- return 0;
-}
-
-static unsigned int ak4104_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u8 *reg_cache = codec->reg_cache;
-
- if (reg >= codec->driver->reg_cache_size)
- return -EINVAL;
-
- return reg_cache[reg];
-}
-
-static int ak4104_spi_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 *cache = codec->reg_cache;
- struct spi_device *spi = codec->control_data;
-
- if (reg >= codec->driver->reg_cache_size)
- return -EINVAL;
-
- /* only write to the hardware if value has changed */
- if (cache[reg] != value) {
- u8 tmp[2] = { (reg & AK4104_REG_MASK) | AK4104_WRITE, value };
-
- if (spi_write(spi, tmp, sizeof(tmp))) {
- dev_err(&spi->dev, "SPI write failed\n");
- return -EIO;
- }
-
- cache[reg] = value;
- }
-
- return 0;
-}
-
static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int format)
{
struct snd_soc_codec *codec = codec_dai->codec;
int val = 0;
-
- val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
- if (val < 0)
- return val;
-
- val &= ~(AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1);
+ int ret;
/* set DAI format */
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -135,7 +75,13 @@ static int ak4104_set_dai_fmt(struct snd_soc_dai *codec_dai,
if ((format & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS)
return -EINVAL;
- return ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+ ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+ AK4104_CONTROL1_DIF0 | AK4104_CONTROL1_DIF1,
+ val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static int ak4104_hw_params(struct snd_pcm_substream *substream,
@@ -148,7 +94,7 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
/* set the IEC958 bits: consumer mode, no copyright bit */
val |= IEC958_AES0_CON_NOT_COPYRIGHT;
- ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(0), val);
+ snd_soc_write(codec, AK4104_REG_CHN_STATUS(0), val);
val = 0;
@@ -167,10 +113,10 @@ static int ak4104_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- return ak4104_spi_write(codec, AK4104_REG_CHN_STATUS(3), val);
+ return snd_soc_write(codec, AK4104_REG_CHN_STATUS(3), val);
}
-static struct snd_soc_dai_ops ak4101_dai_ops = {
+static const struct snd_soc_dai_ops ak4101_dai_ops = {
.hw_params = ak4104_hw_params,
.set_fmt = ak4104_set_dai_fmt,
};
@@ -192,67 +138,57 @@ static struct snd_soc_dai_driver ak4104_dai = {
static int ak4104_probe(struct snd_soc_codec *codec)
{
struct ak4104_private *ak4104 = snd_soc_codec_get_drvdata(codec);
- int ret, val;
-
- codec->control_data = ak4104->control_data;
+ int ret;
- /* read all regs and fill the cache */
- ret = ak4104_fill_cache(codec);
- if (ret < 0) {
- dev_err(codec->dev, "failed to fill register cache\n");
+ codec->control_data = ak4104->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret != 0)
return ret;
- }
-
- /* read the 'reserved' register - according to the datasheet, it
- * should contain 0x5b. Not a good way to verify the presence of
- * the device, but there is no hardware ID register. */
- if (ak4104_read_reg_cache(codec, AK4104_REG_RESERVED) !=
- AK4104_RESERVED_VAL)
- return -ENODEV;
/* set power-up and non-reset bits */
- val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
- val |= AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN;
- ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+ ret = snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+ AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN,
+ AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
if (ret < 0)
return ret;
/* enable transmitter */
- val = ak4104_read_reg_cache(codec, AK4104_REG_TX);
- val |= AK4104_TX_TXE;
- ret = ak4104_spi_write(codec, AK4104_REG_TX, val);
+ ret = snd_soc_update_bits(codec, AK4104_REG_TX,
+ AK4104_TX_TXE, AK4104_TX_TXE);
if (ret < 0)
return ret;
- dev_info(codec->dev, "SPI device initialized\n");
return 0;
}
static int ak4104_remove(struct snd_soc_codec *codec)
{
- int val, ret;
-
- val = ak4104_read_reg_cache(codec, AK4104_REG_CONTROL1);
- if (val < 0)
- return val;
-
- /* clear power-up and non-reset bits */
- val &= ~(AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN);
- ret = ak4104_spi_write(codec, AK4104_REG_CONTROL1, val);
+ snd_soc_update_bits(codec, AK4104_REG_CONTROL1,
+ AK4104_CONTROL1_PW | AK4104_CONTROL1_RSTN, 0);
- return ret;
+ return 0;
}
static struct snd_soc_codec_driver soc_codec_device_ak4104 = {
.probe = ak4104_probe,
.remove = ak4104_remove,
- .reg_cache_size = AK4104_NUM_REGS,
- .reg_word_size = sizeof(u16),
+};
+
+static const struct regmap_config ak4104_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = AK4104_NUM_REGS - 1,
+ .read_flag_mask = AK4104_READ,
+ .write_flag_mask = AK4104_WRITE,
+
+ .cache_type = REGCACHE_RBTREE,
};
static int ak4104_spi_probe(struct spi_device *spi)
{
struct ak4104_private *ak4104;
+ unsigned int val;
int ret;
spi->bits_per_word = 8;
@@ -261,25 +197,47 @@ static int ak4104_spi_probe(struct spi_device *spi)
if (ret < 0)
return ret;
- ak4104 = kzalloc(sizeof(struct ak4104_private), GFP_KERNEL);
+ ak4104 = devm_kzalloc(&spi->dev, sizeof(struct ak4104_private),
+ GFP_KERNEL);
if (ak4104 == NULL)
return -ENOMEM;
- ak4104->control_data = spi;
- ak4104->control_type = SND_SOC_SPI;
+ ak4104->regmap = regmap_init_spi(spi, &ak4104_regmap);
+ if (IS_ERR(ak4104->regmap)) {
+ ret = PTR_ERR(ak4104->regmap);
+ return ret;
+ }
+
+ /* read the 'reserved' register - according to the datasheet, it
+ * should contain 0x5b. Not a good way to verify the presence of
+ * the device, but there is no hardware ID register. */
+ ret = regmap_read(ak4104->regmap, AK4104_REG_RESERVED, &val);
+ if (ret != 0)
+ goto err;
+ if (val != AK4104_RESERVED_VAL) {
+ ret = -ENODEV;
+ goto err;
+ }
+
spi_set_drvdata(spi, ak4104);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_device_ak4104, &ak4104_dai, 1);
- if (ret < 0)
- kfree(ak4104);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(ak4104->regmap);
return ret;
}
static int __devexit ak4104_spi_remove(struct spi_device *spi)
{
+ struct ak4104_private *ak4101 = spi_get_drvdata(spi);
+ regmap_exit(ak4101->regmap);
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
return 0;
}
@@ -292,17 +250,7 @@ static struct spi_driver ak4104_spi_driver = {
.remove = __devexit_p(ak4104_spi_remove),
};
-static int __init ak4104_init(void)
-{
- return spi_register_driver(&ak4104_spi_driver);
-}
-module_init(ak4104_init);
-
-static void __exit ak4104_exit(void)
-{
- spi_unregister_driver(&ak4104_spi_driver);
-}
-module_exit(ak4104_exit);
+module_spi_driver(ak4104_spi_driver);
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
MODULE_DESCRIPTION("Asahi Kasei AK4104 ALSA SoC driver");
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index e1a214ee757f..838ae8b22b50 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -18,7 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -28,82 +28,43 @@
#include "ak4535.h"
-#define AK4535_VERSION "0.3"
-
/* codec private data */
struct ak4535_priv {
+ struct regmap *regmap;
unsigned int sysclk;
- enum snd_soc_control_type control_type;
- void *control_data;
};
/*
* ak4535 register cache
*/
-static const u16 ak4535_reg[AK4535_CACHEREGNUM] = {
- 0x0000, 0x0080, 0x0000, 0x0003,
- 0x0002, 0x0000, 0x0011, 0x0001,
- 0x0000, 0x0040, 0x0036, 0x0010,
- 0x0000, 0x0000, 0x0057, 0x0000,
+static const struct reg_default ak4535_reg_defaults[] = {
+ { 0, 0x00 },
+ { 1, 0x80 },
+ { 2, 0x00 },
+ { 3, 0x03 },
+ { 4, 0x02 },
+ { 5, 0x00 },
+ { 6, 0x11 },
+ { 7, 0x01 },
+ { 8, 0x00 },
+ { 9, 0x40 },
+ { 10, 0x36 },
+ { 11, 0x10 },
+ { 12, 0x00 },
+ { 13, 0x00 },
+ { 14, 0x57 },
};
-/*
- * read ak4535 register cache
- */
-static inline unsigned int ak4535_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
+static bool ak4535_volatile(struct device *dev, unsigned int reg)
{
- u16 *cache = codec->reg_cache;
- if (reg >= AK4535_CACHEREGNUM)
- return -1;
- return cache[reg];
-}
-
-/*
- * write ak4535 register cache
- */
-static inline void ak4535_write_reg_cache(struct snd_soc_codec *codec,
- u16 reg, unsigned int value)
-{
- u16 *cache = codec->reg_cache;
- if (reg >= AK4535_CACHEREGNUM)
- return;
- cache[reg] = value;
-}
-
-/*
- * write to the AK4535 register space
- */
-static int ak4535_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 data[2];
-
- /* data is
- * D15..D8 AK4535 register offset
- * D7...D0 register data
- */
- data[0] = reg & 0xff;
- data[1] = value & 0xff;
-
- ak4535_write_reg_cache(codec, reg, value);
- if (codec->hw_write(codec->control_data, data, 2) == 2)
- return 0;
- else
- return -EIO;
+ switch (reg) {
+ case AK4535_STATUS:
+ return true;
+ default:
+ return false;
+ }
}
-static int ak4535_sync(struct snd_soc_codec *codec)
-{
- u16 *cache = codec->reg_cache;
- int i, r = 0;
-
- for (i = 0; i < AK4535_CACHEREGNUM; i++)
- r |= ak4535_write(codec, i, cache[i]);
-
- return r;
-};
-
static const char *ak4535_mono_gain[] = {"+6dB", "-17dB"};
static const char *ak4535_mono_out[] = {"(L + R)/2", "Hi-Z"};
static const char *ak4535_hp_out[] = {"Stereo", "Mono"};
@@ -304,7 +265,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
- u8 mode2 = ak4535_read_reg_cache(codec, AK4535_MODE2) & ~(0x3 << 5);
+ u8 mode2 = snd_soc_read(codec, AK4535_MODE2) & ~(0x3 << 5);
int rate = params_rate(params), fs = 256;
if (rate)
@@ -323,7 +284,7 @@ static int ak4535_hw_params(struct snd_pcm_substream *substream,
}
/* set rate */
- ak4535_write(codec, AK4535_MODE2, mode2);
+ snd_soc_write(codec, AK4535_MODE2, mode2);
return 0;
}
@@ -348,44 +309,37 @@ static int ak4535_set_dai_fmt(struct snd_soc_dai *codec_dai,
/* use 32 fs for BCLK to save power */
mode1 |= 0x4;
- ak4535_write(codec, AK4535_MODE1, mode1);
+ snd_soc_write(codec, AK4535_MODE1, mode1);
return 0;
}
static int ak4535_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- u16 mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
+ u16 mute_reg = snd_soc_read(codec, AK4535_DAC);
if (!mute)
- ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
+ snd_soc_write(codec, AK4535_DAC, mute_reg & ~0x20);
else
- ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
+ snd_soc_write(codec, AK4535_DAC, mute_reg | 0x20);
return 0;
}
static int ak4535_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 i, mute_reg;
-
switch (level) {
case SND_SOC_BIAS_ON:
- mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
- ak4535_write(codec, AK4535_DAC, mute_reg & ~0x20);
+ snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0);
break;
case SND_SOC_BIAS_PREPARE:
- mute_reg = ak4535_read_reg_cache(codec, AK4535_DAC);
- ak4535_write(codec, AK4535_DAC, mute_reg | 0x20);
+ snd_soc_update_bits(codec, AK4535_DAC, 0x20, 0x20);
break;
case SND_SOC_BIAS_STANDBY:
- i = ak4535_read_reg_cache(codec, AK4535_PM1);
- ak4535_write(codec, AK4535_PM1, i | 0x80);
- i = ak4535_read_reg_cache(codec, AK4535_PM2);
- ak4535_write(codec, AK4535_PM2, i & (~0x80));
+ snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0x80);
+ snd_soc_update_bits(codec, AK4535_PM2, 0x80, 0);
break;
case SND_SOC_BIAS_OFF:
- i = ak4535_read_reg_cache(codec, AK4535_PM1);
- ak4535_write(codec, AK4535_PM1, i & (~0x80));
+ snd_soc_update_bits(codec, AK4535_PM1, 0x80, 0);
break;
}
codec->dapm.bias_level = level;
@@ -396,7 +350,7 @@ static int ak4535_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
-static struct snd_soc_dai_ops ak4535_dai_ops = {
+static const struct snd_soc_dai_ops ak4535_dai_ops = {
.hw_params = ak4535_hw_params,
.set_fmt = ak4535_set_dai_fmt,
.digital_mute = ak4535_mute,
@@ -420,7 +374,7 @@ static struct snd_soc_dai_driver ak4535_dai = {
.ops = &ak4535_dai_ops,
};
-static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ak4535_suspend(struct snd_soc_codec *codec)
{
ak4535_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -428,7 +382,7 @@ static int ak4535_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int ak4535_resume(struct snd_soc_codec *codec)
{
- ak4535_sync(codec);
+ snd_soc_cache_sync(codec);
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
@@ -436,15 +390,18 @@ static int ak4535_resume(struct snd_soc_codec *codec)
static int ak4535_probe(struct snd_soc_codec *codec)
{
struct ak4535_priv *ak4535 = snd_soc_codec_get_drvdata(codec);
+ int ret;
- printk(KERN_INFO "AK4535 Audio Codec %s", AK4535_VERSION);
-
- codec->control_data = ak4535->control_data;
-
+ codec->control_data = ak4535->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
/* power on device */
ak4535_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, ak4535_snd_controls,
+ snd_soc_add_codec_controls(codec, ak4535_snd_controls,
ARRAY_SIZE(ak4535_snd_controls));
return 0;
}
@@ -456,49 +413,64 @@ static int ak4535_remove(struct snd_soc_codec *codec)
return 0;
}
+static const struct regmap_config ak4535_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = AK4535_STATUS,
+ .volatile_reg = ak4535_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = ak4535_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(ak4535_reg_defaults),
+};
+
static struct snd_soc_codec_driver soc_codec_dev_ak4535 = {
.probe = ak4535_probe,
.remove = ak4535_remove,
.suspend = ak4535_suspend,
.resume = ak4535_resume,
- .read = ak4535_read_reg_cache,
- .write = ak4535_write,
.set_bias_level = ak4535_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(ak4535_reg),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = ak4535_reg,
.dapm_widgets = ak4535_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(ak4535_dapm_widgets),
.dapm_routes = ak4535_audio_map,
.num_dapm_routes = ARRAY_SIZE(ak4535_audio_map),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int ak4535_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct ak4535_priv *ak4535;
int ret;
- ak4535 = kzalloc(sizeof(struct ak4535_priv), GFP_KERNEL);
+ ak4535 = devm_kzalloc(&i2c->dev, sizeof(struct ak4535_priv),
+ GFP_KERNEL);
if (ak4535 == NULL)
return -ENOMEM;
+ ak4535->regmap = regmap_init_i2c(i2c, &ak4535_regmap);
+ if (IS_ERR(ak4535->regmap)) {
+ ret = PTR_ERR(ak4535->regmap);
+ dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, ak4535);
- ak4535->control_data = i2c;
- ak4535->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_ak4535, &ak4535_dai, 1);
- if (ret < 0)
- kfree(ak4535);
+ if (ret != 0)
+ regmap_exit(ak4535->regmap);
+
return ret;
}
static __devexit int ak4535_i2c_remove(struct i2c_client *client)
{
+ struct ak4535_priv *ak4535 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(ak4535->regmap);
return 0;
}
@@ -510,36 +482,15 @@ MODULE_DEVICE_TABLE(i2c, ak4535_i2c_id);
static struct i2c_driver ak4535_i2c_driver = {
.driver = {
- .name = "ak4535-codec",
+ .name = "ak4535",
.owner = THIS_MODULE,
},
.probe = ak4535_i2c_probe,
.remove = __devexit_p(ak4535_i2c_remove),
.id_table = ak4535_i2c_id,
};
-#endif
-
-static int __init ak4535_modinit(void)
-{
- int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- ret = i2c_add_driver(&ak4535_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register AK4535 I2C driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(ak4535_modinit);
-static void __exit ak4535_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&ak4535_i2c_driver);
-#endif
-}
-module_exit(ak4535_exit);
+module_i2c_driver(ak4535_i2c_driver);
MODULE_DESCRIPTION("Soc AK4535 driver");
MODULE_AUTHOR("Richard Purdie");
diff --git a/sound/soc/codecs/ak4535.h b/sound/soc/codecs/ak4535.h
index 0431e5f634a2..402de1d274bf 100644
--- a/sound/soc/codecs/ak4535.h
+++ b/sound/soc/codecs/ak4535.h
@@ -34,6 +34,4 @@
#define AK4535_VOL 0xe
#define AK4535_STATUS 0xf
-#define AK4535_CACHEREGNUM 0x10
-
#endif
diff --git a/sound/soc/codecs/ak4641.c b/sound/soc/codecs/ak4641.c
index 7a64e58cddc4..c4d165a4bddf 100644
--- a/sound/soc/codecs/ak4641.c
+++ b/sound/soc/codecs/ak4641.c
@@ -17,7 +17,6 @@
#include <linux/gpio.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -31,7 +30,6 @@
/* codec private data */
struct ak4641_priv {
- struct snd_soc_codec *codec;
unsigned int sysclk;
int deemph;
int playback_fs;
@@ -226,7 +224,7 @@ static const struct snd_soc_dapm_widget ak4641_dapm_widgets[] = {
SND_SOC_DAPM_PGA("Mono Out 2", AK4641_PM2, 3, 0, NULL, 0),
SND_SOC_DAPM_ADC("Voice ADC", "Voice Capture", AK4641_BTIF, 0, 0),
- SND_SOC_DAPM_ADC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0),
+ SND_SOC_DAPM_DAC("Voice DAC", "Voice Playback", AK4641_BTIF, 1, 0),
SND_SOC_DAPM_MICBIAS("Mic Int Bias", AK4641_MIC, 3, 0),
SND_SOC_DAPM_MICBIAS("Mic Ext Bias", AK4641_MIC, 4, 0),
@@ -341,6 +339,7 @@ static int ak4641_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
u8 btif;
+ int ret;
/* interface format */
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -360,7 +359,11 @@ static int ak4641_pcm_set_dai_fmt(struct snd_soc_dai *codec_dai,
return -EINVAL;
}
- return snd_soc_update_bits(codec, AK4641_BTIF, (0x3 << 5), btif);
+ ret = snd_soc_update_bits(codec, AK4641_BTIF, (0x3 << 5), btif);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static int ak4641_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -443,14 +446,14 @@ static int ak4641_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_RATE_16000)
#define AK4641_FORMATS (SNDRV_PCM_FMTBIT_S16_LE)
-static struct snd_soc_dai_ops ak4641_i2s_dai_ops = {
+static const struct snd_soc_dai_ops ak4641_i2s_dai_ops = {
.hw_params = ak4641_i2s_hw_params,
.set_fmt = ak4641_i2s_set_dai_fmt,
.digital_mute = ak4641_mute,
.set_sysclk = ak4641_set_dai_sysclk,
};
-static struct snd_soc_dai_ops ak4641_pcm_dai_ops = {
+static const struct snd_soc_dai_ops ak4641_pcm_dai_ops = {
.hw_params = NULL, /* rates are controlled by BT chip */
.set_fmt = ak4641_pcm_set_dai_fmt,
.digital_mute = ak4641_mute,
@@ -500,7 +503,7 @@ static struct snd_soc_dai_driver ak4641_dai[] = {
},
};
-static int ak4641_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ak4641_suspend(struct snd_soc_codec *codec)
{
ak4641_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -604,7 +607,8 @@ static int __devinit ak4641_i2c_probe(struct i2c_client *i2c,
struct ak4641_priv *ak4641;
int ret;
- ak4641 = kzalloc(sizeof(struct ak4641_priv), GFP_KERNEL);
+ ak4641 = devm_kzalloc(&i2c->dev, sizeof(struct ak4641_priv),
+ GFP_KERNEL);
if (!ak4641)
return -ENOMEM;
@@ -612,16 +616,12 @@ static int __devinit ak4641_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_ak4641,
ak4641_dai, ARRAY_SIZE(ak4641_dai));
- if (ret < 0)
- kfree(ak4641);
-
return ret;
}
static int __devexit ak4641_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
- kfree(i2c_get_clientdata(i2c));
return 0;
}
diff --git a/sound/soc/codecs/ak4642.c b/sound/soc/codecs/ak4642.c
index 65f46047b1cb..f8e10ced244a 100644
--- a/sound/soc/codecs/ak4642.c
+++ b/sound/soc/codecs/ak4642.c
@@ -18,20 +18,19 @@
* This is very simple driver.
* It can use headphone output / stereo input only
*
- * AK4642 is not tested.
+ * AK4642 is tested.
* AK4643 is tested.
+ * AK4648 is tested.
*/
#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/initval.h>
#include <sound/tlv.h>
-#define AK4642_VERSION "0.0.1"
-
#define PW_MGMT1 0x00
#define PW_MGMT2 0x01
#define SG_SL1 0x02
@@ -70,8 +69,6 @@
#define HP_MS 0x23
#define SPK_MS 0x24
-#define AK4642_CACHEREGNUM 0x25
-
/* PW_MGMT1*/
#define PMVCM (1 << 6) /* VCOM Power Management */
#define PMMIN (1 << 5) /* MIN Input Power Management */
@@ -151,86 +148,85 @@ static const struct snd_kcontrol_new ak4642_snd_controls[] = {
0, 0xFF, 1, out_tlv),
};
+static const struct snd_kcontrol_new ak4642_headphone_control =
+ SOC_DAPM_SINGLE("Switch", PW_MGMT2, 6, 1, 0);
-/* codec private data */
-struct ak4642_priv {
- unsigned int sysclk;
- enum snd_soc_control_type control_type;
- void *control_data;
+static const struct snd_kcontrol_new ak4642_lout_mixer_controls[] = {
+ SOC_DAPM_SINGLE("DACL", SG_SL1, 4, 1, 0),
};
-/*
- * ak4642 register cache
- */
-static const u16 ak4642_reg[AK4642_CACHEREGNUM] = {
- 0x0000, 0x0000, 0x0001, 0x0000,
- 0x0002, 0x0000, 0x0000, 0x0000,
- 0x00e1, 0x00e1, 0x0018, 0x0000,
- 0x00e1, 0x0018, 0x0011, 0x0008,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000,
+static const struct snd_soc_dapm_widget ak4642_dapm_widgets[] = {
+
+ /* Outputs */
+ SND_SOC_DAPM_OUTPUT("HPOUTL"),
+ SND_SOC_DAPM_OUTPUT("HPOUTR"),
+ SND_SOC_DAPM_OUTPUT("LINEOUT"),
+
+ SND_SOC_DAPM_PGA("HPL Out", PW_MGMT2, 5, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HPR Out", PW_MGMT2, 4, 0, NULL, 0),
+ SND_SOC_DAPM_SWITCH("Headphone Enable", SND_SOC_NOPM, 0, 0,
+ &ak4642_headphone_control),
+
+ SND_SOC_DAPM_PGA("DACH", MD_CTL4, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MIXER("LINEOUT Mixer", PW_MGMT1, 3, 0,
+ &ak4642_lout_mixer_controls[0],
+ ARRAY_SIZE(ak4642_lout_mixer_controls)),
+
+ /* DAC */
+ SND_SOC_DAPM_DAC("DAC", "HiFi Playback", PW_MGMT1, 2, 0),
};
-/*
- * read ak4642 register cache
- */
-static inline unsigned int ak4642_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u16 *cache = codec->reg_cache;
- if (reg >= AK4642_CACHEREGNUM)
- return -1;
- return cache[reg];
-}
+static const struct snd_soc_dapm_route ak4642_intercon[] = {
-/*
- * write ak4642 register cache
- */
-static inline void ak4642_write_reg_cache(struct snd_soc_codec *codec,
- u16 reg, unsigned int value)
-{
- u16 *cache = codec->reg_cache;
- if (reg >= AK4642_CACHEREGNUM)
- return;
+ /* Outputs */
+ {"HPOUTL", NULL, "HPL Out"},
+ {"HPOUTR", NULL, "HPR Out"},
+ {"LINEOUT", NULL, "LINEOUT Mixer"},
- cache[reg] = value;
-}
+ {"HPL Out", NULL, "Headphone Enable"},
+ {"HPR Out", NULL, "Headphone Enable"},
-/*
- * write to the AK4642 register space
- */
-static int ak4642_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 data[2];
+ {"Headphone Enable", "Switch", "DACH"},
- /* data is
- * D15..D8 AK4642 register offset
- * D7...D0 register data
- */
- data[0] = reg & 0xff;
- data[1] = value & 0xff;
-
- if (codec->hw_write(codec->control_data, data, 2) == 2) {
- ak4642_write_reg_cache(codec, reg, value);
- return 0;
- } else
- return -EIO;
-}
+ {"DACH", NULL, "DAC"},
-static int ak4642_sync(struct snd_soc_codec *codec)
-{
- u16 *cache = codec->reg_cache;
- int i, r = 0;
+ {"LINEOUT Mixer", "DACL", "DAC"},
+};
- for (i = 0; i < AK4642_CACHEREGNUM; i++)
- r |= ak4642_write(codec, i, cache[i]);
+/* codec private data */
+struct ak4642_priv {
+ unsigned int sysclk;
+ enum snd_soc_control_type control_type;
+};
+
+/*
+ * ak4642 register cache
+ */
+static const u8 ak4642_reg[] = {
+ 0x00, 0x00, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0xe1, 0xe1, 0x18, 0x00,
+ 0xe1, 0x18, 0x11, 0x08,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00,
+};
- return r;
+static const u8 ak4648_reg[] = {
+ 0x00, 0x00, 0x01, 0x00,
+ 0x02, 0x00, 0x00, 0x00,
+ 0xe1, 0xe1, 0x18, 0x00,
+ 0xe1, 0x18, 0x11, 0xb8,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x88, 0x88, 0x08,
};
static int ak4642_dai_startup(struct snd_pcm_substream *substream,
@@ -250,14 +246,8 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
* This operation came from example code of
* "ASAHI KASEI AK4642" (japanese) manual p97.
*/
- snd_soc_update_bits(codec, MD_CTL4, DACH, DACH);
- snd_soc_update_bits(codec, MD_CTL3, BST1, BST1);
- ak4642_write(codec, L_IVC, 0x91); /* volume */
- ak4642_write(codec, R_IVC, 0x91); /* volume */
- snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMMIN | PMDAC,
- PMVCM | PMMIN | PMDAC);
- snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, PMHP);
- snd_soc_update_bits(codec, PW_MGMT2, HPMTN, HPMTN);
+ snd_soc_write(codec, L_IVC, 0x91); /* volume */
+ snd_soc_write(codec, R_IVC, 0x91); /* volume */
} else {
/*
* start stereo input
@@ -272,11 +262,10 @@ static int ak4642_dai_startup(struct snd_pcm_substream *substream,
* This operation came from example code of
* "ASAHI KASEI AK4642" (japanese) manual p94.
*/
- ak4642_write(codec, SG_SL1, PMMP | MGAIN0);
- ak4642_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
- ak4642_write(codec, ALC_CTL1, ALC | LMTH0);
- snd_soc_update_bits(codec, PW_MGMT1, PMVCM | PMADL,
- PMVCM | PMADL);
+ snd_soc_write(codec, SG_SL1, PMMP | MGAIN0);
+ snd_soc_write(codec, TIMER, ZTM(0x3) | WTM(0x3));
+ snd_soc_write(codec, ALC_CTL1, ALC | LMTH0);
+ snd_soc_update_bits(codec, PW_MGMT1, PMADL, PMADL);
snd_soc_update_bits(codec, PW_MGMT3, PMADR, PMADR);
}
@@ -290,12 +279,6 @@ static void ak4642_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = dai->codec;
if (is_play) {
- /* stop headphone output */
- snd_soc_update_bits(codec, PW_MGMT2, HPMTN, 0);
- snd_soc_update_bits(codec, PW_MGMT2, PMHP_MASK, 0);
- snd_soc_update_bits(codec, PW_MGMT1, PMMIN | PMDAC, 0);
- snd_soc_update_bits(codec, MD_CTL3, BST1, 0);
- snd_soc_update_bits(codec, MD_CTL4, DACH, 0);
} else {
/* stop stereo input */
snd_soc_update_bits(codec, PW_MGMT1, PMADL, 0);
@@ -434,7 +417,23 @@ static int ak4642_dai_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_dai_ops ak4642_dai_ops = {
+static int ak4642_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_OFF:
+ snd_soc_write(codec, PW_MGMT1, 0x00);
+ break;
+ default:
+ snd_soc_update_bits(codec, PW_MGMT1, PMVCM, PMVCM);
+ break;
+ }
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops ak4642_dai_ops = {
.startup = ak4642_dai_startup,
.shutdown = ak4642_dai_shutdown,
.set_sysclk = ak4642_dai_set_sysclk,
@@ -462,7 +461,7 @@ static struct snd_soc_dai_driver ak4642_dai = {
static int ak4642_resume(struct snd_soc_codec *codec)
{
- ak4642_sync(codec);
+ snd_soc_cache_sync(codec);
return 0;
}
@@ -470,26 +469,54 @@ static int ak4642_resume(struct snd_soc_codec *codec)
static int ak4642_probe(struct snd_soc_codec *codec)
{
struct ak4642_priv *ak4642 = snd_soc_codec_get_drvdata(codec);
+ int ret;
- dev_info(codec->dev, "AK4642 Audio Codec %s", AK4642_VERSION);
-
- codec->hw_write = (hw_write_t)i2c_master_send;
- codec->control_data = ak4642->control_data;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4642->control_type);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
- snd_soc_add_controls(codec, ak4642_snd_controls,
+ snd_soc_add_codec_controls(codec, ak4642_snd_controls,
ARRAY_SIZE(ak4642_snd_controls));
+ ak4642_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
+}
+
+static int ak4642_remove(struct snd_soc_codec *codec)
+{
+ ak4642_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_ak4642 = {
.probe = ak4642_probe,
+ .remove = ak4642_remove,
+ .resume = ak4642_resume,
+ .set_bias_level = ak4642_set_bias_level,
+ .reg_cache_default = ak4642_reg, /* ak4642 reg */
+ .reg_cache_size = ARRAY_SIZE(ak4642_reg), /* ak4642 reg */
+ .reg_word_size = sizeof(u8),
+ .dapm_widgets = ak4642_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets),
+ .dapm_routes = ak4642_intercon,
+ .num_dapm_routes = ARRAY_SIZE(ak4642_intercon),
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_ak4648 = {
+ .probe = ak4642_probe,
+ .remove = ak4642_remove,
.resume = ak4642_resume,
- .read = ak4642_read_reg_cache,
- .write = ak4642_write,
- .reg_cache_size = ARRAY_SIZE(ak4642_reg),
+ .set_bias_level = ak4642_set_bias_level,
+ .reg_cache_default = ak4648_reg, /* ak4648 reg */
+ .reg_cache_size = ARRAY_SIZE(ak4648_reg), /* ak4648 reg */
.reg_word_size = sizeof(u8),
- .reg_cache_default = ak4642_reg,
+ .dapm_widgets = ak4642_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(ak4642_dapm_widgets),
+ .dapm_routes = ak4642_intercon,
+ .num_dapm_routes = ARRAY_SIZE(ak4642_intercon),
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -499,31 +526,30 @@ static __devinit int ak4642_i2c_probe(struct i2c_client *i2c,
struct ak4642_priv *ak4642;
int ret;
- ak4642 = kzalloc(sizeof(struct ak4642_priv), GFP_KERNEL);
+ ak4642 = devm_kzalloc(&i2c->dev, sizeof(struct ak4642_priv),
+ GFP_KERNEL);
if (!ak4642)
return -ENOMEM;
i2c_set_clientdata(i2c, ak4642);
- ak4642->control_data = i2c;
ak4642->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
- &soc_codec_dev_ak4642, &ak4642_dai, 1);
- if (ret < 0)
- kfree(ak4642);
+ (struct snd_soc_codec_driver *)id->driver_data,
+ &ak4642_dai, 1);
return ret;
}
static __devexit int ak4642_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
static const struct i2c_device_id ak4642_i2c_id[] = {
- { "ak4642", 0 },
- { "ak4643", 0 },
+ { "ak4642", (kernel_ulong_t)&soc_codec_dev_ak4642 },
+ { "ak4643", (kernel_ulong_t)&soc_codec_dev_ak4642 },
+ { "ak4648", (kernel_ulong_t)&soc_codec_dev_ak4648 },
{ }
};
MODULE_DEVICE_TABLE(i2c, ak4642_i2c_id);
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c
index 88b29f8c748b..5fb7c2a80e6d 100644
--- a/sound/soc/codecs/ak4671.c
+++ b/sound/soc/codecs/ak4671.c
@@ -26,7 +26,6 @@
/* codec private data */
struct ak4671_priv {
enum snd_soc_control_type control_type;
- void *control_data;
};
/* ak4671 register cache & default register settings */
@@ -169,18 +168,15 @@ static int ak4671_out2_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- u8 reg;
switch (event) {
case SND_SOC_DAPM_POST_PMU:
- reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
- reg |= AK4671_MUTEN;
- snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
+ snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT,
+ AK4671_MUTEN, AK4671_MUTEN);
break;
case SND_SOC_DAPM_PRE_PMD:
- reg = snd_soc_read(codec, AK4671_LOUT2_POWER_MANAGERMENT);
- reg &= ~AK4671_MUTEN;
- snd_soc_write(codec, AK4671_LOUT2_POWER_MANAGERMENT, reg);
+ snd_soc_update_bits(codec, AK4671_LOUT2_POWER_MANAGERMENT,
+ AK4671_MUTEN, 0);
break;
}
@@ -576,15 +572,12 @@ static int ak4671_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
static int ak4671_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u8 reg;
-
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
case SND_SOC_BIAS_STANDBY:
- reg = snd_soc_read(codec, AK4671_AD_DA_POWER_MANAGEMENT);
- snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT,
- reg | AK4671_PMVCM);
+ snd_soc_update_bits(codec, AK4671_AD_DA_POWER_MANAGEMENT,
+ AK4671_PMVCM, AK4671_PMVCM);
break;
case SND_SOC_BIAS_OFF:
snd_soc_write(codec, AK4671_AD_DA_POWER_MANAGEMENT, 0x00);
@@ -601,7 +594,7 @@ static int ak4671_set_bias_level(struct snd_soc_codec *codec,
#define AK4671_FORMATS SNDRV_PCM_FMTBIT_S16_LE
-static struct snd_soc_dai_ops ak4671_dai_ops = {
+static const struct snd_soc_dai_ops ak4671_dai_ops = {
.hw_params = ak4671_hw_params,
.set_sysclk = ak4671_set_dai_sysclk,
.set_fmt = ak4671_set_dai_fmt,
@@ -629,15 +622,13 @@ static int ak4671_probe(struct snd_soc_codec *codec)
struct ak4671_priv *ak4671 = snd_soc_codec_get_drvdata(codec);
int ret;
- codec->hw_write = (hw_write_t)i2c_master_send;
-
ret = snd_soc_codec_set_cache_io(codec, 8, 8, ak4671->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- snd_soc_add_controls(codec, ak4671_snd_controls,
+ snd_soc_add_codec_controls(codec, ak4671_snd_controls,
ARRAY_SIZE(ak4671_snd_controls));
ak4671_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -670,25 +661,22 @@ static int __devinit ak4671_i2c_probe(struct i2c_client *client,
struct ak4671_priv *ak4671;
int ret;
- ak4671 = kzalloc(sizeof(struct ak4671_priv), GFP_KERNEL);
+ ak4671 = devm_kzalloc(&client->dev, sizeof(struct ak4671_priv),
+ GFP_KERNEL);
if (ak4671 == NULL)
return -ENOMEM;
i2c_set_clientdata(client, ak4671);
- ak4671->control_data = client;
ak4671->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&client->dev,
&soc_codec_dev_ak4671, &ak4671_dai, 1);
- if (ret < 0)
- kfree(ak4671);
return ret;
}
static __devexit int ak4671_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c
index eecffb548947..d47b62ddb210 100644
--- a/sound/soc/codecs/alc5623.c
+++ b/sound/soc/codecs/alc5623.c
@@ -22,7 +22,6 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/slab.h>
-#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -40,8 +39,6 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)");
/* codec private data */
struct alc5623_priv {
enum snd_soc_control_type control_type;
- void *control_data;
- struct mutex mutex;
u8 id;
unsigned int sysclk;
u16 reg_cache[ALC5623_VENDOR_ID2+2];
@@ -55,8 +52,10 @@ static void alc5623_fill_cache(struct snd_soc_codec *codec)
u16 *cache = codec->reg_cache;
/* not really efficient ... */
+ codec->cache_bypass = 1;
for (i = 0 ; i < codec->driver->reg_cache_size ; i += step)
- cache[i] = codec->hw_read(codec, i);
+ cache[i] = snd_soc_read(codec, i);
+ codec->cache_bypass = 0;
}
static inline int alc5623_reset(struct snd_soc_codec *codec)
@@ -100,7 +99,7 @@ static const unsigned int boost_tlv[] = {
};
static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
-static const struct snd_kcontrol_new rt5621_vol_snd_controls[] = {
+static const struct snd_kcontrol_new alc5621_vol_snd_controls[] = {
SOC_DOUBLE_TLV("Speaker Playback Volume",
ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
SOC_DOUBLE("Speaker Playback Switch",
@@ -111,7 +110,7 @@ static const struct snd_kcontrol_new rt5621_vol_snd_controls[] = {
ALC5623_HP_OUT_VOL, 15, 7, 1, 1),
};
-static const struct snd_kcontrol_new rt5622_vol_snd_controls[] = {
+static const struct snd_kcontrol_new alc5622_vol_snd_controls[] = {
SOC_DOUBLE_TLV("Speaker Playback Volume",
ALC5623_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
SOC_DOUBLE("Speaker Playback Switch",
@@ -839,7 +838,7 @@ static int alc5623_set_bias_level(struct snd_soc_codec *codec,
| SNDRV_PCM_FMTBIT_S24_LE \
| SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops alc5623_dai_ops = {
+static const struct snd_soc_dai_ops alc5623_dai_ops = {
.hw_params = alc5623_pcm_hw_params,
.digital_mute = alc5623_mute,
.set_fmt = alc5623_set_dai_fmt,
@@ -869,7 +868,7 @@ static struct snd_soc_dai_driver alc5623_dai = {
.ops = &alc5623_dai_ops,
};
-static int alc5623_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+static int alc5623_suspend(struct snd_soc_codec *codec)
{
alc5623_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -926,22 +925,22 @@ static int alc5623_probe(struct snd_soc_codec *codec)
switch (alc5623->id) {
case 0x21:
- snd_soc_add_controls(codec, rt5621_vol_snd_controls,
- ARRAY_SIZE(rt5621_vol_snd_controls));
+ snd_soc_add_codec_controls(codec, alc5621_vol_snd_controls,
+ ARRAY_SIZE(alc5621_vol_snd_controls));
break;
case 0x22:
- snd_soc_add_controls(codec, rt5622_vol_snd_controls,
- ARRAY_SIZE(rt5622_vol_snd_controls));
+ snd_soc_add_codec_controls(codec, alc5622_vol_snd_controls,
+ ARRAY_SIZE(alc5622_vol_snd_controls));
break;
case 0x23:
- snd_soc_add_controls(codec, alc5623_vol_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5623_vol_snd_controls,
ARRAY_SIZE(alc5623_vol_snd_controls));
break;
default:
return -EINVAL;
}
- snd_soc_add_controls(codec, alc5623_snd_controls,
+ snd_soc_add_codec_controls(codec, alc5623_snd_controls,
ARRAY_SIZE(alc5623_snd_controls));
snd_soc_dapm_new_controls(dapm, alc5623_dapm_widgets,
@@ -993,7 +992,7 @@ static struct snd_soc_codec_driver soc_codec_device_alc5623 = {
* low = 0x1a
* high = 0x1b
*/
-static int alc5623_i2c_probe(struct i2c_client *client,
+static __devinit int alc5623_i2c_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
struct alc5623_platform_data *pdata;
@@ -1023,7 +1022,8 @@ static int alc5623_i2c_probe(struct i2c_client *client,
dev_dbg(&client->dev, "Found codec id : alc56%02x\n", vid2);
- alc5623 = kzalloc(sizeof(struct alc5623_priv), GFP_KERNEL);
+ alc5623 = devm_kzalloc(&client->dev, sizeof(struct alc5623_priv),
+ GFP_KERNEL);
if (alc5623 == NULL)
return -ENOMEM;
@@ -1045,31 +1045,23 @@ static int alc5623_i2c_probe(struct i2c_client *client,
alc5623_dai.name = "alc5623-hifi";
break;
default:
- kfree(alc5623);
return -EINVAL;
}
i2c_set_clientdata(client, alc5623);
- alc5623->control_data = client;
alc5623->control_type = SND_SOC_I2C;
- mutex_init(&alc5623->mutex);
ret = snd_soc_register_codec(&client->dev,
&soc_codec_device_alc5623, &alc5623_dai, 1);
- if (ret != 0) {
+ if (ret != 0)
dev_err(&client->dev, "Failed to register codec: %d\n", ret);
- kfree(alc5623);
- }
return ret;
}
-static int alc5623_i2c_remove(struct i2c_client *client)
+static __devexit int alc5623_i2c_remove(struct i2c_client *client)
{
- struct alc5623_priv *alc5623 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- kfree(alc5623);
return 0;
}
diff --git a/sound/soc/codecs/alc5632.c b/sound/soc/codecs/alc5632.c
new file mode 100644
index 000000000000..e2111e0ccad7
--- /dev/null
+++ b/sound/soc/codecs/alc5632.c
@@ -0,0 +1,1234 @@
+/*
+* alc5632.c -- ALC5632 ALSA SoC Audio Codec
+*
+* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+*
+* Authors: Leon Romanovsky <leon@leon.nu>
+* Andrey Danin <danindrey@mail.ru>
+* Ilya Petrov <ilya.muromec@gmail.com>
+* Marc Dietrich <marvin24@gmx.de>
+*
+* Based on alc5623.c by Arnaud Patard
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regmap.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/tlv.h>
+#include <sound/soc.h>
+#include <sound/initval.h>
+
+#include "alc5632.h"
+
+/*
+ * ALC5632 register cache
+ */
+static struct reg_default alc5632_reg_defaults[] = {
+ { 2, 0x8080 }, /* R2 - Speaker Output Volume */
+ { 4, 0x8080 }, /* R4 - Headphone Output Volume */
+ { 6, 0x8080 }, /* R6 - AUXOUT Volume */
+ { 8, 0xC800 }, /* R8 - Phone Input */
+ { 10, 0xE808 }, /* R10 - LINE_IN Volume */
+ { 12, 0x1010 }, /* R12 - STEREO DAC Input Volume */
+ { 14, 0x0808 }, /* R14 - MIC Input Volume */
+ { 16, 0xEE0F }, /* R16 - Stereo DAC and MIC Routing Control */
+ { 18, 0xCBCB }, /* R18 - ADC Record Gain */
+ { 20, 0x7F7F }, /* R20 - ADC Record Mixer Control */
+ { 24, 0xE010 }, /* R24 - Voice DAC Volume */
+ { 28, 0x8008 }, /* R28 - Output Mixer Control */
+ { 34, 0x0000 }, /* R34 - Microphone Control */
+ { 36, 0x00C0 }, /* R36 - Codec Digital MIC/Digital Boost
+ Control */
+ { 46, 0x0000 }, /* R46 - Stereo DAC/Voice DAC/Stereo ADC
+ Function Select */
+ { 52, 0x8000 }, /* R52 - Main Serial Data Port Control
+ (Stereo I2S) */
+ { 54, 0x0000 }, /* R54 - Extend Serial Data Port Control
+ (VoDAC_I2S/PCM) */
+ { 58, 0x0000 }, /* R58 - Power Management Addition 1 */
+ { 60, 0x0000 }, /* R60 - Power Management Addition 2 */
+ { 62, 0x8000 }, /* R62 - Power Management Addition 3 */
+ { 64, 0x0C0A }, /* R64 - General Purpose Control Register 1 */
+ { 66, 0x0000 }, /* R66 - General Purpose Control Register 2 */
+ { 68, 0x0000 }, /* R68 - PLL1 Control */
+ { 70, 0x0000 }, /* R70 - PLL2 Control */
+ { 76, 0xBE3E }, /* R76 - GPIO Pin Configuration */
+ { 78, 0xBE3E }, /* R78 - GPIO Pin Polarity */
+ { 80, 0x0000 }, /* R80 - GPIO Pin Sticky */
+ { 82, 0x0000 }, /* R82 - GPIO Pin Wake Up */
+ { 86, 0x0000 }, /* R86 - Pin Sharing */
+ { 90, 0x0009 }, /* R90 - Soft Volume Control Setting */
+ { 92, 0x0000 }, /* R92 - GPIO_Output Pin Control */
+ { 94, 0x3000 }, /* R94 - MISC Control */
+ { 96, 0x3075 }, /* R96 - Stereo DAC Clock Control_1 */
+ { 98, 0x1010 }, /* R98 - Stereo DAC Clock Control_2 */
+ { 100, 0x3110 }, /* R100 - VoDAC_PCM Clock Control_1 */
+ { 104, 0x0553 }, /* R104 - Pseudo Stereo and Spatial Effect
+ Block Control */
+ { 106, 0x0000 }, /* R106 - Private Register Address */
+};
+
+/* codec private data */
+struct alc5632_priv {
+ struct regmap *regmap;
+ u8 id;
+ unsigned int sysclk;
+};
+
+static bool alc5632_volatile_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case ALC5632_RESET:
+ case ALC5632_PWR_DOWN_CTRL_STATUS:
+ case ALC5632_GPIO_PIN_STATUS:
+ case ALC5632_OVER_CURR_STATUS:
+ case ALC5632_HID_CTRL_DATA:
+ case ALC5632_EQ_CTRL:
+ case ALC5632_VENDOR_ID1:
+ case ALC5632_VENDOR_ID2:
+ return true;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
+static inline int alc5632_reset(struct regmap *map)
+{
+ return regmap_write(map, ALC5632_RESET, 0x59B4);
+}
+
+static int amp_mixer_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ /* to power-on/off class-d amp generators/speaker */
+ /* need to write to 'index-46h' register : */
+ /* so write index num (here 0x46) to reg 0x6a */
+ /* and then 0xffff/0 to reg 0x6c */
+ snd_soc_write(w->codec, ALC5632_HID_CTRL_INDEX, 0x46);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0xFFFF);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ snd_soc_write(w->codec, ALC5632_HID_CTRL_DATA, 0);
+ break;
+ }
+
+ return 0;
+}
+
+/*
+ * ALC5632 Controls
+ */
+
+/* -34.5db min scale, 1.5db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(vol_tlv, -3450, 150, 0);
+/* -46.5db min scale, 1.5db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(hp_tlv, -4650, 150, 0);
+/* -16.5db min scale, 1.5db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(adc_rec_tlv, -1650, 150, 0);
+static const unsigned int boost_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 1, TLV_DB_SCALE_ITEM(0, 2000, 0),
+ 1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
+};
+/* 0db min scale, 6 db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(dig_tlv, 0, 600, 0);
+/* 0db min scalem 0.75db steps, no mute */
+static const DECLARE_TLV_DB_SCALE(vdac_tlv, -3525, 75, 0);
+
+static const struct snd_kcontrol_new alc5632_vol_snd_controls[] = {
+ /* left starts at bit 8, right at bit 0 */
+ /* 31 steps (5 bit), -46.5db scale */
+ SOC_DOUBLE_TLV("Speaker Playback Volume",
+ ALC5632_SPK_OUT_VOL, 8, 0, 31, 1, hp_tlv),
+ /* bit 15 mutes left, bit 7 right */
+ SOC_DOUBLE("Speaker Playback Switch",
+ ALC5632_SPK_OUT_VOL, 15, 7, 1, 1),
+ SOC_DOUBLE_TLV("Headphone Playback Volume",
+ ALC5632_HP_OUT_VOL, 8, 0, 31, 1, hp_tlv),
+ SOC_DOUBLE("Headphone Playback Switch",
+ ALC5632_HP_OUT_VOL, 15, 7, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_snd_controls[] = {
+ SOC_DOUBLE_TLV("Auxout Playback Volume",
+ ALC5632_AUX_OUT_VOL, 8, 0, 31, 1, hp_tlv),
+ SOC_DOUBLE("Auxout Playback Switch",
+ ALC5632_AUX_OUT_VOL, 15, 7, 1, 1),
+ SOC_SINGLE_TLV("Voice DAC Playback Volume",
+ ALC5632_VOICE_DAC_VOL, 0, 63, 0, vdac_tlv),
+ SOC_SINGLE("Voice DAC Playback Switch",
+ ALC5632_VOICE_DAC_VOL, 12, 1, 1),
+ SOC_SINGLE_TLV("Phone Playback Volume",
+ ALC5632_PHONE_IN_VOL, 8, 31, 1, vol_tlv),
+ SOC_DOUBLE_TLV("LineIn Playback Volume",
+ ALC5632_LINE_IN_VOL, 8, 0, 31, 1, vol_tlv),
+ SOC_DOUBLE_TLV("Master Playback Volume",
+ ALC5632_STEREO_DAC_IN_VOL, 8, 0, 63, 1, vdac_tlv),
+ SOC_DOUBLE("Master Playback Switch",
+ ALC5632_STEREO_DAC_IN_VOL, 15, 7, 1, 1),
+ SOC_SINGLE_TLV("Mic1 Playback Volume",
+ ALC5632_MIC_VOL, 8, 31, 1, vol_tlv),
+ SOC_SINGLE_TLV("Mic2 Playback Volume",
+ ALC5632_MIC_VOL, 0, 31, 1, vol_tlv),
+ SOC_DOUBLE_TLV("Rec Capture Volume",
+ ALC5632_ADC_REC_GAIN, 8, 0, 31, 0, adc_rec_tlv),
+ SOC_SINGLE_TLV("Mic 1 Boost Volume",
+ ALC5632_MIC_CTRL, 10, 3, 0, boost_tlv),
+ SOC_SINGLE_TLV("Mic 2 Boost Volume",
+ ALC5632_MIC_CTRL, 8, 3, 0, boost_tlv),
+ SOC_SINGLE_TLV("DMIC Boost Capture Volume",
+ ALC5632_DIGI_BOOST_CTRL, 0, 7, 0, dig_tlv),
+ SOC_SINGLE("DMIC En Capture Switch",
+ ALC5632_DIGI_BOOST_CTRL, 15, 1, 0),
+ SOC_SINGLE("DMIC PreFilter Capture Switch",
+ ALC5632_DIGI_BOOST_CTRL, 12, 1, 0),
+};
+
+/*
+ * DAPM Controls
+ */
+static const struct snd_kcontrol_new alc5632_hp_mixer_controls[] = {
+SOC_DAPM_SINGLE("LI2HP Playback Switch", ALC5632_LINE_IN_VOL, 15, 1, 1),
+SOC_DAPM_SINGLE("PHONE2HP Playback Switch", ALC5632_PHONE_IN_VOL, 15, 1, 1),
+SOC_DAPM_SINGLE("MIC12HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 15, 1, 1),
+SOC_DAPM_SINGLE("MIC22HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 11, 1, 1),
+SOC_DAPM_SINGLE("VOICE2HP Playback Switch", ALC5632_VOICE_DAC_VOL, 15, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_hpl_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC2HP_L Playback Switch", ALC5632_ADC_REC_GAIN, 15, 1, 1),
+SOC_DAPM_SINGLE("DACL2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 3, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_hpr_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC2HP_R Playback Switch", ALC5632_ADC_REC_GAIN, 7, 1, 1),
+SOC_DAPM_SINGLE("DACR2HP Playback Switch", ALC5632_MIC_ROUTING_CTRL, 2, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_mono_mixer_controls[] = {
+SOC_DAPM_SINGLE("ADC2MONO_L Playback Switch", ALC5632_ADC_REC_GAIN, 14, 1, 1),
+SOC_DAPM_SINGLE("ADC2MONO_R Playback Switch", ALC5632_ADC_REC_GAIN, 6, 1, 1),
+SOC_DAPM_SINGLE("LI2MONO Playback Switch", ALC5632_LINE_IN_VOL, 13, 1, 1),
+SOC_DAPM_SINGLE("MIC12MONO Playback Switch",
+ ALC5632_MIC_ROUTING_CTRL, 13, 1, 1),
+SOC_DAPM_SINGLE("MIC22MONO Playback Switch",
+ ALC5632_MIC_ROUTING_CTRL, 9, 1, 1),
+SOC_DAPM_SINGLE("DAC2MONO Playback Switch", ALC5632_MIC_ROUTING_CTRL, 0, 1, 1),
+SOC_DAPM_SINGLE("VOICE2MONO Playback Switch", ALC5632_VOICE_DAC_VOL, 13, 1, 1),
+};
+
+static const struct snd_kcontrol_new alc5632_speaker_mixer_controls[] = {
+SOC_DAPM_SINGLE("LI2SPK Playback Switch", ALC5632_LINE_IN_VOL, 14, 1, 1),
+SOC_DAPM_SINGLE("PHONE2SPK Playback Switch", ALC5632_PHONE_IN_VOL, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC12SPK Playback Switch",
+ ALC5632_MIC_ROUTING_CTRL, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC22SPK Playback Switch",
+ ALC5632_MIC_ROUTING_CTRL, 10, 1, 1),
+SOC_DAPM_SINGLE("DAC2SPK Playback Switch", ALC5632_MIC_ROUTING_CTRL, 1, 1, 1),
+SOC_DAPM_SINGLE("VOICE2SPK Playback Switch", ALC5632_VOICE_DAC_VOL, 14, 1, 1),
+};
+
+/* Left Record Mixer */
+static const struct snd_kcontrol_new alc5632_captureL_mixer_controls[] = {
+SOC_DAPM_SINGLE("MIC12REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 14, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 13, 1, 1),
+SOC_DAPM_SINGLE("LIL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 12, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 11, 1, 1),
+SOC_DAPM_SINGLE("HPL2REC Capture Switch", ALC5632_ADC_REC_MIXER, 10, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 9, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_L Capture Switch", ALC5632_ADC_REC_MIXER, 8, 1, 1),
+};
+
+/* Right Record Mixer */
+static const struct snd_kcontrol_new alc5632_captureR_mixer_controls[] = {
+SOC_DAPM_SINGLE("MIC12REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 6, 1, 1),
+SOC_DAPM_SINGLE("MIC22REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 5, 1, 1),
+SOC_DAPM_SINGLE("LIR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 4, 1, 1),
+SOC_DAPM_SINGLE("PH2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 3, 1, 1),
+SOC_DAPM_SINGLE("HPR2REC Capture Switch", ALC5632_ADC_REC_MIXER, 2, 1, 1),
+SOC_DAPM_SINGLE("SPK2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 1, 1, 1),
+SOC_DAPM_SINGLE("MONO2REC_R Capture Switch", ALC5632_ADC_REC_MIXER, 0, 1, 1),
+};
+
+/* Dmic Mixer */
+static const struct snd_kcontrol_new alc5632_dmicl_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICL2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 7, 1, 1),
+};
+static const struct snd_kcontrol_new alc5632_dmicr_mixer_controls[] = {
+SOC_DAPM_SINGLE("DMICR2ADC Capture Switch", ALC5632_DIGI_BOOST_CTRL, 6, 1, 1),
+};
+
+static const char * const alc5632_spk_n_sour_sel[] = {
+ "RN/-R", "RP/+R", "LN/-R", "Mute"};
+static const char * const alc5632_hpl_out_input_sel[] = {
+ "Vmid", "HP Left Mix"};
+static const char * const alc5632_hpr_out_input_sel[] = {
+ "Vmid", "HP Right Mix"};
+static const char * const alc5632_spkout_input_sel[] = {
+ "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+static const char * const alc5632_aux_out_input_sel[] = {
+ "Vmid", "HPOut Mix", "Speaker Mix", "Mono Mix"};
+static const char * const alc5632_adcr_func_sel[] = {
+ "Stereo ADC", "Voice ADC"};
+static const char * const alc5632_i2s_out_sel[] = {
+ "ADC LR", "Voice Stereo Digital"};
+
+/* auxout output mux */
+static const struct soc_enum alc5632_aux_out_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 6, 4, alc5632_aux_out_input_sel);
+static const struct snd_kcontrol_new alc5632_auxout_mux_controls =
+SOC_DAPM_ENUM("AuxOut Mux", alc5632_aux_out_input_enum);
+
+/* speaker output mux */
+static const struct soc_enum alc5632_spkout_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 10, 4, alc5632_spkout_input_sel);
+static const struct snd_kcontrol_new alc5632_spkout_mux_controls =
+SOC_DAPM_ENUM("SpeakerOut Mux", alc5632_spkout_input_enum);
+
+/* headphone left output mux */
+static const struct soc_enum alc5632_hpl_out_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 9, 2, alc5632_hpl_out_input_sel);
+static const struct snd_kcontrol_new alc5632_hpl_out_mux_controls =
+SOC_DAPM_ENUM("Left Headphone Mux", alc5632_hpl_out_input_enum);
+
+/* headphone right output mux */
+static const struct soc_enum alc5632_hpr_out_input_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 8, 2, alc5632_hpr_out_input_sel);
+static const struct snd_kcontrol_new alc5632_hpr_out_mux_controls =
+SOC_DAPM_ENUM("Right Headphone Mux", alc5632_hpr_out_input_enum);
+
+/* speaker output N select */
+static const struct soc_enum alc5632_spk_n_sour_enum =
+SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 14, 4, alc5632_spk_n_sour_sel);
+static const struct snd_kcontrol_new alc5632_spkoutn_mux_controls =
+SOC_DAPM_ENUM("SpeakerOut N Mux", alc5632_spk_n_sour_enum);
+
+/* speaker amplifier */
+static const char *alc5632_amp_names[] = {"AB Amp", "D Amp"};
+static const struct soc_enum alc5632_amp_enum =
+ SOC_ENUM_SINGLE(ALC5632_OUTPUT_MIXER_CTRL, 13, 2, alc5632_amp_names);
+static const struct snd_kcontrol_new alc5632_amp_mux_controls =
+ SOC_DAPM_ENUM("AB-D Amp Mux", alc5632_amp_enum);
+
+/* ADC output select */
+static const struct soc_enum alc5632_adcr_func_enum =
+ SOC_ENUM_SINGLE(ALC5632_DAC_FUNC_SELECT, 5, 2, alc5632_adcr_func_sel);
+static const struct snd_kcontrol_new alc5632_adcr_func_controls =
+ SOC_DAPM_ENUM("ADCR Mux", alc5632_adcr_func_enum);
+
+/* I2S out select */
+static const struct soc_enum alc5632_i2s_out_enum =
+ SOC_ENUM_SINGLE(ALC5632_I2S_OUT_CTL, 5, 2, alc5632_i2s_out_sel);
+static const struct snd_kcontrol_new alc5632_i2s_out_controls =
+ SOC_DAPM_ENUM("I2SOut Mux", alc5632_i2s_out_enum);
+
+static const struct snd_soc_dapm_widget alc5632_dapm_widgets[] = {
+/* Muxes */
+SND_SOC_DAPM_MUX("AuxOut Mux", SND_SOC_NOPM, 0, 0,
+ &alc5632_auxout_mux_controls),
+SND_SOC_DAPM_MUX("SpeakerOut Mux", SND_SOC_NOPM, 0, 0,
+ &alc5632_spkout_mux_controls),
+SND_SOC_DAPM_MUX("Left Headphone Mux", SND_SOC_NOPM, 0, 0,
+ &alc5632_hpl_out_mux_controls),
+SND_SOC_DAPM_MUX("Right Headphone Mux", SND_SOC_NOPM, 0, 0,
+ &alc5632_hpr_out_mux_controls),
+SND_SOC_DAPM_MUX("SpeakerOut N Mux", SND_SOC_NOPM, 0, 0,
+ &alc5632_spkoutn_mux_controls),
+SND_SOC_DAPM_MUX("ADCR Mux", SND_SOC_NOPM, 0, 0,
+ &alc5632_adcr_func_controls),
+SND_SOC_DAPM_MUX("I2SOut Mux", ALC5632_PWR_MANAG_ADD1, 11, 0,
+ &alc5632_i2s_out_controls),
+
+/* output mixers */
+SND_SOC_DAPM_MIXER("HP Mix", SND_SOC_NOPM, 0, 0,
+ &alc5632_hp_mixer_controls[0],
+ ARRAY_SIZE(alc5632_hp_mixer_controls)),
+SND_SOC_DAPM_MIXER("HPR Mix", ALC5632_PWR_MANAG_ADD2, 4, 0,
+ &alc5632_hpr_mixer_controls[0],
+ ARRAY_SIZE(alc5632_hpr_mixer_controls)),
+SND_SOC_DAPM_MIXER("HPL Mix", ALC5632_PWR_MANAG_ADD2, 5, 0,
+ &alc5632_hpl_mixer_controls[0],
+ ARRAY_SIZE(alc5632_hpl_mixer_controls)),
+SND_SOC_DAPM_MIXER("HPOut Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Mono Mix", ALC5632_PWR_MANAG_ADD2, 2, 0,
+ &alc5632_mono_mixer_controls[0],
+ ARRAY_SIZE(alc5632_mono_mixer_controls)),
+SND_SOC_DAPM_MIXER("Speaker Mix", ALC5632_PWR_MANAG_ADD2, 3, 0,
+ &alc5632_speaker_mixer_controls[0],
+ ARRAY_SIZE(alc5632_speaker_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICL Mix", SND_SOC_NOPM, 0, 0,
+ &alc5632_dmicl_mixer_controls[0],
+ ARRAY_SIZE(alc5632_dmicl_mixer_controls)),
+SND_SOC_DAPM_MIXER("DMICR Mix", SND_SOC_NOPM, 0, 0,
+ &alc5632_dmicr_mixer_controls[0],
+ ARRAY_SIZE(alc5632_dmicr_mixer_controls)),
+
+/* input mixers */
+SND_SOC_DAPM_MIXER("Left Capture Mix", ALC5632_PWR_MANAG_ADD2, 1, 0,
+ &alc5632_captureL_mixer_controls[0],
+ ARRAY_SIZE(alc5632_captureL_mixer_controls)),
+SND_SOC_DAPM_MIXER("Right Capture Mix", ALC5632_PWR_MANAG_ADD2, 0, 0,
+ &alc5632_captureR_mixer_controls[0],
+ ARRAY_SIZE(alc5632_captureR_mixer_controls)),
+
+SND_SOC_DAPM_AIF_IN("AIFRXL", "Left HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIFRXR", "Right HiFi Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXL", "Left HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIFTXR", "Right HiFi Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("VAIFRX", "Voice Playback", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("VAIFTX", "Voice Capture", 0, SND_SOC_NOPM, 0, 0),
+
+SND_SOC_DAPM_DAC("Voice DAC", NULL, ALC5632_PWR_MANAG_ADD2, 10, 0),
+SND_SOC_DAPM_DAC("Left DAC", NULL, ALC5632_PWR_MANAG_ADD2, 9, 0),
+SND_SOC_DAPM_DAC("Right DAC", NULL, ALC5632_PWR_MANAG_ADD2, 8, 0),
+SND_SOC_DAPM_ADC("Left ADC", NULL, ALC5632_PWR_MANAG_ADD2, 7, 0),
+SND_SOC_DAPM_ADC("Right ADC", NULL, ALC5632_PWR_MANAG_ADD2, 6, 0),
+
+SND_SOC_DAPM_MIXER("DAC Left Channel", ALC5632_PWR_MANAG_ADD1, 15, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("DAC Right Channel",
+ ALC5632_PWR_MANAG_ADD1, 14, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("I2S Mix", ALC5632_PWR_MANAG_ADD1, 11, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Phone Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Line Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("Voice Mix", SND_SOC_NOPM, 0, 0, NULL, 0),
+SND_SOC_DAPM_MIXER("ADCLR", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("Left Headphone", ALC5632_PWR_MANAG_ADD3, 11, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Headphone", ALC5632_PWR_MANAG_ADD3, 10, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Left Speaker", ALC5632_PWR_MANAG_ADD3, 13, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right Speaker", ALC5632_PWR_MANAG_ADD3, 12, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Aux Out", ALC5632_PWR_MANAG_ADD3, 14, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Left LineIn", ALC5632_PWR_MANAG_ADD3, 7, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Right LineIn", ALC5632_PWR_MANAG_ADD3, 6, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Phone", ALC5632_PWR_MANAG_ADD3, 5, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Phone ADMix", ALC5632_PWR_MANAG_ADD3, 4, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC1 PGA", ALC5632_PWR_MANAG_ADD3, 3, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC2 PGA", ALC5632_PWR_MANAG_ADD3, 2, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC1 Pre Amp", ALC5632_PWR_MANAG_ADD3, 1, 0, NULL, 0),
+SND_SOC_DAPM_PGA("MIC2 Pre Amp", ALC5632_PWR_MANAG_ADD3, 0, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", ALC5632_PWR_MANAG_ADD1, 3, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", ALC5632_PWR_MANAG_ADD1, 2, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_E("D Amp", ALC5632_PWR_MANAG_ADD2, 14, 0, NULL, 0,
+ amp_mixer_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_PGA("AB Amp", ALC5632_PWR_MANAG_ADD2, 15, 0, NULL, 0),
+SND_SOC_DAPM_MUX("AB-D Amp Mux", ALC5632_PWR_MANAG_ADD1, 10, 0,
+ &alc5632_amp_mux_controls),
+
+SND_SOC_DAPM_OUTPUT("AUXOUT"),
+SND_SOC_DAPM_OUTPUT("HPL"),
+SND_SOC_DAPM_OUTPUT("HPR"),
+SND_SOC_DAPM_OUTPUT("SPKOUT"),
+SND_SOC_DAPM_OUTPUT("SPKOUTN"),
+
+SND_SOC_DAPM_INPUT("LINEINL"),
+SND_SOC_DAPM_INPUT("LINEINR"),
+SND_SOC_DAPM_INPUT("PHONEP"),
+SND_SOC_DAPM_INPUT("PHONEN"),
+SND_SOC_DAPM_INPUT("DMICDAT"),
+SND_SOC_DAPM_INPUT("MIC1"),
+SND_SOC_DAPM_INPUT("MIC2"),
+SND_SOC_DAPM_VMID("Vmid"),
+};
+
+
+static const struct snd_soc_dapm_route alc5632_dapm_routes[] = {
+ /* Playback streams */
+ {"Left DAC", NULL, "AIFRXL"},
+ {"Right DAC", NULL, "AIFRXR"},
+
+ /* virtual mixer - mixes left & right channels */
+ {"I2S Mix", NULL, "Left DAC"},
+ {"I2S Mix", NULL, "Right DAC"},
+ {"Line Mix", NULL, "Right LineIn"},
+ {"Line Mix", NULL, "Left LineIn"},
+ {"Phone Mix", NULL, "Phone"},
+ {"Phone Mix", NULL, "Phone ADMix"},
+ {"AUXOUT", NULL, "Aux Out"},
+
+ /* DAC */
+ {"DAC Right Channel", NULL, "I2S Mix"},
+ {"DAC Left Channel", NULL, "I2S Mix"},
+
+ /* HP mixer */
+ {"HPL Mix", "ADC2HP_L Playback Switch", "Left Capture Mix"},
+ {"HPL Mix", NULL, "HP Mix"},
+ {"HPR Mix", "ADC2HP_R Playback Switch", "Right Capture Mix"},
+ {"HPR Mix", NULL, "HP Mix"},
+ {"HP Mix", "LI2HP Playback Switch", "Line Mix"},
+ {"HP Mix", "PHONE2HP Playback Switch", "Phone Mix"},
+ {"HP Mix", "MIC12HP Playback Switch", "MIC1 PGA"},
+ {"HP Mix", "MIC22HP Playback Switch", "MIC2 PGA"},
+ {"HP Mix", "VOICE2HP Playback Switch", "Voice Mix"},
+ {"HPR Mix", "DACR2HP Playback Switch", "DAC Right Channel"},
+ {"HPL Mix", "DACL2HP Playback Switch", "DAC Left Channel"},
+ {"HPOut Mix", NULL, "HP Mix"},
+ {"HPOut Mix", NULL, "HPR Mix"},
+ {"HPOut Mix", NULL, "HPL Mix"},
+
+ /* speaker mixer */
+ {"Speaker Mix", "LI2SPK Playback Switch", "Line Mix"},
+ {"Speaker Mix", "PHONE2SPK Playback Switch", "Phone Mix"},
+ {"Speaker Mix", "MIC12SPK Playback Switch", "MIC1 PGA"},
+ {"Speaker Mix", "MIC22SPK Playback Switch", "MIC2 PGA"},
+ {"Speaker Mix", "DAC2SPK Playback Switch", "DAC Left Channel"},
+ {"Speaker Mix", "VOICE2SPK Playback Switch", "Voice Mix"},
+
+ /* mono mixer */
+ {"Mono Mix", "ADC2MONO_L Playback Switch", "Left Capture Mix"},
+ {"Mono Mix", "ADC2MONO_R Playback Switch", "Right Capture Mix"},
+ {"Mono Mix", "LI2MONO Playback Switch", "Line Mix"},
+ {"Mono Mix", "MIC12MONO Playback Switch", "MIC1 PGA"},
+ {"Mono Mix", "MIC22MONO Playback Switch", "MIC2 PGA"},
+ {"Mono Mix", "DAC2MONO Playback Switch", "DAC Left Channel"},
+ {"Mono Mix", "VOICE2MONO Playback Switch", "Voice Mix"},
+
+ /* Left record mixer */
+ {"Left Capture Mix", "LIL2REC Capture Switch", "LINEINL"},
+ {"Left Capture Mix", "PH2REC_L Capture Switch", "PHONEN"},
+ {"Left Capture Mix", "MIC12REC_L Capture Switch", "MIC1 Pre Amp"},
+ {"Left Capture Mix", "MIC22REC_L Capture Switch", "MIC2 Pre Amp"},
+ {"Left Capture Mix", "HPL2REC Capture Switch", "HPL Mix"},
+ {"Left Capture Mix", "SPK2REC_L Capture Switch", "Speaker Mix"},
+ {"Left Capture Mix", "MONO2REC_L Capture Switch", "Mono Mix"},
+
+ /*Right record mixer */
+ {"Right Capture Mix", "LIR2REC Capture Switch", "LINEINR"},
+ {"Right Capture Mix", "PH2REC_R Capture Switch", "PHONEP"},
+ {"Right Capture Mix", "MIC12REC_R Capture Switch", "MIC1 Pre Amp"},
+ {"Right Capture Mix", "MIC22REC_R Capture Switch", "MIC2 Pre Amp"},
+ {"Right Capture Mix", "HPR2REC Capture Switch", "HPR Mix"},
+ {"Right Capture Mix", "SPK2REC_R Capture Switch", "Speaker Mix"},
+ {"Right Capture Mix", "MONO2REC_R Capture Switch", "Mono Mix"},
+
+ /* headphone left mux */
+ {"Left Headphone Mux", "HP Left Mix", "HPL Mix"},
+ {"Left Headphone Mux", "Vmid", "Vmid"},
+
+ /* headphone right mux */
+ {"Right Headphone Mux", "HP Right Mix", "HPR Mix"},
+ {"Right Headphone Mux", "Vmid", "Vmid"},
+
+ /* speaker out mux */
+ {"SpeakerOut Mux", "Vmid", "Vmid"},
+ {"SpeakerOut Mux", "HPOut Mix", "HPOut Mix"},
+ {"SpeakerOut Mux", "Speaker Mix", "Speaker Mix"},
+ {"SpeakerOut Mux", "Mono Mix", "Mono Mix"},
+
+ /* Mono/Aux Out mux */
+ {"AuxOut Mux", "Vmid", "Vmid"},
+ {"AuxOut Mux", "HPOut Mix", "HPOut Mix"},
+ {"AuxOut Mux", "Speaker Mix", "Speaker Mix"},
+ {"AuxOut Mux", "Mono Mix", "Mono Mix"},
+
+ /* output pga */
+ {"HPL", NULL, "Left Headphone"},
+ {"Left Headphone", NULL, "Left Headphone Mux"},
+ {"HPR", NULL, "Right Headphone"},
+ {"Right Headphone", NULL, "Right Headphone Mux"},
+ {"Aux Out", NULL, "AuxOut Mux"},
+
+ /* input pga */
+ {"Left LineIn", NULL, "LINEINL"},
+ {"Right LineIn", NULL, "LINEINR"},
+ {"Phone", NULL, "PHONEP"},
+ {"MIC1 Pre Amp", NULL, "MIC1"},
+ {"MIC2 Pre Amp", NULL, "MIC2"},
+ {"MIC1 PGA", NULL, "MIC1 Pre Amp"},
+ {"MIC2 PGA", NULL, "MIC2 Pre Amp"},
+
+ /* left ADC */
+ {"Left ADC", NULL, "Left Capture Mix"},
+ {"DMICL Mix", "DMICL2ADC Capture Switch", "DMICDAT"},
+ {"Left ADC", NULL, "DMICL Mix"},
+ {"ADCLR", NULL, "Left ADC"},
+
+ /* right ADC */
+ {"Right ADC", NULL, "Right Capture Mix"},
+ {"DMICR Mix", "DMICR2ADC Capture Switch", "DMICDAT"},
+ {"Right ADC", NULL, "DMICR Mix"},
+ {"ADCR Mux", "Stereo ADC", "Right ADC"},
+ {"ADCR Mux", "Voice ADC", "Right ADC"},
+ {"ADCLR", NULL, "ADCR Mux"},
+ {"VAIFTX", NULL, "ADCR Mux"},
+
+ /* Digital I2S out */
+ {"I2SOut Mux", "ADC LR", "ADCLR"},
+ {"I2SOut Mux", "Voice Stereo Digital", "VAIFRX"},
+ {"AIFTXL", NULL, "I2SOut Mux"},
+ {"AIFTXR", NULL, "I2SOut Mux"},
+
+ /* Voice Mix */
+ {"Voice DAC", NULL, "VAIFRX"},
+ {"Voice Mix", NULL, "Voice DAC"},
+
+ /* Speaker Output */
+ {"SpeakerOut N Mux", "RN/-R", "Left Speaker"},
+ {"SpeakerOut N Mux", "RP/+R", "Left Speaker"},
+ {"SpeakerOut N Mux", "LN/-R", "Left Speaker"},
+ {"SpeakerOut N Mux", "Mute", "Vmid"},
+
+ {"SpeakerOut N Mux", "RN/-R", "Right Speaker"},
+ {"SpeakerOut N Mux", "RP/+R", "Right Speaker"},
+ {"SpeakerOut N Mux", "LN/-R", "Right Speaker"},
+ {"SpeakerOut N Mux", "Mute", "Vmid"},
+
+ {"AB Amp", NULL, "SpeakerOut Mux"},
+ {"D Amp", NULL, "SpeakerOut Mux"},
+ {"AB-D Amp Mux", "AB Amp", "AB Amp"},
+ {"AB-D Amp Mux", "D Amp", "D Amp"},
+ {"Left Speaker", NULL, "AB-D Amp Mux"},
+ {"Right Speaker", NULL, "AB-D Amp Mux"},
+
+ {"SPKOUT", NULL, "Left Speaker"},
+ {"SPKOUT", NULL, "Right Speaker"},
+
+ {"SPKOUTN", NULL, "SpeakerOut N Mux"},
+
+};
+
+/* PLL divisors */
+struct _pll_div {
+ u32 pll_in;
+ u32 pll_out;
+ u16 regvalue;
+};
+
+/* Note : pll code from original alc5632 driver. Not sure of how good it is */
+/* usefull only for master mode */
+static const struct _pll_div codec_master_pll_div[] = {
+
+ { 2048000, 8192000, 0x0ea0},
+ { 3686400, 8192000, 0x4e27},
+ { 12000000, 8192000, 0x456b},
+ { 13000000, 8192000, 0x495f},
+ { 13100000, 8192000, 0x0320},
+ { 2048000, 11289600, 0xf637},
+ { 3686400, 11289600, 0x2f22},
+ { 12000000, 11289600, 0x3e2f},
+ { 13000000, 11289600, 0x4d5b},
+ { 13100000, 11289600, 0x363b},
+ { 2048000, 16384000, 0x1ea0},
+ { 3686400, 16384000, 0x9e27},
+ { 12000000, 16384000, 0x452b},
+ { 13000000, 16384000, 0x542f},
+ { 13100000, 16384000, 0x03a0},
+ { 2048000, 16934400, 0xe625},
+ { 3686400, 16934400, 0x9126},
+ { 12000000, 16934400, 0x4d2c},
+ { 13000000, 16934400, 0x742f},
+ { 13100000, 16934400, 0x3c27},
+ { 2048000, 22579200, 0x2aa0},
+ { 3686400, 22579200, 0x2f20},
+ { 12000000, 22579200, 0x7e2f},
+ { 13000000, 22579200, 0x742f},
+ { 13100000, 22579200, 0x3c27},
+ { 2048000, 24576000, 0x2ea0},
+ { 3686400, 24576000, 0xee27},
+ { 12000000, 24576000, 0x2915},
+ { 13000000, 24576000, 0x772e},
+ { 13100000, 24576000, 0x0d20},
+};
+
+/* FOUT = MCLK*(N+2)/((M+2)*(K+2))
+ N: bit 15:8 (div 2 .. div 257)
+ K: bit 6:4 typical 2
+ M: bit 3:0 (div 2 .. div 17)
+
+ same as for 5623 - thanks!
+*/
+
+static const struct _pll_div codec_slave_pll_div[] = {
+
+ { 1024000, 16384000, 0x3ea0},
+ { 1411200, 22579200, 0x3ea0},
+ { 1536000, 24576000, 0x3ea0},
+ { 2048000, 16384000, 0x1ea0},
+ { 2822400, 22579200, 0x1ea0},
+ { 3072000, 24576000, 0x1ea0},
+
+};
+
+static int alc5632_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+ int source, unsigned int freq_in, unsigned int freq_out)
+{
+ int i;
+ struct snd_soc_codec *codec = codec_dai->codec;
+ int gbl_clk = 0, pll_div = 0;
+ u16 reg;
+
+ if (pll_id < ALC5632_PLL_FR_MCLK || pll_id > ALC5632_PLL_FR_VBCLK)
+ return -EINVAL;
+
+ /* Disable PLL power */
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+ ALC5632_PWR_ADD2_PLL1,
+ 0);
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+ ALC5632_PWR_ADD2_PLL2,
+ 0);
+
+ /* pll is not used in slave mode */
+ reg = snd_soc_read(codec, ALC5632_DAI_CONTROL);
+ if (reg & ALC5632_DAI_SDP_SLAVE_MODE)
+ return 0;
+
+ if (!freq_in || !freq_out)
+ return 0;
+
+ switch (pll_id) {
+ case ALC5632_PLL_FR_MCLK:
+ for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++) {
+ if (codec_master_pll_div[i].pll_in == freq_in
+ && codec_master_pll_div[i].pll_out == freq_out) {
+ /* PLL source from MCLK */
+ pll_div = codec_master_pll_div[i].regvalue;
+ break;
+ }
+ }
+ break;
+ case ALC5632_PLL_FR_BCLK:
+ for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
+ if (codec_slave_pll_div[i].pll_in == freq_in
+ && codec_slave_pll_div[i].pll_out == freq_out) {
+ /* PLL source from Bitclk */
+ gbl_clk = ALC5632_PLL_FR_BCLK;
+ pll_div = codec_slave_pll_div[i].regvalue;
+ break;
+ }
+ }
+ break;
+ case ALC5632_PLL_FR_VBCLK:
+ for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++) {
+ if (codec_slave_pll_div[i].pll_in == freq_in
+ && codec_slave_pll_div[i].pll_out == freq_out) {
+ /* PLL source from voice clock */
+ gbl_clk = ALC5632_PLL_FR_VBCLK;
+ pll_div = codec_slave_pll_div[i].regvalue;
+ break;
+ }
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (!pll_div)
+ return -EINVAL;
+
+ /* choose MCLK/BCLK/VBCLK */
+ snd_soc_write(codec, ALC5632_GPCR2, gbl_clk);
+ /* choose PLL1 clock rate */
+ snd_soc_write(codec, ALC5632_PLL1_CTRL, pll_div);
+ /* enable PLL1 */
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+ ALC5632_PWR_ADD2_PLL1,
+ ALC5632_PWR_ADD2_PLL1);
+ /* enable PLL2 */
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+ ALC5632_PWR_ADD2_PLL2,
+ ALC5632_PWR_ADD2_PLL2);
+ /* use PLL1 as main SYSCLK */
+ snd_soc_update_bits(codec, ALC5632_GPCR1,
+ ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1,
+ ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1);
+
+ return 0;
+}
+
+struct _coeff_div {
+ u16 fs;
+ u16 regvalue;
+};
+
+/* codec hifi mclk (after PLL) clock divider coefficients */
+/* values inspired from column BCLK=32Fs of Appendix A table */
+static const struct _coeff_div coeff_div[] = {
+ {512*1, 0x3075},
+};
+
+static int get_coeff(struct snd_soc_codec *codec, int rate)
+{
+ struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+ if (coeff_div[i].fs * rate == alc5632->sysclk)
+ return i;
+ }
+ return -EINVAL;
+}
+
+/*
+ * Clock after PLL and dividers
+ */
+static int alc5632_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+
+ switch (freq) {
+ case 4096000:
+ case 8192000:
+ case 11289600:
+ case 12288000:
+ case 16384000:
+ case 16934400:
+ case 18432000:
+ case 22579200:
+ case 24576000:
+ alc5632->sysclk = freq;
+ return 0;
+ }
+ return -EINVAL;
+}
+
+static int alc5632_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ u16 iface = 0;
+
+ /* set master/slave audio interface */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ iface = ALC5632_DAI_SDP_MASTER_MODE;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ iface = ALC5632_DAI_SDP_SLAVE_MODE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* interface format */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ iface |= ALC5632_DAI_I2S_DF_I2S;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= ALC5632_DAI_I2S_DF_LEFT;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= ALC5632_DAI_I2S_DF_PCM_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ iface |= ALC5632_DAI_I2S_DF_PCM_B;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ iface |= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return snd_soc_write(codec, ALC5632_DAI_CONTROL, iface);
+}
+
+static int alc5632_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ int coeff, rate;
+ u16 iface;
+
+ iface = snd_soc_read(codec, ALC5632_DAI_CONTROL);
+ iface &= ~ALC5632_DAI_I2S_DL_MASK;
+
+ /* bit size */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ iface |= ALC5632_DAI_I2S_DL_16;
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface |= ALC5632_DAI_I2S_DL_20;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface |= ALC5632_DAI_I2S_DL_24;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* set iface & srate */
+ snd_soc_write(codec, ALC5632_DAI_CONTROL, iface);
+ rate = params_rate(params);
+ coeff = get_coeff(codec, rate);
+ if (coeff < 0)
+ return -EINVAL;
+
+ coeff = coeff_div[coeff].regvalue;
+ snd_soc_write(codec, ALC5632_DAC_CLK_CTRL1, coeff);
+
+ return 0;
+}
+
+static int alc5632_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u16 hp_mute = ALC5632_MISC_HP_DEPOP_MUTE_L
+ |ALC5632_MISC_HP_DEPOP_MUTE_R;
+ u16 mute_reg = snd_soc_read(codec, ALC5632_MISC_CTRL) & ~hp_mute;
+
+ if (mute)
+ mute_reg |= hp_mute;
+
+ return snd_soc_write(codec, ALC5632_MISC_CTRL, mute_reg);
+}
+
+#define ALC5632_ADD2_POWER_EN (ALC5632_PWR_ADD2_VREF)
+
+#define ALC5632_ADD3_POWER_EN (ALC5632_PWR_ADD3_MIC1_BOOST_AD)
+
+#define ALC5632_ADD1_POWER_EN \
+ (ALC5632_PWR_ADD1_DAC_REF \
+ | ALC5632_PWR_ADD1_SOFTGEN_EN \
+ | ALC5632_PWR_ADD1_HP_OUT_AMP \
+ | ALC5632_PWR_ADD1_HP_OUT_ENH_AMP \
+ | ALC5632_PWR_ADD1_MAIN_BIAS)
+
+static void enable_power_depop(struct snd_soc_codec *codec)
+{
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+ ALC5632_PWR_ADD1_SOFTGEN_EN,
+ ALC5632_PWR_ADD1_SOFTGEN_EN);
+
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3,
+ ALC5632_ADD3_POWER_EN,
+ ALC5632_ADD3_POWER_EN);
+
+ snd_soc_update_bits(codec, ALC5632_MISC_CTRL,
+ ALC5632_MISC_HP_DEPOP_MODE2_EN,
+ ALC5632_MISC_HP_DEPOP_MODE2_EN);
+
+ /* "normal" mode: 0 @ 26 */
+ /* set all PR0-7 mixers to 0 */
+ snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS,
+ ALC5632_PWR_DOWN_CTRL_STATUS_MASK,
+ 0);
+
+ msleep(500);
+
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+ ALC5632_ADD2_POWER_EN,
+ ALC5632_ADD2_POWER_EN);
+
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+ ALC5632_ADD1_POWER_EN,
+ ALC5632_ADD1_POWER_EN);
+
+ /* disable HP Depop2 */
+ snd_soc_update_bits(codec, ALC5632_MISC_CTRL,
+ ALC5632_MISC_HP_DEPOP_MODE2_EN,
+ 0);
+
+}
+
+static int alc5632_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ enable_power_depop(codec);
+ break;
+ case SND_SOC_BIAS_PREPARE:
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ /* everything off except vref/vmid, */
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+ ALC5632_PWR_MANAG_ADD1_MASK,
+ ALC5632_PWR_ADD1_MAIN_BIAS);
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+ ALC5632_PWR_MANAG_ADD2_MASK,
+ ALC5632_PWR_ADD2_VREF);
+ /* "normal" mode: 0 @ 26 */
+ snd_soc_update_bits(codec, ALC5632_PWR_DOWN_CTRL_STATUS,
+ ALC5632_PWR_DOWN_CTRL_STATUS_MASK,
+ 0xffff ^ (ALC5632_PWR_VREF_PR3
+ | ALC5632_PWR_VREF_PR2));
+ break;
+ case SND_SOC_BIAS_OFF:
+ /* everything off, dac mute, inactive */
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD2,
+ ALC5632_PWR_MANAG_ADD2_MASK, 0);
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD3,
+ ALC5632_PWR_MANAG_ADD3_MASK, 0);
+ snd_soc_update_bits(codec, ALC5632_PWR_MANAG_ADD1,
+ ALC5632_PWR_MANAG_ADD1_MASK, 0);
+ break;
+ }
+ codec->dapm.bias_level = level;
+ return 0;
+}
+
+#define ALC5632_FORMATS (SNDRV_PCM_FMTBIT_S16_LE \
+ | SNDRV_PCM_FMTBIT_S24_LE \
+ | SNDRV_PCM_FMTBIT_S32_LE)
+
+static const struct snd_soc_dai_ops alc5632_dai_ops = {
+ .hw_params = alc5632_pcm_hw_params,
+ .digital_mute = alc5632_mute,
+ .set_fmt = alc5632_set_dai_fmt,
+ .set_sysclk = alc5632_set_dai_sysclk,
+ .set_pll = alc5632_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver alc5632_dai = {
+ .name = "alc5632-hifi",
+ .playback = {
+ .stream_name = "HiFi Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = ALC5632_FORMATS,},
+ .capture = {
+ .stream_name = "HiFi Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rate_min = 8000,
+ .rate_max = 48000,
+ .rates = SNDRV_PCM_RATE_8000_48000,
+ .formats = ALC5632_FORMATS,},
+
+ .ops = &alc5632_dai_ops,
+ .symmetric_rates = 1,
+};
+
+#ifdef CONFIG_PM
+static int alc5632_suspend(struct snd_soc_codec *codec)
+{
+ alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int alc5632_resume(struct snd_soc_codec *codec)
+{
+ struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+
+ regcache_sync(alc5632->regmap);
+
+ alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+}
+#else
+#define alc5632_suspend NULL
+#define alc5632_resume NULL
+#endif
+
+static int alc5632_probe(struct snd_soc_codec *codec)
+{
+ struct alc5632_priv *alc5632 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ codec->control_data = alc5632->regmap;
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ /* power on device */
+ alc5632_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ switch (alc5632->id) {
+ case 0x5c:
+ snd_soc_add_codec_controls(codec, alc5632_vol_snd_controls,
+ ARRAY_SIZE(alc5632_vol_snd_controls));
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return ret;
+}
+
+/* power down chip */
+static int alc5632_remove(struct snd_soc_codec *codec)
+{
+ alc5632_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_device_alc5632 = {
+ .probe = alc5632_probe,
+ .remove = alc5632_remove,
+ .suspend = alc5632_suspend,
+ .resume = alc5632_resume,
+ .set_bias_level = alc5632_set_bias_level,
+ .controls = alc5632_snd_controls,
+ .num_controls = ARRAY_SIZE(alc5632_snd_controls),
+ .dapm_widgets = alc5632_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(alc5632_dapm_widgets),
+ .dapm_routes = alc5632_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(alc5632_dapm_routes),
+};
+
+static struct regmap_config alc5632_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = ALC5632_MAX_REGISTER,
+ .reg_defaults = alc5632_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(alc5632_reg_defaults),
+ .volatile_reg = alc5632_volatile_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+/*
+ * alc5632 2 wire address is determined by A1 pin
+ * state during powerup.
+ * low = 0x1a
+ * high = 0x1b
+ */
+static __devinit int alc5632_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct alc5632_priv *alc5632;
+ int ret, ret1, ret2;
+ unsigned int vid1, vid2;
+
+ alc5632 = devm_kzalloc(&client->dev,
+ sizeof(struct alc5632_priv), GFP_KERNEL);
+ if (alc5632 == NULL)
+ return -ENOMEM;
+
+ i2c_set_clientdata(client, alc5632);
+
+ alc5632->regmap = regmap_init_i2c(client, &alc5632_regmap);
+ if (IS_ERR(alc5632->regmap)) {
+ ret = PTR_ERR(alc5632->regmap);
+ dev_err(&client->dev, "regmap_init() failed: %d\n", ret);
+ return ret;
+ }
+
+ ret1 = regmap_read(alc5632->regmap, ALC5632_VENDOR_ID1, &vid1);
+ ret2 = regmap_read(alc5632->regmap, ALC5632_VENDOR_ID2, &vid2);
+ if (ret1 != 0 || ret2 != 0) {
+ dev_err(&client->dev,
+ "Failed to read chip ID: ret1=%d, ret2=%d\n", ret1, ret2);
+ regmap_exit(alc5632->regmap);
+ return -EIO;
+ }
+
+ vid2 >>= 8;
+
+ if ((vid1 != 0x10EC) || (vid2 != id->driver_data)) {
+ dev_err(&client->dev,
+ "Device is not a ALC5632: VID1=0x%x, VID2=0x%x\n", vid1, vid2);
+ regmap_exit(alc5632->regmap);
+ return -EINVAL;
+ }
+
+ ret = alc5632_reset(alc5632->regmap);
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to issue reset\n");
+ regmap_exit(alc5632->regmap);
+ return ret;
+ }
+
+ alc5632->id = vid2;
+ switch (alc5632->id) {
+ case 0x5c:
+ alc5632_dai.name = "alc5632-hifi";
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ ret = snd_soc_register_codec(&client->dev,
+ &soc_codec_device_alc5632, &alc5632_dai, 1);
+
+ if (ret < 0) {
+ dev_err(&client->dev, "Failed to register codec: %d\n", ret);
+ regmap_exit(alc5632->regmap);
+ return ret;
+ }
+
+ return ret;
+}
+
+static __devexit int alc5632_i2c_remove(struct i2c_client *client)
+{
+ struct alc5632_priv *alc5632 = i2c_get_clientdata(client);
+ snd_soc_unregister_codec(&client->dev);
+ regmap_exit(alc5632->regmap);
+ return 0;
+}
+
+static const struct i2c_device_id alc5632_i2c_table[] = {
+ {"alc5632", 0x5c},
+ {}
+};
+MODULE_DEVICE_TABLE(i2c, alc5632_i2c_table);
+
+/* i2c codec control layer */
+static struct i2c_driver alc5632_i2c_driver = {
+ .driver = {
+ .name = "alc5632",
+ .owner = THIS_MODULE,
+ },
+ .probe = alc5632_i2c_probe,
+ .remove = __devexit_p(alc5632_i2c_remove),
+ .id_table = alc5632_i2c_table,
+};
+
+static int __init alc5632_modinit(void)
+{
+ int ret;
+
+ ret = i2c_add_driver(&alc5632_i2c_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "%s: can't add i2c driver", __func__);
+ return ret;
+ }
+
+ return ret;
+}
+module_init(alc5632_modinit);
+
+static void __exit alc5632_modexit(void)
+{
+ i2c_del_driver(&alc5632_i2c_driver);
+}
+module_exit(alc5632_modexit);
+
+MODULE_DESCRIPTION("ASoC ALC5632 driver");
+MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/alc5632.h b/sound/soc/codecs/alc5632.h
new file mode 100644
index 000000000000..1b5bda594ea3
--- /dev/null
+++ b/sound/soc/codecs/alc5632.h
@@ -0,0 +1,252 @@
+/*
+* alc5632.h -- ALC5632 ALSA SoC Audio Codec
+*
+* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+*
+* Authors: Leon Romanovsky <leon@leon.nu>
+* Andrey Danin <danindrey@mail.ru>
+* Ilya Petrov <ilya.muromec@gmail.com>
+* Marc Dietrich <marvin24@gmx.de>
+*
+* Based on alc5623.h by Arnaud Patard
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#ifndef _ALC5632_H
+#define _ALC5632_H
+
+#define ALC5632_RESET 0x00
+/* speaker output vol 2 2 */
+/* line output vol 4 2 */
+/* HP output vol 4 0 4 */
+#define ALC5632_SPK_OUT_VOL 0x02 /* spe out vol */
+#define ALC5632_SPK_OUT_VOL_STEP 1.5
+#define ALC5632_HP_OUT_VOL 0x04 /* hp out vol */
+#define ALC5632_AUX_OUT_VOL 0x06 /* aux out vol */
+#define ALC5632_PHONE_IN_VOL 0x08 /* phone in vol */
+#define ALC5632_LINE_IN_VOL 0x0A /* line in vol */
+#define ALC5632_STEREO_DAC_IN_VOL 0x0C /* stereo dac in vol */
+#define ALC5632_MIC_VOL 0x0E /* mic in vol */
+/* stero dac/mic routing */
+#define ALC5632_MIC_ROUTING_CTRL 0x10
+#define ALC5632_MIC_ROUTE_MONOMIX (1 << 0)
+#define ALC5632_MIC_ROUTE_SPK (1 << 1)
+#define ALC5632_MIC_ROUTE_HP (1 << 2)
+
+#define ALC5632_ADC_REC_GAIN 0x12 /* rec gain */
+#define ALC5632_ADC_REC_GAIN_RANGE 0x1F1F
+#define ALC5632_ADC_REC_GAIN_BASE (-16.5)
+#define ALC5632_ADC_REC_GAIN_STEP 1.5
+
+#define ALC5632_ADC_REC_MIXER 0x14 /* mixer control */
+#define ALC5632_ADC_REC_MIC1 (1 << 6)
+#define ALC5632_ADC_REC_MIC2 (1 << 5)
+#define ALC5632_ADC_REC_LINE_IN (1 << 4)
+#define ALC5632_ADC_REC_AUX (1 << 3)
+#define ALC5632_ADC_REC_HP (1 << 2)
+#define ALC5632_ADC_REC_SPK (1 << 1)
+#define ALC5632_ADC_REC_MONOMIX (1 << 0)
+
+#define ALC5632_VOICE_DAC_VOL 0x18 /* voice dac vol */
+#define ALC5632_I2S_OUT_CTL 0x1A /* undocumented reg. found in path scheme */
+/* ALC5632_OUTPUT_MIXER_CTRL : */
+/* same remark as for reg 2 line vs speaker */
+#define ALC5632_OUTPUT_MIXER_CTRL 0x1C /* out mix ctrl */
+#define ALC5632_OUTPUT_MIXER_RP (1 << 14)
+#define ALC5632_OUTPUT_MIXER_WEEK (1 << 12)
+#define ALC5632_OUTPUT_MIXER_HP (1 << 10)
+#define ALC5632_OUTPUT_MIXER_AUX_SPK (2 << 6)
+#define ALC5632_OUTPUT_MIXER_AUX_HP_LR (1 << 6)
+#define ALC5632_OUTPUT_MIXER_HP_R (1 << 8)
+#define ALC5632_OUTPUT_MIXER_HP_L (1 << 9)
+
+#define ALC5632_MIC_CTRL 0x22 /* mic phone ctrl */
+#define ALC5632_MIC_BOOST_BYPASS 0
+#define ALC5632_MIC_BOOST_20DB 1
+#define ALC5632_MIC_BOOST_30DB 2
+#define ALC5632_MIC_BOOST_40DB 3
+
+#define ALC5632_DIGI_BOOST_CTRL 0x24 /* digi mic / bost ctl */
+#define ALC5632_MIC_BOOST_RANGE 7
+#define ALC5632_MIC_BOOST_STEP 6
+#define ALC5632_PWR_DOWN_CTRL_STATUS 0x26
+#define ALC5632_PWR_DOWN_CTRL_STATUS_MASK 0xEF00
+#define ALC5632_PWR_VREF_PR3 (1 << 11)
+#define ALC5632_PWR_VREF_PR2 (1 << 10)
+#define ALC5632_PWR_VREF_STATUS (1 << 3)
+#define ALC5632_PWR_AMIX_STATUS (1 << 2)
+#define ALC5632_PWR_DAC_STATUS (1 << 1)
+#define ALC5632_PWR_ADC_STATUS (1 << 0)
+/* stereo/voice DAC / stereo adc func ctrl */
+#define ALC5632_DAC_FUNC_SELECT 0x2E
+
+/* Main serial data port ctrl (i2s) */
+#define ALC5632_DAI_CONTROL 0x34
+
+#define ALC5632_DAI_SDP_MASTER_MODE (0 << 15)
+#define ALC5632_DAI_SDP_SLAVE_MODE (1 << 15)
+#define ALC5632_DAI_SADLRCK_MODE (1 << 14)
+/* 0:voice, 1:main */
+#define ALC5632_DAI_MAIN_I2S_SYSCLK_SEL (1 << 8)
+#define ALC5632_DAI_MAIN_I2S_BCLK_POL_CTRL (1 << 7)
+/* 0:normal, 1:invert */
+#define ALC5632_DAI_MAIN_I2S_LRCK_INV (1 << 6)
+#define ALC5632_DAI_I2S_DL_MASK (3 << 2)
+#define ALC5632_DAI_I2S_DL_8 (3 << 2)
+#define ALC5632_DAI_I2S_DL_24 (2 << 2)
+#define ALC5632_DAI_I2S_DL_20 (1 << 2)
+#define ALC5632_DAI_I2S_DL_16 (0 << 2)
+#define ALC5632_DAI_I2S_DF_MASK (3 << 0)
+#define ALC5632_DAI_I2S_DF_PCM_B (3 << 0)
+#define ALC5632_DAI_I2S_DF_PCM_A (2 << 0)
+#define ALC5632_DAI_I2S_DF_LEFT (1 << 0)
+#define ALC5632_DAI_I2S_DF_I2S (0 << 0)
+/* extend serial data port control (VoDAC_i2c/pcm) */
+#define ALC5632_DAI_CONTROL2 0x36
+/* 0:gpio func, 1:voice pcm */
+#define ALC5632_DAI_VOICE_PCM_ENABLE (1 << 15)
+/* 0:master, 1:slave */
+#define ALC5632_DAI_VOICE_MODE_SEL (1 << 14)
+/* 0:disable, 1:enable */
+#define ALC5632_DAI_HPF_CLK_CTRL (1 << 13)
+/* 0:main, 1:voice */
+#define ALC5632_DAI_VOICE_I2S_SYSCLK_SEL (1 << 8)
+/* 0:normal, 1:invert */
+#define ALC5632_DAI_VOICE_VBCLK_SYSCLK_SEL (1 << 7)
+/* 0:normal, 1:invert */
+#define ALC5632_DAI_VOICE_I2S_LR_INV (1 << 6)
+#define ALC5632_DAI_VOICE_DL_MASK (3 << 2)
+#define ALC5632_DAI_VOICE_DL_16 (0 << 2)
+#define ALC5632_DAI_VOICE_DL_20 (1 << 2)
+#define ALC5632_DAI_VOICE_DL_24 (2 << 2)
+#define ALC5632_DAI_VOICE_DL_8 (3 << 2)
+#define ALC5632_DAI_VOICE_DF_MASK (3 << 0)
+#define ALC5632_DAI_VOICE_DF_I2S (0 << 0)
+#define ALC5632_DAI_VOICE_DF_LEFT (1 << 0)
+#define ALC5632_DAI_VOICE_DF_PCM_A (2 << 0)
+#define ALC5632_DAI_VOICE_DF_PCM_B (3 << 0)
+
+#define ALC5632_PWR_MANAG_ADD1 0x3A
+#define ALC5632_PWR_MANAG_ADD1_MASK 0xEFFF
+#define ALC5632_PWR_ADD1_DAC_L_EN (1 << 15)
+#define ALC5632_PWR_ADD1_DAC_R_EN (1 << 14)
+#define ALC5632_PWR_ADD1_ZERO_CROSS (1 << 13)
+#define ALC5632_PWR_ADD1_MAIN_I2S_EN (1 << 11)
+#define ALC5632_PWR_ADD1_SPK_AMP_EN (1 << 10)
+#define ALC5632_PWR_ADD1_HP_OUT_AMP (1 << 9)
+#define ALC5632_PWR_ADD1_HP_OUT_ENH_AMP (1 << 8)
+#define ALC5632_PWR_ADD1_VOICE_DAC_MIX (1 << 7)
+#define ALC5632_PWR_ADD1_SOFTGEN_EN (1 << 6)
+#define ALC5632_PWR_ADD1_MIC1_SHORT_CURR (1 << 5)
+#define ALC5632_PWR_ADD1_MIC2_SHORT_CURR (1 << 4)
+#define ALC5632_PWR_ADD1_MIC1_EN (1 << 3)
+#define ALC5632_PWR_ADD1_MIC2_EN (1 << 2)
+#define ALC5632_PWR_ADD1_MAIN_BIAS (1 << 1)
+#define ALC5632_PWR_ADD1_DAC_REF (1 << 0)
+
+#define ALC5632_PWR_MANAG_ADD2 0x3C
+#define ALC5632_PWR_MANAG_ADD2_MASK 0x7FFF
+#define ALC5632_PWR_ADD2_PLL1 (1 << 15)
+#define ALC5632_PWR_ADD2_PLL2 (1 << 14)
+#define ALC5632_PWR_ADD2_VREF (1 << 13)
+#define ALC5632_PWR_ADD2_OVT_DET (1 << 12)
+#define ALC5632_PWR_ADD2_VOICE_DAC (1 << 10)
+#define ALC5632_PWR_ADD2_L_DAC_CLK (1 << 9)
+#define ALC5632_PWR_ADD2_R_DAC_CLK (1 << 8)
+#define ALC5632_PWR_ADD2_L_ADC_CLK_GAIN (1 << 7)
+#define ALC5632_PWR_ADD2_R_ADC_CLK_GAIN (1 << 6)
+#define ALC5632_PWR_ADD2_L_HP_MIXER (1 << 5)
+#define ALC5632_PWR_ADD2_R_HP_MIXER (1 << 4)
+#define ALC5632_PWR_ADD2_SPK_MIXER (1 << 3)
+#define ALC5632_PWR_ADD2_MONO_MIXER (1 << 2)
+#define ALC5632_PWR_ADD2_L_ADC_REC_MIXER (1 << 1)
+#define ALC5632_PWR_ADD2_R_ADC_REC_MIXER (1 << 0)
+
+#define ALC5632_PWR_MANAG_ADD3 0x3E
+#define ALC5632_PWR_MANAG_ADD3_MASK 0x7CFF
+#define ALC5632_PWR_ADD3_AUXOUT_VOL (1 << 14)
+#define ALC5632_PWR_ADD3_SPK_L_OUT (1 << 13)
+#define ALC5632_PWR_ADD3_SPK_R_OUT (1 << 12)
+#define ALC5632_PWR_ADD3_HP_L_OUT_VOL (1 << 11)
+#define ALC5632_PWR_ADD3_HP_R_OUT_VOL (1 << 10)
+#define ALC5632_PWR_ADD3_LINEIN_L_VOL (1 << 7)
+#define ALC5632_PWR_ADD3_LINEIN_R_VOL (1 << 6)
+#define ALC5632_PWR_ADD3_AUXIN_VOL (1 << 5)
+#define ALC5632_PWR_ADD3_AUXIN_MIX (1 << 4)
+#define ALC5632_PWR_ADD3_MIC1_VOL (1 << 3)
+#define ALC5632_PWR_ADD3_MIC2_VOL (1 << 2)
+#define ALC5632_PWR_ADD3_MIC1_BOOST_AD (1 << 1)
+#define ALC5632_PWR_ADD3_MIC2_BOOST_AD (1 << 0)
+
+#define ALC5632_GPCR1 0x40
+#define ALC5632_GPCR1_CLK_SYS_SRC_SEL_PLL1 (1 << 15)
+#define ALC5632_GPCR1_CLK_SYS_SRC_SEL_MCLK (0 << 15)
+#define ALC5632_GPCR1_DAC_HI_FLT_EN (1 << 10)
+#define ALC5632_GPCR1_SPK_AMP_CTRL (7 << 1)
+#define ALC5632_GPCR1_VDD_100 (5 << 1)
+#define ALC5632_GPCR1_VDD_125 (4 << 1)
+#define ALC5632_GPCR1_VDD_150 (3 << 1)
+#define ALC5632_GPCR1_VDD_175 (2 << 1)
+#define ALC5632_GPCR1_VDD_200 (1 << 1)
+#define ALC5632_GPCR1_VDD_225 (0 << 1)
+
+#define ALC5632_GPCR2 0x42
+#define ALC5632_GPCR2_PLL1_SOUR_SEL (3 << 12)
+#define ALC5632_PLL_FR_MCLK (0 << 12)
+#define ALC5632_PLL_FR_BCLK (2 << 12)
+#define ALC5632_PLL_FR_VBCLK (3 << 12)
+#define ALC5632_GPCR2_CLK_PLL_PRE_DIV1 (0 << 0)
+
+#define ALC5632_PLL1_CTRL 0x44
+#define ALC5632_PLL1_CTRL_N_VAL(n) (((n) & 0x0f) << 8)
+#define ALC5632_PLL1_M_BYPASS (1 << 7)
+#define ALC5632_PLL1_CTRL_K_VAL(k) (((k) & 0x07) << 4)
+#define ALC5632_PLL1_CTRL_M_VAL(m) (((m) & 0x0f) << 0)
+
+#define ALC5632_PLL2_CTRL 0x46
+#define ALC5632_PLL2_EN (1 << 15)
+#define ALC5632_PLL2_RATIO (0 << 15)
+
+#define ALC5632_GPIO_PIN_CONFIG 0x4C
+#define ALC5632_GPIO_PIN_POLARITY 0x4E
+#define ALC5632_GPIO_PIN_STICKY 0x50
+#define ALC5632_GPIO_PIN_WAKEUP 0x52
+#define ALC5632_GPIO_PIN_STATUS 0x54
+#define ALC5632_GPIO_PIN_SHARING 0x56
+#define ALC5632_OVER_CURR_STATUS 0x58
+#define ALC5632_SOFTVOL_CTRL 0x5A
+#define ALC5632_GPIO_OUPUT_PIN_CTRL 0x5C
+
+#define ALC5632_MISC_CTRL 0x5E
+#define ALC5632_MISC_DISABLE_FAST_VREG (1 << 15)
+#define ALC5632_MISC_AVC_TRGT_SEL (3 << 12)
+#define ALC5632_MISC_AVC_TRGT_RIGHT (1 << 12)
+#define ALC5632_MISC_AVC_TRGT_LEFT (2 << 12)
+#define ALC5632_MISC_AVC_TRGT_BOTH (3 << 12)
+#define ALC5632_MISC_HP_DEPOP_MODE1_EN (1 << 9)
+#define ALC5632_MISC_HP_DEPOP_MODE2_EN (1 << 8)
+#define ALC5632_MISC_HP_DEPOP_MUTE_L (1 << 7)
+#define ALC5632_MISC_HP_DEPOP_MUTE_R (1 << 6)
+#define ALC5632_MISC_HP_DEPOP_MUTE (1 << 5)
+#define ALC5632_MISC_GPIO_WAKEUP_CTRL (1 << 1)
+#define ALC5632_MISC_IRQOUT_INV_CTRL (1 << 0)
+
+#define ALC5632_DAC_CLK_CTRL1 0x60
+#define ALC5632_DAC_CLK_CTRL2 0x62
+#define ALC5632_DAC_CLK_CTRL2_DIV1_2 (1 << 0)
+#define ALC5632_VOICE_DAC_PCM_CLK_CTRL1 0x64
+#define ALC5632_PSEUDO_SPATIAL_CTRL 0x68
+#define ALC5632_HID_CTRL_INDEX 0x6A
+#define ALC5632_HID_CTRL_DATA 0x6C
+#define ALC5632_EQ_CTRL 0x6E
+
+/* undocumented */
+#define ALC5632_VENDOR_ID1 0x7C
+#define ALC5632_VENDOR_ID2 0x7E
+
+#define ALC5632_MAX_REGISTER 0x7E
+
+#endif
diff --git a/sound/soc/codecs/cq93vc.c b/sound/soc/codecs/cq93vc.c
index 46dbfd067f79..064cd6a93516 100644
--- a/sound/soc/codecs/cq93vc.c
+++ b/sound/soc/codecs/cq93vc.c
@@ -38,8 +38,6 @@
#include <sound/soc.h>
#include <sound/initval.h>
-#include <mach/dm365.h>
-
static inline unsigned int cq93vc_read(struct snd_soc_codec *codec,
unsigned int reg)
{
@@ -122,7 +120,7 @@ static int cq93vc_set_bias_level(struct snd_soc_codec *codec,
#define CQ93VC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000)
#define CQ93VC_FORMATS (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE)
-static struct snd_soc_dai_ops cq93vc_dai_ops = {
+static const struct snd_soc_dai_ops cq93vc_dai_ops = {
.digital_mute = cq93vc_mute,
.set_sysclk = cq93vc_set_dai_sysclk,
};
@@ -159,7 +157,7 @@ static int cq93vc_probe(struct snd_soc_codec *codec)
codec->control_data = davinci_vc;
/* Set controls */
- snd_soc_add_controls(codec, cq93vc_snd_controls,
+ snd_soc_add_codec_controls(codec, cq93vc_snd_controls,
ARRAY_SIZE(cq93vc_snd_controls));
/* Off, with power on */
@@ -206,17 +204,7 @@ static struct platform_driver cq93vc_codec_driver = {
.remove = __devexit_p(cq93vc_platform_remove),
};
-static int __init cq93vc_init(void)
-{
- return platform_driver_register(&cq93vc_codec_driver);
-}
-module_init(cq93vc_init);
-
-static void __exit cq93vc_exit(void)
-{
- platform_driver_unregister(&cq93vc_codec_driver);
-}
-module_exit(cq93vc_exit);
+module_platform_driver(cq93vc_codec_driver);
MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC CQ0093 Voice Codec Driver");
MODULE_AUTHOR("Miguel Aguilar");
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 6cc8678f49f3..1d672f528662 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -22,7 +22,6 @@
*/
#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/soc.h>
@@ -128,7 +127,6 @@ static const char *supply_names[] = {
/* Private data for the CS4270 */
struct cs4270_private {
enum snd_soc_control_type control_type;
- void *control_data;
unsigned int mclk; /* Input frequency of the MCLK pin */
unsigned int mode; /* The mode (I2S or left-justified) */
unsigned int slave_mode;
@@ -262,7 +260,6 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
- int ret = 0;
/* set DAI format */
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
@@ -272,7 +269,7 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
break;
default:
dev_err(codec->dev, "invalid dai format\n");
- ret = -EINVAL;
+ return -EINVAL;
}
/* set master/slave audio interface */
@@ -285,10 +282,11 @@ static int cs4270_set_dai_fmt(struct snd_soc_dai *codec_dai,
break;
default:
/* all other modes are unsupported by the hardware */
- ret = -EINVAL;
+ dev_err(codec->dev, "Unknown master/slave configuration\n");
+ return -EINVAL;
}
- return ret;
+ return 0;
}
/**
@@ -448,7 +446,7 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = {
snd_soc_get_volsw, cs4270_soc_put_mute),
};
-static struct snd_soc_dai_ops cs4270_dai_ops = {
+static const struct snd_soc_dai_ops cs4270_dai_ops = {
.hw_params = cs4270_hw_params,
.set_sysclk = cs4270_set_dai_sysclk,
.set_fmt = cs4270_set_dai_fmt,
@@ -490,8 +488,6 @@ static int cs4270_probe(struct snd_soc_codec *codec)
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int i, ret;
- codec->control_data = cs4270->control_data;
-
/* Tell ASoC what kind of I/O to use to read the registers. ASoC will
* then do the I2C transactions itself.
*/
@@ -525,7 +521,7 @@ static int cs4270_probe(struct snd_soc_codec *codec)
}
/* Add the non-DAPM controls */
- ret = snd_soc_add_controls(codec, cs4270_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, cs4270_snd_controls,
ARRAY_SIZE(cs4270_snd_controls));
if (ret < 0) {
dev_err(codec->dev, "failed to add controls\n");
@@ -582,7 +578,7 @@ static int cs4270_remove(struct snd_soc_codec *codec)
* and all registers are written back to the hardware when resuming.
*/
-static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+static int cs4270_soc_suspend(struct snd_soc_codec *codec)
{
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
int reg, ret;
@@ -604,7 +600,6 @@ static int cs4270_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
static int cs4270_soc_resume(struct snd_soc_codec *codec)
{
struct cs4270_private *cs4270 = snd_soc_codec_get_drvdata(codec);
- struct i2c_client *i2c_client = codec->control_data;
int reg;
regulator_bulk_enable(ARRAY_SIZE(cs4270->supplies),
@@ -615,14 +610,7 @@ static int cs4270_soc_resume(struct snd_soc_codec *codec)
ndelay(500);
/* first restore the entire register cache ... */
- for (reg = CS4270_FIRSTREG; reg <= CS4270_LASTREG; reg++) {
- u8 val = snd_soc_read(codec, reg);
-
- if (i2c_smbus_write_byte_data(i2c_client, reg, val)) {
- dev_err(codec->dev, "i2c write failed\n");
- return -EIO;
- }
- }
+ snd_soc_cache_sync(codec);
/* ... then disable the power-down bits */
reg = snd_soc_read(codec, CS4270_PWRCTL);
@@ -683,20 +671,18 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
i2c_client->addr);
dev_info(&i2c_client->dev, "hardware revision %X\n", ret & 0xF);
- cs4270 = kzalloc(sizeof(struct cs4270_private), GFP_KERNEL);
+ cs4270 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs4270_private),
+ GFP_KERNEL);
if (!cs4270) {
dev_err(&i2c_client->dev, "could not allocate codec\n");
return -ENOMEM;
}
i2c_set_clientdata(i2c_client, cs4270);
- cs4270->control_data = i2c_client;
cs4270->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c_client->dev,
&soc_codec_device_cs4270, &cs4270_dai, 1);
- if (ret < 0)
- kfree(cs4270);
return ret;
}
@@ -709,7 +695,6 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client,
static int cs4270_i2c_remove(struct i2c_client *i2c_client)
{
snd_soc_unregister_codec(&i2c_client->dev);
- kfree(i2c_get_clientdata(i2c_client));
return 0;
}
@@ -730,7 +715,7 @@ MODULE_DEVICE_TABLE(i2c, cs4270_id);
*/
static struct i2c_driver cs4270_i2c_driver = {
.driver = {
- .name = "cs4270-codec",
+ .name = "cs4270",
.owner = THIS_MODULE,
},
.id_table = cs4270_id,
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index 083aab96ca80..bf7141280a74 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -156,7 +156,6 @@ static const u8 cs4271_dflt_reg[CS4271_NR_REGS] = {
struct cs4271_private {
/* SND_SOC_I2C or SND_SOC_SPI */
enum snd_soc_control_type bus_type;
- void *control_data;
unsigned int mclk;
bool master;
bool deemph;
@@ -403,7 +402,7 @@ static const struct snd_kcontrol_new cs4271_snd_controls[] = {
7, 1, 1),
};
-static struct snd_soc_dai_ops cs4271_dai_ops = {
+static const struct snd_soc_dai_ops cs4271_dai_ops = {
.hw_params = cs4271_hw_params,
.set_sysclk = cs4271_set_dai_sysclk,
.set_fmt = cs4271_set_dai_fmt,
@@ -431,11 +430,12 @@ static struct snd_soc_dai_driver cs4271_dai = {
};
#ifdef CONFIG_PM
-static int cs4271_soc_suspend(struct snd_soc_codec *codec, pm_message_t mesg)
+static int cs4271_soc_suspend(struct snd_soc_codec *codec)
{
int ret;
/* Set power-down bit */
- ret = snd_soc_update_bits(codec, CS4271_MODE2, 0, CS4271_MODE2_PDN);
+ ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN,
+ CS4271_MODE2_PDN);
if (ret < 0)
return ret;
return 0;
@@ -466,8 +466,6 @@ static int cs4271_probe(struct snd_soc_codec *codec)
int ret;
int gpio_nreset = -EINVAL;
- codec->control_data = cs4271->control_data;
-
if (cs4271plat && gpio_is_valid(cs4271plat->gpio_nreset))
gpio_nreset = cs4271plat->gpio_nreset;
@@ -504,8 +502,9 @@ static int cs4271_probe(struct snd_soc_codec *codec)
return ret;
}
- ret = snd_soc_update_bits(codec, CS4271_MODE2, 0,
- CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
+ ret = snd_soc_update_bits(codec, CS4271_MODE2,
+ CS4271_MODE2_PDN | CS4271_MODE2_CPEN,
+ CS4271_MODE2_PDN | CS4271_MODE2_CPEN);
if (ret < 0)
return ret;
ret = snd_soc_update_bits(codec, CS4271_MODE2, CS4271_MODE2_PDN, 0);
@@ -514,7 +513,7 @@ static int cs4271_probe(struct snd_soc_codec *codec)
/* Power-up sequence requires 85 uS */
udelay(85);
- return snd_soc_add_controls(codec, cs4271_snd_controls,
+ return snd_soc_add_codec_controls(codec, cs4271_snd_controls,
ARRAY_SIZE(cs4271_snd_controls));
}
@@ -555,7 +554,6 @@ static int __devinit cs4271_spi_probe(struct spi_device *spi)
return -ENOMEM;
spi_set_drvdata(spi, cs4271);
- cs4271->control_data = spi;
cs4271->bus_type = SND_SOC_SPI;
return snd_soc_register_codec(&spi->dev, &soc_codec_dev_cs4271,
@@ -595,7 +593,6 @@ static int __devinit cs4271_i2c_probe(struct i2c_client *client,
return -ENOMEM;
i2c_set_clientdata(client, cs4271);
- cs4271->control_data = client;
cs4271->bus_type = SND_SOC_I2C;
return snd_soc_register_codec(&client->dev, &soc_codec_dev_cs4271,
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c
index 8fb7070108dd..a8bf588e8740 100644
--- a/sound/soc/codecs/cs42l51.c
+++ b/sound/soc/codecs/cs42l51.c
@@ -22,7 +22,6 @@
*/
#include <linux/module.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/soc.h>
@@ -42,7 +41,6 @@ enum master_slave_mode {
struct cs42l51_private {
enum snd_soc_control_type control_type;
- void *control_data;
unsigned int mclk;
unsigned int audio_mode; /* The mode (I2S or left-justified) */
enum master_slave_mode func;
@@ -57,7 +55,7 @@ struct cs42l51_private {
static int cs42l51_fill_cache(struct snd_soc_codec *codec)
{
u8 *cache = codec->reg_cache + 1;
- struct i2c_client *i2c_client = codec->control_data;
+ struct i2c_client *i2c_client = to_i2c_client(codec->dev);
s32 length;
length = i2c_smbus_read_i2c_block_data(i2c_client,
@@ -176,21 +174,18 @@ static const struct snd_kcontrol_new cs42l51_snd_controls[] = {
static int cs42l51_pdn_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- unsigned long value;
-
- value = snd_soc_read(w->codec, CS42L51_POWER_CTL1);
- value &= ~CS42L51_POWER_CTL1_PDN;
-
switch (event) {
case SND_SOC_DAPM_PRE_PMD:
- value |= CS42L51_POWER_CTL1_PDN;
+ snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
+ CS42L51_POWER_CTL1_PDN,
+ CS42L51_POWER_CTL1_PDN);
break;
default:
case SND_SOC_DAPM_POST_PMD:
+ snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
+ CS42L51_POWER_CTL1_PDN, 0);
break;
}
- snd_soc_update_bits(w->codec, CS42L51_POWER_CTL1,
- CS42L51_POWER_CTL1_PDN, value);
return 0;
}
@@ -289,7 +284,6 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
- int ret = 0;
switch (format & SND_SOC_DAIFMT_FORMAT_MASK) {
case SND_SOC_DAIFMT_I2S:
@@ -299,7 +293,7 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
break;
default:
dev_err(codec->dev, "invalid DAI format\n");
- ret = -EINVAL;
+ return -EINVAL;
}
switch (format & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -310,11 +304,11 @@ static int cs42l51_set_dai_fmt(struct snd_soc_dai *codec_dai,
cs42l51->func = MODE_SLAVE_AUTO;
break;
default:
- ret = -EINVAL;
- break;
+ dev_err(codec->dev, "Unknown master/slave configuration\n");
+ return -EINVAL;
}
- return ret;
+ return 0;
}
struct cs42l51_ratios {
@@ -488,7 +482,7 @@ static int cs42l51_dai_mute(struct snd_soc_dai *dai, int mute)
return snd_soc_write(codec, CS42L51_DAC_OUT_CTL, reg);
}
-static struct snd_soc_dai_ops cs42l51_dai_ops = {
+static const struct snd_soc_dai_ops cs42l51_dai_ops = {
.hw_params = cs42l51_hw_params,
.set_sysclk = cs42l51_set_dai_sysclk,
.set_fmt = cs42l51_set_dai_fmt,
@@ -517,11 +511,8 @@ static struct snd_soc_dai_driver cs42l51_dai = {
static int cs42l51_probe(struct snd_soc_codec *codec)
{
struct cs42l51_private *cs42l51 = snd_soc_codec_get_drvdata(codec);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret, reg;
- codec->control_data = cs42l51->control_data;
-
ret = cs42l51_fill_cache(codec);
if (ret < 0) {
dev_err(codec->dev, "failed to fill register cache\n");
@@ -547,20 +538,20 @@ static int cs42l51_probe(struct snd_soc_codec *codec)
if (ret < 0)
return ret;
- snd_soc_add_controls(codec, cs42l51_snd_controls,
- ARRAY_SIZE(cs42l51_snd_controls));
- snd_soc_dapm_new_controls(dapm, cs42l51_dapm_widgets,
- ARRAY_SIZE(cs42l51_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, cs42l51_routes,
- ARRAY_SIZE(cs42l51_routes));
-
return 0;
}
static struct snd_soc_codec_driver soc_codec_device_cs42l51 = {
- .probe = cs42l51_probe,
- .reg_cache_size = CS42L51_NUMREGS,
+ .probe = cs42l51_probe,
+ .reg_cache_size = CS42L51_NUMREGS + 1,
.reg_word_size = sizeof(u8),
+
+ .controls = cs42l51_snd_controls,
+ .num_controls = ARRAY_SIZE(cs42l51_snd_controls),
+ .dapm_widgets = cs42l51_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(cs42l51_dapm_widgets),
+ .dapm_routes = cs42l51_routes,
+ .num_dapm_routes = ARRAY_SIZE(cs42l51_routes),
};
static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
@@ -586,30 +577,25 @@ static int cs42l51_i2c_probe(struct i2c_client *i2c_client,
dev_info(&i2c_client->dev, "found device cs42l51 rev %d\n",
ret & 7);
- cs42l51 = kzalloc(sizeof(struct cs42l51_private), GFP_KERNEL);
+ cs42l51 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l51_private),
+ GFP_KERNEL);
if (!cs42l51) {
dev_err(&i2c_client->dev, "could not allocate codec\n");
return -ENOMEM;
}
i2c_set_clientdata(i2c_client, cs42l51);
- cs42l51->control_data = i2c_client;
cs42l51->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c_client->dev,
&soc_codec_device_cs42l51, &cs42l51_dai, 1);
- if (ret < 0)
- kfree(cs42l51);
error:
return ret;
}
static int cs42l51_i2c_remove(struct i2c_client *client)
{
- struct cs42l51_private *cs42l51 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- kfree(cs42l51);
return 0;
}
diff --git a/sound/soc/codecs/cs42l73.c b/sound/soc/codecs/cs42l73.c
new file mode 100644
index 000000000000..78979b3e0e95
--- /dev/null
+++ b/sound/soc/codecs/cs42l73.c
@@ -0,0 +1,1453 @@
+/*
+ * cs42l73.c -- CS42L73 ALSA Soc Audio driver
+ *
+ * Copyright 2011 Cirrus Logic, Inc.
+ *
+ * Authors: Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>
+ * Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include "cs42l73.h"
+
+struct sp_config {
+ u8 spc, mmcc, spfs;
+ u32 srate;
+};
+struct cs42l73_private {
+ struct sp_config config[3];
+ struct regmap *regmap;
+ u32 sysclk;
+ u8 mclksel;
+ u32 mclk;
+};
+
+static const struct reg_default cs42l73_reg_defaults[] = {
+ { 1, 0x42 }, /* r01 - Device ID A&B */
+ { 2, 0xA7 }, /* r02 - Device ID C&D */
+ { 3, 0x30 }, /* r03 - Device ID E */
+ { 6, 0xF1 }, /* r06 - Power Ctl 1 */
+ { 7, 0xDF }, /* r07 - Power Ctl 2 */
+ { 8, 0x3F }, /* r08 - Power Ctl 3 */
+ { 9, 0x50 }, /* r09 - Charge Pump Freq */
+ { 10, 0x53 }, /* r0A - Output Load MicBias Short Detect */
+ { 11, 0x00 }, /* r0B - DMIC Master Clock Ctl */
+ { 12, 0x00 }, /* r0C - Aux PCM Ctl */
+ { 13, 0x15 }, /* r0D - Aux PCM Master Clock Ctl */
+ { 14, 0x00 }, /* r0E - Audio PCM Ctl */
+ { 15, 0x15 }, /* r0F - Audio PCM Master Clock Ctl */
+ { 16, 0x00 }, /* r10 - Voice PCM Ctl */
+ { 17, 0x15 }, /* r11 - Voice PCM Master Clock Ctl */
+ { 18, 0x00 }, /* r12 - Voice/Aux Sample Rate */
+ { 19, 0x06 }, /* r13 - Misc I/O Path Ctl */
+ { 20, 0x00 }, /* r14 - ADC Input Path Ctl */
+ { 21, 0x00 }, /* r15 - MICA Preamp, PGA Volume */
+ { 22, 0x00 }, /* r16 - MICB Preamp, PGA Volume */
+ { 23, 0x00 }, /* r17 - Input Path A Digital Volume */
+ { 24, 0x00 }, /* r18 - Input Path B Digital Volume */
+ { 25, 0x00 }, /* r19 - Playback Digital Ctl */
+ { 26, 0x00 }, /* r1A - HP/LO Left Digital Volume */
+ { 27, 0x00 }, /* r1B - HP/LO Right Digital Volume */
+ { 28, 0x00 }, /* r1C - Speakerphone Digital Volume */
+ { 29, 0x00 }, /* r1D - Ear/SPKLO Digital Volume */
+ { 30, 0x00 }, /* r1E - HP Left Analog Volume */
+ { 31, 0x00 }, /* r1F - HP Right Analog Volume */
+ { 32, 0x00 }, /* r20 - LO Left Analog Volume */
+ { 33, 0x00 }, /* r21 - LO Right Analog Volume */
+ { 34, 0x00 }, /* r22 - Stereo Input Path Advisory Volume */
+ { 35, 0x00 }, /* r23 - Aux PCM Input Advisory Volume */
+ { 36, 0x00 }, /* r24 - Audio PCM Input Advisory Volume */
+ { 37, 0x00 }, /* r25 - Voice PCM Input Advisory Volume */
+ { 38, 0x00 }, /* r26 - Limiter Attack Rate HP/LO */
+ { 39, 0x7F }, /* r27 - Limter Ctl, Release Rate HP/LO */
+ { 40, 0x00 }, /* r28 - Limter Threshold HP/LO */
+ { 41, 0x00 }, /* r29 - Limiter Attack Rate Speakerphone */
+ { 42, 0x3F }, /* r2A - Limter Ctl, Release Rate Speakerphone */
+ { 43, 0x00 }, /* r2B - Limter Threshold Speakerphone */
+ { 44, 0x00 }, /* r2C - Limiter Attack Rate Ear/SPKLO */
+ { 45, 0x3F }, /* r2D - Limter Ctl, Release Rate Ear/SPKLO */
+ { 46, 0x00 }, /* r2E - Limter Threshold Ear/SPKLO */
+ { 47, 0x00 }, /* r2F - ALC Enable, Attack Rate Left/Right */
+ { 48, 0x3F }, /* r30 - ALC Release Rate Left/Right */
+ { 49, 0x00 }, /* r31 - ALC Threshold Left/Right */
+ { 50, 0x00 }, /* r32 - Noise Gate Ctl Left/Right */
+ { 51, 0x00 }, /* r33 - ALC/NG Misc Ctl */
+ { 52, 0x18 }, /* r34 - Mixer Ctl */
+ { 53, 0x3F }, /* r35 - HP/LO Left Mixer Input Path Volume */
+ { 54, 0x3F }, /* r36 - HP/LO Right Mixer Input Path Volume */
+ { 55, 0x3F }, /* r37 - HP/LO Left Mixer Aux PCM Volume */
+ { 56, 0x3F }, /* r38 - HP/LO Right Mixer Aux PCM Volume */
+ { 57, 0x3F }, /* r39 - HP/LO Left Mixer Audio PCM Volume */
+ { 58, 0x3F }, /* r3A - HP/LO Right Mixer Audio PCM Volume */
+ { 59, 0x3F }, /* r3B - HP/LO Left Mixer Voice PCM Mono Volume */
+ { 60, 0x3F }, /* r3C - HP/LO Right Mixer Voice PCM Mono Volume */
+ { 61, 0x3F }, /* r3D - Aux PCM Left Mixer Input Path Volume */
+ { 62, 0x3F }, /* r3E - Aux PCM Right Mixer Input Path Volume */
+ { 63, 0x3F }, /* r3F - Aux PCM Left Mixer Volume */
+ { 64, 0x3F }, /* r40 - Aux PCM Left Mixer Volume */
+ { 65, 0x3F }, /* r41 - Aux PCM Left Mixer Audio PCM L Volume */
+ { 66, 0x3F }, /* r42 - Aux PCM Right Mixer Audio PCM R Volume */
+ { 67, 0x3F }, /* r43 - Aux PCM Left Mixer Voice PCM Volume */
+ { 68, 0x3F }, /* r44 - Aux PCM Right Mixer Voice PCM Volume */
+ { 69, 0x3F }, /* r45 - Audio PCM Left Input Path Volume */
+ { 70, 0x3F }, /* r46 - Audio PCM Right Input Path Volume */
+ { 71, 0x3F }, /* r47 - Audio PCM Left Mixer Aux PCM L Volume */
+ { 72, 0x3F }, /* r48 - Audio PCM Right Mixer Aux PCM R Volume */
+ { 73, 0x3F }, /* r49 - Audio PCM Left Mixer Volume */
+ { 74, 0x3F }, /* r4A - Audio PCM Right Mixer Volume */
+ { 75, 0x3F }, /* r4B - Audio PCM Left Mixer Voice PCM Volume */
+ { 76, 0x3F }, /* r4C - Audio PCM Right Mixer Voice PCM Volume */
+ { 77, 0x3F }, /* r4D - Voice PCM Left Input Path Volume */
+ { 78, 0x3F }, /* r4E - Voice PCM Right Input Path Volume */
+ { 79, 0x3F }, /* r4F - Voice PCM Left Mixer Aux PCM L Volume */
+ { 80, 0x3F }, /* r50 - Voice PCM Right Mixer Aux PCM R Volume */
+ { 81, 0x3F }, /* r51 - Voice PCM Left Mixer Audio PCM L Volume */
+ { 82, 0x3F }, /* r52 - Voice PCM Right Mixer Audio PCM R Volume */
+ { 83, 0x3F }, /* r53 - Voice PCM Left Mixer Voice PCM Volume */
+ { 84, 0x3F }, /* r54 - Voice PCM Right Mixer Voice PCM Volume */
+ { 85, 0xAA }, /* r55 - Mono Mixer Ctl */
+ { 86, 0x3F }, /* r56 - SPK Mono Mixer Input Path Volume */
+ { 87, 0x3F }, /* r57 - SPK Mono Mixer Aux PCM Mono/L/R Volume */
+ { 88, 0x3F }, /* r58 - SPK Mono Mixer Audio PCM Mono/L/R Volume */
+ { 89, 0x3F }, /* r59 - SPK Mono Mixer Voice PCM Mono Volume */
+ { 90, 0x3F }, /* r5A - SPKLO Mono Mixer Input Path Mono Volume */
+ { 91, 0x3F }, /* r5B - SPKLO Mono Mixer Aux Mono/L/R Volume */
+ { 92, 0x3F }, /* r5C - SPKLO Mono Mixer Audio Mono/L/R Volume */
+ { 93, 0x3F }, /* r5D - SPKLO Mono Mixer Voice Mono Volume */
+ { 94, 0x00 }, /* r5E - Interrupt Mask 1 */
+ { 95, 0x00 }, /* r5F - Interrupt Mask 2 */
+};
+
+static bool cs42l73_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42L73_IS1:
+ case CS42L73_IS2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool cs42l73_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case CS42L73_DEVID_AB:
+ case CS42L73_DEVID_CD:
+ case CS42L73_DEVID_E:
+ case CS42L73_REVID:
+ case CS42L73_PWRCTL1:
+ case CS42L73_PWRCTL2:
+ case CS42L73_PWRCTL3:
+ case CS42L73_CPFCHC:
+ case CS42L73_OLMBMSDC:
+ case CS42L73_DMMCC:
+ case CS42L73_XSPC:
+ case CS42L73_XSPMMCC:
+ case CS42L73_ASPC:
+ case CS42L73_ASPMMCC:
+ case CS42L73_VSPC:
+ case CS42L73_VSPMMCC:
+ case CS42L73_VXSPFS:
+ case CS42L73_MIOPC:
+ case CS42L73_ADCIPC:
+ case CS42L73_MICAPREPGAAVOL:
+ case CS42L73_MICBPREPGABVOL:
+ case CS42L73_IPADVOL:
+ case CS42L73_IPBDVOL:
+ case CS42L73_PBDC:
+ case CS42L73_HLADVOL:
+ case CS42L73_HLBDVOL:
+ case CS42L73_SPKDVOL:
+ case CS42L73_ESLDVOL:
+ case CS42L73_HPAAVOL:
+ case CS42L73_HPBAVOL:
+ case CS42L73_LOAAVOL:
+ case CS42L73_LOBAVOL:
+ case CS42L73_STRINV:
+ case CS42L73_XSPINV:
+ case CS42L73_ASPINV:
+ case CS42L73_VSPINV:
+ case CS42L73_LIMARATEHL:
+ case CS42L73_LIMRRATEHL:
+ case CS42L73_LMAXHL:
+ case CS42L73_LIMARATESPK:
+ case CS42L73_LIMRRATESPK:
+ case CS42L73_LMAXSPK:
+ case CS42L73_LIMARATEESL:
+ case CS42L73_LIMRRATEESL:
+ case CS42L73_LMAXESL:
+ case CS42L73_ALCARATE:
+ case CS42L73_ALCRRATE:
+ case CS42L73_ALCMINMAX:
+ case CS42L73_NGCAB:
+ case CS42L73_ALCNGMC:
+ case CS42L73_MIXERCTL:
+ case CS42L73_HLAIPAA:
+ case CS42L73_HLBIPBA:
+ case CS42L73_HLAXSPAA:
+ case CS42L73_HLBXSPBA:
+ case CS42L73_HLAASPAA:
+ case CS42L73_HLBASPBA:
+ case CS42L73_HLAVSPMA:
+ case CS42L73_HLBVSPMA:
+ case CS42L73_XSPAIPAA:
+ case CS42L73_XSPBIPBA:
+ case CS42L73_XSPAXSPAA:
+ case CS42L73_XSPBXSPBA:
+ case CS42L73_XSPAASPAA:
+ case CS42L73_XSPAASPBA:
+ case CS42L73_XSPAVSPMA:
+ case CS42L73_XSPBVSPMA:
+ case CS42L73_ASPAIPAA:
+ case CS42L73_ASPBIPBA:
+ case CS42L73_ASPAXSPAA:
+ case CS42L73_ASPBXSPBA:
+ case CS42L73_ASPAASPAA:
+ case CS42L73_ASPBASPBA:
+ case CS42L73_ASPAVSPMA:
+ case CS42L73_ASPBVSPMA:
+ case CS42L73_VSPAIPAA:
+ case CS42L73_VSPBIPBA:
+ case CS42L73_VSPAXSPAA:
+ case CS42L73_VSPBXSPBA:
+ case CS42L73_VSPAASPAA:
+ case CS42L73_VSPBASPBA:
+ case CS42L73_VSPAVSPMA:
+ case CS42L73_VSPBVSPMA:
+ case CS42L73_MMIXCTL:
+ case CS42L73_SPKMIPMA:
+ case CS42L73_SPKMXSPA:
+ case CS42L73_SPKMASPA:
+ case CS42L73_SPKMVSPMA:
+ case CS42L73_ESLMIPMA:
+ case CS42L73_ESLMXSPA:
+ case CS42L73_ESLMASPA:
+ case CS42L73_ESLMVSPMA:
+ case CS42L73_IM1:
+ case CS42L73_IM2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const unsigned int hpaloa_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 13, TLV_DB_SCALE_ITEM(-7600, 200, 0),
+ 14, 75, TLV_DB_SCALE_ITEM(-4900, 100, 0),
+};
+
+static DECLARE_TLV_DB_SCALE(adc_boost_tlv, 0, 2500, 0);
+
+static DECLARE_TLV_DB_SCALE(hl_tlv, -10200, 50, 0);
+
+static DECLARE_TLV_DB_SCALE(ipd_tlv, -9600, 100, 0);
+
+static DECLARE_TLV_DB_SCALE(micpga_tlv, -600, 50, 0);
+
+static const unsigned int limiter_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0, 2, TLV_DB_SCALE_ITEM(-3000, 600, 0),
+ 3, 7, TLV_DB_SCALE_ITEM(-1200, 300, 0),
+};
+
+static const DECLARE_TLV_DB_SCALE(attn_tlv, -6300, 100, 1);
+
+static const char * const cs42l73_pgaa_text[] = { "Line A", "Mic 1" };
+static const char * const cs42l73_pgab_text[] = { "Line B", "Mic 2" };
+
+static const struct soc_enum pgaa_enum =
+ SOC_ENUM_SINGLE(CS42L73_ADCIPC, 3,
+ ARRAY_SIZE(cs42l73_pgaa_text), cs42l73_pgaa_text);
+
+static const struct soc_enum pgab_enum =
+ SOC_ENUM_SINGLE(CS42L73_ADCIPC, 7,
+ ARRAY_SIZE(cs42l73_pgab_text), cs42l73_pgab_text);
+
+static const struct snd_kcontrol_new pgaa_mux =
+ SOC_DAPM_ENUM("Left Analog Input Capture Mux", pgaa_enum);
+
+static const struct snd_kcontrol_new pgab_mux =
+ SOC_DAPM_ENUM("Right Analog Input Capture Mux", pgab_enum);
+
+static const struct snd_kcontrol_new input_left_mixer[] = {
+ SOC_DAPM_SINGLE("ADC Left Input", CS42L73_PWRCTL1,
+ 5, 1, 1),
+ SOC_DAPM_SINGLE("DMIC Left Input", CS42L73_PWRCTL1,
+ 4, 1, 1),
+};
+
+static const struct snd_kcontrol_new input_right_mixer[] = {
+ SOC_DAPM_SINGLE("ADC Right Input", CS42L73_PWRCTL1,
+ 7, 1, 1),
+ SOC_DAPM_SINGLE("DMIC Right Input", CS42L73_PWRCTL1,
+ 6, 1, 1),
+};
+
+static const char * const cs42l73_ng_delay_text[] = {
+ "50ms", "100ms", "150ms", "200ms" };
+
+static const struct soc_enum ng_delay_enum =
+ SOC_ENUM_SINGLE(CS42L73_NGCAB, 0,
+ ARRAY_SIZE(cs42l73_ng_delay_text), cs42l73_ng_delay_text);
+
+static const char * const charge_pump_freq_text[] = {
+ "0", "1", "2", "3", "4",
+ "5", "6", "7", "8", "9",
+ "10", "11", "12", "13", "14", "15" };
+
+static const struct soc_enum charge_pump_enum =
+ SOC_ENUM_SINGLE(CS42L73_CPFCHC, 4,
+ ARRAY_SIZE(charge_pump_freq_text), charge_pump_freq_text);
+
+static const char * const cs42l73_mono_mix_texts[] = {
+ "Left", "Right", "Mono Mix"};
+
+static const unsigned int cs42l73_mono_mix_values[] = { 0, 1, 2 };
+
+static const struct soc_enum spk_asp_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 6, 1,
+ ARRAY_SIZE(cs42l73_mono_mix_texts),
+ cs42l73_mono_mix_texts,
+ cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new spk_asp_mixer =
+ SOC_DAPM_ENUM("Route", spk_asp_enum);
+
+static const struct soc_enum spk_xsp_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 4, 3,
+ ARRAY_SIZE(cs42l73_mono_mix_texts),
+ cs42l73_mono_mix_texts,
+ cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new spk_xsp_mixer =
+ SOC_DAPM_ENUM("Route", spk_xsp_enum);
+
+static const struct soc_enum esl_asp_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 2, 5,
+ ARRAY_SIZE(cs42l73_mono_mix_texts),
+ cs42l73_mono_mix_texts,
+ cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new esl_asp_mixer =
+ SOC_DAPM_ENUM("Route", esl_asp_enum);
+
+static const struct soc_enum esl_xsp_enum =
+ SOC_VALUE_ENUM_SINGLE(CS42L73_MMIXCTL, 0, 7,
+ ARRAY_SIZE(cs42l73_mono_mix_texts),
+ cs42l73_mono_mix_texts,
+ cs42l73_mono_mix_values);
+
+static const struct snd_kcontrol_new esl_xsp_mixer =
+ SOC_DAPM_ENUM("Route", esl_xsp_enum);
+
+static const char * const cs42l73_ip_swap_text[] = {
+ "Stereo", "Mono A", "Mono B", "Swap A-B"};
+
+static const struct soc_enum ip_swap_enum =
+ SOC_ENUM_SINGLE(CS42L73_MIOPC, 6,
+ ARRAY_SIZE(cs42l73_ip_swap_text), cs42l73_ip_swap_text);
+
+static const char * const cs42l73_spo_mixer_text[] = {"Mono", "Stereo"};
+
+static const struct soc_enum vsp_output_mux_enum =
+ SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 5,
+ ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
+
+static const struct soc_enum xsp_output_mux_enum =
+ SOC_ENUM_SINGLE(CS42L73_MIXERCTL, 4,
+ ARRAY_SIZE(cs42l73_spo_mixer_text), cs42l73_spo_mixer_text);
+
+static const struct snd_kcontrol_new vsp_output_mux =
+ SOC_DAPM_ENUM("Route", vsp_output_mux_enum);
+
+static const struct snd_kcontrol_new xsp_output_mux =
+ SOC_DAPM_ENUM("Route", xsp_output_mux_enum);
+
+static const struct snd_kcontrol_new hp_amp_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 0, 1, 1);
+
+static const struct snd_kcontrol_new lo_amp_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 1, 1, 1);
+
+static const struct snd_kcontrol_new spk_amp_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 2, 1, 1);
+
+static const struct snd_kcontrol_new spklo_amp_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 4, 1, 1);
+
+static const struct snd_kcontrol_new ear_amp_ctl =
+ SOC_DAPM_SINGLE("Switch", CS42L73_PWRCTL3, 3, 1, 1);
+
+static const struct snd_kcontrol_new cs42l73_snd_controls[] = {
+ SOC_DOUBLE_R_SX_TLV("Headphone Analog Playback Volume",
+ CS42L73_HPAAVOL, CS42L73_HPBAVOL, 7,
+ 0xffffffC1, 0x0C, hpaloa_tlv),
+
+ SOC_DOUBLE_R_SX_TLV("LineOut Analog Playback Volume", CS42L73_LOAAVOL,
+ CS42L73_LOBAVOL, 7, 0xffffffC1, 0x0C, hpaloa_tlv),
+
+ SOC_DOUBLE_R_SX_TLV("Input PGA Analog Volume", CS42L73_MICAPREPGAAVOL,
+ CS42L73_MICBPREPGABVOL, 5, 0xffffff35,
+ 0x34, micpga_tlv),
+
+ SOC_DOUBLE_R("MIC Preamp Switch", CS42L73_MICAPREPGAAVOL,
+ CS42L73_MICBPREPGABVOL, 6, 1, 1),
+
+ SOC_DOUBLE_R_SX_TLV("Input Path Digital Volume", CS42L73_IPADVOL,
+ CS42L73_IPBDVOL, 7, 0xffffffA0, 0xA0, ipd_tlv),
+
+ SOC_DOUBLE_R_SX_TLV("HL Digital Playback Volume",
+ CS42L73_HLADVOL, CS42L73_HLBDVOL, 7, 0xffffffE5,
+ 0xE4, hl_tlv),
+
+ SOC_SINGLE_TLV("ADC A Boost Volume",
+ CS42L73_ADCIPC, 2, 0x01, 1, adc_boost_tlv),
+
+ SOC_SINGLE_TLV("ADC B Boost Volume",
+ CS42L73_ADCIPC, 6, 0x01, 1, adc_boost_tlv),
+
+ SOC_SINGLE_TLV("Speakerphone Digital Playback Volume",
+ CS42L73_SPKDVOL, 0, 0xE4, 1, hl_tlv),
+
+ SOC_SINGLE_TLV("Ear Speaker Digital Playback Volume",
+ CS42L73_ESLDVOL, 0, 0xE4, 1, hl_tlv),
+
+ SOC_DOUBLE_R("Headphone Analog Playback Switch", CS42L73_HPAAVOL,
+ CS42L73_HPBAVOL, 7, 1, 1),
+
+ SOC_DOUBLE_R("LineOut Analog Playback Switch", CS42L73_LOAAVOL,
+ CS42L73_LOBAVOL, 7, 1, 1),
+ SOC_DOUBLE("Input Path Digital Switch", CS42L73_ADCIPC, 0, 4, 1, 1),
+ SOC_DOUBLE("HL Digital Playback Switch", CS42L73_PBDC, 0,
+ 1, 1, 1),
+ SOC_SINGLE("Speakerphone Digital Playback Switch", CS42L73_PBDC, 2, 1,
+ 1),
+ SOC_SINGLE("Ear Speaker Digital Playback Switch", CS42L73_PBDC, 3, 1,
+ 1),
+
+ SOC_SINGLE("PGA Soft-Ramp Switch", CS42L73_MIOPC, 3, 1, 0),
+ SOC_SINGLE("Analog Zero Cross Switch", CS42L73_MIOPC, 2, 1, 0),
+ SOC_SINGLE("Digital Soft-Ramp Switch", CS42L73_MIOPC, 1, 1, 0),
+ SOC_SINGLE("Analog Output Soft-Ramp Switch", CS42L73_MIOPC, 0, 1, 0),
+
+ SOC_DOUBLE("ADC Signal Polarity Switch", CS42L73_ADCIPC, 1, 5, 1,
+ 0),
+
+ SOC_SINGLE("HL Limiter Attack Rate", CS42L73_LIMARATEHL, 0, 0x3F,
+ 0),
+ SOC_SINGLE("HL Limiter Release Rate", CS42L73_LIMRRATEHL, 0,
+ 0x3F, 0),
+
+
+ SOC_SINGLE("HL Limiter Switch", CS42L73_LIMRRATEHL, 7, 1, 0),
+ SOC_SINGLE("HL Limiter All Channels Switch", CS42L73_LIMRRATEHL, 6, 1,
+ 0),
+
+ SOC_SINGLE_TLV("HL Limiter Max Threshold Volume", CS42L73_LMAXHL, 5, 7,
+ 1, limiter_tlv),
+
+ SOC_SINGLE_TLV("HL Limiter Cushion Volume", CS42L73_LMAXHL, 2, 7, 1,
+ limiter_tlv),
+
+ SOC_SINGLE("SPK Limiter Attack Rate Volume", CS42L73_LIMARATESPK, 0,
+ 0x3F, 0),
+ SOC_SINGLE("SPK Limiter Release Rate Volume", CS42L73_LIMRRATESPK, 0,
+ 0x3F, 0),
+ SOC_SINGLE("SPK Limiter Switch", CS42L73_LIMRRATESPK, 7, 1, 0),
+ SOC_SINGLE("SPK Limiter All Channels Switch", CS42L73_LIMRRATESPK,
+ 6, 1, 0),
+ SOC_SINGLE_TLV("SPK Limiter Max Threshold Volume", CS42L73_LMAXSPK, 5,
+ 7, 1, limiter_tlv),
+
+ SOC_SINGLE_TLV("SPK Limiter Cushion Volume", CS42L73_LMAXSPK, 2, 7, 1,
+ limiter_tlv),
+
+ SOC_SINGLE("ESL Limiter Attack Rate Volume", CS42L73_LIMARATEESL, 0,
+ 0x3F, 0),
+ SOC_SINGLE("ESL Limiter Release Rate Volume", CS42L73_LIMRRATEESL, 0,
+ 0x3F, 0),
+ SOC_SINGLE("ESL Limiter Switch", CS42L73_LIMRRATEESL, 7, 1, 0),
+ SOC_SINGLE_TLV("ESL Limiter Max Threshold Volume", CS42L73_LMAXESL, 5,
+ 7, 1, limiter_tlv),
+
+ SOC_SINGLE_TLV("ESL Limiter Cushion Volume", CS42L73_LMAXESL, 2, 7, 1,
+ limiter_tlv),
+
+ SOC_SINGLE("ALC Attack Rate Volume", CS42L73_ALCARATE, 0, 0x3F, 0),
+ SOC_SINGLE("ALC Release Rate Volume", CS42L73_ALCRRATE, 0, 0x3F, 0),
+ SOC_DOUBLE("ALC Switch", CS42L73_ALCARATE, 6, 7, 1, 0),
+ SOC_SINGLE_TLV("ALC Max Threshold Volume", CS42L73_ALCMINMAX, 5, 7, 0,
+ limiter_tlv),
+ SOC_SINGLE_TLV("ALC Min Threshold Volume", CS42L73_ALCMINMAX, 2, 7, 0,
+ limiter_tlv),
+
+ SOC_DOUBLE("NG Enable Switch", CS42L73_NGCAB, 6, 7, 1, 0),
+ SOC_SINGLE("NG Boost Switch", CS42L73_NGCAB, 5, 1, 0),
+ /*
+ NG Threshold depends on NG_BOOTSAB, which selects
+ between two threshold scales in decibels.
+ Set linear values for now ..
+ */
+ SOC_SINGLE("NG Threshold", CS42L73_NGCAB, 2, 7, 0),
+ SOC_ENUM("NG Delay", ng_delay_enum),
+
+ SOC_ENUM("Charge Pump Frequency", charge_pump_enum),
+
+ SOC_DOUBLE_R_TLV("XSP-IP Volume",
+ CS42L73_XSPAIPAA, CS42L73_XSPBIPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("XSP-XSP Volume",
+ CS42L73_XSPAXSPAA, CS42L73_XSPBXSPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("XSP-ASP Volume",
+ CS42L73_XSPAASPAA, CS42L73_XSPAASPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("XSP-VSP Volume",
+ CS42L73_XSPAVSPMA, CS42L73_XSPBVSPMA, 0, 0x3F, 1,
+ attn_tlv),
+
+ SOC_DOUBLE_R_TLV("ASP-IP Volume",
+ CS42L73_ASPAIPAA, CS42L73_ASPBIPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("ASP-XSP Volume",
+ CS42L73_ASPAXSPAA, CS42L73_ASPBXSPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("ASP-ASP Volume",
+ CS42L73_ASPAASPAA, CS42L73_ASPBASPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("ASP-VSP Volume",
+ CS42L73_ASPAVSPMA, CS42L73_ASPBVSPMA, 0, 0x3F, 1,
+ attn_tlv),
+
+ SOC_DOUBLE_R_TLV("VSP-IP Volume",
+ CS42L73_VSPAIPAA, CS42L73_VSPBIPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("VSP-XSP Volume",
+ CS42L73_VSPAXSPAA, CS42L73_VSPBXSPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("VSP-ASP Volume",
+ CS42L73_VSPAASPAA, CS42L73_VSPBASPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("VSP-VSP Volume",
+ CS42L73_VSPAVSPMA, CS42L73_VSPBVSPMA, 0, 0x3F, 1,
+ attn_tlv),
+
+ SOC_DOUBLE_R_TLV("HL-IP Volume",
+ CS42L73_HLAIPAA, CS42L73_HLBIPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("HL-XSP Volume",
+ CS42L73_HLAXSPAA, CS42L73_HLBXSPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("HL-ASP Volume",
+ CS42L73_HLAASPAA, CS42L73_HLBASPBA, 0, 0x3F, 1,
+ attn_tlv),
+ SOC_DOUBLE_R_TLV("HL-VSP Volume",
+ CS42L73_HLAVSPMA, CS42L73_HLBVSPMA, 0, 0x3F, 1,
+ attn_tlv),
+
+ SOC_SINGLE_TLV("SPK-IP Mono Volume",
+ CS42L73_SPKMIPMA, 0, 0x3E, 1, attn_tlv),
+ SOC_SINGLE_TLV("SPK-XSP Mono Volume",
+ CS42L73_SPKMXSPA, 0, 0x3E, 1, attn_tlv),
+ SOC_SINGLE_TLV("SPK-ASP Mono Volume",
+ CS42L73_SPKMASPA, 0, 0x3E, 1, attn_tlv),
+ SOC_SINGLE_TLV("SPK-VSP Mono Volume",
+ CS42L73_SPKMVSPMA, 0, 0x3E, 1, attn_tlv),
+
+ SOC_SINGLE_TLV("ESL-IP Mono Volume",
+ CS42L73_ESLMIPMA, 0, 0x3E, 1, attn_tlv),
+ SOC_SINGLE_TLV("ESL-XSP Mono Volume",
+ CS42L73_ESLMXSPA, 0, 0x3E, 1, attn_tlv),
+ SOC_SINGLE_TLV("ESL-ASP Mono Volume",
+ CS42L73_ESLMASPA, 0, 0x3E, 1, attn_tlv),
+ SOC_SINGLE_TLV("ESL-VSP Mono Volume",
+ CS42L73_ESLMVSPMA, 0, 0x3E, 1, attn_tlv),
+
+ SOC_ENUM("IP Digital Swap/Mono Select", ip_swap_enum),
+
+ SOC_ENUM("VSPOUT Mono/Stereo Select", vsp_output_mux_enum),
+ SOC_ENUM("XSPOUT Mono/Stereo Select", xsp_output_mux_enum),
+};
+
+static const struct snd_soc_dapm_widget cs42l73_dapm_widgets[] = {
+ SND_SOC_DAPM_INPUT("LINEINA"),
+ SND_SOC_DAPM_INPUT("LINEINB"),
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_SUPPLY("MIC1 Bias", CS42L73_PWRCTL2, 6, 1, NULL, 0),
+ SND_SOC_DAPM_INPUT("MIC2"),
+ SND_SOC_DAPM_SUPPLY("MIC2 Bias", CS42L73_PWRCTL2, 7, 1, NULL, 0),
+
+ SND_SOC_DAPM_AIF_OUT("XSPOUTL", "XSP Capture", 0,
+ CS42L73_PWRCTL2, 1, 1),
+ SND_SOC_DAPM_AIF_OUT("XSPOUTR", "XSP Capture", 0,
+ CS42L73_PWRCTL2, 1, 1),
+ SND_SOC_DAPM_AIF_OUT("ASPOUTL", "ASP Capture", 0,
+ CS42L73_PWRCTL2, 3, 1),
+ SND_SOC_DAPM_AIF_OUT("ASPOUTR", "ASP Capture", 0,
+ CS42L73_PWRCTL2, 3, 1),
+ SND_SOC_DAPM_AIF_OUT("VSPOUTL", "VSP Capture", 0,
+ CS42L73_PWRCTL2, 4, 1),
+ SND_SOC_DAPM_AIF_OUT("VSPOUTR", "VSP Capture", 0,
+ CS42L73_PWRCTL2, 4, 1),
+
+ SND_SOC_DAPM_PGA("PGA Left", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("PGA Right", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("PGA Left Mux", SND_SOC_NOPM, 0, 0, &pgaa_mux),
+ SND_SOC_DAPM_MUX("PGA Right Mux", SND_SOC_NOPM, 0, 0, &pgab_mux),
+
+ SND_SOC_DAPM_ADC("ADC Left", NULL, CS42L73_PWRCTL1, 7, 1),
+ SND_SOC_DAPM_ADC("ADC Right", NULL, CS42L73_PWRCTL1, 5, 1),
+ SND_SOC_DAPM_ADC("DMIC Left", NULL, CS42L73_PWRCTL1, 6, 1),
+ SND_SOC_DAPM_ADC("DMIC Right", NULL, CS42L73_PWRCTL1, 4, 1),
+
+ SND_SOC_DAPM_MIXER_NAMED_CTL("Input Left Capture", SND_SOC_NOPM,
+ 0, 0, input_left_mixer,
+ ARRAY_SIZE(input_left_mixer)),
+
+ SND_SOC_DAPM_MIXER_NAMED_CTL("Input Right Capture", SND_SOC_NOPM,
+ 0, 0, input_right_mixer,
+ ARRAY_SIZE(input_right_mixer)),
+
+ SND_SOC_DAPM_MIXER("ASPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("ASPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("XSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("XSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("VSPL Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("VSPR Output Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_AIF_IN("XSPINL", "XSP Playback", 0,
+ CS42L73_PWRCTL2, 0, 1),
+ SND_SOC_DAPM_AIF_IN("XSPINR", "XSP Playback", 0,
+ CS42L73_PWRCTL2, 0, 1),
+ SND_SOC_DAPM_AIF_IN("XSPINM", "XSP Playback", 0,
+ CS42L73_PWRCTL2, 0, 1),
+
+ SND_SOC_DAPM_AIF_IN("ASPINL", "ASP Playback", 0,
+ CS42L73_PWRCTL2, 2, 1),
+ SND_SOC_DAPM_AIF_IN("ASPINR", "ASP Playback", 0,
+ CS42L73_PWRCTL2, 2, 1),
+ SND_SOC_DAPM_AIF_IN("ASPINM", "ASP Playback", 0,
+ CS42L73_PWRCTL2, 2, 1),
+
+ SND_SOC_DAPM_AIF_IN("VSPIN", "VSP Playback", 0,
+ CS42L73_PWRCTL2, 4, 1),
+
+ SND_SOC_DAPM_MIXER("HL Left Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("HL Right Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("SPK Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_MIXER("ESL Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_MUX("ESL-XSP Mux", SND_SOC_NOPM,
+ 0, 0, &esl_xsp_mixer),
+
+ SND_SOC_DAPM_MUX("ESL-ASP Mux", SND_SOC_NOPM,
+ 0, 0, &esl_asp_mixer),
+
+ SND_SOC_DAPM_MUX("SPK-ASP Mux", SND_SOC_NOPM,
+ 0, 0, &spk_asp_mixer),
+
+ SND_SOC_DAPM_MUX("SPK-XSP Mux", SND_SOC_NOPM,
+ 0, 0, &spk_xsp_mixer),
+
+ SND_SOC_DAPM_PGA("HL Left DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("HL Right DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("SPK DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("ESL DAC", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SWITCH("HP Amp", CS42L73_PWRCTL3, 0, 1,
+ &hp_amp_ctl),
+ SND_SOC_DAPM_SWITCH("LO Amp", CS42L73_PWRCTL3, 1, 1,
+ &lo_amp_ctl),
+ SND_SOC_DAPM_SWITCH("SPK Amp", CS42L73_PWRCTL3, 2, 1,
+ &spk_amp_ctl),
+ SND_SOC_DAPM_SWITCH("EAR Amp", CS42L73_PWRCTL3, 3, 1,
+ &ear_amp_ctl),
+ SND_SOC_DAPM_SWITCH("SPKLO Amp", CS42L73_PWRCTL3, 4, 1,
+ &spklo_amp_ctl),
+
+ SND_SOC_DAPM_OUTPUT("HPOUTA"),
+ SND_SOC_DAPM_OUTPUT("HPOUTB"),
+ SND_SOC_DAPM_OUTPUT("LINEOUTA"),
+ SND_SOC_DAPM_OUTPUT("LINEOUTB"),
+ SND_SOC_DAPM_OUTPUT("EAROUT"),
+ SND_SOC_DAPM_OUTPUT("SPKOUT"),
+ SND_SOC_DAPM_OUTPUT("SPKLINEOUT"),
+};
+
+static const struct snd_soc_dapm_route cs42l73_audio_map[] = {
+
+ /* SPKLO EARSPK Paths */
+ {"EAROUT", NULL, "EAR Amp"},
+ {"SPKLINEOUT", NULL, "SPKLO Amp"},
+
+ {"EAR Amp", "Switch", "ESL DAC"},
+ {"SPKLO Amp", "Switch", "ESL DAC"},
+
+ {"ESL DAC", "ESL-ASP Mono Volume", "ESL Mixer"},
+ {"ESL DAC", "ESL-XSP Mono Volume", "ESL Mixer"},
+ {"ESL DAC", "ESL-VSP Mono Volume", "VSPIN"},
+ /* Loopback */
+ {"ESL DAC", "ESL-IP Mono Volume", "Input Left Capture"},
+ {"ESL DAC", "ESL-IP Mono Volume", "Input Right Capture"},
+
+ {"ESL Mixer", NULL, "ESL-ASP Mux"},
+ {"ESL Mixer", NULL, "ESL-XSP Mux"},
+
+ {"ESL-ASP Mux", "Left", "ASPINL"},
+ {"ESL-ASP Mux", "Right", "ASPINR"},
+ {"ESL-ASP Mux", "Mono Mix", "ASPINM"},
+
+ {"ESL-XSP Mux", "Left", "XSPINL"},
+ {"ESL-XSP Mux", "Right", "XSPINR"},
+ {"ESL-XSP Mux", "Mono Mix", "XSPINM"},
+
+ /* Speakerphone Paths */
+ {"SPKOUT", NULL, "SPK Amp"},
+ {"SPK Amp", "Switch", "SPK DAC"},
+
+ {"SPK DAC", "SPK-ASP Mono Volume", "SPK Mixer"},
+ {"SPK DAC", "SPK-XSP Mono Volume", "SPK Mixer"},
+ {"SPK DAC", "SPK-VSP Mono Volume", "VSPIN"},
+ /* Loopback */
+ {"SPK DAC", "SPK-IP Mono Volume", "Input Left Capture"},
+ {"SPK DAC", "SPK-IP Mono Volume", "Input Right Capture"},
+
+ {"SPK Mixer", NULL, "SPK-ASP Mux"},
+ {"SPK Mixer", NULL, "SPK-XSP Mux"},
+
+ {"SPK-ASP Mux", "Left", "ASPINL"},
+ {"SPK-ASP Mux", "Mono Mix", "ASPINM"},
+ {"SPK-ASP Mux", "Right", "ASPINR"},
+
+ {"SPK-XSP Mux", "Left", "XSPINL"},
+ {"SPK-XSP Mux", "Mono Mix", "XSPINM"},
+ {"SPK-XSP Mux", "Right", "XSPINR"},
+
+ /* HP LineOUT Paths */
+ {"HPOUTA", NULL, "HP Amp"},
+ {"HPOUTB", NULL, "HP Amp"},
+ {"LINEOUTA", NULL, "LO Amp"},
+ {"LINEOUTB", NULL, "LO Amp"},
+
+ {"HP Amp", "Switch", "HL Left DAC"},
+ {"HP Amp", "Switch", "HL Right DAC"},
+ {"LO Amp", "Switch", "HL Left DAC"},
+ {"LO Amp", "Switch", "HL Right DAC"},
+
+ {"HL Left DAC", "HL-XSP Volume", "HL Left Mixer"},
+ {"HL Right DAC", "HL-XSP Volume", "HL Right Mixer"},
+ {"HL Left DAC", "HL-ASP Volume", "HL Left Mixer"},
+ {"HL Right DAC", "HL-ASP Volume", "HL Right Mixer"},
+ {"HL Left DAC", "HL-VSP Volume", "HL Left Mixer"},
+ {"HL Right DAC", "HL-VSP Volume", "HL Right Mixer"},
+ /* Loopback */
+ {"HL Left DAC", "HL-IP Volume", "HL Left Mixer"},
+ {"HL Right DAC", "HL-IP Volume", "HL Right Mixer"},
+ {"HL Left Mixer", NULL, "Input Left Capture"},
+ {"HL Right Mixer", NULL, "Input Right Capture"},
+
+ {"HL Left Mixer", NULL, "ASPINL"},
+ {"HL Right Mixer", NULL, "ASPINR"},
+ {"HL Left Mixer", NULL, "XSPINL"},
+ {"HL Right Mixer", NULL, "XSPINR"},
+ {"HL Left Mixer", NULL, "VSPIN"},
+ {"HL Right Mixer", NULL, "VSPIN"},
+
+ /* Capture Paths */
+ {"MIC1", NULL, "MIC1 Bias"},
+ {"PGA Left Mux", "Mic 1", "MIC1"},
+ {"MIC2", NULL, "MIC2 Bias"},
+ {"PGA Right Mux", "Mic 2", "MIC2"},
+
+ {"PGA Left Mux", "Line A", "LINEINA"},
+ {"PGA Right Mux", "Line B", "LINEINB"},
+
+ {"PGA Left", NULL, "PGA Left Mux"},
+ {"PGA Right", NULL, "PGA Right Mux"},
+
+ {"ADC Left", NULL, "PGA Left"},
+ {"ADC Right", NULL, "PGA Right"},
+
+ {"Input Left Capture", "ADC Left Input", "ADC Left"},
+ {"Input Right Capture", "ADC Right Input", "ADC Right"},
+ {"Input Left Capture", "DMIC Left Input", "DMIC Left"},
+ {"Input Right Capture", "DMIC Right Input", "DMIC Right"},
+
+ /* Audio Capture */
+ {"ASPL Output Mixer", NULL, "Input Left Capture"},
+ {"ASPR Output Mixer", NULL, "Input Right Capture"},
+
+ {"ASPOUTL", "ASP-IP Volume", "ASPL Output Mixer"},
+ {"ASPOUTR", "ASP-IP Volume", "ASPR Output Mixer"},
+
+ /* Auxillary Capture */
+ {"XSPL Output Mixer", NULL, "Input Left Capture"},
+ {"XSPR Output Mixer", NULL, "Input Right Capture"},
+
+ {"XSPOUTL", "XSP-IP Volume", "XSPL Output Mixer"},
+ {"XSPOUTR", "XSP-IP Volume", "XSPR Output Mixer"},
+
+ {"XSPOUTL", NULL, "XSPL Output Mixer"},
+ {"XSPOUTR", NULL, "XSPR Output Mixer"},
+
+ /* Voice Capture */
+ {"VSPL Output Mixer", NULL, "Input Left Capture"},
+ {"VSPR Output Mixer", NULL, "Input Left Capture"},
+
+ {"VSPOUTL", "VSP-IP Volume", "VSPL Output Mixer"},
+ {"VSPOUTR", "VSP-IP Volume", "VSPR Output Mixer"},
+
+ {"VSPOUTL", NULL, "VSPL Output Mixer"},
+ {"VSPOUTR", NULL, "VSPR Output Mixer"},
+};
+
+struct cs42l73_mclk_div {
+ u32 mclk;
+ u32 srate;
+ u8 mmcc;
+};
+
+static struct cs42l73_mclk_div cs42l73_mclk_coeffs[] = {
+ /* MCLK, Sample Rate, xMMCC[5:0] */
+ {5644800, 11025, 0x30},
+ {5644800, 22050, 0x20},
+ {5644800, 44100, 0x10},
+
+ {6000000, 8000, 0x39},
+ {6000000, 11025, 0x33},
+ {6000000, 12000, 0x31},
+ {6000000, 16000, 0x29},
+ {6000000, 22050, 0x23},
+ {6000000, 24000, 0x21},
+ {6000000, 32000, 0x19},
+ {6000000, 44100, 0x13},
+ {6000000, 48000, 0x11},
+
+ {6144000, 8000, 0x38},
+ {6144000, 12000, 0x30},
+ {6144000, 16000, 0x28},
+ {6144000, 24000, 0x20},
+ {6144000, 32000, 0x18},
+ {6144000, 48000, 0x10},
+
+ {6500000, 8000, 0x3C},
+ {6500000, 11025, 0x35},
+ {6500000, 12000, 0x34},
+ {6500000, 16000, 0x2C},
+ {6500000, 22050, 0x25},
+ {6500000, 24000, 0x24},
+ {6500000, 32000, 0x1C},
+ {6500000, 44100, 0x15},
+ {6500000, 48000, 0x14},
+
+ {6400000, 8000, 0x3E},
+ {6400000, 11025, 0x37},
+ {6400000, 12000, 0x36},
+ {6400000, 16000, 0x2E},
+ {6400000, 22050, 0x27},
+ {6400000, 24000, 0x26},
+ {6400000, 32000, 0x1E},
+ {6400000, 44100, 0x17},
+ {6400000, 48000, 0x16},
+};
+
+struct cs42l73_mclkx_div {
+ u32 mclkx;
+ u8 ratio;
+ u8 mclkdiv;
+};
+
+static struct cs42l73_mclkx_div cs42l73_mclkx_coeffs[] = {
+ {5644800, 1, 0}, /* 5644800 */
+ {6000000, 1, 0}, /* 6000000 */
+ {6144000, 1, 0}, /* 6144000 */
+ {11289600, 2, 2}, /* 5644800 */
+ {12288000, 2, 2}, /* 6144000 */
+ {12000000, 2, 2}, /* 6000000 */
+ {13000000, 2, 2}, /* 6500000 */
+ {19200000, 3, 3}, /* 6400000 */
+ {24000000, 4, 4}, /* 6000000 */
+ {26000000, 4, 4}, /* 6500000 */
+ {38400000, 6, 5} /* 6400000 */
+};
+
+static int cs42l73_get_mclkx_coeff(int mclkx)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cs42l73_mclkx_coeffs); i++) {
+ if (cs42l73_mclkx_coeffs[i].mclkx == mclkx)
+ return i;
+ }
+ return -EINVAL;
+}
+
+static int cs42l73_get_mclk_coeff(int mclk, int srate)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(cs42l73_mclk_coeffs); i++) {
+ if (cs42l73_mclk_coeffs[i].mclk == mclk &&
+ cs42l73_mclk_coeffs[i].srate == srate)
+ return i;
+ }
+ return -EINVAL;
+
+}
+
+static int cs42l73_set_mclk(struct snd_soc_dai *dai, unsigned int freq)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+
+ int mclkx_coeff;
+ u32 mclk = 0;
+ u8 dmmcc = 0;
+
+ /* MCLKX -> MCLK */
+ mclkx_coeff = cs42l73_get_mclkx_coeff(freq);
+
+ mclk = cs42l73_mclkx_coeffs[mclkx_coeff].mclkx /
+ cs42l73_mclkx_coeffs[mclkx_coeff].ratio;
+
+ dev_dbg(codec->dev, "MCLK%u %u <-> internal MCLK %u\n",
+ priv->mclksel + 1, cs42l73_mclkx_coeffs[mclkx_coeff].mclkx,
+ mclk);
+
+ dmmcc = (priv->mclksel << 4) |
+ (cs42l73_mclkx_coeffs[mclkx_coeff].mclkdiv << 1);
+
+ snd_soc_write(codec, CS42L73_DMMCC, dmmcc);
+
+ priv->sysclk = mclkx_coeff;
+ priv->mclk = mclk;
+
+ return 0;
+}
+
+static int cs42l73_set_sysclk(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+
+ switch (clk_id) {
+ case CS42L73_CLKID_MCLK1:
+ break;
+ case CS42L73_CLKID_MCLK2:
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if ((cs42l73_set_mclk(dai, freq)) < 0) {
+ dev_err(codec->dev, "Unable to set MCLK for dai %s\n",
+ dai->name);
+ return -EINVAL;
+ }
+
+ priv->mclksel = clk_id;
+
+ return 0;
+}
+
+static int cs42l73_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+ u8 id = codec_dai->id;
+ unsigned int inv, format;
+ u8 spc, mmcc;
+
+ spc = snd_soc_read(codec, CS42L73_SPC(id));
+ mmcc = snd_soc_read(codec, CS42L73_MMCC(id));
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ mmcc |= MS_MASTER;
+ break;
+
+ case SND_SOC_DAIFMT_CBS_CFS:
+ mmcc &= ~MS_MASTER;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ format = (fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ inv = (fmt & SND_SOC_DAIFMT_INV_MASK);
+
+ switch (format) {
+ case SND_SOC_DAIFMT_I2S:
+ spc &= ~SPDIF_PCM;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ case SND_SOC_DAIFMT_DSP_B:
+ if (mmcc & MS_MASTER) {
+ dev_err(codec->dev,
+ "PCM format in slave mode only\n");
+ return -EINVAL;
+ }
+ if (id == CS42L73_ASP) {
+ dev_err(codec->dev,
+ "PCM format is not supported on ASP port\n");
+ return -EINVAL;
+ }
+ spc |= SPDIF_PCM;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (spc & SPDIF_PCM) {
+ /* Clear PCM mode, clear PCM_BIT_ORDER bit for MSB->LSB */
+ spc &= ~(PCM_MODE_MASK | PCM_BIT_ORDER);
+ switch (format) {
+ case SND_SOC_DAIFMT_DSP_B:
+ if (inv == SND_SOC_DAIFMT_IB_IF)
+ spc |= PCM_MODE0;
+ if (inv == SND_SOC_DAIFMT_IB_NF)
+ spc |= PCM_MODE1;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ if (inv == SND_SOC_DAIFMT_IB_IF)
+ spc |= PCM_MODE1;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ priv->config[id].spc = spc;
+ priv->config[id].mmcc = mmcc;
+
+ return 0;
+}
+
+static u32 cs42l73_asrc_rates[] = {
+ 8000, 11025, 12000, 16000, 22050,
+ 24000, 32000, 44100, 48000
+};
+
+static unsigned int cs42l73_get_xspfs_coeff(u32 rate)
+{
+ int i;
+ for (i = 0; i < ARRAY_SIZE(cs42l73_asrc_rates); i++) {
+ if (cs42l73_asrc_rates[i] == rate)
+ return i + 1;
+ }
+ return 0; /* 0 = Don't know */
+}
+
+static void cs42l73_update_asrc(struct snd_soc_codec *codec, int id, int srate)
+{
+ u8 spfs = 0;
+
+ if (srate > 0)
+ spfs = cs42l73_get_xspfs_coeff(srate);
+
+ switch (id) {
+ case CS42L73_XSP:
+ snd_soc_update_bits(codec, CS42L73_VXSPFS, 0x0f, spfs);
+ break;
+ case CS42L73_ASP:
+ snd_soc_update_bits(codec, CS42L73_ASPC, 0x3c, spfs << 2);
+ break;
+ case CS42L73_VSP:
+ snd_soc_update_bits(codec, CS42L73_VXSPFS, 0xf0, spfs << 4);
+ break;
+ default:
+ break;
+ }
+}
+
+static int cs42l73_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct cs42l73_private *priv = snd_soc_codec_get_drvdata(codec);
+ int id = dai->id;
+ int mclk_coeff;
+ int srate = params_rate(params);
+
+ if (priv->config[id].mmcc & MS_MASTER) {
+ /* CS42L73 Master */
+ /* MCLK -> srate */
+ mclk_coeff =
+ cs42l73_get_mclk_coeff(priv->mclk, srate);
+
+ if (mclk_coeff < 0)
+ return -EINVAL;
+
+ dev_dbg(codec->dev,
+ "DAI[%d]: MCLK %u, srate %u, MMCC[5:0] = %x\n",
+ id, priv->mclk, srate,
+ cs42l73_mclk_coeffs[mclk_coeff].mmcc);
+
+ priv->config[id].mmcc &= 0xC0;
+ priv->config[id].mmcc |= cs42l73_mclk_coeffs[mclk_coeff].mmcc;
+ priv->config[id].spc &= 0xFC;
+ priv->config[id].spc |= MCK_SCLK_MCLK;
+ } else {
+ /* CS42L73 Slave */
+ priv->config[id].spc &= 0xFC;
+ priv->config[id].spc |= MCK_SCLK_64FS;
+ }
+ /* Update ASRCs */
+ priv->config[id].srate = srate;
+
+ snd_soc_write(codec, CS42L73_SPC(id), priv->config[id].spc);
+ snd_soc_write(codec, CS42L73_MMCC(id), priv->config[id].mmcc);
+
+ cs42l73_update_asrc(codec, id, srate);
+
+ return 0;
+}
+
+static int cs42l73_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 0);
+ snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 0);
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ regcache_cache_only(cs42l73->regmap, false);
+ regcache_sync(cs42l73->regmap);
+ }
+ snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_update_bits(codec, CS42L73_PWRCTL1, PDN, 1);
+ snd_soc_update_bits(codec, CS42L73_DMMCC, MCLKDIS, 1);
+ break;
+ }
+ codec->dapm.bias_level = level;
+ return 0;
+}
+
+static int cs42l73_set_tristate(struct snd_soc_dai *dai, int tristate)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int id = dai->id;
+
+ return snd_soc_update_bits(codec, CS42L73_SPC(id),
+ 0x7F, tristate << 7);
+}
+
+static struct snd_pcm_hw_constraint_list constraints_12_24 = {
+ .count = ARRAY_SIZE(cs42l73_asrc_rates),
+ .list = cs42l73_asrc_rates,
+};
+
+static int cs42l73_pcm_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ snd_pcm_hw_constraint_list(substream->runtime, 0,
+ SNDRV_PCM_HW_PARAM_RATE,
+ &constraints_12_24);
+ return 0;
+}
+
+/* SNDRV_PCM_RATE_KNOT -> 12000, 24000 Hz, limit with constraint list */
+#define CS42L73_RATES (SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_KNOT)
+
+
+#define CS42L73_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static const struct snd_soc_dai_ops cs42l73_ops = {
+ .startup = cs42l73_pcm_startup,
+ .hw_params = cs42l73_pcm_hw_params,
+ .set_fmt = cs42l73_set_dai_fmt,
+ .set_sysclk = cs42l73_set_sysclk,
+ .set_tristate = cs42l73_set_tristate,
+};
+
+static struct snd_soc_dai_driver cs42l73_dai[] = {
+ {
+ .name = "cs42l73-xsp",
+ .id = CS42L73_XSP,
+ .playback = {
+ .stream_name = "XSP Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS42L73_RATES,
+ .formats = CS42L73_FORMATS,
+ },
+ .capture = {
+ .stream_name = "XSP Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS42L73_RATES,
+ .formats = CS42L73_FORMATS,
+ },
+ .ops = &cs42l73_ops,
+ .symmetric_rates = 1,
+ },
+ {
+ .name = "cs42l73-asp",
+ .id = CS42L73_ASP,
+ .playback = {
+ .stream_name = "ASP Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = CS42L73_RATES,
+ .formats = CS42L73_FORMATS,
+ },
+ .capture = {
+ .stream_name = "ASP Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = CS42L73_RATES,
+ .formats = CS42L73_FORMATS,
+ },
+ .ops = &cs42l73_ops,
+ .symmetric_rates = 1,
+ },
+ {
+ .name = "cs42l73-vsp",
+ .id = CS42L73_VSP,
+ .playback = {
+ .stream_name = "VSP Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS42L73_RATES,
+ .formats = CS42L73_FORMATS,
+ },
+ .capture = {
+ .stream_name = "VSP Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = CS42L73_RATES,
+ .formats = CS42L73_FORMATS,
+ },
+ .ops = &cs42l73_ops,
+ .symmetric_rates = 1,
+ }
+};
+
+static int cs42l73_suspend(struct snd_soc_codec *codec)
+{
+ cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ return 0;
+}
+
+static int cs42l73_resume(struct snd_soc_codec *codec)
+{
+ cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+}
+
+static int cs42l73_probe(struct snd_soc_codec *codec)
+{
+ int ret;
+ struct cs42l73_private *cs42l73 = snd_soc_codec_get_drvdata(codec);
+
+ codec->control_data = cs42l73->regmap;
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ regcache_cache_only(cs42l73->regmap, true);
+
+ cs42l73_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ cs42l73->mclksel = CS42L73_CLKID_MCLK1; /* MCLK1 as master clk */
+ cs42l73->mclk = 0;
+
+ return ret;
+}
+
+static int cs42l73_remove(struct snd_soc_codec *codec)
+{
+ cs42l73_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static struct snd_soc_codec_driver soc_codec_dev_cs42l73 = {
+ .probe = cs42l73_probe,
+ .remove = cs42l73_remove,
+ .suspend = cs42l73_suspend,
+ .resume = cs42l73_resume,
+ .set_bias_level = cs42l73_set_bias_level,
+
+ .dapm_widgets = cs42l73_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(cs42l73_dapm_widgets),
+ .dapm_routes = cs42l73_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(cs42l73_audio_map),
+
+ .controls = cs42l73_snd_controls,
+ .num_controls = ARRAY_SIZE(cs42l73_snd_controls),
+};
+
+static struct regmap_config cs42l73_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = CS42L73_MAX_REGISTER,
+ .reg_defaults = cs42l73_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(cs42l73_reg_defaults),
+ .volatile_reg = cs42l73_volatile_register,
+ .readable_reg = cs42l73_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static __devinit int cs42l73_i2c_probe(struct i2c_client *i2c_client,
+ const struct i2c_device_id *id)
+{
+ struct cs42l73_private *cs42l73;
+ int ret;
+ unsigned int devid = 0;
+ unsigned int reg;
+
+ cs42l73 = devm_kzalloc(&i2c_client->dev, sizeof(struct cs42l73_private),
+ GFP_KERNEL);
+ if (!cs42l73) {
+ dev_err(&i2c_client->dev, "could not allocate codec\n");
+ return -ENOMEM;
+ }
+
+ i2c_set_clientdata(i2c_client, cs42l73);
+
+ cs42l73->regmap = regmap_init_i2c(i2c_client, &cs42l73_regmap);
+ if (IS_ERR(cs42l73->regmap)) {
+ ret = PTR_ERR(cs42l73->regmap);
+ dev_err(&i2c_client->dev, "regmap_init() failed: %d\n", ret);
+ goto err;
+ }
+ /* initialize codec */
+ ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_AB, &reg);
+ devid = (reg & 0xFF) << 12;
+
+ ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_CD, &reg);
+ devid |= (reg & 0xFF) << 4;
+
+ ret = regmap_read(cs42l73->regmap, CS42L73_DEVID_E, &reg);
+ devid |= (reg & 0xF0) >> 4;
+
+
+ if (devid != CS42L73_DEVID) {
+ ret = -ENODEV;
+ dev_err(&i2c_client->dev,
+ "CS42L73 Device ID (%X). Expected %X\n",
+ devid, CS42L73_DEVID);
+ goto err_regmap;
+ }
+
+ ret = regmap_read(cs42l73->regmap, CS42L73_REVID, &reg);
+ if (ret < 0) {
+ dev_err(&i2c_client->dev, "Get Revision ID failed\n");
+ goto err_regmap;
+ }
+
+ dev_info(&i2c_client->dev,
+ "Cirrus Logic CS42L73, Revision: %02X\n", reg & 0xFF);
+
+ regcache_cache_only(cs42l73->regmap, true);
+
+ ret = snd_soc_register_codec(&i2c_client->dev,
+ &soc_codec_dev_cs42l73, cs42l73_dai,
+ ARRAY_SIZE(cs42l73_dai));
+ if (ret < 0)
+ goto err_regmap;
+ return 0;
+
+err_regmap:
+ regmap_exit(cs42l73->regmap);
+
+err:
+ return ret;
+}
+
+static __devexit int cs42l73_i2c_remove(struct i2c_client *client)
+{
+ struct cs42l73_private *cs42l73 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ regmap_exit(cs42l73->regmap);
+
+ return 0;
+}
+
+static const struct i2c_device_id cs42l73_id[] = {
+ {"cs42l73", 0},
+ {}
+};
+
+MODULE_DEVICE_TABLE(i2c, cs42l73_id);
+
+static struct i2c_driver cs42l73_i2c_driver = {
+ .driver = {
+ .name = "cs42l73",
+ .owner = THIS_MODULE,
+ },
+ .id_table = cs42l73_id,
+ .probe = cs42l73_i2c_probe,
+ .remove = __devexit_p(cs42l73_i2c_remove),
+
+};
+
+static int __init cs42l73_modinit(void)
+{
+ int ret;
+ ret = i2c_add_driver(&cs42l73_i2c_driver);
+ if (ret != 0) {
+ pr_err("Failed to register CS42L73 I2C driver: %d\n", ret);
+ return ret;
+ }
+ return 0;
+}
+
+module_init(cs42l73_modinit);
+
+static void __exit cs42l73_exit(void)
+{
+ i2c_del_driver(&cs42l73_i2c_driver);
+}
+
+module_exit(cs42l73_exit);
+
+MODULE_DESCRIPTION("ASoC CS42L73 driver");
+MODULE_AUTHOR("Georgi Vlaev, Nucleus Systems Ltd, <joe@nucleusys.com>");
+MODULE_AUTHOR("Brian Austin, Cirrus Logic Inc, <brian.austin@cirrus.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs42l73.h b/sound/soc/codecs/cs42l73.h
new file mode 100644
index 000000000000..f30a4c4d62e6
--- /dev/null
+++ b/sound/soc/codecs/cs42l73.h
@@ -0,0 +1,227 @@
+/*
+ * ALSA SoC CS42L73 codec driver
+ *
+ * Copyright 2011 Cirrus Logic, Inc.
+ *
+ * Author: Georgi Vlaev <joe@nucleusys.com>
+ * Brian Austin <brian.austin@cirrus.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __CS42L73_H__
+#define __CS42L73_H__
+
+/* I2C Registers */
+/* I2C Address: 1001010[R/W] - 10010100 = 0x94(Write); 10010101 = 0x95(Read) */
+#define CS42L73_CHIP_ID 0x4a
+#define CS42L73_DEVID_AB 0x01 /* Device ID A & B [RO]. */
+#define CS42L73_DEVID_CD 0x02 /* Device ID C & D [RO]. */
+#define CS42L73_DEVID_E 0x03 /* Device ID E [RO]. */
+#define CS42L73_REVID 0x05 /* Revision ID [RO]. */
+#define CS42L73_PWRCTL1 0x06 /* Power Control 1. */
+#define CS42L73_PWRCTL2 0x07 /* Power Control 2. */
+#define CS42L73_PWRCTL3 0x08 /* Power Control 3. */
+#define CS42L73_CPFCHC 0x09 /* Charge Pump Freq. Class H Ctl. */
+#define CS42L73_OLMBMSDC 0x0A /* Output Load, MIC Bias, MIC2 SDT */
+#define CS42L73_DMMCC 0x0B /* Digital MIC & Master Clock Ctl. */
+#define CS42L73_XSPC 0x0C /* Auxiliary Serial Port (XSP) Ctl. */
+#define CS42L73_XSPMMCC 0x0D /* XSP Master Mode Clocking Control. */
+#define CS42L73_ASPC 0x0E /* Audio Serial Port (ASP) Control. */
+#define CS42L73_ASPMMCC 0x0F /* ASP Master Mode Clocking Control. */
+#define CS42L73_VSPC 0x10 /* Voice Serial Port (VSP) Control. */
+#define CS42L73_VSPMMCC 0x11 /* VSP Master Mode Clocking Control. */
+#define CS42L73_VXSPFS 0x12 /* VSP & XSP Sample Rate. */
+#define CS42L73_MIOPC 0x13 /* Misc. Input & Output Path Control. */
+#define CS42L73_ADCIPC 0x14 /* ADC/IP Control. */
+#define CS42L73_MICAPREPGAAVOL 0x15 /* MIC 1 [A] PreAmp, PGAA Vol. */
+#define CS42L73_MICBPREPGABVOL 0x16 /* MIC 2 [B] PreAmp, PGAB Vol. */
+#define CS42L73_IPADVOL 0x17 /* Input Pat7h A Digital Volume. */
+#define CS42L73_IPBDVOL 0x18 /* Input Path B Digital Volume. */
+#define CS42L73_PBDC 0x19 /* Playback Digital Control. */
+#define CS42L73_HLADVOL 0x1A /* HP/Line A Out Digital Vol. */
+#define CS42L73_HLBDVOL 0x1B /* HP/Line B Out Digital Vol. */
+#define CS42L73_SPKDVOL 0x1C /* Spkphone Out [A] Digital Vol. */
+#define CS42L73_ESLDVOL 0x1D /* Ear/Spkphone LO [B] Digital */
+#define CS42L73_HPAAVOL 0x1E /* HP A Analog Volume. */
+#define CS42L73_HPBAVOL 0x1F /* HP B Analog Volume. */
+#define CS42L73_LOAAVOL 0x20 /* Line Out A Analog Volume. */
+#define CS42L73_LOBAVOL 0x21 /* Line Out B Analog Volume. */
+#define CS42L73_STRINV 0x22 /* Stereo Input Path Adv. Vol. */
+#define CS42L73_XSPINV 0x23 /* Auxiliary Port Input Advisory Vol. */
+#define CS42L73_ASPINV 0x24 /* Audio Port Input Advisory Vol. */
+#define CS42L73_VSPINV 0x25 /* Voice Port Input Advisory Vol. */
+#define CS42L73_LIMARATEHL 0x26 /* Lmtr Attack Rate HP/Line. */
+#define CS42L73_LIMRRATEHL 0x27 /* Lmtr Ctl, Rel.Rate HP/Line. */
+#define CS42L73_LMAXHL 0x28 /* Lmtr Thresholds HP/Line. */
+#define CS42L73_LIMARATESPK 0x29 /* Lmtr Attack Rate Spkphone [A]. */
+#define CS42L73_LIMRRATESPK 0x2A /* Lmtr Ctl,Release Rate Spk. [A]. */
+#define CS42L73_LMAXSPK 0x2B /* Lmtr Thresholds Spkphone [A]. */
+#define CS42L73_LIMARATEESL 0x2C /* Lmtr Attack Rate */
+#define CS42L73_LIMRRATEESL 0x2D /* Lmtr Ctl,Release Rate */
+#define CS42L73_LMAXESL 0x2E /* Lmtr Thresholds */
+#define CS42L73_ALCARATE 0x2F /* ALC Enable, Attack Rate AB. */
+#define CS42L73_ALCRRATE 0x30 /* ALC Release Rate AB. */
+#define CS42L73_ALCMINMAX 0x31 /* ALC Thresholds AB. */
+#define CS42L73_NGCAB 0x32 /* Noise Gate Ctl AB. */
+#define CS42L73_ALCNGMC 0x33 /* ALC & Noise Gate Misc Ctl. */
+#define CS42L73_MIXERCTL 0x34 /* Mixer Control. */
+#define CS42L73_HLAIPAA 0x35 /* HP/LO Left Mixer: L. */
+#define CS42L73_HLBIPBA 0x36 /* HP/LO Right Mixer: R. */
+#define CS42L73_HLAXSPAA 0x37 /* HP/LO Left Mixer: XSP L */
+#define CS42L73_HLBXSPBA 0x38 /* HP/LO Right Mixer: XSP R */
+#define CS42L73_HLAASPAA 0x39 /* HP/LO Left Mixer: ASP L */
+#define CS42L73_HLBASPBA 0x3A /* HP/LO Right Mixer: ASP R */
+#define CS42L73_HLAVSPMA 0x3B /* HP/LO Left Mixer: VSP. */
+#define CS42L73_HLBVSPMA 0x3C /* HP/LO Right Mixer: VSP */
+#define CS42L73_XSPAIPAA 0x3D /* XSP Left Mixer: Left */
+#define CS42L73_XSPBIPBA 0x3E /* XSP Rt. Mixer: Right */
+#define CS42L73_XSPAXSPAA 0x3F /* XSP Left Mixer: XSP L */
+#define CS42L73_XSPBXSPBA 0x40 /* XSP Rt. Mixer: XSP R */
+#define CS42L73_XSPAASPAA 0x41 /* XSP Left Mixer: ASP L */
+#define CS42L73_XSPAASPBA 0x42 /* XSP Rt. Mixer: ASP R */
+#define CS42L73_XSPAVSPMA 0x43 /* XSP Left Mixer: VSP */
+#define CS42L73_XSPBVSPMA 0x44 /* XSP Rt. Mixer: VSP */
+#define CS42L73_ASPAIPAA 0x45 /* ASP Left Mixer: Left */
+#define CS42L73_ASPBIPBA 0x46 /* ASP Rt. Mixer: Right */
+#define CS42L73_ASPAXSPAA 0x47 /* ASP Left Mixer: XSP L */
+#define CS42L73_ASPBXSPBA 0x48 /* ASP Rt. Mixer: XSP R */
+#define CS42L73_ASPAASPAA 0x49 /* ASP Left Mixer: ASP L */
+#define CS42L73_ASPBASPBA 0x4A /* ASP Rt. Mixer: ASP R */
+#define CS42L73_ASPAVSPMA 0x4B /* ASP Left Mixer: VSP */
+#define CS42L73_ASPBVSPMA 0x4C /* ASP Rt. Mixer: VSP */
+#define CS42L73_VSPAIPAA 0x4D /* VSP Left Mixer: Left */
+#define CS42L73_VSPBIPBA 0x4E /* VSP Rt. Mixer: Right */
+#define CS42L73_VSPAXSPAA 0x4F /* VSP Left Mixer: XSP L */
+#define CS42L73_VSPBXSPBA 0x50 /* VSP Rt. Mixer: XSP R */
+#define CS42L73_VSPAASPAA 0x51 /* VSP Left Mixer: ASP Left */
+#define CS42L73_VSPBASPBA 0x52 /* VSP Rt. Mixer: ASP Right */
+#define CS42L73_VSPAVSPMA 0x53 /* VSP Left Mixer: VSP */
+#define CS42L73_VSPBVSPMA 0x54 /* VSP Rt. Mixer: VSP */
+#define CS42L73_MMIXCTL 0x55 /* Mono Mixer Controls. */
+#define CS42L73_SPKMIPMA 0x56 /* SPK Mono Mixer: In. Path */
+#define CS42L73_SPKMXSPA 0x57 /* SPK Mono Mixer: XSP Mono/L/R Att. */
+#define CS42L73_SPKMASPA 0x58 /* SPK Mono Mixer: ASP Mono/L/R Att. */
+#define CS42L73_SPKMVSPMA 0x59 /* SPK Mono Mixer: VSP Mono Atten. */
+#define CS42L73_ESLMIPMA 0x5A /* Ear/SpLO Mono Mixer: */
+#define CS42L73_ESLMXSPA 0x5B /* Ear/SpLO Mono Mixer: XSP */
+#define CS42L73_ESLMASPA 0x5C /* Ear/SpLO Mono Mixer: ASP */
+#define CS42L73_ESLMVSPMA 0x5D /* Ear/SpLO Mono Mixer: VSP */
+#define CS42L73_IM1 0x5E /* Interrupt Mask 1. */
+#define CS42L73_IM2 0x5F /* Interrupt Mask 2. */
+#define CS42L73_IS1 0x60 /* Interrupt Status 1 [RO]. */
+#define CS42L73_IS2 0x61 /* Interrupt Status 2 [RO]. */
+#define CS42L73_MAX_REGISTER 0x61 /* Total Registers */
+/* Bitfield Definitions */
+
+/* CS42L73_PWRCTL1 */
+#define PDN_ADCB (1 << 7)
+#define PDN_DMICB (1 << 6)
+#define PDN_ADCA (1 << 5)
+#define PDN_DMICA (1 << 4)
+#define PDN_LDO (1 << 2)
+#define DISCHG_FILT (1 << 1)
+#define PDN (1 << 0)
+
+/* CS42L73_PWRCTL2 */
+#define PDN_MIC2_BIAS (1 << 7)
+#define PDN_MIC1_BIAS (1 << 6)
+#define PDN_VSP (1 << 4)
+#define PDN_ASP_SDOUT (1 << 3)
+#define PDN_ASP_SDIN (1 << 2)
+#define PDN_XSP_SDOUT (1 << 1)
+#define PDN_XSP_SDIN (1 << 0)
+
+/* CS42L73_PWRCTL3 */
+#define PDN_THMS (1 << 5)
+#define PDN_SPKLO (1 << 4)
+#define PDN_EAR (1 << 3)
+#define PDN_SPK (1 << 2)
+#define PDN_LO (1 << 1)
+#define PDN_HP (1 << 0)
+
+/* Thermal Overload Detect. Requires interrupt ... */
+#define THMOVLD_150C 0
+#define THMOVLD_132C 1
+#define THMOVLD_115C 2
+#define THMOVLD_098C 3
+
+
+/* CS42L73_ASPC, CS42L73_XSPC, CS42L73_VSPC */
+#define SP_3ST (1 << 7)
+#define SPDIF_I2S (0 << 6)
+#define SPDIF_PCM (1 << 6)
+#define PCM_MODE0 (0 << 4)
+#define PCM_MODE1 (1 << 4)
+#define PCM_MODE2 (2 << 4)
+#define PCM_MODE_MASK (3 << 4)
+#define PCM_BIT_ORDER (1 << 3)
+#define MCK_SCLK_64FS (0 << 0)
+#define MCK_SCLK_MCLK (2 << 0)
+#define MCK_SCLK_PREMCLK (3 << 0)
+
+/* CS42L73_xSPMMCC */
+#define MS_MASTER (1 << 7)
+
+
+/* CS42L73_DMMCC */
+#define MCLKDIS (1 << 0)
+#define MCLKSEL_MCLK2 (1 << 4)
+#define MCLKSEL_MCLK1 (0 << 4)
+
+/* CS42L73 MCLK derived from MCLK1 or MCLK2 */
+#define CS42L73_CLKID_MCLK1 0
+#define CS42L73_CLKID_MCLK2 1
+
+#define CS42L73_MCLKXDIV 0
+#define CS42L73_MMCCDIV 1
+
+#define CS42L73_XSP 0
+#define CS42L73_ASP 1
+#define CS42L73_VSP 2
+
+/* IS1, IM1 */
+#define MIC2_SDET (1 << 6)
+#define THMOVLD (1 << 4)
+#define DIGMIXOVFL (1 << 3)
+#define IPBOVFL (1 << 1)
+#define IPAOVFL (1 << 0)
+
+/* Analog Softramp */
+#define ANLGOSFT (1 << 0)
+
+/* HP A/B Analog Mute */
+#define HPA_MUTE (1 << 7)
+/* LO A/B Analog Mute */
+#define LOA_MUTE (1 << 7)
+/* Digital Mute */
+#define HLAD_MUTE (1 << 0)
+#define HLBD_MUTE (1 << 1)
+#define SPKD_MUTE (1 << 2)
+#define ESLD_MUTE (1 << 3)
+
+/* Misc defines for codec */
+#define CS42L73_RESET_GPIO 143
+
+#define CS42L73_DEVID 0x00042A73
+#define CS42L73_MCLKX_MIN 5644800
+#define CS42L73_MCLKX_MAX 38400000
+
+#define CS42L73_SPC(id) (CS42L73_XSPC + (id << 1))
+#define CS42L73_MMCC(id) (CS42L73_XSPMMCC + (id << 1))
+#define CS42L73_SPFS(id) ((id == CS42L73_ASP) ? CS42L73_ASPC : CS42L73_VXSPFS)
+
+#endif /* __CS42L73_H__ */
diff --git a/sound/soc/codecs/cx20442.c b/sound/soc/codecs/cx20442.c
index d68ea532cc7f..d5fd00a64748 100644
--- a/sound/soc/codecs/cx20442.c
+++ b/sound/soc/codecs/cx20442.c
@@ -15,6 +15,8 @@
#include <linux/tty.h>
#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
#include <sound/core.h>
#include <sound/initval.h>
@@ -24,8 +26,8 @@
struct cx20442_priv {
- enum snd_soc_control_type control_type;
void *control_data;
+ struct regulator *por;
};
#define CX20442_PM 0x0
@@ -323,6 +325,38 @@ static struct snd_soc_dai_driver cx20442_dai = {
},
};
+static int cx20442_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct cx20442_priv *cx20442 = snd_soc_codec_get_drvdata(codec);
+ int err = 0;
+
+ switch (level) {
+ case SND_SOC_BIAS_PREPARE:
+ if (codec->dapm.bias_level != SND_SOC_BIAS_STANDBY)
+ break;
+ if (IS_ERR(cx20442->por))
+ err = PTR_ERR(cx20442->por);
+ else
+ err = regulator_enable(cx20442->por);
+ break;
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level != SND_SOC_BIAS_PREPARE)
+ break;
+ if (IS_ERR(cx20442->por))
+ err = PTR_ERR(cx20442->por);
+ else
+ err = regulator_disable(cx20442->por);
+ break;
+ default:
+ break;
+ }
+ if (!err)
+ codec->dapm.bias_level = level;
+
+ return err;
+}
+
static int cx20442_codec_probe(struct snd_soc_codec *codec)
{
struct cx20442_priv *cx20442;
@@ -330,9 +364,13 @@ static int cx20442_codec_probe(struct snd_soc_codec *codec)
cx20442 = kzalloc(sizeof(struct cx20442_priv), GFP_KERNEL);
if (cx20442 == NULL)
return -ENOMEM;
- snd_soc_codec_set_drvdata(codec, cx20442);
+ cx20442->por = regulator_get(codec->dev, "POR");
+ if (IS_ERR(cx20442->por))
+ dev_warn(codec->dev, "failed to get the regulator");
cx20442->control_data = NULL;
+
+ snd_soc_codec_set_drvdata(codec, cx20442);
codec->hw_write = NULL;
codec->card->pop_time = 0;
@@ -349,6 +387,12 @@ static int cx20442_codec_remove(struct snd_soc_codec *codec)
tty_hangup(tty);
}
+ if (!IS_ERR(cx20442->por)) {
+ /* should be already in STANDBY, hence disabled */
+ regulator_put(cx20442->por);
+ }
+
+ snd_soc_codec_set_drvdata(codec, NULL);
kfree(cx20442);
return 0;
}
@@ -358,6 +402,7 @@ static const u8 cx20442_reg;
static struct snd_soc_codec_driver cx20442_codec_dev = {
.probe = cx20442_codec_probe,
.remove = cx20442_codec_remove,
+ .set_bias_level = cx20442_set_bias_level,
.reg_cache_default = &cx20442_reg,
.reg_cache_size = 1,
.reg_word_size = sizeof(u8),
@@ -390,17 +435,7 @@ static struct platform_driver cx20442_platform_driver = {
.remove = __exit_p(cx20442_platform_remove),
};
-static int __init cx20442_init(void)
-{
- return platform_driver_register(&cx20442_platform_driver);
-}
-module_init(cx20442_init);
-
-static void __exit cx20442_exit(void)
-{
- platform_driver_unregister(&cx20442_platform_driver);
-}
-module_exit(cx20442_exit);
+module_platform_driver(cx20442_platform_driver);
MODULE_DESCRIPTION("ASoC CX20442-11 voice modem codec driver");
MODULE_AUTHOR("Janusz Krzysztofik");
diff --git a/sound/soc/codecs/da7210.c b/sound/soc/codecs/da7210.c
index 92fd9d7a9221..7843711729bc 100644
--- a/sound/soc/codecs/da7210.c
+++ b/sound/soc/codecs/da7210.c
@@ -17,8 +17,9 @@
#include <linux/delay.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -26,23 +27,41 @@
#include <sound/tlv.h>
/* DA7210 register space */
+#define DA7210_CONTROL 0x01
#define DA7210_STATUS 0x02
#define DA7210_STARTUP1 0x03
+#define DA7210_STARTUP2 0x04
+#define DA7210_STARTUP3 0x05
#define DA7210_MIC_L 0x07
#define DA7210_MIC_R 0x08
+#define DA7210_AUX1_L 0x09
+#define DA7210_AUX1_R 0x0A
+#define DA7210_AUX2 0x0B
+#define DA7210_IN_GAIN 0x0C
#define DA7210_INMIX_L 0x0D
#define DA7210_INMIX_R 0x0E
#define DA7210_ADC_HPF 0x0F
#define DA7210_ADC 0x10
+#define DA7210_ADC_EQ1_2 0X11
+#define DA7210_ADC_EQ3_4 0x12
+#define DA7210_ADC_EQ5 0x13
#define DA7210_DAC_HPF 0x14
#define DA7210_DAC_L 0x15
#define DA7210_DAC_R 0x16
#define DA7210_DAC_SEL 0x17
+#define DA7210_SOFTMUTE 0x18
+#define DA7210_DAC_EQ1_2 0x19
+#define DA7210_DAC_EQ3_4 0x1A
+#define DA7210_DAC_EQ5 0x1B
#define DA7210_OUTMIX_L 0x1C
#define DA7210_OUTMIX_R 0x1D
+#define DA7210_OUT1_L 0x1E
+#define DA7210_OUT1_R 0x1F
+#define DA7210_OUT2 0x20
#define DA7210_HP_L_VOL 0x21
#define DA7210_HP_R_VOL 0x22
#define DA7210_HP_CFG 0x23
+#define DA7210_ZERO_CROSS 0x24
#define DA7210_DAI_SRC_SEL 0x25
#define DA7210_DAI_CFG1 0x26
#define DA7210_DAI_CFG3 0x28
@@ -50,6 +69,12 @@
#define DA7210_PLL_DIV2 0x2A
#define DA7210_PLL_DIV3 0x2B
#define DA7210_PLL 0x2C
+#define DA7210_ALC_MAX 0x83
+#define DA7210_ALC_MIN 0x84
+#define DA7210_ALC_NOIS 0x85
+#define DA7210_ALC_ATT 0x86
+#define DA7210_ALC_REL 0x87
+#define DA7210_ALC_DEL 0x88
#define DA7210_A_HID_UNLOCK 0x8A
#define DA7210_A_TEST_UNLOCK 0x8B
#define DA7210_A_PLL1 0x90
@@ -72,6 +97,7 @@
#define DA7210_IN_R_EN (1 << 7)
/* ADC bit fields */
+#define DA7210_ADC_ALC_EN (1 << 0)
#define DA7210_ADC_L_EN (1 << 3)
#define DA7210_ADC_R_EN (1 << 7)
@@ -105,12 +131,17 @@
/* DAI_CFG1 bit fields */
#define DA7210_DAI_WORD_S16_LE (0 << 0)
+#define DA7210_DAI_WORD_S20_3LE (1 << 0)
#define DA7210_DAI_WORD_S24_LE (2 << 0)
+#define DA7210_DAI_WORD_S32_LE (3 << 0)
#define DA7210_DAI_FLEN_64BIT (1 << 2)
+#define DA7210_DAI_MODE_SLAVE (0 << 7)
#define DA7210_DAI_MODE_MASTER (1 << 7)
/* DAI_CFG3 bit fields */
#define DA7210_DAI_FORMAT_I2SMODE (0 << 0)
+#define DA7210_DAI_FORMAT_LEFT_J (1 << 0)
+#define DA7210_DAI_FORMAT_RIGHT_J (2 << 0)
#define DA7210_DAI_OE (1 << 3)
#define DA7210_DAI_EN (1 << 7)
@@ -133,6 +164,48 @@
#define DA7210_PLL_FS_96000 (0xF << 0)
#define DA7210_PLL_EN (0x1 << 7)
+/* SOFTMUTE bit fields */
+#define DA7210_RAMP_EN (1 << 6)
+
+/* CONTROL bit fields */
+#define DA7210_NOISE_SUP_EN (1 << 3)
+
+/* IN_GAIN bit fields */
+#define DA7210_INPGA_L_VOL (0x0F << 0)
+#define DA7210_INPGA_R_VOL (0xF0 << 0)
+
+/* ZERO_CROSS bit fields */
+#define DA7210_AUX1_L_ZC (1 << 0)
+#define DA7210_AUX1_R_ZC (1 << 1)
+#define DA7210_HP_L_ZC (1 << 6)
+#define DA7210_HP_R_ZC (1 << 7)
+
+/* AUX1_L bit fields */
+#define DA7210_AUX1_L_VOL (0x3F << 0)
+#define DA7210_AUX1_L_EN (1 << 7)
+
+/* AUX1_R bit fields */
+#define DA7210_AUX1_R_VOL (0x3F << 0)
+#define DA7210_AUX1_R_EN (1 << 7)
+
+/* AUX2 bit fields */
+#define DA7210_AUX2_EN (1 << 3)
+
+/* Minimum INPGA and AUX1 volume to enable noise suppression */
+#define DA7210_INPGA_MIN_VOL_NS 0x0A /* 10.5dB */
+#define DA7210_AUX1_MIN_VOL_NS 0x35 /* 6dB */
+
+/* OUT1_L bit fields */
+#define DA7210_OUT1_L_EN (1 << 7)
+
+/* OUT1_R bit fields */
+#define DA7210_OUT1_R_EN (1 << 7)
+
+/* OUT2 bit fields */
+#define DA7210_OUT2_OUTMIX_R (1 << 5)
+#define DA7210_OUT2_OUTMIX_L (1 << 6)
+#define DA7210_OUT2_EN (1 << 7)
+
#define DA7210_VERSION "0.0.1"
/*
@@ -144,116 +217,493 @@
* mute : 0x10
* reserved : 0x00 - 0x0F
*
- * ** FIXME **
- *
* Reserved area are considered as "mute".
- * -> min = -79.5 dB
*/
-static const DECLARE_TLV_DB_SCALE(hp_out_tlv, -7950, 150, 1);
+static const unsigned int hp_out_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
+ /* -54 dB to +15 dB */
+ 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0),
+};
-static const struct snd_kcontrol_new da7210_snd_controls[] = {
+static const unsigned int lineout_vol_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
+ /* -54dB to 15dB */
+ 0x11, 0x3f, TLV_DB_SCALE_ITEM(-5400, 150, 0)
+};
- SOC_DOUBLE_R_TLV("HeadPhone Playback Volume",
- DA7210_HP_L_VOL, DA7210_HP_R_VOL,
- 0, 0x3F, 0, hp_out_tlv),
+static const unsigned int mono_vol_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0x0, 0x2, TLV_DB_SCALE_ITEM(-1800, 0, 1),
+ /* -18dB to 6dB */
+ 0x3, 0x7, TLV_DB_SCALE_ITEM(-1800, 600, 0)
};
-/* Codec private data */
-struct da7210_priv {
- enum snd_soc_control_type control_type;
- void *control_data;
+static const unsigned int aux1_vol_tlv[] = {
+ TLV_DB_RANGE_HEAD(2),
+ 0x0, 0x10, TLV_DB_SCALE_ITEM(TLV_DB_GAIN_MUTE, 0, 1),
+ /* -48dB to 21dB */
+ 0x11, 0x3f, TLV_DB_SCALE_ITEM(-4800, 150, 0)
};
-/*
- * Register cache
- */
-static const u8 da7210_reg[] = {
- 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R0 - R7 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, /* R8 - RF */
- 0x00, 0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x54, /* R10 - R17 */
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R18 - R1F */
- 0x00, 0x00, 0x00, 0x02, 0x00, 0x76, 0x00, 0x00, /* R20 - R27 */
- 0x04, 0x00, 0x00, 0x30, 0x2A, 0x00, 0x40, 0x00, /* R28 - R2F */
- 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, /* R30 - R37 */
- 0x40, 0x00, 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, /* R38 - R3F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R40 - R4F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R48 - R4F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R50 - R57 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R58 - R5F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R60 - R67 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R68 - R6F */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* R70 - R77 */
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x54, 0x54, 0x00, /* R78 - R7F */
- 0x00, 0x00, 0x2C, 0x00, 0x00, 0x00, 0x00, 0x00, /* R80 - R87 */
- 0x00, /* R88 */
+static const DECLARE_TLV_DB_SCALE(eq_gain_tlv, -1050, 150, 0);
+static const DECLARE_TLV_DB_SCALE(adc_eq_master_gain_tlv, -1800, 600, 1);
+static const DECLARE_TLV_DB_SCALE(dac_gain_tlv, -7725, 75, 0);
+static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, -600, 600, 0);
+static const DECLARE_TLV_DB_SCALE(aux2_vol_tlv, -600, 600, 0);
+static const DECLARE_TLV_DB_SCALE(inpga_gain_tlv, -450, 150, 0);
+
+/* ADC and DAC high pass filter f0 value */
+static const char * const da7210_hpf_cutoff_txt[] = {
+ "Fs/8192*pi", "Fs/4096*pi", "Fs/2048*pi", "Fs/1024*pi"
};
-/*
- * Read da7210 register cache
- */
-static inline u32 da7210_read_reg_cache(struct snd_soc_codec *codec, u32 reg)
-{
- u8 *cache = codec->reg_cache;
- BUG_ON(reg >= ARRAY_SIZE(da7210_reg));
- return cache[reg];
-}
+static const struct soc_enum da7210_dac_hpf_cutoff =
+ SOC_ENUM_SINGLE(DA7210_DAC_HPF, 0, 4, da7210_hpf_cutoff_txt);
-/*
- * Write to the da7210 register space
- */
-static int da7210_write(struct snd_soc_codec *codec, u32 reg, u32 value)
-{
- u8 *cache = codec->reg_cache;
- u8 data[2];
+static const struct soc_enum da7210_adc_hpf_cutoff =
+ SOC_ENUM_SINGLE(DA7210_ADC_HPF, 0, 4, da7210_hpf_cutoff_txt);
- BUG_ON(codec->driver->volatile_register);
+/* ADC and DAC voice (8kHz) high pass cutoff value */
+static const char * const da7210_vf_cutoff_txt[] = {
+ "2.5Hz", "25Hz", "50Hz", "100Hz", "150Hz", "200Hz", "300Hz", "400Hz"
+};
- data[0] = reg & 0xff;
- data[1] = value & 0xff;
+static const struct soc_enum da7210_dac_vf_cutoff =
+ SOC_ENUM_SINGLE(DA7210_DAC_HPF, 4, 8, da7210_vf_cutoff_txt);
- if (reg >= codec->driver->reg_cache_size)
- return -EIO;
+static const struct soc_enum da7210_adc_vf_cutoff =
+ SOC_ENUM_SINGLE(DA7210_ADC_HPF, 4, 8, da7210_vf_cutoff_txt);
- if (2 != codec->hw_write(codec->control_data, data, 2))
- return -EIO;
+static const char *da7210_hp_mode_txt[] = {
+ "Class H", "Class G"
+};
- cache[reg] = value;
- return 0;
+static const struct soc_enum da7210_hp_mode_sel =
+ SOC_ENUM_SINGLE(DA7210_HP_CFG, 0, 2, da7210_hp_mode_txt);
+
+/* ALC can be enabled only if noise suppression is disabled */
+static int da7210_put_alc_sw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+
+ if (ucontrol->value.integer.value[0]) {
+ /* Check if noise suppression is enabled */
+ if (snd_soc_read(codec, DA7210_CONTROL) & DA7210_NOISE_SUP_EN) {
+ dev_dbg(codec->dev,
+ "Disable noise suppression to enable ALC\n");
+ return -EINVAL;
+ }
+ }
+ /* If all conditions are met or we are actually disabling ALC */
+ return snd_soc_put_volsw(kcontrol, ucontrol);
}
-/*
- * Read from the da7210 register space.
+/* Noise suppression can be enabled only if following conditions are met
+ * ALC disabled
+ * ZC enabled for HP and AUX1 PGA
+ * INPGA_L_VOL and INPGA_R_VOL >= 10.5 dB
+ * AUX1_L_VOL and AUX1_R_VOL >= 6 dB
*/
-static inline u32 da7210_read(struct snd_soc_codec *codec, u32 reg)
+static int da7210_put_noise_sup_sw(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- if (DA7210_STATUS == reg)
- return i2c_smbus_read_byte_data(codec->control_data, reg);
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ u8 val;
+
+ if (ucontrol->value.integer.value[0]) {
+ /* Check if ALC is enabled */
+ if (snd_soc_read(codec, DA7210_ADC) & DA7210_ADC_ALC_EN)
+ goto err;
+
+ /* Check ZC for HP and AUX1 PGA */
+ if ((snd_soc_read(codec, DA7210_ZERO_CROSS) &
+ (DA7210_AUX1_L_ZC | DA7210_AUX1_R_ZC | DA7210_HP_L_ZC |
+ DA7210_HP_R_ZC)) != (DA7210_AUX1_L_ZC |
+ DA7210_AUX1_R_ZC | DA7210_HP_L_ZC | DA7210_HP_R_ZC))
+ goto err;
+
+ /* Check INPGA_L_VOL and INPGA_R_VOL */
+ val = snd_soc_read(codec, DA7210_IN_GAIN);
+ if (((val & DA7210_INPGA_L_VOL) < DA7210_INPGA_MIN_VOL_NS) ||
+ (((val & DA7210_INPGA_R_VOL) >> 4) <
+ DA7210_INPGA_MIN_VOL_NS))
+ goto err;
+
+ /* Check AUX1_L_VOL and AUX1_R_VOL */
+ if (((snd_soc_read(codec, DA7210_AUX1_L) & DA7210_AUX1_L_VOL) <
+ DA7210_AUX1_MIN_VOL_NS) ||
+ ((snd_soc_read(codec, DA7210_AUX1_R) & DA7210_AUX1_R_VOL) <
+ DA7210_AUX1_MIN_VOL_NS))
+ goto err;
+ }
+ /* If all conditions are met or we are actually disabling Noise sup */
+ return snd_soc_put_volsw(kcontrol, ucontrol);
- return da7210_read_reg_cache(codec, reg);
+err:
+ return -EINVAL;
}
-static int da7210_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- int is_play = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
- struct snd_soc_codec *codec = dai->codec;
+static const struct snd_kcontrol_new da7210_snd_controls[] = {
+
+ SOC_DOUBLE_R_TLV("HeadPhone Playback Volume",
+ DA7210_HP_L_VOL, DA7210_HP_R_VOL,
+ 0, 0x3F, 0, hp_out_tlv),
+ SOC_DOUBLE_R_TLV("Digital Playback Volume",
+ DA7210_DAC_L, DA7210_DAC_R,
+ 0, 0x77, 1, dac_gain_tlv),
+ SOC_DOUBLE_R_TLV("Lineout Playback Volume",
+ DA7210_OUT1_L, DA7210_OUT1_R,
+ 0, 0x3f, 0, lineout_vol_tlv),
+ SOC_SINGLE_TLV("Mono Playback Volume", DA7210_OUT2, 0, 0x7, 0,
+ mono_vol_tlv),
+
+ SOC_DOUBLE_R_TLV("Mic Capture Volume",
+ DA7210_MIC_L, DA7210_MIC_R,
+ 0, 0x5, 0, mic_vol_tlv),
+ SOC_DOUBLE_R_TLV("Aux1 Capture Volume",
+ DA7210_AUX1_L, DA7210_AUX1_R,
+ 0, 0x3f, 0, aux1_vol_tlv),
+ SOC_SINGLE_TLV("Aux2 Capture Volume", DA7210_AUX2, 0, 0x3, 0,
+ aux2_vol_tlv),
+ SOC_DOUBLE_TLV("In PGA Capture Volume", DA7210_IN_GAIN, 0, 4, 0xF, 0,
+ inpga_gain_tlv),
+
+ /* DAC Equalizer controls */
+ SOC_SINGLE("DAC EQ Switch", DA7210_DAC_EQ5, 7, 1, 0),
+ SOC_SINGLE_TLV("DAC EQ1 Volume", DA7210_DAC_EQ1_2, 0, 0xf, 1,
+ eq_gain_tlv),
+ SOC_SINGLE_TLV("DAC EQ2 Volume", DA7210_DAC_EQ1_2, 4, 0xf, 1,
+ eq_gain_tlv),
+ SOC_SINGLE_TLV("DAC EQ3 Volume", DA7210_DAC_EQ3_4, 0, 0xf, 1,
+ eq_gain_tlv),
+ SOC_SINGLE_TLV("DAC EQ4 Volume", DA7210_DAC_EQ3_4, 4, 0xf, 1,
+ eq_gain_tlv),
+ SOC_SINGLE_TLV("DAC EQ5 Volume", DA7210_DAC_EQ5, 0, 0xf, 1,
+ eq_gain_tlv),
+
+ /* ADC Equalizer controls */
+ SOC_SINGLE("ADC EQ Switch", DA7210_ADC_EQ5, 7, 1, 0),
+ SOC_SINGLE_TLV("ADC EQ Master Volume", DA7210_ADC_EQ5, 4, 0x3,
+ 1, adc_eq_master_gain_tlv),
+ SOC_SINGLE_TLV("ADC EQ1 Volume", DA7210_ADC_EQ1_2, 0, 0xf, 1,
+ eq_gain_tlv),
+ SOC_SINGLE_TLV("ADC EQ2 Volume", DA7210_ADC_EQ1_2, 4, 0xf, 1,
+ eq_gain_tlv),
+ SOC_SINGLE_TLV("ADC EQ3 Volume", DA7210_ADC_EQ3_4, 0, 0xf, 1,
+ eq_gain_tlv),
+ SOC_SINGLE_TLV("ADC EQ4 Volume", DA7210_ADC_EQ3_4, 4, 0xf, 1,
+ eq_gain_tlv),
+ SOC_SINGLE_TLV("ADC EQ5 Volume", DA7210_ADC_EQ5, 0, 0xf, 1,
+ eq_gain_tlv),
+
+ SOC_SINGLE("DAC HPF Switch", DA7210_DAC_HPF, 3, 1, 0),
+ SOC_ENUM("DAC HPF Cutoff", da7210_dac_hpf_cutoff),
+ SOC_SINGLE("DAC Voice Mode Switch", DA7210_DAC_HPF, 7, 1, 0),
+ SOC_ENUM("DAC Voice Cutoff", da7210_dac_vf_cutoff),
+
+ SOC_SINGLE("ADC HPF Switch", DA7210_ADC_HPF, 3, 1, 0),
+ SOC_ENUM("ADC HPF Cutoff", da7210_adc_hpf_cutoff),
+ SOC_SINGLE("ADC Voice Mode Switch", DA7210_ADC_HPF, 7, 1, 0),
+ SOC_ENUM("ADC Voice Cutoff", da7210_adc_vf_cutoff),
+
+ /* Mute controls */
+ SOC_DOUBLE_R("Mic Capture Switch", DA7210_MIC_L, DA7210_MIC_R, 3, 1, 0),
+ SOC_SINGLE("Aux2 Capture Switch", DA7210_AUX2, 2, 1, 0),
+ SOC_DOUBLE("ADC Capture Switch", DA7210_ADC, 2, 6, 1, 0),
+ SOC_SINGLE("Digital Soft Mute Switch", DA7210_SOFTMUTE, 7, 1, 0),
+ SOC_SINGLE("Digital Soft Mute Rate", DA7210_SOFTMUTE, 0, 0x7, 0),
+
+ /* Zero cross controls */
+ SOC_DOUBLE("Aux1 ZC Switch", DA7210_ZERO_CROSS, 0, 1, 1, 0),
+ SOC_DOUBLE("In PGA ZC Switch", DA7210_ZERO_CROSS, 2, 3, 1, 0),
+ SOC_DOUBLE("Lineout ZC Switch", DA7210_ZERO_CROSS, 4, 5, 1, 0),
+ SOC_DOUBLE("Headphone ZC Switch", DA7210_ZERO_CROSS, 6, 7, 1, 0),
+
+ SOC_ENUM("Headphone Class", da7210_hp_mode_sel),
+
+ /* ALC controls */
+ SOC_SINGLE_EXT("ALC Enable Switch", DA7210_ADC, 0, 1, 0,
+ snd_soc_get_volsw, da7210_put_alc_sw),
+ SOC_SINGLE("ALC Capture Max Volume", DA7210_ALC_MAX, 0, 0x3F, 0),
+ SOC_SINGLE("ALC Capture Min Volume", DA7210_ALC_MIN, 0, 0x3F, 0),
+ SOC_SINGLE("ALC Capture Noise Volume", DA7210_ALC_NOIS, 0, 0x3F, 0),
+ SOC_SINGLE("ALC Capture Attack Rate", DA7210_ALC_ATT, 0, 0xFF, 0),
+ SOC_SINGLE("ALC Capture Release Rate", DA7210_ALC_REL, 0, 0xFF, 0),
+ SOC_SINGLE("ALC Capture Release Delay", DA7210_ALC_DEL, 0, 0xFF, 0),
+
+ SOC_SINGLE_EXT("Noise Suppression Enable Switch", DA7210_CONTROL, 3, 1,
+ 0, snd_soc_get_volsw, da7210_put_noise_sup_sw),
+};
+
+/*
+ * DAPM Controls
+ *
+ * Current DAPM implementation covers almost all codec components e.g. IOs,
+ * mixers, PGAs,ADC and DAC.
+ */
+/* In Mixer Left */
+static const struct snd_kcontrol_new da7210_dapm_inmixl_controls[] = {
+ SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_L, 0, 1, 0),
+ SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_L, 1, 1, 0),
+ SOC_DAPM_SINGLE("Aux1 Left Switch", DA7210_INMIX_L, 2, 1, 0),
+ SOC_DAPM_SINGLE("Aux2 Switch", DA7210_INMIX_L, 3, 1, 0),
+ SOC_DAPM_SINGLE("Outmix Left Switch", DA7210_INMIX_L, 4, 1, 0),
+};
+
+/* In Mixer Right */
+static const struct snd_kcontrol_new da7210_dapm_inmixr_controls[] = {
+ SOC_DAPM_SINGLE("Mic Right Switch", DA7210_INMIX_R, 0, 1, 0),
+ SOC_DAPM_SINGLE("Mic Left Switch", DA7210_INMIX_R, 1, 1, 0),
+ SOC_DAPM_SINGLE("Aux1 Right Switch", DA7210_INMIX_R, 2, 1, 0),
+ SOC_DAPM_SINGLE("Aux2 Switch", DA7210_INMIX_R, 3, 1, 0),
+ SOC_DAPM_SINGLE("Outmix Right Switch", DA7210_INMIX_R, 4, 1, 0),
+};
+
+/* Out Mixer Left */
+static const struct snd_kcontrol_new da7210_dapm_outmixl_controls[] = {
+ SOC_DAPM_SINGLE("Aux1 Left Switch", DA7210_OUTMIX_L, 0, 1, 0),
+ SOC_DAPM_SINGLE("Aux2 Switch", DA7210_OUTMIX_L, 1, 1, 0),
+ SOC_DAPM_SINGLE("INPGA Left Switch", DA7210_OUTMIX_L, 2, 1, 0),
+ SOC_DAPM_SINGLE("INPGA Right Switch", DA7210_OUTMIX_L, 3, 1, 0),
+ SOC_DAPM_SINGLE("DAC Left Switch", DA7210_OUTMIX_L, 4, 1, 0),
+};
- if (is_play) {
- /* Enable Out */
- snd_soc_update_bits(codec, DA7210_OUTMIX_L, 0x1F, 0x10);
- snd_soc_update_bits(codec, DA7210_OUTMIX_R, 0x1F, 0x10);
+/* Out Mixer Right */
+static const struct snd_kcontrol_new da7210_dapm_outmixr_controls[] = {
+ SOC_DAPM_SINGLE("Aux1 Right Switch", DA7210_OUTMIX_R, 0, 1, 0),
+ SOC_DAPM_SINGLE("Aux2 Switch", DA7210_OUTMIX_R, 1, 1, 0),
+ SOC_DAPM_SINGLE("INPGA Left Switch", DA7210_OUTMIX_R, 2, 1, 0),
+ SOC_DAPM_SINGLE("INPGA Right Switch", DA7210_OUTMIX_R, 3, 1, 0),
+ SOC_DAPM_SINGLE("DAC Right Switch", DA7210_OUTMIX_R, 4, 1, 0),
+};
+
+/* Mono Mixer */
+static const struct snd_kcontrol_new da7210_dapm_monomix_controls[] = {
+ SOC_DAPM_SINGLE("INPGA Right Switch", DA7210_OUT2, 3, 1, 0),
+ SOC_DAPM_SINGLE("INPGA Left Switch", DA7210_OUT2, 4, 1, 0),
+ SOC_DAPM_SINGLE("Outmix Right Switch", DA7210_OUT2, 5, 1, 0),
+ SOC_DAPM_SINGLE("Outmix Left Switch", DA7210_OUT2, 6, 1, 0),
+};
+
+/* DAPM widgets */
+static const struct snd_soc_dapm_widget da7210_dapm_widgets[] = {
+ /* Input Side */
+ /* Input Lines */
+ SND_SOC_DAPM_INPUT("MICL"),
+ SND_SOC_DAPM_INPUT("MICR"),
+ SND_SOC_DAPM_INPUT("AUX1L"),
+ SND_SOC_DAPM_INPUT("AUX1R"),
+ SND_SOC_DAPM_INPUT("AUX2"),
+
+ /* Input PGAs */
+ SND_SOC_DAPM_PGA("Mic Left", DA7210_STARTUP3, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Mic Right", DA7210_STARTUP3, 1, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Aux1 Left", DA7210_STARTUP3, 2, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Aux1 Right", DA7210_STARTUP3, 3, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Aux2 Mono", DA7210_STARTUP3, 4, 1, NULL, 0),
+
+ SND_SOC_DAPM_PGA("INPGA Left", DA7210_INMIX_L, 7, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("INPGA Right", DA7210_INMIX_R, 7, 0, NULL, 0),
+
+ /* MICBIAS */
+ SND_SOC_DAPM_SUPPLY("Mic Bias", DA7210_MIC_L, 6, 0, NULL, 0),
+
+ /* Input Mixers */
+ SND_SOC_DAPM_MIXER("In Mixer Left", SND_SOC_NOPM, 0, 0,
+ &da7210_dapm_inmixl_controls[0],
+ ARRAY_SIZE(da7210_dapm_inmixl_controls)),
+
+ SND_SOC_DAPM_MIXER("In Mixer Right", SND_SOC_NOPM, 0, 0,
+ &da7210_dapm_inmixr_controls[0],
+ ARRAY_SIZE(da7210_dapm_inmixr_controls)),
+
+ /* ADCs */
+ SND_SOC_DAPM_ADC("ADC Left", "Capture", DA7210_STARTUP3, 5, 1),
+ SND_SOC_DAPM_ADC("ADC Right", "Capture", DA7210_STARTUP3, 6, 1),
+
+ /* Output Side */
+ /* DACs */
+ SND_SOC_DAPM_DAC("DAC Left", "Playback", DA7210_STARTUP2, 5, 1),
+ SND_SOC_DAPM_DAC("DAC Right", "Playback", DA7210_STARTUP2, 6, 1),
+
+ /* Output Mixers */
+ SND_SOC_DAPM_MIXER("Out Mixer Left", SND_SOC_NOPM, 0, 0,
+ &da7210_dapm_outmixl_controls[0],
+ ARRAY_SIZE(da7210_dapm_outmixl_controls)),
+
+ SND_SOC_DAPM_MIXER("Out Mixer Right", SND_SOC_NOPM, 0, 0,
+ &da7210_dapm_outmixr_controls[0],
+ ARRAY_SIZE(da7210_dapm_outmixr_controls)),
+
+ SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0,
+ &da7210_dapm_monomix_controls[0],
+ ARRAY_SIZE(da7210_dapm_monomix_controls)),
+
+ /* Output PGAs */
+ SND_SOC_DAPM_PGA("OUTPGA Left Enable", DA7210_OUTMIX_L, 7, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("OUTPGA Right Enable", DA7210_OUTMIX_R, 7, 0, NULL, 0),
+
+ SND_SOC_DAPM_PGA("Out1 Left", DA7210_STARTUP2, 0, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Out1 Right", DA7210_STARTUP2, 1, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Out2 Mono", DA7210_STARTUP2, 2, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Headphone Left", DA7210_STARTUP2, 3, 1, NULL, 0),
+ SND_SOC_DAPM_PGA("Headphone Right", DA7210_STARTUP2, 4, 1, NULL, 0),
+
+ /* Output Lines */
+ SND_SOC_DAPM_OUTPUT("OUT1L"),
+ SND_SOC_DAPM_OUTPUT("OUT1R"),
+ SND_SOC_DAPM_OUTPUT("HPL"),
+ SND_SOC_DAPM_OUTPUT("HPR"),
+ SND_SOC_DAPM_OUTPUT("OUT2"),
+};
+
+/* DAPM audio route definition */
+static const struct snd_soc_dapm_route da7210_audio_map[] = {
+ /* Dest Connecting Widget source */
+ /* Input path */
+ {"Mic Left", NULL, "MICL"},
+ {"Mic Right", NULL, "MICR"},
+ {"Aux1 Left", NULL, "AUX1L"},
+ {"Aux1 Right", NULL, "AUX1R"},
+ {"Aux2 Mono", NULL, "AUX2"},
+
+ {"In Mixer Left", "Mic Left Switch", "Mic Left"},
+ {"In Mixer Left", "Mic Right Switch", "Mic Right"},
+ {"In Mixer Left", "Aux1 Left Switch", "Aux1 Left"},
+ {"In Mixer Left", "Aux2 Switch", "Aux2 Mono"},
+ {"In Mixer Left", "Outmix Left Switch", "Out Mixer Left"},
+
+ {"In Mixer Right", "Mic Right Switch", "Mic Right"},
+ {"In Mixer Right", "Mic Left Switch", "Mic Left"},
+ {"In Mixer Right", "Aux1 Right Switch", "Aux1 Right"},
+ {"In Mixer Right", "Aux2 Switch", "Aux2 Mono"},
+ {"In Mixer Right", "Outmix Right Switch", "Out Mixer Right"},
+
+ {"INPGA Left", NULL, "In Mixer Left"},
+ {"ADC Left", NULL, "INPGA Left"},
+
+ {"INPGA Right", NULL, "In Mixer Right"},
+ {"ADC Right", NULL, "INPGA Right"},
+
+ /* Output path */
+ {"Out Mixer Left", "Aux1 Left Switch", "Aux1 Left"},
+ {"Out Mixer Left", "Aux2 Switch", "Aux2 Mono"},
+ {"Out Mixer Left", "INPGA Left Switch", "INPGA Left"},
+ {"Out Mixer Left", "INPGA Right Switch", "INPGA Right"},
+ {"Out Mixer Left", "DAC Left Switch", "DAC Left"},
+
+ {"Out Mixer Right", "Aux1 Right Switch", "Aux1 Right"},
+ {"Out Mixer Right", "Aux2 Switch", "Aux2 Mono"},
+ {"Out Mixer Right", "INPGA Right Switch", "INPGA Right"},
+ {"Out Mixer Right", "INPGA Left Switch", "INPGA Left"},
+ {"Out Mixer Right", "DAC Right Switch", "DAC Right"},
+
+ {"Mono Mixer", "INPGA Right Switch", "INPGA Right"},
+ {"Mono Mixer", "INPGA Left Switch", "INPGA Left"},
+ {"Mono Mixer", "Outmix Right Switch", "Out Mixer Right"},
+ {"Mono Mixer", "Outmix Left Switch", "Out Mixer Left"},
+
+ {"OUTPGA Left Enable", NULL, "Out Mixer Left"},
+ {"OUTPGA Right Enable", NULL, "Out Mixer Right"},
+
+ {"Out1 Left", NULL, "OUTPGA Left Enable"},
+ {"OUT1L", NULL, "Out1 Left"},
+
+ {"Out1 Right", NULL, "OUTPGA Right Enable"},
+ {"OUT1R", NULL, "Out1 Right"},
+
+ {"Headphone Left", NULL, "OUTPGA Left Enable"},
+ {"HPL", NULL, "Headphone Left"},
+
+ {"Headphone Right", NULL, "OUTPGA Right Enable"},
+ {"HPR", NULL, "Headphone Right"},
+
+ {"Out2 Mono", NULL, "Mono Mixer"},
+ {"OUT2", NULL, "Out2 Mono"},
+};
- } else {
- /* Volume 7 */
- snd_soc_update_bits(codec, DA7210_MIC_L, 0x7, 0x7);
- snd_soc_update_bits(codec, DA7210_MIC_R, 0x7, 0x7);
+/* Codec private data */
+struct da7210_priv {
+ struct regmap *regmap;
+};
- /* Enable Mic */
- snd_soc_update_bits(codec, DA7210_INMIX_L, 0x1F, 0x1);
- snd_soc_update_bits(codec, DA7210_INMIX_R, 0x1F, 0x1);
+static struct reg_default da7210_reg_defaults[] = {
+ { 0x01, 0x11 },
+ { 0x03, 0x00 },
+ { 0x04, 0x00 },
+ { 0x05, 0x00 },
+ { 0x06, 0x00 },
+ { 0x07, 0x00 },
+ { 0x08, 0x00 },
+ { 0x09, 0x00 },
+ { 0x0a, 0x00 },
+ { 0x0b, 0x00 },
+ { 0x0c, 0x00 },
+ { 0x0d, 0x00 },
+ { 0x0e, 0x00 },
+ { 0x0f, 0x08 },
+ { 0x10, 0x00 },
+ { 0x11, 0x00 },
+ { 0x12, 0x00 },
+ { 0x13, 0x00 },
+ { 0x14, 0x08 },
+ { 0x15, 0x10 },
+ { 0x16, 0x10 },
+ { 0x17, 0x54 },
+ { 0x18, 0x40 },
+ { 0x19, 0x00 },
+ { 0x1a, 0x00 },
+ { 0x1b, 0x00 },
+ { 0x1c, 0x00 },
+ { 0x1d, 0x00 },
+ { 0x1e, 0x00 },
+ { 0x1f, 0x00 },
+ { 0x20, 0x00 },
+ { 0x21, 0x00 },
+ { 0x22, 0x00 },
+ { 0x23, 0x02 },
+ { 0x24, 0x00 },
+ { 0x25, 0x76 },
+ { 0x26, 0x00 },
+ { 0x27, 0x00 },
+ { 0x28, 0x04 },
+ { 0x29, 0x00 },
+ { 0x2a, 0x00 },
+ { 0x2b, 0x30 },
+ { 0x2c, 0x2A },
+ { 0x83, 0x00 },
+ { 0x84, 0x00 },
+ { 0x85, 0x00 },
+ { 0x86, 0x00 },
+ { 0x87, 0x00 },
+ { 0x88, 0x00 },
+};
+
+static bool da7210_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case DA7210_A_HID_UNLOCK:
+ case DA7210_A_TEST_UNLOCK:
+ case DA7210_A_PLL1:
+ case DA7210_A_CP_MODE:
+ return false;
+ default:
+ return true;
}
+}
- return 0;
+static bool da7210_volatile_register(struct device *dev,
+ unsigned int reg)
+{
+ switch (reg) {
+ case DA7210_STATUS:
+ return true;
+ default:
+ return false;
+ }
}
/*
@@ -266,93 +716,75 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
u32 dai_cfg1;
- u32 hpf_reg, hpf_mask, hpf_value;
u32 fs, bypass;
/* set DAI source to Left and Right ADC */
- da7210_write(codec, DA7210_DAI_SRC_SEL,
+ snd_soc_write(codec, DA7210_DAI_SRC_SEL,
DA7210_DAI_OUT_R_SRC | DA7210_DAI_OUT_L_SRC);
/* Enable DAI */
- da7210_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN);
+ snd_soc_write(codec, DA7210_DAI_CFG3, DA7210_DAI_OE | DA7210_DAI_EN);
- dai_cfg1 = 0xFC & da7210_read(codec, DA7210_DAI_CFG1);
+ dai_cfg1 = 0xFC & snd_soc_read(codec, DA7210_DAI_CFG1);
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
dai_cfg1 |= DA7210_DAI_WORD_S16_LE;
break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ dai_cfg1 |= DA7210_DAI_WORD_S20_3LE;
+ break;
case SNDRV_PCM_FORMAT_S24_LE:
dai_cfg1 |= DA7210_DAI_WORD_S24_LE;
break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ dai_cfg1 |= DA7210_DAI_WORD_S32_LE;
+ break;
default:
return -EINVAL;
}
- da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
-
- hpf_reg = (SNDRV_PCM_STREAM_PLAYBACK == substream->stream) ?
- DA7210_DAC_HPF : DA7210_ADC_HPF;
+ snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1);
switch (params_rate(params)) {
case 8000:
fs = DA7210_PLL_FS_8000;
- hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
- hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
bypass = DA7210_PLL_BYP;
break;
case 11025:
fs = DA7210_PLL_FS_11025;
- hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
- hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
bypass = 0;
break;
case 12000:
fs = DA7210_PLL_FS_12000;
- hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
- hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
bypass = DA7210_PLL_BYP;
break;
case 16000:
fs = DA7210_PLL_FS_16000;
- hpf_mask = DA7210_VOICE_F0_MASK | DA7210_VOICE_EN;
- hpf_value = DA7210_VOICE_F0_25 | DA7210_VOICE_EN;
bypass = DA7210_PLL_BYP;
break;
case 22050:
fs = DA7210_PLL_FS_22050;
- hpf_mask = DA7210_VOICE_EN;
- hpf_value = 0;
bypass = 0;
break;
case 32000:
fs = DA7210_PLL_FS_32000;
- hpf_mask = DA7210_VOICE_EN;
- hpf_value = 0;
bypass = DA7210_PLL_BYP;
break;
case 44100:
fs = DA7210_PLL_FS_44100;
- hpf_mask = DA7210_VOICE_EN;
- hpf_value = 0;
bypass = 0;
break;
case 48000:
fs = DA7210_PLL_FS_48000;
- hpf_mask = DA7210_VOICE_EN;
- hpf_value = 0;
bypass = DA7210_PLL_BYP;
break;
case 88200:
fs = DA7210_PLL_FS_88200;
- hpf_mask = DA7210_VOICE_EN;
- hpf_value = 0;
bypass = 0;
break;
case 96000:
fs = DA7210_PLL_FS_96000;
- hpf_mask = DA7210_VOICE_EN;
- hpf_value = 0;
bypass = DA7210_PLL_BYP;
break;
default:
@@ -362,7 +794,6 @@ static int da7210_hw_params(struct snd_pcm_substream *substream,
/* Disable active mode */
snd_soc_update_bits(codec, DA7210_STARTUP1, DA7210_SC_MST_EN, 0);
- snd_soc_update_bits(codec, hpf_reg, hpf_mask, hpf_value);
snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_FS_MASK, fs);
snd_soc_update_bits(codec, DA7210_PLL_DIV3, DA7210_PLL_BYP, bypass);
@@ -382,13 +813,16 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
u32 dai_cfg1;
u32 dai_cfg3;
- dai_cfg1 = 0x7f & da7210_read(codec, DA7210_DAI_CFG1);
- dai_cfg3 = 0xfc & da7210_read(codec, DA7210_DAI_CFG3);
+ dai_cfg1 = 0x7f & snd_soc_read(codec, DA7210_DAI_CFG1);
+ dai_cfg3 = 0xfc & snd_soc_read(codec, DA7210_DAI_CFG3);
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
dai_cfg1 |= DA7210_DAI_MODE_MASTER;
break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ dai_cfg1 |= DA7210_DAI_MODE_SLAVE;
+ break;
default:
return -EINVAL;
}
@@ -401,6 +835,12 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
case SND_SOC_DAIFMT_I2S:
dai_cfg3 |= DA7210_DAI_FORMAT_I2SMODE;
break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ dai_cfg3 |= DA7210_DAI_FORMAT_LEFT_J;
+ break;
+ case SND_SOC_DAIFMT_RIGHT_J:
+ dai_cfg3 |= DA7210_DAI_FORMAT_RIGHT_J;
+ break;
default:
return -EINVAL;
}
@@ -411,19 +851,32 @@ static int da7210_set_dai_fmt(struct snd_soc_dai *codec_dai, u32 fmt)
*/
dai_cfg1 |= DA7210_DAI_FLEN_64BIT;
- da7210_write(codec, DA7210_DAI_CFG1, dai_cfg1);
- da7210_write(codec, DA7210_DAI_CFG3, dai_cfg3);
+ snd_soc_write(codec, DA7210_DAI_CFG1, dai_cfg1);
+ snd_soc_write(codec, DA7210_DAI_CFG3, dai_cfg3);
return 0;
}
-#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
+static int da7210_mute(struct snd_soc_dai *dai, int mute)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ u8 mute_reg = snd_soc_read(codec, DA7210_DAC_HPF) & 0xFB;
+
+ if (mute)
+ snd_soc_write(codec, DA7210_DAC_HPF, mute_reg | 0x4);
+ else
+ snd_soc_write(codec, DA7210_DAC_HPF, mute_reg);
+ return 0;
+}
+
+#define DA7210_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
/* DAI operations */
-static struct snd_soc_dai_ops da7210_dai_ops = {
- .startup = da7210_startup,
+static const struct snd_soc_dai_ops da7210_dai_ops = {
.hw_params = da7210_hw_params,
.set_fmt = da7210_set_dai_fmt,
+ .digital_mute = da7210_mute,
};
static struct snd_soc_dai_driver da7210_dai = {
@@ -451,11 +904,16 @@ static struct snd_soc_dai_driver da7210_dai = {
static int da7210_probe(struct snd_soc_codec *codec)
{
struct da7210_priv *da7210 = snd_soc_codec_get_drvdata(codec);
+ int ret;
dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
- codec->control_data = da7210->control_data;
- codec->hw_write = (hw_write_t)i2c_master_send;
+ codec->control_data = da7210->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
/* FIXME
*
@@ -472,8 +930,8 @@ static int da7210_probe(struct snd_soc_codec *codec)
/*
* make sure that DA7210 use bypass mode before start up
*/
- da7210_write(codec, DA7210_STARTUP1, 0);
- da7210_write(codec, DA7210_PLL_DIV3,
+ snd_soc_write(codec, DA7210_STARTUP1, 0);
+ snd_soc_write(codec, DA7210_PLL_DIV3,
DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
/*
@@ -481,36 +939,76 @@ static int da7210_probe(struct snd_soc_codec *codec)
*/
/* Enable Left & Right MIC PGA and Mic Bias */
- da7210_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN);
- da7210_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN);
+ snd_soc_write(codec, DA7210_MIC_L, DA7210_MIC_L_EN | DA7210_MICBIAS_EN);
+ snd_soc_write(codec, DA7210_MIC_R, DA7210_MIC_R_EN);
/* Enable Left and Right input PGA */
- da7210_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN);
- da7210_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN);
+ snd_soc_write(codec, DA7210_INMIX_L, DA7210_IN_L_EN);
+ snd_soc_write(codec, DA7210_INMIX_R, DA7210_IN_R_EN);
/* Enable Left and Right ADC */
- da7210_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN);
+ snd_soc_write(codec, DA7210_ADC, DA7210_ADC_L_EN | DA7210_ADC_R_EN);
/*
* DAC settings
*/
/* Enable Left and Right DAC */
- da7210_write(codec, DA7210_DAC_SEL,
+ snd_soc_write(codec, DA7210_DAC_SEL,
DA7210_DAC_L_SRC_DAI_L | DA7210_DAC_L_EN |
DA7210_DAC_R_SRC_DAI_R | DA7210_DAC_R_EN);
/* Enable Left and Right out PGA */
- da7210_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN);
- da7210_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN);
+ snd_soc_write(codec, DA7210_OUTMIX_L, DA7210_OUT_L_EN);
+ snd_soc_write(codec, DA7210_OUTMIX_R, DA7210_OUT_R_EN);
/* Enable Left and Right HeadPhone PGA */
- da7210_write(codec, DA7210_HP_CFG,
+ snd_soc_write(codec, DA7210_HP_CFG,
DA7210_HP_2CAP_MODE | DA7210_HP_SENSE_EN |
DA7210_HP_L_EN | DA7210_HP_MODE | DA7210_HP_R_EN);
+ /* Enable ramp mode for DAC gain update */
+ snd_soc_write(codec, DA7210_SOFTMUTE, DA7210_RAMP_EN);
+
+ /*
+ * For DA7210 codec, there are two ways to enable/disable analog IOs
+ * and ADC/DAC,
+ * (1) Using "Enable Bit" of register associated with that IO
+ * (or ADC/DAC)
+ * e.g. Mic Left can be enabled using bit 7 of MIC_L(0x7) reg
+ *
+ * (2) Using "Standby Bit" of STARTUP2 or STARTUP3 register
+ * e.g. Mic left can be put to STANDBY using bit 0 of STARTUP3(0x5)
+ *
+ * Out of these two methods, the one using STANDBY bits is preferred
+ * way to enable/disable individual blocks. This is because STANDBY
+ * registers are part of system controller which allows system power
+ * up/down in a controlled, pop-free manner. Also, as per application
+ * note of DA7210, STANDBY register bits are only effective if a
+ * particular IO (or ADC/DAC) is already enabled using enable/disable
+ * register bits. Keeping these things in mind, current DAPM
+ * implementation manipulates only STANDBY bits.
+ *
+ * Overall implementation can be outlined as below,
+ *
+ * - "Enable bit" of an IO or ADC/DAC is used to enable it in probe()
+ * - "STANDBY bit" is controlled by DAPM
+ */
+
+ /* Enable Line out amplifiers */
+ snd_soc_write(codec, DA7210_OUT1_L, DA7210_OUT1_L_EN);
+ snd_soc_write(codec, DA7210_OUT1_R, DA7210_OUT1_R_EN);
+ snd_soc_write(codec, DA7210_OUT2, DA7210_OUT2_EN |
+ DA7210_OUT2_OUTMIX_L | DA7210_OUT2_OUTMIX_R);
+
+ /* Enable Aux1 */
+ snd_soc_write(codec, DA7210_AUX1_L, DA7210_AUX1_L_EN);
+ snd_soc_write(codec, DA7210_AUX1_R, DA7210_AUX1_R_EN);
+ /* Enable Aux2 */
+ snd_soc_write(codec, DA7210_AUX2, DA7210_AUX2_EN);
+
/* Diable PLL and bypass it */
- da7210_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
+ snd_soc_write(codec, DA7210_PLL, DA7210_PLL_FS_48000);
/*
* If 48kHz sound came, it use bypass mode,
@@ -521,25 +1019,24 @@ static int da7210_probe(struct snd_soc_codec *codec)
* DA7210_PLL_DIV3 :: DA7210_PLL_BYP bit.
* see da7210_hw_params
*/
- da7210_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
- da7210_write(codec, DA7210_PLL_DIV2, 0x99);
- da7210_write(codec, DA7210_PLL_DIV3, 0x0A |
+ snd_soc_write(codec, DA7210_PLL_DIV1, 0xE5); /* MCLK = 12.288MHz */
+ snd_soc_write(codec, DA7210_PLL_DIV2, 0x99);
+ snd_soc_write(codec, DA7210_PLL_DIV3, 0x0A |
DA7210_MCLK_RANGE_10_20_MHZ | DA7210_PLL_BYP);
snd_soc_update_bits(codec, DA7210_PLL, DA7210_PLL_EN, DA7210_PLL_EN);
/* As suggested by Dialog */
- da7210_write(codec, DA7210_A_HID_UNLOCK, 0x8B); /* unlock */
- da7210_write(codec, DA7210_A_TEST_UNLOCK, 0xB4);
- da7210_write(codec, DA7210_A_PLL1, 0x01);
- da7210_write(codec, DA7210_A_CP_MODE, 0x7C);
- da7210_write(codec, DA7210_A_HID_UNLOCK, 0x00); /* re-lock */
- da7210_write(codec, DA7210_A_TEST_UNLOCK, 0x00);
+ /* unlock */
+ regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x8B);
+ regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0xB4);
+ regmap_write(da7210->regmap, DA7210_A_PLL1, 0x01);
+ regmap_write(da7210->regmap, DA7210_A_CP_MODE, 0x7C);
+ /* re-lock */
+ regmap_write(da7210->regmap, DA7210_A_HID_UNLOCK, 0x00);
+ regmap_write(da7210->regmap, DA7210_A_TEST_UNLOCK, 0x00);
/* Activate all enabled subsystem */
- da7210_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
-
- snd_soc_add_controls(codec, da7210_snd_controls,
- ARRAY_SIZE(da7210_snd_controls));
+ snd_soc_write(codec, DA7210_STARTUP1, DA7210_SC_MST_EN);
dev_info(codec->dev, "DA7210 Audio Codec %s\n", DA7210_VERSION);
@@ -548,11 +1045,25 @@ static int da7210_probe(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_da7210 = {
.probe = da7210_probe,
- .read = da7210_read,
- .write = da7210_write,
- .reg_cache_size = ARRAY_SIZE(da7210_reg),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = da7210_reg,
+
+ .controls = da7210_snd_controls,
+ .num_controls = ARRAY_SIZE(da7210_snd_controls),
+
+ .dapm_widgets = da7210_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(da7210_dapm_widgets),
+ .dapm_routes = da7210_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(da7210_audio_map),
+};
+
+static struct regmap_config da7210_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .reg_defaults = da7210_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(da7210_reg_defaults),
+ .volatile_reg = da7210_volatile_register,
+ .readable_reg = da7210_readable_register,
+ .cache_type = REGCACHE_RBTREE,
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -562,26 +1073,40 @@ static int __devinit da7210_i2c_probe(struct i2c_client *i2c,
struct da7210_priv *da7210;
int ret;
- da7210 = kzalloc(sizeof(struct da7210_priv), GFP_KERNEL);
+ da7210 = devm_kzalloc(&i2c->dev, sizeof(struct da7210_priv),
+ GFP_KERNEL);
if (!da7210)
return -ENOMEM;
i2c_set_clientdata(i2c, da7210);
- da7210->control_data = i2c;
- da7210->control_type = SND_SOC_I2C;
+
+ da7210->regmap = regmap_init_i2c(i2c, &da7210_regmap);
+ if (IS_ERR(da7210->regmap)) {
+ ret = PTR_ERR(da7210->regmap);
+ dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+ return ret;
+ }
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_da7210, &da7210_dai, 1);
- if (ret < 0)
- kfree(da7210);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
+ goto err_regmap;
+ }
+ return ret;
+
+err_regmap:
+ regmap_exit(da7210->regmap);
return ret;
}
static int __devexit da7210_i2c_remove(struct i2c_client *client)
{
+ struct da7210_priv *da7210 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(da7210->regmap);
return 0;
}
diff --git a/sound/soc/codecs/dfbmcs320.c b/sound/soc/codecs/dfbmcs320.c
index 704bbde65737..bfe46aa90362 100644
--- a/sound/soc/codecs/dfbmcs320.c
+++ b/sound/soc/codecs/dfbmcs320.c
@@ -55,17 +55,7 @@ static struct platform_driver dfmcs320_driver = {
.remove = __devexit_p(dfbmcs320_remove),
};
-static int __init dfbmcs320_init(void)
-{
- return platform_driver_register(&dfmcs320_driver);
-}
-module_init(dfbmcs320_init);
-
-static void __exit dfbmcs320_exit(void)
-{
- platform_driver_unregister(&dfmcs320_driver);
-}
-module_exit(dfbmcs320_exit);
+module_platform_driver(dfmcs320_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ASoC DFBM-CS320 bluethooth module driver");
diff --git a/sound/soc/codecs/dmic.c b/sound/soc/codecs/dmic.c
index f9a87737ec16..3e929f079a1f 100644
--- a/sound/soc/codecs/dmic.c
+++ b/sound/soc/codecs/dmic.c
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -88,17 +89,7 @@ static struct platform_driver dmic_driver = {
.remove = __devexit_p(dmic_dev_remove),
};
-static int __init dmic_init(void)
-{
- return platform_driver_register(&dmic_driver);
-}
-module_init(dmic_init);
-
-static void __exit dmic_exit(void)
-{
- platform_driver_unregister(&dmic_driver);
-}
-module_exit(dmic_exit);
+module_platform_driver(dmic_driver);
MODULE_DESCRIPTION("Generic DMIC driver");
MODULE_AUTHOR("Liam Girdwood <lrg@slimlogic.co.uk>");
diff --git a/sound/soc/codecs/jz4740.c b/sound/soc/codecs/jz4740.c
index e373f8f06907..4624e752a188 100644
--- a/sound/soc/codecs/jz4740.c
+++ b/sound/soc/codecs/jz4740.c
@@ -15,6 +15,7 @@
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
+#include <linux/io.h>
#include <linux/delay.h>
@@ -206,7 +207,7 @@ static int jz4740_codec_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_dai_ops jz4740_codec_dai_ops = {
+static const struct snd_soc_dai_ops jz4740_codec_dai_ops = {
.hw_params = jz4740_codec_hw_params,
};
@@ -311,7 +312,7 @@ static int jz4740_codec_dev_remove(struct snd_soc_codec *codec)
#ifdef CONFIG_PM_SLEEP
-static int jz4740_codec_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int jz4740_codec_suspend(struct snd_soc_codec *codec)
{
return jz4740_codec_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
@@ -352,7 +353,8 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
struct jz4740_codec *jz4740_codec;
struct resource *mem;
- jz4740_codec = kzalloc(sizeof(*jz4740_codec), GFP_KERNEL);
+ jz4740_codec = devm_kzalloc(&pdev->dev, sizeof(*jz4740_codec),
+ GFP_KERNEL);
if (!jz4740_codec)
return -ENOMEM;
@@ -360,14 +362,14 @@ static int __devinit jz4740_codec_probe(struct platform_device *pdev)
if (!mem) {
dev_err(&pdev->dev, "Failed to get mmio memory resource\n");
ret = -ENOENT;
- goto err_free_codec;
+ goto err_out;
}
mem = request_mem_region(mem->start, resource_size(mem), pdev->name);
if (!mem) {
dev_err(&pdev->dev, "Failed to request mmio memory region\n");
ret = -EBUSY;
- goto err_free_codec;
+ goto err_out;
}
jz4740_codec->base = ioremap(mem->start, resource_size(mem));
@@ -393,9 +395,7 @@ err_iounmap:
iounmap(jz4740_codec->base);
err_release_mem_region:
release_mem_region(mem->start, resource_size(mem));
-err_free_codec:
- kfree(jz4740_codec);
-
+err_out:
return ret;
}
@@ -410,7 +410,6 @@ static int __devexit jz4740_codec_remove(struct platform_device *pdev)
release_mem_region(mem->start, resource_size(mem));
platform_set_drvdata(pdev, NULL);
- kfree(jz4740_codec);
return 0;
}
@@ -424,17 +423,7 @@ static struct platform_driver jz4740_codec_driver = {
},
};
-static int __init jz4740_codec_init(void)
-{
- return platform_driver_register(&jz4740_codec_driver);
-}
-module_init(jz4740_codec_init);
-
-static void __exit jz4740_codec_exit(void)
-{
- platform_driver_unregister(&jz4740_codec_driver);
-}
-module_exit(jz4740_codec_exit);
+module_platform_driver(jz4740_codec_driver);
MODULE_DESCRIPTION("JZ4740 SoC internal codec driver");
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c
index 2c2a681da0d7..ba4fafb93e56 100644
--- a/sound/soc/codecs/lm4857.c
+++ b/sound/soc/codecs/lm4857.c
@@ -3,7 +3,7 @@
*
* Copyright 2007 Wolfson Microelectronics PLC.
* Author: Graeme Gregory
- * graeme.gregory@wolfsonmicro.com or linux@wolfsonmicro.com
+ * graeme.gregory@wolfsonmicro.com
* Copyright 2011 Lars-Peter Clausen <lars@metafoo.de>
*
* This program is free software; you can redistribute it and/or modify it
@@ -179,7 +179,7 @@ static int lm4857_probe(struct snd_soc_codec *codec)
codec->control_data = lm4857->i2c;
- ret = snd_soc_add_controls(codec, lm4857_controls,
+ ret = snd_soc_add_codec_controls(codec, lm4857_controls,
ARRAY_SIZE(lm4857_controls));
if (ret)
return ret;
@@ -215,7 +215,7 @@ static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
struct lm4857 *lm4857;
int ret;
- lm4857 = kzalloc(sizeof(*lm4857), GFP_KERNEL);
+ lm4857 = devm_kzalloc(&i2c->dev, sizeof(*lm4857), GFP_KERNEL);
if (!lm4857)
return -ENOMEM;
@@ -225,21 +225,12 @@ static int __devinit lm4857_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_lm4857, NULL, 0);
- if (ret) {
- kfree(lm4857);
- return ret;
- }
-
- return 0;
+ return ret;
}
static int __devexit lm4857_i2c_remove(struct i2c_client *i2c)
{
- struct lm4857 *lm4857 = i2c_get_clientdata(i2c);
-
snd_soc_unregister_codec(&i2c->dev);
- kfree(lm4857);
-
return 0;
}
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c
new file mode 100644
index 000000000000..17b3ec2d05cb
--- /dev/null
+++ b/sound/soc/codecs/max9768.c
@@ -0,0 +1,247 @@
+/*
+ * MAX9768 AMP driver
+ *
+ * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; version 2 of the License.
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/regmap.h>
+
+#include <sound/core.h>
+#include <sound/soc.h>
+#include <sound/tlv.h>
+#include <sound/max9768.h>
+
+/* "Registers" */
+#define MAX9768_VOL 0
+#define MAX9768_CTRL 3
+
+/* Commands */
+#define MAX9768_CTRL_PWM 0x15
+#define MAX9768_CTRL_FILTERLESS 0x16
+
+struct max9768 {
+ struct regmap *regmap;
+ int mute_gpio;
+ int shdn_gpio;
+ u32 flags;
+};
+
+static struct reg_default max9768_default_regs[] = {
+ { 0, 0 },
+ { 3, MAX9768_CTRL_FILTERLESS},
+};
+
+static int max9768_get_gpio(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+ int val = gpio_get_value_cansleep(max9768->mute_gpio);
+
+ ucontrol->value.integer.value[0] = !val;
+
+ return 0;
+}
+
+static int max9768_set_gpio(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+
+ gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]);
+
+ return 0;
+}
+
+static const unsigned int volume_tlv[] = {
+ TLV_DB_RANGE_HEAD(43),
+ 0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0),
+ 3, 3, TLV_DB_SCALE_ITEM(-8680, 0, 0),
+ 4, 4, TLV_DB_SCALE_ITEM(-8430, 0, 0),
+ 5, 5, TLV_DB_SCALE_ITEM(-8080, 0, 0),
+ 6, 6, TLV_DB_SCALE_ITEM(-7830, 0, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(-7470, 0, 0),
+ 8, 8, TLV_DB_SCALE_ITEM(-7220, 0, 0),
+ 9, 9, TLV_DB_SCALE_ITEM(-6870, 0, 0),
+ 10, 10, TLV_DB_SCALE_ITEM(-6620, 0, 0),
+ 11, 11, TLV_DB_SCALE_ITEM(-6270, 0, 0),
+ 12, 12, TLV_DB_SCALE_ITEM(-6020, 0, 0),
+ 13, 13, TLV_DB_SCALE_ITEM(-5670, 0, 0),
+ 14, 14, TLV_DB_SCALE_ITEM(-5420, 0, 0),
+ 15, 17, TLV_DB_SCALE_ITEM(-5060, 250, 0),
+ 18, 18, TLV_DB_SCALE_ITEM(-4370, 0, 0),
+ 19, 19, TLV_DB_SCALE_ITEM(-4210, 0, 0),
+ 20, 20, TLV_DB_SCALE_ITEM(-3960, 0, 0),
+ 21, 21, TLV_DB_SCALE_ITEM(-3760, 0, 0),
+ 22, 22, TLV_DB_SCALE_ITEM(-3600, 0, 0),
+ 23, 23, TLV_DB_SCALE_ITEM(-3340, 0, 0),
+ 24, 24, TLV_DB_SCALE_ITEM(-3150, 0, 0),
+ 25, 25, TLV_DB_SCALE_ITEM(-2980, 0, 0),
+ 26, 26, TLV_DB_SCALE_ITEM(-2720, 0, 0),
+ 27, 27, TLV_DB_SCALE_ITEM(-2520, 0, 0),
+ 28, 30, TLV_DB_SCALE_ITEM(-2350, 190, 0),
+ 31, 31, TLV_DB_SCALE_ITEM(-1750, 0, 0),
+ 32, 34, TLV_DB_SCALE_ITEM(-1640, 100, 0),
+ 35, 37, TLV_DB_SCALE_ITEM(-1310, 110, 0),
+ 38, 39, TLV_DB_SCALE_ITEM(-990, 100, 0),
+ 40, 40, TLV_DB_SCALE_ITEM(-710, 0, 0),
+ 41, 41, TLV_DB_SCALE_ITEM(-600, 0, 0),
+ 42, 42, TLV_DB_SCALE_ITEM(-500, 0, 0),
+ 43, 43, TLV_DB_SCALE_ITEM(-340, 0, 0),
+ 44, 44, TLV_DB_SCALE_ITEM(-190, 0, 0),
+ 45, 45, TLV_DB_SCALE_ITEM(-50, 0, 0),
+ 46, 46, TLV_DB_SCALE_ITEM(50, 0, 0),
+ 47, 50, TLV_DB_SCALE_ITEM(120, 40, 0),
+ 51, 57, TLV_DB_SCALE_ITEM(290, 50, 0),
+ 58, 58, TLV_DB_SCALE_ITEM(650, 0, 0),
+ 59, 62, TLV_DB_SCALE_ITEM(700, 60, 0),
+ 63, 63, TLV_DB_SCALE_ITEM(950, 0, 0),
+};
+
+static const struct snd_kcontrol_new max9768_volume[] = {
+ SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv),
+};
+
+static const struct snd_kcontrol_new max9768_mute[] = {
+ SOC_SINGLE_BOOL_EXT("Playback Switch", 0, max9768_get_gpio, max9768_set_gpio),
+};
+
+static int max9768_probe(struct snd_soc_codec *codec)
+{
+ struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ codec->control_data = max9768->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP);
+ if (ret)
+ return ret;
+
+ if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) {
+ ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM);
+ if (ret)
+ return ret;
+ }
+
+ if (gpio_is_valid(max9768->mute_gpio)) {
+ ret = snd_soc_add_codec_controls(codec, max9768_mute,
+ ARRAY_SIZE(max9768_mute));
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_codec_driver max9768_codec_driver = {
+ .probe = max9768_probe,
+ .controls = max9768_volume,
+ .num_controls = ARRAY_SIZE(max9768_volume),
+};
+
+static const struct regmap_config max9768_i2c_regmap_config = {
+ .reg_bits = 2,
+ .val_bits = 6,
+ .max_register = 3,
+ .reg_defaults = max9768_default_regs,
+ .num_reg_defaults = ARRAY_SIZE(max9768_default_regs),
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static int __devinit max9768_i2c_probe(struct i2c_client *client,
+ const struct i2c_device_id *id)
+{
+ struct max9768 *max9768;
+ struct max9768_pdata *pdata = client->dev.platform_data;
+ int err;
+
+ max9768 = devm_kzalloc(&client->dev, sizeof(*max9768), GFP_KERNEL);
+ if (!max9768)
+ return -ENOMEM;
+
+ if (pdata) {
+ /* Mute on powerup to avoid clicks */
+ err = gpio_request_one(pdata->mute_gpio, GPIOF_INIT_HIGH, "MAX9768 Mute");
+ max9768->mute_gpio = err ?: pdata->mute_gpio;
+
+ /* Activate chip by releasing shutdown, enables I2C */
+ err = gpio_request_one(pdata->shdn_gpio, GPIOF_INIT_HIGH, "MAX9768 Shutdown");
+ max9768->shdn_gpio = err ?: pdata->shdn_gpio;
+
+ max9768->flags = pdata->flags;
+ } else {
+ max9768->shdn_gpio = -EINVAL;
+ max9768->mute_gpio = -EINVAL;
+ }
+
+ i2c_set_clientdata(client, max9768);
+
+ max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config);
+ if (IS_ERR(max9768->regmap)) {
+ err = PTR_ERR(max9768->regmap);
+ goto err_gpio_free;
+ }
+
+ err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0);
+ if (err)
+ goto err_regmap_free;
+
+ return 0;
+
+ err_regmap_free:
+ regmap_exit(max9768->regmap);
+ err_gpio_free:
+ if (gpio_is_valid(max9768->shdn_gpio))
+ gpio_free(max9768->shdn_gpio);
+ if (gpio_is_valid(max9768->mute_gpio))
+ gpio_free(max9768->mute_gpio);
+
+ return err;
+}
+
+static int __devexit max9768_i2c_remove(struct i2c_client *client)
+{
+ struct max9768 *max9768 = i2c_get_clientdata(client);
+
+ snd_soc_unregister_codec(&client->dev);
+ regmap_exit(max9768->regmap);
+
+ if (gpio_is_valid(max9768->shdn_gpio))
+ gpio_free(max9768->shdn_gpio);
+ if (gpio_is_valid(max9768->mute_gpio))
+ gpio_free(max9768->mute_gpio);
+
+ return 0;
+}
+
+static const struct i2c_device_id max9768_i2c_id[] = {
+ { "max9768", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, max9768_i2c_id);
+
+static struct i2c_driver max9768_i2c_driver = {
+ .driver = {
+ .name = "max9768",
+ .owner = THIS_MODULE,
+ },
+ .probe = max9768_i2c_probe,
+ .remove = __devexit_p(max9768_i2c_remove),
+ .id_table = max9768_i2c_id,
+};
+module_i2c_driver(max9768_i2c_driver);
+
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("ASoC MAX9768 amplifier driver");
+MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c
index ac65a2d36408..af7324b79dd0 100644
--- a/sound/soc/codecs/max98088.c
+++ b/sound/soc/codecs/max98088.c
@@ -15,7 +15,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -40,7 +39,6 @@ struct max98088_cdata {
struct max98088_priv {
enum max98088_type devtype;
- void *control_data;
struct max98088_pdata *pdata;
unsigned int sysclk;
struct max98088_cdata dai[2];
@@ -1651,14 +1649,14 @@ static int max98088_set_bias_level(struct snd_soc_codec *codec,
#define MAX98088_RATES SNDRV_PCM_RATE_8000_96000
#define MAX98088_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops max98088_dai1_ops = {
+static const struct snd_soc_dai_ops max98088_dai1_ops = {
.set_sysclk = max98088_dai_set_sysclk,
.set_fmt = max98088_dai1_set_fmt,
.hw_params = max98088_dai1_hw_params,
.digital_mute = max98088_dai1_digital_mute,
};
-static struct snd_soc_dai_ops max98088_dai2_ops = {
+static const struct snd_soc_dai_ops max98088_dai2_ops = {
.set_sysclk = max98088_dai_set_sysclk,
.set_fmt = max98088_dai2_set_fmt,
.hw_params = max98088_dai2_hw_params,
@@ -1697,13 +1695,19 @@ static struct snd_soc_dai_driver max98088_dai[] = {
}
};
-static int max98088_get_channel(const char *name)
+static const char *eq_mode_name[] = {"EQ1 Mode", "EQ2 Mode"};
+
+static int max98088_get_channel(struct snd_soc_codec *codec, const char *name)
{
- if (strcmp(name, "EQ1 Mode") == 0)
- return 0;
- if (strcmp(name, "EQ2 Mode") == 0)
- return 1;
- return -EINVAL;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(eq_mode_name); i++)
+ if (strcmp(name, eq_mode_name[i]) == 0)
+ return i;
+
+ /* Shouldn't happen */
+ dev_err(codec->dev, "Bad EQ channel name '%s'\n", name);
+ return -EINVAL;
}
static void max98088_setup_eq1(struct snd_soc_codec *codec)
@@ -1807,10 +1811,13 @@ static int max98088_put_eq_enum(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
struct max98088_pdata *pdata = max98088->pdata;
- int channel = max98088_get_channel(kcontrol->id.name);
+ int channel = max98088_get_channel(codec, kcontrol->id.name);
struct max98088_cdata *cdata;
int sel = ucontrol->value.integer.value[0];
+ if (channel < 0)
+ return channel;
+
cdata = &max98088->dai[channel];
if (sel >= pdata->eq_cfgcnt)
@@ -1835,9 +1842,12 @@ static int max98088_get_eq_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct max98088_priv *max98088 = snd_soc_codec_get_drvdata(codec);
- int channel = max98088_get_channel(kcontrol->id.name);
+ int channel = max98088_get_channel(codec, kcontrol->id.name);
struct max98088_cdata *cdata;
+ if (channel < 0)
+ return channel;
+
cdata = &max98088->dai[channel];
ucontrol->value.enumerated.item[0] = cdata->eq_sel;
return 0;
@@ -1852,17 +1862,17 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
int i, j;
const char **t;
int ret;
-
struct snd_kcontrol_new controls[] = {
- SOC_ENUM_EXT("EQ1 Mode",
+ SOC_ENUM_EXT((char *)eq_mode_name[0],
max98088->eq_enum,
max98088_get_eq_enum,
max98088_put_eq_enum),
- SOC_ENUM_EXT("EQ2 Mode",
+ SOC_ENUM_EXT((char *)eq_mode_name[1],
max98088->eq_enum,
max98088_get_eq_enum,
max98088_put_eq_enum),
};
+ BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(eq_mode_name));
cfg = pdata->eq_cfg;
cfgcnt = pdata->eq_cfgcnt;
@@ -1898,7 +1908,7 @@ static void max98088_handle_eq_pdata(struct snd_soc_codec *codec)
max98088->eq_enum.texts = max98088->eq_texts;
max98088->eq_enum.max = max98088->eq_textcnt;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
}
@@ -1936,7 +1946,7 @@ static void max98088_handle_pdata(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int max98088_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int max98088_suspend(struct snd_soc_codec *codec)
{
max98088_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -2020,7 +2030,7 @@ static int max98088_probe(struct snd_soc_codec *codec)
max98088_handle_pdata(codec);
- snd_soc_add_controls(codec, max98088_snd_controls,
+ snd_soc_add_codec_controls(codec, max98088_snd_controls,
ARRAY_SIZE(max98088_snd_controls));
err_access:
@@ -2059,27 +2069,24 @@ static int max98088_i2c_probe(struct i2c_client *i2c,
struct max98088_priv *max98088;
int ret;
- max98088 = kzalloc(sizeof(struct max98088_priv), GFP_KERNEL);
+ max98088 = devm_kzalloc(&i2c->dev, sizeof(struct max98088_priv),
+ GFP_KERNEL);
if (max98088 == NULL)
return -ENOMEM;
max98088->devtype = id->driver_data;
i2c_set_clientdata(i2c, max98088);
- max98088->control_data = i2c;
max98088->pdata = i2c->dev.platform_data;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_max98088, &max98088_dai[0], 2);
- if (ret < 0)
- kfree(max98088);
return ret;
}
static int __devexit max98088_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c
index 668434d44303..0bb511a0388d 100644
--- a/sound/soc/codecs/max98095.c
+++ b/sound/soc/codecs/max98095.c
@@ -15,7 +15,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -40,7 +39,6 @@ struct max98095_cdata {
struct max98095_priv {
enum max98095_type devtype;
- void *control_data;
struct max98095_pdata *pdata;
unsigned int sysclk;
struct max98095_cdata dai[3];
@@ -618,14 +616,13 @@ static int max98095_volatile(struct snd_soc_codec *codec, unsigned int reg)
static int max98095_hw_write(struct snd_soc_codec *codec, unsigned int reg,
unsigned int value)
{
- u8 data[2];
+ int ret;
- data[0] = reg;
- data[1] = value;
- if (codec->hw_write(codec->control_data, data, 2) == 2)
- return 0;
- else
- return -EIO;
+ codec->cache_bypass = 1;
+ ret = snd_soc_write(codec, reg, value);
+ codec->cache_bypass = 0;
+
+ return ret ? -EIO : 0;
}
/*
@@ -1287,7 +1284,7 @@ static const struct snd_soc_dapm_route max98095_audio_map[] = {
static int max98095_add_widgets(struct snd_soc_codec *codec)
{
- snd_soc_add_controls(codec, max98095_snd_controls,
+ snd_soc_add_codec_controls(codec, max98095_snd_controls,
ARRAY_SIZE(max98095_snd_controls));
return 0;
@@ -1784,19 +1781,19 @@ static int max98095_set_bias_level(struct snd_soc_codec *codec,
#define MAX98095_RATES SNDRV_PCM_RATE_8000_96000
#define MAX98095_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops max98095_dai1_ops = {
+static const struct snd_soc_dai_ops max98095_dai1_ops = {
.set_sysclk = max98095_dai_set_sysclk,
.set_fmt = max98095_dai1_set_fmt,
.hw_params = max98095_dai1_hw_params,
};
-static struct snd_soc_dai_ops max98095_dai2_ops = {
+static const struct snd_soc_dai_ops max98095_dai2_ops = {
.set_sysclk = max98095_dai_set_sysclk,
.set_fmt = max98095_dai2_set_fmt,
.hw_params = max98095_dai2_hw_params,
};
-static struct snd_soc_dai_ops max98095_dai3_ops = {
+static const struct snd_soc_dai_ops max98095_dai3_ops = {
.set_sysclk = max98095_dai_set_sysclk,
.set_fmt = max98095_dai3_set_fmt,
.hw_params = max98095_dai3_hw_params,
@@ -1987,17 +1984,24 @@ static void max98095_handle_eq_pdata(struct snd_soc_codec *codec)
max98095->eq_enum.texts = max98095->eq_texts;
max98095->eq_enum.max = max98095->eq_textcnt;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev, "Failed to add EQ control: %d\n", ret);
}
-static int max98095_get_bq_channel(const char *name)
+static const char *bq_mode_name[] = {"Biquad1 Mode", "Biquad2 Mode"};
+
+static int max98095_get_bq_channel(struct snd_soc_codec *codec,
+ const char *name)
{
- if (strcmp(name, "Biquad1 Mode") == 0)
- return 0;
- if (strcmp(name, "Biquad2 Mode") == 0)
- return 1;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(bq_mode_name); i++)
+ if (strcmp(name, bq_mode_name[i]) == 0)
+ return i;
+
+ /* Shouldn't happen */
+ dev_err(codec->dev, "Bad biquad channel name '%s'\n", name);
return -EINVAL;
}
@@ -2007,14 +2011,15 @@ static int max98095_put_bq_enum(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
struct max98095_pdata *pdata = max98095->pdata;
- int channel = max98095_get_bq_channel(kcontrol->id.name);
+ int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
struct max98095_cdata *cdata;
int sel = ucontrol->value.integer.value[0];
struct max98095_biquad_cfg *coef_set;
int fs, best, best_val, i;
int regmask, regsave;
- BUG_ON(channel > 1);
+ if (channel < 0)
+ return channel;
if (!pdata || !max98095->bq_textcnt)
return 0;
@@ -2066,9 +2071,12 @@ static int max98095_get_bq_enum(struct snd_kcontrol *kcontrol,
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
struct max98095_priv *max98095 = snd_soc_codec_get_drvdata(codec);
- int channel = max98095_get_bq_channel(kcontrol->id.name);
+ int channel = max98095_get_bq_channel(codec, kcontrol->id.name);
struct max98095_cdata *cdata;
+ if (channel < 0)
+ return channel;
+
cdata = &max98095->dai[channel];
ucontrol->value.enumerated.item[0] = cdata->bq_sel;
@@ -2086,15 +2094,16 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
int ret;
struct snd_kcontrol_new controls[] = {
- SOC_ENUM_EXT("Biquad1 Mode",
+ SOC_ENUM_EXT((char *)bq_mode_name[0],
max98095->bq_enum,
max98095_get_bq_enum,
max98095_put_bq_enum),
- SOC_ENUM_EXT("Biquad2 Mode",
+ SOC_ENUM_EXT((char *)bq_mode_name[1],
max98095->bq_enum,
max98095_get_bq_enum,
max98095_put_bq_enum),
};
+ BUILD_BUG_ON(ARRAY_SIZE(controls) != ARRAY_SIZE(bq_mode_name));
cfg = pdata->bq_cfg;
cfgcnt = pdata->bq_cfgcnt;
@@ -2130,7 +2139,7 @@ static void max98095_handle_bq_pdata(struct snd_soc_codec *codec)
max98095->bq_enum.texts = max98095->bq_texts;
max98095->bq_enum.max = max98095->bq_textcnt;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev, "Failed to add Biquad control: %d\n", ret);
}
@@ -2165,7 +2174,7 @@ static void max98095_handle_pdata(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int max98095_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int max98095_suspend(struct snd_soc_codec *codec)
{
max98095_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -2331,27 +2340,23 @@ static int max98095_i2c_probe(struct i2c_client *i2c,
struct max98095_priv *max98095;
int ret;
- max98095 = kzalloc(sizeof(struct max98095_priv), GFP_KERNEL);
+ max98095 = devm_kzalloc(&i2c->dev, sizeof(struct max98095_priv),
+ GFP_KERNEL);
if (max98095 == NULL)
return -ENOMEM;
max98095->devtype = id->driver_data;
i2c_set_clientdata(i2c, max98095);
- max98095->control_data = i2c;
max98095->pdata = i2c->dev.platform_data;
ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_max98095,
max98095_dai, ARRAY_SIZE(max98095_dai));
- if (ret < 0)
- kfree(max98095);
return ret;
}
static int __devexit max98095_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
-
return 0;
}
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c
index 208d2ee61855..a1913091f56c 100644
--- a/sound/soc/codecs/max9850.c
+++ b/sound/soc/codecs/max9850.c
@@ -86,7 +86,7 @@ SND_SOC_DAPM_INPUT("INL"),
SND_SOC_DAPM_INPUT("INR"),
};
-static const struct snd_soc_dapm_route intercon[] = {
+static const struct snd_soc_dapm_route max9850_dapm_routes[] = {
/* output mixer */
{"Output Mixer", NULL, "DAC"},
{"Output Mixer", "Line In Switch", "Line Input"},
@@ -254,7 +254,7 @@ static int max9850_set_bias_level(struct snd_soc_codec *codec,
#define MAX9850_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops max9850_dai_ops = {
+static const struct snd_soc_dai_ops max9850_dai_ops = {
.hw_params = max9850_hw_params,
.set_sysclk = max9850_set_dai_sysclk,
.set_fmt = max9850_set_dai_fmt,
@@ -273,7 +273,7 @@ static struct snd_soc_dai_driver max9850_dai = {
};
#ifdef CONFIG_PM
-static int max9850_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int max9850_suspend(struct snd_soc_codec *codec)
{
max9850_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -293,7 +293,6 @@ static int max9850_resume(struct snd_soc_codec *codec)
static int max9850_probe(struct snd_soc_codec *codec)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C);
@@ -309,13 +308,6 @@ static int max9850_probe(struct snd_soc_codec *codec)
/* set slew-rate 125ms */
snd_soc_update_bits(codec, MAX9850_CHARGE_PUMP, 0xff, 0xc0);
- snd_soc_dapm_new_controls(dapm, max9850_dapm_widgets,
- ARRAY_SIZE(max9850_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
- snd_soc_add_controls(codec, max9850_controls,
- ARRAY_SIZE(max9850_controls));
-
return 0;
}
@@ -328,6 +320,13 @@ static struct snd_soc_codec_driver soc_codec_dev_max9850 = {
.reg_word_size = sizeof(u8),
.reg_cache_default = max9850_reg,
.volatile_register = max9850_volatile_register,
+
+ .controls = max9850_controls,
+ .num_controls = ARRAY_SIZE(max9850_controls),
+ .dapm_widgets = max9850_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(max9850_dapm_widgets),
+ .dapm_routes = max9850_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(max9850_dapm_routes),
};
static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
@@ -336,7 +335,8 @@ static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
struct max9850_priv *max9850;
int ret;
- max9850 = kzalloc(sizeof(struct max9850_priv), GFP_KERNEL);
+ max9850 = devm_kzalloc(&i2c->dev, sizeof(struct max9850_priv),
+ GFP_KERNEL);
if (max9850 == NULL)
return -ENOMEM;
@@ -344,15 +344,12 @@ static int __devinit max9850_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_max9850, &max9850_dai, 1);
- if (ret < 0)
- kfree(max9850);
return ret;
}
static __devexit int max9850_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c
index 9e7e964a5fa3..3a2ba3d8fd6d 100644
--- a/sound/soc/codecs/max9877.c
+++ b/sound/soc/codecs/max9877.c
@@ -106,13 +106,13 @@ static int max9877_set_2reg(struct snd_kcontrol *kcontrol,
unsigned int mask = mc->max;
unsigned int val = (ucontrol->value.integer.value[0] & mask);
unsigned int val2 = (ucontrol->value.integer.value[1] & mask);
- unsigned int change = 1;
+ unsigned int change = 0;
- if (((max9877_regs[reg] >> shift) & mask) == val)
- change = 0;
+ if (((max9877_regs[reg] >> shift) & mask) != val)
+ change = 1;
- if (((max9877_regs[reg2] >> shift) & mask) == val2)
- change = 0;
+ if (((max9877_regs[reg2] >> shift) & mask) != val2)
+ change = 1;
if (change) {
max9877_regs[reg] &= ~(mask << shift);
@@ -253,7 +253,7 @@ static const struct snd_kcontrol_new max9877_controls[] = {
/* This function is called from ASoC machine driver */
int max9877_add_controls(struct snd_soc_codec *codec)
{
- return snd_soc_add_controls(codec, max9877_controls,
+ return snd_soc_add_codec_controls(codec, max9877_controls,
ARRAY_SIZE(max9877_controls));
}
EXPORT_SYMBOL_GPL(max9877_add_controls);
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
index bd8f26e41602..edcaa7ea5487 100644
--- a/sound/soc/codecs/pcm3008.c
+++ b/sound/soc/codecs/pcm3008.c
@@ -20,6 +20,7 @@
#include <linux/device.h>
#include <linux/gpio.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/initval.h>
@@ -117,7 +118,7 @@ static int pcm3008_soc_remove(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int pcm3008_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
+static int pcm3008_soc_suspend(struct snd_soc_codec *codec)
{
struct pcm3008_setup_data *setup = codec->dev->platform_data;
@@ -171,17 +172,7 @@ static struct platform_driver pcm3008_codec_driver = {
},
};
-static int __init pcm3008_modinit(void)
-{
- return platform_driver_register(&pcm3008_codec_driver);
-}
-module_init(pcm3008_modinit);
-
-static void __exit pcm3008_exit(void)
-{
- platform_driver_unregister(&pcm3008_codec_driver);
-}
-module_exit(pcm3008_exit);
+module_platform_driver(pcm3008_codec_driver);
MODULE_DESCRIPTION("Soc PCM3008 driver");
MODULE_AUTHOR("Hugo Villeneuve");
diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c
new file mode 100644
index 000000000000..20c324c7c349
--- /dev/null
+++ b/sound/soc/codecs/rt5631.c
@@ -0,0 +1,1769 @@
+/*
+ * rt5631.c -- RT5631 ALSA Soc Audio driver
+ *
+ * Copyright 2011 Realtek Microelectronics
+ *
+ * Author: flove <flove@realtek.com>
+ *
+ * Based on WM8753.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ */
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/i2c.h>
+#include <linux/spi/spi.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+
+#include "rt5631.h"
+
+struct rt5631_priv {
+ int codec_version;
+ int master;
+ int sysclk;
+ int rx_rate;
+ int bclk_rate;
+ int dmic_used_flag;
+};
+
+static const u16 rt5631_reg[RT5631_VENDOR_ID2 + 1] = {
+ [RT5631_SPK_OUT_VOL] = 0x8888,
+ [RT5631_HP_OUT_VOL] = 0x8080,
+ [RT5631_MONO_AXO_1_2_VOL] = 0xa080,
+ [RT5631_AUX_IN_VOL] = 0x0808,
+ [RT5631_ADC_REC_MIXER] = 0xf0f0,
+ [RT5631_VDAC_DIG_VOL] = 0x0010,
+ [RT5631_OUTMIXER_L_CTRL] = 0xffc0,
+ [RT5631_OUTMIXER_R_CTRL] = 0xffc0,
+ [RT5631_AXO1MIXER_CTRL] = 0x88c0,
+ [RT5631_AXO2MIXER_CTRL] = 0x88c0,
+ [RT5631_DIG_MIC_CTRL] = 0x3000,
+ [RT5631_MONO_INPUT_VOL] = 0x8808,
+ [RT5631_SPK_MIXER_CTRL] = 0xf8f8,
+ [RT5631_SPK_MONO_OUT_CTRL] = 0xfc00,
+ [RT5631_SPK_MONO_HP_OUT_CTRL] = 0x4440,
+ [RT5631_SDP_CTRL] = 0x8000,
+ [RT5631_MONO_SDP_CTRL] = 0x8000,
+ [RT5631_STEREO_AD_DA_CLK_CTRL] = 0x2010,
+ [RT5631_GEN_PUR_CTRL_REG] = 0x0e00,
+ [RT5631_INT_ST_IRQ_CTRL_2] = 0x071a,
+ [RT5631_MISC_CTRL] = 0x2040,
+ [RT5631_DEPOP_FUN_CTRL_2] = 0x8000,
+ [RT5631_SOFT_VOL_CTRL] = 0x07e0,
+ [RT5631_ALC_CTRL_1] = 0x0206,
+ [RT5631_ALC_CTRL_3] = 0x2000,
+ [RT5631_PSEUDO_SPATL_CTRL] = 0x0553,
+};
+
+/**
+ * rt5631_write_index - write index register of 2nd layer
+ */
+static void rt5631_write_index(struct snd_soc_codec *codec,
+ unsigned int reg, unsigned int value)
+{
+ snd_soc_write(codec, RT5631_INDEX_ADD, reg);
+ snd_soc_write(codec, RT5631_INDEX_DATA, value);
+}
+
+/**
+ * rt5631_read_index - read index register of 2nd layer
+ */
+static unsigned int rt5631_read_index(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ unsigned int value;
+
+ snd_soc_write(codec, RT5631_INDEX_ADD, reg);
+ value = snd_soc_read(codec, RT5631_INDEX_DATA);
+
+ return value;
+}
+
+static int rt5631_reset(struct snd_soc_codec *codec)
+{
+ return snd_soc_write(codec, RT5631_RESET, 0);
+}
+
+static int rt5631_volatile_register(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ switch (reg) {
+ case RT5631_RESET:
+ case RT5631_INT_ST_IRQ_CTRL_2:
+ case RT5631_INDEX_ADD:
+ case RT5631_INDEX_DATA:
+ case RT5631_EQ_CTRL:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int rt5631_readable_register(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ switch (reg) {
+ case RT5631_RESET:
+ case RT5631_SPK_OUT_VOL:
+ case RT5631_HP_OUT_VOL:
+ case RT5631_MONO_AXO_1_2_VOL:
+ case RT5631_AUX_IN_VOL:
+ case RT5631_STEREO_DAC_VOL_1:
+ case RT5631_MIC_CTRL_1:
+ case RT5631_STEREO_DAC_VOL_2:
+ case RT5631_ADC_CTRL_1:
+ case RT5631_ADC_REC_MIXER:
+ case RT5631_ADC_CTRL_2:
+ case RT5631_VDAC_DIG_VOL:
+ case RT5631_OUTMIXER_L_CTRL:
+ case RT5631_OUTMIXER_R_CTRL:
+ case RT5631_AXO1MIXER_CTRL:
+ case RT5631_AXO2MIXER_CTRL:
+ case RT5631_MIC_CTRL_2:
+ case RT5631_DIG_MIC_CTRL:
+ case RT5631_MONO_INPUT_VOL:
+ case RT5631_SPK_MIXER_CTRL:
+ case RT5631_SPK_MONO_OUT_CTRL:
+ case RT5631_SPK_MONO_HP_OUT_CTRL:
+ case RT5631_SDP_CTRL:
+ case RT5631_MONO_SDP_CTRL:
+ case RT5631_STEREO_AD_DA_CLK_CTRL:
+ case RT5631_PWR_MANAG_ADD1:
+ case RT5631_PWR_MANAG_ADD2:
+ case RT5631_PWR_MANAG_ADD3:
+ case RT5631_PWR_MANAG_ADD4:
+ case RT5631_GEN_PUR_CTRL_REG:
+ case RT5631_GLOBAL_CLK_CTRL:
+ case RT5631_PLL_CTRL:
+ case RT5631_INT_ST_IRQ_CTRL_1:
+ case RT5631_INT_ST_IRQ_CTRL_2:
+ case RT5631_GPIO_CTRL:
+ case RT5631_MISC_CTRL:
+ case RT5631_DEPOP_FUN_CTRL_1:
+ case RT5631_DEPOP_FUN_CTRL_2:
+ case RT5631_JACK_DET_CTRL:
+ case RT5631_SOFT_VOL_CTRL:
+ case RT5631_ALC_CTRL_1:
+ case RT5631_ALC_CTRL_2:
+ case RT5631_ALC_CTRL_3:
+ case RT5631_PSEUDO_SPATL_CTRL:
+ case RT5631_INDEX_ADD:
+ case RT5631_INDEX_DATA:
+ case RT5631_EQ_CTRL:
+ case RT5631_VENDOR_ID:
+ case RT5631_VENDOR_ID1:
+ case RT5631_VENDOR_ID2:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0);
+static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -95625, 375, 0);
+static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0);
+/* {0, +20, +24, +30, +35, +40, +44, +50, +52}dB */
+static unsigned int mic_bst_tlv[] = {
+ TLV_DB_RANGE_HEAD(7),
+ 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
+ 1, 1, TLV_DB_SCALE_ITEM(2000, 0, 0),
+ 2, 2, TLV_DB_SCALE_ITEM(2400, 0, 0),
+ 3, 5, TLV_DB_SCALE_ITEM(3000, 500, 0),
+ 6, 6, TLV_DB_SCALE_ITEM(4400, 0, 0),
+ 7, 7, TLV_DB_SCALE_ITEM(5000, 0, 0),
+ 8, 8, TLV_DB_SCALE_ITEM(5200, 0, 0),
+};
+
+static int rt5631_dmic_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = rt5631->dmic_used_flag;
+
+ return 0;
+}
+
+static int rt5631_dmic_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+ rt5631->dmic_used_flag = ucontrol->value.integer.value[0];
+ return 0;
+}
+
+/* MIC Input Type */
+static const char *rt5631_input_mode[] = {
+ "Single ended", "Differential"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_mic1_mode_enum, RT5631_MIC_CTRL_1,
+ RT5631_MIC1_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_mic2_mode_enum, RT5631_MIC_CTRL_1,
+ RT5631_MIC2_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+/* MONO Input Type */
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_monoin_mode_enum, RT5631_MONO_INPUT_VOL,
+ RT5631_MONO_DIFF_INPUT_SHIFT, rt5631_input_mode);
+
+/* SPK Ratio Gain Control */
+static const char *rt5631_spk_ratio[] = {"1.00x", "1.09x", "1.27x", "1.44x",
+ "1.56x", "1.68x", "1.99x", "2.34x"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_spk_ratio_enum, RT5631_GEN_PUR_CTRL_REG,
+ RT5631_SPK_AMP_RATIO_CTRL_SHIFT, rt5631_spk_ratio);
+
+static const struct snd_kcontrol_new rt5631_snd_controls[] = {
+ /* MIC */
+ SOC_ENUM("MIC1 Mode Control", rt5631_mic1_mode_enum),
+ SOC_SINGLE_TLV("MIC1 Boost", RT5631_MIC_CTRL_2,
+ RT5631_MIC1_BOOST_SHIFT, 8, 0, mic_bst_tlv),
+ SOC_ENUM("MIC2 Mode Control", rt5631_mic2_mode_enum),
+ SOC_SINGLE_TLV("MIC2 Boost", RT5631_MIC_CTRL_2,
+ RT5631_MIC2_BOOST_SHIFT, 8, 0, mic_bst_tlv),
+ /* MONO IN */
+ SOC_ENUM("MONOIN Mode Control", rt5631_monoin_mode_enum),
+ SOC_DOUBLE_TLV("MONOIN_RX Capture Volume", RT5631_MONO_INPUT_VOL,
+ RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+ RT5631_VOL_MASK, 1, in_vol_tlv),
+ /* AXI */
+ SOC_DOUBLE_TLV("AXI Capture Volume", RT5631_AUX_IN_VOL,
+ RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+ RT5631_VOL_MASK, 1, in_vol_tlv),
+ /* DAC */
+ SOC_DOUBLE_TLV("PCM Playback Volume", RT5631_STEREO_DAC_VOL_2,
+ RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+ RT5631_DAC_VOL_MASK, 1, dac_vol_tlv),
+ SOC_DOUBLE("PCM Playback Switch", RT5631_STEREO_DAC_VOL_1,
+ RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+ /* AXO */
+ SOC_SINGLE("AXO1 Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+ RT5631_L_MUTE_SHIFT, 1, 1),
+ SOC_SINGLE("AXO2 Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+ RT5631_R_VOL_SHIFT, 1, 1),
+ /* OUTVOL */
+ SOC_DOUBLE("OUTVOL Channel Switch", RT5631_SPK_OUT_VOL,
+ RT5631_L_EN_SHIFT, RT5631_R_EN_SHIFT, 1, 0),
+
+ /* SPK */
+ SOC_DOUBLE("Speaker Playback Switch", RT5631_SPK_OUT_VOL,
+ RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+ SOC_DOUBLE_TLV("Speaker Playback Volume", RT5631_SPK_OUT_VOL,
+ RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT, 39, 1, out_vol_tlv),
+ /* MONO OUT */
+ SOC_SINGLE("MONO Playback Switch", RT5631_MONO_AXO_1_2_VOL,
+ RT5631_MUTE_MONO_SHIFT, 1, 1),
+ /* HP */
+ SOC_DOUBLE("HP Playback Switch", RT5631_HP_OUT_VOL,
+ RT5631_L_MUTE_SHIFT, RT5631_R_MUTE_SHIFT, 1, 1),
+ SOC_DOUBLE_TLV("HP Playback Volume", RT5631_HP_OUT_VOL,
+ RT5631_L_VOL_SHIFT, RT5631_R_VOL_SHIFT,
+ RT5631_VOL_MASK, 1, out_vol_tlv),
+ /* DMIC */
+ SOC_SINGLE_EXT("DMIC Switch", 0, 0, 1, 0,
+ rt5631_dmic_get, rt5631_dmic_put),
+ SOC_DOUBLE("DMIC Capture Switch", RT5631_DIG_MIC_CTRL,
+ RT5631_DMIC_L_CH_MUTE_SHIFT,
+ RT5631_DMIC_R_CH_MUTE_SHIFT, 1, 1),
+
+ /* SPK Ratio Gain Control */
+ SOC_ENUM("SPK Ratio Control", rt5631_spk_ratio_enum),
+};
+
+static int check_sysclk1_source(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int reg;
+
+ reg = snd_soc_read(source->codec, RT5631_GLOBAL_CLK_CTRL);
+ return reg & RT5631_SYSCLK_SOUR_SEL_PLL;
+}
+
+static int check_dmic_used(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(source->codec);
+ return rt5631->dmic_used_flag;
+}
+
+static int check_dacl_to_outmixl(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int reg;
+
+ reg = snd_soc_read(source->codec, RT5631_OUTMIXER_L_CTRL);
+ return !(reg & RT5631_M_DAC_L_TO_OUTMIXER_L);
+}
+
+static int check_dacr_to_outmixr(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int reg;
+
+ reg = snd_soc_read(source->codec, RT5631_OUTMIXER_R_CTRL);
+ return !(reg & RT5631_M_DAC_R_TO_OUTMIXER_R);
+}
+
+static int check_dacl_to_spkmixl(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int reg;
+
+ reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
+ return !(reg & RT5631_M_DAC_L_TO_SPKMIXER_L);
+}
+
+static int check_dacr_to_spkmixr(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int reg;
+
+ reg = snd_soc_read(source->codec, RT5631_SPK_MIXER_CTRL);
+ return !(reg & RT5631_M_DAC_R_TO_SPKMIXER_R);
+}
+
+static int check_adcl_select(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int reg;
+
+ reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
+ return !(reg & RT5631_M_MIC1_TO_RECMIXER_L);
+}
+
+static int check_adcr_select(struct snd_soc_dapm_widget *source,
+ struct snd_soc_dapm_widget *sink)
+{
+ unsigned int reg;
+
+ reg = snd_soc_read(source->codec, RT5631_ADC_REC_MIXER);
+ return !(reg & RT5631_M_MIC2_TO_RECMIXER_R);
+}
+
+/**
+ * onebit_depop_power_stage - auto depop in power stage.
+ * @enable: power on/off
+ *
+ * When power on/off headphone, the depop sequence is done by hardware.
+ */
+static void onebit_depop_power_stage(struct snd_soc_codec *codec, int enable)
+{
+ unsigned int soft_vol, hp_zc;
+
+ /* enable one-bit depop function */
+ snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+ RT5631_EN_ONE_BIT_DEPOP, 0);
+
+ /* keep soft volume and zero crossing setting */
+ soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+ snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+ hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+ snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+ if (enable) {
+ /* config one-bit depop parameter */
+ rt5631_write_index(codec, RT5631_TEST_MODE_CTRL, 0x84c0);
+ rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x309f);
+ rt5631_write_index(codec, RT5631_CP_INTL_REG2, 0x6530);
+ /* power on capless block */
+ snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2,
+ RT5631_EN_CAP_FREE_DEPOP);
+ } else {
+ /* power off capless block */
+ snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_2, 0);
+ msleep(100);
+ }
+
+ /* recover soft volume and zero crossing setting */
+ snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+ snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * onebit_depop_mute_stage - auto depop in mute stage.
+ * @enable: mute/unmute
+ *
+ * When mute/unmute headphone, the depop sequence is done by hardware.
+ */
+static void onebit_depop_mute_stage(struct snd_soc_codec *codec, int enable)
+{
+ unsigned int soft_vol, hp_zc;
+
+ /* enable one-bit depop function */
+ snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+ RT5631_EN_ONE_BIT_DEPOP, 0);
+
+ /* keep soft volume and zero crossing setting */
+ soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+ snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+ hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+ snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+ if (enable) {
+ schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+ /* config one-bit depop parameter */
+ rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x307f);
+ snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+ RT5631_L_MUTE | RT5631_R_MUTE, 0);
+ msleep(300);
+ } else {
+ snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+ RT5631_L_MUTE | RT5631_R_MUTE,
+ RT5631_L_MUTE | RT5631_R_MUTE);
+ msleep(100);
+ }
+
+ /* recover soft volume and zero crossing setting */
+ snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+ snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * onebit_depop_power_stage - step by step depop sequence in power stage.
+ * @enable: power on/off
+ *
+ * When power on/off headphone, the depop sequence is done in step by step.
+ */
+static void depop_seq_power_stage(struct snd_soc_codec *codec, int enable)
+{
+ unsigned int soft_vol, hp_zc;
+
+ /* depop control by register */
+ snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+ RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP);
+
+ /* keep soft volume and zero crossing setting */
+ soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+ snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+ hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+ snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+ if (enable) {
+ /* config depop sequence parameter */
+ rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303e);
+
+ /* power on headphone and charge pump */
+ snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+ RT5631_PWR_HP_R_AMP,
+ RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+ RT5631_PWR_HP_R_AMP);
+
+ /* power on soft generator and depop mode2 */
+ snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+ RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP);
+ msleep(100);
+
+ /* stop depop mode */
+ snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_HP_DEPOP_DIS, RT5631_PWR_HP_DEPOP_DIS);
+ } else {
+ /* config depop sequence parameter */
+ rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x303F);
+ snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+ RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+ RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP);
+ msleep(75);
+ snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+ RT5631_POW_ON_SOFT_GEN | RT5631_PD_HPAMP_L_ST_UP |
+ RT5631_PD_HPAMP_R_ST_UP);
+
+ /* start depop mode */
+ snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_HP_DEPOP_DIS, 0);
+
+ /* config depop sequence parameter */
+ snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+ RT5631_POW_ON_SOFT_GEN | RT5631_EN_DEPOP2_FOR_HP |
+ RT5631_PD_HPAMP_L_ST_UP | RT5631_PD_HPAMP_R_ST_UP);
+ msleep(80);
+ snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+ RT5631_POW_ON_SOFT_GEN);
+
+ /* power down headphone and charge pump */
+ snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_CHARGE_PUMP | RT5631_PWR_HP_L_AMP |
+ RT5631_PWR_HP_R_AMP, 0);
+ }
+
+ /* recover soft volume and zero crossing setting */
+ snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+ snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+/**
+ * depop_seq_mute_stage - step by step depop sequence in mute stage.
+ * @enable: mute/unmute
+ *
+ * When mute/unmute headphone, the depop sequence is done in step by step.
+ */
+static void depop_seq_mute_stage(struct snd_soc_codec *codec, int enable)
+{
+ unsigned int soft_vol, hp_zc;
+
+ /* depop control by register */
+ snd_soc_update_bits(codec, RT5631_DEPOP_FUN_CTRL_2,
+ RT5631_EN_ONE_BIT_DEPOP, RT5631_EN_ONE_BIT_DEPOP);
+
+ /* keep soft volume and zero crossing setting */
+ soft_vol = snd_soc_read(codec, RT5631_SOFT_VOL_CTRL);
+ snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, 0);
+ hp_zc = snd_soc_read(codec, RT5631_INT_ST_IRQ_CTRL_2);
+ snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc & 0xf7ff);
+ if (enable) {
+ schedule_timeout_uninterruptible(msecs_to_jiffies(10));
+
+ /* config depop sequence parameter */
+ rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f);
+ snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+ RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+ RT5631_EN_HP_R_M_UN_MUTE_DEPOP |
+ RT5631_EN_HP_L_M_UN_MUTE_DEPOP);
+
+ snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+ RT5631_L_MUTE | RT5631_R_MUTE, 0);
+ msleep(160);
+ } else {
+ /* config depop sequence parameter */
+ rt5631_write_index(codec, RT5631_SPK_INTL_CTRL, 0x302f);
+ snd_soc_write(codec, RT5631_DEPOP_FUN_CTRL_1,
+ RT5631_POW_ON_SOFT_GEN | RT5631_EN_MUTE_UNMUTE_DEPOP |
+ RT5631_EN_HP_R_M_UN_MUTE_DEPOP |
+ RT5631_EN_HP_L_M_UN_MUTE_DEPOP);
+
+ snd_soc_update_bits(codec, RT5631_HP_OUT_VOL,
+ RT5631_L_MUTE | RT5631_R_MUTE,
+ RT5631_L_MUTE | RT5631_R_MUTE);
+ msleep(150);
+ }
+
+ /* recover soft volume and zero crossing setting */
+ snd_soc_write(codec, RT5631_SOFT_VOL_CTRL, soft_vol);
+ snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, hp_zc);
+}
+
+static int hp_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMD:
+ if (rt5631->codec_version) {
+ onebit_depop_mute_stage(codec, 0);
+ onebit_depop_power_stage(codec, 0);
+ } else {
+ depop_seq_mute_stage(codec, 0);
+ depop_seq_power_stage(codec, 0);
+ }
+ break;
+
+ case SND_SOC_DAPM_POST_PMU:
+ if (rt5631->codec_version) {
+ onebit_depop_power_stage(codec, 1);
+ onebit_depop_mute_stage(codec, 1);
+ } else {
+ depop_seq_power_stage(codec, 1);
+ depop_seq_mute_stage(codec, 1);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int set_dmic_params(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+ switch (rt5631->rx_rate) {
+ case 44100:
+ case 48000:
+ snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+ RT5631_DMIC_CLK_CTRL_MASK,
+ RT5631_DMIC_CLK_CTRL_TO_32FS);
+ break;
+
+ case 32000:
+ case 22050:
+ snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+ RT5631_DMIC_CLK_CTRL_MASK,
+ RT5631_DMIC_CLK_CTRL_TO_64FS);
+ break;
+
+ case 16000:
+ case 11025:
+ case 8000:
+ snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+ RT5631_DMIC_CLK_CTRL_MASK,
+ RT5631_DMIC_CLK_CTRL_TO_128FS);
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const struct snd_kcontrol_new rt5631_recmixl_mixer_controls[] = {
+ SOC_DAPM_SINGLE("OUTMIXL Capture Switch", RT5631_ADC_REC_MIXER,
+ RT5631_M_OUTMIXL_RECMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MIC1_BST1 Capture Switch", RT5631_ADC_REC_MIXER,
+ RT5631_M_MIC1_RECMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("AXILVOL Capture Switch", RT5631_ADC_REC_MIXER,
+ RT5631_M_AXIL_RECMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER,
+ RT5631_M_MONO_IN_RECMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_recmixr_mixer_controls[] = {
+ SOC_DAPM_SINGLE("MONOIN_RX Capture Switch", RT5631_ADC_REC_MIXER,
+ RT5631_M_MONO_IN_RECMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("AXIRVOL Capture Switch", RT5631_ADC_REC_MIXER,
+ RT5631_M_AXIR_RECMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MIC2_BST2 Capture Switch", RT5631_ADC_REC_MIXER,
+ RT5631_M_MIC2_RECMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("OUTMIXR Capture Switch", RT5631_ADC_REC_MIXER,
+ RT5631_M_OUTMIXR_RECMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spkmixl_mixer_controls[] = {
+ SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_SPK_MIXER_CTRL,
+ RT5631_M_RECMIXL_SPKMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MIC1_P Playback Switch", RT5631_SPK_MIXER_CTRL,
+ RT5631_M_MIC1P_SPKMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_SPK_MIXER_CTRL,
+ RT5631_M_DACL_SPKMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("OUTMIXL Playback Switch", RT5631_SPK_MIXER_CTRL,
+ RT5631_M_OUTMIXL_SPKMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spkmixr_mixer_controls[] = {
+ SOC_DAPM_SINGLE("OUTMIXR Playback Switch", RT5631_SPK_MIXER_CTRL,
+ RT5631_M_OUTMIXR_SPKMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_SPK_MIXER_CTRL,
+ RT5631_M_DACR_SPKMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MIC2_P Playback Switch", RT5631_SPK_MIXER_CTRL,
+ RT5631_M_MIC2P_SPKMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_SPK_MIXER_CTRL,
+ RT5631_M_RECMIXR_SPKMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_outmixl_mixer_controls[] = {
+ SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+ RT5631_M_RECMIXL_OUTMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_L_CTRL,
+ RT5631_M_RECMIXR_OUTMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("DACL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+ RT5631_M_DACL_OUTMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_L_CTRL,
+ RT5631_M_MIC1_OUTMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_L_CTRL,
+ RT5631_M_MIC2_OUTMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MONOIN_RXP Playback Switch", RT5631_OUTMIXER_L_CTRL,
+ RT5631_M_MONO_INP_OUTMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+ RT5631_M_AXIL_OUTMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_L_CTRL,
+ RT5631_M_AXIR_OUTMIXL_BIT, 1, 1),
+ SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_L_CTRL,
+ RT5631_M_VDAC_OUTMIXL_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_outmixr_mixer_controls[] = {
+ SOC_DAPM_SINGLE("VDAC Playback Switch", RT5631_OUTMIXER_R_CTRL,
+ RT5631_M_VDAC_OUTMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("AXIRVOL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+ RT5631_M_AXIR_OUTMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("AXILVOL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+ RT5631_M_AXIL_OUTMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MONOIN_RXN Playback Switch", RT5631_OUTMIXER_R_CTRL,
+ RT5631_M_MONO_INN_OUTMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_OUTMIXER_R_CTRL,
+ RT5631_M_MIC2_OUTMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_OUTMIXER_R_CTRL,
+ RT5631_M_MIC1_OUTMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("DACR Playback Switch", RT5631_OUTMIXER_R_CTRL,
+ RT5631_M_DACR_OUTMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("RECMIXR Playback Switch", RT5631_OUTMIXER_R_CTRL,
+ RT5631_M_RECMIXR_OUTMIXR_BIT, 1, 1),
+ SOC_DAPM_SINGLE("RECMIXL Playback Switch", RT5631_OUTMIXER_R_CTRL,
+ RT5631_M_RECMIXL_OUTMIXR_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_AXO1MIX_mixer_controls[] = {
+ SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO1MIXER_CTRL,
+ RT5631_M_MIC1_AXO1MIX_BIT , 1, 1),
+ SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO1MIXER_CTRL,
+ RT5631_M_MIC2_AXO1MIX_BIT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO1MIXER_CTRL,
+ RT5631_M_OUTMIXL_AXO1MIX_BIT , 1 , 1),
+ SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO1MIXER_CTRL,
+ RT5631_M_OUTMIXR_AXO1MIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_AXO2MIX_mixer_controls[] = {
+ SOC_DAPM_SINGLE("MIC1_BST1 Playback Switch", RT5631_AXO2MIXER_CTRL,
+ RT5631_M_MIC1_AXO2MIX_BIT, 1, 1),
+ SOC_DAPM_SINGLE("MIC2_BST2 Playback Switch", RT5631_AXO2MIXER_CTRL,
+ RT5631_M_MIC2_AXO2MIX_BIT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_AXO2MIXER_CTRL,
+ RT5631_M_OUTMIXL_AXO2MIX_BIT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_AXO2MIXER_CTRL,
+ RT5631_M_OUTMIXR_AXO2MIX_BIT, 1 , 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spolmix_mixer_controls[] = {
+ SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+ RT5631_M_SPKVOLL_SPOLMIX_BIT, 1, 1),
+ SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+ RT5631_M_SPKVOLR_SPOLMIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_spormix_mixer_controls[] = {
+ SOC_DAPM_SINGLE("SPKVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+ RT5631_M_SPKVOLL_SPORMIX_BIT, 1, 1),
+ SOC_DAPM_SINGLE("SPKVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+ RT5631_M_SPKVOLR_SPORMIX_BIT, 1, 1),
+};
+
+static const struct snd_kcontrol_new rt5631_monomix_mixer_controls[] = {
+ SOC_DAPM_SINGLE("OUTVOLL Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+ RT5631_M_OUTVOLL_MONOMIX_BIT, 1, 1),
+ SOC_DAPM_SINGLE("OUTVOLR Playback Switch", RT5631_SPK_MONO_OUT_CTRL,
+ RT5631_M_OUTVOLR_MONOMIX_BIT, 1, 1),
+};
+
+/* Left SPK Volume Input */
+static const char *rt5631_spkvoll_sel[] = {"Vmid", "SPKMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_spkvoll_enum, RT5631_SPK_OUT_VOL,
+ RT5631_L_EN_SHIFT, rt5631_spkvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_spkvoll_mux_control =
+ SOC_DAPM_ENUM("Left SPKVOL SRC", rt5631_spkvoll_enum);
+
+/* Left HP Volume Input */
+static const char *rt5631_hpvoll_sel[] = {"Vmid", "OUTMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_hpvoll_enum, RT5631_HP_OUT_VOL,
+ RT5631_L_EN_SHIFT, rt5631_hpvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_hpvoll_mux_control =
+ SOC_DAPM_ENUM("Left HPVOL SRC", rt5631_hpvoll_enum);
+
+/* Left Out Volume Input */
+static const char *rt5631_outvoll_sel[] = {"Vmid", "OUTMIXL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_outvoll_enum, RT5631_MONO_AXO_1_2_VOL,
+ RT5631_L_EN_SHIFT, rt5631_outvoll_sel);
+
+static const struct snd_kcontrol_new rt5631_outvoll_mux_control =
+ SOC_DAPM_ENUM("Left OUTVOL SRC", rt5631_outvoll_enum);
+
+/* Right Out Volume Input */
+static const char *rt5631_outvolr_sel[] = {"Vmid", "OUTMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_outvolr_enum, RT5631_MONO_AXO_1_2_VOL,
+ RT5631_R_EN_SHIFT, rt5631_outvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_outvolr_mux_control =
+ SOC_DAPM_ENUM("Right OUTVOL SRC", rt5631_outvolr_enum);
+
+/* Right HP Volume Input */
+static const char *rt5631_hpvolr_sel[] = {"Vmid", "OUTMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_hpvolr_enum, RT5631_HP_OUT_VOL,
+ RT5631_R_EN_SHIFT, rt5631_hpvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_hpvolr_mux_control =
+ SOC_DAPM_ENUM("Right HPVOL SRC", rt5631_hpvolr_enum);
+
+/* Right SPK Volume Input */
+static const char *rt5631_spkvolr_sel[] = {"Vmid", "SPKMIXR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_spkvolr_enum, RT5631_SPK_OUT_VOL,
+ RT5631_R_EN_SHIFT, rt5631_spkvolr_sel);
+
+static const struct snd_kcontrol_new rt5631_spkvolr_mux_control =
+ SOC_DAPM_ENUM("Right SPKVOL SRC", rt5631_spkvolr_enum);
+
+/* SPO Left Channel Input */
+static const char *rt5631_spol_src_sel[] = {
+ "SPOLMIX", "MONOIN_RX", "VDAC", "DACL"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_spol_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_SPK_L_MUX_SEL_SHIFT, rt5631_spol_src_sel);
+
+static const struct snd_kcontrol_new rt5631_spol_mux_control =
+ SOC_DAPM_ENUM("SPOL SRC", rt5631_spol_src_enum);
+
+/* SPO Right Channel Input */
+static const char *rt5631_spor_src_sel[] = {
+ "SPORMIX", "MONOIN_RX", "VDAC", "DACR"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_spor_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_SPK_R_MUX_SEL_SHIFT, rt5631_spor_src_sel);
+
+static const struct snd_kcontrol_new rt5631_spor_mux_control =
+ SOC_DAPM_ENUM("SPOR SRC", rt5631_spor_src_enum);
+
+/* MONO Input */
+static const char *rt5631_mono_src_sel[] = {"MONOMIX", "MONOIN_RX", "VDAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_mono_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_MONO_MUX_SEL_SHIFT, rt5631_mono_src_sel);
+
+static const struct snd_kcontrol_new rt5631_mono_mux_control =
+ SOC_DAPM_ENUM("MONO SRC", rt5631_mono_src_enum);
+
+/* Left HPO Input */
+static const char *rt5631_hpl_src_sel[] = {"Left HPVOL", "Left DAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_hpl_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_HP_L_MUX_SEL_SHIFT, rt5631_hpl_src_sel);
+
+static const struct snd_kcontrol_new rt5631_hpl_mux_control =
+ SOC_DAPM_ENUM("HPL SRC", rt5631_hpl_src_enum);
+
+/* Right HPO Input */
+static const char *rt5631_hpr_src_sel[] = {"Right HPVOL", "Right DAC"};
+
+static const SOC_ENUM_SINGLE_DECL(
+ rt5631_hpr_src_enum, RT5631_SPK_MONO_HP_OUT_CTRL,
+ RT5631_HP_R_MUX_SEL_SHIFT, rt5631_hpr_src_sel);
+
+static const struct snd_kcontrol_new rt5631_hpr_mux_control =
+ SOC_DAPM_ENUM("HPR SRC", rt5631_hpr_src_enum);
+
+static const struct snd_soc_dapm_widget rt5631_dapm_widgets[] = {
+ /* Vmid */
+ SND_SOC_DAPM_VMID("Vmid"),
+ /* PLL1 */
+ SND_SOC_DAPM_SUPPLY("PLL1", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_PLL1_BIT, 0, NULL, 0),
+
+ /* Input Side */
+ /* Input Lines */
+ SND_SOC_DAPM_INPUT("MIC1"),
+ SND_SOC_DAPM_INPUT("MIC2"),
+ SND_SOC_DAPM_INPUT("AXIL"),
+ SND_SOC_DAPM_INPUT("AXIR"),
+ SND_SOC_DAPM_INPUT("MONOIN_RXN"),
+ SND_SOC_DAPM_INPUT("MONOIN_RXP"),
+ SND_SOC_DAPM_INPUT("DMIC"),
+
+ /* MICBIAS */
+ SND_SOC_DAPM_MICBIAS("MIC Bias1", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_MICBIAS1_VOL_BIT, 0),
+ SND_SOC_DAPM_MICBIAS("MIC Bias2", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_MICBIAS2_VOL_BIT, 0),
+
+ /* Boost */
+ SND_SOC_DAPM_PGA("MIC1 Boost", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_MIC1_BOOT_GAIN_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("MIC2 Boost", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_MIC2_BOOT_GAIN_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("MONOIN_RXP Boost", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_MONO_IN_P_VOL_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("MONOIN_RXN Boost", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_MONO_IN_N_VOL_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("AXIL Boost", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_AXIL_IN_VOL_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_PGA("AXIR Boost", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_AXIR_IN_VOL_BIT, 0, NULL, 0),
+
+ /* MONO In */
+ SND_SOC_DAPM_MIXER("MONO_IN", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* REC Mixer */
+ SND_SOC_DAPM_MIXER("RECMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_RECMIXER_L_BIT, 0,
+ &rt5631_recmixl_mixer_controls[0],
+ ARRAY_SIZE(rt5631_recmixl_mixer_controls)),
+ SND_SOC_DAPM_MIXER("RECMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_RECMIXER_R_BIT, 0,
+ &rt5631_recmixr_mixer_controls[0],
+ ARRAY_SIZE(rt5631_recmixr_mixer_controls)),
+ /* Because of record duplication for L/R channel,
+ * L/R ADCs need power up at the same time */
+ SND_SOC_DAPM_MIXER("ADC Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* DMIC */
+ SND_SOC_DAPM_SUPPLY("DMIC Supply", RT5631_DIG_MIC_CTRL,
+ RT5631_DMIC_ENA_SHIFT, 0,
+ set_dmic_params, SND_SOC_DAPM_PRE_PMU),
+ /* ADC Data Srouce */
+ SND_SOC_DAPM_SUPPLY("Left ADC Select", RT5631_INT_ST_IRQ_CTRL_2,
+ RT5631_ADC_DATA_SEL_MIC1_SHIFT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Right ADC Select", RT5631_INT_ST_IRQ_CTRL_2,
+ RT5631_ADC_DATA_SEL_MIC2_SHIFT, 0, NULL, 0),
+
+ /* ADCs */
+ SND_SOC_DAPM_ADC("Left ADC", "HIFI Capture",
+ RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_L_CLK_BIT, 0),
+ SND_SOC_DAPM_ADC("Right ADC", "HIFI Capture",
+ RT5631_PWR_MANAG_ADD1, RT5631_PWR_ADC_R_CLK_BIT, 0),
+
+ /* DAC and ADC supply power */
+ SND_SOC_DAPM_SUPPLY("I2S", RT5631_PWR_MANAG_ADD1,
+ RT5631_PWR_MAIN_I2S_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("DAC REF", RT5631_PWR_MANAG_ADD1,
+ RT5631_PWR_DAC_REF_BIT, 0, NULL, 0),
+
+ /* Output Side */
+ /* DACs */
+ SND_SOC_DAPM_DAC("Left DAC", "HIFI Playback",
+ RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_L_CLK_BIT, 0),
+ SND_SOC_DAPM_DAC("Right DAC", "HIFI Playback",
+ RT5631_PWR_MANAG_ADD1, RT5631_PWR_DAC_R_CLK_BIT, 0),
+ SND_SOC_DAPM_DAC("Voice DAC", "Voice DAC Mono Playback",
+ SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_PGA("Voice DAC Boost", SND_SOC_NOPM, 0, 0, NULL, 0),
+ /* DAC supply power */
+ SND_SOC_DAPM_SUPPLY("Left DAC To Mixer", RT5631_PWR_MANAG_ADD1,
+ RT5631_PWR_DAC_L_TO_MIXER_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Right DAC To Mixer", RT5631_PWR_MANAG_ADD1,
+ RT5631_PWR_DAC_R_TO_MIXER_BIT, 0, NULL, 0),
+
+ /* Left SPK Mixer */
+ SND_SOC_DAPM_MIXER("SPKMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_SPKMIXER_L_BIT, 0,
+ &rt5631_spkmixl_mixer_controls[0],
+ ARRAY_SIZE(rt5631_spkmixl_mixer_controls)),
+ /* Left Out Mixer */
+ SND_SOC_DAPM_MIXER("OUTMIXL Mixer", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_OUTMIXER_L_BIT, 0,
+ &rt5631_outmixl_mixer_controls[0],
+ ARRAY_SIZE(rt5631_outmixl_mixer_controls)),
+ /* Right Out Mixer */
+ SND_SOC_DAPM_MIXER("OUTMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_OUTMIXER_R_BIT, 0,
+ &rt5631_outmixr_mixer_controls[0],
+ ARRAY_SIZE(rt5631_outmixr_mixer_controls)),
+ /* Right SPK Mixer */
+ SND_SOC_DAPM_MIXER("SPKMIXR Mixer", RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_SPKMIXER_R_BIT, 0,
+ &rt5631_spkmixr_mixer_controls[0],
+ ARRAY_SIZE(rt5631_spkmixr_mixer_controls)),
+
+ /* Volume Mux */
+ SND_SOC_DAPM_MUX("Left SPKVOL Mux", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_SPK_L_VOL_BIT, 0,
+ &rt5631_spkvoll_mux_control),
+ SND_SOC_DAPM_MUX("Left HPVOL Mux", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_HP_L_OUT_VOL_BIT, 0,
+ &rt5631_hpvoll_mux_control),
+ SND_SOC_DAPM_MUX("Left OUTVOL Mux", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_LOUT_VOL_BIT, 0,
+ &rt5631_outvoll_mux_control),
+ SND_SOC_DAPM_MUX("Right OUTVOL Mux", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_ROUT_VOL_BIT, 0,
+ &rt5631_outvolr_mux_control),
+ SND_SOC_DAPM_MUX("Right HPVOL Mux", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_HP_R_OUT_VOL_BIT, 0,
+ &rt5631_hpvolr_mux_control),
+ SND_SOC_DAPM_MUX("Right SPKVOL Mux", RT5631_PWR_MANAG_ADD4,
+ RT5631_PWR_SPK_R_VOL_BIT, 0,
+ &rt5631_spkvolr_mux_control),
+
+ /* DAC To HP */
+ SND_SOC_DAPM_PGA_S("Left DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+ SND_SOC_DAPM_PGA_S("Right DAC_HP", 0, SND_SOC_NOPM, 0, 0, NULL, 0),
+
+ /* HP Depop */
+ SND_SOC_DAPM_PGA_S("HP Depop", 1, SND_SOC_NOPM, 0, 0,
+ hp_event, SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
+
+ /* AXO1 Mixer */
+ SND_SOC_DAPM_MIXER("AXO1MIX Mixer", RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_AXO1MIXER_BIT, 0,
+ &rt5631_AXO1MIX_mixer_controls[0],
+ ARRAY_SIZE(rt5631_AXO1MIX_mixer_controls)),
+ /* SPOL Mixer */
+ SND_SOC_DAPM_MIXER("SPOLMIX Mixer", SND_SOC_NOPM, 0, 0,
+ &rt5631_spolmix_mixer_controls[0],
+ ARRAY_SIZE(rt5631_spolmix_mixer_controls)),
+ /* MONO Mixer */
+ SND_SOC_DAPM_MIXER("MONOMIX Mixer", RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_MONOMIXER_BIT, 0,
+ &rt5631_monomix_mixer_controls[0],
+ ARRAY_SIZE(rt5631_monomix_mixer_controls)),
+ /* SPOR Mixer */
+ SND_SOC_DAPM_MIXER("SPORMIX Mixer", SND_SOC_NOPM, 0, 0,
+ &rt5631_spormix_mixer_controls[0],
+ ARRAY_SIZE(rt5631_spormix_mixer_controls)),
+ /* AXO2 Mixer */
+ SND_SOC_DAPM_MIXER("AXO2MIX Mixer", RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_AXO2MIXER_BIT, 0,
+ &rt5631_AXO2MIX_mixer_controls[0],
+ ARRAY_SIZE(rt5631_AXO2MIX_mixer_controls)),
+
+ /* Mux */
+ SND_SOC_DAPM_MUX("SPOL Mux", SND_SOC_NOPM, 0, 0,
+ &rt5631_spol_mux_control),
+ SND_SOC_DAPM_MUX("SPOR Mux", SND_SOC_NOPM, 0, 0,
+ &rt5631_spor_mux_control),
+ SND_SOC_DAPM_MUX("MONO Mux", SND_SOC_NOPM, 0, 0,
+ &rt5631_mono_mux_control),
+ SND_SOC_DAPM_MUX("HPL Mux", SND_SOC_NOPM, 0, 0,
+ &rt5631_hpl_mux_control),
+ SND_SOC_DAPM_MUX("HPR Mux", SND_SOC_NOPM, 0, 0,
+ &rt5631_hpr_mux_control),
+
+ /* AMP supply */
+ SND_SOC_DAPM_SUPPLY("MONO Depop", RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_MONO_DEPOP_DIS_BIT, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Class D", RT5631_PWR_MANAG_ADD1,
+ RT5631_PWR_CLASS_D_BIT, 0, NULL, 0),
+
+ /* Output Lines */
+ SND_SOC_DAPM_OUTPUT("AUXO1"),
+ SND_SOC_DAPM_OUTPUT("AUXO2"),
+ SND_SOC_DAPM_OUTPUT("SPOL"),
+ SND_SOC_DAPM_OUTPUT("SPOR"),
+ SND_SOC_DAPM_OUTPUT("HPOL"),
+ SND_SOC_DAPM_OUTPUT("HPOR"),
+ SND_SOC_DAPM_OUTPUT("MONO"),
+};
+
+static const struct snd_soc_dapm_route rt5631_dapm_routes[] = {
+ {"MIC1 Boost", NULL, "MIC1"},
+ {"MIC2 Boost", NULL, "MIC2"},
+ {"MONOIN_RXP Boost", NULL, "MONOIN_RXP"},
+ {"MONOIN_RXN Boost", NULL, "MONOIN_RXN"},
+ {"AXIL Boost", NULL, "AXIL"},
+ {"AXIR Boost", NULL, "AXIR"},
+
+ {"MONO_IN", NULL, "MONOIN_RXP Boost"},
+ {"MONO_IN", NULL, "MONOIN_RXN Boost"},
+
+ {"RECMIXL Mixer", "OUTMIXL Capture Switch", "OUTMIXL Mixer"},
+ {"RECMIXL Mixer", "MIC1_BST1 Capture Switch", "MIC1 Boost"},
+ {"RECMIXL Mixer", "AXILVOL Capture Switch", "AXIL Boost"},
+ {"RECMIXL Mixer", "MONOIN_RX Capture Switch", "MONO_IN"},
+
+ {"RECMIXR Mixer", "OUTMIXR Capture Switch", "OUTMIXR Mixer"},
+ {"RECMIXR Mixer", "MIC2_BST2 Capture Switch", "MIC2 Boost"},
+ {"RECMIXR Mixer", "AXIRVOL Capture Switch", "AXIR Boost"},
+ {"RECMIXR Mixer", "MONOIN_RX Capture Switch", "MONO_IN"},
+
+ {"ADC Mixer", NULL, "RECMIXL Mixer"},
+ {"ADC Mixer", NULL, "RECMIXR Mixer"},
+
+ {"Left ADC", NULL, "ADC Mixer"},
+ {"Left ADC", NULL, "Left ADC Select", check_adcl_select},
+ {"Left ADC", NULL, "PLL1", check_sysclk1_source},
+ {"Left ADC", NULL, "I2S"},
+ {"Left ADC", NULL, "DAC REF"},
+
+ {"Right ADC", NULL, "ADC Mixer"},
+ {"Right ADC", NULL, "Right ADC Select", check_adcr_select},
+ {"Right ADC", NULL, "PLL1", check_sysclk1_source},
+ {"Right ADC", NULL, "I2S"},
+ {"Right ADC", NULL, "DAC REF"},
+
+ {"DMIC", NULL, "DMIC Supply", check_dmic_used},
+ {"Left ADC", NULL, "DMIC"},
+ {"Right ADC", NULL, "DMIC"},
+
+ {"Left DAC", NULL, "PLL1", check_sysclk1_source},
+ {"Left DAC", NULL, "I2S"},
+ {"Left DAC", NULL, "DAC REF"},
+ {"Right DAC", NULL, "PLL1", check_sysclk1_source},
+ {"Right DAC", NULL, "I2S"},
+ {"Right DAC", NULL, "DAC REF"},
+
+ {"Voice DAC Boost", NULL, "Voice DAC"},
+
+ {"SPKMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_spkmixl},
+ {"SPKMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+ {"SPKMIXL Mixer", "MIC1_P Playback Switch", "MIC1"},
+ {"SPKMIXL Mixer", "DACL Playback Switch", "Left DAC"},
+ {"SPKMIXL Mixer", "OUTMIXL Playback Switch", "OUTMIXL Mixer"},
+
+ {"SPKMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_spkmixr},
+ {"SPKMIXR Mixer", "OUTMIXR Playback Switch", "OUTMIXR Mixer"},
+ {"SPKMIXR Mixer", "DACR Playback Switch", "Right DAC"},
+ {"SPKMIXR Mixer", "MIC2_P Playback Switch", "MIC2"},
+ {"SPKMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+
+ {"OUTMIXL Mixer", NULL, "Left DAC To Mixer", check_dacl_to_outmixl},
+ {"OUTMIXL Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+ {"OUTMIXL Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+ {"OUTMIXL Mixer", "DACL Playback Switch", "Left DAC"},
+ {"OUTMIXL Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+ {"OUTMIXL Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+ {"OUTMIXL Mixer", "MONOIN_RXP Playback Switch", "MONOIN_RXP Boost"},
+ {"OUTMIXL Mixer", "AXILVOL Playback Switch", "AXIL Boost"},
+ {"OUTMIXL Mixer", "AXIRVOL Playback Switch", "AXIR Boost"},
+ {"OUTMIXL Mixer", "VDAC Playback Switch", "Voice DAC Boost"},
+
+ {"OUTMIXR Mixer", NULL, "Right DAC To Mixer", check_dacr_to_outmixr},
+ {"OUTMIXR Mixer", "RECMIXL Playback Switch", "RECMIXL Mixer"},
+ {"OUTMIXR Mixer", "RECMIXR Playback Switch", "RECMIXR Mixer"},
+ {"OUTMIXR Mixer", "DACR Playback Switch", "Right DAC"},
+ {"OUTMIXR Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+ {"OUTMIXR Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+ {"OUTMIXR Mixer", "MONOIN_RXN Playback Switch", "MONOIN_RXN Boost"},
+ {"OUTMIXR Mixer", "AXILVOL Playback Switch", "AXIL Boost"},
+ {"OUTMIXR Mixer", "AXIRVOL Playback Switch", "AXIR Boost"},
+ {"OUTMIXR Mixer", "VDAC Playback Switch", "Voice DAC Boost"},
+
+ {"Left SPKVOL Mux", "SPKMIXL", "SPKMIXL Mixer"},
+ {"Left SPKVOL Mux", "Vmid", "Vmid"},
+ {"Left HPVOL Mux", "OUTMIXL", "OUTMIXL Mixer"},
+ {"Left HPVOL Mux", "Vmid", "Vmid"},
+ {"Left OUTVOL Mux", "OUTMIXL", "OUTMIXL Mixer"},
+ {"Left OUTVOL Mux", "Vmid", "Vmid"},
+ {"Right OUTVOL Mux", "OUTMIXR", "OUTMIXR Mixer"},
+ {"Right OUTVOL Mux", "Vmid", "Vmid"},
+ {"Right HPVOL Mux", "OUTMIXR", "OUTMIXR Mixer"},
+ {"Right HPVOL Mux", "Vmid", "Vmid"},
+ {"Right SPKVOL Mux", "SPKMIXR", "SPKMIXR Mixer"},
+ {"Right SPKVOL Mux", "Vmid", "Vmid"},
+
+ {"AXO1MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+ {"AXO1MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+ {"AXO1MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+ {"AXO1MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+
+ {"AXO2MIX Mixer", "MIC1_BST1 Playback Switch", "MIC1 Boost"},
+ {"AXO2MIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+ {"AXO2MIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+ {"AXO2MIX Mixer", "MIC2_BST2 Playback Switch", "MIC2 Boost"},
+
+ {"SPOLMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"},
+ {"SPOLMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"},
+
+ {"SPORMIX Mixer", "SPKVOLL Playback Switch", "Left SPKVOL Mux"},
+ {"SPORMIX Mixer", "SPKVOLR Playback Switch", "Right SPKVOL Mux"},
+
+ {"MONOMIX Mixer", "OUTVOLL Playback Switch", "Left OUTVOL Mux"},
+ {"MONOMIX Mixer", "OUTVOLR Playback Switch", "Right OUTVOL Mux"},
+
+ {"SPOL Mux", "SPOLMIX", "SPOLMIX Mixer"},
+ {"SPOL Mux", "MONOIN_RX", "MONO_IN"},
+ {"SPOL Mux", "VDAC", "Voice DAC Boost"},
+ {"SPOL Mux", "DACL", "Left DAC"},
+
+ {"SPOR Mux", "SPORMIX", "SPORMIX Mixer"},
+ {"SPOR Mux", "MONOIN_RX", "MONO_IN"},
+ {"SPOR Mux", "VDAC", "Voice DAC Boost"},
+ {"SPOR Mux", "DACR", "Right DAC"},
+
+ {"MONO Mux", "MONOMIX", "MONOMIX Mixer"},
+ {"MONO Mux", "MONOIN_RX", "MONO_IN"},
+ {"MONO Mux", "VDAC", "Voice DAC Boost"},
+
+ {"Right DAC_HP", NULL, "Right DAC"},
+ {"Left DAC_HP", NULL, "Left DAC"},
+
+ {"HPL Mux", "Left HPVOL", "Left HPVOL Mux"},
+ {"HPL Mux", "Left DAC", "Left DAC_HP"},
+ {"HPR Mux", "Right HPVOL", "Right HPVOL Mux"},
+ {"HPR Mux", "Right DAC", "Right DAC_HP"},
+
+ {"HP Depop", NULL, "HPL Mux"},
+ {"HP Depop", NULL, "HPR Mux"},
+
+ {"AUXO1", NULL, "AXO1MIX Mixer"},
+ {"AUXO2", NULL, "AXO2MIX Mixer"},
+
+ {"SPOL", NULL, "Class D"},
+ {"SPOL", NULL, "SPOL Mux"},
+ {"SPOR", NULL, "Class D"},
+ {"SPOR", NULL, "SPOR Mux"},
+
+ {"HPOL", NULL, "HP Depop"},
+ {"HPOR", NULL, "HP Depop"},
+
+ {"MONO", NULL, "MONO Depop"},
+ {"MONO", NULL, "MONO Mux"},
+};
+
+struct coeff_clk_div {
+ u32 mclk;
+ u32 bclk;
+ u32 rate;
+ u16 reg_val;
+};
+
+/* PLL divisors */
+struct pll_div {
+ u32 pll_in;
+ u32 pll_out;
+ u16 reg_val;
+};
+
+static const struct pll_div codec_master_pll_div[] = {
+ {2048000, 8192000, 0x0ea0},
+ {3686400, 8192000, 0x4e27},
+ {12000000, 8192000, 0x456b},
+ {13000000, 8192000, 0x495f},
+ {13100000, 8192000, 0x0320},
+ {2048000, 11289600, 0xf637},
+ {3686400, 11289600, 0x2f22},
+ {12000000, 11289600, 0x3e2f},
+ {13000000, 11289600, 0x4d5b},
+ {13100000, 11289600, 0x363b},
+ {2048000, 16384000, 0x1ea0},
+ {3686400, 16384000, 0x9e27},
+ {12000000, 16384000, 0x452b},
+ {13000000, 16384000, 0x542f},
+ {13100000, 16384000, 0x03a0},
+ {2048000, 16934400, 0xe625},
+ {3686400, 16934400, 0x9126},
+ {12000000, 16934400, 0x4d2c},
+ {13000000, 16934400, 0x742f},
+ {13100000, 16934400, 0x3c27},
+ {2048000, 22579200, 0x2aa0},
+ {3686400, 22579200, 0x2f20},
+ {12000000, 22579200, 0x7e2f},
+ {13000000, 22579200, 0x742f},
+ {13100000, 22579200, 0x3c27},
+ {2048000, 24576000, 0x2ea0},
+ {3686400, 24576000, 0xee27},
+ {12000000, 24576000, 0x2915},
+ {13000000, 24576000, 0x772e},
+ {13100000, 24576000, 0x0d20},
+ {26000000, 24576000, 0x2027},
+ {26000000, 22579200, 0x392f},
+ {24576000, 22579200, 0x0921},
+ {24576000, 24576000, 0x02a0},
+};
+
+static const struct pll_div codec_slave_pll_div[] = {
+ {256000, 2048000, 0x46f0},
+ {256000, 4096000, 0x3ea0},
+ {352800, 5644800, 0x3ea0},
+ {512000, 8192000, 0x3ea0},
+ {1024000, 8192000, 0x46f0},
+ {705600, 11289600, 0x3ea0},
+ {1024000, 16384000, 0x3ea0},
+ {1411200, 22579200, 0x3ea0},
+ {1536000, 24576000, 0x3ea0},
+ {2048000, 16384000, 0x1ea0},
+ {2822400, 22579200, 0x1ea0},
+ {2822400, 45158400, 0x5ec0},
+ {5644800, 45158400, 0x46f0},
+ {3072000, 24576000, 0x1ea0},
+ {3072000, 49152000, 0x5ec0},
+ {6144000, 49152000, 0x46f0},
+ {705600, 11289600, 0x3ea0},
+ {705600, 8467200, 0x3ab0},
+ {24576000, 24576000, 0x02a0},
+ {1411200, 11289600, 0x1690},
+ {2822400, 11289600, 0x0a90},
+ {1536000, 12288000, 0x1690},
+ {3072000, 12288000, 0x0a90},
+};
+
+static struct coeff_clk_div coeff_div[] = {
+ /* sysclk is 256fs */
+ {2048000, 8000 * 32, 8000, 0x1000},
+ {2048000, 8000 * 64, 8000, 0x0000},
+ {2822400, 11025 * 32, 11025, 0x1000},
+ {2822400, 11025 * 64, 11025, 0x0000},
+ {4096000, 16000 * 32, 16000, 0x1000},
+ {4096000, 16000 * 64, 16000, 0x0000},
+ {5644800, 22050 * 32, 22050, 0x1000},
+ {5644800, 22050 * 64, 22050, 0x0000},
+ {8192000, 32000 * 32, 32000, 0x1000},
+ {8192000, 32000 * 64, 32000, 0x0000},
+ {11289600, 44100 * 32, 44100, 0x1000},
+ {11289600, 44100 * 64, 44100, 0x0000},
+ {12288000, 48000 * 32, 48000, 0x1000},
+ {12288000, 48000 * 64, 48000, 0x0000},
+ {22579200, 88200 * 32, 88200, 0x1000},
+ {22579200, 88200 * 64, 88200, 0x0000},
+ {24576000, 96000 * 32, 96000, 0x1000},
+ {24576000, 96000 * 64, 96000, 0x0000},
+ /* sysclk is 512fs */
+ {4096000, 8000 * 32, 8000, 0x3000},
+ {4096000, 8000 * 64, 8000, 0x2000},
+ {5644800, 11025 * 32, 11025, 0x3000},
+ {5644800, 11025 * 64, 11025, 0x2000},
+ {8192000, 16000 * 32, 16000, 0x3000},
+ {8192000, 16000 * 64, 16000, 0x2000},
+ {11289600, 22050 * 32, 22050, 0x3000},
+ {11289600, 22050 * 64, 22050, 0x2000},
+ {16384000, 32000 * 32, 32000, 0x3000},
+ {16384000, 32000 * 64, 32000, 0x2000},
+ {22579200, 44100 * 32, 44100, 0x3000},
+ {22579200, 44100 * 64, 44100, 0x2000},
+ {24576000, 48000 * 32, 48000, 0x3000},
+ {24576000, 48000 * 64, 48000, 0x2000},
+ {45158400, 88200 * 32, 88200, 0x3000},
+ {45158400, 88200 * 64, 88200, 0x2000},
+ {49152000, 96000 * 32, 96000, 0x3000},
+ {49152000, 96000 * 64, 96000, 0x2000},
+ /* sysclk is 24.576Mhz or 22.5792Mhz */
+ {24576000, 8000 * 32, 8000, 0x7080},
+ {24576000, 8000 * 64, 8000, 0x6080},
+ {24576000, 16000 * 32, 16000, 0x5080},
+ {24576000, 16000 * 64, 16000, 0x4080},
+ {24576000, 24000 * 32, 24000, 0x5000},
+ {24576000, 24000 * 64, 24000, 0x4000},
+ {24576000, 32000 * 32, 32000, 0x3080},
+ {24576000, 32000 * 64, 32000, 0x2080},
+ {22579200, 11025 * 32, 11025, 0x7000},
+ {22579200, 11025 * 64, 11025, 0x6000},
+ {22579200, 22050 * 32, 22050, 0x5000},
+ {22579200, 22050 * 64, 22050, 0x4000},
+};
+
+static int get_coeff(int mclk, int rate, int timesofbclk)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
+ if (coeff_div[i].mclk == mclk && coeff_div[i].rate == rate &&
+ (coeff_div[i].bclk / coeff_div[i].rate) == timesofbclk)
+ return i;
+ }
+ return -EINVAL;
+}
+
+static int rt5631_hifi_pcm_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+ int timesofbclk = 32, coeff;
+ unsigned int iface = 0;
+
+ dev_dbg(codec->dev, "enter %s\n", __func__);
+
+ rt5631->bclk_rate = snd_soc_params_to_bclk(params);
+ if (rt5631->bclk_rate < 0) {
+ dev_err(codec->dev, "Fail to get BCLK rate\n");
+ return rt5631->bclk_rate;
+ }
+ rt5631->rx_rate = params_rate(params);
+
+ if (rt5631->master)
+ coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate,
+ rt5631->bclk_rate / rt5631->rx_rate);
+ else
+ coeff = get_coeff(rt5631->sysclk, rt5631->rx_rate,
+ timesofbclk);
+ if (coeff < 0) {
+ dev_err(codec->dev, "Fail to get coeff\n");
+ return -EINVAL;
+ }
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ iface |= RT5631_SDP_I2S_DL_20;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ iface |= RT5631_SDP_I2S_DL_24;
+ break;
+ case SNDRV_PCM_FORMAT_S8:
+ iface |= RT5631_SDP_I2S_DL_8;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, RT5631_SDP_CTRL,
+ RT5631_SDP_I2S_DL_MASK, iface);
+ snd_soc_write(codec, RT5631_STEREO_AD_DA_CLK_CTRL,
+ coeff_div[coeff].reg_val);
+
+ return 0;
+}
+
+static int rt5631_hifi_codec_set_dai_fmt(struct snd_soc_dai *codec_dai,
+ unsigned int fmt)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+ unsigned int iface = 0;
+
+ dev_dbg(codec->dev, "enter %s\n", __func__);
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBM_CFM:
+ rt5631->master = 1;
+ break;
+ case SND_SOC_DAIFMT_CBS_CFS:
+ iface |= RT5631_SDP_MODE_SEL_SLAVE;
+ rt5631->master = 0;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ iface |= RT5631_SDP_I2S_DF_LEFT;
+ break;
+ case SND_SOC_DAIFMT_DSP_A:
+ iface |= RT5631_SDP_I2S_DF_PCM_A;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ iface |= RT5631_SDP_I2S_DF_PCM_B;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ iface |= RT5631_SDP_I2S_BCLK_POL_CTRL;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_write(codec, RT5631_SDP_CTRL, iface);
+
+ return 0;
+}
+
+static int rt5631_hifi_codec_set_dai_sysclk(struct snd_soc_dai *codec_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+
+ dev_dbg(codec->dev, "enter %s, syclk=%d\n", __func__, freq);
+
+ if ((freq >= (256 * 8000)) && (freq <= (512 * 96000))) {
+ rt5631->sysclk = freq;
+ return 0;
+ }
+
+ return -EINVAL;
+}
+
+static int rt5631_codec_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
+ int source, unsigned int freq_in, unsigned int freq_out)
+{
+ struct snd_soc_codec *codec = codec_dai->codec;
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+ int i, ret = -EINVAL;
+
+ dev_dbg(codec->dev, "enter %s\n", __func__);
+
+ if (!freq_in || !freq_out) {
+ dev_dbg(codec->dev, "PLL disabled\n");
+
+ snd_soc_update_bits(codec, RT5631_GLOBAL_CLK_CTRL,
+ RT5631_SYSCLK_SOUR_SEL_MASK,
+ RT5631_SYSCLK_SOUR_SEL_MCLK);
+
+ return 0;
+ }
+
+ if (rt5631->master) {
+ for (i = 0; i < ARRAY_SIZE(codec_master_pll_div); i++)
+ if (freq_in == codec_master_pll_div[i].pll_in &&
+ freq_out == codec_master_pll_div[i].pll_out) {
+ dev_info(codec->dev,
+ "change PLL in master mode\n");
+ snd_soc_write(codec, RT5631_PLL_CTRL,
+ codec_master_pll_div[i].reg_val);
+ schedule_timeout_uninterruptible(
+ msecs_to_jiffies(20));
+ snd_soc_update_bits(codec,
+ RT5631_GLOBAL_CLK_CTRL,
+ RT5631_SYSCLK_SOUR_SEL_MASK |
+ RT5631_PLLCLK_SOUR_SEL_MASK,
+ RT5631_SYSCLK_SOUR_SEL_PLL |
+ RT5631_PLLCLK_SOUR_SEL_MCLK);
+ ret = 0;
+ break;
+ }
+ } else {
+ for (i = 0; i < ARRAY_SIZE(codec_slave_pll_div); i++)
+ if (freq_in == codec_slave_pll_div[i].pll_in &&
+ freq_out == codec_slave_pll_div[i].pll_out) {
+ dev_info(codec->dev,
+ "change PLL in slave mode\n");
+ snd_soc_write(codec, RT5631_PLL_CTRL,
+ codec_slave_pll_div[i].reg_val);
+ schedule_timeout_uninterruptible(
+ msecs_to_jiffies(20));
+ snd_soc_update_bits(codec,
+ RT5631_GLOBAL_CLK_CTRL,
+ RT5631_SYSCLK_SOUR_SEL_MASK |
+ RT5631_PLLCLK_SOUR_SEL_MASK,
+ RT5631_SYSCLK_SOUR_SEL_PLL |
+ RT5631_PLLCLK_SOUR_SEL_BCLK);
+ ret = 0;
+ break;
+ }
+ }
+
+ return ret;
+}
+
+static int rt5631_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ case SND_SOC_BIAS_PREPARE:
+ snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD2,
+ RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL,
+ RT5631_PWR_MICBIAS1_VOL | RT5631_PWR_MICBIAS2_VOL);
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS,
+ RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS);
+ msleep(80);
+ snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_FAST_VREF_CTRL,
+ RT5631_PWR_FAST_VREF_CTRL);
+ codec->cache_only = false;
+ snd_soc_cache_sync(codec);
+ }
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ snd_soc_write(codec, RT5631_PWR_MANAG_ADD1, 0x0000);
+ snd_soc_write(codec, RT5631_PWR_MANAG_ADD2, 0x0000);
+ snd_soc_write(codec, RT5631_PWR_MANAG_ADD3, 0x0000);
+ snd_soc_write(codec, RT5631_PWR_MANAG_ADD4, 0x0000);
+ break;
+
+ default:
+ break;
+ }
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
+
+static int rt5631_probe(struct snd_soc_codec *codec)
+{
+ struct rt5631_priv *rt5631 = snd_soc_codec_get_drvdata(codec);
+ unsigned int val;
+ int ret;
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ val = rt5631_read_index(codec, RT5631_ADDA_MIXER_INTL_REG3);
+ if (val & 0x0002)
+ rt5631->codec_version = 1;
+ else
+ rt5631->codec_version = 0;
+
+ rt5631_reset(codec);
+ snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS,
+ RT5631_PWR_VREF | RT5631_PWR_MAIN_BIAS);
+ msleep(80);
+ snd_soc_update_bits(codec, RT5631_PWR_MANAG_ADD3,
+ RT5631_PWR_FAST_VREF_CTRL, RT5631_PWR_FAST_VREF_CTRL);
+ /* enable HP zero cross */
+ snd_soc_write(codec, RT5631_INT_ST_IRQ_CTRL_2, 0x0f18);
+ /* power off ClassD auto Recovery */
+ if (rt5631->codec_version)
+ snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2,
+ 0x2000, 0x2000);
+ else
+ snd_soc_update_bits(codec, RT5631_INT_ST_IRQ_CTRL_2,
+ 0x2000, 0);
+ /* DMIC */
+ if (rt5631->dmic_used_flag) {
+ snd_soc_update_bits(codec, RT5631_GPIO_CTRL,
+ RT5631_GPIO_PIN_FUN_SEL_MASK |
+ RT5631_GPIO_DMIC_FUN_SEL_MASK,
+ RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC |
+ RT5631_GPIO_DMIC_FUN_SEL_DIMC);
+ snd_soc_update_bits(codec, RT5631_DIG_MIC_CTRL,
+ RT5631_DMIC_L_CH_LATCH_MASK |
+ RT5631_DMIC_R_CH_LATCH_MASK,
+ RT5631_DMIC_L_CH_LATCH_FALLING |
+ RT5631_DMIC_R_CH_LATCH_RISING);
+ }
+
+ codec->dapm.bias_level = SND_SOC_BIAS_STANDBY;
+
+ return 0;
+}
+
+static int rt5631_remove(struct snd_soc_codec *codec)
+{
+ rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+#ifdef CONFIG_PM
+static int rt5631_suspend(struct snd_soc_codec *codec)
+{
+ rt5631_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ return 0;
+}
+
+static int rt5631_resume(struct snd_soc_codec *codec)
+{
+ rt5631_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
+}
+#else
+#define rt5631_suspend NULL
+#define rt5631_resume NULL
+#endif
+
+#define RT5631_STEREO_RATES SNDRV_PCM_RATE_8000_96000
+#define RT5631_FORMAT (SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE | \
+ SNDRV_PCM_FMTBIT_S8)
+
+static const struct snd_soc_dai_ops rt5631_ops = {
+ .hw_params = rt5631_hifi_pcm_params,
+ .set_fmt = rt5631_hifi_codec_set_dai_fmt,
+ .set_sysclk = rt5631_hifi_codec_set_dai_sysclk,
+ .set_pll = rt5631_codec_set_dai_pll,
+};
+
+static struct snd_soc_dai_driver rt5631_dai[] = {
+ {
+ .name = "rt5631-hifi",
+ .id = 1,
+ .playback = {
+ .stream_name = "HIFI Playback",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5631_STEREO_RATES,
+ .formats = RT5631_FORMAT,
+ },
+ .capture = {
+ .stream_name = "HIFI Capture",
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = RT5631_STEREO_RATES,
+ .formats = RT5631_FORMAT,
+ },
+ .ops = &rt5631_ops,
+ },
+};
+
+static struct snd_soc_codec_driver soc_codec_dev_rt5631 = {
+ .probe = rt5631_probe,
+ .remove = rt5631_remove,
+ .suspend = rt5631_suspend,
+ .resume = rt5631_resume,
+ .set_bias_level = rt5631_set_bias_level,
+ .reg_cache_size = RT5631_VENDOR_ID2 + 1,
+ .reg_word_size = sizeof(u16),
+ .reg_cache_default = rt5631_reg,
+ .volatile_register = rt5631_volatile_register,
+ .readable_register = rt5631_readable_register,
+ .reg_cache_step = 1,
+ .controls = rt5631_snd_controls,
+ .num_controls = ARRAY_SIZE(rt5631_snd_controls),
+ .dapm_widgets = rt5631_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(rt5631_dapm_widgets),
+ .dapm_routes = rt5631_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(rt5631_dapm_routes),
+};
+
+static const struct i2c_device_id rt5631_i2c_id[] = {
+ { "rt5631", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, rt5631_i2c_id);
+
+static int rt5631_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct rt5631_priv *rt5631;
+ int ret;
+
+ rt5631 = devm_kzalloc(&i2c->dev, sizeof(struct rt5631_priv),
+ GFP_KERNEL);
+ if (NULL == rt5631)
+ return -ENOMEM;
+
+ i2c_set_clientdata(i2c, rt5631);
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_rt5631,
+ rt5631_dai, ARRAY_SIZE(rt5631_dai));
+ return ret;
+}
+
+static __devexit int rt5631_i2c_remove(struct i2c_client *client)
+{
+ snd_soc_unregister_codec(&client->dev);
+ return 0;
+}
+
+static struct i2c_driver rt5631_i2c_driver = {
+ .driver = {
+ .name = "rt5631",
+ .owner = THIS_MODULE,
+ },
+ .probe = rt5631_i2c_probe,
+ .remove = __devexit_p(rt5631_i2c_remove),
+ .id_table = rt5631_i2c_id,
+};
+
+static int __init rt5631_modinit(void)
+{
+ return i2c_add_driver(&rt5631_i2c_driver);
+}
+module_init(rt5631_modinit);
+
+static void __exit rt5631_modexit(void)
+{
+ i2c_del_driver(&rt5631_i2c_driver);
+}
+module_exit(rt5631_modexit);
+
+MODULE_DESCRIPTION("ASoC RT5631 driver");
+MODULE_AUTHOR("flove <flove@realtek.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/rt5631.h b/sound/soc/codecs/rt5631.h
new file mode 100644
index 000000000000..13401581b0df
--- /dev/null
+++ b/sound/soc/codecs/rt5631.h
@@ -0,0 +1,701 @@
+#ifndef __RTCODEC5631_H__
+#define __RTCODEC5631_H__
+
+
+#define RT5631_RESET 0x00
+#define RT5631_SPK_OUT_VOL 0x02
+#define RT5631_HP_OUT_VOL 0x04
+#define RT5631_MONO_AXO_1_2_VOL 0x06
+#define RT5631_AUX_IN_VOL 0x0A
+#define RT5631_STEREO_DAC_VOL_1 0x0C
+#define RT5631_MIC_CTRL_1 0x0E
+#define RT5631_STEREO_DAC_VOL_2 0x10
+#define RT5631_ADC_CTRL_1 0x12
+#define RT5631_ADC_REC_MIXER 0x14
+#define RT5631_ADC_CTRL_2 0x16
+#define RT5631_VDAC_DIG_VOL 0x18
+#define RT5631_OUTMIXER_L_CTRL 0x1A
+#define RT5631_OUTMIXER_R_CTRL 0x1C
+#define RT5631_AXO1MIXER_CTRL 0x1E
+#define RT5631_AXO2MIXER_CTRL 0x20
+#define RT5631_MIC_CTRL_2 0x22
+#define RT5631_DIG_MIC_CTRL 0x24
+#define RT5631_MONO_INPUT_VOL 0x26
+#define RT5631_SPK_MIXER_CTRL 0x28
+#define RT5631_SPK_MONO_OUT_CTRL 0x2A
+#define RT5631_SPK_MONO_HP_OUT_CTRL 0x2C
+#define RT5631_SDP_CTRL 0x34
+#define RT5631_MONO_SDP_CTRL 0x36
+#define RT5631_STEREO_AD_DA_CLK_CTRL 0x38
+#define RT5631_PWR_MANAG_ADD1 0x3A
+#define RT5631_PWR_MANAG_ADD2 0x3B
+#define RT5631_PWR_MANAG_ADD3 0x3C
+#define RT5631_PWR_MANAG_ADD4 0x3E
+#define RT5631_GEN_PUR_CTRL_REG 0x40
+#define RT5631_GLOBAL_CLK_CTRL 0x42
+#define RT5631_PLL_CTRL 0x44
+#define RT5631_INT_ST_IRQ_CTRL_1 0x48
+#define RT5631_INT_ST_IRQ_CTRL_2 0x4A
+#define RT5631_GPIO_CTRL 0x4C
+#define RT5631_MISC_CTRL 0x52
+#define RT5631_DEPOP_FUN_CTRL_1 0x54
+#define RT5631_DEPOP_FUN_CTRL_2 0x56
+#define RT5631_JACK_DET_CTRL 0x5A
+#define RT5631_SOFT_VOL_CTRL 0x5C
+#define RT5631_ALC_CTRL_1 0x64
+#define RT5631_ALC_CTRL_2 0x65
+#define RT5631_ALC_CTRL_3 0x66
+#define RT5631_PSEUDO_SPATL_CTRL 0x68
+#define RT5631_INDEX_ADD 0x6A
+#define RT5631_INDEX_DATA 0x6C
+#define RT5631_EQ_CTRL 0x6E
+#define RT5631_VENDOR_ID 0x7A
+#define RT5631_VENDOR_ID1 0x7C
+#define RT5631_VENDOR_ID2 0x7E
+
+/* Index of Codec Private Register definition */
+#define RT5631_EQ_BW_LOP 0x00
+#define RT5631_EQ_GAIN_LOP 0x01
+#define RT5631_EQ_FC_BP1 0x02
+#define RT5631_EQ_BW_BP1 0x03
+#define RT5631_EQ_GAIN_BP1 0x04
+#define RT5631_EQ_FC_BP2 0x05
+#define RT5631_EQ_BW_BP2 0x06
+#define RT5631_EQ_GAIN_BP2 0x07
+#define RT5631_EQ_FC_BP3 0x08
+#define RT5631_EQ_BW_BP3 0x09
+#define RT5631_EQ_GAIN_BP3 0x0a
+#define RT5631_EQ_BW_HIP 0x0b
+#define RT5631_EQ_GAIN_HIP 0x0c
+#define RT5631_EQ_HPF_A1 0x0d
+#define RT5631_EQ_HPF_A2 0x0e
+#define RT5631_EQ_HPF_GAIN 0x0f
+#define RT5631_EQ_PRE_VOL_CTRL 0x11
+#define RT5631_EQ_POST_VOL_CTRL 0x12
+#define RT5631_TEST_MODE_CTRL 0x39
+#define RT5631_CP_INTL_REG2 0x45
+#define RT5631_ADDA_MIXER_INTL_REG3 0x52
+#define RT5631_SPK_INTL_CTRL 0x56
+
+
+/* global definition */
+#define RT5631_L_MUTE (0x1 << 15)
+#define RT5631_L_MUTE_SHIFT 15
+#define RT5631_L_EN (0x1 << 14)
+#define RT5631_L_EN_SHIFT 14
+#define RT5631_R_MUTE (0x1 << 7)
+#define RT5631_R_MUTE_SHIFT 7
+#define RT5631_R_EN (0x1 << 6)
+#define RT5631_R_EN_SHIFT 6
+#define RT5631_VOL_MASK 0x1f
+#define RT5631_L_VOL_SHIFT 8
+#define RT5631_R_VOL_SHIFT 0
+
+/* Speaker Output Control(0x02) */
+#define RT5631_SPK_L_VOL_SEL_MASK (0x1 << 14)
+#define RT5631_SPK_L_VOL_SEL_VMID (0x0 << 14)
+#define RT5631_SPK_L_VOL_SEL_SPKMIX_L (0x1 << 14)
+#define RT5631_SPK_R_VOL_SEL_MASK (0x1 << 6)
+#define RT5631_SPK_R_VOL_SEL_VMID (0x0 << 6)
+#define RT5631_SPK_R_VOL_SEL_SPKMIX_R (0x1 << 6)
+
+/* Headphone Output Control(0x04) */
+#define RT5631_HP_L_VOL_SEL_MASK (0x1 << 14)
+#define RT5631_HP_L_VOL_SEL_VMID (0x0 << 14)
+#define RT5631_HP_L_VOL_SEL_OUTMIX_L (0x1 << 14)
+#define RT5631_HP_R_VOL_SEL_MASK (0x1 << 6)
+#define RT5631_HP_R_VOL_SEL_VMID (0x0 << 6)
+#define RT5631_HP_R_VOL_SEL_OUTMIX_R (0x1 << 6)
+
+/* Output Control for AUXOUT/MONO(0x06) */
+#define RT5631_AUXOUT_1_VOL_SEL_MASK (0x1 << 14)
+#define RT5631_AUXOUT_1_VOL_SEL_VMID (0x0 << 14)
+#define RT5631_AUXOUT_1_VOL_SEL_OUTMIX_L (0x1 << 14)
+#define RT5631_MUTE_MONO (0x1 << 13)
+#define RT5631_MUTE_MONO_SHIFT 13
+#define RT5631_AUXOUT_2_VOL_SEL_MASK (0x1 << 6)
+#define RT5631_AUXOUT_2_VOL_SEL_VMID (0x0 << 6)
+#define RT5631_AUXOUT_2_VOL_SEL_OUTMIX_R (0x1 << 6)
+
+/* Microphone Input Control 1(0x0E) */
+#define RT5631_MIC1_DIFF_INPUT_CTRL (0x1 << 15)
+#define RT5631_MIC1_DIFF_INPUT_SHIFT 15
+#define RT5631_MIC2_DIFF_INPUT_CTRL (0x1 << 7)
+#define RT5631_MIC2_DIFF_INPUT_SHIFT 7
+
+/* Stereo DAC Digital Volume2(0x10) */
+#define RT5631_DAC_VOL_MASK 0xff
+
+/* ADC Recording Mixer Control(0x14) */
+#define RT5631_M_OUTMIXER_L_TO_RECMIXER_L (0x1 << 15)
+#define RT5631_M_OUTMIXL_RECMIXL_BIT 15
+#define RT5631_M_MIC1_TO_RECMIXER_L (0x1 << 14)
+#define RT5631_M_MIC1_RECMIXL_BIT 14
+#define RT5631_M_AXIL_TO_RECMIXER_L (0x1 << 13)
+#define RT5631_M_AXIL_RECMIXL_BIT 13
+#define RT5631_M_MONO_IN_TO_RECMIXER_L (0x1 << 12)
+#define RT5631_M_MONO_IN_RECMIXL_BIT 12
+#define RT5631_M_OUTMIXER_R_TO_RECMIXER_R (0x1 << 7)
+#define RT5631_M_OUTMIXR_RECMIXR_BIT 7
+#define RT5631_M_MIC2_TO_RECMIXER_R (0x1 << 6)
+#define RT5631_M_MIC2_RECMIXR_BIT 6
+#define RT5631_M_AXIR_TO_RECMIXER_R (0x1 << 5)
+#define RT5631_M_AXIR_RECMIXR_BIT 5
+#define RT5631_M_MONO_IN_TO_RECMIXER_R (0x1 << 4)
+#define RT5631_M_MONO_IN_RECMIXR_BIT 4
+
+/* Left Output Mixer Control(0x1A) */
+#define RT5631_M_RECMIXER_L_TO_OUTMIXER_L (0x1 << 15)
+#define RT5631_M_RECMIXL_OUTMIXL_BIT 15
+#define RT5631_M_RECMIXER_R_TO_OUTMIXER_L (0x1 << 14)
+#define RT5631_M_RECMIXR_OUTMIXL_BIT 14
+#define RT5631_M_DAC_L_TO_OUTMIXER_L (0x1 << 13)
+#define RT5631_M_DACL_OUTMIXL_BIT 13
+#define RT5631_M_MIC1_TO_OUTMIXER_L (0x1 << 12)
+#define RT5631_M_MIC1_OUTMIXL_BIT 12
+#define RT5631_M_MIC2_TO_OUTMIXER_L (0x1 << 11)
+#define RT5631_M_MIC2_OUTMIXL_BIT 11
+#define RT5631_M_MONO_IN_P_TO_OUTMIXER_L (0x1 << 10)
+#define RT5631_M_MONO_INP_OUTMIXL_BIT 10
+#define RT5631_M_AXIL_TO_OUTMIXER_L (0x1 << 9)
+#define RT5631_M_AXIL_OUTMIXL_BIT 9
+#define RT5631_M_AXIR_TO_OUTMIXER_L (0x1 << 8)
+#define RT5631_M_AXIR_OUTMIXL_BIT 8
+#define RT5631_M_VDAC_TO_OUTMIXER_L (0x1 << 7)
+#define RT5631_M_VDAC_OUTMIXL_BIT 7
+
+/* Right Output Mixer Control(0x1C) */
+#define RT5631_M_RECMIXER_L_TO_OUTMIXER_R (0x1 << 15)
+#define RT5631_M_RECMIXL_OUTMIXR_BIT 15
+#define RT5631_M_RECMIXER_R_TO_OUTMIXER_R (0x1 << 14)
+#define RT5631_M_RECMIXR_OUTMIXR_BIT 14
+#define RT5631_M_DAC_R_TO_OUTMIXER_R (0x1 << 13)
+#define RT5631_M_DACR_OUTMIXR_BIT 13
+#define RT5631_M_MIC1_TO_OUTMIXER_R (0x1 << 12)
+#define RT5631_M_MIC1_OUTMIXR_BIT 12
+#define RT5631_M_MIC2_TO_OUTMIXER_R (0x1 << 11)
+#define RT5631_M_MIC2_OUTMIXR_BIT 11
+#define RT5631_M_MONO_IN_N_TO_OUTMIXER_R (0x1 << 10)
+#define RT5631_M_MONO_INN_OUTMIXR_BIT 10
+#define RT5631_M_AXIL_TO_OUTMIXER_R (0x1 << 9)
+#define RT5631_M_AXIL_OUTMIXR_BIT 9
+#define RT5631_M_AXIR_TO_OUTMIXER_R (0x1 << 8)
+#define RT5631_M_AXIR_OUTMIXR_BIT 8
+#define RT5631_M_VDAC_TO_OUTMIXER_R (0x1 << 7)
+#define RT5631_M_VDAC_OUTMIXR_BIT 7
+
+/* Lout Mixer Control(0x1E) */
+#define RT5631_M_MIC1_TO_AXO1MIXER (0x1 << 15)
+#define RT5631_M_MIC1_AXO1MIX_BIT 15
+#define RT5631_M_MIC2_TO_AXO1MIXER (0x1 << 11)
+#define RT5631_M_MIC2_AXO1MIX_BIT 11
+#define RT5631_M_OUTMIXER_L_TO_AXO1MIXER (0x1 << 7)
+#define RT5631_M_OUTMIXL_AXO1MIX_BIT 7
+#define RT5631_M_OUTMIXER_R_TO_AXO1MIXER (0x1 << 6)
+#define RT5631_M_OUTMIXR_AXO1MIX_BIT 6
+
+/* Rout Mixer Control(0x20) */
+#define RT5631_M_MIC1_TO_AXO2MIXER (0x1 << 15)
+#define RT5631_M_MIC1_AXO2MIX_BIT 15
+#define RT5631_M_MIC2_TO_AXO2MIXER (0x1 << 11)
+#define RT5631_M_MIC2_AXO2MIX_BIT 11
+#define RT5631_M_OUTMIXER_L_TO_AXO2MIXER (0x1 << 7)
+#define RT5631_M_OUTMIXL_AXO2MIX_BIT 7
+#define RT5631_M_OUTMIXER_R_TO_AXO2MIXER (0x1 << 6)
+#define RT5631_M_OUTMIXR_AXO2MIX_BIT 6
+
+/* Micphone Input Control 2(0x22) */
+#define RT5631_MIC_BIAS_90_PRECNET_AVDD 1
+#define RT5631_MIC_BIAS_75_PRECNET_AVDD 2
+
+#define RT5631_MIC1_BOOST_CTRL_MASK (0xf << 12)
+#define RT5631_MIC1_BOOST_CTRL_BYPASS (0x0 << 12)
+#define RT5631_MIC1_BOOST_CTRL_20DB (0x1 << 12)
+#define RT5631_MIC1_BOOST_CTRL_24DB (0x2 << 12)
+#define RT5631_MIC1_BOOST_CTRL_30DB (0x3 << 12)
+#define RT5631_MIC1_BOOST_CTRL_35DB (0x4 << 12)
+#define RT5631_MIC1_BOOST_CTRL_40DB (0x5 << 12)
+#define RT5631_MIC1_BOOST_CTRL_34DB (0x6 << 12)
+#define RT5631_MIC1_BOOST_CTRL_50DB (0x7 << 12)
+#define RT5631_MIC1_BOOST_CTRL_52DB (0x8 << 12)
+#define RT5631_MIC1_BOOST_SHIFT 12
+
+#define RT5631_MIC2_BOOST_CTRL_MASK (0xf << 8)
+#define RT5631_MIC2_BOOST_CTRL_BYPASS (0x0 << 8)
+#define RT5631_MIC2_BOOST_CTRL_20DB (0x1 << 8)
+#define RT5631_MIC2_BOOST_CTRL_24DB (0x2 << 8)
+#define RT5631_MIC2_BOOST_CTRL_30DB (0x3 << 8)
+#define RT5631_MIC2_BOOST_CTRL_35DB (0x4 << 8)
+#define RT5631_MIC2_BOOST_CTRL_40DB (0x5 << 8)
+#define RT5631_MIC2_BOOST_CTRL_34DB (0x6 << 8)
+#define RT5631_MIC2_BOOST_CTRL_50DB (0x7 << 8)
+#define RT5631_MIC2_BOOST_CTRL_52DB (0x8 << 8)
+#define RT5631_MIC2_BOOST_SHIFT 8
+
+#define RT5631_MICBIAS1_VOLT_CTRL_MASK (0x1 << 7)
+#define RT5631_MICBIAS1_VOLT_CTRL_90P (0x0 << 7)
+#define RT5631_MICBIAS1_VOLT_CTRL_75P (0x1 << 7)
+
+#define RT5631_MICBIAS1_S_C_DET_MASK (0x1 << 6)
+#define RT5631_MICBIAS1_S_C_DET_DIS (0x0 << 6)
+#define RT5631_MICBIAS1_S_C_DET_ENA (0x1 << 6)
+
+#define RT5631_MICBIAS1_SHORT_CURR_DET_MASK (0x3 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_600UA (0x0 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_1500UA (0x1 << 4)
+#define RT5631_MICBIAS1_SHORT_CURR_DET_2000UA (0x2 << 4)
+
+#define RT5631_MICBIAS2_VOLT_CTRL_MASK (0x1 << 3)
+#define RT5631_MICBIAS2_VOLT_CTRL_90P (0x0 << 3)
+#define RT5631_MICBIAS2_VOLT_CTRL_75P (0x1 << 3)
+
+#define RT5631_MICBIAS2_S_C_DET_MASK (0x1 << 2)
+#define RT5631_MICBIAS2_S_C_DET_DIS (0x0 << 2)
+#define RT5631_MICBIAS2_S_C_DET_ENA (0x1 << 2)
+
+#define RT5631_MICBIAS2_SHORT_CURR_DET_MASK (0x3)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_600UA (0x0)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_1500UA (0x1)
+#define RT5631_MICBIAS2_SHORT_CURR_DET_2000UA (0x2)
+
+
+/* Digital Microphone Control(0x24) */
+#define RT5631_DMIC_ENA_MASK (0x1 << 15)
+#define RT5631_DMIC_ENA_SHIFT 15
+/* DMIC_ENA: DMIC to ADC Digital filter */
+#define RT5631_DMIC_ENA (0x1 << 15)
+/* DMIC_DIS: ADC mixer to ADC Digital filter */
+#define RT5631_DMIC_DIS (0x0 << 15)
+#define RT5631_DMIC_L_CH_MUTE (0x1 << 13)
+#define RT5631_DMIC_L_CH_MUTE_SHIFT 13
+#define RT5631_DMIC_R_CH_MUTE (0x1 << 12)
+#define RT5631_DMIC_R_CH_MUTE_SHIFT 12
+#define RT5631_DMIC_L_CH_LATCH_MASK (0x1 << 9)
+#define RT5631_DMIC_L_CH_LATCH_RISING (0x1 << 9)
+#define RT5631_DMIC_L_CH_LATCH_FALLING (0x0 << 9)
+#define RT5631_DMIC_R_CH_LATCH_MASK (0x1 << 8)
+#define RT5631_DMIC_R_CH_LATCH_RISING (0x1 << 8)
+#define RT5631_DMIC_R_CH_LATCH_FALLING (0x0 << 8)
+#define RT5631_DMIC_CLK_CTRL_MASK (0x3 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_128FS (0x0 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_64FS (0x1 << 4)
+#define RT5631_DMIC_CLK_CTRL_TO_32FS (0x2 << 4)
+
+/* Microphone Input Volume(0x26) */
+#define RT5631_MONO_DIFF_INPUT_SHIFT 15
+
+/* Speaker Mixer Control(0x28) */
+#define RT5631_M_RECMIXER_L_TO_SPKMIXER_L (0x1 << 15)
+#define RT5631_M_RECMIXL_SPKMIXL_BIT 15
+#define RT5631_M_MIC1_P_TO_SPKMIXER_L (0x1 << 14)
+#define RT5631_M_MIC1P_SPKMIXL_BIT 14
+#define RT5631_M_DAC_L_TO_SPKMIXER_L (0x1 << 13)
+#define RT5631_M_DACL_SPKMIXL_BIT 13
+#define RT5631_M_OUTMIXER_L_TO_SPKMIXER_L (0x1 << 12)
+#define RT5631_M_OUTMIXL_SPKMIXL_BIT 12
+
+#define RT5631_M_RECMIXER_R_TO_SPKMIXER_R (0x1 << 7)
+#define RT5631_M_RECMIXR_SPKMIXR_BIT 7
+#define RT5631_M_MIC2_P_TO_SPKMIXER_R (0x1 << 6)
+#define RT5631_M_MIC2P_SPKMIXR_BIT 6
+#define RT5631_M_DAC_R_TO_SPKMIXER_R (0x1 << 5)
+#define RT5631_M_DACR_SPKMIXR_BIT 5
+#define RT5631_M_OUTMIXER_R_TO_SPKMIXER_R (0x1 << 4)
+#define RT5631_M_OUTMIXR_SPKMIXR_BIT 4
+
+/* Speaker/Mono Output Control(0x2A) */
+#define RT5631_M_SPKVOL_L_TO_SPOL_MIXER (0x1 << 15)
+#define RT5631_M_SPKVOLL_SPOLMIX_BIT 15
+#define RT5631_M_SPKVOL_R_TO_SPOL_MIXER (0x1 << 14)
+#define RT5631_M_SPKVOLR_SPOLMIX_BIT 14
+#define RT5631_M_SPKVOL_L_TO_SPOR_MIXER (0x1 << 13)
+#define RT5631_M_SPKVOLL_SPORMIX_BIT 13
+#define RT5631_M_SPKVOL_R_TO_SPOR_MIXER (0x1 << 12)
+#define RT5631_M_SPKVOLR_SPORMIX_BIT 12
+#define RT5631_M_OUTVOL_L_TO_MONOMIXER (0x1 << 11)
+#define RT5631_M_OUTVOLL_MONOMIX_BIT 11
+#define RT5631_M_OUTVOL_R_TO_MONOMIXER (0x1 << 10)
+#define RT5631_M_OUTVOLR_MONOMIX_BIT 10
+
+/* Speaker/Mono/HP Output Control(0x2C) */
+#define RT5631_SPK_L_MUX_SEL_MASK (0x3 << 14)
+#define RT5631_SPK_L_MUX_SEL_SPKMIXER_L (0x0 << 14)
+#define RT5631_SPK_L_MUX_SEL_MONO_IN (0x1 << 14)
+#define RT5631_SPK_L_MUX_SEL_DAC_L (0x3 << 14)
+#define RT5631_SPK_L_MUX_SEL_SHIFT 14
+
+#define RT5631_SPK_R_MUX_SEL_MASK (0x3 << 10)
+#define RT5631_SPK_R_MUX_SEL_SPKMIXER_R (0x0 << 10)
+#define RT5631_SPK_R_MUX_SEL_MONO_IN (0x1 << 10)
+#define RT5631_SPK_R_MUX_SEL_DAC_R (0x3 << 10)
+#define RT5631_SPK_R_MUX_SEL_SHIFT 10
+
+#define RT5631_MONO_MUX_SEL_MASK (0x3 << 6)
+#define RT5631_MONO_MUX_SEL_MONOMIXER (0x0 << 6)
+#define RT5631_MONO_MUX_SEL_MONO_IN (0x1 << 6)
+#define RT5631_MONO_MUX_SEL_SHIFT 6
+
+#define RT5631_HP_L_MUX_SEL_MASK (0x1 << 3)
+#define RT5631_HP_L_MUX_SEL_HPVOL_L (0x0 << 3)
+#define RT5631_HP_L_MUX_SEL_DAC_L (0x1 << 3)
+#define RT5631_HP_L_MUX_SEL_SHIFT 3
+
+#define RT5631_HP_R_MUX_SEL_MASK (0x1 << 2)
+#define RT5631_HP_R_MUX_SEL_HPVOL_R (0x0 << 2)
+#define RT5631_HP_R_MUX_SEL_DAC_R (0x1 << 2)
+#define RT5631_HP_R_MUX_SEL_SHIFT 2
+
+/* Stereo I2S Serial Data Port Control(0x34) */
+#define RT5631_SDP_MODE_SEL_MASK (0x1 << 15)
+#define RT5631_SDP_MODE_SEL_MASTER (0x0 << 15)
+#define RT5631_SDP_MODE_SEL_SLAVE (0x1 << 15)
+
+#define RT5631_SDP_ADC_CPS_SEL_MASK (0x3 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_OFF (0x0 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_U_LAW (0x1 << 10)
+#define RT5631_SDP_ADC_CPS_SEL_A_LAW (0x2 << 10)
+
+#define RT5631_SDP_DAC_CPS_SEL_MASK (0x3 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_OFF (0x0 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_U_LAW (0x1 << 8)
+#define RT5631_SDP_DAC_CPS_SEL_A_LAW (0x2 << 8)
+/* 0:Normal 1:Invert */
+#define RT5631_SDP_I2S_BCLK_POL_CTRL (0x1 << 7)
+/* 0:Normal 1:Invert */
+#define RT5631_SDP_DAC_R_INV (0x1 << 6)
+/* 0:ADC data appear at left phase of LRCK
+ * 1:ADC data appear at right phase of LRCK
+ */
+#define RT5631_SDP_ADC_DATA_L_R_SWAP (0x1 << 5)
+/* 0:DAC data appear at left phase of LRCK
+ * 1:DAC data appear at right phase of LRCK
+ */
+#define RT5631_SDP_DAC_DATA_L_R_SWAP (0x1 << 4)
+
+/* Data Length Slection */
+#define RT5631_SDP_I2S_DL_MASK (0x3 << 2)
+#define RT5631_SDP_I2S_DL_16 (0x0 << 2)
+#define RT5631_SDP_I2S_DL_20 (0x1 << 2)
+#define RT5631_SDP_I2S_DL_24 (0x2 << 2)
+#define RT5631_SDP_I2S_DL_8 (0x3 << 2)
+
+/* PCM Data Format Selection */
+#define RT5631_SDP_I2S_DF_MASK (0x3)
+#define RT5631_SDP_I2S_DF_I2S (0x0)
+#define RT5631_SDP_I2S_DF_LEFT (0x1)
+#define RT5631_SDP_I2S_DF_PCM_A (0x2)
+#define RT5631_SDP_I2S_DF_PCM_B (0x3)
+
+/* Stereo AD/DA Clock Control(0x38h) */
+#define RT5631_I2S_PRE_DIV_MASK (0x7 << 13)
+#define RT5631_I2S_PRE_DIV_1 (0x0 << 13)
+#define RT5631_I2S_PRE_DIV_2 (0x1 << 13)
+#define RT5631_I2S_PRE_DIV_4 (0x2 << 13)
+#define RT5631_I2S_PRE_DIV_8 (0x3 << 13)
+#define RT5631_I2S_PRE_DIV_16 (0x4 << 13)
+#define RT5631_I2S_PRE_DIV_32 (0x5 << 13)
+/* CLOCK RELATIVE OF BCLK AND LCRK */
+#define RT5631_I2S_LRCK_SEL_N_BCLK_MASK (0x1 << 12)
+#define RT5631_I2S_LRCK_SEL_64_BCLK (0x0 << 12) /* 64FS */
+#define RT5631_I2S_LRCK_SEL_32_BCLK (0x1 << 12) /* 32FS */
+
+#define RT5631_DAC_OSR_SEL_MASK (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_128FS (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_64FS (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_32FS (0x3 << 10)
+#define RT5631_DAC_OSR_SEL_16FS (0x3 << 10)
+
+#define RT5631_ADC_OSR_SEL_MASK (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_128FS (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_64FS (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_32FS (0x3 << 8)
+#define RT5631_ADC_OSR_SEL_16FS (0x3 << 8)
+
+#define RT5631_ADDA_FILTER_CLK_SEL_256FS (0 << 7) /* 256FS */
+#define RT5631_ADDA_FILTER_CLK_SEL_384FS (1 << 7) /* 384FS */
+
+/* Power managment addition 1 (0x3A) */
+#define RT5631_PWR_MAIN_I2S_EN (0x1 << 15)
+#define RT5631_PWR_MAIN_I2S_BIT 15
+#define RT5631_PWR_CLASS_D (0x1 << 12)
+#define RT5631_PWR_CLASS_D_BIT 12
+#define RT5631_PWR_ADC_L_CLK (0x1 << 11)
+#define RT5631_PWR_ADC_L_CLK_BIT 11
+#define RT5631_PWR_ADC_R_CLK (0x1 << 10)
+#define RT5631_PWR_ADC_R_CLK_BIT 10
+#define RT5631_PWR_DAC_L_CLK (0x1 << 9)
+#define RT5631_PWR_DAC_L_CLK_BIT 9
+#define RT5631_PWR_DAC_R_CLK (0x1 << 8)
+#define RT5631_PWR_DAC_R_CLK_BIT 8
+#define RT5631_PWR_DAC_REF (0x1 << 7)
+#define RT5631_PWR_DAC_REF_BIT 7
+#define RT5631_PWR_DAC_L_TO_MIXER (0x1 << 6)
+#define RT5631_PWR_DAC_L_TO_MIXER_BIT 6
+#define RT5631_PWR_DAC_R_TO_MIXER (0x1 << 5)
+#define RT5631_PWR_DAC_R_TO_MIXER_BIT 5
+
+/* Power managment addition 2 (0x3B) */
+#define RT5631_PWR_OUTMIXER_L (0x1 << 15)
+#define RT5631_PWR_OUTMIXER_L_BIT 15
+#define RT5631_PWR_OUTMIXER_R (0x1 << 14)
+#define RT5631_PWR_OUTMIXER_R_BIT 14
+#define RT5631_PWR_SPKMIXER_L (0x1 << 13)
+#define RT5631_PWR_SPKMIXER_L_BIT 13
+#define RT5631_PWR_SPKMIXER_R (0x1 << 12)
+#define RT5631_PWR_SPKMIXER_R_BIT 12
+#define RT5631_PWR_RECMIXER_L (0x1 << 11)
+#define RT5631_PWR_RECMIXER_L_BIT 11
+#define RT5631_PWR_RECMIXER_R (0x1 << 10)
+#define RT5631_PWR_RECMIXER_R_BIT 10
+#define RT5631_PWR_MIC1_BOOT_GAIN (0x1 << 5)
+#define RT5631_PWR_MIC1_BOOT_GAIN_BIT 5
+#define RT5631_PWR_MIC2_BOOT_GAIN (0x1 << 4)
+#define RT5631_PWR_MIC2_BOOT_GAIN_BIT 4
+#define RT5631_PWR_MICBIAS1_VOL (0x1 << 3)
+#define RT5631_PWR_MICBIAS1_VOL_BIT 3
+#define RT5631_PWR_MICBIAS2_VOL (0x1 << 2)
+#define RT5631_PWR_MICBIAS2_VOL_BIT 2
+#define RT5631_PWR_PLL1 (0x1 << 1)
+#define RT5631_PWR_PLL1_BIT 1
+#define RT5631_PWR_PLL2 (0x1 << 0)
+#define RT5631_PWR_PLL2_BIT 0
+
+/* Power managment addition 3(0x3C) */
+#define RT5631_PWR_VREF (0x1 << 15)
+#define RT5631_PWR_VREF_BIT 15
+#define RT5631_PWR_FAST_VREF_CTRL (0x1 << 14)
+#define RT5631_PWR_FAST_VREF_CTRL_BIT 14
+#define RT5631_PWR_MAIN_BIAS (0x1 << 13)
+#define RT5631_PWR_MAIN_BIAS_BIT 13
+#define RT5631_PWR_AXO1MIXER (0x1 << 11)
+#define RT5631_PWR_AXO1MIXER_BIT 11
+#define RT5631_PWR_AXO2MIXER (0x1 << 10)
+#define RT5631_PWR_AXO2MIXER_BIT 10
+#define RT5631_PWR_MONOMIXER (0x1 << 9)
+#define RT5631_PWR_MONOMIXER_BIT 9
+#define RT5631_PWR_MONO_DEPOP_DIS (0x1 << 8)
+#define RT5631_PWR_MONO_DEPOP_DIS_BIT 8
+#define RT5631_PWR_MONO_AMP_EN (0x1 << 7)
+#define RT5631_PWR_MONO_AMP_EN_BIT 7
+#define RT5631_PWR_CHARGE_PUMP (0x1 << 4)
+#define RT5631_PWR_CHARGE_PUMP_BIT 4
+#define RT5631_PWR_HP_L_AMP (0x1 << 3)
+#define RT5631_PWR_HP_L_AMP_BIT 3
+#define RT5631_PWR_HP_R_AMP (0x1 << 2)
+#define RT5631_PWR_HP_R_AMP_BIT 2
+#define RT5631_PWR_HP_DEPOP_DIS (0x1 << 1)
+#define RT5631_PWR_HP_DEPOP_DIS_BIT 1
+#define RT5631_PWR_HP_AMP_DRIVING (0x1 << 0)
+#define RT5631_PWR_HP_AMP_DRIVING_BIT 0
+
+/* Power managment addition 4(0x3E) */
+#define RT5631_PWR_SPK_L_VOL (0x1 << 15)
+#define RT5631_PWR_SPK_L_VOL_BIT 15
+#define RT5631_PWR_SPK_R_VOL (0x1 << 14)
+#define RT5631_PWR_SPK_R_VOL_BIT 14
+#define RT5631_PWR_LOUT_VOL (0x1 << 13)
+#define RT5631_PWR_LOUT_VOL_BIT 13
+#define RT5631_PWR_ROUT_VOL (0x1 << 12)
+#define RT5631_PWR_ROUT_VOL_BIT 12
+#define RT5631_PWR_HP_L_OUT_VOL (0x1 << 11)
+#define RT5631_PWR_HP_L_OUT_VOL_BIT 11
+#define RT5631_PWR_HP_R_OUT_VOL (0x1 << 10)
+#define RT5631_PWR_HP_R_OUT_VOL_BIT 10
+#define RT5631_PWR_AXIL_IN_VOL (0x1 << 9)
+#define RT5631_PWR_AXIL_IN_VOL_BIT 9
+#define RT5631_PWR_AXIR_IN_VOL (0x1 << 8)
+#define RT5631_PWR_AXIR_IN_VOL_BIT 8
+#define RT5631_PWR_MONO_IN_P_VOL (0x1 << 7)
+#define RT5631_PWR_MONO_IN_P_VOL_BIT 7
+#define RT5631_PWR_MONO_IN_N_VOL (0x1 << 6)
+#define RT5631_PWR_MONO_IN_N_VOL_BIT 6
+
+/* General Purpose Control Register(0x40) */
+#define RT5631_SPK_AMP_AUTO_RATIO_EN (0x1 << 15)
+
+#define RT5631_SPK_AMP_RATIO_CTRL_MASK (0x7 << 12)
+#define RT5631_SPK_AMP_RATIO_CTRL_2_34 (0x0 << 12) /* 7.40DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_99 (0x1 << 12) /* 5.99DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_68 (0x2 << 12) /* 4.50DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_56 (0x3 << 12) /* 3.86DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_44 (0x4 << 12) /* 3.16DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_27 (0x5 << 12) /* 2.10DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_09 (0x6 << 12) /* 0.80DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_1_00 (0x7 << 12) /* 0.00DB */
+#define RT5631_SPK_AMP_RATIO_CTRL_SHIFT 12
+
+#define RT5631_STEREO_DAC_HI_PASS_FILT_EN (0x1 << 11)
+#define RT5631_STEREO_ADC_HI_PASS_FILT_EN (0x1 << 10)
+/* Select ADC Wind Filter Clock type */
+#define RT5631_ADC_WIND_FILT_MASK (0x3 << 4)
+#define RT5631_ADC_WIND_FILT_8_16_32K (0x0 << 4) /*8/16/32k*/
+#define RT5631_ADC_WIND_FILT_11_22_44K (0x1 << 4) /*11/22/44k*/
+#define RT5631_ADC_WIND_FILT_12_24_48K (0x2 << 4) /*12/24/48k*/
+#define RT5631_ADC_WIND_FILT_EN (0x1 << 3)
+/* SelectADC Wind Filter Corner Frequency */
+#define RT5631_ADC_WIND_CNR_FREQ_MASK (0x7 << 0)
+#define RT5631_ADC_WIND_CNR_FREQ_82_113_122 (0x0 << 0) /* 82/113/122 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_102_141_153 (0x1 << 0) /* 102/141/153 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_131_180_156 (0x2 << 0) /* 131/180/156 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_163_225_245 (0x3 << 0) /* 163/225/245 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_204_281_306 (0x4 << 0) /* 204/281/306 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_261_360_392 (0x5 << 0) /* 261/360/392 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_327_450_490 (0x6 << 0) /* 327/450/490 Hz */
+#define RT5631_ADC_WIND_CNR_FREQ_408_563_612 (0x7 << 0) /* 408/563/612 Hz */
+
+/* Global Clock Control Register(0x42) */
+#define RT5631_SYSCLK_SOUR_SEL_MASK (0x3 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_MCLK (0x0 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_PLL (0x1 << 14)
+#define RT5631_SYSCLK_SOUR_SEL_PLL_TCK (0x2 << 14)
+
+#define RT5631_PLLCLK_SOUR_SEL_MASK (0x3 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_MCLK (0x0 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_BCLK (0x1 << 12)
+#define RT5631_PLLCLK_SOUR_SEL_VBCLK (0x2 << 12)
+
+#define RT5631_PLLCLK_PRE_DIV1 (0x0 << 11)
+#define RT5631_PLLCLK_PRE_DIV2 (0x1 << 11)
+
+/* PLL Control(0x44) */
+#define RT5631_PLL_CTRL_M_VAL(m) ((m)&0xf)
+#define RT5631_PLL_CTRL_K_VAL(k) (((k)&0x7) << 4)
+#define RT5631_PLL_CTRL_N_VAL(n) (((n)&0xff) << 8)
+
+/* Internal Status and IRQ Control2(0x4A) */
+#define RT5631_ADC_DATA_SEL_MASK (0x3 << 14)
+#define RT5631_ADC_DATA_SEL_Disable (0x0 << 14)
+#define RT5631_ADC_DATA_SEL_MIC1 (0x1 << 14)
+#define RT5631_ADC_DATA_SEL_MIC1_SHIFT 14
+#define RT5631_ADC_DATA_SEL_MIC2 (0x2 << 14)
+#define RT5631_ADC_DATA_SEL_MIC2_SHIFT 15
+#define RT5631_ADC_DATA_SEL_STO (0x3 << 14)
+#define RT5631_ADC_DATA_SEL_SHIFT 14
+
+/* GPIO Pin Configuration(0x4C) */
+#define RT5631_GPIO_PIN_FUN_SEL_MASK (0x1 << 15)
+#define RT5631_GPIO_PIN_FUN_SEL_IRQ (0x1 << 15)
+#define RT5631_GPIO_PIN_FUN_SEL_GPIO_DIMC (0x0 << 15)
+
+#define RT5631_GPIO_DMIC_FUN_SEL_MASK (0x1 << 3)
+#define RT5631_GPIO_DMIC_FUN_SEL_DIMC (0x1 << 3)
+#define RT5631_GPIO_DMIC_FUN_SEL_GPIO (0x0 << 3)
+
+#define RT5631_GPIO_PIN_CON_MASK (0x1 << 2)
+#define RT5631_GPIO_PIN_SET_INPUT (0x0 << 2)
+#define RT5631_GPIO_PIN_SET_OUTPUT (0x1 << 2)
+
+/* De-POP function Control 1(0x54) */
+#define RT5631_POW_ON_SOFT_GEN (0x1 << 15)
+#define RT5631_EN_MUTE_UNMUTE_DEPOP (0x1 << 14)
+#define RT5631_EN_DEPOP2_FOR_HP (0x1 << 7)
+/* Power Down HPAMP_L Starts Up Signal */
+#define RT5631_PD_HPAMP_L_ST_UP (0x1 << 5)
+/* Power Down HPAMP_R Starts Up Signal */
+#define RT5631_PD_HPAMP_R_ST_UP (0x1 << 4)
+/* Enable left HP mute/unmute depop */
+#define RT5631_EN_HP_L_M_UN_MUTE_DEPOP (0x1 << 1)
+/* Enable right HP mute/unmute depop */
+#define RT5631_EN_HP_R_M_UN_MUTE_DEPOP (0x1 << 0)
+
+/* De-POP Fnction Control(0x56) */
+#define RT5631_EN_ONE_BIT_DEPOP (0x1 << 15)
+#define RT5631_EN_CAP_FREE_DEPOP (0x1 << 14)
+
+/* Jack Detect Control Register(0x5A) */
+#define RT5631_JD_USE_MASK (0x3 << 14)
+#define RT5631_JD_USE_JD2 (0x3 << 14)
+#define RT5631_JD_USE_JD1 (0x2 << 14)
+#define RT5631_JD_USE_GPIO (0x1 << 14)
+#define RT5631_JD_OFF (0x0 << 14)
+/* JD trigger enable for HP */
+#define RT5631_JD_HP_EN (0x1 << 11)
+#define RT5631_JD_HP_TRI_MASK (0x1 << 10)
+#define RT5631_JD_HP_TRI_HI (0x1 << 10)
+#define RT5631_JD_HP_TRI_LO (0x1 << 10)
+/* JD trigger enable for speaker LP/LN */
+#define RT5631_JD_SPK_L_EN (0x1 << 9)
+#define RT5631_JD_SPK_L_TRI_MASK (0x1 << 8)
+#define RT5631_JD_SPK_L_TRI_HI (0x1 << 8)
+#define RT5631_JD_SPK_L_TRI_LO (0x0 << 8)
+/* JD trigger enable for speaker RP/RN */
+#define RT5631_JD_SPK_R_EN (0x1 << 7)
+#define RT5631_JD_SPK_R_TRI_MASK (0x1 << 6)
+#define RT5631_JD_SPK_R_TRI_HI (0x1 << 6)
+#define RT5631_JD_SPK_R_TRI_LO (0x0 << 6)
+/* JD trigger enable for monoout */
+#define RT5631_JD_MONO_EN (0x1 << 5)
+#define RT5631_JD_MONO_TRI_MASK (0x1 << 4)
+#define RT5631_JD_MONO_TRI_HI (0x1 << 4)
+#define RT5631_JD_MONO_TRI_LO (0x0 << 4)
+/* JD trigger enable for Lout */
+#define RT5631_JD_AUX_1_EN (0x1 << 3)
+#define RT5631_JD_AUX_1_MASK (0x1 << 2)
+#define RT5631_JD_AUX_1_TRI_HI (0x1 << 2)
+#define RT5631_JD_AUX_1_TRI_LO (0x0 << 2)
+/* JD trigger enable for Rout */
+#define RT5631_JD_AUX_2_EN (0x1 << 1)
+#define RT5631_JD_AUX_2_MASK (0x1 << 0)
+#define RT5631_JD_AUX_2_TRI_HI (0x1 << 0)
+#define RT5631_JD_AUX_2_TRI_LO (0x0 << 0)
+
+/* ALC CONTROL 1(0x64) */
+#define RT5631_ALC_ATTACK_RATE_MASK (0x1F << 8)
+#define RT5631_ALC_RECOVERY_RATE_MASK (0x1F << 0)
+
+/* ALC CONTROL 2(0x65) */
+/* select Compensation gain for Noise gate function */
+#define RT5631_ALC_COM_NOISE_GATE_MASK (0xF << 0)
+
+/* ALC CONTROL 3(0x66) */
+#define RT5631_ALC_FUN_MASK (0x3 << 14)
+#define RT5631_ALC_FUN_DIS (0x0 << 14)
+#define RT5631_ALC_ENA_DAC_PATH (0x1 << 14)
+#define RT5631_ALC_ENA_ADC_PATH (0x3 << 14)
+#define RT5631_ALC_PARA_UPDATE (0x1 << 13)
+#define RT5631_ALC_LIMIT_LEVEL_MASK (0x1F << 8)
+#define RT5631_ALC_NOISE_GATE_FUN_MASK (0x1 << 7)
+#define RT5631_ALC_NOISE_GATE_FUN_DIS (0x0 << 7)
+#define RT5631_ALC_NOISE_GATE_FUN_ENA (0x1 << 7)
+/* ALC noise gate hold data function */
+#define RT5631_ALC_NOISE_GATE_H_D_MASK (0x1 << 6)
+#define RT5631_ALC_NOISE_GATE_H_D_DIS (0x0 << 6)
+#define RT5631_ALC_NOISE_GATE_H_D_ENA (0x1 << 6)
+
+/* Psedueo Stereo & Spatial Effect Block Control(0x68) */
+#define RT5631_SPATIAL_CTRL_EN (0x1 << 15)
+#define RT5631_ALL_PASS_FILTER_EN (0x1 << 14)
+#define RT5631_PSEUDO_STEREO_EN (0x1 << 13)
+#define RT5631_STEREO_EXPENSION_EN (0x1 << 12)
+/* 3D gain parameter */
+#define RT5631_GAIN_3D_PARA_MASK (0x3 << 6)
+#define RT5631_GAIN_3D_PARA_1_00 (0x0 << 6) /* 3D gain 1.0 */
+#define RT5631_GAIN_3D_PARA_1_50 (0x1 << 6) /* 3D gain 1.5 */
+#define RT5631_GAIN_3D_PARA_2_00 (0x2 << 6) /* 3D gain 2.0 */
+/* 3D ratio parameter */
+#define RT5631_RATIO_3D_MASK (0x3 << 4)
+#define RT5631_RATIO_3D_0_0 (0x0 << 4) /* 3D ratio 0.0 */
+#define RT5631_RATIO_3D_0_66 (0x1 << 4) /* 3D ratio 0.66 */
+#define RT5631_RATIO_3D_1_0 (0x2 << 4) /* 3D ratio 1.0 */
+/* select samplerate for all pass filter */
+#define RT5631_APF_FUN_SLE_MASK (0x3 << 0)
+#define RT5631_APF_FUN_SEL_48K (0x3 << 0)
+#define RT5631_APF_FUN_SEL_44_1K (0x2 << 0)
+#define RT5631_APF_FUN_SEL_32K (0x1 << 0)
+#define RT5631_APF_FUN_DIS (0x0 << 0)
+
+/* EQ CONTROL 1(0x6E) */
+#define RT5631_HW_EQ_PATH_SEL_MASK (0x1 << 15)
+#define RT5631_HW_EQ_PATH_SEL_DAC (0x0 << 15)
+#define RT5631_HW_EQ_PATH_SEL_ADC (0x1 << 15)
+#define RT5631_HW_EQ_UPDATE_CTRL (0x1 << 14)
+
+#define RT5631_EN_HW_EQ_HPF2 (0x1 << 5)
+#define RT5631_EN_HW_EQ_HPF1 (0x1 << 4)
+#define RT5631_EN_HW_EQ_BP3 (0x1 << 3)
+#define RT5631_EN_HW_EQ_BP2 (0x1 << 2)
+#define RT5631_EN_HW_EQ_BP1 (0x1 << 1)
+#define RT5631_EN_HW_EQ_LPF (0x1 << 0)
+
+
+#endif /* __RTCODEC5631_H__ */
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index 7e4066e131e6..d1926266fe00 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -16,10 +16,10 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/clk.h>
-#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/consumer.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/tlv.h>
#include <sound/pcm.h>
@@ -130,16 +130,13 @@ static int mic_bias_event(struct snd_soc_dapm_widget *w,
case SND_SOC_DAPM_POST_PMU:
/* change mic bias resistor to 4Kohm */
snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
- SGTL5000_BIAS_R_4k, SGTL5000_BIAS_R_4k);
+ SGTL5000_BIAS_R_MASK,
+ SGTL5000_BIAS_R_4k << SGTL5000_BIAS_R_SHIFT);
break;
case SND_SOC_DAPM_PRE_PMD:
- /*
- * SGTL5000_BIAS_R_8k as mask to clean the two bits
- * of mic bias and output impedance
- */
snd_soc_update_bits(w->codec, SGTL5000_CHIP_MIC_CTRL,
- SGTL5000_BIAS_R_8k, 0);
+ SGTL5000_BIAS_R_MASK, 0);
break;
}
return 0;
@@ -230,7 +227,7 @@ static const struct snd_soc_dapm_widget sgtl5000_dapm_widgets[] = {
};
/* routes for sgtl5000 */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route sgtl5000_dapm_routes[] = {
{"Capture Mux", "LINE_IN", "LINE_IN"}, /* line_in --> adc_mux */
{"Capture Mux", "MIC_IN", "MIC_IN"}, /* mic_in --> adc_mux */
@@ -367,7 +364,7 @@ static const DECLARE_TLV_DB_SCALE(capture_6db_attenuate, -600, 600, 0);
/* tlv for mic gain, 0db 20db 30db 40db */
static const unsigned int mic_gain_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+ TLV_DB_RANGE_HEAD(2),
0, 0, TLV_DB_SCALE_ITEM(0, 0, 0),
1, 3, TLV_DB_SCALE_ITEM(2000, 1000, 0),
};
@@ -725,7 +722,9 @@ static int sgtl5000_pcm_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL, i2s_ctl, i2s_ctl);
+ snd_soc_update_bits(codec, SGTL5000_CHIP_I2S_CTRL,
+ SGTL5000_I2S_DLEN_MASK | SGTL5000_I2S_SCLKFREQ_MASK,
+ i2s_ctl);
return 0;
}
@@ -756,7 +755,7 @@ static int ldo_regulator_enable(struct regulator_dev *dev)
/* set voltage to register */
snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
- (0x1 << 4) - 1, reg);
+ SGTL5000_LINREG_VDDD_MASK, reg);
snd_soc_update_bits(codec, SGTL5000_CHIP_ANA_POWER,
SGTL5000_LINEREG_D_POWERUP,
@@ -782,7 +781,7 @@ static int ldo_regulator_disable(struct regulator_dev *dev)
/* clear voltage info */
snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
- (0x1 << 4) - 1, 0);
+ SGTL5000_LINREG_VDDD_MASK, 0);
ldo->enabled = 0;
@@ -808,6 +807,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
int voltage)
{
struct ldo_regulator *ldo;
+ struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
ldo = kzalloc(sizeof(struct ldo_regulator), GFP_KERNEL);
@@ -832,7 +832,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
ldo->voltage = voltage;
ldo->dev = regulator_register(&ldo->desc, codec->dev,
- init_data, ldo);
+ init_data, ldo, NULL);
if (IS_ERR(ldo->dev)) {
int ret = PTR_ERR(ldo->dev);
@@ -842,6 +842,7 @@ static int ldo_regulator_register(struct snd_soc_codec *codec,
return ret;
}
+ sgtl5000->ldo = ldo;
return 0;
}
@@ -921,7 +922,7 @@ static int sgtl5000_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops sgtl5000_ops = {
+static const struct snd_soc_dai_ops sgtl5000_ops = {
.hw_params = sgtl5000_pcm_hw_params,
.digital_mute = sgtl5000_digital_mute,
.set_fmt = sgtl5000_set_dai_fmt,
@@ -966,7 +967,7 @@ static int sgtl5000_volatile_register(struct snd_soc_codec *codec,
}
#ifdef CONFIG_SUSPEND
-static int sgtl5000_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int sgtl5000_suspend(struct snd_soc_codec *codec)
{
sgtl5000_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -986,12 +987,12 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
/* restore regular registers */
for (reg = 0; reg <= SGTL5000_CHIP_SHORT_CTRL; reg += 2) {
- /* this regs depends on the others */
+ /* These regs should restore in particular order */
if (reg == SGTL5000_CHIP_ANA_POWER ||
reg == SGTL5000_CHIP_CLK_CTRL ||
reg == SGTL5000_CHIP_LINREG_CTRL ||
reg == SGTL5000_CHIP_LINE_OUT_CTRL ||
- reg == SGTL5000_CHIP_CLK_CTRL)
+ reg == SGTL5000_CHIP_REF_CTRL)
continue;
snd_soc_write(codec, reg, cache[reg]);
@@ -1002,8 +1003,17 @@ static int sgtl5000_restore_regs(struct snd_soc_codec *codec)
snd_soc_write(codec, reg, cache[reg]);
/*
- * restore power and other regs according
- * to set_power() and set_clock()
+ * restore these regs according to the power setting sequence in
+ * sgtl5000_set_power_regs() and clock setting sequence in
+ * sgtl5000_set_clock().
+ *
+ * The order of restore is:
+ * 1. SGTL5000_CHIP_CLK_CTRL MCLK_FREQ bits (1:0) should be restore after
+ * SGTL5000_CHIP_ANA_POWER PLL bits set
+ * 2. SGTL5000_CHIP_LINREG_CTRL should be set before
+ * SGTL5000_CHIP_ANA_POWER LINREG_D restored
+ * 3. SGTL5000_CHIP_REF_CTRL controls Analog Ground Voltage,
+ * prefer to resotre it after SGTL5000_CHIP_ANA_POWER restored
*/
snd_soc_write(codec, SGTL5000_CHIP_LINREG_CTRL,
cache[SGTL5000_CHIP_LINREG_CTRL]);
@@ -1075,7 +1085,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
/* according to datasheet, maximum voltage of supplies */
if (vdda > 3600 || vddio > 3600 || vddd > 1980) {
dev_err(codec->dev,
- "exceed max voltage vdda %dmv vddio %dma vddd %dma\n",
+ "exceed max voltage vdda %dmV vddio %dmV vddd %dmV\n",
vdda, vddio, vddd);
return -EINVAL;
@@ -1115,7 +1125,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
/* set voltage to register */
snd_soc_update_bits(codec, SGTL5000_CHIP_LINREG_CTRL,
- (0x1 << 4) - 1, 0x8);
+ SGTL5000_LINREG_VDDD_MASK, 0x8);
/*
* if vddd linear reg has been enabled,
@@ -1146,8 +1156,7 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
vag = (vag - SGTL5000_ANA_GND_BASE) / SGTL5000_ANA_GND_STP;
snd_soc_update_bits(codec, SGTL5000_CHIP_REF_CTRL,
- vag << SGTL5000_ANA_GND_SHIFT,
- vag << SGTL5000_ANA_GND_SHIFT);
+ SGTL5000_ANA_GND_MASK, vag << SGTL5000_ANA_GND_SHIFT);
/* set line out VAG to vddio / 2, in range (0.8v, 1.675v) */
vag = vddio / 2;
@@ -1161,9 +1170,8 @@ static int sgtl5000_set_power_regs(struct snd_soc_codec *codec)
SGTL5000_LINE_OUT_GND_STP;
snd_soc_update_bits(codec, SGTL5000_CHIP_LINE_OUT_CTRL,
- vag << SGTL5000_LINE_OUT_GND_SHIFT |
- SGTL5000_LINE_OUT_CURRENT_360u <<
- SGTL5000_LINE_OUT_CURRENT_SHIFT,
+ SGTL5000_LINE_OUT_CURRENT_MASK |
+ SGTL5000_LINE_OUT_GND_MASK,
vag << SGTL5000_LINE_OUT_GND_SHIFT |
SGTL5000_LINE_OUT_CURRENT_360u <<
SGTL5000_LINE_OUT_CURRENT_SHIFT);
@@ -1240,7 +1248,7 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
}
rev = (reg & SGTL5000_REVID_MASK) >> SGTL5000_REVID_SHIFT;
- dev_info(codec->dev, "sgtl5000 revision %d\n", rev);
+ dev_info(codec->dev, "sgtl5000 revision 0x%x\n", rev);
/*
* workaround for revision 0x11 and later,
@@ -1345,15 +1353,6 @@ static int sgtl5000_probe(struct snd_soc_codec *codec)
if (ret)
goto err;
- snd_soc_add_controls(codec, sgtl5000_snd_controls,
- ARRAY_SIZE(sgtl5000_snd_controls));
-
- snd_soc_dapm_new_controls(&codec->dapm, sgtl5000_dapm_widgets,
- ARRAY_SIZE(sgtl5000_dapm_widgets));
-
- snd_soc_dapm_add_routes(&codec->dapm, audio_map,
- ARRAY_SIZE(audio_map));
-
snd_soc_dapm_new_widgets(&codec->dapm);
return 0;
@@ -1394,6 +1393,12 @@ static struct snd_soc_codec_driver sgtl5000_driver = {
.reg_cache_step = 2,
.reg_cache_default = sgtl5000_regs,
.volatile_register = sgtl5000_volatile_register,
+ .controls = sgtl5000_snd_controls,
+ .num_controls = ARRAY_SIZE(sgtl5000_snd_controls),
+ .dapm_widgets = sgtl5000_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sgtl5000_dapm_widgets),
+ .dapm_routes = sgtl5000_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(sgtl5000_dapm_routes),
};
static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
@@ -1402,7 +1407,8 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
struct sgtl5000_priv *sgtl5000;
int ret;
- sgtl5000 = kzalloc(sizeof(struct sgtl5000_priv), GFP_KERNEL);
+ sgtl5000 = devm_kzalloc(&client->dev, sizeof(struct sgtl5000_priv),
+ GFP_KERNEL);
if (!sgtl5000)
return -ENOMEM;
@@ -1410,22 +1416,13 @@ static __devinit int sgtl5000_i2c_probe(struct i2c_client *client,
ret = snd_soc_register_codec(&client->dev,
&sgtl5000_driver, &sgtl5000_dai, 1);
- if (ret) {
- dev_err(&client->dev, "Failed to register codec: %d\n", ret);
- kfree(sgtl5000);
- return ret;
- }
-
- return 0;
+ return ret;
}
static __devexit int sgtl5000_i2c_remove(struct i2c_client *client)
{
- struct sgtl5000_priv *sgtl5000 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- kfree(sgtl5000);
return 0;
}
@@ -1436,10 +1433,17 @@ static const struct i2c_device_id sgtl5000_id[] = {
MODULE_DEVICE_TABLE(i2c, sgtl5000_id);
+static const struct of_device_id sgtl5000_dt_ids[] = {
+ { .compatible = "fsl,sgtl5000", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids);
+
static struct i2c_driver sgtl5000_i2c_driver = {
.driver = {
.name = "sgtl5000",
.owner = THIS_MODULE,
+ .of_match_table = sgtl5000_dt_ids,
},
.probe = sgtl5000_i2c_probe,
.remove = __devexit_p(sgtl5000_i2c_remove),
@@ -1459,5 +1463,5 @@ static void __exit sgtl5000_exit(void)
module_exit(sgtl5000_exit);
MODULE_DESCRIPTION("Freescale SGTL5000 ALSA SoC Codec Driver");
-MODULE_AUTHOR("Zeng Zhaoming <zhaoming.zeng@freescale.com>");
+MODULE_AUTHOR("Zeng Zhaoming <zengzm.kernel@gmail.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sgtl5000.h b/sound/soc/codecs/sgtl5000.h
index eec3ab368f39..8a9f43534b79 100644
--- a/sound/soc/codecs/sgtl5000.h
+++ b/sound/soc/codecs/sgtl5000.h
@@ -280,7 +280,7 @@
/*
* SGTL5000_CHIP_MIC_CTRL
*/
-#define SGTL5000_BIAS_R_MASK 0x0200
+#define SGTL5000_BIAS_R_MASK 0x0300
#define SGTL5000_BIAS_R_SHIFT 8
#define SGTL5000_BIAS_R_WIDTH 2
#define SGTL5000_BIAS_R_off 0x0
diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c
new file mode 100644
index 000000000000..5be42bf56996
--- /dev/null
+++ b/sound/soc/codecs/sigmadsp.c
@@ -0,0 +1,246 @@
+/*
+ * Load Analog Devices SigmaStudio firmware files
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/regmap.h>
+#include <linux/module.h>
+
+#include "sigmadsp.h"
+
+#define SIGMA_MAGIC "ADISIGM"
+
+struct sigma_firmware_header {
+ unsigned char magic[7];
+ u8 version;
+ __le32 crc;
+} __packed;
+
+enum {
+ SIGMA_ACTION_WRITEXBYTES = 0,
+ SIGMA_ACTION_WRITESINGLE,
+ SIGMA_ACTION_WRITESAFELOAD,
+ SIGMA_ACTION_DELAY,
+ SIGMA_ACTION_PLLWAIT,
+ SIGMA_ACTION_NOOP,
+ SIGMA_ACTION_END,
+};
+
+struct sigma_action {
+ u8 instr;
+ u8 len_hi;
+ __le16 len;
+ __be16 addr;
+ unsigned char payload[];
+} __packed;
+
+struct sigma_firmware {
+ const struct firmware *fw;
+ size_t pos;
+
+ void *control_data;
+ int (*write)(void *control_data, const struct sigma_action *sa,
+ size_t len);
+};
+
+static inline u32 sigma_action_len(struct sigma_action *sa)
+{
+ return (sa->len_hi << 16) | le16_to_cpu(sa->len);
+}
+
+static size_t sigma_action_size(struct sigma_action *sa)
+{
+ size_t payload = 0;
+
+ switch (sa->instr) {
+ case SIGMA_ACTION_WRITEXBYTES:
+ case SIGMA_ACTION_WRITESINGLE:
+ case SIGMA_ACTION_WRITESAFELOAD:
+ payload = sigma_action_len(sa);
+ break;
+ default:
+ break;
+ }
+
+ payload = ALIGN(payload, 2);
+
+ return payload + sizeof(struct sigma_action);
+}
+
+/*
+ * Returns a negative error value in case of an error, 0 if processing of
+ * the firmware should be stopped after this action, 1 otherwise.
+ */
+static int
+process_sigma_action(struct sigma_firmware *ssfw, struct sigma_action *sa)
+{
+ size_t len = sigma_action_len(sa);
+ int ret;
+
+ pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
+ sa->instr, sa->addr, len);
+
+ switch (sa->instr) {
+ case SIGMA_ACTION_WRITEXBYTES:
+ case SIGMA_ACTION_WRITESINGLE:
+ case SIGMA_ACTION_WRITESAFELOAD:
+ ret = ssfw->write(ssfw->control_data, sa, len);
+ if (ret < 0)
+ return -EINVAL;
+ break;
+ case SIGMA_ACTION_DELAY:
+ udelay(len);
+ len = 0;
+ break;
+ case SIGMA_ACTION_END:
+ return 0;
+ default:
+ return -EINVAL;
+ }
+
+ return 1;
+}
+
+static int
+process_sigma_actions(struct sigma_firmware *ssfw)
+{
+ struct sigma_action *sa;
+ size_t size;
+ int ret;
+
+ while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
+ sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
+
+ size = sigma_action_size(sa);
+ ssfw->pos += size;
+ if (ssfw->pos > ssfw->fw->size || size == 0)
+ break;
+
+ ret = process_sigma_action(ssfw, sa);
+
+ pr_debug("%s: action returned %i\n", __func__, ret);
+
+ if (ret <= 0)
+ return ret;
+ }
+
+ if (ssfw->pos != ssfw->fw->size)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int _process_sigma_firmware(struct device *dev,
+ struct sigma_firmware *ssfw, const char *name)
+{
+ int ret;
+ struct sigma_firmware_header *ssfw_head;
+ const struct firmware *fw;
+ u32 crc;
+
+ pr_debug("%s: loading firmware %s\n", __func__, name);
+
+ /* first load the blob */
+ ret = request_firmware(&fw, name, dev);
+ if (ret) {
+ pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
+ return ret;
+ }
+ ssfw->fw = fw;
+
+ /* then verify the header */
+ ret = -EINVAL;
+
+ /*
+ * Reject too small or unreasonable large files. The upper limit has been
+ * chosen a bit arbitrarily, but it should be enough for all practical
+ * purposes and having the limit makes it easier to avoid integer
+ * overflows later in the loading process.
+ */
+ if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) {
+ dev_err(dev, "Failed to load firmware: Invalid size\n");
+ goto done;
+ }
+
+ ssfw_head = (void *)fw->data;
+ if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) {
+ dev_err(dev, "Failed to load firmware: Invalid magic\n");
+ goto done;
+ }
+
+ crc = crc32(0, fw->data + sizeof(*ssfw_head),
+ fw->size - sizeof(*ssfw_head));
+ pr_debug("%s: crc=%x\n", __func__, crc);
+ if (crc != le32_to_cpu(ssfw_head->crc)) {
+ dev_err(dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n",
+ le32_to_cpu(ssfw_head->crc), crc);
+ goto done;
+ }
+
+ ssfw->pos = sizeof(*ssfw_head);
+
+ /* finally process all of the actions */
+ ret = process_sigma_actions(ssfw);
+
+ done:
+ release_firmware(fw);
+
+ pr_debug("%s: loaded %s\n", __func__, name);
+
+ return ret;
+}
+
+#if IS_ENABLED(CONFIG_I2C)
+
+static int sigma_action_write_i2c(void *control_data,
+ const struct sigma_action *sa, size_t len)
+{
+ return i2c_master_send(control_data, (const unsigned char *)&sa->addr,
+ len);
+}
+
+int process_sigma_firmware(struct i2c_client *client, const char *name)
+{
+ struct sigma_firmware ssfw;
+
+ ssfw.control_data = client;
+ ssfw.write = sigma_action_write_i2c;
+
+ return _process_sigma_firmware(&client->dev, &ssfw, name);
+}
+EXPORT_SYMBOL(process_sigma_firmware);
+
+#endif
+
+#if IS_ENABLED(CONFIG_REGMAP)
+
+static int sigma_action_write_regmap(void *control_data,
+ const struct sigma_action *sa, size_t len)
+{
+ return regmap_raw_write(control_data, le16_to_cpu(sa->addr),
+ sa->payload, len - 2);
+}
+
+int process_sigma_firmware_regmap(struct device *dev, struct regmap *regmap,
+ const char *name)
+{
+ struct sigma_firmware ssfw;
+
+ ssfw.control_data = regmap;
+ ssfw.write = sigma_action_write_regmap;
+
+ return _process_sigma_firmware(dev, &ssfw, name);
+}
+EXPORT_SYMBOL(process_sigma_firmware_regmap);
+
+#endif
+
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/sigmadsp.h b/sound/soc/codecs/sigmadsp.h
new file mode 100644
index 000000000000..e439cbd7af7d
--- /dev/null
+++ b/sound/soc/codecs/sigmadsp.h
@@ -0,0 +1,21 @@
+/*
+ * Load firmware files from Analog Devices SigmaStudio
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#ifndef __SIGMA_FIRMWARE_H__
+#define __SIGMA_FIRMWARE_H__
+
+#include <linux/device.h>
+#include <linux/regmap.h>
+
+struct i2c_client;
+
+extern int process_sigma_firmware(struct i2c_client *client, const char *name);
+extern int process_sigma_firmware_regmap(struct device *dev,
+ struct regmap *regmap, const char *name);
+
+#endif
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c
index 84ffdebb8a8b..50dbdb9357ea 100644
--- a/sound/soc/codecs/sn95031.c
+++ b/sound/soc/codecs/sn95031.c
@@ -28,6 +28,7 @@
#include <linux/platform_device.h>
#include <linux/delay.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <asm/intel_scu_ipc.h>
#include <sound/pcm.h>
@@ -79,7 +80,7 @@ static void configure_adc(struct snd_soc_codec *sn95031_codec, int val)
*/
static int find_free_channel(struct snd_soc_codec *sn95031_codec)
{
- int ret = 0, i, value;
+ int i, value;
/* check whether ADC is enabled */
value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1);
@@ -91,12 +92,10 @@ static int find_free_channel(struct snd_soc_codec *sn95031_codec)
for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) {
value = snd_soc_read(sn95031_codec,
SN95031_ADC_CHNL_START_ADDR + i);
- if (value & SN95031_STOPBIT_MASK) {
- ret = i;
+ if (value & SN95031_STOPBIT_MASK)
break;
- }
}
- return (ret > SN95031_ADC_LOOP_MAX) ? (-EINVAL) : ret;
+ return (i == SN95031_ADC_CHANLS_MAX) ? (-EINVAL) : i;
}
/* Initialize the ADC for reading micbias values. Can sleep. */
@@ -104,7 +103,7 @@ static int sn95031_initialize_adc(struct snd_soc_codec *sn95031_codec)
{
int base_addr, chnl_addr;
int value;
- static int channel_index;
+ int channel_index;
/* Index of the first channel in which the stop bit is set */
channel_index = find_free_channel(sn95031_codec);
@@ -163,7 +162,6 @@ static unsigned int sn95031_get_mic_bias(struct snd_soc_codec *codec)
pr_debug("mic bias = %dmV\n", mic_bias);
return mic_bias;
}
-EXPORT_SYMBOL_GPL(sn95031_get_mic_bias);
/*end - adc helper functions */
static inline unsigned int sn95031_read(struct snd_soc_codec *codec,
@@ -660,7 +658,7 @@ static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute)
return 0;
}
-int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
+static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
{
unsigned int format, rate;
@@ -700,25 +698,25 @@ int sn95031_pcm_hw_params(struct snd_pcm_substream *substream,
}
/* Codec DAI section */
-static struct snd_soc_dai_ops sn95031_headset_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_headset_dai_ops = {
.digital_mute = sn95031_pcm_hs_mute,
.hw_params = sn95031_pcm_hw_params,
};
-static struct snd_soc_dai_ops sn95031_speaker_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_speaker_dai_ops = {
.digital_mute = sn95031_pcm_spkr_mute,
.hw_params = sn95031_pcm_hw_params,
};
-static struct snd_soc_dai_ops sn95031_vib1_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_vib1_dai_ops = {
.hw_params = sn95031_pcm_hw_params,
};
-static struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
+static const struct snd_soc_dai_ops sn95031_vib2_dai_ops = {
.hw_params = sn95031_pcm_hw_params,
};
-struct snd_soc_dai_driver sn95031_dais[] = {
+static struct snd_soc_dai_driver sn95031_dais[] = {
{
.name = "SN95031 Headset",
.playback = {
@@ -829,9 +827,6 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
{
pr_debug("codec_probe called\n");
- codec->dapm.bias_level = SND_SOC_BIAS_OFF;
- codec->dapm.idle_bias_off = 1;
-
/* PCM interface config
* This sets the pcm rx slot conguration to max 6 slots
* for max 4 dais (2 stereo and 2 mono)
@@ -874,7 +869,7 @@ static int sn95031_codec_probe(struct snd_soc_codec *codec)
snd_soc_write(codec, SN95031_SSR2, 0x10);
snd_soc_write(codec, SN95031_SSR3, 0x40);
- snd_soc_add_controls(codec, sn95031_snd_controls,
+ snd_soc_add_codec_controls(codec, sn95031_snd_controls,
ARRAY_SIZE(sn95031_snd_controls));
return 0;
@@ -894,6 +889,7 @@ struct snd_soc_codec_driver sn95031_codec = {
.read = sn95031_read,
.write = sn95031_write,
.set_bias_level = sn95031_set_vaud_bias,
+ .idle_bias_off = true,
.dapm_widgets = sn95031_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(sn95031_dapm_widgets),
.dapm_routes = sn95031_audio_map,
@@ -923,19 +919,7 @@ static struct platform_driver sn95031_codec_driver = {
.remove = __devexit_p(sn95031_device_remove),
};
-static int __init sn95031_init(void)
-{
- pr_debug("driver init called\n");
- return platform_driver_register(&sn95031_codec_driver);
-}
-module_init(sn95031_init);
-
-static void __exit sn95031_exit(void)
-{
- pr_debug("driver exit called\n");
- platform_driver_unregister(&sn95031_codec_driver);
-}
-module_exit(sn95031_exit);
+module_platform_driver(sn95031_codec_driver);
MODULE_DESCRIPTION("ASoC TI SN95031 codec driver");
MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
diff --git a/sound/soc/codecs/spdif_transciever.c b/sound/soc/codecs/spdif_transciever.c
index 6a1a7e705cd7..112a49d66e39 100644
--- a/sound/soc/codecs/spdif_transciever.c
+++ b/sound/soc/codecs/spdif_transciever.c
@@ -61,18 +61,7 @@ static struct platform_driver spdif_dit_driver = {
},
};
-static int __init dit_modinit(void)
-{
- return platform_driver_register(&spdif_dit_driver);
-}
-
-static void __exit dit_exit(void)
-{
- platform_driver_unregister(&spdif_dit_driver);
-}
-
-module_init(dit_modinit);
-module_exit(dit_exit);
+module_platform_driver(spdif_dit_driver);
MODULE_AUTHOR("Steve Chen <schen@mvista.com>");
MODULE_DESCRIPTION("SPDIF dummy codec driver");
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 84f4ad568556..de2b20544ceb 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -33,7 +33,6 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -59,6 +58,7 @@ struct ssm2602_priv {
struct snd_pcm_substream *slave_substream;
enum ssm2602_type type;
+ unsigned int clk_out_pwr;
};
/*
@@ -294,7 +294,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->codec;
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
- struct i2c_client *i2c = codec->control_data;
struct snd_pcm_runtime *master_runtime;
/* The DAI has shared clocks so if we already have a playback or
@@ -303,7 +302,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
*/
if (ssm2602->master_substream) {
master_runtime = ssm2602->master_substream->runtime;
- dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n",
+ dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n",
master_runtime->sample_bits,
master_runtime->rate);
@@ -343,12 +342,14 @@ static void ssm2602_shutdown(struct snd_pcm_substream *substream,
static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- u16 mute_reg = snd_soc_read(codec, SSM2602_APDIGI) & ~APDIGI_ENABLE_DAC_MUTE;
+
if (mute)
- snd_soc_write(codec, SSM2602_APDIGI,
- mute_reg | APDIGI_ENABLE_DAC_MUTE);
+ snd_soc_update_bits(codec, SSM2602_APDIGI,
+ APDIGI_ENABLE_DAC_MUTE,
+ APDIGI_ENABLE_DAC_MUTE);
else
- snd_soc_write(codec, SSM2602_APDIGI, mute_reg);
+ snd_soc_update_bits(codec, SSM2602_APDIGI,
+ APDIGI_ENABLE_DAC_MUTE, 0);
return 0;
}
@@ -357,16 +358,46 @@ static int ssm2602_set_dai_sysclk(struct snd_soc_dai *codec_dai,
{
struct snd_soc_codec *codec = codec_dai->codec;
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
- switch (freq) {
- case 11289600:
- case 12000000:
- case 12288000:
- case 16934400:
- case 18432000:
- ssm2602->sysclk = freq;
- return 0;
+
+ if (dir == SND_SOC_CLOCK_IN) {
+ if (clk_id != SSM2602_SYSCLK)
+ return -EINVAL;
+
+ switch (freq) {
+ case 11289600:
+ case 12000000:
+ case 12288000:
+ case 16934400:
+ case 18432000:
+ ssm2602->sysclk = freq;
+ break;
+ default:
+ return -EINVAL;
+ }
+ } else {
+ unsigned int mask;
+
+ switch (clk_id) {
+ case SSM2602_CLK_CLKOUT:
+ mask = PWR_CLK_OUT_PDN;
+ break;
+ case SSM2602_CLK_XTO:
+ mask = PWR_OSC_PDN;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (freq == 0)
+ ssm2602->clk_out_pwr |= mask;
+ else
+ ssm2602->clk_out_pwr &= ~mask;
+
+ snd_soc_update_bits(codec, SSM2602_PWR,
+ PWR_CLK_OUT_PDN | PWR_OSC_PDN, ssm2602->clk_out_pwr);
}
- return -EINVAL;
+
+ return 0;
}
static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
@@ -431,22 +462,27 @@ static int ssm2602_set_dai_fmt(struct snd_soc_dai *codec_dai,
static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 reg = snd_soc_read(codec, SSM2602_PWR) & 0xff7f;
+ struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
switch (level) {
case SND_SOC_BIAS_ON:
- /* vref/mid, osc on, dac unmute */
- snd_soc_write(codec, SSM2602_PWR, reg);
+ /* vref/mid on, osc and clkout on if enabled */
+ snd_soc_update_bits(codec, SSM2602_PWR,
+ PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
+ ssm2602->clk_out_pwr);
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
/* everything off except vref/vmid, */
- snd_soc_write(codec, SSM2602_PWR, reg | PWR_CLK_OUT_PDN);
+ snd_soc_update_bits(codec, SSM2602_PWR,
+ PWR_POWER_OFF | PWR_CLK_OUT_PDN | PWR_OSC_PDN,
+ PWR_CLK_OUT_PDN | PWR_OSC_PDN);
break;
case SND_SOC_BIAS_OFF:
- /* everything off, dac mute, inactive */
- snd_soc_write(codec, SSM2602_PWR, 0xffff);
+ /* everything off */
+ snd_soc_update_bits(codec, SSM2602_PWR,
+ PWR_POWER_OFF, PWR_POWER_OFF);
break;
}
@@ -461,7 +497,7 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops ssm2602_dai_ops = {
+static const struct snd_soc_dai_ops ssm2602_dai_ops = {
.startup = ssm2602_startup,
.hw_params = ssm2602_hw_params,
.shutdown = ssm2602_shutdown,
@@ -487,7 +523,7 @@ static struct snd_soc_dai_driver ssm2602_dai = {
.ops = &ssm2602_dai_ops,
};
-static int ssm2602_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int ssm2602_suspend(struct snd_soc_codec *codec)
{
ssm2602_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -505,14 +541,14 @@ static int ssm2602_resume(struct snd_soc_codec *codec)
static int ssm2602_probe(struct snd_soc_codec *codec)
{
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret, reg;
+ int ret;
- reg = snd_soc_read(codec, SSM2602_LOUT1V);
- snd_soc_write(codec, SSM2602_LOUT1V, reg | LOUT1V_LRHP_BOTH);
- reg = snd_soc_read(codec, SSM2602_ROUT1V);
- snd_soc_write(codec, SSM2602_ROUT1V, reg | ROUT1V_RLHP_BOTH);
+ snd_soc_update_bits(codec, SSM2602_LOUT1V,
+ LOUT1V_LRHP_BOTH, LOUT1V_LRHP_BOTH);
+ snd_soc_update_bits(codec, SSM2602_ROUT1V,
+ ROUT1V_RLHP_BOTH, ROUT1V_RLHP_BOTH);
- ret = snd_soc_add_controls(codec, ssm2602_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, ssm2602_snd_controls,
ARRAY_SIZE(ssm2602_snd_controls));
if (ret)
return ret;
@@ -543,7 +579,7 @@ static int ssm2604_probe(struct snd_soc_codec *codec)
static int ssm260x_probe(struct snd_soc_codec *codec)
{
struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec);
- int ret, reg;
+ int ret;
pr_info("ssm2602 Audio Codec %s", SSM2602_VERSION);
@@ -560,10 +596,10 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
}
/* set the update bits */
- reg = snd_soc_read(codec, SSM2602_LINVOL);
- snd_soc_write(codec, SSM2602_LINVOL, reg | LINVOL_LRIN_BOTH);
- reg = snd_soc_read(codec, SSM2602_RINVOL);
- snd_soc_write(codec, SSM2602_RINVOL, reg | RINVOL_RLIN_BOTH);
+ snd_soc_update_bits(codec, SSM2602_LINVOL,
+ LINVOL_LRIN_BOTH, LINVOL_LRIN_BOTH);
+ snd_soc_update_bits(codec, SSM2602_RINVOL,
+ RINVOL_RLIN_BOTH, RINVOL_RLIN_BOTH);
/*select Line in as default input*/
snd_soc_write(codec, SSM2602_APANA, APANA_SELECT_DAC |
APANA_ENABLE_MIC_BOOST);
@@ -577,7 +613,12 @@ static int ssm260x_probe(struct snd_soc_codec *codec)
break;
}
- return ret;
+ if (ret)
+ return ret;
+
+ ssm2602_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+
+ return 0;
}
/* remove everything here */
@@ -611,7 +652,8 @@ static int __devinit ssm2602_spi_probe(struct spi_device *spi)
struct ssm2602_priv *ssm2602;
int ret;
- ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
+ ssm2602 = devm_kzalloc(&spi->dev, sizeof(struct ssm2602_priv),
+ GFP_KERNEL);
if (ssm2602 == NULL)
return -ENOMEM;
@@ -621,15 +663,12 @@ static int __devinit ssm2602_spi_probe(struct spi_device *spi)
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_ssm2602, &ssm2602_dai, 1);
- if (ret < 0)
- kfree(ssm2602);
return ret;
}
static int __devexit ssm2602_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
return 0;
}
@@ -656,7 +695,8 @@ static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
struct ssm2602_priv *ssm2602;
int ret;
- ssm2602 = kzalloc(sizeof(struct ssm2602_priv), GFP_KERNEL);
+ ssm2602 = devm_kzalloc(&i2c->dev, sizeof(struct ssm2602_priv),
+ GFP_KERNEL);
if (ssm2602 == NULL)
return -ENOMEM;
@@ -666,15 +706,12 @@ static int __devinit ssm2602_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_ssm2602, &ssm2602_dai, 1);
- if (ret < 0)
- kfree(ssm2602);
return ret;
}
static int __devexit ssm2602_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/sound/soc/codecs/ssm2602.h b/sound/soc/codecs/ssm2602.h
index b98c69168036..fbd07d7b73ca 100644
--- a/sound/soc/codecs/ssm2602.h
+++ b/sound/soc/codecs/ssm2602.h
@@ -116,6 +116,10 @@
#define SSM2602_CACHEREGNUM 10
-#define SSM2602_SYSCLK 0
+enum ssm2602_clk {
+ SSM2602_SYSCLK,
+ SSM2602_CLK_CLKOUT,
+ SSM2602_CLK_XTO
+};
#endif
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c
index fbd7eb9e61ce..7db6fa515028 100644
--- a/sound/soc/codecs/sta32x.c
+++ b/sound/soc/codecs/sta32x.c
@@ -24,9 +24,9 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+#include <linux/workqueue.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -35,6 +35,7 @@
#include <sound/initval.h>
#include <sound/tlv.h>
+#include <sound/sta32x.h>
#include "sta32x.h"
#define STA32X_RATES (SNDRV_PCM_RATE_32000 | \
@@ -73,9 +74,14 @@ static const char *sta32x_supply_names[] = {
struct sta32x_priv {
struct regulator_bulk_data supplies[ARRAY_SIZE(sta32x_supply_names)];
struct snd_soc_codec *codec;
+ struct sta32x_platform_data *pdata;
unsigned int mclk;
unsigned int format;
+
+ u32 coef_shadow[STA32X_COEF_COUNT];
+ struct delayed_work watchdog_work;
+ int shutdown;
};
static const DECLARE_TLV_DB_SCALE(mvol_tlv, -12700, 50, 1);
@@ -227,6 +233,7 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
int numcoef = kcontrol->private_value >> 16;
int index = kcontrol->private_value & 0xffff;
unsigned int cfud;
@@ -239,6 +246,11 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
snd_soc_write(codec, STA32X_CFUD, cfud);
snd_soc_write(codec, STA32X_CFADDR2, index);
+ for (i = 0; i < numcoef && (index + i < STA32X_COEF_COUNT); i++)
+ sta32x->coef_shadow[index + i] =
+ (ucontrol->value.bytes.data[3 * i] << 16)
+ | (ucontrol->value.bytes.data[3 * i + 1] << 8)
+ | (ucontrol->value.bytes.data[3 * i + 2]);
for (i = 0; i < 3 * numcoef; i++)
snd_soc_write(codec, STA32X_B1CF1 + i,
ucontrol->value.bytes.data[i]);
@@ -252,6 +264,88 @@ static int sta32x_coefficient_put(struct snd_kcontrol *kcontrol,
return 0;
}
+static int sta32x_sync_coef_shadow(struct snd_soc_codec *codec)
+{
+ struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+ unsigned int cfud;
+ int i;
+
+ /* preserve reserved bits in STA32X_CFUD */
+ cfud = snd_soc_read(codec, STA32X_CFUD) & 0xf0;
+
+ for (i = 0; i < STA32X_COEF_COUNT; i++) {
+ snd_soc_write(codec, STA32X_CFADDR2, i);
+ snd_soc_write(codec, STA32X_B1CF1,
+ (sta32x->coef_shadow[i] >> 16) & 0xff);
+ snd_soc_write(codec, STA32X_B1CF2,
+ (sta32x->coef_shadow[i] >> 8) & 0xff);
+ snd_soc_write(codec, STA32X_B1CF3,
+ (sta32x->coef_shadow[i]) & 0xff);
+ /* chip documentation does not say if the bits are
+ * self-clearing, so do it explicitly */
+ snd_soc_write(codec, STA32X_CFUD, cfud);
+ snd_soc_write(codec, STA32X_CFUD, cfud | 0x01);
+ }
+ return 0;
+}
+
+static int sta32x_cache_sync(struct snd_soc_codec *codec)
+{
+ unsigned int mute;
+ int rc;
+
+ if (!codec->cache_sync)
+ return 0;
+
+ /* mute during register sync */
+ mute = snd_soc_read(codec, STA32X_MMUTE);
+ snd_soc_write(codec, STA32X_MMUTE, mute | STA32X_MMUTE_MMUTE);
+ sta32x_sync_coef_shadow(codec);
+ rc = snd_soc_cache_sync(codec);
+ snd_soc_write(codec, STA32X_MMUTE, mute);
+ return rc;
+}
+
+/* work around ESD issue where sta32x resets and loses all configuration */
+static void sta32x_watchdog(struct work_struct *work)
+{
+ struct sta32x_priv *sta32x = container_of(work, struct sta32x_priv,
+ watchdog_work.work);
+ struct snd_soc_codec *codec = sta32x->codec;
+ unsigned int confa, confa_cached;
+
+ /* check if sta32x has reset itself */
+ confa_cached = snd_soc_read(codec, STA32X_CONFA);
+ codec->cache_bypass = 1;
+ confa = snd_soc_read(codec, STA32X_CONFA);
+ codec->cache_bypass = 0;
+ if (confa != confa_cached) {
+ codec->cache_sync = 1;
+ sta32x_cache_sync(codec);
+ }
+
+ if (!sta32x->shutdown)
+ schedule_delayed_work(&sta32x->watchdog_work,
+ round_jiffies_relative(HZ));
+}
+
+static void sta32x_watchdog_start(struct sta32x_priv *sta32x)
+{
+ if (sta32x->pdata->needs_esd_watchdog) {
+ sta32x->shutdown = 0;
+ schedule_delayed_work(&sta32x->watchdog_work,
+ round_jiffies_relative(HZ));
+ }
+}
+
+static void sta32x_watchdog_stop(struct sta32x_priv *sta32x)
+{
+ if (sta32x->pdata->needs_esd_watchdog) {
+ sta32x->shutdown = 1;
+ cancel_delayed_work_sync(&sta32x->watchdog_work);
+ }
+}
+
#define SINGLE_COEF(xname, index) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = sta32x_coefficient_info, \
@@ -428,6 +522,7 @@ static int sta32x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
rate_min = fs;
if (fs > rate_max)
rate_max = fs;
+ break;
}
}
}
@@ -524,13 +619,17 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream,
rate = params_rate(params);
pr_debug("rate: %u\n", rate);
for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++)
- if (interpolation_ratios[i].fs == rate)
+ if (interpolation_ratios[i].fs == rate) {
ir = interpolation_ratios[i].ir;
+ break;
+ }
if (ir < 0)
return -EINVAL;
for (i = 0; mclk_ratios[ir][i].ratio; i++)
- if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk)
+ if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) {
mcs = mclk_ratios[ir][i].mcs;
+ break;
+ }
if (mcs < 0)
return -EINVAL;
@@ -657,7 +756,8 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
- snd_soc_cache_sync(codec);
+ sta32x_cache_sync(codec);
+ sta32x_watchdog_start(sta32x);
}
/* Power up to mute */
@@ -674,7 +774,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
STA32X_CONFF_PWDN | STA32X_CONFF_EAPD,
STA32X_CONFF_PWDN);
msleep(300);
-
+ sta32x_watchdog_stop(sta32x);
regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies),
sta32x->supplies);
break;
@@ -683,7 +783,7 @@ static int sta32x_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static struct snd_soc_dai_ops sta32x_dai_ops = {
+static const struct snd_soc_dai_ops sta32x_dai_ops = {
.hw_params = sta32x_hw_params,
.set_sysclk = sta32x_set_dai_sysclk,
.set_fmt = sta32x_set_dai_fmt,
@@ -702,7 +802,7 @@ static struct snd_soc_dai_driver sta32x_dai = {
};
#ifdef CONFIG_PM
-static int sta32x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int sta32x_suspend(struct snd_soc_codec *codec)
{
sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -721,9 +821,10 @@ static int sta32x_resume(struct snd_soc_codec *codec)
static int sta32x_probe(struct snd_soc_codec *codec)
{
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
- int i, ret = 0;
+ int i, ret = 0, thermal = 0;
sta32x->codec = codec;
+ sta32x->pdata = dev_get_platdata(codec->dev);
/* regulators */
for (i = 0; i < ARRAY_SIZE(sta32x->supplies); i++)
@@ -752,45 +853,62 @@ static int sta32x_probe(struct snd_soc_codec *codec)
return ret;
}
- /* read reg reset values into cache */
- for (i = 0; i < STA32X_REGISTER_COUNT; i++)
- snd_soc_cache_write(codec, i, sta32x_regs[i]);
-
- /* preserve reset values of reserved register bits */
- snd_soc_cache_write(codec, STA32X_CONFC,
- codec->hw_read(codec, STA32X_CONFC));
- snd_soc_cache_write(codec, STA32X_CONFE,
- codec->hw_read(codec, STA32X_CONFE));
- snd_soc_cache_write(codec, STA32X_CONFF,
- codec->hw_read(codec, STA32X_CONFF));
- snd_soc_cache_write(codec, STA32X_MMUTE,
- codec->hw_read(codec, STA32X_MMUTE));
- snd_soc_cache_write(codec, STA32X_AUTO1,
- codec->hw_read(codec, STA32X_AUTO1));
- snd_soc_cache_write(codec, STA32X_AUTO3,
- codec->hw_read(codec, STA32X_AUTO3));
- snd_soc_cache_write(codec, STA32X_C3CFG,
- codec->hw_read(codec, STA32X_C3CFG));
-
- /* FIXME enable thermal warning adjustment and recovery */
+ /* Chip documentation explicitly requires that the reset values
+ * of reserved register bits are left untouched.
+ * Write the register default value to cache for reserved registers,
+ * so the write to the these registers are suppressed by the cache
+ * restore code when it skips writes of default registers.
+ */
+ snd_soc_cache_write(codec, STA32X_CONFC, 0xc2);
+ snd_soc_cache_write(codec, STA32X_CONFE, 0xc2);
+ snd_soc_cache_write(codec, STA32X_CONFF, 0x5c);
+ snd_soc_cache_write(codec, STA32X_MMUTE, 0x10);
+ snd_soc_cache_write(codec, STA32X_AUTO1, 0x60);
+ snd_soc_cache_write(codec, STA32X_AUTO3, 0x00);
+ snd_soc_cache_write(codec, STA32X_C3CFG, 0x40);
+
+ /* set thermal warning adjustment and recovery */
+ if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_ADJUSTMENT_ENABLE))
+ thermal |= STA32X_CONFA_TWAB;
+ if (!(sta32x->pdata->thermal_conf & STA32X_THERMAL_RECOVERY_ENABLE))
+ thermal |= STA32X_CONFA_TWRB;
snd_soc_update_bits(codec, STA32X_CONFA,
- STA32X_CONFA_TWAB | STA32X_CONFA_TWRB, 0);
+ STA32X_CONFA_TWAB | STA32X_CONFA_TWRB,
+ thermal);
- /* FIXME select 2.1 mode */
+ /* select output configuration */
snd_soc_update_bits(codec, STA32X_CONFF,
STA32X_CONFF_OCFG_MASK,
- 1 << STA32X_CONFF_OCFG_SHIFT);
+ sta32x->pdata->output_conf
+ << STA32X_CONFF_OCFG_SHIFT);
- /* FIXME channel to output mapping */
+ /* channel to output mapping */
snd_soc_update_bits(codec, STA32X_C1CFG,
STA32X_CxCFG_OM_MASK,
- 0 << STA32X_CxCFG_OM_SHIFT);
+ sta32x->pdata->ch1_output_mapping
+ << STA32X_CxCFG_OM_SHIFT);
snd_soc_update_bits(codec, STA32X_C2CFG,
STA32X_CxCFG_OM_MASK,
- 1 << STA32X_CxCFG_OM_SHIFT);
+ sta32x->pdata->ch2_output_mapping
+ << STA32X_CxCFG_OM_SHIFT);
snd_soc_update_bits(codec, STA32X_C3CFG,
STA32X_CxCFG_OM_MASK,
- 2 << STA32X_CxCFG_OM_SHIFT);
+ sta32x->pdata->ch3_output_mapping
+ << STA32X_CxCFG_OM_SHIFT);
+
+ /* initialize coefficient shadow RAM with reset values */
+ for (i = 4; i <= 49; i += 5)
+ sta32x->coef_shadow[i] = 0x400000;
+ for (i = 50; i <= 54; i++)
+ sta32x->coef_shadow[i] = 0x7fffff;
+ sta32x->coef_shadow[55] = 0x5a9df7;
+ sta32x->coef_shadow[56] = 0x7fffff;
+ sta32x->coef_shadow[59] = 0x7fffff;
+ sta32x->coef_shadow[60] = 0x400000;
+ sta32x->coef_shadow[61] = 0x400000;
+
+ if (sta32x->pdata->needs_esd_watchdog)
+ INIT_DELAYED_WORK(&sta32x->watchdog_work, sta32x_watchdog);
sta32x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Bias level configuration will have done an extra enable */
@@ -808,6 +926,8 @@ static int sta32x_remove(struct snd_soc_codec *codec)
{
struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec);
+ sta32x_watchdog_stop(sta32x);
+ sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
@@ -832,6 +952,7 @@ static const struct snd_soc_codec_driver sta32x_codec = {
.resume = sta32x_resume,
.reg_cache_size = STA32X_REGISTER_COUNT,
.reg_word_size = sizeof(u8),
+ .reg_cache_default = sta32x_regs,
.volatile_register = sta32x_reg_is_volatile,
.set_bias_level = sta32x_set_bias_level,
.controls = sta32x_snd_controls,
@@ -848,38 +969,23 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c,
struct sta32x_priv *sta32x;
int ret;
- sta32x = kzalloc(sizeof(struct sta32x_priv), GFP_KERNEL);
+ sta32x = devm_kzalloc(&i2c->dev, sizeof(struct sta32x_priv),
+ GFP_KERNEL);
if (!sta32x)
return -ENOMEM;
i2c_set_clientdata(i2c, sta32x);
ret = snd_soc_register_codec(&i2c->dev, &sta32x_codec, &sta32x_dai, 1);
- if (ret != 0) {
+ if (ret != 0)
dev_err(&i2c->dev, "Failed to register codec (%d)\n", ret);
- kfree(sta32x);
- return ret;
- }
- return 0;
+ return ret;
}
static __devexit int sta32x_i2c_remove(struct i2c_client *client)
{
- struct sta32x_priv *sta32x = i2c_get_clientdata(client);
- struct snd_soc_codec *codec = sta32x->codec;
-
- if (codec)
- sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies);
-
- if (codec) {
- snd_soc_unregister_codec(&client->dev);
- snd_soc_codec_set_drvdata(codec, NULL);
- }
-
- kfree(sta32x);
+ snd_soc_unregister_codec(&client->dev);
return 0;
}
diff --git a/sound/soc/codecs/sta32x.h b/sound/soc/codecs/sta32x.h
index b97ee5a75667..d8e32a6262ee 100644
--- a/sound/soc/codecs/sta32x.h
+++ b/sound/soc/codecs/sta32x.h
@@ -19,6 +19,7 @@
/* STA326 register addresses */
#define STA32X_REGISTER_COUNT 0x2d
+#define STA32X_COEF_COUNT 62
#define STA32X_CONFA 0x00
#define STA32X_CONFB 0x01
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c
index 78b2b50271e2..982e437799a8 100644
--- a/sound/soc/codecs/stac9766.c
+++ b/sound/soc/codecs/stac9766.c
@@ -256,8 +256,7 @@ static int stac9766_reset(struct snd_soc_codec *codec, int try_warm)
return 0;
}
-static int stac9766_codec_suspend(struct snd_soc_codec *codec,
- pm_message_t state)
+static int stac9766_codec_suspend(struct snd_soc_codec *codec)
{
stac9766_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -286,11 +285,11 @@ reset:
return 0;
}
-static struct snd_soc_dai_ops stac9766_dai_ops_analog = {
+static const struct snd_soc_dai_ops stac9766_dai_ops_analog = {
.prepare = ac97_analog_prepare,
};
-static struct snd_soc_dai_ops stac9766_dai_ops_digital = {
+static const struct snd_soc_dai_ops stac9766_dai_ops_digital = {
.prepare = ac97_digital_prepare,
};
@@ -356,7 +355,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec)
stac9766_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, stac9766_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, stac9766_snd_ac97_controls,
ARRAY_SIZE(stac9766_snd_ac97_controls));
return 0;
@@ -380,7 +379,7 @@ static struct snd_soc_codec_driver soc_codec_dev_stac9766 = {
.remove = stac9766_codec_remove,
.suspend = stac9766_codec_suspend,
.resume = stac9766_codec_resume,
- .reg_cache_size = sizeof(stac9766_reg),
+ .reg_cache_size = ARRAY_SIZE(stac9766_reg),
.reg_word_size = sizeof(u16),
.reg_cache_step = 2,
.reg_cache_default = stac9766_reg,
@@ -408,17 +407,7 @@ static struct platform_driver stac9766_codec_driver = {
.remove = __devexit_p(stac9766_remove),
};
-static int __init stac9766_init(void)
-{
- return platform_driver_register(&stac9766_codec_driver);
-}
-module_init(stac9766_init);
-
-static void __exit stac9766_exit(void)
-{
- platform_driver_unregister(&stac9766_codec_driver);
-}
-module_exit(stac9766_exit);
+module_platform_driver(stac9766_codec_driver);
MODULE_DESCRIPTION("ASoC stac9766 driver");
MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index 33bb52f3f683..16d55f91a653 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -24,7 +24,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -47,63 +46,6 @@ static const u16 tlv320aic23_reg[] = {
0x0000, 0x0000, 0x0000, 0x0000, /* 12 */
};
-/*
- * read tlv320aic23 register cache
- */
-static inline unsigned int tlv320aic23_read_reg_cache(struct snd_soc_codec
- *codec, unsigned int reg)
-{
- u16 *cache = codec->reg_cache;
- if (reg >= ARRAY_SIZE(tlv320aic23_reg))
- return -1;
- return cache[reg];
-}
-
-/*
- * write tlv320aic23 register cache
- */
-static inline void tlv320aic23_write_reg_cache(struct snd_soc_codec *codec,
- u8 reg, u16 value)
-{
- u16 *cache = codec->reg_cache;
- if (reg >= ARRAY_SIZE(tlv320aic23_reg))
- return;
- cache[reg] = value;
-}
-
-/*
- * write to the tlv320aic23 register space
- */
-static int tlv320aic23_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
-
- u8 data[2];
-
- /* TLV320AIC23 has 7 bit address and 9 bits of data
- * so we need to switch one data bit into reg and rest
- * of data into val
- */
-
- if (reg > 9 && reg != 15) {
- printk(KERN_WARNING "%s Invalid register R%u\n", __func__, reg);
- return -1;
- }
-
- data[0] = (reg << 1) | (value >> 8 & 0x01);
- data[1] = value & 0xff;
-
- tlv320aic23_write_reg_cache(codec, reg, value);
-
- if (codec->hw_write(codec->control_data, data, 2) == 2)
- return 0;
-
- printk(KERN_ERR "%s cannot write %03x to register R%u\n", __func__,
- value, reg);
-
- return -EIO;
-}
-
static const char *rec_src_text[] = { "Line", "Mic" };
static const char *deemph_text[] = {"None", "32Khz", "44.1Khz", "48Khz"};
@@ -139,8 +81,8 @@ static int snd_soc_tlv320aic23_put_volsw(struct snd_kcontrol *kcontrol,
*/
val = (val >= 4) ? 4 : (3 - val);
- reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (~0x1C0);
- tlv320aic23_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
+ reg = snd_soc_read(codec, TLV320AIC23_ANLG) & (~0x1C0);
+ snd_soc_write(codec, TLV320AIC23_ANLG, reg | (val << 6));
return 0;
}
@@ -151,7 +93,7 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
u16 val;
- val = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG) & (0x1C0);
+ val = snd_soc_read(codec, TLV320AIC23_ANLG) & (0x1C0);
val = val >> 6;
val = (val >= 4) ? 4 : (3 - val);
ucontrol->value.integer.value[0] = val;
@@ -159,15 +101,6 @@ static int snd_soc_tlv320aic23_get_volsw(struct snd_kcontrol *kcontrol,
}
-#define SOC_TLV320AIC23_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE,\
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, .get = snd_soc_tlv320aic23_get_volsw,\
- .put = snd_soc_tlv320aic23_put_volsw, \
- .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) }
-
static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
SOC_DOUBLE_R_TLV("Digital Playback Volume", TLV320AIC23_LCHNVOL,
TLV320AIC23_RCHNVOL, 0, 127, 0, out_gain_tlv),
@@ -178,8 +111,9 @@ static const struct snd_kcontrol_new tlv320aic23_snd_controls[] = {
TLV320AIC23_RINVOL, 0, 31, 0, input_gain_tlv),
SOC_SINGLE("Mic Input Switch", TLV320AIC23_ANLG, 1, 1, 1),
SOC_SINGLE("Mic Booster Switch", TLV320AIC23_ANLG, 0, 1, 0),
- SOC_TLV320AIC23_SINGLE_TLV("Sidetone Volume", TLV320AIC23_ANLG,
- 6, 4, 0, sidetone_vol_tlv),
+ SOC_SINGLE_EXT_TLV("Sidetone Volume", TLV320AIC23_ANLG, 6, 4, 0,
+ snd_soc_tlv320aic23_get_volsw,
+ snd_soc_tlv320aic23_put_volsw, sidetone_vol_tlv),
SOC_ENUM("Playback De-emphasis", tlv320aic23_deemph),
};
@@ -240,7 +174,6 @@ static const struct snd_soc_dapm_route tlv320aic23_intercon[] = {
/* AIC23 driver data */
struct aic23 {
enum snd_soc_control_type control_type;
- void *control_data;
int mclk;
int requested_adc;
int requested_dac;
@@ -352,7 +285,7 @@ static int find_rate(int mclk, u32 need_adc, u32 need_dac)
static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
u32 *sample_rate_adc, u32 *sample_rate_dac)
{
- int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
+ int src = snd_soc_read(codec, TLV320AIC23_SRATE);
int sr = (src >> 2) & 0x0f;
int val = (mclk / bosr_usb_divisor_table[src & 3]);
int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
@@ -376,7 +309,7 @@ static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
__func__, sample_rate_adc, sample_rate_dac);
return -EINVAL;
}
- tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
+ snd_soc_write(codec, TLV320AIC23_SRATE, data);
#ifdef DEBUG
{
u32 adc, dac;
@@ -415,9 +348,8 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
- iface_reg =
- tlv320aic23_read_reg_cache(codec,
- TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+ iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
break;
@@ -431,7 +363,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
iface_reg |= (0x03 << 2);
break;
}
- tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+ snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
return 0;
}
@@ -443,7 +375,7 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
/* set active */
- tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0001);
+ snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0001);
return 0;
}
@@ -458,7 +390,7 @@ static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
/* deactivate */
if (!codec->active) {
udelay(50);
- tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
+ snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
}
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
aic23->requested_dac = 0;
@@ -471,14 +403,14 @@ static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
struct snd_soc_codec *codec = dai->codec;
u16 reg;
- reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT);
+ reg = snd_soc_read(codec, TLV320AIC23_DIGT);
if (mute)
reg |= TLV320AIC23_DACM_MUTE;
else
reg &= ~TLV320AIC23_DACM_MUTE;
- tlv320aic23_write(codec, TLV320AIC23_DIGT, reg);
+ snd_soc_write(codec, TLV320AIC23_DIGT, reg);
return 0;
}
@@ -489,8 +421,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
struct snd_soc_codec *codec = codec_dai->codec;
u16 iface_reg;
- iface_reg =
- tlv320aic23_read_reg_cache(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
+ iface_reg = snd_soc_read(codec, TLV320AIC23_DIGT_FMT) & (~0x03);
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -498,6 +429,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
iface_reg |= TLV320AIC23_MS_MASTER;
break;
case SND_SOC_DAIFMT_CBS_CFS:
+ iface_reg &= ~TLV320AIC23_MS_MASTER;
break;
default:
return -EINVAL;
@@ -524,7 +456,7 @@ static int tlv320aic23_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
- tlv320aic23_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
+ snd_soc_write(codec, TLV320AIC23_DIGT_FMT, iface_reg);
return 0;
}
@@ -540,26 +472,26 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_PWR) & 0xff7f;
+ u16 reg = snd_soc_read(codec, TLV320AIC23_PWR) & 0xff7f;
switch (level) {
case SND_SOC_BIAS_ON:
/* vref/mid, osc on, dac unmute */
reg &= ~(TLV320AIC23_DEVICE_PWR_OFF | TLV320AIC23_OSC_OFF | \
TLV320AIC23_DAC_OFF);
- tlv320aic23_write(codec, TLV320AIC23_PWR, reg);
+ snd_soc_write(codec, TLV320AIC23_PWR, reg);
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
/* everything off except vref/vmid, */
- tlv320aic23_write(codec, TLV320AIC23_PWR, reg | \
- TLV320AIC23_CLK_OFF);
+ snd_soc_write(codec, TLV320AIC23_PWR,
+ reg | TLV320AIC23_CLK_OFF);
break;
case SND_SOC_BIAS_OFF:
/* everything off, dac mute, inactive */
- tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
- tlv320aic23_write(codec, TLV320AIC23_PWR, 0xffff);
+ snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x0);
+ snd_soc_write(codec, TLV320AIC23_PWR, 0xffff);
break;
}
codec->dapm.bias_level = level;
@@ -570,7 +502,7 @@ static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
#define AIC23_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops tlv320aic23_dai_ops = {
+static const struct snd_soc_dai_ops tlv320aic23_dai_ops = {
.prepare = tlv320aic23_pcm_prepare,
.hw_params = tlv320aic23_hw_params,
.shutdown = tlv320aic23_shutdown,
@@ -596,8 +528,7 @@ static struct snd_soc_dai_driver tlv320aic23_dai = {
.ops = &tlv320aic23_dai_ops,
};
-static int tlv320aic23_suspend(struct snd_soc_codec *codec,
- pm_message_t state)
+static int tlv320aic23_suspend(struct snd_soc_codec *codec)
{
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -606,13 +537,7 @@ static int tlv320aic23_suspend(struct snd_soc_codec *codec,
static int tlv320aic23_resume(struct snd_soc_codec *codec)
{
- u16 reg;
-
- /* Sync reg_cache with the hardware */
- for (reg = 0; reg <= TLV320AIC23_ACTIVE; reg++) {
- u16 val = tlv320aic23_read_reg_cache(codec, reg);
- tlv320aic23_write(codec, reg, val);
- }
+ snd_soc_cache_sync(codec);
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -621,48 +546,54 @@ static int tlv320aic23_resume(struct snd_soc_codec *codec)
static int tlv320aic23_probe(struct snd_soc_codec *codec)
{
struct aic23 *aic23 = snd_soc_codec_get_drvdata(codec);
- int reg;
+ int ret;
printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
- codec->control_data = aic23->control_data;
- codec->hw_write = (hw_write_t)i2c_master_send;
- codec->hw_read = NULL;
+
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, aic23->control_type);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
/* Reset codec */
- tlv320aic23_write(codec, TLV320AIC23_RESET, 0);
+ snd_soc_write(codec, TLV320AIC23_RESET, 0);
+
+ /* Write the register default value to cache for reserved registers,
+ * so the write to the these registers are suppressed by the cache
+ * restore code when it skips writes of default registers.
+ */
+ snd_soc_cache_write(codec, 0x0A, 0);
+ snd_soc_cache_write(codec, 0x0B, 0);
+ snd_soc_cache_write(codec, 0x0C, 0);
+ snd_soc_cache_write(codec, 0x0D, 0);
+ snd_soc_cache_write(codec, 0x0E, 0);
/* power on device */
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- tlv320aic23_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
+ snd_soc_write(codec, TLV320AIC23_DIGT, TLV320AIC23_DEEMP_44K);
/* Unmute input */
- reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_LINVOL);
- tlv320aic23_write(codec, TLV320AIC23_LINVOL,
- (reg & (~TLV320AIC23_LIM_MUTED)) |
- (TLV320AIC23_LRS_ENABLED));
+ snd_soc_update_bits(codec, TLV320AIC23_LINVOL,
+ TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
- reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_RINVOL);
- tlv320aic23_write(codec, TLV320AIC23_RINVOL,
- (reg & (~TLV320AIC23_LIM_MUTED)) |
- TLV320AIC23_LRS_ENABLED);
+ snd_soc_update_bits(codec, TLV320AIC23_RINVOL,
+ TLV320AIC23_LIM_MUTED, TLV320AIC23_LRS_ENABLED);
- reg = tlv320aic23_read_reg_cache(codec, TLV320AIC23_ANLG);
- tlv320aic23_write(codec, TLV320AIC23_ANLG,
- (reg) & (~TLV320AIC23_BYPASS_ON) &
- (~TLV320AIC23_MICM_MUTED));
+ snd_soc_update_bits(codec, TLV320AIC23_ANLG,
+ TLV320AIC23_BYPASS_ON | TLV320AIC23_MICM_MUTED,
+ 0);
/* Default output volume */
- tlv320aic23_write(codec, TLV320AIC23_LCHNVOL,
- TLV320AIC23_DEFAULT_OUT_VOL &
- TLV320AIC23_OUT_VOL_MASK);
- tlv320aic23_write(codec, TLV320AIC23_RCHNVOL,
- TLV320AIC23_DEFAULT_OUT_VOL &
- TLV320AIC23_OUT_VOL_MASK);
+ snd_soc_write(codec, TLV320AIC23_LCHNVOL,
+ TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
+ snd_soc_write(codec, TLV320AIC23_RCHNVOL,
+ TLV320AIC23_DEFAULT_OUT_VOL & TLV320AIC23_OUT_VOL_MASK);
- tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x1);
+ snd_soc_write(codec, TLV320AIC23_ACTIVE, 0x1);
- snd_soc_add_controls(codec, tlv320aic23_snd_controls,
+ snd_soc_add_codec_controls(codec, tlv320aic23_snd_controls,
ARRAY_SIZE(tlv320aic23_snd_controls));
return 0;
@@ -682,8 +613,6 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320aic23 = {
.remove = tlv320aic23_remove,
.suspend = tlv320aic23_suspend,
.resume = tlv320aic23_resume,
- .read = tlv320aic23_read_reg_cache,
- .write = tlv320aic23_write,
.set_bias_level = tlv320aic23_set_bias_level,
.dapm_widgets = tlv320aic23_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
@@ -705,24 +634,20 @@ static int tlv320aic23_codec_probe(struct i2c_client *i2c,
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EINVAL;
- aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
+ aic23 = devm_kzalloc(&i2c->dev, sizeof(struct aic23), GFP_KERNEL);
if (aic23 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, aic23);
- aic23->control_data = i2c;
aic23->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_tlv320aic23, &tlv320aic23_dai, 1);
- if (ret < 0)
- kfree(aic23);
return ret;
}
static int __exit tlv320aic23_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
- kfree(i2c_get_clientdata(i2c));
return 0;
}
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 7859bdcc93db..802064b5030d 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -275,7 +275,7 @@ static int aic26_set_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
#define AIC26_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_BE |\
SNDRV_PCM_FMTBIT_S24_BE | SNDRV_PCM_FMTBIT_S32_BE)
-static struct snd_soc_dai_ops aic26_dai_ops = {
+static const struct snd_soc_dai_ops aic26_dai_ops = {
.hw_params = aic26_hw_params,
.digital_mute = aic26_mute,
.set_sysclk = aic26_set_sysclk,
@@ -389,7 +389,7 @@ static int aic26_probe(struct snd_soc_codec *codec)
/* register controls */
dev_dbg(codec->dev, "Registering controls\n");
- err = snd_soc_add_controls(codec, aic26_snd_controls,
+ err = snd_soc_add_codec_controls(codec, aic26_snd_controls,
ARRAY_SIZE(aic26_snd_controls));
WARN_ON(err < 0);
@@ -416,7 +416,7 @@ static int aic26_spi_probe(struct spi_device *spi)
dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
/* Allocate driver data */
- aic26 = kzalloc(sizeof *aic26, GFP_KERNEL);
+ aic26 = devm_kzalloc(&spi->dev, sizeof *aic26, GFP_KERNEL);
if (!aic26)
return -ENOMEM;
@@ -427,18 +427,12 @@ static int aic26_spi_probe(struct spi_device *spi)
ret = snd_soc_register_codec(&spi->dev,
&aic26_soc_codec_dev, &aic26_dai, 1);
- if (ret < 0)
- kfree(aic26);
return ret;
-
- dev_dbg(&spi->dev, "SPI device initialized\n");
- return 0;
}
static int aic26_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
return 0;
}
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c
index e93b9d1ae1dd..b0a73d37ed52 100644
--- a/sound/soc/codecs/tlv320aic32x4.c
+++ b/sound/soc/codecs/tlv320aic32x4.c
@@ -29,7 +29,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/cdev.h>
#include <linux/slab.h>
@@ -61,7 +60,6 @@ struct aic32x4_rate_divs {
struct aic32x4_priv {
u32 sysclk;
- s32 master;
u8 page_no;
void *control_data;
u32 power_cfg;
@@ -370,7 +368,6 @@ static int aic32x4_set_dai_sysclk(struct snd_soc_dai *codec_dai,
static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
u8 iface_reg_1;
u8 iface_reg_2;
u8 iface_reg_3;
@@ -385,11 +382,9 @@ static int aic32x4_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt)
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
case SND_SOC_DAIFMT_CBM_CFM:
- aic32x4->master = 1;
iface_reg_1 |= AIC32X4_BCLKMASTER | AIC32X4_WCLKMASTER;
break;
case SND_SOC_DAIFMT_CBS_CFS:
- aic32x4->master = 0;
break;
default:
printk(KERN_ERR "aic32x4: invalid DAI master/slave interface\n");
@@ -527,77 +522,58 @@ static int aic32x4_mute(struct snd_soc_dai *dai, int mute)
static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct aic32x4_priv *aic32x4 = snd_soc_codec_get_drvdata(codec);
- u8 value;
-
switch (level) {
case SND_SOC_BIAS_ON:
- if (aic32x4->master) {
- /* Switch on PLL */
- value = snd_soc_read(codec, AIC32X4_PLLPR);
- snd_soc_write(codec, AIC32X4_PLLPR,
- (value | AIC32X4_PLLEN));
-
- /* Switch on NDAC Divider */
- value = snd_soc_read(codec, AIC32X4_NDAC);
- snd_soc_write(codec, AIC32X4_NDAC,
- value | AIC32X4_NDACEN);
-
- /* Switch on MDAC Divider */
- value = snd_soc_read(codec, AIC32X4_MDAC);
- snd_soc_write(codec, AIC32X4_MDAC,
- value | AIC32X4_MDACEN);
-
- /* Switch on NADC Divider */
- value = snd_soc_read(codec, AIC32X4_NADC);
- snd_soc_write(codec, AIC32X4_NADC,
- value | AIC32X4_MDACEN);
-
- /* Switch on MADC Divider */
- value = snd_soc_read(codec, AIC32X4_MADC);
- snd_soc_write(codec, AIC32X4_MADC,
- value | AIC32X4_MDACEN);
-
- /* Switch on BCLK_N Divider */
- value = snd_soc_read(codec, AIC32X4_BCLKN);
- snd_soc_write(codec, AIC32X4_BCLKN,
- value | AIC32X4_BCLKEN);
- }
+ /* Switch on PLL */
+ snd_soc_update_bits(codec, AIC32X4_PLLPR,
+ AIC32X4_PLLEN, AIC32X4_PLLEN);
+
+ /* Switch on NDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NDAC,
+ AIC32X4_NDACEN, AIC32X4_NDACEN);
+
+ /* Switch on MDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MDAC,
+ AIC32X4_MDACEN, AIC32X4_MDACEN);
+
+ /* Switch on NADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NADC,
+ AIC32X4_NADCEN, AIC32X4_NADCEN);
+
+ /* Switch on MADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MADC,
+ AIC32X4_MADCEN, AIC32X4_MADCEN);
+
+ /* Switch on BCLK_N Divider */
+ snd_soc_update_bits(codec, AIC32X4_BCLKN,
+ AIC32X4_BCLKEN, AIC32X4_BCLKEN);
break;
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
- if (aic32x4->master) {
- /* Switch off PLL */
- value = snd_soc_read(codec, AIC32X4_PLLPR);
- snd_soc_write(codec, AIC32X4_PLLPR,
- (value & ~AIC32X4_PLLEN));
-
- /* Switch off NDAC Divider */
- value = snd_soc_read(codec, AIC32X4_NDAC);
- snd_soc_write(codec, AIC32X4_NDAC,
- value & ~AIC32X4_NDACEN);
-
- /* Switch off MDAC Divider */
- value = snd_soc_read(codec, AIC32X4_MDAC);
- snd_soc_write(codec, AIC32X4_MDAC,
- value & ~AIC32X4_MDACEN);
-
- /* Switch off NADC Divider */
- value = snd_soc_read(codec, AIC32X4_NADC);
- snd_soc_write(codec, AIC32X4_NADC,
- value & ~AIC32X4_NDACEN);
-
- /* Switch off MADC Divider */
- value = snd_soc_read(codec, AIC32X4_MADC);
- snd_soc_write(codec, AIC32X4_MADC,
- value & ~AIC32X4_MDACEN);
- value = snd_soc_read(codec, AIC32X4_BCLKN);
-
- /* Switch off BCLK_N Divider */
- snd_soc_write(codec, AIC32X4_BCLKN,
- value & ~AIC32X4_BCLKEN);
- }
+ /* Switch off PLL */
+ snd_soc_update_bits(codec, AIC32X4_PLLPR,
+ AIC32X4_PLLEN, 0);
+
+ /* Switch off NDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NDAC,
+ AIC32X4_NDACEN, 0);
+
+ /* Switch off MDAC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MDAC,
+ AIC32X4_MDACEN, 0);
+
+ /* Switch off NADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_NADC,
+ AIC32X4_NADCEN, 0);
+
+ /* Switch off MADC Divider */
+ snd_soc_update_bits(codec, AIC32X4_MADC,
+ AIC32X4_MADCEN, 0);
+
+ /* Switch off BCLK_N Divider */
+ snd_soc_update_bits(codec, AIC32X4_BCLKN,
+ AIC32X4_BCLKEN, 0);
break;
case SND_SOC_BIAS_OFF:
break;
@@ -610,7 +586,7 @@ static int aic32x4_set_bias_level(struct snd_soc_codec *codec,
#define AIC32X4_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE \
| SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops aic32x4_ops = {
+static const struct snd_soc_dai_ops aic32x4_ops = {
.hw_params = aic32x4_hw_params,
.digital_mute = aic32x4_mute,
.set_fmt = aic32x4_set_dai_fmt,
@@ -635,7 +611,7 @@ static struct snd_soc_dai_driver aic32x4_dai = {
.symmetric_rates = 1,
};
-static int aic32x4_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int aic32x4_suspend(struct snd_soc_codec *codec)
{
aic32x4_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -665,9 +641,11 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
if (aic32x4->power_cfg & AIC32X4_PWR_AVDD_DVDD_WEAK_DISABLE) {
snd_soc_write(codec, AIC32X4_PWRCFG, AIC32X4_AVDDWEAKDISABLE);
}
- if (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) {
- snd_soc_write(codec, AIC32X4_LDOCTL, AIC32X4_LDOCTLEN);
- }
+
+ tmp_reg = (aic32x4->power_cfg & AIC32X4_PWR_AIC32X4_LDO_ENABLE) ?
+ AIC32X4_LDOCTLEN : 0;
+ snd_soc_write(codec, AIC32X4_LDOCTL, tmp_reg);
+
tmp_reg = snd_soc_read(codec, AIC32X4_CMMODE);
if (aic32x4->power_cfg & AIC32X4_PWR_CMMODE_LDOIN_RANGE_18_36) {
tmp_reg |= AIC32X4_LDOIN_18_36;
@@ -685,15 +663,15 @@ static int aic32x4_probe(struct snd_soc_codec *codec)
}
/* Mic PGA routing */
- if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) {
+ if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_LMIC_IN2R_10K) {
snd_soc_write(codec, AIC32X4_LMICPGANIN, AIC32X4_LMICPGANIN_IN2R_10K);
}
- if (aic32x4->micpga_routing | AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) {
+ if (aic32x4->micpga_routing & AIC32X4_MICPGA_ROUTE_RMIC_IN1L_10K) {
snd_soc_write(codec, AIC32X4_RMICPGANIN, AIC32X4_RMICPGANIN_IN1L_10K);
}
aic32x4_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, aic32x4_snd_controls,
+ snd_soc_add_codec_controls(codec, aic32x4_snd_controls,
ARRAY_SIZE(aic32x4_snd_controls));
aic32x4_add_widgets(codec);
@@ -723,7 +701,8 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
struct aic32x4_priv *aic32x4;
int ret;
- aic32x4 = kzalloc(sizeof(struct aic32x4_priv), GFP_KERNEL);
+ aic32x4 = devm_kzalloc(&i2c->dev, sizeof(struct aic32x4_priv),
+ GFP_KERNEL);
if (aic32x4 == NULL)
return -ENOMEM;
@@ -742,15 +721,12 @@ static __devinit int aic32x4_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_aic32x4, &aic32x4_dai, 1);
- if (ret < 0)
- kfree(aic32x4);
return ret;
}
static __devexit int aic32x4_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index 0963c4c7a83f..8d20f6ec20f3 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -40,7 +40,6 @@
#include <linux/i2c.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -76,7 +75,6 @@ struct aic3x_priv {
struct aic3x_disable_nb disable_nb[AIC3X_NUM_SUPPLIES];
enum snd_soc_control_type control_type;
struct aic3x_setup_data *setup;
- void *control_data;
unsigned int sysclk;
struct list_head list;
int master;
@@ -123,27 +121,6 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = {
0x00, 0x00, 0x02, /* 100 */
};
-/*
- * read from the aic3x register space. Only use for this function is if
- * wanting to read volatile bits from those registers that has both read-only
- * and read/write bits. All other cases should use snd_soc_read.
- */
-static int aic3x_read(struct snd_soc_codec *codec, unsigned int reg,
- u8 *value)
-{
- u8 *cache = codec->reg_cache;
-
- if (codec->cache_only)
- return -EINVAL;
- if (reg >= AIC3X_CACHEREGNUM)
- return -1;
-
- *value = codec->hw_read(codec, reg);
- cache[reg] = *value;
-
- return 0;
-}
-
#define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
.info = snd_soc_info_volsw, \
@@ -198,6 +175,10 @@ static int snd_soc_dapm_put_volsw_aic3x(struct snd_kcontrol *kcontrol,
else
/* old connection must be powered down */
path->connect = invert ? 1 : 0;
+
+ dapm_mark_dirty(path->source, "tlv320aic3x source");
+ dapm_mark_dirty(path->sink, "tlv320aic3x sink");
+
break;
}
@@ -827,7 +808,6 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
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;
- u8 reg;
int clk;
/* select data word length */
@@ -863,14 +843,13 @@ static int aic3x_hw_params(struct snd_pcm_substream *substream,
snd_soc_write(codec, AIC3X_PLL_PROGA_REG, pll_q << PLLQ_SHIFT);
snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_CLKDIV);
/* disable PLL if it is bypassed */
- reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
- snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg & ~PLL_ENABLE);
+ snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG, PLL_ENABLE, 0);
} else {
snd_soc_write(codec, AIC3X_GPIOB_REG, CODEC_CLKIN_PLLDIV);
/* enable PLL when it is used */
- reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
- snd_soc_write(codec, AIC3X_PLL_PROGA_REG, reg | PLL_ENABLE);
+ snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG,
+ PLL_ENABLE, PLL_ENABLE);
}
/* Route Left DAC to left channel input and
@@ -1017,6 +996,7 @@ static int aic3x_set_dai_fmt(struct snd_soc_dai *codec_dai,
break;
case SND_SOC_DAIFMT_CBS_CFS:
aic3x->master = 0;
+ iface_areg &= ~(BIT_CLK_MASTER | WORD_CLK_MASTER);
break;
default:
return -EINVAL;
@@ -1149,7 +1129,6 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
- u8 reg;
switch (level) {
case SND_SOC_BIAS_ON:
@@ -1158,9 +1137,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY &&
aic3x->master) {
/* enable pll */
- reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
- snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
- reg | PLL_ENABLE);
+ snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG,
+ PLL_ENABLE, PLL_ENABLE);
}
break;
case SND_SOC_BIAS_STANDBY:
@@ -1169,9 +1147,8 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE &&
aic3x->master) {
/* disable pll */
- reg = snd_soc_read(codec, AIC3X_PLL_PROGA_REG);
- snd_soc_write(codec, AIC3X_PLL_PROGA_REG,
- reg & ~PLL_ENABLE);
+ snd_soc_update_bits(codec, AIC3X_PLL_PROGA_REG,
+ PLL_ENABLE, 0);
}
break;
case SND_SOC_BIAS_OFF:
@@ -1184,25 +1161,6 @@ static int aic3x_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state)
-{
- u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
- u8 bit = gpio ? 3: 0;
- u8 val = snd_soc_read(codec, reg) & ~(1 << bit);
- snd_soc_write(codec, reg, val | (!!state << bit));
-}
-EXPORT_SYMBOL_GPL(aic3x_set_gpio);
-
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
-{
- u8 reg = gpio ? AIC3X_GPIO2_REG : AIC3X_GPIO1_REG;
- u8 val = 0, bit = gpio ? 2 : 1;
-
- aic3x_read(codec, reg, &val);
- return (val >> bit) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_get_gpio);
-
void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
int headset_debounce, int button_debounce)
{
@@ -1220,29 +1178,12 @@ void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
snd_soc_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
}
-EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
-
-int aic3x_headset_detected(struct snd_soc_codec *codec)
-{
- u8 val = 0;
- aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
- return (val >> 4) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_headset_detected);
-
-int aic3x_button_pressed(struct snd_soc_codec *codec)
-{
- u8 val = 0;
- aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
- return (val >> 5) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_button_pressed);
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops aic3x_dai_ops = {
+static const struct snd_soc_dai_ops aic3x_dai_ops = {
.hw_params = aic3x_hw_params,
.digital_mute = aic3x_mute,
.set_sysclk = aic3x_set_dai_sysclk,
@@ -1267,7 +1208,7 @@ static struct snd_soc_dai_driver aic3x_dai = {
.symmetric_rates = 1,
};
-static int aic3x_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int aic3x_suspend(struct snd_soc_codec *codec)
{
aic3x_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -1288,7 +1229,6 @@ static int aic3x_resume(struct snd_soc_codec *codec)
static int aic3x_init(struct snd_soc_codec *codec)
{
struct aic3x_priv *aic3x = snd_soc_codec_get_drvdata(codec);
- int reg;
snd_soc_write(codec, AIC3X_PAGE_SELECT, PAGE0_SELECT);
snd_soc_write(codec, AIC3X_RESET, SOFT_RESET);
@@ -1310,20 +1250,13 @@ static int aic3x_init(struct snd_soc_codec *codec)
snd_soc_write(codec, DACR1_2_MONOLOPM_VOL, DEFAULT_VOL | ROUTE_ON);
/* unmute all outputs */
- reg = snd_soc_read(codec, LLOPM_CTRL);
- snd_soc_write(codec, LLOPM_CTRL, reg | UNMUTE);
- reg = snd_soc_read(codec, RLOPM_CTRL);
- snd_soc_write(codec, RLOPM_CTRL, reg | UNMUTE);
- reg = snd_soc_read(codec, MONOLOPM_CTRL);
- snd_soc_write(codec, MONOLOPM_CTRL, reg | UNMUTE);
- reg = snd_soc_read(codec, HPLOUT_CTRL);
- snd_soc_write(codec, HPLOUT_CTRL, reg | UNMUTE);
- reg = snd_soc_read(codec, HPROUT_CTRL);
- snd_soc_write(codec, HPROUT_CTRL, reg | UNMUTE);
- reg = snd_soc_read(codec, HPLCOM_CTRL);
- snd_soc_write(codec, HPLCOM_CTRL, reg | UNMUTE);
- reg = snd_soc_read(codec, HPRCOM_CTRL);
- snd_soc_write(codec, HPRCOM_CTRL, reg | UNMUTE);
+ snd_soc_update_bits(codec, LLOPM_CTRL, UNMUTE, UNMUTE);
+ snd_soc_update_bits(codec, RLOPM_CTRL, UNMUTE, UNMUTE);
+ snd_soc_update_bits(codec, MONOLOPM_CTRL, UNMUTE, UNMUTE);
+ snd_soc_update_bits(codec, HPLOUT_CTRL, UNMUTE, UNMUTE);
+ snd_soc_update_bits(codec, HPROUT_CTRL, UNMUTE, UNMUTE);
+ snd_soc_update_bits(codec, HPLCOM_CTRL, UNMUTE, UNMUTE);
+ snd_soc_update_bits(codec, HPRCOM_CTRL, UNMUTE, UNMUTE);
/* ADC default volume and unmute */
snd_soc_write(codec, LADC_VOL, DEFAULT_GAIN);
@@ -1383,9 +1316,7 @@ static int aic3x_probe(struct snd_soc_codec *codec)
int ret, i;
INIT_LIST_HEAD(&aic3x->list);
- codec->control_data = aic3x->control_data;
aic3x->codec = codec;
- codec->dapm.idle_bias_off = 1;
ret = snd_soc_codec_set_cache_io(codec, 8, 8, aic3x->control_type);
if (ret != 0) {
@@ -1434,10 +1365,10 @@ static int aic3x_probe(struct snd_soc_codec *codec)
(aic3x->setup->gpio_func[1] & 0xf) << 4);
}
- snd_soc_add_controls(codec, aic3x_snd_controls,
+ snd_soc_add_codec_controls(codec, aic3x_snd_controls,
ARRAY_SIZE(aic3x_snd_controls));
if (aic3x->model == AIC3X_MODEL_3007)
- snd_soc_add_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
+ snd_soc_add_codec_controls(codec, &aic3x_classd_amp_gain_ctrl, 1);
aic3x_add_widgets(codec);
list_add(&aic3x->list, &reset_list);
@@ -1479,6 +1410,7 @@ static int aic3x_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.set_bias_level = aic3x_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(aic3x_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = aic3x_reg,
@@ -1488,16 +1420,15 @@ static struct snd_soc_codec_driver soc_codec_dev_aic3x = {
.resume = aic3x_resume,
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
/*
* AIC3X 2 wire address can be up to 4 devices with device addresses
* 0x18, 0x19, 0x1A, 0x1B
*/
static const struct i2c_device_id aic3x_i2c_id[] = {
- [AIC3X_MODEL_3X] = { "tlv320aic3x", 0 },
- [AIC3X_MODEL_33] = { "tlv320aic33", 0 },
- [AIC3X_MODEL_3007] = { "tlv320aic3007", 0 },
+ { "tlv320aic3x", AIC3X_MODEL_3X },
+ { "tlv320aic33", AIC3X_MODEL_33 },
+ { "tlv320aic3007", AIC3X_MODEL_3007 },
{ }
};
MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id);
@@ -1512,15 +1443,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
struct aic3x_pdata *pdata = i2c->dev.platform_data;
struct aic3x_priv *aic3x;
int ret;
- const struct i2c_device_id *tbl;
- aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL);
+ aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL);
if (aic3x == NULL) {
dev_err(&i2c->dev, "failed to create private data\n");
return -ENOMEM;
}
- aic3x->control_data = i2c;
aic3x->control_type = SND_SOC_I2C;
i2c_set_clientdata(i2c, aic3x);
@@ -1531,23 +1460,16 @@ static int aic3x_i2c_probe(struct i2c_client *i2c,
aic3x->gpio_reset = -1;
}
- for (tbl = aic3x_i2c_id; tbl->name[0]; tbl++) {
- if (!strcmp(tbl->name, id->name))
- break;
- }
- aic3x->model = tbl - aic3x_i2c_id;
+ aic3x->model = id->driver_data;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_aic3x, &aic3x_dai, 1);
- if (ret < 0)
- kfree(aic3x);
return ret;
}
static int aic3x_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1561,27 +1483,22 @@ static struct i2c_driver aic3x_i2c_driver = {
.remove = aic3x_i2c_remove,
.id_table = aic3x_i2c_id,
};
-#endif
static int __init aic3x_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&aic3x_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(aic3x_modinit);
static void __exit aic3x_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&aic3x_i2c_driver);
-#endif
}
module_exit(aic3x_exit);
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 06a19784b162..6f097fb60683 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -212,9 +212,6 @@
/* Default input volume */
#define DEFAULT_GAIN 0x20
-void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
-int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
-
/* headset detection / button API */
/* The AIC3x supports detection of stereo headsets (GND + left + right signal)
@@ -252,10 +249,4 @@ enum {
#define AIC3X_BUTTON_DEBOUNCE_SHIFT 0
#define AIC3X_BUTTON_DEBOUNCE_MASK 3
-/* see the enums above for valid parameters to this function */
-void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
- int headset_debounce, int button_debounce);
-int aic3x_headset_detected(struct snd_soc_codec *codec);
-int aic3x_button_pressed(struct snd_soc_codec *codec);
-
#endif /* _AIC3X_H */
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index faa5e9fb1471..4587ddd0fbf8 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -27,7 +27,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/regulator/consumer.h>
@@ -55,13 +54,13 @@
#define BURST_BASEFREQ_HZ 49152000
#define SAMPLES_TO_US(rate, samples) \
- (1000000000 / ((rate * 1000) / samples))
+ (1000000000 / (((rate) * 1000) / (samples)))
#define US_TO_SAMPLES(rate, us) \
- (rate / (1000000 / (us < 1000000 ? us : 1000000)))
+ ((rate) / (1000000 / ((us) < 1000000 ? (us) : 1000000)))
#define UTHR_FROM_PERIOD_SIZE(samples, playrate, burstrate) \
- ((samples * 5000) / ((burstrate * 5000) / (burstrate - playrate)))
+ (((samples)*5000) / (((burstrate)*5000) / ((burstrate) - (playrate))))
static void dac33_calculate_times(struct snd_pcm_substream *substream);
static int dac33_prepare_chip(struct snd_pcm_substream *substream);
@@ -627,18 +626,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"RIGHT_LO", NULL, "Codec Power"},
};
-static int dac33_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, dac33_dapm_widgets,
- ARRAY_SIZE(dac33_dapm_widgets));
- /* set up audio path interconnects */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
static int dac33_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -819,8 +806,6 @@ static int dac33_startup(struct snd_pcm_substream *substream,
/* Stream started, save the substream pointer */
dac33->substream = substream;
- snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
-
return 0;
}
@@ -1410,7 +1395,6 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
codec->control_data = dac33->control_data;
codec->hw_write = (hw_write_t) i2c_master_send;
- codec->dapm.idle_bias_off = 1;
dac33->codec = codec;
/* Read the tlv320dac33 ID registers */
@@ -1431,7 +1415,7 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
/* Check if the IRQ number is valid and request it */
if (dac33->irq >= 0) {
ret = request_irq(dac33->irq, dac33_interrupt_handler,
- IRQF_TRIGGER_RISING | IRQF_DISABLED,
+ IRQF_TRIGGER_RISING,
codec->name, codec);
if (ret < 0) {
dev_err(codec->dev, "Could not request IRQ%d (%d)\n",
@@ -1451,15 +1435,11 @@ static int dac33_soc_probe(struct snd_soc_codec *codec)
}
}
- snd_soc_add_controls(codec, dac33_snd_controls,
- ARRAY_SIZE(dac33_snd_controls));
/* Only add the FIFO controls, if we have valid IRQ number */
if (dac33->irq >= 0)
- snd_soc_add_controls(codec, dac33_mode_snd_controls,
+ snd_soc_add_codec_controls(codec, dac33_mode_snd_controls,
ARRAY_SIZE(dac33_mode_snd_controls));
- dac33_add_widgets(codec);
-
err_power:
return ret;
}
@@ -1477,7 +1457,7 @@ static int dac33_soc_remove(struct snd_soc_codec *codec)
return 0;
}
-static int dac33_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int dac33_soc_suspend(struct snd_soc_codec *codec)
{
dac33_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -1495,6 +1475,7 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
.read = dac33_read_reg_cache,
.write = dac33_write_locked,
.set_bias_level = dac33_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(dac33_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = dac33_reg,
@@ -1502,13 +1483,20 @@ static struct snd_soc_codec_driver soc_codec_dev_tlv320dac33 = {
.remove = dac33_soc_remove,
.suspend = dac33_soc_suspend,
.resume = dac33_soc_resume,
+
+ .controls = dac33_snd_controls,
+ .num_controls = ARRAY_SIZE(dac33_snd_controls),
+ .dapm_widgets = dac33_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(dac33_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
};
#define DAC33_RATES (SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
#define DAC33_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops dac33_dai_ops = {
+static const struct snd_soc_dai_ops dac33_dai_ops = {
.startup = dac33_startup,
.shutdown = dac33_shutdown,
.hw_params = dac33_hw_params,
@@ -1525,7 +1513,9 @@ static struct snd_soc_dai_driver dac33_dai = {
.channels_min = 2,
.channels_max = 2,
.rates = DAC33_RATES,
- .formats = DAC33_FORMATS,},
+ .formats = DAC33_FORMATS,
+ .sig_bits = 24,
+ },
.ops = &dac33_dai_ops,
};
@@ -1542,7 +1532,8 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client,
}
pdata = client->dev.platform_data;
- dac33 = kzalloc(sizeof(struct tlv320dac33_priv), GFP_KERNEL);
+ dac33 = devm_kzalloc(&client->dev, sizeof(struct tlv320dac33_priv),
+ GFP_KERNEL);
if (dac33 == NULL)
return -ENOMEM;
@@ -1597,7 +1588,6 @@ err_get:
if (dac33->power_gpio >= 0)
gpio_free(dac33->power_gpio);
err_gpio:
- kfree(dac33);
return ret;
}
@@ -1614,8 +1604,6 @@ static int __devexit dac33_i2c_remove(struct i2c_client *client)
regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies);
snd_soc_unregister_codec(&client->dev);
- kfree(dac33);
-
return 0;
}
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 239e0c461068..6fe4aa3ac544 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -33,6 +33,11 @@
#include "tpa6130a2.h"
+enum tpa_model {
+ TPA6130A2,
+ TPA6140A2,
+};
+
static struct i2c_client *tpa6130a2_client;
/* This struct is used to save the context */
@@ -346,10 +351,10 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
data = i2c_get_clientdata(tpa6130a2_client);
if (data->id == TPA6140A2)
- return snd_soc_add_controls(codec, tpa6140a2_controls,
+ return snd_soc_add_codec_controls(codec, tpa6140a2_controls,
ARRAY_SIZE(tpa6140a2_controls));
else
- return snd_soc_add_controls(codec, tpa6130a2_controls,
+ return snd_soc_add_codec_controls(codec, tpa6130a2_controls,
ARRAY_SIZE(tpa6130a2_controls));
}
EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
@@ -371,7 +376,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
return -ENODEV;
}
- data = kzalloc(sizeof(*data), GFP_KERNEL);
+ data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
if (data == NULL) {
dev_err(dev, "Can not allocate memory\n");
return -ENOMEM;
@@ -383,7 +388,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
pdata = client->dev.platform_data;
data->power_gpio = pdata->power_gpio;
- data->id = pdata->id;
+ data->id = id->driver_data;
mutex_init(&data->mutex);
@@ -405,7 +410,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
switch (data->id) {
default:
dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
- pdata->id);
+ data->id);
case TPA6130A2:
regulator = "Vdd";
break;
@@ -445,8 +450,6 @@ err_regulator:
if (data->power_gpio >= 0)
gpio_free(data->power_gpio);
err_gpio:
- kfree(data);
- i2c_set_clientdata(tpa6130a2_client, NULL);
tpa6130a2_client = NULL;
return ret;
@@ -462,15 +465,14 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client)
gpio_free(data->power_gpio);
regulator_put(data->supply);
-
- kfree(data);
tpa6130a2_client = NULL;
return 0;
}
static const struct i2c_device_id tpa6130a2_id[] = {
- { "tpa6130a2", 0 },
+ { "tpa6130a2", TPA6130A2 },
+ { "tpa6140a2", TPA6140A2 },
{ }
};
MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 71674bec9604..170cf9a8fc79 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -863,34 +863,6 @@ static int digimic_event(struct snd_soc_dapm_widget *w,
* Inverting not going to help with these.
* Custom volsw and volsw_2r get/put functions to handle these gain bits.
*/
-#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\
- xinvert, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE,\
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, \
- .get = snd_soc_get_volsw_twl4030, \
- .put = snd_soc_put_volsw_twl4030, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
- .max = xmax, .invert = xinvert} }
-#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\
- xinvert, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE,\
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw_2r, \
- .get = snd_soc_get_volsw_r2_twl4030,\
- .put = snd_soc_put_volsw_r2_twl4030, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
- .rshift = xshift, .max = xmax, .invert = xinvert} }
-#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \
- SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \
- xinvert, tlv_array)
-
static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -1030,8 +1002,8 @@ static int snd_soc_put_twl4030_opmode_enum_double(struct snd_kcontrol *kcontrol,
unsigned short mask, bitmask;
if (twl4030->configured) {
- printk(KERN_ERR "twl4030 operation mode cannot be "
- "changed on-the-fly\n");
+ dev_err(codec->dev,
+ "operation mode cannot be changed on-the-fly\n");
return -EBUSY;
}
@@ -1197,19 +1169,23 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
TWL4030_REG_VDL_APGA_CTL, 1, 1, 0),
/* Separate output gain controls */
- SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
+ SOC_DOUBLE_R_EXT_TLV("PreDriv Playback Volume",
TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
- 4, 3, 0, output_tvl),
+ 4, 3, 0, snd_soc_get_volsw_r2_twl4030,
+ snd_soc_put_volsw_r2_twl4030, output_tvl),
- SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume",
- TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl),
+ SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
+ TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, snd_soc_get_volsw_twl4030,
+ snd_soc_put_volsw_twl4030, output_tvl),
- SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume",
+ SOC_DOUBLE_R_EXT_TLV("Carkit Playback Volume",
TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL,
- 4, 3, 0, output_tvl),
+ 4, 3, 0, snd_soc_get_volsw_r2_twl4030,
+ snd_soc_put_volsw_r2_twl4030, output_tvl),
- SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
- TWL4030_REG_EAR_CTL, 4, 3, 0, output_ear_tvl),
+ SOC_SINGLE_EXT_TLV("Earpiece Playback Volume",
+ TWL4030_REG_EAR_CTL, 4, 3, 0, snd_soc_get_volsw_twl4030,
+ snd_soc_put_volsw_twl4030, output_ear_tvl),
/* Common capture gain controls */
SOC_DOUBLE_R_TLV("TX1 Digital Capture Volume",
@@ -1633,17 +1609,6 @@ static const struct snd_soc_dapm_route intercon[] = {
};
-static int twl4030_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, twl4030_dapm_widgets,
- ARRAY_SIZE(twl4030_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
- return 0;
-}
-
static int twl4030_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -1724,7 +1689,6 @@ static int twl4030_startup(struct snd_pcm_substream *substream,
struct snd_soc_codec *codec = rtd->codec;
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
- snd_pcm_hw_constraint_msbits(substream->runtime, 0, 32, 24);
if (twl4030->master_substream) {
twl4030->slave_substream = substream;
/* The DAI has one configuration for playback and capture, so
@@ -1836,7 +1800,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
mode |= TWL4030_APLL_RATE_96000;
break;
default:
- printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
+ dev_err(codec->dev, "%s: unknown rate %d\n", __func__,
params_rate(params));
return -EINVAL;
}
@@ -1853,7 +1817,7 @@ static int twl4030_hw_params(struct snd_pcm_substream *substream,
format |= TWL4030_DATA_WIDTH_32S_24W;
break;
default:
- printk(KERN_ERR "TWL4030 hw params: unknown format %d\n",
+ dev_err(codec->dev, "%s: unknown format %d\n", __func__,
params_format(params));
return -EINVAL;
}
@@ -1903,13 +1867,13 @@ static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
case 38400000:
break;
default:
- dev_err(codec->dev, "Unsupported APLL mclk: %u\n", freq);
+ dev_err(codec->dev, "Unsupported HFCLKIN: %u\n", freq);
return -EINVAL;
}
if ((freq / 1000) != twl4030->sysclk) {
dev_err(codec->dev,
- "Mismatch in APLL mclk: %u (configured: %u)\n",
+ "Mismatch in HFCLKIN: %u (configured: %u)\n",
freq, twl4030->sysclk * 1000);
return -EINVAL;
}
@@ -2019,9 +1983,9 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
* not available.
*/
if (twl4030->sysclk != 26000) {
- dev_err(codec->dev, "The board is configured for %u Hz, while"
- "the Voice interface needs 26MHz APLL mclk\n",
- twl4030->sysclk * 1000);
+ dev_err(codec->dev,
+ "%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n",
+ __func__, twl4030->sysclk);
return -EINVAL;
}
@@ -2032,8 +1996,8 @@ static int twl4030_voice_startup(struct snd_pcm_substream *substream,
& TWL4030_OPT_MODE;
if (mode != TWL4030_OPTION_2) {
- printk(KERN_ERR "TWL4030 voice startup: "
- "the codec mode is not option2\n");
+ dev_err(codec->dev, "%s: the codec mode is not option2\n",
+ __func__);
return -EINVAL;
}
@@ -2074,7 +2038,7 @@ static int twl4030_voice_hw_params(struct snd_pcm_substream *substream,
mode |= TWL4030_SEL_16K;
break;
default:
- printk(KERN_ERR "TWL4030 voice hw params: unknown rate %d\n",
+ dev_err(codec->dev, "%s: unknown rate %d\n", __func__,
params_rate(params));
return -EINVAL;
}
@@ -2103,13 +2067,14 @@ static int twl4030_voice_set_dai_sysclk(struct snd_soc_dai *codec_dai,
struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec);
if (freq != 26000000) {
- dev_err(codec->dev, "Unsupported APLL mclk: %u, the Voice"
- "interface needs 26MHz APLL mclk\n", freq);
+ dev_err(codec->dev,
+ "%s: HFCLKIN is %u KHz, voice interface needs 26MHz\n",
+ __func__, freq / 1000);
return -EINVAL;
}
if ((freq / 1000) != twl4030->sysclk) {
dev_err(codec->dev,
- "Mismatch in APLL mclk: %u (configured: %u)\n",
+ "Mismatch in HFCLKIN: %u (configured: %u)\n",
freq, twl4030->sysclk * 1000);
return -EINVAL;
}
@@ -2184,7 +2149,7 @@ static int twl4030_voice_set_tristate(struct snd_soc_dai *dai, int tristate)
#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
+static const struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
.startup = twl4030_startup,
.shutdown = twl4030_shutdown,
.hw_params = twl4030_hw_params,
@@ -2193,7 +2158,7 @@ static struct snd_soc_dai_ops twl4030_dai_hifi_ops = {
.set_tristate = twl4030_set_tristate,
};
-static struct snd_soc_dai_ops twl4030_dai_voice_ops = {
+static const struct snd_soc_dai_ops twl4030_dai_voice_ops = {
.startup = twl4030_voice_startup,
.shutdown = twl4030_voice_shutdown,
.hw_params = twl4030_voice_hw_params,
@@ -2210,13 +2175,15 @@ static struct snd_soc_dai_driver twl4030_dai[] = {
.channels_min = 2,
.channels_max = 4,
.rates = TWL4030_RATES | SNDRV_PCM_RATE_96000,
- .formats = TWL4030_FORMATS,},
+ .formats = TWL4030_FORMATS,
+ .sig_bits = 24,},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 4,
.rates = TWL4030_RATES,
- .formats = TWL4030_FORMATS,},
+ .formats = TWL4030_FORMATS,
+ .sig_bits = 24,},
.ops = &twl4030_dai_hifi_ops,
},
{
@@ -2237,7 +2204,7 @@ static struct snd_soc_dai_driver twl4030_dai[] = {
},
};
-static int twl4030_soc_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int twl4030_soc_suspend(struct snd_soc_codec *codec)
{
twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -2255,19 +2222,15 @@ static int twl4030_soc_probe(struct snd_soc_codec *codec)
twl4030 = kzalloc(sizeof(struct twl4030_priv), GFP_KERNEL);
if (twl4030 == NULL) {
- printk("Can not allocate memroy\n");
+ dev_err(codec->dev, "Can not allocate memory\n");
return -ENOMEM;
}
snd_soc_codec_set_drvdata(codec, twl4030);
/* Set the defaults, and power up the codec */
twl4030->sysclk = twl4030_audio_get_mclk() / 1000;
- codec->dapm.idle_bias_off = 1;
twl4030_init_chip(codec);
- snd_soc_add_controls(codec, twl4030_snd_controls,
- ARRAY_SIZE(twl4030_snd_controls));
- twl4030_add_widgets(codec);
return 0;
}
@@ -2290,9 +2253,17 @@ static struct snd_soc_codec_driver soc_codec_dev_twl4030 = {
.read = twl4030_read_reg_cache,
.write = twl4030_write,
.set_bias_level = twl4030_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = sizeof(twl4030_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = twl4030_reg,
+
+ .controls = twl4030_snd_controls,
+ .num_controls = ARRAY_SIZE(twl4030_snd_controls),
+ .dapm_widgets = twl4030_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(twl4030_dapm_widgets),
+ .dapm_routes = intercon,
+ .num_dapm_routes = ARRAY_SIZE(intercon),
};
static int __devinit twl4030_codec_probe(struct platform_device *pdev)
@@ -2325,17 +2296,7 @@ static struct platform_driver twl4030_codec_driver = {
},
};
-static int __init twl4030_modinit(void)
-{
- return platform_driver_register(&twl4030_codec_driver);
-}
-module_init(twl4030_modinit);
-
-static void __exit twl4030_exit(void)
-{
- platform_driver_unregister(&twl4030_codec_driver);
-}
-module_exit(twl4030_exit);
+module_platform_driver(twl4030_codec_driver);
MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
MODULE_AUTHOR("Steve Sakoman");
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 443032b3b329..2d8c6b825e57 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -33,6 +33,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/soc-dapm.h>
#include <sound/initval.h>
#include <sound/tlv.h>
@@ -57,6 +58,13 @@
#define TWL6040_HF_VOL_MASK 0x1F
#define TWL6040_HF_VOL_SHIFT 0
+/* Shadow register used by the driver */
+#define TWL6040_REG_SW_SHADOW 0x2F
+#define TWL6040_CACHEREGNUM (TWL6040_REG_SW_SHADOW + 1)
+
+/* TWL6040_REG_SW_SHADOW (0x2F) fields */
+#define TWL6040_EAR_PATH_ENABLE 0x01
+
struct twl6040_output {
u16 active;
u16 left_vol;
@@ -65,12 +73,13 @@ struct twl6040_output {
u16 right_step;
unsigned int step_delay;
u16 ramp;
- u16 mute;
+ struct delayed_work work;
struct completion ramp_done;
};
struct twl6040_jack_data {
struct snd_soc_jack *jack;
+ struct delayed_work work;
int report;
};
@@ -79,7 +88,6 @@ struct twl6040_data {
int plug_irq;
int codec_powered;
int pll;
- int non_lp;
int pll_power_mode;
int hs_power_mode;
int hs_power_mode_locked;
@@ -92,104 +100,68 @@ struct twl6040_data {
struct twl6040_jack_data hs_jack;
struct snd_soc_codec *codec;
struct workqueue_struct *workqueue;
- struct delayed_work delayed_work;
struct mutex mutex;
struct twl6040_output headset;
struct twl6040_output handsfree;
- struct workqueue_struct *hf_workqueue;
- struct workqueue_struct *hs_workqueue;
- struct delayed_work hs_delayed_work;
- struct delayed_work hf_delayed_work;
};
/*
* twl6040 register cache & default register settings
*/
static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = {
- 0x00, /* not used 0x00 */
- 0x4B, /* TWL6040_ASICID (ro) 0x01 */
- 0x00, /* TWL6040_ASICREV (ro) 0x02 */
- 0x00, /* TWL6040_INTID 0x03 */
- 0x00, /* TWL6040_INTMR 0x04 */
- 0x00, /* TWL6040_NCPCTRL 0x05 */
- 0x00, /* TWL6040_LDOCTL 0x06 */
- 0x60, /* TWL6040_HPPLLCTL 0x07 */
- 0x00, /* TWL6040_LPPLLCTL 0x08 */
- 0x4A, /* TWL6040_LPPLLDIV 0x09 */
- 0x00, /* TWL6040_AMICBCTL 0x0A */
- 0x00, /* TWL6040_DMICBCTL 0x0B */
- 0x18, /* TWL6040_MICLCTL 0x0C - No input selected on Left Mic */
- 0x18, /* TWL6040_MICRCTL 0x0D - No input selected on Right Mic */
- 0x00, /* TWL6040_MICGAIN 0x0E */
- 0x1B, /* TWL6040_LINEGAIN 0x0F */
- 0x00, /* TWL6040_HSLCTL 0x10 */
- 0x00, /* TWL6040_HSRCTL 0x11 */
- 0x00, /* TWL6040_HSGAIN 0x12 */
- 0x00, /* TWL6040_EARCTL 0x13 */
- 0x00, /* TWL6040_HFLCTL 0x14 */
- 0x00, /* TWL6040_HFLGAIN 0x15 */
- 0x00, /* TWL6040_HFRCTL 0x16 */
- 0x00, /* TWL6040_HFRGAIN 0x17 */
- 0x00, /* TWL6040_VIBCTLL 0x18 */
- 0x00, /* TWL6040_VIBDATL 0x19 */
- 0x00, /* TWL6040_VIBCTLR 0x1A */
- 0x00, /* TWL6040_VIBDATR 0x1B */
- 0x00, /* TWL6040_HKCTL1 0x1C */
- 0x00, /* TWL6040_HKCTL2 0x1D */
- 0x00, /* TWL6040_GPOCTL 0x1E */
- 0x00, /* TWL6040_ALB 0x1F */
- 0x00, /* TWL6040_DLB 0x20 */
- 0x00, /* not used 0x21 */
- 0x00, /* not used 0x22 */
- 0x00, /* not used 0x23 */
- 0x00, /* not used 0x24 */
- 0x00, /* not used 0x25 */
- 0x00, /* not used 0x26 */
- 0x00, /* not used 0x27 */
- 0x00, /* TWL6040_TRIM1 0x28 */
- 0x00, /* TWL6040_TRIM2 0x29 */
- 0x00, /* TWL6040_TRIM3 0x2A */
- 0x00, /* TWL6040_HSOTRIM 0x2B */
- 0x00, /* TWL6040_HFOTRIM 0x2C */
- 0x09, /* TWL6040_ACCCTL 0x2D */
- 0x00, /* TWL6040_STATUS (ro) 0x2E */
-};
-
-/*
- * twl6040 vio/gnd registers:
- * registers under vio/gnd supply can be accessed
- * before the power-up sequence, after NRESPWRON goes high
- */
-static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = {
- TWL6040_REG_ASICID,
- TWL6040_REG_ASICREV,
- TWL6040_REG_INTID,
- TWL6040_REG_INTMR,
- TWL6040_REG_NCPCTL,
- TWL6040_REG_LDOCTL,
- TWL6040_REG_AMICBCTL,
- TWL6040_REG_DMICBCTL,
- TWL6040_REG_HKCTL1,
- TWL6040_REG_HKCTL2,
- TWL6040_REG_GPOCTL,
- TWL6040_REG_TRIM1,
- TWL6040_REG_TRIM2,
- TWL6040_REG_TRIM3,
- TWL6040_REG_HSOTRIM,
- TWL6040_REG_HFOTRIM,
- TWL6040_REG_ACCCTL,
- TWL6040_REG_STATUS,
+ 0x00, /* not used 0x00 */
+ 0x4B, /* REG_ASICID 0x01 (ro) */
+ 0x00, /* REG_ASICREV 0x02 (ro) */
+ 0x00, /* REG_INTID 0x03 */
+ 0x00, /* REG_INTMR 0x04 */
+ 0x00, /* REG_NCPCTRL 0x05 */
+ 0x00, /* REG_LDOCTL 0x06 */
+ 0x60, /* REG_HPPLLCTL 0x07 */
+ 0x00, /* REG_LPPLLCTL 0x08 */
+ 0x4A, /* REG_LPPLLDIV 0x09 */
+ 0x00, /* REG_AMICBCTL 0x0A */
+ 0x00, /* REG_DMICBCTL 0x0B */
+ 0x00, /* REG_MICLCTL 0x0C */
+ 0x00, /* REG_MICRCTL 0x0D */
+ 0x00, /* REG_MICGAIN 0x0E */
+ 0x1B, /* REG_LINEGAIN 0x0F */
+ 0x00, /* REG_HSLCTL 0x10 */
+ 0x00, /* REG_HSRCTL 0x11 */
+ 0x00, /* REG_HSGAIN 0x12 */
+ 0x00, /* REG_EARCTL 0x13 */
+ 0x00, /* REG_HFLCTL 0x14 */
+ 0x00, /* REG_HFLGAIN 0x15 */
+ 0x00, /* REG_HFRCTL 0x16 */
+ 0x00, /* REG_HFRGAIN 0x17 */
+ 0x00, /* REG_VIBCTLL 0x18 */
+ 0x00, /* REG_VIBDATL 0x19 */
+ 0x00, /* REG_VIBCTLR 0x1A */
+ 0x00, /* REG_VIBDATR 0x1B */
+ 0x00, /* REG_HKCTL1 0x1C */
+ 0x00, /* REG_HKCTL2 0x1D */
+ 0x00, /* REG_GPOCTL 0x1E */
+ 0x00, /* REG_ALB 0x1F */
+ 0x00, /* REG_DLB 0x20 */
+ 0x00, /* not used 0x21 */
+ 0x00, /* not used 0x22 */
+ 0x00, /* not used 0x23 */
+ 0x00, /* not used 0x24 */
+ 0x00, /* not used 0x25 */
+ 0x00, /* not used 0x26 */
+ 0x00, /* not used 0x27 */
+ 0x00, /* REG_TRIM1 0x28 */
+ 0x00, /* REG_TRIM2 0x29 */
+ 0x00, /* REG_TRIM3 0x2A */
+ 0x00, /* REG_HSOTRIM 0x2B */
+ 0x00, /* REG_HFOTRIM 0x2C */
+ 0x09, /* REG_ACCCTL 0x2D */
+ 0x00, /* REG_STATUS 0x2E (ro) */
+
+ 0x00, /* REG_SW_SHADOW 0x2F - Shadow, non HW register */
};
-/*
- * twl6040 vdd/vss registers:
- * registers under vdd/vss supplies can only be accessed
- * after the power-up sequence
- */
-static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
- TWL6040_REG_HPPLLCTL,
- TWL6040_REG_LPPLLCTL,
- TWL6040_REG_LPPLLDIV,
+/* List of registers to be restored after power up */
+static const int twl6040_restore_list[] = {
TWL6040_REG_MICLCTL,
TWL6040_REG_MICRCTL,
TWL6040_REG_MICGAIN,
@@ -202,12 +174,6 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = {
TWL6040_REG_HFLGAIN,
TWL6040_REG_HFRCTL,
TWL6040_REG_HFRGAIN,
- TWL6040_REG_VIBCTLL,
- TWL6040_REG_VIBDATL,
- TWL6040_REG_VIBCTLR,
- TWL6040_REG_VIBDATR,
- TWL6040_REG_ALB,
- TWL6040_REG_DLB,
};
/* set of rates for each pll: low-power and high-performance */
@@ -275,8 +241,12 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec,
if (reg >= TWL6040_CACHEREGNUM)
return -EIO;
- value = twl6040_reg_read(twl6040, reg);
- twl6040_write_reg_cache(codec, reg, value);
+ if (likely(reg < TWL6040_REG_SW_SHADOW)) {
+ value = twl6040_reg_read(twl6040, reg);
+ twl6040_write_reg_cache(codec, reg, value);
+ } else {
+ value = twl6040_read_reg_cache(codec, reg);
+ }
return value;
}
@@ -293,59 +263,51 @@ static int twl6040_write(struct snd_soc_codec *codec,
return -EIO;
twl6040_write_reg_cache(codec, reg, value);
- return twl6040_reg_write(twl6040, reg, value);
+ if (likely(reg < TWL6040_REG_SW_SHADOW))
+ return twl6040_reg_write(twl6040, reg, value);
+ else
+ return 0;
}
-static void twl6040_init_vio_regs(struct snd_soc_codec *codec)
+static void twl6040_init_chip(struct snd_soc_codec *codec)
{
- u8 *cache = codec->reg_cache;
- int reg, i;
-
- for (i = 0; i < TWL6040_VIOREGNUM; i++) {
- reg = twl6040_vio_reg[i];
- /*
- * skip read-only registers (ASICID, ASICREV, STATUS)
- * and registers shared among MFD children
- */
- switch (reg) {
- case TWL6040_REG_ASICID:
- case TWL6040_REG_ASICREV:
- case TWL6040_REG_INTID:
- case TWL6040_REG_INTMR:
- case TWL6040_REG_NCPCTL:
- case TWL6040_REG_LDOCTL:
- case TWL6040_REG_GPOCTL:
- case TWL6040_REG_ACCCTL:
- case TWL6040_REG_STATUS:
- continue;
- default:
- break;
- }
- twl6040_write(codec, reg, cache[reg]);
- }
+ struct twl6040 *twl6040 = codec->control_data;
+ u8 val;
+
+ /* Update reg_cache: ASICREV, and TRIM values */
+ val = twl6040_get_revid(twl6040);
+ twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val);
+
+ twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM1);
+ twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM2);
+ twl6040_read_reg_volatile(codec, TWL6040_REG_TRIM3);
+ twl6040_read_reg_volatile(codec, TWL6040_REG_HSOTRIM);
+ twl6040_read_reg_volatile(codec, TWL6040_REG_HFOTRIM);
+
+ /* Change chip defaults */
+ /* No imput selected for microphone amplifiers */
+ twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18);
+ twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18);
+
+ /*
+ * We need to lower the default gain values, so the ramp code
+ * can work correctly for the first playback.
+ * This reduces the pop noise heard at the first playback.
+ */
+ twl6040_write_reg_cache(codec, TWL6040_REG_HSGAIN, 0xff);
+ twl6040_write_reg_cache(codec, TWL6040_REG_EARCTL, 0x1e);
+ twl6040_write_reg_cache(codec, TWL6040_REG_HFLGAIN, 0x1d);
+ twl6040_write_reg_cache(codec, TWL6040_REG_HFRGAIN, 0x1d);
+ twl6040_write_reg_cache(codec, TWL6040_REG_LINEGAIN, 0);
}
-static void twl6040_init_vdd_regs(struct snd_soc_codec *codec)
+static void twl6040_restore_regs(struct snd_soc_codec *codec)
{
u8 *cache = codec->reg_cache;
int reg, i;
- for (i = 0; i < TWL6040_VDDREGNUM; i++) {
- reg = twl6040_vdd_reg[i];
- /* skip vibra and PLL registers */
- switch (reg) {
- case TWL6040_REG_VIBCTLL:
- case TWL6040_REG_VIBDATL:
- case TWL6040_REG_VIBCTLR:
- case TWL6040_REG_VIBDATR:
- case TWL6040_REG_HPPLLCTL:
- case TWL6040_REG_LPPLLCTL:
- case TWL6040_REG_LPPLLDIV:
- continue;
- default:
- break;
- }
-
+ for (i = 0; i < ARRAY_SIZE(twl6040_restore_list); i++) {
+ reg = twl6040_restore_list[i];
twl6040_write(codec, reg, cache[reg]);
}
}
@@ -524,18 +486,17 @@ static inline int twl6040_hf_ramp_step(struct snd_soc_codec *codec,
static void twl6040_pga_hs_work(struct work_struct *work)
{
struct twl6040_data *priv =
- container_of(work, struct twl6040_data, hs_delayed_work.work);
+ container_of(work, struct twl6040_data, headset.work.work);
struct snd_soc_codec *codec = priv->codec;
struct twl6040_output *headset = &priv->headset;
- unsigned int delay = headset->step_delay;
int i, headset_complete;
/* do we need to ramp at all ? */
if (headset->ramp == TWL6040_RAMP_NONE)
return;
- /* HS PGA volumes have 4 bits of resolution to ramp */
- for (i = 0; i <= 16; i++) {
+ /* HS PGA gain range: 0x0 - 0xf (0 - 15) */
+ for (i = 0; i < 16; i++) {
headset_complete = twl6040_hs_ramp_step(codec,
headset->left_step,
headset->right_step);
@@ -544,15 +505,8 @@ static void twl6040_pga_hs_work(struct work_struct *work)
if (headset_complete)
break;
- /*
- * TODO: tune: delay is longer over 0dB
- * as increases are larger.
- */
- if (i >= 8)
- schedule_timeout_interruptible(msecs_to_jiffies(delay +
- (delay >> 1)));
- else
- schedule_timeout_interruptible(msecs_to_jiffies(delay));
+ schedule_timeout_interruptible(
+ msecs_to_jiffies(headset->step_delay));
}
if (headset->ramp == TWL6040_RAMP_DOWN) {
@@ -567,18 +521,18 @@ static void twl6040_pga_hs_work(struct work_struct *work)
static void twl6040_pga_hf_work(struct work_struct *work)
{
struct twl6040_data *priv =
- container_of(work, struct twl6040_data, hf_delayed_work.work);
+ container_of(work, struct twl6040_data, handsfree.work.work);
struct snd_soc_codec *codec = priv->codec;
struct twl6040_output *handsfree = &priv->handsfree;
- unsigned int delay = handsfree->step_delay;
int i, handsfree_complete;
/* do we need to ramp at all ? */
if (handsfree->ramp == TWL6040_RAMP_NONE)
return;
- /* HF PGA volumes have 5 bits of resolution to ramp */
- for (i = 0; i <= 32; i++) {
+ /*
+ * HF PGA gain range: 0x00 - 0x1d (0 - 29) */
+ for (i = 0; i < 30; i++) {
handsfree_complete = twl6040_hf_ramp_step(codec,
handsfree->left_step,
handsfree->right_step);
@@ -587,15 +541,8 @@ static void twl6040_pga_hf_work(struct work_struct *work)
if (handsfree_complete)
break;
- /*
- * TODO: tune: delay is longer over 0dB
- * as increases are larger.
- */
- if (i >= 16)
- schedule_timeout_interruptible(msecs_to_jiffies(delay +
- (delay >> 1)));
- else
- schedule_timeout_interruptible(msecs_to_jiffies(delay));
+ schedule_timeout_interruptible(
+ msecs_to_jiffies(handsfree->step_delay));
}
@@ -607,36 +554,40 @@ static void twl6040_pga_hf_work(struct work_struct *work)
handsfree->ramp = TWL6040_RAMP_NONE;
}
-static int pga_event(struct snd_soc_dapm_widget *w,
+static int out_drv_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
struct twl6040_output *out;
struct delayed_work *work;
- struct workqueue_struct *queue;
switch (w->shift) {
- case 2:
- case 3:
+ case 2: /* Headset output driver */
out = &priv->headset;
- work = &priv->hs_delayed_work;
- queue = priv->hs_workqueue;
+ work = &out->work;
+ /*
+ * Make sure, that we do not mess up variables for already
+ * executing work.
+ */
+ cancel_delayed_work_sync(work);
+
out->left_step = priv->hs_left_step;
out->right_step = priv->hs_right_step;
out->step_delay = 5; /* 5 ms between volume ramp steps */
break;
- case 4:
+ case 4: /* Handsfree output driver */
out = &priv->handsfree;
- work = &priv->hf_delayed_work;
- queue = priv->hf_workqueue;
+ work = &out->work;
+ /*
+ * Make sure, that we do not mess up variables for already
+ * executing work.
+ */
+ cancel_delayed_work_sync(work);
+
out->left_step = priv->hf_left_step;
out->right_step = priv->hf_right_step;
out->step_delay = 5; /* 5 ms between volume ramp steps */
- if (SND_SOC_DAPM_EVENT_ON(event))
- priv->non_lp++;
- else
- priv->non_lp--;
break;
default:
return -1;
@@ -648,31 +599,25 @@ static int pga_event(struct snd_soc_dapm_widget *w,
break;
/* don't use volume ramp for power-up */
+ out->ramp = TWL6040_RAMP_UP;
out->left_step = out->left_vol;
out->right_step = out->right_vol;
- if (!delayed_work_pending(work)) {
- out->ramp = TWL6040_RAMP_UP;
- queue_delayed_work(queue, work,
- msecs_to_jiffies(1));
- }
+ queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
break;
case SND_SOC_DAPM_PRE_PMD:
if (!out->active)
break;
- if (!delayed_work_pending(work)) {
- /* use volume ramp for power-down */
- out->ramp = TWL6040_RAMP_DOWN;
- INIT_COMPLETION(out->ramp_done);
+ /* use volume ramp for power-down */
+ out->ramp = TWL6040_RAMP_DOWN;
+ INIT_COMPLETION(out->ramp_done);
- queue_delayed_work(queue, work,
- msecs_to_jiffies(1));
+ queue_delayed_work(priv->workqueue, work, msecs_to_jiffies(1));
- wait_for_completion_timeout(&out->ramp_done,
- msecs_to_jiffies(2000));
- }
+ wait_for_completion_timeout(&out->ramp_done,
+ msecs_to_jiffies(2000));
break;
}
@@ -683,7 +628,7 @@ static int pga_event(struct snd_soc_dapm_widget *w,
static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
{
int hslctl, hsrctl;
- int mask = TWL6040_HSDRVMODEL | TWL6040_HSDACMODEL;
+ int mask = TWL6040_HSDRVMODE | TWL6040_HSDACMODE;
hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
@@ -705,11 +650,31 @@ static int headset_power_mode(struct snd_soc_codec *codec, int high_perf)
static int twl6040_hs_dac_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
+ struct snd_soc_codec *codec = w->codec;
+ u8 hslctl, hsrctl;
+
+ /*
+ * Workaround for Headset DC offset caused pop noise:
+ * Both HS DAC need to be turned on (before the HS driver) and off at
+ * the same time.
+ */
+ hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL);
+ hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL);
+ if (SND_SOC_DAPM_EVENT_ON(event)) {
+ hslctl |= TWL6040_HSDACENA;
+ hsrctl |= TWL6040_HSDACENA;
+ } else {
+ hslctl &= ~TWL6040_HSDACENA;
+ hsrctl &= ~TWL6040_HSDACENA;
+ }
+ twl6040_write(codec, TWL6040_REG_HSLCTL, hslctl);
+ twl6040_write(codec, TWL6040_REG_HSRCTL, hsrctl);
+
msleep(1);
return 0;
}
-static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
+static int twl6040_ep_drv_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
@@ -717,18 +682,12 @@ static int twl6040_power_mode_event(struct snd_soc_dapm_widget *w,
int ret = 0;
if (SND_SOC_DAPM_EVENT_ON(event)) {
- priv->non_lp++;
- if (!strcmp(w->name, "Earphone Driver")) {
- /* Earphone doesn't support low power mode */
- priv->hs_power_mode_locked = 1;
- ret = headset_power_mode(codec, 1);
- }
+ /* Earphone doesn't support low power mode */
+ priv->hs_power_mode_locked = 1;
+ ret = headset_power_mode(codec, 1);
} else {
- priv->non_lp--;
- if (!strcmp(w->name, "Earphone Driver")) {
- priv->hs_power_mode_locked = 0;
- ret = headset_power_mode(codec, priv->hs_power_mode);
- }
+ priv->hs_power_mode_locked = 0;
+ ret = headset_power_mode(codec, priv->hs_power_mode);
}
msleep(1);
@@ -770,7 +729,7 @@ EXPORT_SYMBOL_GPL(twl6040_hs_jack_detect);
static void twl6040_accessory_work(struct work_struct *work)
{
struct twl6040_data *priv = container_of(work,
- struct twl6040_data, delayed_work.work);
+ struct twl6040_data, hs_jack.work.work);
struct snd_soc_codec *codec = priv->codec;
struct twl6040_jack_data *hs_jack = &priv->hs_jack;
@@ -781,15 +740,10 @@ static void twl6040_accessory_work(struct work_struct *work)
static irqreturn_t twl6040_audio_handler(int irq, void *data)
{
struct snd_soc_codec *codec = data;
- struct twl6040 *twl6040 = codec->control_data;
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
- u8 intid;
- intid = twl6040_reg_read(twl6040, TWL6040_REG_INTID);
-
- if ((intid & TWL6040_PLUGINT) || (intid & TWL6040_UNPLUGINT))
- queue_delayed_work(priv->workqueue, &priv->delayed_work,
- msecs_to_jiffies(200));
+ queue_delayed_work(priv->workqueue, &priv->hs_jack.work,
+ msecs_to_jiffies(200));
return IRQ_HANDLED;
}
@@ -803,25 +757,27 @@ static int twl6040_put_volsw(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int ret;
- unsigned int reg = mc->reg;
/* For HS and HF we shadow the values and only actually write
* them out when active in order to ensure the amplifier comes on
* as quietly as possible. */
- switch (reg) {
+ switch (mc->reg) {
case TWL6040_REG_HSGAIN:
out = &twl6040_priv->headset;
break;
- default:
+ case TWL6040_REG_HFLGAIN:
+ out = &twl6040_priv->handsfree;
break;
+ default:
+ dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
+ __func__, mc->reg);
+ return -EINVAL;
}
- if (out) {
- out->left_vol = ucontrol->value.integer.value[0];
- out->right_vol = ucontrol->value.integer.value[1];
- if (!out->active)
- return 1;
- }
+ out->left_vol = ucontrol->value.integer.value[0];
+ out->right_vol = ucontrol->value.integer.value[1];
+ if (!out->active)
+ return 1;
ret = snd_soc_put_volsw(kcontrol, ucontrol);
if (ret < 0)
@@ -838,112 +794,42 @@ static int twl6040_get_volsw(struct snd_kcontrol *kcontrol,
struct twl6040_output *out = &twl6040_priv->headset;
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
- unsigned int reg = mc->reg;
- switch (reg) {
+ switch (mc->reg) {
case TWL6040_REG_HSGAIN:
out = &twl6040_priv->headset;
- ucontrol->value.integer.value[0] = out->left_vol;
- ucontrol->value.integer.value[1] = out->right_vol;
- return 0;
-
- default:
break;
- }
-
- return snd_soc_get_volsw(kcontrol, ucontrol);
-}
-
-static int twl6040_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
- struct twl6040_output *out = NULL;
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- int ret;
- unsigned int reg = mc->reg;
-
- /* For HS and HF we shadow the values and only actually write
- * them out when active in order to ensure the amplifier comes on
- * as quietly as possible. */
- switch (reg) {
case TWL6040_REG_HFLGAIN:
- case TWL6040_REG_HFRGAIN:
out = &twl6040_priv->handsfree;
break;
default:
- break;
- }
-
- if (out) {
- out->left_vol = ucontrol->value.integer.value[0];
- out->right_vol = ucontrol->value.integer.value[1];
- if (!out->active)
- return 1;
+ dev_warn(codec->dev, "%s: Unexpected register: 0x%02x\n",
+ __func__, mc->reg);
+ return -EINVAL;
}
- ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
- if (ret < 0)
- return ret;
-
- return 1;
+ ucontrol->value.integer.value[0] = out->left_vol;
+ ucontrol->value.integer.value[1] = out->right_vol;
+ return 0;
}
-static int twl6040_get_volsw_2r(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int twl6040_soc_dapm_put_vibra_enum(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- struct twl6040_data *twl6040_priv = snd_soc_codec_get_drvdata(codec);
- struct twl6040_output *out = &twl6040_priv->handsfree;
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- unsigned int reg = mc->reg;
-
- /* If these are cached registers use the cache */
- switch (reg) {
- case TWL6040_REG_HFLGAIN:
- case TWL6040_REG_HFRGAIN:
- out = &twl6040_priv->handsfree;
- ucontrol->value.integer.value[0] = out->left_vol;
- ucontrol->value.integer.value[1] = out->right_vol;
- return 0;
-
- default:
- break;
- }
-
- return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+ struct snd_soc_dapm_widget_list *wlist = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_dapm_widget *widget = wlist->widgets[0];
+ struct snd_soc_codec *codec = widget->codec;
+ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
+ unsigned int val;
+
+ /* Do not allow changes while Input/FF efect is running */
+ val = twl6040_read_reg_volatile(codec, e->reg);
+ if (val & TWL6040_VIBENA && !(val & TWL6040_VIBSEL))
+ return -EBUSY;
+
+ return snd_soc_dapm_put_enum_double(kcontrol, ucontrol);
}
-/* double control with volume update */
-#define SOC_TWL6040_DOUBLE_TLV(xname, xreg, shift_left, shift_right, xmax,\
- xinvert, tlv_array)\
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE,\
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, .get = twl6040_get_volsw, \
- .put = twl6040_put_volsw, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
- .max = xmax, .platform_max = xmax, .invert = xinvert} }
-
-/* double control with volume update */
-#define SOC_TWL6040_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax,\
- xinvert, tlv_array)\
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_READWRITE | \
- SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw_2r, \
- .get = twl6040_get_volsw_2r, .put = twl6040_put_volsw_2r_vu, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
- .rshift = xshift, .max = xmax, .invert = xinvert}, }
-
/*
* MICATT volume control:
* from -6 to 0 dB in 6 dB steps
@@ -1015,6 +901,19 @@ static const struct soc_enum twl6040_hf_enum[] = {
twl6040_hf_texts),
};
+static const char *twl6040_vibrapath_texts[] = {
+ "Input FF", "Audio PDM"
+};
+
+static const struct soc_enum twl6040_vibra_enum[] = {
+ SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLL, 1,
+ ARRAY_SIZE(twl6040_vibrapath_texts),
+ twl6040_vibrapath_texts),
+ SOC_ENUM_SINGLE(TWL6040_REG_VIBCTLR, 1,
+ ARRAY_SIZE(twl6040_vibrapath_texts),
+ twl6040_vibrapath_texts),
+};
+
static const struct snd_kcontrol_new amicl_control =
SOC_DAPM_ENUM("Route", twl6040_enum[0]);
@@ -1035,8 +934,25 @@ static const struct snd_kcontrol_new hfl_mux_controls =
static const struct snd_kcontrol_new hfr_mux_controls =
SOC_DAPM_ENUM("Route", twl6040_hf_enum[1]);
-static const struct snd_kcontrol_new ep_driver_switch_controls =
- SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
+static const struct snd_kcontrol_new ep_path_enable_control =
+ SOC_DAPM_SINGLE("Switch", TWL6040_REG_SW_SHADOW, 0, 1, 0);
+
+static const struct snd_kcontrol_new auxl_switch_control =
+ SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFLCTL, 6, 1, 0);
+
+static const struct snd_kcontrol_new auxr_switch_control =
+ SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 6, 1, 0);
+
+/* Vibra playback switches */
+static const struct snd_kcontrol_new vibral_mux_controls =
+ SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[0],
+ snd_soc_dapm_get_enum_double,
+ twl6040_soc_dapm_put_vibra_enum);
+
+static const struct snd_kcontrol_new vibrar_mux_controls =
+ SOC_DAPM_ENUM_EXT("Route", twl6040_vibra_enum[1],
+ snd_soc_dapm_get_enum_double,
+ twl6040_soc_dapm_put_vibra_enum);
/* Headset power mode */
static const char *twl6040_power_mode_texts[] = {
@@ -1097,6 +1013,28 @@ static int twl6040_pll_put_enum(struct snd_kcontrol *kcontrol,
return 0;
}
+int twl6040_get_dl1_gain(struct snd_soc_codec *codec)
+{
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+
+ if (snd_soc_dapm_get_pin_status(dapm, "EP"))
+ return -1; /* -1dB */
+
+ if (snd_soc_dapm_get_pin_status(dapm, "HSOR") ||
+ snd_soc_dapm_get_pin_status(dapm, "HSOL")) {
+
+ u8 val = snd_soc_read(codec, TWL6040_REG_HSLCTL);
+ if (val & TWL6040_HSDACMODE)
+ /* HSDACL in LP mode */
+ return -8; /* -8dB */
+ else
+ /* HSDACL in HP mode */
+ return -1; /* -1dB */
+ }
+ return 0; /* 0dB */
+}
+EXPORT_SYMBOL_GPL(twl6040_get_dl1_gain);
+
int twl6040_get_clk_id(struct snd_soc_codec *codec)
{
struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
@@ -1105,6 +1043,28 @@ int twl6040_get_clk_id(struct snd_soc_codec *codec)
}
EXPORT_SYMBOL_GPL(twl6040_get_clk_id);
+int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim)
+{
+ if (unlikely(trim >= TWL6040_TRIM_INVAL))
+ return -EINVAL;
+
+ return twl6040_read_reg_cache(codec, TWL6040_REG_TRIM1 + trim);
+}
+EXPORT_SYMBOL_GPL(twl6040_get_trim_value);
+
+int twl6040_get_hs_step_size(struct snd_soc_codec *codec)
+{
+ struct twl6040 *twl6040 = codec->control_data;
+
+ if (twl6040_get_revid(twl6040) < TWL6040_REV_ES1_2)
+ /* For ES under ES_1.3 HS step is 2 mV */
+ return 2;
+ else
+ /* For ES_1.3 HS step is 1 mV */
+ return 1;
+}
+EXPORT_SYMBOL_GPL(twl6040_get_hs_step_size);
+
static const struct snd_kcontrol_new twl6040_snd_controls[] = {
/* Capture gains */
SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -1117,10 +1077,12 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
TWL6040_REG_LINEGAIN, 0, 3, 7, 0, afm_amp_tlv),
/* Playback gains */
- SOC_TWL6040_DOUBLE_TLV("Headset Playback Volume",
- TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
- SOC_TWL6040_DOUBLE_R_TLV("Handsfree Playback Volume",
- TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
+ SOC_DOUBLE_EXT_TLV("Headset Playback Volume",
+ TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, twl6040_get_volsw,
+ twl6040_put_volsw, hs_tlv),
+ SOC_DOUBLE_R_EXT_TLV("Handsfree Playback Volume",
+ TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1,
+ twl6040_get_volsw, twl6040_put_volsw, hf_tlv),
SOC_SINGLE_TLV("Earphone Playback Volume",
TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
@@ -1146,6 +1108,10 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("HFL"),
SND_SOC_DAPM_OUTPUT("HFR"),
SND_SOC_DAPM_OUTPUT("EP"),
+ SND_SOC_DAPM_OUTPUT("AUXL"),
+ SND_SOC_DAPM_OUTPUT("AUXR"),
+ SND_SOC_DAPM_OUTPUT("VIBRAL"),
+ SND_SOC_DAPM_OUTPUT("VIBRAR"),
/* Analog input muxes for the capture amplifiers */
SND_SOC_DAPM_MUX("Analog Left Capture Route",
@@ -1172,69 +1138,86 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
TWL6040_REG_MICRCTL, 2, 0),
/* Microphone bias */
- SND_SOC_DAPM_MICBIAS("Headset Mic Bias",
- TWL6040_REG_AMICBCTL, 0, 0),
- SND_SOC_DAPM_MICBIAS("Main Mic Bias",
- TWL6040_REG_AMICBCTL, 4, 0),
- SND_SOC_DAPM_MICBIAS("Digital Mic1 Bias",
- TWL6040_REG_DMICBCTL, 0, 0),
- SND_SOC_DAPM_MICBIAS("Digital Mic2 Bias",
- TWL6040_REG_DMICBCTL, 4, 0),
+ SND_SOC_DAPM_SUPPLY("Headset Mic Bias",
+ TWL6040_REG_AMICBCTL, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Main Mic Bias",
+ TWL6040_REG_AMICBCTL, 4, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Digital Mic1 Bias",
+ TWL6040_REG_DMICBCTL, 0, 0, NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Digital Mic2 Bias",
+ TWL6040_REG_DMICBCTL, 4, 0, NULL, 0),
/* DACs */
- SND_SOC_DAPM_DAC_E("HSDAC Left", "Headset Playback",
- TWL6040_REG_HSLCTL, 0, 0,
- twl6040_hs_dac_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_DAC_E("HSDAC Right", "Headset Playback",
- TWL6040_REG_HSRCTL, 0, 0,
- twl6040_hs_dac_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_DAC_E("HFDAC Left", "Handsfree Playback",
- TWL6040_REG_HFLCTL, 0, 0,
- twl6040_power_mode_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
- SND_SOC_DAPM_DAC_E("HFDAC Right", "Handsfree Playback",
- TWL6040_REG_HFRCTL, 0, 0,
- twl6040_power_mode_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
-
- SND_SOC_DAPM_MUX("HF Left Playback",
+ SND_SOC_DAPM_DAC("HSDAC Left", "Headset Playback", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("HSDAC Right", "Headset Playback", SND_SOC_NOPM, 0, 0),
+ SND_SOC_DAPM_DAC("HFDAC Left", "Handsfree Playback",
+ TWL6040_REG_HFLCTL, 0, 0),
+ SND_SOC_DAPM_DAC("HFDAC Right", "Handsfree Playback",
+ TWL6040_REG_HFRCTL, 0, 0),
+ /* Virtual DAC for vibra path (DL4 channel) */
+ SND_SOC_DAPM_DAC("VIBRA DAC", "Vibra Playback",
+ SND_SOC_NOPM, 0, 0),
+
+ SND_SOC_DAPM_MUX("Handsfree Left Playback",
SND_SOC_NOPM, 0, 0, &hfl_mux_controls),
- SND_SOC_DAPM_MUX("HF Right Playback",
+ SND_SOC_DAPM_MUX("Handsfree Right Playback",
SND_SOC_NOPM, 0, 0, &hfr_mux_controls),
/* Analog playback Muxes */
- SND_SOC_DAPM_MUX("HS Left Playback",
+ SND_SOC_DAPM_MUX("Headset Left Playback",
SND_SOC_NOPM, 0, 0, &hsl_mux_controls),
- SND_SOC_DAPM_MUX("HS Right Playback",
+ SND_SOC_DAPM_MUX("Headset Right Playback",
SND_SOC_NOPM, 0, 0, &hsr_mux_controls),
+ SND_SOC_DAPM_MUX("Vibra Left Playback", SND_SOC_NOPM, 0, 0,
+ &vibral_mux_controls),
+ SND_SOC_DAPM_MUX("Vibra Right Playback", SND_SOC_NOPM, 0, 0,
+ &vibrar_mux_controls),
+
+ SND_SOC_DAPM_SWITCH("Earphone Playback", SND_SOC_NOPM, 0, 0,
+ &ep_path_enable_control),
+ SND_SOC_DAPM_SWITCH("AUXL Playback", SND_SOC_NOPM, 0, 0,
+ &auxl_switch_control),
+ SND_SOC_DAPM_SWITCH("AUXR Playback", SND_SOC_NOPM, 0, 0,
+ &auxr_switch_control),
+
/* Analog playback drivers */
- SND_SOC_DAPM_OUT_DRV_E("Handsfree Left Driver",
+ SND_SOC_DAPM_OUT_DRV_E("HF Left Driver",
TWL6040_REG_HFLCTL, 4, 0, NULL, 0,
- pga_event,
+ out_drv_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_OUT_DRV_E("Handsfree Right Driver",
+ SND_SOC_DAPM_OUT_DRV_E("HF Right Driver",
TWL6040_REG_HFRCTL, 4, 0, NULL, 0,
- pga_event,
+ out_drv_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_OUT_DRV_E("Headset Left Driver",
+ SND_SOC_DAPM_OUT_DRV_E("HS Left Driver",
TWL6040_REG_HSLCTL, 2, 0, NULL, 0,
- pga_event,
+ out_drv_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_OUT_DRV_E("Headset Right Driver",
+ SND_SOC_DAPM_OUT_DRV_E("HS Right Driver",
TWL6040_REG_HSRCTL, 2, 0, NULL, 0,
- pga_event,
+ out_drv_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_SWITCH_E("Earphone Driver",
- SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls,
- twl6040_power_mode_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUT_DRV_E("Earphone Driver",
+ TWL6040_REG_EARCTL, 0, 0, NULL, 0,
+ twl6040_ep_drv_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+ SND_SOC_DAPM_OUT_DRV("Vibra Left Driver",
+ TWL6040_REG_VIBCTLL, 0, 0, NULL, 0),
+ SND_SOC_DAPM_OUT_DRV("Vibra Right Driver",
+ TWL6040_REG_VIBCTLR, 0, 0, NULL, 0),
+
+ SND_SOC_DAPM_SUPPLY("Vibra Left Control", TWL6040_REG_VIBCTLL, 2, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("Vibra Right Control", TWL6040_REG_VIBCTLR, 2, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY_S("HSDAC Power", 1, SND_SOC_NOPM, 0, 0,
+ twl6040_hs_dac_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
/* Analog playback PGAs */
- SND_SOC_DAPM_PGA("HFDAC Left PGA",
+ SND_SOC_DAPM_PGA("HF Left PGA",
TWL6040_REG_HFLCTL, 1, 0, NULL, 0),
- SND_SOC_DAPM_PGA("HFDAC Right PGA",
+ SND_SOC_DAPM_PGA("HF Right PGA",
TWL6040_REG_HFRCTL, 1, 0, NULL, 0),
};
@@ -1256,52 +1239,62 @@ static const struct snd_soc_dapm_route intercon[] = {
{"ADC Right", NULL, "MicAmpR"},
/* AFM path */
- {"AFMAmpL", "NULL", "AFML"},
- {"AFMAmpR", "NULL", "AFMR"},
+ {"AFMAmpL", NULL, "AFML"},
+ {"AFMAmpR", NULL, "AFMR"},
- {"HS Left Playback", "HS DAC", "HSDAC Left"},
- {"HS Left Playback", "Line-In amp", "AFMAmpL"},
+ {"HSDAC Left", NULL, "HSDAC Power"},
+ {"HSDAC Right", NULL, "HSDAC Power"},
- {"HS Right Playback", "HS DAC", "HSDAC Right"},
- {"HS Right Playback", "Line-In amp", "AFMAmpR"},
+ {"Headset Left Playback", "HS DAC", "HSDAC Left"},
+ {"Headset Left Playback", "Line-In amp", "AFMAmpL"},
- {"Headset Left Driver", "NULL", "HS Left Playback"},
- {"Headset Right Driver", "NULL", "HS Right Playback"},
+ {"Headset Right Playback", "HS DAC", "HSDAC Right"},
+ {"Headset Right Playback", "Line-In amp", "AFMAmpR"},
- {"HSOL", NULL, "Headset Left Driver"},
- {"HSOR", NULL, "Headset Right Driver"},
+ {"HS Left Driver", NULL, "Headset Left Playback"},
+ {"HS Right Driver", NULL, "Headset Right Playback"},
+
+ {"HSOL", NULL, "HS Left Driver"},
+ {"HSOR", NULL, "HS Right Driver"},
/* Earphone playback path */
- {"Earphone Driver", "Switch", "HSDAC Left"},
+ {"Earphone Playback", "Switch", "HSDAC Left"},
+ {"Earphone Driver", NULL, "Earphone Playback"},
{"EP", NULL, "Earphone Driver"},
- {"HF Left Playback", "HF DAC", "HFDAC Left"},
- {"HF Left Playback", "Line-In amp", "AFMAmpL"},
+ {"Handsfree Left Playback", "HF DAC", "HFDAC Left"},
+ {"Handsfree Left Playback", "Line-In amp", "AFMAmpL"},
- {"HF Right Playback", "HF DAC", "HFDAC Right"},
- {"HF Right Playback", "Line-In amp", "AFMAmpR"},
+ {"Handsfree Right Playback", "HF DAC", "HFDAC Right"},
+ {"Handsfree Right Playback", "Line-In amp", "AFMAmpR"},
- {"HFDAC Left PGA", NULL, "HF Left Playback"},
- {"HFDAC Right PGA", NULL, "HF Right Playback"},
+ {"HF Left PGA", NULL, "Handsfree Left Playback"},
+ {"HF Right PGA", NULL, "Handsfree Right Playback"},
- {"Handsfree Left Driver", "Switch", "HFDAC Left PGA"},
- {"Handsfree Right Driver", "Switch", "HFDAC Right PGA"},
+ {"HF Left Driver", NULL, "HF Left PGA"},
+ {"HF Right Driver", NULL, "HF Right PGA"},
- {"HFL", NULL, "Handsfree Left Driver"},
- {"HFR", NULL, "Handsfree Right Driver"},
-};
+ {"HFL", NULL, "HF Left Driver"},
+ {"HFR", NULL, "HF Right Driver"},
-static int twl6040_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
+ {"AUXL Playback", "Switch", "HF Left PGA"},
+ {"AUXR Playback", "Switch", "HF Right PGA"},
- snd_soc_dapm_new_controls(dapm, twl6040_dapm_widgets,
- ARRAY_SIZE(twl6040_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
- snd_soc_dapm_new_widgets(dapm);
+ {"AUXL", NULL, "AUXL Playback"},
+ {"AUXR", NULL, "AUXR Playback"},
- return 0;
-}
+ /* Vibrator paths */
+ {"Vibra Left Playback", "Audio PDM", "VIBRA DAC"},
+ {"Vibra Right Playback", "Audio PDM", "VIBRA DAC"},
+
+ {"Vibra Left Driver", NULL, "Vibra Left Playback"},
+ {"Vibra Right Driver", NULL, "Vibra Right Playback"},
+ {"Vibra Left Driver", NULL, "Vibra Left Control"},
+ {"Vibra Right Driver", NULL, "Vibra Right Control"},
+
+ {"VIBRAL", NULL, "Vibra Left Driver"},
+ {"VIBRAR", NULL, "Vibra Right Driver"},
+};
static int twl6040_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
@@ -1325,8 +1318,7 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
priv->codec_powered = 1;
- /* initialize vdd/vss registers with reg_cache */
- twl6040_init_vdd_regs(codec);
+ twl6040_restore_regs(codec);
/* Set external boost GPO */
twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02);
@@ -1380,13 +1372,6 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
rate);
return -EINVAL;
}
- /* Capture is not supported with 17.64MHz sysclk */
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- dev_err(codec->dev,
- "capture mode is not supported at %dHz\n",
- rate);
- return -EINVAL;
- }
priv->sysclk = 17640000;
break;
case 8000:
@@ -1419,13 +1404,6 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
return -EINVAL;
}
- if ((priv->sysclk == 17640000) && priv->non_lp) {
- dev_err(codec->dev,
- "some enabled paths aren't supported at %dHz\n",
- priv->sysclk);
- return -EPERM;
- }
-
ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk);
if (ret) {
dev_err(codec->dev, "Can not set PLL (%d)\n", ret);
@@ -1455,7 +1433,7 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
return 0;
}
-static struct snd_soc_dai_ops twl6040_dai_ops = {
+static const struct snd_soc_dai_ops twl6040_dai_ops = {
.startup = twl6040_startup,
.hw_params = twl6040_hw_params,
.prepare = twl6040_prepare,
@@ -1464,11 +1442,11 @@ static struct snd_soc_dai_ops twl6040_dai_ops = {
static struct snd_soc_dai_driver twl6040_dai[] = {
{
- .name = "twl6040-hifi",
+ .name = "twl6040-legacy",
.playback = {
.stream_name = "Playback",
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 5,
.rates = TWL6040_RATES,
.formats = TWL6040_FORMATS,
},
@@ -1518,8 +1496,8 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
.name = "twl6040-vib",
.playback = {
.stream_name = "Vibra Playback",
- .channels_min = 2,
- .channels_max = 2,
+ .channels_min = 1,
+ .channels_max = 1,
.rates = SNDRV_PCM_RATE_CONTINUOUS,
.formats = TWL6040_FORMATS,
},
@@ -1528,7 +1506,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = {
};
#ifdef CONFIG_PM
-static int twl6040_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int twl6040_suspend(struct snd_soc_codec *codec)
{
twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -1586,33 +1564,21 @@ static int twl6040_probe(struct snd_soc_codec *codec)
goto work_err;
}
- priv->workqueue = create_singlethread_workqueue("twl6040-codec");
+ priv->workqueue = alloc_workqueue("twl6040-codec", 0, 0);
if (!priv->workqueue) {
ret = -ENOMEM;
goto work_err;
}
- INIT_DELAYED_WORK(&priv->delayed_work, twl6040_accessory_work);
+ INIT_DELAYED_WORK(&priv->hs_jack.work, twl6040_accessory_work);
+ INIT_DELAYED_WORK(&priv->headset.work, twl6040_pga_hs_work);
+ INIT_DELAYED_WORK(&priv->handsfree.work, twl6040_pga_hf_work);
mutex_init(&priv->mutex);
init_completion(&priv->headset.ramp_done);
init_completion(&priv->handsfree.ramp_done);
- priv->hf_workqueue = create_singlethread_workqueue("twl6040-hf");
- if (priv->hf_workqueue == NULL) {
- ret = -ENOMEM;
- goto hfwq_err;
- }
- priv->hs_workqueue = create_singlethread_workqueue("twl6040-hs");
- if (priv->hs_workqueue == NULL) {
- ret = -ENOMEM;
- goto hswq_err;
- }
-
- INIT_DELAYED_WORK(&priv->hs_delayed_work, twl6040_pga_hs_work);
- INIT_DELAYED_WORK(&priv->hf_delayed_work, twl6040_pga_hf_work);
-
ret = request_threaded_irq(priv->plug_irq, NULL, twl6040_audio_handler,
0, "twl6040_irq_plug", codec);
if (ret) {
@@ -1620,27 +1586,16 @@ static int twl6040_probe(struct snd_soc_codec *codec)
goto plugirq_err;
}
- /* init vio registers */
- twl6040_init_vio_regs(codec);
+ twl6040_init_chip(codec);
/* power on device */
ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- if (ret)
- goto bias_err;
-
- snd_soc_add_controls(codec, twl6040_snd_controls,
- ARRAY_SIZE(twl6040_snd_controls));
- twl6040_add_widgets(codec);
-
- return 0;
+ if (!ret)
+ return 0;
-bias_err:
+ /* Error path */
free_irq(priv->plug_irq, codec);
plugirq_err:
- destroy_workqueue(priv->hs_workqueue);
-hswq_err:
- destroy_workqueue(priv->hf_workqueue);
-hfwq_err:
destroy_workqueue(priv->workqueue);
work_err:
kfree(priv);
@@ -1654,8 +1609,6 @@ static int twl6040_remove(struct snd_soc_codec *codec)
twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF);
free_irq(priv->plug_irq, codec);
destroy_workqueue(priv->workqueue);
- destroy_workqueue(priv->hf_workqueue);
- destroy_workqueue(priv->hs_workqueue);
kfree(priv);
return 0;
@@ -1672,6 +1625,14 @@ static struct snd_soc_codec_driver soc_codec_dev_twl6040 = {
.reg_cache_size = ARRAY_SIZE(twl6040_reg),
.reg_word_size = sizeof(u8),
.reg_cache_default = twl6040_reg,
+ .ignore_pmdown_time = true,
+
+ .controls = twl6040_snd_controls,
+ .num_controls = ARRAY_SIZE(twl6040_snd_controls),
+ .dapm_widgets = twl6040_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
+ .dapm_routes = intercon,
+ .num_dapm_routes = ARRAY_SIZE(intercon),
};
static int __devinit twl6040_codec_probe(struct platform_device *pdev)
@@ -1695,17 +1656,7 @@ static struct platform_driver twl6040_codec_driver = {
.remove = __devexit_p(twl6040_codec_remove),
};
-static int __init twl6040_codec_init(void)
-{
- return platform_driver_register(&twl6040_codec_driver);
-}
-module_init(twl6040_codec_init);
-
-static void __exit twl6040_codec_exit(void)
-{
- platform_driver_unregister(&twl6040_codec_driver);
-}
-module_exit(twl6040_codec_exit);
+module_platform_driver(twl6040_codec_driver);
MODULE_DESCRIPTION("ASoC TWL6040 codec driver");
MODULE_AUTHOR("Misael Lopez Cruz");
diff --git a/sound/soc/codecs/twl6040.h b/sound/soc/codecs/twl6040.h
index d8de67869dd9..0611406ca7c0 100644
--- a/sound/soc/codecs/twl6040.h
+++ b/sound/soc/codecs/twl6040.h
@@ -22,8 +22,23 @@
#ifndef __TWL6040_H__
#define __TWL6040_H__
+enum twl6040_trim {
+ TWL6040_TRIM_TRIM1 = 0,
+ TWL6040_TRIM_TRIM2,
+ TWL6040_TRIM_TRIM3,
+ TWL6040_TRIM_HSOTRIM,
+ TWL6040_TRIM_HFOTRIM,
+ TWL6040_TRIM_INVAL,
+};
+
+#define TWL6040_HSF_TRIM_LEFT(x) (x & 0x0f)
+#define TWL6040_HSF_TRIM_RIGHT(x) ((x >> 4) & 0x0f)
+
+int twl6040_get_dl1_gain(struct snd_soc_codec *codec);
void twl6040_hs_jack_detect(struct snd_soc_codec *codec,
struct snd_soc_jack *jack, int report);
int twl6040_get_clk_id(struct snd_soc_codec *codec);
+int twl6040_get_trim_value(struct snd_soc_codec *codec, enum twl6040_trim trim);
+int twl6040_get_hs_step_size(struct snd_soc_codec *codec);
#endif /* End of __TWL6040_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
index a7b8f301bad3..797b0dde2c68 100644
--- a/sound/soc/codecs/uda134x.c
+++ b/sound/soc/codecs/uda134x.c
@@ -452,7 +452,7 @@ SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
};
-static struct snd_soc_dai_ops uda134x_dai_ops = {
+static const struct snd_soc_dai_ops uda134x_dai_ops = {
.startup = uda134x_startup,
.shutdown = uda134x_shutdown,
.hw_params = uda134x_hw_params,
@@ -531,15 +531,15 @@ static int uda134x_soc_probe(struct snd_soc_codec *codec)
switch (pd->model) {
case UDA134X_UDA1340:
case UDA134X_UDA1344:
- ret = snd_soc_add_controls(codec, uda1340_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, uda1340_snd_controls,
ARRAY_SIZE(uda1340_snd_controls));
break;
case UDA134X_UDA1341:
- ret = snd_soc_add_controls(codec, uda1341_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, uda1341_snd_controls,
ARRAY_SIZE(uda1341_snd_controls));
break;
case UDA134X_UDA1345:
- ret = snd_soc_add_controls(codec, uda1345_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, uda1345_snd_controls,
ARRAY_SIZE(uda1345_snd_controls));
break;
default:
@@ -571,8 +571,7 @@ static int uda134x_soc_remove(struct snd_soc_codec *codec)
}
#if defined(CONFIG_PM)
-static int uda134x_soc_suspend(struct snd_soc_codec *codec,
- pm_message_t state)
+static int uda134x_soc_suspend(struct snd_soc_codec *codec)
{
uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -625,17 +624,7 @@ static struct platform_driver uda134x_codec_driver = {
.remove = __devexit_p(uda134x_codec_remove),
};
-static int __init uda134x_codec_init(void)
-{
- return platform_driver_register(&uda134x_codec_driver);
-}
-module_init(uda134x_codec_init);
-
-static void __exit uda134x_codec_exit(void)
-{
- platform_driver_unregister(&uda134x_codec_driver);
-}
-module_exit(uda134x_codec_exit);
+module_platform_driver(uda134x_codec_driver);
MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index c5ca8cfea60f..4f1b23d7e404 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -373,7 +373,7 @@ static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
SND_SOC_DAPM_PGA("HeadPhone Driver", UDA1380_PM, 13, 0, NULL, 0),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route uda1380_dapm_routes[] = {
/* output mux */
{"HeadPhone Driver", NULL, "Output Mux"},
@@ -410,17 +410,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Right PGA", NULL, "VINR"},
};
-static int uda1380_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
- ARRAY_SIZE(uda1380_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
static int uda1380_set_dai_fmt_both(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
@@ -643,21 +632,21 @@ static int uda1380_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
-static struct snd_soc_dai_ops uda1380_dai_ops = {
+static const struct snd_soc_dai_ops uda1380_dai_ops = {
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.trigger = uda1380_trigger,
.set_fmt = uda1380_set_dai_fmt_both,
};
-static struct snd_soc_dai_ops uda1380_dai_ops_playback = {
+static const struct snd_soc_dai_ops uda1380_dai_ops_playback = {
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.trigger = uda1380_trigger,
.set_fmt = uda1380_set_dai_fmt_playback,
};
-static struct snd_soc_dai_ops uda1380_dai_ops_capture = {
+static const struct snd_soc_dai_ops uda1380_dai_ops_capture = {
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.trigger = uda1380_trigger,
@@ -705,7 +694,7 @@ static struct snd_soc_dai_driver uda1380_dai[] = {
},
};
-static int uda1380_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int uda1380_suspend(struct snd_soc_codec *codec)
{
uda1380_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -732,27 +721,21 @@ static int uda1380_probe(struct snd_soc_codec *codec)
return -EINVAL;
if (gpio_is_valid(pdata->gpio_reset)) {
- ret = gpio_request(pdata->gpio_reset, "uda1380 reset");
+ ret = gpio_request_one(pdata->gpio_reset, GPIOF_OUT_INIT_LOW,
+ "uda1380 reset");
if (ret)
goto err_out;
- ret = gpio_direction_output(pdata->gpio_reset, 0);
- if (ret)
- goto err_gpio_reset_conf;
}
if (gpio_is_valid(pdata->gpio_power)) {
- ret = gpio_request(pdata->gpio_power, "uda1380 power");
- if (ret)
- goto err_gpio;
- ret = gpio_direction_output(pdata->gpio_power, 0);
+ ret = gpio_request_one(pdata->gpio_power, GPIOF_OUT_INIT_LOW,
+ "uda1380 power");
if (ret)
- goto err_gpio_power_conf;
+ goto err_free_gpio;
} else {
ret = uda1380_reset(codec);
- if (ret) {
- dev_err(codec->dev, "Failed to issue reset\n");
- goto err_reset;
- }
+ if (ret)
+ goto err_free_gpio;
}
INIT_WORK(&uda1380->work, uda1380_flush_work);
@@ -770,19 +753,9 @@ static int uda1380_probe(struct snd_soc_codec *codec)
break;
}
- snd_soc_add_controls(codec, uda1380_snd_controls,
- ARRAY_SIZE(uda1380_snd_controls));
- uda1380_add_widgets(codec);
-
return 0;
-err_reset:
-err_gpio_power_conf:
- if (gpio_is_valid(pdata->gpio_power))
- gpio_free(pdata->gpio_power);
-
-err_gpio_reset_conf:
-err_gpio:
+err_free_gpio:
if (gpio_is_valid(pdata->gpio_reset))
gpio_free(pdata->gpio_reset);
err_out:
@@ -814,6 +787,13 @@ static struct snd_soc_codec_driver soc_codec_dev_uda1380 = {
.reg_word_size = sizeof(u16),
.reg_cache_default = uda1380_reg,
.reg_cache_step = 1,
+
+ .controls = uda1380_snd_controls,
+ .num_controls = ARRAY_SIZE(uda1380_snd_controls),
+ .dapm_widgets = uda1380_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets),
+ .dapm_routes = uda1380_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(uda1380_dapm_routes),
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -823,7 +803,8 @@ static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
struct uda1380_priv *uda1380;
int ret;
- uda1380 = kzalloc(sizeof(struct uda1380_priv), GFP_KERNEL);
+ uda1380 = devm_kzalloc(&i2c->dev, sizeof(struct uda1380_priv),
+ GFP_KERNEL);
if (uda1380 == NULL)
return -ENOMEM;
@@ -832,15 +813,12 @@ static __devinit int uda1380_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_uda1380, uda1380_dai, ARRAY_SIZE(uda1380_dai));
- if (ret < 0)
- kfree(uda1380);
return ret;
}
static int __devexit uda1380_i2c_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
- kfree(i2c_get_clientdata(i2c));
return 0;
}
@@ -863,13 +841,13 @@ static struct i2c_driver uda1380_i2c_driver = {
static int __init uda1380_modinit(void)
{
- int ret;
+ int ret = 0;
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&uda1380_i2c_driver);
if (ret != 0)
pr_err("Failed to register UDA1380 I2C driver: %d\n", ret);
#endif
- return 0;
+ return ret;
}
module_init(uda1380_modinit);
diff --git a/sound/soc/codecs/wl1273.c b/sound/soc/codecs/wl1273.c
index 5836201834d9..3d868dc40092 100644
--- a/sound/soc/codecs/wl1273.c
+++ b/sound/soc/codecs/wl1273.c
@@ -23,6 +23,7 @@
#include <linux/mfd/wl1273-core.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -385,7 +386,7 @@ static int wl1273_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_dai_ops wl1273_dai_ops = {
+static const struct snd_soc_dai_ops wl1273_dai_ops = {
.startup = wl1273_startup,
.hw_params = wl1273_hw_params,
};
@@ -462,9 +463,8 @@ static int wl1273_probe(struct snd_soc_codec *codec)
wl1273->core = *core;
snd_soc_codec_set_drvdata(codec, wl1273);
- mutex_init(&codec->mutex);
- r = snd_soc_add_controls(codec, wl1273_controls,
+ r = snd_soc_add_codec_controls(codec, wl1273_controls,
ARRAY_SIZE(wl1273_controls));
if (r)
kfree(wl1273);
@@ -510,17 +510,7 @@ static struct platform_driver wl1273_platform_driver = {
.remove = __devexit_p(wl1273_platform_remove),
};
-static int __init wl1273_init(void)
-{
- return platform_driver_register(&wl1273_platform_driver);
-}
-module_init(wl1273_init);
-
-static void __exit wl1273_exit(void)
-{
- platform_driver_unregister(&wl1273_platform_driver);
-}
-module_exit(wl1273_exit);
+module_platform_driver(wl1273_platform_driver);
MODULE_AUTHOR("Matti Aaltonen <matti.j.aaltonen@nokia.com>");
MODULE_DESCRIPTION("ASoC WL1273 codec driver");
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c
index bcc208967917..aefb4f89be0e 100644
--- a/sound/soc/codecs/wm1250-ev1.c
+++ b/sound/soc/codecs/wm1250-ev1.c
@@ -12,10 +12,59 @@
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <linux/i2c.h>
+#include <linux/gpio.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
+#include <sound/wm1250-ev1.h>
+
+static const char *wm1250_gpio_names[WM1250_EV1_NUM_GPIOS] = {
+ "WM1250 CLK_ENA",
+ "WM1250 CLK_SEL0",
+ "WM1250 CLK_SEL1",
+ "WM1250 OSR",
+ "WM1250 MASTER",
+};
+
+struct wm1250_priv {
+ struct gpio gpios[WM1250_EV1_NUM_GPIOS];
+};
+
+static int wm1250_ev1_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct wm1250_priv *wm1250 = dev_get_drvdata(codec->dev);
+ int ena;
+
+ if (wm1250)
+ ena = wm1250->gpios[WM1250_EV1_GPIO_CLK_ENA].gpio;
+ else
+ ena = -1;
+
+ switch (level) {
+ case SND_SOC_BIAS_ON:
+ break;
+
+ case SND_SOC_BIAS_PREPARE:
+ break;
+
+ case SND_SOC_BIAS_STANDBY:
+ if (ena >= 0)
+ gpio_set_value_cansleep(ena, 1);
+ break;
+
+ case SND_SOC_BIAS_OFF:
+ if (ena >= 0)
+ gpio_set_value_cansleep(ena, 0);
+ break;
+ }
+
+ codec->dapm.bias_level = level;
+
+ return 0;
+}
static const struct snd_soc_dapm_widget wm1250_ev1_dapm_widgets[] = {
SND_SOC_DAPM_ADC("ADC", "wm1250-ev1 Capture", SND_SOC_NOPM, 0, 0),
@@ -53,18 +102,99 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = {
.num_dapm_widgets = ARRAY_SIZE(wm1250_ev1_dapm_widgets),
.dapm_routes = wm1250_ev1_dapm_routes,
.num_dapm_routes = ARRAY_SIZE(wm1250_ev1_dapm_routes),
+
+ .set_bias_level = wm1250_ev1_set_bias_level,
+ .idle_bias_off = true,
};
+static int __devinit wm1250_ev1_pdata(struct i2c_client *i2c)
+{
+ struct wm1250_ev1_pdata *pdata = dev_get_platdata(&i2c->dev);
+ struct wm1250_priv *wm1250;
+ int i, ret;
+
+ if (!pdata)
+ return 0;
+
+ wm1250 = devm_kzalloc(&i2c->dev, sizeof(*wm1250), GFP_KERNEL);
+ if (!wm1250) {
+ dev_err(&i2c->dev, "Unable to allocate private data\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm1250->gpios); i++) {
+ wm1250->gpios[i].gpio = pdata->gpios[i];
+ wm1250->gpios[i].label = wm1250_gpio_names[i];
+ wm1250->gpios[i].flags = GPIOF_OUT_INIT_LOW;
+ }
+ wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL0].flags = GPIOF_OUT_INIT_HIGH;
+ wm1250->gpios[WM1250_EV1_GPIO_CLK_SEL1].flags = GPIOF_OUT_INIT_HIGH;
+
+ ret = gpio_request_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to get GPIOs: %d\n", ret);
+ goto err;
+ }
+
+ dev_set_drvdata(&i2c->dev, wm1250);
+
+ return ret;
+
+err:
+ return ret;
+}
+
+static void wm1250_ev1_free(struct i2c_client *i2c)
+{
+ struct wm1250_priv *wm1250 = dev_get_drvdata(&i2c->dev);
+
+ if (wm1250)
+ gpio_free_array(wm1250->gpios, ARRAY_SIZE(wm1250->gpios));
+}
+
static int __devinit wm1250_ev1_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+ const struct i2c_device_id *i2c_id)
{
- return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
- &wm1250_ev1_dai, 1);
+ int id, board, rev, ret;
+
+ dev_set_drvdata(&i2c->dev, NULL);
+
+ board = i2c_smbus_read_byte_data(i2c, 0);
+ if (board < 0) {
+ dev_err(&i2c->dev, "Failed to read ID: %d\n", board);
+ return board;
+ }
+
+ id = (board & 0xfe) >> 2;
+ rev = board & 0x3;
+
+ if (id != 1) {
+ dev_err(&i2c->dev, "Unknown board ID %d\n", id);
+ return -ENODEV;
+ }
+
+ dev_info(&i2c->dev, "revision %d\n", rev + 1);
+
+ ret = wm1250_ev1_pdata(i2c);
+ if (ret != 0)
+ return ret;
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1,
+ &wm1250_ev1_dai, 1);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ wm1250_ev1_free(i2c);
+ return ret;
+ }
+
+ return 0;
}
static int __devexit wm1250_ev1_remove(struct i2c_client *i2c)
{
snd_soc_unregister_codec(&i2c->dev);
+ wm1250_ev1_free(i2c);
return 0;
}
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index a3b9cbb20ee9..a75c3766aede 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -29,7 +29,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/debugfs.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -52,6 +52,7 @@ enum wm2000_anc_mode {
struct wm2000_priv {
struct i2c_client *i2c;
+ struct regmap *regmap;
enum wm2000_anc_mode anc_mode;
@@ -66,59 +67,24 @@ struct wm2000_priv {
char *anc_download;
};
-static struct i2c_client *wm2000_i2c;
-
static int wm2000_write(struct i2c_client *i2c, unsigned int reg,
unsigned int value)
{
- u8 data[3];
- int ret;
-
- data[0] = (reg >> 8) & 0xff;
- data[1] = reg & 0xff;
- data[2] = value & 0xff;
-
- dev_vdbg(&i2c->dev, "write %x = %x\n", reg, value);
-
- ret = i2c_master_send(i2c, data, 3);
- if (ret == 3)
- return 0;
- if (ret < 0)
- return ret;
- else
- return -EIO;
+ struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c);
+ return regmap_write(wm2000->regmap, reg, value);
}
static unsigned int wm2000_read(struct i2c_client *i2c, unsigned int r)
{
- struct i2c_msg xfer[2];
- u8 reg[2];
- u8 data;
+ struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c);
+ unsigned int val;
int ret;
- /* Write register */
- reg[0] = (r >> 8) & 0xff;
- reg[1] = r & 0xff;
- xfer[0].addr = i2c->addr;
- xfer[0].flags = 0;
- xfer[0].len = sizeof(reg);
- xfer[0].buf = &reg[0];
-
- /* Read data */
- xfer[1].addr = i2c->addr;
- xfer[1].flags = I2C_M_RD;
- xfer[1].len = 1;
- xfer[1].buf = &data;
-
- ret = i2c_transfer(i2c->adapter, xfer, 2);
- if (ret != 2) {
- dev_err(&i2c->dev, "i2c_transfer() returned %d\n", ret);
- return 0;
- }
-
- dev_vdbg(&i2c->dev, "read %x from %x\n", data, r);
+ ret = regmap_read(wm2000->regmap, r, &val);
+ if (ret < 0)
+ return -1;
- return data;
+ return val;
}
static void wm2000_reset(struct wm2000_priv *wm2000)
@@ -612,7 +578,8 @@ static int wm2000_anc_set_mode(struct wm2000_priv *wm2000)
static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
ucontrol->value.enumerated.item[0] = wm2000->anc_active;
@@ -622,7 +589,8 @@ static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
int anc_active = ucontrol->value.enumerated.item[0];
if (anc_active > 1)
@@ -636,7 +604,8 @@ static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
ucontrol->value.enumerated.item[0] = wm2000->spk_ena;
@@ -646,7 +615,8 @@ static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
static int wm2000_speaker_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
int val = ucontrol->value.enumerated.item[0];
if (val > 1)
@@ -669,7 +639,8 @@ static const struct snd_kcontrol_new wm2000_controls[] = {
static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
- struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
if (SND_SOC_DAPM_EVENT_ON(event))
wm2000->anc_eng_ena = 1;
@@ -682,11 +653,11 @@ static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w,
static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = {
/* Externally visible pins */
-SND_SOC_DAPM_OUTPUT("WM2000 SPKN"),
-SND_SOC_DAPM_OUTPUT("WM2000 SPKP"),
+SND_SOC_DAPM_OUTPUT("SPKN"),
+SND_SOC_DAPM_OUTPUT("SPKP"),
-SND_SOC_DAPM_INPUT("WM2000 LINN"),
-SND_SOC_DAPM_INPUT("WM2000 LINP"),
+SND_SOC_DAPM_INPUT("LINN"),
+SND_SOC_DAPM_INPUT("LINP"),
SND_SOC_DAPM_PGA_E("ANC Engine", SND_SOC_NOPM, 0, 0, NULL, 0,
wm2000_anc_power_event,
@@ -694,37 +665,67 @@ SND_SOC_DAPM_PGA_E("ANC Engine", SND_SOC_NOPM, 0, 0, NULL, 0,
};
/* Target, Path, Source */
-static const struct snd_soc_dapm_route audio_map[] = {
- { "WM2000 SPKN", NULL, "ANC Engine" },
- { "WM2000 SPKP", NULL, "ANC Engine" },
- { "ANC Engine", NULL, "WM2000 LINN" },
- { "ANC Engine", NULL, "WM2000 LINP" },
+static const struct snd_soc_dapm_route wm2000_audio_map[] = {
+ { "SPKN", NULL, "ANC Engine" },
+ { "SPKP", NULL, "ANC Engine" },
+ { "ANC Engine", NULL, "LINN" },
+ { "ANC Engine", NULL, "LINP" },
};
-/* Called from the machine driver */
-int wm2000_add_controls(struct snd_soc_codec *codec)
+#ifdef CONFIG_PM
+static int wm2000_suspend(struct snd_soc_codec *codec)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret;
+ struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
- if (!wm2000_i2c) {
- pr_err("WM2000 not yet probed\n");
- return -ENODEV;
- }
+ return wm2000_anc_transition(wm2000, ANC_OFF);
+}
- ret = snd_soc_dapm_new_controls(dapm, wm2000_dapm_widgets,
- ARRAY_SIZE(wm2000_dapm_widgets));
- if (ret < 0)
- return ret;
+static int wm2000_resume(struct snd_soc_codec *codec)
+{
+ struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
- ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- if (ret < 0)
- return ret;
+ return wm2000_anc_set_mode(wm2000);
+}
+#else
+#define wm2000_suspend NULL
+#define wm2000_resume NULL
+#endif
- return snd_soc_add_controls(codec, wm2000_controls,
- ARRAY_SIZE(wm2000_controls));
+static const struct regmap_config wm2000_regmap = {
+ .reg_bits = 8,
+ .val_bits = 8,
+};
+
+static int wm2000_probe(struct snd_soc_codec *codec)
+{
+ struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
+
+ /* This will trigger a transition to standby mode by default */
+ wm2000_anc_set_mode(wm2000);
+
+ return 0;
+}
+
+static int wm2000_remove(struct snd_soc_codec *codec)
+{
+ struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev);
+
+ return wm2000_anc_transition(wm2000, ANC_OFF);
}
-EXPORT_SYMBOL_GPL(wm2000_add_controls);
+
+static struct snd_soc_codec_driver soc_codec_dev_wm2000 = {
+ .probe = wm2000_probe,
+ .remove = wm2000_remove,
+ .suspend = wm2000_suspend,
+ .resume = wm2000_resume,
+
+ .dapm_widgets = wm2000_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm2000_dapm_widgets),
+ .dapm_routes = wm2000_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(wm2000_audio_map),
+ .controls = wm2000_controls,
+ .num_controls = ARRAY_SIZE(wm2000_controls),
+};
static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *i2c_id)
@@ -732,21 +733,28 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
struct wm2000_priv *wm2000;
struct wm2000_platform_data *pdata;
const char *filename;
- const struct firmware *fw;
- int reg, ret;
+ const struct firmware *fw = NULL;
+ int ret;
+ int reg;
u16 id;
- if (wm2000_i2c) {
- dev_err(&i2c->dev, "Another WM2000 is already registered\n");
- return -EINVAL;
- }
-
- wm2000 = kzalloc(sizeof(struct wm2000_priv), GFP_KERNEL);
+ wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
+ GFP_KERNEL);
if (wm2000 == NULL) {
dev_err(&i2c->dev, "Unable to allocate private data\n");
return -ENOMEM;
}
+ dev_set_drvdata(&i2c->dev, wm2000);
+
+ wm2000->regmap = regmap_init_i2c(i2c, &wm2000_regmap);
+ if (IS_ERR(wm2000->regmap)) {
+ ret = PTR_ERR(wm2000->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto out;
+ }
+
/* Verify that this is a WM2000 */
reg = wm2000_read(i2c, WM2000_REG_ID1);
id = reg << 8;
@@ -756,7 +764,7 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
if (id != 0x2000) {
dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
ret = -ENODEV;
- goto err;
+ goto out_regmap_exit;
}
reg = wm2000_read(i2c, WM2000_REG_REVISON);
@@ -775,25 +783,24 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
ret = request_firmware(&fw, filename, &i2c->dev);
if (ret != 0) {
dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
- goto err;
+ goto out_regmap_exit;
}
/* Pre-cook the concatenation of the register address onto the image */
wm2000->anc_download_size = fw->size + 2;
- wm2000->anc_download = kmalloc(wm2000->anc_download_size, GFP_KERNEL);
+ wm2000->anc_download = devm_kzalloc(&i2c->dev,
+ wm2000->anc_download_size,
+ GFP_KERNEL);
if (wm2000->anc_download == NULL) {
dev_err(&i2c->dev, "Out of memory\n");
ret = -ENOMEM;
- goto err_fw;
+ goto out_regmap_exit;
}
wm2000->anc_download[0] = 0x80;
wm2000->anc_download[1] = 0x00;
memcpy(wm2000->anc_download + 2, fw->data, fw->size);
- release_firmware(fw);
-
- dev_set_drvdata(&i2c->dev, wm2000);
wm2000->anc_eng_ena = 1;
wm2000->anc_active = 1;
wm2000->spk_ena = 1;
@@ -801,17 +808,14 @@ static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
wm2000_reset(wm2000);
- /* This will trigger a transition to standby mode by default */
- wm2000_anc_set_mode(wm2000);
-
- wm2000_i2c = i2c;
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm2000, NULL, 0);
+ if (!ret)
+ goto out;
- return 0;
-
-err_fw:
+out_regmap_exit:
+ regmap_exit(wm2000->regmap);
+out:
release_firmware(fw);
-err:
- kfree(wm2000);
return ret;
}
@@ -819,42 +823,12 @@ static __devexit int wm2000_i2c_remove(struct i2c_client *i2c)
{
struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
- wm2000_anc_transition(wm2000, ANC_OFF);
-
- wm2000_i2c = NULL;
- kfree(wm2000->anc_download);
- kfree(wm2000);
+ snd_soc_unregister_codec(&i2c->dev);
+ regmap_exit(wm2000->regmap);
return 0;
}
-static void wm2000_i2c_shutdown(struct i2c_client *i2c)
-{
- struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
-
- wm2000_anc_transition(wm2000, ANC_OFF);
-}
-
-#ifdef CONFIG_PM
-static int wm2000_i2c_suspend(struct device *dev)
-{
- struct i2c_client *i2c = to_i2c_client(dev);
- struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
-
- return wm2000_anc_transition(wm2000, ANC_OFF);
-}
-
-static int wm2000_i2c_resume(struct device *dev)
-{
- struct i2c_client *i2c = to_i2c_client(dev);
- struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
-
- return wm2000_anc_set_mode(wm2000);
-}
-#endif
-
-static SIMPLE_DEV_PM_OPS(wm2000_pm, wm2000_i2c_suspend, wm2000_i2c_resume);
-
static const struct i2c_device_id wm2000_i2c_id[] = {
{ "wm2000", 0 },
{ }
@@ -865,11 +839,9 @@ static struct i2c_driver wm2000_i2c_driver = {
.driver = {
.name = "wm2000",
.owner = THIS_MODULE,
- .pm = &wm2000_pm,
},
.probe = wm2000_i2c_probe,
.remove = __devexit_p(wm2000_i2c_remove),
- .shutdown = wm2000_i2c_shutdown,
.id_table = wm2000_i2c_id,
};
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h
index 0b6f056f73cc..abcd82a93995 100644
--- a/sound/soc/codecs/wm2000.h
+++ b/sound/soc/codecs/wm2000.h
@@ -9,13 +9,6 @@
#ifndef _WM2000_H
#define _WM2000_H
-struct wm2000_setup_data {
- unsigned short i2c_address;
- int mclk_div; /* Set to a non-zero value if MCLK_DIV_2 required */
-};
-
-extern int wm2000_add_controls(struct snd_soc_codec *codec);
-
#define WM2000_REG_SYS_START 0x8000
#define WM2000_REG_SPEECH_CLARITY 0x8fef
#define WM2000_REG_SYS_WATCHDOG 0x8ff6
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
new file mode 100644
index 000000000000..acbdc5fde923
--- /dev/null
+++ b/sound/soc/codecs/wm2200.c
@@ -0,0 +1,2286 @@
+/*
+ * wm2200.c -- WM2200 ALSA SoC Audio driver
+ *
+ * Copyright 2012 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm2200.h>
+
+#include "wm2200.h"
+
+/* The code assumes DCVDD is generated internally */
+#define WM2200_NUM_CORE_SUPPLIES 2
+static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = {
+ "DBVDD",
+ "LDOVDD",
+};
+
+struct wm2200_fll {
+ int fref;
+ int fout;
+ int src;
+ struct completion lock;
+};
+
+/* codec private data */
+struct wm2200_priv {
+ struct regmap *regmap;
+ struct device *dev;
+ struct snd_soc_codec *codec;
+ struct wm2200_pdata pdata;
+ struct regulator_bulk_data core_supplies[WM2200_NUM_CORE_SUPPLIES];
+
+ struct completion fll_lock;
+ int fll_fout;
+ int fll_fref;
+ int fll_src;
+
+ int rev;
+ int sysclk;
+};
+
+static struct reg_default wm2200_reg_defaults[] = {
+ { 0x000B, 0x0000 }, /* R11 - Tone Generator 1 */
+ { 0x0102, 0x0000 }, /* R258 - Clocking 3 */
+ { 0x0103, 0x0011 }, /* R259 - Clocking 4 */
+ { 0x0111, 0x0000 }, /* R273 - FLL Control 1 */
+ { 0x0112, 0x0000 }, /* R274 - FLL Control 2 */
+ { 0x0113, 0x0000 }, /* R275 - FLL Control 3 */
+ { 0x0114, 0x0000 }, /* R276 - FLL Control 4 */
+ { 0x0116, 0x0177 }, /* R278 - FLL Control 6 */
+ { 0x0117, 0x0004 }, /* R279 - FLL Control 7 */
+ { 0x0119, 0x0000 }, /* R281 - FLL EFS 1 */
+ { 0x011A, 0x0002 }, /* R282 - FLL EFS 2 */
+ { 0x0200, 0x0000 }, /* R512 - Mic Charge Pump 1 */
+ { 0x0201, 0x03FF }, /* R513 - Mic Charge Pump 2 */
+ { 0x0202, 0x9BDE }, /* R514 - DM Charge Pump 1 */
+ { 0x020C, 0x0000 }, /* R524 - Mic Bias Ctrl 1 */
+ { 0x020D, 0x0000 }, /* R525 - Mic Bias Ctrl 2 */
+ { 0x020F, 0x0000 }, /* R527 - Ear Piece Ctrl 1 */
+ { 0x0210, 0x0000 }, /* R528 - Ear Piece Ctrl 2 */
+ { 0x0301, 0x0000 }, /* R769 - Input Enables */
+ { 0x0302, 0x2240 }, /* R770 - IN1L Control */
+ { 0x0303, 0x0040 }, /* R771 - IN1R Control */
+ { 0x0304, 0x2240 }, /* R772 - IN2L Control */
+ { 0x0305, 0x0040 }, /* R773 - IN2R Control */
+ { 0x0306, 0x2240 }, /* R774 - IN3L Control */
+ { 0x0307, 0x0040 }, /* R775 - IN3R Control */
+ { 0x030A, 0x0000 }, /* R778 - RXANC_SRC */
+ { 0x030B, 0x0022 }, /* R779 - Input Volume Ramp */
+ { 0x030C, 0x0180 }, /* R780 - ADC Digital Volume 1L */
+ { 0x030D, 0x0180 }, /* R781 - ADC Digital Volume 1R */
+ { 0x030E, 0x0180 }, /* R782 - ADC Digital Volume 2L */
+ { 0x030F, 0x0180 }, /* R783 - ADC Digital Volume 2R */
+ { 0x0310, 0x0180 }, /* R784 - ADC Digital Volume 3L */
+ { 0x0311, 0x0180 }, /* R785 - ADC Digital Volume 3R */
+ { 0x0400, 0x0000 }, /* R1024 - Output Enables */
+ { 0x0401, 0x0000 }, /* R1025 - DAC Volume Limit 1L */
+ { 0x0402, 0x0000 }, /* R1026 - DAC Volume Limit 1R */
+ { 0x0403, 0x0000 }, /* R1027 - DAC Volume Limit 2L */
+ { 0x0404, 0x0000 }, /* R1028 - DAC Volume Limit 2R */
+ { 0x0409, 0x0000 }, /* R1033 - DAC AEC Control 1 */
+ { 0x040A, 0x0022 }, /* R1034 - Output Volume Ramp */
+ { 0x040B, 0x0180 }, /* R1035 - DAC Digital Volume 1L */
+ { 0x040C, 0x0180 }, /* R1036 - DAC Digital Volume 1R */
+ { 0x040D, 0x0180 }, /* R1037 - DAC Digital Volume 2L */
+ { 0x040E, 0x0180 }, /* R1038 - DAC Digital Volume 2R */
+ { 0x0417, 0x0069 }, /* R1047 - PDM 1 */
+ { 0x0418, 0x0000 }, /* R1048 - PDM 2 */
+ { 0x0500, 0x0000 }, /* R1280 - Audio IF 1_1 */
+ { 0x0501, 0x0008 }, /* R1281 - Audio IF 1_2 */
+ { 0x0502, 0x0000 }, /* R1282 - Audio IF 1_3 */
+ { 0x0503, 0x0000 }, /* R1283 - Audio IF 1_4 */
+ { 0x0504, 0x0000 }, /* R1284 - Audio IF 1_5 */
+ { 0x0505, 0x0001 }, /* R1285 - Audio IF 1_6 */
+ { 0x0506, 0x0001 }, /* R1286 - Audio IF 1_7 */
+ { 0x0507, 0x0000 }, /* R1287 - Audio IF 1_8 */
+ { 0x0508, 0x0000 }, /* R1288 - Audio IF 1_9 */
+ { 0x0509, 0x0000 }, /* R1289 - Audio IF 1_10 */
+ { 0x050A, 0x0000 }, /* R1290 - Audio IF 1_11 */
+ { 0x050B, 0x0000 }, /* R1291 - Audio IF 1_12 */
+ { 0x050C, 0x0000 }, /* R1292 - Audio IF 1_13 */
+ { 0x050D, 0x0000 }, /* R1293 - Audio IF 1_14 */
+ { 0x050E, 0x0000 }, /* R1294 - Audio IF 1_15 */
+ { 0x050F, 0x0000 }, /* R1295 - Audio IF 1_16 */
+ { 0x0510, 0x0000 }, /* R1296 - Audio IF 1_17 */
+ { 0x0511, 0x0000 }, /* R1297 - Audio IF 1_18 */
+ { 0x0512, 0x0000 }, /* R1298 - Audio IF 1_19 */
+ { 0x0513, 0x0000 }, /* R1299 - Audio IF 1_20 */
+ { 0x0514, 0x0000 }, /* R1300 - Audio IF 1_21 */
+ { 0x0515, 0x0001 }, /* R1301 - Audio IF 1_22 */
+ { 0x0600, 0x0000 }, /* R1536 - OUT1LMIX Input 1 Source */
+ { 0x0601, 0x0080 }, /* R1537 - OUT1LMIX Input 1 Volume */
+ { 0x0602, 0x0000 }, /* R1538 - OUT1LMIX Input 2 Source */
+ { 0x0603, 0x0080 }, /* R1539 - OUT1LMIX Input 2 Volume */
+ { 0x0604, 0x0000 }, /* R1540 - OUT1LMIX Input 3 Source */
+ { 0x0605, 0x0080 }, /* R1541 - OUT1LMIX Input 3 Volume */
+ { 0x0606, 0x0000 }, /* R1542 - OUT1LMIX Input 4 Source */
+ { 0x0607, 0x0080 }, /* R1543 - OUT1LMIX Input 4 Volume */
+ { 0x0608, 0x0000 }, /* R1544 - OUT1RMIX Input 1 Source */
+ { 0x0609, 0x0080 }, /* R1545 - OUT1RMIX Input 1 Volume */
+ { 0x060A, 0x0000 }, /* R1546 - OUT1RMIX Input 2 Source */
+ { 0x060B, 0x0080 }, /* R1547 - OUT1RMIX Input 2 Volume */
+ { 0x060C, 0x0000 }, /* R1548 - OUT1RMIX Input 3 Source */
+ { 0x060D, 0x0080 }, /* R1549 - OUT1RMIX Input 3 Volume */
+ { 0x060E, 0x0000 }, /* R1550 - OUT1RMIX Input 4 Source */
+ { 0x060F, 0x0080 }, /* R1551 - OUT1RMIX Input 4 Volume */
+ { 0x0610, 0x0000 }, /* R1552 - OUT2LMIX Input 1 Source */
+ { 0x0611, 0x0080 }, /* R1553 - OUT2LMIX Input 1 Volume */
+ { 0x0612, 0x0000 }, /* R1554 - OUT2LMIX Input 2 Source */
+ { 0x0613, 0x0080 }, /* R1555 - OUT2LMIX Input 2 Volume */
+ { 0x0614, 0x0000 }, /* R1556 - OUT2LMIX Input 3 Source */
+ { 0x0615, 0x0080 }, /* R1557 - OUT2LMIX Input 3 Volume */
+ { 0x0616, 0x0000 }, /* R1558 - OUT2LMIX Input 4 Source */
+ { 0x0617, 0x0080 }, /* R1559 - OUT2LMIX Input 4 Volume */
+ { 0x0618, 0x0000 }, /* R1560 - OUT2RMIX Input 1 Source */
+ { 0x0619, 0x0080 }, /* R1561 - OUT2RMIX Input 1 Volume */
+ { 0x061A, 0x0000 }, /* R1562 - OUT2RMIX Input 2 Source */
+ { 0x061B, 0x0080 }, /* R1563 - OUT2RMIX Input 2 Volume */
+ { 0x061C, 0x0000 }, /* R1564 - OUT2RMIX Input 3 Source */
+ { 0x061D, 0x0080 }, /* R1565 - OUT2RMIX Input 3 Volume */
+ { 0x061E, 0x0000 }, /* R1566 - OUT2RMIX Input 4 Source */
+ { 0x061F, 0x0080 }, /* R1567 - OUT2RMIX Input 4 Volume */
+ { 0x0620, 0x0000 }, /* R1568 - AIF1TX1MIX Input 1 Source */
+ { 0x0621, 0x0080 }, /* R1569 - AIF1TX1MIX Input 1 Volume */
+ { 0x0622, 0x0000 }, /* R1570 - AIF1TX1MIX Input 2 Source */
+ { 0x0623, 0x0080 }, /* R1571 - AIF1TX1MIX Input 2 Volume */
+ { 0x0624, 0x0000 }, /* R1572 - AIF1TX1MIX Input 3 Source */
+ { 0x0625, 0x0080 }, /* R1573 - AIF1TX1MIX Input 3 Volume */
+ { 0x0626, 0x0000 }, /* R1574 - AIF1TX1MIX Input 4 Source */
+ { 0x0627, 0x0080 }, /* R1575 - AIF1TX1MIX Input 4 Volume */
+ { 0x0628, 0x0000 }, /* R1576 - AIF1TX2MIX Input 1 Source */
+ { 0x0629, 0x0080 }, /* R1577 - AIF1TX2MIX Input 1 Volume */
+ { 0x062A, 0x0000 }, /* R1578 - AIF1TX2MIX Input 2 Source */
+ { 0x062B, 0x0080 }, /* R1579 - AIF1TX2MIX Input 2 Volume */
+ { 0x062C, 0x0000 }, /* R1580 - AIF1TX2MIX Input 3 Source */
+ { 0x062D, 0x0080 }, /* R1581 - AIF1TX2MIX Input 3 Volume */
+ { 0x062E, 0x0000 }, /* R1582 - AIF1TX2MIX Input 4 Source */
+ { 0x062F, 0x0080 }, /* R1583 - AIF1TX2MIX Input 4 Volume */
+ { 0x0630, 0x0000 }, /* R1584 - AIF1TX3MIX Input 1 Source */
+ { 0x0631, 0x0080 }, /* R1585 - AIF1TX3MIX Input 1 Volume */
+ { 0x0632, 0x0000 }, /* R1586 - AIF1TX3MIX Input 2 Source */
+ { 0x0633, 0x0080 }, /* R1587 - AIF1TX3MIX Input 2 Volume */
+ { 0x0634, 0x0000 }, /* R1588 - AIF1TX3MIX Input 3 Source */
+ { 0x0635, 0x0080 }, /* R1589 - AIF1TX3MIX Input 3 Volume */
+ { 0x0636, 0x0000 }, /* R1590 - AIF1TX3MIX Input 4 Source */
+ { 0x0637, 0x0080 }, /* R1591 - AIF1TX3MIX Input 4 Volume */
+ { 0x0638, 0x0000 }, /* R1592 - AIF1TX4MIX Input 1 Source */
+ { 0x0639, 0x0080 }, /* R1593 - AIF1TX4MIX Input 1 Volume */
+ { 0x063A, 0x0000 }, /* R1594 - AIF1TX4MIX Input 2 Source */
+ { 0x063B, 0x0080 }, /* R1595 - AIF1TX4MIX Input 2 Volume */
+ { 0x063C, 0x0000 }, /* R1596 - AIF1TX4MIX Input 3 Source */
+ { 0x063D, 0x0080 }, /* R1597 - AIF1TX4MIX Input 3 Volume */
+ { 0x063E, 0x0000 }, /* R1598 - AIF1TX4MIX Input 4 Source */
+ { 0x063F, 0x0080 }, /* R1599 - AIF1TX4MIX Input 4 Volume */
+ { 0x0640, 0x0000 }, /* R1600 - AIF1TX5MIX Input 1 Source */
+ { 0x0641, 0x0080 }, /* R1601 - AIF1TX5MIX Input 1 Volume */
+ { 0x0642, 0x0000 }, /* R1602 - AIF1TX5MIX Input 2 Source */
+ { 0x0643, 0x0080 }, /* R1603 - AIF1TX5MIX Input 2 Volume */
+ { 0x0644, 0x0000 }, /* R1604 - AIF1TX5MIX Input 3 Source */
+ { 0x0645, 0x0080 }, /* R1605 - AIF1TX5MIX Input 3 Volume */
+ { 0x0646, 0x0000 }, /* R1606 - AIF1TX5MIX Input 4 Source */
+ { 0x0647, 0x0080 }, /* R1607 - AIF1TX5MIX Input 4 Volume */
+ { 0x0648, 0x0000 }, /* R1608 - AIF1TX6MIX Input 1 Source */
+ { 0x0649, 0x0080 }, /* R1609 - AIF1TX6MIX Input 1 Volume */
+ { 0x064A, 0x0000 }, /* R1610 - AIF1TX6MIX Input 2 Source */
+ { 0x064B, 0x0080 }, /* R1611 - AIF1TX6MIX Input 2 Volume */
+ { 0x064C, 0x0000 }, /* R1612 - AIF1TX6MIX Input 3 Source */
+ { 0x064D, 0x0080 }, /* R1613 - AIF1TX6MIX Input 3 Volume */
+ { 0x064E, 0x0000 }, /* R1614 - AIF1TX6MIX Input 4 Source */
+ { 0x064F, 0x0080 }, /* R1615 - AIF1TX6MIX Input 4 Volume */
+ { 0x0650, 0x0000 }, /* R1616 - EQLMIX Input 1 Source */
+ { 0x0651, 0x0080 }, /* R1617 - EQLMIX Input 1 Volume */
+ { 0x0652, 0x0000 }, /* R1618 - EQLMIX Input 2 Source */
+ { 0x0653, 0x0080 }, /* R1619 - EQLMIX Input 2 Volume */
+ { 0x0654, 0x0000 }, /* R1620 - EQLMIX Input 3 Source */
+ { 0x0655, 0x0080 }, /* R1621 - EQLMIX Input 3 Volume */
+ { 0x0656, 0x0000 }, /* R1622 - EQLMIX Input 4 Source */
+ { 0x0657, 0x0080 }, /* R1623 - EQLMIX Input 4 Volume */
+ { 0x0658, 0x0000 }, /* R1624 - EQRMIX Input 1 Source */
+ { 0x0659, 0x0080 }, /* R1625 - EQRMIX Input 1 Volume */
+ { 0x065A, 0x0000 }, /* R1626 - EQRMIX Input 2 Source */
+ { 0x065B, 0x0080 }, /* R1627 - EQRMIX Input 2 Volume */
+ { 0x065C, 0x0000 }, /* R1628 - EQRMIX Input 3 Source */
+ { 0x065D, 0x0080 }, /* R1629 - EQRMIX Input 3 Volume */
+ { 0x065E, 0x0000 }, /* R1630 - EQRMIX Input 4 Source */
+ { 0x065F, 0x0080 }, /* R1631 - EQRMIX Input 4 Volume */
+ { 0x0660, 0x0000 }, /* R1632 - LHPF1MIX Input 1 Source */
+ { 0x0661, 0x0080 }, /* R1633 - LHPF1MIX Input 1 Volume */
+ { 0x0662, 0x0000 }, /* R1634 - LHPF1MIX Input 2 Source */
+ { 0x0663, 0x0080 }, /* R1635 - LHPF1MIX Input 2 Volume */
+ { 0x0664, 0x0000 }, /* R1636 - LHPF1MIX Input 3 Source */
+ { 0x0665, 0x0080 }, /* R1637 - LHPF1MIX Input 3 Volume */
+ { 0x0666, 0x0000 }, /* R1638 - LHPF1MIX Input 4 Source */
+ { 0x0667, 0x0080 }, /* R1639 - LHPF1MIX Input 4 Volume */
+ { 0x0668, 0x0000 }, /* R1640 - LHPF2MIX Input 1 Source */
+ { 0x0669, 0x0080 }, /* R1641 - LHPF2MIX Input 1 Volume */
+ { 0x066A, 0x0000 }, /* R1642 - LHPF2MIX Input 2 Source */
+ { 0x066B, 0x0080 }, /* R1643 - LHPF2MIX Input 2 Volume */
+ { 0x066C, 0x0000 }, /* R1644 - LHPF2MIX Input 3 Source */
+ { 0x066D, 0x0080 }, /* R1645 - LHPF2MIX Input 3 Volume */
+ { 0x066E, 0x0000 }, /* R1646 - LHPF2MIX Input 4 Source */
+ { 0x066F, 0x0080 }, /* R1647 - LHPF2MIX Input 4 Volume */
+ { 0x0670, 0x0000 }, /* R1648 - DSP1LMIX Input 1 Source */
+ { 0x0671, 0x0080 }, /* R1649 - DSP1LMIX Input 1 Volume */
+ { 0x0672, 0x0000 }, /* R1650 - DSP1LMIX Input 2 Source */
+ { 0x0673, 0x0080 }, /* R1651 - DSP1LMIX Input 2 Volume */
+ { 0x0674, 0x0000 }, /* R1652 - DSP1LMIX Input 3 Source */
+ { 0x0675, 0x0080 }, /* R1653 - DSP1LMIX Input 3 Volume */
+ { 0x0676, 0x0000 }, /* R1654 - DSP1LMIX Input 4 Source */
+ { 0x0677, 0x0080 }, /* R1655 - DSP1LMIX Input 4 Volume */
+ { 0x0678, 0x0000 }, /* R1656 - DSP1RMIX Input 1 Source */
+ { 0x0679, 0x0080 }, /* R1657 - DSP1RMIX Input 1 Volume */
+ { 0x067A, 0x0000 }, /* R1658 - DSP1RMIX Input 2 Source */
+ { 0x067B, 0x0080 }, /* R1659 - DSP1RMIX Input 2 Volume */
+ { 0x067C, 0x0000 }, /* R1660 - DSP1RMIX Input 3 Source */
+ { 0x067D, 0x0080 }, /* R1661 - DSP1RMIX Input 3 Volume */
+ { 0x067E, 0x0000 }, /* R1662 - DSP1RMIX Input 4 Source */
+ { 0x067F, 0x0080 }, /* R1663 - DSP1RMIX Input 4 Volume */
+ { 0x0680, 0x0000 }, /* R1664 - DSP1AUX1MIX Input 1 Source */
+ { 0x0681, 0x0000 }, /* R1665 - DSP1AUX2MIX Input 1 Source */
+ { 0x0682, 0x0000 }, /* R1666 - DSP1AUX3MIX Input 1 Source */
+ { 0x0683, 0x0000 }, /* R1667 - DSP1AUX4MIX Input 1 Source */
+ { 0x0684, 0x0000 }, /* R1668 - DSP1AUX5MIX Input 1 Source */
+ { 0x0685, 0x0000 }, /* R1669 - DSP1AUX6MIX Input 1 Source */
+ { 0x0686, 0x0000 }, /* R1670 - DSP2LMIX Input 1 Source */
+ { 0x0687, 0x0080 }, /* R1671 - DSP2LMIX Input 1 Volume */
+ { 0x0688, 0x0000 }, /* R1672 - DSP2LMIX Input 2 Source */
+ { 0x0689, 0x0080 }, /* R1673 - DSP2LMIX Input 2 Volume */
+ { 0x068A, 0x0000 }, /* R1674 - DSP2LMIX Input 3 Source */
+ { 0x068B, 0x0080 }, /* R1675 - DSP2LMIX Input 3 Volume */
+ { 0x068C, 0x0000 }, /* R1676 - DSP2LMIX Input 4 Source */
+ { 0x068D, 0x0080 }, /* R1677 - DSP2LMIX Input 4 Volume */
+ { 0x068E, 0x0000 }, /* R1678 - DSP2RMIX Input 1 Source */
+ { 0x068F, 0x0080 }, /* R1679 - DSP2RMIX Input 1 Volume */
+ { 0x0690, 0x0000 }, /* R1680 - DSP2RMIX Input 2 Source */
+ { 0x0691, 0x0080 }, /* R1681 - DSP2RMIX Input 2 Volume */
+ { 0x0692, 0x0000 }, /* R1682 - DSP2RMIX Input 3 Source */
+ { 0x0693, 0x0080 }, /* R1683 - DSP2RMIX Input 3 Volume */
+ { 0x0694, 0x0000 }, /* R1684 - DSP2RMIX Input 4 Source */
+ { 0x0695, 0x0080 }, /* R1685 - DSP2RMIX Input 4 Volume */
+ { 0x0696, 0x0000 }, /* R1686 - DSP2AUX1MIX Input 1 Source */
+ { 0x0697, 0x0000 }, /* R1687 - DSP2AUX2MIX Input 1 Source */
+ { 0x0698, 0x0000 }, /* R1688 - DSP2AUX3MIX Input 1 Source */
+ { 0x0699, 0x0000 }, /* R1689 - DSP2AUX4MIX Input 1 Source */
+ { 0x069A, 0x0000 }, /* R1690 - DSP2AUX5MIX Input 1 Source */
+ { 0x069B, 0x0000 }, /* R1691 - DSP2AUX6MIX Input 1 Source */
+ { 0x0700, 0xA101 }, /* R1792 - GPIO CTRL 1 */
+ { 0x0701, 0xA101 }, /* R1793 - GPIO CTRL 2 */
+ { 0x0702, 0xA101 }, /* R1794 - GPIO CTRL 3 */
+ { 0x0703, 0xA101 }, /* R1795 - GPIO CTRL 4 */
+ { 0x0709, 0x0000 }, /* R1801 - Misc Pad Ctrl 1 */
+ { 0x0801, 0x00FF }, /* R2049 - Interrupt Status 1 Mask */
+ { 0x0804, 0xFFFF }, /* R2052 - Interrupt Status 2 Mask */
+ { 0x0808, 0x0000 }, /* R2056 - Interrupt Control */
+ { 0x0900, 0x0000 }, /* R2304 - EQL_1 */
+ { 0x0901, 0x0000 }, /* R2305 - EQL_2 */
+ { 0x0902, 0x0000 }, /* R2306 - EQL_3 */
+ { 0x0903, 0x0000 }, /* R2307 - EQL_4 */
+ { 0x0904, 0x0000 }, /* R2308 - EQL_5 */
+ { 0x0905, 0x0000 }, /* R2309 - EQL_6 */
+ { 0x0906, 0x0000 }, /* R2310 - EQL_7 */
+ { 0x0907, 0x0000 }, /* R2311 - EQL_8 */
+ { 0x0908, 0x0000 }, /* R2312 - EQL_9 */
+ { 0x0909, 0x0000 }, /* R2313 - EQL_10 */
+ { 0x090A, 0x0000 }, /* R2314 - EQL_11 */
+ { 0x090B, 0x0000 }, /* R2315 - EQL_12 */
+ { 0x090C, 0x0000 }, /* R2316 - EQL_13 */
+ { 0x090D, 0x0000 }, /* R2317 - EQL_14 */
+ { 0x090E, 0x0000 }, /* R2318 - EQL_15 */
+ { 0x090F, 0x0000 }, /* R2319 - EQL_16 */
+ { 0x0910, 0x0000 }, /* R2320 - EQL_17 */
+ { 0x0911, 0x0000 }, /* R2321 - EQL_18 */
+ { 0x0912, 0x0000 }, /* R2322 - EQL_19 */
+ { 0x0913, 0x0000 }, /* R2323 - EQL_20 */
+ { 0x0916, 0x0000 }, /* R2326 - EQR_1 */
+ { 0x0917, 0x0000 }, /* R2327 - EQR_2 */
+ { 0x0918, 0x0000 }, /* R2328 - EQR_3 */
+ { 0x0919, 0x0000 }, /* R2329 - EQR_4 */
+ { 0x091A, 0x0000 }, /* R2330 - EQR_5 */
+ { 0x091B, 0x0000 }, /* R2331 - EQR_6 */
+ { 0x091C, 0x0000 }, /* R2332 - EQR_7 */
+ { 0x091D, 0x0000 }, /* R2333 - EQR_8 */
+ { 0x091E, 0x0000 }, /* R2334 - EQR_9 */
+ { 0x091F, 0x0000 }, /* R2335 - EQR_10 */
+ { 0x0920, 0x0000 }, /* R2336 - EQR_11 */
+ { 0x0921, 0x0000 }, /* R2337 - EQR_12 */
+ { 0x0922, 0x0000 }, /* R2338 - EQR_13 */
+ { 0x0923, 0x0000 }, /* R2339 - EQR_14 */
+ { 0x0924, 0x0000 }, /* R2340 - EQR_15 */
+ { 0x0925, 0x0000 }, /* R2341 - EQR_16 */
+ { 0x0926, 0x0000 }, /* R2342 - EQR_17 */
+ { 0x0927, 0x0000 }, /* R2343 - EQR_18 */
+ { 0x0928, 0x0000 }, /* R2344 - EQR_19 */
+ { 0x0929, 0x0000 }, /* R2345 - EQR_20 */
+ { 0x093E, 0x0000 }, /* R2366 - HPLPF1_1 */
+ { 0x093F, 0x0000 }, /* R2367 - HPLPF1_2 */
+ { 0x0942, 0x0000 }, /* R2370 - HPLPF2_1 */
+ { 0x0943, 0x0000 }, /* R2371 - HPLPF2_2 */
+ { 0x0A00, 0x0000 }, /* R2560 - DSP1 Control 1 */
+ { 0x0A02, 0x0000 }, /* R2562 - DSP1 Control 2 */
+ { 0x0A03, 0x0000 }, /* R2563 - DSP1 Control 3 */
+ { 0x0A04, 0x0000 }, /* R2564 - DSP1 Control 4 */
+ { 0x0A06, 0x0000 }, /* R2566 - DSP1 Control 5 */
+ { 0x0A07, 0x0000 }, /* R2567 - DSP1 Control 6 */
+ { 0x0A08, 0x0000 }, /* R2568 - DSP1 Control 7 */
+ { 0x0A09, 0x0000 }, /* R2569 - DSP1 Control 8 */
+ { 0x0A0A, 0x0000 }, /* R2570 - DSP1 Control 9 */
+ { 0x0A0B, 0x0000 }, /* R2571 - DSP1 Control 10 */
+ { 0x0A0C, 0x0000 }, /* R2572 - DSP1 Control 11 */
+ { 0x0A0D, 0x0000 }, /* R2573 - DSP1 Control 12 */
+ { 0x0A0F, 0x0000 }, /* R2575 - DSP1 Control 13 */
+ { 0x0A10, 0x0000 }, /* R2576 - DSP1 Control 14 */
+ { 0x0A11, 0x0000 }, /* R2577 - DSP1 Control 15 */
+ { 0x0A12, 0x0000 }, /* R2578 - DSP1 Control 16 */
+ { 0x0A13, 0x0000 }, /* R2579 - DSP1 Control 17 */
+ { 0x0A14, 0x0000 }, /* R2580 - DSP1 Control 18 */
+ { 0x0A16, 0x0000 }, /* R2582 - DSP1 Control 19 */
+ { 0x0A17, 0x0000 }, /* R2583 - DSP1 Control 20 */
+ { 0x0A18, 0x0000 }, /* R2584 - DSP1 Control 21 */
+ { 0x0A1A, 0x1800 }, /* R2586 - DSP1 Control 22 */
+ { 0x0A1B, 0x1000 }, /* R2587 - DSP1 Control 23 */
+ { 0x0A1C, 0x0400 }, /* R2588 - DSP1 Control 24 */
+ { 0x0A1E, 0x0000 }, /* R2590 - DSP1 Control 25 */
+ { 0x0A20, 0x0000 }, /* R2592 - DSP1 Control 26 */
+ { 0x0A21, 0x0000 }, /* R2593 - DSP1 Control 27 */
+ { 0x0A22, 0x0000 }, /* R2594 - DSP1 Control 28 */
+ { 0x0A23, 0x0000 }, /* R2595 - DSP1 Control 29 */
+ { 0x0A24, 0x0000 }, /* R2596 - DSP1 Control 30 */
+ { 0x0A26, 0x0000 }, /* R2598 - DSP1 Control 31 */
+ { 0x0B00, 0x0000 }, /* R2816 - DSP2 Control 1 */
+ { 0x0B02, 0x0000 }, /* R2818 - DSP2 Control 2 */
+ { 0x0B03, 0x0000 }, /* R2819 - DSP2 Control 3 */
+ { 0x0B04, 0x0000 }, /* R2820 - DSP2 Control 4 */
+ { 0x0B06, 0x0000 }, /* R2822 - DSP2 Control 5 */
+ { 0x0B07, 0x0000 }, /* R2823 - DSP2 Control 6 */
+ { 0x0B08, 0x0000 }, /* R2824 - DSP2 Control 7 */
+ { 0x0B09, 0x0000 }, /* R2825 - DSP2 Control 8 */
+ { 0x0B0A, 0x0000 }, /* R2826 - DSP2 Control 9 */
+ { 0x0B0B, 0x0000 }, /* R2827 - DSP2 Control 10 */
+ { 0x0B0C, 0x0000 }, /* R2828 - DSP2 Control 11 */
+ { 0x0B0D, 0x0000 }, /* R2829 - DSP2 Control 12 */
+ { 0x0B0F, 0x0000 }, /* R2831 - DSP2 Control 13 */
+ { 0x0B10, 0x0000 }, /* R2832 - DSP2 Control 14 */
+ { 0x0B11, 0x0000 }, /* R2833 - DSP2 Control 15 */
+ { 0x0B12, 0x0000 }, /* R2834 - DSP2 Control 16 */
+ { 0x0B13, 0x0000 }, /* R2835 - DSP2 Control 17 */
+ { 0x0B14, 0x0000 }, /* R2836 - DSP2 Control 18 */
+ { 0x0B16, 0x0000 }, /* R2838 - DSP2 Control 19 */
+ { 0x0B17, 0x0000 }, /* R2839 - DSP2 Control 20 */
+ { 0x0B18, 0x0000 }, /* R2840 - DSP2 Control 21 */
+ { 0x0B1A, 0x0800 }, /* R2842 - DSP2 Control 22 */
+ { 0x0B1B, 0x1000 }, /* R2843 - DSP2 Control 23 */
+ { 0x0B1C, 0x0400 }, /* R2844 - DSP2 Control 24 */
+ { 0x0B1E, 0x0000 }, /* R2846 - DSP2 Control 25 */
+ { 0x0B20, 0x0000 }, /* R2848 - DSP2 Control 26 */
+ { 0x0B21, 0x0000 }, /* R2849 - DSP2 Control 27 */
+ { 0x0B22, 0x0000 }, /* R2850 - DSP2 Control 28 */
+ { 0x0B23, 0x0000 }, /* R2851 - DSP2 Control 29 */
+ { 0x0B24, 0x0000 }, /* R2852 - DSP2 Control 30 */
+ { 0x0B26, 0x0000 }, /* R2854 - DSP2 Control 31 */
+};
+
+static bool wm2200_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM2200_SOFTWARE_RESET:
+ case WM2200_DEVICE_REVISION:
+ case WM2200_ADPS1_IRQ0:
+ case WM2200_ADPS1_IRQ1:
+ case WM2200_INTERRUPT_STATUS_1:
+ case WM2200_INTERRUPT_STATUS_2:
+ case WM2200_INTERRUPT_RAW_STATUS_2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm2200_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM2200_SOFTWARE_RESET:
+ case WM2200_DEVICE_REVISION:
+ case WM2200_TONE_GENERATOR_1:
+ case WM2200_CLOCKING_3:
+ case WM2200_CLOCKING_4:
+ case WM2200_FLL_CONTROL_1:
+ case WM2200_FLL_CONTROL_2:
+ case WM2200_FLL_CONTROL_3:
+ case WM2200_FLL_CONTROL_4:
+ case WM2200_FLL_CONTROL_6:
+ case WM2200_FLL_CONTROL_7:
+ case WM2200_FLL_EFS_1:
+ case WM2200_FLL_EFS_2:
+ case WM2200_MIC_CHARGE_PUMP_1:
+ case WM2200_MIC_CHARGE_PUMP_2:
+ case WM2200_DM_CHARGE_PUMP_1:
+ case WM2200_MIC_BIAS_CTRL_1:
+ case WM2200_MIC_BIAS_CTRL_2:
+ case WM2200_EAR_PIECE_CTRL_1:
+ case WM2200_EAR_PIECE_CTRL_2:
+ case WM2200_INPUT_ENABLES:
+ case WM2200_IN1L_CONTROL:
+ case WM2200_IN1R_CONTROL:
+ case WM2200_IN2L_CONTROL:
+ case WM2200_IN2R_CONTROL:
+ case WM2200_IN3L_CONTROL:
+ case WM2200_IN3R_CONTROL:
+ case WM2200_RXANC_SRC:
+ case WM2200_INPUT_VOLUME_RAMP:
+ case WM2200_ADC_DIGITAL_VOLUME_1L:
+ case WM2200_ADC_DIGITAL_VOLUME_1R:
+ case WM2200_ADC_DIGITAL_VOLUME_2L:
+ case WM2200_ADC_DIGITAL_VOLUME_2R:
+ case WM2200_ADC_DIGITAL_VOLUME_3L:
+ case WM2200_ADC_DIGITAL_VOLUME_3R:
+ case WM2200_OUTPUT_ENABLES:
+ case WM2200_DAC_VOLUME_LIMIT_1L:
+ case WM2200_DAC_VOLUME_LIMIT_1R:
+ case WM2200_DAC_VOLUME_LIMIT_2L:
+ case WM2200_DAC_VOLUME_LIMIT_2R:
+ case WM2200_DAC_AEC_CONTROL_1:
+ case WM2200_OUTPUT_VOLUME_RAMP:
+ case WM2200_DAC_DIGITAL_VOLUME_1L:
+ case WM2200_DAC_DIGITAL_VOLUME_1R:
+ case WM2200_DAC_DIGITAL_VOLUME_2L:
+ case WM2200_DAC_DIGITAL_VOLUME_2R:
+ case WM2200_PDM_1:
+ case WM2200_PDM_2:
+ case WM2200_AUDIO_IF_1_1:
+ case WM2200_AUDIO_IF_1_2:
+ case WM2200_AUDIO_IF_1_3:
+ case WM2200_AUDIO_IF_1_4:
+ case WM2200_AUDIO_IF_1_5:
+ case WM2200_AUDIO_IF_1_6:
+ case WM2200_AUDIO_IF_1_7:
+ case WM2200_AUDIO_IF_1_8:
+ case WM2200_AUDIO_IF_1_9:
+ case WM2200_AUDIO_IF_1_10:
+ case WM2200_AUDIO_IF_1_11:
+ case WM2200_AUDIO_IF_1_12:
+ case WM2200_AUDIO_IF_1_13:
+ case WM2200_AUDIO_IF_1_14:
+ case WM2200_AUDIO_IF_1_15:
+ case WM2200_AUDIO_IF_1_16:
+ case WM2200_AUDIO_IF_1_17:
+ case WM2200_AUDIO_IF_1_18:
+ case WM2200_AUDIO_IF_1_19:
+ case WM2200_AUDIO_IF_1_20:
+ case WM2200_AUDIO_IF_1_21:
+ case WM2200_AUDIO_IF_1_22:
+ case WM2200_OUT1LMIX_INPUT_1_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_1_VOLUME:
+ case WM2200_OUT1LMIX_INPUT_2_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_2_VOLUME:
+ case WM2200_OUT1LMIX_INPUT_3_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_3_VOLUME:
+ case WM2200_OUT1LMIX_INPUT_4_SOURCE:
+ case WM2200_OUT1LMIX_INPUT_4_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_1_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_1_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_2_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_2_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_3_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_3_VOLUME:
+ case WM2200_OUT1RMIX_INPUT_4_SOURCE:
+ case WM2200_OUT1RMIX_INPUT_4_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_1_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_1_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_2_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_2_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_3_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_3_VOLUME:
+ case WM2200_OUT2LMIX_INPUT_4_SOURCE:
+ case WM2200_OUT2LMIX_INPUT_4_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_1_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_1_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_2_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_2_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_3_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_3_VOLUME:
+ case WM2200_OUT2RMIX_INPUT_4_SOURCE:
+ case WM2200_OUT2RMIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX1MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX1MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX2MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX2MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX3MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX3MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX4MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX4MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX5MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX5MIX_INPUT_4_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_1_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_1_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_2_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_2_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_3_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_3_VOLUME:
+ case WM2200_AIF1TX6MIX_INPUT_4_SOURCE:
+ case WM2200_AIF1TX6MIX_INPUT_4_VOLUME:
+ case WM2200_EQLMIX_INPUT_1_SOURCE:
+ case WM2200_EQLMIX_INPUT_1_VOLUME:
+ case WM2200_EQLMIX_INPUT_2_SOURCE:
+ case WM2200_EQLMIX_INPUT_2_VOLUME:
+ case WM2200_EQLMIX_INPUT_3_SOURCE:
+ case WM2200_EQLMIX_INPUT_3_VOLUME:
+ case WM2200_EQLMIX_INPUT_4_SOURCE:
+ case WM2200_EQLMIX_INPUT_4_VOLUME:
+ case WM2200_EQRMIX_INPUT_1_SOURCE:
+ case WM2200_EQRMIX_INPUT_1_VOLUME:
+ case WM2200_EQRMIX_INPUT_2_SOURCE:
+ case WM2200_EQRMIX_INPUT_2_VOLUME:
+ case WM2200_EQRMIX_INPUT_3_SOURCE:
+ case WM2200_EQRMIX_INPUT_3_VOLUME:
+ case WM2200_EQRMIX_INPUT_4_SOURCE:
+ case WM2200_EQRMIX_INPUT_4_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_1_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_1_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_2_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_2_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_3_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_3_VOLUME:
+ case WM2200_LHPF1MIX_INPUT_4_SOURCE:
+ case WM2200_LHPF1MIX_INPUT_4_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_1_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_1_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_2_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_2_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_3_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_3_VOLUME:
+ case WM2200_LHPF2MIX_INPUT_4_SOURCE:
+ case WM2200_LHPF2MIX_INPUT_4_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_1_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_1_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_2_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_2_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_3_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_3_VOLUME:
+ case WM2200_DSP1LMIX_INPUT_4_SOURCE:
+ case WM2200_DSP1LMIX_INPUT_4_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_1_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_1_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_2_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_2_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_3_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_3_VOLUME:
+ case WM2200_DSP1RMIX_INPUT_4_SOURCE:
+ case WM2200_DSP1RMIX_INPUT_4_VOLUME:
+ case WM2200_DSP1AUX1MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX2MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX3MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX4MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX5MIX_INPUT_1_SOURCE:
+ case WM2200_DSP1AUX6MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_1_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_1_VOLUME:
+ case WM2200_DSP2LMIX_INPUT_2_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_2_VOLUME:
+ case WM2200_DSP2LMIX_INPUT_3_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_3_VOLUME:
+ case WM2200_DSP2LMIX_INPUT_4_SOURCE:
+ case WM2200_DSP2LMIX_INPUT_4_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_1_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_1_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_2_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_2_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_3_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_3_VOLUME:
+ case WM2200_DSP2RMIX_INPUT_4_SOURCE:
+ case WM2200_DSP2RMIX_INPUT_4_VOLUME:
+ case WM2200_DSP2AUX1MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX2MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX3MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX4MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX5MIX_INPUT_1_SOURCE:
+ case WM2200_DSP2AUX6MIX_INPUT_1_SOURCE:
+ case WM2200_GPIO_CTRL_1:
+ case WM2200_GPIO_CTRL_2:
+ case WM2200_GPIO_CTRL_3:
+ case WM2200_GPIO_CTRL_4:
+ case WM2200_ADPS1_IRQ0:
+ case WM2200_ADPS1_IRQ1:
+ case WM2200_MISC_PAD_CTRL_1:
+ case WM2200_INTERRUPT_STATUS_1:
+ case WM2200_INTERRUPT_STATUS_1_MASK:
+ case WM2200_INTERRUPT_STATUS_2:
+ case WM2200_INTERRUPT_RAW_STATUS_2:
+ case WM2200_INTERRUPT_STATUS_2_MASK:
+ case WM2200_INTERRUPT_CONTROL:
+ case WM2200_EQL_1:
+ case WM2200_EQL_2:
+ case WM2200_EQL_3:
+ case WM2200_EQL_4:
+ case WM2200_EQL_5:
+ case WM2200_EQL_6:
+ case WM2200_EQL_7:
+ case WM2200_EQL_8:
+ case WM2200_EQL_9:
+ case WM2200_EQL_10:
+ case WM2200_EQL_11:
+ case WM2200_EQL_12:
+ case WM2200_EQL_13:
+ case WM2200_EQL_14:
+ case WM2200_EQL_15:
+ case WM2200_EQL_16:
+ case WM2200_EQL_17:
+ case WM2200_EQL_18:
+ case WM2200_EQL_19:
+ case WM2200_EQL_20:
+ case WM2200_EQR_1:
+ case WM2200_EQR_2:
+ case WM2200_EQR_3:
+ case WM2200_EQR_4:
+ case WM2200_EQR_5:
+ case WM2200_EQR_6:
+ case WM2200_EQR_7:
+ case WM2200_EQR_8:
+ case WM2200_EQR_9:
+ case WM2200_EQR_10:
+ case WM2200_EQR_11:
+ case WM2200_EQR_12:
+ case WM2200_EQR_13:
+ case WM2200_EQR_14:
+ case WM2200_EQR_15:
+ case WM2200_EQR_16:
+ case WM2200_EQR_17:
+ case WM2200_EQR_18:
+ case WM2200_EQR_19:
+ case WM2200_EQR_20:
+ case WM2200_HPLPF1_1:
+ case WM2200_HPLPF1_2:
+ case WM2200_HPLPF2_1:
+ case WM2200_HPLPF2_2:
+ case WM2200_DSP1_CONTROL_1:
+ case WM2200_DSP1_CONTROL_2:
+ case WM2200_DSP1_CONTROL_3:
+ case WM2200_DSP1_CONTROL_4:
+ case WM2200_DSP1_CONTROL_5:
+ case WM2200_DSP1_CONTROL_6:
+ case WM2200_DSP1_CONTROL_7:
+ case WM2200_DSP1_CONTROL_8:
+ case WM2200_DSP1_CONTROL_9:
+ case WM2200_DSP1_CONTROL_10:
+ case WM2200_DSP1_CONTROL_11:
+ case WM2200_DSP1_CONTROL_12:
+ case WM2200_DSP1_CONTROL_13:
+ case WM2200_DSP1_CONTROL_14:
+ case WM2200_DSP1_CONTROL_15:
+ case WM2200_DSP1_CONTROL_16:
+ case WM2200_DSP1_CONTROL_17:
+ case WM2200_DSP1_CONTROL_18:
+ case WM2200_DSP1_CONTROL_19:
+ case WM2200_DSP1_CONTROL_20:
+ case WM2200_DSP1_CONTROL_21:
+ case WM2200_DSP1_CONTROL_22:
+ case WM2200_DSP1_CONTROL_23:
+ case WM2200_DSP1_CONTROL_24:
+ case WM2200_DSP1_CONTROL_25:
+ case WM2200_DSP1_CONTROL_26:
+ case WM2200_DSP1_CONTROL_27:
+ case WM2200_DSP1_CONTROL_28:
+ case WM2200_DSP1_CONTROL_29:
+ case WM2200_DSP1_CONTROL_30:
+ case WM2200_DSP1_CONTROL_31:
+ case WM2200_DSP2_CONTROL_1:
+ case WM2200_DSP2_CONTROL_2:
+ case WM2200_DSP2_CONTROL_3:
+ case WM2200_DSP2_CONTROL_4:
+ case WM2200_DSP2_CONTROL_5:
+ case WM2200_DSP2_CONTROL_6:
+ case WM2200_DSP2_CONTROL_7:
+ case WM2200_DSP2_CONTROL_8:
+ case WM2200_DSP2_CONTROL_9:
+ case WM2200_DSP2_CONTROL_10:
+ case WM2200_DSP2_CONTROL_11:
+ case WM2200_DSP2_CONTROL_12:
+ case WM2200_DSP2_CONTROL_13:
+ case WM2200_DSP2_CONTROL_14:
+ case WM2200_DSP2_CONTROL_15:
+ case WM2200_DSP2_CONTROL_16:
+ case WM2200_DSP2_CONTROL_17:
+ case WM2200_DSP2_CONTROL_18:
+ case WM2200_DSP2_CONTROL_19:
+ case WM2200_DSP2_CONTROL_20:
+ case WM2200_DSP2_CONTROL_21:
+ case WM2200_DSP2_CONTROL_22:
+ case WM2200_DSP2_CONTROL_23:
+ case WM2200_DSP2_CONTROL_24:
+ case WM2200_DSP2_CONTROL_25:
+ case WM2200_DSP2_CONTROL_26:
+ case WM2200_DSP2_CONTROL_27:
+ case WM2200_DSP2_CONTROL_28:
+ case WM2200_DSP2_CONTROL_29:
+ case WM2200_DSP2_CONTROL_30:
+ case WM2200_DSP2_CONTROL_31:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static const struct reg_default wm2200_reva_patch[] = {
+ { 0x07, 0x0003 },
+ { 0x102, 0x0200 },
+ { 0x203, 0x0084 },
+ { 0x201, 0x83FF },
+ { 0x20C, 0x0062 },
+ { 0x20D, 0x0062 },
+ { 0x207, 0x2002 },
+ { 0x208, 0x20C0 },
+ { 0x21D, 0x01C0 },
+ { 0x50A, 0x0001 },
+ { 0x50B, 0x0002 },
+ { 0x50C, 0x0003 },
+ { 0x50D, 0x0004 },
+ { 0x50E, 0x0005 },
+ { 0x510, 0x0001 },
+ { 0x511, 0x0002 },
+ { 0x512, 0x0003 },
+ { 0x513, 0x0004 },
+ { 0x514, 0x0005 },
+ { 0x515, 0x0000 },
+ { 0x201, 0x8084 },
+ { 0x202, 0xBBDE },
+ { 0x203, 0x00EC },
+ { 0x500, 0x8000 },
+ { 0x507, 0x1820 },
+ { 0x508, 0x1820 },
+ { 0x505, 0x0300 },
+ { 0x506, 0x0300 },
+ { 0x302, 0x2280 },
+ { 0x303, 0x0080 },
+ { 0x304, 0x2280 },
+ { 0x305, 0x0080 },
+ { 0x306, 0x2280 },
+ { 0x307, 0x0080 },
+ { 0x401, 0x0080 },
+ { 0x402, 0x0080 },
+ { 0x417, 0x3069 },
+ { 0x900, 0x6318 },
+ { 0x901, 0x6300 },
+ { 0x902, 0x0FC8 },
+ { 0x903, 0x03FE },
+ { 0x904, 0x00E0 },
+ { 0x905, 0x1EC4 },
+ { 0x906, 0xF136 },
+ { 0x907, 0x0409 },
+ { 0x908, 0x04CC },
+ { 0x909, 0x1C9B },
+ { 0x90A, 0xF337 },
+ { 0x90B, 0x040B },
+ { 0x90C, 0x0CBB },
+ { 0x90D, 0x16F8 },
+ { 0x90E, 0xF7D9 },
+ { 0x90F, 0x040A },
+ { 0x910, 0x1F14 },
+ { 0x911, 0x058C },
+ { 0x912, 0x0563 },
+ { 0x913, 0x4000 },
+ { 0x916, 0x6318 },
+ { 0x917, 0x6300 },
+ { 0x918, 0x0FC8 },
+ { 0x919, 0x03FE },
+ { 0x91A, 0x00E0 },
+ { 0x91B, 0x1EC4 },
+ { 0x91C, 0xF136 },
+ { 0x91D, 0x0409 },
+ { 0x91E, 0x04CC },
+ { 0x91F, 0x1C9B },
+ { 0x920, 0xF337 },
+ { 0x921, 0x040B },
+ { 0x922, 0x0CBB },
+ { 0x923, 0x16F8 },
+ { 0x924, 0xF7D9 },
+ { 0x925, 0x040A },
+ { 0x926, 0x1F14 },
+ { 0x927, 0x058C },
+ { 0x928, 0x0563 },
+ { 0x929, 0x4000 },
+ { 0x709, 0x2000 },
+ { 0x207, 0x200E },
+ { 0x208, 0x20D4 },
+ { 0x20A, 0x0080 },
+ { 0x07, 0x0000 },
+};
+
+static int wm2200_reset(struct wm2200_priv *wm2200)
+{
+ if (wm2200->pdata.reset) {
+ gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+ gpio_set_value_cansleep(wm2200->pdata.reset, 1);
+
+ return 0;
+ } else {
+ return regmap_write(wm2200->regmap, WM2200_SOFTWARE_RESET,
+ 0x2200);
+ }
+}
+
+static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
+
+static const char *wm2200_mixer_texts[] = {
+ "None",
+ "Tone Generator",
+ "AEC loopback",
+ "IN1L",
+ "IN1R",
+ "IN2L",
+ "IN2R",
+ "IN3L",
+ "IN3R",
+ "AIF1RX1",
+ "AIF1RX2",
+ "AIF1RX3",
+ "AIF1RX4",
+ "AIF1RX5",
+ "AIF1RX6",
+ "EQL",
+ "EQR",
+ "LHPF1",
+ "LHPF2",
+ "LHPF3",
+ "LHPF4",
+ "DSP1.1",
+ "DSP1.2",
+ "DSP1.3",
+ "DSP1.4",
+ "DSP1.5",
+ "DSP1.6",
+ "DSP2.1",
+ "DSP2.2",
+ "DSP2.3",
+ "DSP2.4",
+ "DSP2.5",
+ "DSP2.6",
+};
+
+static int wm2200_mixer_values[] = {
+ 0x00,
+ 0x04, /* Tone */
+ 0x08, /* AEC */
+ 0x10, /* Input */
+ 0x11,
+ 0x12,
+ 0x13,
+ 0x14,
+ 0x15,
+ 0x20, /* AIF */
+ 0x21,
+ 0x22,
+ 0x23,
+ 0x24,
+ 0x25,
+ 0x50, /* EQ */
+ 0x51,
+ 0x52,
+ 0x60, /* LHPF1 */
+ 0x61, /* LHPF2 */
+ 0x68, /* DSP1 */
+ 0x69,
+ 0x6a,
+ 0x6b,
+ 0x6c,
+ 0x6d,
+ 0x70, /* DSP2 */
+ 0x71,
+ 0x72,
+ 0x73,
+ 0x74,
+ 0x75,
+};
+
+#define WM2200_MIXER_CONTROLS(name, base) \
+ SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
+ WM2200_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
+
+#define WM2200_MUX_ENUM_DECL(name, reg) \
+ SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
+ wm2200_mixer_texts, wm2200_mixer_values)
+
+#define WM2200_MUX_CTL_DECL(name) \
+ const struct snd_kcontrol_new name##_mux = \
+ SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define WM2200_MIXER_ENUMS(name, base_reg) \
+ static WM2200_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
+ static WM2200_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
+ static WM2200_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
+ static WM2200_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
+ static WM2200_MUX_CTL_DECL(name##_in1); \
+ static WM2200_MUX_CTL_DECL(name##_in2); \
+ static WM2200_MUX_CTL_DECL(name##_in3); \
+ static WM2200_MUX_CTL_DECL(name##_in4)
+
+static const struct snd_kcontrol_new wm2200_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", WM2200_IN1L_CONTROL,
+ WM2200_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", WM2200_IN2L_CONTROL,
+ WM2200_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", WM2200_IN3L_CONTROL,
+ WM2200_IN3_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_TLV("IN1 Volume", WM2200_IN1L_CONTROL, WM2200_IN1R_CONTROL,
+ WM2200_IN1L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN2 Volume", WM2200_IN2L_CONTROL, WM2200_IN2R_CONTROL,
+ WM2200_IN2L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN3 Volume", WM2200_IN3L_CONTROL, WM2200_IN3R_CONTROL,
+ WM2200_IN3L_PGA_VOL_SHIFT, 0x5f, 0, in_tlv),
+
+SOC_DOUBLE_R("IN1 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Digital Switch", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_MUTE_SHIFT, 1, 1),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_1R, WM2200_IN1L_DIG_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_2L,
+ WM2200_ADC_DIGITAL_VOLUME_2R, WM2200_IN2L_DIG_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM2200_ADC_DIGITAL_VOLUME_3L,
+ WM2200_ADC_DIGITAL_VOLUME_3R, WM2200_IN3L_DIG_VOL_SHIFT,
+ 0xbf, 0, digital_tlv),
+
+SOC_SINGLE("OUT1 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("OUT2 High Performance Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_OUT2_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R("OUT1 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT1 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_DAC_DIGITAL_VOLUME_1R, WM2200_OUT1L_VOL_SHIFT, 0x9f, 0,
+ digital_tlv),
+SOC_DOUBLE_R_TLV("OUT1 Volume", WM2200_DAC_VOLUME_LIMIT_1L,
+ WM2200_DAC_VOLUME_LIMIT_1R, WM2200_OUT1L_PGA_VOL_SHIFT,
+ 0x46, 0, out_tlv),
+
+SOC_DOUBLE_R("OUT2 Digital Switch", WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R_TLV("OUT2 Digital Volume", WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_DAC_DIGITAL_VOLUME_2R, WM2200_OUT2L_VOL_SHIFT, 0x9f, 0,
+ digital_tlv),
+SOC_DOUBLE("OUT2 Switch", WM2200_PDM_1, WM2200_SPK1L_MUTE_SHIFT,
+ WM2200_SPK1R_MUTE_SHIFT, 1, 0),
+};
+
+WM2200_MIXER_ENUMS(OUT1L, WM2200_OUT1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT1R, WM2200_OUT1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2L, WM2200_OUT2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(OUT2R, WM2200_OUT2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(AIF1TX1, WM2200_AIF1TX1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX2, WM2200_AIF1TX2MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX3, WM2200_AIF1TX3MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX4, WM2200_AIF1TX4MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX5, WM2200_AIF1TX5MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(AIF1TX6, WM2200_AIF1TX6MIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(EQL, WM2200_EQLMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(EQR, WM2200_EQRMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(DSP1L, WM2200_DSP1LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP1R, WM2200_DSP1RMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2L, WM2200_DSP2LMIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(DSP2R, WM2200_DSP2RMIX_INPUT_1_SOURCE);
+
+WM2200_MIXER_ENUMS(LHPF1, WM2200_LHPF1MIX_INPUT_1_SOURCE);
+WM2200_MIXER_ENUMS(LHPF2, WM2200_LHPF2MIX_INPUT_1_SOURCE);
+
+#define WM2200_MUX(name, ctrl) \
+ SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define WM2200_MIXER_WIDGETS(name, name_str) \
+ WM2200_MUX(name_str " Input 1", &name##_in1_mux), \
+ WM2200_MUX(name_str " Input 2", &name##_in2_mux), \
+ WM2200_MUX(name_str " Input 3", &name##_in3_mux), \
+ WM2200_MUX(name_str " Input 4", &name##_in4_mux), \
+ SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define WM2200_MIXER_INPUT_ROUTES(name) \
+ { name, "Tone Generator", "Tone Generator" }, \
+ { name, "IN1L", "IN1L PGA" }, \
+ { name, "IN1R", "IN1R PGA" }, \
+ { name, "IN2L", "IN2L PGA" }, \
+ { name, "IN2R", "IN2R PGA" }, \
+ { name, "IN3L", "IN3L PGA" }, \
+ { name, "IN3R", "IN3R PGA" }, \
+ { name, "DSP1.1", "DSP1" }, \
+ { name, "DSP1.2", "DSP1" }, \
+ { name, "DSP1.3", "DSP1" }, \
+ { name, "DSP1.4", "DSP1" }, \
+ { name, "DSP1.5", "DSP1" }, \
+ { name, "DSP1.6", "DSP1" }, \
+ { name, "DSP2.1", "DSP2" }, \
+ { name, "DSP2.2", "DSP2" }, \
+ { name, "DSP2.3", "DSP2" }, \
+ { name, "DSP2.4", "DSP2" }, \
+ { name, "DSP2.5", "DSP2" }, \
+ { name, "DSP2.6", "DSP2" }, \
+ { name, "AIF1RX1", "AIF1RX1" }, \
+ { name, "AIF1RX2", "AIF1RX2" }, \
+ { name, "AIF1RX3", "AIF1RX3" }, \
+ { name, "AIF1RX4", "AIF1RX4" }, \
+ { name, "AIF1RX5", "AIF1RX5" }, \
+ { name, "AIF1RX6", "AIF1RX6" }, \
+ { name, "EQL", "EQL" }, \
+ { name, "EQR", "EQR" }, \
+ { name, "LHPF1", "LHPF1" }, \
+ { name, "LHPF2", "LHPF2" }
+
+#define WM2200_MIXER_ROUTES(widget, name) \
+ { widget, NULL, name " Mixer" }, \
+ { name " Mixer", NULL, name " Input 1" }, \
+ { name " Mixer", NULL, name " Input 2" }, \
+ { name " Mixer", NULL, name " Input 3" }, \
+ { name " Mixer", NULL, name " Input 4" }, \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 1"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 2"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 3"), \
+ WM2200_MIXER_INPUT_ROUTES(name " Input 4")
+
+static const struct snd_soc_dapm_widget wm2200_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM2200_CLOCKING_3, WM2200_SYSCLK_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP1", WM2200_DM_CHARGE_PUMP_1, WM2200_CPDM_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2", WM2200_MIC_CHARGE_PUMP_1, WM2200_CPMIC_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM2200_MIC_BIAS_CTRL_1, WM2200_MICB1_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM2200_MIC_BIAS_CTRL_2, WM2200_MICB2_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("AVDD", 20),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+
+SND_SOC_DAPM_SIGGEN("TONE"),
+SND_SOC_DAPM_PGA("Tone Generator", WM2200_TONE_GENERATOR_1,
+ WM2200_TONE_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("IN1L PGA", WM2200_INPUT_ENABLES, WM2200_IN1L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN1R PGA", WM2200_INPUT_ENABLES, WM2200_IN1R_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN2L PGA", WM2200_INPUT_ENABLES, WM2200_IN2L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN2R PGA", WM2200_INPUT_ENABLES, WM2200_IN2R_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN3L PGA", WM2200_INPUT_ENABLES, WM2200_IN3L_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("IN3R PGA", WM2200_INPUT_ENABLES, WM2200_IN3R_ENA_SHIFT, 0,
+ NULL, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "Playback", 0,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "Playback", 1,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "Playback", 2,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "Playback", 3,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "Playback", 4,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", "Playback", 5,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1RX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA("EQL", WM2200_EQL_1, WM2200_EQL_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQR", WM2200_EQR_1, WM2200_EQR_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", WM2200_HPLPF1_1, WM2200_LHPF1_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", WM2200_HPLPF2_1, WM2200_LHPF2_ENA_SHIFT, 0,
+ NULL, 0),
+
+SND_SOC_DAPM_PGA_E("DSP1", SND_SOC_NOPM, 0, 0, NULL, 0, NULL, 0),
+SND_SOC_DAPM_PGA_E("DSP2", SND_SOC_NOPM, 1, 0, NULL, 0, NULL, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "Capture", 0,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "Capture", 1,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "Capture", 2,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "Capture", 3,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "Capture", 4,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", "Capture", 5,
+ WM2200_AUDIO_IF_1_22, WM2200_AIF1TX6_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_S("OUT1L", 0, WM2200_OUTPUT_ENABLES,
+ WM2200_OUT1L_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("OUT1R", 0, WM2200_OUTPUT_ENABLES,
+ WM2200_OUT1R_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_OUTP_LP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LP", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_RMV_SHRT_LP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_OUTP_LN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_LN", 1, WM2200_EAR_PIECE_CTRL_1,
+ WM2200_EPD_RMV_SHRT_LN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_OUTP_RP_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RP", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RMV_SHRT_RP_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA_S("EPD_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_OUTP_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_OUTP_RN_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA_S("EPD_RMV_SHRT_RN", 1, WM2200_EAR_PIECE_CTRL_2,
+ WM2200_EPD_RMV_SHRT_RN_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("OUT2L", WM2200_OUTPUT_ENABLES, WM2200_OUT2L_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_PGA("OUT2R", WM2200_OUTPUT_ENABLES, WM2200_OUT2R_ENA_SHIFT,
+ 0, NULL, 0),
+
+SND_SOC_DAPM_OUTPUT("EPOUTLN"),
+SND_SOC_DAPM_OUTPUT("EPOUTLP"),
+SND_SOC_DAPM_OUTPUT("EPOUTRN"),
+SND_SOC_DAPM_OUTPUT("EPOUTRP"),
+SND_SOC_DAPM_OUTPUT("SPK"),
+
+WM2200_MIXER_WIDGETS(EQL, "EQL"),
+WM2200_MIXER_WIDGETS(EQR, "EQR"),
+
+WM2200_MIXER_WIDGETS(LHPF1, "LHPF1"),
+WM2200_MIXER_WIDGETS(LHPF2, "LHPF2"),
+
+WM2200_MIXER_WIDGETS(DSP1L, "DSP1L"),
+WM2200_MIXER_WIDGETS(DSP1R, "DSP1R"),
+WM2200_MIXER_WIDGETS(DSP2L, "DSP2L"),
+WM2200_MIXER_WIDGETS(DSP2R, "DSP2R"),
+
+WM2200_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+WM2200_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+WM2200_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+WM2200_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+WM2200_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+WM2200_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+
+WM2200_MIXER_WIDGETS(OUT1L, "OUT1L"),
+WM2200_MIXER_WIDGETS(OUT1R, "OUT1R"),
+WM2200_MIXER_WIDGETS(OUT2L, "OUT2L"),
+WM2200_MIXER_WIDGETS(OUT2R, "OUT2R"),
+};
+
+static const struct snd_soc_dapm_route wm2200_dapm_routes[] = {
+ /* Everything needs SYSCLK but only hook up things on the edge
+ * of the chip */
+ { "IN1L", NULL, "SYSCLK" },
+ { "IN1R", NULL, "SYSCLK" },
+ { "IN2L", NULL, "SYSCLK" },
+ { "IN2R", NULL, "SYSCLK" },
+ { "IN3L", NULL, "SYSCLK" },
+ { "IN3R", NULL, "SYSCLK" },
+ { "OUT1L", NULL, "SYSCLK" },
+ { "OUT1R", NULL, "SYSCLK" },
+ { "OUT2L", NULL, "SYSCLK" },
+ { "OUT2R", NULL, "SYSCLK" },
+ { "AIF1RX1", NULL, "SYSCLK" },
+ { "AIF1RX2", NULL, "SYSCLK" },
+ { "AIF1RX3", NULL, "SYSCLK" },
+ { "AIF1RX4", NULL, "SYSCLK" },
+ { "AIF1RX5", NULL, "SYSCLK" },
+ { "AIF1RX6", NULL, "SYSCLK" },
+ { "AIF1TX1", NULL, "SYSCLK" },
+ { "AIF1TX2", NULL, "SYSCLK" },
+ { "AIF1TX3", NULL, "SYSCLK" },
+ { "AIF1TX4", NULL, "SYSCLK" },
+ { "AIF1TX5", NULL, "SYSCLK" },
+ { "AIF1TX6", NULL, "SYSCLK" },
+
+ { "IN1L", NULL, "AVDD" },
+ { "IN1R", NULL, "AVDD" },
+ { "IN2L", NULL, "AVDD" },
+ { "IN2R", NULL, "AVDD" },
+ { "IN3L", NULL, "AVDD" },
+ { "IN3R", NULL, "AVDD" },
+ { "OUT1L", NULL, "AVDD" },
+ { "OUT1R", NULL, "AVDD" },
+
+ { "IN1L PGA", NULL, "IN1L" },
+ { "IN1R PGA", NULL, "IN1R" },
+ { "IN2L PGA", NULL, "IN2L" },
+ { "IN2R PGA", NULL, "IN2R" },
+ { "IN3L PGA", NULL, "IN3L" },
+ { "IN3R PGA", NULL, "IN3R" },
+
+ { "Tone Generator", NULL, "TONE" },
+
+ { "CP2", NULL, "CPVDD" },
+ { "MICBIAS1", NULL, "CP2" },
+ { "MICBIAS2", NULL, "CP2" },
+
+ { "CP1", NULL, "CPVDD" },
+ { "EPD_LN", NULL, "CP1" },
+ { "EPD_LP", NULL, "CP1" },
+ { "EPD_RN", NULL, "CP1" },
+ { "EPD_RP", NULL, "CP1" },
+
+ { "EPD_LP", NULL, "OUT1L" },
+ { "EPD_OUTP_LP", NULL, "EPD_LP" },
+ { "EPD_RMV_SHRT_LP", NULL, "EPD_OUTP_LP" },
+ { "EPOUTLP", NULL, "EPD_RMV_SHRT_LP" },
+
+ { "EPD_LN", NULL, "OUT1L" },
+ { "EPD_OUTP_LN", NULL, "EPD_LN" },
+ { "EPD_RMV_SHRT_LN", NULL, "EPD_OUTP_LN" },
+ { "EPOUTLN", NULL, "EPD_RMV_SHRT_LN" },
+
+ { "EPD_RP", NULL, "OUT1R" },
+ { "EPD_OUTP_RP", NULL, "EPD_RP" },
+ { "EPD_RMV_SHRT_RP", NULL, "EPD_OUTP_RP" },
+ { "EPOUTRP", NULL, "EPD_RMV_SHRT_RP" },
+
+ { "EPD_RN", NULL, "OUT1R" },
+ { "EPD_OUTP_RN", NULL, "EPD_RN" },
+ { "EPD_RMV_SHRT_RN", NULL, "EPD_OUTP_RN" },
+ { "EPOUTRN", NULL, "EPD_RMV_SHRT_RN" },
+
+ { "SPK", NULL, "OUT2L" },
+ { "SPK", NULL, "OUT2R" },
+
+ WM2200_MIXER_ROUTES("DSP1", "DSP1L"),
+ WM2200_MIXER_ROUTES("DSP1", "DSP1R"),
+ WM2200_MIXER_ROUTES("DSP2", "DSP2L"),
+ WM2200_MIXER_ROUTES("DSP2", "DSP2R"),
+
+ WM2200_MIXER_ROUTES("OUT1L", "OUT1L"),
+ WM2200_MIXER_ROUTES("OUT1R", "OUT1R"),
+ WM2200_MIXER_ROUTES("OUT2L", "OUT2L"),
+ WM2200_MIXER_ROUTES("OUT2R", "OUT2R"),
+
+ WM2200_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+ WM2200_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+ WM2200_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+ WM2200_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+ WM2200_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+ WM2200_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+
+ WM2200_MIXER_ROUTES("EQL", "EQL"),
+ WM2200_MIXER_ROUTES("EQR", "EQR"),
+
+ WM2200_MIXER_ROUTES("LHPF1", "LHPF1"),
+ WM2200_MIXER_ROUTES("LHPF2", "LHPF2"),
+};
+
+static int wm2200_probe(struct snd_soc_codec *codec)
+{
+ struct wm2200_priv *wm2200 = dev_get_drvdata(codec->dev);
+ int ret;
+
+ wm2200->codec = codec;
+ codec->control_data = wm2200->regmap;
+ codec->dapm.bias_level = SND_SOC_BIAS_OFF;
+
+ ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ return ret;
+}
+
+static int wm2200_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int lrclk, bclk, fmt_val;
+
+ lrclk = 0;
+ bclk = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ fmt_val = 0;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ fmt_val = 1;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ fmt_val = 2;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ fmt_val = 3;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported DAI format %d\n",
+ fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ bclk |= WM2200_AIF1_BCLK_MSTR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ lrclk |= WM2200_AIF1TX_LRCLK_MSTR;
+ bclk |= WM2200_AIF1_BCLK_MSTR;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported master mode %d\n",
+ fmt & SND_SOC_DAIFMT_MASTER_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ bclk |= WM2200_AIF1_BCLK_INV;
+ lrclk |= WM2200_AIF1TX_LRCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ bclk |= WM2200_AIF1_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ lrclk |= WM2200_AIF1TX_LRCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1, WM2200_AIF1_BCLK_MSTR |
+ WM2200_AIF1_BCLK_INV, bclk);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+ WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+ lrclk);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_3,
+ WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
+ lrclk);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
+ WM2200_AIF1_FMT_MASK << 1, fmt_val << 1);
+
+ return 0;
+}
+
+static int wm2200_sr_code[] = {
+ 0,
+ 12000,
+ 24000,
+ 48000,
+ 96000,
+ 192000,
+ 384000,
+ 768000,
+ 0,
+ 11025,
+ 22050,
+ 44100,
+ 88200,
+ 176400,
+ 352800,
+ 705600,
+ 4000,
+ 8000,
+ 16000,
+ 32000,
+ 64000,
+ 128000,
+ 256000,
+ 512000,
+};
+
+#define WM2200_NUM_BCLK_RATES 12
+
+static int wm2200_bclk_rates_dat[WM2200_NUM_BCLK_RATES] = {
+ 6144000,
+ 3072000,
+ 2048000,
+ 1536000,
+ 768000,
+ 512000,
+ 384000,
+ 256000,
+ 192000,
+ 128000,
+ 96000,
+ 64000,
+};
+
+static int wm2200_bclk_rates_cd[WM2200_NUM_BCLK_RATES] = {
+ 5644800,
+ 2882400,
+ 1881600,
+ 1411200,
+ 705600,
+ 470400,
+ 352800,
+ 176400,
+ 117600,
+ 88200,
+ 58800,
+};
+
+static int wm2200_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+ int i, bclk, lrclk, wl, fl, sr_code;
+ int *bclk_rates;
+
+ /* Data sizes if not using TDM */
+ wl = snd_pcm_format_width(params_format(params));
+ if (wl < 0)
+ return wl;
+ fl = snd_soc_params_to_frame_size(params);
+ if (fl < 0)
+ return fl;
+
+ dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
+ wl, fl);
+
+ /* Target BCLK rate */
+ bclk = snd_soc_params_to_bclk(params);
+ if (bclk < 0)
+ return bclk;
+
+ if (!wm2200->sysclk) {
+ dev_err(codec->dev, "SYSCLK has no rate set\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_sr_code); i++)
+ if (wm2200_sr_code[i] == params_rate(params))
+ break;
+ if (i == ARRAY_SIZE(wm2200_sr_code)) {
+ dev_err(codec->dev, "Unsupported sample rate: %dHz\n",
+ params_rate(params));
+ return -EINVAL;
+ }
+ sr_code = i;
+
+ dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz SYSCLK\n",
+ bclk, wm2200->sysclk);
+
+ if (wm2200->sysclk % 4000)
+ bclk_rates = wm2200_bclk_rates_cd;
+ else
+ bclk_rates = wm2200_bclk_rates_dat;
+
+ for (i = 0; i < WM2200_NUM_BCLK_RATES; i++)
+ if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
+ break;
+ if (i == WM2200_NUM_BCLK_RATES) {
+ dev_err(codec->dev,
+ "No valid BCLK for %dHz found from %dHz SYSCLK\n",
+ bclk, wm2200->sysclk);
+ return -EINVAL;
+ }
+
+ bclk = i;
+ dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_1,
+ WM2200_AIF1_BCLK_DIV_MASK, bclk);
+
+ lrclk = bclk_rates[bclk] / params_rate(params);
+ dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+ dai->symmetric_rates)
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_7,
+ WM2200_AIF1RX_BCPF_MASK, lrclk);
+ else
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_6,
+ WM2200_AIF1TX_BCPF_MASK, lrclk);
+
+ i = (wl << WM2200_AIF1TX_WL_SHIFT) | wl;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_9,
+ WM2200_AIF1RX_WL_MASK |
+ WM2200_AIF1RX_SLOT_LEN_MASK, i);
+ else
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_8,
+ WM2200_AIF1TX_WL_MASK |
+ WM2200_AIF1TX_SLOT_LEN_MASK, i);
+
+ snd_soc_update_bits(codec, WM2200_CLOCKING_4,
+ WM2200_SAMPLE_RATE_1_MASK, sr_code);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops wm2200_dai_ops = {
+ .set_fmt = wm2200_set_fmt,
+ .hw_params = wm2200_hw_params,
+};
+
+static int wm2200_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+ int source, unsigned int freq, int dir)
+{
+ struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+ int fval;
+
+ switch (clk_id) {
+ case WM2200_CLK_SYSCLK:
+ break;
+
+ default:
+ dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ switch (source) {
+ case WM2200_CLKSRC_MCLK1:
+ case WM2200_CLKSRC_MCLK2:
+ case WM2200_CLKSRC_FLL:
+ case WM2200_CLKSRC_BCLK1:
+ break;
+ default:
+ dev_err(codec->dev, "Invalid source %d\n", source);
+ return -EINVAL;
+ }
+
+ switch (freq) {
+ case 22579200:
+ case 24576000:
+ fval = 2;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
+ return -EINVAL;
+ }
+
+ /* TODO: Check if MCLKs are in use and enable/disable pulls to
+ * match.
+ */
+
+ snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_FREQ_MASK |
+ WM2200_SYSCLK_SRC_MASK,
+ fval << WM2200_SYSCLK_FREQ_SHIFT | source);
+
+ wm2200->sysclk = freq;
+
+ return 0;
+}
+
+struct _fll_div {
+ u16 fll_fratio;
+ u16 fll_outdiv;
+ u16 fll_refclk_div;
+ u16 n;
+ u16 theta;
+ u16 lambda;
+};
+
+static struct {
+ unsigned int min;
+ unsigned int max;
+ u16 fll_fratio;
+ int ratio;
+} fll_fratios[] = {
+ { 0, 64000, 4, 16 },
+ { 64000, 128000, 3, 8 },
+ { 128000, 256000, 2, 4 },
+ { 256000, 1000000, 1, 2 },
+ { 1000000, 13500000, 0, 1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+ unsigned int Fout)
+{
+ unsigned int target;
+ unsigned int div;
+ unsigned int fratio, gcd_fll;
+ int i;
+
+ /* Fref must be <=13.5MHz */
+ div = 1;
+ fll_div->fll_refclk_div = 0;
+ while ((Fref / div) > 13500000) {
+ div *= 2;
+ fll_div->fll_refclk_div++;
+
+ if (div > 8) {
+ pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+ Fref);
+ return -EINVAL;
+ }
+ }
+
+ pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+ /* Apply the division for our remaining calculations */
+ Fref /= div;
+
+ /* Fvco should be 90-100MHz; don't check the upper bound */
+ div = 2;
+ while (Fout * div < 90000000) {
+ div++;
+ if (div > 64) {
+ pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+ Fout);
+ return -EINVAL;
+ }
+ }
+ target = Fout * div;
+ fll_div->fll_outdiv = div - 1;
+
+ pr_debug("FLL Fvco=%dHz\n", target);
+
+ /* Find an appropraite FLL_FRATIO and factor it out of the target */
+ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+ if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+ fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+ fratio = fll_fratios[i].ratio;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(fll_fratios)) {
+ pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+ return -EINVAL;
+ }
+
+ fll_div->n = target / (fratio * Fref);
+
+ if (target % Fref == 0) {
+ fll_div->theta = 0;
+ fll_div->lambda = 0;
+ } else {
+ gcd_fll = gcd(target, fratio * Fref);
+
+ fll_div->theta = (target - (fll_div->n * fratio * Fref))
+ / gcd_fll;
+ fll_div->lambda = (fratio * Fref) / gcd_fll;
+ }
+
+ pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+ fll_div->n, fll_div->theta, fll_div->lambda);
+ pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+ fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
+ fll_div->fll_refclk_div);
+
+ return 0;
+}
+
+static int wm2200_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+ unsigned int Fref, unsigned int Fout)
+{
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
+ struct wm2200_priv *wm2200 = snd_soc_codec_get_drvdata(codec);
+ struct _fll_div factors;
+ int ret, i, timeout;
+
+ if (!Fout) {
+ dev_dbg(codec->dev, "FLL disabled");
+
+ if (wm2200->fll_fout)
+ pm_runtime_put(codec->dev);
+
+ wm2200->fll_fout = 0;
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+ WM2200_FLL_ENA, 0);
+ return 0;
+ }
+
+ switch (source) {
+ case WM2200_FLL_SRC_MCLK1:
+ case WM2200_FLL_SRC_MCLK2:
+ case WM2200_FLL_SRC_BCLK:
+ break;
+ default:
+ dev_err(codec->dev, "Invalid FLL source %d\n", source);
+ return -EINVAL;
+ }
+
+ ret = fll_factors(&factors, Fref, Fout);
+ if (ret < 0)
+ return ret;
+
+ /* Disable the FLL while we reconfigure */
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1, WM2200_FLL_ENA, 0);
+
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_2,
+ WM2200_FLL_OUTDIV_MASK | WM2200_FLL_FRATIO_MASK,
+ (factors.fll_outdiv << WM2200_FLL_OUTDIV_SHIFT) |
+ factors.fll_fratio);
+ if (factors.theta) {
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+ WM2200_FLL_FRACN_ENA,
+ WM2200_FLL_FRACN_ENA);
+ snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+ WM2200_FLL_EFS_ENA,
+ WM2200_FLL_EFS_ENA);
+ } else {
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_3,
+ WM2200_FLL_FRACN_ENA, 0);
+ snd_soc_update_bits(codec, WM2200_FLL_EFS_2,
+ WM2200_FLL_EFS_ENA, 0);
+ }
+
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_4, WM2200_FLL_THETA_MASK,
+ factors.theta);
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_6, WM2200_FLL_N_MASK,
+ factors.n);
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_7,
+ WM2200_FLL_CLK_REF_DIV_MASK |
+ WM2200_FLL_CLK_REF_SRC_MASK,
+ (factors.fll_refclk_div
+ << WM2200_FLL_CLK_REF_DIV_SHIFT) | source);
+ snd_soc_update_bits(codec, WM2200_FLL_EFS_1,
+ WM2200_FLL_LAMBDA_MASK, factors.lambda);
+
+ /* Clear any pending completions */
+ try_wait_for_completion(&wm2200->fll_lock);
+
+ pm_runtime_get_sync(codec->dev);
+
+ snd_soc_update_bits(codec, WM2200_FLL_CONTROL_1,
+ WM2200_FLL_ENA, WM2200_FLL_ENA);
+
+ if (i2c->irq)
+ timeout = 2;
+ else
+ timeout = 50;
+
+ snd_soc_update_bits(codec, WM2200_CLOCKING_3, WM2200_SYSCLK_ENA,
+ WM2200_SYSCLK_ENA);
+
+ /* Poll for the lock; will use the interrupt to exit quickly */
+ for (i = 0; i < timeout; i++) {
+ if (i2c->irq) {
+ ret = wait_for_completion_timeout(&wm2200->fll_lock,
+ msecs_to_jiffies(25));
+ if (ret > 0)
+ break;
+ } else {
+ msleep(1);
+ }
+
+ ret = snd_soc_read(codec,
+ WM2200_INTERRUPT_RAW_STATUS_2);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to read FLL status: %d\n",
+ ret);
+ continue;
+ }
+ if (ret & WM2200_FLL_LOCK_STS)
+ break;
+ }
+ if (i == timeout) {
+ dev_err(codec->dev, "FLL lock timed out\n");
+ pm_runtime_put(codec->dev);
+ return -ETIMEDOUT;
+ }
+
+ wm2200->fll_src = source;
+ wm2200->fll_fref = Fref;
+ wm2200->fll_fout = Fout;
+
+ dev_dbg(codec->dev, "FLL running %dHz->%dHz\n", Fref, Fout);
+
+ return 0;
+}
+
+static int wm2200_dai_probe(struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ unsigned int val = 0;
+ int ret;
+
+ ret = snd_soc_read(codec, WM2200_GPIO_CTRL_1);
+ if (ret >= 0) {
+ if ((ret & WM2200_GP1_FN_MASK) != 0) {
+ dai->symmetric_rates = true;
+ val = WM2200_AIF1TX_LRCLK_SRC;
+ }
+ } else {
+ dev_err(codec->dev, "Failed to read GPIO 1 config: %d\n", ret);
+ }
+
+ snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_2,
+ WM2200_AIF1TX_LRCLK_SRC, val);
+
+ return 0;
+}
+
+#define WM2200_RATES SNDRV_PCM_RATE_8000_48000
+
+#define WM2200_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm2200_dai = {
+ .name = "wm2200",
+ .probe = wm2200_dai_probe,
+ .playback = {
+ .stream_name = "Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM2200_RATES,
+ .formats = WM2200_FORMATS,
+ },
+ .capture = {
+ .stream_name = "Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM2200_RATES,
+ .formats = WM2200_FORMATS,
+ },
+ .ops = &wm2200_dai_ops,
+};
+
+static struct snd_soc_codec_driver soc_codec_wm2200 = {
+ .probe = wm2200_probe,
+
+ .idle_bias_off = true,
+ .ignore_pmdown_time = true,
+ .set_sysclk = wm2200_set_sysclk,
+ .set_pll = wm2200_set_fll,
+
+ .controls = wm2200_snd_controls,
+ .num_controls = ARRAY_SIZE(wm2200_snd_controls),
+ .dapm_widgets = wm2200_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm2200_dapm_widgets),
+ .dapm_routes = wm2200_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm2200_dapm_routes),
+};
+
+static irqreturn_t wm2200_irq(int irq, void *data)
+{
+ struct wm2200_priv *wm2200 = data;
+ unsigned int val, mask;
+ int ret;
+
+ ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, &val);
+ if (ret != 0) {
+ dev_err(wm2200->dev, "Failed to read IRQ status: %d\n", ret);
+ return IRQ_NONE;
+ }
+
+ ret = regmap_read(wm2200->regmap, WM2200_INTERRUPT_STATUS_2_MASK,
+ &mask);
+ if (ret != 0) {
+ dev_warn(wm2200->dev, "Failed to read IRQ mask: %d\n", ret);
+ mask = 0;
+ }
+
+ val &= ~mask;
+
+ if (val & WM2200_FLL_LOCK_EINT) {
+ dev_dbg(wm2200->dev, "FLL locked\n");
+ complete(&wm2200->fll_lock);
+ }
+
+ if (val) {
+ regmap_write(wm2200->regmap, WM2200_INTERRUPT_STATUS_2, val);
+
+ return IRQ_HANDLED;
+ } else {
+ return IRQ_NONE;
+ }
+}
+
+static const struct regmap_config wm2200_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .max_register = WM2200_MAX_REGISTER,
+ .reg_defaults = wm2200_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm2200_reg_defaults),
+ .volatile_reg = wm2200_volatile_register,
+ .readable_reg = wm2200_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static const unsigned int wm2200_dig_vu[] = {
+ WM2200_DAC_DIGITAL_VOLUME_1L,
+ WM2200_DAC_DIGITAL_VOLUME_1R,
+ WM2200_DAC_DIGITAL_VOLUME_2L,
+ WM2200_DAC_DIGITAL_VOLUME_2R,
+ WM2200_ADC_DIGITAL_VOLUME_1L,
+ WM2200_ADC_DIGITAL_VOLUME_1R,
+ WM2200_ADC_DIGITAL_VOLUME_2L,
+ WM2200_ADC_DIGITAL_VOLUME_2R,
+ WM2200_ADC_DIGITAL_VOLUME_3L,
+ WM2200_ADC_DIGITAL_VOLUME_3R,
+};
+
+static const unsigned int wm2200_mic_ctrl_reg[] = {
+ WM2200_IN1L_CONTROL,
+ WM2200_IN2L_CONTROL,
+ WM2200_IN3L_CONTROL,
+};
+
+static __devinit int wm2200_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm2200_pdata *pdata = dev_get_platdata(&i2c->dev);
+ struct wm2200_priv *wm2200;
+ unsigned int reg;
+ int ret, i;
+
+ wm2200 = devm_kzalloc(&i2c->dev, sizeof(struct wm2200_priv),
+ GFP_KERNEL);
+ if (wm2200 == NULL)
+ return -ENOMEM;
+
+ wm2200->dev = &i2c->dev;
+ init_completion(&wm2200->fll_lock);
+
+ wm2200->regmap = regmap_init_i2c(i2c, &wm2200_regmap);
+ if (IS_ERR(wm2200->regmap)) {
+ ret = PTR_ERR(wm2200->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
+ if (pdata)
+ wm2200->pdata = *pdata;
+
+ i2c_set_clientdata(i2c, wm2200);
+
+ for (i = 0; i < ARRAY_SIZE(wm2200->core_supplies); i++)
+ wm2200->core_supplies[i].supply = wm2200_core_supply_names[i];
+
+ ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
+ ret);
+ goto err_regmap;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
+ ret);
+ goto err_core;
+ }
+
+ if (wm2200->pdata.ldo_ena) {
+ ret = gpio_request_one(wm2200->pdata.ldo_ena,
+ GPIOF_OUT_INIT_HIGH, "WM2200 LDOENA");
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+ wm2200->pdata.ldo_ena, ret);
+ goto err_enable;
+ }
+ msleep(2);
+ }
+
+ if (wm2200->pdata.reset) {
+ ret = gpio_request_one(wm2200->pdata.reset,
+ GPIOF_OUT_INIT_HIGH, "WM2200 /RESET");
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+ wm2200->pdata.reset, ret);
+ goto err_ldo;
+ }
+ }
+
+ ret = regmap_read(wm2200->regmap, WM2200_SOFTWARE_RESET, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+ goto err_reset;
+ }
+ switch (reg) {
+ case 0x2200:
+ break;
+
+ default:
+ dev_err(&i2c->dev, "Device is not a WM2200, ID is %x\n", reg);
+ ret = -EINVAL;
+ goto err_reset;
+ }
+
+ ret = regmap_read(wm2200->regmap, WM2200_DEVICE_REVISION, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read revision register\n");
+ goto err_reset;
+ }
+
+ wm2200->rev = reg & WM2200_DEVICE_REVISION_MASK;
+
+ dev_info(&i2c->dev, "revision %c\n", wm2200->rev + 'A');
+
+ switch (wm2200->rev) {
+ case 0:
+ ret = regmap_register_patch(wm2200->regmap, wm2200_reva_patch,
+ ARRAY_SIZE(wm2200_reva_patch));
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register patch: %d\n",
+ ret);
+ }
+ break;
+ default:
+ break;
+ }
+
+ ret = wm2200_reset(wm2200);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to issue reset\n");
+ goto err_reset;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200->pdata.gpio_defaults); i++) {
+ if (!wm2200->pdata.gpio_defaults[i])
+ continue;
+
+ regmap_write(wm2200->regmap, WM2200_GPIO_CTRL_1 + i,
+ wm2200->pdata.gpio_defaults[i]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200_dig_vu); i++)
+ regmap_update_bits(wm2200->regmap, wm2200_dig_vu[i],
+ WM2200_OUT_VU, WM2200_OUT_VU);
+
+ /* Assign slots 1-6 to channels 1-6 for both TX and RX */
+ for (i = 0; i < 6; i++) {
+ regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_10 + i, i);
+ regmap_write(wm2200->regmap, WM2200_AUDIO_IF_1_16 + i, i);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm2200->pdata.in_mode); i++) {
+ regmap_update_bits(wm2200->regmap, wm2200_mic_ctrl_reg[i],
+ WM2200_IN1_MODE_MASK |
+ WM2200_IN1_DMIC_SUP_MASK,
+ (wm2200->pdata.in_mode[i] <<
+ WM2200_IN1_MODE_SHIFT) |
+ (wm2200->pdata.dmic_sup[i] <<
+ WM2200_IN1_DMIC_SUP_SHIFT));
+ }
+
+ if (i2c->irq) {
+ ret = request_threaded_irq(i2c->irq, NULL, wm2200_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "wm2200", wm2200);
+ if (ret == 0)
+ regmap_update_bits(wm2200->regmap,
+ WM2200_INTERRUPT_STATUS_2_MASK,
+ WM2200_FLL_LOCK_EINT, 0);
+ else
+ dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+ i2c->irq, ret);
+ }
+
+ pm_runtime_set_active(&i2c->dev);
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_wm2200,
+ &wm2200_dai, 1);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_pm_runtime;
+ }
+
+ return 0;
+
+err_pm_runtime:
+ pm_runtime_disable(&i2c->dev);
+err_reset:
+ if (wm2200->pdata.reset) {
+ gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+ gpio_free(wm2200->pdata.reset);
+ }
+err_ldo:
+ if (wm2200->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+ gpio_free(wm2200->pdata.ldo_ena);
+ }
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+err_core:
+ regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+err_regmap:
+ regmap_exit(wm2200->regmap);
+err:
+ return ret;
+}
+
+static __devexit int wm2200_i2c_remove(struct i2c_client *i2c)
+{
+ struct wm2200_priv *wm2200 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ if (i2c->irq)
+ free_irq(i2c->irq, wm2200);
+ if (wm2200->pdata.reset) {
+ gpio_set_value_cansleep(wm2200->pdata.reset, 0);
+ gpio_free(wm2200->pdata.reset);
+ }
+ if (wm2200->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+ gpio_free(wm2200->pdata.ldo_ena);
+ }
+ regulator_bulk_free(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ regmap_exit(wm2200->regmap);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int wm2200_runtime_suspend(struct device *dev)
+{
+ struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+
+ regcache_cache_only(wm2200->regmap, true);
+ regcache_mark_dirty(wm2200->regmap);
+ if (wm2200->pdata.ldo_ena)
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 0);
+ regulator_bulk_disable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+
+ return 0;
+}
+
+static int wm2200_runtime_resume(struct device *dev)
+{
+ struct wm2200_priv *wm2200 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm2200->core_supplies),
+ wm2200->core_supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (wm2200->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm2200->pdata.ldo_ena, 1);
+ msleep(2);
+ }
+
+ regcache_cache_only(wm2200->regmap, false);
+ regcache_sync(wm2200->regmap);
+
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops wm2200_pm = {
+ SET_RUNTIME_PM_OPS(wm2200_runtime_suspend, wm2200_runtime_resume,
+ NULL)
+};
+
+static const struct i2c_device_id wm2200_i2c_id[] = {
+ { "wm2200", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm2200_i2c_id);
+
+static struct i2c_driver wm2200_i2c_driver = {
+ .driver = {
+ .name = "wm2200",
+ .owner = THIS_MODULE,
+ .pm = &wm2200_pm,
+ },
+ .probe = wm2200_i2c_probe,
+ .remove = __devexit_p(wm2200_i2c_remove),
+ .id_table = wm2200_i2c_id,
+};
+
+static int __init wm2200_modinit(void)
+{
+ return i2c_add_driver(&wm2200_i2c_driver);
+}
+module_init(wm2200_modinit);
+
+static void __exit wm2200_exit(void)
+{
+ i2c_del_driver(&wm2200_i2c_driver);
+}
+module_exit(wm2200_exit);
+
+MODULE_DESCRIPTION("ASoC WM2200 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm2200.h b/sound/soc/codecs/wm2200.h
new file mode 100644
index 000000000000..5d719d6b4a8d
--- /dev/null
+++ b/sound/soc/codecs/wm2200.h
@@ -0,0 +1,3674 @@
+/*
+ * wm2200.h - WM2200 audio codec interface
+ *
+ * Copyright 2012 Wolfson Microelectronics PLC.
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _WM2200_H
+#define _WM2200_H
+
+#define WM2200_CLK_SYSCLK 1
+
+#define WM2200_CLKSRC_MCLK1 0
+#define WM2200_CLKSRC_MCLK2 1
+#define WM2200_CLKSRC_FLL 4
+#define WM2200_CLKSRC_BCLK1 8
+
+#define WM2200_FLL_SRC_MCLK1 0
+#define WM2200_FLL_SRC_MCLK2 1
+#define WM2200_FLL_SRC_BCLK 2
+
+/*
+ * Register values.
+ */
+#define WM2200_SOFTWARE_RESET 0x00
+#define WM2200_DEVICE_REVISION 0x01
+#define WM2200_TONE_GENERATOR_1 0x0B
+#define WM2200_CLOCKING_3 0x102
+#define WM2200_CLOCKING_4 0x103
+#define WM2200_FLL_CONTROL_1 0x111
+#define WM2200_FLL_CONTROL_2 0x112
+#define WM2200_FLL_CONTROL_3 0x113
+#define WM2200_FLL_CONTROL_4 0x114
+#define WM2200_FLL_CONTROL_6 0x116
+#define WM2200_FLL_CONTROL_7 0x117
+#define WM2200_FLL_EFS_1 0x119
+#define WM2200_FLL_EFS_2 0x11A
+#define WM2200_MIC_CHARGE_PUMP_1 0x200
+#define WM2200_MIC_CHARGE_PUMP_2 0x201
+#define WM2200_DM_CHARGE_PUMP_1 0x202
+#define WM2200_MIC_BIAS_CTRL_1 0x20C
+#define WM2200_MIC_BIAS_CTRL_2 0x20D
+#define WM2200_EAR_PIECE_CTRL_1 0x20F
+#define WM2200_EAR_PIECE_CTRL_2 0x210
+#define WM2200_INPUT_ENABLES 0x301
+#define WM2200_IN1L_CONTROL 0x302
+#define WM2200_IN1R_CONTROL 0x303
+#define WM2200_IN2L_CONTROL 0x304
+#define WM2200_IN2R_CONTROL 0x305
+#define WM2200_IN3L_CONTROL 0x306
+#define WM2200_IN3R_CONTROL 0x307
+#define WM2200_RXANC_SRC 0x30A
+#define WM2200_INPUT_VOLUME_RAMP 0x30B
+#define WM2200_ADC_DIGITAL_VOLUME_1L 0x30C
+#define WM2200_ADC_DIGITAL_VOLUME_1R 0x30D
+#define WM2200_ADC_DIGITAL_VOLUME_2L 0x30E
+#define WM2200_ADC_DIGITAL_VOLUME_2R 0x30F
+#define WM2200_ADC_DIGITAL_VOLUME_3L 0x310
+#define WM2200_ADC_DIGITAL_VOLUME_3R 0x311
+#define WM2200_OUTPUT_ENABLES 0x400
+#define WM2200_DAC_VOLUME_LIMIT_1L 0x401
+#define WM2200_DAC_VOLUME_LIMIT_1R 0x402
+#define WM2200_DAC_VOLUME_LIMIT_2L 0x403
+#define WM2200_DAC_VOLUME_LIMIT_2R 0x404
+#define WM2200_DAC_AEC_CONTROL_1 0x409
+#define WM2200_OUTPUT_VOLUME_RAMP 0x40A
+#define WM2200_DAC_DIGITAL_VOLUME_1L 0x40B
+#define WM2200_DAC_DIGITAL_VOLUME_1R 0x40C
+#define WM2200_DAC_DIGITAL_VOLUME_2L 0x40D
+#define WM2200_DAC_DIGITAL_VOLUME_2R 0x40E
+#define WM2200_PDM_1 0x417
+#define WM2200_PDM_2 0x418
+#define WM2200_AUDIO_IF_1_1 0x500
+#define WM2200_AUDIO_IF_1_2 0x501
+#define WM2200_AUDIO_IF_1_3 0x502
+#define WM2200_AUDIO_IF_1_4 0x503
+#define WM2200_AUDIO_IF_1_5 0x504
+#define WM2200_AUDIO_IF_1_6 0x505
+#define WM2200_AUDIO_IF_1_7 0x506
+#define WM2200_AUDIO_IF_1_8 0x507
+#define WM2200_AUDIO_IF_1_9 0x508
+#define WM2200_AUDIO_IF_1_10 0x509
+#define WM2200_AUDIO_IF_1_11 0x50A
+#define WM2200_AUDIO_IF_1_12 0x50B
+#define WM2200_AUDIO_IF_1_13 0x50C
+#define WM2200_AUDIO_IF_1_14 0x50D
+#define WM2200_AUDIO_IF_1_15 0x50E
+#define WM2200_AUDIO_IF_1_16 0x50F
+#define WM2200_AUDIO_IF_1_17 0x510
+#define WM2200_AUDIO_IF_1_18 0x511
+#define WM2200_AUDIO_IF_1_19 0x512
+#define WM2200_AUDIO_IF_1_20 0x513
+#define WM2200_AUDIO_IF_1_21 0x514
+#define WM2200_AUDIO_IF_1_22 0x515
+#define WM2200_OUT1LMIX_INPUT_1_SOURCE 0x600
+#define WM2200_OUT1LMIX_INPUT_1_VOLUME 0x601
+#define WM2200_OUT1LMIX_INPUT_2_SOURCE 0x602
+#define WM2200_OUT1LMIX_INPUT_2_VOLUME 0x603
+#define WM2200_OUT1LMIX_INPUT_3_SOURCE 0x604
+#define WM2200_OUT1LMIX_INPUT_3_VOLUME 0x605
+#define WM2200_OUT1LMIX_INPUT_4_SOURCE 0x606
+#define WM2200_OUT1LMIX_INPUT_4_VOLUME 0x607
+#define WM2200_OUT1RMIX_INPUT_1_SOURCE 0x608
+#define WM2200_OUT1RMIX_INPUT_1_VOLUME 0x609
+#define WM2200_OUT1RMIX_INPUT_2_SOURCE 0x60A
+#define WM2200_OUT1RMIX_INPUT_2_VOLUME 0x60B
+#define WM2200_OUT1RMIX_INPUT_3_SOURCE 0x60C
+#define WM2200_OUT1RMIX_INPUT_3_VOLUME 0x60D
+#define WM2200_OUT1RMIX_INPUT_4_SOURCE 0x60E
+#define WM2200_OUT1RMIX_INPUT_4_VOLUME 0x60F
+#define WM2200_OUT2LMIX_INPUT_1_SOURCE 0x610
+#define WM2200_OUT2LMIX_INPUT_1_VOLUME 0x611
+#define WM2200_OUT2LMIX_INPUT_2_SOURCE 0x612
+#define WM2200_OUT2LMIX_INPUT_2_VOLUME 0x613
+#define WM2200_OUT2LMIX_INPUT_3_SOURCE 0x614
+#define WM2200_OUT2LMIX_INPUT_3_VOLUME 0x615
+#define WM2200_OUT2LMIX_INPUT_4_SOURCE 0x616
+#define WM2200_OUT2LMIX_INPUT_4_VOLUME 0x617
+#define WM2200_OUT2RMIX_INPUT_1_SOURCE 0x618
+#define WM2200_OUT2RMIX_INPUT_1_VOLUME 0x619
+#define WM2200_OUT2RMIX_INPUT_2_SOURCE 0x61A
+#define WM2200_OUT2RMIX_INPUT_2_VOLUME 0x61B
+#define WM2200_OUT2RMIX_INPUT_3_SOURCE 0x61C
+#define WM2200_OUT2RMIX_INPUT_3_VOLUME 0x61D
+#define WM2200_OUT2RMIX_INPUT_4_SOURCE 0x61E
+#define WM2200_OUT2RMIX_INPUT_4_VOLUME 0x61F
+#define WM2200_AIF1TX1MIX_INPUT_1_SOURCE 0x620
+#define WM2200_AIF1TX1MIX_INPUT_1_VOLUME 0x621
+#define WM2200_AIF1TX1MIX_INPUT_2_SOURCE 0x622
+#define WM2200_AIF1TX1MIX_INPUT_2_VOLUME 0x623
+#define WM2200_AIF1TX1MIX_INPUT_3_SOURCE 0x624
+#define WM2200_AIF1TX1MIX_INPUT_3_VOLUME 0x625
+#define WM2200_AIF1TX1MIX_INPUT_4_SOURCE 0x626
+#define WM2200_AIF1TX1MIX_INPUT_4_VOLUME 0x627
+#define WM2200_AIF1TX2MIX_INPUT_1_SOURCE 0x628
+#define WM2200_AIF1TX2MIX_INPUT_1_VOLUME 0x629
+#define WM2200_AIF1TX2MIX_INPUT_2_SOURCE 0x62A
+#define WM2200_AIF1TX2MIX_INPUT_2_VOLUME 0x62B
+#define WM2200_AIF1TX2MIX_INPUT_3_SOURCE 0x62C
+#define WM2200_AIF1TX2MIX_INPUT_3_VOLUME 0x62D
+#define WM2200_AIF1TX2MIX_INPUT_4_SOURCE 0x62E
+#define WM2200_AIF1TX2MIX_INPUT_4_VOLUME 0x62F
+#define WM2200_AIF1TX3MIX_INPUT_1_SOURCE 0x630
+#define WM2200_AIF1TX3MIX_INPUT_1_VOLUME 0x631
+#define WM2200_AIF1TX3MIX_INPUT_2_SOURCE 0x632
+#define WM2200_AIF1TX3MIX_INPUT_2_VOLUME 0x633
+#define WM2200_AIF1TX3MIX_INPUT_3_SOURCE 0x634
+#define WM2200_AIF1TX3MIX_INPUT_3_VOLUME 0x635
+#define WM2200_AIF1TX3MIX_INPUT_4_SOURCE 0x636
+#define WM2200_AIF1TX3MIX_INPUT_4_VOLUME 0x637
+#define WM2200_AIF1TX4MIX_INPUT_1_SOURCE 0x638
+#define WM2200_AIF1TX4MIX_INPUT_1_VOLUME 0x639
+#define WM2200_AIF1TX4MIX_INPUT_2_SOURCE 0x63A
+#define WM2200_AIF1TX4MIX_INPUT_2_VOLUME 0x63B
+#define WM2200_AIF1TX4MIX_INPUT_3_SOURCE 0x63C
+#define WM2200_AIF1TX4MIX_INPUT_3_VOLUME 0x63D
+#define WM2200_AIF1TX4MIX_INPUT_4_SOURCE 0x63E
+#define WM2200_AIF1TX4MIX_INPUT_4_VOLUME 0x63F
+#define WM2200_AIF1TX5MIX_INPUT_1_SOURCE 0x640
+#define WM2200_AIF1TX5MIX_INPUT_1_VOLUME 0x641
+#define WM2200_AIF1TX5MIX_INPUT_2_SOURCE 0x642
+#define WM2200_AIF1TX5MIX_INPUT_2_VOLUME 0x643
+#define WM2200_AIF1TX5MIX_INPUT_3_SOURCE 0x644
+#define WM2200_AIF1TX5MIX_INPUT_3_VOLUME 0x645
+#define WM2200_AIF1TX5MIX_INPUT_4_SOURCE 0x646
+#define WM2200_AIF1TX5MIX_INPUT_4_VOLUME 0x647
+#define WM2200_AIF1TX6MIX_INPUT_1_SOURCE 0x648
+#define WM2200_AIF1TX6MIX_INPUT_1_VOLUME 0x649
+#define WM2200_AIF1TX6MIX_INPUT_2_SOURCE 0x64A
+#define WM2200_AIF1TX6MIX_INPUT_2_VOLUME 0x64B
+#define WM2200_AIF1TX6MIX_INPUT_3_SOURCE 0x64C
+#define WM2200_AIF1TX6MIX_INPUT_3_VOLUME 0x64D
+#define WM2200_AIF1TX6MIX_INPUT_4_SOURCE 0x64E
+#define WM2200_AIF1TX6MIX_INPUT_4_VOLUME 0x64F
+#define WM2200_EQLMIX_INPUT_1_SOURCE 0x650
+#define WM2200_EQLMIX_INPUT_1_VOLUME 0x651
+#define WM2200_EQLMIX_INPUT_2_SOURCE 0x652
+#define WM2200_EQLMIX_INPUT_2_VOLUME 0x653
+#define WM2200_EQLMIX_INPUT_3_SOURCE 0x654
+#define WM2200_EQLMIX_INPUT_3_VOLUME 0x655
+#define WM2200_EQLMIX_INPUT_4_SOURCE 0x656
+#define WM2200_EQLMIX_INPUT_4_VOLUME 0x657
+#define WM2200_EQRMIX_INPUT_1_SOURCE 0x658
+#define WM2200_EQRMIX_INPUT_1_VOLUME 0x659
+#define WM2200_EQRMIX_INPUT_2_SOURCE 0x65A
+#define WM2200_EQRMIX_INPUT_2_VOLUME 0x65B
+#define WM2200_EQRMIX_INPUT_3_SOURCE 0x65C
+#define WM2200_EQRMIX_INPUT_3_VOLUME 0x65D
+#define WM2200_EQRMIX_INPUT_4_SOURCE 0x65E
+#define WM2200_EQRMIX_INPUT_4_VOLUME 0x65F
+#define WM2200_LHPF1MIX_INPUT_1_SOURCE 0x660
+#define WM2200_LHPF1MIX_INPUT_1_VOLUME 0x661
+#define WM2200_LHPF1MIX_INPUT_2_SOURCE 0x662
+#define WM2200_LHPF1MIX_INPUT_2_VOLUME 0x663
+#define WM2200_LHPF1MIX_INPUT_3_SOURCE 0x664
+#define WM2200_LHPF1MIX_INPUT_3_VOLUME 0x665
+#define WM2200_LHPF1MIX_INPUT_4_SOURCE 0x666
+#define WM2200_LHPF1MIX_INPUT_4_VOLUME 0x667
+#define WM2200_LHPF2MIX_INPUT_1_SOURCE 0x668
+#define WM2200_LHPF2MIX_INPUT_1_VOLUME 0x669
+#define WM2200_LHPF2MIX_INPUT_2_SOURCE 0x66A
+#define WM2200_LHPF2MIX_INPUT_2_VOLUME 0x66B
+#define WM2200_LHPF2MIX_INPUT_3_SOURCE 0x66C
+#define WM2200_LHPF2MIX_INPUT_3_VOLUME 0x66D
+#define WM2200_LHPF2MIX_INPUT_4_SOURCE 0x66E
+#define WM2200_LHPF2MIX_INPUT_4_VOLUME 0x66F
+#define WM2200_DSP1LMIX_INPUT_1_SOURCE 0x670
+#define WM2200_DSP1LMIX_INPUT_1_VOLUME 0x671
+#define WM2200_DSP1LMIX_INPUT_2_SOURCE 0x672
+#define WM2200_DSP1LMIX_INPUT_2_VOLUME 0x673
+#define WM2200_DSP1LMIX_INPUT_3_SOURCE 0x674
+#define WM2200_DSP1LMIX_INPUT_3_VOLUME 0x675
+#define WM2200_DSP1LMIX_INPUT_4_SOURCE 0x676
+#define WM2200_DSP1LMIX_INPUT_4_VOLUME 0x677
+#define WM2200_DSP1RMIX_INPUT_1_SOURCE 0x678
+#define WM2200_DSP1RMIX_INPUT_1_VOLUME 0x679
+#define WM2200_DSP1RMIX_INPUT_2_SOURCE 0x67A
+#define WM2200_DSP1RMIX_INPUT_2_VOLUME 0x67B
+#define WM2200_DSP1RMIX_INPUT_3_SOURCE 0x67C
+#define WM2200_DSP1RMIX_INPUT_3_VOLUME 0x67D
+#define WM2200_DSP1RMIX_INPUT_4_SOURCE 0x67E
+#define WM2200_DSP1RMIX_INPUT_4_VOLUME 0x67F
+#define WM2200_DSP1AUX1MIX_INPUT_1_SOURCE 0x680
+#define WM2200_DSP1AUX2MIX_INPUT_1_SOURCE 0x681
+#define WM2200_DSP1AUX3MIX_INPUT_1_SOURCE 0x682
+#define WM2200_DSP1AUX4MIX_INPUT_1_SOURCE 0x683
+#define WM2200_DSP1AUX5MIX_INPUT_1_SOURCE 0x684
+#define WM2200_DSP1AUX6MIX_INPUT_1_SOURCE 0x685
+#define WM2200_DSP2LMIX_INPUT_1_SOURCE 0x686
+#define WM2200_DSP2LMIX_INPUT_1_VOLUME 0x687
+#define WM2200_DSP2LMIX_INPUT_2_SOURCE 0x688
+#define WM2200_DSP2LMIX_INPUT_2_VOLUME 0x689
+#define WM2200_DSP2LMIX_INPUT_3_SOURCE 0x68A
+#define WM2200_DSP2LMIX_INPUT_3_VOLUME 0x68B
+#define WM2200_DSP2LMIX_INPUT_4_SOURCE 0x68C
+#define WM2200_DSP2LMIX_INPUT_4_VOLUME 0x68D
+#define WM2200_DSP2RMIX_INPUT_1_SOURCE 0x68E
+#define WM2200_DSP2RMIX_INPUT_1_VOLUME 0x68F
+#define WM2200_DSP2RMIX_INPUT_2_SOURCE 0x690
+#define WM2200_DSP2RMIX_INPUT_2_VOLUME 0x691
+#define WM2200_DSP2RMIX_INPUT_3_SOURCE 0x692
+#define WM2200_DSP2RMIX_INPUT_3_VOLUME 0x693
+#define WM2200_DSP2RMIX_INPUT_4_SOURCE 0x694
+#define WM2200_DSP2RMIX_INPUT_4_VOLUME 0x695
+#define WM2200_DSP2AUX1MIX_INPUT_1_SOURCE 0x696
+#define WM2200_DSP2AUX2MIX_INPUT_1_SOURCE 0x697
+#define WM2200_DSP2AUX3MIX_INPUT_1_SOURCE 0x698
+#define WM2200_DSP2AUX4MIX_INPUT_1_SOURCE 0x699
+#define WM2200_DSP2AUX5MIX_INPUT_1_SOURCE 0x69A
+#define WM2200_DSP2AUX6MIX_INPUT_1_SOURCE 0x69B
+#define WM2200_GPIO_CTRL_1 0x700
+#define WM2200_GPIO_CTRL_2 0x701
+#define WM2200_GPIO_CTRL_3 0x702
+#define WM2200_GPIO_CTRL_4 0x703
+#define WM2200_ADPS1_IRQ0 0x707
+#define WM2200_ADPS1_IRQ1 0x708
+#define WM2200_MISC_PAD_CTRL_1 0x709
+#define WM2200_INTERRUPT_STATUS_1 0x800
+#define WM2200_INTERRUPT_STATUS_1_MASK 0x801
+#define WM2200_INTERRUPT_STATUS_2 0x802
+#define WM2200_INTERRUPT_RAW_STATUS_2 0x803
+#define WM2200_INTERRUPT_STATUS_2_MASK 0x804
+#define WM2200_INTERRUPT_CONTROL 0x808
+#define WM2200_EQL_1 0x900
+#define WM2200_EQL_2 0x901
+#define WM2200_EQL_3 0x902
+#define WM2200_EQL_4 0x903
+#define WM2200_EQL_5 0x904
+#define WM2200_EQL_6 0x905
+#define WM2200_EQL_7 0x906
+#define WM2200_EQL_8 0x907
+#define WM2200_EQL_9 0x908
+#define WM2200_EQL_10 0x909
+#define WM2200_EQL_11 0x90A
+#define WM2200_EQL_12 0x90B
+#define WM2200_EQL_13 0x90C
+#define WM2200_EQL_14 0x90D
+#define WM2200_EQL_15 0x90E
+#define WM2200_EQL_16 0x90F
+#define WM2200_EQL_17 0x910
+#define WM2200_EQL_18 0x911
+#define WM2200_EQL_19 0x912
+#define WM2200_EQL_20 0x913
+#define WM2200_EQR_1 0x916
+#define WM2200_EQR_2 0x917
+#define WM2200_EQR_3 0x918
+#define WM2200_EQR_4 0x919
+#define WM2200_EQR_5 0x91A
+#define WM2200_EQR_6 0x91B
+#define WM2200_EQR_7 0x91C
+#define WM2200_EQR_8 0x91D
+#define WM2200_EQR_9 0x91E
+#define WM2200_EQR_10 0x91F
+#define WM2200_EQR_11 0x920
+#define WM2200_EQR_12 0x921
+#define WM2200_EQR_13 0x922
+#define WM2200_EQR_14 0x923
+#define WM2200_EQR_15 0x924
+#define WM2200_EQR_16 0x925
+#define WM2200_EQR_17 0x926
+#define WM2200_EQR_18 0x927
+#define WM2200_EQR_19 0x928
+#define WM2200_EQR_20 0x929
+#define WM2200_HPLPF1_1 0x93E
+#define WM2200_HPLPF1_2 0x93F
+#define WM2200_HPLPF2_1 0x942
+#define WM2200_HPLPF2_2 0x943
+#define WM2200_DSP1_CONTROL_1 0xA00
+#define WM2200_DSP1_CONTROL_2 0xA02
+#define WM2200_DSP1_CONTROL_3 0xA03
+#define WM2200_DSP1_CONTROL_4 0xA04
+#define WM2200_DSP1_CONTROL_5 0xA06
+#define WM2200_DSP1_CONTROL_6 0xA07
+#define WM2200_DSP1_CONTROL_7 0xA08
+#define WM2200_DSP1_CONTROL_8 0xA09
+#define WM2200_DSP1_CONTROL_9 0xA0A
+#define WM2200_DSP1_CONTROL_10 0xA0B
+#define WM2200_DSP1_CONTROL_11 0xA0C
+#define WM2200_DSP1_CONTROL_12 0xA0D
+#define WM2200_DSP1_CONTROL_13 0xA0F
+#define WM2200_DSP1_CONTROL_14 0xA10
+#define WM2200_DSP1_CONTROL_15 0xA11
+#define WM2200_DSP1_CONTROL_16 0xA12
+#define WM2200_DSP1_CONTROL_17 0xA13
+#define WM2200_DSP1_CONTROL_18 0xA14
+#define WM2200_DSP1_CONTROL_19 0xA16
+#define WM2200_DSP1_CONTROL_20 0xA17
+#define WM2200_DSP1_CONTROL_21 0xA18
+#define WM2200_DSP1_CONTROL_22 0xA1A
+#define WM2200_DSP1_CONTROL_23 0xA1B
+#define WM2200_DSP1_CONTROL_24 0xA1C
+#define WM2200_DSP1_CONTROL_25 0xA1E
+#define WM2200_DSP1_CONTROL_26 0xA20
+#define WM2200_DSP1_CONTROL_27 0xA21
+#define WM2200_DSP1_CONTROL_28 0xA22
+#define WM2200_DSP1_CONTROL_29 0xA23
+#define WM2200_DSP1_CONTROL_30 0xA24
+#define WM2200_DSP1_CONTROL_31 0xA26
+#define WM2200_DSP2_CONTROL_1 0xB00
+#define WM2200_DSP2_CONTROL_2 0xB02
+#define WM2200_DSP2_CONTROL_3 0xB03
+#define WM2200_DSP2_CONTROL_4 0xB04
+#define WM2200_DSP2_CONTROL_5 0xB06
+#define WM2200_DSP2_CONTROL_6 0xB07
+#define WM2200_DSP2_CONTROL_7 0xB08
+#define WM2200_DSP2_CONTROL_8 0xB09
+#define WM2200_DSP2_CONTROL_9 0xB0A
+#define WM2200_DSP2_CONTROL_10 0xB0B
+#define WM2200_DSP2_CONTROL_11 0xB0C
+#define WM2200_DSP2_CONTROL_12 0xB0D
+#define WM2200_DSP2_CONTROL_13 0xB0F
+#define WM2200_DSP2_CONTROL_14 0xB10
+#define WM2200_DSP2_CONTROL_15 0xB11
+#define WM2200_DSP2_CONTROL_16 0xB12
+#define WM2200_DSP2_CONTROL_17 0xB13
+#define WM2200_DSP2_CONTROL_18 0xB14
+#define WM2200_DSP2_CONTROL_19 0xB16
+#define WM2200_DSP2_CONTROL_20 0xB17
+#define WM2200_DSP2_CONTROL_21 0xB18
+#define WM2200_DSP2_CONTROL_22 0xB1A
+#define WM2200_DSP2_CONTROL_23 0xB1B
+#define WM2200_DSP2_CONTROL_24 0xB1C
+#define WM2200_DSP2_CONTROL_25 0xB1E
+#define WM2200_DSP2_CONTROL_26 0xB20
+#define WM2200_DSP2_CONTROL_27 0xB21
+#define WM2200_DSP2_CONTROL_28 0xB22
+#define WM2200_DSP2_CONTROL_29 0xB23
+#define WM2200_DSP2_CONTROL_30 0xB24
+#define WM2200_DSP2_CONTROL_31 0xB26
+#define WM2200_ANC_CTRL1 0xD00
+#define WM2200_ANC_CTRL2 0xD01
+#define WM2200_ANC_CTRL3 0xD02
+#define WM2200_ANC_CTRL7 0xD08
+#define WM2200_ANC_CTRL8 0xD09
+#define WM2200_ANC_CTRL9 0xD0A
+#define WM2200_ANC_CTRL10 0xD0B
+#define WM2200_ANC_CTRL11 0xD0C
+#define WM2200_ANC_CTRL12 0xD0D
+#define WM2200_ANC_CTRL13 0xD0E
+#define WM2200_ANC_CTRL14 0xD0F
+#define WM2200_ANC_CTRL15 0xD10
+#define WM2200_ANC_CTRL16 0xD11
+#define WM2200_ANC_CTRL17 0xD12
+#define WM2200_ANC_CTRL18 0xD15
+#define WM2200_ANC_CTRL19 0xD16
+#define WM2200_ANC_CTRL20 0xD17
+#define WM2200_ANC_CTRL21 0xD18
+#define WM2200_ANC_CTRL22 0xD19
+#define WM2200_ANC_CTRL23 0xD1A
+#define WM2200_ANC_CTRL24 0xD1B
+#define WM2200_ANC_CTRL25 0xD1C
+#define WM2200_ANC_CTRL26 0xD1D
+#define WM2200_ANC_CTRL27 0xD1E
+#define WM2200_ANC_CTRL28 0xD1F
+#define WM2200_ANC_CTRL29 0xD20
+#define WM2200_ANC_CTRL30 0xD21
+#define WM2200_ANC_CTRL31 0xD23
+#define WM2200_ANC_CTRL32 0xD24
+#define WM2200_ANC_CTRL33 0xD25
+#define WM2200_ANC_CTRL34 0xD27
+#define WM2200_ANC_CTRL35 0xD28
+#define WM2200_ANC_CTRL36 0xD29
+#define WM2200_ANC_CTRL37 0xD2A
+#define WM2200_ANC_CTRL38 0xD2B
+#define WM2200_ANC_CTRL39 0xD2C
+#define WM2200_ANC_CTRL40 0xD2D
+#define WM2200_ANC_CTRL41 0xD2E
+#define WM2200_ANC_CTRL42 0xD2F
+#define WM2200_ANC_CTRL43 0xD30
+#define WM2200_ANC_CTRL44 0xD31
+#define WM2200_ANC_CTRL45 0xD32
+#define WM2200_ANC_CTRL46 0xD33
+#define WM2200_ANC_CTRL47 0xD34
+#define WM2200_ANC_CTRL48 0xD35
+#define WM2200_ANC_CTRL49 0xD36
+#define WM2200_ANC_CTRL50 0xD37
+#define WM2200_ANC_CTRL51 0xD38
+#define WM2200_ANC_CTRL52 0xD39
+#define WM2200_ANC_CTRL53 0xD3A
+#define WM2200_ANC_CTRL54 0xD3B
+#define WM2200_ANC_CTRL55 0xD3C
+#define WM2200_ANC_CTRL56 0xD3D
+#define WM2200_ANC_CTRL57 0xD3E
+#define WM2200_ANC_CTRL58 0xD3F
+#define WM2200_ANC_CTRL59 0xD40
+#define WM2200_ANC_CTRL60 0xD41
+#define WM2200_ANC_CTRL61 0xD42
+#define WM2200_ANC_CTRL62 0xD43
+#define WM2200_ANC_CTRL63 0xD44
+#define WM2200_ANC_CTRL64 0xD45
+#define WM2200_ANC_CTRL65 0xD46
+#define WM2200_ANC_CTRL66 0xD47
+#define WM2200_ANC_CTRL67 0xD48
+#define WM2200_ANC_CTRL68 0xD49
+#define WM2200_ANC_CTRL69 0xD4A
+#define WM2200_ANC_CTRL70 0xD4B
+#define WM2200_ANC_CTRL71 0xD4C
+#define WM2200_ANC_CTRL72 0xD4D
+#define WM2200_ANC_CTRL73 0xD4E
+#define WM2200_ANC_CTRL74 0xD4F
+#define WM2200_ANC_CTRL75 0xD50
+#define WM2200_ANC_CTRL76 0xD51
+#define WM2200_ANC_CTRL77 0xD52
+#define WM2200_ANC_CTRL78 0xD53
+#define WM2200_ANC_CTRL79 0xD54
+#define WM2200_ANC_CTRL80 0xD55
+#define WM2200_ANC_CTRL81 0xD56
+#define WM2200_ANC_CTRL82 0xD57
+#define WM2200_ANC_CTRL83 0xD58
+#define WM2200_ANC_CTRL84 0xD5B
+#define WM2200_ANC_CTRL85 0xD5C
+#define WM2200_ANC_CTRL86 0xD5F
+#define WM2200_ANC_CTRL87 0xD60
+#define WM2200_ANC_CTRL88 0xD61
+#define WM2200_ANC_CTRL89 0xD62
+#define WM2200_ANC_CTRL90 0xD63
+#define WM2200_ANC_CTRL91 0xD64
+#define WM2200_ANC_CTRL92 0xD65
+#define WM2200_ANC_CTRL93 0xD66
+#define WM2200_ANC_CTRL94 0xD67
+#define WM2200_ANC_CTRL95 0xD68
+#define WM2200_ANC_CTRL96 0xD69
+#define WM2200_DSP1_DM_0 0x3000
+#define WM2200_DSP1_DM_1 0x3001
+#define WM2200_DSP1_DM_2 0x3002
+#define WM2200_DSP1_DM_3 0x3003
+#define WM2200_DSP1_DM_2044 0x37FC
+#define WM2200_DSP1_DM_2045 0x37FD
+#define WM2200_DSP1_DM_2046 0x37FE
+#define WM2200_DSP1_DM_2047 0x37FF
+#define WM2200_DSP1_PM_0 0x3800
+#define WM2200_DSP1_PM_1 0x3801
+#define WM2200_DSP1_PM_2 0x3802
+#define WM2200_DSP1_PM_3 0x3803
+#define WM2200_DSP1_PM_4 0x3804
+#define WM2200_DSP1_PM_5 0x3805
+#define WM2200_DSP1_PM_762 0x3AFA
+#define WM2200_DSP1_PM_763 0x3AFB
+#define WM2200_DSP1_PM_764 0x3AFC
+#define WM2200_DSP1_PM_765 0x3AFD
+#define WM2200_DSP1_PM_766 0x3AFE
+#define WM2200_DSP1_PM_767 0x3AFF
+#define WM2200_DSP1_ZM_0 0x3C00
+#define WM2200_DSP1_ZM_1 0x3C01
+#define WM2200_DSP1_ZM_2 0x3C02
+#define WM2200_DSP1_ZM_3 0x3C03
+#define WM2200_DSP1_ZM_1020 0x3FFC
+#define WM2200_DSP1_ZM_1021 0x3FFD
+#define WM2200_DSP1_ZM_1022 0x3FFE
+#define WM2200_DSP1_ZM_1023 0x3FFF
+#define WM2200_DSP2_DM_0 0x4000
+#define WM2200_DSP2_DM_1 0x4001
+#define WM2200_DSP2_DM_2 0x4002
+#define WM2200_DSP2_DM_3 0x4003
+#define WM2200_DSP2_DM_2044 0x47FC
+#define WM2200_DSP2_DM_2045 0x47FD
+#define WM2200_DSP2_DM_2046 0x47FE
+#define WM2200_DSP2_DM_2047 0x47FF
+#define WM2200_DSP2_PM_0 0x4800
+#define WM2200_DSP2_PM_1 0x4801
+#define WM2200_DSP2_PM_2 0x4802
+#define WM2200_DSP2_PM_3 0x4803
+#define WM2200_DSP2_PM_4 0x4804
+#define WM2200_DSP2_PM_5 0x4805
+#define WM2200_DSP2_PM_762 0x4AFA
+#define WM2200_DSP2_PM_763 0x4AFB
+#define WM2200_DSP2_PM_764 0x4AFC
+#define WM2200_DSP2_PM_765 0x4AFD
+#define WM2200_DSP2_PM_766 0x4AFE
+#define WM2200_DSP2_PM_767 0x4AFF
+#define WM2200_DSP2_ZM_0 0x4C00
+#define WM2200_DSP2_ZM_1 0x4C01
+#define WM2200_DSP2_ZM_2 0x4C02
+#define WM2200_DSP2_ZM_3 0x4C03
+#define WM2200_DSP2_ZM_1020 0x4FFC
+#define WM2200_DSP2_ZM_1021 0x4FFD
+#define WM2200_DSP2_ZM_1022 0x4FFE
+#define WM2200_DSP2_ZM_1023 0x4FFF
+
+#define WM2200_REGISTER_COUNT 494
+#define WM2200_MAX_REGISTER 0x4FFF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - software reset
+ */
+#define WM2200_SW_RESET_CHIP_ID1_MASK 0xFFFF /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_SHIFT 0 /* SW_RESET_CHIP_ID1 - [15:0] */
+#define WM2200_SW_RESET_CHIP_ID1_WIDTH 16 /* SW_RESET_CHIP_ID1 - [15:0] */
+
+/*
+ * R1 (0x01) - Device Revision
+ */
+#define WM2200_DEVICE_REVISION_MASK 0x000F /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_SHIFT 0 /* DEVICE_REVISION - [3:0] */
+#define WM2200_DEVICE_REVISION_WIDTH 4 /* DEVICE_REVISION - [3:0] */
+
+/*
+ * R11 (0x0B) - Tone Generator 1
+ */
+#define WM2200_TONE_ENA 0x0001 /* TONE_ENA */
+#define WM2200_TONE_ENA_MASK 0x0001 /* TONE_ENA */
+#define WM2200_TONE_ENA_SHIFT 0 /* TONE_ENA */
+#define WM2200_TONE_ENA_WIDTH 1 /* TONE_ENA */
+
+/*
+ * R258 (0x102) - Clocking 3
+ */
+#define WM2200_SYSCLK_FREQ_MASK 0x0700 /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_SHIFT 8 /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_FREQ_WIDTH 3 /* SYSCLK_FREQ - [10:8] */
+#define WM2200_SYSCLK_ENA 0x0040 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_MASK 0x0040 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_SHIFT 6 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */
+#define WM2200_SYSCLK_SRC_MASK 0x000F /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC - [3:0] */
+#define WM2200_SYSCLK_SRC_WIDTH 4 /* SYSCLK_SRC - [3:0] */
+
+/*
+ * R259 (0x103) - Clocking 4
+ */
+#define WM2200_SAMPLE_RATE_1_MASK 0x001F /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_SHIFT 0 /* SAMPLE_RATE_1 - [4:0] */
+#define WM2200_SAMPLE_RATE_1_WIDTH 5 /* SAMPLE_RATE_1 - [4:0] */
+
+/*
+ * R273 (0x111) - FLL Control 1
+ */
+#define WM2200_FLL_ENA 0x0001 /* FLL_ENA */
+#define WM2200_FLL_ENA_MASK 0x0001 /* FLL_ENA */
+#define WM2200_FLL_ENA_SHIFT 0 /* FLL_ENA */
+#define WM2200_FLL_ENA_WIDTH 1 /* FLL_ENA */
+
+/*
+ * R274 (0x112) - FLL Control 2
+ */
+#define WM2200_FLL_OUTDIV_MASK 0x3F00 /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_SHIFT 8 /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_OUTDIV_WIDTH 6 /* FLL_OUTDIV - [13:8] */
+#define WM2200_FLL_FRATIO_MASK 0x0007 /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_SHIFT 0 /* FLL_FRATIO - [2:0] */
+#define WM2200_FLL_FRATIO_WIDTH 3 /* FLL_FRATIO - [2:0] */
+
+/*
+ * R275 (0x113) - FLL Control 3
+ */
+#define WM2200_FLL_FRACN_ENA 0x0001 /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_MASK 0x0001 /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_SHIFT 0 /* FLL_FRACN_ENA */
+#define WM2200_FLL_FRACN_ENA_WIDTH 1 /* FLL_FRACN_ENA */
+
+/*
+ * R276 (0x114) - FLL Control 4
+ */
+#define WM2200_FLL_THETA_MASK 0xFFFF /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_SHIFT 0 /* FLL_THETA - [15:0] */
+#define WM2200_FLL_THETA_WIDTH 16 /* FLL_THETA - [15:0] */
+
+/*
+ * R278 (0x116) - FLL Control 6
+ */
+#define WM2200_FLL_N_MASK 0x03FF /* FLL_N - [9:0] */
+#define WM2200_FLL_N_SHIFT 0 /* FLL_N - [9:0] */
+#define WM2200_FLL_N_WIDTH 10 /* FLL_N - [9:0] */
+
+/*
+ * R279 (0x117) - FLL Control 7
+ */
+#define WM2200_FLL_CLK_REF_DIV_MASK 0x0030 /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_SHIFT 4 /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_DIV_WIDTH 2 /* FLL_CLK_REF_DIV - [5:4] */
+#define WM2200_FLL_CLK_REF_SRC_MASK 0x0003 /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_SHIFT 0 /* FLL_CLK_REF_SRC - [1:0] */
+#define WM2200_FLL_CLK_REF_SRC_WIDTH 2 /* FLL_CLK_REF_SRC - [1:0] */
+
+/*
+ * R281 (0x119) - FLL EFS 1
+ */
+#define WM2200_FLL_LAMBDA_MASK 0xFFFF /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_SHIFT 0 /* FLL_LAMBDA - [15:0] */
+#define WM2200_FLL_LAMBDA_WIDTH 16 /* FLL_LAMBDA - [15:0] */
+
+/*
+ * R282 (0x11A) - FLL EFS 2
+ */
+#define WM2200_FLL_EFS_ENA 0x0001 /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_MASK 0x0001 /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_SHIFT 0 /* FLL_EFS_ENA */
+#define WM2200_FLL_EFS_ENA_WIDTH 1 /* FLL_EFS_ENA */
+
+/*
+ * R512 (0x200) - Mic Charge Pump 1
+ */
+#define WM2200_CPMIC_BYPASS_MODE 0x0020 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_MASK 0x0020 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_SHIFT 5 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_BYPASS_MODE_WIDTH 1 /* CPMIC_BYPASS_MODE */
+#define WM2200_CPMIC_ENA 0x0001 /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_MASK 0x0001 /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_SHIFT 0 /* CPMIC_ENA */
+#define WM2200_CPMIC_ENA_WIDTH 1 /* CPMIC_ENA */
+
+/*
+ * R513 (0x201) - Mic Charge Pump 2
+ */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_MASK 0xF800 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_SHIFT 11 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+#define WM2200_CPMIC_LDO_VSEL_OVERRIDE_WIDTH 5 /* CPMIC_LDO_VSEL_OVERRIDE - [15:11] */
+
+/*
+ * R514 (0x202) - DM Charge Pump 1
+ */
+#define WM2200_CPDM_ENA 0x0001 /* CPDM_ENA */
+#define WM2200_CPDM_ENA_MASK 0x0001 /* CPDM_ENA */
+#define WM2200_CPDM_ENA_SHIFT 0 /* CPDM_ENA */
+#define WM2200_CPDM_ENA_WIDTH 1 /* CPDM_ENA */
+
+/*
+ * R524 (0x20C) - Mic Bias Ctrl 1
+ */
+#define WM2200_MICB1_DISCH 0x0040 /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_MASK 0x0040 /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_SHIFT 6 /* MICB1_DISCH */
+#define WM2200_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */
+#define WM2200_MICB1_RATE 0x0020 /* MICB1_RATE */
+#define WM2200_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */
+#define WM2200_MICB1_RATE_SHIFT 5 /* MICB1_RATE */
+#define WM2200_MICB1_RATE_WIDTH 1 /* MICB1_RATE */
+#define WM2200_MICB1_LVL_MASK 0x001C /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_SHIFT 2 /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [4:2] */
+#define WM2200_MICB1_MODE 0x0002 /* MICB1_MODE */
+#define WM2200_MICB1_MODE_MASK 0x0002 /* MICB1_MODE */
+#define WM2200_MICB1_MODE_SHIFT 1 /* MICB1_MODE */
+#define WM2200_MICB1_MODE_WIDTH 1 /* MICB1_MODE */
+#define WM2200_MICB1_ENA 0x0001 /* MICB1_ENA */
+#define WM2200_MICB1_ENA_MASK 0x0001 /* MICB1_ENA */
+#define WM2200_MICB1_ENA_SHIFT 0 /* MICB1_ENA */
+#define WM2200_MICB1_ENA_WIDTH 1 /* MICB1_ENA */
+
+/*
+ * R525 (0x20D) - Mic Bias Ctrl 2
+ */
+#define WM2200_MICB2_DISCH 0x0040 /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_MASK 0x0040 /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_SHIFT 6 /* MICB2_DISCH */
+#define WM2200_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */
+#define WM2200_MICB2_RATE 0x0020 /* MICB2_RATE */
+#define WM2200_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */
+#define WM2200_MICB2_RATE_SHIFT 5 /* MICB2_RATE */
+#define WM2200_MICB2_RATE_WIDTH 1 /* MICB2_RATE */
+#define WM2200_MICB2_LVL_MASK 0x001C /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_SHIFT 2 /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [4:2] */
+#define WM2200_MICB2_MODE 0x0002 /* MICB2_MODE */
+#define WM2200_MICB2_MODE_MASK 0x0002 /* MICB2_MODE */
+#define WM2200_MICB2_MODE_SHIFT 1 /* MICB2_MODE */
+#define WM2200_MICB2_MODE_WIDTH 1 /* MICB2_MODE */
+#define WM2200_MICB2_ENA 0x0001 /* MICB2_ENA */
+#define WM2200_MICB2_ENA_MASK 0x0001 /* MICB2_ENA */
+#define WM2200_MICB2_ENA_SHIFT 0 /* MICB2_ENA */
+#define WM2200_MICB2_ENA_WIDTH 1 /* MICB2_ENA */
+
+/*
+ * R527 (0x20F) - Ear Piece Ctrl 1
+ */
+#define WM2200_EPD_LP_ENA 0x4000 /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_MASK 0x4000 /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_SHIFT 14 /* EPD_LP_ENA */
+#define WM2200_EPD_LP_ENA_WIDTH 1 /* EPD_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA 0x2000 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_MASK 0x2000 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_SHIFT 13 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_OUTP_LP_ENA_WIDTH 1 /* EPD_OUTP_LP_ENA */
+#define WM2200_EPD_RMV_SHRT_LP 0x1000 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_MASK 0x1000 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_SHIFT 12 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_RMV_SHRT_LP_WIDTH 1 /* EPD_RMV_SHRT_LP */
+#define WM2200_EPD_LN_ENA 0x0800 /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_MASK 0x0800 /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_SHIFT 11 /* EPD_LN_ENA */
+#define WM2200_EPD_LN_ENA_WIDTH 1 /* EPD_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA 0x0400 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_MASK 0x0400 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_SHIFT 10 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_OUTP_LN_ENA_WIDTH 1 /* EPD_OUTP_LN_ENA */
+#define WM2200_EPD_RMV_SHRT_LN 0x0200 /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_MASK 0x0200 /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_SHIFT 9 /* EPD_RMV_SHRT_LN */
+#define WM2200_EPD_RMV_SHRT_LN_WIDTH 1 /* EPD_RMV_SHRT_LN */
+
+/*
+ * R528 (0x210) - Ear Piece Ctrl 2
+ */
+#define WM2200_EPD_RP_ENA 0x4000 /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_MASK 0x4000 /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_SHIFT 14 /* EPD_RP_ENA */
+#define WM2200_EPD_RP_ENA_WIDTH 1 /* EPD_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA 0x2000 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_MASK 0x2000 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_SHIFT 13 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_OUTP_RP_ENA_WIDTH 1 /* EPD_OUTP_RP_ENA */
+#define WM2200_EPD_RMV_SHRT_RP 0x1000 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_MASK 0x1000 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_SHIFT 12 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RMV_SHRT_RP_WIDTH 1 /* EPD_RMV_SHRT_RP */
+#define WM2200_EPD_RN_ENA 0x0800 /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_MASK 0x0800 /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_SHIFT 11 /* EPD_RN_ENA */
+#define WM2200_EPD_RN_ENA_WIDTH 1 /* EPD_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA 0x0400 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_MASK 0x0400 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_SHIFT 10 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_OUTP_RN_ENA_WIDTH 1 /* EPD_OUTP_RN_ENA */
+#define WM2200_EPD_RMV_SHRT_RN 0x0200 /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_MASK 0x0200 /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_SHIFT 9 /* EPD_RMV_SHRT_RN */
+#define WM2200_EPD_RMV_SHRT_RN_WIDTH 1 /* EPD_RMV_SHRT_RN */
+
+/*
+ * R769 (0x301) - Input Enables
+ */
+#define WM2200_IN3L_ENA 0x0020 /* IN3L_ENA */
+#define WM2200_IN3L_ENA_MASK 0x0020 /* IN3L_ENA */
+#define WM2200_IN3L_ENA_SHIFT 5 /* IN3L_ENA */
+#define WM2200_IN3L_ENA_WIDTH 1 /* IN3L_ENA */
+#define WM2200_IN3R_ENA 0x0010 /* IN3R_ENA */
+#define WM2200_IN3R_ENA_MASK 0x0010 /* IN3R_ENA */
+#define WM2200_IN3R_ENA_SHIFT 4 /* IN3R_ENA */
+#define WM2200_IN3R_ENA_WIDTH 1 /* IN3R_ENA */
+#define WM2200_IN2L_ENA 0x0008 /* IN2L_ENA */
+#define WM2200_IN2L_ENA_MASK 0x0008 /* IN2L_ENA */
+#define WM2200_IN2L_ENA_SHIFT 3 /* IN2L_ENA */
+#define WM2200_IN2L_ENA_WIDTH 1 /* IN2L_ENA */
+#define WM2200_IN2R_ENA 0x0004 /* IN2R_ENA */
+#define WM2200_IN2R_ENA_MASK 0x0004 /* IN2R_ENA */
+#define WM2200_IN2R_ENA_SHIFT 2 /* IN2R_ENA */
+#define WM2200_IN2R_ENA_WIDTH 1 /* IN2R_ENA */
+#define WM2200_IN1L_ENA 0x0002 /* IN1L_ENA */
+#define WM2200_IN1L_ENA_MASK 0x0002 /* IN1L_ENA */
+#define WM2200_IN1L_ENA_SHIFT 1 /* IN1L_ENA */
+#define WM2200_IN1L_ENA_WIDTH 1 /* IN1L_ENA */
+#define WM2200_IN1R_ENA 0x0001 /* IN1R_ENA */
+#define WM2200_IN1R_ENA_MASK 0x0001 /* IN1R_ENA */
+#define WM2200_IN1R_ENA_SHIFT 0 /* IN1R_ENA */
+#define WM2200_IN1R_ENA_WIDTH 1 /* IN1R_ENA */
+
+/*
+ * R770 (0x302) - IN1L Control
+ */
+#define WM2200_IN1_OSR 0x2000 /* IN1_OSR */
+#define WM2200_IN1_OSR_MASK 0x2000 /* IN1_OSR */
+#define WM2200_IN1_OSR_SHIFT 13 /* IN1_OSR */
+#define WM2200_IN1_OSR_WIDTH 1 /* IN1_OSR */
+#define WM2200_IN1_DMIC_SUP_MASK 0x1800 /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_SHIFT 11 /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_DMIC_SUP_WIDTH 2 /* IN1_DMIC_SUP - [12:11] */
+#define WM2200_IN1_MODE_MASK 0x0600 /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_SHIFT 9 /* IN1_MODE - [10:9] */
+#define WM2200_IN1_MODE_WIDTH 2 /* IN1_MODE - [10:9] */
+#define WM2200_IN1L_PGA_VOL_MASK 0x00FE /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_SHIFT 1 /* IN1L_PGA_VOL - [7:1] */
+#define WM2200_IN1L_PGA_VOL_WIDTH 7 /* IN1L_PGA_VOL - [7:1] */
+
+/*
+ * R771 (0x303) - IN1R Control
+ */
+#define WM2200_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */
+#define WM2200_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */
+
+/*
+ * R772 (0x304) - IN2L Control
+ */
+#define WM2200_IN2_OSR 0x2000 /* IN2_OSR */
+#define WM2200_IN2_OSR_MASK 0x2000 /* IN2_OSR */
+#define WM2200_IN2_OSR_SHIFT 13 /* IN2_OSR */
+#define WM2200_IN2_OSR_WIDTH 1 /* IN2_OSR */
+#define WM2200_IN2_DMIC_SUP_MASK 0x1800 /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_SHIFT 11 /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_DMIC_SUP_WIDTH 2 /* IN2_DMIC_SUP - [12:11] */
+#define WM2200_IN2_MODE_MASK 0x0600 /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_SHIFT 9 /* IN2_MODE - [10:9] */
+#define WM2200_IN2_MODE_WIDTH 2 /* IN2_MODE - [10:9] */
+#define WM2200_IN2L_PGA_VOL_MASK 0x00FE /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_SHIFT 1 /* IN2L_PGA_VOL - [7:1] */
+#define WM2200_IN2L_PGA_VOL_WIDTH 7 /* IN2L_PGA_VOL - [7:1] */
+
+/*
+ * R773 (0x305) - IN2R Control
+ */
+#define WM2200_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */
+#define WM2200_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */
+
+/*
+ * R774 (0x306) - IN3L Control
+ */
+#define WM2200_IN3_OSR 0x2000 /* IN3_OSR */
+#define WM2200_IN3_OSR_MASK 0x2000 /* IN3_OSR */
+#define WM2200_IN3_OSR_SHIFT 13 /* IN3_OSR */
+#define WM2200_IN3_OSR_WIDTH 1 /* IN3_OSR */
+#define WM2200_IN3_DMIC_SUP_MASK 0x1800 /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_SHIFT 11 /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_DMIC_SUP_WIDTH 2 /* IN3_DMIC_SUP - [12:11] */
+#define WM2200_IN3_MODE_MASK 0x0600 /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_SHIFT 9 /* IN3_MODE - [10:9] */
+#define WM2200_IN3_MODE_WIDTH 2 /* IN3_MODE - [10:9] */
+#define WM2200_IN3L_PGA_VOL_MASK 0x00FE /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_SHIFT 1 /* IN3L_PGA_VOL - [7:1] */
+#define WM2200_IN3L_PGA_VOL_WIDTH 7 /* IN3L_PGA_VOL - [7:1] */
+
+/*
+ * R775 (0x307) - IN3R Control
+ */
+#define WM2200_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */
+#define WM2200_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */
+
+/*
+ * R778 (0x30A) - RXANC_SRC
+ */
+#define WM2200_IN_RXANC_SEL_MASK 0x0007 /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_SHIFT 0 /* IN_RXANC_SEL - [2:0] */
+#define WM2200_IN_RXANC_SEL_WIDTH 3 /* IN_RXANC_SEL - [2:0] */
+
+/*
+ * R779 (0x30B) - Input Volume Ramp
+ */
+#define WM2200_IN_VD_RAMP_MASK 0x0070 /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_SHIFT 4 /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VD_RAMP_WIDTH 3 /* IN_VD_RAMP - [6:4] */
+#define WM2200_IN_VI_RAMP_MASK 0x0007 /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */
+#define WM2200_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */
+
+/*
+ * R780 (0x30C) - ADC Digital Volume 1L
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN1L_MUTE 0x0100 /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_MASK 0x0100 /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_SHIFT 8 /* IN1L_MUTE */
+#define WM2200_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */
+#define WM2200_IN1L_DIG_VOL_MASK 0x00FF /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_SHIFT 0 /* IN1L_DIG_VOL - [7:0] */
+#define WM2200_IN1L_DIG_VOL_WIDTH 8 /* IN1L_DIG_VOL - [7:0] */
+
+/*
+ * R781 (0x30D) - ADC Digital Volume 1R
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN1R_MUTE 0x0100 /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_MASK 0x0100 /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_SHIFT 8 /* IN1R_MUTE */
+#define WM2200_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */
+#define WM2200_IN1R_DIG_VOL_MASK 0x00FF /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_SHIFT 0 /* IN1R_DIG_VOL - [7:0] */
+#define WM2200_IN1R_DIG_VOL_WIDTH 8 /* IN1R_DIG_VOL - [7:0] */
+
+/*
+ * R782 (0x30E) - ADC Digital Volume 2L
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN2L_MUTE 0x0100 /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_MASK 0x0100 /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_SHIFT 8 /* IN2L_MUTE */
+#define WM2200_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */
+#define WM2200_IN2L_DIG_VOL_MASK 0x00FF /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_SHIFT 0 /* IN2L_DIG_VOL - [7:0] */
+#define WM2200_IN2L_DIG_VOL_WIDTH 8 /* IN2L_DIG_VOL - [7:0] */
+
+/*
+ * R783 (0x30F) - ADC Digital Volume 2R
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN2R_MUTE 0x0100 /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_MASK 0x0100 /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_SHIFT 8 /* IN2R_MUTE */
+#define WM2200_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */
+#define WM2200_IN2R_DIG_VOL_MASK 0x00FF /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_SHIFT 0 /* IN2R_DIG_VOL - [7:0] */
+#define WM2200_IN2R_DIG_VOL_WIDTH 8 /* IN2R_DIG_VOL - [7:0] */
+
+/*
+ * R784 (0x310) - ADC Digital Volume 3L
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN3L_MUTE 0x0100 /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_MASK 0x0100 /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_SHIFT 8 /* IN3L_MUTE */
+#define WM2200_IN3L_MUTE_WIDTH 1 /* IN3L_MUTE */
+#define WM2200_IN3L_DIG_VOL_MASK 0x00FF /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_SHIFT 0 /* IN3L_DIG_VOL - [7:0] */
+#define WM2200_IN3L_DIG_VOL_WIDTH 8 /* IN3L_DIG_VOL - [7:0] */
+
+/*
+ * R785 (0x311) - ADC Digital Volume 3R
+ */
+#define WM2200_IN_VU 0x0200 /* IN_VU */
+#define WM2200_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM2200_IN_VU_SHIFT 9 /* IN_VU */
+#define WM2200_IN_VU_WIDTH 1 /* IN_VU */
+#define WM2200_IN3R_MUTE 0x0100 /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_MASK 0x0100 /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_SHIFT 8 /* IN3R_MUTE */
+#define WM2200_IN3R_MUTE_WIDTH 1 /* IN3R_MUTE */
+#define WM2200_IN3R_DIG_VOL_MASK 0x00FF /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_SHIFT 0 /* IN3R_DIG_VOL - [7:0] */
+#define WM2200_IN3R_DIG_VOL_WIDTH 8 /* IN3R_DIG_VOL - [7:0] */
+
+/*
+ * R1024 (0x400) - Output Enables
+ */
+#define WM2200_OUT2L_ENA 0x0008 /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_MASK 0x0008 /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_SHIFT 3 /* OUT2L_ENA */
+#define WM2200_OUT2L_ENA_WIDTH 1 /* OUT2L_ENA */
+#define WM2200_OUT2R_ENA 0x0004 /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_MASK 0x0004 /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_SHIFT 2 /* OUT2R_ENA */
+#define WM2200_OUT2R_ENA_WIDTH 1 /* OUT2R_ENA */
+#define WM2200_OUT1L_ENA 0x0002 /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_MASK 0x0002 /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_SHIFT 1 /* OUT1L_ENA */
+#define WM2200_OUT1L_ENA_WIDTH 1 /* OUT1L_ENA */
+#define WM2200_OUT1R_ENA 0x0001 /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_MASK 0x0001 /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_SHIFT 0 /* OUT1R_ENA */
+#define WM2200_OUT1R_ENA_WIDTH 1 /* OUT1R_ENA */
+
+/*
+ * R1025 (0x401) - DAC Volume Limit 1L
+ */
+#define WM2200_OUT1_OSR 0x2000 /* OUT1_OSR */
+#define WM2200_OUT1_OSR_MASK 0x2000 /* OUT1_OSR */
+#define WM2200_OUT1_OSR_SHIFT 13 /* OUT1_OSR */
+#define WM2200_OUT1_OSR_WIDTH 1 /* OUT1_OSR */
+#define WM2200_OUT1L_ANC_SRC 0x0800 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_MASK 0x0800 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_SHIFT 11 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_ANC_SRC_WIDTH 1 /* OUT1L_ANC_SRC */
+#define WM2200_OUT1L_PGA_VOL_MASK 0x00FE /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_SHIFT 1 /* OUT1L_PGA_VOL - [7:1] */
+#define WM2200_OUT1L_PGA_VOL_WIDTH 7 /* OUT1L_PGA_VOL - [7:1] */
+
+/*
+ * R1026 (0x402) - DAC Volume Limit 1R
+ */
+#define WM2200_OUT1R_ANC_SRC 0x0800 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_MASK 0x0800 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_SHIFT 11 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_ANC_SRC_WIDTH 1 /* OUT1R_ANC_SRC */
+#define WM2200_OUT1R_PGA_VOL_MASK 0x00FE /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_SHIFT 1 /* OUT1R_PGA_VOL - [7:1] */
+#define WM2200_OUT1R_PGA_VOL_WIDTH 7 /* OUT1R_PGA_VOL - [7:1] */
+
+/*
+ * R1027 (0x403) - DAC Volume Limit 2L
+ */
+#define WM2200_OUT2_OSR 0x2000 /* OUT2_OSR */
+#define WM2200_OUT2_OSR_MASK 0x2000 /* OUT2_OSR */
+#define WM2200_OUT2_OSR_SHIFT 13 /* OUT2_OSR */
+#define WM2200_OUT2_OSR_WIDTH 1 /* OUT2_OSR */
+#define WM2200_OUT2L_ANC_SRC 0x0800 /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_MASK 0x0800 /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_SHIFT 11 /* OUT2L_ANC_SRC */
+#define WM2200_OUT2L_ANC_SRC_WIDTH 1 /* OUT2L_ANC_SRC */
+
+/*
+ * R1028 (0x404) - DAC Volume Limit 2R
+ */
+#define WM2200_OUT2R_ANC_SRC 0x0800 /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_MASK 0x0800 /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_SHIFT 11 /* OUT2R_ANC_SRC */
+#define WM2200_OUT2R_ANC_SRC_WIDTH 1 /* OUT2R_ANC_SRC */
+
+/*
+ * R1033 (0x409) - DAC AEC Control 1
+ */
+#define WM2200_AEC_LOOPBACK_ENA 0x0004 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_MASK 0x0004 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_SHIFT 2 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_ENA_WIDTH 1 /* AEC_LOOPBACK_ENA */
+#define WM2200_AEC_LOOPBACK_SRC_MASK 0x0003 /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_SHIFT 0 /* AEC_LOOPBACK_SRC - [1:0] */
+#define WM2200_AEC_LOOPBACK_SRC_WIDTH 2 /* AEC_LOOPBACK_SRC - [1:0] */
+
+/*
+ * R1034 (0x40A) - Output Volume Ramp
+ */
+#define WM2200_OUT_VD_RAMP_MASK 0x0070 /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_SHIFT 4 /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VD_RAMP_WIDTH 3 /* OUT_VD_RAMP - [6:4] */
+#define WM2200_OUT_VI_RAMP_MASK 0x0007 /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_SHIFT 0 /* OUT_VI_RAMP - [2:0] */
+#define WM2200_OUT_VI_RAMP_WIDTH 3 /* OUT_VI_RAMP - [2:0] */
+
+/*
+ * R1035 (0x40B) - DAC Digital Volume 1L
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT1L_MUTE 0x0100 /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_MASK 0x0100 /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_SHIFT 8 /* OUT1L_MUTE */
+#define WM2200_OUT1L_MUTE_WIDTH 1 /* OUT1L_MUTE */
+#define WM2200_OUT1L_VOL_MASK 0x00FF /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_SHIFT 0 /* OUT1L_VOL - [7:0] */
+#define WM2200_OUT1L_VOL_WIDTH 8 /* OUT1L_VOL - [7:0] */
+
+/*
+ * R1036 (0x40C) - DAC Digital Volume 1R
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT1R_MUTE 0x0100 /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_MASK 0x0100 /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_SHIFT 8 /* OUT1R_MUTE */
+#define WM2200_OUT1R_MUTE_WIDTH 1 /* OUT1R_MUTE */
+#define WM2200_OUT1R_VOL_MASK 0x00FF /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_SHIFT 0 /* OUT1R_VOL - [7:0] */
+#define WM2200_OUT1R_VOL_WIDTH 8 /* OUT1R_VOL - [7:0] */
+
+/*
+ * R1037 (0x40D) - DAC Digital Volume 2L
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT2L_MUTE 0x0100 /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_MASK 0x0100 /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_SHIFT 8 /* OUT2L_MUTE */
+#define WM2200_OUT2L_MUTE_WIDTH 1 /* OUT2L_MUTE */
+#define WM2200_OUT2L_VOL_MASK 0x00FF /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_SHIFT 0 /* OUT2L_VOL - [7:0] */
+#define WM2200_OUT2L_VOL_WIDTH 8 /* OUT2L_VOL - [7:0] */
+
+/*
+ * R1038 (0x40E) - DAC Digital Volume 2R
+ */
+#define WM2200_OUT_VU 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM2200_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM2200_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM2200_OUT2R_MUTE 0x0100 /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_MASK 0x0100 /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_SHIFT 8 /* OUT2R_MUTE */
+#define WM2200_OUT2R_MUTE_WIDTH 1 /* OUT2R_MUTE */
+#define WM2200_OUT2R_VOL_MASK 0x00FF /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_SHIFT 0 /* OUT2R_VOL - [7:0] */
+#define WM2200_OUT2R_VOL_WIDTH 8 /* OUT2R_VOL - [7:0] */
+
+/*
+ * R1047 (0x417) - PDM 1
+ */
+#define WM2200_SPK1R_MUTE 0x2000 /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_MASK 0x2000 /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_SHIFT 13 /* SPK1R_MUTE */
+#define WM2200_SPK1R_MUTE_WIDTH 1 /* SPK1R_MUTE */
+#define WM2200_SPK1L_MUTE 0x1000 /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_MASK 0x1000 /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_SHIFT 12 /* SPK1L_MUTE */
+#define WM2200_SPK1L_MUTE_WIDTH 1 /* SPK1L_MUTE */
+#define WM2200_SPK1_MUTE_ENDIAN 0x0100 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_MASK 0x0100 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_SHIFT 8 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_ENDIAN_WIDTH 1 /* SPK1_MUTE_ENDIAN */
+#define WM2200_SPK1_MUTE_SEQL_MASK 0x00FF /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_SHIFT 0 /* SPK1_MUTE_SEQL - [7:0] */
+#define WM2200_SPK1_MUTE_SEQL_WIDTH 8 /* SPK1_MUTE_SEQL - [7:0] */
+
+/*
+ * R1048 (0x418) - PDM 2
+ */
+#define WM2200_SPK1_FMT 0x0001 /* SPK1_FMT */
+#define WM2200_SPK1_FMT_MASK 0x0001 /* SPK1_FMT */
+#define WM2200_SPK1_FMT_SHIFT 0 /* SPK1_FMT */
+#define WM2200_SPK1_FMT_WIDTH 1 /* SPK1_FMT */
+
+/*
+ * R1280 (0x500) - Audio IF 1_1
+ */
+#define WM2200_AIF1_BCLK_INV 0x0040 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_MASK 0x0040 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_SHIFT 6 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */
+#define WM2200_AIF1_BCLK_FRC 0x0020 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_MASK 0x0020 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_SHIFT 5 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */
+#define WM2200_AIF1_BCLK_MSTR 0x0010 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_MASK 0x0010 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_SHIFT 4 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */
+#define WM2200_AIF1_BCLK_DIV_MASK 0x000F /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_SHIFT 0 /* AIF1_BCLK_DIV - [3:0] */
+#define WM2200_AIF1_BCLK_DIV_WIDTH 4 /* AIF1_BCLK_DIV - [3:0] */
+
+/*
+ * R1281 (0x501) - Audio IF 1_2
+ */
+#define WM2200_AIF1TX_DAT_TRI 0x0020 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_MASK 0x0020 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_SHIFT 5 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */
+#define WM2200_AIF1TX_LRCLK_SRC 0x0008 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_MASK 0x0008 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_SHIFT 3 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_SRC_WIDTH 1 /* AIF1TX_LRCLK_SRC */
+#define WM2200_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */
+#define WM2200_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */
+#define WM2200_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */
+#define WM2200_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R1282 (0x502) - Audio IF 1_3
+ */
+#define WM2200_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */
+#define WM2200_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */
+#define WM2200_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */
+#define WM2200_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R1283 (0x503) - Audio IF 1_4
+ */
+#define WM2200_AIF1_TRI 0x0040 /* AIF1_TRI */
+#define WM2200_AIF1_TRI_MASK 0x0040 /* AIF1_TRI */
+#define WM2200_AIF1_TRI_SHIFT 6 /* AIF1_TRI */
+#define WM2200_AIF1_TRI_WIDTH 1 /* AIF1_TRI */
+
+/*
+ * R1284 (0x504) - Audio IF 1_5
+ */
+#define WM2200_AIF1_FMT_MASK 0x0007 /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [2:0] */
+#define WM2200_AIF1_FMT_WIDTH 3 /* AIF1_FMT - [2:0] */
+
+/*
+ * R1285 (0x505) - Audio IF 1_6
+ */
+#define WM2200_AIF1TX_BCPF_MASK 0x07FF /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_SHIFT 0 /* AIF1TX_BCPF - [10:0] */
+#define WM2200_AIF1TX_BCPF_WIDTH 11 /* AIF1TX_BCPF - [10:0] */
+
+/*
+ * R1286 (0x506) - Audio IF 1_7
+ */
+#define WM2200_AIF1RX_BCPF_MASK 0x07FF /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_SHIFT 0 /* AIF1RX_BCPF - [10:0] */
+#define WM2200_AIF1RX_BCPF_WIDTH 11 /* AIF1RX_BCPF - [10:0] */
+
+/*
+ * R1287 (0x507) - Audio IF 1_8
+ */
+#define WM2200_AIF1TX_WL_MASK 0x3F00 /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_WL_WIDTH 6 /* AIF1TX_WL - [13:8] */
+#define WM2200_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1288 (0x508) - Audio IF 1_9
+ */
+#define WM2200_AIF1RX_WL_MASK 0x3F00 /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_WL_WIDTH 6 /* AIF1RX_WL - [13:8] */
+#define WM2200_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM2200_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1289 (0x509) - Audio IF 1_10
+ */
+#define WM2200_AIF1TX1_SLOT_MASK 0x003F /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_SHIFT 0 /* AIF1TX1_SLOT - [5:0] */
+#define WM2200_AIF1TX1_SLOT_WIDTH 6 /* AIF1TX1_SLOT - [5:0] */
+
+/*
+ * R1290 (0x50A) - Audio IF 1_11
+ */
+#define WM2200_AIF1TX2_SLOT_MASK 0x003F /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_SHIFT 0 /* AIF1TX2_SLOT - [5:0] */
+#define WM2200_AIF1TX2_SLOT_WIDTH 6 /* AIF1TX2_SLOT - [5:0] */
+
+/*
+ * R1291 (0x50B) - Audio IF 1_12
+ */
+#define WM2200_AIF1TX3_SLOT_MASK 0x003F /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_SHIFT 0 /* AIF1TX3_SLOT - [5:0] */
+#define WM2200_AIF1TX3_SLOT_WIDTH 6 /* AIF1TX3_SLOT - [5:0] */
+
+/*
+ * R1292 (0x50C) - Audio IF 1_13
+ */
+#define WM2200_AIF1TX4_SLOT_MASK 0x003F /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_SHIFT 0 /* AIF1TX4_SLOT - [5:0] */
+#define WM2200_AIF1TX4_SLOT_WIDTH 6 /* AIF1TX4_SLOT - [5:0] */
+
+/*
+ * R1293 (0x50D) - Audio IF 1_14
+ */
+#define WM2200_AIF1TX5_SLOT_MASK 0x003F /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_SHIFT 0 /* AIF1TX5_SLOT - [5:0] */
+#define WM2200_AIF1TX5_SLOT_WIDTH 6 /* AIF1TX5_SLOT - [5:0] */
+
+/*
+ * R1294 (0x50E) - Audio IF 1_15
+ */
+#define WM2200_AIF1TX6_SLOT_MASK 0x003F /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_SHIFT 0 /* AIF1TX6_SLOT - [5:0] */
+#define WM2200_AIF1TX6_SLOT_WIDTH 6 /* AIF1TX6_SLOT - [5:0] */
+
+/*
+ * R1295 (0x50F) - Audio IF 1_16
+ */
+#define WM2200_AIF1RX1_SLOT_MASK 0x003F /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_SHIFT 0 /* AIF1RX1_SLOT - [5:0] */
+#define WM2200_AIF1RX1_SLOT_WIDTH 6 /* AIF1RX1_SLOT - [5:0] */
+
+/*
+ * R1296 (0x510) - Audio IF 1_17
+ */
+#define WM2200_AIF1RX2_SLOT_MASK 0x003F /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_SHIFT 0 /* AIF1RX2_SLOT - [5:0] */
+#define WM2200_AIF1RX2_SLOT_WIDTH 6 /* AIF1RX2_SLOT - [5:0] */
+
+/*
+ * R1297 (0x511) - Audio IF 1_18
+ */
+#define WM2200_AIF1RX3_SLOT_MASK 0x003F /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_SHIFT 0 /* AIF1RX3_SLOT - [5:0] */
+#define WM2200_AIF1RX3_SLOT_WIDTH 6 /* AIF1RX3_SLOT - [5:0] */
+
+/*
+ * R1298 (0x512) - Audio IF 1_19
+ */
+#define WM2200_AIF1RX4_SLOT_MASK 0x003F /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_SHIFT 0 /* AIF1RX4_SLOT - [5:0] */
+#define WM2200_AIF1RX4_SLOT_WIDTH 6 /* AIF1RX4_SLOT - [5:0] */
+
+/*
+ * R1299 (0x513) - Audio IF 1_20
+ */
+#define WM2200_AIF1RX5_SLOT_MASK 0x003F /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_SHIFT 0 /* AIF1RX5_SLOT - [5:0] */
+#define WM2200_AIF1RX5_SLOT_WIDTH 6 /* AIF1RX5_SLOT - [5:0] */
+
+/*
+ * R1300 (0x514) - Audio IF 1_21
+ */
+#define WM2200_AIF1RX6_SLOT_MASK 0x003F /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_SHIFT 0 /* AIF1RX6_SLOT - [5:0] */
+#define WM2200_AIF1RX6_SLOT_WIDTH 6 /* AIF1RX6_SLOT - [5:0] */
+
+/*
+ * R1301 (0x515) - Audio IF 1_22
+ */
+#define WM2200_AIF1RX6_ENA 0x0800 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_MASK 0x0800 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_SHIFT 11 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX6_ENA_WIDTH 1 /* AIF1RX6_ENA */
+#define WM2200_AIF1RX5_ENA 0x0400 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_MASK 0x0400 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_SHIFT 10 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX5_ENA_WIDTH 1 /* AIF1RX5_ENA */
+#define WM2200_AIF1RX4_ENA 0x0200 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_MASK 0x0200 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_SHIFT 9 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX4_ENA_WIDTH 1 /* AIF1RX4_ENA */
+#define WM2200_AIF1RX3_ENA 0x0100 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_MASK 0x0100 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_SHIFT 8 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX3_ENA_WIDTH 1 /* AIF1RX3_ENA */
+#define WM2200_AIF1RX2_ENA 0x0080 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_MASK 0x0080 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_SHIFT 7 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX2_ENA_WIDTH 1 /* AIF1RX2_ENA */
+#define WM2200_AIF1RX1_ENA 0x0040 /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_MASK 0x0040 /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_SHIFT 6 /* AIF1RX1_ENA */
+#define WM2200_AIF1RX1_ENA_WIDTH 1 /* AIF1RX1_ENA */
+#define WM2200_AIF1TX6_ENA 0x0020 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_MASK 0x0020 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_SHIFT 5 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX6_ENA_WIDTH 1 /* AIF1TX6_ENA */
+#define WM2200_AIF1TX5_ENA 0x0010 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_MASK 0x0010 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_SHIFT 4 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX5_ENA_WIDTH 1 /* AIF1TX5_ENA */
+#define WM2200_AIF1TX4_ENA 0x0008 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_MASK 0x0008 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_SHIFT 3 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX4_ENA_WIDTH 1 /* AIF1TX4_ENA */
+#define WM2200_AIF1TX3_ENA 0x0004 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_MASK 0x0004 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_SHIFT 2 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX3_ENA_WIDTH 1 /* AIF1TX3_ENA */
+#define WM2200_AIF1TX2_ENA 0x0002 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_MASK 0x0002 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_SHIFT 1 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX2_ENA_WIDTH 1 /* AIF1TX2_ENA */
+#define WM2200_AIF1TX1_ENA 0x0001 /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_MASK 0x0001 /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_SHIFT 0 /* AIF1TX1_ENA */
+#define WM2200_AIF1TX1_ENA_WIDTH 1 /* AIF1TX1_ENA */
+
+/*
+ * R1536 (0x600) - OUT1LMIX Input 1 Source
+ */
+#define WM2200_OUT1LMIX_SRC1_MASK 0x007F /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_SHIFT 0 /* OUT1LMIX_SRC1 - [6:0] */
+#define WM2200_OUT1LMIX_SRC1_WIDTH 7 /* OUT1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1537 (0x601) - OUT1LMIX Input 1 Volume
+ */
+#define WM2200_OUT1LMIX_VOL1_MASK 0x00FE /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_SHIFT 1 /* OUT1LMIX_VOL1 - [7:1] */
+#define WM2200_OUT1LMIX_VOL1_WIDTH 7 /* OUT1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1538 (0x602) - OUT1LMIX Input 2 Source
+ */
+#define WM2200_OUT1LMIX_SRC2_MASK 0x007F /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_SHIFT 0 /* OUT1LMIX_SRC2 - [6:0] */
+#define WM2200_OUT1LMIX_SRC2_WIDTH 7 /* OUT1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1539 (0x603) - OUT1LMIX Input 2 Volume
+ */
+#define WM2200_OUT1LMIX_VOL2_MASK 0x00FE /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_SHIFT 1 /* OUT1LMIX_VOL2 - [7:1] */
+#define WM2200_OUT1LMIX_VOL2_WIDTH 7 /* OUT1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1540 (0x604) - OUT1LMIX Input 3 Source
+ */
+#define WM2200_OUT1LMIX_SRC3_MASK 0x007F /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_SHIFT 0 /* OUT1LMIX_SRC3 - [6:0] */
+#define WM2200_OUT1LMIX_SRC3_WIDTH 7 /* OUT1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1541 (0x605) - OUT1LMIX Input 3 Volume
+ */
+#define WM2200_OUT1LMIX_VOL3_MASK 0x00FE /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_SHIFT 1 /* OUT1LMIX_VOL3 - [7:1] */
+#define WM2200_OUT1LMIX_VOL3_WIDTH 7 /* OUT1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1542 (0x606) - OUT1LMIX Input 4 Source
+ */
+#define WM2200_OUT1LMIX_SRC4_MASK 0x007F /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_SHIFT 0 /* OUT1LMIX_SRC4 - [6:0] */
+#define WM2200_OUT1LMIX_SRC4_WIDTH 7 /* OUT1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1543 (0x607) - OUT1LMIX Input 4 Volume
+ */
+#define WM2200_OUT1LMIX_VOL4_MASK 0x00FE /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_SHIFT 1 /* OUT1LMIX_VOL4 - [7:1] */
+#define WM2200_OUT1LMIX_VOL4_WIDTH 7 /* OUT1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1544 (0x608) - OUT1RMIX Input 1 Source
+ */
+#define WM2200_OUT1RMIX_SRC1_MASK 0x007F /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_SHIFT 0 /* OUT1RMIX_SRC1 - [6:0] */
+#define WM2200_OUT1RMIX_SRC1_WIDTH 7 /* OUT1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1545 (0x609) - OUT1RMIX Input 1 Volume
+ */
+#define WM2200_OUT1RMIX_VOL1_MASK 0x00FE /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_SHIFT 1 /* OUT1RMIX_VOL1 - [7:1] */
+#define WM2200_OUT1RMIX_VOL1_WIDTH 7 /* OUT1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1546 (0x60A) - OUT1RMIX Input 2 Source
+ */
+#define WM2200_OUT1RMIX_SRC2_MASK 0x007F /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_SHIFT 0 /* OUT1RMIX_SRC2 - [6:0] */
+#define WM2200_OUT1RMIX_SRC2_WIDTH 7 /* OUT1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1547 (0x60B) - OUT1RMIX Input 2 Volume
+ */
+#define WM2200_OUT1RMIX_VOL2_MASK 0x00FE /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_SHIFT 1 /* OUT1RMIX_VOL2 - [7:1] */
+#define WM2200_OUT1RMIX_VOL2_WIDTH 7 /* OUT1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1548 (0x60C) - OUT1RMIX Input 3 Source
+ */
+#define WM2200_OUT1RMIX_SRC3_MASK 0x007F /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_SHIFT 0 /* OUT1RMIX_SRC3 - [6:0] */
+#define WM2200_OUT1RMIX_SRC3_WIDTH 7 /* OUT1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1549 (0x60D) - OUT1RMIX Input 3 Volume
+ */
+#define WM2200_OUT1RMIX_VOL3_MASK 0x00FE /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_SHIFT 1 /* OUT1RMIX_VOL3 - [7:1] */
+#define WM2200_OUT1RMIX_VOL3_WIDTH 7 /* OUT1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1550 (0x60E) - OUT1RMIX Input 4 Source
+ */
+#define WM2200_OUT1RMIX_SRC4_MASK 0x007F /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_SHIFT 0 /* OUT1RMIX_SRC4 - [6:0] */
+#define WM2200_OUT1RMIX_SRC4_WIDTH 7 /* OUT1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1551 (0x60F) - OUT1RMIX Input 4 Volume
+ */
+#define WM2200_OUT1RMIX_VOL4_MASK 0x00FE /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_SHIFT 1 /* OUT1RMIX_VOL4 - [7:1] */
+#define WM2200_OUT1RMIX_VOL4_WIDTH 7 /* OUT1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1552 (0x610) - OUT2LMIX Input 1 Source
+ */
+#define WM2200_OUT2LMIX_SRC1_MASK 0x007F /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_SHIFT 0 /* OUT2LMIX_SRC1 - [6:0] */
+#define WM2200_OUT2LMIX_SRC1_WIDTH 7 /* OUT2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1553 (0x611) - OUT2LMIX Input 1 Volume
+ */
+#define WM2200_OUT2LMIX_VOL1_MASK 0x00FE /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_SHIFT 1 /* OUT2LMIX_VOL1 - [7:1] */
+#define WM2200_OUT2LMIX_VOL1_WIDTH 7 /* OUT2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1554 (0x612) - OUT2LMIX Input 2 Source
+ */
+#define WM2200_OUT2LMIX_SRC2_MASK 0x007F /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_SHIFT 0 /* OUT2LMIX_SRC2 - [6:0] */
+#define WM2200_OUT2LMIX_SRC2_WIDTH 7 /* OUT2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1555 (0x613) - OUT2LMIX Input 2 Volume
+ */
+#define WM2200_OUT2LMIX_VOL2_MASK 0x00FE /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_SHIFT 1 /* OUT2LMIX_VOL2 - [7:1] */
+#define WM2200_OUT2LMIX_VOL2_WIDTH 7 /* OUT2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1556 (0x614) - OUT2LMIX Input 3 Source
+ */
+#define WM2200_OUT2LMIX_SRC3_MASK 0x007F /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_SHIFT 0 /* OUT2LMIX_SRC3 - [6:0] */
+#define WM2200_OUT2LMIX_SRC3_WIDTH 7 /* OUT2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1557 (0x615) - OUT2LMIX Input 3 Volume
+ */
+#define WM2200_OUT2LMIX_VOL3_MASK 0x00FE /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_SHIFT 1 /* OUT2LMIX_VOL3 - [7:1] */
+#define WM2200_OUT2LMIX_VOL3_WIDTH 7 /* OUT2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1558 (0x616) - OUT2LMIX Input 4 Source
+ */
+#define WM2200_OUT2LMIX_SRC4_MASK 0x007F /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_SHIFT 0 /* OUT2LMIX_SRC4 - [6:0] */
+#define WM2200_OUT2LMIX_SRC4_WIDTH 7 /* OUT2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1559 (0x617) - OUT2LMIX Input 4 Volume
+ */
+#define WM2200_OUT2LMIX_VOL4_MASK 0x00FE /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_SHIFT 1 /* OUT2LMIX_VOL4 - [7:1] */
+#define WM2200_OUT2LMIX_VOL4_WIDTH 7 /* OUT2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1560 (0x618) - OUT2RMIX Input 1 Source
+ */
+#define WM2200_OUT2RMIX_SRC1_MASK 0x007F /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_SHIFT 0 /* OUT2RMIX_SRC1 - [6:0] */
+#define WM2200_OUT2RMIX_SRC1_WIDTH 7 /* OUT2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1561 (0x619) - OUT2RMIX Input 1 Volume
+ */
+#define WM2200_OUT2RMIX_VOL1_MASK 0x00FE /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_SHIFT 1 /* OUT2RMIX_VOL1 - [7:1] */
+#define WM2200_OUT2RMIX_VOL1_WIDTH 7 /* OUT2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1562 (0x61A) - OUT2RMIX Input 2 Source
+ */
+#define WM2200_OUT2RMIX_SRC2_MASK 0x007F /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_SHIFT 0 /* OUT2RMIX_SRC2 - [6:0] */
+#define WM2200_OUT2RMIX_SRC2_WIDTH 7 /* OUT2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1563 (0x61B) - OUT2RMIX Input 2 Volume
+ */
+#define WM2200_OUT2RMIX_VOL2_MASK 0x00FE /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_SHIFT 1 /* OUT2RMIX_VOL2 - [7:1] */
+#define WM2200_OUT2RMIX_VOL2_WIDTH 7 /* OUT2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1564 (0x61C) - OUT2RMIX Input 3 Source
+ */
+#define WM2200_OUT2RMIX_SRC3_MASK 0x007F /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_SHIFT 0 /* OUT2RMIX_SRC3 - [6:0] */
+#define WM2200_OUT2RMIX_SRC3_WIDTH 7 /* OUT2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1565 (0x61D) - OUT2RMIX Input 3 Volume
+ */
+#define WM2200_OUT2RMIX_VOL3_MASK 0x00FE /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_SHIFT 1 /* OUT2RMIX_VOL3 - [7:1] */
+#define WM2200_OUT2RMIX_VOL3_WIDTH 7 /* OUT2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1566 (0x61E) - OUT2RMIX Input 4 Source
+ */
+#define WM2200_OUT2RMIX_SRC4_MASK 0x007F /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_SHIFT 0 /* OUT2RMIX_SRC4 - [6:0] */
+#define WM2200_OUT2RMIX_SRC4_WIDTH 7 /* OUT2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1567 (0x61F) - OUT2RMIX Input 4 Volume
+ */
+#define WM2200_OUT2RMIX_VOL4_MASK 0x00FE /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_SHIFT 1 /* OUT2RMIX_VOL4 - [7:1] */
+#define WM2200_OUT2RMIX_VOL4_WIDTH 7 /* OUT2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1568 (0x620) - AIF1TX1MIX Input 1 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC1_MASK 0x007F /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_SHIFT 0 /* AIF1TX1MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC1_WIDTH 7 /* AIF1TX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1569 (0x621) - AIF1TX1MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL1_MASK 0x00FE /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_SHIFT 1 /* AIF1TX1MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL1_WIDTH 7 /* AIF1TX1MIX_VOL1 - [7:1] */
+
+/*
+ * R1570 (0x622) - AIF1TX1MIX Input 2 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC2_MASK 0x007F /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_SHIFT 0 /* AIF1TX1MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC2_WIDTH 7 /* AIF1TX1MIX_SRC2 - [6:0] */
+
+/*
+ * R1571 (0x623) - AIF1TX1MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL2_MASK 0x00FE /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_SHIFT 1 /* AIF1TX1MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL2_WIDTH 7 /* AIF1TX1MIX_VOL2 - [7:1] */
+
+/*
+ * R1572 (0x624) - AIF1TX1MIX Input 3 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC3_MASK 0x007F /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_SHIFT 0 /* AIF1TX1MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC3_WIDTH 7 /* AIF1TX1MIX_SRC3 - [6:0] */
+
+/*
+ * R1573 (0x625) - AIF1TX1MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL3_MASK 0x00FE /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_SHIFT 1 /* AIF1TX1MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL3_WIDTH 7 /* AIF1TX1MIX_VOL3 - [7:1] */
+
+/*
+ * R1574 (0x626) - AIF1TX1MIX Input 4 Source
+ */
+#define WM2200_AIF1TX1MIX_SRC4_MASK 0x007F /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_SHIFT 0 /* AIF1TX1MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX1MIX_SRC4_WIDTH 7 /* AIF1TX1MIX_SRC4 - [6:0] */
+
+/*
+ * R1575 (0x627) - AIF1TX1MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX1MIX_VOL4_MASK 0x00FE /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_SHIFT 1 /* AIF1TX1MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX1MIX_VOL4_WIDTH 7 /* AIF1TX1MIX_VOL4 - [7:1] */
+
+/*
+ * R1576 (0x628) - AIF1TX2MIX Input 1 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC1_MASK 0x007F /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_SHIFT 0 /* AIF1TX2MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC1_WIDTH 7 /* AIF1TX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1577 (0x629) - AIF1TX2MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL1_MASK 0x00FE /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_SHIFT 1 /* AIF1TX2MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL1_WIDTH 7 /* AIF1TX2MIX_VOL1 - [7:1] */
+
+/*
+ * R1578 (0x62A) - AIF1TX2MIX Input 2 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC2_MASK 0x007F /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_SHIFT 0 /* AIF1TX2MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC2_WIDTH 7 /* AIF1TX2MIX_SRC2 - [6:0] */
+
+/*
+ * R1579 (0x62B) - AIF1TX2MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL2_MASK 0x00FE /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_SHIFT 1 /* AIF1TX2MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL2_WIDTH 7 /* AIF1TX2MIX_VOL2 - [7:1] */
+
+/*
+ * R1580 (0x62C) - AIF1TX2MIX Input 3 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC3_MASK 0x007F /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_SHIFT 0 /* AIF1TX2MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC3_WIDTH 7 /* AIF1TX2MIX_SRC3 - [6:0] */
+
+/*
+ * R1581 (0x62D) - AIF1TX2MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL3_MASK 0x00FE /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_SHIFT 1 /* AIF1TX2MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL3_WIDTH 7 /* AIF1TX2MIX_VOL3 - [7:1] */
+
+/*
+ * R1582 (0x62E) - AIF1TX2MIX Input 4 Source
+ */
+#define WM2200_AIF1TX2MIX_SRC4_MASK 0x007F /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_SHIFT 0 /* AIF1TX2MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX2MIX_SRC4_WIDTH 7 /* AIF1TX2MIX_SRC4 - [6:0] */
+
+/*
+ * R1583 (0x62F) - AIF1TX2MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX2MIX_VOL4_MASK 0x00FE /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_SHIFT 1 /* AIF1TX2MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX2MIX_VOL4_WIDTH 7 /* AIF1TX2MIX_VOL4 - [7:1] */
+
+/*
+ * R1584 (0x630) - AIF1TX3MIX Input 1 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC1_MASK 0x007F /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_SHIFT 0 /* AIF1TX3MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC1_WIDTH 7 /* AIF1TX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1585 (0x631) - AIF1TX3MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL1_MASK 0x00FE /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_SHIFT 1 /* AIF1TX3MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL1_WIDTH 7 /* AIF1TX3MIX_VOL1 - [7:1] */
+
+/*
+ * R1586 (0x632) - AIF1TX3MIX Input 2 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC2_MASK 0x007F /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_SHIFT 0 /* AIF1TX3MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC2_WIDTH 7 /* AIF1TX3MIX_SRC2 - [6:0] */
+
+/*
+ * R1587 (0x633) - AIF1TX3MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL2_MASK 0x00FE /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_SHIFT 1 /* AIF1TX3MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL2_WIDTH 7 /* AIF1TX3MIX_VOL2 - [7:1] */
+
+/*
+ * R1588 (0x634) - AIF1TX3MIX Input 3 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC3_MASK 0x007F /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_SHIFT 0 /* AIF1TX3MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC3_WIDTH 7 /* AIF1TX3MIX_SRC3 - [6:0] */
+
+/*
+ * R1589 (0x635) - AIF1TX3MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL3_MASK 0x00FE /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_SHIFT 1 /* AIF1TX3MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL3_WIDTH 7 /* AIF1TX3MIX_VOL3 - [7:1] */
+
+/*
+ * R1590 (0x636) - AIF1TX3MIX Input 4 Source
+ */
+#define WM2200_AIF1TX3MIX_SRC4_MASK 0x007F /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_SHIFT 0 /* AIF1TX3MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX3MIX_SRC4_WIDTH 7 /* AIF1TX3MIX_SRC4 - [6:0] */
+
+/*
+ * R1591 (0x637) - AIF1TX3MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX3MIX_VOL4_MASK 0x00FE /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_SHIFT 1 /* AIF1TX3MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX3MIX_VOL4_WIDTH 7 /* AIF1TX3MIX_VOL4 - [7:1] */
+
+/*
+ * R1592 (0x638) - AIF1TX4MIX Input 1 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC1_MASK 0x007F /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_SHIFT 0 /* AIF1TX4MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC1_WIDTH 7 /* AIF1TX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1593 (0x639) - AIF1TX4MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL1_MASK 0x00FE /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_SHIFT 1 /* AIF1TX4MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL1_WIDTH 7 /* AIF1TX4MIX_VOL1 - [7:1] */
+
+/*
+ * R1594 (0x63A) - AIF1TX4MIX Input 2 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC2_MASK 0x007F /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_SHIFT 0 /* AIF1TX4MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC2_WIDTH 7 /* AIF1TX4MIX_SRC2 - [6:0] */
+
+/*
+ * R1595 (0x63B) - AIF1TX4MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL2_MASK 0x00FE /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_SHIFT 1 /* AIF1TX4MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL2_WIDTH 7 /* AIF1TX4MIX_VOL2 - [7:1] */
+
+/*
+ * R1596 (0x63C) - AIF1TX4MIX Input 3 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC3_MASK 0x007F /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_SHIFT 0 /* AIF1TX4MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC3_WIDTH 7 /* AIF1TX4MIX_SRC3 - [6:0] */
+
+/*
+ * R1597 (0x63D) - AIF1TX4MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL3_MASK 0x00FE /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_SHIFT 1 /* AIF1TX4MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL3_WIDTH 7 /* AIF1TX4MIX_VOL3 - [7:1] */
+
+/*
+ * R1598 (0x63E) - AIF1TX4MIX Input 4 Source
+ */
+#define WM2200_AIF1TX4MIX_SRC4_MASK 0x007F /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_SHIFT 0 /* AIF1TX4MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX4MIX_SRC4_WIDTH 7 /* AIF1TX4MIX_SRC4 - [6:0] */
+
+/*
+ * R1599 (0x63F) - AIF1TX4MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX4MIX_VOL4_MASK 0x00FE /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_SHIFT 1 /* AIF1TX4MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX4MIX_VOL4_WIDTH 7 /* AIF1TX4MIX_VOL4 - [7:1] */
+
+/*
+ * R1600 (0x640) - AIF1TX5MIX Input 1 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC1_MASK 0x007F /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_SHIFT 0 /* AIF1TX5MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC1_WIDTH 7 /* AIF1TX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1601 (0x641) - AIF1TX5MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL1_MASK 0x00FE /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_SHIFT 1 /* AIF1TX5MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL1_WIDTH 7 /* AIF1TX5MIX_VOL1 - [7:1] */
+
+/*
+ * R1602 (0x642) - AIF1TX5MIX Input 2 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC2_MASK 0x007F /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_SHIFT 0 /* AIF1TX5MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC2_WIDTH 7 /* AIF1TX5MIX_SRC2 - [6:0] */
+
+/*
+ * R1603 (0x643) - AIF1TX5MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL2_MASK 0x00FE /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_SHIFT 1 /* AIF1TX5MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL2_WIDTH 7 /* AIF1TX5MIX_VOL2 - [7:1] */
+
+/*
+ * R1604 (0x644) - AIF1TX5MIX Input 3 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC3_MASK 0x007F /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_SHIFT 0 /* AIF1TX5MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC3_WIDTH 7 /* AIF1TX5MIX_SRC3 - [6:0] */
+
+/*
+ * R1605 (0x645) - AIF1TX5MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL3_MASK 0x00FE /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_SHIFT 1 /* AIF1TX5MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL3_WIDTH 7 /* AIF1TX5MIX_VOL3 - [7:1] */
+
+/*
+ * R1606 (0x646) - AIF1TX5MIX Input 4 Source
+ */
+#define WM2200_AIF1TX5MIX_SRC4_MASK 0x007F /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_SHIFT 0 /* AIF1TX5MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX5MIX_SRC4_WIDTH 7 /* AIF1TX5MIX_SRC4 - [6:0] */
+
+/*
+ * R1607 (0x647) - AIF1TX5MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX5MIX_VOL4_MASK 0x00FE /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_SHIFT 1 /* AIF1TX5MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX5MIX_VOL4_WIDTH 7 /* AIF1TX5MIX_VOL4 - [7:1] */
+
+/*
+ * R1608 (0x648) - AIF1TX6MIX Input 1 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC1_MASK 0x007F /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_SHIFT 0 /* AIF1TX6MIX_SRC1 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC1_WIDTH 7 /* AIF1TX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1609 (0x649) - AIF1TX6MIX Input 1 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL1_MASK 0x00FE /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_SHIFT 1 /* AIF1TX6MIX_VOL1 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL1_WIDTH 7 /* AIF1TX6MIX_VOL1 - [7:1] */
+
+/*
+ * R1610 (0x64A) - AIF1TX6MIX Input 2 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC2_MASK 0x007F /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_SHIFT 0 /* AIF1TX6MIX_SRC2 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC2_WIDTH 7 /* AIF1TX6MIX_SRC2 - [6:0] */
+
+/*
+ * R1611 (0x64B) - AIF1TX6MIX Input 2 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL2_MASK 0x00FE /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_SHIFT 1 /* AIF1TX6MIX_VOL2 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL2_WIDTH 7 /* AIF1TX6MIX_VOL2 - [7:1] */
+
+/*
+ * R1612 (0x64C) - AIF1TX6MIX Input 3 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC3_MASK 0x007F /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_SHIFT 0 /* AIF1TX6MIX_SRC3 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC3_WIDTH 7 /* AIF1TX6MIX_SRC3 - [6:0] */
+
+/*
+ * R1613 (0x64D) - AIF1TX6MIX Input 3 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL3_MASK 0x00FE /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_SHIFT 1 /* AIF1TX6MIX_VOL3 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL3_WIDTH 7 /* AIF1TX6MIX_VOL3 - [7:1] */
+
+/*
+ * R1614 (0x64E) - AIF1TX6MIX Input 4 Source
+ */
+#define WM2200_AIF1TX6MIX_SRC4_MASK 0x007F /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_SHIFT 0 /* AIF1TX6MIX_SRC4 - [6:0] */
+#define WM2200_AIF1TX6MIX_SRC4_WIDTH 7 /* AIF1TX6MIX_SRC4 - [6:0] */
+
+/*
+ * R1615 (0x64F) - AIF1TX6MIX Input 4 Volume
+ */
+#define WM2200_AIF1TX6MIX_VOL4_MASK 0x00FE /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_SHIFT 1 /* AIF1TX6MIX_VOL4 - [7:1] */
+#define WM2200_AIF1TX6MIX_VOL4_WIDTH 7 /* AIF1TX6MIX_VOL4 - [7:1] */
+
+/*
+ * R1616 (0x650) - EQLMIX Input 1 Source
+ */
+#define WM2200_EQLMIX_SRC1_MASK 0x007F /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_SHIFT 0 /* EQLMIX_SRC1 - [6:0] */
+#define WM2200_EQLMIX_SRC1_WIDTH 7 /* EQLMIX_SRC1 - [6:0] */
+
+/*
+ * R1617 (0x651) - EQLMIX Input 1 Volume
+ */
+#define WM2200_EQLMIX_VOL1_MASK 0x00FE /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_SHIFT 1 /* EQLMIX_VOL1 - [7:1] */
+#define WM2200_EQLMIX_VOL1_WIDTH 7 /* EQLMIX_VOL1 - [7:1] */
+
+/*
+ * R1618 (0x652) - EQLMIX Input 2 Source
+ */
+#define WM2200_EQLMIX_SRC2_MASK 0x007F /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_SHIFT 0 /* EQLMIX_SRC2 - [6:0] */
+#define WM2200_EQLMIX_SRC2_WIDTH 7 /* EQLMIX_SRC2 - [6:0] */
+
+/*
+ * R1619 (0x653) - EQLMIX Input 2 Volume
+ */
+#define WM2200_EQLMIX_VOL2_MASK 0x00FE /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_SHIFT 1 /* EQLMIX_VOL2 - [7:1] */
+#define WM2200_EQLMIX_VOL2_WIDTH 7 /* EQLMIX_VOL2 - [7:1] */
+
+/*
+ * R1620 (0x654) - EQLMIX Input 3 Source
+ */
+#define WM2200_EQLMIX_SRC3_MASK 0x007F /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_SHIFT 0 /* EQLMIX_SRC3 - [6:0] */
+#define WM2200_EQLMIX_SRC3_WIDTH 7 /* EQLMIX_SRC3 - [6:0] */
+
+/*
+ * R1621 (0x655) - EQLMIX Input 3 Volume
+ */
+#define WM2200_EQLMIX_VOL3_MASK 0x00FE /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_SHIFT 1 /* EQLMIX_VOL3 - [7:1] */
+#define WM2200_EQLMIX_VOL3_WIDTH 7 /* EQLMIX_VOL3 - [7:1] */
+
+/*
+ * R1622 (0x656) - EQLMIX Input 4 Source
+ */
+#define WM2200_EQLMIX_SRC4_MASK 0x007F /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_SHIFT 0 /* EQLMIX_SRC4 - [6:0] */
+#define WM2200_EQLMIX_SRC4_WIDTH 7 /* EQLMIX_SRC4 - [6:0] */
+
+/*
+ * R1623 (0x657) - EQLMIX Input 4 Volume
+ */
+#define WM2200_EQLMIX_VOL4_MASK 0x00FE /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_SHIFT 1 /* EQLMIX_VOL4 - [7:1] */
+#define WM2200_EQLMIX_VOL4_WIDTH 7 /* EQLMIX_VOL4 - [7:1] */
+
+/*
+ * R1624 (0x658) - EQRMIX Input 1 Source
+ */
+#define WM2200_EQRMIX_SRC1_MASK 0x007F /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_SHIFT 0 /* EQRMIX_SRC1 - [6:0] */
+#define WM2200_EQRMIX_SRC1_WIDTH 7 /* EQRMIX_SRC1 - [6:0] */
+
+/*
+ * R1625 (0x659) - EQRMIX Input 1 Volume
+ */
+#define WM2200_EQRMIX_VOL1_MASK 0x00FE /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_SHIFT 1 /* EQRMIX_VOL1 - [7:1] */
+#define WM2200_EQRMIX_VOL1_WIDTH 7 /* EQRMIX_VOL1 - [7:1] */
+
+/*
+ * R1626 (0x65A) - EQRMIX Input 2 Source
+ */
+#define WM2200_EQRMIX_SRC2_MASK 0x007F /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_SHIFT 0 /* EQRMIX_SRC2 - [6:0] */
+#define WM2200_EQRMIX_SRC2_WIDTH 7 /* EQRMIX_SRC2 - [6:0] */
+
+/*
+ * R1627 (0x65B) - EQRMIX Input 2 Volume
+ */
+#define WM2200_EQRMIX_VOL2_MASK 0x00FE /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_SHIFT 1 /* EQRMIX_VOL2 - [7:1] */
+#define WM2200_EQRMIX_VOL2_WIDTH 7 /* EQRMIX_VOL2 - [7:1] */
+
+/*
+ * R1628 (0x65C) - EQRMIX Input 3 Source
+ */
+#define WM2200_EQRMIX_SRC3_MASK 0x007F /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_SHIFT 0 /* EQRMIX_SRC3 - [6:0] */
+#define WM2200_EQRMIX_SRC3_WIDTH 7 /* EQRMIX_SRC3 - [6:0] */
+
+/*
+ * R1629 (0x65D) - EQRMIX Input 3 Volume
+ */
+#define WM2200_EQRMIX_VOL3_MASK 0x00FE /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_SHIFT 1 /* EQRMIX_VOL3 - [7:1] */
+#define WM2200_EQRMIX_VOL3_WIDTH 7 /* EQRMIX_VOL3 - [7:1] */
+
+/*
+ * R1630 (0x65E) - EQRMIX Input 4 Source
+ */
+#define WM2200_EQRMIX_SRC4_MASK 0x007F /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_SHIFT 0 /* EQRMIX_SRC4 - [6:0] */
+#define WM2200_EQRMIX_SRC4_WIDTH 7 /* EQRMIX_SRC4 - [6:0] */
+
+/*
+ * R1631 (0x65F) - EQRMIX Input 4 Volume
+ */
+#define WM2200_EQRMIX_VOL4_MASK 0x00FE /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_SHIFT 1 /* EQRMIX_VOL4 - [7:1] */
+#define WM2200_EQRMIX_VOL4_WIDTH 7 /* EQRMIX_VOL4 - [7:1] */
+
+/*
+ * R1632 (0x660) - LHPF1MIX Input 1 Source
+ */
+#define WM2200_LHPF1MIX_SRC1_MASK 0x007F /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_SHIFT 0 /* LHPF1MIX_SRC1 - [6:0] */
+#define WM2200_LHPF1MIX_SRC1_WIDTH 7 /* LHPF1MIX_SRC1 - [6:0] */
+
+/*
+ * R1633 (0x661) - LHPF1MIX Input 1 Volume
+ */
+#define WM2200_LHPF1MIX_VOL1_MASK 0x00FE /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_SHIFT 1 /* LHPF1MIX_VOL1 - [7:1] */
+#define WM2200_LHPF1MIX_VOL1_WIDTH 7 /* LHPF1MIX_VOL1 - [7:1] */
+
+/*
+ * R1634 (0x662) - LHPF1MIX Input 2 Source
+ */
+#define WM2200_LHPF1MIX_SRC2_MASK 0x007F /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_SHIFT 0 /* LHPF1MIX_SRC2 - [6:0] */
+#define WM2200_LHPF1MIX_SRC2_WIDTH 7 /* LHPF1MIX_SRC2 - [6:0] */
+
+/*
+ * R1635 (0x663) - LHPF1MIX Input 2 Volume
+ */
+#define WM2200_LHPF1MIX_VOL2_MASK 0x00FE /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_SHIFT 1 /* LHPF1MIX_VOL2 - [7:1] */
+#define WM2200_LHPF1MIX_VOL2_WIDTH 7 /* LHPF1MIX_VOL2 - [7:1] */
+
+/*
+ * R1636 (0x664) - LHPF1MIX Input 3 Source
+ */
+#define WM2200_LHPF1MIX_SRC3_MASK 0x007F /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_SHIFT 0 /* LHPF1MIX_SRC3 - [6:0] */
+#define WM2200_LHPF1MIX_SRC3_WIDTH 7 /* LHPF1MIX_SRC3 - [6:0] */
+
+/*
+ * R1637 (0x665) - LHPF1MIX Input 3 Volume
+ */
+#define WM2200_LHPF1MIX_VOL3_MASK 0x00FE /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_SHIFT 1 /* LHPF1MIX_VOL3 - [7:1] */
+#define WM2200_LHPF1MIX_VOL3_WIDTH 7 /* LHPF1MIX_VOL3 - [7:1] */
+
+/*
+ * R1638 (0x666) - LHPF1MIX Input 4 Source
+ */
+#define WM2200_LHPF1MIX_SRC4_MASK 0x007F /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_SHIFT 0 /* LHPF1MIX_SRC4 - [6:0] */
+#define WM2200_LHPF1MIX_SRC4_WIDTH 7 /* LHPF1MIX_SRC4 - [6:0] */
+
+/*
+ * R1639 (0x667) - LHPF1MIX Input 4 Volume
+ */
+#define WM2200_LHPF1MIX_VOL4_MASK 0x00FE /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_SHIFT 1 /* LHPF1MIX_VOL4 - [7:1] */
+#define WM2200_LHPF1MIX_VOL4_WIDTH 7 /* LHPF1MIX_VOL4 - [7:1] */
+
+/*
+ * R1640 (0x668) - LHPF2MIX Input 1 Source
+ */
+#define WM2200_LHPF2MIX_SRC1_MASK 0x007F /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_SHIFT 0 /* LHPF2MIX_SRC1 - [6:0] */
+#define WM2200_LHPF2MIX_SRC1_WIDTH 7 /* LHPF2MIX_SRC1 - [6:0] */
+
+/*
+ * R1641 (0x669) - LHPF2MIX Input 1 Volume
+ */
+#define WM2200_LHPF2MIX_VOL1_MASK 0x00FE /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_SHIFT 1 /* LHPF2MIX_VOL1 - [7:1] */
+#define WM2200_LHPF2MIX_VOL1_WIDTH 7 /* LHPF2MIX_VOL1 - [7:1] */
+
+/*
+ * R1642 (0x66A) - LHPF2MIX Input 2 Source
+ */
+#define WM2200_LHPF2MIX_SRC2_MASK 0x007F /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_SHIFT 0 /* LHPF2MIX_SRC2 - [6:0] */
+#define WM2200_LHPF2MIX_SRC2_WIDTH 7 /* LHPF2MIX_SRC2 - [6:0] */
+
+/*
+ * R1643 (0x66B) - LHPF2MIX Input 2 Volume
+ */
+#define WM2200_LHPF2MIX_VOL2_MASK 0x00FE /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_SHIFT 1 /* LHPF2MIX_VOL2 - [7:1] */
+#define WM2200_LHPF2MIX_VOL2_WIDTH 7 /* LHPF2MIX_VOL2 - [7:1] */
+
+/*
+ * R1644 (0x66C) - LHPF2MIX Input 3 Source
+ */
+#define WM2200_LHPF2MIX_SRC3_MASK 0x007F /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_SHIFT 0 /* LHPF2MIX_SRC3 - [6:0] */
+#define WM2200_LHPF2MIX_SRC3_WIDTH 7 /* LHPF2MIX_SRC3 - [6:0] */
+
+/*
+ * R1645 (0x66D) - LHPF2MIX Input 3 Volume
+ */
+#define WM2200_LHPF2MIX_VOL3_MASK 0x00FE /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_SHIFT 1 /* LHPF2MIX_VOL3 - [7:1] */
+#define WM2200_LHPF2MIX_VOL3_WIDTH 7 /* LHPF2MIX_VOL3 - [7:1] */
+
+/*
+ * R1646 (0x66E) - LHPF2MIX Input 4 Source
+ */
+#define WM2200_LHPF2MIX_SRC4_MASK 0x007F /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_SHIFT 0 /* LHPF2MIX_SRC4 - [6:0] */
+#define WM2200_LHPF2MIX_SRC4_WIDTH 7 /* LHPF2MIX_SRC4 - [6:0] */
+
+/*
+ * R1647 (0x66F) - LHPF2MIX Input 4 Volume
+ */
+#define WM2200_LHPF2MIX_VOL4_MASK 0x00FE /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_SHIFT 1 /* LHPF2MIX_VOL4 - [7:1] */
+#define WM2200_LHPF2MIX_VOL4_WIDTH 7 /* LHPF2MIX_VOL4 - [7:1] */
+
+/*
+ * R1648 (0x670) - DSP1LMIX Input 1 Source
+ */
+#define WM2200_DSP1LMIX_SRC1_MASK 0x007F /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_SHIFT 0 /* DSP1LMIX_SRC1 - [6:0] */
+#define WM2200_DSP1LMIX_SRC1_WIDTH 7 /* DSP1LMIX_SRC1 - [6:0] */
+
+/*
+ * R1649 (0x671) - DSP1LMIX Input 1 Volume
+ */
+#define WM2200_DSP1LMIX_VOL1_MASK 0x00FE /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_SHIFT 1 /* DSP1LMIX_VOL1 - [7:1] */
+#define WM2200_DSP1LMIX_VOL1_WIDTH 7 /* DSP1LMIX_VOL1 - [7:1] */
+
+/*
+ * R1650 (0x672) - DSP1LMIX Input 2 Source
+ */
+#define WM2200_DSP1LMIX_SRC2_MASK 0x007F /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_SHIFT 0 /* DSP1LMIX_SRC2 - [6:0] */
+#define WM2200_DSP1LMIX_SRC2_WIDTH 7 /* DSP1LMIX_SRC2 - [6:0] */
+
+/*
+ * R1651 (0x673) - DSP1LMIX Input 2 Volume
+ */
+#define WM2200_DSP1LMIX_VOL2_MASK 0x00FE /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_SHIFT 1 /* DSP1LMIX_VOL2 - [7:1] */
+#define WM2200_DSP1LMIX_VOL2_WIDTH 7 /* DSP1LMIX_VOL2 - [7:1] */
+
+/*
+ * R1652 (0x674) - DSP1LMIX Input 3 Source
+ */
+#define WM2200_DSP1LMIX_SRC3_MASK 0x007F /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_SHIFT 0 /* DSP1LMIX_SRC3 - [6:0] */
+#define WM2200_DSP1LMIX_SRC3_WIDTH 7 /* DSP1LMIX_SRC3 - [6:0] */
+
+/*
+ * R1653 (0x675) - DSP1LMIX Input 3 Volume
+ */
+#define WM2200_DSP1LMIX_VOL3_MASK 0x00FE /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_SHIFT 1 /* DSP1LMIX_VOL3 - [7:1] */
+#define WM2200_DSP1LMIX_VOL3_WIDTH 7 /* DSP1LMIX_VOL3 - [7:1] */
+
+/*
+ * R1654 (0x676) - DSP1LMIX Input 4 Source
+ */
+#define WM2200_DSP1LMIX_SRC4_MASK 0x007F /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_SHIFT 0 /* DSP1LMIX_SRC4 - [6:0] */
+#define WM2200_DSP1LMIX_SRC4_WIDTH 7 /* DSP1LMIX_SRC4 - [6:0] */
+
+/*
+ * R1655 (0x677) - DSP1LMIX Input 4 Volume
+ */
+#define WM2200_DSP1LMIX_VOL4_MASK 0x00FE /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_SHIFT 1 /* DSP1LMIX_VOL4 - [7:1] */
+#define WM2200_DSP1LMIX_VOL4_WIDTH 7 /* DSP1LMIX_VOL4 - [7:1] */
+
+/*
+ * R1656 (0x678) - DSP1RMIX Input 1 Source
+ */
+#define WM2200_DSP1RMIX_SRC1_MASK 0x007F /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_SHIFT 0 /* DSP1RMIX_SRC1 - [6:0] */
+#define WM2200_DSP1RMIX_SRC1_WIDTH 7 /* DSP1RMIX_SRC1 - [6:0] */
+
+/*
+ * R1657 (0x679) - DSP1RMIX Input 1 Volume
+ */
+#define WM2200_DSP1RMIX_VOL1_MASK 0x00FE /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_SHIFT 1 /* DSP1RMIX_VOL1 - [7:1] */
+#define WM2200_DSP1RMIX_VOL1_WIDTH 7 /* DSP1RMIX_VOL1 - [7:1] */
+
+/*
+ * R1658 (0x67A) - DSP1RMIX Input 2 Source
+ */
+#define WM2200_DSP1RMIX_SRC2_MASK 0x007F /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_SHIFT 0 /* DSP1RMIX_SRC2 - [6:0] */
+#define WM2200_DSP1RMIX_SRC2_WIDTH 7 /* DSP1RMIX_SRC2 - [6:0] */
+
+/*
+ * R1659 (0x67B) - DSP1RMIX Input 2 Volume
+ */
+#define WM2200_DSP1RMIX_VOL2_MASK 0x00FE /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_SHIFT 1 /* DSP1RMIX_VOL2 - [7:1] */
+#define WM2200_DSP1RMIX_VOL2_WIDTH 7 /* DSP1RMIX_VOL2 - [7:1] */
+
+/*
+ * R1660 (0x67C) - DSP1RMIX Input 3 Source
+ */
+#define WM2200_DSP1RMIX_SRC3_MASK 0x007F /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_SHIFT 0 /* DSP1RMIX_SRC3 - [6:0] */
+#define WM2200_DSP1RMIX_SRC3_WIDTH 7 /* DSP1RMIX_SRC3 - [6:0] */
+
+/*
+ * R1661 (0x67D) - DSP1RMIX Input 3 Volume
+ */
+#define WM2200_DSP1RMIX_VOL3_MASK 0x00FE /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_SHIFT 1 /* DSP1RMIX_VOL3 - [7:1] */
+#define WM2200_DSP1RMIX_VOL3_WIDTH 7 /* DSP1RMIX_VOL3 - [7:1] */
+
+/*
+ * R1662 (0x67E) - DSP1RMIX Input 4 Source
+ */
+#define WM2200_DSP1RMIX_SRC4_MASK 0x007F /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_SHIFT 0 /* DSP1RMIX_SRC4 - [6:0] */
+#define WM2200_DSP1RMIX_SRC4_WIDTH 7 /* DSP1RMIX_SRC4 - [6:0] */
+
+/*
+ * R1663 (0x67F) - DSP1RMIX Input 4 Volume
+ */
+#define WM2200_DSP1RMIX_VOL4_MASK 0x00FE /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_SHIFT 1 /* DSP1RMIX_VOL4 - [7:1] */
+#define WM2200_DSP1RMIX_VOL4_WIDTH 7 /* DSP1RMIX_VOL4 - [7:1] */
+
+/*
+ * R1664 (0x680) - DSP1AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX1MIX_SRC1_MASK 0x007F /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_SHIFT 0 /* DSP1AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX1MIX_SRC1_WIDTH 7 /* DSP1AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1665 (0x681) - DSP1AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX2MIX_SRC1_MASK 0x007F /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_SHIFT 0 /* DSP1AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX2MIX_SRC1_WIDTH 7 /* DSP1AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1666 (0x682) - DSP1AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX3MIX_SRC1_MASK 0x007F /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_SHIFT 0 /* DSP1AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX3MIX_SRC1_WIDTH 7 /* DSP1AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1667 (0x683) - DSP1AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX4MIX_SRC1_MASK 0x007F /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_SHIFT 0 /* DSP1AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX4MIX_SRC1_WIDTH 7 /* DSP1AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1668 (0x684) - DSP1AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX5MIX_SRC1_MASK 0x007F /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_SHIFT 0 /* DSP1AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX5MIX_SRC1_WIDTH 7 /* DSP1AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1669 (0x685) - DSP1AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP1AUX6MIX_SRC1_MASK 0x007F /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_SHIFT 0 /* DSP1AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP1AUX6MIX_SRC1_WIDTH 7 /* DSP1AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1670 (0x686) - DSP2LMIX Input 1 Source
+ */
+#define WM2200_DSP2LMIX_SRC1_MASK 0x007F /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_SHIFT 0 /* DSP2LMIX_SRC1 - [6:0] */
+#define WM2200_DSP2LMIX_SRC1_WIDTH 7 /* DSP2LMIX_SRC1 - [6:0] */
+
+/*
+ * R1671 (0x687) - DSP2LMIX Input 1 Volume
+ */
+#define WM2200_DSP2LMIX_VOL1_MASK 0x00FE /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_SHIFT 1 /* DSP2LMIX_VOL1 - [7:1] */
+#define WM2200_DSP2LMIX_VOL1_WIDTH 7 /* DSP2LMIX_VOL1 - [7:1] */
+
+/*
+ * R1672 (0x688) - DSP2LMIX Input 2 Source
+ */
+#define WM2200_DSP2LMIX_SRC2_MASK 0x007F /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_SHIFT 0 /* DSP2LMIX_SRC2 - [6:0] */
+#define WM2200_DSP2LMIX_SRC2_WIDTH 7 /* DSP2LMIX_SRC2 - [6:0] */
+
+/*
+ * R1673 (0x689) - DSP2LMIX Input 2 Volume
+ */
+#define WM2200_DSP2LMIX_VOL2_MASK 0x00FE /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_SHIFT 1 /* DSP2LMIX_VOL2 - [7:1] */
+#define WM2200_DSP2LMIX_VOL2_WIDTH 7 /* DSP2LMIX_VOL2 - [7:1] */
+
+/*
+ * R1674 (0x68A) - DSP2LMIX Input 3 Source
+ */
+#define WM2200_DSP2LMIX_SRC3_MASK 0x007F /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_SHIFT 0 /* DSP2LMIX_SRC3 - [6:0] */
+#define WM2200_DSP2LMIX_SRC3_WIDTH 7 /* DSP2LMIX_SRC3 - [6:0] */
+
+/*
+ * R1675 (0x68B) - DSP2LMIX Input 3 Volume
+ */
+#define WM2200_DSP2LMIX_VOL3_MASK 0x00FE /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_SHIFT 1 /* DSP2LMIX_VOL3 - [7:1] */
+#define WM2200_DSP2LMIX_VOL3_WIDTH 7 /* DSP2LMIX_VOL3 - [7:1] */
+
+/*
+ * R1676 (0x68C) - DSP2LMIX Input 4 Source
+ */
+#define WM2200_DSP2LMIX_SRC4_MASK 0x007F /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_SHIFT 0 /* DSP2LMIX_SRC4 - [6:0] */
+#define WM2200_DSP2LMIX_SRC4_WIDTH 7 /* DSP2LMIX_SRC4 - [6:0] */
+
+/*
+ * R1677 (0x68D) - DSP2LMIX Input 4 Volume
+ */
+#define WM2200_DSP2LMIX_VOL4_MASK 0x00FE /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_SHIFT 1 /* DSP2LMIX_VOL4 - [7:1] */
+#define WM2200_DSP2LMIX_VOL4_WIDTH 7 /* DSP2LMIX_VOL4 - [7:1] */
+
+/*
+ * R1678 (0x68E) - DSP2RMIX Input 1 Source
+ */
+#define WM2200_DSP2RMIX_SRC1_MASK 0x007F /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_SHIFT 0 /* DSP2RMIX_SRC1 - [6:0] */
+#define WM2200_DSP2RMIX_SRC1_WIDTH 7 /* DSP2RMIX_SRC1 - [6:0] */
+
+/*
+ * R1679 (0x68F) - DSP2RMIX Input 1 Volume
+ */
+#define WM2200_DSP2RMIX_VOL1_MASK 0x00FE /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_SHIFT 1 /* DSP2RMIX_VOL1 - [7:1] */
+#define WM2200_DSP2RMIX_VOL1_WIDTH 7 /* DSP2RMIX_VOL1 - [7:1] */
+
+/*
+ * R1680 (0x690) - DSP2RMIX Input 2 Source
+ */
+#define WM2200_DSP2RMIX_SRC2_MASK 0x007F /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_SHIFT 0 /* DSP2RMIX_SRC2 - [6:0] */
+#define WM2200_DSP2RMIX_SRC2_WIDTH 7 /* DSP2RMIX_SRC2 - [6:0] */
+
+/*
+ * R1681 (0x691) - DSP2RMIX Input 2 Volume
+ */
+#define WM2200_DSP2RMIX_VOL2_MASK 0x00FE /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_SHIFT 1 /* DSP2RMIX_VOL2 - [7:1] */
+#define WM2200_DSP2RMIX_VOL2_WIDTH 7 /* DSP2RMIX_VOL2 - [7:1] */
+
+/*
+ * R1682 (0x692) - DSP2RMIX Input 3 Source
+ */
+#define WM2200_DSP2RMIX_SRC3_MASK 0x007F /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_SHIFT 0 /* DSP2RMIX_SRC3 - [6:0] */
+#define WM2200_DSP2RMIX_SRC3_WIDTH 7 /* DSP2RMIX_SRC3 - [6:0] */
+
+/*
+ * R1683 (0x693) - DSP2RMIX Input 3 Volume
+ */
+#define WM2200_DSP2RMIX_VOL3_MASK 0x00FE /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_SHIFT 1 /* DSP2RMIX_VOL3 - [7:1] */
+#define WM2200_DSP2RMIX_VOL3_WIDTH 7 /* DSP2RMIX_VOL3 - [7:1] */
+
+/*
+ * R1684 (0x694) - DSP2RMIX Input 4 Source
+ */
+#define WM2200_DSP2RMIX_SRC4_MASK 0x007F /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_SHIFT 0 /* DSP2RMIX_SRC4 - [6:0] */
+#define WM2200_DSP2RMIX_SRC4_WIDTH 7 /* DSP2RMIX_SRC4 - [6:0] */
+
+/*
+ * R1685 (0x695) - DSP2RMIX Input 4 Volume
+ */
+#define WM2200_DSP2RMIX_VOL4_MASK 0x00FE /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_SHIFT 1 /* DSP2RMIX_VOL4 - [7:1] */
+#define WM2200_DSP2RMIX_VOL4_WIDTH 7 /* DSP2RMIX_VOL4 - [7:1] */
+
+/*
+ * R1686 (0x696) - DSP2AUX1MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX1MIX_SRC1_MASK 0x007F /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_SHIFT 0 /* DSP2AUX1MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX1MIX_SRC1_WIDTH 7 /* DSP2AUX1MIX_SRC1 - [6:0] */
+
+/*
+ * R1687 (0x697) - DSP2AUX2MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX2MIX_SRC1_MASK 0x007F /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_SHIFT 0 /* DSP2AUX2MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX2MIX_SRC1_WIDTH 7 /* DSP2AUX2MIX_SRC1 - [6:0] */
+
+/*
+ * R1688 (0x698) - DSP2AUX3MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX3MIX_SRC1_MASK 0x007F /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_SHIFT 0 /* DSP2AUX3MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX3MIX_SRC1_WIDTH 7 /* DSP2AUX3MIX_SRC1 - [6:0] */
+
+/*
+ * R1689 (0x699) - DSP2AUX4MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX4MIX_SRC1_MASK 0x007F /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_SHIFT 0 /* DSP2AUX4MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX4MIX_SRC1_WIDTH 7 /* DSP2AUX4MIX_SRC1 - [6:0] */
+
+/*
+ * R1690 (0x69A) - DSP2AUX5MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX5MIX_SRC1_MASK 0x007F /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_SHIFT 0 /* DSP2AUX5MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX5MIX_SRC1_WIDTH 7 /* DSP2AUX5MIX_SRC1 - [6:0] */
+
+/*
+ * R1691 (0x69B) - DSP2AUX6MIX Input 1 Source
+ */
+#define WM2200_DSP2AUX6MIX_SRC1_MASK 0x007F /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_SHIFT 0 /* DSP2AUX6MIX_SRC1 - [6:0] */
+#define WM2200_DSP2AUX6MIX_SRC1_WIDTH 7 /* DSP2AUX6MIX_SRC1 - [6:0] */
+
+/*
+ * R1792 (0x700) - GPIO CTRL 1
+ */
+#define WM2200_GP1_DIR 0x8000 /* GP1_DIR */
+#define WM2200_GP1_DIR_MASK 0x8000 /* GP1_DIR */
+#define WM2200_GP1_DIR_SHIFT 15 /* GP1_DIR */
+#define WM2200_GP1_DIR_WIDTH 1 /* GP1_DIR */
+#define WM2200_GP1_PU 0x4000 /* GP1_PU */
+#define WM2200_GP1_PU_MASK 0x4000 /* GP1_PU */
+#define WM2200_GP1_PU_SHIFT 14 /* GP1_PU */
+#define WM2200_GP1_PU_WIDTH 1 /* GP1_PU */
+#define WM2200_GP1_PD 0x2000 /* GP1_PD */
+#define WM2200_GP1_PD_MASK 0x2000 /* GP1_PD */
+#define WM2200_GP1_PD_SHIFT 13 /* GP1_PD */
+#define WM2200_GP1_PD_WIDTH 1 /* GP1_PD */
+#define WM2200_GP1_POL 0x0400 /* GP1_POL */
+#define WM2200_GP1_POL_MASK 0x0400 /* GP1_POL */
+#define WM2200_GP1_POL_SHIFT 10 /* GP1_POL */
+#define WM2200_GP1_POL_WIDTH 1 /* GP1_POL */
+#define WM2200_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */
+#define WM2200_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */
+#define WM2200_GP1_DB 0x0100 /* GP1_DB */
+#define WM2200_GP1_DB_MASK 0x0100 /* GP1_DB */
+#define WM2200_GP1_DB_SHIFT 8 /* GP1_DB */
+#define WM2200_GP1_DB_WIDTH 1 /* GP1_DB */
+#define WM2200_GP1_LVL 0x0040 /* GP1_LVL */
+#define WM2200_GP1_LVL_MASK 0x0040 /* GP1_LVL */
+#define WM2200_GP1_LVL_SHIFT 6 /* GP1_LVL */
+#define WM2200_GP1_LVL_WIDTH 1 /* GP1_LVL */
+#define WM2200_GP1_FN_MASK 0x003F /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_SHIFT 0 /* GP1_FN - [5:0] */
+#define WM2200_GP1_FN_WIDTH 6 /* GP1_FN - [5:0] */
+
+/*
+ * R1793 (0x701) - GPIO CTRL 2
+ */
+#define WM2200_GP2_DIR 0x8000 /* GP2_DIR */
+#define WM2200_GP2_DIR_MASK 0x8000 /* GP2_DIR */
+#define WM2200_GP2_DIR_SHIFT 15 /* GP2_DIR */
+#define WM2200_GP2_DIR_WIDTH 1 /* GP2_DIR */
+#define WM2200_GP2_PU 0x4000 /* GP2_PU */
+#define WM2200_GP2_PU_MASK 0x4000 /* GP2_PU */
+#define WM2200_GP2_PU_SHIFT 14 /* GP2_PU */
+#define WM2200_GP2_PU_WIDTH 1 /* GP2_PU */
+#define WM2200_GP2_PD 0x2000 /* GP2_PD */
+#define WM2200_GP2_PD_MASK 0x2000 /* GP2_PD */
+#define WM2200_GP2_PD_SHIFT 13 /* GP2_PD */
+#define WM2200_GP2_PD_WIDTH 1 /* GP2_PD */
+#define WM2200_GP2_POL 0x0400 /* GP2_POL */
+#define WM2200_GP2_POL_MASK 0x0400 /* GP2_POL */
+#define WM2200_GP2_POL_SHIFT 10 /* GP2_POL */
+#define WM2200_GP2_POL_WIDTH 1 /* GP2_POL */
+#define WM2200_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */
+#define WM2200_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */
+#define WM2200_GP2_DB 0x0100 /* GP2_DB */
+#define WM2200_GP2_DB_MASK 0x0100 /* GP2_DB */
+#define WM2200_GP2_DB_SHIFT 8 /* GP2_DB */
+#define WM2200_GP2_DB_WIDTH 1 /* GP2_DB */
+#define WM2200_GP2_LVL 0x0040 /* GP2_LVL */
+#define WM2200_GP2_LVL_MASK 0x0040 /* GP2_LVL */
+#define WM2200_GP2_LVL_SHIFT 6 /* GP2_LVL */
+#define WM2200_GP2_LVL_WIDTH 1 /* GP2_LVL */
+#define WM2200_GP2_FN_MASK 0x003F /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_SHIFT 0 /* GP2_FN - [5:0] */
+#define WM2200_GP2_FN_WIDTH 6 /* GP2_FN - [5:0] */
+
+/*
+ * R1794 (0x702) - GPIO CTRL 3
+ */
+#define WM2200_GP3_DIR 0x8000 /* GP3_DIR */
+#define WM2200_GP3_DIR_MASK 0x8000 /* GP3_DIR */
+#define WM2200_GP3_DIR_SHIFT 15 /* GP3_DIR */
+#define WM2200_GP3_DIR_WIDTH 1 /* GP3_DIR */
+#define WM2200_GP3_PU 0x4000 /* GP3_PU */
+#define WM2200_GP3_PU_MASK 0x4000 /* GP3_PU */
+#define WM2200_GP3_PU_SHIFT 14 /* GP3_PU */
+#define WM2200_GP3_PU_WIDTH 1 /* GP3_PU */
+#define WM2200_GP3_PD 0x2000 /* GP3_PD */
+#define WM2200_GP3_PD_MASK 0x2000 /* GP3_PD */
+#define WM2200_GP3_PD_SHIFT 13 /* GP3_PD */
+#define WM2200_GP3_PD_WIDTH 1 /* GP3_PD */
+#define WM2200_GP3_POL 0x0400 /* GP3_POL */
+#define WM2200_GP3_POL_MASK 0x0400 /* GP3_POL */
+#define WM2200_GP3_POL_SHIFT 10 /* GP3_POL */
+#define WM2200_GP3_POL_WIDTH 1 /* GP3_POL */
+#define WM2200_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */
+#define WM2200_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */
+#define WM2200_GP3_DB 0x0100 /* GP3_DB */
+#define WM2200_GP3_DB_MASK 0x0100 /* GP3_DB */
+#define WM2200_GP3_DB_SHIFT 8 /* GP3_DB */
+#define WM2200_GP3_DB_WIDTH 1 /* GP3_DB */
+#define WM2200_GP3_LVL 0x0040 /* GP3_LVL */
+#define WM2200_GP3_LVL_MASK 0x0040 /* GP3_LVL */
+#define WM2200_GP3_LVL_SHIFT 6 /* GP3_LVL */
+#define WM2200_GP3_LVL_WIDTH 1 /* GP3_LVL */
+#define WM2200_GP3_FN_MASK 0x003F /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_SHIFT 0 /* GP3_FN - [5:0] */
+#define WM2200_GP3_FN_WIDTH 6 /* GP3_FN - [5:0] */
+
+/*
+ * R1795 (0x703) - GPIO CTRL 4
+ */
+#define WM2200_GP4_DIR 0x8000 /* GP4_DIR */
+#define WM2200_GP4_DIR_MASK 0x8000 /* GP4_DIR */
+#define WM2200_GP4_DIR_SHIFT 15 /* GP4_DIR */
+#define WM2200_GP4_DIR_WIDTH 1 /* GP4_DIR */
+#define WM2200_GP4_PU 0x4000 /* GP4_PU */
+#define WM2200_GP4_PU_MASK 0x4000 /* GP4_PU */
+#define WM2200_GP4_PU_SHIFT 14 /* GP4_PU */
+#define WM2200_GP4_PU_WIDTH 1 /* GP4_PU */
+#define WM2200_GP4_PD 0x2000 /* GP4_PD */
+#define WM2200_GP4_PD_MASK 0x2000 /* GP4_PD */
+#define WM2200_GP4_PD_SHIFT 13 /* GP4_PD */
+#define WM2200_GP4_PD_WIDTH 1 /* GP4_PD */
+#define WM2200_GP4_POL 0x0400 /* GP4_POL */
+#define WM2200_GP4_POL_MASK 0x0400 /* GP4_POL */
+#define WM2200_GP4_POL_SHIFT 10 /* GP4_POL */
+#define WM2200_GP4_POL_WIDTH 1 /* GP4_POL */
+#define WM2200_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */
+#define WM2200_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */
+#define WM2200_GP4_DB 0x0100 /* GP4_DB */
+#define WM2200_GP4_DB_MASK 0x0100 /* GP4_DB */
+#define WM2200_GP4_DB_SHIFT 8 /* GP4_DB */
+#define WM2200_GP4_DB_WIDTH 1 /* GP4_DB */
+#define WM2200_GP4_LVL 0x0040 /* GP4_LVL */
+#define WM2200_GP4_LVL_MASK 0x0040 /* GP4_LVL */
+#define WM2200_GP4_LVL_SHIFT 6 /* GP4_LVL */
+#define WM2200_GP4_LVL_WIDTH 1 /* GP4_LVL */
+#define WM2200_GP4_FN_MASK 0x003F /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_SHIFT 0 /* GP4_FN - [5:0] */
+#define WM2200_GP4_FN_WIDTH 6 /* GP4_FN - [5:0] */
+
+/*
+ * R1799 (0x707) - ADPS1 IRQ0
+ */
+#define WM2200_DSP_IRQ1 0x0002 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_MASK 0x0002 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_SHIFT 1 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ1_WIDTH 1 /* DSP_IRQ1 */
+#define WM2200_DSP_IRQ0 0x0001 /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_MASK 0x0001 /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_SHIFT 0 /* DSP_IRQ0 */
+#define WM2200_DSP_IRQ0_WIDTH 1 /* DSP_IRQ0 */
+
+/*
+ * R1800 (0x708) - ADPS1 IRQ1
+ */
+#define WM2200_DSP_IRQ3 0x0002 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_MASK 0x0002 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_SHIFT 1 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ3_WIDTH 1 /* DSP_IRQ3 */
+#define WM2200_DSP_IRQ2 0x0001 /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_MASK 0x0001 /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_SHIFT 0 /* DSP_IRQ2 */
+#define WM2200_DSP_IRQ2_WIDTH 1 /* DSP_IRQ2 */
+
+/*
+ * R1801 (0x709) - Misc Pad Ctrl 1
+ */
+#define WM2200_LDO1ENA_PD 0x8000 /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_MASK 0x8000 /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_SHIFT 15 /* LDO1ENA_PD */
+#define WM2200_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */
+#define WM2200_MCLK2_PD 0x2000 /* MCLK2_PD */
+#define WM2200_MCLK2_PD_MASK 0x2000 /* MCLK2_PD */
+#define WM2200_MCLK2_PD_SHIFT 13 /* MCLK2_PD */
+#define WM2200_MCLK2_PD_WIDTH 1 /* MCLK2_PD */
+#define WM2200_MCLK1_PD 0x1000 /* MCLK1_PD */
+#define WM2200_MCLK1_PD_MASK 0x1000 /* MCLK1_PD */
+#define WM2200_MCLK1_PD_SHIFT 12 /* MCLK1_PD */
+#define WM2200_MCLK1_PD_WIDTH 1 /* MCLK1_PD */
+#define WM2200_DACLRCLK1_PU 0x0400 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_MASK 0x0400 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_SHIFT 10 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PU_WIDTH 1 /* DACLRCLK1_PU */
+#define WM2200_DACLRCLK1_PD 0x0200 /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_MASK 0x0200 /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_SHIFT 9 /* DACLRCLK1_PD */
+#define WM2200_DACLRCLK1_PD_WIDTH 1 /* DACLRCLK1_PD */
+#define WM2200_BCLK1_PU 0x0100 /* BCLK1_PU */
+#define WM2200_BCLK1_PU_MASK 0x0100 /* BCLK1_PU */
+#define WM2200_BCLK1_PU_SHIFT 8 /* BCLK1_PU */
+#define WM2200_BCLK1_PU_WIDTH 1 /* BCLK1_PU */
+#define WM2200_BCLK1_PD 0x0080 /* BCLK1_PD */
+#define WM2200_BCLK1_PD_MASK 0x0080 /* BCLK1_PD */
+#define WM2200_BCLK1_PD_SHIFT 7 /* BCLK1_PD */
+#define WM2200_BCLK1_PD_WIDTH 1 /* BCLK1_PD */
+#define WM2200_DACDAT1_PU 0x0040 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_MASK 0x0040 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_SHIFT 6 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PU_WIDTH 1 /* DACDAT1_PU */
+#define WM2200_DACDAT1_PD 0x0020 /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_MASK 0x0020 /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_SHIFT 5 /* DACDAT1_PD */
+#define WM2200_DACDAT1_PD_WIDTH 1 /* DACDAT1_PD */
+#define WM2200_DMICDAT3_PD 0x0010 /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_MASK 0x0010 /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_SHIFT 4 /* DMICDAT3_PD */
+#define WM2200_DMICDAT3_PD_WIDTH 1 /* DMICDAT3_PD */
+#define WM2200_DMICDAT2_PD 0x0008 /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_MASK 0x0008 /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_SHIFT 3 /* DMICDAT2_PD */
+#define WM2200_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */
+#define WM2200_DMICDAT1_PD 0x0004 /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_MASK 0x0004 /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_SHIFT 2 /* DMICDAT1_PD */
+#define WM2200_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */
+#define WM2200_RSTB_PU 0x0002 /* RSTB_PU */
+#define WM2200_RSTB_PU_MASK 0x0002 /* RSTB_PU */
+#define WM2200_RSTB_PU_SHIFT 1 /* RSTB_PU */
+#define WM2200_RSTB_PU_WIDTH 1 /* RSTB_PU */
+#define WM2200_ADDR_PD 0x0001 /* ADDR_PD */
+#define WM2200_ADDR_PD_MASK 0x0001 /* ADDR_PD */
+#define WM2200_ADDR_PD_SHIFT 0 /* ADDR_PD */
+#define WM2200_ADDR_PD_WIDTH 1 /* ADDR_PD */
+
+/*
+ * R2048 (0x800) - Interrupt Status 1
+ */
+#define WM2200_DSP_IRQ0_EINT 0x0080 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_MASK 0x0080 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_SHIFT 7 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ0_EINT_WIDTH 1 /* DSP_IRQ0_EINT */
+#define WM2200_DSP_IRQ1_EINT 0x0040 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_MASK 0x0040 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_SHIFT 6 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ1_EINT_WIDTH 1 /* DSP_IRQ1_EINT */
+#define WM2200_DSP_IRQ2_EINT 0x0020 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_MASK 0x0020 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_SHIFT 5 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ2_EINT_WIDTH 1 /* DSP_IRQ2_EINT */
+#define WM2200_DSP_IRQ3_EINT 0x0010 /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_MASK 0x0010 /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_SHIFT 4 /* DSP_IRQ3_EINT */
+#define WM2200_DSP_IRQ3_EINT_WIDTH 1 /* DSP_IRQ3_EINT */
+#define WM2200_GP4_EINT 0x0008 /* GP4_EINT */
+#define WM2200_GP4_EINT_MASK 0x0008 /* GP4_EINT */
+#define WM2200_GP4_EINT_SHIFT 3 /* GP4_EINT */
+#define WM2200_GP4_EINT_WIDTH 1 /* GP4_EINT */
+#define WM2200_GP3_EINT 0x0004 /* GP3_EINT */
+#define WM2200_GP3_EINT_MASK 0x0004 /* GP3_EINT */
+#define WM2200_GP3_EINT_SHIFT 2 /* GP3_EINT */
+#define WM2200_GP3_EINT_WIDTH 1 /* GP3_EINT */
+#define WM2200_GP2_EINT 0x0002 /* GP2_EINT */
+#define WM2200_GP2_EINT_MASK 0x0002 /* GP2_EINT */
+#define WM2200_GP2_EINT_SHIFT 1 /* GP2_EINT */
+#define WM2200_GP2_EINT_WIDTH 1 /* GP2_EINT */
+#define WM2200_GP1_EINT 0x0001 /* GP1_EINT */
+#define WM2200_GP1_EINT_MASK 0x0001 /* GP1_EINT */
+#define WM2200_GP1_EINT_SHIFT 0 /* GP1_EINT */
+#define WM2200_GP1_EINT_WIDTH 1 /* GP1_EINT */
+
+/*
+ * R2049 (0x801) - Interrupt Status 1 Mask
+ */
+#define WM2200_IM_DSP_IRQ0_EINT 0x0080 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_MASK 0x0080 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_SHIFT 7 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ0_EINT_WIDTH 1 /* IM_DSP_IRQ0_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT 0x0040 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_MASK 0x0040 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_SHIFT 6 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ1_EINT_WIDTH 1 /* IM_DSP_IRQ1_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT 0x0020 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_MASK 0x0020 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_SHIFT 5 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ2_EINT_WIDTH 1 /* IM_DSP_IRQ2_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT 0x0010 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_MASK 0x0010 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_SHIFT 4 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_DSP_IRQ3_EINT_WIDTH 1 /* IM_DSP_IRQ3_EINT */
+#define WM2200_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */
+#define WM2200_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */
+#define WM2200_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */
+#define WM2200_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */
+#define WM2200_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */
+#define WM2200_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */
+#define WM2200_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */
+#define WM2200_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */
+
+/*
+ * R2050 (0x802) - Interrupt Status 2
+ */
+#define WM2200_WSEQ_BUSY_EINT 0x0100 /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_MASK 0x0100 /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_SHIFT 8 /* WSEQ_BUSY_EINT */
+#define WM2200_WSEQ_BUSY_EINT_WIDTH 1 /* WSEQ_BUSY_EINT */
+#define WM2200_FLL_LOCK_EINT 0x0002 /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_MASK 0x0002 /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_SHIFT 1 /* FLL_LOCK_EINT */
+#define WM2200_FLL_LOCK_EINT_WIDTH 1 /* FLL_LOCK_EINT */
+#define WM2200_CLKGEN_EINT 0x0001 /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_MASK 0x0001 /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_SHIFT 0 /* CLKGEN_EINT */
+#define WM2200_CLKGEN_EINT_WIDTH 1 /* CLKGEN_EINT */
+
+/*
+ * R2051 (0x803) - Interrupt Raw Status 2
+ */
+#define WM2200_WSEQ_BUSY_STS 0x0100 /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_MASK 0x0100 /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_SHIFT 8 /* WSEQ_BUSY_STS */
+#define WM2200_WSEQ_BUSY_STS_WIDTH 1 /* WSEQ_BUSY_STS */
+#define WM2200_FLL_LOCK_STS 0x0002 /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_MASK 0x0002 /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_SHIFT 1 /* FLL_LOCK_STS */
+#define WM2200_FLL_LOCK_STS_WIDTH 1 /* FLL_LOCK_STS */
+#define WM2200_CLKGEN_STS 0x0001 /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_MASK 0x0001 /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_SHIFT 0 /* CLKGEN_STS */
+#define WM2200_CLKGEN_STS_WIDTH 1 /* CLKGEN_STS */
+
+/*
+ * R2052 (0x804) - Interrupt Status 2 Mask
+ */
+#define WM2200_IM_WSEQ_BUSY_EINT 0x0100 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_MASK 0x0100 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_SHIFT 8 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_WSEQ_BUSY_EINT_WIDTH 1 /* IM_WSEQ_BUSY_EINT */
+#define WM2200_IM_FLL_LOCK_EINT 0x0002 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_MASK 0x0002 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_SHIFT 1 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_FLL_LOCK_EINT_WIDTH 1 /* IM_FLL_LOCK_EINT */
+#define WM2200_IM_CLKGEN_EINT 0x0001 /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_MASK 0x0001 /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_SHIFT 0 /* IM_CLKGEN_EINT */
+#define WM2200_IM_CLKGEN_EINT_WIDTH 1 /* IM_CLKGEN_EINT */
+
+/*
+ * R2056 (0x808) - Interrupt Control
+ */
+#define WM2200_IM_IRQ 0x0001 /* IM_IRQ */
+#define WM2200_IM_IRQ_MASK 0x0001 /* IM_IRQ */
+#define WM2200_IM_IRQ_SHIFT 0 /* IM_IRQ */
+#define WM2200_IM_IRQ_WIDTH 1 /* IM_IRQ */
+
+/*
+ * R2304 (0x900) - EQL_1
+ */
+#define WM2200_EQL_B1_GAIN_MASK 0xF800 /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_SHIFT 11 /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B1_GAIN_WIDTH 5 /* EQL_B1_GAIN - [15:11] */
+#define WM2200_EQL_B2_GAIN_MASK 0x07C0 /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_SHIFT 6 /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B2_GAIN_WIDTH 5 /* EQL_B2_GAIN - [10:6] */
+#define WM2200_EQL_B3_GAIN_MASK 0x003E /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_SHIFT 1 /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_B3_GAIN_WIDTH 5 /* EQL_B3_GAIN - [5:1] */
+#define WM2200_EQL_ENA 0x0001 /* EQL_ENA */
+#define WM2200_EQL_ENA_MASK 0x0001 /* EQL_ENA */
+#define WM2200_EQL_ENA_SHIFT 0 /* EQL_ENA */
+#define WM2200_EQL_ENA_WIDTH 1 /* EQL_ENA */
+
+/*
+ * R2305 (0x901) - EQL_2
+ */
+#define WM2200_EQL_B4_GAIN_MASK 0xF800 /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_SHIFT 11 /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B4_GAIN_WIDTH 5 /* EQL_B4_GAIN - [15:11] */
+#define WM2200_EQL_B5_GAIN_MASK 0x07C0 /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_SHIFT 6 /* EQL_B5_GAIN - [10:6] */
+#define WM2200_EQL_B5_GAIN_WIDTH 5 /* EQL_B5_GAIN - [10:6] */
+
+/*
+ * R2306 (0x902) - EQL_3
+ */
+#define WM2200_EQL_B1_A_MASK 0xFFFF /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_SHIFT 0 /* EQL_B1_A - [15:0] */
+#define WM2200_EQL_B1_A_WIDTH 16 /* EQL_B1_A - [15:0] */
+
+/*
+ * R2307 (0x903) - EQL_4
+ */
+#define WM2200_EQL_B1_B_MASK 0xFFFF /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_SHIFT 0 /* EQL_B1_B - [15:0] */
+#define WM2200_EQL_B1_B_WIDTH 16 /* EQL_B1_B - [15:0] */
+
+/*
+ * R2308 (0x904) - EQL_5
+ */
+#define WM2200_EQL_B1_PG_MASK 0xFFFF /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_SHIFT 0 /* EQL_B1_PG - [15:0] */
+#define WM2200_EQL_B1_PG_WIDTH 16 /* EQL_B1_PG - [15:0] */
+
+/*
+ * R2309 (0x905) - EQL_6
+ */
+#define WM2200_EQL_B2_A_MASK 0xFFFF /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_SHIFT 0 /* EQL_B2_A - [15:0] */
+#define WM2200_EQL_B2_A_WIDTH 16 /* EQL_B2_A - [15:0] */
+
+/*
+ * R2310 (0x906) - EQL_7
+ */
+#define WM2200_EQL_B2_B_MASK 0xFFFF /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_SHIFT 0 /* EQL_B2_B - [15:0] */
+#define WM2200_EQL_B2_B_WIDTH 16 /* EQL_B2_B - [15:0] */
+
+/*
+ * R2311 (0x907) - EQL_8
+ */
+#define WM2200_EQL_B2_C_MASK 0xFFFF /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_SHIFT 0 /* EQL_B2_C - [15:0] */
+#define WM2200_EQL_B2_C_WIDTH 16 /* EQL_B2_C - [15:0] */
+
+/*
+ * R2312 (0x908) - EQL_9
+ */
+#define WM2200_EQL_B2_PG_MASK 0xFFFF /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_SHIFT 0 /* EQL_B2_PG - [15:0] */
+#define WM2200_EQL_B2_PG_WIDTH 16 /* EQL_B2_PG - [15:0] */
+
+/*
+ * R2313 (0x909) - EQL_10
+ */
+#define WM2200_EQL_B3_A_MASK 0xFFFF /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_SHIFT 0 /* EQL_B3_A - [15:0] */
+#define WM2200_EQL_B3_A_WIDTH 16 /* EQL_B3_A - [15:0] */
+
+/*
+ * R2314 (0x90A) - EQL_11
+ */
+#define WM2200_EQL_B3_B_MASK 0xFFFF /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_SHIFT 0 /* EQL_B3_B - [15:0] */
+#define WM2200_EQL_B3_B_WIDTH 16 /* EQL_B3_B - [15:0] */
+
+/*
+ * R2315 (0x90B) - EQL_12
+ */
+#define WM2200_EQL_B3_C_MASK 0xFFFF /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_SHIFT 0 /* EQL_B3_C - [15:0] */
+#define WM2200_EQL_B3_C_WIDTH 16 /* EQL_B3_C - [15:0] */
+
+/*
+ * R2316 (0x90C) - EQL_13
+ */
+#define WM2200_EQL_B3_PG_MASK 0xFFFF /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_SHIFT 0 /* EQL_B3_PG - [15:0] */
+#define WM2200_EQL_B3_PG_WIDTH 16 /* EQL_B3_PG - [15:0] */
+
+/*
+ * R2317 (0x90D) - EQL_14
+ */
+#define WM2200_EQL_B4_A_MASK 0xFFFF /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_SHIFT 0 /* EQL_B4_A - [15:0] */
+#define WM2200_EQL_B4_A_WIDTH 16 /* EQL_B4_A - [15:0] */
+
+/*
+ * R2318 (0x90E) - EQL_15
+ */
+#define WM2200_EQL_B4_B_MASK 0xFFFF /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_SHIFT 0 /* EQL_B4_B - [15:0] */
+#define WM2200_EQL_B4_B_WIDTH 16 /* EQL_B4_B - [15:0] */
+
+/*
+ * R2319 (0x90F) - EQL_16
+ */
+#define WM2200_EQL_B4_C_MASK 0xFFFF /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_SHIFT 0 /* EQL_B4_C - [15:0] */
+#define WM2200_EQL_B4_C_WIDTH 16 /* EQL_B4_C - [15:0] */
+
+/*
+ * R2320 (0x910) - EQL_17
+ */
+#define WM2200_EQL_B4_PG_MASK 0xFFFF /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_SHIFT 0 /* EQL_B4_PG - [15:0] */
+#define WM2200_EQL_B4_PG_WIDTH 16 /* EQL_B4_PG - [15:0] */
+
+/*
+ * R2321 (0x911) - EQL_18
+ */
+#define WM2200_EQL_B5_A_MASK 0xFFFF /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_SHIFT 0 /* EQL_B5_A - [15:0] */
+#define WM2200_EQL_B5_A_WIDTH 16 /* EQL_B5_A - [15:0] */
+
+/*
+ * R2322 (0x912) - EQL_19
+ */
+#define WM2200_EQL_B5_B_MASK 0xFFFF /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_SHIFT 0 /* EQL_B5_B - [15:0] */
+#define WM2200_EQL_B5_B_WIDTH 16 /* EQL_B5_B - [15:0] */
+
+/*
+ * R2323 (0x913) - EQL_20
+ */
+#define WM2200_EQL_B5_PG_MASK 0xFFFF /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_SHIFT 0 /* EQL_B5_PG - [15:0] */
+#define WM2200_EQL_B5_PG_WIDTH 16 /* EQL_B5_PG - [15:0] */
+
+/*
+ * R2326 (0x916) - EQR_1
+ */
+#define WM2200_EQR_B1_GAIN_MASK 0xF800 /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_SHIFT 11 /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B1_GAIN_WIDTH 5 /* EQR_B1_GAIN - [15:11] */
+#define WM2200_EQR_B2_GAIN_MASK 0x07C0 /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_SHIFT 6 /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B2_GAIN_WIDTH 5 /* EQR_B2_GAIN - [10:6] */
+#define WM2200_EQR_B3_GAIN_MASK 0x003E /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_SHIFT 1 /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_B3_GAIN_WIDTH 5 /* EQR_B3_GAIN - [5:1] */
+#define WM2200_EQR_ENA 0x0001 /* EQR_ENA */
+#define WM2200_EQR_ENA_MASK 0x0001 /* EQR_ENA */
+#define WM2200_EQR_ENA_SHIFT 0 /* EQR_ENA */
+#define WM2200_EQR_ENA_WIDTH 1 /* EQR_ENA */
+
+/*
+ * R2327 (0x917) - EQR_2
+ */
+#define WM2200_EQR_B4_GAIN_MASK 0xF800 /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_SHIFT 11 /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B4_GAIN_WIDTH 5 /* EQR_B4_GAIN - [15:11] */
+#define WM2200_EQR_B5_GAIN_MASK 0x07C0 /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_SHIFT 6 /* EQR_B5_GAIN - [10:6] */
+#define WM2200_EQR_B5_GAIN_WIDTH 5 /* EQR_B5_GAIN - [10:6] */
+
+/*
+ * R2328 (0x918) - EQR_3
+ */
+#define WM2200_EQR_B1_A_MASK 0xFFFF /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_SHIFT 0 /* EQR_B1_A - [15:0] */
+#define WM2200_EQR_B1_A_WIDTH 16 /* EQR_B1_A - [15:0] */
+
+/*
+ * R2329 (0x919) - EQR_4
+ */
+#define WM2200_EQR_B1_B_MASK 0xFFFF /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_SHIFT 0 /* EQR_B1_B - [15:0] */
+#define WM2200_EQR_B1_B_WIDTH 16 /* EQR_B1_B - [15:0] */
+
+/*
+ * R2330 (0x91A) - EQR_5
+ */
+#define WM2200_EQR_B1_PG_MASK 0xFFFF /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_SHIFT 0 /* EQR_B1_PG - [15:0] */
+#define WM2200_EQR_B1_PG_WIDTH 16 /* EQR_B1_PG - [15:0] */
+
+/*
+ * R2331 (0x91B) - EQR_6
+ */
+#define WM2200_EQR_B2_A_MASK 0xFFFF /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_SHIFT 0 /* EQR_B2_A - [15:0] */
+#define WM2200_EQR_B2_A_WIDTH 16 /* EQR_B2_A - [15:0] */
+
+/*
+ * R2332 (0x91C) - EQR_7
+ */
+#define WM2200_EQR_B2_B_MASK 0xFFFF /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_SHIFT 0 /* EQR_B2_B - [15:0] */
+#define WM2200_EQR_B2_B_WIDTH 16 /* EQR_B2_B - [15:0] */
+
+/*
+ * R2333 (0x91D) - EQR_8
+ */
+#define WM2200_EQR_B2_C_MASK 0xFFFF /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_SHIFT 0 /* EQR_B2_C - [15:0] */
+#define WM2200_EQR_B2_C_WIDTH 16 /* EQR_B2_C - [15:0] */
+
+/*
+ * R2334 (0x91E) - EQR_9
+ */
+#define WM2200_EQR_B2_PG_MASK 0xFFFF /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_SHIFT 0 /* EQR_B2_PG - [15:0] */
+#define WM2200_EQR_B2_PG_WIDTH 16 /* EQR_B2_PG - [15:0] */
+
+/*
+ * R2335 (0x91F) - EQR_10
+ */
+#define WM2200_EQR_B3_A_MASK 0xFFFF /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_SHIFT 0 /* EQR_B3_A - [15:0] */
+#define WM2200_EQR_B3_A_WIDTH 16 /* EQR_B3_A - [15:0] */
+
+/*
+ * R2336 (0x920) - EQR_11
+ */
+#define WM2200_EQR_B3_B_MASK 0xFFFF /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_SHIFT 0 /* EQR_B3_B - [15:0] */
+#define WM2200_EQR_B3_B_WIDTH 16 /* EQR_B3_B - [15:0] */
+
+/*
+ * R2337 (0x921) - EQR_12
+ */
+#define WM2200_EQR_B3_C_MASK 0xFFFF /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_SHIFT 0 /* EQR_B3_C - [15:0] */
+#define WM2200_EQR_B3_C_WIDTH 16 /* EQR_B3_C - [15:0] */
+
+/*
+ * R2338 (0x922) - EQR_13
+ */
+#define WM2200_EQR_B3_PG_MASK 0xFFFF /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_SHIFT 0 /* EQR_B3_PG - [15:0] */
+#define WM2200_EQR_B3_PG_WIDTH 16 /* EQR_B3_PG - [15:0] */
+
+/*
+ * R2339 (0x923) - EQR_14
+ */
+#define WM2200_EQR_B4_A_MASK 0xFFFF /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_SHIFT 0 /* EQR_B4_A - [15:0] */
+#define WM2200_EQR_B4_A_WIDTH 16 /* EQR_B4_A - [15:0] */
+
+/*
+ * R2340 (0x924) - EQR_15
+ */
+#define WM2200_EQR_B4_B_MASK 0xFFFF /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_SHIFT 0 /* EQR_B4_B - [15:0] */
+#define WM2200_EQR_B4_B_WIDTH 16 /* EQR_B4_B - [15:0] */
+
+/*
+ * R2341 (0x925) - EQR_16
+ */
+#define WM2200_EQR_B4_C_MASK 0xFFFF /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_SHIFT 0 /* EQR_B4_C - [15:0] */
+#define WM2200_EQR_B4_C_WIDTH 16 /* EQR_B4_C - [15:0] */
+
+/*
+ * R2342 (0x926) - EQR_17
+ */
+#define WM2200_EQR_B4_PG_MASK 0xFFFF /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_SHIFT 0 /* EQR_B4_PG - [15:0] */
+#define WM2200_EQR_B4_PG_WIDTH 16 /* EQR_B4_PG - [15:0] */
+
+/*
+ * R2343 (0x927) - EQR_18
+ */
+#define WM2200_EQR_B5_A_MASK 0xFFFF /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_SHIFT 0 /* EQR_B5_A - [15:0] */
+#define WM2200_EQR_B5_A_WIDTH 16 /* EQR_B5_A - [15:0] */
+
+/*
+ * R2344 (0x928) - EQR_19
+ */
+#define WM2200_EQR_B5_B_MASK 0xFFFF /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_SHIFT 0 /* EQR_B5_B - [15:0] */
+#define WM2200_EQR_B5_B_WIDTH 16 /* EQR_B5_B - [15:0] */
+
+/*
+ * R2345 (0x929) - EQR_20
+ */
+#define WM2200_EQR_B5_PG_MASK 0xFFFF /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_SHIFT 0 /* EQR_B5_PG - [15:0] */
+#define WM2200_EQR_B5_PG_WIDTH 16 /* EQR_B5_PG - [15:0] */
+
+/*
+ * R2366 (0x93E) - HPLPF1_1
+ */
+#define WM2200_LHPF1_MODE 0x0002 /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_MASK 0x0002 /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_SHIFT 1 /* LHPF1_MODE */
+#define WM2200_LHPF1_MODE_WIDTH 1 /* LHPF1_MODE */
+#define WM2200_LHPF1_ENA 0x0001 /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_MASK 0x0001 /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_SHIFT 0 /* LHPF1_ENA */
+#define WM2200_LHPF1_ENA_WIDTH 1 /* LHPF1_ENA */
+
+/*
+ * R2367 (0x93F) - HPLPF1_2
+ */
+#define WM2200_LHPF1_COEFF_MASK 0xFFFF /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_SHIFT 0 /* LHPF1_COEFF - [15:0] */
+#define WM2200_LHPF1_COEFF_WIDTH 16 /* LHPF1_COEFF - [15:0] */
+
+/*
+ * R2370 (0x942) - HPLPF2_1
+ */
+#define WM2200_LHPF2_MODE 0x0002 /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_MASK 0x0002 /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_SHIFT 1 /* LHPF2_MODE */
+#define WM2200_LHPF2_MODE_WIDTH 1 /* LHPF2_MODE */
+#define WM2200_LHPF2_ENA 0x0001 /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_MASK 0x0001 /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_SHIFT 0 /* LHPF2_ENA */
+#define WM2200_LHPF2_ENA_WIDTH 1 /* LHPF2_ENA */
+
+/*
+ * R2371 (0x943) - HPLPF2_2
+ */
+#define WM2200_LHPF2_COEFF_MASK 0xFFFF /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_SHIFT 0 /* LHPF2_COEFF - [15:0] */
+#define WM2200_LHPF2_COEFF_WIDTH 16 /* LHPF2_COEFF - [15:0] */
+
+/*
+ * R2560 (0xA00) - DSP1 Control 1
+ */
+#define WM2200_DSP1_RW_SEQUENCE_ENA 0x0001 /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_MASK 0x0001 /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_SHIFT 0 /* DSP1_RW_SEQUENCE_ENA */
+#define WM2200_DSP1_RW_SEQUENCE_ENA_WIDTH 1 /* DSP1_RW_SEQUENCE_ENA */
+
+/*
+ * R2562 (0xA02) - DSP1 Control 2
+ */
+#define WM2200_DSP1_PAGE_BASE_PM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_SHIFT 8 /* DSP1_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_PM_0_WIDTH 8 /* DSP1_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2563 (0xA03) - DSP1 Control 3
+ */
+#define WM2200_DSP1_PAGE_BASE_DM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_SHIFT 8 /* DSP1_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_DM_0_WIDTH 8 /* DSP1_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2564 (0xA04) - DSP1 Control 4
+ */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_MASK 0xFF00 /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_SHIFT 8 /* DSP1_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP1_PAGE_BASE_ZM_0_WIDTH 8 /* DSP1_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2566 (0xA06) - DSP1 Control 5
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_0_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2567 (0xA07) - DSP1 Control 6
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_1_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2568 (0xA08) - DSP1 Control 7
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_2_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2569 (0xA09) - DSP1 Control 8
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_3_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2570 (0xA0A) - DSP1 Control 9
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_4_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2571 (0xA0B) - DSP1 Control 10
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_5_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2572 (0xA0C) - DSP1 Control 11
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_6_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2573 (0xA0D) - DSP1 Control 12
+ */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_SHIFT 0 /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_WDMA_BUFFER_7_WIDTH 14 /* DSP1_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2575 (0xA0F) - DSP1 Control 13
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_0_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2576 (0xA10) - DSP1 Control 14
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_1_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2577 (0xA11) - DSP1 Control 15
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_2_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2578 (0xA12) - DSP1 Control 16
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_3_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2579 (0xA13) - DSP1 Control 17
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_4_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2580 (0xA14) - DSP1 Control 18
+ */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_SHIFT 0 /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP1_START_ADDRESS_RDMA_BUFFER_5_WIDTH 14 /* DSP1_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2582 (0xA16) - DSP1 Control 19
+ */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP1_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP1_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2583 (0xA17) - DSP1 Control 20
+ */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_MASK 0x00FF /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP1_WDMA_CHANNEL_ENABLE_WIDTH 8 /* DSP1_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2584 (0xA18) - DSP1 Control 21
+ */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_MASK 0x003F /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP1_RDMA_CHANNEL_ENABLE_WIDTH 6 /* DSP1_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2586 (0xA1A) - DSP1 Control 22
+ */
+#define WM2200_DSP1_DM_SIZE_MASK 0xFFFF /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_SHIFT 0 /* DSP1_DM_SIZE - [15:0] */
+#define WM2200_DSP1_DM_SIZE_WIDTH 16 /* DSP1_DM_SIZE - [15:0] */
+
+/*
+ * R2587 (0xA1B) - DSP1 Control 23
+ */
+#define WM2200_DSP1_PM_SIZE_MASK 0xFFFF /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_SHIFT 0 /* DSP1_PM_SIZE - [15:0] */
+#define WM2200_DSP1_PM_SIZE_WIDTH 16 /* DSP1_PM_SIZE - [15:0] */
+
+/*
+ * R2588 (0xA1C) - DSP1 Control 24
+ */
+#define WM2200_DSP1_ZM_SIZE_MASK 0xFFFF /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_SHIFT 0 /* DSP1_ZM_SIZE - [15:0] */
+#define WM2200_DSP1_ZM_SIZE_WIDTH 16 /* DSP1_ZM_SIZE - [15:0] */
+
+/*
+ * R2590 (0xA1E) - DSP1 Control 25
+ */
+#define WM2200_DSP1_PING_FULL 0x8000 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_MASK 0x8000 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_SHIFT 15 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PING_FULL_WIDTH 1 /* DSP1_PING_FULL */
+#define WM2200_DSP1_PONG_FULL 0x4000 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_MASK 0x4000 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_SHIFT 14 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_PONG_FULL_WIDTH 1 /* DSP1_PONG_FULL */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_MASK 0x00FF /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_SHIFT 0 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP1_WDMA_ACTIVE_CHANNELS_WIDTH 8 /* DSP1_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2592 (0xA20) - DSP1 Control 26
+ */
+#define WM2200_DSP1_SCRATCH_0_MASK 0xFFFF /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_SHIFT 0 /* DSP1_SCRATCH_0 - [15:0] */
+#define WM2200_DSP1_SCRATCH_0_WIDTH 16 /* DSP1_SCRATCH_0 - [15:0] */
+
+/*
+ * R2593 (0xA21) - DSP1 Control 27
+ */
+#define WM2200_DSP1_SCRATCH_1_MASK 0xFFFF /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_SHIFT 0 /* DSP1_SCRATCH_1 - [15:0] */
+#define WM2200_DSP1_SCRATCH_1_WIDTH 16 /* DSP1_SCRATCH_1 - [15:0] */
+
+/*
+ * R2594 (0xA22) - DSP1 Control 28
+ */
+#define WM2200_DSP1_SCRATCH_2_MASK 0xFFFF /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_SHIFT 0 /* DSP1_SCRATCH_2 - [15:0] */
+#define WM2200_DSP1_SCRATCH_2_WIDTH 16 /* DSP1_SCRATCH_2 - [15:0] */
+
+/*
+ * R2595 (0xA23) - DSP1 Control 29
+ */
+#define WM2200_DSP1_SCRATCH_3_MASK 0xFFFF /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_SHIFT 0 /* DSP1_SCRATCH_3 - [15:0] */
+#define WM2200_DSP1_SCRATCH_3_WIDTH 16 /* DSP1_SCRATCH_3 - [15:0] */
+
+/*
+ * R2596 (0xA24) - DSP1 Control 30
+ */
+#define WM2200_DSP1_DBG_CLK_ENA 0x0008 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_MASK 0x0008 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_SHIFT 3 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_DBG_CLK_ENA_WIDTH 1 /* DSP1_DBG_CLK_ENA */
+#define WM2200_DSP1_SYS_ENA 0x0004 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_MASK 0x0004 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_SHIFT 2 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_SYS_ENA_WIDTH 1 /* DSP1_SYS_ENA */
+#define WM2200_DSP1_CORE_ENA 0x0002 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_MASK 0x0002 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_SHIFT 1 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_CORE_ENA_WIDTH 1 /* DSP1_CORE_ENA */
+#define WM2200_DSP1_START 0x0001 /* DSP1_START */
+#define WM2200_DSP1_START_MASK 0x0001 /* DSP1_START */
+#define WM2200_DSP1_START_SHIFT 0 /* DSP1_START */
+#define WM2200_DSP1_START_WIDTH 1 /* DSP1_START */
+
+/*
+ * R2598 (0xA26) - DSP1 Control 31
+ */
+#define WM2200_DSP1_CLK_RATE_MASK 0x0018 /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_SHIFT 3 /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_RATE_WIDTH 2 /* DSP1_CLK_RATE - [4:3] */
+#define WM2200_DSP1_CLK_AVAIL 0x0004 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_MASK 0x0004 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_SHIFT 2 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_AVAIL_WIDTH 1 /* DSP1_CLK_AVAIL */
+#define WM2200_DSP1_CLK_REQ_MASK 0x0003 /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_SHIFT 0 /* DSP1_CLK_REQ - [1:0] */
+#define WM2200_DSP1_CLK_REQ_WIDTH 2 /* DSP1_CLK_REQ - [1:0] */
+
+/*
+ * R2816 (0xB00) - DSP2 Control 1
+ */
+#define WM2200_DSP2_RW_SEQUENCE_ENA 0x0001 /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_MASK 0x0001 /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_SHIFT 0 /* DSP2_RW_SEQUENCE_ENA */
+#define WM2200_DSP2_RW_SEQUENCE_ENA_WIDTH 1 /* DSP2_RW_SEQUENCE_ENA */
+
+/*
+ * R2818 (0xB02) - DSP2 Control 2
+ */
+#define WM2200_DSP2_PAGE_BASE_PM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_SHIFT 8 /* DSP2_PAGE_BASE_PM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_PM_0_WIDTH 8 /* DSP2_PAGE_BASE_PM - [15:8] */
+
+/*
+ * R2819 (0xB03) - DSP2 Control 3
+ */
+#define WM2200_DSP2_PAGE_BASE_DM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_SHIFT 8 /* DSP2_PAGE_BASE_DM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_DM_0_WIDTH 8 /* DSP2_PAGE_BASE_DM - [15:8] */
+
+/*
+ * R2820 (0xB04) - DSP2 Control 4
+ */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_MASK 0xFF00 /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_SHIFT 8 /* DSP2_PAGE_BASE_ZM - [15:8] */
+#define WM2200_DSP2_PAGE_BASE_ZM_0_WIDTH 8 /* DSP2_PAGE_BASE_ZM - [15:8] */
+
+/*
+ * R2822 (0xB06) - DSP2 Control 5
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_0_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2823 (0xB07) - DSP2 Control 6
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_1_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2824 (0xB08) - DSP2 Control 7
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_2_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2825 (0xB09) - DSP2 Control 8
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_3_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2826 (0xB0A) - DSP2 Control 9
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_4_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2827 (0xB0B) - DSP2 Control 10
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_5_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2828 (0xB0C) - DSP2 Control 11
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_6_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_6 - [13:0] */
+
+/*
+ * R2829 (0xB0D) - DSP2 Control 12
+ */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_MASK 0x3FFF /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_SHIFT 0 /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_WDMA_BUFFER_7_WIDTH 14 /* DSP2_START_ADDRESS_WDMA_BUFFER_7 - [13:0] */
+
+/*
+ * R2831 (0xB0F) - DSP2 Control 13
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_0_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_0 - [13:0] */
+
+/*
+ * R2832 (0xB10) - DSP2 Control 14
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_1_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_1 - [13:0] */
+
+/*
+ * R2833 (0xB11) - DSP2 Control 15
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_2_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_2 - [13:0] */
+
+/*
+ * R2834 (0xB12) - DSP2 Control 16
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_3_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_3 - [13:0] */
+
+/*
+ * R2835 (0xB13) - DSP2 Control 17
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_4_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_4 - [13:0] */
+
+/*
+ * R2836 (0xB14) - DSP2 Control 18
+ */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_MASK 0x3FFF /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_SHIFT 0 /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+#define WM2200_DSP2_START_ADDRESS_RDMA_BUFFER_5_WIDTH 14 /* DSP2_START_ADDRESS_RDMA_BUFFER_5 - [13:0] */
+
+/*
+ * R2838 (0xB16) - DSP2 Control 19
+ */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_MASK 0x00FF /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_SHIFT 0 /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+#define WM2200_DSP2_WDMA_BUFFER_LENGTH_WIDTH 8 /* DSP2_WDMA_BUFFER_LENGTH - [7:0] */
+
+/*
+ * R2839 (0xB17) - DSP2 Control 20
+ */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_MASK 0x00FF /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+#define WM2200_DSP2_WDMA_CHANNEL_ENABLE_WIDTH 8 /* DSP2_WDMA_CHANNEL_ENABLE - [7:0] */
+
+/*
+ * R2840 (0xB18) - DSP2 Control 21
+ */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_MASK 0x003F /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_SHIFT 0 /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+#define WM2200_DSP2_RDMA_CHANNEL_ENABLE_WIDTH 6 /* DSP2_RDMA_CHANNEL_ENABLE - [5:0] */
+
+/*
+ * R2842 (0xB1A) - DSP2 Control 22
+ */
+#define WM2200_DSP2_DM_SIZE_MASK 0xFFFF /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_SHIFT 0 /* DSP2_DM_SIZE - [15:0] */
+#define WM2200_DSP2_DM_SIZE_WIDTH 16 /* DSP2_DM_SIZE - [15:0] */
+
+/*
+ * R2843 (0xB1B) - DSP2 Control 23
+ */
+#define WM2200_DSP2_PM_SIZE_MASK 0xFFFF /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_SHIFT 0 /* DSP2_PM_SIZE - [15:0] */
+#define WM2200_DSP2_PM_SIZE_WIDTH 16 /* DSP2_PM_SIZE - [15:0] */
+
+/*
+ * R2844 (0xB1C) - DSP2 Control 24
+ */
+#define WM2200_DSP2_ZM_SIZE_MASK 0xFFFF /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_SHIFT 0 /* DSP2_ZM_SIZE - [15:0] */
+#define WM2200_DSP2_ZM_SIZE_WIDTH 16 /* DSP2_ZM_SIZE - [15:0] */
+
+/*
+ * R2846 (0xB1E) - DSP2 Control 25
+ */
+#define WM2200_DSP2_PING_FULL 0x8000 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_MASK 0x8000 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_SHIFT 15 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PING_FULL_WIDTH 1 /* DSP2_PING_FULL */
+#define WM2200_DSP2_PONG_FULL 0x4000 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_MASK 0x4000 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_SHIFT 14 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_PONG_FULL_WIDTH 1 /* DSP2_PONG_FULL */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_MASK 0x00FF /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_SHIFT 0 /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+#define WM2200_DSP2_WDMA_ACTIVE_CHANNELS_WIDTH 8 /* DSP2_WDMA_ACTIVE_CHANNELS - [7:0] */
+
+/*
+ * R2848 (0xB20) - DSP2 Control 26
+ */
+#define WM2200_DSP2_SCRATCH_0_MASK 0xFFFF /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_SHIFT 0 /* DSP2_SCRATCH_0 - [15:0] */
+#define WM2200_DSP2_SCRATCH_0_WIDTH 16 /* DSP2_SCRATCH_0 - [15:0] */
+
+/*
+ * R2849 (0xB21) - DSP2 Control 27
+ */
+#define WM2200_DSP2_SCRATCH_1_MASK 0xFFFF /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_SHIFT 0 /* DSP2_SCRATCH_1 - [15:0] */
+#define WM2200_DSP2_SCRATCH_1_WIDTH 16 /* DSP2_SCRATCH_1 - [15:0] */
+
+/*
+ * R2850 (0xB22) - DSP2 Control 28
+ */
+#define WM2200_DSP2_SCRATCH_2_MASK 0xFFFF /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_SHIFT 0 /* DSP2_SCRATCH_2 - [15:0] */
+#define WM2200_DSP2_SCRATCH_2_WIDTH 16 /* DSP2_SCRATCH_2 - [15:0] */
+
+/*
+ * R2851 (0xB23) - DSP2 Control 29
+ */
+#define WM2200_DSP2_SCRATCH_3_MASK 0xFFFF /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_SHIFT 0 /* DSP2_SCRATCH_3 - [15:0] */
+#define WM2200_DSP2_SCRATCH_3_WIDTH 16 /* DSP2_SCRATCH_3 - [15:0] */
+
+/*
+ * R2852 (0xB24) - DSP2 Control 30
+ */
+#define WM2200_DSP2_DBG_CLK_ENA 0x0008 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_MASK 0x0008 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_SHIFT 3 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_DBG_CLK_ENA_WIDTH 1 /* DSP2_DBG_CLK_ENA */
+#define WM2200_DSP2_SYS_ENA 0x0004 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_MASK 0x0004 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_SHIFT 2 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_SYS_ENA_WIDTH 1 /* DSP2_SYS_ENA */
+#define WM2200_DSP2_CORE_ENA 0x0002 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_MASK 0x0002 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_SHIFT 1 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_CORE_ENA_WIDTH 1 /* DSP2_CORE_ENA */
+#define WM2200_DSP2_START 0x0001 /* DSP2_START */
+#define WM2200_DSP2_START_MASK 0x0001 /* DSP2_START */
+#define WM2200_DSP2_START_SHIFT 0 /* DSP2_START */
+#define WM2200_DSP2_START_WIDTH 1 /* DSP2_START */
+
+/*
+ * R2854 (0xB26) - DSP2 Control 31
+ */
+#define WM2200_DSP2_CLK_RATE_MASK 0x0018 /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_SHIFT 3 /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_RATE_WIDTH 2 /* DSP2_CLK_RATE - [4:3] */
+#define WM2200_DSP2_CLK_AVAIL 0x0004 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_MASK 0x0004 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_SHIFT 2 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_AVAIL_WIDTH 1 /* DSP2_CLK_AVAIL */
+#define WM2200_DSP2_CLK_REQ_MASK 0x0003 /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_SHIFT 0 /* DSP2_CLK_REQ - [1:0] */
+#define WM2200_DSP2_CLK_REQ_WIDTH 2 /* DSP2_CLK_REQ - [1:0] */
+
+#endif
diff --git a/sound/soc/codecs/wm5100-tables.c b/sound/soc/codecs/wm5100-tables.c
new file mode 100644
index 000000000000..9a18fae68204
--- /dev/null
+++ b/sound/soc/codecs/wm5100-tables.c
@@ -0,0 +1,1364 @@
+/*
+ * wm5100-tables.c -- WM5100 ALSA SoC Audio driver data
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include "wm5100.h"
+
+bool wm5100_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM5100_SOFTWARE_RESET:
+ case WM5100_DEVICE_REVISION:
+ case WM5100_FX_CTRL:
+ case WM5100_INTERRUPT_STATUS_1:
+ case WM5100_INTERRUPT_STATUS_2:
+ case WM5100_INTERRUPT_STATUS_3:
+ case WM5100_INTERRUPT_STATUS_4:
+ case WM5100_INTERRUPT_RAW_STATUS_2:
+ case WM5100_INTERRUPT_RAW_STATUS_3:
+ case WM5100_INTERRUPT_RAW_STATUS_4:
+ case WM5100_OUTPUT_STATUS_1:
+ case WM5100_OUTPUT_STATUS_2:
+ case WM5100_INPUT_ENABLES_STATUS:
+ case WM5100_MIC_DETECT_3:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+bool wm5100_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM5100_SOFTWARE_RESET:
+ case WM5100_DEVICE_REVISION:
+ case WM5100_CTRL_IF_1:
+ case WM5100_TONE_GENERATOR_1:
+ case WM5100_PWM_DRIVE_1:
+ case WM5100_PWM_DRIVE_2:
+ case WM5100_PWM_DRIVE_3:
+ case WM5100_CLOCKING_1:
+ case WM5100_CLOCKING_3:
+ case WM5100_CLOCKING_4:
+ case WM5100_CLOCKING_5:
+ case WM5100_CLOCKING_6:
+ case WM5100_CLOCKING_7:
+ case WM5100_CLOCKING_8:
+ case WM5100_ASRC_ENABLE:
+ case WM5100_ASRC_STATUS:
+ case WM5100_ASRC_RATE1:
+ case WM5100_ISRC_1_CTRL_1:
+ case WM5100_ISRC_1_CTRL_2:
+ case WM5100_ISRC_2_CTRL1:
+ case WM5100_ISRC_2_CTRL_2:
+ case WM5100_FLL1_CONTROL_1:
+ case WM5100_FLL1_CONTROL_2:
+ case WM5100_FLL1_CONTROL_3:
+ case WM5100_FLL1_CONTROL_5:
+ case WM5100_FLL1_CONTROL_6:
+ case WM5100_FLL1_EFS_1:
+ case WM5100_FLL2_CONTROL_1:
+ case WM5100_FLL2_CONTROL_2:
+ case WM5100_FLL2_CONTROL_3:
+ case WM5100_FLL2_CONTROL_5:
+ case WM5100_FLL2_CONTROL_6:
+ case WM5100_FLL2_EFS_1:
+ case WM5100_MIC_CHARGE_PUMP_1:
+ case WM5100_MIC_CHARGE_PUMP_2:
+ case WM5100_HP_CHARGE_PUMP_1:
+ case WM5100_LDO1_CONTROL:
+ case WM5100_MIC_BIAS_CTRL_1:
+ case WM5100_MIC_BIAS_CTRL_2:
+ case WM5100_MIC_BIAS_CTRL_3:
+ case WM5100_ACCESSORY_DETECT_MODE_1:
+ case WM5100_HEADPHONE_DETECT_1:
+ case WM5100_HEADPHONE_DETECT_2:
+ case WM5100_MIC_DETECT_1:
+ case WM5100_MIC_DETECT_2:
+ case WM5100_MIC_DETECT_3:
+ case WM5100_MISC_CONTROL:
+ case WM5100_INPUT_ENABLES:
+ case WM5100_INPUT_ENABLES_STATUS:
+ case WM5100_IN1L_CONTROL:
+ case WM5100_IN1R_CONTROL:
+ case WM5100_IN2L_CONTROL:
+ case WM5100_IN2R_CONTROL:
+ case WM5100_IN3L_CONTROL:
+ case WM5100_IN3R_CONTROL:
+ case WM5100_IN4L_CONTROL:
+ case WM5100_IN4R_CONTROL:
+ case WM5100_RXANC_SRC:
+ case WM5100_INPUT_VOLUME_RAMP:
+ case WM5100_ADC_DIGITAL_VOLUME_1L:
+ case WM5100_ADC_DIGITAL_VOLUME_1R:
+ case WM5100_ADC_DIGITAL_VOLUME_2L:
+ case WM5100_ADC_DIGITAL_VOLUME_2R:
+ case WM5100_ADC_DIGITAL_VOLUME_3L:
+ case WM5100_ADC_DIGITAL_VOLUME_3R:
+ case WM5100_ADC_DIGITAL_VOLUME_4L:
+ case WM5100_ADC_DIGITAL_VOLUME_4R:
+ case WM5100_OUTPUT_ENABLES_2:
+ case WM5100_OUTPUT_STATUS_1:
+ case WM5100_OUTPUT_STATUS_2:
+ case WM5100_CHANNEL_ENABLES_1:
+ case WM5100_OUT_VOLUME_1L:
+ case WM5100_OUT_VOLUME_1R:
+ case WM5100_DAC_VOLUME_LIMIT_1L:
+ case WM5100_DAC_VOLUME_LIMIT_1R:
+ case WM5100_OUT_VOLUME_2L:
+ case WM5100_OUT_VOLUME_2R:
+ case WM5100_DAC_VOLUME_LIMIT_2L:
+ case WM5100_DAC_VOLUME_LIMIT_2R:
+ case WM5100_OUT_VOLUME_3L:
+ case WM5100_OUT_VOLUME_3R:
+ case WM5100_DAC_VOLUME_LIMIT_3L:
+ case WM5100_DAC_VOLUME_LIMIT_3R:
+ case WM5100_OUT_VOLUME_4L:
+ case WM5100_OUT_VOLUME_4R:
+ case WM5100_DAC_VOLUME_LIMIT_5L:
+ case WM5100_DAC_VOLUME_LIMIT_5R:
+ case WM5100_DAC_VOLUME_LIMIT_6L:
+ case WM5100_DAC_VOLUME_LIMIT_6R:
+ case WM5100_DAC_AEC_CONTROL_1:
+ case WM5100_OUTPUT_VOLUME_RAMP:
+ case WM5100_DAC_DIGITAL_VOLUME_1L:
+ case WM5100_DAC_DIGITAL_VOLUME_1R:
+ case WM5100_DAC_DIGITAL_VOLUME_2L:
+ case WM5100_DAC_DIGITAL_VOLUME_2R:
+ case WM5100_DAC_DIGITAL_VOLUME_3L:
+ case WM5100_DAC_DIGITAL_VOLUME_3R:
+ case WM5100_DAC_DIGITAL_VOLUME_4L:
+ case WM5100_DAC_DIGITAL_VOLUME_4R:
+ case WM5100_DAC_DIGITAL_VOLUME_5L:
+ case WM5100_DAC_DIGITAL_VOLUME_5R:
+ case WM5100_DAC_DIGITAL_VOLUME_6L:
+ case WM5100_DAC_DIGITAL_VOLUME_6R:
+ case WM5100_PDM_SPK1_CTRL_1:
+ case WM5100_PDM_SPK1_CTRL_2:
+ case WM5100_PDM_SPK2_CTRL_1:
+ case WM5100_PDM_SPK2_CTRL_2:
+ case WM5100_AUDIO_IF_1_1:
+ case WM5100_AUDIO_IF_1_2:
+ case WM5100_AUDIO_IF_1_3:
+ case WM5100_AUDIO_IF_1_4:
+ case WM5100_AUDIO_IF_1_5:
+ case WM5100_AUDIO_IF_1_6:
+ case WM5100_AUDIO_IF_1_7:
+ case WM5100_AUDIO_IF_1_8:
+ case WM5100_AUDIO_IF_1_9:
+ case WM5100_AUDIO_IF_1_10:
+ case WM5100_AUDIO_IF_1_11:
+ case WM5100_AUDIO_IF_1_12:
+ case WM5100_AUDIO_IF_1_13:
+ case WM5100_AUDIO_IF_1_14:
+ case WM5100_AUDIO_IF_1_15:
+ case WM5100_AUDIO_IF_1_16:
+ case WM5100_AUDIO_IF_1_17:
+ case WM5100_AUDIO_IF_1_18:
+ case WM5100_AUDIO_IF_1_19:
+ case WM5100_AUDIO_IF_1_20:
+ case WM5100_AUDIO_IF_1_21:
+ case WM5100_AUDIO_IF_1_22:
+ case WM5100_AUDIO_IF_1_23:
+ case WM5100_AUDIO_IF_1_24:
+ case WM5100_AUDIO_IF_1_25:
+ case WM5100_AUDIO_IF_1_26:
+ case WM5100_AUDIO_IF_1_27:
+ case WM5100_AUDIO_IF_2_1:
+ case WM5100_AUDIO_IF_2_2:
+ case WM5100_AUDIO_IF_2_3:
+ case WM5100_AUDIO_IF_2_4:
+ case WM5100_AUDIO_IF_2_5:
+ case WM5100_AUDIO_IF_2_6:
+ case WM5100_AUDIO_IF_2_7:
+ case WM5100_AUDIO_IF_2_8:
+ case WM5100_AUDIO_IF_2_9:
+ case WM5100_AUDIO_IF_2_10:
+ case WM5100_AUDIO_IF_2_11:
+ case WM5100_AUDIO_IF_2_18:
+ case WM5100_AUDIO_IF_2_19:
+ case WM5100_AUDIO_IF_2_26:
+ case WM5100_AUDIO_IF_2_27:
+ case WM5100_AUDIO_IF_3_1:
+ case WM5100_AUDIO_IF_3_2:
+ case WM5100_AUDIO_IF_3_3:
+ case WM5100_AUDIO_IF_3_4:
+ case WM5100_AUDIO_IF_3_5:
+ case WM5100_AUDIO_IF_3_6:
+ case WM5100_AUDIO_IF_3_7:
+ case WM5100_AUDIO_IF_3_8:
+ case WM5100_AUDIO_IF_3_9:
+ case WM5100_AUDIO_IF_3_10:
+ case WM5100_AUDIO_IF_3_11:
+ case WM5100_AUDIO_IF_3_18:
+ case WM5100_AUDIO_IF_3_19:
+ case WM5100_AUDIO_IF_3_26:
+ case WM5100_AUDIO_IF_3_27:
+ case WM5100_PWM1MIX_INPUT_1_SOURCE:
+ case WM5100_PWM1MIX_INPUT_1_VOLUME:
+ case WM5100_PWM1MIX_INPUT_2_SOURCE:
+ case WM5100_PWM1MIX_INPUT_2_VOLUME:
+ case WM5100_PWM1MIX_INPUT_3_SOURCE:
+ case WM5100_PWM1MIX_INPUT_3_VOLUME:
+ case WM5100_PWM1MIX_INPUT_4_SOURCE:
+ case WM5100_PWM1MIX_INPUT_4_VOLUME:
+ case WM5100_PWM2MIX_INPUT_1_SOURCE:
+ case WM5100_PWM2MIX_INPUT_1_VOLUME:
+ case WM5100_PWM2MIX_INPUT_2_SOURCE:
+ case WM5100_PWM2MIX_INPUT_2_VOLUME:
+ case WM5100_PWM2MIX_INPUT_3_SOURCE:
+ case WM5100_PWM2MIX_INPUT_3_VOLUME:
+ case WM5100_PWM2MIX_INPUT_4_SOURCE:
+ case WM5100_PWM2MIX_INPUT_4_VOLUME:
+ case WM5100_OUT1LMIX_INPUT_1_SOURCE:
+ case WM5100_OUT1LMIX_INPUT_1_VOLUME:
+ case WM5100_OUT1LMIX_INPUT_2_SOURCE:
+ case WM5100_OUT1LMIX_INPUT_2_VOLUME:
+ case WM5100_OUT1LMIX_INPUT_3_SOURCE:
+ case WM5100_OUT1LMIX_INPUT_3_VOLUME:
+ case WM5100_OUT1LMIX_INPUT_4_SOURCE:
+ case WM5100_OUT1LMIX_INPUT_4_VOLUME:
+ case WM5100_OUT1RMIX_INPUT_1_SOURCE:
+ case WM5100_OUT1RMIX_INPUT_1_VOLUME:
+ case WM5100_OUT1RMIX_INPUT_2_SOURCE:
+ case WM5100_OUT1RMIX_INPUT_2_VOLUME:
+ case WM5100_OUT1RMIX_INPUT_3_SOURCE:
+ case WM5100_OUT1RMIX_INPUT_3_VOLUME:
+ case WM5100_OUT1RMIX_INPUT_4_SOURCE:
+ case WM5100_OUT1RMIX_INPUT_4_VOLUME:
+ case WM5100_OUT2LMIX_INPUT_1_SOURCE:
+ case WM5100_OUT2LMIX_INPUT_1_VOLUME:
+ case WM5100_OUT2LMIX_INPUT_2_SOURCE:
+ case WM5100_OUT2LMIX_INPUT_2_VOLUME:
+ case WM5100_OUT2LMIX_INPUT_3_SOURCE:
+ case WM5100_OUT2LMIX_INPUT_3_VOLUME:
+ case WM5100_OUT2LMIX_INPUT_4_SOURCE:
+ case WM5100_OUT2LMIX_INPUT_4_VOLUME:
+ case WM5100_OUT2RMIX_INPUT_1_SOURCE:
+ case WM5100_OUT2RMIX_INPUT_1_VOLUME:
+ case WM5100_OUT2RMIX_INPUT_2_SOURCE:
+ case WM5100_OUT2RMIX_INPUT_2_VOLUME:
+ case WM5100_OUT2RMIX_INPUT_3_SOURCE:
+ case WM5100_OUT2RMIX_INPUT_3_VOLUME:
+ case WM5100_OUT2RMIX_INPUT_4_SOURCE:
+ case WM5100_OUT2RMIX_INPUT_4_VOLUME:
+ case WM5100_OUT3LMIX_INPUT_1_SOURCE:
+ case WM5100_OUT3LMIX_INPUT_1_VOLUME:
+ case WM5100_OUT3LMIX_INPUT_2_SOURCE:
+ case WM5100_OUT3LMIX_INPUT_2_VOLUME:
+ case WM5100_OUT3LMIX_INPUT_3_SOURCE:
+ case WM5100_OUT3LMIX_INPUT_3_VOLUME:
+ case WM5100_OUT3LMIX_INPUT_4_SOURCE:
+ case WM5100_OUT3LMIX_INPUT_4_VOLUME:
+ case WM5100_OUT3RMIX_INPUT_1_SOURCE:
+ case WM5100_OUT3RMIX_INPUT_1_VOLUME:
+ case WM5100_OUT3RMIX_INPUT_2_SOURCE:
+ case WM5100_OUT3RMIX_INPUT_2_VOLUME:
+ case WM5100_OUT3RMIX_INPUT_3_SOURCE:
+ case WM5100_OUT3RMIX_INPUT_3_VOLUME:
+ case WM5100_OUT3RMIX_INPUT_4_SOURCE:
+ case WM5100_OUT3RMIX_INPUT_4_VOLUME:
+ case WM5100_OUT4LMIX_INPUT_1_SOURCE:
+ case WM5100_OUT4LMIX_INPUT_1_VOLUME:
+ case WM5100_OUT4LMIX_INPUT_2_SOURCE:
+ case WM5100_OUT4LMIX_INPUT_2_VOLUME:
+ case WM5100_OUT4LMIX_INPUT_3_SOURCE:
+ case WM5100_OUT4LMIX_INPUT_3_VOLUME:
+ case WM5100_OUT4LMIX_INPUT_4_SOURCE:
+ case WM5100_OUT4LMIX_INPUT_4_VOLUME:
+ case WM5100_OUT4RMIX_INPUT_1_SOURCE:
+ case WM5100_OUT4RMIX_INPUT_1_VOLUME:
+ case WM5100_OUT4RMIX_INPUT_2_SOURCE:
+ case WM5100_OUT4RMIX_INPUT_2_VOLUME:
+ case WM5100_OUT4RMIX_INPUT_3_SOURCE:
+ case WM5100_OUT4RMIX_INPUT_3_VOLUME:
+ case WM5100_OUT4RMIX_INPUT_4_SOURCE:
+ case WM5100_OUT4RMIX_INPUT_4_VOLUME:
+ case WM5100_OUT5LMIX_INPUT_1_SOURCE:
+ case WM5100_OUT5LMIX_INPUT_1_VOLUME:
+ case WM5100_OUT5LMIX_INPUT_2_SOURCE:
+ case WM5100_OUT5LMIX_INPUT_2_VOLUME:
+ case WM5100_OUT5LMIX_INPUT_3_SOURCE:
+ case WM5100_OUT5LMIX_INPUT_3_VOLUME:
+ case WM5100_OUT5LMIX_INPUT_4_SOURCE:
+ case WM5100_OUT5LMIX_INPUT_4_VOLUME:
+ case WM5100_OUT5RMIX_INPUT_1_SOURCE:
+ case WM5100_OUT5RMIX_INPUT_1_VOLUME:
+ case WM5100_OUT5RMIX_INPUT_2_SOURCE:
+ case WM5100_OUT5RMIX_INPUT_2_VOLUME:
+ case WM5100_OUT5RMIX_INPUT_3_SOURCE:
+ case WM5100_OUT5RMIX_INPUT_3_VOLUME:
+ case WM5100_OUT5RMIX_INPUT_4_SOURCE:
+ case WM5100_OUT5RMIX_INPUT_4_VOLUME:
+ case WM5100_OUT6LMIX_INPUT_1_SOURCE:
+ case WM5100_OUT6LMIX_INPUT_1_VOLUME:
+ case WM5100_OUT6LMIX_INPUT_2_SOURCE:
+ case WM5100_OUT6LMIX_INPUT_2_VOLUME:
+ case WM5100_OUT6LMIX_INPUT_3_SOURCE:
+ case WM5100_OUT6LMIX_INPUT_3_VOLUME:
+ case WM5100_OUT6LMIX_INPUT_4_SOURCE:
+ case WM5100_OUT6LMIX_INPUT_4_VOLUME:
+ case WM5100_OUT6RMIX_INPUT_1_SOURCE:
+ case WM5100_OUT6RMIX_INPUT_1_VOLUME:
+ case WM5100_OUT6RMIX_INPUT_2_SOURCE:
+ case WM5100_OUT6RMIX_INPUT_2_VOLUME:
+ case WM5100_OUT6RMIX_INPUT_3_SOURCE:
+ case WM5100_OUT6RMIX_INPUT_3_VOLUME:
+ case WM5100_OUT6RMIX_INPUT_4_SOURCE:
+ case WM5100_OUT6RMIX_INPUT_4_VOLUME:
+ case WM5100_AIF1TX1MIX_INPUT_1_SOURCE:
+ case WM5100_AIF1TX1MIX_INPUT_1_VOLUME:
+ case WM5100_AIF1TX1MIX_INPUT_2_SOURCE:
+ case WM5100_AIF1TX1MIX_INPUT_2_VOLUME:
+ case WM5100_AIF1TX1MIX_INPUT_3_SOURCE:
+ case WM5100_AIF1TX1MIX_INPUT_3_VOLUME:
+ case WM5100_AIF1TX1MIX_INPUT_4_SOURCE:
+ case WM5100_AIF1TX1MIX_INPUT_4_VOLUME:
+ case WM5100_AIF1TX2MIX_INPUT_1_SOURCE:
+ case WM5100_AIF1TX2MIX_INPUT_1_VOLUME:
+ case WM5100_AIF1TX2MIX_INPUT_2_SOURCE:
+ case WM5100_AIF1TX2MIX_INPUT_2_VOLUME:
+ case WM5100_AIF1TX2MIX_INPUT_3_SOURCE:
+ case WM5100_AIF1TX2MIX_INPUT_3_VOLUME:
+ case WM5100_AIF1TX2MIX_INPUT_4_SOURCE:
+ case WM5100_AIF1TX2MIX_INPUT_4_VOLUME:
+ case WM5100_AIF1TX3MIX_INPUT_1_SOURCE:
+ case WM5100_AIF1TX3MIX_INPUT_1_VOLUME:
+ case WM5100_AIF1TX3MIX_INPUT_2_SOURCE:
+ case WM5100_AIF1TX3MIX_INPUT_2_VOLUME:
+ case WM5100_AIF1TX3MIX_INPUT_3_SOURCE:
+ case WM5100_AIF1TX3MIX_INPUT_3_VOLUME:
+ case WM5100_AIF1TX3MIX_INPUT_4_SOURCE:
+ case WM5100_AIF1TX3MIX_INPUT_4_VOLUME:
+ case WM5100_AIF1TX4MIX_INPUT_1_SOURCE:
+ case WM5100_AIF1TX4MIX_INPUT_1_VOLUME:
+ case WM5100_AIF1TX4MIX_INPUT_2_SOURCE:
+ case WM5100_AIF1TX4MIX_INPUT_2_VOLUME:
+ case WM5100_AIF1TX4MIX_INPUT_3_SOURCE:
+ case WM5100_AIF1TX4MIX_INPUT_3_VOLUME:
+ case WM5100_AIF1TX4MIX_INPUT_4_SOURCE:
+ case WM5100_AIF1TX4MIX_INPUT_4_VOLUME:
+ case WM5100_AIF1TX5MIX_INPUT_1_SOURCE:
+ case WM5100_AIF1TX5MIX_INPUT_1_VOLUME:
+ case WM5100_AIF1TX5MIX_INPUT_2_SOURCE:
+ case WM5100_AIF1TX5MIX_INPUT_2_VOLUME:
+ case WM5100_AIF1TX5MIX_INPUT_3_SOURCE:
+ case WM5100_AIF1TX5MIX_INPUT_3_VOLUME:
+ case WM5100_AIF1TX5MIX_INPUT_4_SOURCE:
+ case WM5100_AIF1TX5MIX_INPUT_4_VOLUME:
+ case WM5100_AIF1TX6MIX_INPUT_1_SOURCE:
+ case WM5100_AIF1TX6MIX_INPUT_1_VOLUME:
+ case WM5100_AIF1TX6MIX_INPUT_2_SOURCE:
+ case WM5100_AIF1TX6MIX_INPUT_2_VOLUME:
+ case WM5100_AIF1TX6MIX_INPUT_3_SOURCE:
+ case WM5100_AIF1TX6MIX_INPUT_3_VOLUME:
+ case WM5100_AIF1TX6MIX_INPUT_4_SOURCE:
+ case WM5100_AIF1TX6MIX_INPUT_4_VOLUME:
+ case WM5100_AIF1TX7MIX_INPUT_1_SOURCE:
+ case WM5100_AIF1TX7MIX_INPUT_1_VOLUME:
+ case WM5100_AIF1TX7MIX_INPUT_2_SOURCE:
+ case WM5100_AIF1TX7MIX_INPUT_2_VOLUME:
+ case WM5100_AIF1TX7MIX_INPUT_3_SOURCE:
+ case WM5100_AIF1TX7MIX_INPUT_3_VOLUME:
+ case WM5100_AIF1TX7MIX_INPUT_4_SOURCE:
+ case WM5100_AIF1TX7MIX_INPUT_4_VOLUME:
+ case WM5100_AIF1TX8MIX_INPUT_1_SOURCE:
+ case WM5100_AIF1TX8MIX_INPUT_1_VOLUME:
+ case WM5100_AIF1TX8MIX_INPUT_2_SOURCE:
+ case WM5100_AIF1TX8MIX_INPUT_2_VOLUME:
+ case WM5100_AIF1TX8MIX_INPUT_3_SOURCE:
+ case WM5100_AIF1TX8MIX_INPUT_3_VOLUME:
+ case WM5100_AIF1TX8MIX_INPUT_4_SOURCE:
+ case WM5100_AIF1TX8MIX_INPUT_4_VOLUME:
+ case WM5100_AIF2TX1MIX_INPUT_1_SOURCE:
+ case WM5100_AIF2TX1MIX_INPUT_1_VOLUME:
+ case WM5100_AIF2TX1MIX_INPUT_2_SOURCE:
+ case WM5100_AIF2TX1MIX_INPUT_2_VOLUME:
+ case WM5100_AIF2TX1MIX_INPUT_3_SOURCE:
+ case WM5100_AIF2TX1MIX_INPUT_3_VOLUME:
+ case WM5100_AIF2TX1MIX_INPUT_4_SOURCE:
+ case WM5100_AIF2TX1MIX_INPUT_4_VOLUME:
+ case WM5100_AIF2TX2MIX_INPUT_1_SOURCE:
+ case WM5100_AIF2TX2MIX_INPUT_1_VOLUME:
+ case WM5100_AIF2TX2MIX_INPUT_2_SOURCE:
+ case WM5100_AIF2TX2MIX_INPUT_2_VOLUME:
+ case WM5100_AIF2TX2MIX_INPUT_3_SOURCE:
+ case WM5100_AIF2TX2MIX_INPUT_3_VOLUME:
+ case WM5100_AIF2TX2MIX_INPUT_4_SOURCE:
+ case WM5100_AIF2TX2MIX_INPUT_4_VOLUME:
+ case WM5100_AIF3TX1MIX_INPUT_1_SOURCE:
+ case WM5100_AIF3TX1MIX_INPUT_1_VOLUME:
+ case WM5100_AIF3TX1MIX_INPUT_2_SOURCE:
+ case WM5100_AIF3TX1MIX_INPUT_2_VOLUME:
+ case WM5100_AIF3TX1MIX_INPUT_3_SOURCE:
+ case WM5100_AIF3TX1MIX_INPUT_3_VOLUME:
+ case WM5100_AIF3TX1MIX_INPUT_4_SOURCE:
+ case WM5100_AIF3TX1MIX_INPUT_4_VOLUME:
+ case WM5100_AIF3TX2MIX_INPUT_1_SOURCE:
+ case WM5100_AIF3TX2MIX_INPUT_1_VOLUME:
+ case WM5100_AIF3TX2MIX_INPUT_2_SOURCE:
+ case WM5100_AIF3TX2MIX_INPUT_2_VOLUME:
+ case WM5100_AIF3TX2MIX_INPUT_3_SOURCE:
+ case WM5100_AIF3TX2MIX_INPUT_3_VOLUME:
+ case WM5100_AIF3TX2MIX_INPUT_4_SOURCE:
+ case WM5100_AIF3TX2MIX_INPUT_4_VOLUME:
+ case WM5100_EQ1MIX_INPUT_1_SOURCE:
+ case WM5100_EQ1MIX_INPUT_1_VOLUME:
+ case WM5100_EQ1MIX_INPUT_2_SOURCE:
+ case WM5100_EQ1MIX_INPUT_2_VOLUME:
+ case WM5100_EQ1MIX_INPUT_3_SOURCE:
+ case WM5100_EQ1MIX_INPUT_3_VOLUME:
+ case WM5100_EQ1MIX_INPUT_4_SOURCE:
+ case WM5100_EQ1MIX_INPUT_4_VOLUME:
+ case WM5100_EQ2MIX_INPUT_1_SOURCE:
+ case WM5100_EQ2MIX_INPUT_1_VOLUME:
+ case WM5100_EQ2MIX_INPUT_2_SOURCE:
+ case WM5100_EQ2MIX_INPUT_2_VOLUME:
+ case WM5100_EQ2MIX_INPUT_3_SOURCE:
+ case WM5100_EQ2MIX_INPUT_3_VOLUME:
+ case WM5100_EQ2MIX_INPUT_4_SOURCE:
+ case WM5100_EQ2MIX_INPUT_4_VOLUME:
+ case WM5100_EQ3MIX_INPUT_1_SOURCE:
+ case WM5100_EQ3MIX_INPUT_1_VOLUME:
+ case WM5100_EQ3MIX_INPUT_2_SOURCE:
+ case WM5100_EQ3MIX_INPUT_2_VOLUME:
+ case WM5100_EQ3MIX_INPUT_3_SOURCE:
+ case WM5100_EQ3MIX_INPUT_3_VOLUME:
+ case WM5100_EQ3MIX_INPUT_4_SOURCE:
+ case WM5100_EQ3MIX_INPUT_4_VOLUME:
+ case WM5100_EQ4MIX_INPUT_1_SOURCE:
+ case WM5100_EQ4MIX_INPUT_1_VOLUME:
+ case WM5100_EQ4MIX_INPUT_2_SOURCE:
+ case WM5100_EQ4MIX_INPUT_2_VOLUME:
+ case WM5100_EQ4MIX_INPUT_3_SOURCE:
+ case WM5100_EQ4MIX_INPUT_3_VOLUME:
+ case WM5100_EQ4MIX_INPUT_4_SOURCE:
+ case WM5100_EQ4MIX_INPUT_4_VOLUME:
+ case WM5100_DRC1LMIX_INPUT_1_SOURCE:
+ case WM5100_DRC1LMIX_INPUT_1_VOLUME:
+ case WM5100_DRC1LMIX_INPUT_2_SOURCE:
+ case WM5100_DRC1LMIX_INPUT_2_VOLUME:
+ case WM5100_DRC1LMIX_INPUT_3_SOURCE:
+ case WM5100_DRC1LMIX_INPUT_3_VOLUME:
+ case WM5100_DRC1LMIX_INPUT_4_SOURCE:
+ case WM5100_DRC1LMIX_INPUT_4_VOLUME:
+ case WM5100_DRC1RMIX_INPUT_1_SOURCE:
+ case WM5100_DRC1RMIX_INPUT_1_VOLUME:
+ case WM5100_DRC1RMIX_INPUT_2_SOURCE:
+ case WM5100_DRC1RMIX_INPUT_2_VOLUME:
+ case WM5100_DRC1RMIX_INPUT_3_SOURCE:
+ case WM5100_DRC1RMIX_INPUT_3_VOLUME:
+ case WM5100_DRC1RMIX_INPUT_4_SOURCE:
+ case WM5100_DRC1RMIX_INPUT_4_VOLUME:
+ case WM5100_HPLP1MIX_INPUT_1_SOURCE:
+ case WM5100_HPLP1MIX_INPUT_1_VOLUME:
+ case WM5100_HPLP1MIX_INPUT_2_SOURCE:
+ case WM5100_HPLP1MIX_INPUT_2_VOLUME:
+ case WM5100_HPLP1MIX_INPUT_3_SOURCE:
+ case WM5100_HPLP1MIX_INPUT_3_VOLUME:
+ case WM5100_HPLP1MIX_INPUT_4_SOURCE:
+ case WM5100_HPLP1MIX_INPUT_4_VOLUME:
+ case WM5100_HPLP2MIX_INPUT_1_SOURCE:
+ case WM5100_HPLP2MIX_INPUT_1_VOLUME:
+ case WM5100_HPLP2MIX_INPUT_2_SOURCE:
+ case WM5100_HPLP2MIX_INPUT_2_VOLUME:
+ case WM5100_HPLP2MIX_INPUT_3_SOURCE:
+ case WM5100_HPLP2MIX_INPUT_3_VOLUME:
+ case WM5100_HPLP2MIX_INPUT_4_SOURCE:
+ case WM5100_HPLP2MIX_INPUT_4_VOLUME:
+ case WM5100_HPLP3MIX_INPUT_1_SOURCE:
+ case WM5100_HPLP3MIX_INPUT_1_VOLUME:
+ case WM5100_HPLP3MIX_INPUT_2_SOURCE:
+ case WM5100_HPLP3MIX_INPUT_2_VOLUME:
+ case WM5100_HPLP3MIX_INPUT_3_SOURCE:
+ case WM5100_HPLP3MIX_INPUT_3_VOLUME:
+ case WM5100_HPLP3MIX_INPUT_4_SOURCE:
+ case WM5100_HPLP3MIX_INPUT_4_VOLUME:
+ case WM5100_HPLP4MIX_INPUT_1_SOURCE:
+ case WM5100_HPLP4MIX_INPUT_1_VOLUME:
+ case WM5100_HPLP4MIX_INPUT_2_SOURCE:
+ case WM5100_HPLP4MIX_INPUT_2_VOLUME:
+ case WM5100_HPLP4MIX_INPUT_3_SOURCE:
+ case WM5100_HPLP4MIX_INPUT_3_VOLUME:
+ case WM5100_HPLP4MIX_INPUT_4_SOURCE:
+ case WM5100_HPLP4MIX_INPUT_4_VOLUME:
+ case WM5100_DSP1LMIX_INPUT_1_SOURCE:
+ case WM5100_DSP1LMIX_INPUT_1_VOLUME:
+ case WM5100_DSP1LMIX_INPUT_2_SOURCE:
+ case WM5100_DSP1LMIX_INPUT_2_VOLUME:
+ case WM5100_DSP1LMIX_INPUT_3_SOURCE:
+ case WM5100_DSP1LMIX_INPUT_3_VOLUME:
+ case WM5100_DSP1LMIX_INPUT_4_SOURCE:
+ case WM5100_DSP1LMIX_INPUT_4_VOLUME:
+ case WM5100_DSP1RMIX_INPUT_1_SOURCE:
+ case WM5100_DSP1RMIX_INPUT_1_VOLUME:
+ case WM5100_DSP1RMIX_INPUT_2_SOURCE:
+ case WM5100_DSP1RMIX_INPUT_2_VOLUME:
+ case WM5100_DSP1RMIX_INPUT_3_SOURCE:
+ case WM5100_DSP1RMIX_INPUT_3_VOLUME:
+ case WM5100_DSP1RMIX_INPUT_4_SOURCE:
+ case WM5100_DSP1RMIX_INPUT_4_VOLUME:
+ case WM5100_DSP1AUX1MIX_INPUT_1_SOURCE:
+ case WM5100_DSP1AUX2MIX_INPUT_1_SOURCE:
+ case WM5100_DSP1AUX3MIX_INPUT_1_SOURCE:
+ case WM5100_DSP1AUX4MIX_INPUT_1_SOURCE:
+ case WM5100_DSP1AUX5MIX_INPUT_1_SOURCE:
+ case WM5100_DSP1AUX6MIX_INPUT_1_SOURCE:
+ case WM5100_DSP2LMIX_INPUT_1_SOURCE:
+ case WM5100_DSP2LMIX_INPUT_1_VOLUME:
+ case WM5100_DSP2LMIX_INPUT_2_SOURCE:
+ case WM5100_DSP2LMIX_INPUT_2_VOLUME:
+ case WM5100_DSP2LMIX_INPUT_3_SOURCE:
+ case WM5100_DSP2LMIX_INPUT_3_VOLUME:
+ case WM5100_DSP2LMIX_INPUT_4_SOURCE:
+ case WM5100_DSP2LMIX_INPUT_4_VOLUME:
+ case WM5100_DSP2RMIX_INPUT_1_SOURCE:
+ case WM5100_DSP2RMIX_INPUT_1_VOLUME:
+ case WM5100_DSP2RMIX_INPUT_2_SOURCE:
+ case WM5100_DSP2RMIX_INPUT_2_VOLUME:
+ case WM5100_DSP2RMIX_INPUT_3_SOURCE:
+ case WM5100_DSP2RMIX_INPUT_3_VOLUME:
+ case WM5100_DSP2RMIX_INPUT_4_SOURCE:
+ case WM5100_DSP2RMIX_INPUT_4_VOLUME:
+ case WM5100_DSP2AUX1MIX_INPUT_1_SOURCE:
+ case WM5100_DSP2AUX2MIX_INPUT_1_SOURCE:
+ case WM5100_DSP2AUX3MIX_INPUT_1_SOURCE:
+ case WM5100_DSP2AUX4MIX_INPUT_1_SOURCE:
+ case WM5100_DSP2AUX5MIX_INPUT_1_SOURCE:
+ case WM5100_DSP2AUX6MIX_INPUT_1_SOURCE:
+ case WM5100_DSP3LMIX_INPUT_1_SOURCE:
+ case WM5100_DSP3LMIX_INPUT_1_VOLUME:
+ case WM5100_DSP3LMIX_INPUT_2_SOURCE:
+ case WM5100_DSP3LMIX_INPUT_2_VOLUME:
+ case WM5100_DSP3LMIX_INPUT_3_SOURCE:
+ case WM5100_DSP3LMIX_INPUT_3_VOLUME:
+ case WM5100_DSP3LMIX_INPUT_4_SOURCE:
+ case WM5100_DSP3LMIX_INPUT_4_VOLUME:
+ case WM5100_DSP3RMIX_INPUT_1_SOURCE:
+ case WM5100_DSP3RMIX_INPUT_1_VOLUME:
+ case WM5100_DSP3RMIX_INPUT_2_SOURCE:
+ case WM5100_DSP3RMIX_INPUT_2_VOLUME:
+ case WM5100_DSP3RMIX_INPUT_3_SOURCE:
+ case WM5100_DSP3RMIX_INPUT_3_VOLUME:
+ case WM5100_DSP3RMIX_INPUT_4_SOURCE:
+ case WM5100_DSP3RMIX_INPUT_4_VOLUME:
+ case WM5100_DSP3AUX1MIX_INPUT_1_SOURCE:
+ case WM5100_DSP3AUX2MIX_INPUT_1_SOURCE:
+ case WM5100_DSP3AUX3MIX_INPUT_1_SOURCE:
+ case WM5100_DSP3AUX4MIX_INPUT_1_SOURCE:
+ case WM5100_DSP3AUX5MIX_INPUT_1_SOURCE:
+ case WM5100_DSP3AUX6MIX_INPUT_1_SOURCE:
+ case WM5100_ASRC1LMIX_INPUT_1_SOURCE:
+ case WM5100_ASRC1RMIX_INPUT_1_SOURCE:
+ case WM5100_ASRC2LMIX_INPUT_1_SOURCE:
+ case WM5100_ASRC2RMIX_INPUT_1_SOURCE:
+ case WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC1INT1MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC1INT2MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC1INT3MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC1INT4MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC2INT1MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC2INT2MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC2INT3MIX_INPUT_1_SOURCE:
+ case WM5100_ISRC2INT4MIX_INPUT_1_SOURCE:
+ case WM5100_GPIO_CTRL_1:
+ case WM5100_GPIO_CTRL_2:
+ case WM5100_GPIO_CTRL_3:
+ case WM5100_GPIO_CTRL_4:
+ case WM5100_GPIO_CTRL_5:
+ case WM5100_GPIO_CTRL_6:
+ case WM5100_MISC_PAD_CTRL_1:
+ case WM5100_MISC_PAD_CTRL_2:
+ case WM5100_MISC_PAD_CTRL_3:
+ case WM5100_MISC_PAD_CTRL_4:
+ case WM5100_MISC_PAD_CTRL_5:
+ case WM5100_MISC_GPIO_1:
+ case WM5100_INTERRUPT_STATUS_1:
+ case WM5100_INTERRUPT_STATUS_2:
+ case WM5100_INTERRUPT_STATUS_3:
+ case WM5100_INTERRUPT_STATUS_4:
+ case WM5100_INTERRUPT_RAW_STATUS_2:
+ case WM5100_INTERRUPT_RAW_STATUS_3:
+ case WM5100_INTERRUPT_RAW_STATUS_4:
+ case WM5100_INTERRUPT_STATUS_1_MASK:
+ case WM5100_INTERRUPT_STATUS_2_MASK:
+ case WM5100_INTERRUPT_STATUS_3_MASK:
+ case WM5100_INTERRUPT_STATUS_4_MASK:
+ case WM5100_INTERRUPT_CONTROL:
+ case WM5100_IRQ_DEBOUNCE_1:
+ case WM5100_IRQ_DEBOUNCE_2:
+ case WM5100_FX_CTRL:
+ case WM5100_EQ1_1:
+ case WM5100_EQ1_2:
+ case WM5100_EQ1_3:
+ case WM5100_EQ1_4:
+ case WM5100_EQ1_5:
+ case WM5100_EQ1_6:
+ case WM5100_EQ1_7:
+ case WM5100_EQ1_8:
+ case WM5100_EQ1_9:
+ case WM5100_EQ1_10:
+ case WM5100_EQ1_11:
+ case WM5100_EQ1_12:
+ case WM5100_EQ1_13:
+ case WM5100_EQ1_14:
+ case WM5100_EQ1_15:
+ case WM5100_EQ1_16:
+ case WM5100_EQ1_17:
+ case WM5100_EQ1_18:
+ case WM5100_EQ1_19:
+ case WM5100_EQ1_20:
+ case WM5100_EQ2_1:
+ case WM5100_EQ2_2:
+ case WM5100_EQ2_3:
+ case WM5100_EQ2_4:
+ case WM5100_EQ2_5:
+ case WM5100_EQ2_6:
+ case WM5100_EQ2_7:
+ case WM5100_EQ2_8:
+ case WM5100_EQ2_9:
+ case WM5100_EQ2_10:
+ case WM5100_EQ2_11:
+ case WM5100_EQ2_12:
+ case WM5100_EQ2_13:
+ case WM5100_EQ2_14:
+ case WM5100_EQ2_15:
+ case WM5100_EQ2_16:
+ case WM5100_EQ2_17:
+ case WM5100_EQ2_18:
+ case WM5100_EQ2_19:
+ case WM5100_EQ2_20:
+ case WM5100_EQ3_1:
+ case WM5100_EQ3_2:
+ case WM5100_EQ3_3:
+ case WM5100_EQ3_4:
+ case WM5100_EQ3_5:
+ case WM5100_EQ3_6:
+ case WM5100_EQ3_7:
+ case WM5100_EQ3_8:
+ case WM5100_EQ3_9:
+ case WM5100_EQ3_10:
+ case WM5100_EQ3_11:
+ case WM5100_EQ3_12:
+ case WM5100_EQ3_13:
+ case WM5100_EQ3_14:
+ case WM5100_EQ3_15:
+ case WM5100_EQ3_16:
+ case WM5100_EQ3_17:
+ case WM5100_EQ3_18:
+ case WM5100_EQ3_19:
+ case WM5100_EQ3_20:
+ case WM5100_EQ4_1:
+ case WM5100_EQ4_2:
+ case WM5100_EQ4_3:
+ case WM5100_EQ4_4:
+ case WM5100_EQ4_5:
+ case WM5100_EQ4_6:
+ case WM5100_EQ4_7:
+ case WM5100_EQ4_8:
+ case WM5100_EQ4_9:
+ case WM5100_EQ4_10:
+ case WM5100_EQ4_11:
+ case WM5100_EQ4_12:
+ case WM5100_EQ4_13:
+ case WM5100_EQ4_14:
+ case WM5100_EQ4_15:
+ case WM5100_EQ4_16:
+ case WM5100_EQ4_17:
+ case WM5100_EQ4_18:
+ case WM5100_EQ4_19:
+ case WM5100_EQ4_20:
+ case WM5100_DRC1_CTRL1:
+ case WM5100_DRC1_CTRL2:
+ case WM5100_DRC1_CTRL3:
+ case WM5100_DRC1_CTRL4:
+ case WM5100_DRC1_CTRL5:
+ case WM5100_HPLPF1_1:
+ case WM5100_HPLPF1_2:
+ case WM5100_HPLPF2_1:
+ case WM5100_HPLPF2_2:
+ case WM5100_HPLPF3_1:
+ case WM5100_HPLPF3_2:
+ case WM5100_HPLPF4_1:
+ case WM5100_HPLPF4_2:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+struct reg_default wm5100_reg_defaults[WM5100_REGISTER_COUNT] = {
+ { 0x0000, 0x0000 }, /* R0 - software reset */
+ { 0x0001, 0x0000 }, /* R1 - Device Revision */
+ { 0x0010, 0x0801 }, /* R16 - Ctrl IF 1 */
+ { 0x0020, 0x0000 }, /* R32 - Tone Generator 1 */
+ { 0x0030, 0x0000 }, /* R48 - PWM Drive 1 */
+ { 0x0031, 0x0100 }, /* R49 - PWM Drive 2 */
+ { 0x0032, 0x0100 }, /* R50 - PWM Drive 3 */
+ { 0x0100, 0x0002 }, /* R256 - Clocking 1 */
+ { 0x0101, 0x0000 }, /* R257 - Clocking 3 */
+ { 0x0102, 0x0011 }, /* R258 - Clocking 4 */
+ { 0x0103, 0x0011 }, /* R259 - Clocking 5 */
+ { 0x0104, 0x0011 }, /* R260 - Clocking 6 */
+ { 0x0107, 0x0000 }, /* R263 - Clocking 7 */
+ { 0x0108, 0x0000 }, /* R264 - Clocking 8 */
+ { 0x0120, 0x0000 }, /* R288 - ASRC_ENABLE */
+ { 0x0121, 0x0000 }, /* R289 - ASRC_STATUS */
+ { 0x0122, 0x0000 }, /* R290 - ASRC_RATE1 */
+ { 0x0141, 0x8000 }, /* R321 - ISRC 1 CTRL 1 */
+ { 0x0142, 0x0000 }, /* R322 - ISRC 1 CTRL 2 */
+ { 0x0143, 0x8000 }, /* R323 - ISRC 2 CTRL1 */
+ { 0x0144, 0x0000 }, /* R324 - ISRC 2 CTRL 2 */
+ { 0x0182, 0x0000 }, /* R386 - FLL1 Control 1 */
+ { 0x0183, 0x0000 }, /* R387 - FLL1 Control 2 */
+ { 0x0184, 0x0000 }, /* R388 - FLL1 Control 3 */
+ { 0x0186, 0x0177 }, /* R390 - FLL1 Control 5 */
+ { 0x0187, 0x0001 }, /* R391 - FLL1 Control 6 */
+ { 0x0188, 0x0000 }, /* R392 - FLL1 EFS 1 */
+ { 0x01A2, 0x0000 }, /* R418 - FLL2 Control 1 */
+ { 0x01A3, 0x0000 }, /* R419 - FLL2 Control 2 */
+ { 0x01A4, 0x0000 }, /* R420 - FLL2 Control 3 */
+ { 0x01A6, 0x0177 }, /* R422 - FLL2 Control 5 */
+ { 0x01A7, 0x0001 }, /* R423 - FLL2 Control 6 */
+ { 0x01A8, 0x0000 }, /* R424 - FLL2 EFS 1 */
+ { 0x0200, 0x0020 }, /* R512 - Mic Charge Pump 1 */
+ { 0x0201, 0xB084 }, /* R513 - Mic Charge Pump 2 */
+ { 0x0202, 0xBBDE }, /* R514 - HP Charge Pump 1 */
+ { 0x0211, 0x20D4 }, /* R529 - LDO1 Control */
+ { 0x0215, 0x0062 }, /* R533 - Mic Bias Ctrl 1 */
+ { 0x0216, 0x0062 }, /* R534 - Mic Bias Ctrl 2 */
+ { 0x0217, 0x0062 }, /* R535 - Mic Bias Ctrl 3 */
+ { 0x0280, 0x0004 }, /* R640 - Accessory Detect Mode 1 */
+ { 0x0288, 0x0020 }, /* R648 - Headphone Detect 1 */
+ { 0x0289, 0x0000 }, /* R649 - Headphone Detect 2 */
+ { 0x0290, 0x1100 }, /* R656 - Mic Detect 1 */
+ { 0x0291, 0x009F }, /* R657 - Mic Detect 2 */
+ { 0x0292, 0x0000 }, /* R658 - Mic Detect 3 */
+ { 0x0301, 0x0000 }, /* R769 - Input Enables */
+ { 0x0302, 0x0000 }, /* R770 - Input Enables Status */
+ { 0x0310, 0x2280 }, /* R784 - Status */
+ { 0x0311, 0x0080 }, /* R785 - IN1R Control */
+ { 0x0312, 0x2280 }, /* R786 - IN2L Control */
+ { 0x0313, 0x0080 }, /* R787 - IN2R Control */
+ { 0x0314, 0x2280 }, /* R788 - IN3L Control */
+ { 0x0315, 0x0080 }, /* R789 - IN3R Control */
+ { 0x0316, 0x2280 }, /* R790 - IN4L Control */
+ { 0x0317, 0x0080 }, /* R791 - IN4R Control */
+ { 0x0318, 0x0000 }, /* R792 - RXANC_SRC */
+ { 0x0319, 0x0022 }, /* R793 - Input Volume Ramp */
+ { 0x0320, 0x0180 }, /* R800 - ADC Digital Volume 1L */
+ { 0x0321, 0x0180 }, /* R801 - ADC Digital Volume 1R */
+ { 0x0322, 0x0180 }, /* R802 - ADC Digital Volume 2L */
+ { 0x0323, 0x0180 }, /* R803 - ADC Digital Volume 2R */
+ { 0x0324, 0x0180 }, /* R804 - ADC Digital Volume 3L */
+ { 0x0325, 0x0180 }, /* R805 - ADC Digital Volume 3R */
+ { 0x0326, 0x0180 }, /* R806 - ADC Digital Volume 4L */
+ { 0x0327, 0x0180 }, /* R807 - ADC Digital Volume 4R */
+ { 0x0401, 0x0000 }, /* R1025 - Output Enables 2 */
+ { 0x0402, 0x0000 }, /* R1026 - Output Status 1 */
+ { 0x0403, 0x0000 }, /* R1027 - Output Status 2 */
+ { 0x0408, 0x0000 }, /* R1032 - Channel Enables 1 */
+ { 0x0410, 0x0080 }, /* R1040 - Out Volume 1L */
+ { 0x0411, 0x0080 }, /* R1041 - Out Volume 1R */
+ { 0x0412, 0x0080 }, /* R1042 - DAC Volume Limit 1L */
+ { 0x0413, 0x0080 }, /* R1043 - DAC Volume Limit 1R */
+ { 0x0414, 0x0080 }, /* R1044 - Out Volume 2L */
+ { 0x0415, 0x0080 }, /* R1045 - Out Volume 2R */
+ { 0x0416, 0x0080 }, /* R1046 - DAC Volume Limit 2L */
+ { 0x0417, 0x0080 }, /* R1047 - DAC Volume Limit 2R */
+ { 0x0418, 0x0080 }, /* R1048 - Out Volume 3L */
+ { 0x0419, 0x0080 }, /* R1049 - Out Volume 3R */
+ { 0x041A, 0x0080 }, /* R1050 - DAC Volume Limit 3L */
+ { 0x041B, 0x0080 }, /* R1051 - DAC Volume Limit 3R */
+ { 0x041C, 0x0080 }, /* R1052 - Out Volume 4L */
+ { 0x041D, 0x0080 }, /* R1053 - Out Volume 4R */
+ { 0x041E, 0x0080 }, /* R1054 - DAC Volume Limit 5L */
+ { 0x041F, 0x0080 }, /* R1055 - DAC Volume Limit 5R */
+ { 0x0420, 0x0080 }, /* R1056 - DAC Volume Limit 6L */
+ { 0x0421, 0x0080 }, /* R1057 - DAC Volume Limit 6R */
+ { 0x0440, 0x0000 }, /* R1088 - DAC AEC Control 1 */
+ { 0x0441, 0x0022 }, /* R1089 - Output Volume Ramp */
+ { 0x0480, 0x0180 }, /* R1152 - DAC Digital Volume 1L */
+ { 0x0481, 0x0180 }, /* R1153 - DAC Digital Volume 1R */
+ { 0x0482, 0x0180 }, /* R1154 - DAC Digital Volume 2L */
+ { 0x0483, 0x0180 }, /* R1155 - DAC Digital Volume 2R */
+ { 0x0484, 0x0180 }, /* R1156 - DAC Digital Volume 3L */
+ { 0x0485, 0x0180 }, /* R1157 - DAC Digital Volume 3R */
+ { 0x0486, 0x0180 }, /* R1158 - DAC Digital Volume 4L */
+ { 0x0487, 0x0180 }, /* R1159 - DAC Digital Volume 4R */
+ { 0x0488, 0x0180 }, /* R1160 - DAC Digital Volume 5L */
+ { 0x0489, 0x0180 }, /* R1161 - DAC Digital Volume 5R */
+ { 0x048A, 0x0180 }, /* R1162 - DAC Digital Volume 6L */
+ { 0x048B, 0x0180 }, /* R1163 - DAC Digital Volume 6R */
+ { 0x04C0, 0x0069 }, /* R1216 - PDM SPK1 CTRL 1 */
+ { 0x04C1, 0x0000 }, /* R1217 - PDM SPK1 CTRL 2 */
+ { 0x04C2, 0x0069 }, /* R1218 - PDM SPK2 CTRL 1 */
+ { 0x04C3, 0x0000 }, /* R1219 - PDM SPK2 CTRL 2 */
+ { 0x0500, 0x000C }, /* R1280 - Audio IF 1_1 */
+ { 0x0501, 0x0008 }, /* R1281 - Audio IF 1_2 */
+ { 0x0502, 0x0000 }, /* R1282 - Audio IF 1_3 */
+ { 0x0503, 0x0000 }, /* R1283 - Audio IF 1_4 */
+ { 0x0504, 0x0000 }, /* R1284 - Audio IF 1_5 */
+ { 0x0505, 0x0300 }, /* R1285 - Audio IF 1_6 */
+ { 0x0506, 0x0300 }, /* R1286 - Audio IF 1_7 */
+ { 0x0507, 0x1820 }, /* R1287 - Audio IF 1_8 */
+ { 0x0508, 0x1820 }, /* R1288 - Audio IF 1_9 */
+ { 0x0509, 0x0000 }, /* R1289 - Audio IF 1_10 */
+ { 0x050A, 0x0001 }, /* R1290 - Audio IF 1_11 */
+ { 0x050B, 0x0002 }, /* R1291 - Audio IF 1_12 */
+ { 0x050C, 0x0003 }, /* R1292 - Audio IF 1_13 */
+ { 0x050D, 0x0004 }, /* R1293 - Audio IF 1_14 */
+ { 0x050E, 0x0005 }, /* R1294 - Audio IF 1_15 */
+ { 0x050F, 0x0006 }, /* R1295 - Audio IF 1_16 */
+ { 0x0510, 0x0007 }, /* R1296 - Audio IF 1_17 */
+ { 0x0511, 0x0000 }, /* R1297 - Audio IF 1_18 */
+ { 0x0512, 0x0001 }, /* R1298 - Audio IF 1_19 */
+ { 0x0513, 0x0002 }, /* R1299 - Audio IF 1_20 */
+ { 0x0514, 0x0003 }, /* R1300 - Audio IF 1_21 */
+ { 0x0515, 0x0004 }, /* R1301 - Audio IF 1_22 */
+ { 0x0516, 0x0005 }, /* R1302 - Audio IF 1_23 */
+ { 0x0517, 0x0006 }, /* R1303 - Audio IF 1_24 */
+ { 0x0518, 0x0007 }, /* R1304 - Audio IF 1_25 */
+ { 0x0519, 0x0000 }, /* R1305 - Audio IF 1_26 */
+ { 0x051A, 0x0000 }, /* R1306 - Audio IF 1_27 */
+ { 0x0540, 0x000C }, /* R1344 - Audio IF 2_1 */
+ { 0x0541, 0x0008 }, /* R1345 - Audio IF 2_2 */
+ { 0x0542, 0x0000 }, /* R1346 - Audio IF 2_3 */
+ { 0x0543, 0x0000 }, /* R1347 - Audio IF 2_4 */
+ { 0x0544, 0x0000 }, /* R1348 - Audio IF 2_5 */
+ { 0x0545, 0x0300 }, /* R1349 - Audio IF 2_6 */
+ { 0x0546, 0x0300 }, /* R1350 - Audio IF 2_7 */
+ { 0x0547, 0x1820 }, /* R1351 - Audio IF 2_8 */
+ { 0x0548, 0x1820 }, /* R1352 - Audio IF 2_9 */
+ { 0x0549, 0x0000 }, /* R1353 - Audio IF 2_10 */
+ { 0x054A, 0x0001 }, /* R1354 - Audio IF 2_11 */
+ { 0x0551, 0x0000 }, /* R1361 - Audio IF 2_18 */
+ { 0x0552, 0x0001 }, /* R1362 - Audio IF 2_19 */
+ { 0x0559, 0x0000 }, /* R1369 - Audio IF 2_26 */
+ { 0x055A, 0x0000 }, /* R1370 - Audio IF 2_27 */
+ { 0x0580, 0x000C }, /* R1408 - Audio IF 3_1 */
+ { 0x0581, 0x0008 }, /* R1409 - Audio IF 3_2 */
+ { 0x0582, 0x0000 }, /* R1410 - Audio IF 3_3 */
+ { 0x0583, 0x0000 }, /* R1411 - Audio IF 3_4 */
+ { 0x0584, 0x0000 }, /* R1412 - Audio IF 3_5 */
+ { 0x0585, 0x0300 }, /* R1413 - Audio IF 3_6 */
+ { 0x0586, 0x0300 }, /* R1414 - Audio IF 3_7 */
+ { 0x0587, 0x1820 }, /* R1415 - Audio IF 3_8 */
+ { 0x0588, 0x1820 }, /* R1416 - Audio IF 3_9 */
+ { 0x0589, 0x0000 }, /* R1417 - Audio IF 3_10 */
+ { 0x058A, 0x0001 }, /* R1418 - Audio IF 3_11 */
+ { 0x0591, 0x0000 }, /* R1425 - Audio IF 3_18 */
+ { 0x0592, 0x0001 }, /* R1426 - Audio IF 3_19 */
+ { 0x0599, 0x0000 }, /* R1433 - Audio IF 3_26 */
+ { 0x059A, 0x0000 }, /* R1434 - Audio IF 3_27 */
+ { 0x0640, 0x0000 }, /* R1600 - PWM1MIX Input 1 Source */
+ { 0x0641, 0x0080 }, /* R1601 - PWM1MIX Input 1 Volume */
+ { 0x0642, 0x0000 }, /* R1602 - PWM1MIX Input 2 Source */
+ { 0x0643, 0x0080 }, /* R1603 - PWM1MIX Input 2 Volume */
+ { 0x0644, 0x0000 }, /* R1604 - PWM1MIX Input 3 Source */
+ { 0x0645, 0x0080 }, /* R1605 - PWM1MIX Input 3 Volume */
+ { 0x0646, 0x0000 }, /* R1606 - PWM1MIX Input 4 Source */
+ { 0x0647, 0x0080 }, /* R1607 - PWM1MIX Input 4 Volume */
+ { 0x0648, 0x0000 }, /* R1608 - PWM2MIX Input 1 Source */
+ { 0x0649, 0x0080 }, /* R1609 - PWM2MIX Input 1 Volume */
+ { 0x064A, 0x0000 }, /* R1610 - PWM2MIX Input 2 Source */
+ { 0x064B, 0x0080 }, /* R1611 - PWM2MIX Input 2 Volume */
+ { 0x064C, 0x0000 }, /* R1612 - PWM2MIX Input 3 Source */
+ { 0x064D, 0x0080 }, /* R1613 - PWM2MIX Input 3 Volume */
+ { 0x064E, 0x0000 }, /* R1614 - PWM2MIX Input 4 Source */
+ { 0x064F, 0x0080 }, /* R1615 - PWM2MIX Input 4 Volume */
+ { 0x0680, 0x0000 }, /* R1664 - OUT1LMIX Input 1 Source */
+ { 0x0681, 0x0080 }, /* R1665 - OUT1LMIX Input 1 Volume */
+ { 0x0682, 0x0000 }, /* R1666 - OUT1LMIX Input 2 Source */
+ { 0x0683, 0x0080 }, /* R1667 - OUT1LMIX Input 2 Volume */
+ { 0x0684, 0x0000 }, /* R1668 - OUT1LMIX Input 3 Source */
+ { 0x0685, 0x0080 }, /* R1669 - OUT1LMIX Input 3 Volume */
+ { 0x0686, 0x0000 }, /* R1670 - OUT1LMIX Input 4 Source */
+ { 0x0687, 0x0080 }, /* R1671 - OUT1LMIX Input 4 Volume */
+ { 0x0688, 0x0000 }, /* R1672 - OUT1RMIX Input 1 Source */
+ { 0x0689, 0x0080 }, /* R1673 - OUT1RMIX Input 1 Volume */
+ { 0x068A, 0x0000 }, /* R1674 - OUT1RMIX Input 2 Source */
+ { 0x068B, 0x0080 }, /* R1675 - OUT1RMIX Input 2 Volume */
+ { 0x068C, 0x0000 }, /* R1676 - OUT1RMIX Input 3 Source */
+ { 0x068D, 0x0080 }, /* R1677 - OUT1RMIX Input 3 Volume */
+ { 0x068E, 0x0000 }, /* R1678 - OUT1RMIX Input 4 Source */
+ { 0x068F, 0x0080 }, /* R1679 - OUT1RMIX Input 4 Volume */
+ { 0x0690, 0x0000 }, /* R1680 - OUT2LMIX Input 1 Source */
+ { 0x0691, 0x0080 }, /* R1681 - OUT2LMIX Input 1 Volume */
+ { 0x0692, 0x0000 }, /* R1682 - OUT2LMIX Input 2 Source */
+ { 0x0693, 0x0080 }, /* R1683 - OUT2LMIX Input 2 Volume */
+ { 0x0694, 0x0000 }, /* R1684 - OUT2LMIX Input 3 Source */
+ { 0x0695, 0x0080 }, /* R1685 - OUT2LMIX Input 3 Volume */
+ { 0x0696, 0x0000 }, /* R1686 - OUT2LMIX Input 4 Source */
+ { 0x0697, 0x0080 }, /* R1687 - OUT2LMIX Input 4 Volume */
+ { 0x0698, 0x0000 }, /* R1688 - OUT2RMIX Input 1 Source */
+ { 0x0699, 0x0080 }, /* R1689 - OUT2RMIX Input 1 Volume */
+ { 0x069A, 0x0000 }, /* R1690 - OUT2RMIX Input 2 Source */
+ { 0x069B, 0x0080 }, /* R1691 - OUT2RMIX Input 2 Volume */
+ { 0x069C, 0x0000 }, /* R1692 - OUT2RMIX Input 3 Source */
+ { 0x069D, 0x0080 }, /* R1693 - OUT2RMIX Input 3 Volume */
+ { 0x069E, 0x0000 }, /* R1694 - OUT2RMIX Input 4 Source */
+ { 0x069F, 0x0080 }, /* R1695 - OUT2RMIX Input 4 Volume */
+ { 0x06A0, 0x0000 }, /* R1696 - OUT3LMIX Input 1 Source */
+ { 0x06A1, 0x0080 }, /* R1697 - OUT3LMIX Input 1 Volume */
+ { 0x06A2, 0x0000 }, /* R1698 - OUT3LMIX Input 2 Source */
+ { 0x06A3, 0x0080 }, /* R1699 - OUT3LMIX Input 2 Volume */
+ { 0x06A4, 0x0000 }, /* R1700 - OUT3LMIX Input 3 Source */
+ { 0x06A5, 0x0080 }, /* R1701 - OUT3LMIX Input 3 Volume */
+ { 0x06A6, 0x0000 }, /* R1702 - OUT3LMIX Input 4 Source */
+ { 0x06A7, 0x0080 }, /* R1703 - OUT3LMIX Input 4 Volume */
+ { 0x06A8, 0x0000 }, /* R1704 - OUT3RMIX Input 1 Source */
+ { 0x06A9, 0x0080 }, /* R1705 - OUT3RMIX Input 1 Volume */
+ { 0x06AA, 0x0000 }, /* R1706 - OUT3RMIX Input 2 Source */
+ { 0x06AB, 0x0080 }, /* R1707 - OUT3RMIX Input 2 Volume */
+ { 0x06AC, 0x0000 }, /* R1708 - OUT3RMIX Input 3 Source */
+ { 0x06AD, 0x0080 }, /* R1709 - OUT3RMIX Input 3 Volume */
+ { 0x06AE, 0x0000 }, /* R1710 - OUT3RMIX Input 4 Source */
+ { 0x06AF, 0x0080 }, /* R1711 - OUT3RMIX Input 4 Volume */
+ { 0x06B0, 0x0000 }, /* R1712 - OUT4LMIX Input 1 Source */
+ { 0x06B1, 0x0080 }, /* R1713 - OUT4LMIX Input 1 Volume */
+ { 0x06B2, 0x0000 }, /* R1714 - OUT4LMIX Input 2 Source */
+ { 0x06B3, 0x0080 }, /* R1715 - OUT4LMIX Input 2 Volume */
+ { 0x06B4, 0x0000 }, /* R1716 - OUT4LMIX Input 3 Source */
+ { 0x06B5, 0x0080 }, /* R1717 - OUT4LMIX Input 3 Volume */
+ { 0x06B6, 0x0000 }, /* R1718 - OUT4LMIX Input 4 Source */
+ { 0x06B7, 0x0080 }, /* R1719 - OUT4LMIX Input 4 Volume */
+ { 0x06B8, 0x0000 }, /* R1720 - OUT4RMIX Input 1 Source */
+ { 0x06B9, 0x0080 }, /* R1721 - OUT4RMIX Input 1 Volume */
+ { 0x06BA, 0x0000 }, /* R1722 - OUT4RMIX Input 2 Source */
+ { 0x06BB, 0x0080 }, /* R1723 - OUT4RMIX Input 2 Volume */
+ { 0x06BC, 0x0000 }, /* R1724 - OUT4RMIX Input 3 Source */
+ { 0x06BD, 0x0080 }, /* R1725 - OUT4RMIX Input 3 Volume */
+ { 0x06BE, 0x0000 }, /* R1726 - OUT4RMIX Input 4 Source */
+ { 0x06BF, 0x0080 }, /* R1727 - OUT4RMIX Input 4 Volume */
+ { 0x06C0, 0x0000 }, /* R1728 - OUT5LMIX Input 1 Source */
+ { 0x06C1, 0x0080 }, /* R1729 - OUT5LMIX Input 1 Volume */
+ { 0x06C2, 0x0000 }, /* R1730 - OUT5LMIX Input 2 Source */
+ { 0x06C3, 0x0080 }, /* R1731 - OUT5LMIX Input 2 Volume */
+ { 0x06C4, 0x0000 }, /* R1732 - OUT5LMIX Input 3 Source */
+ { 0x06C5, 0x0080 }, /* R1733 - OUT5LMIX Input 3 Volume */
+ { 0x06C6, 0x0000 }, /* R1734 - OUT5LMIX Input 4 Source */
+ { 0x06C7, 0x0080 }, /* R1735 - OUT5LMIX Input 4 Volume */
+ { 0x06C8, 0x0000 }, /* R1736 - OUT5RMIX Input 1 Source */
+ { 0x06C9, 0x0080 }, /* R1737 - OUT5RMIX Input 1 Volume */
+ { 0x06CA, 0x0000 }, /* R1738 - OUT5RMIX Input 2 Source */
+ { 0x06CB, 0x0080 }, /* R1739 - OUT5RMIX Input 2 Volume */
+ { 0x06CC, 0x0000 }, /* R1740 - OUT5RMIX Input 3 Source */
+ { 0x06CD, 0x0080 }, /* R1741 - OUT5RMIX Input 3 Volume */
+ { 0x06CE, 0x0000 }, /* R1742 - OUT5RMIX Input 4 Source */
+ { 0x06CF, 0x0080 }, /* R1743 - OUT5RMIX Input 4 Volume */
+ { 0x06D0, 0x0000 }, /* R1744 - OUT6LMIX Input 1 Source */
+ { 0x06D1, 0x0080 }, /* R1745 - OUT6LMIX Input 1 Volume */
+ { 0x06D2, 0x0000 }, /* R1746 - OUT6LMIX Input 2 Source */
+ { 0x06D3, 0x0080 }, /* R1747 - OUT6LMIX Input 2 Volume */
+ { 0x06D4, 0x0000 }, /* R1748 - OUT6LMIX Input 3 Source */
+ { 0x06D5, 0x0080 }, /* R1749 - OUT6LMIX Input 3 Volume */
+ { 0x06D6, 0x0000 }, /* R1750 - OUT6LMIX Input 4 Source */
+ { 0x06D7, 0x0080 }, /* R1751 - OUT6LMIX Input 4 Volume */
+ { 0x06D8, 0x0000 }, /* R1752 - OUT6RMIX Input 1 Source */
+ { 0x06D9, 0x0080 }, /* R1753 - OUT6RMIX Input 1 Volume */
+ { 0x06DA, 0x0000 }, /* R1754 - OUT6RMIX Input 2 Source */
+ { 0x06DB, 0x0080 }, /* R1755 - OUT6RMIX Input 2 Volume */
+ { 0x06DC, 0x0000 }, /* R1756 - OUT6RMIX Input 3 Source */
+ { 0x06DD, 0x0080 }, /* R1757 - OUT6RMIX Input 3 Volume */
+ { 0x06DE, 0x0000 }, /* R1758 - OUT6RMIX Input 4 Source */
+ { 0x06DF, 0x0080 }, /* R1759 - OUT6RMIX Input 4 Volume */
+ { 0x0700, 0x0000 }, /* R1792 - AIF1TX1MIX Input 1 Source */
+ { 0x0701, 0x0080 }, /* R1793 - AIF1TX1MIX Input 1 Volume */
+ { 0x0702, 0x0000 }, /* R1794 - AIF1TX1MIX Input 2 Source */
+ { 0x0703, 0x0080 }, /* R1795 - AIF1TX1MIX Input 2 Volume */
+ { 0x0704, 0x0000 }, /* R1796 - AIF1TX1MIX Input 3 Source */
+ { 0x0705, 0x0080 }, /* R1797 - AIF1TX1MIX Input 3 Volume */
+ { 0x0706, 0x0000 }, /* R1798 - AIF1TX1MIX Input 4 Source */
+ { 0x0707, 0x0080 }, /* R1799 - AIF1TX1MIX Input 4 Volume */
+ { 0x0708, 0x0000 }, /* R1800 - AIF1TX2MIX Input 1 Source */
+ { 0x0709, 0x0080 }, /* R1801 - AIF1TX2MIX Input 1 Volume */
+ { 0x070A, 0x0000 }, /* R1802 - AIF1TX2MIX Input 2 Source */
+ { 0x070B, 0x0080 }, /* R1803 - AIF1TX2MIX Input 2 Volume */
+ { 0x070C, 0x0000 }, /* R1804 - AIF1TX2MIX Input 3 Source */
+ { 0x070D, 0x0080 }, /* R1805 - AIF1TX2MIX Input 3 Volume */
+ { 0x070E, 0x0000 }, /* R1806 - AIF1TX2MIX Input 4 Source */
+ { 0x070F, 0x0080 }, /* R1807 - AIF1TX2MIX Input 4 Volume */
+ { 0x0710, 0x0000 }, /* R1808 - AIF1TX3MIX Input 1 Source */
+ { 0x0711, 0x0080 }, /* R1809 - AIF1TX3MIX Input 1 Volume */
+ { 0x0712, 0x0000 }, /* R1810 - AIF1TX3MIX Input 2 Source */
+ { 0x0713, 0x0080 }, /* R1811 - AIF1TX3MIX Input 2 Volume */
+ { 0x0714, 0x0000 }, /* R1812 - AIF1TX3MIX Input 3 Source */
+ { 0x0715, 0x0080 }, /* R1813 - AIF1TX3MIX Input 3 Volume */
+ { 0x0716, 0x0000 }, /* R1814 - AIF1TX3MIX Input 4 Source */
+ { 0x0717, 0x0080 }, /* R1815 - AIF1TX3MIX Input 4 Volume */
+ { 0x0718, 0x0000 }, /* R1816 - AIF1TX4MIX Input 1 Source */
+ { 0x0719, 0x0080 }, /* R1817 - AIF1TX4MIX Input 1 Volume */
+ { 0x071A, 0x0000 }, /* R1818 - AIF1TX4MIX Input 2 Source */
+ { 0x071B, 0x0080 }, /* R1819 - AIF1TX4MIX Input 2 Volume */
+ { 0x071C, 0x0000 }, /* R1820 - AIF1TX4MIX Input 3 Source */
+ { 0x071D, 0x0080 }, /* R1821 - AIF1TX4MIX Input 3 Volume */
+ { 0x071E, 0x0000 }, /* R1822 - AIF1TX4MIX Input 4 Source */
+ { 0x071F, 0x0080 }, /* R1823 - AIF1TX4MIX Input 4 Volume */
+ { 0x0720, 0x0000 }, /* R1824 - AIF1TX5MIX Input 1 Source */
+ { 0x0721, 0x0080 }, /* R1825 - AIF1TX5MIX Input 1 Volume */
+ { 0x0722, 0x0000 }, /* R1826 - AIF1TX5MIX Input 2 Source */
+ { 0x0723, 0x0080 }, /* R1827 - AIF1TX5MIX Input 2 Volume */
+ { 0x0724, 0x0000 }, /* R1828 - AIF1TX5MIX Input 3 Source */
+ { 0x0725, 0x0080 }, /* R1829 - AIF1TX5MIX Input 3 Volume */
+ { 0x0726, 0x0000 }, /* R1830 - AIF1TX5MIX Input 4 Source */
+ { 0x0727, 0x0080 }, /* R1831 - AIF1TX5MIX Input 4 Volume */
+ { 0x0728, 0x0000 }, /* R1832 - AIF1TX6MIX Input 1 Source */
+ { 0x0729, 0x0080 }, /* R1833 - AIF1TX6MIX Input 1 Volume */
+ { 0x072A, 0x0000 }, /* R1834 - AIF1TX6MIX Input 2 Source */
+ { 0x072B, 0x0080 }, /* R1835 - AIF1TX6MIX Input 2 Volume */
+ { 0x072C, 0x0000 }, /* R1836 - AIF1TX6MIX Input 3 Source */
+ { 0x072D, 0x0080 }, /* R1837 - AIF1TX6MIX Input 3 Volume */
+ { 0x072E, 0x0000 }, /* R1838 - AIF1TX6MIX Input 4 Source */
+ { 0x072F, 0x0080 }, /* R1839 - AIF1TX6MIX Input 4 Volume */
+ { 0x0730, 0x0000 }, /* R1840 - AIF1TX7MIX Input 1 Source */
+ { 0x0731, 0x0080 }, /* R1841 - AIF1TX7MIX Input 1 Volume */
+ { 0x0732, 0x0000 }, /* R1842 - AIF1TX7MIX Input 2 Source */
+ { 0x0733, 0x0080 }, /* R1843 - AIF1TX7MIX Input 2 Volume */
+ { 0x0734, 0x0000 }, /* R1844 - AIF1TX7MIX Input 3 Source */
+ { 0x0735, 0x0080 }, /* R1845 - AIF1TX7MIX Input 3 Volume */
+ { 0x0736, 0x0000 }, /* R1846 - AIF1TX7MIX Input 4 Source */
+ { 0x0737, 0x0080 }, /* R1847 - AIF1TX7MIX Input 4 Volume */
+ { 0x0738, 0x0000 }, /* R1848 - AIF1TX8MIX Input 1 Source */
+ { 0x0739, 0x0080 }, /* R1849 - AIF1TX8MIX Input 1 Volume */
+ { 0x073A, 0x0000 }, /* R1850 - AIF1TX8MIX Input 2 Source */
+ { 0x073B, 0x0080 }, /* R1851 - AIF1TX8MIX Input 2 Volume */
+ { 0x073C, 0x0000 }, /* R1852 - AIF1TX8MIX Input 3 Source */
+ { 0x073D, 0x0080 }, /* R1853 - AIF1TX8MIX Input 3 Volume */
+ { 0x073E, 0x0000 }, /* R1854 - AIF1TX8MIX Input 4 Source */
+ { 0x073F, 0x0080 }, /* R1855 - AIF1TX8MIX Input 4 Volume */
+ { 0x0740, 0x0000 }, /* R1856 - AIF2TX1MIX Input 1 Source */
+ { 0x0741, 0x0080 }, /* R1857 - AIF2TX1MIX Input 1 Volume */
+ { 0x0742, 0x0000 }, /* R1858 - AIF2TX1MIX Input 2 Source */
+ { 0x0743, 0x0080 }, /* R1859 - AIF2TX1MIX Input 2 Volume */
+ { 0x0744, 0x0000 }, /* R1860 - AIF2TX1MIX Input 3 Source */
+ { 0x0745, 0x0080 }, /* R1861 - AIF2TX1MIX Input 3 Volume */
+ { 0x0746, 0x0000 }, /* R1862 - AIF2TX1MIX Input 4 Source */
+ { 0x0747, 0x0080 }, /* R1863 - AIF2TX1MIX Input 4 Volume */
+ { 0x0748, 0x0000 }, /* R1864 - AIF2TX2MIX Input 1 Source */
+ { 0x0749, 0x0080 }, /* R1865 - AIF2TX2MIX Input 1 Volume */
+ { 0x074A, 0x0000 }, /* R1866 - AIF2TX2MIX Input 2 Source */
+ { 0x074B, 0x0080 }, /* R1867 - AIF2TX2MIX Input 2 Volume */
+ { 0x074C, 0x0000 }, /* R1868 - AIF2TX2MIX Input 3 Source */
+ { 0x074D, 0x0080 }, /* R1869 - AIF2TX2MIX Input 3 Volume */
+ { 0x074E, 0x0000 }, /* R1870 - AIF2TX2MIX Input 4 Source */
+ { 0x074F, 0x0080 }, /* R1871 - AIF2TX2MIX Input 4 Volume */
+ { 0x0780, 0x0000 }, /* R1920 - AIF3TX1MIX Input 1 Source */
+ { 0x0781, 0x0080 }, /* R1921 - AIF3TX1MIX Input 1 Volume */
+ { 0x0782, 0x0000 }, /* R1922 - AIF3TX1MIX Input 2 Source */
+ { 0x0783, 0x0080 }, /* R1923 - AIF3TX1MIX Input 2 Volume */
+ { 0x0784, 0x0000 }, /* R1924 - AIF3TX1MIX Input 3 Source */
+ { 0x0785, 0x0080 }, /* R1925 - AIF3TX1MIX Input 3 Volume */
+ { 0x0786, 0x0000 }, /* R1926 - AIF3TX1MIX Input 4 Source */
+ { 0x0787, 0x0080 }, /* R1927 - AIF3TX1MIX Input 4 Volume */
+ { 0x0788, 0x0000 }, /* R1928 - AIF3TX2MIX Input 1 Source */
+ { 0x0789, 0x0080 }, /* R1929 - AIF3TX2MIX Input 1 Volume */
+ { 0x078A, 0x0000 }, /* R1930 - AIF3TX2MIX Input 2 Source */
+ { 0x078B, 0x0080 }, /* R1931 - AIF3TX2MIX Input 2 Volume */
+ { 0x078C, 0x0000 }, /* R1932 - AIF3TX2MIX Input 3 Source */
+ { 0x078D, 0x0080 }, /* R1933 - AIF3TX2MIX Input 3 Volume */
+ { 0x078E, 0x0000 }, /* R1934 - AIF3TX2MIX Input 4 Source */
+ { 0x078F, 0x0080 }, /* R1935 - AIF3TX2MIX Input 4 Volume */
+ { 0x0880, 0x0000 }, /* R2176 - EQ1MIX Input 1 Source */
+ { 0x0881, 0x0080 }, /* R2177 - EQ1MIX Input 1 Volume */
+ { 0x0882, 0x0000 }, /* R2178 - EQ1MIX Input 2 Source */
+ { 0x0883, 0x0080 }, /* R2179 - EQ1MIX Input 2 Volume */
+ { 0x0884, 0x0000 }, /* R2180 - EQ1MIX Input 3 Source */
+ { 0x0885, 0x0080 }, /* R2181 - EQ1MIX Input 3 Volume */
+ { 0x0886, 0x0000 }, /* R2182 - EQ1MIX Input 4 Source */
+ { 0x0887, 0x0080 }, /* R2183 - EQ1MIX Input 4 Volume */
+ { 0x0888, 0x0000 }, /* R2184 - EQ2MIX Input 1 Source */
+ { 0x0889, 0x0080 }, /* R2185 - EQ2MIX Input 1 Volume */
+ { 0x088A, 0x0000 }, /* R2186 - EQ2MIX Input 2 Source */
+ { 0x088B, 0x0080 }, /* R2187 - EQ2MIX Input 2 Volume */
+ { 0x088C, 0x0000 }, /* R2188 - EQ2MIX Input 3 Source */
+ { 0x088D, 0x0080 }, /* R2189 - EQ2MIX Input 3 Volume */
+ { 0x088E, 0x0000 }, /* R2190 - EQ2MIX Input 4 Source */
+ { 0x088F, 0x0080 }, /* R2191 - EQ2MIX Input 4 Volume */
+ { 0x0890, 0x0000 }, /* R2192 - EQ3MIX Input 1 Source */
+ { 0x0891, 0x0080 }, /* R2193 - EQ3MIX Input 1 Volume */
+ { 0x0892, 0x0000 }, /* R2194 - EQ3MIX Input 2 Source */
+ { 0x0893, 0x0080 }, /* R2195 - EQ3MIX Input 2 Volume */
+ { 0x0894, 0x0000 }, /* R2196 - EQ3MIX Input 3 Source */
+ { 0x0895, 0x0080 }, /* R2197 - EQ3MIX Input 3 Volume */
+ { 0x0896, 0x0000 }, /* R2198 - EQ3MIX Input 4 Source */
+ { 0x0897, 0x0080 }, /* R2199 - EQ3MIX Input 4 Volume */
+ { 0x0898, 0x0000 }, /* R2200 - EQ4MIX Input 1 Source */
+ { 0x0899, 0x0080 }, /* R2201 - EQ4MIX Input 1 Volume */
+ { 0x089A, 0x0000 }, /* R2202 - EQ4MIX Input 2 Source */
+ { 0x089B, 0x0080 }, /* R2203 - EQ4MIX Input 2 Volume */
+ { 0x089C, 0x0000 }, /* R2204 - EQ4MIX Input 3 Source */
+ { 0x089D, 0x0080 }, /* R2205 - EQ4MIX Input 3 Volume */
+ { 0x089E, 0x0000 }, /* R2206 - EQ4MIX Input 4 Source */
+ { 0x089F, 0x0080 }, /* R2207 - EQ4MIX Input 4 Volume */
+ { 0x08C0, 0x0000 }, /* R2240 - DRC1LMIX Input 1 Source */
+ { 0x08C1, 0x0080 }, /* R2241 - DRC1LMIX Input 1 Volume */
+ { 0x08C2, 0x0000 }, /* R2242 - DRC1LMIX Input 2 Source */
+ { 0x08C3, 0x0080 }, /* R2243 - DRC1LMIX Input 2 Volume */
+ { 0x08C4, 0x0000 }, /* R2244 - DRC1LMIX Input 3 Source */
+ { 0x08C5, 0x0080 }, /* R2245 - DRC1LMIX Input 3 Volume */
+ { 0x08C6, 0x0000 }, /* R2246 - DRC1LMIX Input 4 Source */
+ { 0x08C7, 0x0080 }, /* R2247 - DRC1LMIX Input 4 Volume */
+ { 0x08C8, 0x0000 }, /* R2248 - DRC1RMIX Input 1 Source */
+ { 0x08C9, 0x0080 }, /* R2249 - DRC1RMIX Input 1 Volume */
+ { 0x08CA, 0x0000 }, /* R2250 - DRC1RMIX Input 2 Source */
+ { 0x08CB, 0x0080 }, /* R2251 - DRC1RMIX Input 2 Volume */
+ { 0x08CC, 0x0000 }, /* R2252 - DRC1RMIX Input 3 Source */
+ { 0x08CD, 0x0080 }, /* R2253 - DRC1RMIX Input 3 Volume */
+ { 0x08CE, 0x0000 }, /* R2254 - DRC1RMIX Input 4 Source */
+ { 0x08CF, 0x0080 }, /* R2255 - DRC1RMIX Input 4 Volume */
+ { 0x0900, 0x0000 }, /* R2304 - HPLP1MIX Input 1 Source */
+ { 0x0901, 0x0080 }, /* R2305 - HPLP1MIX Input 1 Volume */
+ { 0x0902, 0x0000 }, /* R2306 - HPLP1MIX Input 2 Source */
+ { 0x0903, 0x0080 }, /* R2307 - HPLP1MIX Input 2 Volume */
+ { 0x0904, 0x0000 }, /* R2308 - HPLP1MIX Input 3 Source */
+ { 0x0905, 0x0080 }, /* R2309 - HPLP1MIX Input 3 Volume */
+ { 0x0906, 0x0000 }, /* R2310 - HPLP1MIX Input 4 Source */
+ { 0x0907, 0x0080 }, /* R2311 - HPLP1MIX Input 4 Volume */
+ { 0x0908, 0x0000 }, /* R2312 - HPLP2MIX Input 1 Source */
+ { 0x0909, 0x0080 }, /* R2313 - HPLP2MIX Input 1 Volume */
+ { 0x090A, 0x0000 }, /* R2314 - HPLP2MIX Input 2 Source */
+ { 0x090B, 0x0080 }, /* R2315 - HPLP2MIX Input 2 Volume */
+ { 0x090C, 0x0000 }, /* R2316 - HPLP2MIX Input 3 Source */
+ { 0x090D, 0x0080 }, /* R2317 - HPLP2MIX Input 3 Volume */
+ { 0x090E, 0x0000 }, /* R2318 - HPLP2MIX Input 4 Source */
+ { 0x090F, 0x0080 }, /* R2319 - HPLP2MIX Input 4 Volume */
+ { 0x0910, 0x0000 }, /* R2320 - HPLP3MIX Input 1 Source */
+ { 0x0911, 0x0080 }, /* R2321 - HPLP3MIX Input 1 Volume */
+ { 0x0912, 0x0000 }, /* R2322 - HPLP3MIX Input 2 Source */
+ { 0x0913, 0x0080 }, /* R2323 - HPLP3MIX Input 2 Volume */
+ { 0x0914, 0x0000 }, /* R2324 - HPLP3MIX Input 3 Source */
+ { 0x0915, 0x0080 }, /* R2325 - HPLP3MIX Input 3 Volume */
+ { 0x0916, 0x0000 }, /* R2326 - HPLP3MIX Input 4 Source */
+ { 0x0917, 0x0080 }, /* R2327 - HPLP3MIX Input 4 Volume */
+ { 0x0918, 0x0000 }, /* R2328 - HPLP4MIX Input 1 Source */
+ { 0x0919, 0x0080 }, /* R2329 - HPLP4MIX Input 1 Volume */
+ { 0x091A, 0x0000 }, /* R2330 - HPLP4MIX Input 2 Source */
+ { 0x091B, 0x0080 }, /* R2331 - HPLP4MIX Input 2 Volume */
+ { 0x091C, 0x0000 }, /* R2332 - HPLP4MIX Input 3 Source */
+ { 0x091D, 0x0080 }, /* R2333 - HPLP4MIX Input 3 Volume */
+ { 0x091E, 0x0000 }, /* R2334 - HPLP4MIX Input 4 Source */
+ { 0x091F, 0x0080 }, /* R2335 - HPLP4MIX Input 4 Volume */
+ { 0x0940, 0x0000 }, /* R2368 - DSP1LMIX Input 1 Source */
+ { 0x0941, 0x0080 }, /* R2369 - DSP1LMIX Input 1 Volume */
+ { 0x0942, 0x0000 }, /* R2370 - DSP1LMIX Input 2 Source */
+ { 0x0943, 0x0080 }, /* R2371 - DSP1LMIX Input 2 Volume */
+ { 0x0944, 0x0000 }, /* R2372 - DSP1LMIX Input 3 Source */
+ { 0x0945, 0x0080 }, /* R2373 - DSP1LMIX Input 3 Volume */
+ { 0x0946, 0x0000 }, /* R2374 - DSP1LMIX Input 4 Source */
+ { 0x0947, 0x0080 }, /* R2375 - DSP1LMIX Input 4 Volume */
+ { 0x0948, 0x0000 }, /* R2376 - DSP1RMIX Input 1 Source */
+ { 0x0949, 0x0080 }, /* R2377 - DSP1RMIX Input 1 Volume */
+ { 0x094A, 0x0000 }, /* R2378 - DSP1RMIX Input 2 Source */
+ { 0x094B, 0x0080 }, /* R2379 - DSP1RMIX Input 2 Volume */
+ { 0x094C, 0x0000 }, /* R2380 - DSP1RMIX Input 3 Source */
+ { 0x094D, 0x0080 }, /* R2381 - DSP1RMIX Input 3 Volume */
+ { 0x094E, 0x0000 }, /* R2382 - DSP1RMIX Input 4 Source */
+ { 0x094F, 0x0080 }, /* R2383 - DSP1RMIX Input 4 Volume */
+ { 0x0950, 0x0000 }, /* R2384 - DSP1AUX1MIX Input 1 Source */
+ { 0x0958, 0x0000 }, /* R2392 - DSP1AUX2MIX Input 1 Source */
+ { 0x0960, 0x0000 }, /* R2400 - DSP1AUX3MIX Input 1 Source */
+ { 0x0968, 0x0000 }, /* R2408 - DSP1AUX4MIX Input 1 Source */
+ { 0x0970, 0x0000 }, /* R2416 - DSP1AUX5MIX Input 1 Source */
+ { 0x0978, 0x0000 }, /* R2424 - DSP1AUX6MIX Input 1 Source */
+ { 0x0980, 0x0000 }, /* R2432 - DSP2LMIX Input 1 Source */
+ { 0x0981, 0x0080 }, /* R2433 - DSP2LMIX Input 1 Volume */
+ { 0x0982, 0x0000 }, /* R2434 - DSP2LMIX Input 2 Source */
+ { 0x0983, 0x0080 }, /* R2435 - DSP2LMIX Input 2 Volume */
+ { 0x0984, 0x0000 }, /* R2436 - DSP2LMIX Input 3 Source */
+ { 0x0985, 0x0080 }, /* R2437 - DSP2LMIX Input 3 Volume */
+ { 0x0986, 0x0000 }, /* R2438 - DSP2LMIX Input 4 Source */
+ { 0x0987, 0x0080 }, /* R2439 - DSP2LMIX Input 4 Volume */
+ { 0x0988, 0x0000 }, /* R2440 - DSP2RMIX Input 1 Source */
+ { 0x0989, 0x0080 }, /* R2441 - DSP2RMIX Input 1 Volume */
+ { 0x098A, 0x0000 }, /* R2442 - DSP2RMIX Input 2 Source */
+ { 0x098B, 0x0080 }, /* R2443 - DSP2RMIX Input 2 Volume */
+ { 0x098C, 0x0000 }, /* R2444 - DSP2RMIX Input 3 Source */
+ { 0x098D, 0x0080 }, /* R2445 - DSP2RMIX Input 3 Volume */
+ { 0x098E, 0x0000 }, /* R2446 - DSP2RMIX Input 4 Source */
+ { 0x098F, 0x0080 }, /* R2447 - DSP2RMIX Input 4 Volume */
+ { 0x0990, 0x0000 }, /* R2448 - DSP2AUX1MIX Input 1 Source */
+ { 0x0998, 0x0000 }, /* R2456 - DSP2AUX2MIX Input 1 Source */
+ { 0x09A0, 0x0000 }, /* R2464 - DSP2AUX3MIX Input 1 Source */
+ { 0x09A8, 0x0000 }, /* R2472 - DSP2AUX4MIX Input 1 Source */
+ { 0x09B0, 0x0000 }, /* R2480 - DSP2AUX5MIX Input 1 Source */
+ { 0x09B8, 0x0000 }, /* R2488 - DSP2AUX6MIX Input 1 Source */
+ { 0x09C0, 0x0000 }, /* R2496 - DSP3LMIX Input 1 Source */
+ { 0x09C1, 0x0080 }, /* R2497 - DSP3LMIX Input 1 Volume */
+ { 0x09C2, 0x0000 }, /* R2498 - DSP3LMIX Input 2 Source */
+ { 0x09C3, 0x0080 }, /* R2499 - DSP3LMIX Input 2 Volume */
+ { 0x09C4, 0x0000 }, /* R2500 - DSP3LMIX Input 3 Source */
+ { 0x09C5, 0x0080 }, /* R2501 - DSP3LMIX Input 3 Volume */
+ { 0x09C6, 0x0000 }, /* R2502 - DSP3LMIX Input 4 Source */
+ { 0x09C7, 0x0080 }, /* R2503 - DSP3LMIX Input 4 Volume */
+ { 0x09C8, 0x0000 }, /* R2504 - DSP3RMIX Input 1 Source */
+ { 0x09C9, 0x0080 }, /* R2505 - DSP3RMIX Input 1 Volume */
+ { 0x09CA, 0x0000 }, /* R2506 - DSP3RMIX Input 2 Source */
+ { 0x09CB, 0x0080 }, /* R2507 - DSP3RMIX Input 2 Volume */
+ { 0x09CC, 0x0000 }, /* R2508 - DSP3RMIX Input 3 Source */
+ { 0x09CD, 0x0080 }, /* R2509 - DSP3RMIX Input 3 Volume */
+ { 0x09CE, 0x0000 }, /* R2510 - DSP3RMIX Input 4 Source */
+ { 0x09CF, 0x0080 }, /* R2511 - DSP3RMIX Input 4 Volume */
+ { 0x09D0, 0x0000 }, /* R2512 - DSP3AUX1MIX Input 1 Source */
+ { 0x09D8, 0x0000 }, /* R2520 - DSP3AUX2MIX Input 1 Source */
+ { 0x09E0, 0x0000 }, /* R2528 - DSP3AUX3MIX Input 1 Source */
+ { 0x09E8, 0x0000 }, /* R2536 - DSP3AUX4MIX Input 1 Source */
+ { 0x09F0, 0x0000 }, /* R2544 - DSP3AUX5MIX Input 1 Source */
+ { 0x09F8, 0x0000 }, /* R2552 - DSP3AUX6MIX Input 1 Source */
+ { 0x0A80, 0x0000 }, /* R2688 - ASRC1LMIX Input 1 Source */
+ { 0x0A88, 0x0000 }, /* R2696 - ASRC1RMIX Input 1 Source */
+ { 0x0A90, 0x0000 }, /* R2704 - ASRC2LMIX Input 1 Source */
+ { 0x0A98, 0x0000 }, /* R2712 - ASRC2RMIX Input 1 Source */
+ { 0x0B00, 0x0000 }, /* R2816 - ISRC1DEC1MIX Input 1 Source */
+ { 0x0B08, 0x0000 }, /* R2824 - ISRC1DEC2MIX Input 1 Source */
+ { 0x0B10, 0x0000 }, /* R2832 - ISRC1DEC3MIX Input 1 Source */
+ { 0x0B18, 0x0000 }, /* R2840 - ISRC1DEC4MIX Input 1 Source */
+ { 0x0B20, 0x0000 }, /* R2848 - ISRC1INT1MIX Input 1 Source */
+ { 0x0B28, 0x0000 }, /* R2856 - ISRC1INT2MIX Input 1 Source */
+ { 0x0B30, 0x0000 }, /* R2864 - ISRC1INT3MIX Input 1 Source */
+ { 0x0B38, 0x0000 }, /* R2872 - ISRC1INT4MIX Input 1 Source */
+ { 0x0B40, 0x0000 }, /* R2880 - ISRC2DEC1MIX Input 1 Source */
+ { 0x0B48, 0x0000 }, /* R2888 - ISRC2DEC2MIX Input 1 Source */
+ { 0x0B50, 0x0000 }, /* R2896 - ISRC2DEC3MIX Input 1 Source */
+ { 0x0B58, 0x0000 }, /* R2904 - ISRC2DEC4MIX Input 1 Source */
+ { 0x0B60, 0x0000 }, /* R2912 - ISRC2INT1MIX Input 1 Source */
+ { 0x0B68, 0x0000 }, /* R2920 - ISRC2INT2MIX Input 1 Source */
+ { 0x0B70, 0x0000 }, /* R2928 - ISRC2INT3MIX Input 1 Source */
+ { 0x0B78, 0x0000 }, /* R2936 - ISRC2INT4MIX Input 1 Source */
+ { 0x0C00, 0xA001 }, /* R3072 - GPIO CTRL 1 */
+ { 0x0C01, 0xA001 }, /* R3073 - GPIO CTRL 2 */
+ { 0x0C02, 0xA001 }, /* R3074 - GPIO CTRL 3 */
+ { 0x0C03, 0xA001 }, /* R3075 - GPIO CTRL 4 */
+ { 0x0C04, 0xA001 }, /* R3076 - GPIO CTRL 5 */
+ { 0x0C05, 0xA001 }, /* R3077 - GPIO CTRL 6 */
+ { 0x0C23, 0x4003 }, /* R3107 - Misc Pad Ctrl 1 */
+ { 0x0C24, 0x0000 }, /* R3108 - Misc Pad Ctrl 2 */
+ { 0x0C25, 0x0000 }, /* R3109 - Misc Pad Ctrl 3 */
+ { 0x0C26, 0x0000 }, /* R3110 - Misc Pad Ctrl 4 */
+ { 0x0C27, 0x0000 }, /* R3111 - Misc Pad Ctrl 5 */
+ { 0x0C28, 0x0000 }, /* R3112 - Misc GPIO 1 */
+ { 0x0D00, 0x0000 }, /* R3328 - Interrupt Status 1 */
+ { 0x0D01, 0x0000 }, /* R3329 - Interrupt Status 2 */
+ { 0x0D02, 0x0000 }, /* R3330 - Interrupt Status 3 */
+ { 0x0D03, 0x0000 }, /* R3331 - Interrupt Status 4 */
+ { 0x0D04, 0x0000 }, /* R3332 - Interrupt Raw Status 2 */
+ { 0x0D05, 0x0000 }, /* R3333 - Interrupt Raw Status 3 */
+ { 0x0D06, 0x0000 }, /* R3334 - Interrupt Raw Status 4 */
+ { 0x0D07, 0xFFFF }, /* R3335 - Interrupt Status 1 Mask */
+ { 0x0D08, 0xFFFF }, /* R3336 - Interrupt Status 2 Mask */
+ { 0x0D09, 0xFFFF }, /* R3337 - Interrupt Status 3 Mask */
+ { 0x0D0A, 0xFFFF }, /* R3338 - Interrupt Status 4 Mask */
+ { 0x0D1F, 0x0000 }, /* R3359 - Interrupt Control */
+ { 0x0D20, 0xFFFF }, /* R3360 - IRQ Debounce 1 */
+ { 0x0D21, 0xFFFF }, /* R3361 - IRQ Debounce 2 */
+ { 0x0E00, 0x0000 }, /* R3584 - FX_Ctrl */
+ { 0x0E10, 0x6318 }, /* R3600 - EQ1_1 */
+ { 0x0E11, 0x6300 }, /* R3601 - EQ1_2 */
+ { 0x0E12, 0x0FC8 }, /* R3602 - EQ1_3 */
+ { 0x0E13, 0x03FE }, /* R3603 - EQ1_4 */
+ { 0x0E14, 0x00E0 }, /* R3604 - EQ1_5 */
+ { 0x0E15, 0x1EC4 }, /* R3605 - EQ1_6 */
+ { 0x0E16, 0xF136 }, /* R3606 - EQ1_7 */
+ { 0x0E17, 0x0409 }, /* R3607 - EQ1_8 */
+ { 0x0E18, 0x04CC }, /* R3608 - EQ1_9 */
+ { 0x0E19, 0x1C9B }, /* R3609 - EQ1_10 */
+ { 0x0E1A, 0xF337 }, /* R3610 - EQ1_11 */
+ { 0x0E1B, 0x040B }, /* R3611 - EQ1_12 */
+ { 0x0E1C, 0x0CBB }, /* R3612 - EQ1_13 */
+ { 0x0E1D, 0x16F8 }, /* R3613 - EQ1_14 */
+ { 0x0E1E, 0xF7D9 }, /* R3614 - EQ1_15 */
+ { 0x0E1F, 0x040A }, /* R3615 - EQ1_16 */
+ { 0x0E20, 0x1F14 }, /* R3616 - EQ1_17 */
+ { 0x0E21, 0x058C }, /* R3617 - EQ1_18 */
+ { 0x0E22, 0x0563 }, /* R3618 - EQ1_19 */
+ { 0x0E23, 0x4000 }, /* R3619 - EQ1_20 */
+ { 0x0E26, 0x6318 }, /* R3622 - EQ2_1 */
+ { 0x0E27, 0x6300 }, /* R3623 - EQ2_2 */
+ { 0x0E28, 0x0FC8 }, /* R3624 - EQ2_3 */
+ { 0x0E29, 0x03FE }, /* R3625 - EQ2_4 */
+ { 0x0E2A, 0x00E0 }, /* R3626 - EQ2_5 */
+ { 0x0E2B, 0x1EC4 }, /* R3627 - EQ2_6 */
+ { 0x0E2C, 0xF136 }, /* R3628 - EQ2_7 */
+ { 0x0E2D, 0x0409 }, /* R3629 - EQ2_8 */
+ { 0x0E2E, 0x04CC }, /* R3630 - EQ2_9 */
+ { 0x0E2F, 0x1C9B }, /* R3631 - EQ2_10 */
+ { 0x0E30, 0xF337 }, /* R3632 - EQ2_11 */
+ { 0x0E31, 0x040B }, /* R3633 - EQ2_12 */
+ { 0x0E32, 0x0CBB }, /* R3634 - EQ2_13 */
+ { 0x0E33, 0x16F8 }, /* R3635 - EQ2_14 */
+ { 0x0E34, 0xF7D9 }, /* R3636 - EQ2_15 */
+ { 0x0E35, 0x040A }, /* R3637 - EQ2_16 */
+ { 0x0E36, 0x1F14 }, /* R3638 - EQ2_17 */
+ { 0x0E37, 0x058C }, /* R3639 - EQ2_18 */
+ { 0x0E38, 0x0563 }, /* R3640 - EQ2_19 */
+ { 0x0E39, 0x4000 }, /* R3641 - EQ2_20 */
+ { 0x0E3C, 0x6318 }, /* R3644 - EQ3_1 */
+ { 0x0E3D, 0x6300 }, /* R3645 - EQ3_2 */
+ { 0x0E3E, 0x0FC8 }, /* R3646 - EQ3_3 */
+ { 0x0E3F, 0x03FE }, /* R3647 - EQ3_4 */
+ { 0x0E40, 0x00E0 }, /* R3648 - EQ3_5 */
+ { 0x0E41, 0x1EC4 }, /* R3649 - EQ3_6 */
+ { 0x0E42, 0xF136 }, /* R3650 - EQ3_7 */
+ { 0x0E43, 0x0409 }, /* R3651 - EQ3_8 */
+ { 0x0E44, 0x04CC }, /* R3652 - EQ3_9 */
+ { 0x0E45, 0x1C9B }, /* R3653 - EQ3_10 */
+ { 0x0E46, 0xF337 }, /* R3654 - EQ3_11 */
+ { 0x0E47, 0x040B }, /* R3655 - EQ3_12 */
+ { 0x0E48, 0x0CBB }, /* R3656 - EQ3_13 */
+ { 0x0E49, 0x16F8 }, /* R3657 - EQ3_14 */
+ { 0x0E4A, 0xF7D9 }, /* R3658 - EQ3_15 */
+ { 0x0E4B, 0x040A }, /* R3659 - EQ3_16 */
+ { 0x0E4C, 0x1F14 }, /* R3660 - EQ3_17 */
+ { 0x0E4D, 0x058C }, /* R3661 - EQ3_18 */
+ { 0x0E4E, 0x0563 }, /* R3662 - EQ3_19 */
+ { 0x0E4F, 0x4000 }, /* R3663 - EQ3_20 */
+ { 0x0E52, 0x6318 }, /* R3666 - EQ4_1 */
+ { 0x0E53, 0x6300 }, /* R3667 - EQ4_2 */
+ { 0x0E54, 0x0FC8 }, /* R3668 - EQ4_3 */
+ { 0x0E55, 0x03FE }, /* R3669 - EQ4_4 */
+ { 0x0E56, 0x00E0 }, /* R3670 - EQ4_5 */
+ { 0x0E57, 0x1EC4 }, /* R3671 - EQ4_6 */
+ { 0x0E58, 0xF136 }, /* R3672 - EQ4_7 */
+ { 0x0E59, 0x0409 }, /* R3673 - EQ4_8 */
+ { 0x0E5A, 0x04CC }, /* R3674 - EQ4_9 */
+ { 0x0E5B, 0x1C9B }, /* R3675 - EQ4_10 */
+ { 0x0E5C, 0xF337 }, /* R3676 - EQ4_11 */
+ { 0x0E5D, 0x040B }, /* R3677 - EQ4_12 */
+ { 0x0E5E, 0x0CBB }, /* R3678 - EQ4_13 */
+ { 0x0E5F, 0x16F8 }, /* R3679 - EQ4_14 */
+ { 0x0E60, 0xF7D9 }, /* R3680 - EQ4_15 */
+ { 0x0E61, 0x040A }, /* R3681 - EQ4_16 */
+ { 0x0E62, 0x1F14 }, /* R3682 - EQ4_17 */
+ { 0x0E63, 0x058C }, /* R3683 - EQ4_18 */
+ { 0x0E64, 0x0563 }, /* R3684 - EQ4_19 */
+ { 0x0E65, 0x4000 }, /* R3685 - EQ4_20 */
+ { 0x0E80, 0x0018 }, /* R3712 - DRC1 ctrl1 */
+ { 0x0E81, 0x0933 }, /* R3713 - DRC1 ctrl2 */
+ { 0x0E82, 0x0018 }, /* R3714 - DRC1 ctrl3 */
+ { 0x0E83, 0x0000 }, /* R3715 - DRC1 ctrl4 */
+ { 0x0E84, 0x0000 }, /* R3716 - DRC1 ctrl5 */
+ { 0x0EC0, 0x0000 }, /* R3776 - HPLPF1_1 */
+ { 0x0EC1, 0x0000 }, /* R3777 - HPLPF1_2 */
+ { 0x0EC4, 0x0000 }, /* R3780 - HPLPF2_1 */
+ { 0x0EC5, 0x0000 }, /* R3781 - HPLPF2_2 */
+ { 0x0EC8, 0x0000 }, /* R3784 - HPLPF3_1 */
+ { 0x0EC9, 0x0000 }, /* R3785 - HPLPF3_2 */
+ { 0x0ECC, 0x0000 }, /* R3788 - HPLPF4_1 */
+ { 0x0ECD, 0x0000 }, /* R3789 - HPLPF4_2 */
+};
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
new file mode 100644
index 000000000000..b9c185ce64e4
--- /dev/null
+++ b/sound/soc/codecs/wm5100.c
@@ -0,0 +1,2766 @@
+/*
+ * wm5100.c -- WM5100 ALSA SoC Audio driver
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/gcd.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
+#include <linux/regulator/fixed.h>
+#include <linux/slab.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/initval.h>
+#include <sound/tlv.h>
+#include <sound/wm5100.h>
+
+#include "wm5100.h"
+
+#define WM5100_NUM_CORE_SUPPLIES 2
+static const char *wm5100_core_supply_names[WM5100_NUM_CORE_SUPPLIES] = {
+ "DBVDD1",
+ "LDOVDD", /* If DCVDD is supplied externally specify as LDOVDD */
+};
+
+#define WM5100_AIFS 3
+#define WM5100_SYNC_SRS 3
+
+struct wm5100_fll {
+ int fref;
+ int fout;
+ int src;
+ struct completion lock;
+};
+
+/* codec private data */
+struct wm5100_priv {
+ struct device *dev;
+ struct regmap *regmap;
+ struct snd_soc_codec *codec;
+
+ struct regulator_bulk_data core_supplies[WM5100_NUM_CORE_SUPPLIES];
+
+ int rev;
+
+ int sysclk;
+ int asyncclk;
+
+ bool aif_async[WM5100_AIFS];
+ bool aif_symmetric[WM5100_AIFS];
+ int sr_ref[WM5100_SYNC_SRS];
+
+ bool out_ena[2];
+
+ struct snd_soc_jack *jack;
+ bool jack_detecting;
+ bool jack_mic;
+ int jack_mode;
+ int jack_flips;
+
+ struct wm5100_fll fll[2];
+
+ struct wm5100_pdata pdata;
+
+#ifdef CONFIG_GPIOLIB
+ struct gpio_chip gpio_chip;
+#endif
+};
+
+static int wm5100_sr_code[] = {
+ 0,
+ 12000,
+ 24000,
+ 48000,
+ 96000,
+ 192000,
+ 384000,
+ 768000,
+ 0,
+ 11025,
+ 22050,
+ 44100,
+ 88200,
+ 176400,
+ 352800,
+ 705600,
+ 4000,
+ 8000,
+ 16000,
+ 32000,
+ 64000,
+ 128000,
+ 256000,
+ 512000,
+};
+
+static int wm5100_sr_regs[WM5100_SYNC_SRS] = {
+ WM5100_CLOCKING_4,
+ WM5100_CLOCKING_5,
+ WM5100_CLOCKING_6,
+};
+
+static int wm5100_alloc_sr(struct snd_soc_codec *codec, int rate)
+{
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ int sr_code, sr_free, i;
+
+ for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+ if (wm5100_sr_code[i] == rate)
+ break;
+ if (i == ARRAY_SIZE(wm5100_sr_code)) {
+ dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
+ return -EINVAL;
+ }
+ sr_code = i;
+
+ if ((wm5100->sysclk % rate) == 0) {
+ /* Is this rate already in use? */
+ sr_free = -1;
+ for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
+ if (!wm5100->sr_ref[i] && sr_free == -1) {
+ sr_free = i;
+ continue;
+ }
+ if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
+ WM5100_SAMPLE_RATE_1_MASK) == sr_code)
+ break;
+ }
+
+ if (i < ARRAY_SIZE(wm5100_sr_regs)) {
+ wm5100->sr_ref[i]++;
+ dev_dbg(codec->dev, "SR %dHz, slot %d, ref %d\n",
+ rate, i, wm5100->sr_ref[i]);
+ return i;
+ }
+
+ if (sr_free == -1) {
+ dev_err(codec->dev, "All SR slots already in use\n");
+ return -EBUSY;
+ }
+
+ dev_dbg(codec->dev, "Allocating SR slot %d for %dHz\n",
+ sr_free, rate);
+ wm5100->sr_ref[sr_free]++;
+ snd_soc_update_bits(codec, wm5100_sr_regs[sr_free],
+ WM5100_SAMPLE_RATE_1_MASK,
+ sr_code);
+
+ return sr_free;
+
+ } else {
+ dev_err(codec->dev,
+ "SR %dHz incompatible with %dHz SYSCLK and %dHz ASYNCCLK\n",
+ rate, wm5100->sysclk, wm5100->asyncclk);
+ return -EINVAL;
+ }
+}
+
+static void wm5100_free_sr(struct snd_soc_codec *codec, int rate)
+{
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ int i, sr_code;
+
+ for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+ if (wm5100_sr_code[i] == rate)
+ break;
+ if (i == ARRAY_SIZE(wm5100_sr_code)) {
+ dev_err(codec->dev, "Unsupported sample rate: %dHz\n", rate);
+ return;
+ }
+ sr_code = wm5100_sr_code[i];
+
+ for (i = 0; i < ARRAY_SIZE(wm5100_sr_regs); i++) {
+ if (!wm5100->sr_ref[i])
+ continue;
+
+ if ((snd_soc_read(codec, wm5100_sr_regs[i]) &
+ WM5100_SAMPLE_RATE_1_MASK) == sr_code)
+ break;
+ }
+ if (i < ARRAY_SIZE(wm5100_sr_regs)) {
+ wm5100->sr_ref[i]--;
+ dev_dbg(codec->dev, "Dereference SR %dHz, count now %d\n",
+ rate, wm5100->sr_ref[i]);
+ } else {
+ dev_warn(codec->dev, "Freeing unreferenced sample rate %dHz\n",
+ rate);
+ }
+}
+
+static int wm5100_reset(struct wm5100_priv *wm5100)
+{
+ if (wm5100->pdata.reset) {
+ gpio_set_value_cansleep(wm5100->pdata.reset, 0);
+ gpio_set_value_cansleep(wm5100->pdata.reset, 1);
+
+ return 0;
+ } else {
+ return regmap_write(wm5100->regmap, WM5100_SOFTWARE_RESET, 0);
+ }
+}
+
+static DECLARE_TLV_DB_SCALE(in_tlv, -6300, 100, 0);
+static DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static DECLARE_TLV_DB_SCALE(mixer_tlv, -3200, 100, 0);
+static DECLARE_TLV_DB_SCALE(out_tlv, -6400, 100, 0);
+static DECLARE_TLV_DB_SCALE(digital_tlv, -6400, 50, 0);
+
+static const char *wm5100_mixer_texts[] = {
+ "None",
+ "Tone Generator 1",
+ "Tone Generator 2",
+ "AEC loopback",
+ "IN1L",
+ "IN1R",
+ "IN2L",
+ "IN2R",
+ "IN3L",
+ "IN3R",
+ "IN4L",
+ "IN4R",
+ "AIF1RX1",
+ "AIF1RX2",
+ "AIF1RX3",
+ "AIF1RX4",
+ "AIF1RX5",
+ "AIF1RX6",
+ "AIF1RX7",
+ "AIF1RX8",
+ "AIF2RX1",
+ "AIF2RX2",
+ "AIF3RX1",
+ "AIF3RX2",
+ "EQ1",
+ "EQ2",
+ "EQ3",
+ "EQ4",
+ "DRC1L",
+ "DRC1R",
+ "LHPF1",
+ "LHPF2",
+ "LHPF3",
+ "LHPF4",
+ "DSP1.1",
+ "DSP1.2",
+ "DSP1.3",
+ "DSP1.4",
+ "DSP1.5",
+ "DSP1.6",
+ "DSP2.1",
+ "DSP2.2",
+ "DSP2.3",
+ "DSP2.4",
+ "DSP2.5",
+ "DSP2.6",
+ "DSP3.1",
+ "DSP3.2",
+ "DSP3.3",
+ "DSP3.4",
+ "DSP3.5",
+ "DSP3.6",
+ "ASRC1L",
+ "ASRC1R",
+ "ASRC2L",
+ "ASRC2R",
+ "ISRC1INT1",
+ "ISRC1INT2",
+ "ISRC1INT3",
+ "ISRC1INT4",
+ "ISRC2INT1",
+ "ISRC2INT2",
+ "ISRC2INT3",
+ "ISRC2INT4",
+ "ISRC1DEC1",
+ "ISRC1DEC2",
+ "ISRC1DEC3",
+ "ISRC1DEC4",
+ "ISRC2DEC1",
+ "ISRC2DEC2",
+ "ISRC2DEC3",
+ "ISRC2DEC4",
+};
+
+static int wm5100_mixer_values[] = {
+ 0x00,
+ 0x04, /* Tone */
+ 0x05,
+ 0x08, /* AEC */
+ 0x10, /* Input */
+ 0x11,
+ 0x12,
+ 0x13,
+ 0x14,
+ 0x15,
+ 0x16,
+ 0x17,
+ 0x20, /* AIF */
+ 0x21,
+ 0x22,
+ 0x23,
+ 0x24,
+ 0x25,
+ 0x26,
+ 0x27,
+ 0x28,
+ 0x29,
+ 0x30, /* AIF3 - check */
+ 0x31,
+ 0x50, /* EQ */
+ 0x51,
+ 0x52,
+ 0x53,
+ 0x54,
+ 0x58, /* DRC */
+ 0x59,
+ 0x60, /* LHPF1 */
+ 0x61, /* LHPF2 */
+ 0x62, /* LHPF3 */
+ 0x63, /* LHPF4 */
+ 0x68, /* DSP1 */
+ 0x69,
+ 0x6a,
+ 0x6b,
+ 0x6c,
+ 0x6d,
+ 0x70, /* DSP2 */
+ 0x71,
+ 0x72,
+ 0x73,
+ 0x74,
+ 0x75,
+ 0x78, /* DSP3 */
+ 0x79,
+ 0x7a,
+ 0x7b,
+ 0x7c,
+ 0x7d,
+ 0x90, /* ASRC1 */
+ 0x91,
+ 0x92, /* ASRC2 */
+ 0x93,
+ 0xa0, /* ISRC1DEC1 */
+ 0xa1,
+ 0xa2,
+ 0xa3,
+ 0xa4, /* ISRC1INT1 */
+ 0xa5,
+ 0xa6,
+ 0xa7,
+ 0xa8, /* ISRC2DEC1 */
+ 0xa9,
+ 0xaa,
+ 0xab,
+ 0xac, /* ISRC2INT1 */
+ 0xad,
+ 0xae,
+ 0xaf,
+};
+
+#define WM5100_MIXER_CONTROLS(name, base) \
+ SOC_SINGLE_TLV(name " Input 1 Volume", base + 1 , \
+ WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 2 Volume", base + 3 , \
+ WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 3 Volume", base + 5 , \
+ WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv), \
+ SOC_SINGLE_TLV(name " Input 4 Volume", base + 7 , \
+ WM5100_MIXER_VOL_SHIFT, 80, 0, mixer_tlv)
+
+#define WM5100_MUX_ENUM_DECL(name, reg) \
+ SOC_VALUE_ENUM_SINGLE_DECL(name, reg, 0, 0xff, \
+ wm5100_mixer_texts, wm5100_mixer_values)
+
+#define WM5100_MUX_CTL_DECL(name) \
+ const struct snd_kcontrol_new name##_mux = \
+ SOC_DAPM_VALUE_ENUM("Route", name##_enum)
+
+#define WM5100_MIXER_ENUMS(name, base_reg) \
+ static WM5100_MUX_ENUM_DECL(name##_in1_enum, base_reg); \
+ static WM5100_MUX_ENUM_DECL(name##_in2_enum, base_reg + 2); \
+ static WM5100_MUX_ENUM_DECL(name##_in3_enum, base_reg + 4); \
+ static WM5100_MUX_ENUM_DECL(name##_in4_enum, base_reg + 6); \
+ static WM5100_MUX_CTL_DECL(name##_in1); \
+ static WM5100_MUX_CTL_DECL(name##_in2); \
+ static WM5100_MUX_CTL_DECL(name##_in3); \
+ static WM5100_MUX_CTL_DECL(name##_in4)
+
+WM5100_MIXER_ENUMS(HPOUT1L, WM5100_OUT1LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT1R, WM5100_OUT1RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT2L, WM5100_OUT2LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT2R, WM5100_OUT2RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT3L, WM5100_OUT3LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(HPOUT3R, WM5100_OUT3RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(SPKOUTL, WM5100_OUT4LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKOUTR, WM5100_OUT4RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT1L, WM5100_OUT5LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT1R, WM5100_OUT5RMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT2L, WM5100_OUT6LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(SPKDAT2R, WM5100_OUT6RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(PWM1, WM5100_PWM1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(PWM2, WM5100_PWM1MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF1TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX3, WM5100_AIF1TX3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX4, WM5100_AIF1TX4MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX5, WM5100_AIF1TX5MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX6, WM5100_AIF1TX6MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX7, WM5100_AIF1TX7MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF1TX8, WM5100_AIF1TX8MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF2TX1, WM5100_AIF2TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF2TX2, WM5100_AIF2TX2MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(AIF3TX1, WM5100_AIF1TX1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(AIF3TX2, WM5100_AIF1TX2MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(EQ1, WM5100_EQ1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ2, WM5100_EQ2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ3, WM5100_EQ3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(EQ4, WM5100_EQ4MIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(DRC1L, WM5100_DRC1LMIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(DRC1R, WM5100_DRC1RMIX_INPUT_1_SOURCE);
+
+WM5100_MIXER_ENUMS(LHPF1, WM5100_HPLP1MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF2, WM5100_HPLP2MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF3, WM5100_HPLP3MIX_INPUT_1_SOURCE);
+WM5100_MIXER_ENUMS(LHPF4, WM5100_HPLP4MIX_INPUT_1_SOURCE);
+
+#define WM5100_MUX(name, ctrl) \
+ SND_SOC_DAPM_VALUE_MUX(name, SND_SOC_NOPM, 0, 0, ctrl)
+
+#define WM5100_MIXER_WIDGETS(name, name_str) \
+ WM5100_MUX(name_str " Input 1", &name##_in1_mux), \
+ WM5100_MUX(name_str " Input 2", &name##_in2_mux), \
+ WM5100_MUX(name_str " Input 3", &name##_in3_mux), \
+ WM5100_MUX(name_str " Input 4", &name##_in4_mux), \
+ SND_SOC_DAPM_MIXER(name_str " Mixer", SND_SOC_NOPM, 0, 0, NULL, 0)
+
+#define WM5100_MIXER_INPUT_ROUTES(name) \
+ { name, "Tone Generator 1", "Tone Generator 1" }, \
+ { name, "Tone Generator 2", "Tone Generator 2" }, \
+ { name, "IN1L", "IN1L PGA" }, \
+ { name, "IN1R", "IN1R PGA" }, \
+ { name, "IN2L", "IN2L PGA" }, \
+ { name, "IN2R", "IN2R PGA" }, \
+ { name, "IN3L", "IN3L PGA" }, \
+ { name, "IN3R", "IN3R PGA" }, \
+ { name, "IN4L", "IN4L PGA" }, \
+ { name, "IN4R", "IN4R PGA" }, \
+ { name, "AIF1RX1", "AIF1RX1" }, \
+ { name, "AIF1RX2", "AIF1RX2" }, \
+ { name, "AIF1RX3", "AIF1RX3" }, \
+ { name, "AIF1RX4", "AIF1RX4" }, \
+ { name, "AIF1RX5", "AIF1RX5" }, \
+ { name, "AIF1RX6", "AIF1RX6" }, \
+ { name, "AIF1RX7", "AIF1RX7" }, \
+ { name, "AIF1RX8", "AIF1RX8" }, \
+ { name, "AIF2RX1", "AIF2RX1" }, \
+ { name, "AIF2RX2", "AIF2RX2" }, \
+ { name, "AIF3RX1", "AIF3RX1" }, \
+ { name, "AIF3RX2", "AIF3RX2" }, \
+ { name, "EQ1", "EQ1" }, \
+ { name, "EQ2", "EQ2" }, \
+ { name, "EQ3", "EQ3" }, \
+ { name, "EQ4", "EQ4" }, \
+ { name, "DRC1L", "DRC1L" }, \
+ { name, "DRC1R", "DRC1R" }, \
+ { name, "LHPF1", "LHPF1" }, \
+ { name, "LHPF2", "LHPF2" }, \
+ { name, "LHPF3", "LHPF3" }, \
+ { name, "LHPF4", "LHPF4" }
+
+#define WM5100_MIXER_ROUTES(widget, name) \
+ { widget, NULL, name " Mixer" }, \
+ { name " Mixer", NULL, name " Input 1" }, \
+ { name " Mixer", NULL, name " Input 2" }, \
+ { name " Mixer", NULL, name " Input 3" }, \
+ { name " Mixer", NULL, name " Input 4" }, \
+ WM5100_MIXER_INPUT_ROUTES(name " Input 1"), \
+ WM5100_MIXER_INPUT_ROUTES(name " Input 2"), \
+ WM5100_MIXER_INPUT_ROUTES(name " Input 3"), \
+ WM5100_MIXER_INPUT_ROUTES(name " Input 4")
+
+static const char *wm5100_lhpf_mode_text[] = {
+ "Low-pass", "High-pass"
+};
+
+static const struct soc_enum wm5100_lhpf1_mode =
+ SOC_ENUM_SINGLE(WM5100_HPLPF1_1, WM5100_LHPF1_MODE_SHIFT, 2,
+ wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf2_mode =
+ SOC_ENUM_SINGLE(WM5100_HPLPF2_1, WM5100_LHPF2_MODE_SHIFT, 2,
+ wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf3_mode =
+ SOC_ENUM_SINGLE(WM5100_HPLPF3_1, WM5100_LHPF3_MODE_SHIFT, 2,
+ wm5100_lhpf_mode_text);
+
+static const struct soc_enum wm5100_lhpf4_mode =
+ SOC_ENUM_SINGLE(WM5100_HPLPF4_1, WM5100_LHPF4_MODE_SHIFT, 2,
+ wm5100_lhpf_mode_text);
+
+static const struct snd_kcontrol_new wm5100_snd_controls[] = {
+SOC_SINGLE("IN1 High Performance Switch", WM5100_IN1L_CONTROL,
+ WM5100_IN1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN2 High Performance Switch", WM5100_IN2L_CONTROL,
+ WM5100_IN2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN3 High Performance Switch", WM5100_IN3L_CONTROL,
+ WM5100_IN3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("IN4 High Performance Switch", WM5100_IN4L_CONTROL,
+ WM5100_IN4_OSR_SHIFT, 1, 0),
+
+/* Only applicable for analogue inputs */
+SOC_DOUBLE_R_TLV("IN1 Volume", WM5100_IN1L_CONTROL, WM5100_IN1R_CONTROL,
+ WM5100_IN1L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN2 Volume", WM5100_IN2L_CONTROL, WM5100_IN2R_CONTROL,
+ WM5100_IN2L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN3 Volume", WM5100_IN3L_CONTROL, WM5100_IN3R_CONTROL,
+ WM5100_IN3L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+SOC_DOUBLE_R_TLV("IN4 Volume", WM5100_IN4L_CONTROL, WM5100_IN4R_CONTROL,
+ WM5100_IN4L_PGA_VOL_SHIFT, 94, 0, in_tlv),
+
+SOC_DOUBLE_R_TLV("IN1 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_1L,
+ WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_VOL_SHIFT, 191,
+ 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN2 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_2L,
+ WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_VOL_SHIFT, 191,
+ 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN3 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_3L,
+ WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_VOL_SHIFT, 191,
+ 0, digital_tlv),
+SOC_DOUBLE_R_TLV("IN4 Digital Volume", WM5100_ADC_DIGITAL_VOLUME_4L,
+ WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_VOL_SHIFT, 191,
+ 0, digital_tlv),
+
+SOC_DOUBLE_R("IN1 Switch", WM5100_ADC_DIGITAL_VOLUME_1L,
+ WM5100_ADC_DIGITAL_VOLUME_1R, WM5100_IN1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN2 Switch", WM5100_ADC_DIGITAL_VOLUME_2L,
+ WM5100_ADC_DIGITAL_VOLUME_2R, WM5100_IN2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN3 Switch", WM5100_ADC_DIGITAL_VOLUME_3L,
+ WM5100_ADC_DIGITAL_VOLUME_3R, WM5100_IN3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("IN4 Switch", WM5100_ADC_DIGITAL_VOLUME_4L,
+ WM5100_ADC_DIGITAL_VOLUME_4R, WM5100_IN4L_MUTE_SHIFT, 1, 1),
+
+SOC_SINGLE("HPOUT1 High Performance Switch", WM5100_OUT_VOLUME_1L,
+ WM5100_OUT1_OSR_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT2 High Performance Switch", WM5100_OUT_VOLUME_2L,
+ WM5100_OUT2_OSR_SHIFT, 1, 0),
+SOC_SINGLE("HPOUT3 High Performance Switch", WM5100_OUT_VOLUME_3L,
+ WM5100_OUT3_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKOUT High Performance Switch", WM5100_OUT_VOLUME_4L,
+ WM5100_OUT4_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT1 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_5L,
+ WM5100_OUT5_OSR_SHIFT, 1, 0),
+SOC_SINGLE("SPKDAT2 High Performance Switch", WM5100_DAC_VOLUME_LIMIT_6L,
+ WM5100_OUT6_OSR_SHIFT, 1, 0),
+
+SOC_DOUBLE_R_TLV("HPOUT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_1L,
+ WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_VOL_SHIFT, 159, 0,
+ digital_tlv),
+SOC_DOUBLE_R_TLV("HPOUT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_2L,
+ WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_VOL_SHIFT, 159, 0,
+ digital_tlv),
+SOC_DOUBLE_R_TLV("HPOUT3 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_3L,
+ WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_VOL_SHIFT, 159, 0,
+ digital_tlv),
+SOC_DOUBLE_R_TLV("SPKOUT Digital Volume", WM5100_DAC_DIGITAL_VOLUME_4L,
+ WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_VOL_SHIFT, 159, 0,
+ digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT1 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_5L,
+ WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_VOL_SHIFT, 159, 0,
+ digital_tlv),
+SOC_DOUBLE_R_TLV("SPKDAT2 Digital Volume", WM5100_DAC_DIGITAL_VOLUME_6L,
+ WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_VOL_SHIFT, 159, 0,
+ digital_tlv),
+
+SOC_DOUBLE_R("HPOUT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_1L,
+ WM5100_DAC_DIGITAL_VOLUME_1R, WM5100_OUT1L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("HPOUT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_2L,
+ WM5100_DAC_DIGITAL_VOLUME_2R, WM5100_OUT2L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("HPOUT3 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_3L,
+ WM5100_DAC_DIGITAL_VOLUME_3R, WM5100_OUT3L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKOUT Digital Switch", WM5100_DAC_DIGITAL_VOLUME_4L,
+ WM5100_DAC_DIGITAL_VOLUME_4R, WM5100_OUT4L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT1 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_5L,
+ WM5100_DAC_DIGITAL_VOLUME_5R, WM5100_OUT5L_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE_R("SPKDAT2 Digital Switch", WM5100_DAC_DIGITAL_VOLUME_6L,
+ WM5100_DAC_DIGITAL_VOLUME_6R, WM5100_OUT6L_MUTE_SHIFT, 1, 1),
+
+/* FIXME: Only valid from -12dB to 0dB (52-64) */
+SOC_DOUBLE_R_TLV("HPOUT1 Volume", WM5100_OUT_VOLUME_1L, WM5100_OUT_VOLUME_1R,
+ WM5100_OUT1L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+SOC_DOUBLE_R_TLV("HPOUT2 Volume", WM5100_OUT_VOLUME_2L, WM5100_OUT_VOLUME_2R,
+ WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+SOC_DOUBLE_R_TLV("HPOUT3 Volume", WM5100_OUT_VOLUME_3L, WM5100_OUT_VOLUME_3R,
+ WM5100_OUT2L_PGA_VOL_SHIFT, 64, 0, out_tlv),
+
+SOC_DOUBLE("SPKDAT1 Switch", WM5100_PDM_SPK1_CTRL_1, WM5100_SPK1L_MUTE_SHIFT,
+ WM5100_SPK1R_MUTE_SHIFT, 1, 1),
+SOC_DOUBLE("SPKDAT2 Switch", WM5100_PDM_SPK2_CTRL_1, WM5100_SPK2L_MUTE_SHIFT,
+ WM5100_SPK2R_MUTE_SHIFT, 1, 1),
+
+SOC_SINGLE_TLV("EQ1 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ1_B1_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 2 Volume", WM5100_EQ1_1, WM5100_EQ1_B2_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 3 Volume", WM5100_EQ1_1, WM5100_EQ1_B3_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 4 Volume", WM5100_EQ1_2, WM5100_EQ1_B4_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ1 Band 5 Volume", WM5100_EQ1_2, WM5100_EQ1_B5_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ2 Band 1 Volume", WM5100_EQ2_1, WM5100_EQ2_B1_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 2 Volume", WM5100_EQ2_1, WM5100_EQ2_B2_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 3 Volume", WM5100_EQ2_1, WM5100_EQ2_B3_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 4 Volume", WM5100_EQ2_2, WM5100_EQ2_B4_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ2 Band 5 Volume", WM5100_EQ2_2, WM5100_EQ2_B5_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ3 Band 1 Volume", WM5100_EQ1_1, WM5100_EQ3_B1_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 2 Volume", WM5100_EQ3_1, WM5100_EQ3_B2_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 3 Volume", WM5100_EQ3_1, WM5100_EQ3_B3_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 4 Volume", WM5100_EQ3_2, WM5100_EQ3_B4_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ3 Band 5 Volume", WM5100_EQ3_2, WM5100_EQ3_B5_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+
+SOC_SINGLE_TLV("EQ4 Band 1 Volume", WM5100_EQ4_1, WM5100_EQ4_B1_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 2 Volume", WM5100_EQ4_1, WM5100_EQ4_B2_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 3 Volume", WM5100_EQ4_1, WM5100_EQ4_B3_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 4 Volume", WM5100_EQ4_2, WM5100_EQ4_B4_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+SOC_SINGLE_TLV("EQ4 Band 5 Volume", WM5100_EQ4_2, WM5100_EQ4_B5_GAIN_SHIFT,
+ 24, 0, eq_tlv),
+
+SOC_ENUM("LHPF1 Mode", wm5100_lhpf1_mode),
+SOC_ENUM("LHPF2 Mode", wm5100_lhpf2_mode),
+SOC_ENUM("LHPF3 Mode", wm5100_lhpf3_mode),
+SOC_ENUM("LHPF4 Mode", wm5100_lhpf4_mode),
+
+WM5100_MIXER_CONTROLS("HPOUT1L", WM5100_OUT1LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT1R", WM5100_OUT1RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT2L", WM5100_OUT2LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT2R", WM5100_OUT2RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT3L", WM5100_OUT3LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("HPOUT3R", WM5100_OUT3RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("SPKOUTL", WM5100_OUT4LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKOUTR", WM5100_OUT4RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT1L", WM5100_OUT5LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT1R", WM5100_OUT5RMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT2L", WM5100_OUT6LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("SPKDAT2R", WM5100_OUT6RMIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("PWM1", WM5100_PWM1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("PWM2", WM5100_PWM2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF1TX1", WM5100_AIF1TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX2", WM5100_AIF1TX2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX3", WM5100_AIF1TX3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX4", WM5100_AIF1TX4MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX5", WM5100_AIF1TX5MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX6", WM5100_AIF1TX6MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX7", WM5100_AIF1TX7MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF1TX8", WM5100_AIF1TX8MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF2TX1", WM5100_AIF2TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF2TX2", WM5100_AIF2TX2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("AIF3TX1", WM5100_AIF3TX1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("AIF3TX2", WM5100_AIF3TX2MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("EQ1", WM5100_EQ1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ2", WM5100_EQ2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ3", WM5100_EQ3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("EQ4", WM5100_EQ4MIX_INPUT_1_SOURCE),
+
+WM5100_MIXER_CONTROLS("DRC1L", WM5100_DRC1LMIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("DRC1R", WM5100_DRC1RMIX_INPUT_1_SOURCE),
+SND_SOC_BYTES_MASK("DRC", WM5100_DRC1_CTRL1, 5,
+ WM5100_DRCL_ENA | WM5100_DRCR_ENA),
+
+WM5100_MIXER_CONTROLS("LHPF1", WM5100_HPLP1MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF2", WM5100_HPLP2MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF3", WM5100_HPLP3MIX_INPUT_1_SOURCE),
+WM5100_MIXER_CONTROLS("LHPF4", WM5100_HPLP4MIX_INPUT_1_SOURCE),
+};
+
+static void wm5100_seq_notifier(struct snd_soc_dapm_context *dapm,
+ enum snd_soc_dapm_type event, int subseq)
+{
+ struct snd_soc_codec *codec = container_of(dapm,
+ struct snd_soc_codec, dapm);
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ u16 val, expect, i;
+
+ /* Wait for the outputs to flag themselves as enabled */
+ if (wm5100->out_ena[0]) {
+ expect = snd_soc_read(codec, WM5100_CHANNEL_ENABLES_1);
+ for (i = 0; i < 200; i++) {
+ val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_1);
+ if (val == expect) {
+ wm5100->out_ena[0] = false;
+ break;
+ }
+ }
+ if (i == 200) {
+ dev_err(codec->dev, "Timeout waiting for OUTPUT1 %x\n",
+ expect);
+ }
+ }
+
+ if (wm5100->out_ena[1]) {
+ expect = snd_soc_read(codec, WM5100_OUTPUT_ENABLES_2);
+ for (i = 0; i < 200; i++) {
+ val = snd_soc_read(codec, WM5100_OUTPUT_STATUS_2);
+ if (val == expect) {
+ wm5100->out_ena[1] = false;
+ break;
+ }
+ }
+ if (i == 200) {
+ dev_err(codec->dev, "Timeout waiting for OUTPUT2 %x\n",
+ expect);
+ }
+ }
+}
+
+static int wm5100_out_ev(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(w->codec);
+
+ switch (w->reg) {
+ case WM5100_CHANNEL_ENABLES_1:
+ wm5100->out_ena[0] = true;
+ break;
+ case WM5100_OUTPUT_ENABLES_2:
+ wm5100->out_ena[0] = true;
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void wm5100_log_status3(struct wm5100_priv *wm5100, int val)
+{
+ if (val & WM5100_SPK_SHUTDOWN_WARN_EINT)
+ dev_crit(wm5100->dev, "Speaker shutdown warning\n");
+ if (val & WM5100_SPK_SHUTDOWN_EINT)
+ dev_crit(wm5100->dev, "Speaker shutdown\n");
+ if (val & WM5100_CLKGEN_ERR_EINT)
+ dev_crit(wm5100->dev, "SYSCLK underclocked\n");
+ if (val & WM5100_CLKGEN_ERR_ASYNC_EINT)
+ dev_crit(wm5100->dev, "ASYNCCLK underclocked\n");
+}
+
+static void wm5100_log_status4(struct wm5100_priv *wm5100, int val)
+{
+ if (val & WM5100_AIF3_ERR_EINT)
+ dev_err(wm5100->dev, "AIF3 configuration error\n");
+ if (val & WM5100_AIF2_ERR_EINT)
+ dev_err(wm5100->dev, "AIF2 configuration error\n");
+ if (val & WM5100_AIF1_ERR_EINT)
+ dev_err(wm5100->dev, "AIF1 configuration error\n");
+ if (val & WM5100_CTRLIF_ERR_EINT)
+ dev_err(wm5100->dev, "Control interface error\n");
+ if (val & WM5100_ISRC2_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "ISRC2 underclocked\n");
+ if (val & WM5100_ISRC1_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "ISRC1 underclocked\n");
+ if (val & WM5100_FX_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "FX underclocked\n");
+ if (val & WM5100_AIF3_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "AIF3 underclocked\n");
+ if (val & WM5100_AIF2_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "AIF2 underclocked\n");
+ if (val & WM5100_AIF1_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "AIF1 underclocked\n");
+ if (val & WM5100_ASRC_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "ASRC underclocked\n");
+ if (val & WM5100_DAC_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "DAC underclocked\n");
+ if (val & WM5100_ADC_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "ADC underclocked\n");
+ if (val & WM5100_MIXER_UNDERCLOCKED_EINT)
+ dev_err(wm5100->dev, "Mixer underclocked\n");
+}
+
+static int wm5100_post_ev(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol,
+ int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ int ret;
+
+ ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_3);
+ ret &= WM5100_SPK_SHUTDOWN_WARN_STS |
+ WM5100_SPK_SHUTDOWN_STS | WM5100_CLKGEN_ERR_STS |
+ WM5100_CLKGEN_ERR_ASYNC_STS;
+ wm5100_log_status3(wm5100, ret);
+
+ ret = snd_soc_read(codec, WM5100_INTERRUPT_RAW_STATUS_4);
+ wm5100_log_status4(wm5100, ret);
+
+ return 0;
+}
+
+static const struct snd_soc_dapm_widget wm5100_dapm_widgets[] = {
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM5100_CLOCKING_3, WM5100_SYSCLK_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("ASYNCCLK", WM5100_CLOCKING_6, WM5100_ASYNC_CLK_ENA_SHIFT,
+ 0, NULL, 0),
+
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0),
+SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0),
+
+SND_SOC_DAPM_SUPPLY("CP1", WM5100_HP_CHARGE_PUMP_1, WM5100_CP1_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2", WM5100_MIC_CHARGE_PUMP_1, WM5100_CP2_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_SUPPLY("CP2 Active", WM5100_MIC_CHARGE_PUMP_1,
+ WM5100_CP2_BYPASS_SHIFT, 1, NULL, 0),
+
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM5100_MIC_BIAS_CTRL_1, WM5100_MICB1_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM5100_MIC_BIAS_CTRL_2, WM5100_MICB2_ENA_SHIFT,
+ 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS3", WM5100_MIC_BIAS_CTRL_3, WM5100_MICB3_ENA_SHIFT,
+ 0, NULL, 0),
+
+SND_SOC_DAPM_INPUT("IN1L"),
+SND_SOC_DAPM_INPUT("IN1R"),
+SND_SOC_DAPM_INPUT("IN2L"),
+SND_SOC_DAPM_INPUT("IN2R"),
+SND_SOC_DAPM_INPUT("IN3L"),
+SND_SOC_DAPM_INPUT("IN3R"),
+SND_SOC_DAPM_INPUT("IN4L"),
+SND_SOC_DAPM_INPUT("IN4R"),
+SND_SOC_DAPM_SIGGEN("TONE"),
+
+SND_SOC_DAPM_PGA_E("IN1L PGA", WM5100_INPUT_ENABLES, WM5100_IN1L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN1R PGA", WM5100_INPUT_ENABLES, WM5100_IN1R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2L PGA", WM5100_INPUT_ENABLES, WM5100_IN2L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN2R PGA", WM5100_INPUT_ENABLES, WM5100_IN2R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3L PGA", WM5100_INPUT_ENABLES, WM5100_IN3L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN3R PGA", WM5100_INPUT_ENABLES, WM5100_IN3R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4L PGA", WM5100_INPUT_ENABLES, WM5100_IN4L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("IN4R PGA", WM5100_INPUT_ENABLES, WM5100_IN4R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("Tone Generator 1", WM5100_TONE_GENERATOR_1,
+ WM5100_TONE1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("Tone Generator 2", WM5100_TONE_GENERATOR_1,
+ WM5100_TONE2_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 0,
+ WM5100_AUDIO_IF_1_27, WM5100_AIF1RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 1,
+ WM5100_AUDIO_IF_1_27, WM5100_AIF1RX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 2,
+ WM5100_AUDIO_IF_1_27, WM5100_AIF1RX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 3,
+ WM5100_AUDIO_IF_1_27, WM5100_AIF1RX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 4,
+ WM5100_AUDIO_IF_1_27, WM5100_AIF1RX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX6", "AIF1 Playback", 5,
+ WM5100_AUDIO_IF_1_27, WM5100_AIF1RX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX7", "AIF1 Playback", 6,
+ WM5100_AUDIO_IF_1_27, WM5100_AIF1RX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX8", "AIF1 Playback", 7,
+ WM5100_AUDIO_IF_1_27, WM5100_AIF1RX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0,
+ WM5100_AUDIO_IF_2_27, WM5100_AIF2RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX2", "AIF2 Playback", 1,
+ WM5100_AUDIO_IF_2_27, WM5100_AIF2RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF3RX1", "AIF3 Playback", 0,
+ WM5100_AUDIO_IF_3_27, WM5100_AIF3RX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_IN("AIF3RX2", "AIF3 Playback", 1,
+ WM5100_AUDIO_IF_3_27, WM5100_AIF3RX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 0,
+ WM5100_AUDIO_IF_1_26, WM5100_AIF1TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 1,
+ WM5100_AUDIO_IF_1_26, WM5100_AIF1TX2_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 2,
+ WM5100_AUDIO_IF_1_26, WM5100_AIF1TX3_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 3,
+ WM5100_AUDIO_IF_1_26, WM5100_AIF1TX4_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 4,
+ WM5100_AUDIO_IF_1_26, WM5100_AIF1TX5_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX6", "AIF1 Capture", 5,
+ WM5100_AUDIO_IF_1_26, WM5100_AIF1TX6_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX7", "AIF1 Capture", 6,
+ WM5100_AUDIO_IF_1_26, WM5100_AIF1TX7_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX8", "AIF1 Capture", 7,
+ WM5100_AUDIO_IF_1_26, WM5100_AIF1TX8_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", "AIF2 Capture", 0,
+ WM5100_AUDIO_IF_2_26, WM5100_AIF2TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX2", "AIF2 Capture", 1,
+ WM5100_AUDIO_IF_2_26, WM5100_AIF2TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF3TX1", "AIF3 Capture", 0,
+ WM5100_AUDIO_IF_3_26, WM5100_AIF3TX1_ENA_SHIFT, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3TX2", "AIF3 Capture", 1,
+ WM5100_AUDIO_IF_3_26, WM5100_AIF3TX2_ENA_SHIFT, 0),
+
+SND_SOC_DAPM_PGA_E("OUT6L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT6R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT6R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT5R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT5R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4L", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT4R", WM5100_OUTPUT_ENABLES_2, WM5100_OUT4R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3L", WM5100_CHANNEL_ENABLES_1, WM5100_HP3L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT3R", WM5100_CHANNEL_ENABLES_1, WM5100_HP3R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2L", WM5100_CHANNEL_ENABLES_1, WM5100_HP2L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT2R", WM5100_CHANNEL_ENABLES_1, WM5100_HP2R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1L", WM5100_CHANNEL_ENABLES_1, WM5100_HP1L_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("OUT1R", WM5100_CHANNEL_ENABLES_1, WM5100_HP1R_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("PWM1 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM1_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+SND_SOC_DAPM_PGA_E("PWM2 Driver", WM5100_PWM_DRIVE_1, WM5100_PWM2_ENA_SHIFT, 0,
+ NULL, 0, wm5100_out_ev, SND_SOC_DAPM_POST_PMU),
+
+SND_SOC_DAPM_PGA("EQ1", WM5100_EQ1_1, WM5100_EQ1_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ2", WM5100_EQ2_1, WM5100_EQ2_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ3", WM5100_EQ3_1, WM5100_EQ3_ENA_SHIFT, 0, NULL, 0),
+SND_SOC_DAPM_PGA("EQ4", WM5100_EQ4_1, WM5100_EQ4_ENA_SHIFT, 0, NULL, 0),
+
+SND_SOC_DAPM_PGA("DRC1L", WM5100_DRC1_CTRL1, WM5100_DRCL_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("DRC1R", WM5100_DRC1_CTRL1, WM5100_DRCR_ENA_SHIFT, 0,
+ NULL, 0),
+
+SND_SOC_DAPM_PGA("LHPF1", WM5100_HPLPF1_1, WM5100_LHPF1_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("LHPF2", WM5100_HPLPF2_1, WM5100_LHPF2_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("LHPF3", WM5100_HPLPF3_1, WM5100_LHPF3_ENA_SHIFT, 0,
+ NULL, 0),
+SND_SOC_DAPM_PGA("LHPF4", WM5100_HPLPF4_1, WM5100_LHPF4_ENA_SHIFT, 0,
+ NULL, 0),
+
+WM5100_MIXER_WIDGETS(EQ1, "EQ1"),
+WM5100_MIXER_WIDGETS(EQ2, "EQ2"),
+WM5100_MIXER_WIDGETS(EQ3, "EQ3"),
+WM5100_MIXER_WIDGETS(EQ4, "EQ4"),
+
+WM5100_MIXER_WIDGETS(DRC1L, "DRC1L"),
+WM5100_MIXER_WIDGETS(DRC1R, "DRC1R"),
+
+WM5100_MIXER_WIDGETS(LHPF1, "LHPF1"),
+WM5100_MIXER_WIDGETS(LHPF2, "LHPF2"),
+WM5100_MIXER_WIDGETS(LHPF3, "LHPF3"),
+WM5100_MIXER_WIDGETS(LHPF4, "LHPF4"),
+
+WM5100_MIXER_WIDGETS(AIF1TX1, "AIF1TX1"),
+WM5100_MIXER_WIDGETS(AIF1TX2, "AIF1TX2"),
+WM5100_MIXER_WIDGETS(AIF1TX3, "AIF1TX3"),
+WM5100_MIXER_WIDGETS(AIF1TX4, "AIF1TX4"),
+WM5100_MIXER_WIDGETS(AIF1TX5, "AIF1TX5"),
+WM5100_MIXER_WIDGETS(AIF1TX6, "AIF1TX6"),
+WM5100_MIXER_WIDGETS(AIF1TX7, "AIF1TX7"),
+WM5100_MIXER_WIDGETS(AIF1TX8, "AIF1TX8"),
+
+WM5100_MIXER_WIDGETS(AIF2TX1, "AIF2TX1"),
+WM5100_MIXER_WIDGETS(AIF2TX2, "AIF2TX2"),
+
+WM5100_MIXER_WIDGETS(AIF3TX1, "AIF3TX1"),
+WM5100_MIXER_WIDGETS(AIF3TX2, "AIF3TX2"),
+
+WM5100_MIXER_WIDGETS(HPOUT1L, "HPOUT1L"),
+WM5100_MIXER_WIDGETS(HPOUT1R, "HPOUT1R"),
+WM5100_MIXER_WIDGETS(HPOUT2L, "HPOUT2L"),
+WM5100_MIXER_WIDGETS(HPOUT2R, "HPOUT2R"),
+WM5100_MIXER_WIDGETS(HPOUT3L, "HPOUT3L"),
+WM5100_MIXER_WIDGETS(HPOUT3R, "HPOUT3R"),
+
+WM5100_MIXER_WIDGETS(SPKOUTL, "SPKOUTL"),
+WM5100_MIXER_WIDGETS(SPKOUTR, "SPKOUTR"),
+WM5100_MIXER_WIDGETS(SPKDAT1L, "SPKDAT1L"),
+WM5100_MIXER_WIDGETS(SPKDAT1R, "SPKDAT1R"),
+WM5100_MIXER_WIDGETS(SPKDAT2L, "SPKDAT2L"),
+WM5100_MIXER_WIDGETS(SPKDAT2R, "SPKDAT2R"),
+
+WM5100_MIXER_WIDGETS(PWM1, "PWM1"),
+WM5100_MIXER_WIDGETS(PWM2, "PWM2"),
+
+SND_SOC_DAPM_OUTPUT("HPOUT1L"),
+SND_SOC_DAPM_OUTPUT("HPOUT1R"),
+SND_SOC_DAPM_OUTPUT("HPOUT2L"),
+SND_SOC_DAPM_OUTPUT("HPOUT2R"),
+SND_SOC_DAPM_OUTPUT("HPOUT3L"),
+SND_SOC_DAPM_OUTPUT("HPOUT3R"),
+SND_SOC_DAPM_OUTPUT("SPKOUTL"),
+SND_SOC_DAPM_OUTPUT("SPKOUTR"),
+SND_SOC_DAPM_OUTPUT("SPKDAT1"),
+SND_SOC_DAPM_OUTPUT("SPKDAT2"),
+SND_SOC_DAPM_OUTPUT("PWM1"),
+SND_SOC_DAPM_OUTPUT("PWM2"),
+};
+
+/* We register a _POST event if we don't have IRQ support so we can
+ * look at the error status from the CODEC - if we've got the IRQ
+ * hooked up then we will get prompted to look by an interrupt.
+ */
+static const struct snd_soc_dapm_widget wm5100_dapm_widgets_noirq[] = {
+SND_SOC_DAPM_POST("Post", wm5100_post_ev),
+};
+
+static const struct snd_soc_dapm_route wm5100_dapm_routes[] = {
+ { "CP1", NULL, "CPVDD" },
+ { "CP2 Active", NULL, "CPVDD" },
+
+ { "IN1L", NULL, "SYSCLK" },
+ { "IN1R", NULL, "SYSCLK" },
+ { "IN2L", NULL, "SYSCLK" },
+ { "IN2R", NULL, "SYSCLK" },
+ { "IN3L", NULL, "SYSCLK" },
+ { "IN3R", NULL, "SYSCLK" },
+ { "IN4L", NULL, "SYSCLK" },
+ { "IN4R", NULL, "SYSCLK" },
+
+ { "OUT1L", NULL, "SYSCLK" },
+ { "OUT1R", NULL, "SYSCLK" },
+ { "OUT2L", NULL, "SYSCLK" },
+ { "OUT2R", NULL, "SYSCLK" },
+ { "OUT3L", NULL, "SYSCLK" },
+ { "OUT3R", NULL, "SYSCLK" },
+ { "OUT4L", NULL, "SYSCLK" },
+ { "OUT4R", NULL, "SYSCLK" },
+ { "OUT5L", NULL, "SYSCLK" },
+ { "OUT5R", NULL, "SYSCLK" },
+ { "OUT6L", NULL, "SYSCLK" },
+ { "OUT6R", NULL, "SYSCLK" },
+
+ { "AIF1RX1", NULL, "SYSCLK" },
+ { "AIF1RX2", NULL, "SYSCLK" },
+ { "AIF1RX3", NULL, "SYSCLK" },
+ { "AIF1RX4", NULL, "SYSCLK" },
+ { "AIF1RX5", NULL, "SYSCLK" },
+ { "AIF1RX6", NULL, "SYSCLK" },
+ { "AIF1RX7", NULL, "SYSCLK" },
+ { "AIF1RX8", NULL, "SYSCLK" },
+
+ { "AIF2RX1", NULL, "SYSCLK" },
+ { "AIF2RX1", NULL, "DBVDD2" },
+ { "AIF2RX2", NULL, "SYSCLK" },
+ { "AIF2RX2", NULL, "DBVDD2" },
+
+ { "AIF3RX1", NULL, "SYSCLK" },
+ { "AIF3RX1", NULL, "DBVDD3" },
+ { "AIF3RX2", NULL, "SYSCLK" },
+ { "AIF3RX2", NULL, "DBVDD3" },
+
+ { "AIF1TX1", NULL, "SYSCLK" },
+ { "AIF1TX2", NULL, "SYSCLK" },
+ { "AIF1TX3", NULL, "SYSCLK" },
+ { "AIF1TX4", NULL, "SYSCLK" },
+ { "AIF1TX5", NULL, "SYSCLK" },
+ { "AIF1TX6", NULL, "SYSCLK" },
+ { "AIF1TX7", NULL, "SYSCLK" },
+ { "AIF1TX8", NULL, "SYSCLK" },
+
+ { "AIF2TX1", NULL, "SYSCLK" },
+ { "AIF2TX1", NULL, "DBVDD2" },
+ { "AIF2TX2", NULL, "SYSCLK" },
+ { "AIF2TX2", NULL, "DBVDD2" },
+
+ { "AIF3TX1", NULL, "SYSCLK" },
+ { "AIF3TX1", NULL, "DBVDD3" },
+ { "AIF3TX2", NULL, "SYSCLK" },
+ { "AIF3TX2", NULL, "DBVDD3" },
+
+ { "MICBIAS1", NULL, "CP2" },
+ { "MICBIAS2", NULL, "CP2" },
+ { "MICBIAS3", NULL, "CP2" },
+
+ { "IN1L PGA", NULL, "CP2" },
+ { "IN1R PGA", NULL, "CP2" },
+ { "IN2L PGA", NULL, "CP2" },
+ { "IN2R PGA", NULL, "CP2" },
+ { "IN3L PGA", NULL, "CP2" },
+ { "IN3R PGA", NULL, "CP2" },
+ { "IN4L PGA", NULL, "CP2" },
+ { "IN4R PGA", NULL, "CP2" },
+
+ { "IN1L PGA", NULL, "CP2 Active" },
+ { "IN1R PGA", NULL, "CP2 Active" },
+ { "IN2L PGA", NULL, "CP2 Active" },
+ { "IN2R PGA", NULL, "CP2 Active" },
+ { "IN3L PGA", NULL, "CP2 Active" },
+ { "IN3R PGA", NULL, "CP2 Active" },
+ { "IN4L PGA", NULL, "CP2 Active" },
+ { "IN4R PGA", NULL, "CP2 Active" },
+
+ { "OUT1L", NULL, "CP1" },
+ { "OUT1R", NULL, "CP1" },
+ { "OUT2L", NULL, "CP1" },
+ { "OUT2R", NULL, "CP1" },
+ { "OUT3L", NULL, "CP1" },
+ { "OUT3R", NULL, "CP1" },
+
+ { "Tone Generator 1", NULL, "TONE" },
+ { "Tone Generator 2", NULL, "TONE" },
+
+ { "IN1L PGA", NULL, "IN1L" },
+ { "IN1R PGA", NULL, "IN1R" },
+ { "IN2L PGA", NULL, "IN2L" },
+ { "IN2R PGA", NULL, "IN2R" },
+ { "IN3L PGA", NULL, "IN3L" },
+ { "IN3R PGA", NULL, "IN3R" },
+ { "IN4L PGA", NULL, "IN4L" },
+ { "IN4R PGA", NULL, "IN4R" },
+
+ WM5100_MIXER_ROUTES("OUT1L", "HPOUT1L"),
+ WM5100_MIXER_ROUTES("OUT1R", "HPOUT1R"),
+ WM5100_MIXER_ROUTES("OUT2L", "HPOUT2L"),
+ WM5100_MIXER_ROUTES("OUT2R", "HPOUT2R"),
+ WM5100_MIXER_ROUTES("OUT3L", "HPOUT3L"),
+ WM5100_MIXER_ROUTES("OUT3R", "HPOUT3R"),
+
+ WM5100_MIXER_ROUTES("OUT4L", "SPKOUTL"),
+ WM5100_MIXER_ROUTES("OUT4R", "SPKOUTR"),
+ WM5100_MIXER_ROUTES("OUT5L", "SPKDAT1L"),
+ WM5100_MIXER_ROUTES("OUT5R", "SPKDAT1R"),
+ WM5100_MIXER_ROUTES("OUT6L", "SPKDAT2L"),
+ WM5100_MIXER_ROUTES("OUT6R", "SPKDAT2R"),
+
+ WM5100_MIXER_ROUTES("PWM1 Driver", "PWM1"),
+ WM5100_MIXER_ROUTES("PWM2 Driver", "PWM2"),
+
+ WM5100_MIXER_ROUTES("AIF1TX1", "AIF1TX1"),
+ WM5100_MIXER_ROUTES("AIF1TX2", "AIF1TX2"),
+ WM5100_MIXER_ROUTES("AIF1TX3", "AIF1TX3"),
+ WM5100_MIXER_ROUTES("AIF1TX4", "AIF1TX4"),
+ WM5100_MIXER_ROUTES("AIF1TX5", "AIF1TX5"),
+ WM5100_MIXER_ROUTES("AIF1TX6", "AIF1TX6"),
+ WM5100_MIXER_ROUTES("AIF1TX7", "AIF1TX7"),
+ WM5100_MIXER_ROUTES("AIF1TX8", "AIF1TX8"),
+
+ WM5100_MIXER_ROUTES("AIF2TX1", "AIF2TX1"),
+ WM5100_MIXER_ROUTES("AIF2TX2", "AIF2TX2"),
+
+ WM5100_MIXER_ROUTES("AIF3TX1", "AIF3TX1"),
+ WM5100_MIXER_ROUTES("AIF3TX2", "AIF3TX2"),
+
+ WM5100_MIXER_ROUTES("EQ1", "EQ1"),
+ WM5100_MIXER_ROUTES("EQ2", "EQ2"),
+ WM5100_MIXER_ROUTES("EQ3", "EQ3"),
+ WM5100_MIXER_ROUTES("EQ4", "EQ4"),
+
+ WM5100_MIXER_ROUTES("DRC1L", "DRC1L"),
+ WM5100_MIXER_ROUTES("DRC1R", "DRC1R"),
+
+ WM5100_MIXER_ROUTES("LHPF1", "LHPF1"),
+ WM5100_MIXER_ROUTES("LHPF2", "LHPF2"),
+ WM5100_MIXER_ROUTES("LHPF3", "LHPF3"),
+ WM5100_MIXER_ROUTES("LHPF4", "LHPF4"),
+
+ { "HPOUT1L", NULL, "OUT1L" },
+ { "HPOUT1R", NULL, "OUT1R" },
+ { "HPOUT2L", NULL, "OUT2L" },
+ { "HPOUT2R", NULL, "OUT2R" },
+ { "HPOUT3L", NULL, "OUT3L" },
+ { "HPOUT3R", NULL, "OUT3R" },
+ { "SPKOUTL", NULL, "OUT4L" },
+ { "SPKOUTR", NULL, "OUT4R" },
+ { "SPKDAT1", NULL, "OUT5L" },
+ { "SPKDAT1", NULL, "OUT5R" },
+ { "SPKDAT2", NULL, "OUT6L" },
+ { "SPKDAT2", NULL, "OUT6R" },
+ { "PWM1", NULL, "PWM1 Driver" },
+ { "PWM2", NULL, "PWM2 Driver" },
+};
+
+static const __devinitdata struct reg_default wm5100_reva_patches[] = {
+ { WM5100_AUDIO_IF_1_10, 0 },
+ { WM5100_AUDIO_IF_1_11, 1 },
+ { WM5100_AUDIO_IF_1_12, 2 },
+ { WM5100_AUDIO_IF_1_13, 3 },
+ { WM5100_AUDIO_IF_1_14, 4 },
+ { WM5100_AUDIO_IF_1_15, 5 },
+ { WM5100_AUDIO_IF_1_16, 6 },
+ { WM5100_AUDIO_IF_1_17, 7 },
+
+ { WM5100_AUDIO_IF_1_18, 0 },
+ { WM5100_AUDIO_IF_1_19, 1 },
+ { WM5100_AUDIO_IF_1_20, 2 },
+ { WM5100_AUDIO_IF_1_21, 3 },
+ { WM5100_AUDIO_IF_1_22, 4 },
+ { WM5100_AUDIO_IF_1_23, 5 },
+ { WM5100_AUDIO_IF_1_24, 6 },
+ { WM5100_AUDIO_IF_1_25, 7 },
+
+ { WM5100_AUDIO_IF_2_10, 0 },
+ { WM5100_AUDIO_IF_2_11, 1 },
+
+ { WM5100_AUDIO_IF_2_18, 0 },
+ { WM5100_AUDIO_IF_2_19, 1 },
+
+ { WM5100_AUDIO_IF_3_10, 0 },
+ { WM5100_AUDIO_IF_3_11, 1 },
+
+ { WM5100_AUDIO_IF_3_18, 0 },
+ { WM5100_AUDIO_IF_3_19, 1 },
+};
+
+static int wm5100_dai_to_base(struct snd_soc_dai *dai)
+{
+ switch (dai->id) {
+ case 0:
+ return WM5100_AUDIO_IF_1_1 - 1;
+ case 1:
+ return WM5100_AUDIO_IF_2_1 - 1;
+ case 2:
+ return WM5100_AUDIO_IF_3_1 - 1;
+ default:
+ BUG();
+ return -EINVAL;
+ }
+}
+
+static int wm5100_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ int lrclk, bclk, mask, base;
+
+ base = wm5100_dai_to_base(dai);
+ if (base < 0)
+ return base;
+
+ lrclk = 0;
+ bclk = 0;
+
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_DSP_A:
+ mask = 0;
+ break;
+ case SND_SOC_DAIFMT_DSP_B:
+ mask = 1;
+ break;
+ case SND_SOC_DAIFMT_I2S:
+ mask = 2;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ mask = 3;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported DAI format %d\n",
+ fmt & SND_SOC_DAIFMT_FORMAT_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ break;
+ case SND_SOC_DAIFMT_CBS_CFM:
+ lrclk |= WM5100_AIF1TX_LRCLK_MSTR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFS:
+ bclk |= WM5100_AIF1_BCLK_MSTR;
+ break;
+ case SND_SOC_DAIFMT_CBM_CFM:
+ lrclk |= WM5100_AIF1TX_LRCLK_MSTR;
+ bclk |= WM5100_AIF1_BCLK_MSTR;
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported master mode %d\n",
+ fmt & SND_SOC_DAIFMT_MASTER_MASK);
+ return -EINVAL;
+ }
+
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_NB_NF:
+ break;
+ case SND_SOC_DAIFMT_IB_IF:
+ bclk |= WM5100_AIF1_BCLK_INV;
+ lrclk |= WM5100_AIF1TX_LRCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ bclk |= WM5100_AIF1_BCLK_INV;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ lrclk |= WM5100_AIF1TX_LRCLK_INV;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_MSTR |
+ WM5100_AIF1_BCLK_INV, bclk);
+ snd_soc_update_bits(codec, base + 2, WM5100_AIF1TX_LRCLK_MSTR |
+ WM5100_AIF1TX_LRCLK_INV, lrclk);
+ snd_soc_update_bits(codec, base + 3, WM5100_AIF1TX_LRCLK_MSTR |
+ WM5100_AIF1TX_LRCLK_INV, lrclk);
+ snd_soc_update_bits(codec, base + 5, WM5100_AIF1_FMT_MASK, mask);
+
+ return 0;
+}
+
+#define WM5100_NUM_BCLK_RATES 19
+
+static int wm5100_bclk_rates_dat[WM5100_NUM_BCLK_RATES] = {
+ 32000,
+ 48000,
+ 64000,
+ 96000,
+ 128000,
+ 192000,
+ 256000,
+ 384000,
+ 512000,
+ 768000,
+ 1024000,
+ 1536000,
+ 2048000,
+ 3072000,
+ 4096000,
+ 6144000,
+ 8192000,
+ 12288000,
+ 24576000,
+};
+
+static int wm5100_bclk_rates_cd[WM5100_NUM_BCLK_RATES] = {
+ 29400,
+ 44100,
+ 58800,
+ 88200,
+ 117600,
+ 176400,
+ 235200,
+ 352800,
+ 470400,
+ 705600,
+ 940800,
+ 1411200,
+ 1881600,
+ 2882400,
+ 3763200,
+ 5644800,
+ 7526400,
+ 11289600,
+ 22579600,
+};
+
+static int wm5100_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ bool async = wm5100->aif_async[dai->id];
+ int i, base, bclk, aif_rate, lrclk, wl, fl, sr;
+ int *bclk_rates;
+
+ base = wm5100_dai_to_base(dai);
+ if (base < 0)
+ return base;
+
+ /* Data sizes if not using TDM */
+ wl = snd_pcm_format_width(params_format(params));
+ if (wl < 0)
+ return wl;
+ fl = snd_soc_params_to_frame_size(params);
+ if (fl < 0)
+ return fl;
+
+ dev_dbg(codec->dev, "Word length %d bits, frame length %d bits\n",
+ wl, fl);
+
+ /* Target BCLK rate */
+ bclk = snd_soc_params_to_bclk(params);
+ if (bclk < 0)
+ return bclk;
+
+ /* Root for BCLK depends on SYS/ASYNCCLK */
+ if (!async) {
+ aif_rate = wm5100->sysclk;
+ sr = wm5100_alloc_sr(codec, params_rate(params));
+ if (sr < 0)
+ return sr;
+ } else {
+ /* If we're in ASYNCCLK set the ASYNC sample rate */
+ aif_rate = wm5100->asyncclk;
+ sr = 3;
+
+ for (i = 0; i < ARRAY_SIZE(wm5100_sr_code); i++)
+ if (params_rate(params) == wm5100_sr_code[i])
+ break;
+ if (i == ARRAY_SIZE(wm5100_sr_code)) {
+ dev_err(codec->dev, "Invalid rate %dHzn",
+ params_rate(params));
+ return -EINVAL;
+ }
+
+ /* TODO: We should really check for symmetry */
+ snd_soc_update_bits(codec, WM5100_CLOCKING_8,
+ WM5100_ASYNC_SAMPLE_RATE_MASK, i);
+ }
+
+ if (!aif_rate) {
+ dev_err(codec->dev, "%s has no rate set\n",
+ async ? "ASYNCCLK" : "SYSCLK");
+ return -EINVAL;
+ }
+
+ dev_dbg(codec->dev, "Target BCLK is %dHz, using %dHz %s\n",
+ bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
+
+ if (aif_rate % 4000)
+ bclk_rates = wm5100_bclk_rates_cd;
+ else
+ bclk_rates = wm5100_bclk_rates_dat;
+
+ for (i = 0; i < WM5100_NUM_BCLK_RATES; i++)
+ if (bclk_rates[i] >= bclk && (bclk_rates[i] % bclk == 0))
+ break;
+ if (i == WM5100_NUM_BCLK_RATES) {
+ dev_err(codec->dev,
+ "No valid BCLK for %dHz found from %dHz %s\n",
+ bclk, aif_rate, async ? "ASYNCCLK" : "SYSCLK");
+ return -EINVAL;
+ }
+
+ bclk = i;
+ dev_dbg(codec->dev, "Setting %dHz BCLK\n", bclk_rates[bclk]);
+ snd_soc_update_bits(codec, base + 1, WM5100_AIF1_BCLK_FREQ_MASK, bclk);
+
+ lrclk = bclk_rates[bclk] / params_rate(params);
+ dev_dbg(codec->dev, "Setting %dHz LRCLK\n", bclk_rates[bclk] / lrclk);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK ||
+ wm5100->aif_symmetric[dai->id])
+ snd_soc_update_bits(codec, base + 7,
+ WM5100_AIF1RX_BCPF_MASK, lrclk);
+ else
+ snd_soc_update_bits(codec, base + 6,
+ WM5100_AIF1TX_BCPF_MASK, lrclk);
+
+ i = (wl << WM5100_AIF1TX_WL_SHIFT) | fl;
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_update_bits(codec, base + 9,
+ WM5100_AIF1RX_WL_MASK |
+ WM5100_AIF1RX_SLOT_LEN_MASK, i);
+ else
+ snd_soc_update_bits(codec, base + 8,
+ WM5100_AIF1TX_WL_MASK |
+ WM5100_AIF1TX_SLOT_LEN_MASK, i);
+
+ snd_soc_update_bits(codec, base + 4, WM5100_AIF1_RATE_MASK, sr);
+
+ return 0;
+}
+
+static const struct snd_soc_dai_ops wm5100_dai_ops = {
+ .set_fmt = wm5100_set_fmt,
+ .hw_params = wm5100_hw_params,
+};
+
+static int wm5100_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+ int source, unsigned int freq, int dir)
+{
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ int *rate_store;
+ int fval, audio_rate, ret, reg;
+
+ switch (clk_id) {
+ case WM5100_CLK_SYSCLK:
+ reg = WM5100_CLOCKING_3;
+ rate_store = &wm5100->sysclk;
+ break;
+ case WM5100_CLK_ASYNCCLK:
+ reg = WM5100_CLOCKING_7;
+ rate_store = &wm5100->asyncclk;
+ break;
+ case WM5100_CLK_32KHZ:
+ /* The 32kHz clock is slightly different to the others */
+ switch (source) {
+ case WM5100_CLKSRC_MCLK1:
+ case WM5100_CLKSRC_MCLK2:
+ case WM5100_CLKSRC_SYSCLK:
+ snd_soc_update_bits(codec, WM5100_CLOCKING_1,
+ WM5100_CLK_32K_SRC_MASK,
+ source);
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+
+ case WM5100_CLK_AIF1:
+ case WM5100_CLK_AIF2:
+ case WM5100_CLK_AIF3:
+ /* Not real clocks, record which clock domain they're in */
+ switch (source) {
+ case WM5100_CLKSRC_SYSCLK:
+ wm5100->aif_async[clk_id - 1] = false;
+ break;
+ case WM5100_CLKSRC_ASYNCCLK:
+ wm5100->aif_async[clk_id - 1] = true;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid source %d\n", source);
+ return -EINVAL;
+ }
+ return 0;
+
+ case WM5100_CLK_OPCLK:
+ switch (freq) {
+ case 5644800:
+ case 6144000:
+ snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+ WM5100_OPCLK_SEL_MASK, 0);
+ break;
+ case 11289600:
+ case 12288000:
+ snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+ WM5100_OPCLK_SEL_MASK, 0);
+ break;
+ case 22579200:
+ case 24576000:
+ snd_soc_update_bits(codec, WM5100_MISC_GPIO_1,
+ WM5100_OPCLK_SEL_MASK, 0);
+ break;
+ default:
+ dev_err(codec->dev, "Unsupported OPCLK %dHz\n",
+ freq);
+ return -EINVAL;
+ }
+ return 0;
+
+ default:
+ dev_err(codec->dev, "Unknown clock %d\n", clk_id);
+ return -EINVAL;
+ }
+
+ switch (source) {
+ case WM5100_CLKSRC_SYSCLK:
+ case WM5100_CLKSRC_ASYNCCLK:
+ dev_err(codec->dev, "Invalid source %d\n", source);
+ return -EINVAL;
+ }
+
+ switch (freq) {
+ case 5644800:
+ case 6144000:
+ fval = 0;
+ break;
+ case 11289600:
+ case 12288000:
+ fval = 1;
+ break;
+ case 22579200:
+ case 24576000:
+ fval = 2;
+ break;
+ default:
+ dev_err(codec->dev, "Invalid clock rate: %d\n", freq);
+ return -EINVAL;
+ }
+
+ switch (freq) {
+ case 5644800:
+ case 11289600:
+ case 22579200:
+ audio_rate = 44100;
+ break;
+
+ case 6144000:
+ case 12288000:
+ case 24576000:
+ audio_rate = 48000;
+ break;
+
+ default:
+ BUG();
+ audio_rate = 0;
+ break;
+ }
+
+ /* TODO: Check if MCLKs are in use and enable/disable pulls to
+ * match.
+ */
+
+ snd_soc_update_bits(codec, reg, WM5100_SYSCLK_FREQ_MASK |
+ WM5100_SYSCLK_SRC_MASK,
+ fval << WM5100_SYSCLK_FREQ_SHIFT | source);
+
+ /* If this is SYSCLK then configure the clock rate for the
+ * internal audio functions to the natural sample rate for
+ * this clock rate.
+ */
+ if (clk_id == WM5100_CLK_SYSCLK) {
+ dev_dbg(codec->dev, "Setting primary audio rate to %dHz",
+ audio_rate);
+ if (0 && *rate_store)
+ wm5100_free_sr(codec, audio_rate);
+ ret = wm5100_alloc_sr(codec, audio_rate);
+ if (ret != 0)
+ dev_warn(codec->dev, "Primary audio slot is %d\n",
+ ret);
+ }
+
+ *rate_store = freq;
+
+ return 0;
+}
+
+struct _fll_div {
+ u16 fll_fratio;
+ u16 fll_outdiv;
+ u16 fll_refclk_div;
+ u16 n;
+ u16 theta;
+ u16 lambda;
+};
+
+static struct {
+ unsigned int min;
+ unsigned int max;
+ u16 fll_fratio;
+ int ratio;
+} fll_fratios[] = {
+ { 0, 64000, 4, 16 },
+ { 64000, 128000, 3, 8 },
+ { 128000, 256000, 2, 4 },
+ { 256000, 1000000, 1, 2 },
+ { 1000000, 13500000, 0, 1 },
+};
+
+static int fll_factors(struct _fll_div *fll_div, unsigned int Fref,
+ unsigned int Fout)
+{
+ unsigned int target;
+ unsigned int div;
+ unsigned int fratio, gcd_fll;
+ int i;
+
+ /* Fref must be <=13.5MHz */
+ div = 1;
+ fll_div->fll_refclk_div = 0;
+ while ((Fref / div) > 13500000) {
+ div *= 2;
+ fll_div->fll_refclk_div++;
+
+ if (div > 8) {
+ pr_err("Can't scale %dMHz input down to <=13.5MHz\n",
+ Fref);
+ return -EINVAL;
+ }
+ }
+
+ pr_debug("FLL Fref=%u Fout=%u\n", Fref, Fout);
+
+ /* Apply the division for our remaining calculations */
+ Fref /= div;
+
+ /* Fvco should be 90-100MHz; don't check the upper bound */
+ div = 2;
+ while (Fout * div < 90000000) {
+ div++;
+ if (div > 64) {
+ pr_err("Unable to find FLL_OUTDIV for Fout=%uHz\n",
+ Fout);
+ return -EINVAL;
+ }
+ }
+ target = Fout * div;
+ fll_div->fll_outdiv = div - 1;
+
+ pr_debug("FLL Fvco=%dHz\n", target);
+
+ /* Find an appropraite FLL_FRATIO and factor it out of the target */
+ for (i = 0; i < ARRAY_SIZE(fll_fratios); i++) {
+ if (fll_fratios[i].min <= Fref && Fref <= fll_fratios[i].max) {
+ fll_div->fll_fratio = fll_fratios[i].fll_fratio;
+ fratio = fll_fratios[i].ratio;
+ break;
+ }
+ }
+ if (i == ARRAY_SIZE(fll_fratios)) {
+ pr_err("Unable to find FLL_FRATIO for Fref=%uHz\n", Fref);
+ return -EINVAL;
+ }
+
+ fll_div->n = target / (fratio * Fref);
+
+ if (target % Fref == 0) {
+ fll_div->theta = 0;
+ fll_div->lambda = 0;
+ } else {
+ gcd_fll = gcd(target, fratio * Fref);
+
+ fll_div->theta = (target - (fll_div->n * fratio * Fref))
+ / gcd_fll;
+ fll_div->lambda = (fratio * Fref) / gcd_fll;
+ }
+
+ pr_debug("FLL N=%x THETA=%x LAMBDA=%x\n",
+ fll_div->n, fll_div->theta, fll_div->lambda);
+ pr_debug("FLL_FRATIO=%x(%d) FLL_OUTDIV=%x FLL_REFCLK_DIV=%x\n",
+ fll_div->fll_fratio, fratio, fll_div->fll_outdiv,
+ fll_div->fll_refclk_div);
+
+ return 0;
+}
+
+static int wm5100_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
+ unsigned int Fref, unsigned int Fout)
+{
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ struct _fll_div factors;
+ struct wm5100_fll *fll;
+ int ret, base, lock, i, timeout;
+
+ switch (fll_id) {
+ case WM5100_FLL1:
+ fll = &wm5100->fll[0];
+ base = WM5100_FLL1_CONTROL_1 - 1;
+ lock = WM5100_FLL1_LOCK_STS;
+ break;
+ case WM5100_FLL2:
+ fll = &wm5100->fll[1];
+ base = WM5100_FLL2_CONTROL_2 - 1;
+ lock = WM5100_FLL2_LOCK_STS;
+ break;
+ default:
+ dev_err(codec->dev, "Unknown FLL %d\n",fll_id);
+ return -EINVAL;
+ }
+
+ if (!Fout) {
+ dev_dbg(codec->dev, "FLL%d disabled", fll_id);
+ if (fll->fout)
+ pm_runtime_put(codec->dev);
+ fll->fout = 0;
+ snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
+ return 0;
+ }
+
+ switch (source) {
+ case WM5100_FLL_SRC_MCLK1:
+ case WM5100_FLL_SRC_MCLK2:
+ case WM5100_FLL_SRC_FLL1:
+ case WM5100_FLL_SRC_FLL2:
+ case WM5100_FLL_SRC_AIF1BCLK:
+ case WM5100_FLL_SRC_AIF2BCLK:
+ case WM5100_FLL_SRC_AIF3BCLK:
+ break;
+ default:
+ dev_err(codec->dev, "Invalid FLL source %d\n", source);
+ return -EINVAL;
+ }
+
+ ret = fll_factors(&factors, Fref, Fout);
+ if (ret < 0)
+ return ret;
+
+ /* Disable the FLL while we reconfigure */
+ snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, 0);
+
+ snd_soc_update_bits(codec, base + 2,
+ WM5100_FLL1_OUTDIV_MASK | WM5100_FLL1_FRATIO_MASK,
+ (factors.fll_outdiv << WM5100_FLL1_OUTDIV_SHIFT) |
+ factors.fll_fratio);
+ snd_soc_update_bits(codec, base + 3, WM5100_FLL1_THETA_MASK,
+ factors.theta);
+ snd_soc_update_bits(codec, base + 5, WM5100_FLL1_N_MASK, factors.n);
+ snd_soc_update_bits(codec, base + 6,
+ WM5100_FLL1_REFCLK_DIV_MASK |
+ WM5100_FLL1_REFCLK_SRC_MASK,
+ (factors.fll_refclk_div
+ << WM5100_FLL1_REFCLK_DIV_SHIFT) | source);
+ snd_soc_update_bits(codec, base + 7, WM5100_FLL1_LAMBDA_MASK,
+ factors.lambda);
+
+ /* Clear any pending completions */
+ try_wait_for_completion(&fll->lock);
+
+ pm_runtime_get_sync(codec->dev);
+
+ snd_soc_update_bits(codec, base + 1, WM5100_FLL1_ENA, WM5100_FLL1_ENA);
+
+ if (i2c->irq)
+ timeout = 2;
+ else
+ timeout = 50;
+
+ snd_soc_update_bits(codec, WM5100_CLOCKING_3, WM5100_SYSCLK_ENA,
+ WM5100_SYSCLK_ENA);
+
+ /* Poll for the lock; will use interrupt when we can test */
+ for (i = 0; i < timeout; i++) {
+ if (i2c->irq) {
+ ret = wait_for_completion_timeout(&fll->lock,
+ msecs_to_jiffies(25));
+ if (ret > 0)
+ break;
+ } else {
+ msleep(1);
+ }
+
+ ret = snd_soc_read(codec,
+ WM5100_INTERRUPT_RAW_STATUS_3);
+ if (ret < 0) {
+ dev_err(codec->dev,
+ "Failed to read FLL status: %d\n",
+ ret);
+ continue;
+ }
+ if (ret & lock)
+ break;
+ }
+ if (i == timeout) {
+ dev_err(codec->dev, "FLL%d lock timed out\n", fll_id);
+ pm_runtime_put(codec->dev);
+ return -ETIMEDOUT;
+ }
+
+ fll->src = source;
+ fll->fref = Fref;
+ fll->fout = Fout;
+
+ dev_dbg(codec->dev, "FLL%d running %dHz->%dHz\n", fll_id,
+ Fref, Fout);
+
+ return 0;
+}
+
+/* Actually go much higher */
+#define WM5100_RATES SNDRV_PCM_RATE_8000_192000
+
+#define WM5100_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+static struct snd_soc_dai_driver wm5100_dai[] = {
+ {
+ .name = "wm5100-aif1",
+ .playback = {
+ .stream_name = "AIF1 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM5100_RATES,
+ .formats = WM5100_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF1 Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM5100_RATES,
+ .formats = WM5100_FORMATS,
+ },
+ .ops = &wm5100_dai_ops,
+ },
+ {
+ .name = "wm5100-aif2",
+ .id = 1,
+ .playback = {
+ .stream_name = "AIF2 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM5100_RATES,
+ .formats = WM5100_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF2 Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM5100_RATES,
+ .formats = WM5100_FORMATS,
+ },
+ .ops = &wm5100_dai_ops,
+ },
+ {
+ .name = "wm5100-aif3",
+ .id = 2,
+ .playback = {
+ .stream_name = "AIF3 Playback",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM5100_RATES,
+ .formats = WM5100_FORMATS,
+ },
+ .capture = {
+ .stream_name = "AIF3 Capture",
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = WM5100_RATES,
+ .formats = WM5100_FORMATS,
+ },
+ .ops = &wm5100_dai_ops,
+ },
+};
+
+static int wm5100_dig_vu[] = {
+ WM5100_ADC_DIGITAL_VOLUME_1L,
+ WM5100_ADC_DIGITAL_VOLUME_1R,
+ WM5100_ADC_DIGITAL_VOLUME_2L,
+ WM5100_ADC_DIGITAL_VOLUME_2R,
+ WM5100_ADC_DIGITAL_VOLUME_3L,
+ WM5100_ADC_DIGITAL_VOLUME_3R,
+ WM5100_ADC_DIGITAL_VOLUME_4L,
+ WM5100_ADC_DIGITAL_VOLUME_4R,
+
+ WM5100_DAC_DIGITAL_VOLUME_1L,
+ WM5100_DAC_DIGITAL_VOLUME_1R,
+ WM5100_DAC_DIGITAL_VOLUME_2L,
+ WM5100_DAC_DIGITAL_VOLUME_2R,
+ WM5100_DAC_DIGITAL_VOLUME_3L,
+ WM5100_DAC_DIGITAL_VOLUME_3R,
+ WM5100_DAC_DIGITAL_VOLUME_4L,
+ WM5100_DAC_DIGITAL_VOLUME_4R,
+ WM5100_DAC_DIGITAL_VOLUME_5L,
+ WM5100_DAC_DIGITAL_VOLUME_5R,
+ WM5100_DAC_DIGITAL_VOLUME_6L,
+ WM5100_DAC_DIGITAL_VOLUME_6R,
+};
+
+static void wm5100_set_detect_mode(struct wm5100_priv *wm5100, int the_mode)
+{
+ struct wm5100_jack_mode *mode = &wm5100->pdata.jack_modes[the_mode];
+
+ BUG_ON(the_mode >= ARRAY_SIZE(wm5100->pdata.jack_modes));
+
+ gpio_set_value_cansleep(wm5100->pdata.hp_pol, mode->hp_pol);
+ regmap_update_bits(wm5100->regmap, WM5100_ACCESSORY_DETECT_MODE_1,
+ WM5100_ACCDET_BIAS_SRC_MASK |
+ WM5100_ACCDET_SRC,
+ (mode->bias << WM5100_ACCDET_BIAS_SRC_SHIFT) |
+ mode->micd_src << WM5100_ACCDET_SRC_SHIFT);
+ regmap_update_bits(wm5100->regmap, WM5100_MISC_CONTROL,
+ WM5100_HPCOM_SRC,
+ mode->micd_src << WM5100_HPCOM_SRC_SHIFT);
+
+ wm5100->jack_mode = the_mode;
+
+ dev_dbg(wm5100->dev, "Set microphone polarity to %d\n",
+ wm5100->jack_mode);
+}
+
+static void wm5100_report_headphone(struct wm5100_priv *wm5100)
+{
+ dev_dbg(wm5100->dev, "Headphone detected\n");
+ wm5100->jack_detecting = false;
+ snd_soc_jack_report(wm5100->jack, SND_JACK_HEADPHONE,
+ SND_JACK_HEADPHONE);
+
+ /* Increase the detection rate a bit for responsiveness. */
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ 7 << WM5100_ACCDET_RATE_SHIFT);
+}
+
+static void wm5100_micd_irq(struct wm5100_priv *wm5100)
+{
+ unsigned int val;
+ int ret;
+
+ ret = regmap_read(wm5100->regmap, WM5100_MIC_DETECT_3, &val);
+ if (ret != 0) {
+ dev_err(wm5100->dev, "Failed to read micropone status: %d\n",
+ ret);
+ return;
+ }
+
+ dev_dbg(wm5100->dev, "Microphone event: %x\n", val);
+
+ if (!(val & WM5100_ACCDET_VALID)) {
+ dev_warn(wm5100->dev, "Microphone detection state invalid\n");
+ return;
+ }
+
+ /* No accessory, reset everything and report removal */
+ if (!(val & WM5100_ACCDET_STS)) {
+ dev_dbg(wm5100->dev, "Jack removal detected\n");
+ wm5100->jack_mic = false;
+ wm5100->jack_detecting = true;
+ wm5100->jack_flips = 0;
+ snd_soc_jack_report(wm5100->jack, 0,
+ SND_JACK_LINEOUT | SND_JACK_HEADSET |
+ SND_JACK_BTN_0);
+
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ WM5100_ACCDET_RATE_MASK);
+ return;
+ }
+
+ /* If the measurement is very high we've got a microphone,
+ * either we just detected one or if we already reported then
+ * we've got a button release event.
+ */
+ if (val & 0x400) {
+ if (wm5100->jack_detecting) {
+ dev_dbg(wm5100->dev, "Microphone detected\n");
+ wm5100->jack_mic = true;
+ wm5100->jack_detecting = false;
+ snd_soc_jack_report(wm5100->jack,
+ SND_JACK_HEADSET,
+ SND_JACK_HEADSET | SND_JACK_BTN_0);
+
+ /* Increase poll rate to give better responsiveness
+ * for buttons */
+ regmap_update_bits(wm5100->regmap, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_RATE_MASK,
+ 5 << WM5100_ACCDET_RATE_SHIFT);
+ } else {
+ dev_dbg(wm5100->dev, "Mic button up\n");
+ snd_soc_jack_report(wm5100->jack, 0, SND_JACK_BTN_0);
+ }
+
+ return;
+ }
+
+ /* If we detected a lower impedence during initial startup
+ * then we probably have the wrong polarity, flip it. Don't
+ * do this for the lowest impedences to speed up detection of
+ * plain headphones and give up if neither polarity looks
+ * sensible.
+ */
+ if (wm5100->jack_detecting && (val & 0x3f8)) {
+ wm5100->jack_flips++;
+
+ if (wm5100->jack_flips > 1)
+ wm5100_report_headphone(wm5100);
+ else
+ wm5100_set_detect_mode(wm5100, !wm5100->jack_mode);
+
+ return;
+ }
+
+ /* Don't distinguish between buttons, just report any low
+ * impedence as BTN_0.
+ */
+ if (val & 0x3fc) {
+ if (wm5100->jack_mic) {
+ dev_dbg(wm5100->dev, "Mic button detected\n");
+ snd_soc_jack_report(wm5100->jack, SND_JACK_BTN_0,
+ SND_JACK_BTN_0);
+ } else if (wm5100->jack_detecting) {
+ wm5100_report_headphone(wm5100);
+ }
+ }
+}
+
+int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
+{
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+
+ if (jack) {
+ wm5100->jack = jack;
+ wm5100->jack_detecting = true;
+ wm5100->jack_flips = 0;
+
+ wm5100_set_detect_mode(wm5100, 0);
+
+ /* Slowest detection rate, gives debounce for initial
+ * detection */
+ snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_BIAS_STARTTIME_MASK |
+ WM5100_ACCDET_RATE_MASK,
+ (7 << WM5100_ACCDET_BIAS_STARTTIME_SHIFT) |
+ WM5100_ACCDET_RATE_MASK);
+
+ /* We need the charge pump to power MICBIAS */
+ snd_soc_dapm_force_enable_pin(&codec->dapm, "CP2");
+ snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
+ snd_soc_dapm_sync(&codec->dapm);
+
+ /* We start off just enabling microphone detection - even a
+ * plain headphone will trigger detection.
+ */
+ snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_ENA, WM5100_ACCDET_ENA);
+
+ snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK,
+ WM5100_IM_ACCDET_EINT, 0);
+ } else {
+ snd_soc_update_bits(codec, WM5100_INTERRUPT_STATUS_3_MASK,
+ WM5100_IM_HPDET_EINT |
+ WM5100_IM_ACCDET_EINT,
+ WM5100_IM_HPDET_EINT |
+ WM5100_IM_ACCDET_EINT);
+ snd_soc_update_bits(codec, WM5100_MIC_DETECT_1,
+ WM5100_ACCDET_ENA, 0);
+ wm5100->jack = NULL;
+ }
+
+ return 0;
+}
+
+static irqreturn_t wm5100_irq(int irq, void *data)
+{
+ struct wm5100_priv *wm5100 = data;
+ irqreturn_t status = IRQ_NONE;
+ unsigned int irq_val, mask_val;
+ int ret;
+
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, &irq_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ status 3: %d\n",
+ ret);
+ irq_val = 0;
+ }
+
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_3_MASK,
+ &mask_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ mask 3: %d\n",
+ ret);
+ mask_val = 0xffff;
+ }
+
+ irq_val &= ~mask_val;
+
+ regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_3, irq_val);
+
+ if (irq_val)
+ status = IRQ_HANDLED;
+
+ wm5100_log_status3(wm5100, irq_val);
+
+ if (irq_val & WM5100_FLL1_LOCK_EINT) {
+ dev_dbg(wm5100->dev, "FLL1 locked\n");
+ complete(&wm5100->fll[0].lock);
+ }
+ if (irq_val & WM5100_FLL2_LOCK_EINT) {
+ dev_dbg(wm5100->dev, "FLL2 locked\n");
+ complete(&wm5100->fll[1].lock);
+ }
+
+ if (irq_val & WM5100_ACCDET_EINT)
+ wm5100_micd_irq(wm5100);
+
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, &irq_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ status 4: %d\n",
+ ret);
+ irq_val = 0;
+ }
+
+ ret = regmap_read(wm5100->regmap, WM5100_INTERRUPT_STATUS_4_MASK,
+ &mask_val);
+ if (ret < 0) {
+ dev_err(wm5100->dev, "Failed to read IRQ mask 4: %d\n",
+ ret);
+ mask_val = 0xffff;
+ }
+
+ irq_val &= ~mask_val;
+
+ if (irq_val)
+ status = IRQ_HANDLED;
+
+ regmap_write(wm5100->regmap, WM5100_INTERRUPT_STATUS_4, irq_val);
+
+ wm5100_log_status4(wm5100, irq_val);
+
+ return status;
+}
+
+static irqreturn_t wm5100_edge_irq(int irq, void *data)
+{
+ irqreturn_t ret = IRQ_NONE;
+ irqreturn_t val;
+
+ do {
+ val = wm5100_irq(irq, data);
+ if (val != IRQ_NONE)
+ ret = val;
+ } while (val != IRQ_NONE);
+
+ return ret;
+}
+
+#ifdef CONFIG_GPIOLIB
+static inline struct wm5100_priv *gpio_to_wm5100(struct gpio_chip *chip)
+{
+ return container_of(chip, struct wm5100_priv, gpio_chip);
+}
+
+static void wm5100_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+ struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+
+ regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
+ WM5100_GP1_LVL, !!value << WM5100_GP1_LVL_SHIFT);
+}
+
+static int wm5100_gpio_direction_out(struct gpio_chip *chip,
+ unsigned offset, int value)
+{
+ struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+ int val, ret;
+
+ val = (1 << WM5100_GP1_FN_SHIFT) | (!!value << WM5100_GP1_LVL_SHIFT);
+
+ ret = regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
+ WM5100_GP1_FN_MASK | WM5100_GP1_DIR |
+ WM5100_GP1_LVL, val);
+ if (ret < 0)
+ return ret;
+ else
+ return 0;
+}
+
+static int wm5100_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+ struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+ unsigned int reg;
+ int ret;
+
+ ret = regmap_read(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset, &reg);
+ if (ret < 0)
+ return ret;
+
+ return (reg & WM5100_GP1_LVL) != 0;
+}
+
+static int wm5100_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
+{
+ struct wm5100_priv *wm5100 = gpio_to_wm5100(chip);
+
+ return regmap_update_bits(wm5100->regmap, WM5100_GPIO_CTRL_1 + offset,
+ WM5100_GP1_FN_MASK | WM5100_GP1_DIR,
+ (1 << WM5100_GP1_FN_SHIFT) |
+ (1 << WM5100_GP1_DIR_SHIFT));
+}
+
+static struct gpio_chip wm5100_template_chip = {
+ .label = "wm5100",
+ .owner = THIS_MODULE,
+ .direction_output = wm5100_gpio_direction_out,
+ .set = wm5100_gpio_set,
+ .direction_input = wm5100_gpio_direction_in,
+ .get = wm5100_gpio_get,
+ .can_sleep = 1,
+};
+
+static void wm5100_init_gpio(struct i2c_client *i2c)
+{
+ struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
+ int ret;
+
+ wm5100->gpio_chip = wm5100_template_chip;
+ wm5100->gpio_chip.ngpio = 6;
+ wm5100->gpio_chip.dev = &i2c->dev;
+
+ if (wm5100->pdata.gpio_base)
+ wm5100->gpio_chip.base = wm5100->pdata.gpio_base;
+ else
+ wm5100->gpio_chip.base = -1;
+
+ ret = gpiochip_add(&wm5100->gpio_chip);
+ if (ret != 0)
+ dev_err(&i2c->dev, "Failed to add GPIOs: %d\n", ret);
+}
+
+static void wm5100_free_gpio(struct i2c_client *i2c)
+{
+ struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
+ int ret;
+
+ ret = gpiochip_remove(&wm5100->gpio_chip);
+ if (ret != 0)
+ dev_err(&i2c->dev, "Failed to remove GPIOs: %d\n", ret);
+}
+#else
+static void wm5100_init_gpio(struct i2c_client *i2c)
+{
+}
+
+static void wm5100_free_gpio(struct i2c_client *i2c)
+{
+}
+#endif
+
+static int wm5100_probe(struct snd_soc_codec *codec)
+{
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+ int ret, i;
+
+ wm5100->codec = codec;
+ codec->control_data = wm5100->regmap;
+
+ ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
+ return ret;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm5100_dig_vu); i++)
+ snd_soc_update_bits(codec, wm5100_dig_vu[i], WM5100_OUT_VU,
+ WM5100_OUT_VU);
+
+ /* Don't debounce interrupts to support use of SYSCLK only */
+ snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_1, 0);
+ snd_soc_write(codec, WM5100_IRQ_DEBOUNCE_2, 0);
+
+ /* TODO: check if we're symmetric */
+
+ if (i2c->irq)
+ snd_soc_dapm_new_controls(&codec->dapm,
+ wm5100_dapm_widgets_noirq,
+ ARRAY_SIZE(wm5100_dapm_widgets_noirq));
+
+ if (wm5100->pdata.hp_pol) {
+ ret = gpio_request_one(wm5100->pdata.hp_pol,
+ GPIOF_OUT_INIT_HIGH, "WM5100 HP_POL");
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to request HP_POL %d: %d\n",
+ wm5100->pdata.hp_pol, ret);
+ goto err_gpio;
+ }
+ }
+
+ return 0;
+
+err_gpio:
+
+ return ret;
+}
+
+static int wm5100_remove(struct snd_soc_codec *codec)
+{
+ struct wm5100_priv *wm5100 = snd_soc_codec_get_drvdata(codec);
+
+ if (wm5100->pdata.hp_pol) {
+ gpio_free(wm5100->pdata.hp_pol);
+ }
+
+ return 0;
+}
+
+static int wm5100_soc_volatile(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ return true;
+}
+
+
+static struct snd_soc_codec_driver soc_codec_dev_wm5100 = {
+ .probe = wm5100_probe,
+ .remove = wm5100_remove,
+
+ .set_sysclk = wm5100_set_sysclk,
+ .set_pll = wm5100_set_fll,
+ .idle_bias_off = 1,
+ .reg_cache_size = WM5100_MAX_REGISTER,
+ .volatile_register = wm5100_soc_volatile,
+
+ .seq_notifier = wm5100_seq_notifier,
+ .controls = wm5100_snd_controls,
+ .num_controls = ARRAY_SIZE(wm5100_snd_controls),
+ .dapm_widgets = wm5100_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm5100_dapm_widgets),
+ .dapm_routes = wm5100_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm5100_dapm_routes),
+};
+
+static const struct regmap_config wm5100_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .max_register = WM5100_MAX_REGISTER,
+ .reg_defaults = wm5100_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm5100_reg_defaults),
+ .volatile_reg = wm5100_volatile_register,
+ .readable_reg = wm5100_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
+static const unsigned int wm5100_mic_ctrl_reg[] = {
+ WM5100_IN1L_CONTROL,
+ WM5100_IN2L_CONTROL,
+ WM5100_IN3L_CONTROL,
+ WM5100_IN4L_CONTROL,
+};
+
+static __devinit int wm5100_i2c_probe(struct i2c_client *i2c,
+ const struct i2c_device_id *id)
+{
+ struct wm5100_pdata *pdata = dev_get_platdata(&i2c->dev);
+ struct wm5100_priv *wm5100;
+ unsigned int reg;
+ int ret, i, irq_flags;
+
+ wm5100 = devm_kzalloc(&i2c->dev, sizeof(struct wm5100_priv),
+ GFP_KERNEL);
+ if (wm5100 == NULL)
+ return -ENOMEM;
+
+ wm5100->dev = &i2c->dev;
+
+ wm5100->regmap = regmap_init_i2c(i2c, &wm5100_regmap);
+ if (IS_ERR(wm5100->regmap)) {
+ ret = PTR_ERR(wm5100->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm5100->fll); i++)
+ init_completion(&wm5100->fll[i].lock);
+
+ if (pdata)
+ wm5100->pdata = *pdata;
+
+ i2c_set_clientdata(i2c, wm5100);
+
+ for (i = 0; i < ARRAY_SIZE(wm5100->core_supplies); i++)
+ wm5100->core_supplies[i].supply = wm5100_core_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&i2c->dev,
+ ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request core supplies: %d\n",
+ ret);
+ goto err_regmap;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to enable core supplies: %d\n",
+ ret);
+ goto err_regmap;
+ }
+
+ if (wm5100->pdata.ldo_ena) {
+ ret = gpio_request_one(wm5100->pdata.ldo_ena,
+ GPIOF_OUT_INIT_HIGH, "WM5100 LDOENA");
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to request LDOENA %d: %d\n",
+ wm5100->pdata.ldo_ena, ret);
+ goto err_enable;
+ }
+ msleep(2);
+ }
+
+ if (wm5100->pdata.reset) {
+ ret = gpio_request_one(wm5100->pdata.reset,
+ GPIOF_OUT_INIT_HIGH, "WM5100 /RESET");
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to request /RESET %d: %d\n",
+ wm5100->pdata.reset, ret);
+ goto err_ldo;
+ }
+ }
+
+ ret = regmap_read(wm5100->regmap, WM5100_SOFTWARE_RESET, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+ goto err_reset;
+ }
+ switch (reg) {
+ case 0x8997:
+ case 0x5100:
+ break;
+
+ default:
+ dev_err(&i2c->dev, "Device is not a WM5100, ID is %x\n", reg);
+ ret = -EINVAL;
+ goto err_reset;
+ }
+
+ ret = regmap_read(wm5100->regmap, WM5100_DEVICE_REVISION, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read revision register\n");
+ goto err_reset;
+ }
+ wm5100->rev = reg & WM5100_DEVICE_REVISION_MASK;
+
+ dev_info(&i2c->dev, "revision %c\n", wm5100->rev + 'A');
+
+ ret = wm5100_reset(wm5100);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to issue reset\n");
+ goto err_reset;
+ }
+
+ switch (wm5100->rev) {
+ case 0:
+ ret = regmap_register_patch(wm5100->regmap,
+ wm5100_reva_patches,
+ ARRAY_SIZE(wm5100_reva_patches));
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register patches: %d\n",
+ ret);
+ goto err_reset;
+ }
+ break;
+ default:
+ break;
+ }
+
+
+ wm5100_init_gpio(i2c);
+
+ for (i = 0; i < ARRAY_SIZE(wm5100->pdata.gpio_defaults); i++) {
+ if (!wm5100->pdata.gpio_defaults[i])
+ continue;
+
+ regmap_write(wm5100->regmap, WM5100_GPIO_CTRL_1 + i,
+ wm5100->pdata.gpio_defaults[i]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(wm5100->pdata.in_mode); i++) {
+ regmap_update_bits(wm5100->regmap, wm5100_mic_ctrl_reg[i],
+ WM5100_IN1_MODE_MASK |
+ WM5100_IN1_DMIC_SUP_MASK,
+ (wm5100->pdata.in_mode[i] <<
+ WM5100_IN1_MODE_SHIFT) |
+ (wm5100->pdata.dmic_sup[i] <<
+ WM5100_IN1_DMIC_SUP_SHIFT));
+ }
+
+ if (i2c->irq) {
+ if (wm5100->pdata.irq_flags)
+ irq_flags = wm5100->pdata.irq_flags;
+ else
+ irq_flags = IRQF_TRIGGER_LOW;
+
+ irq_flags |= IRQF_ONESHOT;
+
+ if (irq_flags & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING))
+ ret = request_threaded_irq(i2c->irq, NULL,
+ wm5100_edge_irq, irq_flags,
+ "wm5100", wm5100);
+ else
+ ret = request_threaded_irq(i2c->irq, NULL, wm5100_irq,
+ irq_flags, "wm5100",
+ wm5100);
+
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
+ i2c->irq, ret);
+ } else {
+ /* Enable default interrupts */
+ regmap_update_bits(wm5100->regmap,
+ WM5100_INTERRUPT_STATUS_3_MASK,
+ WM5100_IM_SPK_SHUTDOWN_WARN_EINT |
+ WM5100_IM_SPK_SHUTDOWN_EINT |
+ WM5100_IM_ASRC2_LOCK_EINT |
+ WM5100_IM_ASRC1_LOCK_EINT |
+ WM5100_IM_FLL2_LOCK_EINT |
+ WM5100_IM_FLL1_LOCK_EINT |
+ WM5100_CLKGEN_ERR_EINT |
+ WM5100_CLKGEN_ERR_ASYNC_EINT, 0);
+
+ regmap_update_bits(wm5100->regmap,
+ WM5100_INTERRUPT_STATUS_4_MASK,
+ WM5100_AIF3_ERR_EINT |
+ WM5100_AIF2_ERR_EINT |
+ WM5100_AIF1_ERR_EINT |
+ WM5100_CTRLIF_ERR_EINT |
+ WM5100_ISRC2_UNDERCLOCKED_EINT |
+ WM5100_ISRC1_UNDERCLOCKED_EINT |
+ WM5100_FX_UNDERCLOCKED_EINT |
+ WM5100_AIF3_UNDERCLOCKED_EINT |
+ WM5100_AIF2_UNDERCLOCKED_EINT |
+ WM5100_AIF1_UNDERCLOCKED_EINT |
+ WM5100_ASRC_UNDERCLOCKED_EINT |
+ WM5100_DAC_UNDERCLOCKED_EINT |
+ WM5100_ADC_UNDERCLOCKED_EINT |
+ WM5100_MIXER_UNDERCLOCKED_EINT, 0);
+ }
+ }
+
+ pm_runtime_set_active(&i2c->dev);
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
+
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm5100, wm5100_dai,
+ ARRAY_SIZE(wm5100_dai));
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to register WM5100: %d\n", ret);
+ goto err_reset;
+ }
+
+ return ret;
+
+err_reset:
+ if (i2c->irq)
+ free_irq(i2c->irq, wm5100);
+ wm5100_free_gpio(i2c);
+ if (wm5100->pdata.reset) {
+ gpio_set_value_cansleep(wm5100->pdata.reset, 0);
+ gpio_free(wm5100->pdata.reset);
+ }
+err_ldo:
+ if (wm5100->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+ gpio_free(wm5100->pdata.ldo_ena);
+ }
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
+err_regmap:
+ regmap_exit(wm5100->regmap);
+err:
+ return ret;
+}
+
+static __devexit int wm5100_i2c_remove(struct i2c_client *i2c)
+{
+ struct wm5100_priv *wm5100 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ if (i2c->irq)
+ free_irq(i2c->irq, wm5100);
+ wm5100_free_gpio(i2c);
+ if (wm5100->pdata.reset) {
+ gpio_set_value_cansleep(wm5100->pdata.reset, 0);
+ gpio_free(wm5100->pdata.reset);
+ }
+ if (wm5100->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+ gpio_free(wm5100->pdata.ldo_ena);
+ }
+ regmap_exit(wm5100->regmap);
+
+ return 0;
+}
+
+#ifdef CONFIG_PM_RUNTIME
+static int wm5100_runtime_suspend(struct device *dev)
+{
+ struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+
+ regcache_cache_only(wm5100->regmap, true);
+ regcache_mark_dirty(wm5100->regmap);
+ if (wm5100->pdata.ldo_ena)
+ gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 0);
+ regulator_bulk_disable(ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
+
+ return 0;
+}
+
+static int wm5100_runtime_resume(struct device *dev)
+{
+ struct wm5100_priv *wm5100 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm5100->core_supplies),
+ wm5100->core_supplies);
+ if (ret != 0) {
+ dev_err(dev, "Failed to enable supplies: %d\n",
+ ret);
+ return ret;
+ }
+
+ if (wm5100->pdata.ldo_ena) {
+ gpio_set_value_cansleep(wm5100->pdata.ldo_ena, 1);
+ msleep(2);
+ }
+
+ regcache_cache_only(wm5100->regmap, false);
+ regcache_sync(wm5100->regmap);
+
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops wm5100_pm = {
+ SET_RUNTIME_PM_OPS(wm5100_runtime_suspend, wm5100_runtime_resume,
+ NULL)
+};
+
+static const struct i2c_device_id wm5100_i2c_id[] = {
+ { "wm5100", 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(i2c, wm5100_i2c_id);
+
+static struct i2c_driver wm5100_i2c_driver = {
+ .driver = {
+ .name = "wm5100",
+ .owner = THIS_MODULE,
+ .pm = &wm5100_pm,
+ },
+ .probe = wm5100_i2c_probe,
+ .remove = __devexit_p(wm5100_i2c_remove),
+ .id_table = wm5100_i2c_id,
+};
+
+static int __init wm5100_modinit(void)
+{
+ return i2c_add_driver(&wm5100_i2c_driver);
+}
+module_init(wm5100_modinit);
+
+static void __exit wm5100_exit(void)
+{
+ i2c_del_driver(&wm5100_i2c_driver);
+}
+module_exit(wm5100_exit);
+
+MODULE_DESCRIPTION("ASoC WM5100 driver");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm5100.h b/sound/soc/codecs/wm5100.h
new file mode 100644
index 000000000000..25cb6016f9d7
--- /dev/null
+++ b/sound/soc/codecs/wm5100.h
@@ -0,0 +1,5156 @@
+/*
+ * wm5100.h -- WM5100 ALSA SoC Audio driver
+ *
+ * Copyright 2011 Wolfson Microelectronics plc
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef WM5100_ASOC_H
+#define WM5100_ASOC_H
+
+#include <sound/soc.h>
+#include <linux/regmap.h>
+
+int wm5100_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack);
+
+#define WM5100_CLK_AIF1 1
+#define WM5100_CLK_AIF2 2
+#define WM5100_CLK_AIF3 3
+#define WM5100_CLK_SYSCLK 4
+#define WM5100_CLK_ASYNCCLK 5
+#define WM5100_CLK_32KHZ 6
+#define WM5100_CLK_OPCLK 7
+
+#define WM5100_CLKSRC_MCLK1 0
+#define WM5100_CLKSRC_MCLK2 1
+#define WM5100_CLKSRC_SYSCLK 2
+#define WM5100_CLKSRC_FLL1 4
+#define WM5100_CLKSRC_FLL2 5
+#define WM5100_CLKSRC_AIF1BCLK 8
+#define WM5100_CLKSRC_AIF2BCLK 9
+#define WM5100_CLKSRC_AIF3BCLK 10
+#define WM5100_CLKSRC_ASYNCCLK 0x100
+
+#define WM5100_FLL1 1
+#define WM5100_FLL2 2
+
+#define WM5100_FLL_SRC_MCLK1 0x0
+#define WM5100_FLL_SRC_MCLK2 0x1
+#define WM5100_FLL_SRC_FLL1 0x4
+#define WM5100_FLL_SRC_FLL2 0x5
+#define WM5100_FLL_SRC_AIF1BCLK 0x8
+#define WM5100_FLL_SRC_AIF2BCLK 0x9
+#define WM5100_FLL_SRC_AIF3BCLK 0xa
+
+/*
+ * Register values.
+ */
+#define WM5100_SOFTWARE_RESET 0x00
+#define WM5100_DEVICE_REVISION 0x01
+#define WM5100_CTRL_IF_1 0x10
+#define WM5100_TONE_GENERATOR_1 0x20
+#define WM5100_PWM_DRIVE_1 0x30
+#define WM5100_PWM_DRIVE_2 0x31
+#define WM5100_PWM_DRIVE_3 0x32
+#define WM5100_CLOCKING_1 0x100
+#define WM5100_CLOCKING_3 0x101
+#define WM5100_CLOCKING_4 0x102
+#define WM5100_CLOCKING_5 0x103
+#define WM5100_CLOCKING_6 0x104
+#define WM5100_CLOCKING_7 0x107
+#define WM5100_CLOCKING_8 0x108
+#define WM5100_ASRC_ENABLE 0x120
+#define WM5100_ASRC_STATUS 0x121
+#define WM5100_ASRC_RATE1 0x122
+#define WM5100_ISRC_1_CTRL_1 0x141
+#define WM5100_ISRC_1_CTRL_2 0x142
+#define WM5100_ISRC_2_CTRL1 0x143
+#define WM5100_ISRC_2_CTRL_2 0x144
+#define WM5100_FLL1_CONTROL_1 0x182
+#define WM5100_FLL1_CONTROL_2 0x183
+#define WM5100_FLL1_CONTROL_3 0x184
+#define WM5100_FLL1_CONTROL_5 0x186
+#define WM5100_FLL1_CONTROL_6 0x187
+#define WM5100_FLL1_EFS_1 0x188
+#define WM5100_FLL2_CONTROL_1 0x1A2
+#define WM5100_FLL2_CONTROL_2 0x1A3
+#define WM5100_FLL2_CONTROL_3 0x1A4
+#define WM5100_FLL2_CONTROL_5 0x1A6
+#define WM5100_FLL2_CONTROL_6 0x1A7
+#define WM5100_FLL2_EFS_1 0x1A8
+#define WM5100_MIC_CHARGE_PUMP_1 0x200
+#define WM5100_MIC_CHARGE_PUMP_2 0x201
+#define WM5100_HP_CHARGE_PUMP_1 0x202
+#define WM5100_LDO1_CONTROL 0x211
+#define WM5100_MIC_BIAS_CTRL_1 0x215
+#define WM5100_MIC_BIAS_CTRL_2 0x216
+#define WM5100_MIC_BIAS_CTRL_3 0x217
+#define WM5100_ACCESSORY_DETECT_MODE_1 0x280
+#define WM5100_HEADPHONE_DETECT_1 0x288
+#define WM5100_HEADPHONE_DETECT_2 0x289
+#define WM5100_MIC_DETECT_1 0x290
+#define WM5100_MIC_DETECT_2 0x291
+#define WM5100_MIC_DETECT_3 0x292
+#define WM5100_MISC_CONTROL 0x2BB
+#define WM5100_INPUT_ENABLES 0x301
+#define WM5100_INPUT_ENABLES_STATUS 0x302
+#define WM5100_IN1L_CONTROL 0x310
+#define WM5100_IN1R_CONTROL 0x311
+#define WM5100_IN2L_CONTROL 0x312
+#define WM5100_IN2R_CONTROL 0x313
+#define WM5100_IN3L_CONTROL 0x314
+#define WM5100_IN3R_CONTROL 0x315
+#define WM5100_IN4L_CONTROL 0x316
+#define WM5100_IN4R_CONTROL 0x317
+#define WM5100_RXANC_SRC 0x318
+#define WM5100_INPUT_VOLUME_RAMP 0x319
+#define WM5100_ADC_DIGITAL_VOLUME_1L 0x320
+#define WM5100_ADC_DIGITAL_VOLUME_1R 0x321
+#define WM5100_ADC_DIGITAL_VOLUME_2L 0x322
+#define WM5100_ADC_DIGITAL_VOLUME_2R 0x323
+#define WM5100_ADC_DIGITAL_VOLUME_3L 0x324
+#define WM5100_ADC_DIGITAL_VOLUME_3R 0x325
+#define WM5100_ADC_DIGITAL_VOLUME_4L 0x326
+#define WM5100_ADC_DIGITAL_VOLUME_4R 0x327
+#define WM5100_OUTPUT_ENABLES_2 0x401
+#define WM5100_OUTPUT_STATUS_1 0x402
+#define WM5100_OUTPUT_STATUS_2 0x403
+#define WM5100_CHANNEL_ENABLES_1 0x408
+#define WM5100_OUT_VOLUME_1L 0x410
+#define WM5100_OUT_VOLUME_1R 0x411
+#define WM5100_DAC_VOLUME_LIMIT_1L 0x412
+#define WM5100_DAC_VOLUME_LIMIT_1R 0x413
+#define WM5100_OUT_VOLUME_2L 0x414
+#define WM5100_OUT_VOLUME_2R 0x415
+#define WM5100_DAC_VOLUME_LIMIT_2L 0x416
+#define WM5100_DAC_VOLUME_LIMIT_2R 0x417
+#define WM5100_OUT_VOLUME_3L 0x418
+#define WM5100_OUT_VOLUME_3R 0x419
+#define WM5100_DAC_VOLUME_LIMIT_3L 0x41A
+#define WM5100_DAC_VOLUME_LIMIT_3R 0x41B
+#define WM5100_OUT_VOLUME_4L 0x41C
+#define WM5100_OUT_VOLUME_4R 0x41D
+#define WM5100_DAC_VOLUME_LIMIT_5L 0x41E
+#define WM5100_DAC_VOLUME_LIMIT_5R 0x41F
+#define WM5100_DAC_VOLUME_LIMIT_6L 0x420
+#define WM5100_DAC_VOLUME_LIMIT_6R 0x421
+#define WM5100_DAC_AEC_CONTROL_1 0x440
+#define WM5100_OUTPUT_VOLUME_RAMP 0x441
+#define WM5100_DAC_DIGITAL_VOLUME_1L 0x480
+#define WM5100_DAC_DIGITAL_VOLUME_1R 0x481
+#define WM5100_DAC_DIGITAL_VOLUME_2L 0x482
+#define WM5100_DAC_DIGITAL_VOLUME_2R 0x483
+#define WM5100_DAC_DIGITAL_VOLUME_3L 0x484
+#define WM5100_DAC_DIGITAL_VOLUME_3R 0x485
+#define WM5100_DAC_DIGITAL_VOLUME_4L 0x486
+#define WM5100_DAC_DIGITAL_VOLUME_4R 0x487
+#define WM5100_DAC_DIGITAL_VOLUME_5L 0x488
+#define WM5100_DAC_DIGITAL_VOLUME_5R 0x489
+#define WM5100_DAC_DIGITAL_VOLUME_6L 0x48A
+#define WM5100_DAC_DIGITAL_VOLUME_6R 0x48B
+#define WM5100_PDM_SPK1_CTRL_1 0x4C0
+#define WM5100_PDM_SPK1_CTRL_2 0x4C1
+#define WM5100_PDM_SPK2_CTRL_1 0x4C2
+#define WM5100_PDM_SPK2_CTRL_2 0x4C3
+#define WM5100_AUDIO_IF_1_1 0x500
+#define WM5100_AUDIO_IF_1_2 0x501
+#define WM5100_AUDIO_IF_1_3 0x502
+#define WM5100_AUDIO_IF_1_4 0x503
+#define WM5100_AUDIO_IF_1_5 0x504
+#define WM5100_AUDIO_IF_1_6 0x505
+#define WM5100_AUDIO_IF_1_7 0x506
+#define WM5100_AUDIO_IF_1_8 0x507
+#define WM5100_AUDIO_IF_1_9 0x508
+#define WM5100_AUDIO_IF_1_10 0x509
+#define WM5100_AUDIO_IF_1_11 0x50A
+#define WM5100_AUDIO_IF_1_12 0x50B
+#define WM5100_AUDIO_IF_1_13 0x50C
+#define WM5100_AUDIO_IF_1_14 0x50D
+#define WM5100_AUDIO_IF_1_15 0x50E
+#define WM5100_AUDIO_IF_1_16 0x50F
+#define WM5100_AUDIO_IF_1_17 0x510
+#define WM5100_AUDIO_IF_1_18 0x511
+#define WM5100_AUDIO_IF_1_19 0x512
+#define WM5100_AUDIO_IF_1_20 0x513
+#define WM5100_AUDIO_IF_1_21 0x514
+#define WM5100_AUDIO_IF_1_22 0x515
+#define WM5100_AUDIO_IF_1_23 0x516
+#define WM5100_AUDIO_IF_1_24 0x517
+#define WM5100_AUDIO_IF_1_25 0x518
+#define WM5100_AUDIO_IF_1_26 0x519
+#define WM5100_AUDIO_IF_1_27 0x51A
+#define WM5100_AUDIO_IF_2_1 0x540
+#define WM5100_AUDIO_IF_2_2 0x541
+#define WM5100_AUDIO_IF_2_3 0x542
+#define WM5100_AUDIO_IF_2_4 0x543
+#define WM5100_AUDIO_IF_2_5 0x544
+#define WM5100_AUDIO_IF_2_6 0x545
+#define WM5100_AUDIO_IF_2_7 0x546
+#define WM5100_AUDIO_IF_2_8 0x547
+#define WM5100_AUDIO_IF_2_9 0x548
+#define WM5100_AUDIO_IF_2_10 0x549
+#define WM5100_AUDIO_IF_2_11 0x54A
+#define WM5100_AUDIO_IF_2_18 0x551
+#define WM5100_AUDIO_IF_2_19 0x552
+#define WM5100_AUDIO_IF_2_26 0x559
+#define WM5100_AUDIO_IF_2_27 0x55A
+#define WM5100_AUDIO_IF_3_1 0x580
+#define WM5100_AUDIO_IF_3_2 0x581
+#define WM5100_AUDIO_IF_3_3 0x582
+#define WM5100_AUDIO_IF_3_4 0x583
+#define WM5100_AUDIO_IF_3_5 0x584
+#define WM5100_AUDIO_IF_3_6 0x585
+#define WM5100_AUDIO_IF_3_7 0x586
+#define WM5100_AUDIO_IF_3_8 0x587
+#define WM5100_AUDIO_IF_3_9 0x588
+#define WM5100_AUDIO_IF_3_10 0x589
+#define WM5100_AUDIO_IF_3_11 0x58A
+#define WM5100_AUDIO_IF_3_18 0x591
+#define WM5100_AUDIO_IF_3_19 0x592
+#define WM5100_AUDIO_IF_3_26 0x599
+#define WM5100_AUDIO_IF_3_27 0x59A
+#define WM5100_PWM1MIX_INPUT_1_SOURCE 0x640
+#define WM5100_PWM1MIX_INPUT_1_VOLUME 0x641
+#define WM5100_PWM1MIX_INPUT_2_SOURCE 0x642
+#define WM5100_PWM1MIX_INPUT_2_VOLUME 0x643
+#define WM5100_PWM1MIX_INPUT_3_SOURCE 0x644
+#define WM5100_PWM1MIX_INPUT_3_VOLUME 0x645
+#define WM5100_PWM1MIX_INPUT_4_SOURCE 0x646
+#define WM5100_PWM1MIX_INPUT_4_VOLUME 0x647
+#define WM5100_PWM2MIX_INPUT_1_SOURCE 0x648
+#define WM5100_PWM2MIX_INPUT_1_VOLUME 0x649
+#define WM5100_PWM2MIX_INPUT_2_SOURCE 0x64A
+#define WM5100_PWM2MIX_INPUT_2_VOLUME 0x64B
+#define WM5100_PWM2MIX_INPUT_3_SOURCE 0x64C
+#define WM5100_PWM2MIX_INPUT_3_VOLUME 0x64D
+#define WM5100_PWM2MIX_INPUT_4_SOURCE 0x64E
+#define WM5100_PWM2MIX_INPUT_4_VOLUME 0x64F
+#define WM5100_OUT1LMIX_INPUT_1_SOURCE 0x680
+#define WM5100_OUT1LMIX_INPUT_1_VOLUME 0x681
+#define WM5100_OUT1LMIX_INPUT_2_SOURCE 0x682
+#define WM5100_OUT1LMIX_INPUT_2_VOLUME 0x683
+#define WM5100_OUT1LMIX_INPUT_3_SOURCE 0x684
+#define WM5100_OUT1LMIX_INPUT_3_VOLUME 0x685
+#define WM5100_OUT1LMIX_INPUT_4_SOURCE 0x686
+#define WM5100_OUT1LMIX_INPUT_4_VOLUME 0x687
+#define WM5100_OUT1RMIX_INPUT_1_SOURCE 0x688
+#define WM5100_OUT1RMIX_INPUT_1_VOLUME 0x689
+#define WM5100_OUT1RMIX_INPUT_2_SOURCE 0x68A
+#define WM5100_OUT1RMIX_INPUT_2_VOLUME 0x68B
+#define WM5100_OUT1RMIX_INPUT_3_SOURCE 0x68C
+#define WM5100_OUT1RMIX_INPUT_3_VOLUME 0x68D
+#define WM5100_OUT1RMIX_INPUT_4_SOURCE 0x68E
+#define WM5100_OUT1RMIX_INPUT_4_VOLUME 0x68F
+#define WM5100_OUT2LMIX_INPUT_1_SOURCE 0x690
+#define WM5100_OUT2LMIX_INPUT_1_VOLUME 0x691
+#define WM5100_OUT2LMIX_INPUT_2_SOURCE 0x692
+#define WM5100_OUT2LMIX_INPUT_2_VOLUME 0x693
+#define WM5100_OUT2LMIX_INPUT_3_SOURCE 0x694
+#define WM5100_OUT2LMIX_INPUT_3_VOLUME 0x695
+#define WM5100_OUT2LMIX_INPUT_4_SOURCE 0x696
+#define WM5100_OUT2LMIX_INPUT_4_VOLUME 0x697
+#define WM5100_OUT2RMIX_INPUT_1_SOURCE 0x698
+#define WM5100_OUT2RMIX_INPUT_1_VOLUME 0x699
+#define WM5100_OUT2RMIX_INPUT_2_SOURCE 0x69A
+#define WM5100_OUT2RMIX_INPUT_2_VOLUME 0x69B
+#define WM5100_OUT2RMIX_INPUT_3_SOURCE 0x69C
+#define WM5100_OUT2RMIX_INPUT_3_VOLUME 0x69D
+#define WM5100_OUT2RMIX_INPUT_4_SOURCE 0x69E
+#define WM5100_OUT2RMIX_INPUT_4_VOLUME 0x69F
+#define WM5100_OUT3LMIX_INPUT_1_SOURCE 0x6A0
+#define WM5100_OUT3LMIX_INPUT_1_VOLUME 0x6A1
+#define WM5100_OUT3LMIX_INPUT_2_SOURCE 0x6A2
+#define WM5100_OUT3LMIX_INPUT_2_VOLUME 0x6A3
+#define WM5100_OUT3LMIX_INPUT_3_SOURCE 0x6A4
+#define WM5100_OUT3LMIX_INPUT_3_VOLUME 0x6A5
+#define WM5100_OUT3LMIX_INPUT_4_SOURCE 0x6A6
+#define WM5100_OUT3LMIX_INPUT_4_VOLUME 0x6A7
+#define WM5100_OUT3RMIX_INPUT_1_SOURCE 0x6A8
+#define WM5100_OUT3RMIX_INPUT_1_VOLUME 0x6A9
+#define WM5100_OUT3RMIX_INPUT_2_SOURCE 0x6AA
+#define WM5100_OUT3RMIX_INPUT_2_VOLUME 0x6AB
+#define WM5100_OUT3RMIX_INPUT_3_SOURCE 0x6AC
+#define WM5100_OUT3RMIX_INPUT_3_VOLUME 0x6AD
+#define WM5100_OUT3RMIX_INPUT_4_SOURCE 0x6AE
+#define WM5100_OUT3RMIX_INPUT_4_VOLUME 0x6AF
+#define WM5100_OUT4LMIX_INPUT_1_SOURCE 0x6B0
+#define WM5100_OUT4LMIX_INPUT_1_VOLUME 0x6B1
+#define WM5100_OUT4LMIX_INPUT_2_SOURCE 0x6B2
+#define WM5100_OUT4LMIX_INPUT_2_VOLUME 0x6B3
+#define WM5100_OUT4LMIX_INPUT_3_SOURCE 0x6B4
+#define WM5100_OUT4LMIX_INPUT_3_VOLUME 0x6B5
+#define WM5100_OUT4LMIX_INPUT_4_SOURCE 0x6B6
+#define WM5100_OUT4LMIX_INPUT_4_VOLUME 0x6B7
+#define WM5100_OUT4RMIX_INPUT_1_SOURCE 0x6B8
+#define WM5100_OUT4RMIX_INPUT_1_VOLUME 0x6B9
+#define WM5100_OUT4RMIX_INPUT_2_SOURCE 0x6BA
+#define WM5100_OUT4RMIX_INPUT_2_VOLUME 0x6BB
+#define WM5100_OUT4RMIX_INPUT_3_SOURCE 0x6BC
+#define WM5100_OUT4RMIX_INPUT_3_VOLUME 0x6BD
+#define WM5100_OUT4RMIX_INPUT_4_SOURCE 0x6BE
+#define WM5100_OUT4RMIX_INPUT_4_VOLUME 0x6BF
+#define WM5100_OUT5LMIX_INPUT_1_SOURCE 0x6C0
+#define WM5100_OUT5LMIX_INPUT_1_VOLUME 0x6C1
+#define WM5100_OUT5LMIX_INPUT_2_SOURCE 0x6C2
+#define WM5100_OUT5LMIX_INPUT_2_VOLUME 0x6C3
+#define WM5100_OUT5LMIX_INPUT_3_SOURCE 0x6C4
+#define WM5100_OUT5LMIX_INPUT_3_VOLUME 0x6C5
+#define WM5100_OUT5LMIX_INPUT_4_SOURCE 0x6C6
+#define WM5100_OUT5LMIX_INPUT_4_VOLUME 0x6C7
+#define WM5100_OUT5RMIX_INPUT_1_SOURCE 0x6C8
+#define WM5100_OUT5RMIX_INPUT_1_VOLUME 0x6C9
+#define WM5100_OUT5RMIX_INPUT_2_SOURCE 0x6CA
+#define WM5100_OUT5RMIX_INPUT_2_VOLUME 0x6CB
+#define WM5100_OUT5RMIX_INPUT_3_SOURCE 0x6CC
+#define WM5100_OUT5RMIX_INPUT_3_VOLUME 0x6CD
+#define WM5100_OUT5RMIX_INPUT_4_SOURCE 0x6CE
+#define WM5100_OUT5RMIX_INPUT_4_VOLUME 0x6CF
+#define WM5100_OUT6LMIX_INPUT_1_SOURCE 0x6D0
+#define WM5100_OUT6LMIX_INPUT_1_VOLUME 0x6D1
+#define WM5100_OUT6LMIX_INPUT_2_SOURCE 0x6D2
+#define WM5100_OUT6LMIX_INPUT_2_VOLUME 0x6D3
+#define WM5100_OUT6LMIX_INPUT_3_SOURCE 0x6D4
+#define WM5100_OUT6LMIX_INPUT_3_VOLUME 0x6D5
+#define WM5100_OUT6LMIX_INPUT_4_SOURCE 0x6D6
+#define WM5100_OUT6LMIX_INPUT_4_VOLUME 0x6D7
+#define WM5100_OUT6RMIX_INPUT_1_SOURCE 0x6D8
+#define WM5100_OUT6RMIX_INPUT_1_VOLUME 0x6D9
+#define WM5100_OUT6RMIX_INPUT_2_SOURCE 0x6DA
+#define WM5100_OUT6RMIX_INPUT_2_VOLUME 0x6DB
+#define WM5100_OUT6RMIX_INPUT_3_SOURCE 0x6DC
+#define WM5100_OUT6RMIX_INPUT_3_VOLUME 0x6DD
+#define WM5100_OUT6RMIX_INPUT_4_SOURCE 0x6DE
+#define WM5100_OUT6RMIX_INPUT_4_VOLUME 0x6DF
+#define WM5100_AIF1TX1MIX_INPUT_1_SOURCE 0x700
+#define WM5100_AIF1TX1MIX_INPUT_1_VOLUME 0x701
+#define WM5100_AIF1TX1MIX_INPUT_2_SOURCE 0x702
+#define WM5100_AIF1TX1MIX_INPUT_2_VOLUME 0x703
+#define WM5100_AIF1TX1MIX_INPUT_3_SOURCE 0x704
+#define WM5100_AIF1TX1MIX_INPUT_3_VOLUME 0x705
+#define WM5100_AIF1TX1MIX_INPUT_4_SOURCE 0x706
+#define WM5100_AIF1TX1MIX_INPUT_4_VOLUME 0x707
+#define WM5100_AIF1TX2MIX_INPUT_1_SOURCE 0x708
+#define WM5100_AIF1TX2MIX_INPUT_1_VOLUME 0x709
+#define WM5100_AIF1TX2MIX_INPUT_2_SOURCE 0x70A
+#define WM5100_AIF1TX2MIX_INPUT_2_VOLUME 0x70B
+#define WM5100_AIF1TX2MIX_INPUT_3_SOURCE 0x70C
+#define WM5100_AIF1TX2MIX_INPUT_3_VOLUME 0x70D
+#define WM5100_AIF1TX2MIX_INPUT_4_SOURCE 0x70E
+#define WM5100_AIF1TX2MIX_INPUT_4_VOLUME 0x70F
+#define WM5100_AIF1TX3MIX_INPUT_1_SOURCE 0x710
+#define WM5100_AIF1TX3MIX_INPUT_1_VOLUME 0x711
+#define WM5100_AIF1TX3MIX_INPUT_2_SOURCE 0x712
+#define WM5100_AIF1TX3MIX_INPUT_2_VOLUME 0x713
+#define WM5100_AIF1TX3MIX_INPUT_3_SOURCE 0x714
+#define WM5100_AIF1TX3MIX_INPUT_3_VOLUME 0x715
+#define WM5100_AIF1TX3MIX_INPUT_4_SOURCE 0x716
+#define WM5100_AIF1TX3MIX_INPUT_4_VOLUME 0x717
+#define WM5100_AIF1TX4MIX_INPUT_1_SOURCE 0x718
+#define WM5100_AIF1TX4MIX_INPUT_1_VOLUME 0x719
+#define WM5100_AIF1TX4MIX_INPUT_2_SOURCE 0x71A
+#define WM5100_AIF1TX4MIX_INPUT_2_VOLUME 0x71B
+#define WM5100_AIF1TX4MIX_INPUT_3_SOURCE 0x71C
+#define WM5100_AIF1TX4MIX_INPUT_3_VOLUME 0x71D
+#define WM5100_AIF1TX4MIX_INPUT_4_SOURCE 0x71E
+#define WM5100_AIF1TX4MIX_INPUT_4_VOLUME 0x71F
+#define WM5100_AIF1TX5MIX_INPUT_1_SOURCE 0x720
+#define WM5100_AIF1TX5MIX_INPUT_1_VOLUME 0x721
+#define WM5100_AIF1TX5MIX_INPUT_2_SOURCE 0x722
+#define WM5100_AIF1TX5MIX_INPUT_2_VOLUME 0x723
+#define WM5100_AIF1TX5MIX_INPUT_3_SOURCE 0x724
+#define WM5100_AIF1TX5MIX_INPUT_3_VOLUME 0x725
+#define WM5100_AIF1TX5MIX_INPUT_4_SOURCE 0x726
+#define WM5100_AIF1TX5MIX_INPUT_4_VOLUME 0x727
+#define WM5100_AIF1TX6MIX_INPUT_1_SOURCE 0x728
+#define WM5100_AIF1TX6MIX_INPUT_1_VOLUME 0x729
+#define WM5100_AIF1TX6MIX_INPUT_2_SOURCE 0x72A
+#define WM5100_AIF1TX6MIX_INPUT_2_VOLUME 0x72B
+#define WM5100_AIF1TX6MIX_INPUT_3_SOURCE 0x72C
+#define WM5100_AIF1TX6MIX_INPUT_3_VOLUME 0x72D
+#define WM5100_AIF1TX6MIX_INPUT_4_SOURCE 0x72E
+#define WM5100_AIF1TX6MIX_INPUT_4_VOLUME 0x72F
+#define WM5100_AIF1TX7MIX_INPUT_1_SOURCE 0x730
+#define WM5100_AIF1TX7MIX_INPUT_1_VOLUME 0x731
+#define WM5100_AIF1TX7MIX_INPUT_2_SOURCE 0x732
+#define WM5100_AIF1TX7MIX_INPUT_2_VOLUME 0x733
+#define WM5100_AIF1TX7MIX_INPUT_3_SOURCE 0x734
+#define WM5100_AIF1TX7MIX_INPUT_3_VOLUME 0x735
+#define WM5100_AIF1TX7MIX_INPUT_4_SOURCE 0x736
+#define WM5100_AIF1TX7MIX_INPUT_4_VOLUME 0x737
+#define WM5100_AIF1TX8MIX_INPUT_1_SOURCE 0x738
+#define WM5100_AIF1TX8MIX_INPUT_1_VOLUME 0x739
+#define WM5100_AIF1TX8MIX_INPUT_2_SOURCE 0x73A
+#define WM5100_AIF1TX8MIX_INPUT_2_VOLUME 0x73B
+#define WM5100_AIF1TX8MIX_INPUT_3_SOURCE 0x73C
+#define WM5100_AIF1TX8MIX_INPUT_3_VOLUME 0x73D
+#define WM5100_AIF1TX8MIX_INPUT_4_SOURCE 0x73E
+#define WM5100_AIF1TX8MIX_INPUT_4_VOLUME 0x73F
+#define WM5100_AIF2TX1MIX_INPUT_1_SOURCE 0x740
+#define WM5100_AIF2TX1MIX_INPUT_1_VOLUME 0x741
+#define WM5100_AIF2TX1MIX_INPUT_2_SOURCE 0x742
+#define WM5100_AIF2TX1MIX_INPUT_2_VOLUME 0x743
+#define WM5100_AIF2TX1MIX_INPUT_3_SOURCE 0x744
+#define WM5100_AIF2TX1MIX_INPUT_3_VOLUME 0x745
+#define WM5100_AIF2TX1MIX_INPUT_4_SOURCE 0x746
+#define WM5100_AIF2TX1MIX_INPUT_4_VOLUME 0x747
+#define WM5100_AIF2TX2MIX_INPUT_1_SOURCE 0x748
+#define WM5100_AIF2TX2MIX_INPUT_1_VOLUME 0x749
+#define WM5100_AIF2TX2MIX_INPUT_2_SOURCE 0x74A
+#define WM5100_AIF2TX2MIX_INPUT_2_VOLUME 0x74B
+#define WM5100_AIF2TX2MIX_INPUT_3_SOURCE 0x74C
+#define WM5100_AIF2TX2MIX_INPUT_3_VOLUME 0x74D
+#define WM5100_AIF2TX2MIX_INPUT_4_SOURCE 0x74E
+#define WM5100_AIF2TX2MIX_INPUT_4_VOLUME 0x74F
+#define WM5100_AIF3TX1MIX_INPUT_1_SOURCE 0x780
+#define WM5100_AIF3TX1MIX_INPUT_1_VOLUME 0x781
+#define WM5100_AIF3TX1MIX_INPUT_2_SOURCE 0x782
+#define WM5100_AIF3TX1MIX_INPUT_2_VOLUME 0x783
+#define WM5100_AIF3TX1MIX_INPUT_3_SOURCE 0x784
+#define WM5100_AIF3TX1MIX_INPUT_3_VOLUME 0x785
+#define WM5100_AIF3TX1MIX_INPUT_4_SOURCE 0x786
+#define WM5100_AIF3TX1MIX_INPUT_4_VOLUME 0x787
+#define WM5100_AIF3TX2MIX_INPUT_1_SOURCE 0x788
+#define WM5100_AIF3TX2MIX_INPUT_1_VOLUME 0x789
+#define WM5100_AIF3TX2MIX_INPUT_2_SOURCE 0x78A
+#define WM5100_AIF3TX2MIX_INPUT_2_VOLUME 0x78B
+#define WM5100_AIF3TX2MIX_INPUT_3_SOURCE 0x78C
+#define WM5100_AIF3TX2MIX_INPUT_3_VOLUME 0x78D
+#define WM5100_AIF3TX2MIX_INPUT_4_SOURCE 0x78E
+#define WM5100_AIF3TX2MIX_INPUT_4_VOLUME 0x78F
+#define WM5100_EQ1MIX_INPUT_1_SOURCE 0x880
+#define WM5100_EQ1MIX_INPUT_1_VOLUME 0x881
+#define WM5100_EQ1MIX_INPUT_2_SOURCE 0x882
+#define WM5100_EQ1MIX_INPUT_2_VOLUME 0x883
+#define WM5100_EQ1MIX_INPUT_3_SOURCE 0x884
+#define WM5100_EQ1MIX_INPUT_3_VOLUME 0x885
+#define WM5100_EQ1MIX_INPUT_4_SOURCE 0x886
+#define WM5100_EQ1MIX_INPUT_4_VOLUME 0x887
+#define WM5100_EQ2MIX_INPUT_1_SOURCE 0x888
+#define WM5100_EQ2MIX_INPUT_1_VOLUME 0x889
+#define WM5100_EQ2MIX_INPUT_2_SOURCE 0x88A
+#define WM5100_EQ2MIX_INPUT_2_VOLUME 0x88B
+#define WM5100_EQ2MIX_INPUT_3_SOURCE 0x88C
+#define WM5100_EQ2MIX_INPUT_3_VOLUME 0x88D
+#define WM5100_EQ2MIX_INPUT_4_SOURCE 0x88E
+#define WM5100_EQ2MIX_INPUT_4_VOLUME 0x88F
+#define WM5100_EQ3MIX_INPUT_1_SOURCE 0x890
+#define WM5100_EQ3MIX_INPUT_1_VOLUME 0x891
+#define WM5100_EQ3MIX_INPUT_2_SOURCE 0x892
+#define WM5100_EQ3MIX_INPUT_2_VOLUME 0x893
+#define WM5100_EQ3MIX_INPUT_3_SOURCE 0x894
+#define WM5100_EQ3MIX_INPUT_3_VOLUME 0x895
+#define WM5100_EQ3MIX_INPUT_4_SOURCE 0x896
+#define WM5100_EQ3MIX_INPUT_4_VOLUME 0x897
+#define WM5100_EQ4MIX_INPUT_1_SOURCE 0x898
+#define WM5100_EQ4MIX_INPUT_1_VOLUME 0x899
+#define WM5100_EQ4MIX_INPUT_2_SOURCE 0x89A
+#define WM5100_EQ4MIX_INPUT_2_VOLUME 0x89B
+#define WM5100_EQ4MIX_INPUT_3_SOURCE 0x89C
+#define WM5100_EQ4MIX_INPUT_3_VOLUME 0x89D
+#define WM5100_EQ4MIX_INPUT_4_SOURCE 0x89E
+#define WM5100_EQ4MIX_INPUT_4_VOLUME 0x89F
+#define WM5100_DRC1LMIX_INPUT_1_SOURCE 0x8C0
+#define WM5100_DRC1LMIX_INPUT_1_VOLUME 0x8C1
+#define WM5100_DRC1LMIX_INPUT_2_SOURCE 0x8C2
+#define WM5100_DRC1LMIX_INPUT_2_VOLUME 0x8C3
+#define WM5100_DRC1LMIX_INPUT_3_SOURCE 0x8C4
+#define WM5100_DRC1LMIX_INPUT_3_VOLUME 0x8C5
+#define WM5100_DRC1LMIX_INPUT_4_SOURCE 0x8C6
+#define WM5100_DRC1LMIX_INPUT_4_VOLUME 0x8C7
+#define WM5100_DRC1RMIX_INPUT_1_SOURCE 0x8C8
+#define WM5100_DRC1RMIX_INPUT_1_VOLUME 0x8C9
+#define WM5100_DRC1RMIX_INPUT_2_SOURCE 0x8CA
+#define WM5100_DRC1RMIX_INPUT_2_VOLUME 0x8CB
+#define WM5100_DRC1RMIX_INPUT_3_SOURCE 0x8CC
+#define WM5100_DRC1RMIX_INPUT_3_VOLUME 0x8CD
+#define WM5100_DRC1RMIX_INPUT_4_SOURCE 0x8CE
+#define WM5100_DRC1RMIX_INPUT_4_VOLUME 0x8CF
+#define WM5100_HPLP1MIX_INPUT_1_SOURCE 0x900
+#define WM5100_HPLP1MIX_INPUT_1_VOLUME 0x901
+#define WM5100_HPLP1MIX_INPUT_2_SOURCE 0x902
+#define WM5100_HPLP1MIX_INPUT_2_VOLUME 0x903
+#define WM5100_HPLP1MIX_INPUT_3_SOURCE 0x904
+#define WM5100_HPLP1MIX_INPUT_3_VOLUME 0x905
+#define WM5100_HPLP1MIX_INPUT_4_SOURCE 0x906
+#define WM5100_HPLP1MIX_INPUT_4_VOLUME 0x907
+#define WM5100_HPLP2MIX_INPUT_1_SOURCE 0x908
+#define WM5100_HPLP2MIX_INPUT_1_VOLUME 0x909
+#define WM5100_HPLP2MIX_INPUT_2_SOURCE 0x90A
+#define WM5100_HPLP2MIX_INPUT_2_VOLUME 0x90B
+#define WM5100_HPLP2MIX_INPUT_3_SOURCE 0x90C
+#define WM5100_HPLP2MIX_INPUT_3_VOLUME 0x90D
+#define WM5100_HPLP2MIX_INPUT_4_SOURCE 0x90E
+#define WM5100_HPLP2MIX_INPUT_4_VOLUME 0x90F
+#define WM5100_HPLP3MIX_INPUT_1_SOURCE 0x910
+#define WM5100_HPLP3MIX_INPUT_1_VOLUME 0x911
+#define WM5100_HPLP3MIX_INPUT_2_SOURCE 0x912
+#define WM5100_HPLP3MIX_INPUT_2_VOLUME 0x913
+#define WM5100_HPLP3MIX_INPUT_3_SOURCE 0x914
+#define WM5100_HPLP3MIX_INPUT_3_VOLUME 0x915
+#define WM5100_HPLP3MIX_INPUT_4_SOURCE 0x916
+#define WM5100_HPLP3MIX_INPUT_4_VOLUME 0x917
+#define WM5100_HPLP4MIX_INPUT_1_SOURCE 0x918
+#define WM5100_HPLP4MIX_INPUT_1_VOLUME 0x919
+#define WM5100_HPLP4MIX_INPUT_2_SOURCE 0x91A
+#define WM5100_HPLP4MIX_INPUT_2_VOLUME 0x91B
+#define WM5100_HPLP4MIX_INPUT_3_SOURCE 0x91C
+#define WM5100_HPLP4MIX_INPUT_3_VOLUME 0x91D
+#define WM5100_HPLP4MIX_INPUT_4_SOURCE 0x91E
+#define WM5100_HPLP4MIX_INPUT_4_VOLUME 0x91F
+#define WM5100_DSP1LMIX_INPUT_1_SOURCE 0x940
+#define WM5100_DSP1LMIX_INPUT_1_VOLUME 0x941
+#define WM5100_DSP1LMIX_INPUT_2_SOURCE 0x942
+#define WM5100_DSP1LMIX_INPUT_2_VOLUME 0x943
+#define WM5100_DSP1LMIX_INPUT_3_SOURCE 0x944
+#define WM5100_DSP1LMIX_INPUT_3_VOLUME 0x945
+#define WM5100_DSP1LMIX_INPUT_4_SOURCE 0x946
+#define WM5100_DSP1LMIX_INPUT_4_VOLUME 0x947
+#define WM5100_DSP1RMIX_INPUT_1_SOURCE 0x948
+#define WM5100_DSP1RMIX_INPUT_1_VOLUME 0x949
+#define WM5100_DSP1RMIX_INPUT_2_SOURCE 0x94A
+#define WM5100_DSP1RMIX_INPUT_2_VOLUME 0x94B
+#define WM5100_DSP1RMIX_INPUT_3_SOURCE 0x94C
+#define WM5100_DSP1RMIX_INPUT_3_VOLUME 0x94D
+#define WM5100_DSP1RMIX_INPUT_4_SOURCE 0x94E
+#define WM5100_DSP1RMIX_INPUT_4_VOLUME 0x94F
+#define WM5100_DSP1AUX1MIX_INPUT_1_SOURCE 0x950
+#define WM5100_DSP1AUX2MIX_INPUT_1_SOURCE 0x958
+#define WM5100_DSP1AUX3MIX_INPUT_1_SOURCE 0x960
+#define WM5100_DSP1AUX4MIX_INPUT_1_SOURCE 0x968
+#define WM5100_DSP1AUX5MIX_INPUT_1_SOURCE 0x970
+#define WM5100_DSP1AUX6MIX_INPUT_1_SOURCE 0x978
+#define WM5100_DSP2LMIX_INPUT_1_SOURCE 0x980
+#define WM5100_DSP2LMIX_INPUT_1_VOLUME 0x981
+#define WM5100_DSP2LMIX_INPUT_2_SOURCE 0x982
+#define WM5100_DSP2LMIX_INPUT_2_VOLUME 0x983
+#define WM5100_DSP2LMIX_INPUT_3_SOURCE 0x984
+#define WM5100_DSP2LMIX_INPUT_3_VOLUME 0x985
+#define WM5100_DSP2LMIX_INPUT_4_SOURCE 0x986
+#define WM5100_DSP2LMIX_INPUT_4_VOLUME 0x987
+#define WM5100_DSP2RMIX_INPUT_1_SOURCE 0x988
+#define WM5100_DSP2RMIX_INPUT_1_VOLUME 0x989
+#define WM5100_DSP2RMIX_INPUT_2_SOURCE 0x98A
+#define WM5100_DSP2RMIX_INPUT_2_VOLUME 0x98B
+#define WM5100_DSP2RMIX_INPUT_3_SOURCE 0x98C
+#define WM5100_DSP2RMIX_INPUT_3_VOLUME 0x98D
+#define WM5100_DSP2RMIX_INPUT_4_SOURCE 0x98E
+#define WM5100_DSP2RMIX_INPUT_4_VOLUME 0x98F
+#define WM5100_DSP2AUX1MIX_INPUT_1_SOURCE 0x990
+#define WM5100_DSP2AUX2MIX_INPUT_1_SOURCE 0x998
+#define WM5100_DSP2AUX3MIX_INPUT_1_SOURCE 0x9A0
+#define WM5100_DSP2AUX4MIX_INPUT_1_SOURCE 0x9A8
+#define WM5100_DSP2AUX5MIX_INPUT_1_SOURCE 0x9B0
+#define WM5100_DSP2AUX6MIX_INPUT_1_SOURCE 0x9B8
+#define WM5100_DSP3LMIX_INPUT_1_SOURCE 0x9C0
+#define WM5100_DSP3LMIX_INPUT_1_VOLUME 0x9C1
+#define WM5100_DSP3LMIX_INPUT_2_SOURCE 0x9C2
+#define WM5100_DSP3LMIX_INPUT_2_VOLUME 0x9C3
+#define WM5100_DSP3LMIX_INPUT_3_SOURCE 0x9C4
+#define WM5100_DSP3LMIX_INPUT_3_VOLUME 0x9C5
+#define WM5100_DSP3LMIX_INPUT_4_SOURCE 0x9C6
+#define WM5100_DSP3LMIX_INPUT_4_VOLUME 0x9C7
+#define WM5100_DSP3RMIX_INPUT_1_SOURCE 0x9C8
+#define WM5100_DSP3RMIX_INPUT_1_VOLUME 0x9C9
+#define WM5100_DSP3RMIX_INPUT_2_SOURCE 0x9CA
+#define WM5100_DSP3RMIX_INPUT_2_VOLUME 0x9CB
+#define WM5100_DSP3RMIX_INPUT_3_SOURCE 0x9CC
+#define WM5100_DSP3RMIX_INPUT_3_VOLUME 0x9CD
+#define WM5100_DSP3RMIX_INPUT_4_SOURCE 0x9CE
+#define WM5100_DSP3RMIX_INPUT_4_VOLUME 0x9CF
+#define WM5100_DSP3AUX1MIX_INPUT_1_SOURCE 0x9D0
+#define WM5100_DSP3AUX2MIX_INPUT_1_SOURCE 0x9D8
+#define WM5100_DSP3AUX3MIX_INPUT_1_SOURCE 0x9E0
+#define WM5100_DSP3AUX4MIX_INPUT_1_SOURCE 0x9E8
+#define WM5100_DSP3AUX5MIX_INPUT_1_SOURCE 0x9F0
+#define WM5100_DSP3AUX6MIX_INPUT_1_SOURCE 0x9F8
+#define WM5100_ASRC1LMIX_INPUT_1_SOURCE 0xA80
+#define WM5100_ASRC1RMIX_INPUT_1_SOURCE 0xA88
+#define WM5100_ASRC2LMIX_INPUT_1_SOURCE 0xA90
+#define WM5100_ASRC2RMIX_INPUT_1_SOURCE 0xA98
+#define WM5100_ISRC1DEC1MIX_INPUT_1_SOURCE 0xB00
+#define WM5100_ISRC1DEC2MIX_INPUT_1_SOURCE 0xB08
+#define WM5100_ISRC1DEC3MIX_INPUT_1_SOURCE 0xB10
+#define WM5100_ISRC1DEC4MIX_INPUT_1_SOURCE 0xB18
+#define WM5100_ISRC1INT1MIX_INPUT_1_SOURCE 0xB20
+#define WM5100_ISRC1INT2MIX_INPUT_1_SOURCE 0xB28
+#define WM5100_ISRC1INT3MIX_INPUT_1_SOURCE 0xB30
+#define WM5100_ISRC1INT4MIX_INPUT_1_SOURCE 0xB38
+#define WM5100_ISRC2DEC1MIX_INPUT_1_SOURCE 0xB40
+#define WM5100_ISRC2DEC2MIX_INPUT_1_SOURCE 0xB48
+#define WM5100_ISRC2DEC3MIX_INPUT_1_SOURCE 0xB50
+#define WM5100_ISRC2DEC4MIX_INPUT_1_SOURCE 0xB58
+#define WM5100_ISRC2INT1MIX_INPUT_1_SOURCE 0xB60
+#define WM5100_ISRC2INT2MIX_INPUT_1_SOURCE 0xB68
+#define WM5100_ISRC2INT3MIX_INPUT_1_SOURCE 0xB70
+#define WM5100_ISRC2INT4MIX_INPUT_1_SOURCE 0xB78
+#define WM5100_GPIO_CTRL_1 0xC00
+#define WM5100_GPIO_CTRL_2 0xC01
+#define WM5100_GPIO_CTRL_3 0xC02
+#define WM5100_GPIO_CTRL_4 0xC03
+#define WM5100_GPIO_CTRL_5 0xC04
+#define WM5100_GPIO_CTRL_6 0xC05
+#define WM5100_MISC_PAD_CTRL_1 0xC23
+#define WM5100_MISC_PAD_CTRL_2 0xC24
+#define WM5100_MISC_PAD_CTRL_3 0xC25
+#define WM5100_MISC_PAD_CTRL_4 0xC26
+#define WM5100_MISC_PAD_CTRL_5 0xC27
+#define WM5100_MISC_GPIO_1 0xC28
+#define WM5100_INTERRUPT_STATUS_1 0xD00
+#define WM5100_INTERRUPT_STATUS_2 0xD01
+#define WM5100_INTERRUPT_STATUS_3 0xD02
+#define WM5100_INTERRUPT_STATUS_4 0xD03
+#define WM5100_INTERRUPT_RAW_STATUS_2 0xD04
+#define WM5100_INTERRUPT_RAW_STATUS_3 0xD05
+#define WM5100_INTERRUPT_RAW_STATUS_4 0xD06
+#define WM5100_INTERRUPT_STATUS_1_MASK 0xD07
+#define WM5100_INTERRUPT_STATUS_2_MASK 0xD08
+#define WM5100_INTERRUPT_STATUS_3_MASK 0xD09
+#define WM5100_INTERRUPT_STATUS_4_MASK 0xD0A
+#define WM5100_INTERRUPT_CONTROL 0xD1F
+#define WM5100_IRQ_DEBOUNCE_1 0xD20
+#define WM5100_IRQ_DEBOUNCE_2 0xD21
+#define WM5100_FX_CTRL 0xE00
+#define WM5100_EQ1_1 0xE10
+#define WM5100_EQ1_2 0xE11
+#define WM5100_EQ1_3 0xE12
+#define WM5100_EQ1_4 0xE13
+#define WM5100_EQ1_5 0xE14
+#define WM5100_EQ1_6 0xE15
+#define WM5100_EQ1_7 0xE16
+#define WM5100_EQ1_8 0xE17
+#define WM5100_EQ1_9 0xE18
+#define WM5100_EQ1_10 0xE19
+#define WM5100_EQ1_11 0xE1A
+#define WM5100_EQ1_12 0xE1B
+#define WM5100_EQ1_13 0xE1C
+#define WM5100_EQ1_14 0xE1D
+#define WM5100_EQ1_15 0xE1E
+#define WM5100_EQ1_16 0xE1F
+#define WM5100_EQ1_17 0xE20
+#define WM5100_EQ1_18 0xE21
+#define WM5100_EQ1_19 0xE22
+#define WM5100_EQ1_20 0xE23
+#define WM5100_EQ2_1 0xE26
+#define WM5100_EQ2_2 0xE27
+#define WM5100_EQ2_3 0xE28
+#define WM5100_EQ2_4 0xE29
+#define WM5100_EQ2_5 0xE2A
+#define WM5100_EQ2_6 0xE2B
+#define WM5100_EQ2_7 0xE2C
+#define WM5100_EQ2_8 0xE2D
+#define WM5100_EQ2_9 0xE2E
+#define WM5100_EQ2_10 0xE2F
+#define WM5100_EQ2_11 0xE30
+#define WM5100_EQ2_12 0xE31
+#define WM5100_EQ2_13 0xE32
+#define WM5100_EQ2_14 0xE33
+#define WM5100_EQ2_15 0xE34
+#define WM5100_EQ2_16 0xE35
+#define WM5100_EQ2_17 0xE36
+#define WM5100_EQ2_18 0xE37
+#define WM5100_EQ2_19 0xE38
+#define WM5100_EQ2_20 0xE39
+#define WM5100_EQ3_1 0xE3C
+#define WM5100_EQ3_2 0xE3D
+#define WM5100_EQ3_3 0xE3E
+#define WM5100_EQ3_4 0xE3F
+#define WM5100_EQ3_5 0xE40
+#define WM5100_EQ3_6 0xE41
+#define WM5100_EQ3_7 0xE42
+#define WM5100_EQ3_8 0xE43
+#define WM5100_EQ3_9 0xE44
+#define WM5100_EQ3_10 0xE45
+#define WM5100_EQ3_11 0xE46
+#define WM5100_EQ3_12 0xE47
+#define WM5100_EQ3_13 0xE48
+#define WM5100_EQ3_14 0xE49
+#define WM5100_EQ3_15 0xE4A
+#define WM5100_EQ3_16 0xE4B
+#define WM5100_EQ3_17 0xE4C
+#define WM5100_EQ3_18 0xE4D
+#define WM5100_EQ3_19 0xE4E
+#define WM5100_EQ3_20 0xE4F
+#define WM5100_EQ4_1 0xE52
+#define WM5100_EQ4_2 0xE53
+#define WM5100_EQ4_3 0xE54
+#define WM5100_EQ4_4 0xE55
+#define WM5100_EQ4_5 0xE56
+#define WM5100_EQ4_6 0xE57
+#define WM5100_EQ4_7 0xE58
+#define WM5100_EQ4_8 0xE59
+#define WM5100_EQ4_9 0xE5A
+#define WM5100_EQ4_10 0xE5B
+#define WM5100_EQ4_11 0xE5C
+#define WM5100_EQ4_12 0xE5D
+#define WM5100_EQ4_13 0xE5E
+#define WM5100_EQ4_14 0xE5F
+#define WM5100_EQ4_15 0xE60
+#define WM5100_EQ4_16 0xE61
+#define WM5100_EQ4_17 0xE62
+#define WM5100_EQ4_18 0xE63
+#define WM5100_EQ4_19 0xE64
+#define WM5100_EQ4_20 0xE65
+#define WM5100_DRC1_CTRL1 0xE80
+#define WM5100_DRC1_CTRL2 0xE81
+#define WM5100_DRC1_CTRL3 0xE82
+#define WM5100_DRC1_CTRL4 0xE83
+#define WM5100_DRC1_CTRL5 0xE84
+#define WM5100_HPLPF1_1 0xEC0
+#define WM5100_HPLPF1_2 0xEC1
+#define WM5100_HPLPF2_1 0xEC4
+#define WM5100_HPLPF2_2 0xEC5
+#define WM5100_HPLPF3_1 0xEC8
+#define WM5100_HPLPF3_2 0xEC9
+#define WM5100_HPLPF4_1 0xECC
+#define WM5100_HPLPF4_2 0xECD
+#define WM5100_DSP1_DM_0 0x4000
+#define WM5100_DSP1_DM_1 0x4001
+#define WM5100_DSP1_DM_2 0x4002
+#define WM5100_DSP1_DM_3 0x4003
+#define WM5100_DSP1_DM_508 0x41FC
+#define WM5100_DSP1_DM_509 0x41FD
+#define WM5100_DSP1_DM_510 0x41FE
+#define WM5100_DSP1_DM_511 0x41FF
+#define WM5100_DSP1_PM_0 0x4800
+#define WM5100_DSP1_PM_1 0x4801
+#define WM5100_DSP1_PM_2 0x4802
+#define WM5100_DSP1_PM_3 0x4803
+#define WM5100_DSP1_PM_4 0x4804
+#define WM5100_DSP1_PM_5 0x4805
+#define WM5100_DSP1_PM_1530 0x4DFA
+#define WM5100_DSP1_PM_1531 0x4DFB
+#define WM5100_DSP1_PM_1532 0x4DFC
+#define WM5100_DSP1_PM_1533 0x4DFD
+#define WM5100_DSP1_PM_1534 0x4DFE
+#define WM5100_DSP1_PM_1535 0x4DFF
+#define WM5100_DSP1_ZM_0 0x5000
+#define WM5100_DSP1_ZM_1 0x5001
+#define WM5100_DSP1_ZM_2 0x5002
+#define WM5100_DSP1_ZM_3 0x5003
+#define WM5100_DSP1_ZM_2044 0x57FC
+#define WM5100_DSP1_ZM_2045 0x57FD
+#define WM5100_DSP1_ZM_2046 0x57FE
+#define WM5100_DSP1_ZM_2047 0x57FF
+#define WM5100_DSP2_DM_0 0x6000
+#define WM5100_DSP2_DM_1 0x6001
+#define WM5100_DSP2_DM_2 0x6002
+#define WM5100_DSP2_DM_3 0x6003
+#define WM5100_DSP2_DM_508 0x61FC
+#define WM5100_DSP2_DM_509 0x61FD
+#define WM5100_DSP2_DM_510 0x61FE
+#define WM5100_DSP2_DM_511 0x61FF
+#define WM5100_DSP2_PM_0 0x6800
+#define WM5100_DSP2_PM_1 0x6801
+#define WM5100_DSP2_PM_2 0x6802
+#define WM5100_DSP2_PM_3 0x6803
+#define WM5100_DSP2_PM_4 0x6804
+#define WM5100_DSP2_PM_5 0x6805
+#define WM5100_DSP2_PM_1530 0x6DFA
+#define WM5100_DSP2_PM_1531 0x6DFB
+#define WM5100_DSP2_PM_1532 0x6DFC
+#define WM5100_DSP2_PM_1533 0x6DFD
+#define WM5100_DSP2_PM_1534 0x6DFE
+#define WM5100_DSP2_PM_1535 0x6DFF
+#define WM5100_DSP2_ZM_0 0x7000
+#define WM5100_DSP2_ZM_1 0x7001
+#define WM5100_DSP2_ZM_2 0x7002
+#define WM5100_DSP2_ZM_3 0x7003
+#define WM5100_DSP2_ZM_2044 0x77FC
+#define WM5100_DSP2_ZM_2045 0x77FD
+#define WM5100_DSP2_ZM_2046 0x77FE
+#define WM5100_DSP2_ZM_2047 0x77FF
+#define WM5100_DSP3_DM_0 0x8000
+#define WM5100_DSP3_DM_1 0x8001
+#define WM5100_DSP3_DM_2 0x8002
+#define WM5100_DSP3_DM_3 0x8003
+#define WM5100_DSP3_DM_508 0x81FC
+#define WM5100_DSP3_DM_509 0x81FD
+#define WM5100_DSP3_DM_510 0x81FE
+#define WM5100_DSP3_DM_511 0x81FF
+#define WM5100_DSP3_PM_0 0x8800
+#define WM5100_DSP3_PM_1 0x8801
+#define WM5100_DSP3_PM_2 0x8802
+#define WM5100_DSP3_PM_3 0x8803
+#define WM5100_DSP3_PM_4 0x8804
+#define WM5100_DSP3_PM_5 0x8805
+#define WM5100_DSP3_PM_1530 0x8DFA
+#define WM5100_DSP3_PM_1531 0x8DFB
+#define WM5100_DSP3_PM_1532 0x8DFC
+#define WM5100_DSP3_PM_1533 0x8DFD
+#define WM5100_DSP3_PM_1534 0x8DFE
+#define WM5100_DSP3_PM_1535 0x8DFF
+#define WM5100_DSP3_ZM_0 0x9000
+#define WM5100_DSP3_ZM_1 0x9001
+#define WM5100_DSP3_ZM_2 0x9002
+#define WM5100_DSP3_ZM_3 0x9003
+#define WM5100_DSP3_ZM_2044 0x97FC
+#define WM5100_DSP3_ZM_2045 0x97FD
+#define WM5100_DSP3_ZM_2046 0x97FE
+#define WM5100_DSP3_ZM_2047 0x97FF
+
+#define WM5100_REGISTER_COUNT 1435
+#define WM5100_MAX_REGISTER 0x97FF
+
+/*
+ * Field Definitions.
+ */
+
+/*
+ * R0 (0x00) - software reset
+ */
+#define WM5100_SW_RST_DEV_ID1_MASK 0xFFFF /* SW_RST_DEV_ID1 - [15:0] */
+#define WM5100_SW_RST_DEV_ID1_SHIFT 0 /* SW_RST_DEV_ID1 - [15:0] */
+#define WM5100_SW_RST_DEV_ID1_WIDTH 16 /* SW_RST_DEV_ID1 - [15:0] */
+
+/*
+ * R1 (0x01) - Device Revision
+ */
+#define WM5100_DEVICE_REVISION_MASK 0x000F /* DEVICE_REVISION - [3:0] */
+#define WM5100_DEVICE_REVISION_SHIFT 0 /* DEVICE_REVISION - [3:0] */
+#define WM5100_DEVICE_REVISION_WIDTH 4 /* DEVICE_REVISION - [3:0] */
+
+/*
+ * R16 (0x10) - Ctrl IF 1
+ */
+#define WM5100_AUTO_INC 0x0001 /* AUTO_INC */
+#define WM5100_AUTO_INC_MASK 0x0001 /* AUTO_INC */
+#define WM5100_AUTO_INC_SHIFT 0 /* AUTO_INC */
+#define WM5100_AUTO_INC_WIDTH 1 /* AUTO_INC */
+
+/*
+ * R32 (0x20) - Tone Generator 1
+ */
+#define WM5100_TONE_RATE_MASK 0x3000 /* TONE_RATE - [13:12] */
+#define WM5100_TONE_RATE_SHIFT 12 /* TONE_RATE - [13:12] */
+#define WM5100_TONE_RATE_WIDTH 2 /* TONE_RATE - [13:12] */
+#define WM5100_TONE_OFFSET_MASK 0x0300 /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE_OFFSET_SHIFT 8 /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE_OFFSET_WIDTH 2 /* TONE_OFFSET - [9:8] */
+#define WM5100_TONE2_ENA 0x0002 /* TONE2_ENA */
+#define WM5100_TONE2_ENA_MASK 0x0002 /* TONE2_ENA */
+#define WM5100_TONE2_ENA_SHIFT 1 /* TONE2_ENA */
+#define WM5100_TONE2_ENA_WIDTH 1 /* TONE2_ENA */
+#define WM5100_TONE1_ENA 0x0001 /* TONE1_ENA */
+#define WM5100_TONE1_ENA_MASK 0x0001 /* TONE1_ENA */
+#define WM5100_TONE1_ENA_SHIFT 0 /* TONE1_ENA */
+#define WM5100_TONE1_ENA_WIDTH 1 /* TONE1_ENA */
+
+/*
+ * R48 (0x30) - PWM Drive 1
+ */
+#define WM5100_PWM_RATE_MASK 0x3000 /* PWM_RATE - [13:12] */
+#define WM5100_PWM_RATE_SHIFT 12 /* PWM_RATE - [13:12] */
+#define WM5100_PWM_RATE_WIDTH 2 /* PWM_RATE - [13:12] */
+#define WM5100_PWM_CLK_SEL_MASK 0x0300 /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM_CLK_SEL_SHIFT 8 /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM_CLK_SEL_WIDTH 2 /* PWM_CLK_SEL - [9:8] */
+#define WM5100_PWM2_OVD 0x0020 /* PWM2_OVD */
+#define WM5100_PWM2_OVD_MASK 0x0020 /* PWM2_OVD */
+#define WM5100_PWM2_OVD_SHIFT 5 /* PWM2_OVD */
+#define WM5100_PWM2_OVD_WIDTH 1 /* PWM2_OVD */
+#define WM5100_PWM1_OVD 0x0010 /* PWM1_OVD */
+#define WM5100_PWM1_OVD_MASK 0x0010 /* PWM1_OVD */
+#define WM5100_PWM1_OVD_SHIFT 4 /* PWM1_OVD */
+#define WM5100_PWM1_OVD_WIDTH 1 /* PWM1_OVD */
+#define WM5100_PWM2_ENA 0x0002 /* PWM2_ENA */
+#define WM5100_PWM2_ENA_MASK 0x0002 /* PWM2_ENA */
+#define WM5100_PWM2_ENA_SHIFT 1 /* PWM2_ENA */
+#define WM5100_PWM2_ENA_WIDTH 1 /* PWM2_ENA */
+#define WM5100_PWM1_ENA 0x0001 /* PWM1_ENA */
+#define WM5100_PWM1_ENA_MASK 0x0001 /* PWM1_ENA */
+#define WM5100_PWM1_ENA_SHIFT 0 /* PWM1_ENA */
+#define WM5100_PWM1_ENA_WIDTH 1 /* PWM1_ENA */
+
+/*
+ * R49 (0x31) - PWM Drive 2
+ */
+#define WM5100_PWM1_LVL_MASK 0x03FF /* PWM1_LVL - [9:0] */
+#define WM5100_PWM1_LVL_SHIFT 0 /* PWM1_LVL - [9:0] */
+#define WM5100_PWM1_LVL_WIDTH 10 /* PWM1_LVL - [9:0] */
+
+/*
+ * R50 (0x32) - PWM Drive 3
+ */
+#define WM5100_PWM2_LVL_MASK 0x03FF /* PWM2_LVL - [9:0] */
+#define WM5100_PWM2_LVL_SHIFT 0 /* PWM2_LVL - [9:0] */
+#define WM5100_PWM2_LVL_WIDTH 10 /* PWM2_LVL - [9:0] */
+
+/*
+ * R256 (0x100) - Clocking 1
+ */
+#define WM5100_CLK_32K_SRC_MASK 0x000F /* CLK_32K_SRC - [3:0] */
+#define WM5100_CLK_32K_SRC_SHIFT 0 /* CLK_32K_SRC - [3:0] */
+#define WM5100_CLK_32K_SRC_WIDTH 4 /* CLK_32K_SRC - [3:0] */
+
+/*
+ * R257 (0x101) - Clocking 3
+ */
+#define WM5100_SYSCLK_FREQ_MASK 0x0700 /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_FREQ_SHIFT 8 /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_FREQ_WIDTH 3 /* SYSCLK_FREQ - [10:8] */
+#define WM5100_SYSCLK_ENA 0x0040 /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_MASK 0x0040 /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_SHIFT 6 /* SYSCLK_ENA */
+#define WM5100_SYSCLK_ENA_WIDTH 1 /* SYSCLK_ENA */
+#define WM5100_SYSCLK_SRC_MASK 0x000F /* SYSCLK_SRC - [3:0] */
+#define WM5100_SYSCLK_SRC_SHIFT 0 /* SYSCLK_SRC - [3:0] */
+#define WM5100_SYSCLK_SRC_WIDTH 4 /* SYSCLK_SRC - [3:0] */
+
+/*
+ * R258 (0x102) - Clocking 4
+ */
+#define WM5100_SAMPLE_RATE_1_MASK 0x001F /* SAMPLE_RATE_1 - [4:0] */
+#define WM5100_SAMPLE_RATE_1_SHIFT 0 /* SAMPLE_RATE_1 - [4:0] */
+#define WM5100_SAMPLE_RATE_1_WIDTH 5 /* SAMPLE_RATE_1 - [4:0] */
+
+/*
+ * R259 (0x103) - Clocking 5
+ */
+#define WM5100_SAMPLE_RATE_2_MASK 0x001F /* SAMPLE_RATE_2 - [4:0] */
+#define WM5100_SAMPLE_RATE_2_SHIFT 0 /* SAMPLE_RATE_2 - [4:0] */
+#define WM5100_SAMPLE_RATE_2_WIDTH 5 /* SAMPLE_RATE_2 - [4:0] */
+
+/*
+ * R260 (0x104) - Clocking 6
+ */
+#define WM5100_SAMPLE_RATE_3_MASK 0x001F /* SAMPLE_RATE_3 - [4:0] */
+#define WM5100_SAMPLE_RATE_3_SHIFT 0 /* SAMPLE_RATE_3 - [4:0] */
+#define WM5100_SAMPLE_RATE_3_WIDTH 5 /* SAMPLE_RATE_3 - [4:0] */
+
+/*
+ * R263 (0x107) - Clocking 7
+ */
+#define WM5100_ASYNC_CLK_FREQ_MASK 0x0700 /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_FREQ_SHIFT 8 /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_FREQ_WIDTH 3 /* ASYNC_CLK_FREQ - [10:8] */
+#define WM5100_ASYNC_CLK_ENA 0x0040 /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_MASK 0x0040 /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_SHIFT 6 /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_ENA_WIDTH 1 /* ASYNC_CLK_ENA */
+#define WM5100_ASYNC_CLK_SRC_MASK 0x000F /* ASYNC_CLK_SRC - [3:0] */
+#define WM5100_ASYNC_CLK_SRC_SHIFT 0 /* ASYNC_CLK_SRC - [3:0] */
+#define WM5100_ASYNC_CLK_SRC_WIDTH 4 /* ASYNC_CLK_SRC - [3:0] */
+
+/*
+ * R264 (0x108) - Clocking 8
+ */
+#define WM5100_ASYNC_SAMPLE_RATE_MASK 0x001F /* ASYNC_SAMPLE_RATE - [4:0] */
+#define WM5100_ASYNC_SAMPLE_RATE_SHIFT 0 /* ASYNC_SAMPLE_RATE - [4:0] */
+#define WM5100_ASYNC_SAMPLE_RATE_WIDTH 5 /* ASYNC_SAMPLE_RATE - [4:0] */
+
+/*
+ * R288 (0x120) - ASRC_ENABLE
+ */
+#define WM5100_ASRC2L_ENA 0x0008 /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_MASK 0x0008 /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_SHIFT 3 /* ASRC2L_ENA */
+#define WM5100_ASRC2L_ENA_WIDTH 1 /* ASRC2L_ENA */
+#define WM5100_ASRC2R_ENA 0x0004 /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_MASK 0x0004 /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_SHIFT 2 /* ASRC2R_ENA */
+#define WM5100_ASRC2R_ENA_WIDTH 1 /* ASRC2R_ENA */
+#define WM5100_ASRC1L_ENA 0x0002 /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_MASK 0x0002 /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_SHIFT 1 /* ASRC1L_ENA */
+#define WM5100_ASRC1L_ENA_WIDTH 1 /* ASRC1L_ENA */
+#define WM5100_ASRC1R_ENA 0x0001 /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_MASK 0x0001 /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_SHIFT 0 /* ASRC1R_ENA */
+#define WM5100_ASRC1R_ENA_WIDTH 1 /* ASRC1R_ENA */
+
+/*
+ * R289 (0x121) - ASRC_STATUS
+ */
+#define WM5100_ASRC2L_ENA_STS 0x0008 /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_MASK 0x0008 /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_SHIFT 3 /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2L_ENA_STS_WIDTH 1 /* ASRC2L_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS 0x0004 /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_MASK 0x0004 /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_SHIFT 2 /* ASRC2R_ENA_STS */
+#define WM5100_ASRC2R_ENA_STS_WIDTH 1 /* ASRC2R_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS 0x0002 /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_MASK 0x0002 /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_SHIFT 1 /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1L_ENA_STS_WIDTH 1 /* ASRC1L_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS 0x0001 /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_MASK 0x0001 /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_SHIFT 0 /* ASRC1R_ENA_STS */
+#define WM5100_ASRC1R_ENA_STS_WIDTH 1 /* ASRC1R_ENA_STS */
+
+/*
+ * R290 (0x122) - ASRC_RATE1
+ */
+#define WM5100_ASRC_RATE1_MASK 0x0006 /* ASRC_RATE1 - [2:1] */
+#define WM5100_ASRC_RATE1_SHIFT 1 /* ASRC_RATE1 - [2:1] */
+#define WM5100_ASRC_RATE1_WIDTH 2 /* ASRC_RATE1 - [2:1] */
+
+/*
+ * R321 (0x141) - ISRC 1 CTRL 1
+ */
+#define WM5100_ISRC1_DFS_ENA 0x2000 /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_MASK 0x2000 /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_SHIFT 13 /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_DFS_ENA_WIDTH 1 /* ISRC1_DFS_ENA */
+#define WM5100_ISRC1_CLK_SEL_MASK 0x0300 /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_CLK_SEL_SHIFT 8 /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_CLK_SEL_WIDTH 2 /* ISRC1_CLK_SEL - [9:8] */
+#define WM5100_ISRC1_FSH_MASK 0x000C /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSH_SHIFT 2 /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSH_WIDTH 2 /* ISRC1_FSH - [3:2] */
+#define WM5100_ISRC1_FSL_MASK 0x0003 /* ISRC1_FSL - [1:0] */
+#define WM5100_ISRC1_FSL_SHIFT 0 /* ISRC1_FSL - [1:0] */
+#define WM5100_ISRC1_FSL_WIDTH 2 /* ISRC1_FSL - [1:0] */
+
+/*
+ * R322 (0x142) - ISRC 1 CTRL 2
+ */
+#define WM5100_ISRC1_INT1_ENA 0x8000 /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_MASK 0x8000 /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_SHIFT 15 /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT1_ENA_WIDTH 1 /* ISRC1_INT1_ENA */
+#define WM5100_ISRC1_INT2_ENA 0x4000 /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_MASK 0x4000 /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_SHIFT 14 /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT2_ENA_WIDTH 1 /* ISRC1_INT2_ENA */
+#define WM5100_ISRC1_INT3_ENA 0x2000 /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_MASK 0x2000 /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_SHIFT 13 /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT3_ENA_WIDTH 1 /* ISRC1_INT3_ENA */
+#define WM5100_ISRC1_INT4_ENA 0x1000 /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_MASK 0x1000 /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_SHIFT 12 /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_INT4_ENA_WIDTH 1 /* ISRC1_INT4_ENA */
+#define WM5100_ISRC1_DEC1_ENA 0x0200 /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_MASK 0x0200 /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_SHIFT 9 /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC1_ENA_WIDTH 1 /* ISRC1_DEC1_ENA */
+#define WM5100_ISRC1_DEC2_ENA 0x0100 /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_MASK 0x0100 /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_SHIFT 8 /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC2_ENA_WIDTH 1 /* ISRC1_DEC2_ENA */
+#define WM5100_ISRC1_DEC3_ENA 0x0080 /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_MASK 0x0080 /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_SHIFT 7 /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC3_ENA_WIDTH 1 /* ISRC1_DEC3_ENA */
+#define WM5100_ISRC1_DEC4_ENA 0x0040 /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_MASK 0x0040 /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_SHIFT 6 /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_DEC4_ENA_WIDTH 1 /* ISRC1_DEC4_ENA */
+#define WM5100_ISRC1_NOTCH_ENA 0x0001 /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_MASK 0x0001 /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_SHIFT 0 /* ISRC1_NOTCH_ENA */
+#define WM5100_ISRC1_NOTCH_ENA_WIDTH 1 /* ISRC1_NOTCH_ENA */
+
+/*
+ * R323 (0x143) - ISRC 2 CTRL1
+ */
+#define WM5100_ISRC2_DFS_ENA 0x2000 /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_MASK 0x2000 /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_SHIFT 13 /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_DFS_ENA_WIDTH 1 /* ISRC2_DFS_ENA */
+#define WM5100_ISRC2_CLK_SEL_MASK 0x0300 /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_CLK_SEL_SHIFT 8 /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_CLK_SEL_WIDTH 2 /* ISRC2_CLK_SEL - [9:8] */
+#define WM5100_ISRC2_FSH_MASK 0x000C /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSH_SHIFT 2 /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSH_WIDTH 2 /* ISRC2_FSH - [3:2] */
+#define WM5100_ISRC2_FSL_MASK 0x0003 /* ISRC2_FSL - [1:0] */
+#define WM5100_ISRC2_FSL_SHIFT 0 /* ISRC2_FSL - [1:0] */
+#define WM5100_ISRC2_FSL_WIDTH 2 /* ISRC2_FSL - [1:0] */
+
+/*
+ * R324 (0x144) - ISRC 2 CTRL 2
+ */
+#define WM5100_ISRC2_INT1_ENA 0x8000 /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_MASK 0x8000 /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_SHIFT 15 /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT1_ENA_WIDTH 1 /* ISRC2_INT1_ENA */
+#define WM5100_ISRC2_INT2_ENA 0x4000 /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_MASK 0x4000 /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_SHIFT 14 /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT2_ENA_WIDTH 1 /* ISRC2_INT2_ENA */
+#define WM5100_ISRC2_INT3_ENA 0x2000 /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_MASK 0x2000 /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_SHIFT 13 /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT3_ENA_WIDTH 1 /* ISRC2_INT3_ENA */
+#define WM5100_ISRC2_INT4_ENA 0x1000 /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_MASK 0x1000 /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_SHIFT 12 /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_INT4_ENA_WIDTH 1 /* ISRC2_INT4_ENA */
+#define WM5100_ISRC2_DEC1_ENA 0x0200 /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_MASK 0x0200 /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_SHIFT 9 /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC1_ENA_WIDTH 1 /* ISRC2_DEC1_ENA */
+#define WM5100_ISRC2_DEC2_ENA 0x0100 /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_MASK 0x0100 /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_SHIFT 8 /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC2_ENA_WIDTH 1 /* ISRC2_DEC2_ENA */
+#define WM5100_ISRC2_DEC3_ENA 0x0080 /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_MASK 0x0080 /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_SHIFT 7 /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC3_ENA_WIDTH 1 /* ISRC2_DEC3_ENA */
+#define WM5100_ISRC2_DEC4_ENA 0x0040 /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_MASK 0x0040 /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_SHIFT 6 /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_DEC4_ENA_WIDTH 1 /* ISRC2_DEC4_ENA */
+#define WM5100_ISRC2_NOTCH_ENA 0x0001 /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_MASK 0x0001 /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_SHIFT 0 /* ISRC2_NOTCH_ENA */
+#define WM5100_ISRC2_NOTCH_ENA_WIDTH 1 /* ISRC2_NOTCH_ENA */
+
+/*
+ * R386 (0x182) - FLL1 Control 1
+ */
+#define WM5100_FLL1_ENA 0x0001 /* FLL1_ENA */
+#define WM5100_FLL1_ENA_MASK 0x0001 /* FLL1_ENA */
+#define WM5100_FLL1_ENA_SHIFT 0 /* FLL1_ENA */
+#define WM5100_FLL1_ENA_WIDTH 1 /* FLL1_ENA */
+
+/*
+ * R387 (0x183) - FLL1 Control 2
+ */
+#define WM5100_FLL1_OUTDIV_MASK 0x3F00 /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_OUTDIV_SHIFT 8 /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_OUTDIV_WIDTH 6 /* FLL1_OUTDIV - [13:8] */
+#define WM5100_FLL1_FRATIO_MASK 0x0007 /* FLL1_FRATIO - [2:0] */
+#define WM5100_FLL1_FRATIO_SHIFT 0 /* FLL1_FRATIO - [2:0] */
+#define WM5100_FLL1_FRATIO_WIDTH 3 /* FLL1_FRATIO - [2:0] */
+
+/*
+ * R388 (0x184) - FLL1 Control 3
+ */
+#define WM5100_FLL1_THETA_MASK 0xFFFF /* FLL1_THETA - [15:0] */
+#define WM5100_FLL1_THETA_SHIFT 0 /* FLL1_THETA - [15:0] */
+#define WM5100_FLL1_THETA_WIDTH 16 /* FLL1_THETA - [15:0] */
+
+/*
+ * R390 (0x186) - FLL1 Control 5
+ */
+#define WM5100_FLL1_N_MASK 0x03FF /* FLL1_N - [9:0] */
+#define WM5100_FLL1_N_SHIFT 0 /* FLL1_N - [9:0] */
+#define WM5100_FLL1_N_WIDTH 10 /* FLL1_N - [9:0] */
+
+/*
+ * R391 (0x187) - FLL1 Control 6
+ */
+#define WM5100_FLL1_REFCLK_DIV_MASK 0x00C0 /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_DIV_SHIFT 6 /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_DIV_WIDTH 2 /* FLL1_REFCLK_DIV - [7:6] */
+#define WM5100_FLL1_REFCLK_SRC_MASK 0x000F /* FLL1_REFCLK_SRC - [3:0] */
+#define WM5100_FLL1_REFCLK_SRC_SHIFT 0 /* FLL1_REFCLK_SRC - [3:0] */
+#define WM5100_FLL1_REFCLK_SRC_WIDTH 4 /* FLL1_REFCLK_SRC - [3:0] */
+
+/*
+ * R392 (0x188) - FLL1 EFS 1
+ */
+#define WM5100_FLL1_LAMBDA_MASK 0xFFFF /* FLL1_LAMBDA - [15:0] */
+#define WM5100_FLL1_LAMBDA_SHIFT 0 /* FLL1_LAMBDA - [15:0] */
+#define WM5100_FLL1_LAMBDA_WIDTH 16 /* FLL1_LAMBDA - [15:0] */
+
+/*
+ * R418 (0x1A2) - FLL2 Control 1
+ */
+#define WM5100_FLL2_ENA 0x0001 /* FLL2_ENA */
+#define WM5100_FLL2_ENA_MASK 0x0001 /* FLL2_ENA */
+#define WM5100_FLL2_ENA_SHIFT 0 /* FLL2_ENA */
+#define WM5100_FLL2_ENA_WIDTH 1 /* FLL2_ENA */
+
+/*
+ * R419 (0x1A3) - FLL2 Control 2
+ */
+#define WM5100_FLL2_OUTDIV_MASK 0x3F00 /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_OUTDIV_SHIFT 8 /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_OUTDIV_WIDTH 6 /* FLL2_OUTDIV - [13:8] */
+#define WM5100_FLL2_FRATIO_MASK 0x0007 /* FLL2_FRATIO - [2:0] */
+#define WM5100_FLL2_FRATIO_SHIFT 0 /* FLL2_FRATIO - [2:0] */
+#define WM5100_FLL2_FRATIO_WIDTH 3 /* FLL2_FRATIO - [2:0] */
+
+/*
+ * R420 (0x1A4) - FLL2 Control 3
+ */
+#define WM5100_FLL2_THETA_MASK 0xFFFF /* FLL2_THETA - [15:0] */
+#define WM5100_FLL2_THETA_SHIFT 0 /* FLL2_THETA - [15:0] */
+#define WM5100_FLL2_THETA_WIDTH 16 /* FLL2_THETA - [15:0] */
+
+/*
+ * R422 (0x1A6) - FLL2 Control 5
+ */
+#define WM5100_FLL2_N_MASK 0x03FF /* FLL2_N - [9:0] */
+#define WM5100_FLL2_N_SHIFT 0 /* FLL2_N - [9:0] */
+#define WM5100_FLL2_N_WIDTH 10 /* FLL2_N - [9:0] */
+
+/*
+ * R423 (0x1A7) - FLL2 Control 6
+ */
+#define WM5100_FLL2_REFCLK_DIV_MASK 0x00C0 /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_DIV_SHIFT 6 /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_DIV_WIDTH 2 /* FLL2_REFCLK_DIV - [7:6] */
+#define WM5100_FLL2_REFCLK_SRC_MASK 0x000F /* FLL2_REFCLK_SRC - [3:0] */
+#define WM5100_FLL2_REFCLK_SRC_SHIFT 0 /* FLL2_REFCLK_SRC - [3:0] */
+#define WM5100_FLL2_REFCLK_SRC_WIDTH 4 /* FLL2_REFCLK_SRC - [3:0] */
+
+/*
+ * R424 (0x1A8) - FLL2 EFS 1
+ */
+#define WM5100_FLL2_LAMBDA_MASK 0xFFFF /* FLL2_LAMBDA - [15:0] */
+#define WM5100_FLL2_LAMBDA_SHIFT 0 /* FLL2_LAMBDA - [15:0] */
+#define WM5100_FLL2_LAMBDA_WIDTH 16 /* FLL2_LAMBDA - [15:0] */
+
+/*
+ * R512 (0x200) - Mic Charge Pump 1
+ */
+#define WM5100_CP2_BYPASS 0x0020 /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_MASK 0x0020 /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_SHIFT 5 /* CP2_BYPASS */
+#define WM5100_CP2_BYPASS_WIDTH 1 /* CP2_BYPASS */
+#define WM5100_CP2_ENA 0x0001 /* CP2_ENA */
+#define WM5100_CP2_ENA_MASK 0x0001 /* CP2_ENA */
+#define WM5100_CP2_ENA_SHIFT 0 /* CP2_ENA */
+#define WM5100_CP2_ENA_WIDTH 1 /* CP2_ENA */
+
+/*
+ * R513 (0x201) - Mic Charge Pump 2
+ */
+#define WM5100_LDO2_VSEL_MASK 0xF800 /* LDO2_VSEL - [15:11] */
+#define WM5100_LDO2_VSEL_SHIFT 11 /* LDO2_VSEL - [15:11] */
+#define WM5100_LDO2_VSEL_WIDTH 5 /* LDO2_VSEL - [15:11] */
+
+/*
+ * R514 (0x202) - HP Charge Pump 1
+ */
+#define WM5100_CP1_ENA 0x0001 /* CP1_ENA */
+#define WM5100_CP1_ENA_MASK 0x0001 /* CP1_ENA */
+#define WM5100_CP1_ENA_SHIFT 0 /* CP1_ENA */
+#define WM5100_CP1_ENA_WIDTH 1 /* CP1_ENA */
+
+/*
+ * R529 (0x211) - LDO1 Control
+ */
+#define WM5100_LDO1_BYPASS 0x0002 /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_MASK 0x0002 /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_SHIFT 1 /* LDO1_BYPASS */
+#define WM5100_LDO1_BYPASS_WIDTH 1 /* LDO1_BYPASS */
+
+/*
+ * R533 (0x215) - Mic Bias Ctrl 1
+ */
+#define WM5100_MICB1_DISCH 0x0040 /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_MASK 0x0040 /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_SHIFT 6 /* MICB1_DISCH */
+#define WM5100_MICB1_DISCH_WIDTH 1 /* MICB1_DISCH */
+#define WM5100_MICB1_RATE 0x0020 /* MICB1_RATE */
+#define WM5100_MICB1_RATE_MASK 0x0020 /* MICB1_RATE */
+#define WM5100_MICB1_RATE_SHIFT 5 /* MICB1_RATE */
+#define WM5100_MICB1_RATE_WIDTH 1 /* MICB1_RATE */
+#define WM5100_MICB1_LVL_MASK 0x001C /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_LVL_SHIFT 2 /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_LVL_WIDTH 3 /* MICB1_LVL - [4:2] */
+#define WM5100_MICB1_BYPASS 0x0002 /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_MASK 0x0002 /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_SHIFT 1 /* MICB1_BYPASS */
+#define WM5100_MICB1_BYPASS_WIDTH 1 /* MICB1_BYPASS */
+#define WM5100_MICB1_ENA 0x0001 /* MICB1_ENA */
+#define WM5100_MICB1_ENA_MASK 0x0001 /* MICB1_ENA */
+#define WM5100_MICB1_ENA_SHIFT 0 /* MICB1_ENA */
+#define WM5100_MICB1_ENA_WIDTH 1 /* MICB1_ENA */
+
+/*
+ * R534 (0x216) - Mic Bias Ctrl 2
+ */
+#define WM5100_MICB2_DISCH 0x0040 /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_MASK 0x0040 /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_SHIFT 6 /* MICB2_DISCH */
+#define WM5100_MICB2_DISCH_WIDTH 1 /* MICB2_DISCH */
+#define WM5100_MICB2_RATE 0x0020 /* MICB2_RATE */
+#define WM5100_MICB2_RATE_MASK 0x0020 /* MICB2_RATE */
+#define WM5100_MICB2_RATE_SHIFT 5 /* MICB2_RATE */
+#define WM5100_MICB2_RATE_WIDTH 1 /* MICB2_RATE */
+#define WM5100_MICB2_LVL_MASK 0x001C /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_LVL_SHIFT 2 /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_LVL_WIDTH 3 /* MICB2_LVL - [4:2] */
+#define WM5100_MICB2_BYPASS 0x0002 /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_MASK 0x0002 /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_SHIFT 1 /* MICB2_BYPASS */
+#define WM5100_MICB2_BYPASS_WIDTH 1 /* MICB2_BYPASS */
+#define WM5100_MICB2_ENA 0x0001 /* MICB2_ENA */
+#define WM5100_MICB2_ENA_MASK 0x0001 /* MICB2_ENA */
+#define WM5100_MICB2_ENA_SHIFT 0 /* MICB2_ENA */
+#define WM5100_MICB2_ENA_WIDTH 1 /* MICB2_ENA */
+
+/*
+ * R535 (0x217) - Mic Bias Ctrl 3
+ */
+#define WM5100_MICB3_DISCH 0x0040 /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_MASK 0x0040 /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_SHIFT 6 /* MICB3_DISCH */
+#define WM5100_MICB3_DISCH_WIDTH 1 /* MICB3_DISCH */
+#define WM5100_MICB3_RATE 0x0020 /* MICB3_RATE */
+#define WM5100_MICB3_RATE_MASK 0x0020 /* MICB3_RATE */
+#define WM5100_MICB3_RATE_SHIFT 5 /* MICB3_RATE */
+#define WM5100_MICB3_RATE_WIDTH 1 /* MICB3_RATE */
+#define WM5100_MICB3_LVL_MASK 0x001C /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_LVL_SHIFT 2 /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_LVL_WIDTH 3 /* MICB3_LVL - [4:2] */
+#define WM5100_MICB3_BYPASS 0x0002 /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_MASK 0x0002 /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_SHIFT 1 /* MICB3_BYPASS */
+#define WM5100_MICB3_BYPASS_WIDTH 1 /* MICB3_BYPASS */
+#define WM5100_MICB3_ENA 0x0001 /* MICB3_ENA */
+#define WM5100_MICB3_ENA_MASK 0x0001 /* MICB3_ENA */
+#define WM5100_MICB3_ENA_SHIFT 0 /* MICB3_ENA */
+#define WM5100_MICB3_ENA_WIDTH 1 /* MICB3_ENA */
+
+/*
+ * R640 (0x280) - Accessory Detect Mode 1
+ */
+#define WM5100_ACCDET_BIAS_SRC_MASK 0xC000 /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_BIAS_SRC_SHIFT 14 /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_BIAS_SRC_WIDTH 2 /* ACCDET_BIAS_SRC - [15:14] */
+#define WM5100_ACCDET_SRC 0x2000 /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_MASK 0x2000 /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_SHIFT 13 /* ACCDET_SRC */
+#define WM5100_ACCDET_SRC_WIDTH 1 /* ACCDET_SRC */
+#define WM5100_ACCDET_MODE_MASK 0x0003 /* ACCDET_MODE - [1:0] */
+#define WM5100_ACCDET_MODE_SHIFT 0 /* ACCDET_MODE - [1:0] */
+#define WM5100_ACCDET_MODE_WIDTH 2 /* ACCDET_MODE - [1:0] */
+
+/*
+ * R648 (0x288) - Headphone Detect 1
+ */
+#define WM5100_HP_HOLDTIME_MASK 0x00E0 /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_HOLDTIME_SHIFT 5 /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_HOLDTIME_WIDTH 3 /* HP_HOLDTIME - [7:5] */
+#define WM5100_HP_CLK_DIV_MASK 0x0018 /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_CLK_DIV_SHIFT 3 /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_CLK_DIV_WIDTH 2 /* HP_CLK_DIV - [4:3] */
+#define WM5100_HP_STEP_SIZE 0x0002 /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_MASK 0x0002 /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_SHIFT 1 /* HP_STEP_SIZE */
+#define WM5100_HP_STEP_SIZE_WIDTH 1 /* HP_STEP_SIZE */
+#define WM5100_HP_POLL 0x0001 /* HP_POLL */
+#define WM5100_HP_POLL_MASK 0x0001 /* HP_POLL */
+#define WM5100_HP_POLL_SHIFT 0 /* HP_POLL */
+#define WM5100_HP_POLL_WIDTH 1 /* HP_POLL */
+
+/*
+ * R649 (0x289) - Headphone Detect 2
+ */
+#define WM5100_HP_DONE 0x0080 /* HP_DONE */
+#define WM5100_HP_DONE_MASK 0x0080 /* HP_DONE */
+#define WM5100_HP_DONE_SHIFT 7 /* HP_DONE */
+#define WM5100_HP_DONE_WIDTH 1 /* HP_DONE */
+#define WM5100_HP_LVL_MASK 0x007F /* HP_LVL - [6:0] */
+#define WM5100_HP_LVL_SHIFT 0 /* HP_LVL - [6:0] */
+#define WM5100_HP_LVL_WIDTH 7 /* HP_LVL - [6:0] */
+
+/*
+ * R656 (0x290) - Mic Detect 1
+ */
+#define WM5100_ACCDET_BIAS_STARTTIME_MASK 0xF000 /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_BIAS_STARTTIME_SHIFT 12 /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_BIAS_STARTTIME_WIDTH 4 /* ACCDET_BIAS_STARTTIME - [15:12] */
+#define WM5100_ACCDET_RATE_MASK 0x0F00 /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_RATE_SHIFT 8 /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_RATE_WIDTH 4 /* ACCDET_RATE - [11:8] */
+#define WM5100_ACCDET_DBTIME 0x0002 /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_MASK 0x0002 /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_SHIFT 1 /* ACCDET_DBTIME */
+#define WM5100_ACCDET_DBTIME_WIDTH 1 /* ACCDET_DBTIME */
+#define WM5100_ACCDET_ENA 0x0001 /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_MASK 0x0001 /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_SHIFT 0 /* ACCDET_ENA */
+#define WM5100_ACCDET_ENA_WIDTH 1 /* ACCDET_ENA */
+
+/*
+ * R657 (0x291) - Mic Detect 2
+ */
+#define WM5100_ACCDET_LVL_SEL_MASK 0x00FF /* ACCDET_LVL_SEL - [7:0] */
+#define WM5100_ACCDET_LVL_SEL_SHIFT 0 /* ACCDET_LVL_SEL - [7:0] */
+#define WM5100_ACCDET_LVL_SEL_WIDTH 8 /* ACCDET_LVL_SEL - [7:0] */
+
+/*
+ * R658 (0x292) - Mic Detect 3
+ */
+#define WM5100_ACCDET_LVL_MASK 0x07FC /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_LVL_SHIFT 2 /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_LVL_WIDTH 9 /* ACCDET_LVL - [10:2] */
+#define WM5100_ACCDET_VALID 0x0002 /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_MASK 0x0002 /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_SHIFT 1 /* ACCDET_VALID */
+#define WM5100_ACCDET_VALID_WIDTH 1 /* ACCDET_VALID */
+#define WM5100_ACCDET_STS 0x0001 /* ACCDET_STS */
+#define WM5100_ACCDET_STS_MASK 0x0001 /* ACCDET_STS */
+#define WM5100_ACCDET_STS_SHIFT 0 /* ACCDET_STS */
+#define WM5100_ACCDET_STS_WIDTH 1 /* ACCDET_STS */
+
+/*
+ * R699 (0x2BB) - Misc Control
+ */
+#define WM5100_HPCOM_SRC 0x200 /* HPCOM_SRC */
+#define WM5100_HPCOM_SRC_SHIFT 9 /* HPCOM_SRC */
+
+/*
+ * R769 (0x301) - Input Enables
+ */
+#define WM5100_IN4L_ENA 0x0080 /* IN4L_ENA */
+#define WM5100_IN4L_ENA_MASK 0x0080 /* IN4L_ENA */
+#define WM5100_IN4L_ENA_SHIFT 7 /* IN4L_ENA */
+#define WM5100_IN4L_ENA_WIDTH 1 /* IN4L_ENA */
+#define WM5100_IN4R_ENA 0x0040 /* IN4R_ENA */
+#define WM5100_IN4R_ENA_MASK 0x0040 /* IN4R_ENA */
+#define WM5100_IN4R_ENA_SHIFT 6 /* IN4R_ENA */
+#define WM5100_IN4R_ENA_WIDTH 1 /* IN4R_ENA */
+#define WM5100_IN3L_ENA 0x0020 /* IN3L_ENA */
+#define WM5100_IN3L_ENA_MASK 0x0020 /* IN3L_ENA */
+#define WM5100_IN3L_ENA_SHIFT 5 /* IN3L_ENA */
+#define WM5100_IN3L_ENA_WIDTH 1 /* IN3L_ENA */
+#define WM5100_IN3R_ENA 0x0010 /* IN3R_ENA */
+#define WM5100_IN3R_ENA_MASK 0x0010 /* IN3R_ENA */
+#define WM5100_IN3R_ENA_SHIFT 4 /* IN3R_ENA */
+#define WM5100_IN3R_ENA_WIDTH 1 /* IN3R_ENA */
+#define WM5100_IN2L_ENA 0x0008 /* IN2L_ENA */
+#define WM5100_IN2L_ENA_MASK 0x0008 /* IN2L_ENA */
+#define WM5100_IN2L_ENA_SHIFT 3 /* IN2L_ENA */
+#define WM5100_IN2L_ENA_WIDTH 1 /* IN2L_ENA */
+#define WM5100_IN2R_ENA 0x0004 /* IN2R_ENA */
+#define WM5100_IN2R_ENA_MASK 0x0004 /* IN2R_ENA */
+#define WM5100_IN2R_ENA_SHIFT 2 /* IN2R_ENA */
+#define WM5100_IN2R_ENA_WIDTH 1 /* IN2R_ENA */
+#define WM5100_IN1L_ENA 0x0002 /* IN1L_ENA */
+#define WM5100_IN1L_ENA_MASK 0x0002 /* IN1L_ENA */
+#define WM5100_IN1L_ENA_SHIFT 1 /* IN1L_ENA */
+#define WM5100_IN1L_ENA_WIDTH 1 /* IN1L_ENA */
+#define WM5100_IN1R_ENA 0x0001 /* IN1R_ENA */
+#define WM5100_IN1R_ENA_MASK 0x0001 /* IN1R_ENA */
+#define WM5100_IN1R_ENA_SHIFT 0 /* IN1R_ENA */
+#define WM5100_IN1R_ENA_WIDTH 1 /* IN1R_ENA */
+
+/*
+ * R770 (0x302) - Input Enables Status
+ */
+#define WM5100_IN4L_ENA_STS 0x0080 /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_MASK 0x0080 /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_SHIFT 7 /* IN4L_ENA_STS */
+#define WM5100_IN4L_ENA_STS_WIDTH 1 /* IN4L_ENA_STS */
+#define WM5100_IN4R_ENA_STS 0x0040 /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_MASK 0x0040 /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_SHIFT 6 /* IN4R_ENA_STS */
+#define WM5100_IN4R_ENA_STS_WIDTH 1 /* IN4R_ENA_STS */
+#define WM5100_IN3L_ENA_STS 0x0020 /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_MASK 0x0020 /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_SHIFT 5 /* IN3L_ENA_STS */
+#define WM5100_IN3L_ENA_STS_WIDTH 1 /* IN3L_ENA_STS */
+#define WM5100_IN3R_ENA_STS 0x0010 /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_MASK 0x0010 /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_SHIFT 4 /* IN3R_ENA_STS */
+#define WM5100_IN3R_ENA_STS_WIDTH 1 /* IN3R_ENA_STS */
+#define WM5100_IN2L_ENA_STS 0x0008 /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_MASK 0x0008 /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_SHIFT 3 /* IN2L_ENA_STS */
+#define WM5100_IN2L_ENA_STS_WIDTH 1 /* IN2L_ENA_STS */
+#define WM5100_IN2R_ENA_STS 0x0004 /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_MASK 0x0004 /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_SHIFT 2 /* IN2R_ENA_STS */
+#define WM5100_IN2R_ENA_STS_WIDTH 1 /* IN2R_ENA_STS */
+#define WM5100_IN1L_ENA_STS 0x0002 /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_MASK 0x0002 /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_SHIFT 1 /* IN1L_ENA_STS */
+#define WM5100_IN1L_ENA_STS_WIDTH 1 /* IN1L_ENA_STS */
+#define WM5100_IN1R_ENA_STS 0x0001 /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_MASK 0x0001 /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_SHIFT 0 /* IN1R_ENA_STS */
+#define WM5100_IN1R_ENA_STS_WIDTH 1 /* IN1R_ENA_STS */
+
+/*
+ * R784 (0x310) - IN1L Control
+ */
+#define WM5100_IN_RATE_MASK 0xC000 /* IN_RATE - [15:14] */
+#define WM5100_IN_RATE_SHIFT 14 /* IN_RATE - [15:14] */
+#define WM5100_IN_RATE_WIDTH 2 /* IN_RATE - [15:14] */
+#define WM5100_IN1_OSR 0x2000 /* IN1_OSR */
+#define WM5100_IN1_OSR_MASK 0x2000 /* IN1_OSR */
+#define WM5100_IN1_OSR_SHIFT 13 /* IN1_OSR */
+#define WM5100_IN1_OSR_WIDTH 1 /* IN1_OSR */
+#define WM5100_IN1_DMIC_SUP_MASK 0x1800 /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_DMIC_SUP_SHIFT 11 /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_DMIC_SUP_WIDTH 2 /* IN1_DMIC_SUP - [12:11] */
+#define WM5100_IN1_MODE_MASK 0x0600 /* IN1_MODE - [10:9] */
+#define WM5100_IN1_MODE_SHIFT 9 /* IN1_MODE - [10:9] */
+#define WM5100_IN1_MODE_WIDTH 2 /* IN1_MODE - [10:9] */
+#define WM5100_IN1L_PGA_VOL_MASK 0x00FE /* IN1L_PGA_VOL - [7:1] */
+#define WM5100_IN1L_PGA_VOL_SHIFT 1 /* IN1L_PGA_VOL - [7:1] */
+#define WM5100_IN1L_PGA_VOL_WIDTH 7 /* IN1L_PGA_VOL - [7:1] */
+
+/*
+ * R785 (0x311) - IN1R Control
+ */
+#define WM5100_IN1R_PGA_VOL_MASK 0x00FE /* IN1R_PGA_VOL - [7:1] */
+#define WM5100_IN1R_PGA_VOL_SHIFT 1 /* IN1R_PGA_VOL - [7:1] */
+#define WM5100_IN1R_PGA_VOL_WIDTH 7 /* IN1R_PGA_VOL - [7:1] */
+
+/*
+ * R786 (0x312) - IN2L Control
+ */
+#define WM5100_IN2_OSR 0x2000 /* IN2_OSR */
+#define WM5100_IN2_OSR_MASK 0x2000 /* IN2_OSR */
+#define WM5100_IN2_OSR_SHIFT 13 /* IN2_OSR */
+#define WM5100_IN2_OSR_WIDTH 1 /* IN2_OSR */
+#define WM5100_IN2_DMIC_SUP_MASK 0x1800 /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_DMIC_SUP_SHIFT 11 /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_DMIC_SUP_WIDTH 2 /* IN2_DMIC_SUP - [12:11] */
+#define WM5100_IN2_MODE_MASK 0x0600 /* IN2_MODE - [10:9] */
+#define WM5100_IN2_MODE_SHIFT 9 /* IN2_MODE - [10:9] */
+#define WM5100_IN2_MODE_WIDTH 2 /* IN2_MODE - [10:9] */
+#define WM5100_IN2L_PGA_VOL_MASK 0x00FE /* IN2L_PGA_VOL - [7:1] */
+#define WM5100_IN2L_PGA_VOL_SHIFT 1 /* IN2L_PGA_VOL - [7:1] */
+#define WM5100_IN2L_PGA_VOL_WIDTH 7 /* IN2L_PGA_VOL - [7:1] */
+
+/*
+ * R787 (0x313) - IN2R Control
+ */
+#define WM5100_IN2R_PGA_VOL_MASK 0x00FE /* IN2R_PGA_VOL - [7:1] */
+#define WM5100_IN2R_PGA_VOL_SHIFT 1 /* IN2R_PGA_VOL - [7:1] */
+#define WM5100_IN2R_PGA_VOL_WIDTH 7 /* IN2R_PGA_VOL - [7:1] */
+
+/*
+ * R788 (0x314) - IN3L Control
+ */
+#define WM5100_IN3_OSR 0x2000 /* IN3_OSR */
+#define WM5100_IN3_OSR_MASK 0x2000 /* IN3_OSR */
+#define WM5100_IN3_OSR_SHIFT 13 /* IN3_OSR */
+#define WM5100_IN3_OSR_WIDTH 1 /* IN3_OSR */
+#define WM5100_IN3_DMIC_SUP_MASK 0x1800 /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_DMIC_SUP_SHIFT 11 /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_DMIC_SUP_WIDTH 2 /* IN3_DMIC_SUP - [12:11] */
+#define WM5100_IN3_MODE_MASK 0x0600 /* IN3_MODE - [10:9] */
+#define WM5100_IN3_MODE_SHIFT 9 /* IN3_MODE - [10:9] */
+#define WM5100_IN3_MODE_WIDTH 2 /* IN3_MODE - [10:9] */
+#define WM5100_IN3L_PGA_VOL_MASK 0x00FE /* IN3L_PGA_VOL - [7:1] */
+#define WM5100_IN3L_PGA_VOL_SHIFT 1 /* IN3L_PGA_VOL - [7:1] */
+#define WM5100_IN3L_PGA_VOL_WIDTH 7 /* IN3L_PGA_VOL - [7:1] */
+
+/*
+ * R789 (0x315) - IN3R Control
+ */
+#define WM5100_IN3R_PGA_VOL_MASK 0x00FE /* IN3R_PGA_VOL - [7:1] */
+#define WM5100_IN3R_PGA_VOL_SHIFT 1 /* IN3R_PGA_VOL - [7:1] */
+#define WM5100_IN3R_PGA_VOL_WIDTH 7 /* IN3R_PGA_VOL - [7:1] */
+
+/*
+ * R790 (0x316) - IN4L Control
+ */
+#define WM5100_IN4_OSR 0x2000 /* IN4_OSR */
+#define WM5100_IN4_OSR_MASK 0x2000 /* IN4_OSR */
+#define WM5100_IN4_OSR_SHIFT 13 /* IN4_OSR */
+#define WM5100_IN4_OSR_WIDTH 1 /* IN4_OSR */
+#define WM5100_IN4_DMIC_SUP_MASK 0x1800 /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_DMIC_SUP_SHIFT 11 /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_DMIC_SUP_WIDTH 2 /* IN4_DMIC_SUP - [12:11] */
+#define WM5100_IN4_MODE_MASK 0x0600 /* IN4_MODE - [10:9] */
+#define WM5100_IN4_MODE_SHIFT 9 /* IN4_MODE - [10:9] */
+#define WM5100_IN4_MODE_WIDTH 2 /* IN4_MODE - [10:9] */
+#define WM5100_IN4L_PGA_VOL_MASK 0x00FE /* IN4L_PGA_VOL - [7:1] */
+#define WM5100_IN4L_PGA_VOL_SHIFT 1 /* IN4L_PGA_VOL - [7:1] */
+#define WM5100_IN4L_PGA_VOL_WIDTH 7 /* IN4L_PGA_VOL - [7:1] */
+
+/*
+ * R791 (0x317) - IN4R Control
+ */
+#define WM5100_IN4R_PGA_VOL_MASK 0x00FE /* IN4R_PGA_VOL - [7:1] */
+#define WM5100_IN4R_PGA_VOL_SHIFT 1 /* IN4R_PGA_VOL - [7:1] */
+#define WM5100_IN4R_PGA_VOL_WIDTH 7 /* IN4R_PGA_VOL - [7:1] */
+
+/*
+ * R792 (0x318) - RXANC_SRC
+ */
+#define WM5100_IN_RXANC_SEL_MASK 0x0007 /* IN_RXANC_SEL - [2:0] */
+#define WM5100_IN_RXANC_SEL_SHIFT 0 /* IN_RXANC_SEL - [2:0] */
+#define WM5100_IN_RXANC_SEL_WIDTH 3 /* IN_RXANC_SEL - [2:0] */
+
+/*
+ * R793 (0x319) - Input Volume Ramp
+ */
+#define WM5100_IN_VD_RAMP_MASK 0x0070 /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VD_RAMP_SHIFT 4 /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VD_RAMP_WIDTH 3 /* IN_VD_RAMP - [6:4] */
+#define WM5100_IN_VI_RAMP_MASK 0x0007 /* IN_VI_RAMP - [2:0] */
+#define WM5100_IN_VI_RAMP_SHIFT 0 /* IN_VI_RAMP - [2:0] */
+#define WM5100_IN_VI_RAMP_WIDTH 3 /* IN_VI_RAMP - [2:0] */
+
+/*
+ * R800 (0x320) - ADC Digital Volume 1L
+ */
+#define WM5100_IN_VU 0x0200 /* IN_VU */
+#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM5100_IN_VU_SHIFT 9 /* IN_VU */
+#define WM5100_IN_VU_WIDTH 1 /* IN_VU */
+#define WM5100_IN1L_MUTE 0x0100 /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_MASK 0x0100 /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_SHIFT 8 /* IN1L_MUTE */
+#define WM5100_IN1L_MUTE_WIDTH 1 /* IN1L_MUTE */
+#define WM5100_IN1L_VOL_MASK 0x00FF /* IN1L_VOL - [7:0] */
+#define WM5100_IN1L_VOL_SHIFT 0 /* IN1L_VOL - [7:0] */
+#define WM5100_IN1L_VOL_WIDTH 8 /* IN1L_VOL - [7:0] */
+
+/*
+ * R801 (0x321) - ADC Digital Volume 1R
+ */
+#define WM5100_IN_VU 0x0200 /* IN_VU */
+#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM5100_IN_VU_SHIFT 9 /* IN_VU */
+#define WM5100_IN_VU_WIDTH 1 /* IN_VU */
+#define WM5100_IN1R_MUTE 0x0100 /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_MASK 0x0100 /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_SHIFT 8 /* IN1R_MUTE */
+#define WM5100_IN1R_MUTE_WIDTH 1 /* IN1R_MUTE */
+#define WM5100_IN1R_VOL_MASK 0x00FF /* IN1R_VOL - [7:0] */
+#define WM5100_IN1R_VOL_SHIFT 0 /* IN1R_VOL - [7:0] */
+#define WM5100_IN1R_VOL_WIDTH 8 /* IN1R_VOL - [7:0] */
+
+/*
+ * R802 (0x322) - ADC Digital Volume 2L
+ */
+#define WM5100_IN_VU 0x0200 /* IN_VU */
+#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM5100_IN_VU_SHIFT 9 /* IN_VU */
+#define WM5100_IN_VU_WIDTH 1 /* IN_VU */
+#define WM5100_IN2L_MUTE 0x0100 /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_MASK 0x0100 /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_SHIFT 8 /* IN2L_MUTE */
+#define WM5100_IN2L_MUTE_WIDTH 1 /* IN2L_MUTE */
+#define WM5100_IN2L_VOL_MASK 0x00FF /* IN2L_VOL - [7:0] */
+#define WM5100_IN2L_VOL_SHIFT 0 /* IN2L_VOL - [7:0] */
+#define WM5100_IN2L_VOL_WIDTH 8 /* IN2L_VOL - [7:0] */
+
+/*
+ * R803 (0x323) - ADC Digital Volume 2R
+ */
+#define WM5100_IN_VU 0x0200 /* IN_VU */
+#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM5100_IN_VU_SHIFT 9 /* IN_VU */
+#define WM5100_IN_VU_WIDTH 1 /* IN_VU */
+#define WM5100_IN2R_MUTE 0x0100 /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_MASK 0x0100 /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_SHIFT 8 /* IN2R_MUTE */
+#define WM5100_IN2R_MUTE_WIDTH 1 /* IN2R_MUTE */
+#define WM5100_IN2R_VOL_MASK 0x00FF /* IN2R_VOL - [7:0] */
+#define WM5100_IN2R_VOL_SHIFT 0 /* IN2R_VOL - [7:0] */
+#define WM5100_IN2R_VOL_WIDTH 8 /* IN2R_VOL - [7:0] */
+
+/*
+ * R804 (0x324) - ADC Digital Volume 3L
+ */
+#define WM5100_IN_VU 0x0200 /* IN_VU */
+#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM5100_IN_VU_SHIFT 9 /* IN_VU */
+#define WM5100_IN_VU_WIDTH 1 /* IN_VU */
+#define WM5100_IN3L_MUTE 0x0100 /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_MASK 0x0100 /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_SHIFT 8 /* IN3L_MUTE */
+#define WM5100_IN3L_MUTE_WIDTH 1 /* IN3L_MUTE */
+#define WM5100_IN3L_VOL_MASK 0x00FF /* IN3L_VOL - [7:0] */
+#define WM5100_IN3L_VOL_SHIFT 0 /* IN3L_VOL - [7:0] */
+#define WM5100_IN3L_VOL_WIDTH 8 /* IN3L_VOL - [7:0] */
+
+/*
+ * R805 (0x325) - ADC Digital Volume 3R
+ */
+#define WM5100_IN_VU 0x0200 /* IN_VU */
+#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM5100_IN_VU_SHIFT 9 /* IN_VU */
+#define WM5100_IN_VU_WIDTH 1 /* IN_VU */
+#define WM5100_IN3R_MUTE 0x0100 /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_MASK 0x0100 /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_SHIFT 8 /* IN3R_MUTE */
+#define WM5100_IN3R_MUTE_WIDTH 1 /* IN3R_MUTE */
+#define WM5100_IN3R_VOL_MASK 0x00FF /* IN3R_VOL - [7:0] */
+#define WM5100_IN3R_VOL_SHIFT 0 /* IN3R_VOL - [7:0] */
+#define WM5100_IN3R_VOL_WIDTH 8 /* IN3R_VOL - [7:0] */
+
+/*
+ * R806 (0x326) - ADC Digital Volume 4L
+ */
+#define WM5100_IN_VU 0x0200 /* IN_VU */
+#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM5100_IN_VU_SHIFT 9 /* IN_VU */
+#define WM5100_IN_VU_WIDTH 1 /* IN_VU */
+#define WM5100_IN4L_MUTE 0x0100 /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_MASK 0x0100 /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_SHIFT 8 /* IN4L_MUTE */
+#define WM5100_IN4L_MUTE_WIDTH 1 /* IN4L_MUTE */
+#define WM5100_IN4L_VOL_MASK 0x00FF /* IN4L_VOL - [7:0] */
+#define WM5100_IN4L_VOL_SHIFT 0 /* IN4L_VOL - [7:0] */
+#define WM5100_IN4L_VOL_WIDTH 8 /* IN4L_VOL - [7:0] */
+
+/*
+ * R807 (0x327) - ADC Digital Volume 4R
+ */
+#define WM5100_IN_VU 0x0200 /* IN_VU */
+#define WM5100_IN_VU_MASK 0x0200 /* IN_VU */
+#define WM5100_IN_VU_SHIFT 9 /* IN_VU */
+#define WM5100_IN_VU_WIDTH 1 /* IN_VU */
+#define WM5100_IN4R_MUTE 0x0100 /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_MASK 0x0100 /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_SHIFT 8 /* IN4R_MUTE */
+#define WM5100_IN4R_MUTE_WIDTH 1 /* IN4R_MUTE */
+#define WM5100_IN4R_VOL_MASK 0x00FF /* IN4R_VOL - [7:0] */
+#define WM5100_IN4R_VOL_SHIFT 0 /* IN4R_VOL - [7:0] */
+#define WM5100_IN4R_VOL_WIDTH 8 /* IN4R_VOL - [7:0] */
+
+/*
+ * R1025 (0x401) - Output Enables 2
+ */
+#define WM5100_OUT6L_ENA 0x0800 /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_MASK 0x0800 /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_SHIFT 11 /* OUT6L_ENA */
+#define WM5100_OUT6L_ENA_WIDTH 1 /* OUT6L_ENA */
+#define WM5100_OUT6R_ENA 0x0400 /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_MASK 0x0400 /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_SHIFT 10 /* OUT6R_ENA */
+#define WM5100_OUT6R_ENA_WIDTH 1 /* OUT6R_ENA */
+#define WM5100_OUT5L_ENA 0x0200 /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_MASK 0x0200 /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_SHIFT 9 /* OUT5L_ENA */
+#define WM5100_OUT5L_ENA_WIDTH 1 /* OUT5L_ENA */
+#define WM5100_OUT5R_ENA 0x0100 /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_MASK 0x0100 /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_SHIFT 8 /* OUT5R_ENA */
+#define WM5100_OUT5R_ENA_WIDTH 1 /* OUT5R_ENA */
+#define WM5100_OUT4L_ENA 0x0080 /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_MASK 0x0080 /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_SHIFT 7 /* OUT4L_ENA */
+#define WM5100_OUT4L_ENA_WIDTH 1 /* OUT4L_ENA */
+#define WM5100_OUT4R_ENA 0x0040 /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_MASK 0x0040 /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_SHIFT 6 /* OUT4R_ENA */
+#define WM5100_OUT4R_ENA_WIDTH 1 /* OUT4R_ENA */
+
+/*
+ * R1026 (0x402) - Output Status 1
+ */
+#define WM5100_OUT3L_ENA_STS 0x0020 /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_MASK 0x0020 /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_SHIFT 5 /* OUT3L_ENA_STS */
+#define WM5100_OUT3L_ENA_STS_WIDTH 1 /* OUT3L_ENA_STS */
+#define WM5100_OUT3R_ENA_STS 0x0010 /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_MASK 0x0010 /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_SHIFT 4 /* OUT3R_ENA_STS */
+#define WM5100_OUT3R_ENA_STS_WIDTH 1 /* OUT3R_ENA_STS */
+#define WM5100_OUT2L_ENA_STS 0x0008 /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_MASK 0x0008 /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_SHIFT 3 /* OUT2L_ENA_STS */
+#define WM5100_OUT2L_ENA_STS_WIDTH 1 /* OUT2L_ENA_STS */
+#define WM5100_OUT2R_ENA_STS 0x0004 /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_MASK 0x0004 /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_SHIFT 2 /* OUT2R_ENA_STS */
+#define WM5100_OUT2R_ENA_STS_WIDTH 1 /* OUT2R_ENA_STS */
+#define WM5100_OUT1L_ENA_STS 0x0002 /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_MASK 0x0002 /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_SHIFT 1 /* OUT1L_ENA_STS */
+#define WM5100_OUT1L_ENA_STS_WIDTH 1 /* OUT1L_ENA_STS */
+#define WM5100_OUT1R_ENA_STS 0x0001 /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_MASK 0x0001 /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_SHIFT 0 /* OUT1R_ENA_STS */
+#define WM5100_OUT1R_ENA_STS_WIDTH 1 /* OUT1R_ENA_STS */
+
+/*
+ * R1027 (0x403) - Output Status 2
+ */
+#define WM5100_OUT6L_ENA_STS 0x0800 /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_MASK 0x0800 /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_SHIFT 11 /* OUT6L_ENA_STS */
+#define WM5100_OUT6L_ENA_STS_WIDTH 1 /* OUT6L_ENA_STS */
+#define WM5100_OUT6R_ENA_STS 0x0400 /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_MASK 0x0400 /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_SHIFT 10 /* OUT6R_ENA_STS */
+#define WM5100_OUT6R_ENA_STS_WIDTH 1 /* OUT6R_ENA_STS */
+#define WM5100_OUT5L_ENA_STS 0x0200 /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_MASK 0x0200 /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_SHIFT 9 /* OUT5L_ENA_STS */
+#define WM5100_OUT5L_ENA_STS_WIDTH 1 /* OUT5L_ENA_STS */
+#define WM5100_OUT5R_ENA_STS 0x0100 /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_MASK 0x0100 /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_SHIFT 8 /* OUT5R_ENA_STS */
+#define WM5100_OUT5R_ENA_STS_WIDTH 1 /* OUT5R_ENA_STS */
+#define WM5100_OUT4L_ENA_STS 0x0080 /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_MASK 0x0080 /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_SHIFT 7 /* OUT4L_ENA_STS */
+#define WM5100_OUT4L_ENA_STS_WIDTH 1 /* OUT4L_ENA_STS */
+#define WM5100_OUT4R_ENA_STS 0x0040 /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_MASK 0x0040 /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_SHIFT 6 /* OUT4R_ENA_STS */
+#define WM5100_OUT4R_ENA_STS_WIDTH 1 /* OUT4R_ENA_STS */
+
+/*
+ * R1032 (0x408) - Channel Enables 1
+ */
+#define WM5100_HP3L_ENA 0x0020 /* HP3L_ENA */
+#define WM5100_HP3L_ENA_MASK 0x0020 /* HP3L_ENA */
+#define WM5100_HP3L_ENA_SHIFT 5 /* HP3L_ENA */
+#define WM5100_HP3L_ENA_WIDTH 1 /* HP3L_ENA */
+#define WM5100_HP3R_ENA 0x0010 /* HP3R_ENA */
+#define WM5100_HP3R_ENA_MASK 0x0010 /* HP3R_ENA */
+#define WM5100_HP3R_ENA_SHIFT 4 /* HP3R_ENA */
+#define WM5100_HP3R_ENA_WIDTH 1 /* HP3R_ENA */
+#define WM5100_HP2L_ENA 0x0008 /* HP2L_ENA */
+#define WM5100_HP2L_ENA_MASK 0x0008 /* HP2L_ENA */
+#define WM5100_HP2L_ENA_SHIFT 3 /* HP2L_ENA */
+#define WM5100_HP2L_ENA_WIDTH 1 /* HP2L_ENA */
+#define WM5100_HP2R_ENA 0x0004 /* HP2R_ENA */
+#define WM5100_HP2R_ENA_MASK 0x0004 /* HP2R_ENA */
+#define WM5100_HP2R_ENA_SHIFT 2 /* HP2R_ENA */
+#define WM5100_HP2R_ENA_WIDTH 1 /* HP2R_ENA */
+#define WM5100_HP1L_ENA 0x0002 /* HP1L_ENA */
+#define WM5100_HP1L_ENA_MASK 0x0002 /* HP1L_ENA */
+#define WM5100_HP1L_ENA_SHIFT 1 /* HP1L_ENA */
+#define WM5100_HP1L_ENA_WIDTH 1 /* HP1L_ENA */
+#define WM5100_HP1R_ENA 0x0001 /* HP1R_ENA */
+#define WM5100_HP1R_ENA_MASK 0x0001 /* HP1R_ENA */
+#define WM5100_HP1R_ENA_SHIFT 0 /* HP1R_ENA */
+#define WM5100_HP1R_ENA_WIDTH 1 /* HP1R_ENA */
+
+/*
+ * R1040 (0x410) - Out Volume 1L
+ */
+#define WM5100_OUT_RATE_MASK 0xC000 /* OUT_RATE - [15:14] */
+#define WM5100_OUT_RATE_SHIFT 14 /* OUT_RATE - [15:14] */
+#define WM5100_OUT_RATE_WIDTH 2 /* OUT_RATE - [15:14] */
+#define WM5100_OUT1_OSR 0x2000 /* OUT1_OSR */
+#define WM5100_OUT1_OSR_MASK 0x2000 /* OUT1_OSR */
+#define WM5100_OUT1_OSR_SHIFT 13 /* OUT1_OSR */
+#define WM5100_OUT1_OSR_WIDTH 1 /* OUT1_OSR */
+#define WM5100_OUT1_MONO 0x1000 /* OUT1_MONO */
+#define WM5100_OUT1_MONO_MASK 0x1000 /* OUT1_MONO */
+#define WM5100_OUT1_MONO_SHIFT 12 /* OUT1_MONO */
+#define WM5100_OUT1_MONO_WIDTH 1 /* OUT1_MONO */
+#define WM5100_OUT1L_ANC_SRC 0x0800 /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_MASK 0x0800 /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_SHIFT 11 /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_ANC_SRC_WIDTH 1 /* OUT1L_ANC_SRC */
+#define WM5100_OUT1L_PGA_VOL_MASK 0x00FE /* OUT1L_PGA_VOL - [7:1] */
+#define WM5100_OUT1L_PGA_VOL_SHIFT 1 /* OUT1L_PGA_VOL - [7:1] */
+#define WM5100_OUT1L_PGA_VOL_WIDTH 7 /* OUT1L_PGA_VOL - [7:1] */
+
+/*
+ * R1041 (0x411) - Out Volume 1R
+ */
+#define WM5100_OUT1R_ANC_SRC 0x0800 /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_MASK 0x0800 /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_SHIFT 11 /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_ANC_SRC_WIDTH 1 /* OUT1R_ANC_SRC */
+#define WM5100_OUT1R_PGA_VOL_MASK 0x00FE /* OUT1R_PGA_VOL - [7:1] */
+#define WM5100_OUT1R_PGA_VOL_SHIFT 1 /* OUT1R_PGA_VOL - [7:1] */
+#define WM5100_OUT1R_PGA_VOL_WIDTH 7 /* OUT1R_PGA_VOL - [7:1] */
+
+/*
+ * R1042 (0x412) - DAC Volume Limit 1L
+ */
+#define WM5100_OUT1L_VOL_LIM_MASK 0x00FF /* OUT1L_VOL_LIM - [7:0] */
+#define WM5100_OUT1L_VOL_LIM_SHIFT 0 /* OUT1L_VOL_LIM - [7:0] */
+#define WM5100_OUT1L_VOL_LIM_WIDTH 8 /* OUT1L_VOL_LIM - [7:0] */
+
+/*
+ * R1043 (0x413) - DAC Volume Limit 1R
+ */
+#define WM5100_OUT1R_VOL_LIM_MASK 0x00FF /* OUT1R_VOL_LIM - [7:0] */
+#define WM5100_OUT1R_VOL_LIM_SHIFT 0 /* OUT1R_VOL_LIM - [7:0] */
+#define WM5100_OUT1R_VOL_LIM_WIDTH 8 /* OUT1R_VOL_LIM - [7:0] */
+
+/*
+ * R1044 (0x414) - Out Volume 2L
+ */
+#define WM5100_OUT2_OSR 0x2000 /* OUT2_OSR */
+#define WM5100_OUT2_OSR_MASK 0x2000 /* OUT2_OSR */
+#define WM5100_OUT2_OSR_SHIFT 13 /* OUT2_OSR */
+#define WM5100_OUT2_OSR_WIDTH 1 /* OUT2_OSR */
+#define WM5100_OUT2_MONO 0x1000 /* OUT2_MONO */
+#define WM5100_OUT2_MONO_MASK 0x1000 /* OUT2_MONO */
+#define WM5100_OUT2_MONO_SHIFT 12 /* OUT2_MONO */
+#define WM5100_OUT2_MONO_WIDTH 1 /* OUT2_MONO */
+#define WM5100_OUT2L_ANC_SRC 0x0800 /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_MASK 0x0800 /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_SHIFT 11 /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_ANC_SRC_WIDTH 1 /* OUT2L_ANC_SRC */
+#define WM5100_OUT2L_PGA_VOL_MASK 0x00FE /* OUT2L_PGA_VOL - [7:1] */
+#define WM5100_OUT2L_PGA_VOL_SHIFT 1 /* OUT2L_PGA_VOL - [7:1] */
+#define WM5100_OUT2L_PGA_VOL_WIDTH 7 /* OUT2L_PGA_VOL - [7:1] */
+
+/*
+ * R1045 (0x415) - Out Volume 2R
+ */
+#define WM5100_OUT2R_ANC_SRC 0x0800 /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_MASK 0x0800 /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_SHIFT 11 /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_ANC_SRC_WIDTH 1 /* OUT2R_ANC_SRC */
+#define WM5100_OUT2R_PGA_VOL_MASK 0x00FE /* OUT2R_PGA_VOL - [7:1] */
+#define WM5100_OUT2R_PGA_VOL_SHIFT 1 /* OUT2R_PGA_VOL - [7:1] */
+#define WM5100_OUT2R_PGA_VOL_WIDTH 7 /* OUT2R_PGA_VOL - [7:1] */
+
+/*
+ * R1046 (0x416) - DAC Volume Limit 2L
+ */
+#define WM5100_OUT2L_VOL_LIM_MASK 0x00FF /* OUT2L_VOL_LIM - [7:0] */
+#define WM5100_OUT2L_VOL_LIM_SHIFT 0 /* OUT2L_VOL_LIM - [7:0] */
+#define WM5100_OUT2L_VOL_LIM_WIDTH 8 /* OUT2L_VOL_LIM - [7:0] */
+
+/*
+ * R1047 (0x417) - DAC Volume Limit 2R
+ */
+#define WM5100_OUT2R_VOL_LIM_MASK 0x00FF /* OUT2R_VOL_LIM - [7:0] */
+#define WM5100_OUT2R_VOL_LIM_SHIFT 0 /* OUT2R_VOL_LIM - [7:0] */
+#define WM5100_OUT2R_VOL_LIM_WIDTH 8 /* OUT2R_VOL_LIM - [7:0] */
+
+/*
+ * R1048 (0x418) - Out Volume 3L
+ */
+#define WM5100_OUT3_OSR 0x2000 /* OUT3_OSR */
+#define WM5100_OUT3_OSR_MASK 0x2000 /* OUT3_OSR */
+#define WM5100_OUT3_OSR_SHIFT 13 /* OUT3_OSR */
+#define WM5100_OUT3_OSR_WIDTH 1 /* OUT3_OSR */
+#define WM5100_OUT3_MONO 0x1000 /* OUT3_MONO */
+#define WM5100_OUT3_MONO_MASK 0x1000 /* OUT3_MONO */
+#define WM5100_OUT3_MONO_SHIFT 12 /* OUT3_MONO */
+#define WM5100_OUT3_MONO_WIDTH 1 /* OUT3_MONO */
+#define WM5100_OUT3L_ANC_SRC 0x0800 /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_MASK 0x0800 /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_SHIFT 11 /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_ANC_SRC_WIDTH 1 /* OUT3L_ANC_SRC */
+#define WM5100_OUT3L_PGA_VOL_MASK 0x00FE /* OUT3L_PGA_VOL - [7:1] */
+#define WM5100_OUT3L_PGA_VOL_SHIFT 1 /* OUT3L_PGA_VOL - [7:1] */
+#define WM5100_OUT3L_PGA_VOL_WIDTH 7 /* OUT3L_PGA_VOL - [7:1] */
+
+/*
+ * R1049 (0x419) - Out Volume 3R
+ */
+#define WM5100_OUT3R_ANC_SRC 0x0800 /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_MASK 0x0800 /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_SHIFT 11 /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_ANC_SRC_WIDTH 1 /* OUT3R_ANC_SRC */
+#define WM5100_OUT3R_PGA_VOL_MASK 0x00FE /* OUT3R_PGA_VOL - [7:1] */
+#define WM5100_OUT3R_PGA_VOL_SHIFT 1 /* OUT3R_PGA_VOL - [7:1] */
+#define WM5100_OUT3R_PGA_VOL_WIDTH 7 /* OUT3R_PGA_VOL - [7:1] */
+
+/*
+ * R1050 (0x41A) - DAC Volume Limit 3L
+ */
+#define WM5100_OUT3L_VOL_LIM_MASK 0x00FF /* OUT3L_VOL_LIM - [7:0] */
+#define WM5100_OUT3L_VOL_LIM_SHIFT 0 /* OUT3L_VOL_LIM - [7:0] */
+#define WM5100_OUT3L_VOL_LIM_WIDTH 8 /* OUT3L_VOL_LIM - [7:0] */
+
+/*
+ * R1051 (0x41B) - DAC Volume Limit 3R
+ */
+#define WM5100_OUT3R_VOL_LIM_MASK 0x00FF /* OUT3R_VOL_LIM - [7:0] */
+#define WM5100_OUT3R_VOL_LIM_SHIFT 0 /* OUT3R_VOL_LIM - [7:0] */
+#define WM5100_OUT3R_VOL_LIM_WIDTH 8 /* OUT3R_VOL_LIM - [7:0] */
+
+/*
+ * R1052 (0x41C) - Out Volume 4L
+ */
+#define WM5100_OUT4_OSR 0x2000 /* OUT4_OSR */
+#define WM5100_OUT4_OSR_MASK 0x2000 /* OUT4_OSR */
+#define WM5100_OUT4_OSR_SHIFT 13 /* OUT4_OSR */
+#define WM5100_OUT4_OSR_WIDTH 1 /* OUT4_OSR */
+#define WM5100_OUT4L_ANC_SRC 0x0800 /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_MASK 0x0800 /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_SHIFT 11 /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_ANC_SRC_WIDTH 1 /* OUT4L_ANC_SRC */
+#define WM5100_OUT4L_VOL_LIM_MASK 0x00FF /* OUT4L_VOL_LIM - [7:0] */
+#define WM5100_OUT4L_VOL_LIM_SHIFT 0 /* OUT4L_VOL_LIM - [7:0] */
+#define WM5100_OUT4L_VOL_LIM_WIDTH 8 /* OUT4L_VOL_LIM - [7:0] */
+
+/*
+ * R1053 (0x41D) - Out Volume 4R
+ */
+#define WM5100_OUT4R_ANC_SRC 0x0800 /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_MASK 0x0800 /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_SHIFT 11 /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_ANC_SRC_WIDTH 1 /* OUT4R_ANC_SRC */
+#define WM5100_OUT4R_VOL_LIM_MASK 0x00FF /* OUT4R_VOL_LIM - [7:0] */
+#define WM5100_OUT4R_VOL_LIM_SHIFT 0 /* OUT4R_VOL_LIM - [7:0] */
+#define WM5100_OUT4R_VOL_LIM_WIDTH 8 /* OUT4R_VOL_LIM - [7:0] */
+
+/*
+ * R1054 (0x41E) - DAC Volume Limit 5L
+ */
+#define WM5100_OUT5_OSR 0x2000 /* OUT5_OSR */
+#define WM5100_OUT5_OSR_MASK 0x2000 /* OUT5_OSR */
+#define WM5100_OUT5_OSR_SHIFT 13 /* OUT5_OSR */
+#define WM5100_OUT5_OSR_WIDTH 1 /* OUT5_OSR */
+#define WM5100_OUT5L_ANC_SRC 0x0800 /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_MASK 0x0800 /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_SHIFT 11 /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_ANC_SRC_WIDTH 1 /* OUT5L_ANC_SRC */
+#define WM5100_OUT5L_VOL_LIM_MASK 0x00FF /* OUT5L_VOL_LIM - [7:0] */
+#define WM5100_OUT5L_VOL_LIM_SHIFT 0 /* OUT5L_VOL_LIM - [7:0] */
+#define WM5100_OUT5L_VOL_LIM_WIDTH 8 /* OUT5L_VOL_LIM - [7:0] */
+
+/*
+ * R1055 (0x41F) - DAC Volume Limit 5R
+ */
+#define WM5100_OUT5R_ANC_SRC 0x0800 /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_MASK 0x0800 /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_SHIFT 11 /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_ANC_SRC_WIDTH 1 /* OUT5R_ANC_SRC */
+#define WM5100_OUT5R_VOL_LIM_MASK 0x00FF /* OUT5R_VOL_LIM - [7:0] */
+#define WM5100_OUT5R_VOL_LIM_SHIFT 0 /* OUT5R_VOL_LIM - [7:0] */
+#define WM5100_OUT5R_VOL_LIM_WIDTH 8 /* OUT5R_VOL_LIM - [7:0] */
+
+/*
+ * R1056 (0x420) - DAC Volume Limit 6L
+ */
+#define WM5100_OUT6_OSR 0x2000 /* OUT6_OSR */
+#define WM5100_OUT6_OSR_MASK 0x2000 /* OUT6_OSR */
+#define WM5100_OUT6_OSR_SHIFT 13 /* OUT6_OSR */
+#define WM5100_OUT6_OSR_WIDTH 1 /* OUT6_OSR */
+#define WM5100_OUT6L_ANC_SRC 0x0800 /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_MASK 0x0800 /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_SHIFT 11 /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_ANC_SRC_WIDTH 1 /* OUT6L_ANC_SRC */
+#define WM5100_OUT6L_VOL_LIM_MASK 0x00FF /* OUT6L_VOL_LIM - [7:0] */
+#define WM5100_OUT6L_VOL_LIM_SHIFT 0 /* OUT6L_VOL_LIM - [7:0] */
+#define WM5100_OUT6L_VOL_LIM_WIDTH 8 /* OUT6L_VOL_LIM - [7:0] */
+
+/*
+ * R1057 (0x421) - DAC Volume Limit 6R
+ */
+#define WM5100_OUT6R_ANC_SRC 0x0800 /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_MASK 0x0800 /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_SHIFT 11 /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_ANC_SRC_WIDTH 1 /* OUT6R_ANC_SRC */
+#define WM5100_OUT6R_VOL_LIM_MASK 0x00FF /* OUT6R_VOL_LIM - [7:0] */
+#define WM5100_OUT6R_VOL_LIM_SHIFT 0 /* OUT6R_VOL_LIM - [7:0] */
+#define WM5100_OUT6R_VOL_LIM_WIDTH 8 /* OUT6R_VOL_LIM - [7:0] */
+
+/*
+ * R1088 (0x440) - DAC AEC Control 1
+ */
+#define WM5100_AEC_LOOPBACK_SRC_MASK 0x003C /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_LOOPBACK_SRC_SHIFT 2 /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_LOOPBACK_SRC_WIDTH 4 /* AEC_LOOPBACK_SRC - [5:2] */
+#define WM5100_AEC_ENA_STS 0x0002 /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_MASK 0x0002 /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_SHIFT 1 /* AEC_ENA_STS */
+#define WM5100_AEC_ENA_STS_WIDTH 1 /* AEC_ENA_STS */
+#define WM5100_AEC_LOOPBACK_ENA 0x0001 /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_MASK 0x0001 /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_SHIFT 0 /* AEC_LOOPBACK_ENA */
+#define WM5100_AEC_LOOPBACK_ENA_WIDTH 1 /* AEC_LOOPBACK_ENA */
+
+/*
+ * R1089 (0x441) - Output Volume Ramp
+ */
+#define WM5100_OUT_VD_RAMP_MASK 0x0070 /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VD_RAMP_SHIFT 4 /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VD_RAMP_WIDTH 3 /* OUT_VD_RAMP - [6:4] */
+#define WM5100_OUT_VI_RAMP_MASK 0x0007 /* OUT_VI_RAMP - [2:0] */
+#define WM5100_OUT_VI_RAMP_SHIFT 0 /* OUT_VI_RAMP - [2:0] */
+#define WM5100_OUT_VI_RAMP_WIDTH 3 /* OUT_VI_RAMP - [2:0] */
+
+/*
+ * R1152 (0x480) - DAC Digital Volume 1L
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT1L_MUTE 0x0100 /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_MASK 0x0100 /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_SHIFT 8 /* OUT1L_MUTE */
+#define WM5100_OUT1L_MUTE_WIDTH 1 /* OUT1L_MUTE */
+#define WM5100_OUT1L_VOL_MASK 0x00FF /* OUT1L_VOL - [7:0] */
+#define WM5100_OUT1L_VOL_SHIFT 0 /* OUT1L_VOL - [7:0] */
+#define WM5100_OUT1L_VOL_WIDTH 8 /* OUT1L_VOL - [7:0] */
+
+/*
+ * R1153 (0x481) - DAC Digital Volume 1R
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT1R_MUTE 0x0100 /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_MASK 0x0100 /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_SHIFT 8 /* OUT1R_MUTE */
+#define WM5100_OUT1R_MUTE_WIDTH 1 /* OUT1R_MUTE */
+#define WM5100_OUT1R_VOL_MASK 0x00FF /* OUT1R_VOL - [7:0] */
+#define WM5100_OUT1R_VOL_SHIFT 0 /* OUT1R_VOL - [7:0] */
+#define WM5100_OUT1R_VOL_WIDTH 8 /* OUT1R_VOL - [7:0] */
+
+/*
+ * R1154 (0x482) - DAC Digital Volume 2L
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT2L_MUTE 0x0100 /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_MASK 0x0100 /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_SHIFT 8 /* OUT2L_MUTE */
+#define WM5100_OUT2L_MUTE_WIDTH 1 /* OUT2L_MUTE */
+#define WM5100_OUT2L_VOL_MASK 0x00FF /* OUT2L_VOL - [7:0] */
+#define WM5100_OUT2L_VOL_SHIFT 0 /* OUT2L_VOL - [7:0] */
+#define WM5100_OUT2L_VOL_WIDTH 8 /* OUT2L_VOL - [7:0] */
+
+/*
+ * R1155 (0x483) - DAC Digital Volume 2R
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT2R_MUTE 0x0100 /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_MASK 0x0100 /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_SHIFT 8 /* OUT2R_MUTE */
+#define WM5100_OUT2R_MUTE_WIDTH 1 /* OUT2R_MUTE */
+#define WM5100_OUT2R_VOL_MASK 0x00FF /* OUT2R_VOL - [7:0] */
+#define WM5100_OUT2R_VOL_SHIFT 0 /* OUT2R_VOL - [7:0] */
+#define WM5100_OUT2R_VOL_WIDTH 8 /* OUT2R_VOL - [7:0] */
+
+/*
+ * R1156 (0x484) - DAC Digital Volume 3L
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT3L_MUTE 0x0100 /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_MASK 0x0100 /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_SHIFT 8 /* OUT3L_MUTE */
+#define WM5100_OUT3L_MUTE_WIDTH 1 /* OUT3L_MUTE */
+#define WM5100_OUT3L_VOL_MASK 0x00FF /* OUT3L_VOL - [7:0] */
+#define WM5100_OUT3L_VOL_SHIFT 0 /* OUT3L_VOL - [7:0] */
+#define WM5100_OUT3L_VOL_WIDTH 8 /* OUT3L_VOL - [7:0] */
+
+/*
+ * R1157 (0x485) - DAC Digital Volume 3R
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT3R_MUTE 0x0100 /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_MASK 0x0100 /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_SHIFT 8 /* OUT3R_MUTE */
+#define WM5100_OUT3R_MUTE_WIDTH 1 /* OUT3R_MUTE */
+#define WM5100_OUT3R_VOL_MASK 0x00FF /* OUT3R_VOL - [7:0] */
+#define WM5100_OUT3R_VOL_SHIFT 0 /* OUT3R_VOL - [7:0] */
+#define WM5100_OUT3R_VOL_WIDTH 8 /* OUT3R_VOL - [7:0] */
+
+/*
+ * R1158 (0x486) - DAC Digital Volume 4L
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT4L_MUTE 0x0100 /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_MASK 0x0100 /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_SHIFT 8 /* OUT4L_MUTE */
+#define WM5100_OUT4L_MUTE_WIDTH 1 /* OUT4L_MUTE */
+#define WM5100_OUT4L_VOL_MASK 0x00FF /* OUT4L_VOL - [7:0] */
+#define WM5100_OUT4L_VOL_SHIFT 0 /* OUT4L_VOL - [7:0] */
+#define WM5100_OUT4L_VOL_WIDTH 8 /* OUT4L_VOL - [7:0] */
+
+/*
+ * R1159 (0x487) - DAC Digital Volume 4R
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT4R_MUTE 0x0100 /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_MASK 0x0100 /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_SHIFT 8 /* OUT4R_MUTE */
+#define WM5100_OUT4R_MUTE_WIDTH 1 /* OUT4R_MUTE */
+#define WM5100_OUT4R_VOL_MASK 0x00FF /* OUT4R_VOL - [7:0] */
+#define WM5100_OUT4R_VOL_SHIFT 0 /* OUT4R_VOL - [7:0] */
+#define WM5100_OUT4R_VOL_WIDTH 8 /* OUT4R_VOL - [7:0] */
+
+/*
+ * R1160 (0x488) - DAC Digital Volume 5L
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT5L_MUTE 0x0100 /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_MASK 0x0100 /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_SHIFT 8 /* OUT5L_MUTE */
+#define WM5100_OUT5L_MUTE_WIDTH 1 /* OUT5L_MUTE */
+#define WM5100_OUT5L_VOL_MASK 0x00FF /* OUT5L_VOL - [7:0] */
+#define WM5100_OUT5L_VOL_SHIFT 0 /* OUT5L_VOL - [7:0] */
+#define WM5100_OUT5L_VOL_WIDTH 8 /* OUT5L_VOL - [7:0] */
+
+/*
+ * R1161 (0x489) - DAC Digital Volume 5R
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT5R_MUTE 0x0100 /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_MASK 0x0100 /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_SHIFT 8 /* OUT5R_MUTE */
+#define WM5100_OUT5R_MUTE_WIDTH 1 /* OUT5R_MUTE */
+#define WM5100_OUT5R_VOL_MASK 0x00FF /* OUT5R_VOL - [7:0] */
+#define WM5100_OUT5R_VOL_SHIFT 0 /* OUT5R_VOL - [7:0] */
+#define WM5100_OUT5R_VOL_WIDTH 8 /* OUT5R_VOL - [7:0] */
+
+/*
+ * R1162 (0x48A) - DAC Digital Volume 6L
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT6L_MUTE 0x0100 /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_MASK 0x0100 /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_SHIFT 8 /* OUT6L_MUTE */
+#define WM5100_OUT6L_MUTE_WIDTH 1 /* OUT6L_MUTE */
+#define WM5100_OUT6L_VOL_MASK 0x00FF /* OUT6L_VOL - [7:0] */
+#define WM5100_OUT6L_VOL_SHIFT 0 /* OUT6L_VOL - [7:0] */
+#define WM5100_OUT6L_VOL_WIDTH 8 /* OUT6L_VOL - [7:0] */
+
+/*
+ * R1163 (0x48B) - DAC Digital Volume 6R
+ */
+#define WM5100_OUT_VU 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_MASK 0x0200 /* OUT_VU */
+#define WM5100_OUT_VU_SHIFT 9 /* OUT_VU */
+#define WM5100_OUT_VU_WIDTH 1 /* OUT_VU */
+#define WM5100_OUT6R_MUTE 0x0100 /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_MASK 0x0100 /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_SHIFT 8 /* OUT6R_MUTE */
+#define WM5100_OUT6R_MUTE_WIDTH 1 /* OUT6R_MUTE */
+#define WM5100_OUT6R_VOL_MASK 0x00FF /* OUT6R_VOL - [7:0] */
+#define WM5100_OUT6R_VOL_SHIFT 0 /* OUT6R_VOL - [7:0] */
+#define WM5100_OUT6R_VOL_WIDTH 8 /* OUT6R_VOL - [7:0] */
+
+/*
+ * R1216 (0x4C0) - PDM SPK1 CTRL 1
+ */
+#define WM5100_SPK1R_MUTE 0x2000 /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_MASK 0x2000 /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_SHIFT 13 /* SPK1R_MUTE */
+#define WM5100_SPK1R_MUTE_WIDTH 1 /* SPK1R_MUTE */
+#define WM5100_SPK1L_MUTE 0x1000 /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_MASK 0x1000 /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_SHIFT 12 /* SPK1L_MUTE */
+#define WM5100_SPK1L_MUTE_WIDTH 1 /* SPK1L_MUTE */
+#define WM5100_SPK1_MUTE_ENDIAN 0x0100 /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_MASK 0x0100 /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_SHIFT 8 /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_ENDIAN_WIDTH 1 /* SPK1_MUTE_ENDIAN */
+#define WM5100_SPK1_MUTE_SEQ1_MASK 0x00FF /* SPK1_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK1_MUTE_SEQ1_SHIFT 0 /* SPK1_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK1_MUTE_SEQ1_WIDTH 8 /* SPK1_MUTE_SEQ1 - [7:0] */
+
+/*
+ * R1217 (0x4C1) - PDM SPK1 CTRL 2
+ */
+#define WM5100_SPK1_FMT 0x0001 /* SPK1_FMT */
+#define WM5100_SPK1_FMT_MASK 0x0001 /* SPK1_FMT */
+#define WM5100_SPK1_FMT_SHIFT 0 /* SPK1_FMT */
+#define WM5100_SPK1_FMT_WIDTH 1 /* SPK1_FMT */
+
+/*
+ * R1218 (0x4C2) - PDM SPK2 CTRL 1
+ */
+#define WM5100_SPK2R_MUTE 0x2000 /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_MASK 0x2000 /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_SHIFT 13 /* SPK2R_MUTE */
+#define WM5100_SPK2R_MUTE_WIDTH 1 /* SPK2R_MUTE */
+#define WM5100_SPK2L_MUTE 0x1000 /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_MASK 0x1000 /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_SHIFT 12 /* SPK2L_MUTE */
+#define WM5100_SPK2L_MUTE_WIDTH 1 /* SPK2L_MUTE */
+#define WM5100_SPK2_MUTE_ENDIAN 0x0100 /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_MASK 0x0100 /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_SHIFT 8 /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_ENDIAN_WIDTH 1 /* SPK2_MUTE_ENDIAN */
+#define WM5100_SPK2_MUTE_SEQ1_MASK 0x00FF /* SPK2_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK2_MUTE_SEQ1_SHIFT 0 /* SPK2_MUTE_SEQ1 - [7:0] */
+#define WM5100_SPK2_MUTE_SEQ1_WIDTH 8 /* SPK2_MUTE_SEQ1 - [7:0] */
+
+/*
+ * R1219 (0x4C3) - PDM SPK2 CTRL 2
+ */
+#define WM5100_SPK2_FMT 0x0001 /* SPK2_FMT */
+#define WM5100_SPK2_FMT_MASK 0x0001 /* SPK2_FMT */
+#define WM5100_SPK2_FMT_SHIFT 0 /* SPK2_FMT */
+#define WM5100_SPK2_FMT_WIDTH 1 /* SPK2_FMT */
+
+/*
+ * R1280 (0x500) - Audio IF 1_1
+ */
+#define WM5100_AIF1_BCLK_INV 0x0080 /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_MASK 0x0080 /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_SHIFT 7 /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_INV_WIDTH 1 /* AIF1_BCLK_INV */
+#define WM5100_AIF1_BCLK_FRC 0x0040 /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_MASK 0x0040 /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_SHIFT 6 /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_FRC_WIDTH 1 /* AIF1_BCLK_FRC */
+#define WM5100_AIF1_BCLK_MSTR 0x0020 /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_MASK 0x0020 /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_SHIFT 5 /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_MSTR_WIDTH 1 /* AIF1_BCLK_MSTR */
+#define WM5100_AIF1_BCLK_FREQ_MASK 0x001F /* AIF1_BCLK_FREQ - [4:0] */
+#define WM5100_AIF1_BCLK_FREQ_SHIFT 0 /* AIF1_BCLK_FREQ - [4:0] */
+#define WM5100_AIF1_BCLK_FREQ_WIDTH 5 /* AIF1_BCLK_FREQ - [4:0] */
+
+/*
+ * R1281 (0x501) - Audio IF 1_2
+ */
+#define WM5100_AIF1TX_DAT_TRI 0x0020 /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_MASK 0x0020 /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_SHIFT 5 /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_DAT_TRI_WIDTH 1 /* AIF1TX_DAT_TRI */
+#define WM5100_AIF1TX_LRCLK_SRC 0x0008 /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_MASK 0x0008 /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_SHIFT 3 /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_SRC_WIDTH 1 /* AIF1TX_LRCLK_SRC */
+#define WM5100_AIF1TX_LRCLK_INV 0x0004 /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_MASK 0x0004 /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_SHIFT 2 /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_INV_WIDTH 1 /* AIF1TX_LRCLK_INV */
+#define WM5100_AIF1TX_LRCLK_FRC 0x0002 /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_MASK 0x0002 /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_SHIFT 1 /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_FRC_WIDTH 1 /* AIF1TX_LRCLK_FRC */
+#define WM5100_AIF1TX_LRCLK_MSTR 0x0001 /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_MASK 0x0001 /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_SHIFT 0 /* AIF1TX_LRCLK_MSTR */
+#define WM5100_AIF1TX_LRCLK_MSTR_WIDTH 1 /* AIF1TX_LRCLK_MSTR */
+
+/*
+ * R1282 (0x502) - Audio IF 1_3
+ */
+#define WM5100_AIF1RX_LRCLK_INV 0x0004 /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_MASK 0x0004 /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_SHIFT 2 /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_INV_WIDTH 1 /* AIF1RX_LRCLK_INV */
+#define WM5100_AIF1RX_LRCLK_FRC 0x0002 /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_MASK 0x0002 /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_SHIFT 1 /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_FRC_WIDTH 1 /* AIF1RX_LRCLK_FRC */
+#define WM5100_AIF1RX_LRCLK_MSTR 0x0001 /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_MASK 0x0001 /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_SHIFT 0 /* AIF1RX_LRCLK_MSTR */
+#define WM5100_AIF1RX_LRCLK_MSTR_WIDTH 1 /* AIF1RX_LRCLK_MSTR */
+
+/*
+ * R1283 (0x503) - Audio IF 1_4
+ */
+#define WM5100_AIF1_TRI 0x0040 /* AIF1_TRI */
+#define WM5100_AIF1_TRI_MASK 0x0040 /* AIF1_TRI */
+#define WM5100_AIF1_TRI_SHIFT 6 /* AIF1_TRI */
+#define WM5100_AIF1_TRI_WIDTH 1 /* AIF1_TRI */
+#define WM5100_AIF1_RATE_MASK 0x0003 /* AIF1_RATE - [1:0] */
+#define WM5100_AIF1_RATE_SHIFT 0 /* AIF1_RATE - [1:0] */
+#define WM5100_AIF1_RATE_WIDTH 2 /* AIF1_RATE - [1:0] */
+
+/*
+ * R1284 (0x504) - Audio IF 1_5
+ */
+#define WM5100_AIF1_FMT_MASK 0x0007 /* AIF1_FMT - [2:0] */
+#define WM5100_AIF1_FMT_SHIFT 0 /* AIF1_FMT - [2:0] */
+#define WM5100_AIF1_FMT_WIDTH 3 /* AIF1_FMT - [2:0] */
+
+/*
+ * R1285 (0x505) - Audio IF 1_6
+ */
+#define WM5100_AIF1TX_BCPF_MASK 0x1FFF /* AIF1TX_BCPF - [12:0] */
+#define WM5100_AIF1TX_BCPF_SHIFT 0 /* AIF1TX_BCPF - [12:0] */
+#define WM5100_AIF1TX_BCPF_WIDTH 13 /* AIF1TX_BCPF - [12:0] */
+
+/*
+ * R1286 (0x506) - Audio IF 1_7
+ */
+#define WM5100_AIF1RX_BCPF_MASK 0x1FFF /* AIF1RX_BCPF - [12:0] */
+#define WM5100_AIF1RX_BCPF_SHIFT 0 /* AIF1RX_BCPF - [12:0] */
+#define WM5100_AIF1RX_BCPF_WIDTH 13 /* AIF1RX_BCPF - [12:0] */
+
+/*
+ * R1287 (0x507) - Audio IF 1_8
+ */
+#define WM5100_AIF1TX_WL_MASK 0x3F00 /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_WL_SHIFT 8 /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_WL_WIDTH 6 /* AIF1TX_WL - [13:8] */
+#define WM5100_AIF1TX_SLOT_LEN_MASK 0x00FF /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1TX_SLOT_LEN_SHIFT 0 /* AIF1TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1TX_SLOT_LEN_WIDTH 8 /* AIF1TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1288 (0x508) - Audio IF 1_9
+ */
+#define WM5100_AIF1RX_WL_MASK 0x3F00 /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_WL_SHIFT 8 /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_WL_WIDTH 6 /* AIF1RX_WL - [13:8] */
+#define WM5100_AIF1RX_SLOT_LEN_MASK 0x00FF /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1RX_SLOT_LEN_SHIFT 0 /* AIF1RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF1RX_SLOT_LEN_WIDTH 8 /* AIF1RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1289 (0x509) - Audio IF 1_10
+ */
+#define WM5100_AIF1TX1_SLOT_MASK 0x003F /* AIF1TX1_SLOT - [5:0] */
+#define WM5100_AIF1TX1_SLOT_SHIFT 0 /* AIF1TX1_SLOT - [5:0] */
+#define WM5100_AIF1TX1_SLOT_WIDTH 6 /* AIF1TX1_SLOT - [5:0] */
+
+/*
+ * R1290 (0x50A) - Audio IF 1_11
+ */
+#define WM5100_AIF1TX2_SLOT_MASK 0x003F /* AIF1TX2_SLOT - [5:0] */
+#define WM5100_AIF1TX2_SLOT_SHIFT 0 /* AIF1TX2_SLOT - [5:0] */
+#define WM5100_AIF1TX2_SLOT_WIDTH 6 /* AIF1TX2_SLOT - [5:0] */
+
+/*
+ * R1291 (0x50B) - Audio IF 1_12
+ */
+#define WM5100_AIF1TX3_SLOT_MASK 0x003F /* AIF1TX3_SLOT - [5:0] */
+#define WM5100_AIF1TX3_SLOT_SHIFT 0 /* AIF1TX3_SLOT - [5:0] */
+#define WM5100_AIF1TX3_SLOT_WIDTH 6 /* AIF1TX3_SLOT - [5:0] */
+
+/*
+ * R1292 (0x50C) - Audio IF 1_13
+ */
+#define WM5100_AIF1TX4_SLOT_MASK 0x003F /* AIF1TX4_SLOT - [5:0] */
+#define WM5100_AIF1TX4_SLOT_SHIFT 0 /* AIF1TX4_SLOT - [5:0] */
+#define WM5100_AIF1TX4_SLOT_WIDTH 6 /* AIF1TX4_SLOT - [5:0] */
+
+/*
+ * R1293 (0x50D) - Audio IF 1_14
+ */
+#define WM5100_AIF1TX5_SLOT_MASK 0x003F /* AIF1TX5_SLOT - [5:0] */
+#define WM5100_AIF1TX5_SLOT_SHIFT 0 /* AIF1TX5_SLOT - [5:0] */
+#define WM5100_AIF1TX5_SLOT_WIDTH 6 /* AIF1TX5_SLOT - [5:0] */
+
+/*
+ * R1294 (0x50E) - Audio IF 1_15
+ */
+#define WM5100_AIF1TX6_SLOT_MASK 0x003F /* AIF1TX6_SLOT - [5:0] */
+#define WM5100_AIF1TX6_SLOT_SHIFT 0 /* AIF1TX6_SLOT - [5:0] */
+#define WM5100_AIF1TX6_SLOT_WIDTH 6 /* AIF1TX6_SLOT - [5:0] */
+
+/*
+ * R1295 (0x50F) - Audio IF 1_16
+ */
+#define WM5100_AIF1TX7_SLOT_MASK 0x003F /* AIF1TX7_SLOT - [5:0] */
+#define WM5100_AIF1TX7_SLOT_SHIFT 0 /* AIF1TX7_SLOT - [5:0] */
+#define WM5100_AIF1TX7_SLOT_WIDTH 6 /* AIF1TX7_SLOT - [5:0] */
+
+/*
+ * R1296 (0x510) - Audio IF 1_17
+ */
+#define WM5100_AIF1TX8_SLOT_MASK 0x003F /* AIF1TX8_SLOT - [5:0] */
+#define WM5100_AIF1TX8_SLOT_SHIFT 0 /* AIF1TX8_SLOT - [5:0] */
+#define WM5100_AIF1TX8_SLOT_WIDTH 6 /* AIF1TX8_SLOT - [5:0] */
+
+/*
+ * R1297 (0x511) - Audio IF 1_18
+ */
+#define WM5100_AIF1RX1_SLOT_MASK 0x003F /* AIF1RX1_SLOT - [5:0] */
+#define WM5100_AIF1RX1_SLOT_SHIFT 0 /* AIF1RX1_SLOT - [5:0] */
+#define WM5100_AIF1RX1_SLOT_WIDTH 6 /* AIF1RX1_SLOT - [5:0] */
+
+/*
+ * R1298 (0x512) - Audio IF 1_19
+ */
+#define WM5100_AIF1RX2_SLOT_MASK 0x003F /* AIF1RX2_SLOT - [5:0] */
+#define WM5100_AIF1RX2_SLOT_SHIFT 0 /* AIF1RX2_SLOT - [5:0] */
+#define WM5100_AIF1RX2_SLOT_WIDTH 6 /* AIF1RX2_SLOT - [5:0] */
+
+/*
+ * R1299 (0x513) - Audio IF 1_20
+ */
+#define WM5100_AIF1RX3_SLOT_MASK 0x003F /* AIF1RX3_SLOT - [5:0] */
+#define WM5100_AIF1RX3_SLOT_SHIFT 0 /* AIF1RX3_SLOT - [5:0] */
+#define WM5100_AIF1RX3_SLOT_WIDTH 6 /* AIF1RX3_SLOT - [5:0] */
+
+/*
+ * R1300 (0x514) - Audio IF 1_21
+ */
+#define WM5100_AIF1RX4_SLOT_MASK 0x003F /* AIF1RX4_SLOT - [5:0] */
+#define WM5100_AIF1RX4_SLOT_SHIFT 0 /* AIF1RX4_SLOT - [5:0] */
+#define WM5100_AIF1RX4_SLOT_WIDTH 6 /* AIF1RX4_SLOT - [5:0] */
+
+/*
+ * R1301 (0x515) - Audio IF 1_22
+ */
+#define WM5100_AIF1RX5_SLOT_MASK 0x003F /* AIF1RX5_SLOT - [5:0] */
+#define WM5100_AIF1RX5_SLOT_SHIFT 0 /* AIF1RX5_SLOT - [5:0] */
+#define WM5100_AIF1RX5_SLOT_WIDTH 6 /* AIF1RX5_SLOT - [5:0] */
+
+/*
+ * R1302 (0x516) - Audio IF 1_23
+ */
+#define WM5100_AIF1RX6_SLOT_MASK 0x003F /* AIF1RX6_SLOT - [5:0] */
+#define WM5100_AIF1RX6_SLOT_SHIFT 0 /* AIF1RX6_SLOT - [5:0] */
+#define WM5100_AIF1RX6_SLOT_WIDTH 6 /* AIF1RX6_SLOT - [5:0] */
+
+/*
+ * R1303 (0x517) - Audio IF 1_24
+ */
+#define WM5100_AIF1RX7_SLOT_MASK 0x003F /* AIF1RX7_SLOT - [5:0] */
+#define WM5100_AIF1RX7_SLOT_SHIFT 0 /* AIF1RX7_SLOT - [5:0] */
+#define WM5100_AIF1RX7_SLOT_WIDTH 6 /* AIF1RX7_SLOT - [5:0] */
+
+/*
+ * R1304 (0x518) - Audio IF 1_25
+ */
+#define WM5100_AIF1RX8_SLOT_MASK 0x003F /* AIF1RX8_SLOT - [5:0] */
+#define WM5100_AIF1RX8_SLOT_SHIFT 0 /* AIF1RX8_SLOT - [5:0] */
+#define WM5100_AIF1RX8_SLOT_WIDTH 6 /* AIF1RX8_SLOT - [5:0] */
+
+/*
+ * R1305 (0x519) - Audio IF 1_26
+ */
+#define WM5100_AIF1TX8_ENA 0x0080 /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_MASK 0x0080 /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_SHIFT 7 /* AIF1TX8_ENA */
+#define WM5100_AIF1TX8_ENA_WIDTH 1 /* AIF1TX8_ENA */
+#define WM5100_AIF1TX7_ENA 0x0040 /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_MASK 0x0040 /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_SHIFT 6 /* AIF1TX7_ENA */
+#define WM5100_AIF1TX7_ENA_WIDTH 1 /* AIF1TX7_ENA */
+#define WM5100_AIF1TX6_ENA 0x0020 /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_MASK 0x0020 /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_SHIFT 5 /* AIF1TX6_ENA */
+#define WM5100_AIF1TX6_ENA_WIDTH 1 /* AIF1TX6_ENA */
+#define WM5100_AIF1TX5_ENA 0x0010 /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_MASK 0x0010 /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_SHIFT 4 /* AIF1TX5_ENA */
+#define WM5100_AIF1TX5_ENA_WIDTH 1 /* AIF1TX5_ENA */
+#define WM5100_AIF1TX4_ENA 0x0008 /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_MASK 0x0008 /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_SHIFT 3 /* AIF1TX4_ENA */
+#define WM5100_AIF1TX4_ENA_WIDTH 1 /* AIF1TX4_ENA */
+#define WM5100_AIF1TX3_ENA 0x0004 /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_MASK 0x0004 /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_SHIFT 2 /* AIF1TX3_ENA */
+#define WM5100_AIF1TX3_ENA_WIDTH 1 /* AIF1TX3_ENA */
+#define WM5100_AIF1TX2_ENA 0x0002 /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_MASK 0x0002 /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_SHIFT 1 /* AIF1TX2_ENA */
+#define WM5100_AIF1TX2_ENA_WIDTH 1 /* AIF1TX2_ENA */
+#define WM5100_AIF1TX1_ENA 0x0001 /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_MASK 0x0001 /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_SHIFT 0 /* AIF1TX1_ENA */
+#define WM5100_AIF1TX1_ENA_WIDTH 1 /* AIF1TX1_ENA */
+
+/*
+ * R1306 (0x51A) - Audio IF 1_27
+ */
+#define WM5100_AIF1RX8_ENA 0x0080 /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_MASK 0x0080 /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_SHIFT 7 /* AIF1RX8_ENA */
+#define WM5100_AIF1RX8_ENA_WIDTH 1 /* AIF1RX8_ENA */
+#define WM5100_AIF1RX7_ENA 0x0040 /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_MASK 0x0040 /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_SHIFT 6 /* AIF1RX7_ENA */
+#define WM5100_AIF1RX7_ENA_WIDTH 1 /* AIF1RX7_ENA */
+#define WM5100_AIF1RX6_ENA 0x0020 /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_MASK 0x0020 /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_SHIFT 5 /* AIF1RX6_ENA */
+#define WM5100_AIF1RX6_ENA_WIDTH 1 /* AIF1RX6_ENA */
+#define WM5100_AIF1RX5_ENA 0x0010 /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_MASK 0x0010 /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_SHIFT 4 /* AIF1RX5_ENA */
+#define WM5100_AIF1RX5_ENA_WIDTH 1 /* AIF1RX5_ENA */
+#define WM5100_AIF1RX4_ENA 0x0008 /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_MASK 0x0008 /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_SHIFT 3 /* AIF1RX4_ENA */
+#define WM5100_AIF1RX4_ENA_WIDTH 1 /* AIF1RX4_ENA */
+#define WM5100_AIF1RX3_ENA 0x0004 /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_MASK 0x0004 /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_SHIFT 2 /* AIF1RX3_ENA */
+#define WM5100_AIF1RX3_ENA_WIDTH 1 /* AIF1RX3_ENA */
+#define WM5100_AIF1RX2_ENA 0x0002 /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_MASK 0x0002 /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_SHIFT 1 /* AIF1RX2_ENA */
+#define WM5100_AIF1RX2_ENA_WIDTH 1 /* AIF1RX2_ENA */
+#define WM5100_AIF1RX1_ENA 0x0001 /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_MASK 0x0001 /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_SHIFT 0 /* AIF1RX1_ENA */
+#define WM5100_AIF1RX1_ENA_WIDTH 1 /* AIF1RX1_ENA */
+
+/*
+ * R1344 (0x540) - Audio IF 2_1
+ */
+#define WM5100_AIF2_BCLK_INV 0x0080 /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_MASK 0x0080 /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_SHIFT 7 /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_INV_WIDTH 1 /* AIF2_BCLK_INV */
+#define WM5100_AIF2_BCLK_FRC 0x0040 /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_MASK 0x0040 /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_SHIFT 6 /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_FRC_WIDTH 1 /* AIF2_BCLK_FRC */
+#define WM5100_AIF2_BCLK_MSTR 0x0020 /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_MASK 0x0020 /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_SHIFT 5 /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_MSTR_WIDTH 1 /* AIF2_BCLK_MSTR */
+#define WM5100_AIF2_BCLK_FREQ_MASK 0x001F /* AIF2_BCLK_FREQ - [4:0] */
+#define WM5100_AIF2_BCLK_FREQ_SHIFT 0 /* AIF2_BCLK_FREQ - [4:0] */
+#define WM5100_AIF2_BCLK_FREQ_WIDTH 5 /* AIF2_BCLK_FREQ - [4:0] */
+
+/*
+ * R1345 (0x541) - Audio IF 2_2
+ */
+#define WM5100_AIF2TX_DAT_TRI 0x0020 /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_MASK 0x0020 /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_SHIFT 5 /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_DAT_TRI_WIDTH 1 /* AIF2TX_DAT_TRI */
+#define WM5100_AIF2TX_LRCLK_SRC 0x0008 /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_MASK 0x0008 /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_SHIFT 3 /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_SRC_WIDTH 1 /* AIF2TX_LRCLK_SRC */
+#define WM5100_AIF2TX_LRCLK_INV 0x0004 /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_MASK 0x0004 /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_SHIFT 2 /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_INV_WIDTH 1 /* AIF2TX_LRCLK_INV */
+#define WM5100_AIF2TX_LRCLK_FRC 0x0002 /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_MASK 0x0002 /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_SHIFT 1 /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_FRC_WIDTH 1 /* AIF2TX_LRCLK_FRC */
+#define WM5100_AIF2TX_LRCLK_MSTR 0x0001 /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_MASK 0x0001 /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_SHIFT 0 /* AIF2TX_LRCLK_MSTR */
+#define WM5100_AIF2TX_LRCLK_MSTR_WIDTH 1 /* AIF2TX_LRCLK_MSTR */
+
+/*
+ * R1346 (0x542) - Audio IF 2_3
+ */
+#define WM5100_AIF2RX_LRCLK_INV 0x0004 /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_MASK 0x0004 /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_SHIFT 2 /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_INV_WIDTH 1 /* AIF2RX_LRCLK_INV */
+#define WM5100_AIF2RX_LRCLK_FRC 0x0002 /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_MASK 0x0002 /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_SHIFT 1 /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_FRC_WIDTH 1 /* AIF2RX_LRCLK_FRC */
+#define WM5100_AIF2RX_LRCLK_MSTR 0x0001 /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_MASK 0x0001 /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_SHIFT 0 /* AIF2RX_LRCLK_MSTR */
+#define WM5100_AIF2RX_LRCLK_MSTR_WIDTH 1 /* AIF2RX_LRCLK_MSTR */
+
+/*
+ * R1347 (0x543) - Audio IF 2_4
+ */
+#define WM5100_AIF2_TRI 0x0040 /* AIF2_TRI */
+#define WM5100_AIF2_TRI_MASK 0x0040 /* AIF2_TRI */
+#define WM5100_AIF2_TRI_SHIFT 6 /* AIF2_TRI */
+#define WM5100_AIF2_TRI_WIDTH 1 /* AIF2_TRI */
+#define WM5100_AIF2_RATE_MASK 0x0003 /* AIF2_RATE - [1:0] */
+#define WM5100_AIF2_RATE_SHIFT 0 /* AIF2_RATE - [1:0] */
+#define WM5100_AIF2_RATE_WIDTH 2 /* AIF2_RATE - [1:0] */
+
+/*
+ * R1348 (0x544) - Audio IF 2_5
+ */
+#define WM5100_AIF2_FMT_MASK 0x0007 /* AIF2_FMT - [2:0] */
+#define WM5100_AIF2_FMT_SHIFT 0 /* AIF2_FMT - [2:0] */
+#define WM5100_AIF2_FMT_WIDTH 3 /* AIF2_FMT - [2:0] */
+
+/*
+ * R1349 (0x545) - Audio IF 2_6
+ */
+#define WM5100_AIF2TX_BCPF_MASK 0x1FFF /* AIF2TX_BCPF - [12:0] */
+#define WM5100_AIF2TX_BCPF_SHIFT 0 /* AIF2TX_BCPF - [12:0] */
+#define WM5100_AIF2TX_BCPF_WIDTH 13 /* AIF2TX_BCPF - [12:0] */
+
+/*
+ * R1350 (0x546) - Audio IF 2_7
+ */
+#define WM5100_AIF2RX_BCPF_MASK 0x1FFF /* AIF2RX_BCPF - [12:0] */
+#define WM5100_AIF2RX_BCPF_SHIFT 0 /* AIF2RX_BCPF - [12:0] */
+#define WM5100_AIF2RX_BCPF_WIDTH 13 /* AIF2RX_BCPF - [12:0] */
+
+/*
+ * R1351 (0x547) - Audio IF 2_8
+ */
+#define WM5100_AIF2TX_WL_MASK 0x3F00 /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_WL_SHIFT 8 /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_WL_WIDTH 6 /* AIF2TX_WL - [13:8] */
+#define WM5100_AIF2TX_SLOT_LEN_MASK 0x00FF /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2TX_SLOT_LEN_SHIFT 0 /* AIF2TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2TX_SLOT_LEN_WIDTH 8 /* AIF2TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1352 (0x548) - Audio IF 2_9
+ */
+#define WM5100_AIF2RX_WL_MASK 0x3F00 /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_WL_SHIFT 8 /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_WL_WIDTH 6 /* AIF2RX_WL - [13:8] */
+#define WM5100_AIF2RX_SLOT_LEN_MASK 0x00FF /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2RX_SLOT_LEN_SHIFT 0 /* AIF2RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF2RX_SLOT_LEN_WIDTH 8 /* AIF2RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1353 (0x549) - Audio IF 2_10
+ */
+#define WM5100_AIF2TX1_SLOT_MASK 0x003F /* AIF2TX1_SLOT - [5:0] */
+#define WM5100_AIF2TX1_SLOT_SHIFT 0 /* AIF2TX1_SLOT - [5:0] */
+#define WM5100_AIF2TX1_SLOT_WIDTH 6 /* AIF2TX1_SLOT - [5:0] */
+
+/*
+ * R1354 (0x54A) - Audio IF 2_11
+ */
+#define WM5100_AIF2TX2_SLOT_MASK 0x003F /* AIF2TX2_SLOT - [5:0] */
+#define WM5100_AIF2TX2_SLOT_SHIFT 0 /* AIF2TX2_SLOT - [5:0] */
+#define WM5100_AIF2TX2_SLOT_WIDTH 6 /* AIF2TX2_SLOT - [5:0] */
+
+/*
+ * R1361 (0x551) - Audio IF 2_18
+ */
+#define WM5100_AIF2RX1_SLOT_MASK 0x003F /* AIF2RX1_SLOT - [5:0] */
+#define WM5100_AIF2RX1_SLOT_SHIFT 0 /* AIF2RX1_SLOT - [5:0] */
+#define WM5100_AIF2RX1_SLOT_WIDTH 6 /* AIF2RX1_SLOT - [5:0] */
+
+/*
+ * R1362 (0x552) - Audio IF 2_19
+ */
+#define WM5100_AIF2RX2_SLOT_MASK 0x003F /* AIF2RX2_SLOT - [5:0] */
+#define WM5100_AIF2RX2_SLOT_SHIFT 0 /* AIF2RX2_SLOT - [5:0] */
+#define WM5100_AIF2RX2_SLOT_WIDTH 6 /* AIF2RX2_SLOT - [5:0] */
+
+/*
+ * R1369 (0x559) - Audio IF 2_26
+ */
+#define WM5100_AIF2TX2_ENA 0x0002 /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_MASK 0x0002 /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_SHIFT 1 /* AIF2TX2_ENA */
+#define WM5100_AIF2TX2_ENA_WIDTH 1 /* AIF2TX2_ENA */
+#define WM5100_AIF2TX1_ENA 0x0001 /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_MASK 0x0001 /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_SHIFT 0 /* AIF2TX1_ENA */
+#define WM5100_AIF2TX1_ENA_WIDTH 1 /* AIF2TX1_ENA */
+
+/*
+ * R1370 (0x55A) - Audio IF 2_27
+ */
+#define WM5100_AIF2RX2_ENA 0x0002 /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_MASK 0x0002 /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_SHIFT 1 /* AIF2RX2_ENA */
+#define WM5100_AIF2RX2_ENA_WIDTH 1 /* AIF2RX2_ENA */
+#define WM5100_AIF2RX1_ENA 0x0001 /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_MASK 0x0001 /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_SHIFT 0 /* AIF2RX1_ENA */
+#define WM5100_AIF2RX1_ENA_WIDTH 1 /* AIF2RX1_ENA */
+
+/*
+ * R1408 (0x580) - Audio IF 3_1
+ */
+#define WM5100_AIF3_BCLK_INV 0x0080 /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_MASK 0x0080 /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_SHIFT 7 /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_INV_WIDTH 1 /* AIF3_BCLK_INV */
+#define WM5100_AIF3_BCLK_FRC 0x0040 /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_MASK 0x0040 /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_SHIFT 6 /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_FRC_WIDTH 1 /* AIF3_BCLK_FRC */
+#define WM5100_AIF3_BCLK_MSTR 0x0020 /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_MASK 0x0020 /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_SHIFT 5 /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_MSTR_WIDTH 1 /* AIF3_BCLK_MSTR */
+#define WM5100_AIF3_BCLK_FREQ_MASK 0x001F /* AIF3_BCLK_FREQ - [4:0] */
+#define WM5100_AIF3_BCLK_FREQ_SHIFT 0 /* AIF3_BCLK_FREQ - [4:0] */
+#define WM5100_AIF3_BCLK_FREQ_WIDTH 5 /* AIF3_BCLK_FREQ - [4:0] */
+
+/*
+ * R1409 (0x581) - Audio IF 3_2
+ */
+#define WM5100_AIF3TX_DAT_TRI 0x0020 /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_MASK 0x0020 /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_SHIFT 5 /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_DAT_TRI_WIDTH 1 /* AIF3TX_DAT_TRI */
+#define WM5100_AIF3TX_LRCLK_SRC 0x0008 /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_MASK 0x0008 /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_SHIFT 3 /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_SRC_WIDTH 1 /* AIF3TX_LRCLK_SRC */
+#define WM5100_AIF3TX_LRCLK_INV 0x0004 /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_MASK 0x0004 /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_SHIFT 2 /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_INV_WIDTH 1 /* AIF3TX_LRCLK_INV */
+#define WM5100_AIF3TX_LRCLK_FRC 0x0002 /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_MASK 0x0002 /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_SHIFT 1 /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_FRC_WIDTH 1 /* AIF3TX_LRCLK_FRC */
+#define WM5100_AIF3TX_LRCLK_MSTR 0x0001 /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_MASK 0x0001 /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_SHIFT 0 /* AIF3TX_LRCLK_MSTR */
+#define WM5100_AIF3TX_LRCLK_MSTR_WIDTH 1 /* AIF3TX_LRCLK_MSTR */
+
+/*
+ * R1410 (0x582) - Audio IF 3_3
+ */
+#define WM5100_AIF3RX_LRCLK_INV 0x0004 /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_MASK 0x0004 /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_SHIFT 2 /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_INV_WIDTH 1 /* AIF3RX_LRCLK_INV */
+#define WM5100_AIF3RX_LRCLK_FRC 0x0002 /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_MASK 0x0002 /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_SHIFT 1 /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_FRC_WIDTH 1 /* AIF3RX_LRCLK_FRC */
+#define WM5100_AIF3RX_LRCLK_MSTR 0x0001 /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_MASK 0x0001 /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_SHIFT 0 /* AIF3RX_LRCLK_MSTR */
+#define WM5100_AIF3RX_LRCLK_MSTR_WIDTH 1 /* AIF3RX_LRCLK_MSTR */
+
+/*
+ * R1411 (0x583) - Audio IF 3_4
+ */
+#define WM5100_AIF3_TRI 0x0040 /* AIF3_TRI */
+#define WM5100_AIF3_TRI_MASK 0x0040 /* AIF3_TRI */
+#define WM5100_AIF3_TRI_SHIFT 6 /* AIF3_TRI */
+#define WM5100_AIF3_TRI_WIDTH 1 /* AIF3_TRI */
+#define WM5100_AIF3_RATE_MASK 0x0003 /* AIF3_RATE - [1:0] */
+#define WM5100_AIF3_RATE_SHIFT 0 /* AIF3_RATE - [1:0] */
+#define WM5100_AIF3_RATE_WIDTH 2 /* AIF3_RATE - [1:0] */
+
+/*
+ * R1412 (0x584) - Audio IF 3_5
+ */
+#define WM5100_AIF3_FMT_MASK 0x0007 /* AIF3_FMT - [2:0] */
+#define WM5100_AIF3_FMT_SHIFT 0 /* AIF3_FMT - [2:0] */
+#define WM5100_AIF3_FMT_WIDTH 3 /* AIF3_FMT - [2:0] */
+
+/*
+ * R1413 (0x585) - Audio IF 3_6
+ */
+#define WM5100_AIF3TX_BCPF_MASK 0x1FFF /* AIF3TX_BCPF - [12:0] */
+#define WM5100_AIF3TX_BCPF_SHIFT 0 /* AIF3TX_BCPF - [12:0] */
+#define WM5100_AIF3TX_BCPF_WIDTH 13 /* AIF3TX_BCPF - [12:0] */
+
+/*
+ * R1414 (0x586) - Audio IF 3_7
+ */
+#define WM5100_AIF3RX_BCPF_MASK 0x1FFF /* AIF3RX_BCPF - [12:0] */
+#define WM5100_AIF3RX_BCPF_SHIFT 0 /* AIF3RX_BCPF - [12:0] */
+#define WM5100_AIF3RX_BCPF_WIDTH 13 /* AIF3RX_BCPF - [12:0] */
+
+/*
+ * R1415 (0x587) - Audio IF 3_8
+ */
+#define WM5100_AIF3TX_WL_MASK 0x3F00 /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_WL_SHIFT 8 /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_WL_WIDTH 6 /* AIF3TX_WL - [13:8] */
+#define WM5100_AIF3TX_SLOT_LEN_MASK 0x00FF /* AIF3TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3TX_SLOT_LEN_SHIFT 0 /* AIF3TX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3TX_SLOT_LEN_WIDTH 8 /* AIF3TX_SLOT_LEN - [7:0] */
+
+/*
+ * R1416 (0x588) - Audio IF 3_9
+ */
+#define WM5100_AIF3RX_WL_MASK 0x3F00 /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_WL_SHIFT 8 /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_WL_WIDTH 6 /* AIF3RX_WL - [13:8] */
+#define WM5100_AIF3RX_SLOT_LEN_MASK 0x00FF /* AIF3RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3RX_SLOT_LEN_SHIFT 0 /* AIF3RX_SLOT_LEN - [7:0] */
+#define WM5100_AIF3RX_SLOT_LEN_WIDTH 8 /* AIF3RX_SLOT_LEN - [7:0] */
+
+/*
+ * R1417 (0x589) - Audio IF 3_10
+ */
+#define WM5100_AIF3TX1_SLOT_MASK 0x003F /* AIF3TX1_SLOT - [5:0] */
+#define WM5100_AIF3TX1_SLOT_SHIFT 0 /* AIF3TX1_SLOT - [5:0] */
+#define WM5100_AIF3TX1_SLOT_WIDTH 6 /* AIF3TX1_SLOT - [5:0] */
+
+/*
+ * R1418 (0x58A) - Audio IF 3_11
+ */
+#define WM5100_AIF3TX2_SLOT_MASK 0x003F /* AIF3TX2_SLOT - [5:0] */
+#define WM5100_AIF3TX2_SLOT_SHIFT 0 /* AIF3TX2_SLOT - [5:0] */
+#define WM5100_AIF3TX2_SLOT_WIDTH 6 /* AIF3TX2_SLOT - [5:0] */
+
+/*
+ * R1425 (0x591) - Audio IF 3_18
+ */
+#define WM5100_AIF3RX1_SLOT_MASK 0x003F /* AIF3RX1_SLOT - [5:0] */
+#define WM5100_AIF3RX1_SLOT_SHIFT 0 /* AIF3RX1_SLOT - [5:0] */
+#define WM5100_AIF3RX1_SLOT_WIDTH 6 /* AIF3RX1_SLOT - [5:0] */
+
+/*
+ * R1426 (0x592) - Audio IF 3_19
+ */
+#define WM5100_AIF3RX2_SLOT_MASK 0x003F /* AIF3RX2_SLOT - [5:0] */
+#define WM5100_AIF3RX2_SLOT_SHIFT 0 /* AIF3RX2_SLOT - [5:0] */
+#define WM5100_AIF3RX2_SLOT_WIDTH 6 /* AIF3RX2_SLOT - [5:0] */
+
+/*
+ * R1433 (0x599) - Audio IF 3_26
+ */
+#define WM5100_AIF3TX2_ENA 0x0002 /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_MASK 0x0002 /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_SHIFT 1 /* AIF3TX2_ENA */
+#define WM5100_AIF3TX2_ENA_WIDTH 1 /* AIF3TX2_ENA */
+#define WM5100_AIF3TX1_ENA 0x0001 /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_MASK 0x0001 /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_SHIFT 0 /* AIF3TX1_ENA */
+#define WM5100_AIF3TX1_ENA_WIDTH 1 /* AIF3TX1_ENA */
+
+/*
+ * R1434 (0x59A) - Audio IF 3_27
+ */
+#define WM5100_AIF3RX2_ENA 0x0002 /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_MASK 0x0002 /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_SHIFT 1 /* AIF3RX2_ENA */
+#define WM5100_AIF3RX2_ENA_WIDTH 1 /* AIF3RX2_ENA */
+#define WM5100_AIF3RX1_ENA 0x0001 /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_MASK 0x0001 /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_SHIFT 0 /* AIF3RX1_ENA */
+#define WM5100_AIF3RX1_ENA_WIDTH 1 /* AIF3RX1_ENA */
+
+#define WM5100_MIXER_VOL_MASK 0x00FE /* MIXER_VOL - [7:1] */
+#define WM5100_MIXER_VOL_SHIFT 1 /* MIXER_VOL - [7:1] */
+#define WM5100_MIXER_VOL_WIDTH 7 /* MIXER_VOL - [7:1] */
+
+/*
+ * R3072 (0xC00) - GPIO CTRL 1
+ */
+#define WM5100_GP1_DIR 0x8000 /* GP1_DIR */
+#define WM5100_GP1_DIR_MASK 0x8000 /* GP1_DIR */
+#define WM5100_GP1_DIR_SHIFT 15 /* GP1_DIR */
+#define WM5100_GP1_DIR_WIDTH 1 /* GP1_DIR */
+#define WM5100_GP1_PU 0x4000 /* GP1_PU */
+#define WM5100_GP1_PU_MASK 0x4000 /* GP1_PU */
+#define WM5100_GP1_PU_SHIFT 14 /* GP1_PU */
+#define WM5100_GP1_PU_WIDTH 1 /* GP1_PU */
+#define WM5100_GP1_PD 0x2000 /* GP1_PD */
+#define WM5100_GP1_PD_MASK 0x2000 /* GP1_PD */
+#define WM5100_GP1_PD_SHIFT 13 /* GP1_PD */
+#define WM5100_GP1_PD_WIDTH 1 /* GP1_PD */
+#define WM5100_GP1_POL 0x0400 /* GP1_POL */
+#define WM5100_GP1_POL_MASK 0x0400 /* GP1_POL */
+#define WM5100_GP1_POL_SHIFT 10 /* GP1_POL */
+#define WM5100_GP1_POL_WIDTH 1 /* GP1_POL */
+#define WM5100_GP1_OP_CFG 0x0200 /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_MASK 0x0200 /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_SHIFT 9 /* GP1_OP_CFG */
+#define WM5100_GP1_OP_CFG_WIDTH 1 /* GP1_OP_CFG */
+#define WM5100_GP1_DB 0x0100 /* GP1_DB */
+#define WM5100_GP1_DB_MASK 0x0100 /* GP1_DB */
+#define WM5100_GP1_DB_SHIFT 8 /* GP1_DB */
+#define WM5100_GP1_DB_WIDTH 1 /* GP1_DB */
+#define WM5100_GP1_LVL 0x0040 /* GP1_LVL */
+#define WM5100_GP1_LVL_MASK 0x0040 /* GP1_LVL */
+#define WM5100_GP1_LVL_SHIFT 6 /* GP1_LVL */
+#define WM5100_GP1_LVL_WIDTH 1 /* GP1_LVL */
+#define WM5100_GP1_FN_MASK 0x003F /* GP1_FN - [5:0] */
+#define WM5100_GP1_FN_SHIFT 0 /* GP1_FN - [5:0] */
+#define WM5100_GP1_FN_WIDTH 6 /* GP1_FN - [5:0] */
+
+/*
+ * R3073 (0xC01) - GPIO CTRL 2
+ */
+#define WM5100_GP2_DIR 0x8000 /* GP2_DIR */
+#define WM5100_GP2_DIR_MASK 0x8000 /* GP2_DIR */
+#define WM5100_GP2_DIR_SHIFT 15 /* GP2_DIR */
+#define WM5100_GP2_DIR_WIDTH 1 /* GP2_DIR */
+#define WM5100_GP2_PU 0x4000 /* GP2_PU */
+#define WM5100_GP2_PU_MASK 0x4000 /* GP2_PU */
+#define WM5100_GP2_PU_SHIFT 14 /* GP2_PU */
+#define WM5100_GP2_PU_WIDTH 1 /* GP2_PU */
+#define WM5100_GP2_PD 0x2000 /* GP2_PD */
+#define WM5100_GP2_PD_MASK 0x2000 /* GP2_PD */
+#define WM5100_GP2_PD_SHIFT 13 /* GP2_PD */
+#define WM5100_GP2_PD_WIDTH 1 /* GP2_PD */
+#define WM5100_GP2_POL 0x0400 /* GP2_POL */
+#define WM5100_GP2_POL_MASK 0x0400 /* GP2_POL */
+#define WM5100_GP2_POL_SHIFT 10 /* GP2_POL */
+#define WM5100_GP2_POL_WIDTH 1 /* GP2_POL */
+#define WM5100_GP2_OP_CFG 0x0200 /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_MASK 0x0200 /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_SHIFT 9 /* GP2_OP_CFG */
+#define WM5100_GP2_OP_CFG_WIDTH 1 /* GP2_OP_CFG */
+#define WM5100_GP2_DB 0x0100 /* GP2_DB */
+#define WM5100_GP2_DB_MASK 0x0100 /* GP2_DB */
+#define WM5100_GP2_DB_SHIFT 8 /* GP2_DB */
+#define WM5100_GP2_DB_WIDTH 1 /* GP2_DB */
+#define WM5100_GP2_LVL 0x0040 /* GP2_LVL */
+#define WM5100_GP2_LVL_MASK 0x0040 /* GP2_LVL */
+#define WM5100_GP2_LVL_SHIFT 6 /* GP2_LVL */
+#define WM5100_GP2_LVL_WIDTH 1 /* GP2_LVL */
+#define WM5100_GP2_FN_MASK 0x003F /* GP2_FN - [5:0] */
+#define WM5100_GP2_FN_SHIFT 0 /* GP2_FN - [5:0] */
+#define WM5100_GP2_FN_WIDTH 6 /* GP2_FN - [5:0] */
+
+/*
+ * R3074 (0xC02) - GPIO CTRL 3
+ */
+#define WM5100_GP3_DIR 0x8000 /* GP3_DIR */
+#define WM5100_GP3_DIR_MASK 0x8000 /* GP3_DIR */
+#define WM5100_GP3_DIR_SHIFT 15 /* GP3_DIR */
+#define WM5100_GP3_DIR_WIDTH 1 /* GP3_DIR */
+#define WM5100_GP3_PU 0x4000 /* GP3_PU */
+#define WM5100_GP3_PU_MASK 0x4000 /* GP3_PU */
+#define WM5100_GP3_PU_SHIFT 14 /* GP3_PU */
+#define WM5100_GP3_PU_WIDTH 1 /* GP3_PU */
+#define WM5100_GP3_PD 0x2000 /* GP3_PD */
+#define WM5100_GP3_PD_MASK 0x2000 /* GP3_PD */
+#define WM5100_GP3_PD_SHIFT 13 /* GP3_PD */
+#define WM5100_GP3_PD_WIDTH 1 /* GP3_PD */
+#define WM5100_GP3_POL 0x0400 /* GP3_POL */
+#define WM5100_GP3_POL_MASK 0x0400 /* GP3_POL */
+#define WM5100_GP3_POL_SHIFT 10 /* GP3_POL */
+#define WM5100_GP3_POL_WIDTH 1 /* GP3_POL */
+#define WM5100_GP3_OP_CFG 0x0200 /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_MASK 0x0200 /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_SHIFT 9 /* GP3_OP_CFG */
+#define WM5100_GP3_OP_CFG_WIDTH 1 /* GP3_OP_CFG */
+#define WM5100_GP3_DB 0x0100 /* GP3_DB */
+#define WM5100_GP3_DB_MASK 0x0100 /* GP3_DB */
+#define WM5100_GP3_DB_SHIFT 8 /* GP3_DB */
+#define WM5100_GP3_DB_WIDTH 1 /* GP3_DB */
+#define WM5100_GP3_LVL 0x0040 /* GP3_LVL */
+#define WM5100_GP3_LVL_MASK 0x0040 /* GP3_LVL */
+#define WM5100_GP3_LVL_SHIFT 6 /* GP3_LVL */
+#define WM5100_GP3_LVL_WIDTH 1 /* GP3_LVL */
+#define WM5100_GP3_FN_MASK 0x003F /* GP3_FN - [5:0] */
+#define WM5100_GP3_FN_SHIFT 0 /* GP3_FN - [5:0] */
+#define WM5100_GP3_FN_WIDTH 6 /* GP3_FN - [5:0] */
+
+/*
+ * R3075 (0xC03) - GPIO CTRL 4
+ */
+#define WM5100_GP4_DIR 0x8000 /* GP4_DIR */
+#define WM5100_GP4_DIR_MASK 0x8000 /* GP4_DIR */
+#define WM5100_GP4_DIR_SHIFT 15 /* GP4_DIR */
+#define WM5100_GP4_DIR_WIDTH 1 /* GP4_DIR */
+#define WM5100_GP4_PU 0x4000 /* GP4_PU */
+#define WM5100_GP4_PU_MASK 0x4000 /* GP4_PU */
+#define WM5100_GP4_PU_SHIFT 14 /* GP4_PU */
+#define WM5100_GP4_PU_WIDTH 1 /* GP4_PU */
+#define WM5100_GP4_PD 0x2000 /* GP4_PD */
+#define WM5100_GP4_PD_MASK 0x2000 /* GP4_PD */
+#define WM5100_GP4_PD_SHIFT 13 /* GP4_PD */
+#define WM5100_GP4_PD_WIDTH 1 /* GP4_PD */
+#define WM5100_GP4_POL 0x0400 /* GP4_POL */
+#define WM5100_GP4_POL_MASK 0x0400 /* GP4_POL */
+#define WM5100_GP4_POL_SHIFT 10 /* GP4_POL */
+#define WM5100_GP4_POL_WIDTH 1 /* GP4_POL */
+#define WM5100_GP4_OP_CFG 0x0200 /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_MASK 0x0200 /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_SHIFT 9 /* GP4_OP_CFG */
+#define WM5100_GP4_OP_CFG_WIDTH 1 /* GP4_OP_CFG */
+#define WM5100_GP4_DB 0x0100 /* GP4_DB */
+#define WM5100_GP4_DB_MASK 0x0100 /* GP4_DB */
+#define WM5100_GP4_DB_SHIFT 8 /* GP4_DB */
+#define WM5100_GP4_DB_WIDTH 1 /* GP4_DB */
+#define WM5100_GP4_LVL 0x0040 /* GP4_LVL */
+#define WM5100_GP4_LVL_MASK 0x0040 /* GP4_LVL */
+#define WM5100_GP4_LVL_SHIFT 6 /* GP4_LVL */
+#define WM5100_GP4_LVL_WIDTH 1 /* GP4_LVL */
+#define WM5100_GP4_FN_MASK 0x003F /* GP4_FN - [5:0] */
+#define WM5100_GP4_FN_SHIFT 0 /* GP4_FN - [5:0] */
+#define WM5100_GP4_FN_WIDTH 6 /* GP4_FN - [5:0] */
+
+/*
+ * R3076 (0xC04) - GPIO CTRL 5
+ */
+#define WM5100_GP5_DIR 0x8000 /* GP5_DIR */
+#define WM5100_GP5_DIR_MASK 0x8000 /* GP5_DIR */
+#define WM5100_GP5_DIR_SHIFT 15 /* GP5_DIR */
+#define WM5100_GP5_DIR_WIDTH 1 /* GP5_DIR */
+#define WM5100_GP5_PU 0x4000 /* GP5_PU */
+#define WM5100_GP5_PU_MASK 0x4000 /* GP5_PU */
+#define WM5100_GP5_PU_SHIFT 14 /* GP5_PU */
+#define WM5100_GP5_PU_WIDTH 1 /* GP5_PU */
+#define WM5100_GP5_PD 0x2000 /* GP5_PD */
+#define WM5100_GP5_PD_MASK 0x2000 /* GP5_PD */
+#define WM5100_GP5_PD_SHIFT 13 /* GP5_PD */
+#define WM5100_GP5_PD_WIDTH 1 /* GP5_PD */
+#define WM5100_GP5_POL 0x0400 /* GP5_POL */
+#define WM5100_GP5_POL_MASK 0x0400 /* GP5_POL */
+#define WM5100_GP5_POL_SHIFT 10 /* GP5_POL */
+#define WM5100_GP5_POL_WIDTH 1 /* GP5_POL */
+#define WM5100_GP5_OP_CFG 0x0200 /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_MASK 0x0200 /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_SHIFT 9 /* GP5_OP_CFG */
+#define WM5100_GP5_OP_CFG_WIDTH 1 /* GP5_OP_CFG */
+#define WM5100_GP5_DB 0x0100 /* GP5_DB */
+#define WM5100_GP5_DB_MASK 0x0100 /* GP5_DB */
+#define WM5100_GP5_DB_SHIFT 8 /* GP5_DB */
+#define WM5100_GP5_DB_WIDTH 1 /* GP5_DB */
+#define WM5100_GP5_LVL 0x0040 /* GP5_LVL */
+#define WM5100_GP5_LVL_MASK 0x0040 /* GP5_LVL */
+#define WM5100_GP5_LVL_SHIFT 6 /* GP5_LVL */
+#define WM5100_GP5_LVL_WIDTH 1 /* GP5_LVL */
+#define WM5100_GP5_FN_MASK 0x003F /* GP5_FN - [5:0] */
+#define WM5100_GP5_FN_SHIFT 0 /* GP5_FN - [5:0] */
+#define WM5100_GP5_FN_WIDTH 6 /* GP5_FN - [5:0] */
+
+/*
+ * R3077 (0xC05) - GPIO CTRL 6
+ */
+#define WM5100_GP6_DIR 0x8000 /* GP6_DIR */
+#define WM5100_GP6_DIR_MASK 0x8000 /* GP6_DIR */
+#define WM5100_GP6_DIR_SHIFT 15 /* GP6_DIR */
+#define WM5100_GP6_DIR_WIDTH 1 /* GP6_DIR */
+#define WM5100_GP6_PU 0x4000 /* GP6_PU */
+#define WM5100_GP6_PU_MASK 0x4000 /* GP6_PU */
+#define WM5100_GP6_PU_SHIFT 14 /* GP6_PU */
+#define WM5100_GP6_PU_WIDTH 1 /* GP6_PU */
+#define WM5100_GP6_PD 0x2000 /* GP6_PD */
+#define WM5100_GP6_PD_MASK 0x2000 /* GP6_PD */
+#define WM5100_GP6_PD_SHIFT 13 /* GP6_PD */
+#define WM5100_GP6_PD_WIDTH 1 /* GP6_PD */
+#define WM5100_GP6_POL 0x0400 /* GP6_POL */
+#define WM5100_GP6_POL_MASK 0x0400 /* GP6_POL */
+#define WM5100_GP6_POL_SHIFT 10 /* GP6_POL */
+#define WM5100_GP6_POL_WIDTH 1 /* GP6_POL */
+#define WM5100_GP6_OP_CFG 0x0200 /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_MASK 0x0200 /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_SHIFT 9 /* GP6_OP_CFG */
+#define WM5100_GP6_OP_CFG_WIDTH 1 /* GP6_OP_CFG */
+#define WM5100_GP6_DB 0x0100 /* GP6_DB */
+#define WM5100_GP6_DB_MASK 0x0100 /* GP6_DB */
+#define WM5100_GP6_DB_SHIFT 8 /* GP6_DB */
+#define WM5100_GP6_DB_WIDTH 1 /* GP6_DB */
+#define WM5100_GP6_LVL 0x0040 /* GP6_LVL */
+#define WM5100_GP6_LVL_MASK 0x0040 /* GP6_LVL */
+#define WM5100_GP6_LVL_SHIFT 6 /* GP6_LVL */
+#define WM5100_GP6_LVL_WIDTH 1 /* GP6_LVL */
+#define WM5100_GP6_FN_MASK 0x003F /* GP6_FN - [5:0] */
+#define WM5100_GP6_FN_SHIFT 0 /* GP6_FN - [5:0] */
+#define WM5100_GP6_FN_WIDTH 6 /* GP6_FN - [5:0] */
+
+/*
+ * R3107 (0xC23) - Misc Pad Ctrl 1
+ */
+#define WM5100_LDO1ENA_PD 0x8000 /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_MASK 0x8000 /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_SHIFT 15 /* LDO1ENA_PD */
+#define WM5100_LDO1ENA_PD_WIDTH 1 /* LDO1ENA_PD */
+#define WM5100_MCLK2_PD 0x2000 /* MCLK2_PD */
+#define WM5100_MCLK2_PD_MASK 0x2000 /* MCLK2_PD */
+#define WM5100_MCLK2_PD_SHIFT 13 /* MCLK2_PD */
+#define WM5100_MCLK2_PD_WIDTH 1 /* MCLK2_PD */
+#define WM5100_MCLK1_PD 0x1000 /* MCLK1_PD */
+#define WM5100_MCLK1_PD_MASK 0x1000 /* MCLK1_PD */
+#define WM5100_MCLK1_PD_SHIFT 12 /* MCLK1_PD */
+#define WM5100_MCLK1_PD_WIDTH 1 /* MCLK1_PD */
+#define WM5100_RESET_PU 0x0002 /* RESET_PU */
+#define WM5100_RESET_PU_MASK 0x0002 /* RESET_PU */
+#define WM5100_RESET_PU_SHIFT 1 /* RESET_PU */
+#define WM5100_RESET_PU_WIDTH 1 /* RESET_PU */
+#define WM5100_ADDR_PD 0x0001 /* ADDR_PD */
+#define WM5100_ADDR_PD_MASK 0x0001 /* ADDR_PD */
+#define WM5100_ADDR_PD_SHIFT 0 /* ADDR_PD */
+#define WM5100_ADDR_PD_WIDTH 1 /* ADDR_PD */
+
+/*
+ * R3108 (0xC24) - Misc Pad Ctrl 2
+ */
+#define WM5100_DMICDAT4_PD 0x0008 /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_MASK 0x0008 /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_SHIFT 3 /* DMICDAT4_PD */
+#define WM5100_DMICDAT4_PD_WIDTH 1 /* DMICDAT4_PD */
+#define WM5100_DMICDAT3_PD 0x0004 /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_MASK 0x0004 /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_SHIFT 2 /* DMICDAT3_PD */
+#define WM5100_DMICDAT3_PD_WIDTH 1 /* DMICDAT3_PD */
+#define WM5100_DMICDAT2_PD 0x0002 /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_MASK 0x0002 /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_SHIFT 1 /* DMICDAT2_PD */
+#define WM5100_DMICDAT2_PD_WIDTH 1 /* DMICDAT2_PD */
+#define WM5100_DMICDAT1_PD 0x0001 /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_MASK 0x0001 /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_SHIFT 0 /* DMICDAT1_PD */
+#define WM5100_DMICDAT1_PD_WIDTH 1 /* DMICDAT1_PD */
+
+/*
+ * R3109 (0xC25) - Misc Pad Ctrl 3
+ */
+#define WM5100_AIF1RXLRCLK_PU 0x0020 /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_MASK 0x0020 /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_SHIFT 5 /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PU_WIDTH 1 /* AIF1RXLRCLK_PU */
+#define WM5100_AIF1RXLRCLK_PD 0x0010 /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_MASK 0x0010 /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_SHIFT 4 /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1RXLRCLK_PD_WIDTH 1 /* AIF1RXLRCLK_PD */
+#define WM5100_AIF1BCLK_PU 0x0008 /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_MASK 0x0008 /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_SHIFT 3 /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PU_WIDTH 1 /* AIF1BCLK_PU */
+#define WM5100_AIF1BCLK_PD 0x0004 /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_MASK 0x0004 /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_SHIFT 2 /* AIF1BCLK_PD */
+#define WM5100_AIF1BCLK_PD_WIDTH 1 /* AIF1BCLK_PD */
+#define WM5100_AIF1RXDAT_PU 0x0002 /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_MASK 0x0002 /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_SHIFT 1 /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PU_WIDTH 1 /* AIF1RXDAT_PU */
+#define WM5100_AIF1RXDAT_PD 0x0001 /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_MASK 0x0001 /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_SHIFT 0 /* AIF1RXDAT_PD */
+#define WM5100_AIF1RXDAT_PD_WIDTH 1 /* AIF1RXDAT_PD */
+
+/*
+ * R3110 (0xC26) - Misc Pad Ctrl 4
+ */
+#define WM5100_AIF2RXLRCLK_PU 0x0020 /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_MASK 0x0020 /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_SHIFT 5 /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PU_WIDTH 1 /* AIF2RXLRCLK_PU */
+#define WM5100_AIF2RXLRCLK_PD 0x0010 /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_MASK 0x0010 /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_SHIFT 4 /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2RXLRCLK_PD_WIDTH 1 /* AIF2RXLRCLK_PD */
+#define WM5100_AIF2BCLK_PU 0x0008 /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_MASK 0x0008 /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_SHIFT 3 /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PU_WIDTH 1 /* AIF2BCLK_PU */
+#define WM5100_AIF2BCLK_PD 0x0004 /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_MASK 0x0004 /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_SHIFT 2 /* AIF2BCLK_PD */
+#define WM5100_AIF2BCLK_PD_WIDTH 1 /* AIF2BCLK_PD */
+#define WM5100_AIF2RXDAT_PU 0x0002 /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_MASK 0x0002 /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_SHIFT 1 /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PU_WIDTH 1 /* AIF2RXDAT_PU */
+#define WM5100_AIF2RXDAT_PD 0x0001 /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_MASK 0x0001 /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_SHIFT 0 /* AIF2RXDAT_PD */
+#define WM5100_AIF2RXDAT_PD_WIDTH 1 /* AIF2RXDAT_PD */
+
+/*
+ * R3111 (0xC27) - Misc Pad Ctrl 5
+ */
+#define WM5100_AIF3RXLRCLK_PU 0x0020 /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_MASK 0x0020 /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_SHIFT 5 /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PU_WIDTH 1 /* AIF3RXLRCLK_PU */
+#define WM5100_AIF3RXLRCLK_PD 0x0010 /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_MASK 0x0010 /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_SHIFT 4 /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3RXLRCLK_PD_WIDTH 1 /* AIF3RXLRCLK_PD */
+#define WM5100_AIF3BCLK_PU 0x0008 /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_MASK 0x0008 /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_SHIFT 3 /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PU_WIDTH 1 /* AIF3BCLK_PU */
+#define WM5100_AIF3BCLK_PD 0x0004 /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_MASK 0x0004 /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_SHIFT 2 /* AIF3BCLK_PD */
+#define WM5100_AIF3BCLK_PD_WIDTH 1 /* AIF3BCLK_PD */
+#define WM5100_AIF3RXDAT_PU 0x0002 /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_MASK 0x0002 /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_SHIFT 1 /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PU_WIDTH 1 /* AIF3RXDAT_PU */
+#define WM5100_AIF3RXDAT_PD 0x0001 /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_MASK 0x0001 /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_SHIFT 0 /* AIF3RXDAT_PD */
+#define WM5100_AIF3RXDAT_PD_WIDTH 1 /* AIF3RXDAT_PD */
+
+/*
+ * R3112 (0xC28) - Misc GPIO 1
+ */
+#define WM5100_OPCLK_SEL_MASK 0x0003 /* OPCLK_SEL - [1:0] */
+#define WM5100_OPCLK_SEL_SHIFT 0 /* OPCLK_SEL - [1:0] */
+#define WM5100_OPCLK_SEL_WIDTH 2 /* OPCLK_SEL - [1:0] */
+
+/*
+ * R3328 (0xD00) - Interrupt Status 1
+ */
+#define WM5100_GP6_EINT 0x0020 /* GP6_EINT */
+#define WM5100_GP6_EINT_MASK 0x0020 /* GP6_EINT */
+#define WM5100_GP6_EINT_SHIFT 5 /* GP6_EINT */
+#define WM5100_GP6_EINT_WIDTH 1 /* GP6_EINT */
+#define WM5100_GP5_EINT 0x0010 /* GP5_EINT */
+#define WM5100_GP5_EINT_MASK 0x0010 /* GP5_EINT */
+#define WM5100_GP5_EINT_SHIFT 4 /* GP5_EINT */
+#define WM5100_GP5_EINT_WIDTH 1 /* GP5_EINT */
+#define WM5100_GP4_EINT 0x0008 /* GP4_EINT */
+#define WM5100_GP4_EINT_MASK 0x0008 /* GP4_EINT */
+#define WM5100_GP4_EINT_SHIFT 3 /* GP4_EINT */
+#define WM5100_GP4_EINT_WIDTH 1 /* GP4_EINT */
+#define WM5100_GP3_EINT 0x0004 /* GP3_EINT */
+#define WM5100_GP3_EINT_MASK 0x0004 /* GP3_EINT */
+#define WM5100_GP3_EINT_SHIFT 2 /* GP3_EINT */
+#define WM5100_GP3_EINT_WIDTH 1 /* GP3_EINT */
+#define WM5100_GP2_EINT 0x0002 /* GP2_EINT */
+#define WM5100_GP2_EINT_MASK 0x0002 /* GP2_EINT */
+#define WM5100_GP2_EINT_SHIFT 1 /* GP2_EINT */
+#define WM5100_GP2_EINT_WIDTH 1 /* GP2_EINT */
+#define WM5100_GP1_EINT 0x0001 /* GP1_EINT */
+#define WM5100_GP1_EINT_MASK 0x0001 /* GP1_EINT */
+#define WM5100_GP1_EINT_SHIFT 0 /* GP1_EINT */
+#define WM5100_GP1_EINT_WIDTH 1 /* GP1_EINT */
+
+/*
+ * R3329 (0xD01) - Interrupt Status 2
+ */
+#define WM5100_DSP_IRQ6_EINT 0x0020 /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_MASK 0x0020 /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_SHIFT 5 /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ6_EINT_WIDTH 1 /* DSP_IRQ6_EINT */
+#define WM5100_DSP_IRQ5_EINT 0x0010 /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_MASK 0x0010 /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_SHIFT 4 /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ5_EINT_WIDTH 1 /* DSP_IRQ5_EINT */
+#define WM5100_DSP_IRQ4_EINT 0x0008 /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_MASK 0x0008 /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_SHIFT 3 /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ4_EINT_WIDTH 1 /* DSP_IRQ4_EINT */
+#define WM5100_DSP_IRQ3_EINT 0x0004 /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_MASK 0x0004 /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_SHIFT 2 /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ3_EINT_WIDTH 1 /* DSP_IRQ3_EINT */
+#define WM5100_DSP_IRQ2_EINT 0x0002 /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_MASK 0x0002 /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_SHIFT 1 /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ2_EINT_WIDTH 1 /* DSP_IRQ2_EINT */
+#define WM5100_DSP_IRQ1_EINT 0x0001 /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_MASK 0x0001 /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_SHIFT 0 /* DSP_IRQ1_EINT */
+#define WM5100_DSP_IRQ1_EINT_WIDTH 1 /* DSP_IRQ1_EINT */
+
+/*
+ * R3330 (0xD02) - Interrupt Status 3
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT 0x8000 /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_MASK 0x8000 /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_SHIFT 15 /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_WARN_EINT_WIDTH 1 /* SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT 0x4000 /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_MASK 0x4000 /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_SHIFT 14 /* SPK_SHUTDOWN_EINT */
+#define WM5100_SPK_SHUTDOWN_EINT_WIDTH 1 /* SPK_SHUTDOWN_EINT */
+#define WM5100_HPDET_EINT 0x2000 /* HPDET_EINT */
+#define WM5100_HPDET_EINT_MASK 0x2000 /* HPDET_EINT */
+#define WM5100_HPDET_EINT_SHIFT 13 /* HPDET_EINT */
+#define WM5100_HPDET_EINT_WIDTH 1 /* HPDET_EINT */
+#define WM5100_ACCDET_EINT 0x1000 /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_MASK 0x1000 /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_SHIFT 12 /* ACCDET_EINT */
+#define WM5100_ACCDET_EINT_WIDTH 1 /* ACCDET_EINT */
+#define WM5100_DRC_SIG_DET_EINT 0x0200 /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_MASK 0x0200 /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_SHIFT 9 /* DRC_SIG_DET_EINT */
+#define WM5100_DRC_SIG_DET_EINT_WIDTH 1 /* DRC_SIG_DET_EINT */
+#define WM5100_ASRC2_LOCK_EINT 0x0100 /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_MASK 0x0100 /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_SHIFT 8 /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC2_LOCK_EINT_WIDTH 1 /* ASRC2_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT 0x0080 /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_MASK 0x0080 /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_SHIFT 7 /* ASRC1_LOCK_EINT */
+#define WM5100_ASRC1_LOCK_EINT_WIDTH 1 /* ASRC1_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT 0x0008 /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_MASK 0x0008 /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_SHIFT 3 /* FLL2_LOCK_EINT */
+#define WM5100_FLL2_LOCK_EINT_WIDTH 1 /* FLL2_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT 0x0004 /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_MASK 0x0004 /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_SHIFT 2 /* FLL1_LOCK_EINT */
+#define WM5100_FLL1_LOCK_EINT_WIDTH 1 /* FLL1_LOCK_EINT */
+#define WM5100_CLKGEN_ERR_EINT 0x0002 /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_MASK 0x0002 /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_SHIFT 1 /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_EINT_WIDTH 1 /* CLKGEN_ERR_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT 0x0001 /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_MASK 0x0001 /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_SHIFT 0 /* CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_CLKGEN_ERR_ASYNC_EINT_WIDTH 1 /* CLKGEN_ERR_ASYNC_EINT */
+
+/*
+ * R3331 (0xD03) - Interrupt Status 4
+ */
+#define WM5100_AIF3_ERR_EINT 0x2000 /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_MASK 0x2000 /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_SHIFT 13 /* AIF3_ERR_EINT */
+#define WM5100_AIF3_ERR_EINT_WIDTH 1 /* AIF3_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT 0x1000 /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_MASK 0x1000 /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_SHIFT 12 /* AIF2_ERR_EINT */
+#define WM5100_AIF2_ERR_EINT_WIDTH 1 /* AIF2_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT 0x0800 /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_MASK 0x0800 /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_SHIFT 11 /* AIF1_ERR_EINT */
+#define WM5100_AIF1_ERR_EINT_WIDTH 1 /* AIF1_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT 0x0400 /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_MASK 0x0400 /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_SHIFT 10 /* CTRLIF_ERR_EINT */
+#define WM5100_CTRLIF_ERR_EINT_WIDTH 1 /* CTRLIF_ERR_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT 0x0200 /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_MASK 0x0200 /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_SHIFT 9 /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC2_UNDERCLOCKED_EINT_WIDTH 1 /* ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT 0x0100 /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_MASK 0x0100 /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_SHIFT 8 /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_ISRC1_UNDERCLOCKED_EINT_WIDTH 1 /* ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT 0x0080 /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_MASK 0x0080 /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_SHIFT 7 /* FX_UNDERCLOCKED_EINT */
+#define WM5100_FX_UNDERCLOCKED_EINT_WIDTH 1 /* FX_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT 0x0040 /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_MASK 0x0040 /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_SHIFT 6 /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF3_UNDERCLOCKED_EINT_WIDTH 1 /* AIF3_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT 0x0020 /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_MASK 0x0020 /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_SHIFT 5 /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF2_UNDERCLOCKED_EINT_WIDTH 1 /* AIF2_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT 0x0010 /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_MASK 0x0010 /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_SHIFT 4 /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_AIF1_UNDERCLOCKED_EINT_WIDTH 1 /* AIF1_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT 0x0008 /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_MASK 0x0008 /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_SHIFT 3 /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_ASRC_UNDERCLOCKED_EINT_WIDTH 1 /* ASRC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT 0x0004 /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_MASK 0x0004 /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_SHIFT 2 /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_DAC_UNDERCLOCKED_EINT_WIDTH 1 /* DAC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT 0x0002 /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_MASK 0x0002 /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_SHIFT 1 /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_ADC_UNDERCLOCKED_EINT_WIDTH 1 /* ADC_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT 0x0001 /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_MASK 0x0001 /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_SHIFT 0 /* MIXER_UNDERCLOCKED_EINT */
+#define WM5100_MIXER_UNDERCLOCKED_EINT_WIDTH 1 /* MIXER_UNDERCLOCKED_EINT */
+
+/*
+ * R3332 (0xD04) - Interrupt Raw Status 2
+ */
+#define WM5100_DSP_IRQ6_STS 0x0020 /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_MASK 0x0020 /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_SHIFT 5 /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ6_STS_WIDTH 1 /* DSP_IRQ6_STS */
+#define WM5100_DSP_IRQ5_STS 0x0010 /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_MASK 0x0010 /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_SHIFT 4 /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ5_STS_WIDTH 1 /* DSP_IRQ5_STS */
+#define WM5100_DSP_IRQ4_STS 0x0008 /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_MASK 0x0008 /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_SHIFT 3 /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ4_STS_WIDTH 1 /* DSP_IRQ4_STS */
+#define WM5100_DSP_IRQ3_STS 0x0004 /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_MASK 0x0004 /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_SHIFT 2 /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ3_STS_WIDTH 1 /* DSP_IRQ3_STS */
+#define WM5100_DSP_IRQ2_STS 0x0002 /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_MASK 0x0002 /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_SHIFT 1 /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ2_STS_WIDTH 1 /* DSP_IRQ2_STS */
+#define WM5100_DSP_IRQ1_STS 0x0001 /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_MASK 0x0001 /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_SHIFT 0 /* DSP_IRQ1_STS */
+#define WM5100_DSP_IRQ1_STS_WIDTH 1 /* DSP_IRQ1_STS */
+
+/*
+ * R3333 (0xD05) - Interrupt Raw Status 3
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_STS 0x8000 /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_MASK 0x8000 /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_SHIFT 15 /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_WARN_STS_WIDTH 1 /* SPK_SHUTDOWN_WARN_STS */
+#define WM5100_SPK_SHUTDOWN_STS 0x4000 /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_MASK 0x4000 /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_SHIFT 14 /* SPK_SHUTDOWN_STS */
+#define WM5100_SPK_SHUTDOWN_STS_WIDTH 1 /* SPK_SHUTDOWN_STS */
+#define WM5100_HPDET_STS 0x2000 /* HPDET_STS */
+#define WM5100_HPDET_STS_MASK 0x2000 /* HPDET_STS */
+#define WM5100_HPDET_STS_SHIFT 13 /* HPDET_STS */
+#define WM5100_HPDET_STS_WIDTH 1 /* HPDET_STS */
+#define WM5100_DRC_SID_DET_STS 0x0200 /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_MASK 0x0200 /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_SHIFT 9 /* DRC_SID_DET_STS */
+#define WM5100_DRC_SID_DET_STS_WIDTH 1 /* DRC_SID_DET_STS */
+#define WM5100_ASRC2_LOCK_STS 0x0100 /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_MASK 0x0100 /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_SHIFT 8 /* ASRC2_LOCK_STS */
+#define WM5100_ASRC2_LOCK_STS_WIDTH 1 /* ASRC2_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS 0x0080 /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_MASK 0x0080 /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_SHIFT 7 /* ASRC1_LOCK_STS */
+#define WM5100_ASRC1_LOCK_STS_WIDTH 1 /* ASRC1_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS 0x0008 /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_MASK 0x0008 /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_SHIFT 3 /* FLL2_LOCK_STS */
+#define WM5100_FLL2_LOCK_STS_WIDTH 1 /* FLL2_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS 0x0004 /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_MASK 0x0004 /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_SHIFT 2 /* FLL1_LOCK_STS */
+#define WM5100_FLL1_LOCK_STS_WIDTH 1 /* FLL1_LOCK_STS */
+#define WM5100_CLKGEN_ERR_STS 0x0002 /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_MASK 0x0002 /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_SHIFT 1 /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_STS_WIDTH 1 /* CLKGEN_ERR_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS 0x0001 /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_MASK 0x0001 /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_SHIFT 0 /* CLKGEN_ERR_ASYNC_STS */
+#define WM5100_CLKGEN_ERR_ASYNC_STS_WIDTH 1 /* CLKGEN_ERR_ASYNC_STS */
+
+/*
+ * R3334 (0xD06) - Interrupt Raw Status 4
+ */
+#define WM5100_AIF3_ERR_STS 0x2000 /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_MASK 0x2000 /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_SHIFT 13 /* AIF3_ERR_STS */
+#define WM5100_AIF3_ERR_STS_WIDTH 1 /* AIF3_ERR_STS */
+#define WM5100_AIF2_ERR_STS 0x1000 /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_MASK 0x1000 /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_SHIFT 12 /* AIF2_ERR_STS */
+#define WM5100_AIF2_ERR_STS_WIDTH 1 /* AIF2_ERR_STS */
+#define WM5100_AIF1_ERR_STS 0x0800 /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_MASK 0x0800 /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_SHIFT 11 /* AIF1_ERR_STS */
+#define WM5100_AIF1_ERR_STS_WIDTH 1 /* AIF1_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS 0x0400 /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_MASK 0x0400 /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_SHIFT 10 /* CTRLIF_ERR_STS */
+#define WM5100_CTRLIF_ERR_STS_WIDTH 1 /* CTRLIF_ERR_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS 0x0200 /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_MASK 0x0200 /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_SHIFT 9 /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC2_UNDERCLOCKED_STS_WIDTH 1 /* ISRC2_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS 0x0100 /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_MASK 0x0100 /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_SHIFT 8 /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_ISRC1_UNDERCLOCKED_STS_WIDTH 1 /* ISRC1_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS 0x0080 /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_MASK 0x0080 /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_SHIFT 7 /* FX_UNDERCLOCKED_STS */
+#define WM5100_FX_UNDERCLOCKED_STS_WIDTH 1 /* FX_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS 0x0040 /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_MASK 0x0040 /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_SHIFT 6 /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF3_UNDERCLOCKED_STS_WIDTH 1 /* AIF3_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS 0x0020 /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_MASK 0x0020 /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_SHIFT 5 /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF2_UNDERCLOCKED_STS_WIDTH 1 /* AIF2_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS 0x0010 /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_MASK 0x0010 /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_SHIFT 4 /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_AIF1_UNDERCLOCKED_STS_WIDTH 1 /* AIF1_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS 0x0008 /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_MASK 0x0008 /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_SHIFT 3 /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_ASRC_UNDERCLOCKED_STS_WIDTH 1 /* ASRC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS 0x0004 /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_MASK 0x0004 /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_SHIFT 2 /* DAC_UNDERCLOCKED_STS */
+#define WM5100_DAC_UNDERCLOCKED_STS_WIDTH 1 /* DAC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS 0x0002 /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_MASK 0x0002 /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_SHIFT 1 /* ADC_UNDERCLOCKED_STS */
+#define WM5100_ADC_UNDERCLOCKED_STS_WIDTH 1 /* ADC_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS 0x0001 /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_MASK 0x0001 /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_SHIFT 0 /* MIXER_UNDERCLOCKED_STS */
+#define WM5100_MIXER_UNDERCLOCKED_STS_WIDTH 1 /* MIXER_UNDERCLOCKED_STS */
+
+/*
+ * R3335 (0xD07) - Interrupt Status 1 Mask
+ */
+#define WM5100_IM_GP6_EINT 0x0020 /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_MASK 0x0020 /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_SHIFT 5 /* IM_GP6_EINT */
+#define WM5100_IM_GP6_EINT_WIDTH 1 /* IM_GP6_EINT */
+#define WM5100_IM_GP5_EINT 0x0010 /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_MASK 0x0010 /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_SHIFT 4 /* IM_GP5_EINT */
+#define WM5100_IM_GP5_EINT_WIDTH 1 /* IM_GP5_EINT */
+#define WM5100_IM_GP4_EINT 0x0008 /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_MASK 0x0008 /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_SHIFT 3 /* IM_GP4_EINT */
+#define WM5100_IM_GP4_EINT_WIDTH 1 /* IM_GP4_EINT */
+#define WM5100_IM_GP3_EINT 0x0004 /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_MASK 0x0004 /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_SHIFT 2 /* IM_GP3_EINT */
+#define WM5100_IM_GP3_EINT_WIDTH 1 /* IM_GP3_EINT */
+#define WM5100_IM_GP2_EINT 0x0002 /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_MASK 0x0002 /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_SHIFT 1 /* IM_GP2_EINT */
+#define WM5100_IM_GP2_EINT_WIDTH 1 /* IM_GP2_EINT */
+#define WM5100_IM_GP1_EINT 0x0001 /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_MASK 0x0001 /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_SHIFT 0 /* IM_GP1_EINT */
+#define WM5100_IM_GP1_EINT_WIDTH 1 /* IM_GP1_EINT */
+
+/*
+ * R3336 (0xD08) - Interrupt Status 2 Mask
+ */
+#define WM5100_IM_DSP_IRQ6_EINT 0x0020 /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_MASK 0x0020 /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_SHIFT 5 /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ6_EINT_WIDTH 1 /* IM_DSP_IRQ6_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT 0x0010 /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_MASK 0x0010 /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_SHIFT 4 /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ5_EINT_WIDTH 1 /* IM_DSP_IRQ5_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT 0x0008 /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_MASK 0x0008 /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_SHIFT 3 /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ4_EINT_WIDTH 1 /* IM_DSP_IRQ4_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT 0x0004 /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_MASK 0x0004 /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_SHIFT 2 /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ3_EINT_WIDTH 1 /* IM_DSP_IRQ3_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT 0x0002 /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_MASK 0x0002 /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_SHIFT 1 /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ2_EINT_WIDTH 1 /* IM_DSP_IRQ2_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT 0x0001 /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_MASK 0x0001 /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_SHIFT 0 /* IM_DSP_IRQ1_EINT */
+#define WM5100_IM_DSP_IRQ1_EINT_WIDTH 1 /* IM_DSP_IRQ1_EINT */
+
+/*
+ * R3337 (0xD09) - Interrupt Status 3 Mask
+ */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_MASK 0x8000 /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_SHIFT 15 /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_WARN_EINT_WIDTH 1 /* IM_SPK_SHUTDOWN_WARN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT 0x4000 /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_MASK 0x4000 /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_SHIFT 14 /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_SPK_SHUTDOWN_EINT_WIDTH 1 /* IM_SPK_SHUTDOWN_EINT */
+#define WM5100_IM_HPDET_EINT 0x2000 /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_MASK 0x2000 /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_SHIFT 13 /* IM_HPDET_EINT */
+#define WM5100_IM_HPDET_EINT_WIDTH 1 /* IM_HPDET_EINT */
+#define WM5100_IM_ACCDET_EINT 0x1000 /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_MASK 0x1000 /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_SHIFT 12 /* IM_ACCDET_EINT */
+#define WM5100_IM_ACCDET_EINT_WIDTH 1 /* IM_ACCDET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT 0x0200 /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_MASK 0x0200 /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_SHIFT 9 /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_DRC_SIG_DET_EINT_WIDTH 1 /* IM_DRC_SIG_DET_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT 0x0100 /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_MASK 0x0100 /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_SHIFT 8 /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC2_LOCK_EINT_WIDTH 1 /* IM_ASRC2_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT 0x0080 /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_MASK 0x0080 /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_SHIFT 7 /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_ASRC1_LOCK_EINT_WIDTH 1 /* IM_ASRC1_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT 0x0008 /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_MASK 0x0008 /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_SHIFT 3 /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL2_LOCK_EINT_WIDTH 1 /* IM_FLL2_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT 0x0004 /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_MASK 0x0004 /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_SHIFT 2 /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_FLL1_LOCK_EINT_WIDTH 1 /* IM_FLL1_LOCK_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT 0x0002 /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_MASK 0x0002 /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_SHIFT 1 /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_EINT_WIDTH 1 /* IM_CLKGEN_ERR_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_MASK 0x0001 /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_SHIFT 0 /* IM_CLKGEN_ERR_ASYNC_EINT */
+#define WM5100_IM_CLKGEN_ERR_ASYNC_EINT_WIDTH 1 /* IM_CLKGEN_ERR_ASYNC_EINT */
+
+/*
+ * R3338 (0xD0A) - Interrupt Status 4 Mask
+ */
+#define WM5100_IM_AIF3_ERR_EINT 0x2000 /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_MASK 0x2000 /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_SHIFT 13 /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF3_ERR_EINT_WIDTH 1 /* IM_AIF3_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT 0x1000 /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_MASK 0x1000 /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_SHIFT 12 /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF2_ERR_EINT_WIDTH 1 /* IM_AIF2_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT 0x0800 /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_MASK 0x0800 /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_SHIFT 11 /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_AIF1_ERR_EINT_WIDTH 1 /* IM_AIF1_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT 0x0400 /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_MASK 0x0400 /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_SHIFT 10 /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_CTRLIF_ERR_EINT_WIDTH 1 /* IM_CTRLIF_ERR_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT 0x0200 /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_MASK 0x0200 /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_SHIFT 9 /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC2_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ISRC2_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT 0x0100 /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_MASK 0x0100 /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_SHIFT 8 /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ISRC1_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ISRC1_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT 0x0080 /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_MASK 0x0080 /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_SHIFT 7 /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_FX_UNDERCLOCKED_EINT_WIDTH 1 /* IM_FX_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT 0x0040 /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_MASK 0x0040 /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_SHIFT 6 /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF3_UNDERCLOCKED_EINT_WIDTH 1 /* IM_AIF3_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT 0x0020 /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_MASK 0x0020 /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_SHIFT 5 /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF2_UNDERCLOCKED_EINT_WIDTH 1 /* IM_AIF2_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT 0x0010 /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_MASK 0x0010 /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_SHIFT 4 /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_AIF1_UNDERCLOCKED_EINT_WIDTH 1 /* IM_AIF1_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT 0x0008 /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_MASK 0x0008 /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_SHIFT 3 /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ASRC_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ASRC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT 0x0004 /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_MASK 0x0004 /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_SHIFT 2 /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_DAC_UNDERCLOCKED_EINT_WIDTH 1 /* IM_DAC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT 0x0002 /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_MASK 0x0002 /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_SHIFT 1 /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_ADC_UNDERCLOCKED_EINT_WIDTH 1 /* IM_ADC_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT 0x0001 /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_MASK 0x0001 /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_SHIFT 0 /* IM_MIXER_UNDERCLOCKED_EINT */
+#define WM5100_IM_MIXER_UNDERCLOCKED_EINT_WIDTH 1 /* IM_MIXER_UNDERCLOCKED_EINT */
+
+/*
+ * R3359 (0xD1F) - Interrupt Control
+ */
+#define WM5100_IM_IRQ 0x0001 /* IM_IRQ */
+#define WM5100_IM_IRQ_MASK 0x0001 /* IM_IRQ */
+#define WM5100_IM_IRQ_SHIFT 0 /* IM_IRQ */
+#define WM5100_IM_IRQ_WIDTH 1 /* IM_IRQ */
+
+/*
+ * R3360 (0xD20) - IRQ Debounce 1
+ */
+#define WM5100_SPK_SHUTDOWN_WARN_DB 0x0200 /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_MASK 0x0200 /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_SHIFT 9 /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_WARN_DB_WIDTH 1 /* SPK_SHUTDOWN_WARN_DB */
+#define WM5100_SPK_SHUTDOWN_DB 0x0100 /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_MASK 0x0100 /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_SHIFT 8 /* SPK_SHUTDOWN_DB */
+#define WM5100_SPK_SHUTDOWN_DB_WIDTH 1 /* SPK_SHUTDOWN_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB 0x0008 /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_MASK 0x0008 /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_SHIFT 3 /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL1_LOCK_IRQ_DB_WIDTH 1 /* FLL1_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB 0x0004 /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_MASK 0x0004 /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_SHIFT 2 /* FLL2_LOCK_IRQ_DB */
+#define WM5100_FLL2_LOCK_IRQ_DB_WIDTH 1 /* FLL2_LOCK_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB 0x0002 /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_MASK 0x0002 /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_SHIFT 1 /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_IRQ_DB_WIDTH 1 /* CLKGEN_ERR_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB 0x0001 /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_MASK 0x0001 /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_SHIFT 0 /* CLKGEN_ERR_ASYNC_IRQ_DB */
+#define WM5100_CLKGEN_ERR_ASYNC_IRQ_DB_WIDTH 1 /* CLKGEN_ERR_ASYNC_IRQ_DB */
+
+/*
+ * R3361 (0xD21) - IRQ Debounce 2
+ */
+#define WM5100_AIF_ERR_DB 0x0001 /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_MASK 0x0001 /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_SHIFT 0 /* AIF_ERR_DB */
+#define WM5100_AIF_ERR_DB_WIDTH 1 /* AIF_ERR_DB */
+
+/*
+ * R3584 (0xE00) - FX_Ctrl
+ */
+#define WM5100_FX_STS_MASK 0xFFC0 /* FX_STS - [15:6] */
+#define WM5100_FX_STS_SHIFT 6 /* FX_STS - [15:6] */
+#define WM5100_FX_STS_WIDTH 10 /* FX_STS - [15:6] */
+#define WM5100_FX_RATE_MASK 0x0003 /* FX_RATE - [1:0] */
+#define WM5100_FX_RATE_SHIFT 0 /* FX_RATE - [1:0] */
+#define WM5100_FX_RATE_WIDTH 2 /* FX_RATE - [1:0] */
+
+/*
+ * R3600 (0xE10) - EQ1_1
+ */
+#define WM5100_EQ1_B1_GAIN_MASK 0xF800 /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B1_GAIN_SHIFT 11 /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B1_GAIN_WIDTH 5 /* EQ1_B1_GAIN - [15:11] */
+#define WM5100_EQ1_B2_GAIN_MASK 0x07C0 /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B2_GAIN_SHIFT 6 /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B2_GAIN_WIDTH 5 /* EQ1_B2_GAIN - [10:6] */
+#define WM5100_EQ1_B3_GAIN_MASK 0x003E /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_B3_GAIN_SHIFT 1 /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_B3_GAIN_WIDTH 5 /* EQ1_B3_GAIN - [5:1] */
+#define WM5100_EQ1_ENA 0x0001 /* EQ1_ENA */
+#define WM5100_EQ1_ENA_MASK 0x0001 /* EQ1_ENA */
+#define WM5100_EQ1_ENA_SHIFT 0 /* EQ1_ENA */
+#define WM5100_EQ1_ENA_WIDTH 1 /* EQ1_ENA */
+
+/*
+ * R3601 (0xE11) - EQ1_2
+ */
+#define WM5100_EQ1_B4_GAIN_MASK 0xF800 /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B4_GAIN_SHIFT 11 /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B4_GAIN_WIDTH 5 /* EQ1_B4_GAIN - [15:11] */
+#define WM5100_EQ1_B5_GAIN_MASK 0x07C0 /* EQ1_B5_GAIN - [10:6] */
+#define WM5100_EQ1_B5_GAIN_SHIFT 6 /* EQ1_B5_GAIN - [10:6] */
+#define WM5100_EQ1_B5_GAIN_WIDTH 5 /* EQ1_B5_GAIN - [10:6] */
+
+/*
+ * R3602 (0xE12) - EQ1_3
+ */
+#define WM5100_EQ1_B1_A_MASK 0xFFFF /* EQ1_B1_A - [15:0] */
+#define WM5100_EQ1_B1_A_SHIFT 0 /* EQ1_B1_A - [15:0] */
+#define WM5100_EQ1_B1_A_WIDTH 16 /* EQ1_B1_A - [15:0] */
+
+/*
+ * R3603 (0xE13) - EQ1_4
+ */
+#define WM5100_EQ1_B1_B_MASK 0xFFFF /* EQ1_B1_B - [15:0] */
+#define WM5100_EQ1_B1_B_SHIFT 0 /* EQ1_B1_B - [15:0] */
+#define WM5100_EQ1_B1_B_WIDTH 16 /* EQ1_B1_B - [15:0] */
+
+/*
+ * R3604 (0xE14) - EQ1_5
+ */
+#define WM5100_EQ1_B1_PG_MASK 0xFFFF /* EQ1_B1_PG - [15:0] */
+#define WM5100_EQ1_B1_PG_SHIFT 0 /* EQ1_B1_PG - [15:0] */
+#define WM5100_EQ1_B1_PG_WIDTH 16 /* EQ1_B1_PG - [15:0] */
+
+/*
+ * R3605 (0xE15) - EQ1_6
+ */
+#define WM5100_EQ1_B2_A_MASK 0xFFFF /* EQ1_B2_A - [15:0] */
+#define WM5100_EQ1_B2_A_SHIFT 0 /* EQ1_B2_A - [15:0] */
+#define WM5100_EQ1_B2_A_WIDTH 16 /* EQ1_B2_A - [15:0] */
+
+/*
+ * R3606 (0xE16) - EQ1_7
+ */
+#define WM5100_EQ1_B2_B_MASK 0xFFFF /* EQ1_B2_B - [15:0] */
+#define WM5100_EQ1_B2_B_SHIFT 0 /* EQ1_B2_B - [15:0] */
+#define WM5100_EQ1_B2_B_WIDTH 16 /* EQ1_B2_B - [15:0] */
+
+/*
+ * R3607 (0xE17) - EQ1_8
+ */
+#define WM5100_EQ1_B2_C_MASK 0xFFFF /* EQ1_B2_C - [15:0] */
+#define WM5100_EQ1_B2_C_SHIFT 0 /* EQ1_B2_C - [15:0] */
+#define WM5100_EQ1_B2_C_WIDTH 16 /* EQ1_B2_C - [15:0] */
+
+/*
+ * R3608 (0xE18) - EQ1_9
+ */
+#define WM5100_EQ1_B2_PG_MASK 0xFFFF /* EQ1_B2_PG - [15:0] */
+#define WM5100_EQ1_B2_PG_SHIFT 0 /* EQ1_B2_PG - [15:0] */
+#define WM5100_EQ1_B2_PG_WIDTH 16 /* EQ1_B2_PG - [15:0] */
+
+/*
+ * R3609 (0xE19) - EQ1_10
+ */
+#define WM5100_EQ1_B3_A_MASK 0xFFFF /* EQ1_B3_A - [15:0] */
+#define WM5100_EQ1_B3_A_SHIFT 0 /* EQ1_B3_A - [15:0] */
+#define WM5100_EQ1_B3_A_WIDTH 16 /* EQ1_B3_A - [15:0] */
+
+/*
+ * R3610 (0xE1A) - EQ1_11
+ */
+#define WM5100_EQ1_B3_B_MASK 0xFFFF /* EQ1_B3_B - [15:0] */
+#define WM5100_EQ1_B3_B_SHIFT 0 /* EQ1_B3_B - [15:0] */
+#define WM5100_EQ1_B3_B_WIDTH 16 /* EQ1_B3_B - [15:0] */
+
+/*
+ * R3611 (0xE1B) - EQ1_12
+ */
+#define WM5100_EQ1_B3_C_MASK 0xFFFF /* EQ1_B3_C - [15:0] */
+#define WM5100_EQ1_B3_C_SHIFT 0 /* EQ1_B3_C - [15:0] */
+#define WM5100_EQ1_B3_C_WIDTH 16 /* EQ1_B3_C - [15:0] */
+
+/*
+ * R3612 (0xE1C) - EQ1_13
+ */
+#define WM5100_EQ1_B3_PG_MASK 0xFFFF /* EQ1_B3_PG - [15:0] */
+#define WM5100_EQ1_B3_PG_SHIFT 0 /* EQ1_B3_PG - [15:0] */
+#define WM5100_EQ1_B3_PG_WIDTH 16 /* EQ1_B3_PG - [15:0] */
+
+/*
+ * R3613 (0xE1D) - EQ1_14
+ */
+#define WM5100_EQ1_B4_A_MASK 0xFFFF /* EQ1_B4_A - [15:0] */
+#define WM5100_EQ1_B4_A_SHIFT 0 /* EQ1_B4_A - [15:0] */
+#define WM5100_EQ1_B4_A_WIDTH 16 /* EQ1_B4_A - [15:0] */
+
+/*
+ * R3614 (0xE1E) - EQ1_15
+ */
+#define WM5100_EQ1_B4_B_MASK 0xFFFF /* EQ1_B4_B - [15:0] */
+#define WM5100_EQ1_B4_B_SHIFT 0 /* EQ1_B4_B - [15:0] */
+#define WM5100_EQ1_B4_B_WIDTH 16 /* EQ1_B4_B - [15:0] */
+
+/*
+ * R3615 (0xE1F) - EQ1_16
+ */
+#define WM5100_EQ1_B4_C_MASK 0xFFFF /* EQ1_B4_C - [15:0] */
+#define WM5100_EQ1_B4_C_SHIFT 0 /* EQ1_B4_C - [15:0] */
+#define WM5100_EQ1_B4_C_WIDTH 16 /* EQ1_B4_C - [15:0] */
+
+/*
+ * R3616 (0xE20) - EQ1_17
+ */
+#define WM5100_EQ1_B4_PG_MASK 0xFFFF /* EQ1_B4_PG - [15:0] */
+#define WM5100_EQ1_B4_PG_SHIFT 0 /* EQ1_B4_PG - [15:0] */
+#define WM5100_EQ1_B4_PG_WIDTH 16 /* EQ1_B4_PG - [15:0] */
+
+/*
+ * R3617 (0xE21) - EQ1_18
+ */
+#define WM5100_EQ1_B5_A_MASK 0xFFFF /* EQ1_B5_A - [15:0] */
+#define WM5100_EQ1_B5_A_SHIFT 0 /* EQ1_B5_A - [15:0] */
+#define WM5100_EQ1_B5_A_WIDTH 16 /* EQ1_B5_A - [15:0] */
+
+/*
+ * R3618 (0xE22) - EQ1_19
+ */
+#define WM5100_EQ1_B5_B_MASK 0xFFFF /* EQ1_B5_B - [15:0] */
+#define WM5100_EQ1_B5_B_SHIFT 0 /* EQ1_B5_B - [15:0] */
+#define WM5100_EQ1_B5_B_WIDTH 16 /* EQ1_B5_B - [15:0] */
+
+/*
+ * R3619 (0xE23) - EQ1_20
+ */
+#define WM5100_EQ1_B5_PG_MASK 0xFFFF /* EQ1_B5_PG - [15:0] */
+#define WM5100_EQ1_B5_PG_SHIFT 0 /* EQ1_B5_PG - [15:0] */
+#define WM5100_EQ1_B5_PG_WIDTH 16 /* EQ1_B5_PG - [15:0] */
+
+/*
+ * R3622 (0xE26) - EQ2_1
+ */
+#define WM5100_EQ2_B1_GAIN_MASK 0xF800 /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B1_GAIN_SHIFT 11 /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B1_GAIN_WIDTH 5 /* EQ2_B1_GAIN - [15:11] */
+#define WM5100_EQ2_B2_GAIN_MASK 0x07C0 /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B2_GAIN_SHIFT 6 /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B2_GAIN_WIDTH 5 /* EQ2_B2_GAIN - [10:6] */
+#define WM5100_EQ2_B3_GAIN_MASK 0x003E /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_B3_GAIN_SHIFT 1 /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_B3_GAIN_WIDTH 5 /* EQ2_B3_GAIN - [5:1] */
+#define WM5100_EQ2_ENA 0x0001 /* EQ2_ENA */
+#define WM5100_EQ2_ENA_MASK 0x0001 /* EQ2_ENA */
+#define WM5100_EQ2_ENA_SHIFT 0 /* EQ2_ENA */
+#define WM5100_EQ2_ENA_WIDTH 1 /* EQ2_ENA */
+
+/*
+ * R3623 (0xE27) - EQ2_2
+ */
+#define WM5100_EQ2_B4_GAIN_MASK 0xF800 /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B4_GAIN_SHIFT 11 /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B4_GAIN_WIDTH 5 /* EQ2_B4_GAIN - [15:11] */
+#define WM5100_EQ2_B5_GAIN_MASK 0x07C0 /* EQ2_B5_GAIN - [10:6] */
+#define WM5100_EQ2_B5_GAIN_SHIFT 6 /* EQ2_B5_GAIN - [10:6] */
+#define WM5100_EQ2_B5_GAIN_WIDTH 5 /* EQ2_B5_GAIN - [10:6] */
+
+/*
+ * R3624 (0xE28) - EQ2_3
+ */
+#define WM5100_EQ2_B1_A_MASK 0xFFFF /* EQ2_B1_A - [15:0] */
+#define WM5100_EQ2_B1_A_SHIFT 0 /* EQ2_B1_A - [15:0] */
+#define WM5100_EQ2_B1_A_WIDTH 16 /* EQ2_B1_A - [15:0] */
+
+/*
+ * R3625 (0xE29) - EQ2_4
+ */
+#define WM5100_EQ2_B1_B_MASK 0xFFFF /* EQ2_B1_B - [15:0] */
+#define WM5100_EQ2_B1_B_SHIFT 0 /* EQ2_B1_B - [15:0] */
+#define WM5100_EQ2_B1_B_WIDTH 16 /* EQ2_B1_B - [15:0] */
+
+/*
+ * R3626 (0xE2A) - EQ2_5
+ */
+#define WM5100_EQ2_B1_PG_MASK 0xFFFF /* EQ2_B1_PG - [15:0] */
+#define WM5100_EQ2_B1_PG_SHIFT 0 /* EQ2_B1_PG - [15:0] */
+#define WM5100_EQ2_B1_PG_WIDTH 16 /* EQ2_B1_PG - [15:0] */
+
+/*
+ * R3627 (0xE2B) - EQ2_6
+ */
+#define WM5100_EQ2_B2_A_MASK 0xFFFF /* EQ2_B2_A - [15:0] */
+#define WM5100_EQ2_B2_A_SHIFT 0 /* EQ2_B2_A - [15:0] */
+#define WM5100_EQ2_B2_A_WIDTH 16 /* EQ2_B2_A - [15:0] */
+
+/*
+ * R3628 (0xE2C) - EQ2_7
+ */
+#define WM5100_EQ2_B2_B_MASK 0xFFFF /* EQ2_B2_B - [15:0] */
+#define WM5100_EQ2_B2_B_SHIFT 0 /* EQ2_B2_B - [15:0] */
+#define WM5100_EQ2_B2_B_WIDTH 16 /* EQ2_B2_B - [15:0] */
+
+/*
+ * R3629 (0xE2D) - EQ2_8
+ */
+#define WM5100_EQ2_B2_C_MASK 0xFFFF /* EQ2_B2_C - [15:0] */
+#define WM5100_EQ2_B2_C_SHIFT 0 /* EQ2_B2_C - [15:0] */
+#define WM5100_EQ2_B2_C_WIDTH 16 /* EQ2_B2_C - [15:0] */
+
+/*
+ * R3630 (0xE2E) - EQ2_9
+ */
+#define WM5100_EQ2_B2_PG_MASK 0xFFFF /* EQ2_B2_PG - [15:0] */
+#define WM5100_EQ2_B2_PG_SHIFT 0 /* EQ2_B2_PG - [15:0] */
+#define WM5100_EQ2_B2_PG_WIDTH 16 /* EQ2_B2_PG - [15:0] */
+
+/*
+ * R3631 (0xE2F) - EQ2_10
+ */
+#define WM5100_EQ2_B3_A_MASK 0xFFFF /* EQ2_B3_A - [15:0] */
+#define WM5100_EQ2_B3_A_SHIFT 0 /* EQ2_B3_A - [15:0] */
+#define WM5100_EQ2_B3_A_WIDTH 16 /* EQ2_B3_A - [15:0] */
+
+/*
+ * R3632 (0xE30) - EQ2_11
+ */
+#define WM5100_EQ2_B3_B_MASK 0xFFFF /* EQ2_B3_B - [15:0] */
+#define WM5100_EQ2_B3_B_SHIFT 0 /* EQ2_B3_B - [15:0] */
+#define WM5100_EQ2_B3_B_WIDTH 16 /* EQ2_B3_B - [15:0] */
+
+/*
+ * R3633 (0xE31) - EQ2_12
+ */
+#define WM5100_EQ2_B3_C_MASK 0xFFFF /* EQ2_B3_C - [15:0] */
+#define WM5100_EQ2_B3_C_SHIFT 0 /* EQ2_B3_C - [15:0] */
+#define WM5100_EQ2_B3_C_WIDTH 16 /* EQ2_B3_C - [15:0] */
+
+/*
+ * R3634 (0xE32) - EQ2_13
+ */
+#define WM5100_EQ2_B3_PG_MASK 0xFFFF /* EQ2_B3_PG - [15:0] */
+#define WM5100_EQ2_B3_PG_SHIFT 0 /* EQ2_B3_PG - [15:0] */
+#define WM5100_EQ2_B3_PG_WIDTH 16 /* EQ2_B3_PG - [15:0] */
+
+/*
+ * R3635 (0xE33) - EQ2_14
+ */
+#define WM5100_EQ2_B4_A_MASK 0xFFFF /* EQ2_B4_A - [15:0] */
+#define WM5100_EQ2_B4_A_SHIFT 0 /* EQ2_B4_A - [15:0] */
+#define WM5100_EQ2_B4_A_WIDTH 16 /* EQ2_B4_A - [15:0] */
+
+/*
+ * R3636 (0xE34) - EQ2_15
+ */
+#define WM5100_EQ2_B4_B_MASK 0xFFFF /* EQ2_B4_B - [15:0] */
+#define WM5100_EQ2_B4_B_SHIFT 0 /* EQ2_B4_B - [15:0] */
+#define WM5100_EQ2_B4_B_WIDTH 16 /* EQ2_B4_B - [15:0] */
+
+/*
+ * R3637 (0xE35) - EQ2_16
+ */
+#define WM5100_EQ2_B4_C_MASK 0xFFFF /* EQ2_B4_C - [15:0] */
+#define WM5100_EQ2_B4_C_SHIFT 0 /* EQ2_B4_C - [15:0] */
+#define WM5100_EQ2_B4_C_WIDTH 16 /* EQ2_B4_C - [15:0] */
+
+/*
+ * R3638 (0xE36) - EQ2_17
+ */
+#define WM5100_EQ2_B4_PG_MASK 0xFFFF /* EQ2_B4_PG - [15:0] */
+#define WM5100_EQ2_B4_PG_SHIFT 0 /* EQ2_B4_PG - [15:0] */
+#define WM5100_EQ2_B4_PG_WIDTH 16 /* EQ2_B4_PG - [15:0] */
+
+/*
+ * R3639 (0xE37) - EQ2_18
+ */
+#define WM5100_EQ2_B5_A_MASK 0xFFFF /* EQ2_B5_A - [15:0] */
+#define WM5100_EQ2_B5_A_SHIFT 0 /* EQ2_B5_A - [15:0] */
+#define WM5100_EQ2_B5_A_WIDTH 16 /* EQ2_B5_A - [15:0] */
+
+/*
+ * R3640 (0xE38) - EQ2_19
+ */
+#define WM5100_EQ2_B5_B_MASK 0xFFFF /* EQ2_B5_B - [15:0] */
+#define WM5100_EQ2_B5_B_SHIFT 0 /* EQ2_B5_B - [15:0] */
+#define WM5100_EQ2_B5_B_WIDTH 16 /* EQ2_B5_B - [15:0] */
+
+/*
+ * R3641 (0xE39) - EQ2_20
+ */
+#define WM5100_EQ2_B5_PG_MASK 0xFFFF /* EQ2_B5_PG - [15:0] */
+#define WM5100_EQ2_B5_PG_SHIFT 0 /* EQ2_B5_PG - [15:0] */
+#define WM5100_EQ2_B5_PG_WIDTH 16 /* EQ2_B5_PG - [15:0] */
+
+/*
+ * R3644 (0xE3C) - EQ3_1
+ */
+#define WM5100_EQ3_B1_GAIN_MASK 0xF800 /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B1_GAIN_SHIFT 11 /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B1_GAIN_WIDTH 5 /* EQ3_B1_GAIN - [15:11] */
+#define WM5100_EQ3_B2_GAIN_MASK 0x07C0 /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B2_GAIN_SHIFT 6 /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B2_GAIN_WIDTH 5 /* EQ3_B2_GAIN - [10:6] */
+#define WM5100_EQ3_B3_GAIN_MASK 0x003E /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_B3_GAIN_SHIFT 1 /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_B3_GAIN_WIDTH 5 /* EQ3_B3_GAIN - [5:1] */
+#define WM5100_EQ3_ENA 0x0001 /* EQ3_ENA */
+#define WM5100_EQ3_ENA_MASK 0x0001 /* EQ3_ENA */
+#define WM5100_EQ3_ENA_SHIFT 0 /* EQ3_ENA */
+#define WM5100_EQ3_ENA_WIDTH 1 /* EQ3_ENA */
+
+/*
+ * R3645 (0xE3D) - EQ3_2
+ */
+#define WM5100_EQ3_B4_GAIN_MASK 0xF800 /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B4_GAIN_SHIFT 11 /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B4_GAIN_WIDTH 5 /* EQ3_B4_GAIN - [15:11] */
+#define WM5100_EQ3_B5_GAIN_MASK 0x07C0 /* EQ3_B5_GAIN - [10:6] */
+#define WM5100_EQ3_B5_GAIN_SHIFT 6 /* EQ3_B5_GAIN - [10:6] */
+#define WM5100_EQ3_B5_GAIN_WIDTH 5 /* EQ3_B5_GAIN - [10:6] */
+
+/*
+ * R3646 (0xE3E) - EQ3_3
+ */
+#define WM5100_EQ3_B1_A_MASK 0xFFFF /* EQ3_B1_A - [15:0] */
+#define WM5100_EQ3_B1_A_SHIFT 0 /* EQ3_B1_A - [15:0] */
+#define WM5100_EQ3_B1_A_WIDTH 16 /* EQ3_B1_A - [15:0] */
+
+/*
+ * R3647 (0xE3F) - EQ3_4
+ */
+#define WM5100_EQ3_B1_B_MASK 0xFFFF /* EQ3_B1_B - [15:0] */
+#define WM5100_EQ3_B1_B_SHIFT 0 /* EQ3_B1_B - [15:0] */
+#define WM5100_EQ3_B1_B_WIDTH 16 /* EQ3_B1_B - [15:0] */
+
+/*
+ * R3648 (0xE40) - EQ3_5
+ */
+#define WM5100_EQ3_B1_PG_MASK 0xFFFF /* EQ3_B1_PG - [15:0] */
+#define WM5100_EQ3_B1_PG_SHIFT 0 /* EQ3_B1_PG - [15:0] */
+#define WM5100_EQ3_B1_PG_WIDTH 16 /* EQ3_B1_PG - [15:0] */
+
+/*
+ * R3649 (0xE41) - EQ3_6
+ */
+#define WM5100_EQ3_B2_A_MASK 0xFFFF /* EQ3_B2_A - [15:0] */
+#define WM5100_EQ3_B2_A_SHIFT 0 /* EQ3_B2_A - [15:0] */
+#define WM5100_EQ3_B2_A_WIDTH 16 /* EQ3_B2_A - [15:0] */
+
+/*
+ * R3650 (0xE42) - EQ3_7
+ */
+#define WM5100_EQ3_B2_B_MASK 0xFFFF /* EQ3_B2_B - [15:0] */
+#define WM5100_EQ3_B2_B_SHIFT 0 /* EQ3_B2_B - [15:0] */
+#define WM5100_EQ3_B2_B_WIDTH 16 /* EQ3_B2_B - [15:0] */
+
+/*
+ * R3651 (0xE43) - EQ3_8
+ */
+#define WM5100_EQ3_B2_C_MASK 0xFFFF /* EQ3_B2_C - [15:0] */
+#define WM5100_EQ3_B2_C_SHIFT 0 /* EQ3_B2_C - [15:0] */
+#define WM5100_EQ3_B2_C_WIDTH 16 /* EQ3_B2_C - [15:0] */
+
+/*
+ * R3652 (0xE44) - EQ3_9
+ */
+#define WM5100_EQ3_B2_PG_MASK 0xFFFF /* EQ3_B2_PG - [15:0] */
+#define WM5100_EQ3_B2_PG_SHIFT 0 /* EQ3_B2_PG - [15:0] */
+#define WM5100_EQ3_B2_PG_WIDTH 16 /* EQ3_B2_PG - [15:0] */
+
+/*
+ * R3653 (0xE45) - EQ3_10
+ */
+#define WM5100_EQ3_B3_A_MASK 0xFFFF /* EQ3_B3_A - [15:0] */
+#define WM5100_EQ3_B3_A_SHIFT 0 /* EQ3_B3_A - [15:0] */
+#define WM5100_EQ3_B3_A_WIDTH 16 /* EQ3_B3_A - [15:0] */
+
+/*
+ * R3654 (0xE46) - EQ3_11
+ */
+#define WM5100_EQ3_B3_B_MASK 0xFFFF /* EQ3_B3_B - [15:0] */
+#define WM5100_EQ3_B3_B_SHIFT 0 /* EQ3_B3_B - [15:0] */
+#define WM5100_EQ3_B3_B_WIDTH 16 /* EQ3_B3_B - [15:0] */
+
+/*
+ * R3655 (0xE47) - EQ3_12
+ */
+#define WM5100_EQ3_B3_C_MASK 0xFFFF /* EQ3_B3_C - [15:0] */
+#define WM5100_EQ3_B3_C_SHIFT 0 /* EQ3_B3_C - [15:0] */
+#define WM5100_EQ3_B3_C_WIDTH 16 /* EQ3_B3_C - [15:0] */
+
+/*
+ * R3656 (0xE48) - EQ3_13
+ */
+#define WM5100_EQ3_B3_PG_MASK 0xFFFF /* EQ3_B3_PG - [15:0] */
+#define WM5100_EQ3_B3_PG_SHIFT 0 /* EQ3_B3_PG - [15:0] */
+#define WM5100_EQ3_B3_PG_WIDTH 16 /* EQ3_B3_PG - [15:0] */
+
+/*
+ * R3657 (0xE49) - EQ3_14
+ */
+#define WM5100_EQ3_B4_A_MASK 0xFFFF /* EQ3_B4_A - [15:0] */
+#define WM5100_EQ3_B4_A_SHIFT 0 /* EQ3_B4_A - [15:0] */
+#define WM5100_EQ3_B4_A_WIDTH 16 /* EQ3_B4_A - [15:0] */
+
+/*
+ * R3658 (0xE4A) - EQ3_15
+ */
+#define WM5100_EQ3_B4_B_MASK 0xFFFF /* EQ3_B4_B - [15:0] */
+#define WM5100_EQ3_B4_B_SHIFT 0 /* EQ3_B4_B - [15:0] */
+#define WM5100_EQ3_B4_B_WIDTH 16 /* EQ3_B4_B - [15:0] */
+
+/*
+ * R3659 (0xE4B) - EQ3_16
+ */
+#define WM5100_EQ3_B4_C_MASK 0xFFFF /* EQ3_B4_C - [15:0] */
+#define WM5100_EQ3_B4_C_SHIFT 0 /* EQ3_B4_C - [15:0] */
+#define WM5100_EQ3_B4_C_WIDTH 16 /* EQ3_B4_C - [15:0] */
+
+/*
+ * R3660 (0xE4C) - EQ3_17
+ */
+#define WM5100_EQ3_B4_PG_MASK 0xFFFF /* EQ3_B4_PG - [15:0] */
+#define WM5100_EQ3_B4_PG_SHIFT 0 /* EQ3_B4_PG - [15:0] */
+#define WM5100_EQ3_B4_PG_WIDTH 16 /* EQ3_B4_PG - [15:0] */
+
+/*
+ * R3661 (0xE4D) - EQ3_18
+ */
+#define WM5100_EQ3_B5_A_MASK 0xFFFF /* EQ3_B5_A - [15:0] */
+#define WM5100_EQ3_B5_A_SHIFT 0 /* EQ3_B5_A - [15:0] */
+#define WM5100_EQ3_B5_A_WIDTH 16 /* EQ3_B5_A - [15:0] */
+
+/*
+ * R3662 (0xE4E) - EQ3_19
+ */
+#define WM5100_EQ3_B5_B_MASK 0xFFFF /* EQ3_B5_B - [15:0] */
+#define WM5100_EQ3_B5_B_SHIFT 0 /* EQ3_B5_B - [15:0] */
+#define WM5100_EQ3_B5_B_WIDTH 16 /* EQ3_B5_B - [15:0] */
+
+/*
+ * R3663 (0xE4F) - EQ3_20
+ */
+#define WM5100_EQ3_B5_PG_MASK 0xFFFF /* EQ3_B5_PG - [15:0] */
+#define WM5100_EQ3_B5_PG_SHIFT 0 /* EQ3_B5_PG - [15:0] */
+#define WM5100_EQ3_B5_PG_WIDTH 16 /* EQ3_B5_PG - [15:0] */
+
+/*
+ * R3666 (0xE52) - EQ4_1
+ */
+#define WM5100_EQ4_B1_GAIN_MASK 0xF800 /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B1_GAIN_SHIFT 11 /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B1_GAIN_WIDTH 5 /* EQ4_B1_GAIN - [15:11] */
+#define WM5100_EQ4_B2_GAIN_MASK 0x07C0 /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B2_GAIN_SHIFT 6 /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B2_GAIN_WIDTH 5 /* EQ4_B2_GAIN - [10:6] */
+#define WM5100_EQ4_B3_GAIN_MASK 0x003E /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_B3_GAIN_SHIFT 1 /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_B3_GAIN_WIDTH 5 /* EQ4_B3_GAIN - [5:1] */
+#define WM5100_EQ4_ENA 0x0001 /* EQ4_ENA */
+#define WM5100_EQ4_ENA_MASK 0x0001 /* EQ4_ENA */
+#define WM5100_EQ4_ENA_SHIFT 0 /* EQ4_ENA */
+#define WM5100_EQ4_ENA_WIDTH 1 /* EQ4_ENA */
+
+/*
+ * R3667 (0xE53) - EQ4_2
+ */
+#define WM5100_EQ4_B4_GAIN_MASK 0xF800 /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B4_GAIN_SHIFT 11 /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B4_GAIN_WIDTH 5 /* EQ4_B4_GAIN - [15:11] */
+#define WM5100_EQ4_B5_GAIN_MASK 0x07C0 /* EQ4_B5_GAIN - [10:6] */
+#define WM5100_EQ4_B5_GAIN_SHIFT 6 /* EQ4_B5_GAIN - [10:6] */
+#define WM5100_EQ4_B5_GAIN_WIDTH 5 /* EQ4_B5_GAIN - [10:6] */
+
+/*
+ * R3668 (0xE54) - EQ4_3
+ */
+#define WM5100_EQ4_B1_A_MASK 0xFFFF /* EQ4_B1_A - [15:0] */
+#define WM5100_EQ4_B1_A_SHIFT 0 /* EQ4_B1_A - [15:0] */
+#define WM5100_EQ4_B1_A_WIDTH 16 /* EQ4_B1_A - [15:0] */
+
+/*
+ * R3669 (0xE55) - EQ4_4
+ */
+#define WM5100_EQ4_B1_B_MASK 0xFFFF /* EQ4_B1_B - [15:0] */
+#define WM5100_EQ4_B1_B_SHIFT 0 /* EQ4_B1_B - [15:0] */
+#define WM5100_EQ4_B1_B_WIDTH 16 /* EQ4_B1_B - [15:0] */
+
+/*
+ * R3670 (0xE56) - EQ4_5
+ */
+#define WM5100_EQ4_B1_PG_MASK 0xFFFF /* EQ4_B1_PG - [15:0] */
+#define WM5100_EQ4_B1_PG_SHIFT 0 /* EQ4_B1_PG - [15:0] */
+#define WM5100_EQ4_B1_PG_WIDTH 16 /* EQ4_B1_PG - [15:0] */
+
+/*
+ * R3671 (0xE57) - EQ4_6
+ */
+#define WM5100_EQ4_B2_A_MASK 0xFFFF /* EQ4_B2_A - [15:0] */
+#define WM5100_EQ4_B2_A_SHIFT 0 /* EQ4_B2_A - [15:0] */
+#define WM5100_EQ4_B2_A_WIDTH 16 /* EQ4_B2_A - [15:0] */
+
+/*
+ * R3672 (0xE58) - EQ4_7
+ */
+#define WM5100_EQ4_B2_B_MASK 0xFFFF /* EQ4_B2_B - [15:0] */
+#define WM5100_EQ4_B2_B_SHIFT 0 /* EQ4_B2_B - [15:0] */
+#define WM5100_EQ4_B2_B_WIDTH 16 /* EQ4_B2_B - [15:0] */
+
+/*
+ * R3673 (0xE59) - EQ4_8
+ */
+#define WM5100_EQ4_B2_C_MASK 0xFFFF /* EQ4_B2_C - [15:0] */
+#define WM5100_EQ4_B2_C_SHIFT 0 /* EQ4_B2_C - [15:0] */
+#define WM5100_EQ4_B2_C_WIDTH 16 /* EQ4_B2_C - [15:0] */
+
+/*
+ * R3674 (0xE5A) - EQ4_9
+ */
+#define WM5100_EQ4_B2_PG_MASK 0xFFFF /* EQ4_B2_PG - [15:0] */
+#define WM5100_EQ4_B2_PG_SHIFT 0 /* EQ4_B2_PG - [15:0] */
+#define WM5100_EQ4_B2_PG_WIDTH 16 /* EQ4_B2_PG - [15:0] */
+
+/*
+ * R3675 (0xE5B) - EQ4_10
+ */
+#define WM5100_EQ4_B3_A_MASK 0xFFFF /* EQ4_B3_A - [15:0] */
+#define WM5100_EQ4_B3_A_SHIFT 0 /* EQ4_B3_A - [15:0] */
+#define WM5100_EQ4_B3_A_WIDTH 16 /* EQ4_B3_A - [15:0] */
+
+/*
+ * R3676 (0xE5C) - EQ4_11
+ */
+#define WM5100_EQ4_B3_B_MASK 0xFFFF /* EQ4_B3_B - [15:0] */
+#define WM5100_EQ4_B3_B_SHIFT 0 /* EQ4_B3_B - [15:0] */
+#define WM5100_EQ4_B3_B_WIDTH 16 /* EQ4_B3_B - [15:0] */
+
+/*
+ * R3677 (0xE5D) - EQ4_12
+ */
+#define WM5100_EQ4_B3_C_MASK 0xFFFF /* EQ4_B3_C - [15:0] */
+#define WM5100_EQ4_B3_C_SHIFT 0 /* EQ4_B3_C - [15:0] */
+#define WM5100_EQ4_B3_C_WIDTH 16 /* EQ4_B3_C - [15:0] */
+
+/*
+ * R3678 (0xE5E) - EQ4_13
+ */
+#define WM5100_EQ4_B3_PG_MASK 0xFFFF /* EQ4_B3_PG - [15:0] */
+#define WM5100_EQ4_B3_PG_SHIFT 0 /* EQ4_B3_PG - [15:0] */
+#define WM5100_EQ4_B3_PG_WIDTH 16 /* EQ4_B3_PG - [15:0] */
+
+/*
+ * R3679 (0xE5F) - EQ4_14
+ */
+#define WM5100_EQ4_B4_A_MASK 0xFFFF /* EQ4_B4_A - [15:0] */
+#define WM5100_EQ4_B4_A_SHIFT 0 /* EQ4_B4_A - [15:0] */
+#define WM5100_EQ4_B4_A_WIDTH 16 /* EQ4_B4_A - [15:0] */
+
+/*
+ * R3680 (0xE60) - EQ4_15
+ */
+#define WM5100_EQ4_B4_B_MASK 0xFFFF /* EQ4_B4_B - [15:0] */
+#define WM5100_EQ4_B4_B_SHIFT 0 /* EQ4_B4_B - [15:0] */
+#define WM5100_EQ4_B4_B_WIDTH 16 /* EQ4_B4_B - [15:0] */
+
+/*
+ * R3681 (0xE61) - EQ4_16
+ */
+#define WM5100_EQ4_B4_C_MASK 0xFFFF /* EQ4_B4_C - [15:0] */
+#define WM5100_EQ4_B4_C_SHIFT 0 /* EQ4_B4_C - [15:0] */
+#define WM5100_EQ4_B4_C_WIDTH 16 /* EQ4_B4_C - [15:0] */
+
+/*
+ * R3682 (0xE62) - EQ4_17
+ */
+#define WM5100_EQ4_B4_PG_MASK 0xFFFF /* EQ4_B4_PG - [15:0] */
+#define WM5100_EQ4_B4_PG_SHIFT 0 /* EQ4_B4_PG - [15:0] */
+#define WM5100_EQ4_B4_PG_WIDTH 16 /* EQ4_B4_PG - [15:0] */
+
+/*
+ * R3683 (0xE63) - EQ4_18
+ */
+#define WM5100_EQ4_B5_A_MASK 0xFFFF /* EQ4_B5_A - [15:0] */
+#define WM5100_EQ4_B5_A_SHIFT 0 /* EQ4_B5_A - [15:0] */
+#define WM5100_EQ4_B5_A_WIDTH 16 /* EQ4_B5_A - [15:0] */
+
+/*
+ * R3684 (0xE64) - EQ4_19
+ */
+#define WM5100_EQ4_B5_B_MASK 0xFFFF /* EQ4_B5_B - [15:0] */
+#define WM5100_EQ4_B5_B_SHIFT 0 /* EQ4_B5_B - [15:0] */
+#define WM5100_EQ4_B5_B_WIDTH 16 /* EQ4_B5_B - [15:0] */
+
+/*
+ * R3685 (0xE65) - EQ4_20
+ */
+#define WM5100_EQ4_B5_PG_MASK 0xFFFF /* EQ4_B5_PG - [15:0] */
+#define WM5100_EQ4_B5_PG_SHIFT 0 /* EQ4_B5_PG - [15:0] */
+#define WM5100_EQ4_B5_PG_WIDTH 16 /* EQ4_B5_PG - [15:0] */
+
+/*
+ * R3712 (0xE80) - DRC1 ctrl1
+ */
+#define WM5100_DRC_SIG_DET_RMS_MASK 0xF800 /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_RMS_SHIFT 11 /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_RMS_WIDTH 5 /* DRC_SIG_DET_RMS - [15:11] */
+#define WM5100_DRC_SIG_DET_PK_MASK 0x0600 /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_SIG_DET_PK_SHIFT 9 /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_SIG_DET_PK_WIDTH 2 /* DRC_SIG_DET_PK - [10:9] */
+#define WM5100_DRC_NG_ENA 0x0100 /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_MASK 0x0100 /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_SHIFT 8 /* DRC_NG_ENA */
+#define WM5100_DRC_NG_ENA_WIDTH 1 /* DRC_NG_ENA */
+#define WM5100_DRC_SIG_DET_MODE 0x0080 /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_MASK 0x0080 /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_SHIFT 7 /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET_MODE_WIDTH 1 /* DRC_SIG_DET_MODE */
+#define WM5100_DRC_SIG_DET 0x0040 /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_MASK 0x0040 /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_SHIFT 6 /* DRC_SIG_DET */
+#define WM5100_DRC_SIG_DET_WIDTH 1 /* DRC_SIG_DET */
+#define WM5100_DRC_KNEE2_OP_ENA 0x0020 /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_MASK 0x0020 /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_SHIFT 5 /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_KNEE2_OP_ENA_WIDTH 1 /* DRC_KNEE2_OP_ENA */
+#define WM5100_DRC_QR 0x0010 /* DRC_QR */
+#define WM5100_DRC_QR_MASK 0x0010 /* DRC_QR */
+#define WM5100_DRC_QR_SHIFT 4 /* DRC_QR */
+#define WM5100_DRC_QR_WIDTH 1 /* DRC_QR */
+#define WM5100_DRC_ANTICLIP 0x0008 /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_MASK 0x0008 /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_SHIFT 3 /* DRC_ANTICLIP */
+#define WM5100_DRC_ANTICLIP_WIDTH 1 /* DRC_ANTICLIP */
+#define WM5100_DRCL_ENA 0x0002 /* DRCL_ENA */
+#define WM5100_DRCL_ENA_MASK 0x0002 /* DRCL_ENA */
+#define WM5100_DRCL_ENA_SHIFT 1 /* DRCL_ENA */
+#define WM5100_DRCL_ENA_WIDTH 1 /* DRCL_ENA */
+#define WM5100_DRCR_ENA 0x0001 /* DRCR_ENA */
+#define WM5100_DRCR_ENA_MASK 0x0001 /* DRCR_ENA */
+#define WM5100_DRCR_ENA_SHIFT 0 /* DRCR_ENA */
+#define WM5100_DRCR_ENA_WIDTH 1 /* DRCR_ENA */
+
+/*
+ * R3713 (0xE81) - DRC1 ctrl2
+ */
+#define WM5100_DRC_ATK_MASK 0x1E00 /* DRC_ATK - [12:9] */
+#define WM5100_DRC_ATK_SHIFT 9 /* DRC_ATK - [12:9] */
+#define WM5100_DRC_ATK_WIDTH 4 /* DRC_ATK - [12:9] */
+#define WM5100_DRC_DCY_MASK 0x01E0 /* DRC_DCY - [8:5] */
+#define WM5100_DRC_DCY_SHIFT 5 /* DRC_DCY - [8:5] */
+#define WM5100_DRC_DCY_WIDTH 4 /* DRC_DCY - [8:5] */
+#define WM5100_DRC_MINGAIN_MASK 0x001C /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MINGAIN_SHIFT 2 /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MINGAIN_WIDTH 3 /* DRC_MINGAIN - [4:2] */
+#define WM5100_DRC_MAXGAIN_MASK 0x0003 /* DRC_MAXGAIN - [1:0] */
+#define WM5100_DRC_MAXGAIN_SHIFT 0 /* DRC_MAXGAIN - [1:0] */
+#define WM5100_DRC_MAXGAIN_WIDTH 2 /* DRC_MAXGAIN - [1:0] */
+
+/*
+ * R3714 (0xE82) - DRC1 ctrl3
+ */
+#define WM5100_DRC_NG_MINGAIN_MASK 0xF000 /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_MINGAIN_SHIFT 12 /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_MINGAIN_WIDTH 4 /* DRC_NG_MINGAIN - [15:12] */
+#define WM5100_DRC_NG_EXP_MASK 0x0C00 /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_NG_EXP_SHIFT 10 /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_NG_EXP_WIDTH 2 /* DRC_NG_EXP - [11:10] */
+#define WM5100_DRC_QR_THR_MASK 0x0300 /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_THR_SHIFT 8 /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_THR_WIDTH 2 /* DRC_QR_THR - [9:8] */
+#define WM5100_DRC_QR_DCY_MASK 0x00C0 /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_QR_DCY_SHIFT 6 /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_QR_DCY_WIDTH 2 /* DRC_QR_DCY - [7:6] */
+#define WM5100_DRC_HI_COMP_MASK 0x0038 /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_HI_COMP_SHIFT 3 /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_HI_COMP_WIDTH 3 /* DRC_HI_COMP - [5:3] */
+#define WM5100_DRC_LO_COMP_MASK 0x0007 /* DRC_LO_COMP - [2:0] */
+#define WM5100_DRC_LO_COMP_SHIFT 0 /* DRC_LO_COMP - [2:0] */
+#define WM5100_DRC_LO_COMP_WIDTH 3 /* DRC_LO_COMP - [2:0] */
+
+/*
+ * R3715 (0xE83) - DRC1 ctrl4
+ */
+#define WM5100_DRC_KNEE_IP_MASK 0x07E0 /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_IP_SHIFT 5 /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_IP_WIDTH 6 /* DRC_KNEE_IP - [10:5] */
+#define WM5100_DRC_KNEE_OP_MASK 0x001F /* DRC_KNEE_OP - [4:0] */
+#define WM5100_DRC_KNEE_OP_SHIFT 0 /* DRC_KNEE_OP - [4:0] */
+#define WM5100_DRC_KNEE_OP_WIDTH 5 /* DRC_KNEE_OP - [4:0] */
+
+/*
+ * R3716 (0xE84) - DRC1 ctrl5
+ */
+#define WM5100_DRC_KNEE2_IP_MASK 0x03E0 /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_IP_SHIFT 5 /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_IP_WIDTH 5 /* DRC_KNEE2_IP - [9:5] */
+#define WM5100_DRC_KNEE2_OP_MASK 0x001F /* DRC_KNEE2_OP - [4:0] */
+#define WM5100_DRC_KNEE2_OP_SHIFT 0 /* DRC_KNEE2_OP - [4:0] */
+#define WM5100_DRC_KNEE2_OP_WIDTH 5 /* DRC_KNEE2_OP - [4:0] */
+
+/*
+ * R3776 (0xEC0) - HPLPF1_1
+ */
+#define WM5100_LHPF1_MODE 0x0002 /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_MASK 0x0002 /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_SHIFT 1 /* LHPF1_MODE */
+#define WM5100_LHPF1_MODE_WIDTH 1 /* LHPF1_MODE */
+#define WM5100_LHPF1_ENA 0x0001 /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_MASK 0x0001 /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_SHIFT 0 /* LHPF1_ENA */
+#define WM5100_LHPF1_ENA_WIDTH 1 /* LHPF1_ENA */
+
+/*
+ * R3777 (0xEC1) - HPLPF1_2
+ */
+#define WM5100_LHPF1_COEFF_MASK 0xFFFF /* LHPF1_COEFF - [15:0] */
+#define WM5100_LHPF1_COEFF_SHIFT 0 /* LHPF1_COEFF - [15:0] */
+#define WM5100_LHPF1_COEFF_WIDTH 16 /* LHPF1_COEFF - [15:0] */
+
+/*
+ * R3780 (0xEC4) - HPLPF2_1
+ */
+#define WM5100_LHPF2_MODE 0x0002 /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_MASK 0x0002 /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_SHIFT 1 /* LHPF2_MODE */
+#define WM5100_LHPF2_MODE_WIDTH 1 /* LHPF2_MODE */
+#define WM5100_LHPF2_ENA 0x0001 /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_MASK 0x0001 /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_SHIFT 0 /* LHPF2_ENA */
+#define WM5100_LHPF2_ENA_WIDTH 1 /* LHPF2_ENA */
+
+/*
+ * R3781 (0xEC5) - HPLPF2_2
+ */
+#define WM5100_LHPF2_COEFF_MASK 0xFFFF /* LHPF2_COEFF - [15:0] */
+#define WM5100_LHPF2_COEFF_SHIFT 0 /* LHPF2_COEFF - [15:0] */
+#define WM5100_LHPF2_COEFF_WIDTH 16 /* LHPF2_COEFF - [15:0] */
+
+/*
+ * R3784 (0xEC8) - HPLPF3_1
+ */
+#define WM5100_LHPF3_MODE 0x0002 /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_MASK 0x0002 /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_SHIFT 1 /* LHPF3_MODE */
+#define WM5100_LHPF3_MODE_WIDTH 1 /* LHPF3_MODE */
+#define WM5100_LHPF3_ENA 0x0001 /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_MASK 0x0001 /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_SHIFT 0 /* LHPF3_ENA */
+#define WM5100_LHPF3_ENA_WIDTH 1 /* LHPF3_ENA */
+
+/*
+ * R3785 (0xEC9) - HPLPF3_2
+ */
+#define WM5100_LHPF3_COEFF_MASK 0xFFFF /* LHPF3_COEFF - [15:0] */
+#define WM5100_LHPF3_COEFF_SHIFT 0 /* LHPF3_COEFF - [15:0] */
+#define WM5100_LHPF3_COEFF_WIDTH 16 /* LHPF3_COEFF - [15:0] */
+
+/*
+ * R3788 (0xECC) - HPLPF4_1
+ */
+#define WM5100_LHPF4_MODE 0x0002 /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_MASK 0x0002 /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_SHIFT 1 /* LHPF4_MODE */
+#define WM5100_LHPF4_MODE_WIDTH 1 /* LHPF4_MODE */
+#define WM5100_LHPF4_ENA 0x0001 /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_MASK 0x0001 /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_SHIFT 0 /* LHPF4_ENA */
+#define WM5100_LHPF4_ENA_WIDTH 1 /* LHPF4_ENA */
+
+/*
+ * R3789 (0xECD) - HPLPF4_2
+ */
+#define WM5100_LHPF4_COEFF_MASK 0xFFFF /* LHPF4_COEFF - [15:0] */
+#define WM5100_LHPF4_COEFF_SHIFT 0 /* LHPF4_COEFF - [15:0] */
+#define WM5100_LHPF4_COEFF_WIDTH 16 /* LHPF4_COEFF - [15:0] */
+
+/*
+ * R16384 (0x4000) - DSP1 DM 0
+ */
+#define WM5100_DSP1_DM_START_1_MASK 0x00FF /* DSP1_DM_START - [7:0] */
+#define WM5100_DSP1_DM_START_1_SHIFT 0 /* DSP1_DM_START - [7:0] */
+#define WM5100_DSP1_DM_START_1_WIDTH 8 /* DSP1_DM_START - [7:0] */
+
+/*
+ * R16385 (0x4001) - DSP1 DM 1
+ */
+#define WM5100_DSP1_DM_START_MASK 0xFFFF /* DSP1_DM_START - [15:0] */
+#define WM5100_DSP1_DM_START_SHIFT 0 /* DSP1_DM_START - [15:0] */
+#define WM5100_DSP1_DM_START_WIDTH 16 /* DSP1_DM_START - [15:0] */
+
+/*
+ * R16386 (0x4002) - DSP1 DM 2
+ */
+#define WM5100_DSP1_DM_1_1_MASK 0x00FF /* DSP1_DM_1 - [7:0] */
+#define WM5100_DSP1_DM_1_1_SHIFT 0 /* DSP1_DM_1 - [7:0] */
+#define WM5100_DSP1_DM_1_1_WIDTH 8 /* DSP1_DM_1 - [7:0] */
+
+/*
+ * R16387 (0x4003) - DSP1 DM 3
+ */
+#define WM5100_DSP1_DM_1_MASK 0xFFFF /* DSP1_DM_1 - [15:0] */
+#define WM5100_DSP1_DM_1_SHIFT 0 /* DSP1_DM_1 - [15:0] */
+#define WM5100_DSP1_DM_1_WIDTH 16 /* DSP1_DM_1 - [15:0] */
+
+/*
+ * R16892 (0x41FC) - DSP1 DM 508
+ */
+#define WM5100_DSP1_DM_254_1_MASK 0x00FF /* DSP1_DM_254 - [7:0] */
+#define WM5100_DSP1_DM_254_1_SHIFT 0 /* DSP1_DM_254 - [7:0] */
+#define WM5100_DSP1_DM_254_1_WIDTH 8 /* DSP1_DM_254 - [7:0] */
+
+/*
+ * R16893 (0x41FD) - DSP1 DM 509
+ */
+#define WM5100_DSP1_DM_254_MASK 0xFFFF /* DSP1_DM_254 - [15:0] */
+#define WM5100_DSP1_DM_254_SHIFT 0 /* DSP1_DM_254 - [15:0] */
+#define WM5100_DSP1_DM_254_WIDTH 16 /* DSP1_DM_254 - [15:0] */
+
+/*
+ * R16894 (0x41FE) - DSP1 DM 510
+ */
+#define WM5100_DSP1_DM_END_1_MASK 0x00FF /* DSP1_DM_END - [7:0] */
+#define WM5100_DSP1_DM_END_1_SHIFT 0 /* DSP1_DM_END - [7:0] */
+#define WM5100_DSP1_DM_END_1_WIDTH 8 /* DSP1_DM_END - [7:0] */
+
+/*
+ * R16895 (0x41FF) - DSP1 DM 511
+ */
+#define WM5100_DSP1_DM_END_MASK 0xFFFF /* DSP1_DM_END - [15:0] */
+#define WM5100_DSP1_DM_END_SHIFT 0 /* DSP1_DM_END - [15:0] */
+#define WM5100_DSP1_DM_END_WIDTH 16 /* DSP1_DM_END - [15:0] */
+
+/*
+ * R18432 (0x4800) - DSP1 PM 0
+ */
+#define WM5100_DSP1_PM_START_2_MASK 0x00FF /* DSP1_PM_START - [7:0] */
+#define WM5100_DSP1_PM_START_2_SHIFT 0 /* DSP1_PM_START - [7:0] */
+#define WM5100_DSP1_PM_START_2_WIDTH 8 /* DSP1_PM_START - [7:0] */
+
+/*
+ * R18433 (0x4801) - DSP1 PM 1
+ */
+#define WM5100_DSP1_PM_START_1_MASK 0xFFFF /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_1_SHIFT 0 /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_1_WIDTH 16 /* DSP1_PM_START - [15:0] */
+
+/*
+ * R18434 (0x4802) - DSP1 PM 2
+ */
+#define WM5100_DSP1_PM_START_MASK 0xFFFF /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_SHIFT 0 /* DSP1_PM_START - [15:0] */
+#define WM5100_DSP1_PM_START_WIDTH 16 /* DSP1_PM_START - [15:0] */
+
+/*
+ * R18435 (0x4803) - DSP1 PM 3
+ */
+#define WM5100_DSP1_PM_1_2_MASK 0x00FF /* DSP1_PM_1 - [7:0] */
+#define WM5100_DSP1_PM_1_2_SHIFT 0 /* DSP1_PM_1 - [7:0] */
+#define WM5100_DSP1_PM_1_2_WIDTH 8 /* DSP1_PM_1 - [7:0] */
+
+/*
+ * R18436 (0x4804) - DSP1 PM 4
+ */
+#define WM5100_DSP1_PM_1_1_MASK 0xFFFF /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_1_SHIFT 0 /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_1_WIDTH 16 /* DSP1_PM_1 - [15:0] */
+
+/*
+ * R18437 (0x4805) - DSP1 PM 5
+ */
+#define WM5100_DSP1_PM_1_MASK 0xFFFF /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_SHIFT 0 /* DSP1_PM_1 - [15:0] */
+#define WM5100_DSP1_PM_1_WIDTH 16 /* DSP1_PM_1 - [15:0] */
+
+/*
+ * R19962 (0x4DFA) - DSP1 PM 1530
+ */
+#define WM5100_DSP1_PM_510_2_MASK 0x00FF /* DSP1_PM_510 - [7:0] */
+#define WM5100_DSP1_PM_510_2_SHIFT 0 /* DSP1_PM_510 - [7:0] */
+#define WM5100_DSP1_PM_510_2_WIDTH 8 /* DSP1_PM_510 - [7:0] */
+
+/*
+ * R19963 (0x4DFB) - DSP1 PM 1531
+ */
+#define WM5100_DSP1_PM_510_1_MASK 0xFFFF /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_1_SHIFT 0 /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_1_WIDTH 16 /* DSP1_PM_510 - [15:0] */
+
+/*
+ * R19964 (0x4DFC) - DSP1 PM 1532
+ */
+#define WM5100_DSP1_PM_510_MASK 0xFFFF /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_SHIFT 0 /* DSP1_PM_510 - [15:0] */
+#define WM5100_DSP1_PM_510_WIDTH 16 /* DSP1_PM_510 - [15:0] */
+
+/*
+ * R19965 (0x4DFD) - DSP1 PM 1533
+ */
+#define WM5100_DSP1_PM_END_2_MASK 0x00FF /* DSP1_PM_END - [7:0] */
+#define WM5100_DSP1_PM_END_2_SHIFT 0 /* DSP1_PM_END - [7:0] */
+#define WM5100_DSP1_PM_END_2_WIDTH 8 /* DSP1_PM_END - [7:0] */
+
+/*
+ * R19966 (0x4DFE) - DSP1 PM 1534
+ */
+#define WM5100_DSP1_PM_END_1_MASK 0xFFFF /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_1_SHIFT 0 /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_1_WIDTH 16 /* DSP1_PM_END - [15:0] */
+
+/*
+ * R19967 (0x4DFF) - DSP1 PM 1535
+ */
+#define WM5100_DSP1_PM_END_MASK 0xFFFF /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_SHIFT 0 /* DSP1_PM_END - [15:0] */
+#define WM5100_DSP1_PM_END_WIDTH 16 /* DSP1_PM_END - [15:0] */
+
+/*
+ * R20480 (0x5000) - DSP1 ZM 0
+ */
+#define WM5100_DSP1_ZM_START_1_MASK 0x00FF /* DSP1_ZM_START - [7:0] */
+#define WM5100_DSP1_ZM_START_1_SHIFT 0 /* DSP1_ZM_START - [7:0] */
+#define WM5100_DSP1_ZM_START_1_WIDTH 8 /* DSP1_ZM_START - [7:0] */
+
+/*
+ * R20481 (0x5001) - DSP1 ZM 1
+ */
+#define WM5100_DSP1_ZM_START_MASK 0xFFFF /* DSP1_ZM_START - [15:0] */
+#define WM5100_DSP1_ZM_START_SHIFT 0 /* DSP1_ZM_START - [15:0] */
+#define WM5100_DSP1_ZM_START_WIDTH 16 /* DSP1_ZM_START - [15:0] */
+
+/*
+ * R20482 (0x5002) - DSP1 ZM 2
+ */
+#define WM5100_DSP1_ZM_1_1_MASK 0x00FF /* DSP1_ZM_1 - [7:0] */
+#define WM5100_DSP1_ZM_1_1_SHIFT 0 /* DSP1_ZM_1 - [7:0] */
+#define WM5100_DSP1_ZM_1_1_WIDTH 8 /* DSP1_ZM_1 - [7:0] */
+
+/*
+ * R20483 (0x5003) - DSP1 ZM 3
+ */
+#define WM5100_DSP1_ZM_1_MASK 0xFFFF /* DSP1_ZM_1 - [15:0] */
+#define WM5100_DSP1_ZM_1_SHIFT 0 /* DSP1_ZM_1 - [15:0] */
+#define WM5100_DSP1_ZM_1_WIDTH 16 /* DSP1_ZM_1 - [15:0] */
+
+/*
+ * R22524 (0x57FC) - DSP1 ZM 2044
+ */
+#define WM5100_DSP1_ZM_1022_1_MASK 0x00FF /* DSP1_ZM_1022 - [7:0] */
+#define WM5100_DSP1_ZM_1022_1_SHIFT 0 /* DSP1_ZM_1022 - [7:0] */
+#define WM5100_DSP1_ZM_1022_1_WIDTH 8 /* DSP1_ZM_1022 - [7:0] */
+
+/*
+ * R22525 (0x57FD) - DSP1 ZM 2045
+ */
+#define WM5100_DSP1_ZM_1022_MASK 0xFFFF /* DSP1_ZM_1022 - [15:0] */
+#define WM5100_DSP1_ZM_1022_SHIFT 0 /* DSP1_ZM_1022 - [15:0] */
+#define WM5100_DSP1_ZM_1022_WIDTH 16 /* DSP1_ZM_1022 - [15:0] */
+
+/*
+ * R22526 (0x57FE) - DSP1 ZM 2046
+ */
+#define WM5100_DSP1_ZM_END_1_MASK 0x00FF /* DSP1_ZM_END - [7:0] */
+#define WM5100_DSP1_ZM_END_1_SHIFT 0 /* DSP1_ZM_END - [7:0] */
+#define WM5100_DSP1_ZM_END_1_WIDTH 8 /* DSP1_ZM_END - [7:0] */
+
+/*
+ * R22527 (0x57FF) - DSP1 ZM 2047
+ */
+#define WM5100_DSP1_ZM_END_MASK 0xFFFF /* DSP1_ZM_END - [15:0] */
+#define WM5100_DSP1_ZM_END_SHIFT 0 /* DSP1_ZM_END - [15:0] */
+#define WM5100_DSP1_ZM_END_WIDTH 16 /* DSP1_ZM_END - [15:0] */
+
+/*
+ * R24576 (0x6000) - DSP2 DM 0
+ */
+#define WM5100_DSP2_DM_START_1_MASK 0x00FF /* DSP2_DM_START - [7:0] */
+#define WM5100_DSP2_DM_START_1_SHIFT 0 /* DSP2_DM_START - [7:0] */
+#define WM5100_DSP2_DM_START_1_WIDTH 8 /* DSP2_DM_START - [7:0] */
+
+/*
+ * R24577 (0x6001) - DSP2 DM 1
+ */
+#define WM5100_DSP2_DM_START_MASK 0xFFFF /* DSP2_DM_START - [15:0] */
+#define WM5100_DSP2_DM_START_SHIFT 0 /* DSP2_DM_START - [15:0] */
+#define WM5100_DSP2_DM_START_WIDTH 16 /* DSP2_DM_START - [15:0] */
+
+/*
+ * R24578 (0x6002) - DSP2 DM 2
+ */
+#define WM5100_DSP2_DM_1_1_MASK 0x00FF /* DSP2_DM_1 - [7:0] */
+#define WM5100_DSP2_DM_1_1_SHIFT 0 /* DSP2_DM_1 - [7:0] */
+#define WM5100_DSP2_DM_1_1_WIDTH 8 /* DSP2_DM_1 - [7:0] */
+
+/*
+ * R24579 (0x6003) - DSP2 DM 3
+ */
+#define WM5100_DSP2_DM_1_MASK 0xFFFF /* DSP2_DM_1 - [15:0] */
+#define WM5100_DSP2_DM_1_SHIFT 0 /* DSP2_DM_1 - [15:0] */
+#define WM5100_DSP2_DM_1_WIDTH 16 /* DSP2_DM_1 - [15:0] */
+
+/*
+ * R25084 (0x61FC) - DSP2 DM 508
+ */
+#define WM5100_DSP2_DM_254_1_MASK 0x00FF /* DSP2_DM_254 - [7:0] */
+#define WM5100_DSP2_DM_254_1_SHIFT 0 /* DSP2_DM_254 - [7:0] */
+#define WM5100_DSP2_DM_254_1_WIDTH 8 /* DSP2_DM_254 - [7:0] */
+
+/*
+ * R25085 (0x61FD) - DSP2 DM 509
+ */
+#define WM5100_DSP2_DM_254_MASK 0xFFFF /* DSP2_DM_254 - [15:0] */
+#define WM5100_DSP2_DM_254_SHIFT 0 /* DSP2_DM_254 - [15:0] */
+#define WM5100_DSP2_DM_254_WIDTH 16 /* DSP2_DM_254 - [15:0] */
+
+/*
+ * R25086 (0x61FE) - DSP2 DM 510
+ */
+#define WM5100_DSP2_DM_END_1_MASK 0x00FF /* DSP2_DM_END - [7:0] */
+#define WM5100_DSP2_DM_END_1_SHIFT 0 /* DSP2_DM_END - [7:0] */
+#define WM5100_DSP2_DM_END_1_WIDTH 8 /* DSP2_DM_END - [7:0] */
+
+/*
+ * R25087 (0x61FF) - DSP2 DM 511
+ */
+#define WM5100_DSP2_DM_END_MASK 0xFFFF /* DSP2_DM_END - [15:0] */
+#define WM5100_DSP2_DM_END_SHIFT 0 /* DSP2_DM_END - [15:0] */
+#define WM5100_DSP2_DM_END_WIDTH 16 /* DSP2_DM_END - [15:0] */
+
+/*
+ * R26624 (0x6800) - DSP2 PM 0
+ */
+#define WM5100_DSP2_PM_START_2_MASK 0x00FF /* DSP2_PM_START - [7:0] */
+#define WM5100_DSP2_PM_START_2_SHIFT 0 /* DSP2_PM_START - [7:0] */
+#define WM5100_DSP2_PM_START_2_WIDTH 8 /* DSP2_PM_START - [7:0] */
+
+/*
+ * R26625 (0x6801) - DSP2 PM 1
+ */
+#define WM5100_DSP2_PM_START_1_MASK 0xFFFF /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_1_SHIFT 0 /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_1_WIDTH 16 /* DSP2_PM_START - [15:0] */
+
+/*
+ * R26626 (0x6802) - DSP2 PM 2
+ */
+#define WM5100_DSP2_PM_START_MASK 0xFFFF /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_SHIFT 0 /* DSP2_PM_START - [15:0] */
+#define WM5100_DSP2_PM_START_WIDTH 16 /* DSP2_PM_START - [15:0] */
+
+/*
+ * R26627 (0x6803) - DSP2 PM 3
+ */
+#define WM5100_DSP2_PM_1_2_MASK 0x00FF /* DSP2_PM_1 - [7:0] */
+#define WM5100_DSP2_PM_1_2_SHIFT 0 /* DSP2_PM_1 - [7:0] */
+#define WM5100_DSP2_PM_1_2_WIDTH 8 /* DSP2_PM_1 - [7:0] */
+
+/*
+ * R26628 (0x6804) - DSP2 PM 4
+ */
+#define WM5100_DSP2_PM_1_1_MASK 0xFFFF /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_1_SHIFT 0 /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_1_WIDTH 16 /* DSP2_PM_1 - [15:0] */
+
+/*
+ * R26629 (0x6805) - DSP2 PM 5
+ */
+#define WM5100_DSP2_PM_1_MASK 0xFFFF /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_SHIFT 0 /* DSP2_PM_1 - [15:0] */
+#define WM5100_DSP2_PM_1_WIDTH 16 /* DSP2_PM_1 - [15:0] */
+
+/*
+ * R28154 (0x6DFA) - DSP2 PM 1530
+ */
+#define WM5100_DSP2_PM_510_2_MASK 0x00FF /* DSP2_PM_510 - [7:0] */
+#define WM5100_DSP2_PM_510_2_SHIFT 0 /* DSP2_PM_510 - [7:0] */
+#define WM5100_DSP2_PM_510_2_WIDTH 8 /* DSP2_PM_510 - [7:0] */
+
+/*
+ * R28155 (0x6DFB) - DSP2 PM 1531
+ */
+#define WM5100_DSP2_PM_510_1_MASK 0xFFFF /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_1_SHIFT 0 /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_1_WIDTH 16 /* DSP2_PM_510 - [15:0] */
+
+/*
+ * R28156 (0x6DFC) - DSP2 PM 1532
+ */
+#define WM5100_DSP2_PM_510_MASK 0xFFFF /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_SHIFT 0 /* DSP2_PM_510 - [15:0] */
+#define WM5100_DSP2_PM_510_WIDTH 16 /* DSP2_PM_510 - [15:0] */
+
+/*
+ * R28157 (0x6DFD) - DSP2 PM 1533
+ */
+#define WM5100_DSP2_PM_END_2_MASK 0x00FF /* DSP2_PM_END - [7:0] */
+#define WM5100_DSP2_PM_END_2_SHIFT 0 /* DSP2_PM_END - [7:0] */
+#define WM5100_DSP2_PM_END_2_WIDTH 8 /* DSP2_PM_END - [7:0] */
+
+/*
+ * R28158 (0x6DFE) - DSP2 PM 1534
+ */
+#define WM5100_DSP2_PM_END_1_MASK 0xFFFF /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_1_SHIFT 0 /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_1_WIDTH 16 /* DSP2_PM_END - [15:0] */
+
+/*
+ * R28159 (0x6DFF) - DSP2 PM 1535
+ */
+#define WM5100_DSP2_PM_END_MASK 0xFFFF /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_SHIFT 0 /* DSP2_PM_END - [15:0] */
+#define WM5100_DSP2_PM_END_WIDTH 16 /* DSP2_PM_END - [15:0] */
+
+/*
+ * R28672 (0x7000) - DSP2 ZM 0
+ */
+#define WM5100_DSP2_ZM_START_1_MASK 0x00FF /* DSP2_ZM_START - [7:0] */
+#define WM5100_DSP2_ZM_START_1_SHIFT 0 /* DSP2_ZM_START - [7:0] */
+#define WM5100_DSP2_ZM_START_1_WIDTH 8 /* DSP2_ZM_START - [7:0] */
+
+/*
+ * R28673 (0x7001) - DSP2 ZM 1
+ */
+#define WM5100_DSP2_ZM_START_MASK 0xFFFF /* DSP2_ZM_START - [15:0] */
+#define WM5100_DSP2_ZM_START_SHIFT 0 /* DSP2_ZM_START - [15:0] */
+#define WM5100_DSP2_ZM_START_WIDTH 16 /* DSP2_ZM_START - [15:0] */
+
+/*
+ * R28674 (0x7002) - DSP2 ZM 2
+ */
+#define WM5100_DSP2_ZM_1_1_MASK 0x00FF /* DSP2_ZM_1 - [7:0] */
+#define WM5100_DSP2_ZM_1_1_SHIFT 0 /* DSP2_ZM_1 - [7:0] */
+#define WM5100_DSP2_ZM_1_1_WIDTH 8 /* DSP2_ZM_1 - [7:0] */
+
+/*
+ * R28675 (0x7003) - DSP2 ZM 3
+ */
+#define WM5100_DSP2_ZM_1_MASK 0xFFFF /* DSP2_ZM_1 - [15:0] */
+#define WM5100_DSP2_ZM_1_SHIFT 0 /* DSP2_ZM_1 - [15:0] */
+#define WM5100_DSP2_ZM_1_WIDTH 16 /* DSP2_ZM_1 - [15:0] */
+
+/*
+ * R30716 (0x77FC) - DSP2 ZM 2044
+ */
+#define WM5100_DSP2_ZM_1022_1_MASK 0x00FF /* DSP2_ZM_1022 - [7:0] */
+#define WM5100_DSP2_ZM_1022_1_SHIFT 0 /* DSP2_ZM_1022 - [7:0] */
+#define WM5100_DSP2_ZM_1022_1_WIDTH 8 /* DSP2_ZM_1022 - [7:0] */
+
+/*
+ * R30717 (0x77FD) - DSP2 ZM 2045
+ */
+#define WM5100_DSP2_ZM_1022_MASK 0xFFFF /* DSP2_ZM_1022 - [15:0] */
+#define WM5100_DSP2_ZM_1022_SHIFT 0 /* DSP2_ZM_1022 - [15:0] */
+#define WM5100_DSP2_ZM_1022_WIDTH 16 /* DSP2_ZM_1022 - [15:0] */
+
+/*
+ * R30718 (0x77FE) - DSP2 ZM 2046
+ */
+#define WM5100_DSP2_ZM_END_1_MASK 0x00FF /* DSP2_ZM_END - [7:0] */
+#define WM5100_DSP2_ZM_END_1_SHIFT 0 /* DSP2_ZM_END - [7:0] */
+#define WM5100_DSP2_ZM_END_1_WIDTH 8 /* DSP2_ZM_END - [7:0] */
+
+/*
+ * R30719 (0x77FF) - DSP2 ZM 2047
+ */
+#define WM5100_DSP2_ZM_END_MASK 0xFFFF /* DSP2_ZM_END - [15:0] */
+#define WM5100_DSP2_ZM_END_SHIFT 0 /* DSP2_ZM_END - [15:0] */
+#define WM5100_DSP2_ZM_END_WIDTH 16 /* DSP2_ZM_END - [15:0] */
+
+/*
+ * R32768 (0x8000) - DSP3 DM 0
+ */
+#define WM5100_DSP3_DM_START_1_MASK 0x00FF /* DSP3_DM_START - [7:0] */
+#define WM5100_DSP3_DM_START_1_SHIFT 0 /* DSP3_DM_START - [7:0] */
+#define WM5100_DSP3_DM_START_1_WIDTH 8 /* DSP3_DM_START - [7:0] */
+
+/*
+ * R32769 (0x8001) - DSP3 DM 1
+ */
+#define WM5100_DSP3_DM_START_MASK 0xFFFF /* DSP3_DM_START - [15:0] */
+#define WM5100_DSP3_DM_START_SHIFT 0 /* DSP3_DM_START - [15:0] */
+#define WM5100_DSP3_DM_START_WIDTH 16 /* DSP3_DM_START - [15:0] */
+
+/*
+ * R32770 (0x8002) - DSP3 DM 2
+ */
+#define WM5100_DSP3_DM_1_1_MASK 0x00FF /* DSP3_DM_1 - [7:0] */
+#define WM5100_DSP3_DM_1_1_SHIFT 0 /* DSP3_DM_1 - [7:0] */
+#define WM5100_DSP3_DM_1_1_WIDTH 8 /* DSP3_DM_1 - [7:0] */
+
+/*
+ * R32771 (0x8003) - DSP3 DM 3
+ */
+#define WM5100_DSP3_DM_1_MASK 0xFFFF /* DSP3_DM_1 - [15:0] */
+#define WM5100_DSP3_DM_1_SHIFT 0 /* DSP3_DM_1 - [15:0] */
+#define WM5100_DSP3_DM_1_WIDTH 16 /* DSP3_DM_1 - [15:0] */
+
+/*
+ * R33276 (0x81FC) - DSP3 DM 508
+ */
+#define WM5100_DSP3_DM_254_1_MASK 0x00FF /* DSP3_DM_254 - [7:0] */
+#define WM5100_DSP3_DM_254_1_SHIFT 0 /* DSP3_DM_254 - [7:0] */
+#define WM5100_DSP3_DM_254_1_WIDTH 8 /* DSP3_DM_254 - [7:0] */
+
+/*
+ * R33277 (0x81FD) - DSP3 DM 509
+ */
+#define WM5100_DSP3_DM_254_MASK 0xFFFF /* DSP3_DM_254 - [15:0] */
+#define WM5100_DSP3_DM_254_SHIFT 0 /* DSP3_DM_254 - [15:0] */
+#define WM5100_DSP3_DM_254_WIDTH 16 /* DSP3_DM_254 - [15:0] */
+
+/*
+ * R33278 (0x81FE) - DSP3 DM 510
+ */
+#define WM5100_DSP3_DM_END_1_MASK 0x00FF /* DSP3_DM_END - [7:0] */
+#define WM5100_DSP3_DM_END_1_SHIFT 0 /* DSP3_DM_END - [7:0] */
+#define WM5100_DSP3_DM_END_1_WIDTH 8 /* DSP3_DM_END - [7:0] */
+
+/*
+ * R33279 (0x81FF) - DSP3 DM 511
+ */
+#define WM5100_DSP3_DM_END_MASK 0xFFFF /* DSP3_DM_END - [15:0] */
+#define WM5100_DSP3_DM_END_SHIFT 0 /* DSP3_DM_END - [15:0] */
+#define WM5100_DSP3_DM_END_WIDTH 16 /* DSP3_DM_END - [15:0] */
+
+/*
+ * R34816 (0x8800) - DSP3 PM 0
+ */
+#define WM5100_DSP3_PM_START_2_MASK 0x00FF /* DSP3_PM_START - [7:0] */
+#define WM5100_DSP3_PM_START_2_SHIFT 0 /* DSP3_PM_START - [7:0] */
+#define WM5100_DSP3_PM_START_2_WIDTH 8 /* DSP3_PM_START - [7:0] */
+
+/*
+ * R34817 (0x8801) - DSP3 PM 1
+ */
+#define WM5100_DSP3_PM_START_1_MASK 0xFFFF /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_1_SHIFT 0 /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_1_WIDTH 16 /* DSP3_PM_START - [15:0] */
+
+/*
+ * R34818 (0x8802) - DSP3 PM 2
+ */
+#define WM5100_DSP3_PM_START_MASK 0xFFFF /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_SHIFT 0 /* DSP3_PM_START - [15:0] */
+#define WM5100_DSP3_PM_START_WIDTH 16 /* DSP3_PM_START - [15:0] */
+
+/*
+ * R34819 (0x8803) - DSP3 PM 3
+ */
+#define WM5100_DSP3_PM_1_2_MASK 0x00FF /* DSP3_PM_1 - [7:0] */
+#define WM5100_DSP3_PM_1_2_SHIFT 0 /* DSP3_PM_1 - [7:0] */
+#define WM5100_DSP3_PM_1_2_WIDTH 8 /* DSP3_PM_1 - [7:0] */
+
+/*
+ * R34820 (0x8804) - DSP3 PM 4
+ */
+#define WM5100_DSP3_PM_1_1_MASK 0xFFFF /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_1_SHIFT 0 /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_1_WIDTH 16 /* DSP3_PM_1 - [15:0] */
+
+/*
+ * R34821 (0x8805) - DSP3 PM 5
+ */
+#define WM5100_DSP3_PM_1_MASK 0xFFFF /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_SHIFT 0 /* DSP3_PM_1 - [15:0] */
+#define WM5100_DSP3_PM_1_WIDTH 16 /* DSP3_PM_1 - [15:0] */
+
+/*
+ * R36346 (0x8DFA) - DSP3 PM 1530
+ */
+#define WM5100_DSP3_PM_510_2_MASK 0x00FF /* DSP3_PM_510 - [7:0] */
+#define WM5100_DSP3_PM_510_2_SHIFT 0 /* DSP3_PM_510 - [7:0] */
+#define WM5100_DSP3_PM_510_2_WIDTH 8 /* DSP3_PM_510 - [7:0] */
+
+/*
+ * R36347 (0x8DFB) - DSP3 PM 1531
+ */
+#define WM5100_DSP3_PM_510_1_MASK 0xFFFF /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_1_SHIFT 0 /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_1_WIDTH 16 /* DSP3_PM_510 - [15:0] */
+
+/*
+ * R36348 (0x8DFC) - DSP3 PM 1532
+ */
+#define WM5100_DSP3_PM_510_MASK 0xFFFF /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_SHIFT 0 /* DSP3_PM_510 - [15:0] */
+#define WM5100_DSP3_PM_510_WIDTH 16 /* DSP3_PM_510 - [15:0] */
+
+/*
+ * R36349 (0x8DFD) - DSP3 PM 1533
+ */
+#define WM5100_DSP3_PM_END_2_MASK 0x00FF /* DSP3_PM_END - [7:0] */
+#define WM5100_DSP3_PM_END_2_SHIFT 0 /* DSP3_PM_END - [7:0] */
+#define WM5100_DSP3_PM_END_2_WIDTH 8 /* DSP3_PM_END - [7:0] */
+
+/*
+ * R36350 (0x8DFE) - DSP3 PM 1534
+ */
+#define WM5100_DSP3_PM_END_1_MASK 0xFFFF /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_1_SHIFT 0 /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_1_WIDTH 16 /* DSP3_PM_END - [15:0] */
+
+/*
+ * R36351 (0x8DFF) - DSP3 PM 1535
+ */
+#define WM5100_DSP3_PM_END_MASK 0xFFFF /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_SHIFT 0 /* DSP3_PM_END - [15:0] */
+#define WM5100_DSP3_PM_END_WIDTH 16 /* DSP3_PM_END - [15:0] */
+
+/*
+ * R36864 (0x9000) - DSP3 ZM 0
+ */
+#define WM5100_DSP3_ZM_START_1_MASK 0x00FF /* DSP3_ZM_START - [7:0] */
+#define WM5100_DSP3_ZM_START_1_SHIFT 0 /* DSP3_ZM_START - [7:0] */
+#define WM5100_DSP3_ZM_START_1_WIDTH 8 /* DSP3_ZM_START - [7:0] */
+
+/*
+ * R36865 (0x9001) - DSP3 ZM 1
+ */
+#define WM5100_DSP3_ZM_START_MASK 0xFFFF /* DSP3_ZM_START - [15:0] */
+#define WM5100_DSP3_ZM_START_SHIFT 0 /* DSP3_ZM_START - [15:0] */
+#define WM5100_DSP3_ZM_START_WIDTH 16 /* DSP3_ZM_START - [15:0] */
+
+/*
+ * R36866 (0x9002) - DSP3 ZM 2
+ */
+#define WM5100_DSP3_ZM_1_1_MASK 0x00FF /* DSP3_ZM_1 - [7:0] */
+#define WM5100_DSP3_ZM_1_1_SHIFT 0 /* DSP3_ZM_1 - [7:0] */
+#define WM5100_DSP3_ZM_1_1_WIDTH 8 /* DSP3_ZM_1 - [7:0] */
+
+/*
+ * R36867 (0x9003) - DSP3 ZM 3
+ */
+#define WM5100_DSP3_ZM_1_MASK 0xFFFF /* DSP3_ZM_1 - [15:0] */
+#define WM5100_DSP3_ZM_1_SHIFT 0 /* DSP3_ZM_1 - [15:0] */
+#define WM5100_DSP3_ZM_1_WIDTH 16 /* DSP3_ZM_1 - [15:0] */
+
+/*
+ * R38908 (0x97FC) - DSP3 ZM 2044
+ */
+#define WM5100_DSP3_ZM_1022_1_MASK 0x00FF /* DSP3_ZM_1022 - [7:0] */
+#define WM5100_DSP3_ZM_1022_1_SHIFT 0 /* DSP3_ZM_1022 - [7:0] */
+#define WM5100_DSP3_ZM_1022_1_WIDTH 8 /* DSP3_ZM_1022 - [7:0] */
+
+/*
+ * R38909 (0x97FD) - DSP3 ZM 2045
+ */
+#define WM5100_DSP3_ZM_1022_MASK 0xFFFF /* DSP3_ZM_1022 - [15:0] */
+#define WM5100_DSP3_ZM_1022_SHIFT 0 /* DSP3_ZM_1022 - [15:0] */
+#define WM5100_DSP3_ZM_1022_WIDTH 16 /* DSP3_ZM_1022 - [15:0] */
+
+/*
+ * R38910 (0x97FE) - DSP3 ZM 2046
+ */
+#define WM5100_DSP3_ZM_END_1_MASK 0x00FF /* DSP3_ZM_END - [7:0] */
+#define WM5100_DSP3_ZM_END_1_SHIFT 0 /* DSP3_ZM_END - [7:0] */
+#define WM5100_DSP3_ZM_END_1_WIDTH 8 /* DSP3_ZM_END - [7:0] */
+
+/*
+ * R38911 (0x97FF) - DSP3 ZM 2047
+ */
+#define WM5100_DSP3_ZM_END_MASK 0xFFFF /* DSP3_ZM_END - [15:0] */
+#define WM5100_DSP3_ZM_END_SHIFT 0 /* DSP3_ZM_END - [15:0] */
+#define WM5100_DSP3_ZM_END_WIDTH 16 /* DSP3_ZM_END - [15:0] */
+
+bool wm5100_readable_register(struct device *dev, unsigned int reg);
+bool wm5100_volatile_register(struct device *dev, unsigned int reg);
+
+extern struct reg_default wm5100_reg_defaults[WM5100_REGISTER_COUNT];
+
+#endif
diff --git a/sound/soc/codecs/wm8350.c b/sound/soc/codecs/wm8350.c
index 6d6dc9efe914..8c4c9591ec05 100644
--- a/sound/soc/codecs/wm8350.c
+++ b/sound/soc/codecs/wm8350.c
@@ -355,7 +355,7 @@ static int wm8350_put_volsw_2r_vu(struct snd_kcontrol *kcontrol,
return 1;
}
- ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
if (ret < 0)
return ret;
@@ -392,23 +392,9 @@ static int wm8350_get_volsw_2r(struct snd_kcontrol *kcontrol,
break;
}
- return snd_soc_get_volsw_2r(kcontrol, ucontrol);
+ return snd_soc_get_volsw(kcontrol, ucontrol);
}
-/* double control with volume update */
-#define SOC_WM8350_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
- xinvert, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_READWRITE | \
- SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw_2r, \
- .get = wm8350_get_volsw_2r, .put = wm8350_put_volsw_2r_vu, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
- .rshift = xshift, .max = xmax, .invert = xinvert}, }
-
static const char *wm8350_deemp[] = { "None", "32kHz", "44.1kHz", "48kHz" };
static const char *wm8350_pol[] = { "Normal", "Inv R", "Inv L", "Inv L & R" };
static const char *wm8350_dacmutem[] = { "Normal", "Soft" };
@@ -443,26 +429,29 @@ static const unsigned int capture_sd_tlv[] = {
static const struct snd_kcontrol_new wm8350_snd_controls[] = {
SOC_ENUM("Playback Deemphasis", wm8350_enum[0]),
SOC_ENUM("Playback DAC Inversion", wm8350_enum[1]),
- SOC_WM8350_DOUBLE_R_TLV("Playback PCM Volume",
+ SOC_DOUBLE_R_EXT_TLV("Playback PCM Volume",
WM8350_DAC_DIGITAL_VOLUME_L,
WM8350_DAC_DIGITAL_VOLUME_R,
- 0, 255, 0, dac_pcm_tlv),
+ 0, 255, 0, wm8350_get_volsw_2r,
+ wm8350_put_volsw_2r_vu, dac_pcm_tlv),
SOC_ENUM("Playback PCM Mute Function", wm8350_enum[2]),
SOC_ENUM("Playback PCM Mute Speed", wm8350_enum[3]),
SOC_ENUM("Capture PCM Filter", wm8350_enum[4]),
SOC_ENUM("Capture PCM HP Filter", wm8350_enum[5]),
SOC_ENUM("Capture ADC Inversion", wm8350_enum[6]),
- SOC_WM8350_DOUBLE_R_TLV("Capture PCM Volume",
+ SOC_DOUBLE_R_EXT_TLV("Capture PCM Volume",
WM8350_ADC_DIGITAL_VOLUME_L,
WM8350_ADC_DIGITAL_VOLUME_R,
- 0, 255, 0, adc_pcm_tlv),
+ 0, 255, 0, wm8350_get_volsw_2r,
+ wm8350_put_volsw_2r_vu, adc_pcm_tlv),
SOC_DOUBLE_TLV("Capture Sidetone Volume",
WM8350_ADC_DIVIDER,
8, 4, 15, 1, capture_sd_tlv),
- SOC_WM8350_DOUBLE_R_TLV("Capture Volume",
+ SOC_DOUBLE_R_EXT_TLV("Capture Volume",
WM8350_LEFT_INPUT_VOLUME,
WM8350_RIGHT_INPUT_VOLUME,
- 2, 63, 0, pre_amp_tlv),
+ 2, 63, 0, wm8350_get_volsw_2r,
+ wm8350_put_volsw_2r_vu, pre_amp_tlv),
SOC_DOUBLE_R("Capture ZC Switch",
WM8350_LEFT_INPUT_VOLUME,
WM8350_RIGHT_INPUT_VOLUME, 13, 1, 0),
@@ -490,17 +479,19 @@ static const struct snd_kcontrol_new wm8350_snd_controls[] = {
SOC_SINGLE_TLV("Out4 Capture Volume",
WM8350_INPUT_MIXER_VOLUME,
1, 7, 0, out_mix_tlv),
- SOC_WM8350_DOUBLE_R_TLV("Out1 Playback Volume",
+ SOC_DOUBLE_R_EXT_TLV("Out1 Playback Volume",
WM8350_LOUT1_VOLUME,
WM8350_ROUT1_VOLUME,
- 2, 63, 0, out_pga_tlv),
+ 2, 63, 0, wm8350_get_volsw_2r,
+ wm8350_put_volsw_2r_vu, out_pga_tlv),
SOC_DOUBLE_R("Out1 Playback ZC Switch",
WM8350_LOUT1_VOLUME,
WM8350_ROUT1_VOLUME, 13, 1, 0),
- SOC_WM8350_DOUBLE_R_TLV("Out2 Playback Volume",
+ SOC_DOUBLE_R_EXT_TLV("Out2 Playback Volume",
WM8350_LOUT2_VOLUME,
WM8350_ROUT2_VOLUME,
- 2, 63, 0, out_pga_tlv),
+ 2, 63, 0, wm8350_get_volsw_2r,
+ wm8350_put_volsw_2r_vu, out_pga_tlv),
SOC_DOUBLE_R("Out2 Playback ZC Switch", WM8350_LOUT2_VOLUME,
WM8350_ROUT2_VOLUME, 13, 1, 0),
SOC_SINGLE("Out2 Right Invert Switch", WM8350_ROUT2_VOLUME, 10, 1, 0),
@@ -705,7 +696,7 @@ static const struct snd_soc_dapm_widget wm8350_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("IN3L"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8350_dapm_routes[] = {
/* left playback mixer */
{"Left Playback Mixer", "Playback Switch", "Left DAC"},
@@ -786,29 +777,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Beep", NULL, "IN3R PGA"},
};
-static int wm8350_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret;
-
- ret = snd_soc_dapm_new_controls(dapm,
- wm8350_dapm_widgets,
- ARRAY_SIZE(wm8350_dapm_widgets));
- if (ret != 0) {
- dev_err(codec->dev, "dapm control register failed\n");
- return ret;
- }
-
- /* set up audio paths */
- ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- if (ret != 0) {
- dev_err(codec->dev, "DAPM route register failed\n");
- return ret;
- }
-
- return 0;
-}
-
static int wm8350_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
@@ -1324,7 +1292,7 @@ static int wm8350_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm8350_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8350_suspend(struct snd_soc_codec *codec)
{
wm8350_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -1520,7 +1488,7 @@ EXPORT_SYMBOL_GPL(wm8350_mic_jack_detect);
SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8350_dai_ops = {
+static const struct snd_soc_dai_ops wm8350_dai_ops = {
.hw_params = wm8350_pcm_hw_params,
.digital_mute = wm8350_mute,
.trigger = wm8350_pcm_trigger,
@@ -1562,7 +1530,8 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
return -EINVAL;
}
- priv = kzalloc(sizeof(struct wm8350_data), GFP_KERNEL);
+ priv = devm_kzalloc(codec->dev, sizeof(struct wm8350_data),
+ GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
snd_soc_codec_set_drvdata(codec, priv);
@@ -1573,7 +1542,7 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
ret = regulator_bulk_get(wm8350->dev, ARRAY_SIZE(priv->supplies),
priv->supplies);
if (ret != 0)
- goto err_priv;
+ return ret;
wm8350->codec.codec = codec;
codec->control_data = wm8350;
@@ -1642,17 +1611,9 @@ static int wm8350_codec_probe(struct snd_soc_codec *codec)
wm8350_mic_handler, 0, "Microphone detect", priv);
- snd_soc_add_controls(codec, wm8350_snd_controls,
- ARRAY_SIZE(wm8350_snd_controls));
- wm8350_add_widgets(codec);
-
wm8350_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
-
-err_priv:
- kfree(priv);
- return ret;
}
static int wm8350_codec_remove(struct snd_soc_codec *codec)
@@ -1685,7 +1646,7 @@ static int wm8350_codec_remove(struct snd_soc_codec *codec)
wm8350_clear_bits(wm8350, WM8350_POWER_MGMT_5, WM8350_CODEC_ENA);
regulator_bulk_free(ARRAY_SIZE(priv->supplies), priv->supplies);
- kfree(priv);
+
return 0;
}
@@ -1697,6 +1658,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8350 = {
.read = wm8350_codec_read,
.write = wm8350_codec_write,
.set_bias_level = wm8350_set_bias_level,
+
+ .controls = wm8350_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8350_snd_controls),
+ .dapm_widgets = wm8350_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8350_dapm_widgets),
+ .dapm_routes = wm8350_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8350_dapm_routes),
};
static int __devinit wm8350_probe(struct platform_device *pdev)
@@ -1720,17 +1688,7 @@ static struct platform_driver wm8350_codec_driver = {
.remove = __devexit_p(wm8350_remove),
};
-static __init int wm8350_init(void)
-{
- return platform_driver_register(&wm8350_codec_driver);
-}
-module_init(wm8350_init);
-
-static __exit void wm8350_exit(void)
-{
- platform_driver_unregister(&wm8350_codec_driver);
-}
-module_exit(wm8350_exit);
+module_platform_driver(wm8350_codec_driver);
MODULE_DESCRIPTION("ASoC WM8350 driver");
MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c
index fbee556cbf35..898979d23010 100644
--- a/sound/soc/codecs/wm8400.c
+++ b/sound/soc/codecs/wm8400.c
@@ -353,13 +353,6 @@ SOC_SINGLE("RIN34 Mute Switch", WM8400_RIGHT_LINE_INPUT_3_4_VOLUME,
};
-/* add non dapm controls */
-static int wm8400_add_controls(struct snd_soc_codec *codec)
-{
- return snd_soc_add_controls(codec, wm8400_snd_controls,
- ARRAY_SIZE(wm8400_snd_controls));
-}
-
/*
* _DAPM_ Controls
*/
@@ -383,7 +376,7 @@ static int inmixer_event (struct snd_soc_dapm_widget *w,
(1 << WM8400_AINRMUX_PWR))) {
reg |= WM8400_AINR_ENA;
} else {
- reg &= ~WM8400_AINL_ENA;
+ reg &= ~WM8400_AINR_ENA;
}
wm8400_write(w->codec, WM8400_POWER_MANAGEMENT_2, reg);
@@ -766,8 +759,8 @@ SND_SOC_DAPM_PGA("ROPGA", WM8400_POWER_MANAGEMENT_3, WM8400_ROPGA_ENA_SHIFT, 0,
NULL, 0),
/* MICBIAS */
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8400_POWER_MANAGEMENT_1,
- WM8400_MIC1BIAS_ENA_SHIFT, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8400_POWER_MANAGEMENT_1,
+ WM8400_MIC1BIAS_ENA_SHIFT, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("LON"),
SND_SOC_DAPM_OUTPUT("LOP"),
@@ -783,7 +776,7 @@ SND_SOC_DAPM_OUTPUT("RON"),
SND_SOC_DAPM_OUTPUT("Internal DAC Sink"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8400_dapm_routes[] = {
/* Make DACs turn on when playing even if not mixed into any outputs */
{"Internal DAC Sink", NULL, "Left DAC"},
{"Internal DAC Sink", NULL, "Right DAC"},
@@ -909,17 +902,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"RON", NULL, "RONMIX"},
};
-static int wm8400_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8400_dapm_widgets,
- ARRAY_SIZE(wm8400_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
/*
* Clock after FLL and dividers
*/
@@ -1059,7 +1041,7 @@ static int wm8400_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
wm8400_write(codec, WM8400_FLL_CONTROL_3, factors.n);
reg = wm8400_read(codec, WM8400_FLL_CONTROL_4);
- reg &= WM8400_FLL_OUTDIV_MASK;
+ reg &= ~WM8400_FLL_OUTDIV_MASK;
reg |= factors.outdiv;
wm8400_write(codec, WM8400_FLL_CONTROL_4, reg);
@@ -1316,7 +1298,7 @@ static int wm8400_set_bias_level(struct snd_soc_codec *codec,
#define WM8400_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8400_dai_ops = {
+static const struct snd_soc_dai_ops wm8400_dai_ops = {
.hw_params = wm8400_hw_params,
.digital_mute = wm8400_mute,
.set_fmt = wm8400_set_dai_fmt,
@@ -1352,7 +1334,7 @@ static struct snd_soc_dai_driver wm8400_dai = {
.ops = &wm8400_dai_ops,
};
-static int wm8400_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8400_suspend(struct snd_soc_codec *codec)
{
wm8400_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -1383,7 +1365,8 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
int ret;
u16 reg;
- priv = kzalloc(sizeof(struct wm8400_priv), GFP_KERNEL);
+ priv = devm_kzalloc(codec->dev, sizeof(struct wm8400_priv),
+ GFP_KERNEL);
if (priv == NULL)
return -ENOMEM;
@@ -1395,7 +1378,7 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
ARRAY_SIZE(power), &power[0]);
if (ret != 0) {
dev_err(codec->dev, "Failed to get regulators: %d\n", ret);
- goto err;
+ return ret;
}
INIT_WORK(&priv->work, wm8400_probe_deferred);
@@ -1420,20 +1403,15 @@ static int wm8400_codec_probe(struct snd_soc_codec *codec)
ret = -EINVAL;
goto err_regulator;
}
- wm8400_add_controls(codec);
- wm8400_add_widgets(codec);
return 0;
err_regulator:
regulator_bulk_free(ARRAY_SIZE(power), power);
-err:
- kfree(priv);
return ret;
}
static int wm8400_codec_remove(struct snd_soc_codec *codec)
{
- struct wm8400_priv *priv = snd_soc_codec_get_drvdata(codec);
u16 reg;
reg = wm8400_read(codec, WM8400_POWER_MANAGEMENT_1);
@@ -1441,7 +1419,6 @@ static int wm8400_codec_remove(struct snd_soc_codec *codec)
reg & (~WM8400_CODEC_ENA));
regulator_bulk_free(ARRAY_SIZE(power), power);
- kfree(priv);
return 0;
}
@@ -1454,6 +1431,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8400 = {
.read = wm8400_read,
.write = wm8400_write,
.set_bias_level = wm8400_set_bias_level,
+
+ .controls = wm8400_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8400_snd_controls),
+ .dapm_widgets = wm8400_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8400_dapm_widgets),
+ .dapm_routes = wm8400_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8400_dapm_routes),
};
static int __devinit wm8400_probe(struct platform_device *pdev)
@@ -1477,17 +1461,7 @@ static struct platform_driver wm8400_codec_driver = {
.remove = __devexit_p(wm8400_remove),
};
-static __init int wm8400_init(void)
-{
- return platform_driver_register(&wm8400_codec_driver);
-}
-module_init(wm8400_init);
-
-static __exit void wm8400_exit(void)
-{
- platform_driver_unregister(&wm8400_codec_driver);
-}
-module_exit(wm8400_exit);
+module_platform_driver(wm8400_codec_driver);
MODULE_DESCRIPTION("ASoC WM8400 driver");
MODULE_AUTHOR("Mark Brown");
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index db0dced74843..9166126bd312 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -17,9 +17,9 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -181,7 +181,7 @@ SND_SOC_DAPM_OUTPUT("SPKOUTP"),
SND_SOC_DAPM_OUTPUT("SPKOUTN"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8510_dapm_routes[] = {
/* Mono output mixer */
{"Mono Mixer", "PCM Playback Switch", "DAC"},
{"Mono Mixer", "Aux Playback Switch", "Aux Input"},
@@ -213,17 +213,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"ADC", NULL, "Boost Mixer"},
};
-static int wm8510_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8510_dapm_widgets,
- ARRAY_SIZE(wm8510_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
struct pll_ {
unsigned int pre_div:4; /* prescale - 1 */
unsigned int n:4;
@@ -479,6 +468,8 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
power1 |= WM8510_POWER1_BIASEN | WM8510_POWER1_BUFIOEN;
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ snd_soc_cache_sync(codec);
+
/* Initial cap charge at VMID 5k */
snd_soc_write(codec, WM8510_POWER1, power1 | 0x3);
mdelay(100);
@@ -506,7 +497,7 @@ static int wm8510_set_bias_level(struct snd_soc_codec *codec,
#define WM8510_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8510_dai_ops = {
+static const struct snd_soc_dai_ops wm8510_dai_ops = {
.hw_params = wm8510_pcm_hw_params,
.digital_mute = wm8510_mute,
.set_fmt = wm8510_set_dai_fmt,
@@ -532,7 +523,7 @@ static struct snd_soc_dai_driver wm8510_dai = {
.symmetric_rates = 1,
};
-static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8510_suspend(struct snd_soc_codec *codec)
{
wm8510_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -540,18 +531,7 @@ static int wm8510_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8510_resume(struct snd_soc_codec *codec)
{
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8510_reg); i++) {
- data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
return 0;
}
@@ -570,9 +550,6 @@ static int wm8510_probe(struct snd_soc_codec *codec)
/* power on device */
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8510_snd_controls,
- ARRAY_SIZE(wm8510_snd_controls));
- wm8510_add_widgets(codec);
return ret;
}
@@ -596,6 +573,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = {
.reg_cache_size = ARRAY_SIZE(wm8510_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default =wm8510_reg,
+
+ .controls = wm8510_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8510_snd_controls),
+ .dapm_widgets = wm8510_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8510_dapm_widgets),
+ .dapm_routes = wm8510_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8510_dapm_routes),
+};
+
+static const struct of_device_id wm8510_of_match[] = {
+ { .compatible = "wlf,wm8510" },
+ { },
};
#if defined(CONFIG_SPI_MASTER)
@@ -628,6 +617,7 @@ static struct spi_driver wm8510_spi_driver = {
.driver = {
.name = "wm8510",
.owner = THIS_MODULE,
+ .of_match_table = wm8510_of_match,
},
.probe = wm8510_spi_probe,
.remove = __devexit_p(wm8510_spi_remove),
@@ -669,8 +659,9 @@ MODULE_DEVICE_TABLE(i2c, wm8510_i2c_id);
static struct i2c_driver wm8510_i2c_driver = {
.driver = {
- .name = "wm8510-codec",
+ .name = "wm8510",
.owner = THIS_MODULE,
+ .of_match_table = wm8510_of_match,
},
.probe = wm8510_i2c_probe,
.remove = __devexit_p(wm8510_i2c_remove),
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c
index 4fd4d8dca0fc..7fea2c3bf7e7 100644
--- a/sound/soc/codecs/wm8523.c
+++ b/sound/soc/codecs/wm8523.c
@@ -17,9 +17,9 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -84,7 +84,7 @@ static const char *wm8523_zd_count_text[] = {
static const struct soc_enum wm8523_zc_count =
SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text);
-static const struct snd_kcontrol_new wm8523_snd_controls[] = {
+static const struct snd_kcontrol_new wm8523_controls[] = {
SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR,
0, 448, 0, dac_tlv),
SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0),
@@ -101,22 +101,11 @@ SND_SOC_DAPM_OUTPUT("LINEVOUTL"),
SND_SOC_DAPM_OUTPUT("LINEVOUTR"),
};
-static const struct snd_soc_dapm_route intercon[] = {
+static const struct snd_soc_dapm_route wm8523_dapm_routes[] = {
{ "LINEVOUTL", NULL, "DAC" },
{ "LINEVOUTR", NULL, "DAC" },
};
-static int wm8523_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8523_dapm_widgets,
- ARRAY_SIZE(wm8523_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
- return 0;
-}
-
static struct {
int value;
int ratio;
@@ -375,7 +364,7 @@ static int wm8523_set_bias_level(struct snd_soc_codec *codec,
#define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8523_dai_ops = {
+static const struct snd_soc_dai_ops wm8523_dai_ops = {
.startup = wm8523_startup,
.hw_params = wm8523_hw_params,
.set_sysclk = wm8523_set_dai_sysclk,
@@ -395,7 +384,7 @@ static struct snd_soc_dai_driver wm8523_dai = {
};
#ifdef CONFIG_PM
-static int wm8523_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8523_suspend(struct snd_soc_codec *codec)
{
wm8523_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -416,7 +405,6 @@ static int wm8523_probe(struct snd_soc_codec *codec)
struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec);
int ret, i;
- codec->hw_write = (hw_write_t)i2c_master_send;
wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0];
wm8523->rate_constraint.count =
ARRAY_SIZE(wm8523->rate_constraint_list);
@@ -479,10 +467,6 @@ static int wm8523_probe(struct snd_soc_codec *codec)
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies);
- snd_soc_add_controls(codec, wm8523_snd_controls,
- ARRAY_SIZE(wm8523_snd_controls));
- wm8523_add_widgets(codec);
-
return 0;
err_enable:
@@ -512,6 +496,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = {
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8523_reg,
.volatile_register = wm8523_volatile_register,
+
+ .controls = wm8523_controls,
+ .num_controls = ARRAY_SIZE(wm8523_controls),
+ .dapm_widgets = wm8523_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets),
+ .dapm_routes = wm8523_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes),
+};
+
+static const struct of_device_id wm8523_of_match[] = {
+ { .compatible = "wlf,wm8523" },
+ { },
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -551,8 +547,9 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id);
static struct i2c_driver wm8523_i2c_driver = {
.driver = {
- .name = "wm8523-codec",
+ .name = "wm8523",
.owner = THIS_MODULE,
+ .of_match_table = wm8523_of_match,
},
.probe = wm8523_i2c_probe,
.remove = __devexit_p(wm8523_i2c_remove),
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 4bbc0a79f01e..211285164d70 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -23,9 +23,9 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -212,7 +212,7 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
reg_cache[reg] = 0;
reg_cache[reg2] = 0;
- ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
if (ret < 0)
return ret;
@@ -223,31 +223,19 @@ static int wm8580_out_vu(struct snd_kcontrol *kcontrol,
return 0;
}
-#define SOC_WM8580_OUT_DOUBLE_R_TLV(xname, reg_left, reg_right, xshift, xmax, \
- xinvert, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw_2r, \
- .get = snd_soc_get_volsw_2r, .put = wm8580_out_vu, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
- .max = xmax, .invert = xinvert} }
-
static const struct snd_kcontrol_new wm8580_snd_controls[] = {
-SOC_WM8580_OUT_DOUBLE_R_TLV("DAC1 Playback Volume",
- WM8580_DIGITAL_ATTENUATION_DACL1,
- WM8580_DIGITAL_ATTENUATION_DACR1,
- 0, 0xff, 0, dac_tlv),
-SOC_WM8580_OUT_DOUBLE_R_TLV("DAC2 Playback Volume",
- WM8580_DIGITAL_ATTENUATION_DACL2,
- WM8580_DIGITAL_ATTENUATION_DACR2,
- 0, 0xff, 0, dac_tlv),
-SOC_WM8580_OUT_DOUBLE_R_TLV("DAC3 Playback Volume",
- WM8580_DIGITAL_ATTENUATION_DACL3,
- WM8580_DIGITAL_ATTENUATION_DACR3,
- 0, 0xff, 0, dac_tlv),
+SOC_DOUBLE_R_EXT_TLV("DAC1 Playback Volume",
+ WM8580_DIGITAL_ATTENUATION_DACL1,
+ WM8580_DIGITAL_ATTENUATION_DACR1,
+ 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
+SOC_DOUBLE_R_EXT_TLV("DAC2 Playback Volume",
+ WM8580_DIGITAL_ATTENUATION_DACL2,
+ WM8580_DIGITAL_ATTENUATION_DACR2,
+ 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
+SOC_DOUBLE_R_EXT_TLV("DAC3 Playback Volume",
+ WM8580_DIGITAL_ATTENUATION_DACL3,
+ WM8580_DIGITAL_ATTENUATION_DACR3,
+ 0, 0xff, 0, snd_soc_get_volsw, wm8580_out_vu, dac_tlv),
SOC_SINGLE("DAC1 Deemphasis Switch", WM8580_DAC_CONTROL3, 0, 1, 0),
SOC_SINGLE("DAC2 Deemphasis Switch", WM8580_DAC_CONTROL3, 1, 1, 0),
@@ -284,7 +272,7 @@ SND_SOC_DAPM_INPUT("AINL"),
SND_SOC_DAPM_INPUT("AINR"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8580_dapm_routes[] = {
{ "VOUT1L", NULL, "DAC1" },
{ "VOUT1R", NULL, "DAC1" },
@@ -298,17 +286,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{ "ADC", NULL, "AINR" },
};
-static int wm8580_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets,
- ARRAY_SIZE(wm8580_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
/* PLL divisors */
struct _pll_div {
u32 prescale:1;
@@ -441,8 +418,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
/* Always disable the PLL - it is not safe to leave it running
* while reprogramming it.
*/
- reg = snd_soc_read(codec, WM8580_PWRDN2);
- snd_soc_write(codec, WM8580_PWRDN2, reg | pwr_mask);
+ snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, pwr_mask);
if (!freq_in || !freq_out)
return 0;
@@ -460,8 +436,7 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
snd_soc_write(codec, WM8580_PLLA4 + offset, reg);
/* All done, turn it on */
- reg = snd_soc_read(codec, WM8580_PWRDN2);
- snd_soc_write(codec, WM8580_PWRDN2, reg & ~pwr_mask);
+ snd_soc_update_bits(codec, WM8580_PWRDN2, pwr_mask, 0);
return 0;
}
@@ -695,7 +670,7 @@ static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id,
{
struct snd_soc_codec *codec = dai->codec;
struct wm8580_priv *wm8580 = snd_soc_codec_get_drvdata(codec);
- int sel, sel_mask, sel_shift;
+ int ret, sel, sel_mask, sel_shift;
switch (dai->driver->id) {
case WM8580_DAI_PAIFRX:
@@ -736,7 +711,11 @@ static int wm8580_set_sysclk(struct snd_soc_dai *dai, int clk_id,
/* We really should validate PLL settings but not yet */
wm8580->sysclk[dai->driver->id] = freq;
- return snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel);
+ ret = snd_soc_update_bits(codec, WM8580_CLKSEL, sel_mask, sel);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
@@ -759,7 +738,6 @@ static int wm8580_digital_mute(struct snd_soc_dai *codec_dai, int mute)
static int wm8580_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 reg;
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
@@ -768,20 +746,19 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
/* Power up and get individual control of the DACs */
- reg = snd_soc_read(codec, WM8580_PWRDN1);
- reg &= ~(WM8580_PWRDN1_PWDN | WM8580_PWRDN1_ALLDACPD);
- snd_soc_write(codec, WM8580_PWRDN1, reg);
+ snd_soc_update_bits(codec, WM8580_PWRDN1,
+ WM8580_PWRDN1_PWDN |
+ WM8580_PWRDN1_ALLDACPD, 0);
/* Make VMID high impedance */
- reg = snd_soc_read(codec, WM8580_ADC_CONTROL1);
- reg &= ~0x100;
- snd_soc_write(codec, WM8580_ADC_CONTROL1, reg);
+ snd_soc_update_bits(codec, WM8580_ADC_CONTROL1,
+ 0x100, 0);
}
break;
case SND_SOC_BIAS_OFF:
- reg = snd_soc_read(codec, WM8580_PWRDN1);
- snd_soc_write(codec, WM8580_PWRDN1, reg | WM8580_PWRDN1_PWDN);
+ snd_soc_update_bits(codec, WM8580_PWRDN1,
+ WM8580_PWRDN1_PWDN, WM8580_PWRDN1_PWDN);
break;
}
codec->dapm.bias_level = level;
@@ -791,7 +768,7 @@ static int wm8580_set_bias_level(struct snd_soc_codec *codec,
#define WM8580_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
+static const struct snd_soc_dai_ops wm8580_dai_ops_playback = {
.set_sysclk = wm8580_set_sysclk,
.hw_params = wm8580_paif_hw_params,
.set_fmt = wm8580_set_paif_dai_fmt,
@@ -800,7 +777,7 @@ static struct snd_soc_dai_ops wm8580_dai_ops_playback = {
.digital_mute = wm8580_digital_mute,
};
-static struct snd_soc_dai_ops wm8580_dai_ops_capture = {
+static const struct snd_soc_dai_ops wm8580_dai_ops_capture = {
.set_sysclk = wm8580_set_sysclk,
.hw_params = wm8580_paif_hw_params,
.set_fmt = wm8580_set_paif_dai_fmt,
@@ -872,10 +849,6 @@ static int wm8580_probe(struct snd_soc_codec *codec)
wm8580_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8580_snd_controls,
- ARRAY_SIZE(wm8580_snd_controls));
- wm8580_add_widgets(codec);
-
return 0;
err_regulator_enable:
@@ -905,6 +878,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = {
.reg_cache_size = ARRAY_SIZE(wm8580_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8580_reg,
+
+ .controls = wm8580_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8580_snd_controls),
+ .dapm_widgets = wm8580_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8580_dapm_widgets),
+ .dapm_routes = wm8580_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8580_dapm_routes),
+};
+
+static const struct of_device_id wm8580_of_match[] = {
+ { .compatible = "wlf,wm8580" },
+ { },
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -943,8 +928,9 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
static struct i2c_driver wm8580_i2c_driver = {
.driver = {
- .name = "wm8580-codec",
+ .name = "wm8580",
.owner = THIS_MODULE,
+ .of_match_table = wm8580_of_match,
},
.probe = wm8580_i2c_probe,
.remove = wm8580_i2c_remove,
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c
index a537e4af6ae7..0b76d1dca5ea 100644
--- a/sound/soc/codecs/wm8711.c
+++ b/sound/soc/codecs/wm8711.c
@@ -3,7 +3,7 @@
*
* Copyright 2006 Wolfson Microelectronics
*
- * Author: Mike Arthur <linux@wolfsonmicro.com>
+ * Author: Mike Arthur <Mike.Arthur@wolfsonmicro.com>
*
* Based on wm8731.c by Richard Purdie
*
@@ -18,9 +18,9 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -150,7 +150,7 @@ static int wm8711_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_codec *codec = dai->codec;
struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
- u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfffc;
+ u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0xfff3;
int i = get_coeff(wm8711->sysclk, params_rate(params));
u16 srate = (coeff_div[i].sr << 2) |
(coeff_div[i].bosr << 1) | coeff_div[i].usb;
@@ -231,7 +231,7 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai,
unsigned int fmt)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 iface = 0;
+ u16 iface = snd_soc_read(codec, WM8711_IFACE) & 0x000c;
/* set master/slave audio interface */
switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
@@ -286,7 +286,6 @@ static int wm8711_set_dai_fmt(struct snd_soc_dai *codec_dai,
return 0;
}
-
static int wm8711_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -299,6 +298,9 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+ snd_soc_cache_sync(codec);
+
snd_soc_write(codec, WM8711_PWR, reg | 0x0040);
break;
case SND_SOC_BIAS_OFF:
@@ -315,7 +317,7 @@ static int wm8711_set_bias_level(struct snd_soc_codec *codec,
#define WM8711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8711_ops = {
+static const struct snd_soc_dai_ops wm8711_ops = {
.prepare = wm8711_pcm_prepare,
.hw_params = wm8711_hw_params,
.shutdown = wm8711_shutdown,
@@ -336,7 +338,7 @@ static struct snd_soc_dai_driver wm8711_dai = {
.ops = &wm8711_ops,
};
-static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8711_suspend(struct snd_soc_codec *codec)
{
snd_soc_write(codec, WM8711_ACTIVE, 0x0);
wm8711_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -345,25 +347,14 @@ static int wm8711_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8711_resume(struct snd_soc_codec *codec)
{
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8711_reg); i++) {
- data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
return 0;
}
static int wm8711_probe(struct snd_soc_codec *codec)
{
struct wm8711_priv *wm8711 = snd_soc_codec_get_drvdata(codec);
- int ret, reg;
+ int ret;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8711->bus_type);
if (ret < 0) {
@@ -380,13 +371,8 @@ static int wm8711_probe(struct snd_soc_codec *codec)
wm8711_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Latch the update bits */
- reg = snd_soc_read(codec, WM8711_LOUT1V);
- snd_soc_write(codec, WM8711_LOUT1V, reg | 0x0100);
- reg = snd_soc_read(codec, WM8711_ROUT1V);
- snd_soc_write(codec, WM8711_ROUT1V, reg | 0x0100);
-
- snd_soc_add_controls(codec, wm8711_snd_controls,
- ARRAY_SIZE(wm8711_snd_controls));
+ snd_soc_update_bits(codec, WM8711_LOUT1V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8711_ROUT1V, 0x0100, 0x0100);
return ret;
@@ -408,12 +394,20 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = {
.reg_cache_size = ARRAY_SIZE(wm8711_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8711_reg,
+ .controls = wm8711_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8711_snd_controls),
.dapm_widgets = wm8711_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(wm8711_dapm_widgets),
.dapm_routes = wm8711_intercon,
.num_dapm_routes = ARRAY_SIZE(wm8711_intercon),
};
+static const struct of_device_id wm8711_of_match[] = {
+ { .compatible = "wlf,wm8711", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8711_of_match);
+
#if defined(CONFIG_SPI_MASTER)
static int __devinit wm8711_spi_probe(struct spi_device *spi)
{
@@ -443,8 +437,9 @@ static int __devexit wm8711_spi_remove(struct spi_device *spi)
static struct spi_driver wm8711_spi_driver = {
.driver = {
- .name = "wm8711-codec",
+ .name = "wm8711",
.owner = THIS_MODULE,
+ .of_match_table = wm8711_of_match,
},
.probe = wm8711_spi_probe,
.remove = __devexit_p(wm8711_spi_remove),
@@ -487,8 +482,9 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id);
static struct i2c_driver wm8711_i2c_driver = {
.driver = {
- .name = "wm8711-codec",
+ .name = "wm8711",
.owner = THIS_MODULE,
+ .of_match_table = wm8711_of_match,
},
.probe = wm8711_i2c_probe,
.remove = __devexit_p(wm8711_i2c_remove),
diff --git a/sound/soc/codecs/wm8727.c b/sound/soc/codecs/wm8727.c
index 748808285119..e81705620718 100644
--- a/sound/soc/codecs/wm8727.c
+++ b/sound/soc/codecs/wm8727.c
@@ -59,7 +59,7 @@ static int __devexit wm8727_remove(struct platform_device *pdev)
static struct platform_driver wm8727_codec_driver = {
.driver = {
- .name = "wm8727-codec",
+ .name = "wm8727",
.owner = THIS_MODULE,
},
@@ -67,17 +67,7 @@ static struct platform_driver wm8727_codec_driver = {
.remove = __devexit_p(wm8727_remove),
};
-static int __init wm8727_init(void)
-{
- return platform_driver_register(&wm8727_codec_driver);
-}
-module_init(wm8727_init);
-
-static void __exit wm8727_exit(void)
-{
- platform_driver_unregister(&wm8727_codec_driver);
-}
-module_exit(wm8727_exit);
+module_platform_driver(wm8727_codec_driver);
MODULE_DESCRIPTION("ASoC wm8727 driver");
MODULE_AUTHOR("Neil Jones");
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
index 86d4718d3a76..fc3d59e49084 100644
--- a/sound/soc/codecs/wm8728.c
+++ b/sound/soc/codecs/wm8728.c
@@ -19,6 +19,7 @@
#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -195,7 +196,7 @@ static int wm8728_set_bias_level(struct snd_soc_codec *codec,
#define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8728_dai_ops = {
+static const struct snd_soc_dai_ops wm8728_dai_ops = {
.hw_params = wm8728_hw_params,
.digital_mute = wm8728_mute,
.set_fmt = wm8728_set_dai_fmt,
@@ -213,7 +214,7 @@ static struct snd_soc_dai_driver wm8728_dai = {
.ops = &wm8728_dai_ops,
};
-static int wm8728_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8728_suspend(struct snd_soc_codec *codec)
{
wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -242,9 +243,6 @@ static int wm8728_probe(struct snd_soc_codec *codec)
/* power on device */
wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8728_snd_controls,
- ARRAY_SIZE(wm8728_snd_controls));
-
return ret;
}
@@ -263,12 +261,20 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = {
.reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8728_reg_defaults,
+ .controls = wm8728_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8728_snd_controls),
.dapm_widgets = wm8728_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(wm8728_dapm_widgets),
.dapm_routes = wm8728_intercon,
.num_dapm_routes = ARRAY_SIZE(wm8728_intercon),
};
+static const struct of_device_id wm8728_of_match[] = {
+ { .compatible = "wlf,wm8728", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8728_of_match);
+
#if defined(CONFIG_SPI_MASTER)
static int __devinit wm8728_spi_probe(struct spi_device *spi)
{
@@ -298,8 +304,9 @@ static int __devexit wm8728_spi_remove(struct spi_device *spi)
static struct spi_driver wm8728_spi_driver = {
.driver = {
- .name = "wm8728-codec",
+ .name = "wm8728",
.owner = THIS_MODULE,
+ .of_match_table = wm8728_of_match,
},
.probe = wm8728_spi_probe,
.remove = __devexit_p(wm8728_spi_remove),
@@ -342,8 +349,9 @@ MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
static struct i2c_driver wm8728_i2c_driver = {
.driver = {
- .name = "wm8728-codec",
+ .name = "wm8728",
.owner = THIS_MODULE,
+ .of_match_table = wm8728_of_match,
},
.probe = wm8728_i2c_probe,
.remove = __devexit_p(wm8728_i2c_remove),
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 76b4361e9b80..a32caa72bd7d 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -19,9 +19,10 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/slab.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -41,7 +42,7 @@ static const char *wm8731_supply_names[WM8731_NUM_SUPPLIES] = {
/* codec private data */
struct wm8731_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[WM8731_NUM_SUPPLIES];
unsigned int sysclk;
int sysclk_type;
@@ -52,16 +53,30 @@ struct wm8731_priv {
/*
* wm8731 register cache
- * We can't read the WM8731 register space when we are
- * using 2 wire for device control, so we cache them instead.
- * There is no point in caching the reset register
*/
-static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
- 0x0097, 0x0097, 0x0079, 0x0079,
- 0x000a, 0x0008, 0x009f, 0x000a,
- 0x0000, 0x0000
+static const struct reg_default wm8731_reg_defaults[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x0079 },
+ { 3, 0x0079 },
+ { 4, 0x000a },
+ { 5, 0x0008 },
+ { 6, 0x009f },
+ { 7, 0x000a },
+ { 8, 0x0000 },
+ { 9, 0x0000 },
};
+static bool wm8731_volatile(struct device *dev, unsigned int reg)
+{
+ return reg == WM8731_RESET;
+}
+
+static bool wm8731_writeable(struct device *dev, unsigned int reg)
+{
+ return reg <= WM8731_RESET;
+}
+
#define wm8731_reset(c) snd_soc_write(c, WM8731_RESET, 0)
static const char *wm8731_input_select[] = {"Line In", "Mic"};
@@ -426,9 +441,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
- int i, ret;
- u8 data[2];
- u16 *cache = codec->reg_cache;
+ int ret;
u16 reg;
switch (level) {
@@ -443,16 +456,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
if (ret != 0)
return ret;
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
- if (cache[i] == wm8731_reg[i])
- continue;
-
- data[0] = (i << 1) | ((cache[i] >> 8)
- & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
+ regcache_sync(wm8731->regmap);
}
/* Clear PWROFF, gate CLKOUT, everything else as-is */
@@ -463,6 +467,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
snd_soc_write(codec, WM8731_PWR, 0xffff);
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies),
wm8731->supplies);
+ regcache_mark_dirty(wm8731->regmap);
break;
}
codec->dapm.bias_level = level;
@@ -474,7 +479,7 @@ static int wm8731_set_bias_level(struct snd_soc_codec *codec,
#define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8731_dai_ops = {
+static const struct snd_soc_dai_ops wm8731_dai_ops = {
.hw_params = wm8731_hw_params,
.digital_mute = wm8731_mute,
.set_sysclk = wm8731_set_dai_sysclk,
@@ -500,7 +505,7 @@ static struct snd_soc_dai_driver wm8731_dai = {
};
#ifdef CONFIG_PM
-static int wm8731_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8731_suspend(struct snd_soc_codec *codec)
{
wm8731_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -523,7 +528,8 @@ static int wm8731_probe(struct snd_soc_codec *codec)
struct wm8731_priv *wm8731 = snd_soc_codec_get_drvdata(codec);
int ret = 0, i;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8731->control_type);
+ codec->control_data = wm8731->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -563,9 +569,6 @@ static int wm8731_probe(struct snd_soc_codec *codec)
/* Disable bypass path by default */
snd_soc_update_bits(codec, WM8731_APANA, 0x8, 0);
- snd_soc_add_controls(codec, wm8731_snd_controls,
- ARRAY_SIZE(wm8731_snd_controls));
-
/* Regulators will have been enabled by bias management */
regulator_bulk_disable(ARRAY_SIZE(wm8731->supplies), wm8731->supplies);
@@ -598,13 +601,32 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = {
.suspend = wm8731_suspend,
.resume = wm8731_resume,
.set_bias_level = wm8731_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8731_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8731_reg,
.dapm_widgets = wm8731_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
.dapm_routes = wm8731_intercon,
.num_dapm_routes = ARRAY_SIZE(wm8731_intercon),
+ .controls = wm8731_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8731_snd_controls),
+};
+
+static const struct of_device_id wm8731_of_match[] = {
+ { .compatible = "wlf,wm8731", },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, wm8731_of_match);
+
+static const struct regmap_config wm8731_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8731_RESET,
+ .volatile_reg = wm8731_volatile,
+ .writeable_reg = wm8731_writeable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8731_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8731_reg_defaults),
};
#if defined(CONFIG_SPI_MASTER)
@@ -617,20 +639,39 @@ static int __devinit wm8731_spi_probe(struct spi_device *spi)
if (wm8731 == NULL)
return -ENOMEM;
- wm8731->control_type = SND_SOC_SPI;
+ wm8731->regmap = regmap_init_spi(spi, &wm8731_regmap);
+ if (IS_ERR(wm8731->regmap)) {
+ ret = PTR_ERR(wm8731->regmap);
+ dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
spi_set_drvdata(spi, wm8731);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8731, &wm8731_dai, 1);
- if (ret < 0)
- kfree(wm8731);
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_regmap;
+ }
+
+ return 0;
+
+err_regmap:
+ regmap_exit(wm8731->regmap);
+err:
+ kfree(wm8731);
return ret;
}
static int __devexit wm8731_spi_remove(struct spi_device *spi)
{
+ struct wm8731_priv *wm8731 = spi_get_drvdata(spi);
+
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8731->regmap);
+ kfree(wm8731);
return 0;
}
@@ -638,6 +679,7 @@ static struct spi_driver wm8731_spi_driver = {
.driver = {
.name = "wm8731",
.owner = THIS_MODULE,
+ .of_match_table = wm8731_of_match,
},
.probe = wm8731_spi_probe,
.remove = __devexit_p(wm8731_spi_remove),
@@ -655,20 +697,38 @@ static __devinit int wm8731_i2c_probe(struct i2c_client *i2c,
if (wm8731 == NULL)
return -ENOMEM;
+ wm8731->regmap = regmap_init_i2c(i2c, &wm8731_regmap);
+ if (IS_ERR(wm8731->regmap)) {
+ ret = PTR_ERR(wm8731->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
i2c_set_clientdata(i2c, wm8731);
- wm8731->control_type = SND_SOC_I2C;
- ret = snd_soc_register_codec(&i2c->dev,
+ ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8731, &wm8731_dai, 1);
- if (ret < 0)
- kfree(wm8731);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_regmap;
+ }
+
+ return 0;
+
+err_regmap:
+ regmap_exit(wm8731->regmap);
+err:
+ kfree(wm8731);
return ret;
}
static __devexit int wm8731_i2c_remove(struct i2c_client *client)
{
+ struct wm8731_priv *wm8731 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8731->regmap);
+ kfree(wm8731);
return 0;
}
@@ -682,6 +742,7 @@ static struct i2c_driver wm8731_i2c_driver = {
.driver = {
.name = "wm8731",
.owner = THIS_MODULE,
+ .of_match_table = wm8731_of_match,
},
.probe = wm8731_i2c_probe,
.remove = __devexit_p(wm8731_i2c_remove),
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c
index 30c67d06a904..4fe9d191e277 100644
--- a/sound/soc/codecs/wm8737.c
+++ b/sound/soc/codecs/wm8737.c
@@ -16,10 +16,10 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -520,7 +520,7 @@ static int wm8737_set_bias_level(struct snd_soc_codec *codec,
#define WM8737_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8737_dai_ops = {
+static const struct snd_soc_dai_ops wm8737_dai_ops = {
.hw_params = wm8737_hw_params,
.set_sysclk = wm8737_set_dai_sysclk,
.set_fmt = wm8737_set_dai_fmt,
@@ -539,7 +539,7 @@ static struct snd_soc_dai_driver wm8737_dai = {
};
#ifdef CONFIG_PM
-static int wm8737_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8737_suspend(struct snd_soc_codec *codec)
{
wm8737_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -599,7 +599,7 @@ static int wm8737_probe(struct snd_soc_codec *codec)
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8737->supplies), wm8737->supplies);
- snd_soc_add_controls(codec, wm8737_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8737_snd_controls,
ARRAY_SIZE(wm8737_snd_controls));
wm8737_add_widgets(codec);
@@ -634,6 +634,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = {
.reg_cache_default = wm8737_reg,
};
+static const struct of_device_id wm8737_of_match[] = {
+ { .compatible = "wlf,wm8737", },
+ { }
+};
+
+MODULE_DEVICE_TABLE(of, wm8737_of_match);
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8737_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
@@ -673,6 +680,7 @@ static struct i2c_driver wm8737_i2c_driver = {
.driver = {
.name = "wm8737",
.owner = THIS_MODULE,
+ .of_match_table = wm8737_of_match,
},
.probe = wm8737_i2c_probe,
.remove = __devexit_p(wm8737_i2c_remove),
@@ -711,6 +719,7 @@ static struct spi_driver wm8737_spi_driver = {
.driver = {
.name = "wm8737",
.owner = THIS_MODULE,
+ .of_match_table = wm8737_of_match,
},
.probe = wm8737_spi_probe,
.remove = __devexit_p(wm8737_spi_remove),
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c
index 25af901fe813..3941f50bf187 100644
--- a/sound/soc/codecs/wm8741.c
+++ b/sound/soc/codecs/wm8741.c
@@ -17,9 +17,10 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -84,24 +85,13 @@ SND_SOC_DAPM_OUTPUT("VOUTRP"),
SND_SOC_DAPM_OUTPUT("VOUTRN"),
};
-static const struct snd_soc_dapm_route intercon[] = {
+static const struct snd_soc_dapm_route wm8741_dapm_routes[] = {
{ "VOUTLP", NULL, "DACL" },
{ "VOUTLN", NULL, "DACL" },
{ "VOUTRP", NULL, "DACR" },
{ "VOUTRN", NULL, "DACR" },
};
-static int wm8741_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8741_dapm_widgets,
- ARRAY_SIZE(wm8741_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon));
-
- return 0;
-}
-
static struct {
int value;
int ratio;
@@ -337,10 +327,10 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
iface |= 0x0004;
break;
case SND_SOC_DAIFMT_DSP_A:
- iface |= 0x0003;
+ iface |= 0x000C;
break;
case SND_SOC_DAIFMT_DSP_B:
- iface |= 0x0013;
+ iface |= 0x001C;
break;
default:
return -EINVAL;
@@ -380,7 +370,7 @@ static int wm8741_set_dai_fmt(struct snd_soc_dai *codec_dai,
#define WM8741_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8741_dai_ops = {
+static const struct snd_soc_dai_ops wm8741_dai_ops = {
.startup = wm8741_startup,
.hw_params = wm8741_hw_params,
.set_sysclk = wm8741_set_dai_sysclk,
@@ -402,15 +392,7 @@ static struct snd_soc_dai_driver wm8741_dai = {
#ifdef CONFIG_PM
static int wm8741_resume(struct snd_soc_codec *codec)
{
- u16 *cache = codec->reg_cache;
- int i;
-
- /* RESTORE REG Cache */
- for (i = 0; i < WM8741_REGISTER_COUNT; i++) {
- if (cache[i] == wm8741_reg_defaults[i] || WM8741_RESET == i)
- continue;
- snd_soc_write(codec, i, cache[i]);
- }
+ snd_soc_cache_sync(codec);
return 0;
}
#else
@@ -422,17 +404,35 @@ static int wm8741_probe(struct snd_soc_codec *codec)
{
struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
int ret = 0;
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
+ wm8741->supplies[i].supply = wm8741_supply_names[i];
+
+ ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies),
+ wm8741->supplies);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
+ goto err;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
+ wm8741->supplies);
+ if (ret != 0) {
+ dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_get;
+ }
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- return ret;
+ goto err_enable;
}
ret = wm8741_reset(codec);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset\n");
- return ret;
+ goto err_enable;
}
/* Change some default settings - latch VU */
@@ -442,79 +442,76 @@ static int wm8741_probe(struct snd_soc_codec *codec)
WM8741_UPDATELM, WM8741_UPDATELM);
snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
WM8741_UPDATERL, WM8741_UPDATERL);
- snd_soc_update_bits(codec, WM8741_DACRLSB_ATTENUATION,
+ snd_soc_update_bits(codec, WM8741_DACRMSB_ATTENUATION,
WM8741_UPDATERM, WM8741_UPDATERM);
- snd_soc_add_controls(codec, wm8741_snd_controls,
- ARRAY_SIZE(wm8741_snd_controls));
- wm8741_add_widgets(codec);
-
dev_dbg(codec->dev, "Successful registration\n");
return ret;
+
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+err_get:
+ regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+err:
+ return ret;
+}
+
+static int wm8741_remove(struct snd_soc_codec *codec)
+{
+ struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec);
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+ regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+
+ return 0;
}
static struct snd_soc_codec_driver soc_codec_dev_wm8741 = {
.probe = wm8741_probe,
+ .remove = wm8741_remove,
.resume = wm8741_resume,
.reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8741_reg_defaults,
+
+ .controls = wm8741_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8741_snd_controls),
+ .dapm_widgets = wm8741_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8741_dapm_widgets),
+ .dapm_routes = wm8741_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8741_dapm_routes),
+};
+
+static const struct of_device_id wm8741_of_match[] = {
+ { .compatible = "wlf,wm8741", },
+ { }
};
+MODULE_DEVICE_TABLE(of, wm8741_of_match);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static int wm8741_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8741_priv *wm8741;
- int ret, i;
+ int ret;
- wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL);
+ wm8741 = devm_kzalloc(&i2c->dev, sizeof(struct wm8741_priv),
+ GFP_KERNEL);
if (wm8741 == NULL)
return -ENOMEM;
- for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++)
- wm8741->supplies[i].supply = wm8741_supply_names[i];
-
- ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies),
- wm8741->supplies);
- if (ret != 0) {
- dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
- goto err;
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies),
- wm8741->supplies);
- if (ret != 0) {
- dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
- }
-
i2c_set_clientdata(i2c, wm8741);
wm8741->control_type = SND_SOC_I2C;
- ret = snd_soc_register_codec(&i2c->dev,
- &soc_codec_dev_wm8741, &wm8741_dai, 1);
- if (ret < 0)
- goto err_enable;
- return ret;
-
-err_enable:
- regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
+ ret = snd_soc_register_codec(&i2c->dev,
+ &soc_codec_dev_wm8741, &wm8741_dai, 1);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
-err:
- kfree(wm8741);
return ret;
}
static int wm8741_i2c_remove(struct i2c_client *client)
{
- struct wm8741_priv *wm8741 = i2c_get_clientdata(client);
-
snd_soc_unregister_codec(&client->dev);
- regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies);
- kfree(i2c_get_clientdata(client));
return 0;
}
@@ -526,8 +523,9 @@ MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id);
static struct i2c_driver wm8741_i2c_driver = {
.driver = {
- .name = "wm8741-codec",
+ .name = "wm8741",
.owner = THIS_MODULE,
+ .of_match_table = wm8741_of_match,
},
.probe = wm8741_i2c_probe,
.remove = wm8741_i2c_remove,
@@ -535,6 +533,42 @@ static struct i2c_driver wm8741_i2c_driver = {
};
#endif
+#if defined(CONFIG_SPI_MASTER)
+static int __devinit wm8741_spi_probe(struct spi_device *spi)
+{
+ struct wm8741_priv *wm8741;
+ int ret;
+
+ wm8741 = devm_kzalloc(&spi->dev, sizeof(struct wm8741_priv),
+ GFP_KERNEL);
+ if (wm8741 == NULL)
+ return -ENOMEM;
+
+ wm8741->control_type = SND_SOC_SPI;
+ spi_set_drvdata(spi, wm8741);
+
+ ret = snd_soc_register_codec(&spi->dev,
+ &soc_codec_dev_wm8741, &wm8741_dai, 1);
+ return ret;
+}
+
+static int __devexit wm8741_spi_remove(struct spi_device *spi)
+{
+ snd_soc_unregister_codec(&spi->dev);
+ return 0;
+}
+
+static struct spi_driver wm8741_spi_driver = {
+ .driver = {
+ .name = "wm8741",
+ .owner = THIS_MODULE,
+ .of_match_table = wm8741_of_match,
+ },
+ .probe = wm8741_spi_probe,
+ .remove = __devexit_p(wm8741_spi_remove),
+};
+#endif /* CONFIG_SPI_MASTER */
+
static int __init wm8741_modinit(void)
{
int ret = 0;
@@ -544,6 +578,13 @@ static int __init wm8741_modinit(void)
if (ret != 0)
pr_err("Failed to register WM8741 I2C driver: %d\n", ret);
#endif
+#if defined(CONFIG_SPI_MASTER)
+ ret = spi_register_driver(&wm8741_spi_driver);
+ if (ret != 0) {
+ printk(KERN_ERR "Failed to register wm8741 SPI driver: %d\n",
+ ret);
+ }
+#endif
return ret;
}
@@ -551,6 +592,9 @@ module_init(wm8741_modinit);
static void __exit wm8741_exit(void)
{
+#if defined(CONFIG_SPI_MASTER)
+ spi_unregister_driver(&wm8741_spi_driver);
+#endif
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8741_i2c_driver);
#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index d0003cc3bcd6..e4c50ce7d9c0 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -18,9 +18,9 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
+#include <linux/of_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -301,7 +301,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("RINPUT3"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8750_dapm_routes[] = {
/* left mixer */
{"Left Mixer", "Playback Switch", "Left DAC"},
{"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
@@ -395,17 +395,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Right ADC", NULL, "Right ADC Mux"},
};
-static int wm8750_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
- ARRAY_SIZE(wm8750_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
struct _coeff_div {
u32 mclk;
u32 rate;
@@ -615,6 +604,8 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ snd_soc_cache_sync(codec);
+
/* Set VMID to 5k */
snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
@@ -640,7 +631,7 @@ static int wm8750_set_bias_level(struct snd_soc_codec *codec,
#define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8750_dai_ops = {
+static const struct snd_soc_dai_ops wm8750_dai_ops = {
.hw_params = wm8750_pcm_hw_params,
.digital_mute = wm8750_mute,
.set_fmt = wm8750_set_dai_fmt,
@@ -664,7 +655,7 @@ static struct snd_soc_dai_driver wm8750_dai = {
.ops = &wm8750_dai_ops,
};
-static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8750_suspend(struct snd_soc_codec *codec)
{
wm8750_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -672,28 +663,14 @@ static int wm8750_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8750_resume(struct snd_soc_codec *codec)
{
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) {
- if (i == WM8750_RESET)
- continue;
- data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
-
wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
return 0;
}
static int wm8750_probe(struct snd_soc_codec *codec)
{
struct wm8750_priv *wm8750 = snd_soc_codec_get_drvdata(codec);
- int reg, ret;
+ int ret;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8750->control_type);
if (ret < 0) {
@@ -711,26 +688,15 @@ static int wm8750_probe(struct snd_soc_codec *codec)
wm8750_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* set the update bits */
- reg = snd_soc_read(codec, WM8750_LDAC);
- snd_soc_write(codec, WM8750_LDAC, reg | 0x0100);
- reg = snd_soc_read(codec, WM8750_RDAC);
- snd_soc_write(codec, WM8750_RDAC, reg | 0x0100);
- reg = snd_soc_read(codec, WM8750_LOUT1V);
- snd_soc_write(codec, WM8750_LOUT1V, reg | 0x0100);
- reg = snd_soc_read(codec, WM8750_ROUT1V);
- snd_soc_write(codec, WM8750_ROUT1V, reg | 0x0100);
- reg = snd_soc_read(codec, WM8750_LOUT2V);
- snd_soc_write(codec, WM8750_LOUT2V, reg | 0x0100);
- reg = snd_soc_read(codec, WM8750_ROUT2V);
- snd_soc_write(codec, WM8750_ROUT2V, reg | 0x0100);
- reg = snd_soc_read(codec, WM8750_LINVOL);
- snd_soc_write(codec, WM8750_LINVOL, reg | 0x0100);
- reg = snd_soc_read(codec, WM8750_RINVOL);
- snd_soc_write(codec, WM8750_RINVOL, reg | 0x0100);
-
- snd_soc_add_controls(codec, wm8750_snd_controls,
- ARRAY_SIZE(wm8750_snd_controls));
- wm8750_add_widgets(codec);
+ snd_soc_update_bits(codec, WM8750_LDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8750_RDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8750_LOUT1V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8750_ROUT1V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8750_LOUT2V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8750_ROUT2V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8750_LINVOL, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8750_RINVOL, 0x0100, 0x0100);
+
return ret;
}
@@ -749,7 +715,21 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = {
.reg_cache_size = ARRAY_SIZE(wm8750_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8750_reg,
+
+ .controls = wm8750_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8750_snd_controls),
+ .dapm_widgets = wm8750_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
+ .dapm_routes = wm8750_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8750_dapm_routes),
+};
+
+static const struct of_device_id wm8750_of_match[] = {
+ { .compatible = "wlf,wm8750", },
+ { .compatible = "wlf,wm8987", },
+ { }
};
+MODULE_DEVICE_TABLE(of, wm8750_of_match);
#if defined(CONFIG_SPI_MASTER)
static int __devinit wm8750_spi_probe(struct spi_device *spi)
@@ -757,7 +737,8 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
struct wm8750_priv *wm8750;
int ret;
- wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
+ wm8750 = devm_kzalloc(&spi->dev, sizeof(struct wm8750_priv),
+ GFP_KERNEL);
if (wm8750 == NULL)
return -ENOMEM;
@@ -766,15 +747,12 @@ static int __devinit wm8750_spi_probe(struct spi_device *spi)
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8750, &wm8750_dai, 1);
- if (ret < 0)
- kfree(wm8750);
return ret;
}
static int __devexit wm8750_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
return 0;
}
@@ -787,8 +765,9 @@ MODULE_DEVICE_TABLE(spi, wm8750_spi_ids);
static struct spi_driver wm8750_spi_driver = {
.driver = {
- .name = "wm8750-codec",
+ .name = "wm8750",
.owner = THIS_MODULE,
+ .of_match_table = wm8750_of_match,
},
.id_table = wm8750_spi_ids,
.probe = wm8750_spi_probe,
@@ -803,7 +782,8 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
struct wm8750_priv *wm8750;
int ret;
- wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
+ wm8750 = devm_kzalloc(&i2c->dev, sizeof(struct wm8750_priv),
+ GFP_KERNEL);
if (wm8750 == NULL)
return -ENOMEM;
@@ -812,15 +792,12 @@ static __devinit int wm8750_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8750, &wm8750_dai, 1);
- if (ret < 0)
- kfree(wm8750);
return ret;
}
static __devexit int wm8750_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
@@ -833,8 +810,9 @@ MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id);
static struct i2c_driver wm8750_i2c_driver = {
.driver = {
- .name = "wm8750-codec",
+ .name = "wm8750",
.owner = THIS_MODULE,
+ .of_match_table = wm8750_of_match,
},
.probe = wm8750_i2c_probe,
.remove = __devexit_p(wm8750_i2c_remove),
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index ffa2ffe5ec11..e27e7b62b365 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -38,7 +38,8 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/of_device.h>
+#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -65,28 +66,86 @@ static int wm8753_voice_write_dai_fmt(struct snd_soc_codec *codec,
* We can't read the WM8753 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
-static const u16 wm8753_reg[] = {
- 0x0000, 0x0008, 0x0000, 0x000a,
- 0x000a, 0x0033, 0x0000, 0x0007,
- 0x00ff, 0x00ff, 0x000f, 0x000f,
- 0x007b, 0x0000, 0x0032, 0x0000,
- 0x00c3, 0x00c3, 0x00c0, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0000, 0x0000, 0x0000,
- 0x0055, 0x0005, 0x0050, 0x0055,
- 0x0050, 0x0055, 0x0050, 0x0055,
- 0x0079, 0x0079, 0x0079, 0x0079,
- 0x0079, 0x0000, 0x0000, 0x0000,
- 0x0000, 0x0097, 0x0097, 0x0000,
- 0x0004, 0x0000, 0x0083, 0x0024,
- 0x01ba, 0x0000, 0x0083, 0x0024,
- 0x01ba, 0x0000, 0x0000, 0x0000
+static const struct reg_default wm8753_reg_defaults[] = {
+ { 0x00, 0x0000 },
+ { 0x01, 0x0008 },
+ { 0x02, 0x0000 },
+ { 0x03, 0x000a },
+ { 0x04, 0x000a },
+ { 0x05, 0x0033 },
+ { 0x06, 0x0000 },
+ { 0x07, 0x0007 },
+ { 0x08, 0x00ff },
+ { 0x09, 0x00ff },
+ { 0x0a, 0x000f },
+ { 0x0b, 0x000f },
+ { 0x0c, 0x007b },
+ { 0x0d, 0x0000 },
+ { 0x0e, 0x0032 },
+ { 0x0f, 0x0000 },
+ { 0x10, 0x00c3 },
+ { 0x11, 0x00c3 },
+ { 0x12, 0x00c0 },
+ { 0x13, 0x0000 },
+ { 0x14, 0x0000 },
+ { 0x15, 0x0000 },
+ { 0x16, 0x0000 },
+ { 0x17, 0x0000 },
+ { 0x18, 0x0000 },
+ { 0x19, 0x0000 },
+ { 0x1a, 0x0000 },
+ { 0x1b, 0x0000 },
+ { 0x1c, 0x0000 },
+ { 0x1d, 0x0000 },
+ { 0x1e, 0x0000 },
+ { 0x1f, 0x0000 },
+ { 0x20, 0x0055 },
+ { 0x21, 0x0005 },
+ { 0x22, 0x0050 },
+ { 0x23, 0x0055 },
+ { 0x24, 0x0050 },
+ { 0x25, 0x0055 },
+ { 0x26, 0x0050 },
+ { 0x27, 0x0055 },
+ { 0x28, 0x0079 },
+ { 0x29, 0x0079 },
+ { 0x2a, 0x0079 },
+ { 0x2b, 0x0079 },
+ { 0x2c, 0x0079 },
+ { 0x2d, 0x0000 },
+ { 0x2e, 0x0000 },
+ { 0x2f, 0x0000 },
+ { 0x30, 0x0000 },
+ { 0x31, 0x0097 },
+ { 0x32, 0x0097 },
+ { 0x33, 0x0000 },
+ { 0x34, 0x0004 },
+ { 0x35, 0x0000 },
+ { 0x36, 0x0083 },
+ { 0x37, 0x0024 },
+ { 0x38, 0x01ba },
+ { 0x39, 0x0000 },
+ { 0x3a, 0x0083 },
+ { 0x3b, 0x0024 },
+ { 0x3c, 0x01ba },
+ { 0x3d, 0x0000 },
+ { 0x3e, 0x0000 },
+ { 0x3f, 0x0000 },
};
+static bool wm8753_volatile(struct device *dev, unsigned int reg)
+{
+ return reg == WM8753_RESET;
+}
+
+static bool wm8753_writeable(struct device *dev, unsigned int reg)
+{
+ return reg <= WM8753_ADCTL2;
+}
+
/* codec private data */
struct wm8753_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
unsigned int sysclk;
unsigned int pcmclk;
@@ -189,6 +248,9 @@ static int wm8753_set_dai(struct snd_kcontrol *kcontrol,
struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
u16 ioctl;
+ if (wm8753->dai_func == ucontrol->value.integer.value[0])
+ return 0;
+
if (codec->active)
return -EBUSY;
@@ -482,7 +544,7 @@ SND_SOC_DAPM_INPUT("MIC2"),
SND_SOC_DAPM_VMID("VREF"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8753_dapm_routes[] = {
/* left mixer */
{"Left Mixer", "Left Playback Switch", "Left DAC"},
{"Left Mixer", "Voice Playback Switch", "Voice DAC"},
@@ -636,17 +698,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"ACOP", NULL, "ALC Mixer"},
};
-static int wm8753_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8753_dapm_widgets,
- ARRAY_SIZE(wm8753_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
/* PLL divisors */
struct _pll_div {
u32 div2:1;
@@ -1322,7 +1373,7 @@ static int wm8753_set_bias_level(struct snd_soc_codec *codec,
* 3. Voice disabled - HIFI over HIFI
* 4. Voice disabled - HIFI over HIFI, uses voice DAI LRC for capture
*/
-static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {
+static const struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {
.hw_params = wm8753_i2s_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_hifi_set_dai_fmt,
@@ -1331,7 +1382,7 @@ static struct snd_soc_dai_ops wm8753_dai_ops_hifi_mode = {
.set_sysclk = wm8753_set_dai_sysclk,
};
-static struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = {
+static const struct snd_soc_dai_ops wm8753_dai_ops_voice_mode = {
.hw_params = wm8753_pcm_hw_params,
.digital_mute = wm8753_mute,
.set_fmt = wm8753_voice_set_dai_fmt,
@@ -1388,28 +1439,18 @@ static void wm8753_work(struct work_struct *work)
wm8753_set_bias_level(codec, dapm->bias_level);
}
-static int wm8753_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8753_suspend(struct snd_soc_codec *codec)
{
wm8753_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ codec->cache_sync = 1;
return 0;
}
static int wm8753_resume(struct snd_soc_codec *codec)
{
- u16 *reg_cache = codec->reg_cache;
- int i;
-
- /* Sync reg_cache with the hardware */
- for (i = 1; i < ARRAY_SIZE(wm8753_reg); i++) {
- if (i == WM8753_RESET)
- continue;
+ struct wm8753_priv *wm8753 = snd_soc_codec_get_drvdata(codec);
- /* No point in writing hardware default values back */
- if (reg_cache[i] == wm8753_reg[i])
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
+ regcache_sync(wm8753->regmap);
wm8753_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1431,7 +1472,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
INIT_DELAYED_WORK(&codec->dapm.delayed_work, wm8753_work);
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8753->control_type);
+ codec->control_data = wm8753->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -1454,8 +1496,8 @@ static int wm8753_probe(struct snd_soc_codec *codec)
/* set the update bits */
snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
- snd_soc_update_bits(codec, WM8753_LDAC, 0x0100, 0x0100);
- snd_soc_update_bits(codec, WM8753_RDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_LADC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8753_RADC, 0x0100, 0x0100);
snd_soc_update_bits(codec, WM8753_LOUT1V, 0x0100, 0x0100);
snd_soc_update_bits(codec, WM8753_ROUT1V, 0x0100, 0x0100);
snd_soc_update_bits(codec, WM8753_LOUT2V, 0x0100, 0x0100);
@@ -1463,10 +1505,6 @@ static int wm8753_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8753_LINVOL, 0x0100, 0x0100);
snd_soc_update_bits(codec, WM8753_RINVOL, 0x0100, 0x0100);
- snd_soc_add_controls(codec, wm8753_snd_controls,
- ARRAY_SIZE(wm8753_snd_controls));
- wm8753_add_widgets(codec);
-
return 0;
}
@@ -1485,9 +1523,32 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = {
.suspend = wm8753_suspend,
.resume = wm8753_resume,
.set_bias_level = wm8753_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8753_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8753_reg,
+
+ .controls = wm8753_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8753_snd_controls),
+ .dapm_widgets = wm8753_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8753_dapm_widgets),
+ .dapm_routes = wm8753_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8753_dapm_routes),
+};
+
+static const struct of_device_id wm8753_of_match[] = {
+ { .compatible = "wlf,wm8753", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8753_of_match);
+
+static const struct regmap_config wm8753_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8753_ADCTL2,
+ .writeable_reg = wm8753_writeable,
+ .volatile_reg = wm8753_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8753_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8753_reg_defaults),
};
#if defined(CONFIG_SPI_MASTER)
@@ -1496,31 +1557,51 @@ static int __devinit wm8753_spi_probe(struct spi_device *spi)
struct wm8753_priv *wm8753;
int ret;
- wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+ wm8753 = devm_kzalloc(&spi->dev, sizeof(struct wm8753_priv),
+ GFP_KERNEL);
if (wm8753 == NULL)
return -ENOMEM;
- wm8753->control_type = SND_SOC_SPI;
spi_set_drvdata(spi, wm8753);
- ret = snd_soc_register_codec(&spi->dev,
- &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
- if (ret < 0)
- kfree(wm8753);
+ wm8753->regmap = regmap_init_spi(spi, &wm8753_regmap);
+ if (IS_ERR(wm8753->regmap)) {
+ ret = PTR_ERR(wm8753->regmap);
+ dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
+ ret = snd_soc_register_codec(&spi->dev, &soc_codec_dev_wm8753,
+ wm8753_dai, ARRAY_SIZE(wm8753_dai));
+ if (ret != 0) {
+ dev_err(&spi->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_regmap;
+ }
+
+ return 0;
+
+err_regmap:
+ regmap_exit(wm8753->regmap);
+err:
return ret;
}
static int __devexit wm8753_spi_remove(struct spi_device *spi)
{
+ struct wm8753_priv *wm8753 = spi_get_drvdata(spi);
+
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8753->regmap);
+ kfree(wm8753);
return 0;
}
static struct spi_driver wm8753_spi_driver = {
.driver = {
- .name = "wm8753-codec",
+ .name = "wm8753",
.owner = THIS_MODULE,
+ .of_match_table = wm8753_of_match,
},
.probe = wm8753_spi_probe,
.remove = __devexit_p(wm8753_spi_remove),
@@ -1534,24 +1615,42 @@ static __devinit int wm8753_i2c_probe(struct i2c_client *i2c,
struct wm8753_priv *wm8753;
int ret;
- wm8753 = kzalloc(sizeof(struct wm8753_priv), GFP_KERNEL);
+ wm8753 = devm_kzalloc(&i2c->dev, sizeof(struct wm8753_priv),
+ GFP_KERNEL);
if (wm8753 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8753);
- wm8753->control_type = SND_SOC_I2C;
- ret = snd_soc_register_codec(&i2c->dev,
- &soc_codec_dev_wm8753, wm8753_dai, ARRAY_SIZE(wm8753_dai));
- if (ret < 0)
- kfree(wm8753);
+ wm8753->regmap = regmap_init_i2c(i2c, &wm8753_regmap);
+ if (IS_ERR(wm8753->regmap)) {
+ ret = PTR_ERR(wm8753->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
+ ret = snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm8753,
+ wm8753_dai, ARRAY_SIZE(wm8753_dai));
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_regmap;
+ }
+
+ return 0;
+
+err_regmap:
+ regmap_exit(wm8753->regmap);
+err:
return ret;
}
static __devexit int wm8753_i2c_remove(struct i2c_client *client)
{
+ struct wm8753_priv *wm8753 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8753->regmap);
return 0;
}
@@ -1563,8 +1662,9 @@ MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id);
static struct i2c_driver wm8753_i2c_driver = {
.driver = {
- .name = "wm8753-codec",
+ .name = "wm8753",
.owner = THIS_MODULE,
+ .of_match_table = wm8753_of_match,
},
.probe = wm8753_i2c_probe,
.remove = __devexit_p(wm8753_i2c_remove),
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c
index 19b92baa9e8c..a5127b4ff9e1 100644
--- a/sound/soc/codecs/wm8770.c
+++ b/sound/soc/codecs/wm8770.c
@@ -14,8 +14,8 @@
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/of_device.h>
#include <linux/pm.h>
-#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@@ -527,7 +527,7 @@ static int wm8770_set_bias_level(struct snd_soc_codec *codec,
#define WM8770_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8770_dai_ops = {
+static const struct snd_soc_dai_ops wm8770_dai_ops = {
.digital_mute = wm8770_mute,
.hw_params = wm8770_hw_params,
.set_fmt = wm8770_set_fmt,
@@ -555,7 +555,7 @@ static struct snd_soc_dai_driver wm8770_dai = {
};
#ifdef CONFIG_PM
-static int wm8770_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8770_suspend(struct snd_soc_codec *codec)
{
wm8770_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -580,8 +580,6 @@ static int wm8770_probe(struct snd_soc_codec *codec)
wm8770 = snd_soc_codec_get_drvdata(codec);
wm8770->codec = codec;
- codec->dapm.idle_bias_off = 1;
-
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8770->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -643,7 +641,7 @@ static int wm8770_probe(struct snd_soc_codec *codec)
/* mute all DACs */
snd_soc_update_bits(codec, WM8770_DACMUTE, 0x10, 0x10);
- snd_soc_add_controls(codec, wm8770_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8770_snd_controls,
ARRAY_SIZE(wm8770_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, wm8770_dapm_widgets,
ARRAY_SIZE(wm8770_dapm_widgets));
@@ -679,18 +677,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = {
.suspend = wm8770_suspend,
.resume = wm8770_resume,
.set_bias_level = wm8770_set_bias_level,
+ .idle_bias_off = true,
.reg_cache_size = ARRAY_SIZE(wm8770_reg_defs),
.reg_word_size = sizeof (u16),
.reg_cache_default = wm8770_reg_defs
};
-#if defined(CONFIG_SPI_MASTER)
+static const struct of_device_id wm8770_of_match[] = {
+ { .compatible = "wlf,wm8770", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8770_of_match);
+
static int __devinit wm8770_spi_probe(struct spi_device *spi)
{
struct wm8770_priv *wm8770;
int ret;
- wm8770 = kzalloc(sizeof(struct wm8770_priv), GFP_KERNEL);
+ wm8770 = devm_kzalloc(&spi->dev, sizeof(struct wm8770_priv),
+ GFP_KERNEL);
if (!wm8770)
return -ENOMEM;
@@ -699,15 +704,13 @@ static int __devinit wm8770_spi_probe(struct spi_device *spi)
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8770, &wm8770_dai, 1);
- if (ret < 0)
- kfree(wm8770);
+
return ret;
}
static int __devexit wm8770_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
return 0;
}
@@ -715,32 +718,28 @@ static struct spi_driver wm8770_spi_driver = {
.driver = {
.name = "wm8770",
.owner = THIS_MODULE,
+ .of_match_table = wm8770_of_match,
},
.probe = wm8770_spi_probe,
.remove = __devexit_p(wm8770_spi_remove)
};
-#endif
static int __init wm8770_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_SPI_MASTER)
ret = spi_register_driver(&wm8770_spi_driver);
if (ret) {
printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8770_modinit);
static void __exit wm8770_exit(void)
{
-#if defined(CONFIG_SPI_MASTER)
spi_unregister_driver(&wm8770_spi_driver);
-#endif
}
module_exit(wm8770_exit);
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c
index 8e7953b1b790..a19db5a0a17a 100644
--- a/sound/soc/codecs/wm8776.c
+++ b/sound/soc/codecs/wm8776.c
@@ -18,7 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/of_device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -30,6 +30,11 @@
#include "wm8776.h"
+enum wm8776_chip_type {
+ WM8775 = 1,
+ WM8776,
+};
+
/* codec private data */
struct wm8776_priv {
enum snd_soc_control_type control_type;
@@ -215,8 +220,6 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
int ratio_shift, master;
int i;
- iface = 0;
-
switch (dai->driver->id) {
case WM8776_DAI_DAC:
iface_reg = WM8776_DACIFCTRL;
@@ -232,20 +235,24 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
-
/* Set word length */
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
+ switch (snd_pcm_format_width(params_format(params))) {
+ case 16:
+ iface = 0;
break;
- case SNDRV_PCM_FORMAT_S20_3LE:
- iface |= 0x10;
+ case 20:
+ iface = 0x10;
break;
- case SNDRV_PCM_FORMAT_S24_LE:
- iface |= 0x20;
+ case 24:
+ iface = 0x20;
break;
- case SNDRV_PCM_FORMAT_S32_LE:
- iface |= 0x30;
+ case 32:
+ iface = 0x30;
break;
+ default:
+ dev_err(codec->dev, "Unsupported sample size: %i\n",
+ snd_pcm_format_width(params_format(params)));
+ return -EINVAL;
}
/* Only need to set MCLK/LRCLK ratio if we're master */
@@ -306,6 +313,8 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ snd_soc_cache_sync(codec);
+
/* Disable the global powerdown; DAPM does the rest */
snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0);
}
@@ -320,22 +329,17 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-#define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
- SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
- SNDRV_PCM_RATE_96000)
-
-
#define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8776_dac_ops = {
+static const struct snd_soc_dai_ops wm8776_dac_ops = {
.digital_mute = wm8776_mute,
.hw_params = wm8776_hw_params,
.set_fmt = wm8776_set_fmt,
.set_sysclk = wm8776_set_sysclk,
};
-static struct snd_soc_dai_ops wm8776_adc_ops = {
+static const struct snd_soc_dai_ops wm8776_adc_ops = {
.hw_params = wm8776_hw_params,
.set_fmt = wm8776_set_fmt,
.set_sysclk = wm8776_set_sysclk,
@@ -349,7 +353,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = {
.stream_name = "Playback",
.channels_min = 2,
.channels_max = 2,
- .rates = WM8776_RATES,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 32000,
+ .rate_max = 192000,
.formats = WM8776_FORMATS,
},
.ops = &wm8776_dac_ops,
@@ -361,7 +367,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
- .rates = WM8776_RATES,
+ .rates = SNDRV_PCM_RATE_CONTINUOUS,
+ .rate_min = 32000,
+ .rate_max = 96000,
.formats = WM8776_FORMATS,
},
.ops = &wm8776_adc_ops,
@@ -369,7 +377,7 @@ static struct snd_soc_dai_driver wm8776_dai[] = {
};
#ifdef CONFIG_PM
-static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8776_suspend(struct snd_soc_codec *codec)
{
wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -378,21 +386,7 @@ static int wm8776_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8776_resume(struct snd_soc_codec *codec)
{
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8776_reg); i++) {
- if (cache[i] == wm8776_reg[i])
- continue;
- data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
-
wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
return 0;
}
#else
@@ -403,7 +397,6 @@ static int wm8776_resume(struct snd_soc_codec *codec)
static int wm8776_probe(struct snd_soc_codec *codec)
{
struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret = 0;
ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type);
@@ -425,12 +418,6 @@ static int wm8776_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100);
snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100);
- snd_soc_add_controls(codec, wm8776_snd_controls,
- ARRAY_SIZE(wm8776_snd_controls));
- snd_soc_dapm_new_controls(dapm, wm8776_dapm_widgets,
- ARRAY_SIZE(wm8776_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes));
-
return ret;
}
@@ -450,15 +437,29 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = {
.reg_cache_size = ARRAY_SIZE(wm8776_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8776_reg,
+
+ .controls = wm8776_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8776_snd_controls),
+ .dapm_widgets = wm8776_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8776_dapm_widgets),
+ .dapm_routes = routes,
+ .num_dapm_routes = ARRAY_SIZE(routes),
};
+static const struct of_device_id wm8776_of_match[] = {
+ { .compatible = "wlf,wm8776", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8776_of_match);
+
#if defined(CONFIG_SPI_MASTER)
static int __devinit wm8776_spi_probe(struct spi_device *spi)
{
struct wm8776_priv *wm8776;
int ret;
- wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
+ wm8776 = devm_kzalloc(&spi->dev, sizeof(struct wm8776_priv),
+ GFP_KERNEL);
if (wm8776 == NULL)
return -ENOMEM;
@@ -467,22 +468,21 @@ static int __devinit wm8776_spi_probe(struct spi_device *spi)
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
- if (ret < 0)
- kfree(wm8776);
+
return ret;
}
static int __devexit wm8776_spi_remove(struct spi_device *spi)
{
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
return 0;
}
static struct spi_driver wm8776_spi_driver = {
.driver = {
- .name = "wm8776-codec",
+ .name = "wm8776",
.owner = THIS_MODULE,
+ .of_match_table = wm8776_of_match,
},
.probe = wm8776_spi_probe,
.remove = __devexit_p(wm8776_spi_remove),
@@ -496,7 +496,8 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
struct wm8776_priv *wm8776;
int ret;
- wm8776 = kzalloc(sizeof(struct wm8776_priv), GFP_KERNEL);
+ wm8776 = devm_kzalloc(&i2c->dev, sizeof(struct wm8776_priv),
+ GFP_KERNEL);
if (wm8776 == NULL)
return -ENOMEM;
@@ -505,28 +506,28 @@ static __devinit int wm8776_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8776, wm8776_dai, ARRAY_SIZE(wm8776_dai));
- if (ret < 0)
- kfree(wm8776);
+
return ret;
}
static __devexit int wm8776_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
static const struct i2c_device_id wm8776_i2c_id[] = {
- { "wm8776", 0 },
+ { "wm8775", WM8775 },
+ { "wm8776", WM8776 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id);
static struct i2c_driver wm8776_i2c_driver = {
.driver = {
- .name = "wm8776-codec",
+ .name = "wm8776",
.owner = THIS_MODULE,
+ .of_match_table = wm8776_of_match,
},
.probe = wm8776_i2c_probe,
.remove = __devexit_p(wm8776_i2c_remove),
diff --git a/sound/soc/codecs/wm8782.c b/sound/soc/codecs/wm8782.c
index a2a09f85ea99..3fdea98f732e 100644
--- a/sound/soc/codecs/wm8782.c
+++ b/sound/soc/codecs/wm8782.c
@@ -60,20 +60,10 @@ static struct platform_driver wm8782_codec_driver = {
.owner = THIS_MODULE,
},
.probe = wm8782_probe,
- .remove = wm8782_remove,
+ .remove = __devexit_p(wm8782_remove),
};
-static int __init wm8782_init(void)
-{
- return platform_driver_register(&wm8782_codec_driver);
-}
-module_init(wm8782_init);
-
-static void __exit wm8782_exit(void)
-{
- platform_driver_unregister(&wm8782_codec_driver);
-}
-module_exit(wm8782_exit);
+module_platform_driver(wm8782_codec_driver);
MODULE_DESCRIPTION("ASoC WM8782 driver");
MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>");
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c
index 9a5e67c5a6bd..6bd1b767b138 100644
--- a/sound/soc/codecs/wm8804.c
+++ b/sound/soc/codecs/wm8804.c
@@ -16,7 +16,9 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/of_device.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -34,45 +36,33 @@ static const char *wm8804_supply_names[WM8804_NUM_SUPPLIES] = {
"DVDD"
};
-static const u8 wm8804_reg_defs[] = {
- 0x05, /* R0 - RST/DEVID1 */
- 0x88, /* R1 - DEVID2 */
- 0x04, /* R2 - DEVREV */
- 0x21, /* R3 - PLL1 */
- 0xFD, /* R4 - PLL2 */
- 0x36, /* R5 - PLL3 */
- 0x07, /* R6 - PLL4 */
- 0x16, /* R7 - PLL5 */
- 0x18, /* R8 - PLL6 */
- 0xFF, /* R9 - SPDMODE */
- 0x00, /* R10 - INTMASK */
- 0x00, /* R11 - INTSTAT */
- 0x00, /* R12 - SPDSTAT */
- 0x00, /* R13 - RXCHAN1 */
- 0x00, /* R14 - RXCHAN2 */
- 0x00, /* R15 - RXCHAN3 */
- 0x00, /* R16 - RXCHAN4 */
- 0x00, /* R17 - RXCHAN5 */
- 0x00, /* R18 - SPDTX1 */
- 0x00, /* R19 - SPDTX2 */
- 0x00, /* R20 - SPDTX3 */
- 0x71, /* R21 - SPDTX4 */
- 0x0B, /* R22 - SPDTX5 */
- 0x70, /* R23 - GPO0 */
- 0x57, /* R24 - GPO1 */
- 0x00, /* R25 */
- 0x42, /* R26 - GPO2 */
- 0x06, /* R27 - AIFTX */
- 0x06, /* R28 - AIFRX */
- 0x80, /* R29 - SPDRX1 */
- 0x07, /* R30 - PWRDN */
+static const struct reg_default wm8804_reg_defaults[] = {
+ { 3, 0x21 }, /* R3 - PLL1 */
+ { 4, 0xFD }, /* R4 - PLL2 */
+ { 5, 0x36 }, /* R5 - PLL3 */
+ { 6, 0x07 }, /* R6 - PLL4 */
+ { 7, 0x16 }, /* R7 - PLL5 */
+ { 8, 0x18 }, /* R8 - PLL6 */
+ { 9, 0xFF }, /* R9 - SPDMODE */
+ { 10, 0x00 }, /* R10 - INTMASK */
+ { 18, 0x00 }, /* R18 - SPDTX1 */
+ { 19, 0x00 }, /* R19 - SPDTX2 */
+ { 20, 0x00 }, /* R20 - SPDTX3 */
+ { 21, 0x71 }, /* R21 - SPDTX4 */
+ { 22, 0x0B }, /* R22 - SPDTX5 */
+ { 23, 0x70 }, /* R23 - GPO0 */
+ { 24, 0x57 }, /* R24 - GPO1 */
+ { 26, 0x42 }, /* R26 - GPO2 */
+ { 27, 0x06 }, /* R27 - AIFTX */
+ { 28, 0x06 }, /* R28 - AIFRX */
+ { 29, 0x80 }, /* R29 - SPDRX1 */
+ { 30, 0x07 }, /* R30 - PWRDN */
};
struct wm8804_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[WM8804_NUM_SUPPLIES];
struct notifier_block disable_nb[WM8804_NUM_SUPPLIES];
- struct snd_soc_codec *codec;
};
static int txsrc_get(struct snd_kcontrol *kcontrol,
@@ -93,7 +83,7 @@ static int wm8804_regulator_event_##n(struct notifier_block *nb, \
struct wm8804_priv *wm8804 = container_of(nb, struct wm8804_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- wm8804->codec->cache_sync = 1; \
+ regcache_mark_dirty(wm8804->regmap); \
} \
return 0; \
}
@@ -175,7 +165,7 @@ static int txsrc_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8804_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM8804_RST_DEVID1:
@@ -188,12 +178,10 @@ static int wm8804_volatile(struct snd_soc_codec *codec, unsigned int reg)
case WM8804_RXCHAN3:
case WM8804_RXCHAN4:
case WM8804_RXCHAN5:
- return 1;
+ return true;
default:
- break;
+ return false;
}
-
- return 0;
}
static int wm8804_reset(struct snd_soc_codec *codec)
@@ -481,24 +469,6 @@ static int wm8804_set_clkdiv(struct snd_soc_dai *dai,
return 0;
}
-static void wm8804_sync_cache(struct snd_soc_codec *codec)
-{
- short i;
- u8 *cache;
-
- if (!codec->cache_sync)
- return;
-
- codec->cache_only = 0;
- cache = codec->reg_cache;
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- if (i == WM8804_RST_DEVID1 || cache[i] == wm8804_reg_defs[i])
- continue;
- snd_soc_write(codec, i, cache[i]);
- }
- codec->cache_sync = 0;
-}
-
static int wm8804_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -523,7 +493,7 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
ret);
return ret;
}
- wm8804_sync_cache(codec);
+ regcache_sync(wm8804->regmap);
}
/* power down the OSC and the PLL */
snd_soc_update_bits(codec, WM8804_PWRDN, 0x9, 0x9);
@@ -541,7 +511,7 @@ static int wm8804_set_bias_level(struct snd_soc_codec *codec,
}
#ifdef CONFIG_PM
-static int wm8804_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8804_suspend(struct snd_soc_codec *codec)
{
wm8804_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -578,11 +548,10 @@ static int wm8804_probe(struct snd_soc_codec *codec)
int i, id1, id2, ret;
wm8804 = snd_soc_codec_get_drvdata(codec);
- wm8804->codec = codec;
- codec->dapm.idle_bias_off = 1;
+ codec->control_data = wm8804->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 8, wm8804->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
return ret;
@@ -635,8 +604,7 @@ static int wm8804_probe(struct snd_soc_codec *codec)
id2 = (id2 << 8) | id1;
- if (id2 != ((wm8804_reg_defs[WM8804_DEVID2] << 8)
- | wm8804_reg_defs[WM8804_RST_DEVID1])) {
+ if (id2 != 0x8805) {
dev_err(codec->dev, "Invalid device ID: %#x\n", id2);
ret = -EINVAL;
goto err_reg_enable;
@@ -658,8 +626,6 @@ static int wm8804_probe(struct snd_soc_codec *codec)
wm8804_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8804_snd_controls,
- ARRAY_SIZE(wm8804_snd_controls));
return 0;
err_reg_enable:
@@ -669,7 +635,7 @@ err_reg_get:
return ret;
}
-static struct snd_soc_dai_ops wm8804_dai_ops = {
+static const struct snd_soc_dai_ops wm8804_dai_ops = {
.hw_params = wm8804_hw_params,
.set_fmt = wm8804_set_fmt,
.set_sysclk = wm8804_set_sysclk,
@@ -711,10 +677,28 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = {
.suspend = wm8804_suspend,
.resume = wm8804_resume,
.set_bias_level = wm8804_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8804_reg_defs),
- .reg_word_size = sizeof(u8),
- .reg_cache_default = wm8804_reg_defs,
- .volatile_register = wm8804_volatile
+ .idle_bias_off = true,
+
+ .controls = wm8804_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8804_snd_controls),
+};
+
+static const struct of_device_id wm8804_of_match[] = {
+ { .compatible = "wlf,wm8804", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8804_of_match);
+
+static struct regmap_config wm8804_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 8,
+
+ .max_register = WM8804_MAX_REGISTER,
+ .volatile_reg = wm8804_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8804_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8804_reg_defaults),
};
#if defined(CONFIG_SPI_MASTER)
@@ -723,24 +707,29 @@ static int __devinit wm8804_spi_probe(struct spi_device *spi)
struct wm8804_priv *wm8804;
int ret;
- wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+ wm8804 = devm_kzalloc(&spi->dev, sizeof *wm8804, GFP_KERNEL);
if (!wm8804)
return -ENOMEM;
- wm8804->control_type = SND_SOC_SPI;
+ wm8804->regmap = regmap_init_spi(spi, &wm8804_regmap_config);
+ if (IS_ERR(wm8804->regmap)) {
+ ret = PTR_ERR(wm8804->regmap);
+ return ret;
+ }
+
spi_set_drvdata(spi, wm8804);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8804, &wm8804_dai, 1);
- if (ret < 0)
- kfree(wm8804);
+
return ret;
}
static int __devexit wm8804_spi_remove(struct spi_device *spi)
{
+ struct wm8804_priv *wm8804 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8804->regmap);
return 0;
}
@@ -748,6 +737,7 @@ static struct spi_driver wm8804_spi_driver = {
.driver = {
.name = "wm8804",
.owner = THIS_MODULE,
+ .of_match_table = wm8804_of_match,
},
.probe = wm8804_spi_probe,
.remove = __devexit_p(wm8804_spi_remove)
@@ -761,24 +751,37 @@ static __devinit int wm8804_i2c_probe(struct i2c_client *i2c,
struct wm8804_priv *wm8804;
int ret;
- wm8804 = kzalloc(sizeof *wm8804, GFP_KERNEL);
+ wm8804 = devm_kzalloc(&i2c->dev, sizeof *wm8804, GFP_KERNEL);
if (!wm8804)
return -ENOMEM;
- wm8804->control_type = SND_SOC_I2C;
+ wm8804->regmap = regmap_init_i2c(i2c, &wm8804_regmap_config);
+ if (IS_ERR(wm8804->regmap)) {
+ ret = PTR_ERR(wm8804->regmap);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, wm8804);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8804, &wm8804_dai, 1);
- if (ret < 0)
- kfree(wm8804);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(wm8804->regmap);
return ret;
}
-static __devexit int wm8804_i2c_remove(struct i2c_client *client)
+static __devexit int wm8804_i2c_remove(struct i2c_client *i2c)
{
- snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ struct wm8804_priv *wm8804 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ regmap_exit(wm8804->regmap);
+
return 0;
}
@@ -792,6 +795,7 @@ static struct i2c_driver wm8804_i2c_driver = {
.driver = {
.name = "wm8804",
.owner = THIS_MODULE,
+ .of_match_table = wm8804_of_match,
},
.probe = wm8804_i2c_probe,
.remove = __devexit_p(wm8804_i2c_remove),
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 082040eda8a2..f18c554efc98 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -24,7 +24,6 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -110,8 +109,8 @@
#define WM8900_REG_CLOCKING1_BCLK_DIR 0x1
#define WM8900_REG_CLOCKING1_MCLK_SRC 0x100
-#define WM8900_REG_CLOCKING1_BCLK_MASK (~0x01e)
-#define WM8900_REG_CLOCKING1_OPCLK_MASK (~0x7000)
+#define WM8900_REG_CLOCKING1_BCLK_MASK 0x01e
+#define WM8900_REG_CLOCKING1_OPCLK_MASK 0x7000
#define WM8900_REG_CLOCKING2_ADC_CLKDIV 0xe0
#define WM8900_REG_CLOCKING2_DAC_CLKDIV 0x1c
@@ -135,7 +134,7 @@
#define WM8900_REG_HPCTL1_HP_SHORT 0x08
#define WM8900_REG_HPCTL1_HP_SHORT2 0x04
-#define WM8900_LRC_MASK 0xfc00
+#define WM8900_LRC_MASK 0x03ff
struct wm8900_priv {
enum snd_soc_control_type control_type;
@@ -513,7 +512,7 @@ SND_SOC_DAPM_MIXER("Right Input Mixer", WM8900_REG_POWER2, 4, 0,
wm8900_rinmix_controls,
ARRAY_SIZE(wm8900_rinmix_controls)),
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8900_REG_POWER1, 4, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias", WM8900_REG_POWER1, 4, 0, NULL, 0),
SND_SOC_DAPM_ADC("ADCL", "Left HiFi Capture", WM8900_REG_POWER2, 1, 0),
SND_SOC_DAPM_ADC("ADCR", "Right HiFi Capture", WM8900_REG_POWER2, 0, 0),
@@ -543,7 +542,7 @@ SND_SOC_DAPM_MIXER("Right Output Mixer", WM8900_REG_POWER3, 2, 0,
};
/* Target, Path, Source */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8900_dapm_routes[] = {
/* Inputs */
{"Left Input PGA", "LINPUT1 Switch", "LINPUT1"},
{"Left Input PGA", "LINPUT2 Switch", "LINPUT2"},
@@ -607,17 +606,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"HP_R", NULL, "Headphone Amplifier"},
};
-static int wm8900_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8900_dapm_widgets,
- ARRAY_SIZE(wm8900_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
static int wm8900_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -742,26 +730,20 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
{
struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
struct _fll_div fll_div;
- unsigned int reg;
if (wm8900->fll_in == freq_in && wm8900->fll_out == freq_out)
return 0;
/* The digital side should be disabled during any change. */
- reg = snd_soc_read(codec, WM8900_REG_POWER1);
- snd_soc_write(codec, WM8900_REG_POWER1,
- reg & (~WM8900_REG_POWER1_FLL_ENA));
+ snd_soc_update_bits(codec, WM8900_REG_POWER1,
+ WM8900_REG_POWER1_FLL_ENA, 0);
/* Disable the FLL? */
if (!freq_in || !freq_out) {
- reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
- snd_soc_write(codec, WM8900_REG_CLOCKING1,
- reg & (~WM8900_REG_CLOCKING1_MCLK_SRC));
-
- reg = snd_soc_read(codec, WM8900_REG_FLLCTL1);
- snd_soc_write(codec, WM8900_REG_FLLCTL1,
- reg & (~WM8900_REG_FLLCTL1_OSC_ENA));
-
+ snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+ WM8900_REG_CLOCKING1_MCLK_SRC, 0);
+ snd_soc_update_bits(codec, WM8900_REG_FLLCTL1,
+ WM8900_REG_FLLCTL1_OSC_ENA, 0);
wm8900->fll_in = freq_in;
wm8900->fll_out = freq_out;
@@ -796,15 +778,14 @@ static int wm8900_set_fll(struct snd_soc_codec *codec,
else
snd_soc_write(codec, WM8900_REG_FLLCTL6, 0);
- reg = snd_soc_read(codec, WM8900_REG_POWER1);
- snd_soc_write(codec, WM8900_REG_POWER1,
- reg | WM8900_REG_POWER1_FLL_ENA);
+ snd_soc_update_bits(codec, WM8900_REG_POWER1,
+ WM8900_REG_POWER1_FLL_ENA,
+ WM8900_REG_POWER1_FLL_ENA);
reenable:
- reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
- snd_soc_write(codec, WM8900_REG_CLOCKING1,
- reg | WM8900_REG_CLOCKING1_MCLK_SRC);
-
+ snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+ WM8900_REG_CLOCKING1_MCLK_SRC,
+ WM8900_REG_CLOCKING1_MCLK_SRC);
return 0;
}
@@ -818,43 +799,35 @@ static int wm8900_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
int div_id, int div)
{
struct snd_soc_codec *codec = codec_dai->codec;
- unsigned int reg;
switch (div_id) {
case WM8900_BCLK_DIV:
- reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
- snd_soc_write(codec, WM8900_REG_CLOCKING1,
- div | (reg & WM8900_REG_CLOCKING1_BCLK_MASK));
+ snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+ WM8900_REG_CLOCKING1_BCLK_MASK, div);
break;
case WM8900_OPCLK_DIV:
- reg = snd_soc_read(codec, WM8900_REG_CLOCKING1);
- snd_soc_write(codec, WM8900_REG_CLOCKING1,
- div | (reg & WM8900_REG_CLOCKING1_OPCLK_MASK));
+ snd_soc_update_bits(codec, WM8900_REG_CLOCKING1,
+ WM8900_REG_CLOCKING1_OPCLK_MASK, div);
break;
case WM8900_DAC_LRCLK:
- reg = snd_soc_read(codec, WM8900_REG_AUDIO4);
- snd_soc_write(codec, WM8900_REG_AUDIO4,
- div | (reg & WM8900_LRC_MASK));
+ snd_soc_update_bits(codec, WM8900_REG_AUDIO4,
+ WM8900_LRC_MASK, div);
break;
case WM8900_ADC_LRCLK:
- reg = snd_soc_read(codec, WM8900_REG_AUDIO3);
- snd_soc_write(codec, WM8900_REG_AUDIO3,
- div | (reg & WM8900_LRC_MASK));
+ snd_soc_update_bits(codec, WM8900_REG_AUDIO3,
+ WM8900_LRC_MASK, div);
break;
case WM8900_DAC_CLKDIV:
- reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
- snd_soc_write(codec, WM8900_REG_CLOCKING2,
- div | (reg & WM8900_REG_CLOCKING2_DAC_CLKDIV));
+ snd_soc_update_bits(codec, WM8900_REG_CLOCKING2,
+ WM8900_REG_CLOCKING2_DAC_CLKDIV, div);
break;
case WM8900_ADC_CLKDIV:
- reg = snd_soc_read(codec, WM8900_REG_CLOCKING2);
- snd_soc_write(codec, WM8900_REG_CLOCKING2,
- div | (reg & WM8900_REG_CLOCKING2_ADC_CLKDIV));
+ snd_soc_update_bits(codec, WM8900_REG_CLOCKING2,
+ WM8900_REG_CLOCKING2_ADC_CLKDIV, div);
break;
case WM8900_LRCLK_MODE:
- reg = snd_soc_read(codec, WM8900_REG_DACCTRL);
- snd_soc_write(codec, WM8900_REG_DACCTRL,
- div | (reg & WM8900_REG_DACCTRL_AIF_LRCLKRATE));
+ snd_soc_update_bits(codec, WM8900_REG_DACCTRL,
+ WM8900_REG_DACCTRL_AIF_LRCLKRATE, div);
break;
default:
return -EINVAL;
@@ -1002,7 +975,7 @@ static int wm8900_digital_mute(struct snd_soc_dai *codec_dai, int mute)
(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
SNDRV_PCM_FORMAT_S24_LE)
-static struct snd_soc_dai_ops wm8900_dai_ops = {
+static const struct snd_soc_dai_ops wm8900_dai_ops = {
.hw_params = wm8900_hw_params,
.set_clkdiv = wm8900_set_dai_clkdiv,
.set_pll = wm8900_set_dai_pll,
@@ -1037,12 +1010,12 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_ON:
/* Enable thermal shutdown */
- reg = snd_soc_read(codec, WM8900_REG_GPIO);
- snd_soc_write(codec, WM8900_REG_GPIO,
- reg | WM8900_REG_GPIO_TEMP_ENA);
- reg = snd_soc_read(codec, WM8900_REG_ADDCTL);
- snd_soc_write(codec, WM8900_REG_ADDCTL,
- reg | WM8900_REG_ADDCTL_TEMP_SD);
+ snd_soc_update_bits(codec, WM8900_REG_GPIO,
+ WM8900_REG_GPIO_TEMP_ENA,
+ WM8900_REG_GPIO_TEMP_ENA);
+ snd_soc_update_bits(codec, WM8900_REG_ADDCTL,
+ WM8900_REG_ADDCTL_TEMP_SD,
+ WM8900_REG_ADDCTL_TEMP_SD);
break;
case SND_SOC_BIAS_PREPARE:
@@ -1122,7 +1095,7 @@ static int wm8900_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm8900_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8900_suspend(struct snd_soc_codec *codec)
{
struct wm8900_priv *wm8900 = snd_soc_codec_get_drvdata(codec);
int fll_out = wm8900->fll_out;
@@ -1205,34 +1178,20 @@ static int wm8900_probe(struct snd_soc_codec *codec)
wm8900_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Latch the volume update bits */
- snd_soc_write(codec, WM8900_REG_LINVOL,
- snd_soc_read(codec, WM8900_REG_LINVOL) | 0x100);
- snd_soc_write(codec, WM8900_REG_RINVOL,
- snd_soc_read(codec, WM8900_REG_RINVOL) | 0x100);
- snd_soc_write(codec, WM8900_REG_LOUT1CTL,
- snd_soc_read(codec, WM8900_REG_LOUT1CTL) | 0x100);
- snd_soc_write(codec, WM8900_REG_ROUT1CTL,
- snd_soc_read(codec, WM8900_REG_ROUT1CTL) | 0x100);
- snd_soc_write(codec, WM8900_REG_LOUT2CTL,
- snd_soc_read(codec, WM8900_REG_LOUT2CTL) | 0x100);
- snd_soc_write(codec, WM8900_REG_ROUT2CTL,
- snd_soc_read(codec, WM8900_REG_ROUT2CTL) | 0x100);
- snd_soc_write(codec, WM8900_REG_LDAC_DV,
- snd_soc_read(codec, WM8900_REG_LDAC_DV) | 0x100);
- snd_soc_write(codec, WM8900_REG_RDAC_DV,
- snd_soc_read(codec, WM8900_REG_RDAC_DV) | 0x100);
- snd_soc_write(codec, WM8900_REG_LADC_DV,
- snd_soc_read(codec, WM8900_REG_LADC_DV) | 0x100);
- snd_soc_write(codec, WM8900_REG_RADC_DV,
- snd_soc_read(codec, WM8900_REG_RADC_DV) | 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_LINVOL, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_RINVOL, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_LOUT1CTL, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_ROUT1CTL, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_LOUT2CTL, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_ROUT2CTL, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_LDAC_DV, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_RDAC_DV, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_LADC_DV, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8900_REG_RADC_DV, 0x100, 0x100);
/* Set the DAC and mixer output bias */
snd_soc_write(codec, WM8900_REG_OUTBIASCTL, 0x81);
- snd_soc_add_controls(codec, wm8900_snd_controls,
- ARRAY_SIZE(wm8900_snd_controls));
- wm8900_add_widgets(codec);
-
return 0;
}
@@ -1253,6 +1212,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8900 = {
.reg_cache_size = ARRAY_SIZE(wm8900_reg_defaults),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8900_reg_defaults,
+
+ .controls = wm8900_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8900_snd_controls),
+ .dapm_widgets = wm8900_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8900_dapm_widgets),
+ .dapm_routes = wm8900_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8900_dapm_routes),
};
#if defined(CONFIG_SPI_MASTER)
@@ -1284,7 +1250,7 @@ static int __devexit wm8900_spi_remove(struct spi_device *spi)
static struct spi_driver wm8900_spi_driver = {
.driver = {
- .name = "wm8900-codec",
+ .name = "wm8900",
.owner = THIS_MODULE,
},
.probe = wm8900_spi_probe,
@@ -1328,7 +1294,7 @@ MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
static struct i2c_driver wm8900_i2c_driver = {
.driver = {
- .name = "wm8900-codec",
+ .name = "wm8900",
.owner = THIS_MODULE,
},
.probe = wm8900_i2c_probe,
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 4ad8ebd290e3..c91fb2f99c13 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -23,8 +23,9 @@
#include <linux/gpio.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
+#include <linux/irq.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/pcm.h>
@@ -38,184 +39,85 @@
#include "wm8903.h"
/* Register defaults at reset */
-static u16 wm8903_reg_defaults[] = {
- 0x8903, /* R0 - SW Reset and ID */
- 0x0000, /* R1 - Revision Number */
- 0x0000, /* R2 */
- 0x0000, /* R3 */
- 0x0018, /* R4 - Bias Control 0 */
- 0x0000, /* R5 - VMID Control 0 */
- 0x0000, /* R6 - Mic Bias Control 0 */
- 0x0000, /* R7 */
- 0x0001, /* R8 - Analogue DAC 0 */
- 0x0000, /* R9 */
- 0x0001, /* R10 - Analogue ADC 0 */
- 0x0000, /* R11 */
- 0x0000, /* R12 - Power Management 0 */
- 0x0000, /* R13 - Power Management 1 */
- 0x0000, /* R14 - Power Management 2 */
- 0x0000, /* R15 - Power Management 3 */
- 0x0000, /* R16 - Power Management 4 */
- 0x0000, /* R17 - Power Management 5 */
- 0x0000, /* R18 - Power Management 6 */
- 0x0000, /* R19 */
- 0x0400, /* R20 - Clock Rates 0 */
- 0x0D07, /* R21 - Clock Rates 1 */
- 0x0000, /* R22 - Clock Rates 2 */
- 0x0000, /* R23 */
- 0x0050, /* R24 - Audio Interface 0 */
- 0x0242, /* R25 - Audio Interface 1 */
- 0x0008, /* R26 - Audio Interface 2 */
- 0x0022, /* R27 - Audio Interface 3 */
- 0x0000, /* R28 */
- 0x0000, /* R29 */
- 0x00C0, /* R30 - DAC Digital Volume Left */
- 0x00C0, /* R31 - DAC Digital Volume Right */
- 0x0000, /* R32 - DAC Digital 0 */
- 0x0000, /* R33 - DAC Digital 1 */
- 0x0000, /* R34 */
- 0x0000, /* R35 */
- 0x00C0, /* R36 - ADC Digital Volume Left */
- 0x00C0, /* R37 - ADC Digital Volume Right */
- 0x0000, /* R38 - ADC Digital 0 */
- 0x0073, /* R39 - Digital Microphone 0 */
- 0x09BF, /* R40 - DRC 0 */
- 0x3241, /* R41 - DRC 1 */
- 0x0020, /* R42 - DRC 2 */
- 0x0000, /* R43 - DRC 3 */
- 0x0085, /* R44 - Analogue Left Input 0 */
- 0x0085, /* R45 - Analogue Right Input 0 */
- 0x0044, /* R46 - Analogue Left Input 1 */
- 0x0044, /* R47 - Analogue Right Input 1 */
- 0x0000, /* R48 */
- 0x0000, /* R49 */
- 0x0008, /* R50 - Analogue Left Mix 0 */
- 0x0004, /* R51 - Analogue Right Mix 0 */
- 0x0000, /* R52 - Analogue Spk Mix Left 0 */
- 0x0000, /* R53 - Analogue Spk Mix Left 1 */
- 0x0000, /* R54 - Analogue Spk Mix Right 0 */
- 0x0000, /* R55 - Analogue Spk Mix Right 1 */
- 0x0000, /* R56 */
- 0x002D, /* R57 - Analogue OUT1 Left */
- 0x002D, /* R58 - Analogue OUT1 Right */
- 0x0039, /* R59 - Analogue OUT2 Left */
- 0x0039, /* R60 - Analogue OUT2 Right */
- 0x0100, /* R61 */
- 0x0139, /* R62 - Analogue OUT3 Left */
- 0x0139, /* R63 - Analogue OUT3 Right */
- 0x0000, /* R64 */
- 0x0000, /* R65 - Analogue SPK Output Control 0 */
- 0x0000, /* R66 */
- 0x0010, /* R67 - DC Servo 0 */
- 0x0100, /* R68 */
- 0x00A4, /* R69 - DC Servo 2 */
- 0x0807, /* R70 */
- 0x0000, /* R71 */
- 0x0000, /* R72 */
- 0x0000, /* R73 */
- 0x0000, /* R74 */
- 0x0000, /* R75 */
- 0x0000, /* R76 */
- 0x0000, /* R77 */
- 0x0000, /* R78 */
- 0x000E, /* R79 */
- 0x0000, /* R80 */
- 0x0000, /* R81 */
- 0x0000, /* R82 */
- 0x0000, /* R83 */
- 0x0000, /* R84 */
- 0x0000, /* R85 */
- 0x0000, /* R86 */
- 0x0006, /* R87 */
- 0x0000, /* R88 */
- 0x0000, /* R89 */
- 0x0000, /* R90 - Analogue HP 0 */
- 0x0060, /* R91 */
- 0x0000, /* R92 */
- 0x0000, /* R93 */
- 0x0000, /* R94 - Analogue Lineout 0 */
- 0x0060, /* R95 */
- 0x0000, /* R96 */
- 0x0000, /* R97 */
- 0x0000, /* R98 - Charge Pump 0 */
- 0x1F25, /* R99 */
- 0x2B19, /* R100 */
- 0x01C0, /* R101 */
- 0x01EF, /* R102 */
- 0x2B00, /* R103 */
- 0x0000, /* R104 - Class W 0 */
- 0x01C0, /* R105 */
- 0x1C10, /* R106 */
- 0x0000, /* R107 */
- 0x0000, /* R108 - Write Sequencer 0 */
- 0x0000, /* R109 - Write Sequencer 1 */
- 0x0000, /* R110 - Write Sequencer 2 */
- 0x0000, /* R111 - Write Sequencer 3 */
- 0x0000, /* R112 - Write Sequencer 4 */
- 0x0000, /* R113 */
- 0x0000, /* R114 - Control Interface */
- 0x0000, /* R115 */
- 0x00A8, /* R116 - GPIO Control 1 */
- 0x00A8, /* R117 - GPIO Control 2 */
- 0x00A8, /* R118 - GPIO Control 3 */
- 0x0220, /* R119 - GPIO Control 4 */
- 0x01A0, /* R120 - GPIO Control 5 */
- 0x0000, /* R121 - Interrupt Status 1 */
- 0xFFFF, /* R122 - Interrupt Status 1 Mask */
- 0x0000, /* R123 - Interrupt Polarity 1 */
- 0x0000, /* R124 */
- 0x0003, /* R125 */
- 0x0000, /* R126 - Interrupt Control */
- 0x0000, /* R127 */
- 0x0005, /* R128 */
- 0x0000, /* R129 - Control Interface Test 1 */
- 0x0000, /* R130 */
- 0x0000, /* R131 */
- 0x0000, /* R132 */
- 0x0000, /* R133 */
- 0x0000, /* R134 */
- 0x03FF, /* R135 */
- 0x0007, /* R136 */
- 0x0040, /* R137 */
- 0x0000, /* R138 */
- 0x0000, /* R139 */
- 0x0000, /* R140 */
- 0x0000, /* R141 */
- 0x0000, /* R142 */
- 0x0000, /* R143 */
- 0x0000, /* R144 */
- 0x0000, /* R145 */
- 0x0000, /* R146 */
- 0x0000, /* R147 */
- 0x4000, /* R148 */
- 0x6810, /* R149 - Charge Pump Test 1 */
- 0x0004, /* R150 */
- 0x0000, /* R151 */
- 0x0000, /* R152 */
- 0x0000, /* R153 */
- 0x0000, /* R154 */
- 0x0000, /* R155 */
- 0x0000, /* R156 */
- 0x0000, /* R157 */
- 0x0000, /* R158 */
- 0x0000, /* R159 */
- 0x0000, /* R160 */
- 0x0000, /* R161 */
- 0x0000, /* R162 */
- 0x0000, /* R163 */
- 0x0028, /* R164 - Clock Rate Test 4 */
- 0x0004, /* R165 */
- 0x0000, /* R166 */
- 0x0060, /* R167 */
- 0x0000, /* R168 */
- 0x0000, /* R169 */
- 0x0000, /* R170 */
- 0x0000, /* R171 */
- 0x0000, /* R172 - Analogue Output Bias 0 */
+static const struct reg_default wm8903_reg_defaults[] = {
+ { 4, 0x0018 }, /* R4 - Bias Control 0 */
+ { 5, 0x0000 }, /* R5 - VMID Control 0 */
+ { 6, 0x0000 }, /* R6 - Mic Bias Control 0 */
+ { 8, 0x0001 }, /* R8 - Analogue DAC 0 */
+ { 10, 0x0001 }, /* R10 - Analogue ADC 0 */
+ { 12, 0x0000 }, /* R12 - Power Management 0 */
+ { 13, 0x0000 }, /* R13 - Power Management 1 */
+ { 14, 0x0000 }, /* R14 - Power Management 2 */
+ { 15, 0x0000 }, /* R15 - Power Management 3 */
+ { 16, 0x0000 }, /* R16 - Power Management 4 */
+ { 17, 0x0000 }, /* R17 - Power Management 5 */
+ { 18, 0x0000 }, /* R18 - Power Management 6 */
+ { 20, 0x0400 }, /* R20 - Clock Rates 0 */
+ { 21, 0x0D07 }, /* R21 - Clock Rates 1 */
+ { 22, 0x0000 }, /* R22 - Clock Rates 2 */
+ { 24, 0x0050 }, /* R24 - Audio Interface 0 */
+ { 25, 0x0242 }, /* R25 - Audio Interface 1 */
+ { 26, 0x0008 }, /* R26 - Audio Interface 2 */
+ { 27, 0x0022 }, /* R27 - Audio Interface 3 */
+ { 30, 0x00C0 }, /* R30 - DAC Digital Volume Left */
+ { 31, 0x00C0 }, /* R31 - DAC Digital Volume Right */
+ { 32, 0x0000 }, /* R32 - DAC Digital 0 */
+ { 33, 0x0000 }, /* R33 - DAC Digital 1 */
+ { 36, 0x00C0 }, /* R36 - ADC Digital Volume Left */
+ { 37, 0x00C0 }, /* R37 - ADC Digital Volume Right */
+ { 38, 0x0000 }, /* R38 - ADC Digital 0 */
+ { 39, 0x0073 }, /* R39 - Digital Microphone 0 */
+ { 40, 0x09BF }, /* R40 - DRC 0 */
+ { 41, 0x3241 }, /* R41 - DRC 1 */
+ { 42, 0x0020 }, /* R42 - DRC 2 */
+ { 43, 0x0000 }, /* R43 - DRC 3 */
+ { 44, 0x0085 }, /* R44 - Analogue Left Input 0 */
+ { 45, 0x0085 }, /* R45 - Analogue Right Input 0 */
+ { 46, 0x0044 }, /* R46 - Analogue Left Input 1 */
+ { 47, 0x0044 }, /* R47 - Analogue Right Input 1 */
+ { 50, 0x0008 }, /* R50 - Analogue Left Mix 0 */
+ { 51, 0x0004 }, /* R51 - Analogue Right Mix 0 */
+ { 52, 0x0000 }, /* R52 - Analogue Spk Mix Left 0 */
+ { 53, 0x0000 }, /* R53 - Analogue Spk Mix Left 1 */
+ { 54, 0x0000 }, /* R54 - Analogue Spk Mix Right 0 */
+ { 55, 0x0000 }, /* R55 - Analogue Spk Mix Right 1 */
+ { 57, 0x002D }, /* R57 - Analogue OUT1 Left */
+ { 58, 0x002D }, /* R58 - Analogue OUT1 Right */
+ { 59, 0x0039 }, /* R59 - Analogue OUT2 Left */
+ { 60, 0x0039 }, /* R60 - Analogue OUT2 Right */
+ { 62, 0x0139 }, /* R62 - Analogue OUT3 Left */
+ { 63, 0x0139 }, /* R63 - Analogue OUT3 Right */
+ { 64, 0x0000 }, /* R65 - Analogue SPK Output Control 0 */
+ { 67, 0x0010 }, /* R67 - DC Servo 0 */
+ { 69, 0x00A4 }, /* R69 - DC Servo 2 */
+ { 90, 0x0000 }, /* R90 - Analogue HP 0 */
+ { 94, 0x0000 }, /* R94 - Analogue Lineout 0 */
+ { 98, 0x0000 }, /* R98 - Charge Pump 0 */
+ { 104, 0x0000 }, /* R104 - Class W 0 */
+ { 108, 0x0000 }, /* R108 - Write Sequencer 0 */
+ { 109, 0x0000 }, /* R109 - Write Sequencer 1 */
+ { 110, 0x0000 }, /* R110 - Write Sequencer 2 */
+ { 111, 0x0000 }, /* R111 - Write Sequencer 3 */
+ { 112, 0x0000 }, /* R112 - Write Sequencer 4 */
+ { 114, 0x0000 }, /* R114 - Control Interface */
+ { 116, 0x00A8 }, /* R116 - GPIO Control 1 */
+ { 117, 0x00A8 }, /* R117 - GPIO Control 2 */
+ { 118, 0x00A8 }, /* R118 - GPIO Control 3 */
+ { 119, 0x0220 }, /* R119 - GPIO Control 4 */
+ { 120, 0x01A0 }, /* R120 - GPIO Control 5 */
+ { 122, 0xFFFF }, /* R122 - Interrupt Status 1 Mask */
+ { 123, 0x0000 }, /* R123 - Interrupt Polarity 1 */
+ { 126, 0x0000 }, /* R126 - Interrupt Control */
+ { 129, 0x0000 }, /* R129 - Control Interface Test 1 */
+ { 149, 0x6810 }, /* R149 - Charge Pump Test 1 */
+ { 164, 0x0028 }, /* R164 - Clock Rate Test 4 */
+ { 172, 0x0000 }, /* R172 - Analogue Output Bias 0 */
};
struct wm8903_priv {
+ struct wm8903_platform_data *pdata;
struct snd_soc_codec *codec;
+ struct regmap *regmap;
int sysclk;
int irq;
@@ -240,7 +142,93 @@ struct wm8903_priv {
#endif
};
-static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8903_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8903_SW_RESET_AND_ID:
+ case WM8903_REVISION_NUMBER:
+ case WM8903_BIAS_CONTROL_0:
+ case WM8903_VMID_CONTROL_0:
+ case WM8903_MIC_BIAS_CONTROL_0:
+ case WM8903_ANALOGUE_DAC_0:
+ case WM8903_ANALOGUE_ADC_0:
+ case WM8903_POWER_MANAGEMENT_0:
+ case WM8903_POWER_MANAGEMENT_1:
+ case WM8903_POWER_MANAGEMENT_2:
+ case WM8903_POWER_MANAGEMENT_3:
+ case WM8903_POWER_MANAGEMENT_4:
+ case WM8903_POWER_MANAGEMENT_5:
+ case WM8903_POWER_MANAGEMENT_6:
+ case WM8903_CLOCK_RATES_0:
+ case WM8903_CLOCK_RATES_1:
+ case WM8903_CLOCK_RATES_2:
+ case WM8903_AUDIO_INTERFACE_0:
+ case WM8903_AUDIO_INTERFACE_1:
+ case WM8903_AUDIO_INTERFACE_2:
+ case WM8903_AUDIO_INTERFACE_3:
+ case WM8903_DAC_DIGITAL_VOLUME_LEFT:
+ case WM8903_DAC_DIGITAL_VOLUME_RIGHT:
+ case WM8903_DAC_DIGITAL_0:
+ case WM8903_DAC_DIGITAL_1:
+ case WM8903_ADC_DIGITAL_VOLUME_LEFT:
+ case WM8903_ADC_DIGITAL_VOLUME_RIGHT:
+ case WM8903_ADC_DIGITAL_0:
+ case WM8903_DIGITAL_MICROPHONE_0:
+ case WM8903_DRC_0:
+ case WM8903_DRC_1:
+ case WM8903_DRC_2:
+ case WM8903_DRC_3:
+ case WM8903_ANALOGUE_LEFT_INPUT_0:
+ case WM8903_ANALOGUE_RIGHT_INPUT_0:
+ case WM8903_ANALOGUE_LEFT_INPUT_1:
+ case WM8903_ANALOGUE_RIGHT_INPUT_1:
+ case WM8903_ANALOGUE_LEFT_MIX_0:
+ case WM8903_ANALOGUE_RIGHT_MIX_0:
+ case WM8903_ANALOGUE_SPK_MIX_LEFT_0:
+ case WM8903_ANALOGUE_SPK_MIX_LEFT_1:
+ case WM8903_ANALOGUE_SPK_MIX_RIGHT_0:
+ case WM8903_ANALOGUE_SPK_MIX_RIGHT_1:
+ case WM8903_ANALOGUE_OUT1_LEFT:
+ case WM8903_ANALOGUE_OUT1_RIGHT:
+ case WM8903_ANALOGUE_OUT2_LEFT:
+ case WM8903_ANALOGUE_OUT2_RIGHT:
+ case WM8903_ANALOGUE_OUT3_LEFT:
+ case WM8903_ANALOGUE_OUT3_RIGHT:
+ case WM8903_ANALOGUE_SPK_OUTPUT_CONTROL_0:
+ case WM8903_DC_SERVO_0:
+ case WM8903_DC_SERVO_2:
+ case WM8903_DC_SERVO_READBACK_1:
+ case WM8903_DC_SERVO_READBACK_2:
+ case WM8903_DC_SERVO_READBACK_3:
+ case WM8903_DC_SERVO_READBACK_4:
+ case WM8903_ANALOGUE_HP_0:
+ case WM8903_ANALOGUE_LINEOUT_0:
+ case WM8903_CHARGE_PUMP_0:
+ case WM8903_CLASS_W_0:
+ case WM8903_WRITE_SEQUENCER_0:
+ case WM8903_WRITE_SEQUENCER_1:
+ case WM8903_WRITE_SEQUENCER_2:
+ case WM8903_WRITE_SEQUENCER_3:
+ case WM8903_WRITE_SEQUENCER_4:
+ case WM8903_CONTROL_INTERFACE:
+ case WM8903_GPIO_CONTROL_1:
+ case WM8903_GPIO_CONTROL_2:
+ case WM8903_GPIO_CONTROL_3:
+ case WM8903_GPIO_CONTROL_4:
+ case WM8903_GPIO_CONTROL_5:
+ case WM8903_INTERRUPT_STATUS_1:
+ case WM8903_INTERRUPT_STATUS_1_MASK:
+ case WM8903_INTERRUPT_POLARITY_1:
+ case WM8903_INTERRUPT_CONTROL:
+ case WM8903_CLOCK_RATE_TEST_4:
+ case WM8903_ANALOGUE_OUTPUT_BIAS_0:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm8903_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM8903_SW_RESET_AND_ID:
@@ -258,13 +246,6 @@ static int wm8903_volatile_register(struct snd_soc_codec *codec, unsigned int re
}
}
-static void wm8903_reset(struct snd_soc_codec *codec)
-{
- snd_soc_write(codec, WM8903_SW_RESET_AND_ID, 0);
- memcpy(codec->reg_cache, wm8903_reg_defaults,
- sizeof(wm8903_reg_defaults));
-}
-
static int wm8903_cp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -839,7 +820,7 @@ SND_SOC_DAPM_OUTPUT("LON"),
SND_SOC_DAPM_OUTPUT("ROP"),
SND_SOC_DAPM_OUTPUT("RON"),
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8903_MIC_BIAS_CONTROL_0, 0, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8903_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("Left Input Mux", SND_SOC_NOPM, 0, 0, &linput_mux),
SND_SOC_DAPM_MUX("Left Input Inverting Mux", SND_SOC_NOPM, 0, 0,
@@ -948,7 +929,7 @@ SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8903_CLOCK_RATES_2, 2, 0, NULL, 0),
static const struct snd_soc_dapm_route wm8903_intercon[] = {
{ "CLK_DSP", NULL, "CLK_SYS" },
- { "Mic Bias", NULL, "CLK_SYS" },
+ { "MICBIAS", NULL, "CLK_SYS" },
{ "HPL_DCS", NULL, "CLK_SYS" },
{ "HPR_DCS", NULL, "CLK_SYS" },
{ "LINEOUTL_DCS", NULL, "CLK_SYS" },
@@ -1732,7 +1713,7 @@ static irqreturn_t wm8903_irq(int irq, void *data)
SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8903_dai_ops = {
+static const struct snd_soc_dai_ops wm8903_dai_ops = {
.hw_params = wm8903_hw_params,
.digital_mute = wm8903_digital_mute,
.set_fmt = wm8903_set_dai_fmt,
@@ -1759,7 +1740,7 @@ static struct snd_soc_dai_driver wm8903_dai = {
.symmetric_rates = 1,
};
-static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8903_suspend(struct snd_soc_codec *codec)
{
wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -1768,23 +1749,11 @@ static int wm8903_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8903_resume(struct snd_soc_codec *codec)
{
- int i;
- u16 *reg_cache = codec->reg_cache;
- u16 *tmp_cache = kmemdup(reg_cache, sizeof(wm8903_reg_defaults),
- GFP_KERNEL);
+ struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
- /* Bring the codec back up to standby first to minimise pop/clicks */
- wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ regcache_sync(wm8903->regmap);
- /* Sync back everything else */
- if (tmp_cache) {
- for (i = 2; i < ARRAY_SIZE(wm8903_reg_defaults); i++)
- if (tmp_cache[i] != reg_cache[i])
- snd_soc_write(codec, i, tmp_cache[i]);
- kfree(tmp_cache);
- } else {
- dev_err(codec->dev, "Failed to allocate temporary cache\n");
- }
+ wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
@@ -1808,13 +1777,18 @@ static int wm8903_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
struct snd_soc_codec *codec = wm8903->codec;
unsigned int mask, val;
+ int ret;
mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK;
val = (WM8903_GPn_FN_GPIO_INPUT << WM8903_GP1_FN_SHIFT) |
WM8903_GP1_DIR;
- return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
- mask, val);
+ ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
+ mask, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static int wm8903_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -1834,13 +1808,18 @@ static int wm8903_gpio_direction_out(struct gpio_chip *chip,
struct wm8903_priv *wm8903 = gpio_to_wm8903(chip);
struct snd_soc_codec *codec = wm8903->codec;
unsigned int mask, val;
+ int ret;
mask = WM8903_GP1_FN_MASK | WM8903_GP1_DIR_MASK | WM8903_GP1_LVL_MASK;
val = (WM8903_GPn_FN_GPIO_OUTPUT << WM8903_GP1_FN_SHIFT) |
(value << WM8903_GP2_LVL_SHIFT);
- return snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
- mask, val);
+ ret = snd_soc_update_bits(codec, WM8903_GPIO_CONTROL_1 + offset,
+ mask, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static void wm8903_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
@@ -1867,14 +1846,14 @@ static struct gpio_chip wm8903_template_chip = {
static void wm8903_init_gpio(struct snd_soc_codec *codec)
{
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
- struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
+ struct wm8903_platform_data *pdata = wm8903->pdata;
int ret;
wm8903->gpio_chip = wm8903_template_chip;
wm8903->gpio_chip.ngpio = WM8903_NUM_GPIO;
wm8903->gpio_chip.dev = codec->dev;
- if (pdata && pdata->gpio_base)
+ if (pdata->gpio_base)
wm8903->gpio_chip.base = pdata->gpio_base;
else
wm8903->gpio_chip.base = -1;
@@ -1905,78 +1884,65 @@ static void wm8903_free_gpio(struct snd_soc_codec *codec)
static int wm8903_probe(struct snd_soc_codec *codec)
{
- struct wm8903_platform_data *pdata = dev_get_platdata(codec->dev);
struct wm8903_priv *wm8903 = snd_soc_codec_get_drvdata(codec);
+ struct wm8903_platform_data *pdata = wm8903->pdata;
int ret, i;
int trigger, irq_pol;
u16 val;
+ bool mic_gpio = false;
wm8903->codec = codec;
+ codec->control_data = wm8903->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- val = snd_soc_read(codec, WM8903_SW_RESET_AND_ID);
- if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
- dev_err(codec->dev,
- "Device with ID register %x is not a WM8903\n", val);
- return -ENODEV;
- }
-
- val = snd_soc_read(codec, WM8903_REVISION_NUMBER);
- dev_info(codec->dev, "WM8903 revision %c\n",
- (val & WM8903_CHIP_REV_MASK) + 'A');
+ /* Set up GPIOs, detect if any are MIC detect outputs */
+ for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
+ if ((!pdata->gpio_cfg[i]) ||
+ (pdata->gpio_cfg[i] > WM8903_GPIO_CONFIG_ZERO))
+ continue;
- wm8903_reset(codec);
+ snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
+ pdata->gpio_cfg[i] & 0x7fff);
- /* Set up GPIOs and microphone detection */
- if (pdata) {
- bool mic_gpio = false;
+ val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
+ >> WM8903_GP1_FN_SHIFT;
- for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
- if (pdata->gpio_cfg[i] == WM8903_GPIO_NO_CONFIG)
- continue;
-
- snd_soc_write(codec, WM8903_GPIO_CONTROL_1 + i,
- pdata->gpio_cfg[i] & 0xffff);
-
- val = (pdata->gpio_cfg[i] & WM8903_GP1_FN_MASK)
- >> WM8903_GP1_FN_SHIFT;
-
- switch (val) {
- case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
- case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
- mic_gpio = true;
- break;
- default:
- break;
- }
+ switch (val) {
+ case WM8903_GPn_FN_MICBIAS_CURRENT_DETECT:
+ case WM8903_GPn_FN_MICBIAS_SHORT_DETECT:
+ mic_gpio = true;
+ break;
+ default:
+ break;
}
+ }
+
+ /* Set up microphone detection */
+ snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0,
+ pdata->micdet_cfg);
- snd_soc_write(codec, WM8903_MIC_BIAS_CONTROL_0,
- pdata->micdet_cfg);
+ /* Microphone detection needs the WSEQ clock */
+ if (pdata->micdet_cfg)
+ snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
+ WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
- /* Microphone detection needs the WSEQ clock */
- if (pdata->micdet_cfg)
- snd_soc_update_bits(codec, WM8903_WRITE_SEQUENCER_0,
- WM8903_WSEQ_ENA, WM8903_WSEQ_ENA);
+ /* If microphone detection is enabled by pdata but
+ * detected via IRQ then interrupts can be lost before
+ * the machine driver has set up microphone detection
+ * IRQs as the IRQs are clear on read. The detection
+ * will be enabled when the machine driver configures.
+ */
+ WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
- /* If microphone detection is enabled by pdata but
- * detected via IRQ then interrupts can be lost before
- * the machine driver has set up microphone detection
- * IRQs as the IRQs are clear on read. The detection
- * will be enabled when the machine driver configures.
- */
- WARN_ON(!mic_gpio && (pdata->micdet_cfg & WM8903_MICDET_ENA));
+ wm8903->mic_delay = pdata->micdet_delay;
- wm8903->mic_delay = pdata->micdet_delay;
- }
-
if (wm8903->irq) {
- if (pdata && pdata->irq_active_low) {
+ if (pdata->irq_active_low) {
trigger = IRQF_TRIGGER_LOW;
irq_pol = WM8903_IRQ_POL;
} else {
@@ -2035,9 +2001,6 @@ static int wm8903_probe(struct snd_soc_codec *codec)
WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE,
WM8903_DAC_MUTEMODE | WM8903_DAC_MUTE);
- snd_soc_add_controls(codec, wm8903_snd_controls,
- ARRAY_SIZE(wm8903_snd_controls));
-
wm8903_init_gpio(codec);
return ret;
@@ -2062,45 +2025,198 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8903 = {
.suspend = wm8903_suspend,
.resume = wm8903_resume,
.set_bias_level = wm8903_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8903_reg_defaults,
- .volatile_register = wm8903_volatile_register,
.seq_notifier = wm8903_seq_notifier,
+ .controls = wm8903_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8903_snd_controls),
.dapm_widgets = wm8903_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(wm8903_dapm_widgets),
.dapm_routes = wm8903_intercon,
.num_dapm_routes = ARRAY_SIZE(wm8903_intercon),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+static const struct regmap_config wm8903_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = WM8903_MAX_REGISTER,
+ .volatile_reg = wm8903_volatile_register,
+ .readable_reg = wm8903_readable_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8903_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8903_reg_defaults),
+};
+
+static int wm8903_set_pdata_irq_trigger(struct i2c_client *i2c,
+ struct wm8903_platform_data *pdata)
+{
+ struct irq_data *irq_data = irq_get_irq_data(i2c->irq);
+ if (!irq_data) {
+ dev_err(&i2c->dev, "Invalid IRQ: %d\n",
+ i2c->irq);
+ return -EINVAL;
+ }
+
+ switch (irqd_get_trigger_type(irq_data)) {
+ case IRQ_TYPE_NONE:
+ default:
+ /*
+ * We assume the controller imposes no restrictions,
+ * so we are able to select active-high
+ */
+ /* Fall-through */
+ case IRQ_TYPE_LEVEL_HIGH:
+ pdata->irq_active_low = false;
+ break;
+ case IRQ_TYPE_LEVEL_LOW:
+ pdata->irq_active_low = true;
+ break;
+ }
+
+ return 0;
+}
+
+static int wm8903_set_pdata_from_of(struct i2c_client *i2c,
+ struct wm8903_platform_data *pdata)
+{
+ const struct device_node *np = i2c->dev.of_node;
+ u32 val32;
+ int i;
+
+ if (of_property_read_u32(np, "micdet-cfg", &val32) >= 0)
+ pdata->micdet_cfg = val32;
+
+ if (of_property_read_u32(np, "micdet-delay", &val32) >= 0)
+ pdata->micdet_delay = val32;
+
+ if (of_property_read_u32_array(np, "gpio-cfg", pdata->gpio_cfg,
+ ARRAY_SIZE(pdata->gpio_cfg)) >= 0) {
+ /*
+ * In device tree: 0 means "write 0",
+ * 0xffffffff means "don't touch".
+ *
+ * In platform data: 0 means "don't touch",
+ * 0x8000 means "write 0".
+ *
+ * Note: WM8903_GPIO_CONFIG_ZERO == 0x8000.
+ *
+ * Convert from DT to pdata representation here,
+ * so no other code needs to change.
+ */
+ for (i = 0; i < ARRAY_SIZE(pdata->gpio_cfg); i++) {
+ if (pdata->gpio_cfg[i] == 0) {
+ pdata->gpio_cfg[i] = WM8903_GPIO_CONFIG_ZERO;
+ } else if (pdata->gpio_cfg[i] == 0xffffffff) {
+ pdata->gpio_cfg[i] = 0;
+ } else if (pdata->gpio_cfg[i] > 0x7fff) {
+ dev_err(&i2c->dev, "Invalid gpio-cfg[%d] %x\n",
+ i, pdata->gpio_cfg[i]);
+ return -EINVAL;
+ }
+ }
+ }
+
+ return 0;
+}
+
static __devinit int wm8903_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ struct wm8903_platform_data *pdata = dev_get_platdata(&i2c->dev);
struct wm8903_priv *wm8903;
+ unsigned int val;
int ret;
- wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
+ wm8903 = devm_kzalloc(&i2c->dev, sizeof(struct wm8903_priv),
+ GFP_KERNEL);
if (wm8903 == NULL)
return -ENOMEM;
+ wm8903->regmap = regmap_init_i2c(i2c, &wm8903_regmap);
+ if (IS_ERR(wm8903->regmap)) {
+ ret = PTR_ERR(wm8903->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, wm8903);
wm8903->irq = i2c->irq;
+ /* If no platform data was supplied, create storage for defaults */
+ if (pdata) {
+ wm8903->pdata = pdata;
+ } else {
+ wm8903->pdata = devm_kzalloc(&i2c->dev,
+ sizeof(struct wm8903_platform_data),
+ GFP_KERNEL);
+ if (wm8903->pdata == NULL) {
+ dev_err(&i2c->dev, "Failed to allocate pdata\n");
+ return -ENOMEM;
+ }
+
+ if (i2c->irq) {
+ ret = wm8903_set_pdata_irq_trigger(i2c, wm8903->pdata);
+ if (ret != 0)
+ return ret;
+ }
+
+ if (i2c->dev.of_node) {
+ ret = wm8903_set_pdata_from_of(i2c, wm8903->pdata);
+ if (ret != 0)
+ return ret;
+ }
+ }
+
+ ret = regmap_read(wm8903->regmap, WM8903_SW_RESET_AND_ID, &val);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+ goto err;
+ }
+ if (val != 0x8903) {
+ dev_err(&i2c->dev, "Device with ID %x is not a WM8903\n", val);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = regmap_read(wm8903->regmap, WM8903_REVISION_NUMBER, &val);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to read chip revision: %d\n", ret);
+ goto err;
+ }
+ dev_info(&i2c->dev, "WM8903 revision %c\n",
+ (val & WM8903_CHIP_REV_MASK) + 'A');
+
+ /* Reset the device */
+ regmap_write(wm8903->regmap, WM8903_SW_RESET_AND_ID, 0x8903);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8903, &wm8903_dai, 1);
- if (ret < 0)
- kfree(wm8903);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+err:
+ regmap_exit(wm8903->regmap);
return ret;
}
static __devexit int wm8903_i2c_remove(struct i2c_client *client)
{
+ struct wm8903_priv *wm8903 = i2c_get_clientdata(client);
+
+ regmap_exit(wm8903->regmap);
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+
return 0;
}
+static const struct of_device_id wm8903_of_match[] = {
+ { .compatible = "wlf,wm8903", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, wm8903_of_match);
+
static const struct i2c_device_id wm8903_i2c_id[] = {
{ "wm8903", 0 },
{ }
@@ -2111,32 +2227,28 @@ static struct i2c_driver wm8903_i2c_driver = {
.driver = {
.name = "wm8903",
.owner = THIS_MODULE,
+ .of_match_table = wm8903_of_match,
},
.probe = wm8903_i2c_probe,
.remove = __devexit_p(wm8903_i2c_remove),
.id_table = wm8903_i2c_id,
};
-#endif
static int __init wm8903_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8903_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8903_modinit);
static void __exit wm8903_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8903_i2c_driver);
-#endif
}
module_exit(wm8903_exit);
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c
index b085575d4aa5..65d525d74c54 100644
--- a/sound/soc/codecs/wm8904.c
+++ b/sound/soc/codecs/wm8904.c
@@ -17,7 +17,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -48,9 +48,9 @@ static const char *wm8904_supply_names[WM8904_NUM_SUPPLIES] = {
/* codec private data */
struct wm8904_priv {
+ struct regmap *regmap;
enum wm8904_type devtype;
- void *control_data;
struct regulator_bulk_data supplies[WM8904_NUM_SUPPLIES];
@@ -88,517 +88,230 @@ struct wm8904_priv {
int dcs_state[WM8904_NUM_DCS_CHANNELS];
};
-static const u16 wm8904_reg[WM8904_MAX_REGISTER + 1] = {
- 0x8904, /* R0 - SW Reset and ID */
- 0x0000, /* R1 - Revision */
- 0x0000, /* R2 */
- 0x0000, /* R3 */
- 0x0018, /* R4 - Bias Control 0 */
- 0x0000, /* R5 - VMID Control 0 */
- 0x0000, /* R6 - Mic Bias Control 0 */
- 0x0000, /* R7 - Mic Bias Control 1 */
- 0x0001, /* R8 - Analogue DAC 0 */
- 0x9696, /* R9 - mic Filter Control */
- 0x0001, /* R10 - Analogue ADC 0 */
- 0x0000, /* R11 */
- 0x0000, /* R12 - Power Management 0 */
- 0x0000, /* R13 */
- 0x0000, /* R14 - Power Management 2 */
- 0x0000, /* R15 - Power Management 3 */
- 0x0000, /* R16 */
- 0x0000, /* R17 */
- 0x0000, /* R18 - Power Management 6 */
- 0x0000, /* R19 */
- 0x945E, /* R20 - Clock Rates 0 */
- 0x0C05, /* R21 - Clock Rates 1 */
- 0x0006, /* R22 - Clock Rates 2 */
- 0x0000, /* R23 */
- 0x0050, /* R24 - Audio Interface 0 */
- 0x000A, /* R25 - Audio Interface 1 */
- 0x00E4, /* R26 - Audio Interface 2 */
- 0x0040, /* R27 - Audio Interface 3 */
- 0x0000, /* R28 */
- 0x0000, /* R29 */
- 0x00C0, /* R30 - DAC Digital Volume Left */
- 0x00C0, /* R31 - DAC Digital Volume Right */
- 0x0000, /* R32 - DAC Digital 0 */
- 0x0008, /* R33 - DAC Digital 1 */
- 0x0000, /* R34 */
- 0x0000, /* R35 */
- 0x00C0, /* R36 - ADC Digital Volume Left */
- 0x00C0, /* R37 - ADC Digital Volume Right */
- 0x0010, /* R38 - ADC Digital 0 */
- 0x0000, /* R39 - Digital Microphone 0 */
- 0x01AF, /* R40 - DRC 0 */
- 0x3248, /* R41 - DRC 1 */
- 0x0000, /* R42 - DRC 2 */
- 0x0000, /* R43 - DRC 3 */
- 0x0085, /* R44 - Analogue Left Input 0 */
- 0x0085, /* R45 - Analogue Right Input 0 */
- 0x0044, /* R46 - Analogue Left Input 1 */
- 0x0044, /* R47 - Analogue Right Input 1 */
- 0x0000, /* R48 */
- 0x0000, /* R49 */
- 0x0000, /* R50 */
- 0x0000, /* R51 */
- 0x0000, /* R52 */
- 0x0000, /* R53 */
- 0x0000, /* R54 */
- 0x0000, /* R55 */
- 0x0000, /* R56 */
- 0x002D, /* R57 - Analogue OUT1 Left */
- 0x002D, /* R58 - Analogue OUT1 Right */
- 0x0039, /* R59 - Analogue OUT2 Left */
- 0x0039, /* R60 - Analogue OUT2 Right */
- 0x0000, /* R61 - Analogue OUT12 ZC */
- 0x0000, /* R62 */
- 0x0000, /* R63 */
- 0x0000, /* R64 */
- 0x0000, /* R65 */
- 0x0000, /* R66 */
- 0x0000, /* R67 - DC Servo 0 */
- 0x0000, /* R68 - DC Servo 1 */
- 0xAAAA, /* R69 - DC Servo 2 */
- 0x0000, /* R70 */
- 0xAAAA, /* R71 - DC Servo 4 */
- 0xAAAA, /* R72 - DC Servo 5 */
- 0x0000, /* R73 - DC Servo 6 */
- 0x0000, /* R74 - DC Servo 7 */
- 0x0000, /* R75 - DC Servo 8 */
- 0x0000, /* R76 - DC Servo 9 */
- 0x0000, /* R77 - DC Servo Readback 0 */
- 0x0000, /* R78 */
- 0x0000, /* R79 */
- 0x0000, /* R80 */
- 0x0000, /* R81 */
- 0x0000, /* R82 */
- 0x0000, /* R83 */
- 0x0000, /* R84 */
- 0x0000, /* R85 */
- 0x0000, /* R86 */
- 0x0000, /* R87 */
- 0x0000, /* R88 */
- 0x0000, /* R89 */
- 0x0000, /* R90 - Analogue HP 0 */
- 0x0000, /* R91 */
- 0x0000, /* R92 */
- 0x0000, /* R93 */
- 0x0000, /* R94 - Analogue Lineout 0 */
- 0x0000, /* R95 */
- 0x0000, /* R96 */
- 0x0000, /* R97 */
- 0x0000, /* R98 - Charge Pump 0 */
- 0x0000, /* R99 */
- 0x0000, /* R100 */
- 0x0000, /* R101 */
- 0x0000, /* R102 */
- 0x0000, /* R103 */
- 0x0004, /* R104 - Class W 0 */
- 0x0000, /* R105 */
- 0x0000, /* R106 */
- 0x0000, /* R107 */
- 0x0000, /* R108 - Write Sequencer 0 */
- 0x0000, /* R109 - Write Sequencer 1 */
- 0x0000, /* R110 - Write Sequencer 2 */
- 0x0000, /* R111 - Write Sequencer 3 */
- 0x0000, /* R112 - Write Sequencer 4 */
- 0x0000, /* R113 */
- 0x0000, /* R114 */
- 0x0000, /* R115 */
- 0x0000, /* R116 - FLL Control 1 */
- 0x0007, /* R117 - FLL Control 2 */
- 0x0000, /* R118 - FLL Control 3 */
- 0x2EE0, /* R119 - FLL Control 4 */
- 0x0004, /* R120 - FLL Control 5 */
- 0x0014, /* R121 - GPIO Control 1 */
- 0x0010, /* R122 - GPIO Control 2 */
- 0x0010, /* R123 - GPIO Control 3 */
- 0x0000, /* R124 - GPIO Control 4 */
- 0x0000, /* R125 */
- 0x0000, /* R126 - Digital Pulls */
- 0x0000, /* R127 - Interrupt Status */
- 0xFFFF, /* R128 - Interrupt Status Mask */
- 0x0000, /* R129 - Interrupt Polarity */
- 0x0000, /* R130 - Interrupt Debounce */
- 0x0000, /* R131 */
- 0x0000, /* R132 */
- 0x0000, /* R133 */
- 0x0000, /* R134 - EQ1 */
- 0x000C, /* R135 - EQ2 */
- 0x000C, /* R136 - EQ3 */
- 0x000C, /* R137 - EQ4 */
- 0x000C, /* R138 - EQ5 */
- 0x000C, /* R139 - EQ6 */
- 0x0FCA, /* R140 - EQ7 */
- 0x0400, /* R141 - EQ8 */
- 0x00D8, /* R142 - EQ9 */
- 0x1EB5, /* R143 - EQ10 */
- 0xF145, /* R144 - EQ11 */
- 0x0B75, /* R145 - EQ12 */
- 0x01C5, /* R146 - EQ13 */
- 0x1C58, /* R147 - EQ14 */
- 0xF373, /* R148 - EQ15 */
- 0x0A54, /* R149 - EQ16 */
- 0x0558, /* R150 - EQ17 */
- 0x168E, /* R151 - EQ18 */
- 0xF829, /* R152 - EQ19 */
- 0x07AD, /* R153 - EQ20 */
- 0x1103, /* R154 - EQ21 */
- 0x0564, /* R155 - EQ22 */
- 0x0559, /* R156 - EQ23 */
- 0x4000, /* R157 - EQ24 */
- 0x0000, /* R158 */
- 0x0000, /* R159 */
- 0x0000, /* R160 */
- 0x0000, /* R161 - Control Interface Test 1 */
- 0x0000, /* R162 */
- 0x0000, /* R163 */
- 0x0000, /* R164 */
- 0x0000, /* R165 */
- 0x0000, /* R166 */
- 0x0000, /* R167 */
- 0x0000, /* R168 */
- 0x0000, /* R169 */
- 0x0000, /* R170 */
- 0x0000, /* R171 */
- 0x0000, /* R172 */
- 0x0000, /* R173 */
- 0x0000, /* R174 */
- 0x0000, /* R175 */
- 0x0000, /* R176 */
- 0x0000, /* R177 */
- 0x0000, /* R178 */
- 0x0000, /* R179 */
- 0x0000, /* R180 */
- 0x0000, /* R181 */
- 0x0000, /* R182 */
- 0x0000, /* R183 */
- 0x0000, /* R184 */
- 0x0000, /* R185 */
- 0x0000, /* R186 */
- 0x0000, /* R187 */
- 0x0000, /* R188 */
- 0x0000, /* R189 */
- 0x0000, /* R190 */
- 0x0000, /* R191 */
- 0x0000, /* R192 */
- 0x0000, /* R193 */
- 0x0000, /* R194 */
- 0x0000, /* R195 */
- 0x0000, /* R196 */
- 0x0000, /* R197 */
- 0x0000, /* R198 */
- 0x0000, /* R199 */
- 0x0000, /* R200 */
- 0x0000, /* R201 */
- 0x0000, /* R202 */
- 0x0000, /* R203 */
- 0x0000, /* R204 - Analogue Output Bias 0 */
- 0x0000, /* R205 */
- 0x0000, /* R206 */
- 0x0000, /* R207 */
- 0x0000, /* R208 */
- 0x0000, /* R209 */
- 0x0000, /* R210 */
- 0x0000, /* R211 */
- 0x0000, /* R212 */
- 0x0000, /* R213 */
- 0x0000, /* R214 */
- 0x0000, /* R215 */
- 0x0000, /* R216 */
- 0x0000, /* R217 */
- 0x0000, /* R218 */
- 0x0000, /* R219 */
- 0x0000, /* R220 */
- 0x0000, /* R221 */
- 0x0000, /* R222 */
- 0x0000, /* R223 */
- 0x0000, /* R224 */
- 0x0000, /* R225 */
- 0x0000, /* R226 */
- 0x0000, /* R227 */
- 0x0000, /* R228 */
- 0x0000, /* R229 */
- 0x0000, /* R230 */
- 0x0000, /* R231 */
- 0x0000, /* R232 */
- 0x0000, /* R233 */
- 0x0000, /* R234 */
- 0x0000, /* R235 */
- 0x0000, /* R236 */
- 0x0000, /* R237 */
- 0x0000, /* R238 */
- 0x0000, /* R239 */
- 0x0000, /* R240 */
- 0x0000, /* R241 */
- 0x0000, /* R242 */
- 0x0000, /* R243 */
- 0x0000, /* R244 */
- 0x0000, /* R245 */
- 0x0000, /* R246 */
- 0x0000, /* R247 - FLL NCO Test 0 */
- 0x0019, /* R248 - FLL NCO Test 1 */
+static const struct reg_default wm8904_reg_defaults[] = {
+ { 4, 0x0018 }, /* R4 - Bias Control 0 */
+ { 5, 0x0000 }, /* R5 - VMID Control 0 */
+ { 6, 0x0000 }, /* R6 - Mic Bias Control 0 */
+ { 7, 0x0000 }, /* R7 - Mic Bias Control 1 */
+ { 8, 0x0001 }, /* R8 - Analogue DAC 0 */
+ { 9, 0x9696 }, /* R9 - mic Filter Control */
+ { 10, 0x0001 }, /* R10 - Analogue ADC 0 */
+ { 12, 0x0000 }, /* R12 - Power Management 0 */
+ { 14, 0x0000 }, /* R14 - Power Management 2 */
+ { 15, 0x0000 }, /* R15 - Power Management 3 */
+ { 18, 0x0000 }, /* R18 - Power Management 6 */
+ { 19, 0x945E }, /* R20 - Clock Rates 0 */
+ { 21, 0x0C05 }, /* R21 - Clock Rates 1 */
+ { 22, 0x0006 }, /* R22 - Clock Rates 2 */
+ { 24, 0x0050 }, /* R24 - Audio Interface 0 */
+ { 25, 0x000A }, /* R25 - Audio Interface 1 */
+ { 26, 0x00E4 }, /* R26 - Audio Interface 2 */
+ { 27, 0x0040 }, /* R27 - Audio Interface 3 */
+ { 30, 0x00C0 }, /* R30 - DAC Digital Volume Left */
+ { 31, 0x00C0 }, /* R31 - DAC Digital Volume Right */
+ { 32, 0x0000 }, /* R32 - DAC Digital 0 */
+ { 33, 0x0008 }, /* R33 - DAC Digital 1 */
+ { 36, 0x00C0 }, /* R36 - ADC Digital Volume Left */
+ { 37, 0x00C0 }, /* R37 - ADC Digital Volume Right */
+ { 38, 0x0010 }, /* R38 - ADC Digital 0 */
+ { 39, 0x0000 }, /* R39 - Digital Microphone 0 */
+ { 40, 0x01AF }, /* R40 - DRC 0 */
+ { 41, 0x3248 }, /* R41 - DRC 1 */
+ { 42, 0x0000 }, /* R42 - DRC 2 */
+ { 43, 0x0000 }, /* R43 - DRC 3 */
+ { 44, 0x0085 }, /* R44 - Analogue Left Input 0 */
+ { 45, 0x0085 }, /* R45 - Analogue Right Input 0 */
+ { 46, 0x0044 }, /* R46 - Analogue Left Input 1 */
+ { 47, 0x0044 }, /* R47 - Analogue Right Input 1 */
+ { 57, 0x002D }, /* R57 - Analogue OUT1 Left */
+ { 58, 0x002D }, /* R58 - Analogue OUT1 Right */
+ { 59, 0x0039 }, /* R59 - Analogue OUT2 Left */
+ { 60, 0x0039 }, /* R60 - Analogue OUT2 Right */
+ { 61, 0x0000 }, /* R61 - Analogue OUT12 ZC */
+ { 67, 0x0000 }, /* R67 - DC Servo 0 */
+ { 69, 0xAAAA }, /* R69 - DC Servo 2 */
+ { 71, 0xAAAA }, /* R71 - DC Servo 4 */
+ { 72, 0xAAAA }, /* R72 - DC Servo 5 */
+ { 90, 0x0000 }, /* R90 - Analogue HP 0 */
+ { 94, 0x0000 }, /* R94 - Analogue Lineout 0 */
+ { 98, 0x0000 }, /* R98 - Charge Pump 0 */
+ { 104, 0x0004 }, /* R104 - Class W 0 */
+ { 108, 0x0000 }, /* R108 - Write Sequencer 0 */
+ { 109, 0x0000 }, /* R109 - Write Sequencer 1 */
+ { 110, 0x0000 }, /* R110 - Write Sequencer 2 */
+ { 111, 0x0000 }, /* R111 - Write Sequencer 3 */
+ { 112, 0x0000 }, /* R112 - Write Sequencer 4 */
+ { 116, 0x0000 }, /* R116 - FLL Control 1 */
+ { 117, 0x0007 }, /* R117 - FLL Control 2 */
+ { 118, 0x0000 }, /* R118 - FLL Control 3 */
+ { 119, 0x2EE0 }, /* R119 - FLL Control 4 */
+ { 120, 0x0004 }, /* R120 - FLL Control 5 */
+ { 121, 0x0014 }, /* R121 - GPIO Control 1 */
+ { 122, 0x0010 }, /* R122 - GPIO Control 2 */
+ { 123, 0x0010 }, /* R123 - GPIO Control 3 */
+ { 124, 0x0000 }, /* R124 - GPIO Control 4 */
+ { 126, 0x0000 }, /* R126 - Digital Pulls */
+ { 128, 0xFFFF }, /* R128 - Interrupt Status Mask */
+ { 129, 0x0000 }, /* R129 - Interrupt Polarity */
+ { 130, 0x0000 }, /* R130 - Interrupt Debounce */
+ { 134, 0x0000 }, /* R134 - EQ1 */
+ { 135, 0x000C }, /* R135 - EQ2 */
+ { 136, 0x000C }, /* R136 - EQ3 */
+ { 137, 0x000C }, /* R137 - EQ4 */
+ { 138, 0x000C }, /* R138 - EQ5 */
+ { 139, 0x000C }, /* R139 - EQ6 */
+ { 140, 0x0FCA }, /* R140 - EQ7 */
+ { 141, 0x0400 }, /* R141 - EQ8 */
+ { 142, 0x00D8 }, /* R142 - EQ9 */
+ { 143, 0x1EB5 }, /* R143 - EQ10 */
+ { 144, 0xF145 }, /* R144 - EQ11 */
+ { 145, 0x0B75 }, /* R145 - EQ12 */
+ { 146, 0x01C5 }, /* R146 - EQ13 */
+ { 147, 0x1C58 }, /* R147 - EQ14 */
+ { 148, 0xF373 }, /* R148 - EQ15 */
+ { 149, 0x0A54 }, /* R149 - EQ16 */
+ { 150, 0x0558 }, /* R150 - EQ17 */
+ { 151, 0x168E }, /* R151 - EQ18 */
+ { 152, 0xF829 }, /* R152 - EQ19 */
+ { 153, 0x07AD }, /* R153 - EQ20 */
+ { 154, 0x1103 }, /* R154 - EQ21 */
+ { 155, 0x0564 }, /* R155 - EQ22 */
+ { 156, 0x0559 }, /* R156 - EQ23 */
+ { 157, 0x4000 }, /* R157 - EQ24 */
+ { 161, 0x0000 }, /* R161 - Control Interface Test 1 */
+ { 204, 0x0000 }, /* R204 - Analogue Output Bias 0 */
+ { 247, 0x0000 }, /* R247 - FLL NCO Test 0 */
+ { 248, 0x0019 }, /* R248 - FLL NCO Test 1 */
};
-static struct {
- int readable;
- int writable;
- int vol;
-} wm8904_access[] = {
- { 0xFFFF, 0xFFFF, 1 }, /* R0 - SW Reset and ID */
- { 0x0000, 0x0000, 0 }, /* R1 - Revision */
- { 0x0000, 0x0000, 0 }, /* R2 */
- { 0x0000, 0x0000, 0 }, /* R3 */
- { 0x001F, 0x001F, 0 }, /* R4 - Bias Control 0 */
- { 0x0047, 0x0047, 0 }, /* R5 - VMID Control 0 */
- { 0x007F, 0x007F, 0 }, /* R6 - Mic Bias Control 0 */
- { 0xC007, 0xC007, 0 }, /* R7 - Mic Bias Control 1 */
- { 0x001E, 0x001E, 0 }, /* R8 - Analogue DAC 0 */
- { 0xFFFF, 0xFFFF, 0 }, /* R9 - mic Filter Control */
- { 0x0001, 0x0001, 0 }, /* R10 - Analogue ADC 0 */
- { 0x0000, 0x0000, 0 }, /* R11 */
- { 0x0003, 0x0003, 0 }, /* R12 - Power Management 0 */
- { 0x0000, 0x0000, 0 }, /* R13 */
- { 0x0003, 0x0003, 0 }, /* R14 - Power Management 2 */
- { 0x0003, 0x0003, 0 }, /* R15 - Power Management 3 */
- { 0x0000, 0x0000, 0 }, /* R16 */
- { 0x0000, 0x0000, 0 }, /* R17 */
- { 0x000F, 0x000F, 0 }, /* R18 - Power Management 6 */
- { 0x0000, 0x0000, 0 }, /* R19 */
- { 0x7001, 0x7001, 0 }, /* R20 - Clock Rates 0 */
- { 0x3C07, 0x3C07, 0 }, /* R21 - Clock Rates 1 */
- { 0xD00F, 0xD00F, 0 }, /* R22 - Clock Rates 2 */
- { 0x0000, 0x0000, 0 }, /* R23 */
- { 0x1FFF, 0x1FFF, 0 }, /* R24 - Audio Interface 0 */
- { 0x3DDF, 0x3DDF, 0 }, /* R25 - Audio Interface 1 */
- { 0x0F1F, 0x0F1F, 0 }, /* R26 - Audio Interface 2 */
- { 0x0FFF, 0x0FFF, 0 }, /* R27 - Audio Interface 3 */
- { 0x0000, 0x0000, 0 }, /* R28 */
- { 0x0000, 0x0000, 0 }, /* R29 */
- { 0x00FF, 0x01FF, 0 }, /* R30 - DAC Digital Volume Left */
- { 0x00FF, 0x01FF, 0 }, /* R31 - DAC Digital Volume Right */
- { 0x0FFF, 0x0FFF, 0 }, /* R32 - DAC Digital 0 */
- { 0x1E4E, 0x1E4E, 0 }, /* R33 - DAC Digital 1 */
- { 0x0000, 0x0000, 0 }, /* R34 */
- { 0x0000, 0x0000, 0 }, /* R35 */
- { 0x00FF, 0x01FF, 0 }, /* R36 - ADC Digital Volume Left */
- { 0x00FF, 0x01FF, 0 }, /* R37 - ADC Digital Volume Right */
- { 0x0073, 0x0073, 0 }, /* R38 - ADC Digital 0 */
- { 0x1800, 0x1800, 0 }, /* R39 - Digital Microphone 0 */
- { 0xDFEF, 0xDFEF, 0 }, /* R40 - DRC 0 */
- { 0xFFFF, 0xFFFF, 0 }, /* R41 - DRC 1 */
- { 0x003F, 0x003F, 0 }, /* R42 - DRC 2 */
- { 0x07FF, 0x07FF, 0 }, /* R43 - DRC 3 */
- { 0x009F, 0x009F, 0 }, /* R44 - Analogue Left Input 0 */
- { 0x009F, 0x009F, 0 }, /* R45 - Analogue Right Input 0 */
- { 0x007F, 0x007F, 0 }, /* R46 - Analogue Left Input 1 */
- { 0x007F, 0x007F, 0 }, /* R47 - Analogue Right Input 1 */
- { 0x0000, 0x0000, 0 }, /* R48 */
- { 0x0000, 0x0000, 0 }, /* R49 */
- { 0x0000, 0x0000, 0 }, /* R50 */
- { 0x0000, 0x0000, 0 }, /* R51 */
- { 0x0000, 0x0000, 0 }, /* R52 */
- { 0x0000, 0x0000, 0 }, /* R53 */
- { 0x0000, 0x0000, 0 }, /* R54 */
- { 0x0000, 0x0000, 0 }, /* R55 */
- { 0x0000, 0x0000, 0 }, /* R56 */
- { 0x017F, 0x01FF, 0 }, /* R57 - Analogue OUT1 Left */
- { 0x017F, 0x01FF, 0 }, /* R58 - Analogue OUT1 Right */
- { 0x017F, 0x01FF, 0 }, /* R59 - Analogue OUT2 Left */
- { 0x017F, 0x01FF, 0 }, /* R60 - Analogue OUT2 Right */
- { 0x000F, 0x000F, 0 }, /* R61 - Analogue OUT12 ZC */
- { 0x0000, 0x0000, 0 }, /* R62 */
- { 0x0000, 0x0000, 0 }, /* R63 */
- { 0x0000, 0x0000, 0 }, /* R64 */
- { 0x0000, 0x0000, 0 }, /* R65 */
- { 0x0000, 0x0000, 0 }, /* R66 */
- { 0x000F, 0x000F, 0 }, /* R67 - DC Servo 0 */
- { 0xFFFF, 0xFFFF, 1 }, /* R68 - DC Servo 1 */
- { 0x0F0F, 0x0F0F, 0 }, /* R69 - DC Servo 2 */
- { 0x0000, 0x0000, 0 }, /* R70 */
- { 0x007F, 0x007F, 0 }, /* R71 - DC Servo 4 */
- { 0x007F, 0x007F, 0 }, /* R72 - DC Servo 5 */
- { 0x00FF, 0x00FF, 1 }, /* R73 - DC Servo 6 */
- { 0x00FF, 0x00FF, 1 }, /* R74 - DC Servo 7 */
- { 0x00FF, 0x00FF, 1 }, /* R75 - DC Servo 8 */
- { 0x00FF, 0x00FF, 1 }, /* R76 - DC Servo 9 */
- { 0x0FFF, 0x0000, 1 }, /* R77 - DC Servo Readback 0 */
- { 0x0000, 0x0000, 0 }, /* R78 */
- { 0x0000, 0x0000, 0 }, /* R79 */
- { 0x0000, 0x0000, 0 }, /* R80 */
- { 0x0000, 0x0000, 0 }, /* R81 */
- { 0x0000, 0x0000, 0 }, /* R82 */
- { 0x0000, 0x0000, 0 }, /* R83 */
- { 0x0000, 0x0000, 0 }, /* R84 */
- { 0x0000, 0x0000, 0 }, /* R85 */
- { 0x0000, 0x0000, 0 }, /* R86 */
- { 0x0000, 0x0000, 0 }, /* R87 */
- { 0x0000, 0x0000, 0 }, /* R88 */
- { 0x0000, 0x0000, 0 }, /* R89 */
- { 0x00FF, 0x00FF, 0 }, /* R90 - Analogue HP 0 */
- { 0x0000, 0x0000, 0 }, /* R91 */
- { 0x0000, 0x0000, 0 }, /* R92 */
- { 0x0000, 0x0000, 0 }, /* R93 */
- { 0x00FF, 0x00FF, 0 }, /* R94 - Analogue Lineout 0 */
- { 0x0000, 0x0000, 0 }, /* R95 */
- { 0x0000, 0x0000, 0 }, /* R96 */
- { 0x0000, 0x0000, 0 }, /* R97 */
- { 0x0001, 0x0001, 0 }, /* R98 - Charge Pump 0 */
- { 0x0000, 0x0000, 0 }, /* R99 */
- { 0x0000, 0x0000, 0 }, /* R100 */
- { 0x0000, 0x0000, 0 }, /* R101 */
- { 0x0000, 0x0000, 0 }, /* R102 */
- { 0x0000, 0x0000, 0 }, /* R103 */
- { 0x0001, 0x0001, 0 }, /* R104 - Class W 0 */
- { 0x0000, 0x0000, 0 }, /* R105 */
- { 0x0000, 0x0000, 0 }, /* R106 */
- { 0x0000, 0x0000, 0 }, /* R107 */
- { 0x011F, 0x011F, 0 }, /* R108 - Write Sequencer 0 */
- { 0x7FFF, 0x7FFF, 0 }, /* R109 - Write Sequencer 1 */
- { 0x4FFF, 0x4FFF, 0 }, /* R110 - Write Sequencer 2 */
- { 0x003F, 0x033F, 0 }, /* R111 - Write Sequencer 3 */
- { 0x03F1, 0x0000, 0 }, /* R112 - Write Sequencer 4 */
- { 0x0000, 0x0000, 0 }, /* R113 */
- { 0x0000, 0x0000, 0 }, /* R114 */
- { 0x0000, 0x0000, 0 }, /* R115 */
- { 0x0007, 0x0007, 0 }, /* R116 - FLL Control 1 */
- { 0x3F77, 0x3F77, 0 }, /* R117 - FLL Control 2 */
- { 0xFFFF, 0xFFFF, 0 }, /* R118 - FLL Control 3 */
- { 0x7FEF, 0x7FEF, 0 }, /* R119 - FLL Control 4 */
- { 0x001B, 0x001B, 0 }, /* R120 - FLL Control 5 */
- { 0x003F, 0x003F, 0 }, /* R121 - GPIO Control 1 */
- { 0x003F, 0x003F, 0 }, /* R122 - GPIO Control 2 */
- { 0x003F, 0x003F, 0 }, /* R123 - GPIO Control 3 */
- { 0x038F, 0x038F, 0 }, /* R124 - GPIO Control 4 */
- { 0x0000, 0x0000, 0 }, /* R125 */
- { 0x00FF, 0x00FF, 0 }, /* R126 - Digital Pulls */
- { 0x07FF, 0x03FF, 1 }, /* R127 - Interrupt Status */
- { 0x03FF, 0x03FF, 0 }, /* R128 - Interrupt Status Mask */
- { 0x03FF, 0x03FF, 0 }, /* R129 - Interrupt Polarity */
- { 0x03FF, 0x03FF, 0 }, /* R130 - Interrupt Debounce */
- { 0x0000, 0x0000, 0 }, /* R131 */
- { 0x0000, 0x0000, 0 }, /* R132 */
- { 0x0000, 0x0000, 0 }, /* R133 */
- { 0x0001, 0x0001, 0 }, /* R134 - EQ1 */
- { 0x001F, 0x001F, 0 }, /* R135 - EQ2 */
- { 0x001F, 0x001F, 0 }, /* R136 - EQ3 */
- { 0x001F, 0x001F, 0 }, /* R137 - EQ4 */
- { 0x001F, 0x001F, 0 }, /* R138 - EQ5 */
- { 0x001F, 0x001F, 0 }, /* R139 - EQ6 */
- { 0xFFFF, 0xFFFF, 0 }, /* R140 - EQ7 */
- { 0xFFFF, 0xFFFF, 0 }, /* R141 - EQ8 */
- { 0xFFFF, 0xFFFF, 0 }, /* R142 - EQ9 */
- { 0xFFFF, 0xFFFF, 0 }, /* R143 - EQ10 */
- { 0xFFFF, 0xFFFF, 0 }, /* R144 - EQ11 */
- { 0xFFFF, 0xFFFF, 0 }, /* R145 - EQ12 */
- { 0xFFFF, 0xFFFF, 0 }, /* R146 - EQ13 */
- { 0xFFFF, 0xFFFF, 0 }, /* R147 - EQ14 */
- { 0xFFFF, 0xFFFF, 0 }, /* R148 - EQ15 */
- { 0xFFFF, 0xFFFF, 0 }, /* R149 - EQ16 */
- { 0xFFFF, 0xFFFF, 0 }, /* R150 - EQ17 */
- { 0xFFFF, 0xFFFF, 0 }, /* R151wm8523_dai - EQ18 */
- { 0xFFFF, 0xFFFF, 0 }, /* R152 - EQ19 */
- { 0xFFFF, 0xFFFF, 0 }, /* R153 - EQ20 */
- { 0xFFFF, 0xFFFF, 0 }, /* R154 - EQ21 */
- { 0xFFFF, 0xFFFF, 0 }, /* R155 - EQ22 */
- { 0xFFFF, 0xFFFF, 0 }, /* R156 - EQ23 */
- { 0xFFFF, 0xFFFF, 0 }, /* R157 - EQ24 */
- { 0x0000, 0x0000, 0 }, /* R158 */
- { 0x0000, 0x0000, 0 }, /* R159 */
- { 0x0000, 0x0000, 0 }, /* R160 */
- { 0x0002, 0x0002, 0 }, /* R161 - Control Interface Test 1 */
- { 0x0000, 0x0000, 0 }, /* R162 */
- { 0x0000, 0x0000, 0 }, /* R163 */
- { 0x0000, 0x0000, 0 }, /* R164 */
- { 0x0000, 0x0000, 0 }, /* R165 */
- { 0x0000, 0x0000, 0 }, /* R166 */
- { 0x0000, 0x0000, 0 }, /* R167 */
- { 0x0000, 0x0000, 0 }, /* R168 */
- { 0x0000, 0x0000, 0 }, /* R169 */
- { 0x0000, 0x0000, 0 }, /* R170 */
- { 0x0000, 0x0000, 0 }, /* R171 */
- { 0x0000, 0x0000, 0 }, /* R172 */
- { 0x0000, 0x0000, 0 }, /* R173 */
- { 0x0000, 0x0000, 0 }, /* R174 */
- { 0x0000, 0x0000, 0 }, /* R175 */
- { 0x0000, 0x0000, 0 }, /* R176 */
- { 0x0000, 0x0000, 0 }, /* R177 */
- { 0x0000, 0x0000, 0 }, /* R178 */
- { 0x0000, 0x0000, 0 }, /* R179 */
- { 0x0000, 0x0000, 0 }, /* R180 */
- { 0x0000, 0x0000, 0 }, /* R181 */
- { 0x0000, 0x0000, 0 }, /* R182 */
- { 0x0000, 0x0000, 0 }, /* R183 */
- { 0x0000, 0x0000, 0 }, /* R184 */
- { 0x0000, 0x0000, 0 }, /* R185 */
- { 0x0000, 0x0000, 0 }, /* R186 */
- { 0x0000, 0x0000, 0 }, /* R187 */
- { 0x0000, 0x0000, 0 }, /* R188 */
- { 0x0000, 0x0000, 0 }, /* R189 */
- { 0x0000, 0x0000, 0 }, /* R190 */
- { 0x0000, 0x0000, 0 }, /* R191 */
- { 0x0000, 0x0000, 0 }, /* R192 */
- { 0x0000, 0x0000, 0 }, /* R193 */
- { 0x0000, 0x0000, 0 }, /* R194 */
- { 0x0000, 0x0000, 0 }, /* R195 */
- { 0x0000, 0x0000, 0 }, /* R196 */
- { 0x0000, 0x0000, 0 }, /* R197 */
- { 0x0000, 0x0000, 0 }, /* R198 */
- { 0x0000, 0x0000, 0 }, /* R199 */
- { 0x0000, 0x0000, 0 }, /* R200 */
- { 0x0000, 0x0000, 0 }, /* R201 */
- { 0x0000, 0x0000, 0 }, /* R202 */
- { 0x0000, 0x0000, 0 }, /* R203 */
- { 0x0070, 0x0070, 0 }, /* R204 - Analogue Output Bias 0 */
- { 0x0000, 0x0000, 0 }, /* R205 */
- { 0x0000, 0x0000, 0 }, /* R206 */
- { 0x0000, 0x0000, 0 }, /* R207 */
- { 0x0000, 0x0000, 0 }, /* R208 */
- { 0x0000, 0x0000, 0 }, /* R209 */
- { 0x0000, 0x0000, 0 }, /* R210 */
- { 0x0000, 0x0000, 0 }, /* R211 */
- { 0x0000, 0x0000, 0 }, /* R212 */
- { 0x0000, 0x0000, 0 }, /* R213 */
- { 0x0000, 0x0000, 0 }, /* R214 */
- { 0x0000, 0x0000, 0 }, /* R215 */
- { 0x0000, 0x0000, 0 }, /* R216 */
- { 0x0000, 0x0000, 0 }, /* R217 */
- { 0x0000, 0x0000, 0 }, /* R218 */
- { 0x0000, 0x0000, 0 }, /* R219 */
- { 0x0000, 0x0000, 0 }, /* R220 */
- { 0x0000, 0x0000, 0 }, /* R221 */
- { 0x0000, 0x0000, 0 }, /* R222 */
- { 0x0000, 0x0000, 0 }, /* R223 */
- { 0x0000, 0x0000, 0 }, /* R224 */
- { 0x0000, 0x0000, 0 }, /* R225 */
- { 0x0000, 0x0000, 0 }, /* R226 */
- { 0x0000, 0x0000, 0 }, /* R227 */
- { 0x0000, 0x0000, 0 }, /* R228 */
- { 0x0000, 0x0000, 0 }, /* R229 */
- { 0x0000, 0x0000, 0 }, /* R230 */
- { 0x0000, 0x0000, 0 }, /* R231 */
- { 0x0000, 0x0000, 0 }, /* R232 */
- { 0x0000, 0x0000, 0 }, /* R233 */
- { 0x0000, 0x0000, 0 }, /* R234 */
- { 0x0000, 0x0000, 0 }, /* R235 */
- { 0x0000, 0x0000, 0 }, /* R236 */
- { 0x0000, 0x0000, 0 }, /* R237 */
- { 0x0000, 0x0000, 0 }, /* R238 */
- { 0x0000, 0x0000, 0 }, /* R239 */
- { 0x0000, 0x0000, 0 }, /* R240 */
- { 0x0000, 0x0000, 0 }, /* R241 */
- { 0x0000, 0x0000, 0 }, /* R242 */
- { 0x0000, 0x0000, 0 }, /* R243 */
- { 0x0000, 0x0000, 0 }, /* R244 */
- { 0x0000, 0x0000, 0 }, /* R245 */
- { 0x0000, 0x0000, 0 }, /* R246 */
- { 0x0001, 0x0001, 0 }, /* R247 - FLL NCO Test 0 */
- { 0x003F, 0x003F, 0 }, /* R248 - FLL NCO Test 1 */
-};
+static bool wm8904_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8904_SW_RESET_AND_ID:
+ case WM8904_REVISION:
+ case WM8904_DC_SERVO_1:
+ case WM8904_DC_SERVO_6:
+ case WM8904_DC_SERVO_7:
+ case WM8904_DC_SERVO_8:
+ case WM8904_DC_SERVO_9:
+ case WM8904_DC_SERVO_READBACK_0:
+ case WM8904_INTERRUPT_STATUS:
+ return true;
+ default:
+ return false;
+ }
+}
-static int wm8904_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8904_readable_register(struct device *dev, unsigned int reg)
{
- return wm8904_access[reg].vol;
+ switch (reg) {
+ case WM8904_SW_RESET_AND_ID:
+ case WM8904_REVISION:
+ case WM8904_BIAS_CONTROL_0:
+ case WM8904_VMID_CONTROL_0:
+ case WM8904_MIC_BIAS_CONTROL_0:
+ case WM8904_MIC_BIAS_CONTROL_1:
+ case WM8904_ANALOGUE_DAC_0:
+ case WM8904_MIC_FILTER_CONTROL:
+ case WM8904_ANALOGUE_ADC_0:
+ case WM8904_POWER_MANAGEMENT_0:
+ case WM8904_POWER_MANAGEMENT_2:
+ case WM8904_POWER_MANAGEMENT_3:
+ case WM8904_POWER_MANAGEMENT_6:
+ case WM8904_CLOCK_RATES_0:
+ case WM8904_CLOCK_RATES_1:
+ case WM8904_CLOCK_RATES_2:
+ case WM8904_AUDIO_INTERFACE_0:
+ case WM8904_AUDIO_INTERFACE_1:
+ case WM8904_AUDIO_INTERFACE_2:
+ case WM8904_AUDIO_INTERFACE_3:
+ case WM8904_DAC_DIGITAL_VOLUME_LEFT:
+ case WM8904_DAC_DIGITAL_VOLUME_RIGHT:
+ case WM8904_DAC_DIGITAL_0:
+ case WM8904_DAC_DIGITAL_1:
+ case WM8904_ADC_DIGITAL_VOLUME_LEFT:
+ case WM8904_ADC_DIGITAL_VOLUME_RIGHT:
+ case WM8904_ADC_DIGITAL_0:
+ case WM8904_DIGITAL_MICROPHONE_0:
+ case WM8904_DRC_0:
+ case WM8904_DRC_1:
+ case WM8904_DRC_2:
+ case WM8904_DRC_3:
+ case WM8904_ANALOGUE_LEFT_INPUT_0:
+ case WM8904_ANALOGUE_RIGHT_INPUT_0:
+ case WM8904_ANALOGUE_LEFT_INPUT_1:
+ case WM8904_ANALOGUE_RIGHT_INPUT_1:
+ case WM8904_ANALOGUE_OUT1_LEFT:
+ case WM8904_ANALOGUE_OUT1_RIGHT:
+ case WM8904_ANALOGUE_OUT2_LEFT:
+ case WM8904_ANALOGUE_OUT2_RIGHT:
+ case WM8904_ANALOGUE_OUT12_ZC:
+ case WM8904_DC_SERVO_0:
+ case WM8904_DC_SERVO_1:
+ case WM8904_DC_SERVO_2:
+ case WM8904_DC_SERVO_4:
+ case WM8904_DC_SERVO_5:
+ case WM8904_DC_SERVO_6:
+ case WM8904_DC_SERVO_7:
+ case WM8904_DC_SERVO_8:
+ case WM8904_DC_SERVO_9:
+ case WM8904_DC_SERVO_READBACK_0:
+ case WM8904_ANALOGUE_HP_0:
+ case WM8904_ANALOGUE_LINEOUT_0:
+ case WM8904_CHARGE_PUMP_0:
+ case WM8904_CLASS_W_0:
+ case WM8904_WRITE_SEQUENCER_0:
+ case WM8904_WRITE_SEQUENCER_1:
+ case WM8904_WRITE_SEQUENCER_2:
+ case WM8904_WRITE_SEQUENCER_3:
+ case WM8904_WRITE_SEQUENCER_4:
+ case WM8904_FLL_CONTROL_1:
+ case WM8904_FLL_CONTROL_2:
+ case WM8904_FLL_CONTROL_3:
+ case WM8904_FLL_CONTROL_4:
+ case WM8904_FLL_CONTROL_5:
+ case WM8904_GPIO_CONTROL_1:
+ case WM8904_GPIO_CONTROL_2:
+ case WM8904_GPIO_CONTROL_3:
+ case WM8904_GPIO_CONTROL_4:
+ case WM8904_DIGITAL_PULLS:
+ case WM8904_INTERRUPT_STATUS:
+ case WM8904_INTERRUPT_STATUS_MASK:
+ case WM8904_INTERRUPT_POLARITY:
+ case WM8904_INTERRUPT_DEBOUNCE:
+ case WM8904_EQ1:
+ case WM8904_EQ2:
+ case WM8904_EQ3:
+ case WM8904_EQ4:
+ case WM8904_EQ5:
+ case WM8904_EQ6:
+ case WM8904_EQ7:
+ case WM8904_EQ8:
+ case WM8904_EQ9:
+ case WM8904_EQ10:
+ case WM8904_EQ11:
+ case WM8904_EQ12:
+ case WM8904_EQ13:
+ case WM8904_EQ14:
+ case WM8904_EQ15:
+ case WM8904_EQ16:
+ case WM8904_EQ17:
+ case WM8904_EQ18:
+ case WM8904_EQ19:
+ case WM8904_EQ20:
+ case WM8904_EQ21:
+ case WM8904_EQ22:
+ case WM8904_EQ23:
+ case WM8904_EQ24:
+ case WM8904_CONTROL_INTERFACE_TEST_1:
+ case WM8904_ADC_TEST_0:
+ case WM8904_ANALOGUE_OUTPUT_BIAS_0:
+ case WM8904_FLL_NCO_TEST_0:
+ case WM8904_FLL_NCO_TEST_1:
+ return true;
+ default:
+ return true;
+ }
}
static int wm8904_reset(struct snd_soc_codec *codec)
@@ -857,6 +570,29 @@ static const char *hpf_mode_text[] = {
static const struct soc_enum hpf_mode =
SOC_ENUM_SINGLE(WM8904_ADC_DIGITAL_0, 5, 4, hpf_mode_text);
+static int wm8904_adc_osr_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ unsigned int val;
+ int ret;
+
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
+ if (ret < 0)
+ return ret;
+
+ if (ucontrol->value.integer.value[0])
+ val = 0;
+ else
+ val = WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5;
+
+ snd_soc_update_bits(codec, WM8904_ADC_TEST_0,
+ WM8904_ADC_128_OSR_TST_MODE | WM8904_ADC_BIASX1P5,
+ val);
+
+ return ret;
+}
+
static const struct snd_kcontrol_new wm8904_adc_snd_controls[] = {
SOC_DOUBLE_R_TLV("Digital Capture Volume", WM8904_ADC_DIGITAL_VOLUME_LEFT,
WM8904_ADC_DIGITAL_VOLUME_RIGHT, 1, 119, 0, digital_tlv),
@@ -868,12 +604,17 @@ SOC_ENUM("Right Capture Mode", rin_mode),
SOC_DOUBLE_R("Capture Volume", WM8904_ANALOGUE_LEFT_INPUT_0,
WM8904_ANALOGUE_RIGHT_INPUT_0, 0, 31, 0),
SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0,
- WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 0),
+ WM8904_ANALOGUE_RIGHT_INPUT_0, 7, 1, 1),
SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0),
SOC_ENUM("High Pass Filter Mode", hpf_mode),
-SOC_SINGLE("ADC 128x OSR Switch", WM8904_ANALOGUE_ADC_0, 0, 1, 0),
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "ADC 128x OSR Switch",
+ .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,
+ .put = wm8904_adc_osr_put,
+ .private_value = SOC_SINGLE_VALUE(WM8904_ANALOGUE_ADC_0, 0, 1, 0),
+},
};
static const char *drc_path_text[] = {
@@ -1197,7 +938,7 @@ SND_SOC_DAPM_INPUT("IN2R"),
SND_SOC_DAPM_INPUT("IN3L"),
SND_SOC_DAPM_INPUT("IN3R"),
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8904_MIC_BIAS_CONTROL_0, 0, 0, NULL, 0),
SND_SOC_DAPM_MUX("Left Capture Mux", SND_SOC_NOPM, 0, 0, &lin_mux),
SND_SOC_DAPM_MUX("Left Capture Inverting Mux", SND_SOC_NOPM, 0, 0,
@@ -1435,11 +1176,11 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
switch (wm8904->devtype) {
case WM8904:
- snd_soc_add_controls(codec, wm8904_adc_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_adc_snd_controls,
ARRAY_SIZE(wm8904_adc_snd_controls));
- snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
ARRAY_SIZE(wm8904_dac_snd_controls));
- snd_soc_add_controls(codec, wm8904_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_snd_controls,
ARRAY_SIZE(wm8904_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8904_adc_dapm_widgets,
@@ -1460,7 +1201,7 @@ static int wm8904_add_widgets(struct snd_soc_codec *codec)
break;
case WM8912:
- snd_soc_add_controls(codec, wm8904_dac_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8904_dac_snd_controls,
ARRAY_SIZE(wm8904_dac_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8904_dac_dapm_widgets,
@@ -2090,32 +1831,6 @@ static int wm8904_digital_mute(struct snd_soc_dai *codec_dai, int mute)
return 0;
}
-static void wm8904_sync_cache(struct snd_soc_codec *codec)
-{
- u16 *reg_cache = codec->reg_cache;
- int i;
-
- if (!codec->cache_sync)
- return;
-
- codec->cache_only = 0;
-
- /* Sync back cached values if they're different from the
- * hardware default.
- */
- for (i = 1; i < codec->driver->reg_cache_size; i++) {
- if (!wm8904_access[i].writable)
- continue;
-
- if (reg_cache[i] == wm8904_reg[i])
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
-
- codec->cache_sync = 0;
-}
-
static int wm8904_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -2148,7 +1863,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
- wm8904_sync_cache(codec);
+ regcache_sync(wm8904->regmap);
/* Enable bias */
snd_soc_update_bits(codec, WM8904_BIAS_CONTROL_0,
@@ -2206,7 +1921,7 @@ static int wm8904_set_bias_level(struct snd_soc_codec *codec,
#define WM8904_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8904_dai_ops = {
+static const struct snd_soc_dai_ops wm8904_dai_ops = {
.set_sysclk = wm8904_set_sysclk,
.set_fmt = wm8904_set_fmt,
.set_tdm_slot = wm8904_set_tdm_slot,
@@ -2236,7 +1951,7 @@ static struct snd_soc_dai_driver wm8904_dai = {
};
#ifdef CONFIG_PM
-static int wm8904_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8904_suspend(struct snd_soc_codec *codec)
{
wm8904_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -2305,7 +2020,7 @@ static void wm8904_handle_retune_mobile_pdata(struct snd_soc_codec *codec)
wm8904->retune_mobile_enum.max = wm8904->num_retune_mobile_texts;
wm8904->retune_mobile_enum.texts = wm8904->retune_mobile_texts;
- ret = snd_soc_add_controls(codec, &control, 1);
+ ret = snd_soc_add_codec_controls(codec, &control, 1);
if (ret != 0)
dev_err(codec->dev,
"Failed to add ReTune Mobile control: %d\n", ret);
@@ -2318,7 +2033,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
int ret, i;
if (!pdata) {
- snd_soc_add_controls(codec, wm8904_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8904_eq_controls,
ARRAY_SIZE(wm8904_eq_controls));
return;
}
@@ -2346,7 +2061,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
wm8904->drc_enum.max = pdata->num_drc_cfgs;
wm8904->drc_enum.texts = wm8904->drc_texts;
- ret = snd_soc_add_controls(codec, &control, 1);
+ ret = snd_soc_add_codec_controls(codec, &control, 1);
if (ret != 0)
dev_err(codec->dev,
"Failed to add DRC mode control: %d\n", ret);
@@ -2360,7 +2075,7 @@ static void wm8904_handle_pdata(struct snd_soc_codec *codec)
if (pdata->num_retune_mobile_cfgs)
wm8904_handle_retune_mobile_pdata(codec);
else
- snd_soc_add_controls(codec, wm8904_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8904_eq_controls,
ARRAY_SIZE(wm8904_eq_controls));
}
@@ -2373,7 +2088,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
int ret, i;
codec->cache_sync = 1;
- codec->dapm.idle_bias_off = 1;
+ codec->control_data = wm8904->regmap;
switch (wm8904->devtype) {
case WM8904:
@@ -2387,7 +2102,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
return -EINVAL;
}
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -2415,7 +2130,7 @@ static int wm8904_probe(struct snd_soc_codec *codec)
dev_err(codec->dev, "Failed to read ID register\n");
goto err_enable;
}
- if (ret != wm8904_reg[WM8904_SW_RESET_AND_ID]) {
+ if (ret != 0x8904) {
dev_err(codec->dev, "Device is not a WM8904, ID is %x\n", ret);
ret = -EINVAL;
goto err_enable;
@@ -2521,39 +2236,62 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8904 = {
.suspend = wm8904_suspend,
.resume = wm8904_resume,
.set_bias_level = wm8904_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8904_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8904_reg,
- .volatile_register = wm8904_volatile_register,
+ .idle_bias_off = true,
+};
+
+static const struct regmap_config wm8904_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = WM8904_MAX_REGISTER,
+ .volatile_reg = wm8904_volatile_register,
+ .readable_reg = wm8904_readable_register,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8904_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8904_reg_defaults),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8904_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8904_priv *wm8904;
int ret;
- wm8904 = kzalloc(sizeof(struct wm8904_priv), GFP_KERNEL);
+ wm8904 = devm_kzalloc(&i2c->dev, sizeof(struct wm8904_priv),
+ GFP_KERNEL);
if (wm8904 == NULL)
return -ENOMEM;
+ wm8904->regmap = regmap_init_i2c(i2c, &wm8904_regmap);
+ if (IS_ERR(wm8904->regmap)) {
+ ret = PTR_ERR(wm8904->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
wm8904->devtype = id->driver_data;
i2c_set_clientdata(i2c, wm8904);
- wm8904->control_data = i2c;
wm8904->pdata = i2c->dev.platform_data;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8904, &wm8904_dai, 1);
- if (ret < 0)
- kfree(wm8904);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(wm8904->regmap);
return ret;
}
static __devexit int wm8904_i2c_remove(struct i2c_client *client)
{
+ struct wm8904_priv *wm8904 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8904->regmap);
return 0;
}
@@ -2567,34 +2305,29 @@ MODULE_DEVICE_TABLE(i2c, wm8904_i2c_id);
static struct i2c_driver wm8904_i2c_driver = {
.driver = {
- .name = "wm8904-codec",
+ .name = "wm8904",
.owner = THIS_MODULE,
},
.probe = wm8904_i2c_probe,
.remove = __devexit_p(wm8904_i2c_remove),
.id_table = wm8904_i2c_id,
};
-#endif
static int __init wm8904_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8904_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register wm8904 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8904_modinit);
static void __exit wm8904_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8904_i2c_driver);
-#endif
}
module_exit(wm8904_exit);
diff --git a/sound/soc/codecs/wm8904.h b/sound/soc/codecs/wm8904.h
index 9e8c84188ba7..c29a0e8131ca 100644
--- a/sound/soc/codecs/wm8904.h
+++ b/sound/soc/codecs/wm8904.h
@@ -123,6 +123,7 @@
#define WM8904_EQ23 0x9C
#define WM8904_EQ24 0x9D
#define WM8904_CONTROL_INTERFACE_TEST_1 0xA1
+#define WM8904_ADC_TEST_0 0xC6
#define WM8904_ANALOGUE_OUTPUT_BIAS_0 0xCC
#define WM8904_FLL_NCO_TEST_0 0xF7
#define WM8904_FLL_NCO_TEST_1 0xF8
@@ -1557,6 +1558,16 @@
#define WM8904_USER_KEY_WIDTH 1 /* USER_KEY */
/*
+ * R198 (0xC6) - ADC Test 0
+ */
+#define WM8904_ADC_128_OSR_TST_MODE 0x0004 /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_128_OSR_TST_MODE_SHIFT 2 /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_128_OSR_TST_MODE_WIDTH 1 /* ADC_128_OSR_TST_MODE */
+#define WM8904_ADC_BIASX1P5 0x0001 /* ADC_BIASX1P5 */
+#define WM8904_ADC_BIASX1P5_SHIFT 0 /* ADC_BIASX1P5 */
+#define WM8904_ADC_BIASX1P5_WIDTH 1 /* ADC_BIASX1P5 */
+
+/*
* R204 (0xCC) - Analogue Output Bias 0
*/
#define WM8904_PGA_BIAS_MASK 0x0070 /* PGA_BIAS - [6:4] */
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c
index 056daa0010f9..d2883affea3b 100644
--- a/sound/soc/codecs/wm8940.c
+++ b/sound/soc/codecs/wm8940.c
@@ -28,7 +28,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -43,9 +42,19 @@
struct wm8940_priv {
unsigned int sysclk;
enum snd_soc_control_type control_type;
- void *control_data;
};
+static int wm8940_volatile_register(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ switch (reg) {
+ case WM8940_SOFTRESET:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static u16 wm8940_reg_defaults[] = {
0x8940, /* Soft Reset */
0x0000, /* Power 1 */
@@ -460,6 +469,14 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
ret = snd_soc_write(codec, WM8940_POWER1, pwr_reg | 0x1);
break;
case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ ret = snd_soc_cache_sync(codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
+ return ret;
+ }
+ }
+
/* ensure bufioen and biasen */
pwr_reg |= (1 << 2) | (1 << 3);
/* set vmid to 300k for standby */
@@ -470,6 +487,8 @@ static int wm8940_set_bias_level(struct snd_soc_codec *codec,
break;
}
+ codec->dapm.bias_level = level;
+
return ret;
}
@@ -601,7 +620,7 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
switch (div_id) {
case WM8940_BCLKDIV:
- reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFEF3;
+ reg = snd_soc_read(codec, WM8940_CLOCK) & 0xFFE3;
ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 2));
break;
case WM8940_MCLKDIV:
@@ -609,8 +628,8 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
ret = snd_soc_write(codec, WM8940_CLOCK, reg | (div << 5));
break;
case WM8940_OPCLKDIV:
- reg = snd_soc_read(codec, WM8940_ADDCNTRL) & 0xFFCF;
- ret = snd_soc_write(codec, WM8940_ADDCNTRL, reg | (div << 4));
+ reg = snd_soc_read(codec, WM8940_GPIO) & 0xFFCF;
+ ret = snd_soc_write(codec, WM8940_GPIO, reg | (div << 4));
break;
}
return ret;
@@ -624,7 +643,7 @@ static int wm8940_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8940_dai_ops = {
+static const struct snd_soc_dai_ops wm8940_dai_ops = {
.hw_params = wm8940_i2s_hw_params,
.set_sysclk = wm8940_set_dai_sysclk,
.digital_mute = wm8940_mute,
@@ -653,37 +672,15 @@ static struct snd_soc_dai_driver wm8940_dai = {
.symmetric_rates = 1,
};
-static int wm8940_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8940_suspend(struct snd_soc_codec *codec)
{
return wm8940_set_bias_level(codec, SND_SOC_BIAS_OFF);
}
static int wm8940_resume(struct snd_soc_codec *codec)
{
- int i;
- int ret;
- u8 data[3];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware
- * Could use auto incremented writes to speed this up
- */
- for (i = 0; i < ARRAY_SIZE(wm8940_reg_defaults); i++) {
- data[0] = i;
- data[1] = (cache[i] & 0xFF00) >> 8;
- data[2] = cache[i] & 0x00FF;
- ret = codec->hw_write(codec->control_data, data, 3);
- if (ret < 0)
- goto error_ret;
- else if (ret != 3) {
- ret = -EIO;
- goto error_ret;
- }
- }
- ret = wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
-error_ret:
- return ret;
+ wm8940_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ return 0;
}
static int wm8940_probe(struct snd_soc_codec *codec)
@@ -693,7 +690,6 @@ static int wm8940_probe(struct snd_soc_codec *codec)
int ret;
u16 reg;
- codec->control_data = wm8940->control_data;
ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8940->control_type);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
@@ -721,7 +717,7 @@ static int wm8940_probe(struct snd_soc_codec *codec)
return ret;
}
- ret = snd_soc_add_controls(codec, wm8940_snd_controls,
+ ret = snd_soc_add_codec_controls(codec, wm8940_snd_controls,
ARRAY_SIZE(wm8940_snd_controls));
if (ret)
return ret;
@@ -744,34 +740,33 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8940 = {
.reg_cache_size = ARRAY_SIZE(wm8940_reg_defaults),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8940_reg_defaults,
+ .volatile_register = wm8940_volatile_register,
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8940_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8940_priv *wm8940;
int ret;
- wm8940 = kzalloc(sizeof(struct wm8940_priv), GFP_KERNEL);
+ wm8940 = devm_kzalloc(&i2c->dev, sizeof(struct wm8940_priv),
+ GFP_KERNEL);
if (wm8940 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8940);
- wm8940->control_data = i2c;
wm8940->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8940, &wm8940_dai, 1);
- if (ret < 0)
- kfree(wm8940);
+
return ret;
}
static __devexit int wm8940_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+
return 0;
}
@@ -783,34 +778,29 @@ MODULE_DEVICE_TABLE(i2c, wm8940_i2c_id);
static struct i2c_driver wm8940_i2c_driver = {
.driver = {
- .name = "wm8940-codec",
+ .name = "wm8940",
.owner = THIS_MODULE,
},
.probe = wm8940_i2c_probe,
.remove = __devexit_p(wm8940_i2c_remove),
.id_table = wm8940_i2c_id,
};
-#endif
static int __init wm8940_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8940_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8940_modinit);
static void __exit wm8940_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8940_i2c_driver);
-#endif
}
module_exit(wm8940_exit);
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c
index 3c7198779c31..61fe97433e73 100644
--- a/sound/soc/codecs/wm8955.c
+++ b/sound/soc/codecs/wm8955.c
@@ -16,7 +16,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
@@ -39,7 +39,7 @@ static const char *wm8955_supply_names[WM8955_NUM_SUPPLIES] = {
/* codec private data */
struct wm8955_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
unsigned int mclk_rate;
@@ -49,69 +49,85 @@ struct wm8955_priv {
struct regulator_bulk_data supplies[WM8955_NUM_SUPPLIES];
};
-static const u16 wm8955_reg[WM8955_MAX_REGISTER + 1] = {
- 0x0000, /* R0 */
- 0x0000, /* R1 */
- 0x0079, /* R2 - LOUT1 volume */
- 0x0079, /* R3 - ROUT1 volume */
- 0x0000, /* R4 */
- 0x0008, /* R5 - DAC Control */
- 0x0000, /* R6 */
- 0x000A, /* R7 - Audio Interface */
- 0x0000, /* R8 - Sample Rate */
- 0x0000, /* R9 */
- 0x00FF, /* R10 - Left DAC volume */
- 0x00FF, /* R11 - Right DAC volume */
- 0x000F, /* R12 - Bass control */
- 0x000F, /* R13 - Treble control */
- 0x0000, /* R14 */
- 0x0000, /* R15 - Reset */
- 0x0000, /* R16 */
- 0x0000, /* R17 */
- 0x0000, /* R18 */
- 0x0000, /* R19 */
- 0x0000, /* R20 */
- 0x0000, /* R21 */
- 0x0000, /* R22 */
- 0x00C1, /* R23 - Additional control (1) */
- 0x0000, /* R24 - Additional control (2) */
- 0x0000, /* R25 - Power Management (1) */
- 0x0000, /* R26 - Power Management (2) */
- 0x0000, /* R27 - Additional Control (3) */
- 0x0000, /* R28 */
- 0x0000, /* R29 */
- 0x0000, /* R30 */
- 0x0000, /* R31 */
- 0x0000, /* R32 */
- 0x0000, /* R33 */
- 0x0050, /* R34 - Left out Mix (1) */
- 0x0050, /* R35 - Left out Mix (2) */
- 0x0050, /* R36 - Right out Mix (1) */
- 0x0050, /* R37 - Right Out Mix (2) */
- 0x0050, /* R38 - Mono out Mix (1) */
- 0x0050, /* R39 - Mono out Mix (2) */
- 0x0079, /* R40 - LOUT2 volume */
- 0x0079, /* R41 - ROUT2 volume */
- 0x0079, /* R42 - MONOOUT volume */
- 0x0000, /* R43 - Clocking / PLL */
- 0x0103, /* R44 - PLL Control 1 */
- 0x0024, /* R45 - PLL Control 2 */
- 0x01BA, /* R46 - PLL Control 3 */
- 0x0000, /* R47 */
- 0x0000, /* R48 */
- 0x0000, /* R49 */
- 0x0000, /* R50 */
- 0x0000, /* R51 */
- 0x0000, /* R52 */
- 0x0000, /* R53 */
- 0x0000, /* R54 */
- 0x0000, /* R55 */
- 0x0000, /* R56 */
- 0x0000, /* R57 */
- 0x0000, /* R58 */
- 0x0000, /* R59 - PLL Control 4 */
+static const struct reg_default wm8955_reg_defaults[] = {
+ { 2, 0x0079 }, /* R2 - LOUT1 volume */
+ { 3, 0x0079 }, /* R3 - ROUT1 volume */
+ { 5, 0x0008 }, /* R5 - DAC Control */
+ { 7, 0x000A }, /* R7 - Audio Interface */
+ { 8, 0x0000 }, /* R8 - Sample Rate */
+ { 10, 0x00FF }, /* R10 - Left DAC volume */
+ { 11, 0x00FF }, /* R11 - Right DAC volume */
+ { 12, 0x000F }, /* R12 - Bass control */
+ { 13, 0x000F }, /* R13 - Treble control */
+ { 23, 0x00C1 }, /* R23 - Additional control (1) */
+ { 24, 0x0000 }, /* R24 - Additional control (2) */
+ { 25, 0x0000 }, /* R25 - Power Management (1) */
+ { 26, 0x0000 }, /* R26 - Power Management (2) */
+ { 27, 0x0000 }, /* R27 - Additional Control (3) */
+ { 34, 0x0050 }, /* R34 - Left out Mix (1) */
+ { 35, 0x0050 }, /* R35 - Left out Mix (2) */
+ { 36, 0x0050 }, /* R36 - Right out Mix (1) */
+ { 37, 0x0050 }, /* R37 - Right Out Mix (2) */
+ { 38, 0x0050 }, /* R38 - Mono out Mix (1) */
+ { 39, 0x0050 }, /* R39 - Mono out Mix (2) */
+ { 40, 0x0079 }, /* R40 - LOUT2 volume */
+ { 41, 0x0079 }, /* R41 - ROUT2 volume */
+ { 42, 0x0079 }, /* R42 - MONOOUT volume */
+ { 43, 0x0000 }, /* R43 - Clocking / PLL */
+ { 44, 0x0103 }, /* R44 - PLL Control 1 */
+ { 45, 0x0024 }, /* R45 - PLL Control 2 */
+ { 46, 0x01BA }, /* R46 - PLL Control 3 */
+ { 59, 0x0000 }, /* R59 - PLL Control 4 */
};
+static bool wm8955_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8955_LOUT1_VOLUME:
+ case WM8955_ROUT1_VOLUME:
+ case WM8955_DAC_CONTROL:
+ case WM8955_AUDIO_INTERFACE:
+ case WM8955_SAMPLE_RATE:
+ case WM8955_LEFT_DAC_VOLUME:
+ case WM8955_RIGHT_DAC_VOLUME:
+ case WM8955_BASS_CONTROL:
+ case WM8955_TREBLE_CONTROL:
+ case WM8955_RESET:
+ case WM8955_ADDITIONAL_CONTROL_1:
+ case WM8955_ADDITIONAL_CONTROL_2:
+ case WM8955_POWER_MANAGEMENT_1:
+ case WM8955_POWER_MANAGEMENT_2:
+ case WM8955_ADDITIONAL_CONTROL_3:
+ case WM8955_LEFT_OUT_MIX_1:
+ case WM8955_LEFT_OUT_MIX_2:
+ case WM8955_RIGHT_OUT_MIX_1:
+ case WM8955_RIGHT_OUT_MIX_2:
+ case WM8955_MONO_OUT_MIX_1:
+ case WM8955_MONO_OUT_MIX_2:
+ case WM8955_LOUT2_VOLUME:
+ case WM8955_ROUT2_VOLUME:
+ case WM8955_MONOOUT_VOLUME:
+ case WM8955_CLOCKING_PLL:
+ case WM8955_PLL_CONTROL_1:
+ case WM8955_PLL_CONTROL_2:
+ case WM8955_PLL_CONTROL_3:
+ case WM8955_PLL_CONTROL_4:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm8955_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8955_RESET:
+ return true;
+ default:
+ return false;
+ }
+}
+
static int wm8955_reset(struct snd_soc_codec *codec)
{
return snd_soc_write(codec, WM8955_RESET, 0);
@@ -528,7 +544,7 @@ SND_SOC_DAPM_OUTPUT("MONOOUT"),
SND_SOC_DAPM_OUTPUT("OUT3"),
};
-static const struct snd_soc_dapm_route wm8955_intercon[] = {
+static const struct snd_soc_dapm_route wm8955_dapm_routes[] = {
{ "DACL", NULL, "SYSCLK" },
{ "DACR", NULL, "SYSCLK" },
@@ -573,21 +589,6 @@ static const struct snd_soc_dapm_route wm8955_intercon[] = {
{ "OUT3", NULL, "OUT3 PGA" },
};
-static int wm8955_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_add_controls(codec, wm8955_snd_controls,
- ARRAY_SIZE(wm8955_snd_controls));
-
- snd_soc_dapm_new_controls(dapm, wm8955_dapm_widgets,
- ARRAY_SIZE(wm8955_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, wm8955_intercon,
- ARRAY_SIZE(wm8955_intercon));
-
- return 0;
-}
-
static int wm8955_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
@@ -766,8 +767,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
- u16 *reg_cache = codec->reg_cache;
- int ret, i;
+ int ret;
switch (level) {
case SND_SOC_BIAS_ON:
@@ -796,18 +796,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
- /* Sync back cached values if they're
- * different from the hardware default.
- */
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- if (i == WM8955_RESET)
- continue;
-
- if (reg_cache[i] == wm8955_reg[i])
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
+ regcache_sync(wm8955->regmap);
/* Enable VREF and VMID */
snd_soc_update_bits(codec, WM8955_POWER_MANAGEMENT_1,
@@ -859,7 +848,7 @@ static int wm8955_set_bias_level(struct snd_soc_codec *codec,
#define WM8955_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8955_dai_ops = {
+static const struct snd_soc_dai_ops wm8955_dai_ops = {
.set_sysclk = wm8955_set_sysclk,
.set_fmt = wm8955_set_fmt,
.hw_params = wm8955_hw_params,
@@ -879,10 +868,14 @@ static struct snd_soc_dai_driver wm8955_dai = {
};
#ifdef CONFIG_PM
-static int wm8955_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8955_suspend(struct snd_soc_codec *codec)
{
+ struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
+
wm8955_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regcache_mark_dirty(wm8955->regmap);
+
return 0;
}
@@ -901,10 +894,11 @@ static int wm8955_probe(struct snd_soc_codec *codec)
{
struct wm8955_priv *wm8955 = snd_soc_codec_get_drvdata(codec);
struct wm8955_pdata *pdata = dev_get_platdata(codec->dev);
- u16 *reg_cache = codec->reg_cache;
int ret, i;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8955->control_type);
+ codec->control_data = wm8955->regmap;
+
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -959,12 +953,12 @@ static int wm8955_probe(struct snd_soc_codec *codec)
/* Set platform data values */
if (pdata) {
if (pdata->out2_speaker)
- reg_cache[WM8955_ADDITIONAL_CONTROL_2]
- |= WM8955_ROUT2INV;
+ snd_soc_update_bits(codec, WM8955_ADDITIONAL_CONTROL_2,
+ WM8955_ROUT2INV, WM8955_ROUT2INV);
if (pdata->monoin_diff)
- reg_cache[WM8955_MONO_OUT_MIX_1]
- |= WM8955_DMEN;
+ snd_soc_update_bits(codec, WM8955_MONO_OUT_MIX_1,
+ WM8955_DMEN, WM8955_DMEN);
}
wm8955_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -972,7 +966,6 @@ static int wm8955_probe(struct snd_soc_codec *codec)
/* Bias level configuration will have done an extra enable */
regulator_bulk_disable(ARRAY_SIZE(wm8955->supplies), wm8955->supplies);
- wm8955_add_widgets(codec);
return 0;
err_enable:
@@ -997,36 +990,68 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8955 = {
.suspend = wm8955_suspend,
.resume = wm8955_resume,
.set_bias_level = wm8955_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8955_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8955_reg,
+
+ .controls = wm8955_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8955_snd_controls),
+ .dapm_widgets = wm8955_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8955_dapm_widgets),
+ .dapm_routes = wm8955_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8955_dapm_routes),
+};
+
+static const struct regmap_config wm8955_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8955_MAX_REGISTER,
+ .volatile_reg = wm8955_volatile,
+ .writeable_reg = wm8955_writeable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8955_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8955_reg_defaults),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8955_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8955_priv *wm8955;
int ret;
- wm8955 = kzalloc(sizeof(struct wm8955_priv), GFP_KERNEL);
+ wm8955 = devm_kzalloc(&i2c->dev, sizeof(struct wm8955_priv),
+ GFP_KERNEL);
if (wm8955 == NULL)
return -ENOMEM;
+ wm8955->regmap = regmap_init_i2c(i2c, &wm8955_regmap);
+ if (IS_ERR(wm8955->regmap)) {
+ ret = PTR_ERR(wm8955->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, wm8955);
- wm8955->control_type = SND_SOC_I2C;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8955, &wm8955_dai, 1);
- if (ret < 0)
- kfree(wm8955);
+ if (ret != 0)
+ goto err;
+
+ return ret;
+
+err:
+ regmap_exit(wm8955->regmap);
return ret;
}
static __devexit int wm8955_i2c_remove(struct i2c_client *client)
{
+ struct wm8955_priv *wm8955 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8955->regmap);
+
return 0;
}
@@ -1038,34 +1063,29 @@ MODULE_DEVICE_TABLE(i2c, wm8955_i2c_id);
static struct i2c_driver wm8955_i2c_driver = {
.driver = {
- .name = "wm8955-codec",
+ .name = "wm8955",
.owner = THIS_MODULE,
},
.probe = wm8955_i2c_probe,
.remove = __devexit_p(wm8955_i2c_remove),
.id_table = wm8955_i2c_id,
};
-#endif
static int __init wm8955_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8955_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8955_modinit);
static void __exit wm8955_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8955_i2c_driver);
-#endif
}
module_exit(wm8955_exit);
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c
index 0293763debe5..1332692ef81b 100644
--- a/sound/soc/codecs/wm8958-dsp2.c
+++ b/sound/soc/codecs/wm8958-dsp2.c
@@ -55,11 +55,14 @@ static int wm8958_dsp2_fw(struct snd_soc_codec *codec, const char *name,
return 0;
if (fw->size < 32) {
- dev_err(codec->dev, "%s: firmware too short\n", name);
+ dev_err(codec->dev, "%s: firmware too short (%zd bytes)\n",
+ name, fw->size);
goto err;
}
if (memcmp(fw->data, "WMFW", 4) != 0) {
+ memcpy(&data32, fw->data, sizeof(data32));
+ data32 = be32_to_cpu(data32);
dev_err(codec->dev, "%s: firmware has bad file magic %08x\n",
name, data32);
goto err;
@@ -917,11 +920,11 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->dsp_active = -1;
- snd_soc_add_controls(codec, wm8958_mbc_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_mbc_snd_controls,
ARRAY_SIZE(wm8958_mbc_snd_controls));
- snd_soc_add_controls(codec, wm8958_vss_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_vss_snd_controls,
ARRAY_SIZE(wm8958_vss_snd_controls));
- snd_soc_add_controls(codec, wm8958_enh_eq_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_enh_eq_snd_controls,
ARRAY_SIZE(wm8958_enh_eq_snd_controls));
@@ -955,7 +958,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->mbc_enum.max = pdata->num_mbc_cfgs;
wm8994->mbc_enum.texts = wm8994->mbc_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add MBC mode controls: %d\n", ret);
@@ -983,7 +986,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->vss_enum.max = pdata->num_vss_cfgs;
wm8994->vss_enum.texts = wm8994->vss_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add VSS mode controls: %d\n", ret);
@@ -1012,7 +1015,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs;
wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add VSS HPFmode controls: %d\n",
@@ -1042,7 +1045,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec)
wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs;
wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts;
- ret = snd_soc_add_controls(wm8994->codec, control, 1);
+ ret = snd_soc_add_codec_controls(wm8994->codec, control, 1);
if (ret != 0)
dev_err(wm8994->codec->dev,
"Failed to add enhanced EQ controls: %d\n",
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c
index 4393394b7bc1..840d72086d04 100644
--- a/sound/soc/codecs/wm8960.c
+++ b/sound/soc/codecs/wm8960.c
@@ -14,7 +14,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -26,8 +25,6 @@
#include "wm8960.h"
-#define AUDIO_NAME "wm8960"
-
/* R25 - Power 1 */
#define WM8960_VMID_MASK 0x180
#define WM8960_VREF 0x40
@@ -72,7 +69,6 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = {
struct wm8960_priv {
enum snd_soc_control_type control_type;
- void *control_data;
int (*set_bias_level)(struct snd_soc_codec *,
enum snd_soc_bias_level level);
struct snd_soc_dapm_widget *lout1;
@@ -266,7 +262,7 @@ SND_SOC_DAPM_INPUT("RINPUT2"),
SND_SOC_DAPM_INPUT("LINPUT3"),
SND_SOC_DAPM_INPUT("RINPUT3"),
-SND_SOC_DAPM_MICBIAS("MICB", WM8960_POWER1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICB", WM8960_POWER1, 1, 0, NULL, 0),
SND_SOC_DAPM_MIXER("Left Boost Mixer", WM8960_POWER1, 5, 0,
wm8960_lin_boost, ARRAY_SIZE(wm8960_lin_boost)),
@@ -547,57 +543,49 @@ static int wm8960_hw_params(struct snd_pcm_substream *substream,
static int wm8960_mute(struct snd_soc_dai *dai, int mute)
{
struct snd_soc_codec *codec = dai->codec;
- u16 mute_reg = snd_soc_read(codec, WM8960_DACCTL1) & 0xfff7;
if (mute)
- snd_soc_write(codec, WM8960_DACCTL1, mute_reg | 0x8);
+ snd_soc_update_bits(codec, WM8960_DACCTL1, 0x8, 0x8);
else
- snd_soc_write(codec, WM8960_DACCTL1, mute_reg);
+ snd_soc_update_bits(codec, WM8960_DACCTL1, 0x8, 0);
return 0;
}
static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 reg;
-
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
/* Set VMID to 2x50k */
- reg = snd_soc_read(codec, WM8960_POWER1);
- reg &= ~0x180;
- reg |= 0x80;
- snd_soc_write(codec, WM8960_POWER1, reg);
+ snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x80);
break;
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ snd_soc_cache_sync(codec);
+
/* Enable anti-pop features */
snd_soc_write(codec, WM8960_APOP1,
WM8960_POBCTRL | WM8960_SOFT_ST |
WM8960_BUFDCOPEN | WM8960_BUFIOEN);
/* Enable & ramp VMID at 2x50k */
- reg = snd_soc_read(codec, WM8960_POWER1);
- reg |= 0x80;
- snd_soc_write(codec, WM8960_POWER1, reg);
+ snd_soc_update_bits(codec, WM8960_POWER1, 0x80, 0x80);
msleep(100);
/* Enable VREF */
- snd_soc_write(codec, WM8960_POWER1, reg | WM8960_VREF);
+ snd_soc_update_bits(codec, WM8960_POWER1, WM8960_VREF,
+ WM8960_VREF);
/* Disable anti-pop features */
snd_soc_write(codec, WM8960_APOP1, WM8960_BUFIOEN);
}
/* Set VMID to 2x250k */
- reg = snd_soc_read(codec, WM8960_POWER1);
- reg &= ~0x180;
- reg |= 0x100;
- snd_soc_write(codec, WM8960_POWER1, reg);
+ snd_soc_update_bits(codec, WM8960_POWER1, 0x180, 0x100);
break;
case SND_SOC_BIAS_OFF:
@@ -677,6 +665,9 @@ static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec,
WM8960_VREF | WM8960_VMID_MASK, 0);
break;
+ case SND_SOC_BIAS_OFF:
+ snd_soc_cache_sync(codec);
+ break;
default:
break;
}
@@ -786,10 +777,8 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
/* Disable the PLL: even if we are changing the frequency the
* PLL needs to be disabled while we do so. */
- snd_soc_write(codec, WM8960_CLOCK1,
- snd_soc_read(codec, WM8960_CLOCK1) & ~1);
- snd_soc_write(codec, WM8960_POWER2,
- snd_soc_read(codec, WM8960_POWER2) & ~1);
+ snd_soc_update_bits(codec, WM8960_CLOCK1, 0x1, 0);
+ snd_soc_update_bits(codec, WM8960_POWER2, 0x1, 0);
if (!freq_in || !freq_out)
return 0;
@@ -808,11 +797,9 @@ static int wm8960_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
snd_soc_write(codec, WM8960_PLL1, reg);
/* Turn it on */
- snd_soc_write(codec, WM8960_POWER2,
- snd_soc_read(codec, WM8960_POWER2) | 1);
+ snd_soc_update_bits(codec, WM8960_POWER2, 0x1, 0x1);
msleep(250);
- snd_soc_write(codec, WM8960_CLOCK1,
- snd_soc_read(codec, WM8960_CLOCK1) | 1);
+ snd_soc_update_bits(codec, WM8960_CLOCK1, 0x1, 0x1);
return 0;
}
@@ -865,7 +852,7 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec,
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8960_dai_ops = {
+static const struct snd_soc_dai_ops wm8960_dai_ops = {
.hw_params = wm8960_hw_params,
.digital_mute = wm8960_mute,
.set_fmt = wm8960_set_dai_fmt,
@@ -891,7 +878,7 @@ static struct snd_soc_dai_driver wm8960_dai = {
.symmetric_rates = 1,
};
-static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8960_suspend(struct snd_soc_codec *codec)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
@@ -902,16 +889,6 @@ static int wm8960_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8960_resume(struct snd_soc_codec *codec)
{
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8960_reg); i++) {
- data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -922,10 +899,8 @@ static int wm8960_probe(struct snd_soc_codec *codec)
struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec);
struct wm8960_data *pdata = dev_get_platdata(codec->dev);
int ret;
- u16 reg;
wm8960->set_bias_level = wm8960_set_bias_level_out3;
- codec->control_data = wm8960->control_data;
if (!pdata) {
dev_warn(codec->dev, "No platform data supplied\n");
@@ -954,28 +929,18 @@ static int wm8960_probe(struct snd_soc_codec *codec)
wm8960->set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* Latch the update bits */
- reg = snd_soc_read(codec, WM8960_LINVOL);
- snd_soc_write(codec, WM8960_LINVOL, reg | 0x100);
- reg = snd_soc_read(codec, WM8960_RINVOL);
- snd_soc_write(codec, WM8960_RINVOL, reg | 0x100);
- reg = snd_soc_read(codec, WM8960_LADC);
- snd_soc_write(codec, WM8960_LADC, reg | 0x100);
- reg = snd_soc_read(codec, WM8960_RADC);
- snd_soc_write(codec, WM8960_RADC, reg | 0x100);
- reg = snd_soc_read(codec, WM8960_LDAC);
- snd_soc_write(codec, WM8960_LDAC, reg | 0x100);
- reg = snd_soc_read(codec, WM8960_RDAC);
- snd_soc_write(codec, WM8960_RDAC, reg | 0x100);
- reg = snd_soc_read(codec, WM8960_LOUT1);
- snd_soc_write(codec, WM8960_LOUT1, reg | 0x100);
- reg = snd_soc_read(codec, WM8960_ROUT1);
- snd_soc_write(codec, WM8960_ROUT1, reg | 0x100);
- reg = snd_soc_read(codec, WM8960_LOUT2);
- snd_soc_write(codec, WM8960_LOUT2, reg | 0x100);
- reg = snd_soc_read(codec, WM8960_ROUT2);
- snd_soc_write(codec, WM8960_ROUT2, reg | 0x100);
-
- snd_soc_add_controls(codec, wm8960_snd_controls,
+ snd_soc_update_bits(codec, WM8960_LINVOL, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8960_RINVOL, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8960_LADC, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8960_RADC, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8960_LDAC, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8960_RDAC, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8960_LOUT1, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8960_ROUT1, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8960_LOUT2, 0x100, 0x100);
+ snd_soc_update_bits(codec, WM8960_ROUT2, 0x100, 0x100);
+
+ snd_soc_add_codec_controls(codec, wm8960_snd_controls,
ARRAY_SIZE(wm8960_snd_controls));
wm8960_add_widgets(codec);
@@ -1002,32 +967,29 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8960 = {
.reg_cache_default = wm8960_reg,
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8960_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8960_priv *wm8960;
int ret;
- wm8960 = kzalloc(sizeof(struct wm8960_priv), GFP_KERNEL);
+ wm8960 = devm_kzalloc(&i2c->dev, sizeof(struct wm8960_priv),
+ GFP_KERNEL);
if (wm8960 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8960);
wm8960->control_type = SND_SOC_I2C;
- wm8960->control_data = i2c;
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8960, &wm8960_dai, 1);
- if (ret < 0)
- kfree(wm8960);
+
return ret;
}
static __devexit int wm8960_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
@@ -1039,34 +1001,29 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id);
static struct i2c_driver wm8960_i2c_driver = {
.driver = {
- .name = "wm8960-codec",
+ .name = "wm8960",
.owner = THIS_MODULE,
},
.probe = wm8960_i2c_probe,
.remove = __devexit_p(wm8960_i2c_remove),
.id_table = wm8960_i2c_id,
};
-#endif
static int __init wm8960_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8960_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8960_modinit);
static void __exit wm8960_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8960_i2c_driver);
-#endif
}
module_exit(wm8960_exit);
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c
index cdee8103d09b..05ea7c274093 100644
--- a/sound/soc/codecs/wm8961.c
+++ b/sound/soc/codecs/wm8961.c
@@ -17,7 +17,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -423,11 +422,11 @@ static int wm8961_spk_event(struct snd_soc_dapm_widget *w,
}
if (event & SND_SOC_DAPM_PRE_PMD) {
- /* Enable the amplifier */
+ /* Disable the amplifier */
spk_reg &= ~(WM8961_SPKL_ENA | WM8961_SPKR_ENA);
snd_soc_write(codec, WM8961_CLASS_D_CONTROL_1, spk_reg);
- /* Enable the PGA */
+ /* Disable the PGA */
pwr_reg &= ~(WM8961_SPKL_PGA | WM8961_SPKR_PGA);
snd_soc_write(codec, WM8961_PWR_MGMT_2, pwr_reg);
}
@@ -531,7 +530,7 @@ SND_SOC_DAPM_PGA("Right Input", WM8961_PWR_MGMT_1, 4, 0, NULL, 0),
SND_SOC_DAPM_ADC("ADCL", "HiFi Capture", WM8961_PWR_MGMT_1, 3, 0),
SND_SOC_DAPM_ADC("ADCR", "HiFi Capture", WM8961_PWR_MGMT_1, 2, 0),
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8961_PWR_MGMT_1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8961_PWR_MGMT_1, 1, 0, NULL, 0),
SND_SOC_DAPM_MUX("DACL Sidetone", SND_SOC_NOPM, 0, 0, &dacl_mux),
SND_SOC_DAPM_MUX("DACR Sidetone", SND_SOC_NOPM, 0, 0, &dacr_mux),
@@ -929,7 +928,7 @@ static int wm8961_set_bias_level(struct snd_soc_codec *codec,
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8961_dai_ops = {
+static const struct snd_soc_dai_ops wm8961_dai_ops = {
.hw_params = wm8961_hw_params,
.set_sysclk = wm8961_set_sysclk,
.set_fmt = wm8961_set_fmt,
@@ -974,7 +973,9 @@ static int wm8961_probe(struct snd_soc_codec *codec)
}
/* This isn't volatile - readback doesn't correspond to write */
- reg = codec->hw_read(codec, WM8961_RIGHT_INPUT_VOLUME);
+ codec->cache_bypass = 1;
+ reg = snd_soc_read(codec, WM8961_RIGHT_INPUT_VOLUME);
+ codec->cache_bypass = 0;
dev_info(codec->dev, "WM8961 family %d revision %c\n",
(reg & WM8961_DEVICE_ID_MASK) >> WM8961_DEVICE_ID_SHIFT,
((reg & WM8961_CHIP_REV_MASK) >> WM8961_CHIP_REV_SHIFT)
@@ -1021,7 +1022,7 @@ static int wm8961_probe(struct snd_soc_codec *codec)
wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8961_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8961_snd_controls,
ARRAY_SIZE(wm8961_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8961_dapm_widgets,
ARRAY_SIZE(wm8961_dapm_widgets));
@@ -1037,7 +1038,7 @@ static int wm8961_remove(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8961_suspend(struct snd_soc_codec *codec)
{
wm8961_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -1046,18 +1047,7 @@ static int wm8961_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8961_resume(struct snd_soc_codec *codec)
{
- u16 *reg_cache = codec->reg_cache;
- int i;
-
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- if (reg_cache[i] == wm8961_reg_defaults[i])
- continue;
-
- if (i == WM8961_SOFTWARE_RESET)
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
+ snd_soc_cache_sync(codec);
wm8961_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -1080,14 +1070,14 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8961 = {
.volatile_register = wm8961_volatile_register,
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8961_priv *wm8961;
int ret;
- wm8961 = kzalloc(sizeof(struct wm8961_priv), GFP_KERNEL);
+ wm8961 = devm_kzalloc(&i2c->dev, sizeof(struct wm8961_priv),
+ GFP_KERNEL);
if (wm8961 == NULL)
return -ENOMEM;
@@ -1095,15 +1085,14 @@ static __devinit int wm8961_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8961, &wm8961_dai, 1);
- if (ret < 0)
- kfree(wm8961);
+
return ret;
}
static __devexit int wm8961_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+
return 0;
}
@@ -1115,34 +1104,29 @@ MODULE_DEVICE_TABLE(i2c, wm8961_i2c_id);
static struct i2c_driver wm8961_i2c_driver = {
.driver = {
- .name = "wm8961-codec",
+ .name = "wm8961",
.owner = THIS_MODULE,
},
.probe = wm8961_i2c_probe,
.remove = __devexit_p(wm8961_i2c_remove),
.id_table = wm8961_i2c_id,
};
-#endif
static int __init wm8961_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8961_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8961_modinit);
static void __exit wm8961_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8961_i2c_driver);
-#endif
}
module_exit(wm8961_exit);
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c
index 1725550c293e..15d467ff91b4 100644
--- a/sound/soc/codecs/wm8962.c
+++ b/sound/soc/codecs/wm8962.c
@@ -20,7 +20,8 @@
#include <linux/gpio.h>
#include <linux/i2c.h>
#include <linux/input.h>
-#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
@@ -50,6 +51,7 @@ static const char *wm8962_supply_names[WM8962_NUM_SUPPLIES] = {
/* codec private data */
struct wm8962_priv {
+ struct regmap *regmap;
struct snd_soc_codec *codec;
int sysclk;
@@ -63,6 +65,8 @@ struct wm8962_priv {
int fll_fref;
int fll_fout;
+ u16 dsp2_ena;
+
struct delayed_work mic_work;
struct snd_soc_jack *jack;
@@ -93,7 +97,7 @@ static int wm8962_regulator_event_##n(struct notifier_block *nb, \
struct wm8962_priv *wm8962 = container_of(nb, struct wm8962_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- wm8962->codec->cache_sync = 1; \
+ regcache_mark_dirty(wm8962->regmap); \
} \
return 0; \
}
@@ -107,1865 +111,1351 @@ WM8962_REGULATOR_EVENT(5)
WM8962_REGULATOR_EVENT(6)
WM8962_REGULATOR_EVENT(7)
-static const u16 wm8962_reg[WM8962_MAX_REGISTER + 1] = {
- [0] = 0x009F, /* R0 - Left Input volume */
- [1] = 0x049F, /* R1 - Right Input volume */
- [2] = 0x0000, /* R2 - HPOUTL volume */
- [3] = 0x0000, /* R3 - HPOUTR volume */
- [4] = 0x0020, /* R4 - Clocking1 */
- [5] = 0x0018, /* R5 - ADC & DAC Control 1 */
- [6] = 0x2008, /* R6 - ADC & DAC Control 2 */
- [7] = 0x000A, /* R7 - Audio Interface 0 */
- [8] = 0x01E4, /* R8 - Clocking2 */
- [9] = 0x0300, /* R9 - Audio Interface 1 */
- [10] = 0x00C0, /* R10 - Left DAC volume */
- [11] = 0x00C0, /* R11 - Right DAC volume */
-
- [14] = 0x0040, /* R14 - Audio Interface 2 */
- [15] = 0x6243, /* R15 - Software Reset */
-
- [17] = 0x007B, /* R17 - ALC1 */
- [18] = 0x0000, /* R18 - ALC2 */
- [19] = 0x1C32, /* R19 - ALC3 */
- [20] = 0x3200, /* R20 - Noise Gate */
- [21] = 0x00C0, /* R21 - Left ADC volume */
- [22] = 0x00C0, /* R22 - Right ADC volume */
- [23] = 0x0160, /* R23 - Additional control(1) */
- [24] = 0x0000, /* R24 - Additional control(2) */
- [25] = 0x0000, /* R25 - Pwr Mgmt (1) */
- [26] = 0x0000, /* R26 - Pwr Mgmt (2) */
- [27] = 0x0010, /* R27 - Additional Control (3) */
- [28] = 0x0000, /* R28 - Anti-pop */
-
- [30] = 0x005E, /* R30 - Clocking 3 */
- [31] = 0x0000, /* R31 - Input mixer control (1) */
- [32] = 0x0145, /* R32 - Left input mixer volume */
- [33] = 0x0145, /* R33 - Right input mixer volume */
- [34] = 0x0009, /* R34 - Input mixer control (2) */
- [35] = 0x0003, /* R35 - Input bias control */
- [37] = 0x0008, /* R37 - Left input PGA control */
- [38] = 0x0008, /* R38 - Right input PGA control */
-
- [40] = 0x0000, /* R40 - SPKOUTL volume */
- [41] = 0x0000, /* R41 - SPKOUTR volume */
-
- [47] = 0x0000, /* R47 - Thermal Shutdown Status */
- [48] = 0x8027, /* R48 - Additional Control (4) */
- [49] = 0x0010, /* R49 - Class D Control 1 */
-
- [51] = 0x0003, /* R51 - Class D Control 2 */
-
- [56] = 0x0506, /* R56 - Clocking 4 */
- [57] = 0x0000, /* R57 - DAC DSP Mixing (1) */
- [58] = 0x0000, /* R58 - DAC DSP Mixing (2) */
-
- [60] = 0x0300, /* R60 - DC Servo 0 */
- [61] = 0x0300, /* R61 - DC Servo 1 */
-
- [64] = 0x0810, /* R64 - DC Servo 4 */
-
- [66] = 0x0000, /* R66 - DC Servo 6 */
-
- [68] = 0x001B, /* R68 - Analogue PGA Bias */
- [69] = 0x0000, /* R69 - Analogue HP 0 */
-
- [71] = 0x01FB, /* R71 - Analogue HP 2 */
- [72] = 0x0000, /* R72 - Charge Pump 1 */
-
- [82] = 0x0004, /* R82 - Charge Pump B */
-
- [87] = 0x0000, /* R87 - Write Sequencer Control 1 */
-
- [90] = 0x0000, /* R90 - Write Sequencer Control 2 */
-
- [93] = 0x0000, /* R93 - Write Sequencer Control 3 */
- [94] = 0x0000, /* R94 - Control Interface */
-
- [99] = 0x0000, /* R99 - Mixer Enables */
- [100] = 0x0000, /* R100 - Headphone Mixer (1) */
- [101] = 0x0000, /* R101 - Headphone Mixer (2) */
- [102] = 0x013F, /* R102 - Headphone Mixer (3) */
- [103] = 0x013F, /* R103 - Headphone Mixer (4) */
-
- [105] = 0x0000, /* R105 - Speaker Mixer (1) */
- [106] = 0x0000, /* R106 - Speaker Mixer (2) */
- [107] = 0x013F, /* R107 - Speaker Mixer (3) */
- [108] = 0x013F, /* R108 - Speaker Mixer (4) */
- [109] = 0x0003, /* R109 - Speaker Mixer (5) */
- [110] = 0x0002, /* R110 - Beep Generator (1) */
-
- [115] = 0x0006, /* R115 - Oscillator Trim (3) */
- [116] = 0x0026, /* R116 - Oscillator Trim (4) */
-
- [119] = 0x0000, /* R119 - Oscillator Trim (7) */
-
- [124] = 0x0011, /* R124 - Analogue Clocking1 */
- [125] = 0x004B, /* R125 - Analogue Clocking2 */
- [126] = 0x000D, /* R126 - Analogue Clocking3 */
- [127] = 0x0000, /* R127 - PLL Software Reset */
-
- [129] = 0x0000, /* R129 - PLL2 */
-
- [131] = 0x0000, /* R131 - PLL 4 */
-
- [136] = 0x0067, /* R136 - PLL 9 */
- [137] = 0x001C, /* R137 - PLL 10 */
- [138] = 0x0071, /* R138 - PLL 11 */
- [139] = 0x00C7, /* R139 - PLL 12 */
- [140] = 0x0067, /* R140 - PLL 13 */
- [141] = 0x0048, /* R141 - PLL 14 */
- [142] = 0x0022, /* R142 - PLL 15 */
- [143] = 0x0097, /* R143 - PLL 16 */
-
- [155] = 0x000C, /* R155 - FLL Control (1) */
- [156] = 0x0039, /* R156 - FLL Control (2) */
- [157] = 0x0180, /* R157 - FLL Control (3) */
-
- [159] = 0x0032, /* R159 - FLL Control (5) */
- [160] = 0x0018, /* R160 - FLL Control (6) */
- [161] = 0x007D, /* R161 - FLL Control (7) */
- [162] = 0x0008, /* R162 - FLL Control (8) */
-
- [252] = 0x0005, /* R252 - General test 1 */
-
- [256] = 0x0000, /* R256 - DF1 */
- [257] = 0x0000, /* R257 - DF2 */
- [258] = 0x0000, /* R258 - DF3 */
- [259] = 0x0000, /* R259 - DF4 */
- [260] = 0x0000, /* R260 - DF5 */
- [261] = 0x0000, /* R261 - DF6 */
- [262] = 0x0000, /* R262 - DF7 */
-
- [264] = 0x0000, /* R264 - LHPF1 */
- [265] = 0x0000, /* R265 - LHPF2 */
-
- [268] = 0x0000, /* R268 - THREED1 */
- [269] = 0x0000, /* R269 - THREED2 */
- [270] = 0x0000, /* R270 - THREED3 */
- [271] = 0x0000, /* R271 - THREED4 */
-
- [276] = 0x000C, /* R276 - DRC 1 */
- [277] = 0x0925, /* R277 - DRC 2 */
- [278] = 0x0000, /* R278 - DRC 3 */
- [279] = 0x0000, /* R279 - DRC 4 */
- [280] = 0x0000, /* R280 - DRC 5 */
-
- [285] = 0x0000, /* R285 - Tloopback */
-
- [335] = 0x0004, /* R335 - EQ1 */
- [336] = 0x6318, /* R336 - EQ2 */
- [337] = 0x6300, /* R337 - EQ3 */
- [338] = 0x0FCA, /* R338 - EQ4 */
- [339] = 0x0400, /* R339 - EQ5 */
- [340] = 0x00D8, /* R340 - EQ6 */
- [341] = 0x1EB5, /* R341 - EQ7 */
- [342] = 0xF145, /* R342 - EQ8 */
- [343] = 0x0B75, /* R343 - EQ9 */
- [344] = 0x01C5, /* R344 - EQ10 */
- [345] = 0x1C58, /* R345 - EQ11 */
- [346] = 0xF373, /* R346 - EQ12 */
- [347] = 0x0A54, /* R347 - EQ13 */
- [348] = 0x0558, /* R348 - EQ14 */
- [349] = 0x168E, /* R349 - EQ15 */
- [350] = 0xF829, /* R350 - EQ16 */
- [351] = 0x07AD, /* R351 - EQ17 */
- [352] = 0x1103, /* R352 - EQ18 */
- [353] = 0x0564, /* R353 - EQ19 */
- [354] = 0x0559, /* R354 - EQ20 */
- [355] = 0x4000, /* R355 - EQ21 */
- [356] = 0x6318, /* R356 - EQ22 */
- [357] = 0x6300, /* R357 - EQ23 */
- [358] = 0x0FCA, /* R358 - EQ24 */
- [359] = 0x0400, /* R359 - EQ25 */
- [360] = 0x00D8, /* R360 - EQ26 */
- [361] = 0x1EB5, /* R361 - EQ27 */
- [362] = 0xF145, /* R362 - EQ28 */
- [363] = 0x0B75, /* R363 - EQ29 */
- [364] = 0x01C5, /* R364 - EQ30 */
- [365] = 0x1C58, /* R365 - EQ31 */
- [366] = 0xF373, /* R366 - EQ32 */
- [367] = 0x0A54, /* R367 - EQ33 */
- [368] = 0x0558, /* R368 - EQ34 */
- [369] = 0x168E, /* R369 - EQ35 */
- [370] = 0xF829, /* R370 - EQ36 */
- [371] = 0x07AD, /* R371 - EQ37 */
- [372] = 0x1103, /* R372 - EQ38 */
- [373] = 0x0564, /* R373 - EQ39 */
- [374] = 0x0559, /* R374 - EQ40 */
- [375] = 0x4000, /* R375 - EQ41 */
-
- [513] = 0x0000, /* R513 - GPIO 2 */
- [514] = 0x0000, /* R514 - GPIO 3 */
-
- [516] = 0x8100, /* R516 - GPIO 5 */
- [517] = 0x8100, /* R517 - GPIO 6 */
-
- [560] = 0x0000, /* R560 - Interrupt Status 1 */
- [561] = 0x0000, /* R561 - Interrupt Status 2 */
-
- [568] = 0x0030, /* R568 - Interrupt Status 1 Mask */
- [569] = 0xFFED, /* R569 - Interrupt Status 2 Mask */
-
- [576] = 0x0000, /* R576 - Interrupt Control */
-
- [584] = 0x002D, /* R584 - IRQ Debounce */
-
- [586] = 0x0000, /* R586 - MICINT Source Pol */
-
- [768] = 0x1C00, /* R768 - DSP2 Power Management */
-
- [1037] = 0x0000, /* R1037 - DSP2_ExecControl */
-
- [8192] = 0x0000, /* R8192 - DSP2 Instruction RAM 0 */
-
- [9216] = 0x0030, /* R9216 - DSP2 Address RAM 2 */
- [9217] = 0x0000, /* R9217 - DSP2 Address RAM 1 */
- [9218] = 0x0000, /* R9218 - DSP2 Address RAM 0 */
-
- [12288] = 0x0000, /* R12288 - DSP2 Data1 RAM 1 */
- [12289] = 0x0000, /* R12289 - DSP2 Data1 RAM 0 */
-
- [13312] = 0x0000, /* R13312 - DSP2 Data2 RAM 1 */
- [13313] = 0x0000, /* R13313 - DSP2 Data2 RAM 0 */
-
- [14336] = 0x0000, /* R14336 - DSP2 Data3 RAM 1 */
- [14337] = 0x0000, /* R14337 - DSP2 Data3 RAM 0 */
-
- [15360] = 0x000A, /* R15360 - DSP2 Coeff RAM 0 */
-
- [16384] = 0x0000, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
- [16385] = 0x0000, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
- [16386] = 0x0000, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
- [16387] = 0x0000, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
- [16388] = 0x0000, /* R16388 - SOUNDSTAGE_ENABLES_1 */
- [16389] = 0x0000, /* R16389 - SOUNDSTAGE_ENABLES_0 */
-
- [16896] = 0x0002, /* R16896 - HDBASS_AI_1 */
- [16897] = 0xBD12, /* R16897 - HDBASS_AI_0 */
- [16898] = 0x007C, /* R16898 - HDBASS_AR_1 */
- [16899] = 0x586C, /* R16899 - HDBASS_AR_0 */
- [16900] = 0x0053, /* R16900 - HDBASS_B_1 */
- [16901] = 0x8121, /* R16901 - HDBASS_B_0 */
- [16902] = 0x003F, /* R16902 - HDBASS_K_1 */
- [16903] = 0x8BD8, /* R16903 - HDBASS_K_0 */
- [16904] = 0x0032, /* R16904 - HDBASS_N1_1 */
- [16905] = 0xF52D, /* R16905 - HDBASS_N1_0 */
- [16906] = 0x0065, /* R16906 - HDBASS_N2_1 */
- [16907] = 0xAC8C, /* R16907 - HDBASS_N2_0 */
- [16908] = 0x006B, /* R16908 - HDBASS_N3_1 */
- [16909] = 0xE087, /* R16909 - HDBASS_N3_0 */
- [16910] = 0x0072, /* R16910 - HDBASS_N4_1 */
- [16911] = 0x1483, /* R16911 - HDBASS_N4_0 */
- [16912] = 0x0072, /* R16912 - HDBASS_N5_1 */
- [16913] = 0x1483, /* R16913 - HDBASS_N5_0 */
- [16914] = 0x0043, /* R16914 - HDBASS_X1_1 */
- [16915] = 0x3525, /* R16915 - HDBASS_X1_0 */
- [16916] = 0x0006, /* R16916 - HDBASS_X2_1 */
- [16917] = 0x6A4A, /* R16917 - HDBASS_X2_0 */
- [16918] = 0x0043, /* R16918 - HDBASS_X3_1 */
- [16919] = 0x6079, /* R16919 - HDBASS_X3_0 */
- [16920] = 0x0008, /* R16920 - HDBASS_ATK_1 */
- [16921] = 0x0000, /* R16921 - HDBASS_ATK_0 */
- [16922] = 0x0001, /* R16922 - HDBASS_DCY_1 */
- [16923] = 0x0000, /* R16923 - HDBASS_DCY_0 */
- [16924] = 0x0059, /* R16924 - HDBASS_PG_1 */
- [16925] = 0x999A, /* R16925 - HDBASS_PG_0 */
-
- [17048] = 0x0083, /* R17408 - HPF_C_1 */
- [17049] = 0x98AD, /* R17409 - HPF_C_0 */
-
- [17920] = 0x007F, /* R17920 - ADCL_RETUNE_C1_1 */
- [17921] = 0xFFFF, /* R17921 - ADCL_RETUNE_C1_0 */
- [17922] = 0x0000, /* R17922 - ADCL_RETUNE_C2_1 */
- [17923] = 0x0000, /* R17923 - ADCL_RETUNE_C2_0 */
- [17924] = 0x0000, /* R17924 - ADCL_RETUNE_C3_1 */
- [17925] = 0x0000, /* R17925 - ADCL_RETUNE_C3_0 */
- [17926] = 0x0000, /* R17926 - ADCL_RETUNE_C4_1 */
- [17927] = 0x0000, /* R17927 - ADCL_RETUNE_C4_0 */
- [17928] = 0x0000, /* R17928 - ADCL_RETUNE_C5_1 */
- [17929] = 0x0000, /* R17929 - ADCL_RETUNE_C5_0 */
- [17930] = 0x0000, /* R17930 - ADCL_RETUNE_C6_1 */
- [17931] = 0x0000, /* R17931 - ADCL_RETUNE_C6_0 */
- [17932] = 0x0000, /* R17932 - ADCL_RETUNE_C7_1 */
- [17933] = 0x0000, /* R17933 - ADCL_RETUNE_C7_0 */
- [17934] = 0x0000, /* R17934 - ADCL_RETUNE_C8_1 */
- [17935] = 0x0000, /* R17935 - ADCL_RETUNE_C8_0 */
- [17936] = 0x0000, /* R17936 - ADCL_RETUNE_C9_1 */
- [17937] = 0x0000, /* R17937 - ADCL_RETUNE_C9_0 */
- [17938] = 0x0000, /* R17938 - ADCL_RETUNE_C10_1 */
- [17939] = 0x0000, /* R17939 - ADCL_RETUNE_C10_0 */
- [17940] = 0x0000, /* R17940 - ADCL_RETUNE_C11_1 */
- [17941] = 0x0000, /* R17941 - ADCL_RETUNE_C11_0 */
- [17942] = 0x0000, /* R17942 - ADCL_RETUNE_C12_1 */
- [17943] = 0x0000, /* R17943 - ADCL_RETUNE_C12_0 */
- [17944] = 0x0000, /* R17944 - ADCL_RETUNE_C13_1 */
- [17945] = 0x0000, /* R17945 - ADCL_RETUNE_C13_0 */
- [17946] = 0x0000, /* R17946 - ADCL_RETUNE_C14_1 */
- [17947] = 0x0000, /* R17947 - ADCL_RETUNE_C14_0 */
- [17948] = 0x0000, /* R17948 - ADCL_RETUNE_C15_1 */
- [17949] = 0x0000, /* R17949 - ADCL_RETUNE_C15_0 */
- [17950] = 0x0000, /* R17950 - ADCL_RETUNE_C16_1 */
- [17951] = 0x0000, /* R17951 - ADCL_RETUNE_C16_0 */
- [17952] = 0x0000, /* R17952 - ADCL_RETUNE_C17_1 */
- [17953] = 0x0000, /* R17953 - ADCL_RETUNE_C17_0 */
- [17954] = 0x0000, /* R17954 - ADCL_RETUNE_C18_1 */
- [17955] = 0x0000, /* R17955 - ADCL_RETUNE_C18_0 */
- [17956] = 0x0000, /* R17956 - ADCL_RETUNE_C19_1 */
- [17957] = 0x0000, /* R17957 - ADCL_RETUNE_C19_0 */
- [17958] = 0x0000, /* R17958 - ADCL_RETUNE_C20_1 */
- [17959] = 0x0000, /* R17959 - ADCL_RETUNE_C20_0 */
- [17960] = 0x0000, /* R17960 - ADCL_RETUNE_C21_1 */
- [17961] = 0x0000, /* R17961 - ADCL_RETUNE_C21_0 */
- [17962] = 0x0000, /* R17962 - ADCL_RETUNE_C22_1 */
- [17963] = 0x0000, /* R17963 - ADCL_RETUNE_C22_0 */
- [17964] = 0x0000, /* R17964 - ADCL_RETUNE_C23_1 */
- [17965] = 0x0000, /* R17965 - ADCL_RETUNE_C23_0 */
- [17966] = 0x0000, /* R17966 - ADCL_RETUNE_C24_1 */
- [17967] = 0x0000, /* R17967 - ADCL_RETUNE_C24_0 */
- [17968] = 0x0000, /* R17968 - ADCL_RETUNE_C25_1 */
- [17969] = 0x0000, /* R17969 - ADCL_RETUNE_C25_0 */
- [17970] = 0x0000, /* R17970 - ADCL_RETUNE_C26_1 */
- [17971] = 0x0000, /* R17971 - ADCL_RETUNE_C26_0 */
- [17972] = 0x0000, /* R17972 - ADCL_RETUNE_C27_1 */
- [17973] = 0x0000, /* R17973 - ADCL_RETUNE_C27_0 */
- [17974] = 0x0000, /* R17974 - ADCL_RETUNE_C28_1 */
- [17975] = 0x0000, /* R17975 - ADCL_RETUNE_C28_0 */
- [17976] = 0x0000, /* R17976 - ADCL_RETUNE_C29_1 */
- [17977] = 0x0000, /* R17977 - ADCL_RETUNE_C29_0 */
- [17978] = 0x0000, /* R17978 - ADCL_RETUNE_C30_1 */
- [17979] = 0x0000, /* R17979 - ADCL_RETUNE_C30_0 */
- [17980] = 0x0000, /* R17980 - ADCL_RETUNE_C31_1 */
- [17981] = 0x0000, /* R17981 - ADCL_RETUNE_C31_0 */
- [17982] = 0x0000, /* R17982 - ADCL_RETUNE_C32_1 */
- [17983] = 0x0000, /* R17983 - ADCL_RETUNE_C32_0 */
-
- [18432] = 0x0020, /* R18432 - RETUNEADC_PG2_1 */
- [18433] = 0x0000, /* R18433 - RETUNEADC_PG2_0 */
- [18434] = 0x0040, /* R18434 - RETUNEADC_PG_1 */
- [18435] = 0x0000, /* R18435 - RETUNEADC_PG_0 */
-
- [18944] = 0x007F, /* R18944 - ADCR_RETUNE_C1_1 */
- [18945] = 0xFFFF, /* R18945 - ADCR_RETUNE_C1_0 */
- [18946] = 0x0000, /* R18946 - ADCR_RETUNE_C2_1 */
- [18947] = 0x0000, /* R18947 - ADCR_RETUNE_C2_0 */
- [18948] = 0x0000, /* R18948 - ADCR_RETUNE_C3_1 */
- [18949] = 0x0000, /* R18949 - ADCR_RETUNE_C3_0 */
- [18950] = 0x0000, /* R18950 - ADCR_RETUNE_C4_1 */
- [18951] = 0x0000, /* R18951 - ADCR_RETUNE_C4_0 */
- [18952] = 0x0000, /* R18952 - ADCR_RETUNE_C5_1 */
- [18953] = 0x0000, /* R18953 - ADCR_RETUNE_C5_0 */
- [18954] = 0x0000, /* R18954 - ADCR_RETUNE_C6_1 */
- [18955] = 0x0000, /* R18955 - ADCR_RETUNE_C6_0 */
- [18956] = 0x0000, /* R18956 - ADCR_RETUNE_C7_1 */
- [18957] = 0x0000, /* R18957 - ADCR_RETUNE_C7_0 */
- [18958] = 0x0000, /* R18958 - ADCR_RETUNE_C8_1 */
- [18959] = 0x0000, /* R18959 - ADCR_RETUNE_C8_0 */
- [18960] = 0x0000, /* R18960 - ADCR_RETUNE_C9_1 */
- [18961] = 0x0000, /* R18961 - ADCR_RETUNE_C9_0 */
- [18962] = 0x0000, /* R18962 - ADCR_RETUNE_C10_1 */
- [18963] = 0x0000, /* R18963 - ADCR_RETUNE_C10_0 */
- [18964] = 0x0000, /* R18964 - ADCR_RETUNE_C11_1 */
- [18965] = 0x0000, /* R18965 - ADCR_RETUNE_C11_0 */
- [18966] = 0x0000, /* R18966 - ADCR_RETUNE_C12_1 */
- [18967] = 0x0000, /* R18967 - ADCR_RETUNE_C12_0 */
- [18968] = 0x0000, /* R18968 - ADCR_RETUNE_C13_1 */
- [18969] = 0x0000, /* R18969 - ADCR_RETUNE_C13_0 */
- [18970] = 0x0000, /* R18970 - ADCR_RETUNE_C14_1 */
- [18971] = 0x0000, /* R18971 - ADCR_RETUNE_C14_0 */
- [18972] = 0x0000, /* R18972 - ADCR_RETUNE_C15_1 */
- [18973] = 0x0000, /* R18973 - ADCR_RETUNE_C15_0 */
- [18974] = 0x0000, /* R18974 - ADCR_RETUNE_C16_1 */
- [18975] = 0x0000, /* R18975 - ADCR_RETUNE_C16_0 */
- [18976] = 0x0000, /* R18976 - ADCR_RETUNE_C17_1 */
- [18977] = 0x0000, /* R18977 - ADCR_RETUNE_C17_0 */
- [18978] = 0x0000, /* R18978 - ADCR_RETUNE_C18_1 */
- [18979] = 0x0000, /* R18979 - ADCR_RETUNE_C18_0 */
- [18980] = 0x0000, /* R18980 - ADCR_RETUNE_C19_1 */
- [18981] = 0x0000, /* R18981 - ADCR_RETUNE_C19_0 */
- [18982] = 0x0000, /* R18982 - ADCR_RETUNE_C20_1 */
- [18983] = 0x0000, /* R18983 - ADCR_RETUNE_C20_0 */
- [18984] = 0x0000, /* R18984 - ADCR_RETUNE_C21_1 */
- [18985] = 0x0000, /* R18985 - ADCR_RETUNE_C21_0 */
- [18986] = 0x0000, /* R18986 - ADCR_RETUNE_C22_1 */
- [18987] = 0x0000, /* R18987 - ADCR_RETUNE_C22_0 */
- [18988] = 0x0000, /* R18988 - ADCR_RETUNE_C23_1 */
- [18989] = 0x0000, /* R18989 - ADCR_RETUNE_C23_0 */
- [18990] = 0x0000, /* R18990 - ADCR_RETUNE_C24_1 */
- [18991] = 0x0000, /* R18991 - ADCR_RETUNE_C24_0 */
- [18992] = 0x0000, /* R18992 - ADCR_RETUNE_C25_1 */
- [18993] = 0x0000, /* R18993 - ADCR_RETUNE_C25_0 */
- [18994] = 0x0000, /* R18994 - ADCR_RETUNE_C26_1 */
- [18995] = 0x0000, /* R18995 - ADCR_RETUNE_C26_0 */
- [18996] = 0x0000, /* R18996 - ADCR_RETUNE_C27_1 */
- [18997] = 0x0000, /* R18997 - ADCR_RETUNE_C27_0 */
- [18998] = 0x0000, /* R18998 - ADCR_RETUNE_C28_1 */
- [18999] = 0x0000, /* R18999 - ADCR_RETUNE_C28_0 */
- [19000] = 0x0000, /* R19000 - ADCR_RETUNE_C29_1 */
- [19001] = 0x0000, /* R19001 - ADCR_RETUNE_C29_0 */
- [19002] = 0x0000, /* R19002 - ADCR_RETUNE_C30_1 */
- [19003] = 0x0000, /* R19003 - ADCR_RETUNE_C30_0 */
- [19004] = 0x0000, /* R19004 - ADCR_RETUNE_C31_1 */
- [19005] = 0x0000, /* R19005 - ADCR_RETUNE_C31_0 */
- [19006] = 0x0000, /* R19006 - ADCR_RETUNE_C32_1 */
- [19007] = 0x0000, /* R19007 - ADCR_RETUNE_C32_0 */
-
- [19456] = 0x007F, /* R19456 - DACL_RETUNE_C1_1 */
- [19457] = 0xFFFF, /* R19457 - DACL_RETUNE_C1_0 */
- [19458] = 0x0000, /* R19458 - DACL_RETUNE_C2_1 */
- [19459] = 0x0000, /* R19459 - DACL_RETUNE_C2_0 */
- [19460] = 0x0000, /* R19460 - DACL_RETUNE_C3_1 */
- [19461] = 0x0000, /* R19461 - DACL_RETUNE_C3_0 */
- [19462] = 0x0000, /* R19462 - DACL_RETUNE_C4_1 */
- [19463] = 0x0000, /* R19463 - DACL_RETUNE_C4_0 */
- [19464] = 0x0000, /* R19464 - DACL_RETUNE_C5_1 */
- [19465] = 0x0000, /* R19465 - DACL_RETUNE_C5_0 */
- [19466] = 0x0000, /* R19466 - DACL_RETUNE_C6_1 */
- [19467] = 0x0000, /* R19467 - DACL_RETUNE_C6_0 */
- [19468] = 0x0000, /* R19468 - DACL_RETUNE_C7_1 */
- [19469] = 0x0000, /* R19469 - DACL_RETUNE_C7_0 */
- [19470] = 0x0000, /* R19470 - DACL_RETUNE_C8_1 */
- [19471] = 0x0000, /* R19471 - DACL_RETUNE_C8_0 */
- [19472] = 0x0000, /* R19472 - DACL_RETUNE_C9_1 */
- [19473] = 0x0000, /* R19473 - DACL_RETUNE_C9_0 */
- [19474] = 0x0000, /* R19474 - DACL_RETUNE_C10_1 */
- [19475] = 0x0000, /* R19475 - DACL_RETUNE_C10_0 */
- [19476] = 0x0000, /* R19476 - DACL_RETUNE_C11_1 */
- [19477] = 0x0000, /* R19477 - DACL_RETUNE_C11_0 */
- [19478] = 0x0000, /* R19478 - DACL_RETUNE_C12_1 */
- [19479] = 0x0000, /* R19479 - DACL_RETUNE_C12_0 */
- [19480] = 0x0000, /* R19480 - DACL_RETUNE_C13_1 */
- [19481] = 0x0000, /* R19481 - DACL_RETUNE_C13_0 */
- [19482] = 0x0000, /* R19482 - DACL_RETUNE_C14_1 */
- [19483] = 0x0000, /* R19483 - DACL_RETUNE_C14_0 */
- [19484] = 0x0000, /* R19484 - DACL_RETUNE_C15_1 */
- [19485] = 0x0000, /* R19485 - DACL_RETUNE_C15_0 */
- [19486] = 0x0000, /* R19486 - DACL_RETUNE_C16_1 */
- [19487] = 0x0000, /* R19487 - DACL_RETUNE_C16_0 */
- [19488] = 0x0000, /* R19488 - DACL_RETUNE_C17_1 */
- [19489] = 0x0000, /* R19489 - DACL_RETUNE_C17_0 */
- [19490] = 0x0000, /* R19490 - DACL_RETUNE_C18_1 */
- [19491] = 0x0000, /* R19491 - DACL_RETUNE_C18_0 */
- [19492] = 0x0000, /* R19492 - DACL_RETUNE_C19_1 */
- [19493] = 0x0000, /* R19493 - DACL_RETUNE_C19_0 */
- [19494] = 0x0000, /* R19494 - DACL_RETUNE_C20_1 */
- [19495] = 0x0000, /* R19495 - DACL_RETUNE_C20_0 */
- [19496] = 0x0000, /* R19496 - DACL_RETUNE_C21_1 */
- [19497] = 0x0000, /* R19497 - DACL_RETUNE_C21_0 */
- [19498] = 0x0000, /* R19498 - DACL_RETUNE_C22_1 */
- [19499] = 0x0000, /* R19499 - DACL_RETUNE_C22_0 */
- [19500] = 0x0000, /* R19500 - DACL_RETUNE_C23_1 */
- [19501] = 0x0000, /* R19501 - DACL_RETUNE_C23_0 */
- [19502] = 0x0000, /* R19502 - DACL_RETUNE_C24_1 */
- [19503] = 0x0000, /* R19503 - DACL_RETUNE_C24_0 */
- [19504] = 0x0000, /* R19504 - DACL_RETUNE_C25_1 */
- [19505] = 0x0000, /* R19505 - DACL_RETUNE_C25_0 */
- [19506] = 0x0000, /* R19506 - DACL_RETUNE_C26_1 */
- [19507] = 0x0000, /* R19507 - DACL_RETUNE_C26_0 */
- [19508] = 0x0000, /* R19508 - DACL_RETUNE_C27_1 */
- [19509] = 0x0000, /* R19509 - DACL_RETUNE_C27_0 */
- [19510] = 0x0000, /* R19510 - DACL_RETUNE_C28_1 */
- [19511] = 0x0000, /* R19511 - DACL_RETUNE_C28_0 */
- [19512] = 0x0000, /* R19512 - DACL_RETUNE_C29_1 */
- [19513] = 0x0000, /* R19513 - DACL_RETUNE_C29_0 */
- [19514] = 0x0000, /* R19514 - DACL_RETUNE_C30_1 */
- [19515] = 0x0000, /* R19515 - DACL_RETUNE_C30_0 */
- [19516] = 0x0000, /* R19516 - DACL_RETUNE_C31_1 */
- [19517] = 0x0000, /* R19517 - DACL_RETUNE_C31_0 */
- [19518] = 0x0000, /* R19518 - DACL_RETUNE_C32_1 */
- [19519] = 0x0000, /* R19519 - DACL_RETUNE_C32_0 */
-
- [19968] = 0x0020, /* R19968 - RETUNEDAC_PG2_1 */
- [19969] = 0x0000, /* R19969 - RETUNEDAC_PG2_0 */
- [19970] = 0x0040, /* R19970 - RETUNEDAC_PG_1 */
- [19971] = 0x0000, /* R19971 - RETUNEDAC_PG_0 */
-
- [20480] = 0x007F, /* R20480 - DACR_RETUNE_C1_1 */
- [20481] = 0xFFFF, /* R20481 - DACR_RETUNE_C1_0 */
- [20482] = 0x0000, /* R20482 - DACR_RETUNE_C2_1 */
- [20483] = 0x0000, /* R20483 - DACR_RETUNE_C2_0 */
- [20484] = 0x0000, /* R20484 - DACR_RETUNE_C3_1 */
- [20485] = 0x0000, /* R20485 - DACR_RETUNE_C3_0 */
- [20486] = 0x0000, /* R20486 - DACR_RETUNE_C4_1 */
- [20487] = 0x0000, /* R20487 - DACR_RETUNE_C4_0 */
- [20488] = 0x0000, /* R20488 - DACR_RETUNE_C5_1 */
- [20489] = 0x0000, /* R20489 - DACR_RETUNE_C5_0 */
- [20490] = 0x0000, /* R20490 - DACR_RETUNE_C6_1 */
- [20491] = 0x0000, /* R20491 - DACR_RETUNE_C6_0 */
- [20492] = 0x0000, /* R20492 - DACR_RETUNE_C7_1 */
- [20493] = 0x0000, /* R20493 - DACR_RETUNE_C7_0 */
- [20494] = 0x0000, /* R20494 - DACR_RETUNE_C8_1 */
- [20495] = 0x0000, /* R20495 - DACR_RETUNE_C8_0 */
- [20496] = 0x0000, /* R20496 - DACR_RETUNE_C9_1 */
- [20497] = 0x0000, /* R20497 - DACR_RETUNE_C9_0 */
- [20498] = 0x0000, /* R20498 - DACR_RETUNE_C10_1 */
- [20499] = 0x0000, /* R20499 - DACR_RETUNE_C10_0 */
- [20500] = 0x0000, /* R20500 - DACR_RETUNE_C11_1 */
- [20501] = 0x0000, /* R20501 - DACR_RETUNE_C11_0 */
- [20502] = 0x0000, /* R20502 - DACR_RETUNE_C12_1 */
- [20503] = 0x0000, /* R20503 - DACR_RETUNE_C12_0 */
- [20504] = 0x0000, /* R20504 - DACR_RETUNE_C13_1 */
- [20505] = 0x0000, /* R20505 - DACR_RETUNE_C13_0 */
- [20506] = 0x0000, /* R20506 - DACR_RETUNE_C14_1 */
- [20507] = 0x0000, /* R20507 - DACR_RETUNE_C14_0 */
- [20508] = 0x0000, /* R20508 - DACR_RETUNE_C15_1 */
- [20509] = 0x0000, /* R20509 - DACR_RETUNE_C15_0 */
- [20510] = 0x0000, /* R20510 - DACR_RETUNE_C16_1 */
- [20511] = 0x0000, /* R20511 - DACR_RETUNE_C16_0 */
- [20512] = 0x0000, /* R20512 - DACR_RETUNE_C17_1 */
- [20513] = 0x0000, /* R20513 - DACR_RETUNE_C17_0 */
- [20514] = 0x0000, /* R20514 - DACR_RETUNE_C18_1 */
- [20515] = 0x0000, /* R20515 - DACR_RETUNE_C18_0 */
- [20516] = 0x0000, /* R20516 - DACR_RETUNE_C19_1 */
- [20517] = 0x0000, /* R20517 - DACR_RETUNE_C19_0 */
- [20518] = 0x0000, /* R20518 - DACR_RETUNE_C20_1 */
- [20519] = 0x0000, /* R20519 - DACR_RETUNE_C20_0 */
- [20520] = 0x0000, /* R20520 - DACR_RETUNE_C21_1 */
- [20521] = 0x0000, /* R20521 - DACR_RETUNE_C21_0 */
- [20522] = 0x0000, /* R20522 - DACR_RETUNE_C22_1 */
- [20523] = 0x0000, /* R20523 - DACR_RETUNE_C22_0 */
- [20524] = 0x0000, /* R20524 - DACR_RETUNE_C23_1 */
- [20525] = 0x0000, /* R20525 - DACR_RETUNE_C23_0 */
- [20526] = 0x0000, /* R20526 - DACR_RETUNE_C24_1 */
- [20527] = 0x0000, /* R20527 - DACR_RETUNE_C24_0 */
- [20528] = 0x0000, /* R20528 - DACR_RETUNE_C25_1 */
- [20529] = 0x0000, /* R20529 - DACR_RETUNE_C25_0 */
- [20530] = 0x0000, /* R20530 - DACR_RETUNE_C26_1 */
- [20531] = 0x0000, /* R20531 - DACR_RETUNE_C26_0 */
- [20532] = 0x0000, /* R20532 - DACR_RETUNE_C27_1 */
- [20533] = 0x0000, /* R20533 - DACR_RETUNE_C27_0 */
- [20534] = 0x0000, /* R20534 - DACR_RETUNE_C28_1 */
- [20535] = 0x0000, /* R20535 - DACR_RETUNE_C28_0 */
- [20536] = 0x0000, /* R20536 - DACR_RETUNE_C29_1 */
- [20537] = 0x0000, /* R20537 - DACR_RETUNE_C29_0 */
- [20538] = 0x0000, /* R20538 - DACR_RETUNE_C30_1 */
- [20539] = 0x0000, /* R20539 - DACR_RETUNE_C30_0 */
- [20540] = 0x0000, /* R20540 - DACR_RETUNE_C31_1 */
- [20541] = 0x0000, /* R20541 - DACR_RETUNE_C31_0 */
- [20542] = 0x0000, /* R20542 - DACR_RETUNE_C32_1 */
- [20543] = 0x0000, /* R20543 - DACR_RETUNE_C32_0 */
-
- [20992] = 0x008C, /* R20992 - VSS_XHD2_1 */
- [20993] = 0x0200, /* R20993 - VSS_XHD2_0 */
- [20994] = 0x0035, /* R20994 - VSS_XHD3_1 */
- [20995] = 0x0700, /* R20995 - VSS_XHD3_0 */
- [20996] = 0x003A, /* R20996 - VSS_XHN1_1 */
- [20997] = 0x4100, /* R20997 - VSS_XHN1_0 */
- [20998] = 0x008B, /* R20998 - VSS_XHN2_1 */
- [20999] = 0x7D00, /* R20999 - VSS_XHN2_0 */
- [21000] = 0x003A, /* R21000 - VSS_XHN3_1 */
- [21001] = 0x4100, /* R21001 - VSS_XHN3_0 */
- [21002] = 0x008C, /* R21002 - VSS_XLA_1 */
- [21003] = 0xFEE8, /* R21003 - VSS_XLA_0 */
- [21004] = 0x0078, /* R21004 - VSS_XLB_1 */
- [21005] = 0x0000, /* R21005 - VSS_XLB_0 */
- [21006] = 0x003F, /* R21006 - VSS_XLG_1 */
- [21007] = 0xB260, /* R21007 - VSS_XLG_0 */
- [21008] = 0x002D, /* R21008 - VSS_PG2_1 */
- [21009] = 0x1818, /* R21009 - VSS_PG2_0 */
- [21010] = 0x0020, /* R21010 - VSS_PG_1 */
- [21011] = 0x0000, /* R21011 - VSS_PG_0 */
- [21012] = 0x00F1, /* R21012 - VSS_XTD1_1 */
- [21013] = 0x8340, /* R21013 - VSS_XTD1_0 */
- [21014] = 0x00FB, /* R21014 - VSS_XTD2_1 */
- [21015] = 0x8300, /* R21015 - VSS_XTD2_0 */
- [21016] = 0x00EE, /* R21016 - VSS_XTD3_1 */
- [21017] = 0xAEC0, /* R21017 - VSS_XTD3_0 */
- [21018] = 0x00FB, /* R21018 - VSS_XTD4_1 */
- [21019] = 0xAC40, /* R21019 - VSS_XTD4_0 */
- [21020] = 0x00F1, /* R21020 - VSS_XTD5_1 */
- [21021] = 0x7F80, /* R21021 - VSS_XTD5_0 */
- [21022] = 0x00F4, /* R21022 - VSS_XTD6_1 */
- [21023] = 0x3B40, /* R21023 - VSS_XTD6_0 */
- [21024] = 0x00F5, /* R21024 - VSS_XTD7_1 */
- [21025] = 0xFB00, /* R21025 - VSS_XTD7_0 */
- [21026] = 0x00EA, /* R21026 - VSS_XTD8_1 */
- [21027] = 0x10C0, /* R21027 - VSS_XTD8_0 */
- [21028] = 0x00FC, /* R21028 - VSS_XTD9_1 */
- [21029] = 0xC580, /* R21029 - VSS_XTD9_0 */
- [21030] = 0x00E2, /* R21030 - VSS_XTD10_1 */
- [21031] = 0x75C0, /* R21031 - VSS_XTD10_0 */
- [21032] = 0x0004, /* R21032 - VSS_XTD11_1 */
- [21033] = 0xB480, /* R21033 - VSS_XTD11_0 */
- [21034] = 0x00D4, /* R21034 - VSS_XTD12_1 */
- [21035] = 0xF980, /* R21035 - VSS_XTD12_0 */
- [21036] = 0x0004, /* R21036 - VSS_XTD13_1 */
- [21037] = 0x9140, /* R21037 - VSS_XTD13_0 */
- [21038] = 0x00D8, /* R21038 - VSS_XTD14_1 */
- [21039] = 0xA480, /* R21039 - VSS_XTD14_0 */
- [21040] = 0x0002, /* R21040 - VSS_XTD15_1 */
- [21041] = 0x3DC0, /* R21041 - VSS_XTD15_0 */
- [21042] = 0x00CF, /* R21042 - VSS_XTD16_1 */
- [21043] = 0x7A80, /* R21043 - VSS_XTD16_0 */
- [21044] = 0x00DC, /* R21044 - VSS_XTD17_1 */
- [21045] = 0x0600, /* R21045 - VSS_XTD17_0 */
- [21046] = 0x00F2, /* R21046 - VSS_XTD18_1 */
- [21047] = 0xDAC0, /* R21047 - VSS_XTD18_0 */
- [21048] = 0x00BA, /* R21048 - VSS_XTD19_1 */
- [21049] = 0xF340, /* R21049 - VSS_XTD19_0 */
- [21050] = 0x000A, /* R21050 - VSS_XTD20_1 */
- [21051] = 0x7940, /* R21051 - VSS_XTD20_0 */
- [21052] = 0x001C, /* R21052 - VSS_XTD21_1 */
- [21053] = 0x0680, /* R21053 - VSS_XTD21_0 */
- [21054] = 0x00FD, /* R21054 - VSS_XTD22_1 */
- [21055] = 0x2D00, /* R21055 - VSS_XTD22_0 */
- [21056] = 0x001C, /* R21056 - VSS_XTD23_1 */
- [21057] = 0xE840, /* R21057 - VSS_XTD23_0 */
- [21058] = 0x000D, /* R21058 - VSS_XTD24_1 */
- [21059] = 0xDC40, /* R21059 - VSS_XTD24_0 */
- [21060] = 0x00FC, /* R21060 - VSS_XTD25_1 */
- [21061] = 0x9D00, /* R21061 - VSS_XTD25_0 */
- [21062] = 0x0009, /* R21062 - VSS_XTD26_1 */
- [21063] = 0x5580, /* R21063 - VSS_XTD26_0 */
- [21064] = 0x00FE, /* R21064 - VSS_XTD27_1 */
- [21065] = 0x7E80, /* R21065 - VSS_XTD27_0 */
- [21066] = 0x000E, /* R21066 - VSS_XTD28_1 */
- [21067] = 0xAB40, /* R21067 - VSS_XTD28_0 */
- [21068] = 0x00F9, /* R21068 - VSS_XTD29_1 */
- [21069] = 0x9880, /* R21069 - VSS_XTD29_0 */
- [21070] = 0x0009, /* R21070 - VSS_XTD30_1 */
- [21071] = 0x87C0, /* R21071 - VSS_XTD30_0 */
- [21072] = 0x00FD, /* R21072 - VSS_XTD31_1 */
- [21073] = 0x2C40, /* R21073 - VSS_XTD31_0 */
- [21074] = 0x0009, /* R21074 - VSS_XTD32_1 */
- [21075] = 0x4800, /* R21075 - VSS_XTD32_0 */
- [21076] = 0x0003, /* R21076 - VSS_XTS1_1 */
- [21077] = 0x5F40, /* R21077 - VSS_XTS1_0 */
- [21078] = 0x0000, /* R21078 - VSS_XTS2_1 */
- [21079] = 0x8700, /* R21079 - VSS_XTS2_0 */
- [21080] = 0x00FA, /* R21080 - VSS_XTS3_1 */
- [21081] = 0xE4C0, /* R21081 - VSS_XTS3_0 */
- [21082] = 0x0000, /* R21082 - VSS_XTS4_1 */
- [21083] = 0x0B40, /* R21083 - VSS_XTS4_0 */
- [21084] = 0x0004, /* R21084 - VSS_XTS5_1 */
- [21085] = 0xE180, /* R21085 - VSS_XTS5_0 */
- [21086] = 0x0001, /* R21086 - VSS_XTS6_1 */
- [21087] = 0x1F40, /* R21087 - VSS_XTS6_0 */
- [21088] = 0x00F8, /* R21088 - VSS_XTS7_1 */
- [21089] = 0xB000, /* R21089 - VSS_XTS7_0 */
- [21090] = 0x00FB, /* R21090 - VSS_XTS8_1 */
- [21091] = 0xCBC0, /* R21091 - VSS_XTS8_0 */
- [21092] = 0x0004, /* R21092 - VSS_XTS9_1 */
- [21093] = 0xF380, /* R21093 - VSS_XTS9_0 */
- [21094] = 0x0007, /* R21094 - VSS_XTS10_1 */
- [21095] = 0xDF40, /* R21095 - VSS_XTS10_0 */
- [21096] = 0x00FF, /* R21096 - VSS_XTS11_1 */
- [21097] = 0x0700, /* R21097 - VSS_XTS11_0 */
- [21098] = 0x00EF, /* R21098 - VSS_XTS12_1 */
- [21099] = 0xD700, /* R21099 - VSS_XTS12_0 */
- [21100] = 0x00FB, /* R21100 - VSS_XTS13_1 */
- [21101] = 0xAF40, /* R21101 - VSS_XTS13_0 */
- [21102] = 0x0010, /* R21102 - VSS_XTS14_1 */
- [21103] = 0x8A80, /* R21103 - VSS_XTS14_0 */
- [21104] = 0x0011, /* R21104 - VSS_XTS15_1 */
- [21105] = 0x07C0, /* R21105 - VSS_XTS15_0 */
- [21106] = 0x00E0, /* R21106 - VSS_XTS16_1 */
- [21107] = 0x0800, /* R21107 - VSS_XTS16_0 */
- [21108] = 0x00D2, /* R21108 - VSS_XTS17_1 */
- [21109] = 0x7600, /* R21109 - VSS_XTS17_0 */
- [21110] = 0x0020, /* R21110 - VSS_XTS18_1 */
- [21111] = 0xCF40, /* R21111 - VSS_XTS18_0 */
- [21112] = 0x0030, /* R21112 - VSS_XTS19_1 */
- [21113] = 0x2340, /* R21113 - VSS_XTS19_0 */
- [21114] = 0x00FD, /* R21114 - VSS_XTS20_1 */
- [21115] = 0x69C0, /* R21115 - VSS_XTS20_0 */
- [21116] = 0x0028, /* R21116 - VSS_XTS21_1 */
- [21117] = 0x3500, /* R21117 - VSS_XTS21_0 */
- [21118] = 0x0006, /* R21118 - VSS_XTS22_1 */
- [21119] = 0x3300, /* R21119 - VSS_XTS22_0 */
- [21120] = 0x00D9, /* R21120 - VSS_XTS23_1 */
- [21121] = 0xF6C0, /* R21121 - VSS_XTS23_0 */
- [21122] = 0x00F3, /* R21122 - VSS_XTS24_1 */
- [21123] = 0x3340, /* R21123 - VSS_XTS24_0 */
- [21124] = 0x000F, /* R21124 - VSS_XTS25_1 */
- [21125] = 0x4200, /* R21125 - VSS_XTS25_0 */
- [21126] = 0x0004, /* R21126 - VSS_XTS26_1 */
- [21127] = 0x0C80, /* R21127 - VSS_XTS26_0 */
- [21128] = 0x00FB, /* R21128 - VSS_XTS27_1 */
- [21129] = 0x3F80, /* R21129 - VSS_XTS27_0 */
- [21130] = 0x00F7, /* R21130 - VSS_XTS28_1 */
- [21131] = 0x57C0, /* R21131 - VSS_XTS28_0 */
- [21132] = 0x0003, /* R21132 - VSS_XTS29_1 */
- [21133] = 0x5400, /* R21133 - VSS_XTS29_0 */
- [21134] = 0x0000, /* R21134 - VSS_XTS30_1 */
- [21135] = 0xC6C0, /* R21135 - VSS_XTS30_0 */
- [21136] = 0x0003, /* R21136 - VSS_XTS31_1 */
- [21137] = 0x12C0, /* R21137 - VSS_XTS31_0 */
- [21138] = 0x00FD, /* R21138 - VSS_XTS32_1 */
- [21139] = 0x8580, /* R21139 - VSS_XTS32_0 */
-};
+static struct reg_default wm8962_reg[] = {
+ { 0, 0x009F }, /* R0 - Left Input volume */
+ { 1, 0x049F }, /* R1 - Right Input volume */
+ { 2, 0x0000 }, /* R2 - HPOUTL volume */
+ { 3, 0x0000 }, /* R3 - HPOUTR volume */
+
+ { 5, 0x0018 }, /* R5 - ADC & DAC Control 1 */
+ { 6, 0x2008 }, /* R6 - ADC & DAC Control 2 */
+ { 7, 0x000A }, /* R7 - Audio Interface 0 */
+
+ { 9, 0x0300 }, /* R9 - Audio Interface 1 */
+ { 10, 0x00C0 }, /* R10 - Left DAC volume */
+ { 11, 0x00C0 }, /* R11 - Right DAC volume */
+
+ { 14, 0x0040 }, /* R14 - Audio Interface 2 */
+ { 15, 0x6243 }, /* R15 - Software Reset */
+
+ { 17, 0x007B }, /* R17 - ALC1 */
+
+ { 19, 0x1C32 }, /* R19 - ALC3 */
+ { 20, 0x3200 }, /* R20 - Noise Gate */
+ { 21, 0x00C0 }, /* R21 - Left ADC volume */
+ { 22, 0x00C0 }, /* R22 - Right ADC volume */
+ { 23, 0x0160 }, /* R23 - Additional control(1) */
+ { 24, 0x0000 }, /* R24 - Additional control(2) */
+ { 25, 0x0000 }, /* R25 - Pwr Mgmt (1) */
+ { 26, 0x0000 }, /* R26 - Pwr Mgmt (2) */
+ { 27, 0x0010 }, /* R27 - Additional Control (3) */
+ { 28, 0x0000 }, /* R28 - Anti-pop */
-static const struct wm8962_reg_access {
- u16 read;
- u16 write;
- u16 vol;
-} wm8962_reg_access[WM8962_MAX_REGISTER + 1] = {
- [0] = { 0x00FF, 0x01FF, 0x0000 }, /* R0 - Left Input volume */
- [1] = { 0xFEFF, 0x01FF, 0xFFFF }, /* R1 - Right Input volume */
- [2] = { 0x00FF, 0x01FF, 0x0000 }, /* R2 - HPOUTL volume */
- [3] = { 0x00FF, 0x01FF, 0x0000 }, /* R3 - HPOUTR volume */
- [4] = { 0x07FE, 0x07FE, 0xFFFF }, /* R4 - Clocking1 */
- [5] = { 0x007F, 0x007F, 0x0000 }, /* R5 - ADC & DAC Control 1 */
- [6] = { 0x37ED, 0x37ED, 0x0000 }, /* R6 - ADC & DAC Control 2 */
- [7] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R7 - Audio Interface 0 */
- [8] = { 0x0FEF, 0x0FEF, 0xFFFF }, /* R8 - Clocking2 */
- [9] = { 0x0B9F, 0x039F, 0x0000 }, /* R9 - Audio Interface 1 */
- [10] = { 0x00FF, 0x01FF, 0x0000 }, /* R10 - Left DAC volume */
- [11] = { 0x00FF, 0x01FF, 0x0000 }, /* R11 - Right DAC volume */
- [14] = { 0x07FF, 0x07FF, 0x0000 }, /* R14 - Audio Interface 2 */
- [15] = { 0xFFFF, 0xFFFF, 0xFFFF }, /* R15 - Software Reset */
- [17] = { 0x07FF, 0x07FF, 0x0000 }, /* R17 - ALC1 */
- [18] = { 0xF8FF, 0x00FF, 0xFFFF }, /* R18 - ALC2 */
- [19] = { 0x1DFF, 0x1DFF, 0x0000 }, /* R19 - ALC3 */
- [20] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20 - Noise Gate */
- [21] = { 0x00FF, 0x01FF, 0x0000 }, /* R21 - Left ADC volume */
- [22] = { 0x00FF, 0x01FF, 0x0000 }, /* R22 - Right ADC volume */
- [23] = { 0x0161, 0x0161, 0x0000 }, /* R23 - Additional control(1) */
- [24] = { 0x0008, 0x0008, 0x0000 }, /* R24 - Additional control(2) */
- [25] = { 0x07FE, 0x07FE, 0x0000 }, /* R25 - Pwr Mgmt (1) */
- [26] = { 0x01FB, 0x01FB, 0x0000 }, /* R26 - Pwr Mgmt (2) */
- [27] = { 0x0017, 0x0017, 0x0000 }, /* R27 - Additional Control (3) */
- [28] = { 0x001C, 0x001C, 0x0000 }, /* R28 - Anti-pop */
-
- [30] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R30 - Clocking 3 */
- [31] = { 0x000F, 0x000F, 0x0000 }, /* R31 - Input mixer control (1) */
- [32] = { 0x01FF, 0x01FF, 0x0000 }, /* R32 - Left input mixer volume */
- [33] = { 0x01FF, 0x01FF, 0x0000 }, /* R33 - Right input mixer volume */
- [34] = { 0x003F, 0x003F, 0x0000 }, /* R34 - Input mixer control (2) */
- [35] = { 0x003F, 0x003F, 0x0000 }, /* R35 - Input bias control */
- [37] = { 0x001F, 0x001F, 0x0000 }, /* R37 - Left input PGA control */
- [38] = { 0x001F, 0x001F, 0x0000 }, /* R38 - Right input PGA control */
- [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */
- [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */
-
- [47] = { 0x000F, 0x0000, 0x0000 }, /* R47 - Thermal Shutdown Status */
- [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */
- [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */
- [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */
- [56] = { 0x001E, 0x001E, 0x0000 }, /* R56 - Clocking 4 */
- [57] = { 0x02FC, 0x02FC, 0x0000 }, /* R57 - DAC DSP Mixing (1) */
- [58] = { 0x00FC, 0x00FC, 0x0000 }, /* R58 - DAC DSP Mixing (2) */
- [60] = { 0x00CC, 0x00CC, 0x0000 }, /* R60 - DC Servo 0 */
- [61] = { 0x00DD, 0x00DD, 0x0000 }, /* R61 - DC Servo 1 */
- [64] = { 0x3F80, 0x3F80, 0x0000 }, /* R64 - DC Servo 4 */
- [66] = { 0x0780, 0x0000, 0xFFFF }, /* R66 - DC Servo 6 */
- [68] = { 0x0007, 0x0007, 0x0000 }, /* R68 - Analogue PGA Bias */
- [69] = { 0x00FF, 0x00FF, 0x0000 }, /* R69 - Analogue HP 0 */
- [71] = { 0x01FF, 0x01FF, 0x0000 }, /* R71 - Analogue HP 2 */
- [72] = { 0x0001, 0x0001, 0x0000 }, /* R72 - Charge Pump 1 */
- [82] = { 0x0001, 0x0001, 0x0000 }, /* R82 - Charge Pump B */
- [87] = { 0x00A0, 0x00A0, 0x0000 }, /* R87 - Write Sequencer Control 1 */
- [90] = { 0x007F, 0x01FF, 0x0000 }, /* R90 - Write Sequencer Control 2 */
- [93] = { 0x03F9, 0x0000, 0x0000 }, /* R93 - Write Sequencer Control 3 */
- [94] = { 0x0070, 0x0070, 0x0000 }, /* R94 - Control Interface */
- [99] = { 0x000F, 0x000F, 0x0000 }, /* R99 - Mixer Enables */
- [100] = { 0x00BF, 0x00BF, 0x0000 }, /* R100 - Headphone Mixer (1) */
- [101] = { 0x00BF, 0x00BF, 0x0000 }, /* R101 - Headphone Mixer (2) */
- [102] = { 0x01FF, 0x01FF, 0x0000 }, /* R102 - Headphone Mixer (3) */
- [103] = { 0x01FF, 0x01FF, 0x0000 }, /* R103 - Headphone Mixer (4) */
- [105] = { 0x00BF, 0x00BF, 0x0000 }, /* R105 - Speaker Mixer (1) */
- [106] = { 0x00BF, 0x00BF, 0x0000 }, /* R106 - Speaker Mixer (2) */
- [107] = { 0x01FF, 0x01FF, 0x0000 }, /* R107 - Speaker Mixer (3) */
- [108] = { 0x01FF, 0x01FF, 0x0000 }, /* R108 - Speaker Mixer (4) */
- [109] = { 0x00F0, 0x00F0, 0x0000 }, /* R109 - Speaker Mixer (5) */
- [110] = { 0x00F7, 0x00F7, 0x0000 }, /* R110 - Beep Generator (1) */
- [115] = { 0x001F, 0x001F, 0x0000 }, /* R115 - Oscillator Trim (3) */
- [116] = { 0x001F, 0x001F, 0x0000 }, /* R116 - Oscillator Trim (4) */
- [119] = { 0x00FF, 0x00FF, 0x0000 }, /* R119 - Oscillator Trim (7) */
- [124] = { 0x0079, 0x0079, 0x0000 }, /* R124 - Analogue Clocking1 */
- [125] = { 0x00DF, 0x00DF, 0x0000 }, /* R125 - Analogue Clocking2 */
- [126] = { 0x000D, 0x000D, 0x0000 }, /* R126 - Analogue Clocking3 */
- [127] = { 0x0000, 0xFFFF, 0x0000 }, /* R127 - PLL Software Reset */
- [129] = { 0x00B0, 0x00B0, 0x0000 }, /* R129 - PLL2 */
- [131] = { 0x0003, 0x0003, 0x0000 }, /* R131 - PLL 4 */
- [136] = { 0x005F, 0x005F, 0x0000 }, /* R136 - PLL 9 */
- [137] = { 0x00FF, 0x00FF, 0x0000 }, /* R137 - PLL 10 */
- [138] = { 0x00FF, 0x00FF, 0x0000 }, /* R138 - PLL 11 */
- [139] = { 0x00FF, 0x00FF, 0x0000 }, /* R139 - PLL 12 */
- [140] = { 0x005F, 0x005F, 0x0000 }, /* R140 - PLL 13 */
- [141] = { 0x00FF, 0x00FF, 0x0000 }, /* R141 - PLL 14 */
- [142] = { 0x00FF, 0x00FF, 0x0000 }, /* R142 - PLL 15 */
- [143] = { 0x00FF, 0x00FF, 0x0000 }, /* R143 - PLL 16 */
- [155] = { 0x0067, 0x0067, 0x0000 }, /* R155 - FLL Control (1) */
- [156] = { 0x01FB, 0x01FB, 0x0000 }, /* R156 - FLL Control (2) */
- [157] = { 0x0007, 0x0007, 0x0000 }, /* R157 - FLL Control (3) */
- [159] = { 0x007F, 0x007F, 0x0000 }, /* R159 - FLL Control (5) */
- [160] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R160 - FLL Control (6) */
- [161] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R161 - FLL Control (7) */
- [162] = { 0x03FF, 0x03FF, 0x0000 }, /* R162 - FLL Control (8) */
- [252] = { 0x0005, 0x0005, 0x0000 }, /* R252 - General test 1 */
- [256] = { 0x000F, 0x000F, 0x0000 }, /* R256 - DF1 */
- [257] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R257 - DF2 */
- [258] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R258 - DF3 */
- [259] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R259 - DF4 */
- [260] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R260 - DF5 */
- [261] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R261 - DF6 */
- [262] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R262 - DF7 */
- [264] = { 0x0003, 0x0003, 0x0000 }, /* R264 - LHPF1 */
- [265] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R265 - LHPF2 */
- [268] = { 0x0077, 0x0077, 0x0000 }, /* R268 - THREED1 */
- [269] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R269 - THREED2 */
- [270] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R270 - THREED3 */
- [271] = { 0xFFFC, 0xFFFC, 0x0000 }, /* R271 - THREED4 */
- [276] = { 0x7FFF, 0x7FFF, 0x0000 }, /* R276 - DRC 1 */
- [277] = { 0x1FFF, 0x1FFF, 0x0000 }, /* R277 - DRC 2 */
- [278] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R278 - DRC 3 */
- [279] = { 0x07FF, 0x07FF, 0x0000 }, /* R279 - DRC 4 */
- [280] = { 0x03FF, 0x03FF, 0x0000 }, /* R280 - DRC 5 */
- [285] = { 0x0003, 0x0003, 0x0000 }, /* R285 - Tloopback */
- [335] = { 0x0007, 0x0007, 0x0000 }, /* R335 - EQ1 */
- [336] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R336 - EQ2 */
- [337] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R337 - EQ3 */
- [338] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R338 - EQ4 */
- [339] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R339 - EQ5 */
- [340] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R340 - EQ6 */
- [341] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R341 - EQ7 */
- [342] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R342 - EQ8 */
- [343] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R343 - EQ9 */
- [344] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R344 - EQ10 */
- [345] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R345 - EQ11 */
- [346] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R346 - EQ12 */
- [347] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R347 - EQ13 */
- [348] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R348 - EQ14 */
- [349] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R349 - EQ15 */
- [350] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R350 - EQ16 */
- [351] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R351 - EQ17 */
- [352] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R352 - EQ18 */
- [353] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R353 - EQ19 */
- [354] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R354 - EQ20 */
- [355] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R355 - EQ21 */
- [356] = { 0xFFFE, 0xFFFE, 0x0000 }, /* R356 - EQ22 */
- [357] = { 0xFFC0, 0xFFC0, 0x0000 }, /* R357 - EQ23 */
- [358] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R358 - EQ24 */
- [359] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R359 - EQ25 */
- [360] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R360 - EQ26 */
- [361] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R361 - EQ27 */
- [362] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R362 - EQ28 */
- [363] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R363 - EQ29 */
- [364] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R364 - EQ30 */
- [365] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R365 - EQ31 */
- [366] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R366 - EQ32 */
- [367] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R367 - EQ33 */
- [368] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R368 - EQ34 */
- [369] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R369 - EQ35 */
- [370] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R370 - EQ36 */
- [371] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R371 - EQ37 */
- [372] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R372 - EQ38 */
- [373] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R373 - EQ39 */
- [374] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R374 - EQ40 */
- [375] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R375 - EQ41 */
- [513] = { 0x045F, 0x045F, 0x0000 }, /* R513 - GPIO 2 */
- [514] = { 0x045F, 0x045F, 0x0000 }, /* R514 - GPIO 3 */
- [516] = { 0xE75F, 0xE75F, 0x0000 }, /* R516 - GPIO 5 */
- [517] = { 0xE75F, 0xE75F, 0x0000 }, /* R517 - GPIO 6 */
- [560] = { 0x0030, 0x0030, 0xFFFF }, /* R560 - Interrupt Status 1 */
- [561] = { 0xFFED, 0xFFED, 0xFFFF }, /* R561 - Interrupt Status 2 */
- [568] = { 0x0030, 0x0030, 0x0000 }, /* R568 - Interrupt Status 1 Mask */
- [569] = { 0xFFED, 0xFFED, 0x0000 }, /* R569 - Interrupt Status 2 Mask */
- [576] = { 0x0001, 0x0001, 0x0000 }, /* R576 - Interrupt Control */
- [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */
- [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */
- [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */
- [1037] = { 0x0000, 0x003F, 0x0000 }, /* R1037 - DSP2_ExecControl */
- [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */
- [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */
- [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */
- [4099] = { 0x010F, 0x010F, 0x0000 }, /* R4099 - Write Sequencer 3 */
- [4100] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4100 - Write Sequencer 4 */
- [4101] = { 0x00FF, 0x00FF, 0x0000 }, /* R4101 - Write Sequencer 5 */
- [4102] = { 0x070F, 0x070F, 0x0000 }, /* R4102 - Write Sequencer 6 */
- [4103] = { 0x010F, 0x010F, 0x0000 }, /* R4103 - Write Sequencer 7 */
- [4104] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4104 - Write Sequencer 8 */
- [4105] = { 0x00FF, 0x00FF, 0x0000 }, /* R4105 - Write Sequencer 9 */
- [4106] = { 0x070F, 0x070F, 0x0000 }, /* R4106 - Write Sequencer 10 */
- [4107] = { 0x010F, 0x010F, 0x0000 }, /* R4107 - Write Sequencer 11 */
- [4108] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4108 - Write Sequencer 12 */
- [4109] = { 0x00FF, 0x00FF, 0x0000 }, /* R4109 - Write Sequencer 13 */
- [4110] = { 0x070F, 0x070F, 0x0000 }, /* R4110 - Write Sequencer 14 */
- [4111] = { 0x010F, 0x010F, 0x0000 }, /* R4111 - Write Sequencer 15 */
- [4112] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4112 - Write Sequencer 16 */
- [4113] = { 0x00FF, 0x00FF, 0x0000 }, /* R4113 - Write Sequencer 17 */
- [4114] = { 0x070F, 0x070F, 0x0000 }, /* R4114 - Write Sequencer 18 */
- [4115] = { 0x010F, 0x010F, 0x0000 }, /* R4115 - Write Sequencer 19 */
- [4116] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4116 - Write Sequencer 20 */
- [4117] = { 0x00FF, 0x00FF, 0x0000 }, /* R4117 - Write Sequencer 21 */
- [4118] = { 0x070F, 0x070F, 0x0000 }, /* R4118 - Write Sequencer 22 */
- [4119] = { 0x010F, 0x010F, 0x0000 }, /* R4119 - Write Sequencer 23 */
- [4120] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4120 - Write Sequencer 24 */
- [4121] = { 0x00FF, 0x00FF, 0x0000 }, /* R4121 - Write Sequencer 25 */
- [4122] = { 0x070F, 0x070F, 0x0000 }, /* R4122 - Write Sequencer 26 */
- [4123] = { 0x010F, 0x010F, 0x0000 }, /* R4123 - Write Sequencer 27 */
- [4124] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4124 - Write Sequencer 28 */
- [4125] = { 0x00FF, 0x00FF, 0x0000 }, /* R4125 - Write Sequencer 29 */
- [4126] = { 0x070F, 0x070F, 0x0000 }, /* R4126 - Write Sequencer 30 */
- [4127] = { 0x010F, 0x010F, 0x0000 }, /* R4127 - Write Sequencer 31 */
- [4128] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4128 - Write Sequencer 32 */
- [4129] = { 0x00FF, 0x00FF, 0x0000 }, /* R4129 - Write Sequencer 33 */
- [4130] = { 0x070F, 0x070F, 0x0000 }, /* R4130 - Write Sequencer 34 */
- [4131] = { 0x010F, 0x010F, 0x0000 }, /* R4131 - Write Sequencer 35 */
- [4132] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4132 - Write Sequencer 36 */
- [4133] = { 0x00FF, 0x00FF, 0x0000 }, /* R4133 - Write Sequencer 37 */
- [4134] = { 0x070F, 0x070F, 0x0000 }, /* R4134 - Write Sequencer 38 */
- [4135] = { 0x010F, 0x010F, 0x0000 }, /* R4135 - Write Sequencer 39 */
- [4136] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4136 - Write Sequencer 40 */
- [4137] = { 0x00FF, 0x00FF, 0x0000 }, /* R4137 - Write Sequencer 41 */
- [4138] = { 0x070F, 0x070F, 0x0000 }, /* R4138 - Write Sequencer 42 */
- [4139] = { 0x010F, 0x010F, 0x0000 }, /* R4139 - Write Sequencer 43 */
- [4140] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4140 - Write Sequencer 44 */
- [4141] = { 0x00FF, 0x00FF, 0x0000 }, /* R4141 - Write Sequencer 45 */
- [4142] = { 0x070F, 0x070F, 0x0000 }, /* R4142 - Write Sequencer 46 */
- [4143] = { 0x010F, 0x010F, 0x0000 }, /* R4143 - Write Sequencer 47 */
- [4144] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4144 - Write Sequencer 48 */
- [4145] = { 0x00FF, 0x00FF, 0x0000 }, /* R4145 - Write Sequencer 49 */
- [4146] = { 0x070F, 0x070F, 0x0000 }, /* R4146 - Write Sequencer 50 */
- [4147] = { 0x010F, 0x010F, 0x0000 }, /* R4147 - Write Sequencer 51 */
- [4148] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4148 - Write Sequencer 52 */
- [4149] = { 0x00FF, 0x00FF, 0x0000 }, /* R4149 - Write Sequencer 53 */
- [4150] = { 0x070F, 0x070F, 0x0000 }, /* R4150 - Write Sequencer 54 */
- [4151] = { 0x010F, 0x010F, 0x0000 }, /* R4151 - Write Sequencer 55 */
- [4152] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4152 - Write Sequencer 56 */
- [4153] = { 0x00FF, 0x00FF, 0x0000 }, /* R4153 - Write Sequencer 57 */
- [4154] = { 0x070F, 0x070F, 0x0000 }, /* R4154 - Write Sequencer 58 */
- [4155] = { 0x010F, 0x010F, 0x0000 }, /* R4155 - Write Sequencer 59 */
- [4156] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4156 - Write Sequencer 60 */
- [4157] = { 0x00FF, 0x00FF, 0x0000 }, /* R4157 - Write Sequencer 61 */
- [4158] = { 0x070F, 0x070F, 0x0000 }, /* R4158 - Write Sequencer 62 */
- [4159] = { 0x010F, 0x010F, 0x0000 }, /* R4159 - Write Sequencer 63 */
- [4160] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4160 - Write Sequencer 64 */
- [4161] = { 0x00FF, 0x00FF, 0x0000 }, /* R4161 - Write Sequencer 65 */
- [4162] = { 0x070F, 0x070F, 0x0000 }, /* R4162 - Write Sequencer 66 */
- [4163] = { 0x010F, 0x010F, 0x0000 }, /* R4163 - Write Sequencer 67 */
- [4164] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4164 - Write Sequencer 68 */
- [4165] = { 0x00FF, 0x00FF, 0x0000 }, /* R4165 - Write Sequencer 69 */
- [4166] = { 0x070F, 0x070F, 0x0000 }, /* R4166 - Write Sequencer 70 */
- [4167] = { 0x010F, 0x010F, 0x0000 }, /* R4167 - Write Sequencer 71 */
- [4168] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4168 - Write Sequencer 72 */
- [4169] = { 0x00FF, 0x00FF, 0x0000 }, /* R4169 - Write Sequencer 73 */
- [4170] = { 0x070F, 0x070F, 0x0000 }, /* R4170 - Write Sequencer 74 */
- [4171] = { 0x010F, 0x010F, 0x0000 }, /* R4171 - Write Sequencer 75 */
- [4172] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4172 - Write Sequencer 76 */
- [4173] = { 0x00FF, 0x00FF, 0x0000 }, /* R4173 - Write Sequencer 77 */
- [4174] = { 0x070F, 0x070F, 0x0000 }, /* R4174 - Write Sequencer 78 */
- [4175] = { 0x010F, 0x010F, 0x0000 }, /* R4175 - Write Sequencer 79 */
- [4176] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4176 - Write Sequencer 80 */
- [4177] = { 0x00FF, 0x00FF, 0x0000 }, /* R4177 - Write Sequencer 81 */
- [4178] = { 0x070F, 0x070F, 0x0000 }, /* R4178 - Write Sequencer 82 */
- [4179] = { 0x010F, 0x010F, 0x0000 }, /* R4179 - Write Sequencer 83 */
- [4180] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4180 - Write Sequencer 84 */
- [4181] = { 0x00FF, 0x00FF, 0x0000 }, /* R4181 - Write Sequencer 85 */
- [4182] = { 0x070F, 0x070F, 0x0000 }, /* R4182 - Write Sequencer 86 */
- [4183] = { 0x010F, 0x010F, 0x0000 }, /* R4183 - Write Sequencer 87 */
- [4184] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4184 - Write Sequencer 88 */
- [4185] = { 0x00FF, 0x00FF, 0x0000 }, /* R4185 - Write Sequencer 89 */
- [4186] = { 0x070F, 0x070F, 0x0000 }, /* R4186 - Write Sequencer 90 */
- [4187] = { 0x010F, 0x010F, 0x0000 }, /* R4187 - Write Sequencer 91 */
- [4188] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4188 - Write Sequencer 92 */
- [4189] = { 0x00FF, 0x00FF, 0x0000 }, /* R4189 - Write Sequencer 93 */
- [4190] = { 0x070F, 0x070F, 0x0000 }, /* R4190 - Write Sequencer 94 */
- [4191] = { 0x010F, 0x010F, 0x0000 }, /* R4191 - Write Sequencer 95 */
- [4192] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4192 - Write Sequencer 96 */
- [4193] = { 0x00FF, 0x00FF, 0x0000 }, /* R4193 - Write Sequencer 97 */
- [4194] = { 0x070F, 0x070F, 0x0000 }, /* R4194 - Write Sequencer 98 */
- [4195] = { 0x010F, 0x010F, 0x0000 }, /* R4195 - Write Sequencer 99 */
- [4196] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4196 - Write Sequencer 100 */
- [4197] = { 0x00FF, 0x00FF, 0x0000 }, /* R4197 - Write Sequencer 101 */
- [4198] = { 0x070F, 0x070F, 0x0000 }, /* R4198 - Write Sequencer 102 */
- [4199] = { 0x010F, 0x010F, 0x0000 }, /* R4199 - Write Sequencer 103 */
- [4200] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4200 - Write Sequencer 104 */
- [4201] = { 0x00FF, 0x00FF, 0x0000 }, /* R4201 - Write Sequencer 105 */
- [4202] = { 0x070F, 0x070F, 0x0000 }, /* R4202 - Write Sequencer 106 */
- [4203] = { 0x010F, 0x010F, 0x0000 }, /* R4203 - Write Sequencer 107 */
- [4204] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4204 - Write Sequencer 108 */
- [4205] = { 0x00FF, 0x00FF, 0x0000 }, /* R4205 - Write Sequencer 109 */
- [4206] = { 0x070F, 0x070F, 0x0000 }, /* R4206 - Write Sequencer 110 */
- [4207] = { 0x010F, 0x010F, 0x0000 }, /* R4207 - Write Sequencer 111 */
- [4208] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4208 - Write Sequencer 112 */
- [4209] = { 0x00FF, 0x00FF, 0x0000 }, /* R4209 - Write Sequencer 113 */
- [4210] = { 0x070F, 0x070F, 0x0000 }, /* R4210 - Write Sequencer 114 */
- [4211] = { 0x010F, 0x010F, 0x0000 }, /* R4211 - Write Sequencer 115 */
- [4212] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4212 - Write Sequencer 116 */
- [4213] = { 0x00FF, 0x00FF, 0x0000 }, /* R4213 - Write Sequencer 117 */
- [4214] = { 0x070F, 0x070F, 0x0000 }, /* R4214 - Write Sequencer 118 */
- [4215] = { 0x010F, 0x010F, 0x0000 }, /* R4215 - Write Sequencer 119 */
- [4216] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4216 - Write Sequencer 120 */
- [4217] = { 0x00FF, 0x00FF, 0x0000 }, /* R4217 - Write Sequencer 121 */
- [4218] = { 0x070F, 0x070F, 0x0000 }, /* R4218 - Write Sequencer 122 */
- [4219] = { 0x010F, 0x010F, 0x0000 }, /* R4219 - Write Sequencer 123 */
- [4220] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4220 - Write Sequencer 124 */
- [4221] = { 0x00FF, 0x00FF, 0x0000 }, /* R4221 - Write Sequencer 125 */
- [4222] = { 0x070F, 0x070F, 0x0000 }, /* R4222 - Write Sequencer 126 */
- [4223] = { 0x010F, 0x010F, 0x0000 }, /* R4223 - Write Sequencer 127 */
- [4224] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4224 - Write Sequencer 128 */
- [4225] = { 0x00FF, 0x00FF, 0x0000 }, /* R4225 - Write Sequencer 129 */
- [4226] = { 0x070F, 0x070F, 0x0000 }, /* R4226 - Write Sequencer 130 */
- [4227] = { 0x010F, 0x010F, 0x0000 }, /* R4227 - Write Sequencer 131 */
- [4228] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4228 - Write Sequencer 132 */
- [4229] = { 0x00FF, 0x00FF, 0x0000 }, /* R4229 - Write Sequencer 133 */
- [4230] = { 0x070F, 0x070F, 0x0000 }, /* R4230 - Write Sequencer 134 */
- [4231] = { 0x010F, 0x010F, 0x0000 }, /* R4231 - Write Sequencer 135 */
- [4232] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4232 - Write Sequencer 136 */
- [4233] = { 0x00FF, 0x00FF, 0x0000 }, /* R4233 - Write Sequencer 137 */
- [4234] = { 0x070F, 0x070F, 0x0000 }, /* R4234 - Write Sequencer 138 */
- [4235] = { 0x010F, 0x010F, 0x0000 }, /* R4235 - Write Sequencer 139 */
- [4236] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4236 - Write Sequencer 140 */
- [4237] = { 0x00FF, 0x00FF, 0x0000 }, /* R4237 - Write Sequencer 141 */
- [4238] = { 0x070F, 0x070F, 0x0000 }, /* R4238 - Write Sequencer 142 */
- [4239] = { 0x010F, 0x010F, 0x0000 }, /* R4239 - Write Sequencer 143 */
- [4240] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4240 - Write Sequencer 144 */
- [4241] = { 0x00FF, 0x00FF, 0x0000 }, /* R4241 - Write Sequencer 145 */
- [4242] = { 0x070F, 0x070F, 0x0000 }, /* R4242 - Write Sequencer 146 */
- [4243] = { 0x010F, 0x010F, 0x0000 }, /* R4243 - Write Sequencer 147 */
- [4244] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4244 - Write Sequencer 148 */
- [4245] = { 0x00FF, 0x00FF, 0x0000 }, /* R4245 - Write Sequencer 149 */
- [4246] = { 0x070F, 0x070F, 0x0000 }, /* R4246 - Write Sequencer 150 */
- [4247] = { 0x010F, 0x010F, 0x0000 }, /* R4247 - Write Sequencer 151 */
- [4248] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4248 - Write Sequencer 152 */
- [4249] = { 0x00FF, 0x00FF, 0x0000 }, /* R4249 - Write Sequencer 153 */
- [4250] = { 0x070F, 0x070F, 0x0000 }, /* R4250 - Write Sequencer 154 */
- [4251] = { 0x010F, 0x010F, 0x0000 }, /* R4251 - Write Sequencer 155 */
- [4252] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4252 - Write Sequencer 156 */
- [4253] = { 0x00FF, 0x00FF, 0x0000 }, /* R4253 - Write Sequencer 157 */
- [4254] = { 0x070F, 0x070F, 0x0000 }, /* R4254 - Write Sequencer 158 */
- [4255] = { 0x010F, 0x010F, 0x0000 }, /* R4255 - Write Sequencer 159 */
- [4256] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4256 - Write Sequencer 160 */
- [4257] = { 0x00FF, 0x00FF, 0x0000 }, /* R4257 - Write Sequencer 161 */
- [4258] = { 0x070F, 0x070F, 0x0000 }, /* R4258 - Write Sequencer 162 */
- [4259] = { 0x010F, 0x010F, 0x0000 }, /* R4259 - Write Sequencer 163 */
- [4260] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4260 - Write Sequencer 164 */
- [4261] = { 0x00FF, 0x00FF, 0x0000 }, /* R4261 - Write Sequencer 165 */
- [4262] = { 0x070F, 0x070F, 0x0000 }, /* R4262 - Write Sequencer 166 */
- [4263] = { 0x010F, 0x010F, 0x0000 }, /* R4263 - Write Sequencer 167 */
- [4264] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4264 - Write Sequencer 168 */
- [4265] = { 0x00FF, 0x00FF, 0x0000 }, /* R4265 - Write Sequencer 169 */
- [4266] = { 0x070F, 0x070F, 0x0000 }, /* R4266 - Write Sequencer 170 */
- [4267] = { 0x010F, 0x010F, 0x0000 }, /* R4267 - Write Sequencer 171 */
- [4268] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4268 - Write Sequencer 172 */
- [4269] = { 0x00FF, 0x00FF, 0x0000 }, /* R4269 - Write Sequencer 173 */
- [4270] = { 0x070F, 0x070F, 0x0000 }, /* R4270 - Write Sequencer 174 */
- [4271] = { 0x010F, 0x010F, 0x0000 }, /* R4271 - Write Sequencer 175 */
- [4272] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4272 - Write Sequencer 176 */
- [4273] = { 0x00FF, 0x00FF, 0x0000 }, /* R4273 - Write Sequencer 177 */
- [4274] = { 0x070F, 0x070F, 0x0000 }, /* R4274 - Write Sequencer 178 */
- [4275] = { 0x010F, 0x010F, 0x0000 }, /* R4275 - Write Sequencer 179 */
- [4276] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4276 - Write Sequencer 180 */
- [4277] = { 0x00FF, 0x00FF, 0x0000 }, /* R4277 - Write Sequencer 181 */
- [4278] = { 0x070F, 0x070F, 0x0000 }, /* R4278 - Write Sequencer 182 */
- [4279] = { 0x010F, 0x010F, 0x0000 }, /* R4279 - Write Sequencer 183 */
- [4280] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4280 - Write Sequencer 184 */
- [4281] = { 0x00FF, 0x00FF, 0x0000 }, /* R4281 - Write Sequencer 185 */
- [4282] = { 0x070F, 0x070F, 0x0000 }, /* R4282 - Write Sequencer 186 */
- [4283] = { 0x010F, 0x010F, 0x0000 }, /* R4283 - Write Sequencer 187 */
- [4284] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4284 - Write Sequencer 188 */
- [4285] = { 0x00FF, 0x00FF, 0x0000 }, /* R4285 - Write Sequencer 189 */
- [4286] = { 0x070F, 0x070F, 0x0000 }, /* R4286 - Write Sequencer 190 */
- [4287] = { 0x010F, 0x010F, 0x0000 }, /* R4287 - Write Sequencer 191 */
- [4288] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4288 - Write Sequencer 192 */
- [4289] = { 0x00FF, 0x00FF, 0x0000 }, /* R4289 - Write Sequencer 193 */
- [4290] = { 0x070F, 0x070F, 0x0000 }, /* R4290 - Write Sequencer 194 */
- [4291] = { 0x010F, 0x010F, 0x0000 }, /* R4291 - Write Sequencer 195 */
- [4292] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4292 - Write Sequencer 196 */
- [4293] = { 0x00FF, 0x00FF, 0x0000 }, /* R4293 - Write Sequencer 197 */
- [4294] = { 0x070F, 0x070F, 0x0000 }, /* R4294 - Write Sequencer 198 */
- [4295] = { 0x010F, 0x010F, 0x0000 }, /* R4295 - Write Sequencer 199 */
- [4296] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4296 - Write Sequencer 200 */
- [4297] = { 0x00FF, 0x00FF, 0x0000 }, /* R4297 - Write Sequencer 201 */
- [4298] = { 0x070F, 0x070F, 0x0000 }, /* R4298 - Write Sequencer 202 */
- [4299] = { 0x010F, 0x010F, 0x0000 }, /* R4299 - Write Sequencer 203 */
- [4300] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4300 - Write Sequencer 204 */
- [4301] = { 0x00FF, 0x00FF, 0x0000 }, /* R4301 - Write Sequencer 205 */
- [4302] = { 0x070F, 0x070F, 0x0000 }, /* R4302 - Write Sequencer 206 */
- [4303] = { 0x010F, 0x010F, 0x0000 }, /* R4303 - Write Sequencer 207 */
- [4304] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4304 - Write Sequencer 208 */
- [4305] = { 0x00FF, 0x00FF, 0x0000 }, /* R4305 - Write Sequencer 209 */
- [4306] = { 0x070F, 0x070F, 0x0000 }, /* R4306 - Write Sequencer 210 */
- [4307] = { 0x010F, 0x010F, 0x0000 }, /* R4307 - Write Sequencer 211 */
- [4308] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4308 - Write Sequencer 212 */
- [4309] = { 0x00FF, 0x00FF, 0x0000 }, /* R4309 - Write Sequencer 213 */
- [4310] = { 0x070F, 0x070F, 0x0000 }, /* R4310 - Write Sequencer 214 */
- [4311] = { 0x010F, 0x010F, 0x0000 }, /* R4311 - Write Sequencer 215 */
- [4312] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4312 - Write Sequencer 216 */
- [4313] = { 0x00FF, 0x00FF, 0x0000 }, /* R4313 - Write Sequencer 217 */
- [4314] = { 0x070F, 0x070F, 0x0000 }, /* R4314 - Write Sequencer 218 */
- [4315] = { 0x010F, 0x010F, 0x0000 }, /* R4315 - Write Sequencer 219 */
- [4316] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4316 - Write Sequencer 220 */
- [4317] = { 0x00FF, 0x00FF, 0x0000 }, /* R4317 - Write Sequencer 221 */
- [4318] = { 0x070F, 0x070F, 0x0000 }, /* R4318 - Write Sequencer 222 */
- [4319] = { 0x010F, 0x010F, 0x0000 }, /* R4319 - Write Sequencer 223 */
- [4320] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4320 - Write Sequencer 224 */
- [4321] = { 0x00FF, 0x00FF, 0x0000 }, /* R4321 - Write Sequencer 225 */
- [4322] = { 0x070F, 0x070F, 0x0000 }, /* R4322 - Write Sequencer 226 */
- [4323] = { 0x010F, 0x010F, 0x0000 }, /* R4323 - Write Sequencer 227 */
- [4324] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4324 - Write Sequencer 228 */
- [4325] = { 0x00FF, 0x00FF, 0x0000 }, /* R4325 - Write Sequencer 229 */
- [4326] = { 0x070F, 0x070F, 0x0000 }, /* R4326 - Write Sequencer 230 */
- [4327] = { 0x010F, 0x010F, 0x0000 }, /* R4327 - Write Sequencer 231 */
- [4328] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4328 - Write Sequencer 232 */
- [4329] = { 0x00FF, 0x00FF, 0x0000 }, /* R4329 - Write Sequencer 233 */
- [4330] = { 0x070F, 0x070F, 0x0000 }, /* R4330 - Write Sequencer 234 */
- [4331] = { 0x010F, 0x010F, 0x0000 }, /* R4331 - Write Sequencer 235 */
- [4332] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4332 - Write Sequencer 236 */
- [4333] = { 0x00FF, 0x00FF, 0x0000 }, /* R4333 - Write Sequencer 237 */
- [4334] = { 0x070F, 0x070F, 0x0000 }, /* R4334 - Write Sequencer 238 */
- [4335] = { 0x010F, 0x010F, 0x0000 }, /* R4335 - Write Sequencer 239 */
- [4336] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4336 - Write Sequencer 240 */
- [4337] = { 0x00FF, 0x00FF, 0x0000 }, /* R4337 - Write Sequencer 241 */
- [4338] = { 0x070F, 0x070F, 0x0000 }, /* R4338 - Write Sequencer 242 */
- [4339] = { 0x010F, 0x010F, 0x0000 }, /* R4339 - Write Sequencer 243 */
- [4340] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4340 - Write Sequencer 244 */
- [4341] = { 0x00FF, 0x00FF, 0x0000 }, /* R4341 - Write Sequencer 245 */
- [4342] = { 0x070F, 0x070F, 0x0000 }, /* R4342 - Write Sequencer 246 */
- [4343] = { 0x010F, 0x010F, 0x0000 }, /* R4343 - Write Sequencer 247 */
- [4344] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4344 - Write Sequencer 248 */
- [4345] = { 0x00FF, 0x00FF, 0x0000 }, /* R4345 - Write Sequencer 249 */
- [4346] = { 0x070F, 0x070F, 0x0000 }, /* R4346 - Write Sequencer 250 */
- [4347] = { 0x010F, 0x010F, 0x0000 }, /* R4347 - Write Sequencer 251 */
- [4348] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4348 - Write Sequencer 252 */
- [4349] = { 0x00FF, 0x00FF, 0x0000 }, /* R4349 - Write Sequencer 253 */
- [4350] = { 0x070F, 0x070F, 0x0000 }, /* R4350 - Write Sequencer 254 */
- [4351] = { 0x010F, 0x010F, 0x0000 }, /* R4351 - Write Sequencer 255 */
- [4352] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4352 - Write Sequencer 256 */
- [4353] = { 0x00FF, 0x00FF, 0x0000 }, /* R4353 - Write Sequencer 257 */
- [4354] = { 0x070F, 0x070F, 0x0000 }, /* R4354 - Write Sequencer 258 */
- [4355] = { 0x010F, 0x010F, 0x0000 }, /* R4355 - Write Sequencer 259 */
- [4356] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4356 - Write Sequencer 260 */
- [4357] = { 0x00FF, 0x00FF, 0x0000 }, /* R4357 - Write Sequencer 261 */
- [4358] = { 0x070F, 0x070F, 0x0000 }, /* R4358 - Write Sequencer 262 */
- [4359] = { 0x010F, 0x010F, 0x0000 }, /* R4359 - Write Sequencer 263 */
- [4360] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4360 - Write Sequencer 264 */
- [4361] = { 0x00FF, 0x00FF, 0x0000 }, /* R4361 - Write Sequencer 265 */
- [4362] = { 0x070F, 0x070F, 0x0000 }, /* R4362 - Write Sequencer 266 */
- [4363] = { 0x010F, 0x010F, 0x0000 }, /* R4363 - Write Sequencer 267 */
- [4364] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4364 - Write Sequencer 268 */
- [4365] = { 0x00FF, 0x00FF, 0x0000 }, /* R4365 - Write Sequencer 269 */
- [4366] = { 0x070F, 0x070F, 0x0000 }, /* R4366 - Write Sequencer 270 */
- [4367] = { 0x010F, 0x010F, 0x0000 }, /* R4367 - Write Sequencer 271 */
- [4368] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4368 - Write Sequencer 272 */
- [4369] = { 0x00FF, 0x00FF, 0x0000 }, /* R4369 - Write Sequencer 273 */
- [4370] = { 0x070F, 0x070F, 0x0000 }, /* R4370 - Write Sequencer 274 */
- [4371] = { 0x010F, 0x010F, 0x0000 }, /* R4371 - Write Sequencer 275 */
- [4372] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4372 - Write Sequencer 276 */
- [4373] = { 0x00FF, 0x00FF, 0x0000 }, /* R4373 - Write Sequencer 277 */
- [4374] = { 0x070F, 0x070F, 0x0000 }, /* R4374 - Write Sequencer 278 */
- [4375] = { 0x010F, 0x010F, 0x0000 }, /* R4375 - Write Sequencer 279 */
- [4376] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4376 - Write Sequencer 280 */
- [4377] = { 0x00FF, 0x00FF, 0x0000 }, /* R4377 - Write Sequencer 281 */
- [4378] = { 0x070F, 0x070F, 0x0000 }, /* R4378 - Write Sequencer 282 */
- [4379] = { 0x010F, 0x010F, 0x0000 }, /* R4379 - Write Sequencer 283 */
- [4380] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4380 - Write Sequencer 284 */
- [4381] = { 0x00FF, 0x00FF, 0x0000 }, /* R4381 - Write Sequencer 285 */
- [4382] = { 0x070F, 0x070F, 0x0000 }, /* R4382 - Write Sequencer 286 */
- [4383] = { 0x010F, 0x010F, 0x0000 }, /* R4383 - Write Sequencer 287 */
- [4384] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4384 - Write Sequencer 288 */
- [4385] = { 0x00FF, 0x00FF, 0x0000 }, /* R4385 - Write Sequencer 289 */
- [4386] = { 0x070F, 0x070F, 0x0000 }, /* R4386 - Write Sequencer 290 */
- [4387] = { 0x010F, 0x010F, 0x0000 }, /* R4387 - Write Sequencer 291 */
- [4388] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4388 - Write Sequencer 292 */
- [4389] = { 0x00FF, 0x00FF, 0x0000 }, /* R4389 - Write Sequencer 293 */
- [4390] = { 0x070F, 0x070F, 0x0000 }, /* R4390 - Write Sequencer 294 */
- [4391] = { 0x010F, 0x010F, 0x0000 }, /* R4391 - Write Sequencer 295 */
- [4392] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4392 - Write Sequencer 296 */
- [4393] = { 0x00FF, 0x00FF, 0x0000 }, /* R4393 - Write Sequencer 297 */
- [4394] = { 0x070F, 0x070F, 0x0000 }, /* R4394 - Write Sequencer 298 */
- [4395] = { 0x010F, 0x010F, 0x0000 }, /* R4395 - Write Sequencer 299 */
- [4396] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4396 - Write Sequencer 300 */
- [4397] = { 0x00FF, 0x00FF, 0x0000 }, /* R4397 - Write Sequencer 301 */
- [4398] = { 0x070F, 0x070F, 0x0000 }, /* R4398 - Write Sequencer 302 */
- [4399] = { 0x010F, 0x010F, 0x0000 }, /* R4399 - Write Sequencer 303 */
- [4400] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4400 - Write Sequencer 304 */
- [4401] = { 0x00FF, 0x00FF, 0x0000 }, /* R4401 - Write Sequencer 305 */
- [4402] = { 0x070F, 0x070F, 0x0000 }, /* R4402 - Write Sequencer 306 */
- [4403] = { 0x010F, 0x010F, 0x0000 }, /* R4403 - Write Sequencer 307 */
- [4404] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4404 - Write Sequencer 308 */
- [4405] = { 0x00FF, 0x00FF, 0x0000 }, /* R4405 - Write Sequencer 309 */
- [4406] = { 0x070F, 0x070F, 0x0000 }, /* R4406 - Write Sequencer 310 */
- [4407] = { 0x010F, 0x010F, 0x0000 }, /* R4407 - Write Sequencer 311 */
- [4408] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4408 - Write Sequencer 312 */
- [4409] = { 0x00FF, 0x00FF, 0x0000 }, /* R4409 - Write Sequencer 313 */
- [4410] = { 0x070F, 0x070F, 0x0000 }, /* R4410 - Write Sequencer 314 */
- [4411] = { 0x010F, 0x010F, 0x0000 }, /* R4411 - Write Sequencer 315 */
- [4412] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4412 - Write Sequencer 316 */
- [4413] = { 0x00FF, 0x00FF, 0x0000 }, /* R4413 - Write Sequencer 317 */
- [4414] = { 0x070F, 0x070F, 0x0000 }, /* R4414 - Write Sequencer 318 */
- [4415] = { 0x010F, 0x010F, 0x0000 }, /* R4415 - Write Sequencer 319 */
- [4416] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4416 - Write Sequencer 320 */
- [4417] = { 0x00FF, 0x00FF, 0x0000 }, /* R4417 - Write Sequencer 321 */
- [4418] = { 0x070F, 0x070F, 0x0000 }, /* R4418 - Write Sequencer 322 */
- [4419] = { 0x010F, 0x010F, 0x0000 }, /* R4419 - Write Sequencer 323 */
- [4420] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4420 - Write Sequencer 324 */
- [4421] = { 0x00FF, 0x00FF, 0x0000 }, /* R4421 - Write Sequencer 325 */
- [4422] = { 0x070F, 0x070F, 0x0000 }, /* R4422 - Write Sequencer 326 */
- [4423] = { 0x010F, 0x010F, 0x0000 }, /* R4423 - Write Sequencer 327 */
- [4424] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4424 - Write Sequencer 328 */
- [4425] = { 0x00FF, 0x00FF, 0x0000 }, /* R4425 - Write Sequencer 329 */
- [4426] = { 0x070F, 0x070F, 0x0000 }, /* R4426 - Write Sequencer 330 */
- [4427] = { 0x010F, 0x010F, 0x0000 }, /* R4427 - Write Sequencer 331 */
- [4428] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4428 - Write Sequencer 332 */
- [4429] = { 0x00FF, 0x00FF, 0x0000 }, /* R4429 - Write Sequencer 333 */
- [4430] = { 0x070F, 0x070F, 0x0000 }, /* R4430 - Write Sequencer 334 */
- [4431] = { 0x010F, 0x010F, 0x0000 }, /* R4431 - Write Sequencer 335 */
- [4432] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4432 - Write Sequencer 336 */
- [4433] = { 0x00FF, 0x00FF, 0x0000 }, /* R4433 - Write Sequencer 337 */
- [4434] = { 0x070F, 0x070F, 0x0000 }, /* R4434 - Write Sequencer 338 */
- [4435] = { 0x010F, 0x010F, 0x0000 }, /* R4435 - Write Sequencer 339 */
- [4436] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4436 - Write Sequencer 340 */
- [4437] = { 0x00FF, 0x00FF, 0x0000 }, /* R4437 - Write Sequencer 341 */
- [4438] = { 0x070F, 0x070F, 0x0000 }, /* R4438 - Write Sequencer 342 */
- [4439] = { 0x010F, 0x010F, 0x0000 }, /* R4439 - Write Sequencer 343 */
- [4440] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4440 - Write Sequencer 344 */
- [4441] = { 0x00FF, 0x00FF, 0x0000 }, /* R4441 - Write Sequencer 345 */
- [4442] = { 0x070F, 0x070F, 0x0000 }, /* R4442 - Write Sequencer 346 */
- [4443] = { 0x010F, 0x010F, 0x0000 }, /* R4443 - Write Sequencer 347 */
- [4444] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4444 - Write Sequencer 348 */
- [4445] = { 0x00FF, 0x00FF, 0x0000 }, /* R4445 - Write Sequencer 349 */
- [4446] = { 0x070F, 0x070F, 0x0000 }, /* R4446 - Write Sequencer 350 */
- [4447] = { 0x010F, 0x010F, 0x0000 }, /* R4447 - Write Sequencer 351 */
- [4448] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4448 - Write Sequencer 352 */
- [4449] = { 0x00FF, 0x00FF, 0x0000 }, /* R4449 - Write Sequencer 353 */
- [4450] = { 0x070F, 0x070F, 0x0000 }, /* R4450 - Write Sequencer 354 */
- [4451] = { 0x010F, 0x010F, 0x0000 }, /* R4451 - Write Sequencer 355 */
- [4452] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4452 - Write Sequencer 356 */
- [4453] = { 0x00FF, 0x00FF, 0x0000 }, /* R4453 - Write Sequencer 357 */
- [4454] = { 0x070F, 0x070F, 0x0000 }, /* R4454 - Write Sequencer 358 */
- [4455] = { 0x010F, 0x010F, 0x0000 }, /* R4455 - Write Sequencer 359 */
- [4456] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4456 - Write Sequencer 360 */
- [4457] = { 0x00FF, 0x00FF, 0x0000 }, /* R4457 - Write Sequencer 361 */
- [4458] = { 0x070F, 0x070F, 0x0000 }, /* R4458 - Write Sequencer 362 */
- [4459] = { 0x010F, 0x010F, 0x0000 }, /* R4459 - Write Sequencer 363 */
- [4460] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4460 - Write Sequencer 364 */
- [4461] = { 0x00FF, 0x00FF, 0x0000 }, /* R4461 - Write Sequencer 365 */
- [4462] = { 0x070F, 0x070F, 0x0000 }, /* R4462 - Write Sequencer 366 */
- [4463] = { 0x010F, 0x010F, 0x0000 }, /* R4463 - Write Sequencer 367 */
- [4464] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4464 - Write Sequencer 368 */
- [4465] = { 0x00FF, 0x00FF, 0x0000 }, /* R4465 - Write Sequencer 369 */
- [4466] = { 0x070F, 0x070F, 0x0000 }, /* R4466 - Write Sequencer 370 */
- [4467] = { 0x010F, 0x010F, 0x0000 }, /* R4467 - Write Sequencer 371 */
- [4468] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4468 - Write Sequencer 372 */
- [4469] = { 0x00FF, 0x00FF, 0x0000 }, /* R4469 - Write Sequencer 373 */
- [4470] = { 0x070F, 0x070F, 0x0000 }, /* R4470 - Write Sequencer 374 */
- [4471] = { 0x010F, 0x010F, 0x0000 }, /* R4471 - Write Sequencer 375 */
- [4472] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4472 - Write Sequencer 376 */
- [4473] = { 0x00FF, 0x00FF, 0x0000 }, /* R4473 - Write Sequencer 377 */
- [4474] = { 0x070F, 0x070F, 0x0000 }, /* R4474 - Write Sequencer 378 */
- [4475] = { 0x010F, 0x010F, 0x0000 }, /* R4475 - Write Sequencer 379 */
- [4476] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4476 - Write Sequencer 380 */
- [4477] = { 0x00FF, 0x00FF, 0x0000 }, /* R4477 - Write Sequencer 381 */
- [4478] = { 0x070F, 0x070F, 0x0000 }, /* R4478 - Write Sequencer 382 */
- [4479] = { 0x010F, 0x010F, 0x0000 }, /* R4479 - Write Sequencer 383 */
- [4480] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4480 - Write Sequencer 384 */
- [4481] = { 0x00FF, 0x00FF, 0x0000 }, /* R4481 - Write Sequencer 385 */
- [4482] = { 0x070F, 0x070F, 0x0000 }, /* R4482 - Write Sequencer 386 */
- [4483] = { 0x010F, 0x010F, 0x0000 }, /* R4483 - Write Sequencer 387 */
- [4484] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4484 - Write Sequencer 388 */
- [4485] = { 0x00FF, 0x00FF, 0x0000 }, /* R4485 - Write Sequencer 389 */
- [4486] = { 0x070F, 0x070F, 0x0000 }, /* R4486 - Write Sequencer 390 */
- [4487] = { 0x010F, 0x010F, 0x0000 }, /* R4487 - Write Sequencer 391 */
- [4488] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4488 - Write Sequencer 392 */
- [4489] = { 0x00FF, 0x00FF, 0x0000 }, /* R4489 - Write Sequencer 393 */
- [4490] = { 0x070F, 0x070F, 0x0000 }, /* R4490 - Write Sequencer 394 */
- [4491] = { 0x010F, 0x010F, 0x0000 }, /* R4491 - Write Sequencer 395 */
- [4492] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4492 - Write Sequencer 396 */
- [4493] = { 0x00FF, 0x00FF, 0x0000 }, /* R4493 - Write Sequencer 397 */
- [4494] = { 0x070F, 0x070F, 0x0000 }, /* R4494 - Write Sequencer 398 */
- [4495] = { 0x010F, 0x010F, 0x0000 }, /* R4495 - Write Sequencer 399 */
- [4496] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4496 - Write Sequencer 400 */
- [4497] = { 0x00FF, 0x00FF, 0x0000 }, /* R4497 - Write Sequencer 401 */
- [4498] = { 0x070F, 0x070F, 0x0000 }, /* R4498 - Write Sequencer 402 */
- [4499] = { 0x010F, 0x010F, 0x0000 }, /* R4499 - Write Sequencer 403 */
- [4500] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4500 - Write Sequencer 404 */
- [4501] = { 0x00FF, 0x00FF, 0x0000 }, /* R4501 - Write Sequencer 405 */
- [4502] = { 0x070F, 0x070F, 0x0000 }, /* R4502 - Write Sequencer 406 */
- [4503] = { 0x010F, 0x010F, 0x0000 }, /* R4503 - Write Sequencer 407 */
- [4504] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4504 - Write Sequencer 408 */
- [4505] = { 0x00FF, 0x00FF, 0x0000 }, /* R4505 - Write Sequencer 409 */
- [4506] = { 0x070F, 0x070F, 0x0000 }, /* R4506 - Write Sequencer 410 */
- [4507] = { 0x010F, 0x010F, 0x0000 }, /* R4507 - Write Sequencer 411 */
- [4508] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4508 - Write Sequencer 412 */
- [4509] = { 0x00FF, 0x00FF, 0x0000 }, /* R4509 - Write Sequencer 413 */
- [4510] = { 0x070F, 0x070F, 0x0000 }, /* R4510 - Write Sequencer 414 */
- [4511] = { 0x010F, 0x010F, 0x0000 }, /* R4511 - Write Sequencer 415 */
- [4512] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4512 - Write Sequencer 416 */
- [4513] = { 0x00FF, 0x00FF, 0x0000 }, /* R4513 - Write Sequencer 417 */
- [4514] = { 0x070F, 0x070F, 0x0000 }, /* R4514 - Write Sequencer 418 */
- [4515] = { 0x010F, 0x010F, 0x0000 }, /* R4515 - Write Sequencer 419 */
- [4516] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4516 - Write Sequencer 420 */
- [4517] = { 0x00FF, 0x00FF, 0x0000 }, /* R4517 - Write Sequencer 421 */
- [4518] = { 0x070F, 0x070F, 0x0000 }, /* R4518 - Write Sequencer 422 */
- [4519] = { 0x010F, 0x010F, 0x0000 }, /* R4519 - Write Sequencer 423 */
- [4520] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4520 - Write Sequencer 424 */
- [4521] = { 0x00FF, 0x00FF, 0x0000 }, /* R4521 - Write Sequencer 425 */
- [4522] = { 0x070F, 0x070F, 0x0000 }, /* R4522 - Write Sequencer 426 */
- [4523] = { 0x010F, 0x010F, 0x0000 }, /* R4523 - Write Sequencer 427 */
- [4524] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4524 - Write Sequencer 428 */
- [4525] = { 0x00FF, 0x00FF, 0x0000 }, /* R4525 - Write Sequencer 429 */
- [4526] = { 0x070F, 0x070F, 0x0000 }, /* R4526 - Write Sequencer 430 */
- [4527] = { 0x010F, 0x010F, 0x0000 }, /* R4527 - Write Sequencer 431 */
- [4528] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4528 - Write Sequencer 432 */
- [4529] = { 0x00FF, 0x00FF, 0x0000 }, /* R4529 - Write Sequencer 433 */
- [4530] = { 0x070F, 0x070F, 0x0000 }, /* R4530 - Write Sequencer 434 */
- [4531] = { 0x010F, 0x010F, 0x0000 }, /* R4531 - Write Sequencer 435 */
- [4532] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4532 - Write Sequencer 436 */
- [4533] = { 0x00FF, 0x00FF, 0x0000 }, /* R4533 - Write Sequencer 437 */
- [4534] = { 0x070F, 0x070F, 0x0000 }, /* R4534 - Write Sequencer 438 */
- [4535] = { 0x010F, 0x010F, 0x0000 }, /* R4535 - Write Sequencer 439 */
- [4536] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4536 - Write Sequencer 440 */
- [4537] = { 0x00FF, 0x00FF, 0x0000 }, /* R4537 - Write Sequencer 441 */
- [4538] = { 0x070F, 0x070F, 0x0000 }, /* R4538 - Write Sequencer 442 */
- [4539] = { 0x010F, 0x010F, 0x0000 }, /* R4539 - Write Sequencer 443 */
- [4540] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4540 - Write Sequencer 444 */
- [4541] = { 0x00FF, 0x00FF, 0x0000 }, /* R4541 - Write Sequencer 445 */
- [4542] = { 0x070F, 0x070F, 0x0000 }, /* R4542 - Write Sequencer 446 */
- [4543] = { 0x010F, 0x010F, 0x0000 }, /* R4543 - Write Sequencer 447 */
- [4544] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4544 - Write Sequencer 448 */
- [4545] = { 0x00FF, 0x00FF, 0x0000 }, /* R4545 - Write Sequencer 449 */
- [4546] = { 0x070F, 0x070F, 0x0000 }, /* R4546 - Write Sequencer 450 */
- [4547] = { 0x010F, 0x010F, 0x0000 }, /* R4547 - Write Sequencer 451 */
- [4548] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4548 - Write Sequencer 452 */
- [4549] = { 0x00FF, 0x00FF, 0x0000 }, /* R4549 - Write Sequencer 453 */
- [4550] = { 0x070F, 0x070F, 0x0000 }, /* R4550 - Write Sequencer 454 */
- [4551] = { 0x010F, 0x010F, 0x0000 }, /* R4551 - Write Sequencer 455 */
- [4552] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4552 - Write Sequencer 456 */
- [4553] = { 0x00FF, 0x00FF, 0x0000 }, /* R4553 - Write Sequencer 457 */
- [4554] = { 0x070F, 0x070F, 0x0000 }, /* R4554 - Write Sequencer 458 */
- [4555] = { 0x010F, 0x010F, 0x0000 }, /* R4555 - Write Sequencer 459 */
- [4556] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4556 - Write Sequencer 460 */
- [4557] = { 0x00FF, 0x00FF, 0x0000 }, /* R4557 - Write Sequencer 461 */
- [4558] = { 0x070F, 0x070F, 0x0000 }, /* R4558 - Write Sequencer 462 */
- [4559] = { 0x010F, 0x010F, 0x0000 }, /* R4559 - Write Sequencer 463 */
- [4560] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4560 - Write Sequencer 464 */
- [4561] = { 0x00FF, 0x00FF, 0x0000 }, /* R4561 - Write Sequencer 465 */
- [4562] = { 0x070F, 0x070F, 0x0000 }, /* R4562 - Write Sequencer 466 */
- [4563] = { 0x010F, 0x010F, 0x0000 }, /* R4563 - Write Sequencer 467 */
- [4564] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4564 - Write Sequencer 468 */
- [4565] = { 0x00FF, 0x00FF, 0x0000 }, /* R4565 - Write Sequencer 469 */
- [4566] = { 0x070F, 0x070F, 0x0000 }, /* R4566 - Write Sequencer 470 */
- [4567] = { 0x010F, 0x010F, 0x0000 }, /* R4567 - Write Sequencer 471 */
- [4568] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4568 - Write Sequencer 472 */
- [4569] = { 0x00FF, 0x00FF, 0x0000 }, /* R4569 - Write Sequencer 473 */
- [4570] = { 0x070F, 0x070F, 0x0000 }, /* R4570 - Write Sequencer 474 */
- [4571] = { 0x010F, 0x010F, 0x0000 }, /* R4571 - Write Sequencer 475 */
- [4572] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4572 - Write Sequencer 476 */
- [4573] = { 0x00FF, 0x00FF, 0x0000 }, /* R4573 - Write Sequencer 477 */
- [4574] = { 0x070F, 0x070F, 0x0000 }, /* R4574 - Write Sequencer 478 */
- [4575] = { 0x010F, 0x010F, 0x0000 }, /* R4575 - Write Sequencer 479 */
- [4576] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4576 - Write Sequencer 480 */
- [4577] = { 0x00FF, 0x00FF, 0x0000 }, /* R4577 - Write Sequencer 481 */
- [4578] = { 0x070F, 0x070F, 0x0000 }, /* R4578 - Write Sequencer 482 */
- [4579] = { 0x010F, 0x010F, 0x0000 }, /* R4579 - Write Sequencer 483 */
- [4580] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4580 - Write Sequencer 484 */
- [4581] = { 0x00FF, 0x00FF, 0x0000 }, /* R4581 - Write Sequencer 485 */
- [4582] = { 0x070F, 0x070F, 0x0000 }, /* R4582 - Write Sequencer 486 */
- [4583] = { 0x010F, 0x010F, 0x0000 }, /* R4583 - Write Sequencer 487 */
- [4584] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4584 - Write Sequencer 488 */
- [4585] = { 0x00FF, 0x00FF, 0x0000 }, /* R4585 - Write Sequencer 489 */
- [4586] = { 0x070F, 0x070F, 0x0000 }, /* R4586 - Write Sequencer 490 */
- [4587] = { 0x010F, 0x010F, 0x0000 }, /* R4587 - Write Sequencer 491 */
- [4588] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4588 - Write Sequencer 492 */
- [4589] = { 0x00FF, 0x00FF, 0x0000 }, /* R4589 - Write Sequencer 493 */
- [4590] = { 0x070F, 0x070F, 0x0000 }, /* R4590 - Write Sequencer 494 */
- [4591] = { 0x010F, 0x010F, 0x0000 }, /* R4591 - Write Sequencer 495 */
- [4592] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4592 - Write Sequencer 496 */
- [4593] = { 0x00FF, 0x00FF, 0x0000 }, /* R4593 - Write Sequencer 497 */
- [4594] = { 0x070F, 0x070F, 0x0000 }, /* R4594 - Write Sequencer 498 */
- [4595] = { 0x010F, 0x010F, 0x0000 }, /* R4595 - Write Sequencer 499 */
- [4596] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4596 - Write Sequencer 500 */
- [4597] = { 0x00FF, 0x00FF, 0x0000 }, /* R4597 - Write Sequencer 501 */
- [4598] = { 0x070F, 0x070F, 0x0000 }, /* R4598 - Write Sequencer 502 */
- [4599] = { 0x010F, 0x010F, 0x0000 }, /* R4599 - Write Sequencer 503 */
- [4600] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4600 - Write Sequencer 504 */
- [4601] = { 0x00FF, 0x00FF, 0x0000 }, /* R4601 - Write Sequencer 505 */
- [4602] = { 0x070F, 0x070F, 0x0000 }, /* R4602 - Write Sequencer 506 */
- [4603] = { 0x010F, 0x010F, 0x0000 }, /* R4603 - Write Sequencer 507 */
- [4604] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4604 - Write Sequencer 508 */
- [4605] = { 0x00FF, 0x00FF, 0x0000 }, /* R4605 - Write Sequencer 509 */
- [4606] = { 0x070F, 0x070F, 0x0000 }, /* R4606 - Write Sequencer 510 */
- [4607] = { 0x010F, 0x010F, 0x0000 }, /* R4607 - Write Sequencer 511 */
- [8192] = { 0x03FF, 0x03FF, 0x0000 }, /* R8192 - DSP2 Instruction RAM 0 */
- [9216] = { 0x003F, 0x003F, 0x0000 }, /* R9216 - DSP2 Address RAM 2 */
- [9217] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9217 - DSP2 Address RAM 1 */
- [9218] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R9218 - DSP2 Address RAM 0 */
- [12288] = { 0x00FF, 0x00FF, 0x0000 }, /* R12288 - DSP2 Data1 RAM 1 */
- [12289] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R12289 - DSP2 Data1 RAM 0 */
- [13312] = { 0x00FF, 0x00FF, 0x0000 }, /* R13312 - DSP2 Data2 RAM 1 */
- [13313] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R13313 - DSP2 Data2 RAM 0 */
- [14336] = { 0x00FF, 0x00FF, 0x0000 }, /* R14336 - DSP2 Data3 RAM 1 */
- [14337] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R14337 - DSP2 Data3 RAM 0 */
- [15360] = { 0x07FF, 0x07FF, 0x0000 }, /* R15360 - DSP2 Coeff RAM 0 */
- [16384] = { 0x00FF, 0x00FF, 0x0000 }, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
- [16385] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
- [16386] = { 0x00FF, 0x00FF, 0x0000 }, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
- [16387] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
- [16388] = { 0x00FF, 0x00FF, 0x0000 }, /* R16388 - SOUNDSTAGE_ENABLES_1 */
- [16389] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16389 - SOUNDSTAGE_ENABLES_0 */
- [16896] = { 0x00FF, 0x00FF, 0x0000 }, /* R16896 - HDBASS_AI_1 */
- [16897] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16897 - HDBASS_AI_0 */
- [16898] = { 0x00FF, 0x00FF, 0x0000 }, /* R16898 - HDBASS_AR_1 */
- [16899] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16899 - HDBASS_AR_0 */
- [16900] = { 0x00FF, 0x00FF, 0x0000 }, /* R16900 - HDBASS_B_1 */
- [16901] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16901 - HDBASS_B_0 */
- [16902] = { 0x00FF, 0x00FF, 0x0000 }, /* R16902 - HDBASS_K_1 */
- [16903] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16903 - HDBASS_K_0 */
- [16904] = { 0x00FF, 0x00FF, 0x0000 }, /* R16904 - HDBASS_N1_1 */
- [16905] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16905 - HDBASS_N1_0 */
- [16906] = { 0x00FF, 0x00FF, 0x0000 }, /* R16906 - HDBASS_N2_1 */
- [16907] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16907 - HDBASS_N2_0 */
- [16908] = { 0x00FF, 0x00FF, 0x0000 }, /* R16908 - HDBASS_N3_1 */
- [16909] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16909 - HDBASS_N3_0 */
- [16910] = { 0x00FF, 0x00FF, 0x0000 }, /* R16910 - HDBASS_N4_1 */
- [16911] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16911 - HDBASS_N4_0 */
- [16912] = { 0x00FF, 0x00FF, 0x0000 }, /* R16912 - HDBASS_N5_1 */
- [16913] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16913 - HDBASS_N5_0 */
- [16914] = { 0x00FF, 0x00FF, 0x0000 }, /* R16914 - HDBASS_X1_1 */
- [16915] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16915 - HDBASS_X1_0 */
- [16916] = { 0x00FF, 0x00FF, 0x0000 }, /* R16916 - HDBASS_X2_1 */
- [16917] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16917 - HDBASS_X2_0 */
- [16918] = { 0x00FF, 0x00FF, 0x0000 }, /* R16918 - HDBASS_X3_1 */
- [16919] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16919 - HDBASS_X3_0 */
- [16920] = { 0x00FF, 0x00FF, 0x0000 }, /* R16920 - HDBASS_ATK_1 */
- [16921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16921 - HDBASS_ATK_0 */
- [16922] = { 0x00FF, 0x00FF, 0x0000 }, /* R16922 - HDBASS_DCY_1 */
- [16923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16923 - HDBASS_DCY_0 */
- [16924] = { 0x00FF, 0x00FF, 0x0000 }, /* R16924 - HDBASS_PG_1 */
- [16925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R16925 - HDBASS_PG_0 */
- [17408] = { 0x00FF, 0x00FF, 0x0000 }, /* R17408 - HPF_C_1 */
- [17409] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17409 - HPF_C_0 */
- [17920] = { 0x00FF, 0x00FF, 0x0000 }, /* R17920 - ADCL_RETUNE_C1_1 */
- [17921] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17921 - ADCL_RETUNE_C1_0 */
- [17922] = { 0x00FF, 0x00FF, 0x0000 }, /* R17922 - ADCL_RETUNE_C2_1 */
- [17923] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17923 - ADCL_RETUNE_C2_0 */
- [17924] = { 0x00FF, 0x00FF, 0x0000 }, /* R17924 - ADCL_RETUNE_C3_1 */
- [17925] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17925 - ADCL_RETUNE_C3_0 */
- [17926] = { 0x00FF, 0x00FF, 0x0000 }, /* R17926 - ADCL_RETUNE_C4_1 */
- [17927] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17927 - ADCL_RETUNE_C4_0 */
- [17928] = { 0x00FF, 0x00FF, 0x0000 }, /* R17928 - ADCL_RETUNE_C5_1 */
- [17929] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17929 - ADCL_RETUNE_C5_0 */
- [17930] = { 0x00FF, 0x00FF, 0x0000 }, /* R17930 - ADCL_RETUNE_C6_1 */
- [17931] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17931 - ADCL_RETUNE_C6_0 */
- [17932] = { 0x00FF, 0x00FF, 0x0000 }, /* R17932 - ADCL_RETUNE_C7_1 */
- [17933] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17933 - ADCL_RETUNE_C7_0 */
- [17934] = { 0x00FF, 0x00FF, 0x0000 }, /* R17934 - ADCL_RETUNE_C8_1 */
- [17935] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17935 - ADCL_RETUNE_C8_0 */
- [17936] = { 0x00FF, 0x00FF, 0x0000 }, /* R17936 - ADCL_RETUNE_C9_1 */
- [17937] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17937 - ADCL_RETUNE_C9_0 */
- [17938] = { 0x00FF, 0x00FF, 0x0000 }, /* R17938 - ADCL_RETUNE_C10_1 */
- [17939] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17939 - ADCL_RETUNE_C10_0 */
- [17940] = { 0x00FF, 0x00FF, 0x0000 }, /* R17940 - ADCL_RETUNE_C11_1 */
- [17941] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17941 - ADCL_RETUNE_C11_0 */
- [17942] = { 0x00FF, 0x00FF, 0x0000 }, /* R17942 - ADCL_RETUNE_C12_1 */
- [17943] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17943 - ADCL_RETUNE_C12_0 */
- [17944] = { 0x00FF, 0x00FF, 0x0000 }, /* R17944 - ADCL_RETUNE_C13_1 */
- [17945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17945 - ADCL_RETUNE_C13_0 */
- [17946] = { 0x00FF, 0x00FF, 0x0000 }, /* R17946 - ADCL_RETUNE_C14_1 */
- [17947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17947 - ADCL_RETUNE_C14_0 */
- [17948] = { 0x00FF, 0x00FF, 0x0000 }, /* R17948 - ADCL_RETUNE_C15_1 */
- [17949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17949 - ADCL_RETUNE_C15_0 */
- [17950] = { 0x00FF, 0x00FF, 0x0000 }, /* R17950 - ADCL_RETUNE_C16_1 */
- [17951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17951 - ADCL_RETUNE_C16_0 */
- [17952] = { 0x00FF, 0x00FF, 0x0000 }, /* R17952 - ADCL_RETUNE_C17_1 */
- [17953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17953 - ADCL_RETUNE_C17_0 */
- [17954] = { 0x00FF, 0x00FF, 0x0000 }, /* R17954 - ADCL_RETUNE_C18_1 */
- [17955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17955 - ADCL_RETUNE_C18_0 */
- [17956] = { 0x00FF, 0x00FF, 0x0000 }, /* R17956 - ADCL_RETUNE_C19_1 */
- [17957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17957 - ADCL_RETUNE_C19_0 */
- [17958] = { 0x00FF, 0x00FF, 0x0000 }, /* R17958 - ADCL_RETUNE_C20_1 */
- [17959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17959 - ADCL_RETUNE_C20_0 */
- [17960] = { 0x00FF, 0x00FF, 0x0000 }, /* R17960 - ADCL_RETUNE_C21_1 */
- [17961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17961 - ADCL_RETUNE_C21_0 */
- [17962] = { 0x00FF, 0x00FF, 0x0000 }, /* R17962 - ADCL_RETUNE_C22_1 */
- [17963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17963 - ADCL_RETUNE_C22_0 */
- [17964] = { 0x00FF, 0x00FF, 0x0000 }, /* R17964 - ADCL_RETUNE_C23_1 */
- [17965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17965 - ADCL_RETUNE_C23_0 */
- [17966] = { 0x00FF, 0x00FF, 0x0000 }, /* R17966 - ADCL_RETUNE_C24_1 */
- [17967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17967 - ADCL_RETUNE_C24_0 */
- [17968] = { 0x00FF, 0x00FF, 0x0000 }, /* R17968 - ADCL_RETUNE_C25_1 */
- [17969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17969 - ADCL_RETUNE_C25_0 */
- [17970] = { 0x00FF, 0x00FF, 0x0000 }, /* R17970 - ADCL_RETUNE_C26_1 */
- [17971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17971 - ADCL_RETUNE_C26_0 */
- [17972] = { 0x00FF, 0x00FF, 0x0000 }, /* R17972 - ADCL_RETUNE_C27_1 */
- [17973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17973 - ADCL_RETUNE_C27_0 */
- [17974] = { 0x00FF, 0x00FF, 0x0000 }, /* R17974 - ADCL_RETUNE_C28_1 */
- [17975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17975 - ADCL_RETUNE_C28_0 */
- [17976] = { 0x00FF, 0x00FF, 0x0000 }, /* R17976 - ADCL_RETUNE_C29_1 */
- [17977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17977 - ADCL_RETUNE_C29_0 */
- [17978] = { 0x00FF, 0x00FF, 0x0000 }, /* R17978 - ADCL_RETUNE_C30_1 */
- [17979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17979 - ADCL_RETUNE_C30_0 */
- [17980] = { 0x00FF, 0x00FF, 0x0000 }, /* R17980 - ADCL_RETUNE_C31_1 */
- [17981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17981 - ADCL_RETUNE_C31_0 */
- [17982] = { 0x00FF, 0x00FF, 0x0000 }, /* R17982 - ADCL_RETUNE_C32_1 */
- [17983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R17983 - ADCL_RETUNE_C32_0 */
- [18432] = { 0x00FF, 0x00FF, 0x0000 }, /* R18432 - RETUNEADC_PG2_1 */
- [18433] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18433 - RETUNEADC_PG2_0 */
- [18434] = { 0x00FF, 0x00FF, 0x0000 }, /* R18434 - RETUNEADC_PG_1 */
- [18435] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18435 - RETUNEADC_PG_0 */
- [18944] = { 0x00FF, 0x00FF, 0x0000 }, /* R18944 - ADCR_RETUNE_C1_1 */
- [18945] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18945 - ADCR_RETUNE_C1_0 */
- [18946] = { 0x00FF, 0x00FF, 0x0000 }, /* R18946 - ADCR_RETUNE_C2_1 */
- [18947] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18947 - ADCR_RETUNE_C2_0 */
- [18948] = { 0x00FF, 0x00FF, 0x0000 }, /* R18948 - ADCR_RETUNE_C3_1 */
- [18949] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18949 - ADCR_RETUNE_C3_0 */
- [18950] = { 0x00FF, 0x00FF, 0x0000 }, /* R18950 - ADCR_RETUNE_C4_1 */
- [18951] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18951 - ADCR_RETUNE_C4_0 */
- [18952] = { 0x00FF, 0x00FF, 0x0000 }, /* R18952 - ADCR_RETUNE_C5_1 */
- [18953] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18953 - ADCR_RETUNE_C5_0 */
- [18954] = { 0x00FF, 0x00FF, 0x0000 }, /* R18954 - ADCR_RETUNE_C6_1 */
- [18955] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18955 - ADCR_RETUNE_C6_0 */
- [18956] = { 0x00FF, 0x00FF, 0x0000 }, /* R18956 - ADCR_RETUNE_C7_1 */
- [18957] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18957 - ADCR_RETUNE_C7_0 */
- [18958] = { 0x00FF, 0x00FF, 0x0000 }, /* R18958 - ADCR_RETUNE_C8_1 */
- [18959] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18959 - ADCR_RETUNE_C8_0 */
- [18960] = { 0x00FF, 0x00FF, 0x0000 }, /* R18960 - ADCR_RETUNE_C9_1 */
- [18961] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18961 - ADCR_RETUNE_C9_0 */
- [18962] = { 0x00FF, 0x00FF, 0x0000 }, /* R18962 - ADCR_RETUNE_C10_1 */
- [18963] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18963 - ADCR_RETUNE_C10_0 */
- [18964] = { 0x00FF, 0x00FF, 0x0000 }, /* R18964 - ADCR_RETUNE_C11_1 */
- [18965] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18965 - ADCR_RETUNE_C11_0 */
- [18966] = { 0x00FF, 0x00FF, 0x0000 }, /* R18966 - ADCR_RETUNE_C12_1 */
- [18967] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18967 - ADCR_RETUNE_C12_0 */
- [18968] = { 0x00FF, 0x00FF, 0x0000 }, /* R18968 - ADCR_RETUNE_C13_1 */
- [18969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18969 - ADCR_RETUNE_C13_0 */
- [18970] = { 0x00FF, 0x00FF, 0x0000 }, /* R18970 - ADCR_RETUNE_C14_1 */
- [18971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18971 - ADCR_RETUNE_C14_0 */
- [18972] = { 0x00FF, 0x00FF, 0x0000 }, /* R18972 - ADCR_RETUNE_C15_1 */
- [18973] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18973 - ADCR_RETUNE_C15_0 */
- [18974] = { 0x00FF, 0x00FF, 0x0000 }, /* R18974 - ADCR_RETUNE_C16_1 */
- [18975] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18975 - ADCR_RETUNE_C16_0 */
- [18976] = { 0x00FF, 0x00FF, 0x0000 }, /* R18976 - ADCR_RETUNE_C17_1 */
- [18977] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18977 - ADCR_RETUNE_C17_0 */
- [18978] = { 0x00FF, 0x00FF, 0x0000 }, /* R18978 - ADCR_RETUNE_C18_1 */
- [18979] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18979 - ADCR_RETUNE_C18_0 */
- [18980] = { 0x00FF, 0x00FF, 0x0000 }, /* R18980 - ADCR_RETUNE_C19_1 */
- [18981] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18981 - ADCR_RETUNE_C19_0 */
- [18982] = { 0x00FF, 0x00FF, 0x0000 }, /* R18982 - ADCR_RETUNE_C20_1 */
- [18983] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18983 - ADCR_RETUNE_C20_0 */
- [18984] = { 0x00FF, 0x00FF, 0x0000 }, /* R18984 - ADCR_RETUNE_C21_1 */
- [18985] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18985 - ADCR_RETUNE_C21_0 */
- [18986] = { 0x00FF, 0x00FF, 0x0000 }, /* R18986 - ADCR_RETUNE_C22_1 */
- [18987] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18987 - ADCR_RETUNE_C22_0 */
- [18988] = { 0x00FF, 0x00FF, 0x0000 }, /* R18988 - ADCR_RETUNE_C23_1 */
- [18989] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18989 - ADCR_RETUNE_C23_0 */
- [18990] = { 0x00FF, 0x00FF, 0x0000 }, /* R18990 - ADCR_RETUNE_C24_1 */
- [18991] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18991 - ADCR_RETUNE_C24_0 */
- [18992] = { 0x00FF, 0x00FF, 0x0000 }, /* R18992 - ADCR_RETUNE_C25_1 */
- [18993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18993 - ADCR_RETUNE_C25_0 */
- [18994] = { 0x00FF, 0x00FF, 0x0000 }, /* R18994 - ADCR_RETUNE_C26_1 */
- [18995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18995 - ADCR_RETUNE_C26_0 */
- [18996] = { 0x00FF, 0x00FF, 0x0000 }, /* R18996 - ADCR_RETUNE_C27_1 */
- [18997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18997 - ADCR_RETUNE_C27_0 */
- [18998] = { 0x00FF, 0x00FF, 0x0000 }, /* R18998 - ADCR_RETUNE_C28_1 */
- [18999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R18999 - ADCR_RETUNE_C28_0 */
- [19000] = { 0x00FF, 0x00FF, 0x0000 }, /* R19000 - ADCR_RETUNE_C29_1 */
- [19001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19001 - ADCR_RETUNE_C29_0 */
- [19002] = { 0x00FF, 0x00FF, 0x0000 }, /* R19002 - ADCR_RETUNE_C30_1 */
- [19003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19003 - ADCR_RETUNE_C30_0 */
- [19004] = { 0x00FF, 0x00FF, 0x0000 }, /* R19004 - ADCR_RETUNE_C31_1 */
- [19005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19005 - ADCR_RETUNE_C31_0 */
- [19006] = { 0x00FF, 0x00FF, 0x0000 }, /* R19006 - ADCR_RETUNE_C32_1 */
- [19007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19007 - ADCR_RETUNE_C32_0 */
- [19456] = { 0x00FF, 0x00FF, 0x0000 }, /* R19456 - DACL_RETUNE_C1_1 */
- [19457] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19457 - DACL_RETUNE_C1_0 */
- [19458] = { 0x00FF, 0x00FF, 0x0000 }, /* R19458 - DACL_RETUNE_C2_1 */
- [19459] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19459 - DACL_RETUNE_C2_0 */
- [19460] = { 0x00FF, 0x00FF, 0x0000 }, /* R19460 - DACL_RETUNE_C3_1 */
- [19461] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19461 - DACL_RETUNE_C3_0 */
- [19462] = { 0x00FF, 0x00FF, 0x0000 }, /* R19462 - DACL_RETUNE_C4_1 */
- [19463] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19463 - DACL_RETUNE_C4_0 */
- [19464] = { 0x00FF, 0x00FF, 0x0000 }, /* R19464 - DACL_RETUNE_C5_1 */
- [19465] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19465 - DACL_RETUNE_C5_0 */
- [19466] = { 0x00FF, 0x00FF, 0x0000 }, /* R19466 - DACL_RETUNE_C6_1 */
- [19467] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19467 - DACL_RETUNE_C6_0 */
- [19468] = { 0x00FF, 0x00FF, 0x0000 }, /* R19468 - DACL_RETUNE_C7_1 */
- [19469] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19469 - DACL_RETUNE_C7_0 */
- [19470] = { 0x00FF, 0x00FF, 0x0000 }, /* R19470 - DACL_RETUNE_C8_1 */
- [19471] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19471 - DACL_RETUNE_C8_0 */
- [19472] = { 0x00FF, 0x00FF, 0x0000 }, /* R19472 - DACL_RETUNE_C9_1 */
- [19473] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19473 - DACL_RETUNE_C9_0 */
- [19474] = { 0x00FF, 0x00FF, 0x0000 }, /* R19474 - DACL_RETUNE_C10_1 */
- [19475] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19475 - DACL_RETUNE_C10_0 */
- [19476] = { 0x00FF, 0x00FF, 0x0000 }, /* R19476 - DACL_RETUNE_C11_1 */
- [19477] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19477 - DACL_RETUNE_C11_0 */
- [19478] = { 0x00FF, 0x00FF, 0x0000 }, /* R19478 - DACL_RETUNE_C12_1 */
- [19479] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19479 - DACL_RETUNE_C12_0 */
- [19480] = { 0x00FF, 0x00FF, 0x0000 }, /* R19480 - DACL_RETUNE_C13_1 */
- [19481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19481 - DACL_RETUNE_C13_0 */
- [19482] = { 0x00FF, 0x00FF, 0x0000 }, /* R19482 - DACL_RETUNE_C14_1 */
- [19483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19483 - DACL_RETUNE_C14_0 */
- [19484] = { 0x00FF, 0x00FF, 0x0000 }, /* R19484 - DACL_RETUNE_C15_1 */
- [19485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19485 - DACL_RETUNE_C15_0 */
- [19486] = { 0x00FF, 0x00FF, 0x0000 }, /* R19486 - DACL_RETUNE_C16_1 */
- [19487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19487 - DACL_RETUNE_C16_0 */
- [19488] = { 0x00FF, 0x00FF, 0x0000 }, /* R19488 - DACL_RETUNE_C17_1 */
- [19489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19489 - DACL_RETUNE_C17_0 */
- [19490] = { 0x00FF, 0x00FF, 0x0000 }, /* R19490 - DACL_RETUNE_C18_1 */
- [19491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19491 - DACL_RETUNE_C18_0 */
- [19492] = { 0x00FF, 0x00FF, 0x0000 }, /* R19492 - DACL_RETUNE_C19_1 */
- [19493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19493 - DACL_RETUNE_C19_0 */
- [19494] = { 0x00FF, 0x00FF, 0x0000 }, /* R19494 - DACL_RETUNE_C20_1 */
- [19495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19495 - DACL_RETUNE_C20_0 */
- [19496] = { 0x00FF, 0x00FF, 0x0000 }, /* R19496 - DACL_RETUNE_C21_1 */
- [19497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19497 - DACL_RETUNE_C21_0 */
- [19498] = { 0x00FF, 0x00FF, 0x0000 }, /* R19498 - DACL_RETUNE_C22_1 */
- [19499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19499 - DACL_RETUNE_C22_0 */
- [19500] = { 0x00FF, 0x00FF, 0x0000 }, /* R19500 - DACL_RETUNE_C23_1 */
- [19501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19501 - DACL_RETUNE_C23_0 */
- [19502] = { 0x00FF, 0x00FF, 0x0000 }, /* R19502 - DACL_RETUNE_C24_1 */
- [19503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19503 - DACL_RETUNE_C24_0 */
- [19504] = { 0x00FF, 0x00FF, 0x0000 }, /* R19504 - DACL_RETUNE_C25_1 */
- [19505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19505 - DACL_RETUNE_C25_0 */
- [19506] = { 0x00FF, 0x00FF, 0x0000 }, /* R19506 - DACL_RETUNE_C26_1 */
- [19507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19507 - DACL_RETUNE_C26_0 */
- [19508] = { 0x00FF, 0x00FF, 0x0000 }, /* R19508 - DACL_RETUNE_C27_1 */
- [19509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19509 - DACL_RETUNE_C27_0 */
- [19510] = { 0x00FF, 0x00FF, 0x0000 }, /* R19510 - DACL_RETUNE_C28_1 */
- [19511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19511 - DACL_RETUNE_C28_0 */
- [19512] = { 0x00FF, 0x00FF, 0x0000 }, /* R19512 - DACL_RETUNE_C29_1 */
- [19513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19513 - DACL_RETUNE_C29_0 */
- [19514] = { 0x00FF, 0x00FF, 0x0000 }, /* R19514 - DACL_RETUNE_C30_1 */
- [19515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19515 - DACL_RETUNE_C30_0 */
- [19516] = { 0x00FF, 0x00FF, 0x0000 }, /* R19516 - DACL_RETUNE_C31_1 */
- [19517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19517 - DACL_RETUNE_C31_0 */
- [19518] = { 0x00FF, 0x00FF, 0x0000 }, /* R19518 - DACL_RETUNE_C32_1 */
- [19519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19519 - DACL_RETUNE_C32_0 */
- [19968] = { 0x00FF, 0x00FF, 0x0000 }, /* R19968 - RETUNEDAC_PG2_1 */
- [19969] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19969 - RETUNEDAC_PG2_0 */
- [19970] = { 0x00FF, 0x00FF, 0x0000 }, /* R19970 - RETUNEDAC_PG_1 */
- [19971] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R19971 - RETUNEDAC_PG_0 */
- [20480] = { 0x00FF, 0x00FF, 0x0000 }, /* R20480 - DACR_RETUNE_C1_1 */
- [20481] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20481 - DACR_RETUNE_C1_0 */
- [20482] = { 0x00FF, 0x00FF, 0x0000 }, /* R20482 - DACR_RETUNE_C2_1 */
- [20483] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20483 - DACR_RETUNE_C2_0 */
- [20484] = { 0x00FF, 0x00FF, 0x0000 }, /* R20484 - DACR_RETUNE_C3_1 */
- [20485] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20485 - DACR_RETUNE_C3_0 */
- [20486] = { 0x00FF, 0x00FF, 0x0000 }, /* R20486 - DACR_RETUNE_C4_1 */
- [20487] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20487 - DACR_RETUNE_C4_0 */
- [20488] = { 0x00FF, 0x00FF, 0x0000 }, /* R20488 - DACR_RETUNE_C5_1 */
- [20489] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20489 - DACR_RETUNE_C5_0 */
- [20490] = { 0x00FF, 0x00FF, 0x0000 }, /* R20490 - DACR_RETUNE_C6_1 */
- [20491] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20491 - DACR_RETUNE_C6_0 */
- [20492] = { 0x00FF, 0x00FF, 0x0000 }, /* R20492 - DACR_RETUNE_C7_1 */
- [20493] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20493 - DACR_RETUNE_C7_0 */
- [20494] = { 0x00FF, 0x00FF, 0x0000 }, /* R20494 - DACR_RETUNE_C8_1 */
- [20495] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20495 - DACR_RETUNE_C8_0 */
- [20496] = { 0x00FF, 0x00FF, 0x0000 }, /* R20496 - DACR_RETUNE_C9_1 */
- [20497] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20497 - DACR_RETUNE_C9_0 */
- [20498] = { 0x00FF, 0x00FF, 0x0000 }, /* R20498 - DACR_RETUNE_C10_1 */
- [20499] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20499 - DACR_RETUNE_C10_0 */
- [20500] = { 0x00FF, 0x00FF, 0x0000 }, /* R20500 - DACR_RETUNE_C11_1 */
- [20501] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20501 - DACR_RETUNE_C11_0 */
- [20502] = { 0x00FF, 0x00FF, 0x0000 }, /* R20502 - DACR_RETUNE_C12_1 */
- [20503] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20503 - DACR_RETUNE_C12_0 */
- [20504] = { 0x00FF, 0x00FF, 0x0000 }, /* R20504 - DACR_RETUNE_C13_1 */
- [20505] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20505 - DACR_RETUNE_C13_0 */
- [20506] = { 0x00FF, 0x00FF, 0x0000 }, /* R20506 - DACR_RETUNE_C14_1 */
- [20507] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20507 - DACR_RETUNE_C14_0 */
- [20508] = { 0x00FF, 0x00FF, 0x0000 }, /* R20508 - DACR_RETUNE_C15_1 */
- [20509] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20509 - DACR_RETUNE_C15_0 */
- [20510] = { 0x00FF, 0x00FF, 0x0000 }, /* R20510 - DACR_RETUNE_C16_1 */
- [20511] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20511 - DACR_RETUNE_C16_0 */
- [20512] = { 0x00FF, 0x00FF, 0x0000 }, /* R20512 - DACR_RETUNE_C17_1 */
- [20513] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20513 - DACR_RETUNE_C17_0 */
- [20514] = { 0x00FF, 0x00FF, 0x0000 }, /* R20514 - DACR_RETUNE_C18_1 */
- [20515] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20515 - DACR_RETUNE_C18_0 */
- [20516] = { 0x00FF, 0x00FF, 0x0000 }, /* R20516 - DACR_RETUNE_C19_1 */
- [20517] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20517 - DACR_RETUNE_C19_0 */
- [20518] = { 0x00FF, 0x00FF, 0x0000 }, /* R20518 - DACR_RETUNE_C20_1 */
- [20519] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20519 - DACR_RETUNE_C20_0 */
- [20520] = { 0x00FF, 0x00FF, 0x0000 }, /* R20520 - DACR_RETUNE_C21_1 */
- [20521] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20521 - DACR_RETUNE_C21_0 */
- [20522] = { 0x00FF, 0x00FF, 0x0000 }, /* R20522 - DACR_RETUNE_C22_1 */
- [20523] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20523 - DACR_RETUNE_C22_0 */
- [20524] = { 0x00FF, 0x00FF, 0x0000 }, /* R20524 - DACR_RETUNE_C23_1 */
- [20525] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20525 - DACR_RETUNE_C23_0 */
- [20526] = { 0x00FF, 0x00FF, 0x0000 }, /* R20526 - DACR_RETUNE_C24_1 */
- [20527] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20527 - DACR_RETUNE_C24_0 */
- [20528] = { 0x00FF, 0x00FF, 0x0000 }, /* R20528 - DACR_RETUNE_C25_1 */
- [20529] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20529 - DACR_RETUNE_C25_0 */
- [20530] = { 0x00FF, 0x00FF, 0x0000 }, /* R20530 - DACR_RETUNE_C26_1 */
- [20531] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20531 - DACR_RETUNE_C26_0 */
- [20532] = { 0x00FF, 0x00FF, 0x0000 }, /* R20532 - DACR_RETUNE_C27_1 */
- [20533] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20533 - DACR_RETUNE_C27_0 */
- [20534] = { 0x00FF, 0x00FF, 0x0000 }, /* R20534 - DACR_RETUNE_C28_1 */
- [20535] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20535 - DACR_RETUNE_C28_0 */
- [20536] = { 0x00FF, 0x00FF, 0x0000 }, /* R20536 - DACR_RETUNE_C29_1 */
- [20537] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20537 - DACR_RETUNE_C29_0 */
- [20538] = { 0x00FF, 0x00FF, 0x0000 }, /* R20538 - DACR_RETUNE_C30_1 */
- [20539] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20539 - DACR_RETUNE_C30_0 */
- [20540] = { 0x00FF, 0x00FF, 0x0000 }, /* R20540 - DACR_RETUNE_C31_1 */
- [20541] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20541 - DACR_RETUNE_C31_0 */
- [20542] = { 0x00FF, 0x00FF, 0x0000 }, /* R20542 - DACR_RETUNE_C32_1 */
- [20543] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20543 - DACR_RETUNE_C32_0 */
- [20992] = { 0x00FF, 0x00FF, 0x0000 }, /* R20992 - VSS_XHD2_1 */
- [20993] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20993 - VSS_XHD2_0 */
- [20994] = { 0x00FF, 0x00FF, 0x0000 }, /* R20994 - VSS_XHD3_1 */
- [20995] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20995 - VSS_XHD3_0 */
- [20996] = { 0x00FF, 0x00FF, 0x0000 }, /* R20996 - VSS_XHN1_1 */
- [20997] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20997 - VSS_XHN1_0 */
- [20998] = { 0x00FF, 0x00FF, 0x0000 }, /* R20998 - VSS_XHN2_1 */
- [20999] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R20999 - VSS_XHN2_0 */
- [21000] = { 0x00FF, 0x00FF, 0x0000 }, /* R21000 - VSS_XHN3_1 */
- [21001] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21001 - VSS_XHN3_0 */
- [21002] = { 0x00FF, 0x00FF, 0x0000 }, /* R21002 - VSS_XLA_1 */
- [21003] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21003 - VSS_XLA_0 */
- [21004] = { 0x00FF, 0x00FF, 0x0000 }, /* R21004 - VSS_XLB_1 */
- [21005] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21005 - VSS_XLB_0 */
- [21006] = { 0x00FF, 0x00FF, 0x0000 }, /* R21006 - VSS_XLG_1 */
- [21007] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21007 - VSS_XLG_0 */
- [21008] = { 0x00FF, 0x00FF, 0x0000 }, /* R21008 - VSS_PG2_1 */
- [21009] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21009 - VSS_PG2_0 */
- [21010] = { 0x00FF, 0x00FF, 0x0000 }, /* R21010 - VSS_PG_1 */
- [21011] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21011 - VSS_PG_0 */
- [21012] = { 0x00FF, 0x00FF, 0x0000 }, /* R21012 - VSS_XTD1_1 */
- [21013] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21013 - VSS_XTD1_0 */
- [21014] = { 0x00FF, 0x00FF, 0x0000 }, /* R21014 - VSS_XTD2_1 */
- [21015] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21015 - VSS_XTD2_0 */
- [21016] = { 0x00FF, 0x00FF, 0x0000 }, /* R21016 - VSS_XTD3_1 */
- [21017] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21017 - VSS_XTD3_0 */
- [21018] = { 0x00FF, 0x00FF, 0x0000 }, /* R21018 - VSS_XTD4_1 */
- [21019] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21019 - VSS_XTD4_0 */
- [21020] = { 0x00FF, 0x00FF, 0x0000 }, /* R21020 - VSS_XTD5_1 */
- [21021] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21021 - VSS_XTD5_0 */
- [21022] = { 0x00FF, 0x00FF, 0x0000 }, /* R21022 - VSS_XTD6_1 */
- [21023] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21023 - VSS_XTD6_0 */
- [21024] = { 0x00FF, 0x00FF, 0x0000 }, /* R21024 - VSS_XTD7_1 */
- [21025] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21025 - VSS_XTD7_0 */
- [21026] = { 0x00FF, 0x00FF, 0x0000 }, /* R21026 - VSS_XTD8_1 */
- [21027] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21027 - VSS_XTD8_0 */
- [21028] = { 0x00FF, 0x00FF, 0x0000 }, /* R21028 - VSS_XTD9_1 */
- [21029] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21029 - VSS_XTD9_0 */
- [21030] = { 0x00FF, 0x00FF, 0x0000 }, /* R21030 - VSS_XTD10_1 */
- [21031] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21031 - VSS_XTD10_0 */
- [21032] = { 0x00FF, 0x00FF, 0x0000 }, /* R21032 - VSS_XTD11_1 */
- [21033] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21033 - VSS_XTD11_0 */
- [21034] = { 0x00FF, 0x00FF, 0x0000 }, /* R21034 - VSS_XTD12_1 */
- [21035] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21035 - VSS_XTD12_0 */
- [21036] = { 0x00FF, 0x00FF, 0x0000 }, /* R21036 - VSS_XTD13_1 */
- [21037] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21037 - VSS_XTD13_0 */
- [21038] = { 0x00FF, 0x00FF, 0x0000 }, /* R21038 - VSS_XTD14_1 */
- [21039] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21039 - VSS_XTD14_0 */
- [21040] = { 0x00FF, 0x00FF, 0x0000 }, /* R21040 - VSS_XTD15_1 */
- [21041] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21041 - VSS_XTD15_0 */
- [21042] = { 0x00FF, 0x00FF, 0x0000 }, /* R21042 - VSS_XTD16_1 */
- [21043] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21043 - VSS_XTD16_0 */
- [21044] = { 0x00FF, 0x00FF, 0x0000 }, /* R21044 - VSS_XTD17_1 */
- [21045] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21045 - VSS_XTD17_0 */
- [21046] = { 0x00FF, 0x00FF, 0x0000 }, /* R21046 - VSS_XTD18_1 */
- [21047] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21047 - VSS_XTD18_0 */
- [21048] = { 0x00FF, 0x00FF, 0x0000 }, /* R21048 - VSS_XTD19_1 */
- [21049] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21049 - VSS_XTD19_0 */
- [21050] = { 0x00FF, 0x00FF, 0x0000 }, /* R21050 - VSS_XTD20_1 */
- [21051] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21051 - VSS_XTD20_0 */
- [21052] = { 0x00FF, 0x00FF, 0x0000 }, /* R21052 - VSS_XTD21_1 */
- [21053] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21053 - VSS_XTD21_0 */
- [21054] = { 0x00FF, 0x00FF, 0x0000 }, /* R21054 - VSS_XTD22_1 */
- [21055] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21055 - VSS_XTD22_0 */
- [21056] = { 0x00FF, 0x00FF, 0x0000 }, /* R21056 - VSS_XTD23_1 */
- [21057] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21057 - VSS_XTD23_0 */
- [21058] = { 0x00FF, 0x00FF, 0x0000 }, /* R21058 - VSS_XTD24_1 */
- [21059] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21059 - VSS_XTD24_0 */
- [21060] = { 0x00FF, 0x00FF, 0x0000 }, /* R21060 - VSS_XTD25_1 */
- [21061] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21061 - VSS_XTD25_0 */
- [21062] = { 0x00FF, 0x00FF, 0x0000 }, /* R21062 - VSS_XTD26_1 */
- [21063] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21063 - VSS_XTD26_0 */
- [21064] = { 0x00FF, 0x00FF, 0x0000 }, /* R21064 - VSS_XTD27_1 */
- [21065] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21065 - VSS_XTD27_0 */
- [21066] = { 0x00FF, 0x00FF, 0x0000 }, /* R21066 - VSS_XTD28_1 */
- [21067] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21067 - VSS_XTD28_0 */
- [21068] = { 0x00FF, 0x00FF, 0x0000 }, /* R21068 - VSS_XTD29_1 */
- [21069] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21069 - VSS_XTD29_0 */
- [21070] = { 0x00FF, 0x00FF, 0x0000 }, /* R21070 - VSS_XTD30_1 */
- [21071] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21071 - VSS_XTD30_0 */
- [21072] = { 0x00FF, 0x00FF, 0x0000 }, /* R21072 - VSS_XTD31_1 */
- [21073] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21073 - VSS_XTD31_0 */
- [21074] = { 0x00FF, 0x00FF, 0x0000 }, /* R21074 - VSS_XTD32_1 */
- [21075] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21075 - VSS_XTD32_0 */
- [21076] = { 0x00FF, 0x00FF, 0x0000 }, /* R21076 - VSS_XTS1_1 */
- [21077] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21077 - VSS_XTS1_0 */
- [21078] = { 0x00FF, 0x00FF, 0x0000 }, /* R21078 - VSS_XTS2_1 */
- [21079] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21079 - VSS_XTS2_0 */
- [21080] = { 0x00FF, 0x00FF, 0x0000 }, /* R21080 - VSS_XTS3_1 */
- [21081] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21081 - VSS_XTS3_0 */
- [21082] = { 0x00FF, 0x00FF, 0x0000 }, /* R21082 - VSS_XTS4_1 */
- [21083] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21083 - VSS_XTS4_0 */
- [21084] = { 0x00FF, 0x00FF, 0x0000 }, /* R21084 - VSS_XTS5_1 */
- [21085] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21085 - VSS_XTS5_0 */
- [21086] = { 0x00FF, 0x00FF, 0x0000 }, /* R21086 - VSS_XTS6_1 */
- [21087] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21087 - VSS_XTS6_0 */
- [21088] = { 0x00FF, 0x00FF, 0x0000 }, /* R21088 - VSS_XTS7_1 */
- [21089] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21089 - VSS_XTS7_0 */
- [21090] = { 0x00FF, 0x00FF, 0x0000 }, /* R21090 - VSS_XTS8_1 */
- [21091] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21091 - VSS_XTS8_0 */
- [21092] = { 0x00FF, 0x00FF, 0x0000 }, /* R21092 - VSS_XTS9_1 */
- [21093] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21093 - VSS_XTS9_0 */
- [21094] = { 0x00FF, 0x00FF, 0x0000 }, /* R21094 - VSS_XTS10_1 */
- [21095] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21095 - VSS_XTS10_0 */
- [21096] = { 0x00FF, 0x00FF, 0x0000 }, /* R21096 - VSS_XTS11_1 */
- [21097] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21097 - VSS_XTS11_0 */
- [21098] = { 0x00FF, 0x00FF, 0x0000 }, /* R21098 - VSS_XTS12_1 */
- [21099] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21099 - VSS_XTS12_0 */
- [21100] = { 0x00FF, 0x00FF, 0x0000 }, /* R21100 - VSS_XTS13_1 */
- [21101] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21101 - VSS_XTS13_0 */
- [21102] = { 0x00FF, 0x00FF, 0x0000 }, /* R21102 - VSS_XTS14_1 */
- [21103] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21103 - VSS_XTS14_0 */
- [21104] = { 0x00FF, 0x00FF, 0x0000 }, /* R21104 - VSS_XTS15_1 */
- [21105] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21105 - VSS_XTS15_0 */
- [21106] = { 0x00FF, 0x00FF, 0x0000 }, /* R21106 - VSS_XTS16_1 */
- [21107] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21107 - VSS_XTS16_0 */
- [21108] = { 0x00FF, 0x00FF, 0x0000 }, /* R21108 - VSS_XTS17_1 */
- [21109] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21109 - VSS_XTS17_0 */
- [21110] = { 0x00FF, 0x00FF, 0x0000 }, /* R21110 - VSS_XTS18_1 */
- [21111] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21111 - VSS_XTS18_0 */
- [21112] = { 0x00FF, 0x00FF, 0x0000 }, /* R21112 - VSS_XTS19_1 */
- [21113] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21113 - VSS_XTS19_0 */
- [21114] = { 0x00FF, 0x00FF, 0x0000 }, /* R21114 - VSS_XTS20_1 */
- [21115] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21115 - VSS_XTS20_0 */
- [21116] = { 0x00FF, 0x00FF, 0x0000 }, /* R21116 - VSS_XTS21_1 */
- [21117] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21117 - VSS_XTS21_0 */
- [21118] = { 0x00FF, 0x00FF, 0x0000 }, /* R21118 - VSS_XTS22_1 */
- [21119] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21119 - VSS_XTS22_0 */
- [21120] = { 0x00FF, 0x00FF, 0x0000 }, /* R21120 - VSS_XTS23_1 */
- [21121] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21121 - VSS_XTS23_0 */
- [21122] = { 0x00FF, 0x00FF, 0x0000 }, /* R21122 - VSS_XTS24_1 */
- [21123] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21123 - VSS_XTS24_0 */
- [21124] = { 0x00FF, 0x00FF, 0x0000 }, /* R21124 - VSS_XTS25_1 */
- [21125] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21125 - VSS_XTS25_0 */
- [21126] = { 0x00FF, 0x00FF, 0x0000 }, /* R21126 - VSS_XTS26_1 */
- [21127] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21127 - VSS_XTS26_0 */
- [21128] = { 0x00FF, 0x00FF, 0x0000 }, /* R21128 - VSS_XTS27_1 */
- [21129] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21129 - VSS_XTS27_0 */
- [21130] = { 0x00FF, 0x00FF, 0x0000 }, /* R21130 - VSS_XTS28_1 */
- [21131] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21131 - VSS_XTS28_0 */
- [21132] = { 0x00FF, 0x00FF, 0x0000 }, /* R21132 - VSS_XTS29_1 */
- [21133] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21133 - VSS_XTS29_0 */
- [21134] = { 0x00FF, 0x00FF, 0x0000 }, /* R21134 - VSS_XTS30_1 */
- [21135] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21135 - VSS_XTS30_0 */
- [21136] = { 0x00FF, 0x00FF, 0x0000 }, /* R21136 - VSS_XTS31_1 */
- [21137] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21137 - VSS_XTS31_0 */
- [21138] = { 0x00FF, 0x00FF, 0x0000 }, /* R21138 - VSS_XTS32_1 */
- [21139] = { 0xFFFF, 0xFFFF, 0x0000 }, /* R21139 - VSS_XTS32_0 */
+ { 30, 0x005E }, /* R30 - Clocking 3 */
+ { 31, 0x0000 }, /* R31 - Input mixer control (1) */
+ { 32, 0x0145 }, /* R32 - Left input mixer volume */
+ { 33, 0x0145 }, /* R33 - Right input mixer volume */
+ { 34, 0x0009 }, /* R34 - Input mixer control (2) */
+ { 35, 0x0003 }, /* R35 - Input bias control */
+ { 37, 0x0008 }, /* R37 - Left input PGA control */
+ { 38, 0x0008 }, /* R38 - Right input PGA control */
+
+ { 40, 0x0000 }, /* R40 - SPKOUTL volume */
+ { 41, 0x0000 }, /* R41 - SPKOUTR volume */
+
+ { 51, 0x0003 }, /* R51 - Class D Control 2 */
+
+ { 56, 0x0506 }, /* R56 - Clocking 4 */
+ { 57, 0x0000 }, /* R57 - DAC DSP Mixing (1) */
+ { 58, 0x0000 }, /* R58 - DAC DSP Mixing (2) */
+
+ { 60, 0x0300 }, /* R60 - DC Servo 0 */
+ { 61, 0x0300 }, /* R61 - DC Servo 1 */
+
+ { 64, 0x0810 }, /* R64 - DC Servo 4 */
+
+ { 68, 0x001B }, /* R68 - Analogue PGA Bias */
+ { 69, 0x0000 }, /* R69 - Analogue HP 0 */
+
+ { 71, 0x01FB }, /* R71 - Analogue HP 2 */
+ { 72, 0x0000 }, /* R72 - Charge Pump 1 */
+
+ { 82, 0x0004 }, /* R82 - Charge Pump B */
+
+ { 87, 0x0000 }, /* R87 - Write Sequencer Control 1 */
+
+ { 90, 0x0000 }, /* R90 - Write Sequencer Control 2 */
+
+ { 93, 0x0000 }, /* R93 - Write Sequencer Control 3 */
+ { 94, 0x0000 }, /* R94 - Control Interface */
+
+ { 99, 0x0000 }, /* R99 - Mixer Enables */
+ { 100, 0x0000 }, /* R100 - Headphone Mixer (1) */
+ { 101, 0x0000 }, /* R101 - Headphone Mixer (2) */
+ { 102, 0x013F }, /* R102 - Headphone Mixer (3) */
+ { 103, 0x013F }, /* R103 - Headphone Mixer (4) */
+
+ { 105, 0x0000 }, /* R105 - Speaker Mixer (1) */
+ { 106, 0x0000 }, /* R106 - Speaker Mixer (2) */
+ { 107, 0x013F }, /* R107 - Speaker Mixer (3) */
+ { 108, 0x013F }, /* R108 - Speaker Mixer (4) */
+ { 109, 0x0003 }, /* R109 - Speaker Mixer (5) */
+ { 110, 0x0002 }, /* R110 - Beep Generator (1) */
+
+ { 115, 0x0006 }, /* R115 - Oscillator Trim (3) */
+ { 116, 0x0026 }, /* R116 - Oscillator Trim (4) */
+
+ { 119, 0x0000 }, /* R119 - Oscillator Trim (7) */
+
+ { 124, 0x0011 }, /* R124 - Analogue Clocking1 */
+ { 125, 0x004B }, /* R125 - Analogue Clocking2 */
+ { 126, 0x000D }, /* R126 - Analogue Clocking3 */
+ { 127, 0x0000 }, /* R127 - PLL Software Reset */
+
+ { 131, 0x0000 }, /* R131 - PLL 4 */
+
+ { 136, 0x0067 }, /* R136 - PLL 9 */
+ { 137, 0x001C }, /* R137 - PLL 10 */
+ { 138, 0x0071 }, /* R138 - PLL 11 */
+ { 139, 0x00C7 }, /* R139 - PLL 12 */
+ { 140, 0x0067 }, /* R140 - PLL 13 */
+ { 141, 0x0048 }, /* R141 - PLL 14 */
+ { 142, 0x0022 }, /* R142 - PLL 15 */
+ { 143, 0x0097 }, /* R143 - PLL 16 */
+
+ { 155, 0x000C }, /* R155 - FLL Control (1) */
+ { 156, 0x0039 }, /* R156 - FLL Control (2) */
+ { 157, 0x0180 }, /* R157 - FLL Control (3) */
+
+ { 159, 0x0032 }, /* R159 - FLL Control (5) */
+ { 160, 0x0018 }, /* R160 - FLL Control (6) */
+ { 161, 0x007D }, /* R161 - FLL Control (7) */
+ { 162, 0x0008 }, /* R162 - FLL Control (8) */
+
+ { 252, 0x0005 }, /* R252 - General test 1 */
+
+ { 256, 0x0000 }, /* R256 - DF1 */
+ { 257, 0x0000 }, /* R257 - DF2 */
+ { 258, 0x0000 }, /* R258 - DF3 */
+ { 259, 0x0000 }, /* R259 - DF4 */
+ { 260, 0x0000 }, /* R260 - DF5 */
+ { 261, 0x0000 }, /* R261 - DF6 */
+ { 262, 0x0000 }, /* R262 - DF7 */
+
+ { 264, 0x0000 }, /* R264 - LHPF1 */
+ { 265, 0x0000 }, /* R265 - LHPF2 */
+
+ { 268, 0x0000 }, /* R268 - THREED1 */
+ { 269, 0x0000 }, /* R269 - THREED2 */
+ { 270, 0x0000 }, /* R270 - THREED3 */
+ { 271, 0x0000 }, /* R271 - THREED4 */
+
+ { 276, 0x000C }, /* R276 - DRC 1 */
+ { 277, 0x0925 }, /* R277 - DRC 2 */
+ { 278, 0x0000 }, /* R278 - DRC 3 */
+ { 279, 0x0000 }, /* R279 - DRC 4 */
+ { 280, 0x0000 }, /* R280 - DRC 5 */
+
+ { 285, 0x0000 }, /* R285 - Tloopback */
+
+ { 335, 0x0004 }, /* R335 - EQ1 */
+ { 336, 0x6318 }, /* R336 - EQ2 */
+ { 337, 0x6300 }, /* R337 - EQ3 */
+ { 338, 0x0FCA }, /* R338 - EQ4 */
+ { 339, 0x0400 }, /* R339 - EQ5 */
+ { 340, 0x00D8 }, /* R340 - EQ6 */
+ { 341, 0x1EB5 }, /* R341 - EQ7 */
+ { 342, 0xF145 }, /* R342 - EQ8 */
+ { 343, 0x0B75 }, /* R343 - EQ9 */
+ { 344, 0x01C5 }, /* R344 - EQ10 */
+ { 345, 0x1C58 }, /* R345 - EQ11 */
+ { 346, 0xF373 }, /* R346 - EQ12 */
+ { 347, 0x0A54 }, /* R347 - EQ13 */
+ { 348, 0x0558 }, /* R348 - EQ14 */
+ { 349, 0x168E }, /* R349 - EQ15 */
+ { 350, 0xF829 }, /* R350 - EQ16 */
+ { 351, 0x07AD }, /* R351 - EQ17 */
+ { 352, 0x1103 }, /* R352 - EQ18 */
+ { 353, 0x0564 }, /* R353 - EQ19 */
+ { 354, 0x0559 }, /* R354 - EQ20 */
+ { 355, 0x4000 }, /* R355 - EQ21 */
+ { 356, 0x6318 }, /* R356 - EQ22 */
+ { 357, 0x6300 }, /* R357 - EQ23 */
+ { 358, 0x0FCA }, /* R358 - EQ24 */
+ { 359, 0x0400 }, /* R359 - EQ25 */
+ { 360, 0x00D8 }, /* R360 - EQ26 */
+ { 361, 0x1EB5 }, /* R361 - EQ27 */
+ { 362, 0xF145 }, /* R362 - EQ28 */
+ { 363, 0x0B75 }, /* R363 - EQ29 */
+ { 364, 0x01C5 }, /* R364 - EQ30 */
+ { 365, 0x1C58 }, /* R365 - EQ31 */
+ { 366, 0xF373 }, /* R366 - EQ32 */
+ { 367, 0x0A54 }, /* R367 - EQ33 */
+ { 368, 0x0558 }, /* R368 - EQ34 */
+ { 369, 0x168E }, /* R369 - EQ35 */
+ { 370, 0xF829 }, /* R370 - EQ36 */
+ { 371, 0x07AD }, /* R371 - EQ37 */
+ { 372, 0x1103 }, /* R372 - EQ38 */
+ { 373, 0x0564 }, /* R373 - EQ39 */
+ { 374, 0x0559 }, /* R374 - EQ40 */
+ { 375, 0x4000 }, /* R375 - EQ41 */
+
+ { 513, 0x0000 }, /* R513 - GPIO 2 */
+ { 514, 0x0000 }, /* R514 - GPIO 3 */
+
+ { 516, 0x8100 }, /* R516 - GPIO 5 */
+ { 517, 0x8100 }, /* R517 - GPIO 6 */
+
+ { 568, 0x0030 }, /* R568 - Interrupt Status 1 Mask */
+ { 569, 0xFFED }, /* R569 - Interrupt Status 2 Mask */
+
+ { 576, 0x0000 }, /* R576 - Interrupt Control */
+
+ { 584, 0x002D }, /* R584 - IRQ Debounce */
+
+ { 586, 0x0000 }, /* R586 - MICINT Source Pol */
+
+ { 768, 0x1C00 }, /* R768 - DSP2 Power Management */
+
+ { 8192, 0x0000 }, /* R8192 - DSP2 Instruction RAM 0 */
+
+ { 9216, 0x0030 }, /* R9216 - DSP2 Address RAM 2 */
+ { 9217, 0x0000 }, /* R9217 - DSP2 Address RAM 1 */
+ { 9218, 0x0000 }, /* R9218 - DSP2 Address RAM 0 */
+
+ { 12288, 0x0000 }, /* R12288 - DSP2 Data1 RAM 1 */
+ { 12289, 0x0000 }, /* R12289 - DSP2 Data1 RAM 0 */
+
+ { 13312, 0x0000 }, /* R13312 - DSP2 Data2 RAM 1 */
+ { 13313, 0x0000 }, /* R13313 - DSP2 Data2 RAM 0 */
+
+ { 14336, 0x0000 }, /* R14336 - DSP2 Data3 RAM 1 */
+ { 14337, 0x0000 }, /* R14337 - DSP2 Data3 RAM 0 */
+
+ { 15360, 0x000A }, /* R15360 - DSP2 Coeff RAM 0 */
+
+ { 16384, 0x0000 }, /* R16384 - RETUNEADC_SHARED_COEFF_1 */
+ { 16385, 0x0000 }, /* R16385 - RETUNEADC_SHARED_COEFF_0 */
+ { 16386, 0x0000 }, /* R16386 - RETUNEDAC_SHARED_COEFF_1 */
+ { 16387, 0x0000 }, /* R16387 - RETUNEDAC_SHARED_COEFF_0 */
+ { 16388, 0x0000 }, /* R16388 - SOUNDSTAGE_ENABLES_1 */
+ { 16389, 0x0000 }, /* R16389 - SOUNDSTAGE_ENABLES_0 */
+
+ { 16896, 0x0002 }, /* R16896 - HDBASS_AI_1 */
+ { 16897, 0xBD12 }, /* R16897 - HDBASS_AI_0 */
+ { 16898, 0x007C }, /* R16898 - HDBASS_AR_1 */
+ { 16899, 0x586C }, /* R16899 - HDBASS_AR_0 */
+ { 16900, 0x0053 }, /* R16900 - HDBASS_B_1 */
+ { 16901, 0x8121 }, /* R16901 - HDBASS_B_0 */
+ { 16902, 0x003F }, /* R16902 - HDBASS_K_1 */
+ { 16903, 0x8BD8 }, /* R16903 - HDBASS_K_0 */
+ { 16904, 0x0032 }, /* R16904 - HDBASS_N1_1 */
+ { 16905, 0xF52D }, /* R16905 - HDBASS_N1_0 */
+ { 16906, 0x0065 }, /* R16906 - HDBASS_N2_1 */
+ { 16907, 0xAC8C }, /* R16907 - HDBASS_N2_0 */
+ { 16908, 0x006B }, /* R16908 - HDBASS_N3_1 */
+ { 16909, 0xE087 }, /* R16909 - HDBASS_N3_0 */
+ { 16910, 0x0072 }, /* R16910 - HDBASS_N4_1 */
+ { 16911, 0x1483 }, /* R16911 - HDBASS_N4_0 */
+ { 16912, 0x0072 }, /* R16912 - HDBASS_N5_1 */
+ { 16913, 0x1483 }, /* R16913 - HDBASS_N5_0 */
+ { 16914, 0x0043 }, /* R16914 - HDBASS_X1_1 */
+ { 16915, 0x3525 }, /* R16915 - HDBASS_X1_0 */
+ { 16916, 0x0006 }, /* R16916 - HDBASS_X2_1 */
+ { 16917, 0x6A4A }, /* R16917 - HDBASS_X2_0 */
+ { 16918, 0x0043 }, /* R16918 - HDBASS_X3_1 */
+ { 16919, 0x6079 }, /* R16919 - HDBASS_X3_0 */
+ { 16920, 0x0008 }, /* R16920 - HDBASS_ATK_1 */
+ { 16921, 0x0000 }, /* R16921 - HDBASS_ATK_0 */
+ { 16922, 0x0001 }, /* R16922 - HDBASS_DCY_1 */
+ { 16923, 0x0000 }, /* R16923 - HDBASS_DCY_0 */
+ { 16924, 0x0059 }, /* R16924 - HDBASS_PG_1 */
+ { 16925, 0x999A }, /* R16925 - HDBASS_PG_0 */
+
+ { 17048, 0x0083 }, /* R17408 - HPF_C_1 */
+ { 17049, 0x98AD }, /* R17409 - HPF_C_0 */
+
+ { 17920, 0x007F }, /* R17920 - ADCL_RETUNE_C1_1 */
+ { 17921, 0xFFFF }, /* R17921 - ADCL_RETUNE_C1_0 */
+ { 17922, 0x0000 }, /* R17922 - ADCL_RETUNE_C2_1 */
+ { 17923, 0x0000 }, /* R17923 - ADCL_RETUNE_C2_0 */
+ { 17924, 0x0000 }, /* R17924 - ADCL_RETUNE_C3_1 */
+ { 17925, 0x0000 }, /* R17925 - ADCL_RETUNE_C3_0 */
+ { 17926, 0x0000 }, /* R17926 - ADCL_RETUNE_C4_1 */
+ { 17927, 0x0000 }, /* R17927 - ADCL_RETUNE_C4_0 */
+ { 17928, 0x0000 }, /* R17928 - ADCL_RETUNE_C5_1 */
+ { 17929, 0x0000 }, /* R17929 - ADCL_RETUNE_C5_0 */
+ { 17930, 0x0000 }, /* R17930 - ADCL_RETUNE_C6_1 */
+ { 17931, 0x0000 }, /* R17931 - ADCL_RETUNE_C6_0 */
+ { 17932, 0x0000 }, /* R17932 - ADCL_RETUNE_C7_1 */
+ { 17933, 0x0000 }, /* R17933 - ADCL_RETUNE_C7_0 */
+ { 17934, 0x0000 }, /* R17934 - ADCL_RETUNE_C8_1 */
+ { 17935, 0x0000 }, /* R17935 - ADCL_RETUNE_C8_0 */
+ { 17936, 0x0000 }, /* R17936 - ADCL_RETUNE_C9_1 */
+ { 17937, 0x0000 }, /* R17937 - ADCL_RETUNE_C9_0 */
+ { 17938, 0x0000 }, /* R17938 - ADCL_RETUNE_C10_1 */
+ { 17939, 0x0000 }, /* R17939 - ADCL_RETUNE_C10_0 */
+ { 17940, 0x0000 }, /* R17940 - ADCL_RETUNE_C11_1 */
+ { 17941, 0x0000 }, /* R17941 - ADCL_RETUNE_C11_0 */
+ { 17942, 0x0000 }, /* R17942 - ADCL_RETUNE_C12_1 */
+ { 17943, 0x0000 }, /* R17943 - ADCL_RETUNE_C12_0 */
+ { 17944, 0x0000 }, /* R17944 - ADCL_RETUNE_C13_1 */
+ { 17945, 0x0000 }, /* R17945 - ADCL_RETUNE_C13_0 */
+ { 17946, 0x0000 }, /* R17946 - ADCL_RETUNE_C14_1 */
+ { 17947, 0x0000 }, /* R17947 - ADCL_RETUNE_C14_0 */
+ { 17948, 0x0000 }, /* R17948 - ADCL_RETUNE_C15_1 */
+ { 17949, 0x0000 }, /* R17949 - ADCL_RETUNE_C15_0 */
+ { 17950, 0x0000 }, /* R17950 - ADCL_RETUNE_C16_1 */
+ { 17951, 0x0000 }, /* R17951 - ADCL_RETUNE_C16_0 */
+ { 17952, 0x0000 }, /* R17952 - ADCL_RETUNE_C17_1 */
+ { 17953, 0x0000 }, /* R17953 - ADCL_RETUNE_C17_0 */
+ { 17954, 0x0000 }, /* R17954 - ADCL_RETUNE_C18_1 */
+ { 17955, 0x0000 }, /* R17955 - ADCL_RETUNE_C18_0 */
+ { 17956, 0x0000 }, /* R17956 - ADCL_RETUNE_C19_1 */
+ { 17957, 0x0000 }, /* R17957 - ADCL_RETUNE_C19_0 */
+ { 17958, 0x0000 }, /* R17958 - ADCL_RETUNE_C20_1 */
+ { 17959, 0x0000 }, /* R17959 - ADCL_RETUNE_C20_0 */
+ { 17960, 0x0000 }, /* R17960 - ADCL_RETUNE_C21_1 */
+ { 17961, 0x0000 }, /* R17961 - ADCL_RETUNE_C21_0 */
+ { 17962, 0x0000 }, /* R17962 - ADCL_RETUNE_C22_1 */
+ { 17963, 0x0000 }, /* R17963 - ADCL_RETUNE_C22_0 */
+ { 17964, 0x0000 }, /* R17964 - ADCL_RETUNE_C23_1 */
+ { 17965, 0x0000 }, /* R17965 - ADCL_RETUNE_C23_0 */
+ { 17966, 0x0000 }, /* R17966 - ADCL_RETUNE_C24_1 */
+ { 17967, 0x0000 }, /* R17967 - ADCL_RETUNE_C24_0 */
+ { 17968, 0x0000 }, /* R17968 - ADCL_RETUNE_C25_1 */
+ { 17969, 0x0000 }, /* R17969 - ADCL_RETUNE_C25_0 */
+ { 17970, 0x0000 }, /* R17970 - ADCL_RETUNE_C26_1 */
+ { 17971, 0x0000 }, /* R17971 - ADCL_RETUNE_C26_0 */
+ { 17972, 0x0000 }, /* R17972 - ADCL_RETUNE_C27_1 */
+ { 17973, 0x0000 }, /* R17973 - ADCL_RETUNE_C27_0 */
+ { 17974, 0x0000 }, /* R17974 - ADCL_RETUNE_C28_1 */
+ { 17975, 0x0000 }, /* R17975 - ADCL_RETUNE_C28_0 */
+ { 17976, 0x0000 }, /* R17976 - ADCL_RETUNE_C29_1 */
+ { 17977, 0x0000 }, /* R17977 - ADCL_RETUNE_C29_0 */
+ { 17978, 0x0000 }, /* R17978 - ADCL_RETUNE_C30_1 */
+ { 17979, 0x0000 }, /* R17979 - ADCL_RETUNE_C30_0 */
+ { 17980, 0x0000 }, /* R17980 - ADCL_RETUNE_C31_1 */
+ { 17981, 0x0000 }, /* R17981 - ADCL_RETUNE_C31_0 */
+ { 17982, 0x0000 }, /* R17982 - ADCL_RETUNE_C32_1 */
+ { 17983, 0x0000 }, /* R17983 - ADCL_RETUNE_C32_0 */
+
+ { 18432, 0x0020 }, /* R18432 - RETUNEADC_PG2_1 */
+ { 18433, 0x0000 }, /* R18433 - RETUNEADC_PG2_0 */
+ { 18434, 0x0040 }, /* R18434 - RETUNEADC_PG_1 */
+ { 18435, 0x0000 }, /* R18435 - RETUNEADC_PG_0 */
+
+ { 18944, 0x007F }, /* R18944 - ADCR_RETUNE_C1_1 */
+ { 18945, 0xFFFF }, /* R18945 - ADCR_RETUNE_C1_0 */
+ { 18946, 0x0000 }, /* R18946 - ADCR_RETUNE_C2_1 */
+ { 18947, 0x0000 }, /* R18947 - ADCR_RETUNE_C2_0 */
+ { 18948, 0x0000 }, /* R18948 - ADCR_RETUNE_C3_1 */
+ { 18949, 0x0000 }, /* R18949 - ADCR_RETUNE_C3_0 */
+ { 18950, 0x0000 }, /* R18950 - ADCR_RETUNE_C4_1 */
+ { 18951, 0x0000 }, /* R18951 - ADCR_RETUNE_C4_0 */
+ { 18952, 0x0000 }, /* R18952 - ADCR_RETUNE_C5_1 */
+ { 18953, 0x0000 }, /* R18953 - ADCR_RETUNE_C5_0 */
+ { 18954, 0x0000 }, /* R18954 - ADCR_RETUNE_C6_1 */
+ { 18955, 0x0000 }, /* R18955 - ADCR_RETUNE_C6_0 */
+ { 18956, 0x0000 }, /* R18956 - ADCR_RETUNE_C7_1 */
+ { 18957, 0x0000 }, /* R18957 - ADCR_RETUNE_C7_0 */
+ { 18958, 0x0000 }, /* R18958 - ADCR_RETUNE_C8_1 */
+ { 18959, 0x0000 }, /* R18959 - ADCR_RETUNE_C8_0 */
+ { 18960, 0x0000 }, /* R18960 - ADCR_RETUNE_C9_1 */
+ { 18961, 0x0000 }, /* R18961 - ADCR_RETUNE_C9_0 */
+ { 18962, 0x0000 }, /* R18962 - ADCR_RETUNE_C10_1 */
+ { 18963, 0x0000 }, /* R18963 - ADCR_RETUNE_C10_0 */
+ { 18964, 0x0000 }, /* R18964 - ADCR_RETUNE_C11_1 */
+ { 18965, 0x0000 }, /* R18965 - ADCR_RETUNE_C11_0 */
+ { 18966, 0x0000 }, /* R18966 - ADCR_RETUNE_C12_1 */
+ { 18967, 0x0000 }, /* R18967 - ADCR_RETUNE_C12_0 */
+ { 18968, 0x0000 }, /* R18968 - ADCR_RETUNE_C13_1 */
+ { 18969, 0x0000 }, /* R18969 - ADCR_RETUNE_C13_0 */
+ { 18970, 0x0000 }, /* R18970 - ADCR_RETUNE_C14_1 */
+ { 18971, 0x0000 }, /* R18971 - ADCR_RETUNE_C14_0 */
+ { 18972, 0x0000 }, /* R18972 - ADCR_RETUNE_C15_1 */
+ { 18973, 0x0000 }, /* R18973 - ADCR_RETUNE_C15_0 */
+ { 18974, 0x0000 }, /* R18974 - ADCR_RETUNE_C16_1 */
+ { 18975, 0x0000 }, /* R18975 - ADCR_RETUNE_C16_0 */
+ { 18976, 0x0000 }, /* R18976 - ADCR_RETUNE_C17_1 */
+ { 18977, 0x0000 }, /* R18977 - ADCR_RETUNE_C17_0 */
+ { 18978, 0x0000 }, /* R18978 - ADCR_RETUNE_C18_1 */
+ { 18979, 0x0000 }, /* R18979 - ADCR_RETUNE_C18_0 */
+ { 18980, 0x0000 }, /* R18980 - ADCR_RETUNE_C19_1 */
+ { 18981, 0x0000 }, /* R18981 - ADCR_RETUNE_C19_0 */
+ { 18982, 0x0000 }, /* R18982 - ADCR_RETUNE_C20_1 */
+ { 18983, 0x0000 }, /* R18983 - ADCR_RETUNE_C20_0 */
+ { 18984, 0x0000 }, /* R18984 - ADCR_RETUNE_C21_1 */
+ { 18985, 0x0000 }, /* R18985 - ADCR_RETUNE_C21_0 */
+ { 18986, 0x0000 }, /* R18986 - ADCR_RETUNE_C22_1 */
+ { 18987, 0x0000 }, /* R18987 - ADCR_RETUNE_C22_0 */
+ { 18988, 0x0000 }, /* R18988 - ADCR_RETUNE_C23_1 */
+ { 18989, 0x0000 }, /* R18989 - ADCR_RETUNE_C23_0 */
+ { 18990, 0x0000 }, /* R18990 - ADCR_RETUNE_C24_1 */
+ { 18991, 0x0000 }, /* R18991 - ADCR_RETUNE_C24_0 */
+ { 18992, 0x0000 }, /* R18992 - ADCR_RETUNE_C25_1 */
+ { 18993, 0x0000 }, /* R18993 - ADCR_RETUNE_C25_0 */
+ { 18994, 0x0000 }, /* R18994 - ADCR_RETUNE_C26_1 */
+ { 18995, 0x0000 }, /* R18995 - ADCR_RETUNE_C26_0 */
+ { 18996, 0x0000 }, /* R18996 - ADCR_RETUNE_C27_1 */
+ { 18997, 0x0000 }, /* R18997 - ADCR_RETUNE_C27_0 */
+ { 18998, 0x0000 }, /* R18998 - ADCR_RETUNE_C28_1 */
+ { 18999, 0x0000 }, /* R18999 - ADCR_RETUNE_C28_0 */
+ { 19000, 0x0000 }, /* R19000 - ADCR_RETUNE_C29_1 */
+ { 19001, 0x0000 }, /* R19001 - ADCR_RETUNE_C29_0 */
+ { 19002, 0x0000 }, /* R19002 - ADCR_RETUNE_C30_1 */
+ { 19003, 0x0000 }, /* R19003 - ADCR_RETUNE_C30_0 */
+ { 19004, 0x0000 }, /* R19004 - ADCR_RETUNE_C31_1 */
+ { 19005, 0x0000 }, /* R19005 - ADCR_RETUNE_C31_0 */
+ { 19006, 0x0000 }, /* R19006 - ADCR_RETUNE_C32_1 */
+ { 19007, 0x0000 }, /* R19007 - ADCR_RETUNE_C32_0 */
+
+ { 19456, 0x007F }, /* R19456 - DACL_RETUNE_C1_1 */
+ { 19457, 0xFFFF }, /* R19457 - DACL_RETUNE_C1_0 */
+ { 19458, 0x0000 }, /* R19458 - DACL_RETUNE_C2_1 */
+ { 19459, 0x0000 }, /* R19459 - DACL_RETUNE_C2_0 */
+ { 19460, 0x0000 }, /* R19460 - DACL_RETUNE_C3_1 */
+ { 19461, 0x0000 }, /* R19461 - DACL_RETUNE_C3_0 */
+ { 19462, 0x0000 }, /* R19462 - DACL_RETUNE_C4_1 */
+ { 19463, 0x0000 }, /* R19463 - DACL_RETUNE_C4_0 */
+ { 19464, 0x0000 }, /* R19464 - DACL_RETUNE_C5_1 */
+ { 19465, 0x0000 }, /* R19465 - DACL_RETUNE_C5_0 */
+ { 19466, 0x0000 }, /* R19466 - DACL_RETUNE_C6_1 */
+ { 19467, 0x0000 }, /* R19467 - DACL_RETUNE_C6_0 */
+ { 19468, 0x0000 }, /* R19468 - DACL_RETUNE_C7_1 */
+ { 19469, 0x0000 }, /* R19469 - DACL_RETUNE_C7_0 */
+ { 19470, 0x0000 }, /* R19470 - DACL_RETUNE_C8_1 */
+ { 19471, 0x0000 }, /* R19471 - DACL_RETUNE_C8_0 */
+ { 19472, 0x0000 }, /* R19472 - DACL_RETUNE_C9_1 */
+ { 19473, 0x0000 }, /* R19473 - DACL_RETUNE_C9_0 */
+ { 19474, 0x0000 }, /* R19474 - DACL_RETUNE_C10_1 */
+ { 19475, 0x0000 }, /* R19475 - DACL_RETUNE_C10_0 */
+ { 19476, 0x0000 }, /* R19476 - DACL_RETUNE_C11_1 */
+ { 19477, 0x0000 }, /* R19477 - DACL_RETUNE_C11_0 */
+ { 19478, 0x0000 }, /* R19478 - DACL_RETUNE_C12_1 */
+ { 19479, 0x0000 }, /* R19479 - DACL_RETUNE_C12_0 */
+ { 19480, 0x0000 }, /* R19480 - DACL_RETUNE_C13_1 */
+ { 19481, 0x0000 }, /* R19481 - DACL_RETUNE_C13_0 */
+ { 19482, 0x0000 }, /* R19482 - DACL_RETUNE_C14_1 */
+ { 19483, 0x0000 }, /* R19483 - DACL_RETUNE_C14_0 */
+ { 19484, 0x0000 }, /* R19484 - DACL_RETUNE_C15_1 */
+ { 19485, 0x0000 }, /* R19485 - DACL_RETUNE_C15_0 */
+ { 19486, 0x0000 }, /* R19486 - DACL_RETUNE_C16_1 */
+ { 19487, 0x0000 }, /* R19487 - DACL_RETUNE_C16_0 */
+ { 19488, 0x0000 }, /* R19488 - DACL_RETUNE_C17_1 */
+ { 19489, 0x0000 }, /* R19489 - DACL_RETUNE_C17_0 */
+ { 19490, 0x0000 }, /* R19490 - DACL_RETUNE_C18_1 */
+ { 19491, 0x0000 }, /* R19491 - DACL_RETUNE_C18_0 */
+ { 19492, 0x0000 }, /* R19492 - DACL_RETUNE_C19_1 */
+ { 19493, 0x0000 }, /* R19493 - DACL_RETUNE_C19_0 */
+ { 19494, 0x0000 }, /* R19494 - DACL_RETUNE_C20_1 */
+ { 19495, 0x0000 }, /* R19495 - DACL_RETUNE_C20_0 */
+ { 19496, 0x0000 }, /* R19496 - DACL_RETUNE_C21_1 */
+ { 19497, 0x0000 }, /* R19497 - DACL_RETUNE_C21_0 */
+ { 19498, 0x0000 }, /* R19498 - DACL_RETUNE_C22_1 */
+ { 19499, 0x0000 }, /* R19499 - DACL_RETUNE_C22_0 */
+ { 19500, 0x0000 }, /* R19500 - DACL_RETUNE_C23_1 */
+ { 19501, 0x0000 }, /* R19501 - DACL_RETUNE_C23_0 */
+ { 19502, 0x0000 }, /* R19502 - DACL_RETUNE_C24_1 */
+ { 19503, 0x0000 }, /* R19503 - DACL_RETUNE_C24_0 */
+ { 19504, 0x0000 }, /* R19504 - DACL_RETUNE_C25_1 */
+ { 19505, 0x0000 }, /* R19505 - DACL_RETUNE_C25_0 */
+ { 19506, 0x0000 }, /* R19506 - DACL_RETUNE_C26_1 */
+ { 19507, 0x0000 }, /* R19507 - DACL_RETUNE_C26_0 */
+ { 19508, 0x0000 }, /* R19508 - DACL_RETUNE_C27_1 */
+ { 19509, 0x0000 }, /* R19509 - DACL_RETUNE_C27_0 */
+ { 19510, 0x0000 }, /* R19510 - DACL_RETUNE_C28_1 */
+ { 19511, 0x0000 }, /* R19511 - DACL_RETUNE_C28_0 */
+ { 19512, 0x0000 }, /* R19512 - DACL_RETUNE_C29_1 */
+ { 19513, 0x0000 }, /* R19513 - DACL_RETUNE_C29_0 */
+ { 19514, 0x0000 }, /* R19514 - DACL_RETUNE_C30_1 */
+ { 19515, 0x0000 }, /* R19515 - DACL_RETUNE_C30_0 */
+ { 19516, 0x0000 }, /* R19516 - DACL_RETUNE_C31_1 */
+ { 19517, 0x0000 }, /* R19517 - DACL_RETUNE_C31_0 */
+ { 19518, 0x0000 }, /* R19518 - DACL_RETUNE_C32_1 */
+ { 19519, 0x0000 }, /* R19519 - DACL_RETUNE_C32_0 */
+
+ { 19968, 0x0020 }, /* R19968 - RETUNEDAC_PG2_1 */
+ { 19969, 0x0000 }, /* R19969 - RETUNEDAC_PG2_0 */
+ { 19970, 0x0040 }, /* R19970 - RETUNEDAC_PG_1 */
+ { 19971, 0x0000 }, /* R19971 - RETUNEDAC_PG_0 */
+
+ { 20480, 0x007F }, /* R20480 - DACR_RETUNE_C1_1 */
+ { 20481, 0xFFFF }, /* R20481 - DACR_RETUNE_C1_0 */
+ { 20482, 0x0000 }, /* R20482 - DACR_RETUNE_C2_1 */
+ { 20483, 0x0000 }, /* R20483 - DACR_RETUNE_C2_0 */
+ { 20484, 0x0000 }, /* R20484 - DACR_RETUNE_C3_1 */
+ { 20485, 0x0000 }, /* R20485 - DACR_RETUNE_C3_0 */
+ { 20486, 0x0000 }, /* R20486 - DACR_RETUNE_C4_1 */
+ { 20487, 0x0000 }, /* R20487 - DACR_RETUNE_C4_0 */
+ { 20488, 0x0000 }, /* R20488 - DACR_RETUNE_C5_1 */
+ { 20489, 0x0000 }, /* R20489 - DACR_RETUNE_C5_0 */
+ { 20490, 0x0000 }, /* R20490 - DACR_RETUNE_C6_1 */
+ { 20491, 0x0000 }, /* R20491 - DACR_RETUNE_C6_0 */
+ { 20492, 0x0000 }, /* R20492 - DACR_RETUNE_C7_1 */
+ { 20493, 0x0000 }, /* R20493 - DACR_RETUNE_C7_0 */
+ { 20494, 0x0000 }, /* R20494 - DACR_RETUNE_C8_1 */
+ { 20495, 0x0000 }, /* R20495 - DACR_RETUNE_C8_0 */
+ { 20496, 0x0000 }, /* R20496 - DACR_RETUNE_C9_1 */
+ { 20497, 0x0000 }, /* R20497 - DACR_RETUNE_C9_0 */
+ { 20498, 0x0000 }, /* R20498 - DACR_RETUNE_C10_1 */
+ { 20499, 0x0000 }, /* R20499 - DACR_RETUNE_C10_0 */
+ { 20500, 0x0000 }, /* R20500 - DACR_RETUNE_C11_1 */
+ { 20501, 0x0000 }, /* R20501 - DACR_RETUNE_C11_0 */
+ { 20502, 0x0000 }, /* R20502 - DACR_RETUNE_C12_1 */
+ { 20503, 0x0000 }, /* R20503 - DACR_RETUNE_C12_0 */
+ { 20504, 0x0000 }, /* R20504 - DACR_RETUNE_C13_1 */
+ { 20505, 0x0000 }, /* R20505 - DACR_RETUNE_C13_0 */
+ { 20506, 0x0000 }, /* R20506 - DACR_RETUNE_C14_1 */
+ { 20507, 0x0000 }, /* R20507 - DACR_RETUNE_C14_0 */
+ { 20508, 0x0000 }, /* R20508 - DACR_RETUNE_C15_1 */
+ { 20509, 0x0000 }, /* R20509 - DACR_RETUNE_C15_0 */
+ { 20510, 0x0000 }, /* R20510 - DACR_RETUNE_C16_1 */
+ { 20511, 0x0000 }, /* R20511 - DACR_RETUNE_C16_0 */
+ { 20512, 0x0000 }, /* R20512 - DACR_RETUNE_C17_1 */
+ { 20513, 0x0000 }, /* R20513 - DACR_RETUNE_C17_0 */
+ { 20514, 0x0000 }, /* R20514 - DACR_RETUNE_C18_1 */
+ { 20515, 0x0000 }, /* R20515 - DACR_RETUNE_C18_0 */
+ { 20516, 0x0000 }, /* R20516 - DACR_RETUNE_C19_1 */
+ { 20517, 0x0000 }, /* R20517 - DACR_RETUNE_C19_0 */
+ { 20518, 0x0000 }, /* R20518 - DACR_RETUNE_C20_1 */
+ { 20519, 0x0000 }, /* R20519 - DACR_RETUNE_C20_0 */
+ { 20520, 0x0000 }, /* R20520 - DACR_RETUNE_C21_1 */
+ { 20521, 0x0000 }, /* R20521 - DACR_RETUNE_C21_0 */
+ { 20522, 0x0000 }, /* R20522 - DACR_RETUNE_C22_1 */
+ { 20523, 0x0000 }, /* R20523 - DACR_RETUNE_C22_0 */
+ { 20524, 0x0000 }, /* R20524 - DACR_RETUNE_C23_1 */
+ { 20525, 0x0000 }, /* R20525 - DACR_RETUNE_C23_0 */
+ { 20526, 0x0000 }, /* R20526 - DACR_RETUNE_C24_1 */
+ { 20527, 0x0000 }, /* R20527 - DACR_RETUNE_C24_0 */
+ { 20528, 0x0000 }, /* R20528 - DACR_RETUNE_C25_1 */
+ { 20529, 0x0000 }, /* R20529 - DACR_RETUNE_C25_0 */
+ { 20530, 0x0000 }, /* R20530 - DACR_RETUNE_C26_1 */
+ { 20531, 0x0000 }, /* R20531 - DACR_RETUNE_C26_0 */
+ { 20532, 0x0000 }, /* R20532 - DACR_RETUNE_C27_1 */
+ { 20533, 0x0000 }, /* R20533 - DACR_RETUNE_C27_0 */
+ { 20534, 0x0000 }, /* R20534 - DACR_RETUNE_C28_1 */
+ { 20535, 0x0000 }, /* R20535 - DACR_RETUNE_C28_0 */
+ { 20536, 0x0000 }, /* R20536 - DACR_RETUNE_C29_1 */
+ { 20537, 0x0000 }, /* R20537 - DACR_RETUNE_C29_0 */
+ { 20538, 0x0000 }, /* R20538 - DACR_RETUNE_C30_1 */
+ { 20539, 0x0000 }, /* R20539 - DACR_RETUNE_C30_0 */
+ { 20540, 0x0000 }, /* R20540 - DACR_RETUNE_C31_1 */
+ { 20541, 0x0000 }, /* R20541 - DACR_RETUNE_C31_0 */
+ { 20542, 0x0000 }, /* R20542 - DACR_RETUNE_C32_1 */
+ { 20543, 0x0000 }, /* R20543 - DACR_RETUNE_C32_0 */
+
+ { 20992, 0x008C }, /* R20992 - VSS_XHD2_1 */
+ { 20993, 0x0200 }, /* R20993 - VSS_XHD2_0 */
+ { 20994, 0x0035 }, /* R20994 - VSS_XHD3_1 */
+ { 20995, 0x0700 }, /* R20995 - VSS_XHD3_0 */
+ { 20996, 0x003A }, /* R20996 - VSS_XHN1_1 */
+ { 20997, 0x4100 }, /* R20997 - VSS_XHN1_0 */
+ { 20998, 0x008B }, /* R20998 - VSS_XHN2_1 */
+ { 20999, 0x7D00 }, /* R20999 - VSS_XHN2_0 */
+ { 21000, 0x003A }, /* R21000 - VSS_XHN3_1 */
+ { 21001, 0x4100 }, /* R21001 - VSS_XHN3_0 */
+ { 21002, 0x008C }, /* R21002 - VSS_XLA_1 */
+ { 21003, 0xFEE8 }, /* R21003 - VSS_XLA_0 */
+ { 21004, 0x0078 }, /* R21004 - VSS_XLB_1 */
+ { 21005, 0x0000 }, /* R21005 - VSS_XLB_0 */
+ { 21006, 0x003F }, /* R21006 - VSS_XLG_1 */
+ { 21007, 0xB260 }, /* R21007 - VSS_XLG_0 */
+ { 21008, 0x002D }, /* R21008 - VSS_PG2_1 */
+ { 21009, 0x1818 }, /* R21009 - VSS_PG2_0 */
+ { 21010, 0x0020 }, /* R21010 - VSS_PG_1 */
+ { 21011, 0x0000 }, /* R21011 - VSS_PG_0 */
+ { 21012, 0x00F1 }, /* R21012 - VSS_XTD1_1 */
+ { 21013, 0x8340 }, /* R21013 - VSS_XTD1_0 */
+ { 21014, 0x00FB }, /* R21014 - VSS_XTD2_1 */
+ { 21015, 0x8300 }, /* R21015 - VSS_XTD2_0 */
+ { 21016, 0x00EE }, /* R21016 - VSS_XTD3_1 */
+ { 21017, 0xAEC0 }, /* R21017 - VSS_XTD3_0 */
+ { 21018, 0x00FB }, /* R21018 - VSS_XTD4_1 */
+ { 21019, 0xAC40 }, /* R21019 - VSS_XTD4_0 */
+ { 21020, 0x00F1 }, /* R21020 - VSS_XTD5_1 */
+ { 21021, 0x7F80 }, /* R21021 - VSS_XTD5_0 */
+ { 21022, 0x00F4 }, /* R21022 - VSS_XTD6_1 */
+ { 21023, 0x3B40 }, /* R21023 - VSS_XTD6_0 */
+ { 21024, 0x00F5 }, /* R21024 - VSS_XTD7_1 */
+ { 21025, 0xFB00 }, /* R21025 - VSS_XTD7_0 */
+ { 21026, 0x00EA }, /* R21026 - VSS_XTD8_1 */
+ { 21027, 0x10C0 }, /* R21027 - VSS_XTD8_0 */
+ { 21028, 0x00FC }, /* R21028 - VSS_XTD9_1 */
+ { 21029, 0xC580 }, /* R21029 - VSS_XTD9_0 */
+ { 21030, 0x00E2 }, /* R21030 - VSS_XTD10_1 */
+ { 21031, 0x75C0 }, /* R21031 - VSS_XTD10_0 */
+ { 21032, 0x0004 }, /* R21032 - VSS_XTD11_1 */
+ { 21033, 0xB480 }, /* R21033 - VSS_XTD11_0 */
+ { 21034, 0x00D4 }, /* R21034 - VSS_XTD12_1 */
+ { 21035, 0xF980 }, /* R21035 - VSS_XTD12_0 */
+ { 21036, 0x0004 }, /* R21036 - VSS_XTD13_1 */
+ { 21037, 0x9140 }, /* R21037 - VSS_XTD13_0 */
+ { 21038, 0x00D8 }, /* R21038 - VSS_XTD14_1 */
+ { 21039, 0xA480 }, /* R21039 - VSS_XTD14_0 */
+ { 21040, 0x0002 }, /* R21040 - VSS_XTD15_1 */
+ { 21041, 0x3DC0 }, /* R21041 - VSS_XTD15_0 */
+ { 21042, 0x00CF }, /* R21042 - VSS_XTD16_1 */
+ { 21043, 0x7A80 }, /* R21043 - VSS_XTD16_0 */
+ { 21044, 0x00DC }, /* R21044 - VSS_XTD17_1 */
+ { 21045, 0x0600 }, /* R21045 - VSS_XTD17_0 */
+ { 21046, 0x00F2 }, /* R21046 - VSS_XTD18_1 */
+ { 21047, 0xDAC0 }, /* R21047 - VSS_XTD18_0 */
+ { 21048, 0x00BA }, /* R21048 - VSS_XTD19_1 */
+ { 21049, 0xF340 }, /* R21049 - VSS_XTD19_0 */
+ { 21050, 0x000A }, /* R21050 - VSS_XTD20_1 */
+ { 21051, 0x7940 }, /* R21051 - VSS_XTD20_0 */
+ { 21052, 0x001C }, /* R21052 - VSS_XTD21_1 */
+ { 21053, 0x0680 }, /* R21053 - VSS_XTD21_0 */
+ { 21054, 0x00FD }, /* R21054 - VSS_XTD22_1 */
+ { 21055, 0x2D00 }, /* R21055 - VSS_XTD22_0 */
+ { 21056, 0x001C }, /* R21056 - VSS_XTD23_1 */
+ { 21057, 0xE840 }, /* R21057 - VSS_XTD23_0 */
+ { 21058, 0x000D }, /* R21058 - VSS_XTD24_1 */
+ { 21059, 0xDC40 }, /* R21059 - VSS_XTD24_0 */
+ { 21060, 0x00FC }, /* R21060 - VSS_XTD25_1 */
+ { 21061, 0x9D00 }, /* R21061 - VSS_XTD25_0 */
+ { 21062, 0x0009 }, /* R21062 - VSS_XTD26_1 */
+ { 21063, 0x5580 }, /* R21063 - VSS_XTD26_0 */
+ { 21064, 0x00FE }, /* R21064 - VSS_XTD27_1 */
+ { 21065, 0x7E80 }, /* R21065 - VSS_XTD27_0 */
+ { 21066, 0x000E }, /* R21066 - VSS_XTD28_1 */
+ { 21067, 0xAB40 }, /* R21067 - VSS_XTD28_0 */
+ { 21068, 0x00F9 }, /* R21068 - VSS_XTD29_1 */
+ { 21069, 0x9880 }, /* R21069 - VSS_XTD29_0 */
+ { 21070, 0x0009 }, /* R21070 - VSS_XTD30_1 */
+ { 21071, 0x87C0 }, /* R21071 - VSS_XTD30_0 */
+ { 21072, 0x00FD }, /* R21072 - VSS_XTD31_1 */
+ { 21073, 0x2C40 }, /* R21073 - VSS_XTD31_0 */
+ { 21074, 0x0009 }, /* R21074 - VSS_XTD32_1 */
+ { 21075, 0x4800 }, /* R21075 - VSS_XTD32_0 */
+ { 21076, 0x0003 }, /* R21076 - VSS_XTS1_1 */
+ { 21077, 0x5F40 }, /* R21077 - VSS_XTS1_0 */
+ { 21078, 0x0000 }, /* R21078 - VSS_XTS2_1 */
+ { 21079, 0x8700 }, /* R21079 - VSS_XTS2_0 */
+ { 21080, 0x00FA }, /* R21080 - VSS_XTS3_1 */
+ { 21081, 0xE4C0 }, /* R21081 - VSS_XTS3_0 */
+ { 21082, 0x0000 }, /* R21082 - VSS_XTS4_1 */
+ { 21083, 0x0B40 }, /* R21083 - VSS_XTS4_0 */
+ { 21084, 0x0004 }, /* R21084 - VSS_XTS5_1 */
+ { 21085, 0xE180 }, /* R21085 - VSS_XTS5_0 */
+ { 21086, 0x0001 }, /* R21086 - VSS_XTS6_1 */
+ { 21087, 0x1F40 }, /* R21087 - VSS_XTS6_0 */
+ { 21088, 0x00F8 }, /* R21088 - VSS_XTS7_1 */
+ { 21089, 0xB000 }, /* R21089 - VSS_XTS7_0 */
+ { 21090, 0x00FB }, /* R21090 - VSS_XTS8_1 */
+ { 21091, 0xCBC0 }, /* R21091 - VSS_XTS8_0 */
+ { 21092, 0x0004 }, /* R21092 - VSS_XTS9_1 */
+ { 21093, 0xF380 }, /* R21093 - VSS_XTS9_0 */
+ { 21094, 0x0007 }, /* R21094 - VSS_XTS10_1 */
+ { 21095, 0xDF40 }, /* R21095 - VSS_XTS10_0 */
+ { 21096, 0x00FF }, /* R21096 - VSS_XTS11_1 */
+ { 21097, 0x0700 }, /* R21097 - VSS_XTS11_0 */
+ { 21098, 0x00EF }, /* R21098 - VSS_XTS12_1 */
+ { 21099, 0xD700 }, /* R21099 - VSS_XTS12_0 */
+ { 21100, 0x00FB }, /* R21100 - VSS_XTS13_1 */
+ { 21101, 0xAF40 }, /* R21101 - VSS_XTS13_0 */
+ { 21102, 0x0010 }, /* R21102 - VSS_XTS14_1 */
+ { 21103, 0x8A80 }, /* R21103 - VSS_XTS14_0 */
+ { 21104, 0x0011 }, /* R21104 - VSS_XTS15_1 */
+ { 21105, 0x07C0 }, /* R21105 - VSS_XTS15_0 */
+ { 21106, 0x00E0 }, /* R21106 - VSS_XTS16_1 */
+ { 21107, 0x0800 }, /* R21107 - VSS_XTS16_0 */
+ { 21108, 0x00D2 }, /* R21108 - VSS_XTS17_1 */
+ { 21109, 0x7600 }, /* R21109 - VSS_XTS17_0 */
+ { 21110, 0x0020 }, /* R21110 - VSS_XTS18_1 */
+ { 21111, 0xCF40 }, /* R21111 - VSS_XTS18_0 */
+ { 21112, 0x0030 }, /* R21112 - VSS_XTS19_1 */
+ { 21113, 0x2340 }, /* R21113 - VSS_XTS19_0 */
+ { 21114, 0x00FD }, /* R21114 - VSS_XTS20_1 */
+ { 21115, 0x69C0 }, /* R21115 - VSS_XTS20_0 */
+ { 21116, 0x0028 }, /* R21116 - VSS_XTS21_1 */
+ { 21117, 0x3500 }, /* R21117 - VSS_XTS21_0 */
+ { 21118, 0x0006 }, /* R21118 - VSS_XTS22_1 */
+ { 21119, 0x3300 }, /* R21119 - VSS_XTS22_0 */
+ { 21120, 0x00D9 }, /* R21120 - VSS_XTS23_1 */
+ { 21121, 0xF6C0 }, /* R21121 - VSS_XTS23_0 */
+ { 21122, 0x00F3 }, /* R21122 - VSS_XTS24_1 */
+ { 21123, 0x3340 }, /* R21123 - VSS_XTS24_0 */
+ { 21124, 0x000F }, /* R21124 - VSS_XTS25_1 */
+ { 21125, 0x4200 }, /* R21125 - VSS_XTS25_0 */
+ { 21126, 0x0004 }, /* R21126 - VSS_XTS26_1 */
+ { 21127, 0x0C80 }, /* R21127 - VSS_XTS26_0 */
+ { 21128, 0x00FB }, /* R21128 - VSS_XTS27_1 */
+ { 21129, 0x3F80 }, /* R21129 - VSS_XTS27_0 */
+ { 21130, 0x00F7 }, /* R21130 - VSS_XTS28_1 */
+ { 21131, 0x57C0 }, /* R21131 - VSS_XTS28_0 */
+ { 21132, 0x0003 }, /* R21132 - VSS_XTS29_1 */
+ { 21133, 0x5400 }, /* R21133 - VSS_XTS29_0 */
+ { 21134, 0x0000 }, /* R21134 - VSS_XTS30_1 */
+ { 21135, 0xC6C0 }, /* R21135 - VSS_XTS30_0 */
+ { 21136, 0x0003 }, /* R21136 - VSS_XTS31_1 */
+ { 21137, 0x12C0 }, /* R21137 - VSS_XTS31_0 */
+ { 21138, 0x00FD }, /* R21138 - VSS_XTS32_1 */
+ { 21139, 0x8580 }, /* R21139 - VSS_XTS32_0 */
};
-static int wm8962_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8962_volatile_register(struct device *dev, unsigned int reg)
{
- if (wm8962_reg_access[reg].vol)
- return 1;
- else
- return 0;
+ switch (reg) {
+ case WM8962_CLOCKING1:
+ case WM8962_CLOCKING2:
+ case WM8962_SOFTWARE_RESET:
+ case WM8962_ALC2:
+ case WM8962_THERMAL_SHUTDOWN_STATUS:
+ case WM8962_ADDITIONAL_CONTROL_4:
+ case WM8962_CLASS_D_CONTROL_1:
+ case WM8962_DC_SERVO_6:
+ case WM8962_INTERRUPT_STATUS_1:
+ case WM8962_INTERRUPT_STATUS_2:
+ case WM8962_DSP2_EXECCONTROL:
+ return true;
+ default:
+ return false;
+ }
}
-static int wm8962_readable_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8962_readable_register(struct device *dev, unsigned int reg)
{
- if (wm8962_reg_access[reg].read)
- return 1;
- else
- return 0;
+ switch (reg) {
+ case WM8962_LEFT_INPUT_VOLUME:
+ case WM8962_RIGHT_INPUT_VOLUME:
+ case WM8962_HPOUTL_VOLUME:
+ case WM8962_HPOUTR_VOLUME:
+ case WM8962_CLOCKING1:
+ case WM8962_ADC_DAC_CONTROL_1:
+ case WM8962_ADC_DAC_CONTROL_2:
+ case WM8962_AUDIO_INTERFACE_0:
+ case WM8962_CLOCKING2:
+ case WM8962_AUDIO_INTERFACE_1:
+ case WM8962_LEFT_DAC_VOLUME:
+ case WM8962_RIGHT_DAC_VOLUME:
+ case WM8962_AUDIO_INTERFACE_2:
+ case WM8962_SOFTWARE_RESET:
+ case WM8962_ALC1:
+ case WM8962_ALC2:
+ case WM8962_ALC3:
+ case WM8962_NOISE_GATE:
+ case WM8962_LEFT_ADC_VOLUME:
+ case WM8962_RIGHT_ADC_VOLUME:
+ case WM8962_ADDITIONAL_CONTROL_1:
+ case WM8962_ADDITIONAL_CONTROL_2:
+ case WM8962_PWR_MGMT_1:
+ case WM8962_PWR_MGMT_2:
+ case WM8962_ADDITIONAL_CONTROL_3:
+ case WM8962_ANTI_POP:
+ case WM8962_CLOCKING_3:
+ case WM8962_INPUT_MIXER_CONTROL_1:
+ case WM8962_LEFT_INPUT_MIXER_VOLUME:
+ case WM8962_RIGHT_INPUT_MIXER_VOLUME:
+ case WM8962_INPUT_MIXER_CONTROL_2:
+ case WM8962_INPUT_BIAS_CONTROL:
+ case WM8962_LEFT_INPUT_PGA_CONTROL:
+ case WM8962_RIGHT_INPUT_PGA_CONTROL:
+ case WM8962_SPKOUTL_VOLUME:
+ case WM8962_SPKOUTR_VOLUME:
+ case WM8962_THERMAL_SHUTDOWN_STATUS:
+ case WM8962_ADDITIONAL_CONTROL_4:
+ case WM8962_CLASS_D_CONTROL_1:
+ case WM8962_CLASS_D_CONTROL_2:
+ case WM8962_CLOCKING_4:
+ case WM8962_DAC_DSP_MIXING_1:
+ case WM8962_DAC_DSP_MIXING_2:
+ case WM8962_DC_SERVO_0:
+ case WM8962_DC_SERVO_1:
+ case WM8962_DC_SERVO_4:
+ case WM8962_DC_SERVO_6:
+ case WM8962_ANALOGUE_PGA_BIAS:
+ case WM8962_ANALOGUE_HP_0:
+ case WM8962_ANALOGUE_HP_2:
+ case WM8962_CHARGE_PUMP_1:
+ case WM8962_CHARGE_PUMP_B:
+ case WM8962_WRITE_SEQUENCER_CONTROL_1:
+ case WM8962_WRITE_SEQUENCER_CONTROL_2:
+ case WM8962_WRITE_SEQUENCER_CONTROL_3:
+ case WM8962_CONTROL_INTERFACE:
+ case WM8962_MIXER_ENABLES:
+ case WM8962_HEADPHONE_MIXER_1:
+ case WM8962_HEADPHONE_MIXER_2:
+ case WM8962_HEADPHONE_MIXER_3:
+ case WM8962_HEADPHONE_MIXER_4:
+ case WM8962_SPEAKER_MIXER_1:
+ case WM8962_SPEAKER_MIXER_2:
+ case WM8962_SPEAKER_MIXER_3:
+ case WM8962_SPEAKER_MIXER_4:
+ case WM8962_SPEAKER_MIXER_5:
+ case WM8962_BEEP_GENERATOR_1:
+ case WM8962_OSCILLATOR_TRIM_3:
+ case WM8962_OSCILLATOR_TRIM_4:
+ case WM8962_OSCILLATOR_TRIM_7:
+ case WM8962_ANALOGUE_CLOCKING1:
+ case WM8962_ANALOGUE_CLOCKING2:
+ case WM8962_ANALOGUE_CLOCKING3:
+ case WM8962_PLL_SOFTWARE_RESET:
+ case WM8962_PLL2:
+ case WM8962_PLL_4:
+ case WM8962_PLL_9:
+ case WM8962_PLL_10:
+ case WM8962_PLL_11:
+ case WM8962_PLL_12:
+ case WM8962_PLL_13:
+ case WM8962_PLL_14:
+ case WM8962_PLL_15:
+ case WM8962_PLL_16:
+ case WM8962_FLL_CONTROL_1:
+ case WM8962_FLL_CONTROL_2:
+ case WM8962_FLL_CONTROL_3:
+ case WM8962_FLL_CONTROL_5:
+ case WM8962_FLL_CONTROL_6:
+ case WM8962_FLL_CONTROL_7:
+ case WM8962_FLL_CONTROL_8:
+ case WM8962_GENERAL_TEST_1:
+ case WM8962_DF1:
+ case WM8962_DF2:
+ case WM8962_DF3:
+ case WM8962_DF4:
+ case WM8962_DF5:
+ case WM8962_DF6:
+ case WM8962_DF7:
+ case WM8962_LHPF1:
+ case WM8962_LHPF2:
+ case WM8962_THREED1:
+ case WM8962_THREED2:
+ case WM8962_THREED3:
+ case WM8962_THREED4:
+ case WM8962_DRC_1:
+ case WM8962_DRC_2:
+ case WM8962_DRC_3:
+ case WM8962_DRC_4:
+ case WM8962_DRC_5:
+ case WM8962_TLOOPBACK:
+ case WM8962_EQ1:
+ case WM8962_EQ2:
+ case WM8962_EQ3:
+ case WM8962_EQ4:
+ case WM8962_EQ5:
+ case WM8962_EQ6:
+ case WM8962_EQ7:
+ case WM8962_EQ8:
+ case WM8962_EQ9:
+ case WM8962_EQ10:
+ case WM8962_EQ11:
+ case WM8962_EQ12:
+ case WM8962_EQ13:
+ case WM8962_EQ14:
+ case WM8962_EQ15:
+ case WM8962_EQ16:
+ case WM8962_EQ17:
+ case WM8962_EQ18:
+ case WM8962_EQ19:
+ case WM8962_EQ20:
+ case WM8962_EQ21:
+ case WM8962_EQ22:
+ case WM8962_EQ23:
+ case WM8962_EQ24:
+ case WM8962_EQ25:
+ case WM8962_EQ26:
+ case WM8962_EQ27:
+ case WM8962_EQ28:
+ case WM8962_EQ29:
+ case WM8962_EQ30:
+ case WM8962_EQ31:
+ case WM8962_EQ32:
+ case WM8962_EQ33:
+ case WM8962_EQ34:
+ case WM8962_EQ35:
+ case WM8962_EQ36:
+ case WM8962_EQ37:
+ case WM8962_EQ38:
+ case WM8962_EQ39:
+ case WM8962_EQ40:
+ case WM8962_EQ41:
+ case WM8962_GPIO_BASE:
+ case WM8962_GPIO_2:
+ case WM8962_GPIO_3:
+ case WM8962_GPIO_5:
+ case WM8962_GPIO_6:
+ case WM8962_INTERRUPT_STATUS_1:
+ case WM8962_INTERRUPT_STATUS_2:
+ case WM8962_INTERRUPT_STATUS_1_MASK:
+ case WM8962_INTERRUPT_STATUS_2_MASK:
+ case WM8962_INTERRUPT_CONTROL:
+ case WM8962_IRQ_DEBOUNCE:
+ case WM8962_MICINT_SOURCE_POL:
+ case WM8962_DSP2_POWER_MANAGEMENT:
+ case WM8962_DSP2_EXECCONTROL:
+ case WM8962_DSP2_INSTRUCTION_RAM_0:
+ case WM8962_DSP2_ADDRESS_RAM_2:
+ case WM8962_DSP2_ADDRESS_RAM_1:
+ case WM8962_DSP2_ADDRESS_RAM_0:
+ case WM8962_DSP2_DATA1_RAM_1:
+ case WM8962_DSP2_DATA1_RAM_0:
+ case WM8962_DSP2_DATA2_RAM_1:
+ case WM8962_DSP2_DATA2_RAM_0:
+ case WM8962_DSP2_DATA3_RAM_1:
+ case WM8962_DSP2_DATA3_RAM_0:
+ case WM8962_DSP2_COEFF_RAM_0:
+ case WM8962_RETUNEADC_SHARED_COEFF_1:
+ case WM8962_RETUNEADC_SHARED_COEFF_0:
+ case WM8962_RETUNEDAC_SHARED_COEFF_1:
+ case WM8962_RETUNEDAC_SHARED_COEFF_0:
+ case WM8962_SOUNDSTAGE_ENABLES_1:
+ case WM8962_SOUNDSTAGE_ENABLES_0:
+ case WM8962_HDBASS_AI_1:
+ case WM8962_HDBASS_AI_0:
+ case WM8962_HDBASS_AR_1:
+ case WM8962_HDBASS_AR_0:
+ case WM8962_HDBASS_B_1:
+ case WM8962_HDBASS_B_0:
+ case WM8962_HDBASS_K_1:
+ case WM8962_HDBASS_K_0:
+ case WM8962_HDBASS_N1_1:
+ case WM8962_HDBASS_N1_0:
+ case WM8962_HDBASS_N2_1:
+ case WM8962_HDBASS_N2_0:
+ case WM8962_HDBASS_N3_1:
+ case WM8962_HDBASS_N3_0:
+ case WM8962_HDBASS_N4_1:
+ case WM8962_HDBASS_N4_0:
+ case WM8962_HDBASS_N5_1:
+ case WM8962_HDBASS_N5_0:
+ case WM8962_HDBASS_X1_1:
+ case WM8962_HDBASS_X1_0:
+ case WM8962_HDBASS_X2_1:
+ case WM8962_HDBASS_X2_0:
+ case WM8962_HDBASS_X3_1:
+ case WM8962_HDBASS_X3_0:
+ case WM8962_HDBASS_ATK_1:
+ case WM8962_HDBASS_ATK_0:
+ case WM8962_HDBASS_DCY_1:
+ case WM8962_HDBASS_DCY_0:
+ case WM8962_HDBASS_PG_1:
+ case WM8962_HDBASS_PG_0:
+ case WM8962_HPF_C_1:
+ case WM8962_HPF_C_0:
+ case WM8962_ADCL_RETUNE_C1_1:
+ case WM8962_ADCL_RETUNE_C1_0:
+ case WM8962_ADCL_RETUNE_C2_1:
+ case WM8962_ADCL_RETUNE_C2_0:
+ case WM8962_ADCL_RETUNE_C3_1:
+ case WM8962_ADCL_RETUNE_C3_0:
+ case WM8962_ADCL_RETUNE_C4_1:
+ case WM8962_ADCL_RETUNE_C4_0:
+ case WM8962_ADCL_RETUNE_C5_1:
+ case WM8962_ADCL_RETUNE_C5_0:
+ case WM8962_ADCL_RETUNE_C6_1:
+ case WM8962_ADCL_RETUNE_C6_0:
+ case WM8962_ADCL_RETUNE_C7_1:
+ case WM8962_ADCL_RETUNE_C7_0:
+ case WM8962_ADCL_RETUNE_C8_1:
+ case WM8962_ADCL_RETUNE_C8_0:
+ case WM8962_ADCL_RETUNE_C9_1:
+ case WM8962_ADCL_RETUNE_C9_0:
+ case WM8962_ADCL_RETUNE_C10_1:
+ case WM8962_ADCL_RETUNE_C10_0:
+ case WM8962_ADCL_RETUNE_C11_1:
+ case WM8962_ADCL_RETUNE_C11_0:
+ case WM8962_ADCL_RETUNE_C12_1:
+ case WM8962_ADCL_RETUNE_C12_0:
+ case WM8962_ADCL_RETUNE_C13_1:
+ case WM8962_ADCL_RETUNE_C13_0:
+ case WM8962_ADCL_RETUNE_C14_1:
+ case WM8962_ADCL_RETUNE_C14_0:
+ case WM8962_ADCL_RETUNE_C15_1:
+ case WM8962_ADCL_RETUNE_C15_0:
+ case WM8962_ADCL_RETUNE_C16_1:
+ case WM8962_ADCL_RETUNE_C16_0:
+ case WM8962_ADCL_RETUNE_C17_1:
+ case WM8962_ADCL_RETUNE_C17_0:
+ case WM8962_ADCL_RETUNE_C18_1:
+ case WM8962_ADCL_RETUNE_C18_0:
+ case WM8962_ADCL_RETUNE_C19_1:
+ case WM8962_ADCL_RETUNE_C19_0:
+ case WM8962_ADCL_RETUNE_C20_1:
+ case WM8962_ADCL_RETUNE_C20_0:
+ case WM8962_ADCL_RETUNE_C21_1:
+ case WM8962_ADCL_RETUNE_C21_0:
+ case WM8962_ADCL_RETUNE_C22_1:
+ case WM8962_ADCL_RETUNE_C22_0:
+ case WM8962_ADCL_RETUNE_C23_1:
+ case WM8962_ADCL_RETUNE_C23_0:
+ case WM8962_ADCL_RETUNE_C24_1:
+ case WM8962_ADCL_RETUNE_C24_0:
+ case WM8962_ADCL_RETUNE_C25_1:
+ case WM8962_ADCL_RETUNE_C25_0:
+ case WM8962_ADCL_RETUNE_C26_1:
+ case WM8962_ADCL_RETUNE_C26_0:
+ case WM8962_ADCL_RETUNE_C27_1:
+ case WM8962_ADCL_RETUNE_C27_0:
+ case WM8962_ADCL_RETUNE_C28_1:
+ case WM8962_ADCL_RETUNE_C28_0:
+ case WM8962_ADCL_RETUNE_C29_1:
+ case WM8962_ADCL_RETUNE_C29_0:
+ case WM8962_ADCL_RETUNE_C30_1:
+ case WM8962_ADCL_RETUNE_C30_0:
+ case WM8962_ADCL_RETUNE_C31_1:
+ case WM8962_ADCL_RETUNE_C31_0:
+ case WM8962_ADCL_RETUNE_C32_1:
+ case WM8962_ADCL_RETUNE_C32_0:
+ case WM8962_RETUNEADC_PG2_1:
+ case WM8962_RETUNEADC_PG2_0:
+ case WM8962_RETUNEADC_PG_1:
+ case WM8962_RETUNEADC_PG_0:
+ case WM8962_ADCR_RETUNE_C1_1:
+ case WM8962_ADCR_RETUNE_C1_0:
+ case WM8962_ADCR_RETUNE_C2_1:
+ case WM8962_ADCR_RETUNE_C2_0:
+ case WM8962_ADCR_RETUNE_C3_1:
+ case WM8962_ADCR_RETUNE_C3_0:
+ case WM8962_ADCR_RETUNE_C4_1:
+ case WM8962_ADCR_RETUNE_C4_0:
+ case WM8962_ADCR_RETUNE_C5_1:
+ case WM8962_ADCR_RETUNE_C5_0:
+ case WM8962_ADCR_RETUNE_C6_1:
+ case WM8962_ADCR_RETUNE_C6_0:
+ case WM8962_ADCR_RETUNE_C7_1:
+ case WM8962_ADCR_RETUNE_C7_0:
+ case WM8962_ADCR_RETUNE_C8_1:
+ case WM8962_ADCR_RETUNE_C8_0:
+ case WM8962_ADCR_RETUNE_C9_1:
+ case WM8962_ADCR_RETUNE_C9_0:
+ case WM8962_ADCR_RETUNE_C10_1:
+ case WM8962_ADCR_RETUNE_C10_0:
+ case WM8962_ADCR_RETUNE_C11_1:
+ case WM8962_ADCR_RETUNE_C11_0:
+ case WM8962_ADCR_RETUNE_C12_1:
+ case WM8962_ADCR_RETUNE_C12_0:
+ case WM8962_ADCR_RETUNE_C13_1:
+ case WM8962_ADCR_RETUNE_C13_0:
+ case WM8962_ADCR_RETUNE_C14_1:
+ case WM8962_ADCR_RETUNE_C14_0:
+ case WM8962_ADCR_RETUNE_C15_1:
+ case WM8962_ADCR_RETUNE_C15_0:
+ case WM8962_ADCR_RETUNE_C16_1:
+ case WM8962_ADCR_RETUNE_C16_0:
+ case WM8962_ADCR_RETUNE_C17_1:
+ case WM8962_ADCR_RETUNE_C17_0:
+ case WM8962_ADCR_RETUNE_C18_1:
+ case WM8962_ADCR_RETUNE_C18_0:
+ case WM8962_ADCR_RETUNE_C19_1:
+ case WM8962_ADCR_RETUNE_C19_0:
+ case WM8962_ADCR_RETUNE_C20_1:
+ case WM8962_ADCR_RETUNE_C20_0:
+ case WM8962_ADCR_RETUNE_C21_1:
+ case WM8962_ADCR_RETUNE_C21_0:
+ case WM8962_ADCR_RETUNE_C22_1:
+ case WM8962_ADCR_RETUNE_C22_0:
+ case WM8962_ADCR_RETUNE_C23_1:
+ case WM8962_ADCR_RETUNE_C23_0:
+ case WM8962_ADCR_RETUNE_C24_1:
+ case WM8962_ADCR_RETUNE_C24_0:
+ case WM8962_ADCR_RETUNE_C25_1:
+ case WM8962_ADCR_RETUNE_C25_0:
+ case WM8962_ADCR_RETUNE_C26_1:
+ case WM8962_ADCR_RETUNE_C26_0:
+ case WM8962_ADCR_RETUNE_C27_1:
+ case WM8962_ADCR_RETUNE_C27_0:
+ case WM8962_ADCR_RETUNE_C28_1:
+ case WM8962_ADCR_RETUNE_C28_0:
+ case WM8962_ADCR_RETUNE_C29_1:
+ case WM8962_ADCR_RETUNE_C29_0:
+ case WM8962_ADCR_RETUNE_C30_1:
+ case WM8962_ADCR_RETUNE_C30_0:
+ case WM8962_ADCR_RETUNE_C31_1:
+ case WM8962_ADCR_RETUNE_C31_0:
+ case WM8962_ADCR_RETUNE_C32_1:
+ case WM8962_ADCR_RETUNE_C32_0:
+ case WM8962_DACL_RETUNE_C1_1:
+ case WM8962_DACL_RETUNE_C1_0:
+ case WM8962_DACL_RETUNE_C2_1:
+ case WM8962_DACL_RETUNE_C2_0:
+ case WM8962_DACL_RETUNE_C3_1:
+ case WM8962_DACL_RETUNE_C3_0:
+ case WM8962_DACL_RETUNE_C4_1:
+ case WM8962_DACL_RETUNE_C4_0:
+ case WM8962_DACL_RETUNE_C5_1:
+ case WM8962_DACL_RETUNE_C5_0:
+ case WM8962_DACL_RETUNE_C6_1:
+ case WM8962_DACL_RETUNE_C6_0:
+ case WM8962_DACL_RETUNE_C7_1:
+ case WM8962_DACL_RETUNE_C7_0:
+ case WM8962_DACL_RETUNE_C8_1:
+ case WM8962_DACL_RETUNE_C8_0:
+ case WM8962_DACL_RETUNE_C9_1:
+ case WM8962_DACL_RETUNE_C9_0:
+ case WM8962_DACL_RETUNE_C10_1:
+ case WM8962_DACL_RETUNE_C10_0:
+ case WM8962_DACL_RETUNE_C11_1:
+ case WM8962_DACL_RETUNE_C11_0:
+ case WM8962_DACL_RETUNE_C12_1:
+ case WM8962_DACL_RETUNE_C12_0:
+ case WM8962_DACL_RETUNE_C13_1:
+ case WM8962_DACL_RETUNE_C13_0:
+ case WM8962_DACL_RETUNE_C14_1:
+ case WM8962_DACL_RETUNE_C14_0:
+ case WM8962_DACL_RETUNE_C15_1:
+ case WM8962_DACL_RETUNE_C15_0:
+ case WM8962_DACL_RETUNE_C16_1:
+ case WM8962_DACL_RETUNE_C16_0:
+ case WM8962_DACL_RETUNE_C17_1:
+ case WM8962_DACL_RETUNE_C17_0:
+ case WM8962_DACL_RETUNE_C18_1:
+ case WM8962_DACL_RETUNE_C18_0:
+ case WM8962_DACL_RETUNE_C19_1:
+ case WM8962_DACL_RETUNE_C19_0:
+ case WM8962_DACL_RETUNE_C20_1:
+ case WM8962_DACL_RETUNE_C20_0:
+ case WM8962_DACL_RETUNE_C21_1:
+ case WM8962_DACL_RETUNE_C21_0:
+ case WM8962_DACL_RETUNE_C22_1:
+ case WM8962_DACL_RETUNE_C22_0:
+ case WM8962_DACL_RETUNE_C23_1:
+ case WM8962_DACL_RETUNE_C23_0:
+ case WM8962_DACL_RETUNE_C24_1:
+ case WM8962_DACL_RETUNE_C24_0:
+ case WM8962_DACL_RETUNE_C25_1:
+ case WM8962_DACL_RETUNE_C25_0:
+ case WM8962_DACL_RETUNE_C26_1:
+ case WM8962_DACL_RETUNE_C26_0:
+ case WM8962_DACL_RETUNE_C27_1:
+ case WM8962_DACL_RETUNE_C27_0:
+ case WM8962_DACL_RETUNE_C28_1:
+ case WM8962_DACL_RETUNE_C28_0:
+ case WM8962_DACL_RETUNE_C29_1:
+ case WM8962_DACL_RETUNE_C29_0:
+ case WM8962_DACL_RETUNE_C30_1:
+ case WM8962_DACL_RETUNE_C30_0:
+ case WM8962_DACL_RETUNE_C31_1:
+ case WM8962_DACL_RETUNE_C31_0:
+ case WM8962_DACL_RETUNE_C32_1:
+ case WM8962_DACL_RETUNE_C32_0:
+ case WM8962_RETUNEDAC_PG2_1:
+ case WM8962_RETUNEDAC_PG2_0:
+ case WM8962_RETUNEDAC_PG_1:
+ case WM8962_RETUNEDAC_PG_0:
+ case WM8962_DACR_RETUNE_C1_1:
+ case WM8962_DACR_RETUNE_C1_0:
+ case WM8962_DACR_RETUNE_C2_1:
+ case WM8962_DACR_RETUNE_C2_0:
+ case WM8962_DACR_RETUNE_C3_1:
+ case WM8962_DACR_RETUNE_C3_0:
+ case WM8962_DACR_RETUNE_C4_1:
+ case WM8962_DACR_RETUNE_C4_0:
+ case WM8962_DACR_RETUNE_C5_1:
+ case WM8962_DACR_RETUNE_C5_0:
+ case WM8962_DACR_RETUNE_C6_1:
+ case WM8962_DACR_RETUNE_C6_0:
+ case WM8962_DACR_RETUNE_C7_1:
+ case WM8962_DACR_RETUNE_C7_0:
+ case WM8962_DACR_RETUNE_C8_1:
+ case WM8962_DACR_RETUNE_C8_0:
+ case WM8962_DACR_RETUNE_C9_1:
+ case WM8962_DACR_RETUNE_C9_0:
+ case WM8962_DACR_RETUNE_C10_1:
+ case WM8962_DACR_RETUNE_C10_0:
+ case WM8962_DACR_RETUNE_C11_1:
+ case WM8962_DACR_RETUNE_C11_0:
+ case WM8962_DACR_RETUNE_C12_1:
+ case WM8962_DACR_RETUNE_C12_0:
+ case WM8962_DACR_RETUNE_C13_1:
+ case WM8962_DACR_RETUNE_C13_0:
+ case WM8962_DACR_RETUNE_C14_1:
+ case WM8962_DACR_RETUNE_C14_0:
+ case WM8962_DACR_RETUNE_C15_1:
+ case WM8962_DACR_RETUNE_C15_0:
+ case WM8962_DACR_RETUNE_C16_1:
+ case WM8962_DACR_RETUNE_C16_0:
+ case WM8962_DACR_RETUNE_C17_1:
+ case WM8962_DACR_RETUNE_C17_0:
+ case WM8962_DACR_RETUNE_C18_1:
+ case WM8962_DACR_RETUNE_C18_0:
+ case WM8962_DACR_RETUNE_C19_1:
+ case WM8962_DACR_RETUNE_C19_0:
+ case WM8962_DACR_RETUNE_C20_1:
+ case WM8962_DACR_RETUNE_C20_0:
+ case WM8962_DACR_RETUNE_C21_1:
+ case WM8962_DACR_RETUNE_C21_0:
+ case WM8962_DACR_RETUNE_C22_1:
+ case WM8962_DACR_RETUNE_C22_0:
+ case WM8962_DACR_RETUNE_C23_1:
+ case WM8962_DACR_RETUNE_C23_0:
+ case WM8962_DACR_RETUNE_C24_1:
+ case WM8962_DACR_RETUNE_C24_0:
+ case WM8962_DACR_RETUNE_C25_1:
+ case WM8962_DACR_RETUNE_C25_0:
+ case WM8962_DACR_RETUNE_C26_1:
+ case WM8962_DACR_RETUNE_C26_0:
+ case WM8962_DACR_RETUNE_C27_1:
+ case WM8962_DACR_RETUNE_C27_0:
+ case WM8962_DACR_RETUNE_C28_1:
+ case WM8962_DACR_RETUNE_C28_0:
+ case WM8962_DACR_RETUNE_C29_1:
+ case WM8962_DACR_RETUNE_C29_0:
+ case WM8962_DACR_RETUNE_C30_1:
+ case WM8962_DACR_RETUNE_C30_0:
+ case WM8962_DACR_RETUNE_C31_1:
+ case WM8962_DACR_RETUNE_C31_0:
+ case WM8962_DACR_RETUNE_C32_1:
+ case WM8962_DACR_RETUNE_C32_0:
+ case WM8962_VSS_XHD2_1:
+ case WM8962_VSS_XHD2_0:
+ case WM8962_VSS_XHD3_1:
+ case WM8962_VSS_XHD3_0:
+ case WM8962_VSS_XHN1_1:
+ case WM8962_VSS_XHN1_0:
+ case WM8962_VSS_XHN2_1:
+ case WM8962_VSS_XHN2_0:
+ case WM8962_VSS_XHN3_1:
+ case WM8962_VSS_XHN3_0:
+ case WM8962_VSS_XLA_1:
+ case WM8962_VSS_XLA_0:
+ case WM8962_VSS_XLB_1:
+ case WM8962_VSS_XLB_0:
+ case WM8962_VSS_XLG_1:
+ case WM8962_VSS_XLG_0:
+ case WM8962_VSS_PG2_1:
+ case WM8962_VSS_PG2_0:
+ case WM8962_VSS_PG_1:
+ case WM8962_VSS_PG_0:
+ case WM8962_VSS_XTD1_1:
+ case WM8962_VSS_XTD1_0:
+ case WM8962_VSS_XTD2_1:
+ case WM8962_VSS_XTD2_0:
+ case WM8962_VSS_XTD3_1:
+ case WM8962_VSS_XTD3_0:
+ case WM8962_VSS_XTD4_1:
+ case WM8962_VSS_XTD4_0:
+ case WM8962_VSS_XTD5_1:
+ case WM8962_VSS_XTD5_0:
+ case WM8962_VSS_XTD6_1:
+ case WM8962_VSS_XTD6_0:
+ case WM8962_VSS_XTD7_1:
+ case WM8962_VSS_XTD7_0:
+ case WM8962_VSS_XTD8_1:
+ case WM8962_VSS_XTD8_0:
+ case WM8962_VSS_XTD9_1:
+ case WM8962_VSS_XTD9_0:
+ case WM8962_VSS_XTD10_1:
+ case WM8962_VSS_XTD10_0:
+ case WM8962_VSS_XTD11_1:
+ case WM8962_VSS_XTD11_0:
+ case WM8962_VSS_XTD12_1:
+ case WM8962_VSS_XTD12_0:
+ case WM8962_VSS_XTD13_1:
+ case WM8962_VSS_XTD13_0:
+ case WM8962_VSS_XTD14_1:
+ case WM8962_VSS_XTD14_0:
+ case WM8962_VSS_XTD15_1:
+ case WM8962_VSS_XTD15_0:
+ case WM8962_VSS_XTD16_1:
+ case WM8962_VSS_XTD16_0:
+ case WM8962_VSS_XTD17_1:
+ case WM8962_VSS_XTD17_0:
+ case WM8962_VSS_XTD18_1:
+ case WM8962_VSS_XTD18_0:
+ case WM8962_VSS_XTD19_1:
+ case WM8962_VSS_XTD19_0:
+ case WM8962_VSS_XTD20_1:
+ case WM8962_VSS_XTD20_0:
+ case WM8962_VSS_XTD21_1:
+ case WM8962_VSS_XTD21_0:
+ case WM8962_VSS_XTD22_1:
+ case WM8962_VSS_XTD22_0:
+ case WM8962_VSS_XTD23_1:
+ case WM8962_VSS_XTD23_0:
+ case WM8962_VSS_XTD24_1:
+ case WM8962_VSS_XTD24_0:
+ case WM8962_VSS_XTD25_1:
+ case WM8962_VSS_XTD25_0:
+ case WM8962_VSS_XTD26_1:
+ case WM8962_VSS_XTD26_0:
+ case WM8962_VSS_XTD27_1:
+ case WM8962_VSS_XTD27_0:
+ case WM8962_VSS_XTD28_1:
+ case WM8962_VSS_XTD28_0:
+ case WM8962_VSS_XTD29_1:
+ case WM8962_VSS_XTD29_0:
+ case WM8962_VSS_XTD30_1:
+ case WM8962_VSS_XTD30_0:
+ case WM8962_VSS_XTD31_1:
+ case WM8962_VSS_XTD31_0:
+ case WM8962_VSS_XTD32_1:
+ case WM8962_VSS_XTD32_0:
+ case WM8962_VSS_XTS1_1:
+ case WM8962_VSS_XTS1_0:
+ case WM8962_VSS_XTS2_1:
+ case WM8962_VSS_XTS2_0:
+ case WM8962_VSS_XTS3_1:
+ case WM8962_VSS_XTS3_0:
+ case WM8962_VSS_XTS4_1:
+ case WM8962_VSS_XTS4_0:
+ case WM8962_VSS_XTS5_1:
+ case WM8962_VSS_XTS5_0:
+ case WM8962_VSS_XTS6_1:
+ case WM8962_VSS_XTS6_0:
+ case WM8962_VSS_XTS7_1:
+ case WM8962_VSS_XTS7_0:
+ case WM8962_VSS_XTS8_1:
+ case WM8962_VSS_XTS8_0:
+ case WM8962_VSS_XTS9_1:
+ case WM8962_VSS_XTS9_0:
+ case WM8962_VSS_XTS10_1:
+ case WM8962_VSS_XTS10_0:
+ case WM8962_VSS_XTS11_1:
+ case WM8962_VSS_XTS11_0:
+ case WM8962_VSS_XTS12_1:
+ case WM8962_VSS_XTS12_0:
+ case WM8962_VSS_XTS13_1:
+ case WM8962_VSS_XTS13_0:
+ case WM8962_VSS_XTS14_1:
+ case WM8962_VSS_XTS14_0:
+ case WM8962_VSS_XTS15_1:
+ case WM8962_VSS_XTS15_0:
+ case WM8962_VSS_XTS16_1:
+ case WM8962_VSS_XTS16_0:
+ case WM8962_VSS_XTS17_1:
+ case WM8962_VSS_XTS17_0:
+ case WM8962_VSS_XTS18_1:
+ case WM8962_VSS_XTS18_0:
+ case WM8962_VSS_XTS19_1:
+ case WM8962_VSS_XTS19_0:
+ case WM8962_VSS_XTS20_1:
+ case WM8962_VSS_XTS20_0:
+ case WM8962_VSS_XTS21_1:
+ case WM8962_VSS_XTS21_0:
+ case WM8962_VSS_XTS22_1:
+ case WM8962_VSS_XTS22_0:
+ case WM8962_VSS_XTS23_1:
+ case WM8962_VSS_XTS23_0:
+ case WM8962_VSS_XTS24_1:
+ case WM8962_VSS_XTS24_0:
+ case WM8962_VSS_XTS25_1:
+ case WM8962_VSS_XTS25_0:
+ case WM8962_VSS_XTS26_1:
+ case WM8962_VSS_XTS26_0:
+ case WM8962_VSS_XTS27_1:
+ case WM8962_VSS_XTS27_0:
+ case WM8962_VSS_XTS28_1:
+ case WM8962_VSS_XTS28_0:
+ case WM8962_VSS_XTS29_1:
+ case WM8962_VSS_XTS29_0:
+ case WM8962_VSS_XTS30_1:
+ case WM8962_VSS_XTS30_0:
+ case WM8962_VSS_XTS31_1:
+ case WM8962_VSS_XTS31_0:
+ case WM8962_VSS_XTS32_1:
+ case WM8962_VSS_XTS32_0:
+ return true;
+ default:
+ return false;
+ }
}
-static int wm8962_reset(struct snd_soc_codec *codec)
+static int wm8962_reset(struct wm8962_priv *wm8962)
{
- return snd_soc_write(codec, WM8962_SOFTWARE_RESET, 0x6243);
+ int ret;
+
+ ret = regmap_write(wm8962->regmap, WM8962_SOFTWARE_RESET, 0x6243);
+ if (ret != 0)
+ return ret;
+
+ return regmap_write(wm8962->regmap, WM8962_PLL_SOFTWARE_RESET, 0);
}
static const DECLARE_TLV_DB_SCALE(inpga_tlv, -2325, 75, 0);
static const DECLARE_TLV_DB_SCALE(mixin_tlv, -1500, 300, 0);
static const unsigned int mixinpga_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+ TLV_DB_RANGE_HEAD(5),
0, 1, TLV_DB_SCALE_ITEM(0, 600, 0),
2, 2, TLV_DB_SCALE_ITEM(1300, 1300, 0),
3, 4, TLV_DB_SCALE_ITEM(1800, 200, 0),
@@ -1980,12 +1470,128 @@ static const DECLARE_TLV_DB_SCALE(bypass_tlv, -1500, 300, 0);
static const DECLARE_TLV_DB_SCALE(out_tlv, -12100, 100, 1);
static const DECLARE_TLV_DB_SCALE(hp_tlv, -700, 100, 0);
static const unsigned int classd_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+ TLV_DB_RANGE_HEAD(2),
0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
};
static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static int wm8962_dsp2_write_config(struct snd_soc_codec *codec)
+{
+ return 0;
+}
+
+static int wm8962_dsp2_set_enable(struct snd_soc_codec *codec, u16 val)
+{
+ u16 adcl = snd_soc_read(codec, WM8962_LEFT_ADC_VOLUME);
+ u16 adcr = snd_soc_read(codec, WM8962_RIGHT_ADC_VOLUME);
+ u16 dac = snd_soc_read(codec, WM8962_ADC_DAC_CONTROL_1);
+
+ /* Mute the ADCs and DACs */
+ snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, 0);
+ snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, WM8962_ADC_VU);
+ snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
+ WM8962_DAC_MUTE, WM8962_DAC_MUTE);
+
+ snd_soc_write(codec, WM8962_SOUNDSTAGE_ENABLES_0, val);
+
+ /* Restore the ADCs and DACs */
+ snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, adcl);
+ snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, adcr);
+ snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1,
+ WM8962_DAC_MUTE, dac);
+
+ return 0;
+}
+
+static int wm8962_dsp2_start(struct snd_soc_codec *codec)
+{
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+ wm8962_dsp2_write_config(codec);
+
+ snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_RUNR);
+
+ wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena);
+
+ return 0;
+}
+
+static int wm8962_dsp2_stop(struct snd_soc_codec *codec)
+{
+ wm8962_dsp2_set_enable(codec, 0);
+
+ snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_STOP);
+
+ return 0;
+}
+
+#define WM8962_DSP2_ENABLE(xname, xshift) \
+{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
+ .info = wm8962_dsp2_ena_info, \
+ .get = wm8962_dsp2_ena_get, .put = wm8962_dsp2_ena_put, \
+ .private_value = xshift }
+
+static int wm8962_dsp2_ena_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
+
+ uinfo->count = 1;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 1;
+
+ return 0;
+}
+
+static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int shift = kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+ ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift);
+
+ return 0;
+}
+
+static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ int shift = kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+ int old = wm8962->dsp2_ena;
+ int ret = 0;
+ int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) &
+ WM8962_DSP2_ENA;
+
+ mutex_lock(&codec->mutex);
+
+ if (ucontrol->value.integer.value[0])
+ wm8962->dsp2_ena |= 1 << shift;
+ else
+ wm8962->dsp2_ena &= ~(1 << shift);
+
+ if (wm8962->dsp2_ena == old)
+ goto out;
+
+ ret = 1;
+
+ if (dsp2_running) {
+ if (wm8962->dsp2_ena)
+ wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena);
+ else
+ wm8962_dsp2_stop(codec);
+ }
+
+out:
+ mutex_unlock(&codec->mutex);
+
+ return ret;
+}
+
/* The VU bits for the headphones are in a different register to the mute
* bits and only take effect on the PGA if it is actually powered.
*/
@@ -2021,7 +1627,6 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- u16 *reg_cache = codec->reg_cache;
int ret;
/* Apply the update (if any) */
@@ -2030,16 +1635,19 @@ static int wm8962_put_spk_sw(struct snd_kcontrol *kcontrol,
return 0;
/* If the left PGA is enabled hit that VU bit... */
- if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTL_PGA_ENA)
- return snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
- reg_cache[WM8962_SPKOUTL_VOLUME]);
+ ret = snd_soc_read(codec, WM8962_PWR_MGMT_2);
+ if (ret & WM8962_SPKOUTL_PGA_ENA) {
+ snd_soc_write(codec, WM8962_SPKOUTL_VOLUME,
+ snd_soc_read(codec, WM8962_SPKOUTL_VOLUME));
+ return 1;
+ }
/* ...otherwise the right. The VU is stereo. */
- if (reg_cache[WM8962_PWR_MGMT_2] & WM8962_SPKOUTR_PGA_ENA)
- return snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
- reg_cache[WM8962_SPKOUTR_VOLUME]);
+ if (ret & WM8962_SPKOUTR_PGA_ENA)
+ snd_soc_write(codec, WM8962_SPKOUTR_VOLUME,
+ snd_soc_read(codec, WM8962_SPKOUTR_VOLUME));
- return 0;
+ return 1;
}
static const char *cap_hpf_mode_text[] = {
@@ -2049,6 +1657,14 @@ static const char *cap_hpf_mode_text[] = {
static const struct soc_enum cap_hpf_mode =
SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text);
+
+static const char *cap_lhpf_mode_text[] = {
+ "LPF", "HPF"
+};
+
+static const struct soc_enum cap_lhpf_mode =
+ SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text);
+
static const struct snd_kcontrol_new wm8962_snd_controls[] = {
SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1),
@@ -2077,6 +1693,8 @@ SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME,
SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1),
SOC_ENUM("Capture HPF Mode", cap_hpf_mode),
SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0),
+SOC_SINGLE("Capture LHPF Switch", WM8962_LHPF1, 0, 1, 0),
+SOC_ENUM("Capture LHPF Mode", cap_lhpf_mode),
SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv),
@@ -2084,6 +1702,8 @@ SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1,
SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8962_LEFT_DAC_VOLUME,
WM8962_RIGHT_DAC_VOLUME, 1, 127, 0, digital_tlv),
SOC_SINGLE("DAC High Performance Switch", WM8962_ADC_DAC_CONTROL_2, 0, 1, 0),
+SOC_SINGLE("DAC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 5, 1, 0),
+SOC_SINGLE("ADC L/R Swap Switch", WM8962_AUDIO_INTERFACE_0, 8, 1, 0),
SOC_SINGLE("ADC High Performance Switch", WM8962_ADDITIONAL_CONTROL_1,
5, 1, 0),
@@ -2134,6 +1754,11 @@ SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23,
WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv),
SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23,
WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv),
+
+WM8962_DSP2_ENABLE("VSS Switch", WM8962_VSS_ENA_SHIFT),
+WM8962_DSP2_ENABLE("HPF1 Switch", WM8962_HPF1_ENA_SHIFT),
+WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT),
+WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT),
};
static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = {
@@ -2195,62 +1820,6 @@ SOC_SINGLE_TLV("SPKOUTR Mixer DACR Volume", WM8962_SPEAKER_MIXER_5,
4, 1, 0, inmix_tlv),
};
-static int sysclk_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct snd_soc_codec *codec = w->codec;
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- unsigned long timeout;
- int src;
- int fll;
-
- src = snd_soc_read(codec, WM8962_CLOCKING2) & WM8962_SYSCLK_SRC_MASK;
-
- switch (src) {
- case 0: /* MCLK */
- fll = 0;
- break;
- case 0x200: /* FLL */
- fll = 1;
- break;
- default:
- dev_err(codec->dev, "Unknown SYSCLK source %x\n", src);
- return -EINVAL;
- }
-
- switch (event) {
- case SND_SOC_DAPM_PRE_PMU:
- if (fll) {
- try_wait_for_completion(&wm8962->fll_lock);
-
- snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
- WM8962_FLL_ENA, WM8962_FLL_ENA);
- if (wm8962->irq) {
- timeout = msecs_to_jiffies(5);
- timeout = wait_for_completion_timeout(&wm8962->fll_lock,
- timeout);
-
- if (timeout == 0)
- dev_err(codec->dev,
- "Timed out starting FLL\n");
- }
- }
- break;
-
- case SND_SOC_DAPM_POST_PMD:
- if (fll)
- snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
- WM8962_FLL_ENA, 0);
- break;
-
- default:
- BUG();
- return -EINVAL;
- }
-
- return 0;
-}
-
static int cp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -2365,7 +1934,6 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
struct snd_soc_codec *codec = w->codec;
- u16 *reg_cache = codec->reg_cache;
int reg;
switch (w->shift) {
@@ -2388,14 +1956,39 @@ static int out_pga_event(struct snd_soc_dapm_widget *w,
switch (event) {
case SND_SOC_DAPM_POST_PMU:
- return snd_soc_write(codec, reg, reg_cache[reg]);
+ return snd_soc_write(codec, reg, snd_soc_read(codec, reg));
default:
BUG();
return -EINVAL;
}
}
-static const char *st_text[] = { "None", "Right", "Left" };
+static int dsp2_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
+
+ switch (event) {
+ case SND_SOC_DAPM_POST_PMU:
+ if (wm8962->dsp2_ena)
+ wm8962_dsp2_start(codec);
+ break;
+
+ case SND_SOC_DAPM_PRE_PMD:
+ if (wm8962->dsp2_ena)
+ wm8962_dsp2_stop(codec);
+ break;
+
+ default:
+ BUG();
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static const char *st_text[] = { "None", "Left", "Right" };
static const struct soc_enum str_enum =
SOC_ENUM_SINGLE(WM8962_DAC_DSP_MIXING_1, 2, 3, st_text);
@@ -2506,17 +2099,21 @@ SND_SOC_DAPM_INPUT("IN3L"),
SND_SOC_DAPM_INPUT("IN3R"),
SND_SOC_DAPM_INPUT("IN4L"),
SND_SOC_DAPM_INPUT("IN4R"),
-SND_SOC_DAPM_INPUT("Beep"),
+SND_SOC_DAPM_SIGGEN("Beep"),
SND_SOC_DAPM_INPUT("DMICDAT"),
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8962_PWR_MGMT_1, 1, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8962_PWR_MGMT_1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Class G", WM8962_CHARGE_PUMP_B, 0, 1, NULL, 0),
-SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event,
- SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
+SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event,
SND_SOC_DAPM_POST_PMU),
SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT,
+ WM8962_DSP2_ENA_SHIFT, 0, dsp2_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_SUPPLY("TEMP_HP", WM8962_ADDITIONAL_CONTROL_4, 2, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("TEMP_SPK", WM8962_ADDITIONAL_CONTROL_4, 1, 0, NULL, 0),
SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0,
inpgal, ARRAY_SIZE(inpgal)),
@@ -2527,7 +2124,7 @@ SND_SOC_DAPM_MIXER("MIXINL", WM8962_PWR_MGMT_1, 5, 0,
SND_SOC_DAPM_MIXER("MIXINR", WM8962_PWR_MGMT_1, 4, 0,
mixinr, ARRAY_SIZE(mixinr)),
-SND_SOC_DAPM_AIF_IN("DMIC", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
+SND_SOC_DAPM_AIF_IN("DMIC_ENA", NULL, 0, WM8962_PWR_MGMT_1, 10, 0),
SND_SOC_DAPM_ADC("ADCL", "Capture", WM8962_PWR_MGMT_1, 3, 0),
SND_SOC_DAPM_ADC("ADCR", "Capture", WM8962_PWR_MGMT_1, 2, 0),
@@ -2606,33 +2203,39 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
{ "MICBIAS", NULL, "SYSCLK" },
- { "DMIC", NULL, "DMICDAT" },
+ { "DMIC_ENA", NULL, "DMICDAT" },
{ "ADCL", NULL, "SYSCLK" },
{ "ADCL", NULL, "TOCLK" },
{ "ADCL", NULL, "MIXINL" },
- { "ADCL", NULL, "DMIC" },
+ { "ADCL", NULL, "DMIC_ENA" },
+ { "ADCL", NULL, "DSP2" },
{ "ADCR", NULL, "SYSCLK" },
{ "ADCR", NULL, "TOCLK" },
{ "ADCR", NULL, "MIXINR" },
- { "ADCR", NULL, "DMIC" },
+ { "ADCR", NULL, "DMIC_ENA" },
+ { "ADCR", NULL, "DSP2" },
{ "STL", "Left", "ADCL" },
{ "STL", "Right", "ADCR" },
+ { "STL", NULL, "Class G" },
{ "STR", "Left", "ADCL" },
{ "STR", "Right", "ADCR" },
+ { "STR", NULL, "Class G" },
{ "DACL", NULL, "SYSCLK" },
{ "DACL", NULL, "TOCLK" },
{ "DACL", NULL, "Beep" },
{ "DACL", NULL, "STL" },
+ { "DACL", NULL, "DSP2" },
{ "DACR", NULL, "SYSCLK" },
{ "DACR", NULL, "TOCLK" },
{ "DACR", NULL, "Beep" },
{ "DACR", NULL, "STR" },
+ { "DACR", NULL, "DSP2" },
{ "HPMIXL", "IN4L Switch", "IN4L" },
{ "HPMIXL", "IN4R Switch", "IN4R" },
@@ -2668,6 +2271,9 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = {
{ "HPOUTL", NULL, "HPOUT" },
{ "HPOUTR", NULL, "HPOUT" },
+
+ { "HPOUTL", NULL, "TEMP_HP" },
+ { "HPOUTR", NULL, "TEMP_HP" },
};
static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
@@ -2684,6 +2290,7 @@ static const struct snd_soc_dapm_route wm8962_spk_mono_intercon[] = {
{ "Speaker Output", NULL, "Speaker PGA" },
{ "Speaker Output", NULL, "SYSCLK" },
{ "Speaker Output", NULL, "TOCLK" },
+ { "Speaker Output", NULL, "TEMP_SPK" },
{ "SPKOUT", NULL, "Speaker Output" },
};
@@ -2712,10 +2319,12 @@ static const struct snd_soc_dapm_route wm8962_spk_stereo_intercon[] = {
{ "SPKOUTL Output", NULL, "SPKOUTL PGA" },
{ "SPKOUTL Output", NULL, "SYSCLK" },
{ "SPKOUTL Output", NULL, "TOCLK" },
+ { "SPKOUTL Output", NULL, "TEMP_SPK" },
{ "SPKOUTR Output", NULL, "SPKOUTR PGA" },
{ "SPKOUTR Output", NULL, "SYSCLK" },
{ "SPKOUTR Output", NULL, "TOCLK" },
+ { "SPKOUTR Output", NULL, "TEMP_SPK" },
{ "SPKOUTL", NULL, "SPKOUTL Output" },
{ "SPKOUTR", NULL, "SPKOUTR Output" },
@@ -2726,13 +2335,13 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
struct wm8962_pdata *pdata = dev_get_platdata(codec->dev);
struct snd_soc_dapm_context *dapm = &codec->dapm;
- snd_soc_add_controls(codec, wm8962_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8962_snd_controls,
ARRAY_SIZE(wm8962_snd_controls));
if (pdata && pdata->spk_mono)
- snd_soc_add_controls(codec, wm8962_spk_mono_controls,
+ snd_soc_add_codec_controls(codec, wm8962_spk_mono_controls,
ARRAY_SIZE(wm8962_spk_mono_controls));
else
- snd_soc_add_controls(codec, wm8962_spk_stereo_controls,
+ snd_soc_add_codec_controls(codec, wm8962_spk_stereo_controls,
ARRAY_SIZE(wm8962_spk_stereo_controls));
@@ -2760,40 +2369,13 @@ static int wm8962_add_widgets(struct snd_soc_codec *codec)
return 0;
}
-static void wm8962_sync_cache(struct snd_soc_codec *codec)
-{
- u16 *reg_cache = codec->reg_cache;
- int i;
-
- if (!codec->cache_sync)
- return;
-
- dev_dbg(codec->dev, "Syncing cache\n");
-
- codec->cache_only = 0;
-
- /* Sync back cached values if they're different from the
- * hardware default.
- */
- for (i = 1; i < codec->driver->reg_cache_size; i++) {
- if (i == WM8962_SOFTWARE_RESET)
- continue;
- if (reg_cache[i] == wm8962_reg[i])
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
-
- codec->cache_sync = 0;
-}
-
/* -1 for reserved values */
static const int bclk_divs[] = {
1, -1, 2, 3, 4, -1, 6, 8, -1, 12, 16, 24, -1, 32, 32, 32
};
static const int sysclk_rates[] = {
- 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536,
+ 64, 128, 192, 256, 384, 512, 768, 1024, 1408, 1536, 3072, 6144
};
static void wm8962_configure_bclk(struct snd_soc_codec *codec)
@@ -2827,6 +2409,8 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
return;
}
+ dev_dbg(codec->dev, "Selected sysclk ratio %d\n", sysclk_rates[i]);
+
snd_soc_update_bits(codec, WM8962_CLOCKING_4,
WM8962_SYSCLK_RATE_MASK, clocking4);
@@ -2885,9 +2469,6 @@ static void wm8962_configure_bclk(struct snd_soc_codec *codec)
static int wm8962_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- int ret;
-
if (level == codec->dapm.bias_level)
return 0;
@@ -2904,50 +2485,15 @@ static int wm8962_set_bias_level(struct snd_soc_codec *codec,
break;
case SND_SOC_BIAS_STANDBY:
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
- wm8962->supplies);
- if (ret != 0) {
- dev_err(codec->dev,
- "Failed to enable supplies: %d\n",
- ret);
- return ret;
- }
-
- wm8962_sync_cache(codec);
-
- snd_soc_update_bits(codec, WM8962_ANTI_POP,
- WM8962_STARTUP_BIAS_ENA |
- WM8962_VMID_BUF_ENA,
- WM8962_STARTUP_BIAS_ENA |
- WM8962_VMID_BUF_ENA);
-
- /* Bias enable at 2*50k for ramp */
- snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
- WM8962_VMID_SEL_MASK |
- WM8962_BIAS_ENA,
- WM8962_BIAS_ENA | 0x180);
-
- msleep(5);
- }
-
/* VMID 2*250k */
snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
WM8962_VMID_SEL_MASK, 0x100);
break;
case SND_SOC_BIAS_OFF:
- snd_soc_update_bits(codec, WM8962_PWR_MGMT_1,
- WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
-
- snd_soc_update_bits(codec, WM8962_ANTI_POP,
- WM8962_STARTUP_BIAS_ENA |
- WM8962_VMID_BUF_ENA, 0);
-
- regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
- wm8962->supplies);
break;
}
+
codec->dapm.bias_level = level;
return 0;
}
@@ -2981,6 +2527,9 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
int adctl3 = 0;
wm8962->bclk = snd_soc_params_to_bclk(params);
+ if (params_channels(params) == 1)
+ wm8962->bclk *= 2;
+
wm8962->lrclk = params_rate(params);
for (i = 0; i < ARRAY_SIZE(sr_vals); i++) {
@@ -3001,13 +2550,13 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
case SNDRV_PCM_FORMAT_S16_LE:
break;
case SNDRV_PCM_FORMAT_S20_3LE:
- aif0 |= 0x40;
+ aif0 |= 0x4;
break;
case SNDRV_PCM_FORMAT_S24_LE:
- aif0 |= 0x80;
+ aif0 |= 0x8;
break;
case SNDRV_PCM_FORMAT_S32_LE:
- aif0 |= 0xc0;
+ aif0 |= 0xc;
break;
default:
return -EINVAL;
@@ -3019,7 +2568,8 @@ static int wm8962_hw_params(struct snd_pcm_substream *substream,
WM8962_SAMPLE_RATE_INT_MODE |
WM8962_SAMPLE_RATE_MASK, adctl3);
- wm8962_configure_bclk(codec);
+ if (codec->dapm.bias_level == SND_SOC_BIAS_ON)
+ wm8962_configure_bclk(codec);
return 0;
}
@@ -3049,6 +2599,8 @@ static int wm8962_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
wm8962->sysclk_rate = freq;
+ wm8962_configure_bclk(codec);
+
return 0;
}
@@ -3058,9 +2610,9 @@ static int wm8962_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
int aif0 = 0;
switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_DSP_A:
- aif0 |= WM8962_LRCLK_INV;
case SND_SOC_DAIFMT_DSP_B:
+ aif0 |= WM8962_LRCLK_INV | 3;
+ case SND_SOC_DAIFMT_DSP_A:
aif0 |= 3;
switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
@@ -3227,7 +2779,7 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
struct _fll_div fll_div;
unsigned long timeout;
int ret;
- int fll1 = snd_soc_read(codec, WM8962_FLL_CONTROL_1) & WM8962_FLL_ENA;
+ int fll1 = 0;
/* Any change? */
if (source == wm8962->fll_src && Fref == wm8962->fll_fref &&
@@ -3243,6 +2795,8 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
WM8962_FLL_ENA, 0);
+ pm_runtime_put(codec->dev);
+
return 0;
}
@@ -3250,6 +2804,9 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
if (ret != 0)
return ret;
+ /* Parameters good, disable so we can reprogram */
+ snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1, WM8962_FLL_ENA, 0);
+
switch (fll_id) {
case WM8962_FLL_MCLK:
case WM8962_FLL_BCLK:
@@ -3288,9 +2845,11 @@ static int wm8962_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
try_wait_for_completion(&wm8962->fll_lock);
+ pm_runtime_get_sync(codec->dev);
+
snd_soc_update_bits(codec, WM8962_FLL_CONTROL_1,
WM8962_FLL_FRAC | WM8962_FLL_REFCLK_SRC_MASK |
- WM8962_FLL_ENA, fll1);
+ WM8962_FLL_ENA, fll1 | WM8962_FLL_ENA);
dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
@@ -3340,7 +2899,7 @@ static int wm8962_mute(struct snd_soc_dai *dai, int mute)
#define WM8962_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8962_dai_ops = {
+static const struct snd_soc_dai_ops wm8962_dai_ops = {
.hw_params = wm8962_hw_params,
.set_sysclk = wm8962_set_dai_sysclk,
.set_fmt = wm8962_set_dai_fmt,
@@ -3351,14 +2910,14 @@ static struct snd_soc_dai_driver wm8962_dai = {
.name = "wm8962",
.playback = {
.stream_name = "Playback",
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = WM8962_RATES,
.formats = WM8962_FORMATS,
},
.capture = {
.stream_name = "Capture",
- .channels_min = 2,
+ .channels_min = 1,
.channels_max = 2,
.rates = WM8962_RATES,
.formats = WM8962_FORMATS,
@@ -3399,38 +2958,73 @@ static void wm8962_mic_work(struct work_struct *work)
static irqreturn_t wm8962_irq(int irq, void *data)
{
- struct snd_soc_codec *codec = data;
- struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec);
- int mask;
- int active;
+ struct device *dev = data;
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+ unsigned int mask;
+ unsigned int active;
+ int reg, ret;
- mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK);
+ ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2_MASK,
+ &mask);
+ if (ret != 0) {
+ dev_err(dev, "Failed to read interrupt mask: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ ret = regmap_read(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, &active);
+ if (ret != 0) {
+ dev_err(dev, "Failed to read interrupt: %d\n", ret);
+ return IRQ_NONE;
+ }
- active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2);
active &= ~mask;
+ if (!active)
+ return IRQ_NONE;
+
/* Acknowledge the interrupts */
- snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active);
+ ret = regmap_write(wm8962->regmap, WM8962_INTERRUPT_STATUS_2, active);
+ if (ret != 0)
+ dev_warn(dev, "Failed to ack interrupt: %d\n", ret);
if (active & WM8962_FLL_LOCK_EINT) {
- dev_dbg(codec->dev, "FLL locked\n");
+ dev_dbg(dev, "FLL locked\n");
complete(&wm8962->fll_lock);
}
if (active & WM8962_FIFOS_ERR_EINT)
- dev_err(codec->dev, "FIFO error\n");
+ dev_err(dev, "FIFO error\n");
+
+ if (active & WM8962_TEMP_SHUT_EINT) {
+ dev_crit(dev, "Thermal shutdown\n");
- if (active & WM8962_TEMP_SHUT_EINT)
- dev_crit(codec->dev, "Thermal shutdown\n");
+ ret = regmap_read(wm8962->regmap,
+ WM8962_THERMAL_SHUTDOWN_STATUS, &reg);
+ if (ret != 0) {
+ dev_warn(dev, "Failed to read thermal status: %d\n",
+ ret);
+ reg = 0;
+ }
+
+ if (reg & WM8962_TEMP_ERR_HP)
+ dev_crit(dev, "Headphone thermal error\n");
+ if (reg & WM8962_TEMP_WARN_HP)
+ dev_crit(dev, "Headphone thermal warning\n");
+ if (reg & WM8962_TEMP_ERR_SPK)
+ dev_crit(dev, "Speaker thermal error\n");
+ if (reg & WM8962_TEMP_WARN_SPK)
+ dev_crit(dev, "Speaker thermal warning\n");
+ }
if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) {
- dev_dbg(codec->dev, "Microphone event detected\n");
+ dev_dbg(dev, "Microphone event detected\n");
#ifndef CONFIG_SND_SOC_WM8962_MODULE
- trace_snd_soc_jack_irq(dev_name(codec->dev));
+ trace_snd_soc_jack_irq(dev_name(dev));
#endif
- pm_wakeup_event(codec->dev, 300);
+ pm_wakeup_event(dev, 300);
schedule_delayed_work(&wm8962->mic_work,
msecs_to_jiffies(250));
@@ -3475,34 +3069,17 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack)
snd_soc_jack_report(wm8962->jack, 0,
SND_JACK_MICROPHONE | SND_JACK_BTN_0);
- return 0;
-}
-EXPORT_SYMBOL_GPL(wm8962_mic_detect);
-
-#ifdef CONFIG_PM
-static int wm8962_resume(struct snd_soc_codec *codec)
-{
- u16 *reg_cache = codec->reg_cache;
- int i;
-
- /* Restore the registers */
- for (i = 1; i < codec->driver->reg_cache_size; i++) {
- switch (i) {
- case WM8962_SOFTWARE_RESET:
- continue;
- default:
- break;
- }
-
- if (reg_cache[i] != wm8962_reg[i])
- snd_soc_write(codec, i, reg_cache[i]);
+ if (jack) {
+ snd_soc_dapm_force_enable_pin(&codec->dapm, "SYSCLK");
+ snd_soc_dapm_force_enable_pin(&codec->dapm, "MICBIAS");
+ } else {
+ snd_soc_dapm_disable_pin(&codec->dapm, "SYSCLK");
+ snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS");
}
return 0;
}
-#else
-#define wm8962_resume NULL
-#endif
+EXPORT_SYMBOL_GPL(wm8962_mic_detect);
#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
static int beep_rates[] = {
@@ -3717,13 +3294,17 @@ static int wm8962_gpio_direction_out(struct gpio_chip *chip,
{
struct wm8962_priv *wm8962 = gpio_to_wm8962(chip);
struct snd_soc_codec *codec = wm8962->codec;
- int val;
+ int ret, val;
/* Force function 1 (logic output) */
val = (1 << WM8962_GP2_FN_SHIFT) | (value << WM8962_GP2_LVL_SHIFT);
- return snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
- WM8962_GP2_FN_MASK | WM8962_GP2_LVL, val);
+ ret = snd_soc_update_bits(codec, WM8962_GPIO_BASE + offset,
+ WM8962_GP2_FN_MASK | WM8962_GP2_LVL, val);
+ if (ret < 0)
+ return ret;
+
+ return 0;
}
static struct gpio_chip wm8962_template_chip = {
@@ -3784,26 +3365,12 @@ static int wm8962_probe(struct snd_soc_codec *codec)
bool dmicclk, dmicdat;
wm8962->codec = codec;
- INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work);
- init_completion(&wm8962->fll_lock);
+ codec->control_data = wm8962->regmap;
- codec->cache_sync = 1;
- codec->dapm.idle_bias_off = 1;
-
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+ ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
- goto err;
- }
-
- for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
- wm8962->supplies[i].supply = wm8962_supply_names[i];
-
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8962->supplies),
- wm8962->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err;
+ return ret;
}
wm8962->disable_nb[0].notifier_call = wm8962_regulator_event_0;
@@ -3826,43 +3393,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
}
}
- ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
- wm8962->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
- }
-
- ret = snd_soc_read(codec, WM8962_SOFTWARE_RESET);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to read ID register\n");
- goto err_enable;
- }
- if (ret != wm8962_reg[WM8962_SOFTWARE_RESET]) {
- dev_err(codec->dev, "Device is not a WM8962, ID %x != %x\n",
- ret, wm8962_reg[WM8962_SOFTWARE_RESET]);
- ret = -EINVAL;
- goto err_enable;
- }
-
- ret = snd_soc_read(codec, WM8962_RIGHT_INPUT_VOLUME);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to read device revision: %d\n",
- ret);
- goto err_enable;
- }
-
- dev_info(codec->dev, "customer id %x revision %c\n",
- (ret & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT,
- ((ret & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT)
- + 'A');
-
- ret = wm8962_reset(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- goto err_enable;
- }
-
/* SYSCLK defaults to on; make sure it is off so we can safely
* write to registers if the device is declocked.
*/
@@ -3872,7 +3402,10 @@ static int wm8962_probe(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8962_CLOCKING2,
WM8962_CLKREG_OVD, WM8962_CLKREG_OVD);
- regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+ /* Ensure that the oscillator and PLLs are disabled */
+ snd_soc_update_bits(codec, WM8962_PLL2,
+ WM8962_OSC_ENA | WM8962_PLL2_ENA | WM8962_PLL3_ENA,
+ 0);
if (pdata) {
/* Apply static configuration for GPIOs */
@@ -3924,6 +3457,12 @@ static int wm8962_probe(struct snd_soc_codec *codec)
/* Stereo control for EQ */
snd_soc_update_bits(codec, WM8962_EQ1, WM8962_EQ_SHARED_COEFF, 0);
+ /* Don't debouce interrupts so we don't need SYSCLK */
+ snd_soc_update_bits(codec, WM8962_IRQ_DEBOUNCE,
+ WM8962_FLL_LOCK_DB | WM8962_PLL3_LOCK_DB |
+ WM8962_PLL2_LOCK_DB | WM8962_TEMP_SHUT_DB,
+ 0);
+
wm8962_add_widgets(codec);
/* Save boards having to disable DMIC when not in use */
@@ -3966,7 +3505,7 @@ static int wm8962_probe(struct snd_soc_codec *codec)
ret = request_threaded_irq(wm8962->irq, NULL, wm8962_irq,
trigger | IRQF_ONESHOT,
- "wm8962", codec);
+ "wm8962", codec->dev);
if (ret != 0) {
dev_err(codec->dev, "Failed to request IRQ %d: %d\n",
wm8962->irq, ret);
@@ -3983,13 +3522,6 @@ static int wm8962_probe(struct snd_soc_codec *codec)
}
return 0;
-
-err_enable:
- regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
-err:
- return ret;
}
static int wm8962_remove(struct snd_soc_codec *codec)
@@ -4007,7 +3539,6 @@ static int wm8962_remove(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
regulator_unregister_notifier(wm8962->supplies[i].consumer,
&wm8962->disable_nb[i]);
- regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
return 0;
}
@@ -4015,46 +3546,214 @@ static int wm8962_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_wm8962 = {
.probe = wm8962_probe,
.remove = wm8962_remove,
- .resume = wm8962_resume,
.set_bias_level = wm8962_set_bias_level,
- .reg_cache_size = WM8962_MAX_REGISTER + 1,
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8962_reg,
- .volatile_register = wm8962_volatile_register,
- .readable_register = wm8962_readable_register,
.set_pll = wm8962_set_fll,
+ .idle_bias_off = true,
+};
+
+/* Improve power consumption for IN4 DC measurement mode */
+static const struct reg_default wm8962_dc_measure[] = {
+ { 0xfd, 0x1 },
+ { 0xcc, 0x40 },
+ { 0xfd, 0 },
+};
+
+static const struct regmap_config wm8962_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .max_register = WM8962_MAX_REGISTER,
+ .reg_defaults = wm8962_reg,
+ .num_reg_defaults = ARRAY_SIZE(wm8962_reg),
+ .volatile_reg = wm8962_volatile_register,
+ .readable_reg = wm8962_readable_register,
+ .cache_type = REGCACHE_RBTREE,
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8962_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
+ struct wm8962_pdata *pdata = dev_get_platdata(&i2c->dev);
struct wm8962_priv *wm8962;
- int ret;
+ unsigned int reg;
+ int ret, i;
- wm8962 = kzalloc(sizeof(struct wm8962_priv), GFP_KERNEL);
+ wm8962 = devm_kzalloc(&i2c->dev, sizeof(struct wm8962_priv),
+ GFP_KERNEL);
if (wm8962 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8962);
+ INIT_DELAYED_WORK(&wm8962->mic_work, wm8962_mic_work);
+ init_completion(&wm8962->fll_lock);
wm8962->irq = i2c->irq;
+ for (i = 0; i < ARRAY_SIZE(wm8962->supplies); i++)
+ wm8962->supplies[i].supply = wm8962_supply_names[i];
+
+ ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+ goto err;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_get;
+ }
+
+ wm8962->regmap = regmap_init_i2c(i2c, &wm8962_regmap);
+ if (IS_ERR(wm8962->regmap)) {
+ ret = PTR_ERR(wm8962->regmap);
+ dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+ goto err_enable;
+ }
+
+ /*
+ * We haven't marked the chip revision as volatile due to
+ * sharing a register with the right input volume; explicitly
+ * bypass the cache to read it.
+ */
+ regcache_cache_bypass(wm8962->regmap, true);
+
+ ret = regmap_read(wm8962->regmap, WM8962_SOFTWARE_RESET, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read ID register\n");
+ goto err_regmap;
+ }
+ if (reg != 0x6243) {
+ dev_err(&i2c->dev,
+ "Device is not a WM8962, ID %x != 0x6243\n", reg);
+ ret = -EINVAL;
+ goto err_regmap;
+ }
+
+ ret = regmap_read(wm8962->regmap, WM8962_RIGHT_INPUT_VOLUME, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read device revision: %d\n",
+ ret);
+ goto err_regmap;
+ }
+
+ dev_info(&i2c->dev, "customer id %x revision %c\n",
+ (reg & WM8962_CUST_ID_MASK) >> WM8962_CUST_ID_SHIFT,
+ ((reg & WM8962_CHIP_REV_MASK) >> WM8962_CHIP_REV_SHIFT)
+ + 'A');
+
+ regcache_cache_bypass(wm8962->regmap, false);
+
+ ret = wm8962_reset(wm8962);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to issue reset\n");
+ goto err_regmap;
+ }
+
+ if (pdata && pdata->in4_dc_measure) {
+ ret = regmap_register_patch(wm8962->regmap,
+ wm8962_dc_measure,
+ ARRAY_SIZE(wm8962_dc_measure));
+ if (ret != 0)
+ dev_err(&i2c->dev,
+ "Failed to configure for DC mesurement: %d\n",
+ ret);
+ }
+
+ pm_runtime_enable(&i2c->dev);
+ pm_request_idle(&i2c->dev);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8962, &wm8962_dai, 1);
if (ret < 0)
- kfree(wm8962);
+ goto err_regmap;
+
+ /* The drivers should power up as needed */
+ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+
+ return 0;
+err_regmap:
+ regmap_exit(wm8962->regmap);
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err_get:
+ regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
+err:
return ret;
}
static __devexit int wm8962_i2c_remove(struct i2c_client *client)
{
+ struct wm8962_priv *wm8962 = dev_get_drvdata(&client->dev);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8962->regmap);
+ regulator_bulk_free(ARRAY_SIZE(wm8962->supplies), wm8962->supplies);
return 0;
}
+#ifdef CONFIG_PM_RUNTIME
+static int wm8962_runtime_resume(struct device *dev)
+{
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+ int ret;
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+ if (ret != 0) {
+ dev_err(dev,
+ "Failed to enable supplies: %d\n", ret);
+ return ret;
+ }
+
+ regcache_cache_only(wm8962->regmap, false);
+ regcache_sync(wm8962->regmap);
+
+ regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
+ WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA,
+ WM8962_STARTUP_BIAS_ENA | WM8962_VMID_BUF_ENA);
+
+ /* Bias enable at 2*50k for ramp */
+ regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA,
+ WM8962_BIAS_ENA | 0x180);
+
+ msleep(5);
+
+ /* VMID back to 2x250k for standby */
+ regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK, 0x100);
+
+ return 0;
+}
+
+static int wm8962_runtime_suspend(struct device *dev)
+{
+ struct wm8962_priv *wm8962 = dev_get_drvdata(dev);
+
+ regmap_update_bits(wm8962->regmap, WM8962_PWR_MGMT_1,
+ WM8962_VMID_SEL_MASK | WM8962_BIAS_ENA, 0);
+
+ regmap_update_bits(wm8962->regmap, WM8962_ANTI_POP,
+ WM8962_STARTUP_BIAS_ENA |
+ WM8962_VMID_BUF_ENA, 0);
+
+ regcache_cache_only(wm8962->regmap, true);
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8962->supplies),
+ wm8962->supplies);
+
+ return 0;
+}
+#endif
+
+static struct dev_pm_ops wm8962_pm = {
+ SET_RUNTIME_PM_OPS(wm8962_runtime_suspend, wm8962_runtime_resume, NULL)
+};
+
static const struct i2c_device_id wm8962_i2c_id[] = {
{ "wm8962", 0 },
{ }
@@ -4065,34 +3764,14 @@ static struct i2c_driver wm8962_i2c_driver = {
.driver = {
.name = "wm8962",
.owner = THIS_MODULE,
+ .pm = &wm8962_pm,
},
.probe = wm8962_i2c_probe,
.remove = __devexit_p(wm8962_i2c_remove),
.id_table = wm8962_i2c_id,
};
-#endif
-static int __init wm8962_modinit(void)
-{
- int ret;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- ret = i2c_add_driver(&wm8962_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register WM8962 I2C driver: %d\n",
- ret);
- }
-#endif
- return 0;
-}
-module_init(wm8962_modinit);
-
-static void __exit wm8962_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&wm8962_i2c_driver);
-#endif
-}
-module_exit(wm8962_exit);
+module_i2c_driver(wm8962_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8962 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 572bb80627a4..28fe59e3ce01 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -19,7 +19,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -224,7 +223,7 @@ static const struct snd_soc_dapm_widget wm8971_dapm_widgets[] = {
SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8971_PWR2, 8, 0),
SND_SOC_DAPM_PGA("Mono Out 1", WM8971_PWR2, 2, 0, NULL, 0),
- SND_SOC_DAPM_MICBIAS("Mic Bias", WM8971_PWR1, 1, 0),
+ SND_SOC_DAPM_SUPPLY("Mic Bias", WM8971_PWR1, 1, 0, NULL, 0),
SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8971_PWR1, 2, 0),
SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8971_PWR1, 3, 0),
@@ -253,7 +252,7 @@ static const struct snd_soc_dapm_widget wm8971_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("MIC"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8971_dapm_routes[] = {
/* left mixer */
{"Left Mixer", "Playback Switch", "Left DAC"},
{"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
@@ -330,17 +329,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Right ADC", NULL, "Right ADC Mux"},
};
-static int wm8971_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8971_dapm_widgets,
- ARRAY_SIZE(wm8971_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
struct _coeff_div {
u32 mclk;
u32 rate;
@@ -546,6 +534,9 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_PREPARE:
break;
case SND_SOC_BIAS_STANDBY:
+ if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+ snd_soc_cache_sync(codec);
+
/* mute dac and set vmid to 500k, enable VREF */
snd_soc_write(codec, WM8971_PWR1, pwr_reg | 0x0140);
break;
@@ -564,7 +555,7 @@ static int wm8971_set_bias_level(struct snd_soc_codec *codec,
#define WM8971_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8971_dai_ops = {
+static const struct snd_soc_dai_ops wm8971_dai_ops = {
.hw_params = wm8971_pcm_hw_params,
.digital_mute = wm8971_mute,
.set_fmt = wm8971_set_dai_fmt,
@@ -597,7 +588,7 @@ static void wm8971_work(struct work_struct *work)
wm8971_set_bias_level(codec, codec->dapm.bias_level);
}
-static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8971_suspend(struct snd_soc_codec *codec)
{
wm8971_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -605,20 +596,8 @@ static int wm8971_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8971_resume(struct snd_soc_codec *codec)
{
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
u16 reg;
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8971_reg); i++) {
- if (i + 1 == WM8971_RESET)
- continue;
- data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
-
wm8971_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
/* charge wm8971 caps */
@@ -660,29 +639,14 @@ static int wm8971_probe(struct snd_soc_codec *codec)
msecs_to_jiffies(1000));
/* set the update bits */
- reg = snd_soc_read(codec, WM8971_LDAC);
- snd_soc_write(codec, WM8971_LDAC, reg | 0x0100);
- reg = snd_soc_read(codec, WM8971_RDAC);
- snd_soc_write(codec, WM8971_RDAC, reg | 0x0100);
-
- reg = snd_soc_read(codec, WM8971_LOUT1V);
- snd_soc_write(codec, WM8971_LOUT1V, reg | 0x0100);
- reg = snd_soc_read(codec, WM8971_ROUT1V);
- snd_soc_write(codec, WM8971_ROUT1V, reg | 0x0100);
-
- reg = snd_soc_read(codec, WM8971_LOUT2V);
- snd_soc_write(codec, WM8971_LOUT2V, reg | 0x0100);
- reg = snd_soc_read(codec, WM8971_ROUT2V);
- snd_soc_write(codec, WM8971_ROUT2V, reg | 0x0100);
-
- reg = snd_soc_read(codec, WM8971_LINVOL);
- snd_soc_write(codec, WM8971_LINVOL, reg | 0x0100);
- reg = snd_soc_read(codec, WM8971_RINVOL);
- snd_soc_write(codec, WM8971_RINVOL, reg | 0x0100);
-
- snd_soc_add_controls(codec, wm8971_snd_controls,
- ARRAY_SIZE(wm8971_snd_controls));
- wm8971_add_widgets(codec);
+ snd_soc_update_bits(codec, WM8971_LDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8971_RDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8971_LOUT1V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8971_ROUT1V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8971_LOUT2V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8971_ROUT2V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8971_LINVOL, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8971_RINVOL, 0x0100, 0x0100);
return ret;
}
@@ -707,16 +671,23 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8971 = {
.reg_cache_size = ARRAY_SIZE(wm8971_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8971_reg,
+
+ .controls = wm8971_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8971_snd_controls),
+ .dapm_widgets = wm8971_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8971_dapm_widgets),
+ .dapm_routes = wm8971_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8971_dapm_routes),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8971_priv *wm8971;
int ret;
- wm8971 = kzalloc(sizeof(struct wm8971_priv), GFP_KERNEL);
+ wm8971 = devm_kzalloc(&i2c->dev, sizeof(struct wm8971_priv),
+ GFP_KERNEL);
if (wm8971 == NULL)
return -ENOMEM;
@@ -725,15 +696,13 @@ static __devinit int wm8971_i2c_probe(struct i2c_client *i2c,
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8971, &wm8971_dai, 1);
- if (ret < 0)
- kfree(wm8971);
+
return ret;
}
static __devexit int wm8971_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
return 0;
}
@@ -745,34 +714,29 @@ MODULE_DEVICE_TABLE(i2c, wm8971_i2c_id);
static struct i2c_driver wm8971_i2c_driver = {
.driver = {
- .name = "wm8971-codec",
+ .name = "wm8971",
.owner = THIS_MODULE,
},
.probe = wm8971_i2c_probe,
.remove = __devexit_p(wm8971_i2c_remove),
.id_table = wm8971_i2c_id,
};
-#endif
static int __init wm8971_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8971_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8971_modinit);
static void __exit wm8971_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8971_i2c_driver);
-#endif
}
module_exit(wm8971_exit);
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c
index ca646a822444..d93c03f820c9 100644
--- a/sound/soc/codecs/wm8974.c
+++ b/sound/soc/codecs/wm8974.c
@@ -3,7 +3,7 @@
*
* Copyright 2006-2009 Wolfson Microelectronics PLC.
*
- * Author: Liam Girdwood <linux@wolfsonmicro.com>
+ * Author: Liam Girdwood <Liam.Girdwood@wolfsonmicro.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -17,7 +17,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -49,10 +48,6 @@ static const u16 wm8974_reg[WM8974_CACHEREGNUM] = {
#define WM8974_POWER1_BIASEN 0x08
#define WM8974_POWER1_BUFIOEN 0x04
-struct wm8974_priv {
- enum snd_soc_control_type control_type;
-};
-
#define wm8974_reset(c) snd_soc_write(c, WM8974_RESET, 0)
static const char *wm8974_companding[] = {"Off", "NC", "u-law", "A-law" };
@@ -226,7 +221,7 @@ SND_SOC_DAPM_MIXER("Input PGA", WM8974_POWER2, 2, 0, wm8974_inpga,
SND_SOC_DAPM_MIXER("Boost Mixer", WM8974_POWER2, 4, 0,
wm8974_boost_mixer, ARRAY_SIZE(wm8974_boost_mixer)),
-SND_SOC_DAPM_MICBIAS("Mic Bias", WM8974_POWER1, 4, 0),
+SND_SOC_DAPM_SUPPLY("Mic Bias", WM8974_POWER1, 4, 0, NULL, 0),
SND_SOC_DAPM_INPUT("MICN"),
SND_SOC_DAPM_INPUT("MICP"),
@@ -236,7 +231,7 @@ SND_SOC_DAPM_OUTPUT("SPKOUTP"),
SND_SOC_DAPM_OUTPUT("SPKOUTN"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8974_dapm_routes[] = {
/* Mono output mixer */
{"Mono Mixer", "PCM Playback Switch", "DAC"},
{"Mono Mixer", "Aux Playback Switch", "Aux Input"},
@@ -270,17 +265,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Aux Input", NULL, "AUX"},
};
-static int wm8974_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8974_dapm_widgets,
- ARRAY_SIZE(wm8974_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
struct pll_ {
unsigned int pre_div:1;
unsigned int n:4;
@@ -530,6 +514,8 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec,
power1 |= WM8974_POWER1_BIASEN | WM8974_POWER1_BUFIOEN;
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ snd_soc_cache_sync(codec);
+
/* Initial cap charge at VMID 5k */
snd_soc_write(codec, WM8974_POWER1, power1 | 0x3);
mdelay(100);
@@ -555,7 +541,7 @@ static int wm8974_set_bias_level(struct snd_soc_codec *codec,
#define WM8974_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8974_ops = {
+static const struct snd_soc_dai_ops wm8974_ops = {
.hw_params = wm8974_pcm_hw_params,
.digital_mute = wm8974_mute,
.set_fmt = wm8974_set_dai_fmt,
@@ -581,7 +567,7 @@ static struct snd_soc_dai_driver wm8974_dai = {
.symmetric_rates = 1,
};
-static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8974_suspend(struct snd_soc_codec *codec)
{
wm8974_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -589,18 +575,7 @@ static int wm8974_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8974_resume(struct snd_soc_codec *codec)
{
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8974_reg); i++) {
- data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
return 0;
}
@@ -621,9 +596,6 @@ static int wm8974_probe(struct snd_soc_codec *codec)
}
wm8974_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8974_snd_controls,
- ARRAY_SIZE(wm8974_snd_controls));
- wm8974_add_widgets(codec);
return ret;
}
@@ -644,32 +616,30 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8974 = {
.reg_cache_size = ARRAY_SIZE(wm8974_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8974_reg,
+
+ .controls = wm8974_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8974_snd_controls),
+ .dapm_widgets = wm8974_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8974_dapm_widgets),
+ .dapm_routes = wm8974_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8974_dapm_routes),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8974_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
- struct wm8974_priv *wm8974;
int ret;
- wm8974 = kzalloc(sizeof(struct wm8974_priv), GFP_KERNEL);
- if (wm8974 == NULL)
- return -ENOMEM;
-
- i2c_set_clientdata(i2c, wm8974);
-
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8974, &wm8974_dai, 1);
- if (ret < 0)
- kfree(wm8974);
+
return ret;
}
static __devexit int wm8974_i2c_remove(struct i2c_client *client)
{
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+
return 0;
}
@@ -681,34 +651,29 @@ MODULE_DEVICE_TABLE(i2c, wm8974_i2c_id);
static struct i2c_driver wm8974_i2c_driver = {
.driver = {
- .name = "wm8974-codec",
+ .name = "wm8974",
.owner = THIS_MODULE,
},
.probe = wm8974_i2c_probe,
.remove = __devexit_p(wm8974_i2c_remove),
.id_table = wm8974_i2c_id,
};
-#endif
static int __init wm8974_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8974_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8974_modinit);
static void __exit wm8974_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8974_i2c_driver);
-#endif
}
module_exit(wm8974_exit);
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c
index 85e3e630e763..72d5fdcd3cc2 100644
--- a/sound/soc/codecs/wm8978.c
+++ b/sound/soc/codecs/wm8978.c
@@ -18,7 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -30,29 +30,74 @@
#include "wm8978.h"
-/* wm8978 register cache. Note that register 0 is not included in the cache. */
-static const u16 wm8978_reg[WM8978_CACHEREGNUM] = {
- 0x0000, 0x0000, 0x0000, 0x0000, /* 0x00...0x03 */
- 0x0050, 0x0000, 0x0140, 0x0000, /* 0x04...0x07 */
- 0x0000, 0x0000, 0x0000, 0x00ff, /* 0x08...0x0b */
- 0x00ff, 0x0000, 0x0100, 0x00ff, /* 0x0c...0x0f */
- 0x00ff, 0x0000, 0x012c, 0x002c, /* 0x10...0x13 */
- 0x002c, 0x002c, 0x002c, 0x0000, /* 0x14...0x17 */
- 0x0032, 0x0000, 0x0000, 0x0000, /* 0x18...0x1b */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 0x1c...0x1f */
- 0x0038, 0x000b, 0x0032, 0x0000, /* 0x20...0x23 */
- 0x0008, 0x000c, 0x0093, 0x00e9, /* 0x24...0x27 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 0x28...0x2b */
- 0x0033, 0x0010, 0x0010, 0x0100, /* 0x2c...0x2f */
- 0x0100, 0x0002, 0x0001, 0x0001, /* 0x30...0x33 */
- 0x0039, 0x0039, 0x0039, 0x0039, /* 0x34...0x37 */
- 0x0001, 0x0001, /* 0x38...0x3b */
+static const struct reg_default wm8978_reg_defaults[] = {
+ { 1, 0x0000 },
+ { 2, 0x0000 },
+ { 3, 0x0000 },
+ { 4, 0x0050 },
+ { 5, 0x0000 },
+ { 6, 0x0140 },
+ { 7, 0x0000 },
+ { 8, 0x0000 },
+ { 9, 0x0000 },
+ { 10, 0x0000 },
+ { 11, 0x00ff },
+ { 12, 0x00ff },
+ { 13, 0x0000 },
+ { 14, 0x0100 },
+ { 15, 0x00ff },
+ { 16, 0x00ff },
+ { 17, 0x0000 },
+ { 18, 0x012c },
+ { 19, 0x002c },
+ { 20, 0x002c },
+ { 21, 0x002c },
+ { 22, 0x002c },
+ { 23, 0x0000 },
+ { 24, 0x0032 },
+ { 25, 0x0000 },
+ { 26, 0x0000 },
+ { 27, 0x0000 },
+ { 28, 0x0000 },
+ { 29, 0x0000 },
+ { 30, 0x0000 },
+ { 31, 0x0000 },
+ { 32, 0x0038 },
+ { 33, 0x000b },
+ { 34, 0x0032 },
+ { 35, 0x0000 },
+ { 36, 0x0008 },
+ { 37, 0x000c },
+ { 38, 0x0093 },
+ { 39, 0x00e9 },
+ { 40, 0x0000 },
+ { 41, 0x0000 },
+ { 42, 0x0000 },
+ { 43, 0x0000 },
+ { 44, 0x0033 },
+ { 45, 0x0010 },
+ { 46, 0x0010 },
+ { 47, 0x0100 },
+ { 48, 0x0100 },
+ { 49, 0x0002 },
+ { 50, 0x0001 },
+ { 51, 0x0001 },
+ { 52, 0x0039 },
+ { 53, 0x0039 },
+ { 54, 0x0039 },
+ { 55, 0x0039 },
+ { 56, 0x0001 },
+ { 57, 0x0001 },
};
+static bool wm8978_volatile(struct device *dev, unsigned int reg)
+{
+ return reg == WM8978_RESET;
+}
+
/* codec private data */
struct wm8978_priv {
- enum snd_soc_control_type control_type;
- void *control_data;
+ struct regmap *regmap;
unsigned int f_pllout;
unsigned int f_mclk;
unsigned int f_256fs;
@@ -305,7 +350,7 @@ static const struct snd_soc_dapm_widget wm8978_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("RSPK"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8978_dapm_routes[] = {
/* Output mixer */
{"Right Output Mixer", "PCM Playback Switch", "Right DAC"},
{"Right Output Mixer", "Aux Playback Switch", "RAUX"},
@@ -354,18 +399,6 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"Left Input Mixer", "MicP Switch", "LMICP"},
};
-static int wm8978_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8978_dapm_widgets,
- ARRAY_SIZE(wm8978_dapm_widgets));
- /* set up the WM8978 audio map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- return 0;
-}
-
/* PLL divisors */
struct wm8978_pll_div {
u32 k;
@@ -866,7 +899,7 @@ static int wm8978_set_bias_level(struct snd_soc_codec *codec,
#define WM8978_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8978_dai_ops = {
+static const struct snd_soc_dai_ops wm8978_dai_ops = {
.hw_params = wm8978_hw_params,
.digital_mute = wm8978_mute,
.set_fmt = wm8978_set_dai_fmt,
@@ -894,28 +927,25 @@ static struct snd_soc_dai_driver wm8978_dai = {
.ops = &wm8978_dai_ops,
};
-static int wm8978_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8978_suspend(struct snd_soc_codec *codec)
{
+ struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
+
wm8978_set_bias_level(codec, SND_SOC_BIAS_OFF);
/* Also switch PLL off */
snd_soc_write(codec, WM8978_POWER_MANAGEMENT_1, 0);
+ regcache_mark_dirty(wm8978->regmap);
+
return 0;
}
static int wm8978_resume(struct snd_soc_codec *codec)
{
struct wm8978_priv *wm8978 = snd_soc_codec_get_drvdata(codec);
- int i;
- u16 *cache = codec->reg_cache;
/* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8978_reg); i++) {
- if (i == WM8978_RESET)
- continue;
- if (cache[i] != wm8978_reg[i])
- snd_soc_write(codec, i, cache[i]);
- }
+ regcache_sync(wm8978->regmap);
wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
@@ -955,8 +985,8 @@ static int wm8978_probe(struct snd_soc_codec *codec)
* default hardware setting
*/
wm8978->sysclk = WM8978_PLL;
- codec->control_data = wm8978->control_data;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_I2C);
+ codec->control_data = wm8978->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -970,19 +1000,8 @@ static int wm8978_probe(struct snd_soc_codec *codec)
for (i = 0; i < ARRAY_SIZE(update_reg); i++)
snd_soc_update_bits(codec, update_reg[i], 0x100, 0x100);
- /* Reset the codec */
- ret = snd_soc_write(codec, WM8978_RESET, 0);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- return ret;
- }
-
wm8978_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8978_snd_controls,
- ARRAY_SIZE(wm8978_snd_controls));
- wm8978_add_widgets(codec);
-
return 0;
}
@@ -999,36 +1018,75 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8978 = {
.suspend = wm8978_suspend,
.resume = wm8978_resume,
.set_bias_level = wm8978_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8978_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8978_reg,
+
+ .controls = wm8978_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8978_snd_controls),
+ .dapm_widgets = wm8978_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8978_dapm_widgets),
+ .dapm_routes = wm8978_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8978_dapm_routes),
+};
+
+static const struct regmap_config wm8978_regmap_config = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8978_MAX_REGISTER,
+ .volatile_reg = wm8978_volatile,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8978_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8978_reg_defaults),
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8978_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8978_priv *wm8978;
int ret;
- wm8978 = kzalloc(sizeof(struct wm8978_priv), GFP_KERNEL);
+ wm8978 = devm_kzalloc(&i2c->dev, sizeof(struct wm8978_priv),
+ GFP_KERNEL);
if (wm8978 == NULL)
return -ENOMEM;
+ wm8978->regmap = regmap_init_i2c(i2c, &wm8978_regmap_config);
+ if (IS_ERR(wm8978->regmap)) {
+ ret = PTR_ERR(wm8978->regmap);
+ dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, wm8978);
- wm8978->control_data = i2c;
+
+ /* Reset the codec */
+ ret = regmap_write(wm8978->regmap, WM8978_RESET, 0);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to issue reset: %d\n", ret);
+ goto err;
+ }
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8978, &wm8978_dai, 1);
- if (ret < 0)
- kfree(wm8978);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ regmap_exit(wm8978->regmap);
return ret;
}
static __devexit int wm8978_i2c_remove(struct i2c_client *client)
{
+ struct wm8978_priv *wm8978 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8978->regmap);
+
return 0;
}
@@ -1047,27 +1105,22 @@ static struct i2c_driver wm8978_i2c_driver = {
.remove = __devexit_p(wm8978_i2c_remove),
.id_table = wm8978_i2c_id,
};
-#endif
static int __init wm8978_modinit(void)
{
int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
ret = i2c_add_driver(&wm8978_i2c_driver);
if (ret != 0) {
printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n",
ret);
}
-#endif
return ret;
}
module_init(wm8978_modinit);
static void __exit wm8978_exit(void)
{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
i2c_del_driver(&wm8978_i2c_driver);
-#endif
}
module_exit(wm8978_exit);
diff --git a/sound/soc/codecs/wm8978.h b/sound/soc/codecs/wm8978.h
index c75525b7f154..6ae43495b7cf 100644
--- a/sound/soc/codecs/wm8978.h
+++ b/sound/soc/codecs/wm8978.h
@@ -67,6 +67,8 @@
#define WM8978_OUT3_MIXER_CONTROL 0x38
#define WM8978_OUT4_MIXER_CONTROL 0x39
+#define WM8978_MAX_REGISTER 0x39
+
#define WM8978_CACHEREGNUM 58
/* Clock divider Id's */
diff --git a/sound/soc/codecs/wm8983.c b/sound/soc/codecs/wm8983.c
index 17f04ec2b940..367388fdc486 100644
--- a/sound/soc/codecs/wm8983.c
+++ b/sound/soc/codecs/wm8983.c
@@ -249,9 +249,6 @@ static const char *eq5_cutoff_text[] = {
static const SOC_ENUM_SINGLE_DECL(eq5_cutoff, WM8983_EQ5_HIGH_SHELF, 5,
eq5_cutoff_text);
-static const char *speaker_mode_text[] = { "Class A/B", "Class D" };
-static const SOC_ENUM_SINGLE_DECL(speaker_mode, 0x17, 8, speaker_mode_text);
-
static const char *depth_3d_text[] = {
"Off",
"6.67%",
@@ -369,8 +366,6 @@ static const struct snd_kcontrol_new wm8983_snd_controls[] = {
SOC_SINGLE_TLV("EQ5 Volume", WM8983_EQ5_HIGH_SHELF, 0, 24, 1, eq_tlv),
SOC_ENUM("3D Depth", depth_3d),
-
- SOC_ENUM("Speaker Mode", speaker_mode)
};
static const struct snd_kcontrol_new left_out_mixer[] = {
@@ -481,7 +476,8 @@ static const struct snd_soc_dapm_widget wm8983_dapm_widgets[] = {
SND_SOC_DAPM_PGA("OUT4 Out", WM8983_POWER_MANAGEMENT_3,
8, 0, NULL, 0),
- SND_SOC_DAPM_MICBIAS("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0),
+ SND_SOC_DAPM_SUPPLY("Mic Bias", WM8983_POWER_MANAGEMENT_1, 4, 0,
+ NULL, 0),
SND_SOC_DAPM_INPUT("LIN"),
SND_SOC_DAPM_INPUT("LIP"),
@@ -973,7 +969,7 @@ static int wm8983_set_bias_level(struct snd_soc_codec *codec,
}
#ifdef CONFIG_PM
-static int wm8983_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8983_suspend(struct snd_soc_codec *codec)
{
wm8983_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -1007,7 +1003,7 @@ static int wm8983_probe(struct snd_soc_codec *codec)
return ret;
}
- ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0x8983);
+ ret = snd_soc_write(codec, WM8983_SOFTWARE_RESET, 0);
if (ret < 0) {
dev_err(codec->dev, "Failed to issue reset: %d\n", ret);
return ret;
@@ -1034,7 +1030,7 @@ static int wm8983_probe(struct snd_soc_codec *codec)
return 0;
}
-static struct snd_soc_dai_ops wm8983_dai_ops = {
+static const struct snd_soc_dai_ops wm8983_dai_ops = {
.digital_mute = wm8983_dac_mute,
.hw_params = wm8983_hw_params,
.set_fmt = wm8983_set_fmt,
diff --git a/sound/soc/codecs/wm8985.c b/sound/soc/codecs/wm8985.c
index bae510acdec8..14f666398d0c 100644
--- a/sound/soc/codecs/wm8985.c
+++ b/sound/soc/codecs/wm8985.c
@@ -19,6 +19,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -39,73 +40,127 @@ static const char *wm8985_supply_names[WM8985_NUM_SUPPLIES] = {
"AVDD2"
};
-static const u16 wm8985_reg_defs[] = {
- 0x0000, /* R0 - Software Reset */
- 0x0000, /* R1 - Power management 1 */
- 0x0000, /* R2 - Power management 2 */
- 0x0000, /* R3 - Power management 3 */
- 0x0050, /* R4 - Audio Interface */
- 0x0000, /* R5 - Companding control */
- 0x0140, /* R6 - Clock Gen control */
- 0x0000, /* R7 - Additional control */
- 0x0000, /* R8 - GPIO Control */
- 0x0000, /* R9 - Jack Detect Control 1 */
- 0x0000, /* R10 - DAC Control */
- 0x00FF, /* R11 - Left DAC digital Vol */
- 0x00FF, /* R12 - Right DAC digital vol */
- 0x0000, /* R13 - Jack Detect Control 2 */
- 0x0100, /* R14 - ADC Control */
- 0x00FF, /* R15 - Left ADC Digital Vol */
- 0x00FF, /* R16 - Right ADC Digital Vol */
- 0x0000, /* R17 */
- 0x012C, /* R18 - EQ1 - low shelf */
- 0x002C, /* R19 - EQ2 - peak 1 */
- 0x002C, /* R20 - EQ3 - peak 2 */
- 0x002C, /* R21 - EQ4 - peak 3 */
- 0x002C, /* R22 - EQ5 - high shelf */
- 0x0000, /* R23 */
- 0x0032, /* R24 - DAC Limiter 1 */
- 0x0000, /* R25 - DAC Limiter 2 */
- 0x0000, /* R26 */
- 0x0000, /* R27 - Notch Filter 1 */
- 0x0000, /* R28 - Notch Filter 2 */
- 0x0000, /* R29 - Notch Filter 3 */
- 0x0000, /* R30 - Notch Filter 4 */
- 0x0000, /* R31 */
- 0x0038, /* R32 - ALC control 1 */
- 0x000B, /* R33 - ALC control 2 */
- 0x0032, /* R34 - ALC control 3 */
- 0x0000, /* R35 - Noise Gate */
- 0x0008, /* R36 - PLL N */
- 0x000C, /* R37 - PLL K 1 */
- 0x0093, /* R38 - PLL K 2 */
- 0x00E9, /* R39 - PLL K 3 */
- 0x0000, /* R40 */
- 0x0000, /* R41 - 3D control */
- 0x0000, /* R42 - OUT4 to ADC */
- 0x0000, /* R43 - Beep control */
- 0x0033, /* R44 - Input ctrl */
- 0x0010, /* R45 - Left INP PGA gain ctrl */
- 0x0010, /* R46 - Right INP PGA gain ctrl */
- 0x0100, /* R47 - Left ADC BOOST ctrl */
- 0x0100, /* R48 - Right ADC BOOST ctrl */
- 0x0002, /* R49 - Output ctrl */
- 0x0001, /* R50 - Left mixer ctrl */
- 0x0001, /* R51 - Right mixer ctrl */
- 0x0039, /* R52 - LOUT1 (HP) volume ctrl */
- 0x0039, /* R53 - ROUT1 (HP) volume ctrl */
- 0x0039, /* R54 - LOUT2 (SPK) volume ctrl */
- 0x0039, /* R55 - ROUT2 (SPK) volume ctrl */
- 0x0001, /* R56 - OUT3 mixer ctrl */
- 0x0001, /* R57 - OUT4 (MONO) mix ctrl */
- 0x0001, /* R58 */
- 0x0000, /* R59 */
- 0x0004, /* R60 - OUTPUT ctrl */
- 0x0000, /* R61 - BIAS CTRL */
- 0x0180, /* R62 */
- 0x0000 /* R63 */
+static const struct reg_default wm8985_reg_defaults[] = {
+ { 1, 0x0000 }, /* R1 - Power management 1 */
+ { 2, 0x0000 }, /* R2 - Power management 2 */
+ { 3, 0x0000 }, /* R3 - Power management 3 */
+ { 4, 0x0050 }, /* R4 - Audio Interface */
+ { 5, 0x0000 }, /* R5 - Companding control */
+ { 6, 0x0140 }, /* R6 - Clock Gen control */
+ { 7, 0x0000 }, /* R7 - Additional control */
+ { 8, 0x0000 }, /* R8 - GPIO Control */
+ { 9, 0x0000 }, /* R9 - Jack Detect Control 1 */
+ { 10, 0x0000 }, /* R10 - DAC Control */
+ { 11, 0x00FF }, /* R11 - Left DAC digital Vol */
+ { 12, 0x00FF }, /* R12 - Right DAC digital vol */
+ { 13, 0x0000 }, /* R13 - Jack Detect Control 2 */
+ { 14, 0x0100 }, /* R14 - ADC Control */
+ { 15, 0x00FF }, /* R15 - Left ADC Digital Vol */
+ { 16, 0x00FF }, /* R16 - Right ADC Digital Vol */
+ { 18, 0x012C }, /* R18 - EQ1 - low shelf */
+ { 19, 0x002C }, /* R19 - EQ2 - peak 1 */
+ { 20, 0x002C }, /* R20 - EQ3 - peak 2 */
+ { 21, 0x002C }, /* R21 - EQ4 - peak 3 */
+ { 22, 0x002C }, /* R22 - EQ5 - high shelf */
+ { 24, 0x0032 }, /* R24 - DAC Limiter 1 */
+ { 25, 0x0000 }, /* R25 - DAC Limiter 2 */
+ { 27, 0x0000 }, /* R27 - Notch Filter 1 */
+ { 28, 0x0000 }, /* R28 - Notch Filter 2 */
+ { 29, 0x0000 }, /* R29 - Notch Filter 3 */
+ { 30, 0x0000 }, /* R30 - Notch Filter 4 */
+ { 32, 0x0038 }, /* R32 - ALC control 1 */
+ { 33, 0x000B }, /* R33 - ALC control 2 */
+ { 34, 0x0032 }, /* R34 - ALC control 3 */
+ { 35, 0x0000 }, /* R35 - Noise Gate */
+ { 36, 0x0008 }, /* R36 - PLL N */
+ { 37, 0x000C }, /* R37 - PLL K 1 */
+ { 38, 0x0093 }, /* R38 - PLL K 2 */
+ { 39, 0x00E9 }, /* R39 - PLL K 3 */
+ { 41, 0x0000 }, /* R41 - 3D control */
+ { 42, 0x0000 }, /* R42 - OUT4 to ADC */
+ { 43, 0x0000 }, /* R43 - Beep control */
+ { 44, 0x0033 }, /* R44 - Input ctrl */
+ { 45, 0x0010 }, /* R45 - Left INP PGA gain ctrl */
+ { 46, 0x0010 }, /* R46 - Right INP PGA gain ctrl */
+ { 47, 0x0100 }, /* R47 - Left ADC BOOST ctrl */
+ { 48, 0x0100 }, /* R48 - Right ADC BOOST ctrl */
+ { 49, 0x0002 }, /* R49 - Output ctrl */
+ { 50, 0x0001 }, /* R50 - Left mixer ctrl */
+ { 51, 0x0001 }, /* R51 - Right mixer ctrl */
+ { 52, 0x0039 }, /* R52 - LOUT1 (HP) volume ctrl */
+ { 53, 0x0039 }, /* R53 - ROUT1 (HP) volume ctrl */
+ { 54, 0x0039 }, /* R54 - LOUT2 (SPK) volume ctrl */
+ { 55, 0x0039 }, /* R55 - ROUT2 (SPK) volume ctrl */
+ { 56, 0x0001 }, /* R56 - OUT3 mixer ctrl */
+ { 57, 0x0001 }, /* R57 - OUT4 (MONO) mix ctrl */
+ { 60, 0x0004 }, /* R60 - OUTPUT ctrl */
+ { 61, 0x0000 }, /* R61 - BIAS CTRL */
};
+static bool wm8985_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8985_SOFTWARE_RESET:
+ case WM8985_POWER_MANAGEMENT_1:
+ case WM8985_POWER_MANAGEMENT_2:
+ case WM8985_POWER_MANAGEMENT_3:
+ case WM8985_AUDIO_INTERFACE:
+ case WM8985_COMPANDING_CONTROL:
+ case WM8985_CLOCK_GEN_CONTROL:
+ case WM8985_ADDITIONAL_CONTROL:
+ case WM8985_GPIO_CONTROL:
+ case WM8985_JACK_DETECT_CONTROL_1:
+ case WM8985_DAC_CONTROL:
+ case WM8985_LEFT_DAC_DIGITAL_VOL:
+ case WM8985_RIGHT_DAC_DIGITAL_VOL:
+ case WM8985_JACK_DETECT_CONTROL_2:
+ case WM8985_ADC_CONTROL:
+ case WM8985_LEFT_ADC_DIGITAL_VOL:
+ case WM8985_RIGHT_ADC_DIGITAL_VOL:
+ case WM8985_EQ1_LOW_SHELF:
+ case WM8985_EQ2_PEAK_1:
+ case WM8985_EQ3_PEAK_2:
+ case WM8985_EQ4_PEAK_3:
+ case WM8985_EQ5_HIGH_SHELF:
+ case WM8985_DAC_LIMITER_1:
+ case WM8985_DAC_LIMITER_2:
+ case WM8985_NOTCH_FILTER_1:
+ case WM8985_NOTCH_FILTER_2:
+ case WM8985_NOTCH_FILTER_3:
+ case WM8985_NOTCH_FILTER_4:
+ case WM8985_ALC_CONTROL_1:
+ case WM8985_ALC_CONTROL_2:
+ case WM8985_ALC_CONTROL_3:
+ case WM8985_NOISE_GATE:
+ case WM8985_PLL_N:
+ case WM8985_PLL_K_1:
+ case WM8985_PLL_K_2:
+ case WM8985_PLL_K_3:
+ case WM8985_3D_CONTROL:
+ case WM8985_OUT4_TO_ADC:
+ case WM8985_BEEP_CONTROL:
+ case WM8985_INPUT_CTRL:
+ case WM8985_LEFT_INP_PGA_GAIN_CTRL:
+ case WM8985_RIGHT_INP_PGA_GAIN_CTRL:
+ case WM8985_LEFT_ADC_BOOST_CTRL:
+ case WM8985_RIGHT_ADC_BOOST_CTRL:
+ case WM8985_OUTPUT_CTRL0:
+ case WM8985_LEFT_MIXER_CTRL:
+ case WM8985_RIGHT_MIXER_CTRL:
+ case WM8985_LOUT1_HP_VOLUME_CTRL:
+ case WM8985_ROUT1_HP_VOLUME_CTRL:
+ case WM8985_LOUT2_SPK_VOLUME_CTRL:
+ case WM8985_ROUT2_SPK_VOLUME_CTRL:
+ case WM8985_OUT3_MIXER_CTRL:
+ case WM8985_OUT4_MONO_MIX_CTRL:
+ case WM8985_OUTPUT_CTRL1:
+ case WM8985_BIAS_CTRL:
+ return true;
+ default:
+ return false;
+ }
+}
+
/*
* latch bit 8 of these registers to ensure instant
* volume updates
@@ -124,7 +179,7 @@ static const int volume_update_regs[] = {
};
struct wm8985_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[WM8985_NUM_SUPPLIES];
unsigned int sysclk;
unsigned int bclk;
@@ -411,7 +466,8 @@ static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
SND_SOC_DAPM_PGA("Right Speaker Out", WM8985_POWER_MANAGEMENT_3,
6, 0, NULL, 0),
- SND_SOC_DAPM_MICBIAS("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0),
+ SND_SOC_DAPM_SUPPLY("Mic Bias", WM8985_POWER_MANAGEMENT_1, 4, 0,
+ NULL, 0),
SND_SOC_DAPM_INPUT("LIN"),
SND_SOC_DAPM_INPUT("LIP"),
@@ -427,7 +483,7 @@ static const struct snd_soc_dapm_widget wm8985_dapm_widgets[] = {
SND_SOC_DAPM_OUTPUT("SPKR")
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8985_dapm_routes[] = {
{ "Right Output Mixer", "PCM Switch", "Right DAC" },
{ "Right Output Mixer", "Aux Switch", "AUXR" },
{ "Right Output Mixer", "Line Switch", "Right Boost Mixer" },
@@ -530,17 +586,6 @@ static int eqmode_put(struct snd_kcontrol *kcontrol,
return 0;
}
-static int wm8985_add_widgets(struct snd_soc_codec *codec)
-{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_new_controls(dapm, wm8985_dapm_widgets,
- ARRAY_SIZE(wm8985_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map,
- ARRAY_SIZE(audio_map));
- return 0;
-}
-
static int wm8985_reset(struct snd_soc_codec *codec)
{
return snd_soc_write(codec, WM8985_SOFTWARE_RESET, 0x0);
@@ -844,25 +889,6 @@ static int wm8985_set_sysclk(struct snd_soc_dai *dai,
return 0;
}
-static void wm8985_sync_cache(struct snd_soc_codec *codec)
-{
- short i;
- u16 *cache;
-
- if (!codec->cache_sync)
- return;
- codec->cache_only = 0;
- /* restore cache */
- cache = codec->reg_cache;
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- if (i == WM8985_SOFTWARE_RESET
- || cache[i] == wm8985_reg_defs[i])
- continue;
- snd_soc_write(codec, i, cache[i]);
- }
- codec->cache_sync = 0;
-}
-
static int wm8985_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
@@ -889,7 +915,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
return ret;
}
- wm8985_sync_cache(codec);
+ regcache_sync(wm8985->regmap);
/* enable anti-pop features */
snd_soc_update_bits(codec, WM8985_OUT4_TO_ADC,
@@ -932,7 +958,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
snd_soc_write(codec, WM8985_POWER_MANAGEMENT_2, 0);
snd_soc_write(codec, WM8985_POWER_MANAGEMENT_3, 0);
- codec->cache_sync = 1;
+ regcache_mark_dirty(wm8985->regmap);
regulator_bulk_disable(ARRAY_SIZE(wm8985->supplies),
wm8985->supplies);
@@ -944,7 +970,7 @@ static int wm8985_set_bias_level(struct snd_soc_codec *codec,
}
#ifdef CONFIG_PM
-static int wm8985_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8985_suspend(struct snd_soc_codec *codec)
{
wm8985_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -975,11 +1001,11 @@ static int wm8985_probe(struct snd_soc_codec *codec)
size_t i;
struct wm8985_priv *wm8985;
int ret;
- u16 *cache;
wm8985 = snd_soc_codec_get_drvdata(codec);
+ codec->control_data = wm8985->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8985->control_type);
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
return ret;
@@ -1008,17 +1034,13 @@ static int wm8985_probe(struct snd_soc_codec *codec)
goto err_reg_enable;
}
- cache = codec->reg_cache;
/* latch volume update bits */
for (i = 0; i < ARRAY_SIZE(volume_update_regs); ++i)
- cache[volume_update_regs[i]] |= 0x100;
+ snd_soc_update_bits(codec, volume_update_regs[i],
+ 0x100, 0x100);
/* enable BIASCUT */
- cache[WM8985_BIAS_CTRL] |= WM8985_BIASCUT;
- codec->cache_sync = 1;
-
- snd_soc_add_controls(codec, wm8985_snd_controls,
- ARRAY_SIZE(wm8985_snd_controls));
- wm8985_add_widgets(codec);
+ snd_soc_update_bits(codec, WM8985_BIAS_CTRL, WM8985_BIASCUT,
+ WM8985_BIASCUT);
wm8985_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
@@ -1030,7 +1052,7 @@ err_reg_get:
return ret;
}
-static struct snd_soc_dai_ops wm8985_dai_ops = {
+static const struct snd_soc_dai_ops wm8985_dai_ops = {
.digital_mute = wm8985_dac_mute,
.hw_params = wm8985_hw_params,
.set_fmt = wm8985_set_fmt,
@@ -1067,9 +1089,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8985 = {
.suspend = wm8985_suspend,
.resume = wm8985_resume,
.set_bias_level = wm8985_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8985_reg_defs),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8985_reg_defs
+
+ .controls = wm8985_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8985_snd_controls),
+ .dapm_widgets = wm8985_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8985_dapm_widgets),
+ .dapm_routes = wm8985_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8985_dapm_routes),
+};
+
+static const struct regmap_config wm8985_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8985_MAX_REGISTER,
+ .writeable_reg = wm8985_writeable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8985_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8985_reg_defaults),
};
#if defined(CONFIG_SPI_MASTER)
@@ -1078,24 +1116,39 @@ static int __devinit wm8985_spi_probe(struct spi_device *spi)
struct wm8985_priv *wm8985;
int ret;
- wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+ wm8985 = devm_kzalloc(&spi->dev, sizeof *wm8985, GFP_KERNEL);
if (!wm8985)
return -ENOMEM;
- wm8985->control_type = SND_SOC_SPI;
spi_set_drvdata(spi, wm8985);
+ wm8985->regmap = regmap_init_spi(spi, &wm8985_regmap);
+ if (IS_ERR(wm8985->regmap)) {
+ ret = PTR_ERR(wm8985->regmap);
+ dev_err(&spi->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8985, &wm8985_dai, 1);
- if (ret < 0)
- kfree(wm8985);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(wm8985->regmap);
return ret;
}
static int __devexit wm8985_spi_remove(struct spi_device *spi)
{
+ struct wm8985_priv *wm8985 = spi_get_drvdata(spi);
+
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8985->regmap);
+
return 0;
}
@@ -1116,24 +1169,39 @@ static __devinit int wm8985_i2c_probe(struct i2c_client *i2c,
struct wm8985_priv *wm8985;
int ret;
- wm8985 = kzalloc(sizeof *wm8985, GFP_KERNEL);
+ wm8985 = devm_kzalloc(&i2c->dev, sizeof *wm8985, GFP_KERNEL);
if (!wm8985)
return -ENOMEM;
- wm8985->control_type = SND_SOC_I2C;
i2c_set_clientdata(i2c, wm8985);
+ wm8985->regmap = regmap_init_i2c(i2c, &wm8985_regmap);
+ if (IS_ERR(wm8985->regmap)) {
+ ret = PTR_ERR(wm8985->regmap);
+ dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
+ ret);
+ goto err;
+ }
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8985, &wm8985_dai, 1);
- if (ret < 0)
- kfree(wm8985);
+ if (ret != 0)
+ goto err;
+
+ return 0;
+
+err:
+ regmap_exit(wm8985->regmap);
return ret;
}
-static __devexit int wm8985_i2c_remove(struct i2c_client *client)
+static __devexit int wm8985_i2c_remove(struct i2c_client *i2c)
{
- snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ struct wm8985_priv *wm8985 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ regmap_exit(wm8985->regmap);
+
return 0;
}
diff --git a/sound/soc/codecs/wm8988.c b/sound/soc/codecs/wm8988.c
index d7170f1381aa..6cdf6a2bc283 100644
--- a/sound/soc/codecs/wm8988.c
+++ b/sound/soc/codecs/wm8988.c
@@ -18,7 +18,6 @@
#include <linux/pm.h>
#include <linux/i2c.h>
#include <linux/spi/spi.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -34,28 +33,92 @@
* We can't read the WM8988 register space when we
* are using 2 wire for device control, so we cache them instead.
*/
-static const u16 wm8988_reg[] = {
- 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
- 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
- 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
- 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
- 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
- 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
- 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
- 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
- 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
- 0x0079, 0x0079, 0x0079, /* 40 */
+static const struct reg_default wm8988_reg_defaults[] = {
+ { 0, 0x0097 },
+ { 1, 0x0097 },
+ { 2, 0x0079 },
+ { 3, 0x0079 },
+ { 5, 0x0008 },
+ { 7, 0x000a },
+ { 8, 0x0000 },
+ { 10, 0x00ff },
+ { 11, 0x00ff },
+ { 12, 0x000f },
+ { 13, 0x000f },
+ { 16, 0x0000 },
+ { 17, 0x007b },
+ { 18, 0x0000 },
+ { 19, 0x0032 },
+ { 20, 0x0000 },
+ { 21, 0x00c3 },
+ { 22, 0x00c3 },
+ { 23, 0x00c0 },
+ { 24, 0x0000 },
+ { 25, 0x0000 },
+ { 26, 0x0000 },
+ { 27, 0x0000 },
+ { 31, 0x0000 },
+ { 32, 0x0000 },
+ { 33, 0x0000 },
+ { 34, 0x0050 },
+ { 35, 0x0050 },
+ { 36, 0x0050 },
+ { 37, 0x0050 },
+ { 40, 0x0079 },
+ { 41, 0x0079 },
+ { 42, 0x0079 },
};
+static bool wm8988_writeable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8988_LINVOL:
+ case WM8988_RINVOL:
+ case WM8988_LOUT1V:
+ case WM8988_ROUT1V:
+ case WM8988_ADCDAC:
+ case WM8988_IFACE:
+ case WM8988_SRATE:
+ case WM8988_LDAC:
+ case WM8988_RDAC:
+ case WM8988_BASS:
+ case WM8988_TREBLE:
+ case WM8988_RESET:
+ case WM8988_3D:
+ case WM8988_ALC1:
+ case WM8988_ALC2:
+ case WM8988_ALC3:
+ case WM8988_NGATE:
+ case WM8988_LADC:
+ case WM8988_RADC:
+ case WM8988_ADCTL1:
+ case WM8988_ADCTL2:
+ case WM8988_PWR1:
+ case WM8988_PWR2:
+ case WM8988_ADCTL3:
+ case WM8988_ADCIN:
+ case WM8988_LADCIN:
+ case WM8988_RADCIN:
+ case WM8988_LOUTM1:
+ case WM8988_LOUTM2:
+ case WM8988_ROUTM1:
+ case WM8988_ROUTM2:
+ case WM8988_LOUT2V:
+ case WM8988_ROUT2V:
+ case WM8988_LPPB:
+ return true;
+ default:
+ return false;
+ }
+}
+
/* codec private data */
struct wm8988_priv {
+ struct regmap *regmap;
unsigned int sysclk;
- enum snd_soc_control_type control_type;
struct snd_pcm_hw_constraint_list *sysclk_constraints;
};
-
#define wm8988_reset(c) snd_soc_write(c, WM8988_RESET, 0)
/*
@@ -268,7 +331,7 @@ static const struct snd_kcontrol_new wm8988_monomux_controls =
SOC_DAPM_ENUM("Route", monomux);
static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
- SND_SOC_DAPM_MICBIAS("Mic Bias", WM8988_PWR1, 1, 0),
+ SND_SOC_DAPM_SUPPLY("Mic Bias", WM8988_PWR1, 1, 0, NULL, 0),
SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
&wm8988_diffmux_controls),
@@ -319,7 +382,7 @@ static const struct snd_soc_dapm_widget wm8988_dapm_widgets[] = {
SND_SOC_DAPM_INPUT("RINPUT2"),
};
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route wm8988_dapm_routes[] = {
{ "Left Line Mux", "Line 1", "LINPUT1" },
{ "Left Line Mux", "Line 2", "LINPUT2" },
@@ -663,6 +726,7 @@ static int wm8988_mute(struct snd_soc_dai *dai, int mute)
static int wm8988_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
+ struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
u16 pwr_reg = snd_soc_read(codec, WM8988_PWR1) & ~0x1c1;
switch (level) {
@@ -676,6 +740,8 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ regcache_sync(wm8988->regmap);
+
/* VREF, VMID=2x5k */
snd_soc_write(codec, WM8988_PWR1, pwr_reg | 0x1c1);
@@ -700,7 +766,7 @@ static int wm8988_set_bias_level(struct snd_soc_codec *codec,
#define WM8988_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8988_ops = {
+static const struct snd_soc_dai_ops wm8988_ops = {
.startup = wm8988_pcm_startup,
.hw_params = wm8988_pcm_hw_params,
.set_fmt = wm8988_set_dai_fmt,
@@ -728,40 +794,28 @@ static struct snd_soc_dai_driver wm8988_dai = {
.symmetric_rates = 1,
};
-static int wm8988_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8988_suspend(struct snd_soc_codec *codec)
{
+ struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
+
wm8988_set_bias_level(codec, SND_SOC_BIAS_OFF);
+ regcache_mark_dirty(wm8988->regmap);
return 0;
}
static int wm8988_resume(struct snd_soc_codec *codec)
{
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < WM8988_NUM_REG; i++) {
- if (i == WM8988_RESET)
- continue;
- data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
-
wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
return 0;
}
static int wm8988_probe(struct snd_soc_codec *codec)
{
struct wm8988_priv *wm8988 = snd_soc_codec_get_drvdata(codec);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret = 0;
- u16 reg;
- ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8988->control_type);
+ codec->control_data = wm8988->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 7, 9, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
@@ -774,25 +828,14 @@ static int wm8988_probe(struct snd_soc_codec *codec)
}
/* set the update bits (we always update left then right) */
- reg = snd_soc_read(codec, WM8988_RADC);
- snd_soc_write(codec, WM8988_RADC, reg | 0x100);
- reg = snd_soc_read(codec, WM8988_RDAC);
- snd_soc_write(codec, WM8988_RDAC, reg | 0x0100);
- reg = snd_soc_read(codec, WM8988_ROUT1V);
- snd_soc_write(codec, WM8988_ROUT1V, reg | 0x0100);
- reg = snd_soc_read(codec, WM8988_ROUT2V);
- snd_soc_write(codec, WM8988_ROUT2V, reg | 0x0100);
- reg = snd_soc_read(codec, WM8988_RINVOL);
- snd_soc_write(codec, WM8988_RINVOL, reg | 0x0100);
+ snd_soc_update_bits(codec, WM8988_RADC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8988_RDAC, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8988_ROUT1V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8988_ROUT2V, 0x0100, 0x0100);
+ snd_soc_update_bits(codec, WM8988_RINVOL, 0x0100, 0x0100);
wm8988_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm8988_snd_controls,
- ARRAY_SIZE(wm8988_snd_controls));
- snd_soc_dapm_new_controls(dapm, wm8988_dapm_widgets,
- ARRAY_SIZE(wm8988_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
return 0;
}
@@ -808,9 +851,25 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8988 = {
.suspend = wm8988_suspend,
.resume = wm8988_resume,
.set_bias_level = wm8988_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8988_reg),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8988_reg,
+
+ .controls = wm8988_snd_controls,
+ .num_controls = ARRAY_SIZE(wm8988_snd_controls),
+ .dapm_widgets = wm8988_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8988_dapm_widgets),
+ .dapm_routes = wm8988_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(wm8988_dapm_routes),
+};
+
+static struct regmap_config wm8988_regmap = {
+ .reg_bits = 7,
+ .val_bits = 9,
+
+ .max_register = WM8988_LPPB,
+ .writeable_reg = wm8988_writeable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8988_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8988_reg_defaults),
};
#if defined(CONFIG_SPI_MASTER)
@@ -819,30 +878,39 @@ static int __devinit wm8988_spi_probe(struct spi_device *spi)
struct wm8988_priv *wm8988;
int ret;
- wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+ wm8988 = devm_kzalloc(&spi->dev, sizeof(struct wm8988_priv),
+ GFP_KERNEL);
if (wm8988 == NULL)
return -ENOMEM;
- wm8988->control_type = SND_SOC_SPI;
+ wm8988->regmap = regmap_init_spi(spi, &wm8988_regmap);
+ if (IS_ERR(wm8988->regmap)) {
+ ret = PTR_ERR(wm8988->regmap);
+ dev_err(&spi->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
+
spi_set_drvdata(spi, wm8988);
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
- if (ret < 0)
- kfree(wm8988);
+ if (ret != 0)
+ regmap_exit(wm8988->regmap);
+
return ret;
}
static int __devexit wm8988_spi_remove(struct spi_device *spi)
{
+ struct wm8988_priv *wm8988 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8988->regmap);
return 0;
}
static struct spi_driver wm8988_spi_driver = {
.driver = {
- .name = "wm8988-codec",
+ .name = "wm8988",
.owner = THIS_MODULE,
},
.probe = wm8988_spi_probe,
@@ -857,24 +925,33 @@ static __devinit int wm8988_i2c_probe(struct i2c_client *i2c,
struct wm8988_priv *wm8988;
int ret;
- wm8988 = kzalloc(sizeof(struct wm8988_priv), GFP_KERNEL);
+ wm8988 = devm_kzalloc(&i2c->dev, sizeof(struct wm8988_priv),
+ GFP_KERNEL);
if (wm8988 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8988);
- wm8988->control_type = SND_SOC_I2C;
+
+ wm8988->regmap = regmap_init_i2c(i2c, &wm8988_regmap);
+ if (IS_ERR(wm8988->regmap)) {
+ ret = PTR_ERR(wm8988->regmap);
+ dev_err(&i2c->dev, "Failed to init regmap: %d\n", ret);
+ return ret;
+ }
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8988, &wm8988_dai, 1);
- if (ret < 0)
- kfree(wm8988);
+ if (ret != 0)
+ regmap_exit(wm8988->regmap);
+
return ret;
}
static __devexit int wm8988_i2c_remove(struct i2c_client *client)
{
+ struct wm8988_priv *wm8988 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8988->regmap);
return 0;
}
@@ -886,7 +963,7 @@ MODULE_DEVICE_TABLE(i2c, wm8988_i2c_id);
static struct i2c_driver wm8988_i2c_driver = {
.driver = {
- .name = "wm8988-codec",
+ .name = "wm8988",
.owner = THIS_MODULE,
},
.probe = wm8988_i2c_probe,
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 100aeee5ba96..9d242351e6e8 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -17,7 +17,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -36,10 +35,17 @@ struct wm8990_priv {
unsigned int pcmclk;
};
-/*
- * wm8990 register cache. Note that register 0 is not included in the
- * cache.
- */
+static int wm8990_volatile_register(struct snd_soc_codec *codec,
+ unsigned int reg)
+{
+ switch (reg) {
+ case WM8990_RESET:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
static const u16 wm8990_reg[] = {
0x8990, /* R0 - Reset */
0x0000, /* R1 - Power Management (1) */
@@ -394,7 +400,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
(1 << WM8990_AINRMUX_PWR_BIT))) {
reg |= WM8990_AINR_ENA;
} else {
- reg &= ~WM8990_AINL_ENA;
+ reg &= ~WM8990_AINR_ENA;
}
snd_soc_write(w->codec, WM8990_POWER_MANAGEMENT_2, reg);
@@ -769,8 +775,8 @@ SND_SOC_DAPM_PGA("ROPGA", WM8990_POWER_MANAGEMENT_3, WM8990_ROPGA_ENA_BIT, 0,
NULL, 0),
/* MICBIAS */
-SND_SOC_DAPM_MICBIAS("MICBIAS", WM8990_POWER_MANAGEMENT_1,
- WM8990_MICBIAS_ENA_BIT, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS", WM8990_POWER_MANAGEMENT_1,
+ WM8990_MICBIAS_ENA_BIT, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("LON"),
SND_SOC_DAPM_OUTPUT("LOP"),
@@ -974,7 +980,6 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int target,
static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
int source, unsigned int freq_in, unsigned int freq_out)
{
- u16 reg;
struct snd_soc_codec *codec = codec_dai->codec;
struct _pll_div pll_div;
@@ -982,13 +987,12 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
pll_factors(&pll_div, freq_out * 4, freq_in);
/* Turn on PLL */
- reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
- reg |= WM8990_PLL_ENA;
- snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+ snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
+ WM8990_PLL_ENA, WM8990_PLL_ENA);
/* sysclk comes from PLL */
- reg = snd_soc_read(codec, WM8990_CLOCKING_2);
- snd_soc_write(codec, WM8990_CLOCKING_2, reg | WM8990_SYSCLK_SRC);
+ snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+ WM8990_SYSCLK_SRC, WM8990_SYSCLK_SRC);
/* set up N , fractional mode and pre-divisor if necessary */
snd_soc_write(codec, WM8990_PLL1, pll_div.n | WM8990_SDM |
@@ -996,10 +1000,9 @@ static int wm8990_set_dai_pll(struct snd_soc_dai *codec_dai, int pll_id,
snd_soc_write(codec, WM8990_PLL2, (u8)(pll_div.k>>8));
snd_soc_write(codec, WM8990_PLL3, (u8)(pll_div.k & 0xFF));
} else {
- /* Turn on PLL */
- reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
- reg &= ~WM8990_PLL_ENA;
- snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg);
+ /* Turn off PLL */
+ snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
+ WM8990_PLL_ENA, 0);
}
return 0;
}
@@ -1077,28 +1080,23 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
int div_id, int div)
{
struct snd_soc_codec *codec = codec_dai->codec;
- u16 reg;
switch (div_id) {
case WM8990_MCLK_DIV:
- reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
- ~WM8990_MCLK_DIV_MASK;
- snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
+ snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+ WM8990_MCLK_DIV_MASK, div);
break;
case WM8990_DACCLK_DIV:
- reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
- ~WM8990_DAC_CLKDIV_MASK;
- snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
+ snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+ WM8990_DAC_CLKDIV_MASK, div);
break;
case WM8990_ADCCLK_DIV:
- reg = snd_soc_read(codec, WM8990_CLOCKING_2) &
- ~WM8990_ADC_CLKDIV_MASK;
- snd_soc_write(codec, WM8990_CLOCKING_2, reg | div);
+ snd_soc_update_bits(codec, WM8990_CLOCKING_2,
+ WM8990_ADC_CLKDIV_MASK, div);
break;
case WM8990_BCLK_DIV:
- reg = snd_soc_read(codec, WM8990_CLOCKING_1) &
- ~WM8990_BCLK_DIV_MASK;
- snd_soc_write(codec, WM8990_CLOCKING_1, reg | div);
+ snd_soc_update_bits(codec, WM8990_CLOCKING_1,
+ WM8990_BCLK_DIV_MASK, div);
break;
default:
return -EINVAL;
@@ -1156,7 +1154,7 @@ static int wm8990_mute(struct snd_soc_dai *dai, int mute)
static int wm8990_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 val;
+ int ret;
switch (level) {
case SND_SOC_BIAS_ON:
@@ -1164,13 +1162,18 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_PREPARE:
/* VMID=2*50k */
- val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
- ~WM8990_VMID_MODE_MASK;
- snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
+ snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1,
+ WM8990_VMID_MODE_MASK, 0x2);
break;
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ ret = snd_soc_cache_sync(codec);
+ if (ret < 0) {
+ dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
+ return ret;
+ }
+
/* Enable all output discharge bits */
snd_soc_write(codec, WM8990_ANTIPOP1, WM8990_DIS_LLINE |
WM8990_DIS_RLINE | WM8990_DIS_OUT3 |
@@ -1225,9 +1228,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
}
/* VMID=2*250k */
- val = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_1) &
- ~WM8990_VMID_MODE_MASK;
- snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
+ snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_1,
+ WM8990_VMID_MODE_MASK, 0x4);
break;
case SND_SOC_BIAS_OFF:
@@ -1241,8 +1243,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
WM8990_BUFIOEN);
/* mute DAC */
- val = snd_soc_read(codec, WM8990_DAC_CTRL);
- snd_soc_write(codec, WM8990_DAC_CTRL, val | WM8990_DAC_MUTE);
+ snd_soc_update_bits(codec, WM8990_DAC_CTRL,
+ WM8990_DAC_MUTE, WM8990_DAC_MUTE);
/* Enable any disabled outputs */
snd_soc_write(codec, WM8990_POWER_MANAGEMENT_1, 0x1f03);
@@ -1284,7 +1286,7 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
* 1. ADC/DAC on Primary Interface
* 2. ADC on Primary Interface/DAC on secondary
*/
-static struct snd_soc_dai_ops wm8990_dai_ops = {
+static const struct snd_soc_dai_ops wm8990_dai_ops = {
.hw_params = wm8990_hw_params,
.digital_mute = wm8990_mute,
.set_fmt = wm8990_set_dai_fmt,
@@ -1311,7 +1313,7 @@ static struct snd_soc_dai_driver wm8990_dai = {
.ops = &wm8990_dai_ops,
};
-static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8990_suspend(struct snd_soc_codec *codec)
{
wm8990_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -1319,19 +1321,6 @@ static int wm8990_suspend(struct snd_soc_codec *codec, pm_message_t state)
static int wm8990_resume(struct snd_soc_codec *codec)
{
- int i;
- u8 data[2];
- u16 *cache = codec->reg_cache;
-
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(wm8990_reg); i++) {
- if (i + 1 == WM8990_RESET)
- continue;
- data[0] = ((i + 1) << 1) | ((cache[i] >> 8) & 0x0001);
- data[1] = cache[i] & 0x00ff;
- codec->hw_write(codec->control_data, data, 2);
- }
-
wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
return 0;
}
@@ -1343,7 +1332,6 @@ static int wm8990_resume(struct snd_soc_codec *codec)
static int wm8990_probe(struct snd_soc_codec *codec)
{
int ret;
- u16 reg;
ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
if (ret < 0) {
@@ -1356,20 +1344,19 @@ static int wm8990_probe(struct snd_soc_codec *codec)
/* charge output caps */
wm8990_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- reg = snd_soc_read(codec, WM8990_AUDIO_INTERFACE_4);
- snd_soc_write(codec, WM8990_AUDIO_INTERFACE_4, reg | WM8990_ALRCGPIO1);
+ snd_soc_update_bits(codec, WM8990_AUDIO_INTERFACE_4,
+ WM8990_ALRCGPIO1, WM8990_ALRCGPIO1);
- reg = snd_soc_read(codec, WM8990_GPIO1_GPIO2) &
- ~WM8990_GPIO1_SEL_MASK;
- snd_soc_write(codec, WM8990_GPIO1_GPIO2, reg | 1);
+ snd_soc_update_bits(codec, WM8990_GPIO1_GPIO2,
+ WM8990_GPIO1_SEL_MASK, 1);
- reg = snd_soc_read(codec, WM8990_POWER_MANAGEMENT_2);
- snd_soc_write(codec, WM8990_POWER_MANAGEMENT_2, reg | WM8990_OPCLK_ENA);
+ snd_soc_update_bits(codec, WM8990_POWER_MANAGEMENT_2,
+ WM8990_OPCLK_ENA, WM8990_OPCLK_ENA);
snd_soc_write(codec, WM8990_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
snd_soc_write(codec, WM8990_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
- snd_soc_add_controls(codec, wm8990_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8990_snd_controls,
ARRAY_SIZE(wm8990_snd_controls));
wm8990_add_widgets(codec);
@@ -1392,6 +1379,7 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8990 = {
.reg_cache_size = ARRAY_SIZE(wm8990_reg),
.reg_word_size = sizeof(u16),
.reg_cache_default = wm8990_reg,
+ .volatile_register = wm8990_volatile_register,
};
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
@@ -1429,7 +1417,7 @@ MODULE_DEVICE_TABLE(i2c, wm8990_i2c_id);
static struct i2c_driver wm8990_i2c_driver = {
.driver = {
- .name = "wm8990-codec",
+ .name = "wm8990",
.owner = THIS_MODULE,
},
.probe = wm8990_i2c_probe,
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c
index 6af23d06870f..9ac31ba9b82e 100644
--- a/sound/soc/codecs/wm8991.c
+++ b/sound/soc/codecs/wm8991.c
@@ -3,7 +3,7 @@
*
* Copyright 2007-2010 Wolfson Microelectronics PLC.
* Author: Graeme Gregory
- * linux@wolfsonmicro.com
+ * Graeme.Gregory@wolfsonmicro.com
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -18,7 +18,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -393,7 +392,7 @@ static int inmixer_event(struct snd_soc_dapm_widget *w,
(1 << WM8991_AINRMUX_PWR_BIT)))
reg |= WM8991_AINR_ENA;
else
- reg &= ~WM8991_AINL_ENA;
+ reg &= ~WM8991_AINR_ENA;
snd_soc_write(w->codec, WM8991_POWER_MANAGEMENT_2, reg);
return 0;
@@ -770,8 +769,8 @@ static const struct snd_soc_dapm_widget wm8991_dapm_widgets[] = {
NULL, 0),
/* MICBIAS */
- SND_SOC_DAPM_MICBIAS("MICBIAS", WM8991_POWER_MANAGEMENT_1,
- WM8991_MICBIAS_ENA_BIT, 0),
+ SND_SOC_DAPM_SUPPLY("MICBIAS", WM8991_POWER_MANAGEMENT_1,
+ WM8991_MICBIAS_ENA_BIT, 0, NULL, 0),
SND_SOC_DAPM_OUTPUT("LON"),
SND_SOC_DAPM_OUTPUT("LOP"),
@@ -1241,7 +1240,7 @@ static int wm8991_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm8991_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8991_suspend(struct snd_soc_codec *codec)
{
wm8991_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -1264,7 +1263,6 @@ static int wm8991_probe(struct snd_soc_codec *codec)
{
struct wm8991_priv *wm8991;
int ret;
- unsigned int reg;
wm8991 = snd_soc_codec_get_drvdata(codec);
@@ -1282,25 +1280,24 @@ static int wm8991_probe(struct snd_soc_codec *codec)
wm8991_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- reg = snd_soc_read(codec, WM8991_AUDIO_INTERFACE_4);
- snd_soc_write(codec, WM8991_AUDIO_INTERFACE_4, reg | WM8991_ALRCGPIO1);
+ snd_soc_update_bits(codec, WM8991_AUDIO_INTERFACE_4,
+ WM8991_ALRCGPIO1, WM8991_ALRCGPIO1);
- reg = snd_soc_read(codec, WM8991_GPIO1_GPIO2) &
- ~WM8991_GPIO1_SEL_MASK;
- snd_soc_write(codec, WM8991_GPIO1_GPIO2, reg | 1);
+ snd_soc_update_bits(codec, WM8991_GPIO1_GPIO2,
+ WM8991_GPIO1_SEL_MASK, 1);
- reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_1);
- snd_soc_write(codec, WM8991_POWER_MANAGEMENT_1, reg | WM8991_VREF_ENA|
- WM8991_VMID_MODE_MASK);
+ snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_1,
+ WM8991_VREF_ENA | WM8991_VMID_MODE_MASK,
+ WM8991_VREF_ENA | WM8991_VMID_MODE_MASK);
- reg = snd_soc_read(codec, WM8991_POWER_MANAGEMENT_2);
- snd_soc_write(codec, WM8991_POWER_MANAGEMENT_2, reg | WM8991_OPCLK_ENA);
+ snd_soc_update_bits(codec, WM8991_POWER_MANAGEMENT_2,
+ WM8991_OPCLK_ENA, WM8991_OPCLK_ENA);
snd_soc_write(codec, WM8991_DAC_CTRL, 0);
snd_soc_write(codec, WM8991_LEFT_OUTPUT_VOLUME, 0x50 | (1<<8));
snd_soc_write(codec, WM8991_RIGHT_OUTPUT_VOLUME, 0x50 | (1<<8));
- snd_soc_add_controls(codec, wm8991_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8991_snd_controls,
ARRAY_SIZE(wm8991_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, wm8991_dapm_widgets,
@@ -1313,7 +1310,7 @@ static int wm8991_probe(struct snd_soc_codec *codec)
#define WM8991_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE)
-static struct snd_soc_dai_ops wm8991_ops = {
+static const struct snd_soc_dai_ops wm8991_ops = {
.hw_params = wm8991_hw_params,
.digital_mute = wm8991_mute,
.set_fmt = wm8991_set_dai_fmt,
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c
index 6e85b8869af7..d256a9340644 100644
--- a/sound/soc/codecs/wm8993.c
+++ b/sound/soc/codecs/wm8993.c
@@ -16,6 +16,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/spi/spi.h>
#include <linux/slab.h>
@@ -40,134 +41,113 @@ static const char *wm8993_supply_names[WM8993_NUM_SUPPLIES] = {
"SPKVDD",
};
-static u16 wm8993_reg_defaults[WM8993_REGISTER_COUNT] = {
- 0x8993, /* R0 - Software Reset */
- 0x0000, /* R1 - Power Management (1) */
- 0x6000, /* R2 - Power Management (2) */
- 0x0000, /* R3 - Power Management (3) */
- 0x4050, /* R4 - Audio Interface (1) */
- 0x4000, /* R5 - Audio Interface (2) */
- 0x01C8, /* R6 - Clocking 1 */
- 0x0000, /* R7 - Clocking 2 */
- 0x0000, /* R8 - Audio Interface (3) */
- 0x0040, /* R9 - Audio Interface (4) */
- 0x0004, /* R10 - DAC CTRL */
- 0x00C0, /* R11 - Left DAC Digital Volume */
- 0x00C0, /* R12 - Right DAC Digital Volume */
- 0x0000, /* R13 - Digital Side Tone */
- 0x0300, /* R14 - ADC CTRL */
- 0x00C0, /* R15 - Left ADC Digital Volume */
- 0x00C0, /* R16 - Right ADC Digital Volume */
- 0x0000, /* R17 */
- 0x0000, /* R18 - GPIO CTRL 1 */
- 0x0010, /* R19 - GPIO1 */
- 0x0000, /* R20 - IRQ_DEBOUNCE */
- 0x0000, /* R21 */
- 0x8000, /* R22 - GPIOCTRL 2 */
- 0x0800, /* R23 - GPIO_POL */
- 0x008B, /* R24 - Left Line Input 1&2 Volume */
- 0x008B, /* R25 - Left Line Input 3&4 Volume */
- 0x008B, /* R26 - Right Line Input 1&2 Volume */
- 0x008B, /* R27 - Right Line Input 3&4 Volume */
- 0x006D, /* R28 - Left Output Volume */
- 0x006D, /* R29 - Right Output Volume */
- 0x0066, /* R30 - Line Outputs Volume */
- 0x0020, /* R31 - HPOUT2 Volume */
- 0x0079, /* R32 - Left OPGA Volume */
- 0x0079, /* R33 - Right OPGA Volume */
- 0x0003, /* R34 - SPKMIXL Attenuation */
- 0x0003, /* R35 - SPKMIXR Attenuation */
- 0x0011, /* R36 - SPKOUT Mixers */
- 0x0100, /* R37 - SPKOUT Boost */
- 0x0079, /* R38 - Speaker Volume Left */
- 0x0079, /* R39 - Speaker Volume Right */
- 0x0000, /* R40 - Input Mixer2 */
- 0x0000, /* R41 - Input Mixer3 */
- 0x0000, /* R42 - Input Mixer4 */
- 0x0000, /* R43 - Input Mixer5 */
- 0x0000, /* R44 - Input Mixer6 */
- 0x0000, /* R45 - Output Mixer1 */
- 0x0000, /* R46 - Output Mixer2 */
- 0x0000, /* R47 - Output Mixer3 */
- 0x0000, /* R48 - Output Mixer4 */
- 0x0000, /* R49 - Output Mixer5 */
- 0x0000, /* R50 - Output Mixer6 */
- 0x0000, /* R51 - HPOUT2 Mixer */
- 0x0000, /* R52 - Line Mixer1 */
- 0x0000, /* R53 - Line Mixer2 */
- 0x0000, /* R54 - Speaker Mixer */
- 0x0000, /* R55 - Additional Control */
- 0x0000, /* R56 - AntiPOP1 */
- 0x0000, /* R57 - AntiPOP2 */
- 0x0000, /* R58 - MICBIAS */
- 0x0000, /* R59 */
- 0x0000, /* R60 - FLL Control 1 */
- 0x0000, /* R61 - FLL Control 2 */
- 0x0000, /* R62 - FLL Control 3 */
- 0x2EE0, /* R63 - FLL Control 4 */
- 0x0002, /* R64 - FLL Control 5 */
- 0x2287, /* R65 - Clocking 3 */
- 0x025F, /* R66 - Clocking 4 */
- 0x0000, /* R67 - MW Slave Control */
- 0x0000, /* R68 */
- 0x0002, /* R69 - Bus Control 1 */
- 0x0000, /* R70 - Write Sequencer 0 */
- 0x0000, /* R71 - Write Sequencer 1 */
- 0x0000, /* R72 - Write Sequencer 2 */
- 0x0000, /* R73 - Write Sequencer 3 */
- 0x0000, /* R74 - Write Sequencer 4 */
- 0x0000, /* R75 - Write Sequencer 5 */
- 0x1F25, /* R76 - Charge Pump 1 */
- 0x0000, /* R77 */
- 0x0000, /* R78 */
- 0x0000, /* R79 */
- 0x0000, /* R80 */
- 0x0000, /* R81 - Class W 0 */
- 0x0000, /* R82 */
- 0x0000, /* R83 */
- 0x0000, /* R84 - DC Servo 0 */
- 0x054A, /* R85 - DC Servo 1 */
- 0x0000, /* R86 */
- 0x0000, /* R87 - DC Servo 3 */
- 0x0000, /* R88 - DC Servo Readback 0 */
- 0x0000, /* R89 - DC Servo Readback 1 */
- 0x0000, /* R90 - DC Servo Readback 2 */
- 0x0000, /* R91 */
- 0x0000, /* R92 */
- 0x0000, /* R93 */
- 0x0000, /* R94 */
- 0x0000, /* R95 */
- 0x0100, /* R96 - Analogue HP 0 */
- 0x0000, /* R97 */
- 0x0000, /* R98 - EQ1 */
- 0x000C, /* R99 - EQ2 */
- 0x000C, /* R100 - EQ3 */
- 0x000C, /* R101 - EQ4 */
- 0x000C, /* R102 - EQ5 */
- 0x000C, /* R103 - EQ6 */
- 0x0FCA, /* R104 - EQ7 */
- 0x0400, /* R105 - EQ8 */
- 0x00D8, /* R106 - EQ9 */
- 0x1EB5, /* R107 - EQ10 */
- 0xF145, /* R108 - EQ11 */
- 0x0B75, /* R109 - EQ12 */
- 0x01C5, /* R110 - EQ13 */
- 0x1C58, /* R111 - EQ14 */
- 0xF373, /* R112 - EQ15 */
- 0x0A54, /* R113 - EQ16 */
- 0x0558, /* R114 - EQ17 */
- 0x168E, /* R115 - EQ18 */
- 0xF829, /* R116 - EQ19 */
- 0x07AD, /* R117 - EQ20 */
- 0x1103, /* R118 - EQ21 */
- 0x0564, /* R119 - EQ22 */
- 0x0559, /* R120 - EQ23 */
- 0x4000, /* R121 - EQ24 */
- 0x0000, /* R122 - Digital Pulls */
- 0x0F08, /* R123 - DRC Control 1 */
- 0x0000, /* R124 - DRC Control 2 */
- 0x0080, /* R125 - DRC Control 3 */
- 0x0000, /* R126 - DRC Control 4 */
+static struct reg_default wm8993_reg_defaults[] = {
+ { 1, 0x0000 }, /* R1 - Power Management (1) */
+ { 2, 0x6000 }, /* R2 - Power Management (2) */
+ { 3, 0x0000 }, /* R3 - Power Management (3) */
+ { 4, 0x4050 }, /* R4 - Audio Interface (1) */
+ { 5, 0x4000 }, /* R5 - Audio Interface (2) */
+ { 6, 0x01C8 }, /* R6 - Clocking 1 */
+ { 7, 0x0000 }, /* R7 - Clocking 2 */
+ { 8, 0x0000 }, /* R8 - Audio Interface (3) */
+ { 9, 0x0040 }, /* R9 - Audio Interface (4) */
+ { 10, 0x0004 }, /* R10 - DAC CTRL */
+ { 11, 0x00C0 }, /* R11 - Left DAC Digital Volume */
+ { 12, 0x00C0 }, /* R12 - Right DAC Digital Volume */
+ { 13, 0x0000 }, /* R13 - Digital Side Tone */
+ { 14, 0x0300 }, /* R14 - ADC CTRL */
+ { 15, 0x00C0 }, /* R15 - Left ADC Digital Volume */
+ { 16, 0x00C0 }, /* R16 - Right ADC Digital Volume */
+ { 18, 0x0000 }, /* R18 - GPIO CTRL 1 */
+ { 19, 0x0010 }, /* R19 - GPIO1 */
+ { 20, 0x0000 }, /* R20 - IRQ_DEBOUNCE */
+ { 21, 0x0000 }, /* R21 - Inputs Clamp */
+ { 22, 0x8000 }, /* R22 - GPIOCTRL 2 */
+ { 23, 0x0800 }, /* R23 - GPIO_POL */
+ { 24, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
+ { 25, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
+ { 26, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
+ { 27, 0x008B }, /* R27 - Right Line Input 3&4 Volume */
+ { 28, 0x006D }, /* R28 - Left Output Volume */
+ { 29, 0x006D }, /* R29 - Right Output Volume */
+ { 30, 0x0066 }, /* R30 - Line Outputs Volume */
+ { 31, 0x0020 }, /* R31 - HPOUT2 Volume */
+ { 32, 0x0079 }, /* R32 - Left OPGA Volume */
+ { 33, 0x0079 }, /* R33 - Right OPGA Volume */
+ { 34, 0x0003 }, /* R34 - SPKMIXL Attenuation */
+ { 35, 0x0003 }, /* R35 - SPKMIXR Attenuation */
+ { 36, 0x0011 }, /* R36 - SPKOUT Mixers */
+ { 37, 0x0100 }, /* R37 - SPKOUT Boost */
+ { 38, 0x0079 }, /* R38 - Speaker Volume Left */
+ { 39, 0x0079 }, /* R39 - Speaker Volume Right */
+ { 40, 0x0000 }, /* R40 - Input Mixer2 */
+ { 41, 0x0000 }, /* R41 - Input Mixer3 */
+ { 42, 0x0000 }, /* R42 - Input Mixer4 */
+ { 43, 0x0000 }, /* R43 - Input Mixer5 */
+ { 44, 0x0000 }, /* R44 - Input Mixer6 */
+ { 45, 0x0000 }, /* R45 - Output Mixer1 */
+ { 46, 0x0000 }, /* R46 - Output Mixer2 */
+ { 47, 0x0000 }, /* R47 - Output Mixer3 */
+ { 48, 0x0000 }, /* R48 - Output Mixer4 */
+ { 49, 0x0000 }, /* R49 - Output Mixer5 */
+ { 50, 0x0000 }, /* R50 - Output Mixer6 */
+ { 51, 0x0000 }, /* R51 - HPOUT2 Mixer */
+ { 52, 0x0000 }, /* R52 - Line Mixer1 */
+ { 53, 0x0000 }, /* R53 - Line Mixer2 */
+ { 54, 0x0000 }, /* R54 - Speaker Mixer */
+ { 55, 0x0000 }, /* R55 - Additional Control */
+ { 56, 0x0000 }, /* R56 - AntiPOP1 */
+ { 57, 0x0000 }, /* R57 - AntiPOP2 */
+ { 58, 0x0000 }, /* R58 - MICBIAS */
+ { 60, 0x0000 }, /* R60 - FLL Control 1 */
+ { 61, 0x0000 }, /* R61 - FLL Control 2 */
+ { 62, 0x0000 }, /* R62 - FLL Control 3 */
+ { 63, 0x2EE0 }, /* R63 - FLL Control 4 */
+ { 64, 0x0002 }, /* R64 - FLL Control 5 */
+ { 65, 0x2287 }, /* R65 - Clocking 3 */
+ { 66, 0x025F }, /* R66 - Clocking 4 */
+ { 67, 0x0000 }, /* R67 - MW Slave Control */
+ { 69, 0x0002 }, /* R69 - Bus Control 1 */
+ { 70, 0x0000 }, /* R70 - Write Sequencer 0 */
+ { 71, 0x0000 }, /* R71 - Write Sequencer 1 */
+ { 72, 0x0000 }, /* R72 - Write Sequencer 2 */
+ { 73, 0x0000 }, /* R73 - Write Sequencer 3 */
+ { 74, 0x0000 }, /* R74 - Write Sequencer 4 */
+ { 75, 0x0000 }, /* R75 - Write Sequencer 5 */
+ { 76, 0x1F25 }, /* R76 - Charge Pump 1 */
+ { 81, 0x0000 }, /* R81 - Class W 0 */
+ { 85, 0x054A }, /* R85 - DC Servo 1 */
+ { 87, 0x0000 }, /* R87 - DC Servo 3 */
+ { 96, 0x0100 }, /* R96 - Analogue HP 0 */
+ { 98, 0x0000 }, /* R98 - EQ1 */
+ { 99, 0x000C }, /* R99 - EQ2 */
+ { 100, 0x000C }, /* R100 - EQ3 */
+ { 101, 0x000C }, /* R101 - EQ4 */
+ { 102, 0x000C }, /* R102 - EQ5 */
+ { 103, 0x000C }, /* R103 - EQ6 */
+ { 104, 0x0FCA }, /* R104 - EQ7 */
+ { 105, 0x0400 }, /* R105 - EQ8 */
+ { 106, 0x00D8 }, /* R106 - EQ9 */
+ { 107, 0x1EB5 }, /* R107 - EQ10 */
+ { 108, 0xF145 }, /* R108 - EQ11 */
+ { 109, 0x0B75 }, /* R109 - EQ12 */
+ { 110, 0x01C5 }, /* R110 - EQ13 */
+ { 111, 0x1C58 }, /* R111 - EQ14 */
+ { 112, 0xF373 }, /* R112 - EQ15 */
+ { 113, 0x0A54 }, /* R113 - EQ16 */
+ { 114, 0x0558 }, /* R114 - EQ17 */
+ { 115, 0x168E }, /* R115 - EQ18 */
+ { 116, 0xF829 }, /* R116 - EQ19 */
+ { 117, 0x07AD }, /* R117 - EQ20 */
+ { 118, 0x1103 }, /* R118 - EQ21 */
+ { 119, 0x0564 }, /* R119 - EQ22 */
+ { 120, 0x0559 }, /* R120 - EQ23 */
+ { 121, 0x4000 }, /* R121 - EQ24 */
+ { 122, 0x0000 }, /* R122 - Digital Pulls */
+ { 123, 0x0F08 }, /* R123 - DRC Control 1 */
+ { 124, 0x0000 }, /* R124 - DRC Control 2 */
+ { 125, 0x0080 }, /* R125 - DRC Control 3 */
+ { 126, 0x0000 }, /* R126 - DRC Control 4 */
};
static struct {
@@ -225,9 +205,11 @@ static struct {
struct wm8993_priv {
struct wm_hubs_data hubs_data;
+ struct device *dev;
+ struct regmap *regmap;
struct regulator_bulk_data supplies[WM8993_NUM_SUPPLIES];
struct wm8993_platform_data pdata;
- enum snd_soc_control_type control_type;
+ struct completion fll_lock;
int master;
int sysclk_source;
int tdm_slots;
@@ -242,17 +224,137 @@ struct wm8993_priv {
int fll_src;
};
-static int wm8993_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8993_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM8993_SOFTWARE_RESET:
+ case WM8993_GPIO_CTRL_1:
case WM8993_DC_SERVO_0:
case WM8993_DC_SERVO_READBACK_0:
case WM8993_DC_SERVO_READBACK_1:
case WM8993_DC_SERVO_READBACK_2:
- return 1;
+ return true;
default:
- return 0;
+ return false;
+ }
+}
+
+static bool wm8993_readable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8993_SOFTWARE_RESET:
+ case WM8993_POWER_MANAGEMENT_1:
+ case WM8993_POWER_MANAGEMENT_2:
+ case WM8993_POWER_MANAGEMENT_3:
+ case WM8993_AUDIO_INTERFACE_1:
+ case WM8993_AUDIO_INTERFACE_2:
+ case WM8993_CLOCKING_1:
+ case WM8993_CLOCKING_2:
+ case WM8993_AUDIO_INTERFACE_3:
+ case WM8993_AUDIO_INTERFACE_4:
+ case WM8993_DAC_CTRL:
+ case WM8993_LEFT_DAC_DIGITAL_VOLUME:
+ case WM8993_RIGHT_DAC_DIGITAL_VOLUME:
+ case WM8993_DIGITAL_SIDE_TONE:
+ case WM8993_ADC_CTRL:
+ case WM8993_LEFT_ADC_DIGITAL_VOLUME:
+ case WM8993_RIGHT_ADC_DIGITAL_VOLUME:
+ case WM8993_GPIO_CTRL_1:
+ case WM8993_GPIO1:
+ case WM8993_IRQ_DEBOUNCE:
+ case WM8993_GPIOCTRL_2:
+ case WM8993_GPIO_POL:
+ case WM8993_LEFT_LINE_INPUT_1_2_VOLUME:
+ case WM8993_LEFT_LINE_INPUT_3_4_VOLUME:
+ case WM8993_RIGHT_LINE_INPUT_1_2_VOLUME:
+ case WM8993_RIGHT_LINE_INPUT_3_4_VOLUME:
+ case WM8993_LEFT_OUTPUT_VOLUME:
+ case WM8993_RIGHT_OUTPUT_VOLUME:
+ case WM8993_LINE_OUTPUTS_VOLUME:
+ case WM8993_HPOUT2_VOLUME:
+ case WM8993_LEFT_OPGA_VOLUME:
+ case WM8993_RIGHT_OPGA_VOLUME:
+ case WM8993_SPKMIXL_ATTENUATION:
+ case WM8993_SPKMIXR_ATTENUATION:
+ case WM8993_SPKOUT_MIXERS:
+ case WM8993_SPKOUT_BOOST:
+ case WM8993_SPEAKER_VOLUME_LEFT:
+ case WM8993_SPEAKER_VOLUME_RIGHT:
+ case WM8993_INPUT_MIXER2:
+ case WM8993_INPUT_MIXER3:
+ case WM8993_INPUT_MIXER4:
+ case WM8993_INPUT_MIXER5:
+ case WM8993_INPUT_MIXER6:
+ case WM8993_OUTPUT_MIXER1:
+ case WM8993_OUTPUT_MIXER2:
+ case WM8993_OUTPUT_MIXER3:
+ case WM8993_OUTPUT_MIXER4:
+ case WM8993_OUTPUT_MIXER5:
+ case WM8993_OUTPUT_MIXER6:
+ case WM8993_HPOUT2_MIXER:
+ case WM8993_LINE_MIXER1:
+ case WM8993_LINE_MIXER2:
+ case WM8993_SPEAKER_MIXER:
+ case WM8993_ADDITIONAL_CONTROL:
+ case WM8993_ANTIPOP1:
+ case WM8993_ANTIPOP2:
+ case WM8993_MICBIAS:
+ case WM8993_FLL_CONTROL_1:
+ case WM8993_FLL_CONTROL_2:
+ case WM8993_FLL_CONTROL_3:
+ case WM8993_FLL_CONTROL_4:
+ case WM8993_FLL_CONTROL_5:
+ case WM8993_CLOCKING_3:
+ case WM8993_CLOCKING_4:
+ case WM8993_MW_SLAVE_CONTROL:
+ case WM8993_BUS_CONTROL_1:
+ case WM8993_WRITE_SEQUENCER_0:
+ case WM8993_WRITE_SEQUENCER_1:
+ case WM8993_WRITE_SEQUENCER_2:
+ case WM8993_WRITE_SEQUENCER_3:
+ case WM8993_WRITE_SEQUENCER_4:
+ case WM8993_WRITE_SEQUENCER_5:
+ case WM8993_CHARGE_PUMP_1:
+ case WM8993_CLASS_W_0:
+ case WM8993_DC_SERVO_0:
+ case WM8993_DC_SERVO_1:
+ case WM8993_DC_SERVO_3:
+ case WM8993_DC_SERVO_READBACK_0:
+ case WM8993_DC_SERVO_READBACK_1:
+ case WM8993_DC_SERVO_READBACK_2:
+ case WM8993_ANALOGUE_HP_0:
+ case WM8993_EQ1:
+ case WM8993_EQ2:
+ case WM8993_EQ3:
+ case WM8993_EQ4:
+ case WM8993_EQ5:
+ case WM8993_EQ6:
+ case WM8993_EQ7:
+ case WM8993_EQ8:
+ case WM8993_EQ9:
+ case WM8993_EQ10:
+ case WM8993_EQ11:
+ case WM8993_EQ12:
+ case WM8993_EQ13:
+ case WM8993_EQ14:
+ case WM8993_EQ15:
+ case WM8993_EQ16:
+ case WM8993_EQ17:
+ case WM8993_EQ18:
+ case WM8993_EQ19:
+ case WM8993_EQ20:
+ case WM8993_EQ21:
+ case WM8993_EQ22:
+ case WM8993_EQ23:
+ case WM8993_EQ24:
+ case WM8993_DIGITAL_PULLS:
+ case WM8993_DRC_CONTROL_1:
+ case WM8993_DRC_CONTROL_2:
+ case WM8993_DRC_CONTROL_3:
+ case WM8993_DRC_CONTROL_4:
+ return true;
+ default:
+ return false;
}
}
@@ -369,8 +471,10 @@ static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
unsigned int Fref, unsigned int Fout)
{
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
+ struct i2c_client *i2c = to_i2c_client(codec->dev);
u16 reg1, reg4, reg5;
struct _fll_div fll_div;
+ unsigned int timeout;
int ret;
/* Any change? */
@@ -441,9 +545,23 @@ static int _wm8993_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
reg5 |= fll_div.fll_clk_ref_div << WM8993_FLL_CLK_REF_DIV_SHIFT;
snd_soc_write(codec, WM8993_FLL_CONTROL_5, reg5);
+ /* If we've got an interrupt wired up make sure we get it */
+ if (i2c->irq)
+ timeout = msecs_to_jiffies(20);
+ else if (Fref < 1000000)
+ timeout = msecs_to_jiffies(3);
+ else
+ timeout = msecs_to_jiffies(1);
+
+ try_wait_for_completion(&wm8993->fll_lock);
+
/* Enable the FLL */
snd_soc_write(codec, WM8993_FLL_CONTROL_1, reg1 | WM8993_FLL_ENA);
+ timeout = wait_for_completion_timeout(&wm8993->fll_lock, timeout);
+ if (i2c->irq && !timeout)
+ dev_warn(codec->dev, "Timed out waiting for FLL\n");
+
dev_dbg(codec->dev, "FLL enabled at %dHz->%dHz\n", Fref, Fout);
wm8993->fll_fref = Fref;
@@ -512,7 +630,7 @@ static const DECLARE_TLV_DB_SCALE(drc_comp_threash, -4500, 75, 0);
static const DECLARE_TLV_DB_SCALE(drc_comp_amp, -2250, 75, 0);
static const DECLARE_TLV_DB_SCALE(drc_min_tlv, -1800, 600, 0);
static const unsigned int drc_max_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+ TLV_DB_RANGE_HEAD(2),
0, 2, TLV_DB_SCALE_ITEM(1200, 600, 0),
3, 3, TLV_DB_SCALE_ITEM(3600, 0, 0),
};
@@ -847,6 +965,7 @@ SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, NULL, 0),
SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0),
SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0),
@@ -880,6 +999,9 @@ SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0),
};
static const struct snd_soc_dapm_route routes[] = {
+ { "MICBIAS1", NULL, "VMID" },
+ { "MICBIAS2", NULL, "VMID" },
+
{ "ADCL", NULL, "CLK_SYS" },
{ "ADCL", NULL, "CLK_DSP" },
{ "ADCR", NULL, "CLK_SYS" },
@@ -930,34 +1052,14 @@ static const struct snd_soc_dapm_route routes[] = {
{ "Right Headphone Mux", "DAC", "DACR" },
};
-static void wm8993_cache_restore(struct snd_soc_codec *codec)
-{
- u16 *cache = codec->reg_cache;
- int i;
-
- if (!codec->cache_sync)
- return;
-
- /* Reenable hardware writes */
- codec->cache_only = 0;
-
- /* Restore the register settings */
- for (i = 1; i < WM8993_MAX_REGISTER; i++) {
- if (cache[i] == wm8993_reg_defaults[i])
- continue;
- snd_soc_write(codec, i, cache[i]);
- }
-
- /* We're in sync again */
- codec->cache_sync = 0;
-}
-
static int wm8993_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
int ret;
+ wm_hubs_set_bias_level(codec, level);
+
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
@@ -975,12 +1077,10 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
if (ret != 0)
return ret;
- wm8993_cache_restore(codec);
+ regcache_cache_only(wm8993->regmap, false);
+ regcache_sync(wm8993->regmap);
- /* Tune DC servo configuration */
- snd_soc_write(codec, 0x44, 3);
- snd_soc_write(codec, 0x56, 3);
- snd_soc_write(codec, 0x44, 0);
+ wm_hubs_vmid_ena(codec);
/* Bring up VMID with fast soft start */
snd_soc_update_bits(codec, WM8993_ANTIPOP2,
@@ -1036,14 +1136,8 @@ static int wm8993_set_bias_level(struct snd_soc_codec *codec,
WM8993_VMID_RAMP_MASK |
WM8993_BIAS_SRC, 0);
-#ifdef CONFIG_REGULATOR
- /* Post 2.6.34 we will be able to get a callback when
- * the regulators are disabled which we can use but
- * for now just assume that the power will be cut if
- * the regulator API is in use.
- */
- codec->cache_sync = 1;
-#endif
+ regcache_cache_only(wm8993->regmap, true);
+ regcache_mark_dirty(wm8993->regmap);
regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies),
wm8993->supplies);
@@ -1390,7 +1484,46 @@ out:
return 0;
}
-static struct snd_soc_dai_ops wm8993_ops = {
+static irqreturn_t wm8993_irq(int irq, void *data)
+{
+ struct wm8993_priv *wm8993 = data;
+ int mask, val, ret;
+
+ ret = regmap_read(wm8993->regmap, WM8993_GPIO_CTRL_1, &val);
+ if (ret != 0) {
+ dev_err(wm8993->dev, "Failed to read interrupt status: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ ret = regmap_read(wm8993->regmap, WM8993_GPIOCTRL_2, &mask);
+ if (ret != 0) {
+ dev_err(wm8993->dev, "Failed to read interrupt mask: %d\n",
+ ret);
+ return IRQ_NONE;
+ }
+
+ /* The IRQ pin status is visible in the register too */
+ val &= ~(mask | WM8993_IRQ);
+ if (!val)
+ return IRQ_NONE;
+
+ if (val & WM8993_TEMPOK_EINT)
+ dev_crit(wm8993->dev, "Thermal warning\n");
+
+ if (val & WM8993_FLL_LOCK_EINT) {
+ dev_dbg(wm8993->dev, "FLL locked\n");
+ complete(&wm8993->fll_lock);
+ }
+
+ ret = regmap_write(wm8993->regmap, WM8993_GPIO_CTRL_1, val);
+ if (ret != 0)
+ dev_err(wm8993->dev, "Failed to ack interrupt: %d\n", ret);
+
+ return IRQ_HANDLED;
+}
+
+static const struct snd_soc_dai_ops wm8993_ops = {
.set_sysclk = wm8993_set_sysclk,
.set_fmt = wm8993_set_dai_fmt,
.hw_params = wm8993_hw_params,
@@ -1414,6 +1547,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
.channels_max = 2,
.rates = WM8993_RATES,
.formats = WM8993_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "Capture",
@@ -1421,6 +1555,7 @@ static struct snd_soc_dai_driver wm8993_dai = {
.channels_max = 2,
.rates = WM8993_RATES,
.formats = WM8993_FORMATS,
+ .sig_bits = 24,
},
.ops = &wm8993_ops,
.symmetric_rates = 1,
@@ -1430,48 +1565,20 @@ static int wm8993_probe(struct snd_soc_codec *codec)
{
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret, i, val;
+ int ret;
wm8993->hubs_data.hp_startup_mode = 1;
- wm8993->hubs_data.dcs_codes = -2;
+ wm8993->hubs_data.dcs_codes_l = -2;
+ wm8993->hubs_data.dcs_codes_r = -2;
wm8993->hubs_data.series_startup = 1;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ codec->control_data = wm8993->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
- wm8993->supplies[i].supply = wm8993_supply_names[i];
-
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8993->supplies),
- wm8993->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- return ret;
- }
-
- ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
- wm8993->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
- }
-
- val = snd_soc_read(codec, WM8993_SOFTWARE_RESET);
- if (val != wm8993_reg_defaults[WM8993_SOFTWARE_RESET]) {
- dev_err(codec->dev, "Invalid ID register value %x\n", val);
- ret = -EINVAL;
- goto err_enable;
- }
-
- ret = snd_soc_write(codec, WM8993_SOFTWARE_RESET, 0xffff);
- if (ret != 0)
- goto err_enable;
-
- codec->cache_only = 1;
-
/* By default we're using the output mixers */
wm8993->class_w_users = 2;
@@ -1500,15 +1607,15 @@ static int wm8993_probe(struct snd_soc_codec *codec)
ret = wm8993_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
if (ret != 0)
- goto err_enable;
+ return ret;
- snd_soc_add_controls(codec, wm8993_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8993_snd_controls,
ARRAY_SIZE(wm8993_snd_controls));
if (wm8993->pdata.num_retune_configs != 0) {
dev_dbg(codec->dev, "Using ReTune Mobile\n");
} else {
dev_dbg(codec->dev, "No ReTune Mobile, using normal EQ\n");
- snd_soc_add_controls(codec, wm8993_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8993_eq_controls,
ARRAY_SIZE(wm8993_eq_controls));
}
@@ -1520,13 +1627,14 @@ static int wm8993_probe(struct snd_soc_codec *codec)
wm_hubs_add_analogue_routes(codec, wm8993->pdata.lineout1_diff,
wm8993->pdata.lineout2_diff);
+ /* If the line outputs are differential then we aren't presenting
+ * VMID as an output and can disable it.
+ */
+ if (wm8993->pdata.lineout1_diff && wm8993->pdata.lineout2_diff)
+ codec->dapm.idle_bias_off = 1;
+
return 0;
-err_enable:
- regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
- return ret;
}
static int wm8993_remove(struct snd_soc_codec *codec)
@@ -1539,7 +1647,7 @@ static int wm8993_remove(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int wm8993_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8993_suspend(struct snd_soc_codec *codec)
{
struct wm8993_priv *wm8993 = snd_soc_codec_get_drvdata(codec);
int fll_fout = wm8993->fll_fout;
@@ -1589,42 +1697,149 @@ static int wm8993_resume(struct snd_soc_codec *codec)
#define wm8993_resume NULL
#endif
+/* Tune DC servo configuration */
+static struct reg_default wm8993_regmap_patch[] = {
+ { 0x44, 3 },
+ { 0x56, 3 },
+ { 0x44, 0 },
+};
+
+static const struct regmap_config wm8993_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = WM8993_MAX_REGISTER,
+ .volatile_reg = wm8993_volatile,
+ .readable_reg = wm8993_readable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm8993_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8993_reg_defaults),
+};
+
static struct snd_soc_codec_driver soc_codec_dev_wm8993 = {
.probe = wm8993_probe,
.remove = wm8993_remove,
.suspend = wm8993_suspend,
.resume = wm8993_resume,
.set_bias_level = wm8993_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8993_reg_defaults),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8993_reg_defaults,
- .volatile_register = wm8993_volatile,
};
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm8993_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8993_priv *wm8993;
- int ret;
+ unsigned int reg;
+ int ret, i;
- wm8993 = kzalloc(sizeof(struct wm8993_priv), GFP_KERNEL);
+ wm8993 = devm_kzalloc(&i2c->dev, sizeof(struct wm8993_priv),
+ GFP_KERNEL);
if (wm8993 == NULL)
return -ENOMEM;
+ wm8993->dev = &i2c->dev;
+ init_completion(&wm8993->fll_lock);
+
+ wm8993->regmap = regmap_init_i2c(i2c, &wm8993_regmap);
+ if (IS_ERR(wm8993->regmap)) {
+ ret = PTR_ERR(wm8993->regmap);
+ dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
i2c_set_clientdata(i2c, wm8993);
+ for (i = 0; i < ARRAY_SIZE(wm8993->supplies); i++)
+ wm8993->supplies[i].supply = wm8993_supply_names[i];
+
+ ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8993->supplies),
+ wm8993->supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+ goto err;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8993->supplies),
+ wm8993->supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_get;
+ }
+
+ ret = regmap_read(wm8993->regmap, WM8993_SOFTWARE_RESET, &reg);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+ goto err_enable;
+ }
+
+ if (reg != 0x8993) {
+ dev_err(&i2c->dev, "Invalid ID register value %x\n", reg);
+ ret = -EINVAL;
+ goto err_enable;
+ }
+
+ ret = regmap_write(wm8993->regmap, WM8993_SOFTWARE_RESET, 0xffff);
+ if (ret != 0)
+ goto err_enable;
+
+ ret = regmap_register_patch(wm8993->regmap, wm8993_regmap_patch,
+ ARRAY_SIZE(wm8993_regmap_patch));
+ if (ret != 0)
+ dev_warn(wm8993->dev, "Failed to apply regmap patch: %d\n",
+ ret);
+
+ if (i2c->irq) {
+ /* Put GPIO1 into interrupt mode (only GPIO1 can output IRQ) */
+ ret = regmap_update_bits(wm8993->regmap, WM8993_GPIO1,
+ WM8993_GPIO1_PD |
+ WM8993_GPIO1_SEL_MASK, 7);
+ if (ret != 0)
+ goto err_enable;
+
+ ret = request_threaded_irq(i2c->irq, NULL, wm8993_irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ "wm8993", wm8993);
+ if (ret != 0)
+ goto err_enable;
+
+ }
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+
+ regcache_cache_only(wm8993->regmap, true);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8993, &wm8993_dai, 1);
- if (ret < 0)
- kfree(wm8993);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_irq;
+ }
+
+ return 0;
+
+err_irq:
+ if (i2c->irq)
+ free_irq(i2c->irq, wm8993);
+err_enable:
+ regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err_get:
+ regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+err:
+ regmap_exit(wm8993->regmap);
return ret;
}
-static __devexit int wm8993_i2c_remove(struct i2c_client *client)
+static __devexit int wm8993_i2c_remove(struct i2c_client *i2c)
{
- snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ struct wm8993_priv *wm8993 = i2c_get_clientdata(i2c);
+
+ snd_soc_unregister_codec(&i2c->dev);
+ if (i2c->irq)
+ free_irq(i2c->irq, wm8993);
+ regmap_exit(wm8993->regmap);
+ regulator_bulk_disable(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+ regulator_bulk_free(ARRAY_SIZE(wm8993->supplies), wm8993->supplies);
+
return 0;
}
@@ -1636,37 +1851,15 @@ MODULE_DEVICE_TABLE(i2c, wm8993_i2c_id);
static struct i2c_driver wm8993_i2c_driver = {
.driver = {
- .name = "wm8993-codec",
+ .name = "wm8993",
.owner = THIS_MODULE,
},
.probe = wm8993_i2c_probe,
.remove = __devexit_p(wm8993_i2c_remove),
.id_table = wm8993_i2c_id,
};
-#endif
-
-static int __init wm8993_modinit(void)
-{
- int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- ret = i2c_add_driver(&wm8993_i2c_driver);
- if (ret != 0) {
- pr_err("WM8993: Unable to register I2C driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(wm8993_modinit);
-
-static void __exit wm8993_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&wm8993_i2c_driver);
-#endif
-}
-module_exit(wm8993_exit);
+module_i2c_driver(wm8993_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8993 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8993.h b/sound/soc/codecs/wm8993.h
index 2184617b9611..4478b40c86e3 100644
--- a/sound/soc/codecs/wm8993.h
+++ b/sound/soc/codecs/wm8993.h
@@ -31,6 +31,7 @@
#define WM8993_GPIO_CTRL_1 0x12
#define WM8993_GPIO1 0x13
#define WM8993_IRQ_DEBOUNCE 0x14
+#define WM8993_INPUTS_CLAMP_REG 0x15
#define WM8993_GPIOCTRL_2 0x16
#define WM8993_GPIO_POL 0x17
#define WM8993_LEFT_LINE_INPUT_1_2_VOLUME 0x18
@@ -656,6 +657,14 @@
#define WM8993_GPIO1_DB_WIDTH 1 /* GPIO1_DB */
/*
+ * R21 (0x15) - Inputs Clamp
+ */
+#define WM8993_INPUTS_CLAMP 0x0040 /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_MASK 0x0040 /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_SHIFT 7 /* INPUTS_CLAMP */
+#define WM8993_INPUTS_CLAMP_WIDTH 1 /* INPUTS_CLAMP */
+
+/*
* R22 (0x16) - GPIOCTRL 2
*/
#define WM8993_IM_JD2_EINT 0x2000 /* IM_JD2_EINT */
diff --git a/sound/soc/codecs/wm8994-tables.c b/sound/soc/codecs/wm8994-tables.c
deleted file mode 100644
index a87adbd05ee1..000000000000
--- a/sound/soc/codecs/wm8994-tables.c
+++ /dev/null
@@ -1,3147 +0,0 @@
-#include "wm8994.h"
-
-const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = {
- { 0xFFFF, 0xFFFF }, /* R0 - Software Reset */
- { 0x3B37, 0x3B37 }, /* R1 - Power Management (1) */
- { 0x6BF0, 0x6BF0 }, /* R2 - Power Management (2) */
- { 0x3FF0, 0x3FF0 }, /* R3 - Power Management (3) */
- { 0x3F3F, 0x3F3F }, /* R4 - Power Management (4) */
- { 0x3F0F, 0x3F0F }, /* R5 - Power Management (5) */
- { 0x003F, 0x003F }, /* R6 - Power Management (6) */
- { 0x0000, 0x0000 }, /* R7 */
- { 0x0000, 0x0000 }, /* R8 */
- { 0x0000, 0x0000 }, /* R9 */
- { 0x0000, 0x0000 }, /* R10 */
- { 0x0000, 0x0000 }, /* R11 */
- { 0x0000, 0x0000 }, /* R12 */
- { 0x0000, 0x0000 }, /* R13 */
- { 0x0000, 0x0000 }, /* R14 */
- { 0x0000, 0x0000 }, /* R15 */
- { 0x0000, 0x0000 }, /* R16 */
- { 0x0000, 0x0000 }, /* R17 */
- { 0x0000, 0x0000 }, /* R18 */
- { 0x0000, 0x0000 }, /* R19 */
- { 0x0000, 0x0000 }, /* R20 */
- { 0x01C0, 0x01C0 }, /* R21 - Input Mixer (1) */
- { 0x0000, 0x0000 }, /* R22 */
- { 0x0000, 0x0000 }, /* R23 */
- { 0x00DF, 0x01DF }, /* R24 - Left Line Input 1&2 Volume */
- { 0x00DF, 0x01DF }, /* R25 - Left Line Input 3&4 Volume */
- { 0x00DF, 0x01DF }, /* R26 - Right Line Input 1&2 Volume */
- { 0x00DF, 0x01DF }, /* R27 - Right Line Input 3&4 Volume */
- { 0x00FF, 0x01FF }, /* R28 - Left Output Volume */
- { 0x00FF, 0x01FF }, /* R29 - Right Output Volume */
- { 0x0077, 0x0077 }, /* R30 - Line Outputs Volume */
- { 0x0030, 0x0030 }, /* R31 - HPOUT2 Volume */
- { 0x00FF, 0x01FF }, /* R32 - Left OPGA Volume */
- { 0x00FF, 0x01FF }, /* R33 - Right OPGA Volume */
- { 0x007F, 0x007F }, /* R34 - SPKMIXL Attenuation */
- { 0x017F, 0x017F }, /* R35 - SPKMIXR Attenuation */
- { 0x003F, 0x003F }, /* R36 - SPKOUT Mixers */
- { 0x003F, 0x003F }, /* R37 - ClassD */
- { 0x00FF, 0x01FF }, /* R38 - Speaker Volume Left */
- { 0x00FF, 0x01FF }, /* R39 - Speaker Volume Right */
- { 0x00FF, 0x00FF }, /* R40 - Input Mixer (2) */
- { 0x01B7, 0x01B7 }, /* R41 - Input Mixer (3) */
- { 0x01B7, 0x01B7 }, /* R42 - Input Mixer (4) */
- { 0x01C7, 0x01C7 }, /* R43 - Input Mixer (5) */
- { 0x01C7, 0x01C7 }, /* R44 - Input Mixer (6) */
- { 0x01FF, 0x01FF }, /* R45 - Output Mixer (1) */
- { 0x01FF, 0x01FF }, /* R46 - Output Mixer (2) */
- { 0x0FFF, 0x0FFF }, /* R47 - Output Mixer (3) */
- { 0x0FFF, 0x0FFF }, /* R48 - Output Mixer (4) */
- { 0x0FFF, 0x0FFF }, /* R49 - Output Mixer (5) */
- { 0x0FFF, 0x0FFF }, /* R50 - Output Mixer (6) */
- { 0x0038, 0x0038 }, /* R51 - HPOUT2 Mixer */
- { 0x0077, 0x0077 }, /* R52 - Line Mixer (1) */
- { 0x0077, 0x0077 }, /* R53 - Line Mixer (2) */
- { 0x03FF, 0x03FF }, /* R54 - Speaker Mixer */
- { 0x00C1, 0x00C1 }, /* R55 - Additional Control */
- { 0x00F0, 0x00F0 }, /* R56 - AntiPOP (1) */
- { 0x01EF, 0x01EF }, /* R57 - AntiPOP (2) */
- { 0x00FF, 0x00FF }, /* R58 - MICBIAS */
- { 0x000F, 0x000F }, /* R59 - LDO 1 */
- { 0x0007, 0x0007 }, /* R60 - LDO 2 */
- { 0xFFFF, 0xFFFF }, /* R61 */
- { 0xFFFF, 0xFFFF }, /* R62 */
- { 0x0000, 0x0000 }, /* R63 */
- { 0x0000, 0x0000 }, /* R64 */
- { 0x0000, 0x0000 }, /* R65 */
- { 0x0000, 0x0000 }, /* R66 */
- { 0x0000, 0x0000 }, /* R67 */
- { 0x0000, 0x0000 }, /* R68 */
- { 0x0000, 0x0000 }, /* R69 */
- { 0x0000, 0x0000 }, /* R70 */
- { 0x0000, 0x0000 }, /* R71 */
- { 0x0000, 0x0000 }, /* R72 */
- { 0x0000, 0x0000 }, /* R73 */
- { 0x0000, 0x0000 }, /* R74 */
- { 0x0000, 0x0000 }, /* R75 */
- { 0x8000, 0x8000 }, /* R76 - Charge Pump (1) */
- { 0x0000, 0x0000 }, /* R77 */
- { 0x0000, 0x0000 }, /* R78 */
- { 0x0000, 0x0000 }, /* R79 */
- { 0x0000, 0x0000 }, /* R80 */
- { 0x0301, 0x0301 }, /* R81 - Class W (1) */
- { 0x0000, 0x0000 }, /* R82 */
- { 0x0000, 0x0000 }, /* R83 */
- { 0x333F, 0x333F }, /* R84 - DC Servo (1) */
- { 0x0FEF, 0x0FEF }, /* R85 - DC Servo (2) */
- { 0x0000, 0x0000 }, /* R86 */
- { 0xFFFF, 0xFFFF }, /* R87 - DC Servo (4) */
- { 0x0333, 0x0000 }, /* R88 - DC Servo Readback */
- { 0x0000, 0x0000 }, /* R89 */
- { 0x0000, 0x0000 }, /* R90 */
- { 0x0000, 0x0000 }, /* R91 */
- { 0x0000, 0x0000 }, /* R92 */
- { 0x0000, 0x0000 }, /* R93 */
- { 0x0000, 0x0000 }, /* R94 */
- { 0x0000, 0x0000 }, /* R95 */
- { 0x00EE, 0x00EE }, /* R96 - Analogue HP (1) */
- { 0x0000, 0x0000 }, /* R97 */
- { 0x0000, 0x0000 }, /* R98 */
- { 0x0000, 0x0000 }, /* R99 */
- { 0x0000, 0x0000 }, /* R100 */
- { 0x0000, 0x0000 }, /* R101 */
- { 0x0000, 0x0000 }, /* R102 */
- { 0x0000, 0x0000 }, /* R103 */
- { 0x0000, 0x0000 }, /* R104 */
- { 0x0000, 0x0000 }, /* R105 */
- { 0x0000, 0x0000 }, /* R106 */
- { 0x0000, 0x0000 }, /* R107 */
- { 0x0000, 0x0000 }, /* R108 */
- { 0x0000, 0x0000 }, /* R109 */
- { 0x0000, 0x0000 }, /* R110 */
- { 0x0000, 0x0000 }, /* R111 */
- { 0x0000, 0x0000 }, /* R112 */
- { 0x0000, 0x0000 }, /* R113 */
- { 0x0000, 0x0000 }, /* R114 */
- { 0x0000, 0x0000 }, /* R115 */
- { 0x0000, 0x0000 }, /* R116 */
- { 0x0000, 0x0000 }, /* R117 */
- { 0x0000, 0x0000 }, /* R118 */
- { 0x0000, 0x0000 }, /* R119 */
- { 0x0000, 0x0000 }, /* R120 */
- { 0x0000, 0x0000 }, /* R121 */
- { 0x0000, 0x0000 }, /* R122 */
- { 0x0000, 0x0000 }, /* R123 */
- { 0x0000, 0x0000 }, /* R124 */
- { 0x0000, 0x0000 }, /* R125 */
- { 0x0000, 0x0000 }, /* R126 */
- { 0x0000, 0x0000 }, /* R127 */
- { 0x0000, 0x0000 }, /* R128 */
- { 0x0000, 0x0000 }, /* R129 */
- { 0x0000, 0x0000 }, /* R130 */
- { 0x0000, 0x0000 }, /* R131 */
- { 0x0000, 0x0000 }, /* R132 */
- { 0x0000, 0x0000 }, /* R133 */
- { 0x0000, 0x0000 }, /* R134 */
- { 0x0000, 0x0000 }, /* R135 */
- { 0x0000, 0x0000 }, /* R136 */
- { 0x0000, 0x0000 }, /* R137 */
- { 0x0000, 0x0000 }, /* R138 */
- { 0x0000, 0x0000 }, /* R139 */
- { 0x0000, 0x0000 }, /* R140 */
- { 0x0000, 0x0000 }, /* R141 */
- { 0x0000, 0x0000 }, /* R142 */
- { 0x0000, 0x0000 }, /* R143 */
- { 0x0000, 0x0000 }, /* R144 */
- { 0x0000, 0x0000 }, /* R145 */
- { 0x0000, 0x0000 }, /* R146 */
- { 0x0000, 0x0000 }, /* R147 */
- { 0x0000, 0x0000 }, /* R148 */
- { 0x0000, 0x0000 }, /* R149 */
- { 0x0000, 0x0000 }, /* R150 */
- { 0x0000, 0x0000 }, /* R151 */
- { 0x0000, 0x0000 }, /* R152 */
- { 0x0000, 0x0000 }, /* R153 */
- { 0x0000, 0x0000 }, /* R154 */
- { 0x0000, 0x0000 }, /* R155 */
- { 0x0000, 0x0000 }, /* R156 */
- { 0x0000, 0x0000 }, /* R157 */
- { 0x0000, 0x0000 }, /* R158 */
- { 0x0000, 0x0000 }, /* R159 */
- { 0x0000, 0x0000 }, /* R160 */
- { 0x0000, 0x0000 }, /* R161 */
- { 0x0000, 0x0000 }, /* R162 */
- { 0x0000, 0x0000 }, /* R163 */
- { 0x0000, 0x0000 }, /* R164 */
- { 0x0000, 0x0000 }, /* R165 */
- { 0x0000, 0x0000 }, /* R166 */
- { 0x0000, 0x0000 }, /* R167 */
- { 0x0000, 0x0000 }, /* R168 */
- { 0x0000, 0x0000 }, /* R169 */
- { 0x0000, 0x0000 }, /* R170 */
- { 0x0000, 0x0000 }, /* R171 */
- { 0x0000, 0x0000 }, /* R172 */
- { 0x0000, 0x0000 }, /* R173 */
- { 0x0000, 0x0000 }, /* R174 */
- { 0x0000, 0x0000 }, /* R175 */
- { 0x0000, 0x0000 }, /* R176 */
- { 0x0000, 0x0000 }, /* R177 */
- { 0x0000, 0x0000 }, /* R178 */
- { 0x0000, 0x0000 }, /* R179 */
- { 0x0000, 0x0000 }, /* R180 */
- { 0x0000, 0x0000 }, /* R181 */
- { 0x0000, 0x0000 }, /* R182 */
- { 0x0000, 0x0000 }, /* R183 */
- { 0x0000, 0x0000 }, /* R184 */
- { 0x0000, 0x0000 }, /* R185 */
- { 0x0000, 0x0000 }, /* R186 */
- { 0x0000, 0x0000 }, /* R187 */
- { 0x0000, 0x0000 }, /* R188 */
- { 0x0000, 0x0000 }, /* R189 */
- { 0x0000, 0x0000 }, /* R190 */
- { 0x0000, 0x0000 }, /* R191 */
- { 0x0000, 0x0000 }, /* R192 */
- { 0x0000, 0x0000 }, /* R193 */
- { 0x0000, 0x0000 }, /* R194 */
- { 0x0000, 0x0000 }, /* R195 */
- { 0x0000, 0x0000 }, /* R196 */
- { 0x0000, 0x0000 }, /* R197 */
- { 0x0000, 0x0000 }, /* R198 */
- { 0x0000, 0x0000 }, /* R199 */
- { 0x0000, 0x0000 }, /* R200 */
- { 0x0000, 0x0000 }, /* R201 */
- { 0x0000, 0x0000 }, /* R202 */
- { 0x0000, 0x0000 }, /* R203 */
- { 0x0000, 0x0000 }, /* R204 */
- { 0x0000, 0x0000 }, /* R205 */
- { 0x0000, 0x0000 }, /* R206 */
- { 0x0000, 0x0000 }, /* R207 */
- { 0xFFFF, 0xFFFF }, /* R208 */
- { 0xFFFF, 0xFFFF }, /* R209 */
- { 0xFFFF, 0xFFFF }, /* R210 */
- { 0x0000, 0x0000 }, /* R211 */
- { 0x0000, 0x0000 }, /* R212 */
- { 0x0000, 0x0000 }, /* R213 */
- { 0x0000, 0x0000 }, /* R214 */
- { 0x0000, 0x0000 }, /* R215 */
- { 0x0000, 0x0000 }, /* R216 */
- { 0x0000, 0x0000 }, /* R217 */
- { 0x0000, 0x0000 }, /* R218 */
- { 0x0000, 0x0000 }, /* R219 */
- { 0x0000, 0x0000 }, /* R220 */
- { 0x0000, 0x0000 }, /* R221 */
- { 0x0000, 0x0000 }, /* R222 */
- { 0x0000, 0x0000 }, /* R223 */
- { 0x0000, 0x0000 }, /* R224 */
- { 0x0000, 0x0000 }, /* R225 */
- { 0x0000, 0x0000 }, /* R226 */
- { 0x0000, 0x0000 }, /* R227 */
- { 0x0000, 0x0000 }, /* R228 */
- { 0x0000, 0x0000 }, /* R229 */
- { 0x0000, 0x0000 }, /* R230 */
- { 0x0000, 0x0000 }, /* R231 */
- { 0x0000, 0x0000 }, /* R232 */
- { 0x0000, 0x0000 }, /* R233 */
- { 0x0000, 0x0000 }, /* R234 */
- { 0x0000, 0x0000 }, /* R235 */
- { 0x0000, 0x0000 }, /* R236 */
- { 0x0000, 0x0000 }, /* R237 */
- { 0x0000, 0x0000 }, /* R238 */
- { 0x0000, 0x0000 }, /* R239 */
- { 0x0000, 0x0000 }, /* R240 */
- { 0x0000, 0x0000 }, /* R241 */
- { 0x0000, 0x0000 }, /* R242 */
- { 0x0000, 0x0000 }, /* R243 */
- { 0x0000, 0x0000 }, /* R244 */
- { 0x0000, 0x0000 }, /* R245 */
- { 0x0000, 0x0000 }, /* R246 */
- { 0x0000, 0x0000 }, /* R247 */
- { 0x0000, 0x0000 }, /* R248 */
- { 0x0000, 0x0000 }, /* R249 */
- { 0x0000, 0x0000 }, /* R250 */
- { 0x0000, 0x0000 }, /* R251 */
- { 0x0000, 0x0000 }, /* R252 */
- { 0x0000, 0x0000 }, /* R253 */
- { 0x0000, 0x0000 }, /* R254 */
- { 0x0000, 0x0000 }, /* R255 */
- { 0x000F, 0x0000 }, /* R256 - Chip Revision */
- { 0x0074, 0x0074 }, /* R257 - Control Interface */
- { 0x0000, 0x0000 }, /* R258 */
- { 0x0000, 0x0000 }, /* R259 */
- { 0x0000, 0x0000 }, /* R260 */
- { 0x0000, 0x0000 }, /* R261 */
- { 0x0000, 0x0000 }, /* R262 */
- { 0x0000, 0x0000 }, /* R263 */
- { 0x0000, 0x0000 }, /* R264 */
- { 0x0000, 0x0000 }, /* R265 */
- { 0x0000, 0x0000 }, /* R266 */
- { 0x0000, 0x0000 }, /* R267 */
- { 0x0000, 0x0000 }, /* R268 */
- { 0x0000, 0x0000 }, /* R269 */
- { 0x0000, 0x0000 }, /* R270 */
- { 0x0000, 0x0000 }, /* R271 */
- { 0x807F, 0x837F }, /* R272 - Write Sequencer Ctrl (1) */
- { 0x017F, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */
- { 0x0000, 0x0000 }, /* R274 */
- { 0x0000, 0x0000 }, /* R275 */
- { 0x0000, 0x0000 }, /* R276 */
- { 0x0000, 0x0000 }, /* R277 */
- { 0x0000, 0x0000 }, /* R278 */
- { 0x0000, 0x0000 }, /* R279 */
- { 0x0000, 0x0000 }, /* R280 */
- { 0x0000, 0x0000 }, /* R281 */
- { 0x0000, 0x0000 }, /* R282 */
- { 0x0000, 0x0000 }, /* R283 */
- { 0x0000, 0x0000 }, /* R284 */
- { 0x0000, 0x0000 }, /* R285 */
- { 0x0000, 0x0000 }, /* R286 */
- { 0x0000, 0x0000 }, /* R287 */
- { 0x0000, 0x0000 }, /* R288 */
- { 0x0000, 0x0000 }, /* R289 */
- { 0x0000, 0x0000 }, /* R290 */
- { 0x0000, 0x0000 }, /* R291 */
- { 0x0000, 0x0000 }, /* R292 */
- { 0x0000, 0x0000 }, /* R293 */
- { 0x0000, 0x0000 }, /* R294 */
- { 0x0000, 0x0000 }, /* R295 */
- { 0x0000, 0x0000 }, /* R296 */
- { 0x0000, 0x0000 }, /* R297 */
- { 0x0000, 0x0000 }, /* R298 */
- { 0x0000, 0x0000 }, /* R299 */
- { 0x0000, 0x0000 }, /* R300 */
- { 0x0000, 0x0000 }, /* R301 */
- { 0x0000, 0x0000 }, /* R302 */
- { 0x0000, 0x0000 }, /* R303 */
- { 0x0000, 0x0000 }, /* R304 */
- { 0x0000, 0x0000 }, /* R305 */
- { 0x0000, 0x0000 }, /* R306 */
- { 0x0000, 0x0000 }, /* R307 */
- { 0x0000, 0x0000 }, /* R308 */
- { 0x0000, 0x0000 }, /* R309 */
- { 0x0000, 0x0000 }, /* R310 */
- { 0x0000, 0x0000 }, /* R311 */
- { 0x0000, 0x0000 }, /* R312 */
- { 0x0000, 0x0000 }, /* R313 */
- { 0x0000, 0x0000 }, /* R314 */
- { 0x0000, 0x0000 }, /* R315 */
- { 0x0000, 0x0000 }, /* R316 */
- { 0x0000, 0x0000 }, /* R317 */
- { 0x0000, 0x0000 }, /* R318 */
- { 0x0000, 0x0000 }, /* R319 */
- { 0x0000, 0x0000 }, /* R320 */
- { 0x0000, 0x0000 }, /* R321 */
- { 0x0000, 0x0000 }, /* R322 */
- { 0x0000, 0x0000 }, /* R323 */
- { 0x0000, 0x0000 }, /* R324 */
- { 0x0000, 0x0000 }, /* R325 */
- { 0x0000, 0x0000 }, /* R326 */
- { 0x0000, 0x0000 }, /* R327 */
- { 0x0000, 0x0000 }, /* R328 */
- { 0x0000, 0x0000 }, /* R329 */
- { 0x0000, 0x0000 }, /* R330 */
- { 0x0000, 0x0000 }, /* R331 */
- { 0x0000, 0x0000 }, /* R332 */
- { 0x0000, 0x0000 }, /* R333 */
- { 0x0000, 0x0000 }, /* R334 */
- { 0x0000, 0x0000 }, /* R335 */
- { 0x0000, 0x0000 }, /* R336 */
- { 0x0000, 0x0000 }, /* R337 */
- { 0x0000, 0x0000 }, /* R338 */
- { 0x0000, 0x0000 }, /* R339 */
- { 0x0000, 0x0000 }, /* R340 */
- { 0x0000, 0x0000 }, /* R341 */
- { 0x0000, 0x0000 }, /* R342 */
- { 0x0000, 0x0000 }, /* R343 */
- { 0x0000, 0x0000 }, /* R344 */
- { 0x0000, 0x0000 }, /* R345 */
- { 0x0000, 0x0000 }, /* R346 */
- { 0x0000, 0x0000 }, /* R347 */
- { 0x0000, 0x0000 }, /* R348 */
- { 0x0000, 0x0000 }, /* R349 */
- { 0x0000, 0x0000 }, /* R350 */
- { 0x0000, 0x0000 }, /* R351 */
- { 0x0000, 0x0000 }, /* R352 */
- { 0x0000, 0x0000 }, /* R353 */
- { 0x0000, 0x0000 }, /* R354 */
- { 0x0000, 0x0000 }, /* R355 */
- { 0x0000, 0x0000 }, /* R356 */
- { 0x0000, 0x0000 }, /* R357 */
- { 0x0000, 0x0000 }, /* R358 */
- { 0x0000, 0x0000 }, /* R359 */
- { 0x0000, 0x0000 }, /* R360 */
- { 0x0000, 0x0000 }, /* R361 */
- { 0x0000, 0x0000 }, /* R362 */
- { 0x0000, 0x0000 }, /* R363 */
- { 0x0000, 0x0000 }, /* R364 */
- { 0x0000, 0x0000 }, /* R365 */
- { 0x0000, 0x0000 }, /* R366 */
- { 0x0000, 0x0000 }, /* R367 */
- { 0x0000, 0x0000 }, /* R368 */
- { 0x0000, 0x0000 }, /* R369 */
- { 0x0000, 0x0000 }, /* R370 */
- { 0x0000, 0x0000 }, /* R371 */
- { 0x0000, 0x0000 }, /* R372 */
- { 0x0000, 0x0000 }, /* R373 */
- { 0x0000, 0x0000 }, /* R374 */
- { 0x0000, 0x0000 }, /* R375 */
- { 0x0000, 0x0000 }, /* R376 */
- { 0x0000, 0x0000 }, /* R377 */
- { 0x0000, 0x0000 }, /* R378 */
- { 0x0000, 0x0000 }, /* R379 */
- { 0x0000, 0x0000 }, /* R380 */
- { 0x0000, 0x0000 }, /* R381 */
- { 0x0000, 0x0000 }, /* R382 */
- { 0x0000, 0x0000 }, /* R383 */
- { 0x0000, 0x0000 }, /* R384 */
- { 0x0000, 0x0000 }, /* R385 */
- { 0x0000, 0x0000 }, /* R386 */
- { 0x0000, 0x0000 }, /* R387 */
- { 0x0000, 0x0000 }, /* R388 */
- { 0x0000, 0x0000 }, /* R389 */
- { 0x0000, 0x0000 }, /* R390 */
- { 0x0000, 0x0000 }, /* R391 */
- { 0x0000, 0x0000 }, /* R392 */
- { 0x0000, 0x0000 }, /* R393 */
- { 0x0000, 0x0000 }, /* R394 */
- { 0x0000, 0x0000 }, /* R395 */
- { 0x0000, 0x0000 }, /* R396 */
- { 0x0000, 0x0000 }, /* R397 */
- { 0x0000, 0x0000 }, /* R398 */
- { 0x0000, 0x0000 }, /* R399 */
- { 0x0000, 0x0000 }, /* R400 */
- { 0x0000, 0x0000 }, /* R401 */
- { 0x0000, 0x0000 }, /* R402 */
- { 0x0000, 0x0000 }, /* R403 */
- { 0x0000, 0x0000 }, /* R404 */
- { 0x0000, 0x0000 }, /* R405 */
- { 0x0000, 0x0000 }, /* R406 */
- { 0x0000, 0x0000 }, /* R407 */
- { 0x0000, 0x0000 }, /* R408 */
- { 0x0000, 0x0000 }, /* R409 */
- { 0x0000, 0x0000 }, /* R410 */
- { 0x0000, 0x0000 }, /* R411 */
- { 0x0000, 0x0000 }, /* R412 */
- { 0x0000, 0x0000 }, /* R413 */
- { 0x0000, 0x0000 }, /* R414 */
- { 0x0000, 0x0000 }, /* R415 */
- { 0x0000, 0x0000 }, /* R416 */
- { 0x0000, 0x0000 }, /* R417 */
- { 0x0000, 0x0000 }, /* R418 */
- { 0x0000, 0x0000 }, /* R419 */
- { 0x0000, 0x0000 }, /* R420 */
- { 0x0000, 0x0000 }, /* R421 */
- { 0x0000, 0x0000 }, /* R422 */
- { 0x0000, 0x0000 }, /* R423 */
- { 0x0000, 0x0000 }, /* R424 */
- { 0x0000, 0x0000 }, /* R425 */
- { 0x0000, 0x0000 }, /* R426 */
- { 0x0000, 0x0000 }, /* R427 */
- { 0x0000, 0x0000 }, /* R428 */
- { 0x0000, 0x0000 }, /* R429 */
- { 0x0000, 0x0000 }, /* R430 */
- { 0x0000, 0x0000 }, /* R431 */
- { 0x0000, 0x0000 }, /* R432 */
- { 0x0000, 0x0000 }, /* R433 */
- { 0x0000, 0x0000 }, /* R434 */
- { 0x0000, 0x0000 }, /* R435 */
- { 0x0000, 0x0000 }, /* R436 */
- { 0x0000, 0x0000 }, /* R437 */
- { 0x0000, 0x0000 }, /* R438 */
- { 0x0000, 0x0000 }, /* R439 */
- { 0x0000, 0x0000 }, /* R440 */
- { 0x0000, 0x0000 }, /* R441 */
- { 0x0000, 0x0000 }, /* R442 */
- { 0x0000, 0x0000 }, /* R443 */
- { 0x0000, 0x0000 }, /* R444 */
- { 0x0000, 0x0000 }, /* R445 */
- { 0x0000, 0x0000 }, /* R446 */
- { 0x0000, 0x0000 }, /* R447 */
- { 0x0000, 0x0000 }, /* R448 */
- { 0x0000, 0x0000 }, /* R449 */
- { 0x0000, 0x0000 }, /* R450 */
- { 0x0000, 0x0000 }, /* R451 */
- { 0x0000, 0x0000 }, /* R452 */
- { 0x0000, 0x0000 }, /* R453 */
- { 0x0000, 0x0000 }, /* R454 */
- { 0x0000, 0x0000 }, /* R455 */
- { 0x0000, 0x0000 }, /* R456 */
- { 0x0000, 0x0000 }, /* R457 */
- { 0x0000, 0x0000 }, /* R458 */
- { 0x0000, 0x0000 }, /* R459 */
- { 0x0000, 0x0000 }, /* R460 */
- { 0x0000, 0x0000 }, /* R461 */
- { 0x0000, 0x0000 }, /* R462 */
- { 0x0000, 0x0000 }, /* R463 */
- { 0x0000, 0x0000 }, /* R464 */
- { 0x0000, 0x0000 }, /* R465 */
- { 0x0000, 0x0000 }, /* R466 */
- { 0x0000, 0x0000 }, /* R467 */
- { 0x0000, 0x0000 }, /* R468 */
- { 0x0000, 0x0000 }, /* R469 */
- { 0x0000, 0x0000 }, /* R470 */
- { 0x0000, 0x0000 }, /* R471 */
- { 0x0000, 0x0000 }, /* R472 */
- { 0x0000, 0x0000 }, /* R473 */
- { 0x0000, 0x0000 }, /* R474 */
- { 0x0000, 0x0000 }, /* R475 */
- { 0x0000, 0x0000 }, /* R476 */
- { 0x0000, 0x0000 }, /* R477 */
- { 0x0000, 0x0000 }, /* R478 */
- { 0x0000, 0x0000 }, /* R479 */
- { 0x0000, 0x0000 }, /* R480 */
- { 0x0000, 0x0000 }, /* R481 */
- { 0x0000, 0x0000 }, /* R482 */
- { 0x0000, 0x0000 }, /* R483 */
- { 0x0000, 0x0000 }, /* R484 */
- { 0x0000, 0x0000 }, /* R485 */
- { 0x0000, 0x0000 }, /* R486 */
- { 0x0000, 0x0000 }, /* R487 */
- { 0x0000, 0x0000 }, /* R488 */
- { 0x0000, 0x0000 }, /* R489 */
- { 0x0000, 0x0000 }, /* R490 */
- { 0x0000, 0x0000 }, /* R491 */
- { 0x0000, 0x0000 }, /* R492 */
- { 0x0000, 0x0000 }, /* R493 */
- { 0x0000, 0x0000 }, /* R494 */
- { 0x0000, 0x0000 }, /* R495 */
- { 0x0000, 0x0000 }, /* R496 */
- { 0x0000, 0x0000 }, /* R497 */
- { 0x0000, 0x0000 }, /* R498 */
- { 0x0000, 0x0000 }, /* R499 */
- { 0x0000, 0x0000 }, /* R500 */
- { 0x0000, 0x0000 }, /* R501 */
- { 0x0000, 0x0000 }, /* R502 */
- { 0x0000, 0x0000 }, /* R503 */
- { 0x0000, 0x0000 }, /* R504 */
- { 0x0000, 0x0000 }, /* R505 */
- { 0x0000, 0x0000 }, /* R506 */
- { 0x0000, 0x0000 }, /* R507 */
- { 0x0000, 0x0000 }, /* R508 */
- { 0x0000, 0x0000 }, /* R509 */
- { 0x0000, 0x0000 }, /* R510 */
- { 0x0000, 0x0000 }, /* R511 */
- { 0x001F, 0x001F }, /* R512 - AIF1 Clocking (1) */
- { 0x003F, 0x003F }, /* R513 - AIF1 Clocking (2) */
- { 0x0000, 0x0000 }, /* R514 */
- { 0x0000, 0x0000 }, /* R515 */
- { 0x001F, 0x001F }, /* R516 - AIF2 Clocking (1) */
- { 0x003F, 0x003F }, /* R517 - AIF2 Clocking (2) */
- { 0x0000, 0x0000 }, /* R518 */
- { 0x0000, 0x0000 }, /* R519 */
- { 0x001F, 0x001F }, /* R520 - Clocking (1) */
- { 0x0777, 0x0777 }, /* R521 - Clocking (2) */
- { 0x0000, 0x0000 }, /* R522 */
- { 0x0000, 0x0000 }, /* R523 */
- { 0x0000, 0x0000 }, /* R524 */
- { 0x0000, 0x0000 }, /* R525 */
- { 0x0000, 0x0000 }, /* R526 */
- { 0x0000, 0x0000 }, /* R527 */
- { 0x00FF, 0x00FF }, /* R528 - AIF1 Rate */
- { 0x00FF, 0x00FF }, /* R529 - AIF2 Rate */
- { 0x000F, 0x0000 }, /* R530 - Rate Status */
- { 0x0000, 0x0000 }, /* R531 */
- { 0x0000, 0x0000 }, /* R532 */
- { 0x0000, 0x0000 }, /* R533 */
- { 0x0000, 0x0000 }, /* R534 */
- { 0x0000, 0x0000 }, /* R535 */
- { 0x0000, 0x0000 }, /* R536 */
- { 0x0000, 0x0000 }, /* R537 */
- { 0x0000, 0x0000 }, /* R538 */
- { 0x0000, 0x0000 }, /* R539 */
- { 0x0000, 0x0000 }, /* R540 */
- { 0x0000, 0x0000 }, /* R541 */
- { 0x0000, 0x0000 }, /* R542 */
- { 0x0000, 0x0000 }, /* R543 */
- { 0x0007, 0x0007 }, /* R544 - FLL1 Control (1) */
- { 0x3F77, 0x3F77 }, /* R545 - FLL1 Control (2) */
- { 0xFFFF, 0xFFFF }, /* R546 - FLL1 Control (3) */
- { 0x7FEF, 0x7FEF }, /* R547 - FLL1 Control (4) */
- { 0x1FDB, 0x1FDB }, /* R548 - FLL1 Control (5) */
- { 0x0000, 0x0000 }, /* R549 */
- { 0x0000, 0x0000 }, /* R550 */
- { 0x0000, 0x0000 }, /* R551 */
- { 0x0000, 0x0000 }, /* R552 */
- { 0x0000, 0x0000 }, /* R553 */
- { 0x0000, 0x0000 }, /* R554 */
- { 0x0000, 0x0000 }, /* R555 */
- { 0x0000, 0x0000 }, /* R556 */
- { 0x0000, 0x0000 }, /* R557 */
- { 0x0000, 0x0000 }, /* R558 */
- { 0x0000, 0x0000 }, /* R559 */
- { 0x0000, 0x0000 }, /* R560 */
- { 0x0000, 0x0000 }, /* R561 */
- { 0x0000, 0x0000 }, /* R562 */
- { 0x0000, 0x0000 }, /* R563 */
- { 0x0000, 0x0000 }, /* R564 */
- { 0x0000, 0x0000 }, /* R565 */
- { 0x0000, 0x0000 }, /* R566 */
- { 0x0000, 0x0000 }, /* R567 */
- { 0x0000, 0x0000 }, /* R568 */
- { 0x0000, 0x0000 }, /* R569 */
- { 0x0000, 0x0000 }, /* R570 */
- { 0x0000, 0x0000 }, /* R571 */
- { 0x0000, 0x0000 }, /* R572 */
- { 0x0000, 0x0000 }, /* R573 */
- { 0x0000, 0x0000 }, /* R574 */
- { 0x0000, 0x0000 }, /* R575 */
- { 0x0007, 0x0007 }, /* R576 - FLL2 Control (1) */
- { 0x3F77, 0x3F77 }, /* R577 - FLL2 Control (2) */
- { 0xFFFF, 0xFFFF }, /* R578 - FLL2 Control (3) */
- { 0x7FEF, 0x7FEF }, /* R579 - FLL2 Control (4) */
- { 0x1FDB, 0x1FDB }, /* R580 - FLL2 Control (5) */
- { 0x0000, 0x0000 }, /* R581 */
- { 0x0000, 0x0000 }, /* R582 */
- { 0x0000, 0x0000 }, /* R583 */
- { 0x0000, 0x0000 }, /* R584 */
- { 0x0000, 0x0000 }, /* R585 */
- { 0x0000, 0x0000 }, /* R586 */
- { 0x0000, 0x0000 }, /* R587 */
- { 0x0000, 0x0000 }, /* R588 */
- { 0x0000, 0x0000 }, /* R589 */
- { 0x0000, 0x0000 }, /* R590 */
- { 0x0000, 0x0000 }, /* R591 */
- { 0x0000, 0x0000 }, /* R592 */
- { 0x0000, 0x0000 }, /* R593 */
- { 0x0000, 0x0000 }, /* R594 */
- { 0x0000, 0x0000 }, /* R595 */
- { 0x0000, 0x0000 }, /* R596 */
- { 0x0000, 0x0000 }, /* R597 */
- { 0x0000, 0x0000 }, /* R598 */
- { 0x0000, 0x0000 }, /* R599 */
- { 0x0000, 0x0000 }, /* R600 */
- { 0x0000, 0x0000 }, /* R601 */
- { 0x0000, 0x0000 }, /* R602 */
- { 0x0000, 0x0000 }, /* R603 */
- { 0x0000, 0x0000 }, /* R604 */
- { 0x0000, 0x0000 }, /* R605 */
- { 0x0000, 0x0000 }, /* R606 */
- { 0x0000, 0x0000 }, /* R607 */
- { 0x0000, 0x0000 }, /* R608 */
- { 0x0000, 0x0000 }, /* R609 */
- { 0x0000, 0x0000 }, /* R610 */
- { 0x0000, 0x0000 }, /* R611 */
- { 0x0000, 0x0000 }, /* R612 */
- { 0x0000, 0x0000 }, /* R613 */
- { 0x0000, 0x0000 }, /* R614 */
- { 0x0000, 0x0000 }, /* R615 */
- { 0x0000, 0x0000 }, /* R616 */
- { 0x0000, 0x0000 }, /* R617 */
- { 0x0000, 0x0000 }, /* R618 */
- { 0x0000, 0x0000 }, /* R619 */
- { 0x0000, 0x0000 }, /* R620 */
- { 0x0000, 0x0000 }, /* R621 */
- { 0x0000, 0x0000 }, /* R622 */
- { 0x0000, 0x0000 }, /* R623 */
- { 0x0000, 0x0000 }, /* R624 */
- { 0x0000, 0x0000 }, /* R625 */
- { 0x0000, 0x0000 }, /* R626 */
- { 0x0000, 0x0000 }, /* R627 */
- { 0x0000, 0x0000 }, /* R628 */
- { 0x0000, 0x0000 }, /* R629 */
- { 0x0000, 0x0000 }, /* R630 */
- { 0x0000, 0x0000 }, /* R631 */
- { 0x0000, 0x0000 }, /* R632 */
- { 0x0000, 0x0000 }, /* R633 */
- { 0x0000, 0x0000 }, /* R634 */
- { 0x0000, 0x0000 }, /* R635 */
- { 0x0000, 0x0000 }, /* R636 */
- { 0x0000, 0x0000 }, /* R637 */
- { 0x0000, 0x0000 }, /* R638 */
- { 0x0000, 0x0000 }, /* R639 */
- { 0x0000, 0x0000 }, /* R640 */
- { 0x0000, 0x0000 }, /* R641 */
- { 0x0000, 0x0000 }, /* R642 */
- { 0x0000, 0x0000 }, /* R643 */
- { 0x0000, 0x0000 }, /* R644 */
- { 0x0000, 0x0000 }, /* R645 */
- { 0x0000, 0x0000 }, /* R646 */
- { 0x0000, 0x0000 }, /* R647 */
- { 0x0000, 0x0000 }, /* R648 */
- { 0x0000, 0x0000 }, /* R649 */
- { 0x0000, 0x0000 }, /* R650 */
- { 0x0000, 0x0000 }, /* R651 */
- { 0x0000, 0x0000 }, /* R652 */
- { 0x0000, 0x0000 }, /* R653 */
- { 0x0000, 0x0000 }, /* R654 */
- { 0x0000, 0x0000 }, /* R655 */
- { 0x0000, 0x0000 }, /* R656 */
- { 0x0000, 0x0000 }, /* R657 */
- { 0x0000, 0x0000 }, /* R658 */
- { 0x0000, 0x0000 }, /* R659 */
- { 0x0000, 0x0000 }, /* R660 */
- { 0x0000, 0x0000 }, /* R661 */
- { 0x0000, 0x0000 }, /* R662 */
- { 0x0000, 0x0000 }, /* R663 */
- { 0x0000, 0x0000 }, /* R664 */
- { 0x0000, 0x0000 }, /* R665 */
- { 0x0000, 0x0000 }, /* R666 */
- { 0x0000, 0x0000 }, /* R667 */
- { 0x0000, 0x0000 }, /* R668 */
- { 0x0000, 0x0000 }, /* R669 */
- { 0x0000, 0x0000 }, /* R670 */
- { 0x0000, 0x0000 }, /* R671 */
- { 0x0000, 0x0000 }, /* R672 */
- { 0x0000, 0x0000 }, /* R673 */
- { 0x0000, 0x0000 }, /* R674 */
- { 0x0000, 0x0000 }, /* R675 */
- { 0x0000, 0x0000 }, /* R676 */
- { 0x0000, 0x0000 }, /* R677 */
- { 0x0000, 0x0000 }, /* R678 */
- { 0x0000, 0x0000 }, /* R679 */
- { 0x0000, 0x0000 }, /* R680 */
- { 0x0000, 0x0000 }, /* R681 */
- { 0x0000, 0x0000 }, /* R682 */
- { 0x0000, 0x0000 }, /* R683 */
- { 0x0000, 0x0000 }, /* R684 */
- { 0x0000, 0x0000 }, /* R685 */
- { 0x0000, 0x0000 }, /* R686 */
- { 0x0000, 0x0000 }, /* R687 */
- { 0x0000, 0x0000 }, /* R688 */
- { 0x0000, 0x0000 }, /* R689 */
- { 0x0000, 0x0000 }, /* R690 */
- { 0x0000, 0x0000 }, /* R691 */
- { 0x0000, 0x0000 }, /* R692 */
- { 0x0000, 0x0000 }, /* R693 */
- { 0x0000, 0x0000 }, /* R694 */
- { 0x0000, 0x0000 }, /* R695 */
- { 0x0000, 0x0000 }, /* R696 */
- { 0x0000, 0x0000 }, /* R697 */
- { 0x0000, 0x0000 }, /* R698 */
- { 0x0000, 0x0000 }, /* R699 */
- { 0x0000, 0x0000 }, /* R700 */
- { 0x0000, 0x0000 }, /* R701 */
- { 0x0000, 0x0000 }, /* R702 */
- { 0x0000, 0x0000 }, /* R703 */
- { 0x0000, 0x0000 }, /* R704 */
- { 0x0000, 0x0000 }, /* R705 */
- { 0x0000, 0x0000 }, /* R706 */
- { 0x0000, 0x0000 }, /* R707 */
- { 0x0000, 0x0000 }, /* R708 */
- { 0x0000, 0x0000 }, /* R709 */
- { 0x0000, 0x0000 }, /* R710 */
- { 0x0000, 0x0000 }, /* R711 */
- { 0x0000, 0x0000 }, /* R712 */
- { 0x0000, 0x0000 }, /* R713 */
- { 0x0000, 0x0000 }, /* R714 */
- { 0x0000, 0x0000 }, /* R715 */
- { 0x0000, 0x0000 }, /* R716 */
- { 0x0000, 0x0000 }, /* R717 */
- { 0x0000, 0x0000 }, /* R718 */
- { 0x0000, 0x0000 }, /* R719 */
- { 0x0000, 0x0000 }, /* R720 */
- { 0x0000, 0x0000 }, /* R721 */
- { 0x0000, 0x0000 }, /* R722 */
- { 0x0000, 0x0000 }, /* R723 */
- { 0x0000, 0x0000 }, /* R724 */
- { 0x0000, 0x0000 }, /* R725 */
- { 0x0000, 0x0000 }, /* R726 */
- { 0x0000, 0x0000 }, /* R727 */
- { 0x0000, 0x0000 }, /* R728 */
- { 0x0000, 0x0000 }, /* R729 */
- { 0x0000, 0x0000 }, /* R730 */
- { 0x0000, 0x0000 }, /* R731 */
- { 0x0000, 0x0000 }, /* R732 */
- { 0x0000, 0x0000 }, /* R733 */
- { 0x0000, 0x0000 }, /* R734 */
- { 0x0000, 0x0000 }, /* R735 */
- { 0x0000, 0x0000 }, /* R736 */
- { 0x0000, 0x0000 }, /* R737 */
- { 0x0000, 0x0000 }, /* R738 */
- { 0x0000, 0x0000 }, /* R739 */
- { 0x0000, 0x0000 }, /* R740 */
- { 0x0000, 0x0000 }, /* R741 */
- { 0x0000, 0x0000 }, /* R742 */
- { 0x0000, 0x0000 }, /* R743 */
- { 0x0000, 0x0000 }, /* R744 */
- { 0x0000, 0x0000 }, /* R745 */
- { 0x0000, 0x0000 }, /* R746 */
- { 0x0000, 0x0000 }, /* R747 */
- { 0x0000, 0x0000 }, /* R748 */
- { 0x0000, 0x0000 }, /* R749 */
- { 0x0000, 0x0000 }, /* R750 */
- { 0x0000, 0x0000 }, /* R751 */
- { 0x0000, 0x0000 }, /* R752 */
- { 0x0000, 0x0000 }, /* R753 */
- { 0x0000, 0x0000 }, /* R754 */
- { 0x0000, 0x0000 }, /* R755 */
- { 0x0000, 0x0000 }, /* R756 */
- { 0x0000, 0x0000 }, /* R757 */
- { 0x0000, 0x0000 }, /* R758 */
- { 0x0000, 0x0000 }, /* R759 */
- { 0x0000, 0x0000 }, /* R760 */
- { 0x0000, 0x0000 }, /* R761 */
- { 0x0000, 0x0000 }, /* R762 */
- { 0x0000, 0x0000 }, /* R763 */
- { 0x0000, 0x0000 }, /* R764 */
- { 0x0000, 0x0000 }, /* R765 */
- { 0x0000, 0x0000 }, /* R766 */
- { 0x0000, 0x0000 }, /* R767 */
- { 0xE1F8, 0xE1F8 }, /* R768 - AIF1 Control (1) */
- { 0xCD1F, 0xCD1F }, /* R769 - AIF1 Control (2) */
- { 0xF000, 0xF000 }, /* R770 - AIF1 Master/Slave */
- { 0x01F0, 0x01F0 }, /* R771 - AIF1 BCLK */
- { 0x0FFF, 0x0FFF }, /* R772 - AIF1ADC LRCLK */
- { 0x0FFF, 0x0FFF }, /* R773 - AIF1DAC LRCLK */
- { 0x0003, 0x0003 }, /* R774 - AIF1DAC Data */
- { 0x0003, 0x0003 }, /* R775 - AIF1ADC Data */
- { 0x0000, 0x0000 }, /* R776 */
- { 0x0000, 0x0000 }, /* R777 */
- { 0x0000, 0x0000 }, /* R778 */
- { 0x0000, 0x0000 }, /* R779 */
- { 0x0000, 0x0000 }, /* R780 */
- { 0x0000, 0x0000 }, /* R781 */
- { 0x0000, 0x0000 }, /* R782 */
- { 0x0000, 0x0000 }, /* R783 */
- { 0xF1F8, 0xF1F8 }, /* R784 - AIF2 Control (1) */
- { 0xFD1F, 0xFD1F }, /* R785 - AIF2 Control (2) */
- { 0xF000, 0xF000 }, /* R786 - AIF2 Master/Slave */
- { 0x01F0, 0x01F0 }, /* R787 - AIF2 BCLK */
- { 0x0FFF, 0x0FFF }, /* R788 - AIF2ADC LRCLK */
- { 0x0FFF, 0x0FFF }, /* R789 - AIF2DAC LRCLK */
- { 0x0003, 0x0003 }, /* R790 - AIF2DAC Data */
- { 0x0003, 0x0003 }, /* R791 - AIF2ADC Data */
- { 0x0000, 0x0000 }, /* R792 */
- { 0x0000, 0x0000 }, /* R793 */
- { 0x0000, 0x0000 }, /* R794 */
- { 0x0000, 0x0000 }, /* R795 */
- { 0x0000, 0x0000 }, /* R796 */
- { 0x0000, 0x0000 }, /* R797 */
- { 0x0000, 0x0000 }, /* R798 */
- { 0x0000, 0x0000 }, /* R799 */
- { 0x0000, 0x0000 }, /* R800 */
- { 0x0000, 0x0000 }, /* R801 */
- { 0x0000, 0x0000 }, /* R802 */
- { 0x0000, 0x0000 }, /* R803 */
- { 0x0000, 0x0000 }, /* R804 */
- { 0x0000, 0x0000 }, /* R805 */
- { 0x0000, 0x0000 }, /* R806 */
- { 0x0000, 0x0000 }, /* R807 */
- { 0x0000, 0x0000 }, /* R808 */
- { 0x0000, 0x0000 }, /* R809 */
- { 0x0000, 0x0000 }, /* R810 */
- { 0x0000, 0x0000 }, /* R811 */
- { 0x0000, 0x0000 }, /* R812 */
- { 0x0000, 0x0000 }, /* R813 */
- { 0x0000, 0x0000 }, /* R814 */
- { 0x0000, 0x0000 }, /* R815 */
- { 0x0000, 0x0000 }, /* R816 */
- { 0x0000, 0x0000 }, /* R817 */
- { 0x0000, 0x0000 }, /* R818 */
- { 0x0000, 0x0000 }, /* R819 */
- { 0x0000, 0x0000 }, /* R820 */
- { 0x0000, 0x0000 }, /* R821 */
- { 0x0000, 0x0000 }, /* R822 */
- { 0x0000, 0x0000 }, /* R823 */
- { 0x0000, 0x0000 }, /* R824 */
- { 0x0000, 0x0000 }, /* R825 */
- { 0x0000, 0x0000 }, /* R826 */
- { 0x0000, 0x0000 }, /* R827 */
- { 0x0000, 0x0000 }, /* R828 */
- { 0x0000, 0x0000 }, /* R829 */
- { 0x0000, 0x0000 }, /* R830 */
- { 0x0000, 0x0000 }, /* R831 */
- { 0x0000, 0x0000 }, /* R832 */
- { 0x0000, 0x0000 }, /* R833 */
- { 0x0000, 0x0000 }, /* R834 */
- { 0x0000, 0x0000 }, /* R835 */
- { 0x0000, 0x0000 }, /* R836 */
- { 0x0000, 0x0000 }, /* R837 */
- { 0x0000, 0x0000 }, /* R838 */
- { 0x0000, 0x0000 }, /* R839 */
- { 0x0000, 0x0000 }, /* R840 */
- { 0x0000, 0x0000 }, /* R841 */
- { 0x0000, 0x0000 }, /* R842 */
- { 0x0000, 0x0000 }, /* R843 */
- { 0x0000, 0x0000 }, /* R844 */
- { 0x0000, 0x0000 }, /* R845 */
- { 0x0000, 0x0000 }, /* R846 */
- { 0x0000, 0x0000 }, /* R847 */
- { 0x0000, 0x0000 }, /* R848 */
- { 0x0000, 0x0000 }, /* R849 */
- { 0x0000, 0x0000 }, /* R850 */
- { 0x0000, 0x0000 }, /* R851 */
- { 0x0000, 0x0000 }, /* R852 */
- { 0x0000, 0x0000 }, /* R853 */
- { 0x0000, 0x0000 }, /* R854 */
- { 0x0000, 0x0000 }, /* R855 */
- { 0x0000, 0x0000 }, /* R856 */
- { 0x0000, 0x0000 }, /* R857 */
- { 0x0000, 0x0000 }, /* R858 */
- { 0x0000, 0x0000 }, /* R859 */
- { 0x0000, 0x0000 }, /* R860 */
- { 0x0000, 0x0000 }, /* R861 */
- { 0x0000, 0x0000 }, /* R862 */
- { 0x0000, 0x0000 }, /* R863 */
- { 0x0000, 0x0000 }, /* R864 */
- { 0x0000, 0x0000 }, /* R865 */
- { 0x0000, 0x0000 }, /* R866 */
- { 0x0000, 0x0000 }, /* R867 */
- { 0x0000, 0x0000 }, /* R868 */
- { 0x0000, 0x0000 }, /* R869 */
- { 0x0000, 0x0000 }, /* R870 */
- { 0x0000, 0x0000 }, /* R871 */
- { 0x0000, 0x0000 }, /* R872 */
- { 0x0000, 0x0000 }, /* R873 */
- { 0x0000, 0x0000 }, /* R874 */
- { 0x0000, 0x0000 }, /* R875 */
- { 0x0000, 0x0000 }, /* R876 */
- { 0x0000, 0x0000 }, /* R877 */
- { 0x0000, 0x0000 }, /* R878 */
- { 0x0000, 0x0000 }, /* R879 */
- { 0x0000, 0x0000 }, /* R880 */
- { 0x0000, 0x0000 }, /* R881 */
- { 0x0000, 0x0000 }, /* R882 */
- { 0x0000, 0x0000 }, /* R883 */
- { 0x0000, 0x0000 }, /* R884 */
- { 0x0000, 0x0000 }, /* R885 */
- { 0x0000, 0x0000 }, /* R886 */
- { 0x0000, 0x0000 }, /* R887 */
- { 0x0000, 0x0000 }, /* R888 */
- { 0x0000, 0x0000 }, /* R889 */
- { 0x0000, 0x0000 }, /* R890 */
- { 0x0000, 0x0000 }, /* R891 */
- { 0x0000, 0x0000 }, /* R892 */
- { 0x0000, 0x0000 }, /* R893 */
- { 0x0000, 0x0000 }, /* R894 */
- { 0x0000, 0x0000 }, /* R895 */
- { 0x0000, 0x0000 }, /* R896 */
- { 0x0000, 0x0000 }, /* R897 */
- { 0x0000, 0x0000 }, /* R898 */
- { 0x0000, 0x0000 }, /* R899 */
- { 0x0000, 0x0000 }, /* R900 */
- { 0x0000, 0x0000 }, /* R901 */
- { 0x0000, 0x0000 }, /* R902 */
- { 0x0000, 0x0000 }, /* R903 */
- { 0x0000, 0x0000 }, /* R904 */
- { 0x0000, 0x0000 }, /* R905 */
- { 0x0000, 0x0000 }, /* R906 */
- { 0x0000, 0x0000 }, /* R907 */
- { 0x0000, 0x0000 }, /* R908 */
- { 0x0000, 0x0000 }, /* R909 */
- { 0x0000, 0x0000 }, /* R910 */
- { 0x0000, 0x0000 }, /* R911 */
- { 0x0000, 0x0000 }, /* R912 */
- { 0x0000, 0x0000 }, /* R913 */
- { 0x0000, 0x0000 }, /* R914 */
- { 0x0000, 0x0000 }, /* R915 */
- { 0x0000, 0x0000 }, /* R916 */
- { 0x0000, 0x0000 }, /* R917 */
- { 0x0000, 0x0000 }, /* R918 */
- { 0x0000, 0x0000 }, /* R919 */
- { 0x0000, 0x0000 }, /* R920 */
- { 0x0000, 0x0000 }, /* R921 */
- { 0x0000, 0x0000 }, /* R922 */
- { 0x0000, 0x0000 }, /* R923 */
- { 0x0000, 0x0000 }, /* R924 */
- { 0x0000, 0x0000 }, /* R925 */
- { 0x0000, 0x0000 }, /* R926 */
- { 0x0000, 0x0000 }, /* R927 */
- { 0x0000, 0x0000 }, /* R928 */
- { 0x0000, 0x0000 }, /* R929 */
- { 0x0000, 0x0000 }, /* R930 */
- { 0x0000, 0x0000 }, /* R931 */
- { 0x0000, 0x0000 }, /* R932 */
- { 0x0000, 0x0000 }, /* R933 */
- { 0x0000, 0x0000 }, /* R934 */
- { 0x0000, 0x0000 }, /* R935 */
- { 0x0000, 0x0000 }, /* R936 */
- { 0x0000, 0x0000 }, /* R937 */
- { 0x0000, 0x0000 }, /* R938 */
- { 0x0000, 0x0000 }, /* R939 */
- { 0x0000, 0x0000 }, /* R940 */
- { 0x0000, 0x0000 }, /* R941 */
- { 0x0000, 0x0000 }, /* R942 */
- { 0x0000, 0x0000 }, /* R943 */
- { 0x0000, 0x0000 }, /* R944 */
- { 0x0000, 0x0000 }, /* R945 */
- { 0x0000, 0x0000 }, /* R946 */
- { 0x0000, 0x0000 }, /* R947 */
- { 0x0000, 0x0000 }, /* R948 */
- { 0x0000, 0x0000 }, /* R949 */
- { 0x0000, 0x0000 }, /* R950 */
- { 0x0000, 0x0000 }, /* R951 */
- { 0x0000, 0x0000 }, /* R952 */
- { 0x0000, 0x0000 }, /* R953 */
- { 0x0000, 0x0000 }, /* R954 */
- { 0x0000, 0x0000 }, /* R955 */
- { 0x0000, 0x0000 }, /* R956 */
- { 0x0000, 0x0000 }, /* R957 */
- { 0x0000, 0x0000 }, /* R958 */
- { 0x0000, 0x0000 }, /* R959 */
- { 0x0000, 0x0000 }, /* R960 */
- { 0x0000, 0x0000 }, /* R961 */
- { 0x0000, 0x0000 }, /* R962 */
- { 0x0000, 0x0000 }, /* R963 */
- { 0x0000, 0x0000 }, /* R964 */
- { 0x0000, 0x0000 }, /* R965 */
- { 0x0000, 0x0000 }, /* R966 */
- { 0x0000, 0x0000 }, /* R967 */
- { 0x0000, 0x0000 }, /* R968 */
- { 0x0000, 0x0000 }, /* R969 */
- { 0x0000, 0x0000 }, /* R970 */
- { 0x0000, 0x0000 }, /* R971 */
- { 0x0000, 0x0000 }, /* R972 */
- { 0x0000, 0x0000 }, /* R973 */
- { 0x0000, 0x0000 }, /* R974 */
- { 0x0000, 0x0000 }, /* R975 */
- { 0x0000, 0x0000 }, /* R976 */
- { 0x0000, 0x0000 }, /* R977 */
- { 0x0000, 0x0000 }, /* R978 */
- { 0x0000, 0x0000 }, /* R979 */
- { 0x0000, 0x0000 }, /* R980 */
- { 0x0000, 0x0000 }, /* R981 */
- { 0x0000, 0x0000 }, /* R982 */
- { 0x0000, 0x0000 }, /* R983 */
- { 0x0000, 0x0000 }, /* R984 */
- { 0x0000, 0x0000 }, /* R985 */
- { 0x0000, 0x0000 }, /* R986 */
- { 0x0000, 0x0000 }, /* R987 */
- { 0x0000, 0x0000 }, /* R988 */
- { 0x0000, 0x0000 }, /* R989 */
- { 0x0000, 0x0000 }, /* R990 */
- { 0x0000, 0x0000 }, /* R991 */
- { 0x0000, 0x0000 }, /* R992 */
- { 0x0000, 0x0000 }, /* R993 */
- { 0x0000, 0x0000 }, /* R994 */
- { 0x0000, 0x0000 }, /* R995 */
- { 0x0000, 0x0000 }, /* R996 */
- { 0x0000, 0x0000 }, /* R997 */
- { 0x0000, 0x0000 }, /* R998 */
- { 0x0000, 0x0000 }, /* R999 */
- { 0x0000, 0x0000 }, /* R1000 */
- { 0x0000, 0x0000 }, /* R1001 */
- { 0x0000, 0x0000 }, /* R1002 */
- { 0x0000, 0x0000 }, /* R1003 */
- { 0x0000, 0x0000 }, /* R1004 */
- { 0x0000, 0x0000 }, /* R1005 */
- { 0x0000, 0x0000 }, /* R1006 */
- { 0x0000, 0x0000 }, /* R1007 */
- { 0x0000, 0x0000 }, /* R1008 */
- { 0x0000, 0x0000 }, /* R1009 */
- { 0x0000, 0x0000 }, /* R1010 */
- { 0x0000, 0x0000 }, /* R1011 */
- { 0x0000, 0x0000 }, /* R1012 */
- { 0x0000, 0x0000 }, /* R1013 */
- { 0x0000, 0x0000 }, /* R1014 */
- { 0x0000, 0x0000 }, /* R1015 */
- { 0x0000, 0x0000 }, /* R1016 */
- { 0x0000, 0x0000 }, /* R1017 */
- { 0x0000, 0x0000 }, /* R1018 */
- { 0x0000, 0x0000 }, /* R1019 */
- { 0x0000, 0x0000 }, /* R1020 */
- { 0x0000, 0x0000 }, /* R1021 */
- { 0x0000, 0x0000 }, /* R1022 */
- { 0x0000, 0x0000 }, /* R1023 */
- { 0x00FF, 0x01FF }, /* R1024 - AIF1 ADC1 Left Volume */
- { 0x00FF, 0x01FF }, /* R1025 - AIF1 ADC1 Right Volume */
- { 0x00FF, 0x01FF }, /* R1026 - AIF1 DAC1 Left Volume */
- { 0x00FF, 0x01FF }, /* R1027 - AIF1 DAC1 Right Volume */
- { 0x00FF, 0x01FF }, /* R1028 - AIF1 ADC2 Left Volume */
- { 0x00FF, 0x01FF }, /* R1029 - AIF1 ADC2 Right Volume */
- { 0x00FF, 0x01FF }, /* R1030 - AIF1 DAC2 Left Volume */
- { 0x00FF, 0x01FF }, /* R1031 - AIF1 DAC2 Right Volume */
- { 0x0000, 0x0000 }, /* R1032 */
- { 0x0000, 0x0000 }, /* R1033 */
- { 0x0000, 0x0000 }, /* R1034 */
- { 0x0000, 0x0000 }, /* R1035 */
- { 0x0000, 0x0000 }, /* R1036 */
- { 0x0000, 0x0000 }, /* R1037 */
- { 0x0000, 0x0000 }, /* R1038 */
- { 0x0000, 0x0000 }, /* R1039 */
- { 0xF800, 0xF800 }, /* R1040 - AIF1 ADC1 Filters */
- { 0x7800, 0x7800 }, /* R1041 - AIF1 ADC2 Filters */
- { 0x0000, 0x0000 }, /* R1042 */
- { 0x0000, 0x0000 }, /* R1043 */
- { 0x0000, 0x0000 }, /* R1044 */
- { 0x0000, 0x0000 }, /* R1045 */
- { 0x0000, 0x0000 }, /* R1046 */
- { 0x0000, 0x0000 }, /* R1047 */
- { 0x0000, 0x0000 }, /* R1048 */
- { 0x0000, 0x0000 }, /* R1049 */
- { 0x0000, 0x0000 }, /* R1050 */
- { 0x0000, 0x0000 }, /* R1051 */
- { 0x0000, 0x0000 }, /* R1052 */
- { 0x0000, 0x0000 }, /* R1053 */
- { 0x0000, 0x0000 }, /* R1054 */
- { 0x0000, 0x0000 }, /* R1055 */
- { 0x02B6, 0x02B6 }, /* R1056 - AIF1 DAC1 Filters (1) */
- { 0x3F00, 0x3F00 }, /* R1057 - AIF1 DAC1 Filters (2) */
- { 0x02B6, 0x02B6 }, /* R1058 - AIF1 DAC2 Filters (1) */
- { 0x3F00, 0x3F00 }, /* R1059 - AIF1 DAC2 Filters (2) */
- { 0x0000, 0x0000 }, /* R1060 */
- { 0x0000, 0x0000 }, /* R1061 */
- { 0x0000, 0x0000 }, /* R1062 */
- { 0x0000, 0x0000 }, /* R1063 */
- { 0x0000, 0x0000 }, /* R1064 */
- { 0x0000, 0x0000 }, /* R1065 */
- { 0x0000, 0x0000 }, /* R1066 */
- { 0x0000, 0x0000 }, /* R1067 */
- { 0x0000, 0x0000 }, /* R1068 */
- { 0x0000, 0x0000 }, /* R1069 */
- { 0x0000, 0x0000 }, /* R1070 */
- { 0x0000, 0x0000 }, /* R1071 */
- { 0x0000, 0x0000 }, /* R1072 */
- { 0x0000, 0x0000 }, /* R1073 */
- { 0x0000, 0x0000 }, /* R1074 */
- { 0x0000, 0x0000 }, /* R1075 */
- { 0x0000, 0x0000 }, /* R1076 */
- { 0x0000, 0x0000 }, /* R1077 */
- { 0x0000, 0x0000 }, /* R1078 */
- { 0x0000, 0x0000 }, /* R1079 */
- { 0x0000, 0x0000 }, /* R1080 */
- { 0x0000, 0x0000 }, /* R1081 */
- { 0x0000, 0x0000 }, /* R1082 */
- { 0x0000, 0x0000 }, /* R1083 */
- { 0x0000, 0x0000 }, /* R1084 */
- { 0x0000, 0x0000 }, /* R1085 */
- { 0x0000, 0x0000 }, /* R1086 */
- { 0x0000, 0x0000 }, /* R1087 */
- { 0xFFFF, 0xFFFF }, /* R1088 - AIF1 DRC1 (1) */
- { 0x1FFF, 0x1FFF }, /* R1089 - AIF1 DRC1 (2) */
- { 0xFFFF, 0xFFFF }, /* R1090 - AIF1 DRC1 (3) */
- { 0x07FF, 0x07FF }, /* R1091 - AIF1 DRC1 (4) */
- { 0x03FF, 0x03FF }, /* R1092 - AIF1 DRC1 (5) */
- { 0x0000, 0x0000 }, /* R1093 */
- { 0x0000, 0x0000 }, /* R1094 */
- { 0x0000, 0x0000 }, /* R1095 */
- { 0x0000, 0x0000 }, /* R1096 */
- { 0x0000, 0x0000 }, /* R1097 */
- { 0x0000, 0x0000 }, /* R1098 */
- { 0x0000, 0x0000 }, /* R1099 */
- { 0x0000, 0x0000 }, /* R1100 */
- { 0x0000, 0x0000 }, /* R1101 */
- { 0x0000, 0x0000 }, /* R1102 */
- { 0x0000, 0x0000 }, /* R1103 */
- { 0xFFFF, 0xFFFF }, /* R1104 - AIF1 DRC2 (1) */
- { 0x1FFF, 0x1FFF }, /* R1105 - AIF1 DRC2 (2) */
- { 0xFFFF, 0xFFFF }, /* R1106 - AIF1 DRC2 (3) */
- { 0x07FF, 0x07FF }, /* R1107 - AIF1 DRC2 (4) */
- { 0x03FF, 0x03FF }, /* R1108 - AIF1 DRC2 (5) */
- { 0x0000, 0x0000 }, /* R1109 */
- { 0x0000, 0x0000 }, /* R1110 */
- { 0x0000, 0x0000 }, /* R1111 */
- { 0x0000, 0x0000 }, /* R1112 */
- { 0x0000, 0x0000 }, /* R1113 */
- { 0x0000, 0x0000 }, /* R1114 */
- { 0x0000, 0x0000 }, /* R1115 */
- { 0x0000, 0x0000 }, /* R1116 */
- { 0x0000, 0x0000 }, /* R1117 */
- { 0x0000, 0x0000 }, /* R1118 */
- { 0x0000, 0x0000 }, /* R1119 */
- { 0x0000, 0x0000 }, /* R1120 */
- { 0x0000, 0x0000 }, /* R1121 */
- { 0x0000, 0x0000 }, /* R1122 */
- { 0x0000, 0x0000 }, /* R1123 */
- { 0x0000, 0x0000 }, /* R1124 */
- { 0x0000, 0x0000 }, /* R1125 */
- { 0x0000, 0x0000 }, /* R1126 */
- { 0x0000, 0x0000 }, /* R1127 */
- { 0x0000, 0x0000 }, /* R1128 */
- { 0x0000, 0x0000 }, /* R1129 */
- { 0x0000, 0x0000 }, /* R1130 */
- { 0x0000, 0x0000 }, /* R1131 */
- { 0x0000, 0x0000 }, /* R1132 */
- { 0x0000, 0x0000 }, /* R1133 */
- { 0x0000, 0x0000 }, /* R1134 */
- { 0x0000, 0x0000 }, /* R1135 */
- { 0x0000, 0x0000 }, /* R1136 */
- { 0x0000, 0x0000 }, /* R1137 */
- { 0x0000, 0x0000 }, /* R1138 */
- { 0x0000, 0x0000 }, /* R1139 */
- { 0x0000, 0x0000 }, /* R1140 */
- { 0x0000, 0x0000 }, /* R1141 */
- { 0x0000, 0x0000 }, /* R1142 */
- { 0x0000, 0x0000 }, /* R1143 */
- { 0x0000, 0x0000 }, /* R1144 */
- { 0x0000, 0x0000 }, /* R1145 */
- { 0x0000, 0x0000 }, /* R1146 */
- { 0x0000, 0x0000 }, /* R1147 */
- { 0x0000, 0x0000 }, /* R1148 */
- { 0x0000, 0x0000 }, /* R1149 */
- { 0x0000, 0x0000 }, /* R1150 */
- { 0x0000, 0x0000 }, /* R1151 */
- { 0xFFFF, 0xFFFF }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
- { 0xFFC0, 0xFFC0 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
- { 0xFFFF, 0xFFFF }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
- { 0xFFFF, 0xFFFF }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
- { 0xFFFF, 0xFFFF }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
- { 0xFFFF, 0xFFFF }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
- { 0xFFFF, 0xFFFF }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
- { 0xFFFF, 0xFFFF }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
- { 0xFFFF, 0xFFFF }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
- { 0xFFFF, 0xFFFF }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
- { 0xFFFF, 0xFFFF }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
- { 0xFFFF, 0xFFFF }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
- { 0xFFFF, 0xFFFF }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
- { 0xFFFF, 0xFFFF }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
- { 0xFFFF, 0xFFFF }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
- { 0xFFFF, 0xFFFF }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
- { 0xFFFF, 0xFFFF }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
- { 0xFFFF, 0xFFFF }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
- { 0xFFFF, 0xFFFF }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
- { 0xFFFF, 0xFFFF }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
- { 0x0000, 0x0000 }, /* R1172 */
- { 0x0000, 0x0000 }, /* R1173 */
- { 0x0000, 0x0000 }, /* R1174 */
- { 0x0000, 0x0000 }, /* R1175 */
- { 0x0000, 0x0000 }, /* R1176 */
- { 0x0000, 0x0000 }, /* R1177 */
- { 0x0000, 0x0000 }, /* R1178 */
- { 0x0000, 0x0000 }, /* R1179 */
- { 0x0000, 0x0000 }, /* R1180 */
- { 0x0000, 0x0000 }, /* R1181 */
- { 0x0000, 0x0000 }, /* R1182 */
- { 0x0000, 0x0000 }, /* R1183 */
- { 0xFFFF, 0xFFFF }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
- { 0xFFC0, 0xFFC0 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
- { 0xFFFF, 0xFFFF }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
- { 0xFFFF, 0xFFFF }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
- { 0xFFFF, 0xFFFF }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
- { 0xFFFF, 0xFFFF }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
- { 0xFFFF, 0xFFFF }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
- { 0xFFFF, 0xFFFF }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
- { 0xFFFF, 0xFFFF }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
- { 0xFFFF, 0xFFFF }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
- { 0xFFFF, 0xFFFF }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
- { 0xFFFF, 0xFFFF }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
- { 0xFFFF, 0xFFFF }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
- { 0xFFFF, 0xFFFF }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
- { 0xFFFF, 0xFFFF }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
- { 0xFFFF, 0xFFFF }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
- { 0xFFFF, 0xFFFF }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
- { 0xFFFF, 0xFFFF }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
- { 0xFFFF, 0xFFFF }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
- { 0xFFFF, 0xFFFF }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
- { 0x0000, 0x0000 }, /* R1204 */
- { 0x0000, 0x0000 }, /* R1205 */
- { 0x0000, 0x0000 }, /* R1206 */
- { 0x0000, 0x0000 }, /* R1207 */
- { 0x0000, 0x0000 }, /* R1208 */
- { 0x0000, 0x0000 }, /* R1209 */
- { 0x0000, 0x0000 }, /* R1210 */
- { 0x0000, 0x0000 }, /* R1211 */
- { 0x0000, 0x0000 }, /* R1212 */
- { 0x0000, 0x0000 }, /* R1213 */
- { 0x0000, 0x0000 }, /* R1214 */
- { 0x0000, 0x0000 }, /* R1215 */
- { 0x0000, 0x0000 }, /* R1216 */
- { 0x0000, 0x0000 }, /* R1217 */
- { 0x0000, 0x0000 }, /* R1218 */
- { 0x0000, 0x0000 }, /* R1219 */
- { 0x0000, 0x0000 }, /* R1220 */
- { 0x0000, 0x0000 }, /* R1221 */
- { 0x0000, 0x0000 }, /* R1222 */
- { 0x0000, 0x0000 }, /* R1223 */
- { 0x0000, 0x0000 }, /* R1224 */
- { 0x0000, 0x0000 }, /* R1225 */
- { 0x0000, 0x0000 }, /* R1226 */
- { 0x0000, 0x0000 }, /* R1227 */
- { 0x0000, 0x0000 }, /* R1228 */
- { 0x0000, 0x0000 }, /* R1229 */
- { 0x0000, 0x0000 }, /* R1230 */
- { 0x0000, 0x0000 }, /* R1231 */
- { 0x0000, 0x0000 }, /* R1232 */
- { 0x0000, 0x0000 }, /* R1233 */
- { 0x0000, 0x0000 }, /* R1234 */
- { 0x0000, 0x0000 }, /* R1235 */
- { 0x0000, 0x0000 }, /* R1236 */
- { 0x0000, 0x0000 }, /* R1237 */
- { 0x0000, 0x0000 }, /* R1238 */
- { 0x0000, 0x0000 }, /* R1239 */
- { 0x0000, 0x0000 }, /* R1240 */
- { 0x0000, 0x0000 }, /* R1241 */
- { 0x0000, 0x0000 }, /* R1242 */
- { 0x0000, 0x0000 }, /* R1243 */
- { 0x0000, 0x0000 }, /* R1244 */
- { 0x0000, 0x0000 }, /* R1245 */
- { 0x0000, 0x0000 }, /* R1246 */
- { 0x0000, 0x0000 }, /* R1247 */
- { 0x0000, 0x0000 }, /* R1248 */
- { 0x0000, 0x0000 }, /* R1249 */
- { 0x0000, 0x0000 }, /* R1250 */
- { 0x0000, 0x0000 }, /* R1251 */
- { 0x0000, 0x0000 }, /* R1252 */
- { 0x0000, 0x0000 }, /* R1253 */
- { 0x0000, 0x0000 }, /* R1254 */
- { 0x0000, 0x0000 }, /* R1255 */
- { 0x0000, 0x0000 }, /* R1256 */
- { 0x0000, 0x0000 }, /* R1257 */
- { 0x0000, 0x0000 }, /* R1258 */
- { 0x0000, 0x0000 }, /* R1259 */
- { 0x0000, 0x0000 }, /* R1260 */
- { 0x0000, 0x0000 }, /* R1261 */
- { 0x0000, 0x0000 }, /* R1262 */
- { 0x0000, 0x0000 }, /* R1263 */
- { 0x0000, 0x0000 }, /* R1264 */
- { 0x0000, 0x0000 }, /* R1265 */
- { 0x0000, 0x0000 }, /* R1266 */
- { 0x0000, 0x0000 }, /* R1267 */
- { 0x0000, 0x0000 }, /* R1268 */
- { 0x0000, 0x0000 }, /* R1269 */
- { 0x0000, 0x0000 }, /* R1270 */
- { 0x0000, 0x0000 }, /* R1271 */
- { 0x0000, 0x0000 }, /* R1272 */
- { 0x0000, 0x0000 }, /* R1273 */
- { 0x0000, 0x0000 }, /* R1274 */
- { 0x0000, 0x0000 }, /* R1275 */
- { 0x0000, 0x0000 }, /* R1276 */
- { 0x0000, 0x0000 }, /* R1277 */
- { 0x0000, 0x0000 }, /* R1278 */
- { 0x0000, 0x0000 }, /* R1279 */
- { 0x00FF, 0x01FF }, /* R1280 - AIF2 ADC Left Volume */
- { 0x00FF, 0x01FF }, /* R1281 - AIF2 ADC Right Volume */
- { 0x00FF, 0x01FF }, /* R1282 - AIF2 DAC Left Volume */
- { 0x00FF, 0x01FF }, /* R1283 - AIF2 DAC Right Volume */
- { 0x0000, 0x0000 }, /* R1284 */
- { 0x0000, 0x0000 }, /* R1285 */
- { 0x0000, 0x0000 }, /* R1286 */
- { 0x0000, 0x0000 }, /* R1287 */
- { 0x0000, 0x0000 }, /* R1288 */
- { 0x0000, 0x0000 }, /* R1289 */
- { 0x0000, 0x0000 }, /* R1290 */
- { 0x0000, 0x0000 }, /* R1291 */
- { 0x0000, 0x0000 }, /* R1292 */
- { 0x0000, 0x0000 }, /* R1293 */
- { 0x0000, 0x0000 }, /* R1294 */
- { 0x0000, 0x0000 }, /* R1295 */
- { 0xF800, 0xF800 }, /* R1296 - AIF2 ADC Filters */
- { 0x0000, 0x0000 }, /* R1297 */
- { 0x0000, 0x0000 }, /* R1298 */
- { 0x0000, 0x0000 }, /* R1299 */
- { 0x0000, 0x0000 }, /* R1300 */
- { 0x0000, 0x0000 }, /* R1301 */
- { 0x0000, 0x0000 }, /* R1302 */
- { 0x0000, 0x0000 }, /* R1303 */
- { 0x0000, 0x0000 }, /* R1304 */
- { 0x0000, 0x0000 }, /* R1305 */
- { 0x0000, 0x0000 }, /* R1306 */
- { 0x0000, 0x0000 }, /* R1307 */
- { 0x0000, 0x0000 }, /* R1308 */
- { 0x0000, 0x0000 }, /* R1309 */
- { 0x0000, 0x0000 }, /* R1310 */
- { 0x0000, 0x0000 }, /* R1311 */
- { 0x02B6, 0x02B6 }, /* R1312 - AIF2 DAC Filters (1) */
- { 0x3F00, 0x3F00 }, /* R1313 - AIF2 DAC Filters (2) */
- { 0x0000, 0x0000 }, /* R1314 */
- { 0x0000, 0x0000 }, /* R1315 */
- { 0x0000, 0x0000 }, /* R1316 */
- { 0x0000, 0x0000 }, /* R1317 */
- { 0x0000, 0x0000 }, /* R1318 */
- { 0x0000, 0x0000 }, /* R1319 */
- { 0x0000, 0x0000 }, /* R1320 */
- { 0x0000, 0x0000 }, /* R1321 */
- { 0x0000, 0x0000 }, /* R1322 */
- { 0x0000, 0x0000 }, /* R1323 */
- { 0x0000, 0x0000 }, /* R1324 */
- { 0x0000, 0x0000 }, /* R1325 */
- { 0x0000, 0x0000 }, /* R1326 */
- { 0x0000, 0x0000 }, /* R1327 */
- { 0x0000, 0x0000 }, /* R1328 */
- { 0x0000, 0x0000 }, /* R1329 */
- { 0x0000, 0x0000 }, /* R1330 */
- { 0x0000, 0x0000 }, /* R1331 */
- { 0x0000, 0x0000 }, /* R1332 */
- { 0x0000, 0x0000 }, /* R1333 */
- { 0x0000, 0x0000 }, /* R1334 */
- { 0x0000, 0x0000 }, /* R1335 */
- { 0x0000, 0x0000 }, /* R1336 */
- { 0x0000, 0x0000 }, /* R1337 */
- { 0x0000, 0x0000 }, /* R1338 */
- { 0x0000, 0x0000 }, /* R1339 */
- { 0x0000, 0x0000 }, /* R1340 */
- { 0x0000, 0x0000 }, /* R1341 */
- { 0x0000, 0x0000 }, /* R1342 */
- { 0x0000, 0x0000 }, /* R1343 */
- { 0xFFFF, 0xFFFF }, /* R1344 - AIF2 DRC (1) */
- { 0x1FFF, 0x1FFF }, /* R1345 - AIF2 DRC (2) */
- { 0xFFFF, 0xFFFF }, /* R1346 - AIF2 DRC (3) */
- { 0x07FF, 0x07FF }, /* R1347 - AIF2 DRC (4) */
- { 0x03FF, 0x03FF }, /* R1348 - AIF2 DRC (5) */
- { 0x0000, 0x0000 }, /* R1349 */
- { 0x0000, 0x0000 }, /* R1350 */
- { 0x0000, 0x0000 }, /* R1351 */
- { 0x0000, 0x0000 }, /* R1352 */
- { 0x0000, 0x0000 }, /* R1353 */
- { 0x0000, 0x0000 }, /* R1354 */
- { 0x0000, 0x0000 }, /* R1355 */
- { 0x0000, 0x0000 }, /* R1356 */
- { 0x0000, 0x0000 }, /* R1357 */
- { 0x0000, 0x0000 }, /* R1358 */
- { 0x0000, 0x0000 }, /* R1359 */
- { 0x0000, 0x0000 }, /* R1360 */
- { 0x0000, 0x0000 }, /* R1361 */
- { 0x0000, 0x0000 }, /* R1362 */
- { 0x0000, 0x0000 }, /* R1363 */
- { 0x0000, 0x0000 }, /* R1364 */
- { 0x0000, 0x0000 }, /* R1365 */
- { 0x0000, 0x0000 }, /* R1366 */
- { 0x0000, 0x0000 }, /* R1367 */
- { 0x0000, 0x0000 }, /* R1368 */
- { 0x0000, 0x0000 }, /* R1369 */
- { 0x0000, 0x0000 }, /* R1370 */
- { 0x0000, 0x0000 }, /* R1371 */
- { 0x0000, 0x0000 }, /* R1372 */
- { 0x0000, 0x0000 }, /* R1373 */
- { 0x0000, 0x0000 }, /* R1374 */
- { 0x0000, 0x0000 }, /* R1375 */
- { 0x0000, 0x0000 }, /* R1376 */
- { 0x0000, 0x0000 }, /* R1377 */
- { 0x0000, 0x0000 }, /* R1378 */
- { 0x0000, 0x0000 }, /* R1379 */
- { 0x0000, 0x0000 }, /* R1380 */
- { 0x0000, 0x0000 }, /* R1381 */
- { 0x0000, 0x0000 }, /* R1382 */
- { 0x0000, 0x0000 }, /* R1383 */
- { 0x0000, 0x0000 }, /* R1384 */
- { 0x0000, 0x0000 }, /* R1385 */
- { 0x0000, 0x0000 }, /* R1386 */
- { 0x0000, 0x0000 }, /* R1387 */
- { 0x0000, 0x0000 }, /* R1388 */
- { 0x0000, 0x0000 }, /* R1389 */
- { 0x0000, 0x0000 }, /* R1390 */
- { 0x0000, 0x0000 }, /* R1391 */
- { 0x0000, 0x0000 }, /* R1392 */
- { 0x0000, 0x0000 }, /* R1393 */
- { 0x0000, 0x0000 }, /* R1394 */
- { 0x0000, 0x0000 }, /* R1395 */
- { 0x0000, 0x0000 }, /* R1396 */
- { 0x0000, 0x0000 }, /* R1397 */
- { 0x0000, 0x0000 }, /* R1398 */
- { 0x0000, 0x0000 }, /* R1399 */
- { 0x0000, 0x0000 }, /* R1400 */
- { 0x0000, 0x0000 }, /* R1401 */
- { 0x0000, 0x0000 }, /* R1402 */
- { 0x0000, 0x0000 }, /* R1403 */
- { 0x0000, 0x0000 }, /* R1404 */
- { 0x0000, 0x0000 }, /* R1405 */
- { 0x0000, 0x0000 }, /* R1406 */
- { 0x0000, 0x0000 }, /* R1407 */
- { 0xFFFF, 0xFFFF }, /* R1408 - AIF2 EQ Gains (1) */
- { 0xFFC0, 0xFFC0 }, /* R1409 - AIF2 EQ Gains (2) */
- { 0xFFFF, 0xFFFF }, /* R1410 - AIF2 EQ Band 1 A */
- { 0xFFFF, 0xFFFF }, /* R1411 - AIF2 EQ Band 1 B */
- { 0xFFFF, 0xFFFF }, /* R1412 - AIF2 EQ Band 1 PG */
- { 0xFFFF, 0xFFFF }, /* R1413 - AIF2 EQ Band 2 A */
- { 0xFFFF, 0xFFFF }, /* R1414 - AIF2 EQ Band 2 B */
- { 0xFFFF, 0xFFFF }, /* R1415 - AIF2 EQ Band 2 C */
- { 0xFFFF, 0xFFFF }, /* R1416 - AIF2 EQ Band 2 PG */
- { 0xFFFF, 0xFFFF }, /* R1417 - AIF2 EQ Band 3 A */
- { 0xFFFF, 0xFFFF }, /* R1418 - AIF2 EQ Band 3 B */
- { 0xFFFF, 0xFFFF }, /* R1419 - AIF2 EQ Band 3 C */
- { 0xFFFF, 0xFFFF }, /* R1420 - AIF2 EQ Band 3 PG */
- { 0xFFFF, 0xFFFF }, /* R1421 - AIF2 EQ Band 4 A */
- { 0xFFFF, 0xFFFF }, /* R1422 - AIF2 EQ Band 4 B */
- { 0xFFFF, 0xFFFF }, /* R1423 - AIF2 EQ Band 4 C */
- { 0xFFFF, 0xFFFF }, /* R1424 - AIF2 EQ Band 4 PG */
- { 0xFFFF, 0xFFFF }, /* R1425 - AIF2 EQ Band 5 A */
- { 0xFFFF, 0xFFFF }, /* R1426 - AIF2 EQ Band 5 B */
- { 0xFFFF, 0xFFFF }, /* R1427 - AIF2 EQ Band 5 PG */
- { 0x0000, 0x0000 }, /* R1428 */
- { 0x0000, 0x0000 }, /* R1429 */
- { 0x0000, 0x0000 }, /* R1430 */
- { 0x0000, 0x0000 }, /* R1431 */
- { 0x0000, 0x0000 }, /* R1432 */
- { 0x0000, 0x0000 }, /* R1433 */
- { 0x0000, 0x0000 }, /* R1434 */
- { 0x0000, 0x0000 }, /* R1435 */
- { 0x0000, 0x0000 }, /* R1436 */
- { 0x0000, 0x0000 }, /* R1437 */
- { 0x0000, 0x0000 }, /* R1438 */
- { 0x0000, 0x0000 }, /* R1439 */
- { 0x0000, 0x0000 }, /* R1440 */
- { 0x0000, 0x0000 }, /* R1441 */
- { 0x0000, 0x0000 }, /* R1442 */
- { 0x0000, 0x0000 }, /* R1443 */
- { 0x0000, 0x0000 }, /* R1444 */
- { 0x0000, 0x0000 }, /* R1445 */
- { 0x0000, 0x0000 }, /* R1446 */
- { 0x0000, 0x0000 }, /* R1447 */
- { 0x0000, 0x0000 }, /* R1448 */
- { 0x0000, 0x0000 }, /* R1449 */
- { 0x0000, 0x0000 }, /* R1450 */
- { 0x0000, 0x0000 }, /* R1451 */
- { 0x0000, 0x0000 }, /* R1452 */
- { 0x0000, 0x0000 }, /* R1453 */
- { 0x0000, 0x0000 }, /* R1454 */
- { 0x0000, 0x0000 }, /* R1455 */
- { 0x0000, 0x0000 }, /* R1456 */
- { 0x0000, 0x0000 }, /* R1457 */
- { 0x0000, 0x0000 }, /* R1458 */
- { 0x0000, 0x0000 }, /* R1459 */
- { 0x0000, 0x0000 }, /* R1460 */
- { 0x0000, 0x0000 }, /* R1461 */
- { 0x0000, 0x0000 }, /* R1462 */
- { 0x0000, 0x0000 }, /* R1463 */
- { 0x0000, 0x0000 }, /* R1464 */
- { 0x0000, 0x0000 }, /* R1465 */
- { 0x0000, 0x0000 }, /* R1466 */
- { 0x0000, 0x0000 }, /* R1467 */
- { 0x0000, 0x0000 }, /* R1468 */
- { 0x0000, 0x0000 }, /* R1469 */
- { 0x0000, 0x0000 }, /* R1470 */
- { 0x0000, 0x0000 }, /* R1471 */
- { 0x0000, 0x0000 }, /* R1472 */
- { 0x0000, 0x0000 }, /* R1473 */
- { 0x0000, 0x0000 }, /* R1474 */
- { 0x0000, 0x0000 }, /* R1475 */
- { 0x0000, 0x0000 }, /* R1476 */
- { 0x0000, 0x0000 }, /* R1477 */
- { 0x0000, 0x0000 }, /* R1478 */
- { 0x0000, 0x0000 }, /* R1479 */
- { 0x0000, 0x0000 }, /* R1480 */
- { 0x0000, 0x0000 }, /* R1481 */
- { 0x0000, 0x0000 }, /* R1482 */
- { 0x0000, 0x0000 }, /* R1483 */
- { 0x0000, 0x0000 }, /* R1484 */
- { 0x0000, 0x0000 }, /* R1485 */
- { 0x0000, 0x0000 }, /* R1486 */
- { 0x0000, 0x0000 }, /* R1487 */
- { 0x0000, 0x0000 }, /* R1488 */
- { 0x0000, 0x0000 }, /* R1489 */
- { 0x0000, 0x0000 }, /* R1490 */
- { 0x0000, 0x0000 }, /* R1491 */
- { 0x0000, 0x0000 }, /* R1492 */
- { 0x0000, 0x0000 }, /* R1493 */
- { 0x0000, 0x0000 }, /* R1494 */
- { 0x0000, 0x0000 }, /* R1495 */
- { 0x0000, 0x0000 }, /* R1496 */
- { 0x0000, 0x0000 }, /* R1497 */
- { 0x0000, 0x0000 }, /* R1498 */
- { 0x0000, 0x0000 }, /* R1499 */
- { 0x0000, 0x0000 }, /* R1500 */
- { 0x0000, 0x0000 }, /* R1501 */
- { 0x0000, 0x0000 }, /* R1502 */
- { 0x0000, 0x0000 }, /* R1503 */
- { 0x0000, 0x0000 }, /* R1504 */
- { 0x0000, 0x0000 }, /* R1505 */
- { 0x0000, 0x0000 }, /* R1506 */
- { 0x0000, 0x0000 }, /* R1507 */
- { 0x0000, 0x0000 }, /* R1508 */
- { 0x0000, 0x0000 }, /* R1509 */
- { 0x0000, 0x0000 }, /* R1510 */
- { 0x0000, 0x0000 }, /* R1511 */
- { 0x0000, 0x0000 }, /* R1512 */
- { 0x0000, 0x0000 }, /* R1513 */
- { 0x0000, 0x0000 }, /* R1514 */
- { 0x0000, 0x0000 }, /* R1515 */
- { 0x0000, 0x0000 }, /* R1516 */
- { 0x0000, 0x0000 }, /* R1517 */
- { 0x0000, 0x0000 }, /* R1518 */
- { 0x0000, 0x0000 }, /* R1519 */
- { 0x0000, 0x0000 }, /* R1520 */
- { 0x0000, 0x0000 }, /* R1521 */
- { 0x0000, 0x0000 }, /* R1522 */
- { 0x0000, 0x0000 }, /* R1523 */
- { 0x0000, 0x0000 }, /* R1524 */
- { 0x0000, 0x0000 }, /* R1525 */
- { 0x0000, 0x0000 }, /* R1526 */
- { 0x0000, 0x0000 }, /* R1527 */
- { 0x0000, 0x0000 }, /* R1528 */
- { 0x0000, 0x0000 }, /* R1529 */
- { 0x0000, 0x0000 }, /* R1530 */
- { 0x0000, 0x0000 }, /* R1531 */
- { 0x0000, 0x0000 }, /* R1532 */
- { 0x0000, 0x0000 }, /* R1533 */
- { 0x0000, 0x0000 }, /* R1534 */
- { 0x0000, 0x0000 }, /* R1535 */
- { 0x01EF, 0x01EF }, /* R1536 - DAC1 Mixer Volumes */
- { 0x0037, 0x0037 }, /* R1537 - DAC1 Left Mixer Routing */
- { 0x0037, 0x0037 }, /* R1538 - DAC1 Right Mixer Routing */
- { 0x01EF, 0x01EF }, /* R1539 - DAC2 Mixer Volumes */
- { 0x0037, 0x0037 }, /* R1540 - DAC2 Left Mixer Routing */
- { 0x0037, 0x0037 }, /* R1541 - DAC2 Right Mixer Routing */
- { 0x0003, 0x0003 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
- { 0x0003, 0x0003 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
- { 0x0003, 0x0003 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
- { 0x0003, 0x0003 }, /* R1545 - AIF1 ADC2 Right mixer Routing */
- { 0x0000, 0x0000 }, /* R1546 */
- { 0x0000, 0x0000 }, /* R1547 */
- { 0x0000, 0x0000 }, /* R1548 */
- { 0x0000, 0x0000 }, /* R1549 */
- { 0x0000, 0x0000 }, /* R1550 */
- { 0x0000, 0x0000 }, /* R1551 */
- { 0x02FF, 0x03FF }, /* R1552 - DAC1 Left Volume */
- { 0x02FF, 0x03FF }, /* R1553 - DAC1 Right Volume */
- { 0x02FF, 0x03FF }, /* R1554 - DAC2 Left Volume */
- { 0x02FF, 0x03FF }, /* R1555 - DAC2 Right Volume */
- { 0x0003, 0x0003 }, /* R1556 - DAC Softmute */
- { 0x0000, 0x0000 }, /* R1557 */
- { 0x0000, 0x0000 }, /* R1558 */
- { 0x0000, 0x0000 }, /* R1559 */
- { 0x0000, 0x0000 }, /* R1560 */
- { 0x0000, 0x0000 }, /* R1561 */
- { 0x0000, 0x0000 }, /* R1562 */
- { 0x0000, 0x0000 }, /* R1563 */
- { 0x0000, 0x0000 }, /* R1564 */
- { 0x0000, 0x0000 }, /* R1565 */
- { 0x0000, 0x0000 }, /* R1566 */
- { 0x0000, 0x0000 }, /* R1567 */
- { 0x0003, 0x0003 }, /* R1568 - Oversampling */
- { 0x03C3, 0x03C3 }, /* R1569 - Sidetone */
-};
-
-const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = {
- 0x8994, /* R0 - Software Reset */
- 0x0000, /* R1 - Power Management (1) */
- 0x6000, /* R2 - Power Management (2) */
- 0x0000, /* R3 - Power Management (3) */
- 0x0000, /* R4 - Power Management (4) */
- 0x0000, /* R5 - Power Management (5) */
- 0x0000, /* R6 - Power Management (6) */
- 0x0000, /* R7 */
- 0x0000, /* R8 */
- 0x0000, /* R9 */
- 0x0000, /* R10 */
- 0x0000, /* R11 */
- 0x0000, /* R12 */
- 0x0000, /* R13 */
- 0x0000, /* R14 */
- 0x0000, /* R15 */
- 0x0000, /* R16 */
- 0x0000, /* R17 */
- 0x0000, /* R18 */
- 0x0000, /* R19 */
- 0x0000, /* R20 */
- 0x0000, /* R21 - Input Mixer (1) */
- 0x0000, /* R22 */
- 0x0000, /* R23 */
- 0x008B, /* R24 - Left Line Input 1&2 Volume */
- 0x008B, /* R25 - Left Line Input 3&4 Volume */
- 0x008B, /* R26 - Right Line Input 1&2 Volume */
- 0x008B, /* R27 - Right Line Input 3&4 Volume */
- 0x006D, /* R28 - Left Output Volume */
- 0x006D, /* R29 - Right Output Volume */
- 0x0066, /* R30 - Line Outputs Volume */
- 0x0020, /* R31 - HPOUT2 Volume */
- 0x0079, /* R32 - Left OPGA Volume */
- 0x0079, /* R33 - Right OPGA Volume */
- 0x0003, /* R34 - SPKMIXL Attenuation */
- 0x0003, /* R35 - SPKMIXR Attenuation */
- 0x0011, /* R36 - SPKOUT Mixers */
- 0x0140, /* R37 - ClassD */
- 0x0079, /* R38 - Speaker Volume Left */
- 0x0079, /* R39 - Speaker Volume Right */
- 0x0000, /* R40 - Input Mixer (2) */
- 0x0000, /* R41 - Input Mixer (3) */
- 0x0000, /* R42 - Input Mixer (4) */
- 0x0000, /* R43 - Input Mixer (5) */
- 0x0000, /* R44 - Input Mixer (6) */
- 0x0000, /* R45 - Output Mixer (1) */
- 0x0000, /* R46 - Output Mixer (2) */
- 0x0000, /* R47 - Output Mixer (3) */
- 0x0000, /* R48 - Output Mixer (4) */
- 0x0000, /* R49 - Output Mixer (5) */
- 0x0000, /* R50 - Output Mixer (6) */
- 0x0000, /* R51 - HPOUT2 Mixer */
- 0x0000, /* R52 - Line Mixer (1) */
- 0x0000, /* R53 - Line Mixer (2) */
- 0x0000, /* R54 - Speaker Mixer */
- 0x0000, /* R55 - Additional Control */
- 0x0000, /* R56 - AntiPOP (1) */
- 0x0000, /* R57 - AntiPOP (2) */
- 0x0000, /* R58 - MICBIAS */
- 0x000D, /* R59 - LDO 1 */
- 0x0003, /* R60 - LDO 2 */
- 0x0000, /* R61 */
- 0x0000, /* R62 */
- 0x0000, /* R63 */
- 0x0000, /* R64 */
- 0x0000, /* R65 */
- 0x0000, /* R66 */
- 0x0000, /* R67 */
- 0x0000, /* R68 */
- 0x0000, /* R69 */
- 0x0000, /* R70 */
- 0x0000, /* R71 */
- 0x0000, /* R72 */
- 0x0000, /* R73 */
- 0x0000, /* R74 */
- 0x0000, /* R75 */
- 0x1F25, /* R76 - Charge Pump (1) */
- 0x0000, /* R77 */
- 0x0000, /* R78 */
- 0x0000, /* R79 */
- 0x0000, /* R80 */
- 0x0004, /* R81 - Class W (1) */
- 0x0000, /* R82 */
- 0x0000, /* R83 */
- 0x0000, /* R84 - DC Servo (1) */
- 0x054A, /* R85 - DC Servo (2) */
- 0x0000, /* R86 */
- 0x0000, /* R87 - DC Servo (4) */
- 0x0000, /* R88 - DC Servo Readback */
- 0x0000, /* R89 */
- 0x0000, /* R90 */
- 0x0000, /* R91 */
- 0x0000, /* R92 */
- 0x0000, /* R93 */
- 0x0000, /* R94 */
- 0x0000, /* R95 */
- 0x0000, /* R96 - Analogue HP (1) */
- 0x0000, /* R97 */
- 0x0000, /* R98 */
- 0x0000, /* R99 */
- 0x0000, /* R100 */
- 0x0000, /* R101 */
- 0x0000, /* R102 */
- 0x0000, /* R103 */
- 0x0000, /* R104 */
- 0x0000, /* R105 */
- 0x0000, /* R106 */
- 0x0000, /* R107 */
- 0x0000, /* R108 */
- 0x0000, /* R109 */
- 0x0000, /* R110 */
- 0x0000, /* R111 */
- 0x0000, /* R112 */
- 0x0000, /* R113 */
- 0x0000, /* R114 */
- 0x0000, /* R115 */
- 0x0000, /* R116 */
- 0x0000, /* R117 */
- 0x0000, /* R118 */
- 0x0000, /* R119 */
- 0x0000, /* R120 */
- 0x0000, /* R121 */
- 0x0000, /* R122 */
- 0x0000, /* R123 */
- 0x0000, /* R124 */
- 0x0000, /* R125 */
- 0x0000, /* R126 */
- 0x0000, /* R127 */
- 0x0000, /* R128 */
- 0x0000, /* R129 */
- 0x0000, /* R130 */
- 0x0000, /* R131 */
- 0x0000, /* R132 */
- 0x0000, /* R133 */
- 0x0000, /* R134 */
- 0x0000, /* R135 */
- 0x0000, /* R136 */
- 0x0000, /* R137 */
- 0x0000, /* R138 */
- 0x0000, /* R139 */
- 0x0000, /* R140 */
- 0x0000, /* R141 */
- 0x0000, /* R142 */
- 0x0000, /* R143 */
- 0x0000, /* R144 */
- 0x0000, /* R145 */
- 0x0000, /* R146 */
- 0x0000, /* R147 */
- 0x0000, /* R148 */
- 0x0000, /* R149 */
- 0x0000, /* R150 */
- 0x0000, /* R151 */
- 0x0000, /* R152 */
- 0x0000, /* R153 */
- 0x0000, /* R154 */
- 0x0000, /* R155 */
- 0x0000, /* R156 */
- 0x0000, /* R157 */
- 0x0000, /* R158 */
- 0x0000, /* R159 */
- 0x0000, /* R160 */
- 0x0000, /* R161 */
- 0x0000, /* R162 */
- 0x0000, /* R163 */
- 0x0000, /* R164 */
- 0x0000, /* R165 */
- 0x0000, /* R166 */
- 0x0000, /* R167 */
- 0x0000, /* R168 */
- 0x0000, /* R169 */
- 0x0000, /* R170 */
- 0x0000, /* R171 */
- 0x0000, /* R172 */
- 0x0000, /* R173 */
- 0x0000, /* R174 */
- 0x0000, /* R175 */
- 0x0000, /* R176 */
- 0x0000, /* R177 */
- 0x0000, /* R178 */
- 0x0000, /* R179 */
- 0x0000, /* R180 */
- 0x0000, /* R181 */
- 0x0000, /* R182 */
- 0x0000, /* R183 */
- 0x0000, /* R184 */
- 0x0000, /* R185 */
- 0x0000, /* R186 */
- 0x0000, /* R187 */
- 0x0000, /* R188 */
- 0x0000, /* R189 */
- 0x0000, /* R190 */
- 0x0000, /* R191 */
- 0x0000, /* R192 */
- 0x0000, /* R193 */
- 0x0000, /* R194 */
- 0x0000, /* R195 */
- 0x0000, /* R196 */
- 0x0000, /* R197 */
- 0x0000, /* R198 */
- 0x0000, /* R199 */
- 0x0000, /* R200 */
- 0x0000, /* R201 */
- 0x0000, /* R202 */
- 0x0000, /* R203 */
- 0x0000, /* R204 */
- 0x0000, /* R205 */
- 0x0000, /* R206 */
- 0x0000, /* R207 */
- 0x0000, /* R208 */
- 0x0000, /* R209 */
- 0x0000, /* R210 */
- 0x0000, /* R211 */
- 0x0000, /* R212 */
- 0x0000, /* R213 */
- 0x0000, /* R214 */
- 0x0000, /* R215 */
- 0x0000, /* R216 */
- 0x0000, /* R217 */
- 0x0000, /* R218 */
- 0x0000, /* R219 */
- 0x0000, /* R220 */
- 0x0000, /* R221 */
- 0x0000, /* R222 */
- 0x0000, /* R223 */
- 0x0000, /* R224 */
- 0x0000, /* R225 */
- 0x0000, /* R226 */
- 0x0000, /* R227 */
- 0x0000, /* R228 */
- 0x0000, /* R229 */
- 0x0000, /* R230 */
- 0x0000, /* R231 */
- 0x0000, /* R232 */
- 0x0000, /* R233 */
- 0x0000, /* R234 */
- 0x0000, /* R235 */
- 0x0000, /* R236 */
- 0x0000, /* R237 */
- 0x0000, /* R238 */
- 0x0000, /* R239 */
- 0x0000, /* R240 */
- 0x0000, /* R241 */
- 0x0000, /* R242 */
- 0x0000, /* R243 */
- 0x0000, /* R244 */
- 0x0000, /* R245 */
- 0x0000, /* R246 */
- 0x0000, /* R247 */
- 0x0000, /* R248 */
- 0x0000, /* R249 */
- 0x0000, /* R250 */
- 0x0000, /* R251 */
- 0x0000, /* R252 */
- 0x0000, /* R253 */
- 0x0000, /* R254 */
- 0x0000, /* R255 */
- 0x0003, /* R256 - Chip Revision */
- 0x8004, /* R257 - Control Interface */
- 0x0000, /* R258 */
- 0x0000, /* R259 */
- 0x0000, /* R260 */
- 0x0000, /* R261 */
- 0x0000, /* R262 */
- 0x0000, /* R263 */
- 0x0000, /* R264 */
- 0x0000, /* R265 */
- 0x0000, /* R266 */
- 0x0000, /* R267 */
- 0x0000, /* R268 */
- 0x0000, /* R269 */
- 0x0000, /* R270 */
- 0x0000, /* R271 */
- 0x0000, /* R272 - Write Sequencer Ctrl (1) */
- 0x0000, /* R273 - Write Sequencer Ctrl (2) */
- 0x0000, /* R274 */
- 0x0000, /* R275 */
- 0x0000, /* R276 */
- 0x0000, /* R277 */
- 0x0000, /* R278 */
- 0x0000, /* R279 */
- 0x0000, /* R280 */
- 0x0000, /* R281 */
- 0x0000, /* R282 */
- 0x0000, /* R283 */
- 0x0000, /* R284 */
- 0x0000, /* R285 */
- 0x0000, /* R286 */
- 0x0000, /* R287 */
- 0x0000, /* R288 */
- 0x0000, /* R289 */
- 0x0000, /* R290 */
- 0x0000, /* R291 */
- 0x0000, /* R292 */
- 0x0000, /* R293 */
- 0x0000, /* R294 */
- 0x0000, /* R295 */
- 0x0000, /* R296 */
- 0x0000, /* R297 */
- 0x0000, /* R298 */
- 0x0000, /* R299 */
- 0x0000, /* R300 */
- 0x0000, /* R301 */
- 0x0000, /* R302 */
- 0x0000, /* R303 */
- 0x0000, /* R304 */
- 0x0000, /* R305 */
- 0x0000, /* R306 */
- 0x0000, /* R307 */
- 0x0000, /* R308 */
- 0x0000, /* R309 */
- 0x0000, /* R310 */
- 0x0000, /* R311 */
- 0x0000, /* R312 */
- 0x0000, /* R313 */
- 0x0000, /* R314 */
- 0x0000, /* R315 */
- 0x0000, /* R316 */
- 0x0000, /* R317 */
- 0x0000, /* R318 */
- 0x0000, /* R319 */
- 0x0000, /* R320 */
- 0x0000, /* R321 */
- 0x0000, /* R322 */
- 0x0000, /* R323 */
- 0x0000, /* R324 */
- 0x0000, /* R325 */
- 0x0000, /* R326 */
- 0x0000, /* R327 */
- 0x0000, /* R328 */
- 0x0000, /* R329 */
- 0x0000, /* R330 */
- 0x0000, /* R331 */
- 0x0000, /* R332 */
- 0x0000, /* R333 */
- 0x0000, /* R334 */
- 0x0000, /* R335 */
- 0x0000, /* R336 */
- 0x0000, /* R337 */
- 0x0000, /* R338 */
- 0x0000, /* R339 */
- 0x0000, /* R340 */
- 0x0000, /* R341 */
- 0x0000, /* R342 */
- 0x0000, /* R343 */
- 0x0000, /* R344 */
- 0x0000, /* R345 */
- 0x0000, /* R346 */
- 0x0000, /* R347 */
- 0x0000, /* R348 */
- 0x0000, /* R349 */
- 0x0000, /* R350 */
- 0x0000, /* R351 */
- 0x0000, /* R352 */
- 0x0000, /* R353 */
- 0x0000, /* R354 */
- 0x0000, /* R355 */
- 0x0000, /* R356 */
- 0x0000, /* R357 */
- 0x0000, /* R358 */
- 0x0000, /* R359 */
- 0x0000, /* R360 */
- 0x0000, /* R361 */
- 0x0000, /* R362 */
- 0x0000, /* R363 */
- 0x0000, /* R364 */
- 0x0000, /* R365 */
- 0x0000, /* R366 */
- 0x0000, /* R367 */
- 0x0000, /* R368 */
- 0x0000, /* R369 */
- 0x0000, /* R370 */
- 0x0000, /* R371 */
- 0x0000, /* R372 */
- 0x0000, /* R373 */
- 0x0000, /* R374 */
- 0x0000, /* R375 */
- 0x0000, /* R376 */
- 0x0000, /* R377 */
- 0x0000, /* R378 */
- 0x0000, /* R379 */
- 0x0000, /* R380 */
- 0x0000, /* R381 */
- 0x0000, /* R382 */
- 0x0000, /* R383 */
- 0x0000, /* R384 */
- 0x0000, /* R385 */
- 0x0000, /* R386 */
- 0x0000, /* R387 */
- 0x0000, /* R388 */
- 0x0000, /* R389 */
- 0x0000, /* R390 */
- 0x0000, /* R391 */
- 0x0000, /* R392 */
- 0x0000, /* R393 */
- 0x0000, /* R394 */
- 0x0000, /* R395 */
- 0x0000, /* R396 */
- 0x0000, /* R397 */
- 0x0000, /* R398 */
- 0x0000, /* R399 */
- 0x0000, /* R400 */
- 0x0000, /* R401 */
- 0x0000, /* R402 */
- 0x0000, /* R403 */
- 0x0000, /* R404 */
- 0x0000, /* R405 */
- 0x0000, /* R406 */
- 0x0000, /* R407 */
- 0x0000, /* R408 */
- 0x0000, /* R409 */
- 0x0000, /* R410 */
- 0x0000, /* R411 */
- 0x0000, /* R412 */
- 0x0000, /* R413 */
- 0x0000, /* R414 */
- 0x0000, /* R415 */
- 0x0000, /* R416 */
- 0x0000, /* R417 */
- 0x0000, /* R418 */
- 0x0000, /* R419 */
- 0x0000, /* R420 */
- 0x0000, /* R421 */
- 0x0000, /* R422 */
- 0x0000, /* R423 */
- 0x0000, /* R424 */
- 0x0000, /* R425 */
- 0x0000, /* R426 */
- 0x0000, /* R427 */
- 0x0000, /* R428 */
- 0x0000, /* R429 */
- 0x0000, /* R430 */
- 0x0000, /* R431 */
- 0x0000, /* R432 */
- 0x0000, /* R433 */
- 0x0000, /* R434 */
- 0x0000, /* R435 */
- 0x0000, /* R436 */
- 0x0000, /* R437 */
- 0x0000, /* R438 */
- 0x0000, /* R439 */
- 0x0000, /* R440 */
- 0x0000, /* R441 */
- 0x0000, /* R442 */
- 0x0000, /* R443 */
- 0x0000, /* R444 */
- 0x0000, /* R445 */
- 0x0000, /* R446 */
- 0x0000, /* R447 */
- 0x0000, /* R448 */
- 0x0000, /* R449 */
- 0x0000, /* R450 */
- 0x0000, /* R451 */
- 0x0000, /* R452 */
- 0x0000, /* R453 */
- 0x0000, /* R454 */
- 0x0000, /* R455 */
- 0x0000, /* R456 */
- 0x0000, /* R457 */
- 0x0000, /* R458 */
- 0x0000, /* R459 */
- 0x0000, /* R460 */
- 0x0000, /* R461 */
- 0x0000, /* R462 */
- 0x0000, /* R463 */
- 0x0000, /* R464 */
- 0x0000, /* R465 */
- 0x0000, /* R466 */
- 0x0000, /* R467 */
- 0x0000, /* R468 */
- 0x0000, /* R469 */
- 0x0000, /* R470 */
- 0x0000, /* R471 */
- 0x0000, /* R472 */
- 0x0000, /* R473 */
- 0x0000, /* R474 */
- 0x0000, /* R475 */
- 0x0000, /* R476 */
- 0x0000, /* R477 */
- 0x0000, /* R478 */
- 0x0000, /* R479 */
- 0x0000, /* R480 */
- 0x0000, /* R481 */
- 0x0000, /* R482 */
- 0x0000, /* R483 */
- 0x0000, /* R484 */
- 0x0000, /* R485 */
- 0x0000, /* R486 */
- 0x0000, /* R487 */
- 0x0000, /* R488 */
- 0x0000, /* R489 */
- 0x0000, /* R490 */
- 0x0000, /* R491 */
- 0x0000, /* R492 */
- 0x0000, /* R493 */
- 0x0000, /* R494 */
- 0x0000, /* R495 */
- 0x0000, /* R496 */
- 0x0000, /* R497 */
- 0x0000, /* R498 */
- 0x0000, /* R499 */
- 0x0000, /* R500 */
- 0x0000, /* R501 */
- 0x0000, /* R502 */
- 0x0000, /* R503 */
- 0x0000, /* R504 */
- 0x0000, /* R505 */
- 0x0000, /* R506 */
- 0x0000, /* R507 */
- 0x0000, /* R508 */
- 0x0000, /* R509 */
- 0x0000, /* R510 */
- 0x0000, /* R511 */
- 0x0000, /* R512 - AIF1 Clocking (1) */
- 0x0000, /* R513 - AIF1 Clocking (2) */
- 0x0000, /* R514 */
- 0x0000, /* R515 */
- 0x0000, /* R516 - AIF2 Clocking (1) */
- 0x0000, /* R517 - AIF2 Clocking (2) */
- 0x0000, /* R518 */
- 0x0000, /* R519 */
- 0x0000, /* R520 - Clocking (1) */
- 0x0000, /* R521 - Clocking (2) */
- 0x0000, /* R522 */
- 0x0000, /* R523 */
- 0x0000, /* R524 */
- 0x0000, /* R525 */
- 0x0000, /* R526 */
- 0x0000, /* R527 */
- 0x0083, /* R528 - AIF1 Rate */
- 0x0083, /* R529 - AIF2 Rate */
- 0x0000, /* R530 - Rate Status */
- 0x0000, /* R531 */
- 0x0000, /* R532 */
- 0x0000, /* R533 */
- 0x0000, /* R534 */
- 0x0000, /* R535 */
- 0x0000, /* R536 */
- 0x0000, /* R537 */
- 0x0000, /* R538 */
- 0x0000, /* R539 */
- 0x0000, /* R540 */
- 0x0000, /* R541 */
- 0x0000, /* R542 */
- 0x0000, /* R543 */
- 0x0000, /* R544 - FLL1 Control (1) */
- 0x0000, /* R545 - FLL1 Control (2) */
- 0x0000, /* R546 - FLL1 Control (3) */
- 0x0000, /* R547 - FLL1 Control (4) */
- 0x0C80, /* R548 - FLL1 Control (5) */
- 0x0000, /* R549 */
- 0x0000, /* R550 */
- 0x0000, /* R551 */
- 0x0000, /* R552 */
- 0x0000, /* R553 */
- 0x0000, /* R554 */
- 0x0000, /* R555 */
- 0x0000, /* R556 */
- 0x0000, /* R557 */
- 0x0000, /* R558 */
- 0x0000, /* R559 */
- 0x0000, /* R560 */
- 0x0000, /* R561 */
- 0x0000, /* R562 */
- 0x0000, /* R563 */
- 0x0000, /* R564 */
- 0x0000, /* R565 */
- 0x0000, /* R566 */
- 0x0000, /* R567 */
- 0x0000, /* R568 */
- 0x0000, /* R569 */
- 0x0000, /* R570 */
- 0x0000, /* R571 */
- 0x0000, /* R572 */
- 0x0000, /* R573 */
- 0x0000, /* R574 */
- 0x0000, /* R575 */
- 0x0000, /* R576 - FLL2 Control (1) */
- 0x0000, /* R577 - FLL2 Control (2) */
- 0x0000, /* R578 - FLL2 Control (3) */
- 0x0000, /* R579 - FLL2 Control (4) */
- 0x0C80, /* R580 - FLL2 Control (5) */
- 0x0000, /* R581 */
- 0x0000, /* R582 */
- 0x0000, /* R583 */
- 0x0000, /* R584 */
- 0x0000, /* R585 */
- 0x0000, /* R586 */
- 0x0000, /* R587 */
- 0x0000, /* R588 */
- 0x0000, /* R589 */
- 0x0000, /* R590 */
- 0x0000, /* R591 */
- 0x0000, /* R592 */
- 0x0000, /* R593 */
- 0x0000, /* R594 */
- 0x0000, /* R595 */
- 0x0000, /* R596 */
- 0x0000, /* R597 */
- 0x0000, /* R598 */
- 0x0000, /* R599 */
- 0x0000, /* R600 */
- 0x0000, /* R601 */
- 0x0000, /* R602 */
- 0x0000, /* R603 */
- 0x0000, /* R604 */
- 0x0000, /* R605 */
- 0x0000, /* R606 */
- 0x0000, /* R607 */
- 0x0000, /* R608 */
- 0x0000, /* R609 */
- 0x0000, /* R610 */
- 0x0000, /* R611 */
- 0x0000, /* R612 */
- 0x0000, /* R613 */
- 0x0000, /* R614 */
- 0x0000, /* R615 */
- 0x0000, /* R616 */
- 0x0000, /* R617 */
- 0x0000, /* R618 */
- 0x0000, /* R619 */
- 0x0000, /* R620 */
- 0x0000, /* R621 */
- 0x0000, /* R622 */
- 0x0000, /* R623 */
- 0x0000, /* R624 */
- 0x0000, /* R625 */
- 0x0000, /* R626 */
- 0x0000, /* R627 */
- 0x0000, /* R628 */
- 0x0000, /* R629 */
- 0x0000, /* R630 */
- 0x0000, /* R631 */
- 0x0000, /* R632 */
- 0x0000, /* R633 */
- 0x0000, /* R634 */
- 0x0000, /* R635 */
- 0x0000, /* R636 */
- 0x0000, /* R637 */
- 0x0000, /* R638 */
- 0x0000, /* R639 */
- 0x0000, /* R640 */
- 0x0000, /* R641 */
- 0x0000, /* R642 */
- 0x0000, /* R643 */
- 0x0000, /* R644 */
- 0x0000, /* R645 */
- 0x0000, /* R646 */
- 0x0000, /* R647 */
- 0x0000, /* R648 */
- 0x0000, /* R649 */
- 0x0000, /* R650 */
- 0x0000, /* R651 */
- 0x0000, /* R652 */
- 0x0000, /* R653 */
- 0x0000, /* R654 */
- 0x0000, /* R655 */
- 0x0000, /* R656 */
- 0x0000, /* R657 */
- 0x0000, /* R658 */
- 0x0000, /* R659 */
- 0x0000, /* R660 */
- 0x0000, /* R661 */
- 0x0000, /* R662 */
- 0x0000, /* R663 */
- 0x0000, /* R664 */
- 0x0000, /* R665 */
- 0x0000, /* R666 */
- 0x0000, /* R667 */
- 0x0000, /* R668 */
- 0x0000, /* R669 */
- 0x0000, /* R670 */
- 0x0000, /* R671 */
- 0x0000, /* R672 */
- 0x0000, /* R673 */
- 0x0000, /* R674 */
- 0x0000, /* R675 */
- 0x0000, /* R676 */
- 0x0000, /* R677 */
- 0x0000, /* R678 */
- 0x0000, /* R679 */
- 0x0000, /* R680 */
- 0x0000, /* R681 */
- 0x0000, /* R682 */
- 0x0000, /* R683 */
- 0x0000, /* R684 */
- 0x0000, /* R685 */
- 0x0000, /* R686 */
- 0x0000, /* R687 */
- 0x0000, /* R688 */
- 0x0000, /* R689 */
- 0x0000, /* R690 */
- 0x0000, /* R691 */
- 0x0000, /* R692 */
- 0x0000, /* R693 */
- 0x0000, /* R694 */
- 0x0000, /* R695 */
- 0x0000, /* R696 */
- 0x0000, /* R697 */
- 0x0000, /* R698 */
- 0x0000, /* R699 */
- 0x0000, /* R700 */
- 0x0000, /* R701 */
- 0x0000, /* R702 */
- 0x0000, /* R703 */
- 0x0000, /* R704 */
- 0x0000, /* R705 */
- 0x0000, /* R706 */
- 0x0000, /* R707 */
- 0x0000, /* R708 */
- 0x0000, /* R709 */
- 0x0000, /* R710 */
- 0x0000, /* R711 */
- 0x0000, /* R712 */
- 0x0000, /* R713 */
- 0x0000, /* R714 */
- 0x0000, /* R715 */
- 0x0000, /* R716 */
- 0x0000, /* R717 */
- 0x0000, /* R718 */
- 0x0000, /* R719 */
- 0x0000, /* R720 */
- 0x0000, /* R721 */
- 0x0000, /* R722 */
- 0x0000, /* R723 */
- 0x0000, /* R724 */
- 0x0000, /* R725 */
- 0x0000, /* R726 */
- 0x0000, /* R727 */
- 0x0000, /* R728 */
- 0x0000, /* R729 */
- 0x0000, /* R730 */
- 0x0000, /* R731 */
- 0x0000, /* R732 */
- 0x0000, /* R733 */
- 0x0000, /* R734 */
- 0x0000, /* R735 */
- 0x0000, /* R736 */
- 0x0000, /* R737 */
- 0x0000, /* R738 */
- 0x0000, /* R739 */
- 0x0000, /* R740 */
- 0x0000, /* R741 */
- 0x0000, /* R742 */
- 0x0000, /* R743 */
- 0x0000, /* R744 */
- 0x0000, /* R745 */
- 0x0000, /* R746 */
- 0x0000, /* R747 */
- 0x0000, /* R748 */
- 0x0000, /* R749 */
- 0x0000, /* R750 */
- 0x0000, /* R751 */
- 0x0000, /* R752 */
- 0x0000, /* R753 */
- 0x0000, /* R754 */
- 0x0000, /* R755 */
- 0x0000, /* R756 */
- 0x0000, /* R757 */
- 0x0000, /* R758 */
- 0x0000, /* R759 */
- 0x0000, /* R760 */
- 0x0000, /* R761 */
- 0x0000, /* R762 */
- 0x0000, /* R763 */
- 0x0000, /* R764 */
- 0x0000, /* R765 */
- 0x0000, /* R766 */
- 0x0000, /* R767 */
- 0x4050, /* R768 - AIF1 Control (1) */
- 0x4000, /* R769 - AIF1 Control (2) */
- 0x0000, /* R770 - AIF1 Master/Slave */
- 0x0040, /* R771 - AIF1 BCLK */
- 0x0040, /* R772 - AIF1ADC LRCLK */
- 0x0040, /* R773 - AIF1DAC LRCLK */
- 0x0004, /* R774 - AIF1DAC Data */
- 0x0100, /* R775 - AIF1ADC Data */
- 0x0000, /* R776 */
- 0x0000, /* R777 */
- 0x0000, /* R778 */
- 0x0000, /* R779 */
- 0x0000, /* R780 */
- 0x0000, /* R781 */
- 0x0000, /* R782 */
- 0x0000, /* R783 */
- 0x4050, /* R784 - AIF2 Control (1) */
- 0x4000, /* R785 - AIF2 Control (2) */
- 0x0000, /* R786 - AIF2 Master/Slave */
- 0x0040, /* R787 - AIF2 BCLK */
- 0x0040, /* R788 - AIF2ADC LRCLK */
- 0x0040, /* R789 - AIF2DAC LRCLK */
- 0x0000, /* R790 - AIF2DAC Data */
- 0x0000, /* R791 - AIF2ADC Data */
- 0x0000, /* R792 */
- 0x0000, /* R793 */
- 0x0000, /* R794 */
- 0x0000, /* R795 */
- 0x0000, /* R796 */
- 0x0000, /* R797 */
- 0x0000, /* R798 */
- 0x0000, /* R799 */
- 0x0000, /* R800 */
- 0x0000, /* R801 */
- 0x0000, /* R802 */
- 0x0000, /* R803 */
- 0x0000, /* R804 */
- 0x0000, /* R805 */
- 0x0000, /* R806 */
- 0x0000, /* R807 */
- 0x0000, /* R808 */
- 0x0000, /* R809 */
- 0x0000, /* R810 */
- 0x0000, /* R811 */
- 0x0000, /* R812 */
- 0x0000, /* R813 */
- 0x0000, /* R814 */
- 0x0000, /* R815 */
- 0x0000, /* R816 */
- 0x0000, /* R817 */
- 0x0000, /* R818 */
- 0x0000, /* R819 */
- 0x0000, /* R820 */
- 0x0000, /* R821 */
- 0x0000, /* R822 */
- 0x0000, /* R823 */
- 0x0000, /* R824 */
- 0x0000, /* R825 */
- 0x0000, /* R826 */
- 0x0000, /* R827 */
- 0x0000, /* R828 */
- 0x0000, /* R829 */
- 0x0000, /* R830 */
- 0x0000, /* R831 */
- 0x0000, /* R832 */
- 0x0000, /* R833 */
- 0x0000, /* R834 */
- 0x0000, /* R835 */
- 0x0000, /* R836 */
- 0x0000, /* R837 */
- 0x0000, /* R838 */
- 0x0000, /* R839 */
- 0x0000, /* R840 */
- 0x0000, /* R841 */
- 0x0000, /* R842 */
- 0x0000, /* R843 */
- 0x0000, /* R844 */
- 0x0000, /* R845 */
- 0x0000, /* R846 */
- 0x0000, /* R847 */
- 0x0000, /* R848 */
- 0x0000, /* R849 */
- 0x0000, /* R850 */
- 0x0000, /* R851 */
- 0x0000, /* R852 */
- 0x0000, /* R853 */
- 0x0000, /* R854 */
- 0x0000, /* R855 */
- 0x0000, /* R856 */
- 0x0000, /* R857 */
- 0x0000, /* R858 */
- 0x0000, /* R859 */
- 0x0000, /* R860 */
- 0x0000, /* R861 */
- 0x0000, /* R862 */
- 0x0000, /* R863 */
- 0x0000, /* R864 */
- 0x0000, /* R865 */
- 0x0000, /* R866 */
- 0x0000, /* R867 */
- 0x0000, /* R868 */
- 0x0000, /* R869 */
- 0x0000, /* R870 */
- 0x0000, /* R871 */
- 0x0000, /* R872 */
- 0x0000, /* R873 */
- 0x0000, /* R874 */
- 0x0000, /* R875 */
- 0x0000, /* R876 */
- 0x0000, /* R877 */
- 0x0000, /* R878 */
- 0x0000, /* R879 */
- 0x0000, /* R880 */
- 0x0000, /* R881 */
- 0x0000, /* R882 */
- 0x0000, /* R883 */
- 0x0000, /* R884 */
- 0x0000, /* R885 */
- 0x0000, /* R886 */
- 0x0000, /* R887 */
- 0x0000, /* R888 */
- 0x0000, /* R889 */
- 0x0000, /* R890 */
- 0x0000, /* R891 */
- 0x0000, /* R892 */
- 0x0000, /* R893 */
- 0x0000, /* R894 */
- 0x0000, /* R895 */
- 0x0000, /* R896 */
- 0x0000, /* R897 */
- 0x0000, /* R898 */
- 0x0000, /* R899 */
- 0x0000, /* R900 */
- 0x0000, /* R901 */
- 0x0000, /* R902 */
- 0x0000, /* R903 */
- 0x0000, /* R904 */
- 0x0000, /* R905 */
- 0x0000, /* R906 */
- 0x0000, /* R907 */
- 0x0000, /* R908 */
- 0x0000, /* R909 */
- 0x0000, /* R910 */
- 0x0000, /* R911 */
- 0x0000, /* R912 */
- 0x0000, /* R913 */
- 0x0000, /* R914 */
- 0x0000, /* R915 */
- 0x0000, /* R916 */
- 0x0000, /* R917 */
- 0x0000, /* R918 */
- 0x0000, /* R919 */
- 0x0000, /* R920 */
- 0x0000, /* R921 */
- 0x0000, /* R922 */
- 0x0000, /* R923 */
- 0x0000, /* R924 */
- 0x0000, /* R925 */
- 0x0000, /* R926 */
- 0x0000, /* R927 */
- 0x0000, /* R928 */
- 0x0000, /* R929 */
- 0x0000, /* R930 */
- 0x0000, /* R931 */
- 0x0000, /* R932 */
- 0x0000, /* R933 */
- 0x0000, /* R934 */
- 0x0000, /* R935 */
- 0x0000, /* R936 */
- 0x0000, /* R937 */
- 0x0000, /* R938 */
- 0x0000, /* R939 */
- 0x0000, /* R940 */
- 0x0000, /* R941 */
- 0x0000, /* R942 */
- 0x0000, /* R943 */
- 0x0000, /* R944 */
- 0x0000, /* R945 */
- 0x0000, /* R946 */
- 0x0000, /* R947 */
- 0x0000, /* R948 */
- 0x0000, /* R949 */
- 0x0000, /* R950 */
- 0x0000, /* R951 */
- 0x0000, /* R952 */
- 0x0000, /* R953 */
- 0x0000, /* R954 */
- 0x0000, /* R955 */
- 0x0000, /* R956 */
- 0x0000, /* R957 */
- 0x0000, /* R958 */
- 0x0000, /* R959 */
- 0x0000, /* R960 */
- 0x0000, /* R961 */
- 0x0000, /* R962 */
- 0x0000, /* R963 */
- 0x0000, /* R964 */
- 0x0000, /* R965 */
- 0x0000, /* R966 */
- 0x0000, /* R967 */
- 0x0000, /* R968 */
- 0x0000, /* R969 */
- 0x0000, /* R970 */
- 0x0000, /* R971 */
- 0x0000, /* R972 */
- 0x0000, /* R973 */
- 0x0000, /* R974 */
- 0x0000, /* R975 */
- 0x0000, /* R976 */
- 0x0000, /* R977 */
- 0x0000, /* R978 */
- 0x0000, /* R979 */
- 0x0000, /* R980 */
- 0x0000, /* R981 */
- 0x0000, /* R982 */
- 0x0000, /* R983 */
- 0x0000, /* R984 */
- 0x0000, /* R985 */
- 0x0000, /* R986 */
- 0x0000, /* R987 */
- 0x0000, /* R988 */
- 0x0000, /* R989 */
- 0x0000, /* R990 */
- 0x0000, /* R991 */
- 0x0000, /* R992 */
- 0x0000, /* R993 */
- 0x0000, /* R994 */
- 0x0000, /* R995 */
- 0x0000, /* R996 */
- 0x0000, /* R997 */
- 0x0000, /* R998 */
- 0x0000, /* R999 */
- 0x0000, /* R1000 */
- 0x0000, /* R1001 */
- 0x0000, /* R1002 */
- 0x0000, /* R1003 */
- 0x0000, /* R1004 */
- 0x0000, /* R1005 */
- 0x0000, /* R1006 */
- 0x0000, /* R1007 */
- 0x0000, /* R1008 */
- 0x0000, /* R1009 */
- 0x0000, /* R1010 */
- 0x0000, /* R1011 */
- 0x0000, /* R1012 */
- 0x0000, /* R1013 */
- 0x0000, /* R1014 */
- 0x0000, /* R1015 */
- 0x0000, /* R1016 */
- 0x0000, /* R1017 */
- 0x0000, /* R1018 */
- 0x0000, /* R1019 */
- 0x0000, /* R1020 */
- 0x0000, /* R1021 */
- 0x0000, /* R1022 */
- 0x0000, /* R1023 */
- 0x00C0, /* R1024 - AIF1 ADC1 Left Volume */
- 0x00C0, /* R1025 - AIF1 ADC1 Right Volume */
- 0x00C0, /* R1026 - AIF1 DAC1 Left Volume */
- 0x00C0, /* R1027 - AIF1 DAC1 Right Volume */
- 0x00C0, /* R1028 - AIF1 ADC2 Left Volume */
- 0x00C0, /* R1029 - AIF1 ADC2 Right Volume */
- 0x00C0, /* R1030 - AIF1 DAC2 Left Volume */
- 0x00C0, /* R1031 - AIF1 DAC2 Right Volume */
- 0x0000, /* R1032 */
- 0x0000, /* R1033 */
- 0x0000, /* R1034 */
- 0x0000, /* R1035 */
- 0x0000, /* R1036 */
- 0x0000, /* R1037 */
- 0x0000, /* R1038 */
- 0x0000, /* R1039 */
- 0x0000, /* R1040 - AIF1 ADC1 Filters */
- 0x0000, /* R1041 - AIF1 ADC2 Filters */
- 0x0000, /* R1042 */
- 0x0000, /* R1043 */
- 0x0000, /* R1044 */
- 0x0000, /* R1045 */
- 0x0000, /* R1046 */
- 0x0000, /* R1047 */
- 0x0000, /* R1048 */
- 0x0000, /* R1049 */
- 0x0000, /* R1050 */
- 0x0000, /* R1051 */
- 0x0000, /* R1052 */
- 0x0000, /* R1053 */
- 0x0000, /* R1054 */
- 0x0000, /* R1055 */
- 0x0200, /* R1056 - AIF1 DAC1 Filters (1) */
- 0x0010, /* R1057 - AIF1 DAC1 Filters (2) */
- 0x0200, /* R1058 - AIF1 DAC2 Filters (1) */
- 0x0010, /* R1059 - AIF1 DAC2 Filters (2) */
- 0x0000, /* R1060 */
- 0x0000, /* R1061 */
- 0x0000, /* R1062 */
- 0x0000, /* R1063 */
- 0x0000, /* R1064 */
- 0x0000, /* R1065 */
- 0x0000, /* R1066 */
- 0x0000, /* R1067 */
- 0x0000, /* R1068 */
- 0x0000, /* R1069 */
- 0x0000, /* R1070 */
- 0x0000, /* R1071 */
- 0x0000, /* R1072 */
- 0x0000, /* R1073 */
- 0x0000, /* R1074 */
- 0x0000, /* R1075 */
- 0x0000, /* R1076 */
- 0x0000, /* R1077 */
- 0x0000, /* R1078 */
- 0x0000, /* R1079 */
- 0x0000, /* R1080 */
- 0x0000, /* R1081 */
- 0x0000, /* R1082 */
- 0x0000, /* R1083 */
- 0x0000, /* R1084 */
- 0x0000, /* R1085 */
- 0x0000, /* R1086 */
- 0x0000, /* R1087 */
- 0x0098, /* R1088 - AIF1 DRC1 (1) */
- 0x0845, /* R1089 - AIF1 DRC1 (2) */
- 0x0000, /* R1090 - AIF1 DRC1 (3) */
- 0x0000, /* R1091 - AIF1 DRC1 (4) */
- 0x0000, /* R1092 - AIF1 DRC1 (5) */
- 0x0000, /* R1093 */
- 0x0000, /* R1094 */
- 0x0000, /* R1095 */
- 0x0000, /* R1096 */
- 0x0000, /* R1097 */
- 0x0000, /* R1098 */
- 0x0000, /* R1099 */
- 0x0000, /* R1100 */
- 0x0000, /* R1101 */
- 0x0000, /* R1102 */
- 0x0000, /* R1103 */
- 0x0098, /* R1104 - AIF1 DRC2 (1) */
- 0x0845, /* R1105 - AIF1 DRC2 (2) */
- 0x0000, /* R1106 - AIF1 DRC2 (3) */
- 0x0000, /* R1107 - AIF1 DRC2 (4) */
- 0x0000, /* R1108 - AIF1 DRC2 (5) */
- 0x0000, /* R1109 */
- 0x0000, /* R1110 */
- 0x0000, /* R1111 */
- 0x0000, /* R1112 */
- 0x0000, /* R1113 */
- 0x0000, /* R1114 */
- 0x0000, /* R1115 */
- 0x0000, /* R1116 */
- 0x0000, /* R1117 */
- 0x0000, /* R1118 */
- 0x0000, /* R1119 */
- 0x0000, /* R1120 */
- 0x0000, /* R1121 */
- 0x0000, /* R1122 */
- 0x0000, /* R1123 */
- 0x0000, /* R1124 */
- 0x0000, /* R1125 */
- 0x0000, /* R1126 */
- 0x0000, /* R1127 */
- 0x0000, /* R1128 */
- 0x0000, /* R1129 */
- 0x0000, /* R1130 */
- 0x0000, /* R1131 */
- 0x0000, /* R1132 */
- 0x0000, /* R1133 */
- 0x0000, /* R1134 */
- 0x0000, /* R1135 */
- 0x0000, /* R1136 */
- 0x0000, /* R1137 */
- 0x0000, /* R1138 */
- 0x0000, /* R1139 */
- 0x0000, /* R1140 */
- 0x0000, /* R1141 */
- 0x0000, /* R1142 */
- 0x0000, /* R1143 */
- 0x0000, /* R1144 */
- 0x0000, /* R1145 */
- 0x0000, /* R1146 */
- 0x0000, /* R1147 */
- 0x0000, /* R1148 */
- 0x0000, /* R1149 */
- 0x0000, /* R1150 */
- 0x0000, /* R1151 */
- 0x6318, /* R1152 - AIF1 DAC1 EQ Gains (1) */
- 0x6300, /* R1153 - AIF1 DAC1 EQ Gains (2) */
- 0x0FCA, /* R1154 - AIF1 DAC1 EQ Band 1 A */
- 0x0400, /* R1155 - AIF1 DAC1 EQ Band 1 B */
- 0x00D8, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
- 0x1EB5, /* R1157 - AIF1 DAC1 EQ Band 2 A */
- 0xF145, /* R1158 - AIF1 DAC1 EQ Band 2 B */
- 0x0B75, /* R1159 - AIF1 DAC1 EQ Band 2 C */
- 0x01C5, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
- 0x1C58, /* R1161 - AIF1 DAC1 EQ Band 3 A */
- 0xF373, /* R1162 - AIF1 DAC1 EQ Band 3 B */
- 0x0A54, /* R1163 - AIF1 DAC1 EQ Band 3 C */
- 0x0558, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
- 0x168E, /* R1165 - AIF1 DAC1 EQ Band 4 A */
- 0xF829, /* R1166 - AIF1 DAC1 EQ Band 4 B */
- 0x07AD, /* R1167 - AIF1 DAC1 EQ Band 4 C */
- 0x1103, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
- 0x0564, /* R1169 - AIF1 DAC1 EQ Band 5 A */
- 0x0559, /* R1170 - AIF1 DAC1 EQ Band 5 B */
- 0x4000, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
- 0x0000, /* R1172 */
- 0x0000, /* R1173 */
- 0x0000, /* R1174 */
- 0x0000, /* R1175 */
- 0x0000, /* R1176 */
- 0x0000, /* R1177 */
- 0x0000, /* R1178 */
- 0x0000, /* R1179 */
- 0x0000, /* R1180 */
- 0x0000, /* R1181 */
- 0x0000, /* R1182 */
- 0x0000, /* R1183 */
- 0x6318, /* R1184 - AIF1 DAC2 EQ Gains (1) */
- 0x6300, /* R1185 - AIF1 DAC2 EQ Gains (2) */
- 0x0FCA, /* R1186 - AIF1 DAC2 EQ Band 1 A */
- 0x0400, /* R1187 - AIF1 DAC2 EQ Band 1 B */
- 0x00D8, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
- 0x1EB5, /* R1189 - AIF1 DAC2 EQ Band 2 A */
- 0xF145, /* R1190 - AIF1 DAC2 EQ Band 2 B */
- 0x0B75, /* R1191 - AIF1 DAC2 EQ Band 2 C */
- 0x01C5, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
- 0x1C58, /* R1193 - AIF1 DAC2 EQ Band 3 A */
- 0xF373, /* R1194 - AIF1 DAC2 EQ Band 3 B */
- 0x0A54, /* R1195 - AIF1 DAC2 EQ Band 3 C */
- 0x0558, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
- 0x168E, /* R1197 - AIF1 DAC2 EQ Band 4 A */
- 0xF829, /* R1198 - AIF1 DAC2 EQ Band 4 B */
- 0x07AD, /* R1199 - AIF1 DAC2 EQ Band 4 C */
- 0x1103, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
- 0x0564, /* R1201 - AIF1 DAC2 EQ Band 5 A */
- 0x0559, /* R1202 - AIF1 DAC2 EQ Band 5 B */
- 0x4000, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
- 0x0000, /* R1204 */
- 0x0000, /* R1205 */
- 0x0000, /* R1206 */
- 0x0000, /* R1207 */
- 0x0000, /* R1208 */
- 0x0000, /* R1209 */
- 0x0000, /* R1210 */
- 0x0000, /* R1211 */
- 0x0000, /* R1212 */
- 0x0000, /* R1213 */
- 0x0000, /* R1214 */
- 0x0000, /* R1215 */
- 0x0000, /* R1216 */
- 0x0000, /* R1217 */
- 0x0000, /* R1218 */
- 0x0000, /* R1219 */
- 0x0000, /* R1220 */
- 0x0000, /* R1221 */
- 0x0000, /* R1222 */
- 0x0000, /* R1223 */
- 0x0000, /* R1224 */
- 0x0000, /* R1225 */
- 0x0000, /* R1226 */
- 0x0000, /* R1227 */
- 0x0000, /* R1228 */
- 0x0000, /* R1229 */
- 0x0000, /* R1230 */
- 0x0000, /* R1231 */
- 0x0000, /* R1232 */
- 0x0000, /* R1233 */
- 0x0000, /* R1234 */
- 0x0000, /* R1235 */
- 0x0000, /* R1236 */
- 0x0000, /* R1237 */
- 0x0000, /* R1238 */
- 0x0000, /* R1239 */
- 0x0000, /* R1240 */
- 0x0000, /* R1241 */
- 0x0000, /* R1242 */
- 0x0000, /* R1243 */
- 0x0000, /* R1244 */
- 0x0000, /* R1245 */
- 0x0000, /* R1246 */
- 0x0000, /* R1247 */
- 0x0000, /* R1248 */
- 0x0000, /* R1249 */
- 0x0000, /* R1250 */
- 0x0000, /* R1251 */
- 0x0000, /* R1252 */
- 0x0000, /* R1253 */
- 0x0000, /* R1254 */
- 0x0000, /* R1255 */
- 0x0000, /* R1256 */
- 0x0000, /* R1257 */
- 0x0000, /* R1258 */
- 0x0000, /* R1259 */
- 0x0000, /* R1260 */
- 0x0000, /* R1261 */
- 0x0000, /* R1262 */
- 0x0000, /* R1263 */
- 0x0000, /* R1264 */
- 0x0000, /* R1265 */
- 0x0000, /* R1266 */
- 0x0000, /* R1267 */
- 0x0000, /* R1268 */
- 0x0000, /* R1269 */
- 0x0000, /* R1270 */
- 0x0000, /* R1271 */
- 0x0000, /* R1272 */
- 0x0000, /* R1273 */
- 0x0000, /* R1274 */
- 0x0000, /* R1275 */
- 0x0000, /* R1276 */
- 0x0000, /* R1277 */
- 0x0000, /* R1278 */
- 0x0000, /* R1279 */
- 0x00C0, /* R1280 - AIF2 ADC Left Volume */
- 0x00C0, /* R1281 - AIF2 ADC Right Volume */
- 0x00C0, /* R1282 - AIF2 DAC Left Volume */
- 0x00C0, /* R1283 - AIF2 DAC Right Volume */
- 0x0000, /* R1284 */
- 0x0000, /* R1285 */
- 0x0000, /* R1286 */
- 0x0000, /* R1287 */
- 0x0000, /* R1288 */
- 0x0000, /* R1289 */
- 0x0000, /* R1290 */
- 0x0000, /* R1291 */
- 0x0000, /* R1292 */
- 0x0000, /* R1293 */
- 0x0000, /* R1294 */
- 0x0000, /* R1295 */
- 0x0000, /* R1296 - AIF2 ADC Filters */
- 0x0000, /* R1297 */
- 0x0000, /* R1298 */
- 0x0000, /* R1299 */
- 0x0000, /* R1300 */
- 0x0000, /* R1301 */
- 0x0000, /* R1302 */
- 0x0000, /* R1303 */
- 0x0000, /* R1304 */
- 0x0000, /* R1305 */
- 0x0000, /* R1306 */
- 0x0000, /* R1307 */
- 0x0000, /* R1308 */
- 0x0000, /* R1309 */
- 0x0000, /* R1310 */
- 0x0000, /* R1311 */
- 0x0200, /* R1312 - AIF2 DAC Filters (1) */
- 0x0010, /* R1313 - AIF2 DAC Filters (2) */
- 0x0000, /* R1314 */
- 0x0000, /* R1315 */
- 0x0000, /* R1316 */
- 0x0000, /* R1317 */
- 0x0000, /* R1318 */
- 0x0000, /* R1319 */
- 0x0000, /* R1320 */
- 0x0000, /* R1321 */
- 0x0000, /* R1322 */
- 0x0000, /* R1323 */
- 0x0000, /* R1324 */
- 0x0000, /* R1325 */
- 0x0000, /* R1326 */
- 0x0000, /* R1327 */
- 0x0000, /* R1328 */
- 0x0000, /* R1329 */
- 0x0000, /* R1330 */
- 0x0000, /* R1331 */
- 0x0000, /* R1332 */
- 0x0000, /* R1333 */
- 0x0000, /* R1334 */
- 0x0000, /* R1335 */
- 0x0000, /* R1336 */
- 0x0000, /* R1337 */
- 0x0000, /* R1338 */
- 0x0000, /* R1339 */
- 0x0000, /* R1340 */
- 0x0000, /* R1341 */
- 0x0000, /* R1342 */
- 0x0000, /* R1343 */
- 0x0098, /* R1344 - AIF2 DRC (1) */
- 0x0845, /* R1345 - AIF2 DRC (2) */
- 0x0000, /* R1346 - AIF2 DRC (3) */
- 0x0000, /* R1347 - AIF2 DRC (4) */
- 0x0000, /* R1348 - AIF2 DRC (5) */
- 0x0000, /* R1349 */
- 0x0000, /* R1350 */
- 0x0000, /* R1351 */
- 0x0000, /* R1352 */
- 0x0000, /* R1353 */
- 0x0000, /* R1354 */
- 0x0000, /* R1355 */
- 0x0000, /* R1356 */
- 0x0000, /* R1357 */
- 0x0000, /* R1358 */
- 0x0000, /* R1359 */
- 0x0000, /* R1360 */
- 0x0000, /* R1361 */
- 0x0000, /* R1362 */
- 0x0000, /* R1363 */
- 0x0000, /* R1364 */
- 0x0000, /* R1365 */
- 0x0000, /* R1366 */
- 0x0000, /* R1367 */
- 0x0000, /* R1368 */
- 0x0000, /* R1369 */
- 0x0000, /* R1370 */
- 0x0000, /* R1371 */
- 0x0000, /* R1372 */
- 0x0000, /* R1373 */
- 0x0000, /* R1374 */
- 0x0000, /* R1375 */
- 0x0000, /* R1376 */
- 0x0000, /* R1377 */
- 0x0000, /* R1378 */
- 0x0000, /* R1379 */
- 0x0000, /* R1380 */
- 0x0000, /* R1381 */
- 0x0000, /* R1382 */
- 0x0000, /* R1383 */
- 0x0000, /* R1384 */
- 0x0000, /* R1385 */
- 0x0000, /* R1386 */
- 0x0000, /* R1387 */
- 0x0000, /* R1388 */
- 0x0000, /* R1389 */
- 0x0000, /* R1390 */
- 0x0000, /* R1391 */
- 0x0000, /* R1392 */
- 0x0000, /* R1393 */
- 0x0000, /* R1394 */
- 0x0000, /* R1395 */
- 0x0000, /* R1396 */
- 0x0000, /* R1397 */
- 0x0000, /* R1398 */
- 0x0000, /* R1399 */
- 0x0000, /* R1400 */
- 0x0000, /* R1401 */
- 0x0000, /* R1402 */
- 0x0000, /* R1403 */
- 0x0000, /* R1404 */
- 0x0000, /* R1405 */
- 0x0000, /* R1406 */
- 0x0000, /* R1407 */
- 0x6318, /* R1408 - AIF2 EQ Gains (1) */
- 0x6300, /* R1409 - AIF2 EQ Gains (2) */
- 0x0FCA, /* R1410 - AIF2 EQ Band 1 A */
- 0x0400, /* R1411 - AIF2 EQ Band 1 B */
- 0x00D8, /* R1412 - AIF2 EQ Band 1 PG */
- 0x1EB5, /* R1413 - AIF2 EQ Band 2 A */
- 0xF145, /* R1414 - AIF2 EQ Band 2 B */
- 0x0B75, /* R1415 - AIF2 EQ Band 2 C */
- 0x01C5, /* R1416 - AIF2 EQ Band 2 PG */
- 0x1C58, /* R1417 - AIF2 EQ Band 3 A */
- 0xF373, /* R1418 - AIF2 EQ Band 3 B */
- 0x0A54, /* R1419 - AIF2 EQ Band 3 C */
- 0x0558, /* R1420 - AIF2 EQ Band 3 PG */
- 0x168E, /* R1421 - AIF2 EQ Band 4 A */
- 0xF829, /* R1422 - AIF2 EQ Band 4 B */
- 0x07AD, /* R1423 - AIF2 EQ Band 4 C */
- 0x1103, /* R1424 - AIF2 EQ Band 4 PG */
- 0x0564, /* R1425 - AIF2 EQ Band 5 A */
- 0x0559, /* R1426 - AIF2 EQ Band 5 B */
- 0x4000, /* R1427 - AIF2 EQ Band 5 PG */
- 0x0000, /* R1428 */
- 0x0000, /* R1429 */
- 0x0000, /* R1430 */
- 0x0000, /* R1431 */
- 0x0000, /* R1432 */
- 0x0000, /* R1433 */
- 0x0000, /* R1434 */
- 0x0000, /* R1435 */
- 0x0000, /* R1436 */
- 0x0000, /* R1437 */
- 0x0000, /* R1438 */
- 0x0000, /* R1439 */
- 0x0000, /* R1440 */
- 0x0000, /* R1441 */
- 0x0000, /* R1442 */
- 0x0000, /* R1443 */
- 0x0000, /* R1444 */
- 0x0000, /* R1445 */
- 0x0000, /* R1446 */
- 0x0000, /* R1447 */
- 0x0000, /* R1448 */
- 0x0000, /* R1449 */
- 0x0000, /* R1450 */
- 0x0000, /* R1451 */
- 0x0000, /* R1452 */
- 0x0000, /* R1453 */
- 0x0000, /* R1454 */
- 0x0000, /* R1455 */
- 0x0000, /* R1456 */
- 0x0000, /* R1457 */
- 0x0000, /* R1458 */
- 0x0000, /* R1459 */
- 0x0000, /* R1460 */
- 0x0000, /* R1461 */
- 0x0000, /* R1462 */
- 0x0000, /* R1463 */
- 0x0000, /* R1464 */
- 0x0000, /* R1465 */
- 0x0000, /* R1466 */
- 0x0000, /* R1467 */
- 0x0000, /* R1468 */
- 0x0000, /* R1469 */
- 0x0000, /* R1470 */
- 0x0000, /* R1471 */
- 0x0000, /* R1472 */
- 0x0000, /* R1473 */
- 0x0000, /* R1474 */
- 0x0000, /* R1475 */
- 0x0000, /* R1476 */
- 0x0000, /* R1477 */
- 0x0000, /* R1478 */
- 0x0000, /* R1479 */
- 0x0000, /* R1480 */
- 0x0000, /* R1481 */
- 0x0000, /* R1482 */
- 0x0000, /* R1483 */
- 0x0000, /* R1484 */
- 0x0000, /* R1485 */
- 0x0000, /* R1486 */
- 0x0000, /* R1487 */
- 0x0000, /* R1488 */
- 0x0000, /* R1489 */
- 0x0000, /* R1490 */
- 0x0000, /* R1491 */
- 0x0000, /* R1492 */
- 0x0000, /* R1493 */
- 0x0000, /* R1494 */
- 0x0000, /* R1495 */
- 0x0000, /* R1496 */
- 0x0000, /* R1497 */
- 0x0000, /* R1498 */
- 0x0000, /* R1499 */
- 0x0000, /* R1500 */
- 0x0000, /* R1501 */
- 0x0000, /* R1502 */
- 0x0000, /* R1503 */
- 0x0000, /* R1504 */
- 0x0000, /* R1505 */
- 0x0000, /* R1506 */
- 0x0000, /* R1507 */
- 0x0000, /* R1508 */
- 0x0000, /* R1509 */
- 0x0000, /* R1510 */
- 0x0000, /* R1511 */
- 0x0000, /* R1512 */
- 0x0000, /* R1513 */
- 0x0000, /* R1514 */
- 0x0000, /* R1515 */
- 0x0000, /* R1516 */
- 0x0000, /* R1517 */
- 0x0000, /* R1518 */
- 0x0000, /* R1519 */
- 0x0000, /* R1520 */
- 0x0000, /* R1521 */
- 0x0000, /* R1522 */
- 0x0000, /* R1523 */
- 0x0000, /* R1524 */
- 0x0000, /* R1525 */
- 0x0000, /* R1526 */
- 0x0000, /* R1527 */
- 0x0000, /* R1528 */
- 0x0000, /* R1529 */
- 0x0000, /* R1530 */
- 0x0000, /* R1531 */
- 0x0000, /* R1532 */
- 0x0000, /* R1533 */
- 0x0000, /* R1534 */
- 0x0000, /* R1535 */
- 0x0000, /* R1536 - DAC1 Mixer Volumes */
- 0x0000, /* R1537 - DAC1 Left Mixer Routing */
- 0x0000, /* R1538 - DAC1 Right Mixer Routing */
- 0x0000, /* R1539 - DAC2 Mixer Volumes */
- 0x0000, /* R1540 - DAC2 Left Mixer Routing */
- 0x0000, /* R1541 - DAC2 Right Mixer Routing */
- 0x0000, /* R1542 - AIF1 ADC1 Left Mixer Routing */
- 0x0000, /* R1543 - AIF1 ADC1 Right Mixer Routing */
- 0x0000, /* R1544 - AIF1 ADC2 Left Mixer Routing */
- 0x0000, /* R1545 - AIF1 ADC2 Right mixer Routing */
- 0x0000, /* R1546 */
- 0x0000, /* R1547 */
- 0x0000, /* R1548 */
- 0x0000, /* R1549 */
- 0x0000, /* R1550 */
- 0x0000, /* R1551 */
- 0x02C0, /* R1552 - DAC1 Left Volume */
- 0x02C0, /* R1553 - DAC1 Right Volume */
- 0x02C0, /* R1554 - DAC2 Left Volume */
- 0x02C0, /* R1555 - DAC2 Right Volume */
- 0x0000, /* R1556 - DAC Softmute */
- 0x0000, /* R1557 */
- 0x0000, /* R1558 */
- 0x0000, /* R1559 */
- 0x0000, /* R1560 */
- 0x0000, /* R1561 */
- 0x0000, /* R1562 */
- 0x0000, /* R1563 */
- 0x0000, /* R1564 */
- 0x0000, /* R1565 */
- 0x0000, /* R1566 */
- 0x0000, /* R1567 */
- 0x0002, /* R1568 - Oversampling */
- 0x0000, /* R1569 - Sidetone */
-};
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c
index b393f9fac97a..9685dff44dd8 100644
--- a/sound/soc/codecs/wm8994.c
+++ b/sound/soc/codecs/wm8994.c
@@ -38,6 +38,11 @@
#include "wm8994.h"
#include "wm_hubs.h"
+#define WM1811_JACKDET_MODE_NONE 0x0000
+#define WM1811_JACKDET_MODE_JACK 0x0100
+#define WM1811_JACKDET_MODE_MIC 0x0080
+#define WM1811_JACKDET_MODE_AUDIO 0x0180
+
#define WM8994_NUM_DRC 3
#define WM8994_NUM_EQ 3
@@ -53,102 +58,69 @@ static int wm8994_retune_mobile_base[] = {
WM8994_AIF2_EQ_GAINS_1,
};
-static int wm8994_readable(struct snd_soc_codec *codec, unsigned int reg)
-{
- struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994 *control = wm8994->control_data;
-
- switch (reg) {
- case WM8994_GPIO_1:
- case WM8994_GPIO_2:
- case WM8994_GPIO_3:
- case WM8994_GPIO_4:
- case WM8994_GPIO_5:
- case WM8994_GPIO_6:
- case WM8994_GPIO_7:
- case WM8994_GPIO_8:
- case WM8994_GPIO_9:
- case WM8994_GPIO_10:
- case WM8994_GPIO_11:
- case WM8994_INTERRUPT_STATUS_1:
- case WM8994_INTERRUPT_STATUS_2:
- case WM8994_INTERRUPT_RAW_STATUS_2:
- return 1;
-
- case WM8958_DSP2_PROGRAM:
- case WM8958_DSP2_CONFIG:
- case WM8958_DSP2_EXECCONTROL:
- if (control->type == WM8958)
- return 1;
- else
- return 0;
+static void wm8958_default_micdet(u16 status, void *data);
- default:
- break;
- }
+static const struct wm8958_micd_rate micdet_rates[] = {
+ { 32768, true, 1, 4 },
+ { 32768, false, 1, 1 },
+ { 44100 * 256, true, 7, 10 },
+ { 44100 * 256, false, 7, 10 },
+};
- if (reg >= WM8994_CACHE_SIZE)
- return 0;
- return wm8994_access_masks[reg].readable != 0;
-}
+static const struct wm8958_micd_rate jackdet_rates[] = {
+ { 32768, true, 0, 1 },
+ { 32768, false, 0, 1 },
+ { 44100 * 256, true, 7, 10 },
+ { 44100 * 256, false, 7, 10 },
+};
-static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static void wm8958_micd_set_rate(struct snd_soc_codec *codec)
{
- if (reg >= WM8994_CACHE_SIZE)
- return 1;
-
- switch (reg) {
- case WM8994_SOFTWARE_RESET:
- case WM8994_CHIP_REVISION:
- case WM8994_DC_SERVO_1:
- case WM8994_DC_SERVO_READBACK:
- case WM8994_RATE_STATUS:
- case WM8994_LDO_1:
- case WM8994_LDO_2:
- case WM8958_DSP2_EXECCONTROL:
- case WM8958_MIC_DETECT_3:
- return 1;
- default:
- return 0;
- }
-}
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ int best, i, sysclk, val;
+ bool idle;
+ const struct wm8958_micd_rate *rates;
+ int num_rates;
-static int wm8994_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- int ret;
+ if (wm8994->jack_cb != wm8958_default_micdet)
+ return;
- BUG_ON(reg > WM8994_MAX_REGISTER);
+ idle = !wm8994->jack_mic;
- if (!wm8994_volatile(codec, reg)) {
- ret = snd_soc_cache_write(codec, reg, value);
- if (ret != 0)
- dev_err(codec->dev, "Cache write to %x failed: %d\n",
- reg, ret);
+ sysclk = snd_soc_read(codec, WM8994_CLOCKING_1);
+ if (sysclk & WM8994_SYSCLK_SRC)
+ sysclk = wm8994->aifclk[1];
+ else
+ sysclk = wm8994->aifclk[0];
+
+ if (wm8994->pdata && wm8994->pdata->micd_rates) {
+ rates = wm8994->pdata->micd_rates;
+ num_rates = wm8994->pdata->num_micd_rates;
+ } else if (wm8994->jackdet) {
+ rates = jackdet_rates;
+ num_rates = ARRAY_SIZE(jackdet_rates);
+ } else {
+ rates = micdet_rates;
+ num_rates = ARRAY_SIZE(micdet_rates);
}
- return wm8994_reg_write(codec->control_data, reg, value);
-}
-
-static unsigned int wm8994_read(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- unsigned int val;
- int ret;
-
- BUG_ON(reg > WM8994_MAX_REGISTER);
-
- if (!wm8994_volatile(codec, reg) && wm8994_readable(codec, reg) &&
- reg < codec->driver->reg_cache_size) {
- ret = snd_soc_cache_read(codec, reg, &val);
- if (ret >= 0)
- return val;
- else
- dev_err(codec->dev, "Cache read from %x failed: %d\n",
- reg, ret);
+ best = 0;
+ for (i = 0; i < num_rates; i++) {
+ if (rates[i].idle != idle)
+ continue;
+ if (abs(rates[i].sysclk - sysclk) <
+ abs(rates[best].sysclk - sysclk))
+ best = i;
+ else if (rates[best].idle != idle)
+ best = i;
}
- return wm8994_reg_read(codec->control_data, reg);
+ val = rates[best].start << WM8958_MICD_BIAS_STARTTIME_SHIFT
+ | rates[best].rate << WM8958_MICD_RATE_SHIFT;
+
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+ WM8958_MICD_BIAS_STARTTIME_MASK |
+ WM8958_MICD_RATE_MASK, val);
}
static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
@@ -207,7 +179,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
static int configure_clock(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- int old, new;
+ int change, new;
/* Bring up the AIF clocks first */
configure_aif_clock(codec, 0);
@@ -220,23 +192,22 @@ static int configure_clock(struct snd_soc_codec *codec)
*/
/* If they're equal it doesn't matter which is used */
- if (wm8994->aifclk[0] == wm8994->aifclk[1])
+ if (wm8994->aifclk[0] == wm8994->aifclk[1]) {
+ wm8958_micd_set_rate(codec);
return 0;
+ }
if (wm8994->aifclk[0] < wm8994->aifclk[1])
new = WM8994_SYSCLK_SRC;
else
new = 0;
- old = snd_soc_read(codec, WM8994_CLOCKING_1) & WM8994_SYSCLK_SRC;
-
- /* If there's no change then we're done. */
- if (old == new)
- return 0;
-
- snd_soc_update_bits(codec, WM8994_CLOCKING_1, WM8994_SYSCLK_SRC, new);
+ change = snd_soc_update_bits(codec, WM8994_CLOCKING_1,
+ WM8994_SYSCLK_SRC, new);
+ if (change)
+ snd_soc_dapm_sync(&codec->dapm);
- snd_soc_dapm_sync(&codec->dapm);
+ wm8958_micd_set_rate(codec);
return 0;
}
@@ -281,6 +252,8 @@ static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1);
static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0);
static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0);
static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0);
+static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0);
#define WM8994_DRC_SWITCH(xname, reg, shift) \
{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
@@ -660,10 +633,120 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0,
eq_tlv),
};
+static const char *wm8958_ng_text[] = {
+ "30ms", "125ms", "250ms", "500ms",
+};
+
+static const struct soc_enum wm8958_aif1dac1_ng_hold =
+ SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE,
+ WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text);
+
+static const struct soc_enum wm8958_aif1dac2_ng_hold =
+ SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE,
+ WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text);
+
+static const struct soc_enum wm8958_aif2dac_ng_hold =
+ SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE,
+ WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text);
+
static const struct snd_kcontrol_new wm8958_snd_controls[] = {
SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv),
+
+SOC_SINGLE("AIF1DAC1 Noise Gate Switch", WM8958_AIF1_DAC1_NOISE_GATE,
+ WM8958_AIF1DAC1_NG_ENA_SHIFT, 1, 0),
+SOC_ENUM("AIF1DAC1 Noise Gate Hold Time", wm8958_aif1dac1_ng_hold),
+SOC_SINGLE_TLV("AIF1DAC1 Noise Gate Threshold Volume",
+ WM8958_AIF1_DAC1_NOISE_GATE, WM8958_AIF1DAC1_NG_THR_SHIFT,
+ 7, 1, ng_tlv),
+
+SOC_SINGLE("AIF1DAC2 Noise Gate Switch", WM8958_AIF1_DAC2_NOISE_GATE,
+ WM8958_AIF1DAC2_NG_ENA_SHIFT, 1, 0),
+SOC_ENUM("AIF1DAC2 Noise Gate Hold Time", wm8958_aif1dac2_ng_hold),
+SOC_SINGLE_TLV("AIF1DAC2 Noise Gate Threshold Volume",
+ WM8958_AIF1_DAC2_NOISE_GATE, WM8958_AIF1DAC2_NG_THR_SHIFT,
+ 7, 1, ng_tlv),
+
+SOC_SINGLE("AIF2DAC Noise Gate Switch", WM8958_AIF2_DAC_NOISE_GATE,
+ WM8958_AIF2DAC_NG_ENA_SHIFT, 1, 0),
+SOC_ENUM("AIF2DAC Noise Gate Hold Time", wm8958_aif2dac_ng_hold),
+SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume",
+ WM8958_AIF2_DAC_NOISE_GATE, WM8958_AIF2DAC_NG_THR_SHIFT,
+ 7, 1, ng_tlv),
+};
+
+static const struct snd_kcontrol_new wm1811_snd_controls[] = {
+SOC_SINGLE_TLV("MIXINL IN1LP Boost Volume", WM8994_INPUT_MIXER_1, 7, 1, 0,
+ mixin_boost_tlv),
+SOC_SINGLE_TLV("MIXINL IN1RP Boost Volume", WM8994_INPUT_MIXER_1, 8, 1, 0,
+ mixin_boost_tlv),
};
+/* We run all mode setting through a function to enforce audio mode */
+static void wm1811_jackdet_set_mode(struct snd_soc_codec *codec, u16 mode)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ if (!wm8994->jackdet || !wm8994->jack_cb)
+ return;
+
+ if (wm8994->active_refcount)
+ mode = WM1811_JACKDET_MODE_AUDIO;
+
+ if (mode == wm8994->jackdet_mode)
+ return;
+
+ wm8994->jackdet_mode = mode;
+
+ /* Always use audio mode to detect while the system is active */
+ if (mode != WM1811_JACKDET_MODE_NONE)
+ mode = WM1811_JACKDET_MODE_AUDIO;
+
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM1811_JACKDET_MODE_MASK, mode);
+}
+
+static void active_reference(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ mutex_lock(&wm8994->accdet_lock);
+
+ wm8994->active_refcount++;
+
+ dev_dbg(codec->dev, "Active refcount incremented, now %d\n",
+ wm8994->active_refcount);
+
+ /* If we're using jack detection go into audio mode */
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_AUDIO);
+
+ mutex_unlock(&wm8994->accdet_lock);
+}
+
+static void active_dereference(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ u16 mode;
+
+ mutex_lock(&wm8994->accdet_lock);
+
+ wm8994->active_refcount--;
+
+ dev_dbg(codec->dev, "Active refcount decremented, now %d\n",
+ wm8994->active_refcount);
+
+ if (wm8994->active_refcount == 0) {
+ /* Go into appropriate detection only mode */
+ if (wm8994->jack_mic || wm8994->mic_detecting)
+ mode = WM1811_JACKDET_MODE_MIC;
+ else
+ mode = WM1811_JACKDET_MODE_JACK;
+
+ wm1811_jackdet_set_mode(codec, mode);
+ }
+
+ mutex_unlock(&wm8994->accdet_lock);
+}
+
static int clk_sys_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
@@ -681,6 +764,179 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static void vmid_reference(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ pm_runtime_get_sync(codec->dev);
+
+ wm8994->vmid_refcount++;
+
+ dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n",
+ wm8994->vmid_refcount);
+
+ if (wm8994->vmid_refcount == 1) {
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+ WM8994_LINEOUT1_DISCH |
+ WM8994_LINEOUT2_DISCH, 0);
+
+ wm_hubs_vmid_ena(codec);
+
+ switch (wm8994->vmid_mode) {
+ default:
+ WARN_ON(0 == "Invalid VMID mode");
+ case WM8994_VMID_NORMAL:
+ /* Startup bias, VMID ramp & buffer */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_BIAS_SRC |
+ WM8994_VMID_DISCH |
+ WM8994_STARTUP_BIAS_ENA |
+ WM8994_VMID_BUF_ENA |
+ WM8994_VMID_RAMP_MASK,
+ WM8994_BIAS_SRC |
+ WM8994_STARTUP_BIAS_ENA |
+ WM8994_VMID_BUF_ENA |
+ (0x3 << WM8994_VMID_RAMP_SHIFT));
+
+ /* Main bias enable, VMID=2x40k */
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_BIAS_ENA |
+ WM8994_VMID_SEL_MASK,
+ WM8994_BIAS_ENA | 0x2);
+
+ msleep(50);
+
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_VMID_RAMP_MASK |
+ WM8994_BIAS_SRC,
+ 0);
+ break;
+
+ case WM8994_VMID_FORCE:
+ /* Startup bias, slow VMID ramp & buffer */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_BIAS_SRC |
+ WM8994_VMID_DISCH |
+ WM8994_STARTUP_BIAS_ENA |
+ WM8994_VMID_BUF_ENA |
+ WM8994_VMID_RAMP_MASK,
+ WM8994_BIAS_SRC |
+ WM8994_STARTUP_BIAS_ENA |
+ WM8994_VMID_BUF_ENA |
+ (0x2 << WM8994_VMID_RAMP_SHIFT));
+
+ /* Main bias enable, VMID=2x40k */
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_BIAS_ENA |
+ WM8994_VMID_SEL_MASK,
+ WM8994_BIAS_ENA | 0x2);
+
+ msleep(400);
+
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_VMID_RAMP_MASK |
+ WM8994_BIAS_SRC,
+ 0);
+ break;
+ }
+ }
+}
+
+static void vmid_dereference(struct snd_soc_codec *codec)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+
+ wm8994->vmid_refcount--;
+
+ dev_dbg(codec->dev, "Dereferencing VMID, refcount is now %d\n",
+ wm8994->vmid_refcount);
+
+ if (wm8994->vmid_refcount == 0) {
+ if (wm8994->hubs.lineout1_se)
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
+ WM8994_LINEOUT1N_ENA |
+ WM8994_LINEOUT1P_ENA,
+ WM8994_LINEOUT1N_ENA |
+ WM8994_LINEOUT1P_ENA);
+
+ if (wm8994->hubs.lineout2_se)
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
+ WM8994_LINEOUT2N_ENA |
+ WM8994_LINEOUT2P_ENA,
+ WM8994_LINEOUT2N_ENA |
+ WM8994_LINEOUT2P_ENA);
+
+ /* Start discharging VMID */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_BIAS_SRC |
+ WM8994_VMID_DISCH,
+ WM8994_BIAS_SRC |
+ WM8994_VMID_DISCH);
+
+ switch (wm8994->vmid_mode) {
+ case WM8994_VMID_FORCE:
+ msleep(350);
+ break;
+ default:
+ break;
+ }
+
+ snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
+ WM8994_VROI, WM8994_VROI);
+
+ /* Active discharge */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
+ WM8994_LINEOUT1_DISCH |
+ WM8994_LINEOUT2_DISCH,
+ WM8994_LINEOUT1_DISCH |
+ WM8994_LINEOUT2_DISCH);
+
+ msleep(150);
+
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_3,
+ WM8994_LINEOUT1N_ENA |
+ WM8994_LINEOUT1P_ENA |
+ WM8994_LINEOUT2N_ENA |
+ WM8994_LINEOUT2P_ENA, 0);
+
+ snd_soc_update_bits(codec, WM8994_ADDITIONAL_CONTROL,
+ WM8994_VROI, 0);
+
+ /* Switch off startup biases */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_BIAS_SRC |
+ WM8994_STARTUP_BIAS_ENA |
+ WM8994_VMID_BUF_ENA |
+ WM8994_VMID_RAMP_MASK, 0);
+
+ snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
+ WM8994_BIAS_ENA | WM8994_VMID_SEL_MASK, 0);
+
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM8994_VMID_RAMP_MASK, 0);
+ }
+
+ pm_runtime_put(codec->dev);
+}
+
+static int vmid_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ vmid_reference(codec);
+ break;
+
+ case SND_SOC_DAPM_POST_PMD:
+ vmid_dereference(codec);
+ break;
+ }
+
+ return 0;
+}
+
static void wm8994_update_class_w(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
@@ -1190,15 +1446,15 @@ SND_SOC_DAPM_DAC("DAC1R", NULL, WM8994_POWER_MANAGEMENT_5, 0, 0),
};
static const struct snd_soc_dapm_widget wm8994_adc_revd_widgets[] = {
-SND_SOC_DAPM_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
- adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
-SND_SOC_DAPM_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
- adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_VIRT_MUX_E("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux,
+ adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_VIRT_MUX_E("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux,
+ adc_mux_ev, SND_SOC_DAPM_PRE_PMU),
};
static const struct snd_soc_dapm_widget wm8994_adc_widgets[] = {
-SND_SOC_DAPM_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
-SND_SOC_DAPM_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
+SND_SOC_DAPM_VIRT_MUX("ADCL Mux", WM8994_POWER_MANAGEMENT_4, 1, 0, &adcl_mux),
+SND_SOC_DAPM_VIRT_MUX("ADCR Mux", WM8994_POWER_MANAGEMENT_4, 0, 0, &adcr_mux),
};
static const struct snd_soc_dapm_widget wm8994_dapm_widgets[] = {
@@ -1208,6 +1464,8 @@ SND_SOC_DAPM_INPUT("Clock"),
SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev,
SND_SOC_DAPM_PRE_PMU),
+SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1272,17 +1530,17 @@ SND_SOC_DAPM_AIF_IN_E("AIF2DACR", NULL, 0,
WM8994_POWER_MANAGEMENT_5, 12, 0, wm8958_aif_ev,
SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_AIF_IN("AIF1DACDAT", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF2DACDAT", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF1DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF2DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_MUX("AIF1DAC Mux", SND_SOC_NOPM, 0, 0, &aif1dac_mux),
SND_SOC_DAPM_MUX("AIF2DAC Mux", SND_SOC_NOPM, 0, 0, &aif2dac_mux),
SND_SOC_DAPM_MUX("AIF2ADC Mux", SND_SOC_NOPM, 0, 0, &aif2adc_mux),
-SND_SOC_DAPM_AIF_IN("AIF3DACDAT", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF3ADCDAT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF3DACDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
+SND_SOC_DAPM_AIF_OUT("AIF3ADCDAT", NULL, 0, SND_SOC_NOPM, 0, 0),
SND_SOC_DAPM_SUPPLY("TOCLK", WM8994_CLOCKING_1, 4, 0, NULL, 0),
@@ -1397,6 +1655,14 @@ static const struct snd_soc_dapm_route intercon[] = {
{ "TOCLK", NULL, "CLK_SYS" },
+ { "AIF1DACDAT", NULL, "AIF1 Playback" },
+ { "AIF2DACDAT", NULL, "AIF2 Playback" },
+ { "AIF3DACDAT", NULL, "AIF3 Playback" },
+
+ { "AIF1 Capture", NULL, "AIF1ADCDAT" },
+ { "AIF2 Capture", NULL, "AIF2ADCDAT" },
+ { "AIF3 Capture", NULL, "AIF3ADCDAT" },
+
/* AIF1 outputs */
{ "AIF1ADC1L", NULL, "AIF1ADC1L Mixer" },
{ "AIF1ADC1L Mixer", "ADC/DMIC Switch", "ADCL Mux" },
@@ -1525,6 +1791,8 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = {
static const struct snd_soc_dapm_route wm8994_intercon[] = {
{ "AIF2DACL", NULL, "AIF2DAC Mux" },
{ "AIF2DACR", NULL, "AIF2DAC Mux" },
+ { "MICBIAS1", NULL, "VMID" },
+ { "MICBIAS2", NULL, "VMID" },
};
static const struct snd_soc_dapm_route wm8958_intercon[] = {
@@ -1629,10 +1897,12 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
unsigned int freq_in, unsigned int freq_out)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
int reg_offset, ret;
struct fll_div fll;
u16 reg, aif1, aif2;
unsigned long timeout;
+ bool was_enabled;
aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1)
& WM8994_AIF1CLK_ENA;
@@ -1653,6 +1923,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
return -EINVAL;
}
+ reg = snd_soc_read(codec, WM8994_FLL1_CONTROL_1 + reg_offset);
+ was_enabled = reg & WM8994_FLL1_ENA;
+
switch (src) {
case 0:
/* Allow no source specification when stopping */
@@ -1702,7 +1975,8 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
WM8994_FLL1_OUTDIV_MASK |
WM8994_FLL1_FRATIO_MASK, reg);
- snd_soc_write(codec, WM8994_FLL1_CONTROL_3 + reg_offset, fll.k);
+ snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_3 + reg_offset,
+ WM8994_FLL1_K_MASK, fll.k);
snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset,
WM8994_FLL1_N_MASK,
@@ -1719,6 +1993,23 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
/* Enable (with fractional mode if required) */
if (freq_out) {
+ /* Enable VMID if we need it */
+ if (!was_enabled) {
+ active_reference(codec);
+
+ switch (control->type) {
+ case WM8994:
+ vmid_reference(codec);
+ break;
+ case WM8958:
+ if (wm8994->revision < 1)
+ vmid_reference(codec);
+ break;
+ default:
+ break;
+ }
+ }
+
if (fll.k)
reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC;
else
@@ -1736,6 +2027,22 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src,
} else {
msleep(5);
}
+ } else {
+ if (was_enabled) {
+ switch (control->type) {
+ case WM8994:
+ vmid_dereference(codec);
+ break;
+ case WM8958:
+ if (wm8994->revision < 1)
+ vmid_dereference(codec);
+ break;
+ default:
+ break;
+ }
+
+ active_dereference(codec);
+ }
}
wm8994->fll[id].in = freq_in;
@@ -1844,23 +2151,35 @@ static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai,
static int wm8994_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- struct wm8994 *control = codec->control_data;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
+
+ wm_hubs_set_bias_level(codec, level);
switch (level) {
case SND_SOC_BIAS_ON:
break;
case SND_SOC_BIAS_PREPARE:
- /* VMID=2x40k */
- snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
- WM8994_VMID_SEL_MASK, 0x2);
+ /* MICBIAS into regulating mode */
+ switch (control->type) {
+ case WM8958:
+ case WM1811:
+ snd_soc_update_bits(codec, WM8958_MICBIAS1,
+ WM8958_MICB1_MODE, 0);
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_MODE, 0);
+ break;
+ default:
+ break;
+ }
+
+ if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+ active_reference(codec);
break;
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
- pm_runtime_get_sync(codec->dev);
-
switch (control->type) {
case WM8994:
if (wm8994->revision < 4) {
@@ -1888,6 +2207,15 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
WM8958_CP_DISCH);
}
break;
+
+ case WM1811:
+ if (wm8994->revision < 2) {
+ snd_soc_write(codec, 0x102, 0x3);
+ snd_soc_write(codec, 0x5d, 0x7e);
+ snd_soc_write(codec, 0x5e, 0x0);
+ snd_soc_write(codec, 0x102, 0x0);
+ }
+ break;
}
/* Discharge LINEOUT1 & 2 */
@@ -1896,79 +2224,92 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec,
WM8994_LINEOUT2_DISCH,
WM8994_LINEOUT1_DISCH |
WM8994_LINEOUT2_DISCH);
-
- /* Startup bias, VMID ramp & buffer */
- snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
- WM8994_STARTUP_BIAS_ENA |
- WM8994_VMID_BUF_ENA |
- WM8994_VMID_RAMP_MASK,
- WM8994_STARTUP_BIAS_ENA |
- WM8994_VMID_BUF_ENA |
- (0x11 << WM8994_VMID_RAMP_SHIFT));
-
- /* Main bias enable, VMID=2x40k */
- snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
- WM8994_BIAS_ENA |
- WM8994_VMID_SEL_MASK,
- WM8994_BIAS_ENA | 0x2);
-
- msleep(20);
}
- /* VMID=2x500k */
- snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
- WM8994_VMID_SEL_MASK, 0x4);
+ if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE)
+ active_dereference(codec);
+ /* MICBIAS into bypass mode on newer devices */
+ switch (control->type) {
+ case WM8958:
+ case WM1811:
+ snd_soc_update_bits(codec, WM8958_MICBIAS1,
+ WM8958_MICB1_MODE,
+ WM8958_MICB1_MODE);
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_MODE,
+ WM8958_MICB2_MODE);
+ break;
+ default:
+ break;
+ }
break;
case SND_SOC_BIAS_OFF:
- if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
- /* Switch over to startup biases */
- snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
- WM8994_BIAS_SRC |
- WM8994_STARTUP_BIAS_ENA |
- WM8994_VMID_BUF_ENA |
- WM8994_VMID_RAMP_MASK,
- WM8994_BIAS_SRC |
- WM8994_STARTUP_BIAS_ENA |
- WM8994_VMID_BUF_ENA |
- (1 << WM8994_VMID_RAMP_SHIFT));
+ if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+ wm8994->cur_fw = NULL;
+ break;
+ }
- /* Disable main biases */
- snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1,
- WM8994_BIAS_ENA |
- WM8994_VMID_SEL_MASK, 0);
+ codec->dapm.bias_level = level;
- /* Discharge line */
- snd_soc_update_bits(codec, WM8994_ANTIPOP_1,
- WM8994_LINEOUT1_DISCH |
- WM8994_LINEOUT2_DISCH,
- WM8994_LINEOUT1_DISCH |
- WM8994_LINEOUT2_DISCH);
+ return 0;
+}
- msleep(5);
+int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode)
+{
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- /* Switch off startup biases */
- snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
- WM8994_BIAS_SRC |
- WM8994_STARTUP_BIAS_ENA |
- WM8994_VMID_BUF_ENA |
- WM8994_VMID_RAMP_MASK, 0);
+ switch (mode) {
+ case WM8994_VMID_NORMAL:
+ if (wm8994->hubs.lineout1_se) {
+ snd_soc_dapm_disable_pin(&codec->dapm,
+ "LINEOUT1N Driver");
+ snd_soc_dapm_disable_pin(&codec->dapm,
+ "LINEOUT1P Driver");
+ }
+ if (wm8994->hubs.lineout2_se) {
+ snd_soc_dapm_disable_pin(&codec->dapm,
+ "LINEOUT2N Driver");
+ snd_soc_dapm_disable_pin(&codec->dapm,
+ "LINEOUT2P Driver");
+ }
- wm8994->cur_fw = NULL;
+ /* Do the sync with the old mode to allow it to clean up */
+ snd_soc_dapm_sync(&codec->dapm);
+ wm8994->vmid_mode = mode;
+ break;
- pm_runtime_put(codec->dev);
+ case WM8994_VMID_FORCE:
+ if (wm8994->hubs.lineout1_se) {
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "LINEOUT1N Driver");
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "LINEOUT1P Driver");
+ }
+ if (wm8994->hubs.lineout2_se) {
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "LINEOUT2N Driver");
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "LINEOUT2P Driver");
}
+
+ wm8994->vmid_mode = mode;
+ snd_soc_dapm_sync(&codec->dapm);
break;
+
+ default:
+ return -EINVAL;
}
- codec->dapm.bias_level = level;
+
return 0;
}
static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct snd_soc_codec *codec = dai->codec;
- struct wm8994 *control = codec->control_data;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
int ms_reg;
int aif1_reg;
int ms = 0;
@@ -2055,10 +2396,18 @@ static int wm8994_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt)
/* The AIF2 format configuration needs to be mirrored to AIF3
* on WM8958 if it's in use so just do it all the time. */
- if (control->type == WM8958 && dai->id == 2)
- snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1,
- WM8994_AIF1_LRCLK_INV |
- WM8958_AIF3_FMT_MASK, aif1);
+ switch (control->type) {
+ case WM1811:
+ case WM8958:
+ if (dai->id == 2)
+ snd_soc_update_bits(codec, WM8958_AIF3_CONTROL_1,
+ WM8994_AIF1_LRCLK_INV |
+ WM8958_AIF3_FMT_MASK, aif1);
+ break;
+
+ default:
+ break;
+ }
snd_soc_update_bits(codec, aif1_reg,
WM8994_AIF1_BCLK_INV | WM8994_AIF1_LRCLK_INV |
@@ -2100,7 +2449,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- struct wm8994 *control = codec->control_data;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
int aif1_reg;
int aif2_reg;
@@ -2143,14 +2491,6 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
dev_dbg(codec->dev, "AIF2 using split LRCLK\n");
}
break;
- case 3:
- switch (control->type) {
- case WM8958:
- aif1_reg = WM8958_AIF3_CONTROL_1;
- break;
- default:
- return 0;
- }
default:
return -EINVAL;
}
@@ -2231,6 +2571,11 @@ static int wm8994_hw_params(struct snd_pcm_substream *substream,
bclk |= best << WM8994_AIF1_BCLK_DIV_SHIFT;
lrclk = bclk_rate / params_rate(params);
+ if (!lrclk) {
+ dev_err(dai->dev, "Unable to generate LRCLK from %dHz BCLK\n",
+ bclk_rate);
+ return -EINVAL;
+ }
dev_dbg(dai->dev, "Using LRCLK rate %d for actual LRCLK %dHz\n",
lrclk, bclk_rate / lrclk);
@@ -2264,13 +2609,15 @@ static int wm8994_aif3_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_codec *codec = dai->codec;
- struct wm8994 *control = codec->control_data;
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
+ struct wm8994 *control = wm8994->wm8994;
int aif1_reg;
int aif1 = 0;
switch (dai->id) {
case 3:
switch (control->type) {
+ case WM1811:
case WM8958:
aif1_reg = WM8958_AIF3_CONTROL_1;
break;
@@ -2311,7 +2658,7 @@ static void wm8994_aif_shutdown(struct snd_pcm_substream *substream,
rate_reg = WM8994_AIF1_RATE;
break;
case 2:
- rate_reg = WM8994_AIF1_RATE;
+ rate_reg = WM8994_AIF2_RATE;
break;
default:
break;
@@ -2384,12 +2731,27 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate)
return snd_soc_update_bits(codec, reg, mask, val);
}
+static int wm8994_aif2_probe(struct snd_soc_dai *dai)
+{
+ struct snd_soc_codec *codec = dai->codec;
+
+ /* Disable the pulls on the AIF if we're using it to save power. */
+ snd_soc_update_bits(codec, WM8994_GPIO_3,
+ WM8994_GPN_PU | WM8994_GPN_PD, 0);
+ snd_soc_update_bits(codec, WM8994_GPIO_4,
+ WM8994_GPN_PU | WM8994_GPN_PD, 0);
+ snd_soc_update_bits(codec, WM8994_GPIO_5,
+ WM8994_GPN_PU | WM8994_GPN_PD, 0);
+
+ return 0;
+}
+
#define WM8994_RATES SNDRV_PCM_RATE_8000_96000
#define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
+static const struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
.set_sysclk = wm8994_set_dai_sysclk,
.set_fmt = wm8994_set_dai_fmt,
.hw_params = wm8994_hw_params,
@@ -2399,7 +2761,7 @@ static struct snd_soc_dai_ops wm8994_aif1_dai_ops = {
.set_tristate = wm8994_set_tristate,
};
-static struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
+static const struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
.set_sysclk = wm8994_set_dai_sysclk,
.set_fmt = wm8994_set_dai_fmt,
.hw_params = wm8994_hw_params,
@@ -2409,7 +2771,7 @@ static struct snd_soc_dai_ops wm8994_aif2_dai_ops = {
.set_tristate = wm8994_set_tristate,
};
-static struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
+static const struct snd_soc_dai_ops wm8994_aif3_dai_ops = {
.hw_params = wm8994_aif3_hw_params,
.set_tristate = wm8994_set_tristate,
};
@@ -2424,6 +2786,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF1 Capture",
@@ -2431,6 +2794,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
.ops = &wm8994_aif1_dai_ops,
},
@@ -2443,6 +2807,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF2 Capture",
@@ -2450,7 +2815,9 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
+ .probe = wm8994_aif2_probe,
.ops = &wm8994_aif2_dai_ops,
},
{
@@ -2462,6 +2829,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF3 Capture",
@@ -2469,22 +2837,27 @@ static struct snd_soc_dai_driver wm8994_dai[] = {
.channels_max = 2,
.rates = WM8994_RATES,
.formats = WM8994_FORMATS,
- },
+ .sig_bits = 24,
+ },
.ops = &wm8994_aif3_dai_ops,
}
};
#ifdef CONFIG_PM
-static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8994_codec_suspend(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994 *control = codec->control_data;
+ struct wm8994 *control = wm8994->wm8994;
int i, ret;
switch (control->type) {
case WM8994:
snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, 0);
break;
+ case WM1811:
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM1811_JACKDET_MODE_MASK, 0);
+ /* Fall through */
case WM8958:
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_ENA, 0);
@@ -2505,17 +2878,17 @@ static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state)
return 0;
}
-static int wm8994_resume(struct snd_soc_codec *codec)
+static int wm8994_codec_resume(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994 *control = codec->control_data;
+ struct wm8994 *control = wm8994->wm8994;
int i, ret;
unsigned int val, mask;
if (wm8994->revision < 4) {
/* force a HW read */
- val = wm8994_reg_read(codec->control_data,
- WM8994_POWER_MANAGEMENT_5);
+ ret = regmap_read(control->regmap,
+ WM8994_POWER_MANAGEMENT_5, &val);
/* modify the cache only */
codec->cache_only = 1;
@@ -2527,13 +2900,6 @@ static int wm8994_resume(struct snd_soc_codec *codec)
codec->cache_only = 0;
}
- /* Restore the registers */
- ret = snd_soc_cache_sync(codec);
- if (ret != 0)
- dev_err(codec->dev, "Failed to sync cache: %d\n", ret);
-
- wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) {
if (!wm8994->fll_suspend[i].out)
continue;
@@ -2553,6 +2919,15 @@ static int wm8994_resume(struct snd_soc_codec *codec)
snd_soc_update_bits(codec, WM8994_MICBIAS,
WM8994_MICD_ENA, WM8994_MICD_ENA);
break;
+ case WM1811:
+ if (wm8994->jackdet && wm8994->jack_cb) {
+ /* Restart from idle */
+ snd_soc_update_bits(codec, WM8994_ANTIPOP_2,
+ WM1811_JACKDET_MODE_MASK,
+ WM1811_JACKDET_MODE_JACK);
+ break;
+ }
+ break;
case WM8958:
if (wm8994->jack_cb)
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
@@ -2563,8 +2938,8 @@ static int wm8994_resume(struct snd_soc_codec *codec)
return 0;
}
#else
-#define wm8994_suspend NULL
-#define wm8994_resume NULL
+#define wm8994_codec_suspend NULL
+#define wm8994_codec_resume NULL
#endif
static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
@@ -2627,7 +3002,7 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994)
wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts;
wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts;
- ret = snd_soc_add_controls(wm8994->codec, controls,
+ ret = snd_soc_add_codec_controls(wm8994->codec, controls,
ARRAY_SIZE(controls));
if (ret != 0)
dev_err(wm8994->codec->dev,
@@ -2665,8 +3040,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
};
/* We need an array of texts for the enum API */
- wm8994->drc_texts = kmalloc(sizeof(char *)
- * pdata->num_drc_cfgs, GFP_KERNEL);
+ wm8994->drc_texts = devm_kzalloc(wm8994->codec->dev,
+ sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL);
if (!wm8994->drc_texts) {
dev_err(wm8994->codec->dev,
"Failed to allocate %d DRC config texts\n",
@@ -2680,7 +3055,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
wm8994->drc_enum.max = pdata->num_drc_cfgs;
wm8994->drc_enum.texts = wm8994->drc_texts;
- ret = snd_soc_add_controls(wm8994->codec, controls,
+ ret = snd_soc_add_codec_controls(wm8994->codec, controls,
ARRAY_SIZE(controls));
if (ret != 0)
dev_err(wm8994->codec->dev,
@@ -2696,7 +3071,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
if (pdata->num_retune_mobile_cfgs)
wm8994_handle_retune_mobile_pdata(wm8994);
else
- snd_soc_add_controls(wm8994->codec, wm8994_eq_controls,
+ snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls,
ARRAY_SIZE(wm8994_eq_controls));
for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) {
@@ -2713,8 +3088,6 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
* @codec: WM8994 codec
* @jack: jack to report detection events on
* @micbias: microphone bias to detect on
- * @det: value to report for presence detection
- * @shrt: value to report for short detection
*
* Enable microphone detection via IRQ on the WM8994. If GPIOs are
* being used to bring out signals to the processor then only platform
@@ -2725,43 +3098,63 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994)
* and micbias2_lvl platform data members.
*/
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- int micbias, int det, int shrt)
+ int micbias)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct wm8994_micdet *micdet;
- struct wm8994 *control = codec->control_data;
- int reg;
+ struct wm8994 *control = wm8994->wm8994;
+ int reg, ret;
- if (control->type != WM8994)
+ if (control->type != WM8994) {
+ dev_warn(codec->dev, "Not a WM8994\n");
return -EINVAL;
+ }
switch (micbias) {
case 1:
micdet = &wm8994->micdet[0];
+ if (jack)
+ ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS1");
+ else
+ ret = snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS1");
break;
case 2:
micdet = &wm8994->micdet[1];
+ if (jack)
+ ret = snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS1");
+ else
+ ret = snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS1");
break;
default:
+ dev_warn(codec->dev, "Invalid MICBIAS %d\n", micbias);
return -EINVAL;
- }
+ }
- dev_dbg(codec->dev, "Configuring microphone detection on %d: %x %x\n",
- micbias, det, shrt);
+ if (ret != 0)
+ dev_warn(codec->dev, "Failed to configure MICBIAS%d: %d\n",
+ micbias, ret);
+
+ dev_dbg(codec->dev, "Configuring microphone detection on %d %p\n",
+ micbias, jack);
/* Store the configuration */
micdet->jack = jack;
- micdet->det = det;
- micdet->shrt = shrt;
+ micdet->detecting = true;
/* If either of the jacks is set up then enable detection */
if (wm8994->micdet[0].jack || wm8994->micdet[1].jack)
reg = WM8994_MICD_ENA;
- else
+ else
reg = 0;
snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg);
+ snd_soc_dapm_sync(&codec->dapm);
+
return 0;
}
EXPORT_SYMBOL_GPL(wm8994_mic_detect);
@@ -2787,20 +3180,42 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data)
dev_dbg(codec->dev, "Microphone status: %x\n", reg);
report = 0;
- if (reg & WM8994_MIC1_DET_STS)
- report |= priv->micdet[0].det;
- if (reg & WM8994_MIC1_SHRT_STS)
- report |= priv->micdet[0].shrt;
+ if (reg & WM8994_MIC1_DET_STS) {
+ if (priv->micdet[0].detecting)
+ report = SND_JACK_HEADSET;
+ }
+ if (reg & WM8994_MIC1_SHRT_STS) {
+ if (priv->micdet[0].detecting)
+ report = SND_JACK_HEADPHONE;
+ else
+ report |= SND_JACK_BTN_0;
+ }
+ if (report)
+ priv->micdet[0].detecting = false;
+ else
+ priv->micdet[0].detecting = true;
+
snd_soc_jack_report(priv->micdet[0].jack, report,
- priv->micdet[0].det | priv->micdet[0].shrt);
+ SND_JACK_HEADSET | SND_JACK_BTN_0);
report = 0;
- if (reg & WM8994_MIC2_DET_STS)
- report |= priv->micdet[1].det;
- if (reg & WM8994_MIC2_SHRT_STS)
- report |= priv->micdet[1].shrt;
+ if (reg & WM8994_MIC2_DET_STS) {
+ if (priv->micdet[1].detecting)
+ report = SND_JACK_HEADSET;
+ }
+ if (reg & WM8994_MIC2_SHRT_STS) {
+ if (priv->micdet[1].detecting)
+ report = SND_JACK_HEADPHONE;
+ else
+ report |= SND_JACK_BTN_0;
+ }
+ if (report)
+ priv->micdet[1].detecting = false;
+ else
+ priv->micdet[1].detecting = true;
+
snd_soc_jack_report(priv->micdet[1].jack, report,
- priv->micdet[1].det | priv->micdet[1].shrt);
+ SND_JACK_HEADSET | SND_JACK_BTN_0);
return IRQ_HANDLED;
}
@@ -2812,21 +3227,181 @@ static void wm8958_default_micdet(u16 status, void *data)
{
struct snd_soc_codec *codec = data;
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- int report = 0;
+ int report;
- /* If nothing present then clear our statuses */
- if (!(status & WM8958_MICD_STS))
- goto done;
+ dev_dbg(codec->dev, "MICDET %x\n", status);
- report = SND_JACK_MICROPHONE;
+ /* Either nothing present or just starting detection */
+ if (!(status & WM8958_MICD_STS)) {
+ if (!wm8994->jackdet) {
+ /* If nothing present then clear our statuses */
+ dev_dbg(codec->dev, "Detected open circuit\n");
+ wm8994->jack_mic = false;
+ wm8994->mic_detecting = true;
- /* Everything else is buttons; just assign slots */
- if (status & 0x1c)
- report |= SND_JACK_BTN_0;
+ wm8958_micd_set_rate(codec);
-done:
- snd_soc_jack_report(wm8994->micdet[0].jack, report,
- SND_JACK_BTN_0 | SND_JACK_MICROPHONE);
+ snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+ wm8994->btn_mask |
+ SND_JACK_HEADSET);
+ }
+ return;
+ }
+
+ /* If the measurement is showing a high impedence we've got a
+ * microphone.
+ */
+ if (wm8994->mic_detecting && (status & 0x600)) {
+ dev_dbg(codec->dev, "Detected microphone\n");
+
+ wm8994->mic_detecting = false;
+ wm8994->jack_mic = true;
+
+ wm8958_micd_set_rate(codec);
+
+ snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADSET,
+ SND_JACK_HEADSET);
+ }
+
+
+ if (wm8994->mic_detecting && status & 0xfc) {
+ dev_dbg(codec->dev, "Detected headphone\n");
+ wm8994->mic_detecting = false;
+
+ wm8958_micd_set_rate(codec);
+
+ snd_soc_jack_report(wm8994->micdet[0].jack, SND_JACK_HEADPHONE,
+ SND_JACK_HEADSET);
+
+ /* If we have jackdet that will detect removal */
+ if (wm8994->jackdet) {
+ mutex_lock(&wm8994->accdet_lock);
+
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+ WM8958_MICD_ENA, 0);
+
+ wm1811_jackdet_set_mode(codec,
+ WM1811_JACKDET_MODE_JACK);
+
+ mutex_unlock(&wm8994->accdet_lock);
+
+ if (wm8994->pdata->jd_ext_cap) {
+ mutex_lock(&codec->mutex);
+ snd_soc_dapm_disable_pin(&codec->dapm,
+ "MICBIAS2");
+ snd_soc_dapm_sync(&codec->dapm);
+ mutex_unlock(&codec->mutex);
+ }
+ }
+ }
+
+ /* Report short circuit as a button */
+ if (wm8994->jack_mic) {
+ report = 0;
+ if (status & 0x4)
+ report |= SND_JACK_BTN_0;
+
+ if (status & 0x8)
+ report |= SND_JACK_BTN_1;
+
+ if (status & 0x10)
+ report |= SND_JACK_BTN_2;
+
+ if (status & 0x20)
+ report |= SND_JACK_BTN_3;
+
+ if (status & 0x40)
+ report |= SND_JACK_BTN_4;
+
+ if (status & 0x80)
+ report |= SND_JACK_BTN_5;
+
+ snd_soc_jack_report(wm8994->micdet[0].jack, report,
+ wm8994->btn_mask);
+ }
+}
+
+static irqreturn_t wm1811_jackdet_irq(int irq, void *data)
+{
+ struct wm8994_priv *wm8994 = data;
+ struct snd_soc_codec *codec = wm8994->codec;
+ int reg;
+ bool present;
+
+ mutex_lock(&wm8994->accdet_lock);
+
+ reg = snd_soc_read(codec, WM1811_JACKDET_CTRL);
+ if (reg < 0) {
+ dev_err(codec->dev, "Failed to read jack status: %d\n", reg);
+ mutex_unlock(&wm8994->accdet_lock);
+ return IRQ_NONE;
+ }
+
+ dev_dbg(codec->dev, "JACKDET %x\n", reg);
+
+ present = reg & WM1811_JACKDET_LVL;
+
+ if (present) {
+ dev_dbg(codec->dev, "Jack detected\n");
+
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_DISCH, 0);
+
+ /* Disable debounce while inserted */
+ snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
+ WM1811_JACKDET_DB, 0);
+
+ /*
+ * Start off measument of microphone impedence to find
+ * out what's actually there.
+ */
+ wm8994->mic_detecting = true;
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_MIC);
+
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+ WM8958_MICD_ENA, WM8958_MICD_ENA);
+ } else {
+ dev_dbg(codec->dev, "Jack not detected\n");
+
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_DISCH, WM8958_MICB2_DISCH);
+
+ /* Enable debounce while removed */
+ snd_soc_update_bits(codec, WM1811_JACKDET_CTRL,
+ WM1811_JACKDET_DB, WM1811_JACKDET_DB);
+
+ wm8994->mic_detecting = false;
+ wm8994->jack_mic = false;
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+ WM8958_MICD_ENA, 0);
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_JACK);
+ }
+
+ mutex_unlock(&wm8994->accdet_lock);
+
+ /* If required for an external cap force MICBIAS on */
+ if (wm8994->pdata->jd_ext_cap) {
+ mutex_lock(&codec->mutex);
+
+ if (present)
+ snd_soc_dapm_force_enable_pin(&codec->dapm,
+ "MICBIAS2");
+ else
+ snd_soc_dapm_disable_pin(&codec->dapm, "MICBIAS2");
+
+ snd_soc_dapm_sync(&codec->dapm);
+ mutex_unlock(&codec->mutex);
+ }
+
+ if (present)
+ snd_soc_jack_report(wm8994->micdet[0].jack,
+ SND_JACK_MECHANICAL, SND_JACK_MECHANICAL);
+ else
+ snd_soc_jack_report(wm8994->micdet[0].jack, 0,
+ SND_JACK_MECHANICAL | SND_JACK_HEADSET |
+ wm8994->btn_mask);
+
+ return IRQ_HANDLED;
}
/**
@@ -2849,10 +3424,16 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8958_micdet_cb cb, void *cb_data)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994 *control = codec->control_data;
+ struct wm8994 *control = wm8994->wm8994;
+ u16 micd_lvl_sel;
- if (control->type != WM8958)
+ switch (control->type) {
+ case WM1811:
+ case WM8958:
+ break;
+ default:
return -EINVAL;
+ }
if (jack) {
if (!cb) {
@@ -2861,15 +3442,56 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
cb_data = codec;
}
+ snd_soc_dapm_force_enable_pin(&codec->dapm, "CLK_SYS");
+ snd_soc_dapm_sync(&codec->dapm);
+
wm8994->micdet[0].jack = jack;
wm8994->jack_cb = cb;
wm8994->jack_cb_data = cb_data;
- snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
- WM8958_MICD_ENA, WM8958_MICD_ENA);
+ wm8994->mic_detecting = true;
+ wm8994->jack_mic = false;
+
+ wm8958_micd_set_rate(codec);
+
+ /* Detect microphones and short circuits by default */
+ if (wm8994->pdata->micd_lvl_sel)
+ micd_lvl_sel = wm8994->pdata->micd_lvl_sel;
+ else
+ micd_lvl_sel = 0x41;
+
+ wm8994->btn_mask = SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+ SND_JACK_BTN_4 | SND_JACK_BTN_5;
+
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_2,
+ WM8958_MICD_LVL_SEL_MASK, micd_lvl_sel);
+
+ WARN_ON(codec->dapm.bias_level > SND_SOC_BIAS_STANDBY);
+
+ /*
+ * If we can use jack detection start off with that,
+ * otherwise jump straight to microphone detection.
+ */
+ if (wm8994->jackdet) {
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_DISCH,
+ WM8958_MICB2_DISCH);
+ snd_soc_update_bits(codec, WM8994_LDO_1,
+ WM8994_LDO1_DISCH, 0);
+ wm1811_jackdet_set_mode(codec,
+ WM1811_JACKDET_MODE_JACK);
+ } else {
+ snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
+ WM8958_MICD_ENA, WM8958_MICD_ENA);
+ }
+
} else {
snd_soc_update_bits(codec, WM8958_MIC_DETECT_1,
WM8958_MICD_ENA, 0);
+ wm1811_jackdet_set_mode(codec, WM1811_JACKDET_MODE_NONE);
+ snd_soc_dapm_disable_pin(&codec->dapm, "CLK_SYS");
+ snd_soc_dapm_sync(&codec->dapm);
}
return 0;
@@ -2880,19 +3502,42 @@ static irqreturn_t wm8958_mic_irq(int irq, void *data)
{
struct wm8994_priv *wm8994 = data;
struct snd_soc_codec *codec = wm8994->codec;
- int reg;
+ int reg, count;
- reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
- if (reg < 0) {
- dev_err(codec->dev, "Failed to read mic detect status: %d\n",
- reg);
- return IRQ_NONE;
- }
+ /*
+ * Jack detection may have detected a removal simulataneously
+ * with an update of the MICDET status; if so it will have
+ * stopped detection and we can ignore this interrupt.
+ */
+ if (!(snd_soc_read(codec, WM8958_MIC_DETECT_1) & WM8958_MICD_ENA))
+ return IRQ_HANDLED;
- if (!(reg & WM8958_MICD_VALID)) {
- dev_dbg(codec->dev, "Mic detect data not valid\n");
- goto out;
- }
+ /* We may occasionally read a detection without an impedence
+ * range being provided - if that happens loop again.
+ */
+ count = 10;
+ do {
+ reg = snd_soc_read(codec, WM8958_MIC_DETECT_3);
+ if (reg < 0) {
+ dev_err(codec->dev,
+ "Failed to read mic detect status: %d\n",
+ reg);
+ return IRQ_NONE;
+ }
+
+ if (!(reg & WM8958_MICD_VALID)) {
+ dev_dbg(codec->dev, "Mic detect data not valid\n");
+ goto out;
+ }
+
+ if (!(reg & WM8958_MICD_STS) || (reg & WM8958_MICD_LVL_MASK))
+ break;
+
+ msleep(1);
+ } while (count--);
+
+ if (count == 0)
+ dev_warn(codec->dev, "No impedence range reported for jack\n");
#ifndef CONFIG_SND_SOC_WM8994_MODULE
trace_snd_soc_jack_irq(dev_name(codec->dev));
@@ -2916,24 +3561,41 @@ static irqreturn_t wm8994_fifo_error(int irq, void *data)
return IRQ_HANDLED;
}
+static irqreturn_t wm8994_temp_warn(int irq, void *data)
+{
+ struct snd_soc_codec *codec = data;
+
+ dev_err(codec->dev, "Thermal warning\n");
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t wm8994_temp_shut(int irq, void *data)
+{
+ struct snd_soc_codec *codec = data;
+
+ dev_crit(codec->dev, "Thermal shutdown\n");
+
+ return IRQ_HANDLED;
+}
+
static int wm8994_codec_probe(struct snd_soc_codec *codec)
{
- struct wm8994 *control;
- struct wm8994_priv *wm8994;
+ struct wm8994 *control = dev_get_drvdata(codec->dev->parent);
+ struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
struct snd_soc_dapm_context *dapm = &codec->dapm;
+ unsigned int reg;
int ret, i;
- codec->control_data = dev_get_drvdata(codec->dev->parent);
- control = codec->control_data;
+ wm8994->codec = codec;
+ codec->control_data = control->regmap;
- wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL);
- if (wm8994 == NULL)
- return -ENOMEM;
- snd_soc_codec_set_drvdata(codec, wm8994);
+ snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
- wm8994->pdata = dev_get_platdata(codec->dev->parent);
wm8994->codec = codec;
+ mutex_init(&wm8994->accdet_lock);
+
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
init_completion(&wm8994->fll_locked[i]);
@@ -2944,57 +3606,74 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
WM8994_IRQ_MIC1_DET;
pm_runtime_enable(codec->dev);
- pm_runtime_resume(codec->dev);
-
- /* Read our current status back from the chip - we don't want to
- * reset as this may interfere with the GPIO or LDO operation. */
- for (i = 0; i < WM8994_CACHE_SIZE; i++) {
- if (!wm8994_readable(codec, i) || wm8994_volatile(codec, i))
- continue;
-
- ret = wm8994_reg_read(codec->control_data, i);
- if (ret <= 0)
- continue;
+ pm_runtime_idle(codec->dev);
- ret = snd_soc_cache_write(codec, i, ret);
- if (ret != 0) {
- dev_err(codec->dev,
- "Failed to initialise cache for 0x%x: %d\n",
- i, ret);
- goto err;
- }
- }
+ /* By default use idle_bias_off, will override for WM8994 */
+ codec->dapm.idle_bias_off = 1;
/* Set revision-specific configuration */
wm8994->revision = snd_soc_read(codec, WM8994_CHIP_REVISION);
switch (control->type) {
case WM8994:
+ /* Single ended line outputs should have VMID on. */
+ if (!wm8994->pdata->lineout1_diff ||
+ !wm8994->pdata->lineout2_diff)
+ codec->dapm.idle_bias_off = 0;
+
switch (wm8994->revision) {
case 2:
case 3:
- wm8994->hubs.dcs_codes = -5;
+ wm8994->hubs.dcs_codes_l = -5;
+ wm8994->hubs.dcs_codes_r = -5;
wm8994->hubs.hp_startup_mode = 1;
wm8994->hubs.dcs_readback_mode = 1;
wm8994->hubs.series_startup = 1;
break;
default:
- wm8994->hubs.dcs_readback_mode = 1;
+ wm8994->hubs.dcs_readback_mode = 2;
break;
}
break;
case WM8958:
wm8994->hubs.dcs_readback_mode = 1;
+ wm8994->hubs.hp_startup_mode = 1;
+ break;
+
+ case WM1811:
+ wm8994->hubs.dcs_readback_mode = 2;
+ wm8994->hubs.no_series_update = 1;
+ wm8994->hubs.hp_startup_mode = 1;
+ wm8994->hubs.no_cache_class_w = true;
+
+ switch (wm8994->revision) {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ wm8994->hubs.dcs_codes_l = -9;
+ wm8994->hubs.dcs_codes_r = -5;
+ break;
+ default:
+ break;
+ }
+
+ snd_soc_update_bits(codec, WM8994_ANALOGUE_HP_1,
+ WM1811_HPOUT1_ATTN, WM1811_HPOUT1_ATTN);
break;
default:
break;
}
- wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR,
+ wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR,
wm8994_fifo_error, "FIFO error", codec);
+ wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN,
+ wm8994_temp_warn, "Thermal warning", codec);
+ wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT,
+ wm8994_temp_shut, "Thermal shutdown", codec);
- ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+ ret = wm8994_request_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
wm_hubs_dcs_done, "DC servo done",
&wm8994->hubs);
if (ret == 0)
@@ -3014,7 +3693,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
ret);
}
- ret = wm8994_request_irq(codec->control_data,
+ ret = wm8994_request_irq(wm8994->wm8994,
WM8994_IRQ_MIC1_SHRT,
wm8994_mic_irq, "Mic 1 short",
wm8994);
@@ -3023,7 +3702,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
"Failed to request Mic1 short IRQ: %d\n",
ret);
- ret = wm8994_request_irq(codec->control_data,
+ ret = wm8994_request_irq(wm8994->wm8994,
WM8994_IRQ_MIC2_DET,
wm8994_mic_irq, "Mic 2 detect",
wm8994);
@@ -3032,7 +3711,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
"Failed to request Mic2 detect IRQ: %d\n",
ret);
- ret = wm8994_request_irq(codec->control_data,
+ ret = wm8994_request_irq(wm8994->wm8994,
WM8994_IRQ_MIC2_SHRT,
wm8994_mic_irq, "Mic 2 short",
wm8994);
@@ -3043,6 +3722,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
break;
case WM8958:
+ case WM1811:
if (wm8994->micdet_irq) {
ret = request_threaded_irq(wm8994->micdet_irq, NULL,
wm8958_mic_irq,
@@ -3056,9 +3736,24 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
}
}
+ switch (control->type) {
+ case WM1811:
+ if (wm8994->revision > 1) {
+ ret = wm8994_request_irq(wm8994->wm8994,
+ WM8994_IRQ_GPIO(6),
+ wm1811_jackdet_irq, "JACKDET",
+ wm8994);
+ if (ret == 0)
+ wm8994->jackdet = true;
+ }
+ break;
+ default:
+ break;
+ }
+
wm8994->fll_locked_irq = true;
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) {
- ret = wm8994_request_irq(codec->control_data,
+ ret = wm8994_request_irq(wm8994->wm8994,
WM8994_IRQ_FLL1_LOCK + i,
wm8994_fll_locked_irq, "FLL lock",
&wm8994->fll_locked[i]);
@@ -3066,35 +3761,38 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8994->fll_locked_irq = false;
}
+ /* Make sure we can read from the GPIOs if they're inputs */
+ pm_runtime_get_sync(codec->dev);
+
/* Remember if AIFnLRCLK is configured as a GPIO. This should be
* configured on init - if a system wants to do this dynamically
* at runtime we can deal with that then.
*/
- ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_1);
+ ret = regmap_read(control->regmap, WM8994_GPIO_1, &reg);
if (ret < 0) {
dev_err(codec->dev, "Failed to read GPIO1 state: %d\n", ret);
goto err_irq;
}
- if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
+ if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
wm8994->lrclk_shared[0] = 1;
wm8994_dai[0].symmetric_rates = 1;
} else {
wm8994->lrclk_shared[0] = 0;
}
- ret = wm8994_reg_read(codec->control_data, WM8994_GPIO_6);
+ ret = regmap_read(control->regmap, WM8994_GPIO_6, &reg);
if (ret < 0) {
dev_err(codec->dev, "Failed to read GPIO6 state: %d\n", ret);
goto err_irq;
}
- if ((ret & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
+ if ((reg & WM8994_GPN_FN_MASK) != WM8994_GP_FN_PIN_SPECIFIC) {
wm8994->lrclk_shared[1] = 1;
wm8994_dai[1].symmetric_rates = 1;
} else {
wm8994->lrclk_shared[1] = 0;
}
- wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
+ pm_runtime_put(codec->dev);
/* Latch volume updates (right only; we always do left then right). */
snd_soc_update_bits(codec, WM8994_AIF1_DAC1_LEFT_VOLUME,
@@ -3154,12 +3852,25 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
break;
}
+ /* Put MICBIAS into bypass mode by default on newer devices */
+ switch (control->type) {
+ case WM8958:
+ case WM1811:
+ snd_soc_update_bits(codec, WM8958_MICBIAS1,
+ WM8958_MICB1_MODE, WM8958_MICB1_MODE);
+ snd_soc_update_bits(codec, WM8958_MICBIAS2,
+ WM8958_MICB2_MODE, WM8958_MICB2_MODE);
+ break;
+ default:
+ break;
+ }
+
wm8994_update_class_w(codec);
wm8994_handle_pdata(wm8994);
wm_hubs_add_analogue_controls(codec);
- snd_soc_add_controls(codec, wm8994_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8994_snd_controls,
ARRAY_SIZE(wm8994_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8994_dapm_widgets,
ARRAY_SIZE(wm8994_dapm_widgets));
@@ -3185,7 +3896,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
}
break;
case WM8958:
- snd_soc_add_controls(codec, wm8958_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8958_snd_controls,
ARRAY_SIZE(wm8958_snd_controls));
snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
ARRAY_SIZE(wm8958_dapm_widgets));
@@ -3205,6 +3916,19 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
ARRAY_SIZE(wm8994_dac_widgets));
}
break;
+
+ case WM1811:
+ snd_soc_add_codec_controls(codec, wm8958_snd_controls,
+ ARRAY_SIZE(wm8958_snd_controls));
+ snd_soc_dapm_new_controls(dapm, wm8958_dapm_widgets,
+ ARRAY_SIZE(wm8958_dapm_widgets));
+ snd_soc_dapm_new_controls(dapm, wm8994_lateclk_widgets,
+ ARRAY_SIZE(wm8994_lateclk_widgets));
+ snd_soc_dapm_new_controls(dapm, wm8994_adc_widgets,
+ ARRAY_SIZE(wm8994_adc_widgets));
+ snd_soc_dapm_new_controls(dapm, wm8994_dac_widgets,
+ ARRAY_SIZE(wm8994_dac_widgets));
+ break;
}
@@ -3241,31 +3965,40 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec)
wm8958_dsp2_init(codec);
break;
+ case WM1811:
+ snd_soc_dapm_add_routes(dapm, wm8994_lateclk_intercon,
+ ARRAY_SIZE(wm8994_lateclk_intercon));
+ snd_soc_dapm_add_routes(dapm, wm8958_intercon,
+ ARRAY_SIZE(wm8958_intercon));
+ break;
}
return 0;
err_irq:
- wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994);
- wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994);
- wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994);
+ if (wm8994->jackdet)
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994);
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_SHRT, wm8994);
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET, wm8994);
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT, wm8994);
if (wm8994->micdet_irq)
free_irq(wm8994->micdet_irq, wm8994);
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
- wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i,
&wm8994->fll_locked[i]);
- wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
&wm8994->hubs);
- wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
-err:
- kfree(wm8994);
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, codec);
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec);
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec);
+
return ret;
}
static int wm8994_codec_remove(struct snd_soc_codec *codec)
{
struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec);
- struct wm8994 *control = codec->control_data;
+ struct wm8994 *control = wm8994->wm8994;
int i;
wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -3273,25 +4006,31 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
pm_runtime_disable(codec->dev);
for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++)
- wm8994_free_irq(codec->control_data, WM8994_IRQ_FLL1_LOCK + i,
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FLL1_LOCK + i,
&wm8994->fll_locked[i]);
- wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE,
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_DCS_DONE,
&wm8994->hubs);
- wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec);
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_FIFOS_ERR, codec);
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_SHUT, codec);
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_TEMP_WARN, codec);
+
+ if (wm8994->jackdet)
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_GPIO(6), wm8994);
switch (control->type) {
case WM8994:
if (wm8994->micdet_irq)
free_irq(wm8994->micdet_irq, wm8994);
- wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET,
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC2_DET,
wm8994);
- wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT,
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_SHRT,
wm8994);
- wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET,
+ wm8994_free_irq(wm8994->wm8994, WM8994_IRQ_MIC1_DET,
wm8994);
break;
+ case WM1811:
case WM8958:
if (wm8994->micdet_irq)
free_irq(wm8994->micdet_irq, wm8994);
@@ -3304,8 +4043,6 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
if (wm8994->enh_eq)
release_firmware(wm8994->enh_eq);
kfree(wm8994->retune_mobile_texts);
- kfree(wm8994->drc_texts);
- kfree(wm8994);
return 0;
}
@@ -3313,22 +4050,24 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec)
static struct snd_soc_codec_driver soc_codec_dev_wm8994 = {
.probe = wm8994_codec_probe,
.remove = wm8994_codec_remove,
- .suspend = wm8994_suspend,
- .resume = wm8994_resume,
- .read = wm8994_read,
- .write = wm8994_write,
- .readable_register = wm8994_readable,
- .volatile_register = wm8994_volatile,
+ .suspend = wm8994_codec_suspend,
+ .resume = wm8994_codec_resume,
.set_bias_level = wm8994_set_bias_level,
-
- .reg_cache_size = WM8994_CACHE_SIZE,
- .reg_cache_default = wm8994_reg_defaults,
- .reg_word_size = 2,
- .compress_type = SND_SOC_RBTREE_COMPRESSION,
};
static int __devinit wm8994_probe(struct platform_device *pdev)
{
+ struct wm8994_priv *wm8994;
+
+ wm8994 = devm_kzalloc(&pdev->dev, sizeof(struct wm8994_priv),
+ GFP_KERNEL);
+ if (wm8994 == NULL)
+ return -ENOMEM;
+ platform_set_drvdata(pdev, wm8994);
+
+ wm8994->wm8994 = dev_get_drvdata(pdev->dev.parent);
+ wm8994->pdata = dev_get_platdata(pdev->dev.parent);
+
return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994,
wm8994_dai, ARRAY_SIZE(wm8994_dai));
}
@@ -3339,27 +4078,48 @@ static int __devexit wm8994_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver wm8994_codec_driver = {
- .driver = {
- .name = "wm8994-codec",
- .owner = THIS_MODULE,
- },
- .probe = wm8994_probe,
- .remove = __devexit_p(wm8994_remove),
-};
-
-static __init int wm8994_init(void)
+#ifdef CONFIG_PM_SLEEP
+static int wm8994_suspend(struct device *dev)
{
- return platform_driver_register(&wm8994_codec_driver);
+ struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
+
+ /* Drop down to power saving mode when system is suspended */
+ if (wm8994->jackdet && !wm8994->active_refcount)
+ regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
+ WM1811_JACKDET_MODE_MASK,
+ wm8994->jackdet_mode);
+
+ return 0;
}
-module_init(wm8994_init);
-static __exit void wm8994_exit(void)
+static int wm8994_resume(struct device *dev)
{
- platform_driver_unregister(&wm8994_codec_driver);
+ struct wm8994_priv *wm8994 = dev_get_drvdata(dev);
+
+ if (wm8994->jackdet && wm8994->jack_cb)
+ regmap_update_bits(wm8994->wm8994->regmap, WM8994_ANTIPOP_2,
+ WM1811_JACKDET_MODE_MASK,
+ WM1811_JACKDET_MODE_AUDIO);
+
+ return 0;
}
-module_exit(wm8994_exit);
+#endif
+
+static const struct dev_pm_ops wm8994_pm_ops = {
+ SET_SYSTEM_SLEEP_PM_OPS(wm8994_suspend, wm8994_resume)
+};
+
+static struct platform_driver wm8994_codec_driver = {
+ .driver = {
+ .name = "wm8994-codec",
+ .owner = THIS_MODULE,
+ .pm = &wm8994_pm_ops,
+ },
+ .probe = wm8994_probe,
+ .remove = __devexit_p(wm8994_remove),
+};
+module_platform_driver(wm8994_codec_driver);
MODULE_DESCRIPTION("ASoC WM8994 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h
index 1ab2266039f7..c724112998d8 100644
--- a/sound/soc/codecs/wm8994.h
+++ b/sound/soc/codecs/wm8994.h
@@ -32,22 +32,19 @@
#define WM8994_FLL_SRC_LRCLK 3
#define WM8994_FLL_SRC_BCLK 4
+enum wm8994_vmid_mode {
+ WM8994_VMID_NORMAL,
+ WM8994_VMID_FORCE,
+};
+
typedef void (*wm8958_micdet_cb)(u16 status, void *data);
int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
- int micbias, int det, int shrt);
+ int micbias);
int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8958_micdet_cb cb, void *cb_data);
-#define WM8994_CACHE_SIZE 1570
-
-struct wm8994_access_mask {
- unsigned short readable; /* Mask of readable bits */
- unsigned short writable; /* Mask of writable bits */
-};
-
-extern const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE];
-extern const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE];
+int wm8994_vmid_mode(struct snd_soc_codec *codec, enum wm8994_vmid_mode mode);
int wm8958_aif_ev(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event);
@@ -56,8 +53,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec);
struct wm8994_micdet {
struct snd_soc_jack *jack;
- int det;
- int shrt;
+ bool detecting;
};
/* codec private data */
@@ -70,10 +66,11 @@ struct wm8994_fll_config {
#define WM8994_NUM_DRC 3
#define WM8994_NUM_EQ 3
+struct wm8994;
+
struct wm8994_priv {
struct wm_hubs_data hubs;
- enum snd_soc_control_type control_type;
- void *control_data;
+ struct wm8994 *wm8994;
struct snd_soc_codec *codec;
int sysclk[2];
int sysclk_rate[2];
@@ -83,6 +80,10 @@ struct wm8994_priv {
struct completion fll_locked[2];
bool fll_locked_irq;
+ int vmid_refcount;
+ int active_refcount;
+ enum wm8994_vmid_mode vmid_mode;
+
int dac_rates[2];
int lrclk_shared[2];
@@ -123,7 +124,13 @@ struct wm8994_priv {
const char **enh_eq_texts;
struct soc_enum enh_eq_enum;
+ struct mutex accdet_lock;
struct wm8994_micdet micdet[2];
+ bool mic_detecting;
+ bool jack_mic;
+ int btn_mask;
+ bool jackdet;
+ int jackdet_mode;
wm8958_micdet_cb jack_cb;
void *jack_cb_data;
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c
index 5ad873fda814..28c89b094c6e 100644
--- a/sound/soc/codecs/wm8995.c
+++ b/sound/soc/codecs/wm8995.c
@@ -18,6 +18,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/spi/spi.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
@@ -43,88 +44,331 @@ static const char *wm8995_supply_names[WM8995_NUM_SUPPLIES] = {
"MICVDD"
};
-static const u16 wm8995_reg_defs[WM8995_MAX_REGISTER + 1] = {
- [0] = 0x8995, [5] = 0x0100, [16] = 0x000b, [17] = 0x000b,
- [24] = 0x02c0, [25] = 0x02c0, [26] = 0x02c0, [27] = 0x02c0,
- [28] = 0x000f, [32] = 0x0005, [33] = 0x0005, [40] = 0x0003,
- [41] = 0x0013, [48] = 0x0004, [56] = 0x09f8, [64] = 0x1f25,
- [69] = 0x0004, [82] = 0xaaaa, [84] = 0x2a2a, [146] = 0x0060,
- [256] = 0x0002, [257] = 0x8004, [520] = 0x0010, [528] = 0x0083,
- [529] = 0x0083, [548] = 0x0c80, [580] = 0x0c80, [768] = 0x4050,
- [769] = 0x4000, [771] = 0x0040, [772] = 0x0040, [773] = 0x0040,
- [774] = 0x0004, [775] = 0x0100, [784] = 0x4050, [785] = 0x4000,
- [787] = 0x0040, [788] = 0x0040, [789] = 0x0040, [1024] = 0x00c0,
- [1025] = 0x00c0, [1026] = 0x00c0, [1027] = 0x00c0, [1028] = 0x00c0,
- [1029] = 0x00c0, [1030] = 0x00c0, [1031] = 0x00c0, [1056] = 0x0200,
- [1057] = 0x0010, [1058] = 0x0200, [1059] = 0x0010, [1088] = 0x0098,
- [1089] = 0x0845, [1104] = 0x0098, [1105] = 0x0845, [1152] = 0x6318,
- [1153] = 0x6300, [1154] = 0x0fca, [1155] = 0x0400, [1156] = 0x00d8,
- [1157] = 0x1eb5, [1158] = 0xf145, [1159] = 0x0b75, [1160] = 0x01c5,
- [1161] = 0x1c58, [1162] = 0xf373, [1163] = 0x0a54, [1164] = 0x0558,
- [1165] = 0x168e, [1166] = 0xf829, [1167] = 0x07ad, [1168] = 0x1103,
- [1169] = 0x0564, [1170] = 0x0559, [1171] = 0x4000, [1184] = 0x6318,
- [1185] = 0x6300, [1186] = 0x0fca, [1187] = 0x0400, [1188] = 0x00d8,
- [1189] = 0x1eb5, [1190] = 0xf145, [1191] = 0x0b75, [1192] = 0x01c5,
- [1193] = 0x1c58, [1194] = 0xf373, [1195] = 0x0a54, [1196] = 0x0558,
- [1197] = 0x168e, [1198] = 0xf829, [1199] = 0x07ad, [1200] = 0x1103,
- [1201] = 0x0564, [1202] = 0x0559, [1203] = 0x4000, [1280] = 0x00c0,
- [1281] = 0x00c0, [1282] = 0x00c0, [1283] = 0x00c0, [1312] = 0x0200,
- [1313] = 0x0010, [1344] = 0x0098, [1345] = 0x0845, [1408] = 0x6318,
- [1409] = 0x6300, [1410] = 0x0fca, [1411] = 0x0400, [1412] = 0x00d8,
- [1413] = 0x1eb5, [1414] = 0xf145, [1415] = 0x0b75, [1416] = 0x01c5,
- [1417] = 0x1c58, [1418] = 0xf373, [1419] = 0x0a54, [1420] = 0x0558,
- [1421] = 0x168e, [1422] = 0xf829, [1423] = 0x07ad, [1424] = 0x1103,
- [1425] = 0x0564, [1426] = 0x0559, [1427] = 0x4000, [1568] = 0x0002,
- [1792] = 0xa100, [1793] = 0xa101, [1794] = 0xa101, [1795] = 0xa101,
- [1796] = 0xa101, [1797] = 0xa101, [1798] = 0xa101, [1799] = 0xa101,
- [1800] = 0xa101, [1801] = 0xa101, [1802] = 0xa101, [1803] = 0xa101,
- [1804] = 0xa101, [1805] = 0xa101, [1825] = 0x0055, [1848] = 0x3fff,
- [1849] = 0x1fff, [2049] = 0x0001, [2050] = 0x0069, [2056] = 0x0002,
- [2057] = 0x0003, [2058] = 0x0069, [12288] = 0x0001, [12289] = 0x0001,
- [12291] = 0x0006, [12292] = 0x0040, [12293] = 0x0001, [12294] = 0x000f,
- [12295] = 0x0006, [12296] = 0x0001, [12297] = 0x0003, [12298] = 0x0104,
- [12300] = 0x0060, [12301] = 0x0011, [12302] = 0x0401, [12304] = 0x0050,
- [12305] = 0x0003, [12306] = 0x0100, [12308] = 0x0051, [12309] = 0x0003,
- [12310] = 0x0104, [12311] = 0x000a, [12312] = 0x0060, [12313] = 0x003b,
- [12314] = 0x0502, [12315] = 0x0100, [12316] = 0x2fff, [12320] = 0x2fff,
- [12324] = 0x2fff, [12328] = 0x2fff, [12332] = 0x2fff, [12336] = 0x2fff,
- [12340] = 0x2fff, [12344] = 0x2fff, [12348] = 0x2fff, [12352] = 0x0001,
- [12353] = 0x0001, [12355] = 0x0006, [12356] = 0x0040, [12357] = 0x0001,
- [12358] = 0x000f, [12359] = 0x0006, [12360] = 0x0001, [12361] = 0x0003,
- [12362] = 0x0104, [12364] = 0x0060, [12365] = 0x0011, [12366] = 0x0401,
- [12368] = 0x0050, [12369] = 0x0003, [12370] = 0x0100, [12372] = 0x0060,
- [12373] = 0x003b, [12374] = 0x0502, [12375] = 0x0100, [12376] = 0x2fff,
- [12380] = 0x2fff, [12384] = 0x2fff, [12388] = 0x2fff, [12392] = 0x2fff,
- [12396] = 0x2fff, [12400] = 0x2fff, [12404] = 0x2fff, [12408] = 0x2fff,
- [12412] = 0x2fff, [12416] = 0x0001, [12417] = 0x0001, [12419] = 0x0006,
- [12420] = 0x0040, [12421] = 0x0001, [12422] = 0x000f, [12423] = 0x0006,
- [12424] = 0x0001, [12425] = 0x0003, [12426] = 0x0106, [12428] = 0x0061,
- [12429] = 0x0011, [12430] = 0x0401, [12432] = 0x0050, [12433] = 0x0003,
- [12434] = 0x0102, [12436] = 0x0051, [12437] = 0x0003, [12438] = 0x0106,
- [12439] = 0x000a, [12440] = 0x0061, [12441] = 0x003b, [12442] = 0x0502,
- [12443] = 0x0100, [12444] = 0x2fff, [12448] = 0x2fff, [12452] = 0x2fff,
- [12456] = 0x2fff, [12460] = 0x2fff, [12464] = 0x2fff, [12468] = 0x2fff,
- [12472] = 0x2fff, [12476] = 0x2fff, [12480] = 0x0001, [12481] = 0x0001,
- [12483] = 0x0006, [12484] = 0x0040, [12485] = 0x0001, [12486] = 0x000f,
- [12487] = 0x0006, [12488] = 0x0001, [12489] = 0x0003, [12490] = 0x0106,
- [12492] = 0x0061, [12493] = 0x0011, [12494] = 0x0401, [12496] = 0x0050,
- [12497] = 0x0003, [12498] = 0x0102, [12500] = 0x0061, [12501] = 0x003b,
- [12502] = 0x0502, [12503] = 0x0100, [12504] = 0x2fff, [12508] = 0x2fff,
- [12512] = 0x2fff, [12516] = 0x2fff, [12520] = 0x2fff, [12524] = 0x2fff,
- [12528] = 0x2fff, [12532] = 0x2fff, [12536] = 0x2fff, [12540] = 0x2fff,
- [12544] = 0x0060, [12546] = 0x0601, [12548] = 0x0050, [12550] = 0x0100,
- [12552] = 0x0001, [12554] = 0x0104, [12555] = 0x0100, [12556] = 0x2fff,
- [12560] = 0x2fff, [12564] = 0x2fff, [12568] = 0x2fff, [12572] = 0x2fff,
- [12576] = 0x2fff, [12580] = 0x2fff, [12584] = 0x2fff, [12588] = 0x2fff,
- [12592] = 0x2fff, [12596] = 0x2fff, [12600] = 0x2fff, [12604] = 0x2fff,
- [12608] = 0x0061, [12610] = 0x0601, [12612] = 0x0050, [12614] = 0x0102,
- [12616] = 0x0001, [12618] = 0x0106, [12619] = 0x0100, [12620] = 0x2fff,
- [12624] = 0x2fff, [12628] = 0x2fff, [12632] = 0x2fff, [12636] = 0x2fff,
- [12640] = 0x2fff, [12644] = 0x2fff, [12648] = 0x2fff, [12652] = 0x2fff,
- [12656] = 0x2fff, [12660] = 0x2fff, [12664] = 0x2fff, [12668] = 0x2fff,
- [12672] = 0x0060, [12674] = 0x0601, [12676] = 0x0061, [12678] = 0x0601,
- [12680] = 0x0050, [12682] = 0x0300, [12684] = 0x0001, [12686] = 0x0304,
- [12688] = 0x0040, [12690] = 0x000f, [12692] = 0x0001, [12695] = 0x0100
+static struct reg_default wm8995_reg_defaults[] = {
+ { 0, 0x8995 },
+ { 5, 0x0100 },
+ { 16, 0x000b },
+ { 17, 0x000b },
+ { 24, 0x02c0 },
+ { 25, 0x02c0 },
+ { 26, 0x02c0 },
+ { 27, 0x02c0 },
+ { 28, 0x000f },
+ { 32, 0x0005 },
+ { 33, 0x0005 },
+ { 40, 0x0003 },
+ { 41, 0x0013 },
+ { 48, 0x0004 },
+ { 56, 0x09f8 },
+ { 64, 0x1f25 },
+ { 69, 0x0004 },
+ { 82, 0xaaaa },
+ { 84, 0x2a2a },
+ { 146, 0x0060 },
+ { 256, 0x0002 },
+ { 257, 0x8004 },
+ { 520, 0x0010 },
+ { 528, 0x0083 },
+ { 529, 0x0083 },
+ { 548, 0x0c80 },
+ { 580, 0x0c80 },
+ { 768, 0x4050 },
+ { 769, 0x4000 },
+ { 771, 0x0040 },
+ { 772, 0x0040 },
+ { 773, 0x0040 },
+ { 774, 0x0004 },
+ { 775, 0x0100 },
+ { 784, 0x4050 },
+ { 785, 0x4000 },
+ { 787, 0x0040 },
+ { 788, 0x0040 },
+ { 789, 0x0040 },
+ { 1024, 0x00c0 },
+ { 1025, 0x00c0 },
+ { 1026, 0x00c0 },
+ { 1027, 0x00c0 },
+ { 1028, 0x00c0 },
+ { 1029, 0x00c0 },
+ { 1030, 0x00c0 },
+ { 1031, 0x00c0 },
+ { 1056, 0x0200 },
+ { 1057, 0x0010 },
+ { 1058, 0x0200 },
+ { 1059, 0x0010 },
+ { 1088, 0x0098 },
+ { 1089, 0x0845 },
+ { 1104, 0x0098 },
+ { 1105, 0x0845 },
+ { 1152, 0x6318 },
+ { 1153, 0x6300 },
+ { 1154, 0x0fca },
+ { 1155, 0x0400 },
+ { 1156, 0x00d8 },
+ { 1157, 0x1eb5 },
+ { 1158, 0xf145 },
+ { 1159, 0x0b75 },
+ { 1160, 0x01c5 },
+ { 1161, 0x1c58 },
+ { 1162, 0xf373 },
+ { 1163, 0x0a54 },
+ { 1164, 0x0558 },
+ { 1165, 0x168e },
+ { 1166, 0xf829 },
+ { 1167, 0x07ad },
+ { 1168, 0x1103 },
+ { 1169, 0x0564 },
+ { 1170, 0x0559 },
+ { 1171, 0x4000 },
+ { 1184, 0x6318 },
+ { 1185, 0x6300 },
+ { 1186, 0x0fca },
+ { 1187, 0x0400 },
+ { 1188, 0x00d8 },
+ { 1189, 0x1eb5 },
+ { 1190, 0xf145 },
+ { 1191, 0x0b75 },
+ { 1192, 0x01c5 },
+ { 1193, 0x1c58 },
+ { 1194, 0xf373 },
+ { 1195, 0x0a54 },
+ { 1196, 0x0558 },
+ { 1197, 0x168e },
+ { 1198, 0xf829 },
+ { 1199, 0x07ad },
+ { 1200, 0x1103 },
+ { 1201, 0x0564 },
+ { 1202, 0x0559 },
+ { 1203, 0x4000 },
+ { 1280, 0x00c0 },
+ { 1281, 0x00c0 },
+ { 1282, 0x00c0 },
+ { 1283, 0x00c0 },
+ { 1312, 0x0200 },
+ { 1313, 0x0010 },
+ { 1344, 0x0098 },
+ { 1345, 0x0845 },
+ { 1408, 0x6318 },
+ { 1409, 0x6300 },
+ { 1410, 0x0fca },
+ { 1411, 0x0400 },
+ { 1412, 0x00d8 },
+ { 1413, 0x1eb5 },
+ { 1414, 0xf145 },
+ { 1415, 0x0b75 },
+ { 1416, 0x01c5 },
+ { 1417, 0x1c58 },
+ { 1418, 0xf373 },
+ { 1419, 0x0a54 },
+ { 1420, 0x0558 },
+ { 1421, 0x168e },
+ { 1422, 0xf829 },
+ { 1423, 0x07ad },
+ { 1424, 0x1103 },
+ { 1425, 0x0564 },
+ { 1426, 0x0559 },
+ { 1427, 0x4000 },
+ { 1568, 0x0002 },
+ { 1792, 0xa100 },
+ { 1793, 0xa101 },
+ { 1794, 0xa101 },
+ { 1795, 0xa101 },
+ { 1796, 0xa101 },
+ { 1797, 0xa101 },
+ { 1798, 0xa101 },
+ { 1799, 0xa101 },
+ { 1800, 0xa101 },
+ { 1801, 0xa101 },
+ { 1802, 0xa101 },
+ { 1803, 0xa101 },
+ { 1804, 0xa101 },
+ { 1805, 0xa101 },
+ { 1825, 0x0055 },
+ { 1848, 0x3fff },
+ { 1849, 0x1fff },
+ { 2049, 0x0001 },
+ { 2050, 0x0069 },
+ { 2056, 0x0002 },
+ { 2057, 0x0003 },
+ { 2058, 0x0069 },
+ { 12288, 0x0001 },
+ { 12289, 0x0001 },
+ { 12291, 0x0006 },
+ { 12292, 0x0040 },
+ { 12293, 0x0001 },
+ { 12294, 0x000f },
+ { 12295, 0x0006 },
+ { 12296, 0x0001 },
+ { 12297, 0x0003 },
+ { 12298, 0x0104 },
+ { 12300, 0x0060 },
+ { 12301, 0x0011 },
+ { 12302, 0x0401 },
+ { 12304, 0x0050 },
+ { 12305, 0x0003 },
+ { 12306, 0x0100 },
+ { 12308, 0x0051 },
+ { 12309, 0x0003 },
+ { 12310, 0x0104 },
+ { 12311, 0x000a },
+ { 12312, 0x0060 },
+ { 12313, 0x003b },
+ { 12314, 0x0502 },
+ { 12315, 0x0100 },
+ { 12316, 0x2fff },
+ { 12320, 0x2fff },
+ { 12324, 0x2fff },
+ { 12328, 0x2fff },
+ { 12332, 0x2fff },
+ { 12336, 0x2fff },
+ { 12340, 0x2fff },
+ { 12344, 0x2fff },
+ { 12348, 0x2fff },
+ { 12352, 0x0001 },
+ { 12353, 0x0001 },
+ { 12355, 0x0006 },
+ { 12356, 0x0040 },
+ { 12357, 0x0001 },
+ { 12358, 0x000f },
+ { 12359, 0x0006 },
+ { 12360, 0x0001 },
+ { 12361, 0x0003 },
+ { 12362, 0x0104 },
+ { 12364, 0x0060 },
+ { 12365, 0x0011 },
+ { 12366, 0x0401 },
+ { 12368, 0x0050 },
+ { 12369, 0x0003 },
+ { 12370, 0x0100 },
+ { 12372, 0x0060 },
+ { 12373, 0x003b },
+ { 12374, 0x0502 },
+ { 12375, 0x0100 },
+ { 12376, 0x2fff },
+ { 12380, 0x2fff },
+ { 12384, 0x2fff },
+ { 12388, 0x2fff },
+ { 12392, 0x2fff },
+ { 12396, 0x2fff },
+ { 12400, 0x2fff },
+ { 12404, 0x2fff },
+ { 12408, 0x2fff },
+ { 12412, 0x2fff },
+ { 12416, 0x0001 },
+ { 12417, 0x0001 },
+ { 12419, 0x0006 },
+ { 12420, 0x0040 },
+ { 12421, 0x0001 },
+ { 12422, 0x000f },
+ { 12423, 0x0006 },
+ { 12424, 0x0001 },
+ { 12425, 0x0003 },
+ { 12426, 0x0106 },
+ { 12428, 0x0061 },
+ { 12429, 0x0011 },
+ { 12430, 0x0401 },
+ { 12432, 0x0050 },
+ { 12433, 0x0003 },
+ { 12434, 0x0102 },
+ { 12436, 0x0051 },
+ { 12437, 0x0003 },
+ { 12438, 0x0106 },
+ { 12439, 0x000a },
+ { 12440, 0x0061 },
+ { 12441, 0x003b },
+ { 12442, 0x0502 },
+ { 12443, 0x0100 },
+ { 12444, 0x2fff },
+ { 12448, 0x2fff },
+ { 12452, 0x2fff },
+ { 12456, 0x2fff },
+ { 12460, 0x2fff },
+ { 12464, 0x2fff },
+ { 12468, 0x2fff },
+ { 12472, 0x2fff },
+ { 12476, 0x2fff },
+ { 12480, 0x0001 },
+ { 12481, 0x0001 },
+ { 12483, 0x0006 },
+ { 12484, 0x0040 },
+ { 12485, 0x0001 },
+ { 12486, 0x000f },
+ { 12487, 0x0006 },
+ { 12488, 0x0001 },
+ { 12489, 0x0003 },
+ { 12490, 0x0106 },
+ { 12492, 0x0061 },
+ { 12493, 0x0011 },
+ { 12494, 0x0401 },
+ { 12496, 0x0050 },
+ { 12497, 0x0003 },
+ { 12498, 0x0102 },
+ { 12500, 0x0061 },
+ { 12501, 0x003b },
+ { 12502, 0x0502 },
+ { 12503, 0x0100 },
+ { 12504, 0x2fff },
+ { 12508, 0x2fff },
+ { 12512, 0x2fff },
+ { 12516, 0x2fff },
+ { 12520, 0x2fff },
+ { 12524, 0x2fff },
+ { 12528, 0x2fff },
+ { 12532, 0x2fff },
+ { 12536, 0x2fff },
+ { 12540, 0x2fff },
+ { 12544, 0x0060 },
+ { 12546, 0x0601 },
+ { 12548, 0x0050 },
+ { 12550, 0x0100 },
+ { 12552, 0x0001 },
+ { 12554, 0x0104 },
+ { 12555, 0x0100 },
+ { 12556, 0x2fff },
+ { 12560, 0x2fff },
+ { 12564, 0x2fff },
+ { 12568, 0x2fff },
+ { 12572, 0x2fff },
+ { 12576, 0x2fff },
+ { 12580, 0x2fff },
+ { 12584, 0x2fff },
+ { 12588, 0x2fff },
+ { 12592, 0x2fff },
+ { 12596, 0x2fff },
+ { 12600, 0x2fff },
+ { 12604, 0x2fff },
+ { 12608, 0x0061 },
+ { 12610, 0x0601 },
+ { 12612, 0x0050 },
+ { 12614, 0x0102 },
+ { 12616, 0x0001 },
+ { 12618, 0x0106 },
+ { 12619, 0x0100 },
+ { 12620, 0x2fff },
+ { 12624, 0x2fff },
+ { 12628, 0x2fff },
+ { 12632, 0x2fff },
+ { 12636, 0x2fff },
+ { 12640, 0x2fff },
+ { 12644, 0x2fff },
+ { 12648, 0x2fff },
+ { 12652, 0x2fff },
+ { 12656, 0x2fff },
+ { 12660, 0x2fff },
+ { 12664, 0x2fff },
+ { 12668, 0x2fff },
+ { 12672, 0x0060 },
+ { 12674, 0x0601 },
+ { 12676, 0x0061 },
+ { 12678, 0x0601 },
+ { 12680, 0x0050 },
+ { 12682, 0x0300 },
+ { 12684, 0x0001 },
+ { 12686, 0x0304 },
+ { 12688, 0x0040 },
+ { 12690, 0x000f },
+ { 12692, 0x0001 },
+ { 12695, 0x0100 },
};
struct fll_config {
@@ -134,7 +378,7 @@ struct fll_config {
};
struct wm8995_priv {
- enum snd_soc_control_type control_type;
+ struct regmap *regmap;
int sysclk[2];
int mclk[2];
int aifclk[2];
@@ -156,7 +400,7 @@ static int wm8995_regulator_event_##n(struct notifier_block *nb, \
struct wm8995_priv *wm8995 = container_of(nb, struct wm8995_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- wm8995->codec->cache_sync = 1; \
+ regcache_mark_dirty(wm8995->regmap); \
} \
return 0; \
}
@@ -485,7 +729,7 @@ static int configure_aif_clock(struct snd_soc_codec *codec, int aif)
static int configure_clock(struct snd_soc_codec *codec)
{
struct wm8995_priv *wm8995;
- int old, new;
+ int change, new;
wm8995 = snd_soc_codec_get_drvdata(codec);
@@ -509,15 +753,11 @@ static int configure_clock(struct snd_soc_codec *codec)
else
new = 0;
- old = snd_soc_read(codec, WM8995_CLOCKING_1) & WM8995_SYSCLK_SRC;
-
- /* If there's no change then we're done. */
- if (old == new)
+ change = snd_soc_update_bits(codec, WM8995_CLOCKING_1,
+ WM8995_SYSCLK_SRC_MASK, new);
+ if (!change)
return 0;
- snd_soc_update_bits(codec, WM8995_CLOCKING_1,
- WM8995_SYSCLK_SRC_MASK, new);
-
snd_soc_dapm_sync(&codec->dapm);
return 0;
@@ -692,8 +932,10 @@ static const struct snd_soc_dapm_widget wm8995_dapm_widgets[] = {
SND_SOC_DAPM_MIXER("IN1R PGA", SND_SOC_NOPM, 0, 0,
&in1r_pga, 1),
- SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8995_POWER_MANAGEMENT_1, 8, 0),
- SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8995_POWER_MANAGEMENT_1, 9, 0),
+ SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8995_POWER_MANAGEMENT_1, 8, 0,
+ NULL, 0),
+ SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8995_POWER_MANAGEMENT_1, 9, 0,
+ NULL, 0),
SND_SOC_DAPM_SUPPLY("AIF1CLK", WM8995_AIF1_CLOCKING_1, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("AIF2CLK", WM8995_AIF2_CLOCKING_1, 0, 0, NULL, 0),
@@ -951,31 +1193,244 @@ static const struct snd_soc_dapm_route wm8995_intercon[] = {
{ "SPK2R", NULL, "SPK2R Driver" }
};
-static int wm8995_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm8995_readable(struct device *dev, unsigned int reg)
{
- /* out of bounds registers are generally considered
- * volatile to support register banks that are partially
- * owned by something else for e.g. a DSP
- */
- if (reg > WM8995_MAX_CACHED_REGISTER)
- return 1;
-
switch (reg) {
case WM8995_SOFTWARE_RESET:
+ case WM8995_POWER_MANAGEMENT_1:
+ case WM8995_POWER_MANAGEMENT_2:
+ case WM8995_POWER_MANAGEMENT_3:
+ case WM8995_POWER_MANAGEMENT_4:
+ case WM8995_POWER_MANAGEMENT_5:
+ case WM8995_LEFT_LINE_INPUT_1_VOLUME:
+ case WM8995_RIGHT_LINE_INPUT_1_VOLUME:
+ case WM8995_LEFT_LINE_INPUT_CONTROL:
+ case WM8995_DAC1_LEFT_VOLUME:
+ case WM8995_DAC1_RIGHT_VOLUME:
+ case WM8995_DAC2_LEFT_VOLUME:
+ case WM8995_DAC2_RIGHT_VOLUME:
+ case WM8995_OUTPUT_VOLUME_ZC_1:
+ case WM8995_MICBIAS_1:
+ case WM8995_MICBIAS_2:
+ case WM8995_LDO_1:
+ case WM8995_LDO_2:
+ case WM8995_ACCESSORY_DETECT_MODE1:
+ case WM8995_ACCESSORY_DETECT_MODE2:
+ case WM8995_HEADPHONE_DETECT1:
+ case WM8995_HEADPHONE_DETECT2:
+ case WM8995_MIC_DETECT_1:
+ case WM8995_MIC_DETECT_2:
+ case WM8995_CHARGE_PUMP_1:
+ case WM8995_CLASS_W_1:
+ case WM8995_DC_SERVO_1:
+ case WM8995_DC_SERVO_2:
+ case WM8995_DC_SERVO_3:
+ case WM8995_DC_SERVO_5:
+ case WM8995_DC_SERVO_6:
+ case WM8995_DC_SERVO_7:
case WM8995_DC_SERVO_READBACK_0:
+ case WM8995_ANALOGUE_HP_1:
+ case WM8995_ANALOGUE_HP_2:
+ case WM8995_CHIP_REVISION:
+ case WM8995_CONTROL_INTERFACE_1:
+ case WM8995_CONTROL_INTERFACE_2:
+ case WM8995_WRITE_SEQUENCER_CTRL_1:
+ case WM8995_WRITE_SEQUENCER_CTRL_2:
+ case WM8995_AIF1_CLOCKING_1:
+ case WM8995_AIF1_CLOCKING_2:
+ case WM8995_AIF2_CLOCKING_1:
+ case WM8995_AIF2_CLOCKING_2:
+ case WM8995_CLOCKING_1:
+ case WM8995_CLOCKING_2:
+ case WM8995_AIF1_RATE:
+ case WM8995_AIF2_RATE:
+ case WM8995_RATE_STATUS:
+ case WM8995_FLL1_CONTROL_1:
+ case WM8995_FLL1_CONTROL_2:
+ case WM8995_FLL1_CONTROL_3:
+ case WM8995_FLL1_CONTROL_4:
+ case WM8995_FLL1_CONTROL_5:
+ case WM8995_FLL2_CONTROL_1:
+ case WM8995_FLL2_CONTROL_2:
+ case WM8995_FLL2_CONTROL_3:
+ case WM8995_FLL2_CONTROL_4:
+ case WM8995_FLL2_CONTROL_5:
+ case WM8995_AIF1_CONTROL_1:
+ case WM8995_AIF1_CONTROL_2:
+ case WM8995_AIF1_MASTER_SLAVE:
+ case WM8995_AIF1_BCLK:
+ case WM8995_AIF1ADC_LRCLK:
+ case WM8995_AIF1DAC_LRCLK:
+ case WM8995_AIF1DAC_DATA:
+ case WM8995_AIF1ADC_DATA:
+ case WM8995_AIF2_CONTROL_1:
+ case WM8995_AIF2_CONTROL_2:
+ case WM8995_AIF2_MASTER_SLAVE:
+ case WM8995_AIF2_BCLK:
+ case WM8995_AIF2ADC_LRCLK:
+ case WM8995_AIF2DAC_LRCLK:
+ case WM8995_AIF2DAC_DATA:
+ case WM8995_AIF2ADC_DATA:
+ case WM8995_AIF1_ADC1_LEFT_VOLUME:
+ case WM8995_AIF1_ADC1_RIGHT_VOLUME:
+ case WM8995_AIF1_DAC1_LEFT_VOLUME:
+ case WM8995_AIF1_DAC1_RIGHT_VOLUME:
+ case WM8995_AIF1_ADC2_LEFT_VOLUME:
+ case WM8995_AIF1_ADC2_RIGHT_VOLUME:
+ case WM8995_AIF1_DAC2_LEFT_VOLUME:
+ case WM8995_AIF1_DAC2_RIGHT_VOLUME:
+ case WM8995_AIF1_ADC1_FILTERS:
+ case WM8995_AIF1_ADC2_FILTERS:
+ case WM8995_AIF1_DAC1_FILTERS_1:
+ case WM8995_AIF1_DAC1_FILTERS_2:
+ case WM8995_AIF1_DAC2_FILTERS_1:
+ case WM8995_AIF1_DAC2_FILTERS_2:
+ case WM8995_AIF1_DRC1_1:
+ case WM8995_AIF1_DRC1_2:
+ case WM8995_AIF1_DRC1_3:
+ case WM8995_AIF1_DRC1_4:
+ case WM8995_AIF1_DRC1_5:
+ case WM8995_AIF1_DRC2_1:
+ case WM8995_AIF1_DRC2_2:
+ case WM8995_AIF1_DRC2_3:
+ case WM8995_AIF1_DRC2_4:
+ case WM8995_AIF1_DRC2_5:
+ case WM8995_AIF1_DAC1_EQ_GAINS_1:
+ case WM8995_AIF1_DAC1_EQ_GAINS_2:
+ case WM8995_AIF1_DAC1_EQ_BAND_1_A:
+ case WM8995_AIF1_DAC1_EQ_BAND_1_B:
+ case WM8995_AIF1_DAC1_EQ_BAND_1_PG:
+ case WM8995_AIF1_DAC1_EQ_BAND_2_A:
+ case WM8995_AIF1_DAC1_EQ_BAND_2_B:
+ case WM8995_AIF1_DAC1_EQ_BAND_2_C:
+ case WM8995_AIF1_DAC1_EQ_BAND_2_PG:
+ case WM8995_AIF1_DAC1_EQ_BAND_3_A:
+ case WM8995_AIF1_DAC1_EQ_BAND_3_B:
+ case WM8995_AIF1_DAC1_EQ_BAND_3_C:
+ case WM8995_AIF1_DAC1_EQ_BAND_3_PG:
+ case WM8995_AIF1_DAC1_EQ_BAND_4_A:
+ case WM8995_AIF1_DAC1_EQ_BAND_4_B:
+ case WM8995_AIF1_DAC1_EQ_BAND_4_C:
+ case WM8995_AIF1_DAC1_EQ_BAND_4_PG:
+ case WM8995_AIF1_DAC1_EQ_BAND_5_A:
+ case WM8995_AIF1_DAC1_EQ_BAND_5_B:
+ case WM8995_AIF1_DAC1_EQ_BAND_5_PG:
+ case WM8995_AIF1_DAC2_EQ_GAINS_1:
+ case WM8995_AIF1_DAC2_EQ_GAINS_2:
+ case WM8995_AIF1_DAC2_EQ_BAND_1_A:
+ case WM8995_AIF1_DAC2_EQ_BAND_1_B:
+ case WM8995_AIF1_DAC2_EQ_BAND_1_PG:
+ case WM8995_AIF1_DAC2_EQ_BAND_2_A:
+ case WM8995_AIF1_DAC2_EQ_BAND_2_B:
+ case WM8995_AIF1_DAC2_EQ_BAND_2_C:
+ case WM8995_AIF1_DAC2_EQ_BAND_2_PG:
+ case WM8995_AIF1_DAC2_EQ_BAND_3_A:
+ case WM8995_AIF1_DAC2_EQ_BAND_3_B:
+ case WM8995_AIF1_DAC2_EQ_BAND_3_C:
+ case WM8995_AIF1_DAC2_EQ_BAND_3_PG:
+ case WM8995_AIF1_DAC2_EQ_BAND_4_A:
+ case WM8995_AIF1_DAC2_EQ_BAND_4_B:
+ case WM8995_AIF1_DAC2_EQ_BAND_4_C:
+ case WM8995_AIF1_DAC2_EQ_BAND_4_PG:
+ case WM8995_AIF1_DAC2_EQ_BAND_5_A:
+ case WM8995_AIF1_DAC2_EQ_BAND_5_B:
+ case WM8995_AIF1_DAC2_EQ_BAND_5_PG:
+ case WM8995_AIF2_ADC_LEFT_VOLUME:
+ case WM8995_AIF2_ADC_RIGHT_VOLUME:
+ case WM8995_AIF2_DAC_LEFT_VOLUME:
+ case WM8995_AIF2_DAC_RIGHT_VOLUME:
+ case WM8995_AIF2_ADC_FILTERS:
+ case WM8995_AIF2_DAC_FILTERS_1:
+ case WM8995_AIF2_DAC_FILTERS_2:
+ case WM8995_AIF2_DRC_1:
+ case WM8995_AIF2_DRC_2:
+ case WM8995_AIF2_DRC_3:
+ case WM8995_AIF2_DRC_4:
+ case WM8995_AIF2_DRC_5:
+ case WM8995_AIF2_EQ_GAINS_1:
+ case WM8995_AIF2_EQ_GAINS_2:
+ case WM8995_AIF2_EQ_BAND_1_A:
+ case WM8995_AIF2_EQ_BAND_1_B:
+ case WM8995_AIF2_EQ_BAND_1_PG:
+ case WM8995_AIF2_EQ_BAND_2_A:
+ case WM8995_AIF2_EQ_BAND_2_B:
+ case WM8995_AIF2_EQ_BAND_2_C:
+ case WM8995_AIF2_EQ_BAND_2_PG:
+ case WM8995_AIF2_EQ_BAND_3_A:
+ case WM8995_AIF2_EQ_BAND_3_B:
+ case WM8995_AIF2_EQ_BAND_3_C:
+ case WM8995_AIF2_EQ_BAND_3_PG:
+ case WM8995_AIF2_EQ_BAND_4_A:
+ case WM8995_AIF2_EQ_BAND_4_B:
+ case WM8995_AIF2_EQ_BAND_4_C:
+ case WM8995_AIF2_EQ_BAND_4_PG:
+ case WM8995_AIF2_EQ_BAND_5_A:
+ case WM8995_AIF2_EQ_BAND_5_B:
+ case WM8995_AIF2_EQ_BAND_5_PG:
+ case WM8995_DAC1_MIXER_VOLUMES:
+ case WM8995_DAC1_LEFT_MIXER_ROUTING:
+ case WM8995_DAC1_RIGHT_MIXER_ROUTING:
+ case WM8995_DAC2_MIXER_VOLUMES:
+ case WM8995_DAC2_LEFT_MIXER_ROUTING:
+ case WM8995_DAC2_RIGHT_MIXER_ROUTING:
+ case WM8995_AIF1_ADC1_LEFT_MIXER_ROUTING:
+ case WM8995_AIF1_ADC1_RIGHT_MIXER_ROUTING:
+ case WM8995_AIF1_ADC2_LEFT_MIXER_ROUTING:
+ case WM8995_AIF1_ADC2_RIGHT_MIXER_ROUTING:
+ case WM8995_DAC_SOFTMUTE:
+ case WM8995_OVERSAMPLING:
+ case WM8995_SIDETONE:
+ case WM8995_GPIO_1:
+ case WM8995_GPIO_2:
+ case WM8995_GPIO_3:
+ case WM8995_GPIO_4:
+ case WM8995_GPIO_5:
+ case WM8995_GPIO_6:
+ case WM8995_GPIO_7:
+ case WM8995_GPIO_8:
+ case WM8995_GPIO_9:
+ case WM8995_GPIO_10:
+ case WM8995_GPIO_11:
+ case WM8995_GPIO_12:
+ case WM8995_GPIO_13:
+ case WM8995_GPIO_14:
+ case WM8995_PULL_CONTROL_1:
+ case WM8995_PULL_CONTROL_2:
case WM8995_INTERRUPT_STATUS_1:
case WM8995_INTERRUPT_STATUS_2:
+ case WM8995_INTERRUPT_RAW_STATUS_2:
case WM8995_INTERRUPT_STATUS_1_MASK:
case WM8995_INTERRUPT_STATUS_2_MASK:
case WM8995_INTERRUPT_CONTROL:
+ case WM8995_LEFT_PDM_SPEAKER_1:
+ case WM8995_RIGHT_PDM_SPEAKER_1:
+ case WM8995_PDM_SPEAKER_1_MUTE_SEQUENCE:
+ case WM8995_LEFT_PDM_SPEAKER_2:
+ case WM8995_RIGHT_PDM_SPEAKER_2:
+ case WM8995_PDM_SPEAKER_2_MUTE_SEQUENCE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm8995_volatile(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8995_SOFTWARE_RESET:
+ case WM8995_DC_SERVO_READBACK_0:
+ case WM8995_INTERRUPT_STATUS_1:
+ case WM8995_INTERRUPT_STATUS_2:
+ case WM8995_INTERRUPT_CONTROL:
case WM8995_ACCESSORY_DETECT_MODE1:
case WM8995_ACCESSORY_DETECT_MODE2:
case WM8995_HEADPHONE_DETECT1:
case WM8995_HEADPHONE_DETECT2:
- return 1;
+ case WM8995_RATE_STATUS:
+ return true;
+ default:
+ return false;
}
-
- return 0;
}
static int wm8995_aif_mute(struct snd_soc_dai *dai, int mute)
@@ -1530,7 +1985,7 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec,
if (ret)
return ret;
- ret = snd_soc_cache_sync(codec);
+ ret = regcache_sync(wm8995->regmap);
if (ret) {
dev_err(codec->dev,
"Failed to sync cache: %d\n", ret);
@@ -1554,7 +2009,7 @@ static int wm8995_set_bias_level(struct snd_soc_codec *codec,
}
#ifdef CONFIG_PM
-static int wm8995_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm8995_suspend(struct snd_soc_codec *codec)
{
wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -1573,11 +2028,16 @@ static int wm8995_resume(struct snd_soc_codec *codec)
static int wm8995_remove(struct snd_soc_codec *codec)
{
struct wm8995_priv *wm8995;
- struct i2c_client *i2c;
+ int i;
- i2c = container_of(codec->dev, struct i2c_client, dev);
wm8995 = snd_soc_codec_get_drvdata(codec);
wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF);
+
+ for (i = 0; i < ARRAY_SIZE(wm8995->supplies); ++i)
+ regulator_unregister_notifier(wm8995->supplies[i].consumer,
+ &wm8995->disable_nb[i]);
+
+ regulator_bulk_free(ARRAY_SIZE(wm8995->supplies), wm8995->supplies);
return 0;
}
@@ -1587,11 +2047,11 @@ static int wm8995_probe(struct snd_soc_codec *codec)
int i;
int ret;
- codec->dapm.idle_bias_off = 1;
wm8995 = snd_soc_codec_get_drvdata(codec);
wm8995->codec = codec;
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, wm8995->control_type);
+ codec->control_data = wm8995->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
if (ret < 0) {
dev_err(codec->dev, "Failed to set cache i/o: %d\n", ret);
return ret;
@@ -1642,6 +2102,7 @@ static int wm8995_probe(struct snd_soc_codec *codec)
if (ret != 0x8995) {
dev_err(codec->dev, "Invalid device ID: %#x\n", ret);
+ ret = -EINVAL;
goto err_reg_enable;
}
@@ -1675,7 +2136,7 @@ static int wm8995_probe(struct snd_soc_codec *codec)
wm8995_update_class_w(codec);
- snd_soc_add_controls(codec, wm8995_snd_controls,
+ snd_soc_add_codec_controls(codec, wm8995_snd_controls,
ARRAY_SIZE(wm8995_snd_controls));
snd_soc_dapm_new_controls(&codec->dapm, wm8995_dapm_widgets,
ARRAY_SIZE(wm8995_dapm_widgets));
@@ -1694,7 +2155,7 @@ err_reg_get:
#define WM8995_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8995_aif1_dai_ops = {
+static const struct snd_soc_dai_ops wm8995_aif1_dai_ops = {
.set_sysclk = wm8995_set_dai_sysclk,
.set_fmt = wm8995_set_dai_fmt,
.hw_params = wm8995_hw_params,
@@ -1703,7 +2164,7 @@ static struct snd_soc_dai_ops wm8995_aif1_dai_ops = {
.set_tristate = wm8995_set_tristate,
};
-static struct snd_soc_dai_ops wm8995_aif2_dai_ops = {
+static const struct snd_soc_dai_ops wm8995_aif2_dai_ops = {
.set_sysclk = wm8995_set_dai_sysclk,
.set_fmt = wm8995_set_dai_fmt,
.hw_params = wm8995_hw_params,
@@ -1712,7 +2173,7 @@ static struct snd_soc_dai_ops wm8995_aif2_dai_ops = {
.set_tristate = wm8995_set_tristate,
};
-static struct snd_soc_dai_ops wm8995_aif3_dai_ops = {
+static const struct snd_soc_dai_ops wm8995_aif3_dai_ops = {
.set_tristate = wm8995_set_tristate,
};
@@ -1779,11 +2240,19 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8995 = {
.suspend = wm8995_suspend,
.resume = wm8995_resume,
.set_bias_level = wm8995_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm8995_reg_defs),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8995_reg_defs,
- .volatile_register = wm8995_volatile,
- .compress_type = SND_SOC_RBTREE_COMPRESSION
+ .idle_bias_off = true,
+};
+
+static struct regmap_config wm8995_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .max_register = WM8995_MAX_REGISTER,
+ .reg_defaults = wm8995_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8995_reg_defaults),
+ .volatile_reg = wm8995_volatile,
+ .readable_reg = wm8995_readable,
+ .cache_type = REGCACHE_RBTREE,
};
#if defined(CONFIG_SPI_MASTER)
@@ -1796,21 +2265,37 @@ static int __devinit wm8995_spi_probe(struct spi_device *spi)
if (!wm8995)
return -ENOMEM;
- wm8995->control_type = SND_SOC_SPI;
spi_set_drvdata(spi, wm8995);
+ wm8995->regmap = regmap_init_spi(spi, &wm8995_regmap);
+ if (IS_ERR(wm8995->regmap)) {
+ ret = PTR_ERR(wm8995->regmap);
+ dev_err(&spi->dev, "Failed to register regmap: %d\n", ret);
+ goto err_alloc;
+ }
+
ret = snd_soc_register_codec(&spi->dev,
&soc_codec_dev_wm8995, wm8995_dai,
ARRAY_SIZE(wm8995_dai));
if (ret < 0)
- kfree(wm8995);
+ goto err_regmap;
+
+ return ret;
+
+err_regmap:
+ regmap_exit(wm8995->regmap);
+err_alloc:
+ kfree(wm8995);
+
return ret;
}
static int __devexit wm8995_spi_remove(struct spi_device *spi)
{
+ struct wm8995_priv *wm8995 = spi_get_drvdata(spi);
snd_soc_unregister_codec(&spi->dev);
- kfree(spi_get_drvdata(spi));
+ regmap_exit(wm8995->regmap);
+ kfree(wm8995);
return 0;
}
@@ -1835,21 +2320,40 @@ static __devinit int wm8995_i2c_probe(struct i2c_client *i2c,
if (!wm8995)
return -ENOMEM;
- wm8995->control_type = SND_SOC_I2C;
i2c_set_clientdata(i2c, wm8995);
+ wm8995->regmap = regmap_init_i2c(i2c, &wm8995_regmap);
+ if (IS_ERR(wm8995->regmap)) {
+ ret = PTR_ERR(wm8995->regmap);
+ dev_err(&i2c->dev, "Failed to register regmap: %d\n", ret);
+ goto err_alloc;
+ }
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8995, wm8995_dai,
ARRAY_SIZE(wm8995_dai));
- if (ret < 0)
- kfree(wm8995);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err_regmap;
+ }
+
+ return ret;
+
+err_regmap:
+ regmap_exit(wm8995->regmap);
+err_alloc:
+ kfree(wm8995);
+
return ret;
}
static __devexit int wm8995_i2c_remove(struct i2c_client *client)
{
+ struct wm8995_priv *wm8995 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm8995->regmap);
+ kfree(wm8995);
return 0;
}
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c
index 0cdb9d105671..1fd635494045 100644
--- a/sound/soc/codecs/wm8996.c
+++ b/sound/soc/codecs/wm8996.c
@@ -19,6 +19,7 @@
#include <linux/gcd.h>
#include <linux/gpio.h>
#include <linux/i2c.h>
+#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
@@ -41,15 +42,16 @@
#define HPOUT2L 4
#define HPOUT2R 8
-#define WM8996_NUM_SUPPLIES 4
+#define WM8996_NUM_SUPPLIES 3
static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = {
"DBVDD",
"AVDD1",
"AVDD2",
- "CPVDD",
};
struct wm8996_priv {
+ struct device *dev;
+ struct regmap *regmap;
struct snd_soc_codec *codec;
int ldo1ena;
@@ -71,6 +73,7 @@ struct wm8996_priv {
struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES];
struct notifier_block disable_nb[WM8996_NUM_SUPPLIES];
+ int bg_ena;
struct wm8996_pdata pdata;
@@ -86,6 +89,7 @@ struct wm8996_priv {
struct snd_soc_jack *jack;
bool detecting;
bool jack_mic;
+ int jack_flips;
wm8996_polarity_fn polarity_cb;
#ifdef CONFIG_GPIOLIB
@@ -104,7 +108,7 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \
struct wm8996_priv *wm8996 = container_of(nb, struct wm8996_priv, \
disable_nb[n]); \
if (event & REGULATOR_EVENT_DISABLE) { \
- wm8996->codec->cache_sync = 1; \
+ regcache_mark_dirty(wm8996->regmap); \
} \
return 0; \
}
@@ -112,299 +116,364 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \
WM8996_REGULATOR_EVENT(0)
WM8996_REGULATOR_EVENT(1)
WM8996_REGULATOR_EVENT(2)
-WM8996_REGULATOR_EVENT(3)
-
-static const u16 wm8996_reg[WM8996_MAX_REGISTER] = {
- [WM8996_SOFTWARE_RESET] = 0x8996,
- [WM8996_POWER_MANAGEMENT_7] = 0x10,
- [WM8996_DAC1_HPOUT1_VOLUME] = 0x88,
- [WM8996_DAC2_HPOUT2_VOLUME] = 0x88,
- [WM8996_DAC1_LEFT_VOLUME] = 0x2c0,
- [WM8996_DAC1_RIGHT_VOLUME] = 0x2c0,
- [WM8996_DAC2_LEFT_VOLUME] = 0x2c0,
- [WM8996_DAC2_RIGHT_VOLUME] = 0x2c0,
- [WM8996_OUTPUT1_LEFT_VOLUME] = 0x80,
- [WM8996_OUTPUT1_RIGHT_VOLUME] = 0x80,
- [WM8996_OUTPUT2_LEFT_VOLUME] = 0x80,
- [WM8996_OUTPUT2_RIGHT_VOLUME] = 0x80,
- [WM8996_MICBIAS_1] = 0x39,
- [WM8996_MICBIAS_2] = 0x39,
- [WM8996_LDO_1] = 0x3,
- [WM8996_LDO_2] = 0x13,
- [WM8996_ACCESSORY_DETECT_MODE_1] = 0x4,
- [WM8996_HEADPHONE_DETECT_1] = 0x20,
- [WM8996_MIC_DETECT_1] = 0x7600,
- [WM8996_MIC_DETECT_2] = 0xbf,
- [WM8996_CHARGE_PUMP_1] = 0x1f25,
- [WM8996_CHARGE_PUMP_2] = 0xab19,
- [WM8996_DC_SERVO_5] = 0x2a2a,
- [WM8996_CONTROL_INTERFACE_1] = 0x8004,
- [WM8996_CLOCKING_1] = 0x10,
- [WM8996_AIF_RATE] = 0x83,
- [WM8996_FLL_CONTROL_4] = 0x5dc0,
- [WM8996_FLL_CONTROL_5] = 0xc84,
- [WM8996_FLL_EFS_2] = 0x2,
- [WM8996_AIF1_TX_LRCLK_1] = 0x80,
- [WM8996_AIF1_TX_LRCLK_2] = 0x8,
- [WM8996_AIF1_RX_LRCLK_1] = 0x80,
- [WM8996_AIF1TX_DATA_CONFIGURATION_1] = 0x1818,
- [WM8996_AIF1RX_DATA_CONFIGURATION] = 0x1818,
- [WM8996_AIF1TX_TEST] = 0x7,
- [WM8996_AIF2_TX_LRCLK_1] = 0x80,
- [WM8996_AIF2_TX_LRCLK_2] = 0x8,
- [WM8996_AIF2_RX_LRCLK_1] = 0x80,
- [WM8996_AIF2TX_DATA_CONFIGURATION_1] = 0x1818,
- [WM8996_AIF2RX_DATA_CONFIGURATION] = 0x1818,
- [WM8996_AIF2TX_TEST] = 0x1,
- [WM8996_DSP1_TX_LEFT_VOLUME] = 0xc0,
- [WM8996_DSP1_TX_RIGHT_VOLUME] = 0xc0,
- [WM8996_DSP1_RX_LEFT_VOLUME] = 0xc0,
- [WM8996_DSP1_RX_RIGHT_VOLUME] = 0xc0,
- [WM8996_DSP1_TX_FILTERS] = 0x2000,
- [WM8996_DSP1_RX_FILTERS_1] = 0x200,
- [WM8996_DSP1_RX_FILTERS_2] = 0x10,
- [WM8996_DSP1_DRC_1] = 0x98,
- [WM8996_DSP1_DRC_2] = 0x845,
- [WM8996_DSP1_RX_EQ_GAINS_1] = 0x6318,
- [WM8996_DSP1_RX_EQ_GAINS_2] = 0x6300,
- [WM8996_DSP1_RX_EQ_BAND_1_A] = 0xfca,
- [WM8996_DSP1_RX_EQ_BAND_1_B] = 0x400,
- [WM8996_DSP1_RX_EQ_BAND_1_PG] = 0xd8,
- [WM8996_DSP1_RX_EQ_BAND_2_A] = 0x1eb5,
- [WM8996_DSP1_RX_EQ_BAND_2_B] = 0xf145,
- [WM8996_DSP1_RX_EQ_BAND_2_C] = 0xb75,
- [WM8996_DSP1_RX_EQ_BAND_2_PG] = 0x1c5,
- [WM8996_DSP1_RX_EQ_BAND_3_A] = 0x1c58,
- [WM8996_DSP1_RX_EQ_BAND_3_B] = 0xf373,
- [WM8996_DSP1_RX_EQ_BAND_3_C] = 0xa54,
- [WM8996_DSP1_RX_EQ_BAND_3_PG] = 0x558,
- [WM8996_DSP1_RX_EQ_BAND_4_A] = 0x168e,
- [WM8996_DSP1_RX_EQ_BAND_4_B] = 0xf829,
- [WM8996_DSP1_RX_EQ_BAND_4_C] = 0x7ad,
- [WM8996_DSP1_RX_EQ_BAND_4_PG] = 0x1103,
- [WM8996_DSP1_RX_EQ_BAND_5_A] = 0x564,
- [WM8996_DSP1_RX_EQ_BAND_5_B] = 0x559,
- [WM8996_DSP1_RX_EQ_BAND_5_PG] = 0x4000,
- [WM8996_DSP2_TX_LEFT_VOLUME] = 0xc0,
- [WM8996_DSP2_TX_RIGHT_VOLUME] = 0xc0,
- [WM8996_DSP2_RX_LEFT_VOLUME] = 0xc0,
- [WM8996_DSP2_RX_RIGHT_VOLUME] = 0xc0,
- [WM8996_DSP2_TX_FILTERS] = 0x2000,
- [WM8996_DSP2_RX_FILTERS_1] = 0x200,
- [WM8996_DSP2_RX_FILTERS_2] = 0x10,
- [WM8996_DSP2_DRC_1] = 0x98,
- [WM8996_DSP2_DRC_2] = 0x845,
- [WM8996_DSP2_RX_EQ_GAINS_1] = 0x6318,
- [WM8996_DSP2_RX_EQ_GAINS_2] = 0x6300,
- [WM8996_DSP2_RX_EQ_BAND_1_A] = 0xfca,
- [WM8996_DSP2_RX_EQ_BAND_1_B] = 0x400,
- [WM8996_DSP2_RX_EQ_BAND_1_PG] = 0xd8,
- [WM8996_DSP2_RX_EQ_BAND_2_A] = 0x1eb5,
- [WM8996_DSP2_RX_EQ_BAND_2_B] = 0xf145,
- [WM8996_DSP2_RX_EQ_BAND_2_C] = 0xb75,
- [WM8996_DSP2_RX_EQ_BAND_2_PG] = 0x1c5,
- [WM8996_DSP2_RX_EQ_BAND_3_A] = 0x1c58,
- [WM8996_DSP2_RX_EQ_BAND_3_B] = 0xf373,
- [WM8996_DSP2_RX_EQ_BAND_3_C] = 0xa54,
- [WM8996_DSP2_RX_EQ_BAND_3_PG] = 0x558,
- [WM8996_DSP2_RX_EQ_BAND_4_A] = 0x168e,
- [WM8996_DSP2_RX_EQ_BAND_4_B] = 0xf829,
- [WM8996_DSP2_RX_EQ_BAND_4_C] = 0x7ad,
- [WM8996_DSP2_RX_EQ_BAND_4_PG] = 0x1103,
- [WM8996_DSP2_RX_EQ_BAND_5_A] = 0x564,
- [WM8996_DSP2_RX_EQ_BAND_5_B] = 0x559,
- [WM8996_DSP2_RX_EQ_BAND_5_PG] = 0x4000,
- [WM8996_OVERSAMPLING] = 0xd,
- [WM8996_SIDETONE] = 0x1040,
- [WM8996_GPIO_1] = 0xa101,
- [WM8996_GPIO_2] = 0xa101,
- [WM8996_GPIO_3] = 0xa101,
- [WM8996_GPIO_4] = 0xa101,
- [WM8996_GPIO_5] = 0xa101,
- [WM8996_PULL_CONTROL_2] = 0x140,
- [WM8996_INTERRUPT_STATUS_1_MASK] = 0x1f,
- [WM8996_INTERRUPT_STATUS_2_MASK] = 0x1ecf,
- [WM8996_RIGHT_PDM_SPEAKER] = 0x1,
- [WM8996_PDM_SPEAKER_MUTE_SEQUENCE] = 0x69,
- [WM8996_PDM_SPEAKER_VOLUME] = 0x66,
- [WM8996_WRITE_SEQUENCER_0] = 0x1,
- [WM8996_WRITE_SEQUENCER_1] = 0x1,
- [WM8996_WRITE_SEQUENCER_3] = 0x6,
- [WM8996_WRITE_SEQUENCER_4] = 0x40,
- [WM8996_WRITE_SEQUENCER_5] = 0x1,
- [WM8996_WRITE_SEQUENCER_6] = 0xf,
- [WM8996_WRITE_SEQUENCER_7] = 0x6,
- [WM8996_WRITE_SEQUENCER_8] = 0x1,
- [WM8996_WRITE_SEQUENCER_9] = 0x3,
- [WM8996_WRITE_SEQUENCER_10] = 0x104,
- [WM8996_WRITE_SEQUENCER_12] = 0x60,
- [WM8996_WRITE_SEQUENCER_13] = 0x11,
- [WM8996_WRITE_SEQUENCER_14] = 0x401,
- [WM8996_WRITE_SEQUENCER_16] = 0x50,
- [WM8996_WRITE_SEQUENCER_17] = 0x3,
- [WM8996_WRITE_SEQUENCER_18] = 0x100,
- [WM8996_WRITE_SEQUENCER_20] = 0x51,
- [WM8996_WRITE_SEQUENCER_21] = 0x3,
- [WM8996_WRITE_SEQUENCER_22] = 0x104,
- [WM8996_WRITE_SEQUENCER_23] = 0xa,
- [WM8996_WRITE_SEQUENCER_24] = 0x60,
- [WM8996_WRITE_SEQUENCER_25] = 0x3b,
- [WM8996_WRITE_SEQUENCER_26] = 0x502,
- [WM8996_WRITE_SEQUENCER_27] = 0x100,
- [WM8996_WRITE_SEQUENCER_28] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_32] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_36] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_40] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_44] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_48] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_52] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_56] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_60] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_64] = 0x1,
- [WM8996_WRITE_SEQUENCER_65] = 0x1,
- [WM8996_WRITE_SEQUENCER_67] = 0x6,
- [WM8996_WRITE_SEQUENCER_68] = 0x40,
- [WM8996_WRITE_SEQUENCER_69] = 0x1,
- [WM8996_WRITE_SEQUENCER_70] = 0xf,
- [WM8996_WRITE_SEQUENCER_71] = 0x6,
- [WM8996_WRITE_SEQUENCER_72] = 0x1,
- [WM8996_WRITE_SEQUENCER_73] = 0x3,
- [WM8996_WRITE_SEQUENCER_74] = 0x104,
- [WM8996_WRITE_SEQUENCER_76] = 0x60,
- [WM8996_WRITE_SEQUENCER_77] = 0x11,
- [WM8996_WRITE_SEQUENCER_78] = 0x401,
- [WM8996_WRITE_SEQUENCER_80] = 0x50,
- [WM8996_WRITE_SEQUENCER_81] = 0x3,
- [WM8996_WRITE_SEQUENCER_82] = 0x100,
- [WM8996_WRITE_SEQUENCER_84] = 0x60,
- [WM8996_WRITE_SEQUENCER_85] = 0x3b,
- [WM8996_WRITE_SEQUENCER_86] = 0x502,
- [WM8996_WRITE_SEQUENCER_87] = 0x100,
- [WM8996_WRITE_SEQUENCER_88] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_92] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_96] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_100] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_104] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_108] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_112] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_116] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_120] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_124] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_128] = 0x1,
- [WM8996_WRITE_SEQUENCER_129] = 0x1,
- [WM8996_WRITE_SEQUENCER_131] = 0x6,
- [WM8996_WRITE_SEQUENCER_132] = 0x40,
- [WM8996_WRITE_SEQUENCER_133] = 0x1,
- [WM8996_WRITE_SEQUENCER_134] = 0xf,
- [WM8996_WRITE_SEQUENCER_135] = 0x6,
- [WM8996_WRITE_SEQUENCER_136] = 0x1,
- [WM8996_WRITE_SEQUENCER_137] = 0x3,
- [WM8996_WRITE_SEQUENCER_138] = 0x106,
- [WM8996_WRITE_SEQUENCER_140] = 0x61,
- [WM8996_WRITE_SEQUENCER_141] = 0x11,
- [WM8996_WRITE_SEQUENCER_142] = 0x401,
- [WM8996_WRITE_SEQUENCER_144] = 0x50,
- [WM8996_WRITE_SEQUENCER_145] = 0x3,
- [WM8996_WRITE_SEQUENCER_146] = 0x102,
- [WM8996_WRITE_SEQUENCER_148] = 0x51,
- [WM8996_WRITE_SEQUENCER_149] = 0x3,
- [WM8996_WRITE_SEQUENCER_150] = 0x106,
- [WM8996_WRITE_SEQUENCER_151] = 0xa,
- [WM8996_WRITE_SEQUENCER_152] = 0x61,
- [WM8996_WRITE_SEQUENCER_153] = 0x3b,
- [WM8996_WRITE_SEQUENCER_154] = 0x502,
- [WM8996_WRITE_SEQUENCER_155] = 0x100,
- [WM8996_WRITE_SEQUENCER_156] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_160] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_164] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_168] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_172] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_176] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_180] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_184] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_188] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_192] = 0x1,
- [WM8996_WRITE_SEQUENCER_193] = 0x1,
- [WM8996_WRITE_SEQUENCER_195] = 0x6,
- [WM8996_WRITE_SEQUENCER_196] = 0x40,
- [WM8996_WRITE_SEQUENCER_197] = 0x1,
- [WM8996_WRITE_SEQUENCER_198] = 0xf,
- [WM8996_WRITE_SEQUENCER_199] = 0x6,
- [WM8996_WRITE_SEQUENCER_200] = 0x1,
- [WM8996_WRITE_SEQUENCER_201] = 0x3,
- [WM8996_WRITE_SEQUENCER_202] = 0x106,
- [WM8996_WRITE_SEQUENCER_204] = 0x61,
- [WM8996_WRITE_SEQUENCER_205] = 0x11,
- [WM8996_WRITE_SEQUENCER_206] = 0x401,
- [WM8996_WRITE_SEQUENCER_208] = 0x50,
- [WM8996_WRITE_SEQUENCER_209] = 0x3,
- [WM8996_WRITE_SEQUENCER_210] = 0x102,
- [WM8996_WRITE_SEQUENCER_212] = 0x61,
- [WM8996_WRITE_SEQUENCER_213] = 0x3b,
- [WM8996_WRITE_SEQUENCER_214] = 0x502,
- [WM8996_WRITE_SEQUENCER_215] = 0x100,
- [WM8996_WRITE_SEQUENCER_216] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_220] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_224] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_228] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_232] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_236] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_240] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_244] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_248] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_252] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_256] = 0x60,
- [WM8996_WRITE_SEQUENCER_258] = 0x601,
- [WM8996_WRITE_SEQUENCER_260] = 0x50,
- [WM8996_WRITE_SEQUENCER_262] = 0x100,
- [WM8996_WRITE_SEQUENCER_264] = 0x1,
- [WM8996_WRITE_SEQUENCER_266] = 0x104,
- [WM8996_WRITE_SEQUENCER_267] = 0x100,
- [WM8996_WRITE_SEQUENCER_268] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_272] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_276] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_280] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_284] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_288] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_292] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_296] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_300] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_304] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_308] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_312] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_316] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_320] = 0x61,
- [WM8996_WRITE_SEQUENCER_322] = 0x601,
- [WM8996_WRITE_SEQUENCER_324] = 0x50,
- [WM8996_WRITE_SEQUENCER_326] = 0x102,
- [WM8996_WRITE_SEQUENCER_328] = 0x1,
- [WM8996_WRITE_SEQUENCER_330] = 0x106,
- [WM8996_WRITE_SEQUENCER_331] = 0x100,
- [WM8996_WRITE_SEQUENCER_332] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_336] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_340] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_344] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_348] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_352] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_356] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_360] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_364] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_368] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_372] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_376] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_380] = 0x2fff,
- [WM8996_WRITE_SEQUENCER_384] = 0x60,
- [WM8996_WRITE_SEQUENCER_386] = 0x601,
- [WM8996_WRITE_SEQUENCER_388] = 0x61,
- [WM8996_WRITE_SEQUENCER_390] = 0x601,
- [WM8996_WRITE_SEQUENCER_392] = 0x50,
- [WM8996_WRITE_SEQUENCER_394] = 0x300,
- [WM8996_WRITE_SEQUENCER_396] = 0x1,
- [WM8996_WRITE_SEQUENCER_398] = 0x304,
- [WM8996_WRITE_SEQUENCER_400] = 0x40,
- [WM8996_WRITE_SEQUENCER_402] = 0xf,
- [WM8996_WRITE_SEQUENCER_404] = 0x1,
- [WM8996_WRITE_SEQUENCER_407] = 0x100,
+
+static struct reg_default wm8996_reg[] = {
+ { WM8996_POWER_MANAGEMENT_1, 0x0 },
+ { WM8996_POWER_MANAGEMENT_2, 0x0 },
+ { WM8996_POWER_MANAGEMENT_3, 0x0 },
+ { WM8996_POWER_MANAGEMENT_4, 0x0 },
+ { WM8996_POWER_MANAGEMENT_5, 0x0 },
+ { WM8996_POWER_MANAGEMENT_6, 0x0 },
+ { WM8996_POWER_MANAGEMENT_7, 0x10 },
+ { WM8996_POWER_MANAGEMENT_8, 0x0 },
+ { WM8996_LEFT_LINE_INPUT_VOLUME, 0x0 },
+ { WM8996_RIGHT_LINE_INPUT_VOLUME, 0x0 },
+ { WM8996_LINE_INPUT_CONTROL, 0x0 },
+ { WM8996_DAC1_HPOUT1_VOLUME, 0x88 },
+ { WM8996_DAC2_HPOUT2_VOLUME, 0x88 },
+ { WM8996_DAC1_LEFT_VOLUME, 0x2c0 },
+ { WM8996_DAC1_RIGHT_VOLUME, 0x2c0 },
+ { WM8996_DAC2_LEFT_VOLUME, 0x2c0 },
+ { WM8996_DAC2_RIGHT_VOLUME, 0x2c0 },
+ { WM8996_OUTPUT1_LEFT_VOLUME, 0x80 },
+ { WM8996_OUTPUT1_RIGHT_VOLUME, 0x80 },
+ { WM8996_OUTPUT2_LEFT_VOLUME, 0x80 },
+ { WM8996_OUTPUT2_RIGHT_VOLUME, 0x80 },
+ { WM8996_MICBIAS_1, 0x39 },
+ { WM8996_MICBIAS_2, 0x39 },
+ { WM8996_LDO_1, 0x3 },
+ { WM8996_LDO_2, 0x13 },
+ { WM8996_ACCESSORY_DETECT_MODE_1, 0x4 },
+ { WM8996_ACCESSORY_DETECT_MODE_2, 0x0 },
+ { WM8996_HEADPHONE_DETECT_1, 0x20 },
+ { WM8996_HEADPHONE_DETECT_2, 0x0 },
+ { WM8996_MIC_DETECT_1, 0x7600 },
+ { WM8996_MIC_DETECT_2, 0xbf },
+ { WM8996_CHARGE_PUMP_1, 0x1f25 },
+ { WM8996_CHARGE_PUMP_2, 0xab19 },
+ { WM8996_DC_SERVO_1, 0x0 },
+ { WM8996_DC_SERVO_3, 0x0 },
+ { WM8996_DC_SERVO_5, 0x2a2a },
+ { WM8996_DC_SERVO_6, 0x0 },
+ { WM8996_DC_SERVO_7, 0x0 },
+ { WM8996_ANALOGUE_HP_1, 0x0 },
+ { WM8996_ANALOGUE_HP_2, 0x0 },
+ { WM8996_CONTROL_INTERFACE_1, 0x8004 },
+ { WM8996_WRITE_SEQUENCER_CTRL_1, 0x0 },
+ { WM8996_WRITE_SEQUENCER_CTRL_2, 0x0 },
+ { WM8996_AIF_CLOCKING_1, 0x0 },
+ { WM8996_AIF_CLOCKING_2, 0x0 },
+ { WM8996_CLOCKING_1, 0x10 },
+ { WM8996_CLOCKING_2, 0x0 },
+ { WM8996_AIF_RATE, 0x83 },
+ { WM8996_FLL_CONTROL_1, 0x0 },
+ { WM8996_FLL_CONTROL_2, 0x0 },
+ { WM8996_FLL_CONTROL_3, 0x0 },
+ { WM8996_FLL_CONTROL_4, 0x5dc0 },
+ { WM8996_FLL_CONTROL_5, 0xc84 },
+ { WM8996_FLL_EFS_1, 0x0 },
+ { WM8996_FLL_EFS_2, 0x2 },
+ { WM8996_AIF1_CONTROL, 0x0 },
+ { WM8996_AIF1_BCLK, 0x0 },
+ { WM8996_AIF1_TX_LRCLK_1, 0x80 },
+ { WM8996_AIF1_TX_LRCLK_2, 0x8 },
+ { WM8996_AIF1_RX_LRCLK_1, 0x80 },
+ { WM8996_AIF1_RX_LRCLK_2, 0x0 },
+ { WM8996_AIF1TX_DATA_CONFIGURATION_1, 0x1818 },
+ { WM8996_AIF1TX_DATA_CONFIGURATION_2, 0 },
+ { WM8996_AIF1RX_DATA_CONFIGURATION, 0x1818 },
+ { WM8996_AIF1TX_CHANNEL_0_CONFIGURATION, 0x0 },
+ { WM8996_AIF1TX_CHANNEL_1_CONFIGURATION, 0x0 },
+ { WM8996_AIF1TX_CHANNEL_2_CONFIGURATION, 0x0 },
+ { WM8996_AIF1TX_CHANNEL_3_CONFIGURATION, 0x0 },
+ { WM8996_AIF1TX_CHANNEL_4_CONFIGURATION, 0x0 },
+ { WM8996_AIF1TX_CHANNEL_5_CONFIGURATION, 0x0 },
+ { WM8996_AIF1RX_CHANNEL_0_CONFIGURATION, 0x0 },
+ { WM8996_AIF1RX_CHANNEL_1_CONFIGURATION, 0x0 },
+ { WM8996_AIF1RX_CHANNEL_2_CONFIGURATION, 0x0 },
+ { WM8996_AIF1RX_CHANNEL_3_CONFIGURATION, 0x0 },
+ { WM8996_AIF1RX_CHANNEL_4_CONFIGURATION, 0x0 },
+ { WM8996_AIF1RX_CHANNEL_5_CONFIGURATION, 0x0 },
+ { WM8996_AIF1RX_MONO_CONFIGURATION, 0x0 },
+ { WM8996_AIF1TX_TEST, 0x7 },
+ { WM8996_AIF2_CONTROL, 0x0 },
+ { WM8996_AIF2_BCLK, 0x0 },
+ { WM8996_AIF2_TX_LRCLK_1, 0x80 },
+ { WM8996_AIF2_TX_LRCLK_2, 0x8 },
+ { WM8996_AIF2_RX_LRCLK_1, 0x80 },
+ { WM8996_AIF2_RX_LRCLK_2, 0x0 },
+ { WM8996_AIF2TX_DATA_CONFIGURATION_1, 0x1818 },
+ { WM8996_AIF2RX_DATA_CONFIGURATION, 0x1818 },
+ { WM8996_AIF2RX_DATA_CONFIGURATION, 0x0 },
+ { WM8996_AIF2TX_CHANNEL_0_CONFIGURATION, 0x0 },
+ { WM8996_AIF2TX_CHANNEL_1_CONFIGURATION, 0x0 },
+ { WM8996_AIF2RX_CHANNEL_0_CONFIGURATION, 0x0 },
+ { WM8996_AIF2RX_CHANNEL_1_CONFIGURATION, 0x0 },
+ { WM8996_AIF2RX_MONO_CONFIGURATION, 0x0 },
+ { WM8996_AIF2TX_TEST, 0x1 },
+ { WM8996_DSP1_TX_LEFT_VOLUME, 0xc0 },
+ { WM8996_DSP1_TX_RIGHT_VOLUME, 0xc0 },
+ { WM8996_DSP1_RX_LEFT_VOLUME, 0xc0 },
+ { WM8996_DSP1_RX_RIGHT_VOLUME, 0xc0 },
+ { WM8996_DSP1_TX_FILTERS, 0x2000 },
+ { WM8996_DSP1_RX_FILTERS_1, 0x200 },
+ { WM8996_DSP1_RX_FILTERS_2, 0x10 },
+ { WM8996_DSP1_DRC_1, 0x98 },
+ { WM8996_DSP1_DRC_2, 0x845 },
+ { WM8996_DSP1_RX_EQ_GAINS_1, 0x6318 },
+ { WM8996_DSP1_RX_EQ_GAINS_2, 0x6300 },
+ { WM8996_DSP1_RX_EQ_BAND_1_A, 0xfca },
+ { WM8996_DSP1_RX_EQ_BAND_1_B, 0x400 },
+ { WM8996_DSP1_RX_EQ_BAND_1_PG, 0xd8 },
+ { WM8996_DSP1_RX_EQ_BAND_2_A, 0x1eb5 },
+ { WM8996_DSP1_RX_EQ_BAND_2_B, 0xf145 },
+ { WM8996_DSP1_RX_EQ_BAND_2_C, 0xb75 },
+ { WM8996_DSP1_RX_EQ_BAND_2_PG, 0x1c5 },
+ { WM8996_DSP1_RX_EQ_BAND_3_A, 0x1c58 },
+ { WM8996_DSP1_RX_EQ_BAND_3_B, 0xf373 },
+ { WM8996_DSP1_RX_EQ_BAND_3_C, 0xa54 },
+ { WM8996_DSP1_RX_EQ_BAND_3_PG, 0x558 },
+ { WM8996_DSP1_RX_EQ_BAND_4_A, 0x168e },
+ { WM8996_DSP1_RX_EQ_BAND_4_B, 0xf829 },
+ { WM8996_DSP1_RX_EQ_BAND_4_C, 0x7ad },
+ { WM8996_DSP1_RX_EQ_BAND_4_PG, 0x1103 },
+ { WM8996_DSP1_RX_EQ_BAND_5_A, 0x564 },
+ { WM8996_DSP1_RX_EQ_BAND_5_B, 0x559 },
+ { WM8996_DSP1_RX_EQ_BAND_5_PG, 0x4000 },
+ { WM8996_DSP2_TX_LEFT_VOLUME, 0xc0 },
+ { WM8996_DSP2_TX_RIGHT_VOLUME, 0xc0 },
+ { WM8996_DSP2_RX_LEFT_VOLUME, 0xc0 },
+ { WM8996_DSP2_RX_RIGHT_VOLUME, 0xc0 },
+ { WM8996_DSP2_TX_FILTERS, 0x2000 },
+ { WM8996_DSP2_RX_FILTERS_1, 0x200 },
+ { WM8996_DSP2_RX_FILTERS_2, 0x10 },
+ { WM8996_DSP2_DRC_1, 0x98 },
+ { WM8996_DSP2_DRC_2, 0x845 },
+ { WM8996_DSP2_RX_EQ_GAINS_1, 0x6318 },
+ { WM8996_DSP2_RX_EQ_GAINS_2, 0x6300 },
+ { WM8996_DSP2_RX_EQ_BAND_1_A, 0xfca },
+ { WM8996_DSP2_RX_EQ_BAND_1_B, 0x400 },
+ { WM8996_DSP2_RX_EQ_BAND_1_PG, 0xd8 },
+ { WM8996_DSP2_RX_EQ_BAND_2_A, 0x1eb5 },
+ { WM8996_DSP2_RX_EQ_BAND_2_B, 0xf145 },
+ { WM8996_DSP2_RX_EQ_BAND_2_C, 0xb75 },
+ { WM8996_DSP2_RX_EQ_BAND_2_PG, 0x1c5 },
+ { WM8996_DSP2_RX_EQ_BAND_3_A, 0x1c58 },
+ { WM8996_DSP2_RX_EQ_BAND_3_B, 0xf373 },
+ { WM8996_DSP2_RX_EQ_BAND_3_C, 0xa54 },
+ { WM8996_DSP2_RX_EQ_BAND_3_PG, 0x558 },
+ { WM8996_DSP2_RX_EQ_BAND_4_A, 0x168e },
+ { WM8996_DSP2_RX_EQ_BAND_4_B, 0xf829 },
+ { WM8996_DSP2_RX_EQ_BAND_4_C, 0x7ad },
+ { WM8996_DSP2_RX_EQ_BAND_4_PG, 0x1103 },
+ { WM8996_DSP2_RX_EQ_BAND_5_A, 0x564 },
+ { WM8996_DSP2_RX_EQ_BAND_5_B, 0x559 },
+ { WM8996_DSP2_RX_EQ_BAND_5_PG, 0x4000 },
+ { WM8996_DAC1_MIXER_VOLUMES, 0x0 },
+ { WM8996_DAC1_LEFT_MIXER_ROUTING, 0x0 },
+ { WM8996_DAC1_RIGHT_MIXER_ROUTING, 0x0 },
+ { WM8996_DAC2_MIXER_VOLUMES, 0x0 },
+ { WM8996_DAC2_LEFT_MIXER_ROUTING, 0x0 },
+ { WM8996_DAC2_RIGHT_MIXER_ROUTING, 0x0 },
+ { WM8996_DSP1_TX_LEFT_MIXER_ROUTING, 0x0 },
+ { WM8996_DSP1_TX_RIGHT_MIXER_ROUTING, 0x0 },
+ { WM8996_DSP2_TX_LEFT_MIXER_ROUTING, 0x0 },
+ { WM8996_DSP2_TX_RIGHT_MIXER_ROUTING, 0x0 },
+ { WM8996_DSP_TX_MIXER_SELECT, 0x0 },
+ { WM8996_DAC_SOFTMUTE, 0x0 },
+ { WM8996_OVERSAMPLING, 0xd },
+ { WM8996_SIDETONE, 0x1040 },
+ { WM8996_GPIO_1, 0xa101 },
+ { WM8996_GPIO_2, 0xa101 },
+ { WM8996_GPIO_3, 0xa101 },
+ { WM8996_GPIO_4, 0xa101 },
+ { WM8996_GPIO_5, 0xa101 },
+ { WM8996_PULL_CONTROL_1, 0x0 },
+ { WM8996_PULL_CONTROL_2, 0x140 },
+ { WM8996_INTERRUPT_STATUS_1_MASK, 0x1f },
+ { WM8996_INTERRUPT_STATUS_2_MASK, 0x1ecf },
+ { WM8996_LEFT_PDM_SPEAKER, 0x0 },
+ { WM8996_RIGHT_PDM_SPEAKER, 0x1 },
+ { WM8996_PDM_SPEAKER_MUTE_SEQUENCE, 0x69 },
+ { WM8996_PDM_SPEAKER_VOLUME, 0x66 },
+ { WM8996_WRITE_SEQUENCER_0, 0x1 },
+ { WM8996_WRITE_SEQUENCER_1, 0x1 },
+ { WM8996_WRITE_SEQUENCER_3, 0x6 },
+ { WM8996_WRITE_SEQUENCER_4, 0x40 },
+ { WM8996_WRITE_SEQUENCER_5, 0x1 },
+ { WM8996_WRITE_SEQUENCER_6, 0xf },
+ { WM8996_WRITE_SEQUENCER_7, 0x6 },
+ { WM8996_WRITE_SEQUENCER_8, 0x1 },
+ { WM8996_WRITE_SEQUENCER_9, 0x3 },
+ { WM8996_WRITE_SEQUENCER_10, 0x104 },
+ { WM8996_WRITE_SEQUENCER_12, 0x60 },
+ { WM8996_WRITE_SEQUENCER_13, 0x11 },
+ { WM8996_WRITE_SEQUENCER_14, 0x401 },
+ { WM8996_WRITE_SEQUENCER_16, 0x50 },
+ { WM8996_WRITE_SEQUENCER_17, 0x3 },
+ { WM8996_WRITE_SEQUENCER_18, 0x100 },
+ { WM8996_WRITE_SEQUENCER_20, 0x51 },
+ { WM8996_WRITE_SEQUENCER_21, 0x3 },
+ { WM8996_WRITE_SEQUENCER_22, 0x104 },
+ { WM8996_WRITE_SEQUENCER_23, 0xa },
+ { WM8996_WRITE_SEQUENCER_24, 0x60 },
+ { WM8996_WRITE_SEQUENCER_25, 0x3b },
+ { WM8996_WRITE_SEQUENCER_26, 0x502 },
+ { WM8996_WRITE_SEQUENCER_27, 0x100 },
+ { WM8996_WRITE_SEQUENCER_28, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_32, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_36, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_40, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_44, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_48, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_52, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_56, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_60, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_64, 0x1 },
+ { WM8996_WRITE_SEQUENCER_65, 0x1 },
+ { WM8996_WRITE_SEQUENCER_67, 0x6 },
+ { WM8996_WRITE_SEQUENCER_68, 0x40 },
+ { WM8996_WRITE_SEQUENCER_69, 0x1 },
+ { WM8996_WRITE_SEQUENCER_70, 0xf },
+ { WM8996_WRITE_SEQUENCER_71, 0x6 },
+ { WM8996_WRITE_SEQUENCER_72, 0x1 },
+ { WM8996_WRITE_SEQUENCER_73, 0x3 },
+ { WM8996_WRITE_SEQUENCER_74, 0x104 },
+ { WM8996_WRITE_SEQUENCER_76, 0x60 },
+ { WM8996_WRITE_SEQUENCER_77, 0x11 },
+ { WM8996_WRITE_SEQUENCER_78, 0x401 },
+ { WM8996_WRITE_SEQUENCER_80, 0x50 },
+ { WM8996_WRITE_SEQUENCER_81, 0x3 },
+ { WM8996_WRITE_SEQUENCER_82, 0x100 },
+ { WM8996_WRITE_SEQUENCER_84, 0x60 },
+ { WM8996_WRITE_SEQUENCER_85, 0x3b },
+ { WM8996_WRITE_SEQUENCER_86, 0x502 },
+ { WM8996_WRITE_SEQUENCER_87, 0x100 },
+ { WM8996_WRITE_SEQUENCER_88, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_92, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_96, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_100, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_104, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_108, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_112, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_116, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_120, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_124, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_128, 0x1 },
+ { WM8996_WRITE_SEQUENCER_129, 0x1 },
+ { WM8996_WRITE_SEQUENCER_131, 0x6 },
+ { WM8996_WRITE_SEQUENCER_132, 0x40 },
+ { WM8996_WRITE_SEQUENCER_133, 0x1 },
+ { WM8996_WRITE_SEQUENCER_134, 0xf },
+ { WM8996_WRITE_SEQUENCER_135, 0x6 },
+ { WM8996_WRITE_SEQUENCER_136, 0x1 },
+ { WM8996_WRITE_SEQUENCER_137, 0x3 },
+ { WM8996_WRITE_SEQUENCER_138, 0x106 },
+ { WM8996_WRITE_SEQUENCER_140, 0x61 },
+ { WM8996_WRITE_SEQUENCER_141, 0x11 },
+ { WM8996_WRITE_SEQUENCER_142, 0x401 },
+ { WM8996_WRITE_SEQUENCER_144, 0x50 },
+ { WM8996_WRITE_SEQUENCER_145, 0x3 },
+ { WM8996_WRITE_SEQUENCER_146, 0x102 },
+ { WM8996_WRITE_SEQUENCER_148, 0x51 },
+ { WM8996_WRITE_SEQUENCER_149, 0x3 },
+ { WM8996_WRITE_SEQUENCER_150, 0x106 },
+ { WM8996_WRITE_SEQUENCER_151, 0xa },
+ { WM8996_WRITE_SEQUENCER_152, 0x61 },
+ { WM8996_WRITE_SEQUENCER_153, 0x3b },
+ { WM8996_WRITE_SEQUENCER_154, 0x502 },
+ { WM8996_WRITE_SEQUENCER_155, 0x100 },
+ { WM8996_WRITE_SEQUENCER_156, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_160, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_164, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_168, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_172, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_176, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_180, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_184, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_188, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_192, 0x1 },
+ { WM8996_WRITE_SEQUENCER_193, 0x1 },
+ { WM8996_WRITE_SEQUENCER_195, 0x6 },
+ { WM8996_WRITE_SEQUENCER_196, 0x40 },
+ { WM8996_WRITE_SEQUENCER_197, 0x1 },
+ { WM8996_WRITE_SEQUENCER_198, 0xf },
+ { WM8996_WRITE_SEQUENCER_199, 0x6 },
+ { WM8996_WRITE_SEQUENCER_200, 0x1 },
+ { WM8996_WRITE_SEQUENCER_201, 0x3 },
+ { WM8996_WRITE_SEQUENCER_202, 0x106 },
+ { WM8996_WRITE_SEQUENCER_204, 0x61 },
+ { WM8996_WRITE_SEQUENCER_205, 0x11 },
+ { WM8996_WRITE_SEQUENCER_206, 0x401 },
+ { WM8996_WRITE_SEQUENCER_208, 0x50 },
+ { WM8996_WRITE_SEQUENCER_209, 0x3 },
+ { WM8996_WRITE_SEQUENCER_210, 0x102 },
+ { WM8996_WRITE_SEQUENCER_212, 0x61 },
+ { WM8996_WRITE_SEQUENCER_213, 0x3b },
+ { WM8996_WRITE_SEQUENCER_214, 0x502 },
+ { WM8996_WRITE_SEQUENCER_215, 0x100 },
+ { WM8996_WRITE_SEQUENCER_216, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_220, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_224, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_228, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_232, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_236, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_240, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_244, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_248, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_252, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_256, 0x60 },
+ { WM8996_WRITE_SEQUENCER_258, 0x601 },
+ { WM8996_WRITE_SEQUENCER_260, 0x50 },
+ { WM8996_WRITE_SEQUENCER_262, 0x100 },
+ { WM8996_WRITE_SEQUENCER_264, 0x1 },
+ { WM8996_WRITE_SEQUENCER_266, 0x104 },
+ { WM8996_WRITE_SEQUENCER_267, 0x100 },
+ { WM8996_WRITE_SEQUENCER_268, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_272, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_276, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_280, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_284, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_288, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_292, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_296, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_300, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_304, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_308, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_312, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_316, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_320, 0x61 },
+ { WM8996_WRITE_SEQUENCER_322, 0x601 },
+ { WM8996_WRITE_SEQUENCER_324, 0x50 },
+ { WM8996_WRITE_SEQUENCER_326, 0x102 },
+ { WM8996_WRITE_SEQUENCER_328, 0x1 },
+ { WM8996_WRITE_SEQUENCER_330, 0x106 },
+ { WM8996_WRITE_SEQUENCER_331, 0x100 },
+ { WM8996_WRITE_SEQUENCER_332, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_336, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_340, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_344, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_348, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_352, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_356, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_360, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_364, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_368, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_372, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_376, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_380, 0x2fff },
+ { WM8996_WRITE_SEQUENCER_384, 0x60 },
+ { WM8996_WRITE_SEQUENCER_386, 0x601 },
+ { WM8996_WRITE_SEQUENCER_388, 0x61 },
+ { WM8996_WRITE_SEQUENCER_390, 0x601 },
+ { WM8996_WRITE_SEQUENCER_392, 0x50 },
+ { WM8996_WRITE_SEQUENCER_394, 0x300 },
+ { WM8996_WRITE_SEQUENCER_396, 0x1 },
+ { WM8996_WRITE_SEQUENCER_398, 0x304 },
+ { WM8996_WRITE_SEQUENCER_400, 0x40 },
+ { WM8996_WRITE_SEQUENCER_402, 0xf },
+ { WM8996_WRITE_SEQUENCER_404, 0x1 },
+ { WM8996_WRITE_SEQUENCER_407, 0x100 },
};
static const DECLARE_TLV_DB_SCALE(inpga_tlv, 0, 100, 0);
@@ -414,6 +483,7 @@ static const DECLARE_TLV_DB_SCALE(out_digital_tlv, -1200, 150, 0);
static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0);
static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0);
static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0);
+static const DECLARE_TLV_DB_SCALE(threedstereo_tlv, -1600, 183, 1);
static const char *sidetone_hpf_text[] = {
"2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz"
@@ -608,6 +678,14 @@ SOC_SINGLE("DAC High Performance Switch", WM8996_OVERSAMPLING, 0, 1, 0),
SOC_SINGLE("DAC Soft Mute Switch", WM8996_DAC_SOFTMUTE, 1, 1, 0),
SOC_SINGLE("DAC Slow Soft Mute Switch", WM8996_DAC_SOFTMUTE, 0, 1, 0),
+SOC_SINGLE("DSP1 3D Stereo Switch", WM8996_DSP1_RX_FILTERS_2, 8, 1, 0),
+SOC_SINGLE("DSP2 3D Stereo Switch", WM8996_DSP2_RX_FILTERS_2, 8, 1, 0),
+
+SOC_SINGLE_TLV("DSP1 3D Stereo Volume", WM8996_DSP1_RX_FILTERS_2, 10, 15,
+ 0, threedstereo_tlv),
+SOC_SINGLE_TLV("DSP2 3D Stereo Volume", WM8996_DSP2_RX_FILTERS_2, 10, 15,
+ 0, threedstereo_tlv),
+
SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8996_DAC1_HPOUT1_VOLUME, 0, 4,
8, 0, out_digital_tlv),
SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8996_DAC2_HPOUT2_VOLUME, 0, 4,
@@ -632,6 +710,20 @@ SOC_DOUBLE_R("Speaker ZC Switch", WM8996_LEFT_PDM_SPEAKER,
SOC_SINGLE("DSP1 EQ Switch", WM8996_DSP1_RX_EQ_GAINS_1, 0, 1, 0),
SOC_SINGLE("DSP2 EQ Switch", WM8996_DSP2_RX_EQ_GAINS_1, 0, 1, 0),
+
+SOC_SINGLE("DSP1 DRC TXL Switch", WM8996_DSP1_DRC_1, 0, 1, 0),
+SOC_SINGLE("DSP1 DRC TXR Switch", WM8996_DSP1_DRC_1, 1, 1, 0),
+SOC_SINGLE("DSP1 DRC RX Switch", WM8996_DSP1_DRC_1, 2, 1, 0),
+SND_SOC_BYTES_MASK("DSP1 DRC", WM8996_DSP1_DRC_1, 5,
+ WM8996_DSP1RX_DRC_ENA | WM8996_DSP1TXL_DRC_ENA |
+ WM8996_DSP1TXR_DRC_ENA),
+
+SOC_SINGLE("DSP2 DRC TXL Switch", WM8996_DSP2_DRC_1, 0, 1, 0),
+SOC_SINGLE("DSP2 DRC TXR Switch", WM8996_DSP2_DRC_1, 1, 1, 0),
+SOC_SINGLE("DSP2 DRC RX Switch", WM8996_DSP2_DRC_1, 2, 1, 0),
+SND_SOC_BYTES_MASK("DSP2 DRC", WM8996_DSP2_DRC_1, 5,
+ WM8996_DSP2RX_DRC_ENA | WM8996_DSP2TXL_DRC_ENA |
+ WM8996_DSP2TXR_DRC_ENA),
};
static const struct snd_kcontrol_new wm8996_eq_controls[] = {
@@ -658,16 +750,61 @@ SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 6, 31, 0,
eq_tlv),
};
+static void wm8996_bg_enable(struct snd_soc_codec *codec)
+{
+ struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+
+ wm8996->bg_ena++;
+ if (wm8996->bg_ena == 1) {
+ snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
+ WM8996_BG_ENA, WM8996_BG_ENA);
+ msleep(2);
+ }
+}
+
+static void wm8996_bg_disable(struct snd_soc_codec *codec)
+{
+ struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+
+ wm8996->bg_ena--;
+ if (!wm8996->bg_ena)
+ snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
+ WM8996_BG_ENA, 0);
+}
+
+static int bg_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ int ret = 0;
+
+ switch (event) {
+ case SND_SOC_DAPM_PRE_PMU:
+ wm8996_bg_enable(codec);
+ break;
+ case SND_SOC_DAPM_POST_PMD:
+ wm8996_bg_disable(codec);
+ break;
+ default:
+ BUG();
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
static int cp_event(struct snd_soc_dapm_widget *w,
struct snd_kcontrol *kcontrol, int event)
{
+ int ret = 0;
+
switch (event) {
case SND_SOC_DAPM_POST_PMU:
msleep(5);
break;
default:
BUG();
- return -EINVAL;
+ ret = -EINVAL;
}
return 0;
@@ -698,7 +835,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask)
{
struct i2c_client *i2c = to_i2c_client(codec->dev);
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
- int i, ret;
+ int ret;
unsigned long timeout = 200;
snd_soc_write(codec, WM8996_DC_SERVO_2, mask);
@@ -713,15 +850,12 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask)
} else {
msleep(1);
- if (--i) {
- timeout = 0;
- break;
- }
+ timeout--;
}
ret = snd_soc_read(codec, WM8996_DC_SERVO_2);
dev_dbg(codec->dev, "DC servo state: %x\n", ret);
- } while (ret & mask);
+ } while (timeout && ret & mask);
if (timeout == 0)
dev_err(codec->dev, "DC servo timed out for %x\n", mask);
@@ -756,8 +890,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
val = 0;
mask = 0;
if (wm8996->hpout_pending & HPOUT1L) {
- val |= WM8996_HPOUT1L_RMV_SHORT;
- mask |= WM8996_HPOUT1L_RMV_SHORT;
+ val |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP;
+ mask |= WM8996_HPOUT1L_RMV_SHORT | WM8996_HPOUT1L_OUTP;
} else {
mask |= WM8996_HPOUT1L_RMV_SHORT |
WM8996_HPOUT1L_OUTP |
@@ -765,8 +899,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
}
if (wm8996->hpout_pending & HPOUT1R) {
- val |= WM8996_HPOUT1R_RMV_SHORT;
- mask |= WM8996_HPOUT1R_RMV_SHORT;
+ val |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP;
+ mask |= WM8996_HPOUT1R_RMV_SHORT | WM8996_HPOUT1R_OUTP;
} else {
mask |= WM8996_HPOUT1R_RMV_SHORT |
WM8996_HPOUT1R_OUTP |
@@ -778,8 +912,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
val = 0;
mask = 0;
if (wm8996->hpout_pending & HPOUT2L) {
- val |= WM8996_HPOUT2L_RMV_SHORT;
- mask |= WM8996_HPOUT2L_RMV_SHORT;
+ val |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP;
+ mask |= WM8996_HPOUT2L_RMV_SHORT | WM8996_HPOUT2L_OUTP;
} else {
mask |= WM8996_HPOUT2L_RMV_SHORT |
WM8996_HPOUT2L_OUTP |
@@ -787,8 +921,8 @@ static void wm8996_seq_notifier(struct snd_soc_dapm_context *dapm,
}
if (wm8996->hpout_pending & HPOUT2R) {
- val |= WM8996_HPOUT2R_RMV_SHORT;
- mask |= WM8996_HPOUT2R_RMV_SHORT;
+ val |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP;
+ mask |= WM8996_HPOUT2R_RMV_SHORT | WM8996_HPOUT2R_OUTP;
} else {
mask |= WM8996_HPOUT2R_RMV_SHORT |
WM8996_HPOUT2R_OUTP |
@@ -975,13 +1109,17 @@ SND_SOC_DAPM_INPUT("IN2RP"),
SND_SOC_DAPM_INPUT("DMIC1DAT"),
SND_SOC_DAPM_INPUT("DMIC2DAT"),
+SND_SOC_DAPM_REGULATOR_SUPPLY("CPVDD", 20),
SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event,
SND_SOC_DAPM_POST_PMU),
-
+SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event,
+ SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICB2 Audio", WM8996_MICBIAS_2, 4, 1, NULL, 0),
SND_SOC_DAPM_MICBIAS("MICB2", WM8996_POWER_MANAGEMENT_1, 9, 0),
SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0),
@@ -1035,41 +1173,25 @@ SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0),
SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0),
SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0),
-SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 1,
- WM8996_POWER_MANAGEMENT_4, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 2,
- WM8996_POWER_MANAGEMENT_4, 8, 0),
-
-SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 1,
- WM8996_POWER_MANAGEMENT_6, 9, 0),
-SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 2,
- WM8996_POWER_MANAGEMENT_6, 8, 0),
-
-SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5,
- WM8996_POWER_MANAGEMENT_4, 5, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX4", "AIF1 Playback", 4,
- WM8996_POWER_MANAGEMENT_4, 4, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX3", "AIF1 Playback", 3,
- WM8996_POWER_MANAGEMENT_4, 3, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX2", "AIF1 Playback", 2,
- WM8996_POWER_MANAGEMENT_4, 2, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX1", "AIF1 Playback", 1,
- WM8996_POWER_MANAGEMENT_4, 1, 0),
-SND_SOC_DAPM_AIF_IN("AIF1RX0", "AIF1 Playback", 0,
- WM8996_POWER_MANAGEMENT_4, 0, 0),
-
-SND_SOC_DAPM_AIF_OUT("AIF1TX5", "AIF1 Capture", 5,
- WM8996_POWER_MANAGEMENT_6, 5, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX4", "AIF1 Capture", 4,
- WM8996_POWER_MANAGEMENT_6, 4, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX3", "AIF1 Capture", 3,
- WM8996_POWER_MANAGEMENT_6, 3, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX2", "AIF1 Capture", 2,
- WM8996_POWER_MANAGEMENT_6, 2, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX1", "AIF1 Capture", 1,
- WM8996_POWER_MANAGEMENT_6, 1, 0),
-SND_SOC_DAPM_AIF_OUT("AIF1TX0", "AIF1 Capture", 0,
- WM8996_POWER_MANAGEMENT_6, 0, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX1", NULL, 0, WM8996_POWER_MANAGEMENT_4, 9, 0),
+SND_SOC_DAPM_AIF_IN("AIF2RX0", NULL, 1, WM8996_POWER_MANAGEMENT_4, 8, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF2TX1", NULL, 0, WM8996_POWER_MANAGEMENT_6, 9, 0),
+SND_SOC_DAPM_AIF_OUT("AIF2TX0", NULL, 1, WM8996_POWER_MANAGEMENT_6, 8, 0),
+
+SND_SOC_DAPM_AIF_IN("AIF1RX5", NULL, 5, WM8996_POWER_MANAGEMENT_4, 5, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX4", NULL, 4, WM8996_POWER_MANAGEMENT_4, 4, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX3", NULL, 3, WM8996_POWER_MANAGEMENT_4, 3, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX2", NULL, 2, WM8996_POWER_MANAGEMENT_4, 2, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX1", NULL, 1, WM8996_POWER_MANAGEMENT_4, 1, 0),
+SND_SOC_DAPM_AIF_IN("AIF1RX0", NULL, 0, WM8996_POWER_MANAGEMENT_4, 0, 0),
+
+SND_SOC_DAPM_AIF_OUT("AIF1TX5", NULL, 5, WM8996_POWER_MANAGEMENT_6, 5, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX4", NULL, 4, WM8996_POWER_MANAGEMENT_6, 4, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX3", NULL, 3, WM8996_POWER_MANAGEMENT_6, 3, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX2", NULL, 2, WM8996_POWER_MANAGEMENT_6, 2, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX1", NULL, 1, WM8996_POWER_MANAGEMENT_6, 1, 0),
+SND_SOC_DAPM_AIF_OUT("AIF1TX0", NULL, 0, WM8996_POWER_MANAGEMENT_6, 0, 0),
/* We route as stereo pairs so define some dummy widgets to squash
* things down for now. RXA = 0,1, RXB = 2,3 and so on */
@@ -1092,7 +1214,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2L PGA", 0, WM8996_POWER_MANAGEMENT_1, 7, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2L_DLY", 1, WM8996_ANALOGUE_HP_2, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2L_DCS", 2, WM8996_DC_SERVO_1, 2, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT2L_OUTP", 3, WM8996_ANALOGUE_HP_2, 6, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2L, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1101,7 +1222,6 @@ SND_SOC_DAPM_PGA_S("HPOUT2R PGA", 0, WM8996_POWER_MANAGEMENT_1, 6, 0,NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2R_DLY", 1, WM8996_ANALOGUE_HP_2, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2R_DCS", 2, WM8996_DC_SERVO_1, 3, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT2R_OUTP", 3, WM8996_ANALOGUE_HP_2, 2, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT2R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT2R, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1110,7 +1230,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1L PGA", 0, WM8996_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1L_DLY", 1, WM8996_ANALOGUE_HP_1, 5, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1L_DCS", 2, WM8996_DC_SERVO_1, 0, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT1L_OUTP", 3, WM8996_ANALOGUE_HP_1, 6, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1L_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1L, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1119,7 +1238,6 @@ SND_SOC_DAPM_PGA_S("HPOUT1R PGA", 0, WM8996_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1R_DLY", 1, WM8996_ANALOGUE_HP_1, 1, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1R_DCS", 2, WM8996_DC_SERVO_1, 1, 0, dcs_start,
SND_SOC_DAPM_POST_PMU),
-SND_SOC_DAPM_PGA_S("HPOUT1R_OUTP", 3, WM8996_ANALOGUE_HP_1, 2, 0, NULL, 0),
SND_SOC_DAPM_PGA_S("HPOUT1R_RMV_SHORT", 3, SND_SOC_NOPM, HPOUT1R, 0,
rmv_short_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
@@ -1135,19 +1253,46 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
{ "AIFCLK", NULL, "SYSCLK" },
{ "SYSDSPCLK", NULL, "SYSCLK" },
{ "Charge Pump", NULL, "SYSCLK" },
+ { "Charge Pump", NULL, "CPVDD" },
{ "MICB1", NULL, "LDO2" },
+ { "MICB1", NULL, "MICB1 Audio" },
+ { "MICB1", NULL, "Bandgap" },
{ "MICB2", NULL, "LDO2" },
+ { "MICB2", NULL, "MICB2 Audio" },
+ { "MICB2", NULL, "Bandgap" },
+
+ { "AIF1RX0", NULL, "AIF1 Playback" },
+ { "AIF1RX1", NULL, "AIF1 Playback" },
+ { "AIF1RX2", NULL, "AIF1 Playback" },
+ { "AIF1RX3", NULL, "AIF1 Playback" },
+ { "AIF1RX4", NULL, "AIF1 Playback" },
+ { "AIF1RX5", NULL, "AIF1 Playback" },
+
+ { "AIF2RX0", NULL, "AIF2 Playback" },
+ { "AIF2RX1", NULL, "AIF2 Playback" },
+
+ { "AIF1 Capture", NULL, "AIF1TX0" },
+ { "AIF1 Capture", NULL, "AIF1TX1" },
+ { "AIF1 Capture", NULL, "AIF1TX2" },
+ { "AIF1 Capture", NULL, "AIF1TX3" },
+ { "AIF1 Capture", NULL, "AIF1TX4" },
+ { "AIF1 Capture", NULL, "AIF1TX5" },
+
+ { "AIF2 Capture", NULL, "AIF2TX0" },
+ { "AIF2 Capture", NULL, "AIF2TX1" },
{ "IN1L PGA", NULL, "IN2LN" },
{ "IN1L PGA", NULL, "IN2LP" },
{ "IN1L PGA", NULL, "IN1LN" },
{ "IN1L PGA", NULL, "IN1LP" },
+ { "IN1L PGA", NULL, "Bandgap" },
{ "IN1R PGA", NULL, "IN2RN" },
{ "IN1R PGA", NULL, "IN2RP" },
{ "IN1R PGA", NULL, "IN1RN" },
{ "IN1R PGA", NULL, "IN1RP" },
+ { "IN1R PGA", NULL, "Bandgap" },
{ "ADCL", NULL, "IN1L PGA" },
@@ -1281,32 +1426,32 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
{ "DAC2R", NULL, "DAC2R Mixer" },
{ "HPOUT2L PGA", NULL, "Charge Pump" },
+ { "HPOUT2L PGA", NULL, "Bandgap" },
{ "HPOUT2L PGA", NULL, "DAC2L" },
{ "HPOUT2L_DLY", NULL, "HPOUT2L PGA" },
{ "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" },
- { "HPOUT2L_OUTP", NULL, "HPOUT2L_DCS" },
- { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" },
+ { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_DCS" },
{ "HPOUT2R PGA", NULL, "Charge Pump" },
+ { "HPOUT2R PGA", NULL, "Bandgap" },
{ "HPOUT2R PGA", NULL, "DAC2R" },
{ "HPOUT2R_DLY", NULL, "HPOUT2R PGA" },
{ "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" },
- { "HPOUT2R_OUTP", NULL, "HPOUT2R_DCS" },
- { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" },
+ { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_DCS" },
{ "HPOUT1L PGA", NULL, "Charge Pump" },
+ { "HPOUT1L PGA", NULL, "Bandgap" },
{ "HPOUT1L PGA", NULL, "DAC1L" },
{ "HPOUT1L_DLY", NULL, "HPOUT1L PGA" },
{ "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" },
- { "HPOUT1L_OUTP", NULL, "HPOUT1L_DCS" },
- { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" },
+ { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_DCS" },
{ "HPOUT1R PGA", NULL, "Charge Pump" },
+ { "HPOUT1R PGA", NULL, "Bandgap" },
{ "HPOUT1R PGA", NULL, "DAC1R" },
{ "HPOUT1R_DLY", NULL, "HPOUT1R PGA" },
{ "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" },
- { "HPOUT1R_OUTP", NULL, "HPOUT1R_DCS" },
- { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_OUTP" },
+ { "HPOUT1R_RMV_SHORT", NULL, "HPOUT1R_DCS" },
{ "HPOUT2L", NULL, "HPOUT2L_RMV_SHORT" },
{ "HPOUT2R", NULL, "HPOUT2R_RMV_SHORT" },
@@ -1330,8 +1475,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = {
{ "SPKDAT", NULL, "SPKR PGA" },
};
-static int wm8996_readable_register(struct snd_soc_codec *codec,
- unsigned int reg)
+static bool wm8996_readable_register(struct device *dev, unsigned int reg)
{
/* Due to the sparseness of the register map the compiler
* output from an explicit switch statement ends up being much
@@ -1538,8 +1682,7 @@ static int wm8996_readable_register(struct snd_soc_codec *codec,
}
}
-static int wm8996_volatile_register(struct snd_soc_codec *codec,
- unsigned int reg)
+static bool wm8996_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM8996_SOFTWARE_RESET:
@@ -1563,9 +1706,16 @@ static int wm8996_volatile_register(struct snd_soc_codec *codec,
}
}
-static int wm8996_reset(struct snd_soc_codec *codec)
+static int wm8996_reset(struct wm8996_priv *wm8996)
{
- return snd_soc_write(codec, WM8996_SOFTWARE_RESET, 0x8915);
+ if (wm8996->pdata.ldo_ena > 0) {
+ gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+ gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
+ return 0;
+ } else {
+ return regmap_write(wm8996->regmap, WM8996_SOFTWARE_RESET,
+ 0x8915);
+ }
}
static const int bclk_divs[] = {
@@ -1620,14 +1770,7 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_ON:
- break;
-
case SND_SOC_BIAS_PREPARE:
- if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
- snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
- WM8996_BG_ENA, WM8996_BG_ENA);
- msleep(2);
- }
break;
case SND_SOC_BIAS_STANDBY:
@@ -1647,16 +1790,13 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec,
msleep(5);
}
- codec->cache_only = false;
- snd_soc_cache_sync(codec);
+ regcache_cache_only(codec->control_data, false);
+ regcache_sync(codec->control_data);
}
-
- snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1,
- WM8996_BG_ENA, 0);
break;
case SND_SOC_BIAS_OFF:
- codec->cache_only = true;
+ regcache_cache_only(codec->control_data, true);
if (wm8996->pdata.ldo_ena >= 0)
gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies),
@@ -1774,7 +1914,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_codec *codec = dai->codec;
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
- int bits, i, bclk_rate;
+ int bits, i, bclk_rate, best;
int aifdata = 0;
int lrclk = 0;
int dsp = 0;
@@ -1823,14 +1963,11 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
return bits;
aifdata |= (bits << WM8996_AIF1TX_WL_SHIFT) | bits;
+ best = 0;
for (i = 0; i < ARRAY_SIZE(dsp_divs); i++) {
- if (dsp_divs[i] == params_rate(params))
- break;
- }
- if (i == ARRAY_SIZE(dsp_divs)) {
- dev_err(codec->dev, "Unsupported sample rate %dHz\n",
- params_rate(params));
- return -EINVAL;
+ if (abs(dsp_divs[i] - params_rate(params)) <
+ abs(dsp_divs[best] - params_rate(params)))
+ best = i;
}
dsp |= i << dsp_shift;
@@ -1847,7 +1984,7 @@ static int wm8996_hw_params(struct snd_pcm_substream *substream,
snd_soc_update_bits(codec, lrclk_reg, WM8996_AIF1RX_RATE_MASK,
lrclk);
snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_2,
- WM8996_DSP1_DIV_SHIFT << dsp_shift, dsp);
+ WM8996_DSP1_DIV_MASK << dsp_shift, dsp);
return 0;
}
@@ -1859,6 +1996,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int lfclk = 0;
int ratediv = 0;
+ int sync = WM8996_REG_SYNC;
int src;
int old;
@@ -1889,12 +2027,16 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
}
switch (wm8996->sysclk) {
+ case 5644800:
case 6144000:
snd_soc_update_bits(codec, WM8996_AIF_RATE,
WM8996_SYSCLK_RATE, 0);
break;
+ case 22579200:
case 24576000:
ratediv = WM8996_SYSCLK_DIV;
+ wm8996->sysclk /= 2;
+ case 11289600:
case 12288000:
snd_soc_update_bits(codec, WM8996_AIF_RATE,
WM8996_SYSCLK_RATE, WM8996_SYSCLK_RATE);
@@ -1902,6 +2044,7 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
case 32000:
case 32768:
lfclk = WM8996_LFCLK_ENA;
+ sync = 0;
break;
default:
dev_warn(codec->dev, "Unsupported clock rate %dHz\n",
@@ -1915,6 +2058,8 @@ static int wm8996_set_sysclk(struct snd_soc_dai *dai,
WM8996_SYSCLK_SRC_MASK | WM8996_SYSCLK_DIV_MASK,
src << WM8996_SYSCLK_SRC_SHIFT | ratediv);
snd_soc_update_bits(codec, WM8996_CLOCKING_1, WM8996_LFCLK_ENA, lfclk);
+ snd_soc_update_bits(codec, WM8996_CONTROL_INTERFACE_1,
+ WM8996_REG_SYNC, sync);
snd_soc_update_bits(codec, WM8996_AIF_CLOCKING_1,
WM8996_SYSCLK_ENA, old);
@@ -2041,7 +2186,7 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
struct i2c_client *i2c = to_i2c_client(codec->dev);
struct _fll_div fll_div;
unsigned long timeout;
- int ret, reg;
+ int ret, reg, retry;
/* Any change? */
if (source == wm8996->fll_src && Fref == wm8996->fll_fref &&
@@ -2057,6 +2202,8 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1,
WM8996_FLL_ENA, 0);
+ wm8996_bg_disable(codec);
+
return 0;
}
@@ -2111,6 +2258,11 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda);
+ /* Enable the bandgap if it's not already enabled */
+ ret = snd_soc_read(codec, WM8996_FLL_CONTROL_1);
+ if (!(ret & WM8996_FLL_ENA))
+ wm8996_bg_enable(codec);
+
/* Clear any pending completions (eg, from failed startups) */
try_wait_for_completion(&wm8996->fll_lock);
@@ -2128,17 +2280,29 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source,
else
timeout = msecs_to_jiffies(2);
- /* Allow substantially longer if we've actually got the IRQ */
+ /* Allow substantially longer if we've actually got the IRQ, poll
+ * at a slightly higher rate if we don't.
+ */
if (i2c->irq)
- timeout *= 1000;
+ timeout *= 10;
+ else
+ timeout /= 2;
- ret = wait_for_completion_timeout(&wm8996->fll_lock, timeout);
+ for (retry = 0; retry < 10; retry++) {
+ ret = wait_for_completion_timeout(&wm8996->fll_lock,
+ timeout);
+ if (ret != 0) {
+ WARN_ON(!i2c->irq);
+ break;
+ }
- if (ret == 0 && i2c->irq) {
+ ret = snd_soc_read(codec, WM8996_INTERRUPT_RAW_STATUS_2);
+ if (ret & WM8996_FLL_LOCK_STS)
+ break;
+ }
+ if (retry == 10) {
dev_err(codec->dev, "Timed out waiting for FLL\n");
ret = -ETIMEDOUT;
- } else {
- ret = 0;
}
dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout);
@@ -2159,48 +2323,45 @@ static inline struct wm8996_priv *gpio_to_wm8996(struct gpio_chip *chip)
static void wm8996_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
{
struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
- struct snd_soc_codec *codec = wm8996->codec;
- snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
- WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT);
+ regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset,
+ WM8996_GP1_LVL, !!value << WM8996_GP1_LVL_SHIFT);
}
static int wm8996_gpio_direction_out(struct gpio_chip *chip,
unsigned offset, int value)
{
struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
- struct snd_soc_codec *codec = wm8996->codec;
int val;
val = (1 << WM8996_GP1_FN_SHIFT) | (!!value << WM8996_GP1_LVL_SHIFT);
- return snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
- WM8996_GP1_FN_MASK | WM8996_GP1_DIR |
- WM8996_GP1_LVL, val);
+ return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset,
+ WM8996_GP1_FN_MASK | WM8996_GP1_DIR |
+ WM8996_GP1_LVL, val);
}
static int wm8996_gpio_get(struct gpio_chip *chip, unsigned offset)
{
struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
- struct snd_soc_codec *codec = wm8996->codec;
+ unsigned int reg;
int ret;
- ret = snd_soc_read(codec, WM8996_GPIO_1 + offset);
+ ret = regmap_read(wm8996->regmap, WM8996_GPIO_1 + offset, &reg);
if (ret < 0)
return ret;
- return (ret & WM8996_GP1_LVL) != 0;
+ return (reg & WM8996_GP1_LVL) != 0;
}
static int wm8996_gpio_direction_in(struct gpio_chip *chip, unsigned offset)
{
struct wm8996_priv *wm8996 = gpio_to_wm8996(chip);
- struct snd_soc_codec *codec = wm8996->codec;
- return snd_soc_update_bits(codec, WM8996_GPIO_1 + offset,
- WM8996_GP1_FN_MASK | WM8996_GP1_DIR,
- (1 << WM8996_GP1_FN_SHIFT) |
- (1 << WM8996_GP1_DIR_SHIFT));
+ return regmap_update_bits(wm8996->regmap, WM8996_GPIO_1 + offset,
+ WM8996_GP1_FN_MASK | WM8996_GP1_DIR,
+ (1 << WM8996_GP1_FN_SHIFT) |
+ (1 << WM8996_GP1_DIR_SHIFT));
}
static struct gpio_chip wm8996_template_chip = {
@@ -2213,14 +2374,13 @@ static struct gpio_chip wm8996_template_chip = {
.can_sleep = 1,
};
-static void wm8996_init_gpio(struct snd_soc_codec *codec)
+static void wm8996_init_gpio(struct wm8996_priv *wm8996)
{
- struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int ret;
wm8996->gpio_chip = wm8996_template_chip;
wm8996->gpio_chip.ngpio = 5;
- wm8996->gpio_chip.dev = codec->dev;
+ wm8996->gpio_chip.dev = wm8996->dev;
if (wm8996->pdata.gpio_base)
wm8996->gpio_chip.base = wm8996->pdata.gpio_base;
@@ -2229,24 +2389,23 @@ static void wm8996_init_gpio(struct snd_soc_codec *codec)
ret = gpiochip_add(&wm8996->gpio_chip);
if (ret != 0)
- dev_err(codec->dev, "Failed to add GPIOs: %d\n", ret);
+ dev_err(wm8996->dev, "Failed to add GPIOs: %d\n", ret);
}
-static void wm8996_free_gpio(struct snd_soc_codec *codec)
+static void wm8996_free_gpio(struct wm8996_priv *wm8996)
{
- struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
int ret;
ret = gpiochip_remove(&wm8996->gpio_chip);
if (ret != 0)
- dev_err(codec->dev, "Failed to remove GPIOs: %d\n", ret);
+ dev_err(wm8996->dev, "Failed to remove GPIOs: %d\n", ret);
}
#else
-static void wm8996_init_gpio(struct snd_soc_codec *codec)
+static void wm8996_init_gpio(struct wm8996_priv *wm8996)
{
}
-static void wm8996_free_gpio(struct snd_soc_codec *codec)
+static void wm8996_free_gpio(struct wm8996_priv *wm8996)
{
}
#endif
@@ -2270,6 +2429,7 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
wm8996->jack = jack;
wm8996->detecting = true;
wm8996->polarity_cb = polarity_cb;
+ wm8996->jack_flips = 0;
if (wm8996->polarity_cb)
wm8996->polarity_cb(codec, 0);
@@ -2297,12 +2457,107 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
/* Enable interrupts and we're off */
snd_soc_update_bits(codec, WM8996_INTERRUPT_STATUS_2_MASK,
- WM8996_IM_MICD_EINT, 0);
+ WM8996_IM_MICD_EINT | WM8996_HP_DONE_EINT, 0);
return 0;
}
EXPORT_SYMBOL_GPL(wm8996_detect);
+static void wm8996_hpdet_irq(struct snd_soc_codec *codec)
+{
+ struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
+ int val, reg, report;
+
+ /* Assume headphone in error conditions; we need to report
+ * something or we stall our state machine.
+ */
+ report = SND_JACK_HEADPHONE;
+
+ reg = snd_soc_read(codec, WM8996_HEADPHONE_DETECT_2);
+ if (reg < 0) {
+ dev_err(codec->dev, "Failed to read HPDET status\n");
+ goto out;
+ }
+
+ if (!(reg & WM8996_HP_DONE)) {
+ dev_err(codec->dev, "Got HPDET IRQ but HPDET is busy\n");
+ goto out;
+ }
+
+ val = reg & WM8996_HP_LVL_MASK;
+
+ dev_dbg(codec->dev, "HPDET measured %d ohms\n", val);
+
+ /* If we've got high enough impedence then report as line,
+ * otherwise assume headphone.
+ */
+ if (val >= 126)
+ report = SND_JACK_LINEOUT;
+ else
+ report = SND_JACK_HEADPHONE;
+
+out:
+ if (wm8996->jack_mic)
+ report |= SND_JACK_MICROPHONE;
+
+ snd_soc_jack_report(wm8996->jack, report,
+ SND_JACK_LINEOUT | SND_JACK_HEADSET);
+
+ wm8996->detecting = false;
+
+ /* If the output isn't running re-clamp it */
+ if (!(snd_soc_read(codec, WM8996_POWER_MANAGEMENT_1) &
+ (WM8996_HPOUT1L_ENA | WM8996_HPOUT1R_RMV_SHORT)))
+ snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1,
+ WM8996_HPOUT1L_RMV_SHORT |
+ WM8996_HPOUT1R_RMV_SHORT, 0);
+
+ /* Go back to looking at the microphone */
+ snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1,
+ WM8996_JD_MODE_MASK, 0);
+ snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA,
+ WM8996_MICD_ENA);
+
+ snd_soc_dapm_disable_pin(&codec->dapm, "Bandgap");
+ snd_soc_dapm_sync(&codec->dapm);
+}
+
+static void wm8996_hpdet_start(struct snd_soc_codec *codec)
+{
+ /* Unclamp the output, we can't measure while we're shorting it */
+ snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1,
+ WM8996_HPOUT1L_RMV_SHORT |
+ WM8996_HPOUT1R_RMV_SHORT,
+ WM8996_HPOUT1L_RMV_SHORT |
+ WM8996_HPOUT1R_RMV_SHORT);
+
+ /* We need bandgap for HPDET */
+ snd_soc_dapm_force_enable_pin(&codec->dapm, "Bandgap");
+ snd_soc_dapm_sync(&codec->dapm);
+
+ /* Go into headphone detect left mode */
+ snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, 0);
+ snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1,
+ WM8996_JD_MODE_MASK, 1);
+
+ /* Trigger a measurement */
+ snd_soc_update_bits(codec, WM8996_HEADPHONE_DETECT_1,
+ WM8996_HP_POLL, WM8996_HP_POLL);
+}
+
+static void wm8996_report_headphone(struct snd_soc_codec *codec)
+{
+ dev_dbg(codec->dev, "Headphone detected\n");
+ wm8996_hpdet_start(codec);
+
+ /* Increase the detection rate a bit for responsiveness. */
+ snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+ WM8996_MICD_RATE_MASK |
+ WM8996_MICD_BIAS_STARTTIME_MASK,
+ 7 << WM8996_MICD_RATE_SHIFT |
+ 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+}
+
static void wm8996_micd(struct snd_soc_codec *codec)
{
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
@@ -2322,37 +2577,58 @@ static void wm8996_micd(struct snd_soc_codec *codec)
dev_dbg(codec->dev, "Jack removal detected\n");
wm8996->jack_mic = false;
wm8996->detecting = true;
+ wm8996->jack_flips = 0;
snd_soc_jack_report(wm8996->jack, 0,
- SND_JACK_HEADSET | SND_JACK_BTN_0);
+ SND_JACK_LINEOUT | SND_JACK_HEADSET |
+ SND_JACK_BTN_0);
+
snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
- WM8996_MICD_RATE_MASK,
- WM8996_MICD_RATE_MASK);
+ WM8996_MICD_RATE_MASK |
+ WM8996_MICD_BIAS_STARTTIME_MASK,
+ WM8996_MICD_RATE_MASK |
+ 9 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
return;
}
- /* If the measurement is very high we've got a microphone but
- * do a little debounce to account for mechanical issues.
+ /* If the measurement is very high we've got a microphone,
+ * either we just detected one or if we already reported then
+ * we've got a button release event.
*/
if (val & 0x400) {
- dev_dbg(codec->dev, "Microphone detected\n");
- snd_soc_jack_report(wm8996->jack, SND_JACK_HEADSET,
- SND_JACK_HEADSET | SND_JACK_BTN_0);
- wm8996->jack_mic = true;
- wm8996->detecting = false;
-
- /* Increase poll rate to give better responsiveness
- * for buttons */
- snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
- WM8996_MICD_RATE_MASK,
- 5 << WM8996_MICD_RATE_SHIFT);
+ if (wm8996->detecting) {
+ dev_dbg(codec->dev, "Microphone detected\n");
+ wm8996->jack_mic = true;
+ wm8996_hpdet_start(codec);
+
+ /* Increase poll rate to give better responsiveness
+ * for buttons */
+ snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
+ WM8996_MICD_RATE_MASK |
+ WM8996_MICD_BIAS_STARTTIME_MASK,
+ 5 << WM8996_MICD_RATE_SHIFT |
+ 7 << WM8996_MICD_BIAS_STARTTIME_SHIFT);
+ } else {
+ dev_dbg(codec->dev, "Mic button up\n");
+ snd_soc_jack_report(wm8996->jack, 0, SND_JACK_BTN_0);
+ }
+
+ return;
}
/* If we detected a lower impedence during initial startup
* then we probably have the wrong polarity, flip it. Don't
* do this for the lowest impedences to speed up detection of
- * plain headphones.
+ * plain headphones. If both polarities report a low
+ * impedence then give up and report headphones.
*/
if (wm8996->detecting && (val & 0x3f0)) {
+ wm8996->jack_flips++;
+
+ if (wm8996->jack_flips > 1) {
+ wm8996_report_headphone(codec);
+ return;
+ }
+
reg = snd_soc_read(codec, WM8996_ACCESSORY_DETECT_MODE_2);
reg ^= WM8996_HPOUT1FB_SRC | WM8996_MICD_SRC |
WM8996_MICD_BIAS_SRC;
@@ -2376,24 +2652,10 @@ static void wm8996_micd(struct snd_soc_codec *codec)
if (val & 0x3fc) {
if (wm8996->jack_mic) {
dev_dbg(codec->dev, "Mic button detected\n");
- snd_soc_jack_report(wm8996->jack,
- SND_JACK_HEADSET | SND_JACK_BTN_0,
- SND_JACK_HEADSET | SND_JACK_BTN_0);
- } else {
- dev_dbg(codec->dev, "Headphone detected\n");
- snd_soc_jack_report(wm8996->jack,
- SND_JACK_HEADPHONE,
- SND_JACK_HEADSET |
+ snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0,
SND_JACK_BTN_0);
-
- /* Increase the detection rate a bit for
- * responsiveness.
- */
- snd_soc_update_bits(codec, WM8996_MIC_DETECT_1,
- WM8996_MICD_RATE_MASK,
- 7 << WM8996_MICD_RATE_SHIFT);
-
- wm8996->detecting = false;
+ } else if (wm8996->detecting) {
+ wm8996_report_headphone(codec);
}
}
}
@@ -2412,6 +2674,9 @@ static irqreturn_t wm8996_irq(int irq, void *data)
}
irq_val &= ~snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2_MASK);
+ if (!irq_val)
+ return IRQ_NONE;
+
snd_soc_write(codec, WM8996_INTERRUPT_STATUS_2, irq_val);
if (irq_val & (WM8996_DCS_DONE_01_EINT | WM8996_DCS_DONE_23_EINT)) {
@@ -2430,10 +2695,10 @@ static irqreturn_t wm8996_irq(int irq, void *data)
if (irq_val & WM8996_MICD_EINT)
wm8996_micd(codec);
- if (irq_val)
- return IRQ_HANDLED;
- else
- return IRQ_NONE;
+ if (irq_val & WM8996_HP_DONE_EINT)
+ wm8996_hpdet_irq(codec);
+
+ return IRQ_HANDLED;
}
static irqreturn_t wm8996_edge_irq(int irq, void *data)
@@ -2507,18 +2772,29 @@ static void wm8996_retune_mobile_pdata(struct snd_soc_codec *codec)
wm8996->retune_mobile_enum.max = wm8996->num_retune_mobile_texts;
wm8996->retune_mobile_enum.texts = wm8996->retune_mobile_texts;
- ret = snd_soc_add_controls(codec, controls, ARRAY_SIZE(controls));
+ ret = snd_soc_add_codec_controls(codec, controls, ARRAY_SIZE(controls));
if (ret != 0)
dev_err(codec->dev,
"Failed to add ReTune Mobile controls: %d\n", ret);
}
+static const struct regmap_config wm8996_regmap = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .max_register = WM8996_MAX_REGISTER,
+ .reg_defaults = wm8996_reg,
+ .num_reg_defaults = ARRAY_SIZE(wm8996_reg),
+ .volatile_reg = wm8996_volatile_register,
+ .readable_reg = wm8996_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
static int wm8996_probe(struct snd_soc_codec *codec)
{
int ret;
struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec);
struct i2c_client *i2c = to_i2c_client(codec->dev);
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int i, irq_flags;
wm8996->codec = codec;
@@ -2526,29 +2802,17 @@ static int wm8996_probe(struct snd_soc_codec *codec)
init_completion(&wm8996->dcs_done);
init_completion(&wm8996->fll_lock);
- dapm->idle_bias_off = true;
- dapm->bias_level = SND_SOC_BIAS_OFF;
+ codec->control_data = wm8996->regmap;
- ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_I2C);
+ ret = snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
goto err;
}
- for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
- wm8996->supplies[i].supply = wm8996_supply_names[i];
-
- ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8996->supplies),
- wm8996->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
- goto err;
- }
-
wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0;
wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1;
wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2;
- wm8996->disable_nb[3].notifier_call = wm8996_regulator_event_3;
/* This should really be moved into the regulator core */
for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) {
@@ -2561,50 +2825,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
}
}
- ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
- wm8996->supplies);
- if (ret != 0) {
- dev_err(codec->dev, "Failed to enable supplies: %d\n", ret);
- goto err_get;
- }
-
- if (wm8996->pdata.ldo_ena >= 0) {
- gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
- msleep(5);
- }
-
- ret = snd_soc_read(codec, WM8996_SOFTWARE_RESET);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to read ID register: %d\n", ret);
- goto err_enable;
- }
- if (ret != 0x8915) {
- dev_err(codec->dev, "Device is not a WM8996, ID %x\n", ret);
- ret = -EINVAL;
- goto err_enable;
- }
-
- ret = snd_soc_read(codec, WM8996_CHIP_REVISION);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to read device revision: %d\n",
- ret);
- goto err_enable;
- }
-
- dev_info(codec->dev, "revision %c\n",
- (ret & WM8996_CHIP_REV_MASK) + 'A');
-
- if (wm8996->pdata.ldo_ena >= 0) {
- gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
- } else {
- ret = wm8996_reset(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- goto err_enable;
- }
- }
-
- codec->cache_only = true;
+ regcache_cache_only(codec->control_data, true);
/* Apply platform data settings */
snd_soc_update_bits(codec, WM8996_LINE_INPUT_CONTROL,
@@ -2746,7 +2967,7 @@ static int wm8996_probe(struct snd_soc_codec *codec)
if (wm8996->pdata.num_retune_mobile_cfgs)
wm8996_retune_mobile_pdata(codec);
else
- snd_soc_add_controls(codec, wm8996_eq_controls,
+ snd_soc_add_codec_controls(codec, wm8996_eq_controls,
ARRAY_SIZE(wm8996_eq_controls));
/* If the TX LRCLK pins are not in LRCLK mode configure the
@@ -2762,10 +2983,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
WM8996_AIF2TX_LRCLK_MODE,
WM8996_AIF2TX_LRCLK_MODE);
- regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
-
- wm8996_init_gpio(codec);
-
if (i2c->irq) {
if (wm8996->pdata.irq_flags)
irq_flags = wm8996->pdata.irq_flags;
@@ -2803,13 +3020,6 @@ static int wm8996_probe(struct snd_soc_codec *codec)
return 0;
-err_enable:
- if (wm8996->pdata.ldo_ena >= 0)
- gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
-
- regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
-err_get:
- regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
err:
return ret;
}
@@ -2826,8 +3036,6 @@ static int wm8996_remove(struct snd_soc_codec *codec)
if (i2c->irq)
free_irq(i2c->irq, codec);
- wm8996_free_gpio(codec);
-
for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
regulator_unregister_notifier(wm8996->supplies[i].consumer,
&wm8996->disable_nb[i]);
@@ -2840,13 +3048,8 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
.probe = wm8996_probe,
.remove = wm8996_remove,
.set_bias_level = wm8996_set_bias_level,
+ .idle_bias_off = true,
.seq_notifier = wm8996_seq_notifier,
- .reg_cache_size = WM8996_MAX_REGISTER + 1,
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm8996_reg,
- .volatile_register = wm8996_volatile_register,
- .readable_register = wm8996_readable_register,
- .compress_type = SND_SOC_RBTREE_COMPRESSION,
.controls = wm8996_snd_controls,
.num_controls = ARRAY_SIZE(wm8996_snd_controls),
.dapm_widgets = wm8996_dapm_widgets,
@@ -2857,12 +3060,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8996 = {
};
#define WM8996_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
- SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000)
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
+ SNDRV_PCM_RATE_48000)
#define WM8996_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\
SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm8996_dai_ops = {
+static const struct snd_soc_dai_ops wm8996_dai_ops = {
.set_fmt = wm8996_set_fmt,
.hw_params = wm8996_hw_params,
.set_sysclk = wm8996_set_sysclk,
@@ -2877,6 +3081,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
.channels_max = 6,
.rates = WM8996_RATES,
.formats = WM8996_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF1 Capture",
@@ -2884,6 +3089,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
.channels_max = 6,
.rates = WM8996_RATES,
.formats = WM8996_FORMATS,
+ .sig_bits = 24,
},
.ops = &wm8996_dai_ops,
},
@@ -2895,6 +3101,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
.channels_max = 2,
.rates = WM8996_RATES,
.formats = WM8996_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.stream_name = "AIF2 Capture",
@@ -2902,6 +3109,7 @@ static struct snd_soc_dai_driver wm8996_dai[] = {
.channels_max = 2,
.rates = WM8996_RATES,
.formats = WM8996_FORMATS,
+ .sig_bits = 24,
},
.ops = &wm8996_dai_ops,
},
@@ -2911,13 +3119,16 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8996_priv *wm8996;
- int ret;
+ int ret, i;
+ unsigned int reg;
- wm8996 = kzalloc(sizeof(struct wm8996_priv), GFP_KERNEL);
+ wm8996 = devm_kzalloc(&i2c->dev, sizeof(struct wm8996_priv),
+ GFP_KERNEL);
if (wm8996 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm8996);
+ wm8996->dev = &i2c->dev;
if (dev_get_platdata(&i2c->dev))
memcpy(&wm8996->pdata, dev_get_platdata(&i2c->dev),
@@ -2933,19 +3144,86 @@ static __devinit int wm8996_i2c_probe(struct i2c_client *i2c,
}
}
+ for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++)
+ wm8996->supplies[i].supply = wm8996_supply_names[i];
+
+ ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8996->supplies),
+ wm8996->supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret);
+ goto err_gpio;
+ }
+
+ ret = regulator_bulk_enable(ARRAY_SIZE(wm8996->supplies),
+ wm8996->supplies);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret);
+ goto err_gpio;
+ }
+
+ if (wm8996->pdata.ldo_ena > 0) {
+ gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 1);
+ msleep(5);
+ }
+
+ wm8996->regmap = regmap_init_i2c(i2c, &wm8996_regmap);
+ if (IS_ERR(wm8996->regmap)) {
+ ret = PTR_ERR(wm8996->regmap);
+ dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+ goto err_enable;
+ }
+
+ ret = regmap_read(wm8996->regmap, WM8996_SOFTWARE_RESET, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read ID register: %d\n", ret);
+ goto err_regmap;
+ }
+ if (reg != 0x8915) {
+ dev_err(&i2c->dev, "Device is not a WM8996, ID %x\n", reg);
+ ret = -EINVAL;
+ goto err_regmap;
+ }
+
+ ret = regmap_read(wm8996->regmap, WM8996_CHIP_REVISION, &reg);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to read device revision: %d\n",
+ ret);
+ goto err_regmap;
+ }
+
+ dev_info(&i2c->dev, "revision %c\n",
+ (reg & WM8996_CHIP_REV_MASK) + 'A');
+
+ regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
+
+ ret = wm8996_reset(wm8996);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to issue reset\n");
+ goto err_regmap;
+ }
+
+ wm8996_init_gpio(wm8996);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm8996, wm8996_dai,
ARRAY_SIZE(wm8996_dai));
if (ret < 0)
- goto err_gpio;
+ goto err_gpiolib;
return ret;
+err_gpiolib:
+ wm8996_free_gpio(wm8996);
+err_regmap:
+ regmap_exit(wm8996->regmap);
+err_enable:
+ if (wm8996->pdata.ldo_ena > 0)
+ gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
+ regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies);
err_gpio:
if (wm8996->pdata.ldo_ena > 0)
gpio_free(wm8996->pdata.ldo_ena);
err:
- kfree(wm8996);
return ret;
}
@@ -2955,9 +3233,12 @@ static __devexit int wm8996_i2c_remove(struct i2c_client *client)
struct wm8996_priv *wm8996 = i2c_get_clientdata(client);
snd_soc_unregister_codec(&client->dev);
- if (wm8996->pdata.ldo_ena > 0)
+ wm8996_free_gpio(wm8996);
+ regmap_exit(wm8996->regmap);
+ if (wm8996->pdata.ldo_ena > 0) {
+ gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0);
gpio_free(wm8996->pdata.ldo_ena);
- kfree(i2c_get_clientdata(client));
+ }
return 0;
}
@@ -2977,25 +3258,7 @@ static struct i2c_driver wm8996_i2c_driver = {
.id_table = wm8996_i2c_id,
};
-static int __init wm8996_modinit(void)
-{
- int ret;
-
- ret = i2c_add_driver(&wm8996_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register WM8996 I2C driver: %d\n",
- ret);
- }
-
- return ret;
-}
-module_init(wm8996_modinit);
-
-static void __exit wm8996_exit(void)
-{
- i2c_del_driver(&wm8996_i2c_driver);
-}
-module_exit(wm8996_exit);
+module_i2c_driver(wm8996_i2c_driver);
MODULE_DESCRIPTION("ASoC WM8996 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm8996.h b/sound/soc/codecs/wm8996.h
index 0fde643194ce..de9ac3e44aec 100644
--- a/sound/soc/codecs/wm8996.h
+++ b/sound/soc/codecs/wm8996.h
@@ -1567,6 +1567,10 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack,
/*
* R257 (0x101) - Control Interface (1)
*/
+#define WM8996_REG_SYNC 0x8000 /* REG_SYNC */
+#define WM8996_REG_SYNC_MASK 0x8000 /* REG_SYNC */
+#define WM8996_REG_SYNC_SHIFT 15 /* REG_SYNC */
+#define WM8996_REG_SYNC_WIDTH 1 /* REG_SYNC */
#define WM8996_AUTO_INC 0x0004 /* AUTO_INC */
#define WM8996_AUTO_INC_MASK 0x0004 /* AUTO_INC */
#define WM8996_AUTO_INC_SHIFT 2 /* AUTO_INC */
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c
index a4691321f9b3..076c126ed9b1 100644
--- a/sound/soc/codecs/wm9081.c
+++ b/sound/soc/codecs/wm9081.c
@@ -18,7 +18,7 @@
#include <linux/device.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -30,69 +30,60 @@
#include <sound/wm9081.h>
#include "wm9081.h"
-static u16 wm9081_reg_defaults[] = {
- 0x0000, /* R0 - Software Reset */
- 0x0000, /* R1 */
- 0x00B9, /* R2 - Analogue Lineout */
- 0x00B9, /* R3 - Analogue Speaker PGA */
- 0x0001, /* R4 - VMID Control */
- 0x0068, /* R5 - Bias Control 1 */
- 0x0000, /* R6 */
- 0x0000, /* R7 - Analogue Mixer */
- 0x0000, /* R8 - Anti Pop Control */
- 0x01DB, /* R9 - Analogue Speaker 1 */
- 0x0018, /* R10 - Analogue Speaker 2 */
- 0x0180, /* R11 - Power Management */
- 0x0000, /* R12 - Clock Control 1 */
- 0x0038, /* R13 - Clock Control 2 */
- 0x4000, /* R14 - Clock Control 3 */
- 0x0000, /* R15 */
- 0x0000, /* R16 - FLL Control 1 */
- 0x0200, /* R17 - FLL Control 2 */
- 0x0000, /* R18 - FLL Control 3 */
- 0x0204, /* R19 - FLL Control 4 */
- 0x0000, /* R20 - FLL Control 5 */
- 0x0000, /* R21 */
- 0x0000, /* R22 - Audio Interface 1 */
- 0x0002, /* R23 - Audio Interface 2 */
- 0x0008, /* R24 - Audio Interface 3 */
- 0x0022, /* R25 - Audio Interface 4 */
- 0x0000, /* R26 - Interrupt Status */
- 0x0006, /* R27 - Interrupt Status Mask */
- 0x0000, /* R28 - Interrupt Polarity */
- 0x0000, /* R29 - Interrupt Control */
- 0x00C0, /* R30 - DAC Digital 1 */
- 0x0008, /* R31 - DAC Digital 2 */
- 0x09AF, /* R32 - DRC 1 */
- 0x4201, /* R33 - DRC 2 */
- 0x0000, /* R34 - DRC 3 */
- 0x0000, /* R35 - DRC 4 */
- 0x0000, /* R36 */
- 0x0000, /* R37 */
- 0x0000, /* R38 - Write Sequencer 1 */
- 0x0000, /* R39 - Write Sequencer 2 */
- 0x0002, /* R40 - MW Slave 1 */
- 0x0000, /* R41 */
- 0x0000, /* R42 - EQ 1 */
- 0x0000, /* R43 - EQ 2 */
- 0x0FCA, /* R44 - EQ 3 */
- 0x0400, /* R45 - EQ 4 */
- 0x00B8, /* R46 - EQ 5 */
- 0x1EB5, /* R47 - EQ 6 */
- 0xF145, /* R48 - EQ 7 */
- 0x0B75, /* R49 - EQ 8 */
- 0x01C5, /* R50 - EQ 9 */
- 0x169E, /* R51 - EQ 10 */
- 0xF829, /* R52 - EQ 11 */
- 0x07AD, /* R53 - EQ 12 */
- 0x1103, /* R54 - EQ 13 */
- 0x1C58, /* R55 - EQ 14 */
- 0xF373, /* R56 - EQ 15 */
- 0x0A54, /* R57 - EQ 16 */
- 0x0558, /* R58 - EQ 17 */
- 0x0564, /* R59 - EQ 18 */
- 0x0559, /* R60 - EQ 19 */
- 0x4000, /* R61 - EQ 20 */
+static struct reg_default wm9081_reg[] = {
+ { 2, 0x00B9 }, /* R2 - Analogue Lineout */
+ { 3, 0x00B9 }, /* R3 - Analogue Speaker PGA */
+ { 4, 0x0001 }, /* R4 - VMID Control */
+ { 5, 0x0068 }, /* R5 - Bias Control 1 */
+ { 7, 0x0000 }, /* R7 - Analogue Mixer */
+ { 8, 0x0000 }, /* R8 - Anti Pop Control */
+ { 9, 0x01DB }, /* R9 - Analogue Speaker 1 */
+ { 10, 0x0018 }, /* R10 - Analogue Speaker 2 */
+ { 11, 0x0180 }, /* R11 - Power Management */
+ { 12, 0x0000 }, /* R12 - Clock Control 1 */
+ { 13, 0x0038 }, /* R13 - Clock Control 2 */
+ { 14, 0x4000 }, /* R14 - Clock Control 3 */
+ { 16, 0x0000 }, /* R16 - FLL Control 1 */
+ { 17, 0x0200 }, /* R17 - FLL Control 2 */
+ { 18, 0x0000 }, /* R18 - FLL Control 3 */
+ { 19, 0x0204 }, /* R19 - FLL Control 4 */
+ { 20, 0x0000 }, /* R20 - FLL Control 5 */
+ { 22, 0x0000 }, /* R22 - Audio Interface 1 */
+ { 23, 0x0002 }, /* R23 - Audio Interface 2 */
+ { 24, 0x0008 }, /* R24 - Audio Interface 3 */
+ { 25, 0x0022 }, /* R25 - Audio Interface 4 */
+ { 27, 0x0006 }, /* R27 - Interrupt Status Mask */
+ { 28, 0x0000 }, /* R28 - Interrupt Polarity */
+ { 29, 0x0000 }, /* R29 - Interrupt Control */
+ { 30, 0x00C0 }, /* R30 - DAC Digital 1 */
+ { 31, 0x0008 }, /* R31 - DAC Digital 2 */
+ { 32, 0x09AF }, /* R32 - DRC 1 */
+ { 33, 0x4201 }, /* R33 - DRC 2 */
+ { 34, 0x0000 }, /* R34 - DRC 3 */
+ { 35, 0x0000 }, /* R35 - DRC 4 */
+ { 38, 0x0000 }, /* R38 - Write Sequencer 1 */
+ { 39, 0x0000 }, /* R39 - Write Sequencer 2 */
+ { 40, 0x0002 }, /* R40 - MW Slave 1 */
+ { 42, 0x0000 }, /* R42 - EQ 1 */
+ { 43, 0x0000 }, /* R43 - EQ 2 */
+ { 44, 0x0FCA }, /* R44 - EQ 3 */
+ { 45, 0x0400 }, /* R45 - EQ 4 */
+ { 46, 0x00B8 }, /* R46 - EQ 5 */
+ { 47, 0x1EB5 }, /* R47 - EQ 6 */
+ { 48, 0xF145 }, /* R48 - EQ 7 */
+ { 49, 0x0B75 }, /* R49 - EQ 8 */
+ { 50, 0x01C5 }, /* R50 - EQ 9 */
+ { 51, 0x169E }, /* R51 - EQ 10 */
+ { 52, 0xF829 }, /* R52 - EQ 11 */
+ { 53, 0x07AD }, /* R53 - EQ 12 */
+ { 54, 0x1103 }, /* R54 - EQ 13 */
+ { 55, 0x1C58 }, /* R55 - EQ 14 */
+ { 56, 0xF373 }, /* R56 - EQ 15 */
+ { 57, 0x0A54 }, /* R57 - EQ 16 */
+ { 58, 0x0558 }, /* R58 - EQ 17 */
+ { 59, 0x0564 }, /* R59 - EQ 18 */
+ { 60, 0x0559 }, /* R60 - EQ 19 */
+ { 61, 0x4000 }, /* R61 - EQ 20 */
};
static struct {
@@ -156,8 +147,7 @@ static struct {
};
struct wm9081_priv {
- enum snd_soc_control_type control_type;
- void *control_data;
+ struct regmap *regmap;
int sysclk_source;
int mclk_rate;
int sysclk_rate;
@@ -170,19 +160,84 @@ struct wm9081_priv {
struct wm9081_pdata pdata;
};
-static int wm9081_volatile_register(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm9081_volatile_register(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM9081_SOFTWARE_RESET:
- return 1;
+ case WM9081_INTERRUPT_STATUS:
+ return true;
default:
- return 0;
+ return false;
}
}
-static int wm9081_reset(struct snd_soc_codec *codec)
+static bool wm9081_readable_register(struct device *dev, unsigned int reg)
{
- return snd_soc_write(codec, WM9081_SOFTWARE_RESET, 0);
+ switch (reg) {
+ case WM9081_SOFTWARE_RESET:
+ case WM9081_ANALOGUE_LINEOUT:
+ case WM9081_ANALOGUE_SPEAKER_PGA:
+ case WM9081_VMID_CONTROL:
+ case WM9081_BIAS_CONTROL_1:
+ case WM9081_ANALOGUE_MIXER:
+ case WM9081_ANTI_POP_CONTROL:
+ case WM9081_ANALOGUE_SPEAKER_1:
+ case WM9081_ANALOGUE_SPEAKER_2:
+ case WM9081_POWER_MANAGEMENT:
+ case WM9081_CLOCK_CONTROL_1:
+ case WM9081_CLOCK_CONTROL_2:
+ case WM9081_CLOCK_CONTROL_3:
+ case WM9081_FLL_CONTROL_1:
+ case WM9081_FLL_CONTROL_2:
+ case WM9081_FLL_CONTROL_3:
+ case WM9081_FLL_CONTROL_4:
+ case WM9081_FLL_CONTROL_5:
+ case WM9081_AUDIO_INTERFACE_1:
+ case WM9081_AUDIO_INTERFACE_2:
+ case WM9081_AUDIO_INTERFACE_3:
+ case WM9081_AUDIO_INTERFACE_4:
+ case WM9081_INTERRUPT_STATUS:
+ case WM9081_INTERRUPT_STATUS_MASK:
+ case WM9081_INTERRUPT_POLARITY:
+ case WM9081_INTERRUPT_CONTROL:
+ case WM9081_DAC_DIGITAL_1:
+ case WM9081_DAC_DIGITAL_2:
+ case WM9081_DRC_1:
+ case WM9081_DRC_2:
+ case WM9081_DRC_3:
+ case WM9081_DRC_4:
+ case WM9081_WRITE_SEQUENCER_1:
+ case WM9081_WRITE_SEQUENCER_2:
+ case WM9081_MW_SLAVE_1:
+ case WM9081_EQ_1:
+ case WM9081_EQ_2:
+ case WM9081_EQ_3:
+ case WM9081_EQ_4:
+ case WM9081_EQ_5:
+ case WM9081_EQ_6:
+ case WM9081_EQ_7:
+ case WM9081_EQ_8:
+ case WM9081_EQ_9:
+ case WM9081_EQ_10:
+ case WM9081_EQ_11:
+ case WM9081_EQ_12:
+ case WM9081_EQ_13:
+ case WM9081_EQ_14:
+ case WM9081_EQ_15:
+ case WM9081_EQ_16:
+ case WM9081_EQ_17:
+ case WM9081_EQ_18:
+ case WM9081_EQ_19:
+ case WM9081_EQ_20:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static int wm9081_reset(struct regmap *map)
+{
+ return regmap_write(map, WM9081_SOFTWARE_RESET, 0x9081);
}
static const DECLARE_TLV_DB_SCALE(drc_in_tlv, -4500, 75, 0);
@@ -737,6 +792,7 @@ SND_SOC_DAPM_SUPPLY("CLK_SYS", WM9081_CLOCK_CONTROL_3, 0, 0, clk_sys_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
SND_SOC_DAPM_SUPPLY("CLK_DSP", WM9081_CLOCK_CONTROL_3, 1, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("TOCLK", WM9081_CLOCK_CONTROL_3, 2, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("TSENSE", WM9081_POWER_MANAGEMENT, 7, 0, NULL, 0),
};
@@ -759,6 +815,7 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
{ "Speaker PGA", NULL, "CLK_SYS" },
{ "Speaker", NULL, "Speaker PGA" },
+ { "Speaker", NULL, "TSENSE" },
{ "SPKN", NULL, "Speaker" },
{ "SPKP", NULL, "Speaker" },
@@ -767,7 +824,7 @@ static const struct snd_soc_dapm_route wm9081_audio_paths[] = {
static int wm9081_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 reg;
+ struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
switch (level) {
case SND_SOC_BIAS_ON:
@@ -775,76 +832,73 @@ static int wm9081_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_PREPARE:
/* VMID=2*40k */
- reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
- reg &= ~WM9081_VMID_SEL_MASK;
- reg |= 0x2;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+ snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+ WM9081_VMID_SEL_MASK, 0x2);
/* Normal bias current */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg &= ~WM9081_STBY_BIAS_ENA;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+ WM9081_STBY_BIAS_ENA, 0);
break;
case SND_SOC_BIAS_STANDBY:
/* Initial cold start */
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
+ regcache_cache_only(wm9081->regmap, false);
+ regcache_sync(wm9081->regmap);
+
/* Disable LINEOUT discharge */
- reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
- reg &= ~WM9081_LINEOUT_DISCH;
- snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
+ snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
+ WM9081_LINEOUT_DISCH, 0);
/* Select startup bias source */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg |= WM9081_BIAS_SRC | WM9081_BIAS_ENA;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+ WM9081_BIAS_SRC | WM9081_BIAS_ENA,
+ WM9081_BIAS_SRC | WM9081_BIAS_ENA);
/* VMID 2*4k; Soft VMID ramp enable */
- reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
- reg |= WM9081_VMID_RAMP | 0x6;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+ snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+ WM9081_VMID_RAMP |
+ WM9081_VMID_SEL_MASK,
+ WM9081_VMID_RAMP | 0x6);
mdelay(100);
/* Normal bias enable & soft start off */
- reg |= WM9081_BIAS_ENA;
- reg &= ~WM9081_VMID_RAMP;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+ snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+ WM9081_VMID_RAMP, 0);
/* Standard bias source */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg &= ~WM9081_BIAS_SRC;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+ WM9081_BIAS_SRC, 0);
}
/* VMID 2*240k */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg &= ~WM9081_VMID_SEL_MASK;
- reg |= 0x40;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+ snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+ WM9081_VMID_SEL_MASK, 0x04);
/* Standby bias current on */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg |= WM9081_STBY_BIAS_ENA;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+ WM9081_STBY_BIAS_ENA,
+ WM9081_STBY_BIAS_ENA);
break;
case SND_SOC_BIAS_OFF:
- /* Startup bias source */
- reg = snd_soc_read(codec, WM9081_BIAS_CONTROL_1);
- reg |= WM9081_BIAS_SRC;
- snd_soc_write(codec, WM9081_BIAS_CONTROL_1, reg);
+ /* Startup bias source and disable bias */
+ snd_soc_update_bits(codec, WM9081_BIAS_CONTROL_1,
+ WM9081_BIAS_SRC | WM9081_BIAS_ENA,
+ WM9081_BIAS_SRC);
- /* Disable VMID and biases with soft ramping */
- reg = snd_soc_read(codec, WM9081_VMID_CONTROL);
- reg &= ~(WM9081_VMID_SEL_MASK | WM9081_BIAS_ENA);
- reg |= WM9081_VMID_RAMP;
- snd_soc_write(codec, WM9081_VMID_CONTROL, reg);
+ /* Disable VMID with soft ramping */
+ snd_soc_update_bits(codec, WM9081_VMID_CONTROL,
+ WM9081_VMID_RAMP | WM9081_VMID_SEL_MASK,
+ WM9081_VMID_RAMP);
/* Actively discharge LINEOUT */
- reg = snd_soc_read(codec, WM9081_ANTI_POP_CONTROL);
- reg |= WM9081_LINEOUT_DISCH;
- snd_soc_write(codec, WM9081_ANTI_POP_CONTROL, reg);
+ snd_soc_update_bits(codec, WM9081_ANTI_POP_CONTROL,
+ WM9081_LINEOUT_DISCH,
+ WM9081_LINEOUT_DISCH);
+
+ regcache_cache_only(wm9081->regmap, true);
break;
}
@@ -1120,8 +1174,8 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute)
return 0;
}
-static int wm9081_set_sysclk(struct snd_soc_codec *codec,
- int clk_id, unsigned int freq, int dir)
+static int wm9081_set_sysclk(struct snd_soc_codec *codec, int clk_id,
+ int source, unsigned int freq, int dir)
{
struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
@@ -1185,7 +1239,7 @@ static int wm9081_set_tdm_slot(struct snd_soc_dai *dai,
(SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops wm9081_dai_ops = {
+static const struct snd_soc_dai_ops wm9081_dai_ops = {
.hw_params = wm9081_hw_params,
.set_fmt = wm9081_set_dai_fmt,
.digital_mute = wm9081_digital_mute,
@@ -1211,51 +1265,25 @@ static int wm9081_probe(struct snd_soc_codec *codec)
{
struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec);
int ret;
- u16 reg;
- codec->control_data = wm9081->control_data;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm9081->control_type);
+ codec->control_data = wm9081->regmap;
+
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- reg = snd_soc_read(codec, WM9081_SOFTWARE_RESET);
- if (reg != 0x9081) {
- dev_err(codec->dev, "Device is not a WM9081: ID=0x%x\n", reg);
- ret = -EINVAL;
- return ret;
- }
-
- ret = wm9081_reset(codec);
- if (ret < 0) {
- dev_err(codec->dev, "Failed to issue reset\n");
- return ret;
- }
-
- reg = 0;
- if (wm9081->pdata.irq_high)
- reg |= WM9081_IRQ_POL;
- if (!wm9081->pdata.irq_cmos)
- reg |= WM9081_IRQ_OP_CTRL;
- snd_soc_update_bits(codec, WM9081_INTERRUPT_CONTROL,
- WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
-
- wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
/* Enable zero cross by default */
- reg = snd_soc_read(codec, WM9081_ANALOGUE_LINEOUT);
- snd_soc_write(codec, WM9081_ANALOGUE_LINEOUT, reg | WM9081_LINEOUTZC);
- reg = snd_soc_read(codec, WM9081_ANALOGUE_SPEAKER_PGA);
- snd_soc_write(codec, WM9081_ANALOGUE_SPEAKER_PGA,
- reg | WM9081_SPKPGAZC);
-
- snd_soc_add_controls(codec, wm9081_snd_controls,
- ARRAY_SIZE(wm9081_snd_controls));
+ snd_soc_update_bits(codec, WM9081_ANALOGUE_LINEOUT,
+ WM9081_LINEOUTZC, WM9081_LINEOUTZC);
+ snd_soc_update_bits(codec, WM9081_ANALOGUE_SPEAKER_PGA,
+ WM9081_SPKPGAZC, WM9081_SPKPGAZC);
+
if (!wm9081->pdata.num_retune_configs) {
dev_dbg(codec->dev,
"No ReTune Mobile data, using normal EQ\n");
- snd_soc_add_controls(codec, wm9081_eq_controls,
+ snd_soc_add_codec_controls(codec, wm9081_eq_controls,
ARRAY_SIZE(wm9081_eq_controls));
}
@@ -1268,85 +1296,108 @@ static int wm9081_remove(struct snd_soc_codec *codec)
return 0;
}
-#ifdef CONFIG_PM
-static int wm9081_suspend(struct snd_soc_codec *codec, pm_message_t state)
-{
- wm9081_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- return 0;
-}
-
-static int wm9081_resume(struct snd_soc_codec *codec)
-{
- u16 *reg_cache = codec->reg_cache;
- int i;
-
- for (i = 0; i < codec->driver->reg_cache_size; i++) {
- if (i == WM9081_SOFTWARE_RESET)
- continue;
-
- snd_soc_write(codec, i, reg_cache[i]);
- }
-
- wm9081_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- return 0;
-}
-#else
-#define wm9081_suspend NULL
-#define wm9081_resume NULL
-#endif
-
static struct snd_soc_codec_driver soc_codec_dev_wm9081 = {
.probe = wm9081_probe,
.remove = wm9081_remove,
- .suspend = wm9081_suspend,
- .resume = wm9081_resume,
.set_sysclk = wm9081_set_sysclk,
.set_bias_level = wm9081_set_bias_level,
- .reg_cache_size = ARRAY_SIZE(wm9081_reg_defaults),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm9081_reg_defaults,
- .volatile_register = wm9081_volatile_register,
+ .idle_bias_off = true,
+ .controls = wm9081_snd_controls,
+ .num_controls = ARRAY_SIZE(wm9081_snd_controls),
.dapm_widgets = wm9081_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(wm9081_dapm_widgets),
.dapm_routes = wm9081_audio_paths,
.num_dapm_routes = ARRAY_SIZE(wm9081_audio_paths),
};
+static const struct regmap_config wm9081_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = WM9081_MAX_REGISTER,
+ .reg_defaults = wm9081_reg,
+ .num_reg_defaults = ARRAY_SIZE(wm9081_reg),
+ .volatile_reg = wm9081_volatile_register,
+ .readable_reg = wm9081_readable_register,
+ .cache_type = REGCACHE_RBTREE,
+};
+
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
static __devinit int wm9081_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm9081_priv *wm9081;
+ unsigned int reg;
int ret;
- wm9081 = kzalloc(sizeof(struct wm9081_priv), GFP_KERNEL);
+ wm9081 = devm_kzalloc(&i2c->dev, sizeof(struct wm9081_priv),
+ GFP_KERNEL);
if (wm9081 == NULL)
return -ENOMEM;
i2c_set_clientdata(i2c, wm9081);
- wm9081->control_type = SND_SOC_I2C;
- wm9081->control_data = i2c;
+
+ wm9081->regmap = regmap_init_i2c(i2c, &wm9081_regmap);
+ if (IS_ERR(wm9081->regmap)) {
+ ret = PTR_ERR(wm9081->regmap);
+ dev_err(&i2c->dev, "regmap_init() failed: %d\n", ret);
+ goto err;
+ }
+
+ ret = regmap_read(wm9081->regmap, WM9081_SOFTWARE_RESET, &reg);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to read chip ID: %d\n", ret);
+ goto err_regmap;
+ }
+ if (reg != 0x9081) {
+ dev_err(&i2c->dev, "Device is not a WM9081: ID=0x%x\n", reg);
+ ret = -EINVAL;
+ goto err_regmap;
+ }
+
+ ret = wm9081_reset(wm9081->regmap);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "Failed to issue reset\n");
+ goto err_regmap;
+ }
if (dev_get_platdata(&i2c->dev))
memcpy(&wm9081->pdata, dev_get_platdata(&i2c->dev),
sizeof(wm9081->pdata));
+ reg = 0;
+ if (wm9081->pdata.irq_high)
+ reg |= WM9081_IRQ_POL;
+ if (!wm9081->pdata.irq_cmos)
+ reg |= WM9081_IRQ_OP_CTRL;
+ regmap_update_bits(wm9081->regmap, WM9081_INTERRUPT_CONTROL,
+ WM9081_IRQ_POL | WM9081_IRQ_OP_CTRL, reg);
+
+ regcache_cache_only(wm9081->regmap, true);
+
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm9081, &wm9081_dai, 1);
if (ret < 0)
- kfree(wm9081);
+ goto err_regmap;
+
+ return 0;
+
+err_regmap:
+ regmap_exit(wm9081->regmap);
+err:
+
return ret;
}
static __devexit int wm9081_i2c_remove(struct i2c_client *client)
{
+ struct wm9081_priv *wm9081 = i2c_get_clientdata(client);
+
snd_soc_unregister_codec(&client->dev);
- kfree(i2c_get_clientdata(client));
+ regmap_exit(wm9081->regmap);
return 0;
}
@@ -1367,28 +1418,7 @@ static struct i2c_driver wm9081_i2c_driver = {
};
#endif
-static int __init wm9081_modinit(void)
-{
- int ret = 0;
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- ret = i2c_add_driver(&wm9081_i2c_driver);
- if (ret != 0) {
- printk(KERN_ERR "Failed to register WM9081 I2C driver: %d\n",
- ret);
- }
-#endif
- return ret;
-}
-module_init(wm9081_modinit);
-
-static void __exit wm9081_exit(void)
-{
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_del_driver(&wm9081_i2c_driver);
-#endif
-}
-module_exit(wm9081_exit);
-
+module_i2c_driver(wm9081_i2c_driver);
MODULE_DESCRIPTION("ASoC WM9081 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c
index 4de12203e611..4b263b6edf13 100644
--- a/sound/soc/codecs/wm9090.c
+++ b/sound/soc/codecs/wm9090.c
@@ -25,6 +25,7 @@
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/delay.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <sound/initval.h>
#include <sound/soc.h>
@@ -33,118 +34,51 @@
#include "wm9090.h"
-static const u16 wm9090_reg_defaults[] = {
- 0x9093, /* R0 - Software Reset */
- 0x0006, /* R1 - Power Management (1) */
- 0x6000, /* R2 - Power Management (2) */
- 0x0000, /* R3 - Power Management (3) */
- 0x0000, /* R4 */
- 0x0000, /* R5 */
- 0x01C0, /* R6 - Clocking 1 */
- 0x0000, /* R7 */
- 0x0000, /* R8 */
- 0x0000, /* R9 */
- 0x0000, /* R10 */
- 0x0000, /* R11 */
- 0x0000, /* R12 */
- 0x0000, /* R13 */
- 0x0000, /* R14 */
- 0x0000, /* R15 */
- 0x0000, /* R16 */
- 0x0000, /* R17 */
- 0x0000, /* R18 */
- 0x0000, /* R19 */
- 0x0000, /* R20 */
- 0x0000, /* R21 */
- 0x0003, /* R22 - IN1 Line Control */
- 0x0003, /* R23 - IN2 Line Control */
- 0x0083, /* R24 - IN1 Line Input A Volume */
- 0x0083, /* R25 - IN1 Line Input B Volume */
- 0x0083, /* R26 - IN2 Line Input A Volume */
- 0x0083, /* R27 - IN2 Line Input B Volume */
- 0x002D, /* R28 - Left Output Volume */
- 0x002D, /* R29 - Right Output Volume */
- 0x0000, /* R30 */
- 0x0000, /* R31 */
- 0x0000, /* R32 */
- 0x0000, /* R33 */
- 0x0100, /* R34 - SPKMIXL Attenuation */
- 0x0000, /* R35 */
- 0x0010, /* R36 - SPKOUT Mixers */
- 0x0140, /* R37 - ClassD3 */
- 0x0039, /* R38 - Speaker Volume Left */
- 0x0000, /* R39 */
- 0x0000, /* R40 */
- 0x0000, /* R41 */
- 0x0000, /* R42 */
- 0x0000, /* R43 */
- 0x0000, /* R44 */
- 0x0000, /* R45 - Output Mixer1 */
- 0x0000, /* R46 - Output Mixer2 */
- 0x0100, /* R47 - Output Mixer3 */
- 0x0100, /* R48 - Output Mixer4 */
- 0x0000, /* R49 */
- 0x0000, /* R50 */
- 0x0000, /* R51 */
- 0x0000, /* R52 */
- 0x0000, /* R53 */
- 0x0000, /* R54 - Speaker Mixer */
- 0x0000, /* R55 */
- 0x0000, /* R56 */
- 0x000D, /* R57 - AntiPOP2 */
- 0x0000, /* R58 */
- 0x0000, /* R59 */
- 0x0000, /* R60 */
- 0x0000, /* R61 */
- 0x0000, /* R62 */
- 0x0000, /* R63 */
- 0x0000, /* R64 */
- 0x0000, /* R65 */
- 0x0000, /* R66 */
- 0x0000, /* R67 */
- 0x0000, /* R68 */
- 0x0000, /* R69 */
- 0x0000, /* R70 - Write Sequencer 0 */
- 0x0000, /* R71 - Write Sequencer 1 */
- 0x0000, /* R72 - Write Sequencer 2 */
- 0x0000, /* R73 - Write Sequencer 3 */
- 0x0000, /* R74 - Write Sequencer 4 */
- 0x0000, /* R75 - Write Sequencer 5 */
- 0x1F25, /* R76 - Charge Pump 1 */
- 0x0000, /* R77 */
- 0x0000, /* R78 */
- 0x0000, /* R79 */
- 0x0000, /* R80 */
- 0x0000, /* R81 */
- 0x0000, /* R82 */
- 0x0000, /* R83 */
- 0x0000, /* R84 - DC Servo 0 */
- 0x054A, /* R85 - DC Servo 1 */
- 0x0000, /* R86 */
- 0x0000, /* R87 - DC Servo 3 */
- 0x0000, /* R88 - DC Servo Readback 0 */
- 0x0000, /* R89 - DC Servo Readback 1 */
- 0x0000, /* R90 - DC Servo Readback 2 */
- 0x0000, /* R91 */
- 0x0000, /* R92 */
- 0x0000, /* R93 */
- 0x0000, /* R94 */
- 0x0000, /* R95 */
- 0x0100, /* R96 - Analogue HP 0 */
- 0x0000, /* R97 */
- 0x8640, /* R98 - AGC Control 0 */
- 0xC000, /* R99 - AGC Control 1 */
- 0x0200, /* R100 - AGC Control 2 */
+static const struct reg_default wm9090_reg_defaults[] = {
+ { 1, 0x0006 }, /* R1 - Power Management (1) */
+ { 2, 0x6000 }, /* R2 - Power Management (2) */
+ { 3, 0x0000 }, /* R3 - Power Management (3) */
+ { 6, 0x01C0 }, /* R6 - Clocking 1 */
+ { 22, 0x0003 }, /* R22 - IN1 Line Control */
+ { 23, 0x0003 }, /* R23 - IN2 Line Control */
+ { 24, 0x0083 }, /* R24 - IN1 Line Input A Volume */
+ { 25, 0x0083 }, /* R25 - IN1 Line Input B Volume */
+ { 26, 0x0083 }, /* R26 - IN2 Line Input A Volume */
+ { 27, 0x0083 }, /* R27 - IN2 Line Input B Volume */
+ { 28, 0x002D }, /* R28 - Left Output Volume */
+ { 29, 0x002D }, /* R29 - Right Output Volume */
+ { 34, 0x0100 }, /* R34 - SPKMIXL Attenuation */
+ { 35, 0x0010 }, /* R36 - SPKOUT Mixers */
+ { 37, 0x0140 }, /* R37 - ClassD3 */
+ { 38, 0x0039 }, /* R38 - Speaker Volume Left */
+ { 45, 0x0000 }, /* R45 - Output Mixer1 */
+ { 46, 0x0000 }, /* R46 - Output Mixer2 */
+ { 47, 0x0100 }, /* R47 - Output Mixer3 */
+ { 48, 0x0100 }, /* R48 - Output Mixer4 */
+ { 54, 0x0000 }, /* R54 - Speaker Mixer */
+ { 57, 0x000D }, /* R57 - AntiPOP2 */
+ { 70, 0x0000 }, /* R70 - Write Sequencer 0 */
+ { 71, 0x0000 }, /* R71 - Write Sequencer 1 */
+ { 72, 0x0000 }, /* R72 - Write Sequencer 2 */
+ { 73, 0x0000 }, /* R73 - Write Sequencer 3 */
+ { 74, 0x0000 }, /* R74 - Write Sequencer 4 */
+ { 75, 0x0000 }, /* R75 - Write Sequencer 5 */
+ { 76, 0x1F25 }, /* R76 - Charge Pump 1 */
+ { 85, 0x054A }, /* R85 - DC Servo 1 */
+ { 87, 0x0000 }, /* R87 - DC Servo 3 */
+ { 96, 0x0100 }, /* R96 - Analogue HP 0 */
+ { 98, 0x8640 }, /* R98 - AGC Control 0 */
+ { 99, 0xC000 }, /* R99 - AGC Control 1 */
+ { 100, 0x0200 }, /* R100 - AGC Control 2 */
};
/* This struct is used to save the context */
struct wm9090_priv {
- struct mutex mutex;
struct wm9090_platform_data pdata;
- void *control_data;
+ struct regmap *regmap;
};
-static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
+static bool wm9090_volatile(struct device *dev, unsigned int reg)
{
switch (reg) {
case WM9090_SOFTWARE_RESET:
@@ -152,10 +86,60 @@ static int wm9090_volatile(struct snd_soc_codec *codec, unsigned int reg)
case WM9090_DC_SERVO_READBACK_0:
case WM9090_DC_SERVO_READBACK_1:
case WM9090_DC_SERVO_READBACK_2:
- return 1;
+ return true;
default:
- return 0;
+ return false;
+ }
+}
+
+static bool wm9090_readable(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM9090_SOFTWARE_RESET:
+ case WM9090_POWER_MANAGEMENT_1:
+ case WM9090_POWER_MANAGEMENT_2:
+ case WM9090_POWER_MANAGEMENT_3:
+ case WM9090_CLOCKING_1:
+ case WM9090_IN1_LINE_CONTROL:
+ case WM9090_IN2_LINE_CONTROL:
+ case WM9090_IN1_LINE_INPUT_A_VOLUME:
+ case WM9090_IN1_LINE_INPUT_B_VOLUME:
+ case WM9090_IN2_LINE_INPUT_A_VOLUME:
+ case WM9090_IN2_LINE_INPUT_B_VOLUME:
+ case WM9090_LEFT_OUTPUT_VOLUME:
+ case WM9090_RIGHT_OUTPUT_VOLUME:
+ case WM9090_SPKMIXL_ATTENUATION:
+ case WM9090_SPKOUT_MIXERS:
+ case WM9090_CLASSD3:
+ case WM9090_SPEAKER_VOLUME_LEFT:
+ case WM9090_OUTPUT_MIXER1:
+ case WM9090_OUTPUT_MIXER2:
+ case WM9090_OUTPUT_MIXER3:
+ case WM9090_OUTPUT_MIXER4:
+ case WM9090_SPEAKER_MIXER:
+ case WM9090_ANTIPOP2:
+ case WM9090_WRITE_SEQUENCER_0:
+ case WM9090_WRITE_SEQUENCER_1:
+ case WM9090_WRITE_SEQUENCER_2:
+ case WM9090_WRITE_SEQUENCER_3:
+ case WM9090_WRITE_SEQUENCER_4:
+ case WM9090_WRITE_SEQUENCER_5:
+ case WM9090_CHARGE_PUMP_1:
+ case WM9090_DC_SERVO_0:
+ case WM9090_DC_SERVO_1:
+ case WM9090_DC_SERVO_3:
+ case WM9090_DC_SERVO_READBACK_0:
+ case WM9090_DC_SERVO_READBACK_1:
+ case WM9090_DC_SERVO_READBACK_2:
+ case WM9090_ANALOGUE_HP_0:
+ case WM9090_AGC_CONTROL_0:
+ case WM9090_AGC_CONTROL_1:
+ case WM9090_AGC_CONTROL_2:
+ return true;
+
+ default:
+ return false;
}
}
@@ -179,19 +163,19 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec)
}
static const unsigned int in_tlv[] = {
- TLV_DB_RANGE_HEAD(6),
+ TLV_DB_RANGE_HEAD(3),
0, 0, TLV_DB_SCALE_ITEM(-600, 0, 0),
1, 3, TLV_DB_SCALE_ITEM(-350, 350, 0),
4, 6, TLV_DB_SCALE_ITEM(600, 600, 0),
};
static const unsigned int mix_tlv[] = {
- TLV_DB_RANGE_HEAD(4),
+ TLV_DB_RANGE_HEAD(2),
0, 2, TLV_DB_SCALE_ITEM(-1200, 300, 0),
3, 3, TLV_DB_SCALE_ITEM(0, 0, 0),
};
static const DECLARE_TLV_DB_SCALE(out_tlv, -5700, 100, 0);
static const unsigned int spkboost_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+ TLV_DB_RANGE_HEAD(2),
0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
};
@@ -449,7 +433,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_add_controls(codec, wm9090_controls,
+ snd_soc_add_codec_controls(codec, wm9090_controls,
ARRAY_SIZE(wm9090_controls));
if (wm9090->pdata.lin1_diff) {
@@ -458,7 +442,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
} else {
snd_soc_dapm_add_routes(dapm, audio_map_in1_se,
ARRAY_SIZE(audio_map_in1_se));
- snd_soc_add_controls(codec, wm9090_in1_se_controls,
+ snd_soc_add_codec_controls(codec, wm9090_in1_se_controls,
ARRAY_SIZE(wm9090_in1_se_controls));
}
@@ -468,7 +452,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
} else {
snd_soc_dapm_add_routes(dapm, audio_map_in2_se,
ARRAY_SIZE(audio_map_in2_se));
- snd_soc_add_controls(codec, wm9090_in2_se_controls,
+ snd_soc_add_codec_controls(codec, wm9090_in2_se_controls,
ARRAY_SIZE(wm9090_in2_se_controls));
}
@@ -494,8 +478,7 @@ static int wm9090_add_controls(struct snd_soc_codec *codec)
static int wm9090_set_bias_level(struct snd_soc_codec *codec,
enum snd_soc_bias_level level)
{
- u16 *reg_cache = codec->reg_cache;
- int i, ret;
+ struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
switch (level) {
case SND_SOC_BIAS_ON:
@@ -515,18 +498,7 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
case SND_SOC_BIAS_STANDBY:
if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) {
/* Restore the register cache */
- for (i = 1; i < codec->driver->reg_cache_size; i++) {
- if (reg_cache[i] == wm9090_reg_defaults[i])
- continue;
- if (wm9090_volatile(codec, i))
- continue;
-
- ret = snd_soc_write(codec, i, reg_cache[i]);
- if (ret != 0)
- dev_warn(codec->dev,
- "Failed to restore register %d: %d\n",
- i, ret);
- }
+ regcache_sync(wm9090->regmap);
}
/* We keep VMID off during standby since the combination of
@@ -550,28 +522,16 @@ static int wm9090_set_bias_level(struct snd_soc_codec *codec,
static int wm9090_probe(struct snd_soc_codec *codec)
{
- struct wm9090_priv *wm9090 = snd_soc_codec_get_drvdata(codec);
+ struct wm9090_priv *wm9090 = dev_get_drvdata(codec->dev);
int ret;
- codec->control_data = wm9090->control_data;
- ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C);
+ codec->control_data = wm9090->regmap;
+ ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_REGMAP);
if (ret != 0) {
dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret);
return ret;
}
- ret = snd_soc_read(codec, WM9090_SOFTWARE_RESET);
- if (ret < 0)
- return ret;
- if (ret != wm9090_reg_defaults[WM9090_SOFTWARE_RESET]) {
- dev_err(codec->dev, "Device is not a WM9090, ID=%x\n", ret);
- return -EINVAL;
- }
-
- ret = snd_soc_write(codec, WM9090_SOFTWARE_RESET, 0);
- if (ret < 0)
- return ret;
-
/* Configure some defaults; they will be written out when we
* bring the bias up.
*/
@@ -608,7 +568,7 @@ static int wm9090_probe(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int wm9090_suspend(struct snd_soc_codec *codec, pm_message_t state)
+static int wm9090_suspend(struct snd_soc_codec *codec)
{
wm9090_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -639,36 +599,72 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9090 = {
.suspend = wm9090_suspend,
.resume = wm9090_resume,
.set_bias_level = wm9090_set_bias_level,
- .reg_cache_size = (WM9090_MAX_REGISTER + 1),
- .reg_word_size = sizeof(u16),
- .reg_cache_default = wm9090_reg_defaults,
- .volatile_register = wm9090_volatile,
};
+static const struct regmap_config wm9090_regmap = {
+ .reg_bits = 8,
+ .val_bits = 16,
+
+ .max_register = WM9090_MAX_REGISTER,
+ .volatile_reg = wm9090_volatile,
+ .readable_reg = wm9090_readable,
+
+ .cache_type = REGCACHE_RBTREE,
+ .reg_defaults = wm9090_reg_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm9090_reg_defaults),
+};
+
+
static int wm9090_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm9090_priv *wm9090;
+ unsigned int reg;
int ret;
- wm9090 = kzalloc(sizeof(*wm9090), GFP_KERNEL);
+ wm9090 = devm_kzalloc(&i2c->dev, sizeof(*wm9090), GFP_KERNEL);
if (wm9090 == NULL) {
dev_err(&i2c->dev, "Can not allocate memory\n");
return -ENOMEM;
}
+ wm9090->regmap = regmap_init_i2c(i2c, &wm9090_regmap);
+ if (IS_ERR(wm9090->regmap)) {
+ ret = PTR_ERR(wm9090->regmap);
+ dev_err(&i2c->dev, "Failed to allocate regmap: %d\n", ret);
+ return ret;
+ }
+
+ ret = regmap_read(wm9090->regmap, WM9090_SOFTWARE_RESET, &reg);
+ if (ret < 0)
+ goto err;
+ if (reg != 0x9093) {
+ dev_err(&i2c->dev, "Device is not a WM9090, ID=%x\n", reg);
+ ret = -ENODEV;
+ goto err;
+ }
+
+ ret = regmap_write(wm9090->regmap, WM9090_SOFTWARE_RESET, 0);
+ if (ret < 0)
+ goto err;
+
if (i2c->dev.platform_data)
memcpy(&wm9090->pdata, i2c->dev.platform_data,
sizeof(wm9090->pdata));
i2c_set_clientdata(i2c, wm9090);
- wm9090->control_data = i2c;
- mutex_init(&wm9090->mutex);
ret = snd_soc_register_codec(&i2c->dev,
&soc_codec_dev_wm9090, NULL, 0);
- if (ret < 0)
- kfree(wm9090);
+ if (ret != 0) {
+ dev_err(&i2c->dev, "Failed to register CODEC: %d\n", ret);
+ goto err;
+ }
+
+ return 0;
+
+err:
+ regmap_exit(wm9090->regmap);
return ret;
}
@@ -677,20 +673,21 @@ static int __devexit wm9090_i2c_remove(struct i2c_client *i2c)
struct wm9090_priv *wm9090 = i2c_get_clientdata(i2c);
snd_soc_unregister_codec(&i2c->dev);
- kfree(wm9090);
+ regmap_exit(wm9090->regmap);
return 0;
}
static const struct i2c_device_id wm9090_id[] = {
{ "wm9090", 0 },
+ { "wm9093", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, wm9090_id);
static struct i2c_driver wm9090_i2c_driver = {
.driver = {
- .name = "wm9090-codec",
+ .name = "wm9090",
.owner = THIS_MODULE,
},
.probe = wm9090_i2c_probe,
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c
index 646b58dda849..cacc6a86b46f 100644
--- a/sound/soc/codecs/wm9705.c
+++ b/sound/soc/codecs/wm9705.c
@@ -258,7 +258,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
-static struct snd_soc_dai_ops wm9705_dai_ops = {
+static const struct snd_soc_dai_ops wm9705_dai_ops = {
.prepare = ac97_prepare,
};
@@ -306,7 +306,7 @@ static int wm9705_reset(struct snd_soc_codec *codec)
}
#ifdef CONFIG_PM
-static int wm9705_soc_suspend(struct snd_soc_codec *codec, pm_message_t msg)
+static int wm9705_soc_suspend(struct snd_soc_codec *codec)
{
soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff);
@@ -351,7 +351,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec)
if (ret)
goto reset_err;
- snd_soc_add_controls(codec, wm9705_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls,
ARRAY_SIZE(wm9705_snd_ac97_controls));
return 0;
@@ -406,17 +406,7 @@ static struct platform_driver wm9705_codec_driver = {
.remove = __devexit_p(wm9705_remove),
};
-static int __init wm9705_init(void)
-{
- return platform_driver_register(&wm9705_codec_driver);
-}
-module_init(wm9705_init);
-
-static void __exit wm9705_exit(void)
-{
- platform_driver_unregister(&wm9705_codec_driver);
-}
-module_exit(wm9705_exit);
+module_platform_driver(wm9705_codec_driver);
MODULE_DESCRIPTION("ASoC WM9705 driver");
MODULE_AUTHOR("Ian Molton");
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index 90117f8156e8..b342ae50bcd6 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -20,10 +20,9 @@
#include <sound/ac97_codec.h>
#include <sound/initval.h>
#include <sound/soc.h>
+#include <sound/tlv.h>
#include "wm9712.h"
-#define WM9712_VERSION "0.4"
-
static unsigned int ac97_read(struct snd_soc_codec *codec,
unsigned int reg);
static int ac97_write(struct snd_soc_codec *codec,
@@ -71,6 +70,9 @@ static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
static const char *wm9712_diff_sel[] = {"Mic", "Line"};
+static const DECLARE_TLV_DB_SCALE(main_tlv, -3450, 150, 0);
+static const DECLARE_TLV_DB_SCALE(boost_tlv, 0, 2000, 0);
+
static const struct soc_enum wm9712_enum[] = {
SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
@@ -149,9 +151,9 @@ SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
-SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
-SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
-SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
+SOC_SINGLE_TLV("Mic 1 Volume", AC97_MIC, 8, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv),
+SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv),
};
/* We have to create a fake left and right HP mixers because
@@ -505,11 +507,11 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 |\
SNDRV_PCM_RATE_48000)
-static struct snd_soc_dai_ops wm9712_dai_ops_hifi = {
+static const struct snd_soc_dai_ops wm9712_dai_ops_hifi = {
.prepare = ac97_prepare,
};
-static struct snd_soc_dai_ops wm9712_dai_ops_aux = {
+static const struct snd_soc_dai_ops wm9712_dai_ops_aux = {
.prepare = ac97_aux_prepare,
};
@@ -583,8 +585,7 @@ err:
return -EIO;
}
-static int wm9712_soc_suspend(struct snd_soc_codec *codec,
- pm_message_t state)
+static int wm9712_soc_suspend(struct snd_soc_codec *codec)
{
wm9712_set_bias_level(codec, SND_SOC_BIAS_OFF);
return 0;
@@ -620,8 +621,6 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
{
int ret = 0;
- printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
-
ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
if (ret < 0) {
printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
@@ -638,7 +637,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec)
ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- snd_soc_add_controls(codec, wm9712_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, wm9712_snd_ac97_controls,
ARRAY_SIZE(wm9712_snd_ac97_controls));
return 0;
@@ -694,17 +693,7 @@ static struct platform_driver wm9712_codec_driver = {
.remove = __devexit_p(wm9712_remove),
};
-static int __init wm9712_init(void)
-{
- return platform_driver_register(&wm9712_codec_driver);
-}
-module_init(wm9712_init);
-
-static void __exit wm9712_exit(void)
-{
- platform_driver_unregister(&wm9712_codec_driver);
-}
-module_exit(wm9712_exit);
+module_platform_driver(wm9712_codec_driver);
MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index 7167cb6787db..2d22cc70d536 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -1026,19 +1026,19 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
(SNDRV_PCM_FORMAT_S16_LE | SNDRV_PCM_FORMAT_S20_3LE | \
SNDRV_PCM_FORMAT_S24_LE)
-static struct snd_soc_dai_ops wm9713_dai_ops_hifi = {
+static const struct snd_soc_dai_ops wm9713_dai_ops_hifi = {
.prepare = ac97_hifi_prepare,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,
};
-static struct snd_soc_dai_ops wm9713_dai_ops_aux = {
+static const struct snd_soc_dai_ops wm9713_dai_ops_aux = {
.prepare = ac97_aux_prepare,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,
};
-static struct snd_soc_dai_ops wm9713_dai_ops_voice = {
+static const struct snd_soc_dai_ops wm9713_dai_ops_voice = {
.hw_params = wm9713_pcm_hw_params,
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,
@@ -1140,8 +1140,7 @@ static int wm9713_set_bias_level(struct snd_soc_codec *codec,
return 0;
}
-static int wm9713_soc_suspend(struct snd_soc_codec *codec,
- pm_message_t state)
+static int wm9713_soc_suspend(struct snd_soc_codec *codec)
{
u16 reg;
@@ -1217,7 +1216,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec)
reg = ac97_read(codec, AC97_CD) & 0x7fff;
ac97_write(codec, AC97_CD, reg);
- snd_soc_add_controls(codec, wm9713_snd_ac97_controls,
+ snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls,
ARRAY_SIZE(wm9713_snd_ac97_controls));
return 0;
@@ -1277,17 +1276,7 @@ static struct platform_driver wm9713_codec_driver = {
.remove = __devexit_p(wm9713_remove),
};
-static int __init wm9713_init(void)
-{
- return platform_driver_register(&wm9713_codec_driver);
-}
-module_init(wm9713_init);
-
-static void __exit wm9713_exit(void)
-{
- platform_driver_unregister(&wm9713_codec_driver);
-}
-module_exit(wm9713_exit);
+module_platform_driver(wm9713_codec_driver);
MODULE_DESCRIPTION("ASoC WM9713/WM9714 driver");
MODULE_AUTHOR("Liam Girdwood");
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c
index e763c54c55dc..f13f2886339c 100644
--- a/sound/soc/codecs/wm_hubs.c
+++ b/sound/soc/codecs/wm_hubs.c
@@ -17,7 +17,7 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/i2c.h>
-#include <linux/platform_device.h>
+#include <linux/mfd/wm8994/registers.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -39,7 +39,7 @@ static const DECLARE_TLV_DB_SCALE(outmix_tlv, -2100, 300, 0);
static const DECLARE_TLV_DB_SCALE(spkmixout_tlv, -1800, 600, 1);
static const DECLARE_TLV_DB_SCALE(outpga_tlv, -5700, 100, 0);
static const unsigned int spkboost_tlv[] = {
- TLV_DB_RANGE_HEAD(7),
+ TLV_DB_RANGE_HEAD(2),
0, 6, TLV_DB_SCALE_ITEM(0, 150, 0),
7, 7, TLV_DB_SCALE_ITEM(1200, 0, 0),
};
@@ -116,14 +116,23 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
{
struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
s8 offset;
- u16 reg, reg_l, reg_r, dcs_cfg;
+ u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg;
+
+ switch (hubs->dcs_readback_mode) {
+ case 2:
+ dcs_reg = WM8994_DC_SERVO_4E;
+ break;
+ default:
+ dcs_reg = WM8993_DC_SERVO_3;
+ break;
+ }
/* If we're using a digital only path and have a previously
* callibrated DC servo offset stored then use that. */
if (hubs->class_w && hubs->class_w_dcs) {
dev_dbg(codec->dev, "Using cached DC servo offset %x\n",
hubs->class_w_dcs);
- snd_soc_write(codec, WM8993_DC_SERVO_3, hubs->class_w_dcs);
+ snd_soc_write(codec, dcs_reg, hubs->class_w_dcs);
wait_for_dc_servo(codec,
WM8993_DCS_TRIG_DAC_WR_0 |
WM8993_DCS_TRIG_DAC_WR_1);
@@ -154,38 +163,40 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2)
& WM8993_DCS_INTEG_CHAN_1_MASK;
break;
+ case 2:
case 1:
- reg = snd_soc_read(codec, WM8993_DC_SERVO_3);
+ reg = snd_soc_read(codec, dcs_reg);
reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK)
>> WM8993_DCS_DAC_WR_VAL_1_SHIFT;
reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK;
break;
default:
WARN(1, "Unknown DCS readback method\n");
- break;
+ return;
}
dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r);
/* Apply correction to DC servo result */
- if (hubs->dcs_codes) {
- dev_dbg(codec->dev, "Applying %d code DC servo correction\n",
- hubs->dcs_codes);
+ if (hubs->dcs_codes_l || hubs->dcs_codes_r) {
+ dev_dbg(codec->dev,
+ "Applying %d/%d code DC servo correction\n",
+ hubs->dcs_codes_l, hubs->dcs_codes_r);
/* HPOUT1R */
offset = reg_r;
- offset += hubs->dcs_codes;
+ offset += hubs->dcs_codes_r;
dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT;
/* HPOUT1L */
offset = reg_l;
- offset += hubs->dcs_codes;
+ offset += hubs->dcs_codes_l;
dcs_cfg |= (u8)offset;
dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg);
/* Do it */
- snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg);
+ snd_soc_write(codec, dcs_reg, dcs_cfg);
wait_for_dc_servo(codec,
WM8993_DCS_TRIG_DAC_WR_0 |
WM8993_DCS_TRIG_DAC_WR_1);
@@ -196,7 +207,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec)
/* Save the callibrated offset if we're in class W mode and
* therefore don't have any analogue signal mixed in. */
- if (hubs->class_w)
+ if (hubs->class_w && !hubs->no_cache_class_w)
hubs->class_w_dcs = dcs_cfg;
}
@@ -210,14 +221,14 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol,
struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
int ret;
- ret = snd_soc_put_volsw_2r(kcontrol, ucontrol);
+ ret = snd_soc_put_volsw(kcontrol, ucontrol);
/* Updating the analogue gains invalidates the DC servo cache */
hubs->class_w_dcs = 0;
/* If we're applying an offset correction then updating the
* callibration would be likely to introduce further offsets. */
- if (hubs->dcs_codes || hubs->no_series_update)
+ if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update)
return ret;
/* Only need to do this if the outputs are active */
@@ -350,19 +361,11 @@ SOC_DOUBLE_TLV("Speaker Boost Volume", WM8993_SPKOUT_BOOST, 3, 0, 7, 0,
SOC_ENUM("Speaker Reference", speaker_ref),
SOC_ENUM("Speaker Mode", speaker_mode),
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Headphone Volume",
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |
- SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .tlv.p = outpga_tlv,
- .info = snd_soc_info_volsw_2r,
- .get = snd_soc_get_volsw_2r, .put = wm8993_put_dc_servo,
- .private_value = (unsigned long)&(struct soc_mixer_control) {
- .reg = WM8993_LEFT_OUTPUT_VOLUME,
- .rreg = WM8993_RIGHT_OUTPUT_VOLUME,
- .shift = 0, .max = 63
- },
-},
+SOC_DOUBLE_R_EXT_TLV("Headphone Volume",
+ WM8993_LEFT_OUTPUT_VOLUME, WM8993_RIGHT_OUTPUT_VOLUME,
+ 0, 63, 0, snd_soc_get_volsw, wm8993_put_dc_servo,
+ outpga_tlv),
+
SOC_DOUBLE_R("Headphone Switch", WM8993_LEFT_OUTPUT_VOLUME,
WM8993_RIGHT_OUTPUT_VOLUME, 6, 1, 0),
SOC_DOUBLE_R("Headphone ZC Switch", WM8993_LEFT_OUTPUT_VOLUME,
@@ -497,6 +500,36 @@ static int earpiece_event(struct snd_soc_dapm_widget *w,
return 0;
}
+static int lineout_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *control, int event)
+{
+ struct snd_soc_codec *codec = w->codec;
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ bool *flag;
+
+ switch (w->shift) {
+ case WM8993_LINEOUT1N_ENA_SHIFT:
+ flag = &hubs->lineout1n_ena;
+ break;
+ case WM8993_LINEOUT1P_ENA_SHIFT:
+ flag = &hubs->lineout1p_ena;
+ break;
+ case WM8993_LINEOUT2N_ENA_SHIFT:
+ flag = &hubs->lineout2n_ena;
+ break;
+ case WM8993_LINEOUT2P_ENA_SHIFT:
+ flag = &hubs->lineout2p_ena;
+ break;
+ default:
+ WARN(1, "Unknown line output");
+ return -EINVAL;
+ }
+
+ *flag = SND_SOC_DAPM_EVENT_ON(event);
+
+ return 0;
+}
+
static const struct snd_kcontrol_new in1l_pga[] = {
SOC_DAPM_SINGLE("IN1LP Switch", WM8993_INPUT_MIXER2, 5, 1, 0),
SOC_DAPM_SINGLE("IN1LN Switch", WM8993_INPUT_MIXER2, 4, 1, 0),
@@ -583,14 +616,14 @@ SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER1, 0, 1, 0),
};
static const struct snd_kcontrol_new line2_mix[] = {
-SOC_DAPM_SINGLE("IN2R Switch", WM8993_LINE_MIXER2, 2, 1, 0),
-SOC_DAPM_SINGLE("IN2L Switch", WM8993_LINE_MIXER2, 1, 1, 0),
+SOC_DAPM_SINGLE("IN1L Switch", WM8993_LINE_MIXER2, 2, 1, 0),
+SOC_DAPM_SINGLE("IN1R Switch", WM8993_LINE_MIXER2, 1, 1, 0),
SOC_DAPM_SINGLE("Output Switch", WM8993_LINE_MIXER2, 0, 1, 0),
};
static const struct snd_kcontrol_new line2n_mix[] = {
-SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
-SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Left Output Switch", WM8993_LINE_MIXER2, 5, 1, 0),
+SOC_DAPM_SINGLE("Right Output Switch", WM8993_LINE_MIXER2, 6, 1, 0),
};
static const struct snd_kcontrol_new line2p_mix[] = {
@@ -607,8 +640,8 @@ SND_SOC_DAPM_INPUT("IN1RP"),
SND_SOC_DAPM_INPUT("IN2RN"),
SND_SOC_DAPM_INPUT("IN2RP:VXRP"),
-SND_SOC_DAPM_MICBIAS("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0),
-SND_SOC_DAPM_MICBIAS("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0),
+SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0),
SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0,
in1l_pga, ARRAY_SIZE(in1l_pga)),
@@ -635,9 +668,8 @@ SND_SOC_DAPM_PGA("Right Output PGA", WM8993_POWER_MANAGEMENT_3, 6, 0, NULL, 0),
SND_SOC_DAPM_SUPPLY("Headphone Supply", SND_SOC_NOPM, 0, 0, hp_supply_event,
SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD),
-SND_SOC_DAPM_PGA_E("Headphone PGA", SND_SOC_NOPM, 0, 0,
- NULL, 0,
- hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("Headphone PGA", SND_SOC_NOPM, 0, 0, NULL, 0,
+ hp_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_MIXER("Earpiece Mixer", SND_SOC_NOPM, 0, 0,
earpiece_mixer, ARRAY_SIZE(earpiece_mixer)),
@@ -650,10 +682,11 @@ SND_SOC_DAPM_MIXER("SPKL Boost", SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_MIXER("SPKR Boost", SND_SOC_NOPM, 0, 0,
right_speaker_boost, ARRAY_SIZE(right_speaker_boost)),
-SND_SOC_DAPM_PGA("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
- NULL, 0),
+SND_SOC_DAPM_SUPPLY("TSHUT", WM8993_POWER_MANAGEMENT_2, 14, 0, NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKL Driver", WM8993_POWER_MANAGEMENT_1, 12, 0,
+ NULL, 0),
+SND_SOC_DAPM_OUT_DRV("SPKR Driver", WM8993_POWER_MANAGEMENT_1, 13, 0,
+ NULL, 0),
SND_SOC_DAPM_MIXER("LINEOUT1 Mixer", SND_SOC_NOPM, 0, 0,
line1_mix, ARRAY_SIZE(line1_mix)),
@@ -669,14 +702,18 @@ SND_SOC_DAPM_MIXER("LINEOUT2N Mixer", SND_SOC_NOPM, 0, 0,
SND_SOC_DAPM_MIXER("LINEOUT2P Mixer", SND_SOC_NOPM, 0, 0,
line2p_mix, ARRAY_SIZE(line2p_mix)),
-SND_SOC_DAPM_PGA("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
- NULL, 0),
-SND_SOC_DAPM_PGA("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
- NULL, 0),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1N Driver", WM8993_POWER_MANAGEMENT_3, 13, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT1P Driver", WM8993_POWER_MANAGEMENT_3, 12, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2N Driver", WM8993_POWER_MANAGEMENT_3, 11, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
+SND_SOC_DAPM_OUT_DRV_E("LINEOUT2P Driver", WM8993_POWER_MANAGEMENT_3, 10, 0,
+ NULL, 0, lineout_event,
+ SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
SND_SOC_DAPM_OUTPUT("SPKOUTLP"),
SND_SOC_DAPM_OUTPUT("SPKOUTLN"),
@@ -699,6 +736,11 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
{ "IN1L PGA", "IN1LP Switch", "IN1LP" },
{ "IN1L PGA", "IN1LN Switch", "IN1LN" },
+ { "IN1L PGA", NULL, "VMID" },
+ { "IN1R PGA", NULL, "VMID" },
+ { "IN2L PGA", NULL, "VMID" },
+ { "IN2R PGA", NULL, "VMID" },
+
{ "IN1R PGA", "IN1RP Switch", "IN1RP" },
{ "IN1R PGA", "IN1RN Switch", "IN1RN" },
@@ -716,12 +758,14 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
{ "MIXINL", NULL, "Direct Voice" },
{ "MIXINL", NULL, "IN1LP" },
{ "MIXINL", NULL, "Left Output Mixer" },
+ { "MIXINL", NULL, "VMID" },
{ "MIXINR", "IN1R Switch", "IN1R PGA" },
{ "MIXINR", "IN2R Switch", "IN2R PGA" },
{ "MIXINR", NULL, "Direct Voice" },
{ "MIXINR", NULL, "IN1RP" },
{ "MIXINR", NULL, "Right Output Mixer" },
+ { "MIXINR", NULL, "VMID" },
{ "ADCL", NULL, "MIXINL" },
{ "ADCR", NULL, "MIXINR" },
@@ -752,6 +796,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
{ "Earpiece Mixer", "Left Output Switch", "Left Output PGA" },
{ "Earpiece Mixer", "Right Output Switch", "Right Output PGA" },
+ { "Earpiece Driver", NULL, "VMID" },
{ "Earpiece Driver", NULL, "Earpiece Mixer" },
{ "HPOUT2N", NULL, "Earpiece Driver" },
{ "HPOUT2P", NULL, "Earpiece Driver" },
@@ -774,11 +819,15 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
{ "SPKR Boost", "SPKR Switch", "SPKR" },
{ "SPKR Boost", "SPKL Switch", "SPKL" },
+ { "SPKL Driver", NULL, "VMID" },
{ "SPKL Driver", NULL, "SPKL Boost" },
{ "SPKL Driver", NULL, "CLK_SYS" },
+ { "SPKL Driver", NULL, "TSHUT" },
+ { "SPKR Driver", NULL, "VMID" },
{ "SPKR Driver", NULL, "SPKR Boost" },
{ "SPKR Driver", NULL, "CLK_SYS" },
+ { "SPKR Driver", NULL, "TSHUT" },
{ "SPKOUTLP", NULL, "SPKL Driver" },
{ "SPKOUTLN", NULL, "SPKL Driver" },
@@ -790,12 +839,18 @@ static const struct snd_soc_dapm_route analogue_routes[] = {
{ "Headphone PGA", NULL, "Left Headphone Mux" },
{ "Headphone PGA", NULL, "Right Headphone Mux" },
+ { "Headphone PGA", NULL, "VMID" },
{ "Headphone PGA", NULL, "CLK_SYS" },
{ "Headphone PGA", NULL, "Headphone Supply" },
{ "HPOUT1L", NULL, "Headphone PGA" },
{ "HPOUT1R", NULL, "Headphone PGA" },
+ { "LINEOUT1N Driver", NULL, "VMID" },
+ { "LINEOUT1P Driver", NULL, "VMID" },
+ { "LINEOUT2N Driver", NULL, "VMID" },
+ { "LINEOUT2P Driver", NULL, "VMID" },
+
{ "LINEOUT1N", NULL, "LINEOUT1N Driver" },
{ "LINEOUT1P", NULL, "LINEOUT1P Driver" },
{ "LINEOUT2N", NULL, "LINEOUT2N Driver" },
@@ -822,8 +877,8 @@ static const struct snd_soc_dapm_route lineout1_se_routes[] = {
};
static const struct snd_soc_dapm_route lineout2_diff_routes[] = {
- { "LINEOUT2 Mixer", "IN2L Switch", "IN2L PGA" },
- { "LINEOUT2 Mixer", "IN2R Switch", "IN2R PGA" },
+ { "LINEOUT2 Mixer", "IN1L Switch", "IN1L PGA" },
+ { "LINEOUT2 Mixer", "IN1R Switch", "IN1R PGA" },
{ "LINEOUT2 Mixer", "Output Switch", "Right Output PGA" },
{ "LINEOUT2N Driver", NULL, "LINEOUT2 Mixer" },
@@ -873,7 +928,7 @@ int wm_hubs_add_analogue_controls(struct snd_soc_codec *codec)
WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU,
WM8993_MIXOUTR_ZC | WM8993_MIXOUT_VU);
- snd_soc_add_controls(codec, analogue_snd_controls,
+ snd_soc_add_codec_controls(codec, analogue_snd_controls,
ARRAY_SIZE(analogue_snd_controls));
snd_soc_dapm_new_controls(dapm, analogue_dapm_widgets,
@@ -921,6 +976,11 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
int jd_scthr, int jd_thr, int micbias1_lvl,
int micbias2_lvl)
{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+
+ hubs->lineout1_se = !lineout1_diff;
+ hubs->lineout2_se = !lineout2_diff;
+
if (!lineout1_diff)
snd_soc_update_bits(codec, WM8993_LINE_MIXER1,
WM8993_LINEOUT1_MODE,
@@ -930,11 +990,10 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
WM8993_LINEOUT2_MODE,
WM8993_LINEOUT2_MODE);
- /* If the line outputs are differential then we aren't presenting
- * VMID as an output and can disable it.
- */
- if (lineout1_diff && lineout2_diff)
- codec->dapm.idle_bias_off = 1;
+ if (!lineout1_diff && !lineout2_diff)
+ snd_soc_update_bits(codec, WM8993_ANTIPOP1,
+ WM8993_LINEOUT_VMID_BUF_ENA,
+ WM8993_LINEOUT_VMID_BUF_ENA);
if (lineout1fb)
snd_soc_update_bits(codec, WM8993_ADDITIONAL_CONTROL,
@@ -956,6 +1015,69 @@ int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec,
}
EXPORT_SYMBOL_GPL(wm_hubs_handle_analogue_pdata);
+void wm_hubs_vmid_ena(struct snd_soc_codec *codec)
+{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ int val = 0;
+
+ if (hubs->lineout1_se)
+ val |= WM8993_LINEOUT1N_ENA | WM8993_LINEOUT1P_ENA;
+
+ if (hubs->lineout2_se)
+ val |= WM8993_LINEOUT2N_ENA | WM8993_LINEOUT2P_ENA;
+
+ /* Enable the line outputs while we power up */
+ snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3, val, val);
+}
+EXPORT_SYMBOL_GPL(wm_hubs_vmid_ena);
+
+void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level)
+{
+ struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec);
+ int val;
+
+ switch (level) {
+ case SND_SOC_BIAS_STANDBY:
+ /* Clamp the inputs to VMID while we ramp to charge caps */
+ snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+ WM8993_INPUTS_CLAMP, WM8993_INPUTS_CLAMP);
+ break;
+
+ case SND_SOC_BIAS_ON:
+ /* Turn off any unneded single ended outputs */
+ val = 0;
+
+ if (hubs->lineout1_se && hubs->lineout1n_ena)
+ val |= WM8993_LINEOUT1N_ENA;
+
+ if (hubs->lineout1_se && hubs->lineout1p_ena)
+ val |= WM8993_LINEOUT1P_ENA;
+
+ if (hubs->lineout2_se && hubs->lineout2n_ena)
+ val |= WM8993_LINEOUT2N_ENA;
+
+ if (hubs->lineout2_se && hubs->lineout2p_ena)
+ val |= WM8993_LINEOUT2P_ENA;
+
+ snd_soc_update_bits(codec, WM8993_POWER_MANAGEMENT_3,
+ WM8993_LINEOUT1N_ENA |
+ WM8993_LINEOUT1P_ENA |
+ WM8993_LINEOUT2N_ENA |
+ WM8993_LINEOUT2P_ENA,
+ val);
+
+ /* Remove the input clamps */
+ snd_soc_update_bits(codec, WM8993_INPUTS_CLAMP_REG,
+ WM8993_INPUTS_CLAMP, 0);
+ break;
+
+ default:
+ break;
+ }
+}
+EXPORT_SYMBOL_GPL(wm_hubs_set_bias_level);
+
MODULE_DESCRIPTION("Shared support for Wolfson hubs products");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h
index 676b1252ab91..5705276f4943 100644
--- a/sound/soc/codecs/wm_hubs.h
+++ b/sound/soc/codecs/wm_hubs.h
@@ -23,15 +23,25 @@ extern const unsigned int wm_hubs_spkmix_tlv[];
/* This *must* be the first element of the codec->private_data struct */
struct wm_hubs_data {
- int dcs_codes;
+ int dcs_codes_l;
+ int dcs_codes_r;
int dcs_readback_mode;
int hp_startup_mode;
int series_startup;
int no_series_update;
+ bool no_cache_class_w;
bool class_w;
u16 class_w_dcs;
+ bool lineout1_se;
+ bool lineout1n_ena;
+ bool lineout1p_ena;
+
+ bool lineout2_se;
+ bool lineout2n_ena;
+ bool lineout2p_ena;
+
bool dcs_done_irq;
struct completion dcs_done;
};
@@ -45,5 +55,8 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *,
int micbias1_lvl, int micbias2_lvl);
extern irqreturn_t wm_hubs_dcs_done(int irq, void *data);
+extern void wm_hubs_vmid_ena(struct snd_soc_codec *codec);
+extern void wm_hubs_set_bias_level(struct snd_soc_codec *codec,
+ enum snd_soc_bias_level level);
#endif
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index 6bbf001f6591..9e11a14d1b45 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -29,7 +29,6 @@ choice
prompt "DM365 codec select"
depends on SND_DAVINCI_SOC_EVM
depends on MACH_DAVINCI_DM365_EVM
- default SND_DM365_EXTERNAL_CODEC
config SND_DM365_AIC3X_CODEC
bool "Audio Codec - AIC3101"
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index fe7984221eb9..10a2d8c788b7 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -150,8 +150,6 @@ static int evm_aic3x_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
snd_soc_dapm_enable_pin(dapm, "Line In");
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -244,6 +242,7 @@ static struct snd_soc_dai_link da850_evm_dai = {
/* davinci dm6446 evm audio machine driver */
static struct snd_soc_card dm6446_snd_soc_card_evm = {
.name = "DaVinci DM6446 EVM",
+ .owner = THIS_MODULE,
.dai_link = &dm6446_evm_dai,
.num_links = 1,
};
@@ -251,6 +250,7 @@ static struct snd_soc_card dm6446_snd_soc_card_evm = {
/* davinci dm355 evm audio machine driver */
static struct snd_soc_card dm355_snd_soc_card_evm = {
.name = "DaVinci DM355 EVM",
+ .owner = THIS_MODULE,
.dai_link = &dm355_evm_dai,
.num_links = 1,
};
@@ -258,6 +258,7 @@ static struct snd_soc_card dm355_snd_soc_card_evm = {
/* davinci dm365 evm audio machine driver */
static struct snd_soc_card dm365_snd_soc_card_evm = {
.name = "DaVinci DM365 EVM",
+ .owner = THIS_MODULE,
.dai_link = &dm365_evm_dai,
.num_links = 1,
};
@@ -265,18 +266,21 @@ static struct snd_soc_card dm365_snd_soc_card_evm = {
/* davinci dm6467 evm audio machine driver */
static struct snd_soc_card dm6467_snd_soc_card_evm = {
.name = "DaVinci DM6467 EVM",
+ .owner = THIS_MODULE,
.dai_link = dm6467_evm_dai,
.num_links = ARRAY_SIZE(dm6467_evm_dai),
};
static struct snd_soc_card da830_snd_soc_card = {
.name = "DA830/OMAP-L137 EVM",
+ .owner = THIS_MODULE,
.dai_link = &da830_evm_dai,
.num_links = 1,
};
static struct snd_soc_card da850_snd_soc_card = {
.name = "DA850/OMAP-L138 EVM",
+ .owner = THIS_MODULE,
.dai_link = &da850_evm_dai,
.num_links = 1,
};
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index d0d60b8a54d4..0a74b9587a2c 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -265,6 +265,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
struct davinci_mcbsp_dev *dev = snd_soc_dai_get_drvdata(cpu_dai);
unsigned int pcr;
unsigned int srgr;
+ bool inv_fs = false;
/* Attention srgr is updated by hw_params! */
srgr = DAVINCI_MCBSP_SRGR_FSGM |
DAVINCI_MCBSP_SRGR_FPER(DEFAULT_BITPERSAMPLE * 2 - 1) |
@@ -330,7 +331,7 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
* more empty bit clock slots between channels as the sample
* rate is lowered.
*/
- fmt ^= SND_SOC_DAIFMT_NB_IF;
+ inv_fs = true;
case SND_SOC_DAIFMT_DSP_A:
dev->mode = MOD_DSP_A;
break;
@@ -394,6 +395,8 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
default:
return -EINVAL;
}
+ if (inv_fs == true)
+ pcr ^= (DAVINCI_MCBSP_PCR_FSXP | DAVINCI_MCBSP_PCR_FSRP);
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG, srgr);
dev->pcr = pcr;
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, pcr);
@@ -617,7 +620,7 @@ static void davinci_i2s_shutdown(struct snd_pcm_substream *substream,
#define DAVINCI_I2S_RATES SNDRV_PCM_RATE_8000_96000
-static struct snd_soc_dai_ops davinci_i2s_dai_ops = {
+static const struct snd_soc_dai_ops davinci_i2s_dai_ops = {
.startup = davinci_i2s_startup,
.shutdown = davinci_i2s_shutdown,
.prepare = davinci_i2s_prepare,
@@ -658,18 +661,18 @@ static int davinci_i2s_probe(struct platform_device *pdev)
return -ENODEV;
}
- ioarea = request_mem_region(mem->start, resource_size(mem),
- pdev->name);
+ ioarea = devm_request_mem_region(&pdev->dev, mem->start,
+ resource_size(mem),
+ pdev->name);
if (!ioarea) {
dev_err(&pdev->dev, "McBSP region already claimed\n");
return -EBUSY;
}
- dev = kzalloc(sizeof(struct davinci_mcbsp_dev), GFP_KERNEL);
- if (!dev) {
- ret = -ENOMEM;
- goto err_release_region;
- }
+ dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_mcbsp_dev),
+ GFP_KERNEL);
+ if (!dev)
+ return -ENOMEM;
if (pdata) {
dev->enable_channel_combine = pdata->enable_channel_combine;
dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].sram_size =
@@ -688,13 +691,11 @@ static int davinci_i2s_probe(struct platform_device *pdev)
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].ram_chan_q = ram_chan_q;
dev->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(dev->clk)) {
- ret = -ENODEV;
- goto err_free_mem;
- }
+ if (IS_ERR(dev->clk))
+ return -ENODEV;
clk_enable(dev->clk);
- dev->base = ioremap(mem->start, resource_size(mem));
+ dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
if (!dev->base) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENOMEM;
@@ -712,7 +713,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
ret = -ENXIO;
- goto err_iounmap;
+ goto err_release_clk;
}
dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK].channel = res->start;
@@ -720,7 +721,7 @@ static int davinci_i2s_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
ret = -ENXIO;
- goto err_iounmap;
+ goto err_release_clk;
}
dev->dma_params[SNDRV_PCM_STREAM_CAPTURE].channel = res->start;
dev->dev = &pdev->dev;
@@ -729,35 +730,24 @@ static int davinci_i2s_probe(struct platform_device *pdev)
ret = snd_soc_register_dai(&pdev->dev, &davinci_i2s_dai);
if (ret != 0)
- goto err_iounmap;
+ goto err_release_clk;
return 0;
-err_iounmap:
- iounmap(dev->base);
err_release_clk:
clk_disable(dev->clk);
clk_put(dev->clk);
-err_free_mem:
- kfree(dev);
-err_release_region:
- release_mem_region(mem->start, resource_size(mem));
-
return ret;
}
static int davinci_i2s_remove(struct platform_device *pdev)
{
struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev);
- struct resource *mem;
snd_soc_unregister_dai(&pdev->dev);
clk_disable(dev->clk);
clk_put(dev->clk);
dev->clk = NULL;
- kfree(dev);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
return 0;
}
@@ -771,17 +761,7 @@ static struct platform_driver davinci_mcbsp_driver = {
},
};
-static int __init davinci_i2s_init(void)
-{
- return platform_driver_register(&davinci_mcbsp_driver);
-}
-module_init(davinci_i2s_init);
-
-static void __exit davinci_i2s_exit(void)
-{
- platform_driver_unregister(&davinci_mcbsp_driver);
-}
-module_exit(davinci_i2s_exit);
+module_platform_driver(davinci_mcbsp_driver);
MODULE_AUTHOR("Vladimir Barinov");
MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c
index 8566238db2a5..95441bfc8190 100644
--- a/sound/soc/davinci/davinci-mcasp.c
+++ b/sound/soc/davinci/davinci-mcasp.c
@@ -732,16 +732,19 @@ static int davinci_mcasp_hw_params(struct snd_pcm_substream *substream,
davinci_hw_param(dev, substream->stream);
switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_U8:
case SNDRV_PCM_FORMAT_S8:
dma_params->data_type = 1;
word_length = DAVINCI_AUDIO_WORD_8;
break;
+ case SNDRV_PCM_FORMAT_U16_LE:
case SNDRV_PCM_FORMAT_S16_LE:
dma_params->data_type = 2;
word_length = DAVINCI_AUDIO_WORD_16;
break;
+ case SNDRV_PCM_FORMAT_U32_LE:
case SNDRV_PCM_FORMAT_S32_LE:
dma_params->data_type = 4;
word_length = DAVINCI_AUDIO_WORD_32;
@@ -810,7 +813,7 @@ static int davinci_mcasp_startup(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
+static const struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
.startup = davinci_mcasp_startup,
.trigger = davinci_mcasp_trigger,
.hw_params = davinci_mcasp_hw_params,
@@ -818,6 +821,13 @@ static struct snd_soc_dai_ops davinci_mcasp_dai_ops = {
};
+#define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
+ SNDRV_PCM_FMTBIT_U8 | \
+ SNDRV_PCM_FMTBIT_S16_LE | \
+ SNDRV_PCM_FMTBIT_U16_LE | \
+ SNDRV_PCM_FMTBIT_S32_LE | \
+ SNDRV_PCM_FMTBIT_U32_LE)
+
static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
{
.name = "davinci-mcasp.0",
@@ -825,17 +835,13 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
.channels_min = 2,
.channels_max = 2,
.rates = DAVINCI_MCASP_RATES,
- .formats = SNDRV_PCM_FMTBIT_S8 |
- SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
+ .formats = DAVINCI_MCASP_PCM_FMTS,
},
.capture = {
.channels_min = 2,
.channels_max = 2,
.rates = DAVINCI_MCASP_RATES,
- .formats = SNDRV_PCM_FMTBIT_S8 |
- SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S32_LE,
+ .formats = DAVINCI_MCASP_PCM_FMTS,
},
.ops = &davinci_mcasp_dai_ops,
@@ -846,7 +852,7 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
.channels_min = 1,
.channels_max = 384,
.rates = DAVINCI_MCASP_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .formats = DAVINCI_MCASP_PCM_FMTS,
},
.ops = &davinci_mcasp_dai_ops,
},
@@ -859,38 +865,35 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
struct resource *mem, *ioarea, *res;
struct snd_platform_data *pdata;
struct davinci_audio_dev *dev;
- int ret = 0;
+ int ret;
- dev = kzalloc(sizeof(struct davinci_audio_dev), GFP_KERNEL);
+ dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev),
+ GFP_KERNEL);
if (!dev)
return -ENOMEM;
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!mem) {
dev_err(&pdev->dev, "no mem resource?\n");
- ret = -ENODEV;
- goto err_release_data;
+ return -ENODEV;
}
- ioarea = request_mem_region(mem->start,
+ ioarea = devm_request_mem_region(&pdev->dev, mem->start,
resource_size(mem), pdev->name);
if (!ioarea) {
dev_err(&pdev->dev, "Audio region already claimed\n");
- ret = -EBUSY;
- goto err_release_data;
+ return -EBUSY;
}
pdata = pdev->dev.platform_data;
dev->clk = clk_get(&pdev->dev, NULL);
- if (IS_ERR(dev->clk)) {
- ret = -ENODEV;
- goto err_release_region;
- }
+ if (IS_ERR(dev->clk))
+ return -ENODEV;
clk_enable(dev->clk);
dev->clk_active = 1;
- dev->base = ioremap(mem->start, resource_size(mem));
+ dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
if (!dev->base) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENOMEM;
@@ -918,7 +921,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
ret = -ENODEV;
- goto err_iounmap;
+ goto err_release_clk;
}
dma_data->channel = res->start;
@@ -934,7 +937,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev, "no DMA resource\n");
ret = -ENODEV;
- goto err_iounmap;
+ goto err_release_clk;
}
dma_data->channel = res->start;
@@ -942,37 +945,24 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
ret = snd_soc_register_dai(&pdev->dev, &davinci_mcasp_dai[pdata->op_mode]);
if (ret != 0)
- goto err_iounmap;
+ goto err_release_clk;
return 0;
-err_iounmap:
- iounmap(dev->base);
err_release_clk:
clk_disable(dev->clk);
clk_put(dev->clk);
-err_release_region:
- release_mem_region(mem->start, resource_size(mem));
-err_release_data:
- kfree(dev);
-
return ret;
}
static int davinci_mcasp_remove(struct platform_device *pdev)
{
struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev);
- struct resource *mem;
snd_soc_unregister_dai(&pdev->dev);
clk_disable(dev->clk);
clk_put(dev->clk);
dev->clk = NULL;
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(mem->start, resource_size(mem));
-
- kfree(dev);
-
return 0;
}
@@ -985,17 +975,7 @@ static struct platform_driver davinci_mcasp_driver = {
},
};
-static int __init davinci_mcasp_init(void)
-{
- return platform_driver_register(&davinci_mcasp_driver);
-}
-module_init(davinci_mcasp_init);
-
-static void __exit davinci_mcasp_exit(void)
-{
- platform_driver_unregister(&davinci_mcasp_driver);
-}
-module_exit(davinci_mcasp_exit);
+module_platform_driver(davinci_mcasp_driver);
MODULE_AUTHOR("Steve Chen");
MODULE_DESCRIPTION("TI DAVINCI McASP SoC Interface");
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index a49e667373bc..97d77b298968 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -180,7 +180,6 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
{
struct davinci_runtime_data *prtd = substream->runtime->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
- int link = prtd->asp_link[0];
unsigned int period_size;
unsigned int dma_offset;
dma_addr_t dma_pos;
@@ -198,7 +197,8 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
fifo_level = prtd->params->fifo_level;
pr_debug("davinci_pcm: audio_set_dma_params_play channel = %d "
- "dma_ptr = %x period_size=%x\n", link, dma_pos, period_size);
+ "dma_ptr = %x period_size=%x\n", prtd->asp_link[0], dma_pos,
+ period_size);
data_type = prtd->params->data_type;
count = period_size / data_type;
@@ -222,17 +222,19 @@ static void davinci_pcm_enqueue_dma(struct snd_pcm_substream *substream)
}
acnt = prtd->params->acnt;
- edma_set_src(link, src, INCR, W8BIT);
- edma_set_dest(link, dst, INCR, W8BIT);
+ edma_set_src(prtd->asp_link[0], src, INCR, W8BIT);
+ edma_set_dest(prtd->asp_link[0], dst, INCR, W8BIT);
- edma_set_src_index(link, src_bidx, src_cidx);
- edma_set_dest_index(link, dst_bidx, dst_cidx);
+ edma_set_src_index(prtd->asp_link[0], src_bidx, src_cidx);
+ edma_set_dest_index(prtd->asp_link[0], dst_bidx, dst_cidx);
if (!fifo_level)
- edma_set_transfer_params(link, acnt, count, 1, 0, ASYNC);
+ edma_set_transfer_params(prtd->asp_link[0], acnt, count, 1, 0,
+ ASYNC);
else
- edma_set_transfer_params(link, acnt, fifo_level, count,
- fifo_level, ABSYNC);
+ edma_set_transfer_params(prtd->asp_link[0], acnt, fifo_level,
+ count, fifo_level,
+ ABSYNC);
}
static void davinci_pcm_dma_irq(unsigned link, u16 ch_status, void *data)
@@ -305,7 +307,6 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
unsigned int acnt = params->acnt;
/* divide by 2 for ping/pong */
unsigned int ping_size = snd_pcm_lib_period_bytes(substream) >> 1;
- int link = prtd->asp_link[1];
unsigned int fifo_level = prtd->params->fifo_level;
unsigned int count;
if ((data_type == 0) || (data_type > 4)) {
@@ -316,28 +317,26 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
dma_addr_t asp_src_pong = iram_dma->addr + ping_size;
ram_src_cidx = ping_size;
ram_dst_cidx = -ping_size;
- edma_set_src(link, asp_src_pong, INCR, W8BIT);
+ edma_set_src(prtd->asp_link[1], asp_src_pong, INCR, W8BIT);
- link = prtd->asp_link[0];
- edma_set_src_index(link, data_type, data_type * fifo_level);
- link = prtd->asp_link[1];
- edma_set_src_index(link, data_type, data_type * fifo_level);
+ edma_set_src_index(prtd->asp_link[0], data_type,
+ data_type * fifo_level);
+ edma_set_src_index(prtd->asp_link[1], data_type,
+ data_type * fifo_level);
- link = prtd->ram_link;
- edma_set_src(link, runtime->dma_addr, INCR, W32BIT);
+ edma_set_src(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
} else {
dma_addr_t asp_dst_pong = iram_dma->addr + ping_size;
ram_src_cidx = -ping_size;
ram_dst_cidx = ping_size;
- edma_set_dest(link, asp_dst_pong, INCR, W8BIT);
+ edma_set_dest(prtd->asp_link[1], asp_dst_pong, INCR, W8BIT);
- link = prtd->asp_link[0];
- edma_set_dest_index(link, data_type, data_type * fifo_level);
- link = prtd->asp_link[1];
- edma_set_dest_index(link, data_type, data_type * fifo_level);
+ edma_set_dest_index(prtd->asp_link[0], data_type,
+ data_type * fifo_level);
+ edma_set_dest_index(prtd->asp_link[1], data_type,
+ data_type * fifo_level);
- link = prtd->ram_link;
- edma_set_dest(link, runtime->dma_addr, INCR, W32BIT);
+ edma_set_dest(prtd->ram_link, runtime->dma_addr, INCR, W32BIT);
}
if (!fifo_level) {
@@ -354,10 +353,9 @@ static int ping_pong_dma_setup(struct snd_pcm_substream *substream)
count, fifo_level, ABSYNC);
}
- link = prtd->ram_link;
- edma_set_src_index(link, ping_size, ram_src_cidx);
- edma_set_dest_index(link, ping_size, ram_dst_cidx);
- edma_set_transfer_params(link, ping_size, 2,
+ edma_set_src_index(prtd->ram_link, ping_size, ram_src_cidx);
+ edma_set_dest_index(prtd->ram_link, ping_size, ram_dst_cidx);
+ edma_set_transfer_params(prtd->ram_link, ping_size, 2,
runtime->periods, 2, ASYNC);
/* init master params */
@@ -406,32 +404,32 @@ static int request_ping_pong(struct snd_pcm_substream *substream,
{
dma_addr_t asp_src_ping;
dma_addr_t asp_dst_ping;
- int link;
+ int ret;
struct davinci_pcm_dma_params *params = prtd->params;
/* Request ram master channel */
- link = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
+ ret = prtd->ram_channel = edma_alloc_channel(EDMA_CHANNEL_ANY,
davinci_pcm_dma_irq, substream,
prtd->params->ram_chan_q);
- if (link < 0)
+ if (ret < 0)
goto exit1;
/* Request ram link channel */
- link = prtd->ram_link = edma_alloc_slot(
+ ret = prtd->ram_link = edma_alloc_slot(
EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
- if (link < 0)
+ if (ret < 0)
goto exit2;
- link = prtd->asp_link[1] = edma_alloc_slot(
+ ret = prtd->asp_link[1] = edma_alloc_slot(
EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
- if (link < 0)
+ if (ret < 0)
goto exit3;
prtd->ram_link2 = -1;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- link = prtd->ram_link2 = edma_alloc_slot(
+ ret = prtd->ram_link2 = edma_alloc_slot(
EDMA_CTLR(prtd->ram_channel), EDMA_SLOT_ANY);
- if (link < 0)
+ if (ret < 0)
goto exit4;
}
/* circle ping-pong buffers */
@@ -448,36 +446,33 @@ static int request_ping_pong(struct snd_pcm_substream *substream,
asp_dst_ping = iram_dma->addr;
}
/* ping */
- link = prtd->asp_link[0];
- edma_set_src(link, asp_src_ping, INCR, W16BIT);
- edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
- edma_set_src_index(link, 0, 0);
- edma_set_dest_index(link, 0, 0);
+ edma_set_src(prtd->asp_link[0], asp_src_ping, INCR, W16BIT);
+ edma_set_dest(prtd->asp_link[0], asp_dst_ping, INCR, W16BIT);
+ edma_set_src_index(prtd->asp_link[0], 0, 0);
+ edma_set_dest_index(prtd->asp_link[0], 0, 0);
- edma_read_slot(link, &prtd->asp_params);
+ edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f) | TCINTEN);
prtd->asp_params.opt |= TCCHEN |
EDMA_TCC(prtd->ram_channel & 0x3f);
- edma_write_slot(link, &prtd->asp_params);
+ edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
/* pong */
- link = prtd->asp_link[1];
- edma_set_src(link, asp_src_ping, INCR, W16BIT);
- edma_set_dest(link, asp_dst_ping, INCR, W16BIT);
- edma_set_src_index(link, 0, 0);
- edma_set_dest_index(link, 0, 0);
+ edma_set_src(prtd->asp_link[1], asp_src_ping, INCR, W16BIT);
+ edma_set_dest(prtd->asp_link[1], asp_dst_ping, INCR, W16BIT);
+ edma_set_src_index(prtd->asp_link[1], 0, 0);
+ edma_set_dest_index(prtd->asp_link[1], 0, 0);
- edma_read_slot(link, &prtd->asp_params);
+ edma_read_slot(prtd->asp_link[1], &prtd->asp_params);
prtd->asp_params.opt &= ~(TCCMODE | EDMA_TCC(0x3f));
/* interrupt after every pong completion */
prtd->asp_params.opt |= TCINTEN | TCCHEN |
EDMA_TCC(prtd->ram_channel & 0x3f);
- edma_write_slot(link, &prtd->asp_params);
+ edma_write_slot(prtd->asp_link[1], &prtd->asp_params);
/* ram */
- link = prtd->ram_link;
- edma_set_src(link, iram_dma->addr, INCR, W32BIT);
- edma_set_dest(link, iram_dma->addr, INCR, W32BIT);
+ edma_set_src(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
+ edma_set_dest(prtd->ram_link, iram_dma->addr, INCR, W32BIT);
pr_debug("%s: audio dma channels/slots in use for ram:%u %u %u,"
"for asp:%u %u %u\n", __func__,
prtd->ram_channel, prtd->ram_link, prtd->ram_link2,
@@ -494,7 +489,7 @@ exit2:
edma_free_channel(prtd->ram_channel);
prtd->ram_channel = -1;
exit1:
- return link;
+ return ret;
}
static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
@@ -502,22 +497,22 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
struct snd_dma_buffer *iram_dma;
struct davinci_runtime_data *prtd = substream->runtime->private_data;
struct davinci_pcm_dma_params *params = prtd->params;
- int link;
+ int ret;
if (!params)
return -ENODEV;
/* Request asp master DMA channel */
- link = prtd->asp_channel = edma_alloc_channel(params->channel,
+ ret = prtd->asp_channel = edma_alloc_channel(params->channel,
davinci_pcm_dma_irq, substream,
prtd->params->asp_chan_q);
- if (link < 0)
+ if (ret < 0)
goto exit1;
/* Request asp link channels */
- link = prtd->asp_link[0] = edma_alloc_slot(
+ ret = prtd->asp_link[0] = edma_alloc_slot(
EDMA_CTLR(prtd->asp_channel), EDMA_SLOT_ANY);
- if (link < 0)
+ if (ret < 0)
goto exit2;
iram_dma = (struct snd_dma_buffer *)substream->dma_buffer.private_data;
@@ -537,17 +532,17 @@ static int davinci_pcm_dma_request(struct snd_pcm_substream *substream)
* the buffer and its length (ccnt) ... use it as a template
* so davinci_pcm_enqueue_dma() takes less time in IRQ.
*/
- edma_read_slot(link, &prtd->asp_params);
+ edma_read_slot(prtd->asp_link[0], &prtd->asp_params);
prtd->asp_params.opt |= TCINTEN |
EDMA_TCC(EDMA_CHAN_SLOT(prtd->asp_channel));
- prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(link) << 5;
- edma_write_slot(link, &prtd->asp_params);
+ prtd->asp_params.link_bcntrld = EDMA_CHAN_SLOT(prtd->asp_link[0]) << 5;
+ edma_write_slot(prtd->asp_link[0], &prtd->asp_params);
return 0;
exit2:
edma_free_channel(prtd->asp_channel);
prtd->asp_channel = -1;
exit1:
- return link;
+ return ret;
}
static int davinci_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
@@ -831,21 +826,20 @@ static void davinci_pcm_free(struct snd_pcm *pcm)
}
}
-static u64 davinci_pcm_dmamask = 0xffffffff;
+static u64 davinci_pcm_dmamask = DMA_BIT_MASK(32);
static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret;
if (!card->dev->dma_mask)
card->dev->dma_mask = &davinci_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = davinci_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK,
pcm_hardware_playback.buffer_bytes_max);
@@ -853,7 +847,7 @@ static int davinci_pcm_new(struct snd_soc_pcm_runtime *rtd)
return ret;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = davinci_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE,
pcm_hardware_capture.buffer_bytes_max);
@@ -891,17 +885,7 @@ static struct platform_driver davinci_pcm_driver = {
.remove = __devexit_p(davinci_soc_platform_remove),
};
-static int __init snd_davinci_pcm_init(void)
-{
- return platform_driver_register(&davinci_pcm_driver);
-}
-module_init(snd_davinci_pcm_init);
-
-static void __exit snd_davinci_pcm_exit(void)
-{
- platform_driver_unregister(&davinci_pcm_driver);
-}
-module_exit(snd_davinci_pcm_exit);
+module_platform_driver(davinci_pcm_driver);
MODULE_AUTHOR("Vladimir Barinov");
MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
index 0fe558c65145..f71175b29e38 100644
--- a/sound/soc/davinci/davinci-sffsdr.c
+++ b/sound/soc/davinci/davinci-sffsdr.c
@@ -93,6 +93,7 @@ static struct snd_soc_dai_link sffsdr_dai = {
/* davinci-sffsdr audio machine driver */
static struct snd_soc_card snd_soc_sffsdr = {
.name = "DaVinci SFFSDR",
+ .owner = THIS_MODULE,
.dai_link = &sffsdr_dai,
.num_links = 1,
};
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c
index 1f11525d97e8..da030ff883d5 100644
--- a/sound/soc/davinci/davinci-vcif.c
+++ b/sound/soc/davinci/davinci-vcif.c
@@ -183,7 +183,7 @@ static int davinci_vcif_startup(struct snd_pcm_substream *substream,
#define DAVINCI_VCIF_RATES SNDRV_PCM_RATE_8000_48000
-static struct snd_soc_dai_ops davinci_vcif_dai_ops = {
+static const struct snd_soc_dai_ops davinci_vcif_dai_ops = {
.startup = davinci_vcif_startup,
.trigger = davinci_vcif_trigger,
.hw_params = davinci_vcif_hw_params,
@@ -210,7 +210,9 @@ static int davinci_vcif_probe(struct platform_device *pdev)
struct davinci_vcif_dev *davinci_vcif_dev;
int ret;
- davinci_vcif_dev = kzalloc(sizeof(struct davinci_vcif_dev), GFP_KERNEL);
+ davinci_vcif_dev = devm_kzalloc(&pdev->dev,
+ sizeof(struct davinci_vcif_dev),
+ GFP_KERNEL);
if (!davinci_vcif_dev) {
dev_dbg(&pdev->dev,
"could not allocate memory for private data\n");
@@ -235,23 +237,15 @@ static int davinci_vcif_probe(struct platform_device *pdev)
ret = snd_soc_register_dai(&pdev->dev, &davinci_vcif_dai);
if (ret != 0) {
dev_err(&pdev->dev, "could not register dai\n");
- goto fail;
+ return ret;
}
return 0;
-
-fail:
- kfree(davinci_vcif_dev);
-
- return ret;
}
static int davinci_vcif_remove(struct platform_device *pdev)
{
- struct davinci_vcif_dev *davinci_vcif_dev = dev_get_drvdata(&pdev->dev);
-
snd_soc_unregister_dai(&pdev->dev);
- kfree(davinci_vcif_dev);
return 0;
}
@@ -265,17 +259,7 @@ static struct platform_driver davinci_vcif_driver = {
},
};
-static int __init davinci_vcif_init(void)
-{
- return platform_driver_probe(&davinci_vcif_driver, davinci_vcif_probe);
-}
-module_init(davinci_vcif_init);
-
-static void __exit davinci_vcif_exit(void)
-{
- platform_driver_unregister(&davinci_vcif_driver);
-}
-module_exit(davinci_vcif_exit);
+module_platform_driver(davinci_vcif_driver);
MODULE_AUTHOR("Miguel Aguilar");
MODULE_DESCRIPTION("Texas Instruments DaVinci ASoC Voice Codec Interface");
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/ep93xx/Kconfig
index 91a28de94109..88143db7e753 100644
--- a/sound/soc/ep93xx/Kconfig
+++ b/sound/soc/ep93xx/Kconfig
@@ -1,6 +1,7 @@
config SND_EP93XX_SOC
tristate "SoC Audio support for the Cirrus Logic EP93xx series"
depends on ARCH_EP93XX && SND_SOC
+ select SND_SOC_DMAENGINE_PCM
help
Say Y or M if you want to add support for codecs attached to
the EP93xx I2S or AC97 interfaces.
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/ep93xx/edb93xx.c
index d3aa15119d26..e01cb02abd3a 100644
--- a/sound/soc/ep93xx/edb93xx.c
+++ b/sound/soc/ep93xx/edb93xx.c
@@ -21,6 +21,7 @@
#include <linux/platform_device.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -28,12 +29,6 @@
#include <mach/hardware.h>
#include "ep93xx-pcm.h"
-#define edb93xx_has_audio() (machine_is_edb9301() || \
- machine_is_edb9302() || \
- machine_is_edb9302a() || \
- machine_is_edb9307a() || \
- machine_is_edb9315a())
-
static int edb93xx_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
@@ -53,18 +48,6 @@ static int edb93xx_hw_params(struct snd_pcm_substream *substream,
else
mclk_rate = rate * 64 * 2;
- err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (err)
- return err;
-
- err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (err)
- return err;
-
err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate,
SND_SOC_CLOCK_IN);
if (err)
@@ -85,58 +68,61 @@ static struct snd_soc_dai_link edb93xx_dai = {
.cpu_dai_name = "ep93xx-i2s",
.codec_name = "spi0.0",
.codec_dai_name = "cs4271-hifi",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &edb93xx_ops,
};
static struct snd_soc_card snd_soc_edb93xx = {
.name = "EDB93XX",
+ .owner = THIS_MODULE,
.dai_link = &edb93xx_dai,
.num_links = 1,
};
-static struct platform_device *edb93xx_snd_device;
-
-static int __init edb93xx_init(void)
+static int __devinit edb93xx_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &snd_soc_edb93xx;
int ret;
- if (!edb93xx_has_audio())
- return -ENODEV;
-
- ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
- EP93XX_SYSCON_I2SCLKDIV_ORIDE |
- EP93XX_SYSCON_I2SCLKDIV_SPOL);
+ ret = ep93xx_i2s_acquire();
if (ret)
return ret;
- edb93xx_snd_device = platform_device_alloc("soc-audio", -1);
- if (!edb93xx_snd_device) {
- ret = -ENOMEM;
- goto free_i2s;
- }
+ card->dev = &pdev->dev;
- platform_set_drvdata(edb93xx_snd_device, &snd_soc_edb93xx);
- ret = platform_device_add(edb93xx_snd_device);
- if (ret)
- goto device_put;
-
- return 0;
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ ep93xx_i2s_release();
+ }
-device_put:
- platform_device_put(edb93xx_snd_device);
-free_i2s:
- ep93xx_i2s_release();
return ret;
}
-module_init(edb93xx_init);
-static void __exit edb93xx_exit(void)
+static int __devexit edb93xx_remove(struct platform_device *pdev)
{
- platform_device_unregister(edb93xx_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
ep93xx_i2s_release();
+
+ return 0;
}
-module_exit(edb93xx_exit);
+
+static struct platform_driver edb93xx_driver = {
+ .driver = {
+ .name = "edb93xx-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = edb93xx_probe,
+ .remove = __devexit_p(edb93xx_remove),
+};
+
+module_platform_driver(edb93xx_driver);
MODULE_AUTHOR("Alexander Sverdlin <subaparts@yandex.ru>");
MODULE_DESCRIPTION("ALSA SoC EDB93xx");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:edb93xx-audio");
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/ep93xx/ep93xx-ac97.c
index c7417c76552b..0678637abd66 100644
--- a/sound/soc/ep93xx/ep93xx-ac97.c
+++ b/sound/soc/ep93xx/ep93xx-ac97.c
@@ -330,12 +330,12 @@ static int ep93xx_ac97_startup(struct snd_pcm_substream *substream,
return 0;
}
-static struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
+static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = {
.startup = ep93xx_ac97_startup,
.trigger = ep93xx_ac97_trigger,
};
-struct snd_soc_dai_driver ep93xx_ac97_dai = {
+static struct snd_soc_dai_driver ep93xx_ac97_dai = {
.name = "ep93xx-ac97",
.id = 0,
.ac97_control = 1,
@@ -449,17 +449,7 @@ static struct platform_driver ep93xx_ac97_driver = {
},
};
-static int __init ep93xx_ac97_init(void)
-{
- return platform_driver_register(&ep93xx_ac97_driver);
-}
-module_init(ep93xx_ac97_init);
-
-static void __exit ep93xx_ac97_exit(void)
-{
- platform_driver_unregister(&ep93xx_ac97_driver);
-}
-module_exit(ep93xx_ac97_exit);
+module_platform_driver(ep93xx_ac97_driver);
MODULE_DESCRIPTION("EP93xx AC97 ASoC Driver");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/ep93xx/ep93xx-i2s.c
index 099614e16651..f7a62348e3fe 100644
--- a/sound/soc/ep93xx/ep93xx-i2s.c
+++ b/sound/soc/ep93xx/ep93xx-i2s.c
@@ -338,7 +338,7 @@ static int ep93xx_i2s_resume(struct snd_soc_dai *dai)
#define ep93xx_i2s_resume NULL
#endif
-static struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
+static const struct snd_soc_dai_ops ep93xx_i2s_dai_ops = {
.startup = ep93xx_i2s_startup,
.shutdown = ep93xx_i2s_shutdown,
.hw_params = ep93xx_i2s_hw_params,
@@ -464,18 +464,7 @@ static struct platform_driver ep93xx_i2s_driver = {
},
};
-static int __init ep93xx_i2s_init(void)
-{
- return platform_driver_register(&ep93xx_i2s_driver);
-}
-
-static void __exit ep93xx_i2s_exit(void)
-{
- platform_driver_unregister(&ep93xx_i2s_driver);
-}
-
-module_init(ep93xx_i2s_init);
-module_exit(ep93xx_i2s_exit);
+module_platform_driver(ep93xx_i2s_driver);
MODULE_ALIAS("platform:ep93xx-i2s");
MODULE_AUTHOR("Ryan Mallon");
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/ep93xx/ep93xx-pcm.c
index 8dfd3ad84b19..162dbb74f4cc 100644
--- a/sound/soc/ep93xx/ep93xx-pcm.c
+++ b/sound/soc/ep93xx/ep93xx-pcm.c
@@ -23,6 +23,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
#include <mach/dma.h>
#include <mach/hardware.h>
@@ -52,26 +53,6 @@ static const struct snd_pcm_hardware ep93xx_pcm_hardware = {
.fifo_size = 32,
};
-struct ep93xx_runtime_data
-{
- int pointer_bytes;
- int periods;
- int period_bytes;
- struct dma_chan *dma_chan;
- struct ep93xx_dma_data dma_data;
-};
-
-static void ep93xx_pcm_dma_callback(void *data)
-{
- struct snd_pcm_substream *substream = data;
- struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
-
- rtd->pointer_bytes += rtd->period_bytes;
- rtd->pointer_bytes %= rtd->period_bytes * rtd->periods;
-
- snd_pcm_period_elapsed(substream);
-}
-
static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
{
struct ep93xx_dma_data *data = filter_param;
@@ -86,98 +67,48 @@ static bool ep93xx_pcm_dma_filter(struct dma_chan *chan, void *filter_param)
static int ep93xx_pcm_open(struct snd_pcm_substream *substream)
{
- struct snd_soc_pcm_runtime *soc_rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = soc_rtd->cpu_dai;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct ep93xx_pcm_dma_params *dma_params;
- struct ep93xx_runtime_data *rtd;
- dma_cap_mask_t mask;
+ struct ep93xx_dma_data *dma_data;
int ret;
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- return ret;
-
snd_soc_set_runtime_hwparams(substream, &ep93xx_pcm_hardware);
- rtd = kmalloc(sizeof(*rtd), GFP_KERNEL);
- if (!rtd)
+ dma_data = kmalloc(sizeof(*dma_data), GFP_KERNEL);
+ if (!dma_data)
return -ENOMEM;
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- dma_cap_set(DMA_CYCLIC, mask);
-
dma_params = snd_soc_dai_get_dma_data(cpu_dai, substream);
- rtd->dma_data.port = dma_params->dma_port;
- rtd->dma_data.name = dma_params->name;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- rtd->dma_data.direction = DMA_TO_DEVICE;
- else
- rtd->dma_data.direction = DMA_FROM_DEVICE;
-
- rtd->dma_chan = dma_request_channel(mask, ep93xx_pcm_dma_filter,
- &rtd->dma_data);
- if (!rtd->dma_chan) {
- kfree(rtd);
- return -EINVAL;
- }
-
- substream->runtime->private_data = rtd;
- return 0;
-}
+ dma_data->port = dma_params->dma_port;
+ dma_data->name = dma_params->name;
+ dma_data->direction = snd_pcm_substream_to_dma_direction(substream);
-static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
-{
- struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
+ ret = snd_dmaengine_pcm_open(substream, ep93xx_pcm_dma_filter, dma_data);
+ if (ret) {
+ kfree(dma_data);
+ return ret;
+ }
- dma_release_channel(rtd->dma_chan);
- kfree(rtd);
- return 0;
-}
+ snd_dmaengine_pcm_set_data(substream, dma_data);
-static int ep93xx_pcm_dma_submit(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct ep93xx_runtime_data *rtd = runtime->private_data;
- struct dma_chan *chan = rtd->dma_chan;
- struct dma_device *dma_dev = chan->device;
- struct dma_async_tx_descriptor *desc;
-
- rtd->pointer_bytes = 0;
- desc = dma_dev->device_prep_dma_cyclic(chan, runtime->dma_addr,
- rtd->period_bytes * rtd->periods,
- rtd->period_bytes,
- rtd->dma_data.direction);
- if (!desc)
- return -EINVAL;
-
- desc->callback = ep93xx_pcm_dma_callback;
- desc->callback_param = substream;
-
- dmaengine_submit(desc);
return 0;
}
-static void ep93xx_pcm_dma_flush(struct snd_pcm_substream *substream)
+static int ep93xx_pcm_close(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct ep93xx_runtime_data *rtd = runtime->private_data;
+ struct dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
- dmaengine_terminate_all(rtd->dma_chan);
+ snd_dmaengine_pcm_close(substream);
+ kfree(dma_data);
+ return 0;
}
static int ep93xx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct ep93xx_runtime_data *rtd = runtime->private_data;
-
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- rtd->periods = params_periods(params);
- rtd->period_bytes = params_period_bytes(params);
return 0;
}
@@ -187,41 +118,6 @@ static int ep93xx_pcm_hw_free(struct snd_pcm_substream *substream)
return 0;
}
-static int ep93xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- int ret;
-
- ret = 0;
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- ret = ep93xx_pcm_dma_submit(substream);
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- ep93xx_pcm_dma_flush(substream);
- break;
-
- default:
- ret = -EINVAL;
- break;
- }
-
- return ret;
-}
-
-static snd_pcm_uframes_t ep93xx_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct ep93xx_runtime_data *rtd = substream->runtime->private_data;
-
- /* FIXME: implement this with sub-period granularity */
- return bytes_to_frames(runtime, rtd->pointer_bytes);
-}
-
static int ep93xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
@@ -239,8 +135,8 @@ static struct snd_pcm_ops ep93xx_pcm_ops = {
.ioctl = snd_pcm_lib_ioctl,
.hw_params = ep93xx_pcm_hw_params,
.hw_free = ep93xx_pcm_hw_free,
- .trigger = ep93xx_pcm_trigger,
- .pointer = ep93xx_pcm_pointer,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer,
.mmap = ep93xx_pcm_mmap,
};
@@ -281,28 +177,27 @@ static void ep93xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
}
}
-static u64 ep93xx_pcm_dmamask = 0xffffffff;
+static u64 ep93xx_pcm_dmamask = DMA_BIT_MASK(32);
static int ep93xx_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
card->dev->dma_mask = &ep93xx_pcm_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
return ret;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = ep93xx_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -339,19 +234,9 @@ static struct platform_driver ep93xx_pcm_driver = {
.remove = __devexit_p(ep93xx_soc_platform_remove),
};
-static int __init ep93xx_soc_platform_init(void)
-{
- return platform_driver_register(&ep93xx_pcm_driver);
-}
-
-static void __exit ep93xx_soc_platform_exit(void)
-{
- platform_driver_unregister(&ep93xx_pcm_driver);
-}
-
-module_init(ep93xx_soc_platform_init);
-module_exit(ep93xx_soc_platform_exit);
+module_platform_driver(ep93xx_pcm_driver);
MODULE_AUTHOR("Ryan Mallon");
MODULE_DESCRIPTION("EP93xx ALSA PCM interface");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ep93xx-pcm-audio");
diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/ep93xx/simone.c
index 286817946c56..dd997094eb30 100644
--- a/sound/soc/ep93xx/simone.c
+++ b/sound/soc/ep93xx/simone.c
@@ -34,58 +34,57 @@ static struct snd_soc_dai_link simone_dai = {
static struct snd_soc_card snd_soc_simone = {
.name = "Sim.One",
+ .owner = THIS_MODULE,
.dai_link = &simone_dai,
.num_links = 1,
};
static struct platform_device *simone_snd_ac97_device;
-static struct platform_device *simone_snd_device;
-static int __init simone_init(void)
+static int __devinit simone_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &snd_soc_simone;
int ret;
- if (!machine_is_sim_one())
- return -ENODEV;
+ simone_snd_ac97_device = platform_device_register_simple("ac97-codec",
+ -1, NULL, 0);
+ if (IS_ERR(simone_snd_ac97_device))
+ return PTR_ERR(simone_snd_ac97_device);
- simone_snd_ac97_device = platform_device_alloc("ac97-codec", -1);
- if (!simone_snd_ac97_device)
- return -ENOMEM;
+ card->dev = &pdev->dev;
- ret = platform_device_add(simone_snd_ac97_device);
- if (ret)
- goto fail1;
-
- simone_snd_device = platform_device_alloc("soc-audio", -1);
- if (!simone_snd_device) {
- ret = -ENOMEM;
- goto fail2;
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ platform_device_unregister(simone_snd_ac97_device);
}
- platform_set_drvdata(simone_snd_device, &snd_soc_simone);
- ret = platform_device_add(simone_snd_device);
- if (ret)
- goto fail3;
-
- return 0;
-
-fail3:
- platform_device_put(simone_snd_device);
-fail2:
- platform_device_del(simone_snd_ac97_device);
-fail1:
- platform_device_put(simone_snd_ac97_device);
return ret;
}
-module_init(simone_init);
-static void __exit simone_exit(void)
+static int __devexit simone_remove(struct platform_device *pdev)
{
- platform_device_unregister(simone_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
platform_device_unregister(simone_snd_ac97_device);
+
+ return 0;
}
-module_exit(simone_exit);
+
+static struct platform_driver simone_driver = {
+ .driver = {
+ .name = "simone-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = simone_probe,
+ .remove = __devexit_p(simone_remove),
+};
+
+module_platform_driver(simone_driver);
MODULE_DESCRIPTION("ALSA SoC Simplemachines Sim.One");
MODULE_AUTHOR("Mika Westerberg <mika.westerberg@iki.fi>");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:simone-audio");
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/ep93xx/snappercl15.c
index c8aa8a5003ca..a193cea3cf3c 100644
--- a/sound/soc/ep93xx/snappercl15.c
+++ b/sound/soc/ep93xx/snappercl15.c
@@ -12,6 +12,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -32,16 +33,6 @@ static int snappercl15_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int err;
- err = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBS_CFS);
-
- err = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_IF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (err)
- return err;
-
err = snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK,
SND_SOC_CLOCK_IN);
if (err)
@@ -95,52 +86,61 @@ static struct snd_soc_dai_link snappercl15_dai = {
.codec_name = "tlv320aic23-codec.0-001a",
.platform_name = "ep93xx-pcm-audio",
.init = snappercl15_tlv320aic23_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_IF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &snappercl15_ops,
};
static struct snd_soc_card snd_soc_snappercl15 = {
.name = "Snapper CL15",
+ .owner = THIS_MODULE,
.dai_link = &snappercl15_dai,
.num_links = 1,
};
-static struct platform_device *snappercl15_snd_device;
-
-static int __init snappercl15_init(void)
+static int __devinit snappercl15_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &snd_soc_snappercl15;
int ret;
- if (!machine_is_snapper_cl15())
- return -ENODEV;
-
- ret = ep93xx_i2s_acquire(EP93XX_SYSCON_DEVCFG_I2SONAC97,
- EP93XX_SYSCON_I2SCLKDIV_ORIDE |
- EP93XX_SYSCON_I2SCLKDIV_SPOL);
+ ret = ep93xx_i2s_acquire();
if (ret)
return ret;
- snappercl15_snd_device = platform_device_alloc("soc-audio", -1);
- if (!snappercl15_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(snappercl15_snd_device, &snd_soc_snappercl15);
- ret = platform_device_add(snappercl15_snd_device);
- if (ret)
- platform_device_put(snappercl15_snd_device);
+ card->dev = &pdev->dev;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ ep93xx_i2s_release();
+ }
return ret;
}
-static void __exit snappercl15_exit(void)
+static int __devexit snappercl15_remove(struct platform_device *pdev)
{
- platform_device_unregister(snappercl15_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
ep93xx_i2s_release();
+
+ return 0;
}
-module_init(snappercl15_init);
-module_exit(snappercl15_exit);
+static struct platform_driver snappercl15_driver = {
+ .driver = {
+ .name = "snappercl15-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = snappercl15_probe,
+ .remove = __devexit_p(snappercl15_remove),
+};
+
+module_platform_driver(snappercl15_driver);
MODULE_AUTHOR("Ryan Mallon");
MODULE_DESCRIPTION("ALSA SoC Snapper CL15");
MODULE_LICENSE("GPL");
-
+MODULE_ALIAS("platform:snappercl15-audio");
diff --git a/sound/soc/fsl/efika-audio-fabric.c b/sound/soc/fsl/efika-audio-fabric.c
index 108b5d8bd0e9..b2acd3293ea8 100644
--- a/sound/soc/fsl/efika-audio-fabric.c
+++ b/sound/soc/fsl/efika-audio-fabric.c
@@ -31,8 +31,6 @@
#define DRV_NAME "efika-audio-fabric"
-static struct snd_soc_card card;
-
static struct snd_soc_dai_link efika_fabric_dai[] = {
{
.name = "AC97",
@@ -52,6 +50,13 @@ static struct snd_soc_dai_link efika_fabric_dai[] = {
},
};
+static struct snd_soc_card card = {
+ .name = "Efika",
+ .owner = THIS_MODULE,
+ .dai_link = efika_fabric_dai,
+ .num_links = ARRAY_SIZE(efika_fabric_dai),
+};
+
static __init int efika_fabric_init(void)
{
struct platform_device *pdev;
@@ -60,11 +65,6 @@ static __init int efika_fabric_init(void)
if (!of_machine_is_compatible("bplan,efika"))
return -ENODEV;
- card.name = "Efika";
- card.dai_link = efika_fabric_dai;
- card.num_links = ARRAY_SIZE(efika_fabric_dai);
-
-
pdev = platform_device_alloc("soc-audio", 1);
if (!pdev) {
pr_err("efika_fabric_init: platform_device_alloc() failed\n");
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index cb50598338e9..96bb92dd174c 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -297,7 +297,6 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
static u64 fsl_dma_dmamask = DMA_BIT_MASK(36);
int ret;
@@ -312,23 +311,23 @@ static int fsl_dma_new(struct snd_soc_pcm_runtime *rtd)
* should allocate a DMA buffer only for the streams that are valid.
*/
- if (pcm->streams[0].substream) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
fsl_dma_hardware.buffer_bytes_max,
- &pcm->streams[0].substream->dma_buffer);
+ &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
if (ret) {
dev_err(card->dev, "can't alloc playback dma buffer\n");
return ret;
}
}
- if (pcm->streams[1].substream) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, card->dev,
fsl_dma_hardware.buffer_bytes_max,
- &pcm->streams[1].substream->dma_buffer);
+ &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
if (ret) {
dev_err(card->dev, "can't alloc capture dma buffer\n");
- snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
+ snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
return ret;
}
}
@@ -993,20 +992,7 @@ static struct platform_driver fsl_soc_dma_driver = {
.remove = __devexit_p(fsl_soc_dma_remove),
};
-static int __init fsl_soc_dma_init(void)
-{
- pr_info("Freescale Elo DMA ASoC PCM Driver\n");
-
- return platform_driver_register(&fsl_soc_dma_driver);
-}
-
-static void __exit fsl_soc_dma_exit(void)
-{
- platform_driver_unregister(&fsl_soc_dma_driver);
-}
-
-module_init(fsl_soc_dma_init);
-module_exit(fsl_soc_dma_exit);
+module_platform_driver(fsl_soc_dma_driver);
MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM Driver");
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index d48afea5d93d..2eb407fa3b48 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -78,7 +78,6 @@
* @second_stream: pointer to second stream
* @playback: the number of playback streams opened
* @capture: the number of capture streams opened
- * @asynchronous: 0=synchronous mode, 1=asynchronous mode
* @cpu_dai: the CPU DAI for this device
* @dev_attr: the sysfs device attribute structure
* @stats: SSI statistics
@@ -90,9 +89,6 @@ struct fsl_ssi_private {
unsigned int irq;
struct snd_pcm_substream *first_stream;
struct snd_pcm_substream *second_stream;
- unsigned int playback;
- unsigned int capture;
- int asynchronous;
unsigned int fifo_depth;
struct snd_soc_dai_driver cpu_dai_drv;
struct device_attribute dev_attr;
@@ -281,24 +277,18 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+ struct fsl_ssi_private *ssi_private =
+ snd_soc_dai_get_drvdata(rtd->cpu_dai);
+ int synchronous = ssi_private->cpu_dai_drv.symmetric_rates;
/*
* If this is the first stream opened, then request the IRQ
* and initialize the SSI registers.
*/
- if (!ssi_private->playback && !ssi_private->capture) {
+ if (!ssi_private->first_stream) {
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
- int ret;
-
- /* The 'name' should not have any slashes in it. */
- ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0,
- ssi_private->name, ssi_private);
- if (ret < 0) {
- dev_err(substream->pcm->card->dev,
- "could not claim irq %u\n", ssi_private->irq);
- return ret;
- }
+
+ ssi_private->first_stream = substream;
/*
* Section 16.5 of the MPC8610 reference manual says that the
@@ -316,7 +306,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
clrsetbits_be32(&ssi->scr,
CCSR_SSI_SCR_I2S_MODE_MASK | CCSR_SSI_SCR_SYN,
CCSR_SSI_SCR_TFR_CLK_DIS | CCSR_SSI_SCR_I2S_MODE_SLAVE
- | (ssi_private->asynchronous ? 0 : CCSR_SSI_SCR_SYN));
+ | (synchronous ? CCSR_SSI_SCR_SYN : 0));
out_be32(&ssi->stcr,
CCSR_SSI_STCR_TXBIT0 | CCSR_SSI_STCR_TFEN0 |
@@ -333,7 +323,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
* master.
*/
- /* 4. Enable the interrupts and DMA requests */
+ /* Enable the interrupts and DMA requests */
out_be32(&ssi->sier, SIER_FLAGS);
/*
@@ -362,58 +352,47 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
* this is bad is because at this point, the PCM driver has not
* finished initializing the DMA controller.
*/
- }
+ } else {
+ if (synchronous) {
+ struct snd_pcm_runtime *first_runtime =
+ ssi_private->first_stream->runtime;
+ /*
+ * This is the second stream open, and we're in
+ * synchronous mode, so we need to impose sample
+ * sample size constraints. This is because STCCR is
+ * used for playback and capture in synchronous mode,
+ * so there's no way to specify different word
+ * lengths.
+ *
+ * Note that this can cause a race condition if the
+ * second stream is opened before the first stream is
+ * fully initialized. We provide some protection by
+ * checking to make sure the first stream is
+ * initialized, but it's not perfect. ALSA sometimes
+ * re-initializes the driver with a different sample
+ * rate or size. If the second stream is opened
+ * before the first stream has received its final
+ * parameters, then the second stream may be
+ * constrained to the wrong sample rate or size.
+ */
+ if (!first_runtime->sample_bits) {
+ dev_err(substream->pcm->card->dev,
+ "set sample size in %s stream first\n",
+ substream->stream ==
+ SNDRV_PCM_STREAM_PLAYBACK
+ ? "capture" : "playback");
+ return -EAGAIN;
+ }
- if (!ssi_private->first_stream)
- ssi_private->first_stream = substream;
- else {
- /* This is the second stream open, so we need to impose sample
- * rate and maybe sample size constraints. Note that this can
- * cause a race condition if the second stream is opened before
- * the first stream is fully initialized.
- *
- * We provide some protection by checking to make sure the first
- * stream is initialized, but it's not perfect. ALSA sometimes
- * re-initializes the driver with a different sample rate or
- * size. If the second stream is opened before the first stream
- * has received its final parameters, then the second stream may
- * be constrained to the wrong sample rate or size.
- *
- * FIXME: This code does not handle opening and closing streams
- * repeatedly. If you open two streams and then close the first
- * one, you may not be able to open another stream until you
- * close the second one as well.
- */
- struct snd_pcm_runtime *first_runtime =
- ssi_private->first_stream->runtime;
-
- if (!first_runtime->sample_bits) {
- dev_err(substream->pcm->card->dev,
- "set sample size in %s stream first\n",
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK
- ? "capture" : "playback");
- return -EAGAIN;
- }
-
- /* If we're in synchronous mode, then we need to constrain
- * the sample size as well. We don't support independent sample
- * rates in asynchronous mode.
- */
- if (!ssi_private->asynchronous)
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
first_runtime->sample_bits,
first_runtime->sample_bits);
+ }
ssi_private->second_stream = substream;
}
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- ssi_private->playback++;
-
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- ssi_private->capture++;
-
return 0;
}
@@ -434,24 +413,35 @@ static int fsl_ssi_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params, struct snd_soc_dai *cpu_dai)
{
struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(cpu_dai);
+ struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
+ unsigned int sample_size =
+ snd_pcm_format_width(params_format(hw_params));
+ u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
+ int enabled = in_be32(&ssi->scr) & CCSR_SSI_SCR_SSIEN;
- if (substream == ssi_private->first_stream) {
- struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
- unsigned int sample_size =
- snd_pcm_format_width(params_format(hw_params));
- u32 wl = CCSR_SSI_SxCCR_WL(sample_size);
+ /*
+ * If we're in synchronous mode, and the SSI is already enabled,
+ * then STCCR is already set properly.
+ */
+ if (enabled && ssi_private->cpu_dai_drv.symmetric_rates)
+ return 0;
- /* The SSI should always be disabled at this points (SSIEN=0) */
+ /*
+ * FIXME: The documentation says that SxCCR[WL] should not be
+ * modified while the SSI is enabled. The only time this can
+ * happen is if we're trying to do simultaneous playback and
+ * capture in asynchronous mode. Unfortunately, I have been enable
+ * to get that to work at all on the P1022DS. Therefore, we don't
+ * bother to disable/enable the SSI when setting SxCCR[WL], because
+ * the SSI will stop anyway. Maybe one day, this will get fixed.
+ */
- /* In synchronous mode, the SSI uses STCCR for capture */
- if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
- !ssi_private->asynchronous)
- clrsetbits_be32(&ssi->stccr,
- CCSR_SSI_SxCCR_WL_MASK, wl);
- else
- clrsetbits_be32(&ssi->srccr,
- CCSR_SSI_SxCCR_WL_MASK, wl);
- }
+ /* In synchronous mode, the SSI uses STCCR for capture */
+ if ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ||
+ ssi_private->cpu_dai_drv.symmetric_rates)
+ clrsetbits_be32(&ssi->stccr, CCSR_SSI_SxCCR_WL_MASK, wl);
+ else
+ clrsetbits_be32(&ssi->srccr, CCSR_SSI_SxCCR_WL_MASK, wl);
return 0;
}
@@ -474,7 +464,6 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
setbits32(&ssi->scr,
@@ -510,31 +499,22 @@ static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = snd_soc_dai_get_drvdata(rtd->cpu_dai);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- ssi_private->playback--;
-
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- ssi_private->capture--;
-
if (ssi_private->first_stream == substream)
ssi_private->first_stream = ssi_private->second_stream;
ssi_private->second_stream = NULL;
/*
- * If this is the last active substream, disable the SSI and release
- * the IRQ.
+ * If this is the last active substream, disable the SSI.
*/
- if (!ssi_private->playback && !ssi_private->capture) {
+ if (!ssi_private->first_stream) {
struct ccsr_ssi __iomem *ssi = ssi_private->ssi;
clrbits32(&ssi->scr, CCSR_SSI_SCR_SSIEN);
-
- free_irq(ssi_private->irq, ssi_private);
}
}
-static struct snd_soc_dai_ops fsl_ssi_dai_ops = {
+static const struct snd_soc_dai_ops fsl_ssi_dai_ops = {
.startup = fsl_ssi_startup,
.hw_params = fsl_ssi_hw_params,
.shutdown = fsl_ssi_shutdown,
@@ -675,22 +655,33 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
ret = of_address_to_resource(np, 0, &res);
if (ret) {
dev_err(&pdev->dev, "could not determine device resources\n");
- kfree(ssi_private);
- return ret;
+ goto error_kmalloc;
}
ssi_private->ssi = of_iomap(np, 0);
if (!ssi_private->ssi) {
dev_err(&pdev->dev, "could not map device resources\n");
- kfree(ssi_private);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto error_kmalloc;
}
ssi_private->ssi_phys = res.start;
+
ssi_private->irq = irq_of_parse_and_map(np, 0);
+ if (ssi_private->irq == NO_IRQ) {
+ dev_err(&pdev->dev, "no irq for node %s\n", np->full_name);
+ ret = -ENXIO;
+ goto error_iomap;
+ }
+
+ /* The 'name' should not have any slashes in it. */
+ ret = request_irq(ssi_private->irq, fsl_ssi_isr, 0, ssi_private->name,
+ ssi_private);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "could not claim irq %u\n", ssi_private->irq);
+ goto error_irqmap;
+ }
/* Are the RX and the TX clocks locked? */
- if (of_find_property(np, "fsl,ssi-asynchronous", NULL))
- ssi_private->asynchronous = 1;
- else
+ if (!of_find_property(np, "fsl,ssi-asynchronous", NULL))
ssi_private->cpu_dai_drv.symmetric_rates = 1;
/* Determine the FIFO depth. */
@@ -703,6 +694,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
/* Initialize the the device_attribute structure */
dev_attr = &ssi_private->dev_attr;
+ sysfs_attr_init(&dev_attr->attr);
dev_attr->attr.name = "statistics";
dev_attr->attr.mode = S_IRUGO;
dev_attr->show = fsl_sysfs_ssi_show;
@@ -711,7 +703,7 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
if (ret) {
dev_err(&pdev->dev, "could not create sysfs %s file\n",
ssi_private->dev_attr.attr.name);
- goto error;
+ goto error_irq;
}
/* Register with ASoC */
@@ -720,16 +712,16 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
ret = snd_soc_register_dai(&pdev->dev, &ssi_private->cpu_dai_drv);
if (ret) {
dev_err(&pdev->dev, "failed to register DAI: %d\n", ret);
- goto error;
+ goto error_dev;
}
/* Trigger the machine driver's probe function. The platform driver
- * name of the machine driver is taken from the /model property of the
+ * name of the machine driver is taken from /compatible property of the
* device tree. We also pass the address of the CPU DAI driver
* structure.
*/
- sprop = of_get_property(of_find_node_by_path("/"), "model", NULL);
- /* Sometimes the model name has a "fsl," prefix, so we strip that. */
+ sprop = of_get_property(of_find_node_by_path("/"), "compatible", NULL);
+ /* Sometimes the compatible name has a "fsl," prefix, so we strip it. */
p = strrchr(sprop, ',');
if (p)
sprop = p + 1;
@@ -741,18 +733,28 @@ static int __devinit fsl_ssi_probe(struct platform_device *pdev)
if (IS_ERR(ssi_private->pdev)) {
ret = PTR_ERR(ssi_private->pdev);
dev_err(&pdev->dev, "failed to register platform: %d\n", ret);
- goto error;
+ goto error_dai;
}
return 0;
-error:
+error_dai:
snd_soc_unregister_dai(&pdev->dev);
+
+error_dev:
dev_set_drvdata(&pdev->dev, NULL);
- if (dev_attr)
- device_remove_file(&pdev->dev, dev_attr);
+ device_remove_file(&pdev->dev, dev_attr);
+
+error_irq:
+ free_irq(ssi_private->irq, ssi_private);
+
+error_irqmap:
irq_dispose_mapping(ssi_private->irq);
+
+error_iomap:
iounmap(ssi_private->ssi);
+
+error_kmalloc:
kfree(ssi_private);
return ret;
@@ -766,6 +768,9 @@ static int fsl_ssi_remove(struct platform_device *pdev)
snd_soc_unregister_dai(&pdev->dev);
device_remove_file(&pdev->dev, &ssi_private->dev_attr);
+ free_irq(ssi_private->irq, ssi_private);
+ irq_dispose_mapping(ssi_private->irq);
+
kfree(ssi_private);
dev_set_drvdata(&pdev->dev, NULL);
@@ -788,20 +793,7 @@ static struct platform_driver fsl_ssi_driver = {
.remove = fsl_ssi_remove,
};
-static int __init fsl_ssi_init(void)
-{
- printk(KERN_INFO "Freescale Synchronous Serial Interface (SSI) ASoC Driver\n");
-
- return platform_driver_register(&fsl_ssi_driver);
-}
-
-static void __exit fsl_ssi_exit(void)
-{
- platform_driver_unregister(&fsl_ssi_driver);
-}
-
-module_init(fsl_ssi_init);
-module_exit(fsl_ssi_exit);
+module_platform_driver(fsl_ssi_driver);
MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
MODULE_DESCRIPTION("Freescale Synchronous Serial Interface (SSI) ASoC Driver");
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c
index fd0dc46afc34..9a3f7c5ab687 100644
--- a/sound/soc/fsl/mpc5200_dma.c
+++ b/sound/soc/fsl/mpc5200_dma.c
@@ -8,6 +8,7 @@
#include <linux/module.h>
#include <linux/of_device.h>
+#include <linux/dma-mapping.h>
#include <linux/slab.h>
#include <linux/of_platform.h>
@@ -298,7 +299,7 @@ static struct snd_pcm_ops psc_dma_ops = {
.hw_params = psc_dma_hw_params,
};
-static u64 psc_dma_dmamask = 0xffffffff;
+static u64 psc_dma_dmamask = DMA_BIT_MASK(32);
static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
@@ -314,18 +315,18 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->dma_mask)
card->dev->dma_mask = &psc_dma_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (pcm->streams[0].substream) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
- size, &pcm->streams[0].substream->dma_buffer);
+ size, &pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
if (rc)
goto playback_alloc_err;
}
- if (pcm->streams[1].substream) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
rc = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, pcm->card->dev,
- size, &pcm->streams[1].substream->dma_buffer);
+ size, &pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream->dma_buffer);
if (rc)
goto capture_alloc_err;
}
@@ -336,8 +337,8 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd)
return 0;
capture_alloc_err:
- if (pcm->streams[0].substream)
- snd_dma_free_pages(&pcm->streams[0].substream->dma_buffer);
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
+ snd_dma_free_pages(&pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream->dma_buffer);
playback_alloc_err:
dev_err(card->dev, "Cannot allocate buffer(s)\n");
@@ -369,7 +370,7 @@ static struct snd_soc_platform_driver mpc5200_audio_dma_platform = {
.pcm_free = &psc_dma_free,
};
-static int mpc5200_hpcd_probe(struct of_device *op)
+static int mpc5200_hpcd_probe(struct platform_device *op)
{
phys_addr_t fifo;
struct psc_dma *psc_dma;
@@ -487,7 +488,7 @@ out_unmap:
return ret;
}
-static int mpc5200_hpcd_remove(struct of_device *op)
+static int mpc5200_hpcd_remove(struct platform_device *op)
{
struct psc_dma *psc_dma = dev_get_drvdata(&op->dev);
@@ -519,24 +520,14 @@ MODULE_DEVICE_TABLE(of, mpc5200_hpcd_match);
static struct platform_driver mpc5200_hpcd_of_driver = {
.probe = mpc5200_hpcd_probe,
.remove = mpc5200_hpcd_remove,
- .dev = {
+ .driver = {
.owner = THIS_MODULE,
.name = "mpc5200-pcm-audio",
.of_match_table = mpc5200_hpcd_match,
}
};
-static int __init mpc5200_hpcd_init(void)
-{
- return platform_driver_register(&mpc5200_hpcd_of_driver);
-}
-module_init(mpc5200_hpcd_init);
-
-static void __exit mpc5200_hpcd_exit(void)
-{
- platform_driver_unregister(&mpc5200_hpcd_of_driver);
-}
-module_exit(mpc5200_hpcd_exit);
+module_platform_driver(mpc5200_hpcd_of_driver);
MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
MODULE_DESCRIPTION("Freescale MPC5200 PSC in DMA mode ASoC Driver");
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c
index ad36b095bb79..ffa00a2eb770 100644
--- a/sound/soc/fsl/mpc5200_psc_ac97.c
+++ b/sound/soc/fsl/mpc5200_psc_ac97.c
@@ -226,12 +226,12 @@ static int psc_ac97_probe(struct snd_soc_dai *cpu_dai)
/**
* psc_ac97_dai_template: template CPU Digital Audio Interface
*/
-static struct snd_soc_dai_ops psc_ac97_analog_ops = {
+static const struct snd_soc_dai_ops psc_ac97_analog_ops = {
.hw_params = psc_ac97_hw_analog_params,
.trigger = psc_ac97_trigger,
};
-static struct snd_soc_dai_ops psc_ac97_digital_ops = {
+static const struct snd_soc_dai_ops psc_ac97_digital_ops = {
.hw_params = psc_ac97_hw_digital_params,
};
@@ -325,21 +325,7 @@ static struct platform_driver psc_ac97_driver = {
},
};
-/* ---------------------------------------------------------------------
- * Module setup and teardown; simply register the of_platform driver
- * for the PSC in AC97 mode.
- */
-static int __init psc_ac97_init(void)
-{
- return platform_driver_register(&psc_ac97_driver);
-}
-module_init(psc_ac97_init);
-
-static void __exit psc_ac97_exit(void)
-{
- platform_driver_unregister(&psc_ac97_driver);
-}
-module_exit(psc_ac97_exit);
+module_platform_driver(psc_ac97_driver);
MODULE_AUTHOR("Jon Smirl <jonsmirl@gmail.com>");
MODULE_DESCRIPTION("mpc5200 AC97 module");
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 87cf2a5c2b2c..7b530327553a 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -123,7 +123,7 @@ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
/**
* psc_i2s_dai_template: template CPU Digital Audio Interface
*/
-static struct snd_soc_dai_ops psc_i2s_dai_ops = {
+static const struct snd_soc_dai_ops psc_i2s_dai_ops = {
.hw_params = psc_i2s_hw_params,
.set_sysclk = psc_i2s_set_sysclk,
.set_fmt = psc_i2s_set_fmt,
@@ -222,21 +222,7 @@ static struct platform_driver psc_i2s_driver = {
},
};
-/* ---------------------------------------------------------------------
- * Module setup and teardown; simply register the of_platform driver
- * for the PSC in I2S mode.
- */
-static int __init psc_i2s_init(void)
-{
- return platform_driver_register(&psc_i2s_driver);
-}
-module_init(psc_i2s_init);
-
-static void __exit psc_i2s_exit(void)
-{
- platform_driver_unregister(&psc_i2s_driver);
-}
-module_exit(psc_i2s_exit);
+module_platform_driver(psc_i2s_driver);
MODULE_AUTHOR("Grant Likely <grant.likely@secretlab.ca>");
MODULE_DESCRIPTION("Freescale MPC5200 PSC in I2S mode ASoC Driver");
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index 358f0baaf71b..afbabf427f27 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -14,6 +14,7 @@
#include <linux/interrupt.h>
#include <linux/of_device.h>
#include <linux/slab.h>
+#include <linux/of_i2c.h>
#include <sound/soc.h>
#include <asm/fsl_guts.h>
@@ -244,13 +245,14 @@ static int get_parent_cell_index(struct device_node *np)
* 'struct device' It's ugly and hackish, but it works.
*
* The dev_name for such devices include the bus number and I2C address. For
- * example, "cs4270-codec.0-004f".
+ * example, "cs4270.0-004f".
*/
static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
{
const u32 *iprop;
- int bus, addr;
+ int addr;
char temp[DAI_NAME_SIZE];
+ struct i2c_client *i2c;
of_modalias_node(np, temp, DAI_NAME_SIZE);
@@ -260,17 +262,18 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
addr = be32_to_cpup(iprop);
- bus = get_parent_cell_index(np);
- if (bus < 0)
- return bus;
+ /* We need the adapter number */
+ i2c = of_find_i2c_device_by_node(np);
+ if (!i2c)
+ return -ENODEV;
- snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
+ snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr);
return 0;
}
static int get_dma_channel(struct device_node *ssi_np,
- const char *compatible,
+ const char *name,
struct snd_soc_dai_link *dai,
unsigned int *dma_channel_id,
unsigned int *dma_id)
@@ -280,7 +283,7 @@ static int get_dma_channel(struct device_node *ssi_np,
const u32 *iprop;
int ret;
- dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+ dma_channel_np = get_node_by_phandle_name(ssi_np, name,
"fsl,ssi-dma-channel");
if (!dma_channel_np)
return -EINVAL;
@@ -333,12 +336,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
const char *sprop;
const u32 *iprop;
- /* We are only interested in SSIs with a codec phandle in them,
- * so let's make sure this SSI has one. The MPC8610 HPCD only
- * knows about the CS4270 codec, so reject anything else.
- */
- codec_np = get_node_by_phandle_name(np, "codec-handle",
- "cirrus,cs4270");
+ /* Find the codec node for this SSI. */
+ codec_np = of_parse_phandle(np, "codec-handle", 0);
if (!codec_np) {
dev_err(dev, "invalid codec node\n");
return -EINVAL;
@@ -392,7 +391,8 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
}
if (strcasecmp(sprop, "i2s-slave") == 0) {
- machine_data->dai_format = SND_SOC_DAIFMT_I2S;
+ machine_data->dai_format =
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
@@ -409,31 +409,38 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
}
machine_data->clk_frequency = be32_to_cpup(iprop);
} else if (strcasecmp(sprop, "i2s-master") == 0) {
- machine_data->dai_format = SND_SOC_DAIFMT_I2S;
+ machine_data->dai_format =
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else if (strcasecmp(sprop, "lj-slave") == 0) {
- machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J;
+ machine_data->dai_format =
+ SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM;
machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
} else if (strcasecmp(sprop, "lj-master") == 0) {
- machine_data->dai_format = SND_SOC_DAIFMT_LEFT_J;
+ machine_data->dai_format =
+ SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS;
machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else if (strcasecmp(sprop, "rj-slave") == 0) {
- machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+ machine_data->dai_format =
+ SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM;
machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
} else if (strcasecmp(sprop, "rj-master") == 0) {
- machine_data->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+ machine_data->dai_format =
+ SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS;
machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else if (strcasecmp(sprop, "ac97-slave") == 0) {
- machine_data->dai_format = SND_SOC_DAIFMT_AC97;
+ machine_data->dai_format =
+ SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM;
machine_data->codec_clk_direction = SND_SOC_CLOCK_OUT;
machine_data->cpu_clk_direction = SND_SOC_CLOCK_IN;
} else if (strcasecmp(sprop, "ac97-master") == 0) {
- machine_data->dai_format = SND_SOC_DAIFMT_AC97;
+ machine_data->dai_format =
+ SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS;
machine_data->codec_clk_direction = SND_SOC_CLOCK_IN;
machine_data->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else {
@@ -505,7 +512,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev)
return 0;
error_sound:
- platform_device_unregister(sound_device);
+ platform_device_put(sound_device);
error:
kfree(machine_data);
error_alloc:
@@ -539,7 +546,7 @@ static struct platform_driver mpc8610_hpcd_driver = {
.probe = mpc8610_hpcd_probe,
.remove = __devexit_p(mpc8610_hpcd_remove),
.driver = {
- /* The name must match the 'model' property in the device tree,
+ /* The name must match 'compatible' property in the device tree,
* in lowercase letters.
*/
.name = "snd-soc-mpc8610hpcd",
diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c
index fcb862eb0c73..46623405a2ce 100644
--- a/sound/soc/fsl/p1022_ds.c
+++ b/sound/soc/fsl/p1022_ds.c
@@ -14,6 +14,7 @@
#include <linux/interrupt.h>
#include <linux/of_device.h>
#include <linux/slab.h>
+#include <linux/of_i2c.h>
#include <sound/soc.h>
#include <asm/fsl_guts.h>
@@ -252,8 +253,9 @@ static int get_parent_cell_index(struct device_node *np)
static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
{
const u32 *iprop;
- int bus, addr;
+ int addr;
char temp[DAI_NAME_SIZE];
+ struct i2c_client *i2c;
of_modalias_node(np, temp, DAI_NAME_SIZE);
@@ -263,17 +265,18 @@ static int codec_node_dev_name(struct device_node *np, char *buf, size_t len)
addr = be32_to_cpup(iprop);
- bus = get_parent_cell_index(np);
- if (bus < 0)
- return bus;
+ /* We need the adapter number */
+ i2c = of_find_i2c_device_by_node(np);
+ if (!i2c)
+ return -ENODEV;
- snprintf(buf, len, "%s-codec.%u-%04x", temp, bus, addr);
+ snprintf(buf, len, "%s.%u-%04x", temp, i2c->adapter->nr, addr);
return 0;
}
static int get_dma_channel(struct device_node *ssi_np,
- const char *compatible,
+ const char *name,
struct snd_soc_dai_link *dai,
unsigned int *dma_channel_id,
unsigned int *dma_id)
@@ -283,7 +286,7 @@ static int get_dma_channel(struct device_node *ssi_np,
const u32 *iprop;
int ret;
- dma_channel_np = get_node_by_phandle_name(ssi_np, compatible,
+ dma_channel_np = get_node_by_phandle_name(ssi_np, name,
"fsl,ssi-dma-channel");
if (!dma_channel_np)
return -EINVAL;
@@ -392,7 +395,8 @@ static int p1022_ds_probe(struct platform_device *pdev)
}
if (strcasecmp(sprop, "i2s-slave") == 0) {
- mdata->dai_format = SND_SOC_DAIFMT_I2S;
+ mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM;
mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
@@ -409,31 +413,38 @@ static int p1022_ds_probe(struct platform_device *pdev)
}
mdata->clk_frequency = be32_to_cpup(iprop);
} else if (strcasecmp(sprop, "i2s-master") == 0) {
- mdata->dai_format = SND_SOC_DAIFMT_I2S;
+ mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else if (strcasecmp(sprop, "lj-slave") == 0) {
- mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+ mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBM_CFM;
mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
} else if (strcasecmp(sprop, "lj-master") == 0) {
- mdata->dai_format = SND_SOC_DAIFMT_LEFT_J;
+ mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_LEFT_J | SND_SOC_DAIFMT_CBS_CFS;
mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else if (strcasecmp(sprop, "rj-slave") == 0) {
- mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+ mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBM_CFM;
mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
} else if (strcasecmp(sprop, "rj-master") == 0) {
- mdata->dai_format = SND_SOC_DAIFMT_RIGHT_J;
+ mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_RIGHT_J | SND_SOC_DAIFMT_CBS_CFS;
mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else if (strcasecmp(sprop, "ac97-slave") == 0) {
- mdata->dai_format = SND_SOC_DAIFMT_AC97;
+ mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBM_CFM;
mdata->codec_clk_direction = SND_SOC_CLOCK_OUT;
mdata->cpu_clk_direction = SND_SOC_CLOCK_IN;
} else if (strcasecmp(sprop, "ac97-master") == 0) {
- mdata->dai_format = SND_SOC_DAIFMT_AC97;
+ mdata->dai_format = SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_AC97 | SND_SOC_DAIFMT_CBS_CFS;
mdata->codec_clk_direction = SND_SOC_CLOCK_IN;
mdata->cpu_clk_direction = SND_SOC_CLOCK_OUT;
} else {
@@ -506,7 +517,7 @@ static int p1022_ds_probe(struct platform_device *pdev)
error:
if (sound_device)
- platform_device_unregister(sound_device);
+ platform_device_put(sound_device);
kfree(mdata);
error_put:
@@ -540,12 +551,11 @@ static struct platform_driver p1022_ds_driver = {
.probe = p1022_ds_probe,
.remove = __devexit_p(p1022_ds_remove),
.driver = {
- /* The name must match the 'model' property in the device tree,
- * in lowercase letters, but only the part after that last
- * comma. This is because some model properties have a "fsl,"
- * prefix.
+ /*
+ * The name must match 'compatible' property in the device tree,
+ * in lowercase letters.
*/
- .name = "snd-soc-p1022",
+ .name = "snd-soc-p1022ds",
.owner = THIS_MODULE,
},
};
@@ -560,12 +570,11 @@ static int __init p1022_ds_init(void)
struct device_node *guts_np;
struct resource res;
- pr_info("Freescale P1022 DS ALSA SoC machine driver\n");
-
/* Get the physical address of the global utilities registers */
guts_np = of_find_compatible_node(NULL, NULL, "fsl,p1022-guts");
if (of_address_to_resource(guts_np, 0, &res)) {
- pr_err("p1022-ds: missing/invalid global utilities node\n");
+ pr_err("snd-soc-p1022ds: missing/invalid global utils node\n");
+ of_node_put(guts_np);
return -EINVAL;
}
guts_phys = res.start;
diff --git a/sound/soc/fsl/pcm030-audio-fabric.c b/sound/soc/fsl/pcm030-audio-fabric.c
index ba4d85e317ed..b3af55dcde9d 100644
--- a/sound/soc/fsl/pcm030-audio-fabric.c
+++ b/sound/soc/fsl/pcm030-audio-fabric.c
@@ -31,8 +31,6 @@
#define DRV_NAME "pcm030-audio-fabric"
-static struct snd_soc_card card;
-
static struct snd_soc_dai_link pcm030_fabric_dai[] = {
{
.name = "AC97",
@@ -52,6 +50,13 @@ static struct snd_soc_dai_link pcm030_fabric_dai[] = {
},
};
+static struct snd_soc_card card = {
+ .name = "pcm030",
+ .owner = THIS_MODULE,
+ .dai_link = pcm030_fabric_dai,
+ .num_links = ARRAY_SIZE(pcm030_fabric_dai),
+};
+
static __init int pcm030_fabric_init(void)
{
struct platform_device *pdev;
@@ -60,11 +65,6 @@ static __init int pcm030_fabric_init(void)
if (!of_machine_is_compatible("phytec,pcm030"))
return -ENODEV;
-
- card.name = "pcm030";
- card.dai_link = pcm030_fabric_dai;
- card.num_links = ARRAY_SIZE(pcm030_fabric_dai);
-
pdev = platform_device_alloc("soc-audio", 1);
if (!pdev) {
pr_err("pcm030_fabric_init: platform_device_alloc() failed\n");
diff --git a/sound/soc/imx/Kconfig b/sound/soc/imx/Kconfig
index bb699bb55a50..810acaa09009 100644
--- a/sound/soc/imx/Kconfig
+++ b/sound/soc/imx/Kconfig
@@ -1,9 +1,6 @@
menuconfig SND_IMX_SOC
tristate "SoC Audio for Freescale i.MX CPUs"
depends on ARCH_MXC
- select SND_PCM
- select FIQ
- select SND_SOC_AC97_BUS
help
Say Y or M if you want to add support for codecs attached to
the i.MX SSI interface.
@@ -11,10 +8,23 @@ menuconfig SND_IMX_SOC
if SND_IMX_SOC
+config SND_SOC_IMX_SSI
+ tristate
+
+config SND_SOC_IMX_PCM
+ tristate
+
config SND_MXC_SOC_FIQ
tristate
+ select FIQ
+ select SND_SOC_IMX_PCM
config SND_MXC_SOC_MX2
+ select SND_SOC_DMAENGINE_PCM
+ tristate
+ select SND_SOC_IMX_PCM
+
+config SND_SOC_IMX_AUDMUX
tristate
config SND_MXC_SOC_WM1133_EV1
@@ -22,15 +32,19 @@ config SND_MXC_SOC_WM1133_EV1
depends on MACH_MX31ADS_WM1133_EV1 && EXPERIMENTAL
select SND_SOC_WM8350
select SND_MXC_SOC_FIQ
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
help
Enable support for audio on the i.MX31ADS with the WM1133-EV1
PMIC board with WM8835x fitted.
config SND_SOC_MX27VIS_AIC32X4
tristate "SoC audio support for Visstrim M10 boards"
- depends on MACH_IMX27_VISSTRIM_M10
- select SND_SOC_TVL320AIC32X4
+ depends on MACH_IMX27_VISSTRIM_M10 && I2C
+ select SND_SOC_TLV320AIC32X4
select SND_MXC_SOC_MX2
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
help
Say Y if you want to add support for SoC audio on Visstrim SM10
board with TLV320AIC32X4 codec.
@@ -38,8 +52,11 @@ config SND_SOC_MX27VIS_AIC32X4
config SND_SOC_PHYCORE_AC97
tristate "SoC Audio support for Phytec phyCORE (and phyCARD) boards"
depends on MACH_PCM043 || MACH_PCA100
+ select SND_SOC_AC97_BUS
select SND_SOC_WM9712
select SND_MXC_SOC_FIQ
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
help
Say Y if you want to add support for SoC audio on Phytec phyCORE
and phyCARD boards in AC97 mode
@@ -50,8 +67,11 @@ config SND_SOC_EUKREA_TLV320
|| MACH_EUKREA_MBIMXSD25_BASEBOARD \
|| MACH_EUKREA_MBIMXSD35_BASEBOARD \
|| MACH_EUKREA_MBIMXSD51_BASEBOARD
+ depends on I2C
select SND_SOC_TLV320AIC23
select SND_MXC_SOC_FIQ
+ select SND_SOC_IMX_AUDMUX
+ select SND_SOC_IMX_SSI
help
Enable I2S based access to the TLV320AIC23B codec attached
to the SSI interface
diff --git a/sound/soc/imx/Makefile b/sound/soc/imx/Makefile
index d6d609ba7e24..f5db3e92d0d1 100644
--- a/sound/soc/imx/Makefile
+++ b/sound/soc/imx/Makefile
@@ -1,11 +1,14 @@
# i.MX Platform Support
-snd-soc-imx-objs := imx-ssi.o
-snd-soc-imx-fiq-objs := imx-pcm-fiq.o
-snd-soc-imx-mx2-objs := imx-pcm-dma-mx2.o
+snd-soc-imx-ssi-objs := imx-ssi.o
+snd-soc-imx-audmux-objs := imx-audmux.o
-obj-$(CONFIG_SND_IMX_SOC) += snd-soc-imx.o
-obj-$(CONFIG_SND_MXC_SOC_FIQ) += snd-soc-imx-fiq.o
-obj-$(CONFIG_SND_MXC_SOC_MX2) += snd-soc-imx-mx2.o
+obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
+obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
+
+obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
+snd-soc-imx-pcm-y := imx-pcm.o
+snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_FIQ) += imx-pcm-fiq.o
+snd-soc-imx-pcm-$(CONFIG_SND_MXC_SOC_MX2) += imx-pcm-dma-mx2.o
# i.MX Machine Support
snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/imx/eukrea-tlv320.c b/sound/soc/imx/eukrea-tlv320.c
index 75fb4b83548b..7d4475cfdb24 100644
--- a/sound/soc/imx/eukrea-tlv320.c
+++ b/sound/soc/imx/eukrea-tlv320.c
@@ -26,6 +26,7 @@
#include "../codecs/tlv320aic23.h"
#include "imx-ssi.h"
+#include "imx-audmux.h"
#define CODEC_CLOCK 12000000
@@ -87,6 +88,7 @@ static struct snd_soc_dai_link eukrea_tlv320_dai = {
static struct snd_soc_card eukrea_tlv320 = {
.name = "cpuimx-audio",
+ .owner = THIS_MODULE,
.dai_link = &eukrea_tlv320_dai,
.num_links = 1,
};
@@ -96,12 +98,43 @@ static struct platform_device *eukrea_tlv320_snd_device;
static int __init eukrea_tlv320_init(void)
{
int ret;
-
- if (!machine_is_eukrea_cpuimx27() && !machine_is_eukrea_cpuimx25sd()
- && !machine_is_eukrea_cpuimx35sd()
- && !machine_is_eukrea_cpuimx51sd())
+ int int_port = 0, ext_port;
+
+ if (machine_is_eukrea_cpuimx27()) {
+ imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+ IMX_AUDMUX_V1_PCR_SYN |
+ IMX_AUDMUX_V1_PCR_TFSDIR |
+ IMX_AUDMUX_V1_PCR_TCLKDIR |
+ IMX_AUDMUX_V1_PCR_RFSDIR |
+ IMX_AUDMUX_V1_PCR_RCLKDIR |
+ IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
+ IMX_AUDMUX_V1_PCR_RFCSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4) |
+ IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR3_SSI_PINS_4)
+ );
+ imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR3_SSI_PINS_4,
+ IMX_AUDMUX_V1_PCR_SYN |
+ IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
+ );
+ } else if (machine_is_eukrea_cpuimx25sd() ||
+ machine_is_eukrea_cpuimx35sd() ||
+ machine_is_eukrea_cpuimx51sd()) {
+ ext_port = machine_is_eukrea_cpuimx25sd() ? 4 : 3;
+ imx_audmux_v2_configure_port(int_port,
+ IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TFSEL(ext_port) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR |
+ IMX_AUDMUX_V2_PTCR_TCSEL(ext_port),
+ IMX_AUDMUX_V2_PDCR_RXDSEL(ext_port)
+ );
+ imx_audmux_v2_configure_port(ext_port,
+ IMX_AUDMUX_V2_PTCR_SYN,
+ IMX_AUDMUX_V2_PDCR_RXDSEL(int_port)
+ );
+ } else {
/* return happy. We might run on a totally different machine */
return 0;
+ }
eukrea_tlv320_snd_device = platform_device_alloc("soc-audio", -1);
if (!eukrea_tlv320_snd_device)
diff --git a/sound/soc/imx/imx-audmux.c b/sound/soc/imx/imx-audmux.c
new file mode 100644
index 000000000000..a839494c5ea8
--- /dev/null
+++ b/sound/soc/imx/imx-audmux.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright 2012 Freescale Semiconductor, Inc.
+ * Copyright 2012 Linaro Ltd.
+ * Copyright 2009 Pengutronix, Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * Initial development of this code was funded by
+ * Phytec Messtechnik GmbH, http://www.phytec.de
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/debugfs.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+
+#include "imx-audmux.h"
+
+#define DRIVER_NAME "imx-audmux"
+
+static struct clk *audmux_clk;
+static void __iomem *audmux_base;
+
+#define IMX_AUDMUX_V2_PTCR(x) ((x) * 8)
+#define IMX_AUDMUX_V2_PDCR(x) ((x) * 8 + 4)
+
+#ifdef CONFIG_DEBUG_FS
+static struct dentry *audmux_debugfs_root;
+
+static int audmux_open_file(struct inode *inode, struct file *file)
+{
+ file->private_data = inode->i_private;
+ return 0;
+}
+
+/* There is an annoying discontinuity in the SSI numbering with regard
+ * to the Linux number of the devices */
+static const char *audmux_port_string(int port)
+{
+ switch (port) {
+ case MX31_AUDMUX_PORT1_SSI0:
+ return "imx-ssi.0";
+ case MX31_AUDMUX_PORT2_SSI1:
+ return "imx-ssi.1";
+ case MX31_AUDMUX_PORT3_SSI_PINS_3:
+ return "SSI3";
+ case MX31_AUDMUX_PORT4_SSI_PINS_4:
+ return "SSI4";
+ case MX31_AUDMUX_PORT5_SSI_PINS_5:
+ return "SSI5";
+ case MX31_AUDMUX_PORT6_SSI_PINS_6:
+ return "SSI6";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ ssize_t ret;
+ char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+ int port = (int)file->private_data;
+ u32 pdcr, ptcr;
+
+ if (!buf)
+ return -ENOMEM;
+
+ if (audmux_clk)
+ clk_enable(audmux_clk);
+
+ ptcr = readl(audmux_base + IMX_AUDMUX_V2_PTCR(port));
+ pdcr = readl(audmux_base + IMX_AUDMUX_V2_PDCR(port));
+
+ if (audmux_clk)
+ clk_disable(audmux_clk);
+
+ ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
+ pdcr, ptcr);
+
+ if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "TxFS output from %s, ",
+ audmux_port_string((ptcr >> 27) & 0x7));
+ else
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "TxFS input, ");
+
+ if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "TxClk output from %s",
+ audmux_port_string((ptcr >> 22) & 0x7));
+ else
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "TxClk input");
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+
+ if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "Port is symmetric");
+ } else {
+ if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "RxFS output from %s, ",
+ audmux_port_string((ptcr >> 17) & 0x7));
+ else
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "RxFS input, ");
+
+ if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "RxClk output from %s",
+ audmux_port_string((ptcr >> 12) & 0x7));
+ else
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "RxClk input");
+ }
+
+ ret += snprintf(buf + ret, PAGE_SIZE - ret,
+ "\nData received from %s\n",
+ audmux_port_string((pdcr >> 13) & 0x7));
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
+
+ kfree(buf);
+
+ return ret;
+}
+
+static const struct file_operations audmux_debugfs_fops = {
+ .open = audmux_open_file,
+ .read = audmux_read_file,
+ .llseek = default_llseek,
+};
+
+static void __init audmux_debugfs_init(void)
+{
+ int i;
+ char buf[20];
+
+ audmux_debugfs_root = debugfs_create_dir("audmux", NULL);
+ if (!audmux_debugfs_root) {
+ pr_warning("Failed to create AUDMUX debugfs root\n");
+ return;
+ }
+
+ for (i = 1; i < 8; i++) {
+ snprintf(buf, sizeof(buf), "ssi%d", i);
+ if (!debugfs_create_file(buf, 0444, audmux_debugfs_root,
+ (void *)i, &audmux_debugfs_fops))
+ pr_warning("Failed to create AUDMUX port %d debugfs file\n",
+ i);
+ }
+}
+
+static void __devexit audmux_debugfs_remove(void)
+{
+ debugfs_remove_recursive(audmux_debugfs_root);
+}
+#else
+static inline void audmux_debugfs_init(void)
+{
+}
+
+static inline void audmux_debugfs_remove(void)
+{
+}
+#endif
+
+enum imx_audmux_type {
+ IMX21_AUDMUX,
+ IMX31_AUDMUX,
+} audmux_type;
+
+static struct platform_device_id imx_audmux_ids[] = {
+ {
+ .name = "imx21-audmux",
+ .driver_data = IMX21_AUDMUX,
+ }, {
+ .name = "imx31-audmux",
+ .driver_data = IMX31_AUDMUX,
+ }, {
+ /* sentinel */
+ }
+};
+MODULE_DEVICE_TABLE(platform, imx_audmux_ids);
+
+static const struct of_device_id imx_audmux_dt_ids[] = {
+ { .compatible = "fsl,imx21-audmux", .data = &imx_audmux_ids[0], },
+ { .compatible = "fsl,imx31-audmux", .data = &imx_audmux_ids[1], },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, imx_audmux_dt_ids);
+
+static const uint8_t port_mapping[] = {
+ 0x0, 0x4, 0x8, 0x10, 0x14, 0x1c,
+};
+
+int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr)
+{
+ if (audmux_type != IMX21_AUDMUX)
+ return -EINVAL;
+
+ if (!audmux_base)
+ return -ENOSYS;
+
+ if (port >= ARRAY_SIZE(port_mapping))
+ return -EINVAL;
+
+ writel(pcr, audmux_base + port_mapping[port]);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(imx_audmux_v1_configure_port);
+
+int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
+ unsigned int pdcr)
+{
+ if (audmux_type != IMX31_AUDMUX)
+ return -EINVAL;
+
+ if (!audmux_base)
+ return -ENOSYS;
+
+ if (audmux_clk)
+ clk_enable(audmux_clk);
+
+ writel(ptcr, audmux_base + IMX_AUDMUX_V2_PTCR(port));
+ writel(pdcr, audmux_base + IMX_AUDMUX_V2_PDCR(port));
+
+ if (audmux_clk)
+ clk_disable(audmux_clk);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(imx_audmux_v2_configure_port);
+
+static int __devinit imx_audmux_probe(struct platform_device *pdev)
+{
+ struct resource *res;
+ const struct of_device_id *of_id =
+ of_match_device(imx_audmux_dt_ids, &pdev->dev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ audmux_base = devm_request_and_ioremap(&pdev->dev, res);
+ if (!audmux_base)
+ return -EADDRNOTAVAIL;
+
+ audmux_clk = clk_get(&pdev->dev, "audmux");
+ if (IS_ERR(audmux_clk)) {
+ dev_dbg(&pdev->dev, "cannot get clock: %ld\n",
+ PTR_ERR(audmux_clk));
+ audmux_clk = NULL;
+ }
+
+ if (of_id)
+ pdev->id_entry = of_id->data;
+ audmux_type = pdev->id_entry->driver_data;
+ if (audmux_type == IMX31_AUDMUX)
+ audmux_debugfs_init();
+
+ return 0;
+}
+
+static int __devexit imx_audmux_remove(struct platform_device *pdev)
+{
+ if (audmux_type == IMX31_AUDMUX)
+ audmux_debugfs_remove();
+ clk_put(audmux_clk);
+
+ return 0;
+}
+
+static struct platform_driver imx_audmux_driver = {
+ .probe = imx_audmux_probe,
+ .remove = __devexit_p(imx_audmux_remove),
+ .id_table = imx_audmux_ids,
+ .driver = {
+ .name = DRIVER_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = imx_audmux_dt_ids,
+ }
+};
+
+static int __init imx_audmux_init(void)
+{
+ return platform_driver_register(&imx_audmux_driver);
+}
+subsys_initcall(imx_audmux_init);
+
+static void __exit imx_audmux_exit(void)
+{
+ platform_driver_unregister(&imx_audmux_driver);
+}
+module_exit(imx_audmux_exit);
+
+MODULE_DESCRIPTION("Freescale i.MX AUDMUX driver");
+MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/sound/soc/imx/imx-audmux.h b/sound/soc/imx/imx-audmux.h
new file mode 100644
index 000000000000..04ebbab8d7b9
--- /dev/null
+++ b/sound/soc/imx/imx-audmux.h
@@ -0,0 +1,60 @@
+#ifndef __IMX_AUDMUX_H
+#define __IMX_AUDMUX_H
+
+#define MX27_AUDMUX_HPCR1_SSI0 0
+#define MX27_AUDMUX_HPCR2_SSI1 1
+#define MX27_AUDMUX_HPCR3_SSI_PINS_4 2
+#define MX27_AUDMUX_PPCR1_SSI_PINS_1 3
+#define MX27_AUDMUX_PPCR2_SSI_PINS_2 4
+#define MX27_AUDMUX_PPCR3_SSI_PINS_3 5
+
+#define MX31_AUDMUX_PORT1_SSI0 0
+#define MX31_AUDMUX_PORT2_SSI1 1
+#define MX31_AUDMUX_PORT3_SSI_PINS_3 2
+#define MX31_AUDMUX_PORT4_SSI_PINS_4 3
+#define MX31_AUDMUX_PORT5_SSI_PINS_5 4
+#define MX31_AUDMUX_PORT6_SSI_PINS_6 5
+
+#define MX51_AUDMUX_PORT1_SSI0 0
+#define MX51_AUDMUX_PORT2_SSI1 1
+#define MX51_AUDMUX_PORT3 2
+#define MX51_AUDMUX_PORT4 3
+#define MX51_AUDMUX_PORT5 4
+#define MX51_AUDMUX_PORT6 5
+#define MX51_AUDMUX_PORT7 6
+
+/* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
+#define IMX_AUDMUX_V1_PCR_INMMASK(x) ((x) & 0xff)
+#define IMX_AUDMUX_V1_PCR_INMEN (1 << 8)
+#define IMX_AUDMUX_V1_PCR_TXRXEN (1 << 10)
+#define IMX_AUDMUX_V1_PCR_SYN (1 << 12)
+#define IMX_AUDMUX_V1_PCR_RXDSEL(x) (((x) & 0x7) << 13)
+#define IMX_AUDMUX_V1_PCR_RFCSEL(x) (((x) & 0xf) << 20)
+#define IMX_AUDMUX_V1_PCR_RCLKDIR (1 << 24)
+#define IMX_AUDMUX_V1_PCR_RFSDIR (1 << 25)
+#define IMX_AUDMUX_V1_PCR_TFCSEL(x) (((x) & 0xf) << 26)
+#define IMX_AUDMUX_V1_PCR_TCLKDIR (1 << 30)
+#define IMX_AUDMUX_V1_PCR_TFSDIR (1 << 31)
+
+/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
+#define IMX_AUDMUX_V2_PTCR_TFSDIR (1 << 31)
+#define IMX_AUDMUX_V2_PTCR_TFSEL(x) (((x) & 0xf) << 27)
+#define IMX_AUDMUX_V2_PTCR_TCLKDIR (1 << 26)
+#define IMX_AUDMUX_V2_PTCR_TCSEL(x) (((x) & 0xf) << 22)
+#define IMX_AUDMUX_V2_PTCR_RFSDIR (1 << 21)
+#define IMX_AUDMUX_V2_PTCR_RFSEL(x) (((x) & 0xf) << 17)
+#define IMX_AUDMUX_V2_PTCR_RCLKDIR (1 << 16)
+#define IMX_AUDMUX_V2_PTCR_RCSEL(x) (((x) & 0xf) << 12)
+#define IMX_AUDMUX_V2_PTCR_SYN (1 << 11)
+
+#define IMX_AUDMUX_V2_PDCR_RXDSEL(x) (((x) & 0x7) << 13)
+#define IMX_AUDMUX_V2_PDCR_TXRXEN (1 << 12)
+#define IMX_AUDMUX_V2_PDCR_MODE(x) (((x) & 0x3) << 8)
+#define IMX_AUDMUX_V2_PDCR_INMMASK(x) ((x) & 0xff)
+
+int imx_audmux_v1_configure_port(unsigned int port, unsigned int pcr);
+
+int imx_audmux_v2_configure_port(unsigned int port, unsigned int ptcr,
+ unsigned int pdcr);
+
+#endif /* __IMX_AUDMUX_H */
diff --git a/sound/soc/imx/imx-pcm-dma-mx2.c b/sound/soc/imx/imx-pcm-dma-mx2.c
index 43fdc24f7e8d..e43c8fa2788b 100644
--- a/sound/soc/imx/imx-pcm-dma-mx2.c
+++ b/sound/soc/imx/imx-pcm-dma-mx2.c
@@ -27,210 +27,54 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
#include <mach/dma.h>
-#include "imx-ssi.h"
-
-struct imx_pcm_runtime_data {
- int period_bytes;
- int periods;
- int dma;
- unsigned long offset;
- unsigned long size;
- void *buf;
- int period_time;
- struct dma_async_tx_descriptor *desc;
- struct dma_chan *dma_chan;
- struct imx_dma_data dma_data;
-};
-
-static void audio_dma_irq(void *data)
-{
- struct snd_pcm_substream *substream = (struct snd_pcm_substream *)data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- iprtd->offset += iprtd->period_bytes;
- iprtd->offset %= iprtd->period_bytes * iprtd->periods;
-
- snd_pcm_period_elapsed(substream);
-}
+#include "imx-pcm.h"
static bool filter(struct dma_chan *chan, void *param)
{
- struct imx_pcm_runtime_data *iprtd = param;
-
if (!imx_dma_is_general_purpose(chan))
return false;
- chan->private = &iprtd->dma_data;
+ chan->private = param;
- return true;
+ return true;
}
-static int imx_ssi_dma_alloc(struct snd_pcm_substream *substream,
+static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct dma_chan *chan = snd_dmaengine_pcm_get_chan(substream);
struct imx_pcm_dma_params *dma_params;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
struct dma_slave_config slave_config;
- dma_cap_mask_t mask;
- enum dma_slave_buswidth buswidth;
int ret;
dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- iprtd->dma_data.peripheral_type = IMX_DMATYPE_SSI;
- iprtd->dma_data.priority = DMA_PRIO_HIGH;
- iprtd->dma_data.dma_request = dma_params->dma;
-
- /* Try to grab a DMA channel */
- dma_cap_zero(mask);
- dma_cap_set(DMA_SLAVE, mask);
- iprtd->dma_chan = dma_request_channel(mask, filter, iprtd);
- if (!iprtd->dma_chan)
- return -EINVAL;
-
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
- break;
- case SNDRV_PCM_FORMAT_S20_3LE:
- case SNDRV_PCM_FORMAT_S24_LE:
- buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
- break;
- default:
- return 0;
- }
+ ret = snd_hwparams_to_dma_slave_config(substream, params, &slave_config);
+ if (ret)
+ return ret;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- slave_config.direction = DMA_TO_DEVICE;
slave_config.dst_addr = dma_params->dma_addr;
- slave_config.dst_addr_width = buswidth;
slave_config.dst_maxburst = dma_params->burstsize;
} else {
- slave_config.direction = DMA_FROM_DEVICE;
slave_config.src_addr = dma_params->dma_addr;
- slave_config.src_addr_width = buswidth;
slave_config.src_maxburst = dma_params->burstsize;
}
- ret = dmaengine_slave_config(iprtd->dma_chan, &slave_config);
+ ret = dmaengine_slave_config(chan, &slave_config);
if (ret)
return ret;
- return 0;
-}
-
-static int snd_imx_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
- unsigned long dma_addr;
- struct dma_chan *chan;
- struct imx_pcm_dma_params *dma_params;
- int ret;
-
- dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- ret = imx_ssi_dma_alloc(substream, params);
- if (ret)
- return ret;
- chan = iprtd->dma_chan;
-
- iprtd->size = params_buffer_bytes(params);
- iprtd->periods = params_periods(params);
- iprtd->period_bytes = params_period_bytes(params);
- iprtd->offset = 0;
- iprtd->period_time = HZ / (params_rate(params) /
- params_period_size(params));
-
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- dma_addr = runtime->dma_addr;
-
- iprtd->buf = (unsigned int *)substream->dma_buffer.area;
-
- iprtd->desc = chan->device->device_prep_dma_cyclic(chan, dma_addr,
- iprtd->period_bytes * iprtd->periods,
- iprtd->period_bytes,
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE);
- if (!iprtd->desc) {
- dev_err(&chan->dev->device, "cannot prepare slave dma\n");
- return -EINVAL;
- }
-
- iprtd->desc->callback = audio_dma_irq;
- iprtd->desc->callback_param = substream;
-
- return 0;
-}
-
-static int snd_imx_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- if (iprtd->dma_chan) {
- dma_release_channel(iprtd->dma_chan);
- iprtd->dma_chan = NULL;
- }
-
return 0;
}
-static int snd_imx_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct imx_pcm_dma_params *dma_params;
-
- dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
-
- return 0;
-}
-
-static int snd_imx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- dmaengine_submit(iprtd->desc);
-
- break;
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- dmaengine_terminate_all(iprtd->dma_chan);
-
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static snd_pcm_uframes_t snd_imx_pcm_pointer(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
-
- pr_debug("%s: %ld %ld\n", __func__, iprtd->offset,
- bytes_to_frames(substream->runtime, iprtd->offset));
-
- return bytes_to_frames(substream->runtime, iprtd->offset);
-}
-
static struct snd_pcm_hardware snd_imx_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -252,33 +96,37 @@ static struct snd_pcm_hardware snd_imx_hardware = {
static int snd_imx_open(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct imx_pcm_dma_params *dma_params;
+ struct imx_dma_data *dma_data;
int ret;
- iprtd = kzalloc(sizeof(*iprtd), GFP_KERNEL);
- if (iprtd == NULL)
- return -ENOMEM;
- runtime->private_data = iprtd;
+ snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
- ret = snd_pcm_hw_constraint_integer(substream->runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0) {
- kfree(iprtd);
- return ret;
+ dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+
+ dma_data = kzalloc(sizeof(*dma_data), GFP_KERNEL);
+ dma_data->peripheral_type = IMX_DMATYPE_SSI;
+ dma_data->priority = DMA_PRIO_HIGH;
+ dma_data->dma_request = dma_params->dma;
+
+ ret = snd_dmaengine_pcm_open(substream, filter, dma_data);
+ if (ret) {
+ kfree(dma_data);
+ return 0;
}
- snd_soc_set_runtime_hwparams(substream, &snd_imx_hardware);
+ snd_dmaengine_pcm_set_data(substream, dma_data);
return 0;
}
static int snd_imx_close(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct imx_pcm_runtime_data *iprtd = runtime->private_data;
+ struct imx_dma_data *dma_data = snd_dmaengine_pcm_get_data(substream);
- kfree(iprtd);
+ snd_dmaengine_pcm_close(substream);
+ kfree(dma_data);
return 0;
}
@@ -288,10 +136,8 @@ static struct snd_pcm_ops imx_pcm_ops = {
.close = snd_imx_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = snd_imx_pcm_hw_params,
- .hw_free = snd_imx_pcm_hw_free,
- .prepare = snd_imx_pcm_prepare,
- .trigger = snd_imx_pcm_trigger,
- .pointer = snd_imx_pcm_pointer,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer,
.mmap = snd_imx_pcm_mmap,
};
@@ -303,11 +149,6 @@ static struct snd_soc_platform_driver imx_soc_platform_mx2 = {
static int __devinit imx_soc_platform_probe(struct platform_device *pdev)
{
- struct imx_ssi *ssi = platform_get_drvdata(pdev);
-
- ssi->dma_params_tx.burstsize = 6;
- ssi->dma_params_rx.burstsize = 4;
-
return snd_soc_register_platform(&pdev->dev, &imx_soc_platform_mx2);
}
@@ -326,16 +167,6 @@ static struct platform_driver imx_pcm_driver = {
.remove = __devexit_p(imx_soc_platform_remove),
};
-static int __init snd_imx_pcm_init(void)
-{
- return platform_driver_register(&imx_pcm_driver);
-}
-module_init(snd_imx_pcm_init);
-
-static void __exit snd_imx_pcm_exit(void)
-{
- platform_driver_unregister(&imx_pcm_driver);
-}
-module_exit(snd_imx_pcm_exit);
+module_platform_driver(imx_pcm_driver);
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:imx-pcm-audio");
diff --git a/sound/soc/imx/imx-pcm-fiq.c b/sound/soc/imx/imx-pcm-fiq.c
index 309c59e6fb6c..456b7d723d66 100644
--- a/sound/soc/imx/imx-pcm-fiq.c
+++ b/sound/soc/imx/imx-pcm-fiq.c
@@ -240,26 +240,23 @@ static int ssi_irq = 0;
static int imx_pcm_fiq_new(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
+ struct snd_pcm_substream *substream;
int ret;
ret = imx_pcm_new(rtd);
if (ret)
return ret;
- if (dai->driver->playback.channels_min) {
- struct snd_pcm_substream *substream =
- pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
+ if (substream) {
struct snd_dma_buffer *buf = &substream->dma_buffer;
imx_ssi_fiq_tx_buffer = (unsigned long)buf->area;
}
- if (dai->driver->capture.channels_min) {
- struct snd_pcm_substream *substream =
- pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+ substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
+ if (substream) {
struct snd_dma_buffer *buf = &substream->dma_buffer;
imx_ssi_fiq_rx_buffer = (unsigned long)buf->area;
@@ -334,14 +331,6 @@ static struct platform_driver imx_pcm_driver = {
.remove = __devexit_p(imx_soc_platform_remove),
};
-static int __init snd_imx_pcm_init(void)
-{
- return platform_driver_register(&imx_pcm_driver);
-}
-module_init(snd_imx_pcm_init);
+module_platform_driver(imx_pcm_driver);
-static void __exit snd_imx_pcm_exit(void)
-{
- platform_driver_unregister(&imx_pcm_driver);
-}
-module_exit(snd_imx_pcm_exit);
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/imx/imx-pcm.c b/sound/soc/imx/imx-pcm.c
new file mode 100644
index 000000000000..93dc360b1777
--- /dev/null
+++ b/sound/soc/imx/imx-pcm.c
@@ -0,0 +1,105 @@
+/*
+ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This code is based on code copyrighted by Freescale,
+ * Liam Girdwood, Javier Martin and probably others.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/dma-mapping.h>
+#include <linux/module.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include "imx-pcm.h"
+
+int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ int ret;
+
+ ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
+
+ pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
+ runtime->dma_area,
+ runtime->dma_addr,
+ runtime->dma_bytes);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
+
+static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = IMX_SSI_DMABUF_SIZE;
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ if (!buf->area)
+ return -ENOMEM;
+ buf->bytes = size;
+
+ return 0;
+}
+
+static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
+
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm *pcm = rtd->pcm;
+ int ret = 0;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &imx_pcm_dmamask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ ret = imx_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ ret = imx_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+
+out:
+ return ret;
+}
+EXPORT_SYMBOL_GPL(imx_pcm_new);
+
+void imx_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+
+ dma_free_writecombine(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+EXPORT_SYMBOL_GPL(imx_pcm_free);
diff --git a/sound/soc/imx/imx-pcm.h b/sound/soc/imx/imx-pcm.h
new file mode 100644
index 000000000000..b5f5c3acf34d
--- /dev/null
+++ b/sound/soc/imx/imx-pcm.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ *
+ * This code is based on code copyrighted by Freescale,
+ * Liam Girdwood, Javier Martin and probably others.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _IMX_PCM_H
+#define _IMX_PCM_H
+
+/*
+ * Do not change this as the FIQ handler depends on this size
+ */
+#define IMX_SSI_DMABUF_SIZE (64 * 1024)
+
+struct imx_pcm_dma_params {
+ int dma;
+ unsigned long dma_addr;
+ int burstsize;
+};
+
+int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma);
+int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
+void imx_pcm_free(struct snd_pcm *pcm);
+
+#endif /* _IMX_PCM_H */
diff --git a/sound/soc/imx/imx-ssi.c b/sound/soc/imx/imx-ssi.c
index 10a8e2783751..4f81ed456325 100644
--- a/sound/soc/imx/imx-ssi.c
+++ b/sound/soc/imx/imx-ssi.c
@@ -112,7 +112,7 @@ static int imx_ssi_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
break;
case SND_SOC_DAIFMT_DSP_A:
/* data on rising edge of bclk, frame high 1clk before data */
- strcr |= SSI_STCR_TFSL | SSI_STCR_TEFS;
+ strcr |= SSI_STCR_TFSL | SSI_STCR_TXBIT0 | SSI_STCR_TEFS;
break;
}
@@ -233,6 +233,23 @@ static int imx_ssi_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
return 0;
}
+static int imx_ssi_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
+ struct imx_pcm_dma_params *dma_data;
+
+ /* Tx/Rx config */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ dma_data = &ssi->dma_params_tx;
+ else
+ dma_data = &ssi->dma_params_rx;
+
+ snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
+
+ return 0;
+}
+
/*
* Should only be called when port is inactive (i.e. SSIEN = 0),
* although can be called multiple times by upper layers.
@@ -242,23 +259,17 @@ static int imx_ssi_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
struct imx_ssi *ssi = snd_soc_dai_get_drvdata(cpu_dai);
- struct imx_pcm_dma_params *dma_data;
u32 reg, sccr;
/* Tx/Rx config */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
reg = SSI_STCCR;
- dma_data = &ssi->dma_params_tx;
- } else {
+ else
reg = SSI_SRCCR;
- dma_data = &ssi->dma_params_rx;
- }
if (ssi->flags & IMX_SSI_SYN)
reg = SSI_STCCR;
- snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
-
sccr = readl(ssi->base + reg) & ~SSI_STCCR_WL_MASK;
/* DAI data (word) size */
@@ -342,7 +353,8 @@ static int imx_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
return 0;
}
-static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
+static const struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
+ .startup = imx_ssi_startup,
.hw_params = imx_ssi_hw_params,
.set_fmt = imx_ssi_set_dai_fmt,
.set_clkdiv = imx_ssi_set_dai_clkdiv,
@@ -351,95 +363,6 @@ static struct snd_soc_dai_ops imx_ssi_pcm_dai_ops = {
.trigger = imx_ssi_trigger,
};
-int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- int ret;
-
- ret = dma_mmap_coherent(NULL, vma, runtime->dma_area,
- runtime->dma_addr, runtime->dma_bytes);
-
- pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
- runtime->dma_area,
- runtime->dma_addr,
- runtime->dma_bytes);
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
-
-static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = IMX_SSI_DMABUF_SIZE;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_writecombine(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
- if (!buf->area)
- return -ENOMEM;
- buf->bytes = size;
-
- return 0;
-}
-
-static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
-
-int imx_pcm_new(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
- struct snd_pcm *pcm = rtd->pcm;
- int ret = 0;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &imx_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
- ret = imx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
-
- if (dai->driver->capture.channels_min) {
- ret = imx_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
-
-out:
- return ret;
-}
-EXPORT_SYMBOL_GPL(imx_pcm_new);
-
-void imx_pcm_free(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
-
- dma_free_writecombine(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-EXPORT_SYMBOL_GPL(imx_pcm_free);
-
static int imx_ssi_dai_probe(struct snd_soc_dai *dai)
{
struct imx_ssi *ssi = dev_get_drvdata(dai->dev);
@@ -657,7 +580,7 @@ static int imx_ssi_probe(struct platform_device *pdev)
ssi->dma_params_rx.dma_addr = res->start + SSI_SRX0;
ssi->dma_params_tx.dma_addr = res->start + SSI_STX0;
- ssi->dma_params_tx.burstsize = 4;
+ ssi->dma_params_tx.burstsize = 6;
ssi->dma_params_rx.burstsize = 4;
res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx0");
@@ -758,18 +681,7 @@ static struct platform_driver imx_ssi_driver = {
},
};
-static int __init imx_ssi_init(void)
-{
- return platform_driver_register(&imx_ssi_driver);
-}
-
-static void __exit imx_ssi_exit(void)
-{
- platform_driver_unregister(&imx_ssi_driver);
-}
-
-module_init(imx_ssi_init);
-module_exit(imx_ssi_exit);
+module_platform_driver(imx_ssi_driver);
/* Module information */
MODULE_AUTHOR("Sascha Hauer, <s.hauer@pengutronix.de>");
diff --git a/sound/soc/imx/imx-ssi.h b/sound/soc/imx/imx-ssi.h
index 0a84cec3599e..5744e86ca878 100644
--- a/sound/soc/imx/imx-ssi.h
+++ b/sound/soc/imx/imx-ssi.h
@@ -187,12 +187,7 @@
#include <linux/dmaengine.h>
#include <mach/dma.h>
-
-struct imx_pcm_dma_params {
- int dma;
- unsigned long dma_addr;
- int burstsize;
-};
+#include "imx-pcm.h"
struct imx_ssi {
struct platform_device *ac97_dev;
@@ -218,19 +213,4 @@ struct imx_ssi {
struct platform_device *soc_platform_pdev_fiq;
};
-struct snd_soc_platform *imx_ssi_fiq_init(struct platform_device *pdev,
- struct imx_ssi *ssi);
-void imx_ssi_fiq_exit(struct platform_device *pdev, struct imx_ssi *ssi);
-struct snd_soc_platform *imx_ssi_dma_mx2_init(struct platform_device *pdev,
- struct imx_ssi *ssi);
-
-int snd_imx_pcm_mmap(struct snd_pcm_substream *substream, struct vm_area_struct *vma);
-int imx_pcm_new(struct snd_soc_pcm_runtime *rtd);
-void imx_pcm_free(struct snd_pcm *pcm);
-
-/*
- * Do not change this as the FIQ handler depends on this size
- */
-#define IMX_SSI_DMABUF_SIZE (64 * 1024)
-
#endif /* _IMX_SSI_H */
diff --git a/sound/soc/imx/mx27vis-aic32x4.c b/sound/soc/imx/mx27vis-aic32x4.c
index 054110b91d42..f6d04ad4bb39 100644
--- a/sound/soc/imx/mx27vis-aic32x4.c
+++ b/sound/soc/imx/mx27vis-aic32x4.c
@@ -25,15 +25,36 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
#include <linux/i2c.h>
+#include <linux/gpio.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <sound/soc-dapm.h>
+#include <sound/tlv.h>
#include <asm/mach-types.h>
-#include <mach/audmux.h>
+#include <mach/iomux-mx27.h>
#include "../codecs/tlv320aic32x4.h"
#include "imx-ssi.h"
+#include "imx-audmux.h"
+
+#define MX27VIS_AMP_GAIN 0
+#define MX27VIS_AMP_MUTE 1
+
+#define MX27VIS_PIN_G0 (GPIO_PORTF + 9)
+#define MX27VIS_PIN_G1 (GPIO_PORTF + 8)
+#define MX27VIS_PIN_SDL (GPIO_PORTE + 5)
+#define MX27VIS_PIN_SDR (GPIO_PORTF + 7)
+
+static int mx27vis_amp_gain;
+static int mx27vis_amp_mute;
+
+static const int mx27vis_amp_pins[] = {
+ MX27VIS_PIN_G0 | GPIO_GPIO | GPIO_OUT,
+ MX27VIS_PIN_G1 | GPIO_GPIO | GPIO_OUT,
+ MX27VIS_PIN_SDL | GPIO_GPIO | GPIO_OUT,
+ MX27VIS_PIN_SDR | GPIO_GPIO | GPIO_OUT,
+};
static int mx27vis_aic32x4_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
@@ -74,6 +95,76 @@ static struct snd_soc_ops mx27vis_aic32x4_snd_ops = {
.hw_params = mx27vis_aic32x4_hw_params,
};
+static int mx27vis_amp_set(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ int value = ucontrol->value.integer.value[0];
+ unsigned int reg = mc->reg;
+ int max = mc->max;
+
+ if (value > max)
+ return -EINVAL;
+
+ switch (reg) {
+ case MX27VIS_AMP_GAIN:
+ gpio_set_value(MX27VIS_PIN_G0, value & 1);
+ gpio_set_value(MX27VIS_PIN_G1, value >> 1);
+ mx27vis_amp_gain = value;
+ break;
+ case MX27VIS_AMP_MUTE:
+ gpio_set_value(MX27VIS_PIN_SDL, value & 1);
+ gpio_set_value(MX27VIS_PIN_SDR, value >> 1);
+ mx27vis_amp_mute = value;
+ break;
+ }
+ return 0;
+}
+
+static int mx27vis_amp_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_mixer_control *mc =
+ (struct soc_mixer_control *)kcontrol->private_value;
+ unsigned int reg = mc->reg;
+
+ switch (reg) {
+ case MX27VIS_AMP_GAIN:
+ ucontrol->value.integer.value[0] = mx27vis_amp_gain;
+ break;
+ case MX27VIS_AMP_MUTE:
+ ucontrol->value.integer.value[0] = mx27vis_amp_mute;
+ break;
+ }
+ return 0;
+}
+
+/* From 6dB to 24dB in steps of 6dB */
+static const DECLARE_TLV_DB_SCALE(mx27vis_amp_tlv, 600, 600, 0);
+
+static const struct snd_kcontrol_new mx27vis_aic32x4_controls[] = {
+ SOC_DAPM_PIN_SWITCH("External Mic"),
+ SOC_SINGLE_EXT_TLV("LO Ext Boost", MX27VIS_AMP_GAIN, 0, 3, 0,
+ mx27vis_amp_get, mx27vis_amp_set, mx27vis_amp_tlv),
+ SOC_DOUBLE_EXT("LO Ext Mute Switch", MX27VIS_AMP_MUTE, 0, 1, 1, 0,
+ mx27vis_amp_get, mx27vis_amp_set),
+};
+
+static const struct snd_soc_dapm_widget aic32x4_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("External Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route aic32x4_dapm_routes[] = {
+ {"Mic Bias", NULL, "External Mic"},
+ {"IN1_R", NULL, "Mic Bias"},
+ {"IN2_R", NULL, "Mic Bias"},
+ {"IN3_R", NULL, "Mic Bias"},
+ {"IN1_L", NULL, "Mic Bias"},
+ {"IN2_L", NULL, "Mic Bias"},
+ {"IN3_L", NULL, "Mic Bias"},
+};
+
static struct snd_soc_dai_link mx27vis_aic32x4_dai = {
.name = "tlv320aic32x4",
.stream_name = "TLV320AIC32X4",
@@ -86,52 +177,69 @@ static struct snd_soc_dai_link mx27vis_aic32x4_dai = {
static struct snd_soc_card mx27vis_aic32x4 = {
.name = "visstrim_m10-audio",
+ .owner = THIS_MODULE,
.dai_link = &mx27vis_aic32x4_dai,
.num_links = 1,
+ .controls = mx27vis_aic32x4_controls,
+ .num_controls = ARRAY_SIZE(mx27vis_aic32x4_controls),
+ .dapm_widgets = aic32x4_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(aic32x4_dapm_widgets),
+ .dapm_routes = aic32x4_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(aic32x4_dapm_routes),
};
-static struct platform_device *mx27vis_aic32x4_snd_device;
-
-static int __init mx27vis_aic32x4_init(void)
+static int __devinit mx27vis_aic32x4_probe(struct platform_device *pdev)
{
int ret;
- mx27vis_aic32x4_snd_device = platform_device_alloc("soc-audio", -1);
- if (!mx27vis_aic32x4_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(mx27vis_aic32x4_snd_device, &mx27vis_aic32x4);
- ret = platform_device_add(mx27vis_aic32x4_snd_device);
-
+ mx27vis_aic32x4.dev = &pdev->dev;
+ ret = snd_soc_register_card(&mx27vis_aic32x4);
if (ret) {
- printk(KERN_ERR "ASoC: Platform device allocation failed\n");
- platform_device_put(mx27vis_aic32x4_snd_device);
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ return ret;
}
/* Connect SSI0 as clock slave to SSI1 external pins */
- mxc_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
- MXC_AUDMUX_V1_PCR_SYN |
- MXC_AUDMUX_V1_PCR_TFSDIR |
- MXC_AUDMUX_V1_PCR_TCLKDIR |
- MXC_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) |
- MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1)
+ imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+ IMX_AUDMUX_V1_PCR_SYN |
+ IMX_AUDMUX_V1_PCR_TFSDIR |
+ IMX_AUDMUX_V1_PCR_TCLKDIR |
+ IMX_AUDMUX_V1_PCR_TFCSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1) |
+ IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_PPCR1_SSI_PINS_1)
);
- mxc_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1,
- MXC_AUDMUX_V1_PCR_SYN |
- MXC_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
+ imx_audmux_v1_configure_port(MX27_AUDMUX_PPCR1_SSI_PINS_1,
+ IMX_AUDMUX_V1_PCR_SYN |
+ IMX_AUDMUX_V1_PCR_RXDSEL(MX27_AUDMUX_HPCR1_SSI0)
);
+ ret = mxc_gpio_setup_multiple_pins(mx27vis_amp_pins,
+ ARRAY_SIZE(mx27vis_amp_pins), "MX27VIS_AMP");
+ if (ret)
+ printk(KERN_ERR "ASoC: unable to setup gpios\n");
+
return ret;
}
-static void __exit mx27vis_aic32x4_exit(void)
+static int __devexit mx27vis_aic32x4_remove(struct platform_device *pdev)
{
- platform_device_unregister(mx27vis_aic32x4_snd_device);
+ snd_soc_unregister_card(&mx27vis_aic32x4);
+
+ return 0;
}
-module_init(mx27vis_aic32x4_init);
-module_exit(mx27vis_aic32x4_exit);
+static struct platform_driver mx27vis_aic32x4_audio_driver = {
+ .driver = {
+ .name = "mx27vis",
+ .owner = THIS_MODULE,
+ },
+ .probe = mx27vis_aic32x4_probe,
+ .remove = __devexit_p(mx27vis_aic32x4_remove),
+};
+
+module_platform_driver(mx27vis_aic32x4_audio_driver);
MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
MODULE_DESCRIPTION("ALSA SoC AIC32X4 mx27 visstrim");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mx27vis");
diff --git a/sound/soc/imx/phycore-ac97.c b/sound/soc/imx/phycore-ac97.c
index a7deb5cb2433..f8da6dd115ed 100644
--- a/sound/soc/imx/phycore-ac97.c
+++ b/sound/soc/imx/phycore-ac97.c
@@ -19,6 +19,8 @@
#include <sound/soc.h>
#include <asm/mach-types.h>
+#include "imx-audmux.h"
+
static struct snd_soc_card imx_phycore;
static struct snd_soc_ops imx_phycore_hifi_ops = {
@@ -38,6 +40,7 @@ static struct snd_soc_dai_link imx_phycore_dai_ac97[] = {
static struct snd_soc_card imx_phycore = {
.name = "PhyCORE-ac97-audio",
+ .owner = THIS_MODULE,
.dai_link = imx_phycore_dai_ac97,
.num_links = ARRAY_SIZE(imx_phycore_dai_ac97),
};
@@ -49,9 +52,32 @@ static int __init imx_phycore_init(void)
{
int ret;
- if (!machine_is_pcm043() && !machine_is_pca100())
+ if (machine_is_pca100()) {
+ imx_audmux_v1_configure_port(MX27_AUDMUX_HPCR1_SSI0,
+ IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */
+ IMX_AUDMUX_V1_PCR_TFCSEL(3) |
+ IMX_AUDMUX_V1_PCR_TCLKDIR | /* clock is output */
+ IMX_AUDMUX_V1_PCR_RXDSEL(3));
+ imx_audmux_v1_configure_port(3,
+ IMX_AUDMUX_V1_PCR_SYN | /* 4wire mode */
+ IMX_AUDMUX_V1_PCR_TFCSEL(0) |
+ IMX_AUDMUX_V1_PCR_TFSDIR |
+ IMX_AUDMUX_V1_PCR_RXDSEL(0));
+ } else if (machine_is_pcm043()) {
+ imx_audmux_v2_configure_port(3,
+ IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
+ IMX_AUDMUX_V2_PTCR_TFSEL(0) |
+ IMX_AUDMUX_V2_PTCR_TFSDIR,
+ IMX_AUDMUX_V2_PDCR_RXDSEL(0));
+ imx_audmux_v2_configure_port(0,
+ IMX_AUDMUX_V2_PTCR_SYN | /* 4wire mode */
+ IMX_AUDMUX_V2_PTCR_TCSEL(3) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR, /* clock is output */
+ IMX_AUDMUX_V2_PDCR_RXDSEL(3));
+ } else {
/* return happy. We might run on a totally different machine */
return 0;
+ }
imx_phycore_snd_ac97_device = platform_device_alloc("soc-audio", -1);
if (!imx_phycore_snd_ac97_device)
diff --git a/sound/soc/imx/wm1133-ev1.c b/sound/soc/imx/wm1133-ev1.c
index 75b4c72787e2..fe54a69073e5 100644
--- a/sound/soc/imx/wm1133-ev1.c
+++ b/sound/soc/imx/wm1133-ev1.c
@@ -14,16 +14,16 @@
#include <linux/platform_device.h>
#include <linux/clk.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include <mach/audmux.h>
-
#include "imx-ssi.h"
#include "../codecs/wm8350.h"
+#include "imx-audmux.h"
/* There is a silicon mic on the board optionally connected via a solder pad
* SP1. Define this to enable it.
@@ -254,6 +254,7 @@ static struct snd_soc_dai_link wm1133_ev1_dai = {
static struct snd_soc_card wm1133_ev1 = {
.name = "WM1133-EV1",
+ .owner = THIS_MODULE,
.dai_link = &wm1133_ev1_dai,
.num_links = 1,
};
@@ -266,17 +267,17 @@ static int __init wm1133_ev1_audio_init(void)
unsigned int ptcr, pdcr;
/* SSI0 mastered by port 5 */
- ptcr = MXC_AUDMUX_V2_PTCR_SYN |
- MXC_AUDMUX_V2_PTCR_TFSDIR |
- MXC_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) |
- MXC_AUDMUX_V2_PTCR_TCLKDIR |
- MXC_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
- pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
- mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr);
-
- ptcr = MXC_AUDMUX_V2_PTCR_SYN;
- pdcr = MXC_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0);
- mxc_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
+ ptcr = IMX_AUDMUX_V2_PTCR_SYN |
+ IMX_AUDMUX_V2_PTCR_TFSDIR |
+ IMX_AUDMUX_V2_PTCR_TFSEL(MX31_AUDMUX_PORT5_SSI_PINS_5) |
+ IMX_AUDMUX_V2_PTCR_TCLKDIR |
+ IMX_AUDMUX_V2_PTCR_TCSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
+ pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT5_SSI_PINS_5);
+ imx_audmux_v2_configure_port(MX31_AUDMUX_PORT1_SSI0, ptcr, pdcr);
+
+ ptcr = IMX_AUDMUX_V2_PTCR_SYN;
+ pdcr = IMX_AUDMUX_V2_PDCR_RXDSEL(MX31_AUDMUX_PORT1_SSI0);
+ imx_audmux_v2_configure_port(MX31_AUDMUX_PORT5_SSI_PINS_5, ptcr, pdcr);
wm1133_ev1_snd_device = platform_device_alloc("soc-audio", -1);
if (!wm1133_ev1_snd_device)
diff --git a/sound/soc/jz4740/jz4740-i2s.c b/sound/soc/jz4740/jz4740-i2s.c
index cd22a54b2f14..a5af7c42e62b 100644
--- a/sound/soc/jz4740/jz4740-i2s.c
+++ b/sound/soc/jz4740/jz4740-i2s.c
@@ -392,7 +392,7 @@ static int jz4740_i2s_dai_remove(struct snd_soc_dai *dai)
return 0;
}
-static struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
+static const struct snd_soc_dai_ops jz4740_i2s_dai_ops = {
.startup = jz4740_i2s_startup,
.shutdown = jz4740_i2s_shutdown,
.trigger = jz4740_i2s_trigger,
@@ -519,17 +519,7 @@ static struct platform_driver jz4740_i2s_driver = {
},
};
-static int __init jz4740_i2s_init(void)
-{
- return platform_driver_register(&jz4740_i2s_driver);
-}
-module_init(jz4740_i2s_init);
-
-static void __exit jz4740_i2s_exit(void)
-{
- platform_driver_unregister(&jz4740_i2s_driver);
-}
-module_exit(jz4740_i2s_exit);
+module_platform_driver(jz4740_i2s_driver);
MODULE_AUTHOR("Lars-Peter Clausen, <lars@metafoo.de>");
MODULE_DESCRIPTION("Ingenic JZ4740 SoC I2S driver");
diff --git a/sound/soc/jz4740/jz4740-pcm.c b/sound/soc/jz4740/jz4740-pcm.c
index a7c9578be983..9b8cf256847d 100644
--- a/sound/soc/jz4740/jz4740-pcm.c
+++ b/sound/soc/jz4740/jz4740-pcm.c
@@ -299,10 +299,9 @@ static void jz4740_pcm_free(struct snd_pcm *pcm)
static u64 jz4740_pcm_dmamask = DMA_BIT_MASK(32);
-int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
+static int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
@@ -312,14 +311,14 @@ int jz4740_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = jz4740_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto err;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = jz4740_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -356,17 +355,7 @@ static struct platform_driver jz4740_pcm_driver = {
},
};
-static int __init jz4740_soc_platform_init(void)
-{
- return platform_driver_register(&jz4740_pcm_driver);
-}
-module_init(jz4740_soc_platform_init);
-
-static void __exit jz4740_soc_platform_exit(void)
-{
- return platform_driver_unregister(&jz4740_pcm_driver);
-}
-module_exit(jz4740_soc_platform_exit);
+module_platform_driver(jz4740_pcm_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Ingenic SoC JZ4740 PCM driver");
diff --git a/sound/soc/jz4740/qi_lb60.c b/sound/soc/jz4740/qi_lb60.c
index c5fc339f68f1..e8aaff18d7cc 100644
--- a/sound/soc/jz4740/qi_lb60.c
+++ b/sound/soc/jz4740/qi_lb60.c
@@ -81,6 +81,7 @@ static struct snd_soc_dai_link qi_lb60_dai = {
static struct snd_soc_card qi_lb60 = {
.name = "QI LB60",
+ .owner = THIS_MODULE,
.dai_link = &qi_lb60_dai,
.num_links = 1,
@@ -90,56 +91,52 @@ static struct snd_soc_card qi_lb60 = {
.num_dapm_routes = ARRAY_SIZE(qi_lb60_routes),
};
-static struct platform_device *qi_lb60_snd_device;
-
static const struct gpio qi_lb60_gpios[] = {
{ QI_LB60_SND_GPIO, GPIOF_OUT_INIT_LOW, "SND" },
{ QI_LB60_AMP_GPIO, GPIOF_OUT_INIT_LOW, "AMP" },
};
-static int __init qi_lb60_init(void)
+static int __devinit qi_lb60_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &qi_lb60;
int ret;
- qi_lb60_snd_device = platform_device_alloc("soc-audio", -1);
-
- if (!qi_lb60_snd_device)
- return -ENOMEM;
-
ret = gpio_request_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
- if (ret) {
- pr_err("qi_lb60 snd: Failed to request gpios: %d\n", ret);
- goto err_device_put;
- }
+ if (ret)
+ return ret;
- platform_set_drvdata(qi_lb60_snd_device, &qi_lb60);
+ card->dev = &pdev->dev;
- ret = platform_device_add(qi_lb60_snd_device);
+ ret = snd_soc_register_card(card);
if (ret) {
- pr_err("qi_lb60 snd: Failed to add snd soc device: %d\n", ret);
- goto err_unset_pdata;
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
}
-
- return 0;
-
-err_unset_pdata:
- platform_set_drvdata(qi_lb60_snd_device, NULL);
-/*err_gpio_free_array:*/
- gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
-err_device_put:
- platform_device_put(qi_lb60_snd_device);
-
return ret;
}
-module_init(qi_lb60_init);
-static void __exit qi_lb60_exit(void)
+static int __devexit qi_lb60_remove(struct platform_device *pdev)
{
- platform_device_unregister(qi_lb60_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
gpio_free_array(qi_lb60_gpios, ARRAY_SIZE(qi_lb60_gpios));
+ return 0;
}
-module_exit(qi_lb60_exit);
+
+static struct platform_driver qi_lb60_driver = {
+ .driver = {
+ .name = "qi-lb60-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = qi_lb60_probe,
+ .remove = __devexit_p(qi_lb60_remove),
+};
+
+module_platform_driver(qi_lb60_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("ALSA SoC QI LB60 Audio support");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:qi-lb60-audio");
diff --git a/sound/soc/kirkwood/Kconfig b/sound/soc/kirkwood/Kconfig
index 8f49e165f4d1..c62d715235e2 100644
--- a/sound/soc/kirkwood/Kconfig
+++ b/sound/soc/kirkwood/Kconfig
@@ -12,6 +12,7 @@ config SND_KIRKWOOD_SOC_I2S
config SND_KIRKWOOD_SOC_OPENRD
tristate "SoC Audio support for Kirkwood Openrd Client"
depends on SND_KIRKWOOD_SOC && (MACH_OPENRD_CLIENT || MACH_OPENRD_ULTIMATE)
+ depends on I2C
select SND_KIRKWOOD_SOC_I2S
select SND_SOC_CS42L51
help
@@ -20,7 +21,7 @@ config SND_KIRKWOOD_SOC_OPENRD
config SND_KIRKWOOD_SOC_T5325
tristate "SoC Audio support for HP t5325"
- depends on SND_KIRKWOOD_SOC && MACH_T5325
+ depends on SND_KIRKWOOD_SOC && MACH_T5325 && I2C
select SND_KIRKWOOD_SOC_I2S
select SND_SOC_ALC5623
help
diff --git a/sound/soc/kirkwood/kirkwood-dma.c b/sound/soc/kirkwood/kirkwood-dma.c
index cd33de1c5b7a..b9f16598324c 100644
--- a/sound/soc/kirkwood/kirkwood-dma.c
+++ b/sound/soc/kirkwood/kirkwood-dma.c
@@ -55,7 +55,7 @@ static struct snd_pcm_hardware kirkwood_dma_snd_hw = {
.fifo_size = 0,
};
-static u64 kirkwood_dma_dmamask = 0xFFFFFFFFUL;
+static u64 kirkwood_dma_dmamask = DMA_BIT_MASK(32);
static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
{
@@ -94,9 +94,10 @@ static irqreturn_t kirkwood_dma_irq(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static void kirkwood_dma_conf_mbus_windows(void __iomem *base, int win,
- unsigned long dma,
- struct mbus_dram_target_info *dram)
+static void
+kirkwood_dma_conf_mbus_windows(void __iomem *base, int win,
+ unsigned long dma,
+ const struct mbus_dram_target_info *dram)
{
int i;
@@ -106,7 +107,7 @@ static void kirkwood_dma_conf_mbus_windows(void __iomem *base, int win,
/* try to find matching cs for current dma address */
for (i = 0; i < dram->num_cs; i++) {
- struct mbus_dram_window *cs = dram->cs + i;
+ const struct mbus_dram_window *cs = dram->cs + i;
if ((cs->base & 0xffff0000) < (dma & 0xffff0000)) {
writel(cs->base & 0xffff0000,
base + KIRKWOOD_AUDIO_WIN_BASE_REG(win));
@@ -127,6 +128,7 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
struct snd_soc_dai *cpu_dai = soc_runtime->cpu_dai;
struct kirkwood_dma_data *priv;
struct kirkwood_dma_priv *prdata = snd_soc_platform_get_drvdata(platform);
+ const struct mbus_dram_target_info *dram;
unsigned long addr;
priv = snd_soc_dai_get_dma_data(cpu_dai, substream);
@@ -175,15 +177,16 @@ static int kirkwood_dma_open(struct snd_pcm_substream *substream)
writel((unsigned long)-1, priv->io + KIRKWOOD_ERR_MASK);
}
+ dram = mv_mbus_dram_info();
addr = virt_to_phys(substream->dma_buffer.area);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
prdata->play_stream = substream;
kirkwood_dma_conf_mbus_windows(priv->io,
- KIRKWOOD_PLAYBACK_WIN, addr, priv->dram);
+ KIRKWOOD_PLAYBACK_WIN, addr, dram);
} else {
prdata->rec_stream = substream;
kirkwood_dma_conf_mbus_windows(priv->io,
- KIRKWOOD_RECORD_WIN, addr, priv->dram);
+ KIRKWOOD_RECORD_WIN, addr, dram);
}
return 0;
@@ -315,23 +318,22 @@ static int kirkwood_dma_preallocate_dma_buffer(struct snd_pcm *pcm,
static int kirkwood_dma_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret;
if (!card->dev->dma_mask)
card->dev->dma_mask = &kirkwood_dma_dmamask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = kirkwood_dma_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
return ret;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = kirkwood_dma_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -388,17 +390,7 @@ static struct platform_driver kirkwood_pcm_driver = {
.remove = __devexit_p(kirkwood_soc_platform_remove),
};
-static int __init kirkwood_pcm_init(void)
-{
- return platform_driver_register(&kirkwood_pcm_driver);
-}
-module_init(kirkwood_pcm_init);
-
-static void __exit kirkwood_pcm_exit(void)
-{
- platform_driver_unregister(&kirkwood_pcm_driver);
-}
-module_exit(kirkwood_pcm_exit);
+module_platform_driver(kirkwood_pcm_driver);
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("Marvell Kirkwood Audio DMA module");
diff --git a/sound/soc/kirkwood/kirkwood-i2s.c b/sound/soc/kirkwood/kirkwood-i2s.c
index 8f16cd37c2af..3cb9aa4299d3 100644
--- a/sound/soc/kirkwood/kirkwood-i2s.c
+++ b/sound/soc/kirkwood/kirkwood-i2s.c
@@ -373,7 +373,7 @@ static int kirkwood_i2s_remove(struct snd_soc_dai *dai)
return 0;
}
-static struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
+static const struct snd_soc_dai_ops kirkwood_i2s_dai_ops = {
.startup = kirkwood_i2s_startup,
.trigger = kirkwood_i2s_trigger,
.hw_params = kirkwood_i2s_hw_params,
@@ -424,7 +424,7 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
if (!priv->mem) {
dev_err(&pdev->dev, "request_mem_region failed\n");
err = -EBUSY;
- goto error_alloc;
+ goto err_alloc;
}
priv->io = ioremap(priv->mem->start, SZ_16K);
@@ -441,13 +441,12 @@ static __devinit int kirkwood_i2s_dev_probe(struct platform_device *pdev)
goto err_ioremap;
}
- if (!data || !data->dram) {
+ if (!data) {
dev_err(&pdev->dev, "no platform data ?!\n");
err = -EINVAL;
goto err_ioremap;
}
- priv->dram = data->dram;
priv->burst = data->burst;
return snd_soc_register_dai(&pdev->dev, &kirkwood_i2s_dai);
@@ -476,24 +475,14 @@ static __devexit int kirkwood_i2s_dev_remove(struct platform_device *pdev)
static struct platform_driver kirkwood_i2s_driver = {
.probe = kirkwood_i2s_dev_probe,
- .remove = kirkwood_i2s_dev_remove,
+ .remove = __devexit_p(kirkwood_i2s_dev_remove),
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
},
};
-static int __init kirkwood_i2s_init(void)
-{
- return platform_driver_register(&kirkwood_i2s_driver);
-}
-module_init(kirkwood_i2s_init);
-
-static void __exit kirkwood_i2s_exit(void)
-{
- platform_driver_unregister(&kirkwood_i2s_driver);
-}
-module_exit(kirkwood_i2s_exit);
+module_platform_driver(kirkwood_i2s_driver);
/* Module information */
MODULE_AUTHOR("Arnaud Patard, <arnaud.patard@rtp-net.org>");
diff --git a/sound/soc/kirkwood/kirkwood-openrd.c b/sound/soc/kirkwood/kirkwood-openrd.c
index d863afb3ee52..80bd59c33be4 100644
--- a/sound/soc/kirkwood/kirkwood-openrd.c
+++ b/sound/soc/kirkwood/kirkwood-openrd.c
@@ -26,18 +26,7 @@ static int openrd_client_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret;
- unsigned int freq, fmt;
-
- fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
- ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, fmt);
- if (ret < 0)
- return ret;
+ unsigned int freq;
switch (params_rate(params)) {
default:
@@ -69,6 +58,7 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
.platform_name = "kirkwood-pcm-audio",
.codec_dai_name = "cs42l51-hifi",
.codec_name = "cs42l51-codec.0-004a",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
.ops = &openrd_client_ops,
},
};
@@ -76,45 +66,46 @@ static struct snd_soc_dai_link openrd_client_dai[] = {
static struct snd_soc_card openrd_client = {
.name = "OpenRD Client",
+ .owner = THIS_MODULE,
.dai_link = openrd_client_dai,
.num_links = ARRAY_SIZE(openrd_client_dai),
};
-static struct platform_device *openrd_client_snd_device;
-
-static int __init openrd_client_init(void)
+static int __devinit openrd_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &openrd_client;
int ret;
- if (!machine_is_openrd_client() && !machine_is_openrd_ultimate())
- return 0;
-
- openrd_client_snd_device = platform_device_alloc("soc-audio", -1);
- if (!openrd_client_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(openrd_client_snd_device,
- &openrd_client);
-
- ret = platform_device_add(openrd_client_snd_device);
- if (ret) {
- printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
- platform_device_put(openrd_client_snd_device);
- }
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
return ret;
}
-static void __exit openrd_client_exit(void)
+static int __devexit openrd_remove(struct platform_device *pdev)
{
- platform_device_unregister(openrd_client_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(openrd_client_init);
-module_exit(openrd_client_exit);
+static struct platform_driver openrd_driver = {
+ .driver = {
+ .name = "openrd-client-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = openrd_probe,
+ .remove = __devexit_p(openrd_remove),
+};
+
+module_platform_driver(openrd_driver);
/* Module information */
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("ALSA SoC OpenRD Client");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:soc-audio");
+MODULE_ALIAS("platform:openrd-client-audio");
diff --git a/sound/soc/kirkwood/kirkwood-t5325.c b/sound/soc/kirkwood/kirkwood-t5325.c
index c8d21956ab52..f8983635f7ef 100644
--- a/sound/soc/kirkwood/kirkwood-t5325.c
+++ b/sound/soc/kirkwood/kirkwood-t5325.c
@@ -25,18 +25,7 @@ static int t5325_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret;
- unsigned int freq, fmt;
-
- fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS;
- ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, fmt);
- if (ret < 0)
- return ret;
+ unsigned int freq;
freq = params_rate(params) * 256;
@@ -70,17 +59,10 @@ static int t5325_dai_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- snd_soc_dapm_new_controls(dapm, t5325_dapm_widgets,
- ARRAY_SIZE(t5325_dapm_widgets));
-
- snd_soc_dapm_add_routes(dapm, t5325_route, ARRAY_SIZE(t5325_route));
-
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Speaker");
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -92,50 +74,58 @@ static struct snd_soc_dai_link t5325_dai[] = {
.platform_name = "kirkwood-pcm-audio",
.codec_dai_name = "alc5621-hifi",
.codec_name = "alc562x-codec.0-001a",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS,
.ops = &t5325_ops,
.init = t5325_dai_init,
},
};
-
static struct snd_soc_card t5325 = {
.name = "t5325",
+ .owner = THIS_MODULE,
.dai_link = t5325_dai,
.num_links = ARRAY_SIZE(t5325_dai),
-};
-static struct platform_device *t5325_snd_device;
+ .dapm_widgets = t5325_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(t5325_dapm_widgets),
+ .dapm_routes = t5325_route,
+ .num_dapm_routes = ARRAY_SIZE(t5325_route),
+};
-static int __init t5325_init(void)
+static int __devinit t5325_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &t5325;
int ret;
- if (!machine_is_t5325())
- return 0;
-
- t5325_snd_device = platform_device_alloc("soc-audio", -1);
- if (!t5325_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(t5325_snd_device,
- &t5325);
-
- ret = platform_device_add(t5325_snd_device);
- if (ret) {
- printk(KERN_ERR "%s: platform_device_add failed\n", __func__);
- platform_device_put(t5325_snd_device);
- }
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
return ret;
}
-module_init(t5325_init);
-static void __exit t5325_exit(void)
+static int __devexit t5325_remove(struct platform_device *pdev)
{
- platform_device_unregister(t5325_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_exit(t5325_exit);
+
+static struct platform_driver t5325_driver = {
+ .driver = {
+ .name = "t5325-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = t5325_probe,
+ .remove = __devexit_p(t5325_remove),
+};
+
+module_platform_driver(t5325_driver);
MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>");
MODULE_DESCRIPTION("ALSA SoC t5325 audio client");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:t5325-audio");
diff --git a/sound/soc/kirkwood/kirkwood.h b/sound/soc/kirkwood/kirkwood.h
index bb6e6a5648c9..9047436b3937 100644
--- a/sound/soc/kirkwood/kirkwood.h
+++ b/sound/soc/kirkwood/kirkwood.h
@@ -123,7 +123,6 @@ struct kirkwood_dma_data {
void __iomem *io;
int irq;
int burst;
- struct mbus_dram_target_info *dram;
};
#endif
diff --git a/sound/soc/mid-x86/Kconfig b/sound/soc/mid-x86/Kconfig
index 29350428f1c2..61c10bf503d2 100644
--- a/sound/soc/mid-x86/Kconfig
+++ b/sound/soc/mid-x86/Kconfig
@@ -1,7 +1,6 @@
config SND_MFLD_MACHINE
tristate "SOC Machine Audio driver for Intel Medfield MID platform"
depends on INTEL_SCU_IPC
- depends on SND_INTEL_SST
select SND_SOC_SN95031
select SND_SST_PLATFORM
help
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c
index 429aa1be2cff..2937e54da49e 100644
--- a/sound/soc/mid-x86/mfld_machine.c
+++ b/sound/soc/mid-x86/mfld_machine.c
@@ -28,6 +28,7 @@
#include <linux/device.h>
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -54,9 +55,7 @@ static unsigned int hs_switch;
static unsigned int lo_dac;
struct mfld_mc_private {
- struct platform_device *socdev;
void __iomem *int_base;
- struct snd_soc_codec *codec;
u8 interrupt_status;
};
@@ -235,9 +234,8 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
/* always connected */
snd_soc_dapm_enable_pin(dapm, "Headphones");
snd_soc_dapm_enable_pin(dapm, "Mic");
- snd_soc_dapm_sync(dapm);
- ret_val = snd_soc_add_controls(codec, mfld_snd_controls,
+ ret_val = snd_soc_add_codec_controls(codec, mfld_snd_controls,
ARRAY_SIZE(mfld_snd_controls));
if (ret_val) {
pr_err("soc_add_controls failed %d", ret_val);
@@ -253,7 +251,6 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
/* we dont use linein in this so set to NC */
snd_soc_dapm_disable_pin(dapm, "LINEINL");
snd_soc_dapm_disable_pin(dapm, "LINEINR");
- snd_soc_dapm_sync(dapm);
/* Headset and button jack detection */
ret_val = snd_soc_jack_new(codec, "Intel(R) MID Audio Jack",
@@ -284,7 +281,7 @@ static int mfld_init(struct snd_soc_pcm_runtime *runtime)
return ret_val;
}
-struct snd_soc_dai_link mfld_msic_dailink[] = {
+static struct snd_soc_dai_link mfld_msic_dailink[] = {
{
.name = "Medfield Headset",
.stream_name = "Headset",
@@ -326,6 +323,7 @@ struct snd_soc_dai_link mfld_msic_dailink[] = {
/* SoC card */
static struct snd_soc_card snd_soc_card_mfld = {
.name = "medfield_audio",
+ .owner = THIS_MODULE,
.dai_link = mfld_msic_dailink,
.num_links = ARRAY_SIZE(mfld_msic_dailink),
};
@@ -431,19 +429,7 @@ static struct platform_driver snd_mfld_mc_driver = {
.remove = __devexit_p(snd_mfld_mc_remove),
};
-static int __init snd_mfld_driver_init(void)
-{
- pr_debug("snd_mfld_driver_init called\n");
- return platform_driver_register(&snd_mfld_mc_driver);
-}
-module_init(snd_mfld_driver_init);
-
-static void __exit snd_mfld_driver_exit(void)
-{
- pr_debug("snd_mfld_driver_exit called\n");
- platform_driver_unregister(&snd_mfld_mc_driver);
-}
-module_exit(snd_mfld_driver_exit);
+module_platform_driver(snd_mfld_mc_driver);
MODULE_DESCRIPTION("ASoC Intel(R) MID Machine driver");
MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
index 3e7826058efe..d34563b12c3b 100644
--- a/sound/soc/mid-x86/sst_platform.c
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -27,14 +27,56 @@
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include "../../../drivers/staging/intel_sst/intel_sst_ioctl.h"
-#include "../../../drivers/staging/intel_sst/intel_sst.h"
#include "sst_platform.h"
+static struct sst_device *sst;
+static DEFINE_MUTEX(sst_lock);
+
+int sst_register_dsp(struct sst_device *dev)
+{
+ BUG_ON(!dev);
+ if (!try_module_get(dev->dev->driver->owner))
+ return -ENODEV;
+ mutex_lock(&sst_lock);
+ if (sst) {
+ pr_err("we already have a device %s\n", sst->name);
+ module_put(dev->dev->driver->owner);
+ mutex_unlock(&sst_lock);
+ return -EEXIST;
+ }
+ pr_debug("registering device %s\n", dev->name);
+ sst = dev;
+ mutex_unlock(&sst_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sst_register_dsp);
+
+int sst_unregister_dsp(struct sst_device *dev)
+{
+ BUG_ON(!dev);
+ if (dev != sst)
+ return -EINVAL;
+
+ mutex_lock(&sst_lock);
+
+ if (!sst) {
+ mutex_unlock(&sst_lock);
+ return -EIO;
+ }
+
+ module_put(sst->dev->driver->owner);
+ pr_debug("unreg %s\n", sst->name);
+ sst = NULL;
+ mutex_unlock(&sst_lock);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(sst_unregister_dsp);
+
static struct snd_pcm_hardware sst_platform_pcm_hw = {
.info = (SNDRV_PCM_INFO_INTERLEAVED |
SNDRV_PCM_INFO_DOUBLE |
@@ -63,7 +105,7 @@ static struct snd_pcm_hardware sst_platform_pcm_hw = {
};
/* MFLD - MSIC */
-struct snd_soc_dai_driver sst_platform_dai[] = {
+static struct snd_soc_dai_driver sst_platform_dai[] = {
{
.name = "Headset-cpu-dai",
.id = 0,
@@ -134,37 +176,34 @@ static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
}
static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
- struct snd_sst_stream_params *param)
+ struct sst_pcm_params *param)
{
- param->uc.pcm_params.codec = SST_CODEC_TYPE_PCM;
- param->uc.pcm_params.num_chan = (u8) substream->runtime->channels;
- param->uc.pcm_params.pcm_wd_sz = substream->runtime->sample_bits;
- param->uc.pcm_params.reserved = 0;
- param->uc.pcm_params.sfreq = substream->runtime->rate;
- param->uc.pcm_params.ring_buffer_size =
- snd_pcm_lib_buffer_bytes(substream);
- param->uc.pcm_params.period_count = substream->runtime->period_size;
- param->uc.pcm_params.ring_buffer_addr =
- virt_to_phys(substream->dma_buffer.area);
- pr_debug("period_cnt = %d\n", param->uc.pcm_params.period_count);
- pr_debug("sfreq= %d, wd_sz = %d\n",
- param->uc.pcm_params.sfreq, param->uc.pcm_params.pcm_wd_sz);
+ param->codec = SST_CODEC_TYPE_PCM;
+ param->num_chan = (u8) substream->runtime->channels;
+ param->pcm_wd_sz = substream->runtime->sample_bits;
+ param->reserved = 0;
+ param->sfreq = substream->runtime->rate;
+ param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream);
+ param->period_count = substream->runtime->period_size;
+ param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area);
+ pr_debug("period_cnt = %d\n", param->period_count);
+ pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz);
}
static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
{
struct sst_runtime_stream *stream =
substream->runtime->private_data;
- struct snd_sst_stream_params param = {{{0,},},};
- struct snd_sst_params str_params = {0};
+ struct sst_pcm_params param = {0};
+ struct sst_stream_params str_params = {0};
int ret_val;
/* set codec params and inform SST driver the same */
sst_fill_pcm_params(substream, &param);
substream->runtime->dma_area = substream->dma_buffer.area;
str_params.sparams = param;
- str_params.codec = param.uc.pcm_params.codec;
+ str_params.codec = param.codec;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
str_params.ops = STREAM_OPS_PLAYBACK;
str_params.device_type = substream->pcm->device + 1;
@@ -176,7 +215,7 @@ static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
pr_debug("Capture stream,Device %d\n",
substream->pcm->device);
}
- ret_val = stream->sstdrv_ops->pcm_control->open(&str_params);
+ ret_val = stream->ops->open(&str_params);
pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
if (ret_val < 0)
return ret_val;
@@ -215,7 +254,7 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
stream->stream_info.mad_substream = substream;
stream->stream_info.buffer_ptr = 0;
stream->stream_info.sfreq = substream->runtime->rate;
- ret_val = stream->sstdrv_ops->pcm_control->device_control(
+ ret_val = stream->ops->device_control(
SST_SND_STREAM_INIT, &stream->stream_info);
if (ret_val)
pr_err("control_set ret error %d\n", ret_val);
@@ -226,41 +265,46 @@ static int sst_platform_init_stream(struct snd_pcm_substream *substream)
static int sst_platform_open(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime;
+ struct snd_pcm_runtime *runtime = substream->runtime;
struct sst_runtime_stream *stream;
- int ret_val = 0;
+ int ret_val;
pr_debug("sst_platform_open called\n");
- runtime = substream->runtime;
- runtime->hw = sst_platform_pcm_hw;
+
+ snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw);
+ ret_val = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret_val < 0)
+ return ret_val;
+
stream = kzalloc(sizeof(*stream), GFP_KERNEL);
if (!stream)
return -ENOMEM;
spin_lock_init(&stream->status_lock);
- stream->stream_info.str_id = 0;
- sst_set_stream_status(stream, SST_PLATFORM_INIT);
- stream->stream_info.mad_substream = substream;
- /* allocate memory for SST API set */
- stream->sstdrv_ops = kzalloc(sizeof(*stream->sstdrv_ops),
- GFP_KERNEL);
- if (!stream->sstdrv_ops) {
- pr_err("sst: mem allocation for ops fail\n");
+
+ /* get the sst ops */
+ mutex_lock(&sst_lock);
+ if (!sst) {
+ pr_err("no device available to run\n");
+ mutex_unlock(&sst_lock);
kfree(stream);
- return -ENOMEM;
+ return -ENODEV;
}
- stream->sstdrv_ops->vendor_id = MSIC_VENDOR_ID;
- stream->sstdrv_ops->module_name = SST_CARD_NAMES;
- /* registering with SST driver to get access to SST APIs to use */
- ret_val = register_sst_card(stream->sstdrv_ops);
- if (ret_val) {
- pr_err("sst: sst card registration failed\n");
- kfree(stream->sstdrv_ops);
+ if (!try_module_get(sst->dev->driver->owner)) {
+ mutex_unlock(&sst_lock);
kfree(stream);
- return ret_val;
+ return -ENODEV;
}
+ stream->ops = sst->ops;
+ mutex_unlock(&sst_lock);
+
+ stream->stream_info.str_id = 0;
+ sst_set_stream_status(stream, SST_PLATFORM_INIT);
+ stream->stream_info.mad_substream = substream;
+ /* allocate memory for SST API set */
runtime->private_data = stream;
- return snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
+
+ return 0;
}
static int sst_platform_close(struct snd_pcm_substream *substream)
@@ -272,9 +316,8 @@ static int sst_platform_close(struct snd_pcm_substream *substream)
stream = substream->runtime->private_data;
str_id = stream->stream_info.str_id;
if (str_id)
- ret_val = stream->sstdrv_ops->pcm_control->close(str_id);
- unregister_sst_card(stream->sstdrv_ops);
- kfree(stream->sstdrv_ops);
+ ret_val = stream->ops->close(str_id);
+ module_put(sst->dev->driver->owner);
kfree(stream);
return ret_val;
}
@@ -288,8 +331,8 @@ static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
stream = substream->runtime->private_data;
str_id = stream->stream_info.str_id;
if (stream->stream_info.str_id) {
- ret_val = stream->sstdrv_ops->pcm_control->device_control(
- SST_SND_DROP, &str_id);
+ ret_val = stream->ops->device_control(
+ SST_SND_DROP, &str_id);
return ret_val;
}
@@ -341,8 +384,7 @@ static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
default:
return -EINVAL;
}
- ret_val = stream->sstdrv_ops->pcm_control->device_control(str_cmd,
- &str_id);
+ ret_val = stream->ops->device_control(str_cmd, &str_id);
if (!ret_val)
sst_set_stream_status(stream, status);
@@ -362,7 +404,7 @@ static snd_pcm_uframes_t sst_platform_pcm_pointer
if (status == SST_PLATFORM_INIT)
return 0;
str_info = &stream->stream_info;
- ret_val = stream->sstdrv_ops->pcm_control->device_control(
+ ret_val = stream->ops->device_control(
SST_SND_BUFFER_POINTER, str_info);
if (ret_val) {
pr_err("sst: error code = %d\n", ret_val);
@@ -402,15 +444,14 @@ static void sst_pcm_free(struct snd_pcm *pcm)
snd_pcm_lib_preallocate_free_for_all(pcm);
}
-int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
+static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int retval = 0;
pr_debug("sst_pcm_new called\n");
- if (dai->driver->playback.channels_min ||
- dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
+ pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
retval = snd_pcm_lib_preallocate_pages_for_all(pcm,
SNDRV_DMA_TYPE_CONTINUOUS,
snd_dma_continuous_data(GFP_KERNEL),
@@ -422,7 +463,7 @@ int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
}
return retval;
}
-struct snd_soc_platform_driver sst_soc_platform_drv = {
+static struct snd_soc_platform_driver sst_soc_platform_drv = {
.ops = &sst_platform_ops,
.pcm_new = sst_pcm_new,
.pcm_free = sst_pcm_free,
@@ -433,6 +474,7 @@ static int sst_platform_probe(struct platform_device *pdev)
int ret;
pr_debug("sst_platform_probe called\n");
+ sst = NULL;
ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
if (ret) {
pr_err("registering soc platform failed\n");
@@ -466,19 +508,7 @@ static struct platform_driver sst_platform_driver = {
.remove = sst_platform_remove,
};
-static int __init sst_soc_platform_init(void)
-{
- pr_debug("sst_soc_platform_init called\n");
- return platform_driver_register(&sst_platform_driver);
-}
-module_init(sst_soc_platform_init);
-
-static void __exit sst_soc_platform_exit(void)
-{
- platform_driver_unregister(&sst_platform_driver);
- pr_debug("sst_soc_platform_exit success\n");
-}
-module_exit(sst_soc_platform_exit);
+module_platform_driver(sst_platform_driver);
MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h
index df370286694f..f04f4f72daa0 100644
--- a/sound/soc/mid-x86/sst_platform.h
+++ b/sound/soc/mid-x86/sst_platform.h
@@ -42,14 +42,14 @@
#define SST_MIN_PERIODS 2
#define SST_MAX_PERIODS (1024*2)
#define SST_FIFO_SIZE 0
-#define SST_CARD_NAMES "intel_mid_card"
-#define MSIC_VENDOR_ID 3
+#define SST_CODEC_TYPE_PCM 1
-struct sst_runtime_stream {
- int stream_status;
- struct pcm_stream_info stream_info;
- struct intel_sst_card_ops *sstdrv_ops;
- spinlock_t status_lock;
+struct pcm_stream_info {
+ int str_id;
+ void *mad_substream;
+ void (*period_elapsed) (void *mad_substream);
+ unsigned long long buffer_ptr;
+ int sfreq;
};
enum sst_drv_status {
@@ -60,4 +60,72 @@ enum sst_drv_status {
SST_PLATFORM_DROPPED,
};
+enum sst_controls {
+ SST_SND_ALLOC = 0x00,
+ SST_SND_PAUSE = 0x01,
+ SST_SND_RESUME = 0x02,
+ SST_SND_DROP = 0x03,
+ SST_SND_FREE = 0x04,
+ SST_SND_BUFFER_POINTER = 0x05,
+ SST_SND_STREAM_INIT = 0x06,
+ SST_SND_START = 0x07,
+ SST_MAX_CONTROLS = 0x07,
+};
+
+enum sst_stream_ops {
+ STREAM_OPS_PLAYBACK = 0,
+ STREAM_OPS_CAPTURE,
+};
+
+enum sst_audio_device_type {
+ SND_SST_DEVICE_HEADSET = 1,
+ SND_SST_DEVICE_IHF,
+ SND_SST_DEVICE_VIBRA,
+ SND_SST_DEVICE_HAPTIC,
+ SND_SST_DEVICE_CAPTURE,
+};
+
+/* PCM Parameters */
+struct sst_pcm_params {
+ u16 codec; /* codec type */
+ u8 num_chan; /* 1=Mono, 2=Stereo */
+ u8 pcm_wd_sz; /* 16/24 - bit*/
+ u32 reserved; /* Bitrate in bits per second */
+ u32 sfreq; /* Sampling rate in Hz */
+ u32 ring_buffer_size;
+ u32 period_count; /* period elapsed in samples*/
+ u32 ring_buffer_addr;
+};
+
+struct sst_stream_params {
+ u32 result;
+ u32 stream_id;
+ u8 codec;
+ u8 ops;
+ u8 stream_type;
+ u8 device_type;
+ struct sst_pcm_params sparams;
+};
+
+struct sst_ops {
+ int (*open) (struct sst_stream_params *str_param);
+ int (*device_control) (int cmd, void *arg);
+ int (*close) (unsigned int str_id);
+};
+
+struct sst_runtime_stream {
+ int stream_status;
+ struct pcm_stream_info stream_info;
+ struct sst_ops *ops;
+ spinlock_t status_lock;
+};
+
+struct sst_device {
+ char *name;
+ struct device *dev;
+ struct sst_ops *ops;
+};
+
+int sst_register_dsp(struct sst_device *sst);
+int sst_unregister_dsp(struct sst_device *sst);
#endif
diff --git a/sound/soc/mxs/Kconfig b/sound/soc/mxs/Kconfig
new file mode 100644
index 000000000000..99a997f19bb9
--- /dev/null
+++ b/sound/soc/mxs/Kconfig
@@ -0,0 +1,20 @@
+menuconfig SND_MXS_SOC
+ tristate "SoC Audio for Freescale MXS CPUs"
+ depends on ARCH_MXS
+ select SND_SOC_DMAENGINE_PCM
+ help
+ Say Y or M if you want to add support for codecs attached to
+ the MXS SAIF interface.
+
+
+if SND_MXS_SOC
+
+config SND_SOC_MXS_SGTL5000
+ tristate "SoC Audio support for i.MX boards with sgtl5000"
+ depends on I2C
+ select SND_SOC_SGTL5000
+ help
+ Say Y if you want to add support for SoC audio on an MXS board with
+ a sgtl5000 codec.
+
+endif # SND_MXS_SOC
diff --git a/sound/soc/mxs/Makefile b/sound/soc/mxs/Makefile
new file mode 100644
index 000000000000..565b5b51e8b7
--- /dev/null
+++ b/sound/soc/mxs/Makefile
@@ -0,0 +1,10 @@
+# MXS Platform Support
+snd-soc-mxs-objs := mxs-saif.o
+snd-soc-mxs-pcm-objs := mxs-pcm.o
+
+obj-$(CONFIG_SND_MXS_SOC) += snd-soc-mxs.o snd-soc-mxs-pcm.o
+
+# i.MX Machine Support
+snd-soc-mxs-sgtl5000-objs := mxs-sgtl5000.o
+
+obj-$(CONFIG_SND_SOC_MXS_SGTL5000) += snd-soc-mxs-sgtl5000.o
diff --git a/sound/soc/mxs/mxs-pcm.c b/sound/soc/mxs/mxs-pcm.c
new file mode 100644
index 000000000000..6ca1f46d84a4
--- /dev/null
+++ b/sound/soc/mxs/mxs-pcm.c
@@ -0,0 +1,247 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Based on sound/soc/imx/imx-pcm-dma-mx2.c
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dmaengine.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/dmaengine_pcm.h>
+
+#include <mach/dma.h>
+#include "mxs-pcm.h"
+
+struct mxs_pcm_dma_data {
+ struct mxs_dma_data dma_data;
+ struct mxs_pcm_dma_params *dma_params;
+};
+
+static struct snd_pcm_hardware snd_mxs_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_PAUSE |
+ SNDRV_PCM_INFO_RESUME |
+ SNDRV_PCM_INFO_INTERLEAVED,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE |
+ SNDRV_PCM_FMTBIT_S20_3LE |
+ SNDRV_PCM_FMTBIT_S24_LE,
+ .channels_min = 2,
+ .channels_max = 2,
+ .period_bytes_min = 32,
+ .period_bytes_max = 8192,
+ .periods_min = 1,
+ .periods_max = 52,
+ .buffer_bytes_max = 64 * 1024,
+ .fifo_size = 32,
+
+};
+
+static bool filter(struct dma_chan *chan, void *param)
+{
+ struct mxs_pcm_dma_data *pcm_dma_data = param;
+ struct mxs_pcm_dma_params *dma_params = pcm_dma_data->dma_params;
+
+ if (!mxs_dma_is_apbx(chan))
+ return false;
+
+ if (chan->chan_id != dma_params->chan_num)
+ return false;
+
+ chan->private = &pcm_dma_data->dma_data;
+
+ return true;
+}
+
+static int snd_mxs_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+
+ return 0;
+}
+
+static int snd_mxs_open(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct mxs_pcm_dma_data *pcm_dma_data;
+ int ret;
+
+ pcm_dma_data = kzalloc(sizeof(*pcm_dma_data), GFP_KERNEL);
+ if (pcm_dma_data == NULL)
+ return -ENOMEM;
+
+ pcm_dma_data->dma_params = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
+ pcm_dma_data->dma_data.chan_irq = pcm_dma_data->dma_params->chan_irq;
+
+ ret = snd_dmaengine_pcm_open(substream, filter, pcm_dma_data);
+ if (ret) {
+ kfree(pcm_dma_data);
+ return ret;
+ }
+
+ snd_soc_set_runtime_hwparams(substream, &snd_mxs_hardware);
+
+ snd_dmaengine_pcm_set_data(substream, pcm_dma_data);
+
+ return 0;
+}
+
+static int snd_mxs_close(struct snd_pcm_substream *substream)
+{
+ struct mxs_pcm_dma_data *pcm_dma_data = snd_dmaengine_pcm_get_data(substream);
+
+ snd_dmaengine_pcm_close(substream);
+ kfree(pcm_dma_data);
+
+ return 0;
+}
+
+static int snd_mxs_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area,
+ runtime->dma_addr,
+ runtime->dma_bytes);
+}
+
+static struct snd_pcm_ops mxs_pcm_ops = {
+ .open = snd_mxs_open,
+ .close = snd_mxs_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = snd_mxs_pcm_hw_params,
+ .trigger = snd_dmaengine_pcm_trigger,
+ .pointer = snd_dmaengine_pcm_pointer,
+ .mmap = snd_mxs_pcm_mmap,
+};
+
+static int mxs_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = snd_mxs_hardware.buffer_bytes_max;
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+ if (!buf->area)
+ return -ENOMEM;
+ buf->bytes = size;
+
+ return 0;
+}
+
+static u64 mxs_pcm_dmamask = DMA_BIT_MASK(32);
+static int mxs_pcm_new(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_card *card = rtd->card->snd_card;
+ struct snd_pcm *pcm = rtd->pcm;
+ int ret = 0;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &mxs_pcm_dmamask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
+ ret = mxs_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
+ ret = mxs_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+
+out:
+ return ret;
+}
+
+static void mxs_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+
+ dma_free_writecombine(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+
+static struct snd_soc_platform_driver mxs_soc_platform = {
+ .ops = &mxs_pcm_ops,
+ .pcm_new = mxs_pcm_new,
+ .pcm_free = mxs_pcm_free,
+};
+
+static int __devinit mxs_soc_platform_probe(struct platform_device *pdev)
+{
+ return snd_soc_register_platform(&pdev->dev, &mxs_soc_platform);
+}
+
+static int __devexit mxs_soc_platform_remove(struct platform_device *pdev)
+{
+ snd_soc_unregister_platform(&pdev->dev);
+
+ return 0;
+}
+
+static struct platform_driver mxs_pcm_driver = {
+ .driver = {
+ .name = "mxs-pcm-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = mxs_soc_platform_probe,
+ .remove = __devexit_p(mxs_soc_platform_remove),
+};
+
+module_platform_driver(mxs_pcm_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-pcm-audio");
diff --git a/sound/soc/mxs/mxs-pcm.h b/sound/soc/mxs/mxs-pcm.h
new file mode 100644
index 000000000000..5f01a9124b3d
--- /dev/null
+++ b/sound/soc/mxs/mxs-pcm.h
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef _MXS_PCM_H
+#define _MXS_PCM_H
+
+struct mxs_pcm_dma_params {
+ int chan_irq;
+ int chan_num;
+};
+
+#endif
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c
new file mode 100644
index 000000000000..12be05b16880
--- /dev/null
+++ b/sound/soc/mxs/mxs-saif.c
@@ -0,0 +1,762 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/time.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+#include <sound/saif.h>
+#include <mach/dma.h>
+#include <asm/mach-types.h>
+#include <mach/hardware.h>
+#include <mach/mxs.h>
+
+#include "mxs-saif.h"
+
+static struct mxs_saif *mxs_saif[2];
+
+/*
+ * SAIF is a little different with other normal SOC DAIs on clock using.
+ *
+ * For MXS, two SAIF modules are instantiated on-chip.
+ * Each SAIF has a set of clock pins and can be operating in master
+ * mode simultaneously if they are connected to different off-chip codecs.
+ * Also, one of the two SAIFs can master or drive the clock pins while the
+ * other SAIF, in slave mode, receives clocking from the master SAIF.
+ * This also means that both SAIFs must operate at the same sample rate.
+ *
+ * We abstract this as each saif has a master, the master could be
+ * himself or other saifs. In the generic saif driver, saif does not need
+ * to know the different clkmux. Saif only needs to know who is his master
+ * and operating his master to generate the proper clock rate for him.
+ * The master id is provided in mach-specific layer according to different
+ * clkmux setting.
+ */
+
+static int mxs_saif_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+
+ switch (clk_id) {
+ case MXS_SAIF_MCLK:
+ saif->mclk = freq;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/*
+ * Since SAIF may work on EXTMASTER mode, IOW, it's working BITCLK&LRCLK
+ * is provided by other SAIF, we provide a interface here to get its master
+ * from its master_id.
+ * Note that the master could be himself.
+ */
+static inline struct mxs_saif *mxs_saif_get_master(struct mxs_saif * saif)
+{
+ return mxs_saif[saif->master_id];
+}
+
+/*
+ * Set SAIF clock and MCLK
+ */
+static int mxs_saif_set_clk(struct mxs_saif *saif,
+ unsigned int mclk,
+ unsigned int rate)
+{
+ u32 scr;
+ int ret;
+ struct mxs_saif *master_saif;
+
+ dev_dbg(saif->dev, "mclk %d rate %d\n", mclk, rate);
+
+ /* Set master saif to generate proper clock */
+ master_saif = mxs_saif_get_master(saif);
+ if (!master_saif)
+ return -EINVAL;
+
+ dev_dbg(saif->dev, "master saif%d\n", master_saif->id);
+
+ /* Checking if can playback and capture simutaneously */
+ if (master_saif->ongoing && rate != master_saif->cur_rate) {
+ dev_err(saif->dev,
+ "can not change clock, master saif%d(rate %d) is ongoing\n",
+ master_saif->id, master_saif->cur_rate);
+ return -EINVAL;
+ }
+
+ scr = __raw_readl(master_saif->base + SAIF_CTRL);
+ scr &= ~BM_SAIF_CTRL_BITCLK_MULT_RATE;
+ scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
+
+ /*
+ * Set SAIF clock
+ *
+ * The SAIF clock should be either 384*fs or 512*fs.
+ * If MCLK is used, the SAIF clk ratio need to match mclk ratio.
+ * For 32x mclk, set saif clk as 512*fs.
+ * For 48x mclk, set saif clk as 384*fs.
+ *
+ * If MCLK is not used, we just set saif clk to 512*fs.
+ */
+ clk_prepare_enable(master_saif->clk);
+
+ if (master_saif->mclk_in_use) {
+ if (mclk % 32 == 0) {
+ scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
+ ret = clk_set_rate(master_saif->clk, 512 * rate);
+ } else if (mclk % 48 == 0) {
+ scr |= BM_SAIF_CTRL_BITCLK_BASE_RATE;
+ ret = clk_set_rate(master_saif->clk, 384 * rate);
+ } else {
+ /* SAIF MCLK should be either 32x or 48x */
+ clk_disable_unprepare(master_saif->clk);
+ return -EINVAL;
+ }
+ } else {
+ ret = clk_set_rate(master_saif->clk, 512 * rate);
+ scr &= ~BM_SAIF_CTRL_BITCLK_BASE_RATE;
+ }
+
+ clk_disable_unprepare(master_saif->clk);
+
+ if (ret)
+ return ret;
+
+ master_saif->cur_rate = rate;
+
+ if (!master_saif->mclk_in_use) {
+ __raw_writel(scr, master_saif->base + SAIF_CTRL);
+ return 0;
+ }
+
+ /*
+ * Program the over-sample rate for MCLK output
+ *
+ * The available MCLK range is 32x, 48x... 512x. The rate
+ * could be from 8kHz to 192kH.
+ */
+ switch (mclk / rate) {
+ case 32:
+ scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(4);
+ break;
+ case 64:
+ scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3);
+ break;
+ case 128:
+ scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2);
+ break;
+ case 256:
+ scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1);
+ break;
+ case 512:
+ scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0);
+ break;
+ case 48:
+ scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(3);
+ break;
+ case 96:
+ scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(2);
+ break;
+ case 192:
+ scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(1);
+ break;
+ case 384:
+ scr |= BF_SAIF_CTRL_BITCLK_MULT_RATE(0);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ __raw_writel(scr, master_saif->base + SAIF_CTRL);
+
+ return 0;
+}
+
+/*
+ * Put and disable MCLK.
+ */
+int mxs_saif_put_mclk(unsigned int saif_id)
+{
+ struct mxs_saif *saif = mxs_saif[saif_id];
+ u32 stat;
+
+ if (!saif)
+ return -EINVAL;
+
+ stat = __raw_readl(saif->base + SAIF_STAT);
+ if (stat & BM_SAIF_STAT_BUSY) {
+ dev_err(saif->dev, "error: busy\n");
+ return -EBUSY;
+ }
+
+ clk_disable_unprepare(saif->clk);
+
+ /* disable MCLK output */
+ __raw_writel(BM_SAIF_CTRL_CLKGATE,
+ saif->base + SAIF_CTRL + MXS_SET_ADDR);
+ __raw_writel(BM_SAIF_CTRL_RUN,
+ saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+ saif->mclk_in_use = 0;
+ return 0;
+}
+
+/*
+ * Get MCLK and set clock rate, then enable it
+ *
+ * This interface is used for codecs who are using MCLK provided
+ * by saif.
+ */
+int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk,
+ unsigned int rate)
+{
+ struct mxs_saif *saif = mxs_saif[saif_id];
+ u32 stat;
+ int ret;
+ struct mxs_saif *master_saif;
+
+ if (!saif)
+ return -EINVAL;
+
+ /* Clear Reset */
+ __raw_writel(BM_SAIF_CTRL_SFTRST,
+ saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+ /* FIXME: need clear clk gate for register r/w */
+ __raw_writel(BM_SAIF_CTRL_CLKGATE,
+ saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+ master_saif = mxs_saif_get_master(saif);
+ if (saif != master_saif) {
+ dev_err(saif->dev, "can not get mclk from a non-master saif\n");
+ return -EINVAL;
+ }
+
+ stat = __raw_readl(saif->base + SAIF_STAT);
+ if (stat & BM_SAIF_STAT_BUSY) {
+ dev_err(saif->dev, "error: busy\n");
+ return -EBUSY;
+ }
+
+ saif->mclk_in_use = 1;
+ ret = mxs_saif_set_clk(saif, mclk, rate);
+ if (ret)
+ return ret;
+
+ ret = clk_prepare_enable(saif->clk);
+ if (ret)
+ return ret;
+
+ /* enable MCLK output */
+ __raw_writel(BM_SAIF_CTRL_RUN,
+ saif->base + SAIF_CTRL + MXS_SET_ADDR);
+
+ return 0;
+}
+
+/*
+ * SAIF DAI format configuration.
+ * Should only be called when port is inactive.
+ */
+static int mxs_saif_set_dai_fmt(struct snd_soc_dai *cpu_dai, unsigned int fmt)
+{
+ u32 scr, stat;
+ u32 scr0;
+ struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+
+ stat = __raw_readl(saif->base + SAIF_STAT);
+ if (stat & BM_SAIF_STAT_BUSY) {
+ dev_err(cpu_dai->dev, "error: busy\n");
+ return -EBUSY;
+ }
+
+ scr0 = __raw_readl(saif->base + SAIF_CTRL);
+ scr0 = scr0 & ~BM_SAIF_CTRL_BITCLK_EDGE & ~BM_SAIF_CTRL_LRCLK_POLARITY \
+ & ~BM_SAIF_CTRL_JUSTIFY & ~BM_SAIF_CTRL_DELAY;
+ scr = 0;
+
+ /* DAI mode */
+ switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
+ case SND_SOC_DAIFMT_I2S:
+ /* data frame low 1clk before data */
+ scr |= BM_SAIF_CTRL_DELAY;
+ scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
+ break;
+ case SND_SOC_DAIFMT_LEFT_J:
+ /* data frame high with data */
+ scr &= ~BM_SAIF_CTRL_DELAY;
+ scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
+ scr &= ~BM_SAIF_CTRL_JUSTIFY;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* DAI clock inversion */
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
+ case SND_SOC_DAIFMT_IB_IF:
+ scr |= BM_SAIF_CTRL_BITCLK_EDGE;
+ scr |= BM_SAIF_CTRL_LRCLK_POLARITY;
+ break;
+ case SND_SOC_DAIFMT_IB_NF:
+ scr |= BM_SAIF_CTRL_BITCLK_EDGE;
+ scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
+ break;
+ case SND_SOC_DAIFMT_NB_IF:
+ scr &= ~BM_SAIF_CTRL_BITCLK_EDGE;
+ scr |= BM_SAIF_CTRL_LRCLK_POLARITY;
+ break;
+ case SND_SOC_DAIFMT_NB_NF:
+ scr &= ~BM_SAIF_CTRL_BITCLK_EDGE;
+ scr &= ~BM_SAIF_CTRL_LRCLK_POLARITY;
+ break;
+ }
+
+ /*
+ * Note: We simply just support master mode since SAIF TX can only
+ * work as master.
+ * Here the master is relative to codec side.
+ * Saif internally could be slave when working on EXTMASTER mode.
+ * We just hide this to machine driver.
+ */
+ switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
+ case SND_SOC_DAIFMT_CBS_CFS:
+ if (saif->id == saif->master_id)
+ scr &= ~BM_SAIF_CTRL_SLAVE_MODE;
+ else
+ scr |= BM_SAIF_CTRL_SLAVE_MODE;
+
+ __raw_writel(scr | scr0, saif->base + SAIF_CTRL);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mxs_saif_startup(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+ snd_soc_dai_set_dma_data(cpu_dai, substream, &saif->dma_param);
+
+ /* clear error status to 0 for each re-open */
+ saif->fifo_underrun = 0;
+ saif->fifo_overrun = 0;
+
+ /* Clear Reset for normal operations */
+ __raw_writel(BM_SAIF_CTRL_SFTRST,
+ saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+ /* clear clock gate */
+ __raw_writel(BM_SAIF_CTRL_CLKGATE,
+ saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+
+ return 0;
+}
+
+/*
+ * Should only be called when port is inactive.
+ * although can be called multiple times by upper layers.
+ */
+static int mxs_saif_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+ u32 scr, stat;
+ int ret;
+
+ /* mclk should already be set */
+ if (!saif->mclk && saif->mclk_in_use) {
+ dev_err(cpu_dai->dev, "set mclk first\n");
+ return -EINVAL;
+ }
+
+ stat = __raw_readl(saif->base + SAIF_STAT);
+ if (stat & BM_SAIF_STAT_BUSY) {
+ dev_err(cpu_dai->dev, "error: busy\n");
+ return -EBUSY;
+ }
+
+ /*
+ * Set saif clk based on sample rate.
+ * If mclk is used, we also set mclk, if not, saif->mclk is
+ * default 0, means not used.
+ */
+ ret = mxs_saif_set_clk(saif, saif->mclk, params_rate(params));
+ if (ret) {
+ dev_err(cpu_dai->dev, "unable to get proper clk\n");
+ return ret;
+ }
+
+ scr = __raw_readl(saif->base + SAIF_CTRL);
+
+ scr &= ~BM_SAIF_CTRL_WORD_LENGTH;
+ scr &= ~BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S16_LE:
+ scr |= BF_SAIF_CTRL_WORD_LENGTH(0);
+ break;
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ scr |= BF_SAIF_CTRL_WORD_LENGTH(4);
+ scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ scr |= BF_SAIF_CTRL_WORD_LENGTH(8);
+ scr |= BM_SAIF_CTRL_BITCLK_48XFS_ENABLE;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ /* Tx/Rx config */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /* enable TX mode */
+ scr &= ~BM_SAIF_CTRL_READ_MODE;
+ } else {
+ /* enable RX mode */
+ scr |= BM_SAIF_CTRL_READ_MODE;
+ }
+
+ __raw_writel(scr, saif->base + SAIF_CTRL);
+ return 0;
+}
+
+static int mxs_saif_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+
+ /* enable FIFO error irqs */
+ __raw_writel(BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN,
+ saif->base + SAIF_CTRL + MXS_SET_ADDR);
+
+ return 0;
+}
+
+static int mxs_saif_trigger(struct snd_pcm_substream *substream, int cmd,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct mxs_saif *saif = snd_soc_dai_get_drvdata(cpu_dai);
+ struct mxs_saif *master_saif;
+ u32 delay;
+
+ master_saif = mxs_saif_get_master(saif);
+ if (!master_saif)
+ return -EINVAL;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ dev_dbg(cpu_dai->dev, "start\n");
+
+ clk_enable(master_saif->clk);
+ if (!master_saif->mclk_in_use)
+ __raw_writel(BM_SAIF_CTRL_RUN,
+ master_saif->base + SAIF_CTRL + MXS_SET_ADDR);
+
+ /*
+ * If the saif's master is not himself, we also need to enable
+ * itself clk for its internal basic logic to work.
+ */
+ if (saif != master_saif) {
+ clk_enable(saif->clk);
+ __raw_writel(BM_SAIF_CTRL_RUN,
+ saif->base + SAIF_CTRL + MXS_SET_ADDR);
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ /*
+ * write a data to saif data register to trigger
+ * the transfer
+ */
+ __raw_writel(0, saif->base + SAIF_DATA);
+ } else {
+ /*
+ * read a data from saif data register to trigger
+ * the receive
+ */
+ __raw_readl(saif->base + SAIF_DATA);
+ }
+
+ master_saif->ongoing = 1;
+
+ dev_dbg(saif->dev, "CTRL 0x%x STAT 0x%x\n",
+ __raw_readl(saif->base + SAIF_CTRL),
+ __raw_readl(saif->base + SAIF_STAT));
+
+ dev_dbg(master_saif->dev, "CTRL 0x%x STAT 0x%x\n",
+ __raw_readl(master_saif->base + SAIF_CTRL),
+ __raw_readl(master_saif->base + SAIF_STAT));
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dev_dbg(cpu_dai->dev, "stop\n");
+
+ /* wait a while for the current sample to complete */
+ delay = USEC_PER_SEC / master_saif->cur_rate;
+
+ if (!master_saif->mclk_in_use) {
+ __raw_writel(BM_SAIF_CTRL_RUN,
+ master_saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+ udelay(delay);
+ }
+ clk_disable(master_saif->clk);
+
+ if (saif != master_saif) {
+ __raw_writel(BM_SAIF_CTRL_RUN,
+ saif->base + SAIF_CTRL + MXS_CLR_ADDR);
+ udelay(delay);
+ clk_disable(saif->clk);
+ }
+
+ master_saif->ongoing = 0;
+
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+#define MXS_SAIF_RATES SNDRV_PCM_RATE_8000_192000
+#define MXS_SAIF_FORMATS \
+ (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
+ SNDRV_PCM_FMTBIT_S24_LE)
+
+static const struct snd_soc_dai_ops mxs_saif_dai_ops = {
+ .startup = mxs_saif_startup,
+ .trigger = mxs_saif_trigger,
+ .prepare = mxs_saif_prepare,
+ .hw_params = mxs_saif_hw_params,
+ .set_sysclk = mxs_saif_set_dai_sysclk,
+ .set_fmt = mxs_saif_set_dai_fmt,
+};
+
+static int mxs_saif_dai_probe(struct snd_soc_dai *dai)
+{
+ struct mxs_saif *saif = dev_get_drvdata(dai->dev);
+
+ snd_soc_dai_set_drvdata(dai, saif);
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver mxs_saif_dai = {
+ .name = "mxs-saif",
+ .probe = mxs_saif_dai_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = MXS_SAIF_RATES,
+ .formats = MXS_SAIF_FORMATS,
+ },
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = MXS_SAIF_RATES,
+ .formats = MXS_SAIF_FORMATS,
+ },
+ .ops = &mxs_saif_dai_ops,
+};
+
+static irqreturn_t mxs_saif_irq(int irq, void *dev_id)
+{
+ struct mxs_saif *saif = dev_id;
+ unsigned int stat;
+
+ stat = __raw_readl(saif->base + SAIF_STAT);
+ if (!(stat & (BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ |
+ BM_SAIF_STAT_FIFO_OVERFLOW_IRQ)))
+ return IRQ_NONE;
+
+ if (stat & BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ) {
+ dev_dbg(saif->dev, "underrun!!! %d\n", ++saif->fifo_underrun);
+ __raw_writel(BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ,
+ saif->base + SAIF_STAT + MXS_CLR_ADDR);
+ }
+
+ if (stat & BM_SAIF_STAT_FIFO_OVERFLOW_IRQ) {
+ dev_dbg(saif->dev, "overrun!!! %d\n", ++saif->fifo_overrun);
+ __raw_writel(BM_SAIF_STAT_FIFO_OVERFLOW_IRQ,
+ saif->base + SAIF_STAT + MXS_CLR_ADDR);
+ }
+
+ dev_dbg(saif->dev, "SAIF_CTRL %x SAIF_STAT %x\n",
+ __raw_readl(saif->base + SAIF_CTRL),
+ __raw_readl(saif->base + SAIF_STAT));
+
+ return IRQ_HANDLED;
+}
+
+static int mxs_saif_probe(struct platform_device *pdev)
+{
+ struct resource *iores, *dmares;
+ struct mxs_saif *saif;
+ struct mxs_saif_platform_data *pdata;
+ int ret = 0;
+
+ if (pdev->id >= ARRAY_SIZE(mxs_saif))
+ return -EINVAL;
+
+ saif = devm_kzalloc(&pdev->dev, sizeof(*saif), GFP_KERNEL);
+ if (!saif)
+ return -ENOMEM;
+
+ mxs_saif[pdev->id] = saif;
+ saif->id = pdev->id;
+
+ pdata = pdev->dev.platform_data;
+ if (pdata && !pdata->master_mode) {
+ saif->master_id = pdata->master_id;
+ if (saif->master_id < 0 ||
+ saif->master_id >= ARRAY_SIZE(mxs_saif) ||
+ saif->master_id == saif->id) {
+ dev_err(&pdev->dev, "get wrong master id\n");
+ return -EINVAL;
+ }
+ } else {
+ saif->master_id = saif->id;
+ }
+
+ saif->clk = clk_get(&pdev->dev, NULL);
+ if (IS_ERR(saif->clk)) {
+ ret = PTR_ERR(saif->clk);
+ dev_err(&pdev->dev, "Cannot get the clock: %d\n",
+ ret);
+ return ret;
+ }
+
+ iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+ saif->base = devm_request_and_ioremap(&pdev->dev, iores);
+ if (!saif->base) {
+ dev_err(&pdev->dev, "ioremap failed\n");
+ ret = -ENODEV;
+ goto failed_get_resource;
+ }
+
+ dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!dmares) {
+ ret = -ENODEV;
+ dev_err(&pdev->dev, "failed to get dma resource: %d\n",
+ ret);
+ goto failed_get_resource;
+ }
+ saif->dma_param.chan_num = dmares->start;
+
+ saif->irq = platform_get_irq(pdev, 0);
+ if (saif->irq < 0) {
+ ret = saif->irq;
+ dev_err(&pdev->dev, "failed to get irq resource: %d\n",
+ ret);
+ goto failed_get_resource;
+ }
+
+ saif->dev = &pdev->dev;
+ ret = devm_request_irq(&pdev->dev, saif->irq, mxs_saif_irq, 0,
+ "mxs-saif", saif);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request irq\n");
+ goto failed_get_resource;
+ }
+
+ saif->dma_param.chan_irq = platform_get_irq(pdev, 1);
+ if (saif->dma_param.chan_irq < 0) {
+ ret = saif->dma_param.chan_irq;
+ dev_err(&pdev->dev, "failed to get dma irq resource: %d\n",
+ ret);
+ goto failed_get_resource;
+ }
+
+ platform_set_drvdata(pdev, saif);
+
+ ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai);
+ if (ret) {
+ dev_err(&pdev->dev, "register DAI failed\n");
+ goto failed_get_resource;
+ }
+
+ saif->soc_platform_pdev = platform_device_alloc(
+ "mxs-pcm-audio", pdev->id);
+ if (!saif->soc_platform_pdev) {
+ ret = -ENOMEM;
+ goto failed_pdev_alloc;
+ }
+
+ platform_set_drvdata(saif->soc_platform_pdev, saif);
+ ret = platform_device_add(saif->soc_platform_pdev);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to add soc platform device\n");
+ goto failed_pdev_add;
+ }
+
+ return 0;
+
+failed_pdev_add:
+ platform_device_put(saif->soc_platform_pdev);
+failed_pdev_alloc:
+ snd_soc_unregister_dai(&pdev->dev);
+failed_get_resource:
+ clk_put(saif->clk);
+
+ return ret;
+}
+
+static int __devexit mxs_saif_remove(struct platform_device *pdev)
+{
+ struct mxs_saif *saif = platform_get_drvdata(pdev);
+
+ platform_device_unregister(saif->soc_platform_pdev);
+ snd_soc_unregister_dai(&pdev->dev);
+ clk_put(saif->clk);
+
+ return 0;
+}
+
+static struct platform_driver mxs_saif_driver = {
+ .probe = mxs_saif_probe,
+ .remove = __devexit_p(mxs_saif_remove),
+
+ .driver = {
+ .name = "mxs-saif",
+ .owner = THIS_MODULE,
+ },
+};
+
+module_platform_driver(mxs_saif_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXS ASoC SAIF driver");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/mxs/mxs-saif.h b/sound/soc/mxs/mxs-saif.h
new file mode 100644
index 000000000000..12c91e4eb941
--- /dev/null
+++ b/sound/soc/mxs/mxs-saif.h
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+
+#ifndef _MXS_SAIF_H
+#define _MXS_SAIF_H
+
+#define SAIF_CTRL 0x0
+#define SAIF_STAT 0x10
+#define SAIF_DATA 0x20
+#define SAIF_VERSION 0X30
+
+/* SAIF_CTRL */
+#define BM_SAIF_CTRL_SFTRST 0x80000000
+#define BM_SAIF_CTRL_CLKGATE 0x40000000
+#define BP_SAIF_CTRL_BITCLK_MULT_RATE 27
+#define BM_SAIF_CTRL_BITCLK_MULT_RATE 0x38000000
+#define BF_SAIF_CTRL_BITCLK_MULT_RATE(v) \
+ (((v) << 27) & BM_SAIF_CTRL_BITCLK_MULT_RATE)
+#define BM_SAIF_CTRL_BITCLK_BASE_RATE 0x04000000
+#define BM_SAIF_CTRL_FIFO_ERROR_IRQ_EN 0x02000000
+#define BM_SAIF_CTRL_FIFO_SERVICE_IRQ_EN 0x01000000
+#define BP_SAIF_CTRL_RSRVD2 21
+#define BM_SAIF_CTRL_RSRVD2 0x00E00000
+
+#define BP_SAIF_CTRL_DMAWAIT_COUNT 16
+#define BM_SAIF_CTRL_DMAWAIT_COUNT 0x001F0000
+#define BF_SAIF_CTRL_DMAWAIT_COUNT(v) \
+ (((v) << 16) & BM_SAIF_CTRL_DMAWAIT_COUNT)
+#define BP_SAIF_CTRL_CHANNEL_NUM_SELECT 14
+#define BM_SAIF_CTRL_CHANNEL_NUM_SELECT 0x0000C000
+#define BF_SAIF_CTRL_CHANNEL_NUM_SELECT(v) \
+ (((v) << 14) & BM_SAIF_CTRL_CHANNEL_NUM_SELECT)
+#define BM_SAIF_CTRL_LRCLK_PULSE 0x00002000
+#define BM_SAIF_CTRL_BIT_ORDER 0x00001000
+#define BM_SAIF_CTRL_DELAY 0x00000800
+#define BM_SAIF_CTRL_JUSTIFY 0x00000400
+#define BM_SAIF_CTRL_LRCLK_POLARITY 0x00000200
+#define BM_SAIF_CTRL_BITCLK_EDGE 0x00000100
+#define BP_SAIF_CTRL_WORD_LENGTH 4
+#define BM_SAIF_CTRL_WORD_LENGTH 0x000000F0
+#define BF_SAIF_CTRL_WORD_LENGTH(v) \
+ (((v) << 4) & BM_SAIF_CTRL_WORD_LENGTH)
+#define BM_SAIF_CTRL_BITCLK_48XFS_ENABLE 0x00000008
+#define BM_SAIF_CTRL_SLAVE_MODE 0x00000004
+#define BM_SAIF_CTRL_READ_MODE 0x00000002
+#define BM_SAIF_CTRL_RUN 0x00000001
+
+/* SAIF_STAT */
+#define BM_SAIF_STAT_PRESENT 0x80000000
+#define BP_SAIF_STAT_RSRVD2 17
+#define BM_SAIF_STAT_RSRVD2 0x7FFE0000
+#define BF_SAIF_STAT_RSRVD2(v) \
+ (((v) << 17) & BM_SAIF_STAT_RSRVD2)
+#define BM_SAIF_STAT_DMA_PREQ 0x00010000
+#define BP_SAIF_STAT_RSRVD1 7
+#define BM_SAIF_STAT_RSRVD1 0x0000FF80
+#define BF_SAIF_STAT_RSRVD1(v) \
+ (((v) << 7) & BM_SAIF_STAT_RSRVD1)
+
+#define BM_SAIF_STAT_FIFO_UNDERFLOW_IRQ 0x00000040
+#define BM_SAIF_STAT_FIFO_OVERFLOW_IRQ 0x00000020
+#define BM_SAIF_STAT_FIFO_SERVICE_IRQ 0x00000010
+#define BP_SAIF_STAT_RSRVD0 1
+#define BM_SAIF_STAT_RSRVD0 0x0000000E
+#define BF_SAIF_STAT_RSRVD0(v) \
+ (((v) << 1) & BM_SAIF_STAT_RSRVD0)
+#define BM_SAIF_STAT_BUSY 0x00000001
+
+/* SAFI_DATA */
+#define BP_SAIF_DATA_PCM_RIGHT 16
+#define BM_SAIF_DATA_PCM_RIGHT 0xFFFF0000
+#define BF_SAIF_DATA_PCM_RIGHT(v) \
+ (((v) << 16) & BM_SAIF_DATA_PCM_RIGHT)
+#define BP_SAIF_DATA_PCM_LEFT 0
+#define BM_SAIF_DATA_PCM_LEFT 0x0000FFFF
+#define BF_SAIF_DATA_PCM_LEFT(v) \
+ (((v) << 0) & BM_SAIF_DATA_PCM_LEFT)
+
+/* SAIF_VERSION */
+#define BP_SAIF_VERSION_MAJOR 24
+#define BM_SAIF_VERSION_MAJOR 0xFF000000
+#define BF_SAIF_VERSION_MAJOR(v) \
+ (((v) << 24) & BM_SAIF_VERSION_MAJOR)
+#define BP_SAIF_VERSION_MINOR 16
+#define BM_SAIF_VERSION_MINOR 0x00FF0000
+#define BF_SAIF_VERSION_MINOR(v) \
+ (((v) << 16) & BM_SAIF_VERSION_MINOR)
+#define BP_SAIF_VERSION_STEP 0
+#define BM_SAIF_VERSION_STEP 0x0000FFFF
+#define BF_SAIF_VERSION_STEP(v) \
+ (((v) << 0) & BM_SAIF_VERSION_STEP)
+
+#define MXS_SAIF_MCLK 0
+
+#include "mxs-pcm.h"
+
+struct mxs_saif {
+ struct device *dev;
+ struct clk *clk;
+ unsigned int mclk;
+ unsigned int mclk_in_use;
+ void __iomem *base;
+ int irq;
+ struct mxs_pcm_dma_params dma_param;
+ unsigned int id;
+ unsigned int master_id;
+ unsigned int cur_rate;
+ unsigned int ongoing;
+
+ struct platform_device *soc_platform_pdev;
+ u32 fifo_underrun;
+ u32 fifo_overrun;
+};
+
+extern int mxs_saif_put_mclk(unsigned int saif_id);
+extern int mxs_saif_get_mclk(unsigned int saif_id, unsigned int mclk,
+ unsigned int rate);
+#endif
diff --git a/sound/soc/mxs/mxs-sgtl5000.c b/sound/soc/mxs/mxs-sgtl5000.c
new file mode 100644
index 000000000000..60f052b7cf22
--- /dev/null
+++ b/sound/soc/mxs/mxs-sgtl5000.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <linux/module.h>
+#include <linux/device.h>
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+#include <sound/soc-dapm.h>
+#include <asm/mach-types.h>
+
+#include "../codecs/sgtl5000.h"
+#include "mxs-saif.h"
+
+static int mxs_sgtl5000_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ unsigned int rate = params_rate(params);
+ u32 dai_format, mclk;
+ int ret;
+
+ /* sgtl5000 does not support 512*rate when in 96000 fs */
+ switch (rate) {
+ case 96000:
+ mclk = 256 * rate;
+ break;
+ default:
+ mclk = 512 * rate;
+ break;
+ }
+
+ /* Sgtl5000 sysclk should be >= 8MHz and <= 27M */
+ if (mclk < 8000000 || mclk > 27000000)
+ return -EINVAL;
+
+ /* Set SGTL5000's SYSCLK (provided by SAIF MCLK) */
+ ret = snd_soc_dai_set_sysclk(codec_dai, SGTL5000_SYSCLK, mclk, 0);
+ if (ret)
+ return ret;
+
+ /* The SAIF MCLK should be the same as SGTL5000_SYSCLK */
+ ret = snd_soc_dai_set_sysclk(cpu_dai, MXS_SAIF_MCLK, mclk, 0);
+ if (ret)
+ return ret;
+
+ /* set codec to slave mode */
+ dai_format = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS;
+
+ /* set codec DAI configuration */
+ ret = snd_soc_dai_set_fmt(codec_dai, dai_format);
+ if (ret)
+ return ret;
+
+ /* set cpu DAI configuration */
+ ret = snd_soc_dai_set_fmt(cpu_dai, dai_format);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops mxs_sgtl5000_hifi_ops = {
+ .hw_params = mxs_sgtl5000_hw_params,
+};
+
+static struct snd_soc_dai_link mxs_sgtl5000_dai[] = {
+ {
+ .name = "HiFi Tx",
+ .stream_name = "HiFi Playback",
+ .codec_dai_name = "sgtl5000",
+ .codec_name = "sgtl5000.0-000a",
+ .cpu_dai_name = "mxs-saif.0",
+ .platform_name = "mxs-pcm-audio.0",
+ .ops = &mxs_sgtl5000_hifi_ops,
+ }, {
+ .name = "HiFi Rx",
+ .stream_name = "HiFi Capture",
+ .codec_dai_name = "sgtl5000",
+ .codec_name = "sgtl5000.0-000a",
+ .cpu_dai_name = "mxs-saif.1",
+ .platform_name = "mxs-pcm-audio.1",
+ .ops = &mxs_sgtl5000_hifi_ops,
+ },
+};
+
+static struct snd_soc_card mxs_sgtl5000 = {
+ .name = "mxs_sgtl5000",
+ .owner = THIS_MODULE,
+ .dai_link = mxs_sgtl5000_dai,
+ .num_links = ARRAY_SIZE(mxs_sgtl5000_dai),
+};
+
+static int __devinit mxs_sgtl5000_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &mxs_sgtl5000;
+ int ret;
+
+ /*
+ * Set an init clock(11.28Mhz) for sgtl5000 initialization(i2c r/w).
+ * The Sgtl5000 sysclk is derived from saif0 mclk and it's range
+ * should be >= 8MHz and <= 27M.
+ */
+ ret = mxs_saif_get_mclk(0, 44100 * 256, 44100);
+ if (ret)
+ return ret;
+
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devexit mxs_sgtl5000_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ mxs_saif_put_mclk(0);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static struct platform_driver mxs_sgtl5000_audio_driver = {
+ .driver = {
+ .name = "mxs-sgtl5000",
+ .owner = THIS_MODULE,
+ },
+ .probe = mxs_sgtl5000_probe,
+ .remove = __devexit_p(mxs_sgtl5000_remove),
+};
+
+module_platform_driver(mxs_sgtl5000_audio_driver);
+
+MODULE_AUTHOR("Freescale Semiconductor, Inc.");
+MODULE_DESCRIPTION("MXS ALSA SoC Machine driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:mxs-sgtl5000");
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c
index 9c0edad90d8b..946020a647db 100644
--- a/sound/soc/nuc900/nuc900-ac97.c
+++ b/sound/soc/nuc900/nuc900-ac97.c
@@ -291,7 +291,7 @@ static int nuc900_ac97_remove(struct snd_soc_dai *dai)
return 0;
}
-static struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
+static const struct snd_soc_dai_ops nuc900_ac97_dai_ops = {
.trigger = nuc900_ac97_trigger,
};
@@ -365,7 +365,8 @@ static int __devinit nuc900_ac97_drvprobe(struct platform_device *pdev)
if (ret)
goto out3;
- mfp_set_groupg(nuc900_audio->dev); /* enbale ac97 multifunction pin*/
+ /* enbale ac97 multifunction pin */
+ mfp_set_groupg(nuc900_audio->dev, NULL);
return 0;
@@ -405,18 +406,7 @@ static struct platform_driver nuc900_ac97_driver = {
.remove = __devexit_p(nuc900_ac97_drvremove),
};
-static int __init nuc900_ac97_init(void)
-{
- return platform_driver_register(&nuc900_ac97_driver);
-}
-
-static void __exit nuc900_ac97_exit(void)
-{
- platform_driver_unregister(&nuc900_ac97_driver);
-}
-
-module_init(nuc900_ac97_init);
-module_exit(nuc900_ac97_exit);
+module_platform_driver(nuc900_ac97_driver);
MODULE_AUTHOR("Wan ZongShun <mcuos.com@gmail.com>");
MODULE_DESCRIPTION("NUC900 AC97 SoC driver!");
diff --git a/sound/soc/nuc900/nuc900-audio.c b/sound/soc/nuc900/nuc900-audio.c
index 38a2d0d883b5..2f6e6fd6e05c 100644
--- a/sound/soc/nuc900/nuc900-audio.c
+++ b/sound/soc/nuc900/nuc900-audio.c
@@ -32,6 +32,7 @@ static struct snd_soc_dai_link nuc900evb_ac97_dai = {
static struct snd_soc_card nuc900evb_audio_machine = {
.name = "NUC900EVB_AC97",
+ .owner = THIS_MODULE,
.dai_link = &nuc900evb_ac97_dai,
.num_links = 1,
};
diff --git a/sound/soc/nuc900/nuc900-pcm.c b/sound/soc/nuc900/nuc900-pcm.c
index d589ef14e917..37585b47f4e3 100644
--- a/sound/soc/nuc900/nuc900-pcm.c
+++ b/sound/soc/nuc900/nuc900-pcm.c
@@ -227,7 +227,7 @@ static int nuc900_dma_trigger(struct snd_pcm_substream *substream, int cmd)
return ret;
}
-int nuc900_dma_getposition(struct snd_pcm_substream *substream,
+static int nuc900_dma_getposition(struct snd_pcm_substream *substream,
dma_addr_t *src, dma_addr_t *dst)
{
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -268,7 +268,7 @@ static int nuc900_dma_open(struct snd_pcm_substream *substream)
nuc900_audio = nuc900_ac97_data;
if (request_irq(nuc900_audio->irq_num, nuc900_dma_interrupt,
- IRQF_DISABLED, "nuc900-dma", substream))
+ 0, "nuc900-dma", substream))
return -EBUSY;
runtime->private_data = nuc900_audio;
@@ -318,7 +318,6 @@ static u64 nuc900_pcm_dmamask = DMA_BIT_MASK(32);
static int nuc900_dma_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
if (!card->dev->dma_mask)
@@ -359,17 +358,7 @@ static struct platform_driver nuc900_pcm_driver = {
.remove = __devexit_p(nuc900_soc_platform_remove),
};
-static int __init nuc900_pcm_init(void)
-{
- return platform_driver_register(&nuc900_pcm_driver);
-}
-module_init(nuc900_pcm_init);
-
-static void __exit nuc900_pcm_exit(void)
-{
- platform_driver_unregister(&nuc900_pcm_driver);
-}
-module_exit(nuc900_pcm_exit);
+module_platform_driver(nuc900_pcm_driver);
MODULE_AUTHOR("Wan ZongShun, <mcuos.com@gmail.com>");
MODULE_DESCRIPTION("nuc900 Audio DMA module");
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index fe83d0d176be..e00dd0b1139c 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -2,9 +2,11 @@ config SND_OMAP_SOC
tristate "SoC Audio for the Texas Instruments OMAP chips"
depends on ARCH_OMAP
+config SND_OMAP_SOC_DMIC
+ tristate
+
config SND_OMAP_SOC_MCBSP
tristate
- select OMAP_MCBSP
config SND_OMAP_SOC_MCPDM
tristate
@@ -24,7 +26,6 @@ config SND_OMAP_SOC_N810
config SND_OMAP_SOC_RX51
tristate "SoC Audio support for Nokia RX-51"
depends on SND_OMAP_SOC && MACH_NOKIA_RX51
- select OMAP_MCBSP
select SND_OMAP_SOC_MCBSP
select SND_SOC_TLV320AIC3X
select SND_SOC_TPA6130A2
@@ -94,14 +95,19 @@ config SND_OMAP_SOC_SDP3430
Say Y if you want to add support for SoC audio on Texas Instruments
SDP3430.
-config SND_OMAP_SOC_SDP4430
- tristate "SoC Audio support for Texas Instruments SDP4430"
- depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_4430SDP
+config SND_OMAP_SOC_OMAP_ABE_TWL6040
+ tristate "SoC Audio support for OMAP boards using ABE and twl6040 codec"
+ depends on TWL4030_CORE && SND_OMAP_SOC && ARCH_OMAP4
+ select SND_OMAP_SOC_DMIC
select SND_OMAP_SOC_MCPDM
select SND_SOC_TWL6040
+ select SND_SOC_DMIC
help
- Say Y if you want to add support for SoC audio on Texas Instruments
- SDP4430.
+ Say Y if you want to add support for SoC audio on OMAP boards using
+ ABE and twl6040 codec. This driver currently supports:
+ - SDP4430/Blaze boards
+ - PandaBoard (4430)
+ - PandaBoardES (4460)
config SND_OMAP_SOC_OMAP4_HDMI
tristate "SoC Audio support for Texas Instruments OMAP4 HDMI"
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 59e2c8d1e38d..1d656bce01d4 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -1,10 +1,12 @@
# OMAP Platform Support
snd-soc-omap-objs := omap-pcm.o
-snd-soc-omap-mcbsp-objs := omap-mcbsp.o
-snd-soc-omap-mcpdm-objs := omap-mcpdm.o mcpdm.o
+snd-soc-omap-dmic-objs := omap-dmic.o
+snd-soc-omap-mcbsp-objs := omap-mcbsp.o mcbsp.o
+snd-soc-omap-mcpdm-objs := omap-mcpdm.o
snd-soc-omap-hdmi-objs := omap-hdmi.o
obj-$(CONFIG_SND_OMAP_SOC) += snd-soc-omap.o
+obj-$(CONFIG_SND_OMAP_SOC_DMIC) += snd-soc-omap-dmic.o
obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o
obj-$(CONFIG_SND_OMAP_SOC_HDMI) += snd-soc-omap-hdmi.o
@@ -18,7 +20,7 @@ snd-soc-overo-objs := overo.o
snd-soc-omap3evm-objs := omap3evm.o
snd-soc-am3517evm-objs := am3517evm.o
snd-soc-sdp3430-objs := sdp3430.o
-snd-soc-sdp4430-objs := sdp4430.o
+snd-soc-omap-abe-twl6040-objs := omap-abe-twl6040.o
snd-soc-omap3pandora-objs := omap3pandora.o
snd-soc-omap3beagle-objs := omap3beagle.o
snd-soc-zoom2-objs := zoom2.o
@@ -34,7 +36,7 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
-obj-$(CONFIG_SND_OMAP_SOC_SDP4430) += snd-soc-sdp4430.o
+obj-$(CONFIG_SND_OMAP_SOC_OMAP_ABE_TWL6040) += snd-soc-omap-abe-twl6040.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
diff --git a/sound/soc/omap/am3517evm.c b/sound/soc/omap/am3517evm.c
index 73dde4a1adc3..009533ab8d18 100644
--- a/sound/soc/omap/am3517evm.c
+++ b/sound/soc/omap/am3517evm.c
@@ -19,6 +19,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -43,26 +44,6 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret;
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_DSP_B |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_B |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0,
CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -110,45 +91,30 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"MICIN", NULL, "Mic In"},
};
-static int am3517evm_aic23_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_codec *codec = rtd->codec;
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- /* Add am3517-evm specific widgets */
- snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
- ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
- /* Set up davinci-evm specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- /* always connected */
- snd_soc_dapm_enable_pin(dapm, "Line Out");
- snd_soc_dapm_enable_pin(dapm, "Line In");
- snd_soc_dapm_enable_pin(dapm, "Mic In");
-
- snd_soc_dapm_sync(dapm);
-
- return 0;
-}
-
/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link am3517evm_dai = {
.name = "TLV320AIC23",
.stream_name = "AIC23",
- .cpu_dai_name ="omap-mcbsp-dai.0",
+ .cpu_dai_name = "omap-mcbsp.1",
.codec_dai_name = "tlv320aic23-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "tlv320aic23-codec.2-001a",
- .init = am3517evm_aic23_init,
+ .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &am3517evm_ops,
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_am3517evm = {
.name = "am3517evm",
+ .owner = THIS_MODULE,
.dai_link = &am3517evm_dai,
.num_links = 1,
+
+ .dapm_widgets = tlv320aic23_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
};
static struct platform_device *am3517evm_snd_device;
diff --git a/sound/soc/omap/ams-delta.c b/sound/soc/omap/ams-delta.c
index 0aa475f92efa..49fe63ce51f7 100644
--- a/sound/soc/omap/ams-delta.c
+++ b/sound/soc/omap/ams-delta.c
@@ -25,6 +25,7 @@
#include <linux/gpio.h>
#include <linux/spinlock.h>
#include <linux/tty.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/jack.h>
@@ -430,22 +431,20 @@ static int ams_delta_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
- struct snd_soc_codec *codec = card->rtd->codec;
-
switch (level) {
case SND_SOC_BIAS_ON:
case SND_SOC_BIAS_PREPARE:
case SND_SOC_BIAS_STANDBY:
- if (codec->dapm.bias_level == SND_SOC_BIAS_OFF)
+ if (card->dapm.bias_level == SND_SOC_BIAS_OFF)
ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
AMS_DELTA_LATCH2_MODEM_NRESET);
break;
case SND_SOC_BIAS_OFF:
- if (codec->dapm.bias_level != SND_SOC_BIAS_OFF)
+ if (card->dapm.bias_level != SND_SOC_BIAS_OFF)
ams_delta_latch2_write(AMS_DELTA_LATCH2_MODEM_NRESET,
0);
}
- codec->dapm.bias_level = level;
+ card->dapm.bias_level = level;
return 0;
}
@@ -473,7 +472,7 @@ static int ams_delta_digital_mute(struct snd_soc_dai *dai, int mute)
}
/* Our codec DAI probably doesn't have its own .ops structure */
-static struct snd_soc_dai_ops ams_delta_dai_ops = {
+static const struct snd_soc_dai_ops ams_delta_dai_ops = {
.digital_mute = ams_delta_digital_mute,
};
@@ -569,10 +568,9 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "Speaker");
snd_soc_dapm_disable_pin(dapm, "AGCIN");
snd_soc_dapm_disable_pin(dapm, "AGCOUT");
- snd_soc_dapm_sync(dapm);
/* Add virtual switch */
- ret = snd_soc_add_controls(codec, ams_delta_audio_controls,
+ ret = snd_soc_add_codec_controls(codec, ams_delta_audio_controls,
ARRAY_SIZE(ams_delta_audio_controls));
if (ret)
dev_warn(card->dev,
@@ -586,7 +584,7 @@ static int ams_delta_cx20442_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_dai_link ams_delta_dai_link = {
.name = "CX20442",
.stream_name = "CX20442",
- .cpu_dai_name ="omap-mcbsp-dai.0",
+ .cpu_dai_name = "omap-mcbsp.1",
.codec_dai_name = "cx20442-voice",
.init = ams_delta_cx20442_init,
.platform_name = "omap-pcm-audio",
@@ -597,6 +595,7 @@ static struct snd_soc_dai_link ams_delta_dai_link = {
/* Audio card driver */
static struct snd_soc_card ams_delta_audio_card = {
.name = "AMS_DELTA",
+ .owner = THIS_MODULE,
.dai_link = &ams_delta_dai_link,
.num_links = 1,
.set_bias_level = ams_delta_set_bias_level,
diff --git a/sound/soc/omap/igep0020.c b/sound/soc/omap/igep0020.c
index 0ae34702995b..e8357819175b 100644
--- a/sound/soc/omap/igep0020.c
+++ b/sound/soc/omap/igep0020.c
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -38,29 +39,8 @@ static int igep2_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret;
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
SND_SOC_CLOCK_IN);
@@ -80,16 +60,19 @@ static struct snd_soc_ops igep2_ops = {
static struct snd_soc_dai_link igep2_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &igep2_ops,
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_card_igep2 = {
.name = "igep2",
+ .owner = THIS_MODULE,
.dai_link = &igep2_dai,
.num_links = 1,
};
diff --git a/sound/soc/omap/mcbsp.c b/sound/soc/omap/mcbsp.c
new file mode 100644
index 000000000000..e5f44440d1b9
--- /dev/null
+++ b/sound/soc/omap/mcbsp.c
@@ -0,0 +1,1040 @@
+/*
+ * sound/soc/omap/mcbsp.c
+ *
+ * Copyright (C) 2004 Nokia Corporation
+ * Author: Samuel Ortiz <samuel.ortiz@nokia.com>
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ * Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Multichannel mode not supported.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+
+#include <plat/mcbsp.h>
+
+#include "mcbsp.h"
+
+static void omap_mcbsp_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+{
+ void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+ if (mcbsp->pdata->reg_size == 2) {
+ ((u16 *)mcbsp->reg_cache)[reg] = (u16)val;
+ __raw_writew((u16)val, addr);
+ } else {
+ ((u32 *)mcbsp->reg_cache)[reg] = val;
+ __raw_writel(val, addr);
+ }
+}
+
+static int omap_mcbsp_read(struct omap_mcbsp *mcbsp, u16 reg, bool from_cache)
+{
+ void __iomem *addr = mcbsp->io_base + reg * mcbsp->pdata->reg_step;
+
+ if (mcbsp->pdata->reg_size == 2) {
+ return !from_cache ? __raw_readw(addr) :
+ ((u16 *)mcbsp->reg_cache)[reg];
+ } else {
+ return !from_cache ? __raw_readl(addr) :
+ ((u32 *)mcbsp->reg_cache)[reg];
+ }
+}
+
+static void omap_mcbsp_st_write(struct omap_mcbsp *mcbsp, u16 reg, u32 val)
+{
+ __raw_writel(val, mcbsp->st_data->io_base_st + reg);
+}
+
+static int omap_mcbsp_st_read(struct omap_mcbsp *mcbsp, u16 reg)
+{
+ return __raw_readl(mcbsp->st_data->io_base_st + reg);
+}
+
+#define MCBSP_READ(mcbsp, reg) \
+ omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 0)
+#define MCBSP_WRITE(mcbsp, reg, val) \
+ omap_mcbsp_write(mcbsp, OMAP_MCBSP_REG_##reg, val)
+#define MCBSP_READ_CACHE(mcbsp, reg) \
+ omap_mcbsp_read(mcbsp, OMAP_MCBSP_REG_##reg, 1)
+
+#define MCBSP_ST_READ(mcbsp, reg) \
+ omap_mcbsp_st_read(mcbsp, OMAP_ST_REG_##reg)
+#define MCBSP_ST_WRITE(mcbsp, reg, val) \
+ omap_mcbsp_st_write(mcbsp, OMAP_ST_REG_##reg, val)
+
+static void omap_mcbsp_dump_reg(struct omap_mcbsp *mcbsp)
+{
+ dev_dbg(mcbsp->dev, "**** McBSP%d regs ****\n", mcbsp->id);
+ dev_dbg(mcbsp->dev, "DRR2: 0x%04x\n",
+ MCBSP_READ(mcbsp, DRR2));
+ dev_dbg(mcbsp->dev, "DRR1: 0x%04x\n",
+ MCBSP_READ(mcbsp, DRR1));
+ dev_dbg(mcbsp->dev, "DXR2: 0x%04x\n",
+ MCBSP_READ(mcbsp, DXR2));
+ dev_dbg(mcbsp->dev, "DXR1: 0x%04x\n",
+ MCBSP_READ(mcbsp, DXR1));
+ dev_dbg(mcbsp->dev, "SPCR2: 0x%04x\n",
+ MCBSP_READ(mcbsp, SPCR2));
+ dev_dbg(mcbsp->dev, "SPCR1: 0x%04x\n",
+ MCBSP_READ(mcbsp, SPCR1));
+ dev_dbg(mcbsp->dev, "RCR2: 0x%04x\n",
+ MCBSP_READ(mcbsp, RCR2));
+ dev_dbg(mcbsp->dev, "RCR1: 0x%04x\n",
+ MCBSP_READ(mcbsp, RCR1));
+ dev_dbg(mcbsp->dev, "XCR2: 0x%04x\n",
+ MCBSP_READ(mcbsp, XCR2));
+ dev_dbg(mcbsp->dev, "XCR1: 0x%04x\n",
+ MCBSP_READ(mcbsp, XCR1));
+ dev_dbg(mcbsp->dev, "SRGR2: 0x%04x\n",
+ MCBSP_READ(mcbsp, SRGR2));
+ dev_dbg(mcbsp->dev, "SRGR1: 0x%04x\n",
+ MCBSP_READ(mcbsp, SRGR1));
+ dev_dbg(mcbsp->dev, "PCR0: 0x%04x\n",
+ MCBSP_READ(mcbsp, PCR0));
+ dev_dbg(mcbsp->dev, "***********************\n");
+}
+
+static irqreturn_t omap_mcbsp_tx_irq_handler(int irq, void *dev_id)
+{
+ struct omap_mcbsp *mcbsp_tx = dev_id;
+ u16 irqst_spcr2;
+
+ irqst_spcr2 = MCBSP_READ(mcbsp_tx, SPCR2);
+ dev_dbg(mcbsp_tx->dev, "TX IRQ callback : 0x%x\n", irqst_spcr2);
+
+ if (irqst_spcr2 & XSYNC_ERR) {
+ dev_err(mcbsp_tx->dev, "TX Frame Sync Error! : 0x%x\n",
+ irqst_spcr2);
+ /* Writing zero to XSYNC_ERR clears the IRQ */
+ MCBSP_WRITE(mcbsp_tx, SPCR2, MCBSP_READ_CACHE(mcbsp_tx, SPCR2));
+ }
+
+ return IRQ_HANDLED;
+}
+
+static irqreturn_t omap_mcbsp_rx_irq_handler(int irq, void *dev_id)
+{
+ struct omap_mcbsp *mcbsp_rx = dev_id;
+ u16 irqst_spcr1;
+
+ irqst_spcr1 = MCBSP_READ(mcbsp_rx, SPCR1);
+ dev_dbg(mcbsp_rx->dev, "RX IRQ callback : 0x%x\n", irqst_spcr1);
+
+ if (irqst_spcr1 & RSYNC_ERR) {
+ dev_err(mcbsp_rx->dev, "RX Frame Sync Error! : 0x%x\n",
+ irqst_spcr1);
+ /* Writing zero to RSYNC_ERR clears the IRQ */
+ MCBSP_WRITE(mcbsp_rx, SPCR1, MCBSP_READ_CACHE(mcbsp_rx, SPCR1));
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * omap_mcbsp_config simply write a config to the
+ * appropriate McBSP.
+ * You either call this function or set the McBSP registers
+ * by yourself before calling omap_mcbsp_start().
+ */
+void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
+ const struct omap_mcbsp_reg_cfg *config)
+{
+ dev_dbg(mcbsp->dev, "Configuring McBSP%d phys_base: 0x%08lx\n",
+ mcbsp->id, mcbsp->phys_base);
+
+ /* We write the given config */
+ MCBSP_WRITE(mcbsp, SPCR2, config->spcr2);
+ MCBSP_WRITE(mcbsp, SPCR1, config->spcr1);
+ MCBSP_WRITE(mcbsp, RCR2, config->rcr2);
+ MCBSP_WRITE(mcbsp, RCR1, config->rcr1);
+ MCBSP_WRITE(mcbsp, XCR2, config->xcr2);
+ MCBSP_WRITE(mcbsp, XCR1, config->xcr1);
+ MCBSP_WRITE(mcbsp, SRGR2, config->srgr2);
+ MCBSP_WRITE(mcbsp, SRGR1, config->srgr1);
+ MCBSP_WRITE(mcbsp, MCR2, config->mcr2);
+ MCBSP_WRITE(mcbsp, MCR1, config->mcr1);
+ MCBSP_WRITE(mcbsp, PCR0, config->pcr0);
+ if (mcbsp->pdata->has_ccr) {
+ MCBSP_WRITE(mcbsp, XCCR, config->xccr);
+ MCBSP_WRITE(mcbsp, RCCR, config->rccr);
+ }
+ /* Enable wakeup behavior */
+ if (mcbsp->pdata->has_wakeup)
+ MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
+}
+
+/**
+ * omap_mcbsp_dma_reg_params - returns the address of mcbsp data register
+ * @id - mcbsp id
+ * @stream - indicates the direction of data flow (rx or tx)
+ *
+ * Returns the address of mcbsp data transmit register or data receive register
+ * to be used by DMA for transferring/receiving data based on the value of
+ * @stream for the requested mcbsp given by @id
+ */
+static int omap_mcbsp_dma_reg_params(struct omap_mcbsp *mcbsp,
+ unsigned int stream)
+{
+ int data_reg;
+
+ if (mcbsp->pdata->reg_size == 2) {
+ if (stream)
+ data_reg = OMAP_MCBSP_REG_DRR1;
+ else
+ data_reg = OMAP_MCBSP_REG_DXR1;
+ } else {
+ if (stream)
+ data_reg = OMAP_MCBSP_REG_DRR;
+ else
+ data_reg = OMAP_MCBSP_REG_DXR;
+ }
+
+ return mcbsp->phys_dma_base + data_reg * mcbsp->pdata->reg_step;
+}
+
+static void omap_st_on(struct omap_mcbsp *mcbsp)
+{
+ unsigned int w;
+
+ if (mcbsp->pdata->enable_st_clock)
+ mcbsp->pdata->enable_st_clock(mcbsp->id, 1);
+
+ /* Enable McBSP Sidetone */
+ w = MCBSP_READ(mcbsp, SSELCR);
+ MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN);
+
+ /* Enable Sidetone from Sidetone Core */
+ w = MCBSP_ST_READ(mcbsp, SSELCR);
+ MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN);
+}
+
+static void omap_st_off(struct omap_mcbsp *mcbsp)
+{
+ unsigned int w;
+
+ w = MCBSP_ST_READ(mcbsp, SSELCR);
+ MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));
+
+ w = MCBSP_READ(mcbsp, SSELCR);
+ MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
+
+ if (mcbsp->pdata->enable_st_clock)
+ mcbsp->pdata->enable_st_clock(mcbsp->id, 0);
+}
+
+static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
+{
+ u16 val, i;
+
+ val = MCBSP_ST_READ(mcbsp, SSELCR);
+
+ if (val & ST_COEFFWREN)
+ MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN));
+
+ MCBSP_ST_WRITE(mcbsp, SSELCR, val | ST_COEFFWREN);
+
+ for (i = 0; i < 128; i++)
+ MCBSP_ST_WRITE(mcbsp, SFIRCR, fir[i]);
+
+ i = 0;
+
+ val = MCBSP_ST_READ(mcbsp, SSELCR);
+ while (!(val & ST_COEFFWRDONE) && (++i < 1000))
+ val = MCBSP_ST_READ(mcbsp, SSELCR);
+
+ MCBSP_ST_WRITE(mcbsp, SSELCR, val & ~(ST_COEFFWREN));
+
+ if (i == 1000)
+ dev_err(mcbsp->dev, "McBSP FIR load error!\n");
+}
+
+static void omap_st_chgain(struct omap_mcbsp *mcbsp)
+{
+ u16 w;
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+ w = MCBSP_ST_READ(mcbsp, SSELCR);
+
+ MCBSP_ST_WRITE(mcbsp, SGAINCR, ST_CH0GAIN(st_data->ch0gain) | \
+ ST_CH1GAIN(st_data->ch1gain));
+}
+
+int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ int ret = 0;
+
+ if (!st_data)
+ return -ENOENT;
+
+ spin_lock_irq(&mcbsp->lock);
+ if (channel == 0)
+ st_data->ch0gain = chgain;
+ else if (channel == 1)
+ st_data->ch1gain = chgain;
+ else
+ ret = -EINVAL;
+
+ if (st_data->enabled)
+ omap_st_chgain(mcbsp);
+ spin_unlock_irq(&mcbsp->lock);
+
+ return ret;
+}
+
+int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ int ret = 0;
+
+ if (!st_data)
+ return -ENOENT;
+
+ spin_lock_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;
+}
+
+static int omap_st_start(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+ if (st_data->enabled && !st_data->running) {
+ omap_st_fir_write(mcbsp, st_data->taps);
+ omap_st_chgain(mcbsp);
+
+ if (!mcbsp->free) {
+ omap_st_on(mcbsp);
+ st_data->running = 1;
+ }
+ }
+
+ return 0;
+}
+
+int omap_st_enable(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+ if (!st_data)
+ return -ENODEV;
+
+ spin_lock_irq(&mcbsp->lock);
+ st_data->enabled = 1;
+ omap_st_start(mcbsp);
+ spin_unlock_irq(&mcbsp->lock);
+
+ return 0;
+}
+
+static int omap_st_stop(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+ if (st_data->running) {
+ if (!mcbsp->free) {
+ omap_st_off(mcbsp);
+ st_data->running = 0;
+ }
+ }
+
+ return 0;
+}
+
+int omap_st_disable(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ int ret = 0;
+
+ if (!st_data)
+ return -ENODEV;
+
+ spin_lock_irq(&mcbsp->lock);
+ omap_st_stop(mcbsp);
+ st_data->enabled = 0;
+ spin_unlock_irq(&mcbsp->lock);
+
+ return ret;
+}
+
+int omap_st_is_enabled(struct omap_mcbsp *mcbsp)
+{
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+
+ if (!st_data)
+ return -ENODEV;
+
+ return st_data->enabled;
+}
+
+/*
+ * omap_mcbsp_set_rx_threshold configures the transmit threshold in words.
+ * The threshold parameter is 1 based, and it is converted (threshold - 1)
+ * for the THRSH2 register.
+ */
+void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
+{
+ if (mcbsp->pdata->buffer_size == 0)
+ return;
+
+ if (threshold && threshold <= mcbsp->max_tx_thres)
+ MCBSP_WRITE(mcbsp, THRSH2, threshold - 1);
+}
+
+/*
+ * omap_mcbsp_set_rx_threshold configures the receive threshold in words.
+ * The threshold parameter is 1 based, and it is converted (threshold - 1)
+ * for the THRSH1 register.
+ */
+void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold)
+{
+ if (mcbsp->pdata->buffer_size == 0)
+ return;
+
+ if (threshold && threshold <= mcbsp->max_rx_thres)
+ MCBSP_WRITE(mcbsp, THRSH1, threshold - 1);
+}
+
+/*
+ * omap_mcbsp_get_tx_delay returns the number of used slots in the McBSP FIFO
+ */
+u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp)
+{
+ u16 buffstat;
+
+ if (mcbsp->pdata->buffer_size == 0)
+ return 0;
+
+ /* Returns the number of free locations in the buffer */
+ buffstat = MCBSP_READ(mcbsp, XBUFFSTAT);
+
+ /* Number of slots are different in McBSP ports */
+ return mcbsp->pdata->buffer_size - buffstat;
+}
+
+/*
+ * omap_mcbsp_get_rx_delay returns the number of free slots in the McBSP FIFO
+ * to reach the threshold value (when the DMA will be triggered to read it)
+ */
+u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp)
+{
+ u16 buffstat, threshold;
+
+ if (mcbsp->pdata->buffer_size == 0)
+ return 0;
+
+ /* Returns the number of used locations in the buffer */
+ buffstat = MCBSP_READ(mcbsp, RBUFFSTAT);
+ /* RX threshold */
+ threshold = MCBSP_READ(mcbsp, THRSH1);
+
+ /* Return the number of location till we reach the threshold limit */
+ if (threshold <= buffstat)
+ return 0;
+ else
+ return threshold - buffstat;
+}
+
+int omap_mcbsp_request(struct omap_mcbsp *mcbsp)
+{
+ void *reg_cache;
+ 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;
+ }
+
+ mcbsp->free = false;
+ mcbsp->reg_cache = reg_cache;
+ spin_unlock(&mcbsp->lock);
+
+ if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
+ mcbsp->pdata->ops->request(mcbsp->id - 1);
+
+ /*
+ * Make sure that transmitter, receiver and sample-rate generator are
+ * not running before activating IRQs.
+ */
+ MCBSP_WRITE(mcbsp, SPCR1, 0);
+ MCBSP_WRITE(mcbsp, SPCR2, 0);
+
+ err = request_irq(mcbsp->tx_irq, omap_mcbsp_tx_irq_handler,
+ 0, "McBSP", (void *)mcbsp);
+ if (err != 0) {
+ dev_err(mcbsp->dev, "Unable to request TX IRQ %d "
+ "for McBSP%d\n", mcbsp->tx_irq,
+ mcbsp->id);
+ goto err_clk_disable;
+ }
+
+ if (mcbsp->rx_irq) {
+ err = request_irq(mcbsp->rx_irq,
+ omap_mcbsp_rx_irq_handler,
+ 0, "McBSP", (void *)mcbsp);
+ if (err != 0) {
+ dev_err(mcbsp->dev, "Unable to request RX IRQ %d "
+ "for McBSP%d\n", mcbsp->rx_irq,
+ mcbsp->id);
+ goto err_free_irq;
+ }
+ }
+
+ return 0;
+err_free_irq:
+ free_irq(mcbsp->tx_irq, (void *)mcbsp);
+err_clk_disable:
+ if (mcbsp->pdata && 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);
+
+ spin_lock(&mcbsp->lock);
+ mcbsp->free = true;
+ mcbsp->reg_cache = NULL;
+err_kfree:
+ spin_unlock(&mcbsp->lock);
+ kfree(reg_cache);
+
+ return err;
+}
+
+void omap_mcbsp_free(struct omap_mcbsp *mcbsp)
+{
+ void *reg_cache;
+
+ if (mcbsp->pdata && 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);
+
+ if (mcbsp->rx_irq)
+ free_irq(mcbsp->rx_irq, (void *)mcbsp);
+ free_irq(mcbsp->tx_irq, (void *)mcbsp);
+
+ reg_cache = mcbsp->reg_cache;
+
+ /*
+ * Select CLKS source from internal source unconditionally before
+ * marking the McBSP port as free.
+ * If the external clock source via MCBSP_CLKS pin has been selected the
+ * system will refuse to enter idle if the CLKS pin source is not reset
+ * back to internal source.
+ */
+ if (!cpu_class_is_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);
+
+ if (reg_cache)
+ kfree(reg_cache);
+}
+
+/*
+ * Here we start the McBSP, by enabling transmitter, receiver or both.
+ * If no transmitter or receiver is active prior calling, then sample-rate
+ * generator and frame sync are started.
+ */
+void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx)
+{
+ int enable_srg = 0;
+ u16 w;
+
+ if (mcbsp->st_data)
+ omap_st_start(mcbsp);
+
+ /* Only enable SRG, if McBSP is master */
+ w = MCBSP_READ_CACHE(mcbsp, PCR0);
+ if (w & (FSXM | FSRM | CLKXM | CLKRM))
+ enable_srg = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
+ MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
+
+ if (enable_srg) {
+ /* Start the sample generator */
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+ MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 6));
+ }
+
+ /* Enable transmitter and receiver */
+ tx &= 1;
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+ MCBSP_WRITE(mcbsp, SPCR2, w | tx);
+
+ rx &= 1;
+ w = MCBSP_READ_CACHE(mcbsp, SPCR1);
+ MCBSP_WRITE(mcbsp, SPCR1, w | rx);
+
+ /*
+ * Worst case: CLKSRG*2 = 8000khz: (1/8000) * 2 * 2 usec
+ * REVISIT: 100us may give enough time for two CLKSRG, however
+ * due to some unknown PM related, clock gating etc. reason it
+ * is now at 500us.
+ */
+ udelay(500);
+
+ if (enable_srg) {
+ /* Start frame sync */
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+ MCBSP_WRITE(mcbsp, SPCR2, w | (1 << 7));
+ }
+
+ if (mcbsp->pdata->has_ccr) {
+ /* Release the transmitter and receiver */
+ w = MCBSP_READ_CACHE(mcbsp, XCCR);
+ w &= ~(tx ? XDISABLE : 0);
+ MCBSP_WRITE(mcbsp, XCCR, w);
+ w = MCBSP_READ_CACHE(mcbsp, RCCR);
+ w &= ~(rx ? RDISABLE : 0);
+ MCBSP_WRITE(mcbsp, RCCR, w);
+ }
+
+ /* Dump McBSP Regs */
+ omap_mcbsp_dump_reg(mcbsp);
+}
+
+void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx)
+{
+ int idle;
+ u16 w;
+
+ /* Reset transmitter */
+ tx &= 1;
+ if (mcbsp->pdata->has_ccr) {
+ w = MCBSP_READ_CACHE(mcbsp, XCCR);
+ w |= (tx ? XDISABLE : 0);
+ MCBSP_WRITE(mcbsp, XCCR, w);
+ }
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+ MCBSP_WRITE(mcbsp, SPCR2, w & ~tx);
+
+ /* Reset receiver */
+ rx &= 1;
+ if (mcbsp->pdata->has_ccr) {
+ w = MCBSP_READ_CACHE(mcbsp, RCCR);
+ w |= (rx ? RDISABLE : 0);
+ MCBSP_WRITE(mcbsp, RCCR, w);
+ }
+ w = MCBSP_READ_CACHE(mcbsp, SPCR1);
+ MCBSP_WRITE(mcbsp, SPCR1, w & ~rx);
+
+ idle = !((MCBSP_READ_CACHE(mcbsp, SPCR2) |
+ MCBSP_READ_CACHE(mcbsp, SPCR1)) & 1);
+
+ if (idle) {
+ /* Reset the sample rate generator */
+ w = MCBSP_READ_CACHE(mcbsp, SPCR2);
+ MCBSP_WRITE(mcbsp, SPCR2, w & ~(1 << 6));
+ }
+
+ if (mcbsp->st_data)
+ omap_st_stop(mcbsp);
+}
+
+int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id)
+{
+ const char *src;
+
+ if (fck_src_id == MCBSP_CLKS_PAD_SRC)
+ src = "clks_ext";
+ else if (fck_src_id == MCBSP_CLKS_PRCM_SRC)
+ src = "clks_fclk";
+ else
+ return -EINVAL;
+
+ if (mcbsp->pdata->set_clk_src)
+ return mcbsp->pdata->set_clk_src(mcbsp->dev, mcbsp->fclk, src);
+ else
+ return -EINVAL;
+}
+
+int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux)
+{
+ const char *signal, *src;
+
+ if (mcbsp->pdata->mux_signal)
+ return -EINVAL;
+
+ switch (mux) {
+ case CLKR_SRC_CLKR:
+ signal = "clkr";
+ src = "clkr";
+ break;
+ case CLKR_SRC_CLKX:
+ signal = "clkr";
+ src = "clkx";
+ break;
+ case FSR_SRC_FSR:
+ signal = "fsr";
+ src = "fsr";
+ break;
+ case FSR_SRC_FSX:
+ signal = "fsr";
+ src = "fsx";
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return mcbsp->pdata->mux_signal(mcbsp->dev, signal, src);
+}
+
+#define max_thres(m) (mcbsp->pdata->buffer_size)
+#define valid_threshold(m, val) ((val) <= max_thres(m))
+#define THRESHOLD_PROP_BUILDER(prop) \
+static ssize_t prop##_show(struct device *dev, \
+ struct device_attribute *attr, char *buf) \
+{ \
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
+ \
+ return sprintf(buf, "%u\n", mcbsp->prop); \
+} \
+ \
+static ssize_t prop##_store(struct device *dev, \
+ struct device_attribute *attr, \
+ const char *buf, size_t size) \
+{ \
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev); \
+ unsigned long val; \
+ int status; \
+ \
+ status = strict_strtoul(buf, 0, &val); \
+ if (status) \
+ return status; \
+ \
+ if (!valid_threshold(mcbsp, val)) \
+ return -EDOM; \
+ \
+ mcbsp->prop = val; \
+ return size; \
+} \
+ \
+static DEVICE_ATTR(prop, 0644, prop##_show, prop##_store);
+
+THRESHOLD_PROP_BUILDER(max_tx_thres);
+THRESHOLD_PROP_BUILDER(max_rx_thres);
+
+static const char *dma_op_modes[] = {
+ "element", "threshold", "frame",
+};
+
+static ssize_t dma_op_mode_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ int dma_op_mode, i = 0;
+ ssize_t len = 0;
+ const char * const *s;
+
+ dma_op_mode = mcbsp->dma_op_mode;
+
+ for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++) {
+ if (dma_op_mode == i)
+ len += sprintf(buf + len, "[%s] ", *s);
+ else
+ len += sprintf(buf + len, "%s ", *s);
+ }
+ len += sprintf(buf + len, "\n");
+
+ return len;
+}
+
+static ssize_t dma_op_mode_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ const char * const *s;
+ int i = 0;
+
+ for (s = &dma_op_modes[i]; i < ARRAY_SIZE(dma_op_modes); s++, i++)
+ if (sysfs_streq(buf, *s))
+ break;
+
+ if (i == ARRAY_SIZE(dma_op_modes))
+ return -EINVAL;
+
+ spin_lock_irq(&mcbsp->lock);
+ if (!mcbsp->free) {
+ size = -EBUSY;
+ goto unlock;
+ }
+ mcbsp->dma_op_mode = i;
+
+unlock:
+ spin_unlock_irq(&mcbsp->lock);
+
+ return size;
+}
+
+static DEVICE_ATTR(dma_op_mode, 0644, dma_op_mode_show, dma_op_mode_store);
+
+static const struct attribute *additional_attrs[] = {
+ &dev_attr_max_tx_thres.attr,
+ &dev_attr_max_rx_thres.attr,
+ &dev_attr_dma_op_mode.attr,
+ NULL,
+};
+
+static const struct attribute_group additional_attr_group = {
+ .attrs = (struct attribute **)additional_attrs,
+};
+
+static ssize_t st_taps_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ ssize_t status = 0;
+ int i;
+
+ spin_lock_irq(&mcbsp->lock);
+ for (i = 0; i < st_data->nr_taps; i++)
+ status += sprintf(&buf[status], (i ? ", %d" : "%d"),
+ st_data->taps[i]);
+ if (i)
+ status += sprintf(&buf[status], "\n");
+ spin_unlock_irq(&mcbsp->lock);
+
+ return status;
+}
+
+static ssize_t st_taps_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t size)
+{
+ struct omap_mcbsp *mcbsp = dev_get_drvdata(dev);
+ struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+ int val, tmp, status, i = 0;
+
+ spin_lock_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;
+ }
+ if (val < -32768 || val > 32767) {
+ size = -EINVAL;
+ goto out;
+ }
+ st_data->taps[i++] = val;
+ buf += tmp;
+ if (*buf != ',')
+ break;
+ buf++;
+ } while (1);
+
+ st_data->nr_taps = i;
+
+out:
+ spin_unlock_irq(&mcbsp->lock);
+
+ return size;
+}
+
+static DEVICE_ATTR(st_taps, 0644, st_taps_show, st_taps_store);
+
+static const struct attribute *sidetone_attrs[] = {
+ &dev_attr_st_taps.attr,
+ NULL,
+};
+
+static const struct attribute_group sidetone_attr_group = {
+ .attrs = (struct attribute **)sidetone_attrs,
+};
+
+static int __devinit omap_st_add(struct omap_mcbsp *mcbsp,
+ struct resource *res)
+{
+ struct omap_mcbsp_st_data *st_data;
+ int err;
+
+ st_data = devm_kzalloc(mcbsp->dev, sizeof(*mcbsp->st_data), GFP_KERNEL);
+ if (!st_data)
+ return -ENOMEM;
+
+ st_data->io_base_st = devm_ioremap(mcbsp->dev, res->start,
+ resource_size(res));
+ if (!st_data->io_base_st)
+ return -ENOMEM;
+
+ err = sysfs_create_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+ if (err)
+ return err;
+
+ mcbsp->st_data = st_data;
+ return 0;
+}
+
+/*
+ * McBSP1 and McBSP3 are directly mapped on 1610 and 1510.
+ * 730 has only 2 McBSP, and both of them are MPU peripherals.
+ */
+int __devinit omap_mcbsp_init(struct platform_device *pdev)
+{
+ struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+ struct resource *res;
+ int ret = 0;
+
+ spin_lock_init(&mcbsp->lock);
+ mcbsp->free = true;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+ if (!res) {
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (!res) {
+ dev_err(mcbsp->dev, "invalid memory resource\n");
+ return -ENOMEM;
+ }
+ }
+ if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+ dev_name(&pdev->dev))) {
+ dev_err(mcbsp->dev, "memory region already claimed\n");
+ return -ENODEV;
+ }
+
+ mcbsp->phys_base = res->start;
+ mcbsp->reg_cache_size = resource_size(res);
+ mcbsp->io_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!mcbsp->io_base)
+ return -ENOMEM;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
+ if (!res)
+ mcbsp->phys_dma_base = mcbsp->phys_base;
+ else
+ mcbsp->phys_dma_base = res->start;
+
+ mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
+ mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
+
+ /* From OMAP4 there will be a single irq line */
+ if (mcbsp->tx_irq == -ENXIO) {
+ mcbsp->tx_irq = platform_get_irq(pdev, 0);
+ mcbsp->rx_irq = 0;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+ if (!res) {
+ dev_err(&pdev->dev, "invalid rx DMA channel\n");
+ return -ENODEV;
+ }
+ /* RX DMA request number, and port address configuration */
+ mcbsp->dma_data[1].name = "Audio Capture";
+ mcbsp->dma_data[1].dma_req = res->start;
+ mcbsp->dma_data[1].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 1);
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+ if (!res) {
+ dev_err(&pdev->dev, "invalid tx DMA channel\n");
+ return -ENODEV;
+ }
+ /* TX DMA request number, and port address configuration */
+ mcbsp->dma_data[0].name = "Audio Playback";
+ mcbsp->dma_data[0].dma_req = res->start;
+ mcbsp->dma_data[0].port_addr = omap_mcbsp_dma_reg_params(mcbsp, 0);
+
+ mcbsp->fclk = clk_get(&pdev->dev, "fck");
+ if (IS_ERR(mcbsp->fclk)) {
+ ret = PTR_ERR(mcbsp->fclk);
+ dev_err(mcbsp->dev, "unable to get fck: %d\n", ret);
+ return ret;
+ }
+
+ mcbsp->dma_op_mode = MCBSP_DMA_MODE_ELEMENT;
+ if (mcbsp->pdata->buffer_size) {
+ /*
+ * Initially configure the maximum thresholds to a safe value.
+ * The McBSP FIFO usage with these values should not go under
+ * 16 locations.
+ * If the whole FIFO without safety buffer is used, than there
+ * is a possibility that the DMA will be not able to push the
+ * new data on time, causing channel shifts in runtime.
+ */
+ mcbsp->max_tx_thres = max_thres(mcbsp) - 0x10;
+ mcbsp->max_rx_thres = max_thres(mcbsp) - 0x10;
+
+ ret = sysfs_create_group(&mcbsp->dev->kobj,
+ &additional_attr_group);
+ if (ret) {
+ dev_err(mcbsp->dev,
+ "Unable to create additional controls\n");
+ goto err_thres;
+ }
+ } else {
+ mcbsp->max_tx_thres = -EINVAL;
+ mcbsp->max_rx_thres = -EINVAL;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
+ if (res) {
+ ret = omap_st_add(mcbsp, res);
+ if (ret) {
+ dev_err(mcbsp->dev,
+ "Unable to create sidetone controls\n");
+ goto err_st;
+ }
+ }
+
+ return 0;
+
+err_st:
+ if (mcbsp->pdata->buffer_size)
+ sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
+err_thres:
+ clk_put(mcbsp->fclk);
+ return ret;
+}
+
+void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp)
+{
+ if (mcbsp->pdata->buffer_size)
+ sysfs_remove_group(&mcbsp->dev->kobj, &additional_attr_group);
+
+ if (mcbsp->st_data)
+ sysfs_remove_group(&mcbsp->dev->kobj, &sidetone_attr_group);
+}
diff --git a/sound/soc/omap/mcbsp.h b/sound/soc/omap/mcbsp.h
new file mode 100644
index 000000000000..a944fcc9073c
--- /dev/null
+++ b/sound/soc/omap/mcbsp.h
@@ -0,0 +1,346 @@
+/*
+ * sound/soc/omap/mcbsp.h
+ *
+ * OMAP Multi-Channel Buffered Serial Port
+ *
+ * Contact: Jarkko Nikula <jarkko.nikula@bitmer.com>
+ * Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+#ifndef __ASOC_MCBSP_H
+#define __ASOC_MCBSP_H
+
+#include "omap-pcm.h"
+
+/* McBSP register numbers. Register address offset = num * reg_step */
+enum {
+ /* Common registers */
+ OMAP_MCBSP_REG_SPCR2 = 4,
+ OMAP_MCBSP_REG_SPCR1,
+ OMAP_MCBSP_REG_RCR2,
+ OMAP_MCBSP_REG_RCR1,
+ OMAP_MCBSP_REG_XCR2,
+ OMAP_MCBSP_REG_XCR1,
+ OMAP_MCBSP_REG_SRGR2,
+ OMAP_MCBSP_REG_SRGR1,
+ OMAP_MCBSP_REG_MCR2,
+ OMAP_MCBSP_REG_MCR1,
+ OMAP_MCBSP_REG_RCERA,
+ OMAP_MCBSP_REG_RCERB,
+ OMAP_MCBSP_REG_XCERA,
+ OMAP_MCBSP_REG_XCERB,
+ OMAP_MCBSP_REG_PCR0,
+ OMAP_MCBSP_REG_RCERC,
+ OMAP_MCBSP_REG_RCERD,
+ OMAP_MCBSP_REG_XCERC,
+ OMAP_MCBSP_REG_XCERD,
+ OMAP_MCBSP_REG_RCERE,
+ OMAP_MCBSP_REG_RCERF,
+ OMAP_MCBSP_REG_XCERE,
+ OMAP_MCBSP_REG_XCERF,
+ OMAP_MCBSP_REG_RCERG,
+ OMAP_MCBSP_REG_RCERH,
+ OMAP_MCBSP_REG_XCERG,
+ OMAP_MCBSP_REG_XCERH,
+
+ /* OMAP1-OMAP2420 registers */
+ OMAP_MCBSP_REG_DRR2 = 0,
+ OMAP_MCBSP_REG_DRR1,
+ OMAP_MCBSP_REG_DXR2,
+ OMAP_MCBSP_REG_DXR1,
+
+ /* OMAP2430 and onwards */
+ OMAP_MCBSP_REG_DRR = 0,
+ OMAP_MCBSP_REG_DXR = 2,
+ OMAP_MCBSP_REG_SYSCON = 35,
+ OMAP_MCBSP_REG_THRSH2,
+ OMAP_MCBSP_REG_THRSH1,
+ OMAP_MCBSP_REG_IRQST = 40,
+ OMAP_MCBSP_REG_IRQEN,
+ OMAP_MCBSP_REG_WAKEUPEN,
+ OMAP_MCBSP_REG_XCCR,
+ OMAP_MCBSP_REG_RCCR,
+ OMAP_MCBSP_REG_XBUFFSTAT,
+ OMAP_MCBSP_REG_RBUFFSTAT,
+ OMAP_MCBSP_REG_SSELCR,
+};
+
+/* OMAP3 sidetone control registers */
+#define OMAP_ST_REG_REV 0x00
+#define OMAP_ST_REG_SYSCONFIG 0x10
+#define OMAP_ST_REG_IRQSTATUS 0x18
+#define OMAP_ST_REG_IRQENABLE 0x1C
+#define OMAP_ST_REG_SGAINCR 0x24
+#define OMAP_ST_REG_SFIRCR 0x28
+#define OMAP_ST_REG_SSELCR 0x2C
+
+/************************** McBSP SPCR1 bit definitions ***********************/
+#define RRST BIT(0)
+#define RRDY BIT(1)
+#define RFULL BIT(2)
+#define RSYNC_ERR BIT(3)
+#define RINTM(value) (((value) & 0x3) << 4) /* bits 4:5 */
+#define ABIS BIT(6)
+#define DXENA BIT(7)
+#define CLKSTP(value) (((value) & 0x3) << 11) /* bits 11:12 */
+#define RJUST(value) (((value) & 0x3) << 13) /* bits 13:14 */
+#define ALB BIT(15)
+#define DLB BIT(15)
+
+/************************** McBSP SPCR2 bit definitions ***********************/
+#define XRST BIT(0)
+#define XRDY BIT(1)
+#define XEMPTY BIT(2)
+#define XSYNC_ERR BIT(3)
+#define XINTM(value) (((value) & 0x3) << 4) /* bits 4:5 */
+#define GRST BIT(6)
+#define FRST BIT(7)
+#define SOFT BIT(8)
+#define FREE BIT(9)
+
+/************************** McBSP PCR bit definitions *************************/
+#define CLKRP BIT(0)
+#define CLKXP BIT(1)
+#define FSRP BIT(2)
+#define FSXP BIT(3)
+#define DR_STAT BIT(4)
+#define DX_STAT BIT(5)
+#define CLKS_STAT BIT(6)
+#define SCLKME BIT(7)
+#define CLKRM BIT(8)
+#define CLKXM BIT(9)
+#define FSRM BIT(10)
+#define FSXM BIT(11)
+#define RIOEN BIT(12)
+#define XIOEN BIT(13)
+#define IDLE_EN BIT(14)
+
+/************************** McBSP RCR1 bit definitions ************************/
+#define RWDLEN1(value) (((value) & 0x7) << 5) /* Bits 5:7 */
+#define RFRLEN1(value) (((value) & 0x7f) << 8) /* Bits 8:14 */
+
+/************************** McBSP XCR1 bit definitions ************************/
+#define XWDLEN1(value) (((value) & 0x7) << 5) /* Bits 5:7 */
+#define XFRLEN1(value) (((value) & 0x7f) << 8) /* Bits 8:14 */
+
+/*************************** McBSP RCR2 bit definitions ***********************/
+#define RDATDLY(value) ((value) & 0x3) /* Bits 0:1 */
+#define RFIG BIT(2)
+#define RCOMPAND(value) (((value) & 0x3) << 3) /* Bits 3:4 */
+#define RWDLEN2(value) (((value) & 0x7) << 5) /* Bits 5:7 */
+#define RFRLEN2(value) (((value) & 0x7f) << 8) /* Bits 8:14 */
+#define RPHASE BIT(15)
+
+/*************************** McBSP XCR2 bit definitions ***********************/
+#define XDATDLY(value) ((value) & 0x3) /* Bits 0:1 */
+#define XFIG BIT(2)
+#define XCOMPAND(value) (((value) & 0x3) << 3) /* Bits 3:4 */
+#define XWDLEN2(value) (((value) & 0x7) << 5) /* Bits 5:7 */
+#define XFRLEN2(value) (((value) & 0x7f) << 8) /* Bits 8:14 */
+#define XPHASE BIT(15)
+
+/************************* McBSP SRGR1 bit definitions ************************/
+#define CLKGDV(value) ((value) & 0x7f) /* Bits 0:7 */
+#define FWID(value) (((value) & 0xff) << 8) /* Bits 8:15 */
+
+/************************* McBSP SRGR2 bit definitions ************************/
+#define FPER(value) ((value) & 0x0fff) /* Bits 0:11 */
+#define FSGM BIT(12)
+#define CLKSM BIT(13)
+#define CLKSP BIT(14)
+#define GSYNC BIT(15)
+
+/************************* McBSP MCR1 bit definitions *************************/
+#define RMCM BIT(0)
+#define RCBLK(value) (((value) & 0x7) << 2) /* Bits 2:4 */
+#define RPABLK(value) (((value) & 0x3) << 5) /* Bits 5:6 */
+#define RPBBLK(value) (((value) & 0x3) << 7) /* Bits 7:8 */
+
+/************************* McBSP MCR2 bit definitions *************************/
+#define XMCM(value) ((value) & 0x3) /* Bits 0:1 */
+#define XCBLK(value) (((value) & 0x7) << 2) /* Bits 2:4 */
+#define XPABLK(value) (((value) & 0x3) << 5) /* Bits 5:6 */
+#define XPBBLK(value) (((value) & 0x3) << 7) /* Bits 7:8 */
+
+/*********************** McBSP XCCR bit definitions *************************/
+#define XDISABLE BIT(0)
+#define XDMAEN BIT(3)
+#define DILB BIT(5)
+#define XFULL_CYCLE BIT(11)
+#define DXENDLY(value) (((value) & 0x3) << 12) /* Bits 12:13 */
+#define PPCONNECT BIT(14)
+#define EXTCLKGATE BIT(15)
+
+/********************** McBSP RCCR bit definitions *************************/
+#define RDISABLE BIT(0)
+#define RDMAEN BIT(3)
+#define RFULL_CYCLE BIT(11)
+
+/********************** McBSP SYSCONFIG bit definitions ********************/
+#define SOFTRST BIT(1)
+#define ENAWAKEUP BIT(2)
+#define SIDLEMODE(value) (((value) & 0x3) << 3)
+#define CLOCKACTIVITY(value) (((value) & 0x3) << 8)
+
+/********************** McBSP SSELCR bit definitions ***********************/
+#define SIDETONEEN BIT(10)
+
+/********************** McBSP Sidetone SYSCONFIG bit definitions ***********/
+#define ST_AUTOIDLE BIT(0)
+
+/********************** McBSP Sidetone SGAINCR bit definitions *************/
+#define ST_CH0GAIN(value) ((value) & 0xffff) /* Bits 0:15 */
+#define ST_CH1GAIN(value) (((value) & 0xffff) << 16) /* Bits 16:31 */
+
+/********************** McBSP Sidetone SFIRCR bit definitions **************/
+#define ST_FIRCOEFF(value) ((value) & 0xffff) /* Bits 0:15 */
+
+/********************** McBSP Sidetone SSELCR bit definitions **************/
+#define ST_SIDETONEEN BIT(0)
+#define ST_COEFFWREN BIT(1)
+#define ST_COEFFWRDONE BIT(2)
+
+/********************** McBSP DMA operating modes **************************/
+#define MCBSP_DMA_MODE_ELEMENT 0
+#define MCBSP_DMA_MODE_THRESHOLD 1
+#define MCBSP_DMA_MODE_FRAME 2
+
+/********************** McBSP WAKEUPEN bit definitions *********************/
+#define RSYNCERREN BIT(0)
+#define RFSREN BIT(1)
+#define REOFEN BIT(2)
+#define RRDYEN BIT(3)
+#define XSYNCERREN BIT(7)
+#define XFSXEN BIT(8)
+#define XEOFEN BIT(9)
+#define XRDYEN BIT(10)
+#define XEMPTYEOFEN BIT(14)
+
+/* Clock signal muxing options */
+#define CLKR_SRC_CLKR 0 /* CLKR signal is from the CLKR pin */
+#define CLKR_SRC_CLKX 1 /* CLKR signal is from the CLKX pin */
+#define FSR_SRC_FSR 2 /* FSR signal is from the FSR pin */
+#define FSR_SRC_FSX 3 /* FSR signal is from the FSX pin */
+
+/* McBSP functional clock sources */
+#define MCBSP_CLKS_PRCM_SRC 0
+#define MCBSP_CLKS_PAD_SRC 1
+
+/* we don't do multichannel for now */
+struct omap_mcbsp_reg_cfg {
+ u16 spcr2;
+ u16 spcr1;
+ u16 rcr2;
+ u16 rcr1;
+ u16 xcr2;
+ u16 xcr1;
+ u16 srgr2;
+ u16 srgr1;
+ u16 mcr2;
+ u16 mcr1;
+ u16 pcr0;
+ u16 rcerc;
+ u16 rcerd;
+ u16 xcerc;
+ u16 xcerd;
+ u16 rcere;
+ u16 rcerf;
+ u16 xcere;
+ u16 xcerf;
+ u16 rcerg;
+ u16 rcerh;
+ u16 xcerg;
+ u16 xcerh;
+ u16 xccr;
+ u16 rccr;
+};
+
+struct omap_mcbsp_st_data {
+ void __iomem *io_base_st;
+ bool running;
+ bool enabled;
+ s16 taps[128]; /* Sidetone filter coefficients */
+ int nr_taps; /* Number of filter coefficients in use */
+ s16 ch0gain;
+ s16 ch1gain;
+};
+
+struct omap_mcbsp {
+ struct device *dev;
+ struct clk *fclk;
+ spinlock_t lock;
+ unsigned long phys_base;
+ unsigned long phys_dma_base;
+ void __iomem *io_base;
+ u8 id;
+ /*
+ * Flags indicating is the bus already activated and configured by
+ * another substream
+ */
+ int active;
+ int configured;
+ u8 free;
+
+ int rx_irq;
+ int tx_irq;
+
+ /* Protect the field .free, while checking if the mcbsp is in use */
+ struct omap_mcbsp_platform_data *pdata;
+ struct omap_mcbsp_st_data *st_data;
+ struct omap_mcbsp_reg_cfg cfg_regs;
+ struct omap_pcm_dma_data dma_data[2];
+ int dma_op_mode;
+ u16 max_tx_thres;
+ u16 max_rx_thres;
+ void *reg_cache;
+ int reg_cache_size;
+
+ unsigned int fmt;
+ unsigned int in_freq;
+ int clk_div;
+ int wlen;
+};
+
+void omap_mcbsp_config(struct omap_mcbsp *mcbsp,
+ const struct omap_mcbsp_reg_cfg *config);
+void omap_mcbsp_set_tx_threshold(struct omap_mcbsp *mcbsp, u16 threshold);
+void omap_mcbsp_set_rx_threshold(struct omap_mcbsp *mcbsp, u16 threshold);
+u16 omap_mcbsp_get_tx_delay(struct omap_mcbsp *mcbsp);
+u16 omap_mcbsp_get_rx_delay(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_get_dma_op_mode(struct omap_mcbsp *mcbsp);
+int omap_mcbsp_request(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_free(struct omap_mcbsp *mcbsp);
+void omap_mcbsp_start(struct omap_mcbsp *mcbsp, int tx, int rx);
+void omap_mcbsp_stop(struct omap_mcbsp *mcbsp, int tx, int rx);
+
+/* McBSP functional clock source changing function */
+int omap2_mcbsp_set_clks_src(struct omap_mcbsp *mcbsp, u8 fck_src_id);
+
+/* McBSP signal muxing API */
+int omap_mcbsp_6pin_src_mux(struct omap_mcbsp *mcbsp, u8 mux);
+
+/* Sidetone specific API */
+int omap_st_set_chgain(struct omap_mcbsp *mcbsp, int channel, s16 chgain);
+int omap_st_get_chgain(struct omap_mcbsp *mcbsp, int channel, s16 *chgain);
+int omap_st_enable(struct omap_mcbsp *mcbsp);
+int omap_st_disable(struct omap_mcbsp *mcbsp);
+int omap_st_is_enabled(struct omap_mcbsp *mcbsp);
+
+int __devinit omap_mcbsp_init(struct platform_device *pdev);
+void __devexit omap_mcbsp_sysfs_remove(struct omap_mcbsp *mcbsp);
+
+#endif /* __ASOC_MCBSP_H */
diff --git a/sound/soc/omap/mcpdm.c b/sound/soc/omap/mcpdm.c
deleted file mode 100644
index 928f03707451..000000000000
--- a/sound/soc/omap/mcpdm.c
+++ /dev/null
@@ -1,470 +0,0 @@
-/*
- * mcpdm.c -- McPDM interface driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
- * Copyright (C) 2009 - Texas Instruments, Inc.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/platform_device.h>
-#include <linux/wait.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-
-#include "mcpdm.h"
-
-static struct omap_mcpdm *mcpdm;
-
-static inline void omap_mcpdm_write(u16 reg, u32 val)
-{
- __raw_writel(val, mcpdm->io_base + reg);
-}
-
-static inline int omap_mcpdm_read(u16 reg)
-{
- return __raw_readl(mcpdm->io_base + reg);
-}
-
-static void omap_mcpdm_reg_dump(void)
-{
- dev_dbg(mcpdm->dev, "***********************\n");
- dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQSTATUS_RAW));
- dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQSTATUS));
- dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQENABLE_SET));
- dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQENABLE_CLR));
- dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
- omap_mcpdm_read(MCPDM_IRQWAKE_EN));
- dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DMAENABLE_SET));
- dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DMAENABLE_CLR));
- dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DMAWAKEEN));
- dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n",
- omap_mcpdm_read(MCPDM_CTRL));
- dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DN_DATA));
- dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
- omap_mcpdm_read(MCPDM_UP_DATA));
- dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
- omap_mcpdm_read(MCPDM_FIFO_CTRL_DN));
- dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n",
- omap_mcpdm_read(MCPDM_FIFO_CTRL_UP));
- dev_dbg(mcpdm->dev, "DN_OFFSET: 0x%04x\n",
- omap_mcpdm_read(MCPDM_DN_OFFSET));
- dev_dbg(mcpdm->dev, "***********************\n");
-}
-
-/*
- * Takes the McPDM module in and out of reset state.
- * Uplink and downlink can be reset individually.
- */
-static void omap_mcpdm_reset_capture(int reset)
-{
- int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
- if (reset)
- ctrl |= SW_UP_RST;
- else
- ctrl &= ~SW_UP_RST;
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-static void omap_mcpdm_reset_playback(int reset)
-{
- int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
- if (reset)
- ctrl |= SW_DN_RST;
- else
- ctrl &= ~SW_DN_RST;
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Enables the transfer through the PDM interface to/from the Phoenix
- * codec by enabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_start(int stream)
-{
- int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
- if (stream)
- ctrl |= mcpdm->up_channels;
- else
- ctrl |= mcpdm->dn_channels;
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Disables the transfer through the PDM interface to/from the Phoenix
- * codec by disabling the corresponding UP or DN channels.
- */
-void omap_mcpdm_stop(int stream)
-{
- int ctrl = omap_mcpdm_read(MCPDM_CTRL);
-
- if (stream)
- ctrl &= ~mcpdm->up_channels;
- else
- ctrl &= ~mcpdm->dn_channels;
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-}
-
-/*
- * Configures McPDM uplink for audio recording.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink)
-{
- int irq_mask = 0;
- int ctrl;
-
- if (!uplink)
- return -EINVAL;
-
- mcpdm->uplink = uplink;
-
- /* Enable irq request generation */
- irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
- omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
- /* Configure uplink threshold */
- if (uplink->threshold > UP_THRES_MAX)
- uplink->threshold = UP_THRES_MAX;
-
- omap_mcpdm_write(MCPDM_FIFO_CTRL_UP, uplink->threshold);
-
- /* Configure DMA controller */
- omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_UP_ENABLE);
-
- /* Set pdm out format */
- ctrl = omap_mcpdm_read(MCPDM_CTRL);
- ctrl &= ~PDMOUTFORMAT;
- ctrl |= uplink->format & PDMOUTFORMAT;
-
- /* Uplink channels */
- mcpdm->up_channels = uplink->channels & (PDM_UP_MASK | PDM_STATUS_MASK);
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
- return 0;
-}
-
-/*
- * Configures McPDM downlink for audio playback.
- * This function should be called before omap_mcpdm_start.
- */
-int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink)
-{
- int irq_mask = 0;
- int ctrl;
-
- if (!downlink)
- return -EINVAL;
-
- mcpdm->downlink = downlink;
-
- /* Enable irq request generation */
- irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
- omap_mcpdm_write(MCPDM_IRQENABLE_SET, irq_mask);
-
- /* Configure uplink threshold */
- if (downlink->threshold > DN_THRES_MAX)
- downlink->threshold = DN_THRES_MAX;
-
- omap_mcpdm_write(MCPDM_FIFO_CTRL_DN, downlink->threshold);
-
- /* Enable DMA request generation */
- omap_mcpdm_write(MCPDM_DMAENABLE_SET, DMA_DN_ENABLE);
-
- /* Set pdm out format */
- ctrl = omap_mcpdm_read(MCPDM_CTRL);
- ctrl &= ~PDMOUTFORMAT;
- ctrl |= downlink->format & PDMOUTFORMAT;
-
- /* Downlink channels */
- mcpdm->dn_channels = downlink->channels & (PDM_DN_MASK | PDM_CMD_MASK);
-
- omap_mcpdm_write(MCPDM_CTRL, ctrl);
-
- return 0;
-}
-
-/*
- * Cleans McPDM uplink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink)
-{
- int irq_mask = 0;
-
- if (!uplink)
- return -EINVAL;
-
- /* Disable irq request generation */
- irq_mask |= uplink->irq_mask & MCPDM_UPLINK_IRQ_MASK;
- omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
- /* Disable DMA request generation */
- omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_UP_ENABLE);
-
- /* Clear Downlink channels */
- mcpdm->up_channels = 0;
-
- mcpdm->uplink = NULL;
-
- return 0;
-}
-
-/*
- * Cleans McPDM downlink configuration.
- * This function should be called when the stream is closed.
- */
-int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink)
-{
- int irq_mask = 0;
-
- if (!downlink)
- return -EINVAL;
-
- /* Disable irq request generation */
- irq_mask |= downlink->irq_mask & MCPDM_DOWNLINK_IRQ_MASK;
- omap_mcpdm_write(MCPDM_IRQENABLE_CLR, irq_mask);
-
- /* Disable DMA request generation */
- omap_mcpdm_write(MCPDM_DMAENABLE_CLR, DMA_DN_ENABLE);
-
- /* clear Downlink channels */
- mcpdm->dn_channels = 0;
-
- mcpdm->downlink = NULL;
-
- return 0;
-}
-
-static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
-{
- struct omap_mcpdm *mcpdm_irq = dev_id;
- int irq_status;
-
- irq_status = omap_mcpdm_read(MCPDM_IRQSTATUS);
-
- /* Acknowledge irq event */
- omap_mcpdm_write(MCPDM_IRQSTATUS, irq_status);
-
- if (irq & MCPDM_DN_IRQ_FULL) {
- dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
- omap_mcpdm_reset_playback(1);
- omap_mcpdm_playback_open(mcpdm_irq->downlink);
- omap_mcpdm_reset_playback(0);
- }
-
- if (irq & MCPDM_DN_IRQ_EMPTY) {
- dev_err(mcpdm_irq->dev, "DN FIFO error %x\n", irq_status);
- omap_mcpdm_reset_playback(1);
- omap_mcpdm_playback_open(mcpdm_irq->downlink);
- omap_mcpdm_reset_playback(0);
- }
-
- if (irq & MCPDM_DN_IRQ) {
- dev_dbg(mcpdm_irq->dev, "DN write request\n");
- }
-
- if (irq & MCPDM_UP_IRQ_FULL) {
- dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
- omap_mcpdm_reset_capture(1);
- omap_mcpdm_capture_open(mcpdm_irq->uplink);
- omap_mcpdm_reset_capture(0);
- }
-
- if (irq & MCPDM_UP_IRQ_EMPTY) {
- dev_err(mcpdm_irq->dev, "UP FIFO error %x\n", irq_status);
- omap_mcpdm_reset_capture(1);
- omap_mcpdm_capture_open(mcpdm_irq->uplink);
- omap_mcpdm_reset_capture(0);
- }
-
- if (irq & MCPDM_UP_IRQ) {
- dev_dbg(mcpdm_irq->dev, "UP write request\n");
- }
-
- return IRQ_HANDLED;
-}
-
-int omap_mcpdm_request(void)
-{
- int ret;
-
- clk_enable(mcpdm->clk);
-
- spin_lock(&mcpdm->lock);
-
- if (!mcpdm->free) {
- dev_err(mcpdm->dev, "McPDM interface is in use\n");
- spin_unlock(&mcpdm->lock);
- ret = -EBUSY;
- goto err;
- }
- mcpdm->free = 0;
-
- spin_unlock(&mcpdm->lock);
-
- /* Disable lines while request is ongoing */
- omap_mcpdm_write(MCPDM_CTRL, 0x00);
-
- ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
- 0, "McPDM", (void *)mcpdm);
- if (ret) {
- dev_err(mcpdm->dev, "Request for McPDM IRQ failed\n");
- goto err;
- }
-
- return 0;
-
-err:
- clk_disable(mcpdm->clk);
- return ret;
-}
-
-void omap_mcpdm_free(void)
-{
- spin_lock(&mcpdm->lock);
- if (mcpdm->free) {
- dev_err(mcpdm->dev, "McPDM interface is already free\n");
- spin_unlock(&mcpdm->lock);
- return;
- }
- mcpdm->free = 1;
- spin_unlock(&mcpdm->lock);
-
- clk_disable(mcpdm->clk);
-
- free_irq(mcpdm->irq, (void *)mcpdm);
-}
-
-/* Enable/disable DC offset cancelation for the analog
- * headset path (PDM channels 1 and 2).
- */
-int omap_mcpdm_set_offset(int offset1, int offset2)
-{
- int offset;
-
- if ((offset1 > DN_OFST_MAX) || (offset2 > DN_OFST_MAX))
- return -EINVAL;
-
- offset = (offset1 << DN_OFST_RX1) | (offset2 << DN_OFST_RX2);
-
- /* offset cancellation for channel 1 */
- if (offset1)
- offset |= DN_OFST_RX1_EN;
- else
- offset &= ~DN_OFST_RX1_EN;
-
- /* offset cancellation for channel 2 */
- if (offset2)
- offset |= DN_OFST_RX2_EN;
- else
- offset &= ~DN_OFST_RX2_EN;
-
- omap_mcpdm_write(MCPDM_DN_OFFSET, offset);
-
- return 0;
-}
-
-int __devinit omap_mcpdm_probe(struct platform_device *pdev)
-{
- struct resource *res;
- int ret = 0;
-
- mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
- if (!mcpdm) {
- ret = -ENOMEM;
- goto exit;
- }
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (res == NULL) {
- dev_err(&pdev->dev, "no resource\n");
- goto err_resource;
- }
-
- spin_lock_init(&mcpdm->lock);
- mcpdm->free = 1;
- mcpdm->io_base = ioremap(res->start, resource_size(res));
- if (!mcpdm->io_base) {
- ret = -ENOMEM;
- goto err_resource;
- }
-
- mcpdm->irq = platform_get_irq(pdev, 0);
-
- mcpdm->clk = clk_get(&pdev->dev, "pdm_ck");
- if (IS_ERR(mcpdm->clk)) {
- ret = PTR_ERR(mcpdm->clk);
- dev_err(&pdev->dev, "unable to get pdm_ck: %d\n", ret);
- goto err_clk;
- }
-
- mcpdm->dev = &pdev->dev;
- platform_set_drvdata(pdev, mcpdm);
-
- return 0;
-
-err_clk:
- iounmap(mcpdm->io_base);
-err_resource:
- kfree(mcpdm);
-exit:
- return ret;
-}
-
-int __devexit omap_mcpdm_remove(struct platform_device *pdev)
-{
- struct omap_mcpdm *mcpdm_ptr = platform_get_drvdata(pdev);
-
- platform_set_drvdata(pdev, NULL);
-
- clk_put(mcpdm_ptr->clk);
-
- iounmap(mcpdm_ptr->io_base);
-
- mcpdm_ptr->clk = NULL;
- mcpdm_ptr->free = 0;
- mcpdm_ptr->dev = NULL;
-
- kfree(mcpdm_ptr);
-
- return 0;
-}
-
diff --git a/sound/soc/omap/mcpdm.h b/sound/soc/omap/mcpdm.h
deleted file mode 100644
index df3e16fb51f3..000000000000
--- a/sound/soc/omap/mcpdm.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * mcpdm.h -- Defines for McPDM driver
- *
- * Author: Jorge Eduardo Candelaria <x0107209@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-/* McPDM registers */
-
-#define MCPDM_REVISION 0x00
-#define MCPDM_SYSCONFIG 0x10
-#define MCPDM_IRQSTATUS_RAW 0x24
-#define MCPDM_IRQSTATUS 0x28
-#define MCPDM_IRQENABLE_SET 0x2C
-#define MCPDM_IRQENABLE_CLR 0x30
-#define MCPDM_IRQWAKE_EN 0x34
-#define MCPDM_DMAENABLE_SET 0x38
-#define MCPDM_DMAENABLE_CLR 0x3C
-#define MCPDM_DMAWAKEEN 0x40
-#define MCPDM_CTRL 0x44
-#define MCPDM_DN_DATA 0x48
-#define MCPDM_UP_DATA 0x4C
-#define MCPDM_FIFO_CTRL_DN 0x50
-#define MCPDM_FIFO_CTRL_UP 0x54
-#define MCPDM_DN_OFFSET 0x58
-
-/*
- * MCPDM_IRQ bit fields
- * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
- */
-
-#define MCPDM_DN_IRQ (1 << 0)
-#define MCPDM_DN_IRQ_EMPTY (1 << 1)
-#define MCPDM_DN_IRQ_ALMST_EMPTY (1 << 2)
-#define MCPDM_DN_IRQ_FULL (1 << 3)
-
-#define MCPDM_UP_IRQ (1 << 8)
-#define MCPDM_UP_IRQ_EMPTY (1 << 9)
-#define MCPDM_UP_IRQ_ALMST_FULL (1 << 10)
-#define MCPDM_UP_IRQ_FULL (1 << 11)
-
-#define MCPDM_DOWNLINK_IRQ_MASK 0x00F
-#define MCPDM_UPLINK_IRQ_MASK 0xF00
-
-/*
- * MCPDM_DMAENABLE bit fields
- */
-
-#define DMA_DN_ENABLE 0x1
-#define DMA_UP_ENABLE 0x2
-
-/*
- * MCPDM_CTRL bit fields
- */
-
-#define PDM_UP1_EN 0x0001
-#define PDM_UP2_EN 0x0002
-#define PDM_UP3_EN 0x0004
-#define PDM_DN1_EN 0x0008
-#define PDM_DN2_EN 0x0010
-#define PDM_DN3_EN 0x0020
-#define PDM_DN4_EN 0x0040
-#define PDM_DN5_EN 0x0080
-#define PDMOUTFORMAT 0x0100
-#define CMD_INT 0x0200
-#define STATUS_INT 0x0400
-#define SW_UP_RST 0x0800
-#define SW_DN_RST 0x1000
-#define PDM_UP_MASK 0x007
-#define PDM_DN_MASK 0x0F8
-#define PDM_CMD_MASK 0x200
-#define PDM_STATUS_MASK 0x400
-
-
-#define PDMOUTFORMAT_LJUST (0 << 8)
-#define PDMOUTFORMAT_RJUST (1 << 8)
-
-/*
- * MCPDM_FIFO_CTRL bit fields
- */
-
-#define UP_THRES_MAX 0xF
-#define DN_THRES_MAX 0xF
-
-/*
- * MCPDM_DN_OFFSET bit fields
- */
-
-#define DN_OFST_RX1_EN 0x0001
-#define DN_OFST_RX2_EN 0x0100
-
-#define DN_OFST_RX1 1
-#define DN_OFST_RX2 9
-#define DN_OFST_MAX 0x1F
-
-#define MCPDM_UPLINK 1
-#define MCPDM_DOWNLINK 2
-
-struct omap_mcpdm_link {
- int irq_mask;
- int threshold;
- int format;
- int channels;
-};
-
-struct omap_mcpdm_platform_data {
- unsigned long phys_base;
- u16 irq;
-};
-
-struct omap_mcpdm {
- struct device *dev;
- unsigned long phys_base;
- void __iomem *io_base;
- u8 free;
- int irq;
-
- spinlock_t lock;
- struct omap_mcpdm_platform_data *pdata;
- struct clk *clk;
- struct omap_mcpdm_link *downlink;
- struct omap_mcpdm_link *uplink;
- struct completion irq_completion;
-
- int dn_channels;
- int up_channels;
-};
-
-extern void omap_mcpdm_start(int stream);
-extern void omap_mcpdm_stop(int stream);
-extern int omap_mcpdm_capture_open(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_open(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_capture_close(struct omap_mcpdm_link *uplink);
-extern int omap_mcpdm_playback_close(struct omap_mcpdm_link *downlink);
-extern int omap_mcpdm_request(void);
-extern void omap_mcpdm_free(void);
-extern int omap_mcpdm_set_offset(int offset1, int offset2);
-int __devinit omap_mcpdm_probe(struct platform_device *pdev);
-int __devexit omap_mcpdm_remove(struct platform_device *pdev);
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 62e292f49313..abac4b690750 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -31,6 +31,7 @@
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include <plat/mcbsp.h>
#include "omap-mcbsp.h"
@@ -54,9 +55,8 @@ static int n810_spk_func;
static int n810_jack_func;
static int n810_dmic_func;
-static void n810_ext_control(struct snd_soc_codec *codec)
+static void n810_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int hp = 0, line1l = 0;
switch (n810_jack_func) {
@@ -101,7 +101,7 @@ static int n810_startup(struct snd_pcm_substream *substream)
snd_pcm_hw_constraint_minmax(runtime,
SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
- n810_ext_control(codec);
+ n810_ext_control(&codec->dapm);
return clk_enable(sys_clkout2);
}
@@ -115,25 +115,8 @@ static int n810_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int err;
- /* Set codec DAI configuration */
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0)
- return err;
-
- /* Set cpu DAI configuration */
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0)
- return err;
-
/* Set the codec system clock for DAC and ADC */
err = snd_soc_dai_set_sysclk(codec_dai, 0, 12000000,
SND_SOC_CLOCK_IN);
@@ -158,13 +141,13 @@ static int n810_get_spk(struct snd_kcontrol *kcontrol,
static int n810_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (n810_spk_func == ucontrol->value.integer.value[0])
return 0;
n810_spk_func = ucontrol->value.integer.value[0];
- n810_ext_control(codec);
+ n810_ext_control(&card->dapm);
return 1;
}
@@ -180,13 +163,13 @@ static int n810_get_jack(struct snd_kcontrol *kcontrol,
static int n810_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (n810_jack_func == ucontrol->value.integer.value[0])
return 0;
n810_jack_func = ucontrol->value.integer.value[0];
- n810_ext_control(codec);
+ n810_ext_control(&card->dapm);
return 1;
}
@@ -202,13 +185,13 @@ static int n810_get_input(struct snd_kcontrol *kcontrol,
static int n810_set_input(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (n810_dmic_func == ucontrol->value.integer.value[0])
return 0;
n810_dmic_func = ucontrol->value.integer.value[0];
- n810_ext_control(codec);
+ n810_ext_control(&card->dapm);
return 1;
}
@@ -274,7 +257,6 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int err;
/* Not connected */
snd_soc_dapm_nc_pin(dapm, "MONO_LOUT");
@@ -286,21 +268,6 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "LINE2L");
snd_soc_dapm_nc_pin(dapm, "LINE2R");
- /* Add N810 specific controls */
- err = snd_soc_add_controls(codec, aic33_n810_controls,
- ARRAY_SIZE(aic33_n810_controls));
- if (err < 0)
- return err;
-
- /* Add N810 specific widgets */
- snd_soc_dapm_new_controls(dapm, aic33_dapm_widgets,
- ARRAY_SIZE(aic33_dapm_widgets));
-
- /* Set up N810 specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -308,10 +275,12 @@ static int n810_aic33_init(struct snd_soc_pcm_runtime *rtd)
static struct snd_soc_dai_link n810_dai = {
.name = "TLV320AIC33",
.stream_name = "AIC33",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.platform_name = "omap-pcm-audio",
.codec_name = "tlv320aic3x-codec.2-0018",
.codec_dai_name = "tlv320aic3x-hifi",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.init = n810_aic33_init,
.ops = &n810_ops,
};
@@ -319,8 +288,16 @@ static struct snd_soc_dai_link n810_dai = {
/* Audio machine driver */
static struct snd_soc_card snd_soc_n810 = {
.name = "N810",
+ .owner = THIS_MODULE,
.dai_link = &n810_dai,
.num_links = 1,
+
+ .controls = aic33_n810_controls,
+ .num_controls = ARRAY_SIZE(aic33_n810_controls),
+ .dapm_widgets = aic33_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(aic33_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
};
static struct platform_device *n810_snd_device;
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c
new file mode 100644
index 000000000000..93bb8eee22b3
--- /dev/null
+++ b/sound/soc/omap/omap-abe-twl6040.c
@@ -0,0 +1,349 @@
+/*
+ * omap-abe-twl6040.c -- SoC audio for TI OMAP based boards with ABE and
+ * twl6040 codec
+ *
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/twl6040.h>
+#include <linux/platform_data/omap-abe-twl6040.h>
+#include <linux/module.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/soc.h>
+#include <sound/jack.h>
+
+#include <asm/mach-types.h>
+#include <plat/hardware.h>
+#include <plat/mux.h>
+
+#include "omap-dmic.h"
+#include "omap-mcpdm.h"
+#include "omap-pcm.h"
+#include "../codecs/twl6040.h"
+
+static int omap_abe_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = codec->card;
+ struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
+ int clk_id, freq;
+ int ret;
+
+ clk_id = twl6040_get_clk_id(rtd->codec);
+ if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
+ freq = pdata->mclk_freq;
+ else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
+ freq = 32768;
+ else
+ return -EINVAL;
+
+ /* set the codec mclk */
+ ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
+ SND_SOC_CLOCK_IN);
+ if (ret) {
+ printk(KERN_ERR "can't set codec system clock\n");
+ return ret;
+ }
+ return ret;
+}
+
+static struct snd_soc_ops omap_abe_ops = {
+ .hw_params = omap_abe_hw_params,
+};
+
+static int omap_abe_dmic_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ int ret = 0;
+
+ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_SYSCLK_PAD_CLKS,
+ 19200000, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set DMIC cpu system clock\n");
+ return ret;
+ }
+ ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_DMIC_ABE_DMIC_CLK, 2400000,
+ SND_SOC_CLOCK_OUT);
+ if (ret < 0) {
+ printk(KERN_ERR "can't set DMIC output clock\n");
+ return ret;
+ }
+ return 0;
+}
+
+static struct snd_soc_ops omap_abe_dmic_ops = {
+ .hw_params = omap_abe_dmic_hw_params,
+};
+
+/* Headset jack */
+static struct snd_soc_jack hs_jack;
+
+/*Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin hs_jack_pins[] = {
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
+ {
+ .pin = "Headset Stereophone",
+ .mask = SND_JACK_HEADPHONE,
+ },
+};
+
+/* SDP4430 machine DAPM */
+static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
+ /* Outputs */
+ SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+ SND_SOC_DAPM_SPK("Earphone Spk", NULL),
+ SND_SOC_DAPM_SPK("Ext Spk", NULL),
+ SND_SOC_DAPM_LINE("Line Out", NULL),
+ SND_SOC_DAPM_SPK("Vibrator", NULL),
+
+ /* Inputs */
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Main Handset Mic", NULL),
+ SND_SOC_DAPM_MIC("Sub Handset Mic", NULL),
+ SND_SOC_DAPM_LINE("Line In", NULL),
+};
+
+static const struct snd_soc_dapm_route audio_map[] = {
+ /* Routings for outputs */
+ {"Headset Stereophone", NULL, "HSOL"},
+ {"Headset Stereophone", NULL, "HSOR"},
+
+ {"Earphone Spk", NULL, "EP"},
+
+ {"Ext Spk", NULL, "HFL"},
+ {"Ext Spk", NULL, "HFR"},
+
+ {"Line Out", NULL, "AUXL"},
+ {"Line Out", NULL, "AUXR"},
+
+ {"Vibrator", NULL, "VIBRAL"},
+ {"Vibrator", NULL, "VIBRAR"},
+
+ /* Routings for inputs */
+ {"HSMIC", NULL, "Headset Mic"},
+ {"Headset Mic", NULL, "Headset Mic Bias"},
+
+ {"MAINMIC", NULL, "Main Handset Mic"},
+ {"Main Handset Mic", NULL, "Main Mic Bias"},
+
+ {"SUBMIC", NULL, "Sub Handset Mic"},
+ {"Sub Handset Mic", NULL, "Main Mic Bias"},
+
+ {"AFML", NULL, "Line In"},
+ {"AFMR", NULL, "Line In"},
+};
+
+static inline void twl6040_disconnect_pin(struct snd_soc_dapm_context *dapm,
+ int connected, char *pin)
+{
+ if (!connected)
+ snd_soc_dapm_disable_pin(dapm, pin);
+}
+
+static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = codec->card;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct omap_abe_twl6040_data *pdata = dev_get_platdata(card->dev);
+ int hs_trim;
+ int ret = 0;
+
+ /* Disable not connected paths if not used */
+ twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone");
+ twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk");
+ twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk");
+ twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out");
+ twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator");
+ twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic");
+ twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic");
+ twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic");
+ twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In");
+
+ /*
+ * Configure McPDM offset cancellation based on the HSOTRIM value from
+ * twl6040.
+ */
+ hs_trim = twl6040_get_trim_value(codec, TWL6040_TRIM_HSOTRIM);
+ omap_mcpdm_configure_dn_offsets(rtd, TWL6040_HSF_TRIM_LEFT(hs_trim),
+ TWL6040_HSF_TRIM_RIGHT(hs_trim));
+
+ /* Headset jack detection only if it is supported */
+ if (pdata->jack_detection) {
+ ret = snd_soc_jack_new(codec, "Headset Jack",
+ SND_JACK_HEADSET, &hs_jack);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
+ hs_jack_pins);
+ twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
+ }
+
+ return ret;
+}
+
+static const struct snd_soc_dapm_widget dmic_dapm_widgets[] = {
+ SND_SOC_DAPM_MIC("Digital Mic", NULL),
+};
+
+static const struct snd_soc_dapm_route dmic_audio_map[] = {
+ {"DMic", NULL, "Digital Mic"},
+ {"Digital Mic", NULL, "Digital Mic1 Bias"},
+};
+
+static int omap_abe_dmic_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ int ret;
+
+ ret = snd_soc_dapm_new_controls(dapm, dmic_dapm_widgets,
+ ARRAY_SIZE(dmic_dapm_widgets));
+ if (ret)
+ return ret;
+
+ return snd_soc_dapm_add_routes(dapm, dmic_audio_map,
+ ARRAY_SIZE(dmic_audio_map));
+}
+
+/* Digital audio interface glue - connects codec <--> CPU */
+static struct snd_soc_dai_link twl6040_dmic_dai[] = {
+ {
+ .name = "TWL6040",
+ .stream_name = "TWL6040",
+ .cpu_dai_name = "omap-mcpdm",
+ .codec_dai_name = "twl6040-legacy",
+ .platform_name = "omap-pcm-audio",
+ .codec_name = "twl6040-codec",
+ .init = omap_abe_twl6040_init,
+ .ops = &omap_abe_ops,
+ },
+ {
+ .name = "DMIC",
+ .stream_name = "DMIC Capture",
+ .cpu_dai_name = "omap-dmic",
+ .codec_dai_name = "dmic-hifi",
+ .platform_name = "omap-pcm-audio",
+ .codec_name = "dmic-codec",
+ .init = omap_abe_dmic_init,
+ .ops = &omap_abe_dmic_ops,
+ },
+};
+
+static struct snd_soc_dai_link twl6040_only_dai[] = {
+ {
+ .name = "TWL6040",
+ .stream_name = "TWL6040",
+ .cpu_dai_name = "omap-mcpdm",
+ .codec_dai_name = "twl6040-legacy",
+ .platform_name = "omap-pcm-audio",
+ .codec_name = "twl6040-codec",
+ .init = omap_abe_twl6040_init,
+ .ops = &omap_abe_ops,
+ },
+};
+
+/* Audio machine driver */
+static struct snd_soc_card omap_abe_card = {
+ .owner = THIS_MODULE,
+
+ .dapm_widgets = twl6040_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(twl6040_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
+static __devinit int omap_abe_probe(struct platform_device *pdev)
+{
+ struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev);
+ struct snd_soc_card *card = &omap_abe_card;
+ int ret;
+
+ card->dev = &pdev->dev;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "Missing pdata\n");
+ return -ENODEV;
+ }
+
+ if (pdata->card_name) {
+ card->name = pdata->card_name;
+ } else {
+ dev_err(&pdev->dev, "Card name is not provided\n");
+ return -ENODEV;
+ }
+
+ if (!pdata->mclk_freq) {
+ dev_err(&pdev->dev, "MCLK frequency missing\n");
+ return -ENODEV;
+ }
+
+ if (pdata->has_dmic) {
+ card->dai_link = twl6040_dmic_dai;
+ card->num_links = ARRAY_SIZE(twl6040_dmic_dai);
+ } else {
+ card->dai_link = twl6040_only_dai;
+ card->num_links = ARRAY_SIZE(twl6040_only_dai);
+ }
+
+ ret = snd_soc_register_card(card);
+ if (ret)
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+
+ return ret;
+}
+
+static int __devexit omap_abe_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static struct platform_driver omap_abe_driver = {
+ .driver = {
+ .name = "omap-abe-twl6040",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = omap_abe_probe,
+ .remove = __devexit_p(omap_abe_remove),
+};
+
+module_platform_driver(omap_abe_driver);
+
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
+MODULE_DESCRIPTION("ALSA SoC for OMAP boards with ABE and twl6040 codec");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:omap-abe-twl6040");
diff --git a/sound/soc/omap/omap-dmic.c b/sound/soc/omap/omap-dmic.c
new file mode 100644
index 000000000000..4dcb5a7e40e8
--- /dev/null
+++ b/sound/soc/omap/omap-dmic.c
@@ -0,0 +1,545 @@
+/*
+ * omap-dmic.c -- OMAP ASoC DMIC DAI driver
+ *
+ * Copyright (C) 2010 - 2011 Texas Instruments
+ *
+ * Author: David Lambert <dlambert@ti.com>
+ * Misael Lopez Cruz <misael.lopez@ti.com>
+ * Liam Girdwood <lrg@ti.com>
+ * Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+#include <plat/dma.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "omap-pcm.h"
+#include "omap-dmic.h"
+
+struct omap_dmic {
+ struct device *dev;
+ void __iomem *io_base;
+ struct clk *fclk;
+ int fclk_freq;
+ int out_freq;
+ int clk_div;
+ int sysclk;
+ int threshold;
+ u32 ch_enabled;
+ bool active;
+ struct mutex mutex;
+};
+
+/*
+ * Stream DMA parameters
+ */
+static struct omap_pcm_dma_data omap_dmic_dai_dma_params = {
+ .name = "DMIC capture",
+ .data_type = OMAP_DMA_DATA_TYPE_S32,
+ .sync_mode = OMAP_DMA_SYNC_PACKET,
+};
+
+static inline void omap_dmic_write(struct omap_dmic *dmic, u16 reg, u32 val)
+{
+ __raw_writel(val, dmic->io_base + reg);
+}
+
+static inline int omap_dmic_read(struct omap_dmic *dmic, u16 reg)
+{
+ return __raw_readl(dmic->io_base + reg);
+}
+
+static inline void omap_dmic_start(struct omap_dmic *dmic)
+{
+ u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+
+ /* Configure DMA controller */
+ omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_SET_REG,
+ OMAP_DMIC_DMA_ENABLE);
+
+ omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl | dmic->ch_enabled);
+}
+
+static inline void omap_dmic_stop(struct omap_dmic *dmic)
+{
+ u32 ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+ omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
+ ctrl & ~OMAP_DMIC_UP_ENABLE_MASK);
+
+ /* Disable DMA request generation */
+ omap_dmic_write(dmic, OMAP_DMIC_DMAENABLE_CLR_REG,
+ OMAP_DMIC_DMA_ENABLE);
+
+}
+
+static inline int dmic_is_enabled(struct omap_dmic *dmic)
+{
+ return omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG) &
+ OMAP_DMIC_UP_ENABLE_MASK;
+}
+
+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 (!dai->active)
+ dmic->active = 1;
+ else
+ ret = -EBUSY;
+
+ mutex_unlock(&dmic->mutex);
+
+ return ret;
+}
+
+static void omap_dmic_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+ mutex_lock(&dmic->mutex);
+
+ if (!dai->active)
+ dmic->active = 0;
+
+ mutex_unlock(&dmic->mutex);
+}
+
+static int omap_dmic_select_divider(struct omap_dmic *dmic, int sample_rate)
+{
+ int divider = -EINVAL;
+
+ /*
+ * 192KHz rate is only supported with 19.2MHz/3.84MHz clock
+ * configuration.
+ */
+ if (sample_rate == 192000) {
+ if (dmic->fclk_freq == 19200000 && dmic->out_freq == 3840000)
+ divider = 0x6; /* Divider: 5 (192KHz sampling rate) */
+ else
+ dev_err(dmic->dev,
+ "invalid clock configuration for 192KHz\n");
+
+ return divider;
+ }
+
+ switch (dmic->out_freq) {
+ case 1536000:
+ if (dmic->fclk_freq != 24576000)
+ goto div_err;
+ divider = 0x4; /* Divider: 16 */
+ break;
+ case 2400000:
+ switch (dmic->fclk_freq) {
+ case 12000000:
+ divider = 0x5; /* Divider: 5 */
+ break;
+ case 19200000:
+ divider = 0x0; /* Divider: 8 */
+ break;
+ case 24000000:
+ divider = 0x2; /* Divider: 10 */
+ break;
+ default:
+ goto div_err;
+ }
+ break;
+ case 3072000:
+ if (dmic->fclk_freq != 24576000)
+ goto div_err;
+ divider = 0x3; /* Divider: 8 */
+ break;
+ case 3840000:
+ if (dmic->fclk_freq != 19200000)
+ goto div_err;
+ divider = 0x1; /* Divider: 5 (96KHz sampling rate) */
+ break;
+ default:
+ dev_err(dmic->dev, "invalid out frequency: %dHz\n",
+ dmic->out_freq);
+ break;
+ }
+
+ return divider;
+
+div_err:
+ dev_err(dmic->dev, "invalid out frequency %dHz for %dHz input\n",
+ dmic->out_freq, dmic->fclk_freq);
+ return -EINVAL;
+}
+
+static int omap_dmic_dai_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params,
+ struct snd_soc_dai *dai)
+{
+ struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+ int channels;
+
+ dmic->clk_div = omap_dmic_select_divider(dmic, params_rate(params));
+ if (dmic->clk_div < 0) {
+ dev_err(dmic->dev, "no valid divider for %dHz from %dHz\n",
+ dmic->out_freq, dmic->fclk_freq);
+ return -EINVAL;
+ }
+
+ dmic->ch_enabled = 0;
+ channels = params_channels(params);
+ switch (channels) {
+ case 6:
+ dmic->ch_enabled |= OMAP_DMIC_UP3_ENABLE;
+ case 4:
+ dmic->ch_enabled |= OMAP_DMIC_UP2_ENABLE;
+ case 2:
+ dmic->ch_enabled |= OMAP_DMIC_UP1_ENABLE;
+ break;
+ default:
+ dev_err(dmic->dev, "invalid number of legacy channels\n");
+ return -EINVAL;
+ }
+
+ /* packet size is threshold * channels */
+ omap_dmic_dai_dma_params.packet_size = dmic->threshold * channels;
+ snd_soc_dai_set_dma_data(dai, substream, &omap_dmic_dai_dma_params);
+
+ return 0;
+}
+
+static int omap_dmic_dai_prepare(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+ u32 ctrl;
+
+ /* Configure uplink threshold */
+ omap_dmic_write(dmic, OMAP_DMIC_FIFO_CTRL_REG, dmic->threshold);
+
+ ctrl = omap_dmic_read(dmic, OMAP_DMIC_CTRL_REG);
+
+ /* Set dmic out format */
+ ctrl &= ~(OMAP_DMIC_FORMAT | OMAP_DMIC_POLAR_MASK);
+ ctrl |= (OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
+ OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
+
+ /* Configure dmic clock divider */
+ ctrl &= ~OMAP_DMIC_CLK_DIV_MASK;
+ ctrl |= OMAP_DMIC_CLK_DIV(dmic->clk_div);
+
+ omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, ctrl);
+
+ omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG,
+ ctrl | OMAP_DMICOUTFORMAT_LJUST | OMAP_DMIC_POLAR1 |
+ OMAP_DMIC_POLAR2 | OMAP_DMIC_POLAR3);
+
+ return 0;
+}
+
+static int omap_dmic_dai_trigger(struct snd_pcm_substream *substream,
+ int cmd, struct snd_soc_dai *dai)
+{
+ struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ omap_dmic_start(dmic);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ omap_dmic_stop(dmic);
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int omap_dmic_select_fclk(struct omap_dmic *dmic, int clk_id,
+ unsigned int freq)
+{
+ struct clk *parent_clk;
+ char *parent_clk_name;
+ int ret = 0;
+
+ switch (freq) {
+ case 12000000:
+ case 19200000:
+ case 24000000:
+ case 24576000:
+ break;
+ default:
+ dev_err(dmic->dev, "invalid input frequency: %dHz\n", freq);
+ dmic->fclk_freq = 0;
+ return -EINVAL;
+ }
+
+ if (dmic->sysclk == clk_id) {
+ dmic->fclk_freq = freq;
+ return 0;
+ }
+
+ /* re-parent not allowed if a stream is ongoing */
+ if (dmic->active && dmic_is_enabled(dmic)) {
+ dev_err(dmic->dev, "can't re-parent when DMIC active\n");
+ return -EBUSY;
+ }
+
+ switch (clk_id) {
+ case OMAP_DMIC_SYSCLK_PAD_CLKS:
+ parent_clk_name = "pad_clks_ck";
+ break;
+ case OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS:
+ parent_clk_name = "slimbus_clk";
+ break;
+ case OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS:
+ parent_clk_name = "dmic_sync_mux_ck";
+ break;
+ default:
+ dev_err(dmic->dev, "fclk clk_id (%d) not supported\n", clk_id);
+ return -EINVAL;
+ }
+
+ parent_clk = clk_get(dmic->dev, parent_clk_name);
+ if (IS_ERR(parent_clk)) {
+ dev_err(dmic->dev, "can't get %s\n", parent_clk_name);
+ return -ENODEV;
+ }
+
+ mutex_lock(&dmic->mutex);
+ if (dmic->active) {
+ /* disable clock while reparenting */
+ pm_runtime_put_sync(dmic->dev);
+ ret = clk_set_parent(dmic->fclk, parent_clk);
+ pm_runtime_get_sync(dmic->dev);
+ } else {
+ ret = clk_set_parent(dmic->fclk, parent_clk);
+ }
+ mutex_unlock(&dmic->mutex);
+
+ if (ret < 0) {
+ dev_err(dmic->dev, "re-parent failed\n");
+ goto err_busy;
+ }
+
+ dmic->sysclk = clk_id;
+ dmic->fclk_freq = freq;
+
+err_busy:
+ clk_put(parent_clk);
+
+ return ret;
+}
+
+static int omap_dmic_select_outclk(struct omap_dmic *dmic, int clk_id,
+ unsigned int freq)
+{
+ int ret = 0;
+
+ if (clk_id != OMAP_DMIC_ABE_DMIC_CLK) {
+ dev_err(dmic->dev, "output clk_id (%d) not supported\n",
+ clk_id);
+ return -EINVAL;
+ }
+
+ switch (freq) {
+ case 1536000:
+ case 2400000:
+ case 3072000:
+ case 3840000:
+ dmic->out_freq = freq;
+ break;
+ default:
+ dev_err(dmic->dev, "invalid out frequency: %dHz\n", freq);
+ dmic->out_freq = 0;
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int omap_dmic_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir)
+{
+ struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+ if (dir == SND_SOC_CLOCK_IN)
+ return omap_dmic_select_fclk(dmic, clk_id, freq);
+ else if (dir == SND_SOC_CLOCK_OUT)
+ return omap_dmic_select_outclk(dmic, clk_id, freq);
+
+ dev_err(dmic->dev, "invalid clock direction (%d)\n", dir);
+ return -EINVAL;
+}
+
+static const struct snd_soc_dai_ops omap_dmic_dai_ops = {
+ .startup = omap_dmic_dai_startup,
+ .shutdown = omap_dmic_dai_shutdown,
+ .hw_params = omap_dmic_dai_hw_params,
+ .prepare = omap_dmic_dai_prepare,
+ .trigger = omap_dmic_dai_trigger,
+ .set_sysclk = omap_dmic_set_dai_sysclk,
+};
+
+static int omap_dmic_probe(struct snd_soc_dai *dai)
+{
+ struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+ pm_runtime_enable(dmic->dev);
+
+ /* Disable lines while request is ongoing */
+ pm_runtime_get_sync(dmic->dev);
+ omap_dmic_write(dmic, OMAP_DMIC_CTRL_REG, 0x00);
+ pm_runtime_put_sync(dmic->dev);
+
+ /* Configure DMIC threshold value */
+ dmic->threshold = OMAP_DMIC_THRES_MAX - 3;
+ return 0;
+}
+
+static int omap_dmic_remove(struct snd_soc_dai *dai)
+{
+ struct omap_dmic *dmic = snd_soc_dai_get_drvdata(dai);
+
+ pm_runtime_disable(dmic->dev);
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver omap_dmic_dai = {
+ .name = "omap-dmic",
+ .probe = omap_dmic_probe,
+ .remove = omap_dmic_remove,
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 6,
+ .rates = SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000,
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,
+ .sig_bits = 24,
+ },
+ .ops = &omap_dmic_dai_ops,
+};
+
+static __devinit int asoc_dmic_probe(struct platform_device *pdev)
+{
+ struct omap_dmic *dmic;
+ struct resource *res;
+ int ret;
+
+ dmic = devm_kzalloc(&pdev->dev, sizeof(struct omap_dmic), GFP_KERNEL);
+ if (!dmic)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, dmic);
+ dmic->dev = &pdev->dev;
+ dmic->sysclk = OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS;
+
+ mutex_init(&dmic->mutex);
+
+ dmic->fclk = clk_get(dmic->dev, "dmic_fck");
+ if (IS_ERR(dmic->fclk)) {
+ dev_err(dmic->dev, "cant get dmic_fck\n");
+ return -ENODEV;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
+ if (!res) {
+ dev_err(dmic->dev, "invalid dma memory resource\n");
+ ret = -ENODEV;
+ goto err_put_clk;
+ }
+ omap_dmic_dai_dma_params.port_addr = res->start + OMAP_DMIC_DATA_REG;
+
+ res = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+ if (!res) {
+ dev_err(dmic->dev, "invalid dma resource\n");
+ ret = -ENODEV;
+ goto err_put_clk;
+ }
+ omap_dmic_dai_dma_params.dma_req = res->start;
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+ if (!res) {
+ dev_err(dmic->dev, "invalid memory resource\n");
+ ret = -ENODEV;
+ goto err_put_clk;
+ }
+
+ if (!devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name)) {
+ dev_err(dmic->dev, "memory region already claimed\n");
+ ret = -ENODEV;
+ goto err_put_clk;
+ }
+
+ dmic->io_base = devm_ioremap(&pdev->dev, res->start,
+ resource_size(res));
+ if (!dmic->io_base) {
+ ret = -ENOMEM;
+ goto err_put_clk;
+ }
+
+ ret = snd_soc_register_dai(&pdev->dev, &omap_dmic_dai);
+ if (ret)
+ goto err_put_clk;
+
+ return 0;
+
+err_put_clk:
+ clk_put(dmic->fclk);
+ return ret;
+}
+
+static int __devexit asoc_dmic_remove(struct platform_device *pdev)
+{
+ struct omap_dmic *dmic = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_dai(&pdev->dev);
+ clk_put(dmic->fclk);
+
+ return 0;
+}
+
+static struct platform_driver asoc_dmic_driver = {
+ .driver = {
+ .name = "omap-dmic",
+ .owner = THIS_MODULE,
+ },
+ .probe = asoc_dmic_probe,
+ .remove = __devexit_p(asoc_dmic_remove),
+};
+
+module_platform_driver(asoc_dmic_driver);
+
+MODULE_ALIAS("platform:omap-dmic");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_DESCRIPTION("OMAP DMIC ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-dmic.h b/sound/soc/omap/omap-dmic.h
new file mode 100644
index 000000000000..231e728bff0e
--- /dev/null
+++ b/sound/soc/omap/omap-dmic.h
@@ -0,0 +1,69 @@
+/*
+ * omap-dmic.h -- OMAP Digital Microphone Controller
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _OMAP_DMIC_H
+#define _OMAP_DMIC_H
+
+#define OMAP_DMIC_REVISION_REG 0x00
+#define OMAP_DMIC_SYSCONFIG_REG 0x10
+#define OMAP_DMIC_IRQSTATUS_RAW_REG 0x24
+#define OMAP_DMIC_IRQSTATUS_REG 0x28
+#define OMAP_DMIC_IRQENABLE_SET_REG 0x2C
+#define OMAP_DMIC_IRQENABLE_CLR_REG 0x30
+#define OMAP_DMIC_IRQWAKE_EN_REG 0x34
+#define OMAP_DMIC_DMAENABLE_SET_REG 0x38
+#define OMAP_DMIC_DMAENABLE_CLR_REG 0x3C
+#define OMAP_DMIC_DMAWAKEEN_REG 0x40
+#define OMAP_DMIC_CTRL_REG 0x44
+#define OMAP_DMIC_DATA_REG 0x48
+#define OMAP_DMIC_FIFO_CTRL_REG 0x4C
+#define OMAP_DMIC_FIFO_DMIC1R_DATA_REG 0x50
+#define OMAP_DMIC_FIFO_DMIC1L_DATA_REG 0x54
+#define OMAP_DMIC_FIFO_DMIC2R_DATA_REG 0x58
+#define OMAP_DMIC_FIFO_DMIC2L_DATA_REG 0x5C
+#define OMAP_DMIC_FIFO_DMIC3R_DATA_REG 0x60
+#define OMAP_DMIC_FIFO_DMIC3L_DATA_REG 0x64
+
+/* IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR bit fields */
+#define OMAP_DMIC_IRQ (1 << 0)
+#define OMAP_DMIC_IRQ_FULL (1 << 1)
+#define OMAP_DMIC_IRQ_ALMST_EMPTY (1 << 2)
+#define OMAP_DMIC_IRQ_EMPTY (1 << 3)
+#define OMAP_DMIC_IRQ_MASK 0x07
+
+/* DMIC_DMAENABLE bit fields */
+#define OMAP_DMIC_DMA_ENABLE 0x1
+
+/* DMIC_CTRL bit fields */
+#define OMAP_DMIC_UP1_ENABLE (1 << 0)
+#define OMAP_DMIC_UP2_ENABLE (1 << 1)
+#define OMAP_DMIC_UP3_ENABLE (1 << 2)
+#define OMAP_DMIC_UP_ENABLE_MASK 0x7
+#define OMAP_DMIC_FORMAT (1 << 3)
+#define OMAP_DMIC_POLAR1 (1 << 4)
+#define OMAP_DMIC_POLAR2 (1 << 5)
+#define OMAP_DMIC_POLAR3 (1 << 6)
+#define OMAP_DMIC_POLAR_MASK (0x7 << 4)
+#define OMAP_DMIC_CLK_DIV(x) (((x) & 0x7) << 7)
+#define OMAP_DMIC_CLK_DIV_MASK (0x7 << 7)
+#define OMAP_DMIC_RESET (1 << 10)
+
+#define OMAP_DMICOUTFORMAT_LJUST (0 << 3)
+#define OMAP_DMICOUTFORMAT_RJUST (1 << 3)
+
+/* DMIC_FIFO_CTRL bit fields */
+#define OMAP_DMIC_THRES_MAX 0xF
+
+enum omap_dmic_clk {
+ OMAP_DMIC_SYSCLK_PAD_CLKS, /* PAD_CLKS */
+ OMAP_DMIC_SYSCLK_SLIMBLUS_CLKS, /* SLIMBUS_CLK */
+ OMAP_DMIC_SYSCLK_SYNC_MUX_CLKS, /* DMIC_SYNC_MUX_CLK */
+ OMAP_DMIC_ABE_DMIC_CLK, /* abe_dmic_clk */
+};
+
+#endif
diff --git a/sound/soc/omap/omap-hdmi.c b/sound/soc/omap/omap-hdmi.c
index 36c6eaeffb02..38e0defa7078 100644
--- a/sound/soc/omap/omap-hdmi.c
+++ b/sound/soc/omap/omap-hdmi.c
@@ -83,7 +83,7 @@ static int omap_hdmi_dai_hw_params(struct snd_pcm_substream *substream,
return err;
}
-static struct snd_soc_dai_ops omap_hdmi_dai_ops = {
+static const struct snd_soc_dai_ops omap_hdmi_dai_ops = {
.startup = omap_hdmi_dai_startup,
.hw_params = omap_hdmi_dai_hw_params,
};
@@ -139,17 +139,7 @@ static struct platform_driver hdmi_dai_driver = {
.remove = __devexit_p(omap_hdmi_remove),
};
-static int __init hdmi_dai_init(void)
-{
- return platform_driver_register(&hdmi_dai_driver);
-}
-module_init(hdmi_dai_init);
-
-static void __exit hdmi_dai_exit(void)
-{
- platform_driver_unregister(&hdmi_dai_driver);
-}
-module_exit(hdmi_dai_exit);
+module_platform_driver(hdmi_dai_driver);
MODULE_AUTHOR("Jorge Candelaria <jorge.candelaria@ti.com>");
MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index ebcc2d4d2b18..6912ac7cb625 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -25,6 +25,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/device.h>
+#include <linux/pm_runtime.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -33,6 +34,7 @@
#include <plat/dma.h>
#include <plat/mcbsp.h>
+#include "mcbsp.h"
#include "omap-mcbsp.h"
#include "omap-pcm.h"
@@ -46,42 +48,31 @@
.private_value = (unsigned long) &(struct soc_mixer_control) \
{.min = xmin, .max = xmax} }
-struct omap_mcbsp_data {
- unsigned int bus_id;
- struct omap_mcbsp_reg_cfg regs;
- unsigned int fmt;
- /*
- * Flags indicating is the bus already activated and configured by
- * another substream
- */
- int active;
- int configured;
- unsigned int in_freq;
- int clk_div;
- int wlen;
+enum {
+ OMAP_MCBSP_WORD_8 = 0,
+ OMAP_MCBSP_WORD_12,
+ OMAP_MCBSP_WORD_16,
+ OMAP_MCBSP_WORD_20,
+ OMAP_MCBSP_WORD_24,
+ OMAP_MCBSP_WORD_32,
};
-static struct omap_mcbsp_data mcbsp_data[NUM_LINKS];
-
/*
* Stream DMA parameters. DMA request line and port address are set runtime
* since they are different between OMAP1 and later OMAPs
*/
-static struct omap_pcm_dma_data omap_mcbsp_dai_dma_params[NUM_LINKS][2];
-
static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
struct omap_pcm_dma_data *dma_data;
- int dma_op_mode = omap_mcbsp_get_dma_op_mode(mcbsp_data->bus_id);
int words;
dma_data = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
- if (dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
+ if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD)
/*
* Configure McBSP threshold based on either:
* packet_size, when the sDMA is in packet mode, or
@@ -91,15 +82,15 @@ static void omap_mcbsp_set_threshold(struct snd_pcm_substream *substream)
words = dma_data->packet_size;
else
words = snd_pcm_lib_period_bytes(substream) /
- (mcbsp_data->wlen / 8);
+ (mcbsp->wlen / 8);
else
words = 1;
/* Configure McBSP internal buffer usage */
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- omap_mcbsp_set_tx_threshold(mcbsp_data->bus_id, words);
+ omap_mcbsp_set_tx_threshold(mcbsp, words);
else
- omap_mcbsp_set_rx_threshold(mcbsp_data->bus_id, words);
+ omap_mcbsp_set_rx_threshold(mcbsp, words);
}
static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
@@ -109,12 +100,12 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
SNDRV_PCM_HW_PARAM_BUFFER_SIZE);
struct snd_interval *channels = hw_param_interval(params,
SNDRV_PCM_HW_PARAM_CHANNELS);
- struct omap_mcbsp_data *mcbsp_data = rule->private;
+ struct omap_mcbsp *mcbsp = rule->private;
struct snd_interval frames;
int size;
snd_interval_any(&frames);
- size = omap_mcbsp_get_fifo_size(mcbsp_data->bus_id);
+ size = mcbsp->pdata->buffer_size;
frames.min = size / channels->min;
frames.integer = 1;
@@ -124,12 +115,11 @@ static int omap_mcbsp_hwrule_min_buffersize(struct snd_pcm_hw_params *params,
static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
- int bus_id = mcbsp_data->bus_id;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
int err = 0;
if (!cpu_dai->active)
- err = omap_mcbsp_request(bus_id);
+ err = omap_mcbsp_request(mcbsp);
/*
* OMAP3 McBSP FIFO is word structured.
@@ -146,16 +136,16 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
* 2 channels (stereo): size is 128 / 2 = 64 frames (2 * 64 words)
* 4 channels: size is 128 / 4 = 32 frames (4 * 32 words)
*/
- if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
+ if (mcbsp->pdata->buffer_size) {
/*
* Rule for the buffer size. We should not allow
* smaller buffer than the FIFO size to avoid underruns
*/
snd_pcm_hw_rule_add(substream->runtime, 0,
- SNDRV_PCM_HW_PARAM_CHANNELS,
+ SNDRV_PCM_HW_PARAM_BUFFER_SIZE,
omap_mcbsp_hwrule_min_buffersize,
- mcbsp_data,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE, -1);
+ mcbsp,
+ SNDRV_PCM_HW_PARAM_CHANNELS, -1);
/* Make sure, that the period size is always even */
snd_pcm_hw_constraint_step(substream->runtime, 0,
@@ -168,33 +158,33 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
if (!cpu_dai->active) {
- omap_mcbsp_free(mcbsp_data->bus_id);
- mcbsp_data->configured = 0;
+ omap_mcbsp_free(mcbsp);
+ mcbsp->configured = 0;
}
}
static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
int err = 0, play = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- mcbsp_data->active++;
- omap_mcbsp_start(mcbsp_data->bus_id, play, !play);
+ mcbsp->active++;
+ omap_mcbsp_start(mcbsp, play, !play);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- omap_mcbsp_stop(mcbsp_data->bus_id, play, !play);
- mcbsp_data->active--;
+ omap_mcbsp_stop(mcbsp, play, !play);
+ mcbsp->active--;
break;
default:
err = -EINVAL;
@@ -209,14 +199,14 @@ static snd_pcm_sframes_t omap_mcbsp_dai_delay(
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
u16 fifo_use;
snd_pcm_sframes_t delay;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- fifo_use = omap_mcbsp_get_tx_delay(mcbsp_data->bus_id);
+ fifo_use = omap_mcbsp_get_tx_delay(mcbsp);
else
- fifo_use = omap_mcbsp_get_rx_delay(mcbsp_data->bus_id);
+ fifo_use = omap_mcbsp_get_rx_delay(mcbsp);
/*
* Divide the used locations with the channel count to get the
@@ -232,19 +222,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *cpu_dai)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
- struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
struct omap_pcm_dma_data *dma_data;
- int dma, bus_id = mcbsp_data->bus_id;
int wlen, channels, wpf, sync_mode = OMAP_DMA_SYNC_ELEMENT;
int pkt_size = 0;
- unsigned long port;
unsigned int format, div, framesize, master;
- dma_data = &omap_mcbsp_dai_dma_params[cpu_dai->id][substream->stream];
-
- dma = omap_mcbsp_dma_ch_params(bus_id, substream->stream);
- port = omap_mcbsp_dma_reg_params(bus_id, substream->stream);
+ dma_data = &mcbsp->dma_data[substream->stream];
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
@@ -258,20 +243,17 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
default:
return -EINVAL;
}
- if (cpu_is_omap34xx()) {
+ if (mcbsp->pdata->buffer_size) {
dma_data->set_threshold = omap_mcbsp_set_threshold;
/* TODO: Currently, MODE_ELEMENT == MODE_FRAME */
- if (omap_mcbsp_get_dma_op_mode(bus_id) ==
- MCBSP_DMA_MODE_THRESHOLD) {
+ if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
int period_words, max_thrsh;
period_words = params_period_bytes(params) / (wlen / 8);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- max_thrsh = omap_mcbsp_get_max_tx_threshold(
- mcbsp_data->bus_id);
+ max_thrsh = mcbsp->max_tx_thres;
else
- max_thrsh = omap_mcbsp_get_max_rx_threshold(
- mcbsp_data->bus_id);
+ max_thrsh = mcbsp->max_rx_thres;
/*
* If the period contains less or equal number of words,
* we are using the original threshold mode setup:
@@ -304,20 +286,21 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
}
}
- dma_data->name = substream->stream ? "Audio Capture" : "Audio Playback";
- dma_data->dma_req = dma;
- dma_data->port_addr = port;
dma_data->sync_mode = sync_mode;
dma_data->packet_size = pkt_size;
snd_soc_dai_set_dma_data(cpu_dai, substream, dma_data);
- if (mcbsp_data->configured) {
+ if (mcbsp->configured) {
/* McBSP already configured by another stream */
return 0;
}
- format = mcbsp_data->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
+ regs->rcr2 &= ~(RPHASE | RFRLEN2(0x7f) | RWDLEN2(7));
+ regs->xcr2 &= ~(RPHASE | XFRLEN2(0x7f) | XWDLEN2(7));
+ regs->rcr1 &= ~(RFRLEN1(0x7f) | RWDLEN1(7));
+ regs->xcr1 &= ~(XFRLEN1(0x7f) | XWDLEN1(7));
+ format = mcbsp->fmt & SND_SOC_DAIFMT_FORMAT_MASK;
wpf = channels = params_channels(params);
if (channels == 2 && (format == SND_SOC_DAIFMT_I2S ||
format == SND_SOC_DAIFMT_LEFT_J)) {
@@ -355,10 +338,10 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
/* In McBSP master modes, FRAME (i.e. sample rate) is generated
* by _counting_ BCLKs. Calculate frame size in BCLKs */
- master = mcbsp_data->fmt & SND_SOC_DAIFMT_MASTER_MASK;
+ master = mcbsp->fmt & SND_SOC_DAIFMT_MASTER_MASK;
if (master == SND_SOC_DAIFMT_CBS_CFS) {
- div = mcbsp_data->clk_div ? mcbsp_data->clk_div : 1;
- framesize = (mcbsp_data->in_freq / div) / params_rate(params);
+ div = mcbsp->clk_div ? mcbsp->clk_div : 1;
+ framesize = (mcbsp->in_freq / div) / params_rate(params);
if (framesize < wlen * channels) {
printk(KERN_ERR "%s: not enough bandwidth for desired rate and "
@@ -369,6 +352,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
framesize = wlen * channels;
/* Set FS period and length in terms of bit clock periods */
+ regs->srgr2 &= ~FPER(0xfff);
+ regs->srgr1 &= ~FWID(0xff);
switch (format) {
case SND_SOC_DAIFMT_I2S:
case SND_SOC_DAIFMT_LEFT_J:
@@ -382,9 +367,9 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
break;
}
- omap_mcbsp_config(bus_id, &mcbsp_data->regs);
- mcbsp_data->wlen = wlen;
- mcbsp_data->configured = 1;
+ omap_mcbsp_config(mcbsp, &mcbsp->cfg_regs);
+ mcbsp->wlen = wlen;
+ mcbsp->configured = 1;
return 0;
}
@@ -396,14 +381,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
unsigned int fmt)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
- struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
- unsigned int temp_fmt = fmt;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
+ bool inv_fs = false;
- if (mcbsp_data->configured)
+ if (mcbsp->configured)
return 0;
- mcbsp_data->fmt = fmt;
+ mcbsp->fmt = fmt;
memset(regs, 0, sizeof(*regs));
/* Generic McBSP register settings */
regs->spcr2 |= XINTM(3) | FREE;
@@ -430,21 +415,21 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
regs->xcr2 |= XDATDLY(0);
regs->spcr1 |= RJUST(2);
/* Invert FS polarity configuration */
- temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+ inv_fs = true;
break;
case SND_SOC_DAIFMT_DSP_A:
/* 1-bit data delay */
regs->rcr2 |= RDATDLY(1);
regs->xcr2 |= XDATDLY(1);
/* Invert FS polarity configuration */
- temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+ inv_fs = true;
break;
case SND_SOC_DAIFMT_DSP_B:
/* 0-bit data delay */
regs->rcr2 |= RDATDLY(0);
regs->xcr2 |= XDATDLY(0);
/* Invert FS polarity configuration */
- temp_fmt ^= SND_SOC_DAIFMT_NB_IF;
+ inv_fs = true;
break;
default:
/* Unsupported data format */
@@ -468,7 +453,7 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
}
/* Set bit clock (CLKX/CLKR) and FS polarities */
- switch (temp_fmt & SND_SOC_DAIFMT_INV_MASK) {
+ switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
case SND_SOC_DAIFMT_NB_NF:
/*
* Normal BCLK + FS.
@@ -489,6 +474,8 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
default:
return -EINVAL;
}
+ if (inv_fs == true)
+ regs->pcr0 ^= FSXP | FSRP;
return 0;
}
@@ -496,13 +483,14 @@ static int omap_mcbsp_dai_set_dai_fmt(struct snd_soc_dai *cpu_dai,
static int omap_mcbsp_dai_set_clkdiv(struct snd_soc_dai *cpu_dai,
int div_id, int div)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
- struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
if (div_id != OMAP_MCBSP_CLKGDV)
return -ENODEV;
- mcbsp_data->clk_div = div;
+ mcbsp->clk_div = div;
+ regs->srgr1 &= ~CLKGDV(0xff);
regs->srgr1 |= CLKGDV(div - 1);
return 0;
@@ -512,19 +500,32 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
int clk_id, unsigned int freq,
int dir)
{
- struct omap_mcbsp_data *mcbsp_data = snd_soc_dai_get_drvdata(cpu_dai);
- struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+ struct omap_mcbsp_reg_cfg *regs = &mcbsp->cfg_regs;
int err = 0;
- /* The McBSP signal muxing functions are only available on McBSP1 */
- if (clk_id == OMAP_MCBSP_CLKR_SRC_CLKR ||
- clk_id == OMAP_MCBSP_CLKR_SRC_CLKX ||
- clk_id == OMAP_MCBSP_FSR_SRC_FSR ||
- clk_id == OMAP_MCBSP_FSR_SRC_FSX)
- if (cpu_class_is_omap1() || mcbsp_data->bus_id != 0)
- return -EINVAL;
+ if (mcbsp->active) {
+ if (freq == mcbsp->in_freq)
+ return 0;
+ else
+ return -EBUSY;
+ }
- mcbsp_data->in_freq = freq;
+ if (clk_id == OMAP_MCBSP_SYSCLK_CLK ||
+ clk_id == OMAP_MCBSP_SYSCLK_CLKS_FCLK ||
+ clk_id == OMAP_MCBSP_SYSCLK_CLKS_EXT ||
+ clk_id == OMAP_MCBSP_SYSCLK_CLKX_EXT ||
+ clk_id == OMAP_MCBSP_SYSCLK_CLKR_EXT) {
+ mcbsp->in_freq = freq;
+ regs->srgr2 &= ~CLKSM;
+ regs->pcr0 &= ~SCLKME;
+ } else if (cpu_class_is_omap1()) {
+ /*
+ * McBSP CLKR/FSR signal muxing functions are only available on
+ * OMAP2 or newer versions
+ */
+ return -EINVAL;
+ }
switch (clk_id) {
case OMAP_MCBSP_SYSCLK_CLK:
@@ -535,7 +536,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
err = -EINVAL;
break;
}
- err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+ err = omap2_mcbsp_set_clks_src(mcbsp,
MCBSP_CLKS_PRCM_SRC);
break;
case OMAP_MCBSP_SYSCLK_CLKS_EXT:
@@ -543,7 +544,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
err = 0;
break;
}
- err = omap2_mcbsp_set_clks_src(mcbsp_data->bus_id,
+ err = omap2_mcbsp_set_clks_src(mcbsp,
MCBSP_CLKS_PAD_SRC);
break;
@@ -555,24 +556,16 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
case OMAP_MCBSP_CLKR_SRC_CLKR:
- if (cpu_class_is_omap1())
- break;
- omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKR);
+ err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKR);
break;
case OMAP_MCBSP_CLKR_SRC_CLKX:
- if (cpu_class_is_omap1())
- break;
- omap2_mcbsp1_mux_clkr_src(CLKR_SRC_CLKX);
+ err = omap_mcbsp_6pin_src_mux(mcbsp, CLKR_SRC_CLKX);
break;
case OMAP_MCBSP_FSR_SRC_FSR:
- if (cpu_class_is_omap1())
- break;
- omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSR);
+ err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSR);
break;
case OMAP_MCBSP_FSR_SRC_FSX:
- if (cpu_class_is_omap1())
- break;
- omap2_mcbsp1_mux_fsr_src(FSR_SRC_FSX);
+ err = omap_mcbsp_6pin_src_mux(mcbsp, FSR_SRC_FSX);
break;
default:
err = -ENODEV;
@@ -581,7 +574,7 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
return err;
}
-static struct snd_soc_dai_ops mcbsp_dai_ops = {
+static const struct snd_soc_dai_ops mcbsp_dai_ops = {
.startup = omap_mcbsp_dai_startup,
.shutdown = omap_mcbsp_dai_shutdown,
.trigger = omap_mcbsp_dai_trigger,
@@ -592,16 +585,27 @@ static struct snd_soc_dai_ops mcbsp_dai_ops = {
.set_sysclk = omap_mcbsp_dai_set_dai_sysclk,
};
-static int mcbsp_dai_probe(struct snd_soc_dai *dai)
+static int omap_mcbsp_probe(struct snd_soc_dai *dai)
{
- mcbsp_data[dai->id].bus_id = dai->id;
- snd_soc_dai_set_drvdata(dai, &mcbsp_data[dai->id].bus_id);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
+
+ pm_runtime_enable(mcbsp->dev);
+
return 0;
}
-static struct snd_soc_dai_driver omap_mcbsp_dai =
+static int omap_mcbsp_remove(struct snd_soc_dai *dai)
{
- .probe = mcbsp_dai_probe,
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(dai);
+
+ pm_runtime_disable(mcbsp->dev);
+
+ return 0;
+}
+
+static struct snd_soc_dai_driver omap_mcbsp_dai = {
+ .probe = omap_mcbsp_probe,
+ .remove = omap_mcbsp_remove,
.playback = {
.channels_min = 1,
.channels_max = 16,
@@ -632,11 +636,13 @@ static int omap_mcbsp_st_info_volsw(struct snd_kcontrol *kcontrol,
return 0;
}
-#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(id, channel) \
+#define OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(channel) \
static int \
-omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
+omap_mcbsp_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
struct snd_ctl_elem_value *uc) \
{ \
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \
struct soc_mixer_control *mc = \
(struct soc_mixer_control *)kc->private_value; \
int max = mc->max; \
@@ -647,46 +653,44 @@ omap_mcbsp##id##_set_st_ch##channel##_volume(struct snd_kcontrol *kc, \
return -EINVAL; \
\
/* OMAP McBSP implementation uses index values 0..4 */ \
- return omap_st_set_chgain((id)-1, channel, val); \
+ return omap_st_set_chgain(mcbsp, channel, val); \
}
-#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(id, channel) \
+#define OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(channel) \
static int \
-omap_mcbsp##id##_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
+omap_mcbsp_get_st_ch##channel##_volume(struct snd_kcontrol *kc, \
struct snd_ctl_elem_value *uc) \
{ \
+ struct snd_soc_dai *cpu_dai = snd_kcontrol_chip(kc); \
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai); \
s16 chgain; \
\
- if (omap_st_get_chgain((id)-1, channel, &chgain)) \
+ if (omap_st_get_chgain(mcbsp, channel, &chgain)) \
return -EAGAIN; \
\
uc->value.integer.value[0] = chgain; \
return 0; \
}
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 0)
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(2, 1)
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 0)
-OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(3, 1)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 0)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(2, 1)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 0)
-OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(3, 1)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(0)
+OMAP_MCBSP_ST_SET_CHANNEL_VOLUME(1)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(0)
+OMAP_MCBSP_ST_GET_CHANNEL_VOLUME(1)
static int omap_mcbsp_st_put_mode(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_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
u8 value = ucontrol->value.integer.value[0];
- if (value == omap_st_is_enabled(mc->reg))
+ if (value == omap_st_is_enabled(mcbsp))
return 0;
if (value)
- omap_st_enable(mc->reg);
+ omap_st_enable(mcbsp);
else
- omap_st_disable(mc->reg);
+ omap_st_disable(mcbsp);
return 1;
}
@@ -694,10 +698,10 @@ static int omap_mcbsp_st_put_mode(struct snd_kcontrol *kcontrol,
static int omap_mcbsp_st_get_mode(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_dai *cpu_dai = snd_kcontrol_chip(kcontrol);
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
- ucontrol->value.integer.value[0] = omap_st_is_enabled(mc->reg);
+ ucontrol->value.integer.value[0] = omap_st_is_enabled(mcbsp);
return 0;
}
@@ -706,12 +710,12 @@ static const struct snd_kcontrol_new omap_mcbsp2_st_controls[] = {
omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 0 Volume",
-32768, 32767,
- omap_mcbsp2_get_st_ch0_volume,
- omap_mcbsp2_set_st_ch0_volume),
+ omap_mcbsp_get_st_ch0_volume,
+ omap_mcbsp_set_st_ch0_volume),
OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP2 Sidetone Channel 1 Volume",
-32768, 32767,
- omap_mcbsp2_get_st_ch1_volume,
- omap_mcbsp2_set_st_ch1_volume),
+ omap_mcbsp_get_st_ch1_volume,
+ omap_mcbsp_set_st_ch1_volume),
};
static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
@@ -719,25 +723,30 @@ static const struct snd_kcontrol_new omap_mcbsp3_st_controls[] = {
omap_mcbsp_st_get_mode, omap_mcbsp_st_put_mode),
OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 0 Volume",
-32768, 32767,
- omap_mcbsp3_get_st_ch0_volume,
- omap_mcbsp3_set_st_ch0_volume),
+ omap_mcbsp_get_st_ch0_volume,
+ omap_mcbsp_set_st_ch0_volume),
OMAP_MCBSP_SOC_SINGLE_S16_EXT("McBSP3 Sidetone Channel 1 Volume",
-32768, 32767,
- omap_mcbsp3_get_st_ch1_volume,
- omap_mcbsp3_set_st_ch1_volume),
+ omap_mcbsp_get_st_ch1_volume,
+ omap_mcbsp_set_st_ch1_volume),
};
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id)
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd)
{
- if (!cpu_is_omap34xx())
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct omap_mcbsp *mcbsp = snd_soc_dai_get_drvdata(cpu_dai);
+
+ if (!mcbsp->st_data)
return -ENODEV;
- switch (mcbsp_id) {
- case 1: /* McBSP 2 */
- return snd_soc_add_controls(codec, omap_mcbsp2_st_controls,
+ switch (cpu_dai->id) {
+ case 2: /* McBSP 2 */
+ return snd_soc_add_dai_controls(cpu_dai,
+ omap_mcbsp2_st_controls,
ARRAY_SIZE(omap_mcbsp2_st_controls));
- case 2: /* McBSP 3 */
- return snd_soc_add_controls(codec, omap_mcbsp3_st_controls,
+ case 3: /* McBSP 3 */
+ return snd_soc_add_dai_controls(cpu_dai,
+ omap_mcbsp3_st_controls,
ARRAY_SIZE(omap_mcbsp3_st_controls));
default:
break;
@@ -749,18 +758,51 @@ EXPORT_SYMBOL_GPL(omap_mcbsp_st_add_controls);
static __devinit int asoc_mcbsp_probe(struct platform_device *pdev)
{
- return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
+ struct omap_mcbsp_platform_data *pdata = dev_get_platdata(&pdev->dev);
+ struct omap_mcbsp *mcbsp;
+ int ret;
+
+ if (!pdata) {
+ dev_err(&pdev->dev, "missing platform data.\n");
+ return -EINVAL;
+ }
+ mcbsp = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcbsp), GFP_KERNEL);
+ if (!mcbsp)
+ return -ENOMEM;
+
+ mcbsp->id = pdev->id;
+ mcbsp->pdata = pdata;
+ mcbsp->dev = &pdev->dev;
+ platform_set_drvdata(pdev, mcbsp);
+
+ ret = omap_mcbsp_init(pdev);
+ if (!ret)
+ return snd_soc_register_dai(&pdev->dev, &omap_mcbsp_dai);
+
+ return ret;
}
static int __devexit asoc_mcbsp_remove(struct platform_device *pdev)
{
+ struct omap_mcbsp *mcbsp = platform_get_drvdata(pdev);
+
snd_soc_unregister_dai(&pdev->dev);
+
+ if (mcbsp->pdata->ops && mcbsp->pdata->ops->free)
+ mcbsp->pdata->ops->free(mcbsp->id);
+
+ omap_mcbsp_sysfs_remove(mcbsp);
+
+ clk_put(mcbsp->fclk);
+
+ platform_set_drvdata(pdev, NULL);
+
return 0;
}
static struct platform_driver asoc_mcbsp_driver = {
.driver = {
- .name = "omap-mcbsp-dai",
+ .name = "omap-mcbsp",
.owner = THIS_MODULE,
},
@@ -768,17 +810,7 @@ static struct platform_driver asoc_mcbsp_driver = {
.remove = __devexit_p(asoc_mcbsp_remove),
};
-static int __init snd_omap_mcbsp_init(void)
-{
- return platform_driver_register(&asoc_mcbsp_driver);
-}
-module_init(snd_omap_mcbsp_init);
-
-static void __exit snd_omap_mcbsp_exit(void)
-{
- platform_driver_unregister(&asoc_mcbsp_driver);
-}
-module_exit(snd_omap_mcbsp_exit);
+module_platform_driver(asoc_mcbsp_driver);
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
MODULE_DESCRIPTION("OMAP I2S SoC Interface");
diff --git a/sound/soc/omap/omap-mcbsp.h b/sound/soc/omap/omap-mcbsp.h
index 65cde9d3807b..f877b16f19c9 100644
--- a/sound/soc/omap/omap-mcbsp.h
+++ b/sound/soc/omap/omap-mcbsp.h
@@ -59,6 +59,6 @@ enum omap_mcbsp_div {
#define NUM_LINKS 5
#endif
-int omap_mcbsp_st_add_controls(struct snd_soc_codec *codec, int mcbsp_id);
+int omap_mcbsp_st_add_controls(struct snd_soc_pcm_runtime *rtd);
#endif
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c
index bed09c27e44c..39705561131a 100644
--- a/sound/soc/omap/omap-mcpdm.c
+++ b/sound/soc/omap/omap-mcpdm.c
@@ -1,11 +1,12 @@
/*
* omap-mcpdm.c -- OMAP ALSA SoC DAI driver using McPDM port
*
- * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2009 - 2011 Texas Instruments
*
- * Author: Misael Lopez Cruz <x0052729@ti.com>
+ * Author: Misael Lopez Cruz <misael.lopez@ti.com>
* Contact: Jorge Eduardo Candelaria <x0107209@ti.com>
* Margarita Olaya <magi.olaya@ti.com>
+ * Peter Ujfalusi <peter.ujfalusi@ti.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -25,41 +26,42 @@
#include <linux/init.h>
#include <linux/module.h>
-#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/slab.h>
+#include <linux/pm_runtime.h>
+
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
-#include <sound/initval.h>
#include <sound/soc.h>
#include <plat/dma.h>
-#include <plat/mcbsp.h>
-#include "mcpdm.h"
+#include <plat/omap_hwmod.h>
+#include "omap-mcpdm.h"
#include "omap-pcm.h"
-struct omap_mcpdm_data {
- struct omap_mcpdm_link *links;
- int active;
-};
+struct omap_mcpdm {
+ struct device *dev;
+ unsigned long phys_base;
+ void __iomem *io_base;
+ int irq;
-static struct omap_mcpdm_link omap_mcpdm_links[] = {
- /* downlink */
- {
- .irq_mask = MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL,
- .threshold = 1,
- .format = PDMOUTFORMAT_LJUST,
- },
- /* uplink */
- {
- .irq_mask = MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL,
- .threshold = 1,
- .format = PDMOUTFORMAT_LJUST,
- },
-};
+ struct mutex mutex;
+
+ /* channel data */
+ u32 dn_channels;
+ u32 up_channels;
+
+ /* McPDM FIFO thresholds */
+ u32 dn_threshold;
+ u32 up_threshold;
-static struct omap_mcpdm_data mcpdm_data = {
- .links = omap_mcpdm_links,
- .active = 0,
+ /* McPDM dn offsets for rx1, and 2 channels */
+ u32 dn_rx_offset;
};
/*
@@ -71,88 +73,254 @@ static struct omap_pcm_dma_data omap_mcpdm_dai_dma_params[] = {
.dma_req = OMAP44XX_DMA_MCPDM_DL,
.data_type = OMAP_DMA_DATA_TYPE_S32,
.sync_mode = OMAP_DMA_SYNC_PACKET,
- .packet_size = 16,
- .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_DN_DATA,
+ .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_DN_DATA,
},
{
.name = "Audio capture",
.dma_req = OMAP44XX_DMA_MCPDM_UP,
.data_type = OMAP_DMA_DATA_TYPE_S32,
.sync_mode = OMAP_DMA_SYNC_PACKET,
- .packet_size = 16,
- .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_UP_DATA,
+ .port_addr = OMAP44XX_MCPDM_L3_BASE + MCPDM_REG_UP_DATA,
},
};
-static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static inline void omap_mcpdm_write(struct omap_mcpdm *mcpdm, u16 reg, u32 val)
{
- int err = 0;
+ __raw_writel(val, mcpdm->io_base + reg);
+}
- if (!dai->active)
- err = omap_mcpdm_request();
+static inline int omap_mcpdm_read(struct omap_mcpdm *mcpdm, u16 reg)
+{
+ return __raw_readl(mcpdm->io_base + reg);
+}
- return err;
+#ifdef DEBUG
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm)
+{
+ dev_dbg(mcpdm->dev, "***********************\n");
+ dev_dbg(mcpdm->dev, "IRQSTATUS_RAW: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS_RAW));
+ dev_dbg(mcpdm->dev, "IRQSTATUS: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS));
+ dev_dbg(mcpdm->dev, "IRQENABLE_SET: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_SET));
+ dev_dbg(mcpdm->dev, "IRQENABLE_CLR: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_IRQENABLE_CLR));
+ dev_dbg(mcpdm->dev, "IRQWAKE_EN: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_IRQWAKE_EN));
+ dev_dbg(mcpdm->dev, "DMAENABLE_SET: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_SET));
+ dev_dbg(mcpdm->dev, "DMAENABLE_CLR: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_DMAENABLE_CLR));
+ dev_dbg(mcpdm->dev, "DMAWAKEEN: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_DMAWAKEEN));
+ dev_dbg(mcpdm->dev, "CTRL: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL));
+ dev_dbg(mcpdm->dev, "DN_DATA: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_DN_DATA));
+ dev_dbg(mcpdm->dev, "UP_DATA: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_UP_DATA));
+ dev_dbg(mcpdm->dev, "FIFO_CTRL_DN: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_DN));
+ dev_dbg(mcpdm->dev, "FIFO_CTRL_UP: 0x%04x\n",
+ omap_mcpdm_read(mcpdm, MCPDM_REG_FIFO_CTRL_UP));
+ dev_dbg(mcpdm->dev, "***********************\n");
}
+#else
+static void omap_mcpdm_reg_dump(struct omap_mcpdm *mcpdm) {}
+#endif
-static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+/*
+ * Enables the transfer through the PDM interface to/from the Phoenix
+ * codec by enabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_start(struct omap_mcpdm *mcpdm)
{
- if (!dai->active)
- omap_mcpdm_free();
+ u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+ ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+ omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+ ctrl |= mcpdm->dn_channels | mcpdm->up_channels;
+ omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+ ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+ omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
}
-static int omap_mcpdm_dai_trigger(struct snd_pcm_substream *substream, int cmd,
+/*
+ * Disables the transfer through the PDM interface to/from the Phoenix
+ * codec by disabling the corresponding UP or DN channels.
+ */
+static void omap_mcpdm_stop(struct omap_mcpdm *mcpdm)
+{
+ u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+ ctrl |= (MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+ omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+ ctrl &= ~(mcpdm->dn_channels | mcpdm->up_channels);
+ omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+ ctrl &= ~(MCPDM_SW_DN_RST | MCPDM_SW_UP_RST);
+ omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, ctrl);
+
+}
+
+/*
+ * Is the physical McPDM interface active.
+ */
+static inline int omap_mcpdm_active(struct omap_mcpdm *mcpdm)
+{
+ return omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL) &
+ (MCPDM_PDM_DN_MASK | MCPDM_PDM_UP_MASK);
+}
+
+/*
+ * Configures McPDM uplink, and downlink for audio.
+ * This function should be called before omap_mcpdm_start.
+ */
+static void omap_mcpdm_open_streams(struct omap_mcpdm *mcpdm)
+{
+ omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_SET,
+ MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL |
+ MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+ /* Enable DN RX1/2 offset cancellation feature, if configured */
+ if (mcpdm->dn_rx_offset) {
+ u32 dn_offset = mcpdm->dn_rx_offset;
+
+ omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+ dn_offset |= (MCPDM_DN_OFST_RX1_EN | MCPDM_DN_OFST_RX2_EN);
+ omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, dn_offset);
+ }
+
+ omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_DN, mcpdm->dn_threshold);
+ omap_mcpdm_write(mcpdm, MCPDM_REG_FIFO_CTRL_UP, mcpdm->up_threshold);
+
+ omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_SET,
+ MCPDM_DMA_DN_ENABLE | MCPDM_DMA_UP_ENABLE);
+}
+
+/*
+ * Cleans McPDM uplink, and downlink configuration.
+ * This function should be called when the stream is closed.
+ */
+static void omap_mcpdm_close_streams(struct omap_mcpdm *mcpdm)
+{
+ /* Disable irq request generation for downlink */
+ omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+ MCPDM_DN_IRQ_EMPTY | MCPDM_DN_IRQ_FULL);
+
+ /* Disable DMA request generation for downlink */
+ omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_DN_ENABLE);
+
+ /* Disable irq request generation for uplink */
+ omap_mcpdm_write(mcpdm, MCPDM_REG_IRQENABLE_CLR,
+ MCPDM_UP_IRQ_EMPTY | MCPDM_UP_IRQ_FULL);
+
+ /* Disable DMA request generation for uplink */
+ omap_mcpdm_write(mcpdm, MCPDM_REG_DMAENABLE_CLR, MCPDM_DMA_UP_ENABLE);
+
+ /* Disable RX1/2 offset cancellation */
+ if (mcpdm->dn_rx_offset)
+ omap_mcpdm_write(mcpdm, MCPDM_REG_DN_OFFSET, 0);
+}
+
+static irqreturn_t omap_mcpdm_irq_handler(int irq, void *dev_id)
+{
+ struct omap_mcpdm *mcpdm = dev_id;
+ int irq_status;
+
+ irq_status = omap_mcpdm_read(mcpdm, MCPDM_REG_IRQSTATUS);
+
+ /* Acknowledge irq event */
+ omap_mcpdm_write(mcpdm, MCPDM_REG_IRQSTATUS, irq_status);
+
+ if (irq_status & MCPDM_DN_IRQ_FULL)
+ dev_dbg(mcpdm->dev, "DN (playback) FIFO Full\n");
+
+ if (irq_status & MCPDM_DN_IRQ_EMPTY)
+ dev_dbg(mcpdm->dev, "DN (playback) FIFO Empty\n");
+
+ if (irq_status & MCPDM_DN_IRQ)
+ dev_dbg(mcpdm->dev, "DN (playback) write request\n");
+
+ if (irq_status & MCPDM_UP_IRQ_FULL)
+ dev_dbg(mcpdm->dev, "UP (capture) FIFO Full\n");
+
+ if (irq_status & MCPDM_UP_IRQ_EMPTY)
+ dev_dbg(mcpdm->dev, "UP (capture) FIFO Empty\n");
+
+ if (irq_status & MCPDM_UP_IRQ)
+ dev_dbg(mcpdm->dev, "UP (capture) write request\n");
+
+ return IRQ_HANDLED;
+}
+
+static int omap_mcpdm_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
- int stream = substream->stream;
- int err = 0;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- if (!mcpdm_priv->active++)
- omap_mcpdm_start(stream);
- break;
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- if (!--mcpdm_priv->active)
- omap_mcpdm_stop(stream);
- break;
- default:
- err = -EINVAL;
+ mutex_lock(&mcpdm->mutex);
+
+ if (!dai->active) {
+ /* Enable watch dog for ES above ES 1.0 to avoid saturation */
+ if (omap_rev() != OMAP4430_REV_ES1_0) {
+ u32 ctrl = omap_mcpdm_read(mcpdm, MCPDM_REG_CTRL);
+
+ omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL,
+ ctrl | MCPDM_WD_EN);
+ }
+ omap_mcpdm_open_streams(mcpdm);
}
- return err;
+ mutex_unlock(&mcpdm->mutex);
+
+ return 0;
+}
+
+static void omap_mcpdm_dai_shutdown(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+ mutex_lock(&mcpdm->mutex);
+
+ if (!dai->active) {
+ if (omap_mcpdm_active(mcpdm)) {
+ omap_mcpdm_stop(mcpdm);
+ omap_mcpdm_close_streams(mcpdm);
+ }
+ }
+
+ mutex_unlock(&mcpdm->mutex);
}
static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params,
struct snd_soc_dai *dai)
{
- struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
- struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
int stream = substream->stream;
- int channels, err, link_mask = 0;
-
- snd_soc_dai_set_dma_data(dai, substream,
- &omap_mcpdm_dai_dma_params[stream]);
+ struct omap_pcm_dma_data *dma_data;
+ int channels;
+ int link_mask = 0;
channels = params_channels(params);
switch (channels) {
+ case 5:
+ if (stream == SNDRV_PCM_STREAM_CAPTURE)
+ /* up to 3 channels for capture */
+ return -EINVAL;
+ link_mask |= 1 << 4;
case 4:
if (stream == SNDRV_PCM_STREAM_CAPTURE)
- /* up to 2 channels for capture */
+ /* up to 3 channels for capture */
return -EINVAL;
link_mask |= 1 << 3;
case 3:
- if (stream == SNDRV_PCM_STREAM_CAPTURE)
- /* up to 2 channels for capture */
- return -EINVAL;
link_mask |= 1 << 2;
case 2:
link_mask |= 1 << 1;
@@ -164,109 +332,193 @@ static int omap_mcpdm_dai_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
+ dma_data = &omap_mcpdm_dai_dma_params[stream];
+
+ /* Configure McPDM channels, and DMA packet size */
if (stream == SNDRV_PCM_STREAM_PLAYBACK) {
- mcpdm_links[stream].channels = link_mask << 3;
- err = omap_mcpdm_playback_open(&mcpdm_links[stream]);
+ mcpdm->dn_channels = link_mask << 3;
+ dma_data->packet_size =
+ (MCPDM_DN_THRES_MAX - mcpdm->dn_threshold) * channels;
} else {
- mcpdm_links[stream].channels = link_mask << 0;
- err = omap_mcpdm_capture_open(&mcpdm_links[stream]);
+ mcpdm->up_channels = link_mask << 0;
+ dma_data->packet_size = mcpdm->up_threshold * channels;
}
- return err;
+ snd_soc_dai_set_dma_data(dai, substream, dma_data);
+
+ return 0;
}
-static int omap_mcpdm_dai_hw_free(struct snd_pcm_substream *substream,
+static int omap_mcpdm_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
- struct omap_mcpdm_data *mcpdm_priv = snd_soc_dai_get_drvdata(dai);
- struct omap_mcpdm_link *mcpdm_links = mcpdm_priv->links;
- int stream = substream->stream;
- int err;
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- err = omap_mcpdm_playback_close(&mcpdm_links[stream]);
- else
- err = omap_mcpdm_capture_close(&mcpdm_links[stream]);
+ if (!omap_mcpdm_active(mcpdm)) {
+ omap_mcpdm_start(mcpdm);
+ omap_mcpdm_reg_dump(mcpdm);
+ }
- return err;
+ return 0;
}
-static struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
+static const struct snd_soc_dai_ops omap_mcpdm_dai_ops = {
.startup = omap_mcpdm_dai_startup,
.shutdown = omap_mcpdm_dai_shutdown,
- .trigger = omap_mcpdm_dai_trigger,
.hw_params = omap_mcpdm_dai_hw_params,
- .hw_free = omap_mcpdm_dai_hw_free,
+ .prepare = omap_mcpdm_prepare,
};
-#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-#define OMAP_MCPDM_FORMATS (SNDRV_PCM_FMTBIT_S32_LE)
+static int omap_mcpdm_probe(struct snd_soc_dai *dai)
+{
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+ int ret;
+
+ pm_runtime_enable(mcpdm->dev);
+
+ /* Disable lines while request is ongoing */
+ pm_runtime_get_sync(mcpdm->dev);
+ omap_mcpdm_write(mcpdm, MCPDM_REG_CTRL, 0x00);
+
+ ret = request_irq(mcpdm->irq, omap_mcpdm_irq_handler,
+ 0, "McPDM", (void *)mcpdm);
+
+ pm_runtime_put_sync(mcpdm->dev);
-static int omap_mcpdm_dai_probe(struct snd_soc_dai *dai)
+ if (ret) {
+ dev_err(mcpdm->dev, "Request for IRQ failed\n");
+ pm_runtime_disable(mcpdm->dev);
+ }
+
+ /* Configure McPDM threshold values */
+ mcpdm->dn_threshold = 2;
+ mcpdm->up_threshold = MCPDM_UP_THRES_MAX - 3;
+ return ret;
+}
+
+static int omap_mcpdm_remove(struct snd_soc_dai *dai)
{
- snd_soc_dai_set_drvdata(dai, &mcpdm_data);
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(dai);
+
+ free_irq(mcpdm->irq, (void *)mcpdm);
+ pm_runtime_disable(mcpdm->dev);
+
return 0;
}
+#define OMAP_MCPDM_RATES (SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+#define OMAP_MCPDM_FORMATS SNDRV_PCM_FMTBIT_S32_LE
+
static struct snd_soc_dai_driver omap_mcpdm_dai = {
- .probe = omap_mcpdm_dai_probe,
+ .probe = omap_mcpdm_probe,
+ .remove = omap_mcpdm_remove,
+ .probe_order = SND_SOC_COMP_ORDER_LATE,
+ .remove_order = SND_SOC_COMP_ORDER_EARLY,
.playback = {
.channels_min = 1,
- .channels_max = 4,
+ .channels_max = 5,
.rates = OMAP_MCPDM_RATES,
.formats = OMAP_MCPDM_FORMATS,
+ .sig_bits = 24,
},
.capture = {
.channels_min = 1,
- .channels_max = 2,
+ .channels_max = 3,
.rates = OMAP_MCPDM_RATES,
.formats = OMAP_MCPDM_FORMATS,
+ .sig_bits = 24,
},
.ops = &omap_mcpdm_dai_ops,
};
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+ u8 rx1, u8 rx2)
+{
+ struct omap_mcpdm *mcpdm = snd_soc_dai_get_drvdata(rtd->cpu_dai);
+
+ mcpdm->dn_rx_offset = MCPDM_DNOFST_RX1(rx1) | MCPDM_DNOFST_RX2(rx2);
+}
+EXPORT_SYMBOL_GPL(omap_mcpdm_configure_dn_offsets);
+
static __devinit int asoc_mcpdm_probe(struct platform_device *pdev)
{
- int ret;
+ struct omap_mcpdm *mcpdm;
+ struct resource *res;
+ int ret = 0;
+
+ mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL);
+ if (!mcpdm)
+ return -ENOMEM;
+
+ platform_set_drvdata(pdev, mcpdm);
+
+ mutex_init(&mcpdm->mutex);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ if (res == NULL) {
+ dev_err(&pdev->dev, "no resource\n");
+ goto err_res;
+ }
+
+ if (!request_mem_region(res->start, resource_size(res), "McPDM")) {
+ ret = -EBUSY;
+ goto err_res;
+ }
+
+ mcpdm->io_base = ioremap(res->start, resource_size(res));
+ if (!mcpdm->io_base) {
+ ret = -ENOMEM;
+ goto err_iomap;
+ }
+
+ mcpdm->irq = platform_get_irq(pdev, 0);
+ if (mcpdm->irq < 0) {
+ ret = mcpdm->irq;
+ goto err_irq;
+ }
+
+ mcpdm->dev = &pdev->dev;
- ret = omap_mcpdm_probe(pdev);
- if (ret < 0)
- return ret;
ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai);
- if (ret < 0)
- omap_mcpdm_remove(pdev);
+ if (!ret)
+ return 0;
+
+err_irq:
+ iounmap(mcpdm->io_base);
+err_iomap:
+ release_mem_region(res->start, resource_size(res));
+err_res:
+ kfree(mcpdm);
return ret;
}
static int __devexit asoc_mcpdm_remove(struct platform_device *pdev)
{
+ struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev);
+ struct resource *res;
+
snd_soc_unregister_dai(&pdev->dev);
- omap_mcpdm_remove(pdev);
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ iounmap(mcpdm->io_base);
+ release_mem_region(res->start, resource_size(res));
+
+ kfree(mcpdm);
return 0;
}
static struct platform_driver asoc_mcpdm_driver = {
.driver = {
- .name = "omap-mcpdm-dai",
- .owner = THIS_MODULE,
+ .name = "omap-mcpdm",
+ .owner = THIS_MODULE,
},
- .probe = asoc_mcpdm_probe,
- .remove = __devexit_p(asoc_mcpdm_remove),
+ .probe = asoc_mcpdm_probe,
+ .remove = __devexit_p(asoc_mcpdm_remove),
};
-static int __init snd_omap_mcpdm_init(void)
-{
- return platform_driver_register(&asoc_mcpdm_driver);
-}
-module_init(snd_omap_mcpdm_init);
-
-static void __exit snd_omap_mcpdm_exit(void)
-{
- platform_driver_unregister(&asoc_mcpdm_driver);
-}
-module_exit(snd_omap_mcpdm_exit);
+module_platform_driver(asoc_mcpdm_driver);
-MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
+MODULE_AUTHOR("Misael Lopez Cruz <misael.lopez@ti.com>");
MODULE_DESCRIPTION("OMAP PDM SoC Interface");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-mcpdm.h b/sound/soc/omap/omap-mcpdm.h
new file mode 100644
index 000000000000..de8cf26595b1
--- /dev/null
+++ b/sound/soc/omap/omap-mcpdm.h
@@ -0,0 +1,107 @@
+/*
+ * omap-mcpdm.h
+ *
+ * Copyright (C) 2009 - 2011 Texas Instruments
+ *
+ * Contact: Misael Lopez Cruz <misael.lopez@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA
+ *
+ */
+
+#ifndef __OMAP_MCPDM_H__
+#define __OMAP_MCPDM_H__
+
+#define MCPDM_REG_REVISION 0x00
+#define MCPDM_REG_SYSCONFIG 0x10
+#define MCPDM_REG_IRQSTATUS_RAW 0x24
+#define MCPDM_REG_IRQSTATUS 0x28
+#define MCPDM_REG_IRQENABLE_SET 0x2C
+#define MCPDM_REG_IRQENABLE_CLR 0x30
+#define MCPDM_REG_IRQWAKE_EN 0x34
+#define MCPDM_REG_DMAENABLE_SET 0x38
+#define MCPDM_REG_DMAENABLE_CLR 0x3C
+#define MCPDM_REG_DMAWAKEEN 0x40
+#define MCPDM_REG_CTRL 0x44
+#define MCPDM_REG_DN_DATA 0x48
+#define MCPDM_REG_UP_DATA 0x4C
+#define MCPDM_REG_FIFO_CTRL_DN 0x50
+#define MCPDM_REG_FIFO_CTRL_UP 0x54
+#define MCPDM_REG_DN_OFFSET 0x58
+
+/*
+ * MCPDM_IRQ bit fields
+ * IRQSTATUS_RAW, IRQSTATUS, IRQENABLE_SET, IRQENABLE_CLR
+ */
+
+#define MCPDM_DN_IRQ (1 << 0)
+#define MCPDM_DN_IRQ_EMPTY (1 << 1)
+#define MCPDM_DN_IRQ_ALMST_EMPTY (1 << 2)
+#define MCPDM_DN_IRQ_FULL (1 << 3)
+
+#define MCPDM_UP_IRQ (1 << 8)
+#define MCPDM_UP_IRQ_EMPTY (1 << 9)
+#define MCPDM_UP_IRQ_ALMST_FULL (1 << 10)
+#define MCPDM_UP_IRQ_FULL (1 << 11)
+
+#define MCPDM_DOWNLINK_IRQ_MASK 0x00F
+#define MCPDM_UPLINK_IRQ_MASK 0xF00
+
+/*
+ * MCPDM_DMAENABLE bit fields
+ */
+
+#define MCPDM_DMA_DN_ENABLE (1 << 0)
+#define MCPDM_DMA_UP_ENABLE (1 << 1)
+
+/*
+ * MCPDM_CTRL bit fields
+ */
+
+#define MCPDM_PDM_UPLINK_EN(x) (1 << (x - 1)) /* ch1 is at bit 0 */
+#define MCPDM_PDM_DOWNLINK_EN(x) (1 << (x + 2)) /* ch1 is at bit 3 */
+#define MCPDM_PDMOUTFORMAT (1 << 8)
+#define MCPDM_CMD_INT (1 << 9)
+#define MCPDM_STATUS_INT (1 << 10)
+#define MCPDM_SW_UP_RST (1 << 11)
+#define MCPDM_SW_DN_RST (1 << 12)
+#define MCPDM_WD_EN (1 << 14)
+#define MCPDM_PDM_UP_MASK 0x7
+#define MCPDM_PDM_DN_MASK (0x1f << 3)
+
+
+#define MCPDM_PDMOUTFORMAT_LJUST (0 << 8)
+#define MCPDM_PDMOUTFORMAT_RJUST (1 << 8)
+
+/*
+ * MCPDM_FIFO_CTRL bit fields
+ */
+
+#define MCPDM_UP_THRES_MAX 0xF
+#define MCPDM_DN_THRES_MAX 0xF
+
+/*
+ * MCPDM_DN_OFFSET bit fields
+ */
+
+#define MCPDM_DN_OFST_RX1_EN (1 << 0)
+#define MCPDM_DNOFST_RX1(x) ((x & 0x1f) << 1)
+#define MCPDM_DN_OFST_RX2_EN (1 << 8)
+#define MCPDM_DNOFST_RX2(x) ((x & 0x1f) << 9)
+
+void omap_mcpdm_configure_dn_offsets(struct snd_soc_pcm_runtime *rtd,
+ u8 rx1, u8 rx2);
+
+#endif /* End of __OMAP_MCPDM_H__ */
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 9b5c88ac35b9..a59bd352d342 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -24,6 +24,7 @@
#include <linux/dma-mapping.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -198,6 +199,14 @@ static int omap_pcm_prepare(struct snd_pcm_substream *substream)
OMAP_DMA_LAST_IRQ | OMAP_DMA_BLOCK_IRQ);
else if (!substream->runtime->no_period_wakeup)
omap_enable_dma_irq(prtd->dma_ch, OMAP_DMA_FRAME_IRQ);
+ else {
+ /*
+ * No period wakeup:
+ * we need to disable BLOCK_IRQ, which is enabled by the omap
+ * dma core at request dma time.
+ */
+ omap_disable_dma_irq(prtd->dma_ch, OMAP_DMA_BLOCK_IRQ);
+ }
if (!(cpu_class_is_omap1())) {
omap_set_dma_src_burst_mode(prtd->dma_ch,
@@ -369,7 +378,6 @@ static void omap_pcm_free_dma_buffers(struct snd_pcm *pcm)
static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
@@ -378,14 +386,14 @@ static int omap_pcm_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(64);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = omap_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = omap_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -424,17 +432,7 @@ static struct platform_driver omap_pcm_driver = {
.remove = __devexit_p(omap_pcm_remove),
};
-static int __init snd_omap_pcm_init(void)
-{
- return platform_driver_register(&omap_pcm_driver);
-}
-module_init(snd_omap_pcm_init);
-
-static void __exit snd_omap_pcm_exit(void)
-{
- platform_driver_unregister(&omap_pcm_driver);
-}
-module_exit(snd_omap_pcm_exit);
+module_platform_driver(omap_pcm_driver);
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
MODULE_DESCRIPTION("OMAP PCM DMA module");
diff --git a/sound/soc/omap/omap-pcm.h b/sound/soc/omap/omap-pcm.h
index f95fe3064172..b92248cbd47a 100644
--- a/sound/soc/omap/omap-pcm.h
+++ b/sound/soc/omap/omap-pcm.h
@@ -25,6 +25,8 @@
#ifndef __OMAP_PCM_H__
#define __OMAP_PCM_H__
+struct snd_pcm_substream;
+
struct omap_pcm_dma_data {
char *name; /* stream identifier */
int dma_req; /* DMA request line */
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
index 40db813c0795..2830dfd05661 100644
--- a/sound/soc/omap/omap3beagle.c
+++ b/sound/soc/omap/omap3beagle.c
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -90,7 +91,7 @@ static struct snd_soc_ops omap3beagle_ops = {
static struct snd_soc_dai_link omap3beagle_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.platform_name = "omap-pcm-audio",
.codec_dai_name = "twl4030-hifi",
.codec_name = "twl4030-codec",
diff --git a/sound/soc/omap/omap3evm.c b/sound/soc/omap/omap3evm.c
index 0daa04469836..3d468c9179d7 100644
--- a/sound/soc/omap/omap3evm.c
+++ b/sound/soc/omap/omap3evm.c
@@ -19,6 +19,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -36,29 +37,8 @@ static int omap3evm_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret;
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "Can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "Can't set cpu DAI configuration\n");
- return ret;
- }
-
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
SND_SOC_CLOCK_IN);
@@ -78,16 +58,19 @@ static struct snd_soc_ops omap3evm_ops = {
static struct snd_soc_dai_link omap3evm_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &omap3evm_ops,
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_omap3evm = {
.name = "omap3evm",
+ .owner = THIS_MODULE,
.dai_link = &omap3evm_dai,
.num_links = 1,
};
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
index 8047c521e318..4c3a0978578a 100644
--- a/sound/soc/omap/omap3pandora.c
+++ b/sound/soc/omap/omap3pandora.c
@@ -24,6 +24,7 @@
#include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/regulator/consumer.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -48,24 +49,8 @@ static int omap3pandora_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS;
int ret;
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, fmt);
- if (ret < 0) {
- pr_err(PREFIX "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
- if (ret < 0) {
- pr_err(PREFIX "can't set cpu DAI configuration\n");
- return ret;
- }
-
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
SND_SOC_CLOCK_IN);
@@ -189,10 +174,8 @@ static int omap3pandora_out_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
- snd_soc_dapm_add_routes(dapm, omap3pandora_out_map,
+ return snd_soc_dapm_add_routes(dapm, omap3pandora_out_map,
ARRAY_SIZE(omap3pandora_out_map));
-
- return snd_soc_dapm_sync(dapm);
}
static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
@@ -212,10 +195,8 @@ static int omap3pandora_in_init(struct snd_soc_pcm_runtime *rtd)
if (ret < 0)
return ret;
- snd_soc_dapm_add_routes(dapm, omap3pandora_in_map,
+ return snd_soc_dapm_add_routes(dapm, omap3pandora_in_map,
ARRAY_SIZE(omap3pandora_in_map));
-
- return snd_soc_dapm_sync(dapm);
}
static struct snd_soc_ops omap3pandora_ops = {
@@ -227,19 +208,23 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
{
.name = "PCM1773",
.stream_name = "HiFi Out",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &omap3pandora_ops,
.init = omap3pandora_out_init,
}, {
.name = "TWL4030",
.stream_name = "Line/Mic In",
- .cpu_dai_name = "omap-mcbsp-dai.3",
+ .cpu_dai_name = "omap-mcbsp.4",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &omap3pandora_ops,
.init = omap3pandora_in_init,
}
@@ -248,6 +233,7 @@ static struct snd_soc_dai_link omap3pandora_dai[] = {
/* SoC card */
static struct snd_soc_card snd_soc_card_omap3pandora = {
.name = "omap3pandora",
+ .owner = THIS_MODULE,
.dai_link = omap3pandora_dai,
.num_links = ARRAY_SIZE(omap3pandora_dai),
};
diff --git a/sound/soc/omap/omap4-hdmi-card.c b/sound/soc/omap/omap4-hdmi-card.c
index 9f32615b81f7..28d689b2714d 100644
--- a/sound/soc/omap/omap4-hdmi-card.c
+++ b/sound/soc/omap/omap4-hdmi-card.c
@@ -21,6 +21,7 @@
*
*/
+#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/soc.h>
#include <asm/mach-types.h>
@@ -73,6 +74,7 @@ static struct snd_soc_dai_link omap4_hdmi_dai = {
static struct snd_soc_card snd_soc_omap4_hdmi = {
.name = "OMAP4HDMI",
+ .owner = THIS_MODULE,
.dai_link = &omap4_hdmi_dai,
.num_links = 1,
};
@@ -111,17 +113,7 @@ static struct platform_driver omap4_hdmi_driver = {
.remove = __devexit_p(omap4_hdmi_remove),
};
-static int __init omap4_hdmi_init(void)
-{
- return platform_driver_register(&omap4_hdmi_driver);
-}
-module_init(omap4_hdmi_init);
-
-static void __exit omap4_hdmi_exit(void)
-{
- platform_driver_unregister(&omap4_hdmi_driver);
-}
-module_exit(omap4_hdmi_exit);
+module_platform_driver(omap4_hdmi_driver);
MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
MODULE_DESCRIPTION("OMAP4 HDMI machine ASoC driver");
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index 7e75e775fb4a..b1a9d64cbc56 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -30,6 +30,7 @@
#include <asm/mach-types.h>
#include <mach/hardware.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include <plat/mcbsp.h>
#include "omap-mcbsp.h"
@@ -55,29 +56,8 @@ static int osk_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int err;
- /* Set codec DAI configuration */
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_DSP_B |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return err;
- }
-
- /* Set cpu DAI configuration */
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_B |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return err;
- }
-
/* Set the codec system clock for DAC and ADC */
err =
snd_soc_dai_set_sysclk(codec_dai, 0, CODEC_CLOCK, SND_SOC_CLOCK_IN);
@@ -112,44 +92,30 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"MICIN", NULL, "Mic Jack"},
};
-static int osk_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_codec *codec = rtd->codec;
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- /* Add osk5912 specific widgets */
- snd_soc_dapm_new_controls(dapm, tlv320aic23_dapm_widgets,
- ARRAY_SIZE(tlv320aic23_dapm_widgets));
-
- /* Set up osk5912 specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
- snd_soc_dapm_enable_pin(dapm, "Line In");
- snd_soc_dapm_enable_pin(dapm, "Mic Jack");
-
- snd_soc_dapm_sync(dapm);
-
- return 0;
-}
-
/* Digital audio interface glue - connects codec <--> CPU */
static struct snd_soc_dai_link osk_dai = {
.name = "TLV320AIC23",
.stream_name = "AIC23",
- .cpu_dai_name = "omap-mcbsp-dai.0",
+ .cpu_dai_name = "omap-mcbsp.1",
.codec_dai_name = "tlv320aic23-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "tlv320aic23-codec",
- .init = osk_tlv320aic23_init,
+ .dai_fmt = SND_SOC_DAIFMT_DSP_B | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &osk_ops,
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_card_osk = {
.name = "OSK5912",
+ .owner = THIS_MODULE,
.dai_link = &osk_dai,
.num_links = 1,
+
+ .dapm_widgets = tlv320aic23_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tlv320aic23_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
};
static struct platform_device *osk_snd_device;
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
index bbcf380bfb56..6ac3e0c3c282 100644
--- a/sound/soc/omap/overo.c
+++ b/sound/soc/omap/overo.c
@@ -21,6 +21,7 @@
#include <linux/clk.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -38,29 +39,8 @@ static int overo_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret;
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
SND_SOC_CLOCK_IN);
@@ -80,16 +60,19 @@ static struct snd_soc_ops overo_ops = {
static struct snd_soc_dai_link overo_dai = {
.name = "TWL4030",
.stream_name = "TWL4030",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &overo_ops,
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_card_overo = {
.name = "overo",
+ .owner = THIS_MODULE,
.dai_link = &overo_dai,
.num_links = 1,
};
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 893300a53bab..2712dd232b6d 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -26,6 +26,7 @@
#include <linux/delay.h>
#include <linux/gpio.h>
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/jack.h>
#include <sound/pcm.h>
@@ -58,9 +59,8 @@ static int rx51_spk_func;
static int rx51_dmic_func;
static int rx51_jack_func;
-static void rx51_ext_control(struct snd_soc_codec *codec)
+static void rx51_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
int hp = 0, hs = 0, tvout = 0;
switch (rx51_jack_func) {
@@ -101,11 +101,11 @@ static int rx51_startup(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = rtd->card;
snd_pcm_hw_constraint_minmax(runtime,
SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 0;
}
@@ -115,24 +115,6 @@ static int rx51_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int err;
-
- /* Set codec DAI configuration */
- err = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0)
- return err;
-
- /* Set cpu DAI configuration */
- err = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (err < 0)
- return err;
/* Set the codec system clock for DAC and ADC */
return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000,
@@ -155,13 +137,13 @@ static int rx51_get_spk(struct snd_kcontrol *kcontrol,
static int rx51_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (rx51_spk_func == ucontrol->value.integer.value[0])
return 0;
rx51_spk_func = ucontrol->value.integer.value[0];
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 1;
}
@@ -201,13 +183,13 @@ static int rx51_get_input(struct snd_kcontrol *kcontrol,
static int rx51_set_input(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (rx51_dmic_func == ucontrol->value.integer.value[0])
return 0;
rx51_dmic_func = ucontrol->value.integer.value[0];
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 1;
}
@@ -223,13 +205,13 @@ static int rx51_get_jack(struct snd_kcontrol *kcontrol,
static int rx51_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (rx51_jack_func == ucontrol->value.integer.value[0])
return 0;
rx51_jack_func = ucontrol->value.integer.value[0];
- rx51_ext_control(codec);
+ rx51_ext_control(&card->dapm);
return 1;
}
@@ -314,7 +296,7 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "LINE1R");
/* Add RX-51 specific controls */
- err = snd_soc_add_controls(codec, aic34_rx51_controls,
+ err = snd_soc_add_card_controls(rtd->card, aic34_rx51_controls,
ARRAY_SIZE(aic34_rx51_controls));
if (err < 0)
return err;
@@ -331,12 +313,10 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
return err;
snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
- err = omap_mcbsp_st_add_controls(codec, 1);
+ err = omap_mcbsp_st_add_controls(rtd);
if (err < 0)
return err;
- snd_soc_dapm_sync(dapm);
-
/* AV jack detection */
err = snd_soc_jack_new(codec, "AV Jack",
SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
@@ -354,7 +334,7 @@ static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm)
{
int err;
- err = snd_soc_add_controls(dapm->codec, aic34_rx51_controlsb,
+ err = snd_soc_add_card_controls(dapm->card, aic34_rx51_controlsb,
ARRAY_SIZE(aic34_rx51_controlsb));
if (err < 0)
return err;
@@ -373,16 +353,18 @@ static struct snd_soc_dai_link rx51_dai[] = {
{
.name = "TLV320AIC34",
.stream_name = "AIC34",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "tlv320aic3x-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "tlv320aic3x-codec.2-0018",
+ .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.init = rx51_aic34_init,
.ops = &rx51_ops,
},
};
-struct snd_soc_aux_dev rx51_aux_dev[] = {
+static struct snd_soc_aux_dev rx51_aux_dev[] = {
{
.name = "TLV320AIC34b",
.codec_name = "tlv320aic3x-codec.2-0019",
@@ -400,6 +382,7 @@ static struct snd_soc_codec_conf rx51_codec_conf[] = {
/* Audio card */
static struct snd_soc_card rx51_sound_card = {
.name = "RX-51",
+ .owner = THIS_MODULE,
.dai_link = rx51_dai,
.num_links = ARRAY_SIZE(rx51_dai),
.aux_dev = rx51_aux_dev,
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
index 9f6a758029d1..0e283226e2bf 100644
--- a/sound/soc/omap/sdp3430.c
+++ b/sound/soc/omap/sdp3430.c
@@ -37,6 +37,7 @@
/* Register descriptions for twl4030 codec part */
#include <linux/mfd/twl4030-audio.h>
+#include <linux/module.h>
#include "omap-mcbsp.h"
#include "omap-pcm.h"
@@ -53,29 +54,8 @@ static int sdp3430_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret;
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
SND_SOC_CLOCK_IN);
@@ -91,49 +71,6 @@ static struct snd_soc_ops sdp3430_ops = {
.hw_params = sdp3430_hw_params,
};
-static int sdp3430_hw_voice_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret;
-
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
- /* Set the codec system clock for DAC and ADC */
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec system clock\n");
- return ret;
- }
-
- return 0;
-}
-
-static struct snd_soc_ops sdp3430_voice_ops = {
- .hw_params = sdp3430_hw_voice_params,
-};
-
/* Headset jack */
static struct snd_soc_jack hs_jack;
@@ -193,15 +130,6 @@ static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
- /* Add SDP3430 specific widgets */
- ret = snd_soc_dapm_new_controls(dapm, sdp3430_twl4030_dapm_widgets,
- ARRAY_SIZE(sdp3430_twl4030_dapm_widgets));
- if (ret)
- return ret;
-
- /* Set up SDP3430 specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
/* SDP3430 connected pins */
snd_soc_dapm_enable_pin(dapm, "Ext Mic");
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
@@ -223,10 +151,6 @@ static int sdp3430_twl4030_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "CARKITL");
snd_soc_dapm_nc_pin(dapm, "CARKITR");
- ret = snd_soc_dapm_sync(dapm);
- if (ret)
- return ret;
-
/* Headset jack detection */
ret = snd_soc_jack_new(codec, "Headset Jack",
SND_JACK_HEADSET, &hs_jack);
@@ -263,30 +187,40 @@ static struct snd_soc_dai_link sdp3430_dai[] = {
{
.name = "TWL4030 I2S",
.stream_name = "TWL4030 Audio",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.init = sdp3430_twl4030_init,
.ops = &sdp3430_ops,
},
{
.name = "TWL4030 PCM",
.stream_name = "TWL4030 Voice",
- .cpu_dai_name = "omap-mcbsp-dai.2",
+ .cpu_dai_name = "omap-mcbsp.3",
.codec_dai_name = "twl4030-voice",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
+ .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.init = sdp3430_twl4030_voice_init,
- .ops = &sdp3430_voice_ops,
+ .ops = &sdp3430_ops,
},
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_sdp3430 = {
.name = "SDP3430",
+ .owner = THIS_MODULE,
.dai_link = sdp3430_dai,
.num_links = ARRAY_SIZE(sdp3430_dai),
+
+ .dapm_widgets = sdp3430_twl4030_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(sdp3430_twl4030_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
};
static struct platform_device *sdp3430_snd_device;
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
deleted file mode 100644
index b80efb02bfca..000000000000
--- a/sound/soc/omap/sdp4430.c
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * sdp4430.c -- SoC audio for TI OMAP4430 SDP
- *
- * Author: Misael Lopez Cruz <x0052729@ti.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/twl6040.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/jack.h>
-
-#include <asm/mach-types.h>
-#include <plat/hardware.h>
-#include <plat/mux.h>
-
-#include "mcpdm.h"
-#include "omap-pcm.h"
-#include "../codecs/twl6040.h"
-
-static int sdp4430_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- int clk_id, freq;
- int ret;
-
- clk_id = twl6040_get_clk_id(rtd->codec);
- if (clk_id == TWL6040_SYSCLK_SEL_HPPLL)
- freq = 38400000;
- else if (clk_id == TWL6040_SYSCLK_SEL_LPPLL)
- freq = 32768;
- else
- return -EINVAL;
-
- /* set the codec mclk */
- ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
- SND_SOC_CLOCK_IN);
- if (ret) {
- printk(KERN_ERR "can't set codec system clock\n");
- return ret;
- }
- return ret;
-}
-
-static struct snd_soc_ops sdp4430_ops = {
- .hw_params = sdp4430_hw_params,
-};
-
-/* Headset jack */
-static struct snd_soc_jack hs_jack;
-
-/*Headset jack detection DAPM pins */
-static struct snd_soc_jack_pin hs_jack_pins[] = {
- {
- .pin = "Headset Mic",
- .mask = SND_JACK_MICROPHONE,
- },
- {
- .pin = "Headset Stereophone",
- .mask = SND_JACK_HEADPHONE,
- },
-};
-
-/* SDP4430 machine DAPM */
-static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
- SND_SOC_DAPM_MIC("Ext Mic", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
- SND_SOC_DAPM_MIC("Headset Mic", NULL),
- SND_SOC_DAPM_HP("Headset Stereophone", NULL),
- SND_SOC_DAPM_SPK("Earphone Spk", NULL),
- SND_SOC_DAPM_INPUT("Aux/FM Stereo In"),
-};
-
-static const struct snd_soc_dapm_route audio_map[] = {
- /* External Mics: MAINMIC, SUBMIC with bias*/
- {"MAINMIC", NULL, "Main Mic Bias"},
- {"SUBMIC", NULL, "Main Mic Bias"},
- {"Main Mic Bias", NULL, "Ext Mic"},
-
- /* External Speakers: HFL, HFR */
- {"Ext Spk", NULL, "HFL"},
- {"Ext Spk", NULL, "HFR"},
-
- /* Headset Mic: HSMIC with bias */
- {"HSMIC", NULL, "Headset Mic Bias"},
- {"Headset Mic Bias", NULL, "Headset Mic"},
-
- /* Headset Stereophone (Headphone): HSOL, HSOR */
- {"Headset Stereophone", NULL, "HSOL"},
- {"Headset Stereophone", NULL, "HSOR"},
-
- /* Earphone speaker */
- {"Earphone Spk", NULL, "EP"},
-
- /* Aux/FM Stereo In: AFML, AFMR */
- {"AFML", NULL, "Aux/FM Stereo In"},
- {"AFMR", NULL, "Aux/FM Stereo In"},
-};
-
-static int sdp4430_twl6040_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_codec *codec = rtd->codec;
- struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret;
-
- /* Add SDP4430 specific widgets */
- ret = snd_soc_dapm_new_controls(dapm, sdp4430_twl6040_dapm_widgets,
- ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
- if (ret)
- return ret;
-
- /* Set up SDP4430 specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- /* SDP4430 connected pins */
- snd_soc_dapm_enable_pin(dapm, "Ext Mic");
- snd_soc_dapm_enable_pin(dapm, "Ext Spk");
- snd_soc_dapm_enable_pin(dapm, "AFML");
- snd_soc_dapm_enable_pin(dapm, "AFMR");
- snd_soc_dapm_enable_pin(dapm, "Headset Mic");
- snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
-
- ret = snd_soc_dapm_sync(dapm);
- if (ret)
- return ret;
-
- /* Headset jack detection */
- ret = snd_soc_jack_new(codec, "Headset Jack",
- SND_JACK_HEADSET, &hs_jack);
- if (ret)
- return ret;
-
- ret = snd_soc_jack_add_pins(&hs_jack, ARRAY_SIZE(hs_jack_pins),
- hs_jack_pins);
-
- if (machine_is_omap_4430sdp())
- twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET);
- else
- snd_soc_jack_report(&hs_jack, SND_JACK_HEADSET, SND_JACK_HEADSET);
-
- return ret;
-}
-
-/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link sdp4430_dai = {
- .name = "TWL6040",
- .stream_name = "TWL6040",
- .cpu_dai_name ="omap-mcpdm-dai",
- .codec_dai_name = "twl6040-hifi",
- .platform_name = "omap-pcm-audio",
- .codec_name = "twl6040-codec",
- .init = sdp4430_twl6040_init,
- .ops = &sdp4430_ops,
-};
-
-/* Audio machine driver */
-static struct snd_soc_card snd_soc_sdp4430 = {
- .name = "SDP4430",
- .dai_link = &sdp4430_dai,
- .num_links = 1,
-};
-
-static struct platform_device *sdp4430_snd_device;
-
-static int __init sdp4430_soc_init(void)
-{
- int ret;
-
- if (!machine_is_omap_4430sdp())
- return -ENODEV;
- printk(KERN_INFO "SDP4430 SoC init\n");
-
- sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
- if (!sdp4430_snd_device) {
- printk(KERN_ERR "Platform device allocation failed\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(sdp4430_snd_device, &snd_soc_sdp4430);
-
- ret = platform_device_add(sdp4430_snd_device);
- if (ret)
- goto err;
-
- return 0;
-
-err:
- printk(KERN_ERR "Unable to add platform device\n");
- platform_device_put(sdp4430_snd_device);
- return ret;
-}
-module_init(sdp4430_soc_init);
-
-static void __exit sdp4430_soc_exit(void)
-{
- platform_device_unregister(sdp4430_snd_device);
-}
-module_exit(sdp4430_soc_exit);
-
-MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
-MODULE_DESCRIPTION("ALSA SoC SDP4430");
-MODULE_LICENSE("GPL");
-
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c
index 9a2666ffc16c..920e0d9e03db 100644
--- a/sound/soc/omap/zoom2.c
+++ b/sound/soc/omap/zoom2.c
@@ -33,6 +33,7 @@
/* Register descriptions for twl4030 codec part */
#include <linux/mfd/twl4030-audio.h>
+#include <linux/module.h>
#include "omap-mcbsp.h"
#include "omap-pcm.h"
@@ -44,29 +45,8 @@ static int zoom2_hw_params(struct snd_pcm_substream *substream,
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret;
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
/* Set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
SND_SOC_CLOCK_IN);
@@ -82,49 +62,6 @@ static struct snd_soc_ops zoom2_ops = {
.hw_params = zoom2_hw_params,
};
-static int zoom2_hw_voice_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret;
-
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_DSP_A |
- SND_SOC_DAIFMT_IB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
- /* Set the codec system clock for DAC and ADC */
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec system clock\n");
- return ret;
- }
-
- return 0;
-}
-
-static struct snd_soc_ops zoom2_voice_ops = {
- .hw_params = zoom2_hw_voice_params,
-};
-
/* Zoom2 machine DAPM */
static const struct snd_soc_dapm_widget zoom2_twl4030_dapm_widgets[] = {
SND_SOC_DAPM_MIC("Ext Mic", NULL),
@@ -162,23 +99,6 @@ static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret;
-
- /* Add Zoom2 specific widgets */
- ret = snd_soc_dapm_new_controls(dapm, zoom2_twl4030_dapm_widgets,
- ARRAY_SIZE(zoom2_twl4030_dapm_widgets));
- if (ret)
- return ret;
-
- /* Set up Zoom2 specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- /* Zoom2 connected pins */
- snd_soc_dapm_enable_pin(dapm, "Ext Mic");
- snd_soc_dapm_enable_pin(dapm, "Ext Spk");
- snd_soc_dapm_enable_pin(dapm, "Headset Mic");
- snd_soc_dapm_enable_pin(dapm, "Headset Stereophone");
- snd_soc_dapm_enable_pin(dapm, "Aux In");
/* TWL4030 not connected pins */
snd_soc_dapm_nc_pin(dapm, "CARKITMIC");
@@ -190,9 +110,7 @@ static int zoom2_twl4030_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "CARKITL");
snd_soc_dapm_nc_pin(dapm, "CARKITR");
- ret = snd_soc_dapm_sync(dapm);
-
- return ret;
+ return 0;
}
static int zoom2_twl4030_voice_init(struct snd_soc_pcm_runtime *rtd)
@@ -213,30 +131,40 @@ static struct snd_soc_dai_link zoom2_dai[] = {
{
.name = "TWL4030 I2S",
.stream_name = "TWL4030 Audio",
- .cpu_dai_name = "omap-mcbsp-dai.1",
+ .cpu_dai_name = "omap-mcbsp.2",
.codec_dai_name = "twl4030-hifi",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.init = zoom2_twl4030_init,
.ops = &zoom2_ops,
},
{
.name = "TWL4030 PCM",
.stream_name = "TWL4030 Voice",
- .cpu_dai_name = "omap-mcbsp-dai.2",
+ .cpu_dai_name = "omap-mcbsp.3",
.codec_dai_name = "twl4030-voice",
.platform_name = "omap-pcm-audio",
.codec_name = "twl4030-codec",
+ .dai_fmt = SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.init = zoom2_twl4030_voice_init,
- .ops = &zoom2_voice_ops,
+ .ops = &zoom2_ops,
},
};
/* Audio machine driver */
static struct snd_soc_card snd_soc_zoom2 = {
.name = "Zoom2",
+ .owner = THIS_MODULE,
.dai_link = zoom2_dai,
.num_links = ARRAY_SIZE(zoom2_dai),
+
+ .dapm_widgets = zoom2_twl4030_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(zoom2_twl4030_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
};
static struct platform_device *zoom2_snd_device;
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index 33ebc46b45b5..a0f7d3cfa470 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -121,6 +121,7 @@ config SND_PXA2XX_SOC_PALM27X
config SND_SOC_SAARB
tristate "SoC Audio support for Marvell Saarb"
depends on SND_PXA2XX_SOC && MACH_SAARB
+ select MFD_88PM860X
select SND_PXA_SOC_SSP
select SND_SOC_88PM860X
help
@@ -130,6 +131,7 @@ config SND_SOC_SAARB
config SND_SOC_TAVOREVB3
tristate "SoC Audio support for Marvell Tavor EVB3"
depends on SND_PXA2XX_SOC && MACH_TAVOREVB3
+ select MFD_88PM860X
select SND_PXA_SOC_SSP
select SND_SOC_88PM860X
help
@@ -149,6 +151,7 @@ config SND_SOC_ZYLONITE
config SND_SOC_RAUMFELD
tristate "SoC Audio support Raumfeld audio adapter"
depends on SND_PXA2XX_SOC && (MACH_RAUMFELD_SPEAKER || MACH_RAUMFELD_CONNECTOR)
+ depends on I2C && SPI_MASTER
select SND_PXA_SOC_SSP
select SND_SOC_CS4270
select SND_SOC_AK4104
@@ -157,7 +160,7 @@ config SND_SOC_RAUMFELD
config SND_PXA2XX_SOC_HX4700
tristate "SoC Audio support for HP iPAQ hx4700"
- depends on SND_PXA2XX_SOC && MACH_H4700
+ depends on SND_PXA2XX_SOC && MACH_H4700 && I2C
select SND_PXA2XX_SOC_I2S
select SND_SOC_AK4641
help
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 28757fb9df31..863367ad89ce 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -45,10 +45,8 @@
static int corgi_jack_func;
static int corgi_spk_func;
-static void corgi_ext_control(struct snd_soc_codec *codec)
+static void corgi_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
/* set up jack connection */
switch (corgi_jack_func) {
case CORGI_HP:
@@ -104,7 +102,7 @@ static int corgi_startup(struct snd_pcm_substream *substream)
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */
- corgi_ext_control(codec);
+ corgi_ext_control(&codec->dapm);
mutex_unlock(&codec->mutex);
@@ -142,18 +140,6 @@ static int corgi_hw_params(struct snd_pcm_substream *substream,
break;
}
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
/* set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
SND_SOC_CLOCK_IN);
@@ -185,13 +171,13 @@ static int corgi_get_jack(struct snd_kcontrol *kcontrol,
static int corgi_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (corgi_jack_func == ucontrol->value.integer.value[0])
return 0;
corgi_jack_func = ucontrol->value.integer.value[0];
- corgi_ext_control(codec);
+ corgi_ext_control(&card->dapm);
return 1;
}
@@ -205,13 +191,13 @@ static int corgi_get_spk(struct snd_kcontrol *kcontrol,
static int corgi_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (corgi_spk_func == ucontrol->value.integer.value[0])
return 0;
corgi_spk_func = ucontrol->value.integer.value[0];
- corgi_ext_control(codec);
+ corgi_ext_control(&card->dapm);
return 1;
}
@@ -239,7 +225,7 @@ SND_SOC_DAPM_HP("Headset Jack", NULL),
};
/* Corgi machine audio map (connections to the codec pins) */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route corgi_audio_map[] = {
/* headset Jack - in = micin, out = LHPOUT*/
{"Headset Jack", NULL, "LHPOUT"},
@@ -281,25 +267,10 @@ static int corgi_wm8731_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int err;
snd_soc_dapm_nc_pin(dapm, "LLINEIN");
snd_soc_dapm_nc_pin(dapm, "RLINEIN");
- /* Add corgi specific controls */
- err = snd_soc_add_controls(codec, wm8731_corgi_controls,
- ARRAY_SIZE(wm8731_corgi_controls));
- if (err < 0)
- return err;
-
- /* Add corgi specific widgets */
- snd_soc_dapm_new_controls(dapm, wm8731_dapm_widgets,
- ARRAY_SIZE(wm8731_dapm_widgets));
-
- /* Set up corgi specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -312,48 +283,61 @@ static struct snd_soc_dai_link corgi_dai = {
.platform_name = "pxa-pcm-audio",
.codec_name = "wm8731.0-001b",
.init = corgi_wm8731_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &corgi_ops,
};
/* corgi audio machine driver */
-static struct snd_soc_card snd_soc_corgi = {
+static struct snd_soc_card corgi = {
.name = "Corgi",
+ .owner = THIS_MODULE,
.dai_link = &corgi_dai,
.num_links = 1,
-};
-static struct platform_device *corgi_snd_device;
+ .controls = wm8731_corgi_controls,
+ .num_controls = ARRAY_SIZE(wm8731_corgi_controls),
+ .dapm_widgets = wm8731_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
+ .dapm_routes = corgi_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(corgi_audio_map),
+};
-static int __init corgi_init(void)
+static int __devinit corgi_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &corgi;
int ret;
- if (!(machine_is_corgi() || machine_is_shepherd() ||
- machine_is_husky()))
- return -ENODEV;
-
- corgi_snd_device = platform_device_alloc("soc-audio", -1);
- if (!corgi_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(corgi_snd_device, &snd_soc_corgi);
- ret = platform_device_add(corgi_snd_device);
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
if (ret)
- platform_device_put(corgi_snd_device);
-
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
return ret;
}
-static void __exit corgi_exit(void)
+static int __devexit corgi_remove(struct platform_device *pdev)
{
- platform_device_unregister(corgi_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(corgi_init);
-module_exit(corgi_exit);
+static struct platform_driver corgi_driver = {
+ .driver = {
+ .name = "corgi-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = corgi_probe,
+ .remove = __devexit_p(corgi_remove),
+};
+
+module_platform_driver(corgi_driver);
/* Module information */
MODULE_AUTHOR("Richard Purdie");
MODULE_DESCRIPTION("ALSA SoC Corgi");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:corgi-audio");
diff --git a/sound/soc/pxa/e740_wm9705.c b/sound/soc/pxa/e740_wm9705.c
index dc65650a6fa1..7b1bc2390039 100644
--- a/sound/soc/pxa/e740_wm9705.c
+++ b/sound/soc/pxa/e740_wm9705.c
@@ -108,8 +108,6 @@ static int e740_ac97_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -135,78 +133,60 @@ static struct snd_soc_dai_link e740_dai[] = {
static struct snd_soc_card e740 = {
.name = "Toshiba e740",
+ .owner = THIS_MODULE,
.dai_link = e740_dai,
.num_links = ARRAY_SIZE(e740_dai),
};
-static struct platform_device *e740_snd_device;
+static struct gpio e740_audio_gpios[] = {
+ { GPIO_E740_MIC_ON, GPIOF_OUT_INIT_LOW, "Mic amp" },
+ { GPIO_E740_AMP_ON, GPIOF_OUT_INIT_LOW, "Output amp" },
+ { GPIO_E740_WM9705_nAVDD2, GPIOF_OUT_INIT_HIGH, "Audio power" },
+};
-static int __init e740_init(void)
+static int __devinit e740_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &e740;
int ret;
- if (!machine_is_e740())
- return -ENODEV;
-
- ret = gpio_request(GPIO_E740_MIC_ON, "Mic amp");
+ ret = gpio_request_array(e740_audio_gpios,
+ ARRAY_SIZE(e740_audio_gpios));
if (ret)
return ret;
- ret = gpio_request(GPIO_E740_AMP_ON, "Output amp");
- if (ret)
- goto free_mic_amp_gpio;
-
- ret = gpio_request(GPIO_E740_WM9705_nAVDD2, "Audio power");
- if (ret)
- goto free_op_amp_gpio;
-
- /* Disable audio */
- ret = gpio_direction_output(GPIO_E740_MIC_ON, 0);
- if (ret)
- goto free_apwr_gpio;
- ret = gpio_direction_output(GPIO_E740_AMP_ON, 0);
- if (ret)
- goto free_apwr_gpio;
- ret = gpio_direction_output(GPIO_E740_WM9705_nAVDD2, 1);
- if (ret)
- goto free_apwr_gpio;
+ card->dev = &pdev->dev;
- e740_snd_device = platform_device_alloc("soc-audio", -1);
- if (!e740_snd_device) {
- ret = -ENOMEM;
- goto free_apwr_gpio;
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ gpio_free_array(e740_audio_gpios, ARRAY_SIZE(e740_audio_gpios));
}
-
- platform_set_drvdata(e740_snd_device, &e740);
- ret = platform_device_add(e740_snd_device);
-
- if (!ret)
- return 0;
-
-/* Fail gracefully */
- platform_device_put(e740_snd_device);
-free_apwr_gpio:
- gpio_free(GPIO_E740_WM9705_nAVDD2);
-free_op_amp_gpio:
- gpio_free(GPIO_E740_AMP_ON);
-free_mic_amp_gpio:
- gpio_free(GPIO_E740_MIC_ON);
-
return ret;
}
-static void __exit e740_exit(void)
+static int __devexit e740_remove(struct platform_device *pdev)
{
- platform_device_unregister(e740_snd_device);
- gpio_free(GPIO_E740_WM9705_nAVDD2);
- gpio_free(GPIO_E740_AMP_ON);
- gpio_free(GPIO_E740_MIC_ON);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ gpio_free_array(e740_audio_gpios, ARRAY_SIZE(e740_audio_gpios));
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(e740_init);
-module_exit(e740_exit);
+static struct platform_driver e740_driver = {
+ .driver = {
+ .name = "e740-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = e740_probe,
+ .remove = __devexit_p(e740_remove),
+};
+
+module_platform_driver(e740_driver);
/* Module information */
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("ALSA SoC driver for e740");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:e740-audio");
diff --git a/sound/soc/pxa/e750_wm9705.c b/sound/soc/pxa/e750_wm9705.c
index 51897fcd911b..47b89d71e287 100644
--- a/sound/soc/pxa/e750_wm9705.c
+++ b/sound/soc/pxa/e750_wm9705.c
@@ -90,8 +90,6 @@ static int e750_ac97_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -118,68 +116,59 @@ static struct snd_soc_dai_link e750_dai[] = {
static struct snd_soc_card e750 = {
.name = "Toshiba e750",
+ .owner = THIS_MODULE,
.dai_link = e750_dai,
.num_links = ARRAY_SIZE(e750_dai),
};
-static struct platform_device *e750_snd_device;
+static struct gpio e750_audio_gpios[] = {
+ { GPIO_E750_HP_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Headphone amp" },
+ { GPIO_E750_SPK_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" },
+};
-static int __init e750_init(void)
+static int __devinit e750_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &e750;
int ret;
- if (!machine_is_e750())
- return -ENODEV;
-
- ret = gpio_request(GPIO_E750_HP_AMP_OFF, "Headphone amp");
+ ret = gpio_request_array(e750_audio_gpios,
+ ARRAY_SIZE(e750_audio_gpios));
if (ret)
return ret;
- ret = gpio_request(GPIO_E750_SPK_AMP_OFF, "Speaker amp");
- if (ret)
- goto free_hp_amp_gpio;
+ card->dev = &pdev->dev;
- ret = gpio_direction_output(GPIO_E750_HP_AMP_OFF, 1);
- if (ret)
- goto free_spk_amp_gpio;
-
- ret = gpio_direction_output(GPIO_E750_SPK_AMP_OFF, 1);
- if (ret)
- goto free_spk_amp_gpio;
-
- e750_snd_device = platform_device_alloc("soc-audio", -1);
- if (!e750_snd_device) {
- ret = -ENOMEM;
- goto free_spk_amp_gpio;
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ gpio_free_array(e750_audio_gpios, ARRAY_SIZE(e750_audio_gpios));
}
-
- platform_set_drvdata(e750_snd_device, &e750);
- ret = platform_device_add(e750_snd_device);
-
- if (!ret)
- return 0;
-
-/* Fail gracefully */
- platform_device_put(e750_snd_device);
-free_spk_amp_gpio:
- gpio_free(GPIO_E750_SPK_AMP_OFF);
-free_hp_amp_gpio:
- gpio_free(GPIO_E750_HP_AMP_OFF);
-
return ret;
}
-static void __exit e750_exit(void)
+static int __devexit e750_remove(struct platform_device *pdev)
{
- platform_device_unregister(e750_snd_device);
- gpio_free(GPIO_E750_SPK_AMP_OFF);
- gpio_free(GPIO_E750_HP_AMP_OFF);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ gpio_free_array(e750_audio_gpios, ARRAY_SIZE(e750_audio_gpios));
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(e750_init);
-module_exit(e750_exit);
+static struct platform_driver e750_driver = {
+ .driver = {
+ .name = "e750-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = e750_probe,
+ .remove = __devexit_p(e750_remove),
+};
+
+module_platform_driver(e750_driver);
/* Module information */
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("ALSA SoC driver for e750");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:e750-audio");
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index 053ed208e59f..ea9707ec6f28 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -80,7 +80,6 @@ static int e800_ac97_init(struct snd_soc_pcm_runtime *rtd)
ARRAY_SIZE(e800_dapm_widgets));
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -107,66 +106,59 @@ static struct snd_soc_dai_link e800_dai[] = {
static struct snd_soc_card e800 = {
.name = "Toshiba e800",
+ .owner = THIS_MODULE,
.dai_link = e800_dai,
.num_links = ARRAY_SIZE(e800_dai),
};
-static struct platform_device *e800_snd_device;
+static struct gpio e800_audio_gpios[] = {
+ { GPIO_E800_SPK_AMP_ON, GPIOF_OUT_INIT_HIGH, "Headphone amp" },
+ { GPIO_E800_HP_AMP_OFF, GPIOF_OUT_INIT_HIGH, "Speaker amp" },
+};
-static int __init e800_init(void)
+static int __devinit e800_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &e800;
int ret;
- if (!machine_is_e800())
- return -ENODEV;
-
- ret = gpio_request(GPIO_E800_HP_AMP_OFF, "Headphone amp");
+ ret = gpio_request_array(e800_audio_gpios,
+ ARRAY_SIZE(e800_audio_gpios));
if (ret)
return ret;
- ret = gpio_request(GPIO_E800_SPK_AMP_ON, "Speaker amp");
- if (ret)
- goto free_hp_amp_gpio;
-
- ret = gpio_direction_output(GPIO_E800_HP_AMP_OFF, 1);
- if (ret)
- goto free_spk_amp_gpio;
-
- ret = gpio_direction_output(GPIO_E800_SPK_AMP_ON, 1);
- if (ret)
- goto free_spk_amp_gpio;
-
- e800_snd_device = platform_device_alloc("soc-audio", -1);
- if (!e800_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(e800_snd_device, &e800);
- ret = platform_device_add(e800_snd_device);
-
- if (!ret)
- return 0;
-
-/* Fail gracefully */
- platform_device_put(e800_snd_device);
-free_spk_amp_gpio:
- gpio_free(GPIO_E800_SPK_AMP_ON);
-free_hp_amp_gpio:
- gpio_free(GPIO_E800_HP_AMP_OFF);
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ gpio_free_array(e800_audio_gpios, ARRAY_SIZE(e800_audio_gpios));
+ }
return ret;
}
-static void __exit e800_exit(void)
+static int __devexit e800_remove(struct platform_device *pdev)
{
- platform_device_unregister(e800_snd_device);
- gpio_free(GPIO_E800_SPK_AMP_ON);
- gpio_free(GPIO_E800_HP_AMP_OFF);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ gpio_free_array(e800_audio_gpios, ARRAY_SIZE(e800_audio_gpios));
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(e800_init);
-module_exit(e800_exit);
+static struct platform_driver e800_driver = {
+ .driver = {
+ .name = "e800-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = e800_probe,
+ .remove = __devexit_p(e800_remove),
+};
+
+module_platform_driver(e800_driver);
/* Module information */
MODULE_AUTHOR("Ian Molton <spyro@f2s.com>");
MODULE_DESCRIPTION("ALSA SoC driver for e800");
MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:e800-audio");
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index b13a4252812d..64743a05aeae 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -54,6 +54,7 @@ static struct snd_soc_dai_link em_x270_dai[] = {
static struct snd_soc_card em_x270 = {
.name = "EM-X270",
+ .owner = THIS_MODULE,
.dai_link = em_x270_dai,
.num_links = ARRAY_SIZE(em_x270_dai),
};
diff --git a/sound/soc/pxa/hx4700.c b/sound/soc/pxa/hx4700.c
index 65c124831a00..2a342c92d829 100644
--- a/sound/soc/pxa/hx4700.c
+++ b/sound/soc/pxa/hx4700.c
@@ -65,20 +65,6 @@ static int hx4700_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int ret = 0;
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
/* set the I2S system clock as output */
ret = snd_soc_dai_set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
SND_SOC_CLOCK_OUT);
@@ -175,12 +161,15 @@ static struct snd_soc_dai_link hx4700_dai = {
.platform_name = "pxa-pcm-audio",
.codec_name = "ak4641.0-0012",
.init = hx4700_ak4641_init,
+ .dai_fmt = SND_SOC_DAIFMT_MSB | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &hx4700_ops,
};
/* hx4700 audio machine driver */
static struct snd_soc_card snd_soc_card_hx4700 = {
.name = "iPAQ hx4700",
+ .owner = THIS_MODULE,
.dai_link = &hx4700_dai,
.num_links = 1,
.dapm_widgets = hx4700_dapm_widgets,
@@ -209,9 +198,10 @@ static int __devinit hx4700_audio_probe(struct platform_device *pdev)
snd_soc_card_hx4700.dev = &pdev->dev;
ret = snd_soc_register_card(&snd_soc_card_hx4700);
if (ret)
- return ret;
+ gpio_free_array(hx4700_audio_gpios,
+ ARRAY_SIZE(hx4700_audio_gpios));
- return 0;
+ return ret;
}
static int __devexit hx4700_audio_remove(struct platform_device *pdev)
@@ -236,18 +226,7 @@ static struct platform_driver hx4700_audio_driver = {
.remove = __devexit_p(hx4700_audio_remove),
};
-static int __init hx4700_modinit(void)
-{
- return platform_driver_register(&hx4700_audio_driver);
-}
-module_init(hx4700_modinit);
-
-static void __exit hx4700_modexit(void)
-{
- platform_driver_unregister(&hx4700_audio_driver);
-}
-
-module_exit(hx4700_modexit);
+module_platform_driver(hx4700_audio_driver);
MODULE_AUTHOR("Philipp Zabel");
MODULE_DESCRIPTION("ALSA SoC iPAQ hx4700");
diff --git a/sound/soc/pxa/imote2.c b/sound/soc/pxa/imote2.c
index 154fc6f23438..b93dafd32b80 100644
--- a/sound/soc/pxa/imote2.c
+++ b/sound/soc/pxa/imote2.c
@@ -30,20 +30,6 @@ static int imote2_asoc_hw_params(struct snd_pcm_substream *substream,
break;
}
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
- | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /* CPU should be clock master */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
- | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
SND_SOC_CLOCK_IN);
if (ret < 0)
@@ -67,42 +53,52 @@ static struct snd_soc_dai_link imote2_dai = {
.codec_dai_name = "wm8940-hifi",
.platform_name = "pxa-pcm-audio",
.codec_name = "wm8940-codec.0-0034",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &imote2_asoc_ops,
};
-static struct snd_soc_card snd_soc_imote2 = {
+static struct snd_soc_card imote2 = {
.name = "Imote2",
+ .owner = THIS_MODULE,
.dai_link = &imote2_dai,
.num_links = 1,
};
-static struct platform_device *imote2_snd_device;
-
-static int __init imote2_asoc_init(void)
+static int __devinit imote2_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &imote2;
int ret;
- if (!machine_is_intelmote2())
- return -ENODEV;
- imote2_snd_device = platform_device_alloc("soc-audio", -1);
- if (!imote2_snd_device)
- return -ENOMEM;
+ card->dev = &pdev->dev;
- platform_set_drvdata(imote2_snd_device, &snd_soc_imote2);
- ret = platform_device_add(imote2_snd_device);
+ ret = snd_soc_register_card(card);
if (ret)
- platform_device_put(imote2_snd_device);
-
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
return ret;
}
-module_init(imote2_asoc_init);
-static void __exit imote2_asoc_exit(void)
+static int __devexit imote2_remove(struct platform_device *pdev)
{
- platform_device_unregister(imote2_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_exit(imote2_asoc_exit);
+
+static struct platform_driver imote2_driver = {
+ .driver = {
+ .name = "imote2-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = imote2_probe,
+ .remove = __devexit_p(imote2_remove),
+};
+
+module_platform_driver(imote2_driver);
MODULE_AUTHOR("Jonathan Cameron");
MODULE_DESCRIPTION("ALSA SoC Imote 2");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:imote2-audio");
diff --git a/sound/soc/pxa/magician.c b/sound/soc/pxa/magician.c
index 67dcc36cd621..aace19e0fe2c 100644
--- a/sound/soc/pxa/magician.c
+++ b/sound/soc/pxa/magician.c
@@ -92,11 +92,10 @@ static int magician_playback_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- unsigned int acps, acds, width, rate;
+ unsigned int acps, acds, width;
unsigned int div4 = PXA_SSP_CLK_SCDB_4;
int ret = 0;
- rate = params_rate(params);
width = snd_pcm_format_physical_width(params_format(params));
/*
@@ -412,7 +411,7 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "VINR");
/* Add magician specific controls */
- err = snd_soc_add_controls(codec, uda1380_magician_controls,
+ err = snd_soc_add_codec_controls(codec, uda1380_magician_controls,
ARRAY_SIZE(uda1380_magician_controls));
if (err < 0)
return err;
@@ -424,7 +423,6 @@ static int magician_uda1380_init(struct snd_soc_pcm_runtime *rtd)
/* Set up magician specific audio path interconnects */
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -454,6 +452,7 @@ static struct snd_soc_dai_link magician_dai[] = {
/* magician audio machine driver */
static struct snd_soc_card snd_soc_card_magician = {
.name = "Magician",
+ .owner = THIS_MODULE,
.dai_link = magician_dai,
.num_links = ARRAY_SIZE(magician_dai),
diff --git a/sound/soc/pxa/mioa701_wm9713.c b/sound/soc/pxa/mioa701_wm9713.c
index 38ca6759907e..9c585af59b5f 100644
--- a/sound/soc/pxa/mioa701_wm9713.c
+++ b/sound/soc/pxa/mioa701_wm9713.c
@@ -151,7 +151,6 @@ static int mioa701_wm9713_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_enable_pin(dapm, "Front Mic");
snd_soc_dapm_enable_pin(dapm, "GSM Line In");
snd_soc_dapm_enable_pin(dapm, "GSM Line Out");
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -182,6 +181,7 @@ static struct snd_soc_dai_link mioa701_dai[] = {
static struct snd_soc_card mioa701 = {
.name = "MioA701",
+ .owner = THIS_MODULE,
.dai_link = mioa701_dai,
.num_links = ARRAY_SIZE(mioa701_dai),
};
@@ -228,18 +228,7 @@ static struct platform_driver mioa701_wm9713_driver = {
},
};
-static int __init mioa701_asoc_init(void)
-{
- return platform_driver_register(&mioa701_wm9713_driver);
-}
-
-static void __exit mioa701_asoc_exit(void)
-{
- platform_driver_unregister(&mioa701_wm9713_driver);
-}
-
-module_init(mioa701_asoc_init);
-module_exit(mioa701_asoc_exit);
+module_platform_driver(mioa701_wm9713_driver);
/* Module information */
MODULE_AUTHOR("Robert Jarzmik (rjarzmik@free.fr)");
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
index 504e4004f004..db24bc685bd3 100644
--- a/sound/soc/pxa/palm27x.c
+++ b/sound/soc/pxa/palm27x.c
@@ -107,10 +107,6 @@ static int palm27x_ac97_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "PHONE");
snd_soc_dapm_nc_pin(dapm, "MIC2");
- err = snd_soc_dapm_sync(dapm);
- if (err)
- return err;
-
/* Jack detection API stuff */
err = snd_soc_jack_new(codec, "Headphone Jack",
SND_JACK_HEADPHONE, &hs_jack);
@@ -150,6 +146,7 @@ static struct snd_soc_dai_link palm27x_dai[] = {
static struct snd_soc_card palm27x_asoc = {
.name = "Palm/PXA27x",
+ .owner = THIS_MODULE,
.dai_link = palm27x_dai,
.num_links = ARRAY_SIZE(palm27x_dai),
};
@@ -205,18 +202,7 @@ static struct platform_driver palm27x_wm9712_driver = {
},
};
-static int __init palm27x_asoc_init(void)
-{
- return platform_driver_register(&palm27x_wm9712_driver);
-}
-
-static void __exit palm27x_asoc_exit(void)
-{
- platform_driver_unregister(&palm27x_wm9712_driver);
-}
-
-module_init(palm27x_asoc_init);
-module_exit(palm27x_asoc_exit);
+module_platform_driver(palm27x_wm9712_driver);
/* Module information */
MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index da3ae4316cf2..d2cc81735036 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -43,10 +43,8 @@
static int poodle_jack_func;
static int poodle_spk_func;
-static void poodle_ext_control(struct snd_soc_codec *codec)
+static void poodle_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
/* set up jack connection */
if (poodle_jack_func == POODLE_HP) {
/* set = unmute headphone */
@@ -81,7 +79,7 @@ static int poodle_startup(struct snd_pcm_substream *substream)
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */
- poodle_ext_control(codec);
+ poodle_ext_control(&codec->dapm);
mutex_unlock(&codec->mutex);
@@ -121,18 +119,6 @@ static int poodle_hw_params(struct snd_pcm_substream *substream,
break;
}
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
/* set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK_XTAL, clk,
SND_SOC_CLOCK_IN);
@@ -164,13 +150,13 @@ static int poodle_get_jack(struct snd_kcontrol *kcontrol,
static int poodle_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (poodle_jack_func == ucontrol->value.integer.value[0])
return 0;
poodle_jack_func = ucontrol->value.integer.value[0];
- poodle_ext_control(codec);
+ poodle_ext_control(&card->dapm);
return 1;
}
@@ -184,13 +170,13 @@ static int poodle_get_spk(struct snd_kcontrol *kcontrol,
static int poodle_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (poodle_spk_func == ucontrol->value.integer.value[0])
return 0;
poodle_spk_func = ucontrol->value.integer.value[0];
- poodle_ext_control(codec);
+ poodle_ext_control(&card->dapm);
return 1;
}
@@ -214,7 +200,7 @@ SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event),
};
/* Corgi machine connections to the codec pins */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route poodle_audio_map[] = {
/* headphone connected to LHPOUT1, RHPOUT1 */
{"Headphone Jack", NULL, "LHPOUT"},
@@ -246,26 +232,11 @@ static int poodle_wm8731_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int err;
snd_soc_dapm_nc_pin(dapm, "LLINEIN");
snd_soc_dapm_nc_pin(dapm, "RLINEIN");
snd_soc_dapm_enable_pin(dapm, "MICIN");
- /* Add poodle specific controls */
- err = snd_soc_add_controls(codec, wm8731_poodle_controls,
- ARRAY_SIZE(wm8731_poodle_controls));
- if (err < 0)
- return err;
-
- /* Add poodle specific widgets */
- snd_soc_dapm_new_controls(dapm, wm8731_dapm_widgets,
- ARRAY_SIZE(wm8731_dapm_widgets));
-
- /* Set up poodle specific audio path audio_map */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -278,26 +249,31 @@ static struct snd_soc_dai_link poodle_dai = {
.platform_name = "pxa-pcm-audio",
.codec_name = "wm8731.0-001b",
.init = poodle_wm8731_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &poodle_ops,
};
/* poodle audio machine driver */
-static struct snd_soc_card snd_soc_poodle = {
+static struct snd_soc_card poodle = {
.name = "Poodle",
.dai_link = &poodle_dai,
.num_links = 1,
.owner = THIS_MODULE,
-};
-static struct platform_device *poodle_snd_device;
+ .controls = wm8731_poodle_controls,
+ .num_controls = ARRAY_SIZE(wm8731_poodle_controls),
+ .dapm_widgets = wm8731_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8731_dapm_widgets),
+ .dapm_routes = poodle_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(poodle_audio_map),
+};
-static int __init poodle_init(void)
+static int __devinit poodle_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &poodle;
int ret;
- if (!machine_is_poodle())
- return -ENODEV;
-
locomo_gpio_set_dir(&poodle_locomo_device.dev,
POODLE_LOCOMO_GPIO_AMP_ON, 0);
/* should we mute HP at startup - burning power ?*/
@@ -306,28 +282,36 @@ static int __init poodle_init(void)
locomo_gpio_set_dir(&poodle_locomo_device.dev,
POODLE_LOCOMO_GPIO_MUTE_R, 0);
- poodle_snd_device = platform_device_alloc("soc-audio", -1);
- if (!poodle_snd_device)
- return -ENOMEM;
-
- platform_set_drvdata(poodle_snd_device, &snd_soc_poodle);
- ret = platform_device_add(poodle_snd_device);
+ card->dev = &pdev->dev;
+ ret = snd_soc_register_card(card);
if (ret)
- platform_device_put(poodle_snd_device);
-
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
return ret;
}
-static void __exit poodle_exit(void)
+static int __devexit poodle_remove(struct platform_device *pdev)
{
- platform_device_unregister(poodle_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(poodle_init);
-module_exit(poodle_exit);
+static struct platform_driver poodle_driver = {
+ .driver = {
+ .name = "poodle-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = poodle_probe,
+ .remove = __devexit_p(poodle_remove),
+};
+
+module_platform_driver(poodle_driver);
/* Module information */
MODULE_AUTHOR("Richard Purdie");
MODULE_DESCRIPTION("ALSA SoC Poodle");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:poodle-audio");
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
index 8ad93ee2e92b..fd04ce139031 100644
--- a/sound/soc/pxa/pxa-ssp.c
+++ b/sound/soc/pxa/pxa-ssp.c
@@ -668,6 +668,38 @@ static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
return 0;
}
+static void pxa_ssp_set_running_bit(struct snd_pcm_substream *substream,
+ struct ssp_device *ssp, int value)
+{
+ uint32_t sscr0 = pxa_ssp_read_reg(ssp, SSCR0);
+ uint32_t sscr1 = pxa_ssp_read_reg(ssp, SSCR1);
+ uint32_t sspsp = pxa_ssp_read_reg(ssp, SSPSP);
+ uint32_t sssr = pxa_ssp_read_reg(ssp, SSSR);
+
+ if (value && (sscr0 & SSCR0_SSE))
+ pxa_ssp_write_reg(ssp, SSCR0, sscr0 & ~SSCR0_SSE);
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ if (value)
+ sscr1 |= SSCR1_TSRE;
+ else
+ sscr1 &= ~SSCR1_TSRE;
+ } else {
+ if (value)
+ sscr1 |= SSCR1_RSRE;
+ else
+ sscr1 &= ~SSCR1_RSRE;
+ }
+
+ pxa_ssp_write_reg(ssp, SSCR1, sscr1);
+
+ if (value) {
+ pxa_ssp_write_reg(ssp, SSSR, sssr);
+ pxa_ssp_write_reg(ssp, SSPSP, sspsp);
+ pxa_ssp_write_reg(ssp, SSCR0, sscr0 | SSCR0_SSE);
+ }
+}
+
static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *cpu_dai)
{
@@ -681,42 +713,21 @@ static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
pxa_ssp_enable(ssp);
break;
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- val = pxa_ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val |= SSCR1_TSRE;
- else
- val |= SSCR1_RSRE;
- pxa_ssp_write_reg(ssp, SSCR1, val);
+ pxa_ssp_set_running_bit(substream, ssp, 1);
val = pxa_ssp_read_reg(ssp, SSSR);
pxa_ssp_write_reg(ssp, SSSR, val);
break;
case SNDRV_PCM_TRIGGER_START:
- val = pxa_ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val |= SSCR1_TSRE;
- else
- val |= SSCR1_RSRE;
- pxa_ssp_write_reg(ssp, SSCR1, val);
- pxa_ssp_enable(ssp);
+ pxa_ssp_set_running_bit(substream, ssp, 1);
break;
case SNDRV_PCM_TRIGGER_STOP:
- val = pxa_ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val &= ~SSCR1_TSRE;
- else
- val &= ~SSCR1_RSRE;
- pxa_ssp_write_reg(ssp, SSCR1, val);
+ pxa_ssp_set_running_bit(substream, ssp, 0);
break;
case SNDRV_PCM_TRIGGER_SUSPEND:
pxa_ssp_disable(ssp);
break;
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- val = pxa_ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val &= ~SSCR1_TSRE;
- else
- val &= ~SSCR1_RSRE;
- pxa_ssp_write_reg(ssp, SSCR1, val);
+ pxa_ssp_set_running_bit(substream, ssp, 0);
break;
default:
@@ -764,14 +775,15 @@ static int pxa_ssp_remove(struct snd_soc_dai *dai)
#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
- SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_64000 | \
SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
SNDRV_PCM_FMTBIT_S24_LE | \
SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops pxa_ssp_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ssp_dai_ops = {
.startup = pxa_ssp_startup,
.shutdown = pxa_ssp_shutdown,
.trigger = pxa_ssp_trigger,
@@ -825,17 +837,7 @@ static struct platform_driver asoc_ssp_driver = {
.remove = __devexit_p(asoc_ssp_remove),
};
-static int __init pxa_ssp_init(void)
-{
- return platform_driver_register(&asoc_ssp_driver);
-}
-module_init(pxa_ssp_init);
-
-static void __exit pxa_ssp_exit(void)
-{
- platform_driver_unregister(&asoc_ssp_driver);
-}
-module_exit(pxa_ssp_exit);
+module_platform_driver(asoc_ssp_driver);
/* Module information */
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index ac51c6d25c42..4800d5fe568d 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -103,7 +103,7 @@ static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
#define pxa2xx_ac97_resume NULL
#endif
-static int pxa2xx_ac97_probe(struct snd_soc_dai *dai)
+static int __devinit pxa2xx_ac97_probe(struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_probe(to_platform_device(dai->dev));
}
@@ -163,15 +163,15 @@ static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000)
-static struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ac97_hifi_dai_ops = {
.hw_params = pxa2xx_ac97_hw_params,
};
-static struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ac97_aux_dai_ops = {
.hw_params = pxa2xx_ac97_hw_aux_params,
};
-static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
+static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
.hw_params = pxa2xx_ac97_hw_mic_params,
};
@@ -179,7 +179,7 @@ static struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = {
* There is only 1 physical AC97 interface for pxa2xx, but it
* has extra fifo's that can be used for aux DACs and ADCs.
*/
-static struct snd_soc_dai_driver pxa_ac97_dai[] = {
+static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = {
{
.name = "pxa2xx-ac97",
.ac97_control = 1,
@@ -244,13 +244,13 @@ static __devinit int pxa2xx_ac97_dev_probe(struct platform_device *pdev)
* driver to do interesting things with the clocking to get us up
* and running.
*/
- return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai,
- ARRAY_SIZE(pxa_ac97_dai));
+ return snd_soc_register_dais(&pdev->dev, pxa_ac97_dai_driver,
+ ARRAY_SIZE(pxa_ac97_dai_driver));
}
static int __devexit pxa2xx_ac97_dev_remove(struct platform_device *pdev)
{
- snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai));
+ snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(pxa_ac97_dai_driver));
return 0;
}
@@ -263,17 +263,7 @@ static struct platform_driver pxa2xx_ac97_driver = {
},
};
-static int __init pxa_ac97_init(void)
-{
- return platform_driver_register(&pxa2xx_ac97_driver);
-}
-module_init(pxa_ac97_init);
-
-static void __exit pxa_ac97_exit(void)
-{
- platform_driver_unregister(&pxa2xx_ac97_driver);
-}
-module_exit(pxa_ac97_exit);
+module_platform_driver(pxa2xx_ac97_driver);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 11be5952a506..609abd51e55f 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -331,7 +331,7 @@ static int pxa2xx_i2s_remove(struct snd_soc_dai *dai)
SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
-static struct snd_soc_dai_ops pxa_i2s_dai_ops = {
+static const struct snd_soc_dai_ops pxa_i2s_dai_ops = {
.startup = pxa2xx_i2s_startup,
.shutdown = pxa2xx_i2s_shutdown,
.trigger = pxa2xx_i2s_trigger,
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index c43060053dd7..fdd6bedef9bd 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -11,6 +11,7 @@
*/
#include <linux/dma-mapping.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/soc.h>
@@ -140,17 +141,7 @@ static struct platform_driver pxa_pcm_driver = {
.remove = __devexit_p(pxa2xx_soc_platform_remove),
};
-static int __init snd_pxa_pcm_init(void)
-{
- return platform_driver_register(&pxa_pcm_driver);
-}
-module_init(snd_pxa_pcm_init);
-
-static void __exit snd_pxa_pcm_exit(void)
-{
- platform_driver_unregister(&pxa_pcm_driver);
-}
-module_exit(snd_pxa_pcm_exit);
+module_platform_driver(pxa_pcm_driver);
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
diff --git a/sound/soc/pxa/raumfeld.c b/sound/soc/pxa/raumfeld.c
index 1a591f1ebfbd..083706595495 100644
--- a/sound/soc/pxa/raumfeld.c
+++ b/sound/soc/pxa/raumfeld.c
@@ -232,7 +232,7 @@ static struct snd_soc_ops raumfeld_ak4104_ops = {
.cpu_dai_name = "pxa-ssp-dai.0", \
.platform_name = "pxa-pcm-audio", \
.codec_dai_name = "cs4270-hifi", \
- .codec_name = "cs4270-codec.0-0048", \
+ .codec_name = "cs4270.0-0048", \
.ops = &raumfeld_cs4270_ops, \
}
@@ -260,6 +260,7 @@ static struct snd_soc_dai_link snd_soc_raumfeld_speaker_dai[] =
static struct snd_soc_card snd_soc_raumfeld_connector = {
.name = "Raumfeld Connector",
+ .owner = THIS_MODULE,
.dai_link = snd_soc_raumfeld_connector_dai,
.num_links = ARRAY_SIZE(snd_soc_raumfeld_connector_dai),
.suspend_post = raumfeld_analog_suspend,
@@ -268,6 +269,7 @@ static struct snd_soc_card snd_soc_raumfeld_connector = {
static struct snd_soc_card snd_soc_raumfeld_speaker = {
.name = "Raumfeld Speaker",
+ .owner = THIS_MODULE,
.dai_link = snd_soc_raumfeld_speaker_dai,
.num_links = ARRAY_SIZE(snd_soc_raumfeld_speaker_dai),
.suspend_post = raumfeld_analog_suspend,
@@ -306,8 +308,10 @@ static int __init raumfeld_audio_init(void)
&snd_soc_raumfeld_connector);
ret = platform_device_add(raumfeld_audio_device);
- if (ret < 0)
+ if (ret < 0) {
+ platform_device_put(raumfeld_audio_device);
return ret;
+ }
raumfeld_enable_audio(true);
return 0;
diff --git a/sound/soc/pxa/saarb.c b/sound/soc/pxa/saarb.c
index 9595189fc681..c34146b776b4 100644
--- a/sound/soc/pxa/saarb.c
+++ b/sound/soc/pxa/saarb.c
@@ -51,7 +51,7 @@ static const struct snd_soc_dapm_widget saarb_dapm_widgets[] = {
};
/* saarb machine audio map */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route saarb_audio_map[] = {
{"Headset Stereophone", NULL, "HS1"},
{"Headset Stereophone", NULL, "HS2"},
@@ -92,15 +92,6 @@ static int saarb_i2s_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
return ret;
@@ -119,25 +110,28 @@ static struct snd_soc_dai_link saarb_dai[] = {
.platform_name = "pxa-pcm-audio",
.codec_name = "88pm860x-codec",
.init = saarb_pm860x_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &saarb_i2s_ops,
},
};
static struct snd_soc_card snd_soc_card_saarb = {
.name = "Saarb",
+ .owner = THIS_MODULE,
.dai_link = saarb_dai,
.num_links = ARRAY_SIZE(saarb_dai),
+
+ .dapm_widgets = saarb_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(saarb_dapm_widgets),
+ .dapm_routes = saarb_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(saarb_audio_map),
};
static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret;
-
- snd_soc_dapm_new_controls(dapm, saarb_dapm_widgets,
- ARRAY_SIZE(saarb_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
/* connected pins */
snd_soc_dapm_enable_pin(dapm, "Ext Speaker");
@@ -146,10 +140,6 @@ static int saarb_pm860x_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
- ret = snd_soc_dapm_sync(dapm);
- if (ret)
- return ret;
-
/* Headset jack detection */
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
| SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index b253d864868a..fc052d8247ff 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -44,10 +44,8 @@ static int spitz_jack_func;
static int spitz_spk_func;
static int spitz_mic_gpio;
-static void spitz_ext_control(struct snd_soc_codec *codec)
+static void spitz_ext_control(struct snd_soc_dapm_context *dapm)
{
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
if (spitz_spk_func == SPITZ_SPK_ON)
snd_soc_dapm_enable_pin(dapm, "Ext Spk");
else
@@ -113,7 +111,7 @@ static int spitz_startup(struct snd_pcm_substream *substream)
mutex_lock(&codec->mutex);
/* check the jack status at stream startup */
- spitz_ext_control(codec);
+ spitz_ext_control(&codec->dapm);
mutex_unlock(&codec->mutex);
@@ -143,18 +141,6 @@ static int spitz_hw_params(struct snd_pcm_substream *substream,
break;
}
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
/* set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
SND_SOC_CLOCK_IN);
@@ -185,13 +171,13 @@ static int spitz_get_jack(struct snd_kcontrol *kcontrol,
static int spitz_set_jack(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (spitz_jack_func == ucontrol->value.integer.value[0])
return 0;
spitz_jack_func = ucontrol->value.integer.value[0];
- spitz_ext_control(codec);
+ spitz_ext_control(&card->dapm);
return 1;
}
@@ -205,13 +191,13 @@ static int spitz_get_spk(struct snd_kcontrol *kcontrol,
static int spitz_set_spk(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
if (spitz_spk_func == ucontrol->value.integer.value[0])
return 0;
spitz_spk_func = ucontrol->value.integer.value[0];
- spitz_ext_control(codec);
+ spitz_ext_control(&card->dapm);
return 1;
}
@@ -234,7 +220,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
};
/* Spitz machine audio_map */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route spitz_audio_map[] = {
/* headphone connected to LOUT1, ROUT1 */
{"Headphone Jack", NULL, "LOUT1"},
@@ -277,7 +263,6 @@ static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int err;
/* NC codec pins */
snd_soc_dapm_nc_pin(dapm, "RINPUT1");
@@ -288,20 +273,6 @@ static int spitz_wm8750_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "OUT3");
snd_soc_dapm_nc_pin(dapm, "MONO1");
- /* Add spitz specific controls */
- err = snd_soc_add_controls(codec, wm8750_spitz_controls,
- ARRAY_SIZE(wm8750_spitz_controls));
- if (err < 0)
- return err;
-
- /* Add spitz specific widgets */
- snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
- ARRAY_SIZE(wm8750_dapm_widgets));
-
- /* Set up spitz specific audio paths */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -312,16 +283,26 @@ static struct snd_soc_dai_link spitz_dai = {
.cpu_dai_name = "pxa2xx-i2s",
.codec_dai_name = "wm8750-hifi",
.platform_name = "pxa-pcm-audio",
- .codec_name = "wm8750-codec.0-001b",
+ .codec_name = "wm8750.0-001b",
.init = spitz_wm8750_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &spitz_ops,
};
/* spitz audio machine driver */
static struct snd_soc_card snd_soc_spitz = {
.name = "Spitz",
+ .owner = THIS_MODULE,
.dai_link = &spitz_dai,
.num_links = 1,
+
+ .controls = wm8750_spitz_controls,
+ .num_controls = ARRAY_SIZE(wm8750_spitz_controls),
+ .dapm_widgets = wm8750_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
+ .dapm_routes = spitz_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(spitz_audio_map),
};
static struct platform_device *spitz_snd_device;
diff --git a/sound/soc/pxa/tavorevb3.c b/sound/soc/pxa/tavorevb3.c
index f881f65ec172..8b5ab8f72726 100644
--- a/sound/soc/pxa/tavorevb3.c
+++ b/sound/soc/pxa/tavorevb3.c
@@ -51,7 +51,7 @@ static const struct snd_soc_dapm_widget evb3_dapm_widgets[] = {
};
/* tavorevb3 machine audio map */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route evb3_audio_map[] = {
{"Headset Stereophone", NULL, "HS1"},
{"Headset Stereophone", NULL, "HS2"},
@@ -92,16 +92,6 @@ static int evb3_i2s_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
return ret;
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
ret = snd_soc_dai_set_tdm_slot(cpu_dai, 3, 3, 2, width);
return ret;
}
@@ -119,25 +109,28 @@ static struct snd_soc_dai_link evb3_dai[] = {
.platform_name = "pxa-pcm-audio",
.codec_name = "88pm860x-codec",
.init = evb3_pm860x_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBM_CFM,
.ops = &evb3_i2s_ops,
},
};
static struct snd_soc_card snd_soc_card_evb3 = {
.name = "Tavor EVB3",
+ .owner = THIS_MODULE,
.dai_link = evb3_dai,
.num_links = ARRAY_SIZE(evb3_dai),
+
+ .dapm_widgets = evb3_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(evb3_dapm_widgets),
+ .dapm_routes = evb3_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(evb3_audio_map),
};
static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int ret;
-
- snd_soc_dapm_new_controls(dapm, evb3_dapm_widgets,
- ARRAY_SIZE(evb3_dapm_widgets));
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
/* connected pins */
snd_soc_dapm_enable_pin(dapm, "Ext Speaker");
@@ -146,10 +139,6 @@ static int evb3_pm860x_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "Headset Mic 2");
snd_soc_dapm_disable_pin(dapm, "Headset Stereophone");
- ret = snd_soc_dapm_sync(dapm);
- if (ret)
- return ret;
-
/* Headset jack detection */
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE
| SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2,
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index 9a2351366957..2aec63f3706a 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -34,8 +34,6 @@
#include "../codecs/wm9712.h"
#include "pxa2xx-ac97.h"
-static struct snd_soc_card tosa;
-
#define TOSA_HP 0
#define TOSA_MIC_INT 1
#define TOSA_HEADSET 2
@@ -199,7 +197,7 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "MONOOUT");
/* add tosa specific controls */
- err = snd_soc_add_controls(codec, tosa_controls,
+ err = snd_soc_add_codec_controls(codec, tosa_controls,
ARRAY_SIZE(tosa_controls));
if (err < 0)
return err;
@@ -211,7 +209,6 @@ static int tosa_ac97_init(struct snd_soc_pcm_runtime *rtd)
/* set up tosa specific audio path audio_map */
snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -237,70 +234,56 @@ static struct snd_soc_dai_link tosa_dai[] = {
},
};
-static int tosa_probe(struct snd_soc_card *card)
-{
- int ret;
-
- ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
- if (ret)
- return ret;
- ret = gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
- if (ret)
- gpio_free(TOSA_GPIO_L_MUTE);
-
- return ret;
-}
-
-static int tosa_remove(struct snd_soc_card *card)
-{
- gpio_free(TOSA_GPIO_L_MUTE);
- return 0;
-}
-
static struct snd_soc_card tosa = {
.name = "Tosa",
+ .owner = THIS_MODULE,
.dai_link = tosa_dai,
.num_links = ARRAY_SIZE(tosa_dai),
- .probe = tosa_probe,
- .remove = tosa_remove,
};
-static struct platform_device *tosa_snd_device;
-
-static int __init tosa_init(void)
+static int __devinit tosa_probe(struct platform_device *pdev)
{
+ struct snd_soc_card *card = &tosa;
int ret;
- if (!machine_is_tosa())
- return -ENODEV;
-
- tosa_snd_device = platform_device_alloc("soc-audio", -1);
- if (!tosa_snd_device) {
- ret = -ENOMEM;
- goto err_alloc;
- }
-
- platform_set_drvdata(tosa_snd_device, &tosa);
- ret = platform_device_add(tosa_snd_device);
-
- if (!ret)
- return 0;
+ ret = gpio_request_one(TOSA_GPIO_L_MUTE, GPIOF_OUT_INIT_LOW,
+ "Headphone Jack");
+ if (ret)
+ return ret;
- platform_device_put(tosa_snd_device);
+ card->dev = &pdev->dev;
-err_alloc:
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ gpio_free(TOSA_GPIO_L_MUTE);
+ }
return ret;
}
-static void __exit tosa_exit(void)
+static int __devexit tosa_remove(struct platform_device *pdev)
{
- platform_device_unregister(tosa_snd_device);
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ gpio_free(TOSA_GPIO_L_MUTE);
+ snd_soc_unregister_card(card);
+ return 0;
}
-module_init(tosa_init);
-module_exit(tosa_exit);
+static struct platform_driver tosa_driver = {
+ .driver = {
+ .name = "tosa-audio",
+ .owner = THIS_MODULE,
+ },
+ .probe = tosa_probe,
+ .remove = __devexit_p(tosa_remove),
+};
+
+module_platform_driver(tosa_driver);
/* Module information */
MODULE_AUTHOR("Richard Purdie");
MODULE_DESCRIPTION("ALSA SoC Tosa");
MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:tosa-audio");
diff --git a/sound/soc/pxa/z2.c b/sound/soc/pxa/z2.c
index d69d9fc32233..76ccb172d0a7 100644
--- a/sound/soc/pxa/z2.c
+++ b/sound/soc/pxa/z2.c
@@ -56,18 +56,6 @@ static int z2_hw_params(struct snd_pcm_substream *substream,
break;
}
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
/* set the codec system clock for DAC and ADC */
ret = snd_soc_dai_set_sysclk(codec_dai, WM8750_SYSCLK, clk,
SND_SOC_CLOCK_IN);
@@ -124,7 +112,7 @@ static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
};
/* Z2 machine audio_map */
-static const struct snd_soc_dapm_route audio_map[] = {
+static const struct snd_soc_dapm_route z2_audio_map[] = {
/* headphone connected to LOUT1, ROUT1 */
{"Headphone Jack", NULL, "LOUT1"},
@@ -154,17 +142,6 @@ static int z2_wm8750_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_disable_pin(dapm, "OUT3");
snd_soc_dapm_disable_pin(dapm, "MONO1");
- /* Add z2 specific widgets */
- snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
- ARRAY_SIZE(wm8750_dapm_widgets));
-
- /* Set up z2 specific audio paths */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
- ret = snd_soc_dapm_sync(dapm);
- if (ret)
- goto err;
-
/* Jack detection API stuff */
ret = snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
&hs_jack);
@@ -198,16 +175,24 @@ static struct snd_soc_dai_link z2_dai = {
.cpu_dai_name = "pxa2xx-i2s",
.codec_dai_name = "wm8750-hifi",
.platform_name = "pxa-pcm-audio",
- .codec_name = "wm8750-codec.0-001b",
+ .codec_name = "wm8750.0-001b",
.init = z2_wm8750_init,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
+ SND_SOC_DAIFMT_CBS_CFS,
.ops = &z2_ops,
};
/* z2 audio machine driver */
static struct snd_soc_card snd_soc_z2 = {
.name = "Z2",
+ .owner = THIS_MODULE,
.dai_link = &z2_dai,
.num_links = 1,
+
+ .dapm_widgets = wm8750_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
+ .dapm_routes = z2_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(z2_audio_map),
};
static struct platform_device *z2_snd_device;
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
index b6445757fc54..ceb656695b0f 100644
--- a/sound/soc/pxa/zylonite.c
+++ b/sound/soc/pxa/zylonite.c
@@ -87,7 +87,6 @@ static int zylonite_wm9713_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_enable_pin(dapm, "Headphone");
snd_soc_dapm_enable_pin(dapm, "Headset Earpiece");
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -196,20 +195,20 @@ static int zylonite_probe(struct snd_soc_card *card)
if (clk_pout) {
pout = clk_get(NULL, "CLK_POUT");
if (IS_ERR(pout)) {
- dev_err(&pdev->dev, "Unable to obtain CLK_POUT: %ld\n",
+ dev_err(card->dev, "Unable to obtain CLK_POUT: %ld\n",
PTR_ERR(pout));
return PTR_ERR(pout);
}
ret = clk_enable(pout);
if (ret != 0) {
- dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
+ dev_err(card->dev, "Unable to enable CLK_POUT: %d\n",
ret);
clk_put(pout);
return ret;
}
- dev_dbg(&pdev->dev, "MCLK enabled at %luHz\n",
+ dev_dbg(card->dev, "MCLK enabled at %luHz\n",
clk_get_rate(pout));
}
@@ -241,7 +240,7 @@ static int zylonite_resume_pre(struct snd_soc_card *card)
if (clk_pout) {
ret = clk_enable(pout);
if (ret != 0)
- dev_err(&pdev->dev, "Unable to enable CLK_POUT: %d\n",
+ dev_err(card->dev, "Unable to enable CLK_POUT: %d\n",
ret);
}
@@ -250,6 +249,7 @@ static int zylonite_resume_pre(struct snd_soc_card *card)
static struct snd_soc_card zylonite = {
.name = "Zylonite",
+ .owner = THIS_MODULE,
.probe = &zylonite_probe,
.remove = &zylonite_remove,
.suspend_post = &zylonite_suspend_post,
diff --git a/sound/soc/s6000/s6000-i2s.c b/sound/soc/s6000/s6000-i2s.c
index 3052f64b2403..aaabdbaec19c 100644
--- a/sound/soc/s6000/s6000-i2s.c
+++ b/sound/soc/s6000/s6000-i2s.c
@@ -409,7 +409,7 @@ static int s6000_i2s_dai_probe(struct snd_soc_dai *dai)
SNDRV_PCM_RATE_8000_192000)
#define S6000_I2S_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE)
-static struct snd_soc_dai_ops s6000_i2s_dai_ops = {
+static const struct snd_soc_dai_ops s6000_i2s_dai_ops = {
.set_fmt = s6000_i2s_set_dai_fmt,
.set_clkdiv = s6000_i2s_set_clkdiv,
.hw_params = s6000_i2s_hw_params,
@@ -604,17 +604,7 @@ static struct platform_driver s6000_i2s_driver = {
},
};
-static int __init s6000_i2s_init(void)
-{
- return platform_driver_register(&s6000_i2s_driver);
-}
-module_init(s6000_i2s_init);
-
-static void __exit s6000_i2s_exit(void)
-{
- platform_driver_unregister(&s6000_i2s_driver);
-}
-module_exit(s6000_i2s_exit);
+module_platform_driver(s6000_i2s_driver);
MODULE_AUTHOR("Daniel Gloeckner");
MODULE_DESCRIPTION("Stretch s6000 family I2S SoC Interface");
diff --git a/sound/soc/s6000/s6000-pcm.c b/sound/soc/s6000/s6000-pcm.c
index 80c85fd64e1a..716da861c629 100644
--- a/sound/soc/s6000/s6000-pcm.c
+++ b/sound/soc/s6000/s6000-pcm.c
@@ -435,7 +435,8 @@ static void s6000_pcm_free(struct snd_pcm *pcm)
{
struct snd_soc_pcm_runtime *runtime = pcm->private_data;
struct s6000_pcm_dma_params *params =
- snd_soc_dai_get_dma_data(runtime->cpu_dai, pcm->streams[0].substream);
+ snd_soc_dai_get_dma_data(runtime->cpu_dai,
+ pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
free_irq(params->irq, pcm);
snd_pcm_lib_preallocate_free_for_all(pcm);
@@ -446,13 +447,12 @@ static u64 s6000_pcm_dmamask = DMA_BIT_MASK(32);
static int s6000_pcm_new(struct snd_soc_pcm_runtime *runtime)
{
struct snd_card *card = runtime->card->snd_card;
- struct snd_soc_dai *dai = runtime->cpu_dai;
struct snd_pcm *pcm = runtime->pcm;
struct s6000_pcm_dma_params *params;
int res;
params = snd_soc_dai_get_dma_data(runtime->cpu_dai,
- pcm->streams[0].substream);
+ pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream);
if (!card->dev->dma_mask)
card->dev->dma_mask = &s6000_pcm_dmamask;
@@ -521,17 +521,7 @@ static struct platform_driver s6000_pcm_driver = {
.remove = __devexit_p(s6000_soc_platform_remove),
};
-static int __init snd_s6000_pcm_init(void)
-{
- return platform_driver_register(&s6000_pcm_driver);
-}
-module_init(snd_s6000_pcm_init);
-
-static void __exit snd_s6000_pcm_exit(void)
-{
- platform_driver_unregister(&s6000_pcm_driver);
-}
-module_exit(snd_s6000_pcm_exit);
+module_platform_driver(s6000_pcm_driver);
MODULE_AUTHOR("Daniel Gloeckner");
MODULE_DESCRIPTION("Stretch s6000 family PCM DMA module");
diff --git a/sound/soc/s6000/s6105-ipcam.c b/sound/soc/s6000/s6105-ipcam.c
index 5890e431852f..58cfb1eb7dd3 100644
--- a/sound/soc/s6000/s6105-ipcam.c
+++ b/sound/soc/s6000/s6105-ipcam.c
@@ -187,6 +187,7 @@ static struct snd_soc_dai_link s6105_dai = {
/* s6105 audio machine driver */
static struct snd_soc_card snd_soc_card_s6105 = {
.name = "Stretch IP Camera",
+ .owner = THIS_MODULE,
.dai_link = &s6105_dai,
.num_links = 1,
};
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig
index 65f980ef2870..f3417f2311b8 100644
--- a/sound/soc/samsung/Kconfig
+++ b/sound/soc/samsung/Kconfig
@@ -63,7 +63,9 @@ config SND_SOC_SAMSUNG_SMDK_WM8580
config SND_SOC_SAMSUNG_SMDK_WM8994
tristate "SoC I2S Audio support for WM8994 on SMDK"
- depends on SND_SOC_SAMSUNG && (MACH_SMDKV310 || MACH_SMDKC210)
+ depends on SND_SOC_SAMSUNG && (MACH_SMDKV310 || MACH_SMDKC210 || MACH_SMDK4212)
+ depends on I2C=y && GENERIC_HARDIRQS
+ select MFD_WM8994
select SND_SOC_WM8994
select SND_SAMSUNG_I2S
help
@@ -150,7 +152,9 @@ config SND_SOC_SMARTQ
config SND_SOC_GONI_AQUILA_WM8994
tristate "SoC I2S Audio support for AQUILA/GONI - WM8994"
depends on SND_SOC_SAMSUNG && (MACH_GONI || MACH_AQUILA)
+ depends on I2C=y && GENERIC_HARDIRQS
select SND_SAMSUNG_I2S
+ select MFD_WM8994
select SND_SOC_WM8994
help
Say Y if you want to add support for SoC audio on goni or aquila
@@ -158,7 +162,7 @@ config SND_SOC_GONI_AQUILA_WM8994
config SND_SOC_SAMSUNG_SMDK_SPDIF
tristate "SoC S/PDIF Audio support for SMDK"
- depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310)
+ depends on SND_SOC_SAMSUNG && (MACH_SMDKC100 || MACH_SMDKC110 || MACH_SMDKV210 || MACH_SMDKV310 || MACH_SMDK4212)
select SND_SAMSUNG_SPDIF
help
Say Y if you want to add support for SoC S/PDIF audio on the SMDK.
@@ -173,7 +177,9 @@ config SND_SOC_SMDK_WM8580_PCM
config SND_SOC_SMDK_WM8994_PCM
tristate "SoC PCM Audio support for WM8994 on SMDK"
- depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310)
+ depends on SND_SOC_SAMSUNG && (MACH_SMDKC210 || MACH_SMDKV310 || MACH_SMDK4212)
+ depends on I2C=y && GENERIC_HARDIRQS
+ select MFD_WM8994
select SND_SOC_WM8994
select SND_SAMSUNG_PCM
help
@@ -187,8 +193,22 @@ config SND_SOC_SPEYSIDE
select SND_SOC_WM9081
select SND_SOC_WM1250_EV1
-config SND_SOC_SPEYSIDE_WM8962
- tristate "Audio support for Wolfson Speyside with WM8962"
+config SND_SOC_TOBERMORY
+ tristate "Audio support for Wolfson Tobermory"
depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
select SND_SAMSUNG_I2S
select SND_SOC_WM8962
+
+config SND_SOC_LOWLAND
+ tristate "Audio support for Wolfson Lowland"
+ depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
+ select SND_SAMSUNG_I2S
+ select SND_SOC_WM5100
+ select SND_SOC_WM9081
+
+config SND_SOC_LITTLEMILL
+ tristate "Audio support for Wolfson Littlemill"
+ depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410
+ select SND_SAMSUNG_I2S
+ select MFD_WM8994
+ select SND_SOC_WM8994
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile
index 8509d3c4366e..9d03beb40c86 100644
--- a/sound/soc/samsung/Makefile
+++ b/sound/soc/samsung/Makefile
@@ -39,7 +39,9 @@ snd-soc-smdk-spdif-objs := smdk_spdif.o
snd-soc-smdk-wm8580pcm-objs := smdk_wm8580pcm.o
snd-soc-smdk-wm8994pcm-objs := smdk_wm8994pcm.o
snd-soc-speyside-objs := speyside.o
-snd-soc-speyside-wm8962-objs := speyside_wm8962.o
+snd-soc-tobermory-objs := tobermory.o
+snd-soc-lowland-objs := lowland.o
+snd-soc-littlemill-objs := littlemill.o
obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o
obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
@@ -60,4 +62,6 @@ obj-$(CONFIG_SND_SOC_GONI_AQUILA_WM8994) += snd-soc-goni-wm8994.o
obj-$(CONFIG_SND_SOC_SMDK_WM8580_PCM) += snd-soc-smdk-wm8580pcm.o
obj-$(CONFIG_SND_SOC_SMDK_WM8994_PCM) += snd-soc-smdk-wm8994pcm.o
obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o
-obj-$(CONFIG_SND_SOC_SPEYSIDE_WM8962) += snd-soc-speyside-wm8962.o
+obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o
+obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o
+obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c
index f97110e72e85..3d04c1fa6781 100644
--- a/sound/soc/samsung/ac97.c
+++ b/sound/soc/samsung/ac97.c
@@ -4,7 +4,7 @@
* Evolved from s3c2443-ac97.c
*
* Copyright (c) 2010 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@gmail.com>
* Credits: Graeme Gregory, Sean Choi
*
* This program is free software; you can redistribute it and/or modify
@@ -15,6 +15,7 @@
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/clk.h>
+#include <linux/module.h>
#include <sound/soc.h>
@@ -271,7 +272,10 @@ static int s3c_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
- s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+ if (!dma_data->ops)
+ dma_data->ops = samsung_dma_get_ops();
+
+ dma_data->ops->started(dma_data->channel);
return 0;
}
@@ -317,17 +321,20 @@ static int s3c_ac97_mic_trigger(struct snd_pcm_substream *substream,
writel(ac_glbctrl, s3c_ac97.regs + S3C_AC97_GLBCTRL);
- s3c2410_dma_ctrl(dma_data->channel, S3C2410_DMAOP_STARTED);
+ if (!dma_data->ops)
+ dma_data->ops = samsung_dma_get_ops();
+
+ dma_data->ops->started(dma_data->channel);
return 0;
}
-static struct snd_soc_dai_ops s3c_ac97_dai_ops = {
+static const struct snd_soc_dai_ops s3c_ac97_dai_ops = {
.hw_params = s3c_ac97_hw_params,
.trigger = s3c_ac97_trigger,
};
-static struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
+static const struct snd_soc_dai_ops s3c_ac97_mic_dai_ops = {
.hw_params = s3c_ac97_hw_mic_params,
.trigger = s3c_ac97_mic_trigger,
};
@@ -444,7 +451,7 @@ static __devinit int s3c_ac97_probe(struct platform_device *pdev)
}
ret = request_irq(irq_res->start, s3c_ac97_irq,
- IRQF_DISABLED, "AC97", NULL);
+ 0, "AC97", NULL);
if (ret < 0) {
dev_err(&pdev->dev, "ac97: interrupt request failed.\n");
goto err4;
@@ -495,26 +502,16 @@ static __devexit int s3c_ac97_remove(struct platform_device *pdev)
static struct platform_driver s3c_ac97_driver = {
.probe = s3c_ac97_probe,
- .remove = s3c_ac97_remove,
+ .remove = __devexit_p(s3c_ac97_remove),
.driver = {
.name = "samsung-ac97",
.owner = THIS_MODULE,
},
};
-static int __init s3c_ac97_init(void)
-{
- return platform_driver_register(&s3c_ac97_driver);
-}
-module_init(s3c_ac97_init);
-
-static void __exit s3c_ac97_exit(void)
-{
- platform_driver_unregister(&s3c_ac97_driver);
-}
-module_exit(s3c_ac97_exit);
+module_platform_driver(s3c_ac97_driver);
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("AC97 driver for the Samsung SoC");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:samsung-ac97");
diff --git a/sound/soc/samsung/dma.c b/sound/soc/samsung/dma.c
index 9465588b02f2..ddc6cde14e2a 100644
--- a/sound/soc/samsung/dma.c
+++ b/sound/soc/samsung/dma.c
@@ -16,6 +16,7 @@
#include <linux/slab.h>
#include <linux/dma-mapping.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
@@ -54,7 +55,6 @@ struct runtime_data {
spinlock_t lock;
int state;
unsigned int dma_loaded;
- unsigned int dma_limit;
unsigned int dma_period;
dma_addr_t dma_start;
dma_addr_t dma_pos;
@@ -62,77 +62,79 @@ struct runtime_data {
struct s3c_dma_params *params;
};
+static void audio_buffdone(void *data);
+
/* dma_enqueue
*
* place a dma buffer onto the queue for the dma system
* to handle.
-*/
+ */
static void dma_enqueue(struct snd_pcm_substream *substream)
{
struct runtime_data *prtd = substream->runtime->private_data;
dma_addr_t pos = prtd->dma_pos;
unsigned int limit;
- int ret;
+ struct samsung_dma_prep_info dma_info;
pr_debug("Entered %s\n", __func__);
- if (s3c_dma_has_circular())
- limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
- else
- limit = prtd->dma_limit;
+ limit = (prtd->dma_end - prtd->dma_start) / prtd->dma_period;
pr_debug("%s: loaded %d, limit %d\n",
__func__, prtd->dma_loaded, limit);
- while (prtd->dma_loaded < limit) {
- unsigned long len = prtd->dma_period;
+ dma_info.cap = (samsung_dma_has_circular() ? DMA_CYCLIC : DMA_SLAVE);
+ dma_info.direction =
+ (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+ ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
+ dma_info.fp = audio_buffdone;
+ dma_info.fp_param = substream;
+ dma_info.period = prtd->dma_period;
+ dma_info.len = prtd->dma_period*limit;
+ while (prtd->dma_loaded < limit) {
pr_debug("dma_loaded: %d\n", prtd->dma_loaded);
- if ((pos + len) > prtd->dma_end) {
- len = prtd->dma_end - pos;
- pr_debug("%s: corrected dma len %ld\n", __func__, len);
+ if ((pos + dma_info.period) > prtd->dma_end) {
+ dma_info.period = prtd->dma_end - pos;
+ pr_debug("%s: corrected dma len %ld\n",
+ __func__, dma_info.period);
}
- ret = s3c2410_dma_enqueue(prtd->params->channel,
- substream, pos, len);
+ dma_info.buf = pos;
+ prtd->params->ops->prepare(prtd->params->ch, &dma_info);
- if (ret == 0) {
- prtd->dma_loaded++;
- pos += prtd->dma_period;
- if (pos >= prtd->dma_end)
- pos = prtd->dma_start;
- } else
- break;
+ prtd->dma_loaded++;
+ pos += prtd->dma_period;
+ if (pos >= prtd->dma_end)
+ pos = prtd->dma_start;
}
prtd->dma_pos = pos;
}
-static void audio_buffdone(struct s3c2410_dma_chan *channel,
- void *dev_id, int size,
- enum s3c2410_dma_buffresult result)
+static void audio_buffdone(void *data)
{
- struct snd_pcm_substream *substream = dev_id;
- struct runtime_data *prtd;
+ struct snd_pcm_substream *substream = data;
+ struct runtime_data *prtd = substream->runtime->private_data;
pr_debug("Entered %s\n", __func__);
- if (result == S3C2410_RES_ABORT || result == S3C2410_RES_ERR)
- return;
+ if (prtd->state & ST_RUNNING) {
+ prtd->dma_pos += prtd->dma_period;
+ if (prtd->dma_pos >= prtd->dma_end)
+ prtd->dma_pos = prtd->dma_start;
- prtd = substream->runtime->private_data;
+ if (substream)
+ snd_pcm_period_elapsed(substream);
- if (substream)
- snd_pcm_period_elapsed(substream);
-
- spin_lock(&prtd->lock);
- if (prtd->state & ST_RUNNING && !s3c_dma_has_circular()) {
- prtd->dma_loaded--;
- dma_enqueue(substream);
+ spin_lock(&prtd->lock);
+ if (!samsung_dma_has_circular()) {
+ prtd->dma_loaded--;
+ dma_enqueue(substream);
+ }
+ spin_unlock(&prtd->lock);
}
-
- spin_unlock(&prtd->lock);
}
static int dma_hw_params(struct snd_pcm_substream *substream,
@@ -144,8 +146,7 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
unsigned long totbytes = params_buffer_bytes(params);
struct s3c_dma_params *dma =
snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
- int ret = 0;
-
+ struct samsung_dma_info dma_info;
pr_debug("Entered %s\n", __func__);
@@ -163,30 +164,26 @@ static int dma_hw_params(struct snd_pcm_substream *substream,
pr_debug("params %p, client %p, channel %d\n", prtd->params,
prtd->params->client, prtd->params->channel);
- ret = s3c2410_dma_request(prtd->params->channel,
- prtd->params->client, NULL);
-
- if (ret < 0) {
- printk(KERN_ERR "failed to get dma channel\n");
- return ret;
- }
-
- /* use the circular buffering if we have it available. */
- if (s3c_dma_has_circular())
- s3c2410_dma_setflags(prtd->params->channel,
- S3C2410_DMAF_CIRCULAR);
+ prtd->params->ops = samsung_dma_get_ops();
+
+ dma_info.cap = (samsung_dma_has_circular() ?
+ DMA_CYCLIC : DMA_SLAVE);
+ dma_info.client = prtd->params->client;
+ dma_info.direction =
+ (substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+ ? DMA_MEM_TO_DEV : DMA_DEV_TO_MEM);
+ dma_info.width = prtd->params->dma_size;
+ dma_info.fifo = prtd->params->dma_addr;
+ prtd->params->ch = prtd->params->ops->request(
+ prtd->params->channel, &dma_info);
}
- s3c2410_dma_set_buffdone_fn(prtd->params->channel,
- audio_buffdone);
-
snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
runtime->dma_bytes = totbytes;
spin_lock_irq(&prtd->lock);
prtd->dma_loaded = 0;
- prtd->dma_limit = runtime->hw.periods_min;
prtd->dma_period = params_period_bytes(params);
prtd->dma_start = runtime->dma_addr;
prtd->dma_pos = prtd->dma_start;
@@ -202,11 +199,12 @@ static int dma_hw_free(struct snd_pcm_substream *substream)
pr_debug("Entered %s\n", __func__);
- /* TODO - do we need to ensure DMA flushed */
snd_pcm_set_runtime_buffer(substream, NULL);
if (prtd->params) {
- s3c2410_dma_free(prtd->params->channel, prtd->params->client);
+ prtd->params->ops->flush(prtd->params->ch);
+ prtd->params->ops->release(prtd->params->ch,
+ prtd->params->client);
prtd->params = NULL;
}
@@ -225,23 +223,9 @@ static int dma_prepare(struct snd_pcm_substream *substream)
if (!prtd->params)
return 0;
- /* channel needs configuring for mem=>device, increment memory addr,
- * sync to pclk, half-word transfers to the IIS-FIFO. */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- s3c2410_dma_devconfig(prtd->params->channel,
- S3C2410_DMASRC_MEM,
- prtd->params->dma_addr);
- } else {
- s3c2410_dma_devconfig(prtd->params->channel,
- S3C2410_DMASRC_HW,
- prtd->params->dma_addr);
- }
-
- s3c2410_dma_config(prtd->params->channel,
- prtd->params->dma_size);
-
/* flush the DMA channel */
- s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_FLUSH);
+ prtd->params->ops->flush(prtd->params->ch);
+
prtd->dma_loaded = 0;
prtd->dma_pos = prtd->dma_start;
@@ -265,14 +249,14 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
case SNDRV_PCM_TRIGGER_RESUME:
case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
prtd->state |= ST_RUNNING;
- s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_START);
+ prtd->params->ops->trigger(prtd->params->ch);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
prtd->state &= ~ST_RUNNING;
- s3c2410_dma_ctrl(prtd->params->channel, S3C2410_DMAOP_STOP);
+ prtd->params->ops->stop(prtd->params->ch);
break;
default:
@@ -291,21 +275,12 @@ dma_pointer(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct runtime_data *prtd = runtime->private_data;
unsigned long res;
- dma_addr_t src, dst;
pr_debug("Entered %s\n", __func__);
- spin_lock(&prtd->lock);
- s3c2410_dma_getposition(prtd->params->channel, &src, &dst);
+ res = prtd->dma_pos - prtd->dma_start;
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
- res = dst - prtd->dma_start;
- else
- res = src - prtd->dma_start;
-
- spin_unlock(&prtd->lock);
-
- pr_debug("Pointer %x %x\n", src, dst);
+ pr_debug("Pointer offset: %lu\n", res);
/* we seem to be getting the odd error from the pcm library due
* to out-of-bounds pointers. this is maybe due to the dma engine
@@ -428,7 +403,6 @@ static u64 dma_mask = DMA_BIT_MASK(32);
static int dma_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
@@ -437,16 +411,16 @@ static int dma_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->dma_mask)
card->dev->dma_mask = &dma_mask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto out;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -483,17 +457,7 @@ static struct platform_driver asoc_dma_driver = {
.remove = __devexit_p(samsung_asoc_platform_remove),
};
-static int __init samsung_asoc_init(void)
-{
- return platform_driver_register(&asoc_dma_driver);
-}
-module_init(samsung_asoc_init);
-
-static void __exit samsung_asoc_exit(void)
-{
- platform_driver_unregister(&asoc_dma_driver);
-}
-module_exit(samsung_asoc_exit);
+module_platform_driver(asoc_dma_driver);
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("Samsung ASoC DMA Driver");
diff --git a/sound/soc/samsung/dma.h b/sound/soc/samsung/dma.h
index c50659269a40..7d1ead77ef21 100644
--- a/sound/soc/samsung/dma.h
+++ b/sound/soc/samsung/dma.h
@@ -6,7 +6,7 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
- * ALSA PCM interface for the Samsung S3C24xx CPU
+ * ALSA PCM interface for the Samsung SoC
*/
#ifndef _S3C_AUDIO_H
@@ -17,6 +17,8 @@ struct s3c_dma_params {
int channel; /* Channel ID */
dma_addr_t dma_addr;
int dma_size; /* Size of the DMA transfer */
+ unsigned ch;
+ struct samsung_dma_ops *ops;
};
#endif
diff --git a/sound/soc/samsung/goni_wm8994.c b/sound/soc/samsung/goni_wm8994.c
index eb6d72ed55a7..c23c2ae91f58 100644
--- a/sound/soc/samsung/goni_wm8994.c
+++ b/sound/soc/samsung/goni_wm8994.c
@@ -11,6 +11,7 @@
*
*/
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/jack.h>
@@ -99,14 +100,6 @@ static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
int ret;
- /* add goni specific widgets */
- snd_soc_dapm_new_controls(dapm, goni_dapm_widgets,
- ARRAY_SIZE(goni_dapm_widgets));
-
- /* set up goni specific audio routes */
- snd_soc_dapm_add_routes(dapm, goni_dapm_routes,
- ARRAY_SIZE(goni_dapm_routes));
-
/* set endpoints to not connected */
snd_soc_dapm_nc_pin(dapm, "IN2LP:VXRN");
snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
@@ -120,8 +113,6 @@ static int goni_wm8994_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "SPKOUTRP");
}
- snd_soc_dapm_sync(dapm);
-
/* Headset jack detection */
ret = snd_soc_jack_new(codec, "Headset Jack",
SND_JACK_HEADSET | SND_JACK_MECHANICAL | SND_JACK_AVOUT,
@@ -253,8 +244,14 @@ static struct snd_soc_dai_link goni_dai[] = {
static struct snd_soc_card goni = {
.name = "goni",
+ .owner = THIS_MODULE,
.dai_link = goni_dai,
.num_links = ARRAY_SIZE(goni_dai),
+
+ .dapm_widgets = goni_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(goni_dapm_widgets),
+ .dapm_routes = goni_dapm_routes,
+ .num_dapm_routes = ARRAY_SIZE(goni_dapm_routes),
};
static int __init goni_init(void)
diff --git a/sound/soc/samsung/h1940_uda1380.c b/sound/soc/samsung/h1940_uda1380.c
index c6c65892294e..6e3257717c54 100644
--- a/sound/soc/samsung/h1940_uda1380.c
+++ b/sound/soc/samsung/h1940_uda1380.c
@@ -15,6 +15,7 @@
#include <linux/types.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/jack.h>
@@ -182,24 +183,10 @@ static int h1940_uda1380_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
int err;
- /* Add h1940 specific widgets */
- err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
- ARRAY_SIZE(uda1380_dapm_widgets));
- if (err)
- return err;
-
- /* Set up h1940 specific audio path audio_mapnects */
- err = snd_soc_dapm_add_routes(dapm, audio_map,
- ARRAY_SIZE(audio_map));
- if (err)
- return err;
-
snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Speaker");
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
- snd_soc_dapm_sync(dapm);
-
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
&hp_jack);
@@ -228,8 +215,14 @@ static struct snd_soc_dai_link h1940_uda1380_dai[] = {
static struct snd_soc_card h1940_asoc = {
.name = "h1940",
+ .owner = THIS_MODULE,
.dai_link = h1940_uda1380_dai,
.num_links = ARRAY_SIZE(h1940_uda1380_dai),
+
+ .dapm_widgets = uda1380_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
};
static int __init h1940_init(void)
diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c
index c086b78539ee..6ac7b8281a02 100644
--- a/sound/soc/samsung/i2s.c
+++ b/sound/soc/samsung/i2s.c
@@ -3,7 +3,7 @@
* ALSA SoC Audio Layer - Samsung I2S Controller driver
*
* Copyright (c) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
+ * Jaswinder Singh <jassisinghbrar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
@@ -14,6 +14,8 @@
#include <linux/slab.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
@@ -557,6 +559,17 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
mod |= MOD_DC1_EN;
break;
case 2:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ i2s->dma_playback.dma_size = 4;
+ else
+ i2s->dma_capture.dma_size = 4;
+ break;
+ case 1:
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ i2s->dma_playback.dma_size = 2;
+ else
+ i2s->dma_capture.dma_size = 2;
+
break;
default:
dev_err(&i2s->pdev->dev, "%d channels not supported\n",
@@ -759,15 +772,13 @@ static int i2s_trigger(struct snd_pcm_substream *substream,
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
local_irq_save(flags);
- if (capture)
+ if (capture) {
i2s_rxctrl(i2s, 0);
- else
- i2s_txctrl(i2s, 0);
-
- if (capture)
i2s_fifo(i2s, FIC_RXFLUSH);
- else
+ } else {
+ i2s_txctrl(i2s, 0);
i2s_fifo(i2s, FIC_TXFLUSH);
+ }
local_irq_restore(flags);
break;
@@ -880,7 +891,7 @@ static int samsung_i2s_dai_probe(struct snd_soc_dai *dai)
writel(CON_RSTCLR, i2s->addr + I2SCON);
if (i2s->quirks & QUIRK_SEC_DAI)
- idma_reg_addr_init((void *)i2s->addr,
+ idma_reg_addr_init(i2s->addr,
i2s->sec_dai->idma_playback.dma_addr);
probe_exit:
@@ -922,7 +933,7 @@ static int samsung_i2s_dai_remove(struct snd_soc_dai *dai)
return 0;
}
-static struct snd_soc_dai_ops samsung_i2s_dai_ops = {
+static const struct snd_soc_dai_ops samsung_i2s_dai_ops = {
.trigger = i2s_trigger,
.hw_params = i2s_hw_params,
.set_fmt = i2s_set_fmt,
@@ -944,7 +955,7 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
{
struct i2s_dai *i2s;
- i2s = kzalloc(sizeof(struct i2s_dai), GFP_KERNEL);
+ i2s = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dai), GFP_KERNEL);
if (i2s == NULL)
return NULL;
@@ -963,7 +974,7 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
i2s->i2s_dai_drv.playback.formats = SAMSUNG_I2S_FMTS;
if (!sec) {
- i2s->i2s_dai_drv.capture.channels_min = 2;
+ i2s->i2s_dai_drv.capture.channels_min = 1;
i2s->i2s_dai_drv.capture.channels_max = 2;
i2s->i2s_dai_drv.capture.rates = SAMSUNG_I2S_RATES;
i2s->i2s_dai_drv.capture.formats = SAMSUNG_I2S_FMTS;
@@ -971,10 +982,8 @@ struct i2s_dai *i2s_alloc_dai(struct platform_device *pdev, bool sec)
i2s->pdev = platform_device_register_resndata(NULL,
pdev->name, pdev->id + SAMSUNG_I2S_SECOFF,
NULL, 0, NULL, 0);
- if (IS_ERR(i2s->pdev)) {
- kfree(i2s);
+ if (IS_ERR(i2s->pdev))
return NULL;
- }
}
/* Pre-assign snd_soc_dai_set_drvdata */
@@ -1047,7 +1056,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
if (!pri_dai) {
dev_err(&pdev->dev, "Unable to alloc I2S_pri\n");
ret = -ENOMEM;
- goto err1;
+ goto err;
}
pri_dai->dma_playback.dma_addr = regs_base + I2STXD;
@@ -1072,7 +1081,7 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
if (!sec_dai) {
dev_err(&pdev->dev, "Unable to alloc I2S_sec\n");
ret = -ENOMEM;
- goto err2;
+ goto err;
}
sec_dai->dma_playback.dma_addr = regs_base + I2STXDS;
sec_dai->dma_playback.client =
@@ -1091,17 +1100,15 @@ static __devinit int samsung_i2s_probe(struct platform_device *pdev)
if (i2s_pdata->cfg_gpio && i2s_pdata->cfg_gpio(pdev)) {
dev_err(&pdev->dev, "Unable to configure gpio\n");
ret = -EINVAL;
- goto err3;
+ goto err;
}
snd_soc_register_dai(&pri_dai->pdev->dev, &pri_dai->i2s_dai_drv);
+ pm_runtime_enable(&pdev->dev);
+
return 0;
-err3:
- kfree(sec_dai);
-err2:
- kfree(pri_dai);
-err1:
+err:
release_mem_region(regs_base, resource_size(res));
return ret;
@@ -1110,6 +1117,7 @@ err1:
static __devexit int samsung_i2s_remove(struct platform_device *pdev)
{
struct i2s_dai *i2s, *other;
+ struct resource *res;
i2s = dev_get_drvdata(&pdev->dev);
other = i2s->pri_dai ? : i2s->sec_dai;
@@ -1118,7 +1126,7 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
other->pri_dai = NULL;
other->sec_dai = NULL;
} else {
- struct resource *res;
+ pm_runtime_disable(&pdev->dev);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (res)
release_mem_region(res->start, resource_size(res));
@@ -1127,8 +1135,6 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
i2s->pri_dai = NULL;
i2s->sec_dai = NULL;
- kfree(i2s);
-
snd_soc_unregister_dai(&pdev->dev);
return 0;
@@ -1136,27 +1142,17 @@ static __devexit int samsung_i2s_remove(struct platform_device *pdev)
static struct platform_driver samsung_i2s_driver = {
.probe = samsung_i2s_probe,
- .remove = samsung_i2s_remove,
+ .remove = __devexit_p(samsung_i2s_remove),
.driver = {
.name = "samsung-i2s",
.owner = THIS_MODULE,
},
};
-static int __init samsung_i2s_init(void)
-{
- return platform_driver_register(&samsung_i2s_driver);
-}
-module_init(samsung_i2s_init);
-
-static void __exit samsung_i2s_exit(void)
-{
- platform_driver_unregister(&samsung_i2s_driver);
-}
-module_exit(samsung_i2s_exit);
+module_platform_driver(samsung_i2s_driver);
/* Module information */
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("Samsung I2S Interface");
MODULE_ALIAS("platform:samsung-i2s");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/i2s.h b/sound/soc/samsung/i2s.h
index 8e15f6a616d1..d420a7ca56ca 100644
--- a/sound/soc/samsung/i2s.h
+++ b/sound/soc/samsung/i2s.h
@@ -3,7 +3,7 @@
* ALSA SoC Audio Layer - Samsung I2S Controller driver
*
* Copyright (c) 2010 Samsung Electronics Co. Ltd.
- * Jaswinder Singh <jassi.brar@samsung.com>
+ * Jaswinder Singh <jassisinghbrar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
diff --git a/sound/soc/samsung/idma.c b/sound/soc/samsung/idma.c
index ebde0740ab19..c227c3163cae 100644
--- a/sound/soc/samsung/idma.c
+++ b/sound/soc/samsung/idma.c
@@ -15,6 +15,7 @@
#include <linux/platform_device.h>
#include <linux/dma-mapping.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
@@ -386,7 +387,6 @@ static u64 idma_mask = DMA_BIT_MASK(32);
static int idma_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
@@ -395,21 +395,22 @@ static int idma_new(struct snd_soc_pcm_runtime *rtd)
if (!card->dev->coherent_dma_mask)
card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min)
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = preallocate_idma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
+ }
return ret;
}
-void idma_reg_addr_init(void *regs, dma_addr_t addr)
+void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr)
{
spin_lock_init(&idma.lock);
idma.regs = regs;
idma.lp_tx_addr = addr;
}
-struct snd_soc_platform_driver asoc_idma_platform = {
+static struct snd_soc_platform_driver asoc_idma_platform = {
.ops = &idma_ops,
.pcm_new = idma_new,
.pcm_free = idma_free,
@@ -436,17 +437,7 @@ static struct platform_driver asoc_idma_driver = {
.remove = __devexit_p(asoc_idma_platform_remove),
};
-static int __init asoc_idma_init(void)
-{
- return platform_driver_register(&asoc_idma_driver);
-}
-module_init(asoc_idma_init);
-
-static void __exit asoc_idma_exit(void)
-{
- platform_driver_unregister(&asoc_idma_driver);
-}
-module_exit(asoc_idma_exit);
+module_platform_driver(asoc_idma_driver);
MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("Samsung ASoC IDMA Driver");
diff --git a/sound/soc/samsung/idma.h b/sound/soc/samsung/idma.h
index 48273216166e..8644946973e5 100644
--- a/sound/soc/samsung/idma.h
+++ b/sound/soc/samsung/idma.h
@@ -14,7 +14,7 @@
#ifndef __SND_SOC_SAMSUNG_IDMA_H_
#define __SND_SOC_SAMSUNG_IDMA_H_
-extern void idma_reg_addr_init(void *regs, dma_addr_t addr);
+extern void idma_reg_addr_init(void __iomem *regs, dma_addr_t addr);
/* dma_state */
#define LPAM_DMA_STOP 0
diff --git a/sound/soc/samsung/jive_wm8750.c b/sound/soc/samsung/jive_wm8750.c
index 14eb6ea69e7c..1578663a1faa 100644
--- a/sound/soc/samsung/jive_wm8750.c
+++ b/sound/soc/samsung/jive_wm8750.c
@@ -11,6 +11,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/module.h>
#include <sound/soc.h>
#include <asm/mach-types.h>
@@ -100,7 +101,6 @@ static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- int err;
/* These endpoints are not being used. */
snd_soc_dapm_nc_pin(dapm, "LINPUT2");
@@ -110,18 +110,6 @@ static int jive_wm8750_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "OUT3");
snd_soc_dapm_nc_pin(dapm, "MONO");
- /* Add jive specific widgets */
- err = snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets,
- ARRAY_SIZE(wm8750_dapm_widgets));
- if (err) {
- printk(KERN_ERR "%s: failed to add widgets (%d)\n",
- __func__, err);
- return err;
- }
-
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -131,7 +119,7 @@ static struct snd_soc_dai_link jive_dai = {
.cpu_dai_name = "s3c2412-i2s",
.codec_dai_name = "wm8750-hifi",
.platform_name = "samsung-audio",
- .codec_name = "wm8750-codec.0-001a",
+ .codec_name = "wm8750.0-001a",
.init = jive_wm8750_init,
.ops = &jive_ops,
};
@@ -139,8 +127,14 @@ static struct snd_soc_dai_link jive_dai = {
/* jive audio machine driver */
static struct snd_soc_card snd_soc_machine_jive = {
.name = "Jive",
+ .owner = THIS_MODULE,
.dai_link = &jive_dai,
.num_links = 1,
+
+ .dapm_widgets = wm8750_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8750_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
};
static struct platform_device *jive_snd_device;
diff --git a/sound/soc/samsung/littlemill.c b/sound/soc/samsung/littlemill.c
new file mode 100644
index 000000000000..e7416851bf7d
--- /dev/null
+++ b/sound/soc/samsung/littlemill.c
@@ -0,0 +1,256 @@
+/*
+ * Littlemill audio support
+ *
+ * Copyright 2011 Wolfson Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include "../codecs/wm8994.h"
+
+static int sample_rate = 44100;
+
+static int littlemill_set_bias_level(struct snd_soc_card *card,
+ struct snd_soc_dapm_context *dapm,
+ enum snd_soc_bias_level level)
+{
+ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ int ret;
+
+ if (dapm->dev != codec_dai->dev)
+ return 0;
+
+ switch (level) {
+ case SND_SOC_BIAS_PREPARE:
+ /*
+ * If we've not already clocked things via hw_params()
+ * then do so now, otherwise these are noops.
+ */
+ if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
+ ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+ WM8994_FLL_SRC_MCLK2, 32768,
+ sample_rate * 512);
+ if (ret < 0) {
+ pr_err("Failed to start FLL: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ WM8994_SYSCLK_FLL1,
+ sample_rate * 512,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err("Failed to set SYSCLK: %d\n", ret);
+ return ret;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static int littlemill_set_bias_level_post(struct snd_soc_card *card,
+ struct snd_soc_dapm_context *dapm,
+ enum snd_soc_bias_level level)
+{
+ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ int ret;
+
+ if (dapm->dev != codec_dai->dev)
+ return 0;
+
+ switch (level) {
+ case SND_SOC_BIAS_STANDBY:
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK2,
+ 32768, SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err("Failed to switch away from FLL: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+ 0, 0, 0);
+ if (ret < 0) {
+ pr_err("Failed to stop FLL: %d\n", ret);
+ return ret;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ dapm->bias_level = level;
+
+ return 0;
+}
+
+static int littlemill_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+
+ sample_rate = params_rate(params);
+
+ ret = snd_soc_dai_set_pll(codec_dai, WM8994_FLL1,
+ WM8994_FLL_SRC_MCLK2, 32768,
+ sample_rate * 512);
+ if (ret < 0) {
+ pr_err("Failed to start FLL: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_dai_set_sysclk(codec_dai,
+ WM8994_SYSCLK_FLL1,
+ sample_rate * 512,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err("Failed to set SYSCLK: %d\n", ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops littlemill_ops = {
+ .hw_params = littlemill_hw_params,
+};
+
+static struct snd_soc_dai_link littlemill_dai[] = {
+ {
+ .name = "CPU",
+ .stream_name = "CPU",
+ .cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "wm8994-aif1",
+ .platform_name = "samsung-audio",
+ .codec_name = "wm8994-codec",
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ .ops = &littlemill_ops,
+ },
+};
+
+static struct snd_soc_dapm_widget widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+
+ SND_SOC_DAPM_MIC("AMIC", NULL),
+ SND_SOC_DAPM_MIC("DMIC", NULL),
+};
+
+static struct snd_soc_dapm_route audio_paths[] = {
+ { "Headphone", NULL, "HPOUT1L" },
+ { "Headphone", NULL, "HPOUT1R" },
+
+ { "AMIC", NULL, "MICBIAS1" }, /* Default for AMICBIAS jumper */
+ { "IN1LN", NULL, "AMIC" },
+
+ { "DMIC", NULL, "MICBIAS2" }, /* Default for DMICBIAS jumper */
+ { "DMIC1DAT", NULL, "DMIC" },
+ { "DMIC2DAT", NULL, "DMIC" },
+};
+
+static struct snd_soc_jack littlemill_headset;
+
+static int littlemill_late_probe(struct snd_soc_card *card)
+{
+ struct snd_soc_codec *codec = card->rtd[0].codec;
+ struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
+ int ret;
+
+ ret = snd_soc_dai_set_sysclk(codec_dai, WM8994_SYSCLK_MCLK2,
+ 32768, SND_SOC_CLOCK_IN);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_jack_new(codec, "Headset",
+ SND_JACK_HEADSET | SND_JACK_MECHANICAL |
+ SND_JACK_BTN_0 | SND_JACK_BTN_1 |
+ SND_JACK_BTN_2 | SND_JACK_BTN_3 |
+ SND_JACK_BTN_4 | SND_JACK_BTN_5,
+ &littlemill_headset);
+ if (ret)
+ return ret;
+
+ /* This will check device compatibility itself */
+ wm8958_mic_detect(codec, &littlemill_headset, NULL, NULL);
+
+ /* As will this */
+ wm8994_mic_detect(codec, &littlemill_headset, 1);
+
+ return 0;
+}
+
+static struct snd_soc_card littlemill = {
+ .name = "Littlemill",
+ .owner = THIS_MODULE,
+ .dai_link = littlemill_dai,
+ .num_links = ARRAY_SIZE(littlemill_dai),
+
+ .set_bias_level = littlemill_set_bias_level,
+ .set_bias_level_post = littlemill_set_bias_level_post,
+
+ .dapm_widgets = widgets,
+ .num_dapm_widgets = ARRAY_SIZE(widgets),
+ .dapm_routes = audio_paths,
+ .num_dapm_routes = ARRAY_SIZE(audio_paths),
+
+ .late_probe = littlemill_late_probe,
+};
+
+static __devinit int littlemill_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &littlemill;
+ int ret;
+
+ card->dev = &pdev->dev;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devexit littlemill_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static struct platform_driver littlemill_driver = {
+ .driver = {
+ .name = "littlemill",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = littlemill_probe,
+ .remove = __devexit_p(littlemill_remove),
+};
+
+module_platform_driver(littlemill_driver);
+
+MODULE_DESCRIPTION("Littlemill audio support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:littlemill");
diff --git a/sound/soc/samsung/ln2440sbc_alc650.c b/sound/soc/samsung/ln2440sbc_alc650.c
index bd91c19a6c08..69c4a5934a4d 100644
--- a/sound/soc/samsung/ln2440sbc_alc650.c
+++ b/sound/soc/samsung/ln2440sbc_alc650.c
@@ -16,6 +16,7 @@
*
*/
+#include <linux/module.h>
#include <sound/soc.h>
static struct snd_soc_card ln2440sbc;
@@ -33,6 +34,7 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = {
static struct snd_soc_card ln2440sbc = {
.name = "LN2440SBC",
+ .owner = THIS_MODULE,
.dai_link = ln2440sbc_dai,
.num_links = ARRAY_SIZE(ln2440sbc_dai),
};
diff --git a/sound/soc/samsung/lowland.c b/sound/soc/samsung/lowland.c
new file mode 100644
index 000000000000..4adff934f771
--- /dev/null
+++ b/sound/soc/samsung/lowland.c
@@ -0,0 +1,237 @@
+/*
+ * Lowland audio support
+ *
+ * Copyright 2011 Wolfson Microelectronics
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <sound/soc.h>
+#include <sound/soc-dapm.h>
+#include <sound/jack.h>
+#include <linux/gpio.h>
+#include <linux/module.h>
+
+#include "../codecs/wm5100.h"
+#include "../codecs/wm9081.h"
+
+#define MCLK1_RATE (44100 * 512)
+#define CLKOUT_RATE (44100 * 256)
+
+static int lowland_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ int ret;
+
+ ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+static struct snd_soc_ops lowland_ops = {
+ .hw_params = lowland_hw_params,
+};
+
+static struct snd_soc_jack lowland_headset;
+
+/* Headset jack detection DAPM pins */
+static struct snd_soc_jack_pin lowland_headset_pins[] = {
+ {
+ .pin = "Headphone",
+ .mask = SND_JACK_HEADPHONE | SND_JACK_LINEOUT,
+ },
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
+};
+
+static int lowland_wm5100_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ int ret;
+
+ ret = snd_soc_codec_set_sysclk(codec, WM5100_CLK_SYSCLK,
+ WM5100_CLKSRC_MCLK1, MCLK1_RATE,
+ SND_SOC_CLOCK_IN);
+ if (ret < 0) {
+ pr_err("Failed to set SYSCLK clock source: %d\n", ret);
+ return ret;
+ }
+
+ /* Clock OPCLK, used by the other audio components. */
+ ret = snd_soc_codec_set_sysclk(codec, WM5100_CLK_OPCLK, 0,
+ CLKOUT_RATE, 0);
+ if (ret < 0) {
+ pr_err("Failed to set OPCLK rate: %d\n", ret);
+ return ret;
+ }
+
+ ret = snd_soc_jack_new(codec, "Headset",
+ SND_JACK_LINEOUT | SND_JACK_HEADSET |
+ SND_JACK_BTN_0,
+ &lowland_headset);
+ if (ret)
+ return ret;
+
+ ret = snd_soc_jack_add_pins(&lowland_headset,
+ ARRAY_SIZE(lowland_headset_pins),
+ lowland_headset_pins);
+ if (ret)
+ return ret;
+
+ wm5100_detect(codec, &lowland_headset);
+
+ return 0;
+}
+
+static struct snd_soc_dai_link lowland_dai[] = {
+ {
+ .name = "CPU",
+ .stream_name = "CPU",
+ .cpu_dai_name = "samsung-i2s.0",
+ .codec_dai_name = "wm5100-aif1",
+ .platform_name = "samsung-audio",
+ .codec_name = "wm5100.1-001a",
+ .ops = &lowland_ops,
+ .init = lowland_wm5100_init,
+ },
+ {
+ .name = "Baseband",
+ .stream_name = "Baseband",
+ .cpu_dai_name = "wm5100-aif2",
+ .codec_dai_name = "wm1250-ev1",
+ .codec_name = "wm1250-ev1.1-0027",
+ .ops = &lowland_ops,
+ .ignore_suspend = 1,
+ },
+};
+
+static int lowland_wm9081_init(struct snd_soc_dapm_context *dapm)
+{
+ snd_soc_dapm_nc_pin(dapm, "LINEOUT");
+
+ /* At any time the WM9081 is active it will have this clock */
+ return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0,
+ CLKOUT_RATE, 0);
+}
+
+static struct snd_soc_aux_dev lowland_aux_dev[] = {
+ {
+ .name = "wm9081",
+ .codec_name = "wm9081.1-006c",
+ .init = lowland_wm9081_init,
+ },
+};
+
+static struct snd_soc_codec_conf lowland_codec_conf[] = {
+ {
+ .dev_name = "wm9081.1-006c",
+ .name_prefix = "Sub",
+ },
+};
+
+static const struct snd_kcontrol_new controls[] = {
+ SOC_DAPM_PIN_SWITCH("Main Speaker"),
+ SOC_DAPM_PIN_SWITCH("Main DMIC"),
+ SOC_DAPM_PIN_SWITCH("Main AMIC"),
+ SOC_DAPM_PIN_SWITCH("WM1250 Input"),
+ SOC_DAPM_PIN_SWITCH("WM1250 Output"),
+ SOC_DAPM_PIN_SWITCH("Headphone"),
+};
+
+static struct snd_soc_dapm_widget widgets[] = {
+ SND_SOC_DAPM_HP("Headphone", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+
+ SND_SOC_DAPM_SPK("Main Speaker", NULL),
+
+ SND_SOC_DAPM_MIC("Main AMIC", NULL),
+ SND_SOC_DAPM_MIC("Main DMIC", NULL),
+};
+
+static struct snd_soc_dapm_route audio_paths[] = {
+ { "Sub IN1", NULL, "HPOUT2L" },
+ { "Sub IN2", NULL, "HPOUT2R" },
+
+ { "Main Speaker", NULL, "Sub SPKN" },
+ { "Main Speaker", NULL, "Sub SPKP" },
+ { "Main Speaker", NULL, "SPKDAT1" },
+};
+
+static struct snd_soc_card lowland = {
+ .name = "Lowland",
+ .owner = THIS_MODULE,
+ .dai_link = lowland_dai,
+ .num_links = ARRAY_SIZE(lowland_dai),
+ .aux_dev = lowland_aux_dev,
+ .num_aux_devs = ARRAY_SIZE(lowland_aux_dev),
+ .codec_conf = lowland_codec_conf,
+ .num_configs = ARRAY_SIZE(lowland_codec_conf),
+
+ .controls = controls,
+ .num_controls = ARRAY_SIZE(controls),
+ .dapm_widgets = widgets,
+ .num_dapm_widgets = ARRAY_SIZE(widgets),
+ .dapm_routes = audio_paths,
+ .num_dapm_routes = ARRAY_SIZE(audio_paths),
+};
+
+static __devinit int lowland_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &lowland;
+ int ret;
+
+ card->dev = &pdev->dev;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n",
+ ret);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int __devexit lowland_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+
+ snd_soc_unregister_card(card);
+
+ return 0;
+}
+
+static struct platform_driver lowland_driver = {
+ .driver = {
+ .name = "lowland",
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ },
+ .probe = lowland_probe,
+ .remove = __devexit_p(lowland_remove),
+};
+
+module_platform_driver(lowland_driver);
+
+MODULE_DESCRIPTION("Lowland audio support");
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:lowland");
diff --git a/sound/soc/samsung/neo1973_wm8753.c b/sound/soc/samsung/neo1973_wm8753.c
index 16152ed08648..321d51134e47 100644
--- a/sound/soc/samsung/neo1973_wm8753.c
+++ b/sound/soc/samsung/neo1973_wm8753.c
@@ -230,8 +230,6 @@ static const struct snd_kcontrol_new neo1973_wm8753_controls[] = {
/* GTA02 specific routes and controls */
-#ifdef CONFIG_MACH_NEO1973_GTA02
-
static int gta02_speaker_enabled;
static int lm4853_set_spk(struct snd_kcontrol *kcontrol,
@@ -298,7 +296,7 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
if (ret)
return ret;
- ret = snd_soc_add_controls(codec, neo1973_gta02_wm8753_controls,
+ ret = snd_soc_add_card_controls(codec->card, neo1973_gta02_wm8753_controls,
ARRAY_SIZE(neo1973_gta02_wm8753_controls));
if (ret)
return ret;
@@ -311,10 +309,6 @@ static int neo1973_gta02_wm8753_init(struct snd_soc_codec *codec)
return 0;
}
-#else
-static int neo1973_gta02_wm8753_init(struct snd_soc_code *codec) { return 0; }
-#endif
-
static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
{
struct snd_soc_codec *codec = rtd->codec;
@@ -322,10 +316,6 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
int ret;
/* set up NC codec pins */
- if (machine_is_neo1973_gta01()) {
- snd_soc_dapm_nc_pin(dapm, "LOUT2");
- snd_soc_dapm_nc_pin(dapm, "ROUT2");
- }
snd_soc_dapm_nc_pin(dapm, "OUT3");
snd_soc_dapm_nc_pin(dapm, "OUT4");
snd_soc_dapm_nc_pin(dapm, "LINE1");
@@ -338,7 +328,7 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
return ret;
/* add neo1973 specific controls */
- ret = snd_soc_add_controls(codec, neo1973_wm8753_controls,
+ ret = snd_soc_add_card_controls(rtd->card, neo1973_wm8753_controls,
ARRAY_SIZE(neo1973_wm8753_controls));
if (ret)
return ret;
@@ -367,57 +357,9 @@ static int neo1973_wm8753_init(struct snd_soc_pcm_runtime *rtd)
return ret;
}
- snd_soc_dapm_sync(dapm);
-
return 0;
}
-/* GTA01 specific controls */
-
-#ifdef CONFIG_MACH_NEO1973_GTA01
-
-static const struct snd_soc_dapm_route neo1973_lm4857_routes[] = {
- {"Amp IN", NULL, "ROUT1"},
- {"Amp IN", NULL, "LOUT1"},
-
- {"Handset Spk", NULL, "Amp EP"},
- {"Stereo Out", NULL, "Amp LS"},
- {"Headphone", NULL, "Amp HP"},
-};
-
-static const struct snd_soc_dapm_widget neo1973_lm4857_dapm_widgets[] = {
- SND_SOC_DAPM_SPK("Handset Spk", NULL),
- SND_SOC_DAPM_SPK("Stereo Out", NULL),
- SND_SOC_DAPM_HP("Headphone", NULL),
-};
-
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm)
-{
- int ret;
-
- ret = snd_soc_dapm_new_controls(dapm, neo1973_lm4857_dapm_widgets,
- ARRAY_SIZE(neo1973_lm4857_dapm_widgets));
- if (ret)
- return ret;
-
- ret = snd_soc_dapm_add_routes(dapm, neo1973_lm4857_routes,
- ARRAY_SIZE(neo1973_lm4857_routes));
- if (ret)
- return ret;
-
- snd_soc_dapm_ignore_suspend(dapm, "Stereo Out");
- snd_soc_dapm_ignore_suspend(dapm, "Handset Spk");
- snd_soc_dapm_ignore_suspend(dapm, "Headphone");
-
- snd_soc_dapm_sync(dapm);
-
- return 0;
-}
-
-#else
-static int neo1973_lm4857_init(struct snd_soc_dapm_context *dapm) { return 0; };
-#endif
-
static struct snd_soc_dai_link neo1973_dai[] = {
{ /* Hifi Playback - for similatious use with voice below */
.name = "WM8753",
@@ -425,7 +367,7 @@ static struct snd_soc_dai_link neo1973_dai[] = {
.platform_name = "samsung-audio",
.cpu_dai_name = "s3c24xx-iis",
.codec_dai_name = "wm8753-hifi",
- .codec_name = "wm8753-codec.0-001a",
+ .codec_name = "wm8753.0-001a",
.init = neo1973_wm8753_init,
.ops = &neo1973_hifi_ops,
},
@@ -434,7 +376,7 @@ static struct snd_soc_dai_link neo1973_dai[] = {
.stream_name = "Voice",
.cpu_dai_name = "dfbmcs320-pcm",
.codec_dai_name = "wm8753-voice",
- .codec_name = "wm8753-codec.0-001a",
+ .codec_name = "wm8753.0-001a",
.ops = &neo1973_voice_ops,
},
};
@@ -444,11 +386,6 @@ static struct snd_soc_aux_dev neo1973_aux_devs[] = {
.name = "dfbmcs320",
.codec_name = "dfbmcs320.0",
},
- {
- .name = "lm4857",
- .codec_name = "lm4857.0-007c",
- .init = neo1973_lm4857_init,
- },
};
static struct snd_soc_codec_conf neo1973_codec_conf[] = {
@@ -458,17 +395,14 @@ static struct snd_soc_codec_conf neo1973_codec_conf[] = {
},
};
-#ifdef CONFIG_MACH_NEO1973_GTA02
static const struct gpio neo1973_gta02_gpios[] = {
{ GTA02_GPIO_HP_IN, GPIOF_OUT_INIT_HIGH, "GTA02_HP_IN" },
{ GTA02_GPIO_AMP_SHUT, GPIOF_OUT_INIT_HIGH, "GTA02_AMP_SHUT" },
};
-#else
-static const struct gpio neo1973_gta02_gpios[] = {};
-#endif
static struct snd_soc_card neo1973 = {
.name = "neo1973",
+ .owner = THIS_MODULE,
.dai_link = neo1973_dai,
.num_links = ARRAY_SIZE(neo1973_dai),
.aux_dev = neo1973_aux_devs,
@@ -483,7 +417,7 @@ static int __init neo1973_init(void)
{
int ret;
- if (!machine_is_neo1973_gta01() && !machine_is_neo1973_gta02())
+ if (!machine_is_neo1973_gta02())
return -ENODEV;
if (machine_is_neo1973_gta02()) {
diff --git a/sound/soc/samsung/pcm.c b/sound/soc/samsung/pcm.c
index 9c7e8b48aed6..b7b2a1f91425 100644
--- a/sound/soc/samsung/pcm.c
+++ b/sound/soc/samsung/pcm.c
@@ -3,7 +3,7 @@
* ALSA SoC Audio Layer - S3C PCM-Controller driver
*
* Copyright (c) 2009 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@gmail.com>
* based upon I2S drivers by Ben Dooks.
*
* This program is free software; you can redistribute it and/or modify
@@ -13,6 +13,8 @@
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/pm_runtime.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
@@ -451,7 +453,7 @@ static int s3c_pcm_set_sysclk(struct snd_soc_dai *cpu_dai,
return 0;
}
-static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
+static const struct snd_soc_dai_ops s3c_pcm_dai_ops = {
.set_sysclk = s3c_pcm_set_sysclk,
.set_clkdiv = s3c_pcm_set_clkdiv,
.trigger = s3c_pcm_trigger,
@@ -477,7 +479,7 @@ static struct snd_soc_dai_ops s3c_pcm_dai_ops = {
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
}
-struct snd_soc_dai_driver s3c_pcm_dai[] = {
+static struct snd_soc_dai_driver s3c_pcm_dai[] = {
[0] = {
.name = "samsung-pcm.0",
S3C_PCM_DAI_DECLARE,
@@ -487,7 +489,6 @@ struct snd_soc_dai_driver s3c_pcm_dai[] = {
S3C_PCM_DAI_DECLARE,
},
};
-EXPORT_SYMBOL_GPL(s3c_pcm_dai);
static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
{
@@ -569,12 +570,6 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
}
clk_enable(pcm->pclk);
- ret = snd_soc_register_dai(&pdev->dev, &s3c_pcm_dai[pdev->id]);
- if (ret != 0) {
- dev_err(&pdev->dev, "failed to get pcm_clock\n");
- goto err5;
- }
-
s3c_pcm_stereo_in[pdev->id].dma_addr = mem_res->start
+ S3C_PCM_RXFIFO;
s3c_pcm_stereo_out[pdev->id].dma_addr = mem_res->start
@@ -586,6 +581,14 @@ static __devinit int s3c_pcm_dev_probe(struct platform_device *pdev)
pcm->dma_capture = &s3c_pcm_stereo_in[pdev->id];
pcm->dma_playback = &s3c_pcm_stereo_out[pdev->id];
+ pm_runtime_enable(&pdev->dev);
+
+ ret = snd_soc_register_dai(&pdev->dev, &s3c_pcm_dai[pdev->id]);
+ if (ret != 0) {
+ dev_err(&pdev->dev, "failed to get register DAI: %d\n", ret);
+ goto err5;
+ }
+
return 0;
err5:
@@ -609,6 +612,8 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
snd_soc_unregister_dai(&pdev->dev);
+ pm_runtime_disable(&pdev->dev);
+
iounmap(pcm->regs);
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -624,27 +629,17 @@ static __devexit int s3c_pcm_dev_remove(struct platform_device *pdev)
static struct platform_driver s3c_pcm_driver = {
.probe = s3c_pcm_dev_probe,
- .remove = s3c_pcm_dev_remove,
+ .remove = __devexit_p(s3c_pcm_dev_remove),
.driver = {
.name = "samsung-pcm",
.owner = THIS_MODULE,
},
};
-static int __init s3c_pcm_init(void)
-{
- return platform_driver_register(&s3c_pcm_driver);
-}
-module_init(s3c_pcm_init);
-
-static void __exit s3c_pcm_exit(void)
-{
- platform_driver_unregister(&s3c_pcm_driver);
-}
-module_exit(s3c_pcm_exit);
+module_platform_driver(s3c_pcm_driver);
/* Module information */
-MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
+MODULE_AUTHOR("Jaswinder Singh, <jassisinghbrar@gmail.com>");
MODULE_DESCRIPTION("S3C PCM Controller Driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:samsung-pcm");
diff --git a/sound/soc/samsung/rx1950_uda1380.c b/sound/soc/samsung/rx1950_uda1380.c
index bc8c1676459f..21e12361a9cd 100644
--- a/sound/soc/samsung/rx1950_uda1380.c
+++ b/sound/soc/samsung/rx1950_uda1380.c
@@ -19,6 +19,7 @@
#include <linux/types.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/jack.h>
@@ -90,12 +91,6 @@ static struct snd_soc_dai_link rx1950_uda1380_dai[] = {
},
};
-static struct snd_soc_card rx1950_asoc = {
- .name = "rx1950",
- .dai_link = rx1950_uda1380_dai,
- .num_links = ARRAY_SIZE(rx1950_uda1380_dai),
-};
-
/* rx1950 machine dapm widgets */
static const struct snd_soc_dapm_widget uda1380_dapm_widgets[] = {
SND_SOC_DAPM_HP("Headphone Jack", NULL),
@@ -117,6 +112,18 @@ static const struct snd_soc_dapm_route audio_map[] = {
{"VINM", NULL, "Mic Jack"},
};
+static struct snd_soc_card rx1950_asoc = {
+ .name = "rx1950",
+ .owner = THIS_MODULE,
+ .dai_link = rx1950_uda1380_dai,
+ .num_links = ARRAY_SIZE(rx1950_uda1380_dai),
+
+ .dapm_widgets = uda1380_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(uda1380_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+};
+
static struct platform_device *s3c24xx_snd_device;
static int rx1950_startup(struct snd_pcm_substream *substream)
@@ -220,26 +227,10 @@ static int rx1950_uda1380_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
int err;
- /* Add rx1950 specific widgets */
- err = snd_soc_dapm_new_controls(dapm, uda1380_dapm_widgets,
- ARRAY_SIZE(uda1380_dapm_widgets));
-
- if (err)
- return err;
-
- /* Set up rx1950 specific audio path audio_mapnects */
- err = snd_soc_dapm_add_routes(dapm, audio_map,
- ARRAY_SIZE(audio_map));
-
- if (err)
- return err;
-
snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Speaker");
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
- snd_soc_dapm_sync(dapm);
-
snd_soc_jack_new(codec, "Headphone Jack", SND_JACK_HEADPHONE,
&hp_jack);
diff --git a/sound/soc/samsung/s3c-i2s-v2.c b/sound/soc/samsung/s3c-i2s-v2.c
index 52074a2b0696..7a73380b3560 100644
--- a/sound/soc/samsung/s3c-i2s-v2.c
+++ b/sound/soc/samsung/s3c-i2s-v2.c
@@ -16,6 +16,7 @@
* option) any later version.
*/
+#include <linux/module.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/io.h>
diff --git a/sound/soc/samsung/s3c2412-i2s.c b/sound/soc/samsung/s3c2412-i2s.c
index 841ab14c1100..72185078ddf8 100644
--- a/sound/soc/samsung/s3c2412-i2s.c
+++ b/sound/soc/samsung/s3c2412-i2s.c
@@ -20,6 +20,7 @@
#include <linux/gpio.h>
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
@@ -69,10 +70,10 @@ static int s3c2412_i2s_probe(struct snd_soc_dai *dai)
s3c2412_i2s.dma_playback = &s3c2412_i2s_pcm_stereo_out;
s3c2412_i2s.iis_cclk = clk_get(dai->dev, "i2sclk");
- if (s3c2412_i2s.iis_cclk == NULL) {
+ if (IS_ERR(s3c2412_i2s.iis_cclk)) {
pr_err("failed to get i2sclk clock\n");
iounmap(s3c2412_i2s.regs);
- return -ENODEV;
+ return PTR_ERR(s3c2412_i2s.iis_cclk);
}
/* Set MPLL as the source for IIS CLK */
@@ -141,7 +142,7 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-static struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
+static const struct snd_soc_dai_ops s3c2412_i2s_dai_ops = {
.hw_params = s3c2412_i2s_hw_params,
};
@@ -176,24 +177,14 @@ static __devexit int s3c2412_iis_dev_remove(struct platform_device *pdev)
static struct platform_driver s3c2412_iis_driver = {
.probe = s3c2412_iis_dev_probe,
- .remove = s3c2412_iis_dev_remove,
+ .remove = __devexit_p(s3c2412_iis_dev_remove),
.driver = {
.name = "s3c2412-iis",
.owner = THIS_MODULE,
},
};
-static int __init s3c2412_i2s_init(void)
-{
- return platform_driver_register(&s3c2412_iis_driver);
-}
-module_init(s3c2412_i2s_init);
-
-static void __exit s3c2412_i2s_exit(void)
-{
- platform_driver_unregister(&s3c2412_iis_driver);
-}
-module_exit(s3c2412_i2s_exit);
+module_platform_driver(s3c2412_iis_driver);
/* Module information */
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
diff --git a/sound/soc/samsung/s3c24xx-i2s.c b/sound/soc/samsung/s3c24xx-i2s.c
index 63d8849d80bd..c4aa4d412fbf 100644
--- a/sound/soc/samsung/s3c24xx-i2s.c
+++ b/sound/soc/samsung/s3c24xx-i2s.c
@@ -18,6 +18,7 @@
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
@@ -383,10 +384,10 @@ static int s3c24xx_i2s_probe(struct snd_soc_dai *dai)
return -ENXIO;
s3c24xx_i2s.iis_clk = clk_get(dai->dev, "iis");
- if (s3c24xx_i2s.iis_clk == NULL) {
+ if (IS_ERR(s3c24xx_i2s.iis_clk)) {
pr_err("failed to get iis_clock\n");
iounmap(s3c24xx_i2s.regs);
- return -ENODEV;
+ return PTR_ERR(s3c24xx_i2s.iis_clk);
}
clk_enable(s3c24xx_i2s.iis_clk);
@@ -443,7 +444,7 @@ static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-static struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
+static const struct snd_soc_dai_ops s3c24xx_i2s_dai_ops = {
.trigger = s3c24xx_i2s_trigger,
.hw_params = s3c24xx_i2s_hw_params,
.set_fmt = s3c24xx_i2s_set_fmt,
@@ -481,24 +482,14 @@ static __devexit int s3c24xx_iis_dev_remove(struct platform_device *pdev)
static struct platform_driver s3c24xx_iis_driver = {
.probe = s3c24xx_iis_dev_probe,
- .remove = s3c24xx_iis_dev_remove,
+ .remove = __devexit_p(s3c24xx_iis_dev_remove),
.driver = {
.name = "s3c24xx-iis",
.owner = THIS_MODULE,
},
};
-static int __init s3c24xx_i2s_init(void)
-{
- return platform_driver_register(&s3c24xx_iis_driver);
-}
-module_init(s3c24xx_i2s_init);
-
-static void __exit s3c24xx_i2s_exit(void)
-{
- platform_driver_unregister(&s3c24xx_iis_driver);
-}
-module_exit(s3c24xx_i2s_exit);
+module_platform_driver(s3c24xx_iis_driver);
/* Module information */
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c
index 349566f0686b..656d5afe4ca9 100644
--- a/sound/soc/samsung/s3c24xx_simtec.c
+++ b/sound/soc/samsung/s3c24xx_simtec.c
@@ -9,6 +9,7 @@
#include <linux/gpio.h>
#include <linux/clk.h>
+#include <linux/module.h>
#include <sound/soc.h>
@@ -133,18 +134,18 @@ static const struct snd_kcontrol_new amp_unmute_controls[] = {
void simtec_audio_init(struct snd_soc_pcm_runtime *rtd)
{
- struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = rtd->card;
if (pdata->amp_gpio > 0) {
pr_debug("%s: adding amp routes\n", __func__);
- snd_soc_add_controls(codec, amp_unmute_controls,
+ snd_soc_add_card_controls(card, amp_unmute_controls,
ARRAY_SIZE(amp_unmute_controls));
}
if (pdata->amp_gain[0] > 0) {
pr_debug("%s: adding amp controls\n", __func__);
- snd_soc_add_controls(codec, amp_gain_controls,
+ snd_soc_add_card_controls(card, amp_gain_controls,
ARRAY_SIZE(amp_gain_controls));
}
}
@@ -300,7 +301,7 @@ static void detach_gpio_amp(struct s3c24xx_audio_simtec_pdata *pd)
}
#ifdef CONFIG_PM
-int simtec_audio_resume(struct device *dev)
+static int simtec_audio_resume(struct device *dev)
{
simtec_call_startup(pdata);
return 0;
diff --git a/sound/soc/samsung/s3c24xx_simtec_hermes.c b/sound/soc/samsung/s3c24xx_simtec_hermes.c
index ce6aef604179..7ace6a87f41b 100644
--- a/sound/soc/samsung/s3c24xx_simtec_hermes.c
+++ b/sound/soc/samsung/s3c24xx_simtec_hermes.c
@@ -7,6 +7,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/module.h>
#include <sound/soc.h>
#include "s3c24xx_simtec.h"
@@ -65,18 +66,12 @@ static int simtec_hermes_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- snd_soc_dapm_new_controls(dapm, dapm_widgets,
- ARRAY_SIZE(dapm_widgets));
-
- snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map));
-
snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Line In");
snd_soc_dapm_enable_pin(dapm, "Line Out");
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
simtec_audio_init(rtd);
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -94,8 +89,14 @@ static struct snd_soc_dai_link simtec_dai_aic33 = {
/* simtec audio machine driver */
static struct snd_soc_card snd_soc_machine_simtec_aic33 = {
.name = "Simtec-Hermes",
+ .owner = THIS_MODULE,
.dai_link = &simtec_dai_aic33,
.num_links = 1,
+
+ .dapm_widgets = dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
+ .dapm_routes = base_map,
+ .num_dapm_routes = ARRAY_SIZE(base_map),
};
static int __devinit simtec_audio_hermes_probe(struct platform_device *pd)
@@ -114,21 +115,9 @@ static struct platform_driver simtec_audio_hermes_platdrv = {
.remove = __devexit_p(simtec_audio_remove),
};
-MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd");
-
-static int __init simtec_hermes_modinit(void)
-{
- return platform_driver_register(&simtec_audio_hermes_platdrv);
-}
-
-static void __exit simtec_hermes_modexit(void)
-{
- platform_driver_unregister(&simtec_audio_hermes_platdrv);
-}
-
-module_init(simtec_hermes_modinit);
-module_exit(simtec_hermes_modexit);
+module_platform_driver(simtec_audio_hermes_platdrv);
+MODULE_ALIAS("platform:s3c24xx-simtec-hermes-snd");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
index a7ef7db54687..c42d5f00b0e1 100644
--- a/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
+++ b/sound/soc/samsung/s3c24xx_simtec_tlv320aic23.c
@@ -7,6 +7,7 @@
* published by the Free Software Foundation.
*/
+#include <linux/module.h>
#include <sound/soc.h>
#include "s3c24xx_simtec.h"
@@ -54,18 +55,12 @@ static int simtec_tlv320aic23_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- snd_soc_dapm_new_controls(dapm, dapm_widgets,
- ARRAY_SIZE(dapm_widgets));
-
- snd_soc_dapm_add_routes(dapm, base_map, ARRAY_SIZE(base_map));
-
snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
snd_soc_dapm_enable_pin(dapm, "Line In");
snd_soc_dapm_enable_pin(dapm, "Line Out");
snd_soc_dapm_enable_pin(dapm, "Mic Jack");
simtec_audio_init(rtd);
- snd_soc_dapm_sync(dapm);
return 0;
}
@@ -83,8 +78,14 @@ static struct snd_soc_dai_link simtec_dai_aic23 = {
/* simtec audio machine driver */
static struct snd_soc_card snd_soc_machine_simtec_aic23 = {
.name = "Simtec",
+ .owner = THIS_MODULE,
.dai_link = &simtec_dai_aic23,
.num_links = 1,
+
+ .dapm_widgets = dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(dapm_widgets),
+ .dapm_routes = base_map,
+ .num_dapm_routes = ARRAY_SIZE(base_map),
};
static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
@@ -92,7 +93,7 @@ static int __devinit simtec_audio_tlv320aic23_probe(struct platform_device *pd)
return simtec_audio_core_probe(pd, &snd_soc_machine_simtec_aic23);
}
-static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
+static struct platform_driver simtec_audio_tlv320aic23_driver = {
.driver = {
.owner = THIS_MODULE,
.name = "s3c24xx-simtec-tlv320aic23",
@@ -102,21 +103,9 @@ static struct platform_driver simtec_audio_tlv320aic23_platdrv = {
.remove = __devexit_p(simtec_audio_remove),
};
-MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23");
-
-static int __init simtec_tlv320aic23_modinit(void)
-{
- return platform_driver_register(&simtec_audio_tlv320aic23_platdrv);
-}
-
-static void __exit simtec_tlv320aic23_modexit(void)
-{
- platform_driver_unregister(&simtec_audio_tlv320aic23_platdrv);
-}
-
-module_init(simtec_tlv320aic23_modinit);
-module_exit(simtec_tlv320aic23_modexit);
+module_platform_driver(simtec_audio_tlv320aic23_driver);
+MODULE_ALIAS("platform:s3c24xx-simtec-tlv320aic23");
MODULE_AUTHOR("Ben Dooks <ben@simtec.co.uk>");
MODULE_DESCRIPTION("ALSA SoC Simtec Audio support");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/s3c24xx_uda134x.c b/sound/soc/samsung/s3c24xx_uda134x.c
index dc9d551f6788..d731042e51b0 100644
--- a/sound/soc/samsung/s3c24xx_uda134x.c
+++ b/sound/soc/samsung/s3c24xx_uda134x.c
@@ -13,6 +13,7 @@
#include <linux/clk.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/s3c24xx_uda134x.h>
@@ -66,17 +67,17 @@ static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
pr_debug("%s %d\n", __func__, clk_users);
if (clk_users == 0) {
xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
- if (!xtal) {
+ if (IS_ERR(xtal)) {
printk(KERN_ERR "%s cannot get xtal\n", __func__);
- ret = -EBUSY;
+ ret = PTR_ERR(xtal);
} else {
pclk = clk_get(&s3c24xx_uda134x_snd_device->dev,
"pclk");
- if (!pclk) {
+ if (IS_ERR(pclk)) {
printk(KERN_ERR "%s cannot get pclk\n",
__func__);
clk_put(xtal);
- ret = -EBUSY;
+ ret = PTR_ERR(pclk);
}
}
if (!ret) {
@@ -228,6 +229,7 @@ static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
.name = "S3C24XX_UDA134X",
+ .owner = THIS_MODULE,
.dai_link = &s3c24xx_uda134x_dai_link,
.num_links = 1,
};
@@ -342,19 +344,7 @@ static struct platform_driver s3c24xx_uda134x_driver = {
},
};
-static int __init s3c24xx_uda134x_init(void)
-{
- return platform_driver_register(&s3c24xx_uda134x_driver);
-}
-
-static void __exit s3c24xx_uda134x_exit(void)
-{
- platform_driver_unregister(&s3c24xx_uda134x_driver);
-}
-
-
-module_init(s3c24xx_uda134x_init);
-module_exit(s3c24xx_uda134x_exit);
+module_platform_driver(s3c24xx_uda134x_driver);
MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver");
diff --git a/sound/soc/samsung/smartq_wm8987.c b/sound/soc/samsung/smartq_wm8987.c
index 0a2c4f223038..f2dcb424ea25 100644
--- a/sound/soc/samsung/smartq_wm8987.c
+++ b/sound/soc/samsung/smartq_wm8987.c
@@ -14,6 +14,7 @@
*/
#include <linux/gpio.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/jack.h>
@@ -153,20 +154,6 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
int err = 0;
- /* Add SmartQ specific widgets */
- snd_soc_dapm_new_controls(dapm, wm8987_dapm_widgets,
- ARRAY_SIZE(wm8987_dapm_widgets));
-
- /* add SmartQ specific controls */
- err = snd_soc_add_controls(codec, wm8987_smartq_controls,
- ARRAY_SIZE(wm8987_smartq_controls));
-
- if (err < 0)
- return err;
-
- /* setup SmartQ specific audio path */
- snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
-
/* set endpoints to not connected */
snd_soc_dapm_nc_pin(dapm, "LINPUT1");
snd_soc_dapm_nc_pin(dapm, "RINPUT1");
@@ -178,10 +165,6 @@ static int smartq_wm8987_init(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_enable_pin(dapm, "Internal Mic");
snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
- err = snd_soc_dapm_sync(dapm);
- if (err)
- return err;
-
/* Headphone jack detection */
err = snd_soc_jack_new(codec, "Headphone Jack",
SND_JACK_HEADPHONE, &smartq_jack);
@@ -207,7 +190,7 @@ static struct snd_soc_dai_link smartq_dai[] = {
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8750-hifi",
.platform_name = "samsung-audio",
- .codec_name = "wm8750-codec.0-0x1a",
+ .codec_name = "wm8750.0-0x1a",
.init = smartq_wm8987_init,
.ops = &smartq_hifi_ops,
},
@@ -215,8 +198,16 @@ static struct snd_soc_dai_link smartq_dai[] = {
static struct snd_soc_card snd_soc_smartq = {
.name = "SmartQ",
+ .owner = THIS_MODULE,
.dai_link = smartq_dai,
.num_links = ARRAY_SIZE(smartq_dai),
+
+ .dapm_widgets = wm8987_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(wm8987_dapm_widgets),
+ .dapm_routes = audio_map,
+ .num_dapm_routes = ARRAY_SIZE(audio_map),
+ .controls = wm8987_smartq_controls,
+ .num_controls = ARRAY_SIZE(wm8987_smartq_controls),
};
static struct platform_device *smartq_snd_device;
diff --git a/sound/soc/samsung/smdk2443_wm9710.c b/sound/soc/samsung/smdk2443_wm9710.c
index 3a0dbfc793f0..720ba29bb7e4 100644
--- a/sound/soc/samsung/smdk2443_wm9710.c
+++ b/sound/soc/samsung/smdk2443_wm9710.c
@@ -12,6 +12,7 @@
*
*/
+#include <linux/module.h>
#include <sound/soc.h>
static struct snd_soc_card smdk2443;
@@ -29,6 +30,7 @@ static struct snd_soc_dai_link smdk2443_dai[] = {
static struct snd_soc_card smdk2443 = {
.name = "SMDK2443",
+ .owner = THIS_MODULE,
.dai_link = smdk2443_dai,
.num_links = ARRAY_SIZE(smdk2443_dai),
};
diff --git a/sound/soc/samsung/smdk_spdif.c b/sound/soc/samsung/smdk_spdif.c
index e8ac961c6ba1..beaa9c15d697 100644
--- a/sound/soc/samsung/smdk_spdif.c
+++ b/sound/soc/samsung/smdk_spdif.c
@@ -11,6 +11,7 @@
*/
#include <linux/clk.h>
+#include <linux/module.h>
#include <sound/soc.h>
@@ -159,6 +160,7 @@ static struct snd_soc_dai_link smdk_dai = {
static struct snd_soc_card smdk = {
.name = "SMDK-S/PDIF",
+ .owner = THIS_MODULE,
.dai_link = &smdk_dai,
.num_links = 1,
};
diff --git a/sound/soc/samsung/smdk_wm8580.c b/sound/soc/samsung/smdk_wm8580.c
index 3d26f6607aa4..ade2809cf393 100644
--- a/sound/soc/samsung/smdk_wm8580.c
+++ b/sound/soc/samsung/smdk_wm8580.c
@@ -2,7 +2,7 @@
* smdk_wm8580.c
*
* Copyright (c) 2009 Samsung Electronics Co. Ltd
- * Author: Jaswinder Singh <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh <jassisinghbrar@gmail.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License as published by the
@@ -10,6 +10,7 @@
* option) any later version.
*/
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
@@ -119,30 +120,24 @@ static struct snd_soc_ops smdk_ops = {
};
/* SMDK Playback widgets */
-static const struct snd_soc_dapm_widget wm8580_dapm_widgets_pbk[] = {
+static const struct snd_soc_dapm_widget smdk_wm8580_dapm_widgets[] = {
SND_SOC_DAPM_HP("Front", NULL),
SND_SOC_DAPM_HP("Center+Sub", NULL),
SND_SOC_DAPM_HP("Rear", NULL),
-};
-/* SMDK Capture widgets */
-static const struct snd_soc_dapm_widget wm8580_dapm_widgets_cpt[] = {
SND_SOC_DAPM_MIC("MicIn", NULL),
SND_SOC_DAPM_LINE("LineIn", NULL),
};
/* SMDK-PAIFTX connections */
-static const struct snd_soc_dapm_route audio_map_tx[] = {
+static const struct snd_soc_dapm_route smdk_wm8580_audio_map[] = {
/* MicIn feeds AINL */
{"AINL", NULL, "MicIn"},
/* LineIn feeds AINL/R */
{"AINL", NULL, "LineIn"},
{"AINR", NULL, "LineIn"},
-};
-/* SMDK-PAIFRX connections */
-static const struct snd_soc_dapm_route audio_map_rx[] = {
/* Front Left/Right are fed VOUT1L/R */
{"Front", NULL, "VOUT1L"},
{"Front", NULL, "VOUT1R"},
@@ -161,39 +156,11 @@ static int smdk_wm8580_init_paiftx(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_dapm_context *dapm = &codec->dapm;
- /* Add smdk specific Capture widgets */
- snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_cpt,
- ARRAY_SIZE(wm8580_dapm_widgets_cpt));
-
- /* Set up PAIFTX audio path */
- snd_soc_dapm_add_routes(dapm, audio_map_tx, ARRAY_SIZE(audio_map_tx));
-
/* Enabling the microphone requires the fitting of a 0R
* resistor to connect the line from the microphone jack.
*/
snd_soc_dapm_disable_pin(dapm, "MicIn");
- /* signal a DAPM event */
- snd_soc_dapm_sync(dapm);
-
- return 0;
-}
-
-static int smdk_wm8580_init_paifrx(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_codec *codec = rtd->codec;
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- /* Add smdk specific Playback widgets */
- snd_soc_dapm_new_controls(dapm, wm8580_dapm_widgets_pbk,
- ARRAY_SIZE(wm8580_dapm_widgets_pbk));
-
- /* Set up PAIFRX audio path */
- snd_soc_dapm_add_routes(dapm, audio_map_rx, ARRAY_SIZE(audio_map_rx));
-
- /* signal a DAPM event */
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -210,8 +177,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8580-hifi-playback",
.platform_name = "samsung-audio",
- .codec_name = "wm8580-codec.0-001b",
- .init = smdk_wm8580_init_paifrx,
+ .codec_name = "wm8580.0-001b",
.ops = &smdk_ops,
},
[PRI_CAPTURE] = { /* Primary Capture i/f */
@@ -220,7 +186,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.cpu_dai_name = "samsung-i2s.0",
.codec_dai_name = "wm8580-hifi-capture",
.platform_name = "samsung-audio",
- .codec_name = "wm8580-codec.0-001b",
+ .codec_name = "wm8580.0-001b",
.init = smdk_wm8580_init_paiftx,
.ops = &smdk_ops,
},
@@ -230,16 +196,21 @@ static struct snd_soc_dai_link smdk_dai[] = {
.cpu_dai_name = "samsung-i2s.x",
.codec_dai_name = "wm8580-hifi-playback",
.platform_name = "samsung-audio",
- .codec_name = "wm8580-codec.0-001b",
- .init = smdk_wm8580_init_paifrx,
+ .codec_name = "wm8580.0-001b",
.ops = &smdk_ops,
},
};
static struct snd_soc_card smdk = {
.name = "SMDK-I2S",
+ .owner = THIS_MODULE,
.dai_link = smdk_dai,
.num_links = 2,
+
+ .dapm_widgets = smdk_wm8580_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(smdk_wm8580_dapm_widgets),
+ .dapm_routes = smdk_wm8580_audio_map,
+ .num_dapm_routes = ARRAY_SIZE(smdk_wm8580_audio_map),
};
static struct platform_device *smdk_snd_device;
@@ -282,6 +253,6 @@ static void __exit smdk_audio_exit(void)
}
module_exit(smdk_audio_exit);
-MODULE_AUTHOR("Jaswinder Singh, jassi.brar@samsung.com");
+MODULE_AUTHOR("Jaswinder Singh, jassisinghbrar@gmail.com");
MODULE_DESCRIPTION("ALSA SoC SMDK WM8580");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/smdk_wm8580pcm.c b/sound/soc/samsung/smdk_wm8580pcm.c
index 0d12092df164..fab5322e9f05 100644
--- a/sound/soc/samsung/smdk_wm8580pcm.c
+++ b/sound/soc/samsung/smdk_wm8580pcm.c
@@ -8,6 +8,7 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
#include <sound/pcm.h>
@@ -127,7 +128,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
.cpu_dai_name = "samsung-pcm.0",
.codec_dai_name = "wm8580-hifi-playback",
.platform_name = "samsung-audio",
- .codec_name = "wm8580-codec.0-001b",
+ .codec_name = "wm8580.0-001b",
.ops = &smdk_wm8580_pcm_ops,
}, {
.name = "WM8580 PAIF PCM TX",
@@ -135,13 +136,14 @@ static struct snd_soc_dai_link smdk_dai[] = {
.cpu_dai_name = "samsung-pcm.0",
.codec_dai_name = "wm8580-hifi-capture",
.platform_name = "samsung-audio",
- .codec_name = "wm8580-codec.0-001b",
+ .codec_name = "wm8580.0-001b",
.ops = &smdk_wm8580_pcm_ops,
},
};
static struct snd_soc_card smdk_pcm = {
.name = "SMDK-PCM",
+ .owner = THIS_MODULE,
.dai_link = smdk_dai,
.num_links = 2,
};
@@ -187,19 +189,7 @@ static struct platform_driver snd_smdk_driver = {
.remove = __devexit_p(snd_smdk_remove),
};
-static int __init smdk_audio_init(void)
-{
- return platform_driver_register(&snd_smdk_driver);
-}
-
-module_init(smdk_audio_init);
-
-static void __exit smdk_audio_exit(void)
-{
- platform_driver_unregister(&snd_smdk_driver);
-}
-
-module_exit(smdk_audio_exit);
+module_platform_driver(snd_smdk_driver);
MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
MODULE_DESCRIPTION("ALSA SoC SMDK WM8580 for PCM");
diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c
index 45fbe2b3727f..8eb309f23d18 100644
--- a/sound/soc/samsung/smdk_wm8994.c
+++ b/sound/soc/samsung/smdk_wm8994.c
@@ -9,6 +9,7 @@
#include "../codecs/wm8994.h"
#include <sound/pcm_params.h>
+#include <linux/module.h>
/*
* Default CFG switch settings to use this driver:
@@ -117,8 +118,6 @@ static int smdk_wm8994_init_paiftx(struct snd_soc_pcm_runtime *rtd)
snd_soc_dapm_nc_pin(dapm, "IN1RP");
snd_soc_dapm_nc_pin(dapm, "IN2RP:VXRP");
- snd_soc_dapm_sync(dapm);
-
return 0;
}
@@ -145,6 +144,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
static struct snd_soc_card smdk = {
.name = "SMDK-I2S",
+ .owner = THIS_MODULE,
.dai_link = smdk_dai,
.num_links = ARRAY_SIZE(smdk_dai),
};
diff --git a/sound/soc/samsung/smdk_wm8994pcm.c b/sound/soc/samsung/smdk_wm8994pcm.c
index 5f2111685480..77ecba935119 100644
--- a/sound/soc/samsung/smdk_wm8994pcm.c
+++ b/sound/soc/samsung/smdk_wm8994pcm.c
@@ -9,6 +9,7 @@
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*/
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -123,6 +124,7 @@ static struct snd_soc_dai_link smdk_dai[] = {
static struct snd_soc_card smdk_pcm = {
.name = "SMDK-PCM",
+ .owner = THIS_MODULE,
.dai_link = smdk_dai,
.num_links = 1,
};
@@ -157,19 +159,7 @@ static struct platform_driver snd_smdk_driver = {
.remove = __devexit_p(snd_smdk_remove),
};
-static int __init smdk_audio_init(void)
-{
- return platform_driver_register(&snd_smdk_driver);
-}
-
-module_init(smdk_audio_init);
-
-static void __exit smdk_audio_exit(void)
-{
- platform_driver_unregister(&snd_smdk_driver);
-}
-
-module_exit(smdk_audio_exit);
+module_platform_driver(snd_smdk_driver);
MODULE_AUTHOR("Sangbeom Kim, <sbkim73@samsung.com>");
MODULE_DESCRIPTION("ALSA SoC SMDK WM8994 for PCM");
diff --git a/sound/soc/samsung/smdk_wm9713.c b/sound/soc/samsung/smdk_wm9713.c
index fffe3c1dd1bd..55b2ca7f3290 100644
--- a/sound/soc/samsung/smdk_wm9713.c
+++ b/sound/soc/samsung/smdk_wm9713.c
@@ -2,7 +2,7 @@
* smdk_wm9713.c -- SoC audio for SMDK
*
* Copyright 2010 Samsung Electronics Co. Ltd.
- * Author: Jaswinder Singh Brar <jassi.brar@samsung.com>
+ * Author: Jaswinder Singh Brar <jassisinghbrar@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -11,6 +11,7 @@
*
*/
+#include <linux/module.h>
#include <sound/soc.h>
static struct snd_soc_card smdk;
@@ -49,6 +50,7 @@ static struct snd_soc_dai_link smdk_dai = {
static struct snd_soc_card smdk = {
.name = "SMDK WM9713",
+ .owner = THIS_MODULE,
.dai_link = &smdk_dai,
.num_links = 1,
};
@@ -101,6 +103,6 @@ module_init(smdk_init);
module_exit(smdk_exit);
/* Module information */
-MODULE_AUTHOR("Jaswinder Singh Brar, jassi.brar@samsung.com");
+MODULE_AUTHOR("Jaswinder Singh Brar, jassisinghbrar@gmail.com");
MODULE_DESCRIPTION("ALSA SoC SMDK+WM9713");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/samsung/spdif.c b/sound/soc/samsung/spdif.c
index 28c491dacf7a..a5a56a120345 100644
--- a/sound/soc/samsung/spdif.c
+++ b/sound/soc/samsung/spdif.c
@@ -12,6 +12,7 @@
#include <linux/clk.h>
#include <linux/io.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/pcm_params.h>
@@ -333,14 +334,14 @@ static int spdif_resume(struct snd_soc_dai *cpu_dai)
#define spdif_resume NULL
#endif
-static struct snd_soc_dai_ops spdif_dai_ops = {
+static const struct snd_soc_dai_ops spdif_dai_ops = {
.set_sysclk = spdif_set_sysclk,
.trigger = spdif_trigger,
.hw_params = spdif_hw_params,
.shutdown = spdif_shutdown,
};
-struct snd_soc_dai_driver samsung_spdif_dai = {
+static struct snd_soc_dai_driver samsung_spdif_dai = {
.name = "samsung-spdif",
.playback = {
.stream_name = "S/PDIF Playback",
@@ -475,24 +476,14 @@ static __devexit int spdif_remove(struct platform_device *pdev)
static struct platform_driver samsung_spdif_driver = {
.probe = spdif_probe,
- .remove = spdif_remove,
+ .remove = __devexit_p(spdif_remove),
.driver = {
.name = "samsung-spdif",
.owner = THIS_MODULE,
},
};
-static int __init spdif_init(void)
-{
- return platform_driver_register(&samsung_spdif_driver);
-}
-module_init(spdif_init);
-
-static void __exit spdif_exit(void)
-{
- platform_driver_unregister(&samsung_spdif_driver);
-}
-module_exit(spdif_exit);
+module_platform_driver(samsung_spdif_driver);
MODULE_AUTHOR("Seungwhan Youn, <sw.youn@samsung.com>");
MODULE_DESCRIPTION("Samsung S/PDIF Controller Driver");
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c
index 590e9274b062..f9ab7707a3e4 100644
--- a/sound/soc/samsung/speyside.c
+++ b/sound/soc/samsung/speyside.c
@@ -13,11 +13,13 @@
#include <sound/soc-dapm.h>
#include <sound/jack.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include "../codecs/wm8996.h"
#include "../codecs/wm9081.h"
#define WM8996_HPSEL_GPIO 214
+#define MCLK_AUDIO_RATE (512 * 48000)
static int speyside_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
@@ -66,7 +68,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card,
if (card->dapm.bias_level == SND_SOC_BIAS_STANDBY) {
ret = snd_soc_dai_set_pll(codec_dai, 0,
WM8996_FLL_MCLK2,
- 32768, 48000 * 256);
+ 32768, MCLK_AUDIO_RATE);
if (ret < 0) {
pr_err("Failed to start FLL\n");
return ret;
@@ -74,7 +76,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card,
ret = snd_soc_dai_set_sysclk(codec_dai,
WM8996_SYSCLK_FLL,
- 48000 * 256,
+ MCLK_AUDIO_RATE,
SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
@@ -125,10 +127,6 @@ static struct snd_soc_jack_pin speyside_headset_pins[] = {
.pin = "Headset Mic",
.mask = SND_JACK_MICROPHONE,
},
- {
- .pin = "Headphone",
- .mask = SND_JACK_HEADPHONE,
- },
};
/* Default the headphone selection to active high */
@@ -171,7 +169,8 @@ static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd)
gpio_direction_output(WM8996_HPSEL_GPIO, speyside_jack_polarity);
ret = snd_soc_jack_new(codec, "Headset",
- SND_JACK_HEADSET | SND_JACK_BTN_0,
+ SND_JACK_LINEOUT | SND_JACK_HEADSET |
+ SND_JACK_BTN_0,
&speyside_headset);
if (ret)
return ret;
@@ -193,7 +192,7 @@ static int speyside_late_probe(struct snd_soc_card *card)
snd_soc_dapm_ignore_suspend(&card->dapm, "Headset Mic");
snd_soc_dapm_ignore_suspend(&card->dapm, "Main AMIC");
snd_soc_dapm_ignore_suspend(&card->dapm, "Main DMIC");
- snd_soc_dapm_ignore_suspend(&card->dapm, "Speaker");
+ snd_soc_dapm_ignore_suspend(&card->dapm, "Main Speaker");
snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Output");
snd_soc_dapm_ignore_suspend(&card->dapm, "WM1250 Input");
@@ -224,11 +223,9 @@ static struct snd_soc_dai_link speyside_dai[] = {
static int speyside_wm9081_init(struct snd_soc_dapm_context *dapm)
{
- snd_soc_dapm_nc_pin(dapm, "LINEOUT");
-
/* At any time the WM9081 is active it will have this clock */
- return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK,
- 48000 * 256, 0);
+ return snd_soc_codec_set_sysclk(dapm->codec, WM9081_SYSCLK_MCLK, 0,
+ MCLK_AUDIO_RATE, 0);
}
static struct snd_soc_aux_dev speyside_aux_dev[] = {
@@ -252,6 +249,7 @@ static const struct snd_kcontrol_new controls[] = {
SOC_DAPM_PIN_SWITCH("Main AMIC"),
SOC_DAPM_PIN_SWITCH("WM1250 Input"),
SOC_DAPM_PIN_SWITCH("WM1250 Output"),
+ SOC_DAPM_PIN_SWITCH("Headphone"),
};
static struct snd_soc_dapm_widget widgets[] = {
@@ -293,6 +291,7 @@ static struct snd_soc_dapm_route audio_paths[] = {
static struct snd_soc_card speyside = {
.name = "Speyside",
+ .owner = THIS_MODULE,
.dai_link = speyside_dai,
.num_links = ARRAY_SIZE(speyside_dai),
.aux_dev = speyside_aux_dev,
@@ -309,6 +308,7 @@ static struct snd_soc_card speyside = {
.num_dapm_widgets = ARRAY_SIZE(widgets),
.dapm_routes = audio_paths,
.num_dapm_routes = ARRAY_SIZE(audio_paths),
+ .fully_routed = true,
.late_probe = speyside_late_probe,
};
@@ -349,17 +349,7 @@ static struct platform_driver speyside_driver = {
.remove = __devexit_p(speyside_remove),
};
-static int __init speyside_audio_init(void)
-{
- return platform_driver_register(&speyside_driver);
-}
-module_init(speyside_audio_init);
-
-static void __exit speyside_audio_exit(void)
-{
- platform_driver_unregister(&speyside_driver);
-}
-module_exit(speyside_audio_exit);
+module_platform_driver(speyside_driver);
MODULE_DESCRIPTION("Speyside audio support");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/sound/soc/samsung/speyside_wm8962.c b/sound/soc/samsung/tobermory.c
index 72535f2daaf2..9199649bf786 100644
--- a/sound/soc/samsung/speyside_wm8962.c
+++ b/sound/soc/samsung/tobermory.c
@@ -1,5 +1,5 @@
/*
- * Speyside with WM8962 audio support
+ * Tobermory audio support
*
* Copyright 2011 Wolfson Microelectronics
*
@@ -13,10 +13,13 @@
#include <sound/soc-dapm.h>
#include <sound/jack.h>
#include <linux/gpio.h>
+#include <linux/module.h>
#include "../codecs/wm8962.h"
-static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
+static int sample_rate = 44100;
+
+static int tobermory_set_bias_level(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
@@ -31,13 +34,13 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
if (dapm->bias_level == SND_SOC_BIAS_STANDBY) {
ret = snd_soc_dai_set_pll(codec_dai, WM8962_FLL,
WM8962_FLL_MCLK, 32768,
- 44100 * 256);
+ sample_rate * 512);
if (ret < 0)
pr_err("Failed to start FLL: %d\n", ret);
ret = snd_soc_dai_set_sysclk(codec_dai,
WM8962_SYSCLK_FLL,
- 44100 * 256,
+ sample_rate * 512,
SND_SOC_CLOCK_IN);
if (ret < 0) {
pr_err("Failed to set SYSCLK: %d\n", ret);
@@ -53,7 +56,7 @@ static int speyside_wm8962_set_bias_level(struct snd_soc_card *card,
return 0;
}
-static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
+static int tobermory_set_bias_level_post(struct snd_soc_card *card,
struct snd_soc_dapm_context *dapm,
enum snd_soc_bias_level level)
{
@@ -89,34 +92,19 @@ static int speyside_wm8962_set_bias_level_post(struct snd_soc_card *card,
return 0;
}
-static int speyside_wm8962_hw_params(struct snd_pcm_substream *substream,
+static int tobermory_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
- int ret;
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S
- | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S
- | SND_SOC_DAIFMT_NB_NF
- | SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0)
- return ret;
+ sample_rate = params_rate(params);
return 0;
}
-static struct snd_soc_ops speyside_wm8962_ops = {
- .hw_params = speyside_wm8962_hw_params,
+static struct snd_soc_ops tobermory_ops = {
+ .hw_params = tobermory_hw_params,
};
-static struct snd_soc_dai_link speyside_wm8962_dai[] = {
+static struct snd_soc_dai_link tobermory_dai[] = {
{
.name = "CPU",
.stream_name = "CPU",
@@ -124,12 +112,15 @@ static struct snd_soc_dai_link speyside_wm8962_dai[] = {
.codec_dai_name = "wm8962",
.platform_name = "samsung-audio",
.codec_name = "wm8962.1-001a",
- .ops = &speyside_wm8962_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBM_CFM,
+ .ops = &tobermory_ops,
},
};
static const struct snd_kcontrol_new controls[] = {
SOC_DAPM_PIN_SWITCH("Main Speaker"),
+ SOC_DAPM_PIN_SWITCH("DMIC"),
};
static struct snd_soc_dapm_widget widgets[] = {
@@ -137,6 +128,7 @@ static struct snd_soc_dapm_widget widgets[] = {
SND_SOC_DAPM_MIC("Headset Mic", NULL),
SND_SOC_DAPM_MIC("DMIC", NULL),
+ SND_SOC_DAPM_MIC("AMIC", NULL),
SND_SOC_DAPM_SPK("Main Speaker", NULL),
};
@@ -148,18 +140,22 @@ static struct snd_soc_dapm_route audio_paths[] = {
{ "Main Speaker", NULL, "SPKOUTL" },
{ "Main Speaker", NULL, "SPKOUTR" },
- { "MICBIAS", NULL, "Headset Mic" },
- { "IN4L", NULL, "MICBIAS" },
- { "IN4R", NULL, "MICBIAS" },
+ { "Headset Mic", NULL, "MICBIAS" },
+ { "IN4L", NULL, "Headset Mic" },
+ { "IN4R", NULL, "Headset Mic" },
+
+ { "AMIC", NULL, "MICBIAS" },
+ { "IN1L", NULL, "AMIC" },
+ { "IN1R", NULL, "AMIC" },
- { "MICBIAS", NULL, "DMIC" },
- { "DMICDAT", NULL, "MICBIAS" },
+ { "DMIC", NULL, "MICBIAS" },
+ { "DMICDAT", NULL, "DMIC" },
};
-static struct snd_soc_jack speyside_wm8962_headset;
+static struct snd_soc_jack tobermory_headset;
/* Headset jack detection DAPM pins */
-static struct snd_soc_jack_pin speyside_wm8962_headset_pins[] = {
+static struct snd_soc_jack_pin tobermory_headset_pins[] = {
{
.pin = "Headset Mic",
.mask = SND_JACK_MICROPHONE,
@@ -170,7 +166,7 @@ static struct snd_soc_jack_pin speyside_wm8962_headset_pins[] = {
},
};
-static int speyside_wm8962_late_probe(struct snd_soc_card *card)
+static int tobermory_late_probe(struct snd_soc_card *card)
{
struct snd_soc_codec *codec = card->rtd[0].codec;
struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai;
@@ -183,28 +179,29 @@ static int speyside_wm8962_late_probe(struct snd_soc_card *card)
ret = snd_soc_jack_new(codec, "Headset",
SND_JACK_HEADSET | SND_JACK_BTN_0,
- &speyside_wm8962_headset);
+ &tobermory_headset);
if (ret)
return ret;
- ret = snd_soc_jack_add_pins(&speyside_wm8962_headset,
- ARRAY_SIZE(speyside_wm8962_headset_pins),
- speyside_wm8962_headset_pins);
+ ret = snd_soc_jack_add_pins(&tobermory_headset,
+ ARRAY_SIZE(tobermory_headset_pins),
+ tobermory_headset_pins);
if (ret)
return ret;
- wm8962_mic_detect(codec, &speyside_wm8962_headset);
+ wm8962_mic_detect(codec, &tobermory_headset);
return 0;
}
-static struct snd_soc_card speyside_wm8962 = {
- .name = "Speyside WM8962",
- .dai_link = speyside_wm8962_dai,
- .num_links = ARRAY_SIZE(speyside_wm8962_dai),
+static struct snd_soc_card tobermory = {
+ .name = "Tobermory",
+ .owner = THIS_MODULE,
+ .dai_link = tobermory_dai,
+ .num_links = ARRAY_SIZE(tobermory_dai),
- .set_bias_level = speyside_wm8962_set_bias_level,
- .set_bias_level_post = speyside_wm8962_set_bias_level_post,
+ .set_bias_level = tobermory_set_bias_level,
+ .set_bias_level_post = tobermory_set_bias_level_post,
.controls = controls,
.num_controls = ARRAY_SIZE(controls),
@@ -212,13 +209,14 @@ static struct snd_soc_card speyside_wm8962 = {
.num_dapm_widgets = ARRAY_SIZE(widgets),
.dapm_routes = audio_paths,
.num_dapm_routes = ARRAY_SIZE(audio_paths),
+ .fully_routed = true,
- .late_probe = speyside_wm8962_late_probe,
+ .late_probe = tobermory_late_probe,
};
-static __devinit int speyside_wm8962_probe(struct platform_device *pdev)
+static __devinit int tobermory_probe(struct platform_device *pdev)
{
- struct snd_soc_card *card = &speyside_wm8962;
+ struct snd_soc_card *card = &tobermory;
int ret;
card->dev = &pdev->dev;
@@ -233,7 +231,7 @@ static __devinit int speyside_wm8962_probe(struct platform_device *pdev)
return 0;
}
-static int __devexit speyside_wm8962_remove(struct platform_device *pdev)
+static int __devexit tobermory_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
@@ -242,29 +240,19 @@ static int __devexit speyside_wm8962_remove(struct platform_device *pdev)
return 0;
}
-static struct platform_driver speyside_wm8962_driver = {
+static struct platform_driver tobermory_driver = {
.driver = {
- .name = "speyside-wm8962",
+ .name = "tobermory",
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops,
},
- .probe = speyside_wm8962_probe,
- .remove = __devexit_p(speyside_wm8962_remove),
+ .probe = tobermory_probe,
+ .remove = __devexit_p(tobermory_remove),
};
-static int __init speyside_wm8962_audio_init(void)
-{
- return platform_driver_register(&speyside_wm8962_driver);
-}
-module_init(speyside_wm8962_audio_init);
-
-static void __exit speyside_wm8962_audio_exit(void)
-{
- platform_driver_unregister(&speyside_wm8962_driver);
-}
-module_exit(speyside_wm8962_audio_exit);
+module_platform_driver(tobermory_driver);
-MODULE_DESCRIPTION("Speyside WM8962 audio support");
+MODULE_DESCRIPTION("Tobermory audio support");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:speyside-wm8962");
+MODULE_ALIAS("platform:tobermory");
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index db74005f37ce..7da20186b19e 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -369,17 +369,7 @@ static struct platform_driver sh7760_pcm_driver = {
.remove = __devexit_p(sh7760_soc_platform_remove),
};
-static int __init snd_sh7760_pcm_init(void)
-{
- return platform_driver_register(&sh7760_pcm_driver);
-}
-module_init(snd_sh7760_pcm_init);
-
-static void __exit snd_sh7760_pcm_exit(void)
-{
- platform_driver_unregister(&sh7760_pcm_driver);
-}
-module_exit(snd_sh7760_pcm_exit);
+module_platform_driver(sh7760_pcm_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
diff --git a/sound/soc/sh/fsi-ak4642.c b/sound/soc/sh/fsi-ak4642.c
index 770a71a15366..97f540aabbdd 100644
--- a/sound/soc/sh/fsi-ak4642.c
+++ b/sound/soc/sh/fsi-ak4642.c
@@ -10,6 +10,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/sh_fsi.h>
struct fsi_ak4642_data {
@@ -48,6 +49,7 @@ static struct snd_soc_dai_link fsi_dai_link = {
};
static struct snd_soc_card fsi_soc_card = {
+ .owner = THIS_MODULE,
.dai_link = &fsi_dai_link,
.num_links = 1,
};
@@ -57,27 +59,23 @@ static struct platform_device *fsi_snd_device;
static int fsi_ak4642_probe(struct platform_device *pdev)
{
int ret = -ENOMEM;
- const struct platform_device_id *id_entry;
- struct fsi_ak4642_data *pdata;
+ struct fsi_ak4642_info *pinfo = pdev->dev.platform_data;
- id_entry = pdev->id_entry;
- if (!id_entry) {
- dev_err(&pdev->dev, "unknown fsi ak4642\n");
- return -ENODEV;
+ if (!pinfo) {
+ dev_err(&pdev->dev, "no info for fsi ak4642\n");
+ goto out;
}
- pdata = (struct fsi_ak4642_data *)id_entry->driver_data;
-
- fsi_snd_device = platform_device_alloc("soc-audio", pdata->id);
+ fsi_snd_device = platform_device_alloc("soc-audio", pinfo->id);
if (!fsi_snd_device)
goto out;
- fsi_dai_link.name = pdata->name;
- fsi_dai_link.stream_name = pdata->name;
- fsi_dai_link.cpu_dai_name = pdata->cpu_dai;
- fsi_dai_link.platform_name = pdata->platform;
- fsi_dai_link.codec_name = pdata->codec;
- fsi_soc_card.name = pdata->card;
+ fsi_dai_link.name = pinfo->name;
+ fsi_dai_link.stream_name = pinfo->name;
+ fsi_dai_link.cpu_dai_name = pinfo->cpu_dai;
+ fsi_dai_link.platform_name = pinfo->platform;
+ fsi_dai_link.codec_name = pinfo->codec;
+ fsi_soc_card.name = pinfo->card;
platform_set_drvdata(fsi_snd_device, &fsi_soc_card);
ret = platform_device_add(fsi_snd_device);
@@ -95,114 +93,15 @@ static int fsi_ak4642_remove(struct platform_device *pdev)
return 0;
}
-static struct fsi_ak4642_data fsi_a_ak4642 = {
- .name = "AK4642",
- .card = "FSIA-AK4642",
- .cpu_dai = "fsia-dai",
- .codec = "ak4642-codec.0-0012",
- .platform = "sh_fsi.0",
- .id = FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi_b_ak4642 = {
- .name = "AK4642",
- .card = "FSIB-AK4642",
- .cpu_dai = "fsib-dai",
- .codec = "ak4642-codec.0-0012",
- .platform = "sh_fsi.0",
- .id = FSI_PORT_B,
-};
-
-static struct fsi_ak4642_data fsi_a_ak4643 = {
- .name = "AK4643",
- .card = "FSIA-AK4643",
- .cpu_dai = "fsia-dai",
- .codec = "ak4642-codec.0-0013",
- .platform = "sh_fsi.0",
- .id = FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi_b_ak4643 = {
- .name = "AK4643",
- .card = "FSIB-AK4643",
- .cpu_dai = "fsib-dai",
- .codec = "ak4642-codec.0-0013",
- .platform = "sh_fsi.0",
- .id = FSI_PORT_B,
-};
-
-static struct fsi_ak4642_data fsi2_a_ak4642 = {
- .name = "AK4642",
- .card = "FSI2A-AK4642",
- .cpu_dai = "fsia-dai",
- .codec = "ak4642-codec.0-0012",
- .platform = "sh_fsi2",
- .id = FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi2_b_ak4642 = {
- .name = "AK4642",
- .card = "FSI2B-AK4642",
- .cpu_dai = "fsib-dai",
- .codec = "ak4642-codec.0-0012",
- .platform = "sh_fsi2",
- .id = FSI_PORT_B,
-};
-
-static struct fsi_ak4642_data fsi2_a_ak4643 = {
- .name = "AK4643",
- .card = "FSI2A-AK4643",
- .cpu_dai = "fsia-dai",
- .codec = "ak4642-codec.0-0013",
- .platform = "sh_fsi2",
- .id = FSI_PORT_A,
-};
-
-static struct fsi_ak4642_data fsi2_b_ak4643 = {
- .name = "AK4643",
- .card = "FSI2B-AK4643",
- .cpu_dai = "fsib-dai",
- .codec = "ak4642-codec.0-0013",
- .platform = "sh_fsi2",
- .id = FSI_PORT_B,
-};
-
-static struct platform_device_id fsi_id_table[] = {
- /* FSI */
- { "sh_fsi_a_ak4642", (kernel_ulong_t)&fsi_a_ak4642 },
- { "sh_fsi_b_ak4642", (kernel_ulong_t)&fsi_b_ak4642 },
- { "sh_fsi_a_ak4643", (kernel_ulong_t)&fsi_a_ak4643 },
- { "sh_fsi_b_ak4643", (kernel_ulong_t)&fsi_b_ak4643 },
-
- /* FSI 2 */
- { "sh_fsi2_a_ak4642", (kernel_ulong_t)&fsi2_a_ak4642 },
- { "sh_fsi2_b_ak4642", (kernel_ulong_t)&fsi2_b_ak4642 },
- { "sh_fsi2_a_ak4643", (kernel_ulong_t)&fsi2_a_ak4643 },
- { "sh_fsi2_b_ak4643", (kernel_ulong_t)&fsi2_b_ak4643 },
- {},
-};
-
static struct platform_driver fsi_ak4642 = {
.driver = {
.name = "fsi-ak4642-audio",
},
.probe = fsi_ak4642_probe,
.remove = fsi_ak4642_remove,
- .id_table = fsi_id_table,
};
-static int __init fsi_ak4642_init(void)
-{
- return platform_driver_register(&fsi_ak4642);
-}
-
-static void __exit fsi_ak4642_exit(void)
-{
- platform_driver_unregister(&fsi_ak4642);
-}
-
-module_init(fsi_ak4642_init);
-module_exit(fsi_ak4642_exit);
+module_platform_driver(fsi_ak4642);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic SH4 FSI-AK4642 sound card");
diff --git a/sound/soc/sh/fsi-da7210.c b/sound/soc/sh/fsi-da7210.c
index 59553fd8c2fb..1dd3354c7411 100644
--- a/sound/soc/sh/fsi-da7210.c
+++ b/sound/soc/sh/fsi-da7210.c
@@ -11,6 +11,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/sh_fsi.h>
static int fsi_da7210_init(struct snd_soc_pcm_runtime *rtd)
@@ -43,6 +44,7 @@ static struct snd_soc_dai_link fsi_da7210_dai = {
static struct snd_soc_card fsi_soc_card = {
.name = "FSI-DA7210",
+ .owner = THIS_MODULE,
.dai_link = &fsi_da7210_dai,
.num_links = 1,
};
diff --git a/sound/soc/sh/fsi-hdmi.c b/sound/soc/sh/fsi-hdmi.c
index d3d9fd880680..6e41908323e8 100644
--- a/sound/soc/sh/fsi-hdmi.c
+++ b/sound/soc/sh/fsi-hdmi.c
@@ -10,6 +10,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/module.h>
#include <sound/sh_fsi.h>
struct fsi_hdmi_data {
@@ -38,6 +39,7 @@ static struct snd_soc_dai_link fsi_dai_link = {
};
static struct snd_soc_card fsi_soc_card = {
+ .owner = THIS_MODULE,
.dai_link = &fsi_dai_link,
.num_links = 1,
};
@@ -109,18 +111,7 @@ static struct platform_driver fsi_hdmi = {
.id_table = fsi_id_table,
};
-static int __init fsi_hdmi_init(void)
-{
- return platform_driver_register(&fsi_hdmi);
-}
-
-static void __exit fsi_hdmi_exit(void)
-{
- platform_driver_unregister(&fsi_hdmi);
-}
-
-module_init(fsi_hdmi_init);
-module_exit(fsi_hdmi_exit);
+module_platform_driver(fsi_hdmi);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Generic SH4 FSI-HDMI sound card");
diff --git a/sound/soc/sh/fsi.c b/sound/soc/sh/fsi.c
index 8e112ccffb13..378cc5b056d7 100644
--- a/sound/soc/sh/fsi.c
+++ b/sound/soc/sh/fsi.c
@@ -13,9 +13,13 @@
*/
#include <linux/delay.h>
+#include <linux/dma-mapping.h>
#include <linux/pm_runtime.h>
#include <linux/io.h>
+#include <linux/scatterlist.h>
+#include <linux/sh_dma.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/soc.h>
#include <sound/sh_fsi.h>
@@ -31,7 +35,9 @@
#define REG_DIDT 0x0020
#define REG_DODT 0x0024
#define REG_MUTE_ST 0x0028
+#define REG_OUT_DMAC 0x002C
#define REG_OUT_SEL 0x0030
+#define REG_IN_DMAC 0x0038
/* master register */
#define MST_CLK_RST 0x0210
@@ -50,6 +56,7 @@
/* DO_FMT */
/* DI_FMT */
+#define CR_BWS_MASK (0x3 << 20) /* FSI2 */
#define CR_BWS_24 (0x0 << 20) /* FSI2 */
#define CR_BWS_16 (0x1 << 20) /* FSI2 */
#define CR_BWS_20 (0x2 << 20) /* FSI2 */
@@ -65,6 +72,15 @@
#define CR_TDM (0x4 << 4)
#define CR_TDM_D (0x5 << 4)
+/* OUT_DMAC */
+/* IN_DMAC */
+#define VDMD_MASK (0x3 << 4)
+#define VDMD_FRONT (0x0 << 4) /* Package in front */
+#define VDMD_BACK (0x1 << 4) /* Package in back */
+#define VDMD_STREAM (0x2 << 4) /* Stream mode(16bit * 2) */
+
+#define DMA_ON (0x1 << 0)
+
/* DOFF_CTL */
/* DIFF_CTL */
#define IRQ_HALF 0x00100000
@@ -113,7 +129,7 @@
#define FSI_FMTS (SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S16_LE)
-typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int enable);
+typedef int (*set_rate_func)(struct device *dev, int rate, int enable);
/*
* FSI driver use below type name for variable
@@ -156,22 +172,41 @@ typedef int (*set_rate_func)(struct device *dev, int is_porta, int rate, int ena
* struct
*/
+struct fsi_stream_handler;
struct fsi_stream {
- struct snd_pcm_substream *substream;
+ /*
+ * these are initialized by fsi_stream_init()
+ */
+ struct snd_pcm_substream *substream;
int fifo_sample_capa; /* sample capacity of FSI FIFO */
int buff_sample_capa; /* sample capacity of ALSA buffer */
int buff_sample_pos; /* sample position of ALSA buffer */
int period_samples; /* sample number / 1 period */
int period_pos; /* current period position */
-
+ int sample_width; /* sample width */
int uerr_num;
int oerr_num;
+
+ /*
+ * thse are initialized by fsi_handler_init()
+ */
+ struct fsi_stream_handler *handler;
+ struct fsi_priv *priv;
+
+ /*
+ * these are for DMAEngine
+ */
+ struct dma_chan *chan;
+ struct sh_dmae_slave slave; /* see fsi_handler_init() */
+ struct tasklet_struct tasklet;
+ dma_addr_t dma;
};
struct fsi_priv {
void __iomem *base;
struct fsi_master *master;
+ struct sh_fsi_port_info *info;
struct fsi_stream playback;
struct fsi_stream capture;
@@ -186,6 +221,20 @@ struct fsi_priv {
long rate;
};
+struct fsi_stream_handler {
+ int (*init)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*quit)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*probe)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*transfer)(struct fsi_priv *fsi, struct fsi_stream *io);
+ int (*remove)(struct fsi_priv *fsi, struct fsi_stream *io);
+ void (*start_stop)(struct fsi_priv *fsi, struct fsi_stream *io,
+ int enable);
+};
+#define fsi_stream_handler_call(io, func, args...) \
+ (!(io) ? -ENODEV : \
+ !((io)->handler->func) ? 0 : \
+ (io)->handler->func(args))
+
struct fsi_core {
int ver;
@@ -202,15 +251,16 @@ struct fsi_master {
struct fsi_priv fsia;
struct fsi_priv fsib;
struct fsi_core *core;
- struct sh_fsi_platform_info *info;
spinlock_t lock;
};
+static int fsi_stream_is_play(struct fsi_priv *fsi, struct fsi_stream *io);
+
/*
* basic read write function
*/
-static void __fsi_reg_write(u32 reg, u32 data)
+static void __fsi_reg_write(u32 __iomem *reg, u32 data)
{
/* valid data area is 24bit */
data &= 0x00ffffff;
@@ -218,12 +268,12 @@ static void __fsi_reg_write(u32 reg, u32 data)
__raw_writel(data, reg);
}
-static u32 __fsi_reg_read(u32 reg)
+static u32 __fsi_reg_read(u32 __iomem *reg)
{
return __raw_readl(reg);
}
-static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
+static void __fsi_reg_mask_set(u32 __iomem *reg, u32 mask, u32 data)
{
u32 val = __fsi_reg_read(reg);
@@ -234,13 +284,13 @@ static void __fsi_reg_mask_set(u32 reg, u32 mask, u32 data)
}
#define fsi_reg_write(p, r, d)\
- __fsi_reg_write((u32)(p->base + REG_##r), d)
+ __fsi_reg_write((p->base + REG_##r), d)
#define fsi_reg_read(p, r)\
- __fsi_reg_read((u32)(p->base + REG_##r))
+ __fsi_reg_read((p->base + REG_##r))
#define fsi_reg_mask_set(p, r, m, d)\
- __fsi_reg_mask_set((u32)(p->base + REG_##r), m, d)
+ __fsi_reg_mask_set((p->base + REG_##r), m, d)
#define fsi_master_read(p, r) _fsi_master_read(p, MST_##r)
#define fsi_core_read(p, r) _fsi_master_read(p, p->core->r)
@@ -250,7 +300,7 @@ static u32 _fsi_master_read(struct fsi_master *master, u32 reg)
unsigned long flags;
spin_lock_irqsave(&master->lock, flags);
- ret = __fsi_reg_read((u32)(master->base + reg));
+ ret = __fsi_reg_read(master->base + reg);
spin_unlock_irqrestore(&master->lock, flags);
return ret;
@@ -264,7 +314,7 @@ static void _fsi_master_mask_set(struct fsi_master *master,
unsigned long flags;
spin_lock_irqsave(&master->lock, flags);
- __fsi_reg_mask_set((u32)(master->base + reg), mask, data);
+ __fsi_reg_mask_set(master->base + reg, mask, data);
spin_unlock_irqrestore(&master->lock, flags);
}
@@ -292,6 +342,11 @@ static int fsi_is_spdif(struct fsi_priv *fsi)
return fsi->spdif;
}
+static int fsi_is_play(struct snd_pcm_substream *substream)
+{
+ return substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
+}
+
static struct snd_soc_dai *fsi_get_dai(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -314,44 +369,25 @@ static struct fsi_priv *fsi_get_priv(struct snd_pcm_substream *substream)
return fsi_get_priv_frm_dai(fsi_get_dai(substream));
}
-static set_rate_func fsi_get_info_set_rate(struct fsi_master *master)
+static set_rate_func fsi_get_info_set_rate(struct fsi_priv *fsi)
{
- if (!master->info)
+ if (!fsi->info)
return NULL;
- return master->info->set_rate;
+ return fsi->info->set_rate;
}
static u32 fsi_get_info_flags(struct fsi_priv *fsi)
{
- int is_porta = fsi_is_port_a(fsi);
- struct fsi_master *master = fsi_get_master(fsi);
-
- if (!master->info)
+ if (!fsi->info)
return 0;
- return is_porta ? master->info->porta_flags :
- master->info->portb_flags;
-}
-
-static inline int fsi_stream_is_play(int stream)
-{
- return stream == SNDRV_PCM_STREAM_PLAYBACK;
-}
-
-static inline int fsi_is_play(struct snd_pcm_substream *substream)
-{
- return fsi_stream_is_play(substream->stream);
+ return fsi->info->flags;
}
-static inline struct fsi_stream *fsi_get_stream(struct fsi_priv *fsi,
- int is_play)
-{
- return is_play ? &fsi->playback : &fsi->capture;
-}
-
-static u32 fsi_get_port_shift(struct fsi_priv *fsi, int is_play)
+static u32 fsi_get_port_shift(struct fsi_priv *fsi, struct fsi_stream *io)
{
+ int is_play = fsi_stream_is_play(fsi, io);
int is_porta = fsi_is_port_a(fsi);
u32 shift;
@@ -373,26 +409,81 @@ static int fsi_sample2frame(struct fsi_priv *fsi, int samples)
return samples / fsi->chan_num;
}
+static int fsi_get_current_fifo_samples(struct fsi_priv *fsi,
+ struct fsi_stream *io)
+{
+ int is_play = fsi_stream_is_play(fsi, io);
+ u32 status;
+ int frames;
+
+ status = is_play ?
+ fsi_reg_read(fsi, DOFF_ST) :
+ fsi_reg_read(fsi, DIFF_ST);
+
+ frames = 0x1ff & (status >> 8);
+
+ return fsi_frame2sample(fsi, frames);
+}
+
+static void fsi_count_fifo_err(struct fsi_priv *fsi)
+{
+ u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
+ u32 istatus = fsi_reg_read(fsi, DIFF_ST);
+
+ if (ostatus & ERR_OVER)
+ fsi->playback.oerr_num++;
+
+ if (ostatus & ERR_UNDER)
+ fsi->playback.uerr_num++;
+
+ if (istatus & ERR_OVER)
+ fsi->capture.oerr_num++;
+
+ if (istatus & ERR_UNDER)
+ fsi->capture.uerr_num++;
+
+ fsi_reg_write(fsi, DOFF_ST, 0);
+ fsi_reg_write(fsi, DIFF_ST, 0);
+}
+
+/*
+ * fsi_stream_xx() function
+ */
+static inline int fsi_stream_is_play(struct fsi_priv *fsi,
+ struct fsi_stream *io)
+{
+ return &fsi->playback == io;
+}
+
+static inline struct fsi_stream *fsi_stream_get(struct fsi_priv *fsi,
+ struct snd_pcm_substream *substream)
+{
+ return fsi_is_play(substream) ? &fsi->playback : &fsi->capture;
+}
+
static int fsi_stream_is_working(struct fsi_priv *fsi,
- int is_play)
+ struct fsi_stream *io)
{
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
struct fsi_master *master = fsi_get_master(fsi);
unsigned long flags;
int ret;
spin_lock_irqsave(&master->lock, flags);
- ret = !!io->substream;
+ ret = !!(io->substream && io->substream->runtime);
spin_unlock_irqrestore(&master->lock, flags);
return ret;
}
-static void fsi_stream_push(struct fsi_priv *fsi,
- int is_play,
+static struct fsi_priv *fsi_stream_to_priv(struct fsi_stream *io)
+{
+ return io->priv;
+}
+
+static void fsi_stream_init(struct fsi_priv *fsi,
+ struct fsi_stream *io,
struct snd_pcm_substream *substream)
{
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
struct snd_pcm_runtime *runtime = substream->runtime;
struct fsi_master *master = fsi_get_master(fsi);
unsigned long flags;
@@ -403,14 +494,15 @@ static void fsi_stream_push(struct fsi_priv *fsi,
io->buff_sample_pos = 0;
io->period_samples = fsi_frame2sample(fsi, runtime->period_size);
io->period_pos = 0;
+ io->sample_width = samples_to_bytes(runtime, 1);
io->oerr_num = -1; /* ignore 1st err */
io->uerr_num = -1; /* ignore 1st err */
+ fsi_stream_handler_call(io, init, fsi, io);
spin_unlock_irqrestore(&master->lock, flags);
}
-static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
+static void fsi_stream_quit(struct fsi_priv *fsi, struct fsi_stream *io)
{
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
struct snd_soc_dai *dai = fsi_get_dai(io->substream);
struct fsi_master *master = fsi_get_master(fsi);
unsigned long flags;
@@ -423,127 +515,87 @@ static void fsi_stream_pop(struct fsi_priv *fsi, int is_play)
if (io->uerr_num > 0)
dev_err(dai->dev, "under_run = %d\n", io->uerr_num);
+ fsi_stream_handler_call(io, quit, fsi, io);
io->substream = NULL;
io->buff_sample_capa = 0;
io->buff_sample_pos = 0;
io->period_samples = 0;
io->period_pos = 0;
+ io->sample_width = 0;
io->oerr_num = 0;
io->uerr_num = 0;
spin_unlock_irqrestore(&master->lock, flags);
}
-static int fsi_get_current_fifo_samples(struct fsi_priv *fsi, int is_play)
-{
- u32 status;
- int frames;
-
- status = is_play ?
- fsi_reg_read(fsi, DOFF_ST) :
- fsi_reg_read(fsi, DIFF_ST);
-
- frames = 0x1ff & (status >> 8);
-
- return fsi_frame2sample(fsi, frames);
-}
-
-static void fsi_count_fifo_err(struct fsi_priv *fsi)
+static int fsi_stream_transfer(struct fsi_stream *io)
{
- u32 ostatus = fsi_reg_read(fsi, DOFF_ST);
- u32 istatus = fsi_reg_read(fsi, DIFF_ST);
-
- if (ostatus & ERR_OVER)
- fsi->playback.oerr_num++;
-
- if (ostatus & ERR_UNDER)
- fsi->playback.uerr_num++;
-
- if (istatus & ERR_OVER)
- fsi->capture.oerr_num++;
-
- if (istatus & ERR_UNDER)
- fsi->capture.uerr_num++;
+ struct fsi_priv *fsi = fsi_stream_to_priv(io);
+ if (!fsi)
+ return -EIO;
- fsi_reg_write(fsi, DOFF_ST, 0);
- fsi_reg_write(fsi, DIFF_ST, 0);
+ return fsi_stream_handler_call(io, transfer, fsi, io);
}
-/*
- * dma function
- */
+#define fsi_stream_start(fsi, io)\
+ fsi_stream_handler_call(io, start_stop, fsi, io, 1)
-static u8 *fsi_dma_get_area(struct fsi_priv *fsi, int stream)
-{
- int is_play = fsi_stream_is_play(stream);
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
- struct snd_pcm_runtime *runtime = io->substream->runtime;
+#define fsi_stream_stop(fsi, io)\
+ fsi_stream_handler_call(io, start_stop, fsi, io, 0)
- return runtime->dma_area +
- samples_to_bytes(runtime, io->buff_sample_pos);
-}
-
-static void fsi_dma_soft_push16(struct fsi_priv *fsi, int num)
+static int fsi_stream_probe(struct fsi_priv *fsi)
{
- u16 *start;
- int i;
-
- start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
-
- for (i = 0; i < num; i++)
- fsi_reg_write(fsi, DODT, ((u32)*(start + i) << 8));
-}
+ struct fsi_stream *io;
+ int ret1, ret2;
-static void fsi_dma_soft_pop16(struct fsi_priv *fsi, int num)
-{
- u16 *start;
- int i;
+ io = &fsi->playback;
+ ret1 = fsi_stream_handler_call(io, probe, fsi, io);
- start = (u16 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
+ io = &fsi->capture;
+ ret2 = fsi_stream_handler_call(io, probe, fsi, io);
+ if (ret1 < 0)
+ return ret1;
+ if (ret2 < 0)
+ return ret2;
- for (i = 0; i < num; i++)
- *(start + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
+ return 0;
}
-static void fsi_dma_soft_push32(struct fsi_priv *fsi, int num)
+static int fsi_stream_remove(struct fsi_priv *fsi)
{
- u32 *start;
- int i;
+ struct fsi_stream *io;
+ int ret1, ret2;
- start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+ io = &fsi->playback;
+ ret1 = fsi_stream_handler_call(io, remove, fsi, io);
+ io = &fsi->capture;
+ ret2 = fsi_stream_handler_call(io, remove, fsi, io);
- for (i = 0; i < num; i++)
- fsi_reg_write(fsi, DODT, *(start + i));
-}
+ if (ret1 < 0)
+ return ret1;
+ if (ret2 < 0)
+ return ret2;
-static void fsi_dma_soft_pop32(struct fsi_priv *fsi, int num)
-{
- u32 *start;
- int i;
-
- start = (u32 *)fsi_dma_get_area(fsi, SNDRV_PCM_STREAM_CAPTURE);
-
- for (i = 0; i < num; i++)
- *(start + i) = fsi_reg_read(fsi, DIDT);
+ return 0;
}
/*
* irq function
*/
-static void fsi_irq_enable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_enable(struct fsi_priv *fsi, struct fsi_stream *io)
{
- u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+ u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
struct fsi_master *master = fsi_get_master(fsi);
fsi_core_mask_set(master, imsk, data, data);
fsi_core_mask_set(master, iemsk, data, data);
}
-static void fsi_irq_disable(struct fsi_priv *fsi, int is_play)
+static void fsi_irq_disable(struct fsi_priv *fsi, struct fsi_stream *io)
{
- u32 data = AB_IO(1, fsi_get_port_shift(fsi, is_play));
+ u32 data = AB_IO(1, fsi_get_port_shift(fsi, io));
struct fsi_master *master = fsi_get_master(fsi);
fsi_core_mask_set(master, imsk, data, 0);
@@ -560,8 +612,8 @@ static void fsi_irq_clear_status(struct fsi_priv *fsi)
u32 data = 0;
struct fsi_master *master = fsi_get_master(fsi);
- data |= AB_IO(1, fsi_get_port_shift(fsi, 0));
- data |= AB_IO(1, fsi_get_port_shift(fsi, 1));
+ data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->playback));
+ data |= AB_IO(1, fsi_get_port_shift(fsi, &fsi->capture));
/* clear interrupt factor */
fsi_core_mask_set(master, int_st, data, 0);
@@ -597,11 +649,14 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
long rate, int enable)
{
struct fsi_master *master = fsi_get_master(fsi);
- set_rate_func set_rate = fsi_get_info_set_rate(master);
+ set_rate_func set_rate = fsi_get_info_set_rate(fsi);
int fsi_ver = master->core->ver;
int ret;
- ret = set_rate(dev, fsi_is_port_a(fsi), rate, enable);
+ if (!set_rate)
+ return 0;
+
+ ret = set_rate(dev, rate, enable);
if (ret < 0) /* error */
return ret;
@@ -668,96 +723,64 @@ static int fsi_set_master_clk(struct device *dev, struct fsi_priv *fsi,
return ret;
}
-#define fsi_port_start(f, i) __fsi_port_clk_ctrl(f, i, 1)
-#define fsi_port_stop(f, i) __fsi_port_clk_ctrl(f, i, 0)
-static void __fsi_port_clk_ctrl(struct fsi_priv *fsi, int is_play, int enable)
+/*
+ * pio data transfer handler
+ */
+static void fsi_pio_push16(struct fsi_priv *fsi, u8 *_buf, int samples)
{
- struct fsi_master *master = fsi_get_master(fsi);
- u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
+ u16 *buf = (u16 *)_buf;
+ int i;
- if (enable)
- fsi_irq_enable(fsi, is_play);
- else
- fsi_irq_disable(fsi, is_play);
+ for (i = 0; i < samples; i++)
+ fsi_reg_write(fsi, DODT, ((u32)*(buf + i) << 8));
+}
- if (fsi_is_clk_master(fsi))
- fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
+static void fsi_pio_pop16(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+ u16 *buf = (u16 *)_buf;
+ int i;
+
+ for (i = 0; i < samples; i++)
+ *(buf + i) = (u16)(fsi_reg_read(fsi, DIDT) >> 8);
}
-/*
- * ctrl function
- */
-static void fsi_fifo_init(struct fsi_priv *fsi,
- int is_play,
- struct device *dev)
+static void fsi_pio_push32(struct fsi_priv *fsi, u8 *_buf, int samples)
{
- struct fsi_master *master = fsi_get_master(fsi);
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
- u32 shift, i;
- int frame_capa;
+ u32 *buf = (u32 *)_buf;
+ int i;
- /* get on-chip RAM capacity */
- shift = fsi_master_read(master, FIFO_SZ);
- shift >>= fsi_get_port_shift(fsi, is_play);
- shift &= FIFO_SZ_MASK;
- frame_capa = 256 << shift;
- dev_dbg(dev, "fifo = %d words\n", frame_capa);
+ for (i = 0; i < samples; i++)
+ fsi_reg_write(fsi, DODT, *(buf + i));
+}
- /*
- * The maximum number of sample data varies depending
- * on the number of channels selected for the format.
- *
- * FIFOs are used in 4-channel units in 3-channel mode
- * and in 8-channel units in 5- to 7-channel mode
- * meaning that more FIFOs than the required size of DPRAM
- * are used.
- *
- * ex) if 256 words of DP-RAM is connected
- * 1 channel: 256 (256 x 1 = 256)
- * 2 channels: 128 (128 x 2 = 256)
- * 3 channels: 64 ( 64 x 3 = 192)
- * 4 channels: 64 ( 64 x 4 = 256)
- * 5 channels: 32 ( 32 x 5 = 160)
- * 6 channels: 32 ( 32 x 6 = 192)
- * 7 channels: 32 ( 32 x 7 = 224)
- * 8 channels: 32 ( 32 x 8 = 256)
- */
- for (i = 1; i < fsi->chan_num; i <<= 1)
- frame_capa >>= 1;
- dev_dbg(dev, "%d channel %d store\n",
- fsi->chan_num, frame_capa);
+static void fsi_pio_pop32(struct fsi_priv *fsi, u8 *_buf, int samples)
+{
+ u32 *buf = (u32 *)_buf;
+ int i;
- io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+ for (i = 0; i < samples; i++)
+ *(buf + i) = fsi_reg_read(fsi, DIDT);
+}
- /*
- * set interrupt generation factor
- * clear FIFO
- */
- if (is_play) {
- fsi_reg_write(fsi, DOFF_CTL, IRQ_HALF);
- fsi_reg_mask_set(fsi, DOFF_CTL, FIFO_CLR, FIFO_CLR);
- } else {
- fsi_reg_write(fsi, DIFF_CTL, IRQ_HALF);
- fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
- }
+static u8 *fsi_pio_get_area(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+ return runtime->dma_area +
+ samples_to_bytes(runtime, io->buff_sample_pos);
}
-static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
+static int fsi_pio_transfer(struct fsi_priv *fsi, struct fsi_stream *io,
+ void (*run16)(struct fsi_priv *fsi, u8 *buf, int samples),
+ void (*run32)(struct fsi_priv *fsi, u8 *buf, int samples),
+ int samples)
{
struct snd_pcm_runtime *runtime;
- struct snd_pcm_substream *substream = NULL;
- int is_play = fsi_stream_is_play(stream);
- struct fsi_stream *io = fsi_get_stream(fsi, is_play);
- int sample_residues;
- int sample_width;
- int samples;
- int samples_max;
+ struct snd_pcm_substream *substream;
+ u8 *buf;
int over_period;
- void (*fn)(struct fsi_priv *fsi, int size);
- if (!fsi ||
- !io->substream ||
- !io->substream->runtime)
+ if (!fsi_stream_is_working(fsi, io))
return -EINVAL;
over_period = 0;
@@ -777,60 +800,19 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
io->buff_sample_pos = 0;
}
- /* get 1 sample data width */
- sample_width = samples_to_bytes(runtime, 1);
+ buf = fsi_pio_get_area(fsi, io);
- /* get number of residue samples */
- sample_residues = io->buff_sample_capa - io->buff_sample_pos;
-
- if (is_play) {
- /*
- * for play-back
- *
- * samples_max : number of FSI fifo free samples space
- * samples : number of ALSA residue samples
- */
- samples_max = io->fifo_sample_capa;
- samples_max -= fsi_get_current_fifo_samples(fsi, is_play);
-
- samples = sample_residues;
-
- switch (sample_width) {
- case 2:
- fn = fsi_dma_soft_push16;
- break;
- case 4:
- fn = fsi_dma_soft_push32;
- break;
- default:
- return -EINVAL;
- }
- } else {
- /*
- * for capture
- *
- * samples_max : number of ALSA free samples space
- * samples : number of samples in FSI fifo
- */
- samples_max = sample_residues;
- samples = fsi_get_current_fifo_samples(fsi, is_play);
-
- switch (sample_width) {
- case 2:
- fn = fsi_dma_soft_pop16;
- break;
- case 4:
- fn = fsi_dma_soft_pop32;
- break;
- default:
- return -EINVAL;
- }
+ switch (io->sample_width) {
+ case 2:
+ run16(fsi, buf, samples);
+ break;
+ case 4:
+ run32(fsi, buf, samples);
+ break;
+ default:
+ return -EINVAL;
}
- samples = min(samples, samples_max);
-
- fn(fsi, samples);
-
/* update buff_sample_pos */
io->buff_sample_pos += samples;
@@ -840,16 +822,66 @@ static int fsi_fifo_data_ctrl(struct fsi_priv *fsi, int stream)
return 0;
}
-static int fsi_data_pop(struct fsi_priv *fsi)
+static int fsi_pio_pop(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ int sample_residues; /* samples in FSI fifo */
+ int sample_space; /* ALSA free samples space */
+ int samples;
+
+ sample_residues = fsi_get_current_fifo_samples(fsi, io);
+ sample_space = io->buff_sample_capa - io->buff_sample_pos;
+
+ samples = min(sample_residues, sample_space);
+
+ return fsi_pio_transfer(fsi, io,
+ fsi_pio_pop16,
+ fsi_pio_pop32,
+ samples);
+}
+
+static int fsi_pio_push(struct fsi_priv *fsi, struct fsi_stream *io)
{
- return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_CAPTURE);
+ int sample_residues; /* ALSA residue samples */
+ int sample_space; /* FSI fifo free samples space */
+ int samples;
+
+ sample_residues = io->buff_sample_capa - io->buff_sample_pos;
+ sample_space = io->fifo_sample_capa -
+ fsi_get_current_fifo_samples(fsi, io);
+
+ samples = min(sample_residues, sample_space);
+
+ return fsi_pio_transfer(fsi, io,
+ fsi_pio_push16,
+ fsi_pio_push32,
+ samples);
}
-static int fsi_data_push(struct fsi_priv *fsi)
+static void fsi_pio_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+ int enable)
{
- return fsi_fifo_data_ctrl(fsi, SNDRV_PCM_STREAM_PLAYBACK);
+ struct fsi_master *master = fsi_get_master(fsi);
+ u32 clk = fsi_is_port_a(fsi) ? CRA : CRB;
+
+ if (enable)
+ fsi_irq_enable(fsi, io);
+ else
+ fsi_irq_disable(fsi, io);
+
+ if (fsi_is_clk_master(fsi))
+ fsi_master_mask_set(master, CLK_RST, clk, (enable) ? clk : 0);
}
+static struct fsi_stream_handler fsi_pio_push_handler = {
+ .transfer = fsi_pio_push,
+ .start_stop = fsi_pio_start_stop,
+};
+
+static struct fsi_stream_handler fsi_pio_pop_handler = {
+ .transfer = fsi_pio_pop,
+ .start_stop = fsi_pio_start_stop,
+};
+
static irqreturn_t fsi_interrupt(int irq, void *data)
{
struct fsi_master *master = data;
@@ -860,13 +892,13 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
fsi_master_mask_set(master, SOFT_RST, IR, IR);
if (int_st & AB_IO(1, AO_SHIFT))
- fsi_data_push(&master->fsia);
+ fsi_stream_transfer(&master->fsia.playback);
if (int_st & AB_IO(1, BO_SHIFT))
- fsi_data_push(&master->fsib);
+ fsi_stream_transfer(&master->fsib.playback);
if (int_st & AB_IO(1, AI_SHIFT))
- fsi_data_pop(&master->fsia);
+ fsi_stream_transfer(&master->fsia.capture);
if (int_st & AB_IO(1, BI_SHIFT))
- fsi_data_pop(&master->fsib);
+ fsi_stream_transfer(&master->fsib.capture);
fsi_count_fifo_err(&master->fsia);
fsi_count_fifo_err(&master->fsib);
@@ -878,18 +910,278 @@ static irqreturn_t fsi_interrupt(int irq, void *data)
}
/*
+ * dma data transfer handler
+ */
+static int fsi_dma_init(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+ struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ io->dma = dma_map_single(dai->dev, runtime->dma_area,
+ snd_pcm_lib_buffer_bytes(io->substream), dir);
+ return 0;
+}
+
+static int fsi_dma_quit(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ dma_unmap_single(dai->dev, io->dma,
+ snd_pcm_lib_buffer_bytes(io->substream), dir);
+ return 0;
+}
+
+static void fsi_dma_complete(void *data)
+{
+ struct fsi_stream *io = (struct fsi_stream *)data;
+ struct fsi_priv *fsi = fsi_stream_to_priv(io);
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+ struct snd_soc_dai *dai = fsi_get_dai(io->substream);
+ enum dma_data_direction dir = fsi_stream_is_play(fsi, io) ?
+ DMA_TO_DEVICE : DMA_FROM_DEVICE;
+
+ dma_sync_single_for_cpu(dai->dev, io->dma,
+ samples_to_bytes(runtime, io->period_samples), dir);
+
+ io->buff_sample_pos += io->period_samples;
+ io->period_pos++;
+
+ if (io->period_pos >= runtime->periods) {
+ io->period_pos = 0;
+ io->buff_sample_pos = 0;
+ }
+
+ fsi_count_fifo_err(fsi);
+ fsi_stream_transfer(io);
+
+ snd_pcm_period_elapsed(io->substream);
+}
+
+static dma_addr_t fsi_dma_get_area(struct fsi_stream *io)
+{
+ struct snd_pcm_runtime *runtime = io->substream->runtime;
+
+ return io->dma + samples_to_bytes(runtime, io->buff_sample_pos);
+}
+
+static void fsi_dma_do_tasklet(unsigned long data)
+{
+ struct fsi_stream *io = (struct fsi_stream *)data;
+ struct fsi_priv *fsi = fsi_stream_to_priv(io);
+ struct dma_chan *chan;
+ struct snd_soc_dai *dai;
+ struct dma_async_tx_descriptor *desc;
+ struct scatterlist sg;
+ struct snd_pcm_runtime *runtime;
+ enum dma_data_direction dir;
+ dma_cookie_t cookie;
+ int is_play = fsi_stream_is_play(fsi, io);
+ int len;
+ dma_addr_t buf;
+
+ if (!fsi_stream_is_working(fsi, io))
+ return;
+
+ dai = fsi_get_dai(io->substream);
+ chan = io->chan;
+ runtime = io->substream->runtime;
+ dir = is_play ? DMA_TO_DEVICE : DMA_FROM_DEVICE;
+ len = samples_to_bytes(runtime, io->period_samples);
+ buf = fsi_dma_get_area(io);
+
+ dma_sync_single_for_device(dai->dev, io->dma, len, dir);
+
+ sg_init_table(&sg, 1);
+ sg_set_page(&sg, pfn_to_page(PFN_DOWN(buf)),
+ len , offset_in_page(buf));
+ sg_dma_address(&sg) = buf;
+ sg_dma_len(&sg) = len;
+
+ desc = chan->device->device_prep_slave_sg(chan, &sg, 1, dir,
+ DMA_PREP_INTERRUPT |
+ DMA_CTRL_ACK);
+ if (!desc) {
+ dev_err(dai->dev, "device_prep_slave_sg() fail\n");
+ return;
+ }
+
+ desc->callback = fsi_dma_complete;
+ desc->callback_param = io;
+
+ cookie = desc->tx_submit(desc);
+ if (cookie < 0) {
+ dev_err(dai->dev, "tx_submit() fail\n");
+ return;
+ }
+
+ dma_async_issue_pending(chan);
+
+ /*
+ * FIXME
+ *
+ * In DMAEngine case, codec and FSI cannot be started simultaneously
+ * since FSI is using tasklet.
+ * Therefore, in capture case, probably FSI FIFO will have got
+ * overflow error in this point.
+ * in that case, DMA cannot start transfer until error was cleared.
+ */
+ if (!is_play) {
+ if (ERR_OVER & fsi_reg_read(fsi, DIFF_ST)) {
+ fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
+ fsi_reg_write(fsi, DIFF_ST, 0);
+ }
+ }
+}
+
+static bool fsi_dma_filter(struct dma_chan *chan, void *param)
+{
+ struct sh_dmae_slave *slave = param;
+
+ chan->private = slave;
+
+ return true;
+}
+
+static int fsi_dma_transfer(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ tasklet_schedule(&io->tasklet);
+
+ return 0;
+}
+
+static void fsi_dma_push_start_stop(struct fsi_priv *fsi, struct fsi_stream *io,
+ int start)
+{
+ u32 bws;
+ u32 dma;
+
+ switch (io->sample_width * start) {
+ case 2:
+ bws = CR_BWS_16;
+ dma = VDMD_STREAM | DMA_ON;
+ break;
+ case 4:
+ bws = CR_BWS_24;
+ dma = VDMD_BACK | DMA_ON;
+ break;
+ default:
+ bws = 0;
+ dma = 0;
+ }
+
+ fsi_reg_mask_set(fsi, DO_FMT, CR_BWS_MASK, bws);
+ fsi_reg_write(fsi, OUT_DMAC, dma);
+}
+
+static int fsi_dma_probe(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+
+ io->chan = dma_request_channel(mask, fsi_dma_filter, &io->slave);
+ if (!io->chan)
+ return -EIO;
+
+ tasklet_init(&io->tasklet, fsi_dma_do_tasklet, (unsigned long)io);
+
+ return 0;
+}
+
+static int fsi_dma_remove(struct fsi_priv *fsi, struct fsi_stream *io)
+{
+ tasklet_kill(&io->tasklet);
+
+ fsi_stream_stop(fsi, io);
+
+ if (io->chan)
+ dma_release_channel(io->chan);
+
+ io->chan = NULL;
+ return 0;
+}
+
+static struct fsi_stream_handler fsi_dma_push_handler = {
+ .init = fsi_dma_init,
+ .quit = fsi_dma_quit,
+ .probe = fsi_dma_probe,
+ .transfer = fsi_dma_transfer,
+ .remove = fsi_dma_remove,
+ .start_stop = fsi_dma_push_start_stop,
+};
+
+/*
* dai ops
*/
+static void fsi_fifo_init(struct fsi_priv *fsi,
+ struct fsi_stream *io,
+ struct device *dev)
+{
+ struct fsi_master *master = fsi_get_master(fsi);
+ int is_play = fsi_stream_is_play(fsi, io);
+ u32 shift, i;
+ int frame_capa;
+
+ /* get on-chip RAM capacity */
+ shift = fsi_master_read(master, FIFO_SZ);
+ shift >>= fsi_get_port_shift(fsi, io);
+ shift &= FIFO_SZ_MASK;
+ frame_capa = 256 << shift;
+ dev_dbg(dev, "fifo = %d words\n", frame_capa);
+
+ /*
+ * The maximum number of sample data varies depending
+ * on the number of channels selected for the format.
+ *
+ * FIFOs are used in 4-channel units in 3-channel mode
+ * and in 8-channel units in 5- to 7-channel mode
+ * meaning that more FIFOs than the required size of DPRAM
+ * are used.
+ *
+ * ex) if 256 words of DP-RAM is connected
+ * 1 channel: 256 (256 x 1 = 256)
+ * 2 channels: 128 (128 x 2 = 256)
+ * 3 channels: 64 ( 64 x 3 = 192)
+ * 4 channels: 64 ( 64 x 4 = 256)
+ * 5 channels: 32 ( 32 x 5 = 160)
+ * 6 channels: 32 ( 32 x 6 = 192)
+ * 7 channels: 32 ( 32 x 7 = 224)
+ * 8 channels: 32 ( 32 x 8 = 256)
+ */
+ for (i = 1; i < fsi->chan_num; i <<= 1)
+ frame_capa >>= 1;
+ dev_dbg(dev, "%d channel %d store\n",
+ fsi->chan_num, frame_capa);
+
+ io->fifo_sample_capa = fsi_frame2sample(fsi, frame_capa);
+
+ /*
+ * set interrupt generation factor
+ * clear FIFO
+ */
+ if (is_play) {
+ fsi_reg_write(fsi, DOFF_CTL, IRQ_HALF);
+ fsi_reg_mask_set(fsi, DOFF_CTL, FIFO_CLR, FIFO_CLR);
+ } else {
+ fsi_reg_write(fsi, DIFF_CTL, IRQ_HALF);
+ fsi_reg_mask_set(fsi, DIFF_CTL, FIFO_CLR, FIFO_CLR);
+ }
+}
static int fsi_hw_startup(struct fsi_priv *fsi,
- int is_play,
+ struct fsi_stream *io,
struct device *dev)
{
+ struct fsi_master *master = fsi_get_master(fsi);
+ int fsi_ver = master->core->ver;
u32 flags = fsi_get_info_flags(fsi);
u32 data = 0;
- pm_runtime_get_sync(dev);
-
/* clock setting */
if (fsi_is_clk_master(fsi))
data = DIMD | DOMD;
@@ -919,42 +1211,48 @@ static int fsi_hw_startup(struct fsi_priv *fsi,
fsi_reg_mask_set(fsi, OUT_SEL, DMMD, DMMD);
}
+ /*
+ * FIXME
+ *
+ * FSI driver assumed that data package is in-back.
+ * FSI2 chip can select it.
+ */
+ if (fsi_ver >= 2) {
+ fsi_reg_write(fsi, OUT_DMAC, (1 << 4));
+ fsi_reg_write(fsi, IN_DMAC, (1 << 4));
+ }
+
/* irq clear */
- fsi_irq_disable(fsi, is_play);
+ fsi_irq_disable(fsi, io);
fsi_irq_clear_status(fsi);
/* fifo init */
- fsi_fifo_init(fsi, is_play, dev);
+ fsi_fifo_init(fsi, io, dev);
return 0;
}
static void fsi_hw_shutdown(struct fsi_priv *fsi,
- int is_play,
struct device *dev)
{
if (fsi_is_clk_master(fsi))
fsi_set_master_clk(dev, fsi, fsi->rate, 0);
-
- pm_runtime_put_sync(dev);
}
static int fsi_dai_startup(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- int is_play = fsi_is_play(substream);
- return fsi_hw_startup(fsi, is_play, dai->dev);
+ return fsi_hw_startup(fsi, fsi_stream_get(fsi, substream), dai->dev);
}
static void fsi_dai_shutdown(struct snd_pcm_substream *substream,
struct snd_soc_dai *dai)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- int is_play = fsi_is_play(substream);
- fsi_hw_shutdown(fsi, is_play, dai->dev);
+ fsi_hw_shutdown(fsi, dai->dev);
fsi->rate = 0;
}
@@ -962,18 +1260,19 @@ static int fsi_dai_trigger(struct snd_pcm_substream *substream, int cmd,
struct snd_soc_dai *dai)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- int is_play = fsi_is_play(substream);
+ struct fsi_stream *io = fsi_stream_get(fsi, substream);
int ret = 0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- fsi_stream_push(fsi, is_play, substream);
- ret = is_play ? fsi_data_push(fsi) : fsi_data_pop(fsi);
- fsi_port_start(fsi, is_play);
+ fsi_stream_init(fsi, io, substream);
+ ret = fsi_stream_transfer(io);
+ if (0 == ret)
+ fsi_stream_start(fsi, io);
break;
case SNDRV_PCM_TRIGGER_STOP:
- fsi_port_stop(fsi, is_play);
- fsi_stream_pop(fsi, is_play);
+ fsi_stream_stop(fsi, io);
+ fsi_stream_quit(fsi, io);
break;
}
@@ -1024,8 +1323,7 @@ static int fsi_set_fmt_spdif(struct fsi_priv *fsi)
static int fsi_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
struct fsi_priv *fsi = fsi_get_priv_frm_dai(dai);
- struct fsi_master *master = fsi_get_master(fsi);
- set_rate_func set_rate = fsi_get_info_set_rate(master);
+ set_rate_func set_rate = fsi_get_info_set_rate(fsi);
u32 flags = fsi_get_info_flags(fsi);
int ret;
@@ -1080,7 +1378,7 @@ static int fsi_dai_hw_params(struct snd_pcm_substream *substream,
return ret;
}
-static struct snd_soc_dai_ops fsi_dai_ops = {
+static const struct snd_soc_dai_ops fsi_dai_ops = {
.startup = fsi_dai_startup,
.shutdown = fsi_dai_shutdown,
.trigger = fsi_dai_trigger,
@@ -1139,13 +1437,9 @@ static int fsi_hw_free(struct snd_pcm_substream *substream)
static snd_pcm_uframes_t fsi_pointer(struct snd_pcm_substream *substream)
{
struct fsi_priv *fsi = fsi_get_priv(substream);
- struct fsi_stream *io = fsi_get_stream(fsi, fsi_is_play(substream));
- int samples_pos = io->buff_sample_pos - 1;
+ struct fsi_stream *io = fsi_stream_get(fsi, substream);
- if (samples_pos < 0)
- samples_pos = 0;
-
- return fsi_sample2frame(fsi, samples_pos);
+ return fsi_sample2frame(fsi, io->buff_sample_pos);
}
static struct snd_pcm_ops fsi_pcm_ops = {
@@ -1231,11 +1525,24 @@ static struct snd_soc_platform_driver fsi_soc_platform = {
/*
* platform function
*/
+static void fsi_handler_init(struct fsi_priv *fsi)
+{
+ fsi->playback.handler = &fsi_pio_push_handler; /* default PIO */
+ fsi->playback.priv = fsi;
+ fsi->capture.handler = &fsi_pio_pop_handler; /* default PIO */
+ fsi->capture.priv = fsi;
+
+ if (fsi->info->tx_id) {
+ fsi->playback.slave.slave_id = fsi->info->tx_id;
+ fsi->playback.handler = &fsi_dma_push_handler;
+ }
+}
static int fsi_probe(struct platform_device *pdev)
{
struct fsi_master *master;
const struct platform_device_id *id_entry;
+ struct sh_fsi_platform_info *info = pdev->dev.platform_data;
struct resource *res;
unsigned int irq;
int ret;
@@ -1270,26 +1577,39 @@ static int fsi_probe(struct platform_device *pdev)
/* master setting */
master->irq = irq;
- master->info = pdev->dev.platform_data;
master->core = (struct fsi_core *)id_entry->driver_data;
spin_lock_init(&master->lock);
/* FSI A setting */
master->fsia.base = master->base;
master->fsia.master = master;
+ master->fsia.info = &info->port_a;
+ fsi_handler_init(&master->fsia);
+ ret = fsi_stream_probe(&master->fsia);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "FSIA stream probe failed\n");
+ goto exit_iounmap;
+ }
/* FSI B setting */
master->fsib.base = master->base + 0x40;
master->fsib.master = master;
+ master->fsib.info = &info->port_b;
+ fsi_handler_init(&master->fsib);
+ ret = fsi_stream_probe(&master->fsib);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "FSIB stream probe failed\n");
+ goto exit_fsia;
+ }
pm_runtime_enable(&pdev->dev);
dev_set_drvdata(&pdev->dev, master);
- ret = request_irq(irq, &fsi_interrupt, IRQF_DISABLED,
+ ret = request_irq(irq, &fsi_interrupt, 0,
id_entry->name, master);
if (ret) {
dev_err(&pdev->dev, "irq request err\n");
- goto exit_iounmap;
+ goto exit_fsib;
}
ret = snd_soc_register_platform(&pdev->dev, &fsi_soc_platform);
@@ -1311,6 +1631,10 @@ exit_snd_soc:
snd_soc_unregister_platform(&pdev->dev);
exit_free_irq:
free_irq(irq, master);
+exit_fsib:
+ fsi_stream_remove(&master->fsib);
+exit_fsia:
+ fsi_stream_remove(&master->fsia);
exit_iounmap:
iounmap(master->base);
pm_runtime_disable(&pdev->dev);
@@ -1333,6 +1657,9 @@ static int fsi_remove(struct platform_device *pdev)
snd_soc_unregister_dais(&pdev->dev, ARRAY_SIZE(fsi_soc_dai));
snd_soc_unregister_platform(&pdev->dev);
+ fsi_stream_remove(&master->fsia);
+ fsi_stream_remove(&master->fsib);
+
iounmap(master->base);
kfree(master);
@@ -1340,30 +1667,29 @@ static int fsi_remove(struct platform_device *pdev)
}
static void __fsi_suspend(struct fsi_priv *fsi,
- int is_play,
+ struct fsi_stream *io,
struct device *dev)
{
- if (!fsi_stream_is_working(fsi, is_play))
+ if (!fsi_stream_is_working(fsi, io))
return;
- fsi_port_stop(fsi, is_play);
- fsi_hw_shutdown(fsi, is_play, dev);
+ fsi_stream_stop(fsi, io);
+ fsi_hw_shutdown(fsi, dev);
}
static void __fsi_resume(struct fsi_priv *fsi,
- int is_play,
+ struct fsi_stream *io,
struct device *dev)
{
- if (!fsi_stream_is_working(fsi, is_play))
+ if (!fsi_stream_is_working(fsi, io))
return;
- fsi_hw_startup(fsi, is_play, dev);
+ fsi_hw_startup(fsi, io, dev);
if (fsi_is_clk_master(fsi) && fsi->rate)
fsi_set_master_clk(dev, fsi, fsi->rate, 1);
- fsi_port_start(fsi, is_play);
-
+ fsi_stream_start(fsi, io);
}
static int fsi_suspend(struct device *dev)
@@ -1372,11 +1698,11 @@ static int fsi_suspend(struct device *dev)
struct fsi_priv *fsia = &master->fsia;
struct fsi_priv *fsib = &master->fsib;
- __fsi_suspend(fsia, 1, dev);
- __fsi_suspend(fsia, 0, dev);
+ __fsi_suspend(fsia, &fsia->playback, dev);
+ __fsi_suspend(fsia, &fsia->capture, dev);
- __fsi_suspend(fsib, 1, dev);
- __fsi_suspend(fsib, 0, dev);
+ __fsi_suspend(fsib, &fsib->playback, dev);
+ __fsi_suspend(fsib, &fsib->capture, dev);
return 0;
}
@@ -1387,32 +1713,18 @@ static int fsi_resume(struct device *dev)
struct fsi_priv *fsia = &master->fsia;
struct fsi_priv *fsib = &master->fsib;
- __fsi_resume(fsia, 1, dev);
- __fsi_resume(fsia, 0, dev);
+ __fsi_resume(fsia, &fsia->playback, dev);
+ __fsi_resume(fsia, &fsia->capture, dev);
- __fsi_resume(fsib, 1, dev);
- __fsi_resume(fsib, 0, dev);
+ __fsi_resume(fsib, &fsib->playback, dev);
+ __fsi_resume(fsib, &fsib->capture, dev);
return 0;
}
-static int fsi_runtime_nop(struct device *dev)
-{
- /* Runtime PM callback shared between ->runtime_suspend()
- * and ->runtime_resume(). Simply returns success.
- *
- * This driver re-initializes all registers after
- * pm_runtime_get_sync() anyway so there is no need
- * to save and restore registers here.
- */
- return 0;
-}
-
static struct dev_pm_ops fsi_pm_ops = {
.suspend = fsi_suspend,
.resume = fsi_resume,
- .runtime_suspend = fsi_runtime_nop,
- .runtime_resume = fsi_runtime_nop,
};
static struct fsi_core fsi1_core = {
@@ -1452,18 +1764,7 @@ static struct platform_driver fsi_driver = {
.id_table = fsi_id_table,
};
-static int __init fsi_mobile_init(void)
-{
- return platform_driver_register(&fsi_driver);
-}
-
-static void __exit fsi_mobile_exit(void)
-{
- platform_driver_unregister(&fsi_driver);
-}
-
-module_init(fsi_mobile_init);
-module_exit(fsi_mobile_exit);
+module_platform_driver(fsi_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SuperH onchip FSI audio driver");
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index c87e3ff28a0a..3474d7befe5a 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -266,7 +266,7 @@ static int hac_hw_params(struct snd_pcm_substream *substream,
#define AC97_FMTS \
SNDRV_PCM_FMTBIT_S16_LE
-static struct snd_soc_dai_ops hac_dai_ops = {
+static const struct snd_soc_dai_ops hac_dai_ops = {
.hw_params = hac_hw_params,
};
@@ -332,17 +332,7 @@ static struct platform_driver hac_pcm_driver = {
.remove = __devexit_p(hac_soc_platform_remove),
};
-static int __init sh4_hac_pcm_init(void)
-{
- return platform_driver_register(&hac_pcm_driver);
-}
-module_init(sh4_hac_pcm_init);
-
-static void __exit sh4_hac_pcm_exit(void)
-{
- platform_driver_unregister(&hac_pcm_driver);
-}
-module_exit(sh4_hac_pcm_exit);
+module_platform_driver(hac_pcm_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
diff --git a/sound/soc/sh/migor.c b/sound/soc/sh/migor.c
index 6088a6a3238a..9d9ad8d61c0a 100644
--- a/sound/soc/sh/migor.c
+++ b/sound/soc/sh/migor.c
@@ -164,6 +164,7 @@ static struct snd_soc_dai_link migor_dai = {
/* migor audio machine driver */
static struct snd_soc_card snd_soc_migor = {
.name = "Migo-R",
+ .owner = THIS_MODULE,
.dai_link = &migor_dai,
.num_links = 1,
};
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c
index 917d3ceadc9d..4a3568a9bf59 100644
--- a/sound/soc/sh/sh7760-ac97.c
+++ b/sound/soc/sh/sh7760-ac97.c
@@ -16,16 +16,6 @@
#define IPSEL 0xFE400034
-/* platform specific structs can be declared here */
-extern struct snd_soc_dai_driver sh4_hac_dai[2];
-extern struct snd_soc_platform_driver sh7760_soc_platform;
-
-static int machine_init(struct snd_soc_pcm_runtime *rtd)
-{
- snd_soc_dapm_sync(&rtd->codec->dapm);
- return 0;
-}
-
static struct snd_soc_dai_link sh7760_ac97_dai = {
.name = "AC97",
.stream_name = "AC97 HiFi",
@@ -33,12 +23,12 @@ static struct snd_soc_dai_link sh7760_ac97_dai = {
.codec_dai_name = "ac97-hifi",
.platform_name = "sh7760-pcm-audio",
.codec_name = "ac97-codec",
- .init = machine_init,
.ops = NULL,
};
static struct snd_soc_card sh7760_ac97_soc_machine = {
.name = "SH7760 AC97",
+ .owner = THIS_MODULE,
.dai_link = &sh7760_ac97_dai,
.num_links = 1,
};
diff --git a/sound/soc/sh/siu_dai.c b/sound/soc/sh/siu_dai.c
index 4973c2939d79..52d4c17b1232 100644
--- a/sound/soc/sh/siu_dai.c
+++ b/sound/soc/sh/siu_dai.c
@@ -23,6 +23,7 @@
#include <linux/firmware.h>
#include <linux/pm_runtime.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <asm/clock.h>
#include <asm/siu.h>
@@ -111,9 +112,6 @@ static void siu_dai_start(struct siu_port *port_info)
dev_dbg(port_info->pcm->card->dev, "%s\n", __func__);
- /* Turn on SIU clock */
- pm_runtime_get_sync(info->dev);
-
/* Issue software reset to siu */
siu_write32(base + SIU_SRCTL, 0);
@@ -157,9 +155,6 @@ static void siu_dai_stop(struct siu_port *port_info)
/* SIU software reset */
siu_write32(base + SIU_SRCTL, 0);
-
- /* Turn off SIU clock */
- pm_runtime_put_sync(info->dev);
}
static void siu_dai_spbAselect(struct siu_port *port_info)
@@ -706,7 +701,7 @@ epclkget:
return ret;
}
-static struct snd_soc_dai_ops siu_dai_ops = {
+static const struct snd_soc_dai_ops siu_dai_ops = {
.startup = siu_dai_startup,
.shutdown = siu_dai_shutdown,
.prepare = siu_dai_prepare,
@@ -851,18 +846,7 @@ static struct platform_driver siu_driver = {
.remove = __devexit_p(siu_remove),
};
-static int __init siu_init(void)
-{
- return platform_driver_register(&siu_driver);
-}
-
-static void __exit siu_exit(void)
-{
- platform_driver_unregister(&siu_driver);
-}
-
-module_init(siu_init)
-module_exit(siu_exit)
+module_platform_driver(siu_driver);
MODULE_AUTHOR("Carlos Munoz <carlos@kenati.com>");
MODULE_DESCRIPTION("ALSA SoC SH7722 SIU driver");
diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c
index f8f681690a71..0193e595d415 100644
--- a/sound/soc/sh/siu_pcm.c
+++ b/sound/soc/sh/siu_pcm.c
@@ -131,7 +131,7 @@ static int siu_pcm_wr_set(struct siu_port *port_info,
sg_dma_address(&sg) = buff;
desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
- &sg, 1, DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ &sg, 1, DMA_MEM_TO_DEV, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
dev_err(dev, "Failed to allocate a dma descriptor\n");
return -ENOMEM;
@@ -181,7 +181,7 @@ static int siu_pcm_rd_set(struct siu_port *port_info,
sg_dma_address(&sg) = buff;
desc = siu_stream->chan->device->device_prep_slave_sg(siu_stream->chan,
- &sg, 1, DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+ &sg, 1, DMA_DEV_TO_MEM, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
dev_err(dev, "Failed to allocate dma descriptor\n");
return -ENOMEM;
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index 05192d97b377..ff82b56a8860 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -332,7 +332,7 @@ static int ssi_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_U24_3LE | \
SNDRV_PCM_FMTBIT_S32_LE | SNDRV_PCM_FMTBIT_U32_LE)
-static struct snd_soc_dai_ops ssi_dai_ops = {
+static const struct snd_soc_dai_ops ssi_dai_ops = {
.startup = ssi_startup,
.shutdown = ssi_shutdown,
.trigger = ssi_trigger,
@@ -342,7 +342,7 @@ static struct snd_soc_dai_ops ssi_dai_ops = {
.set_fmt = ssi_set_fmt,
};
-struct snd_soc_dai_driver sh4_ssi_dai[] = {
+static struct snd_soc_dai_driver sh4_ssi_dai[] = {
{
.name = "ssi-dai.0",
.playback = {
@@ -401,17 +401,7 @@ static struct platform_driver sh4_ssi_driver = {
.remove = __devexit_p(sh4_soc_dai_remove),
};
-static int __init snd_sh4_ssi_init(void)
-{
- return platform_driver_register(&sh4_ssi_driver);
-}
-module_init(snd_sh4_ssi_init);
-
-static void __exit snd_sh4_ssi_exit(void)
-{
- platform_driver_unregister(&sh4_ssi_driver);
-}
-module_exit(snd_sh4_ssi_exit);
+module_platform_driver(sh4_ssi_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
diff --git a/sound/soc/soc-cache.c b/sound/soc/soc-cache.c
index d9f8aded51f3..9d56f0218f41 100644
--- a/sound/soc/soc-cache.c
+++ b/sound/soc/soc-cache.c
@@ -14,9 +14,9 @@
#include <linux/i2c.h>
#include <linux/spi/spi.h>
#include <sound/soc.h>
-#include <linux/lzo.h>
#include <linux/bitmap.h>
#include <linux/rbtree.h>
+#include <linux/export.h>
#include <trace/events/asoc.h>
@@ -66,754 +66,6 @@ static unsigned int snd_soc_get_cache_val(const void *base, unsigned int idx,
return -1;
}
-struct snd_soc_rbtree_node {
- struct rb_node node; /* the actual rbtree node holding this block */
- unsigned int base_reg; /* base register handled by this block */
- unsigned int word_size; /* number of bytes needed to represent the register index */
- void *block; /* block of adjacent registers */
- unsigned int blklen; /* number of registers available in the block */
-} __attribute__ ((packed));
-
-struct snd_soc_rbtree_ctx {
- struct rb_root root;
- struct snd_soc_rbtree_node *cached_rbnode;
-};
-
-static inline void snd_soc_rbtree_get_base_top_reg(
- struct snd_soc_rbtree_node *rbnode,
- unsigned int *base, unsigned int *top)
-{
- *base = rbnode->base_reg;
- *top = rbnode->base_reg + rbnode->blklen - 1;
-}
-
-static unsigned int snd_soc_rbtree_get_register(
- struct snd_soc_rbtree_node *rbnode, unsigned int idx)
-{
- unsigned int val;
-
- switch (rbnode->word_size) {
- case 1: {
- u8 *p = rbnode->block;
- val = p[idx];
- return val;
- }
- case 2: {
- u16 *p = rbnode->block;
- val = p[idx];
- return val;
- }
- default:
- BUG();
- break;
- }
- return -1;
-}
-
-static void snd_soc_rbtree_set_register(struct snd_soc_rbtree_node *rbnode,
- unsigned int idx, unsigned int val)
-{
- switch (rbnode->word_size) {
- case 1: {
- u8 *p = rbnode->block;
- p[idx] = val;
- break;
- }
- case 2: {
- u16 *p = rbnode->block;
- p[idx] = val;
- break;
- }
- default:
- BUG();
- break;
- }
-}
-
-static struct snd_soc_rbtree_node *snd_soc_rbtree_lookup(
- struct rb_root *root, unsigned int reg)
-{
- struct rb_node *node;
- struct snd_soc_rbtree_node *rbnode;
- unsigned int base_reg, top_reg;
-
- node = root->rb_node;
- while (node) {
- rbnode = container_of(node, struct snd_soc_rbtree_node, node);
- snd_soc_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
- if (reg >= base_reg && reg <= top_reg)
- return rbnode;
- else if (reg > top_reg)
- node = node->rb_right;
- else if (reg < base_reg)
- node = node->rb_left;
- }
-
- return NULL;
-}
-
-static int snd_soc_rbtree_insert(struct rb_root *root,
- struct snd_soc_rbtree_node *rbnode)
-{
- struct rb_node **new, *parent;
- struct snd_soc_rbtree_node *rbnode_tmp;
- unsigned int base_reg_tmp, top_reg_tmp;
- unsigned int base_reg;
-
- parent = NULL;
- new = &root->rb_node;
- while (*new) {
- rbnode_tmp = container_of(*new, struct snd_soc_rbtree_node,
- node);
- /* base and top registers of the current rbnode */
- snd_soc_rbtree_get_base_top_reg(rbnode_tmp, &base_reg_tmp,
- &top_reg_tmp);
- /* base register of the rbnode to be added */
- base_reg = rbnode->base_reg;
- parent = *new;
- /* if this register has already been inserted, just return */
- if (base_reg >= base_reg_tmp &&
- base_reg <= top_reg_tmp)
- return 0;
- else if (base_reg > top_reg_tmp)
- new = &((*new)->rb_right);
- else if (base_reg < base_reg_tmp)
- new = &((*new)->rb_left);
- }
-
- /* insert the node into the rbtree */
- rb_link_node(&rbnode->node, parent, new);
- rb_insert_color(&rbnode->node, root);
-
- return 1;
-}
-
-static int snd_soc_rbtree_cache_sync(struct snd_soc_codec *codec)
-{
- struct snd_soc_rbtree_ctx *rbtree_ctx;
- struct rb_node *node;
- struct snd_soc_rbtree_node *rbnode;
- unsigned int regtmp;
- unsigned int val, def;
- int ret;
- int i;
-
- rbtree_ctx = codec->reg_cache;
- for (node = rb_first(&rbtree_ctx->root); node; node = rb_next(node)) {
- rbnode = rb_entry(node, struct snd_soc_rbtree_node, node);
- for (i = 0; i < rbnode->blklen; ++i) {
- regtmp = rbnode->base_reg + i;
- WARN_ON(codec->writable_register &&
- codec->writable_register(codec, regtmp));
- val = snd_soc_rbtree_get_register(rbnode, i);
- def = snd_soc_get_cache_val(codec->reg_def_copy, i,
- rbnode->word_size);
- if (val == def)
- continue;
-
- codec->cache_bypass = 1;
- ret = snd_soc_write(codec, regtmp, val);
- codec->cache_bypass = 0;
- if (ret)
- return ret;
- dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
- regtmp, val);
- }
- }
-
- return 0;
-}
-
-static int snd_soc_rbtree_insert_to_block(struct snd_soc_rbtree_node *rbnode,
- unsigned int pos, unsigned int reg,
- unsigned int value)
-{
- u8 *blk;
-
- blk = krealloc(rbnode->block,
- (rbnode->blklen + 1) * rbnode->word_size, GFP_KERNEL);
- if (!blk)
- return -ENOMEM;
-
- /* insert the register value in the correct place in the rbnode block */
- memmove(blk + (pos + 1) * rbnode->word_size,
- blk + pos * rbnode->word_size,
- (rbnode->blklen - pos) * rbnode->word_size);
-
- /* update the rbnode block, its size and the base register */
- rbnode->block = blk;
- rbnode->blklen++;
- if (!pos)
- rbnode->base_reg = reg;
-
- snd_soc_rbtree_set_register(rbnode, pos, value);
- return 0;
-}
-
-static int snd_soc_rbtree_cache_write(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
-{
- struct snd_soc_rbtree_ctx *rbtree_ctx;
- struct snd_soc_rbtree_node *rbnode, *rbnode_tmp;
- struct rb_node *node;
- unsigned int val;
- unsigned int reg_tmp;
- unsigned int base_reg, top_reg;
- unsigned int pos;
- int i;
- int ret;
-
- rbtree_ctx = codec->reg_cache;
- /* look up the required register in the cached rbnode */
- rbnode = rbtree_ctx->cached_rbnode;
- if (rbnode) {
- snd_soc_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
- if (reg >= base_reg && reg <= top_reg) {
- reg_tmp = reg - base_reg;
- val = snd_soc_rbtree_get_register(rbnode, reg_tmp);
- if (val == value)
- return 0;
- snd_soc_rbtree_set_register(rbnode, reg_tmp, value);
- return 0;
- }
- }
- /* if we can't locate it in the cached rbnode we'll have
- * to traverse the rbtree looking for it.
- */
- rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
- if (rbnode) {
- reg_tmp = reg - rbnode->base_reg;
- val = snd_soc_rbtree_get_register(rbnode, reg_tmp);
- if (val == value)
- return 0;
- snd_soc_rbtree_set_register(rbnode, reg_tmp, value);
- rbtree_ctx->cached_rbnode = rbnode;
- } else {
- /* bail out early, no need to create the rbnode yet */
- if (!value)
- return 0;
- /* look for an adjacent register to the one we are about to add */
- for (node = rb_first(&rbtree_ctx->root); node;
- node = rb_next(node)) {
- rbnode_tmp = rb_entry(node, struct snd_soc_rbtree_node, node);
- for (i = 0; i < rbnode_tmp->blklen; ++i) {
- reg_tmp = rbnode_tmp->base_reg + i;
- if (abs(reg_tmp - reg) != 1)
- continue;
- /* decide where in the block to place our register */
- if (reg_tmp + 1 == reg)
- pos = i + 1;
- else
- pos = i;
- ret = snd_soc_rbtree_insert_to_block(rbnode_tmp, pos,
- reg, value);
- if (ret)
- return ret;
- rbtree_ctx->cached_rbnode = rbnode_tmp;
- return 0;
- }
- }
- /* we did not manage to find a place to insert it in an existing
- * block so create a new rbnode with a single register in its block.
- * This block will get populated further if any other adjacent
- * registers get modified in the future.
- */
- rbnode = kzalloc(sizeof *rbnode, GFP_KERNEL);
- if (!rbnode)
- return -ENOMEM;
- rbnode->blklen = 1;
- rbnode->base_reg = reg;
- rbnode->word_size = codec->driver->reg_word_size;
- rbnode->block = kmalloc(rbnode->blklen * rbnode->word_size,
- GFP_KERNEL);
- if (!rbnode->block) {
- kfree(rbnode);
- return -ENOMEM;
- }
- snd_soc_rbtree_set_register(rbnode, 0, value);
- snd_soc_rbtree_insert(&rbtree_ctx->root, rbnode);
- rbtree_ctx->cached_rbnode = rbnode;
- }
-
- return 0;
-}
-
-static int snd_soc_rbtree_cache_read(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int *value)
-{
- struct snd_soc_rbtree_ctx *rbtree_ctx;
- struct snd_soc_rbtree_node *rbnode;
- unsigned int base_reg, top_reg;
- unsigned int reg_tmp;
-
- rbtree_ctx = codec->reg_cache;
- /* look up the required register in the cached rbnode */
- rbnode = rbtree_ctx->cached_rbnode;
- if (rbnode) {
- snd_soc_rbtree_get_base_top_reg(rbnode, &base_reg, &top_reg);
- if (reg >= base_reg && reg <= top_reg) {
- reg_tmp = reg - base_reg;
- *value = snd_soc_rbtree_get_register(rbnode, reg_tmp);
- return 0;
- }
- }
- /* if we can't locate it in the cached rbnode we'll have
- * to traverse the rbtree looking for it.
- */
- rbnode = snd_soc_rbtree_lookup(&rbtree_ctx->root, reg);
- if (rbnode) {
- reg_tmp = reg - rbnode->base_reg;
- *value = snd_soc_rbtree_get_register(rbnode, reg_tmp);
- rbtree_ctx->cached_rbnode = rbnode;
- } else {
- /* uninitialized registers default to 0 */
- *value = 0;
- }
-
- return 0;
-}
-
-static int snd_soc_rbtree_cache_exit(struct snd_soc_codec *codec)
-{
- struct rb_node *next;
- struct snd_soc_rbtree_ctx *rbtree_ctx;
- struct snd_soc_rbtree_node *rbtree_node;
-
- /* if we've already been called then just return */
- rbtree_ctx = codec->reg_cache;
- if (!rbtree_ctx)
- return 0;
-
- /* free up the rbtree */
- next = rb_first(&rbtree_ctx->root);
- while (next) {
- rbtree_node = rb_entry(next, struct snd_soc_rbtree_node, node);
- next = rb_next(&rbtree_node->node);
- rb_erase(&rbtree_node->node, &rbtree_ctx->root);
- kfree(rbtree_node->block);
- kfree(rbtree_node);
- }
-
- /* release the resources */
- kfree(codec->reg_cache);
- codec->reg_cache = NULL;
-
- return 0;
-}
-
-static int snd_soc_rbtree_cache_init(struct snd_soc_codec *codec)
-{
- struct snd_soc_rbtree_ctx *rbtree_ctx;
- unsigned int word_size;
- unsigned int val;
- int i;
- int ret;
-
- codec->reg_cache = kmalloc(sizeof *rbtree_ctx, GFP_KERNEL);
- if (!codec->reg_cache)
- return -ENOMEM;
-
- rbtree_ctx = codec->reg_cache;
- rbtree_ctx->root = RB_ROOT;
- rbtree_ctx->cached_rbnode = NULL;
-
- if (!codec->reg_def_copy)
- return 0;
-
- word_size = codec->driver->reg_word_size;
- for (i = 0; i < codec->driver->reg_cache_size; ++i) {
- val = snd_soc_get_cache_val(codec->reg_def_copy, i,
- word_size);
- if (!val)
- continue;
- ret = snd_soc_rbtree_cache_write(codec, i, val);
- if (ret)
- goto err;
- }
-
- return 0;
-
-err:
- snd_soc_cache_exit(codec);
- return ret;
-}
-
-#ifdef CONFIG_SND_SOC_CACHE_LZO
-struct snd_soc_lzo_ctx {
- void *wmem;
- void *dst;
- const void *src;
- size_t src_len;
- size_t dst_len;
- size_t decompressed_size;
- unsigned long *sync_bmp;
- int sync_bmp_nbits;
-};
-
-#define LZO_BLOCK_NUM 8
-static int snd_soc_lzo_block_count(void)
-{
- return LZO_BLOCK_NUM;
-}
-
-static int snd_soc_lzo_prepare(struct snd_soc_lzo_ctx *lzo_ctx)
-{
- lzo_ctx->wmem = kmalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
- if (!lzo_ctx->wmem)
- return -ENOMEM;
- return 0;
-}
-
-static int snd_soc_lzo_compress(struct snd_soc_lzo_ctx *lzo_ctx)
-{
- size_t compress_size;
- int ret;
-
- ret = lzo1x_1_compress(lzo_ctx->src, lzo_ctx->src_len,
- lzo_ctx->dst, &compress_size, lzo_ctx->wmem);
- if (ret != LZO_E_OK || compress_size > lzo_ctx->dst_len)
- return -EINVAL;
- lzo_ctx->dst_len = compress_size;
- return 0;
-}
-
-static int snd_soc_lzo_decompress(struct snd_soc_lzo_ctx *lzo_ctx)
-{
- size_t dst_len;
- int ret;
-
- dst_len = lzo_ctx->dst_len;
- ret = lzo1x_decompress_safe(lzo_ctx->src, lzo_ctx->src_len,
- lzo_ctx->dst, &dst_len);
- if (ret != LZO_E_OK || dst_len != lzo_ctx->dst_len)
- return -EINVAL;
- return 0;
-}
-
-static int snd_soc_lzo_compress_cache_block(struct snd_soc_codec *codec,
- struct snd_soc_lzo_ctx *lzo_ctx)
-{
- int ret;
-
- lzo_ctx->dst_len = lzo1x_worst_compress(PAGE_SIZE);
- lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
- if (!lzo_ctx->dst) {
- lzo_ctx->dst_len = 0;
- return -ENOMEM;
- }
-
- ret = snd_soc_lzo_compress(lzo_ctx);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-static int snd_soc_lzo_decompress_cache_block(struct snd_soc_codec *codec,
- struct snd_soc_lzo_ctx *lzo_ctx)
-{
- int ret;
-
- lzo_ctx->dst_len = lzo_ctx->decompressed_size;
- lzo_ctx->dst = kmalloc(lzo_ctx->dst_len, GFP_KERNEL);
- if (!lzo_ctx->dst) {
- lzo_ctx->dst_len = 0;
- return -ENOMEM;
- }
-
- ret = snd_soc_lzo_decompress(lzo_ctx);
- if (ret < 0)
- return ret;
- return 0;
-}
-
-static inline int snd_soc_lzo_get_blkindex(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- const struct snd_soc_codec_driver *codec_drv;
-
- codec_drv = codec->driver;
- return (reg * codec_drv->reg_word_size) /
- DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
-}
-
-static inline int snd_soc_lzo_get_blkpos(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- const struct snd_soc_codec_driver *codec_drv;
-
- codec_drv = codec->driver;
- return reg % (DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count()) /
- codec_drv->reg_word_size);
-}
-
-static inline int snd_soc_lzo_get_blksize(struct snd_soc_codec *codec)
-{
- const struct snd_soc_codec_driver *codec_drv;
-
- codec_drv = codec->driver;
- return DIV_ROUND_UP(codec->reg_size, snd_soc_lzo_block_count());
-}
-
-static int snd_soc_lzo_cache_sync(struct snd_soc_codec *codec)
-{
- struct snd_soc_lzo_ctx **lzo_blocks;
- unsigned int val;
- int i;
- int ret;
-
- lzo_blocks = codec->reg_cache;
- for_each_set_bit(i, lzo_blocks[0]->sync_bmp, lzo_blocks[0]->sync_bmp_nbits) {
- WARN_ON(codec->writable_register &&
- codec->writable_register(codec, i));
- ret = snd_soc_cache_read(codec, i, &val);
- if (ret)
- return ret;
- codec->cache_bypass = 1;
- ret = snd_soc_write(codec, i, val);
- codec->cache_bypass = 0;
- if (ret)
- return ret;
- dev_dbg(codec->dev, "Synced register %#x, value = %#x\n",
- i, val);
- }
-
- return 0;
-}
-
-static int snd_soc_lzo_cache_write(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
-{
- struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
- int ret, blkindex, blkpos;
- size_t blksize, tmp_dst_len;
- void *tmp_dst;
-
- /* index of the compressed lzo block */
- blkindex = snd_soc_lzo_get_blkindex(codec, reg);
- /* register index within the decompressed block */
- blkpos = snd_soc_lzo_get_blkpos(codec, reg);
- /* size of the compressed block */
- blksize = snd_soc_lzo_get_blksize(codec);
- lzo_blocks = codec->reg_cache;
- lzo_block = lzo_blocks[blkindex];
-
- /* save the pointer and length of the compressed block */
- tmp_dst = lzo_block->dst;
- tmp_dst_len = lzo_block->dst_len;
-
- /* prepare the source to be the compressed block */
- lzo_block->src = lzo_block->dst;
- lzo_block->src_len = lzo_block->dst_len;
-
- /* decompress the block */
- ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
- if (ret < 0) {
- kfree(lzo_block->dst);
- goto out;
- }
-
- /* write the new value to the cache */
- if (snd_soc_set_cache_val(lzo_block->dst, blkpos, value,
- codec->driver->reg_word_size)) {
- kfree(lzo_block->dst);
- goto out;
- }
-
- /* prepare the source to be the decompressed block */
- lzo_block->src = lzo_block->dst;
- lzo_block->src_len = lzo_block->dst_len;
-
- /* compress the block */
- ret = snd_soc_lzo_compress_cache_block(codec, lzo_block);
- if (ret < 0) {
- kfree(lzo_block->dst);
- kfree(lzo_block->src);
- goto out;
- }
-
- /* set the bit so we know we have to sync this register */
- set_bit(reg, lzo_block->sync_bmp);
- kfree(tmp_dst);
- kfree(lzo_block->src);
- return 0;
-out:
- lzo_block->dst = tmp_dst;
- lzo_block->dst_len = tmp_dst_len;
- return ret;
-}
-
-static int snd_soc_lzo_cache_read(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int *value)
-{
- struct snd_soc_lzo_ctx *lzo_block, **lzo_blocks;
- int ret, blkindex, blkpos;
- size_t blksize, tmp_dst_len;
- void *tmp_dst;
-
- *value = 0;
- /* index of the compressed lzo block */
- blkindex = snd_soc_lzo_get_blkindex(codec, reg);
- /* register index within the decompressed block */
- blkpos = snd_soc_lzo_get_blkpos(codec, reg);
- /* size of the compressed block */
- blksize = snd_soc_lzo_get_blksize(codec);
- lzo_blocks = codec->reg_cache;
- lzo_block = lzo_blocks[blkindex];
-
- /* save the pointer and length of the compressed block */
- tmp_dst = lzo_block->dst;
- tmp_dst_len = lzo_block->dst_len;
-
- /* prepare the source to be the compressed block */
- lzo_block->src = lzo_block->dst;
- lzo_block->src_len = lzo_block->dst_len;
-
- /* decompress the block */
- ret = snd_soc_lzo_decompress_cache_block(codec, lzo_block);
- if (ret >= 0)
- /* fetch the value from the cache */
- *value = snd_soc_get_cache_val(lzo_block->dst, blkpos,
- codec->driver->reg_word_size);
-
- kfree(lzo_block->dst);
- /* restore the pointer and length of the compressed block */
- lzo_block->dst = tmp_dst;
- lzo_block->dst_len = tmp_dst_len;
- return 0;
-}
-
-static int snd_soc_lzo_cache_exit(struct snd_soc_codec *codec)
-{
- struct snd_soc_lzo_ctx **lzo_blocks;
- int i, blkcount;
-
- lzo_blocks = codec->reg_cache;
- if (!lzo_blocks)
- return 0;
-
- blkcount = snd_soc_lzo_block_count();
- /*
- * the pointer to the bitmap used for syncing the cache
- * is shared amongst all lzo_blocks. Ensure it is freed
- * only once.
- */
- if (lzo_blocks[0])
- kfree(lzo_blocks[0]->sync_bmp);
- for (i = 0; i < blkcount; ++i) {
- if (lzo_blocks[i]) {
- kfree(lzo_blocks[i]->wmem);
- kfree(lzo_blocks[i]->dst);
- }
- /* each lzo_block is a pointer returned by kmalloc or NULL */
- kfree(lzo_blocks[i]);
- }
- kfree(lzo_blocks);
- codec->reg_cache = NULL;
- return 0;
-}
-
-static int snd_soc_lzo_cache_init(struct snd_soc_codec *codec)
-{
- struct snd_soc_lzo_ctx **lzo_blocks;
- size_t bmp_size;
- const struct snd_soc_codec_driver *codec_drv;
- int ret, tofree, i, blksize, blkcount;
- const char *p, *end;
- unsigned long *sync_bmp;
-
- ret = 0;
- codec_drv = codec->driver;
-
- /*
- * If we have not been given a default register cache
- * then allocate a dummy zero-ed out region, compress it
- * and remember to free it afterwards.
- */
- tofree = 0;
- if (!codec->reg_def_copy)
- tofree = 1;
-
- if (!codec->reg_def_copy) {
- codec->reg_def_copy = kzalloc(codec->reg_size, GFP_KERNEL);
- if (!codec->reg_def_copy)
- return -ENOMEM;
- }
-
- blkcount = snd_soc_lzo_block_count();
- codec->reg_cache = kzalloc(blkcount * sizeof *lzo_blocks,
- GFP_KERNEL);
- if (!codec->reg_cache) {
- ret = -ENOMEM;
- goto err_tofree;
- }
- lzo_blocks = codec->reg_cache;
-
- /*
- * allocate a bitmap to be used when syncing the cache with
- * the hardware. Each time a register is modified, the corresponding
- * bit is set in the bitmap, so we know that we have to sync
- * that register.
- */
- bmp_size = codec_drv->reg_cache_size;
- sync_bmp = kmalloc(BITS_TO_LONGS(bmp_size) * sizeof(long),
- GFP_KERNEL);
- if (!sync_bmp) {
- ret = -ENOMEM;
- goto err;
- }
- bitmap_zero(sync_bmp, bmp_size);
-
- /* allocate the lzo blocks and initialize them */
- for (i = 0; i < blkcount; ++i) {
- lzo_blocks[i] = kzalloc(sizeof **lzo_blocks,
- GFP_KERNEL);
- if (!lzo_blocks[i]) {
- kfree(sync_bmp);
- ret = -ENOMEM;
- goto err;
- }
- lzo_blocks[i]->sync_bmp = sync_bmp;
- lzo_blocks[i]->sync_bmp_nbits = bmp_size;
- /* alloc the working space for the compressed block */
- ret = snd_soc_lzo_prepare(lzo_blocks[i]);
- if (ret < 0)
- goto err;
- }
-
- blksize = snd_soc_lzo_get_blksize(codec);
- p = codec->reg_def_copy;
- end = codec->reg_def_copy + codec->reg_size;
- /* compress the register map and fill the lzo blocks */
- for (i = 0; i < blkcount; ++i, p += blksize) {
- lzo_blocks[i]->src = p;
- if (p + blksize > end)
- lzo_blocks[i]->src_len = end - p;
- else
- lzo_blocks[i]->src_len = blksize;
- ret = snd_soc_lzo_compress_cache_block(codec,
- lzo_blocks[i]);
- if (ret < 0)
- goto err;
- lzo_blocks[i]->decompressed_size =
- lzo_blocks[i]->src_len;
- }
-
- if (tofree) {
- kfree(codec->reg_def_copy);
- codec->reg_def_copy = NULL;
- }
- return 0;
-err:
- snd_soc_cache_exit(codec);
-err_tofree:
- if (tofree) {
- kfree(codec->reg_def_copy);
- codec->reg_def_copy = NULL;
- }
- return ret;
-}
-#endif
-
static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
{
int i;
@@ -823,8 +75,6 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
codec_drv = codec->driver;
for (i = 0; i < codec_drv->reg_cache_size; ++i) {
- WARN_ON(codec->writable_register &&
- codec->writable_register(codec, i));
ret = snd_soc_cache_read(codec, i, &val);
if (ret)
return ret;
@@ -832,6 +82,9 @@ static int snd_soc_flat_cache_sync(struct snd_soc_codec *codec)
if (snd_soc_get_cache_val(codec->reg_def_copy,
i, codec_drv->reg_word_size) == val)
continue;
+
+ WARN_ON(!snd_soc_codec_writable_register(codec, i));
+
ret = snd_soc_write(codec, i, val);
if (ret)
return ret;
@@ -868,10 +121,6 @@ static int snd_soc_flat_cache_exit(struct snd_soc_codec *codec)
static int snd_soc_flat_cache_init(struct snd_soc_codec *codec)
{
- const struct snd_soc_codec_driver *codec_drv;
-
- codec_drv = codec->driver;
-
if (codec->reg_def_copy)
codec->reg_cache = kmemdup(codec->reg_def_copy,
codec->reg_size, GFP_KERNEL);
@@ -895,26 +144,6 @@ static const struct snd_soc_cache_ops cache_types[] = {
.write = snd_soc_flat_cache_write,
.sync = snd_soc_flat_cache_sync
},
-#ifdef CONFIG_SND_SOC_CACHE_LZO
- {
- .id = SND_SOC_LZO_COMPRESSION,
- .name = "LZO",
- .init = snd_soc_lzo_cache_init,
- .exit = snd_soc_lzo_cache_exit,
- .read = snd_soc_lzo_cache_read,
- .write = snd_soc_lzo_cache_write,
- .sync = snd_soc_lzo_cache_sync
- },
-#endif
- {
- .id = SND_SOC_RBTREE_COMPRESSION,
- .name = "rbtree",
- .init = snd_soc_rbtree_cache_init,
- .exit = snd_soc_rbtree_cache_exit,
- .read = snd_soc_rbtree_cache_read,
- .write = snd_soc_rbtree_cache_write,
- .sync = snd_soc_rbtree_cache_sync
- }
};
int snd_soc_cache_init(struct snd_soc_codec *codec)
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index b085d8e87574..a4deebc0801a 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -30,7 +30,9 @@
#include <linux/bitops.h>
#include <linux/debugfs.h>
#include <linux/platform_device.h>
+#include <linux/ctype.h>
#include <linux/slab.h>
+#include <linux/of.h>
#include <sound/ac97_codec.h>
#include <sound/core.h>
#include <sound/jack.h>
@@ -57,8 +59,6 @@ static LIST_HEAD(dai_list);
static LIST_HEAD(platform_list);
static LIST_HEAD(codec_list);
-int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num);
-
/*
* This is a timeout to do a DAPM powerdown after a stream is closed().
* It can be used to eliminate pops between different playback streams, e.g.
@@ -105,7 +105,7 @@ static int format_register_str(struct snd_soc_codec *codec,
if (wordsize + regsize + 2 + 1 != len)
return -EINVAL;
- ret = snd_soc_read(codec , reg);
+ ret = snd_soc_read(codec, reg);
if (ret < 0) {
memset(regbuf, 'X', regsize);
regbuf[regsize] = '\0';
@@ -143,7 +143,7 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf,
step = codec->driver->reg_cache_step;
for (i = 0; i < codec->driver->reg_cache_size; i += step) {
- if (codec->readable_register && !codec->readable_register(codec, i))
+ if (!snd_soc_codec_readable_register(codec, i))
continue;
if (codec->driver->display_register) {
count += codec->driver->display_register(codec, buf + count,
@@ -169,8 +169,7 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf,
static ssize_t codec_reg_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct snd_soc_pcm_runtime *rtd =
- container_of(dev, struct snd_soc_pcm_runtime, dev);
+ struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
return soc_codec_reg_show(rtd->codec, buf, PAGE_SIZE, 0);
}
@@ -180,8 +179,7 @@ static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
static ssize_t pmdown_time_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct snd_soc_pcm_runtime *rtd =
- container_of(dev, struct snd_soc_pcm_runtime, dev);
+ struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
return sprintf(buf, "%ld\n", rtd->pmdown_time);
}
@@ -190,8 +188,7 @@ static ssize_t pmdown_time_set(struct device *dev,
struct device_attribute *attr,
const char *buf, size_t count)
{
- struct snd_soc_pcm_runtime *rtd =
- container_of(dev, struct snd_soc_pcm_runtime, dev);
+ struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
int ret;
ret = strict_strtol(buf, 10, &rtd->pmdown_time);
@@ -244,7 +241,6 @@ static ssize_t codec_reg_write_file(struct file *file,
size_t buf_size;
char *start = buf;
unsigned long reg, value;
- int step = 1;
struct snd_soc_codec *codec = file->private_data;
buf_size = min(count, (sizeof(buf)-1));
@@ -252,9 +248,6 @@ static ssize_t codec_reg_write_file(struct file *file,
return -EFAULT;
buf[buf_size] = 0;
- if (codec->driver->reg_cache_step)
- step = codec->driver->reg_cache_step;
-
while (*start == ' ')
start++;
reg = simple_strtoul(start, &start, 16);
@@ -284,8 +277,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
codec->debugfs_codec_root = debugfs_create_dir(codec->name,
debugfs_card_root);
if (!codec->debugfs_codec_root) {
- printk(KERN_WARNING
- "ASoC: Failed to create codec debugfs directory\n");
+ dev_warn(codec->dev, "Failed to create codec debugfs directory\n");
return;
}
@@ -298,8 +290,7 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
codec->debugfs_codec_root,
codec, &codec_reg_fops);
if (!codec->debugfs_reg)
- printk(KERN_WARNING
- "ASoC: Failed to create codec register debugfs file\n");
+ dev_warn(codec->dev, "Failed to create codec register debugfs file\n");
snd_soc_dapm_debugfs_init(&codec->dapm, codec->debugfs_codec_root);
}
@@ -309,6 +300,27 @@ static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
debugfs_remove_recursive(codec->debugfs_codec_root);
}
+static void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+ struct dentry *debugfs_card_root = platform->card->debugfs_card_root;
+
+ platform->debugfs_platform_root = debugfs_create_dir(platform->name,
+ debugfs_card_root);
+ if (!platform->debugfs_platform_root) {
+ dev_warn(platform->dev,
+ "Failed to create platform debugfs directory\n");
+ return;
+ }
+
+ snd_soc_dapm_debugfs_init(&platform->dapm,
+ platform->debugfs_platform_root);
+}
+
+static void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+ debugfs_remove_recursive(platform->debugfs_platform_root);
+}
+
static ssize_t codec_list_read_file(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -415,7 +427,7 @@ static void soc_init_card_debugfs(struct snd_soc_card *card)
snd_soc_debugfs_root);
if (!card->debugfs_card_root) {
dev_warn(card->dev,
- "ASoC: Failed to create codec debugfs directory\n");
+ "ASoC: Failed to create card debugfs directory\n");
return;
}
@@ -442,6 +454,14 @@ static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
{
}
+static inline void soc_init_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
+static inline void soc_cleanup_platform_debugfs(struct snd_soc_platform *platform)
+{
+}
+
static inline void soc_init_card_debugfs(struct snd_soc_card *card)
{
}
@@ -553,18 +573,20 @@ int snd_soc_suspend(struct device *dev)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+ struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
- if (driver->playback.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_SUSPEND);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_PLAYBACK,
+ codec_dai,
+ SND_SOC_DAPM_STREAM_SUSPEND);
- if (driver->capture.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_SUSPEND);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_CAPTURE,
+ codec_dai,
+ SND_SOC_DAPM_STREAM_SUSPEND);
}
/* suspend all CODECs */
@@ -574,8 +596,19 @@ int snd_soc_suspend(struct device *dev)
if (!codec->suspended && codec->driver->suspend) {
switch (codec->dapm.bias_level) {
case SND_SOC_BIAS_STANDBY:
+ /*
+ * If the CODEC is capable of idle
+ * bias off then being in STANDBY
+ * means it's doing something,
+ * otherwise fall through.
+ */
+ if (codec->dapm.idle_bias_off) {
+ dev_dbg(codec->dev,
+ "idle_bias_off CODEC on over suspend\n");
+ break;
+ }
case SND_SOC_BIAS_OFF:
- codec->driver->suspend(codec, PMSG_SUSPEND);
+ codec->driver->suspend(codec);
codec->suspended = 1;
codec->cache_sync = 1;
break;
@@ -656,18 +689,18 @@ static void soc_resume_deferred(struct work_struct *work)
}
for (i = 0; i < card->num_rtd; i++) {
- struct snd_soc_dai_driver *driver = card->rtd[i].codec_dai->driver;
+ struct snd_soc_dai *codec_dai = card->rtd[i].codec_dai;
if (card->rtd[i].dai_link->ignore_suspend)
continue;
- if (driver->playback.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_RESUME);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_PLAYBACK, codec_dai,
+ SND_SOC_DAPM_STREAM_RESUME);
- if (driver->capture.stream_name != NULL)
- snd_soc_dapm_stream_event(&card->rtd[i], driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_RESUME);
+ snd_soc_dapm_stream_event(&card->rtd[i],
+ SNDRV_PCM_STREAM_CAPTURE, codec_dai,
+ SND_SOC_DAPM_STREAM_RESUME);
}
/* unmute any active DACs */
@@ -712,6 +745,12 @@ int snd_soc_resume(struct device *dev)
struct snd_soc_card *card = dev_get_drvdata(dev);
int i, ac97_control = 0;
+ /* If the initialization of this soc device failed, there is no codec
+ * associated with it. Just bail out in this case.
+ */
+ if (list_empty(&card->codec_dev_list))
+ return 0;
+
/* AC97 devices might have other drivers hanging off them so
* need to resume immediately. Other drivers don't have that
* problem and may take a substantial amount of time to resume
@@ -738,7 +777,7 @@ EXPORT_SYMBOL_GPL(snd_soc_resume);
#define snd_soc_resume NULL
#endif
-static struct snd_soc_dai_ops null_dai_ops = {
+static const struct snd_soc_dai_ops null_dai_ops = {
};
static int soc_bind_dai_link(struct snd_soc_card *card, int num)
@@ -760,10 +799,16 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num)
}
/* no, then find CPU DAI from registered DAIs*/
list_for_each_entry(cpu_dai, &dai_list, list) {
- if (!strcmp(cpu_dai->name, dai_link->cpu_dai_name)) {
- rtd->cpu_dai = cpu_dai;
- goto find_codec;
+ if (dai_link->cpu_dai_of_node) {
+ if (cpu_dai->dev->of_node != dai_link->cpu_dai_of_node)
+ continue;
+ } else {
+ if (strcmp(cpu_dai->name, dai_link->cpu_dai_name))
+ continue;
}
+
+ rtd->cpu_dai = cpu_dai;
+ goto find_codec;
}
dev_dbg(card->dev, "CPU DAI %s not registered\n",
dai_link->cpu_dai_name);
@@ -776,22 +821,33 @@ find_codec:
/* no, then find CODEC from registered CODECs*/
list_for_each_entry(codec, &codec_list, list) {
- if (!strcmp(codec->name, dai_link->codec_name)) {
- rtd->codec = codec;
-
- /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/
- list_for_each_entry(codec_dai, &dai_list, list) {
- if (codec->dev == codec_dai->dev &&
- !strcmp(codec_dai->name, dai_link->codec_dai_name)) {
- rtd->codec_dai = codec_dai;
- goto find_platform;
- }
- }
- dev_dbg(card->dev, "CODEC DAI %s not registered\n",
- dai_link->codec_dai_name);
+ if (dai_link->codec_of_node) {
+ if (codec->dev->of_node != dai_link->codec_of_node)
+ continue;
+ } else {
+ if (strcmp(codec->name, dai_link->codec_name))
+ continue;
+ }
- goto find_platform;
+ rtd->codec = codec;
+
+ /*
+ * CODEC found, so find CODEC DAI from registered DAIs from
+ * this CODEC
+ */
+ list_for_each_entry(codec_dai, &dai_list, list) {
+ if (codec->dev == codec_dai->dev &&
+ !strcmp(codec_dai->name,
+ dai_link->codec_dai_name)) {
+
+ rtd->codec_dai = codec_dai;
+ goto find_platform;
+ }
}
+ dev_dbg(card->dev, "CODEC DAI %s not registered\n",
+ dai_link->codec_dai_name);
+
+ goto find_platform;
}
dev_dbg(card->dev, "CODEC %s not registered\n",
dai_link->codec_name);
@@ -803,15 +859,22 @@ find_platform:
/* if there's no platform we match on the empty platform */
platform_name = dai_link->platform_name;
- if (!platform_name)
+ if (!platform_name && !dai_link->platform_of_node)
platform_name = "snd-soc-dummy";
/* no, then find one from the set of registered platforms */
list_for_each_entry(platform, &platform_list, list) {
- if (!strcmp(platform->name, platform_name)) {
- rtd->platform = platform;
- goto out;
+ if (dai_link->platform_of_node) {
+ if (platform->dev->of_node !=
+ dai_link->platform_of_node)
+ continue;
+ } else {
+ if (strcmp(platform->name, platform_name))
+ continue;
}
+
+ rtd->platform = platform;
+ goto out;
}
dev_dbg(card->dev, "platform %s not registered\n",
@@ -858,9 +921,9 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
/* unregister the rtd device */
if (rtd->dev_registered) {
- device_remove_file(&rtd->dev, &dev_attr_pmdown_time);
- device_remove_file(&rtd->dev, &dev_attr_codec_reg);
- device_unregister(&rtd->dev);
+ device_remove_file(rtd->dev, &dev_attr_pmdown_time);
+ device_remove_file(rtd->dev, &dev_attr_codec_reg);
+ device_unregister(rtd->dev);
rtd->dev_registered = 0;
}
@@ -870,7 +933,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
if (codec_dai->driver->remove) {
err = codec_dai->driver->remove(codec_dai);
if (err < 0)
- printk(KERN_ERR "asoc: failed to remove %s\n", codec_dai->name);
+ pr_err("asoc: failed to remove %s: %d\n",
+ codec_dai->name, err);
}
codec_dai->probed = 0;
list_del(&codec_dai->card_list);
@@ -882,8 +946,14 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
if (platform->driver->remove) {
err = platform->driver->remove(platform);
if (err < 0)
- printk(KERN_ERR "asoc: failed to remove %s\n", platform->name);
+ pr_err("asoc: failed to remove %s: %d\n",
+ platform->name, err);
}
+
+ /* Make sure all DAPM widgets are freed */
+ snd_soc_dapm_free(&platform->dapm);
+
+ soc_cleanup_platform_debugfs(platform);
platform->probed = 0;
list_del(&platform->card_list);
module_put(platform->dev->driver->owner);
@@ -900,7 +970,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
if (cpu_dai->driver->remove) {
err = cpu_dai->driver->remove(cpu_dai);
if (err < 0)
- printk(KERN_ERR "asoc: failed to remove %s\n", cpu_dai->name);
+ pr_err("asoc: failed to remove %s: %d\n",
+ cpu_dai->name, err);
}
cpu_dai->probed = 0;
list_del(&cpu_dai->card_list);
@@ -942,6 +1013,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
{
int ret = 0;
const struct snd_soc_codec_driver *driver = codec->driver;
+ struct snd_soc_dai *dai;
codec->card = card;
codec->dapm.card = card;
@@ -956,6 +1028,16 @@ static int soc_probe_codec(struct snd_soc_card *card,
snd_soc_dapm_new_controls(&codec->dapm, driver->dapm_widgets,
driver->num_dapm_widgets);
+ /* Create DAPM widgets for each DAI stream */
+ list_for_each_entry(dai, &dai_list, list) {
+ if (dai->dev != codec->dev)
+ continue;
+
+ snd_soc_dapm_new_dai_widgets(&codec->dapm, dai);
+ }
+
+ codec->dapm.idle_bias_off = driver->idle_bias_off;
+
if (driver->probe) {
ret = driver->probe(codec);
if (ret < 0) {
@@ -967,7 +1049,7 @@ static int soc_probe_codec(struct snd_soc_card *card,
}
if (driver->controls)
- snd_soc_add_controls(codec, driver->controls,
+ snd_soc_add_codec_controls(codec, driver->controls,
driver->num_controls);
if (driver->dapm_routes)
snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes,
@@ -999,6 +1081,8 @@ static int soc_probe_platform(struct snd_soc_card *card,
if (!try_module_get(platform->dev->driver->owner))
return -ENODEV;
+ soc_init_platform_debugfs(platform);
+
if (driver->dapm_widgets)
snd_soc_dapm_new_controls(&platform->dapm,
driver->dapm_widgets, driver->num_dapm_widgets);
@@ -1028,12 +1112,16 @@ static int soc_probe_platform(struct snd_soc_card *card,
return 0;
err_probe:
+ soc_cleanup_platform_debugfs(platform);
module_put(platform->dev->driver->owner);
return ret;
}
-static void rtd_release(struct device *dev) {}
+static void rtd_release(struct device *dev)
+{
+ kfree(dev);
+}
static int soc_post_component_init(struct snd_soc_card *card,
struct snd_soc_codec *codec,
@@ -1056,6 +1144,9 @@ static int soc_post_component_init(struct snd_soc_card *card,
}
rtd->card = card;
+ /* Make sure all DAPM widgets are instantiated */
+ snd_soc_dapm_new_widgets(&codec->dapm);
+
/* machine controls, routes and widgets are not prefixed */
temp = codec->name_prefix;
codec->name_prefix = NULL;
@@ -1071,16 +1162,19 @@ static int soc_post_component_init(struct snd_soc_card *card,
}
codec->name_prefix = temp;
- /* Make sure all DAPM widgets are instantiated */
- snd_soc_dapm_new_widgets(&codec->dapm);
-
/* register the rtd device */
rtd->codec = codec;
- rtd->dev.parent = card->dev;
- rtd->dev.release = rtd_release;
- rtd->dev.init_name = name;
+
+ rtd->dev = kzalloc(sizeof(struct device), GFP_KERNEL);
+ if (!rtd->dev)
+ return -ENOMEM;
+ device_initialize(rtd->dev);
+ rtd->dev->parent = card->dev;
+ rtd->dev->release = rtd_release;
+ rtd->dev->init_name = name;
+ dev_set_drvdata(rtd->dev, rtd);
mutex_init(&rtd->pcm_mutex);
- ret = device_register(&rtd->dev);
+ ret = device_add(rtd->dev);
if (ret < 0) {
dev_err(card->dev,
"asoc: failed to register runtime device: %d\n", ret);
@@ -1089,14 +1183,14 @@ static int soc_post_component_init(struct snd_soc_card *card,
rtd->dev_registered = 1;
/* add DAPM sysfs entries for this codec */
- ret = snd_soc_dapm_sys_add(&rtd->dev);
+ ret = snd_soc_dapm_sys_add(rtd->dev);
if (ret < 0)
dev_err(codec->dev,
"asoc: failed to add codec dapm sysfs entries: %d\n",
ret);
/* add codec sysfs entries */
- ret = device_create_file(&rtd->dev, &dev_attr_codec_reg);
+ ret = device_create_file(rtd->dev, &dev_attr_codec_reg);
if (ret < 0)
dev_err(codec->dev,
"asoc: failed to add codec sysfs files: %d\n", ret);
@@ -1134,8 +1228,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
if (cpu_dai->driver->probe) {
ret = cpu_dai->driver->probe(cpu_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to probe CPU DAI %s\n",
- cpu_dai->name);
+ pr_err("asoc: failed to probe CPU DAI %s: %d\n",
+ cpu_dai->name, ret);
module_put(cpu_dai->dev->driver->owner);
return ret;
}
@@ -1166,8 +1260,8 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
if (codec_dai->driver->probe) {
ret = codec_dai->driver->probe(codec_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to probe CODEC DAI %s\n",
- codec_dai->name);
+ pr_err("asoc: failed to probe CODEC DAI %s: %d\n",
+ codec_dai->name, ret);
return ret;
}
}
@@ -1185,14 +1279,15 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
if (ret)
return ret;
- ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time);
+ ret = device_create_file(rtd->dev, &dev_attr_pmdown_time);
if (ret < 0)
- printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n");
+ pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret);
/* create the pcm */
ret = soc_new_pcm(rtd, num);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't create pcm %s\n", dai_link->stream_name);
+ pr_err("asoc: can't create pcm %s :%d\n",
+ dai_link->stream_name, ret);
return ret;
}
@@ -1225,7 +1320,7 @@ static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd)
ret = soc_ac97_dev_register(rtd->codec);
if (ret < 0) {
- printk(KERN_ERR "asoc: AC97 device register failed\n");
+ pr_err("asoc: AC97 device register failed:%d\n", ret);
return ret;
}
@@ -1283,8 +1378,8 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num)
/* unregister the rtd device */
if (rtd->dev_registered) {
- device_remove_file(&rtd->dev, &dev_attr_codec_reg);
- device_unregister(&rtd->dev);
+ device_remove_file(rtd->dev, &dev_attr_codec_reg);
+ device_del(rtd->dev);
rtd->dev_registered = 0;
}
@@ -1318,6 +1413,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
struct snd_soc_codec *codec;
struct snd_soc_codec_conf *codec_conf;
enum snd_soc_compress_type compress_type;
+ struct snd_soc_dai_link *dai_link;
int ret, i, order;
mutex_lock(&card->mutex);
@@ -1364,8 +1460,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
card->owner, 0, &card->snd_card);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't create sound card for card %s\n",
- card->name);
+ pr_err("asoc: can't create sound card for card %s: %d\n",
+ card->name, ret);
mutex_unlock(&card->mutex);
return;
}
@@ -1418,25 +1514,55 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
- /* We should have a non-codec control add function but we don't */
+ snd_soc_dapm_link_dai_widgets(card);
+
if (card->controls)
- snd_soc_add_controls(list_first_entry(&card->codec_dev_list,
- struct snd_soc_codec,
- card_list),
- card->controls,
- card->num_controls);
+ snd_soc_add_card_controls(card, card->controls, card->num_controls);
if (card->dapm_routes)
snd_soc_dapm_add_routes(&card->dapm, card->dapm_routes,
card->num_dapm_routes);
+ snd_soc_dapm_new_widgets(&card->dapm);
+
+ for (i = 0; i < card->num_links; i++) {
+ dai_link = &card->dai_link[i];
+
+ if (dai_link->dai_fmt) {
+ ret = snd_soc_dai_set_fmt(card->rtd[i].codec_dai,
+ dai_link->dai_fmt);
+ if (ret != 0 && ret != -ENOTSUPP)
+ dev_warn(card->rtd[i].codec_dai->dev,
+ "Failed to set DAI format: %d\n",
+ ret);
+
+ ret = snd_soc_dai_set_fmt(card->rtd[i].cpu_dai,
+ dai_link->dai_fmt);
+ if (ret != 0 && ret != -ENOTSUPP)
+ dev_warn(card->rtd[i].cpu_dai->dev,
+ "Failed to set DAI format: %d\n",
+ ret);
+ }
+ }
+
snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname),
"%s", card->name);
snprintf(card->snd_card->longname, sizeof(card->snd_card->longname),
"%s", card->long_name ? card->long_name : card->name);
- if (card->driver_name)
- strlcpy(card->snd_card->driver, card->driver_name,
- sizeof(card->snd_card->driver));
+ snprintf(card->snd_card->driver, sizeof(card->snd_card->driver),
+ "%s", card->driver_name ? card->driver_name : card->name);
+ for (i = 0; i < ARRAY_SIZE(card->snd_card->driver); i++) {
+ switch (card->snd_card->driver[i]) {
+ case '_':
+ case '-':
+ case '\0':
+ break;
+ default:
+ if (!isalnum(card->snd_card->driver[i]))
+ card->snd_card->driver[i] = '_';
+ break;
+ }
+ }
if (card->late_probe) {
ret = card->late_probe(card);
@@ -1447,9 +1573,16 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
}
}
+ snd_soc_dapm_new_widgets(&card->dapm);
+
+ if (card->fully_routed)
+ list_for_each_entry(codec, &card->codec_dev_list, card_list)
+ snd_soc_dapm_auto_nc_codec_pins(codec);
+
ret = snd_card_register(card->snd_card);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name);
+ pr_err("asoc: failed to register soundcard for %s: %d\n",
+ card->name, ret);
goto probe_aux_dev_err;
}
@@ -1458,7 +1591,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
for (i = 0; i < card->num_rtd; i++) {
ret = soc_register_ac97_dai_link(&card->rtd[i]);
if (ret < 0) {
- printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name);
+ pr_err("asoc: failed to register AC97 %s: %d\n",
+ card->name, ret);
while (--i >= 0)
soc_unregister_ac97_dai_link(card->rtd[i].codec);
goto probe_aux_dev_err;
@@ -1467,6 +1601,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
#endif
card->instantiated = 1;
+ snd_soc_dapm_sync(&card->dapm);
mutex_unlock(&card->mutex);
return;
@@ -1510,6 +1645,10 @@ static int soc_probe(struct platform_device *pdev)
if (!card)
return -EINVAL;
+ dev_warn(&pdev->dev,
+ "ASoC machine %s should use snd_soc_register_card()\n",
+ card->name);
+
/* Bodge while we unpick instantiation */
card->dev = &pdev->dev;
@@ -1547,7 +1686,6 @@ static int soc_cleanup_card_resources(struct snd_soc_card *card)
snd_soc_dapm_free(&card->dapm);
- kfree(card->rtd);
snd_card_free(card->snd_card);
return 0;
@@ -1586,7 +1724,10 @@ EXPORT_SYMBOL_GPL(snd_soc_poweroff);
const struct dev_pm_ops snd_soc_pm_ops = {
.suspend = snd_soc_suspend,
.resume = snd_soc_resume,
+ .freeze = snd_soc_suspend,
+ .thaw = snd_soc_resume,
.poweroff = snd_soc_poweroff,
+ .restore = snd_soc_resume,
};
EXPORT_SYMBOL_GPL(snd_soc_pm_ops);
@@ -1633,7 +1774,7 @@ int snd_soc_codec_readable_register(struct snd_soc_codec *codec,
if (codec->readable_register)
return codec->readable_register(codec, reg);
else
- return 0;
+ return 1;
}
EXPORT_SYMBOL_GPL(snd_soc_codec_readable_register);
@@ -1651,7 +1792,7 @@ int snd_soc_codec_writable_register(struct snd_soc_codec *codec,
if (codec->writable_register)
return codec->writable_register(codec, reg);
else
- return 0;
+ return 1;
}
EXPORT_SYMBOL_GPL(snd_soc_codec_writable_register);
@@ -1790,23 +1931,28 @@ EXPORT_SYMBOL_GPL(snd_soc_bulk_write_raw);
int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
unsigned int mask, unsigned int value)
{
- int change;
+ bool change;
unsigned int old, new;
int ret;
- ret = snd_soc_read(codec, reg);
- if (ret < 0)
- return ret;
-
- old = ret;
- new = (old & ~mask) | (value & mask);
- change = old != new;
- if (change) {
- ret = snd_soc_write(codec, reg, new);
+ if (codec->using_regmap) {
+ ret = regmap_update_bits_check(codec->control_data, reg,
+ mask, value, &change);
+ } else {
+ ret = snd_soc_read(codec, reg);
if (ret < 0)
return ret;
+
+ old = ret;
+ new = (old & ~mask) | (value & mask);
+ change = old != new;
+ if (change)
+ ret = snd_soc_write(codec, reg, new);
}
+ if (ret < 0)
+ return ret;
+
return change;
}
EXPORT_SYMBOL_GPL(snd_soc_update_bits);
@@ -1897,7 +2043,7 @@ EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
* Returns 0 for success, else error.
*/
struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
- void *data, char *long_name,
+ void *data, const char *long_name,
const char *prefix)
{
struct snd_kcontrol_new template;
@@ -1932,9 +2078,28 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
}
EXPORT_SYMBOL_GPL(snd_soc_cnew);
+static int snd_soc_add_controls(struct snd_card *card, struct device *dev,
+ const struct snd_kcontrol_new *controls, int num_controls,
+ const char *prefix, void *data)
+{
+ int err, i;
+
+ for (i = 0; i < num_controls; i++) {
+ const struct snd_kcontrol_new *control = &controls[i];
+ err = snd_ctl_add(card, snd_soc_cnew(control, data,
+ control->name, prefix));
+ if (err < 0) {
+ dev_err(dev, "Failed to add %s: %d\n", control->name, err);
+ return err;
+ }
+ }
+
+ return 0;
+}
+
/**
- * snd_soc_add_controls - add an array of controls to a codec.
- * Convienience function to add a list of controls. Many codecs were
+ * snd_soc_add_codec_controls - add an array of controls to a codec.
+ * Convenience function to add a list of controls. Many codecs were
* duplicating this code.
*
* @codec: codec to add controls to
@@ -1943,31 +2108,19 @@ EXPORT_SYMBOL_GPL(snd_soc_cnew);
*
* Return 0 for success, else error.
*/
-int snd_soc_add_controls(struct snd_soc_codec *codec,
+int snd_soc_add_codec_controls(struct snd_soc_codec *codec,
const struct snd_kcontrol_new *controls, int num_controls)
{
struct snd_card *card = codec->card->snd_card;
- int err, i;
- for (i = 0; i < num_controls; i++) {
- const struct snd_kcontrol_new *control = &controls[i];
- err = snd_ctl_add(card, snd_soc_cnew(control, codec,
- control->name,
- codec->name_prefix));
- if (err < 0) {
- dev_err(codec->dev, "%s: Failed to add %s: %d\n",
- codec->name, control->name, err);
- return err;
- }
- }
-
- return 0;
+ return snd_soc_add_controls(card, codec->dev, controls, num_controls,
+ codec->name_prefix, codec);
}
-EXPORT_SYMBOL_GPL(snd_soc_add_controls);
+EXPORT_SYMBOL_GPL(snd_soc_add_codec_controls);
/**
* snd_soc_add_platform_controls - add an array of controls to a platform.
- * Convienience function to add a list of controls.
+ * Convenience function to add a list of controls.
*
* @platform: platform to add controls to
* @controls: array of controls to add
@@ -1979,23 +2132,53 @@ int snd_soc_add_platform_controls(struct snd_soc_platform *platform,
const struct snd_kcontrol_new *controls, int num_controls)
{
struct snd_card *card = platform->card->snd_card;
- int err, i;
-
- for (i = 0; i < num_controls; i++) {
- const struct snd_kcontrol_new *control = &controls[i];
- err = snd_ctl_add(card, snd_soc_cnew(control, platform,
- control->name, NULL));
- if (err < 0) {
- dev_err(platform->dev, "Failed to add %s %d\n",control->name, err);
- return err;
- }
- }
- return 0;
+ return snd_soc_add_controls(card, platform->dev, controls, num_controls,
+ NULL, platform);
}
EXPORT_SYMBOL_GPL(snd_soc_add_platform_controls);
/**
+ * snd_soc_add_card_controls - add an array of controls to a SoC card.
+ * Convenience function to add a list of controls.
+ *
+ * @soc_card: SoC card to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_card_controls(struct snd_soc_card *soc_card,
+ const struct snd_kcontrol_new *controls, int num_controls)
+{
+ struct snd_card *card = soc_card->snd_card;
+
+ return snd_soc_add_controls(card, soc_card->dev, controls, num_controls,
+ NULL, soc_card);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_card_controls);
+
+/**
+ * snd_soc_add_dai_controls - add an array of controls to a DAI.
+ * Convienience function to add a list of controls.
+ *
+ * @dai: DAI to add controls to
+ * @controls: array of controls to add
+ * @num_controls: number of elements in the array
+ *
+ * Return 0 for success, else error.
+ */
+int snd_soc_add_dai_controls(struct snd_soc_dai *dai,
+ const struct snd_kcontrol_new *controls, int num_controls)
+{
+ struct snd_card *card = dai->card->snd_card;
+
+ return snd_soc_add_controls(card, dai->dev, controls, num_controls,
+ NULL, dai);
+}
+EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
+
+/**
* snd_soc_info_enum_double - enumerated double mixer info callback
* @kcontrol: mixer control
* @uinfo: control element information
@@ -2217,7 +2400,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
* @kcontrol: mixer control
* @uinfo: control element information
*
- * Callback to provide information about a single mixer control.
+ * Callback to provide information about a single mixer control, or a double
+ * mixer control that spans 2 registers.
*
* Returns 0 for success.
*/
@@ -2227,8 +2411,6 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
int platform_max;
- unsigned int shift = mc->shift;
- unsigned int rshift = mc->rshift;
if (!mc->platform_max)
mc->platform_max = mc->max;
@@ -2239,7 +2421,7 @@ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
else
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = shift == rshift ? 1 : 2;
+ uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
uinfo->value.integer.min = 0;
uinfo->value.integer.max = platform_max;
return 0;
@@ -2251,7 +2433,8 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
* @kcontrol: mixer control
* @ucontrol: control element information
*
- * Callback to get the value of a single mixer control.
+ * Callback to get the value of a single mixer control, or a double mixer
+ * control that spans 2 registers.
*
* Returns 0 for success.
*/
@@ -2262,6 +2445,7 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
unsigned int shift = mc->shift;
unsigned int rshift = mc->rshift;
int max = mc->max;
@@ -2270,13 +2454,18 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
ucontrol->value.integer.value[0] =
(snd_soc_read(codec, reg) >> shift) & mask;
- if (shift != rshift)
- ucontrol->value.integer.value[1] =
- (snd_soc_read(codec, reg) >> rshift) & mask;
- if (invert) {
+ if (invert)
ucontrol->value.integer.value[0] =
max - ucontrol->value.integer.value[0];
- if (shift != rshift)
+
+ if (snd_soc_volsw_is_stereo(mc)) {
+ if (reg == reg2)
+ ucontrol->value.integer.value[1] =
+ (snd_soc_read(codec, reg) >> rshift) & mask;
+ else
+ ucontrol->value.integer.value[1] =
+ (snd_soc_read(codec, reg2) >> shift) & mask;
+ if (invert)
ucontrol->value.integer.value[1] =
max - ucontrol->value.integer.value[1];
}
@@ -2290,7 +2479,8 @@ EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
* @kcontrol: mixer control
* @ucontrol: control element information
*
- * Callback to set the value of a single mixer control.
+ * Callback to set the value of a single mixer control, or a double mixer
+ * control that spans 2 registers.
*
* Returns 0 for success.
*/
@@ -2301,143 +2491,44 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
(struct soc_mixer_control *)kcontrol->private_value;
struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
unsigned int reg = mc->reg;
+ unsigned int reg2 = mc->rreg;
unsigned int shift = mc->shift;
unsigned int rshift = mc->rshift;
int max = mc->max;
unsigned int mask = (1 << fls(max)) - 1;
unsigned int invert = mc->invert;
- unsigned int val, val2, val_mask;
+ int err;
+ bool type_2r = 0;
+ unsigned int val2 = 0;
+ unsigned int val, val_mask;
val = (ucontrol->value.integer.value[0] & mask);
if (invert)
val = max - val;
val_mask = mask << shift;
val = val << shift;
- if (shift != rshift) {
+ if (snd_soc_volsw_is_stereo(mc)) {
val2 = (ucontrol->value.integer.value[1] & mask);
if (invert)
val2 = max - val2;
- val_mask |= mask << rshift;
- val |= val2 << rshift;
- }
- return snd_soc_update_bits_locked(codec, reg, val_mask, val);
-}
-EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
-
-/**
- * snd_soc_info_volsw_2r - double mixer info callback
- * @kcontrol: mixer control
- * @uinfo: control element information
- *
- * Callback to provide information about a double mixer control that
- * spans 2 codec registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- int platform_max;
-
- if (!mc->platform_max)
- mc->platform_max = mc->max;
- platform_max = mc->platform_max;
-
- if (platform_max == 1 && !strstr(kcontrol->id.name, " Volume"))
- uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
- else
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-
- uinfo->count = 2;
- uinfo->value.integer.min = 0;
- uinfo->value.integer.max = platform_max;
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
-
-/**
- * snd_soc_get_volsw_2r - double mixer get callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to get the value of a double mixer control that spans 2 registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_get_volsw_2r(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_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int reg = mc->reg;
- unsigned int reg2 = mc->rreg;
- unsigned int shift = mc->shift;
- int max = mc->max;
- unsigned int mask = (1 << fls(max)) - 1;
- unsigned int invert = mc->invert;
-
- ucontrol->value.integer.value[0] =
- (snd_soc_read(codec, reg) >> shift) & mask;
- ucontrol->value.integer.value[1] =
- (snd_soc_read(codec, reg2) >> shift) & mask;
- if (invert) {
- ucontrol->value.integer.value[0] =
- max - ucontrol->value.integer.value[0];
- ucontrol->value.integer.value[1] =
- max - ucontrol->value.integer.value[1];
- }
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
-
-/**
- * snd_soc_put_volsw_2r - double mixer set callback
- * @kcontrol: mixer control
- * @ucontrol: control element information
- *
- * Callback to set the value of a double mixer control that spans 2 registers.
- *
- * Returns 0 for success.
- */
-int snd_soc_put_volsw_2r(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_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int reg = mc->reg;
- unsigned int reg2 = mc->rreg;
- unsigned int shift = mc->shift;
- int max = mc->max;
- unsigned int mask = (1 << fls(max)) - 1;
- unsigned int invert = mc->invert;
- int err;
- unsigned int val, val2, val_mask;
-
- val_mask = mask << shift;
- val = (ucontrol->value.integer.value[0] & mask);
- val2 = (ucontrol->value.integer.value[1] & mask);
-
- if (invert) {
- val = max - val;
- val2 = max - val2;
+ if (reg == reg2) {
+ val_mask |= mask << rshift;
+ val |= val2 << rshift;
+ } else {
+ val2 = val2 << shift;
+ type_2r = 1;
+ }
}
-
- val = val << shift;
- val2 = val2 << shift;
-
err = snd_soc_update_bits_locked(codec, reg, val_mask, val);
if (err < 0)
return err;
- err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
+ if (type_2r)
+ err = snd_soc_update_bits_locked(codec, reg2, val_mask, val2);
+
return err;
}
-EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
+EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
/**
* snd_soc_info_volsw_s8 - signed mixer info callback
@@ -2653,6 +2744,115 @@ int snd_soc_put_volsw_2r_sx(struct snd_kcontrol *kcontrol,
}
EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r_sx);
+int snd_soc_bytes_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES;
+ uinfo->count = params->num_regs * codec->val_bytes;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_info);
+
+int snd_soc_bytes_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int ret;
+
+ if (codec->using_regmap)
+ ret = regmap_raw_read(codec->control_data, params->base,
+ ucontrol->value.bytes.data,
+ params->num_regs * codec->val_bytes);
+ else
+ ret = -EINVAL;
+
+ /* Hide any masked bytes to ensure consistent data reporting */
+ if (ret == 0 && params->mask) {
+ switch (codec->val_bytes) {
+ case 1:
+ ucontrol->value.bytes.data[0] &= ~params->mask;
+ break;
+ case 2:
+ ((u16 *)(&ucontrol->value.bytes.data))[0]
+ &= ~params->mask;
+ break;
+ case 4:
+ ((u32 *)(&ucontrol->value.bytes.data))[0]
+ &= ~params->mask;
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_get);
+
+int snd_soc_bytes_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct soc_bytes *params = (void *)kcontrol->private_value;
+ struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ int ret, len;
+ unsigned int val;
+ void *data;
+
+ if (!codec->using_regmap)
+ return -EINVAL;
+
+ data = ucontrol->value.bytes.data;
+ len = params->num_regs * codec->val_bytes;
+
+ /*
+ * If we've got a mask then we need to preserve the register
+ * bits. We shouldn't modify the incoming data so take a
+ * copy.
+ */
+ if (params->mask) {
+ ret = regmap_read(codec->control_data, params->base, &val);
+ if (ret != 0)
+ return ret;
+
+ val &= params->mask;
+
+ data = kmemdup(data, len, GFP_KERNEL);
+ if (!data)
+ return -ENOMEM;
+
+ switch (codec->val_bytes) {
+ case 1:
+ ((u8 *)data)[0] &= ~params->mask;
+ ((u8 *)data)[0] |= val;
+ break;
+ case 2:
+ ((u16 *)data)[0] &= cpu_to_be16(~params->mask);
+ ((u16 *)data)[0] |= cpu_to_be16(val);
+ break;
+ case 4:
+ ((u32 *)data)[0] &= cpu_to_be32(~params->mask);
+ ((u32 *)data)[0] |= cpu_to_be32(val);
+ break;
+ default:
+ return -EINVAL;
+ }
+ }
+
+ ret = regmap_raw_write(codec->control_data, params->base,
+ data, len);
+
+ if (params->mask)
+ kfree(data);
+
+ return ret;
+}
+EXPORT_SYMBOL_GPL(snd_soc_bytes_put);
+
/**
* snd_soc_dai_set_sysclk - configure DAI system or master clock.
* @dai: DAI
@@ -2668,7 +2868,7 @@ int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
if (dai->driver && dai->driver->ops->set_sysclk)
return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
else if (dai->codec && dai->codec->driver->set_sysclk)
- return dai->codec->driver->set_sysclk(dai->codec, clk_id,
+ return dai->codec->driver->set_sysclk(dai->codec, clk_id, 0,
freq, dir);
else
return -EINVAL;
@@ -2679,16 +2879,18 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
* snd_soc_codec_set_sysclk - configure CODEC system or master clock.
* @codec: CODEC
* @clk_id: DAI specific clock ID
+ * @source: Source for the clock
* @freq: new clock frequency in Hz
* @dir: new clock direction - input/output.
*
* Configures the CODEC master (MCLK) or system (SYSCLK) clocking.
*/
int snd_soc_codec_set_sysclk(struct snd_soc_codec *codec, int clk_id,
- unsigned int freq, int dir)
+ int source, unsigned int freq, int dir)
{
if (codec->driver->set_sysclk)
- return codec->driver->set_sysclk(codec, clk_id, freq, dir);
+ return codec->driver->set_sysclk(codec, clk_id, source,
+ freq, dir);
else
return -EINVAL;
}
@@ -2768,10 +2970,11 @@ EXPORT_SYMBOL_GPL(snd_soc_codec_set_pll);
*/
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
- if (dai->driver && dai->driver->ops->set_fmt)
- return dai->driver->ops->set_fmt(dai, fmt);
- else
+ if (dai->driver == NULL)
return -EINVAL;
+ if (dai->driver->ops->set_fmt == NULL)
+ return -ENOTSUPP;
+ return dai->driver->ops->set_fmt(dai, fmt);
}
EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
@@ -2866,15 +3069,52 @@ int snd_soc_register_card(struct snd_soc_card *card)
if (!card->name || !card->dev)
return -EINVAL;
+ for (i = 0; i < card->num_links; i++) {
+ struct snd_soc_dai_link *link = &card->dai_link[i];
+
+ /*
+ * Codec must be specified by 1 of name or OF node,
+ * not both or neither.
+ */
+ if (!!link->codec_name == !!link->codec_of_node) {
+ dev_err(card->dev,
+ "Neither/both codec name/of_node are set for %s\n",
+ link->name);
+ return -EINVAL;
+ }
+
+ /*
+ * Platform may be specified by either name or OF node, but
+ * can be left unspecified, and a dummy platform will be used.
+ */
+ if (link->platform_name && link->platform_of_node) {
+ dev_err(card->dev,
+ "Both platform name/of_node are set for %s\n", link->name);
+ return -EINVAL;
+ }
+
+ /*
+ * CPU DAI must be specified by 1 of name or OF node,
+ * not both or neither.
+ */
+ if (!!link->cpu_dai_name == !!link->cpu_dai_of_node) {
+ dev_err(card->dev,
+ "Neither/both cpu_dai name/of_node are set for %s\n",
+ link->name);
+ return -EINVAL;
+ }
+ }
+
dev_set_drvdata(card->dev, card);
snd_soc_initialize_card_lists(card);
soc_init_card_debugfs(card);
- card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) *
- (card->num_links + card->num_aux_devs),
- GFP_KERNEL);
+ card->rtd = devm_kzalloc(card->dev,
+ sizeof(struct snd_soc_pcm_runtime) *
+ (card->num_links + card->num_aux_devs),
+ GFP_KERNEL);
if (card->rtd == NULL)
return -ENOMEM;
card->rtd_aux = &card->rtd[card->num_links];
@@ -2883,6 +3123,7 @@ int snd_soc_register_card(struct snd_soc_card *card)
card->rtd[i].dai_link = &card->dai_link[i];
INIT_LIST_HEAD(&card->list);
+ INIT_LIST_HEAD(&card->dapm_dirty);
card->instantiated = 0;
mutex_init(&card->mutex);
@@ -2967,7 +3208,7 @@ static inline char *fmt_multiple_name(struct device *dev,
struct snd_soc_dai_driver *dai_drv)
{
if (dai_drv->name == NULL) {
- printk(KERN_ERR "asoc: error - multiple DAI %s registered with no name\n",
+ pr_err("asoc: error - multiple DAI %s registered with no name\n",
dev_name(dev));
return NULL;
}
@@ -3141,6 +3382,8 @@ int snd_soc_register_platform(struct device *dev,
platform->driver = platform_drv;
platform->dapm.dev = dev;
platform->dapm.platform = platform;
+ platform->dapm.stream_event = platform_drv->stream_event;
+ mutex_init(&platform->mutex);
mutex_lock(&client_mutex);
list_add(&platform->list, &platform_list);
@@ -3249,10 +3492,12 @@ int snd_soc_register_codec(struct device *dev,
codec->volatile_register = codec_drv->volatile_register;
codec->readable_register = codec_drv->readable_register;
codec->writable_register = codec_drv->writable_register;
+ codec->ignore_pmdown_time = codec_drv->ignore_pmdown_time;
codec->dapm.bias_level = SND_SOC_BIAS_OFF;
codec->dapm.dev = dev;
codec->dapm.codec = codec;
codec->dapm.seq_notifier = codec_drv->seq_notifier;
+ codec->dapm.stream_event = codec_drv->stream_event;
codec->dev = dev;
codec->driver = codec_drv;
codec->num_dai = num_dai;
@@ -3350,13 +3595,93 @@ found:
}
EXPORT_SYMBOL_GPL(snd_soc_unregister_codec);
+/* Retrieve a card's name from device tree */
+int snd_soc_of_parse_card_name(struct snd_soc_card *card,
+ const char *propname)
+{
+ struct device_node *np = card->dev->of_node;
+ int ret;
+
+ ret = of_property_read_string_index(np, propname, 0, &card->name);
+ /*
+ * EINVAL means the property does not exist. This is fine providing
+ * card->name was previously set, which is checked later in
+ * snd_soc_register_card.
+ */
+ if (ret < 0 && ret != -EINVAL) {
+ dev_err(card->dev,
+ "Property '%s' could not be read: %d\n",
+ propname, ret);
+ return ret;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_card_name);
+
+int snd_soc_of_parse_audio_routing(struct snd_soc_card *card,
+ const char *propname)
+{
+ struct device_node *np = card->dev->of_node;
+ int num_routes;
+ struct snd_soc_dapm_route *routes;
+ int i, ret;
+
+ num_routes = of_property_count_strings(np, propname);
+ if (num_routes & 1) {
+ dev_err(card->dev,
+ "Property '%s's length is not even\n",
+ propname);
+ return -EINVAL;
+ }
+ num_routes /= 2;
+ if (!num_routes) {
+ dev_err(card->dev,
+ "Property '%s's length is zero\n",
+ propname);
+ return -EINVAL;
+ }
+
+ routes = devm_kzalloc(card->dev, num_routes * sizeof(*routes),
+ GFP_KERNEL);
+ if (!routes) {
+ dev_err(card->dev,
+ "Could not allocate DAPM route table\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_routes; i++) {
+ ret = of_property_read_string_index(np, propname,
+ 2 * i, &routes[i].sink);
+ if (ret) {
+ dev_err(card->dev,
+ "Property '%s' index %d could not be read: %d\n",
+ propname, 2 * i, ret);
+ return -EINVAL;
+ }
+ ret = of_property_read_string_index(np, propname,
+ (2 * i) + 1, &routes[i].source);
+ if (ret) {
+ dev_err(card->dev,
+ "Property '%s' index %d could not be read: %d\n",
+ propname, (2 * i) + 1, ret);
+ return -EINVAL;
+ }
+ }
+
+ card->num_dapm_routes = num_routes;
+ card->dapm_routes = routes;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_of_parse_audio_routing);
+
static int __init snd_soc_init(void)
{
#ifdef CONFIG_DEBUG_FS
snd_soc_debugfs_root = debugfs_create_dir("asoc", NULL);
if (IS_ERR(snd_soc_debugfs_root) || !snd_soc_debugfs_root) {
- printk(KERN_WARNING
- "ASoC: Failed to create debugfs directory\n");
+ pr_warn("ASoC: Failed to create debugfs directory\n");
snd_soc_debugfs_root = NULL;
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 7e15914b3633..6241490fff30 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -14,19 +14,13 @@
* dynamic configuration of codec internal audio paths and active
* DACs/ADCs.
* o Platform power domain - can support external components i.e. amps and
- * mic/meadphone insertion events.
+ * mic/headphone insertion events.
* o Automatic Mic Bias support
* o Jack insertion power event initiation - e.g. hp insertion will enable
* sinks, dacs, etc
- * o Delayed powerdown of audio susbsystem to reduce pops between a quick
+ * o Delayed power down of audio subsystem to reduce pops between a quick
* device reopen.
*
- * Todo:
- * o DAPM power change sequencing - allow for configurable per
- * codec sequences.
- * o Support for analogue bias optimisation.
- * o Support for reduced codec oversampling rates.
- * o Support for reduced codec bias currents.
*/
#include <linux/module.h>
@@ -39,6 +33,8 @@
#include <linux/platform_device.h>
#include <linux/jiffies.h>
#include <linux/debugfs.h>
+#include <linux/pm_runtime.h>
+#include <linux/regulator/consumer.h>
#include <linux/slab.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -48,11 +44,15 @@
#include <trace/events/asoc.h>
+#define DAPM_UPDATE_STAT(widget, val) widget->dapm->card->dapm_stats.val++;
+
/* dapm power sequences - make this per codec in the future */
static int dapm_up_seq[] = {
[snd_soc_dapm_pre] = 0,
[snd_soc_dapm_supply] = 1,
+ [snd_soc_dapm_regulator_supply] = 1,
[snd_soc_dapm_micbias] = 2,
+ [snd_soc_dapm_dai] = 3,
[snd_soc_dapm_aif_in] = 3,
[snd_soc_dapm_aif_out] = 3,
[snd_soc_dapm_mic] = 4,
@@ -87,6 +87,8 @@ static int dapm_down_seq[] = {
[snd_soc_dapm_value_mux] = 9,
[snd_soc_dapm_aif_in] = 10,
[snd_soc_dapm_aif_out] = 10,
+ [snd_soc_dapm_dai] = 10,
+ [snd_soc_dapm_regulator_supply] = 11,
[snd_soc_dapm_supply] = 11,
[snd_soc_dapm_post] = 12,
};
@@ -117,6 +119,21 @@ static void pop_dbg(struct device *dev, u32 pop_time, const char *fmt, ...)
kfree(buf);
}
+static bool dapm_dirty_widget(struct snd_soc_dapm_widget *w)
+{
+ return !list_empty(&w->dirty);
+}
+
+void dapm_mark_dirty(struct snd_soc_dapm_widget *w, const char *reason)
+{
+ if (!dapm_dirty_widget(w)) {
+ dev_vdbg(w->dapm->dev, "Marking %s dirty due to %s\n",
+ w->name, reason);
+ list_add_tail(&w->dirty, &w->dapm->card->dapm_dirty);
+ }
+}
+EXPORT_SYMBOL_GPL(dapm_mark_dirty);
+
/* create a new dapm widget */
static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
const struct snd_soc_dapm_widget *_widget)
@@ -154,6 +171,19 @@ static inline struct snd_soc_card *dapm_get_soc_card(
return NULL;
}
+static void dapm_reset(struct snd_soc_card *card)
+{
+ struct snd_soc_dapm_widget *w;
+
+ memset(&card->dapm_stats, 0, sizeof(card->dapm_stats));
+
+ list_for_each_entry(w, &card->widgets, list) {
+ w->power_checked = false;
+ w->inputs = -1;
+ w->outputs = -1;
+ }
+}
+
static int soc_widget_read(struct snd_soc_dapm_widget *w, int reg)
{
if (w->codec)
@@ -179,21 +209,28 @@ static int soc_widget_write(struct snd_soc_dapm_widget *w, int reg, int val)
static int soc_widget_update_bits(struct snd_soc_dapm_widget *w,
unsigned short reg, unsigned int mask, unsigned int value)
{
- int change;
+ bool change;
unsigned int old, new;
int ret;
- ret = soc_widget_read(w, reg);
- if (ret < 0)
- return ret;
-
- old = ret;
- new = (old & ~mask) | (value & mask);
- change = old != new;
- if (change) {
- ret = soc_widget_write(w, reg, new);
+ if (w->codec && w->codec->using_regmap) {
+ ret = regmap_update_bits_check(w->codec->control_data,
+ reg, mask, value, &change);
+ if (ret != 0)
+ return ret;
+ } else {
+ ret = soc_widget_read(w, reg);
if (ret < 0)
return ret;
+
+ old = ret;
+ new = (old & ~mask) | (value & mask);
+ change = old != new;
+ if (change) {
+ ret = soc_widget_write(w, reg, new);
+ if (ret < 0)
+ return ret;
+ }
}
return change;
@@ -316,25 +353,28 @@ static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
}
}
break;
- /* does not effect routing - always connected */
+ /* does not affect routing - always connected */
case snd_soc_dapm_pga:
case snd_soc_dapm_out_drv:
case snd_soc_dapm_output:
case snd_soc_dapm_adc:
case snd_soc_dapm_input:
+ case snd_soc_dapm_siggen:
case snd_soc_dapm_dac:
case snd_soc_dapm_micbias:
case snd_soc_dapm_vmid:
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
- p->connect = 1;
- break;
- /* does effect routing - dynamically connected */
+ case snd_soc_dapm_dai:
case snd_soc_dapm_hp:
case snd_soc_dapm_mic:
case snd_soc_dapm_spk:
case snd_soc_dapm_line:
+ p->connect = 1;
+ break;
+ /* does affect routing - dynamically connected */
case snd_soc_dapm_pre:
case snd_soc_dapm_post:
p->connect = 0;
@@ -443,6 +483,11 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
if (path->name != (char *)w->kcontrol_news[i].name)
continue;
+ if (w->kcontrols[i]) {
+ path->kcontrol = w->kcontrols[i];
+ continue;
+ }
+
wlistsize = sizeof(struct snd_soc_dapm_widget_list) +
sizeof(struct snd_soc_dapm_widget *),
wlist = kzalloc(wlistsize, GFP_KERNEL);
@@ -480,17 +525,17 @@ static int dapm_new_mixer(struct snd_soc_dapm_widget *w)
* for widgets so cut the prefix off
* the front of the widget name.
*/
- snprintf(path->long_name, name_len, "%s %s",
- w->name + prefix_len,
+ snprintf((char *)path->long_name, name_len,
+ "%s %s", w->name + prefix_len,
w->kcontrol_news[i].name);
break;
case snd_soc_dapm_mixer_named_ctl:
- snprintf(path->long_name, name_len, "%s",
- w->kcontrol_news[i].name);
+ snprintf((char *)path->long_name, name_len,
+ "%s", w->kcontrol_news[i].name);
break;
}
- path->long_name[name_len - 1] = '\0';
+ ((char *)path->long_name)[name_len - 1] = '\0';
path->kcontrol = snd_soc_cnew(&w->kcontrol_news[i],
wlist, path->long_name,
@@ -524,7 +569,7 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
struct snd_soc_dapm_widget_list *wlist;
int shared, wlistentries;
size_t wlistsize;
- char *name;
+ const char *name;
if (w->num_kcontrols != 1) {
dev_err(dapm->dev,
@@ -579,8 +624,8 @@ static int dapm_new_mux(struct snd_soc_dapm_widget *w)
name + prefix_len, prefix);
ret = snd_ctl_add(card, kcontrol);
if (ret < 0) {
- dev_err(dapm->dev,
- "asoc: failed to add kcontrol %s\n", w->name);
+ dev_err(dapm->dev, "failed to add kcontrol %s: %d\n",
+ w->name, ret);
kfree(wlist);
return ret;
}
@@ -644,30 +689,51 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
struct snd_soc_dapm_path *path;
int con = 0;
- if (widget->id == snd_soc_dapm_supply)
+ if (widget->outputs >= 0)
+ return widget->outputs;
+
+ DAPM_UPDATE_STAT(widget, path_checks);
+
+ switch (widget->id) {
+ case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
return 0;
+ default:
+ break;
+ }
switch (widget->id) {
case snd_soc_dapm_adc:
case snd_soc_dapm_aif_out:
- if (widget->active)
- return snd_soc_dapm_suspend_check(widget);
+ case snd_soc_dapm_dai:
+ if (widget->active) {
+ widget->outputs = snd_soc_dapm_suspend_check(widget);
+ return widget->outputs;
+ }
default:
break;
}
if (widget->connected) {
/* connected pin ? */
- if (widget->id == snd_soc_dapm_output && !widget->ext)
- return snd_soc_dapm_suspend_check(widget);
+ if (widget->id == snd_soc_dapm_output && !widget->ext) {
+ widget->outputs = snd_soc_dapm_suspend_check(widget);
+ return widget->outputs;
+ }
/* connected jack or spk ? */
- if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
- (widget->id == snd_soc_dapm_line && !list_empty(&widget->sources)))
- return snd_soc_dapm_suspend_check(widget);
+ if (widget->id == snd_soc_dapm_hp ||
+ widget->id == snd_soc_dapm_spk ||
+ (widget->id == snd_soc_dapm_line &&
+ !list_empty(&widget->sources))) {
+ widget->outputs = snd_soc_dapm_suspend_check(widget);
+ return widget->outputs;
+ }
}
list_for_each_entry(path, &widget->sinks, list_source) {
+ DAPM_UPDATE_STAT(widget, neighbour_checks);
+
if (path->weak)
continue;
@@ -680,6 +746,8 @@ static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
}
}
+ widget->outputs = con;
+
return con;
}
@@ -692,35 +760,63 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
struct snd_soc_dapm_path *path;
int con = 0;
- if (widget->id == snd_soc_dapm_supply)
+ if (widget->inputs >= 0)
+ return widget->inputs;
+
+ DAPM_UPDATE_STAT(widget, path_checks);
+
+ switch (widget->id) {
+ case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
return 0;
+ default:
+ break;
+ }
/* active stream ? */
switch (widget->id) {
case snd_soc_dapm_dac:
case snd_soc_dapm_aif_in:
- if (widget->active)
- return snd_soc_dapm_suspend_check(widget);
+ case snd_soc_dapm_dai:
+ if (widget->active) {
+ widget->inputs = snd_soc_dapm_suspend_check(widget);
+ return widget->inputs;
+ }
default:
break;
}
if (widget->connected) {
/* connected pin ? */
- if (widget->id == snd_soc_dapm_input && !widget->ext)
- return snd_soc_dapm_suspend_check(widget);
+ if (widget->id == snd_soc_dapm_input && !widget->ext) {
+ widget->inputs = snd_soc_dapm_suspend_check(widget);
+ return widget->inputs;
+ }
/* connected VMID/Bias for lower pops */
- if (widget->id == snd_soc_dapm_vmid)
- return snd_soc_dapm_suspend_check(widget);
+ if (widget->id == snd_soc_dapm_vmid) {
+ widget->inputs = snd_soc_dapm_suspend_check(widget);
+ return widget->inputs;
+ }
/* connected jack ? */
if (widget->id == snd_soc_dapm_mic ||
- (widget->id == snd_soc_dapm_line && !list_empty(&widget->sinks)))
- return snd_soc_dapm_suspend_check(widget);
+ (widget->id == snd_soc_dapm_line &&
+ !list_empty(&widget->sinks))) {
+ widget->inputs = snd_soc_dapm_suspend_check(widget);
+ return widget->inputs;
+ }
+
+ /* signal generator */
+ if (widget->id == snd_soc_dapm_siggen) {
+ widget->inputs = snd_soc_dapm_suspend_check(widget);
+ return widget->inputs;
+ }
}
list_for_each_entry(path, &widget->sources, list_sink) {
+ DAPM_UPDATE_STAT(widget, neighbour_checks);
+
if (path->weak)
continue;
@@ -733,6 +829,8 @@ static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
}
}
+ widget->inputs = con;
+
return con;
}
@@ -756,12 +854,42 @@ int dapm_reg_event(struct snd_soc_dapm_widget *w,
}
EXPORT_SYMBOL_GPL(dapm_reg_event);
+/*
+ * Handler for regulator supply widget.
+ */
+int dapm_regulator_event(struct snd_soc_dapm_widget *w,
+ struct snd_kcontrol *kcontrol, int event)
+{
+ if (SND_SOC_DAPM_EVENT_ON(event))
+ return regulator_enable(w->priv);
+ else
+ return regulator_disable_deferred(w->priv, w->shift);
+}
+EXPORT_SYMBOL_GPL(dapm_regulator_event);
+
+static int dapm_widget_power_check(struct snd_soc_dapm_widget *w)
+{
+ if (w->power_checked)
+ return w->new_power;
+
+ if (w->force)
+ w->new_power = 1;
+ else
+ w->new_power = w->power_check(w);
+
+ w->power_checked = true;
+
+ return w->new_power;
+}
+
/* Generic check to see if a widget should be powered.
*/
static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
{
int in, out;
+ DAPM_UPDATE_STAT(w, power_checks);
+
in = is_connected_input_ep(w);
dapm_clear_walk(w->dapm);
out = is_connected_output_ep(w);
@@ -769,11 +897,20 @@ static int dapm_generic_check_power(struct snd_soc_dapm_widget *w)
return out != 0 && in != 0;
}
+static int dapm_dai_check_power(struct snd_soc_dapm_widget *w)
+{
+ DAPM_UPDATE_STAT(w, power_checks);
+
+ return w->active;
+}
+
/* Check to see if an ADC has power */
static int dapm_adc_check_power(struct snd_soc_dapm_widget *w)
{
int in;
+ DAPM_UPDATE_STAT(w, power_checks);
+
if (w->active) {
in = is_connected_input_ep(w);
dapm_clear_walk(w->dapm);
@@ -788,6 +925,8 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
{
int out;
+ DAPM_UPDATE_STAT(w, power_checks);
+
if (w->active) {
out = is_connected_output_ep(w);
dapm_clear_walk(w->dapm);
@@ -801,10 +940,13 @@ static int dapm_dac_check_power(struct snd_soc_dapm_widget *w)
static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
{
struct snd_soc_dapm_path *path;
- int power = 0;
+
+ DAPM_UPDATE_STAT(w, power_checks);
/* Check if one of our outputs is connected */
list_for_each_entry(path, &w->sinks, list_source) {
+ DAPM_UPDATE_STAT(w, neighbour_checks);
+
if (path->weak)
continue;
@@ -815,21 +957,18 @@ static int dapm_supply_check_power(struct snd_soc_dapm_widget *w)
if (!path->sink)
continue;
- if (path->sink->force) {
- power = 1;
- break;
- }
-
- if (path->sink->power_check &&
- path->sink->power_check(path->sink)) {
- power = 1;
- break;
- }
+ if (dapm_widget_power_check(path->sink))
+ return 1;
}
dapm_clear_walk(w->dapm);
- return power;
+ return 0;
+}
+
+static int dapm_always_on_check_power(struct snd_soc_dapm_widget *w)
+{
+ return 1;
}
static int dapm_seq_compare(struct snd_soc_dapm_widget *a,
@@ -1121,6 +1260,9 @@ static void dapm_pre_sequence_async(void *data, async_cookie_t cookie)
/* If we're off and we're not supposed to be go into STANDBY */
if (d->bias_level == SND_SOC_BIAS_OFF &&
d->target_bias_level != SND_SOC_BIAS_OFF) {
+ if (d->dev)
+ pm_runtime_get_sync(d->dev);
+
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_STANDBY);
if (ret != 0)
dev_err(d->dev,
@@ -1160,6 +1302,9 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
ret = snd_soc_dapm_set_bias_level(d, SND_SOC_BIAS_OFF);
if (ret != 0)
dev_err(d->dev, "Failed to turn off bias: %d\n", ret);
+
+ if (d->dev)
+ pm_runtime_put(d->dev);
}
/* If we just powered up then move to active bias */
@@ -1172,6 +1317,86 @@ static void dapm_post_sequence_async(void *data, async_cookie_t cookie)
}
}
+static void dapm_widget_set_peer_power(struct snd_soc_dapm_widget *peer,
+ bool power, bool connect)
+{
+ /* If a connection is being made or broken then that update
+ * will have marked the peer dirty, otherwise the widgets are
+ * not connected and this update has no impact. */
+ if (!connect)
+ return;
+
+ /* If the peer is already in the state we're moving to then we
+ * won't have an impact on it. */
+ if (power != peer->power)
+ dapm_mark_dirty(peer, "peer state change");
+}
+
+static void dapm_widget_set_power(struct snd_soc_dapm_widget *w, bool power,
+ struct list_head *up_list,
+ struct list_head *down_list)
+{
+ struct snd_soc_dapm_path *path;
+
+ if (w->power == power)
+ return;
+
+ trace_snd_soc_dapm_widget_power(w, power);
+
+ /* If we changed our power state perhaps our neigbours changed
+ * also.
+ */
+ list_for_each_entry(path, &w->sources, list_sink) {
+ if (path->source) {
+ dapm_widget_set_peer_power(path->source, power,
+ path->connect);
+ }
+ }
+ switch (w->id) {
+ case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
+ /* Supplies can't affect their outputs, only their inputs */
+ break;
+ default:
+ list_for_each_entry(path, &w->sinks, list_source) {
+ if (path->sink) {
+ dapm_widget_set_peer_power(path->sink, power,
+ path->connect);
+ }
+ }
+ break;
+ }
+
+ if (power)
+ dapm_seq_insert(w, up_list, true);
+ else
+ dapm_seq_insert(w, down_list, false);
+
+ w->power = power;
+}
+
+static void dapm_power_one_widget(struct snd_soc_dapm_widget *w,
+ struct list_head *up_list,
+ struct list_head *down_list)
+{
+ int power;
+
+ switch (w->id) {
+ case snd_soc_dapm_pre:
+ dapm_seq_insert(w, down_list, false);
+ break;
+ case snd_soc_dapm_post:
+ dapm_seq_insert(w, up_list, true);
+ break;
+
+ default:
+ power = dapm_widget_power_check(w);
+
+ dapm_widget_set_power(w, power, up_list, down_list);
+ break;
+ }
+}
+
/*
* Scan each dapm widget for complete audio path.
* A complete path is a route that has valid endpoints i.e.:-
@@ -1190,7 +1415,6 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
LIST_HEAD(down_list);
LIST_HEAD(async_domain);
enum snd_soc_bias_level bias;
- int power;
trace_snd_soc_dapm_start(card);
@@ -1203,61 +1427,46 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
}
}
+ dapm_reset(card);
+
/* Check which widgets we need to power and store them in
- * lists indicating if they should be powered up or down.
+ * lists indicating if they should be powered up or down. We
+ * only check widgets that have been flagged as dirty but note
+ * that new widgets may be added to the dirty list while we
+ * iterate.
*/
- list_for_each_entry(w, &card->widgets, list) {
- switch (w->id) {
- case snd_soc_dapm_pre:
- dapm_seq_insert(w, &down_list, false);
- break;
- case snd_soc_dapm_post:
- dapm_seq_insert(w, &up_list, true);
- break;
-
- default:
- if (!w->power_check)
- continue;
-
- if (!w->force)
- power = w->power_check(w);
- else
- power = 1;
+ list_for_each_entry(w, &card->dapm_dirty, dirty) {
+ dapm_power_one_widget(w, &up_list, &down_list);
+ }
- if (power) {
- d = w->dapm;
+ list_for_each_entry(w, &card->widgets, list) {
+ list_del_init(&w->dirty);
- /* Supplies and micbiases only bring
- * the context up to STANDBY as unless
- * something else is active and
- * passing audio they generally don't
- * require full power.
- */
- switch (w->id) {
- case snd_soc_dapm_supply:
- case snd_soc_dapm_micbias:
- if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
- d->target_bias_level = SND_SOC_BIAS_STANDBY;
- break;
- default:
- d->target_bias_level = SND_SOC_BIAS_ON;
- break;
- }
+ if (w->power) {
+ d = w->dapm;
+
+ /* Supplies and micbiases only bring the
+ * context up to STANDBY as unless something
+ * else is active and passing audio they
+ * generally don't require full power. Signal
+ * generators are virtual pins and have no
+ * power impact themselves.
+ */
+ switch (w->id) {
+ case snd_soc_dapm_siggen:
+ break;
+ case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
+ case snd_soc_dapm_micbias:
+ if (d->target_bias_level < SND_SOC_BIAS_STANDBY)
+ d->target_bias_level = SND_SOC_BIAS_STANDBY;
+ break;
+ default:
+ d->target_bias_level = SND_SOC_BIAS_ON;
+ break;
}
-
- if (w->power == power)
- continue;
-
- trace_snd_soc_dapm_widget_power(w, power);
-
- if (power)
- dapm_seq_insert(w, &up_list, true);
- else
- dapm_seq_insert(w, &down_list, false);
-
- w->power = power;
- break;
}
+
}
/* If there are no DAPM widgets then try to figure out power from the
@@ -1270,7 +1479,7 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
dapm->target_bias_level = SND_SOC_BIAS_ON;
break;
case SND_SOC_DAPM_STREAM_STOP:
- if (dapm->codec->active)
+ if (dapm->codec && dapm->codec->active)
dapm->target_bias_level = SND_SOC_BIAS_ON;
else
dapm->target_bias_level = SND_SOC_BIAS_STANDBY;
@@ -1286,14 +1495,18 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
}
}
- /* Force all contexts in the card to the same bias state */
+ /* Force all contexts in the card to the same bias state if
+ * they're not ground referenced.
+ */
bias = SND_SOC_BIAS_OFF;
list_for_each_entry(d, &card->dapm_list, list)
if (d->target_bias_level > bias)
bias = d->target_bias_level;
list_for_each_entry(d, &card->dapm_list, list)
- d->target_bias_level = bias;
+ if (!d->idle_bias_off)
+ d->target_bias_level = bias;
+ trace_snd_soc_dapm_walk_done(card);
/* Run all the bias changes in parallel */
list_for_each_entry(d, &dapm->card->dapm_list, list)
@@ -1315,6 +1528,12 @@ static int dapm_power_widgets(struct snd_soc_dapm_context *dapm, int event)
&async_domain);
async_synchronize_full_domain(&async_domain);
+ /* do we need to notify any clients that DAPM event is complete */
+ list_for_each_entry(d, &card->dapm_list, list) {
+ if (d->stream_event)
+ d->stream_event(d, event);
+ }
+
pop_dbg(dapm->dev, card->pop_time,
"DAPM sequencing finished, waiting %dms\n", card->pop_time);
pop_wait(card->pop_time);
@@ -1350,8 +1569,9 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
out = is_connected_output_ep(w);
dapm_clear_walk(w->dapm);
- ret = snprintf(buf, PAGE_SIZE, "%s: %s in %d out %d",
- w->name, w->power ? "On" : "Off", in, out);
+ ret = snprintf(buf, PAGE_SIZE, "%s: %s%s in %d out %d",
+ w->name, w->power ? "On" : "Off",
+ w->force ? " (forced)" : "", in, out);
if (w->reg >= 0)
ret += snprintf(buf + ret, PAGE_SIZE - ret,
@@ -1447,7 +1667,7 @@ void snd_soc_dapm_debugfs_init(struct snd_soc_dapm_context *dapm,
dapm->debugfs_dapm = debugfs_create_dir("dapm", parent);
if (!dapm->debugfs_dapm) {
- printk(KERN_WARNING
+ dev_warn(dapm->dev,
"Failed to create DAPM debugfs directory\n");
return;
}
@@ -1499,9 +1719,8 @@ static inline void dapm_debugfs_cleanup(struct snd_soc_dapm_context *dapm)
#endif
/* test and update the power status of a mux widget */
-static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
- struct snd_kcontrol *kcontrol, int change,
- int mux, struct soc_enum *e)
+int snd_soc_dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
+ struct snd_kcontrol *kcontrol, int mux, struct soc_enum *e)
{
struct snd_soc_dapm_path *path;
int found = 0;
@@ -1511,9 +1730,6 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
widget->id != snd_soc_dapm_value_mux)
return -ENODEV;
- if (!change)
- return 0;
-
/* find dapm widget path assoc with kcontrol */
list_for_each_entry(path, &widget->dapm->card->paths, list) {
if (path->kcontrol != kcontrol)
@@ -1524,20 +1740,28 @@ static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
found = 1;
/* we now need to match the string in the enum to the path */
- if (!(strcmp(path->name, e->texts[mux])))
+ if (!(strcmp(path->name, e->texts[mux]))) {
path->connect = 1; /* new connection */
- else
+ dapm_mark_dirty(path->source, "mux connection");
+ } else {
+ if (path->connect)
+ dapm_mark_dirty(path->source,
+ "mux disconnection");
path->connect = 0; /* old connection must be powered down */
+ }
}
- if (found)
+ if (found) {
+ dapm_mark_dirty(widget, "mux change");
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
+ }
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mux_update_power);
/* test and update the power status of a mixer or switch widget */
-static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
+int snd_soc_dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
struct snd_kcontrol *kcontrol, int connect)
{
struct snd_soc_dapm_path *path;
@@ -1556,21 +1780,23 @@ static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
/* found, now check type */
found = 1;
path->connect = connect;
- break;
+ dapm_mark_dirty(path->source, "mixer connection");
}
- if (found)
+ if (found) {
+ dapm_mark_dirty(widget, "mixer update");
dapm_power_widgets(widget->dapm, SND_SOC_DAPM_STREAM_NOP);
+ }
return 0;
}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_mixer_update_power);
/* show dapm widget status in sys fs */
static ssize_t dapm_widget_show(struct device *dev,
struct device_attribute *attr, char *buf)
{
- struct snd_soc_pcm_runtime *rtd =
- container_of(dev, struct snd_soc_pcm_runtime, dev);
+ struct snd_soc_pcm_runtime *rtd = dev_get_drvdata(dev);
struct snd_soc_codec *codec =rtd->codec;
struct snd_soc_dapm_widget *w;
int count = 0;
@@ -1594,6 +1820,7 @@ static ssize_t dapm_widget_show(struct device *dev,
case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl:
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
if (w->name)
count += sprintf(buf + count, "%s: %s\n",
w->name, w->power ? "On":"Off");
@@ -1701,6 +1928,9 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
return -EINVAL;
}
+ if (w->connected != status)
+ dapm_mark_dirty(w, "pin configuration");
+
w->connected = status;
if (status == 0)
w->force = 0;
@@ -1719,6 +1949,13 @@ static int snd_soc_dapm_set_pin(struct snd_soc_dapm_context *dapm,
*/
int snd_soc_dapm_sync(struct snd_soc_dapm_context *dapm)
{
+ /*
+ * Suppress early reports (eg, jacks syncing their state) to avoid
+ * silly DAPM runs during card startup.
+ */
+ if (!dapm->card || !dapm->card->instantiated)
+ return 0;
+
return dapm_power_widgets(dapm, SND_SOC_DAPM_STREAM_NOP);
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_sync);
@@ -1818,13 +2055,16 @@ static int snd_soc_dapm_add_route(struct snd_soc_dapm_context *dapm,
case snd_soc_dapm_out_drv:
case snd_soc_dapm_input:
case snd_soc_dapm_output:
+ case snd_soc_dapm_siggen:
case snd_soc_dapm_micbias:
case snd_soc_dapm_vmid:
case snd_soc_dapm_pre:
case snd_soc_dapm_post:
case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
case snd_soc_dapm_aif_in:
case snd_soc_dapm_aif_out:
+ case snd_soc_dapm_dai:
list_add(&path->list, &dapm->card->paths);
list_add(&path->list_sink, &wsink->sources);
list_add(&path->list_source, &wsource->sinks);
@@ -2004,42 +2244,18 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
case snd_soc_dapm_switch:
case snd_soc_dapm_mixer:
case snd_soc_dapm_mixer_named_ctl:
- w->power_check = dapm_generic_check_power;
dapm_new_mixer(w);
break;
case snd_soc_dapm_mux:
case snd_soc_dapm_virt_mux:
case snd_soc_dapm_value_mux:
- w->power_check = dapm_generic_check_power;
dapm_new_mux(w);
break;
- case snd_soc_dapm_adc:
- case snd_soc_dapm_aif_out:
- w->power_check = dapm_adc_check_power;
- break;
- case snd_soc_dapm_dac:
- case snd_soc_dapm_aif_in:
- w->power_check = dapm_dac_check_power;
- break;
case snd_soc_dapm_pga:
case snd_soc_dapm_out_drv:
- w->power_check = dapm_generic_check_power;
dapm_new_pga(w);
break;
- case snd_soc_dapm_input:
- case snd_soc_dapm_output:
- case snd_soc_dapm_micbias:
- case snd_soc_dapm_spk:
- case snd_soc_dapm_hp:
- case snd_soc_dapm_mic:
- case snd_soc_dapm_line:
- w->power_check = dapm_generic_check_power;
- break;
- case snd_soc_dapm_supply:
- w->power_check = dapm_supply_check_power;
- case snd_soc_dapm_vmid:
- case snd_soc_dapm_pre:
- case snd_soc_dapm_post:
+ default:
break;
}
@@ -2056,6 +2272,7 @@ int snd_soc_dapm_new_widgets(struct snd_soc_dapm_context *dapm)
w->new = 1;
+ dapm_mark_dirty(w, "new widget");
dapm_debugfs_add_widget(w);
}
@@ -2161,7 +2378,7 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mixer_update_power(widget, kcontrol, connect);
+ snd_soc_dapm_mixer_update_power(widget, kcontrol, connect);
widget->dapm->update = NULL;
}
@@ -2252,7 +2469,7 @@ int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
widget->dapm->update = NULL;
}
@@ -2313,8 +2530,7 @@ int snd_soc_dapm_put_enum_virt(struct snd_kcontrol *kcontrol,
widget->value = ucontrol->value.enumerated.item[0];
- dapm_mux_update_power(widget, kcontrol, change,
- widget->value, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, widget->value, e);
}
}
@@ -2417,7 +2633,7 @@ int snd_soc_dapm_put_value_enum_double(struct snd_kcontrol *kcontrol,
update.val = val;
widget->dapm->update = &update;
- dapm_mux_update_power(widget, kcontrol, change, mux, e);
+ snd_soc_dapm_mux_update_power(widget, kcontrol, mux, e);
widget->dapm->update = NULL;
}
@@ -2457,15 +2673,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_info_pin_switch);
int snd_soc_dapm_get_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&codec->mutex);
+ mutex_lock(&card->mutex);
ucontrol->value.integer.value[0] =
- snd_soc_dapm_get_pin_status(&codec->dapm, pin);
+ snd_soc_dapm_get_pin_status(&card->dapm, pin);
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->mutex);
return 0;
}
@@ -2480,41 +2696,48 @@ EXPORT_SYMBOL_GPL(snd_soc_dapm_get_pin_switch);
int snd_soc_dapm_put_pin_switch(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct snd_soc_card *card = snd_kcontrol_chip(kcontrol);
const char *pin = (const char *)kcontrol->private_value;
- mutex_lock(&codec->mutex);
+ mutex_lock(&card->mutex);
if (ucontrol->value.integer.value[0])
- snd_soc_dapm_enable_pin(&codec->dapm, pin);
+ snd_soc_dapm_enable_pin(&card->dapm, pin);
else
- snd_soc_dapm_disable_pin(&codec->dapm, pin);
+ snd_soc_dapm_disable_pin(&card->dapm, pin);
- snd_soc_dapm_sync(&codec->dapm);
+ snd_soc_dapm_sync(&card->dapm);
- mutex_unlock(&codec->mutex);
+ mutex_unlock(&card->mutex);
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_put_pin_switch);
-/**
- * snd_soc_dapm_new_control - create new dapm control
- * @dapm: DAPM context
- * @widget: widget template
- *
- * Creates a new dapm control based upon the template.
- *
- * Returns 0 for success else error.
- */
-int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
- const struct snd_soc_dapm_widget *widget)
+static struct snd_soc_dapm_widget *
+snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
+ const struct snd_soc_dapm_widget *widget)
{
struct snd_soc_dapm_widget *w;
size_t name_len;
+ int ret;
if ((w = dapm_cnew_widget(widget)) == NULL)
- return -ENOMEM;
+ return NULL;
+
+ switch (w->id) {
+ case snd_soc_dapm_regulator_supply:
+ w->priv = devm_regulator_get(dapm->dev, w->name);
+ if (IS_ERR(w->priv)) {
+ ret = PTR_ERR(w->priv);
+ dev_err(dapm->dev, "Failed to request %s: %d\n",
+ w->name, ret);
+ return NULL;
+ }
+ break;
+ default:
+ break;
+ }
name_len = strlen(widget->name) + 1;
if (dapm->codec && dapm->codec->name_prefix)
@@ -2522,13 +2745,55 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
w->name = kmalloc(name_len, GFP_KERNEL);
if (w->name == NULL) {
kfree(w);
- return -ENOMEM;
+ return NULL;
}
if (dapm->codec && dapm->codec->name_prefix)
- snprintf(w->name, name_len, "%s %s",
+ snprintf((char *)w->name, name_len, "%s %s",
dapm->codec->name_prefix, widget->name);
else
- snprintf(w->name, name_len, "%s", widget->name);
+ snprintf((char *)w->name, name_len, "%s", widget->name);
+
+ switch (w->id) {
+ case snd_soc_dapm_switch:
+ case snd_soc_dapm_mixer:
+ case snd_soc_dapm_mixer_named_ctl:
+ w->power_check = dapm_generic_check_power;
+ break;
+ case snd_soc_dapm_mux:
+ case snd_soc_dapm_virt_mux:
+ case snd_soc_dapm_value_mux:
+ w->power_check = dapm_generic_check_power;
+ break;
+ case snd_soc_dapm_adc:
+ case snd_soc_dapm_aif_out:
+ w->power_check = dapm_adc_check_power;
+ break;
+ case snd_soc_dapm_dac:
+ case snd_soc_dapm_aif_in:
+ w->power_check = dapm_dac_check_power;
+ break;
+ case snd_soc_dapm_pga:
+ case snd_soc_dapm_out_drv:
+ case snd_soc_dapm_input:
+ case snd_soc_dapm_output:
+ case snd_soc_dapm_micbias:
+ case snd_soc_dapm_spk:
+ case snd_soc_dapm_hp:
+ case snd_soc_dapm_mic:
+ case snd_soc_dapm_line:
+ w->power_check = dapm_generic_check_power;
+ break;
+ case snd_soc_dapm_supply:
+ case snd_soc_dapm_regulator_supply:
+ w->power_check = dapm_supply_check_power;
+ break;
+ case snd_soc_dapm_dai:
+ w->power_check = dapm_dai_check_power;
+ break;
+ default:
+ w->power_check = dapm_always_on_check_power;
+ break;
+ }
dapm->n_widgets++;
w->dapm = dapm;
@@ -2537,13 +2802,13 @@ int snd_soc_dapm_new_control(struct snd_soc_dapm_context *dapm,
INIT_LIST_HEAD(&w->sources);
INIT_LIST_HEAD(&w->sinks);
INIT_LIST_HEAD(&w->list);
+ INIT_LIST_HEAD(&w->dirty);
list_add(&w->list, &dapm->card->widgets);
/* machine layer set ups unconnected pins and insertions */
w->connected = 1;
- return 0;
+ return w;
}
-EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
/**
* snd_soc_dapm_new_controls - create new dapm controls
@@ -2559,15 +2824,16 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
const struct snd_soc_dapm_widget *widget,
int num)
{
- int i, ret;
+ struct snd_soc_dapm_widget *w;
+ int i;
for (i = 0; i < num; i++) {
- ret = snd_soc_dapm_new_control(dapm, widget);
- if (ret < 0) {
+ w = snd_soc_dapm_new_control(dapm, widget);
+ if (!w) {
dev_err(dapm->dev,
- "ASoC: Failed to create DAPM control %s: %d\n",
- widget->name, ret);
- return ret;
+ "ASoC: Failed to create DAPM control %s\n",
+ widget->name);
+ return -ENOMEM;
}
widget++;
}
@@ -2575,34 +2841,139 @@ int snd_soc_dapm_new_controls(struct snd_soc_dapm_context *dapm,
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_new_controls);
-static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
- const char *stream, int event)
+int snd_soc_dapm_new_dai_widgets(struct snd_soc_dapm_context *dapm,
+ struct snd_soc_dai *dai)
{
+ struct snd_soc_dapm_widget template;
struct snd_soc_dapm_widget *w;
- list_for_each_entry(w, &dapm->card->widgets, list)
- {
- if (!w->sname || w->dapm != dapm)
+ WARN_ON(dapm->dev != dai->dev);
+
+ memset(&template, 0, sizeof(template));
+ template.reg = SND_SOC_NOPM;
+
+ if (dai->driver->playback.stream_name) {
+ template.id = snd_soc_dapm_dai;
+ template.name = dai->driver->playback.stream_name;
+ template.sname = dai->driver->playback.stream_name;
+
+ dev_dbg(dai->dev, "adding %s widget\n",
+ template.name);
+
+ w = snd_soc_dapm_new_control(dapm, &template);
+ if (!w) {
+ dev_err(dapm->dev, "Failed to create %s widget\n",
+ dai->driver->playback.stream_name);
+ }
+
+ w->priv = dai;
+ dai->playback_widget = w;
+ }
+
+ if (dai->driver->capture.stream_name) {
+ template.id = snd_soc_dapm_dai;
+ template.name = dai->driver->capture.stream_name;
+ template.sname = dai->driver->capture.stream_name;
+
+ dev_dbg(dai->dev, "adding %s widget\n",
+ template.name);
+
+ w = snd_soc_dapm_new_control(dapm, &template);
+ if (!w) {
+ dev_err(dapm->dev, "Failed to create %s widget\n",
+ dai->driver->capture.stream_name);
+ }
+
+ w->priv = dai;
+ dai->capture_widget = w;
+ }
+
+ return 0;
+}
+
+int snd_soc_dapm_link_dai_widgets(struct snd_soc_card *card)
+{
+ struct snd_soc_dapm_widget *dai_w, *w;
+ struct snd_soc_dai *dai;
+ struct snd_soc_dapm_route r;
+
+ memset(&r, 0, sizeof(r));
+
+ /* For each DAI widget... */
+ list_for_each_entry(dai_w, &card->widgets, list) {
+ if (dai_w->id != snd_soc_dapm_dai)
continue;
- dev_dbg(w->dapm->dev, "widget %s\n %s stream %s event %d\n",
- w->name, w->sname, stream, event);
- if (strstr(w->sname, stream)) {
- switch(event) {
- case SND_SOC_DAPM_STREAM_START:
- w->active = 1;
- break;
- case SND_SOC_DAPM_STREAM_STOP:
- w->active = 0;
- break;
- case SND_SOC_DAPM_STREAM_SUSPEND:
- case SND_SOC_DAPM_STREAM_RESUME:
- case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
- case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
- break;
+
+ dai = dai_w->priv;
+
+ /* ...find all widgets with the same stream and link them */
+ list_for_each_entry(w, &card->widgets, list) {
+ if (w->dapm != dai_w->dapm)
+ continue;
+
+ if (w->id == snd_soc_dapm_dai)
+ continue;
+
+ if (!w->sname)
+ continue;
+
+ if (dai->driver->playback.stream_name &&
+ strstr(w->sname,
+ dai->driver->playback.stream_name)) {
+ r.source = dai->playback_widget->name;
+ r.sink = w->name;
+ dev_dbg(dai->dev, "%s -> %s\n",
+ r.source, r.sink);
+
+ snd_soc_dapm_add_route(w->dapm, &r);
+ }
+
+ if (dai->driver->capture.stream_name &&
+ strstr(w->sname,
+ dai->driver->capture.stream_name)) {
+ r.source = w->name;
+ r.sink = dai->capture_widget->name;
+ dev_dbg(dai->dev, "%s -> %s\n",
+ r.source, r.sink);
+
+ snd_soc_dapm_add_route(w->dapm, &r);
}
}
}
+ return 0;
+}
+
+static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
+ int stream, struct snd_soc_dai *dai,
+ int event)
+{
+ struct snd_soc_dapm_widget *w;
+
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ w = dai->playback_widget;
+ else
+ w = dai->capture_widget;
+
+ if (!w)
+ return;
+
+ dapm_mark_dirty(w, "stream event");
+
+ switch (event) {
+ case SND_SOC_DAPM_STREAM_START:
+ w->active = 1;
+ break;
+ case SND_SOC_DAPM_STREAM_STOP:
+ w->active = 0;
+ break;
+ case SND_SOC_DAPM_STREAM_SUSPEND:
+ case SND_SOC_DAPM_STREAM_RESUME:
+ case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
+ case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
+ break;
+ }
+
dapm_power_widgets(dapm, event);
}
@@ -2617,16 +2988,13 @@ static void soc_dapm_stream_event(struct snd_soc_dapm_context *dapm,
*
* Returns 0 for success else error.
*/
-int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd,
- const char *stream, int event)
+int snd_soc_dapm_stream_event(struct snd_soc_pcm_runtime *rtd, int stream,
+ struct snd_soc_dai *dai, int event)
{
struct snd_soc_codec *codec = rtd->codec;
- if (stream == NULL)
- return 0;
-
mutex_lock(&codec->mutex);
- soc_dapm_stream_event(&codec->dapm, stream, event);
+ soc_dapm_stream_event(&codec->dapm, stream, dai, event);
mutex_unlock(&codec->mutex);
return 0;
}
@@ -2672,6 +3040,7 @@ int snd_soc_dapm_force_enable_pin(struct snd_soc_dapm_context *dapm,
dev_dbg(w->dapm->dev, "dapm: force enable pin %s\n", pin);
w->connected = 1;
w->force = 1;
+ dapm_mark_dirty(w, "force enable");
return 0;
}
@@ -2761,9 +3130,82 @@ int snd_soc_dapm_ignore_suspend(struct snd_soc_dapm_context *dapm,
}
EXPORT_SYMBOL_GPL(snd_soc_dapm_ignore_suspend);
+static bool snd_soc_dapm_widget_in_card_paths(struct snd_soc_card *card,
+ struct snd_soc_dapm_widget *w)
+{
+ struct snd_soc_dapm_path *p;
+
+ list_for_each_entry(p, &card->paths, list) {
+ if ((p->source == w) || (p->sink == w)) {
+ dev_dbg(card->dev,
+ "... Path %s(id:%d dapm:%p) - %s(id:%d dapm:%p)\n",
+ p->source->name, p->source->id, p->source->dapm,
+ p->sink->name, p->sink->id, p->sink->dapm);
+
+ /* Connected to something other than the codec */
+ if (p->source->dapm != p->sink->dapm)
+ return true;
+ /*
+ * Loopback connection from codec external pin to
+ * codec external pin
+ */
+ if (p->sink->id == snd_soc_dapm_input) {
+ switch (p->source->id) {
+ case snd_soc_dapm_output:
+ case snd_soc_dapm_micbias:
+ return true;
+ default:
+ break;
+ }
+ }
+ }
+ }
+
+ return false;
+}
+
+/**
+ * snd_soc_dapm_auto_nc_codec_pins - call snd_soc_dapm_nc_pin for unused pins
+ * @codec: The codec whose pins should be processed
+ *
+ * Automatically call snd_soc_dapm_nc_pin() for any external pins in the codec
+ * which are unused. Pins are used if they are connected externally to the
+ * codec, whether that be to some other device, or a loop-back connection to
+ * the codec itself.
+ */
+void snd_soc_dapm_auto_nc_codec_pins(struct snd_soc_codec *codec)
+{
+ struct snd_soc_card *card = codec->card;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct snd_soc_dapm_widget *w;
+
+ dev_dbg(codec->dev, "Auto NC: DAPMs: card:%p codec:%p\n",
+ &card->dapm, &codec->dapm);
+
+ list_for_each_entry(w, &card->widgets, list) {
+ if (w->dapm != dapm)
+ continue;
+ switch (w->id) {
+ case snd_soc_dapm_input:
+ case snd_soc_dapm_output:
+ case snd_soc_dapm_micbias:
+ dev_dbg(codec->dev, "Auto NC: Checking widget %s\n",
+ w->name);
+ if (!snd_soc_dapm_widget_in_card_paths(card, w)) {
+ dev_dbg(codec->dev,
+ "... Not in map; disabling\n");
+ snd_soc_dapm_nc_pin(dapm, w->name);
+ }
+ break;
+ default:
+ break;
+ }
+ }
+}
+
/**
* snd_soc_dapm_free - free dapm resources
- * @card: SoC device
+ * @dapm: DAPM context
*
* Free all dapm widgets and resources.
*/
@@ -2796,9 +3238,13 @@ static void soc_dapm_shutdown_codec(struct snd_soc_dapm_context *dapm)
* standby.
*/
if (powerdown) {
- snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_PREPARE);
+ if (dapm->bias_level == SND_SOC_BIAS_ON)
+ snd_soc_dapm_set_bias_level(dapm,
+ SND_SOC_BIAS_PREPARE);
dapm_seq_run(dapm, &down_list, 0, false);
- snd_soc_dapm_set_bias_level(dapm, SND_SOC_BIAS_STANDBY);
+ if (dapm->bias_level == SND_SOC_BIAS_PREPARE)
+ snd_soc_dapm_set_bias_level(dapm,
+ SND_SOC_BIAS_STANDBY);
}
}
@@ -2811,7 +3257,9 @@ void snd_soc_dapm_shutdown(struct snd_soc_card *card)
list_for_each_entry(codec, &card->codec_dev_list, list) {
soc_dapm_shutdown_codec(&codec->dapm);
- snd_soc_dapm_set_bias_level(&codec->dapm, SND_SOC_BIAS_OFF);
+ if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY)
+ snd_soc_dapm_set_bias_level(&codec->dapm,
+ SND_SOC_BIAS_OFF);
}
}
diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c
new file mode 100644
index 000000000000..4420b7030c83
--- /dev/null
+++ b/sound/soc/soc-dmaengine-pcm.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (C) 2012, Analog Devices Inc.
+ * Author: Lars-Peter Clausen <lars@metafoo.de>
+ *
+ * Based on:
+ * imx-pcm-dma-mx2.c, Copyright 2009 Sascha Hauer <s.hauer@pengutronix.de>
+ * mxs-pcm.c, Copyright (C) 2011 Freescale Semiconductor, Inc.
+ * ep93xx-pcm.c, Copyright (C) 2006 Lennert Buytenhek <buytenh@wantstofly.org>
+ * Copyright (C) 2006 Applied Data Systems
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ */
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/dmaengine.h>
+#include <linux/slab.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <sound/dmaengine_pcm.h>
+
+struct dmaengine_pcm_runtime_data {
+ struct dma_chan *dma_chan;
+
+ unsigned int pos;
+
+ void *data;
+};
+
+static inline struct dmaengine_pcm_runtime_data *substream_to_prtd(
+ const struct snd_pcm_substream *substream)
+{
+ return substream->runtime->private_data;
+}
+
+/**
+ * snd_dmaengine_pcm_set_data - Set dmaengine substream private data
+ * @substream: PCM substream
+ * @data: Data to set
+ */
+void snd_dmaengine_pcm_set_data(struct snd_pcm_substream *substream, void *data)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ prtd->data = data;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_set_data);
+
+/**
+ * snd_dmaengine_pcm_get_data - Get dmaeinge substream private data
+ * @substream: PCM substream
+ *
+ * Returns the data previously set with snd_dmaengine_pcm_set_data
+ */
+void *snd_dmaengine_pcm_get_data(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ return prtd->data;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_data);
+
+struct dma_chan *snd_dmaengine_pcm_get_chan(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ return prtd->dma_chan;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_get_chan);
+
+/**
+ * snd_hwparams_to_dma_slave_config - Convert hw_params to dma_slave_config
+ * @substream: PCM substream
+ * @params: hw_params
+ * @slave_config: DMA slave config
+ *
+ * This function can be used to initialize a dma_slave_config from a substream
+ * and hw_params in a dmaengine based PCM driver implementation.
+ */
+int snd_hwparams_to_dma_slave_config(const struct snd_pcm_substream *substream,
+ const struct snd_pcm_hw_params *params,
+ struct dma_slave_config *slave_config)
+{
+ enum dma_slave_buswidth buswidth;
+
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ buswidth = DMA_SLAVE_BUSWIDTH_1_BYTE;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ buswidth = DMA_SLAVE_BUSWIDTH_2_BYTES;
+ break;
+ case SNDRV_PCM_FORMAT_S18_3LE:
+ case SNDRV_PCM_FORMAT_S20_3LE:
+ case SNDRV_PCM_FORMAT_S24_LE:
+ case SNDRV_PCM_FORMAT_S32_LE:
+ buswidth = DMA_SLAVE_BUSWIDTH_4_BYTES;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ slave_config->direction = DMA_MEM_TO_DEV;
+ slave_config->dst_addr_width = buswidth;
+ } else {
+ slave_config->direction = DMA_DEV_TO_MEM;
+ slave_config->src_addr_width = buswidth;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_hwparams_to_dma_slave_config);
+
+static void dmaengine_pcm_dma_complete(void *arg)
+{
+ struct snd_pcm_substream *substream = arg;
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ prtd->pos += snd_pcm_lib_period_bytes(substream);
+ if (prtd->pos >= snd_pcm_lib_buffer_bytes(substream))
+ prtd->pos = 0;
+
+ snd_pcm_period_elapsed(substream);
+}
+
+static int dmaengine_pcm_prepare_and_submit(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ struct dma_chan *chan = prtd->dma_chan;
+ struct dma_async_tx_descriptor *desc;
+ enum dma_transfer_direction direction;
+
+ direction = snd_pcm_substream_to_dma_direction(substream);
+
+ prtd->pos = 0;
+ desc = chan->device->device_prep_dma_cyclic(chan,
+ substream->runtime->dma_addr,
+ snd_pcm_lib_buffer_bytes(substream),
+ snd_pcm_lib_period_bytes(substream), direction);
+
+ if (!desc)
+ return -ENOMEM;
+
+ desc->callback = dmaengine_pcm_dma_complete;
+ desc->callback_param = substream;
+ dmaengine_submit(desc);
+
+ return 0;
+}
+
+/**
+ * snd_dmaengine_pcm_trigger - dmaengine based PCM trigger implementation
+ * @substream: PCM substream
+ * @cmd: Trigger command
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function can be used as the PCM trigger callback for dmaengine based PCM
+ * driver implementations.
+ */
+int snd_dmaengine_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ int ret;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ ret = dmaengine_pcm_prepare_and_submit(substream);
+ if (ret)
+ return ret;
+ dma_async_issue_pending(prtd->dma_chan);
+ break;
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ dmaengine_resume(prtd->dma_chan);
+ break;
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ dmaengine_pause(prtd->dma_chan);
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ dmaengine_terminate_all(prtd->dma_chan);
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_trigger);
+
+/**
+ * snd_dmaengine_pcm_pointer - dmaengine based PCM pointer implementation
+ * @substream: PCM substream
+ *
+ * This function can be used as the PCM pointer callback for dmaengine based PCM
+ * driver implementations.
+ */
+snd_pcm_uframes_t snd_dmaengine_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+ return bytes_to_frames(substream->runtime, prtd->pos);
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_pointer);
+
+static int dmaengine_pcm_request_channel(struct dmaengine_pcm_runtime_data *prtd,
+ dma_filter_fn filter_fn, void *filter_data)
+{
+ dma_cap_mask_t mask;
+
+ dma_cap_zero(mask);
+ dma_cap_set(DMA_SLAVE, mask);
+ dma_cap_set(DMA_CYCLIC, mask);
+ prtd->dma_chan = dma_request_channel(mask, filter_fn, filter_data);
+
+ if (!prtd->dma_chan)
+ return -ENXIO;
+
+ return 0;
+}
+
+/**
+ * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream
+ * @substream: PCM substream
+ * @filter_fn: Filter function used to request the DMA channel
+ * @filter_data: Data passed to the DMA filter function
+ *
+ * Returns 0 on success, a negative error code otherwise.
+ *
+ * This function will request a DMA channel using the passed filter function and
+ * data. The function should usually be called from the pcm open callback.
+ *
+ * Note that this function will use private_data field of the substream's
+ * runtime. So it is not availabe to your pcm driver implementation. If you need
+ * to keep additional data attached to a substream use
+ * snd_dmaeinge_pcm_{set,get}_data.
+ */
+int snd_dmaengine_pcm_open(struct snd_pcm_substream *substream,
+ dma_filter_fn filter_fn, void *filter_data)
+{
+ struct dmaengine_pcm_runtime_data *prtd;
+ int ret;
+
+ ret = snd_pcm_hw_constraint_integer(substream->runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ return ret;
+
+ prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+ if (!prtd)
+ return -ENOMEM;
+
+ ret = dmaengine_pcm_request_channel(prtd, filter_fn, filter_data);
+ if (ret < 0) {
+ kfree(prtd);
+ return ret;
+ }
+
+ substream->runtime->private_data = prtd;
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open);
+
+/**
+ * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream
+ * @substream: PCM substream
+ */
+int snd_dmaengine_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct dmaengine_pcm_runtime_data *prtd = substream_to_prtd(substream);
+
+ dma_release_channel(prtd->dma_chan);
+ kfree(prtd);
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_close);
diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
index a62f7dd4ba96..4d8dc6a27d4d 100644
--- a/sound/soc/soc-io.c
+++ b/sound/soc/soc-io.c
@@ -13,26 +13,15 @@
#include <linux/i2c.h>
#include <linux/spi/spi.h>
+#include <linux/regmap.h>
+#include <linux/export.h>
#include <sound/soc.h>
#include <trace/events/asoc.h>
-#ifdef CONFIG_SPI_MASTER
-static int do_spi_write(void *control, const char *data, int len)
-{
- struct spi_device *spi = control;
- int ret;
-
- ret = spi_write(spi, data, len);
- if (ret < 0)
- return ret;
-
- return len;
-}
-#endif
-
-static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value, const void *data, int len)
+#ifdef CONFIG_REGMAP
+static int hw_write(struct snd_soc_codec *codec, unsigned int reg,
+ unsigned int value)
{
int ret;
@@ -49,13 +38,7 @@ static int do_hw_write(struct snd_soc_codec *codec, unsigned int reg,
return 0;
}
- ret = codec->hw_write(codec->control_data, data, len);
- if (ret == len)
- return 0;
- if (ret < 0)
- return ret;
- else
- return -EIO;
+ return regmap_write(codec->control_data, reg, value);
}
static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
@@ -69,8 +52,11 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
if (codec->cache_only)
return -1;
- BUG_ON(!codec->hw_read);
- return codec->hw_read(codec, reg);
+ ret = regmap_read(codec->control_data, reg, &val);
+ if (ret == 0)
+ return val;
+ else
+ return -1;
}
ret = snd_soc_cache_read(codec, reg, &val);
@@ -79,202 +65,18 @@ static unsigned int hw_read(struct snd_soc_codec *codec, unsigned int reg)
return val;
}
-static int snd_soc_4_12_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u16 data;
-
- data = cpu_to_be16((reg << 12) | (value & 0xffffff));
-
- return do_hw_write(codec, reg, value, &data, 2);
-}
-
-static int snd_soc_7_9_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u16 data;
-
- data = cpu_to_be16((reg << 9) | (value & 0x1ff));
-
- return do_hw_write(codec, reg, value, &data, 2);
-}
-
-static int snd_soc_8_8_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 data[2];
-
- reg &= 0xff;
- data[0] = reg;
- data[1] = value & 0xff;
-
- return do_hw_write(codec, reg, value, data, 2);
-}
-
-static int snd_soc_8_16_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 data[3];
- u16 val = cpu_to_be16(value);
-
- data[0] = reg;
- memcpy(&data[1], &val, sizeof(val));
-
- return do_hw_write(codec, reg, value, data, 3);
-}
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int do_i2c_read(struct snd_soc_codec *codec,
- void *reg, int reglen,
- void *data, int datalen)
-{
- struct i2c_msg xfer[2];
- int ret;
- struct i2c_client *client = codec->control_data;
-
- /* Write register */
- xfer[0].addr = client->addr;
- xfer[0].flags = 0;
- xfer[0].len = reglen;
- xfer[0].buf = reg;
-
- /* Read data */
- xfer[1].addr = client->addr;
- xfer[1].flags = I2C_M_RD;
- xfer[1].len = datalen;
- xfer[1].buf = data;
-
- ret = i2c_transfer(client->adapter, xfer, 2);
- if (ret == 2)
- return 0;
- else if (ret < 0)
- return ret;
- else
- return -EIO;
-}
-#endif
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_8_8_read_i2c(struct snd_soc_codec *codec,
- unsigned int r)
-{
- u8 reg = r;
- u8 data;
- int ret;
-
- ret = do_i2c_read(codec, &reg, 1, &data, 1);
- if (ret < 0)
- return 0;
- return data;
-}
-#else
-#define snd_soc_8_8_read_i2c NULL
-#endif
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_8_16_read_i2c(struct snd_soc_codec *codec,
- unsigned int r)
-{
- u8 reg = r;
- u16 data;
- int ret;
-
- ret = do_i2c_read(codec, &reg, 1, &data, 2);
- if (ret < 0)
- return 0;
- return (data >> 8) | ((data & 0xff) << 8);
-}
-#else
-#define snd_soc_8_16_read_i2c NULL
-#endif
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_16_8_read_i2c(struct snd_soc_codec *codec,
- unsigned int r)
-{
- u16 reg = r;
- u8 data;
- int ret;
-
- ret = do_i2c_read(codec, &reg, 2, &data, 1);
- if (ret < 0)
- return 0;
- return data;
-}
-#else
-#define snd_soc_16_8_read_i2c NULL
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static unsigned int snd_soc_16_8_read_spi(struct snd_soc_codec *codec,
- unsigned int r)
-{
- struct spi_device *spi = codec->control_data;
-
- const u16 reg = cpu_to_be16(r | 0x100);
- u8 data;
- int ret;
-
- ret = spi_write_then_read(spi, &reg, 2, &data, 1);
- if (ret < 0)
- return 0;
- return data;
-}
-#else
-#define snd_soc_16_8_read_spi NULL
-#endif
-
-static int snd_soc_16_8_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 data[3];
- u16 rval = cpu_to_be16(reg);
-
- memcpy(data, &rval, sizeof(rval));
- data[2] = value;
-
- return do_hw_write(codec, reg, value, data, 3);
-}
-
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
-static unsigned int snd_soc_16_16_read_i2c(struct snd_soc_codec *codec,
- unsigned int r)
-{
- u16 reg = cpu_to_be16(r);
- u16 data;
- int ret;
-
- ret = do_i2c_read(codec, &reg, 2, &data, 2);
- if (ret < 0)
- return 0;
- return be16_to_cpu(data);
-}
-#else
-#define snd_soc_16_16_read_i2c NULL
-#endif
-
-static int snd_soc_16_16_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u16 data[2];
-
- data[0] = cpu_to_be16(reg);
- data[1] = cpu_to_be16(value);
-
- return do_hw_write(codec, reg, value, data, sizeof(data));
-}
-
/* Primitive bulk write support for soc-cache. The data pointed to by
- * `data' needs to already be in the form the hardware expects
- * including any leading register specific data. Any data written
- * through this function will not go through the cache as it only
- * handles writing to volatile or out of bounds registers.
+ * `data' needs to already be in the form the hardware expects. Any
+ * data written through this function will not go through the cache as
+ * it only handles writing to volatile or out of bounds registers.
+ *
+ * This is currently only supported for devices using the regmap API
+ * wrappers.
*/
-static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int reg,
+static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec,
+ unsigned int reg,
const void *data, size_t len)
{
- int ret;
-
/* To ensure that we don't get out of sync with the cache, check
* whether the base register is volatile or if we've directly asked
* to bypass the cache. Out of bounds registers are considered
@@ -285,68 +87,9 @@ static int snd_soc_hw_bulk_write_raw(struct snd_soc_codec *codec, unsigned int r
&& reg < codec->driver->reg_cache_size)
return -EINVAL;
- switch (codec->control_type) {
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
- case SND_SOC_I2C:
- ret = i2c_master_send(to_i2c_client(codec->dev), data, len);
- break;
-#endif
-#if defined(CONFIG_SPI_MASTER)
- case SND_SOC_SPI:
- ret = spi_write(to_spi_device(codec->dev), data, len);
- break;
-#endif
- default:
- BUG();
- }
-
- if (ret == len)
- return 0;
- if (ret < 0)
- return ret;
- else
- return -EIO;
+ return regmap_raw_write(codec->control_data, reg, data, len);
}
-static struct {
- int addr_bits;
- int data_bits;
- int (*write)(struct snd_soc_codec *codec, unsigned int, unsigned int);
- unsigned int (*read)(struct snd_soc_codec *, unsigned int);
- unsigned int (*i2c_read)(struct snd_soc_codec *, unsigned int);
- unsigned int (*spi_read)(struct snd_soc_codec *, unsigned int);
-} io_types[] = {
- {
- .addr_bits = 4, .data_bits = 12,
- .write = snd_soc_4_12_write,
- },
- {
- .addr_bits = 7, .data_bits = 9,
- .write = snd_soc_7_9_write,
- },
- {
- .addr_bits = 8, .data_bits = 8,
- .write = snd_soc_8_8_write,
- .i2c_read = snd_soc_8_8_read_i2c,
- },
- {
- .addr_bits = 8, .data_bits = 16,
- .write = snd_soc_8_16_write,
- .i2c_read = snd_soc_8_16_read_i2c,
- },
- {
- .addr_bits = 16, .data_bits = 8,
- .write = snd_soc_16_8_write,
- .i2c_read = snd_soc_16_8_read_i2c,
- .spi_read = snd_soc_16_8_read_spi,
- },
- {
- .addr_bits = 16, .data_bits = 16,
- .write = snd_soc_16_16_write,
- .i2c_read = snd_soc_16_16_read_i2c,
- },
-};
-
/**
* snd_soc_codec_set_cache_io: Set up standard I/O functions.
*
@@ -370,50 +113,58 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
int addr_bits, int data_bits,
enum snd_soc_control_type control)
{
- int i;
-
- for (i = 0; i < ARRAY_SIZE(io_types); i++)
- if (io_types[i].addr_bits == addr_bits &&
- io_types[i].data_bits == data_bits)
- break;
- if (i == ARRAY_SIZE(io_types)) {
- printk(KERN_ERR
- "No I/O functions for %d bit address %d bit data\n",
- addr_bits, data_bits);
- return -EINVAL;
- }
+ struct regmap_config config;
+ int ret;
- codec->write = io_types[i].write;
+ memset(&config, 0, sizeof(config));
+ codec->write = hw_write;
codec->read = hw_read;
codec->bulk_write_raw = snd_soc_hw_bulk_write_raw;
+ config.reg_bits = addr_bits;
+ config.val_bits = data_bits;
+
switch (control) {
+#if defined(CONFIG_REGMAP_I2C) || defined(CONFIG_REGMAP_I2C_MODULE)
case SND_SOC_I2C:
-#if defined(CONFIG_I2C) || (defined(CONFIG_I2C_MODULE) && defined(MODULE))
- codec->hw_write = (hw_write_t)i2c_master_send;
-#endif
- if (io_types[i].i2c_read)
- codec->hw_read = io_types[i].i2c_read;
-
- codec->control_data = container_of(codec->dev,
- struct i2c_client,
- dev);
+ codec->control_data = regmap_init_i2c(to_i2c_client(codec->dev),
+ &config);
break;
+#endif
+#if defined(CONFIG_REGMAP_SPI) || defined(CONFIG_REGMAP_SPI_MODULE)
case SND_SOC_SPI:
-#ifdef CONFIG_SPI_MASTER
- codec->hw_write = do_spi_write;
+ codec->control_data = regmap_init_spi(to_spi_device(codec->dev),
+ &config);
+ break;
#endif
- if (io_types[i].spi_read)
- codec->hw_read = io_types[i].spi_read;
- codec->control_data = container_of(codec->dev,
- struct spi_device,
- dev);
+ case SND_SOC_REGMAP:
+ /* Device has made its own regmap arrangements */
+ codec->using_regmap = true;
+
+ ret = regmap_get_val_bytes(codec->control_data);
+ /* Errors are legitimate for non-integer byte multiples */
+ if (ret > 0)
+ codec->val_bytes = ret;
break;
+
+ default:
+ return -EINVAL;
}
+ if (IS_ERR(codec->control_data))
+ return PTR_ERR(codec->control_data);
+
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
-
+#else
+int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
+ int addr_bits, int data_bits,
+ enum snd_soc_control_type control)
+{
+ return -ENOTSUPP;
+}
+EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
+#endif
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c
index 38b00131b2fe..ee4353f843ea 100644
--- a/sound/soc/soc-jack.c
+++ b/sound/soc/soc-jack.c
@@ -17,6 +17,7 @@
#include <linux/interrupt.h>
#include <linux/workqueue.h>
#include <linux/delay.h>
+#include <linux/export.h>
#include <trace/events/asoc.h>
/**
@@ -105,7 +106,7 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask)
snd_soc_dapm_sync(dapm);
- snd_jack_report(jack->jack, status);
+ snd_jack_report(jack->jack, jack->status);
out:
mutex_unlock(&codec->mutex);
@@ -188,6 +189,8 @@ int snd_soc_jack_add_pins(struct snd_soc_jack *jack, int count,
list_add(&(pins[i].list), &jack->pins);
}
+ snd_soc_dapm_new_widgets(&jack->codec->card->dapm);
+
/* Update to reflect the last reported status; canned jack
* implementations are likely to set their state before the
* card has an opportunity to associate pins.
@@ -338,10 +341,8 @@ int snd_soc_jack_add_gpios(struct snd_soc_jack *jack, int count,
gpios[i].gpio, ret);
}
-#ifdef CONFIG_GPIO_SYSFS
/* Expose GPIO value over sysfs for diagnostic purposes */
gpio_export(gpios[i].gpio, false);
-#endif
/* Update initial jack status */
snd_soc_jack_gpio_detect(&gpios[i]);
@@ -373,9 +374,7 @@ void snd_soc_jack_free_gpios(struct snd_soc_jack *jack, int count,
int i;
for (i = 0; i < count; i++) {
-#ifdef CONFIG_GPIO_SYSFS
gpio_unexport(gpios[i].gpio);
-#endif
free_irq(gpio_to_irq(gpios[i].gpio), &gpios[i]);
cancel_delayed_work_sync(&gpios[i].work);
gpio_free(gpios[i].gpio);
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index 2879c883eebc..0ad8dcacd2f3 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -19,6 +19,7 @@
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/delay.h>
+#include <linux/pm_runtime.h>
#include <linux/slab.h>
#include <linux/workqueue.h>
#include <sound/core.h>
@@ -27,17 +28,13 @@
#include <sound/soc.h>
#include <sound/initval.h>
-static DEFINE_MUTEX(pcm_mutex);
-
-static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
+static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *soc_dai)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- struct snd_soc_dai *codec_dai = rtd->codec_dai;
int ret;
- if (!codec_dai->driver->symmetric_rates &&
- !cpu_dai->driver->symmetric_rates &&
+ if (!soc_dai->driver->symmetric_rates &&
!rtd->dai_link->symmetric_rates)
return 0;
@@ -45,19 +42,19 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
* the second can need to get its constraints before the first has
* picked a rate. Complain and allow the application to carry on.
*/
- if (!rtd->rate) {
- dev_warn(&rtd->dev,
+ if (!soc_dai->rate) {
+ dev_warn(soc_dai->dev,
"Not enforcing symmetric_rates due to race\n");
return 0;
}
- dev_dbg(&rtd->dev, "Symmetry forces %dHz rate\n", rtd->rate);
+ dev_dbg(soc_dai->dev, "Symmetry forces %dHz rate\n", soc_dai->rate);
ret = snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
- rtd->rate, rtd->rate);
+ soc_dai->rate, soc_dai->rate);
if (ret < 0) {
- dev_err(&rtd->dev,
+ dev_err(soc_dai->dev,
"Unable to apply rate symmetry constraint: %d\n", ret);
return ret;
}
@@ -66,6 +63,41 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream)
}
/*
+ * List of sample sizes that might go over the bus for parameter
+ * application. There ought to be a wildcard sample size for things
+ * like the DAC/ADC resolution to use but there isn't right now.
+ */
+static int sample_sizes[] = {
+ 24, 32,
+};
+
+static void soc_pcm_apply_msb(struct snd_pcm_substream *substream,
+ struct snd_soc_dai *dai)
+{
+ int ret, i, bits;
+
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ bits = dai->driver->playback.sig_bits;
+ else
+ bits = dai->driver->capture.sig_bits;
+
+ if (!bits)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(sample_sizes); i++) {
+ if (bits >= sample_sizes[i])
+ continue;
+
+ ret = snd_pcm_hw_constraint_msbits(substream->runtime, 0,
+ sample_sizes[i], bits);
+ if (ret != 0)
+ dev_warn(dai->dev,
+ "Failed to set MSB %d/%d: %d\n",
+ bits, sample_sizes[i], ret);
+ }
+}
+
+/*
* Called by ALSA when a PCM substream is opened, the runtime->hw record is
* then initialized and any private data can be allocated. This also calls
* startup for the cpu DAI, platform, machine and codec DAI.
@@ -81,14 +113,18 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
struct snd_soc_dai_driver *codec_dai_drv = codec_dai->driver;
int ret = 0;
+ pm_runtime_get_sync(cpu_dai->dev);
+ pm_runtime_get_sync(codec_dai->dev);
+ pm_runtime_get_sync(platform->dev);
+
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
/* startup the audio subsystem */
if (cpu_dai->driver->ops->startup) {
ret = cpu_dai->driver->ops->startup(substream, cpu_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't open interface %s\n",
- cpu_dai->name);
+ dev_err(cpu_dai->dev, "can't open interface %s: %d\n",
+ cpu_dai->name, ret);
goto out;
}
}
@@ -96,7 +132,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->open) {
ret = platform->driver->ops->open(substream);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
+ dev_err(platform->dev, "can't open platform %s: %d\n",
+ platform->name, ret);
goto platform_err;
}
}
@@ -104,8 +141,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (codec_dai->driver->ops->startup) {
ret = codec_dai->driver->ops->startup(substream, codec_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't open codec %s\n",
- codec_dai->name);
+ dev_err(codec_dai->dev, "can't open codec %s: %d\n",
+ codec_dai->name, ret);
goto codec_dai_err;
}
}
@@ -113,7 +150,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
if (rtd->dai_link->ops && rtd->dai_link->ops->startup) {
ret = rtd->dai_link->ops->startup(substream);
if (ret < 0) {
- printk(KERN_ERR "asoc: %s startup failed\n", rtd->dai_link->name);
+ pr_err("asoc: %s startup failed: %d\n",
+ rtd->dai_link->name, ret);
goto machine_err;
}
}
@@ -186,9 +224,18 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
goto config_err;
}
+ soc_pcm_apply_msb(substream, codec_dai);
+ soc_pcm_apply_msb(substream, cpu_dai);
+
/* Symmetry only applies if we've already got an active stream. */
- if (cpu_dai->active || codec_dai->active) {
- ret = soc_pcm_apply_symmetry(substream);
+ if (cpu_dai->active) {
+ ret = soc_pcm_apply_symmetry(substream, cpu_dai);
+ if (ret != 0)
+ goto config_err;
+ }
+
+ if (codec_dai->active) {
+ ret = soc_pcm_apply_symmetry(substream, codec_dai);
if (ret != 0)
goto config_err;
}
@@ -231,6 +278,11 @@ platform_err:
cpu_dai->driver->ops->shutdown(substream, cpu_dai);
out:
mutex_unlock(&rtd->pcm_mutex);
+
+ pm_runtime_put(platform->dev);
+ pm_runtime_put(codec_dai->dev);
+ pm_runtime_put(cpu_dai->dev);
+
return ret;
}
@@ -255,9 +307,8 @@ static void close_delayed_work(struct work_struct *work)
/* are we waiting on this codec DAI stream */
if (codec_dai->pop_wait == 1) {
codec_dai->pop_wait = 0;
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK,
+ codec_dai, SND_SOC_DAPM_STREAM_STOP);
}
mutex_unlock(&rtd->pcm_mutex);
@@ -290,8 +341,12 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
codec_dai->active--;
codec->active--;
- if (!cpu_dai->active && !codec_dai->active)
- rtd->rate = 0;
+ /* clear the corresponding DAIs rate when inactive */
+ if (!cpu_dai->active)
+ cpu_dai->rate = 0;
+
+ if (!codec_dai->active)
+ codec_dai->rate = 0;
/* Muting the DAC suppresses artifacts caused during digital
* shutdown, for example from stopping clocks.
@@ -313,18 +368,31 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
cpu_dai->runtime = NULL;
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* start delayed pop wq here for playback streams */
- codec_dai->pop_wait = 1;
- schedule_delayed_work(&rtd->delayed_work,
- msecs_to_jiffies(rtd->pmdown_time));
+ if (!rtd->pmdown_time || codec->ignore_pmdown_time ||
+ rtd->dai_link->ignore_pmdown_time) {
+ /* powered down playback stream now */
+ snd_soc_dapm_stream_event(rtd,
+ SNDRV_PCM_STREAM_PLAYBACK,
+ codec_dai,
+ SND_SOC_DAPM_STREAM_STOP);
+ } else {
+ /* start delayed pop wq here for playback streams */
+ codec_dai->pop_wait = 1;
+ schedule_delayed_work(&rtd->delayed_work,
+ msecs_to_jiffies(rtd->pmdown_time));
+ }
} else {
/* capture streams can be powered down now */
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_STOP);
+ snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_CAPTURE,
+ codec_dai, SND_SOC_DAPM_STREAM_STOP);
}
mutex_unlock(&rtd->pcm_mutex);
+
+ pm_runtime_put(platform->dev);
+ pm_runtime_put(codec_dai->dev);
+ pm_runtime_put(cpu_dai->dev);
+
return 0;
}
@@ -346,7 +414,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (rtd->dai_link->ops && rtd->dai_link->ops->prepare) {
ret = rtd->dai_link->ops->prepare(substream);
if (ret < 0) {
- printk(KERN_ERR "asoc: machine prepare error\n");
+ pr_err("asoc: machine prepare error: %d\n", ret);
goto out;
}
}
@@ -354,7 +422,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (platform->driver->ops && platform->driver->ops->prepare) {
ret = platform->driver->ops->prepare(substream);
if (ret < 0) {
- printk(KERN_ERR "asoc: platform prepare error\n");
+ dev_err(platform->dev, "platform prepare error: %d\n",
+ ret);
goto out;
}
}
@@ -362,7 +431,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (codec_dai->driver->ops->prepare) {
ret = codec_dai->driver->ops->prepare(substream, codec_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: codec DAI prepare error\n");
+ dev_err(codec_dai->dev, "DAI prepare error: %d\n",
+ ret);
goto out;
}
}
@@ -370,7 +440,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
if (cpu_dai->driver->ops->prepare) {
ret = cpu_dai->driver->ops->prepare(substream, cpu_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: cpu DAI prepare error\n");
+ dev_err(cpu_dai->dev, "DAI prepare error: %d\n",
+ ret);
goto out;
}
}
@@ -382,14 +453,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
cancel_delayed_work(&rtd->delayed_work);
}
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->playback.stream_name,
- SND_SOC_DAPM_STREAM_START);
- else
- snd_soc_dapm_stream_event(rtd,
- codec_dai->driver->capture.stream_name,
- SND_SOC_DAPM_STREAM_START);
+ snd_soc_dapm_stream_event(rtd, substream->stream, codec_dai,
+ SND_SOC_DAPM_STREAM_START);
snd_soc_dai_digital_mute(codec_dai, 0);
@@ -417,7 +482,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (rtd->dai_link->ops && rtd->dai_link->ops->hw_params) {
ret = rtd->dai_link->ops->hw_params(substream, params);
if (ret < 0) {
- printk(KERN_ERR "asoc: machine hw_params failed\n");
+ pr_err("asoc: machine hw_params failed: %d\n", ret);
goto out;
}
}
@@ -425,8 +490,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (codec_dai->driver->ops->hw_params) {
ret = codec_dai->driver->ops->hw_params(substream, params, codec_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: can't set codec %s hw params\n",
- codec_dai->name);
+ dev_err(codec_dai->dev, "can't set %s hw params: %d\n",
+ codec_dai->name, ret);
goto codec_err;
}
}
@@ -434,8 +499,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (cpu_dai->driver->ops->hw_params) {
ret = cpu_dai->driver->ops->hw_params(substream, params, cpu_dai);
if (ret < 0) {
- printk(KERN_ERR "asoc: interface %s hw params failed\n",
- cpu_dai->name);
+ dev_err(cpu_dai->dev, "%s hw params failed: %d\n",
+ cpu_dai->name, ret);
goto interface_err;
}
}
@@ -443,13 +508,15 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (platform->driver->ops && platform->driver->ops->hw_params) {
ret = platform->driver->ops->hw_params(substream, params);
if (ret < 0) {
- printk(KERN_ERR "asoc: platform %s hw params failed\n",
- platform->name);
+ dev_err(platform->dev, "%s hw params failed: %d\n",
+ platform->name, ret);
goto platform_err;
}
}
- rtd->rate = params_rate(params);
+ /* store the rate for each DAIs */
+ cpu_dai->rate = params_rate(params);
+ codec_dai->rate = params_rate(params);
out:
mutex_unlock(&rtd->pcm_mutex);
@@ -567,17 +634,6 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
return offset;
}
-/* ASoC PCM operations */
-static struct snd_pcm_ops soc_pcm_ops = {
- .open = soc_pcm_open,
- .close = soc_pcm_close,
- .hw_params = soc_pcm_hw_params,
- .hw_free = soc_pcm_hw_free,
- .prepare = soc_pcm_prepare,
- .trigger = soc_pcm_trigger,
- .pointer = soc_pcm_pointer,
-};
-
/* create a new pcm */
int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
{
@@ -585,10 +641,19 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
struct snd_soc_platform *platform = rtd->platform;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
+ struct snd_pcm_ops *soc_pcm_ops = &rtd->ops;
struct snd_pcm *pcm;
char new_name[64];
int ret = 0, playback = 0, capture = 0;
+ soc_pcm_ops->open = soc_pcm_open;
+ soc_pcm_ops->close = soc_pcm_close;
+ soc_pcm_ops->hw_params = soc_pcm_hw_params;
+ soc_pcm_ops->hw_free = soc_pcm_hw_free;
+ soc_pcm_ops->prepare = soc_pcm_prepare;
+ soc_pcm_ops->trigger = soc_pcm_trigger;
+ soc_pcm_ops->pointer = soc_pcm_pointer;
+
/* check client and interface hw capabilities */
snprintf(new_name, sizeof(new_name), "%s %s-%d",
rtd->dai_link->stream_name, codec_dai->name, num);
@@ -612,20 +677,20 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->pcm = pcm;
pcm->private_data = rtd;
if (platform->driver->ops) {
- soc_pcm_ops.mmap = platform->driver->ops->mmap;
- soc_pcm_ops.pointer = platform->driver->ops->pointer;
- soc_pcm_ops.ioctl = platform->driver->ops->ioctl;
- soc_pcm_ops.copy = platform->driver->ops->copy;
- soc_pcm_ops.silence = platform->driver->ops->silence;
- soc_pcm_ops.ack = platform->driver->ops->ack;
- soc_pcm_ops.page = platform->driver->ops->page;
+ soc_pcm_ops->mmap = platform->driver->ops->mmap;
+ soc_pcm_ops->pointer = platform->driver->ops->pointer;
+ soc_pcm_ops->ioctl = platform->driver->ops->ioctl;
+ soc_pcm_ops->copy = platform->driver->ops->copy;
+ soc_pcm_ops->silence = platform->driver->ops->silence;
+ soc_pcm_ops->ack = platform->driver->ops->ack;
+ soc_pcm_ops->page = platform->driver->ops->page;
}
if (playback)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, soc_pcm_ops);
if (capture)
- snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, soc_pcm_ops);
if (platform->driver->pcm_new) {
ret = platform->driver->pcm_new(rtd);
diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c
index ec921ec99c26..60053709e417 100644
--- a/sound/soc/soc-utils.c
+++ b/sound/soc/soc-utils.c
@@ -14,6 +14,7 @@
*/
#include <linux/platform_device.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -57,16 +58,63 @@ int snd_soc_params_to_bclk(struct snd_pcm_hw_params *params)
}
EXPORT_SYMBOL_GPL(snd_soc_params_to_bclk);
-static struct snd_soc_platform_driver dummy_platform;
+static const struct snd_pcm_hardware dummy_dma_hardware = {
+ .formats = 0xffffffff,
+ .channels_min = 1,
+ .channels_max = UINT_MAX,
+
+ /* Random values to keep userspace happy when checking constraints */
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
+ .buffer_bytes_max = 128*1024,
+ .period_bytes_min = PAGE_SIZE,
+ .period_bytes_max = PAGE_SIZE*2,
+ .periods_min = 2,
+ .periods_max = 128,
+};
+
+static int dummy_dma_open(struct snd_pcm_substream *substream)
+{
+ snd_soc_set_runtime_hwparams(substream, &dummy_dma_hardware);
+
+ return 0;
+}
+
+static struct snd_pcm_ops dummy_dma_ops = {
+ .open = dummy_dma_open,
+ .ioctl = snd_pcm_lib_ioctl,
+};
+
+static struct snd_soc_platform_driver dummy_platform = {
+ .ops = &dummy_dma_ops,
+};
+
+static struct snd_soc_codec_driver dummy_codec;
+static struct snd_soc_dai_driver dummy_dai = {
+ .name = "snd-soc-dummy-dai",
+};
static __devinit int snd_soc_dummy_probe(struct platform_device *pdev)
{
- return snd_soc_register_platform(&pdev->dev, &dummy_platform);
+ int ret;
+
+ ret = snd_soc_register_codec(&pdev->dev, &dummy_codec, &dummy_dai, 1);
+ if (ret < 0)
+ return ret;
+
+ ret = snd_soc_register_platform(&pdev->dev, &dummy_platform);
+ if (ret < 0) {
+ snd_soc_unregister_codec(&pdev->dev);
+ return ret;
+ }
+
+ return ret;
}
static __devexit int snd_soc_dummy_remove(struct platform_device *pdev)
{
snd_soc_unregister_platform(&pdev->dev);
+ snd_soc_unregister_codec(&pdev->dev);
return 0;
}
diff --git a/sound/soc/tegra/Kconfig b/sound/soc/tegra/Kconfig
index c6af1fd707f5..ce1b773c351f 100644
--- a/sound/soc/tegra/Kconfig
+++ b/sound/soc/tegra/Kconfig
@@ -47,3 +47,12 @@ config SND_SOC_TEGRA_TRIMSLICE
help
Say Y or M here if you want to add support for SoC audio on the
TrimSlice platform.
+
+config SND_SOC_TEGRA_ALC5632
+ tristate "SoC Audio support for Tegra boards using an ALC5632 codec"
+ depends on SND_SOC_TEGRA && I2C
+ select SND_SOC_TEGRA_I2S
+ select SND_SOC_ALC5632
+ help
+ Say Y or M here if you want to add support for SoC audio on the
+ Toshiba AC100 netbook.
diff --git a/sound/soc/tegra/Makefile b/sound/soc/tegra/Makefile
index 4d943b3fe150..8e584b8fcfba 100644
--- a/sound/soc/tegra/Makefile
+++ b/sound/soc/tegra/Makefile
@@ -14,6 +14,8 @@ obj-$(CONFIG_SND_SOC_TEGRA_SPDIF) += snd-soc-tegra-spdif.o
# Tegra machine Support
snd-soc-tegra-wm8903-objs := tegra_wm8903.o
snd-soc-tegra-trimslice-objs := trimslice.o
+snd-soc-tegra-alc5632-objs := tegra_alc5632.o
obj-$(CONFIG_SND_SOC_TEGRA_WM8903) += snd-soc-tegra-wm8903.o
obj-$(CONFIG_SND_SOC_TEGRA_TRIMSLICE) += snd-soc-tegra-trimslice.o
+obj-$(CONFIG_SND_SOC_TEGRA_ALC5632) += snd-soc-tegra-alc5632.o
diff --git a/sound/soc/tegra/tegra_alc5632.c b/sound/soc/tegra/tegra_alc5632.c
new file mode 100644
index 000000000000..e45ccd851f6a
--- /dev/null
+++ b/sound/soc/tegra/tegra_alc5632.c
@@ -0,0 +1,289 @@
+/*
+* tegra_alc5632.c -- Toshiba AC100(PAZ00) machine ASoC driver
+*
+* Copyright (C) 2011 The AC100 Kernel Team <ac100@lists.lauchpad.net>
+*
+* Authors: Leon Romanovsky <leon@leon.nu>
+* Andrey Danin <danindrey@mail.ru>
+* Marc Dietrich <marvin24@gmx.de>
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*/
+
+#include <asm/mach-types.h>
+
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/of_gpio.h>
+
+#include <sound/core.h>
+#include <sound/jack.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "../codecs/alc5632.h"
+
+#include "tegra_das.h"
+#include "tegra_i2s.h"
+#include "tegra_pcm.h"
+#include "tegra_asoc_utils.h"
+
+#define DRV_NAME "tegra-alc5632"
+
+#define GPIO_HP_DET BIT(0)
+
+struct tegra_alc5632 {
+ struct tegra_asoc_utils_data util_data;
+ struct platform_device *pcm_dev;
+ int gpio_requested;
+ int gpio_hp_det;
+};
+
+static int tegra_alc5632_asoc_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai *codec_dai = rtd->codec_dai;
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_card *card = codec->card;
+ struct tegra_alc5632 *alc5632 = snd_soc_card_get_drvdata(card);
+ int srate, mclk;
+ int err;
+
+ srate = params_rate(params);
+ mclk = 512 * srate;
+
+ err = tegra_asoc_utils_set_rate(&alc5632->util_data, srate, mclk);
+ if (err < 0) {
+ dev_err(card->dev, "Can't configure clocks\n");
+ return err;
+ }
+
+ err = snd_soc_dai_set_sysclk(codec_dai, 0, mclk,
+ SND_SOC_CLOCK_IN);
+ if (err < 0) {
+ dev_err(card->dev, "codec_dai clock not set\n");
+ return err;
+ }
+
+ return 0;
+}
+
+static struct snd_soc_ops tegra_alc5632_asoc_ops = {
+ .hw_params = tegra_alc5632_asoc_hw_params,
+};
+
+static struct snd_soc_jack tegra_alc5632_hs_jack;
+
+static struct snd_soc_jack_pin tegra_alc5632_hs_jack_pins[] = {
+ {
+ .pin = "Headset Mic",
+ .mask = SND_JACK_MICROPHONE,
+ },
+ {
+ .pin = "Headset Stereophone",
+ .mask = SND_JACK_HEADPHONE,
+ },
+};
+
+static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = {
+ .name = "Headset detection",
+ .report = SND_JACK_HEADSET,
+ .debounce_time = 150,
+ .invert = 1,
+};
+
+static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = {
+ SND_SOC_DAPM_SPK("Int Spk", NULL),
+ SND_SOC_DAPM_HP("Headset Stereophone", NULL),
+ SND_SOC_DAPM_MIC("Headset Mic", NULL),
+ SND_SOC_DAPM_MIC("Digital Mic", NULL),
+};
+
+static const struct snd_kcontrol_new tegra_alc5632_controls[] = {
+ SOC_DAPM_PIN_SWITCH("Int Spk"),
+};
+
+static int tegra_alc5632_asoc_init(struct snd_soc_pcm_runtime *rtd)
+{
+ struct snd_soc_codec *codec = rtd->codec;
+ struct snd_soc_dapm_context *dapm = &codec->dapm;
+ struct device_node *np = codec->card->dev->of_node;
+ struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(codec->card);
+
+ snd_soc_jack_new(codec, "Headset Jack", SND_JACK_HEADSET,
+ &tegra_alc5632_hs_jack);
+ snd_soc_jack_add_pins(&tegra_alc5632_hs_jack,
+ ARRAY_SIZE(tegra_alc5632_hs_jack_pins),
+ tegra_alc5632_hs_jack_pins);
+
+ machine->gpio_hp_det = of_get_named_gpio(np, "nvidia,hp-det-gpios", 0);
+
+ if (gpio_is_valid(machine->gpio_hp_det)) {
+ tegra_alc5632_hp_jack_gpio.gpio = machine->gpio_hp_det;
+ snd_soc_jack_add_gpios(&tegra_alc5632_hs_jack,
+ 1,
+ &tegra_alc5632_hp_jack_gpio);
+ machine->gpio_requested |= GPIO_HP_DET;
+ }
+
+ snd_soc_dapm_force_enable_pin(dapm, "MICBIAS1");
+
+ return 0;
+}
+
+static struct snd_soc_dai_link tegra_alc5632_dai = {
+ .name = "ALC5632",
+ .stream_name = "ALC5632 PCM",
+ .platform_name = "tegra-pcm-audio",
+ .codec_dai_name = "alc5632-hifi",
+ .init = tegra_alc5632_asoc_init,
+ .ops = &tegra_alc5632_asoc_ops,
+ .dai_fmt = SND_SOC_DAIFMT_I2S
+ | SND_SOC_DAIFMT_NB_NF
+ | SND_SOC_DAIFMT_CBS_CFS,
+};
+
+static struct snd_soc_card snd_soc_tegra_alc5632 = {
+ .name = "tegra-alc5632",
+ .owner = THIS_MODULE,
+ .dai_link = &tegra_alc5632_dai,
+ .num_links = 1,
+ .controls = tegra_alc5632_controls,
+ .num_controls = ARRAY_SIZE(tegra_alc5632_controls),
+ .dapm_widgets = tegra_alc5632_dapm_widgets,
+ .num_dapm_widgets = ARRAY_SIZE(tegra_alc5632_dapm_widgets),
+ .fully_routed = true,
+};
+
+static __devinit int tegra_alc5632_probe(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = &snd_soc_tegra_alc5632;
+ struct tegra_alc5632 *alc5632;
+ int ret;
+
+ alc5632 = devm_kzalloc(&pdev->dev,
+ sizeof(struct tegra_alc5632), GFP_KERNEL);
+ if (!alc5632) {
+ dev_err(&pdev->dev, "Can't allocate tegra_alc5632\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ card->dev = &pdev->dev;
+ platform_set_drvdata(pdev, card);
+ snd_soc_card_set_drvdata(card, alc5632);
+
+ alc5632->pcm_dev = ERR_PTR(-EINVAL);
+
+ if (!(pdev->dev.of_node)) {
+ dev_err(&pdev->dev, "Must be instantiated using device tree\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+ if (ret)
+ goto err;
+
+ ret = snd_soc_of_parse_audio_routing(card, "nvidia,audio-routing");
+ if (ret)
+ goto err;
+
+ tegra_alc5632_dai.codec_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,audio-codec", 0);
+
+ if (!tegra_alc5632_dai.codec_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,audio-codec' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_alc5632_dai.cpu_dai_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,i2s-controller", 0);
+ if (!tegra_alc5632_dai.cpu_dai_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,i2s-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ alc5632->pcm_dev = platform_device_register_simple(
+ "tegra-pcm-audio", -1, NULL, 0);
+ if (IS_ERR(alc5632->pcm_dev)) {
+ dev_err(&pdev->dev,
+ "Can't instantiate tegra-pcm-audio\n");
+ ret = PTR_ERR(alc5632->pcm_dev);
+ goto err;
+ }
+
+ ret = tegra_asoc_utils_init(&alc5632->util_data, &pdev->dev);
+ if (ret)
+ goto err_unregister;
+
+ ret = snd_soc_register_card(card);
+ if (ret) {
+ dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
+ ret);
+ goto err_fini_utils;
+ }
+
+ return 0;
+
+err_fini_utils:
+ tegra_asoc_utils_fini(&alc5632->util_data);
+err_unregister:
+ if (!IS_ERR(alc5632->pcm_dev))
+ platform_device_unregister(alc5632->pcm_dev);
+err:
+ return ret;
+}
+
+static int __devexit tegra_alc5632_remove(struct platform_device *pdev)
+{
+ struct snd_soc_card *card = platform_get_drvdata(pdev);
+ struct tegra_alc5632 *machine = snd_soc_card_get_drvdata(card);
+
+ if (machine->gpio_requested & GPIO_HP_DET)
+ snd_soc_jack_free_gpios(&tegra_alc5632_hs_jack,
+ 1,
+ &tegra_alc5632_hp_jack_gpio);
+ machine->gpio_requested = 0;
+
+ snd_soc_unregister_card(card);
+
+ tegra_asoc_utils_fini(&machine->util_data);
+ if (!IS_ERR(machine->pcm_dev))
+ platform_device_unregister(machine->pcm_dev);
+
+ return 0;
+}
+
+static const struct of_device_id tegra_alc5632_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra-audio-alc5632", },
+ {},
+};
+
+static struct platform_driver tegra_alc5632_driver = {
+ .driver = {
+ .name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .pm = &snd_soc_pm_ops,
+ .of_match_table = tegra_alc5632_of_match,
+ },
+ .probe = tegra_alc5632_probe,
+ .remove = __devexit_p(tegra_alc5632_remove),
+};
+module_platform_driver(tegra_alc5632_driver);
+
+MODULE_AUTHOR("Leon Romanovsky <leon@leon.nu>");
+MODULE_DESCRIPTION("Tegra+ALC5632 machine ASoC driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_alc5632_of_match);
diff --git a/sound/soc/tegra/tegra_asoc_utils.c b/sound/soc/tegra/tegra_asoc_utils.c
index dfa85cbb05c8..f8428e410e05 100644
--- a/sound/soc/tegra/tegra_asoc_utils.c
+++ b/sound/soc/tegra/tegra_asoc_utils.c
@@ -24,6 +24,7 @@
#include <linux/device.h>
#include <linux/err.h>
#include <linux/kernel.h>
+#include <linux/module.h>
#include "tegra_asoc_utils.h"
diff --git a/sound/soc/tegra/tegra_das.c b/sound/soc/tegra/tegra_das.c
index 9f24ef73f2cb..3b3c1ba4d235 100644
--- a/sound/soc/tegra/tegra_das.c
+++ b/sound/soc/tegra/tegra_das.c
@@ -172,11 +172,11 @@ static int __devinit tegra_das_probe(struct platform_device *pdev)
if (das)
return -ENODEV;
- das = kzalloc(sizeof(struct tegra_das), GFP_KERNEL);
+ das = devm_kzalloc(&pdev->dev, sizeof(struct tegra_das), GFP_KERNEL);
if (!das) {
dev_err(&pdev->dev, "Can't allocate tegra_das\n");
ret = -ENOMEM;
- goto exit;
+ goto err;
}
das->dev = &pdev->dev;
@@ -184,22 +184,35 @@ static int __devinit tegra_das_probe(struct platform_device *pdev)
if (!res) {
dev_err(&pdev->dev, "No memory resource\n");
ret = -ENODEV;
- goto err_free;
+ goto err;
}
- region = request_mem_region(res->start, resource_size(res),
- pdev->name);
+ region = devm_request_mem_region(&pdev->dev, res->start,
+ resource_size(res), pdev->name);
if (!region) {
dev_err(&pdev->dev, "Memory region already claimed\n");
ret = -EBUSY;
- goto err_free;
+ goto err;
}
- das->regs = ioremap(res->start, resource_size(res));
+ das->regs = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!das->regs) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENOMEM;
- goto err_release;
+ goto err;
+ }
+
+ ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1,
+ TEGRA_DAS_DAP_SEL_DAC1);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't set up DAS DAP connection\n");
+ goto err;
+ }
+ ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1,
+ TEGRA_DAS_DAC_SEL_DAP1);
+ if (ret) {
+ dev_err(&pdev->dev, "Can't set up DAS DAC connection\n");
+ goto err;
}
tegra_das_debug_add(das);
@@ -208,58 +221,41 @@ static int __devinit tegra_das_probe(struct platform_device *pdev)
return 0;
-err_release:
- release_mem_region(res->start, resource_size(res));
-err_free:
- kfree(das);
- das = 0;
-exit:
+err:
+ das = NULL;
return ret;
}
static int __devexit tegra_das_remove(struct platform_device *pdev)
{
- struct resource *res;
-
if (!das)
return -ENODEV;
- platform_set_drvdata(pdev, NULL);
-
tegra_das_debug_remove(das);
- iounmap(das->regs);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
- kfree(das);
- das = 0;
+ das = NULL;
return 0;
}
+static const struct of_device_id tegra_das_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra20-das", },
+ {},
+};
+
static struct platform_driver tegra_das_driver = {
.probe = tegra_das_probe,
.remove = __devexit_p(tegra_das_remove),
.driver = {
.name = DRV_NAME,
+ .owner = THIS_MODULE,
+ .of_match_table = tegra_das_of_match,
},
};
-
-static int __init tegra_das_modinit(void)
-{
- return platform_driver_register(&tegra_das_driver);
-}
-module_init(tegra_das_modinit);
-
-static void __exit tegra_das_modexit(void)
-{
- platform_driver_unregister(&tegra_das_driver);
-}
-module_exit(tegra_das_modexit);
+module_platform_driver(tegra_das_driver);
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra DAS driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_das_of_match);
diff --git a/sound/soc/tegra/tegra_i2s.c b/sound/soc/tegra/tegra_i2s.c
index f36b9969cfec..33509de52540 100644
--- a/sound/soc/tegra/tegra_i2s.c
+++ b/sound/soc/tegra/tegra_i2s.c
@@ -36,13 +36,13 @@
#include <linux/seq_file.h>
#include <linux/slab.h>
#include <linux/io.h>
+#include <linux/of.h>
#include <mach/iomap.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
-#include "tegra_das.h"
#include "tegra_i2s.h"
#define DRV_NAME "tegra-i2s"
@@ -99,13 +99,11 @@ static const struct file_operations tegra_i2s_debug_fops = {
.release = single_release,
};
-static void tegra_i2s_debug_add(struct tegra_i2s *i2s, int id)
+static void tegra_i2s_debug_add(struct tegra_i2s *i2s)
{
- char name[] = DRV_NAME ".0";
-
- snprintf(name, sizeof(name), DRV_NAME".%1d", id);
- i2s->debug = debugfs_create_file(name, S_IRUGO, snd_soc_debugfs_root,
- i2s, &tegra_i2s_debug_fops);
+ i2s->debug = debugfs_create_file(i2s->dai.name, S_IRUGO,
+ snd_soc_debugfs_root, i2s,
+ &tegra_i2s_debug_fops);
}
static void tegra_i2s_debug_remove(struct tegra_i2s *i2s)
@@ -306,93 +304,54 @@ static int tegra_i2s_probe(struct snd_soc_dai *dai)
return 0;
}
-static struct snd_soc_dai_ops tegra_i2s_dai_ops = {
+static const struct snd_soc_dai_ops tegra_i2s_dai_ops = {
.set_fmt = tegra_i2s_set_fmt,
.hw_params = tegra_i2s_hw_params,
.trigger = tegra_i2s_trigger,
};
-struct snd_soc_dai_driver tegra_i2s_dai[] = {
- {
- .name = DRV_NAME ".0",
- .probe = tegra_i2s_probe,
- .playback = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_96000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .capture = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_96000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .ops = &tegra_i2s_dai_ops,
- .symmetric_rates = 1,
+static const struct snd_soc_dai_driver tegra_i2s_dai_template = {
+ .probe = tegra_i2s_probe,
+ .playback = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
},
- {
- .name = DRV_NAME ".1",
- .probe = tegra_i2s_probe,
- .playback = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_96000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .capture = {
- .channels_min = 2,
- .channels_max = 2,
- .rates = SNDRV_PCM_RATE_8000_96000,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .ops = &tegra_i2s_dai_ops,
- .symmetric_rates = 1,
+ .capture = {
+ .channels_min = 2,
+ .channels_max = 2,
+ .rates = SNDRV_PCM_RATE_8000_96000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
},
+ .ops = &tegra_i2s_dai_ops,
+ .symmetric_rates = 1,
};
static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
{
struct tegra_i2s * i2s;
struct resource *mem, *memregion, *dmareq;
+ u32 of_dma[2];
+ u32 dma_ch;
int ret;
- if ((pdev->id < 0) ||
- (pdev->id >= ARRAY_SIZE(tegra_i2s_dai))) {
- dev_err(&pdev->dev, "ID %d out of range\n", pdev->id);
- return -EINVAL;
- }
-
- /*
- * FIXME: Until a codec driver exists for the tegra DAS, hard-code a
- * 1:1 mapping between audio controllers and audio ports.
- */
- ret = tegra_das_connect_dap_to_dac(TEGRA_DAS_DAP_ID_1 + pdev->id,
- TEGRA_DAS_DAP_SEL_DAC1 + pdev->id);
- if (ret) {
- dev_err(&pdev->dev, "Can't set up DAP connection\n");
- return ret;
- }
- ret = tegra_das_connect_dac_to_dap(TEGRA_DAS_DAC_ID_1 + pdev->id,
- TEGRA_DAS_DAC_SEL_DAP1 + pdev->id);
- if (ret) {
- dev_err(&pdev->dev, "Can't set up DAC connection\n");
- return ret;
- }
-
- i2s = kzalloc(sizeof(struct tegra_i2s), GFP_KERNEL);
+ i2s = devm_kzalloc(&pdev->dev, sizeof(struct tegra_i2s), GFP_KERNEL);
if (!i2s) {
dev_err(&pdev->dev, "Can't allocate tegra_i2s\n");
ret = -ENOMEM;
- goto exit;
+ goto err;
}
dev_set_drvdata(&pdev->dev, i2s);
+ i2s->dai = tegra_i2s_dai_template;
+ i2s->dai.name = dev_name(&pdev->dev);
+
i2s->clk_i2s = clk_get(&pdev->dev, NULL);
if (IS_ERR(i2s->clk_i2s)) {
dev_err(&pdev->dev, "Can't retrieve i2s clock\n");
ret = PTR_ERR(i2s->clk_i2s);
- goto err_free;
+ goto err;
}
mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -404,104 +363,93 @@ static __devinit int tegra_i2s_platform_probe(struct platform_device *pdev)
dmareq = platform_get_resource(pdev, IORESOURCE_DMA, 0);
if (!dmareq) {
- dev_err(&pdev->dev, "No DMA resource\n");
- ret = -ENODEV;
- goto err_clk_put;
+ if (of_property_read_u32_array(pdev->dev.of_node,
+ "nvidia,dma-request-selector",
+ of_dma, 2) < 0) {
+ dev_err(&pdev->dev, "No DMA resource\n");
+ ret = -ENODEV;
+ goto err_clk_put;
+ }
+ dma_ch = of_dma[1];
+ } else {
+ dma_ch = dmareq->start;
}
- memregion = request_mem_region(mem->start, resource_size(mem),
- DRV_NAME);
+ memregion = devm_request_mem_region(&pdev->dev, mem->start,
+ resource_size(mem), DRV_NAME);
if (!memregion) {
dev_err(&pdev->dev, "Memory region already claimed\n");
ret = -EBUSY;
goto err_clk_put;
}
- i2s->regs = ioremap(mem->start, resource_size(mem));
+ i2s->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
if (!i2s->regs) {
dev_err(&pdev->dev, "ioremap failed\n");
ret = -ENOMEM;
- goto err_release;
+ goto err_clk_put;
}
i2s->capture_dma_data.addr = mem->start + TEGRA_I2S_FIFO2;
i2s->capture_dma_data.wrap = 4;
i2s->capture_dma_data.width = 32;
- i2s->capture_dma_data.req_sel = dmareq->start;
+ i2s->capture_dma_data.req_sel = dma_ch;
i2s->playback_dma_data.addr = mem->start + TEGRA_I2S_FIFO1;
i2s->playback_dma_data.wrap = 4;
i2s->playback_dma_data.width = 32;
- i2s->playback_dma_data.req_sel = dmareq->start;
+ i2s->playback_dma_data.req_sel = dma_ch;
i2s->reg_ctrl = TEGRA_I2S_CTRL_FIFO_FORMAT_PACKED;
- ret = snd_soc_register_dai(&pdev->dev, &tegra_i2s_dai[pdev->id]);
+ ret = snd_soc_register_dai(&pdev->dev, &i2s->dai);
if (ret) {
dev_err(&pdev->dev, "Could not register DAI: %d\n", ret);
ret = -ENOMEM;
- goto err_unmap;
+ goto err_clk_put;
}
- tegra_i2s_debug_add(i2s, pdev->id);
+ tegra_i2s_debug_add(i2s);
return 0;
-err_unmap:
- iounmap(i2s->regs);
-err_release:
- release_mem_region(mem->start, resource_size(mem));
err_clk_put:
clk_put(i2s->clk_i2s);
-err_free:
- kfree(i2s);
-exit:
+err:
return ret;
}
static int __devexit tegra_i2s_platform_remove(struct platform_device *pdev)
{
struct tegra_i2s *i2s = dev_get_drvdata(&pdev->dev);
- struct resource *res;
snd_soc_unregister_dai(&pdev->dev);
tegra_i2s_debug_remove(i2s);
- iounmap(i2s->regs);
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- release_mem_region(res->start, resource_size(res));
-
clk_put(i2s->clk_i2s);
- kfree(i2s);
-
return 0;
}
+static const struct of_device_id tegra_i2s_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra20-i2s", },
+ {},
+};
+
static struct platform_driver tegra_i2s_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
+ .of_match_table = tegra_i2s_of_match,
},
.probe = tegra_i2s_platform_probe,
.remove = __devexit_p(tegra_i2s_platform_remove),
};
-
-static int __init snd_tegra_i2s_init(void)
-{
- return platform_driver_register(&tegra_i2s_driver);
-}
-module_init(snd_tegra_i2s_init);
-
-static void __exit snd_tegra_i2s_exit(void)
-{
- platform_driver_unregister(&tegra_i2s_driver);
-}
-module_exit(snd_tegra_i2s_exit);
+module_platform_driver(tegra_i2s_driver);
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra I2S ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_i2s_of_match);
diff --git a/sound/soc/tegra/tegra_i2s.h b/sound/soc/tegra/tegra_i2s.h
index 2b38a096f46c..15ce1e2e8bde 100644
--- a/sound/soc/tegra/tegra_i2s.h
+++ b/sound/soc/tegra/tegra_i2s.h
@@ -153,6 +153,7 @@
#define TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_TWELVE_SLOTS (TEGRA_I2S_FIFO_ATN_LVL_TWELVE_SLOTS << TEGRA_I2S_FIFO_SCR_FIFO1_ATN_LVL_SHIFT)
struct tegra_i2s {
+ struct snd_soc_dai_driver dai;
struct clk *clk_i2s;
int clk_refs;
struct tegra_pcm_dma_params capture_dma_data;
diff --git a/sound/soc/tegra/tegra_pcm.c b/sound/soc/tegra/tegra_pcm.c
index c7cfd96e991e..8b4457137c7c 100644
--- a/sound/soc/tegra/tegra_pcm.c
+++ b/sound/soc/tegra/tegra_pcm.c
@@ -330,23 +330,22 @@ static u64 tegra_dma_mask = DMA_BIT_MASK(32);
static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
{
struct snd_card *card = rtd->card->snd_card;
- struct snd_soc_dai *dai = rtd->cpu_dai;
struct snd_pcm *pcm = rtd->pcm;
int ret = 0;
if (!card->dev->dma_mask)
card->dev->dma_mask = &tegra_dma_mask;
if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
+ card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
- if (dai->driver->playback.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_PLAYBACK);
if (ret)
goto err;
}
- if (dai->driver->capture.channels_min) {
+ if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
ret = tegra_pcm_preallocate_dma_buffer(pcm,
SNDRV_PCM_STREAM_CAPTURE);
if (ret)
@@ -367,7 +366,7 @@ static void tegra_pcm_free(struct snd_pcm *pcm)
tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
}
-struct snd_soc_platform_driver tegra_pcm_platform = {
+static struct snd_soc_platform_driver tegra_pcm_platform = {
.ops = &tegra_pcm_ops,
.pcm_new = tegra_pcm_new,
.pcm_free = tegra_pcm_free,
@@ -392,18 +391,7 @@ static struct platform_driver tegra_pcm_driver = {
.probe = tegra_pcm_platform_probe,
.remove = __devexit_p(tegra_pcm_platform_remove),
};
-
-static int __init snd_tegra_pcm_init(void)
-{
- return platform_driver_register(&tegra_pcm_driver);
-}
-module_init(snd_tegra_pcm_init);
-
-static void __exit snd_tegra_pcm_exit(void)
-{
- platform_driver_unregister(&tegra_pcm_driver);
-}
-module_exit(snd_tegra_pcm_exit);
+module_platform_driver(tegra_pcm_driver);
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra PCM ASoC driver");
diff --git a/sound/soc/tegra/tegra_spdif.c b/sound/soc/tegra/tegra_spdif.c
index abe606b0a29e..475428cf270e 100644
--- a/sound/soc/tegra/tegra_spdif.c
+++ b/sound/soc/tegra/tegra_spdif.c
@@ -127,7 +127,7 @@ static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
{
struct device *dev = substream->pcm->card->dev;
struct tegra_spdif *spdif = snd_soc_dai_get_drvdata(dai);
- int ret, srate, spdifclock;
+ int ret, spdifclock;
spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_PACK;
spdif->reg_ctrl &= ~TEGRA_SPDIF_CTRL_BIT_MODE_MASK;
@@ -140,7 +140,6 @@ static int tegra_spdif_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- srate = params_rate(params);
switch (params_rate(params)) {
case 32000:
spdifclock = 4096000;
@@ -227,12 +226,12 @@ static int tegra_spdif_probe(struct snd_soc_dai *dai)
return 0;
}
-static struct snd_soc_dai_ops tegra_spdif_dai_ops = {
+static const struct snd_soc_dai_ops tegra_spdif_dai_ops = {
.hw_params = tegra_spdif_hw_params,
.trigger = tegra_spdif_trigger,
};
-struct snd_soc_dai_driver tegra_spdif_dai = {
+static struct snd_soc_dai_driver tegra_spdif_dai = {
.name = DRV_NAME,
.probe = tegra_spdif_probe,
.playback = {
@@ -353,17 +352,7 @@ static struct platform_driver tegra_spdif_driver = {
.remove = __devexit_p(tegra_spdif_platform_remove),
};
-static int __init snd_tegra_spdif_init(void)
-{
- return platform_driver_register(&tegra_spdif_driver);
-}
-module_init(snd_tegra_spdif_init);
-
-static void __exit snd_tegra_spdif_exit(void)
-{
- platform_driver_unregister(&tegra_spdif_driver);
-}
-module_exit(snd_tegra_spdif_exit);
+module_platform_driver(tegra_spdif_driver);
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra SPDIF ASoC driver");
diff --git a/sound/soc/tegra/tegra_wm8903.c b/sound/soc/tegra/tegra_wm8903.c
index be27f1d229af..566655e23b7d 100644
--- a/sound/soc/tegra/tegra_wm8903.c
+++ b/sound/soc/tegra/tegra_wm8903.c
@@ -34,6 +34,7 @@
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/gpio.h>
+#include <linux/of_gpio.h>
#include <mach/tegra_wm8903_pdata.h>
@@ -59,8 +60,9 @@
#define GPIO_HP_DET BIT(4)
struct tegra_wm8903 {
+ struct tegra_wm8903_platform_data pdata;
+ struct platform_device *pcm_dev;
struct tegra_asoc_utils_data util_data;
- struct tegra_wm8903_platform_data *pdata;
int gpio_requested;
};
@@ -160,7 +162,7 @@ static int tegra_wm8903_event_int_spk(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_wm8903_platform_data *pdata = &machine->pdata;
if (!(machine->gpio_requested & GPIO_SPKR_EN))
return 0;
@@ -177,7 +179,7 @@ static int tegra_wm8903_event_hp(struct snd_soc_dapm_widget *w,
struct snd_soc_dapm_context *dapm = w->dapm;
struct snd_soc_card *card = dapm->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_wm8903_platform_data *pdata = &machine->pdata;
if (!(machine->gpio_requested & GPIO_HP_MUTE))
return 0;
@@ -201,8 +203,8 @@ static const struct snd_soc_dapm_route harmony_audio_map[] = {
{"Int Spk", NULL, "RON"},
{"Int Spk", NULL, "LOP"},
{"Int Spk", NULL, "LON"},
- {"Mic Bias", NULL, "Mic Jack"},
- {"IN1L", NULL, "Mic Bias"},
+ {"Mic Jack", NULL, "MICBIAS"},
+ {"IN1L", NULL, "Mic Jack"},
};
static const struct snd_soc_dapm_route seaboard_audio_map[] = {
@@ -212,8 +214,8 @@ static const struct snd_soc_dapm_route seaboard_audio_map[] = {
{"Int Spk", NULL, "RON"},
{"Int Spk", NULL, "LOP"},
{"Int Spk", NULL, "LON"},
- {"Mic Bias", NULL, "Mic Jack"},
- {"IN1R", NULL, "Mic Bias"},
+ {"Mic Jack", NULL, "MICBIAS"},
+ {"IN1R", NULL, "Mic Jack"},
};
static const struct snd_soc_dapm_route kaen_audio_map[] = {
@@ -223,8 +225,8 @@ static const struct snd_soc_dapm_route kaen_audio_map[] = {
{"Int Spk", NULL, "RON"},
{"Int Spk", NULL, "LOP"},
{"Int Spk", NULL, "LON"},
- {"Mic Bias", NULL, "Mic Jack"},
- {"IN2R", NULL, "Mic Bias"},
+ {"Mic Jack", NULL, "MICBIAS"},
+ {"IN2R", NULL, "Mic Jack"},
};
static const struct snd_soc_dapm_route aebl_audio_map[] = {
@@ -232,8 +234,8 @@ static const struct snd_soc_dapm_route aebl_audio_map[] = {
{"Headphone Jack", NULL, "HPOUTL"},
{"Int Spk", NULL, "LINEOUTR"},
{"Int Spk", NULL, "LINEOUTL"},
- {"Mic Bias", NULL, "Mic Jack"},
- {"IN1R", NULL, "Mic Bias"},
+ {"Mic Jack", NULL, "MICBIAS"},
+ {"IN1R", NULL, "Mic Jack"},
};
static const struct snd_kcontrol_new tegra_wm8903_controls[] = {
@@ -246,9 +248,36 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
struct snd_soc_dapm_context *dapm = &codec->dapm;
struct snd_soc_card *card = codec->card;
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_wm8903_platform_data *pdata = &machine->pdata;
+ struct device_node *np = card->dev->of_node;
int ret;
+ if (card->dev->platform_data) {
+ memcpy(pdata, card->dev->platform_data, sizeof(*pdata));
+ } else if (np) {
+ /*
+ * This part must be in init() rather than probe() in order to
+ * guarantee that the WM8903 has been probed, and hence its
+ * GPIO controller registered, which is a pre-condition for
+ * of_get_named_gpio() to be able to map the phandles in the
+ * properties to the controller node. Given this, all
+ * pdata handling is in init() for consistency.
+ */
+ pdata->gpio_spkr_en = of_get_named_gpio(np,
+ "nvidia,spkr-en-gpios", 0);
+ pdata->gpio_hp_mute = of_get_named_gpio(np,
+ "nvidia,hp-mute-gpios", 0);
+ pdata->gpio_hp_det = of_get_named_gpio(np,
+ "nvidia,hp-det-gpios", 0);
+ pdata->gpio_int_mic_en = of_get_named_gpio(np,
+ "nvidia,int-mic-en-gpios", 0);
+ pdata->gpio_ext_mic_en = of_get_named_gpio(np,
+ "nvidia,ext-mic-en-gpios", 0);
+ } else {
+ dev_err(card->dev, "No platform data supplied\n");
+ return -EINVAL;
+ }
+
if (gpio_is_valid(pdata->gpio_spkr_en)) {
ret = gpio_request(pdata->gpio_spkr_en, "spkr_en");
if (ret) {
@@ -316,30 +345,7 @@ static int tegra_wm8903_init(struct snd_soc_pcm_runtime *rtd)
wm8903_mic_detect(codec, &tegra_wm8903_mic_jack, SND_JACK_MICROPHONE,
0);
- snd_soc_dapm_force_enable_pin(dapm, "Mic Bias");
-
- /* FIXME: Calculate automatically based on DAPM routes? */
- if (!machine_is_harmony())
- snd_soc_dapm_nc_pin(dapm, "IN1L");
- if (!machine_is_seaboard() && !machine_is_aebl())
- snd_soc_dapm_nc_pin(dapm, "IN1R");
- snd_soc_dapm_nc_pin(dapm, "IN2L");
- if (!machine_is_kaen())
- snd_soc_dapm_nc_pin(dapm, "IN2R");
- snd_soc_dapm_nc_pin(dapm, "IN3L");
- snd_soc_dapm_nc_pin(dapm, "IN3R");
-
- if (machine_is_aebl()) {
- snd_soc_dapm_nc_pin(dapm, "LON");
- snd_soc_dapm_nc_pin(dapm, "RON");
- snd_soc_dapm_nc_pin(dapm, "ROP");
- snd_soc_dapm_nc_pin(dapm, "LOP");
- } else {
- snd_soc_dapm_nc_pin(dapm, "LINEOUTR");
- snd_soc_dapm_nc_pin(dapm, "LINEOUTL");
- }
-
- snd_soc_dapm_sync(dapm);
+ snd_soc_dapm_force_enable_pin(dapm, "MICBIAS");
return 0;
}
@@ -357,6 +363,7 @@ static struct snd_soc_dai_link tegra_wm8903_dai = {
static struct snd_soc_card snd_soc_tegra_wm8903 = {
.name = "tegra-wm8903",
+ .owner = THIS_MODULE,
.dai_link = &tegra_wm8903_dai,
.num_links = 1,
@@ -364,51 +371,91 @@ static struct snd_soc_card snd_soc_tegra_wm8903 = {
.num_controls = ARRAY_SIZE(tegra_wm8903_controls),
.dapm_widgets = tegra_wm8903_dapm_widgets,
.num_dapm_widgets = ARRAY_SIZE(tegra_wm8903_dapm_widgets),
+ .fully_routed = true,
};
static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
{
struct snd_soc_card *card = &snd_soc_tegra_wm8903;
struct tegra_wm8903 *machine;
- struct tegra_wm8903_platform_data *pdata;
int ret;
- pdata = pdev->dev.platform_data;
- if (!pdata) {
+ if (!pdev->dev.platform_data && !pdev->dev.of_node) {
dev_err(&pdev->dev, "No platform data supplied\n");
return -EINVAL;
}
- machine = kzalloc(sizeof(struct tegra_wm8903), GFP_KERNEL);
+ machine = devm_kzalloc(&pdev->dev, sizeof(struct tegra_wm8903),
+ GFP_KERNEL);
if (!machine) {
dev_err(&pdev->dev, "Can't allocate tegra_wm8903 struct\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err;
}
-
- machine->pdata = pdata;
-
- ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
- if (ret)
- goto err_free_machine;
+ machine->pcm_dev = ERR_PTR(-EINVAL);
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
snd_soc_card_set_drvdata(card, machine);
- if (machine_is_harmony()) {
- card->dapm_routes = harmony_audio_map;
- card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
- } else if (machine_is_seaboard()) {
- card->dapm_routes = seaboard_audio_map;
- card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map);
- } else if (machine_is_kaen()) {
- card->dapm_routes = kaen_audio_map;
- card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map);
+ if (pdev->dev.of_node) {
+ ret = snd_soc_of_parse_card_name(card, "nvidia,model");
+ if (ret)
+ goto err;
+
+ ret = snd_soc_of_parse_audio_routing(card,
+ "nvidia,audio-routing");
+ if (ret)
+ goto err;
+
+ tegra_wm8903_dai.codec_name = NULL;
+ tegra_wm8903_dai.codec_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,audio-codec", 0);
+ if (!tegra_wm8903_dai.codec_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,audio-codec' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ tegra_wm8903_dai.cpu_dai_name = NULL;
+ tegra_wm8903_dai.cpu_dai_of_node = of_parse_phandle(
+ pdev->dev.of_node, "nvidia,i2s-controller", 0);
+ if (!tegra_wm8903_dai.cpu_dai_of_node) {
+ dev_err(&pdev->dev,
+ "Property 'nvidia,i2s-controller' missing or invalid\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ machine->pcm_dev = platform_device_register_simple(
+ "tegra-pcm-audio", -1, NULL, 0);
+ if (IS_ERR(machine->pcm_dev)) {
+ dev_err(&pdev->dev,
+ "Can't instantiate tegra-pcm-audio\n");
+ ret = PTR_ERR(machine->pcm_dev);
+ goto err;
+ }
} else {
- card->dapm_routes = aebl_audio_map;
- card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map);
+ if (machine_is_harmony()) {
+ card->dapm_routes = harmony_audio_map;
+ card->num_dapm_routes = ARRAY_SIZE(harmony_audio_map);
+ } else if (machine_is_seaboard()) {
+ card->dapm_routes = seaboard_audio_map;
+ card->num_dapm_routes = ARRAY_SIZE(seaboard_audio_map);
+ } else if (machine_is_kaen()) {
+ card->dapm_routes = kaen_audio_map;
+ card->num_dapm_routes = ARRAY_SIZE(kaen_audio_map);
+ } else {
+ card->dapm_routes = aebl_audio_map;
+ card->num_dapm_routes = ARRAY_SIZE(aebl_audio_map);
+ }
}
+ ret = tegra_asoc_utils_init(&machine->util_data, &pdev->dev);
+ if (ret)
+ goto err_unregister;
+
ret = snd_soc_register_card(card);
if (ret) {
dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n",
@@ -420,8 +467,10 @@ static __devinit int tegra_wm8903_driver_probe(struct platform_device *pdev)
err_fini_utils:
tegra_asoc_utils_fini(&machine->util_data);
-err_free_machine:
- kfree(machine);
+err_unregister:
+ if (!IS_ERR(machine->pcm_dev))
+ platform_device_unregister(machine->pcm_dev);
+err:
return ret;
}
@@ -429,7 +478,7 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
{
struct snd_soc_card *card = platform_get_drvdata(pdev);
struct tegra_wm8903 *machine = snd_soc_card_get_drvdata(card);
- struct tegra_wm8903_platform_data *pdata = machine->pdata;
+ struct tegra_wm8903_platform_data *pdata = &machine->pdata;
if (machine->gpio_requested & GPIO_HP_DET)
snd_soc_jack_free_gpios(&tegra_wm8903_hp_jack,
@@ -448,35 +497,31 @@ static int __devexit tegra_wm8903_driver_remove(struct platform_device *pdev)
snd_soc_unregister_card(card);
tegra_asoc_utils_fini(&machine->util_data);
-
- kfree(machine);
+ if (!IS_ERR(machine->pcm_dev))
+ platform_device_unregister(machine->pcm_dev);
return 0;
}
+static const struct of_device_id tegra_wm8903_of_match[] __devinitconst = {
+ { .compatible = "nvidia,tegra-audio-wm8903", },
+ {},
+};
+
static struct platform_driver tegra_wm8903_driver = {
.driver = {
.name = DRV_NAME,
.owner = THIS_MODULE,
.pm = &snd_soc_pm_ops,
+ .of_match_table = tegra_wm8903_of_match,
},
.probe = tegra_wm8903_driver_probe,
.remove = __devexit_p(tegra_wm8903_driver_remove),
};
-
-static int __init tegra_wm8903_modinit(void)
-{
- return platform_driver_register(&tegra_wm8903_driver);
-}
-module_init(tegra_wm8903_modinit);
-
-static void __exit tegra_wm8903_modexit(void)
-{
- platform_driver_unregister(&tegra_wm8903_driver);
-}
-module_exit(tegra_wm8903_modexit);
+module_platform_driver(tegra_wm8903_driver);
MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
MODULE_DESCRIPTION("Tegra+WM8903 machine ASoC driver");
MODULE_LICENSE("GPL");
MODULE_ALIAS("platform:" DRV_NAME);
+MODULE_DEVICE_TABLE(of, tegra_wm8903_of_match);
diff --git a/sound/soc/tegra/trimslice.c b/sound/soc/tegra/trimslice.c
index 8fc07e9adf2e..2bdfc550cff8 100644
--- a/sound/soc/tegra/trimslice.c
+++ b/sound/soc/tegra/trimslice.c
@@ -115,20 +115,6 @@ static const struct snd_soc_dapm_route trimslice_audio_map[] = {
{"RLINEIN", NULL, "Line In"},
};
-static int trimslice_asoc_init(struct snd_soc_pcm_runtime *rtd)
-{
- struct snd_soc_codec *codec = rtd->codec;
- struct snd_soc_dapm_context *dapm = &codec->dapm;
-
- snd_soc_dapm_nc_pin(dapm, "LHPOUT");
- snd_soc_dapm_nc_pin(dapm, "RHPOUT");
- snd_soc_dapm_nc_pin(dapm, "MICIN");
-
- snd_soc_dapm_sync(dapm);
-
- return 0;
-}
-
static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
.name = "TLV320AIC23",
.stream_name = "AIC23",
@@ -136,12 +122,12 @@ static struct snd_soc_dai_link trimslice_tlv320aic23_dai = {
.platform_name = "tegra-pcm-audio",
.cpu_dai_name = "tegra-i2s.0",
.codec_dai_name = "tlv320aic23-hifi",
- .init = trimslice_asoc_init,
.ops = &trimslice_asoc_ops,
};
static struct snd_soc_card snd_soc_trimslice = {
.name = "tegra-trimslice",
+ .owner = THIS_MODULE,
.dai_link = &trimslice_tlv320aic23_dai,
.num_links = 1,
@@ -149,6 +135,7 @@ static struct snd_soc_card snd_soc_trimslice = {
.num_dapm_widgets = ARRAY_SIZE(trimslice_dapm_widgets),
.dapm_routes = trimslice_audio_map,
.num_dapm_routes = ARRAY_SIZE(trimslice_audio_map),
+ .fully_routed = true,
};
static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
@@ -157,15 +144,17 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
struct tegra_trimslice *trimslice;
int ret;
- trimslice = kzalloc(sizeof(struct tegra_trimslice), GFP_KERNEL);
+ trimslice = devm_kzalloc(&pdev->dev, sizeof(struct tegra_trimslice),
+ GFP_KERNEL);
if (!trimslice) {
dev_err(&pdev->dev, "Can't allocate tegra_trimslice\n");
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto err;
}
ret = tegra_asoc_utils_init(&trimslice->util_data, &pdev->dev);
if (ret)
- goto err_free_trimslice;
+ goto err;
card->dev = &pdev->dev;
platform_set_drvdata(pdev, card);
@@ -182,8 +171,7 @@ static __devinit int tegra_snd_trimslice_probe(struct platform_device *pdev)
err_fini_utils:
tegra_asoc_utils_fini(&trimslice->util_data);
-err_free_trimslice:
- kfree(trimslice);
+err:
return ret;
}
@@ -196,8 +184,6 @@ static int __devexit tegra_snd_trimslice_remove(struct platform_device *pdev)
tegra_asoc_utils_fini(&trimslice->util_data);
- kfree(trimslice);
-
return 0;
}
@@ -209,18 +195,7 @@ static struct platform_driver tegra_snd_trimslice_driver = {
.probe = tegra_snd_trimslice_probe,
.remove = __devexit_p(tegra_snd_trimslice_remove),
};
-
-static int __init snd_tegra_trimslice_init(void)
-{
- return platform_driver_register(&tegra_snd_trimslice_driver);
-}
-module_init(snd_tegra_trimslice_init);
-
-static void __exit snd_tegra_trimslice_exit(void)
-{
- platform_driver_unregister(&tegra_snd_trimslice_driver);
-}
-module_exit(snd_tegra_trimslice_exit);
+module_platform_driver(tegra_snd_trimslice_driver);
MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
MODULE_DESCRIPTION("Trimslice machine ASoC driver");
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c
index 743d07b82c06..28db4ca997ca 100644
--- a/sound/soc/txx9/txx9aclc-ac97.c
+++ b/sound/soc/txx9/txx9aclc-ac97.c
@@ -201,7 +201,7 @@ static int __devinit txx9aclc_ac97_dev_probe(struct platform_device *pdev)
if (!drvdata->base)
return -EBUSY;
err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq,
- IRQF_DISABLED, dev_name(&pdev->dev), drvdata);
+ 0, dev_name(&pdev->dev), drvdata);
if (err < 0)
return err;
@@ -223,18 +223,7 @@ static struct platform_driver txx9aclc_ac97_driver = {
},
};
-static int __init txx9aclc_ac97_init(void)
-{
- return platform_driver_register(&txx9aclc_ac97_driver);
-}
-
-static void __exit txx9aclc_ac97_exit(void)
-{
- platform_driver_unregister(&txx9aclc_ac97_driver);
-}
-
-module_init(txx9aclc_ac97_init);
-module_exit(txx9aclc_ac97_exit);
+module_platform_driver(txx9aclc_ac97_driver);
MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
MODULE_DESCRIPTION("TXx9 ACLC AC97 driver");
diff --git a/sound/soc/txx9/txx9aclc-generic.c b/sound/soc/txx9/txx9aclc-generic.c
index 6770e7166be4..b056a1431ed4 100644
--- a/sound/soc/txx9/txx9aclc-generic.c
+++ b/sound/soc/txx9/txx9aclc-generic.c
@@ -32,6 +32,7 @@ static struct snd_soc_dai_link txx9aclc_generic_dai = {
static struct snd_soc_card txx9aclc_generic_card = {
.name = "Generic TXx9 ACLC Audio",
+ .owner = THIS_MODULE,
.dai_link = &txx9aclc_generic_dai,
.num_links = 1,
};
@@ -62,7 +63,7 @@ static int __exit txx9aclc_generic_remove(struct platform_device *pdev)
}
static struct platform_driver txx9aclc_generic_driver = {
- .remove = txx9aclc_generic_remove,
+ .remove = __exit_p(txx9aclc_generic_remove),
.driver = {
.name = "txx9aclc-generic",
.owner = THIS_MODULE,
diff --git a/sound/soc/txx9/txx9aclc.c b/sound/soc/txx9/txx9aclc.c
index 3de99af8cb82..21554611557c 100644
--- a/sound/soc/txx9/txx9aclc.c
+++ b/sound/soc/txx9/txx9aclc.c
@@ -134,7 +134,7 @@ txx9aclc_dma_submit(struct txx9aclc_dmadata *dmadata, dma_addr_t buf_dma_addr)
sg_dma_address(&sg) = buf_dma_addr;
desc = chan->device->device_prep_slave_sg(chan, &sg, 1,
dmadata->substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
- DMA_TO_DEVICE : DMA_FROM_DEVICE,
+ DMA_MEM_TO_DEV : DMA_DEV_TO_MEM,
DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
if (!desc) {
dev_err(&chan->dev->device, "cannot prepare slave dma\n");
@@ -438,17 +438,7 @@ static struct platform_driver txx9aclc_pcm_driver = {
.remove = __devexit_p(txx9aclc_soc_platform_remove),
};
-static int __init snd_txx9aclc_pcm_init(void)
-{
- return platform_driver_register(&txx9aclc_pcm_driver);
-}
-module_init(snd_txx9aclc_pcm_init);
-
-static void __exit snd_txx9aclc_pcm_exit(void)
-{
- platform_driver_unregister(&txx9aclc_pcm_driver);
-}
-module_exit(snd_txx9aclc_pcm_exit);
+module_platform_driver(txx9aclc_pcm_driver);
MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
MODULE_DESCRIPTION("TXx9 ACLC Audio DMA driver");
diff --git a/sound/sound_core.c b/sound/sound_core.c
index 6ce277860fd7..c6e81fb928e9 100644
--- a/sound/sound_core.c
+++ b/sound/sound_core.c
@@ -29,7 +29,7 @@ MODULE_DESCRIPTION("Core sound module");
MODULE_AUTHOR("Alan Cox");
MODULE_LICENSE("GPL");
-static char *sound_devnode(struct device *dev, mode_t *mode)
+static char *sound_devnode(struct device *dev, umode_t *mode)
{
if (MAJOR(dev->devt) == SOUND_MAJOR)
return NULL;
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
index ad7d4d7d9237..b63b3a86d3f4 100644
--- a/sound/sparc/amd7930.c
+++ b/sound/sparc/amd7930.c
@@ -50,7 +50,7 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Sun AMD7930 soundcard.");
@@ -962,7 +962,7 @@ static int __devinit snd_amd7930_create(struct snd_card *card,
amd7930_idle(amd);
if (request_irq(irq, snd_amd7930_interrupt,
- IRQF_DISABLED | IRQF_SHARED, "amd7930", amd)) {
+ IRQF_SHARED, "amd7930", amd)) {
snd_printk(KERN_ERR "amd7930-%d: Unable to grab IRQ %d\n",
dev, irq);
snd_amd7930_free(amd);
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
index 0e618f82808c..f2eabd3f22fd 100644
--- a/sound/sparc/cs4231.c
+++ b/sound/sparc/cs4231.c
@@ -40,7 +40,7 @@
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
/* Enable this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard.");
@@ -2118,15 +2118,4 @@ static struct platform_driver cs4231_driver = {
.remove = __devexit_p(cs4231_remove),
};
-static int __init cs4231_init(void)
-{
- return platform_driver_register(&cs4231_driver);
-}
-
-static void __exit cs4231_exit(void)
-{
- platform_driver_unregister(&cs4231_driver);
-}
-
-module_init(cs4231_init);
-module_exit(cs4231_exit);
+module_platform_driver(cs4231_driver);
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 1b839a0f3653..a6b0deb77746 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -70,6 +70,7 @@
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/atomic.h>
+#include <linux/module.h>
MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets");
MODULE_DESCRIPTION("Sun DBRI");
@@ -79,7 +80,7 @@ MODULE_SUPPORTED_DEVICE("{{Sun,DBRI}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
/* Enable this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard.");
@@ -2696,16 +2697,4 @@ static struct platform_driver dbri_sbus_driver = {
.remove = __devexit_p(dbri_remove),
};
-/* Probe for the dbri chip and then attach the driver. */
-static int __init dbri_init(void)
-{
- return platform_driver_register(&dbri_sbus_driver);
-}
-
-static void __exit dbri_exit(void)
-{
- platform_driver_unregister(&dbri_sbus_driver);
-}
-
-module_init(dbri_init);
-module_exit(dbri_exit);
+module_platform_driver(dbri_sbus_driver);
diff --git a/sound/spi/at73c213.c b/sound/spi/at73c213.c
index 4dd051bdf4fd..c6500d00053b 100644
--- a/sound/spi/at73c213.c
+++ b/sound/spi/at73c213.c
@@ -1112,17 +1112,7 @@ static struct spi_driver at73c213_driver = {
.remove = __devexit_p(snd_at73c213_remove),
};
-static int __init at73c213_init(void)
-{
- return spi_register_driver(&at73c213_driver);
-}
-module_init(at73c213_init);
-
-static void __exit at73c213_exit(void)
-{
- spi_unregister_driver(&at73c213_driver);
-}
-module_exit(at73c213_exit);
+module_spi_driver(at73c213_driver);
MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>");
MODULE_DESCRIPTION("Sound driver for AT73C213 with Atmel SSC");
diff --git a/sound/synth/emux/emux.c b/sound/synth/emux/emux.c
index f16a3fce4597..93522072bc87 100644
--- a/sound/synth/emux/emux.c
+++ b/sound/synth/emux/emux.c
@@ -24,6 +24,7 @@
#include <sound/core.h>
#include <sound/emux_synth.h>
#include <linux/init.h>
+#include <linux/module.h>
#include "emux_voice.h"
MODULE_AUTHOR("Takashi Iwai");
diff --git a/sound/synth/emux/emux_oss.c b/sound/synth/emux/emux_oss.c
index 87e42206c4ef..319754cf6208 100644
--- a/sound/synth/emux/emux_oss.c
+++ b/sound/synth/emux/emux_oss.c
@@ -25,6 +25,7 @@
#ifdef CONFIG_SND_SEQUENCER_OSS
+#include <linux/export.h>
#include <asm/uaccess.h>
#include <sound/core.h>
#include "emux_voice.h"
diff --git a/sound/synth/emux/emux_seq.c b/sound/synth/emux/emux_seq.c
index ca5f7effb4df..7778b8e19782 100644
--- a/sound/synth/emux/emux_seq.c
+++ b/sound/synth/emux/emux_seq.c
@@ -21,7 +21,7 @@
#include "emux_voice.h"
#include <linux/slab.h>
-
+#include <linux/module.h>
/* Prototypes for static functions */
static void free_port(void *private);
diff --git a/sound/synth/emux/emux_synth.c b/sound/synth/emux/emux_synth.c
index 3e921b386fd5..9a38de459acb 100644
--- a/sound/synth/emux/emux_synth.c
+++ b/sound/synth/emux/emux_synth.c
@@ -22,6 +22,7 @@
*
*/
+#include <linux/export.h>
#include "emux_voice.h"
#include <sound/asoundef.h>
diff --git a/sound/synth/emux/soundfont.c b/sound/synth/emux/soundfont.c
index 67c91230c197..1137b85c36e6 100644
--- a/sound/synth/emux/soundfont.c
+++ b/sound/synth/emux/soundfont.c
@@ -27,6 +27,7 @@
*/
#include <asm/uaccess.h>
#include <linux/slab.h>
+#include <linux/export.h>
#include <sound/core.h>
#include <sound/soundfont.h>
#include <sound/seq_oss_legacy.h>
diff --git a/sound/synth/util_mem.c b/sound/synth/util_mem.c
index c85522e3808d..8e34bc4e07ec 100644
--- a/sound/synth/util_mem.c
+++ b/sound/synth/util_mem.c
@@ -21,6 +21,7 @@
#include <linux/mutex.h>
#include <linux/init.h>
#include <linux/slab.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/util_mem.h>
diff --git a/sound/usb/6fire/chip.c b/sound/usb/6fire/chip.c
index c7dca7b0b9fe..fc8cc823e438 100644
--- a/sound/usb/6fire/chip.c
+++ b/sound/usb/6fire/chip.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
@@ -29,13 +28,13 @@
#include <sound/initval.h>
MODULE_AUTHOR("Torsten Schenk <torsten.schenk@zoho.com>");
-MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver, version 0.3.0");
+MODULE_DESCRIPTION("TerraTec DMX 6Fire USB audio driver");
MODULE_LICENSE("GPL v2");
MODULE_SUPPORTED_DEVICE("{{TerraTec, DMX 6Fire USB}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable card */
static struct sfire_chip *chips[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
static struct usb_device *devices[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
@@ -211,22 +210,11 @@ static struct usb_device_id device_table[] = {
MODULE_DEVICE_TABLE(usb, device_table);
-static struct usb_driver driver = {
+static struct usb_driver usb_driver = {
.name = "snd-usb-6fire",
.probe = usb6fire_chip_probe,
.disconnect = usb6fire_chip_disconnect,
.id_table = device_table,
};
-static int __init usb6fire_chip_init(void)
-{
- return usb_register(&driver);
-}
-
-static void __exit usb6fire_chip_cleanup(void)
-{
- usb_deregister(&driver);
-}
-
-module_init(usb6fire_chip_init);
-module_exit(usb6fire_chip_cleanup);
+module_usb_driver(usb_driver);
diff --git a/sound/usb/6fire/chip.h b/sound/usb/6fire/chip.h
index d11e5cb520f0..bde02d105a51 100644
--- a/sound/usb/6fire/chip.h
+++ b/sound/usb/6fire/chip.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/comm.c b/sound/usb/6fire/comm.c
index c994daa57af2..6c3d531a250e 100644
--- a/sound/usb/6fire/comm.c
+++ b/sound/usb/6fire/comm.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/comm.h b/sound/usb/6fire/comm.h
index edc5dc84b888..d2af0a5ddcf3 100644
--- a/sound/usb/6fire/comm.h
+++ b/sound/usb/6fire/comm.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/common.h b/sound/usb/6fire/common.h
index 7dbeb4a37831..b6eb03ed1c2c 100644
--- a/sound/usb/6fire/common.h
+++ b/sound/usb/6fire/common.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/control.c b/sound/usb/6fire/control.c
index ac828eff1a63..07ed914d5e71 100644
--- a/sound/usb/6fire/control.c
+++ b/sound/usb/6fire/control.c
@@ -5,9 +5,12 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
+ * Thanks to:
+ * - Holger Ruckdeschel: he found out how to control individual channel
+ * volumes and introduced mute switch
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -16,6 +19,7 @@
#include <linux/interrupt.h>
#include <sound/control.h>
+#include <sound/tlv.h>
#include "control.h"
#include "comm.h"
@@ -25,26 +29,6 @@ static char *opt_coax_texts[2] = { "Optical", "Coax" };
static char *line_phono_texts[2] = { "Line", "Phono" };
/*
- * calculated with $value\[i\] = 128 \cdot sqrt[3]{\frac{i}{128}}$
- * this is done because the linear values cause rapid degredation
- * of volume in the uppermost region.
- */
-static const u8 log_volume_table[128] = {
- 0x00, 0x19, 0x20, 0x24, 0x28, 0x2b, 0x2e, 0x30, 0x32, 0x34,
- 0x36, 0x38, 0x3a, 0x3b, 0x3d, 0x3e, 0x40, 0x41, 0x42, 0x43,
- 0x44, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e,
- 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x53, 0x54, 0x55, 0x56,
- 0x56, 0x57, 0x58, 0x58, 0x59, 0x5a, 0x5b, 0x5b, 0x5c, 0x5c,
- 0x5d, 0x5e, 0x5e, 0x5f, 0x60, 0x60, 0x61, 0x61, 0x62, 0x62,
- 0x63, 0x63, 0x64, 0x65, 0x65, 0x66, 0x66, 0x67, 0x67, 0x68,
- 0x68, 0x69, 0x69, 0x6a, 0x6a, 0x6b, 0x6b, 0x6c, 0x6c, 0x6c,
- 0x6d, 0x6d, 0x6e, 0x6e, 0x6f, 0x6f, 0x70, 0x70, 0x70, 0x71,
- 0x71, 0x72, 0x72, 0x73, 0x73, 0x73, 0x74, 0x74, 0x75, 0x75,
- 0x75, 0x76, 0x76, 0x77, 0x77, 0x77, 0x78, 0x78, 0x78, 0x79,
- 0x79, 0x7a, 0x7a, 0x7a, 0x7b, 0x7b, 0x7b, 0x7c, 0x7c, 0x7c,
- 0x7d, 0x7d, 0x7d, 0x7e, 0x7e, 0x7e, 0x7f, 0x7f };
-
-/*
* data that needs to be sent to device. sets up card internal stuff.
* values dumped from windows driver and filtered by trial'n'error.
*/
@@ -59,7 +43,7 @@ init_data[] = {
{ 0x22, 0x03, 0x00 }, { 0x20, 0x03, 0x08 }, { 0x22, 0x04, 0x00 },
{ 0x20, 0x04, 0x08 }, { 0x22, 0x05, 0x01 }, { 0x20, 0x05, 0x08 },
{ 0x22, 0x04, 0x01 }, { 0x12, 0x04, 0x00 }, { 0x12, 0x05, 0x00 },
- { 0x12, 0x0d, 0x78 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
+ { 0x12, 0x0d, 0x38 }, { 0x12, 0x21, 0x82 }, { 0x12, 0x22, 0x80 },
{ 0x12, 0x23, 0x00 }, { 0x12, 0x06, 0x02 }, { 0x12, 0x03, 0x00 },
{ 0x12, 0x02, 0x00 }, { 0x22, 0x03, 0x01 },
{ 0 } /* TERMINATING ENTRY */
@@ -70,20 +54,47 @@ static const int rates_altsetting[] = { 1, 1, 2, 2, 3, 3 };
static const u16 rates_6fire_vl[] = {0x00, 0x01, 0x00, 0x01, 0x00, 0x01};
static const u16 rates_6fire_vh[] = {0x11, 0x11, 0x10, 0x10, 0x00, 0x00};
+static DECLARE_TLV_DB_MINMAX(tlv_output, -9000, 0);
+static DECLARE_TLV_DB_MINMAX(tlv_input, -1500, 1500);
+
enum {
DIGITAL_THRU_ONLY_SAMPLERATE = 3
};
-static void usb6fire_control_master_vol_update(struct control_runtime *rt)
+static void usb6fire_control_output_vol_update(struct control_runtime *rt)
{
struct comm_runtime *comm_rt = rt->chip->comm;
- if (comm_rt) {
- /* set volume */
- comm_rt->write8(comm_rt, 0x12, 0x0f, 0x7f -
- log_volume_table[rt->master_vol]);
- /* unmute */
- comm_rt->write8(comm_rt, 0x12, 0x0e, 0x00);
- }
+ int i;
+
+ if (comm_rt)
+ for (i = 0; i < 6; i++)
+ if (!(rt->ovol_updated & (1 << i))) {
+ comm_rt->write8(comm_rt, 0x12, 0x0f + i,
+ 180 - rt->output_vol[i]);
+ rt->ovol_updated |= 1 << i;
+ }
+}
+
+static void usb6fire_control_output_mute_update(struct control_runtime *rt)
+{
+ struct comm_runtime *comm_rt = rt->chip->comm;
+
+ if (comm_rt)
+ comm_rt->write8(comm_rt, 0x12, 0x0e, ~rt->output_mute);
+}
+
+static void usb6fire_control_input_vol_update(struct control_runtime *rt)
+{
+ struct comm_runtime *comm_rt = rt->chip->comm;
+ int i;
+
+ if (comm_rt)
+ for (i = 0; i < 2; i++)
+ if (!(rt->ivol_updated & (1 << i))) {
+ comm_rt->write8(comm_rt, 0x12, 0x1c + i,
+ rt->input_vol[i] & 0x3f);
+ rt->ivol_updated |= 1 << i;
+ }
}
static void usb6fire_control_line_phono_update(struct control_runtime *rt)
@@ -165,34 +176,147 @@ static int usb6fire_control_streaming_update(struct control_runtime *rt)
return -EINVAL;
}
-static int usb6fire_control_master_vol_info(struct snd_kcontrol *kcontrol,
+static int usb6fire_control_output_vol_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
+ uinfo->count = 2;
uinfo->value.integer.min = 0;
- uinfo->value.integer.max = 127;
+ uinfo->value.integer.max = 180;
return 0;
}
-static int usb6fire_control_master_vol_put(struct snd_kcontrol *kcontrol,
+static int usb6fire_control_output_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+ unsigned int ch = kcontrol->private_value;
int changed = 0;
- if (rt->master_vol != ucontrol->value.integer.value[0]) {
- rt->master_vol = ucontrol->value.integer.value[0];
- usb6fire_control_master_vol_update(rt);
+
+ if (ch > 4) {
+ snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ return -EINVAL;
+ }
+
+ if (rt->output_vol[ch] != ucontrol->value.integer.value[0]) {
+ rt->output_vol[ch] = ucontrol->value.integer.value[0];
+ rt->ovol_updated &= ~(1 << ch);
changed = 1;
}
+ if (rt->output_vol[ch + 1] != ucontrol->value.integer.value[1]) {
+ rt->output_vol[ch + 1] = ucontrol->value.integer.value[1];
+ rt->ovol_updated &= ~(2 << ch);
+ changed = 1;
+ }
+
+ if (changed)
+ usb6fire_control_output_vol_update(rt);
+
return changed;
}
-static int usb6fire_control_master_vol_get(struct snd_kcontrol *kcontrol,
+static int usb6fire_control_output_vol_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
- ucontrol->value.integer.value[0] = rt->master_vol;
+ unsigned int ch = kcontrol->private_value;
+
+ if (ch > 4) {
+ snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = rt->output_vol[ch];
+ ucontrol->value.integer.value[1] = rt->output_vol[ch + 1];
+ return 0;
+}
+
+static int usb6fire_control_output_mute_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+ unsigned int ch = kcontrol->private_value;
+ u8 old = rt->output_mute;
+ u8 value = 0;
+
+ if (ch > 4) {
+ snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ return -EINVAL;
+ }
+
+ rt->output_mute &= ~(3 << ch);
+ if (ucontrol->value.integer.value[0])
+ value |= 1;
+ if (ucontrol->value.integer.value[1])
+ value |= 2;
+ rt->output_mute |= value << ch;
+
+ if (rt->output_mute != old)
+ usb6fire_control_output_mute_update(rt);
+
+ return rt->output_mute != old;
+}
+
+static int usb6fire_control_output_mute_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+ unsigned int ch = kcontrol->private_value;
+ u8 value = rt->output_mute >> ch;
+
+ if (ch > 4) {
+ snd_printk(KERN_ERR PREFIX "Invalid channel in volume control.");
+ return -EINVAL;
+ }
+
+ ucontrol->value.integer.value[0] = 1 & value;
+ value >>= 1;
+ ucontrol->value.integer.value[1] = 1 & value;
+
+ return 0;
+}
+
+static int usb6fire_control_input_vol_info(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_info *uinfo)
+{
+ uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+ uinfo->count = 2;
+ uinfo->value.integer.min = 0;
+ uinfo->value.integer.max = 30;
+ return 0;
+}
+
+static int usb6fire_control_input_vol_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+ int changed = 0;
+
+ if (rt->input_vol[0] != ucontrol->value.integer.value[0]) {
+ rt->input_vol[0] = ucontrol->value.integer.value[0] - 15;
+ rt->ivol_updated &= ~(1 << 0);
+ changed = 1;
+ }
+ if (rt->input_vol[1] != ucontrol->value.integer.value[1]) {
+ rt->input_vol[1] = ucontrol->value.integer.value[1] - 15;
+ rt->ivol_updated &= ~(1 << 1);
+ changed = 1;
+ }
+
+ if (changed)
+ usb6fire_control_input_vol_update(rt);
+
+ return changed;
+}
+
+static int usb6fire_control_input_vol_get(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct control_runtime *rt = snd_kcontrol_chip(kcontrol);
+
+ ucontrol->value.integer.value[0] = rt->input_vol[0] + 15;
+ ucontrol->value.integer.value[1] = rt->input_vol[1] + 15;
+
return 0;
}
@@ -287,18 +411,83 @@ static int usb6fire_control_digital_thru_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static struct __devinitdata snd_kcontrol_new elements[] = {
+static struct __devinitdata snd_kcontrol_new vol_elements[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Volume",
+ .name = "Analog Playback Volume",
.index = 0,
+ .private_value = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = usb6fire_control_output_vol_info,
+ .get = usb6fire_control_output_vol_get,
+ .put = usb6fire_control_output_vol_put,
+ .tlv = { .p = tlv_output }
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Volume",
+ .index = 1,
+ .private_value = 2,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = usb6fire_control_output_vol_info,
+ .get = usb6fire_control_output_vol_get,
+ .put = usb6fire_control_output_vol_put,
+ .tlv = { .p = tlv_output }
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Volume",
+ .index = 2,
+ .private_value = 4,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = usb6fire_control_output_vol_info,
+ .get = usb6fire_control_output_vol_get,
+ .put = usb6fire_control_output_vol_put,
+ .tlv = { .p = tlv_output }
+ },
+ {}
+};
+
+static struct __devinitdata snd_kcontrol_new mute_elements[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Switch",
+ .index = 0,
+ .private_value = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ctl_boolean_stereo_info,
+ .get = usb6fire_control_output_mute_get,
+ .put = usb6fire_control_output_mute_put,
+ },
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Switch",
+ .index = 1,
+ .private_value = 2,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
- .info = usb6fire_control_master_vol_info,
- .get = usb6fire_control_master_vol_get,
- .put = usb6fire_control_master_vol_put
+ .info = snd_ctl_boolean_stereo_info,
+ .get = usb6fire_control_output_mute_get,
+ .put = usb6fire_control_output_mute_put,
},
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Playback Switch",
+ .index = 2,
+ .private_value = 4,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
+ .info = snd_ctl_boolean_stereo_info,
+ .get = usb6fire_control_output_mute_get,
+ .put = usb6fire_control_output_mute_put,
+ },
+ {}
+};
+
+static struct __devinitdata snd_kcontrol_new elements[] = {
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Line/Phono Capture Route",
.index = 0,
.access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
@@ -324,9 +513,54 @@ static struct __devinitdata snd_kcontrol_new elements[] = {
.get = usb6fire_control_digital_thru_get,
.put = usb6fire_control_digital_thru_put
},
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Analog Capture Volume",
+ .index = 0,
+ .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+ SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+ .info = usb6fire_control_input_vol_info,
+ .get = usb6fire_control_input_vol_get,
+ .put = usb6fire_control_input_vol_put,
+ .tlv = { .p = tlv_input }
+ },
{}
};
+static int usb6fire_control_add_virtual(
+ struct control_runtime *rt,
+ struct snd_card *card,
+ char *name,
+ struct snd_kcontrol_new *elems)
+{
+ int ret;
+ int i;
+ struct snd_kcontrol *vmaster =
+ snd_ctl_make_virtual_master(name, tlv_output);
+ struct snd_kcontrol *control;
+
+ if (!vmaster)
+ return -ENOMEM;
+ ret = snd_ctl_add(card, vmaster);
+ if (ret < 0)
+ return ret;
+
+ i = 0;
+ while (elems[i].name) {
+ control = snd_ctl_new1(&elems[i], rt);
+ if (!control)
+ return -ENOMEM;
+ ret = snd_ctl_add(card, control);
+ if (ret < 0)
+ return ret;
+ ret = snd_ctl_add_slave(vmaster, control);
+ if (ret < 0)
+ return ret;
+ i++;
+ }
+ return 0;
+}
+
int __devinit usb6fire_control_init(struct sfire_chip *chip)
{
int i;
@@ -352,9 +586,26 @@ int __devinit usb6fire_control_init(struct sfire_chip *chip)
usb6fire_control_opt_coax_update(rt);
usb6fire_control_line_phono_update(rt);
- usb6fire_control_master_vol_update(rt);
+ usb6fire_control_output_vol_update(rt);
+ usb6fire_control_output_mute_update(rt);
+ usb6fire_control_input_vol_update(rt);
usb6fire_control_streaming_update(rt);
+ ret = usb6fire_control_add_virtual(rt, chip->card,
+ "Master Playback Volume", vol_elements);
+ if (ret) {
+ snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+ kfree(rt);
+ return ret;
+ }
+ ret = usb6fire_control_add_virtual(rt, chip->card,
+ "Master Playback Switch", mute_elements);
+ if (ret) {
+ snd_printk(KERN_ERR PREFIX "cannot add control.\n");
+ kfree(rt);
+ return ret;
+ }
+
i = 0;
while (elements[i].name) {
ret = snd_ctl_add(chip->card, snd_ctl_new1(&elements[i], rt));
diff --git a/sound/usb/6fire/control.h b/sound/usb/6fire/control.h
index 8f5aeead2e3d..9a596d95474a 100644
--- a/sound/usb/6fire/control.h
+++ b/sound/usb/6fire/control.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
@@ -44,7 +43,11 @@ struct control_runtime {
bool line_phono_switch;
bool digital_thru_switch;
bool usb_streaming;
- u8 master_vol;
+ u8 output_vol[6];
+ u8 ovol_updated;
+ u8 output_mute;
+ s8 input_vol[2];
+ u8 ivol_updated;
};
int __devinit usb6fire_control_init(struct sfire_chip *chip);
diff --git a/sound/usb/6fire/firmware.c b/sound/usb/6fire/firmware.c
index 1e3ae3327dd3..6f9715ab32fe 100644
--- a/sound/usb/6fire/firmware.c
+++ b/sound/usb/6fire/firmware.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
@@ -15,7 +14,9 @@
*/
#include <linux/firmware.h>
+#include <linux/module.h>
#include <linux/bitrev.h>
+#include <linux/kernel.h>
#include "firmware.h"
#include "chip.h"
@@ -59,21 +60,19 @@ struct ihex_record {
unsigned int txt_offset; /* current position in txt_data */
};
-static u8 usb6fire_fw_ihex_nibble(const u8 n)
-{
- if (n >= '0' && n <= '9')
- return n - '0';
- else if (n >= 'A' && n <= 'F')
- return n - ('A' - 10);
- else if (n >= 'a' && n <= 'f')
- return n - ('a' - 10);
- return 0;
-}
-
static u8 usb6fire_fw_ihex_hex(const u8 *data, u8 *crc)
{
- u8 val = (usb6fire_fw_ihex_nibble(data[0]) << 4) |
- usb6fire_fw_ihex_nibble(data[1]);
+ u8 val = 0;
+ int hval;
+
+ hval = hex_to_bin(data[0]);
+ if (hval >= 0)
+ val |= (hval << 4);
+
+ hval = hex_to_bin(data[1]);
+ if (hval >= 0)
+ val |= hval;
+
*crc += val;
return val;
}
diff --git a/sound/usb/6fire/midi.c b/sound/usb/6fire/midi.c
index 13f4509dce2b..f0e5179b242b 100644
--- a/sound/usb/6fire/midi.c
+++ b/sound/usb/6fire/midi.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/midi.h b/sound/usb/6fire/midi.h
index 97a7bf669135..5114eccc1d8e 100644
--- a/sound/usb/6fire/midi.h
+++ b/sound/usb/6fire/midi.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/pcm.c b/sound/usb/6fire/pcm.c
index d144cdb2f159..c97d05f0e966 100644
--- a/sound/usb/6fire/pcm.c
+++ b/sound/usb/6fire/pcm.c
@@ -5,7 +5,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/6fire/pcm.h b/sound/usb/6fire/pcm.h
index 2bee81374002..3104301b257d 100644
--- a/sound/usb/6fire/pcm.h
+++ b/sound/usb/6fire/pcm.h
@@ -3,7 +3,6 @@
*
* Author: Torsten Schenk <torsten.schenk@zoho.com>
* Created: Jan 01, 2011
- * Version: 0.3.0
* Copyright: (C) Torsten Schenk
*
* This program is free software; you can redistribute it and/or modify
diff --git a/sound/usb/Kconfig b/sound/usb/Kconfig
index 8beb77563da2..ff77b28f3da1 100644
--- a/sound/usb/Kconfig
+++ b/sound/usb/Kconfig
@@ -67,6 +67,7 @@ config SND_USB_CAIAQ
* Native Instruments Guitar Rig mobile
* Native Instruments Traktor Kontrol X1
* Native Instruments Traktor Kontrol S4
+ * Native Instruments Maschine Controller
To compile this driver as a module, choose M here: the module
will be called snd-usb-caiaq.
@@ -85,6 +86,7 @@ config SND_USB_CAIAQ_INPUT
* Native Instruments Kore Controller 2
* Native Instruments Audio Kontrol 1
* Native Instruments Traktor Kontrol S4
+ * Native Instruments Maschine Controller
config SND_USB_US122L
tristate "Tascam US-122L USB driver"
@@ -104,6 +106,7 @@ config SND_USB_6FIRE
select BITREVERSE
select SND_RAWMIDI
select SND_PCM
+ select SND_VMASTER
help
Say Y here to include support for TerraTec 6fire DMX USB interface.
diff --git a/sound/usb/Makefile b/sound/usb/Makefile
index cf9ed66445fa..ac256dc4c6be 100644
--- a/sound/usb/Makefile
+++ b/sound/usb/Makefile
@@ -3,16 +3,16 @@
#
snd-usb-audio-objs := card.o \
+ clock.o \
+ endpoint.o \
+ format.o \
+ helper.o \
mixer.o \
mixer_quirks.o \
+ pcm.o \
proc.o \
quirks.o \
- format.o \
- endpoint.o \
- urb.o \
- pcm.o \
- helper.o \
- clock.o
+ stream.o
snd-usbmidi-lib-objs := midi.o
diff --git a/sound/usb/caiaq/audio.c b/sound/usb/caiaq/audio.c
index 2cf87f5afed4..fde9a7a29cb6 100644
--- a/sound/usb/caiaq/audio.c
+++ b/sound/usb/caiaq/audio.c
@@ -311,8 +311,10 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
spin_lock(&dev->spinlock);
- if (dev->input_panic || dev->output_panic)
+ if (dev->input_panic || dev->output_panic) {
ptr = SNDRV_PCM_POS_XRUN;
+ goto unlock;
+ }
if (sub->stream == SNDRV_PCM_STREAM_PLAYBACK)
ptr = bytes_to_frames(sub->runtime,
@@ -321,6 +323,7 @@ snd_usb_caiaq_pcm_pointer(struct snd_pcm_substream *sub)
ptr = bytes_to_frames(sub->runtime,
dev->audio_in_buf_pos[index]);
+unlock:
spin_unlock(&dev->spinlock);
return ptr;
}
diff --git a/sound/usb/caiaq/device.c b/sound/usb/caiaq/device.c
index 45bc4a2dc6f0..64aed432ae22 100644
--- a/sound/usb/caiaq/device.c
+++ b/sound/usb/caiaq/device.c
@@ -50,11 +50,12 @@ MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
"{Native Instruments, Session I/O},"
"{Native Instruments, GuitarRig mobile}"
"{Native Instruments, Traktor Kontrol X1}"
- "{Native Instruments, Traktor Kontrol S4}");
+ "{Native Instruments, Traktor Kontrol S4}"
+ "{Native Instruments, Maschine Controller}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
static int snd_card_used[SNDRV_CARDS];
module_param_array(index, int, NULL, 0444);
@@ -146,6 +147,11 @@ static struct usb_device_id snd_usb_id_table[] = {
.idVendor = USB_VID_NATIVEINSTRUMENTS,
.idProduct = USB_PID_TRAKTORAUDIO2
},
+ {
+ .match_flags = USB_DEVICE_ID_MATCH_DEVICE,
+ .idVendor = USB_VID_NATIVEINSTRUMENTS,
+ .idProduct = USB_PID_MASCHINECONTROLLER
+ },
{ /* terminator */ }
};
@@ -532,16 +538,5 @@ static struct usb_driver snd_usb_driver = {
.id_table = snd_usb_id_table,
};
-static int __init snd_module_init(void)
-{
- return usb_register(&snd_usb_driver);
-}
-
-static void __exit snd_module_exit(void)
-{
- usb_deregister(&snd_usb_driver);
-}
-
-module_init(snd_module_init)
-module_exit(snd_module_exit)
+module_usb_driver(snd_usb_driver);
diff --git a/sound/usb/caiaq/device.h b/sound/usb/caiaq/device.h
index 3f9c6339ae90..562b0bff9c41 100644
--- a/sound/usb/caiaq/device.h
+++ b/sound/usb/caiaq/device.h
@@ -18,6 +18,7 @@
#define USB_PID_TRAKTORKONTROLX1 0x2305
#define USB_PID_TRAKTORKONTROLS4 0xbaff
#define USB_PID_TRAKTORAUDIO2 0x041d
+#define USB_PID_MASCHINECONTROLLER 0x0808
#define EP1_BUFSIZE 64
#define EP4_BUFSIZE 512
diff --git a/sound/usb/caiaq/input.c b/sound/usb/caiaq/input.c
index a213813487bd..26a121b42c3c 100644
--- a/sound/usb/caiaq/input.c
+++ b/sound/usb/caiaq/input.c
@@ -67,6 +67,61 @@ static unsigned short keycode_kore[] = {
KEY_BRL_DOT5
};
+#define MASCHINE_BUTTONS (42)
+#define MASCHINE_BUTTON(X) ((X) + BTN_MISC)
+#define MASCHINE_PADS (16)
+#define MASCHINE_PAD(X) ((X) + ABS_PRESSURE)
+
+static unsigned short keycode_maschine[] = {
+ MASCHINE_BUTTON(40), /* mute */
+ MASCHINE_BUTTON(39), /* solo */
+ MASCHINE_BUTTON(38), /* select */
+ MASCHINE_BUTTON(37), /* duplicate */
+ MASCHINE_BUTTON(36), /* navigate */
+ MASCHINE_BUTTON(35), /* pad mode */
+ MASCHINE_BUTTON(34), /* pattern */
+ MASCHINE_BUTTON(33), /* scene */
+ KEY_RESERVED, /* spacer */
+
+ MASCHINE_BUTTON(30), /* rec */
+ MASCHINE_BUTTON(31), /* erase */
+ MASCHINE_BUTTON(32), /* shift */
+ MASCHINE_BUTTON(28), /* grid */
+ MASCHINE_BUTTON(27), /* > */
+ MASCHINE_BUTTON(26), /* < */
+ MASCHINE_BUTTON(25), /* restart */
+
+ MASCHINE_BUTTON(21), /* E */
+ MASCHINE_BUTTON(22), /* F */
+ MASCHINE_BUTTON(23), /* G */
+ MASCHINE_BUTTON(24), /* H */
+ MASCHINE_BUTTON(20), /* D */
+ MASCHINE_BUTTON(19), /* C */
+ MASCHINE_BUTTON(18), /* B */
+ MASCHINE_BUTTON(17), /* A */
+
+ MASCHINE_BUTTON(0), /* control */
+ MASCHINE_BUTTON(2), /* browse */
+ MASCHINE_BUTTON(4), /* < */
+ MASCHINE_BUTTON(6), /* snap */
+ MASCHINE_BUTTON(7), /* autowrite */
+ MASCHINE_BUTTON(5), /* > */
+ MASCHINE_BUTTON(3), /* sampling */
+ MASCHINE_BUTTON(1), /* step */
+
+ MASCHINE_BUTTON(15), /* 8 softkeys */
+ MASCHINE_BUTTON(14),
+ MASCHINE_BUTTON(13),
+ MASCHINE_BUTTON(12),
+ MASCHINE_BUTTON(11),
+ MASCHINE_BUTTON(10),
+ MASCHINE_BUTTON(9),
+ MASCHINE_BUTTON(8),
+
+ MASCHINE_BUTTON(16), /* note repeat */
+ MASCHINE_BUTTON(29) /* play */
+};
+
#define KONTROLX1_INPUTS (40)
#define KONTROLS4_BUTTONS (12 * 8)
#define KONTROLS4_AXIS (46)
@@ -218,6 +273,29 @@ static void snd_caiaq_input_read_erp(struct snd_usb_caiaqdev *dev,
input_report_abs(input_dev, ABS_HAT3Y, i);
input_sync(input_dev);
break;
+
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
+ /* 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]));
+ input_report_abs(input_dev, ABS_HAT1X, decode_erp(buf[9], buf[8]));
+ input_report_abs(input_dev, ABS_HAT1Y, decode_erp(buf[3], buf[2]));
+
+ /* 4 under the right screen */
+ input_report_abs(input_dev, ABS_HAT2X, decode_erp(buf[19], buf[18]));
+ input_report_abs(input_dev, ABS_HAT2Y, decode_erp(buf[13], buf[12]));
+ input_report_abs(input_dev, ABS_HAT3X, decode_erp(buf[7], buf[6]));
+ input_report_abs(input_dev, ABS_HAT3Y, decode_erp(buf[1], buf[0]));
+
+ /* volume */
+ input_report_abs(input_dev, ABS_RX, decode_erp(buf[17], buf[16]));
+ /* tempo */
+ input_report_abs(input_dev, ABS_RY, decode_erp(buf[11], buf[10]));
+ /* swing */
+ input_report_abs(input_dev, ABS_RZ, decode_erp(buf[5], buf[4]));
+
+ input_sync(input_dev);
+ break;
}
}
@@ -400,6 +478,25 @@ static void snd_usb_caiaq_tks4_dispatch(struct snd_usb_caiaqdev *dev,
input_sync(dev->input_dev);
}
+#define MASCHINE_MSGBLOCK_SIZE 2
+
+static void snd_usb_caiaq_maschine_dispatch(struct snd_usb_caiaqdev *dev,
+ const unsigned char *buf,
+ unsigned int len)
+{
+ unsigned int i, pad_id;
+ uint16_t pressure;
+
+ for (i = 0; i < MASCHINE_PADS; i++) {
+ pressure = be16_to_cpu(buf[i * 2] << 8 | buf[(i * 2) + 1]);
+ pad_id = pressure >> 12;
+
+ input_report_abs(dev->input_dev, MASCHINE_PAD(pad_id), pressure & 0xfff);
+ }
+
+ input_sync(dev->input_dev);
+}
+
static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
{
struct snd_usb_caiaqdev *dev = urb->context;
@@ -425,6 +522,13 @@ static void snd_usb_caiaq_ep4_reply_dispatch(struct urb *urb)
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
snd_usb_caiaq_tks4_dispatch(dev, buf, urb->actual_length);
break;
+
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
+ if (urb->actual_length < (MASCHINE_PADS * MASCHINE_MSGBLOCK_SIZE))
+ goto requeue;
+
+ snd_usb_caiaq_maschine_dispatch(dev, buf, urb->actual_length);
+ break;
}
requeue:
@@ -444,6 +548,7 @@ static int snd_usb_caiaq_input_open(struct input_dev *idev)
switch (dev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
if (usb_submit_urb(dev->ep4_in_urb, GFP_KERNEL) != 0)
return -EIO;
break;
@@ -462,6 +567,7 @@ static void snd_usb_caiaq_input_close(struct input_dev *idev)
switch (dev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLS4):
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
usb_kill_urb(dev->ep4_in_urb);
break;
}
@@ -652,6 +758,50 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
break;
+ case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER):
+ input->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS);
+ input->absbit[0] = BIT_MASK(ABS_HAT0X) | BIT_MASK(ABS_HAT0Y) |
+ BIT_MASK(ABS_HAT1X) | BIT_MASK(ABS_HAT1Y) |
+ BIT_MASK(ABS_HAT2X) | BIT_MASK(ABS_HAT2Y) |
+ BIT_MASK(ABS_HAT3X) | BIT_MASK(ABS_HAT3Y) |
+ BIT_MASK(ABS_RX) | BIT_MASK(ABS_RY) |
+ BIT_MASK(ABS_RZ);
+
+ BUILD_BUG_ON(sizeof(dev->keycode) < sizeof(keycode_maschine));
+ memcpy(dev->keycode, keycode_maschine, sizeof(keycode_maschine));
+ input->keycodemax = ARRAY_SIZE(keycode_maschine);
+
+ for (i = 0; i < MASCHINE_PADS; i++) {
+ input->absbit[0] |= MASCHINE_PAD(i);
+ input_set_abs_params(input, MASCHINE_PAD(i), 0, 0xfff, 5, 10);
+ }
+
+ input_set_abs_params(input, ABS_HAT0X, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_HAT0Y, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_HAT1X, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_HAT1Y, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_HAT2X, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_HAT2Y, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_HAT3X, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_HAT3Y, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_RX, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_RY, 0, 999, 0, 10);
+ input_set_abs_params(input, ABS_RZ, 0, 999, 0, 10);
+
+ dev->ep4_in_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!dev->ep4_in_urb) {
+ ret = -ENOMEM;
+ goto exit_free_idev;
+ }
+
+ usb_fill_bulk_urb(dev->ep4_in_urb, usb_dev,
+ usb_rcvbulkpipe(usb_dev, 0x4),
+ dev->ep4_in_buf, EP4_BUFSIZE,
+ snd_usb_caiaq_ep4_reply_dispatch, dev);
+
+ snd_usb_caiaq_set_auto_msg(dev, 1, 10, 5);
+ break;
+
default:
/* no input methods supported on this device */
goto exit_free_idev;
@@ -664,15 +814,17 @@ int snd_usb_caiaq_input_init(struct snd_usb_caiaqdev *dev)
for (i = 0; i < input->keycodemax; i++)
__set_bit(dev->keycode[i], input->keybit);
+ dev->input_dev = input;
+
ret = input_register_device(input);
if (ret < 0)
goto exit_free_idev;
- dev->input_dev = input;
return 0;
exit_free_idev:
input_free_device(input);
+ dev->input_dev = NULL;
return ret;
}
@@ -688,4 +840,3 @@ void snd_usb_caiaq_input_free(struct snd_usb_caiaqdev *dev)
input_unregister_device(dev->input_dev);
dev->input_dev = NULL;
}
-
diff --git a/sound/usb/card.c b/sound/usb/card.c
index 781d9e61adfb..4a7be7b98331 100644
--- a/sound/usb/card.c
+++ b/sound/usb/card.c
@@ -47,6 +47,7 @@
#include <linux/mutex.h>
#include <linux/usb/audio.h>
#include <linux/usb/audio-v2.h>
+#include <linux/module.h>
#include <sound/control.h>
#include <sound/core.h>
@@ -65,9 +66,9 @@
#include "helper.h"
#include "debug.h"
#include "pcm.h"
-#include "urb.h"
#include "format.h"
#include "power.h"
+#include "stream.h"
MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
MODULE_DESCRIPTION("USB Audio");
@@ -77,14 +78,14 @@ MODULE_SUPPORTED_DEVICE("{{Generic,USB Audio}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
/* Vendor/product IDs for this card */
static int vid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
static int pid[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = -1 };
static int nrpacks = 8; /* max. number of packets per urb */
-static int async_unlink = 1;
+static bool async_unlink = 1;
static int device_setup[SNDRV_CARDS]; /* device parameter for this card */
-static int ignore_ctl_error;
+static bool ignore_ctl_error;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for the USB audio adapter.");
@@ -185,7 +186,7 @@ static int snd_usb_create_stream(struct snd_usb_audio *chip, int ctrlif, int int
return -EINVAL;
}
- if (! snd_usb_parse_audio_endpoints(chip, interface)) {
+ if (! snd_usb_parse_audio_interface(chip, interface)) {
usb_set_interface(dev, interface, 0); /* reset the current interface */
usb_driver_claim_interface(&usb_audio_driver, iface, (void *)-1L);
return -EINVAL;
@@ -530,8 +531,11 @@ snd_usb_audio_probe(struct usb_device *dev,
return chip;
__error:
- if (chip && !chip->num_interfaces)
- snd_card_free(chip->card);
+ if (chip) {
+ if (!chip->num_interfaces)
+ snd_card_free(chip->card);
+ chip->probing = 0;
+ }
mutex_unlock(&register_mutex);
__err_val:
return NULL;
@@ -628,7 +632,7 @@ static int usb_audio_suspend(struct usb_interface *intf, pm_message_t message)
if (chip == (void *)-1L)
return 0;
- if (!(message.event & PM_EVENT_AUTO)) {
+ if (!PMSG_IS_AUTO(message)) {
snd_power_change_state(chip->card, SNDRV_CTL_POWER_D3hot);
if (!chip->num_suspended_intf++) {
list_for_each(p, &chip->pcm_list) {
diff --git a/sound/usb/card.h b/sound/usb/card.h
index ae4251d5abf7..da5fa1ac4eda 100644
--- a/sound/usb/card.h
+++ b/sound/usb/card.h
@@ -1,6 +1,7 @@
#ifndef __USBAUDIO_CARD_H
#define __USBAUDIO_CARD_H
+#define MAX_NR_RATES 1024
#define MAX_PACKS 20
#define MAX_PACKS_HS (MAX_PACKS * 8) /* in high speed mode */
#define MAX_URBS 8
@@ -94,6 +95,8 @@ struct snd_usb_substream {
spinlock_t lock;
struct snd_urb_ops ops; /* callbacks (must be filled at init) */
+ int last_frame_number; /* stored frame number */
+ int last_delay; /* stored delay */
};
struct snd_usb_stream {
diff --git a/sound/usb/clock.c b/sound/usb/clock.c
index 075195e8661a..379baad3d5ad 100644
--- a/sound/usb/clock.c
+++ b/sound/usb/clock.c
@@ -91,7 +91,7 @@ static int uac_clock_selector_get_val(struct snd_usb_audio *chip, int selector_i
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
UAC2_CX_CLOCK_SELECTOR << 8,
snd_usb_ctrl_intf(chip) | (selector_id << 8),
- &buf, sizeof(buf), 1000);
+ &buf, sizeof(buf));
if (ret < 0)
return ret;
@@ -118,7 +118,7 @@ static bool uac_clock_source_is_valid(struct snd_usb_audio *chip, int source_id)
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
UAC2_CS_CONTROL_CLOCK_VALID << 8,
snd_usb_ctrl_intf(chip) | (source_id << 8),
- &data, sizeof(data), 1000);
+ &data, sizeof(data));
if (err < 0) {
snd_printk(KERN_WARNING "%s(): cannot get clock validity for id %d\n",
@@ -222,7 +222,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
- data, sizeof(data), 1000)) < 0) {
+ data, sizeof(data))) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d to ep %#x\n",
dev->devnum, iface, fmt->altsetting, rate, ep);
return err;
@@ -231,7 +231,7 @@ static int set_sample_rate_v1(struct snd_usb_audio *chip, int iface,
if ((err = snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), UAC_GET_CUR,
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_IN,
UAC_EP_CS_ATTR_SAMPLE_RATE << 8, ep,
- data, sizeof(data), 1000)) < 0) {
+ data, sizeof(data))) < 0) {
snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq at ep %#x\n",
dev->devnum, iface, fmt->altsetting, ep);
return 0; /* some devices don't support reading */
@@ -273,7 +273,7 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
UAC2_CS_CONTROL_SAM_FREQ << 8,
snd_usb_ctrl_intf(chip) | (clock << 8),
- data, sizeof(data), 1000)) < 0) {
+ data, sizeof(data))) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set freq %d (v2)\n",
dev->devnum, iface, fmt->altsetting, rate);
return err;
@@ -283,7 +283,7 @@ static int set_sample_rate_v2(struct snd_usb_audio *chip, int iface,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
UAC2_CS_CONTROL_SAM_FREQ << 8,
snd_usb_ctrl_intf(chip) | (clock << 8),
- data, sizeof(data), 1000)) < 0) {
+ data, sizeof(data))) < 0) {
snd_printk(KERN_WARNING "%d:%d:%d: cannot get freq (v2)\n",
dev->devnum, iface, fmt->altsetting);
return err;
diff --git a/sound/usb/endpoint.c b/sound/usb/endpoint.c
index 7d46e482375d..08dcce53720b 100644
--- a/sound/usb/endpoint.c
+++ b/sound/usb/endpoint.c
@@ -15,436 +15,952 @@
*
*/
+#include <linux/gfp.h>
#include <linux/init.h>
-#include <linux/slab.h>
+#include <linux/ratelimit.h>
#include <linux/usb.h>
#include <linux/usb/audio.h>
-#include <linux/usb/audio-v2.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include "usbaudio.h"
+#include "helper.h"
#include "card.h"
-#include "proc.h"
-#include "quirks.h"
#include "endpoint.h"
-#include "urb.h"
#include "pcm.h"
-#include "helper.h"
-#include "format.h"
-#include "clock.h"
/*
- * free a substream
+ * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
+ * this will overflow at approx 524 kHz
*/
-static void free_substream(struct snd_usb_substream *subs)
+static inline unsigned get_usb_full_speed_rate(unsigned int rate)
{
- struct list_head *p, *n;
-
- if (!subs->num_formats)
- return; /* not initialized */
- list_for_each_safe(p, n, &subs->fmt_list) {
- struct audioformat *fp = list_entry(p, struct audioformat, list);
- kfree(fp->rate_table);
- kfree(fp);
- }
- kfree(subs->rate_list.list);
+ return ((rate << 13) + 62) / 125;
}
+/*
+ * convert a sampling rate into USB high speed format (fs/8000 in Q16.16)
+ * this will overflow at approx 4 MHz
+ */
+static inline unsigned get_usb_high_speed_rate(unsigned int rate)
+{
+ return ((rate << 10) + 62) / 125;
+}
/*
- * free a usb stream instance
+ * unlink active urbs.
*/
-static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
+static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep)
{
- free_substream(&stream->substream[0]);
- free_substream(&stream->substream[1]);
- list_del(&stream->list);
- kfree(stream);
+ struct snd_usb_audio *chip = subs->stream->chip;
+ unsigned int i;
+ int async;
+
+ subs->running = 0;
+
+ if (!force && subs->stream->chip->shutdown) /* to be sure... */
+ return -EBADFD;
+
+ async = !can_sleep && chip->async_unlink;
+
+ if (!async && in_interrupt())
+ return 0;
+
+ for (i = 0; i < subs->nurbs; i++) {
+ if (test_bit(i, &subs->active_mask)) {
+ if (!test_and_set_bit(i, &subs->unlink_mask)) {
+ struct urb *u = subs->dataurb[i].urb;
+ if (async)
+ usb_unlink_urb(u);
+ else
+ usb_kill_urb(u);
+ }
+ }
+ }
+ if (subs->syncpipe) {
+ for (i = 0; i < SYNC_URBS; i++) {
+ if (test_bit(i+16, &subs->active_mask)) {
+ if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
+ struct urb *u = subs->syncurb[i].urb;
+ if (async)
+ usb_unlink_urb(u);
+ else
+ usb_kill_urb(u);
+ }
+ }
+ }
+ }
+ return 0;
}
-static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
+
+/*
+ * release a urb data
+ */
+static void release_urb_ctx(struct snd_urb_ctx *u)
{
- struct snd_usb_stream *stream = pcm->private_data;
- if (stream) {
- stream->pcm = NULL;
- snd_usb_audio_stream_free(stream);
+ if (u->urb) {
+ if (u->buffer_size)
+ usb_free_coherent(u->subs->dev, u->buffer_size,
+ u->urb->transfer_buffer,
+ u->urb->transfer_dma);
+ usb_free_urb(u->urb);
+ u->urb = NULL;
}
}
+/*
+ * wait until all urbs are processed.
+ */
+static int wait_clear_urbs(struct snd_usb_substream *subs)
+{
+ unsigned long end_time = jiffies + msecs_to_jiffies(1000);
+ unsigned int i;
+ int alive;
+
+ do {
+ alive = 0;
+ for (i = 0; i < subs->nurbs; i++) {
+ if (test_bit(i, &subs->active_mask))
+ alive++;
+ }
+ if (subs->syncpipe) {
+ for (i = 0; i < SYNC_URBS; i++) {
+ if (test_bit(i + 16, &subs->active_mask))
+ alive++;
+ }
+ }
+ if (! alive)
+ break;
+ schedule_timeout_uninterruptible(1);
+ } while (time_before(jiffies, end_time));
+ if (alive)
+ snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
+ return 0;
+}
/*
- * add this endpoint to the chip instance.
- * if a stream with the same endpoint already exists, append to it.
- * if not, create a new pcm stream.
+ * release a substream
*/
-int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip, int stream, struct audioformat *fp)
+void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
{
- struct list_head *p;
- struct snd_usb_stream *as;
- struct snd_usb_substream *subs;
- struct snd_pcm *pcm;
- int err;
+ int i;
+
+ /* stop urbs (to be sure) */
+ deactivate_urbs(subs, force, 1);
+ wait_clear_urbs(subs);
+
+ for (i = 0; i < MAX_URBS; i++)
+ release_urb_ctx(&subs->dataurb[i]);
+ for (i = 0; i < SYNC_URBS; i++)
+ release_urb_ctx(&subs->syncurb[i]);
+ usb_free_coherent(subs->dev, SYNC_URBS * 4,
+ subs->syncbuf, subs->sync_dma);
+ subs->syncbuf = NULL;
+ subs->nurbs = 0;
+}
- list_for_each(p, &chip->pcm_list) {
- as = list_entry(p, struct snd_usb_stream, list);
- if (as->fmt_type != fp->fmt_type)
- continue;
- subs = &as->substream[stream];
- if (!subs->endpoint)
- continue;
- if (subs->endpoint == fp->endpoint) {
- list_add_tail(&fp->list, &subs->fmt_list);
- subs->num_formats++;
- subs->formats |= fp->formats;
- return 0;
+/*
+ * complete callback from data urb
+ */
+static void snd_complete_urb(struct urb *urb)
+{
+ struct snd_urb_ctx *ctx = urb->context;
+ struct snd_usb_substream *subs = ctx->subs;
+ struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
+ int err = 0;
+
+ if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
+ !subs->running || /* can be stopped during retire callback */
+ (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
+ (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ clear_bit(ctx->index, &subs->active_mask);
+ if (err < 0) {
+ snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
}
}
- /* look for an empty stream */
- list_for_each(p, &chip->pcm_list) {
- as = list_entry(p, struct snd_usb_stream, list);
- if (as->fmt_type != fp->fmt_type)
- continue;
- subs = &as->substream[stream];
- if (subs->endpoint)
- continue;
- err = snd_pcm_new_stream(as->pcm, stream, 1);
- if (err < 0)
- return err;
- snd_usb_init_substream(as, stream, fp);
- return 0;
+}
+
+
+/*
+ * complete callback from sync urb
+ */
+static void snd_complete_sync_urb(struct urb *urb)
+{
+ struct snd_urb_ctx *ctx = urb->context;
+ struct snd_usb_substream *subs = ctx->subs;
+ struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
+ int err = 0;
+
+ if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
+ !subs->running || /* can be stopped during retire callback */
+ (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
+ (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
+ clear_bit(ctx->index + 16, &subs->active_mask);
+ if (err < 0) {
+ snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
+ snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
+ }
}
+}
+
- /* create a new pcm */
- as = kzalloc(sizeof(*as), GFP_KERNEL);
- if (!as)
- return -ENOMEM;
- as->pcm_index = chip->pcm_devs;
- as->chip = chip;
- as->fmt_type = fp->fmt_type;
- err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
- stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
- stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
- &pcm);
- if (err < 0) {
- kfree(as);
- return err;
+/*
+ * initialize a substream for plaback/capture
+ */
+int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
+ unsigned int period_bytes,
+ unsigned int rate,
+ unsigned int frame_bits)
+{
+ unsigned int maxsize, i;
+ int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
+ unsigned int urb_packs, total_packs, packs_per_ms;
+ struct snd_usb_audio *chip = subs->stream->chip;
+
+ /* calculate the frequency in 16.16 format */
+ if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
+ subs->freqn = get_usb_full_speed_rate(rate);
+ else
+ subs->freqn = get_usb_high_speed_rate(rate);
+ subs->freqm = subs->freqn;
+ subs->freqshift = INT_MIN;
+ /* calculate max. frequency */
+ if (subs->maxpacksize) {
+ /* whatever fits into a max. size packet */
+ maxsize = subs->maxpacksize;
+ subs->freqmax = (maxsize / (frame_bits >> 3))
+ << (16 - subs->datainterval);
+ } else {
+ /* no max. packet size: just take 25% higher than nominal */
+ subs->freqmax = subs->freqn + (subs->freqn >> 2);
+ maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
+ >> (16 - subs->datainterval);
}
- as->pcm = pcm;
- pcm->private_data = as;
- pcm->private_free = snd_usb_audio_pcm_free;
- pcm->info_flags = 0;
- if (chip->pcm_devs > 0)
- sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
+ subs->phase = 0;
+
+ if (subs->fill_max)
+ subs->curpacksize = subs->maxpacksize;
else
- strcpy(pcm->name, "USB Audio");
+ subs->curpacksize = maxsize;
- snd_usb_init_substream(as, stream, fp);
+ if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
+ packs_per_ms = 8 >> subs->datainterval;
+ else
+ packs_per_ms = 1;
+
+ if (is_playback) {
+ urb_packs = max(chip->nrpacks, 1);
+ urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
+ } else
+ urb_packs = 1;
+ urb_packs *= packs_per_ms;
+ if (subs->syncpipe)
+ urb_packs = min(urb_packs, 1U << subs->syncinterval);
+
+ /* decide how many packets to be used */
+ if (is_playback) {
+ unsigned int minsize, maxpacks;
+ /* determine how small a packet can be */
+ minsize = (subs->freqn >> (16 - subs->datainterval))
+ * (frame_bits >> 3);
+ /* with sync from device, assume it can be 12% lower */
+ if (subs->syncpipe)
+ minsize -= minsize >> 3;
+ minsize = max(minsize, 1u);
+ total_packs = (period_bytes + minsize - 1) / minsize;
+ /* we need at least two URBs for queueing */
+ if (total_packs < 2) {
+ total_packs = 2;
+ } else {
+ /* and we don't want too long a queue either */
+ maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
+ total_packs = min(total_packs, maxpacks);
+ }
+ } else {
+ while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
+ urb_packs >>= 1;
+ total_packs = MAX_URBS * urb_packs;
+ }
+ subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
+ if (subs->nurbs > MAX_URBS) {
+ /* too much... */
+ subs->nurbs = MAX_URBS;
+ total_packs = MAX_URBS * urb_packs;
+ } else if (subs->nurbs < 2) {
+ /* too little - we need at least two packets
+ * to ensure contiguous playback/capture
+ */
+ subs->nurbs = 2;
+ }
- list_add(&as->list, &chip->pcm_list);
- chip->pcm_devs++;
+ /* allocate and initialize data urbs */
+ for (i = 0; i < subs->nurbs; i++) {
+ struct snd_urb_ctx *u = &subs->dataurb[i];
+ u->index = i;
+ u->subs = subs;
+ u->packets = (i + 1) * total_packs / subs->nurbs
+ - i * total_packs / subs->nurbs;
+ u->buffer_size = maxsize * u->packets;
+ if (subs->fmt_type == UAC_FORMAT_TYPE_II)
+ u->packets++; /* for transfer delimiter */
+ u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
+ if (!u->urb)
+ goto out_of_memory;
+ u->urb->transfer_buffer =
+ usb_alloc_coherent(subs->dev, u->buffer_size,
+ GFP_KERNEL, &u->urb->transfer_dma);
+ if (!u->urb->transfer_buffer)
+ goto out_of_memory;
+ u->urb->pipe = subs->datapipe;
+ u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+ u->urb->interval = 1 << subs->datainterval;
+ u->urb->context = u;
+ u->urb->complete = snd_complete_urb;
+ }
+
+ if (subs->syncpipe) {
+ /* allocate and initialize sync urbs */
+ subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4,
+ GFP_KERNEL, &subs->sync_dma);
+ if (!subs->syncbuf)
+ goto out_of_memory;
+ for (i = 0; i < SYNC_URBS; i++) {
+ struct snd_urb_ctx *u = &subs->syncurb[i];
+ u->index = i;
+ u->subs = subs;
+ u->packets = 1;
+ u->urb = usb_alloc_urb(1, GFP_KERNEL);
+ if (!u->urb)
+ goto out_of_memory;
+ u->urb->transfer_buffer = subs->syncbuf + i * 4;
+ u->urb->transfer_dma = subs->sync_dma + i * 4;
+ u->urb->transfer_buffer_length = 4;
+ u->urb->pipe = subs->syncpipe;
+ u->urb->transfer_flags = URB_ISO_ASAP |
+ URB_NO_TRANSFER_DMA_MAP;
+ u->urb->number_of_packets = 1;
+ u->urb->interval = 1 << subs->syncinterval;
+ u->urb->context = u;
+ u->urb->complete = snd_complete_sync_urb;
+ }
+ }
+ return 0;
- snd_usb_proc_pcm_format_add(as);
+out_of_memory:
+ snd_usb_release_substream_urbs(subs, 0);
+ return -ENOMEM;
+}
+/*
+ * prepare urb for full speed capture sync pipe
+ *
+ * fill the length and offset of each urb descriptor.
+ * the fixed 10.14 frequency is passed through the pipe.
+ */
+static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
+{
+ unsigned char *cp = urb->transfer_buffer;
+ struct snd_urb_ctx *ctx = urb->context;
+
+ urb->dev = ctx->subs->dev; /* we need to set this at each time */
+ urb->iso_frame_desc[0].length = 3;
+ urb->iso_frame_desc[0].offset = 0;
+ cp[0] = subs->freqn >> 2;
+ cp[1] = subs->freqn >> 10;
+ cp[2] = subs->freqn >> 18;
return 0;
}
-static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
- struct usb_host_interface *alts,
- int protocol, int iface_no)
+/*
+ * prepare urb for high speed capture sync pipe
+ *
+ * fill the length and offset of each urb descriptor.
+ * the fixed 12.13 frequency is passed as 16.16 through the pipe.
+ */
+static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
{
- /* parsed with a v1 header here. that's ok as we only look at the
- * header first which is the same for both versions */
- struct uac_iso_endpoint_descriptor *csep;
- struct usb_interface_descriptor *altsd = get_iface_desc(alts);
- int attributes = 0;
-
- csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
-
- /* Creamware Noah has this descriptor after the 2nd endpoint */
- if (!csep && altsd->bNumEndpoints >= 2)
- csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
-
- if (!csep || csep->bLength < 7 ||
- csep->bDescriptorSubtype != UAC_EP_GENERAL) {
- snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
- " class specific endpoint descriptor\n",
- chip->dev->devnum, iface_no,
- altsd->bAlternateSetting);
- return 0;
- }
+ unsigned char *cp = urb->transfer_buffer;
+ struct snd_urb_ctx *ctx = urb->context;
+
+ urb->dev = ctx->subs->dev; /* we need to set this at each time */
+ urb->iso_frame_desc[0].length = 4;
+ urb->iso_frame_desc[0].offset = 0;
+ cp[0] = subs->freqn;
+ cp[1] = subs->freqn >> 8;
+ cp[2] = subs->freqn >> 16;
+ cp[3] = subs->freqn >> 24;
+ return 0;
+}
- if (protocol == UAC_VERSION_1) {
- attributes = csep->bmAttributes;
- } else {
- struct uac2_iso_endpoint_descriptor *csep2 =
- (struct uac2_iso_endpoint_descriptor *) csep;
+/*
+ * process after capture sync complete
+ * - nothing to do
+ */
+static int retire_capture_sync_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
+{
+ return 0;
+}
- attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
+/*
+ * prepare urb for capture data pipe
+ *
+ * fill the offset and length of each descriptor.
+ *
+ * we use a temporary buffer to write the captured data.
+ * since the length of written data is determined by host, we cannot
+ * write onto the pcm buffer directly... the data is thus copied
+ * later at complete callback to the global buffer.
+ */
+static int prepare_capture_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
+{
+ int i, offs;
+ struct snd_urb_ctx *ctx = urb->context;
+
+ offs = 0;
+ urb->dev = ctx->subs->dev; /* we need to set this at each time */
+ for (i = 0; i < ctx->packets; i++) {
+ urb->iso_frame_desc[i].offset = offs;
+ urb->iso_frame_desc[i].length = subs->curpacksize;
+ offs += subs->curpacksize;
+ }
+ urb->transfer_buffer_length = offs;
+ urb->number_of_packets = ctx->packets;
+ return 0;
+}
- /* emulate the endpoint attributes of a v1 device */
- if (csep2->bmControls & UAC2_CONTROL_PITCH)
- attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
+/*
+ * process after capture complete
+ *
+ * copy the data from each desctiptor to the pcm buffer, and
+ * update the current position.
+ */
+static int retire_capture_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
+{
+ unsigned long flags;
+ unsigned char *cp;
+ int i;
+ unsigned int stride, frames, bytes, oldptr;
+ int period_elapsed = 0;
+
+ stride = runtime->frame_bits >> 3;
+
+ for (i = 0; i < urb->number_of_packets; i++) {
+ cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+ if (urb->iso_frame_desc[i].status && printk_ratelimit()) {
+ snd_printdd("frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
+ // continue;
+ }
+ bytes = urb->iso_frame_desc[i].actual_length;
+ frames = bytes / stride;
+ if (!subs->txfr_quirk)
+ bytes = frames * stride;
+ if (bytes % (runtime->sample_bits >> 3) != 0) {
+#ifdef CONFIG_SND_DEBUG_VERBOSE
+ int oldbytes = bytes;
+#endif
+ bytes = frames * stride;
+ snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
+ oldbytes, bytes);
+ }
+ /* update the current pointer */
+ spin_lock_irqsave(&subs->lock, flags);
+ oldptr = subs->hwptr_done;
+ subs->hwptr_done += bytes;
+ if (subs->hwptr_done >= runtime->buffer_size * stride)
+ subs->hwptr_done -= runtime->buffer_size * stride;
+ frames = (bytes + (oldptr % stride)) / stride;
+ subs->transfer_done += frames;
+ if (subs->transfer_done >= runtime->period_size) {
+ subs->transfer_done -= runtime->period_size;
+ period_elapsed = 1;
+ }
+ spin_unlock_irqrestore(&subs->lock, flags);
+ /* copy a data chunk */
+ if (oldptr + bytes > runtime->buffer_size * stride) {
+ unsigned int bytes1 =
+ runtime->buffer_size * stride - oldptr;
+ memcpy(runtime->dma_area + oldptr, cp, bytes1);
+ memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
+ } else {
+ memcpy(runtime->dma_area + oldptr, cp, bytes);
+ }
}
+ if (period_elapsed)
+ snd_pcm_period_elapsed(subs->pcm_substream);
+ return 0;
+}
- return attributes;
+/*
+ * Process after capture complete when paused. Nothing to do.
+ */
+static int retire_paused_capture_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
+{
+ return 0;
}
-static struct uac2_input_terminal_descriptor *
- snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
- int terminal_id)
+
+/*
+ * prepare urb for playback sync pipe
+ *
+ * set up the offset and length to receive the current frequency.
+ */
+static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
{
- struct uac2_input_terminal_descriptor *term = NULL;
+ struct snd_urb_ctx *ctx = urb->context;
+
+ urb->dev = ctx->subs->dev; /* we need to set this at each time */
+ urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
+ urb->iso_frame_desc[0].offset = 0;
+ return 0;
+}
- while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
- ctrl_iface->extralen,
- term, UAC_INPUT_TERMINAL))) {
- if (term->bTerminalID == terminal_id)
- return term;
+/*
+ * process after playback sync complete
+ *
+ * Full speed devices report feedback values in 10.14 format as samples per
+ * frame, high speed devices in 16.16 format as samples per microframe.
+ * Because the Audio Class 1 spec was written before USB 2.0, many high speed
+ * devices use a wrong interpretation, some others use an entirely different
+ * format. Therefore, we cannot predict what format any particular device uses
+ * and must detect it automatically.
+ */
+static int retire_playback_sync_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
+{
+ unsigned int f;
+ int shift;
+ unsigned long flags;
+
+ if (urb->iso_frame_desc[0].status != 0 ||
+ urb->iso_frame_desc[0].actual_length < 3)
+ return 0;
+
+ f = le32_to_cpup(urb->transfer_buffer);
+ if (urb->iso_frame_desc[0].actual_length == 3)
+ f &= 0x00ffffff;
+ else
+ f &= 0x0fffffff;
+ if (f == 0)
+ return 0;
+
+ if (unlikely(subs->freqshift == INT_MIN)) {
+ /*
+ * The first time we see a feedback value, determine its format
+ * by shifting it left or right until it matches the nominal
+ * frequency value. This assumes that the feedback does not
+ * differ from the nominal value more than +50% or -25%.
+ */
+ shift = 0;
+ while (f < subs->freqn - subs->freqn / 4) {
+ f <<= 1;
+ shift++;
+ }
+ while (f > subs->freqn + subs->freqn / 2) {
+ f >>= 1;
+ shift--;
+ }
+ subs->freqshift = shift;
+ }
+ else if (subs->freqshift >= 0)
+ f <<= subs->freqshift;
+ else
+ f >>= -subs->freqshift;
+
+ if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
+ /*
+ * If the frequency looks valid, set it.
+ * This value is referred to in prepare_playback_urb().
+ */
+ spin_lock_irqsave(&subs->lock, flags);
+ subs->freqm = f;
+ spin_unlock_irqrestore(&subs->lock, flags);
+ } else {
+ /*
+ * Out of range; maybe the shift value is wrong.
+ * Reset it so that we autodetect again the next time.
+ */
+ subs->freqshift = INT_MIN;
}
- return NULL;
+ return 0;
}
-static struct uac2_output_terminal_descriptor *
- snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
- int terminal_id)
+/* determine the number of frames in the next packet */
+static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
{
- struct uac2_output_terminal_descriptor *term = NULL;
-
- while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
- ctrl_iface->extralen,
- term, UAC_OUTPUT_TERMINAL))) {
- if (term->bTerminalID == terminal_id)
- return term;
+ if (subs->fill_max)
+ return subs->maxframesize;
+ else {
+ subs->phase = (subs->phase & 0xffff)
+ + (subs->freqm << subs->datainterval);
+ return min(subs->phase >> 16, subs->maxframesize);
}
+}
- return NULL;
+/*
+ * Prepare urb for streaming before playback starts or when paused.
+ *
+ * We don't have any data, so we send silence.
+ */
+static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
+{
+ unsigned int i, offs, counts;
+ struct snd_urb_ctx *ctx = urb->context;
+ int stride = runtime->frame_bits >> 3;
+
+ offs = 0;
+ urb->dev = ctx->subs->dev;
+ for (i = 0; i < ctx->packets; ++i) {
+ counts = snd_usb_audio_next_packet_size(subs);
+ urb->iso_frame_desc[i].offset = offs * stride;
+ urb->iso_frame_desc[i].length = counts * stride;
+ offs += counts;
+ }
+ urb->number_of_packets = ctx->packets;
+ urb->transfer_buffer_length = offs * stride;
+ memset(urb->transfer_buffer,
+ runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
+ offs * stride);
+ return 0;
}
-int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip, int iface_no)
+/*
+ * prepare urb for playback data pipe
+ *
+ * Since a URB can handle only a single linear buffer, we must use double
+ * buffering when the data to be transferred overflows the buffer boundary.
+ * To avoid inconsistencies when updating hwptr_done, we use double buffering
+ * for all URBs.
+ */
+static int prepare_playback_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
{
- struct usb_device *dev;
- struct usb_interface *iface;
- struct usb_host_interface *alts;
- struct usb_interface_descriptor *altsd;
- int i, altno, err, stream;
- int format = 0, num_channels = 0;
- struct audioformat *fp = NULL;
- int num, protocol, clock = 0;
- struct uac_format_type_i_continuous_descriptor *fmt;
+ int i, stride;
+ unsigned int counts, frames, bytes;
+ unsigned long flags;
+ int period_elapsed = 0;
+ struct snd_urb_ctx *ctx = urb->context;
+
+ stride = runtime->frame_bits >> 3;
+
+ frames = 0;
+ urb->dev = ctx->subs->dev; /* we need to set this at each time */
+ urb->number_of_packets = 0;
+ spin_lock_irqsave(&subs->lock, flags);
+ for (i = 0; i < ctx->packets; i++) {
+ counts = snd_usb_audio_next_packet_size(subs);
+ /* set up descriptor */
+ urb->iso_frame_desc[i].offset = frames * stride;
+ urb->iso_frame_desc[i].length = counts * stride;
+ frames += counts;
+ urb->number_of_packets++;
+ subs->transfer_done += counts;
+ if (subs->transfer_done >= runtime->period_size) {
+ subs->transfer_done -= runtime->period_size;
+ period_elapsed = 1;
+ if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
+ if (subs->transfer_done > 0) {
+ /* FIXME: fill-max mode is not
+ * supported yet */
+ frames -= subs->transfer_done;
+ counts -= subs->transfer_done;
+ urb->iso_frame_desc[i].length =
+ counts * stride;
+ subs->transfer_done = 0;
+ }
+ i++;
+ if (i < ctx->packets) {
+ /* add a transfer delimiter */
+ urb->iso_frame_desc[i].offset =
+ frames * stride;
+ urb->iso_frame_desc[i].length = 0;
+ urb->number_of_packets++;
+ }
+ break;
+ }
+ }
+ if (period_elapsed) /* finish at the period boundary */
+ break;
+ }
+ bytes = frames * stride;
+ if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
+ /* err, the transferred area goes over buffer boundary. */
+ unsigned int bytes1 =
+ runtime->buffer_size * stride - subs->hwptr_done;
+ memcpy(urb->transfer_buffer,
+ runtime->dma_area + subs->hwptr_done, bytes1);
+ memcpy(urb->transfer_buffer + bytes1,
+ runtime->dma_area, bytes - bytes1);
+ } else {
+ memcpy(urb->transfer_buffer,
+ runtime->dma_area + subs->hwptr_done, bytes);
+ }
+ subs->hwptr_done += bytes;
+ if (subs->hwptr_done >= runtime->buffer_size * stride)
+ subs->hwptr_done -= runtime->buffer_size * stride;
+
+ /* update delay with exact number of samples queued */
+ runtime->delay = subs->last_delay;
+ runtime->delay += frames;
+ subs->last_delay = runtime->delay;
+
+ /* realign last_frame_number */
+ subs->last_frame_number = usb_get_current_frame_number(subs->dev);
+ subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
+
+ spin_unlock_irqrestore(&subs->lock, flags);
+ urb->transfer_buffer_length = bytes;
+ if (period_elapsed)
+ snd_pcm_period_elapsed(subs->pcm_substream);
+ return 0;
+}
- dev = chip->dev;
+/*
+ * process after playback data complete
+ * - decrease the delay count again
+ */
+static int retire_playback_urb(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime,
+ struct urb *urb)
+{
+ unsigned long flags;
+ int stride = runtime->frame_bits >> 3;
+ int processed = urb->transfer_buffer_length / stride;
+ int est_delay;
- /* parse the interface's altsettings */
- iface = usb_ifnum_to_if(dev, iface_no);
+ spin_lock_irqsave(&subs->lock, flags);
- num = iface->num_altsetting;
+ est_delay = snd_usb_pcm_delay(subs, runtime->rate);
+ /* update delay with exact number of samples played */
+ if (processed > subs->last_delay)
+ subs->last_delay = 0;
+ else
+ subs->last_delay -= processed;
+ runtime->delay = subs->last_delay;
/*
- * Dallas DS4201 workaround: It presents 5 altsettings, but the last
- * one misses syncpipe, and does not produce any sound.
+ * Report when delay estimate is off by more than 2ms.
+ * The error should be lower than 2ms since the estimate relies
+ * on two reads of a counter updated every ms.
*/
- if (chip->usb_id == USB_ID(0x04fa, 0x4201))
- num = 4;
-
- for (i = 0; i < num; i++) {
- alts = &iface->altsetting[i];
- altsd = get_iface_desc(alts);
- protocol = altsd->bInterfaceProtocol;
- /* skip invalid one */
- if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
- altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
- (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
- altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
- altsd->bNumEndpoints < 1 ||
- le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
- continue;
- /* must be isochronous */
- if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
- USB_ENDPOINT_XFER_ISOC)
- continue;
- /* check direction */
- stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
- SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
- altno = altsd->bAlternateSetting;
-
- if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
- continue;
-
- /* get audio formats */
- switch (protocol) {
- default:
- snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
- dev->devnum, iface_no, altno, protocol);
- protocol = UAC_VERSION_1;
- /* fall through */
-
- case UAC_VERSION_1: {
- struct uac1_as_header_descriptor *as =
- snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
-
- if (!as) {
- snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
- dev->devnum, iface_no, altno);
- continue;
- }
+ if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
+ snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
+ est_delay, subs->last_delay);
- if (as->bLength < sizeof(*as)) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
- dev->devnum, iface_no, altno);
- continue;
- }
+ spin_unlock_irqrestore(&subs->lock, flags);
+ return 0;
+}
- format = le16_to_cpu(as->wFormatTag); /* remember the format value */
- break;
- }
+static const char *usb_error_string(int err)
+{
+ switch (err) {
+ case -ENODEV:
+ return "no device";
+ case -ENOENT:
+ return "endpoint not enabled";
+ case -EPIPE:
+ return "endpoint stalled";
+ case -ENOSPC:
+ return "not enough bandwidth";
+ case -ESHUTDOWN:
+ return "device disabled";
+ case -EHOSTUNREACH:
+ return "device suspended";
+ case -EINVAL:
+ case -EAGAIN:
+ case -EFBIG:
+ case -EMSGSIZE:
+ return "internal error";
+ default:
+ return "unknown error";
+ }
+}
- case UAC_VERSION_2: {
- struct uac2_input_terminal_descriptor *input_term;
- struct uac2_output_terminal_descriptor *output_term;
- struct uac2_as_header_descriptor *as =
- snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+/*
+ * set up and start data/sync urbs
+ */
+static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime)
+{
+ unsigned int i;
+ int err;
- if (!as) {
- snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
- dev->devnum, iface_no, altno);
- continue;
+ if (subs->stream->chip->shutdown)
+ return -EBADFD;
+
+ for (i = 0; i < subs->nurbs; i++) {
+ if (snd_BUG_ON(!subs->dataurb[i].urb))
+ return -EINVAL;
+ if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
+ snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i);
+ goto __error;
+ }
+ }
+ if (subs->syncpipe) {
+ for (i = 0; i < SYNC_URBS; i++) {
+ if (snd_BUG_ON(!subs->syncurb[i].urb))
+ return -EINVAL;
+ if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) {
+ snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i);
+ goto __error;
}
+ }
+ }
- if (as->bLength < sizeof(*as)) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
- dev->devnum, iface_no, altno);
- continue;
+ subs->active_mask = 0;
+ subs->unlink_mask = 0;
+ subs->running = 1;
+ for (i = 0; i < subs->nurbs; i++) {
+ err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC);
+ if (err < 0) {
+ snd_printk(KERN_ERR "cannot submit datapipe "
+ "for urb %d, error %d: %s\n",
+ i, err, usb_error_string(err));
+ goto __error;
+ }
+ set_bit(i, &subs->active_mask);
+ }
+ if (subs->syncpipe) {
+ for (i = 0; i < SYNC_URBS; i++) {
+ err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC);
+ if (err < 0) {
+ snd_printk(KERN_ERR "cannot submit syncpipe "
+ "for urb %d, error %d: %s\n",
+ i, err, usb_error_string(err));
+ goto __error;
}
+ set_bit(i + 16, &subs->active_mask);
+ }
+ }
+ return 0;
- num_channels = as->bNrChannels;
- format = le32_to_cpu(as->bmFormats);
+ __error:
+ // snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
+ deactivate_urbs(subs, 0, 0);
+ return -EPIPE;
+}
- /* lookup the terminal associated to this interface
- * to extract the clock */
- input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
- as->bTerminalLink);
- if (input_term) {
- clock = input_term->bCSourceID;
- break;
- }
- output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
- as->bTerminalLink);
- if (output_term) {
- clock = output_term->bCSourceID;
- break;
- }
+/*
+ */
+static struct snd_urb_ops audio_urb_ops[2] = {
+ {
+ .prepare = prepare_nodata_playback_urb,
+ .retire = retire_playback_urb,
+ .prepare_sync = prepare_playback_sync_urb,
+ .retire_sync = retire_playback_sync_urb,
+ },
+ {
+ .prepare = prepare_capture_urb,
+ .retire = retire_capture_urb,
+ .prepare_sync = prepare_capture_sync_urb,
+ .retire_sync = retire_capture_sync_urb,
+ },
+};
- snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
- dev->devnum, iface_no, altno, as->bTerminalLink);
- continue;
- }
- }
+/*
+ * initialize the substream instance.
+ */
- /* get format type */
- fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
- if (!fmt) {
- snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
- dev->devnum, iface_no, altno);
- continue;
- }
- if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
- ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
- snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
- dev->devnum, iface_no, altno);
- continue;
- }
+void snd_usb_init_substream(struct snd_usb_stream *as,
+ int stream, struct audioformat *fp)
+{
+ struct snd_usb_substream *subs = &as->substream[stream];
+
+ INIT_LIST_HEAD(&subs->fmt_list);
+ spin_lock_init(&subs->lock);
+
+ subs->stream = as;
+ subs->direction = stream;
+ subs->dev = as->chip->dev;
+ subs->txfr_quirk = as->chip->txfr_quirk;
+ subs->ops = audio_urb_ops[stream];
+ if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
+ subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
+
+ snd_usb_set_pcm_ops(as->pcm, stream);
+
+ list_add_tail(&fp->list, &subs->fmt_list);
+ subs->formats |= fp->formats;
+ subs->endpoint = fp->endpoint;
+ subs->num_formats++;
+ subs->fmt_type = fp->fmt_type;
+}
- /*
- * Blue Microphones workaround: The last altsetting is identical
- * with the previous one, except for a larger packet size, but
- * is actually a mislabeled two-channel setting; ignore it.
- */
- if (fmt->bNrChannels == 1 &&
- fmt->bSubframeSize == 2 &&
- altno == 2 && num == 3 &&
- fp && fp->altsetting == 1 && fp->channels == 1 &&
- fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
- protocol == UAC_VERSION_1 &&
- le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
- fp->maxpacksize * 2)
- continue;
-
- fp = kzalloc(sizeof(*fp), GFP_KERNEL);
- if (! fp) {
- snd_printk(KERN_ERR "cannot malloc\n");
- return -ENOMEM;
- }
+int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_usb_substream *subs = substream->runtime->private_data;
- fp->iface = iface_no;
- fp->altsetting = altno;
- fp->altset_idx = i;
- fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
- fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
- fp->datainterval = snd_usb_parse_datainterval(chip, alts);
- fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
- /* num_channels is only set for v2 interfaces */
- fp->channels = num_channels;
- if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
- fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
- * (fp->maxpacksize & 0x7ff);
- fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
- fp->clock = clock;
-
- /* some quirks for attributes here */
-
- switch (chip->usb_id) {
- case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
- /* Optoplay sets the sample rate attribute although
- * it seems not supporting it in fact.
- */
- fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
- break;
- case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
- case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
- /* doesn't set the sample rate attribute, but supports it */
- fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
- break;
- case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */
- case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
- case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
- case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
- an older model 77d:223) */
- /*
- * plantronics headset and Griffin iMic have set adaptive-in
- * although it's really not...
- */
- fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
- if (stream == SNDRV_PCM_STREAM_PLAYBACK)
- fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
- else
- fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
- break;
- }
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ subs->ops.prepare = prepare_playback_urb;
+ return 0;
+ case SNDRV_PCM_TRIGGER_STOP:
+ return deactivate_urbs(subs, 0, 0);
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ subs->ops.prepare = prepare_nodata_playback_urb;
+ return 0;
+ }
- /* ok, let's parse further... */
- if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
- kfree(fp->rate_table);
- kfree(fp);
- fp = NULL;
- continue;
- }
+ return -EINVAL;
+}
- snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
- err = snd_usb_add_audio_endpoint(chip, stream, fp);
- if (err < 0) {
- kfree(fp->rate_table);
- kfree(fp);
- return err;
- }
- /* try to set the interface... */
- usb_set_interface(chip->dev, iface_no, altno);
- snd_usb_init_pitch(chip, iface_no, alts, fp);
- snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
+int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_usb_substream *subs = substream->runtime->private_data;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ subs->ops.retire = retire_capture_urb;
+ return start_urbs(subs, substream->runtime);
+ case SNDRV_PCM_TRIGGER_STOP:
+ return deactivate_urbs(subs, 0, 0);
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ subs->ops.retire = retire_paused_capture_urb;
+ return 0;
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ subs->ops.retire = retire_capture_urb;
+ return 0;
}
+
+ return -EINVAL;
+}
+
+int snd_usb_substream_prepare(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime)
+{
+ /* clear urbs (to be sure) */
+ deactivate_urbs(subs, 0, 1);
+ wait_clear_urbs(subs);
+
+ /* for playback, submit the URBs now; otherwise, the first hwptr_done
+ * updates for all URBs would happen at the same time when starting */
+ if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
+ subs->ops.prepare = prepare_nodata_playback_urb;
+ return start_urbs(subs, runtime);
+ }
+
return 0;
}
diff --git a/sound/usb/endpoint.h b/sound/usb/endpoint.h
index 64dd0db023b2..88eb63a636eb 100644
--- a/sound/usb/endpoint.h
+++ b/sound/usb/endpoint.h
@@ -1,11 +1,21 @@
#ifndef __USBAUDIO_ENDPOINT_H
#define __USBAUDIO_ENDPOINT_H
-int snd_usb_parse_audio_endpoints(struct snd_usb_audio *chip,
- int iface_no);
+void snd_usb_init_substream(struct snd_usb_stream *as,
+ int stream,
+ struct audioformat *fp);
-int snd_usb_add_audio_endpoint(struct snd_usb_audio *chip,
- int stream,
- struct audioformat *fp);
+int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
+ unsigned int period_bytes,
+ unsigned int rate,
+ unsigned int frame_bits);
+
+void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
+
+int snd_usb_substream_prepare(struct snd_usb_substream *subs,
+ struct snd_pcm_runtime *runtime);
+
+int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
+int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
#endif /* __USBAUDIO_ENDPOINT_H */
diff --git a/sound/usb/format.c b/sound/usb/format.c
index 8d042dce0d16..ddfef57c4c9f 100644
--- a/sound/usb/format.c
+++ b/sound/usb/format.c
@@ -226,7 +226,7 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
int min = combine_quad(&data[2 + 12 * i]);
int max = combine_quad(&data[6 + 12 * i]);
int res = combine_quad(&data[10 + 12 * i]);
- int rate;
+ unsigned int rate;
if ((max < 0) || (min < 0) || (res < 0) || (max < min))
continue;
@@ -253,6 +253,10 @@ static int parse_uac2_sample_rate_range(struct audioformat *fp, int nr_triplets,
fp->rates |= snd_pcm_rate_to_rate_bit(rate);
nr_rates++;
+ if (nr_rates >= MAX_NR_RATES) {
+ snd_printk(KERN_ERR "invalid uac2 rates\n");
+ break;
+ }
/* avoid endless loop */
if (res == 0)
@@ -286,7 +290,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
UAC2_CS_CONTROL_SAM_FREQ << 8,
snd_usb_ctrl_intf(chip) | (clock << 8),
- tmp, sizeof(tmp), 1000);
+ tmp, sizeof(tmp));
if (ret < 0) {
snd_printk(KERN_ERR "%s(): unable to retrieve number of sample rates (clock %d)\n",
@@ -307,7 +311,7 @@ static int parse_audio_format_rates_v2(struct snd_usb_audio *chip,
USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
UAC2_CS_CONTROL_SAM_FREQ << 8,
snd_usb_ctrl_intf(chip) | (clock << 8),
- data, data_size, 1000);
+ data, data_size);
if (ret < 0) {
snd_printk(KERN_ERR "%s(): unable to retrieve sample rate range (clock %d)\n",
diff --git a/sound/usb/helper.c b/sound/usb/helper.c
index f280c1903c25..9eed8f40b179 100644
--- a/sound/usb/helper.c
+++ b/sound/usb/helper.c
@@ -81,7 +81,7 @@ void *snd_usb_find_csint_desc(void *buffer, int buflen, void *after, u8 dsubtype
*/
int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
__u8 requesttype, __u16 value, __u16 index, void *data,
- __u16 size, int timeout)
+ __u16 size)
{
int err;
void *buf = NULL;
@@ -92,7 +92,7 @@ int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe, __u8 request,
return -ENOMEM;
}
err = usb_control_msg(dev, pipe, request, requesttype,
- value, index, buf, size, timeout);
+ value, index, buf, size, 1000);
if (size > 0) {
memcpy(data, buf, size);
kfree(buf);
diff --git a/sound/usb/helper.h b/sound/usb/helper.h
index 09bd943c43bf..805c300dd004 100644
--- a/sound/usb/helper.h
+++ b/sound/usb/helper.h
@@ -8,7 +8,7 @@ void *snd_usb_find_csint_desc(void *descstart, int desclen, void *after, u8 dsub
int snd_usb_ctl_msg(struct usb_device *dev, unsigned int pipe,
__u8 request, __u8 requesttype, __u16 value, __u16 index,
- void *data, __u16 size, int timeout);
+ void *data, __u16 size);
unsigned char snd_usb_parse_datainterval(struct snd_usb_audio *chip,
struct usb_host_interface *alts);
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index f9289102886a..c83f6143c0eb 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -47,6 +47,7 @@
#include <linux/usb.h>
#include <linux/wait.h>
#include <linux/usb/audio.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/control.h>
@@ -816,6 +817,22 @@ static struct usb_protocol_ops snd_usbmidi_raw_ops = {
.output = snd_usbmidi_raw_output,
};
+/*
+ * FTDI protocol: raw MIDI bytes, but input packets have two modem status bytes.
+ */
+
+static void snd_usbmidi_ftdi_input(struct snd_usb_midi_in_endpoint* ep,
+ uint8_t* buffer, int buffer_length)
+{
+ if (buffer_length > 2)
+ snd_usbmidi_input_data(ep, 0, buffer + 2, buffer_length - 2);
+}
+
+static struct usb_protocol_ops snd_usbmidi_ftdi_ops = {
+ .input = snd_usbmidi_ftdi_input,
+ .output = snd_usbmidi_raw_output,
+};
+
static void snd_usbmidi_us122l_input(struct snd_usb_midi_in_endpoint *ep,
uint8_t *buffer, int buffer_length)
{
@@ -2163,6 +2180,17 @@ int snd_usbmidi_create(struct snd_card *card,
/* endpoint 1 is input-only */
endpoints[1].out_cables = 0;
break;
+ case QUIRK_MIDI_FTDI:
+ umidi->usb_protocol_ops = &snd_usbmidi_ftdi_ops;
+
+ /* set baud rate to 31250 (48 MHz / 16 / 96) */
+ err = usb_control_msg(umidi->dev, usb_sndctrlpipe(umidi->dev, 0),
+ 3, 0x40, 0x60, 0, NULL, 0, 1000);
+ if (err < 0)
+ break;
+
+ err = snd_usbmidi_detect_per_port_endpoints(umidi, endpoints);
+ break;
default:
snd_printd(KERN_ERR "invalid quirk type %d\n", quirk->type);
err = -ENXIO;
diff --git a/sound/usb/misc/ua101.c b/sound/usb/misc/ua101.c
index 67bec7612442..8b81cb54026f 100644
--- a/sound/usb/misc/ua101.c
+++ b/sound/usb/misc/ua101.c
@@ -52,7 +52,7 @@ MODULE_SUPPORTED_DEVICE("{{Edirol,UA-101},{Edirol,UA-1000}}");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
static unsigned int queue_length = 21;
module_param_array(index, int, NULL, 0444);
@@ -459,7 +459,8 @@ static void kill_stream_urbs(struct ua101_stream *stream)
unsigned int i;
for (i = 0; i < stream->queue_length; ++i)
- usb_kill_urb(&stream->urbs[i]->urb);
+ if (stream->urbs[i])
+ usb_kill_urb(&stream->urbs[i]->urb);
}
static int enable_iso_interface(struct ua101 *ua, unsigned int intf_index)
@@ -484,6 +485,9 @@ static void disable_iso_interface(struct ua101 *ua, unsigned int intf_index)
{
struct usb_host_interface *alts;
+ if (!ua->intf[intf_index])
+ return;
+
alts = ua->intf[intf_index]->cur_altsetting;
if (alts->desc.bAlternateSetting != 0) {
int err = usb_set_interface(ua->dev,
@@ -1144,27 +1148,37 @@ static void free_stream_urbs(struct ua101_stream *stream)
{
unsigned int i;
- for (i = 0; i < stream->queue_length; ++i)
+ for (i = 0; i < stream->queue_length; ++i) {
kfree(stream->urbs[i]);
+ stream->urbs[i] = NULL;
+ }
}
static void free_usb_related_resources(struct ua101 *ua,
struct usb_interface *interface)
{
unsigned int i;
+ struct usb_interface *intf;
+ mutex_lock(&ua->mutex);
free_stream_urbs(&ua->capture);
free_stream_urbs(&ua->playback);
+ mutex_unlock(&ua->mutex);
free_stream_buffers(ua, &ua->capture);
free_stream_buffers(ua, &ua->playback);
- for (i = 0; i < ARRAY_SIZE(ua->intf); ++i)
- if (ua->intf[i]) {
- usb_set_intfdata(ua->intf[i], NULL);
- if (ua->intf[i] != interface)
+ for (i = 0; i < ARRAY_SIZE(ua->intf); ++i) {
+ mutex_lock(&ua->mutex);
+ intf = ua->intf[i];
+ ua->intf[i] = NULL;
+ mutex_unlock(&ua->mutex);
+ if (intf) {
+ usb_set_intfdata(intf, NULL);
+ if (intf != interface)
usb_driver_release_interface(&ua101_driver,
- ua->intf[i]);
+ intf);
}
+ }
}
static void ua101_card_free(struct snd_card *card)
@@ -1373,16 +1387,4 @@ static struct usb_driver ua101_driver = {
#endif
};
-static int __init alsa_card_ua101_init(void)
-{
- return usb_register(&ua101_driver);
-}
-
-static void __exit alsa_card_ua101_exit(void)
-{
- usb_deregister(&ua101_driver);
- mutex_destroy(&devices_mutex);
-}
-
-module_init(alsa_card_ua101_init);
-module_exit(alsa_card_ua101_exit);
+module_usb_driver(ua101_driver);
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index cdd19d7fe500..ab23869c01bb 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -296,7 +296,7 @@ static int get_ctl_value_v1(struct usb_mixer_elem_info *cval, int request, int v
if (snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
- buf, val_len, 100) >= val_len) {
+ buf, val_len) >= val_len) {
*value_ret = convert_signed_value(cval, snd_usb_combine_bytes(buf, val_len));
snd_usb_autosuspend(cval->mixer->chip);
return 0;
@@ -333,7 +333,7 @@ static int get_ctl_value_v2(struct usb_mixer_elem_info *cval, int request, int v
ret = snd_usb_ctl_msg(chip->dev, usb_rcvctrlpipe(chip->dev, 0), bRequest,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_IN,
validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
- buf, size, 1000);
+ buf, size);
snd_usb_autosuspend(chip);
if (ret < 0) {
@@ -445,7 +445,7 @@ int snd_usb_mixer_set_ctl_value(struct usb_mixer_elem_info *cval,
usb_sndctrlpipe(chip->dev, 0), request,
USB_RECIP_INTERFACE | USB_TYPE_CLASS | USB_DIR_OUT,
validx, snd_usb_ctrl_intf(chip) | (cval->id << 8),
- buf, val_len, 100) >= 0) {
+ buf, val_len) >= 0) {
snd_usb_autosuspend(chip);
return 0;
}
@@ -765,10 +765,61 @@ static void usb_mixer_elem_free(struct snd_kcontrol *kctl)
* interface to ALSA control for feature/mixer units
*/
+/* volume control quirks */
+static void volume_control_quirks(struct usb_mixer_elem_info *cval,
+ struct snd_kcontrol *kctl)
+{
+ switch (cval->mixer->chip->usb_id) {
+ case USB_ID(0x0471, 0x0101):
+ case USB_ID(0x0471, 0x0104):
+ case USB_ID(0x0471, 0x0105):
+ case USB_ID(0x0672, 0x1041):
+ /* quirk for UDA1321/N101.
+ * note that detection between firmware 2.1.1.7 (N101)
+ * and later 2.1.1.21 is not very clear from datasheets.
+ * I hope that the min value is -15360 for newer firmware --jk
+ */
+ if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
+ cval->min == -15616) {
+ snd_printk(KERN_INFO
+ "set volume quirk for UDA1321/N101 chip\n");
+ cval->max = -256;
+ }
+ break;
+
+ case USB_ID(0x046d, 0x09a4):
+ if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+ snd_printk(KERN_INFO
+ "set volume quirk for QuickCam E3500\n");
+ cval->min = 6080;
+ cval->max = 8768;
+ cval->res = 192;
+ }
+ break;
+
+ case USB_ID(0x046d, 0x0808):
+ case USB_ID(0x046d, 0x0809):
+ case USB_ID(0x046d, 0x081d): /* HD Webcam c510 */
+ case USB_ID(0x046d, 0x0991):
+ /* Most audio usb devices lie about volume resolution.
+ * Most Logitech webcams have res = 384.
+ * Proboly there is some logitech magic behind this number --fishor
+ */
+ if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
+ snd_printk(KERN_INFO
+ "set resolution quirk: cval->res = 384\n");
+ cval->res = 384;
+ }
+ break;
+
+ }
+}
+
/*
* retrieve the minimum and maximum values for the specified control
*/
-static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
+static int get_min_max_with_quirks(struct usb_mixer_elem_info *cval,
+ int default_min, struct snd_kcontrol *kctl)
{
/* for failsafe */
cval->min = default_min;
@@ -844,6 +895,9 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
cval->initialized = 1;
}
+ if (kctl)
+ volume_control_quirks(cval, kctl);
+
/* USB descriptions contain the dB scale in 1/256 dB unit
* while ALSA TLV contains in 1/100 dB unit
*/
@@ -864,6 +918,7 @@ static int get_min_max(struct usb_mixer_elem_info *cval, int default_min)
return 0;
}
+#define get_min_max(cval, def) get_min_max_with_quirks(cval, def, NULL)
/* get a feature/mixer unit info */
static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
@@ -881,8 +936,17 @@ static int mixer_ctl_feature_info(struct snd_kcontrol *kcontrol, struct snd_ctl_
uinfo->value.integer.min = 0;
uinfo->value.integer.max = 1;
} else {
- if (! cval->initialized)
- get_min_max(cval, 0);
+ if (!cval->initialized) {
+ get_min_max_with_quirks(cval, 0, kcontrol);
+ if (cval->initialized && cval->dBmin >= cval->dBmax) {
+ kcontrol->vd[0].access &=
+ ~(SNDRV_CTL_ELEM_ACCESS_TLV_READ |
+ SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK);
+ snd_ctl_notify(cval->mixer->chip->card,
+ SNDRV_CTL_EVENT_MASK_INFO,
+ &kcontrol->id);
+ }
+ }
uinfo->value.integer.min = 0;
uinfo->value.integer.max =
(cval->max - cval->min + cval->res - 1) / cval->res;
@@ -1036,9 +1100,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
cval->ch_readonly = readonly_mask;
}
- /* get min/max values */
- get_min_max(cval, 0);
-
/* if all channels in the mask are marked read-only, make the control
* read-only. set_cur_mix_value() will check the mask again and won't
* issue write commands to read-only channels. */
@@ -1060,6 +1121,9 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
len = snd_usb_copy_string_desc(state, nameid,
kctl->id.name, sizeof(kctl->id.name));
+ /* get min/max values */
+ get_min_max_with_quirks(cval, 0, kctl);
+
switch (control) {
case UAC_FU_MUTE:
case UAC_FU_VOLUME:
@@ -1109,51 +1173,6 @@ static void build_feature_ctl(struct mixer_build *state, void *raw_desc,
break;
}
- /* volume control quirks */
- switch (state->chip->usb_id) {
- case USB_ID(0x0471, 0x0101):
- case USB_ID(0x0471, 0x0104):
- case USB_ID(0x0471, 0x0105):
- case USB_ID(0x0672, 0x1041):
- /* quirk for UDA1321/N101.
- * note that detection between firmware 2.1.1.7 (N101)
- * and later 2.1.1.21 is not very clear from datasheets.
- * I hope that the min value is -15360 for newer firmware --jk
- */
- if (!strcmp(kctl->id.name, "PCM Playback Volume") &&
- cval->min == -15616) {
- snd_printk(KERN_INFO
- "set volume quirk for UDA1321/N101 chip\n");
- cval->max = -256;
- }
- break;
-
- case USB_ID(0x046d, 0x09a4):
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- snd_printk(KERN_INFO
- "set volume quirk for QuickCam E3500\n");
- cval->min = 6080;
- cval->max = 8768;
- cval->res = 192;
- }
- break;
-
- case USB_ID(0x046d, 0x0808):
- case USB_ID(0x046d, 0x0809):
- case USB_ID(0x046d, 0x0991):
- /* Most audio usb devices lie about volume resolution.
- * Most Logitech webcams have res = 384.
- * Proboly there is some logitech magic behind this number --fishor
- */
- if (!strcmp(kctl->id.name, "Mic Capture Volume")) {
- snd_printk(KERN_INFO
- "set resolution quirk: cval->res = 384\n");
- cval->res = 384;
- }
- break;
-
- }
-
range = (cval->max - cval->min) / cval->res;
/* Are there devices with volume range more than 255? I use a bit more
* to be sure. 384 is a resolution magic number found on Logitech
@@ -1250,7 +1269,7 @@ static int parse_audio_feature_unit(struct mixer_build *state, int unitid, void
build_feature_ctl(state, _ftr, 0, i, &iterm, unitid, 0);
}
} else { /* UAC_VERSION_2 */
- for (i = 0; i < 30/2; i++) {
+ for (i = 0; i < ARRAY_SIZE(audio_feature_info); i++) {
unsigned int ch_bits = 0;
unsigned int ch_read_only = 0;
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 3d0f4873112b..ab125ee0b0f0 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -190,18 +190,18 @@ static int snd_audigy2nx_led_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
err = snd_usb_ctl_msg(mixer->chip->dev,
usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- !value, 0, NULL, 0, 100);
+ !value, 0, NULL, 0);
/* USB X-Fi S51 Pro */
if (mixer->chip->usb_id == USB_ID(0x041e, 0x30df))
err = snd_usb_ctl_msg(mixer->chip->dev,
usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- !value, 0, NULL, 0, 100);
+ !value, 0, NULL, 0);
else
err = snd_usb_ctl_msg(mixer->chip->dev,
usb_sndctrlpipe(mixer->chip->dev, 0), 0x24,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- value, index + 2, NULL, 0, 100);
+ value, index + 2, NULL, 0);
if (err < 0)
return err;
mixer->audigy2nx_leds[index] = value;
@@ -299,7 +299,7 @@ static void snd_audigy2nx_proc_read(struct snd_info_entry *entry,
usb_rcvctrlpipe(mixer->chip->dev, 0),
UAC_GET_MEM, USB_DIR_IN | USB_TYPE_CLASS |
USB_RECIP_INTERFACE, 0,
- jacks[i].unitid << 8, buf, 3, 100);
+ jacks[i].unitid << 8, buf, 3);
if (err == 3 && (buf[0] == 3 || buf[0] == 6))
snd_iprintf(buffer, "%02x %02x\n", buf[1], buf[2]);
else
@@ -332,7 +332,7 @@ static int snd_xonar_u1_switch_put(struct snd_kcontrol *kcontrol,
err = snd_usb_ctl_msg(mixer->chip->dev,
usb_sndctrlpipe(mixer->chip->dev, 0), 0x08,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- 50, 0, &new_status, 1, 100);
+ 50, 0, &new_status, 1);
if (err < 0)
return err;
mixer->xonar_u1_status = new_status;
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index b8dcbf407bbb..0eed6115c2d4 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -28,12 +28,36 @@
#include "card.h"
#include "quirks.h"
#include "debug.h"
-#include "urb.h"
+#include "endpoint.h"
#include "helper.h"
#include "pcm.h"
#include "clock.h"
#include "power.h"
+/* return the estimated delay based on USB frame counters */
+snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
+ unsigned int rate)
+{
+ int current_frame_number;
+ int frame_diff;
+ int est_delay;
+
+ current_frame_number = usb_get_current_frame_number(subs->dev);
+ /*
+ * HCD implementations use different widths, use lower 8 bits.
+ * The delay will be managed up to 256ms, which is more than
+ * enough
+ */
+ frame_diff = (current_frame_number - subs->last_frame_number) & 0xff;
+
+ /* Approximation based on number of samples per USB frame (ms),
+ some truncation for 44.1 but the estimate is good enough */
+ est_delay = subs->last_delay - (frame_diff * rate / 1000);
+ if (est_delay < 0)
+ est_delay = 0;
+ return est_delay;
+}
+
/*
* return the current pcm pointer. just based on the hwptr_done value.
*/
@@ -45,6 +69,8 @@ static snd_pcm_uframes_t snd_usb_pcm_pointer(struct snd_pcm_substream *substream
subs = (struct snd_usb_substream *)substream->runtime->private_data;
spin_lock(&subs->lock);
hwptr_done = subs->hwptr_done;
+ substream->runtime->delay = snd_usb_pcm_delay(subs,
+ substream->runtime->rate);
spin_unlock(&subs->lock);
return hwptr_done / (substream->runtime->frame_bits >> 3);
}
@@ -126,7 +152,7 @@ static int init_pitch_v1(struct snd_usb_audio *chip, int iface,
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC_SET_CUR,
USB_TYPE_CLASS|USB_RECIP_ENDPOINT|USB_DIR_OUT,
UAC_EP_CS_ATTR_PITCH_CONTROL << 8, ep,
- data, sizeof(data), 1000)) < 0) {
+ data, sizeof(data))) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH\n",
dev->devnum, iface, ep);
return err;
@@ -150,7 +176,7 @@ static int init_pitch_v2(struct snd_usb_audio *chip, int iface,
if ((err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), UAC2_CS_CUR,
USB_TYPE_CLASS | USB_RECIP_ENDPOINT | USB_DIR_OUT,
UAC2_EP_CS_PITCH << 8, 0,
- data, sizeof(data), 1000)) < 0) {
+ data, sizeof(data))) < 0) {
snd_printk(KERN_ERR "%d:%d:%d: cannot set enable PITCH (v2)\n",
dev->devnum, iface, fmt->altsetting);
return err;
@@ -417,6 +443,8 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
subs->hwptr_done = 0;
subs->transfer_done = 0;
subs->phase = 0;
+ subs->last_delay = 0;
+ subs->last_frame_number = 0;
runtime->delay = 0;
return snd_usb_substream_prepare(subs, runtime);
@@ -667,6 +695,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
struct snd_usb_substream *subs)
{
struct audioformat *fp;
+ int *rate_list;
int count = 0, needs_knot = 0;
int err;
@@ -680,7 +709,8 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
if (!needs_knot)
return 0;
- subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL);
+ subs->rate_list.list = rate_list =
+ kmalloc(sizeof(int) * count, GFP_KERNEL);
if (!subs->rate_list.list)
return -ENOMEM;
subs->rate_list.count = count;
@@ -689,7 +719,7 @@ static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
list_for_each_entry(fp, &subs->fmt_list, list) {
int i;
for (i = 0; i < fp->nr_rates; i++)
- subs->rate_list.list[count++] = fp->rate_table[i];
+ rate_list[count++] = fp->rate_table[i];
}
err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
&subs->rate_list);
diff --git a/sound/usb/pcm.h b/sound/usb/pcm.h
index ed3e283f618d..df7a003682ad 100644
--- a/sound/usb/pcm.h
+++ b/sound/usb/pcm.h
@@ -1,6 +1,9 @@
#ifndef __USBAUDIO_PCM_H
#define __USBAUDIO_PCM_H
+snd_pcm_uframes_t snd_usb_pcm_delay(struct snd_usb_substream *subs,
+ unsigned int rate);
+
void snd_usb_set_pcm_ops(struct snd_pcm *pcm, int stream);
int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index a42e3ef3832d..d89ab4c7d44b 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -39,6 +39,17 @@
.idProduct = prod, \
.bInterfaceClass = USB_CLASS_VENDOR_SPEC
+/* FTDI devices */
+{
+ USB_DEVICE(0x0403, 0xb8d8),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ /* .vendor_name = "STARR LABS", */
+ /* .product_name = "Starr Labs MIDI USB device", */
+ .ifnum = 0,
+ .type = QUIRK_MIDI_FTDI
+ }
+},
+
/* Creative/Toshiba Multimedia Center SB-0500 */
{
USB_DEVICE(0x041e, 0x3048),
@@ -258,6 +269,32 @@ YAMAHA_DEVICE(0x105a, NULL),
YAMAHA_DEVICE(0x105b, NULL),
YAMAHA_DEVICE(0x105c, NULL),
YAMAHA_DEVICE(0x105d, NULL),
+{
+ USB_DEVICE(0x0499, 0x1503),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ /* .vendor_name = "Yamaha", */
+ /* .product_name = "MOX6/MOX8", */
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 3,
+ .type = QUIRK_MIDI_YAMAHA
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
YAMAHA_DEVICE(0x2000, "DGP-7"),
YAMAHA_DEVICE(0x2001, "DGP-5"),
YAMAHA_DEVICE(0x2002, NULL),
@@ -1581,6 +1618,14 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ /* Edirol UM-3G */
+ USB_DEVICE_VENDOR_SPEC(0x0582, 0x0108),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .ifnum = 0,
+ .type = QUIRK_MIDI_STANDARD_INTERFACE
+ }
+},
+{
/* Boss JS-8 Jam Station */
USB_DEVICE(0x0582, 0x0109),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
@@ -1622,6 +1667,37 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ /* Roland GAIA SH-01 */
+ USB_DEVICE(0x0582, 0x0111),
+ .driver_info = (unsigned long) &(const struct snd_usb_audio_quirk) {
+ .vendor_name = "Roland",
+ .product_name = "GAIA",
+ .ifnum = QUIRK_ANY_INTERFACE,
+ .type = QUIRK_COMPOSITE,
+ .data = (const struct snd_usb_audio_quirk[]) {
+ {
+ .ifnum = 0,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 1,
+ .type = QUIRK_AUDIO_STANDARD_INTERFACE
+ },
+ {
+ .ifnum = 2,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = &(const struct snd_usb_midi_endpoint_info) {
+ .out_cables = 0x0003,
+ .in_cables = 0x0003
+ }
+ },
+ {
+ .ifnum = -1
+ }
+ }
+ }
+},
+{
USB_DEVICE(0x0582, 0x0113),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
/* .vendor_name = "BOSS", */
@@ -1678,6 +1754,20 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
{
+ /* Added support for Roland UM-ONE which differs from UM-1 */
+ USB_DEVICE(0x0582, 0x012a),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ /* .vendor_name = "ROLAND", */
+ /* .product_name = "UM-ONE", */
+ .ifnum = 0,
+ .type = QUIRK_MIDI_FIXED_ENDPOINT,
+ .data = & (const struct snd_usb_midi_endpoint_info) {
+ .out_cables = 0x0001,
+ .in_cables = 0x0003
+ }
+ }
+},
+{
USB_DEVICE(0x0582, 0x011e),
.driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
/* .vendor_name = "BOSS", */
@@ -2280,6 +2370,16 @@ YAMAHA_DEVICE(0x7010, "UB99"),
}
},
+{
+ USB_DEVICE_VENDOR_SPEC(0x0944, 0x0201),
+ .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
+ .vendor_name = "KORG, Inc.",
+ /* .product_name = "ToneLab ST", */
+ .ifnum = 3,
+ .type = QUIRK_MIDI_STANDARD_INTERFACE,
+ }
+},
+
/* AKAI devices */
{
USB_DEVICE(0x09e8, 0x0062),
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 81e07d842581..27817266867a 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -34,6 +34,7 @@
#include "endpoint.h"
#include "pcm.h"
#include "clock.h"
+#include "stream.h"
/*
* handle the quirks for the contained interfaces
@@ -106,7 +107,7 @@ static int create_standard_audio_quirk(struct snd_usb_audio *chip,
alts = &iface->altsetting[0];
altsd = get_iface_desc(alts);
- err = snd_usb_parse_audio_endpoints(chip, altsd->bInterfaceNumber);
+ err = snd_usb_parse_audio_interface(chip, altsd->bInterfaceNumber);
if (err < 0) {
snd_printk(KERN_ERR "cannot setup if %d: error %d\n",
altsd->bInterfaceNumber, err);
@@ -131,23 +132,27 @@ static int create_fixed_stream_quirk(struct snd_usb_audio *chip,
unsigned *rate_table = NULL;
fp = kmemdup(quirk->data, sizeof(*fp), GFP_KERNEL);
- if (! fp) {
+ if (!fp) {
snd_printk(KERN_ERR "cannot memdup\n");
return -ENOMEM;
}
+ if (fp->nr_rates > MAX_NR_RATES) {
+ kfree(fp);
+ return -EINVAL;
+ }
if (fp->nr_rates > 0) {
- rate_table = kmalloc(sizeof(int) * fp->nr_rates, GFP_KERNEL);
+ rate_table = kmemdup(fp->rate_table,
+ sizeof(int) * fp->nr_rates, GFP_KERNEL);
if (!rate_table) {
kfree(fp);
return -ENOMEM;
}
- memcpy(rate_table, fp->rate_table, sizeof(int) * fp->nr_rates);
fp->rate_table = rate_table;
}
stream = (fp->endpoint & USB_DIR_IN)
? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
- err = snd_usb_add_audio_endpoint(chip, stream, fp);
+ err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0) {
kfree(fp);
kfree(rate_table);
@@ -223,10 +228,9 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
if (altsd->bNumEndpoints != 1)
return -ENXIO;
- fp = kmalloc(sizeof(*fp), GFP_KERNEL);
+ fp = kmemdup(&ua_format, sizeof(*fp), GFP_KERNEL);
if (!fp)
return -ENOMEM;
- memcpy(fp, &ua_format, sizeof(*fp));
fp->iface = altsd->bInterfaceNumber;
fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
@@ -254,7 +258,7 @@ static int create_uaxx_quirk(struct snd_usb_audio *chip,
stream = (fp->endpoint & USB_DIR_IN)
? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
- err = snd_usb_add_audio_endpoint(chip, stream, fp);
+ err = snd_usb_add_audio_stream(chip, stream, fp);
if (err < 0) {
kfree(fp);
return err;
@@ -306,6 +310,7 @@ int snd_usb_create_quirk(struct snd_usb_audio *chip,
[QUIRK_MIDI_EMAGIC] = create_any_midi_quirk,
[QUIRK_MIDI_CME] = create_any_midi_quirk,
[QUIRK_MIDI_AKAI] = create_any_midi_quirk,
+ [QUIRK_MIDI_FTDI] = create_any_midi_quirk,
[QUIRK_AUDIO_STANDARD_INTERFACE] = create_standard_audio_quirk,
[QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
[QUIRK_AUDIO_EDIROL_UAXX] = create_uaxx_quirk,
@@ -338,7 +343,7 @@ static int snd_usb_extigy_boot_quirk(struct usb_device *dev, struct usb_interfac
snd_printdd("sending Extigy boot sequence...\n");
/* Send message to force it to reconnect with full interface. */
err = snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev,0),
- 0x10, 0x43, 0x0001, 0x000a, NULL, 0, 1000);
+ 0x10, 0x43, 0x0001, 0x000a, NULL, 0);
if (err < 0) snd_printdd("error sending boot message: %d\n", err);
err = usb_get_descriptor(dev, USB_DT_DEVICE, 0,
&dev->descriptor, sizeof(dev->descriptor));
@@ -359,11 +364,11 @@ static int snd_usb_audigy2nx_boot_quirk(struct usb_device *dev)
snd_usb_ctl_msg(dev, usb_rcvctrlpipe(dev, 0), 0x2a,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- 0, 0, &buf, 1, 1000);
+ 0, 0, &buf, 1);
if (buf == 0) {
snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), 0x29,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_OTHER,
- 1, 2000, NULL, 0, 1000);
+ 1, 2000, NULL, 0);
return -ENODEV;
}
return 0;
@@ -406,7 +411,7 @@ static int snd_usb_cm106_write_int_reg(struct usb_device *dev, int reg, u16 valu
buf[3] = reg;
return snd_usb_ctl_msg(dev, usb_sndctrlpipe(dev, 0), USB_REQ_SET_CONFIGURATION,
USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_ENDPOINT,
- 0, 0, &buf, 4, 1000);
+ 0, 0, &buf, 4);
}
static int snd_usb_cm106_boot_quirk(struct usb_device *dev)
diff --git a/sound/usb/stream.c b/sound/usb/stream.c
new file mode 100644
index 000000000000..5ff8010b2d6f
--- /dev/null
+++ b/sound/usb/stream.c
@@ -0,0 +1,452 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/audio.h>
+#include <linux/usb/audio-v2.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "usbaudio.h"
+#include "card.h"
+#include "proc.h"
+#include "quirks.h"
+#include "endpoint.h"
+#include "pcm.h"
+#include "helper.h"
+#include "format.h"
+#include "clock.h"
+#include "stream.h"
+
+/*
+ * free a substream
+ */
+static void free_substream(struct snd_usb_substream *subs)
+{
+ struct list_head *p, *n;
+
+ if (!subs->num_formats)
+ return; /* not initialized */
+ list_for_each_safe(p, n, &subs->fmt_list) {
+ struct audioformat *fp = list_entry(p, struct audioformat, list);
+ kfree(fp->rate_table);
+ kfree(fp);
+ }
+ kfree(subs->rate_list.list);
+}
+
+
+/*
+ * free a usb stream instance
+ */
+static void snd_usb_audio_stream_free(struct snd_usb_stream *stream)
+{
+ free_substream(&stream->substream[0]);
+ free_substream(&stream->substream[1]);
+ list_del(&stream->list);
+ kfree(stream);
+}
+
+static void snd_usb_audio_pcm_free(struct snd_pcm *pcm)
+{
+ struct snd_usb_stream *stream = pcm->private_data;
+ if (stream) {
+ stream->pcm = NULL;
+ snd_usb_audio_stream_free(stream);
+ }
+}
+
+
+/*
+ * add this endpoint to the chip instance.
+ * if a stream with the same endpoint already exists, append to it.
+ * if not, create a new pcm stream.
+ */
+int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
+ int stream,
+ struct audioformat *fp)
+{
+ struct list_head *p;
+ struct snd_usb_stream *as;
+ struct snd_usb_substream *subs;
+ struct snd_pcm *pcm;
+ int err;
+
+ list_for_each(p, &chip->pcm_list) {
+ as = list_entry(p, struct snd_usb_stream, list);
+ if (as->fmt_type != fp->fmt_type)
+ continue;
+ subs = &as->substream[stream];
+ if (!subs->endpoint)
+ continue;
+ if (subs->endpoint == fp->endpoint) {
+ list_add_tail(&fp->list, &subs->fmt_list);
+ subs->num_formats++;
+ subs->formats |= fp->formats;
+ return 0;
+ }
+ }
+ /* look for an empty stream */
+ list_for_each(p, &chip->pcm_list) {
+ as = list_entry(p, struct snd_usb_stream, list);
+ if (as->fmt_type != fp->fmt_type)
+ continue;
+ subs = &as->substream[stream];
+ if (subs->endpoint)
+ continue;
+ err = snd_pcm_new_stream(as->pcm, stream, 1);
+ if (err < 0)
+ return err;
+ snd_usb_init_substream(as, stream, fp);
+ return 0;
+ }
+
+ /* create a new pcm */
+ as = kzalloc(sizeof(*as), GFP_KERNEL);
+ if (!as)
+ return -ENOMEM;
+ as->pcm_index = chip->pcm_devs;
+ as->chip = chip;
+ as->fmt_type = fp->fmt_type;
+ err = snd_pcm_new(chip->card, "USB Audio", chip->pcm_devs,
+ stream == SNDRV_PCM_STREAM_PLAYBACK ? 1 : 0,
+ stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1,
+ &pcm);
+ if (err < 0) {
+ kfree(as);
+ return err;
+ }
+ as->pcm = pcm;
+ pcm->private_data = as;
+ pcm->private_free = snd_usb_audio_pcm_free;
+ pcm->info_flags = 0;
+ if (chip->pcm_devs > 0)
+ sprintf(pcm->name, "USB Audio #%d", chip->pcm_devs);
+ else
+ strcpy(pcm->name, "USB Audio");
+
+ snd_usb_init_substream(as, stream, fp);
+
+ list_add(&as->list, &chip->pcm_list);
+ chip->pcm_devs++;
+
+ snd_usb_proc_pcm_format_add(as);
+
+ return 0;
+}
+
+static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
+ struct usb_host_interface *alts,
+ int protocol, int iface_no)
+{
+ /* parsed with a v1 header here. that's ok as we only look at the
+ * header first which is the same for both versions */
+ struct uac_iso_endpoint_descriptor *csep;
+ struct usb_interface_descriptor *altsd = get_iface_desc(alts);
+ int attributes = 0;
+
+ csep = snd_usb_find_desc(alts->endpoint[0].extra, alts->endpoint[0].extralen, NULL, USB_DT_CS_ENDPOINT);
+
+ /* Creamware Noah has this descriptor after the 2nd endpoint */
+ if (!csep && altsd->bNumEndpoints >= 2)
+ csep = snd_usb_find_desc(alts->endpoint[1].extra, alts->endpoint[1].extralen, NULL, USB_DT_CS_ENDPOINT);
+
+ if (!csep || csep->bLength < 7 ||
+ csep->bDescriptorSubtype != UAC_EP_GENERAL) {
+ snd_printk(KERN_WARNING "%d:%u:%d : no or invalid"
+ " class specific endpoint descriptor\n",
+ chip->dev->devnum, iface_no,
+ altsd->bAlternateSetting);
+ return 0;
+ }
+
+ if (protocol == UAC_VERSION_1) {
+ attributes = csep->bmAttributes;
+ } else {
+ struct uac2_iso_endpoint_descriptor *csep2 =
+ (struct uac2_iso_endpoint_descriptor *) csep;
+
+ attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
+
+ /* emulate the endpoint attributes of a v1 device */
+ if (csep2->bmControls & UAC2_CONTROL_PITCH)
+ attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
+ }
+
+ return attributes;
+}
+
+static struct uac2_input_terminal_descriptor *
+ snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+ int terminal_id)
+{
+ struct uac2_input_terminal_descriptor *term = NULL;
+
+ while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ term, UAC_INPUT_TERMINAL))) {
+ if (term->bTerminalID == terminal_id)
+ return term;
+ }
+
+ return NULL;
+}
+
+static struct uac2_output_terminal_descriptor *
+ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
+ int terminal_id)
+{
+ struct uac2_output_terminal_descriptor *term = NULL;
+
+ while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
+ ctrl_iface->extralen,
+ term, UAC_OUTPUT_TERMINAL))) {
+ if (term->bTerminalID == terminal_id)
+ return term;
+ }
+
+ return NULL;
+}
+
+int snd_usb_parse_audio_interface(struct snd_usb_audio *chip, int iface_no)
+{
+ struct usb_device *dev;
+ struct usb_interface *iface;
+ struct usb_host_interface *alts;
+ struct usb_interface_descriptor *altsd;
+ int i, altno, err, stream;
+ int format = 0, num_channels = 0;
+ struct audioformat *fp = NULL;
+ int num, protocol, clock = 0;
+ struct uac_format_type_i_continuous_descriptor *fmt;
+
+ dev = chip->dev;
+
+ /* parse the interface's altsettings */
+ iface = usb_ifnum_to_if(dev, iface_no);
+
+ num = iface->num_altsetting;
+
+ /*
+ * Dallas DS4201 workaround: It presents 5 altsettings, but the last
+ * one misses syncpipe, and does not produce any sound.
+ */
+ if (chip->usb_id == USB_ID(0x04fa, 0x4201))
+ num = 4;
+
+ for (i = 0; i < num; i++) {
+ alts = &iface->altsetting[i];
+ altsd = get_iface_desc(alts);
+ protocol = altsd->bInterfaceProtocol;
+ /* skip invalid one */
+ if ((altsd->bInterfaceClass != USB_CLASS_AUDIO &&
+ altsd->bInterfaceClass != USB_CLASS_VENDOR_SPEC) ||
+ (altsd->bInterfaceSubClass != USB_SUBCLASS_AUDIOSTREAMING &&
+ altsd->bInterfaceSubClass != USB_SUBCLASS_VENDOR_SPEC) ||
+ altsd->bNumEndpoints < 1 ||
+ le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) == 0)
+ continue;
+ /* must be isochronous */
+ if ((get_endpoint(alts, 0)->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK) !=
+ USB_ENDPOINT_XFER_ISOC)
+ continue;
+ /* check direction */
+ stream = (get_endpoint(alts, 0)->bEndpointAddress & USB_DIR_IN) ?
+ SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
+ altno = altsd->bAlternateSetting;
+
+ if (snd_usb_apply_interface_quirk(chip, iface_no, altno))
+ continue;
+
+ /* get audio formats */
+ switch (protocol) {
+ default:
+ snd_printdd(KERN_WARNING "%d:%u:%d: unknown interface protocol %#02x, assuming v1\n",
+ dev->devnum, iface_no, altno, protocol);
+ protocol = UAC_VERSION_1;
+ /* fall through */
+
+ case UAC_VERSION_1: {
+ struct uac1_as_header_descriptor *as =
+ snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+
+ if (!as) {
+ snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
+ dev->devnum, iface_no, altno);
+ continue;
+ }
+
+ if (as->bLength < sizeof(*as)) {
+ snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
+ dev->devnum, iface_no, altno);
+ continue;
+ }
+
+ format = le16_to_cpu(as->wFormatTag); /* remember the format value */
+ break;
+ }
+
+ case UAC_VERSION_2: {
+ struct uac2_input_terminal_descriptor *input_term;
+ struct uac2_output_terminal_descriptor *output_term;
+ struct uac2_as_header_descriptor *as =
+ snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_AS_GENERAL);
+
+ if (!as) {
+ snd_printk(KERN_ERR "%d:%u:%d : UAC_AS_GENERAL descriptor not found\n",
+ dev->devnum, iface_no, altno);
+ continue;
+ }
+
+ if (as->bLength < sizeof(*as)) {
+ snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_AS_GENERAL desc\n",
+ dev->devnum, iface_no, altno);
+ continue;
+ }
+
+ num_channels = as->bNrChannels;
+ format = le32_to_cpu(as->bmFormats);
+
+ /* lookup the terminal associated to this interface
+ * to extract the clock */
+ input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
+ as->bTerminalLink);
+ if (input_term) {
+ clock = input_term->bCSourceID;
+ break;
+ }
+
+ output_term = snd_usb_find_output_terminal_descriptor(chip->ctrl_intf,
+ as->bTerminalLink);
+ if (output_term) {
+ clock = output_term->bCSourceID;
+ break;
+ }
+
+ snd_printk(KERN_ERR "%d:%u:%d : bogus bTerminalLink %d\n",
+ dev->devnum, iface_no, altno, as->bTerminalLink);
+ continue;
+ }
+ }
+
+ /* get format type */
+ fmt = snd_usb_find_csint_desc(alts->extra, alts->extralen, NULL, UAC_FORMAT_TYPE);
+ if (!fmt) {
+ snd_printk(KERN_ERR "%d:%u:%d : no UAC_FORMAT_TYPE desc\n",
+ dev->devnum, iface_no, altno);
+ continue;
+ }
+ if (((protocol == UAC_VERSION_1) && (fmt->bLength < 8)) ||
+ ((protocol == UAC_VERSION_2) && (fmt->bLength < 6))) {
+ snd_printk(KERN_ERR "%d:%u:%d : invalid UAC_FORMAT_TYPE desc\n",
+ dev->devnum, iface_no, altno);
+ continue;
+ }
+
+ /*
+ * Blue Microphones workaround: The last altsetting is identical
+ * with the previous one, except for a larger packet size, but
+ * is actually a mislabeled two-channel setting; ignore it.
+ */
+ if (fmt->bNrChannels == 1 &&
+ fmt->bSubframeSize == 2 &&
+ altno == 2 && num == 3 &&
+ fp && fp->altsetting == 1 && fp->channels == 1 &&
+ fp->formats == SNDRV_PCM_FMTBIT_S16_LE &&
+ protocol == UAC_VERSION_1 &&
+ le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize) ==
+ fp->maxpacksize * 2)
+ continue;
+
+ fp = kzalloc(sizeof(*fp), GFP_KERNEL);
+ if (! fp) {
+ snd_printk(KERN_ERR "cannot malloc\n");
+ return -ENOMEM;
+ }
+
+ fp->iface = iface_no;
+ fp->altsetting = altno;
+ fp->altset_idx = i;
+ fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
+ fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
+ fp->datainterval = snd_usb_parse_datainterval(chip, alts);
+ fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
+ /* num_channels is only set for v2 interfaces */
+ fp->channels = num_channels;
+ if (snd_usb_get_speed(dev) == USB_SPEED_HIGH)
+ fp->maxpacksize = (((fp->maxpacksize >> 11) & 3) + 1)
+ * (fp->maxpacksize & 0x7ff);
+ fp->attributes = parse_uac_endpoint_attributes(chip, alts, protocol, iface_no);
+ fp->clock = clock;
+
+ /* some quirks for attributes here */
+
+ switch (chip->usb_id) {
+ case USB_ID(0x0a92, 0x0053): /* AudioTrak Optoplay */
+ /* Optoplay sets the sample rate attribute although
+ * it seems not supporting it in fact.
+ */
+ fp->attributes &= ~UAC_EP_CS_ATTR_SAMPLE_RATE;
+ break;
+ case USB_ID(0x041e, 0x3020): /* Creative SB Audigy 2 NX */
+ case USB_ID(0x0763, 0x2003): /* M-Audio Audiophile USB */
+ /* doesn't set the sample rate attribute, but supports it */
+ fp->attributes |= UAC_EP_CS_ATTR_SAMPLE_RATE;
+ break;
+ case USB_ID(0x0763, 0x2001): /* M-Audio Quattro USB */
+ case USB_ID(0x0763, 0x2012): /* M-Audio Fast Track Pro USB */
+ case USB_ID(0x047f, 0x0ca1): /* plantronics headset */
+ case USB_ID(0x077d, 0x07af): /* Griffin iMic (note that there is
+ an older model 77d:223) */
+ /*
+ * plantronics headset and Griffin iMic have set adaptive-in
+ * although it's really not...
+ */
+ fp->ep_attr &= ~USB_ENDPOINT_SYNCTYPE;
+ if (stream == SNDRV_PCM_STREAM_PLAYBACK)
+ fp->ep_attr |= USB_ENDPOINT_SYNC_ADAPTIVE;
+ else
+ fp->ep_attr |= USB_ENDPOINT_SYNC_SYNC;
+ break;
+ }
+
+ /* ok, let's parse further... */
+ if (snd_usb_parse_audio_format(chip, fp, format, fmt, stream, alts) < 0) {
+ kfree(fp->rate_table);
+ kfree(fp);
+ fp = NULL;
+ continue;
+ }
+
+ snd_printdd(KERN_INFO "%d:%u:%d: add audio endpoint %#x\n", dev->devnum, iface_no, altno, fp->endpoint);
+ err = snd_usb_add_audio_stream(chip, stream, fp);
+ if (err < 0) {
+ kfree(fp->rate_table);
+ kfree(fp);
+ return err;
+ }
+ /* try to set the interface... */
+ usb_set_interface(chip->dev, iface_no, altno);
+ snd_usb_init_pitch(chip, iface_no, alts, fp);
+ snd_usb_init_sample_rate(chip, iface_no, alts, fp, fp->rate_max);
+ }
+ return 0;
+}
+
diff --git a/sound/usb/stream.h b/sound/usb/stream.h
new file mode 100644
index 000000000000..c97f679fc84f
--- /dev/null
+++ b/sound/usb/stream.h
@@ -0,0 +1,12 @@
+#ifndef __USBAUDIO_STREAM_H
+#define __USBAUDIO_STREAM_H
+
+int snd_usb_parse_audio_interface(struct snd_usb_audio *chip,
+ int iface_no);
+
+int snd_usb_add_audio_stream(struct snd_usb_audio *chip,
+ int stream,
+ struct audioformat *fp);
+
+#endif /* __USBAUDIO_STREAM_H */
+
diff --git a/sound/usb/urb.c b/sound/usb/urb.c
deleted file mode 100644
index e184349aee83..000000000000
--- a/sound/usb/urb.c
+++ /dev/null
@@ -1,941 +0,0 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/gfp.h>
-#include <linux/init.h>
-#include <linux/usb.h>
-#include <linux/usb/audio.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-
-#include "usbaudio.h"
-#include "helper.h"
-#include "card.h"
-#include "urb.h"
-#include "pcm.h"
-
-/*
- * convert a sampling rate into our full speed format (fs/1000 in Q16.16)
- * this will overflow at approx 524 kHz
- */
-static inline unsigned get_usb_full_speed_rate(unsigned int rate)
-{
- return ((rate << 13) + 62) / 125;
-}
-
-/*
- * convert a sampling rate into USB high speed format (fs/8000 in Q16.16)
- * this will overflow at approx 4 MHz
- */
-static inline unsigned get_usb_high_speed_rate(unsigned int rate)
-{
- return ((rate << 10) + 62) / 125;
-}
-
-/*
- * unlink active urbs.
- */
-static int deactivate_urbs(struct snd_usb_substream *subs, int force, int can_sleep)
-{
- struct snd_usb_audio *chip = subs->stream->chip;
- unsigned int i;
- int async;
-
- subs->running = 0;
-
- if (!force && subs->stream->chip->shutdown) /* to be sure... */
- return -EBADFD;
-
- async = !can_sleep && chip->async_unlink;
-
- if (!async && in_interrupt())
- return 0;
-
- for (i = 0; i < subs->nurbs; i++) {
- if (test_bit(i, &subs->active_mask)) {
- if (!test_and_set_bit(i, &subs->unlink_mask)) {
- struct urb *u = subs->dataurb[i].urb;
- if (async)
- usb_unlink_urb(u);
- else
- usb_kill_urb(u);
- }
- }
- }
- if (subs->syncpipe) {
- for (i = 0; i < SYNC_URBS; i++) {
- if (test_bit(i+16, &subs->active_mask)) {
- if (!test_and_set_bit(i+16, &subs->unlink_mask)) {
- struct urb *u = subs->syncurb[i].urb;
- if (async)
- usb_unlink_urb(u);
- else
- usb_kill_urb(u);
- }
- }
- }
- }
- return 0;
-}
-
-
-/*
- * release a urb data
- */
-static void release_urb_ctx(struct snd_urb_ctx *u)
-{
- if (u->urb) {
- if (u->buffer_size)
- usb_free_coherent(u->subs->dev, u->buffer_size,
- u->urb->transfer_buffer,
- u->urb->transfer_dma);
- usb_free_urb(u->urb);
- u->urb = NULL;
- }
-}
-
-/*
- * wait until all urbs are processed.
- */
-static int wait_clear_urbs(struct snd_usb_substream *subs)
-{
- unsigned long end_time = jiffies + msecs_to_jiffies(1000);
- unsigned int i;
- int alive;
-
- do {
- alive = 0;
- for (i = 0; i < subs->nurbs; i++) {
- if (test_bit(i, &subs->active_mask))
- alive++;
- }
- if (subs->syncpipe) {
- for (i = 0; i < SYNC_URBS; i++) {
- if (test_bit(i + 16, &subs->active_mask))
- alive++;
- }
- }
- if (! alive)
- break;
- schedule_timeout_uninterruptible(1);
- } while (time_before(jiffies, end_time));
- if (alive)
- snd_printk(KERN_ERR "timeout: still %d active urbs..\n", alive);
- return 0;
-}
-
-/*
- * release a substream
- */
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force)
-{
- int i;
-
- /* stop urbs (to be sure) */
- deactivate_urbs(subs, force, 1);
- wait_clear_urbs(subs);
-
- for (i = 0; i < MAX_URBS; i++)
- release_urb_ctx(&subs->dataurb[i]);
- for (i = 0; i < SYNC_URBS; i++)
- release_urb_ctx(&subs->syncurb[i]);
- usb_free_coherent(subs->dev, SYNC_URBS * 4,
- subs->syncbuf, subs->sync_dma);
- subs->syncbuf = NULL;
- subs->nurbs = 0;
-}
-
-/*
- * complete callback from data urb
- */
-static void snd_complete_urb(struct urb *urb)
-{
- struct snd_urb_ctx *ctx = urb->context;
- struct snd_usb_substream *subs = ctx->subs;
- struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
- int err = 0;
-
- if ((subs->running && subs->ops.retire(subs, substream->runtime, urb)) ||
- !subs->running || /* can be stopped during retire callback */
- (err = subs->ops.prepare(subs, substream->runtime, urb)) < 0 ||
- (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- clear_bit(ctx->index, &subs->active_mask);
- if (err < 0) {
- snd_printd(KERN_ERR "cannot submit urb (err = %d)\n", err);
- snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
- }
- }
-}
-
-
-/*
- * complete callback from sync urb
- */
-static void snd_complete_sync_urb(struct urb *urb)
-{
- struct snd_urb_ctx *ctx = urb->context;
- struct snd_usb_substream *subs = ctx->subs;
- struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
- int err = 0;
-
- if ((subs->running && subs->ops.retire_sync(subs, substream->runtime, urb)) ||
- !subs->running || /* can be stopped during retire callback */
- (err = subs->ops.prepare_sync(subs, substream->runtime, urb)) < 0 ||
- (err = usb_submit_urb(urb, GFP_ATOMIC)) < 0) {
- clear_bit(ctx->index + 16, &subs->active_mask);
- if (err < 0) {
- snd_printd(KERN_ERR "cannot submit sync urb (err = %d)\n", err);
- snd_pcm_stop(substream, SNDRV_PCM_STATE_XRUN);
- }
- }
-}
-
-
-/*
- * initialize a substream for plaback/capture
- */
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
- unsigned int period_bytes,
- unsigned int rate,
- unsigned int frame_bits)
-{
- unsigned int maxsize, i;
- int is_playback = subs->direction == SNDRV_PCM_STREAM_PLAYBACK;
- unsigned int urb_packs, total_packs, packs_per_ms;
- struct snd_usb_audio *chip = subs->stream->chip;
-
- /* calculate the frequency in 16.16 format */
- if (snd_usb_get_speed(subs->dev) == USB_SPEED_FULL)
- subs->freqn = get_usb_full_speed_rate(rate);
- else
- subs->freqn = get_usb_high_speed_rate(rate);
- subs->freqm = subs->freqn;
- subs->freqshift = INT_MIN;
- /* calculate max. frequency */
- if (subs->maxpacksize) {
- /* whatever fits into a max. size packet */
- maxsize = subs->maxpacksize;
- subs->freqmax = (maxsize / (frame_bits >> 3))
- << (16 - subs->datainterval);
- } else {
- /* no max. packet size: just take 25% higher than nominal */
- subs->freqmax = subs->freqn + (subs->freqn >> 2);
- maxsize = ((subs->freqmax + 0xffff) * (frame_bits >> 3))
- >> (16 - subs->datainterval);
- }
- subs->phase = 0;
-
- if (subs->fill_max)
- subs->curpacksize = subs->maxpacksize;
- else
- subs->curpacksize = maxsize;
-
- if (snd_usb_get_speed(subs->dev) != USB_SPEED_FULL)
- packs_per_ms = 8 >> subs->datainterval;
- else
- packs_per_ms = 1;
-
- if (is_playback) {
- urb_packs = max(chip->nrpacks, 1);
- urb_packs = min(urb_packs, (unsigned int)MAX_PACKS);
- } else
- urb_packs = 1;
- urb_packs *= packs_per_ms;
- if (subs->syncpipe)
- urb_packs = min(urb_packs, 1U << subs->syncinterval);
-
- /* decide how many packets to be used */
- if (is_playback) {
- unsigned int minsize, maxpacks;
- /* determine how small a packet can be */
- minsize = (subs->freqn >> (16 - subs->datainterval))
- * (frame_bits >> 3);
- /* with sync from device, assume it can be 12% lower */
- if (subs->syncpipe)
- minsize -= minsize >> 3;
- minsize = max(minsize, 1u);
- total_packs = (period_bytes + minsize - 1) / minsize;
- /* we need at least two URBs for queueing */
- if (total_packs < 2) {
- total_packs = 2;
- } else {
- /* and we don't want too long a queue either */
- maxpacks = max(MAX_QUEUE * packs_per_ms, urb_packs * 2);
- total_packs = min(total_packs, maxpacks);
- }
- } else {
- while (urb_packs > 1 && urb_packs * maxsize >= period_bytes)
- urb_packs >>= 1;
- total_packs = MAX_URBS * urb_packs;
- }
- subs->nurbs = (total_packs + urb_packs - 1) / urb_packs;
- if (subs->nurbs > MAX_URBS) {
- /* too much... */
- subs->nurbs = MAX_URBS;
- total_packs = MAX_URBS * urb_packs;
- } else if (subs->nurbs < 2) {
- /* too little - we need at least two packets
- * to ensure contiguous playback/capture
- */
- subs->nurbs = 2;
- }
-
- /* allocate and initialize data urbs */
- for (i = 0; i < subs->nurbs; i++) {
- struct snd_urb_ctx *u = &subs->dataurb[i];
- u->index = i;
- u->subs = subs;
- u->packets = (i + 1) * total_packs / subs->nurbs
- - i * total_packs / subs->nurbs;
- u->buffer_size = maxsize * u->packets;
- if (subs->fmt_type == UAC_FORMAT_TYPE_II)
- u->packets++; /* for transfer delimiter */
- u->urb = usb_alloc_urb(u->packets, GFP_KERNEL);
- if (!u->urb)
- goto out_of_memory;
- u->urb->transfer_buffer =
- usb_alloc_coherent(subs->dev, u->buffer_size,
- GFP_KERNEL, &u->urb->transfer_dma);
- if (!u->urb->transfer_buffer)
- goto out_of_memory;
- u->urb->pipe = subs->datapipe;
- u->urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
- u->urb->interval = 1 << subs->datainterval;
- u->urb->context = u;
- u->urb->complete = snd_complete_urb;
- }
-
- if (subs->syncpipe) {
- /* allocate and initialize sync urbs */
- subs->syncbuf = usb_alloc_coherent(subs->dev, SYNC_URBS * 4,
- GFP_KERNEL, &subs->sync_dma);
- if (!subs->syncbuf)
- goto out_of_memory;
- for (i = 0; i < SYNC_URBS; i++) {
- struct snd_urb_ctx *u = &subs->syncurb[i];
- u->index = i;
- u->subs = subs;
- u->packets = 1;
- u->urb = usb_alloc_urb(1, GFP_KERNEL);
- if (!u->urb)
- goto out_of_memory;
- u->urb->transfer_buffer = subs->syncbuf + i * 4;
- u->urb->transfer_dma = subs->sync_dma + i * 4;
- u->urb->transfer_buffer_length = 4;
- u->urb->pipe = subs->syncpipe;
- u->urb->transfer_flags = URB_ISO_ASAP |
- URB_NO_TRANSFER_DMA_MAP;
- u->urb->number_of_packets = 1;
- u->urb->interval = 1 << subs->syncinterval;
- u->urb->context = u;
- u->urb->complete = snd_complete_sync_urb;
- }
- }
- return 0;
-
-out_of_memory:
- snd_usb_release_substream_urbs(subs, 0);
- return -ENOMEM;
-}
-
-/*
- * prepare urb for full speed capture sync pipe
- *
- * fill the length and offset of each urb descriptor.
- * the fixed 10.14 frequency is passed through the pipe.
- */
-static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- unsigned char *cp = urb->transfer_buffer;
- struct snd_urb_ctx *ctx = urb->context;
-
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = 3;
- urb->iso_frame_desc[0].offset = 0;
- cp[0] = subs->freqn >> 2;
- cp[1] = subs->freqn >> 10;
- cp[2] = subs->freqn >> 18;
- return 0;
-}
-
-/*
- * prepare urb for high speed capture sync pipe
- *
- * fill the length and offset of each urb descriptor.
- * the fixed 12.13 frequency is passed as 16.16 through the pipe.
- */
-static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- unsigned char *cp = urb->transfer_buffer;
- struct snd_urb_ctx *ctx = urb->context;
-
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = 4;
- urb->iso_frame_desc[0].offset = 0;
- cp[0] = subs->freqn;
- cp[1] = subs->freqn >> 8;
- cp[2] = subs->freqn >> 16;
- cp[3] = subs->freqn >> 24;
- return 0;
-}
-
-/*
- * process after capture sync complete
- * - nothing to do
- */
-static int retire_capture_sync_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- return 0;
-}
-
-/*
- * prepare urb for capture data pipe
- *
- * fill the offset and length of each descriptor.
- *
- * we use a temporary buffer to write the captured data.
- * since the length of written data is determined by host, we cannot
- * write onto the pcm buffer directly... the data is thus copied
- * later at complete callback to the global buffer.
- */
-static int prepare_capture_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- int i, offs;
- struct snd_urb_ctx *ctx = urb->context;
-
- offs = 0;
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- for (i = 0; i < ctx->packets; i++) {
- urb->iso_frame_desc[i].offset = offs;
- urb->iso_frame_desc[i].length = subs->curpacksize;
- offs += subs->curpacksize;
- }
- urb->transfer_buffer_length = offs;
- urb->number_of_packets = ctx->packets;
- return 0;
-}
-
-/*
- * process after capture complete
- *
- * copy the data from each desctiptor to the pcm buffer, and
- * update the current position.
- */
-static int retire_capture_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- unsigned long flags;
- unsigned char *cp;
- int i;
- unsigned int stride, frames, bytes, oldptr;
- int period_elapsed = 0;
-
- stride = runtime->frame_bits >> 3;
-
- for (i = 0; i < urb->number_of_packets; i++) {
- cp = (unsigned char *)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
- if (urb->iso_frame_desc[i].status) {
- snd_printd(KERN_ERR "frame %d active: %d\n", i, urb->iso_frame_desc[i].status);
- // continue;
- }
- bytes = urb->iso_frame_desc[i].actual_length;
- frames = bytes / stride;
- if (!subs->txfr_quirk)
- bytes = frames * stride;
- if (bytes % (runtime->sample_bits >> 3) != 0) {
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- int oldbytes = bytes;
-#endif
- bytes = frames * stride;
- snd_printdd(KERN_ERR "Corrected urb data len. %d->%d\n",
- oldbytes, bytes);
- }
- /* update the current pointer */
- spin_lock_irqsave(&subs->lock, flags);
- oldptr = subs->hwptr_done;
- subs->hwptr_done += bytes;
- if (subs->hwptr_done >= runtime->buffer_size * stride)
- subs->hwptr_done -= runtime->buffer_size * stride;
- frames = (bytes + (oldptr % stride)) / stride;
- subs->transfer_done += frames;
- if (subs->transfer_done >= runtime->period_size) {
- subs->transfer_done -= runtime->period_size;
- period_elapsed = 1;
- }
- spin_unlock_irqrestore(&subs->lock, flags);
- /* copy a data chunk */
- if (oldptr + bytes > runtime->buffer_size * stride) {
- unsigned int bytes1 =
- runtime->buffer_size * stride - oldptr;
- memcpy(runtime->dma_area + oldptr, cp, bytes1);
- memcpy(runtime->dma_area, cp + bytes1, bytes - bytes1);
- } else {
- memcpy(runtime->dma_area + oldptr, cp, bytes);
- }
- }
- if (period_elapsed)
- snd_pcm_period_elapsed(subs->pcm_substream);
- return 0;
-}
-
-/*
- * Process after capture complete when paused. Nothing to do.
- */
-static int retire_paused_capture_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- return 0;
-}
-
-
-/*
- * prepare urb for playback sync pipe
- *
- * set up the offset and length to receive the current frequency.
- */
-static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- struct snd_urb_ctx *ctx = urb->context;
-
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->iso_frame_desc[0].length = min(4u, ctx->subs->syncmaxsize);
- urb->iso_frame_desc[0].offset = 0;
- return 0;
-}
-
-/*
- * process after playback sync complete
- *
- * Full speed devices report feedback values in 10.14 format as samples per
- * frame, high speed devices in 16.16 format as samples per microframe.
- * Because the Audio Class 1 spec was written before USB 2.0, many high speed
- * devices use a wrong interpretation, some others use an entirely different
- * format. Therefore, we cannot predict what format any particular device uses
- * and must detect it automatically.
- */
-static int retire_playback_sync_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- unsigned int f;
- int shift;
- unsigned long flags;
-
- if (urb->iso_frame_desc[0].status != 0 ||
- urb->iso_frame_desc[0].actual_length < 3)
- return 0;
-
- f = le32_to_cpup(urb->transfer_buffer);
- if (urb->iso_frame_desc[0].actual_length == 3)
- f &= 0x00ffffff;
- else
- f &= 0x0fffffff;
- if (f == 0)
- return 0;
-
- if (unlikely(subs->freqshift == INT_MIN)) {
- /*
- * The first time we see a feedback value, determine its format
- * by shifting it left or right until it matches the nominal
- * frequency value. This assumes that the feedback does not
- * differ from the nominal value more than +50% or -25%.
- */
- shift = 0;
- while (f < subs->freqn - subs->freqn / 4) {
- f <<= 1;
- shift++;
- }
- while (f > subs->freqn + subs->freqn / 2) {
- f >>= 1;
- shift--;
- }
- subs->freqshift = shift;
- }
- else if (subs->freqshift >= 0)
- f <<= subs->freqshift;
- else
- f >>= -subs->freqshift;
-
- if (likely(f >= subs->freqn - subs->freqn / 8 && f <= subs->freqmax)) {
- /*
- * If the frequency looks valid, set it.
- * This value is referred to in prepare_playback_urb().
- */
- spin_lock_irqsave(&subs->lock, flags);
- subs->freqm = f;
- spin_unlock_irqrestore(&subs->lock, flags);
- } else {
- /*
- * Out of range; maybe the shift value is wrong.
- * Reset it so that we autodetect again the next time.
- */
- subs->freqshift = INT_MIN;
- }
-
- return 0;
-}
-
-/* determine the number of frames in the next packet */
-static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
-{
- if (subs->fill_max)
- return subs->maxframesize;
- else {
- subs->phase = (subs->phase & 0xffff)
- + (subs->freqm << subs->datainterval);
- return min(subs->phase >> 16, subs->maxframesize);
- }
-}
-
-/*
- * Prepare urb for streaming before playback starts or when paused.
- *
- * We don't have any data, so we send silence.
- */
-static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- unsigned int i, offs, counts;
- struct snd_urb_ctx *ctx = urb->context;
- int stride = runtime->frame_bits >> 3;
-
- offs = 0;
- urb->dev = ctx->subs->dev;
- for (i = 0; i < ctx->packets; ++i) {
- counts = snd_usb_audio_next_packet_size(subs);
- urb->iso_frame_desc[i].offset = offs * stride;
- urb->iso_frame_desc[i].length = counts * stride;
- offs += counts;
- }
- urb->number_of_packets = ctx->packets;
- urb->transfer_buffer_length = offs * stride;
- memset(urb->transfer_buffer,
- runtime->format == SNDRV_PCM_FORMAT_U8 ? 0x80 : 0,
- offs * stride);
- return 0;
-}
-
-/*
- * prepare urb for playback data pipe
- *
- * Since a URB can handle only a single linear buffer, we must use double
- * buffering when the data to be transferred overflows the buffer boundary.
- * To avoid inconsistencies when updating hwptr_done, we use double buffering
- * for all URBs.
- */
-static int prepare_playback_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- int i, stride;
- unsigned int counts, frames, bytes;
- unsigned long flags;
- int period_elapsed = 0;
- struct snd_urb_ctx *ctx = urb->context;
-
- stride = runtime->frame_bits >> 3;
-
- frames = 0;
- urb->dev = ctx->subs->dev; /* we need to set this at each time */
- urb->number_of_packets = 0;
- spin_lock_irqsave(&subs->lock, flags);
- for (i = 0; i < ctx->packets; i++) {
- counts = snd_usb_audio_next_packet_size(subs);
- /* set up descriptor */
- urb->iso_frame_desc[i].offset = frames * stride;
- urb->iso_frame_desc[i].length = counts * stride;
- frames += counts;
- urb->number_of_packets++;
- subs->transfer_done += counts;
- if (subs->transfer_done >= runtime->period_size) {
- subs->transfer_done -= runtime->period_size;
- period_elapsed = 1;
- if (subs->fmt_type == UAC_FORMAT_TYPE_II) {
- if (subs->transfer_done > 0) {
- /* FIXME: fill-max mode is not
- * supported yet */
- frames -= subs->transfer_done;
- counts -= subs->transfer_done;
- urb->iso_frame_desc[i].length =
- counts * stride;
- subs->transfer_done = 0;
- }
- i++;
- if (i < ctx->packets) {
- /* add a transfer delimiter */
- urb->iso_frame_desc[i].offset =
- frames * stride;
- urb->iso_frame_desc[i].length = 0;
- urb->number_of_packets++;
- }
- break;
- }
- }
- if (period_elapsed) /* finish at the period boundary */
- break;
- }
- bytes = frames * stride;
- if (subs->hwptr_done + bytes > runtime->buffer_size * stride) {
- /* err, the transferred area goes over buffer boundary. */
- unsigned int bytes1 =
- runtime->buffer_size * stride - subs->hwptr_done;
- memcpy(urb->transfer_buffer,
- runtime->dma_area + subs->hwptr_done, bytes1);
- memcpy(urb->transfer_buffer + bytes1,
- runtime->dma_area, bytes - bytes1);
- } else {
- memcpy(urb->transfer_buffer,
- runtime->dma_area + subs->hwptr_done, bytes);
- }
- subs->hwptr_done += bytes;
- if (subs->hwptr_done >= runtime->buffer_size * stride)
- subs->hwptr_done -= runtime->buffer_size * stride;
- runtime->delay += frames;
- spin_unlock_irqrestore(&subs->lock, flags);
- urb->transfer_buffer_length = bytes;
- if (period_elapsed)
- snd_pcm_period_elapsed(subs->pcm_substream);
- return 0;
-}
-
-/*
- * process after playback data complete
- * - decrease the delay count again
- */
-static int retire_playback_urb(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime,
- struct urb *urb)
-{
- unsigned long flags;
- int stride = runtime->frame_bits >> 3;
- int processed = urb->transfer_buffer_length / stride;
-
- spin_lock_irqsave(&subs->lock, flags);
- if (processed > runtime->delay)
- runtime->delay = 0;
- else
- runtime->delay -= processed;
- spin_unlock_irqrestore(&subs->lock, flags);
- return 0;
-}
-
-static const char *usb_error_string(int err)
-{
- switch (err) {
- case -ENODEV:
- return "no device";
- case -ENOENT:
- return "endpoint not enabled";
- case -EPIPE:
- return "endpoint stalled";
- case -ENOSPC:
- return "not enough bandwidth";
- case -ESHUTDOWN:
- return "device disabled";
- case -EHOSTUNREACH:
- return "device suspended";
- case -EINVAL:
- case -EAGAIN:
- case -EFBIG:
- case -EMSGSIZE:
- return "internal error";
- default:
- return "unknown error";
- }
-}
-
-/*
- * set up and start data/sync urbs
- */
-static int start_urbs(struct snd_usb_substream *subs, struct snd_pcm_runtime *runtime)
-{
- unsigned int i;
- int err;
-
- if (subs->stream->chip->shutdown)
- return -EBADFD;
-
- for (i = 0; i < subs->nurbs; i++) {
- if (snd_BUG_ON(!subs->dataurb[i].urb))
- return -EINVAL;
- if (subs->ops.prepare(subs, runtime, subs->dataurb[i].urb) < 0) {
- snd_printk(KERN_ERR "cannot prepare datapipe for urb %d\n", i);
- goto __error;
- }
- }
- if (subs->syncpipe) {
- for (i = 0; i < SYNC_URBS; i++) {
- if (snd_BUG_ON(!subs->syncurb[i].urb))
- return -EINVAL;
- if (subs->ops.prepare_sync(subs, runtime, subs->syncurb[i].urb) < 0) {
- snd_printk(KERN_ERR "cannot prepare syncpipe for urb %d\n", i);
- goto __error;
- }
- }
- }
-
- subs->active_mask = 0;
- subs->unlink_mask = 0;
- subs->running = 1;
- for (i = 0; i < subs->nurbs; i++) {
- err = usb_submit_urb(subs->dataurb[i].urb, GFP_ATOMIC);
- if (err < 0) {
- snd_printk(KERN_ERR "cannot submit datapipe "
- "for urb %d, error %d: %s\n",
- i, err, usb_error_string(err));
- goto __error;
- }
- set_bit(i, &subs->active_mask);
- }
- if (subs->syncpipe) {
- for (i = 0; i < SYNC_URBS; i++) {
- err = usb_submit_urb(subs->syncurb[i].urb, GFP_ATOMIC);
- if (err < 0) {
- snd_printk(KERN_ERR "cannot submit syncpipe "
- "for urb %d, error %d: %s\n",
- i, err, usb_error_string(err));
- goto __error;
- }
- set_bit(i + 16, &subs->active_mask);
- }
- }
- return 0;
-
- __error:
- // snd_pcm_stop(subs->pcm_substream, SNDRV_PCM_STATE_XRUN);
- deactivate_urbs(subs, 0, 0);
- return -EPIPE;
-}
-
-
-/*
- */
-static struct snd_urb_ops audio_urb_ops[2] = {
- {
- .prepare = prepare_nodata_playback_urb,
- .retire = retire_playback_urb,
- .prepare_sync = prepare_playback_sync_urb,
- .retire_sync = retire_playback_sync_urb,
- },
- {
- .prepare = prepare_capture_urb,
- .retire = retire_capture_urb,
- .prepare_sync = prepare_capture_sync_urb,
- .retire_sync = retire_capture_sync_urb,
- },
-};
-
-/*
- * initialize the substream instance.
- */
-
-void snd_usb_init_substream(struct snd_usb_stream *as,
- int stream, struct audioformat *fp)
-{
- struct snd_usb_substream *subs = &as->substream[stream];
-
- INIT_LIST_HEAD(&subs->fmt_list);
- spin_lock_init(&subs->lock);
-
- subs->stream = as;
- subs->direction = stream;
- subs->dev = as->chip->dev;
- subs->txfr_quirk = as->chip->txfr_quirk;
- subs->ops = audio_urb_ops[stream];
- if (snd_usb_get_speed(subs->dev) >= USB_SPEED_HIGH)
- subs->ops.prepare_sync = prepare_capture_sync_urb_hs;
-
- snd_usb_set_pcm_ops(as->pcm, stream);
-
- list_add_tail(&fp->list, &subs->fmt_list);
- subs->formats |= fp->formats;
- subs->endpoint = fp->endpoint;
- subs->num_formats++;
- subs->fmt_type = fp->fmt_type;
-}
-
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_usb_substream *subs = substream->runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- subs->ops.prepare = prepare_playback_urb;
- return 0;
- case SNDRV_PCM_TRIGGER_STOP:
- return deactivate_urbs(subs, 0, 0);
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- subs->ops.prepare = prepare_nodata_playback_urb;
- return 0;
- }
-
- return -EINVAL;
-}
-
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd)
-{
- struct snd_usb_substream *subs = substream->runtime->private_data;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- subs->ops.retire = retire_capture_urb;
- return start_urbs(subs, substream->runtime);
- case SNDRV_PCM_TRIGGER_STOP:
- return deactivate_urbs(subs, 0, 0);
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- subs->ops.retire = retire_paused_capture_urb;
- return 0;
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- subs->ops.retire = retire_capture_urb;
- return 0;
- }
-
- return -EINVAL;
-}
-
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime)
-{
- /* clear urbs (to be sure) */
- deactivate_urbs(subs, 0, 1);
- wait_clear_urbs(subs);
-
- /* for playback, submit the URBs now; otherwise, the first hwptr_done
- * updates for all URBs would happen at the same time when starting */
- if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
- subs->ops.prepare = prepare_nodata_playback_urb;
- return start_urbs(subs, runtime);
- }
-
- return 0;
-}
-
diff --git a/sound/usb/urb.h b/sound/usb/urb.h
deleted file mode 100644
index 888da38079cf..000000000000
--- a/sound/usb/urb.h
+++ /dev/null
@@ -1,21 +0,0 @@
-#ifndef __USBAUDIO_URB_H
-#define __USBAUDIO_URB_H
-
-void snd_usb_init_substream(struct snd_usb_stream *as,
- int stream,
- struct audioformat *fp);
-
-int snd_usb_init_substream_urbs(struct snd_usb_substream *subs,
- unsigned int period_bytes,
- unsigned int rate,
- unsigned int frame_bits);
-
-void snd_usb_release_substream_urbs(struct snd_usb_substream *subs, int force);
-
-int snd_usb_substream_prepare(struct snd_usb_substream *subs,
- struct snd_pcm_runtime *runtime);
-
-int snd_usb_substream_playback_trigger(struct snd_pcm_substream *substream, int cmd);
-int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream, int cmd);
-
-#endif /* __USBAUDIO_URB_H */
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 1e79986b5777..3e2b03577936 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -80,6 +80,7 @@ enum quirk_type {
QUIRK_MIDI_CME,
QUIRK_MIDI_AKAI,
QUIRK_MIDI_US122L,
+ QUIRK_MIDI_FTDI,
QUIRK_AUDIO_STANDARD_INTERFACE,
QUIRK_AUDIO_FIXED_ENDPOINT,
QUIRK_AUDIO_EDIROL_UAXX,
diff --git a/sound/usb/usx2y/us122l.c b/sound/usb/usx2y/us122l.c
index 084e6fc8d5bf..c4fd3b1d9592 100644
--- a/sound/usb/usx2y/us122l.c
+++ b/sound/usb/usx2y/us122l.c
@@ -19,6 +19,7 @@
#include <linux/slab.h>
#include <linux/usb.h>
#include <linux/usb/audio.h>
+#include <linux/module.h>
#include <sound/core.h>
#include <sound/hwdep.h>
#include <sound/pcm.h>
@@ -36,7 +37,7 @@ MODULE_LICENSE("GPL");
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
/* Enable this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS".");
@@ -771,16 +772,4 @@ static struct usb_driver snd_us122l_usb_driver = {
.supports_autosuspend = 1
};
-
-static int __init snd_us122l_module_init(void)
-{
- return usb_register(&snd_us122l_usb_driver);
-}
-
-static void __exit snd_us122l_module_exit(void)
-{
- usb_deregister(&snd_us122l_usb_driver);
-}
-
-module_init(snd_us122l_module_init)
-module_exit(snd_us122l_module_exit)
+module_usb_driver(snd_us122l_usb_driver);
diff --git a/sound/usb/usx2y/usb_stream.c b/sound/usb/usx2y/usb_stream.c
index c400ade3ff08..1e7a47a86605 100644
--- a/sound/usb/usx2y/usb_stream.c
+++ b/sound/usb/usx2y/usb_stream.c
@@ -674,7 +674,7 @@ dotry:
inurb->transfer_buffer_length =
inurb->number_of_packets *
inurb->iso_frame_desc[0].length;
- preempt_disable();
+
if (u == 0) {
int now;
struct usb_device *dev = inurb->dev;
@@ -686,19 +686,17 @@ dotry:
}
err = usb_submit_urb(inurb, GFP_ATOMIC);
if (err < 0) {
- preempt_enable();
snd_printk(KERN_ERR"usb_submit_urb(sk->inurb[%i])"
" returned %i\n", u, err);
return err;
}
err = usb_submit_urb(outurb, GFP_ATOMIC);
if (err < 0) {
- preempt_enable();
snd_printk(KERN_ERR"usb_submit_urb(sk->outurb[%i])"
" returned %i\n", u, err);
return err;
}
- preempt_enable();
+
if (inurb->start_frame != outurb->start_frame) {
snd_printd(KERN_DEBUG
"u[%i] start_frames differ in:%u out:%u\n",
diff --git a/sound/usb/usx2y/usbusx2y.c b/sound/usb/usx2y/usbusx2y.c
index cbd37f2c76d0..9af7c1f17413 100644
--- a/sound/usb/usx2y/usbusx2y.c
+++ b/sound/usb/usx2y/usbusx2y.c
@@ -154,7 +154,7 @@ MODULE_SUPPORTED_DEVICE("{{TASCAM(0x1604), "NAME_ALLCAPS"(0x8001)(0x8005)(0x8007
static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-max */
static char* id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* Id for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for "NAME_ALLCAPS".");
@@ -459,15 +459,4 @@ static void usX2Y_usb_disconnect(struct usb_device *device, void* ptr)
}
}
-static int __init snd_usX2Y_module_init(void)
-{
- return usb_register(&snd_usX2Y_usb_driver);
-}
-
-static void __exit snd_usX2Y_module_exit(void)
-{
- usb_deregister(&snd_usX2Y_usb_driver);
-}
-
-module_init(snd_usX2Y_module_init)
-module_exit(snd_usX2Y_module_exit)
+module_usb_driver(snd_usX2Y_usb_driver);
diff --git a/sound/usb/usx2y/usbusx2yaudio.c b/sound/usb/usx2y/usbusx2yaudio.c
index 5d37d1ccf813..520ef96d7c75 100644
--- a/sound/usb/usx2y/usbusx2yaudio.c
+++ b/sound/usb/usx2y/usbusx2yaudio.c
@@ -34,6 +34,7 @@
#include <linux/interrupt.h>
#include <linux/slab.h>
#include <linux/usb.h>
+#include <linux/moduleparam.h>
#include <sound/core.h>
#include <sound/info.h>
#include <sound/pcm.h>
@@ -79,7 +80,7 @@ static int usX2Y_urb_capt_retire(struct snd_usX2Y_substream *subs)
cp = (unsigned char*)urb->transfer_buffer + urb->iso_frame_desc[i].offset;
if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
snd_printk(KERN_ERR "active frame status %i. "
- "Most propably some hardware problem.\n",
+ "Most probably some hardware problem.\n",
urb->iso_frame_desc[i].status);
return urb->iso_frame_desc[i].status;
}
@@ -299,7 +300,7 @@ static void usX2Y_error_sequence(struct usX2Ydev *usX2Y,
{
snd_printk(KERN_ERR
"Sequence Error!(hcd_frame=%i ep=%i%s;wait=%i,frame=%i).\n"
-"Most propably some urb of usb-frame %i is still missing.\n"
+"Most probably some urb of usb-frame %i is still missing.\n"
"Cause could be too long delays in usb-hcd interrupt handling.\n",
usb_get_current_frame_number(usX2Y->dev),
subs->endpoint, usb_pipein(urb->pipe) ? "in" : "out",
diff --git a/sound/usb/usx2y/usx2yhwdeppcm.c b/sound/usb/usx2y/usx2yhwdeppcm.c
index a51340f6f2db..8e40b6e67e9e 100644
--- a/sound/usb/usx2y/usx2yhwdeppcm.c
+++ b/sound/usb/usx2y/usx2yhwdeppcm.c
@@ -74,7 +74,7 @@ static int usX2Y_usbpcm_urb_capt_retire(struct snd_usX2Y_substream *subs)
}
for (i = 0; i < nr_of_packs(); i++) {
if (urb->iso_frame_desc[i].status) { /* active? hmm, skip this */
- snd_printk(KERN_ERR "activ frame status %i. Most propably some hardware problem.\n", urb->iso_frame_desc[i].status);
+ snd_printk(KERN_ERR "active frame status %i. Most probably some hardware problem.\n", urb->iso_frame_desc[i].status);
return urb->iso_frame_desc[i].status;
}
lens += urb->iso_frame_desc[i].actual_length / usX2Y->stride;