aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt60
-rw-r--r--Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl4
-rw-r--r--Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl33
-rw-r--r--Documentation/sound/alsa/hda_codec.txt10
-rw-r--r--Documentation/sound/alsa/soc/DAI.txt56
-rw-r--r--Documentation/sound/alsa/soc/clocking.txt51
-rw-r--r--Documentation/sound/alsa/soc/codec.txt197
-rw-r--r--Documentation/sound/alsa/soc/dapm.txt297
-rw-r--r--Documentation/sound/alsa/soc/machine.txt113
-rw-r--r--Documentation/sound/alsa/soc/overview.txt83
-rw-r--r--Documentation/sound/alsa/soc/platform.txt58
-rw-r--r--Documentation/sound/alsa/soc/pops_clicks.txt52
-rw-r--r--MAINTAINERS6
-rw-r--r--drivers/input/touchscreen/ucb1400_ts.c2
-rw-r--r--include/linux/i2c-id.h2
-rw-r--r--include/sound/ac97_codec.h4
-rw-r--r--include/sound/ad1848.h2
-rw-r--r--include/sound/ak4114.h3
-rw-r--r--include/sound/ak4117.h2
-rw-r--r--include/sound/ak4xxx-adda.h6
-rw-r--r--include/sound/control.h5
-rw-r--r--include/sound/core.h62
-rw-r--r--include/sound/emu10k1.h418
-rw-r--r--include/sound/pcm.h4
-rw-r--r--include/sound/pt2258.h37
-rw-r--r--include/sound/sb16_csp.h14
-rw-r--r--include/sound/snd_wavefront.h2
-rw-r--r--include/sound/soc-dapm.h286
-rw-r--r--include/sound/soc.h461
-rw-r--r--include/sound/typedefs.h173
-rw-r--r--include/sound/version.h4
-rw-r--r--include/sound/vx_core.h2
-rw-r--r--include/sound/ymfpci.h6
-rw-r--r--sound/Kconfig2
-rw-r--r--sound/Makefile2
-rw-r--r--sound/ac97_bus.c4
-rw-r--r--sound/aoa/aoa.h2
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-onyx.c11
-rw-r--r--sound/aoa/core/snd-aoa-alsa.c5
-rw-r--r--sound/aoa/core/snd-aoa-alsa.h2
-rw-r--r--sound/aoa/core/snd-aoa-core.c4
-rw-r--r--sound/aoa/fabrics/snd-aoa-fabric-layout.c13
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-core.c22
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-pcm.c407
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus.h6
-rw-r--r--sound/arm/aaci.h2
-rw-r--r--sound/core/control.c42
-rw-r--r--sound/core/control_compat.c5
-rw-r--r--sound/core/device.c24
-rw-r--r--sound/core/hwdep.c19
-rw-r--r--sound/core/init.c22
-rw-r--r--sound/core/memalloc.c10
-rw-r--r--sound/core/misc.c28
-rw-r--r--sound/core/pcm.c50
-rw-r--r--sound/core/pcm_lib.c5
-rw-r--r--sound/core/pcm_memory.c23
-rw-r--r--sound/core/rawmidi.c29
-rw-r--r--sound/core/seq/seq_clientmgr.c14
-rw-r--r--sound/core/seq/seq_device.c25
-rw-r--r--sound/core/seq/seq_ports.c51
-rw-r--r--sound/core/seq/seq_virmidi.c4
-rw-r--r--sound/core/sound.c15
-rw-r--r--sound/core/timer.c80
-rw-r--r--sound/drivers/Kconfig11
-rw-r--r--sound/drivers/Makefile2
-rw-r--r--sound/drivers/dummy.c2
-rw-r--r--sound/drivers/portman2x4.c876
-rw-r--r--sound/drivers/serial-u16550.c221
-rw-r--r--sound/drivers/vx/vx_mixer.c2
-rw-r--r--sound/i2c/Makefile1
-rw-r--r--sound/i2c/other/Makefile4
-rw-r--r--sound/i2c/other/ak4114.c29
-rw-r--r--sound/i2c/other/ak4117.c2
-rw-r--r--sound/i2c/other/ak4xxx-adda.c110
-rw-r--r--sound/i2c/other/pt2258.c233
-rw-r--r--sound/isa/Kconfig2
-rw-r--r--sound/isa/ad1816a/ad1816a_lib.c10
-rw-r--r--sound/isa/ad1848/ad1848_lib.c6
-rw-r--r--sound/isa/gus/gus_main.c6
-rw-r--r--sound/isa/opl3sa2.c4
-rw-r--r--sound/isa/sb/sb16_csp.c61
-rw-r--r--sound/isa/wavefront/wavefront.c1
-rw-r--r--sound/isa/wavefront/wavefront_fx.c812
-rw-r--r--sound/isa/wavefront/yss225.c2739
-rw-r--r--sound/pci/Kconfig30
-rw-r--r--sound/pci/ac97/ac97_codec.c64
-rw-r--r--sound/pci/ac97/ac97_patch.c549
-rw-r--r--sound/pci/ac97/ac97_patch.h1
-rw-r--r--sound/pci/ac97/ak4531_codec.c6
-rw-r--r--sound/pci/als300.c6
-rw-r--r--sound/pci/atiixp.c31
-rw-r--r--sound/pci/atiixp_modem.c2
-rw-r--r--sound/pci/ca0106/ca0106_main.c21
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c50
-rw-r--r--sound/pci/cs4281.c2
-rw-r--r--sound/pci/echoaudio/darla20.c1
-rw-r--r--sound/pci/echoaudio/darla24.c1
-rw-r--r--sound/pci/echoaudio/echo3g.c1
-rw-r--r--sound/pci/echoaudio/echo3g_dsp.c2
-rw-r--r--sound/pci/echoaudio/echoaudio.c18
-rw-r--r--sound/pci/echoaudio/gina20.c1
-rw-r--r--sound/pci/echoaudio/gina24.c1
-rw-r--r--sound/pci/echoaudio/indigo.c1
-rw-r--r--sound/pci/echoaudio/indigodj.c1
-rw-r--r--sound/pci/echoaudio/indigoio.c1
-rw-r--r--sound/pci/echoaudio/layla20.c1
-rw-r--r--sound/pci/echoaudio/layla24.c1
-rw-r--r--sound/pci/echoaudio/mia.c1
-rw-r--r--sound/pci/echoaudio/mona.c1
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c616
-rw-r--r--sound/pci/emu10k1/emu10k1x.c6
-rw-r--r--sound/pci/emu10k1/emufx.c204
-rw-r--r--sound/pci/emu10k1/emumixer.c745
-rw-r--r--sound/pci/emu10k1/emupcm.c147
-rw-r--r--sound/pci/emu10k1/emuproc.c34
-rw-r--r--sound/pci/emu10k1/io.c104
-rw-r--r--sound/pci/emu10k1/p16v.c14
-rw-r--r--sound/pci/emu10k1/p17v.h47
-rw-r--r--sound/pci/emu10k1/voice.c2
-rw-r--r--sound/pci/ens1370.c154
-rw-r--r--sound/pci/es1938.c2
-rw-r--r--sound/pci/fm801.c2
-rw-r--r--sound/pci/hda/Makefile11
-rw-r--r--sound/pci/hda/hda_codec.c68
-rw-r--r--sound/pci/hda/hda_intel.c33
-rw-r--r--sound/pci/hda/hda_local.h12
-rw-r--r--sound/pci/hda/hda_patch.h6
-rw-r--r--sound/pci/hda/patch_analog.c165
-rw-r--r--sound/pci/hda/patch_cmedia.c24
-rw-r--r--sound/pci/hda/patch_conexant.c1311
-rw-r--r--sound/pci/hda/patch_realtek.c2367
-rw-r--r--sound/pci/hda/patch_sigmatel.c692
-rw-r--r--sound/pci/hda/patch_via.c1396
-rw-r--r--sound/pci/ice1712/Makefile2
-rw-r--r--sound/pci/ice1712/amp.c4
-rw-r--r--sound/pci/ice1712/amp.h2
-rw-r--r--sound/pci/ice1712/aureon.c186
-rw-r--r--sound/pci/ice1712/aureon.h6
-rw-r--r--sound/pci/ice1712/delta.c34
-rw-r--r--sound/pci/ice1712/delta.h2
-rw-r--r--sound/pci/ice1712/ews.c24
-rw-r--r--sound/pci/ice1712/ews.h2
-rw-r--r--sound/pci/ice1712/hoontech.c7
-rw-r--r--sound/pci/ice1712/hoontech.h2
-rw-r--r--sound/pci/ice1712/ice1712.c74
-rw-r--r--sound/pci/ice1712/ice1712.h18
-rw-r--r--sound/pci/ice1712/ice1724.c78
-rw-r--r--sound/pci/ice1712/juli.c36
-rw-r--r--sound/pci/ice1712/juli.h2
-rw-r--r--sound/pci/ice1712/phase.c76
-rw-r--r--sound/pci/ice1712/phase.h2
-rw-r--r--sound/pci/ice1712/pontis.c42
-rw-r--r--sound/pci/ice1712/pontis.h2
-rw-r--r--sound/pci/ice1712/prodigy192.c40
-rw-r--r--sound/pci/ice1712/prodigy192.h2
-rw-r--r--sound/pci/ice1712/revo.c372
-rw-r--r--sound/pci/ice1712/revo.h13
-rw-r--r--sound/pci/ice1712/vt1720_mobo.c59
-rw-r--r--sound/pci/ice1712/vt1720_mobo.h2
-rw-r--r--sound/pci/ice1712/wtm.c542
-rw-r--r--sound/pci/ice1712/wtm.h20
-rw-r--r--sound/pci/intel8x0.c208
-rw-r--r--sound/pci/intel8x0m.c120
-rw-r--r--sound/pci/korg1212/korg1212.c45
-rw-r--r--sound/pci/maestro3.c373
-rw-r--r--sound/pci/mixart/mixart_mixer.c4
-rw-r--r--sound/pci/nm256/nm256.c56
-rw-r--r--sound/pci/pcxhr/pcxhr_mixer.c6
-rw-r--r--sound/pci/rme9652/hdsp.c38
-rw-r--r--sound/pci/rme9652/hdspm.c1242
-rw-r--r--sound/pci/trident/trident_main.c4
-rw-r--r--sound/pci/via82xx.c134
-rw-r--r--sound/pci/via82xx_modem.c2
-rw-r--r--sound/pci/vx222/vx222.c4
-rw-r--r--sound/pci/vx222/vx222_ops.c2
-rw-r--r--sound/pci/ymfpci/ymfpci_image.h6
-rw-r--r--sound/pci/ymfpci/ymfpci_main.c171
-rw-r--r--sound/pcmcia/vx/vxp_mixer.c2
-rw-r--r--sound/pcmcia/vx/vxpocket.c2
-rw-r--r--sound/soc/Kconfig32
-rw-r--r--sound/soc/Makefile4
-rw-r--r--sound/soc/at91/Kconfig32
-rw-r--r--sound/soc/at91/Makefile11
-rw-r--r--sound/soc/at91/at91-i2s.c720
-rw-r--r--sound/soc/at91/at91-i2s.h27
-rw-r--r--sound/soc/at91/at91-pcm.c432
-rw-r--r--sound/soc/at91/at91-pcm.h72
-rw-r--r--sound/soc/at91/eti_b1_wm8731.c375
-rw-r--r--sound/soc/codecs/Kconfig15
-rw-r--r--sound/soc/codecs/Makefile9
-rw-r--r--sound/soc/codecs/ac97.c156
-rw-r--r--sound/soc/codecs/ac97.h18
-rw-r--r--sound/soc/codecs/wm8731.c758
-rw-r--r--sound/soc/codecs/wm8731.h44
-rw-r--r--sound/soc/codecs/wm8750.c1049
-rw-r--r--sound/soc/codecs/wm8750.h67
-rw-r--r--sound/soc/codecs/wm9712.c771
-rw-r--r--sound/soc/codecs/wm9712.h14
-rw-r--r--sound/soc/pxa/Kconfig60
-rw-r--r--sound/soc/pxa/Makefile20
-rw-r--r--sound/soc/pxa/corgi.c383
-rw-r--r--sound/soc/pxa/poodle.c352
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c431
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.h22
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c318
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.h20
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c372
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.h34
-rw-r--r--sound/soc/pxa/spitz.c394
-rw-r--r--sound/soc/pxa/tosa.c289
-rw-r--r--sound/soc/soc-core.c1587
-rw-r--r--sound/soc/soc-dapm.c1323
-rw-r--r--sound/sparc/dbri.c2
-rw-r--r--sound/usb/usbaudio.c189
-rw-r--r--sound/usb/usbaudio.h1
-rw-r--r--sound/usb/usbquirks.h32
216 files changed, 28241 insertions, 3797 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 9fef210ab50a..c30ff1bb2d10 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -242,6 +242,12 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
242 ac97_clock - AC'97 clock (default = 48000) 242 ac97_clock - AC'97 clock (default = 48000)
243 ac97_quirk - AC'97 workaround for strange hardware 243 ac97_quirk - AC'97 workaround for strange hardware
244 See "AC97 Quirk Option" section below. 244 See "AC97 Quirk Option" section below.
245 ac97_codec - Workaround to specify which AC'97 codec
246 instead of probing. If this works for you
247 file a bug with your `lspci -vn` output.
248 -2 -- Force probing.
249 -1 -- Default behavior.
250 0-2 -- Use the specified codec.
245 spdif_aclink - S/PDIF transfer over AC-link (default = 1) 251 spdif_aclink - S/PDIF transfer over AC-link (default = 1)
246 252
247 This module supports one card and autoprobe. 253 This module supports one card and autoprobe.
@@ -779,6 +785,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
779 asus-dig ASUS with SPDIF out 785 asus-dig ASUS with SPDIF out
780 asus-dig2 ASUS with SPDIF out (using GPIO2) 786 asus-dig2 ASUS with SPDIF out (using GPIO2)
781 uniwill 3-jack 787 uniwill 3-jack
788 fujitsu Fujitsu Laptops (Pi1536)
782 F1734 2-jack 789 F1734 2-jack
783 lg LG laptop (m1 express dual) 790 lg LG laptop (m1 express dual)
784 lg-lw LG LW20/LW25 laptop 791 lg-lw LG LW20/LW25 laptop
@@ -800,14 +807,18 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
800 ALC262 807 ALC262
801 fujitsu Fujitsu Laptop 808 fujitsu Fujitsu Laptop
802 hp-bpc HP xw4400/6400/8400/9400 laptops 809 hp-bpc HP xw4400/6400/8400/9400 laptops
810 hp-bpc-d7000 HP BPC D7000
803 benq Benq ED8 811 benq Benq ED8
812 hippo Hippo (ATI) with jack detection, Sony UX-90s
813 hippo_1 Hippo (Benq) with jack detection
804 basic fixed pin assignment w/o SPDIF 814 basic fixed pin assignment w/o SPDIF
805 auto auto-config reading BIOS (default) 815 auto auto-config reading BIOS (default)
806 816
807 ALC882/885 817 ALC882/885
808 3stack-dig 3-jack with SPDIF I/O 818 3stack-dig 3-jack with SPDIF I/O
809 6stck-dig 6-jack digital with SPDIF I/O 819 6stack-dig 6-jack digital with SPDIF I/O
810 arima Arima W820Di1 820 arima Arima W820Di1
821 macpro MacPro support
811 auto auto-config reading BIOS (default) 822 auto auto-config reading BIOS (default)
812 823
813 ALC883/888 824 ALC883/888
@@ -817,6 +828,10 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
817 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O 828 3stack-6ch-dig 3-jack 6-channel with SPDIF I/O
818 6stack-dig-demo 6-jack digital for Intel demo board 829 6stack-dig-demo 6-jack digital for Intel demo board
819 acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc) 830 acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
831 medion Medion Laptops
832 targa-dig Targa/MSI
833 targa-2ch-dig Targs/MSI with 2-channel
834 laptop-eapd 3-jack with SPDIF I/O and EAPD (Clevo M540JE, M550JE)
820 auto auto-config reading BIOS (default) 835 auto auto-config reading BIOS (default)
821 836
822 ALC861/660 837 ALC861/660
@@ -825,6 +840,16 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
825 6stack-dig 6-jack with SPDIF I/O 840 6stack-dig 6-jack with SPDIF I/O
826 3stack-660 3-jack (for ALC660) 841 3stack-660 3-jack (for ALC660)
827 uniwill-m31 Uniwill M31 laptop 842 uniwill-m31 Uniwill M31 laptop
843 toshiba Toshiba laptop support
844 asus Asus laptop support
845 asus-laptop ASUS F2/F3 laptops
846 auto auto-config reading BIOS (default)
847
848 ALC861VD/660VD
849 3stack 3-jack
850 3stack-dig 3-jack with SPDIF OUT
851 6stack-dig 6-jack with SPDIF OUT
852 3stack-660 3-jack (for ALC660VD)
828 auto auto-config reading BIOS (default) 853 auto auto-config reading BIOS (default)
829 854
830 CMI9880 855 CMI9880
@@ -845,6 +870,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
845 3stack 3-stack, shared surrounds 870 3stack 3-stack, shared surrounds
846 laptop 2-channel only (FSC V2060, Samsung M50) 871 laptop 2-channel only (FSC V2060, Samsung M50)
847 laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J) 872 laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J)
873 ultra 2-channel with EAPD (Samsung Ultra tablet PC)
848 874
849 AD1988 875 AD1988
850 6stack 6-jack 876 6stack 6-jack
@@ -854,12 +880,31 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
854 laptop 3-jack with hp-jack automute 880 laptop 3-jack with hp-jack automute
855 laptop-dig ditto with SPDIF 881 laptop-dig ditto with SPDIF
856 auto auto-config reading BIOS (default) 882 auto auto-config reading BIOS (default)
883
884 Conexant 5045
885 laptop Laptop config
886 test for testing/debugging purpose, almost all controls
887 can be adjusted. Appearing only when compiled with
888 $CONFIG_SND_DEBUG=y
889
890 Conexant 5047
891 laptop Basic Laptop config
892 laptop-hp Laptop config for some HP models (subdevice 30A5)
893 laptop-eapd Laptop config with EAPD support
894 test for testing/debugging purpose, almost all controls
895 can be adjusted. Appearing only when compiled with
896 $CONFIG_SND_DEBUG=y
857 897
858 STAC9200/9205/9220/9221/9254 898 STAC9200/9205/9220/9221/9254
859 ref Reference board 899 ref Reference board
860 3stack D945 3stack 900 3stack D945 3stack
861 5stack D945 5stack + SPDIF 901 5stack D945 5stack + SPDIF
862 902
903 STAC9202/9250/9251
904 ref Reference board, base config
905 m2-2 Some Gateway MX series laptops
906 m6 Some Gateway NX series laptops
907
863 STAC9227/9228/9229/927x 908 STAC9227/9228/9229/927x
864 ref Reference board 909 ref Reference board
865 3stack D965 3stack 910 3stack D965 3stack
@@ -974,6 +1019,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
974 Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards. 1019 Module for Envy24HT (VT/ICE1724), Envy24PT (VT1720) based PCI sound cards.
975 * MidiMan M Audio Revolution 5.1 1020 * MidiMan M Audio Revolution 5.1
976 * MidiMan M Audio Revolution 7.1 1021 * MidiMan M Audio Revolution 7.1
1022 * MidiMan M Audio Audiophile 192
977 * AMP Ltd AUDIO2000 1023 * AMP Ltd AUDIO2000
978 * TerraTec Aureon 5.1 Sky 1024 * TerraTec Aureon 5.1 Sky
979 * TerraTec Aureon 7.1 Space 1025 * TerraTec Aureon 7.1 Space
@@ -993,7 +1039,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
993 1039
994 model - Use the given board model, one of the following: 1040 model - Use the given board model, one of the following:
995 revo51, revo71, amp2000, prodigy71, prodigy71lt, 1041 revo51, revo71, amp2000, prodigy71, prodigy71lt,
996 prodigy192, aureon51, aureon71, universe, 1042 prodigy192, aureon51, aureon71, universe, ap192,
997 k8x800, phase22, phase28, ms300, av710 1043 k8x800, phase22, phase28, ms300, av710
998 1044
999 This module supports multiple cards and autoprobe. 1045 This module supports multiple cards and autoprobe.
@@ -1049,6 +1095,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1049 buggy_semaphore - Enable workaround for hardwares with buggy 1095 buggy_semaphore - Enable workaround for hardwares with buggy
1050 semaphores (e.g. on some ASUS laptops) 1096 semaphores (e.g. on some ASUS laptops)
1051 (default off) 1097 (default off)
1098 spdif_aclink - Use S/PDIF over AC-link instead of direct connection
1099 from the controller chip
1100 (0 = off, 1 = on, -1 = default)
1052 1101
1053 This module supports one chip and autoprobe. 1102 This module supports one chip and autoprobe.
1054 1103
@@ -1371,6 +1420,13 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
1371 1420
1372 This module supports multiple cards. 1421 This module supports multiple cards.
1373 1422
1423 Module snd-portman2x4
1424 ---------------------
1425
1426 Module for Midiman Portman 2x4 parallel port MIDI interface
1427
1428 This module supports multiple cards.
1429
1374 Module snd-powermac (on ppc only) 1430 Module snd-powermac (on ppc only)
1375 --------------------------------- 1431 ---------------------------------
1376 1432
diff --git a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
index 1f3ae3e32d69..c4d2e3507af9 100644
--- a/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
+++ b/Documentation/sound/alsa/DocBook/alsa-driver-api.tmpl
@@ -36,7 +36,7 @@
36 </bookinfo> 36 </bookinfo>
37 37
38 <chapter><title>Management of Cards and Devices</title> 38 <chapter><title>Management of Cards and Devices</title>
39 <sect1><title>Card Managment</title> 39 <sect1><title>Card Management</title>
40!Esound/core/init.c 40!Esound/core/init.c
41 </sect1> 41 </sect1>
42 <sect1><title>Device Components</title> 42 <sect1><title>Device Components</title>
@@ -59,7 +59,7 @@
59 <sect1><title>PCM Format Helpers</title> 59 <sect1><title>PCM Format Helpers</title>
60!Esound/core/pcm_misc.c 60!Esound/core/pcm_misc.c
61 </sect1> 61 </sect1>
62 <sect1><title>PCM Memory Managment</title> 62 <sect1><title>PCM Memory Management</title>
63!Esound/core/pcm_memory.c 63!Esound/core/pcm_memory.c
64 </sect1> 64 </sect1>
65 </chapter> 65 </chapter>
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
index ccd0a953953d..74d3a35b59bc 100644
--- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
+++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl
@@ -1360,8 +1360,7 @@
1360 <informalexample> 1360 <informalexample>
1361 <programlisting> 1361 <programlisting>
1362<![CDATA[ 1362<![CDATA[
1363 static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id, 1363 static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
1364 struct pt_regs *regs)
1365 { 1364 {
1366 struct mychip *chip = dev_id; 1365 struct mychip *chip = dev_id;
1367 .... 1366 ....
@@ -2127,7 +2126,7 @@
2127 accessible via <constant>substream-&gt;runtime</constant>. 2126 accessible via <constant>substream-&gt;runtime</constant>.
2128 This runtime pointer holds the various information; it holds 2127 This runtime pointer holds the various information; it holds
2129 the copy of hw_params and sw_params configurations, the buffer 2128 the copy of hw_params and sw_params configurations, the buffer
2130 pointers, mmap records, spinlocks, etc. Almost everyhing you 2129 pointers, mmap records, spinlocks, etc. Almost everything you
2131 need for controlling the PCM can be found there. 2130 need for controlling the PCM can be found there.
2132 </para> 2131 </para>
2133 2132
@@ -2340,7 +2339,7 @@ struct _snd_pcm_runtime {
2340 2339
2341 <para> 2340 <para>
2342 When the PCM substreams can be synchronized (typically, 2341 When the PCM substreams can be synchronized (typically,
2343 synchorinized start/stop of a playback and a capture streams), 2342 synchronized start/stop of a playback and a capture streams),
2344 you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>, 2343 you can give <constant>SNDRV_PCM_INFO_SYNC_START</constant>,
2345 too. In this case, you'll need to check the linked-list of 2344 too. In this case, you'll need to check the linked-list of
2346 PCM substreams in the trigger callback. This will be 2345 PCM substreams in the trigger callback. This will be
@@ -3062,8 +3061,7 @@ struct _snd_pcm_runtime {
3062 <title>Interrupt Handler Case #1</title> 3061 <title>Interrupt Handler Case #1</title>
3063 <programlisting> 3062 <programlisting>
3064<![CDATA[ 3063<![CDATA[
3065 static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id, 3064 static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
3066 struct pt_regs *regs)
3067 { 3065 {
3068 struct mychip *chip = dev_id; 3066 struct mychip *chip = dev_id;
3069 spin_lock(&chip->lock); 3067 spin_lock(&chip->lock);
@@ -3106,8 +3104,7 @@ struct _snd_pcm_runtime {
3106 <title>Interrupt Handler Case #2</title> 3104 <title>Interrupt Handler Case #2</title>
3107 <programlisting> 3105 <programlisting>
3108<![CDATA[ 3106<![CDATA[
3109 static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id, 3107 static irqreturn_t snd_mychip_interrupt(int irq, void *dev_id)
3110 struct pt_regs *regs)
3111 { 3108 {
3112 struct mychip *chip = dev_id; 3109 struct mychip *chip = dev_id;
3113 spin_lock(&chip->lock); 3110 spin_lock(&chip->lock);
@@ -3247,7 +3244,7 @@ struct _snd_pcm_runtime {
3247 You can even define your own constraint rules. 3244 You can even define your own constraint rules.
3248 For example, let's suppose my_chip can manage a substream of 1 channel 3245 For example, let's suppose my_chip can manage a substream of 1 channel
3249 if and only if the format is S16_LE, otherwise it supports any format 3246 if and only if the format is S16_LE, otherwise it supports any format
3250 specified in the <structname>snd_pcm_hardware</structname> stucture (or in any 3247 specified in the <structname>snd_pcm_hardware</structname> structure (or in any
3251 other constraint_list). You can build a rule like this: 3248 other constraint_list). You can build a rule like this:
3252 3249
3253 <example> 3250 <example>
@@ -3691,16 +3688,6 @@ struct _snd_pcm_runtime {
3691 </para> 3688 </para>
3692 3689
3693 <para> 3690 <para>
3694 Here, the chip instance is retrieved via
3695 <function>snd_kcontrol_chip()</function> macro. This macro
3696 just accesses to kcontrol-&gt;private_data. The
3697 kcontrol-&gt;private_data field is
3698 given as the argument of <function>snd_ctl_new()</function>
3699 (see the later subsection
3700 <link linkend="control-interface-constructor"><citetitle>Constructor</citetitle></link>).
3701 </para>
3702
3703 <para>
3704 The <structfield>value</structfield> field is depending on 3691 The <structfield>value</structfield> field is depending on
3705 the type of control as well as on info callback. For example, 3692 the type of control as well as on info callback. For example,
3706 the sb driver uses this field to store the register offset, 3693 the sb driver uses this field to store the register offset,
@@ -3780,7 +3767,7 @@ struct _snd_pcm_runtime {
3780 <para> 3767 <para>
3781 Like <structfield>get</structfield> callback, 3768 Like <structfield>get</structfield> callback,
3782 when the control has more than one elements, 3769 when the control has more than one elements,
3783 all elemehts must be evaluated in this callback, too. 3770 all elements must be evaluated in this callback, too.
3784 </para> 3771 </para>
3785 </section> 3772 </section>
3786 3773
@@ -5541,12 +5528,12 @@ struct _snd_pcm_runtime {
5541 #ifdef CONFIG_PM 5528 #ifdef CONFIG_PM
5542 static int snd_my_suspend(struct pci_dev *pci, pm_message_t state) 5529 static int snd_my_suspend(struct pci_dev *pci, pm_message_t state)
5543 { 5530 {
5544 .... /* do things for suspsend */ 5531 .... /* do things for suspend */
5545 return 0; 5532 return 0;
5546 } 5533 }
5547 static int snd_my_resume(struct pci_dev *pci) 5534 static int snd_my_resume(struct pci_dev *pci)
5548 { 5535 {
5549 .... /* do things for suspsend */ 5536 .... /* do things for suspend */
5550 return 0; 5537 return 0;
5551 } 5538 }
5552 #endif 5539 #endif
@@ -6111,7 +6098,7 @@ struct _snd_pcm_runtime {
6111<!-- ****************************************************** --> 6098<!-- ****************************************************** -->
6112<!-- Acknowledgments --> 6099<!-- Acknowledgments -->
6113<!-- ****************************************************** --> 6100<!-- ****************************************************** -->
6114 <chapter id="acknowledments"> 6101 <chapter id="acknowledgments">
6115 <title>Acknowledgments</title> 6102 <title>Acknowledgments</title>
6116 <para> 6103 <para>
6117 I would like to thank Phil Kerr for his help for improvement and 6104 I would like to thank Phil Kerr for his help for improvement and
diff --git a/Documentation/sound/alsa/hda_codec.txt b/Documentation/sound/alsa/hda_codec.txt
index 0be57ed81302..4eaae2a45534 100644
--- a/Documentation/sound/alsa/hda_codec.txt
+++ b/Documentation/sound/alsa/hda_codec.txt
@@ -277,11 +277,11 @@ Helper Functions
277snd_hda_get_codec_name() stores the codec name on the given string. 277snd_hda_get_codec_name() stores the codec name on the given string.
278 278
279snd_hda_check_board_config() can be used to obtain the configuration 279snd_hda_check_board_config() can be used to obtain the configuration
280information matching with the device. Define the table with struct 280information matching with the device. Define the model string table
281hda_board_config entries (zero-terminated), and pass it to the 281and the table with struct snd_pci_quirk entries (zero-terminated),
282function. The function checks the modelname given as a module 282and pass it to the function. The function checks the modelname given
283parameter, and PCI subsystem IDs. If the matching entry is found, it 283as a module parameter, and PCI subsystem IDs. If the matching entry
284returns the config field value. 284is found, it returns the config field value.
285 285
286snd_hda_add_new_ctls() can be used to create and add control entries. 286snd_hda_add_new_ctls() can be used to create and add control entries.
287Pass the zero-terminated array of struct snd_kcontrol_new. The same array 287Pass the zero-terminated array of struct snd_kcontrol_new. The same array
diff --git a/Documentation/sound/alsa/soc/DAI.txt b/Documentation/sound/alsa/soc/DAI.txt
new file mode 100644
index 000000000000..58cbfd01ea8f
--- /dev/null
+++ b/Documentation/sound/alsa/soc/DAI.txt
@@ -0,0 +1,56 @@
1ASoC currently supports the three main Digital Audio Interfaces (DAI) found on
2SoC controllers and portable audio CODECS today, namely AC97, I2S and PCM.
3
4
5AC97
6====
7
8 AC97 is a five wire interface commonly found on many PC sound cards. It is
9now also popular in many portable devices. This DAI has a reset line and time
10multiplexes its data on its SDATA_OUT (playback) and SDATA_IN (capture) lines.
11The bit clock (BCLK) is always driven by the CODEC (usually 12.288MHz) and the
12frame (FRAME) (usually 48kHz) is always driven by the controller. Each AC97
13frame is 21uS long and is divided into 13 time slots.
14
15The AC97 specification can be found at :-
16http://www.intel.com/design/chipsets/audio/ac97_r23.pdf
17
18
19I2S
20===
21
22 I2S is a common 4 wire DAI used in HiFi, STB and portable devices. The Tx and
23Rx lines are used for audio transmision, whilst the bit clock (BCLK) and
24left/right clock (LRC) synchronise the link. I2S is flexible in that either the
25controller or CODEC can drive (master) the BCLK and LRC clock lines. Bit clock
26usually varies depending on the sample rate and the master system clock
27(SYSCLK). LRCLK is the same as the sample rate. A few devices support separate
28ADC and DAC LRCLK's, this allows for similtanious capture and playback at
29different sample rates.
30
31I2S has several different operating modes:-
32
33 o I2S - MSB is transmitted on the falling edge of the first BCLK after LRC
34 transition.
35
36 o Left Justified - MSB is transmitted on transition of LRC.
37
38 o Right Justified - MSB is transmitted sample size BCLK's before LRC
39 transition.
40
41PCM
42===
43
44PCM is another 4 wire interface, very similar to I2S, that can support a more
45flexible protocol. It has bit clock (BCLK) and sync (SYNC) lines that are used
46to synchronise the link whilst the Tx and Rx lines are used to transmit and
47receive the audio data. Bit clock usually varies depending on sample rate
48whilst sync runs at the sample rate. PCM also supports Time Division
49Multiplexing (TDM) in that several devices can use the bus similtaniuosly (This
50is sometimes referred to as network mode).
51
52Common PCM operating modes:-
53
54 o Mode A - MSB is transmitted on falling edge of first BCLK after FRAME/SYNC.
55
56 o Mode B - MSB is transmitted on rising edge of FRAME/SYNC.
diff --git a/Documentation/sound/alsa/soc/clocking.txt b/Documentation/sound/alsa/soc/clocking.txt
new file mode 100644
index 000000000000..e93960d53a1e
--- /dev/null
+++ b/Documentation/sound/alsa/soc/clocking.txt
@@ -0,0 +1,51 @@
1Audio Clocking
2==============
3
4This text describes the audio clocking terms in ASoC and digital audio in
5general. Note: Audio clocking can be complex !
6
7
8Master Clock
9------------
10
11Every audio subsystem is driven by a master clock (sometimes refered to as MCLK
12or SYSCLK). This audio master clock can be derived from a number of sources
13(e.g. crystal, PLL, CPU clock) and is responsible for producing the correct
14audio playback and capture sample rates.
15
16Some master clocks (e.g. PLL's and CPU based clocks) are configuarble in that
17their speed can be altered by software (depending on the system use and to save
18power). Other master clocks are fixed at at set frequency (i.e. crystals).
19
20
21DAI Clocks
22----------
23The Digital Audio Interface is usually driven by a Bit Clock (often referred to
24as BCLK). This clock is used to drive the digital audio data across the link
25between the codec and CPU.
26
27The DAI also has a frame clock to signal the start of each audio frame. This
28clock is sometimes referred to as LRC (left right clock) or FRAME. This clock
29runs at exactly the sample rate (LRC = Rate).
30
31Bit Clock can be generated as follows:-
32
33BCLK = MCLK / x
34
35 or
36
37BCLK = LRC * x
38
39 or
40
41BCLK = LRC * Channels * Word Size
42
43This relationship depends on the codec or SoC CPU in particular. In general
44it's best to configure BCLK to the lowest possible speed (depending on your
45rate, number of channels and wordsize) to save on power.
46
47It's also desireable to use the codec (if possible) to drive (or master) the
48audio clocks as it's usually gives more accurate sample rates than the CPU.
49
50
51
diff --git a/Documentation/sound/alsa/soc/codec.txt b/Documentation/sound/alsa/soc/codec.txt
new file mode 100644
index 000000000000..48983c75aad9
--- /dev/null
+++ b/Documentation/sound/alsa/soc/codec.txt
@@ -0,0 +1,197 @@
1ASoC Codec Driver
2=================
3
4The codec driver is generic and hardware independent code that configures the
5codec to provide audio capture and playback. It should contain no code that is
6specific to the target platform or machine. All platform and machine specific
7code should be added to the platform and machine drivers respectively.
8
9Each codec driver *must* provide the following features:-
10
11 1) Codec DAI and PCM configuration
12 2) Codec control IO - using I2C, 3 Wire(SPI) or both API's
13 3) Mixers and audio controls
14 4) Codec audio operations
15
16Optionally, codec drivers can also provide:-
17
18 5) DAPM description.
19 6) DAPM event handler.
20 7) DAC Digital mute control.
21
22It's probably best to use this guide in conjuction with the existing codec
23driver code in sound/soc/codecs/
24
25ASoC Codec driver breakdown
26===========================
27
281 - Codec DAI and PCM configuration
29-----------------------------------
30Each codec driver must have a struct snd_soc_codec_dai to define it's DAI and
31PCM's capablities and operations. This struct is exported so that it can be
32registered with the core by your machine driver.
33
34e.g.
35
36struct snd_soc_codec_dai wm8731_dai = {
37 .name = "WM8731",
38 /* playback capabilities */
39 .playback = {
40 .stream_name = "Playback",
41 .channels_min = 1,
42 .channels_max = 2,
43 .rates = WM8731_RATES,
44 .formats = WM8731_FORMATS,},
45 /* capture capabilities */
46 .capture = {
47 .stream_name = "Capture",
48 .channels_min = 1,
49 .channels_max = 2,
50 .rates = WM8731_RATES,
51 .formats = WM8731_FORMATS,},
52 /* pcm operations - see section 4 below */
53 .ops = {
54 .prepare = wm8731_pcm_prepare,
55 .hw_params = wm8731_hw_params,
56 .shutdown = wm8731_shutdown,
57 },
58 /* DAI operations - see DAI.txt */
59 .dai_ops = {
60 .digital_mute = wm8731_mute,
61 .set_sysclk = wm8731_set_dai_sysclk,
62 .set_fmt = wm8731_set_dai_fmt,
63 }
64};
65EXPORT_SYMBOL_GPL(wm8731_dai);
66
67
682 - Codec control IO
69--------------------
70The codec can ususally be controlled via an I2C or SPI style interface (AC97
71combines control with data in the DAI). The codec drivers will have to provide
72functions to read and write the codec registers along with supplying a register
73cache:-
74
75 /* IO control data and register cache */
76 void *control_data; /* codec control (i2c/3wire) data */
77 void *reg_cache;
78
79Codec read/write should do any data formatting and call the hardware read write
80below to perform the IO. These functions are called by the core and alsa when
81performing DAPM or changing the mixer:-
82
83 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
84 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
85
86Codec hardware IO functions - usually points to either the I2C, SPI or AC97
87read/write:-
88
89 hw_write_t hw_write;
90 hw_read_t hw_read;
91
92
933 - Mixers and audio controls
94-----------------------------
95All the codec mixers and audio controls can be defined using the convenience
96macros defined in soc.h.
97
98 #define SOC_SINGLE(xname, reg, shift, mask, invert)
99
100Defines a single control as follows:-
101
102 xname = Control name e.g. "Playback Volume"
103 reg = codec register
104 shift = control bit(s) offset in register
105 mask = control bit size(s) e.g. mask of 7 = 3 bits
106 invert = the control is inverted
107
108Other macros include:-
109
110 #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert)
111
112A stereo control
113
114 #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert)
115
116A stereo control spanning 2 registers
117
118 #define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts)
119
120Defines an single enumerated control as follows:-
121
122 xreg = register
123 xshift = control bit(s) offset in register
124 xmask = control bit(s) size
125 xtexts = pointer to array of strings that describe each setting
126
127 #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts)
128
129Defines a stereo enumerated control
130
131
1324 - Codec Audio Operations
133--------------------------
134The codec driver also supports the following alsa operations:-
135
136/* SoC audio ops */
137struct snd_soc_ops {
138 int (*startup)(struct snd_pcm_substream *);
139 void (*shutdown)(struct snd_pcm_substream *);
140 int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
141 int (*hw_free)(struct snd_pcm_substream *);
142 int (*prepare)(struct snd_pcm_substream *);
143};
144
145Please refer to the alsa driver PCM documentation for details.
146http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
147
148
1495 - DAPM description.
150---------------------
151The Dynamic Audio Power Management description describes the codec's power
152components, their relationships and registers to the ASoC core. Please read
153dapm.txt for details of building the description.
154
155Please also see the examples in other codec drivers.
156
157
1586 - DAPM event handler
159----------------------
160This function is a callback that handles codec domain PM calls and system
161domain PM calls (e.g. suspend and resume). It's used to put the codec to sleep
162when not in use.
163
164Power states:-
165
166 SNDRV_CTL_POWER_D0: /* full On */
167 /* vref/mid, clk and osc on, active */
168
169 SNDRV_CTL_POWER_D1: /* partial On */
170 SNDRV_CTL_POWER_D2: /* partial On */
171
172 SNDRV_CTL_POWER_D3hot: /* Off, with power */
173 /* everything off except vref/vmid, inactive */
174
175 SNDRV_CTL_POWER_D3cold: /* Everything Off, without power */
176
177
1787 - Codec DAC digital mute control.
179------------------------------------
180Most codecs have a digital mute before the DAC's that can be used to minimise
181any system noise. The mute stops any digital data from entering the DAC.
182
183A callback can be created that is called by the core for each codec DAI when the
184mute is applied or freed.
185
186i.e.
187
188static int wm8974_mute(struct snd_soc_codec *codec,
189 struct snd_soc_codec_dai *dai, int mute)
190{
191 u16 mute_reg = wm8974_read_reg_cache(codec, WM8974_DAC) & 0xffbf;
192 if(mute)
193 wm8974_write(codec, WM8974_DAC, mute_reg | 0x40);
194 else
195 wm8974_write(codec, WM8974_DAC, mute_reg);
196 return 0;
197}
diff --git a/Documentation/sound/alsa/soc/dapm.txt b/Documentation/sound/alsa/soc/dapm.txt
new file mode 100644
index 000000000000..c11877f5b4a1
--- /dev/null
+++ b/Documentation/sound/alsa/soc/dapm.txt
@@ -0,0 +1,297 @@
1Dynamic Audio Power Management for Portable Devices
2===================================================
3
41. Description
5==============
6
7Dynamic Audio Power Management (DAPM) is designed to allow portable Linux devices
8to use the minimum amount of power within the audio subsystem at all times. It
9is independent of other kernel PM and as such, can easily co-exist with the
10other PM systems.
11
12DAPM is also completely transparent to all user space applications as all power
13switching is done within the ASoC core. No code changes or recompiling are
14required for user space applications. DAPM makes power switching descisions based
15upon any audio stream (capture/playback) activity and audio mixer settings
16within the device.
17
18DAPM spans the whole machine. It covers power control within the entire audio
19subsystem, this includes internal codec power blocks and machine level power
20systems.
21
22There are 4 power domains within DAPM
23
24 1. Codec domain - VREF, VMID (core codec and audio power)
25 Usually controlled at codec probe/remove and suspend/resume, although
26 can be set at stream time if power is not needed for sidetone, etc.
27
28 2. Platform/Machine domain - physically connected inputs and outputs
29 Is platform/machine and user action specific, is configured by the
30 machine driver and responds to asynchronous events e.g when HP
31 are inserted
32
33 3. Path domain - audio susbsystem signal paths
34 Automatically set when mixer and mux settings are changed by the user.
35 e.g. alsamixer, amixer.
36
37 4. Stream domain - DAC's and ADC's.
38 Enabled and disabled when stream playback/capture is started and
39 stopped respectively. e.g. aplay, arecord.
40
41All DAPM power switching descisons are made automatically by consulting an audio
42routing map of the whole machine. This map is specific to each machine and
43consists of the interconnections between every audio component (including
44internal codec components). All audio components that effect power are called
45widgets hereafter.
46
47
482. DAPM Widgets
49===============
50
51Audio DAPM widgets fall into a number of types:-
52
53 o Mixer - Mixes several analog signals into a single analog signal.
54 o Mux - An analog switch that outputs only 1 of it's inputs.
55 o PGA - A programmable gain amplifier or attenuation widget.
56 o ADC - Analog to Digital Converter
57 o DAC - Digital to Analog Converter
58 o Switch - An analog switch
59 o Input - A codec input pin
60 o Output - A codec output pin
61 o Headphone - Headphone (and optional Jack)
62 o Mic - Mic (and optional Jack)
63 o Line - Line Input/Output (and optional Jack)
64 o Speaker - Speaker
65 o Pre - Special PRE widget (exec before all others)
66 o Post - Special POST widget (exec after all others)
67
68(Widgets are defined in include/sound/soc-dapm.h)
69
70Widgets are usually added in the codec driver and the machine driver. There are
71convience macros defined in soc-dapm.h that can be used to quickly build a
72list of widgets of the codecs and machines DAPM widgets.
73
74Most widgets have a name, register, shift and invert. Some widgets have extra
75parameters for stream name and kcontrols.
76
77
782.1 Stream Domain Widgets
79-------------------------
80
81Stream Widgets relate to the stream power domain and only consist of ADC's
82(analog to digital converters) and DAC's (digital to analog converters).
83
84Stream widgets have the following format:-
85
86SND_SOC_DAPM_DAC(name, stream name, reg, shift, invert),
87
88NOTE: the stream name must match the corresponding stream name in your codecs
89snd_soc_codec_dai.
90
91e.g. stream widgets for HiFi playback and capture
92
93SND_SOC_DAPM_DAC("HiFi DAC", "HiFi Playback", REG, 3, 1),
94SND_SOC_DAPM_ADC("HiFi ADC", "HiFi Capture", REG, 2, 1),
95
96
972.2 Path Domain Widgets
98-----------------------
99
100Path domain widgets have a ability to control or effect the audio signal or
101audio paths within the audio subsystem. They have the following form:-
102
103SND_SOC_DAPM_PGA(name, reg, shift, invert, controls, num_controls)
104
105Any widget kcontrols can be set using the controls and num_controls members.
106
107e.g. Mixer widget (the kcontrols are declared first)
108
109/* Output Mixer */
110static const snd_kcontrol_new_t wm8731_output_mixer_controls[] = {
111SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
112SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
113SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
114};
115
116SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1, wm8731_output_mixer_controls,
117 ARRAY_SIZE(wm8731_output_mixer_controls)),
118
119
1202.3 Platform/Machine domain Widgets
121-----------------------------------
122
123Machine widgets are different from codec widgets in that they don't have a
124codec register bit associated with them. A machine widget is assigned to each
125machine audio component (non codec) that can be independently powered. e.g.
126
127 o Speaker Amp
128 o Microphone Bias
129 o Jack connectors
130
131A machine widget can have an optional call back.
132
133e.g. Jack connector widget for an external Mic that enables Mic Bias
134when the Mic is inserted:-
135
136static int spitz_mic_bias(struct snd_soc_dapm_widget* w, int event)
137{
138 if(SND_SOC_DAPM_EVENT_ON(event))
139 set_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
140 else
141 reset_scoop_gpio(&spitzscoop2_device.dev, SPITZ_SCP2_MIC_BIAS);
142
143 return 0;
144}
145
146SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
147
148
1492.4 Codec Domain
150----------------
151
152The Codec power domain has no widgets and is handled by the codecs DAPM event
153handler. This handler is called when the codec powerstate is changed wrt to any
154stream event or by kernel PM events.
155
156
1572.5 Virtual Widgets
158-------------------
159
160Sometimes widgets exist in the codec or machine audio map that don't have any
161corresponding register bit for power control. In this case it's necessary to
162create a virtual widget - a widget with no control bits e.g.
163
164SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_DAPM_NOPM, 0, 0, NULL, 0),
165
166This can be used to merge to signal paths together in software.
167
168After all the widgets have been defined, they can then be added to the DAPM
169subsystem individually with a call to snd_soc_dapm_new_control().
170
171
1723. Codec Widget Interconnections
173================================
174
175Widgets are connected to each other within the codec and machine by audio
176paths (called interconnections). Each interconnection must be defined in order
177to create a map of all audio paths between widgets.
178This is easiest with a diagram of the codec (and schematic of the machine audio
179system), as it requires joining widgets together via their audio signal paths.
180
181i.e. from the WM8731 codec's output mixer (wm8731.c)
182
183The WM8731 output mixer has 3 inputs (sources)
184
185 1. Line Bypass Input
186 2. DAC (HiFi playback)
187 3. Mic Sidetone Input
188
189Each input in this example has a kcontrol associated with it (defined in example
190above) and is connected to the output mixer via it's kcontrol name. We can now
191connect the destination widget (wrt audio signal) with it's source widgets.
192
193 /* output mixer */
194 {"Output Mixer", "Line Bypass Switch", "Line Input"},
195 {"Output Mixer", "HiFi Playback Switch", "DAC"},
196 {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
197
198So we have :-
199
200 Destination Widget <=== Path Name <=== Source Widget
201
202Or:-
203
204 Sink, Path, Source
205
206Or :-
207
208 "Output Mixer" is connected to the "DAC" via the "HiFi Playback Switch".
209
210When there is no path name connecting widgets (e.g. a direct connection) we
211pass NULL for the path name.
212
213Interconnections are created with a call to:-
214
215snd_soc_dapm_connect_input(codec, sink, path, source);
216
217Finally, snd_soc_dapm_new_widgets(codec) must be called after all widgets and
218interconnections have been registered with the core. This causes the core to
219scan the codec and machine so that the internal DAPM state matches the
220physical state of the machine.
221
222
2233.1 Machine Widget Interconnections
224-----------------------------------
225Machine widget interconnections are created in the same way as codec ones and
226directly connect the codec pins to machine level widgets.
227
228e.g. connects the speaker out codec pins to the internal speaker.
229
230 /* ext speaker connected to codec pins LOUT2, ROUT2 */
231 {"Ext Spk", NULL , "ROUT2"},
232 {"Ext Spk", NULL , "LOUT2"},
233
234This allows the DAPM to power on and off pins that are connected (and in use)
235and pins that are NC respectively.
236
237
2384 Endpoint Widgets
239===================
240An endpoint is a start or end point (widget) of an audio signal within the
241machine and includes the codec. e.g.
242
243 o Headphone Jack
244 o Internal Speaker
245 o Internal Mic
246 o Mic Jack
247 o Codec Pins
248
249When a codec pin is NC it can be marked as not used with a call to
250
251snd_soc_dapm_set_endpoint(codec, "Widget Name", 0);
252
253The last argument is 0 for inactive and 1 for active. This way the pin and its
254input widget will never be powered up and consume power.
255
256This also applies to machine widgets. e.g. if a headphone is connected to a
257jack then the jack can be marked active. If the headphone is removed, then
258the headphone jack can be marked inactive.
259
260
2615 DAPM Widget Events
262====================
263
264Some widgets can register their interest with the DAPM core in PM events.
265e.g. A Speaker with an amplifier registers a widget so the amplifier can be
266powered only when the spk is in use.
267
268/* turn speaker amplifier on/off depending on use */
269static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
270{
271 if (SND_SOC_DAPM_EVENT_ON(event))
272 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
273 else
274 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
275
276 return 0;
277}
278
279/* corgi machine dapm widgets */
280static const struct snd_soc_dapm_widget wm8731_dapm_widgets =
281 SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event);
282
283Please see soc-dapm.h for all other widgets that support events.
284
285
2865.1 Event types
287---------------
288
289The following event types are supported by event widgets.
290
291/* dapm event types */
292#define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */
293#define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */
294#define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */
295#define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
296#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
297#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt
new file mode 100644
index 000000000000..72bd222f2a21
--- /dev/null
+++ b/Documentation/sound/alsa/soc/machine.txt
@@ -0,0 +1,113 @@
1ASoC Machine Driver
2===================
3
4The ASoC machine (or board) driver is the code that glues together the platform
5and codec drivers.
6
7The machine driver can contain codec and platform specific code. It registers
8the audio subsystem with the kernel as a platform device and is represented by
9the following struct:-
10
11/* SoC machine */
12struct snd_soc_machine {
13 char *name;
14
15 int (*probe)(struct platform_device *pdev);
16 int (*remove)(struct platform_device *pdev);
17
18 /* the pre and post PM functions are used to do any PM work before and
19 * after the codec and DAI's do any PM work. */
20 int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
21 int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
22 int (*resume_pre)(struct platform_device *pdev);
23 int (*resume_post)(struct platform_device *pdev);
24
25 /* machine stream operations */
26 struct snd_soc_ops *ops;
27
28 /* CPU <--> Codec DAI links */
29 struct snd_soc_dai_link *dai_link;
30 int num_links;
31};
32
33probe()/remove()
34----------------
35probe/remove are optional. Do any machine specific probe here.
36
37
38suspend()/resume()
39------------------
40The machine driver has pre and post versions of suspend and resume to take care
41of any machine audio tasks that have to be done before or after the codec, DAI's
42and DMA is suspended and resumed. Optional.
43
44
45Machine operations
46------------------
47The machine specific audio operations can be set here. Again this is optional.
48
49
50Machine DAI Configuration
51-------------------------
52The machine DAI configuration glues all the codec and CPU DAI's together. It can
53also be used to set up the DAI system clock and for any machine related DAI
54initialisation e.g. the machine audio map can be connected to the codec audio
55map, unconnnected codec pins can be set as such. Please see corgi.c, spitz.c
56for examples.
57
58struct snd_soc_dai_link is used to set up each DAI in your machine. e.g.
59
60/* corgi digital audio interface glue - connects codec <--> CPU */
61static struct snd_soc_dai_link corgi_dai = {
62 .name = "WM8731",
63 .stream_name = "WM8731",
64 .cpu_dai = &pxa_i2s_dai,
65 .codec_dai = &wm8731_dai,
66 .init = corgi_wm8731_init,
67 .ops = &corgi_ops,
68};
69
70struct snd_soc_machine then sets up the machine with it's DAI's. e.g.
71
72/* corgi audio machine driver */
73static struct snd_soc_machine snd_soc_machine_corgi = {
74 .name = "Corgi",
75 .dai_link = &corgi_dai,
76 .num_links = 1,
77};
78
79
80Machine Audio Subsystem
81-----------------------
82
83The machine soc device glues the platform, machine and codec driver together.
84Private data can also be set here. e.g.
85
86/* corgi audio private data */
87static struct wm8731_setup_data corgi_wm8731_setup = {
88 .i2c_address = 0x1b,
89};
90
91/* corgi audio subsystem */
92static struct snd_soc_device corgi_snd_devdata = {
93 .machine = &snd_soc_machine_corgi,
94 .platform = &pxa2xx_soc_platform,
95 .codec_dev = &soc_codec_dev_wm8731,
96 .codec_data = &corgi_wm8731_setup,
97};
98
99
100Machine Power Map
101-----------------
102
103The machine driver can optionally extend the codec power map and to become an
104audio power map of the audio subsystem. This allows for automatic power up/down
105of speaker/HP amplifiers, etc. Codec pins can be connected to the machines jack
106sockets in the machine init function. See soc/pxa/spitz.c and dapm.txt for
107details.
108
109
110Machine Controls
111----------------
112
113Machine specific audio mixer controls can be added in the dai init function. \ No newline at end of file
diff --git a/Documentation/sound/alsa/soc/overview.txt b/Documentation/sound/alsa/soc/overview.txt
new file mode 100644
index 000000000000..753c5cc5984a
--- /dev/null
+++ b/Documentation/sound/alsa/soc/overview.txt
@@ -0,0 +1,83 @@
1ALSA SoC Layer
2==============
3
4The overall project goal of the ALSA System on Chip (ASoC) layer is to provide
5better ALSA support for embedded system on chip procesors (e.g. pxa2xx, au1x00,
6iMX, etc) and portable audio codecs. Currently there is some support in the
7kernel for SoC audio, however it has some limitations:-
8
9 * Currently, codec drivers are often tightly coupled to the underlying SoC
10 cpu. This is not ideal and leads to code duplication i.e. Linux now has 4
11 different wm8731 drivers for 4 different SoC platforms.
12
13 * There is no standard method to signal user initiated audio events.
14 e.g. Headphone/Mic insertion, Headphone/Mic detection after an insertion
15 event. These are quite common events on portable devices and ofter require
16 machine specific code to re route audio, enable amps etc after such an event.
17
18 * Current drivers tend to power up the entire codec when playing
19 (or recording) audio. This is fine for a PC, but tends to waste a lot of
20 power on portable devices. There is also no support for saving power via
21 changing codec oversampling rates, bias currents, etc.
22
23
24ASoC Design
25===========
26
27The ASoC layer is designed to address these issues and provide the following
28features :-
29
30 * Codec independence. Allows reuse of codec drivers on other platforms
31 and machines.
32
33 * Easy I2S/PCM audio interface setup between codec and SoC. Each SoC interface
34 and codec registers it's audio interface capabilities with the core and are
35 subsequently matched and configured when the application hw params are known.
36
37 * Dynamic Audio Power Management (DAPM). DAPM automatically sets the codec to
38 it's minimum power state at all times. This includes powering up/down
39 internal power blocks depending on the internal codec audio routing and any
40 active streams.
41
42 * Pop and click reduction. Pops and clicks can be reduced by powering the
43 codec up/down in the correct sequence (including using digital mute). ASoC
44 signals the codec when to change power states.
45
46 * Machine specific controls: Allow machines to add controls to the sound card
47 e.g. volume control for speaker amp.
48
49To achieve all this, ASoC basically splits an embedded audio system into 3
50components :-
51
52 * Codec driver: The codec driver is platform independent and contains audio
53 controls, audio interface capabilities, codec dapm definition and codec IO
54 functions.
55
56 * Platform driver: The platform driver contains the audio dma engine and audio
57 interface drivers (e.g. I2S, AC97, PCM) for that platform.
58
59 * Machine driver: The machine driver handles any machine specific controls and
60 audio events. i.e. turing on an amp at start of playback.
61
62
63Documentation
64=============
65
66The documentation is spilt into the following sections:-
67
68overview.txt: This file.
69
70codec.txt: Codec driver internals.
71
72DAI.txt: Description of Digital Audio Interface standards and how to configure
73a DAI within your codec and CPU DAI drivers.
74
75dapm.txt: Dynamic Audio Power Management
76
77platform.txt: Platform audio DMA and DAI.
78
79machine.txt: Machine driver internals.
80
81pop_clicks.txt: How to minimise audio artifacts.
82
83clocking.txt: ASoC clocking for best power performance. \ No newline at end of file
diff --git a/Documentation/sound/alsa/soc/platform.txt b/Documentation/sound/alsa/soc/platform.txt
new file mode 100644
index 000000000000..e95b16d5a53b
--- /dev/null
+++ b/Documentation/sound/alsa/soc/platform.txt
@@ -0,0 +1,58 @@
1ASoC Platform Driver
2====================
3
4An ASoC platform driver can be divided into audio DMA and SoC DAI configuration
5and control. The platform drivers only target the SoC CPU and must have no board
6specific code.
7
8Audio DMA
9=========
10
11The platform DMA driver optionally supports the following alsa operations:-
12
13/* SoC audio ops */
14struct snd_soc_ops {
15 int (*startup)(struct snd_pcm_substream *);
16 void (*shutdown)(struct snd_pcm_substream *);
17 int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
18 int (*hw_free)(struct snd_pcm_substream *);
19 int (*prepare)(struct snd_pcm_substream *);
20 int (*trigger)(struct snd_pcm_substream *, int);
21};
22
23The platform driver exports it's DMA functionailty via struct snd_soc_platform:-
24
25struct snd_soc_platform {
26 char *name;
27
28 int (*probe)(struct platform_device *pdev);
29 int (*remove)(struct platform_device *pdev);
30 int (*suspend)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
31 int (*resume)(struct platform_device *pdev, struct snd_soc_cpu_dai *cpu_dai);
32
33 /* pcm creation and destruction */
34 int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *, struct snd_pcm *);
35 void (*pcm_free)(struct snd_pcm *);
36
37 /* platform stream ops */
38 struct snd_pcm_ops *pcm_ops;
39};
40
41Please refer to the alsa driver documentation for details of audio DMA.
42http://www.alsa-project.org/~iwai/writing-an-alsa-driver/c436.htm
43
44An example DMA driver is soc/pxa/pxa2xx-pcm.c
45
46
47SoC DAI Drivers
48===============
49
50Each SoC DAI driver must provide the following features:-
51
52 1) Digital audio interface (DAI) description
53 2) Digital audio interface configuration
54 3) PCM's description
55 4) Sysclk configuration
56 5) Suspend and resume (optional)
57
58Please see codec.txt for a description of items 1 - 4.
diff --git a/Documentation/sound/alsa/soc/pops_clicks.txt b/Documentation/sound/alsa/soc/pops_clicks.txt
new file mode 100644
index 000000000000..2cf7ee5b3d74
--- /dev/null
+++ b/Documentation/sound/alsa/soc/pops_clicks.txt
@@ -0,0 +1,52 @@
1Audio Pops and Clicks
2=====================
3
4Pops and clicks are unwanted audio artifacts caused by the powering up and down
5of components within the audio subsystem. This is noticable on PC's when an
6audio module is either loaded or unloaded (at module load time the sound card is
7powered up and causes a popping noise on the speakers).
8
9Pops and clicks can be more frequent on portable systems with DAPM. This is
10because the components within the subsystem are being dynamically powered
11depending on the audio usage and this can subsequently cause a small pop or
12click every time a component power state is changed.
13
14
15Minimising Playback Pops and Clicks
16===================================
17
18Playback pops in portable audio subsystems cannot be completely eliminated atm,
19however future audio codec hardware will have better pop and click supression.
20Pops can be reduced within playback by powering the audio components in a
21specific order. This order is different for startup and shutdown and follows
22some basic rules:-
23
24 Startup Order :- DAC --> Mixers --> Output PGA --> Digital Unmute
25
26 Shutdown Order :- Digital Mute --> Output PGA --> Mixers --> DAC
27
28This assumes that the codec PCM output path from the DAC is via a mixer and then
29a PGA (programmable gain amplifier) before being output to the speakers.
30
31
32Minimising Capture Pops and Clicks
33==================================
34
35Capture artifacts are somewhat easier to get rid as we can delay activating the
36ADC until all the pops have occured. This follows similar power rules to
37playback in that components are powered in a sequence depending upon stream
38startup or shutdown.
39
40 Startup Order - Input PGA --> Mixers --> ADC
41
42 Shutdown Order - ADC --> Mixers --> Input PGA
43
44
45Zipper Noise
46============
47An unwanted zipper noise can occur within the audio playback or capture stream
48when a volume control is changed near its maximum gain value. The zipper noise
49is heard when the gain increase or decrease changes the mean audio signal
50amplitude too quickly. It can be minimised by enabling the zero cross setting
51for each volume control. The ZC forces the gain change to occur when the signal
52crosses the zero amplitude line.
diff --git a/MAINTAINERS b/MAINTAINERS
index 6ddae2bb6821..f2a79481f1c1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3037,6 +3037,12 @@ M: perex@suse.cz
3037L: alsa-devel@alsa-project.org 3037L: alsa-devel@alsa-project.org
3038S: Maintained 3038S: Maintained
3039 3039
3040SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
3041P: Liam Girdwood
3042M: liam.girdwood@wolfsonmicro.com
3043L: alsa-devel@alsa-project.org
3044S: Supported
3045
3040SPI SUBSYSTEM 3046SPI SUBSYSTEM
3041P: David Brownell 3047P: David Brownell
3042M: dbrownell@users.sourceforge.net 3048M: dbrownell@users.sourceforge.net
diff --git a/drivers/input/touchscreen/ucb1400_ts.c b/drivers/input/touchscreen/ucb1400_ts.c
index 4358a0a78eaa..c7db4032ef02 100644
--- a/drivers/input/touchscreen/ucb1400_ts.c
+++ b/drivers/input/touchscreen/ucb1400_ts.c
@@ -83,7 +83,7 @@
83 83
84 84
85struct ucb1400 { 85struct ucb1400 {
86 ac97_t *ac97; 86 struct snd_ac97 *ac97;
87 struct input_dev *ts_idev; 87 struct input_dev *ts_idev;
88 88
89 int irq; 89 int irq;
diff --git a/include/linux/i2c-id.h b/include/linux/i2c-id.h
index d38778f2fbec..6e7ec4c76178 100644
--- a/include/linux/i2c-id.h
+++ b/include/linux/i2c-id.h
@@ -115,6 +115,8 @@
115#define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */ 115#define I2C_DRIVERID_KS0127 86 /* Samsung ks0127 video decoder */
116#define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */ 116#define I2C_DRIVERID_TLV320AIC23B 87 /* TI TLV320AIC23B audio codec */
117#define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */ 117#define I2C_DRIVERID_ISL1208 88 /* Intersil ISL1208 RTC */
118#define I2C_DRIVERID_WM8731 89 /* Wolfson WM8731 audio codec */
119#define I2C_DRIVERID_WM8750 90 /* Wolfson WM8750 audio codec */
118 120
119#define I2C_DRIVERID_I2CDEV 900 121#define I2C_DRIVERID_I2CDEV 900
120#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */ 122#define I2C_DRIVERID_ARP 902 /* SMBus ARP Client */
diff --git a/include/sound/ac97_codec.h b/include/sound/ac97_codec.h
index 33720397a904..246ac23534bd 100644
--- a/include/sound/ac97_codec.h
+++ b/include/sound/ac97_codec.h
@@ -375,6 +375,7 @@
375#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */ 375#define AC97_SCAP_DETECT_BY_VENDOR (1<<8) /* use vendor registers for read tests */
376#define AC97_SCAP_NO_SPDIF (1<<9) /* don't build SPDIF controls */ 376#define AC97_SCAP_NO_SPDIF (1<<9) /* don't build SPDIF controls */
377#define AC97_SCAP_EAPD_LED (1<<10) /* EAPD as mute LED */ 377#define AC97_SCAP_EAPD_LED (1<<10) /* EAPD as mute LED */
378#define AC97_SCAP_POWER_SAVE (1<<11) /* capable for aggresive power-saving */
378 379
379/* ac97->flags */ 380/* ac97->flags */
380#define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */ 381#define AC97_HAS_PC_BEEP (1<<0) /* force PC Speaker usage */
@@ -425,6 +426,7 @@ struct snd_ac97_build_ops {
425 426
426struct snd_ac97_bus_ops { 427struct snd_ac97_bus_ops {
427 void (*reset) (struct snd_ac97 *ac97); 428 void (*reset) (struct snd_ac97 *ac97);
429 void (*warm_reset)(struct snd_ac97 *ac97);
428 void (*write) (struct snd_ac97 *ac97, unsigned short reg, unsigned short val); 430 void (*write) (struct snd_ac97 *ac97, unsigned short reg, unsigned short val);
429 unsigned short (*read) (struct snd_ac97 *ac97, unsigned short reg); 431 unsigned short (*read) (struct snd_ac97 *ac97, unsigned short reg);
430 void (*wait) (struct snd_ac97 *ac97); 432 void (*wait) (struct snd_ac97 *ac97);
@@ -501,6 +503,7 @@ struct snd_ac97 {
501 unsigned short id[3]; // codec IDs (lower 16-bit word) 503 unsigned short id[3]; // codec IDs (lower 16-bit word)
502 unsigned short pcmreg[3]; // PCM registers 504 unsigned short pcmreg[3]; // PCM registers
503 unsigned short codec_cfg[3]; // CODEC_CFG bits 505 unsigned short codec_cfg[3]; // CODEC_CFG bits
506 unsigned char swap_mic_linein; // AD1986/AD1986A only
504 } ad18xx; 507 } ad18xx;
505 unsigned int dev_flags; /* device specific */ 508 unsigned int dev_flags; /* device specific */
506 } spec; 509 } spec;
@@ -510,7 +513,6 @@ struct snd_ac97 {
510 513
511#ifdef CONFIG_SND_AC97_POWER_SAVE 514#ifdef CONFIG_SND_AC97_POWER_SAVE
512 unsigned int power_up; /* power states */ 515 unsigned int power_up; /* power states */
513 struct workqueue_struct *power_workq;
514 struct delayed_work power_work; 516 struct delayed_work power_work;
515#endif 517#endif
516 struct device dev; 518 struct device dev;
diff --git a/include/sound/ad1848.h b/include/sound/ad1848.h
index c8de6f83338f..b2c3f00a9b35 100644
--- a/include/sound/ad1848.h
+++ b/include/sound/ad1848.h
@@ -185,7 +185,7 @@ struct ad1848_mix_elem {
185 int index; 185 int index;
186 int type; 186 int type;
187 unsigned long private_value; 187 unsigned long private_value;
188 unsigned int *tlv; 188 const unsigned int *tlv;
189}; 189};
190 190
191#define AD1848_SINGLE(xname, xindex, reg, shift, mask, invert) \ 191#define AD1848_SINGLE(xname, xindex, reg, shift, mask, invert) \
diff --git a/include/sound/ak4114.h b/include/sound/ak4114.h
index 2ee061625fd0..c149d3b2558b 100644
--- a/include/sound/ak4114.h
+++ b/include/sound/ak4114.h
@@ -181,7 +181,6 @@ struct ak4114 {
181 unsigned long ccrc_errors; 181 unsigned long ccrc_errors;
182 unsigned char rcs0; 182 unsigned char rcs0;
183 unsigned char rcs1; 183 unsigned char rcs1;
184 struct workqueue_struct *workqueue;
185 struct delayed_work work; 184 struct delayed_work work;
186 void *change_callback_private; 185 void *change_callback_private;
187 void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1); 186 void (*change_callback)(struct ak4114 *ak4114, unsigned char c0, unsigned char c1);
@@ -189,7 +188,7 @@ struct ak4114 {
189 188
190int snd_ak4114_create(struct snd_card *card, 189int snd_ak4114_create(struct snd_card *card,
191 ak4114_read_t *read, ak4114_write_t *write, 190 ak4114_read_t *read, ak4114_write_t *write,
192 unsigned char pgm[7], unsigned char txcsb[5], 191 const unsigned char pgm[7], const unsigned char txcsb[5],
193 void *private_data, struct ak4114 **r_ak4114); 192 void *private_data, struct ak4114 **r_ak4114);
194void snd_ak4114_reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char mask, unsigned char val); 193void snd_ak4114_reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char mask, unsigned char val);
195void snd_ak4114_reinit(struct ak4114 *ak4114); 194void snd_ak4114_reinit(struct ak4114 *ak4114);
diff --git a/include/sound/ak4117.h b/include/sound/ak4117.h
index 2b96c32f06fd..d650d52e3d29 100644
--- a/include/sound/ak4117.h
+++ b/include/sound/ak4117.h
@@ -178,7 +178,7 @@ struct ak4117 {
178}; 178};
179 179
180int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write, 180int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write,
181 unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117); 181 const unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117);
182void snd_ak4117_reg_write(struct ak4117 *ak4117, unsigned char reg, unsigned char mask, unsigned char val); 182void snd_ak4117_reg_write(struct ak4117 *ak4117, unsigned char reg, unsigned char mask, unsigned char val);
183void snd_ak4117_reinit(struct ak4117 *ak4117); 183void snd_ak4117_reinit(struct ak4117 *ak4117);
184int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *capture_substream); 184int snd_ak4117_build(struct ak4117 *ak4117, struct snd_pcm_substream *capture_substream);
diff --git a/include/sound/ak4xxx-adda.h b/include/sound/ak4xxx-adda.h
index d0deca669b92..aa49dda4f410 100644
--- a/include/sound/ak4xxx-adda.h
+++ b/include/sound/ak4xxx-adda.h
@@ -50,6 +50,8 @@ struct snd_akm4xxx_adc_channel {
50 char *name; /* capture gain volume label */ 50 char *name; /* capture gain volume label */
51 char *switch_name; /* capture switch */ 51 char *switch_name; /* capture switch */
52 unsigned int num_channels; 52 unsigned int num_channels;
53 char *selector_name; /* capture source select label */
54 const char **input_names; /* capture source names (NULL terminated) */
53}; 55};
54 56
55struct snd_akm4xxx { 57struct snd_akm4xxx {
@@ -69,8 +71,8 @@ struct snd_akm4xxx {
69 } type; 71 } type;
70 72
71 /* (array) information of combined codecs */ 73 /* (array) information of combined codecs */
72 struct snd_akm4xxx_dac_channel *dac_info; 74 const struct snd_akm4xxx_dac_channel *dac_info;
73 struct snd_akm4xxx_adc_channel *adc_info; 75 const struct snd_akm4xxx_adc_channel *adc_info;
74 76
75 struct snd_ak4xxx_ops ops; 77 struct snd_ak4xxx_ops ops;
76}; 78};
diff --git a/include/sound/control.h b/include/sound/control.h
index 1de148b0fd94..72e759f619b1 100644
--- a/include/sound/control.h
+++ b/include/sound/control.h
@@ -49,7 +49,7 @@ struct snd_kcontrol_new {
49 snd_kcontrol_put_t *put; 49 snd_kcontrol_put_t *put;
50 union { 50 union {
51 snd_kcontrol_tlv_rw_t *c; 51 snd_kcontrol_tlv_rw_t *c;
52 unsigned int *p; 52 const unsigned int *p;
53 } tlv; 53 } tlv;
54 unsigned long private_value; 54 unsigned long private_value;
55}; 55};
@@ -69,7 +69,7 @@ struct snd_kcontrol {
69 snd_kcontrol_put_t *put; 69 snd_kcontrol_put_t *put;
70 union { 70 union {
71 snd_kcontrol_tlv_rw_t *c; 71 snd_kcontrol_tlv_rw_t *c;
72 unsigned int *p; 72 const unsigned int *p;
73 } tlv; 73 } tlv;
74 unsigned long private_value; 74 unsigned long private_value;
75 void *private_data; 75 void *private_data;
@@ -108,7 +108,6 @@ typedef int (*snd_kctl_ioctl_func_t) (struct snd_card * card,
108 108
109void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id); 109void snd_ctl_notify(struct snd_card * card, unsigned int mask, struct snd_ctl_elem_id * id);
110 110
111struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol * kcontrol, unsigned int access);
112struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data); 111struct snd_kcontrol *snd_ctl_new1(const struct snd_kcontrol_new * kcontrolnew, void * private_data);
113void snd_ctl_free_one(struct snd_kcontrol * kcontrol); 112void snd_ctl_free_one(struct snd_kcontrol * kcontrol);
114int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol); 113int snd_ctl_add(struct snd_card * card, struct snd_kcontrol * kcontrol);
diff --git a/include/sound/core.h b/include/sound/core.h
index 521f036cce99..4b9e609975ab 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -211,9 +211,40 @@ extern struct class *sound_class;
211 211
212void snd_request_card(int card); 212void snd_request_card(int card);
213 213
214int snd_register_device(int type, struct snd_card *card, int dev, 214int snd_register_device_for_dev(int type, struct snd_card *card,
215 const struct file_operations *f_ops, void *private_data, 215 int dev,
216 const char *name); 216 const struct file_operations *f_ops,
217 void *private_data,
218 const char *name,
219 struct device *device);
220
221/**
222 * snd_register_device - Register the ALSA device file for the card
223 * @type: the device type, SNDRV_DEVICE_TYPE_XXX
224 * @card: the card instance
225 * @dev: the device index
226 * @f_ops: the file operations
227 * @private_data: user pointer for f_ops->open()
228 * @name: the device file name
229 *
230 * Registers an ALSA device file for the given card.
231 * The operators have to be set in reg parameter.
232 *
233 * This function uses the card's device pointer to link to the
234 * correct &struct device.
235 *
236 * Returns zero if successful, or a negative error code on failure.
237 */
238static inline int snd_register_device(int type, struct snd_card *card, int dev,
239 const struct file_operations *f_ops,
240 void *private_data,
241 const char *name)
242{
243 return snd_register_device_for_dev(type, card, dev, f_ops,
244 private_data, name,
245 snd_card_get_device_link(card));
246}
247
217int snd_unregister_device(int type, struct snd_card *card, int dev); 248int snd_unregister_device(int type, struct snd_card *card, int dev);
218void *snd_lookup_minor_data(unsigned int minor, int type); 249void *snd_lookup_minor_data(unsigned int minor, int type);
219int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev, 250int snd_add_device_sysfs_file(int type, struct snd_card *card, int dev,
@@ -396,6 +427,29 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
396#endif 427#endif
397#endif 428#endif
398 429
399#include "typedefs.h" 430/* PCI quirk list helper */
431struct snd_pci_quirk {
432 unsigned short subvendor; /* PCI subvendor ID */
433 unsigned short subdevice; /* PCI subdevice ID */
434 int value; /* value */
435#ifdef CONFIG_SND_DEBUG_DETECT
436 const char *name; /* name of the device (optional) */
437#endif
438};
439
440#define _SND_PCI_QUIRK_ID(vend,dev) \
441 .subvendor = (vend), .subdevice = (dev)
442#define SND_PCI_QUIRK_ID(vend,dev) {_SND_PCI_QUIRK_ID(vend, dev)}
443#ifdef CONFIG_SND_DEBUG_DETECT
444#define SND_PCI_QUIRK(vend,dev,xname,val) \
445 {_SND_PCI_QUIRK_ID(vend, dev), .value = (val), .name = (xname)}
446#else
447#define SND_PCI_QUIRK(vend,dev,xname,val) \
448 {_SND_PCI_QUIRK_ID(vend, dev), .value = (val)}
449#endif
450
451const struct snd_pci_quirk *
452snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list);
453
400 454
401#endif /* __SOUND_CORE_H */ 455#endif /* __SOUND_CORE_H */
diff --git a/include/sound/emu10k1.h b/include/sound/emu10k1.h
index 3d3c1514cf71..eb7ce96ddf3a 100644
--- a/include/sound/emu10k1.h
+++ b/include/sound/emu10k1.h
@@ -188,7 +188,35 @@
188#define HCFG_LEGACYINT 0x00200000 /* 1 = legacy event captured. Write 1 to clear. */ 188#define HCFG_LEGACYINT 0x00200000 /* 1 = legacy event captured. Write 1 to clear. */
189 /* NOTE: The rest of the bits in this register */ 189 /* NOTE: The rest of the bits in this register */
190 /* _are_ relevant under Linux. */ 190 /* _are_ relevant under Linux. */
191#define HCFG_CODECFORMAT_MASK 0x00070000 /* CODEC format */ 191#define HCFG_PUSH_BUTTON_ENABLE 0x00100000 /* Enables Volume Inc/Dec and Mute functions */
192#define HCFG_BAUD_RATE 0x00080000 /* 0 = 48kHz, 1 = 44.1kHz */
193#define HCFG_EXPANDED_MEM 0x00040000 /* 1 = any 16M of 4G addr, 0 = 32M of 2G addr */
194#define HCFG_CODECFORMAT_MASK 0x00030000 /* CODEC format */
195
196/* Specific to Alice2, CA0102 */
197#define HCFG_CODECFORMAT_AC97_1 0x00000000 /* AC97 CODEC format -- Ver 1.03 */
198#define HCFG_CODECFORMAT_AC97_2 0x00010000 /* AC97 CODEC format -- Ver 2.1 */
199#define HCFG_AUTOMUTE_ASYNC 0x00008000 /* When set, the async sample rate convertors */
200 /* will automatically mute their output when */
201 /* they are not rate-locked to the external */
202 /* async audio source */
203#define HCFG_AUTOMUTE_SPDIF 0x00004000 /* When set, the async sample rate convertors */
204 /* will automatically mute their output when */
205 /* the SPDIF V-bit indicates invalid audio */
206#define HCFG_EMU32_SLAVE 0x00002000 /* 0 = Master, 1 = Slave. Slave for EMU1010 */
207#define HCFG_SLOW_RAMP 0x00001000 /* Increases Send Smoothing time constant */
208/* 0x00000800 not used on Alice2 */
209#define HCFG_PHASE_TRACK_MASK 0x00000700 /* When set, forces corresponding input to */
210 /* phase track the previous input. */
211 /* I2S0 can phase track the last S/PDIF input */
212#define HCFG_I2S_ASRC_ENABLE 0x00000070 /* When set, enables asynchronous sample rate */
213 /* conversion for the corresponding */
214 /* I2S format input */
215/* Rest of HCFG 0x0000000f same as below. LOCKSOUNDCACHE etc. */
216
217
218
219/* Older chips */
192#define HCFG_CODECFORMAT_AC97 0x00000000 /* AC97 CODEC format -- Primary Output */ 220#define HCFG_CODECFORMAT_AC97 0x00000000 /* AC97 CODEC format -- Primary Output */
193#define HCFG_CODECFORMAT_I2S 0x00010000 /* I2S CODEC format -- Secondary (Rear) Output */ 221#define HCFG_CODECFORMAT_I2S 0x00010000 /* I2S CODEC format -- Secondary (Rear) Output */
194#define HCFG_GPINPUT0 0x00004000 /* External pin112 */ 222#define HCFG_GPINPUT0 0x00004000 /* External pin112 */
@@ -432,6 +460,7 @@
432#define FXRT_CHANNELC 0x0f000000 /* Effects send bus number for channel's effects send C */ 460#define FXRT_CHANNELC 0x0f000000 /* Effects send bus number for channel's effects send C */
433#define FXRT_CHANNELD 0xf0000000 /* Effects send bus number for channel's effects send D */ 461#define FXRT_CHANNELD 0xf0000000 /* Effects send bus number for channel's effects send D */
434 462
463#define A_HR 0x0b /* High Resolution. 24bit playback from host to DSP. */
435#define MAPA 0x0c /* Cache map A */ 464#define MAPA 0x0c /* Cache map A */
436 465
437#define MAPB 0x0d /* Cache map B */ 466#define MAPB 0x0d /* Cache map B */
@@ -439,6 +468,8 @@
439#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */ 468#define MAP_PTE_MASK 0xffffe000 /* The 19 MSBs of the PTE indexed by the PTI */
440#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */ 469#define MAP_PTI_MASK 0x00001fff /* The 13 bit index to one of the 8192 PTE dwords */
441 470
471/* 0x0e, 0x0f: Not used */
472
442#define ENVVOL 0x10 /* Volume envelope register */ 473#define ENVVOL 0x10 /* Volume envelope register */
443#define ENVVOL_MASK 0x0000ffff /* Current value of volume envelope state variable */ 474#define ENVVOL_MASK 0x0000ffff /* Current value of volume envelope state variable */
444 /* 0x8000-n == 666*n usec delay */ 475 /* 0x8000-n == 666*n usec delay */
@@ -527,7 +558,7 @@
527 /* NOTE: All channels contain internal variables; do */ 558 /* NOTE: All channels contain internal variables; do */
528 /* not write to these locations. */ 559 /* not write to these locations. */
529 560
530/* 1f something */ 561/* 0x1f: not used */
531 562
532#define CD0 0x20 /* Cache data 0 register */ 563#define CD0 0x20 /* Cache data 0 register */
533#define CD1 0x21 /* Cache data 1 register */ 564#define CD1 0x21 /* Cache data 1 register */
@@ -597,6 +628,8 @@
597#define FXWC_SPDIFLEFT (1<<22) /* 0x00400000 */ 628#define FXWC_SPDIFLEFT (1<<22) /* 0x00400000 */
598#define FXWC_SPDIFRIGHT (1<<23) /* 0x00800000 */ 629#define FXWC_SPDIFRIGHT (1<<23) /* 0x00800000 */
599 630
631#define A_TBLSZ ` 0x43 /* Effects Tank Internal Table Size. Only low byte or register used */
632
600#define TCBS 0x44 /* Tank cache buffer size register */ 633#define TCBS 0x44 /* Tank cache buffer size register */
601#define TCBS_MASK 0x00000007 /* Tank cache buffer size field */ 634#define TCBS_MASK 0x00000007 /* Tank cache buffer size field */
602#define TCBS_BUFFSIZE_16K 0x00000000 635#define TCBS_BUFFSIZE_16K 0x00000000
@@ -617,7 +650,7 @@
617#define FXBA 0x47 /* FX Buffer Address */ 650#define FXBA 0x47 /* FX Buffer Address */
618#define FXBA_MASK 0xfffff000 /* 20 bit base address */ 651#define FXBA_MASK 0xfffff000 /* 20 bit base address */
619 652
620/* 0x48 something - word access, defaults to 3f */ 653#define A_HWM 0x48 /* High PCI Water Mark - word access, defaults to 3f */
621 654
622#define MICBS 0x49 /* Microphone buffer size register */ 655#define MICBS 0x49 /* Microphone buffer size register */
623 656
@@ -661,6 +694,18 @@
661#define ADCBS_BUFSIZE_57344 0x0000001e 694#define ADCBS_BUFSIZE_57344 0x0000001e
662#define ADCBS_BUFSIZE_65536 0x0000001f 695#define ADCBS_BUFSIZE_65536 0x0000001f
663 696
697/* Current Send B, A Amounts */
698#define A_CSBA 0x4c
699
700/* Current Send D, C Amounts */
701#define A_CSDC 0x4d
702
703/* Current Send F, E Amounts */
704#define A_CSFE 0x4e
705
706/* Current Send H, G Amounts */
707#define A_CSHG 0x4f
708
664 709
665#define CDCS 0x50 /* CD-ROM digital channel status register */ 710#define CDCS 0x50 /* CD-ROM digital channel status register */
666 711
@@ -668,6 +713,9 @@
668 713
669#define DBG 0x52 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ 714#define DBG 0x52 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
670 715
716/* S/PDIF Input C Channel Status */
717#define A_SPSC 0x52
718
671#define REG53 0x53 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */ 719#define REG53 0x53 /* DO NOT PROGRAM THIS REGISTER!!! MAY DESTROY CHIP */
672 720
673#define A_DBG 0x53 721#define A_DBG 0x53
@@ -708,6 +756,8 @@
708#define SPCS_NOTAUDIODATA 0x00000002 /* 0 = Digital audio, 1 = not audio */ 756#define SPCS_NOTAUDIODATA 0x00000002 /* 0 = Digital audio, 1 = not audio */
709#define SPCS_PROFESSIONAL 0x00000001 /* 0 = Consumer (IEC-958), 1 = pro (AES3-1992) */ 757#define SPCS_PROFESSIONAL 0x00000001 /* 0 = Consumer (IEC-958), 1 = pro (AES3-1992) */
710 758
759/* 0x57: Not used */
760
711/* The 32-bit CLIx and SOLx registers all have one bit per channel control/status */ 761/* The 32-bit CLIx and SOLx registers all have one bit per channel control/status */
712#define CLIEL 0x58 /* Channel loop interrupt enable low register */ 762#define CLIEL 0x58 /* Channel loop interrupt enable low register */
713 763
@@ -733,6 +783,9 @@
733#define AC97SLOT_CNTR 0x10 /* Center enable */ 783#define AC97SLOT_CNTR 0x10 /* Center enable */
734#define AC97SLOT_LFE 0x20 /* LFE enable */ 784#define AC97SLOT_LFE 0x20 /* LFE enable */
735 785
786/* PCB Revision */
787#define A_PCB 0x5f
788
736// NOTE: 0x60,61,62: 64-bit 789// NOTE: 0x60,61,62: 64-bit
737#define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */ 790#define CDSRCS 0x60 /* CD-ROM Sample Rate Converter status register */
738 791
@@ -780,9 +833,18 @@
780 833
781#define HLIPH 0x69 /* Channel half loop interrupt pending high register */ 834#define HLIPH 0x69 /* Channel half loop interrupt pending high register */
782 835
783// 0x6a,6b,6c used for some recording 836/* S/PDIF Host Record Index (bypasses SRC) */
784// 0x6d unused 837#define A_SPRI 0x6a
785// 0x6e,6f - tanktable base / offset 838/* S/PDIF Host Record Address */
839#define A_SPRA 0x6b
840/* S/PDIF Host Record Control */
841#define A_SPRC 0x6c
842/* Delayed Interrupt Counter & Enable */
843#define A_DICE 0x6d
844/* Tank Table Base */
845#define A_TTB 0x6e
846/* Tank Delay Offset */
847#define A_TDOF 0x6f
786 848
787/* This is the MPU port on the card (via the game port) */ 849/* This is the MPU port on the card (via the game port) */
788#define A_MUDATA1 0x70 850#define A_MUDATA1 0x70
@@ -800,6 +862,7 @@
800#define A_FXWC1 0x74 /* Selects 0x7f-0x60 for FX recording */ 862#define A_FXWC1 0x74 /* Selects 0x7f-0x60 for FX recording */
801#define A_FXWC2 0x75 /* Selects 0x9f-0x80 for FX recording */ 863#define A_FXWC2 0x75 /* Selects 0x9f-0x80 for FX recording */
802 864
865/* Extended Hardware Control */
803#define A_SPDIF_SAMPLERATE 0x76 /* Set the sample rate of SPDIF output */ 866#define A_SPDIF_SAMPLERATE 0x76 /* Set the sample rate of SPDIF output */
804#define A_SAMPLE_RATE 0x76 /* Various sample rate settings. */ 867#define A_SAMPLE_RATE 0x76 /* Various sample rate settings. */
805#define A_SAMPLE_RATE_NOT_USED 0x0ffc111e /* Bits that are not used and cannot be set. */ 868#define A_SAMPLE_RATE_NOT_USED 0x0ffc111e /* Bits that are not used and cannot be set. */
@@ -822,8 +885,20 @@
822#define A_PCM_96000 0x00004000 885#define A_PCM_96000 0x00004000
823#define A_PCM_44100 0x00008000 886#define A_PCM_44100 0x00008000
824 887
825/* 0x77,0x78,0x79 "something i2s-related" - default to 0x01080000 on my audigy 2 ZS --rlrevell */ 888/* I2S0 Sample Rate Tracker Status */
826/* 0x7a, 0x7b - lookup tables */ 889#define A_SRT3 0x77
890
891/* I2S1 Sample Rate Tracker Status */
892#define A_SRT4 0x78
893
894/* I2S2 Sample Rate Tracker Status */
895#define A_SRT5 0x79
896/* - default to 0x01080000 on my audigy 2 ZS --rlrevell */
897
898/* Tank Table DMA Address */
899#define A_TTDA 0x7a
900/* Tank Table DMA Data */
901#define A_TTDD 0x7b
827 902
828#define A_FXRT2 0x7c 903#define A_FXRT2 0x7c
829#define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */ 904#define A_FXRT_CHANNELE 0x0000003f /* Effects send bus number for channel's effects send E */
@@ -845,7 +920,7 @@
845#define A_FXRT_CHANNELC 0x003f0000 920#define A_FXRT_CHANNELC 0x003f0000
846#define A_FXRT_CHANNELD 0x3f000000 921#define A_FXRT_CHANNELD 0x3f000000
847 922
848 923/* 0x7f: Not used */
849/* Each FX general purpose register is 32 bits in length, all bits are used */ 924/* Each FX general purpose register is 32 bits in length, all bits are used */
850#define FXGPREGBASE 0x100 /* FX general purpose registers base */ 925#define FXGPREGBASE 0x100 /* FX general purpose registers base */
851#define A_FXGPREGBASE 0x400 /* Audigy GPRs, 0x400 to 0x5ff */ 926#define A_FXGPREGBASE 0x400 /* Audigy GPRs, 0x400 to 0x5ff */
@@ -886,6 +961,293 @@
886#define A_HIWORD_RESULT_MASK 0x007ff000 961#define A_HIWORD_RESULT_MASK 0x007ff000
887#define A_HIWORD_OPA_MASK 0x000007ff 962#define A_HIWORD_OPA_MASK 0x000007ff
888 963
964/************************************************************************************************/
965/* EMU1010m HANA FPGA registers */
966/************************************************************************************************/
967#define EMU_HANA_DESTHI 0x00 /* 0000xxx 3 bits Link Destination */
968#define EMU_HANA_DESTLO 0x01 /* 00xxxxx 5 bits */
969#define EMU_HANA_SRCHI 0x02 /* 0000xxx 3 bits Link Source */
970#define EMU_HANA_SRCLO 0x03 /* 00xxxxx 5 bits */
971#define EMU_HANA_DOCK_PWR 0x04 /* 000000x 1 bits Audio Dock power */
972#define EMU_HANA_DOCK_PWR_ON 0x01 /* Audio Dock power on */
973#define EMU_HANA_WCLOCK 0x05 /* 0000xxx 3 bits Word Clock source select */
974 /* Must be written after power on to reset DLL */
975 /* One is unable to detect the Audio dock without this */
976#define EMU_HANA_WCLOCK_SRC_MASK 0x07
977#define EMU_HANA_WCLOCK_INT_48K 0x00
978#define EMU_HANA_WCLOCK_INT_44_1K 0x01
979#define EMU_HANA_WCLOCK_HANA_SPDIF_IN 0x02
980#define EMU_HANA_WCLOCK_HANA_ADAT_IN 0x03
981#define EMU_HANA_WCLOCK_SYNC_BNCN 0x04
982#define EMU_HANA_WCLOCK_2ND_HANA 0x05
983#define EMU_HANA_WCLOCK_SRC_RESERVED 0x06
984#define EMU_HANA_WCLOCK_OFF 0x07 /* For testing, forces fallback to DEFCLOCK */
985#define EMU_HANA_WCLOCK_MULT_MASK 0x18
986#define EMU_HANA_WCLOCK_1X 0x00
987#define EMU_HANA_WCLOCK_2X 0x08
988#define EMU_HANA_WCLOCK_4X 0x10
989#define EMU_HANA_WCLOCK_MULT_RESERVED 0x18
990
991#define EMU_HANA_DEFCLOCK 0x06 /* 000000x 1 bits Default Word Clock */
992#define EMU_HANA_DEFCLOCK_48K 0x00
993#define EMU_HANA_DEFCLOCK_44_1K 0x01
994
995#define EMU_HANA_UNMUTE 0x07 /* 000000x 1 bits Mute all audio outputs */
996#define EMU_MUTE 0x00
997#define EMU_UNMUTE 0x01
998
999#define EMU_HANA_FPGA_CONFIG 0x08 /* 00000xx 2 bits Config control of FPGAs */
1000#define EMU_HANA_FPGA_CONFIG_AUDIODOCK 0x01 /* Set in order to program FPGA on Audio Dock */
1001#define EMU_HANA_FPGA_CONFIG_HANA 0x02 /* Set in order to program FPGA on Hana */
1002
1003#define EMU_HANA_IRQ_ENABLE 0x09 /* 000xxxx 4 bits IRQ Enable */
1004#define EMU_HANA_IRQ_WCLK_CHANGED 0x01
1005#define EMU_HANA_IRQ_ADAT 0x02
1006#define EMU_HANA_IRQ_DOCK 0x04
1007#define EMU_HANA_IRQ_DOCK_LOST 0x08
1008
1009#define EMU_HANA_SPDIF_MODE 0x0a /* 00xxxxx 5 bits SPDIF MODE */
1010#define EMU_HANA_SPDIF_MODE_TX_COMSUMER 0x00
1011#define EMU_HANA_SPDIF_MODE_TX_PRO 0x01
1012#define EMU_HANA_SPDIF_MODE_TX_NOCOPY 0x02
1013#define EMU_HANA_SPDIF_MODE_RX_COMSUMER 0x00
1014#define EMU_HANA_SPDIF_MODE_RX_PRO 0x04
1015#define EMU_HANA_SPDIF_MODE_RX_NOCOPY 0x08
1016#define EMU_HANA_SPDIF_MODE_RX_INVALID 0x10
1017
1018#define EMU_HANA_OPTICAL_TYPE 0x0b /* 00000xx 2 bits ADAT or SPDIF in/out */
1019#define EMU_HANA_OPTICAL_IN_SPDIF 0x00
1020#define EMU_HANA_OPTICAL_IN_ADAT 0x01
1021#define EMU_HANA_OPTICAL_OUT_SPDIF 0x00
1022#define EMU_HANA_OPTICAL_OUT_ADAT 0x02
1023
1024#define EMU_HANA_MIDI_IN 0x0c /* 000000x 1 bit Control MIDI */
1025#define EMU_HANA_MIDI_IN_FROM_HAMOA 0x00 /* HAMOA MIDI in to Alice 2 MIDI B */
1026#define EMU_HANA_MIDI_IN_FROM_DOCK 0x01 /* Audio Dock MIDI in to Alice 2 MIDI B */
1027
1028#define EMU_HANA_DOCK_LEDS_1 0x0d /* 000xxxx 4 bit Audio Dock LEDs */
1029#define EMU_HANA_DOCK_LEDS_1_MIDI1 0x01 /* MIDI 1 LED on */
1030#define EMU_HANA_DOCK_LEDS_1_MIDI2 0x02 /* MIDI 2 LED on */
1031#define EMU_HANA_DOCK_LEDS_1_SMPTE_IN 0x04 /* SMPTE IN LED on */
1032#define EMU_HANA_DOCK_LEDS_1_SMPTE_OUT 0x08 /* SMPTE OUT LED on */
1033
1034#define EMU_HANA_DOCK_LEDS_2 0x0e /* 0xxxxxx 6 bit Audio Dock LEDs */
1035#define EMU_HANA_DOCK_LEDS_2_44K 0x01 /* 44.1 kHz LED on */
1036#define EMU_HANA_DOCK_LEDS_2_48K 0x02 /* 48 kHz LED on */
1037#define EMU_HANA_DOCK_LEDS_2_96K 0x04 /* 96 kHz LED on */
1038#define EMU_HANA_DOCK_LEDS_2_192K 0x08 /* 192 kHz LED on */
1039#define EMU_HANA_DOCK_LEDS_2_LOCK 0x10 /* LOCK LED on */
1040#define EMU_HANA_DOCK_LEDS_2_EXT 0x20 /* EXT LED on */
1041
1042#define EMU_HANA_DOCK_LEDS_3 0x0f /* 0xxxxxx 6 bit Audio Dock LEDs */
1043#define EMU_HANA_DOCK_LEDS_3_CLIP_A 0x01 /* Mic A Clip LED on */
1044#define EMU_HANA_DOCK_LEDS_3_CLIP_B 0x02 /* Mic B Clip LED on */
1045#define EMU_HANA_DOCK_LEDS_3_SIGNAL_A 0x04 /* Signal A Clip LED on */
1046#define EMU_HANA_DOCK_LEDS_3_SIGNAL_B 0x08 /* Signal B Clip LED on */
1047#define EMU_HANA_DOCK_LEDS_3_MANUAL_CLIP 0x10 /* Manual Clip detection */
1048#define EMU_HANA_DOCK_LEDS_3_MANUAL_SIGNAL 0x20 /* Manual Signal detection */
1049
1050#define EMU_HANA_ADC_PADS 0x10 /* 0000xxx 3 bit Audio Dock ADC 14dB pads */
1051#define EMU_HANA_DOCK_ADC_PAD1 0x01 /* 14dB Attenuation on Audio Dock ADC 1 */
1052#define EMU_HANA_DOCK_ADC_PAD2 0x02 /* 14dB Attenuation on Audio Dock ADC 2 */
1053#define EMU_HANA_DOCK_ADC_PAD3 0x04 /* 14dB Attenuation on Audio Dock ADC 3 */
1054#define EMU_HANA_0202_ADC_PAD1 0x08 /* 14dB Attenuation on 0202 ADC 1 */
1055
1056#define EMU_HANA_DOCK_MISC 0x11 /* 0xxxxxx 6 bit Audio Dock misc bits */
1057#define EMU_HANA_DOCK_DAC1_MUTE 0x01 /* DAC 1 Mute */
1058#define EMU_HANA_DOCK_DAC2_MUTE 0x02 /* DAC 2 Mute */
1059#define EMU_HANA_DOCK_DAC3_MUTE 0x04 /* DAC 3 Mute */
1060#define EMU_HANA_DOCK_DAC4_MUTE 0x08 /* DAC 4 Mute */
1061#define EMU_HANA_DOCK_PHONES_192_DAC1 0x00 /* DAC 1 Headphones source at 192kHz */
1062#define EMU_HANA_DOCK_PHONES_192_DAC2 0x10 /* DAC 2 Headphones source at 192kHz */
1063#define EMU_HANA_DOCK_PHONES_192_DAC3 0x20 /* DAC 3 Headphones source at 192kHz */
1064#define EMU_HANA_DOCK_PHONES_192_DAC4 0x30 /* DAC 4 Headphones source at 192kHz */
1065
1066#define EMU_HANA_MIDI_OUT 0x12 /* 00xxxxx 5 bit Source for each MIDI out port */
1067#define EMU_HANA_MIDI_OUT_0202 0x01 /* 0202 MIDI from Alice 2. 0 = A, 1 = B */
1068#define EMU_HANA_MIDI_OUT_DOCK1 0x02 /* Audio Dock MIDI1 front, from Alice 2. 0 = A, 1 = B */
1069#define EMU_HANA_MIDI_OUT_DOCK2 0x04 /* Audio Dock MIDI2 rear, from Alice 2. 0 = A, 1 = B */
1070#define EMU_HANA_MIDI_OUT_SYNC2 0x08 /* Sync card. Not the actual MIDI out jack. 0 = A, 1 = B */
1071#define EMU_HANA_MIDI_OUT_LOOP 0x10 /* 0 = bits (3:0) normal. 1 = MIDI loopback enabled. */
1072
1073#define EMU_HANA_DAC_PADS 0x13 /* 00xxxxx 5 bit DAC 14dB attenuation pads */
1074#define EMU_HANA_DOCK_DAC_PAD1 0x01 /* 14dB Attenuation on AudioDock DAC 1. Left and Right */
1075#define EMU_HANA_DOCK_DAC_PAD2 0x02 /* 14dB Attenuation on AudioDock DAC 2. Left and Right */
1076#define EMU_HANA_DOCK_DAC_PAD3 0x04 /* 14dB Attenuation on AudioDock DAC 3. Left and Right */
1077#define EMU_HANA_DOCK_DAC_PAD4 0x08 /* 14dB Attenuation on AudioDock DAC 4. Left and Right */
1078#define EMU_HANA_0202_DAC_PAD1 0x10 /* 14dB Attenuation on 0202 DAC 1. Left and Right */
1079
1080/* 0x14 - 0x1f Unused R/W registers */
1081#define EMU_HANA_IRQ_STATUS 0x20 /* 000xxxx 4 bits IRQ Status */
1082#if 0 /* Already defined for reg 0x09 IRQ_ENABLE */
1083#define EMU_HANA_IRQ_WCLK_CHANGED 0x01
1084#define EMU_HANA_IRQ_ADAT 0x02
1085#define EMU_HANA_IRQ_DOCK 0x04
1086#define EMU_HANA_IRQ_DOCK_LOST 0x08
1087#endif
1088
1089#define EMU_HANA_OPTION_CARDS 0x21 /* 000xxxx 4 bits Presence of option cards */
1090#define EMU_HANA_OPTION_HAMOA 0x01 /* HAMOA card present */
1091#define EMU_HANA_OPTION_SYNC 0x02 /* Sync card present */
1092#define EMU_HANA_OPTION_DOCK_ONLINE 0x04 /* Audio Dock online and FPGA configured */
1093#define EMU_HANA_OPTION_DOCK_OFFLINE 0x08 /* Audio Dock online and FPGA not configured */
1094
1095#define EMU_HANA_ID 0x22 /* 1010101 7 bits ID byte & 0x7f = 0x55 */
1096
1097#define EMU_HANA_MAJOR_REV 0x23 /* 0000xxx 3 bit Hana FPGA Major rev */
1098#define EMU_HANA_MINOR_REV 0x24 /* 0000xxx 3 bit Hana FPGA Minor rev */
1099
1100#define EMU_DOCK_MAJOR_REV 0x25 /* 0000xxx 3 bit Audio Dock FPGA Major rev */
1101#define EMU_DOCK_MINOR_REV 0x26 /* 0000xxx 3 bit Audio Dock FPGA Minor rev */
1102
1103#define EMU_DOCK_BOARD_ID 0x27 /* 00000xx 2 bits Audio Dock ID pins */
1104#define EMU_DOCK_BOARD_ID0 0x00 /* ID bit 0 */
1105#define EMU_DOCK_BOARD_ID1 0x03 /* ID bit 1 */
1106
1107#define EMU_HANA_WC_SPDIF_HI 0x28 /* 0xxxxxx 6 bit SPDIF IN Word clock, upper 6 bits */
1108#define EMU_HANA_WC_SPDIF_LO 0x29 /* 0xxxxxx 6 bit SPDIF IN Word clock, lower 6 bits */
1109
1110#define EMU_HANA_WC_ADAT_HI 0x2a /* 0xxxxxx 6 bit ADAT IN Word clock, upper 6 bits */
1111#define EMU_HANA_WC_ADAT_LO 0x2b /* 0xxxxxx 6 bit ADAT IN Word clock, lower 6 bits */
1112
1113#define EMU_HANA_WC_BNC_LO 0x2c /* 0xxxxxx 6 bit BNC IN Word clock, lower 6 bits */
1114#define EMU_HANA_WC_BNC_HI 0x2d /* 0xxxxxx 6 bit BNC IN Word clock, upper 6 bits */
1115
1116#define EMU_HANA2_WC_SPDIF_HI 0x2e /* 0xxxxxx 6 bit HANA2 SPDIF IN Word clock, upper 6 bits */
1117#define EMU_HANA2_WC_SPDIF_LO 0x2f /* 0xxxxxx 6 bit HANA2 SPDIF IN Word clock, lower 6 bits */
1118/* 0x30 - 0x3f Unused Read only registers */
1119
1120/************************************************************************************************/
1121/* EMU1010m HANA Destinations */
1122/************************************************************************************************/
1123#define EMU_DST_ALICE2_EMU32_0 0x000f /* 16 EMU32 channels to Alice2 +0 to +0xf */
1124#define EMU_DST_ALICE2_EMU32_1 0x0000 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1125#define EMU_DST_ALICE2_EMU32_2 0x0001 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1126#define EMU_DST_ALICE2_EMU32_3 0x0002 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1127#define EMU_DST_ALICE2_EMU32_4 0x0003 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1128#define EMU_DST_ALICE2_EMU32_5 0x0004 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1129#define EMU_DST_ALICE2_EMU32_6 0x0005 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1130#define EMU_DST_ALICE2_EMU32_7 0x0006 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1131#define EMU_DST_ALICE2_EMU32_8 0x0007 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1132#define EMU_DST_ALICE2_EMU32_9 0x0008 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1133#define EMU_DST_ALICE2_EMU32_A 0x0009 /* 16 EMU32 channels to Alice2 +0 to +0xf */
1134#define EMU_DST_ALICE2_EMU32_B 0x000a /* 16 EMU32 channels to Alice2 +0 to +0xf */
1135#define EMU_DST_ALICE2_EMU32_C 0x000b /* 16 EMU32 channels to Alice2 +0 to +0xf */
1136#define EMU_DST_ALICE2_EMU32_D 0x000c /* 16 EMU32 channels to Alice2 +0 to +0xf */
1137#define EMU_DST_ALICE2_EMU32_E 0x000d /* 16 EMU32 channels to Alice2 +0 to +0xf */
1138#define EMU_DST_ALICE2_EMU32_F 0x000e /* 16 EMU32 channels to Alice2 +0 to +0xf */
1139#define EMU_DST_DOCK_DAC1_LEFT1 0x0100 /* Audio Dock DAC1 Left, 1st or 48kHz only */
1140#define EMU_DST_DOCK_DAC1_LEFT2 0x0101 /* Audio Dock DAC1 Left, 2nd or 96kHz */
1141#define EMU_DST_DOCK_DAC1_LEFT3 0x0102 /* Audio Dock DAC1 Left, 3rd or 192kHz */
1142#define EMU_DST_DOCK_DAC1_LEFT4 0x0103 /* Audio Dock DAC1 Left, 4th or 192kHz */
1143#define EMU_DST_DOCK_DAC1_RIGHT1 0x0104 /* Audio Dock DAC1 Right, 1st or 48kHz only */
1144#define EMU_DST_DOCK_DAC1_RIGHT2 0x0105 /* Audio Dock DAC1 Right, 2nd or 96kHz */
1145#define EMU_DST_DOCK_DAC1_RIGHT3 0x0106 /* Audio Dock DAC1 Right, 3rd or 192kHz */
1146#define EMU_DST_DOCK_DAC1_RIGHT4 0x0107 /* Audio Dock DAC1 Right, 4th or 192kHz */
1147#define EMU_DST_DOCK_DAC2_LEFT1 0x0108 /* Audio Dock DAC2 Left, 1st or 48kHz only */
1148#define EMU_DST_DOCK_DAC2_LEFT2 0x0109 /* Audio Dock DAC2 Left, 2nd or 96kHz */
1149#define EMU_DST_DOCK_DAC2_LEFT3 0x010a /* Audio Dock DAC2 Left, 3rd or 192kHz */
1150#define EMU_DST_DOCK_DAC2_LEFT4 0x010b /* Audio Dock DAC2 Left, 4th or 192kHz */
1151#define EMU_DST_DOCK_DAC2_RIGHT1 0x010c /* Audio Dock DAC2 Right, 1st or 48kHz only */
1152#define EMU_DST_DOCK_DAC2_RIGHT2 0x010d /* Audio Dock DAC2 Right, 2nd or 96kHz */
1153#define EMU_DST_DOCK_DAC2_RIGHT3 0x010e /* Audio Dock DAC2 Right, 3rd or 192kHz */
1154#define EMU_DST_DOCK_DAC2_RIGHT4 0x010f /* Audio Dock DAC2 Right, 4th or 192kHz */
1155#define EMU_DST_DOCK_DAC3_LEFT1 0x0110 /* Audio Dock DAC1 Left, 1st or 48kHz only */
1156#define EMU_DST_DOCK_DAC3_LEFT2 0x0111 /* Audio Dock DAC1 Left, 2nd or 96kHz */
1157#define EMU_DST_DOCK_DAC3_LEFT3 0x0112 /* Audio Dock DAC1 Left, 3rd or 192kHz */
1158#define EMU_DST_DOCK_DAC3_LEFT4 0x0113 /* Audio Dock DAC1 Left, 4th or 192kHz */
1159#define EMU_DST_DOCK_PHONES_LEFT1 0x0112 /* Audio Dock PHONES Left, 1st or 48kHz only */
1160#define EMU_DST_DOCK_PHONES_LEFT2 0x0113 /* Audio Dock PHONES Left, 2nd or 96kHz */
1161#define EMU_DST_DOCK_DAC3_RIGHT1 0x0114 /* Audio Dock DAC1 Right, 1st or 48kHz only */
1162#define EMU_DST_DOCK_DAC3_RIGHT2 0x0115 /* Audio Dock DAC1 Right, 2nd or 96kHz */
1163#define EMU_DST_DOCK_DAC3_RIGHT3 0x0116 /* Audio Dock DAC1 Right, 3rd or 192kHz */
1164#define EMU_DST_DOCK_DAC3_RIGHT4 0x0117 /* Audio Dock DAC1 Right, 4th or 192kHz */
1165#define EMU_DST_DOCK_PHONES_RIGHT1 0x0116 /* Audio Dock PHONES Right, 1st or 48kHz only */
1166#define EMU_DST_DOCK_PHONES_RIGHT2 0x0117 /* Audio Dock PHONES Right, 2nd or 96kHz */
1167#define EMU_DST_DOCK_DAC4_LEFT1 0x0118 /* Audio Dock DAC2 Left, 1st or 48kHz only */
1168#define EMU_DST_DOCK_DAC4_LEFT2 0x0119 /* Audio Dock DAC2 Left, 2nd or 96kHz */
1169#define EMU_DST_DOCK_DAC4_LEFT3 0x011a /* Audio Dock DAC2 Left, 3rd or 192kHz */
1170#define EMU_DST_DOCK_DAC4_LEFT4 0x011b /* Audio Dock DAC2 Left, 4th or 192kHz */
1171#define EMU_DST_DOCK_SPDIF_LEFT1 0x011a /* Audio Dock SPDIF Left, 1st or 48kHz only */
1172#define EMU_DST_DOCK_SPDIF_LEFT2 0x011b /* Audio Dock SPDIF Left, 2nd or 96kHz */
1173#define EMU_DST_DOCK_DAC4_RIGHT1 0x011c /* Audio Dock DAC2 Right, 1st or 48kHz only */
1174#define EMU_DST_DOCK_DAC4_RIGHT2 0x011d /* Audio Dock DAC2 Right, 2nd or 96kHz */
1175#define EMU_DST_DOCK_DAC4_RIGHT3 0x011e /* Audio Dock DAC2 Right, 3rd or 192kHz */
1176#define EMU_DST_DOCK_DAC4_RIGHT4 0x011f /* Audio Dock DAC2 Right, 4th or 192kHz */
1177#define EMU_DST_DOCK_SPDIF_RIGHT1 0x011e /* Audio Dock SPDIF Right, 1st or 48kHz only */
1178#define EMU_DST_DOCK_SPDIF_RIGHT2 0x011f /* Audio Dock SPDIF Right, 2nd or 96kHz */
1179#define EMU_DST_HANA_SPDIF_LEFT1 0x0200 /* Hana SPDIF Left, 1st or 48kHz only */
1180#define EMU_DST_HANA_SPDIF_LEFT2 0x0202 /* Hana SPDIF Left, 2nd or 96kHz */
1181#define EMU_DST_HANA_SPDIF_RIGHT1 0x0201 /* Hana SPDIF Right, 1st or 48kHz only */
1182#define EMU_DST_HANA_SPDIF_RIGHT2 0x0203 /* Hana SPDIF Right, 2nd or 96kHz */
1183#define EMU_DST_HAMOA_DAC_LEFT1 0x0300 /* Hamoa DAC Left, 1st or 48kHz only */
1184#define EMU_DST_HAMOA_DAC_LEFT2 0x0302 /* Hamoa DAC Left, 2nd or 96kHz */
1185#define EMU_DST_HAMOA_DAC_LEFT3 0x0304 /* Hamoa DAC Left, 3rd or 192kHz */
1186#define EMU_DST_HAMOA_DAC_LEFT4 0x0306 /* Hamoa DAC Left, 4th or 192kHz */
1187#define EMU_DST_HAMOA_DAC_RIGHT1 0x0301 /* Hamoa DAC Right, 1st or 48kHz only */
1188#define EMU_DST_HAMOA_DAC_RIGHT2 0x0303 /* Hamoa DAC Right, 2nd or 96kHz */
1189#define EMU_DST_HAMOA_DAC_RIGHT3 0x0305 /* Hamoa DAC Right, 3rd or 192kHz */
1190#define EMU_DST_HAMOA_DAC_RIGHT4 0x0307 /* Hamoa DAC Right, 4th or 192kHz */
1191#define EMU_DST_HANA_ADAT 0x0400 /* Hana ADAT 8 channel out +0 to +7 */
1192#define EMU_DST_ALICE_I2S0_LEFT 0x0500 /* Alice2 I2S0 Left */
1193#define EMU_DST_ALICE_I2S0_RIGHT 0x0501 /* Alice2 I2S0 Right */
1194#define EMU_DST_ALICE_I2S1_LEFT 0x0600 /* Alice2 I2S1 Left */
1195#define EMU_DST_ALICE_I2S1_RIGHT 0x0601 /* Alice2 I2S1 Right */
1196#define EMU_DST_ALICE_I2S2_LEFT 0x0700 /* Alice2 I2S2 Left */
1197#define EMU_DST_ALICE_I2S2_RIGHT 0x0701 /* Alice2 I2S2 Right */
1198
1199/************************************************************************************************/
1200/* EMU1010m HANA Sources */
1201/************************************************************************************************/
1202#define EMU_SRC_SILENCE 0x0000 /* Silence */
1203#define EMU_SRC_DOCK_MIC_A1 0x0100 /* Audio Dock Mic A, 1st or 48kHz only */
1204#define EMU_SRC_DOCK_MIC_A2 0x0101 /* Audio Dock Mic A, 2nd or 96kHz */
1205#define EMU_SRC_DOCK_MIC_A3 0x0102 /* Audio Dock Mic A, 3rd or 192kHz */
1206#define EMU_SRC_DOCK_MIC_A4 0x0103 /* Audio Dock Mic A, 4th or 192kHz */
1207#define EMU_SRC_DOCK_MIC_B1 0x0104 /* Audio Dock Mic B, 1st or 48kHz only */
1208#define EMU_SRC_DOCK_MIC_B2 0x0105 /* Audio Dock Mic B, 2nd or 96kHz */
1209#define EMU_SRC_DOCK_MIC_B3 0x0106 /* Audio Dock Mic B, 3rd or 192kHz */
1210#define EMU_SRC_DOCK_MIC_B4 0x0107 /* Audio Dock Mic B, 4th or 192kHz */
1211#define EMU_SRC_DOCK_ADC1_LEFT1 0x0108 /* Audio Dock ADC1 Left, 1st or 48kHz only */
1212#define EMU_SRC_DOCK_ADC1_LEFT2 0x0109 /* Audio Dock ADC1 Left, 2nd or 96kHz */
1213#define EMU_SRC_DOCK_ADC1_LEFT3 0x010a /* Audio Dock ADC1 Left, 3rd or 192kHz */
1214#define EMU_SRC_DOCK_ADC1_LEFT4 0x010b /* Audio Dock ADC1 Left, 4th or 192kHz */
1215#define EMU_SRC_DOCK_ADC1_RIGHT1 0x010c /* Audio Dock ADC1 Right, 1st or 48kHz only */
1216#define EMU_SRC_DOCK_ADC1_RIGHT2 0x010d /* Audio Dock ADC1 Right, 2nd or 96kHz */
1217#define EMU_SRC_DOCK_ADC1_RIGHT3 0x010e /* Audio Dock ADC1 Right, 3rd or 192kHz */
1218#define EMU_SRC_DOCK_ADC1_RIGHT4 0x010f /* Audio Dock ADC1 Right, 4th or 192kHz */
1219#define EMU_SRC_DOCK_ADC2_LEFT1 0x0110 /* Audio Dock ADC2 Left, 1st or 48kHz only */
1220#define EMU_SRC_DOCK_ADC2_LEFT2 0x0111 /* Audio Dock ADC2 Left, 2nd or 96kHz */
1221#define EMU_SRC_DOCK_ADC2_LEFT3 0x0112 /* Audio Dock ADC2 Left, 3rd or 192kHz */
1222#define EMU_SRC_DOCK_ADC2_LEFT4 0x0113 /* Audio Dock ADC2 Left, 4th or 192kHz */
1223#define EMU_SRC_DOCK_ADC2_RIGHT1 0x0114 /* Audio Dock ADC2 Right, 1st or 48kHz only */
1224#define EMU_SRC_DOCK_ADC2_RIGHT2 0x0115 /* Audio Dock ADC2 Right, 2nd or 96kHz */
1225#define EMU_SRC_DOCK_ADC2_RIGHT3 0x0116 /* Audio Dock ADC2 Right, 3rd or 192kHz */
1226#define EMU_SRC_DOCK_ADC2_RIGHT4 0x0117 /* Audio Dock ADC2 Right, 4th or 192kHz */
1227#define EMU_SRC_DOCK_ADC3_LEFT1 0x0118 /* Audio Dock ADC3 Left, 1st or 48kHz only */
1228#define EMU_SRC_DOCK_ADC3_LEFT2 0x0119 /* Audio Dock ADC3 Left, 2nd or 96kHz */
1229#define EMU_SRC_DOCK_ADC3_LEFT3 0x011a /* Audio Dock ADC3 Left, 3rd or 192kHz */
1230#define EMU_SRC_DOCK_ADC3_LEFT4 0x011b /* Audio Dock ADC3 Left, 4th or 192kHz */
1231#define EMU_SRC_DOCK_ADC3_RIGHT1 0x011c /* Audio Dock ADC3 Right, 1st or 48kHz only */
1232#define EMU_SRC_DOCK_ADC3_RIGHT2 0x011d /* Audio Dock ADC3 Right, 2nd or 96kHz */
1233#define EMU_SRC_DOCK_ADC3_RIGHT3 0x011e /* Audio Dock ADC3 Right, 3rd or 192kHz */
1234#define EMU_SRC_DOCK_ADC3_RIGHT4 0x011f /* Audio Dock ADC3 Right, 4th or 192kHz */
1235#define EMU_SRC_HAMOA_ADC_LEFT1 0x0200 /* Hamoa ADC Left, 1st or 48kHz only */
1236#define EMU_SRC_HAMOA_ADC_LEFT2 0x0202 /* Hamoa ADC Left, 2nd or 96kHz */
1237#define EMU_SRC_HAMOA_ADC_LEFT3 0x0204 /* Hamoa ADC Left, 3rd or 192kHz */
1238#define EMU_SRC_HAMOA_ADC_LEFT4 0x0206 /* Hamoa ADC Left, 4th or 192kHz */
1239#define EMU_SRC_HAMOA_ADC_RIGHT1 0x0201 /* Hamoa ADC Right, 1st or 48kHz only */
1240#define EMU_SRC_HAMOA_ADC_RIGHT2 0x0203 /* Hamoa ADC Right, 2nd or 96kHz */
1241#define EMU_SRC_HAMOA_ADC_RIGHT3 0x0205 /* Hamoa ADC Right, 3rd or 192kHz */
1242#define EMU_SRC_HAMOA_ADC_RIGHT4 0x0207 /* Hamoa ADC Right, 4th or 192kHz */
1243#define EMU_SRC_ALICE_EMU32A 0x0300 /* Alice2 EMU32a 16 outputs. +0 to +0xf */
1244#define EMU_SRC_ALICE_EMU32B 0x0310 /* Alice2 EMU32b 16 outputs. +0 to +0xf */
1245#define EMU_SRC_HANA_ADAT 0x0400 /* Hana ADAT 8 channel in +0 to +7 */
1246#define EMU_SRC_HANA_SPDIF_LEFT1 0x0500 /* Hana SPDIF Left, 1st or 48kHz only */
1247#define EMU_SRC_HANA_SPDIF_LEFT2 0x0502 /* Hana SPDIF Left, 2nd or 96kHz */
1248#define EMU_SRC_HANA_SPDIF_RIGHT1 0x0501 /* Hana SPDIF Right, 1st or 48kHz only */
1249#define EMU_SRC_HANA_SPDIF_RIGHT2 0x0503 /* Hana SPDIF Right, 2nd or 96kHz */
1250/* 0x600 and 0x700 no used */
889 1251
890/* ------------------- STRUCTURES -------------------- */ 1252/* ------------------- STRUCTURES -------------------- */
891 1253
@@ -1063,7 +1425,7 @@ struct snd_emu_chip_details {
1063 unsigned char spdif_bug; /* Has Spdif phasing bug */ 1425 unsigned char spdif_bug; /* Has Spdif phasing bug */
1064 unsigned char ac97_chip; /* Has an AC97 chip: 1 = mandatory, 2 = optional */ 1426 unsigned char ac97_chip; /* Has an AC97 chip: 1 = mandatory, 2 = optional */
1065 unsigned char ecard; /* APS EEPROM */ 1427 unsigned char ecard; /* APS EEPROM */
1066 unsigned char emu1212m; /* EMU 1212m card */ 1428 unsigned char emu1010; /* EMU 1010m card */
1067 unsigned char spi_dac; /* SPI interface for DAC */ 1429 unsigned char spi_dac; /* SPI interface for DAC */
1068 unsigned char i2c_adc; /* I2C interface for ADC */ 1430 unsigned char i2c_adc; /* I2C interface for ADC */
1069 unsigned char adc_1361t; /* Use Philips 1361T ADC */ 1431 unsigned char adc_1361t; /* Use Philips 1361T ADC */
@@ -1072,6 +1434,14 @@ struct snd_emu_chip_details {
1072 const char *id; /* for backward compatibility - can be NULL if not needed */ 1434 const char *id; /* for backward compatibility - can be NULL if not needed */
1073}; 1435};
1074 1436
1437struct snd_emu1010 {
1438 unsigned int output_source[64];
1439 unsigned int input_source[64];
1440 unsigned int adc_pads; /* bit mask */
1441 unsigned int dac_pads; /* bit mask */
1442 unsigned int internal_clock; /* 44100 or 48000 */
1443};
1444
1075struct snd_emu10k1 { 1445struct snd_emu10k1 {
1076 int irq; 1446 int irq;
1077 1447
@@ -1079,6 +1449,7 @@ struct snd_emu10k1 {
1079 unsigned int tos_link: 1, /* tos link detected */ 1449 unsigned int tos_link: 1, /* tos link detected */
1080 rear_ac97: 1, /* rear channels are on AC'97 */ 1450 rear_ac97: 1, /* rear channels are on AC'97 */
1081 enable_ir: 1; 1451 enable_ir: 1;
1452 unsigned int support_tlv :1;
1082 /* Contains profile of card capabilities */ 1453 /* Contains profile of card capabilities */
1083 const struct snd_emu_chip_details *card_capabilities; 1454 const struct snd_emu_chip_details *card_capabilities;
1084 unsigned int audigy; /* is Audigy? */ 1455 unsigned int audigy; /* is Audigy? */
@@ -1104,6 +1475,8 @@ struct snd_emu10k1 {
1104 spinlock_t memblk_lock; 1475 spinlock_t memblk_lock;
1105 1476
1106 unsigned int spdif_bits[3]; /* s/pdif out setup */ 1477 unsigned int spdif_bits[3]; /* s/pdif out setup */
1478 unsigned int i2c_capture_source;
1479 u8 i2c_capture_volume[4][2];
1107 1480
1108 struct snd_emu10k1_fx8010 fx8010; /* FX8010 info */ 1481 struct snd_emu10k1_fx8010 fx8010; /* FX8010 info */
1109 int gpr_base; 1482 int gpr_base;
@@ -1132,6 +1505,7 @@ struct snd_emu10k1 {
1132 int p16v_device_offset; 1505 int p16v_device_offset;
1133 u32 p16v_capture_source; 1506 u32 p16v_capture_source;
1134 u32 p16v_capture_channel; 1507 u32 p16v_capture_channel;
1508 struct snd_emu1010 emu1010;
1135 struct snd_emu10k1_pcm_mixer pcm_mixer[32]; 1509 struct snd_emu10k1_pcm_mixer pcm_mixer[32];
1136 struct snd_emu10k1_pcm_mixer efx_pcm_mixer[NUM_EFX_PLAYBACK]; 1510 struct snd_emu10k1_pcm_mixer efx_pcm_mixer[NUM_EFX_PLAYBACK];
1137 struct snd_kcontrol *ctl_send_routing; 1511 struct snd_kcontrol *ctl_send_routing;
@@ -1208,6 +1582,10 @@ void snd_emu10k1_ptr_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned i
1208unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn); 1582unsigned int snd_emu10k1_ptr20_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn);
1209void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data); 1583void snd_emu10k1_ptr20_write(struct snd_emu10k1 *emu, unsigned int reg, unsigned int chn, unsigned int data);
1210int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data); 1584int snd_emu10k1_spi_write(struct snd_emu10k1 * emu, unsigned int data);
1585int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu, u32 reg, u32 value);
1586int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value);
1587int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value);
1588int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src);
1211unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc); 1589unsigned int snd_emu10k1_efx_read(struct snd_emu10k1 *emu, unsigned int pc);
1212void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb); 1590void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb);
1213void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb); 1591void snd_emu10k1_intr_disable(struct snd_emu10k1 *emu, unsigned int intrenb);
@@ -1524,11 +1902,20 @@ struct snd_emu10k1_fx8010_control_gpr {
1524 unsigned int value[32]; /* initial values */ 1902 unsigned int value[32]; /* initial values */
1525 unsigned int min; /* minimum range */ 1903 unsigned int min; /* minimum range */
1526 unsigned int max; /* maximum range */ 1904 unsigned int max; /* maximum range */
1527 union {
1528 snd_kcontrol_tlv_rw_t *c;
1529 unsigned int *p;
1530 } tlv;
1531 unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */ 1905 unsigned int translation; /* translation type (EMU10K1_GPR_TRANSLATION*) */
1906 const unsigned int *tlv;
1907};
1908
1909/* old ABI without TLV support */
1910struct snd_emu10k1_fx8010_control_old_gpr {
1911 struct snd_ctl_elem_id id;
1912 unsigned int vcount;
1913 unsigned int count;
1914 unsigned short gpr[32];
1915 unsigned int value[32];
1916 unsigned int min;
1917 unsigned int max;
1918 unsigned int translation;
1532}; 1919};
1533 1920
1534struct snd_emu10k1_fx8010_code { 1921struct snd_emu10k1_fx8010_code {
@@ -1579,6 +1966,8 @@ struct snd_emu10k1_fx8010_pcm_rec {
1579 unsigned int res2; /* reserved */ 1966 unsigned int res2; /* reserved */
1580}; 1967};
1581 1968
1969#define SNDRV_EMU10K1_VERSION SNDRV_PROTOCOL_VERSION(1, 0, 1)
1970
1582#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info) 1971#define SNDRV_EMU10K1_IOCTL_INFO _IOR ('H', 0x10, struct snd_emu10k1_fx8010_info)
1583#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code) 1972#define SNDRV_EMU10K1_IOCTL_CODE_POKE _IOW ('H', 0x11, struct snd_emu10k1_fx8010_code)
1584#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code) 1973#define SNDRV_EMU10K1_IOCTL_CODE_PEEK _IOWR('H', 0x12, struct snd_emu10k1_fx8010_code)
@@ -1587,6 +1976,7 @@ struct snd_emu10k1_fx8010_pcm_rec {
1587#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram) 1976#define SNDRV_EMU10K1_IOCTL_TRAM_PEEK _IOWR('H', 0x22, struct snd_emu10k1_fx8010_tram)
1588#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec) 1977#define SNDRV_EMU10K1_IOCTL_PCM_POKE _IOW ('H', 0x30, struct snd_emu10k1_fx8010_pcm_rec)
1589#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec) 1978#define SNDRV_EMU10K1_IOCTL_PCM_PEEK _IOWR('H', 0x31, struct snd_emu10k1_fx8010_pcm_rec)
1979#define SNDRV_EMU10K1_IOCTL_PVERSION _IOR ('H', 0x40, int)
1590#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80) 1980#define SNDRV_EMU10K1_IOCTL_STOP _IO ('H', 0x80)
1591#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81) 1981#define SNDRV_EMU10K1_IOCTL_CONTINUE _IO ('H', 0x81)
1592#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82) 1982#define SNDRV_EMU10K1_IOCTL_ZERO_TRAM_COUNTER _IO ('H', 0x82)
diff --git a/include/sound/pcm.h b/include/sound/pcm.h
index 2f645dfd7f70..ee6bc2d06803 100644
--- a/include/sound/pcm.h
+++ b/include/sound/pcm.h
@@ -56,6 +56,8 @@ struct snd_pcm_hardware {
56 size_t fifo_size; /* fifo size in bytes */ 56 size_t fifo_size; /* fifo size in bytes */
57}; 57};
58 58
59struct snd_pcm_substream;
60
59struct snd_pcm_ops { 61struct snd_pcm_ops {
60 int (*open)(struct snd_pcm_substream *substream); 62 int (*open)(struct snd_pcm_substream *substream);
61 int (*close)(struct snd_pcm_substream *substream); 63 int (*close)(struct snd_pcm_substream *substream);
@@ -384,6 +386,7 @@ struct snd_pcm_substream {
384 struct snd_info_entry *proc_sw_params_entry; 386 struct snd_info_entry *proc_sw_params_entry;
385 struct snd_info_entry *proc_status_entry; 387 struct snd_info_entry *proc_status_entry;
386 struct snd_info_entry *proc_prealloc_entry; 388 struct snd_info_entry *proc_prealloc_entry;
389 struct snd_info_entry *proc_prealloc_max_entry;
387#endif 390#endif
388 /* misc flags */ 391 /* misc flags */
389 unsigned int hw_opened: 1; 392 unsigned int hw_opened: 1;
@@ -427,6 +430,7 @@ struct snd_pcm {
427 wait_queue_head_t open_wait; 430 wait_queue_head_t open_wait;
428 void *private_data; 431 void *private_data;
429 void (*private_free) (struct snd_pcm *pcm); 432 void (*private_free) (struct snd_pcm *pcm);
433 struct device *dev; /* actual hw device this belongs to */
430#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE) 434#if defined(CONFIG_SND_PCM_OSS) || defined(CONFIG_SND_PCM_OSS_MODULE)
431 struct snd_pcm_oss oss; 435 struct snd_pcm_oss oss;
432#endif 436#endif
diff --git a/include/sound/pt2258.h b/include/sound/pt2258.h
new file mode 100644
index 000000000000..160f812faa42
--- /dev/null
+++ b/include/sound/pt2258.h
@@ -0,0 +1,37 @@
1/*
2 * ALSA Driver for the PT2258 volume controller.
3 *
4 * Copyright (c) 2006 Jochen Voss <voss@seehuhn.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#ifndef __SOUND_PT2258_H
23#define __SOUND_PT2258_H
24
25struct snd_pt2258 {
26 struct snd_card *card;
27 struct snd_i2c_bus *i2c_bus;
28 struct snd_i2c_device *i2c_dev;
29
30 unsigned char volume[6];
31 int mute;
32};
33
34extern int snd_pt2258_reset(struct snd_pt2258 *pt);
35extern int snd_pt2258_build_controls(struct snd_pt2258 *pt);
36
37#endif /* __SOUND_PT2258_H */
diff --git a/include/sound/sb16_csp.h b/include/sound/sb16_csp.h
index caf6fe21514d..736eac71d053 100644
--- a/include/sound/sb16_csp.h
+++ b/include/sound/sb16_csp.h
@@ -114,9 +114,21 @@ struct snd_sb_csp_info {
114#ifdef __KERNEL__ 114#ifdef __KERNEL__
115#include "sb.h" 115#include "sb.h"
116#include "hwdep.h" 116#include "hwdep.h"
117#include <linux/firmware.h>
117 118
118struct snd_sb_csp; 119struct snd_sb_csp;
119 120
121/* indices for the known CSP programs */
122enum {
123 CSP_PROGRAM_MULAW,
124 CSP_PROGRAM_ALAW,
125 CSP_PROGRAM_ADPCM_INIT,
126 CSP_PROGRAM_ADPCM_PLAYBACK,
127 CSP_PROGRAM_ADPCM_CAPTURE,
128
129 CSP_PROGRAM_COUNT
130};
131
120/* 132/*
121 * CSP operators 133 * CSP operators
122 */ 134 */
@@ -159,6 +171,8 @@ struct snd_sb_csp {
159 struct snd_kcontrol *qsound_space; 171 struct snd_kcontrol *qsound_space;
160 172
161 struct mutex access_mutex; /* locking */ 173 struct mutex access_mutex; /* locking */
174
175 const struct firmware *csp_programs[CSP_PROGRAM_COUNT];
162}; 176};
163 177
164int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep); 178int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep);
diff --git a/include/sound/snd_wavefront.h b/include/sound/snd_wavefront.h
index 0b9e5de94ff1..9688d4be918e 100644
--- a/include/sound/snd_wavefront.h
+++ b/include/sound/snd_wavefront.h
@@ -85,6 +85,7 @@ struct _snd_wavefront {
85 char hw_version[2]; /* major = [0], minor = [1] */ 85 char hw_version[2]; /* major = [0], minor = [1] */
86 char israw; /* needs Motorola microcode */ 86 char israw; /* needs Motorola microcode */
87 char has_fx; /* has FX processor (Tropez+) */ 87 char has_fx; /* has FX processor (Tropez+) */
88 char fx_initialized; /* FX's register pages initialized */
88 char prog_status[WF_MAX_PROGRAM]; /* WF_SLOT_* */ 89 char prog_status[WF_MAX_PROGRAM]; /* WF_SLOT_* */
89 char patch_status[WF_MAX_PATCH]; /* WF_SLOT_* */ 90 char patch_status[WF_MAX_PATCH]; /* WF_SLOT_* */
90 char sample_status[WF_MAX_SAMPLE]; /* WF_ST_* | WF_SLOT_* */ 91 char sample_status[WF_MAX_SAMPLE]; /* WF_ST_* | WF_SLOT_* */
@@ -94,6 +95,7 @@ struct _snd_wavefront {
94 spinlock_t irq_lock; 95 spinlock_t irq_lock;
95 wait_queue_head_t interrupt_sleeper; 96 wait_queue_head_t interrupt_sleeper;
96 snd_wavefront_midi_t midi; /* ICS2115 MIDI interface */ 97 snd_wavefront_midi_t midi; /* ICS2115 MIDI interface */
98 struct snd_card *card;
97}; 99};
98 100
99struct _snd_wavefront_card { 101struct _snd_wavefront_card {
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
new file mode 100644
index 000000000000..2b1ae8edc43c
--- /dev/null
+++ b/include/sound/soc-dapm.h
@@ -0,0 +1,286 @@
1/*
2 * linux/sound/soc-dapm.h -- ALSA SoC Dynamic Audio Power Management
3 *
4 * Author: Liam Girdwood
5 * Created: Aug 11th 2005
6 * Copyright: Wolfson Microelectronics. PLC.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __LINUX_SND_SOC_DAPM_H
14#define __LINUX_SND_SOC_DAPM_H
15
16#include <linux/device.h>
17#include <linux/types.h>
18#include <sound/control.h>
19#include <sound/soc.h>
20
21/* widget has no PM register bit */
22#define SND_SOC_NOPM -1
23
24/*
25 * SoC dynamic audio power managment
26 *
27 * We can have upto 4 power domains
28 * 1. Codec domain - VREF, VMID
29 * Usually controlled at codec probe/remove, although can be set
30 * at stream time if power is not needed for sidetone, etc.
31 * 2. Platform/Machine domain - physically connected inputs and outputs
32 * Is platform/machine and user action specific, is set in the machine
33 * driver and by userspace e.g when HP are inserted
34 * 3. Path domain - Internal codec path mixers
35 * Are automatically set when mixer and mux settings are
36 * changed by the user.
37 * 4. Stream domain - DAC's and ADC's.
38 * Enabled when stream playback/capture is started.
39 */
40
41/* codec domain */
42#define SND_SOC_DAPM_VMID(wname) \
43{ .id = snd_soc_dapm_vmid, .name = wname, .kcontrols = NULL, \
44 .num_kcontrols = 0}
45
46/* platform domain */
47#define SND_SOC_DAPM_INPUT(wname) \
48{ .id = snd_soc_dapm_input, .name = wname, .kcontrols = NULL, \
49 .num_kcontrols = 0}
50#define SND_SOC_DAPM_OUTPUT(wname) \
51{ .id = snd_soc_dapm_output, .name = wname, .kcontrols = NULL, \
52 .num_kcontrols = 0}
53#define SND_SOC_DAPM_MIC(wname, wevent) \
54{ .id = snd_soc_dapm_mic, .name = wname, .kcontrols = NULL, \
55 .num_kcontrols = 0, .event = wevent, \
56 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD}
57#define SND_SOC_DAPM_HP(wname, wevent) \
58{ .id = snd_soc_dapm_hp, .name = wname, .kcontrols = NULL, \
59 .num_kcontrols = 0, .event = wevent, \
60 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
61#define SND_SOC_DAPM_SPK(wname, wevent) \
62{ .id = snd_soc_dapm_spk, .name = wname, .kcontrols = NULL, \
63 .num_kcontrols = 0, .event = wevent, \
64 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
65#define SND_SOC_DAPM_LINE(wname, wevent) \
66{ .id = snd_soc_dapm_line, .name = wname, .kcontrols = NULL, \
67 .num_kcontrols = 0, .event = wevent, \
68 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD}
69
70/* path domain */
71#define SND_SOC_DAPM_PGA(wname, wreg, wshift, winvert,\
72 wcontrols, wncontrols) \
73{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
74 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
75#define SND_SOC_DAPM_MIXER(wname, wreg, wshift, winvert, \
76 wcontrols, wncontrols)\
77{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
78 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols}
79#define SND_SOC_DAPM_MICBIAS(wname, wreg, wshift, winvert) \
80{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
81 .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0}
82#define SND_SOC_DAPM_SWITCH(wname, wreg, wshift, winvert, wcontrols) \
83{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
84 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
85#define SND_SOC_DAPM_MUX(wname, wreg, wshift, winvert, wcontrols) \
86{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
87 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1}
88
89/* path domain with event - event handler must return 0 for success */
90#define SND_SOC_DAPM_PGA_E(wname, wreg, wshift, winvert, wcontrols, \
91 wncontrols, wevent, wflags) \
92{ .id = snd_soc_dapm_pga, .name = wname, .reg = wreg, .shift = wshift, \
93 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
94 .event = wevent, .event_flags = wflags}
95#define SND_SOC_DAPM_MIXER_E(wname, wreg, wshift, winvert, wcontrols, \
96 wncontrols, wevent, wflags) \
97{ .id = snd_soc_dapm_mixer, .name = wname, .reg = wreg, .shift = wshift, \
98 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = wncontrols, \
99 .event = wevent, .event_flags = wflags}
100#define SND_SOC_DAPM_MICBIAS_E(wname, wreg, wshift, winvert, wevent, wflags) \
101{ .id = snd_soc_dapm_micbias, .name = wname, .reg = wreg, .shift = wshift, \
102 .invert = winvert, .kcontrols = NULL, .num_kcontrols = 0, \
103 .event = wevent, .event_flags = wflags}
104#define SND_SOC_DAPM_SWITCH_E(wname, wreg, wshift, winvert, wcontrols, \
105 wevent, wflags) \
106{ .id = snd_soc_dapm_switch, .name = wname, .reg = wreg, .shift = wshift, \
107 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1 \
108 .event = wevent, .event_flags = wflags}
109#define SND_SOC_DAPM_MUX_E(wname, wreg, wshift, winvert, wcontrols, \
110 wevent, wflags) \
111{ .id = snd_soc_dapm_mux, .name = wname, .reg = wreg, .shift = wshift, \
112 .invert = winvert, .kcontrols = wcontrols, .num_kcontrols = 1, \
113 .event = wevent, .event_flags = wflags}
114
115/* events that are pre and post DAPM */
116#define SND_SOC_DAPM_PRE(wname, wevent) \
117{ .id = snd_soc_dapm_pre, .name = wname, .kcontrols = NULL, \
118 .num_kcontrols = 0, .event = wevent, \
119 .event_flags = SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_PRE_PMD}
120#define SND_SOC_DAPM_POST(wname, wevent) \
121{ .id = snd_soc_dapm_post, .name = wname, .kcontrols = NULL, \
122 .num_kcontrols = 0, .event = wevent, \
123 .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD}
124
125/* stream domain */
126#define SND_SOC_DAPM_DAC(wname, stname, wreg, wshift, winvert) \
127{ .id = snd_soc_dapm_dac, .name = wname, .sname = stname, .reg = wreg, \
128 .shift = wshift, .invert = winvert}
129#define SND_SOC_DAPM_ADC(wname, stname, wreg, wshift, winvert) \
130{ .id = snd_soc_dapm_adc, .name = wname, .sname = stname, .reg = wreg, \
131 .shift = wshift, .invert = winvert}
132
133/* dapm kcontrol types */
134#define SOC_DAPM_SINGLE(xname, reg, shift, mask, invert) \
135{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
136 .info = snd_soc_info_volsw, \
137 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
138 .private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) }
139#define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, mask, invert, \
140 power) \
141{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
142 .info = snd_soc_info_volsw, \
143 .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \
144 .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\
145 ((mask) << 16) | ((invert) << 24) }
146#define SOC_DAPM_ENUM(xname, xenum) \
147{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
148 .info = snd_soc_info_enum_double, \
149 .get = snd_soc_dapm_get_enum_double, \
150 .put = snd_soc_dapm_put_enum_double, \
151 .private_value = (unsigned long)&xenum }
152
153/* dapm stream operations */
154#define SND_SOC_DAPM_STREAM_NOP 0x0
155#define SND_SOC_DAPM_STREAM_START 0x1
156#define SND_SOC_DAPM_STREAM_STOP 0x2
157#define SND_SOC_DAPM_STREAM_SUSPEND 0x4
158#define SND_SOC_DAPM_STREAM_RESUME 0x8
159#define SND_SOC_DAPM_STREAM_PAUSE_PUSH 0x10
160#define SND_SOC_DAPM_STREAM_PAUSE_RELEASE 0x20
161
162/* dapm event types */
163#define SND_SOC_DAPM_PRE_PMU 0x1 /* before widget power up */
164#define SND_SOC_DAPM_POST_PMU 0x2 /* after widget power up */
165#define SND_SOC_DAPM_PRE_PMD 0x4 /* before widget power down */
166#define SND_SOC_DAPM_POST_PMD 0x8 /* after widget power down */
167#define SND_SOC_DAPM_PRE_REG 0x10 /* before audio path setup */
168#define SND_SOC_DAPM_POST_REG 0x20 /* after audio path setup */
169
170/* convenience event type detection */
171#define SND_SOC_DAPM_EVENT_ON(e) \
172 (e & (SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU))
173#define SND_SOC_DAPM_EVENT_OFF(e) \
174 (e & (SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMD))
175
176struct snd_soc_dapm_widget;
177enum snd_soc_dapm_type;
178struct snd_soc_dapm_path;
179struct snd_soc_dapm_pin;
180
181/* dapm controls */
182int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
183 struct snd_ctl_elem_value *ucontrol);
184int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
185 struct snd_ctl_elem_value *ucontrol);
186int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
187 struct snd_ctl_elem_value *ucontrol);
188int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
189 struct snd_ctl_elem_value *ucontrol);
190int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
191 const struct snd_soc_dapm_widget *widget);
192
193/* dapm path setup */
194int snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
195 const char *sink_name, const char *control_name, const char *src_name);
196int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
197void snd_soc_dapm_free(struct snd_soc_device *socdev);
198
199/* dapm events */
200int snd_soc_dapm_stream_event(struct snd_soc_codec *codec, char *stream,
201 int event);
202
203/* dapm sys fs - used by the core */
204int snd_soc_dapm_sys_add(struct device *dev);
205
206/* dapm audio endpoint control */
207int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
208 char *pin, int status);
209int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec);
210
211/* dapm widget types */
212enum snd_soc_dapm_type {
213 snd_soc_dapm_input = 0, /* input pin */
214 snd_soc_dapm_output, /* output pin */
215 snd_soc_dapm_mux, /* selects 1 analog signal from many inputs */
216 snd_soc_dapm_mixer, /* mixes several analog signals together */
217 snd_soc_dapm_pga, /* programmable gain/attenuation (volume) */
218 snd_soc_dapm_adc, /* analog to digital converter */
219 snd_soc_dapm_dac, /* digital to analog converter */
220 snd_soc_dapm_micbias, /* microphone bias (power) */
221 snd_soc_dapm_mic, /* microphone */
222 snd_soc_dapm_hp, /* headphones */
223 snd_soc_dapm_spk, /* speaker */
224 snd_soc_dapm_line, /* line input/output */
225 snd_soc_dapm_switch, /* analog switch */
226 snd_soc_dapm_vmid, /* codec bias/vmid - to minimise pops */
227 snd_soc_dapm_pre, /* machine specific pre widget - exec first */
228 snd_soc_dapm_post, /* machine specific post widget - exec last */
229};
230
231/* dapm audio path between two widgets */
232struct snd_soc_dapm_path {
233 char *name;
234 char *long_name;
235
236 /* source (input) and sink (output) widgets */
237 struct snd_soc_dapm_widget *source;
238 struct snd_soc_dapm_widget *sink;
239 struct snd_kcontrol *kcontrol;
240
241 /* status */
242 u32 connect:1; /* source and sink widgets are connected */
243 u32 walked:1; /* path has been walked */
244
245 struct list_head list_source;
246 struct list_head list_sink;
247 struct list_head list;
248};
249
250/* dapm widget */
251struct snd_soc_dapm_widget {
252 enum snd_soc_dapm_type id;
253 char *name; /* widget name */
254 char *sname; /* stream name */
255 struct snd_soc_codec *codec;
256 struct list_head list;
257
258 /* dapm control */
259 short reg; /* negative reg = no direct dapm */
260 unsigned char shift; /* bits to shift */
261 unsigned int saved_value; /* widget saved value */
262 unsigned int value; /* widget current value */
263 unsigned char power:1; /* block power status */
264 unsigned char invert:1; /* invert the power bit */
265 unsigned char active:1; /* active stream on DAC, ADC's */
266 unsigned char connected:1; /* connected codec pin */
267 unsigned char new:1; /* cnew complete */
268 unsigned char ext:1; /* has external widgets */
269 unsigned char muted:1; /* muted for pop reduction */
270 unsigned char suspend:1; /* was active before suspend */
271 unsigned char pmdown:1; /* waiting for timeout */
272
273 /* external events */
274 unsigned short event_flags; /* flags to specify event types */
275 int (*event)(struct snd_soc_dapm_widget*, int);
276
277 /* kcontrols that relate to this widget */
278 int num_kcontrols;
279 const struct snd_kcontrol_new *kcontrols;
280
281 /* widget input and outputs */
282 struct list_head sources;
283 struct list_head sinks;
284};
285
286#endif
diff --git a/include/sound/soc.h b/include/sound/soc.h
new file mode 100644
index 000000000000..b1dc364b8f74
--- /dev/null
+++ b/include/sound/soc.h
@@ -0,0 +1,461 @@
1/*
2 * linux/sound/soc.h -- ALSA SoC Layer
3 *
4 * Author: Liam Girdwood
5 * Created: Aug 11th 2005
6 * Copyright: Wolfson Microelectronics. PLC.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __LINUX_SND_SOC_H
14#define __LINUX_SND_SOC_H
15
16#include <linux/platform_device.h>
17#include <linux/types.h>
18#include <linux/workqueue.h>
19#include <sound/driver.h>
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/control.h>
23#include <sound/ac97_codec.h>
24
25#define SND_SOC_VERSION "0.13.0"
26
27/*
28 * Convenience kcontrol builders
29 */
30#define SOC_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) |\
31 ((shift) << 12) | ((mask) << 16) | ((invert) << 24))
32#define SOC_SINGLE_VALUE_EXT(reg,mask,invert) ((reg) | ((mask) << 16) |\
33 ((invert) << 31))
34#define SOC_SINGLE(xname, reg, shift, mask, invert) \
35{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
36 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\
37 .put = snd_soc_put_volsw, \
38 .private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) }
39#define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \
40{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
41 .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
42 .put = snd_soc_put_volsw, \
43 .private_value = (reg) | ((shift_left) << 8) | \
44 ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) }
45#define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert) \
46{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \
47 .info = snd_soc_info_volsw_2r, \
48 .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \
49 .private_value = (reg_left) | ((shift) << 8) | \
50 ((mask) << 12) | ((invert) << 20) | ((reg_right) << 24) }
51#define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \
52{ .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \
53 .mask = xmask, .texts = xtexts }
54#define SOC_ENUM_SINGLE(xreg, xshift, xmask, xtexts) \
55 SOC_ENUM_DOUBLE(xreg, xshift, xshift, xmask, xtexts)
56#define SOC_ENUM_SINGLE_EXT(xmask, xtexts) \
57{ .mask = xmask, .texts = xtexts }
58#define SOC_ENUM(xname, xenum) \
59{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname,\
60 .info = snd_soc_info_enum_double, \
61 .get = snd_soc_get_enum_double, .put = snd_soc_put_enum_double, \
62 .private_value = (unsigned long)&xenum }
63#define SOC_SINGLE_EXT(xname, xreg, xshift, xmask, xinvert,\
64 xhandler_get, xhandler_put) \
65{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
66 .info = snd_soc_info_volsw, \
67 .get = xhandler_get, .put = xhandler_put, \
68 .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmask, xinvert) }
69#define SOC_SINGLE_BOOL_EXT(xname, xdata, xhandler_get, xhandler_put) \
70{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
71 .info = snd_soc_info_bool_ext, \
72 .get = xhandler_get, .put = xhandler_put, \
73 .private_value = xdata }
74#define SOC_ENUM_EXT(xname, xenum, xhandler_get, xhandler_put) \
75{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
76 .info = snd_soc_info_enum_ext, \
77 .get = xhandler_get, .put = xhandler_put, \
78 .private_value = (unsigned long)&xenum }
79
80/*
81 * Digital Audio Interface (DAI) types
82 */
83#define SND_SOC_DAI_AC97 0x1
84#define SND_SOC_DAI_I2S 0x2
85#define SND_SOC_DAI_PCM 0x4
86
87/*
88 * DAI hardware audio formats
89 */
90#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
91#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right justified mode */
92#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
93#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM or LRC */
94#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM or LRC */
95#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
96
97#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
98#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
99
100/*
101 * DAI Gating
102 */
103#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
104#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */
105
106/*
107 * DAI hardware signal inversions
108 */
109#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */
110#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
111#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
112#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
113
114/*
115 * DAI hardware clock masters
116 * This is wrt the codec, the inverse is true for the interface
117 * i.e. if the codec is clk and frm master then the interface is
118 * clk and frame slave.
119 */
120#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */
121#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */
122#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
123#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */
124
125#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
126#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
127#define SND_SOC_DAIFMT_INV_MASK 0x0f00
128#define SND_SOC_DAIFMT_MASTER_MASK 0xf000
129
130
131/*
132 * Master Clock Directions
133 */
134#define SND_SOC_CLOCK_IN 0
135#define SND_SOC_CLOCK_OUT 1
136
137/*
138 * AC97 codec ID's bitmask
139 */
140#define SND_SOC_DAI_AC97_ID0 (1 << 0)
141#define SND_SOC_DAI_AC97_ID1 (1 << 1)
142#define SND_SOC_DAI_AC97_ID2 (1 << 2)
143#define SND_SOC_DAI_AC97_ID3 (1 << 3)
144
145struct snd_soc_device;
146struct snd_soc_pcm_stream;
147struct snd_soc_ops;
148struct snd_soc_dai_mode;
149struct snd_soc_pcm_runtime;
150struct snd_soc_codec_dai;
151struct snd_soc_cpu_dai;
152struct snd_soc_codec;
153struct snd_soc_machine_config;
154struct soc_enum;
155struct snd_soc_ac97_ops;
156struct snd_soc_clock_info;
157
158typedef int (*hw_write_t)(void *,const char* ,int);
159typedef int (*hw_read_t)(void *,char* ,int);
160
161extern struct snd_ac97_bus_ops soc_ac97_ops;
162
163/* pcm <-> DAI connect */
164void snd_soc_free_pcms(struct snd_soc_device *socdev);
165int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
166int snd_soc_register_card(struct snd_soc_device *socdev);
167
168/* set runtime hw params */
169int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
170 const struct snd_pcm_hardware *hw);
171
172/* codec IO */
173#define snd_soc_read(codec, reg) codec->read(codec, reg)
174#define snd_soc_write(codec, reg, value) codec->write(codec, reg, value)
175
176/* codec register bit access */
177int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
178 unsigned short mask, unsigned short value);
179int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
180 unsigned short mask, unsigned short value);
181
182int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
183 struct snd_ac97_bus_ops *ops, int num);
184void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
185
186/*
187 *Controls
188 */
189struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
190 void *data, char *long_name);
191int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
192 struct snd_ctl_elem_info *uinfo);
193int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
194 struct snd_ctl_elem_info *uinfo);
195int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
196 struct snd_ctl_elem_value *ucontrol);
197int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
198 struct snd_ctl_elem_value *ucontrol);
199int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
200 struct snd_ctl_elem_info *uinfo);
201int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
202 struct snd_ctl_elem_info *uinfo);
203int snd_soc_info_bool_ext(struct snd_kcontrol *kcontrol,
204 struct snd_ctl_elem_info *uinfo);
205int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
206 struct snd_ctl_elem_value *ucontrol);
207int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
208 struct snd_ctl_elem_value *ucontrol);
209int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
210 struct snd_ctl_elem_info *uinfo);
211int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
212 struct snd_ctl_elem_value *ucontrol);
213int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
214 struct snd_ctl_elem_value *ucontrol);
215
216/* SoC PCM stream information */
217struct snd_soc_pcm_stream {
218 char *stream_name;
219 u64 formats; /* SNDRV_PCM_FMTBIT_* */
220 unsigned int rates; /* SNDRV_PCM_RATE_* */
221 unsigned int rate_min; /* min rate */
222 unsigned int rate_max; /* max rate */
223 unsigned int channels_min; /* min channels */
224 unsigned int channels_max; /* max channels */
225 unsigned int active:1; /* stream is in use */
226};
227
228/* SoC audio ops */
229struct snd_soc_ops {
230 int (*startup)(struct snd_pcm_substream *);
231 void (*shutdown)(struct snd_pcm_substream *);
232 int (*hw_params)(struct snd_pcm_substream *, struct snd_pcm_hw_params *);
233 int (*hw_free)(struct snd_pcm_substream *);
234 int (*prepare)(struct snd_pcm_substream *);
235 int (*trigger)(struct snd_pcm_substream *, int);
236};
237
238/* ASoC codec DAI ops */
239struct snd_soc_codec_ops {
240 /* codec DAI clocking configuration */
241 int (*set_sysclk)(struct snd_soc_codec_dai *codec_dai,
242 int clk_id, unsigned int freq, int dir);
243 int (*set_pll)(struct snd_soc_codec_dai *codec_dai,
244 int pll_id, unsigned int freq_in, unsigned int freq_out);
245 int (*set_clkdiv)(struct snd_soc_codec_dai *codec_dai,
246 int div_id, int div);
247
248 /* CPU DAI format configuration */
249 int (*set_fmt)(struct snd_soc_codec_dai *codec_dai,
250 unsigned int fmt);
251 int (*set_tdm_slot)(struct snd_soc_codec_dai *codec_dai,
252 unsigned int mask, int slots);
253 int (*set_tristate)(struct snd_soc_codec_dai *, int tristate);
254
255 /* digital mute */
256 int (*digital_mute)(struct snd_soc_codec_dai *, int mute);
257};
258
259/* ASoC cpu DAI ops */
260struct snd_soc_cpu_ops {
261 /* CPU DAI clocking configuration */
262 int (*set_sysclk)(struct snd_soc_cpu_dai *cpu_dai,
263 int clk_id, unsigned int freq, int dir);
264 int (*set_clkdiv)(struct snd_soc_cpu_dai *cpu_dai,
265 int div_id, int div);
266 int (*set_pll)(struct snd_soc_cpu_dai *cpu_dai,
267 int pll_id, unsigned int freq_in, unsigned int freq_out);
268
269 /* CPU DAI format configuration */
270 int (*set_fmt)(struct snd_soc_cpu_dai *cpu_dai,
271 unsigned int fmt);
272 int (*set_tdm_slot)(struct snd_soc_cpu_dai *cpu_dai,
273 unsigned int mask, int slots);
274 int (*set_tristate)(struct snd_soc_cpu_dai *, int tristate);
275};
276
277/* SoC Codec DAI */
278struct snd_soc_codec_dai {
279 char *name;
280 int id;
281
282 /* DAI capabilities */
283 struct snd_soc_pcm_stream playback;
284 struct snd_soc_pcm_stream capture;
285
286 /* DAI runtime info */
287 struct snd_soc_codec *codec;
288 unsigned int active;
289 unsigned char pop_wait:1;
290
291 /* ops */
292 struct snd_soc_ops ops;
293 struct snd_soc_codec_ops dai_ops;
294
295 /* DAI private data */
296 void *private_data;
297};
298
299/* SoC CPU DAI */
300struct snd_soc_cpu_dai {
301
302 /* DAI description */
303 char *name;
304 unsigned int id;
305 unsigned char type;
306
307 /* DAI callbacks */
308 int (*probe)(struct platform_device *pdev);
309 void (*remove)(struct platform_device *pdev);
310 int (*suspend)(struct platform_device *pdev,
311 struct snd_soc_cpu_dai *cpu_dai);
312 int (*resume)(struct platform_device *pdev,
313 struct snd_soc_cpu_dai *cpu_dai);
314
315 /* ops */
316 struct snd_soc_ops ops;
317 struct snd_soc_cpu_ops dai_ops;
318
319 /* DAI capabilities */
320 struct snd_soc_pcm_stream capture;
321 struct snd_soc_pcm_stream playback;
322
323 /* DAI runtime info */
324 struct snd_pcm_runtime *runtime;
325 unsigned char active:1;
326 void *dma_data;
327
328 /* DAI private data */
329 void *private_data;
330};
331
332/* SoC Audio Codec */
333struct snd_soc_codec {
334 char *name;
335 struct module *owner;
336 struct mutex mutex;
337
338 /* callbacks */
339 int (*dapm_event)(struct snd_soc_codec *codec, int event);
340
341 /* runtime */
342 struct snd_card *card;
343 struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */
344 unsigned int active;
345 unsigned int pcm_devs;
346 void *private_data;
347
348 /* codec IO */
349 void *control_data; /* codec control (i2c/3wire) data */
350 unsigned int (*read)(struct snd_soc_codec *, unsigned int);
351 int (*write)(struct snd_soc_codec *, unsigned int, unsigned int);
352 hw_write_t hw_write;
353 hw_read_t hw_read;
354 void *reg_cache;
355 short reg_cache_size;
356 short reg_cache_step;
357
358 /* dapm */
359 struct list_head dapm_widgets;
360 struct list_head dapm_paths;
361 unsigned int dapm_state;
362 unsigned int suspend_dapm_state;
363 struct delayed_work delayed_work;
364
365 /* codec DAI's */
366 struct snd_soc_codec_dai *dai;
367 unsigned int num_dai;
368};
369
370/* codec device */
371struct snd_soc_codec_device {
372 int (*probe)(struct platform_device *pdev);
373 int (*remove)(struct platform_device *pdev);
374 int (*suspend)(struct platform_device *pdev, pm_message_t state);
375 int (*resume)(struct platform_device *pdev);
376};
377
378/* SoC platform interface */
379struct snd_soc_platform {
380 char *name;
381
382 int (*probe)(struct platform_device *pdev);
383 int (*remove)(struct platform_device *pdev);
384 int (*suspend)(struct platform_device *pdev,
385 struct snd_soc_cpu_dai *cpu_dai);
386 int (*resume)(struct platform_device *pdev,
387 struct snd_soc_cpu_dai *cpu_dai);
388
389 /* pcm creation and destruction */
390 int (*pcm_new)(struct snd_card *, struct snd_soc_codec_dai *,
391 struct snd_pcm *);
392 void (*pcm_free)(struct snd_pcm *);
393
394 /* platform stream ops */
395 struct snd_pcm_ops *pcm_ops;
396};
397
398/* SoC machine DAI configuration, glues a codec and cpu DAI together */
399struct snd_soc_dai_link {
400 char *name; /* Codec name */
401 char *stream_name; /* Stream name */
402
403 /* DAI */
404 struct snd_soc_codec_dai *codec_dai;
405 struct snd_soc_cpu_dai *cpu_dai;
406
407 /* machine stream operations */
408 struct snd_soc_ops *ops;
409
410 /* codec/machine specific init - e.g. add machine controls */
411 int (*init)(struct snd_soc_codec *codec);
412};
413
414/* SoC machine */
415struct snd_soc_machine {
416 char *name;
417
418 int (*probe)(struct platform_device *pdev);
419 int (*remove)(struct platform_device *pdev);
420
421 /* the pre and post PM functions are used to do any PM work before and
422 * after the codec and DAI's do any PM work. */
423 int (*suspend_pre)(struct platform_device *pdev, pm_message_t state);
424 int (*suspend_post)(struct platform_device *pdev, pm_message_t state);
425 int (*resume_pre)(struct platform_device *pdev);
426 int (*resume_post)(struct platform_device *pdev);
427
428 /* CPU <--> Codec DAI links */
429 struct snd_soc_dai_link *dai_link;
430 int num_links;
431};
432
433/* SoC Device - the audio subsystem */
434struct snd_soc_device {
435 struct device *dev;
436 struct snd_soc_machine *machine;
437 struct snd_soc_platform *platform;
438 struct snd_soc_codec *codec;
439 struct snd_soc_codec_device *codec_dev;
440 struct delayed_work delayed_work;
441 void *codec_data;
442};
443
444/* runtime channel data */
445struct snd_soc_pcm_runtime {
446 struct snd_soc_dai_link *dai;
447 struct snd_soc_device *socdev;
448};
449
450/* enumerated kcontrol */
451struct soc_enum {
452 unsigned short reg;
453 unsigned short reg2;
454 unsigned char shift_l;
455 unsigned char shift_r;
456 unsigned int mask;
457 const char **texts;
458 void *dapm;
459};
460
461#endif
diff --git a/include/sound/typedefs.h b/include/sound/typedefs.h
deleted file mode 100644
index f454b0206b93..000000000000
--- a/include/sound/typedefs.h
+++ /dev/null
@@ -1,173 +0,0 @@
1/*
2 * Typedef's for backward compatibility (for out-of-kernel drivers)
3 *
4 * This file will be removed soon in future
5 */
6
7/* core stuff */
8typedef struct snd_card snd_card_t;
9typedef struct snd_device snd_device_t;
10typedef struct snd_device_ops snd_device_ops_t;
11typedef enum snd_card_type snd_card_type_t;
12typedef struct snd_minor snd_minor_t;
13
14/* info */
15typedef struct snd_info_entry snd_info_entry_t;
16typedef struct snd_info_buffer snd_info_buffer_t;
17
18/* control */
19typedef struct snd_ctl_file snd_ctl_file_t;
20typedef struct snd_kcontrol snd_kcontrol_t;
21typedef struct snd_kcontrol_new snd_kcontrol_new_t;
22typedef struct snd_kcontrol_volatile snd_kcontrol_volatile_t;
23typedef struct snd_kctl_event snd_kctl_event_t;
24typedef struct snd_aes_iec958 snd_aes_iec958_t;
25typedef struct snd_ctl_card_info snd_ctl_card_info_t;
26typedef struct snd_ctl_elem_id snd_ctl_elem_id_t;
27typedef struct snd_ctl_elem_list snd_ctl_elem_list_t;
28typedef struct snd_ctl_elem_info snd_ctl_elem_info_t;
29typedef struct snd_ctl_elem_value snd_ctl_elem_value_t;
30typedef struct snd_ctl_event snd_ctl_event_t;
31#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
32typedef struct snd_mixer_oss snd_mixer_oss_t;
33#endif
34
35/* timer */
36typedef struct snd_timer snd_timer_t;
37typedef struct snd_timer_instance snd_timer_instance_t;
38typedef struct snd_timer_id snd_timer_id_t;
39typedef struct snd_timer_ginfo snd_timer_ginfo_t;
40typedef struct snd_timer_gparams snd_timer_gparams_t;
41typedef struct snd_timer_gstatus snd_timer_gstatus_t;
42typedef struct snd_timer_select snd_timer_select_t;
43typedef struct snd_timer_info snd_timer_info_t;
44typedef struct snd_timer_params snd_timer_params_t;
45typedef struct snd_timer_status snd_timer_status_t;
46typedef struct snd_timer_read snd_timer_read_t;
47typedef struct snd_timer_tread snd_timer_tread_t;
48
49/* PCM */
50typedef struct snd_pcm snd_pcm_t;
51typedef struct snd_pcm_str snd_pcm_str_t;
52typedef struct snd_pcm_substream snd_pcm_substream_t;
53typedef struct snd_pcm_info snd_pcm_info_t;
54typedef struct snd_pcm_hw_params snd_pcm_hw_params_t;
55typedef struct snd_pcm_sw_params snd_pcm_sw_params_t;
56typedef struct snd_pcm_channel_info snd_pcm_channel_info_t;
57typedef struct snd_pcm_status snd_pcm_status_t;
58typedef struct snd_pcm_mmap_status snd_pcm_mmap_status_t;
59typedef struct snd_pcm_mmap_control snd_pcm_mmap_control_t;
60typedef struct snd_mask snd_mask_t;
61typedef struct snd_sg_buf snd_pcm_sgbuf_t;
62
63typedef struct snd_interval snd_interval_t;
64typedef struct snd_xferi snd_xferi_t;
65typedef struct snd_xfern snd_xfern_t;
66typedef struct snd_xferv snd_xferv_t;
67
68typedef struct snd_pcm_file snd_pcm_file_t;
69typedef struct snd_pcm_runtime snd_pcm_runtime_t;
70typedef struct snd_pcm_hardware snd_pcm_hardware_t;
71typedef struct snd_pcm_ops snd_pcm_ops_t;
72typedef struct snd_pcm_hw_rule snd_pcm_hw_rule_t;
73typedef struct snd_pcm_hw_constraints snd_pcm_hw_constraints_t;
74typedef struct snd_ratnum ratnum_t;
75typedef struct snd_ratden ratden_t;
76typedef struct snd_pcm_hw_constraint_ratnums snd_pcm_hw_constraint_ratnums_t;
77typedef struct snd_pcm_hw_constraint_ratdens snd_pcm_hw_constraint_ratdens_t;
78typedef struct snd_pcm_hw_constraint_list snd_pcm_hw_constraint_list_t;
79typedef struct snd_pcm_group snd_pcm_group_t;
80typedef struct snd_pcm_notify snd_pcm_notify_t;
81
82/* rawmidi */
83typedef struct snd_rawmidi snd_rawmidi_t;
84typedef struct snd_rawmidi_info snd_rawmidi_info_t;
85typedef struct snd_rawmidi_params snd_rawmidi_params_t;
86typedef struct snd_rawmidi_status snd_rawmidi_status_t;
87typedef struct snd_rawmidi_runtime snd_rawmidi_runtime_t;
88typedef struct snd_rawmidi_substream snd_rawmidi_substream_t;
89typedef struct snd_rawmidi_str snd_rawmidi_str_t;
90typedef struct snd_rawmidi_ops snd_rawmidi_ops_t;
91typedef struct snd_rawmidi_global_ops snd_rawmidi_global_ops_t;
92typedef struct snd_rawmidi_file snd_rawmidi_file_t;
93
94/* hwdep */
95typedef struct snd_hwdep snd_hwdep_t;
96typedef struct snd_hwdep_info snd_hwdep_info_t;
97typedef struct snd_hwdep_dsp_status snd_hwdep_dsp_status_t;
98typedef struct snd_hwdep_dsp_image snd_hwdep_dsp_image_t;
99typedef struct snd_hwdep_ops snd_hwdep_ops_t;
100
101/* sequencer */
102typedef struct snd_seq_port_info snd_seq_port_info_t;
103typedef struct snd_seq_port_subscribe snd_seq_port_subscribe_t;
104typedef struct snd_seq_event snd_seq_event_t;
105typedef struct snd_seq_addr snd_seq_addr_t;
106typedef struct snd_seq_ev_volume snd_seq_ev_volume_t;
107typedef struct snd_seq_ev_loop snd_seq_ev_loop_t;
108typedef struct snd_seq_remove_events snd_seq_remove_events_t;
109typedef struct snd_seq_query_subs snd_seq_query_subs_t;
110typedef struct snd_seq_system_info snd_seq_system_info_t;
111typedef struct snd_seq_client_info snd_seq_client_info_t;
112typedef struct snd_seq_queue_info snd_seq_queue_info_t;
113typedef struct snd_seq_queue_status snd_seq_queue_status_t;
114typedef struct snd_seq_queue_tempo snd_seq_queue_tempo_t;
115typedef struct snd_seq_queue_owner snd_seq_queue_owner_t;
116typedef struct snd_seq_queue_timer snd_seq_queue_timer_t;
117typedef struct snd_seq_queue_client snd_seq_queue_client_t;
118typedef struct snd_seq_client_pool snd_seq_client_pool_t;
119typedef struct snd_seq_instr snd_seq_instr_t;
120typedef struct snd_seq_instr_data snd_seq_instr_data_t;
121typedef struct snd_seq_instr_header snd_seq_instr_header_t;
122
123typedef struct snd_seq_user_client user_client_t;
124typedef struct snd_seq_kernel_client kernel_client_t;
125typedef struct snd_seq_client client_t;
126typedef struct snd_seq_queue queue_t;
127
128/* seq_device */
129typedef struct snd_seq_device snd_seq_device_t;
130typedef struct snd_seq_dev_ops snd_seq_dev_ops_t;
131
132/* seq_midi */
133typedef struct snd_midi_event snd_midi_event_t;
134
135/* seq_midi_emul */
136typedef struct snd_midi_channel snd_midi_channel_t;
137typedef struct snd_midi_channel_set snd_midi_channel_set_t;
138typedef struct snd_midi_op snd_midi_op_t;
139
140/* seq_oss */
141typedef struct snd_seq_oss_arg snd_seq_oss_arg_t;
142typedef struct snd_seq_oss_callback snd_seq_oss_callback_t;
143typedef struct snd_seq_oss_reg snd_seq_oss_reg_t;
144
145/* virmidi */
146typedef struct snd_virmidi_dev snd_virmidi_dev_t;
147typedef struct snd_virmidi snd_virmidi_t;
148
149/* seq_instr */
150typedef struct snd_seq_kcluster snd_seq_kcluster_t;
151typedef struct snd_seq_kinstr_ops snd_seq_kinstr_ops_t;
152typedef struct snd_seq_kinstr snd_seq_kinstr_t;
153typedef struct snd_seq_kinstr_list snd_seq_kinstr_list_t;
154
155/* ac97 */
156typedef struct snd_ac97_bus ac97_bus_t;
157typedef struct snd_ac97_bus_ops ac97_bus_ops_t;
158typedef struct snd_ac97_template ac97_template_t;
159typedef struct snd_ac97 ac97_t;
160
161/* opl3/4 */
162typedef struct snd_opl3 opl3_t;
163typedef struct snd_opl4 opl4_t;
164
165/* mpu401 */
166typedef struct snd_mpu401 mpu401_t;
167
168/* i2c */
169typedef struct snd_i2c_device snd_i2c_device_t;
170typedef struct snd_i2c_bus snd_i2c_bus_t;
171
172typedef struct snd_ak4531 ak4531_t;
173
diff --git a/include/sound/version.h b/include/sound/version.h
index 20f7babad514..c39b3802cf18 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
1/* include/version.h. Generated by alsa/ksync script. */ 1/* include/version.h. Generated by alsa/ksync script. */
2#define CONFIG_SND_VERSION "1.0.14rc1" 2#define CONFIG_SND_VERSION "1.0.14rc2"
3#define CONFIG_SND_DATE " (Tue Jan 09 09:56:17 2007 UTC)" 3#define CONFIG_SND_DATE " (Fri Feb 09 13:50:10 2007 UTC)"
diff --git a/include/sound/vx_core.h b/include/sound/vx_core.h
index 217394652090..4830651cc4cf 100644
--- a/include/sound/vx_core.h
+++ b/include/sound/vx_core.h
@@ -128,7 +128,7 @@ struct snd_vx_hardware {
128 unsigned int num_ins; 128 unsigned int num_ins;
129 unsigned int num_outs; 129 unsigned int num_outs;
130 unsigned int output_level_max; 130 unsigned int output_level_max;
131 unsigned int *output_level_db_scale; 131 const unsigned int *output_level_db_scale;
132}; 132};
133 133
134/* hwdep id string */ 134/* hwdep id string */
diff --git a/include/sound/ymfpci.h b/include/sound/ymfpci.h
index f3514ee96bd9..203d2b45b788 100644
--- a/include/sound/ymfpci.h
+++ b/include/sound/ymfpci.h
@@ -270,6 +270,7 @@ struct snd_ymfpci_pcm {
270 struct snd_pcm_substream *substream; 270 struct snd_pcm_substream *substream;
271 struct snd_ymfpci_voice *voices[2]; /* playback only */ 271 struct snd_ymfpci_voice *voices[2]; /* playback only */
272 unsigned int running: 1, 272 unsigned int running: 1,
273 use_441_slot: 1,
273 output_front: 1, 274 output_front: 1,
274 output_rear: 1, 275 output_rear: 1,
275 swap_rear: 1; 276 swap_rear: 1;
@@ -324,6 +325,7 @@ struct snd_ymfpci {
324 325
325 u32 active_bank; 326 u32 active_bank;
326 struct snd_ymfpci_voice voices[64]; 327 struct snd_ymfpci_voice voices[64];
328 int src441_used;
327 329
328 struct snd_ac97_bus *ac97_bus; 330 struct snd_ac97_bus *ac97_bus;
329 struct snd_ac97 *ac97; 331 struct snd_ac97 *ac97;
@@ -346,7 +348,7 @@ struct snd_ymfpci {
346 int mode_dup4ch; 348 int mode_dup4ch;
347 int rear_opened; 349 int rear_opened;
348 int spdif_opened; 350 int spdif_opened;
349 struct { 351 struct snd_ymfpci_pcm_mixer {
350 u16 left; 352 u16 left;
351 u16 right; 353 u16 right;
352 struct snd_kcontrol *ctl; 354 struct snd_kcontrol *ctl;
@@ -357,6 +359,8 @@ struct snd_ymfpci {
357 wait_queue_head_t interrupt_sleep; 359 wait_queue_head_t interrupt_sleep;
358 atomic_t interrupt_sleep_count; 360 atomic_t interrupt_sleep_count;
359 struct snd_info_entry *proc_entry; 361 struct snd_info_entry *proc_entry;
362 const struct firmware *dsp_microcode;
363 const struct firmware *controller_microcode;
360 364
361#ifdef CONFIG_PM 365#ifdef CONFIG_PM
362 u32 *saved_regs; 366 u32 *saved_regs;
diff --git a/sound/Kconfig b/sound/Kconfig
index 9d77300746c6..97532bbc2ccb 100644
--- a/sound/Kconfig
+++ b/sound/Kconfig
@@ -76,6 +76,8 @@ source "sound/sparc/Kconfig"
76 76
77source "sound/parisc/Kconfig" 77source "sound/parisc/Kconfig"
78 78
79source "sound/soc/Kconfig"
80
79endmenu 81endmenu
80 82
81menu "Open Sound System" 83menu "Open Sound System"
diff --git a/sound/Makefile b/sound/Makefile
index 9aee54c4882d..b7c7fb7c24c8 100644
--- a/sound/Makefile
+++ b/sound/Makefile
@@ -5,7 +5,7 @@ obj-$(CONFIG_SOUND) += soundcore.o
5obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o 5obj-$(CONFIG_SOUND_PRIME) += sound_firmware.o
6obj-$(CONFIG_SOUND_PRIME) += oss/ 6obj-$(CONFIG_SOUND_PRIME) += oss/
7obj-$(CONFIG_DMASOUND) += oss/ 7obj-$(CONFIG_DMASOUND) += oss/
8obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ 8obj-$(CONFIG_SND) += core/ i2c/ drivers/ isa/ pci/ ppc/ arm/ synth/ usb/ sparc/ parisc/ pcmcia/ mips/ soc/
9obj-$(CONFIG_SND_AOA) += aoa/ 9obj-$(CONFIG_SND_AOA) += aoa/
10 10
11# This one must be compilable even if sound is configured out 11# This one must be compilable even if sound is configured out
diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c
index 66de2c2f1554..7fa37e15f196 100644
--- a/sound/ac97_bus.c
+++ b/sound/ac97_bus.c
@@ -26,6 +26,7 @@ static int ac97_bus_match(struct device *dev, struct device_driver *drv)
26 return 1; 26 return 1;
27} 27}
28 28
29#ifdef CONFIG_PM
29static int ac97_bus_suspend(struct device *dev, pm_message_t state) 30static int ac97_bus_suspend(struct device *dev, pm_message_t state)
30{ 31{
31 int ret = 0; 32 int ret = 0;
@@ -45,12 +46,15 @@ static int ac97_bus_resume(struct device *dev)
45 46
46 return ret; 47 return ret;
47} 48}
49#endif /* CONFIG_PM */
48 50
49struct bus_type ac97_bus_type = { 51struct bus_type ac97_bus_type = {
50 .name = "ac97", 52 .name = "ac97",
51 .match = ac97_bus_match, 53 .match = ac97_bus_match,
54#ifdef CONFIG_PM
52 .suspend = ac97_bus_suspend, 55 .suspend = ac97_bus_suspend,
53 .resume = ac97_bus_resume, 56 .resume = ac97_bus_resume,
57#endif /* CONFIG_PM */
54}; 58};
55 59
56static int __init ac97_bus_init(void) 60static int __init ac97_bus_init(void)
diff --git a/sound/aoa/aoa.h b/sound/aoa/aoa.h
index 378ef1e9879b..541b908f3cdf 100644
--- a/sound/aoa/aoa.h
+++ b/sound/aoa/aoa.h
@@ -99,7 +99,7 @@ struct aoa_fabric {
99 * that are not assigned yet are passed to the fabric 99 * that are not assigned yet are passed to the fabric
100 * again for reconsideration. */ 100 * again for reconsideration. */
101extern int 101extern int
102aoa_fabric_register(struct aoa_fabric *fabric); 102aoa_fabric_register(struct aoa_fabric *fabric, struct device *dev);
103 103
104/* it is vital to call this when the fabric exits! 104/* it is vital to call this when the fabric exits!
105 * When calling, the remove_codec will be called 105 * When calling, the remove_codec will be called
diff --git a/sound/aoa/codecs/snd-aoa-codec-onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c
index 0b7650788f1f..b00fc4842c93 100644
--- a/sound/aoa/codecs/snd-aoa-codec-onyx.c
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c
@@ -825,7 +825,16 @@ static int onyx_resume(struct codec_info_item *cii)
825 int err = -ENXIO; 825 int err = -ENXIO;
826 826
827 mutex_lock(&onyx->mutex); 827 mutex_lock(&onyx->mutex);
828 /* take codec out of suspend */ 828
829 /* reset codec */
830 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
831 msleep(1);
832 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 1);
833 msleep(1);
834 onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
835 msleep(1);
836
837 /* take codec out of suspend (if it still is after reset) */
829 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v)) 838 if (onyx_read_register(onyx, ONYX_REG_CONTROL, &v))
830 goto out_unlock; 839 goto out_unlock;
831 onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV)); 840 onyx_write_register(onyx, ONYX_REG_CONTROL, v & ~(ONYX_ADPSV | ONYX_DAPSV));
diff --git a/sound/aoa/core/snd-aoa-alsa.c b/sound/aoa/core/snd-aoa-alsa.c
index b42fdea77ed0..17fe689ed287 100644
--- a/sound/aoa/core/snd-aoa-alsa.c
+++ b/sound/aoa/core/snd-aoa-alsa.c
@@ -14,7 +14,7 @@ MODULE_PARM_DESC(index, "index for AOA sound card.");
14 14
15static struct aoa_card *aoa_card; 15static struct aoa_card *aoa_card;
16 16
17int aoa_alsa_init(char *name, struct module *mod) 17int aoa_alsa_init(char *name, struct module *mod, struct device *dev)
18{ 18{
19 struct snd_card *alsa_card; 19 struct snd_card *alsa_card;
20 int err; 20 int err;
@@ -28,6 +28,7 @@ int aoa_alsa_init(char *name, struct module *mod)
28 return -ENOMEM; 28 return -ENOMEM;
29 aoa_card = alsa_card->private_data; 29 aoa_card = alsa_card->private_data;
30 aoa_card->alsa_card = alsa_card; 30 aoa_card->alsa_card = alsa_card;
31 alsa_card->dev = dev;
31 strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver)); 32 strlcpy(alsa_card->driver, "AppleOnbdAudio", sizeof(alsa_card->driver));
32 strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname)); 33 strlcpy(alsa_card->shortname, name, sizeof(alsa_card->shortname));
33 strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname)); 34 strlcpy(alsa_card->longname, name, sizeof(alsa_card->longname));
@@ -59,7 +60,7 @@ void aoa_alsa_cleanup(void)
59} 60}
60 61
61int aoa_snd_device_new(snd_device_type_t type, 62int aoa_snd_device_new(snd_device_type_t type,
62 void * device_data, struct snd_device_ops * ops) 63 void * device_data, struct snd_device_ops * ops)
63{ 64{
64 struct snd_card *card = aoa_get_card(); 65 struct snd_card *card = aoa_get_card();
65 int err; 66 int err;
diff --git a/sound/aoa/core/snd-aoa-alsa.h b/sound/aoa/core/snd-aoa-alsa.h
index 660d2f1793bb..9669e4489cab 100644
--- a/sound/aoa/core/snd-aoa-alsa.h
+++ b/sound/aoa/core/snd-aoa-alsa.h
@@ -10,7 +10,7 @@
10#define __SND_AOA_ALSA_H 10#define __SND_AOA_ALSA_H
11#include "../aoa.h" 11#include "../aoa.h"
12 12
13extern int aoa_alsa_init(char *name, struct module *mod); 13extern int aoa_alsa_init(char *name, struct module *mod, struct device *dev);
14extern void aoa_alsa_cleanup(void); 14extern void aoa_alsa_cleanup(void);
15 15
16#endif /* __SND_AOA_ALSA_H */ 16#endif /* __SND_AOA_ALSA_H */
diff --git a/sound/aoa/core/snd-aoa-core.c b/sound/aoa/core/snd-aoa-core.c
index ecd2d8263f2d..19fdae400687 100644
--- a/sound/aoa/core/snd-aoa-core.c
+++ b/sound/aoa/core/snd-aoa-core.c
@@ -82,7 +82,7 @@ void aoa_codec_unregister(struct aoa_codec *codec)
82} 82}
83EXPORT_SYMBOL_GPL(aoa_codec_unregister); 83EXPORT_SYMBOL_GPL(aoa_codec_unregister);
84 84
85int aoa_fabric_register(struct aoa_fabric *new_fabric) 85int aoa_fabric_register(struct aoa_fabric *new_fabric, struct device *dev)
86{ 86{
87 struct aoa_codec *c; 87 struct aoa_codec *c;
88 int err; 88 int err;
@@ -98,7 +98,7 @@ int aoa_fabric_register(struct aoa_fabric *new_fabric)
98 if (!new_fabric) 98 if (!new_fabric)
99 return -EINVAL; 99 return -EINVAL;
100 100
101 err = aoa_alsa_init(new_fabric->name, new_fabric->owner); 101 err = aoa_alsa_init(new_fabric->name, new_fabric->owner, dev);
102 if (err) 102 if (err)
103 return err; 103 return err;
104 104
diff --git a/sound/aoa/fabrics/snd-aoa-fabric-layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
index 172eb95476c0..1b94ba6dd279 100644
--- a/sound/aoa/fabrics/snd-aoa-fabric-layout.c
+++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
@@ -1014,7 +1014,7 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
1014 1014
1015 ldev->gpio.methods->init(&ldev->gpio); 1015 ldev->gpio.methods->init(&ldev->gpio);
1016 1016
1017 err = aoa_fabric_register(&layout_fabric); 1017 err = aoa_fabric_register(&layout_fabric, &sdev->ofdev.dev);
1018 if (err && err != -EALREADY) { 1018 if (err && err != -EALREADY) {
1019 printk(KERN_INFO "snd-aoa-fabric-layout: can't use," 1019 printk(KERN_INFO "snd-aoa-fabric-layout: can't use,"
1020 " another fabric is active!\n"); 1020 " another fabric is active!\n");
@@ -1034,9 +1034,9 @@ static int aoa_fabric_layout_probe(struct soundbus_dev *sdev)
1034 list_del(&ldev->list); 1034 list_del(&ldev->list);
1035 layouts_list_items--; 1035 layouts_list_items--;
1036 outnodev: 1036 outnodev:
1037 if (sound) of_node_put(sound); 1037 of_node_put(sound);
1038 layout_device = NULL; 1038 layout_device = NULL;
1039 if (ldev) kfree(ldev); 1039 kfree(ldev);
1040 return -ENODEV; 1040 return -ENODEV;
1041} 1041}
1042 1042
@@ -1077,8 +1077,6 @@ static int aoa_fabric_layout_suspend(struct soundbus_dev *sdev, pm_message_t sta
1077{ 1077{
1078 struct layout_dev *ldev = sdev->ofdev.dev.driver_data; 1078 struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
1079 1079
1080 printk("aoa_fabric_layout_suspend()\n");
1081
1082 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) 1080 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
1083 ldev->gpio.methods->all_amps_off(&ldev->gpio); 1081 ldev->gpio.methods->all_amps_off(&ldev->gpio);
1084 1082
@@ -1089,8 +1087,6 @@ static int aoa_fabric_layout_resume(struct soundbus_dev *sdev)
1089{ 1087{
1090 struct layout_dev *ldev = sdev->ofdev.dev.driver_data; 1088 struct layout_dev *ldev = sdev->ofdev.dev.driver_data;
1091 1089
1092 printk("aoa_fabric_layout_resume()\n");
1093
1094 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off) 1090 if (ldev->gpio.methods && ldev->gpio.methods->all_amps_off)
1095 ldev->gpio.methods->all_amps_restore(&ldev->gpio); 1091 ldev->gpio.methods->all_amps_restore(&ldev->gpio);
1096 1092
@@ -1107,6 +1103,9 @@ static struct soundbus_driver aoa_soundbus_driver = {
1107 .suspend = aoa_fabric_layout_suspend, 1103 .suspend = aoa_fabric_layout_suspend,
1108 .resume = aoa_fabric_layout_resume, 1104 .resume = aoa_fabric_layout_resume,
1109#endif 1105#endif
1106 .driver = {
1107 .owner = THIS_MODULE,
1108 }
1110}; 1109};
1111 1110
1112static int __init aoa_fabric_layout_init(void) 1111static int __init aoa_fabric_layout_init(void)
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
index e593a1333fe3..e36f6aa448d4 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-core.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -41,8 +41,8 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
41 struct dbdma_command_mem *r, 41 struct dbdma_command_mem *r,
42 int numcmds) 42 int numcmds)
43{ 43{
44 /* one more for rounding */ 44 /* one more for rounding, one for branch back, one for stop command */
45 r->size = (numcmds+1) * sizeof(struct dbdma_cmd); 45 r->size = (numcmds + 3) * sizeof(struct dbdma_cmd);
46 /* We use the PCI APIs for now until the generic one gets fixed 46 /* We use the PCI APIs for now until the generic one gets fixed
47 * enough or until we get some macio-specific versions 47 * enough or until we get some macio-specific versions
48 */ 48 */
@@ -377,11 +377,8 @@ static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
377 if (i2sdev->sound.pcm) { 377 if (i2sdev->sound.pcm) {
378 /* Suspend PCM streams */ 378 /* Suspend PCM streams */
379 snd_pcm_suspend_all(i2sdev->sound.pcm); 379 snd_pcm_suspend_all(i2sdev->sound.pcm);
380 /* Probably useless as we handle
381 * power transitions ourselves */
382 snd_power_change_state(i2sdev->sound.pcm->card,
383 SNDRV_CTL_POWER_D3hot);
384 } 380 }
381
385 /* Notify codecs */ 382 /* Notify codecs */
386 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { 383 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
387 err = 0; 384 err = 0;
@@ -390,7 +387,11 @@ static int i2sbus_suspend(struct macio_dev* dev, pm_message_t state)
390 if (err) 387 if (err)
391 ret = err; 388 ret = err;
392 } 389 }
390
391 /* wait until streams are stopped */
392 i2sbus_wait_for_stop_both(i2sdev);
393 } 393 }
394
394 return ret; 395 return ret;
395} 396}
396 397
@@ -402,6 +403,9 @@ static int i2sbus_resume(struct macio_dev* dev)
402 int err, ret = 0; 403 int err, ret = 0;
403 404
404 list_for_each_entry(i2sdev, &control->list, item) { 405 list_for_each_entry(i2sdev, &control->list, item) {
406 /* reset i2s bus format etc. */
407 i2sbus_pcm_prepare_both(i2sdev);
408
405 /* Notify codecs so they can re-initialize */ 409 /* Notify codecs so they can re-initialize */
406 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) { 410 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) {
407 err = 0; 411 err = 0;
@@ -410,12 +414,6 @@ static int i2sbus_resume(struct macio_dev* dev)
410 if (err) 414 if (err)
411 ret = err; 415 ret = err;
412 } 416 }
413 /* Notify Alsa */
414 if (i2sdev->sound.pcm) {
415 /* Same comment as above, probably useless */
416 snd_power_change_state(i2sdev->sound.pcm->card,
417 SNDRV_CTL_POWER_D0);
418 }
419 } 417 }
420 418
421 return ret; 419 return ret;
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
index 5eff30b10201..c6b42f9bdbc9 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
@@ -125,7 +125,8 @@ static int i2sbus_pcm_open(struct i2sbus_dev *i2sdev, int in)
125 } 125 }
126 /* bus dependent stuff */ 126 /* bus dependent stuff */
127 hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | 127 hw->info = SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID |
128 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME; 128 SNDRV_PCM_INFO_INTERLEAVED | SNDRV_PCM_INFO_RESUME |
129 SNDRV_PCM_INFO_JOINT_DUPLEX;
129 130
130 CHECK_RATE(5512); 131 CHECK_RATE(5512);
131 CHECK_RATE(8000); 132 CHECK_RATE(8000);
@@ -245,18 +246,78 @@ static int i2sbus_pcm_close(struct i2sbus_dev *i2sdev, int in)
245 return err; 246 return err;
246} 247}
247 248
249static void i2sbus_wait_for_stop(struct i2sbus_dev *i2sdev,
250 struct pcm_info *pi)
251{
252 unsigned long flags;
253 struct completion done;
254 long timeout;
255
256 spin_lock_irqsave(&i2sdev->low_lock, flags);
257 if (pi->dbdma_ring.stopping) {
258 init_completion(&done);
259 pi->stop_completion = &done;
260 spin_unlock_irqrestore(&i2sdev->low_lock, flags);
261 timeout = wait_for_completion_timeout(&done, HZ);
262 spin_lock_irqsave(&i2sdev->low_lock, flags);
263 pi->stop_completion = NULL;
264 if (timeout == 0) {
265 /* timeout expired, stop dbdma forcefully */
266 printk(KERN_ERR "i2sbus_wait_for_stop: timed out\n");
267 /* make sure RUN, PAUSE and S0 bits are cleared */
268 out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
269 pi->dbdma_ring.stopping = 0;
270 timeout = 10;
271 while (in_le32(&pi->dbdma->status) & ACTIVE) {
272 if (--timeout <= 0)
273 break;
274 udelay(1);
275 }
276 }
277 }
278 spin_unlock_irqrestore(&i2sdev->low_lock, flags);
279}
280
281#ifdef CONFIG_PM
282void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev)
283{
284 struct pcm_info *pi;
285
286 get_pcm_info(i2sdev, 0, &pi, NULL);
287 i2sbus_wait_for_stop(i2sdev, pi);
288 get_pcm_info(i2sdev, 1, &pi, NULL);
289 i2sbus_wait_for_stop(i2sdev, pi);
290}
291#endif
292
248static int i2sbus_hw_params(struct snd_pcm_substream *substream, 293static int i2sbus_hw_params(struct snd_pcm_substream *substream,
249 struct snd_pcm_hw_params *params) 294 struct snd_pcm_hw_params *params)
250{ 295{
251 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params)); 296 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
252} 297}
253 298
254static int i2sbus_hw_free(struct snd_pcm_substream *substream) 299static inline int i2sbus_hw_free(struct snd_pcm_substream *substream, int in)
255{ 300{
301 struct i2sbus_dev *i2sdev = snd_pcm_substream_chip(substream);
302 struct pcm_info *pi;
303
304 get_pcm_info(i2sdev, in, &pi, NULL);
305 if (pi->dbdma_ring.stopping)
306 i2sbus_wait_for_stop(i2sdev, pi);
256 snd_pcm_lib_free_pages(substream); 307 snd_pcm_lib_free_pages(substream);
257 return 0; 308 return 0;
258} 309}
259 310
311static int i2sbus_playback_hw_free(struct snd_pcm_substream *substream)
312{
313 return i2sbus_hw_free(substream, 0);
314}
315
316static int i2sbus_record_hw_free(struct snd_pcm_substream *substream)
317{
318 return i2sbus_hw_free(substream, 1);
319}
320
260static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in) 321static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
261{ 322{
262 /* whee. Hard work now. The user has selected a bitrate 323 /* whee. Hard work now. The user has selected a bitrate
@@ -264,7 +325,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
264 * I2S controller appropriately. */ 325 * I2S controller appropriately. */
265 struct snd_pcm_runtime *runtime; 326 struct snd_pcm_runtime *runtime;
266 struct dbdma_cmd *command; 327 struct dbdma_cmd *command;
267 int i, periodsize; 328 int i, periodsize, nperiods;
268 dma_addr_t offset; 329 dma_addr_t offset;
269 struct bus_info bi; 330 struct bus_info bi;
270 struct codec_info_item *cii; 331 struct codec_info_item *cii;
@@ -274,6 +335,7 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
274 struct pcm_info *pi, *other; 335 struct pcm_info *pi, *other;
275 int cnt; 336 int cnt;
276 int result = 0; 337 int result = 0;
338 unsigned int cmd, stopaddr;
277 339
278 mutex_lock(&i2sdev->lock); 340 mutex_lock(&i2sdev->lock);
279 341
@@ -283,6 +345,13 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
283 result = -EBUSY; 345 result = -EBUSY;
284 goto out_unlock; 346 goto out_unlock;
285 } 347 }
348 if (pi->dbdma_ring.stopping)
349 i2sbus_wait_for_stop(i2sdev, pi);
350
351 if (!pi->substream || !pi->substream->runtime) {
352 result = -EINVAL;
353 goto out_unlock;
354 }
286 355
287 runtime = pi->substream->runtime; 356 runtime = pi->substream->runtime;
288 pi->active = 1; 357 pi->active = 1;
@@ -297,24 +366,43 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
297 i2sdev->rate = runtime->rate; 366 i2sdev->rate = runtime->rate;
298 367
299 periodsize = snd_pcm_lib_period_bytes(pi->substream); 368 periodsize = snd_pcm_lib_period_bytes(pi->substream);
369 nperiods = pi->substream->runtime->periods;
300 pi->current_period = 0; 370 pi->current_period = 0;
301 371
302 /* generate dbdma command ring first */ 372 /* generate dbdma command ring first */
303 command = pi->dbdma_ring.cmds; 373 command = pi->dbdma_ring.cmds;
374 memset(command, 0, (nperiods + 2) * sizeof(struct dbdma_cmd));
375
376 /* commands to DMA to/from the ring */
377 /*
378 * For input, we need to do a graceful stop; if we abort
379 * the DMA, we end up with leftover bytes that corrupt
380 * the next recording. To do this we set the S0 status
381 * bit and wait for the DMA controller to stop. Each
382 * command has a branch condition to
383 * make it branch to a stop command if S0 is set.
384 * On input we also need to wait for the S7 bit to be
385 * set before turning off the DMA controller.
386 * In fact we do the graceful stop for output as well.
387 */
304 offset = runtime->dma_addr; 388 offset = runtime->dma_addr;
305 for (i = 0; i < pi->substream->runtime->periods; 389 cmd = (in? INPUT_MORE: OUTPUT_MORE) | BR_IFSET | INTR_ALWAYS;
306 i++, command++, offset += periodsize) { 390 stopaddr = pi->dbdma_ring.bus_cmd_start +
307 memset(command, 0, sizeof(struct dbdma_cmd)); 391 (nperiods + 1) * sizeof(struct dbdma_cmd);
308 command->command = 392 for (i = 0; i < nperiods; i++, command++, offset += periodsize) {
309 cpu_to_le16((in ? INPUT_MORE : OUTPUT_MORE) | INTR_ALWAYS); 393 command->command = cpu_to_le16(cmd);
394 command->cmd_dep = cpu_to_le32(stopaddr);
310 command->phy_addr = cpu_to_le32(offset); 395 command->phy_addr = cpu_to_le32(offset);
311 command->req_count = cpu_to_le16(periodsize); 396 command->req_count = cpu_to_le16(periodsize);
312 command->xfer_status = cpu_to_le16(0);
313 } 397 }
314 /* last one branches back to first */ 398
315 command--; 399 /* branch back to beginning of ring */
316 command->command |= cpu_to_le16(BR_ALWAYS); 400 command->command = cpu_to_le16(DBDMA_NOP | BR_ALWAYS);
317 command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start); 401 command->cmd_dep = cpu_to_le32(pi->dbdma_ring.bus_cmd_start);
402 command++;
403
404 /* set stop command */
405 command->command = cpu_to_le16(DBDMA_STOP);
318 406
319 /* ok, let's set the serial format and stuff */ 407 /* ok, let's set the serial format and stuff */
320 switch (runtime->format) { 408 switch (runtime->format) {
@@ -435,16 +523,18 @@ static int i2sbus_pcm_prepare(struct i2sbus_dev *i2sdev, int in)
435 return result; 523 return result;
436} 524}
437 525
438static struct dbdma_cmd STOP_CMD = { 526#ifdef CONFIG_PM
439 .command = __constant_cpu_to_le16(DBDMA_STOP), 527void i2sbus_pcm_prepare_both(struct i2sbus_dev *i2sdev)
440}; 528{
529 i2sbus_pcm_prepare(i2sdev, 0);
530 i2sbus_pcm_prepare(i2sdev, 1);
531}
532#endif
441 533
442static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd) 534static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
443{ 535{
444 struct codec_info_item *cii; 536 struct codec_info_item *cii;
445 struct pcm_info *pi; 537 struct pcm_info *pi;
446 int timeout;
447 struct dbdma_cmd tmp;
448 int result = 0; 538 int result = 0;
449 unsigned long flags; 539 unsigned long flags;
450 540
@@ -464,92 +554,50 @@ static int i2sbus_pcm_trigger(struct i2sbus_dev *i2sdev, int in, int cmd)
464 cii->codec->start(cii, pi->substream); 554 cii->codec->start(cii, pi->substream);
465 pi->dbdma_ring.running = 1; 555 pi->dbdma_ring.running = 1;
466 556
467 /* reset dma engine */ 557 if (pi->dbdma_ring.stopping) {
468 out_le32(&pi->dbdma->control, 558 /* Clear the S0 bit, then see if we stopped yet */
469 0 | (RUN | PAUSE | FLUSH | WAKE) << 16); 559 out_le32(&pi->dbdma->control, 1 << 16);
470 timeout = 100; 560 if (in_le32(&pi->dbdma->status) & ACTIVE) {
471 while (in_le32(&pi->dbdma->status) & RUN && timeout--) 561 /* possible race here? */
472 udelay(1); 562 udelay(10);
473 if (timeout <= 0) { 563 if (in_le32(&pi->dbdma->status) & ACTIVE) {
474 printk(KERN_ERR 564 pi->dbdma_ring.stopping = 0;
475 "i2sbus: error waiting for dma reset\n"); 565 goto out_unlock; /* keep running */
476 result = -ENXIO; 566 }
477 goto out_unlock; 567 }
478 } 568 }
479 569
570 /* make sure RUN, PAUSE and S0 bits are cleared */
571 out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
572
573 /* set branch condition select register */
574 out_le32(&pi->dbdma->br_sel, (1 << 16) | 1);
575
480 /* write dma command buffer address to the dbdma chip */ 576 /* write dma command buffer address to the dbdma chip */
481 out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start); 577 out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
482 /* post PCI write */
483 mb();
484 (void)in_le32(&pi->dbdma->status);
485
486 /* change first command to STOP */
487 tmp = *pi->dbdma_ring.cmds;
488 *pi->dbdma_ring.cmds = STOP_CMD;
489
490 /* set running state, remember that the first command is STOP */
491 out_le32(&pi->dbdma->control, RUN | (RUN << 16));
492 timeout = 100;
493 /* wait for STOP to be executed */
494 while (in_le32(&pi->dbdma->status) & ACTIVE && timeout--)
495 udelay(1);
496 if (timeout <= 0) {
497 printk(KERN_ERR "i2sbus: error waiting for dma stop\n");
498 result = -ENXIO;
499 goto out_unlock;
500 }
501 /* again, write dma command buffer address to the dbdma chip,
502 * this time of the first real command */
503 *pi->dbdma_ring.cmds = tmp;
504 out_le32(&pi->dbdma->cmdptr, pi->dbdma_ring.bus_cmd_start);
505 /* post write */
506 mb();
507 (void)in_le32(&pi->dbdma->status);
508
509 /* reset dma engine again */
510 out_le32(&pi->dbdma->control,
511 0 | (RUN | PAUSE | FLUSH | WAKE) << 16);
512 timeout = 100;
513 while (in_le32(&pi->dbdma->status) & RUN && timeout--)
514 udelay(1);
515 if (timeout <= 0) {
516 printk(KERN_ERR
517 "i2sbus: error waiting for dma reset\n");
518 result = -ENXIO;
519 goto out_unlock;
520 }
521 578
522 /* wake up the chip with the next descriptor */ 579 /* initialize the frame count and current period */
523 out_le32(&pi->dbdma->control, 580 pi->current_period = 0;
524 (RUN | WAKE) | ((RUN | WAKE) << 16));
525 /* get the frame count */
526 pi->frame_count = in_le32(&i2sdev->intfregs->frame_count); 581 pi->frame_count = in_le32(&i2sdev->intfregs->frame_count);
527 582
583 /* set the DMA controller running */
584 out_le32(&pi->dbdma->control, (RUN << 16) | RUN);
585
528 /* off you go! */ 586 /* off you go! */
529 break; 587 break;
588
530 case SNDRV_PCM_TRIGGER_STOP: 589 case SNDRV_PCM_TRIGGER_STOP:
531 case SNDRV_PCM_TRIGGER_SUSPEND: 590 case SNDRV_PCM_TRIGGER_SUSPEND:
532 if (!pi->dbdma_ring.running) { 591 if (!pi->dbdma_ring.running) {
533 result = -EALREADY; 592 result = -EALREADY;
534 goto out_unlock; 593 goto out_unlock;
535 } 594 }
595 pi->dbdma_ring.running = 0;
536 596
537 /* turn off all relevant bits */ 597 /* Set the S0 bit to make the DMA branch to the stop cmd */
538 out_le32(&pi->dbdma->control, 598 out_le32(&pi->dbdma->control, (1 << 16) | 1);
539 (RUN | WAKE | FLUSH | PAUSE) << 16); 599 pi->dbdma_ring.stopping = 1;
540 {
541 /* FIXME: move to own function */
542 int timeout = 5000;
543 while ((in_le32(&pi->dbdma->status) & RUN)
544 && --timeout > 0)
545 udelay(1);
546 if (!timeout)
547 printk(KERN_ERR
548 "i2sbus: timed out turning "
549 "off dbdma engine!\n");
550 }
551 600
552 pi->dbdma_ring.running = 0;
553 list_for_each_entry(cii, &i2sdev->sound.codec_list, list) 601 list_for_each_entry(cii, &i2sdev->sound.codec_list, list)
554 if (cii->codec->stop) 602 if (cii->codec->stop)
555 cii->codec->stop(cii, pi->substream); 603 cii->codec->stop(cii, pi->substream);
@@ -574,70 +622,82 @@ static snd_pcm_uframes_t i2sbus_pcm_pointer(struct i2sbus_dev *i2sdev, int in)
574 fc = in_le32(&i2sdev->intfregs->frame_count); 622 fc = in_le32(&i2sdev->intfregs->frame_count);
575 fc = fc - pi->frame_count; 623 fc = fc - pi->frame_count;
576 624
577 return (bytes_to_frames(pi->substream->runtime, 625 if (fc >= pi->substream->runtime->buffer_size)
578 pi->current_period * 626 fc %= pi->substream->runtime->buffer_size;
579 snd_pcm_lib_period_bytes(pi->substream)) 627 return fc;
580 + fc) % pi->substream->runtime->buffer_size;
581} 628}
582 629
583static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in) 630static inline void handle_interrupt(struct i2sbus_dev *i2sdev, int in)
584{ 631{
585 struct pcm_info *pi; 632 struct pcm_info *pi;
586 u32 fc; 633 u32 fc, nframes;
587 u32 delta; 634 u32 status;
635 int timeout, i;
636 int dma_stopped = 0;
637 struct snd_pcm_runtime *runtime;
588 638
589 spin_lock(&i2sdev->low_lock); 639 spin_lock(&i2sdev->low_lock);
590 get_pcm_info(i2sdev, in, &pi, NULL); 640 get_pcm_info(i2sdev, in, &pi, NULL);
591 641 if (!pi->dbdma_ring.running && !pi->dbdma_ring.stopping)
592 if (!pi->dbdma_ring.running) {
593 /* there was still an interrupt pending
594 * while we stopped. or maybe another
595 * processor (not the one that was stopping
596 * the DMA engine) was spinning above
597 * waiting for the lock. */
598 goto out_unlock; 642 goto out_unlock;
599 }
600 643
601 fc = in_le32(&i2sdev->intfregs->frame_count); 644 i = pi->current_period;
602 /* a counter overflow does not change the calculation. */ 645 runtime = pi->substream->runtime;
603 delta = fc - pi->frame_count; 646 while (pi->dbdma_ring.cmds[i].xfer_status) {
604 647 if (le16_to_cpu(pi->dbdma_ring.cmds[i].xfer_status) & BT)
605 /* update current_period */ 648 /*
606 while (delta >= pi->substream->runtime->period_size) { 649 * BT is the branch taken bit. If it took a branch
607 pi->current_period++; 650 * it is because we set the S0 bit to make it
608 delta = delta - pi->substream->runtime->period_size; 651 * branch to the stop command.
609 } 652 */
610 653 dma_stopped = 1;
611 if (unlikely(delta)) { 654 pi->dbdma_ring.cmds[i].xfer_status = 0;
612 /* Some interrupt came late, so check the dbdma. 655
613 * This special case exists to syncronize the frame_count with 656 if (++i >= runtime->periods) {
614 * the dbdma transfer, but is hit every once in a while. */ 657 i = 0;
615 int period; 658 pi->frame_count += runtime->buffer_size;
616
617 period = (in_le32(&pi->dbdma->cmdptr)
618 - pi->dbdma_ring.bus_cmd_start)
619 / sizeof(struct dbdma_cmd);
620 pi->current_period = pi->current_period
621 % pi->substream->runtime->periods;
622
623 while (pi->current_period != period) {
624 pi->current_period++;
625 pi->current_period %= pi->substream->runtime->periods;
626 /* Set delta to zero, as the frame_count value is too
627 * high (otherwise the code path will not be executed).
628 * This corrects the fact that the frame_count is too
629 * low at the beginning due to buffering. */
630 delta = 0;
631 } 659 }
660 pi->current_period = i;
661
662 /*
663 * Check the frame count. The DMA tends to get a bit
664 * ahead of the frame counter, which confuses the core.
665 */
666 fc = in_le32(&i2sdev->intfregs->frame_count);
667 nframes = i * runtime->period_size;
668 if (fc < pi->frame_count + nframes)
669 pi->frame_count = fc - nframes;
632 } 670 }
633 671
634 pi->frame_count = fc - delta; 672 if (dma_stopped) {
635 pi->current_period %= pi->substream->runtime->periods; 673 timeout = 1000;
674 for (;;) {
675 status = in_le32(&pi->dbdma->status);
676 if (!(status & ACTIVE) && (!in || (status & 0x80)))
677 break;
678 if (--timeout <= 0) {
679 printk(KERN_ERR "i2sbus: timed out "
680 "waiting for DMA to stop!\n");
681 break;
682 }
683 udelay(1);
684 }
685
686 /* Turn off DMA controller, clear S0 bit */
687 out_le32(&pi->dbdma->control, (RUN | PAUSE | 1) << 16);
688
689 pi->dbdma_ring.stopping = 0;
690 if (pi->stop_completion)
691 complete(pi->stop_completion);
692 }
636 693
694 if (!pi->dbdma_ring.running)
695 goto out_unlock;
637 spin_unlock(&i2sdev->low_lock); 696 spin_unlock(&i2sdev->low_lock);
638 /* may call _trigger again, hence needs to be unlocked */ 697 /* may call _trigger again, hence needs to be unlocked */
639 snd_pcm_period_elapsed(pi->substream); 698 snd_pcm_period_elapsed(pi->substream);
640 return; 699 return;
700
641 out_unlock: 701 out_unlock:
642 spin_unlock(&i2sdev->low_lock); 702 spin_unlock(&i2sdev->low_lock);
643} 703}
@@ -718,7 +778,7 @@ static struct snd_pcm_ops i2sbus_playback_ops = {
718 .close = i2sbus_playback_close, 778 .close = i2sbus_playback_close,
719 .ioctl = snd_pcm_lib_ioctl, 779 .ioctl = snd_pcm_lib_ioctl,
720 .hw_params = i2sbus_hw_params, 780 .hw_params = i2sbus_hw_params,
721 .hw_free = i2sbus_hw_free, 781 .hw_free = i2sbus_playback_hw_free,
722 .prepare = i2sbus_playback_prepare, 782 .prepare = i2sbus_playback_prepare,
723 .trigger = i2sbus_playback_trigger, 783 .trigger = i2sbus_playback_trigger,
724 .pointer = i2sbus_playback_pointer, 784 .pointer = i2sbus_playback_pointer,
@@ -788,7 +848,7 @@ static struct snd_pcm_ops i2sbus_record_ops = {
788 .close = i2sbus_record_close, 848 .close = i2sbus_record_close,
789 .ioctl = snd_pcm_lib_ioctl, 849 .ioctl = snd_pcm_lib_ioctl,
790 .hw_params = i2sbus_hw_params, 850 .hw_params = i2sbus_hw_params,
791 .hw_free = i2sbus_hw_free, 851 .hw_free = i2sbus_record_hw_free,
792 .prepare = i2sbus_record_prepare, 852 .prepare = i2sbus_record_prepare,
793 .trigger = i2sbus_record_trigger, 853 .trigger = i2sbus_record_trigger,
794 .pointer = i2sbus_record_pointer, 854 .pointer = i2sbus_record_pointer,
@@ -812,7 +872,6 @@ static void i2sbus_private_free(struct snd_pcm *pcm)
812 module_put(THIS_MODULE); 872 module_put(THIS_MODULE);
813} 873}
814 874
815/* FIXME: this function needs an error handling strategy with labels */
816int 875int
817i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card, 876i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
818 struct codec_info *ci, void *data) 877 struct codec_info *ci, void *data)
@@ -880,41 +939,31 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
880 if (!cii->sdev) { 939 if (!cii->sdev) {
881 printk(KERN_DEBUG 940 printk(KERN_DEBUG
882 "i2sbus: failed to get soundbus dev reference\n"); 941 "i2sbus: failed to get soundbus dev reference\n");
883 kfree(cii); 942 err = -ENODEV;
884 return -ENODEV; 943 goto out_free_cii;
885 } 944 }
886 945
887 if (!try_module_get(THIS_MODULE)) { 946 if (!try_module_get(THIS_MODULE)) {
888 printk(KERN_DEBUG "i2sbus: failed to get module reference!\n"); 947 printk(KERN_DEBUG "i2sbus: failed to get module reference!\n");
889 soundbus_dev_put(dev); 948 err = -EBUSY;
890 kfree(cii); 949 goto out_put_sdev;
891 return -EBUSY;
892 } 950 }
893 951
894 if (!try_module_get(ci->owner)) { 952 if (!try_module_get(ci->owner)) {
895 printk(KERN_DEBUG 953 printk(KERN_DEBUG
896 "i2sbus: failed to get module reference to codec owner!\n"); 954 "i2sbus: failed to get module reference to codec owner!\n");
897 module_put(THIS_MODULE); 955 err = -EBUSY;
898 soundbus_dev_put(dev); 956 goto out_put_this_module;
899 kfree(cii);
900 return -EBUSY;
901 } 957 }
902 958
903 if (!dev->pcm) { 959 if (!dev->pcm) {
904 err = snd_pcm_new(card, 960 err = snd_pcm_new(card, dev->pcmname, dev->pcmid, 0, 0,
905 dev->pcmname,
906 dev->pcmid,
907 0,
908 0,
909 &dev->pcm); 961 &dev->pcm);
910 if (err) { 962 if (err) {
911 printk(KERN_DEBUG "i2sbus: failed to create pcm\n"); 963 printk(KERN_DEBUG "i2sbus: failed to create pcm\n");
912 kfree(cii); 964 goto out_put_ci_module;
913 module_put(ci->owner);
914 soundbus_dev_put(dev);
915 module_put(THIS_MODULE);
916 return err;
917 } 965 }
966 dev->pcm->dev = &dev->ofdev.dev;
918 } 967 }
919 968
920 /* ALSA yet again sucks. 969 /* ALSA yet again sucks.
@@ -926,20 +975,12 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
926 /* eh? */ 975 /* eh? */
927 printk(KERN_ERR 976 printk(KERN_ERR
928 "Can't attach same bus to different cards!\n"); 977 "Can't attach same bus to different cards!\n");
929 module_put(ci->owner); 978 err = -EINVAL;
930 kfree(cii); 979 goto out_put_ci_module;
931 soundbus_dev_put(dev);
932 module_put(THIS_MODULE);
933 return -EINVAL;
934 }
935 if ((err =
936 snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1))) {
937 module_put(ci->owner);
938 kfree(cii);
939 soundbus_dev_put(dev);
940 module_put(THIS_MODULE);
941 return err;
942 } 980 }
981 err = snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 1);
982 if (err)
983 goto out_put_ci_module;
943 snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK, 984 snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_PLAYBACK,
944 &i2sbus_playback_ops); 985 &i2sbus_playback_ops);
945 i2sdev->out.created = 1; 986 i2sdev->out.created = 1;
@@ -949,20 +990,11 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
949 if (dev->pcm->card != card) { 990 if (dev->pcm->card != card) {
950 printk(KERN_ERR 991 printk(KERN_ERR
951 "Can't attach same bus to different cards!\n"); 992 "Can't attach same bus to different cards!\n");
952 module_put(ci->owner); 993 goto out_put_ci_module;
953 kfree(cii);
954 soundbus_dev_put(dev);
955 module_put(THIS_MODULE);
956 return -EINVAL;
957 }
958 if ((err =
959 snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1))) {
960 module_put(ci->owner);
961 kfree(cii);
962 soundbus_dev_put(dev);
963 module_put(THIS_MODULE);
964 return err;
965 } 994 }
995 err = snd_pcm_new_stream(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 1);
996 if (err)
997 goto out_put_ci_module;
966 snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE, 998 snd_pcm_set_ops(dev->pcm, SNDRV_PCM_STREAM_CAPTURE,
967 &i2sbus_record_ops); 999 &i2sbus_record_ops);
968 i2sdev->in.created = 1; 1000 i2sdev->in.created = 1;
@@ -977,11 +1009,7 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
977 err = snd_device_register(card, dev->pcm); 1009 err = snd_device_register(card, dev->pcm);
978 if (err) { 1010 if (err) {
979 printk(KERN_ERR "i2sbus: error registering new pcm\n"); 1011 printk(KERN_ERR "i2sbus: error registering new pcm\n");
980 module_put(ci->owner); 1012 goto out_put_ci_module;
981 kfree(cii);
982 soundbus_dev_put(dev);
983 module_put(THIS_MODULE);
984 return err;
985 } 1013 }
986 /* no errors any more, so let's add this to our list */ 1014 /* no errors any more, so let's add this to our list */
987 list_add(&cii->list, &dev->codec_list); 1015 list_add(&cii->list, &dev->codec_list);
@@ -996,6 +1024,15 @@ i2sbus_attach_codec(struct soundbus_dev *dev, struct snd_card *card,
996 64 * 1024, 64 * 1024); 1024 64 * 1024, 64 * 1024);
997 1025
998 return 0; 1026 return 0;
1027 out_put_ci_module:
1028 module_put(ci->owner);
1029 out_put_this_module:
1030 module_put(THIS_MODULE);
1031 out_put_sdev:
1032 soundbus_dev_put(dev);
1033 out_free_cii:
1034 kfree(cii);
1035 return err;
999} 1036}
1000 1037
1001void i2sbus_detach_codec(struct soundbus_dev *dev, void *data) 1038void i2sbus_detach_codec(struct soundbus_dev *dev, void *data)
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
index ec20ee615d7f..ff29654782c9 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus.h
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -10,6 +10,7 @@
10#include <linux/interrupt.h> 10#include <linux/interrupt.h>
11#include <linux/spinlock.h> 11#include <linux/spinlock.h>
12#include <linux/mutex.h> 12#include <linux/mutex.h>
13#include <linux/completion.h>
13 14
14#include <sound/pcm.h> 15#include <sound/pcm.h>
15 16
@@ -34,6 +35,7 @@ struct dbdma_command_mem {
34 void *space; 35 void *space;
35 int size; 36 int size;
36 u32 running:1; 37 u32 running:1;
38 u32 stopping:1;
37}; 39};
38 40
39struct pcm_info { 41struct pcm_info {
@@ -45,6 +47,7 @@ struct pcm_info {
45 u32 frame_count; 47 u32 frame_count;
46 struct dbdma_command_mem dbdma_ring; 48 struct dbdma_command_mem dbdma_ring;
47 volatile struct dbdma_regs __iomem *dbdma; 49 volatile struct dbdma_regs __iomem *dbdma;
50 struct completion *stop_completion;
48}; 51};
49 52
50enum { 53enum {
@@ -101,6 +104,9 @@ i2sbus_tx_intr(int irq, void *devid);
101extern irqreturn_t 104extern irqreturn_t
102i2sbus_rx_intr(int irq, void *devid); 105i2sbus_rx_intr(int irq, void *devid);
103 106
107extern void i2sbus_wait_for_stop_both(struct i2sbus_dev *i2sdev);
108extern void i2sbus_pcm_prepare_both(struct i2sbus_dev *i2sdev);
109
104/* control specific functions */ 110/* control specific functions */
105extern int i2sbus_control_init(struct macio_dev* dev, 111extern int i2sbus_control_init(struct macio_dev* dev,
106 struct i2sbus_control **c); 112 struct i2sbus_control **c);
diff --git a/sound/arm/aaci.h b/sound/arm/aaci.h
index 06295190606c..9175ff9ded01 100644
--- a/sound/arm/aaci.h
+++ b/sound/arm/aaci.h
@@ -228,7 +228,7 @@ struct aaci {
228 228
229 /* AC'97 */ 229 /* AC'97 */
230 struct mutex ac97_sem; 230 struct mutex ac97_sem;
231 ac97_bus_t *ac97_bus; 231 struct snd_ac97_bus *ac97_bus;
232 232
233 u32 maincr; 233 u32 maincr;
234 spinlock_t lock; 234 spinlock_t lock;
diff --git a/sound/core/control.c b/sound/core/control.c
index 0c7bcd62e5b2..42bcf2794b28 100644
--- a/sound/core/control.c
+++ b/sound/core/control.c
@@ -108,7 +108,6 @@ static void snd_ctl_empty_read_queue(struct snd_ctl_file * ctl)
108static int snd_ctl_release(struct inode *inode, struct file *file) 108static int snd_ctl_release(struct inode *inode, struct file *file)
109{ 109{
110 unsigned long flags; 110 unsigned long flags;
111 struct list_head *list;
112 struct snd_card *card; 111 struct snd_card *card;
113 struct snd_ctl_file *ctl; 112 struct snd_ctl_file *ctl;
114 struct snd_kcontrol *control; 113 struct snd_kcontrol *control;
@@ -122,12 +121,10 @@ static int snd_ctl_release(struct inode *inode, struct file *file)
122 list_del(&ctl->list); 121 list_del(&ctl->list);
123 write_unlock_irqrestore(&card->ctl_files_rwlock, flags); 122 write_unlock_irqrestore(&card->ctl_files_rwlock, flags);
124 down_write(&card->controls_rwsem); 123 down_write(&card->controls_rwsem);
125 list_for_each(list, &card->controls) { 124 list_for_each_entry(control, &card->controls, list)
126 control = snd_kcontrol(list);
127 for (idx = 0; idx < control->count; idx++) 125 for (idx = 0; idx < control->count; idx++)
128 if (control->vd[idx].owner == ctl) 126 if (control->vd[idx].owner == ctl)
129 control->vd[idx].owner = NULL; 127 control->vd[idx].owner = NULL;
130 }
131 up_write(&card->controls_rwsem); 128 up_write(&card->controls_rwsem);
132 snd_ctl_empty_read_queue(ctl); 129 snd_ctl_empty_read_queue(ctl);
133 kfree(ctl); 130 kfree(ctl);
@@ -140,7 +137,6 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
140 struct snd_ctl_elem_id *id) 137 struct snd_ctl_elem_id *id)
141{ 138{
142 unsigned long flags; 139 unsigned long flags;
143 struct list_head *flist;
144 struct snd_ctl_file *ctl; 140 struct snd_ctl_file *ctl;
145 struct snd_kctl_event *ev; 141 struct snd_kctl_event *ev;
146 142
@@ -149,14 +145,11 @@ void snd_ctl_notify(struct snd_card *card, unsigned int mask,
149#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE) 145#if defined(CONFIG_SND_MIXER_OSS) || defined(CONFIG_SND_MIXER_OSS_MODULE)
150 card->mixer_oss_change_count++; 146 card->mixer_oss_change_count++;
151#endif 147#endif
152 list_for_each(flist, &card->ctl_files) { 148 list_for_each_entry(ctl, &card->ctl_files, list) {
153 struct list_head *elist;
154 ctl = snd_ctl_file(flist);
155 if (!ctl->subscribed) 149 if (!ctl->subscribed)
156 continue; 150 continue;
157 spin_lock_irqsave(&ctl->read_lock, flags); 151 spin_lock_irqsave(&ctl->read_lock, flags);
158 list_for_each(elist, &ctl->events) { 152 list_for_each_entry(ev, &ctl->events, list) {
159 ev = snd_kctl_event(elist);
160 if (ev->id.numid == id->numid) { 153 if (ev->id.numid == id->numid) {
161 ev->mask |= mask; 154 ev->mask |= mask;
162 goto _found; 155 goto _found;
@@ -190,7 +183,8 @@ EXPORT_SYMBOL(snd_ctl_notify);
190 * 183 *
191 * Returns the pointer of the new instance, or NULL on failure. 184 * Returns the pointer of the new instance, or NULL on failure.
192 */ 185 */
193struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, unsigned int access) 186static struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control,
187 unsigned int access)
194{ 188{
195 struct snd_kcontrol *kctl; 189 struct snd_kcontrol *kctl;
196 unsigned int idx; 190 unsigned int idx;
@@ -208,8 +202,6 @@ struct snd_kcontrol *snd_ctl_new(struct snd_kcontrol *control, unsigned int acce
208 return kctl; 202 return kctl;
209} 203}
210 204
211EXPORT_SYMBOL(snd_ctl_new);
212
213/** 205/**
214 * snd_ctl_new1 - create a control instance from the template 206 * snd_ctl_new1 - create a control instance from the template
215 * @ncontrol: the initialization record 207 * @ncontrol: the initialization record
@@ -277,11 +269,9 @@ EXPORT_SYMBOL(snd_ctl_free_one);
277static unsigned int snd_ctl_hole_check(struct snd_card *card, 269static unsigned int snd_ctl_hole_check(struct snd_card *card,
278 unsigned int count) 270 unsigned int count)
279{ 271{
280 struct list_head *list;
281 struct snd_kcontrol *kctl; 272 struct snd_kcontrol *kctl;
282 273
283 list_for_each(list, &card->controls) { 274 list_for_each_entry(kctl, &card->controls, list) {
284 kctl = snd_kcontrol(list);
285 if ((kctl->id.numid <= card->last_numid && 275 if ((kctl->id.numid <= card->last_numid &&
286 kctl->id.numid + kctl->count > card->last_numid) || 276 kctl->id.numid + kctl->count > card->last_numid) ||
287 (kctl->id.numid <= card->last_numid + count - 1 && 277 (kctl->id.numid <= card->last_numid + count - 1 &&
@@ -498,12 +488,10 @@ EXPORT_SYMBOL(snd_ctl_rename_id);
498 */ 488 */
499struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid) 489struct snd_kcontrol *snd_ctl_find_numid(struct snd_card *card, unsigned int numid)
500{ 490{
501 struct list_head *list;
502 struct snd_kcontrol *kctl; 491 struct snd_kcontrol *kctl;
503 492
504 snd_assert(card != NULL && numid != 0, return NULL); 493 snd_assert(card != NULL && numid != 0, return NULL);
505 list_for_each(list, &card->controls) { 494 list_for_each_entry(kctl, &card->controls, list) {
506 kctl = snd_kcontrol(list);
507 if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid) 495 if (kctl->id.numid <= numid && kctl->id.numid + kctl->count > numid)
508 return kctl; 496 return kctl;
509 } 497 }
@@ -527,14 +515,12 @@ EXPORT_SYMBOL(snd_ctl_find_numid);
527struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card, 515struct snd_kcontrol *snd_ctl_find_id(struct snd_card *card,
528 struct snd_ctl_elem_id *id) 516 struct snd_ctl_elem_id *id)
529{ 517{
530 struct list_head *list;
531 struct snd_kcontrol *kctl; 518 struct snd_kcontrol *kctl;
532 519
533 snd_assert(card != NULL && id != NULL, return NULL); 520 snd_assert(card != NULL && id != NULL, return NULL);
534 if (id->numid != 0) 521 if (id->numid != 0)
535 return snd_ctl_find_numid(card, id->numid); 522 return snd_ctl_find_numid(card, id->numid);
536 list_for_each(list, &card->controls) { 523 list_for_each_entry(kctl, &card->controls, list) {
537 kctl = snd_kcontrol(list);
538 if (kctl->id.iface != id->iface) 524 if (kctl->id.iface != id->iface)
539 continue; 525 continue;
540 if (kctl->id.device != id->device) 526 if (kctl->id.device != id->device)
@@ -1182,7 +1168,6 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
1182{ 1168{
1183 struct snd_ctl_file *ctl; 1169 struct snd_ctl_file *ctl;
1184 struct snd_card *card; 1170 struct snd_card *card;
1185 struct list_head *list;
1186 struct snd_kctl_ioctl *p; 1171 struct snd_kctl_ioctl *p;
1187 void __user *argp = (void __user *)arg; 1172 void __user *argp = (void __user *)arg;
1188 int __user *ip = argp; 1173 int __user *ip = argp;
@@ -1232,8 +1217,7 @@ static long snd_ctl_ioctl(struct file *file, unsigned int cmd, unsigned long arg
1232#endif 1217#endif
1233 } 1218 }
1234 down_read(&snd_ioctl_rwsem); 1219 down_read(&snd_ioctl_rwsem);
1235 list_for_each(list, &snd_control_ioctls) { 1220 list_for_each_entry(p, &snd_control_ioctls, list) {
1236 p = list_entry(list, struct snd_kctl_ioctl, list);
1237 err = p->fioctl(card, ctl, cmd, arg); 1221 err = p->fioctl(card, ctl, cmd, arg);
1238 if (err != -ENOIOCTLCMD) { 1222 if (err != -ENOIOCTLCMD) {
1239 up_read(&snd_ioctl_rwsem); 1223 up_read(&snd_ioctl_rwsem);
@@ -1357,13 +1341,11 @@ EXPORT_SYMBOL(snd_ctl_register_ioctl_compat);
1357static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn, 1341static int _snd_ctl_unregister_ioctl(snd_kctl_ioctl_func_t fcn,
1358 struct list_head *lists) 1342 struct list_head *lists)
1359{ 1343{
1360 struct list_head *list;
1361 struct snd_kctl_ioctl *p; 1344 struct snd_kctl_ioctl *p;
1362 1345
1363 snd_assert(fcn != NULL, return -EINVAL); 1346 snd_assert(fcn != NULL, return -EINVAL);
1364 down_write(&snd_ioctl_rwsem); 1347 down_write(&snd_ioctl_rwsem);
1365 list_for_each(list, lists) { 1348 list_for_each_entry(p, lists, list) {
1366 p = list_entry(list, struct snd_kctl_ioctl, list);
1367 if (p->fioctl == fcn) { 1349 if (p->fioctl == fcn) {
1368 list_del(&p->list); 1350 list_del(&p->list);
1369 up_write(&snd_ioctl_rwsem); 1351 up_write(&snd_ioctl_rwsem);
@@ -1453,7 +1435,6 @@ static int snd_ctl_dev_register(struct snd_device *device)
1453static int snd_ctl_dev_disconnect(struct snd_device *device) 1435static int snd_ctl_dev_disconnect(struct snd_device *device)
1454{ 1436{
1455 struct snd_card *card = device->device_data; 1437 struct snd_card *card = device->device_data;
1456 struct list_head *flist;
1457 struct snd_ctl_file *ctl; 1438 struct snd_ctl_file *ctl;
1458 int err, cardnum; 1439 int err, cardnum;
1459 1440
@@ -1462,8 +1443,7 @@ static int snd_ctl_dev_disconnect(struct snd_device *device)
1462 snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO); 1443 snd_assert(cardnum >= 0 && cardnum < SNDRV_CARDS, return -ENXIO);
1463 1444
1464 down_read(&card->controls_rwsem); 1445 down_read(&card->controls_rwsem);
1465 list_for_each(flist, &card->ctl_files) { 1446 list_for_each_entry(ctl, &card->ctl_files, list) {
1466 ctl = snd_ctl_file(flist);
1467 wake_up(&ctl->change_sleep); 1447 wake_up(&ctl->change_sleep);
1468 kill_fasync(&ctl->fasync, SIGIO, POLL_ERR); 1448 kill_fasync(&ctl->fasync, SIGIO, POLL_ERR);
1469 } 1449 }
diff --git a/sound/core/control_compat.c b/sound/core/control_compat.c
index ab48962c48ce..9311ca397bbc 100644
--- a/sound/core/control_compat.c
+++ b/sound/core/control_compat.c
@@ -392,7 +392,7 @@ enum {
392static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg) 392static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
393{ 393{
394 struct snd_ctl_file *ctl; 394 struct snd_ctl_file *ctl;
395 struct list_head *list; 395 struct snd_kctl_ioctl *p;
396 void __user *argp = compat_ptr(arg); 396 void __user *argp = compat_ptr(arg);
397 int err; 397 int err;
398 398
@@ -427,8 +427,7 @@ static inline long snd_ctl_ioctl_compat(struct file *file, unsigned int cmd, uns
427 } 427 }
428 428
429 down_read(&snd_ioctl_rwsem); 429 down_read(&snd_ioctl_rwsem);
430 list_for_each(list, &snd_control_compat_ioctls) { 430 list_for_each_entry(p, &snd_control_compat_ioctls, list) {
431 struct snd_kctl_ioctl *p = list_entry(list, struct snd_kctl_ioctl, list);
432 if (p->fioctl) { 431 if (p->fioctl) {
433 err = p->fioctl(ctl->card, ctl, cmd, arg); 432 err = p->fioctl(ctl->card, ctl, cmd, arg);
434 if (err != -ENOIOCTLCMD) { 433 if (err != -ENOIOCTLCMD) {
diff --git a/sound/core/device.c b/sound/core/device.c
index ccb25816ac9e..5858b02b0b1d 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -79,13 +79,11 @@ EXPORT_SYMBOL(snd_device_new);
79 */ 79 */
80int snd_device_free(struct snd_card *card, void *device_data) 80int snd_device_free(struct snd_card *card, void *device_data)
81{ 81{
82 struct list_head *list;
83 struct snd_device *dev; 82 struct snd_device *dev;
84 83
85 snd_assert(card != NULL, return -ENXIO); 84 snd_assert(card != NULL, return -ENXIO);
86 snd_assert(device_data != NULL, return -ENXIO); 85 snd_assert(device_data != NULL, return -ENXIO);
87 list_for_each(list, &card->devices) { 86 list_for_each_entry(dev, &card->devices, list) {
88 dev = snd_device(list);
89 if (dev->device_data != device_data) 87 if (dev->device_data != device_data)
90 continue; 88 continue;
91 /* unlink */ 89 /* unlink */
@@ -124,13 +122,11 @@ EXPORT_SYMBOL(snd_device_free);
124 */ 122 */
125int snd_device_disconnect(struct snd_card *card, void *device_data) 123int snd_device_disconnect(struct snd_card *card, void *device_data)
126{ 124{
127 struct list_head *list;
128 struct snd_device *dev; 125 struct snd_device *dev;
129 126
130 snd_assert(card != NULL, return -ENXIO); 127 snd_assert(card != NULL, return -ENXIO);
131 snd_assert(device_data != NULL, return -ENXIO); 128 snd_assert(device_data != NULL, return -ENXIO);
132 list_for_each(list, &card->devices) { 129 list_for_each_entry(dev, &card->devices, list) {
133 dev = snd_device(list);
134 if (dev->device_data != device_data) 130 if (dev->device_data != device_data)
135 continue; 131 continue;
136 if (dev->state == SNDRV_DEV_REGISTERED && 132 if (dev->state == SNDRV_DEV_REGISTERED &&
@@ -161,14 +157,12 @@ int snd_device_disconnect(struct snd_card *card, void *device_data)
161 */ 157 */
162int snd_device_register(struct snd_card *card, void *device_data) 158int snd_device_register(struct snd_card *card, void *device_data)
163{ 159{
164 struct list_head *list;
165 struct snd_device *dev; 160 struct snd_device *dev;
166 int err; 161 int err;
167 162
168 snd_assert(card != NULL, return -ENXIO); 163 snd_assert(card != NULL, return -ENXIO);
169 snd_assert(device_data != NULL, return -ENXIO); 164 snd_assert(device_data != NULL, return -ENXIO);
170 list_for_each(list, &card->devices) { 165 list_for_each_entry(dev, &card->devices, list) {
171 dev = snd_device(list);
172 if (dev->device_data != device_data) 166 if (dev->device_data != device_data)
173 continue; 167 continue;
174 if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { 168 if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
@@ -192,13 +186,11 @@ EXPORT_SYMBOL(snd_device_register);
192 */ 186 */
193int snd_device_register_all(struct snd_card *card) 187int snd_device_register_all(struct snd_card *card)
194{ 188{
195 struct list_head *list;
196 struct snd_device *dev; 189 struct snd_device *dev;
197 int err; 190 int err;
198 191
199 snd_assert(card != NULL, return -ENXIO); 192 snd_assert(card != NULL, return -ENXIO);
200 list_for_each(list, &card->devices) { 193 list_for_each_entry(dev, &card->devices, list) {
201 dev = snd_device(list);
202 if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) { 194 if (dev->state == SNDRV_DEV_BUILD && dev->ops->dev_register) {
203 if ((err = dev->ops->dev_register(dev)) < 0) 195 if ((err = dev->ops->dev_register(dev)) < 0)
204 return err; 196 return err;
@@ -215,12 +207,10 @@ int snd_device_register_all(struct snd_card *card)
215int snd_device_disconnect_all(struct snd_card *card) 207int snd_device_disconnect_all(struct snd_card *card)
216{ 208{
217 struct snd_device *dev; 209 struct snd_device *dev;
218 struct list_head *list;
219 int err = 0; 210 int err = 0;
220 211
221 snd_assert(card != NULL, return -ENXIO); 212 snd_assert(card != NULL, return -ENXIO);
222 list_for_each(list, &card->devices) { 213 list_for_each_entry(dev, &card->devices, list) {
223 dev = snd_device(list);
224 if (snd_device_disconnect(card, dev->device_data) < 0) 214 if (snd_device_disconnect(card, dev->device_data) < 0)
225 err = -ENXIO; 215 err = -ENXIO;
226 } 216 }
@@ -234,7 +224,6 @@ int snd_device_disconnect_all(struct snd_card *card)
234int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd) 224int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd)
235{ 225{
236 struct snd_device *dev; 226 struct snd_device *dev;
237 struct list_head *list;
238 int err; 227 int err;
239 unsigned int range_low, range_high; 228 unsigned int range_low, range_high;
240 229
@@ -242,8 +231,7 @@ int snd_device_free_all(struct snd_card *card, snd_device_cmd_t cmd)
242 range_low = cmd * SNDRV_DEV_TYPE_RANGE_SIZE; 231 range_low = cmd * SNDRV_DEV_TYPE_RANGE_SIZE;
243 range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1; 232 range_high = range_low + SNDRV_DEV_TYPE_RANGE_SIZE - 1;
244 __again: 233 __again:
245 list_for_each(list, &card->devices) { 234 list_for_each_entry(dev, &card->devices, list) {
246 dev = snd_device(list);
247 if (dev->type >= range_low && dev->type <= range_high) { 235 if (dev->type >= range_low && dev->type <= range_high) {
248 if ((err = snd_device_free(card, dev->device_data)) < 0) 236 if ((err = snd_device_free(card, dev->device_data)) < 0)
249 return err; 237 return err;
diff --git a/sound/core/hwdep.c b/sound/core/hwdep.c
index 46b47689362c..39c03f3dfbfa 100644
--- a/sound/core/hwdep.c
+++ b/sound/core/hwdep.c
@@ -47,14 +47,11 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device);
47 47
48static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device) 48static struct snd_hwdep *snd_hwdep_search(struct snd_card *card, int device)
49{ 49{
50 struct list_head *p;
51 struct snd_hwdep *hwdep; 50 struct snd_hwdep *hwdep;
52 51
53 list_for_each(p, &snd_hwdep_devices) { 52 list_for_each_entry(hwdep, &snd_hwdep_devices, list)
54 hwdep = list_entry(p, struct snd_hwdep, list);
55 if (hwdep->card == card && hwdep->device == device) 53 if (hwdep->card == card && hwdep->device == device)
56 return hwdep; 54 return hwdep;
57 }
58 return NULL; 55 return NULL;
59} 56}
60 57
@@ -159,15 +156,16 @@ static int snd_hwdep_release(struct inode *inode, struct file * file)
159 int err = -ENXIO; 156 int err = -ENXIO;
160 struct snd_hwdep *hw = file->private_data; 157 struct snd_hwdep *hw = file->private_data;
161 struct module *mod = hw->card->module; 158 struct module *mod = hw->card->module;
159
162 mutex_lock(&hw->open_mutex); 160 mutex_lock(&hw->open_mutex);
163 if (hw->ops.release) { 161 if (hw->ops.release)
164 err = hw->ops.release(hw, file); 162 err = hw->ops.release(hw, file);
165 wake_up(&hw->open_wait);
166 }
167 if (hw->used > 0) 163 if (hw->used > 0)
168 hw->used--; 164 hw->used--;
169 snd_card_file_remove(hw->card, file);
170 mutex_unlock(&hw->open_mutex); 165 mutex_unlock(&hw->open_mutex);
166 wake_up(&hw->open_wait);
167
168 snd_card_file_remove(hw->card, file);
171 module_put(mod); 169 module_put(mod);
172 return err; 170 return err;
173} 171}
@@ -468,15 +466,12 @@ static int snd_hwdep_dev_disconnect(struct snd_device *device)
468static void snd_hwdep_proc_read(struct snd_info_entry *entry, 466static void snd_hwdep_proc_read(struct snd_info_entry *entry,
469 struct snd_info_buffer *buffer) 467 struct snd_info_buffer *buffer)
470{ 468{
471 struct list_head *p;
472 struct snd_hwdep *hwdep; 469 struct snd_hwdep *hwdep;
473 470
474 mutex_lock(&register_mutex); 471 mutex_lock(&register_mutex);
475 list_for_each(p, &snd_hwdep_devices) { 472 list_for_each_entry(hwdep, &snd_hwdep_devices, list)
476 hwdep = list_entry(p, struct snd_hwdep, list);
477 snd_iprintf(buffer, "%02i-%02i: %s\n", 473 snd_iprintf(buffer, "%02i-%02i: %s\n",
478 hwdep->card->number, hwdep->device, hwdep->name); 474 hwdep->card->number, hwdep->device, hwdep->name);
479 }
480 mutex_unlock(&register_mutex); 475 mutex_unlock(&register_mutex);
481} 476}
482 477
diff --git a/sound/core/init.c b/sound/core/init.c
index a4cc6b155ae9..db6103733742 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -114,22 +114,28 @@ struct snd_card *snd_card_new(int idx, const char *xid,
114 if (idx < 0) { 114 if (idx < 0) {
115 int idx2; 115 int idx2;
116 for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++) 116 for (idx2 = 0; idx2 < SNDRV_CARDS; idx2++)
117 /* idx == -1 == 0xffff means: take any free slot */
117 if (~snd_cards_lock & idx & 1<<idx2) { 118 if (~snd_cards_lock & idx & 1<<idx2) {
118 idx = idx2; 119 idx = idx2;
119 if (idx >= snd_ecards_limit) 120 if (idx >= snd_ecards_limit)
120 snd_ecards_limit = idx + 1; 121 snd_ecards_limit = idx + 1;
121 break; 122 break;
122 } 123 }
123 } else if (idx < snd_ecards_limit) { 124 } else {
124 if (snd_cards_lock & (1 << idx)) 125 if (idx < snd_ecards_limit) {
125 err = -ENODEV; /* invalid */ 126 if (snd_cards_lock & (1 << idx))
126 } else if (idx < SNDRV_CARDS) 127 err = -EBUSY; /* invalid */
127 snd_ecards_limit = idx + 1; /* increase the limit */ 128 } else {
128 else 129 if (idx < SNDRV_CARDS)
129 err = -ENODEV; 130 snd_ecards_limit = idx + 1; /* increase the limit */
131 else
132 err = -ENODEV;
133 }
134 }
130 if (idx < 0 || err < 0) { 135 if (idx < 0 || err < 0) {
131 mutex_unlock(&snd_card_mutex); 136 mutex_unlock(&snd_card_mutex);
132 snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i)\n", idx, snd_ecards_limit - 1); 137 snd_printk(KERN_ERR "cannot find the slot for index %d (range 0-%i), error: %d\n",
138 idx, snd_ecards_limit - 1, err);
133 goto __error; 139 goto __error;
134 } 140 }
135 snd_cards_lock |= 1 << idx; /* lock it */ 141 snd_cards_lock |= 1 << idx; /* lock it */
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c
index bc0bd0910a62..f057430db0d0 100644
--- a/sound/core/memalloc.c
+++ b/sound/core/memalloc.c
@@ -406,19 +406,17 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab)
406 */ 406 */
407size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id) 407size_t snd_dma_get_reserved_buf(struct snd_dma_buffer *dmab, unsigned int id)
408{ 408{
409 struct list_head *p;
410 struct snd_mem_list *mem; 409 struct snd_mem_list *mem;
411 410
412 snd_assert(dmab, return 0); 411 snd_assert(dmab, return 0);
413 412
414 mutex_lock(&list_mutex); 413 mutex_lock(&list_mutex);
415 list_for_each(p, &mem_list_head) { 414 list_for_each_entry(mem, &mem_list_head, list) {
416 mem = list_entry(p, struct snd_mem_list, list);
417 if (mem->id == id && 415 if (mem->id == id &&
418 (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL || 416 (mem->buffer.dev.dev == NULL || dmab->dev.dev == NULL ||
419 ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) { 417 ! memcmp(&mem->buffer.dev, &dmab->dev, sizeof(dmab->dev)))) {
420 struct device *dev = dmab->dev.dev; 418 struct device *dev = dmab->dev.dev;
421 list_del(p); 419 list_del(&mem->list);
422 *dmab = mem->buffer; 420 *dmab = mem->buffer;
423 if (dmab->dev.dev == NULL) 421 if (dmab->dev.dev == NULL)
424 dmab->dev.dev = dev; 422 dmab->dev.dev = dev;
@@ -488,7 +486,6 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
488{ 486{
489 int len = 0; 487 int len = 0;
490 long pages = snd_allocated_pages >> (PAGE_SHIFT-12); 488 long pages = snd_allocated_pages >> (PAGE_SHIFT-12);
491 struct list_head *p;
492 struct snd_mem_list *mem; 489 struct snd_mem_list *mem;
493 int devno; 490 int devno;
494 static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" }; 491 static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" };
@@ -498,8 +495,7 @@ static int snd_mem_proc_read(char *page, char **start, off_t off,
498 "pages : %li bytes (%li pages per %likB)\n", 495 "pages : %li bytes (%li pages per %likB)\n",
499 pages * PAGE_SIZE, pages, PAGE_SIZE / 1024); 496 pages * PAGE_SIZE, pages, PAGE_SIZE / 1024);
500 devno = 0; 497 devno = 0;
501 list_for_each(p, &mem_list_head) { 498 list_for_each_entry(mem, &mem_list_head, list) {
502 mem = list_entry(p, struct snd_mem_list, list);
503 devno++; 499 devno++;
504 len += snprintf(page + len, count - len, 500 len += snprintf(page + len, count - len,
505 "buffer %d : ID %08x : type %s\n", 501 "buffer %d : ID %08x : type %s\n",
diff --git a/sound/core/misc.c b/sound/core/misc.c
index 03fc711f4127..6db86a7c9704 100644
--- a/sound/core/misc.c
+++ b/sound/core/misc.c
@@ -78,3 +78,31 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
78 78
79EXPORT_SYMBOL(snd_verbose_printd); 79EXPORT_SYMBOL(snd_verbose_printd);
80#endif 80#endif
81
82#ifdef CONFIG_PCI
83#include <linux/pci.h>
84/**
85 * snd_pci_quirk_lookup - look up a PCI SSID quirk list
86 * @pci: pci_dev handle
87 * @list: quirk list, terminated by a null entry
88 *
89 * Look through the given quirk list and finds a matching entry
90 * with the same PCI SSID. When subdevice is 0, all subdevice
91 * values may match.
92 *
93 * Returns the matched entry pointer, or NULL if nothing matched.
94 */
95const struct snd_pci_quirk *
96snd_pci_quirk_lookup(struct pci_dev *pci, const struct snd_pci_quirk *list)
97{
98 const struct snd_pci_quirk *q;
99
100 for (q = list; q->subvendor; q++)
101 if (q->subvendor == pci->subsystem_vendor &&
102 (!q->subdevice || q->subdevice == pci->subsystem_device))
103 return q;
104 return NULL;
105}
106
107EXPORT_SYMBOL(snd_pci_quirk_lookup);
108#endif
diff --git a/sound/core/pcm.c b/sound/core/pcm.c
index 8e0189885516..2743414fc8fa 100644
--- a/sound/core/pcm.c
+++ b/sound/core/pcm.c
@@ -45,11 +45,9 @@ static int snd_pcm_dev_disconnect(struct snd_device *device);
45 45
46static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device) 46static struct snd_pcm *snd_pcm_search(struct snd_card *card, int device)
47{ 47{
48 struct list_head *p;
49 struct snd_pcm *pcm; 48 struct snd_pcm *pcm;
50 49
51 list_for_each(p, &snd_pcm_devices) { 50 list_for_each_entry(pcm, &snd_pcm_devices, list) {
52 pcm = list_entry(p, struct snd_pcm, list);
53 if (pcm->card == card && pcm->device == device) 51 if (pcm->card == card && pcm->device == device)
54 return pcm; 52 return pcm;
55 } 53 }
@@ -782,7 +780,6 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
782 struct snd_pcm_runtime *runtime; 780 struct snd_pcm_runtime *runtime;
783 struct snd_ctl_file *kctl; 781 struct snd_ctl_file *kctl;
784 struct snd_card *card; 782 struct snd_card *card;
785 struct list_head *list;
786 int prefer_subdevice = -1; 783 int prefer_subdevice = -1;
787 size_t size; 784 size_t size;
788 785
@@ -795,8 +792,7 @@ int snd_pcm_attach_substream(struct snd_pcm *pcm, int stream,
795 792
796 card = pcm->card; 793 card = pcm->card;
797 down_read(&card->controls_rwsem); 794 down_read(&card->controls_rwsem);
798 list_for_each(list, &card->ctl_files) { 795 list_for_each_entry(kctl, &card->ctl_files, list) {
799 kctl = snd_ctl_file(list);
800 if (kctl->pid == current->pid) { 796 if (kctl->pid == current->pid) {
801 prefer_subdevice = kctl->prefer_pcm_subdevice; 797 prefer_subdevice = kctl->prefer_pcm_subdevice;
802 if (prefer_subdevice != -1) 798 if (prefer_subdevice != -1)
@@ -941,9 +937,10 @@ static int snd_pcm_dev_register(struct snd_device *device)
941{ 937{
942 int cidx, err; 938 int cidx, err;
943 struct snd_pcm_substream *substream; 939 struct snd_pcm_substream *substream;
944 struct list_head *list; 940 struct snd_pcm_notify *notify;
945 char str[16]; 941 char str[16];
946 struct snd_pcm *pcm = device->device_data; 942 struct snd_pcm *pcm = device->device_data;
943 struct device *dev;
947 944
948 snd_assert(pcm != NULL && device != NULL, return -ENXIO); 945 snd_assert(pcm != NULL && device != NULL, return -ENXIO);
949 mutex_lock(&register_mutex); 946 mutex_lock(&register_mutex);
@@ -966,11 +963,18 @@ static int snd_pcm_dev_register(struct snd_device *device)
966 devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE; 963 devtype = SNDRV_DEVICE_TYPE_PCM_CAPTURE;
967 break; 964 break;
968 } 965 }
969 if ((err = snd_register_device(devtype, pcm->card, 966 /* device pointer to use, pcm->dev takes precedence if
970 pcm->device, 967 * it is assigned, otherwise fall back to card's device
971 &snd_pcm_f_ops[cidx], 968 * if possible */
972 pcm, str)) < 0) 969 dev = pcm->dev;
973 { 970 if (!dev)
971 dev = snd_card_get_device_link(pcm->card);
972 /* register pcm */
973 err = snd_register_device_for_dev(devtype, pcm->card,
974 pcm->device,
975 &snd_pcm_f_ops[cidx],
976 pcm, str, dev);
977 if (err < 0) {
974 list_del(&pcm->list); 978 list_del(&pcm->list);
975 mutex_unlock(&register_mutex); 979 mutex_unlock(&register_mutex);
976 return err; 980 return err;
@@ -980,11 +984,10 @@ static int snd_pcm_dev_register(struct snd_device *device)
980 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next) 984 for (substream = pcm->streams[cidx].substream; substream; substream = substream->next)
981 snd_pcm_timer_init(substream); 985 snd_pcm_timer_init(substream);
982 } 986 }
983 list_for_each(list, &snd_pcm_notify_list) { 987
984 struct snd_pcm_notify *notify; 988 list_for_each_entry(notify, &snd_pcm_notify_list, list)
985 notify = list_entry(list, struct snd_pcm_notify, list);
986 notify->n_register(pcm); 989 notify->n_register(pcm);
987 } 990
988 mutex_unlock(&register_mutex); 991 mutex_unlock(&register_mutex);
989 return 0; 992 return 0;
990} 993}
@@ -1027,7 +1030,7 @@ static int snd_pcm_dev_disconnect(struct snd_device *device)
1027 1030
1028int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree) 1031int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
1029{ 1032{
1030 struct list_head *p; 1033 struct snd_pcm *pcm;
1031 1034
1032 snd_assert(notify != NULL && 1035 snd_assert(notify != NULL &&
1033 notify->n_register != NULL && 1036 notify->n_register != NULL &&
@@ -1036,13 +1039,12 @@ int snd_pcm_notify(struct snd_pcm_notify *notify, int nfree)
1036 mutex_lock(&register_mutex); 1039 mutex_lock(&register_mutex);
1037 if (nfree) { 1040 if (nfree) {
1038 list_del(&notify->list); 1041 list_del(&notify->list);
1039 list_for_each(p, &snd_pcm_devices) 1042 list_for_each_entry(pcm, &snd_pcm_devices, list)
1040 notify->n_unregister(list_entry(p, 1043 notify->n_unregister(pcm);
1041 struct snd_pcm, list));
1042 } else { 1044 } else {
1043 list_add_tail(&notify->list, &snd_pcm_notify_list); 1045 list_add_tail(&notify->list, &snd_pcm_notify_list);
1044 list_for_each(p, &snd_pcm_devices) 1046 list_for_each_entry(pcm, &snd_pcm_devices, list)
1045 notify->n_register(list_entry(p, struct snd_pcm, list)); 1047 notify->n_register(pcm);
1046 } 1048 }
1047 mutex_unlock(&register_mutex); 1049 mutex_unlock(&register_mutex);
1048 return 0; 1050 return 0;
@@ -1058,12 +1060,10 @@ EXPORT_SYMBOL(snd_pcm_notify);
1058static void snd_pcm_proc_read(struct snd_info_entry *entry, 1060static void snd_pcm_proc_read(struct snd_info_entry *entry,
1059 struct snd_info_buffer *buffer) 1061 struct snd_info_buffer *buffer)
1060{ 1062{
1061 struct list_head *p;
1062 struct snd_pcm *pcm; 1063 struct snd_pcm *pcm;
1063 1064
1064 mutex_lock(&register_mutex); 1065 mutex_lock(&register_mutex);
1065 list_for_each(p, &snd_pcm_devices) { 1066 list_for_each_entry(pcm, &snd_pcm_devices, list) {
1066 pcm = list_entry(p, struct snd_pcm, list);
1067 snd_iprintf(buffer, "%02i-%02i: %s : %s", 1067 snd_iprintf(buffer, "%02i-%02i: %s : %s",
1068 pcm->card->number, pcm->device, pcm->id, pcm->name); 1068 pcm->card->number, pcm->device, pcm->id, pcm->name);
1069 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) 1069 if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c
index b336797be4fc..9fefcaa2c324 100644
--- a/sound/core/pcm_lib.c
+++ b/sound/core/pcm_lib.c
@@ -781,6 +781,11 @@ int snd_interval_list(struct snd_interval *i, unsigned int count, unsigned int *
781{ 781{
782 unsigned int k; 782 unsigned int k;
783 int changed = 0; 783 int changed = 0;
784
785 if (!count) {
786 i->empty = 1;
787 return -EINVAL;
788 }
784 for (k = 0; k < count; k++) { 789 for (k = 0; k < count; k++) {
785 if (mask && !(mask & (1 << k))) 790 if (mask && !(mask & (1 << k)))
786 continue; 791 continue;
diff --git a/sound/core/pcm_memory.c b/sound/core/pcm_memory.c
index be030cb4d373..95b1b2f0b1e2 100644
--- a/sound/core/pcm_memory.c
+++ b/sound/core/pcm_memory.c
@@ -101,6 +101,8 @@ int snd_pcm_lib_preallocate_free(struct snd_pcm_substream *substream)
101{ 101{
102 snd_pcm_lib_preallocate_dma_free(substream); 102 snd_pcm_lib_preallocate_dma_free(substream);
103#ifdef CONFIG_SND_VERBOSE_PROCFS 103#ifdef CONFIG_SND_VERBOSE_PROCFS
104 snd_info_free_entry(substream->proc_prealloc_max_entry);
105 substream->proc_prealloc_max_entry = NULL;
104 snd_info_free_entry(substream->proc_prealloc_entry); 106 snd_info_free_entry(substream->proc_prealloc_entry);
105 substream->proc_prealloc_entry = NULL; 107 substream->proc_prealloc_entry = NULL;
106#endif 108#endif
@@ -142,6 +144,18 @@ static void snd_pcm_lib_preallocate_proc_read(struct snd_info_entry *entry,
142} 144}
143 145
144/* 146/*
147 * read callback for prealloc_max proc file
148 *
149 * prints the maximum allowed size in kB.
150 */
151static void snd_pcm_lib_preallocate_max_proc_read(struct snd_info_entry *entry,
152 struct snd_info_buffer *buffer)
153{
154 struct snd_pcm_substream *substream = entry->private_data;
155 snd_iprintf(buffer, "%lu\n", (unsigned long) substream->dma_max / 1024);
156}
157
158/*
145 * write callback for prealloc proc file 159 * write callback for prealloc proc file
146 * 160 *
147 * accepts the preallocation size in kB. 161 * accepts the preallocation size in kB.
@@ -203,6 +217,15 @@ static inline void preallocate_info_init(struct snd_pcm_substream *substream)
203 } 217 }
204 } 218 }
205 substream->proc_prealloc_entry = entry; 219 substream->proc_prealloc_entry = entry;
220 if ((entry = snd_info_create_card_entry(substream->pcm->card, "prealloc_max", substream->proc_root)) != NULL) {
221 entry->c.text.read = snd_pcm_lib_preallocate_max_proc_read;
222 entry->private_data = substream;
223 if (snd_info_register(entry) < 0) {
224 snd_info_free_entry(entry);
225 entry = NULL;
226 }
227 }
228 substream->proc_prealloc_max_entry = entry;
206} 229}
207 230
208#else /* !CONFIG_SND_VERBOSE_PROCFS */ 231#else /* !CONFIG_SND_VERBOSE_PROCFS */
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index 0f055bfcbdac..7e6ceec738d5 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -61,14 +61,11 @@ static DEFINE_MUTEX(register_mutex);
61 61
62static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device) 62static struct snd_rawmidi *snd_rawmidi_search(struct snd_card *card, int device)
63{ 63{
64 struct list_head *p;
65 struct snd_rawmidi *rawmidi; 64 struct snd_rawmidi *rawmidi;
66 65
67 list_for_each(p, &snd_rawmidi_devices) { 66 list_for_each_entry(rawmidi, &snd_rawmidi_devices, list)
68 rawmidi = list_entry(p, struct snd_rawmidi, list);
69 if (rawmidi->card == card && rawmidi->device == device) 67 if (rawmidi->card == card && rawmidi->device == device)
70 return rawmidi; 68 return rawmidi;
71 }
72 return NULL; 69 return NULL;
73} 70}
74 71
@@ -389,7 +386,6 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
389 struct snd_rawmidi *rmidi; 386 struct snd_rawmidi *rmidi;
390 struct snd_rawmidi_file *rawmidi_file; 387 struct snd_rawmidi_file *rawmidi_file;
391 wait_queue_t wait; 388 wait_queue_t wait;
392 struct list_head *list;
393 struct snd_ctl_file *kctl; 389 struct snd_ctl_file *kctl;
394 390
395 if (maj == snd_major) { 391 if (maj == snd_major) {
@@ -426,8 +422,7 @@ static int snd_rawmidi_open(struct inode *inode, struct file *file)
426 while (1) { 422 while (1) {
427 subdevice = -1; 423 subdevice = -1;
428 down_read(&card->controls_rwsem); 424 down_read(&card->controls_rwsem);
429 list_for_each(list, &card->ctl_files) { 425 list_for_each_entry(kctl, &card->ctl_files, list) {
430 kctl = snd_ctl_file(list);
431 if (kctl->pid == current->pid) { 426 if (kctl->pid == current->pid) {
432 subdevice = kctl->prefer_rawmidi_subdevice; 427 subdevice = kctl->prefer_rawmidi_subdevice;
433 if (subdevice != -1) 428 if (subdevice != -1)
@@ -575,7 +570,6 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info
575 struct snd_rawmidi *rmidi; 570 struct snd_rawmidi *rmidi;
576 struct snd_rawmidi_str *pstr; 571 struct snd_rawmidi_str *pstr;
577 struct snd_rawmidi_substream *substream; 572 struct snd_rawmidi_substream *substream;
578 struct list_head *list;
579 573
580 mutex_lock(&register_mutex); 574 mutex_lock(&register_mutex);
581 rmidi = snd_rawmidi_search(card, info->device); 575 rmidi = snd_rawmidi_search(card, info->device);
@@ -589,8 +583,7 @@ int snd_rawmidi_info_select(struct snd_card *card, struct snd_rawmidi_info *info
589 return -ENOENT; 583 return -ENOENT;
590 if (info->subdevice >= pstr->substream_count) 584 if (info->subdevice >= pstr->substream_count)
591 return -ENXIO; 585 return -ENXIO;
592 list_for_each(list, &pstr->substreams) { 586 list_for_each_entry(substream, &pstr->substreams, list) {
593 substream = list_entry(list, struct snd_rawmidi_substream, list);
594 if ((unsigned int)substream->number == info->subdevice) 587 if ((unsigned int)substream->number == info->subdevice)
595 return snd_rawmidi_info(substream, info); 588 return snd_rawmidi_info(substream, info);
596 } 589 }
@@ -1313,14 +1306,14 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
1313 struct snd_rawmidi *rmidi; 1306 struct snd_rawmidi *rmidi;
1314 struct snd_rawmidi_substream *substream; 1307 struct snd_rawmidi_substream *substream;
1315 struct snd_rawmidi_runtime *runtime; 1308 struct snd_rawmidi_runtime *runtime;
1316 struct list_head *list;
1317 1309
1318 rmidi = entry->private_data; 1310 rmidi = entry->private_data;
1319 snd_iprintf(buffer, "%s\n\n", rmidi->name); 1311 snd_iprintf(buffer, "%s\n\n", rmidi->name);
1320 mutex_lock(&rmidi->open_mutex); 1312 mutex_lock(&rmidi->open_mutex);
1321 if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) { 1313 if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_OUTPUT) {
1322 list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams) { 1314 list_for_each_entry(substream,
1323 substream = list_entry(list, struct snd_rawmidi_substream, list); 1315 &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
1316 list) {
1324 snd_iprintf(buffer, 1317 snd_iprintf(buffer,
1325 "Output %d\n" 1318 "Output %d\n"
1326 " Tx bytes : %lu\n", 1319 " Tx bytes : %lu\n",
@@ -1339,8 +1332,9 @@ static void snd_rawmidi_proc_info_read(struct snd_info_entry *entry,
1339 } 1332 }
1340 } 1333 }
1341 if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT) { 1334 if (rmidi->info_flags & SNDRV_RAWMIDI_INFO_INPUT) {
1342 list_for_each(list, &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams) { 1335 list_for_each_entry(substream,
1343 substream = list_entry(list, struct snd_rawmidi_substream, list); 1336 &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams,
1337 list) {
1344 snd_iprintf(buffer, 1338 snd_iprintf(buffer,
1345 "Input %d\n" 1339 "Input %d\n"
1346 " Rx bytes : %lu\n", 1340 " Rx bytes : %lu\n",
@@ -1625,13 +1619,10 @@ static int snd_rawmidi_dev_disconnect(struct snd_device *device)
1625void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream, 1619void snd_rawmidi_set_ops(struct snd_rawmidi *rmidi, int stream,
1626 struct snd_rawmidi_ops *ops) 1620 struct snd_rawmidi_ops *ops)
1627{ 1621{
1628 struct list_head *list;
1629 struct snd_rawmidi_substream *substream; 1622 struct snd_rawmidi_substream *substream;
1630 1623
1631 list_for_each(list, &rmidi->streams[stream].substreams) { 1624 list_for_each_entry(substream, &rmidi->streams[stream].substreams, list)
1632 substream = list_entry(list, struct snd_rawmidi_substream, list);
1633 substream->ops = ops; 1625 substream->ops = ops;
1634 }
1635} 1626}
1636 1627
1637/* 1628/*
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 532a660df51d..bb9dd9fa8e51 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -659,7 +659,6 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
659 int err = 0, num_ev = 0; 659 int err = 0, num_ev = 0;
660 struct snd_seq_event event_saved; 660 struct snd_seq_event event_saved;
661 struct snd_seq_client_port *src_port; 661 struct snd_seq_client_port *src_port;
662 struct list_head *p;
663 struct snd_seq_port_subs_info *grp; 662 struct snd_seq_port_subs_info *grp;
664 663
665 src_port = snd_seq_port_use_ptr(client, event->source.port); 664 src_port = snd_seq_port_use_ptr(client, event->source.port);
@@ -674,8 +673,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
674 read_lock(&grp->list_lock); 673 read_lock(&grp->list_lock);
675 else 674 else
676 down_read(&grp->list_mutex); 675 down_read(&grp->list_mutex);
677 list_for_each(p, &grp->list_head) { 676 list_for_each_entry(subs, &grp->list_head, src_list) {
678 subs = list_entry(p, struct snd_seq_subscribers, src_list);
679 event->dest = subs->info.dest; 677 event->dest = subs->info.dest;
680 if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP) 678 if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
681 /* convert time according to flag with subscription */ 679 /* convert time according to flag with subscription */
@@ -709,15 +707,14 @@ static int port_broadcast_event(struct snd_seq_client *client,
709{ 707{
710 int num_ev = 0, err = 0; 708 int num_ev = 0, err = 0;
711 struct snd_seq_client *dest_client; 709 struct snd_seq_client *dest_client;
712 struct list_head *p; 710 struct snd_seq_client_port *port;
713 711
714 dest_client = get_event_dest_client(event, SNDRV_SEQ_FILTER_BROADCAST); 712 dest_client = get_event_dest_client(event, SNDRV_SEQ_FILTER_BROADCAST);
715 if (dest_client == NULL) 713 if (dest_client == NULL)
716 return 0; /* no matching destination */ 714 return 0; /* no matching destination */
717 715
718 read_lock(&dest_client->ports_lock); 716 read_lock(&dest_client->ports_lock);
719 list_for_each(p, &dest_client->ports_list_head) { 717 list_for_each_entry(port, &dest_client->ports_list_head, list) {
720 struct snd_seq_client_port *port = list_entry(p, struct snd_seq_client_port, list);
721 event->dest.port = port->addr.port; 718 event->dest.port = port->addr.port;
722 /* pass NULL as source client to avoid error bounce */ 719 /* pass NULL as source client to avoid error bounce */
723 err = snd_seq_deliver_single_event(NULL, event, 720 err = snd_seq_deliver_single_event(NULL, event,
@@ -2473,11 +2470,10 @@ static void snd_seq_info_dump_subscribers(struct snd_info_buffer *buffer,
2473static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer, 2470static void snd_seq_info_dump_ports(struct snd_info_buffer *buffer,
2474 struct snd_seq_client *client) 2471 struct snd_seq_client *client)
2475{ 2472{
2476 struct list_head *l; 2473 struct snd_seq_client_port *p;
2477 2474
2478 mutex_lock(&client->ports_mutex); 2475 mutex_lock(&client->ports_mutex);
2479 list_for_each(l, &client->ports_list_head) { 2476 list_for_each_entry(p, &client->ports_list_head, list) {
2480 struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
2481 snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c)\n", 2477 snd_iprintf(buffer, " Port %3d : \"%s\" (%c%c%c%c)\n",
2482 p->addr.port, p->name, 2478 p->addr.port, p->name,
2483 FLAG_PERM_RD(p->capability), 2479 FLAG_PERM_RD(p->capability),
diff --git a/sound/core/seq/seq_device.c b/sound/core/seq/seq_device.c
index b79d011813c0..37852cdace76 100644
--- a/sound/core/seq/seq_device.c
+++ b/sound/core/seq/seq_device.c
@@ -106,11 +106,10 @@ static void remove_drivers(void);
106static void snd_seq_device_info(struct snd_info_entry *entry, 106static void snd_seq_device_info(struct snd_info_entry *entry,
107 struct snd_info_buffer *buffer) 107 struct snd_info_buffer *buffer)
108{ 108{
109 struct list_head *head; 109 struct ops_list *ops;
110 110
111 mutex_lock(&ops_mutex); 111 mutex_lock(&ops_mutex);
112 list_for_each(head, &opslist) { 112 list_for_each_entry(ops, &opslist, list) {
113 struct ops_list *ops = list_entry(head, struct ops_list, list);
114 snd_iprintf(buffer, "snd-%s%s%s%s,%d\n", 113 snd_iprintf(buffer, "snd-%s%s%s%s,%d\n",
115 ops->id, 114 ops->id,
116 ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""), 115 ops->driver & DRIVER_LOADED ? ",loaded" : (ops->driver == DRIVER_EMPTY ? ",empty" : ""),
@@ -143,7 +142,7 @@ void snd_seq_autoload_unlock(void)
143void snd_seq_device_load_drivers(void) 142void snd_seq_device_load_drivers(void)
144{ 143{
145#ifdef CONFIG_KMOD 144#ifdef CONFIG_KMOD
146 struct list_head *head; 145 struct ops_list *ops;
147 146
148 /* Calling request_module during module_init() 147 /* Calling request_module during module_init()
149 * may cause blocking. 148 * may cause blocking.
@@ -155,8 +154,7 @@ void snd_seq_device_load_drivers(void)
155 return; 154 return;
156 155
157 mutex_lock(&ops_mutex); 156 mutex_lock(&ops_mutex);
158 list_for_each(head, &opslist) { 157 list_for_each_entry(ops, &opslist, list) {
159 struct ops_list *ops = list_entry(head, struct ops_list, list);
160 if (! (ops->driver & DRIVER_LOADED) && 158 if (! (ops->driver & DRIVER_LOADED) &&
161 ! (ops->driver & DRIVER_REQUESTED)) { 159 ! (ops->driver & DRIVER_REQUESTED)) {
162 ops->used++; 160 ops->used++;
@@ -314,8 +312,8 @@ static int snd_seq_device_dev_disconnect(struct snd_device *device)
314int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry, 312int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
315 int argsize) 313 int argsize)
316{ 314{
317 struct list_head *head;
318 struct ops_list *ops; 315 struct ops_list *ops;
316 struct snd_seq_device *dev;
319 317
320 if (id == NULL || entry == NULL || 318 if (id == NULL || entry == NULL ||
321 entry->init_device == NULL || entry->free_device == NULL) 319 entry->init_device == NULL || entry->free_device == NULL)
@@ -341,8 +339,7 @@ int snd_seq_device_register_driver(char *id, struct snd_seq_dev_ops *entry,
341 ops->argsize = argsize; 339 ops->argsize = argsize;
342 340
343 /* initialize existing devices if necessary */ 341 /* initialize existing devices if necessary */
344 list_for_each(head, &ops->dev_list) { 342 list_for_each_entry(dev, &ops->dev_list, list) {
345 struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list);
346 init_device(dev, ops); 343 init_device(dev, ops);
347 } 344 }
348 mutex_unlock(&ops->reg_mutex); 345 mutex_unlock(&ops->reg_mutex);
@@ -394,8 +391,8 @@ static struct ops_list * create_driver(char *id)
394 */ 391 */
395int snd_seq_device_unregister_driver(char *id) 392int snd_seq_device_unregister_driver(char *id)
396{ 393{
397 struct list_head *head;
398 struct ops_list *ops; 394 struct ops_list *ops;
395 struct snd_seq_device *dev;
399 396
400 ops = find_driver(id, 0); 397 ops = find_driver(id, 0);
401 if (ops == NULL) 398 if (ops == NULL)
@@ -411,8 +408,7 @@ int snd_seq_device_unregister_driver(char *id)
411 /* close and release all devices associated with this driver */ 408 /* close and release all devices associated with this driver */
412 mutex_lock(&ops->reg_mutex); 409 mutex_lock(&ops->reg_mutex);
413 ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */ 410 ops->driver |= DRIVER_LOCKED; /* do not remove this driver recursively */
414 list_for_each(head, &ops->dev_list) { 411 list_for_each_entry(dev, &ops->dev_list, list) {
415 struct snd_seq_device *dev = list_entry(head, struct snd_seq_device, list);
416 free_device(dev, ops); 412 free_device(dev, ops);
417 } 413 }
418 414
@@ -512,11 +508,10 @@ static int free_device(struct snd_seq_device *dev, struct ops_list *ops)
512 */ 508 */
513static struct ops_list * find_driver(char *id, int create_if_empty) 509static struct ops_list * find_driver(char *id, int create_if_empty)
514{ 510{
515 struct list_head *head; 511 struct ops_list *ops;
516 512
517 mutex_lock(&ops_mutex); 513 mutex_lock(&ops_mutex);
518 list_for_each(head, &opslist) { 514 list_for_each_entry(ops, &opslist, list) {
519 struct ops_list *ops = list_entry(head, struct ops_list, list);
520 if (strcmp(ops->id, id) == 0) { 515 if (strcmp(ops->id, id) == 0) {
521 ops->used++; 516 ops->used++;
522 mutex_unlock(&ops_mutex); 517 mutex_unlock(&ops_mutex);
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 8c64b58ff77b..eefd1cf872b4 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -59,14 +59,12 @@ much elements are in array.
59struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client, 59struct snd_seq_client_port *snd_seq_port_use_ptr(struct snd_seq_client *client,
60 int num) 60 int num)
61{ 61{
62 struct list_head *p;
63 struct snd_seq_client_port *port; 62 struct snd_seq_client_port *port;
64 63
65 if (client == NULL) 64 if (client == NULL)
66 return NULL; 65 return NULL;
67 read_lock(&client->ports_lock); 66 read_lock(&client->ports_lock);
68 list_for_each(p, &client->ports_list_head) { 67 list_for_each_entry(port, &client->ports_list_head, list) {
69 port = list_entry(p, struct snd_seq_client_port, list);
70 if (port->addr.port == num) { 68 if (port->addr.port == num) {
71 if (port->closing) 69 if (port->closing)
72 break; /* deleting now */ 70 break; /* deleting now */
@@ -85,14 +83,12 @@ struct snd_seq_client_port *snd_seq_port_query_nearest(struct snd_seq_client *cl
85 struct snd_seq_port_info *pinfo) 83 struct snd_seq_port_info *pinfo)
86{ 84{
87 int num; 85 int num;
88 struct list_head *p;
89 struct snd_seq_client_port *port, *found; 86 struct snd_seq_client_port *port, *found;
90 87
91 num = pinfo->addr.port; 88 num = pinfo->addr.port;
92 found = NULL; 89 found = NULL;
93 read_lock(&client->ports_lock); 90 read_lock(&client->ports_lock);
94 list_for_each(p, &client->ports_list_head) { 91 list_for_each_entry(port, &client->ports_list_head, list) {
95 port = list_entry(p, struct snd_seq_client_port, list);
96 if (port->addr.port < num) 92 if (port->addr.port < num)
97 continue; 93 continue;
98 if (port->addr.port == num) { 94 if (port->addr.port == num) {
@@ -131,8 +127,7 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
131 int port) 127 int port)
132{ 128{
133 unsigned long flags; 129 unsigned long flags;
134 struct snd_seq_client_port *new_port; 130 struct snd_seq_client_port *new_port, *p;
135 struct list_head *l;
136 int num = -1; 131 int num = -1;
137 132
138 /* sanity check */ 133 /* sanity check */
@@ -161,15 +156,14 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
161 num = port >= 0 ? port : 0; 156 num = port >= 0 ? port : 0;
162 mutex_lock(&client->ports_mutex); 157 mutex_lock(&client->ports_mutex);
163 write_lock_irqsave(&client->ports_lock, flags); 158 write_lock_irqsave(&client->ports_lock, flags);
164 list_for_each(l, &client->ports_list_head) { 159 list_for_each_entry(p, &client->ports_list_head, list) {
165 struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
166 if (p->addr.port > num) 160 if (p->addr.port > num)
167 break; 161 break;
168 if (port < 0) /* auto-probe mode */ 162 if (port < 0) /* auto-probe mode */
169 num = p->addr.port + 1; 163 num = p->addr.port + 1;
170 } 164 }
171 /* insert the new port */ 165 /* insert the new port */
172 list_add_tail(&new_port->list, l); 166 list_add_tail(&new_port->list, &p->list);
173 client->num_ports++; 167 client->num_ports++;
174 new_port->addr.port = num; /* store the port number in the port */ 168 new_port->addr.port = num; /* store the port number in the port */
175 write_unlock_irqrestore(&client->ports_lock, flags); 169 write_unlock_irqrestore(&client->ports_lock, flags);
@@ -251,9 +245,9 @@ static void clear_subscriber_list(struct snd_seq_client *client,
251 list_del(&subs->dest_list); 245 list_del(&subs->dest_list);
252 else 246 else
253 list_del(&subs->src_list); 247 list_del(&subs->src_list);
248 up_write(&agrp->list_mutex);
254 unsubscribe_port(c, aport, agrp, &subs->info, 1); 249 unsubscribe_port(c, aport, agrp, &subs->info, 1);
255 kfree(subs); 250 kfree(subs);
256 up_write(&agrp->list_mutex);
257 snd_seq_port_unlock(aport); 251 snd_seq_port_unlock(aport);
258 snd_seq_client_unlock(c); 252 snd_seq_client_unlock(c);
259 } 253 }
@@ -287,16 +281,14 @@ static int port_delete(struct snd_seq_client *client,
287int snd_seq_delete_port(struct snd_seq_client *client, int port) 281int snd_seq_delete_port(struct snd_seq_client *client, int port)
288{ 282{
289 unsigned long flags; 283 unsigned long flags;
290 struct list_head *l; 284 struct snd_seq_client_port *found = NULL, *p;
291 struct snd_seq_client_port *found = NULL;
292 285
293 mutex_lock(&client->ports_mutex); 286 mutex_lock(&client->ports_mutex);
294 write_lock_irqsave(&client->ports_lock, flags); 287 write_lock_irqsave(&client->ports_lock, flags);
295 list_for_each(l, &client->ports_list_head) { 288 list_for_each_entry(p, &client->ports_list_head, list) {
296 struct snd_seq_client_port *p = list_entry(l, struct snd_seq_client_port, list);
297 if (p->addr.port == port) { 289 if (p->addr.port == port) {
298 /* ok found. delete from the list at first */ 290 /* ok found. delete from the list at first */
299 list_del(l); 291 list_del(&p->list);
300 client->num_ports--; 292 client->num_ports--;
301 found = p; 293 found = p;
302 break; 294 break;
@@ -314,7 +306,8 @@ int snd_seq_delete_port(struct snd_seq_client *client, int port)
314int snd_seq_delete_all_ports(struct snd_seq_client *client) 306int snd_seq_delete_all_ports(struct snd_seq_client *client)
315{ 307{
316 unsigned long flags; 308 unsigned long flags;
317 struct list_head deleted_list, *p, *n; 309 struct list_head deleted_list;
310 struct snd_seq_client_port *port, *tmp;
318 311
319 /* move the port list to deleted_list, and 312 /* move the port list to deleted_list, and
320 * clear the port list in the client data. 313 * clear the port list in the client data.
@@ -331,9 +324,8 @@ int snd_seq_delete_all_ports(struct snd_seq_client *client)
331 write_unlock_irqrestore(&client->ports_lock, flags); 324 write_unlock_irqrestore(&client->ports_lock, flags);
332 325
333 /* remove each port in deleted_list */ 326 /* remove each port in deleted_list */
334 list_for_each_safe(p, n, &deleted_list) { 327 list_for_each_entry_safe(port, tmp, &deleted_list, list) {
335 struct snd_seq_client_port *port = list_entry(p, struct snd_seq_client_port, list); 328 list_del(&port->list);
336 list_del(p);
337 snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port); 329 snd_seq_system_client_ev_port_exit(port->addr.client, port->addr.port);
338 port_delete(client, port); 330 port_delete(client, port);
339 } 331 }
@@ -500,8 +492,7 @@ int snd_seq_port_connect(struct snd_seq_client *connector,
500{ 492{
501 struct snd_seq_port_subs_info *src = &src_port->c_src; 493 struct snd_seq_port_subs_info *src = &src_port->c_src;
502 struct snd_seq_port_subs_info *dest = &dest_port->c_dest; 494 struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
503 struct snd_seq_subscribers *subs; 495 struct snd_seq_subscribers *subs, *s;
504 struct list_head *p;
505 int err, src_called = 0; 496 int err, src_called = 0;
506 unsigned long flags; 497 unsigned long flags;
507 int exclusive; 498 int exclusive;
@@ -525,13 +516,11 @@ int snd_seq_port_connect(struct snd_seq_client *connector,
525 if (src->exclusive || dest->exclusive) 516 if (src->exclusive || dest->exclusive)
526 goto __error; 517 goto __error;
527 /* check whether already exists */ 518 /* check whether already exists */
528 list_for_each(p, &src->list_head) { 519 list_for_each_entry(s, &src->list_head, src_list) {
529 struct snd_seq_subscribers *s = list_entry(p, struct snd_seq_subscribers, src_list);
530 if (match_subs_info(info, &s->info)) 520 if (match_subs_info(info, &s->info))
531 goto __error; 521 goto __error;
532 } 522 }
533 list_for_each(p, &dest->list_head) { 523 list_for_each_entry(s, &dest->list_head, dest_list) {
534 struct snd_seq_subscribers *s = list_entry(p, struct snd_seq_subscribers, dest_list);
535 if (match_subs_info(info, &s->info)) 524 if (match_subs_info(info, &s->info))
536 goto __error; 525 goto __error;
537 } 526 }
@@ -582,7 +571,6 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
582 struct snd_seq_port_subs_info *src = &src_port->c_src; 571 struct snd_seq_port_subs_info *src = &src_port->c_src;
583 struct snd_seq_port_subs_info *dest = &dest_port->c_dest; 572 struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
584 struct snd_seq_subscribers *subs; 573 struct snd_seq_subscribers *subs;
585 struct list_head *p;
586 int err = -ENOENT; 574 int err = -ENOENT;
587 unsigned long flags; 575 unsigned long flags;
588 576
@@ -590,8 +578,7 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
590 down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING); 578 down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
591 579
592 /* look for the connection */ 580 /* look for the connection */
593 list_for_each(p, &src->list_head) { 581 list_for_each_entry(subs, &src->list_head, src_list) {
594 subs = list_entry(p, struct snd_seq_subscribers, src_list);
595 if (match_subs_info(info, &subs->info)) { 582 if (match_subs_info(info, &subs->info)) {
596 write_lock_irqsave(&src->list_lock, flags); 583 write_lock_irqsave(&src->list_lock, flags);
597 // write_lock(&dest->list_lock); // no lock yet 584 // write_lock(&dest->list_lock); // no lock yet
@@ -620,12 +607,10 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
620struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp, 607struct snd_seq_subscribers *snd_seq_port_get_subscription(struct snd_seq_port_subs_info *src_grp,
621 struct snd_seq_addr *dest_addr) 608 struct snd_seq_addr *dest_addr)
622{ 609{
623 struct list_head *p;
624 struct snd_seq_subscribers *s, *found = NULL; 610 struct snd_seq_subscribers *s, *found = NULL;
625 611
626 down_read(&src_grp->list_mutex); 612 down_read(&src_grp->list_mutex);
627 list_for_each(p, &src_grp->list_head) { 613 list_for_each_entry(s, &src_grp->list_head, src_list) {
628 s = list_entry(p, struct snd_seq_subscribers, src_list);
629 if (addr_match(dest_addr, &s->info.dest)) { 614 if (addr_match(dest_addr, &s->info.dest)) {
630 found = s; 615 found = s;
631 break; 616 break;
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 0cfa06c6b81f..972f93405364 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -81,13 +81,11 @@ static int snd_virmidi_dev_receive_event(struct snd_virmidi_dev *rdev,
81 struct snd_seq_event *ev) 81 struct snd_seq_event *ev)
82{ 82{
83 struct snd_virmidi *vmidi; 83 struct snd_virmidi *vmidi;
84 struct list_head *list;
85 unsigned char msg[4]; 84 unsigned char msg[4];
86 int len; 85 int len;
87 86
88 read_lock(&rdev->filelist_lock); 87 read_lock(&rdev->filelist_lock);
89 list_for_each(list, &rdev->filelist) { 88 list_for_each_entry(vmidi, &rdev->filelist, list) {
90 vmidi = list_entry(list, struct snd_virmidi, list);
91 if (!vmidi->trigger) 89 if (!vmidi->trigger)
92 continue; 90 continue;
93 if (ev->type == SNDRV_SEQ_EVENT_SYSEX) { 91 if (ev->type == SNDRV_SEQ_EVENT_SYSEX) {
diff --git a/sound/core/sound.c b/sound/core/sound.c
index 82a61c67cf3a..4084de064127 100644
--- a/sound/core/sound.c
+++ b/sound/core/sound.c
@@ -219,26 +219,27 @@ static int snd_kernel_minor(int type, struct snd_card *card, int dev)
219#endif 219#endif
220 220
221/** 221/**
222 * snd_register_device - Register the ALSA device file for the card 222 * snd_register_device_for_dev - Register the ALSA device file for the card
223 * @type: the device type, SNDRV_DEVICE_TYPE_XXX 223 * @type: the device type, SNDRV_DEVICE_TYPE_XXX
224 * @card: the card instance 224 * @card: the card instance
225 * @dev: the device index 225 * @dev: the device index
226 * @f_ops: the file operations 226 * @f_ops: the file operations
227 * @private_data: user pointer for f_ops->open() 227 * @private_data: user pointer for f_ops->open()
228 * @name: the device file name 228 * @name: the device file name
229 * @device: the &struct device to link this new device to
229 * 230 *
230 * Registers an ALSA device file for the given card. 231 * Registers an ALSA device file for the given card.
231 * The operators have to be set in reg parameter. 232 * The operators have to be set in reg parameter.
232 * 233 *
233 * Retrurns zero if successful, or a negative error code on failure. 234 * Returns zero if successful, or a negative error code on failure.
234 */ 235 */
235int snd_register_device(int type, struct snd_card *card, int dev, 236int snd_register_device_for_dev(int type, struct snd_card *card, int dev,
236 const struct file_operations *f_ops, void *private_data, 237 const struct file_operations *f_ops,
237 const char *name) 238 void *private_data,
239 const char *name, struct device *device)
238{ 240{
239 int minor; 241 int minor;
240 struct snd_minor *preg; 242 struct snd_minor *preg;
241 struct device *device = snd_card_get_device_link(card);
242 243
243 snd_assert(name, return -EINVAL); 244 snd_assert(name, return -EINVAL);
244 preg = kmalloc(sizeof *preg, GFP_KERNEL); 245 preg = kmalloc(sizeof *preg, GFP_KERNEL);
@@ -272,7 +273,7 @@ int snd_register_device(int type, struct snd_card *card, int dev,
272 return 0; 273 return 0;
273} 274}
274 275
275EXPORT_SYMBOL(snd_register_device); 276EXPORT_SYMBOL(snd_register_device_for_dev);
276 277
277/* find the matching minor record 278/* find the matching minor record
278 * return the index of snd_minor, or -1 if not found 279 * return the index of snd_minor, or -1 if not found
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 10a79aed33f8..3e0638351069 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -35,9 +35,6 @@
35#include <sound/minors.h> 35#include <sound/minors.h>
36#include <sound/initval.h> 36#include <sound/initval.h>
37#include <linux/kmod.h> 37#include <linux/kmod.h>
38#ifdef CONFIG_KERNELD
39#include <linux/kerneld.h>
40#endif
41 38
42#if defined(CONFIG_SND_HPET) || defined(CONFIG_SND_HPET_MODULE) 39#if defined(CONFIG_SND_HPET) || defined(CONFIG_SND_HPET_MODULE)
43#define DEFAULT_TIMER_LIMIT 3 40#define DEFAULT_TIMER_LIMIT 3
@@ -130,11 +127,8 @@ static struct snd_timer_instance *snd_timer_instance_new(char *owner,
130static struct snd_timer *snd_timer_find(struct snd_timer_id *tid) 127static struct snd_timer *snd_timer_find(struct snd_timer_id *tid)
131{ 128{
132 struct snd_timer *timer = NULL; 129 struct snd_timer *timer = NULL;
133 struct list_head *p;
134
135 list_for_each(p, &snd_timer_list) {
136 timer = list_entry(p, struct snd_timer, device_list);
137 130
131 list_for_each_entry(timer, &snd_timer_list, device_list) {
138 if (timer->tmr_class != tid->dev_class) 132 if (timer->tmr_class != tid->dev_class)
139 continue; 133 continue;
140 if ((timer->tmr_class == SNDRV_TIMER_CLASS_CARD || 134 if ((timer->tmr_class == SNDRV_TIMER_CLASS_CARD ||
@@ -184,13 +178,10 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
184{ 178{
185 struct snd_timer *timer; 179 struct snd_timer *timer;
186 struct snd_timer_instance *master; 180 struct snd_timer_instance *master;
187 struct list_head *p, *q;
188 181
189 /* FIXME: it's really dumb to look up all entries.. */ 182 /* FIXME: it's really dumb to look up all entries.. */
190 list_for_each(p, &snd_timer_list) { 183 list_for_each_entry(timer, &snd_timer_list, device_list) {
191 timer = list_entry(p, struct snd_timer, device_list); 184 list_for_each_entry(master, &timer->open_list_head, open_list) {
192 list_for_each(q, &timer->open_list_head) {
193 master = list_entry(q, struct snd_timer_instance, open_list);
194 if (slave->slave_class == master->slave_class && 185 if (slave->slave_class == master->slave_class &&
195 slave->slave_id == master->slave_id) { 186 slave->slave_id == master->slave_id) {
196 list_del(&slave->open_list); 187 list_del(&slave->open_list);
@@ -214,16 +205,13 @@ static void snd_timer_check_slave(struct snd_timer_instance *slave)
214 */ 205 */
215static void snd_timer_check_master(struct snd_timer_instance *master) 206static void snd_timer_check_master(struct snd_timer_instance *master)
216{ 207{
217 struct snd_timer_instance *slave; 208 struct snd_timer_instance *slave, *tmp;
218 struct list_head *p, *n;
219 209
220 /* check all pending slaves */ 210 /* check all pending slaves */
221 list_for_each_safe(p, n, &snd_timer_slave_list) { 211 list_for_each_entry_safe(slave, tmp, &snd_timer_slave_list, open_list) {
222 slave = list_entry(p, struct snd_timer_instance, open_list);
223 if (slave->slave_class == master->slave_class && 212 if (slave->slave_class == master->slave_class &&
224 slave->slave_id == master->slave_id) { 213 slave->slave_id == master->slave_id) {
225 list_del(p); 214 list_move_tail(&slave->open_list, &master->slave_list_head);
226 list_add_tail(p, &master->slave_list_head);
227 spin_lock_irq(&slave_active_lock); 215 spin_lock_irq(&slave_active_lock);
228 slave->master = master; 216 slave->master = master;
229 slave->timer = master->timer; 217 slave->timer = master->timer;
@@ -317,8 +305,7 @@ static int _snd_timer_stop(struct snd_timer_instance *timeri,
317int snd_timer_close(struct snd_timer_instance *timeri) 305int snd_timer_close(struct snd_timer_instance *timeri)
318{ 306{
319 struct snd_timer *timer = NULL; 307 struct snd_timer *timer = NULL;
320 struct list_head *p, *n; 308 struct snd_timer_instance *slave, *tmp;
321 struct snd_timer_instance *slave;
322 309
323 snd_assert(timeri != NULL, return -ENXIO); 310 snd_assert(timeri != NULL, return -ENXIO);
324 311
@@ -353,12 +340,11 @@ int snd_timer_close(struct snd_timer_instance *timeri)
353 timer->hw.close) 340 timer->hw.close)
354 timer->hw.close(timer); 341 timer->hw.close(timer);
355 /* remove slave links */ 342 /* remove slave links */
356 list_for_each_safe(p, n, &timeri->slave_list_head) { 343 list_for_each_entry_safe(slave, tmp, &timeri->slave_list_head,
357 slave = list_entry(p, struct snd_timer_instance, open_list); 344 open_list) {
358 spin_lock_irq(&slave_active_lock); 345 spin_lock_irq(&slave_active_lock);
359 _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION); 346 _snd_timer_stop(slave, 1, SNDRV_TIMER_EVENT_RESOLUTION);
360 list_del(p); 347 list_move_tail(&slave->open_list, &snd_timer_slave_list);
361 list_add_tail(p, &snd_timer_slave_list);
362 slave->master = NULL; 348 slave->master = NULL;
363 slave->timer = NULL; 349 slave->timer = NULL;
364 spin_unlock_irq(&slave_active_lock); 350 spin_unlock_irq(&slave_active_lock);
@@ -394,7 +380,6 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
394 unsigned long flags; 380 unsigned long flags;
395 unsigned long resolution = 0; 381 unsigned long resolution = 0;
396 struct snd_timer_instance *ts; 382 struct snd_timer_instance *ts;
397 struct list_head *n;
398 struct timespec tstamp; 383 struct timespec tstamp;
399 384
400 getnstimeofday(&tstamp); 385 getnstimeofday(&tstamp);
@@ -413,11 +398,9 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
413 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) 398 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
414 return; 399 return;
415 spin_lock_irqsave(&timer->lock, flags); 400 spin_lock_irqsave(&timer->lock, flags);
416 list_for_each(n, &ti->slave_active_head) { 401 list_for_each_entry(ts, &ti->slave_active_head, active_list)
417 ts = list_entry(n, struct snd_timer_instance, active_list);
418 if (ts->ccallback) 402 if (ts->ccallback)
419 ts->ccallback(ti, event + 100, &tstamp, resolution); 403 ts->ccallback(ti, event + 100, &tstamp, resolution);
420 }
421 spin_unlock_irqrestore(&timer->lock, flags); 404 spin_unlock_irqrestore(&timer->lock, flags);
422} 405}
423 406
@@ -593,10 +576,8 @@ static void snd_timer_reschedule(struct snd_timer * timer, unsigned long ticks_l
593{ 576{
594 struct snd_timer_instance *ti; 577 struct snd_timer_instance *ti;
595 unsigned long ticks = ~0UL; 578 unsigned long ticks = ~0UL;
596 struct list_head *p;
597 579
598 list_for_each(p, &timer->active_list_head) { 580 list_for_each_entry(ti, &timer->active_list_head, active_list) {
599 ti = list_entry(p, struct snd_timer_instance, active_list);
600 if (ti->flags & SNDRV_TIMER_IFLG_START) { 581 if (ti->flags & SNDRV_TIMER_IFLG_START) {
601 ti->flags &= ~SNDRV_TIMER_IFLG_START; 582 ti->flags &= ~SNDRV_TIMER_IFLG_START;
602 ti->flags |= SNDRV_TIMER_IFLG_RUNNING; 583 ti->flags |= SNDRV_TIMER_IFLG_RUNNING;
@@ -661,9 +642,9 @@ static void snd_timer_tasklet(unsigned long arg)
661 */ 642 */
662void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left) 643void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
663{ 644{
664 struct snd_timer_instance *ti, *ts; 645 struct snd_timer_instance *ti, *ts, *tmp;
665 unsigned long resolution, ticks; 646 unsigned long resolution, ticks;
666 struct list_head *p, *q, *n, *ack_list_head; 647 struct list_head *p, *ack_list_head;
667 unsigned long flags; 648 unsigned long flags;
668 int use_tasklet = 0; 649 int use_tasklet = 0;
669 650
@@ -679,12 +660,12 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
679 resolution = timer->hw.resolution; 660 resolution = timer->hw.resolution;
680 661
681 /* loop for all active instances 662 /* loop for all active instances
682 * Here we cannot use list_for_each because the active_list of a 663 * Here we cannot use list_for_each_entry because the active_list of a
683 * processed instance is relinked to done_list_head before the callback 664 * processed instance is relinked to done_list_head before the callback
684 * is called. 665 * is called.
685 */ 666 */
686 list_for_each_safe(p, n, &timer->active_list_head) { 667 list_for_each_entry_safe(ti, tmp, &timer->active_list_head,
687 ti = list_entry(p, struct snd_timer_instance, active_list); 668 active_list) {
688 if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING)) 669 if (!(ti->flags & SNDRV_TIMER_IFLG_RUNNING))
689 continue; 670 continue;
690 ti->pticks += ticks_left; 671 ti->pticks += ticks_left;
@@ -700,7 +681,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
700 } else { 681 } else {
701 ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING; 682 ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
702 if (--timer->running) 683 if (--timer->running)
703 list_del(p); 684 list_del(&ti->active_list);
704 } 685 }
705 if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) || 686 if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
706 (ti->flags & SNDRV_TIMER_IFLG_FAST)) 687 (ti->flags & SNDRV_TIMER_IFLG_FAST))
@@ -709,8 +690,7 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
709 ack_list_head = &timer->sack_list_head; 690 ack_list_head = &timer->sack_list_head;
710 if (list_empty(&ti->ack_list)) 691 if (list_empty(&ti->ack_list))
711 list_add_tail(&ti->ack_list, ack_list_head); 692 list_add_tail(&ti->ack_list, ack_list_head);
712 list_for_each(q, &ti->slave_active_head) { 693 list_for_each_entry(ts, &ti->slave_active_head, active_list) {
713 ts = list_entry(q, struct snd_timer_instance, active_list);
714 ts->pticks = ti->pticks; 694 ts->pticks = ti->pticks;
715 ts->resolution = resolution; 695 ts->resolution = resolution;
716 if (list_empty(&ts->ack_list)) 696 if (list_empty(&ts->ack_list))
@@ -844,7 +824,6 @@ static int snd_timer_dev_register(struct snd_device *dev)
844{ 824{
845 struct snd_timer *timer = dev->device_data; 825 struct snd_timer *timer = dev->device_data;
846 struct snd_timer *timer1; 826 struct snd_timer *timer1;
847 struct list_head *p;
848 827
849 snd_assert(timer != NULL && timer->hw.start != NULL && 828 snd_assert(timer != NULL && timer->hw.start != NULL &&
850 timer->hw.stop != NULL, return -ENXIO); 829 timer->hw.stop != NULL, return -ENXIO);
@@ -853,8 +832,7 @@ static int snd_timer_dev_register(struct snd_device *dev)
853 return -EINVAL; 832 return -EINVAL;
854 833
855 mutex_lock(&register_mutex); 834 mutex_lock(&register_mutex);
856 list_for_each(p, &snd_timer_list) { 835 list_for_each_entry(timer1, &snd_timer_list, device_list) {
857 timer1 = list_entry(p, struct snd_timer, device_list);
858 if (timer1->tmr_class > timer->tmr_class) 836 if (timer1->tmr_class > timer->tmr_class)
859 break; 837 break;
860 if (timer1->tmr_class < timer->tmr_class) 838 if (timer1->tmr_class < timer->tmr_class)
@@ -877,7 +855,7 @@ static int snd_timer_dev_register(struct snd_device *dev)
877 mutex_unlock(&register_mutex); 855 mutex_unlock(&register_mutex);
878 return -EBUSY; 856 return -EBUSY;
879 } 857 }
880 list_add_tail(&timer->device_list, p); 858 list_add_tail(&timer->device_list, &timer1->device_list);
881 mutex_unlock(&register_mutex); 859 mutex_unlock(&register_mutex);
882 return 0; 860 return 0;
883} 861}
@@ -896,7 +874,6 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
896 unsigned long flags; 874 unsigned long flags;
897 unsigned long resolution = 0; 875 unsigned long resolution = 0;
898 struct snd_timer_instance *ti, *ts; 876 struct snd_timer_instance *ti, *ts;
899 struct list_head *p, *n;
900 877
901 if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)) 878 if (! (timer->hw.flags & SNDRV_TIMER_HW_SLAVE))
902 return; 879 return;
@@ -911,15 +888,12 @@ void snd_timer_notify(struct snd_timer *timer, int event, struct timespec *tstam
911 else 888 else
912 resolution = timer->hw.resolution; 889 resolution = timer->hw.resolution;
913 } 890 }
914 list_for_each(p, &timer->active_list_head) { 891 list_for_each_entry(ti, &timer->active_list_head, active_list) {
915 ti = list_entry(p, struct snd_timer_instance, active_list);
916 if (ti->ccallback) 892 if (ti->ccallback)
917 ti->ccallback(ti, event, tstamp, resolution); 893 ti->ccallback(ti, event, tstamp, resolution);
918 list_for_each(n, &ti->slave_active_head) { 894 list_for_each_entry(ts, &ti->slave_active_head, active_list)
919 ts = list_entry(n, struct snd_timer_instance, active_list);
920 if (ts->ccallback) 895 if (ts->ccallback)
921 ts->ccallback(ts, event, tstamp, resolution); 896 ts->ccallback(ts, event, tstamp, resolution);
922 }
923 } 897 }
924 spin_unlock_irqrestore(&timer->lock, flags); 898 spin_unlock_irqrestore(&timer->lock, flags);
925} 899}
@@ -1057,11 +1031,9 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
1057{ 1031{
1058 struct snd_timer *timer; 1032 struct snd_timer *timer;
1059 struct snd_timer_instance *ti; 1033 struct snd_timer_instance *ti;
1060 struct list_head *p, *q;
1061 1034
1062 mutex_lock(&register_mutex); 1035 mutex_lock(&register_mutex);
1063 list_for_each(p, &snd_timer_list) { 1036 list_for_each_entry(timer, &snd_timer_list, device_list) {
1064 timer = list_entry(p, struct snd_timer, device_list);
1065 switch (timer->tmr_class) { 1037 switch (timer->tmr_class) {
1066 case SNDRV_TIMER_CLASS_GLOBAL: 1038 case SNDRV_TIMER_CLASS_GLOBAL:
1067 snd_iprintf(buffer, "G%i: ", timer->tmr_device); 1039 snd_iprintf(buffer, "G%i: ", timer->tmr_device);
@@ -1088,14 +1060,12 @@ static void snd_timer_proc_read(struct snd_info_entry *entry,
1088 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE) 1060 if (timer->hw.flags & SNDRV_TIMER_HW_SLAVE)
1089 snd_iprintf(buffer, " SLAVE"); 1061 snd_iprintf(buffer, " SLAVE");
1090 snd_iprintf(buffer, "\n"); 1062 snd_iprintf(buffer, "\n");
1091 list_for_each(q, &timer->open_list_head) { 1063 list_for_each_entry(ti, &timer->open_list_head, open_list)
1092 ti = list_entry(q, struct snd_timer_instance, open_list);
1093 snd_iprintf(buffer, " Client %s : %s\n", 1064 snd_iprintf(buffer, " Client %s : %s\n",
1094 ti->owner ? ti->owner : "unknown", 1065 ti->owner ? ti->owner : "unknown",
1095 ti->flags & (SNDRV_TIMER_IFLG_START | 1066 ti->flags & (SNDRV_TIMER_IFLG_START |
1096 SNDRV_TIMER_IFLG_RUNNING) 1067 SNDRV_TIMER_IFLG_RUNNING)
1097 ? "running" : "stopped"); 1068 ? "running" : "stopped");
1098 }
1099 } 1069 }
1100 mutex_unlock(&register_mutex); 1070 mutex_unlock(&register_mutex);
1101} 1071}
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 40ebd2f44056..83529b08d019 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -109,4 +109,15 @@ config SND_MPU401
109 To compile this driver as a module, choose M here: the module 109 To compile this driver as a module, choose M here: the module
110 will be called snd-mpu401. 110 will be called snd-mpu401.
111 111
112config SND_PORTMAN2X4
113 tristate "Portman 2x4 driver"
114 depends on SND && PARPORT
115 select SND_RAWMIDI
116 help
117 Say Y here to include support for Midiman Portman 2x4 parallel
118 port MIDI device.
119
120 To compile this driver as a module, choose M here: the module
121 will be called snd-portman2x4.
122
112endmenu 123endmenu
diff --git a/sound/drivers/Makefile b/sound/drivers/Makefile
index c9bad6d67e73..04112642611a 100644
--- a/sound/drivers/Makefile
+++ b/sound/drivers/Makefile
@@ -6,6 +6,7 @@
6snd-dummy-objs := dummy.o 6snd-dummy-objs := dummy.o
7snd-mtpav-objs := mtpav.o 7snd-mtpav-objs := mtpav.o
8snd-mts64-objs := mts64.o 8snd-mts64-objs := mts64.o
9snd-portman2x4-objs := portman2x4.o
9snd-serial-u16550-objs := serial-u16550.o 10snd-serial-u16550-objs := serial-u16550.o
10snd-virmidi-objs := virmidi.o 11snd-virmidi-objs := virmidi.o
11 12
@@ -15,5 +16,6 @@ obj-$(CONFIG_SND_VIRMIDI) += snd-virmidi.o
15obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o 16obj-$(CONFIG_SND_SERIAL_U16550) += snd-serial-u16550.o
16obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o 17obj-$(CONFIG_SND_MTPAV) += snd-mtpav.o
17obj-$(CONFIG_SND_MTS64) += snd-mts64.o 18obj-$(CONFIG_SND_MTS64) += snd-mts64.o
19obj-$(CONFIG_SND_PORTMAN2X4) += snd-portman2x4.o
18 20
19obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/ 21obj-$(CONFIG_SND) += opl3/ opl4/ mpu401/ vx/
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 42001efa9f3e..8339bad969ba 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -501,7 +501,7 @@ static int snd_dummy_volume_put(struct snd_kcontrol *kcontrol,
501 return change; 501 return change;
502} 502}
503 503
504static DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0); 504static const DECLARE_TLV_DB_SCALE(db_scale_dummy, -4500, 30, 0);
505 505
506#define DUMMY_CAPSRC(xname, xindex, addr) \ 506#define DUMMY_CAPSRC(xname, xindex, addr) \
507{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 507{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
diff --git a/sound/drivers/portman2x4.c b/sound/drivers/portman2x4.c
new file mode 100644
index 000000000000..6c48772aaefd
--- /dev/null
+++ b/sound/drivers/portman2x4.c
@@ -0,0 +1,876 @@
1/*
2 * Driver for Midiman Portman2x4 parallel port midi interface
3 *
4 * Copyright (c) by Levent Guendogdu <levon@feature-it.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 *
20 * ChangeLog
21 * Jan 24 2007 Matthias Koenig <mkoenig@suse.de>
22 * - cleanup and rewrite
23 * Sep 30 2004 Tobias Gehrig <tobias@gehrig.tk>
24 * - source code cleanup
25 * Sep 03 2004 Tobias Gehrig <tobias@gehrig.tk>
26 * - fixed compilation problem with alsa 1.0.6a (removed MODULE_CLASSES,
27 * MODULE_PARM_SYNTAX and changed MODULE_DEVICES to
28 * MODULE_SUPPORTED_DEVICE)
29 * Mar 24 2004 Tobias Gehrig <tobias@gehrig.tk>
30 * - added 2.6 kernel support
31 * Mar 18 2004 Tobias Gehrig <tobias@gehrig.tk>
32 * - added parport_unregister_driver to the startup routine if the driver fails to detect a portman
33 * - added support for all 4 output ports in portman_putmidi
34 * Mar 17 2004 Tobias Gehrig <tobias@gehrig.tk>
35 * - added checks for opened input device in interrupt handler
36 * Feb 20 2004 Tobias Gehrig <tobias@gehrig.tk>
37 * - ported from alsa 0.5 to 1.0
38 */
39
40#include <sound/driver.h>
41#include <linux/init.h>
42#include <linux/platform_device.h>
43#include <linux/parport.h>
44#include <linux/spinlock.h>
45#include <linux/delay.h>
46#include <sound/core.h>
47#include <sound/initval.h>
48#include <sound/rawmidi.h>
49#include <sound/control.h>
50
51#define CARD_NAME "Portman 2x4"
52#define DRIVER_NAME "portman"
53#define PLATFORM_DRIVER "snd_portman2x4"
54
55static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
56static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
57static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
58
59static struct platform_device *platform_devices[SNDRV_CARDS];
60static int device_count;
61
62module_param_array(index, int, NULL, S_IRUGO);
63MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
64module_param_array(id, charp, NULL, S_IRUGO);
65MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
66module_param_array(enable, bool, NULL, S_IRUGO);
67MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
68
69MODULE_AUTHOR("Levent Guendogdu, Tobias Gehrig, Matthias Koenig");
70MODULE_DESCRIPTION("Midiman Portman2x4");
71MODULE_LICENSE("GPL");
72MODULE_SUPPORTED_DEVICE("{{Midiman,Portman2x4}}");
73
74/*********************************************************************
75 * Chip specific
76 *********************************************************************/
77#define PORTMAN_NUM_INPUT_PORTS 2
78#define PORTMAN_NUM_OUTPUT_PORTS 4
79
80struct portman {
81 spinlock_t reg_lock;
82 struct snd_card *card;
83 struct snd_rawmidi *rmidi;
84 struct pardevice *pardev;
85 int pardev_claimed;
86
87 int open_count;
88 int mode[PORTMAN_NUM_INPUT_PORTS];
89 struct snd_rawmidi_substream *midi_input[PORTMAN_NUM_INPUT_PORTS];
90};
91
92static int portman_free(struct portman *pm)
93{
94 kfree(pm);
95 return 0;
96}
97
98static int __devinit portman_create(struct snd_card *card,
99 struct pardevice *pardev,
100 struct portman **rchip)
101{
102 struct portman *pm;
103
104 *rchip = NULL;
105
106 pm = kzalloc(sizeof(struct portman), GFP_KERNEL);
107 if (pm == NULL)
108 return -ENOMEM;
109
110 /* Init chip specific data */
111 spin_lock_init(&pm->reg_lock);
112 pm->card = card;
113 pm->pardev = pardev;
114
115 *rchip = pm;
116
117 return 0;
118}
119
120/*********************************************************************
121 * HW related constants
122 *********************************************************************/
123
124/* Standard PC parallel port status register equates. */
125#define PP_STAT_BSY 0x80 /* Busy status. Inverted. */
126#define PP_STAT_ACK 0x40 /* Acknowledge. Non-Inverted. */
127#define PP_STAT_POUT 0x20 /* Paper Out. Non-Inverted. */
128#define PP_STAT_SEL 0x10 /* Select. Non-Inverted. */
129#define PP_STAT_ERR 0x08 /* Error. Non-Inverted. */
130
131/* Standard PC parallel port command register equates. */
132#define PP_CMD_IEN 0x10 /* IRQ Enable. Non-Inverted. */
133#define PP_CMD_SELI 0x08 /* Select Input. Inverted. */
134#define PP_CMD_INIT 0x04 /* Init Printer. Non-Inverted. */
135#define PP_CMD_FEED 0x02 /* Auto Feed. Inverted. */
136#define PP_CMD_STB 0x01 /* Strobe. Inverted. */
137
138/* Parallel Port Command Register as implemented by PCP2x4. */
139#define INT_EN PP_CMD_IEN /* Interrupt enable. */
140#define STROBE PP_CMD_STB /* Command strobe. */
141
142/* The parallel port command register field (b1..b3) selects the
143 * various "registers" within the PC/P 2x4. These are the internal
144 * address of these "registers" that must be written to the parallel
145 * port command register.
146 */
147#define RXDATA0 (0 << 1) /* PCP RxData channel 0. */
148#define RXDATA1 (1 << 1) /* PCP RxData channel 1. */
149#define GEN_CTL (2 << 1) /* PCP General Control Register. */
150#define SYNC_CTL (3 << 1) /* PCP Sync Control Register. */
151#define TXDATA0 (4 << 1) /* PCP TxData channel 0. */
152#define TXDATA1 (5 << 1) /* PCP TxData channel 1. */
153#define TXDATA2 (6 << 1) /* PCP TxData channel 2. */
154#define TXDATA3 (7 << 1) /* PCP TxData channel 3. */
155
156/* Parallel Port Status Register as implemented by PCP2x4. */
157#define ESTB PP_STAT_POUT /* Echoed strobe. */
158#define INT_REQ PP_STAT_ACK /* Input data int request. */
159#define BUSY PP_STAT_ERR /* Interface Busy. */
160
161/* Parallel Port Status Register BUSY and SELECT lines are multiplexed
162 * between several functions. Depending on which 2x4 "register" is
163 * currently selected (b1..b3), the BUSY and SELECT lines are
164 * assigned as follows:
165 *
166 * SELECT LINE: A3 A2 A1
167 * --------
168 */
169#define RXAVAIL PP_STAT_SEL /* Rx Available, channel 0. 0 0 0 */
170// RXAVAIL1 PP_STAT_SEL /* Rx Available, channel 1. 0 0 1 */
171#define SYNC_STAT PP_STAT_SEL /* Reserved - Sync Status. 0 1 0 */
172// /* Reserved. 0 1 1 */
173#define TXEMPTY PP_STAT_SEL /* Tx Empty, channel 0. 1 0 0 */
174// TXEMPTY1 PP_STAT_SEL /* Tx Empty, channel 1. 1 0 1 */
175// TXEMPTY2 PP_STAT_SEL /* Tx Empty, channel 2. 1 1 0 */
176// TXEMPTY3 PP_STAT_SEL /* Tx Empty, channel 3. 1 1 1 */
177
178/* BUSY LINE: A3 A2 A1
179 * --------
180 */
181#define RXDATA PP_STAT_BSY /* Rx Input Data, channel 0. 0 0 0 */
182// RXDATA1 PP_STAT_BSY /* Rx Input Data, channel 1. 0 0 1 */
183#define SYNC_DATA PP_STAT_BSY /* Reserved - Sync Data. 0 1 0 */
184 /* Reserved. 0 1 1 */
185#define DATA_ECHO PP_STAT_BSY /* Parallel Port Data Echo. 1 0 0 */
186#define A0_ECHO PP_STAT_BSY /* Address 0 Echo. 1 0 1 */
187#define A1_ECHO PP_STAT_BSY /* Address 1 Echo. 1 1 0 */
188#define A2_ECHO PP_STAT_BSY /* Address 2 Echo. 1 1 1 */
189
190#define PORTMAN2X4_MODE_INPUT_TRIGGERED 0x01
191
192/*********************************************************************
193 * Hardware specific functions
194 *********************************************************************/
195static inline void portman_write_command(struct portman *pm, u8 value)
196{
197 parport_write_control(pm->pardev->port, value);
198}
199
200static inline u8 portman_read_command(struct portman *pm)
201{
202 return parport_read_control(pm->pardev->port);
203}
204
205static inline u8 portman_read_status(struct portman *pm)
206{
207 return parport_read_status(pm->pardev->port);
208}
209
210static inline u8 portman_read_data(struct portman *pm)
211{
212 return parport_read_data(pm->pardev->port);
213}
214
215static inline void portman_write_data(struct portman *pm, u8 value)
216{
217 parport_write_data(pm->pardev->port, value);
218}
219
220static void portman_write_midi(struct portman *pm,
221 int port, u8 mididata)
222{
223 int command = ((port + 4) << 1);
224
225 /* Get entering data byte and port number in BL and BH respectively.
226 * Set up Tx Channel address field for use with PP Cmd Register.
227 * Store address field in BH register.
228 * Inputs: AH = Output port number (0..3).
229 * AL = Data byte.
230 * command = TXDATA0 | INT_EN;
231 * Align port num with address field (b1...b3),
232 * set address for TXDatax, Strobe=0
233 */
234 command |= INT_EN;
235
236 /* Disable interrupts so that the process is not interrupted, then
237 * write the address associated with the current Tx channel to the
238 * PP Command Reg. Do not set the Strobe signal yet.
239 */
240
241 do {
242 portman_write_command(pm, command);
243
244 /* While the address lines settle, write parallel output data to
245 * PP Data Reg. This has no effect until Strobe signal is asserted.
246 */
247
248 portman_write_data(pm, mididata);
249
250 /* If PCP channel's TxEmpty is set (TxEmpty is read through the PP
251 * Status Register), then go write data. Else go back and wait.
252 */
253 } while ((portman_read_status(pm) & TXEMPTY) != TXEMPTY);
254
255 /* TxEmpty is set. Maintain PC/P destination address and assert
256 * Strobe through the PP Command Reg. This will Strobe data into
257 * the PC/P transmitter and set the PC/P BUSY signal.
258 */
259
260 portman_write_command(pm, command | STROBE);
261
262 /* Wait for strobe line to settle and echo back through hardware.
263 * Once it has echoed back, assume that the address and data lines
264 * have settled!
265 */
266
267 while ((portman_read_status(pm) & ESTB) == 0)
268 cpu_relax();
269
270 /* Release strobe and immediately re-allow interrupts. */
271 portman_write_command(pm, command);
272
273 while ((portman_read_status(pm) & ESTB) == ESTB)
274 cpu_relax();
275
276 /* PC/P BUSY is now set. We must wait until BUSY resets itself.
277 * We'll reenable ints while we're waiting.
278 */
279
280 while ((portman_read_status(pm) & BUSY) == BUSY)
281 cpu_relax();
282
283 /* Data sent. */
284}
285
286
287/*
288 * Read MIDI byte from port
289 * Attempt to read input byte from specified hardware input port (0..).
290 * Return -1 if no data
291 */
292static int portman_read_midi(struct portman *pm, int port)
293{
294 unsigned char midi_data = 0;
295 unsigned char cmdout; /* Saved address+IE bit. */
296
297 /* Make sure clocking edge is down before starting... */
298 portman_write_data(pm, 0); /* Make sure edge is down. */
299
300 /* Set destination address to PCP. */
301 cmdout = (port << 1) | INT_EN; /* Address + IE + No Strobe. */
302 portman_write_command(pm, cmdout);
303
304 while ((portman_read_status(pm) & ESTB) == ESTB)
305 cpu_relax(); /* Wait for strobe echo. */
306
307 /* After the address lines settle, check multiplexed RxAvail signal.
308 * If data is available, read it.
309 */
310 if ((portman_read_status(pm) & RXAVAIL) == 0)
311 return -1; /* No data. */
312
313 /* Set the Strobe signal to enable the Rx clocking circuitry. */
314 portman_write_command(pm, cmdout | STROBE); /* Write address+IE+Strobe. */
315
316 while ((portman_read_status(pm) & ESTB) == 0)
317 cpu_relax(); /* Wait for strobe echo. */
318
319 /* The first data bit (msb) is already sitting on the input line. */
320 midi_data = (portman_read_status(pm) & 128);
321 portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */
322
323 /* Data bit 6. */
324 portman_write_data(pm, 0); /* Cause falling edge while data settles. */
325 midi_data |= (portman_read_status(pm) >> 1) & 64;
326 portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */
327
328 /* Data bit 5. */
329 portman_write_data(pm, 0); /* Cause falling edge while data settles. */
330 midi_data |= (portman_read_status(pm) >> 2) & 32;
331 portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */
332
333 /* Data bit 4. */
334 portman_write_data(pm, 0); /* Cause falling edge while data settles. */
335 midi_data |= (portman_read_status(pm) >> 3) & 16;
336 portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */
337
338 /* Data bit 3. */
339 portman_write_data(pm, 0); /* Cause falling edge while data settles. */
340 midi_data |= (portman_read_status(pm) >> 4) & 8;
341 portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */
342
343 /* Data bit 2. */
344 portman_write_data(pm, 0); /* Cause falling edge while data settles. */
345 midi_data |= (portman_read_status(pm) >> 5) & 4;
346 portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */
347
348 /* Data bit 1. */
349 portman_write_data(pm, 0); /* Cause falling edge while data settles. */
350 midi_data |= (portman_read_status(pm) >> 6) & 2;
351 portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */
352
353 /* Data bit 0. */
354 portman_write_data(pm, 0); /* Cause falling edge while data settles. */
355 midi_data |= (portman_read_status(pm) >> 7) & 1;
356 portman_write_data(pm, 1); /* Cause rising edge, which shifts data. */
357 portman_write_data(pm, 0); /* Return data clock low. */
358
359
360 /* De-assert Strobe and return data. */
361 portman_write_command(pm, cmdout); /* Output saved address+IE. */
362
363 /* Wait for strobe echo. */
364 while ((portman_read_status(pm) & ESTB) == ESTB)
365 cpu_relax();
366
367 return (midi_data & 255); /* Shift back and return value. */
368}
369
370/*
371 * Checks if any input data on the given channel is available
372 * Checks RxAvail
373 */
374static int portman_data_avail(struct portman *pm, int channel)
375{
376 int command = INT_EN;
377 switch (channel) {
378 case 0:
379 command |= RXDATA0;
380 break;
381 case 1:
382 command |= RXDATA1;
383 break;
384 }
385 /* Write hardware (assumme STROBE=0) */
386 portman_write_command(pm, command);
387 /* Check multiplexed RxAvail signal */
388 if ((portman_read_status(pm) & RXAVAIL) == RXAVAIL)
389 return 1; /* Data available */
390
391 /* No Data available */
392 return 0;
393}
394
395
396/*
397 * Flushes any input
398 */
399static void portman_flush_input(struct portman *pm, unsigned char port)
400{
401 /* Local variable for counting things */
402 unsigned int i = 0;
403 unsigned char command = 0;
404
405 switch (port) {
406 case 0:
407 command = RXDATA0;
408 break;
409 case 1:
410 command = RXDATA1;
411 break;
412 default:
413 snd_printk(KERN_WARNING
414 "portman_flush_input() Won't flush port %i\n",
415 port);
416 return;
417 }
418
419 /* Set address for specified channel in port and allow to settle. */
420 portman_write_command(pm, command);
421
422 /* Assert the Strobe and wait for echo back. */
423 portman_write_command(pm, command | STROBE);
424
425 /* Wait for ESTB */
426 while ((portman_read_status(pm) & ESTB) == 0)
427 cpu_relax();
428
429 /* Output clock cycles to the Rx circuitry. */
430 portman_write_data(pm, 0);
431
432 /* Flush 250 bits... */
433 for (i = 0; i < 250; i++) {
434 portman_write_data(pm, 1);
435 portman_write_data(pm, 0);
436 }
437
438 /* Deassert the Strobe signal of the port and wait for it to settle. */
439 portman_write_command(pm, command | INT_EN);
440
441 /* Wait for settling */
442 while ((portman_read_status(pm) & ESTB) == ESTB)
443 cpu_relax();
444}
445
446static int portman_probe(struct parport *p)
447{
448 /* Initialize the parallel port data register. Will set Rx clocks
449 * low in case we happen to be addressing the Rx ports at this time.
450 */
451 /* 1 */
452 parport_write_data(p, 0);
453
454 /* Initialize the parallel port command register, thus initializing
455 * hardware handshake lines to midi box:
456 *
457 * Strobe = 0
458 * Interrupt Enable = 0
459 */
460 /* 2 */
461 parport_write_control(p, 0);
462
463 /* Check if Portman PC/P 2x4 is out there. */
464 /* 3 */
465 parport_write_control(p, RXDATA0); /* Write Strobe=0 to command reg. */
466
467 /* Check for ESTB to be clear */
468 /* 4 */
469 if ((parport_read_status(p) & ESTB) == ESTB)
470 return 1; /* CODE 1 - Strobe Failure. */
471
472 /* Set for RXDATA0 where no damage will be done. */
473 /* 5 */
474 parport_write_control(p, RXDATA0 + STROBE); /* Write Strobe=1 to command reg. */
475
476 /* 6 */
477 if ((parport_read_status(p) & ESTB) != ESTB)
478 return 1; /* CODE 1 - Strobe Failure. */
479
480 /* 7 */
481 parport_write_control(p, 0); /* Reset Strobe=0. */
482
483 /* Check if Tx circuitry is functioning properly. If initialized
484 * unit TxEmpty is false, send out char and see if if goes true.
485 */
486 /* 8 */
487 parport_write_control(p, TXDATA0); /* Tx channel 0, strobe off. */
488
489 /* If PCP channel's TxEmpty is set (TxEmpty is read through the PP
490 * Status Register), then go write data. Else go back and wait.
491 */
492 /* 9 */
493 if ((parport_read_status(p) & TXEMPTY) == 0)
494 return 2;
495
496 /* Return OK status. */
497 return 0;
498}
499
500static int portman_device_init(struct portman *pm)
501{
502 portman_flush_input(pm, 0);
503 portman_flush_input(pm, 1);
504
505 return 0;
506}
507
508/*********************************************************************
509 * Rawmidi
510 *********************************************************************/
511static int snd_portman_midi_open(struct snd_rawmidi_substream *substream)
512{
513 return 0;
514}
515
516static int snd_portman_midi_close(struct snd_rawmidi_substream *substream)
517{
518 return 0;
519}
520
521static void snd_portman_midi_input_trigger(struct snd_rawmidi_substream *substream,
522 int up)
523{
524 struct portman *pm = substream->rmidi->private_data;
525 unsigned long flags;
526
527 spin_lock_irqsave(&pm->reg_lock, flags);
528 if (up)
529 pm->mode[substream->number] |= PORTMAN2X4_MODE_INPUT_TRIGGERED;
530 else
531 pm->mode[substream->number] &= ~PORTMAN2X4_MODE_INPUT_TRIGGERED;
532 spin_unlock_irqrestore(&pm->reg_lock, flags);
533}
534
535static void snd_portman_midi_output_trigger(struct snd_rawmidi_substream *substream,
536 int up)
537{
538 struct portman *pm = substream->rmidi->private_data;
539 unsigned long flags;
540 unsigned char byte;
541
542 spin_lock_irqsave(&pm->reg_lock, flags);
543 if (up) {
544 while ((snd_rawmidi_transmit(substream, &byte, 1) == 1))
545 portman_write_midi(pm, substream->number, byte);
546 }
547 spin_unlock_irqrestore(&pm->reg_lock, flags);
548}
549
550static struct snd_rawmidi_ops snd_portman_midi_output = {
551 .open = snd_portman_midi_open,
552 .close = snd_portman_midi_close,
553 .trigger = snd_portman_midi_output_trigger,
554};
555
556static struct snd_rawmidi_ops snd_portman_midi_input = {
557 .open = snd_portman_midi_open,
558 .close = snd_portman_midi_close,
559 .trigger = snd_portman_midi_input_trigger,
560};
561
562/* Create and initialize the rawmidi component */
563static int __devinit snd_portman_rawmidi_create(struct snd_card *card)
564{
565 struct portman *pm = card->private_data;
566 struct snd_rawmidi *rmidi;
567 struct snd_rawmidi_substream *substream;
568 int err;
569
570 err = snd_rawmidi_new(card, CARD_NAME, 0,
571 PORTMAN_NUM_OUTPUT_PORTS,
572 PORTMAN_NUM_INPUT_PORTS,
573 &rmidi);
574 if (err < 0)
575 return err;
576
577 rmidi->private_data = pm;
578 strcpy(rmidi->name, CARD_NAME);
579 rmidi->info_flags = SNDRV_RAWMIDI_INFO_OUTPUT |
580 SNDRV_RAWMIDI_INFO_INPUT |
581 SNDRV_RAWMIDI_INFO_DUPLEX;
582
583 pm->rmidi = rmidi;
584
585 /* register rawmidi ops */
586 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
587 &snd_portman_midi_output);
588 snd_rawmidi_set_ops(rmidi, SNDRV_RAWMIDI_STREAM_INPUT,
589 &snd_portman_midi_input);
590
591 /* name substreams */
592 /* output */
593 list_for_each_entry(substream,
594 &rmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT].substreams,
595 list) {
596 sprintf(substream->name,
597 "Portman2x4 %d", substream->number+1);
598 }
599 /* input */
600 list_for_each_entry(substream,
601 &rmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT].substreams,
602 list) {
603 pm->midi_input[substream->number] = substream;
604 sprintf(substream->name,
605 "Portman2x4 %d", substream->number+1);
606 }
607
608 return err;
609}
610
611/*********************************************************************
612 * parport stuff
613 *********************************************************************/
614static void snd_portman_interrupt(int irq, void *userdata)
615{
616 unsigned char midivalue = 0;
617 struct portman *pm = ((struct snd_card*)userdata)->private_data;
618
619 spin_lock(&pm->reg_lock);
620
621 /* While any input data is waiting */
622 while ((portman_read_status(pm) & INT_REQ) == INT_REQ) {
623 /* If data available on channel 0,
624 read it and stuff it into the queue. */
625 if (portman_data_avail(pm, 0)) {
626 /* Read Midi */
627 midivalue = portman_read_midi(pm, 0);
628 /* put midi into queue... */
629 if (pm->mode[0] & PORTMAN2X4_MODE_INPUT_TRIGGERED)
630 snd_rawmidi_receive(pm->midi_input[0],
631 &midivalue, 1);
632
633 }
634 /* If data available on channel 1,
635 read it and stuff it into the queue. */
636 if (portman_data_avail(pm, 1)) {
637 /* Read Midi */
638 midivalue = portman_read_midi(pm, 1);
639 /* put midi into queue... */
640 if (pm->mode[1] & PORTMAN2X4_MODE_INPUT_TRIGGERED)
641 snd_rawmidi_receive(pm->midi_input[1],
642 &midivalue, 1);
643 }
644
645 }
646
647 spin_unlock(&pm->reg_lock);
648}
649
650static int __devinit snd_portman_probe_port(struct parport *p)
651{
652 struct pardevice *pardev;
653 int res;
654
655 pardev = parport_register_device(p, DRIVER_NAME,
656 NULL, NULL, NULL,
657 0, NULL);
658 if (!pardev)
659 return -EIO;
660
661 if (parport_claim(pardev)) {
662 parport_unregister_device(pardev);
663 return -EIO;
664 }
665
666 res = portman_probe(p);
667
668 parport_release(pardev);
669 parport_unregister_device(pardev);
670
671 return res;
672}
673
674static void __devinit snd_portman_attach(struct parport *p)
675{
676 struct platform_device *device;
677
678 device = platform_device_alloc(PLATFORM_DRIVER, device_count);
679 if (!device)
680 return;
681
682 /* Temporary assignment to forward the parport */
683 platform_set_drvdata(device, p);
684
685 if (platform_device_register(device) < 0) {
686 platform_device_put(device);
687 return;
688 }
689
690 /* Since we dont get the return value of probe
691 * We need to check if device probing succeeded or not */
692 if (!platform_get_drvdata(device)) {
693 platform_device_unregister(device);
694 return;
695 }
696
697 /* register device in global table */
698 platform_devices[device_count] = device;
699 device_count++;
700}
701
702static void snd_portman_detach(struct parport *p)
703{
704 /* nothing to do here */
705}
706
707static struct parport_driver portman_parport_driver = {
708 .name = "portman2x4",
709 .attach = snd_portman_attach,
710 .detach = snd_portman_detach
711};
712
713/*********************************************************************
714 * platform stuff
715 *********************************************************************/
716static void snd_portman_card_private_free(struct snd_card *card)
717{
718 struct portman *pm = card->private_data;
719 struct pardevice *pardev = pm->pardev;
720
721 if (pardev) {
722 if (pm->pardev_claimed)
723 parport_release(pardev);
724 parport_unregister_device(pardev);
725 }
726
727 portman_free(pm);
728}
729
730static int __devinit snd_portman_probe(struct platform_device *pdev)
731{
732 struct pardevice *pardev;
733 struct parport *p;
734 int dev = pdev->id;
735 struct snd_card *card = NULL;
736 struct portman *pm = NULL;
737 int err;
738
739 p = platform_get_drvdata(pdev);
740 platform_set_drvdata(pdev, NULL);
741
742 if (dev >= SNDRV_CARDS)
743 return -ENODEV;
744 if (!enable[dev])
745 return -ENOENT;
746
747 if ((err = snd_portman_probe_port(p)) < 0)
748 return err;
749
750 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
751 if (card == NULL) {
752 snd_printd("Cannot create card\n");
753 return -ENOMEM;
754 }
755 strcpy(card->driver, DRIVER_NAME);
756 strcpy(card->shortname, CARD_NAME);
757 sprintf(card->longname, "%s at 0x%lx, irq %i",
758 card->shortname, p->base, p->irq);
759
760 pardev = parport_register_device(p, /* port */
761 DRIVER_NAME, /* name */
762 NULL, /* preempt */
763 NULL, /* wakeup */
764 snd_portman_interrupt, /* ISR */
765 PARPORT_DEV_EXCL, /* flags */
766 (void *)card); /* private */
767 if (pardev == NULL) {
768 snd_printd("Cannot register pardevice\n");
769 err = -EIO;
770 goto __err;
771 }
772
773 if ((err = portman_create(card, pardev, &pm)) < 0) {
774 snd_printd("Cannot create main component\n");
775 parport_unregister_device(pardev);
776 goto __err;
777 }
778 card->private_data = pm;
779 card->private_free = snd_portman_card_private_free;
780
781 if ((err = snd_portman_rawmidi_create(card)) < 0) {
782 snd_printd("Creating Rawmidi component failed\n");
783 goto __err;
784 }
785
786 /* claim parport */
787 if (parport_claim(pardev)) {
788 snd_printd("Cannot claim parport 0x%lx\n", pardev->port->base);
789 err = -EIO;
790 goto __err;
791 }
792 pm->pardev_claimed = 1;
793
794 /* init device */
795 if ((err = portman_device_init(pm)) < 0)
796 goto __err;
797
798 platform_set_drvdata(pdev, card);
799
800 /* At this point card will be usable */
801 if ((err = snd_card_register(card)) < 0) {
802 snd_printd("Cannot register card\n");
803 goto __err;
804 }
805
806 snd_printk(KERN_INFO "Portman 2x4 on 0x%lx\n", p->base);
807 return 0;
808
809__err:
810 snd_card_free(card);
811 return err;
812}
813
814static int snd_portman_remove(struct platform_device *pdev)
815{
816 struct snd_card *card = platform_get_drvdata(pdev);
817
818 if (card)
819 snd_card_free(card);
820
821 return 0;
822}
823
824
825static struct platform_driver snd_portman_driver = {
826 .probe = snd_portman_probe,
827 .remove = snd_portman_remove,
828 .driver = {
829 .name = PLATFORM_DRIVER
830 }
831};
832
833/*********************************************************************
834 * module init stuff
835 *********************************************************************/
836static void snd_portman_unregister_all(void)
837{
838 int i;
839
840 for (i = 0; i < SNDRV_CARDS; ++i) {
841 if (platform_devices[i]) {
842 platform_device_unregister(platform_devices[i]);
843 platform_devices[i] = NULL;
844 }
845 }
846 platform_driver_unregister(&snd_portman_driver);
847 parport_unregister_driver(&portman_parport_driver);
848}
849
850static int __init snd_portman_module_init(void)
851{
852 int err;
853
854 if ((err = platform_driver_register(&snd_portman_driver)) < 0)
855 return err;
856
857 if (parport_register_driver(&portman_parport_driver) != 0) {
858 platform_driver_unregister(&snd_portman_driver);
859 return -EIO;
860 }
861
862 if (device_count == 0) {
863 snd_portman_unregister_all();
864 return -ENODEV;
865 }
866
867 return 0;
868}
869
870static void __exit snd_portman_module_exit(void)
871{
872 snd_portman_unregister_all();
873}
874
875module_init(snd_portman_module_init);
876module_exit(snd_portman_module_exit);
diff --git a/sound/drivers/serial-u16550.c b/sound/drivers/serial-u16550.c
index 74028b2219c2..3a86a5820726 100644
--- a/sound/drivers/serial-u16550.c
+++ b/sound/drivers/serial-u16550.c
@@ -117,13 +117,13 @@ MODULE_PARM_DESC(adaptor, "Type of adaptor.");
117#define SERIAL_MODE_INPUT_TRIGGERED (1 << 2) 117#define SERIAL_MODE_INPUT_TRIGGERED (1 << 2)
118#define SERIAL_MODE_OUTPUT_TRIGGERED (1 << 3) 118#define SERIAL_MODE_OUTPUT_TRIGGERED (1 << 3)
119 119
120typedef struct _snd_uart16550 { 120struct snd_uart16550 {
121 struct snd_card *card; 121 struct snd_card *card;
122 struct snd_rawmidi *rmidi; 122 struct snd_rawmidi *rmidi;
123 struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS]; 123 struct snd_rawmidi_substream *midi_output[SNDRV_SERIAL_MAX_OUTS];
124 struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS]; 124 struct snd_rawmidi_substream *midi_input[SNDRV_SERIAL_MAX_INS];
125 125
126 int filemode; //open status of file 126 int filemode; /* open status of file */
127 127
128 spinlock_t open_lock; 128 spinlock_t open_lock;
129 129
@@ -140,39 +140,39 @@ typedef struct _snd_uart16550 {
140 unsigned char old_divisor_msb; 140 unsigned char old_divisor_msb;
141 unsigned char old_line_ctrl_reg; 141 unsigned char old_line_ctrl_reg;
142 142
143 // parameter for using of write loop 143 /* parameter for using of write loop */
144 short int fifo_limit; //used in uart16550 144 short int fifo_limit; /* used in uart16550 */
145 short int fifo_count; //used in uart16550 145 short int fifo_count; /* used in uart16550 */
146 146
147 // type of adaptor 147 /* type of adaptor */
148 int adaptor; 148 int adaptor;
149 149
150 // inputs 150 /* inputs */
151 int prev_in; 151 int prev_in;
152 unsigned char rstatus; 152 unsigned char rstatus;
153 153
154 // outputs 154 /* outputs */
155 int prev_out; 155 int prev_out;
156 unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS]; 156 unsigned char prev_status[SNDRV_SERIAL_MAX_OUTS];
157 157
158 // write buffer and its writing/reading position 158 /* write buffer and its writing/reading position */
159 unsigned char tx_buff[TX_BUFF_SIZE]; 159 unsigned char tx_buff[TX_BUFF_SIZE];
160 int buff_in_count; 160 int buff_in_count;
161 int buff_in; 161 int buff_in;
162 int buff_out; 162 int buff_out;
163 int drop_on_full; 163 int drop_on_full;
164 164
165 // wait timer 165 /* wait timer */
166 unsigned int timer_running:1; 166 unsigned int timer_running:1;
167 struct timer_list buffer_timer; 167 struct timer_list buffer_timer;
168 168
169} snd_uart16550_t; 169};
170 170
171static struct platform_device *devices[SNDRV_CARDS]; 171static struct platform_device *devices[SNDRV_CARDS];
172 172
173static inline void snd_uart16550_add_timer(snd_uart16550_t *uart) 173static inline void snd_uart16550_add_timer(struct snd_uart16550 *uart)
174{ 174{
175 if (! uart->timer_running) { 175 if (!uart->timer_running) {
176 /* timer 38600bps * 10bit * 16byte */ 176 /* timer 38600bps * 10bit * 16byte */
177 uart->buffer_timer.expires = jiffies + (HZ+255)/256; 177 uart->buffer_timer.expires = jiffies + (HZ+255)/256;
178 uart->timer_running = 1; 178 uart->timer_running = 1;
@@ -180,7 +180,7 @@ static inline void snd_uart16550_add_timer(snd_uart16550_t *uart)
180 } 180 }
181} 181}
182 182
183static inline void snd_uart16550_del_timer(snd_uart16550_t *uart) 183static inline void snd_uart16550_del_timer(struct snd_uart16550 *uart)
184{ 184{
185 if (uart->timer_running) { 185 if (uart->timer_running) {
186 del_timer(&uart->buffer_timer); 186 del_timer(&uart->buffer_timer);
@@ -189,10 +189,10 @@ static inline void snd_uart16550_del_timer(snd_uart16550_t *uart)
189} 189}
190 190
191/* This macro is only used in snd_uart16550_io_loop */ 191/* This macro is only used in snd_uart16550_io_loop */
192static inline void snd_uart16550_buffer_output(snd_uart16550_t *uart) 192static inline void snd_uart16550_buffer_output(struct snd_uart16550 *uart)
193{ 193{
194 unsigned short buff_out = uart->buff_out; 194 unsigned short buff_out = uart->buff_out;
195 if( uart->buff_in_count > 0 ) { 195 if (uart->buff_in_count > 0) {
196 outb(uart->tx_buff[buff_out], uart->base + UART_TX); 196 outb(uart->tx_buff[buff_out], uart->base + UART_TX);
197 uart->fifo_count++; 197 uart->fifo_count++;
198 buff_out++; 198 buff_out++;
@@ -206,7 +206,7 @@ static inline void snd_uart16550_buffer_output(snd_uart16550_t *uart)
206 * We don't want to interrupt this, 206 * We don't want to interrupt this,
207 * as we're already handling an interrupt 207 * as we're already handling an interrupt
208 */ 208 */
209static void snd_uart16550_io_loop(snd_uart16550_t * uart) 209static void snd_uart16550_io_loop(struct snd_uart16550 * uart)
210{ 210{
211 unsigned char c, status; 211 unsigned char c, status;
212 int substream; 212 int substream;
@@ -220,9 +220,8 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart)
220 c = inb(uart->base + UART_RX); 220 c = inb(uart->base + UART_RX);
221 221
222 /* keep track of last status byte */ 222 /* keep track of last status byte */
223 if (c & 0x80) { 223 if (c & 0x80)
224 uart->rstatus = c; 224 uart->rstatus = c;
225 }
226 225
227 /* handle stream switch */ 226 /* handle stream switch */
228 if (uart->adaptor == SNDRV_SERIAL_GENERIC) { 227 if (uart->adaptor == SNDRV_SERIAL_GENERIC) {
@@ -230,14 +229,16 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart)
230 if (c <= SNDRV_SERIAL_MAX_INS && c > 0) 229 if (c <= SNDRV_SERIAL_MAX_INS && c > 0)
231 substream = c - 1; 230 substream = c - 1;
232 if (c != 0xf5) 231 if (c != 0xf5)
233 uart->rstatus = 0; /* prevent future bytes from being interpreted as streams */ 232 /* prevent future bytes from being
234 } 233 interpreted as streams */
235 else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { 234 uart->rstatus = 0;
236 snd_rawmidi_receive(uart->midi_input[substream], &c, 1); 235 } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN)
237 } 236 && uart->midi_input[substream])
238 } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) && (uart->midi_input[substream] != NULL)) { 237 snd_rawmidi_receive(uart->midi_input[substream],
238 &c, 1);
239 } else if ((uart->filemode & SERIAL_MODE_INPUT_OPEN) &&
240 uart->midi_input[substream])
239 snd_rawmidi_receive(uart->midi_input[substream], &c, 1); 241 snd_rawmidi_receive(uart->midi_input[substream], &c, 1);
240 }
241 242
242 if (status & UART_LSR_OE) 243 if (status & UART_LSR_OE)
243 snd_printk("%s: Overrun on device at 0x%lx\n", 244 snd_printk("%s: Overrun on device at 0x%lx\n",
@@ -250,21 +251,20 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart)
250 /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not, 251 /* no need of check SERIAL_MODE_OUTPUT_OPEN because if not,
251 buffer is never filled. */ 252 buffer is never filled. */
252 /* Check write status */ 253 /* Check write status */
253 if (status & UART_LSR_THRE) { 254 if (status & UART_LSR_THRE)
254 uart->fifo_count = 0; 255 uart->fifo_count = 0;
255 }
256 if (uart->adaptor == SNDRV_SERIAL_MS124W_SA 256 if (uart->adaptor == SNDRV_SERIAL_MS124W_SA
257 || uart->adaptor == SNDRV_SERIAL_GENERIC) { 257 || uart->adaptor == SNDRV_SERIAL_GENERIC) {
258 /* Can't use FIFO, must send only when CTS is true */ 258 /* Can't use FIFO, must send only when CTS is true */
259 status = inb(uart->base + UART_MSR); 259 status = inb(uart->base + UART_MSR);
260 while( (uart->fifo_count == 0) && (status & UART_MSR_CTS) && 260 while (uart->fifo_count == 0 && (status & UART_MSR_CTS) &&
261 (uart->buff_in_count > 0) ) { 261 uart->buff_in_count > 0) {
262 snd_uart16550_buffer_output(uart); 262 snd_uart16550_buffer_output(uart);
263 status = inb( uart->base + UART_MSR ); 263 status = inb(uart->base + UART_MSR);
264 } 264 }
265 } else { 265 } else {
266 /* Write loop */ 266 /* Write loop */
267 while (uart->fifo_count < uart->fifo_limit /* Can we write ? */ 267 while (uart->fifo_count < uart->fifo_limit /* Can we write ? */
268 && uart->buff_in_count > 0) /* Do we want to? */ 268 && uart->buff_in_count > 0) /* Do we want to? */
269 snd_uart16550_buffer_output(uart); 269 snd_uart16550_buffer_output(uart);
270 } 270 }
@@ -294,15 +294,16 @@ static void snd_uart16550_io_loop(snd_uart16550_t * uart)
294 */ 294 */
295static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id) 295static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id)
296{ 296{
297 snd_uart16550_t *uart; 297 struct snd_uart16550 *uart;
298 298
299 uart = (snd_uart16550_t *) dev_id; 299 uart = dev_id;
300 spin_lock(&uart->open_lock); 300 spin_lock(&uart->open_lock);
301 if (uart->filemode == SERIAL_MODE_NOT_OPENED) { 301 if (uart->filemode == SERIAL_MODE_NOT_OPENED) {
302 spin_unlock(&uart->open_lock); 302 spin_unlock(&uart->open_lock);
303 return IRQ_NONE; 303 return IRQ_NONE;
304 } 304 }
305 inb(uart->base + UART_IIR); /* indicate to the UART that the interrupt has been serviced */ 305 /* indicate to the UART that the interrupt has been serviced */
306 inb(uart->base + UART_IIR);
306 snd_uart16550_io_loop(uart); 307 snd_uart16550_io_loop(uart);
307 spin_unlock(&uart->open_lock); 308 spin_unlock(&uart->open_lock);
308 return IRQ_HANDLED; 309 return IRQ_HANDLED;
@@ -312,9 +313,9 @@ static irqreturn_t snd_uart16550_interrupt(int irq, void *dev_id)
312static void snd_uart16550_buffer_timer(unsigned long data) 313static void snd_uart16550_buffer_timer(unsigned long data)
313{ 314{
314 unsigned long flags; 315 unsigned long flags;
315 snd_uart16550_t *uart; 316 struct snd_uart16550 *uart;
316 317
317 uart = (snd_uart16550_t *)data; 318 uart = (struct snd_uart16550 *)data;
318 spin_lock_irqsave(&uart->open_lock, flags); 319 spin_lock_irqsave(&uart->open_lock, flags);
319 snd_uart16550_del_timer(uart); 320 snd_uart16550_del_timer(uart);
320 snd_uart16550_io_loop(uart); 321 snd_uart16550_io_loop(uart);
@@ -326,7 +327,7 @@ static void snd_uart16550_buffer_timer(unsigned long data)
326 * return 0 if found 327 * return 0 if found
327 * return negative error if not found 328 * return negative error if not found
328 */ 329 */
329static int __init snd_uart16550_detect(snd_uart16550_t *uart) 330static int __init snd_uart16550_detect(struct snd_uart16550 *uart)
330{ 331{
331 unsigned long io_base = uart->base; 332 unsigned long io_base = uart->base;
332 int ok; 333 int ok;
@@ -343,7 +344,8 @@ static int __init snd_uart16550_detect(snd_uart16550_t *uart)
343 return -EBUSY; 344 return -EBUSY;
344 } 345 }
345 346
346 ok = 1; /* uart detected unless one of the following tests should fail */ 347 /* uart detected unless one of the following tests should fail */
348 ok = 1;
347 /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */ 349 /* 8 data-bits, 1 stop-bit, parity off, DLAB = 0 */
348 outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */ 350 outb(UART_LCR_WLEN8, io_base + UART_LCR); /* Line Control Register */
349 c = inb(io_base + UART_IER); 351 c = inb(io_base + UART_IER);
@@ -368,7 +370,7 @@ static int __init snd_uart16550_detect(snd_uart16550_t *uart)
368 return ok; 370 return ok;
369} 371}
370 372
371static void snd_uart16550_do_open(snd_uart16550_t * uart) 373static void snd_uart16550_do_open(struct snd_uart16550 * uart)
372{ 374{
373 char byte; 375 char byte;
374 376
@@ -460,7 +462,7 @@ static void snd_uart16550_do_open(snd_uart16550_t * uart)
460 inb(uart->base + UART_RX); /* Clear any pre-existing receive interrupt */ 462 inb(uart->base + UART_RX); /* Clear any pre-existing receive interrupt */
461} 463}
462 464
463static void snd_uart16550_do_close(snd_uart16550_t * uart) 465static void snd_uart16550_do_close(struct snd_uart16550 * uart)
464{ 466{
465 if (uart->irq < 0) 467 if (uart->irq < 0)
466 snd_uart16550_del_timer(uart); 468 snd_uart16550_del_timer(uart);
@@ -514,7 +516,7 @@ static void snd_uart16550_do_close(snd_uart16550_t * uart)
514static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream) 516static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream)
515{ 517{
516 unsigned long flags; 518 unsigned long flags;
517 snd_uart16550_t *uart = substream->rmidi->private_data; 519 struct snd_uart16550 *uart = substream->rmidi->private_data;
518 520
519 spin_lock_irqsave(&uart->open_lock, flags); 521 spin_lock_irqsave(&uart->open_lock, flags);
520 if (uart->filemode == SERIAL_MODE_NOT_OPENED) 522 if (uart->filemode == SERIAL_MODE_NOT_OPENED)
@@ -528,7 +530,7 @@ static int snd_uart16550_input_open(struct snd_rawmidi_substream *substream)
528static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream) 530static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream)
529{ 531{
530 unsigned long flags; 532 unsigned long flags;
531 snd_uart16550_t *uart = substream->rmidi->private_data; 533 struct snd_uart16550 *uart = substream->rmidi->private_data;
532 534
533 spin_lock_irqsave(&uart->open_lock, flags); 535 spin_lock_irqsave(&uart->open_lock, flags);
534 uart->filemode &= ~SERIAL_MODE_INPUT_OPEN; 536 uart->filemode &= ~SERIAL_MODE_INPUT_OPEN;
@@ -539,24 +541,24 @@ static int snd_uart16550_input_close(struct snd_rawmidi_substream *substream)
539 return 0; 541 return 0;
540} 542}
541 543
542static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream, int up) 544static void snd_uart16550_input_trigger(struct snd_rawmidi_substream *substream,
545 int up)
543{ 546{
544 unsigned long flags; 547 unsigned long flags;
545 snd_uart16550_t *uart = substream->rmidi->private_data; 548 struct snd_uart16550 *uart = substream->rmidi->private_data;
546 549
547 spin_lock_irqsave(&uart->open_lock, flags); 550 spin_lock_irqsave(&uart->open_lock, flags);
548 if (up) { 551 if (up)
549 uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED; 552 uart->filemode |= SERIAL_MODE_INPUT_TRIGGERED;
550 } else { 553 else
551 uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED; 554 uart->filemode &= ~SERIAL_MODE_INPUT_TRIGGERED;
552 }
553 spin_unlock_irqrestore(&uart->open_lock, flags); 555 spin_unlock_irqrestore(&uart->open_lock, flags);
554} 556}
555 557
556static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream) 558static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream)
557{ 559{
558 unsigned long flags; 560 unsigned long flags;
559 snd_uart16550_t *uart = substream->rmidi->private_data; 561 struct snd_uart16550 *uart = substream->rmidi->private_data;
560 562
561 spin_lock_irqsave(&uart->open_lock, flags); 563 spin_lock_irqsave(&uart->open_lock, flags);
562 if (uart->filemode == SERIAL_MODE_NOT_OPENED) 564 if (uart->filemode == SERIAL_MODE_NOT_OPENED)
@@ -570,7 +572,7 @@ static int snd_uart16550_output_open(struct snd_rawmidi_substream *substream)
570static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream) 572static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream)
571{ 573{
572 unsigned long flags; 574 unsigned long flags;
573 snd_uart16550_t *uart = substream->rmidi->private_data; 575 struct snd_uart16550 *uart = substream->rmidi->private_data;
574 576
575 spin_lock_irqsave(&uart->open_lock, flags); 577 spin_lock_irqsave(&uart->open_lock, flags);
576 uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN; 578 uart->filemode &= ~SERIAL_MODE_OUTPUT_OPEN;
@@ -581,18 +583,20 @@ static int snd_uart16550_output_close(struct snd_rawmidi_substream *substream)
581 return 0; 583 return 0;
582}; 584};
583 585
584static inline int snd_uart16550_buffer_can_write( snd_uart16550_t *uart, int Num ) 586static inline int snd_uart16550_buffer_can_write(struct snd_uart16550 *uart,
587 int Num)
585{ 588{
586 if( uart->buff_in_count + Num < TX_BUFF_SIZE ) 589 if (uart->buff_in_count + Num < TX_BUFF_SIZE)
587 return 1; 590 return 1;
588 else 591 else
589 return 0; 592 return 0;
590} 593}
591 594
592static inline int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned char byte) 595static inline int snd_uart16550_write_buffer(struct snd_uart16550 *uart,
596 unsigned char byte)
593{ 597{
594 unsigned short buff_in = uart->buff_in; 598 unsigned short buff_in = uart->buff_in;
595 if( uart->buff_in_count < TX_BUFF_SIZE ) { 599 if (uart->buff_in_count < TX_BUFF_SIZE) {
596 uart->tx_buff[buff_in] = byte; 600 uart->tx_buff[buff_in] = byte;
597 buff_in++; 601 buff_in++;
598 buff_in &= TX_BUFF_MASK; 602 buff_in &= TX_BUFF_MASK;
@@ -605,12 +609,14 @@ static inline int snd_uart16550_write_buffer(snd_uart16550_t *uart, unsigned cha
605 return 0; 609 return 0;
606} 610}
607 611
608static int snd_uart16550_output_byte(snd_uart16550_t *uart, struct snd_rawmidi_substream *substream, unsigned char midi_byte) 612static int snd_uart16550_output_byte(struct snd_uart16550 *uart,
613 struct snd_rawmidi_substream *substream,
614 unsigned char midi_byte)
609{ 615{
610 if (uart->buff_in_count == 0 /* Buffer empty? */ 616 if (uart->buff_in_count == 0 /* Buffer empty? */
611 && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA && 617 && ((uart->adaptor != SNDRV_SERIAL_MS124W_SA &&
612 uart->adaptor != SNDRV_SERIAL_GENERIC) || 618 uart->adaptor != SNDRV_SERIAL_GENERIC) ||
613 (uart->fifo_count == 0 /* FIFO empty? */ 619 (uart->fifo_count == 0 /* FIFO empty? */
614 && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */ 620 && (inb(uart->base + UART_MSR) & UART_MSR_CTS)))) { /* CTS? */
615 621
616 /* Tx Buffer Empty - try to write immediately */ 622 /* Tx Buffer Empty - try to write immediately */
@@ -623,12 +629,13 @@ static int snd_uart16550_output_byte(snd_uart16550_t *uart, struct snd_rawmidi_s
623 uart->fifo_count++; 629 uart->fifo_count++;
624 outb(midi_byte, uart->base + UART_TX); 630 outb(midi_byte, uart->base + UART_TX);
625 } else { 631 } else {
626 /* Cannot write (buffer empty) - put char in buffer */ 632 /* Cannot write (buffer empty) -
633 * put char in buffer */
627 snd_uart16550_write_buffer(uart, midi_byte); 634 snd_uart16550_write_buffer(uart, midi_byte);
628 } 635 }
629 } 636 }
630 } else { 637 } else {
631 if( !snd_uart16550_write_buffer(uart, midi_byte) ) { 638 if (!snd_uart16550_write_buffer(uart, midi_byte)) {
632 snd_printk("%s: Buffer overrun on device at 0x%lx\n", 639 snd_printk("%s: Buffer overrun on device at 0x%lx\n",
633 uart->rmidi->name, uart->base); 640 uart->rmidi->name, uart->base);
634 return 0; 641 return 0;
@@ -642,9 +649,9 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream)
642{ 649{
643 unsigned long flags; 650 unsigned long flags;
644 unsigned char midi_byte, addr_byte; 651 unsigned char midi_byte, addr_byte;
645 snd_uart16550_t *uart = substream->rmidi->private_data; 652 struct snd_uart16550 *uart = substream->rmidi->private_data;
646 char first; 653 char first;
647 static unsigned long lasttime=0; 654 static unsigned long lasttime = 0;
648 655
649 /* Interupts are disabled during the updating of the tx_buff, 656 /* Interupts are disabled during the updating of the tx_buff,
650 * since it is 'bad' to have two processes updating the same 657 * since it is 'bad' to have two processes updating the same
@@ -653,7 +660,7 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream)
653 660
654 spin_lock_irqsave(&uart->open_lock, flags); 661 spin_lock_irqsave(&uart->open_lock, flags);
655 662
656 if (uart->irq < 0) //polling 663 if (uart->irq < 0) /* polling */
657 snd_uart16550_io_loop(uart); 664 snd_uart16550_io_loop(uart);
658 665
659 if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) { 666 if (uart->adaptor == SNDRV_SERIAL_MS124W_MB) {
@@ -671,7 +678,8 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream)
671 /* select any combination of the four ports */ 678 /* select any combination of the four ports */
672 addr_byte = (substream->number << 4) | 0x08; 679 addr_byte = (substream->number << 4) | 0x08;
673 /* ...except none */ 680 /* ...except none */
674 if (addr_byte == 0x08) addr_byte = 0xf8; 681 if (addr_byte == 0x08)
682 addr_byte = 0xf8;
675#endif 683#endif
676 snd_uart16550_output_byte(uart, substream, addr_byte); 684 snd_uart16550_output_byte(uart, substream, addr_byte);
677 /* send midi byte */ 685 /* send midi byte */
@@ -679,31 +687,42 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream)
679 } 687 }
680 } else { 688 } else {
681 first = 0; 689 first = 0;
682 while( 1 == snd_rawmidi_transmit_peek(substream, &midi_byte, 1) ) { 690 while (snd_rawmidi_transmit_peek(substream, &midi_byte, 1) == 1) {
683 /* Also send F5 after 3 seconds with no data to handle device disconnect */ 691 /* Also send F5 after 3 seconds with no data
684 if (first == 0 && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS || 692 * to handle device disconnect */
685 uart->adaptor == SNDRV_SERIAL_GENERIC) && 693 if (first == 0 &&
686 (uart->prev_out != substream->number || jiffies-lasttime > 3*HZ)) { 694 (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS ||
687 695 uart->adaptor == SNDRV_SERIAL_GENERIC) &&
688 if( snd_uart16550_buffer_can_write( uart, 3 ) ) { 696 (uart->prev_out != substream->number ||
697 jiffies-lasttime > 3*HZ)) {
698
699 if (snd_uart16550_buffer_can_write(uart, 3)) {
689 /* Roland Soundcanvas part selection */ 700 /* Roland Soundcanvas part selection */
690 /* If this substream of the data is different previous 701 /* If this substream of the data is
691 substream in this uart, send the change part event */ 702 * different previous substream
703 * in this uart, send the change part
704 * event
705 */
692 uart->prev_out = substream->number; 706 uart->prev_out = substream->number;
693 /* change part */ 707 /* change part */
694 snd_uart16550_output_byte(uart, substream, 0xf5); 708 snd_uart16550_output_byte(uart, substream,
709 0xf5);
695 /* data */ 710 /* data */
696 snd_uart16550_output_byte(uart, substream, uart->prev_out + 1); 711 snd_uart16550_output_byte(uart, substream,
697 /* If midi_byte is a data byte, send the previous status byte */ 712 uart->prev_out + 1);
698 if ((midi_byte < 0x80) && (uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS)) 713 /* If midi_byte is a data byte,
714 * send the previous status byte */
715 if (midi_byte < 0x80 &&
716 uart->adaptor == SNDRV_SERIAL_SOUNDCANVAS)
699 snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]); 717 snd_uart16550_output_byte(uart, substream, uart->prev_status[uart->prev_out]);
700 } else if( !uart->drop_on_full ) 718 } else if (!uart->drop_on_full)
701 break; 719 break;
702 720
703 } 721 }
704 722
705 /* send midi byte */ 723 /* send midi byte */
706 if( !snd_uart16550_output_byte(uart, substream, midi_byte) && !uart->drop_on_full ) 724 if (!snd_uart16550_output_byte(uart, substream, midi_byte) &&
725 !uart->drop_on_full )
707 break; 726 break;
708 727
709 if (midi_byte >= 0x80 && midi_byte < 0xf0) 728 if (midi_byte >= 0x80 && midi_byte < 0xf0)
@@ -717,17 +736,17 @@ static void snd_uart16550_output_write(struct snd_rawmidi_substream *substream)
717 spin_unlock_irqrestore(&uart->open_lock, flags); 736 spin_unlock_irqrestore(&uart->open_lock, flags);
718} 737}
719 738
720static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream, int up) 739static void snd_uart16550_output_trigger(struct snd_rawmidi_substream *substream,
740 int up)
721{ 741{
722 unsigned long flags; 742 unsigned long flags;
723 snd_uart16550_t *uart = substream->rmidi->private_data; 743 struct snd_uart16550 *uart = substream->rmidi->private_data;
724 744
725 spin_lock_irqsave(&uart->open_lock, flags); 745 spin_lock_irqsave(&uart->open_lock, flags);
726 if (up) { 746 if (up)
727 uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED; 747 uart->filemode |= SERIAL_MODE_OUTPUT_TRIGGERED;
728 } else { 748 else
729 uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED; 749 uart->filemode &= ~SERIAL_MODE_OUTPUT_TRIGGERED;
730 }
731 spin_unlock_irqrestore(&uart->open_lock, flags); 750 spin_unlock_irqrestore(&uart->open_lock, flags);
732 if (up) 751 if (up)
733 snd_uart16550_output_write(substream); 752 snd_uart16550_output_write(substream);
@@ -747,10 +766,10 @@ static struct snd_rawmidi_ops snd_uart16550_input =
747 .trigger = snd_uart16550_input_trigger, 766 .trigger = snd_uart16550_input_trigger,
748}; 767};
749 768
750static int snd_uart16550_free(snd_uart16550_t *uart) 769static int snd_uart16550_free(struct snd_uart16550 *uart)
751{ 770{
752 if (uart->irq >= 0) 771 if (uart->irq >= 0)
753 free_irq(uart->irq, (void *)uart); 772 free_irq(uart->irq, uart);
754 release_and_free_resource(uart->res_base); 773 release_and_free_resource(uart->res_base);
755 kfree(uart); 774 kfree(uart);
756 return 0; 775 return 0;
@@ -758,7 +777,7 @@ static int snd_uart16550_free(snd_uart16550_t *uart)
758 777
759static int snd_uart16550_dev_free(struct snd_device *device) 778static int snd_uart16550_dev_free(struct snd_device *device)
760{ 779{
761 snd_uart16550_t *uart = device->device_data; 780 struct snd_uart16550 *uart = device->device_data;
762 return snd_uart16550_free(uart); 781 return snd_uart16550_free(uart);
763} 782}
764 783
@@ -769,12 +788,12 @@ static int __init snd_uart16550_create(struct snd_card *card,
769 unsigned int base, 788 unsigned int base,
770 int adaptor, 789 int adaptor,
771 int droponfull, 790 int droponfull,
772 snd_uart16550_t **ruart) 791 struct snd_uart16550 **ruart)
773{ 792{
774 static struct snd_device_ops ops = { 793 static struct snd_device_ops ops = {
775 .dev_free = snd_uart16550_dev_free, 794 .dev_free = snd_uart16550_dev_free,
776 }; 795 };
777 snd_uart16550_t *uart; 796 struct snd_uart16550 *uart;
778 int err; 797 int err;
779 798
780 799
@@ -795,7 +814,7 @@ static int __init snd_uart16550_create(struct snd_card *card,
795 814
796 if (irq >= 0 && irq != SNDRV_AUTO_IRQ) { 815 if (irq >= 0 && irq != SNDRV_AUTO_IRQ) {
797 if (request_irq(irq, snd_uart16550_interrupt, 816 if (request_irq(irq, snd_uart16550_interrupt,
798 IRQF_DISABLED, "Serial MIDI", (void *) uart)) { 817 IRQF_DISABLED, "Serial MIDI", uart)) {
799 snd_printk("irq %d busy. Using Polling.\n", irq); 818 snd_printk("irq %d busy. Using Polling.\n", irq);
800 } else { 819 } else {
801 uart->irq = irq; 820 uart->irq = irq;
@@ -843,23 +862,28 @@ static int __init snd_uart16550_create(struct snd_card *card,
843 862
844static void __init snd_uart16550_substreams(struct snd_rawmidi_str *stream) 863static void __init snd_uart16550_substreams(struct snd_rawmidi_str *stream)
845{ 864{
846 struct list_head *list; 865 struct snd_rawmidi_substream *substream;
847 866
848 list_for_each(list, &stream->substreams) { 867 list_for_each_entry(substream, &stream->substreams, list) {
849 struct snd_rawmidi_substream *substream = list_entry(list, struct snd_rawmidi_substream, list);
850 sprintf(substream->name, "Serial MIDI %d", substream->number + 1); 868 sprintf(substream->name, "Serial MIDI %d", substream->number + 1);
851 } 869 }
852} 870}
853 871
854static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int outs, int ins, struct snd_rawmidi **rmidi) 872static int __init snd_uart16550_rmidi(struct snd_uart16550 *uart, int device,
873 int outs, int ins,
874 struct snd_rawmidi **rmidi)
855{ 875{
856 struct snd_rawmidi *rrawmidi; 876 struct snd_rawmidi *rrawmidi;
857 int err; 877 int err;
858 878
859 if ((err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device, outs, ins, &rrawmidi)) < 0) 879 err = snd_rawmidi_new(uart->card, "UART Serial MIDI", device,
880 outs, ins, &rrawmidi);
881 if (err < 0)
860 return err; 882 return err;
861 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT, &snd_uart16550_input); 883 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_INPUT,
862 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_uart16550_output); 884 &snd_uart16550_input);
885 snd_rawmidi_set_ops(rrawmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
886 &snd_uart16550_output);
863 strcpy(rrawmidi->name, "Serial MIDI"); 887 strcpy(rrawmidi->name, "Serial MIDI");
864 snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]); 888 snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_OUTPUT]);
865 snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]); 889 snd_uart16550_substreams(&rrawmidi->streams[SNDRV_RAWMIDI_STREAM_INPUT]);
@@ -875,7 +899,7 @@ static int __init snd_uart16550_rmidi(snd_uart16550_t *uart, int device, int out
875static int __init snd_serial_probe(struct platform_device *devptr) 899static int __init snd_serial_probe(struct platform_device *devptr)
876{ 900{
877 struct snd_card *card; 901 struct snd_card *card;
878 snd_uart16550_t *uart; 902 struct snd_uart16550 *uart;
879 int err; 903 int err;
880 int dev = devptr->id; 904 int dev = devptr->id;
881 905
@@ -929,7 +953,8 @@ static int __init snd_serial_probe(struct platform_device *devptr)
929 &uart)) < 0) 953 &uart)) < 0)
930 goto _err; 954 goto _err;
931 955
932 if ((err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi)) < 0) 956 err = snd_uart16550_rmidi(uart, 0, outs[dev], ins[dev], &uart->rmidi);
957 if (err < 0)
933 goto _err; 958 goto _err;
934 959
935 sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d", 960 sprintf(card->longname, "%s at 0x%lx, irq %d speed %d div %d outs %d ins %d adaptor %s droponfull %d",
diff --git a/sound/drivers/vx/vx_mixer.c b/sound/drivers/vx/vx_mixer.c
index 1613ed844ac6..f63152a6a223 100644
--- a/sound/drivers/vx/vx_mixer.c
+++ b/sound/drivers/vx/vx_mixer.c
@@ -716,7 +716,7 @@ static int vx_monitor_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
716 return 0; 716 return 0;
717} 717}
718 718
719static DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0); 719static const DECLARE_TLV_DB_SCALE(db_scale_audio_gain, -10975, 25, 0);
720 720
721static struct snd_kcontrol_new vx_control_audio_gain = { 721static struct snd_kcontrol_new vx_control_audio_gain = {
722 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 722 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
diff --git a/sound/i2c/Makefile b/sound/i2c/Makefile
index 816a2e7c88ca..45902d48c89c 100644
--- a/sound/i2c/Makefile
+++ b/sound/i2c/Makefile
@@ -16,3 +16,4 @@ obj-$(CONFIG_SND) += other/
16# Toplevel Module Dependency 16# Toplevel Module Dependency
17obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o 17obj-$(CONFIG_SND_INTERWAVE_STB) += snd-tea6330t.o snd-i2c.o
18obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o 18obj-$(CONFIG_SND_ICE1712) += snd-cs8427.o snd-i2c.o
19obj-$(CONFIG_SND_ICE1724) += snd-i2c.o
diff --git a/sound/i2c/other/Makefile b/sound/i2c/other/Makefile
index 2fe023ef00a7..77a8a7c75dd9 100644
--- a/sound/i2c/other/Makefile
+++ b/sound/i2c/other/Makefile
@@ -6,11 +6,11 @@
6snd-ak4114-objs := ak4114.o 6snd-ak4114-objs := ak4114.o
7snd-ak4117-objs := ak4117.o 7snd-ak4117-objs := ak4117.o
8snd-ak4xxx-adda-objs := ak4xxx-adda.o 8snd-ak4xxx-adda-objs := ak4xxx-adda.o
9snd-pt2258-objs := pt2258.o
9snd-tea575x-tuner-objs := tea575x-tuner.o 10snd-tea575x-tuner-objs := tea575x-tuner.o
10 11
11# Module Dependency 12# Module Dependency
12obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o 13obj-$(CONFIG_SND_PDAUDIOCF) += snd-ak4117.o
13obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o 14obj-$(CONFIG_SND_ICE1712) += snd-ak4xxx-adda.o
14obj-$(CONFIG_SND_ICE1724) += snd-ak4xxx-adda.o 15obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o snd-ak4xxx-adda.o snd-pt2258.o
15obj-$(CONFIG_SND_ICE1724) += snd-ak4114.o
16obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o 16obj-$(CONFIG_SND_FM801_TEA575X) += snd-tea575x-tuner.o
diff --git a/sound/i2c/other/ak4114.c b/sound/i2c/other/ak4114.c
index d2f2c5078e65..adbfd5884d06 100644
--- a/sound/i2c/other/ak4114.c
+++ b/sound/i2c/other/ak4114.c
@@ -42,8 +42,8 @@ static void reg_write(struct ak4114 *ak4114, unsigned char reg, unsigned char va
42 ak4114->write(ak4114->private_data, reg, val); 42 ak4114->write(ak4114->private_data, reg, val);
43 if (reg <= AK4114_REG_INT1_MASK) 43 if (reg <= AK4114_REG_INT1_MASK)
44 ak4114->regmap[reg] = val; 44 ak4114->regmap[reg] = val;
45 else if (reg >= AK4114_REG_RXCSB0 && reg <= AK4114_REG_TXCSB4) 45 else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4)
46 ak4114->txcsb[reg-AK4114_REG_RXCSB0] = val; 46 ak4114->txcsb[reg-AK4114_REG_TXCSB0] = val;
47} 47}
48 48
49static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg) 49static inline unsigned char reg_read(struct ak4114 *ak4114, unsigned char reg)
@@ -66,10 +66,8 @@ static void snd_ak4114_free(struct ak4114 *chip)
66{ 66{
67 chip->init = 1; /* don't schedule new work */ 67 chip->init = 1; /* don't schedule new work */
68 mb(); 68 mb();
69 if (chip->workqueue != NULL) { 69 cancel_delayed_work(&chip->work);
70 flush_workqueue(chip->workqueue); 70 flush_scheduled_work();
71 destroy_workqueue(chip->workqueue);
72 }
73 kfree(chip); 71 kfree(chip);
74} 72}
75 73
@@ -82,7 +80,7 @@ static int snd_ak4114_dev_free(struct snd_device *device)
82 80
83int snd_ak4114_create(struct snd_card *card, 81int snd_ak4114_create(struct snd_card *card,
84 ak4114_read_t *read, ak4114_write_t *write, 82 ak4114_read_t *read, ak4114_write_t *write,
85 unsigned char pgm[7], unsigned char txcsb[5], 83 const unsigned char pgm[7], const unsigned char txcsb[5],
86 void *private_data, struct ak4114 **r_ak4114) 84 void *private_data, struct ak4114 **r_ak4114)
87{ 85{
88 struct ak4114 *chip; 86 struct ak4114 *chip;
@@ -100,18 +98,13 @@ int snd_ak4114_create(struct snd_card *card,
100 chip->read = read; 98 chip->read = read;
101 chip->write = write; 99 chip->write = write;
102 chip->private_data = private_data; 100 chip->private_data = private_data;
101 INIT_DELAYED_WORK(&chip->work, ak4114_stats);
103 102
104 for (reg = 0; reg < 7; reg++) 103 for (reg = 0; reg < 7; reg++)
105 chip->regmap[reg] = pgm[reg]; 104 chip->regmap[reg] = pgm[reg];
106 for (reg = 0; reg < 5; reg++) 105 for (reg = 0; reg < 5; reg++)
107 chip->txcsb[reg] = txcsb[reg]; 106 chip->txcsb[reg] = txcsb[reg];
108 107
109 chip->workqueue = create_workqueue("snd-ak4114");
110 if (chip->workqueue == NULL) {
111 kfree(chip);
112 return -ENOMEM;
113 }
114
115 snd_ak4114_reinit(chip); 108 snd_ak4114_reinit(chip);
116 109
117 chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT); 110 chip->rcs0 = reg_read(chip, AK4114_REG_RCS0) & ~(AK4114_QINT | AK4114_CINT);
@@ -134,7 +127,8 @@ void snd_ak4114_reg_write(struct ak4114 *chip, unsigned char reg, unsigned char
134 if (reg <= AK4114_REG_INT1_MASK) 127 if (reg <= AK4114_REG_INT1_MASK)
135 reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val); 128 reg_write(chip, reg, (chip->regmap[reg] & ~mask) | val);
136 else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4) 129 else if (reg >= AK4114_REG_TXCSB0 && reg <= AK4114_REG_TXCSB4)
137 reg_write(chip, reg, (chip->txcsb[reg] & ~mask) | val); 130 reg_write(chip, reg,
131 (chip->txcsb[reg-AK4114_REG_TXCSB0] & ~mask) | val);
138} 132}
139 133
140void snd_ak4114_reinit(struct ak4114 *chip) 134void snd_ak4114_reinit(struct ak4114 *chip)
@@ -143,7 +137,7 @@ void snd_ak4114_reinit(struct ak4114 *chip)
143 137
144 chip->init = 1; 138 chip->init = 1;
145 mb(); 139 mb();
146 flush_workqueue(chip->workqueue); 140 flush_scheduled_work();
147 /* bring the chip to reset state and powerdown state */ 141 /* bring the chip to reset state and powerdown state */
148 reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN)); 142 reg_write(chip, AK4114_REG_PWRDN, old & ~(AK4114_RST|AK4114_PWN));
149 udelay(200); 143 udelay(200);
@@ -158,8 +152,7 @@ void snd_ak4114_reinit(struct ak4114 *chip)
158 reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN); 152 reg_write(chip, AK4114_REG_PWRDN, old | AK4114_RST | AK4114_PWN);
159 /* bring up statistics / event queing */ 153 /* bring up statistics / event queing */
160 chip->init = 0; 154 chip->init = 0;
161 INIT_DELAYED_WORK(&chip->work, ak4114_stats); 155 schedule_delayed_work(&chip->work, HZ / 10);
162 queue_delayed_work(chip->workqueue, &chip->work, HZ / 10);
163} 156}
164 157
165static unsigned int external_rate(unsigned char rcs1) 158static unsigned int external_rate(unsigned char rcs1)
@@ -568,7 +561,7 @@ static void ak4114_stats(struct work_struct *work)
568 if (chip->init) 561 if (chip->init)
569 return; 562 return;
570 snd_ak4114_check_rate_and_errors(chip, 0); 563 snd_ak4114_check_rate_and_errors(chip, 0);
571 queue_delayed_work(chip->workqueue, &chip->work, HZ / 10); 564 schedule_delayed_work(&chip->work, HZ / 10);
572} 565}
573 566
574EXPORT_SYMBOL(snd_ak4114_create); 567EXPORT_SYMBOL(snd_ak4114_create);
diff --git a/sound/i2c/other/ak4117.c b/sound/i2c/other/ak4117.c
index 4e45952dd95a..c022f29da2f7 100644
--- a/sound/i2c/other/ak4117.c
+++ b/sound/i2c/other/ak4117.c
@@ -74,7 +74,7 @@ static int snd_ak4117_dev_free(struct snd_device *device)
74} 74}
75 75
76int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write, 76int snd_ak4117_create(struct snd_card *card, ak4117_read_t *read, ak4117_write_t *write,
77 unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117) 77 const unsigned char pgm[5], void *private_data, struct ak4117 **r_ak4117)
78{ 78{
79 struct ak4117 *chip; 79 struct ak4117 *chip;
80 int err = 0; 80 int err = 0;
diff --git a/sound/i2c/other/ak4xxx-adda.c b/sound/i2c/other/ak4xxx-adda.c
index 5da49e2eb350..8805110017a7 100644
--- a/sound/i2c/other/ak4xxx-adda.c
+++ b/sound/i2c/other/ak4xxx-adda.c
@@ -140,7 +140,7 @@ EXPORT_SYMBOL(snd_akm4xxx_reset);
140 * Used for AK4524 input/ouput attenuation, AK4528, and 140 * Used for AK4524 input/ouput attenuation, AK4528, and
141 * AK5365 input attenuation 141 * AK5365 input attenuation
142 */ 142 */
143static unsigned char vol_cvt_datt[128] = { 143static const unsigned char vol_cvt_datt[128] = {
144 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04, 144 0x00, 0x01, 0x01, 0x02, 0x02, 0x03, 0x03, 0x04,
145 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06, 145 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x06, 0x06,
146 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a, 146 0x06, 0x07, 0x07, 0x08, 0x08, 0x08, 0x09, 0x0a,
@@ -162,17 +162,17 @@ static unsigned char vol_cvt_datt[128] = {
162/* 162/*
163 * dB tables 163 * dB tables
164 */ 164 */
165static DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1); 165static const DECLARE_TLV_DB_SCALE(db_scale_vol_datt, -6350, 50, 1);
166static DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1); 166static const DECLARE_TLV_DB_SCALE(db_scale_8bit, -12750, 50, 1);
167static DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1); 167static const DECLARE_TLV_DB_SCALE(db_scale_7bit, -6350, 50, 1);
168static DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0); 168static const DECLARE_TLV_DB_LINEAR(db_scale_linear, TLV_DB_GAIN_MUTE, 0);
169 169
170/* 170/*
171 * initialize all the ak4xxx chips 171 * initialize all the ak4xxx chips
172 */ 172 */
173void snd_akm4xxx_init(struct snd_akm4xxx *ak) 173void snd_akm4xxx_init(struct snd_akm4xxx *ak)
174{ 174{
175 static unsigned char inits_ak4524[] = { 175 static const unsigned char inits_ak4524[] = {
176 0x00, 0x07, /* 0: all power up */ 176 0x00, 0x07, /* 0: all power up */
177 0x01, 0x00, /* 1: ADC/DAC reset */ 177 0x01, 0x00, /* 1: ADC/DAC reset */
178 0x02, 0x60, /* 2: 24bit I2S */ 178 0x02, 0x60, /* 2: 24bit I2S */
@@ -184,7 +184,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
184 0x07, 0x00, /* 7: DAC right muted */ 184 0x07, 0x00, /* 7: DAC right muted */
185 0xff, 0xff 185 0xff, 0xff
186 }; 186 };
187 static unsigned char inits_ak4528[] = { 187 static const unsigned char inits_ak4528[] = {
188 0x00, 0x07, /* 0: all power up */ 188 0x00, 0x07, /* 0: all power up */
189 0x01, 0x00, /* 1: ADC/DAC reset */ 189 0x01, 0x00, /* 1: ADC/DAC reset */
190 0x02, 0x60, /* 2: 24bit I2S */ 190 0x02, 0x60, /* 2: 24bit I2S */
@@ -194,7 +194,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
194 0x05, 0x00, /* 5: ADC right muted */ 194 0x05, 0x00, /* 5: ADC right muted */
195 0xff, 0xff 195 0xff, 0xff
196 }; 196 };
197 static unsigned char inits_ak4529[] = { 197 static const unsigned char inits_ak4529[] = {
198 0x09, 0x01, /* 9: ATS=0, RSTN=1 */ 198 0x09, 0x01, /* 9: ATS=0, RSTN=1 */
199 0x0a, 0x3f, /* A: all power up, no zero/overflow detection */ 199 0x0a, 0x3f, /* A: all power up, no zero/overflow detection */
200 0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */ 200 0x00, 0x0c, /* 0: TDM=0, 24bit I2S, SMUTE=0 */
@@ -210,7 +210,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
210 0x08, 0x55, /* 8: deemphasis all off */ 210 0x08, 0x55, /* 8: deemphasis all off */
211 0xff, 0xff 211 0xff, 0xff
212 }; 212 };
213 static unsigned char inits_ak4355[] = { 213 static const unsigned char inits_ak4355[] = {
214 0x01, 0x02, /* 1: reset and soft-mute */ 214 0x01, 0x02, /* 1: reset and soft-mute */
215 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, 215 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect,
216 * disable DZF, sharp roll-off, RSTN#=0 */ 216 * disable DZF, sharp roll-off, RSTN#=0 */
@@ -227,7 +227,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
227 0x01, 0x01, /* 1: un-reset, unmute */ 227 0x01, 0x01, /* 1: un-reset, unmute */
228 0xff, 0xff 228 0xff, 0xff
229 }; 229 };
230 static unsigned char inits_ak4358[] = { 230 static const unsigned char inits_ak4358[] = {
231 0x01, 0x02, /* 1: reset and soft-mute */ 231 0x01, 0x02, /* 1: reset and soft-mute */
232 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect, 232 0x00, 0x06, /* 0: mode3(i2s), disable auto-clock detect,
233 * disable DZF, sharp roll-off, RSTN#=0 */ 233 * disable DZF, sharp roll-off, RSTN#=0 */
@@ -246,7 +246,7 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
246 0x01, 0x01, /* 1: un-reset, unmute */ 246 0x01, 0x01, /* 1: un-reset, unmute */
247 0xff, 0xff 247 0xff, 0xff
248 }; 248 };
249 static unsigned char inits_ak4381[] = { 249 static const unsigned char inits_ak4381[] = {
250 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */ 250 0x00, 0x0c, /* 0: mode3(i2s), disable auto-clock detect */
251 0x01, 0x02, /* 1: de-emphasis off, normal speed, 251 0x01, 0x02, /* 1: de-emphasis off, normal speed,
252 * sharp roll-off, DZF off */ 252 * sharp roll-off, DZF off */
@@ -259,7 +259,8 @@ void snd_akm4xxx_init(struct snd_akm4xxx *ak)
259 }; 259 };
260 260
261 int chip, num_chips; 261 int chip, num_chips;
262 unsigned char *ptr, reg, data, *inits; 262 const unsigned char *ptr, *inits;
263 unsigned char reg, data;
263 264
264 memset(ak->images, 0, sizeof(ak->images)); 265 memset(ak->images, 0, sizeof(ak->images));
265 memset(ak->volumes, 0, sizeof(ak->volumes)); 266 memset(ak->volumes, 0, sizeof(ak->volumes));
@@ -513,6 +514,66 @@ static int ak4xxx_switch_put(struct snd_kcontrol *kcontrol,
513 return change; 514 return change;
514} 515}
515 516
517#define AK5365_NUM_INPUTS 5
518
519static int ak4xxx_capture_source_info(struct snd_kcontrol *kcontrol,
520 struct snd_ctl_elem_info *uinfo)
521{
522 struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
523 int mixer_ch = AK_GET_SHIFT(kcontrol->private_value);
524 const char **input_names;
525 int num_names, idx;
526
527 input_names = ak->adc_info[mixer_ch].input_names;
528
529 num_names = 0;
530 while (num_names < AK5365_NUM_INPUTS && input_names[num_names])
531 ++num_names;
532
533 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
534 uinfo->count = 1;
535 uinfo->value.enumerated.items = num_names;
536 idx = uinfo->value.enumerated.item;
537 if (idx >= num_names)
538 return -EINVAL;
539 strncpy(uinfo->value.enumerated.name, input_names[idx],
540 sizeof(uinfo->value.enumerated.name));
541 return 0;
542}
543
544static int ak4xxx_capture_source_get(struct snd_kcontrol *kcontrol,
545 struct snd_ctl_elem_value *ucontrol)
546{
547 struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
548 int chip = AK_GET_CHIP(kcontrol->private_value);
549 int addr = AK_GET_ADDR(kcontrol->private_value);
550 int mask = AK_GET_MASK(kcontrol->private_value);
551 unsigned char val;
552
553 val = snd_akm4xxx_get(ak, chip, addr) & mask;
554 ucontrol->value.enumerated.item[0] = val;
555 return 0;
556}
557
558static int ak4xxx_capture_source_put(struct snd_kcontrol *kcontrol,
559 struct snd_ctl_elem_value *ucontrol)
560{
561 struct snd_akm4xxx *ak = snd_kcontrol_chip(kcontrol);
562 int chip = AK_GET_CHIP(kcontrol->private_value);
563 int addr = AK_GET_ADDR(kcontrol->private_value);
564 int mask = AK_GET_MASK(kcontrol->private_value);
565 unsigned char oval, val;
566
567 oval = snd_akm4xxx_get(ak, chip, addr);
568 val = oval & ~mask;
569 val |= ucontrol->value.enumerated.item[0] & mask;
570 if (val != oval) {
571 snd_akm4xxx_write(ak, chip, addr, val);
572 return 1;
573 }
574 return 0;
575}
576
516/* 577/*
517 * build AK4xxx controls 578 * build AK4xxx controls
518 */ 579 */
@@ -647,9 +708,10 @@ static int build_adc_controls(struct snd_akm4xxx *ak)
647 708
648 if (ak->type == SND_AK5365 && (idx % 2) == 0) { 709 if (ak->type == SND_AK5365 && (idx % 2) == 0) {
649 if (! ak->adc_info || 710 if (! ak->adc_info ||
650 ! ak->adc_info[mixer_ch].switch_name) 711 ! ak->adc_info[mixer_ch].switch_name) {
651 knew.name = "Capture Switch"; 712 knew.name = "Capture Switch";
652 else 713 knew.index = mixer_ch + ak->idx_offset * 2;
714 } else
653 knew.name = ak->adc_info[mixer_ch].switch_name; 715 knew.name = ak->adc_info[mixer_ch].switch_name;
654 knew.info = ak4xxx_switch_info; 716 knew.info = ak4xxx_switch_info;
655 knew.get = ak4xxx_switch_get; 717 knew.get = ak4xxx_switch_get;
@@ -662,6 +724,26 @@ static int build_adc_controls(struct snd_akm4xxx *ak)
662 err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak)); 724 err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
663 if (err < 0) 725 if (err < 0)
664 return err; 726 return err;
727
728 memset(&knew, 0, sizeof(knew));
729 knew.name = ak->adc_info[mixer_ch].selector_name;
730 if (!knew.name) {
731 knew.name = "Capture Channel";
732 knew.index = mixer_ch + ak->idx_offset * 2;
733 }
734
735 knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
736 knew.info = ak4xxx_capture_source_info;
737 knew.get = ak4xxx_capture_source_get;
738 knew.put = ak4xxx_capture_source_put;
739 knew.access = 0;
740 /* input selector control: reg. 1, bits 0-2.
741 * mis-use 'shift' to pass mixer_ch */
742 knew.private_value
743 = AK_COMPOSE(idx/2, 1, mixer_ch, 0x07);
744 err = snd_ctl_add(ak->card, snd_ctl_new1(&knew, ak));
745 if (err < 0)
746 return err;
665 } 747 }
666 748
667 idx += num_stereo; 749 idx += num_stereo;
diff --git a/sound/i2c/other/pt2258.c b/sound/i2c/other/pt2258.c
new file mode 100644
index 000000000000..e91cc3b44de5
--- /dev/null
+++ b/sound/i2c/other/pt2258.c
@@ -0,0 +1,233 @@
1/*
2 * ALSA Driver for the PT2258 volume controller.
3 *
4 * Copyright (c) 2006 Jochen Voss <voss@seehuhn.de>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 *
20 */
21
22#include <sound/driver.h>
23#include <sound/core.h>
24#include <sound/control.h>
25#include <sound/tlv.h>
26#include <sound/i2c.h>
27#include <sound/pt2258.h>
28
29MODULE_AUTHOR("Jochen Voss <voss@seehuhn.de>");
30MODULE_DESCRIPTION("PT2258 volume controller (Princeton Technology Corp.)");
31MODULE_LICENSE("GPL");
32
33#define PT2258_CMD_RESET 0xc0
34#define PT2258_CMD_UNMUTE 0xf8
35#define PT2258_CMD_MUTE 0xf9
36
37static const unsigned char pt2258_channel_code[12] = {
38 0x80, 0x90, /* channel 1: -10dB, -1dB */
39 0x40, 0x50, /* channel 2: -10dB, -1dB */
40 0x00, 0x10, /* channel 3: -10dB, -1dB */
41 0x20, 0x30, /* channel 4: -10dB, -1dB */
42 0x60, 0x70, /* channel 5: -10dB, -1dB */
43 0xa0, 0xb0 /* channel 6: -10dB, -1dB */
44};
45
46int snd_pt2258_reset(struct snd_pt2258 *pt)
47{
48 unsigned char bytes[2];
49 int i;
50
51 /* reset chip */
52 bytes[0] = PT2258_CMD_RESET;
53 snd_i2c_lock(pt->i2c_bus);
54 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
55 goto __error;
56 snd_i2c_unlock(pt->i2c_bus);
57
58 /* mute all channels */
59 pt->mute = 1;
60 bytes[0] = PT2258_CMD_MUTE;
61 snd_i2c_lock(pt->i2c_bus);
62 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
63 goto __error;
64 snd_i2c_unlock(pt->i2c_bus);
65
66 /* set all channels to 0dB */
67 for (i = 0; i < 6; ++i)
68 pt->volume[i] = 0;
69 bytes[0] = 0xd0;
70 bytes[1] = 0xe0;
71 snd_i2c_lock(pt->i2c_bus);
72 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
73 goto __error;
74 snd_i2c_unlock(pt->i2c_bus);
75
76 return 0;
77
78 __error:
79 snd_i2c_unlock(pt->i2c_bus);
80 snd_printk(KERN_ERR "PT2258 reset failed\n");
81 return -EIO;
82}
83
84static int pt2258_stereo_volume_info(struct snd_kcontrol *kcontrol,
85 struct snd_ctl_elem_info *uinfo)
86{
87 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
88 uinfo->count = 2;
89 uinfo->value.integer.min = 0;
90 uinfo->value.integer.max = 79;
91 return 0;
92}
93
94static int pt2258_stereo_volume_get(struct snd_kcontrol *kcontrol,
95 struct snd_ctl_elem_value *ucontrol)
96{
97 struct snd_pt2258 *pt = kcontrol->private_data;
98 int base = kcontrol->private_value;
99
100 /* chip does not support register reads */
101 ucontrol->value.integer.value[0] = 79 - pt->volume[base];
102 ucontrol->value.integer.value[1] = 79 - pt->volume[base + 1];
103 return 0;
104}
105
106static int pt2258_stereo_volume_put(struct snd_kcontrol *kcontrol,
107 struct snd_ctl_elem_value *ucontrol)
108{
109 struct snd_pt2258 *pt = kcontrol->private_data;
110 int base = kcontrol->private_value;
111 unsigned char bytes[2];
112 int val0, val1;
113
114 val0 = 79 - ucontrol->value.integer.value[0];
115 val1 = 79 - ucontrol->value.integer.value[1];
116 if (val0 == pt->volume[base] && val1 == pt->volume[base + 1])
117 return 0;
118
119 pt->volume[base] = val0;
120 bytes[0] = pt2258_channel_code[2 * base] | (val0 / 10);
121 bytes[1] = pt2258_channel_code[2 * base + 1] | (val0 % 10);
122 snd_i2c_lock(pt->i2c_bus);
123 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
124 goto __error;
125 snd_i2c_unlock(pt->i2c_bus);
126
127 pt->volume[base + 1] = val1;
128 bytes[0] = pt2258_channel_code[2 * base + 2] | (val1 / 10);
129 bytes[1] = pt2258_channel_code[2 * base + 3] | (val1 % 10);
130 snd_i2c_lock(pt->i2c_bus);
131 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 2) != 2)
132 goto __error;
133 snd_i2c_unlock(pt->i2c_bus);
134
135 return 1;
136
137 __error:
138 snd_i2c_unlock(pt->i2c_bus);
139 snd_printk(KERN_ERR "PT2258 access failed\n");
140 return -EIO;
141}
142
143static int pt2258_switch_info(struct snd_kcontrol *kcontrol,
144 struct snd_ctl_elem_info *uinfo)
145{
146 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
147 uinfo->count = 1;
148 uinfo->value.integer.min = 0;
149 uinfo->value.integer.max = 1;
150 return 0;
151}
152
153static int pt2258_switch_get(struct snd_kcontrol *kcontrol,
154 struct snd_ctl_elem_value *ucontrol)
155{
156 struct snd_pt2258 *pt = kcontrol->private_data;
157
158 ucontrol->value.integer.value[0] = !pt->mute;
159 return 0;
160}
161
162static int pt2258_switch_put(struct snd_kcontrol *kcontrol,
163 struct snd_ctl_elem_value *ucontrol)
164{
165 struct snd_pt2258 *pt = kcontrol->private_data;
166 unsigned char bytes[2];
167 int val;
168
169 val = !ucontrol->value.integer.value[0];
170 if (pt->mute == val)
171 return 0;
172
173 pt->mute = val;
174 bytes[0] = val ? PT2258_CMD_MUTE : PT2258_CMD_UNMUTE;
175 snd_i2c_lock(pt->i2c_bus);
176 if (snd_i2c_sendbytes(pt->i2c_dev, bytes, 1) != 1)
177 goto __error;
178 snd_i2c_unlock(pt->i2c_bus);
179
180 return 1;
181
182 __error:
183 snd_i2c_unlock(pt->i2c_bus);
184 snd_printk(KERN_ERR "PT2258 access failed 2\n");
185 return -EIO;
186}
187
188static const DECLARE_TLV_DB_SCALE(pt2258_db_scale, -7900, 100, 0);
189
190int snd_pt2258_build_controls(struct snd_pt2258 *pt)
191{
192 struct snd_kcontrol_new knew;
193 char *names[3] = {
194 "Mic Loopback Playback Volume",
195 "Line Loopback Playback Volume",
196 "CD Loopback Playback Volume"
197 };
198 int i, err;
199
200 for (i = 0; i < 3; ++i) {
201 memset(&knew, 0, sizeof(knew));
202 knew.name = names[i];
203 knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
204 knew.count = 1;
205 knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
206 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
207 knew.private_value = 2 * i;
208 knew.info = pt2258_stereo_volume_info;
209 knew.get = pt2258_stereo_volume_get;
210 knew.put = pt2258_stereo_volume_put;
211 knew.tlv.p = pt2258_db_scale;
212
213 err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt));
214 if (err < 0)
215 return err;
216 }
217
218 memset(&knew, 0, sizeof(knew));
219 knew.name = "Loopback Switch";
220 knew.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
221 knew.info = pt2258_switch_info;
222 knew.get = pt2258_switch_get;
223 knew.put = pt2258_switch_put;
224 knew.access = 0;
225 err = snd_ctl_add(pt->card, snd_ctl_new1(&knew, pt));
226 if (err < 0)
227 return err;
228
229 return 0;
230}
231
232EXPORT_SYMBOL(snd_pt2258_reset);
233EXPORT_SYMBOL(snd_pt2258_build_controls);
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 57371f1a441f..4e3a9729f569 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -358,6 +358,7 @@ config SND_SBAWE
358config SND_SB16_CSP 358config SND_SB16_CSP
359 bool "Sound Blaster 16/AWE CSP support" 359 bool "Sound Blaster 16/AWE CSP support"
360 depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC) 360 depends on (SND_SB16 || SND_SBAWE) && (BROKEN || !PPC)
361 select FW_LOADER
361 help 362 help
362 Say Y here to include support for the CSP core. This special 363 Say Y here to include support for the CSP core. This special
363 coprocessor can do variable tasks like various compression and 364 coprocessor can do variable tasks like various compression and
@@ -390,6 +391,7 @@ config SND_SSCAPE
390config SND_WAVEFRONT 391config SND_WAVEFRONT
391 tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)" 392 tristate "Turtle Beach Maui,Tropez,Tropez+ (Wavefront)"
392 depends on SND 393 depends on SND
394 select FW_LOADER
393 select SND_OPL3_LIB 395 select SND_OPL3_LIB
394 select SND_MPU401_UART 396 select SND_MPU401_UART
395 select SND_CS4231_LIB 397 select SND_CS4231_LIB
diff --git a/sound/isa/ad1816a/ad1816a_lib.c b/sound/isa/ad1816a/ad1816a_lib.c
index b524e0d9ee44..ec9209cd5177 100644
--- a/sound/isa/ad1816a/ad1816a_lib.c
+++ b/sound/isa/ad1816a/ad1816a_lib.c
@@ -906,11 +906,11 @@ static int snd_ad1816a_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_
906 return change; 906 return change;
907} 907}
908 908
909static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); 909static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
910static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); 910static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
911static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); 911static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
912static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); 912static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
913static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); 913static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
914 914
915static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = { 915static struct snd_kcontrol_new snd_ad1816a_controls[] __devinitdata = {
916AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1), 916AD1816A_DOUBLE("Master Playback Switch", AD1816A_MASTER_ATT, 15, 7, 1, 1),
diff --git a/sound/isa/ad1848/ad1848_lib.c b/sound/isa/ad1848/ad1848_lib.c
index 666b3bcc19f0..8094282c2ae1 100644
--- a/sound/isa/ad1848/ad1848_lib.c
+++ b/sound/isa/ad1848/ad1848_lib.c
@@ -1223,9 +1223,9 @@ int snd_ad1848_add_ctl_elem(struct snd_ad1848 *chip,
1223 1223
1224EXPORT_SYMBOL(snd_ad1848_add_ctl_elem); 1224EXPORT_SYMBOL(snd_ad1848_add_ctl_elem);
1225 1225
1226static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); 1226static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
1227static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); 1227static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
1228static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); 1228static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
1229 1229
1230static struct ad1848_mix_elem snd_ad1848_controls[] = { 1230static struct ad1848_mix_elem snd_ad1848_controls[] = {
1231AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1), 1231AD1848_DOUBLE("PCM Playback Switch", 0, AD1848_LEFT_OUTPUT, AD1848_RIGHT_OUTPUT, 7, 7, 1, 1),
diff --git a/sound/isa/gus/gus_main.c b/sound/isa/gus/gus_main.c
index b680fddf0d74..8ced5e81b9a7 100644
--- a/sound/isa/gus/gus_main.c
+++ b/sound/isa/gus/gus_main.c
@@ -294,10 +294,10 @@ static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches)
294 gus->mix_cntrl_reg |= 4; /* enable MIC */ 294 gus->mix_cntrl_reg |= 4; /* enable MIC */
295 } 295 }
296 dma1 = gus->gf1.dma1; 296 dma1 = gus->gf1.dma1;
297 dma1 = dma1 < 0 ? -dma1 : dma1; 297 dma1 = abs(dma1);
298 dma1 = dmas[dma1 & 7]; 298 dma1 = dmas[dma1 & 7];
299 dma2 = gus->gf1.dma2; 299 dma2 = gus->gf1.dma2;
300 dma2 = dma2 < 0 ? -dma2 : dma2; 300 dma2 = abs(dma2);
301 dma2 = dmas[dma2 & 7]; 301 dma2 = dmas[dma2 & 7];
302 dma1 |= gus->equal_dma ? 0x40 : (dma2 << 3); 302 dma1 |= gus->equal_dma ? 0x40 : (dma2 << 3);
303 303
@@ -306,7 +306,7 @@ static int snd_gus_init_dma_irq(struct snd_gus_card * gus, int latches)
306 return -EINVAL; 306 return -EINVAL;
307 } 307 }
308 irq = gus->gf1.irq; 308 irq = gus->gf1.irq;
309 irq = irq < 0 ? -irq : irq; 309 irq = abs(irq);
310 irq = irqs[irq & 0x0f]; 310 irq = irqs[irq & 0x0f];
311 if (irq == 0) { 311 if (irq == 0) {
312 snd_printk(KERN_ERR "Error! IRQ isn't defined.\n"); 312 snd_printk(KERN_ERR "Error! IRQ isn't defined.\n");
diff --git a/sound/isa/opl3sa2.c b/sound/isa/opl3sa2.c
index 419b4ebbf00e..1e30713d2cad 100644
--- a/sound/isa/opl3sa2.c
+++ b/sound/isa/opl3sa2.c
@@ -486,8 +486,8 @@ static int snd_opl3sa2_put_double(struct snd_kcontrol *kcontrol, struct snd_ctl_
486 return change; 486 return change;
487} 487}
488 488
489static DECLARE_TLV_DB_SCALE(db_scale_master, -3000, 200, 0); 489static const DECLARE_TLV_DB_SCALE(db_scale_master, -3000, 200, 0);
490static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); 490static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
491 491
492static struct snd_kcontrol_new snd_opl3sa2_controls[] = { 492static struct snd_kcontrol_new snd_opl3sa2_controls[] = {
493OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1), 493OPL3SA2_DOUBLE("Master Playback Switch", 0, 0x07, 0x08, 7, 7, 1, 1),
diff --git a/sound/isa/sb/sb16_csp.c b/sound/isa/sb/sb16_csp.c
index fcd638090a9e..3d9d7e0107ca 100644
--- a/sound/isa/sb/sb16_csp.c
+++ b/sound/isa/sb/sb16_csp.c
@@ -161,10 +161,13 @@ int snd_sb_csp_new(struct snd_sb *chip, int device, struct snd_hwdep ** rhwdep)
161 */ 161 */
162static void snd_sb_csp_free(struct snd_hwdep *hwdep) 162static void snd_sb_csp_free(struct snd_hwdep *hwdep)
163{ 163{
164 int i;
164 struct snd_sb_csp *p = hwdep->private_data; 165 struct snd_sb_csp *p = hwdep->private_data;
165 if (p) { 166 if (p) {
166 if (p->running & SNDRV_SB_CSP_ST_RUNNING) 167 if (p->running & SNDRV_SB_CSP_ST_RUNNING)
167 snd_sb_csp_stop(p); 168 snd_sb_csp_stop(p);
169 for (i = 0; i < ARRAY_SIZE(p->csp_programs); ++i)
170 release_firmware(p->csp_programs[i]);
168 kfree(p); 171 kfree(p);
169 } 172 }
170} 173}
@@ -687,8 +690,50 @@ static int snd_sb_csp_load_user(struct snd_sb_csp * p, const unsigned char __use
687 return err; 690 return err;
688} 691}
689 692
693#define FIRMWARE_IN_THE_KERNEL
694
695#ifdef FIRMWARE_IN_THE_KERNEL
690#include "sb16_csp_codecs.h" 696#include "sb16_csp_codecs.h"
691 697
698static const struct firmware snd_sb_csp_static_programs[] = {
699 { .data = mulaw_main, .size = sizeof mulaw_main },
700 { .data = alaw_main, .size = sizeof alaw_main },
701 { .data = ima_adpcm_init, .size = sizeof ima_adpcm_init },
702 { .data = ima_adpcm_playback, .size = sizeof ima_adpcm_playback },
703 { .data = ima_adpcm_capture, .size = sizeof ima_adpcm_capture },
704};
705#endif
706
707static int snd_sb_csp_firmware_load(struct snd_sb_csp *p, int index, int flags)
708{
709 static const char *const names[] = {
710 "sb16/mulaw_main.csp",
711 "sb16/alaw_main.csp",
712 "sb16/ima_adpcm_init.csp",
713 "sb16/ima_adpcm_playback.csp",
714 "sb16/ima_adpcm_capture.csp",
715 };
716 const struct firmware *program;
717 int err;
718
719 BUILD_BUG_ON(ARRAY_SIZE(names) != CSP_PROGRAM_COUNT);
720 program = p->csp_programs[index];
721 if (!program) {
722 err = request_firmware(&program, names[index],
723 p->chip->card->dev);
724 if (err >= 0)
725 p->csp_programs[index] = program;
726 else {
727#ifdef FIRMWARE_IN_THE_KERNEL
728 program = &snd_sb_csp_static_programs[index];
729#else
730 return err;
731#endif
732 }
733 }
734 return snd_sb_csp_load(p, program->data, program->size, flags);
735}
736
692/* 737/*
693 * autoload hardware codec if necessary 738 * autoload hardware codec if necessary
694 * return 0 if CSP is loaded and ready to run (p->running != 0) 739 * return 0 if CSP is loaded and ready to run (p->running != 0)
@@ -708,27 +753,27 @@ static int snd_sb_csp_autoload(struct snd_sb_csp * p, int pcm_sfmt, int play_rec
708 } else { 753 } else {
709 switch (pcm_sfmt) { 754 switch (pcm_sfmt) {
710 case SNDRV_PCM_FORMAT_MU_LAW: 755 case SNDRV_PCM_FORMAT_MU_LAW:
711 err = snd_sb_csp_load(p, &mulaw_main[0], sizeof(mulaw_main), 0); 756 err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_MULAW, 0);
712 p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW; 757 p->acc_format = SNDRV_PCM_FMTBIT_MU_LAW;
713 p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; 758 p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
714 break; 759 break;
715 case SNDRV_PCM_FORMAT_A_LAW: 760 case SNDRV_PCM_FORMAT_A_LAW:
716 err = snd_sb_csp_load(p, &alaw_main[0], sizeof(alaw_main), 0); 761 err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ALAW, 0);
717 p->acc_format = SNDRV_PCM_FMTBIT_A_LAW; 762 p->acc_format = SNDRV_PCM_FMTBIT_A_LAW;
718 p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE; 763 p->mode = SNDRV_SB_CSP_MODE_DSP_READ | SNDRV_SB_CSP_MODE_DSP_WRITE;
719 break; 764 break;
720 case SNDRV_PCM_FORMAT_IMA_ADPCM: 765 case SNDRV_PCM_FORMAT_IMA_ADPCM:
721 err = snd_sb_csp_load(p, &ima_adpcm_init[0], sizeof(ima_adpcm_init), 766 err = snd_sb_csp_firmware_load(p, CSP_PROGRAM_ADPCM_INIT,
722 SNDRV_SB_CSP_LOAD_INITBLOCK); 767 SNDRV_SB_CSP_LOAD_INITBLOCK);
723 if (err) 768 if (err)
724 break; 769 break;
725 if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) { 770 if (play_rec_mode == SNDRV_SB_CSP_MODE_DSP_WRITE) {
726 err = snd_sb_csp_load(p, &ima_adpcm_playback[0], 771 err = snd_sb_csp_firmware_load
727 sizeof(ima_adpcm_playback), 0); 772 (p, CSP_PROGRAM_ADPCM_PLAYBACK, 0);
728 p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE; 773 p->mode = SNDRV_SB_CSP_MODE_DSP_WRITE;
729 } else { 774 } else {
730 err = snd_sb_csp_load(p, &ima_adpcm_capture[0], 775 err = snd_sb_csp_firmware_load
731 sizeof(ima_adpcm_capture), 0); 776 (p, CSP_PROGRAM_ADPCM_CAPTURE, 0);
732 p->mode = SNDRV_SB_CSP_MODE_DSP_READ; 777 p->mode = SNDRV_SB_CSP_MODE_DSP_READ;
733 } 778 }
734 p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM; 779 p->acc_format = SNDRV_PCM_FMTBIT_IMA_ADPCM;
diff --git a/sound/isa/wavefront/wavefront.c b/sound/isa/wavefront/wavefront.c
index 85db535aea9b..e2fdd5fd39d0 100644
--- a/sound/isa/wavefront/wavefront.c
+++ b/sound/isa/wavefront/wavefront.c
@@ -402,6 +402,7 @@ static struct snd_card *snd_wavefront_card_new(int dev)
402 init_waitqueue_head(&acard->wavefront.interrupt_sleeper); 402 init_waitqueue_head(&acard->wavefront.interrupt_sleeper);
403 spin_lock_init(&acard->wavefront.midi.open); 403 spin_lock_init(&acard->wavefront.midi.open);
404 spin_lock_init(&acard->wavefront.midi.virtual); 404 spin_lock_init(&acard->wavefront.midi.virtual);
405 acard->wavefront.card = card;
405 card->private_free = snd_wavefront_free; 406 card->private_free = snd_wavefront_free;
406 407
407 return card; 408 return card;
diff --git a/sound/isa/wavefront/wavefront_fx.c b/sound/isa/wavefront/wavefront_fx.c
index 4f0846feb73f..15331ed88194 100644
--- a/sound/isa/wavefront/wavefront_fx.c
+++ b/sound/isa/wavefront/wavefront_fx.c
@@ -21,6 +21,7 @@
21#include <linux/init.h> 21#include <linux/init.h>
22#include <linux/time.h> 22#include <linux/time.h>
23#include <linux/wait.h> 23#include <linux/wait.h>
24#include <linux/firmware.h>
24#include <sound/core.h> 25#include <sound/core.h>
25#include <sound/snd_wavefront.h> 26#include <sound/snd_wavefront.h>
26#include <sound/initval.h> 27#include <sound/initval.h>
@@ -32,325 +33,17 @@
32#define FX_MSB_TRANSFER 0x02 /* transfer after DSP MSB byte written */ 33#define FX_MSB_TRANSFER 0x02 /* transfer after DSP MSB byte written */
33#define FX_AUTO_INCR 0x04 /* auto-increment DSP address after transfer */ 34#define FX_AUTO_INCR 0x04 /* auto-increment DSP address after transfer */
34 35
35/* weird stuff, derived from port I/O tracing with dosemu */ 36#define WAIT_IDLE 0xff
36
37static unsigned char page_zero[] __devinitdata = {
380x01, 0x7c, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf5, 0x00,
390x11, 0x00, 0x20, 0x00, 0x32, 0x00, 0x40, 0x00, 0x13, 0x00, 0x00,
400x00, 0x14, 0x02, 0x76, 0x00, 0x60, 0x00, 0x80, 0x02, 0x00, 0x00,
410x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
420x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
430x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
440x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
450x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
460x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
470x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
480x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
490x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x19,
500x01, 0x1a, 0x01, 0x20, 0x01, 0x40, 0x01, 0x17, 0x00, 0x00, 0x01,
510x80, 0x01, 0x20, 0x00, 0x10, 0x01, 0xa0, 0x03, 0xd1, 0x00, 0x00,
520x01, 0xf2, 0x02, 0x00, 0x00, 0x13, 0x00, 0x00, 0x00, 0xf4, 0x02,
530xe0, 0x00, 0x15, 0x00, 0x00, 0x00, 0x16, 0x00, 0x00, 0x00, 0x17,
540x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x00, 0x50, 0x00, 0x00, 0x00,
550x40, 0x00, 0x00, 0x00, 0x71, 0x02, 0x00, 0x00, 0x60, 0x00, 0x00,
560x00, 0x92, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xb3, 0x02,
570x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00, 0x40,
580x00, 0x80, 0x00, 0xf5, 0x00, 0x20, 0x00, 0x70, 0x00, 0xa0, 0x02,
590x11, 0x00, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
600x02, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x17, 0x00, 0x1b, 0x00,
610x1d, 0x02, 0xdf
62};
63
64static unsigned char page_one[] __devinitdata = {
650x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x19, 0x00,
660x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xd8, 0x00, 0x00,
670x02, 0x20, 0x00, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x01,
680xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
690x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
700x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
710x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
720x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
730x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
740x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
750x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
760x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x40, 0x02, 0x60,
770x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x80, 0x00,
780x00, 0x02, 0xfb, 0x02, 0xa0, 0x00, 0x00, 0x00, 0x1b, 0x02, 0xd7,
790x00, 0x00, 0x02, 0xf7, 0x03, 0x20, 0x03, 0x00, 0x00, 0x00, 0x00,
800x1c, 0x03, 0x3c, 0x00, 0x00, 0x03, 0x3f, 0x00, 0x00, 0x03, 0xc0,
810x00, 0x00, 0x03, 0xdf, 0x00, 0x00, 0x00, 0x00, 0x03, 0x5d, 0x00,
820x00, 0x03, 0xc0, 0x00, 0x00, 0x03, 0x7d, 0x00, 0x00, 0x03, 0xc0,
830x00, 0x00, 0x03, 0x9e, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x03,
840xbe, 0x00, 0x00, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
850x00, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
860xdb, 0x00, 0x00, 0x02, 0xdb, 0x00, 0x00, 0x02, 0xe0, 0x00, 0x00,
870x02, 0xfb, 0x00, 0x00, 0x02, 0xc0, 0x02, 0x40, 0x02, 0xfb, 0x02,
880x60, 0x00, 0x1b
89};
90
91static unsigned char page_two[] __devinitdata = {
920xc4, 0x00, 0x44, 0x07, 0x44, 0x00, 0x40, 0x25, 0x01, 0x06, 0xc4,
930x07, 0x40, 0x25, 0x01, 0x00, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00,
940x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
950x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
960x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
970x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x46, 0x07,
980x05, 0x05, 0x05, 0x04, 0x07, 0x05, 0x04, 0x07, 0x05, 0x44, 0x46,
990x44, 0x46, 0x46, 0x07, 0x05, 0x44, 0x46, 0x05, 0x46, 0x05, 0x46,
1000x05, 0x46, 0x05, 0x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07,
1010x44, 0x46, 0x05, 0x07, 0x44, 0x46, 0x05, 0x07, 0x44, 0x05, 0x05,
1020x05, 0x44, 0x05, 0x05, 0x05, 0x46, 0x05, 0x46, 0x05, 0x46, 0x05,
1030x46, 0x05, 0x46, 0x07, 0x46, 0x07, 0x44
104};
105
106static unsigned char page_three[] __devinitdata = {
1070x07, 0x40, 0x00, 0x00, 0x00, 0x47, 0x00, 0x40, 0x00, 0x40, 0x06,
1080x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1090x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1100x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1110x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1120x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x80,
1130xc0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x40, 0x00,
1140x60, 0x00, 0x70, 0x00, 0x40, 0x00, 0x40, 0x00, 0x42, 0x00, 0x40,
1150x00, 0x02, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
1160x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
1170x00, 0x42, 0x00, 0x40, 0x00, 0x42, 0x00, 0x02, 0x00, 0x02, 0x00,
1180x02, 0x00, 0x42, 0x00, 0xc0, 0x00, 0x40
119};
120
121static unsigned char page_four[] __devinitdata = {
1220x63, 0x03, 0x26, 0x02, 0x2c, 0x00, 0x24, 0x00, 0x2e, 0x02, 0x02,
1230x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1240x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1250x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1260x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1270x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
1280x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
1290x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x60, 0x00,
1300x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60,
1310x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00, 0x60, 0x00, 0x20, 0x00,
1320x20, 0x00, 0x22, 0x02, 0x22, 0x02, 0x20, 0x00, 0x60, 0x00, 0x22,
1330x02, 0x62, 0x02, 0x20, 0x01, 0x21, 0x01
134};
135
136static unsigned char page_six[] __devinitdata = {
1370x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x04, 0x00, 0x00, 0x06, 0x00,
1380x00, 0x08, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x0e,
1390x00, 0x00, 0x10, 0x00, 0x00, 0x12, 0x00, 0x00, 0x14, 0x00, 0x00,
1400x16, 0x00, 0x00, 0x18, 0x00, 0x00, 0x1a, 0x00, 0x00, 0x1c, 0x00,
1410x00, 0x1e, 0x00, 0x00, 0x20, 0x00, 0x00, 0x22, 0x00, 0x00, 0x24,
1420x00, 0x00, 0x26, 0x00, 0x00, 0x28, 0x00, 0x00, 0x2a, 0x00, 0x00,
1430x2c, 0x00, 0x00, 0x2e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x32, 0x00,
1440x00, 0x34, 0x00, 0x00, 0x36, 0x00, 0x00, 0x38, 0x00, 0x00, 0x3a,
1450x00, 0x00, 0x3c, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x40, 0x00, 0x00,
1460x42, 0x03, 0x00, 0x44, 0x01, 0x00, 0x46, 0x0a, 0x21, 0x48, 0x0d,
1470x23, 0x4a, 0x23, 0x1b, 0x4c, 0x37, 0x8f, 0x4e, 0x45, 0x77, 0x50,
1480x52, 0xe2, 0x52, 0x1c, 0x92, 0x54, 0x1c, 0x52, 0x56, 0x07, 0x00,
1490x58, 0x2f, 0xc6, 0x5a, 0x0b, 0x00, 0x5c, 0x30, 0x06, 0x5e, 0x17,
1500x00, 0x60, 0x3d, 0xda, 0x62, 0x29, 0x00, 0x64, 0x3e, 0x41, 0x66,
1510x39, 0x00, 0x68, 0x4c, 0x48, 0x6a, 0x49, 0x00, 0x6c, 0x4c, 0x6c,
1520x6e, 0x11, 0xd2, 0x70, 0x16, 0x0c, 0x72, 0x00, 0x00, 0x74, 0x00,
1530x80, 0x76, 0x0f, 0x00, 0x78, 0x00, 0x80, 0x7a, 0x13, 0x00, 0x7c,
1540x80, 0x00, 0x7e, 0x80, 0x80
155};
156
157static unsigned char page_seven[] __devinitdata = {
1580x0f, 0xff, 0x00, 0x00, 0x08, 0x00, 0x08, 0x00, 0x02, 0x00, 0x00,
1590x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
1600x08, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x0f,
1610xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1620x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1630x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1640x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1650x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1660x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1670x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1680x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1690x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1700x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1710x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xff, 0x0f, 0xff,
1720x0f, 0xff, 0x0f, 0xff, 0x02, 0xe9, 0x06, 0x8c, 0x06, 0x8c, 0x0f,
1730xff, 0x1a, 0x75, 0x0d, 0x8b, 0x04, 0xe9, 0x0b, 0x16, 0x1a, 0x38,
1740x0d, 0xc8, 0x04, 0x6f, 0x0b, 0x91, 0x0f, 0xff, 0x06, 0x40, 0x06,
1750x40, 0x02, 0x8f, 0x0f, 0xff, 0x06, 0x62, 0x06, 0x62, 0x02, 0x7b,
1760x0f, 0xff, 0x06, 0x97, 0x06, 0x97, 0x02, 0x52, 0x0f, 0xff, 0x06,
1770xf6, 0x06, 0xf6, 0x02, 0x19, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55,
1780x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x05, 0x55, 0x14,
1790xda, 0x0d, 0x93, 0x04, 0xda, 0x05, 0x93, 0x14, 0xda, 0x0d, 0x93,
1800x04, 0xda, 0x05, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1810x00, 0x02, 0x00
182};
183
184static unsigned char page_zero_v2[] __devinitdata = {
1850x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1860x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1870x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1880x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1890x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1900x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1910x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1920x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1930x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
194};
195
196static unsigned char page_one_v2[] __devinitdata = {
1970x01, 0xc0, 0x01, 0xfa, 0x00, 0x1a, 0x00, 0x00, 0x00, 0x00, 0x00,
1980x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
1990x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2000x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2010x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2020x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2030x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2040x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2050x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
206};
207
208static unsigned char page_two_v2[] __devinitdata = {
2090x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2100x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2110x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2120x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2130x00, 0x00, 0x00, 0x00
214};
215static unsigned char page_three_v2[] __devinitdata = {
2160x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2170x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2180x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2190x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2200x00, 0x00, 0x00, 0x00
221};
222static unsigned char page_four_v2[] __devinitdata = {
2230x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2240x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2250x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2260x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2270x00, 0x00, 0x00, 0x00
228};
229 37
230static unsigned char page_seven_v2[] __devinitdata = { 38#define FIRMWARE_IN_THE_KERNEL
2310x0f, 0xff, 0x0f, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2320x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2330x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2340x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2350x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2360x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2370x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2380x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
2390x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
240};
241 39
242static unsigned char mod_v2[] __devinitdata = { 40#ifdef FIRMWARE_IN_THE_KERNEL
2430x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 41#include "yss225.c"
2440x00, 0x01, 0x03, 0x02, 0x00, 0x01, 0x04, 0x02, 0x00, 0x01, 0x05, 42static const struct firmware yss225_registers_firmware = {
2450x02, 0x00, 0x01, 0x06, 0x02, 0x00, 0x01, 0x07, 0x02, 0x00, 0xb0, 43 .data = (u8 *)yss225_registers,
2460x20, 0xb1, 0x20, 0xb2, 0x20, 0xb3, 0x20, 0xb4, 0x20, 0xb5, 0x20, 44 .size = sizeof yss225_registers
2470xb6, 0x20, 0xb7, 0x20, 0xf0, 0x20, 0xf1, 0x20, 0xf2, 0x20, 0xf3,
2480x20, 0xf4, 0x20, 0xf5, 0x20, 0xf6, 0x20, 0xf7, 0x20, 0x10, 0xff,
2490x11, 0xff, 0x12, 0xff, 0x13, 0xff, 0x14, 0xff, 0x15, 0xff, 0x16,
2500xff, 0x17, 0xff, 0x20, 0xff, 0x21, 0xff, 0x22, 0xff, 0x23, 0xff,
2510x24, 0xff, 0x25, 0xff, 0x26, 0xff, 0x27, 0xff, 0x30, 0x00, 0x31,
2520x00, 0x32, 0x00, 0x33, 0x00, 0x34, 0x00, 0x35, 0x00, 0x36, 0x00,
2530x37, 0x00, 0x40, 0x00, 0x41, 0x00, 0x42, 0x00, 0x43, 0x00, 0x44,
2540x00, 0x45, 0x00, 0x46, 0x00, 0x47, 0x00, 0x50, 0x00, 0x51, 0x00,
2550x52, 0x00, 0x53, 0x00, 0x54, 0x00, 0x55, 0x00, 0x56, 0x00, 0x57,
2560x00, 0x60, 0x00, 0x61, 0x00, 0x62, 0x00, 0x63, 0x00, 0x64, 0x00,
2570x65, 0x00, 0x66, 0x00, 0x67, 0x00, 0x70, 0xc0, 0x71, 0xc0, 0x72,
2580xc0, 0x73, 0xc0, 0x74, 0xc0, 0x75, 0xc0, 0x76, 0xc0, 0x77, 0xc0,
2590x80, 0x00, 0x81, 0x00, 0x82, 0x00, 0x83, 0x00, 0x84, 0x00, 0x85,
2600x00, 0x86, 0x00, 0x87, 0x00, 0x90, 0x00, 0x91, 0x00, 0x92, 0x00,
2610x93, 0x00, 0x94, 0x00, 0x95, 0x00, 0x96, 0x00, 0x97, 0x00, 0xa0,
2620x00, 0xa1, 0x00, 0xa2, 0x00, 0xa3, 0x00, 0xa4, 0x00, 0xa5, 0x00,
2630xa6, 0x00, 0xa7, 0x00, 0xc0, 0x00, 0xc1, 0x00, 0xc2, 0x00, 0xc3,
2640x00, 0xc4, 0x00, 0xc5, 0x00, 0xc6, 0x00, 0xc7, 0x00, 0xd0, 0x00,
2650xd1, 0x00, 0xd2, 0x00, 0xd3, 0x00, 0xd4, 0x00, 0xd5, 0x00, 0xd6,
2660x00, 0xd7, 0x00, 0xe0, 0x00, 0xe1, 0x00, 0xe2, 0x00, 0xe3, 0x00,
2670xe4, 0x00, 0xe5, 0x00, 0xe6, 0x00, 0xe7, 0x00, 0x01, 0x00, 0x02,
2680x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x03,
2690x02, 0x01, 0x01, 0x04, 0x02, 0x01, 0x01, 0x05, 0x02, 0x01, 0x01,
2700x06, 0x02, 0x01, 0x01, 0x07, 0x02, 0x01
271};
272static unsigned char coefficients[] __devinitdata = {
2730x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x00, 0x4b, 0x03,
2740x11, 0x00, 0x4d, 0x01, 0x32, 0x07, 0x46, 0x00, 0x00, 0x07, 0x49,
2750x00, 0x00, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x01,
2760x40, 0x02, 0x40, 0x01, 0x41, 0x02, 0x60, 0x07, 0x40, 0x00, 0x00,
2770x07, 0x41, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00, 0x07, 0x4a, 0x00,
2780x00, 0x00, 0x47, 0x01, 0x00, 0x00, 0x4a, 0x01, 0x20, 0x07, 0x47,
2790x00, 0x00, 0x07, 0x4a, 0x00, 0x00, 0x07, 0x7c, 0x00, 0x00, 0x07,
2800x7e, 0x00, 0x00, 0x00, 0x00, 0x01, 0x1c, 0x07, 0x7c, 0x00, 0x00,
2810x07, 0x7e, 0x00, 0x00, 0x07, 0x44, 0x00, 0x00, 0x00, 0x44, 0x01,
2820x00, 0x07, 0x44, 0x00, 0x00, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43,
2830x00, 0x00, 0x00, 0x42, 0x01, 0x1a, 0x00, 0x43, 0x01, 0x20, 0x07,
2840x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07, 0x40, 0x00, 0x00,
2850x07, 0x41, 0x00, 0x00, 0x01, 0x40, 0x02, 0x40, 0x01, 0x41, 0x02,
2860x60, 0x07, 0x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x44,
2870x0f, 0xff, 0x07, 0x42, 0x00, 0x00, 0x07, 0x43, 0x00, 0x00, 0x07,
2880x40, 0x00, 0x00, 0x07, 0x41, 0x00, 0x00, 0x07, 0x51, 0x06, 0x40,
2890x07, 0x50, 0x06, 0x40, 0x07, 0x4f, 0x03, 0x81, 0x07, 0x53, 0x1a,
2900x76, 0x07, 0x54, 0x0d, 0x8b, 0x07, 0x55, 0x04, 0xe9, 0x07, 0x56,
2910x0b, 0x17, 0x07, 0x57, 0x1a, 0x38, 0x07, 0x58, 0x0d, 0xc9, 0x07,
2920x59, 0x04, 0x6f, 0x07, 0x5a, 0x0b, 0x91, 0x07, 0x73, 0x14, 0xda,
2930x07, 0x74, 0x0d, 0x93, 0x07, 0x75, 0x04, 0xd9, 0x07, 0x76, 0x05,
2940x93, 0x07, 0x77, 0x14, 0xda, 0x07, 0x78, 0x0d, 0x93, 0x07, 0x79,
2950x04, 0xd9, 0x07, 0x7a, 0x05, 0x93, 0x07, 0x5e, 0x03, 0x68, 0x07,
2960x5c, 0x04, 0x31, 0x07, 0x5d, 0x04, 0x31, 0x07, 0x62, 0x03, 0x52,
2970x07, 0x60, 0x04, 0x76, 0x07, 0x61, 0x04, 0x76, 0x07, 0x66, 0x03,
2980x2e, 0x07, 0x64, 0x04, 0xda, 0x07, 0x65, 0x04, 0xda, 0x07, 0x6a,
2990x02, 0xf6, 0x07, 0x68, 0x05, 0x62, 0x07, 0x69, 0x05, 0x62, 0x06,
3000x46, 0x0a, 0x22, 0x06, 0x48, 0x0d, 0x24, 0x06, 0x6e, 0x11, 0xd3,
3010x06, 0x70, 0x15, 0xcb, 0x06, 0x52, 0x20, 0x93, 0x06, 0x54, 0x20,
3020x54, 0x06, 0x4a, 0x27, 0x1d, 0x06, 0x58, 0x2f, 0xc8, 0x06, 0x5c,
3030x30, 0x07, 0x06, 0x4c, 0x37, 0x90, 0x06, 0x60, 0x3d, 0xdb, 0x06,
3040x64, 0x3e, 0x42, 0x06, 0x4e, 0x45, 0x78, 0x06, 0x68, 0x4c, 0x48,
3050x06, 0x6c, 0x4c, 0x6c, 0x06, 0x50, 0x52, 0xe2, 0x06, 0x42, 0x02,
3060xba
307};
308static unsigned char coefficients2[] __devinitdata = {
3090x07, 0x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x45, 0x0f,
3100xff, 0x07, 0x48, 0x0f, 0xff, 0x07, 0x7b, 0x04, 0xcc, 0x07, 0x7d,
3110x04, 0xcc, 0x07, 0x7c, 0x00, 0x00, 0x07, 0x7e, 0x00, 0x00, 0x07,
3120x46, 0x00, 0x00, 0x07, 0x49, 0x00, 0x00, 0x07, 0x47, 0x00, 0x00,
3130x07, 0x4a, 0x00, 0x00, 0x07, 0x4c, 0x00, 0x00, 0x07, 0x4e, 0x00, 0x00
314};
315static unsigned char coefficients3[] __devinitdata = {
3160x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x00, 0x28, 0x00, 0x51, 0x00,
3170x51, 0x00, 0x7a, 0x00, 0x7a, 0x00, 0xa3, 0x00, 0xa3, 0x00, 0xcc,
3180x00, 0xcc, 0x00, 0xf5, 0x00, 0xf5, 0x01, 0x1e, 0x01, 0x1e, 0x01,
3190x47, 0x01, 0x47, 0x01, 0x70, 0x01, 0x70, 0x01, 0x99, 0x01, 0x99,
3200x01, 0xc2, 0x01, 0xc2, 0x01, 0xeb, 0x01, 0xeb, 0x02, 0x14, 0x02,
3210x14, 0x02, 0x3d, 0x02, 0x3d, 0x02, 0x66, 0x02, 0x66, 0x02, 0x8f,
3220x02, 0x8f, 0x02, 0xb8, 0x02, 0xb8, 0x02, 0xe1, 0x02, 0xe1, 0x03,
3230x0a, 0x03, 0x0a, 0x03, 0x33, 0x03, 0x33, 0x03, 0x5c, 0x03, 0x5c,
3240x03, 0x85, 0x03, 0x85, 0x03, 0xae, 0x03, 0xae, 0x03, 0xd7, 0x03,
3250xd7, 0x04, 0x00, 0x04, 0x00, 0x04, 0x28, 0x04, 0x28, 0x04, 0x51,
3260x04, 0x51, 0x04, 0x7a, 0x04, 0x7a, 0x04, 0xa3, 0x04, 0xa3, 0x04,
3270xcc, 0x04, 0xcc, 0x04, 0xf5, 0x04, 0xf5, 0x05, 0x1e, 0x05, 0x1e,
3280x05, 0x47, 0x05, 0x47, 0x05, 0x70, 0x05, 0x70, 0x05, 0x99, 0x05,
3290x99, 0x05, 0xc2, 0x05, 0xc2, 0x05, 0xeb, 0x05, 0xeb, 0x06, 0x14,
3300x06, 0x14, 0x06, 0x3d, 0x06, 0x3d, 0x06, 0x66, 0x06, 0x66, 0x06,
3310x8f, 0x06, 0x8f, 0x06, 0xb8, 0x06, 0xb8, 0x06, 0xe1, 0x06, 0xe1,
3320x07, 0x0a, 0x07, 0x0a, 0x07, 0x33, 0x07, 0x33, 0x07, 0x5c, 0x07,
3330x5c, 0x07, 0x85, 0x07, 0x85, 0x07, 0xae, 0x07, 0xae, 0x07, 0xd7,
3340x07, 0xd7, 0x08, 0x00, 0x08, 0x00, 0x08, 0x28, 0x08, 0x28, 0x08,
3350x51, 0x08, 0x51, 0x08, 0x7a, 0x08, 0x7a, 0x08, 0xa3, 0x08, 0xa3,
3360x08, 0xcc, 0x08, 0xcc, 0x08, 0xf5, 0x08, 0xf5, 0x09, 0x1e, 0x09,
3370x1e, 0x09, 0x47, 0x09, 0x47, 0x09, 0x70, 0x09, 0x70, 0x09, 0x99,
3380x09, 0x99, 0x09, 0xc2, 0x09, 0xc2, 0x09, 0xeb, 0x09, 0xeb, 0x0a,
3390x14, 0x0a, 0x14, 0x0a, 0x3d, 0x0a, 0x3d, 0x0a, 0x66, 0x0a, 0x66,
3400x0a, 0x8f, 0x0a, 0x8f, 0x0a, 0xb8, 0x0a, 0xb8, 0x0a, 0xe1, 0x0a,
3410xe1, 0x0b, 0x0a, 0x0b, 0x0a, 0x0b, 0x33, 0x0b, 0x33, 0x0b, 0x5c,
3420x0b, 0x5c, 0x0b, 0x85, 0x0b, 0x85, 0x0b, 0xae, 0x0b, 0xae, 0x0b,
3430xd7, 0x0b, 0xd7, 0x0c, 0x00, 0x0c, 0x00, 0x0c, 0x28, 0x0c, 0x28,
3440x0c, 0x51, 0x0c, 0x51, 0x0c, 0x7a, 0x0c, 0x7a, 0x0c, 0xa3, 0x0c,
3450xa3, 0x0c, 0xcc, 0x0c, 0xcc, 0x0c, 0xf5, 0x0c, 0xf5, 0x0d, 0x1e,
3460x0d, 0x1e, 0x0d, 0x47, 0x0d, 0x47, 0x0d, 0x70, 0x0d, 0x70, 0x0d,
3470x99, 0x0d, 0x99, 0x0d, 0xc2, 0x0d, 0xc2, 0x0d, 0xeb, 0x0d, 0xeb,
3480x0e, 0x14, 0x0e, 0x14, 0x0e, 0x3d, 0x0e, 0x3d, 0x0e, 0x66, 0x0e,
3490x66, 0x0e, 0x8f, 0x0e, 0x8f, 0x0e, 0xb8, 0x0e, 0xb8, 0x0e, 0xe1,
3500x0e, 0xe1, 0x0f, 0x0a, 0x0f, 0x0a, 0x0f, 0x33, 0x0f, 0x33, 0x0f,
3510x5c, 0x0f, 0x5c, 0x0f, 0x85, 0x0f, 0x85, 0x0f, 0xae, 0x0f, 0xae,
3520x0f, 0xd7, 0x0f, 0xd7, 0x0f, 0xff, 0x0f, 0xff
353}; 45};
46#endif
354 47
355static int 48static int
356wavefront_fx_idle (snd_wavefront_t *dev) 49wavefront_fx_idle (snd_wavefront_t *dev)
@@ -555,465 +248,56 @@ snd_wavefront_fx_ioctl (struct snd_hwdep *sdev, struct file *file,
555 of the port I/O done, using the Yamaha faxback document as a guide 248 of the port I/O done, using the Yamaha faxback document as a guide
556 to add more logic to the code. Its really pretty weird. 249 to add more logic to the code. Its really pretty weird.
557 250
558 There was an alternative approach of just dumping the whole I/O 251 This is the approach of just dumping the whole I/O
559 sequence as a series of port/value pairs and a simple loop 252 sequence as a series of port/value pairs and a simple loop
560 that output it. However, I hope that eventually I'll get more 253 that outputs it.
561 control over what this code does, and so I tried to stick with
562 a somewhat "algorithmic" approach.
563*/ 254*/
564 255
565
566int __devinit 256int __devinit
567snd_wavefront_fx_start (snd_wavefront_t *dev) 257snd_wavefront_fx_start (snd_wavefront_t *dev)
568
569{ 258{
570 unsigned int i, j; 259 unsigned int i;
260 int err;
261 const struct firmware *firmware;
571 262
572 /* Set all bits for all channels on the MOD unit to zero */ 263 if (dev->fx_initialized)
573 /* XXX But why do this twice ? */ 264 return 0;
574 265
575 for (j = 0; j < 2; j++) { 266 err = request_firmware(&firmware, "yamaha/yss225_registers.bin",
576 for (i = 0x10; i <= 0xff; i++) { 267 dev->card->dev);
577 268 if (err < 0) {
578 if (!wavefront_fx_idle (dev)) { 269#ifdef FIRMWARE_IN_THE_KERNEL
579 return (-1); 270 firmware = &yss225_registers_firmware;
271#else
272 err = -1;
273 goto out;
274#endif
275 }
276
277 for (i = 0; i + 1 < firmware->size; i += 2) {
278 if (firmware->data[i] >= 8 && firmware->data[i] < 16) {
279 outb(firmware->data[i + 1],
280 dev->base + firmware->data[i]);
281 } else if (firmware->data[i] == WAIT_IDLE) {
282 if (!wavefront_fx_idle(dev)) {
283 err = -1;
284 goto out;
580 } 285 }
581 286 } else {
582 outb (i, dev->fx_mod_addr); 287 snd_printk(KERN_ERR "invalid address"
583 outb (0x0, dev->fx_mod_data); 288 " in register data\n");
584 } 289 err = -1;
585 } 290 goto out;
586
587 if (!wavefront_fx_idle (dev)) return (-1);
588 outb (0x02, dev->fx_op); /* mute on */
589
590 if (!wavefront_fx_idle (dev)) return (-1);
591 outb (0x07, dev->fx_dsp_page);
592 outb (0x44, dev->fx_dsp_addr);
593 outb (0x00, dev->fx_dsp_msb);
594 outb (0x00, dev->fx_dsp_lsb);
595 if (!wavefront_fx_idle (dev)) return (-1);
596 outb (0x07, dev->fx_dsp_page);
597 outb (0x42, dev->fx_dsp_addr);
598 outb (0x00, dev->fx_dsp_msb);
599 outb (0x00, dev->fx_dsp_lsb);
600 if (!wavefront_fx_idle (dev)) return (-1);
601 outb (0x07, dev->fx_dsp_page);
602 outb (0x43, dev->fx_dsp_addr);
603 outb (0x00, dev->fx_dsp_msb);
604 outb (0x00, dev->fx_dsp_lsb);
605 if (!wavefront_fx_idle (dev)) return (-1);
606 outb (0x07, dev->fx_dsp_page);
607 outb (0x7c, dev->fx_dsp_addr);
608 outb (0x00, dev->fx_dsp_msb);
609 outb (0x00, dev->fx_dsp_lsb);
610 if (!wavefront_fx_idle (dev)) return (-1);
611 outb (0x07, dev->fx_dsp_page);
612 outb (0x7e, dev->fx_dsp_addr);
613 outb (0x00, dev->fx_dsp_msb);
614 outb (0x00, dev->fx_dsp_lsb);
615 if (!wavefront_fx_idle (dev)) return (-1);
616 outb (0x07, dev->fx_dsp_page);
617 outb (0x46, dev->fx_dsp_addr);
618 outb (0x00, dev->fx_dsp_msb);
619 outb (0x00, dev->fx_dsp_lsb);
620 if (!wavefront_fx_idle (dev)) return (-1);
621 outb (0x07, dev->fx_dsp_page);
622 outb (0x49, dev->fx_dsp_addr);
623 outb (0x00, dev->fx_dsp_msb);
624 outb (0x00, dev->fx_dsp_lsb);
625 if (!wavefront_fx_idle (dev)) return (-1);
626 outb (0x07, dev->fx_dsp_page);
627 outb (0x47, dev->fx_dsp_addr);
628 outb (0x00, dev->fx_dsp_msb);
629 outb (0x00, dev->fx_dsp_lsb);
630 if (!wavefront_fx_idle (dev)) return (-1);
631 outb (0x07, dev->fx_dsp_page);
632 outb (0x4a, dev->fx_dsp_addr);
633 outb (0x00, dev->fx_dsp_msb);
634 outb (0x00, dev->fx_dsp_lsb);
635
636 /* either because of stupidity by TB's programmers, or because it
637 actually does something, rezero the MOD page.
638 */
639 for (i = 0x10; i <= 0xff; i++) {
640
641 if (!wavefront_fx_idle (dev)) {
642 return (-1);
643 } 291 }
644
645 outb (i, dev->fx_mod_addr);
646 outb (0x0, dev->fx_mod_data);
647 }
648 /* load page zero */
649
650 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
651 outb (0x00, dev->fx_dsp_page);
652 outb (0x00, dev->fx_dsp_addr);
653
654 for (i = 0; i < sizeof (page_zero); i += 2) {
655 outb (page_zero[i], dev->fx_dsp_msb);
656 outb (page_zero[i+1], dev->fx_dsp_lsb);
657 if (!wavefront_fx_idle (dev)) return (-1);
658 }
659
660 /* Now load page one */
661
662 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
663 outb (0x01, dev->fx_dsp_page);
664 outb (0x00, dev->fx_dsp_addr);
665
666 for (i = 0; i < sizeof (page_one); i += 2) {
667 outb (page_one[i], dev->fx_dsp_msb);
668 outb (page_one[i+1], dev->fx_dsp_lsb);
669 if (!wavefront_fx_idle (dev)) return (-1);
670 }
671
672 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
673 outb (0x02, dev->fx_dsp_page);
674 outb (0x00, dev->fx_dsp_addr);
675
676 for (i = 0; i < sizeof (page_two); i++) {
677 outb (page_two[i], dev->fx_dsp_lsb);
678 if (!wavefront_fx_idle (dev)) return (-1);
679 }
680
681 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
682 outb (0x03, dev->fx_dsp_page);
683 outb (0x00, dev->fx_dsp_addr);
684
685 for (i = 0; i < sizeof (page_three); i++) {
686 outb (page_three[i], dev->fx_dsp_lsb);
687 if (!wavefront_fx_idle (dev)) return (-1);
688 }
689
690 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
691 outb (0x04, dev->fx_dsp_page);
692 outb (0x00, dev->fx_dsp_addr);
693
694 for (i = 0; i < sizeof (page_four); i++) {
695 outb (page_four[i], dev->fx_dsp_lsb);
696 if (!wavefront_fx_idle (dev)) return (-1);
697 }
698
699 /* Load memory area (page six) */
700
701 outb (FX_LSB_TRANSFER, dev->fx_lcr);
702 outb (0x06, dev->fx_dsp_page);
703
704 for (i = 0; i < sizeof (page_six); i += 3) {
705 outb (page_six[i], dev->fx_dsp_addr);
706 outb (page_six[i+1], dev->fx_dsp_msb);
707 outb (page_six[i+2], dev->fx_dsp_lsb);
708 if (!wavefront_fx_idle (dev)) return (-1);
709 }
710
711 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
712 outb (0x07, dev->fx_dsp_page);
713 outb (0x00, dev->fx_dsp_addr);
714
715 for (i = 0; i < sizeof (page_seven); i += 2) {
716 outb (page_seven[i], dev->fx_dsp_msb);
717 outb (page_seven[i+1], dev->fx_dsp_lsb);
718 if (!wavefront_fx_idle (dev)) return (-1);
719 }
720
721 /* Now setup the MOD area. We do this algorithmically in order to
722 save a little data space. It could be done in the same fashion
723 as the "pages".
724 */
725
726 for (i = 0x00; i <= 0x0f; i++) {
727 outb (0x01, dev->fx_mod_addr);
728 outb (i, dev->fx_mod_data);
729 if (!wavefront_fx_idle (dev)) return (-1);
730 outb (0x02, dev->fx_mod_addr);
731 outb (0x00, dev->fx_mod_data);
732 if (!wavefront_fx_idle (dev)) return (-1);
733 }
734
735 for (i = 0xb0; i <= 0xbf; i++) {
736 outb (i, dev->fx_mod_addr);
737 outb (0x20, dev->fx_mod_data);
738 if (!wavefront_fx_idle (dev)) return (-1);
739 } 292 }
740 293
741 for (i = 0xf0; i <= 0xff; i++) { 294 dev->fx_initialized = 1;
742 outb (i, dev->fx_mod_addr); 295 err = 0;
743 outb (0x20, dev->fx_mod_data);
744 if (!wavefront_fx_idle (dev)) return (-1);
745 }
746
747 for (i = 0x10; i <= 0x1d; i++) {
748 outb (i, dev->fx_mod_addr);
749 outb (0xff, dev->fx_mod_data);
750 if (!wavefront_fx_idle (dev)) return (-1);
751 }
752
753 outb (0x1e, dev->fx_mod_addr);
754 outb (0x40, dev->fx_mod_data);
755 if (!wavefront_fx_idle (dev)) return (-1);
756
757 for (i = 0x1f; i <= 0x2d; i++) {
758 outb (i, dev->fx_mod_addr);
759 outb (0xff, dev->fx_mod_data);
760 if (!wavefront_fx_idle (dev)) return (-1);
761 }
762
763 outb (0x2e, dev->fx_mod_addr);
764 outb (0x00, dev->fx_mod_data);
765 if (!wavefront_fx_idle (dev)) return (-1);
766
767 for (i = 0x2f; i <= 0x3e; i++) {
768 outb (i, dev->fx_mod_addr);
769 outb (0x00, dev->fx_mod_data);
770 if (!wavefront_fx_idle (dev)) return (-1);
771 }
772
773 outb (0x3f, dev->fx_mod_addr);
774 outb (0x20, dev->fx_mod_data);
775 if (!wavefront_fx_idle (dev)) return (-1);
776
777 for (i = 0x40; i <= 0x4d; i++) {
778 outb (i, dev->fx_mod_addr);
779 outb (0x00, dev->fx_mod_data);
780 if (!wavefront_fx_idle (dev)) return (-1);
781 }
782
783 outb (0x4e, dev->fx_mod_addr);
784 outb (0x0e, dev->fx_mod_data);
785 if (!wavefront_fx_idle (dev)) return (-1);
786 outb (0x4f, dev->fx_mod_addr);
787 outb (0x0e, dev->fx_mod_data);
788 if (!wavefront_fx_idle (dev)) return (-1);
789
790
791 for (i = 0x50; i <= 0x6b; i++) {
792 outb (i, dev->fx_mod_addr);
793 outb (0x00, dev->fx_mod_data);
794 if (!wavefront_fx_idle (dev)) return (-1);
795 }
796
797 outb (0x6c, dev->fx_mod_addr);
798 outb (0x40, dev->fx_mod_data);
799 if (!wavefront_fx_idle (dev)) return (-1);
800
801 outb (0x6d, dev->fx_mod_addr);
802 outb (0x00, dev->fx_mod_data);
803 if (!wavefront_fx_idle (dev)) return (-1);
804
805 outb (0x6e, dev->fx_mod_addr);
806 outb (0x40, dev->fx_mod_data);
807 if (!wavefront_fx_idle (dev)) return (-1);
808
809 outb (0x6f, dev->fx_mod_addr);
810 outb (0x40, dev->fx_mod_data);
811 if (!wavefront_fx_idle (dev)) return (-1);
812
813 for (i = 0x70; i <= 0x7f; i++) {
814 outb (i, dev->fx_mod_addr);
815 outb (0xc0, dev->fx_mod_data);
816 if (!wavefront_fx_idle (dev)) return (-1);
817 }
818
819 for (i = 0x80; i <= 0xaf; i++) {
820 outb (i, dev->fx_mod_addr);
821 outb (0x00, dev->fx_mod_data);
822 if (!wavefront_fx_idle (dev)) return (-1);
823 }
824
825 for (i = 0xc0; i <= 0xdd; i++) {
826 outb (i, dev->fx_mod_addr);
827 outb (0x00, dev->fx_mod_data);
828 if (!wavefront_fx_idle (dev)) return (-1);
829 }
830
831 outb (0xde, dev->fx_mod_addr);
832 outb (0x10, dev->fx_mod_data);
833 if (!wavefront_fx_idle (dev)) return (-1);
834 outb (0xdf, dev->fx_mod_addr);
835 outb (0x10, dev->fx_mod_data);
836 if (!wavefront_fx_idle (dev)) return (-1);
837
838 for (i = 0xe0; i <= 0xef; i++) {
839 outb (i, dev->fx_mod_addr);
840 outb (0x00, dev->fx_mod_data);
841 if (!wavefront_fx_idle (dev)) return (-1);
842 }
843
844 for (i = 0x00; i <= 0x0f; i++) {
845 outb (0x01, dev->fx_mod_addr);
846 outb (i, dev->fx_mod_data);
847 outb (0x02, dev->fx_mod_addr);
848 outb (0x01, dev->fx_mod_data);
849 if (!wavefront_fx_idle (dev)) return (-1);
850 }
851
852 outb (0x02, dev->fx_op); /* mute on */
853
854 /* Now set the coefficients and so forth for the programs above */
855
856 for (i = 0; i < sizeof (coefficients); i += 4) {
857 outb (coefficients[i], dev->fx_dsp_page);
858 outb (coefficients[i+1], dev->fx_dsp_addr);
859 outb (coefficients[i+2], dev->fx_dsp_msb);
860 outb (coefficients[i+3], dev->fx_dsp_lsb);
861 if (!wavefront_fx_idle (dev)) return (-1);
862 }
863
864 /* Some settings (?) that are too small to bundle into loops */
865
866 if (!wavefront_fx_idle (dev)) return (-1);
867 outb (0x1e, dev->fx_mod_addr);
868 outb (0x14, dev->fx_mod_data);
869 if (!wavefront_fx_idle (dev)) return (-1);
870 outb (0xde, dev->fx_mod_addr);
871 outb (0x20, dev->fx_mod_data);
872 if (!wavefront_fx_idle (dev)) return (-1);
873 outb (0xdf, dev->fx_mod_addr);
874 outb (0x20, dev->fx_mod_data);
875
876 /* some more coefficients */
877
878 if (!wavefront_fx_idle (dev)) return (-1);
879 outb (0x06, dev->fx_dsp_page);
880 outb (0x78, dev->fx_dsp_addr);
881 outb (0x00, dev->fx_dsp_msb);
882 outb (0x40, dev->fx_dsp_lsb);
883 if (!wavefront_fx_idle (dev)) return (-1);
884 outb (0x07, dev->fx_dsp_page);
885 outb (0x03, dev->fx_dsp_addr);
886 outb (0x0f, dev->fx_dsp_msb);
887 outb (0xff, dev->fx_dsp_lsb);
888 if (!wavefront_fx_idle (dev)) return (-1);
889 outb (0x07, dev->fx_dsp_page);
890 outb (0x0b, dev->fx_dsp_addr);
891 outb (0x0f, dev->fx_dsp_msb);
892 outb (0xff, dev->fx_dsp_lsb);
893 if (!wavefront_fx_idle (dev)) return (-1);
894 outb (0x07, dev->fx_dsp_page);
895 outb (0x02, dev->fx_dsp_addr);
896 outb (0x00, dev->fx_dsp_msb);
897 outb (0x00, dev->fx_dsp_lsb);
898 if (!wavefront_fx_idle (dev)) return (-1);
899 outb (0x07, dev->fx_dsp_page);
900 outb (0x0a, dev->fx_dsp_addr);
901 outb (0x00, dev->fx_dsp_msb);
902 outb (0x00, dev->fx_dsp_lsb);
903 if (!wavefront_fx_idle (dev)) return (-1);
904 outb (0x07, dev->fx_dsp_page);
905 outb (0x46, dev->fx_dsp_addr);
906 outb (0x00, dev->fx_dsp_msb);
907 outb (0x00, dev->fx_dsp_lsb);
908 if (!wavefront_fx_idle (dev)) return (-1);
909 outb (0x07, dev->fx_dsp_page);
910 outb (0x49, dev->fx_dsp_addr);
911 outb (0x00, dev->fx_dsp_msb);
912 outb (0x00, dev->fx_dsp_lsb);
913
914 /* Now, for some strange reason, lets reload every page
915 and all the coefficients over again. I have *NO* idea
916 why this is done. I do know that no sound is produced
917 is this phase is omitted.
918 */
919
920 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
921 outb (0x00, dev->fx_dsp_page);
922 outb (0x10, dev->fx_dsp_addr);
923
924 for (i = 0; i < sizeof (page_zero_v2); i += 2) {
925 outb (page_zero_v2[i], dev->fx_dsp_msb);
926 outb (page_zero_v2[i+1], dev->fx_dsp_lsb);
927 if (!wavefront_fx_idle (dev)) return (-1);
928 }
929
930 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
931 outb (0x01, dev->fx_dsp_page);
932 outb (0x10, dev->fx_dsp_addr);
933
934 for (i = 0; i < sizeof (page_one_v2); i += 2) {
935 outb (page_one_v2[i], dev->fx_dsp_msb);
936 outb (page_one_v2[i+1], dev->fx_dsp_lsb);
937 if (!wavefront_fx_idle (dev)) return (-1);
938 }
939
940 if (!wavefront_fx_idle (dev)) return (-1);
941 if (!wavefront_fx_idle (dev)) return (-1);
942
943 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
944 outb (0x02, dev->fx_dsp_page);
945 outb (0x10, dev->fx_dsp_addr);
946
947 for (i = 0; i < sizeof (page_two_v2); i++) {
948 outb (page_two_v2[i], dev->fx_dsp_lsb);
949 if (!wavefront_fx_idle (dev)) return (-1);
950 }
951 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
952 outb (0x03, dev->fx_dsp_page);
953 outb (0x10, dev->fx_dsp_addr);
954
955 for (i = 0; i < sizeof (page_three_v2); i++) {
956 outb (page_three_v2[i], dev->fx_dsp_lsb);
957 if (!wavefront_fx_idle (dev)) return (-1);
958 }
959
960 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
961 outb (0x04, dev->fx_dsp_page);
962 outb (0x10, dev->fx_dsp_addr);
963
964 for (i = 0; i < sizeof (page_four_v2); i++) {
965 outb (page_four_v2[i], dev->fx_dsp_lsb);
966 if (!wavefront_fx_idle (dev)) return (-1);
967 }
968
969 outb (FX_LSB_TRANSFER, dev->fx_lcr);
970 outb (0x06, dev->fx_dsp_page);
971
972 /* Page six v.2 is algorithmic */
973
974 for (i = 0x10; i <= 0x3e; i += 2) {
975 outb (i, dev->fx_dsp_addr);
976 outb (0x00, dev->fx_dsp_msb);
977 outb (0x00, dev->fx_dsp_lsb);
978 if (!wavefront_fx_idle (dev)) return (-1);
979 }
980
981 outb (FX_AUTO_INCR|FX_LSB_TRANSFER, dev->fx_lcr);
982 outb (0x07, dev->fx_dsp_page);
983 outb (0x10, dev->fx_dsp_addr);
984
985 for (i = 0; i < sizeof (page_seven_v2); i += 2) {
986 outb (page_seven_v2[i], dev->fx_dsp_msb);
987 outb (page_seven_v2[i+1], dev->fx_dsp_lsb);
988 if (!wavefront_fx_idle (dev)) return (-1);
989 }
990
991 for (i = 0x00; i < sizeof(mod_v2); i += 2) {
992 outb (mod_v2[i], dev->fx_mod_addr);
993 outb (mod_v2[i+1], dev->fx_mod_data);
994 if (!wavefront_fx_idle (dev)) return (-1);
995 }
996 296
997 for (i = 0; i < sizeof (coefficients2); i += 4) { 297out:
998 outb (coefficients2[i], dev->fx_dsp_page); 298#ifdef FIRMWARE_IN_THE_KERNEL
999 outb (coefficients2[i+1], dev->fx_dsp_addr); 299 if (firmware != &yss225_registers_firmware)
1000 outb (coefficients2[i+2], dev->fx_dsp_msb); 300#endif
1001 outb (coefficients2[i+3], dev->fx_dsp_lsb); 301 release_firmware(firmware);
1002 if (!wavefront_fx_idle (dev)) return (-1); 302 return err;
1003 }
1004
1005 for (i = 0; i < sizeof (coefficients3); i += 2) {
1006 int x;
1007
1008 outb (0x07, dev->fx_dsp_page);
1009 x = (i % 4) ? 0x4e : 0x4c;
1010 outb (x, dev->fx_dsp_addr);
1011 outb (coefficients3[i], dev->fx_dsp_msb);
1012 outb (coefficients3[i+1], dev->fx_dsp_lsb);
1013 }
1014
1015 outb (0x00, dev->fx_op); /* mute off */
1016 if (!wavefront_fx_idle (dev)) return (-1);
1017
1018 return (0);
1019} 303}
diff --git a/sound/isa/wavefront/yss225.c b/sound/isa/wavefront/yss225.c
new file mode 100644
index 000000000000..9f6be3ff8ecf
--- /dev/null
+++ b/sound/isa/wavefront/yss225.c
@@ -0,0 +1,2739 @@
1/*
2 * Copyright (c) 1998-2002 by Paul Davis <pbd@op.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18
19/* weird stuff, derived from port I/O tracing with dosemu */
20
21static const struct {
22 unsigned char addr;
23 unsigned char data;
24} yss225_registers[] __devinitdata = {
25/* Set all bits for all channels on the MOD unit to zero */
26{ WAIT_IDLE }, { 0xe, 0x10 }, { 0xf, 0x00 },
27{ WAIT_IDLE }, { 0xe, 0x11 }, { 0xf, 0x00 },
28{ WAIT_IDLE }, { 0xe, 0x12 }, { 0xf, 0x00 },
29{ WAIT_IDLE }, { 0xe, 0x13 }, { 0xf, 0x00 },
30{ WAIT_IDLE }, { 0xe, 0x14 }, { 0xf, 0x00 },
31{ WAIT_IDLE }, { 0xe, 0x15 }, { 0xf, 0x00 },
32{ WAIT_IDLE }, { 0xe, 0x16 }, { 0xf, 0x00 },
33{ WAIT_IDLE }, { 0xe, 0x17 }, { 0xf, 0x00 },
34{ WAIT_IDLE }, { 0xe, 0x18 }, { 0xf, 0x00 },
35{ WAIT_IDLE }, { 0xe, 0x19 }, { 0xf, 0x00 },
36{ WAIT_IDLE }, { 0xe, 0x1a }, { 0xf, 0x00 },
37{ WAIT_IDLE }, { 0xe, 0x1b }, { 0xf, 0x00 },
38{ WAIT_IDLE }, { 0xe, 0x1c }, { 0xf, 0x00 },
39{ WAIT_IDLE }, { 0xe, 0x1d }, { 0xf, 0x00 },
40{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x00 },
41{ WAIT_IDLE }, { 0xe, 0x1f }, { 0xf, 0x00 },
42{ WAIT_IDLE }, { 0xe, 0x20 }, { 0xf, 0x00 },
43{ WAIT_IDLE }, { 0xe, 0x21 }, { 0xf, 0x00 },
44{ WAIT_IDLE }, { 0xe, 0x22 }, { 0xf, 0x00 },
45{ WAIT_IDLE }, { 0xe, 0x23 }, { 0xf, 0x00 },
46{ WAIT_IDLE }, { 0xe, 0x24 }, { 0xf, 0x00 },
47{ WAIT_IDLE }, { 0xe, 0x25 }, { 0xf, 0x00 },
48{ WAIT_IDLE }, { 0xe, 0x26 }, { 0xf, 0x00 },
49{ WAIT_IDLE }, { 0xe, 0x27 }, { 0xf, 0x00 },
50{ WAIT_IDLE }, { 0xe, 0x28 }, { 0xf, 0x00 },
51{ WAIT_IDLE }, { 0xe, 0x29 }, { 0xf, 0x00 },
52{ WAIT_IDLE }, { 0xe, 0x2a }, { 0xf, 0x00 },
53{ WAIT_IDLE }, { 0xe, 0x2b }, { 0xf, 0x00 },
54{ WAIT_IDLE }, { 0xe, 0x2c }, { 0xf, 0x00 },
55{ WAIT_IDLE }, { 0xe, 0x2d }, { 0xf, 0x00 },
56{ WAIT_IDLE }, { 0xe, 0x2e }, { 0xf, 0x00 },
57{ WAIT_IDLE }, { 0xe, 0x2f }, { 0xf, 0x00 },
58{ WAIT_IDLE }, { 0xe, 0x30 }, { 0xf, 0x00 },
59{ WAIT_IDLE }, { 0xe, 0x31 }, { 0xf, 0x00 },
60{ WAIT_IDLE }, { 0xe, 0x32 }, { 0xf, 0x00 },
61{ WAIT_IDLE }, { 0xe, 0x33 }, { 0xf, 0x00 },
62{ WAIT_IDLE }, { 0xe, 0x34 }, { 0xf, 0x00 },
63{ WAIT_IDLE }, { 0xe, 0x35 }, { 0xf, 0x00 },
64{ WAIT_IDLE }, { 0xe, 0x36 }, { 0xf, 0x00 },
65{ WAIT_IDLE }, { 0xe, 0x37 }, { 0xf, 0x00 },
66{ WAIT_IDLE }, { 0xe, 0x38 }, { 0xf, 0x00 },
67{ WAIT_IDLE }, { 0xe, 0x39 }, { 0xf, 0x00 },
68{ WAIT_IDLE }, { 0xe, 0x3a }, { 0xf, 0x00 },
69{ WAIT_IDLE }, { 0xe, 0x3b }, { 0xf, 0x00 },
70{ WAIT_IDLE }, { 0xe, 0x3c }, { 0xf, 0x00 },
71{ WAIT_IDLE }, { 0xe, 0x3d }, { 0xf, 0x00 },
72{ WAIT_IDLE }, { 0xe, 0x3e }, { 0xf, 0x00 },
73{ WAIT_IDLE }, { 0xe, 0x3f }, { 0xf, 0x00 },
74{ WAIT_IDLE }, { 0xe, 0x40 }, { 0xf, 0x00 },
75{ WAIT_IDLE }, { 0xe, 0x41 }, { 0xf, 0x00 },
76{ WAIT_IDLE }, { 0xe, 0x42 }, { 0xf, 0x00 },
77{ WAIT_IDLE }, { 0xe, 0x43 }, { 0xf, 0x00 },
78{ WAIT_IDLE }, { 0xe, 0x44 }, { 0xf, 0x00 },
79{ WAIT_IDLE }, { 0xe, 0x45 }, { 0xf, 0x00 },
80{ WAIT_IDLE }, { 0xe, 0x46 }, { 0xf, 0x00 },
81{ WAIT_IDLE }, { 0xe, 0x47 }, { 0xf, 0x00 },
82{ WAIT_IDLE }, { 0xe, 0x48 }, { 0xf, 0x00 },
83{ WAIT_IDLE }, { 0xe, 0x49 }, { 0xf, 0x00 },
84{ WAIT_IDLE }, { 0xe, 0x4a }, { 0xf, 0x00 },
85{ WAIT_IDLE }, { 0xe, 0x4b }, { 0xf, 0x00 },
86{ WAIT_IDLE }, { 0xe, 0x4c }, { 0xf, 0x00 },
87{ WAIT_IDLE }, { 0xe, 0x4d }, { 0xf, 0x00 },
88{ WAIT_IDLE }, { 0xe, 0x4e }, { 0xf, 0x00 },
89{ WAIT_IDLE }, { 0xe, 0x4f }, { 0xf, 0x00 },
90{ WAIT_IDLE }, { 0xe, 0x50 }, { 0xf, 0x00 },
91{ WAIT_IDLE }, { 0xe, 0x51 }, { 0xf, 0x00 },
92{ WAIT_IDLE }, { 0xe, 0x52 }, { 0xf, 0x00 },
93{ WAIT_IDLE }, { 0xe, 0x53 }, { 0xf, 0x00 },
94{ WAIT_IDLE }, { 0xe, 0x54 }, { 0xf, 0x00 },
95{ WAIT_IDLE }, { 0xe, 0x55 }, { 0xf, 0x00 },
96{ WAIT_IDLE }, { 0xe, 0x56 }, { 0xf, 0x00 },
97{ WAIT_IDLE }, { 0xe, 0x57 }, { 0xf, 0x00 },
98{ WAIT_IDLE }, { 0xe, 0x58 }, { 0xf, 0x00 },
99{ WAIT_IDLE }, { 0xe, 0x59 }, { 0xf, 0x00 },
100{ WAIT_IDLE }, { 0xe, 0x5a }, { 0xf, 0x00 },
101{ WAIT_IDLE }, { 0xe, 0x5b }, { 0xf, 0x00 },
102{ WAIT_IDLE }, { 0xe, 0x5c }, { 0xf, 0x00 },
103{ WAIT_IDLE }, { 0xe, 0x5d }, { 0xf, 0x00 },
104{ WAIT_IDLE }, { 0xe, 0x5e }, { 0xf, 0x00 },
105{ WAIT_IDLE }, { 0xe, 0x5f }, { 0xf, 0x00 },
106{ WAIT_IDLE }, { 0xe, 0x60 }, { 0xf, 0x00 },
107{ WAIT_IDLE }, { 0xe, 0x61 }, { 0xf, 0x00 },
108{ WAIT_IDLE }, { 0xe, 0x62 }, { 0xf, 0x00 },
109{ WAIT_IDLE }, { 0xe, 0x63 }, { 0xf, 0x00 },
110{ WAIT_IDLE }, { 0xe, 0x64 }, { 0xf, 0x00 },
111{ WAIT_IDLE }, { 0xe, 0x65 }, { 0xf, 0x00 },
112{ WAIT_IDLE }, { 0xe, 0x66 }, { 0xf, 0x00 },
113{ WAIT_IDLE }, { 0xe, 0x67 }, { 0xf, 0x00 },
114{ WAIT_IDLE }, { 0xe, 0x68 }, { 0xf, 0x00 },
115{ WAIT_IDLE }, { 0xe, 0x69 }, { 0xf, 0x00 },
116{ WAIT_IDLE }, { 0xe, 0x6a }, { 0xf, 0x00 },
117{ WAIT_IDLE }, { 0xe, 0x6b }, { 0xf, 0x00 },
118{ WAIT_IDLE }, { 0xe, 0x6c }, { 0xf, 0x00 },
119{ WAIT_IDLE }, { 0xe, 0x6d }, { 0xf, 0x00 },
120{ WAIT_IDLE }, { 0xe, 0x6e }, { 0xf, 0x00 },
121{ WAIT_IDLE }, { 0xe, 0x6f }, { 0xf, 0x00 },
122{ WAIT_IDLE }, { 0xe, 0x70 }, { 0xf, 0x00 },
123{ WAIT_IDLE }, { 0xe, 0x71 }, { 0xf, 0x00 },
124{ WAIT_IDLE }, { 0xe, 0x72 }, { 0xf, 0x00 },
125{ WAIT_IDLE }, { 0xe, 0x73 }, { 0xf, 0x00 },
126{ WAIT_IDLE }, { 0xe, 0x74 }, { 0xf, 0x00 },
127{ WAIT_IDLE }, { 0xe, 0x75 }, { 0xf, 0x00 },
128{ WAIT_IDLE }, { 0xe, 0x76 }, { 0xf, 0x00 },
129{ WAIT_IDLE }, { 0xe, 0x77 }, { 0xf, 0x00 },
130{ WAIT_IDLE }, { 0xe, 0x78 }, { 0xf, 0x00 },
131{ WAIT_IDLE }, { 0xe, 0x79 }, { 0xf, 0x00 },
132{ WAIT_IDLE }, { 0xe, 0x7a }, { 0xf, 0x00 },
133{ WAIT_IDLE }, { 0xe, 0x7b }, { 0xf, 0x00 },
134{ WAIT_IDLE }, { 0xe, 0x7c }, { 0xf, 0x00 },
135{ WAIT_IDLE }, { 0xe, 0x7d }, { 0xf, 0x00 },
136{ WAIT_IDLE }, { 0xe, 0x7e }, { 0xf, 0x00 },
137{ WAIT_IDLE }, { 0xe, 0x7f }, { 0xf, 0x00 },
138{ WAIT_IDLE }, { 0xe, 0x80 }, { 0xf, 0x00 },
139{ WAIT_IDLE }, { 0xe, 0x81 }, { 0xf, 0x00 },
140{ WAIT_IDLE }, { 0xe, 0x82 }, { 0xf, 0x00 },
141{ WAIT_IDLE }, { 0xe, 0x83 }, { 0xf, 0x00 },
142{ WAIT_IDLE }, { 0xe, 0x84 }, { 0xf, 0x00 },
143{ WAIT_IDLE }, { 0xe, 0x85 }, { 0xf, 0x00 },
144{ WAIT_IDLE }, { 0xe, 0x86 }, { 0xf, 0x00 },
145{ WAIT_IDLE }, { 0xe, 0x87 }, { 0xf, 0x00 },
146{ WAIT_IDLE }, { 0xe, 0x88 }, { 0xf, 0x00 },
147{ WAIT_IDLE }, { 0xe, 0x89 }, { 0xf, 0x00 },
148{ WAIT_IDLE }, { 0xe, 0x8a }, { 0xf, 0x00 },
149{ WAIT_IDLE }, { 0xe, 0x8b }, { 0xf, 0x00 },
150{ WAIT_IDLE }, { 0xe, 0x8c }, { 0xf, 0x00 },
151{ WAIT_IDLE }, { 0xe, 0x8d }, { 0xf, 0x00 },
152{ WAIT_IDLE }, { 0xe, 0x8e }, { 0xf, 0x00 },
153{ WAIT_IDLE }, { 0xe, 0x8f }, { 0xf, 0x00 },
154{ WAIT_IDLE }, { 0xe, 0x90 }, { 0xf, 0x00 },
155{ WAIT_IDLE }, { 0xe, 0x91 }, { 0xf, 0x00 },
156{ WAIT_IDLE }, { 0xe, 0x92 }, { 0xf, 0x00 },
157{ WAIT_IDLE }, { 0xe, 0x93 }, { 0xf, 0x00 },
158{ WAIT_IDLE }, { 0xe, 0x94 }, { 0xf, 0x00 },
159{ WAIT_IDLE }, { 0xe, 0x95 }, { 0xf, 0x00 },
160{ WAIT_IDLE }, { 0xe, 0x96 }, { 0xf, 0x00 },
161{ WAIT_IDLE }, { 0xe, 0x97 }, { 0xf, 0x00 },
162{ WAIT_IDLE }, { 0xe, 0x98 }, { 0xf, 0x00 },
163{ WAIT_IDLE }, { 0xe, 0x99 }, { 0xf, 0x00 },
164{ WAIT_IDLE }, { 0xe, 0x9a }, { 0xf, 0x00 },
165{ WAIT_IDLE }, { 0xe, 0x9b }, { 0xf, 0x00 },
166{ WAIT_IDLE }, { 0xe, 0x9c }, { 0xf, 0x00 },
167{ WAIT_IDLE }, { 0xe, 0x9d }, { 0xf, 0x00 },
168{ WAIT_IDLE }, { 0xe, 0x9e }, { 0xf, 0x00 },
169{ WAIT_IDLE }, { 0xe, 0x9f }, { 0xf, 0x00 },
170{ WAIT_IDLE }, { 0xe, 0xa0 }, { 0xf, 0x00 },
171{ WAIT_IDLE }, { 0xe, 0xa1 }, { 0xf, 0x00 },
172{ WAIT_IDLE }, { 0xe, 0xa2 }, { 0xf, 0x00 },
173{ WAIT_IDLE }, { 0xe, 0xa3 }, { 0xf, 0x00 },
174{ WAIT_IDLE }, { 0xe, 0xa4 }, { 0xf, 0x00 },
175{ WAIT_IDLE }, { 0xe, 0xa5 }, { 0xf, 0x00 },
176{ WAIT_IDLE }, { 0xe, 0xa6 }, { 0xf, 0x00 },
177{ WAIT_IDLE }, { 0xe, 0xa7 }, { 0xf, 0x00 },
178{ WAIT_IDLE }, { 0xe, 0xa8 }, { 0xf, 0x00 },
179{ WAIT_IDLE }, { 0xe, 0xa9 }, { 0xf, 0x00 },
180{ WAIT_IDLE }, { 0xe, 0xaa }, { 0xf, 0x00 },
181{ WAIT_IDLE }, { 0xe, 0xab }, { 0xf, 0x00 },
182{ WAIT_IDLE }, { 0xe, 0xac }, { 0xf, 0x00 },
183{ WAIT_IDLE }, { 0xe, 0xad }, { 0xf, 0x00 },
184{ WAIT_IDLE }, { 0xe, 0xae }, { 0xf, 0x00 },
185{ WAIT_IDLE }, { 0xe, 0xaf }, { 0xf, 0x00 },
186{ WAIT_IDLE }, { 0xe, 0xb0 }, { 0xf, 0x00 },
187{ WAIT_IDLE }, { 0xe, 0xb1 }, { 0xf, 0x00 },
188{ WAIT_IDLE }, { 0xe, 0xb2 }, { 0xf, 0x00 },
189{ WAIT_IDLE }, { 0xe, 0xb3 }, { 0xf, 0x00 },
190{ WAIT_IDLE }, { 0xe, 0xb4 }, { 0xf, 0x00 },
191{ WAIT_IDLE }, { 0xe, 0xb5 }, { 0xf, 0x00 },
192{ WAIT_IDLE }, { 0xe, 0xb6 }, { 0xf, 0x00 },
193{ WAIT_IDLE }, { 0xe, 0xb7 }, { 0xf, 0x00 },
194{ WAIT_IDLE }, { 0xe, 0xb8 }, { 0xf, 0x00 },
195{ WAIT_IDLE }, { 0xe, 0xb9 }, { 0xf, 0x00 },
196{ WAIT_IDLE }, { 0xe, 0xba }, { 0xf, 0x00 },
197{ WAIT_IDLE }, { 0xe, 0xbb }, { 0xf, 0x00 },
198{ WAIT_IDLE }, { 0xe, 0xbc }, { 0xf, 0x00 },
199{ WAIT_IDLE }, { 0xe, 0xbd }, { 0xf, 0x00 },
200{ WAIT_IDLE }, { 0xe, 0xbe }, { 0xf, 0x00 },
201{ WAIT_IDLE }, { 0xe, 0xbf }, { 0xf, 0x00 },
202{ WAIT_IDLE }, { 0xe, 0xc0 }, { 0xf, 0x00 },
203{ WAIT_IDLE }, { 0xe, 0xc1 }, { 0xf, 0x00 },
204{ WAIT_IDLE }, { 0xe, 0xc2 }, { 0xf, 0x00 },
205{ WAIT_IDLE }, { 0xe, 0xc3 }, { 0xf, 0x00 },
206{ WAIT_IDLE }, { 0xe, 0xc4 }, { 0xf, 0x00 },
207{ WAIT_IDLE }, { 0xe, 0xc5 }, { 0xf, 0x00 },
208{ WAIT_IDLE }, { 0xe, 0xc6 }, { 0xf, 0x00 },
209{ WAIT_IDLE }, { 0xe, 0xc7 }, { 0xf, 0x00 },
210{ WAIT_IDLE }, { 0xe, 0xc8 }, { 0xf, 0x00 },
211{ WAIT_IDLE }, { 0xe, 0xc9 }, { 0xf, 0x00 },
212{ WAIT_IDLE }, { 0xe, 0xca }, { 0xf, 0x00 },
213{ WAIT_IDLE }, { 0xe, 0xcb }, { 0xf, 0x00 },
214{ WAIT_IDLE }, { 0xe, 0xcc }, { 0xf, 0x00 },
215{ WAIT_IDLE }, { 0xe, 0xcd }, { 0xf, 0x00 },
216{ WAIT_IDLE }, { 0xe, 0xce }, { 0xf, 0x00 },
217{ WAIT_IDLE }, { 0xe, 0xcf }, { 0xf, 0x00 },
218{ WAIT_IDLE }, { 0xe, 0xd0 }, { 0xf, 0x00 },
219{ WAIT_IDLE }, { 0xe, 0xd1 }, { 0xf, 0x00 },
220{ WAIT_IDLE }, { 0xe, 0xd2 }, { 0xf, 0x00 },
221{ WAIT_IDLE }, { 0xe, 0xd3 }, { 0xf, 0x00 },
222{ WAIT_IDLE }, { 0xe, 0xd4 }, { 0xf, 0x00 },
223{ WAIT_IDLE }, { 0xe, 0xd5 }, { 0xf, 0x00 },
224{ WAIT_IDLE }, { 0xe, 0xd6 }, { 0xf, 0x00 },
225{ WAIT_IDLE }, { 0xe, 0xd7 }, { 0xf, 0x00 },
226{ WAIT_IDLE }, { 0xe, 0xd8 }, { 0xf, 0x00 },
227{ WAIT_IDLE }, { 0xe, 0xd9 }, { 0xf, 0x00 },
228{ WAIT_IDLE }, { 0xe, 0xda }, { 0xf, 0x00 },
229{ WAIT_IDLE }, { 0xe, 0xdb }, { 0xf, 0x00 },
230{ WAIT_IDLE }, { 0xe, 0xdc }, { 0xf, 0x00 },
231{ WAIT_IDLE }, { 0xe, 0xdd }, { 0xf, 0x00 },
232{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x00 },
233{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x00 },
234{ WAIT_IDLE }, { 0xe, 0xe0 }, { 0xf, 0x00 },
235{ WAIT_IDLE }, { 0xe, 0xe1 }, { 0xf, 0x00 },
236{ WAIT_IDLE }, { 0xe, 0xe2 }, { 0xf, 0x00 },
237{ WAIT_IDLE }, { 0xe, 0xe3 }, { 0xf, 0x00 },
238{ WAIT_IDLE }, { 0xe, 0xe4 }, { 0xf, 0x00 },
239{ WAIT_IDLE }, { 0xe, 0xe5 }, { 0xf, 0x00 },
240{ WAIT_IDLE }, { 0xe, 0xe6 }, { 0xf, 0x00 },
241{ WAIT_IDLE }, { 0xe, 0xe7 }, { 0xf, 0x00 },
242{ WAIT_IDLE }, { 0xe, 0xe8 }, { 0xf, 0x00 },
243{ WAIT_IDLE }, { 0xe, 0xe9 }, { 0xf, 0x00 },
244{ WAIT_IDLE }, { 0xe, 0xea }, { 0xf, 0x00 },
245{ WAIT_IDLE }, { 0xe, 0xeb }, { 0xf, 0x00 },
246{ WAIT_IDLE }, { 0xe, 0xec }, { 0xf, 0x00 },
247{ WAIT_IDLE }, { 0xe, 0xed }, { 0xf, 0x00 },
248{ WAIT_IDLE }, { 0xe, 0xee }, { 0xf, 0x00 },
249{ WAIT_IDLE }, { 0xe, 0xef }, { 0xf, 0x00 },
250{ WAIT_IDLE }, { 0xe, 0xf0 }, { 0xf, 0x00 },
251{ WAIT_IDLE }, { 0xe, 0xf1 }, { 0xf, 0x00 },
252{ WAIT_IDLE }, { 0xe, 0xf2 }, { 0xf, 0x00 },
253{ WAIT_IDLE }, { 0xe, 0xf3 }, { 0xf, 0x00 },
254{ WAIT_IDLE }, { 0xe, 0xf4 }, { 0xf, 0x00 },
255{ WAIT_IDLE }, { 0xe, 0xf5 }, { 0xf, 0x00 },
256{ WAIT_IDLE }, { 0xe, 0xf6 }, { 0xf, 0x00 },
257{ WAIT_IDLE }, { 0xe, 0xf7 }, { 0xf, 0x00 },
258{ WAIT_IDLE }, { 0xe, 0xf8 }, { 0xf, 0x00 },
259{ WAIT_IDLE }, { 0xe, 0xf9 }, { 0xf, 0x00 },
260{ WAIT_IDLE }, { 0xe, 0xfa }, { 0xf, 0x00 },
261{ WAIT_IDLE }, { 0xe, 0xfb }, { 0xf, 0x00 },
262{ WAIT_IDLE }, { 0xe, 0xfc }, { 0xf, 0x00 },
263{ WAIT_IDLE }, { 0xe, 0xfd }, { 0xf, 0x00 },
264{ WAIT_IDLE }, { 0xe, 0xfe }, { 0xf, 0x00 },
265{ WAIT_IDLE }, { 0xe, 0xff }, { 0xf, 0x00 },
266
267/* XXX But why do this twice? */
268{ WAIT_IDLE }, { 0xe, 0x10 }, { 0xf, 0x00 },
269{ WAIT_IDLE }, { 0xe, 0x11 }, { 0xf, 0x00 },
270{ WAIT_IDLE }, { 0xe, 0x12 }, { 0xf, 0x00 },
271{ WAIT_IDLE }, { 0xe, 0x13 }, { 0xf, 0x00 },
272{ WAIT_IDLE }, { 0xe, 0x14 }, { 0xf, 0x00 },
273{ WAIT_IDLE }, { 0xe, 0x15 }, { 0xf, 0x00 },
274{ WAIT_IDLE }, { 0xe, 0x16 }, { 0xf, 0x00 },
275{ WAIT_IDLE }, { 0xe, 0x17 }, { 0xf, 0x00 },
276{ WAIT_IDLE }, { 0xe, 0x18 }, { 0xf, 0x00 },
277{ WAIT_IDLE }, { 0xe, 0x19 }, { 0xf, 0x00 },
278{ WAIT_IDLE }, { 0xe, 0x1a }, { 0xf, 0x00 },
279{ WAIT_IDLE }, { 0xe, 0x1b }, { 0xf, 0x00 },
280{ WAIT_IDLE }, { 0xe, 0x1c }, { 0xf, 0x00 },
281{ WAIT_IDLE }, { 0xe, 0x1d }, { 0xf, 0x00 },
282{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x00 },
283{ WAIT_IDLE }, { 0xe, 0x1f }, { 0xf, 0x00 },
284{ WAIT_IDLE }, { 0xe, 0x20 }, { 0xf, 0x00 },
285{ WAIT_IDLE }, { 0xe, 0x21 }, { 0xf, 0x00 },
286{ WAIT_IDLE }, { 0xe, 0x22 }, { 0xf, 0x00 },
287{ WAIT_IDLE }, { 0xe, 0x23 }, { 0xf, 0x00 },
288{ WAIT_IDLE }, { 0xe, 0x24 }, { 0xf, 0x00 },
289{ WAIT_IDLE }, { 0xe, 0x25 }, { 0xf, 0x00 },
290{ WAIT_IDLE }, { 0xe, 0x26 }, { 0xf, 0x00 },
291{ WAIT_IDLE }, { 0xe, 0x27 }, { 0xf, 0x00 },
292{ WAIT_IDLE }, { 0xe, 0x28 }, { 0xf, 0x00 },
293{ WAIT_IDLE }, { 0xe, 0x29 }, { 0xf, 0x00 },
294{ WAIT_IDLE }, { 0xe, 0x2a }, { 0xf, 0x00 },
295{ WAIT_IDLE }, { 0xe, 0x2b }, { 0xf, 0x00 },
296{ WAIT_IDLE }, { 0xe, 0x2c }, { 0xf, 0x00 },
297{ WAIT_IDLE }, { 0xe, 0x2d }, { 0xf, 0x00 },
298{ WAIT_IDLE }, { 0xe, 0x2e }, { 0xf, 0x00 },
299{ WAIT_IDLE }, { 0xe, 0x2f }, { 0xf, 0x00 },
300{ WAIT_IDLE }, { 0xe, 0x30 }, { 0xf, 0x00 },
301{ WAIT_IDLE }, { 0xe, 0x31 }, { 0xf, 0x00 },
302{ WAIT_IDLE }, { 0xe, 0x32 }, { 0xf, 0x00 },
303{ WAIT_IDLE }, { 0xe, 0x33 }, { 0xf, 0x00 },
304{ WAIT_IDLE }, { 0xe, 0x34 }, { 0xf, 0x00 },
305{ WAIT_IDLE }, { 0xe, 0x35 }, { 0xf, 0x00 },
306{ WAIT_IDLE }, { 0xe, 0x36 }, { 0xf, 0x00 },
307{ WAIT_IDLE }, { 0xe, 0x37 }, { 0xf, 0x00 },
308{ WAIT_IDLE }, { 0xe, 0x38 }, { 0xf, 0x00 },
309{ WAIT_IDLE }, { 0xe, 0x39 }, { 0xf, 0x00 },
310{ WAIT_IDLE }, { 0xe, 0x3a }, { 0xf, 0x00 },
311{ WAIT_IDLE }, { 0xe, 0x3b }, { 0xf, 0x00 },
312{ WAIT_IDLE }, { 0xe, 0x3c }, { 0xf, 0x00 },
313{ WAIT_IDLE }, { 0xe, 0x3d }, { 0xf, 0x00 },
314{ WAIT_IDLE }, { 0xe, 0x3e }, { 0xf, 0x00 },
315{ WAIT_IDLE }, { 0xe, 0x3f }, { 0xf, 0x00 },
316{ WAIT_IDLE }, { 0xe, 0x40 }, { 0xf, 0x00 },
317{ WAIT_IDLE }, { 0xe, 0x41 }, { 0xf, 0x00 },
318{ WAIT_IDLE }, { 0xe, 0x42 }, { 0xf, 0x00 },
319{ WAIT_IDLE }, { 0xe, 0x43 }, { 0xf, 0x00 },
320{ WAIT_IDLE }, { 0xe, 0x44 }, { 0xf, 0x00 },
321{ WAIT_IDLE }, { 0xe, 0x45 }, { 0xf, 0x00 },
322{ WAIT_IDLE }, { 0xe, 0x46 }, { 0xf, 0x00 },
323{ WAIT_IDLE }, { 0xe, 0x47 }, { 0xf, 0x00 },
324{ WAIT_IDLE }, { 0xe, 0x48 }, { 0xf, 0x00 },
325{ WAIT_IDLE }, { 0xe, 0x49 }, { 0xf, 0x00 },
326{ WAIT_IDLE }, { 0xe, 0x4a }, { 0xf, 0x00 },
327{ WAIT_IDLE }, { 0xe, 0x4b }, { 0xf, 0x00 },
328{ WAIT_IDLE }, { 0xe, 0x4c }, { 0xf, 0x00 },
329{ WAIT_IDLE }, { 0xe, 0x4d }, { 0xf, 0x00 },
330{ WAIT_IDLE }, { 0xe, 0x4e }, { 0xf, 0x00 },
331{ WAIT_IDLE }, { 0xe, 0x4f }, { 0xf, 0x00 },
332{ WAIT_IDLE }, { 0xe, 0x50 }, { 0xf, 0x00 },
333{ WAIT_IDLE }, { 0xe, 0x51 }, { 0xf, 0x00 },
334{ WAIT_IDLE }, { 0xe, 0x52 }, { 0xf, 0x00 },
335{ WAIT_IDLE }, { 0xe, 0x53 }, { 0xf, 0x00 },
336{ WAIT_IDLE }, { 0xe, 0x54 }, { 0xf, 0x00 },
337{ WAIT_IDLE }, { 0xe, 0x55 }, { 0xf, 0x00 },
338{ WAIT_IDLE }, { 0xe, 0x56 }, { 0xf, 0x00 },
339{ WAIT_IDLE }, { 0xe, 0x57 }, { 0xf, 0x00 },
340{ WAIT_IDLE }, { 0xe, 0x58 }, { 0xf, 0x00 },
341{ WAIT_IDLE }, { 0xe, 0x59 }, { 0xf, 0x00 },
342{ WAIT_IDLE }, { 0xe, 0x5a }, { 0xf, 0x00 },
343{ WAIT_IDLE }, { 0xe, 0x5b }, { 0xf, 0x00 },
344{ WAIT_IDLE }, { 0xe, 0x5c }, { 0xf, 0x00 },
345{ WAIT_IDLE }, { 0xe, 0x5d }, { 0xf, 0x00 },
346{ WAIT_IDLE }, { 0xe, 0x5e }, { 0xf, 0x00 },
347{ WAIT_IDLE }, { 0xe, 0x5f }, { 0xf, 0x00 },
348{ WAIT_IDLE }, { 0xe, 0x60 }, { 0xf, 0x00 },
349{ WAIT_IDLE }, { 0xe, 0x61 }, { 0xf, 0x00 },
350{ WAIT_IDLE }, { 0xe, 0x62 }, { 0xf, 0x00 },
351{ WAIT_IDLE }, { 0xe, 0x63 }, { 0xf, 0x00 },
352{ WAIT_IDLE }, { 0xe, 0x64 }, { 0xf, 0x00 },
353{ WAIT_IDLE }, { 0xe, 0x65 }, { 0xf, 0x00 },
354{ WAIT_IDLE }, { 0xe, 0x66 }, { 0xf, 0x00 },
355{ WAIT_IDLE }, { 0xe, 0x67 }, { 0xf, 0x00 },
356{ WAIT_IDLE }, { 0xe, 0x68 }, { 0xf, 0x00 },
357{ WAIT_IDLE }, { 0xe, 0x69 }, { 0xf, 0x00 },
358{ WAIT_IDLE }, { 0xe, 0x6a }, { 0xf, 0x00 },
359{ WAIT_IDLE }, { 0xe, 0x6b }, { 0xf, 0x00 },
360{ WAIT_IDLE }, { 0xe, 0x6c }, { 0xf, 0x00 },
361{ WAIT_IDLE }, { 0xe, 0x6d }, { 0xf, 0x00 },
362{ WAIT_IDLE }, { 0xe, 0x6e }, { 0xf, 0x00 },
363{ WAIT_IDLE }, { 0xe, 0x6f }, { 0xf, 0x00 },
364{ WAIT_IDLE }, { 0xe, 0x70 }, { 0xf, 0x00 },
365{ WAIT_IDLE }, { 0xe, 0x71 }, { 0xf, 0x00 },
366{ WAIT_IDLE }, { 0xe, 0x72 }, { 0xf, 0x00 },
367{ WAIT_IDLE }, { 0xe, 0x73 }, { 0xf, 0x00 },
368{ WAIT_IDLE }, { 0xe, 0x74 }, { 0xf, 0x00 },
369{ WAIT_IDLE }, { 0xe, 0x75 }, { 0xf, 0x00 },
370{ WAIT_IDLE }, { 0xe, 0x76 }, { 0xf, 0x00 },
371{ WAIT_IDLE }, { 0xe, 0x77 }, { 0xf, 0x00 },
372{ WAIT_IDLE }, { 0xe, 0x78 }, { 0xf, 0x00 },
373{ WAIT_IDLE }, { 0xe, 0x79 }, { 0xf, 0x00 },
374{ WAIT_IDLE }, { 0xe, 0x7a }, { 0xf, 0x00 },
375{ WAIT_IDLE }, { 0xe, 0x7b }, { 0xf, 0x00 },
376{ WAIT_IDLE }, { 0xe, 0x7c }, { 0xf, 0x00 },
377{ WAIT_IDLE }, { 0xe, 0x7d }, { 0xf, 0x00 },
378{ WAIT_IDLE }, { 0xe, 0x7e }, { 0xf, 0x00 },
379{ WAIT_IDLE }, { 0xe, 0x7f }, { 0xf, 0x00 },
380{ WAIT_IDLE }, { 0xe, 0x80 }, { 0xf, 0x00 },
381{ WAIT_IDLE }, { 0xe, 0x81 }, { 0xf, 0x00 },
382{ WAIT_IDLE }, { 0xe, 0x82 }, { 0xf, 0x00 },
383{ WAIT_IDLE }, { 0xe, 0x83 }, { 0xf, 0x00 },
384{ WAIT_IDLE }, { 0xe, 0x84 }, { 0xf, 0x00 },
385{ WAIT_IDLE }, { 0xe, 0x85 }, { 0xf, 0x00 },
386{ WAIT_IDLE }, { 0xe, 0x86 }, { 0xf, 0x00 },
387{ WAIT_IDLE }, { 0xe, 0x87 }, { 0xf, 0x00 },
388{ WAIT_IDLE }, { 0xe, 0x88 }, { 0xf, 0x00 },
389{ WAIT_IDLE }, { 0xe, 0x89 }, { 0xf, 0x00 },
390{ WAIT_IDLE }, { 0xe, 0x8a }, { 0xf, 0x00 },
391{ WAIT_IDLE }, { 0xe, 0x8b }, { 0xf, 0x00 },
392{ WAIT_IDLE }, { 0xe, 0x8c }, { 0xf, 0x00 },
393{ WAIT_IDLE }, { 0xe, 0x8d }, { 0xf, 0x00 },
394{ WAIT_IDLE }, { 0xe, 0x8e }, { 0xf, 0x00 },
395{ WAIT_IDLE }, { 0xe, 0x8f }, { 0xf, 0x00 },
396{ WAIT_IDLE }, { 0xe, 0x90 }, { 0xf, 0x00 },
397{ WAIT_IDLE }, { 0xe, 0x91 }, { 0xf, 0x00 },
398{ WAIT_IDLE }, { 0xe, 0x92 }, { 0xf, 0x00 },
399{ WAIT_IDLE }, { 0xe, 0x93 }, { 0xf, 0x00 },
400{ WAIT_IDLE }, { 0xe, 0x94 }, { 0xf, 0x00 },
401{ WAIT_IDLE }, { 0xe, 0x95 }, { 0xf, 0x00 },
402{ WAIT_IDLE }, { 0xe, 0x96 }, { 0xf, 0x00 },
403{ WAIT_IDLE }, { 0xe, 0x97 }, { 0xf, 0x00 },
404{ WAIT_IDLE }, { 0xe, 0x98 }, { 0xf, 0x00 },
405{ WAIT_IDLE }, { 0xe, 0x99 }, { 0xf, 0x00 },
406{ WAIT_IDLE }, { 0xe, 0x9a }, { 0xf, 0x00 },
407{ WAIT_IDLE }, { 0xe, 0x9b }, { 0xf, 0x00 },
408{ WAIT_IDLE }, { 0xe, 0x9c }, { 0xf, 0x00 },
409{ WAIT_IDLE }, { 0xe, 0x9d }, { 0xf, 0x00 },
410{ WAIT_IDLE }, { 0xe, 0x9e }, { 0xf, 0x00 },
411{ WAIT_IDLE }, { 0xe, 0x9f }, { 0xf, 0x00 },
412{ WAIT_IDLE }, { 0xe, 0xa0 }, { 0xf, 0x00 },
413{ WAIT_IDLE }, { 0xe, 0xa1 }, { 0xf, 0x00 },
414{ WAIT_IDLE }, { 0xe, 0xa2 }, { 0xf, 0x00 },
415{ WAIT_IDLE }, { 0xe, 0xa3 }, { 0xf, 0x00 },
416{ WAIT_IDLE }, { 0xe, 0xa4 }, { 0xf, 0x00 },
417{ WAIT_IDLE }, { 0xe, 0xa5 }, { 0xf, 0x00 },
418{ WAIT_IDLE }, { 0xe, 0xa6 }, { 0xf, 0x00 },
419{ WAIT_IDLE }, { 0xe, 0xa7 }, { 0xf, 0x00 },
420{ WAIT_IDLE }, { 0xe, 0xa8 }, { 0xf, 0x00 },
421{ WAIT_IDLE }, { 0xe, 0xa9 }, { 0xf, 0x00 },
422{ WAIT_IDLE }, { 0xe, 0xaa }, { 0xf, 0x00 },
423{ WAIT_IDLE }, { 0xe, 0xab }, { 0xf, 0x00 },
424{ WAIT_IDLE }, { 0xe, 0xac }, { 0xf, 0x00 },
425{ WAIT_IDLE }, { 0xe, 0xad }, { 0xf, 0x00 },
426{ WAIT_IDLE }, { 0xe, 0xae }, { 0xf, 0x00 },
427{ WAIT_IDLE }, { 0xe, 0xaf }, { 0xf, 0x00 },
428{ WAIT_IDLE }, { 0xe, 0xb0 }, { 0xf, 0x00 },
429{ WAIT_IDLE }, { 0xe, 0xb1 }, { 0xf, 0x00 },
430{ WAIT_IDLE }, { 0xe, 0xb2 }, { 0xf, 0x00 },
431{ WAIT_IDLE }, { 0xe, 0xb3 }, { 0xf, 0x00 },
432{ WAIT_IDLE }, { 0xe, 0xb4 }, { 0xf, 0x00 },
433{ WAIT_IDLE }, { 0xe, 0xb5 }, { 0xf, 0x00 },
434{ WAIT_IDLE }, { 0xe, 0xb6 }, { 0xf, 0x00 },
435{ WAIT_IDLE }, { 0xe, 0xb7 }, { 0xf, 0x00 },
436{ WAIT_IDLE }, { 0xe, 0xb8 }, { 0xf, 0x00 },
437{ WAIT_IDLE }, { 0xe, 0xb9 }, { 0xf, 0x00 },
438{ WAIT_IDLE }, { 0xe, 0xba }, { 0xf, 0x00 },
439{ WAIT_IDLE }, { 0xe, 0xbb }, { 0xf, 0x00 },
440{ WAIT_IDLE }, { 0xe, 0xbc }, { 0xf, 0x00 },
441{ WAIT_IDLE }, { 0xe, 0xbd }, { 0xf, 0x00 },
442{ WAIT_IDLE }, { 0xe, 0xbe }, { 0xf, 0x00 },
443{ WAIT_IDLE }, { 0xe, 0xbf }, { 0xf, 0x00 },
444{ WAIT_IDLE }, { 0xe, 0xc0 }, { 0xf, 0x00 },
445{ WAIT_IDLE }, { 0xe, 0xc1 }, { 0xf, 0x00 },
446{ WAIT_IDLE }, { 0xe, 0xc2 }, { 0xf, 0x00 },
447{ WAIT_IDLE }, { 0xe, 0xc3 }, { 0xf, 0x00 },
448{ WAIT_IDLE }, { 0xe, 0xc4 }, { 0xf, 0x00 },
449{ WAIT_IDLE }, { 0xe, 0xc5 }, { 0xf, 0x00 },
450{ WAIT_IDLE }, { 0xe, 0xc6 }, { 0xf, 0x00 },
451{ WAIT_IDLE }, { 0xe, 0xc7 }, { 0xf, 0x00 },
452{ WAIT_IDLE }, { 0xe, 0xc8 }, { 0xf, 0x00 },
453{ WAIT_IDLE }, { 0xe, 0xc9 }, { 0xf, 0x00 },
454{ WAIT_IDLE }, { 0xe, 0xca }, { 0xf, 0x00 },
455{ WAIT_IDLE }, { 0xe, 0xcb }, { 0xf, 0x00 },
456{ WAIT_IDLE }, { 0xe, 0xcc }, { 0xf, 0x00 },
457{ WAIT_IDLE }, { 0xe, 0xcd }, { 0xf, 0x00 },
458{ WAIT_IDLE }, { 0xe, 0xce }, { 0xf, 0x00 },
459{ WAIT_IDLE }, { 0xe, 0xcf }, { 0xf, 0x00 },
460{ WAIT_IDLE }, { 0xe, 0xd0 }, { 0xf, 0x00 },
461{ WAIT_IDLE }, { 0xe, 0xd1 }, { 0xf, 0x00 },
462{ WAIT_IDLE }, { 0xe, 0xd2 }, { 0xf, 0x00 },
463{ WAIT_IDLE }, { 0xe, 0xd3 }, { 0xf, 0x00 },
464{ WAIT_IDLE }, { 0xe, 0xd4 }, { 0xf, 0x00 },
465{ WAIT_IDLE }, { 0xe, 0xd5 }, { 0xf, 0x00 },
466{ WAIT_IDLE }, { 0xe, 0xd6 }, { 0xf, 0x00 },
467{ WAIT_IDLE }, { 0xe, 0xd7 }, { 0xf, 0x00 },
468{ WAIT_IDLE }, { 0xe, 0xd8 }, { 0xf, 0x00 },
469{ WAIT_IDLE }, { 0xe, 0xd9 }, { 0xf, 0x00 },
470{ WAIT_IDLE }, { 0xe, 0xda }, { 0xf, 0x00 },
471{ WAIT_IDLE }, { 0xe, 0xdb }, { 0xf, 0x00 },
472{ WAIT_IDLE }, { 0xe, 0xdc }, { 0xf, 0x00 },
473{ WAIT_IDLE }, { 0xe, 0xdd }, { 0xf, 0x00 },
474{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x00 },
475{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x00 },
476{ WAIT_IDLE }, { 0xe, 0xe0 }, { 0xf, 0x00 },
477{ WAIT_IDLE }, { 0xe, 0xe1 }, { 0xf, 0x00 },
478{ WAIT_IDLE }, { 0xe, 0xe2 }, { 0xf, 0x00 },
479{ WAIT_IDLE }, { 0xe, 0xe3 }, { 0xf, 0x00 },
480{ WAIT_IDLE }, { 0xe, 0xe4 }, { 0xf, 0x00 },
481{ WAIT_IDLE }, { 0xe, 0xe5 }, { 0xf, 0x00 },
482{ WAIT_IDLE }, { 0xe, 0xe6 }, { 0xf, 0x00 },
483{ WAIT_IDLE }, { 0xe, 0xe7 }, { 0xf, 0x00 },
484{ WAIT_IDLE }, { 0xe, 0xe8 }, { 0xf, 0x00 },
485{ WAIT_IDLE }, { 0xe, 0xe9 }, { 0xf, 0x00 },
486{ WAIT_IDLE }, { 0xe, 0xea }, { 0xf, 0x00 },
487{ WAIT_IDLE }, { 0xe, 0xeb }, { 0xf, 0x00 },
488{ WAIT_IDLE }, { 0xe, 0xec }, { 0xf, 0x00 },
489{ WAIT_IDLE }, { 0xe, 0xed }, { 0xf, 0x00 },
490{ WAIT_IDLE }, { 0xe, 0xee }, { 0xf, 0x00 },
491{ WAIT_IDLE }, { 0xe, 0xef }, { 0xf, 0x00 },
492{ WAIT_IDLE }, { 0xe, 0xf0 }, { 0xf, 0x00 },
493{ WAIT_IDLE }, { 0xe, 0xf1 }, { 0xf, 0x00 },
494{ WAIT_IDLE }, { 0xe, 0xf2 }, { 0xf, 0x00 },
495{ WAIT_IDLE }, { 0xe, 0xf3 }, { 0xf, 0x00 },
496{ WAIT_IDLE }, { 0xe, 0xf4 }, { 0xf, 0x00 },
497{ WAIT_IDLE }, { 0xe, 0xf5 }, { 0xf, 0x00 },
498{ WAIT_IDLE }, { 0xe, 0xf6 }, { 0xf, 0x00 },
499{ WAIT_IDLE }, { 0xe, 0xf7 }, { 0xf, 0x00 },
500{ WAIT_IDLE }, { 0xe, 0xf8 }, { 0xf, 0x00 },
501{ WAIT_IDLE }, { 0xe, 0xf9 }, { 0xf, 0x00 },
502{ WAIT_IDLE }, { 0xe, 0xfa }, { 0xf, 0x00 },
503{ WAIT_IDLE }, { 0xe, 0xfb }, { 0xf, 0x00 },
504{ WAIT_IDLE }, { 0xe, 0xfc }, { 0xf, 0x00 },
505{ WAIT_IDLE }, { 0xe, 0xfd }, { 0xf, 0x00 },
506{ WAIT_IDLE }, { 0xe, 0xfe }, { 0xf, 0x00 },
507{ WAIT_IDLE }, { 0xe, 0xff }, { 0xf, 0x00 },
508
509/* mute on */
510{ WAIT_IDLE }, { 0x8, 0x02 },
511
512{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x00 }, { 0xc, 0x00 },
513{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 },
514{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 },
515{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 },
516{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 },
517{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 },
518{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 },
519{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 },
520{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 },
521
522/* either because of stupidity by TB's programmers, or because it
523 actually does something, rezero the MOD page. */
524{ WAIT_IDLE }, { 0xe, 0x10 }, { 0xf, 0x00 },
525{ WAIT_IDLE }, { 0xe, 0x11 }, { 0xf, 0x00 },
526{ WAIT_IDLE }, { 0xe, 0x12 }, { 0xf, 0x00 },
527{ WAIT_IDLE }, { 0xe, 0x13 }, { 0xf, 0x00 },
528{ WAIT_IDLE }, { 0xe, 0x14 }, { 0xf, 0x00 },
529{ WAIT_IDLE }, { 0xe, 0x15 }, { 0xf, 0x00 },
530{ WAIT_IDLE }, { 0xe, 0x16 }, { 0xf, 0x00 },
531{ WAIT_IDLE }, { 0xe, 0x17 }, { 0xf, 0x00 },
532{ WAIT_IDLE }, { 0xe, 0x18 }, { 0xf, 0x00 },
533{ WAIT_IDLE }, { 0xe, 0x19 }, { 0xf, 0x00 },
534{ WAIT_IDLE }, { 0xe, 0x1a }, { 0xf, 0x00 },
535{ WAIT_IDLE }, { 0xe, 0x1b }, { 0xf, 0x00 },
536{ WAIT_IDLE }, { 0xe, 0x1c }, { 0xf, 0x00 },
537{ WAIT_IDLE }, { 0xe, 0x1d }, { 0xf, 0x00 },
538{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x00 },
539{ WAIT_IDLE }, { 0xe, 0x1f }, { 0xf, 0x00 },
540{ WAIT_IDLE }, { 0xe, 0x20 }, { 0xf, 0x00 },
541{ WAIT_IDLE }, { 0xe, 0x21 }, { 0xf, 0x00 },
542{ WAIT_IDLE }, { 0xe, 0x22 }, { 0xf, 0x00 },
543{ WAIT_IDLE }, { 0xe, 0x23 }, { 0xf, 0x00 },
544{ WAIT_IDLE }, { 0xe, 0x24 }, { 0xf, 0x00 },
545{ WAIT_IDLE }, { 0xe, 0x25 }, { 0xf, 0x00 },
546{ WAIT_IDLE }, { 0xe, 0x26 }, { 0xf, 0x00 },
547{ WAIT_IDLE }, { 0xe, 0x27 }, { 0xf, 0x00 },
548{ WAIT_IDLE }, { 0xe, 0x28 }, { 0xf, 0x00 },
549{ WAIT_IDLE }, { 0xe, 0x29 }, { 0xf, 0x00 },
550{ WAIT_IDLE }, { 0xe, 0x2a }, { 0xf, 0x00 },
551{ WAIT_IDLE }, { 0xe, 0x2b }, { 0xf, 0x00 },
552{ WAIT_IDLE }, { 0xe, 0x2c }, { 0xf, 0x00 },
553{ WAIT_IDLE }, { 0xe, 0x2d }, { 0xf, 0x00 },
554{ WAIT_IDLE }, { 0xe, 0x2e }, { 0xf, 0x00 },
555{ WAIT_IDLE }, { 0xe, 0x2f }, { 0xf, 0x00 },
556{ WAIT_IDLE }, { 0xe, 0x30 }, { 0xf, 0x00 },
557{ WAIT_IDLE }, { 0xe, 0x31 }, { 0xf, 0x00 },
558{ WAIT_IDLE }, { 0xe, 0x32 }, { 0xf, 0x00 },
559{ WAIT_IDLE }, { 0xe, 0x33 }, { 0xf, 0x00 },
560{ WAIT_IDLE }, { 0xe, 0x34 }, { 0xf, 0x00 },
561{ WAIT_IDLE }, { 0xe, 0x35 }, { 0xf, 0x00 },
562{ WAIT_IDLE }, { 0xe, 0x36 }, { 0xf, 0x00 },
563{ WAIT_IDLE }, { 0xe, 0x37 }, { 0xf, 0x00 },
564{ WAIT_IDLE }, { 0xe, 0x38 }, { 0xf, 0x00 },
565{ WAIT_IDLE }, { 0xe, 0x39 }, { 0xf, 0x00 },
566{ WAIT_IDLE }, { 0xe, 0x3a }, { 0xf, 0x00 },
567{ WAIT_IDLE }, { 0xe, 0x3b }, { 0xf, 0x00 },
568{ WAIT_IDLE }, { 0xe, 0x3c }, { 0xf, 0x00 },
569{ WAIT_IDLE }, { 0xe, 0x3d }, { 0xf, 0x00 },
570{ WAIT_IDLE }, { 0xe, 0x3e }, { 0xf, 0x00 },
571{ WAIT_IDLE }, { 0xe, 0x3f }, { 0xf, 0x00 },
572{ WAIT_IDLE }, { 0xe, 0x40 }, { 0xf, 0x00 },
573{ WAIT_IDLE }, { 0xe, 0x41 }, { 0xf, 0x00 },
574{ WAIT_IDLE }, { 0xe, 0x42 }, { 0xf, 0x00 },
575{ WAIT_IDLE }, { 0xe, 0x43 }, { 0xf, 0x00 },
576{ WAIT_IDLE }, { 0xe, 0x44 }, { 0xf, 0x00 },
577{ WAIT_IDLE }, { 0xe, 0x45 }, { 0xf, 0x00 },
578{ WAIT_IDLE }, { 0xe, 0x46 }, { 0xf, 0x00 },
579{ WAIT_IDLE }, { 0xe, 0x47 }, { 0xf, 0x00 },
580{ WAIT_IDLE }, { 0xe, 0x48 }, { 0xf, 0x00 },
581{ WAIT_IDLE }, { 0xe, 0x49 }, { 0xf, 0x00 },
582{ WAIT_IDLE }, { 0xe, 0x4a }, { 0xf, 0x00 },
583{ WAIT_IDLE }, { 0xe, 0x4b }, { 0xf, 0x00 },
584{ WAIT_IDLE }, { 0xe, 0x4c }, { 0xf, 0x00 },
585{ WAIT_IDLE }, { 0xe, 0x4d }, { 0xf, 0x00 },
586{ WAIT_IDLE }, { 0xe, 0x4e }, { 0xf, 0x00 },
587{ WAIT_IDLE }, { 0xe, 0x4f }, { 0xf, 0x00 },
588{ WAIT_IDLE }, { 0xe, 0x50 }, { 0xf, 0x00 },
589{ WAIT_IDLE }, { 0xe, 0x51 }, { 0xf, 0x00 },
590{ WAIT_IDLE }, { 0xe, 0x52 }, { 0xf, 0x00 },
591{ WAIT_IDLE }, { 0xe, 0x53 }, { 0xf, 0x00 },
592{ WAIT_IDLE }, { 0xe, 0x54 }, { 0xf, 0x00 },
593{ WAIT_IDLE }, { 0xe, 0x55 }, { 0xf, 0x00 },
594{ WAIT_IDLE }, { 0xe, 0x56 }, { 0xf, 0x00 },
595{ WAIT_IDLE }, { 0xe, 0x57 }, { 0xf, 0x00 },
596{ WAIT_IDLE }, { 0xe, 0x58 }, { 0xf, 0x00 },
597{ WAIT_IDLE }, { 0xe, 0x59 }, { 0xf, 0x00 },
598{ WAIT_IDLE }, { 0xe, 0x5a }, { 0xf, 0x00 },
599{ WAIT_IDLE }, { 0xe, 0x5b }, { 0xf, 0x00 },
600{ WAIT_IDLE }, { 0xe, 0x5c }, { 0xf, 0x00 },
601{ WAIT_IDLE }, { 0xe, 0x5d }, { 0xf, 0x00 },
602{ WAIT_IDLE }, { 0xe, 0x5e }, { 0xf, 0x00 },
603{ WAIT_IDLE }, { 0xe, 0x5f }, { 0xf, 0x00 },
604{ WAIT_IDLE }, { 0xe, 0x60 }, { 0xf, 0x00 },
605{ WAIT_IDLE }, { 0xe, 0x61 }, { 0xf, 0x00 },
606{ WAIT_IDLE }, { 0xe, 0x62 }, { 0xf, 0x00 },
607{ WAIT_IDLE }, { 0xe, 0x63 }, { 0xf, 0x00 },
608{ WAIT_IDLE }, { 0xe, 0x64 }, { 0xf, 0x00 },
609{ WAIT_IDLE }, { 0xe, 0x65 }, { 0xf, 0x00 },
610{ WAIT_IDLE }, { 0xe, 0x66 }, { 0xf, 0x00 },
611{ WAIT_IDLE }, { 0xe, 0x67 }, { 0xf, 0x00 },
612{ WAIT_IDLE }, { 0xe, 0x68 }, { 0xf, 0x00 },
613{ WAIT_IDLE }, { 0xe, 0x69 }, { 0xf, 0x00 },
614{ WAIT_IDLE }, { 0xe, 0x6a }, { 0xf, 0x00 },
615{ WAIT_IDLE }, { 0xe, 0x6b }, { 0xf, 0x00 },
616{ WAIT_IDLE }, { 0xe, 0x6c }, { 0xf, 0x00 },
617{ WAIT_IDLE }, { 0xe, 0x6d }, { 0xf, 0x00 },
618{ WAIT_IDLE }, { 0xe, 0x6e }, { 0xf, 0x00 },
619{ WAIT_IDLE }, { 0xe, 0x6f }, { 0xf, 0x00 },
620{ WAIT_IDLE }, { 0xe, 0x70 }, { 0xf, 0x00 },
621{ WAIT_IDLE }, { 0xe, 0x71 }, { 0xf, 0x00 },
622{ WAIT_IDLE }, { 0xe, 0x72 }, { 0xf, 0x00 },
623{ WAIT_IDLE }, { 0xe, 0x73 }, { 0xf, 0x00 },
624{ WAIT_IDLE }, { 0xe, 0x74 }, { 0xf, 0x00 },
625{ WAIT_IDLE }, { 0xe, 0x75 }, { 0xf, 0x00 },
626{ WAIT_IDLE }, { 0xe, 0x76 }, { 0xf, 0x00 },
627{ WAIT_IDLE }, { 0xe, 0x77 }, { 0xf, 0x00 },
628{ WAIT_IDLE }, { 0xe, 0x78 }, { 0xf, 0x00 },
629{ WAIT_IDLE }, { 0xe, 0x79 }, { 0xf, 0x00 },
630{ WAIT_IDLE }, { 0xe, 0x7a }, { 0xf, 0x00 },
631{ WAIT_IDLE }, { 0xe, 0x7b }, { 0xf, 0x00 },
632{ WAIT_IDLE }, { 0xe, 0x7c }, { 0xf, 0x00 },
633{ WAIT_IDLE }, { 0xe, 0x7d }, { 0xf, 0x00 },
634{ WAIT_IDLE }, { 0xe, 0x7e }, { 0xf, 0x00 },
635{ WAIT_IDLE }, { 0xe, 0x7f }, { 0xf, 0x00 },
636{ WAIT_IDLE }, { 0xe, 0x80 }, { 0xf, 0x00 },
637{ WAIT_IDLE }, { 0xe, 0x81 }, { 0xf, 0x00 },
638{ WAIT_IDLE }, { 0xe, 0x82 }, { 0xf, 0x00 },
639{ WAIT_IDLE }, { 0xe, 0x83 }, { 0xf, 0x00 },
640{ WAIT_IDLE }, { 0xe, 0x84 }, { 0xf, 0x00 },
641{ WAIT_IDLE }, { 0xe, 0x85 }, { 0xf, 0x00 },
642{ WAIT_IDLE }, { 0xe, 0x86 }, { 0xf, 0x00 },
643{ WAIT_IDLE }, { 0xe, 0x87 }, { 0xf, 0x00 },
644{ WAIT_IDLE }, { 0xe, 0x88 }, { 0xf, 0x00 },
645{ WAIT_IDLE }, { 0xe, 0x89 }, { 0xf, 0x00 },
646{ WAIT_IDLE }, { 0xe, 0x8a }, { 0xf, 0x00 },
647{ WAIT_IDLE }, { 0xe, 0x8b }, { 0xf, 0x00 },
648{ WAIT_IDLE }, { 0xe, 0x8c }, { 0xf, 0x00 },
649{ WAIT_IDLE }, { 0xe, 0x8d }, { 0xf, 0x00 },
650{ WAIT_IDLE }, { 0xe, 0x8e }, { 0xf, 0x00 },
651{ WAIT_IDLE }, { 0xe, 0x8f }, { 0xf, 0x00 },
652{ WAIT_IDLE }, { 0xe, 0x90 }, { 0xf, 0x00 },
653{ WAIT_IDLE }, { 0xe, 0x91 }, { 0xf, 0x00 },
654{ WAIT_IDLE }, { 0xe, 0x92 }, { 0xf, 0x00 },
655{ WAIT_IDLE }, { 0xe, 0x93 }, { 0xf, 0x00 },
656{ WAIT_IDLE }, { 0xe, 0x94 }, { 0xf, 0x00 },
657{ WAIT_IDLE }, { 0xe, 0x95 }, { 0xf, 0x00 },
658{ WAIT_IDLE }, { 0xe, 0x96 }, { 0xf, 0x00 },
659{ WAIT_IDLE }, { 0xe, 0x97 }, { 0xf, 0x00 },
660{ WAIT_IDLE }, { 0xe, 0x98 }, { 0xf, 0x00 },
661{ WAIT_IDLE }, { 0xe, 0x99 }, { 0xf, 0x00 },
662{ WAIT_IDLE }, { 0xe, 0x9a }, { 0xf, 0x00 },
663{ WAIT_IDLE }, { 0xe, 0x9b }, { 0xf, 0x00 },
664{ WAIT_IDLE }, { 0xe, 0x9c }, { 0xf, 0x00 },
665{ WAIT_IDLE }, { 0xe, 0x9d }, { 0xf, 0x00 },
666{ WAIT_IDLE }, { 0xe, 0x9e }, { 0xf, 0x00 },
667{ WAIT_IDLE }, { 0xe, 0x9f }, { 0xf, 0x00 },
668{ WAIT_IDLE }, { 0xe, 0xa0 }, { 0xf, 0x00 },
669{ WAIT_IDLE }, { 0xe, 0xa1 }, { 0xf, 0x00 },
670{ WAIT_IDLE }, { 0xe, 0xa2 }, { 0xf, 0x00 },
671{ WAIT_IDLE }, { 0xe, 0xa3 }, { 0xf, 0x00 },
672{ WAIT_IDLE }, { 0xe, 0xa4 }, { 0xf, 0x00 },
673{ WAIT_IDLE }, { 0xe, 0xa5 }, { 0xf, 0x00 },
674{ WAIT_IDLE }, { 0xe, 0xa6 }, { 0xf, 0x00 },
675{ WAIT_IDLE }, { 0xe, 0xa7 }, { 0xf, 0x00 },
676{ WAIT_IDLE }, { 0xe, 0xa8 }, { 0xf, 0x00 },
677{ WAIT_IDLE }, { 0xe, 0xa9 }, { 0xf, 0x00 },
678{ WAIT_IDLE }, { 0xe, 0xaa }, { 0xf, 0x00 },
679{ WAIT_IDLE }, { 0xe, 0xab }, { 0xf, 0x00 },
680{ WAIT_IDLE }, { 0xe, 0xac }, { 0xf, 0x00 },
681{ WAIT_IDLE }, { 0xe, 0xad }, { 0xf, 0x00 },
682{ WAIT_IDLE }, { 0xe, 0xae }, { 0xf, 0x00 },
683{ WAIT_IDLE }, { 0xe, 0xaf }, { 0xf, 0x00 },
684{ WAIT_IDLE }, { 0xe, 0xb0 }, { 0xf, 0x00 },
685{ WAIT_IDLE }, { 0xe, 0xb1 }, { 0xf, 0x00 },
686{ WAIT_IDLE }, { 0xe, 0xb2 }, { 0xf, 0x00 },
687{ WAIT_IDLE }, { 0xe, 0xb3 }, { 0xf, 0x00 },
688{ WAIT_IDLE }, { 0xe, 0xb4 }, { 0xf, 0x00 },
689{ WAIT_IDLE }, { 0xe, 0xb5 }, { 0xf, 0x00 },
690{ WAIT_IDLE }, { 0xe, 0xb6 }, { 0xf, 0x00 },
691{ WAIT_IDLE }, { 0xe, 0xb7 }, { 0xf, 0x00 },
692{ WAIT_IDLE }, { 0xe, 0xb8 }, { 0xf, 0x00 },
693{ WAIT_IDLE }, { 0xe, 0xb9 }, { 0xf, 0x00 },
694{ WAIT_IDLE }, { 0xe, 0xba }, { 0xf, 0x00 },
695{ WAIT_IDLE }, { 0xe, 0xbb }, { 0xf, 0x00 },
696{ WAIT_IDLE }, { 0xe, 0xbc }, { 0xf, 0x00 },
697{ WAIT_IDLE }, { 0xe, 0xbd }, { 0xf, 0x00 },
698{ WAIT_IDLE }, { 0xe, 0xbe }, { 0xf, 0x00 },
699{ WAIT_IDLE }, { 0xe, 0xbf }, { 0xf, 0x00 },
700{ WAIT_IDLE }, { 0xe, 0xc0 }, { 0xf, 0x00 },
701{ WAIT_IDLE }, { 0xe, 0xc1 }, { 0xf, 0x00 },
702{ WAIT_IDLE }, { 0xe, 0xc2 }, { 0xf, 0x00 },
703{ WAIT_IDLE }, { 0xe, 0xc3 }, { 0xf, 0x00 },
704{ WAIT_IDLE }, { 0xe, 0xc4 }, { 0xf, 0x00 },
705{ WAIT_IDLE }, { 0xe, 0xc5 }, { 0xf, 0x00 },
706{ WAIT_IDLE }, { 0xe, 0xc6 }, { 0xf, 0x00 },
707{ WAIT_IDLE }, { 0xe, 0xc7 }, { 0xf, 0x00 },
708{ WAIT_IDLE }, { 0xe, 0xc8 }, { 0xf, 0x00 },
709{ WAIT_IDLE }, { 0xe, 0xc9 }, { 0xf, 0x00 },
710{ WAIT_IDLE }, { 0xe, 0xca }, { 0xf, 0x00 },
711{ WAIT_IDLE }, { 0xe, 0xcb }, { 0xf, 0x00 },
712{ WAIT_IDLE }, { 0xe, 0xcc }, { 0xf, 0x00 },
713{ WAIT_IDLE }, { 0xe, 0xcd }, { 0xf, 0x00 },
714{ WAIT_IDLE }, { 0xe, 0xce }, { 0xf, 0x00 },
715{ WAIT_IDLE }, { 0xe, 0xcf }, { 0xf, 0x00 },
716{ WAIT_IDLE }, { 0xe, 0xd0 }, { 0xf, 0x00 },
717{ WAIT_IDLE }, { 0xe, 0xd1 }, { 0xf, 0x00 },
718{ WAIT_IDLE }, { 0xe, 0xd2 }, { 0xf, 0x00 },
719{ WAIT_IDLE }, { 0xe, 0xd3 }, { 0xf, 0x00 },
720{ WAIT_IDLE }, { 0xe, 0xd4 }, { 0xf, 0x00 },
721{ WAIT_IDLE }, { 0xe, 0xd5 }, { 0xf, 0x00 },
722{ WAIT_IDLE }, { 0xe, 0xd6 }, { 0xf, 0x00 },
723{ WAIT_IDLE }, { 0xe, 0xd7 }, { 0xf, 0x00 },
724{ WAIT_IDLE }, { 0xe, 0xd8 }, { 0xf, 0x00 },
725{ WAIT_IDLE }, { 0xe, 0xd9 }, { 0xf, 0x00 },
726{ WAIT_IDLE }, { 0xe, 0xda }, { 0xf, 0x00 },
727{ WAIT_IDLE }, { 0xe, 0xdb }, { 0xf, 0x00 },
728{ WAIT_IDLE }, { 0xe, 0xdc }, { 0xf, 0x00 },
729{ WAIT_IDLE }, { 0xe, 0xdd }, { 0xf, 0x00 },
730{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x00 },
731{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x00 },
732{ WAIT_IDLE }, { 0xe, 0xe0 }, { 0xf, 0x00 },
733{ WAIT_IDLE }, { 0xe, 0xe1 }, { 0xf, 0x00 },
734{ WAIT_IDLE }, { 0xe, 0xe2 }, { 0xf, 0x00 },
735{ WAIT_IDLE }, { 0xe, 0xe3 }, { 0xf, 0x00 },
736{ WAIT_IDLE }, { 0xe, 0xe4 }, { 0xf, 0x00 },
737{ WAIT_IDLE }, { 0xe, 0xe5 }, { 0xf, 0x00 },
738{ WAIT_IDLE }, { 0xe, 0xe6 }, { 0xf, 0x00 },
739{ WAIT_IDLE }, { 0xe, 0xe7 }, { 0xf, 0x00 },
740{ WAIT_IDLE }, { 0xe, 0xe8 }, { 0xf, 0x00 },
741{ WAIT_IDLE }, { 0xe, 0xe9 }, { 0xf, 0x00 },
742{ WAIT_IDLE }, { 0xe, 0xea }, { 0xf, 0x00 },
743{ WAIT_IDLE }, { 0xe, 0xeb }, { 0xf, 0x00 },
744{ WAIT_IDLE }, { 0xe, 0xec }, { 0xf, 0x00 },
745{ WAIT_IDLE }, { 0xe, 0xed }, { 0xf, 0x00 },
746{ WAIT_IDLE }, { 0xe, 0xee }, { 0xf, 0x00 },
747{ WAIT_IDLE }, { 0xe, 0xef }, { 0xf, 0x00 },
748{ WAIT_IDLE }, { 0xe, 0xf0 }, { 0xf, 0x00 },
749{ WAIT_IDLE }, { 0xe, 0xf1 }, { 0xf, 0x00 },
750{ WAIT_IDLE }, { 0xe, 0xf2 }, { 0xf, 0x00 },
751{ WAIT_IDLE }, { 0xe, 0xf3 }, { 0xf, 0x00 },
752{ WAIT_IDLE }, { 0xe, 0xf4 }, { 0xf, 0x00 },
753{ WAIT_IDLE }, { 0xe, 0xf5 }, { 0xf, 0x00 },
754{ WAIT_IDLE }, { 0xe, 0xf6 }, { 0xf, 0x00 },
755{ WAIT_IDLE }, { 0xe, 0xf7 }, { 0xf, 0x00 },
756{ WAIT_IDLE }, { 0xe, 0xf8 }, { 0xf, 0x00 },
757{ WAIT_IDLE }, { 0xe, 0xf9 }, { 0xf, 0x00 },
758{ WAIT_IDLE }, { 0xe, 0xfa }, { 0xf, 0x00 },
759{ WAIT_IDLE }, { 0xe, 0xfb }, { 0xf, 0x00 },
760{ WAIT_IDLE }, { 0xe, 0xfc }, { 0xf, 0x00 },
761{ WAIT_IDLE }, { 0xe, 0xfd }, { 0xf, 0x00 },
762{ WAIT_IDLE }, { 0xe, 0xfe }, { 0xf, 0x00 },
763{ WAIT_IDLE }, { 0xe, 0xff }, { 0xf, 0x00 },
764
765/* load page zero */
766{ 0x9, 0x05 }, { 0xb, 0x00 }, { 0xa, 0x00 },
767
768{ 0xd, 0x01 }, { 0xc, 0x7c }, { WAIT_IDLE },
769{ 0xd, 0x00 }, { 0xc, 0x1e }, { WAIT_IDLE },
770{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
771{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
772{ 0xd, 0x00 }, { 0xc, 0xf5 }, { WAIT_IDLE },
773{ 0xd, 0x00 }, { 0xc, 0x11 }, { WAIT_IDLE },
774{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
775{ 0xd, 0x00 }, { 0xc, 0x32 }, { WAIT_IDLE },
776{ 0xd, 0x00 }, { 0xc, 0x40 }, { WAIT_IDLE },
777{ 0xd, 0x00 }, { 0xc, 0x13 }, { WAIT_IDLE },
778{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
779{ 0xd, 0x00 }, { 0xc, 0x14 }, { WAIT_IDLE },
780{ 0xd, 0x02 }, { 0xc, 0x76 }, { WAIT_IDLE },
781{ 0xd, 0x00 }, { 0xc, 0x60 }, { WAIT_IDLE },
782{ 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
783{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
784{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
785{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
786{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
787{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
788{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
789{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
790{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
791{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
792{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
793{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
794{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
795{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
796{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
797{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
798{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
799{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
800{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
801{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
802{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
803{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
804{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
805{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
806{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
807{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
808{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
809{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
810{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
811{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
812{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
813{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
814{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
815{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
816{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
817{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
818{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
819{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
820{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
821{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
822{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
823{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
824{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
825{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
826{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
827{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
828{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
829{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
830{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
831{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
832{ 0xd, 0x00 }, { 0xc, 0x18 }, { WAIT_IDLE },
833{ 0xd, 0x00 }, { 0xc, 0x19 }, { WAIT_IDLE },
834{ 0xd, 0x01 }, { 0xc, 0x1a }, { WAIT_IDLE },
835{ 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE },
836{ 0xd, 0x01 }, { 0xc, 0x40 }, { WAIT_IDLE },
837{ 0xd, 0x01 }, { 0xc, 0x17 }, { WAIT_IDLE },
838{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
839{ 0xd, 0x01 }, { 0xc, 0x80 }, { WAIT_IDLE },
840{ 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE },
841{ 0xd, 0x00 }, { 0xc, 0x10 }, { WAIT_IDLE },
842{ 0xd, 0x01 }, { 0xc, 0xa0 }, { WAIT_IDLE },
843{ 0xd, 0x03 }, { 0xc, 0xd1 }, { WAIT_IDLE },
844{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
845{ 0xd, 0x01 }, { 0xc, 0xf2 }, { WAIT_IDLE },
846{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
847{ 0xd, 0x00 }, { 0xc, 0x13 }, { WAIT_IDLE },
848{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
849{ 0xd, 0x00 }, { 0xc, 0xf4 }, { WAIT_IDLE },
850{ 0xd, 0x02 }, { 0xc, 0xe0 }, { WAIT_IDLE },
851{ 0xd, 0x00 }, { 0xc, 0x15 }, { WAIT_IDLE },
852{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
853{ 0xd, 0x00 }, { 0xc, 0x16 }, { WAIT_IDLE },
854{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
855{ 0xd, 0x00 }, { 0xc, 0x17 }, { WAIT_IDLE },
856{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
857{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
858{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
859{ 0xd, 0x00 }, { 0xc, 0x50 }, { WAIT_IDLE },
860{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
861{ 0xd, 0x00 }, { 0xc, 0x40 }, { WAIT_IDLE },
862{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
863{ 0xd, 0x00 }, { 0xc, 0x71 }, { WAIT_IDLE },
864{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
865{ 0xd, 0x00 }, { 0xc, 0x60 }, { WAIT_IDLE },
866{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
867{ 0xd, 0x00 }, { 0xc, 0x92 }, { WAIT_IDLE },
868{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
869{ 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
870{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
871{ 0xd, 0x00 }, { 0xc, 0xb3 }, { WAIT_IDLE },
872{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
873{ 0xd, 0x00 }, { 0xc, 0xa0 }, { WAIT_IDLE },
874{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
875{ 0xd, 0x00 }, { 0xc, 0xd4 }, { WAIT_IDLE },
876{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
877{ 0xd, 0x00 }, { 0xc, 0x40 }, { WAIT_IDLE },
878{ 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
879{ 0xd, 0x00 }, { 0xc, 0xf5 }, { WAIT_IDLE },
880{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
881{ 0xd, 0x00 }, { 0xc, 0x70 }, { WAIT_IDLE },
882{ 0xd, 0x00 }, { 0xc, 0xa0 }, { WAIT_IDLE },
883{ 0xd, 0x02 }, { 0xc, 0x11 }, { WAIT_IDLE },
884{ 0xd, 0x00 }, { 0xc, 0x16 }, { WAIT_IDLE },
885{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
886{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
887{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
888{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
889{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
890{ 0xd, 0x00 }, { 0xc, 0x20 }, { WAIT_IDLE },
891{ 0xd, 0x00 }, { 0xc, 0x10 }, { WAIT_IDLE },
892{ 0xd, 0x00 }, { 0xc, 0x17 }, { WAIT_IDLE },
893{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE },
894{ 0xd, 0x00 }, { 0xc, 0x1d }, { WAIT_IDLE },
895{ 0xd, 0x02 }, { 0xc, 0xdf }, { WAIT_IDLE },
896
897/* Now load page one */
898{ 0x9, 0x05 }, { 0xb, 0x01 }, { 0xa, 0x00 },
899
900{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
901{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
902{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
903{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
904{ 0xd, 0x00 }, { 0xc, 0x19 }, { WAIT_IDLE },
905{ 0xd, 0x00 }, { 0xc, 0x1f }, { WAIT_IDLE },
906{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
907{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
908{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
909{ 0xd, 0x03 }, { 0xc, 0xd8 }, { WAIT_IDLE },
910{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
911{ 0xd, 0x02 }, { 0xc, 0x20 }, { WAIT_IDLE },
912{ 0xd, 0x00 }, { 0xc, 0x19 }, { WAIT_IDLE },
913{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
914{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
915{ 0xd, 0x00 }, { 0xc, 0x18 }, { WAIT_IDLE },
916{ 0xd, 0x01 }, { 0xc, 0xc0 }, { WAIT_IDLE },
917{ 0xd, 0x01 }, { 0xc, 0xfa }, { WAIT_IDLE },
918{ 0xd, 0x00 }, { 0xc, 0x1a }, { WAIT_IDLE },
919{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
920{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
921{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
922{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
923{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
924{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
925{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
926{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
927{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
928{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
929{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
930{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
931{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
932{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
933{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
934{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
935{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
936{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
937{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
938{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
939{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
940{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
941{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
942{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
943{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
944{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
945{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
946{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
947{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
948{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
949{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
950{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
951{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
952{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
953{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
954{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
955{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
956{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
957{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
958{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
959{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
960{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
961{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
962{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
963{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
964{ 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE },
965{ 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE },
966{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
967{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
968{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
969{ 0xd, 0x02 }, { 0xc, 0xc0 }, { WAIT_IDLE },
970{ 0xd, 0x02 }, { 0xc, 0x80 }, { WAIT_IDLE },
971{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
972{ 0xd, 0x02 }, { 0xc, 0xfb }, { WAIT_IDLE },
973{ 0xd, 0x02 }, { 0xc, 0xa0 }, { WAIT_IDLE },
974{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
975{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE },
976{ 0xd, 0x02 }, { 0xc, 0xd7 }, { WAIT_IDLE },
977{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
978{ 0xd, 0x02 }, { 0xc, 0xf7 }, { WAIT_IDLE },
979{ 0xd, 0x03 }, { 0xc, 0x20 }, { WAIT_IDLE },
980{ 0xd, 0x03 }, { 0xc, 0x00 }, { WAIT_IDLE },
981{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
982{ 0xd, 0x00 }, { 0xc, 0x1c }, { WAIT_IDLE },
983{ 0xd, 0x03 }, { 0xc, 0x3c }, { WAIT_IDLE },
984{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
985{ 0xd, 0x03 }, { 0xc, 0x3f }, { WAIT_IDLE },
986{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
987{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
988{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
989{ 0xd, 0x03 }, { 0xc, 0xdf }, { WAIT_IDLE },
990{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
991{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
992{ 0xd, 0x03 }, { 0xc, 0x5d }, { WAIT_IDLE },
993{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
994{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
995{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
996{ 0xd, 0x03 }, { 0xc, 0x7d }, { WAIT_IDLE },
997{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
998{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
999{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1000{ 0xd, 0x03 }, { 0xc, 0x9e }, { WAIT_IDLE },
1001{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1002{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
1003{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1004{ 0xd, 0x03 }, { 0xc, 0xbe }, { WAIT_IDLE },
1005{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1006{ 0xd, 0x03 }, { 0xc, 0xc0 }, { WAIT_IDLE },
1007{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1008{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1009{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1010{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1011{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE },
1012{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1013{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1014{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1015{ 0xd, 0x02 }, { 0xc, 0xdb }, { WAIT_IDLE },
1016{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1017{ 0xd, 0x02 }, { 0xc, 0xdb }, { WAIT_IDLE },
1018{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1019{ 0xd, 0x02 }, { 0xc, 0xe0 }, { WAIT_IDLE },
1020{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1021{ 0xd, 0x02 }, { 0xc, 0xfb }, { WAIT_IDLE },
1022{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1023{ 0xd, 0x02 }, { 0xc, 0xc0 }, { WAIT_IDLE },
1024{ 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE },
1025{ 0xd, 0x02 }, { 0xc, 0xfb }, { WAIT_IDLE },
1026{ 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE },
1027{ 0xd, 0x00 }, { 0xc, 0x1b }, { WAIT_IDLE },
1028
1029{ 0x9, 0x05 }, { 0xb, 0x02 }, { 0xa, 0x00 },
1030
1031{ 0xc, 0xc4 }, { WAIT_IDLE },
1032{ 0xc, 0x00 }, { WAIT_IDLE },
1033{ 0xc, 0x44 }, { WAIT_IDLE },
1034{ 0xc, 0x07 }, { WAIT_IDLE },
1035{ 0xc, 0x44 }, { WAIT_IDLE },
1036{ 0xc, 0x00 }, { WAIT_IDLE },
1037{ 0xc, 0x40 }, { WAIT_IDLE },
1038{ 0xc, 0x25 }, { WAIT_IDLE },
1039{ 0xc, 0x01 }, { WAIT_IDLE },
1040{ 0xc, 0x06 }, { WAIT_IDLE },
1041{ 0xc, 0xc4 }, { WAIT_IDLE },
1042{ 0xc, 0x07 }, { WAIT_IDLE },
1043{ 0xc, 0x40 }, { WAIT_IDLE },
1044{ 0xc, 0x25 }, { WAIT_IDLE },
1045{ 0xc, 0x01 }, { WAIT_IDLE },
1046{ 0xc, 0x00 }, { WAIT_IDLE },
1047{ 0xc, 0x46 }, { WAIT_IDLE },
1048{ 0xc, 0x46 }, { WAIT_IDLE },
1049{ 0xc, 0x00 }, { WAIT_IDLE },
1050{ 0xc, 0x00 }, { WAIT_IDLE },
1051{ 0xc, 0x00 }, { WAIT_IDLE },
1052{ 0xc, 0x00 }, { WAIT_IDLE },
1053{ 0xc, 0x00 }, { WAIT_IDLE },
1054{ 0xc, 0x00 }, { WAIT_IDLE },
1055{ 0xc, 0x00 }, { WAIT_IDLE },
1056{ 0xc, 0x00 }, { WAIT_IDLE },
1057{ 0xc, 0x00 }, { WAIT_IDLE },
1058{ 0xc, 0x00 }, { WAIT_IDLE },
1059{ 0xc, 0x00 }, { WAIT_IDLE },
1060{ 0xc, 0x00 }, { WAIT_IDLE },
1061{ 0xc, 0x00 }, { WAIT_IDLE },
1062{ 0xc, 0x00 }, { WAIT_IDLE },
1063{ 0xc, 0x00 }, { WAIT_IDLE },
1064{ 0xc, 0x00 }, { WAIT_IDLE },
1065{ 0xc, 0x00 }, { WAIT_IDLE },
1066{ 0xc, 0x00 }, { WAIT_IDLE },
1067{ 0xc, 0x00 }, { WAIT_IDLE },
1068{ 0xc, 0x00 }, { WAIT_IDLE },
1069{ 0xc, 0x00 }, { WAIT_IDLE },
1070{ 0xc, 0x00 }, { WAIT_IDLE },
1071{ 0xc, 0x00 }, { WAIT_IDLE },
1072{ 0xc, 0x00 }, { WAIT_IDLE },
1073{ 0xc, 0x00 }, { WAIT_IDLE },
1074{ 0xc, 0x00 }, { WAIT_IDLE },
1075{ 0xc, 0x00 }, { WAIT_IDLE },
1076{ 0xc, 0x00 }, { WAIT_IDLE },
1077{ 0xc, 0x00 }, { WAIT_IDLE },
1078{ 0xc, 0x00 }, { WAIT_IDLE },
1079{ 0xc, 0x00 }, { WAIT_IDLE },
1080{ 0xc, 0x00 }, { WAIT_IDLE },
1081{ 0xc, 0x00 }, { WAIT_IDLE },
1082{ 0xc, 0x00 }, { WAIT_IDLE },
1083{ 0xc, 0x00 }, { WAIT_IDLE },
1084{ 0xc, 0x00 }, { WAIT_IDLE },
1085{ 0xc, 0x00 }, { WAIT_IDLE },
1086{ 0xc, 0x00 }, { WAIT_IDLE },
1087{ 0xc, 0x00 }, { WAIT_IDLE },
1088{ 0xc, 0x00 }, { WAIT_IDLE },
1089{ 0xc, 0x00 }, { WAIT_IDLE },
1090{ 0xc, 0x00 }, { WAIT_IDLE },
1091{ 0xc, 0x00 }, { WAIT_IDLE },
1092{ 0xc, 0x00 }, { WAIT_IDLE },
1093{ 0xc, 0x00 }, { WAIT_IDLE },
1094{ 0xc, 0x00 }, { WAIT_IDLE },
1095{ 0xc, 0x46 }, { WAIT_IDLE },
1096{ 0xc, 0x07 }, { WAIT_IDLE },
1097{ 0xc, 0x05 }, { WAIT_IDLE },
1098{ 0xc, 0x05 }, { WAIT_IDLE },
1099{ 0xc, 0x05 }, { WAIT_IDLE },
1100{ 0xc, 0x04 }, { WAIT_IDLE },
1101{ 0xc, 0x07 }, { WAIT_IDLE },
1102{ 0xc, 0x05 }, { WAIT_IDLE },
1103{ 0xc, 0x04 }, { WAIT_IDLE },
1104{ 0xc, 0x07 }, { WAIT_IDLE },
1105{ 0xc, 0x05 }, { WAIT_IDLE },
1106{ 0xc, 0x44 }, { WAIT_IDLE },
1107{ 0xc, 0x46 }, { WAIT_IDLE },
1108{ 0xc, 0x44 }, { WAIT_IDLE },
1109{ 0xc, 0x46 }, { WAIT_IDLE },
1110{ 0xc, 0x46 }, { WAIT_IDLE },
1111{ 0xc, 0x07 }, { WAIT_IDLE },
1112{ 0xc, 0x05 }, { WAIT_IDLE },
1113{ 0xc, 0x44 }, { WAIT_IDLE },
1114{ 0xc, 0x46 }, { WAIT_IDLE },
1115{ 0xc, 0x05 }, { WAIT_IDLE },
1116{ 0xc, 0x46 }, { WAIT_IDLE },
1117{ 0xc, 0x05 }, { WAIT_IDLE },
1118{ 0xc, 0x46 }, { WAIT_IDLE },
1119{ 0xc, 0x05 }, { WAIT_IDLE },
1120{ 0xc, 0x46 }, { WAIT_IDLE },
1121{ 0xc, 0x05 }, { WAIT_IDLE },
1122{ 0xc, 0x44 }, { WAIT_IDLE },
1123{ 0xc, 0x46 }, { WAIT_IDLE },
1124{ 0xc, 0x05 }, { WAIT_IDLE },
1125{ 0xc, 0x07 }, { WAIT_IDLE },
1126{ 0xc, 0x44 }, { WAIT_IDLE },
1127{ 0xc, 0x46 }, { WAIT_IDLE },
1128{ 0xc, 0x05 }, { WAIT_IDLE },
1129{ 0xc, 0x07 }, { WAIT_IDLE },
1130{ 0xc, 0x44 }, { WAIT_IDLE },
1131{ 0xc, 0x46 }, { WAIT_IDLE },
1132{ 0xc, 0x05 }, { WAIT_IDLE },
1133{ 0xc, 0x07 }, { WAIT_IDLE },
1134{ 0xc, 0x44 }, { WAIT_IDLE },
1135{ 0xc, 0x46 }, { WAIT_IDLE },
1136{ 0xc, 0x05 }, { WAIT_IDLE },
1137{ 0xc, 0x07 }, { WAIT_IDLE },
1138{ 0xc, 0x44 }, { WAIT_IDLE },
1139{ 0xc, 0x05 }, { WAIT_IDLE },
1140{ 0xc, 0x05 }, { WAIT_IDLE },
1141{ 0xc, 0x05 }, { WAIT_IDLE },
1142{ 0xc, 0x44 }, { WAIT_IDLE },
1143{ 0xc, 0x05 }, { WAIT_IDLE },
1144{ 0xc, 0x05 }, { WAIT_IDLE },
1145{ 0xc, 0x05 }, { WAIT_IDLE },
1146{ 0xc, 0x46 }, { WAIT_IDLE },
1147{ 0xc, 0x05 }, { WAIT_IDLE },
1148{ 0xc, 0x46 }, { WAIT_IDLE },
1149{ 0xc, 0x05 }, { WAIT_IDLE },
1150{ 0xc, 0x46 }, { WAIT_IDLE },
1151{ 0xc, 0x05 }, { WAIT_IDLE },
1152{ 0xc, 0x46 }, { WAIT_IDLE },
1153{ 0xc, 0x05 }, { WAIT_IDLE },
1154{ 0xc, 0x46 }, { WAIT_IDLE },
1155{ 0xc, 0x07 }, { WAIT_IDLE },
1156{ 0xc, 0x46 }, { WAIT_IDLE },
1157{ 0xc, 0x07 }, { WAIT_IDLE },
1158{ 0xc, 0x44 }, { WAIT_IDLE },
1159
1160{ 0x9, 0x05 }, { 0xb, 0x03 }, { 0xa, 0x00 },
1161
1162{ 0xc, 0x07 }, { WAIT_IDLE },
1163{ 0xc, 0x40 }, { WAIT_IDLE },
1164{ 0xc, 0x00 }, { WAIT_IDLE },
1165{ 0xc, 0x00 }, { WAIT_IDLE },
1166{ 0xc, 0x00 }, { WAIT_IDLE },
1167{ 0xc, 0x47 }, { WAIT_IDLE },
1168{ 0xc, 0x00 }, { WAIT_IDLE },
1169{ 0xc, 0x40 }, { WAIT_IDLE },
1170{ 0xc, 0x00 }, { WAIT_IDLE },
1171{ 0xc, 0x40 }, { WAIT_IDLE },
1172{ 0xc, 0x06 }, { WAIT_IDLE },
1173{ 0xc, 0x40 }, { WAIT_IDLE },
1174{ 0xc, 0x00 }, { WAIT_IDLE },
1175{ 0xc, 0x00 }, { WAIT_IDLE },
1176{ 0xc, 0x00 }, { WAIT_IDLE },
1177{ 0xc, 0x00 }, { WAIT_IDLE },
1178{ 0xc, 0x00 }, { WAIT_IDLE },
1179{ 0xc, 0x00 }, { WAIT_IDLE },
1180{ 0xc, 0x00 }, { WAIT_IDLE },
1181{ 0xc, 0x00 }, { WAIT_IDLE },
1182{ 0xc, 0x00 }, { WAIT_IDLE },
1183{ 0xc, 0x00 }, { WAIT_IDLE },
1184{ 0xc, 0x00 }, { WAIT_IDLE },
1185{ 0xc, 0x00 }, { WAIT_IDLE },
1186{ 0xc, 0x00 }, { WAIT_IDLE },
1187{ 0xc, 0x00 }, { WAIT_IDLE },
1188{ 0xc, 0x00 }, { WAIT_IDLE },
1189{ 0xc, 0x00 }, { WAIT_IDLE },
1190{ 0xc, 0x00 }, { WAIT_IDLE },
1191{ 0xc, 0x00 }, { WAIT_IDLE },
1192{ 0xc, 0x00 }, { WAIT_IDLE },
1193{ 0xc, 0x00 }, { WAIT_IDLE },
1194{ 0xc, 0x00 }, { WAIT_IDLE },
1195{ 0xc, 0x00 }, { WAIT_IDLE },
1196{ 0xc, 0x00 }, { WAIT_IDLE },
1197{ 0xc, 0x00 }, { WAIT_IDLE },
1198{ 0xc, 0x00 }, { WAIT_IDLE },
1199{ 0xc, 0x00 }, { WAIT_IDLE },
1200{ 0xc, 0x00 }, { WAIT_IDLE },
1201{ 0xc, 0x00 }, { WAIT_IDLE },
1202{ 0xc, 0x00 }, { WAIT_IDLE },
1203{ 0xc, 0x00 }, { WAIT_IDLE },
1204{ 0xc, 0x00 }, { WAIT_IDLE },
1205{ 0xc, 0x00 }, { WAIT_IDLE },
1206{ 0xc, 0x00 }, { WAIT_IDLE },
1207{ 0xc, 0x00 }, { WAIT_IDLE },
1208{ 0xc, 0x00 }, { WAIT_IDLE },
1209{ 0xc, 0x00 }, { WAIT_IDLE },
1210{ 0xc, 0x00 }, { WAIT_IDLE },
1211{ 0xc, 0x00 }, { WAIT_IDLE },
1212{ 0xc, 0x00 }, { WAIT_IDLE },
1213{ 0xc, 0x00 }, { WAIT_IDLE },
1214{ 0xc, 0x00 }, { WAIT_IDLE },
1215{ 0xc, 0x00 }, { WAIT_IDLE },
1216{ 0xc, 0x00 }, { WAIT_IDLE },
1217{ 0xc, 0x00 }, { WAIT_IDLE },
1218{ 0xc, 0x00 }, { WAIT_IDLE },
1219{ 0xc, 0x00 }, { WAIT_IDLE },
1220{ 0xc, 0x00 }, { WAIT_IDLE },
1221{ 0xc, 0x00 }, { WAIT_IDLE },
1222{ 0xc, 0x00 }, { WAIT_IDLE },
1223{ 0xc, 0x00 }, { WAIT_IDLE },
1224{ 0xc, 0x00 }, { WAIT_IDLE },
1225{ 0xc, 0x00 }, { WAIT_IDLE },
1226{ 0xc, 0x80 }, { WAIT_IDLE },
1227{ 0xc, 0x80 }, { WAIT_IDLE },
1228{ 0xc, 0xc0 }, { WAIT_IDLE },
1229{ 0xc, 0x00 }, { WAIT_IDLE },
1230{ 0xc, 0x00 }, { WAIT_IDLE },
1231{ 0xc, 0x40 }, { WAIT_IDLE },
1232{ 0xc, 0x00 }, { WAIT_IDLE },
1233{ 0xc, 0x00 }, { WAIT_IDLE },
1234{ 0xc, 0x00 }, { WAIT_IDLE },
1235{ 0xc, 0x40 }, { WAIT_IDLE },
1236{ 0xc, 0x00 }, { WAIT_IDLE },
1237{ 0xc, 0x40 }, { WAIT_IDLE },
1238{ 0xc, 0x00 }, { WAIT_IDLE },
1239{ 0xc, 0x60 }, { WAIT_IDLE },
1240{ 0xc, 0x00 }, { WAIT_IDLE },
1241{ 0xc, 0x70 }, { WAIT_IDLE },
1242{ 0xc, 0x00 }, { WAIT_IDLE },
1243{ 0xc, 0x40 }, { WAIT_IDLE },
1244{ 0xc, 0x00 }, { WAIT_IDLE },
1245{ 0xc, 0x40 }, { WAIT_IDLE },
1246{ 0xc, 0x00 }, { WAIT_IDLE },
1247{ 0xc, 0x42 }, { WAIT_IDLE },
1248{ 0xc, 0x00 }, { WAIT_IDLE },
1249{ 0xc, 0x40 }, { WAIT_IDLE },
1250{ 0xc, 0x00 }, { WAIT_IDLE },
1251{ 0xc, 0x02 }, { WAIT_IDLE },
1252{ 0xc, 0x00 }, { WAIT_IDLE },
1253{ 0xc, 0x40 }, { WAIT_IDLE },
1254{ 0xc, 0x00 }, { WAIT_IDLE },
1255{ 0xc, 0x00 }, { WAIT_IDLE },
1256{ 0xc, 0x00 }, { WAIT_IDLE },
1257{ 0xc, 0x40 }, { WAIT_IDLE },
1258{ 0xc, 0x00 }, { WAIT_IDLE },
1259{ 0xc, 0x00 }, { WAIT_IDLE },
1260{ 0xc, 0x00 }, { WAIT_IDLE },
1261{ 0xc, 0x40 }, { WAIT_IDLE },
1262{ 0xc, 0x00 }, { WAIT_IDLE },
1263{ 0xc, 0x00 }, { WAIT_IDLE },
1264{ 0xc, 0x00 }, { WAIT_IDLE },
1265{ 0xc, 0x40 }, { WAIT_IDLE },
1266{ 0xc, 0x00 }, { WAIT_IDLE },
1267{ 0xc, 0x00 }, { WAIT_IDLE },
1268{ 0xc, 0x00 }, { WAIT_IDLE },
1269{ 0xc, 0x40 }, { WAIT_IDLE },
1270{ 0xc, 0x00 }, { WAIT_IDLE },
1271{ 0xc, 0x00 }, { WAIT_IDLE },
1272{ 0xc, 0x00 }, { WAIT_IDLE },
1273{ 0xc, 0x42 }, { WAIT_IDLE },
1274{ 0xc, 0x00 }, { WAIT_IDLE },
1275{ 0xc, 0x40 }, { WAIT_IDLE },
1276{ 0xc, 0x00 }, { WAIT_IDLE },
1277{ 0xc, 0x42 }, { WAIT_IDLE },
1278{ 0xc, 0x00 }, { WAIT_IDLE },
1279{ 0xc, 0x02 }, { WAIT_IDLE },
1280{ 0xc, 0x00 }, { WAIT_IDLE },
1281{ 0xc, 0x02 }, { WAIT_IDLE },
1282{ 0xc, 0x00 }, { WAIT_IDLE },
1283{ 0xc, 0x02 }, { WAIT_IDLE },
1284{ 0xc, 0x00 }, { WAIT_IDLE },
1285{ 0xc, 0x42 }, { WAIT_IDLE },
1286{ 0xc, 0x00 }, { WAIT_IDLE },
1287{ 0xc, 0xc0 }, { WAIT_IDLE },
1288{ 0xc, 0x00 }, { WAIT_IDLE },
1289{ 0xc, 0x40 }, { WAIT_IDLE },
1290
1291{ 0x9, 0x05 }, { 0xb, 0x04 }, { 0xa, 0x00 },
1292
1293{ 0xc, 0x63 }, { WAIT_IDLE },
1294{ 0xc, 0x03 }, { WAIT_IDLE },
1295{ 0xc, 0x26 }, { WAIT_IDLE },
1296{ 0xc, 0x02 }, { WAIT_IDLE },
1297{ 0xc, 0x2c }, { WAIT_IDLE },
1298{ 0xc, 0x00 }, { WAIT_IDLE },
1299{ 0xc, 0x24 }, { WAIT_IDLE },
1300{ 0xc, 0x00 }, { WAIT_IDLE },
1301{ 0xc, 0x2e }, { WAIT_IDLE },
1302{ 0xc, 0x02 }, { WAIT_IDLE },
1303{ 0xc, 0x02 }, { WAIT_IDLE },
1304{ 0xc, 0x02 }, { WAIT_IDLE },
1305{ 0xc, 0x00 }, { WAIT_IDLE },
1306{ 0xc, 0x00 }, { WAIT_IDLE },
1307{ 0xc, 0x00 }, { WAIT_IDLE },
1308{ 0xc, 0x00 }, { WAIT_IDLE },
1309{ 0xc, 0x00 }, { WAIT_IDLE },
1310{ 0xc, 0x00 }, { WAIT_IDLE },
1311{ 0xc, 0x00 }, { WAIT_IDLE },
1312{ 0xc, 0x00 }, { WAIT_IDLE },
1313{ 0xc, 0x00 }, { WAIT_IDLE },
1314{ 0xc, 0x00 }, { WAIT_IDLE },
1315{ 0xc, 0x00 }, { WAIT_IDLE },
1316{ 0xc, 0x00 }, { WAIT_IDLE },
1317{ 0xc, 0x00 }, { WAIT_IDLE },
1318{ 0xc, 0x00 }, { WAIT_IDLE },
1319{ 0xc, 0x00 }, { WAIT_IDLE },
1320{ 0xc, 0x00 }, { WAIT_IDLE },
1321{ 0xc, 0x00 }, { WAIT_IDLE },
1322{ 0xc, 0x00 }, { WAIT_IDLE },
1323{ 0xc, 0x00 }, { WAIT_IDLE },
1324{ 0xc, 0x00 }, { WAIT_IDLE },
1325{ 0xc, 0x00 }, { WAIT_IDLE },
1326{ 0xc, 0x00 }, { WAIT_IDLE },
1327{ 0xc, 0x00 }, { WAIT_IDLE },
1328{ 0xc, 0x00 }, { WAIT_IDLE },
1329{ 0xc, 0x00 }, { WAIT_IDLE },
1330{ 0xc, 0x00 }, { WAIT_IDLE },
1331{ 0xc, 0x00 }, { WAIT_IDLE },
1332{ 0xc, 0x00 }, { WAIT_IDLE },
1333{ 0xc, 0x00 }, { WAIT_IDLE },
1334{ 0xc, 0x00 }, { WAIT_IDLE },
1335{ 0xc, 0x00 }, { WAIT_IDLE },
1336{ 0xc, 0x00 }, { WAIT_IDLE },
1337{ 0xc, 0x00 }, { WAIT_IDLE },
1338{ 0xc, 0x00 }, { WAIT_IDLE },
1339{ 0xc, 0x00 }, { WAIT_IDLE },
1340{ 0xc, 0x00 }, { WAIT_IDLE },
1341{ 0xc, 0x00 }, { WAIT_IDLE },
1342{ 0xc, 0x00 }, { WAIT_IDLE },
1343{ 0xc, 0x00 }, { WAIT_IDLE },
1344{ 0xc, 0x00 }, { WAIT_IDLE },
1345{ 0xc, 0x00 }, { WAIT_IDLE },
1346{ 0xc, 0x00 }, { WAIT_IDLE },
1347{ 0xc, 0x00 }, { WAIT_IDLE },
1348{ 0xc, 0x00 }, { WAIT_IDLE },
1349{ 0xc, 0x00 }, { WAIT_IDLE },
1350{ 0xc, 0x00 }, { WAIT_IDLE },
1351{ 0xc, 0x00 }, { WAIT_IDLE },
1352{ 0xc, 0x00 }, { WAIT_IDLE },
1353{ 0xc, 0x00 }, { WAIT_IDLE },
1354{ 0xc, 0x00 }, { WAIT_IDLE },
1355{ 0xc, 0x00 }, { WAIT_IDLE },
1356{ 0xc, 0x00 }, { WAIT_IDLE },
1357{ 0xc, 0x00 }, { WAIT_IDLE },
1358{ 0xc, 0x01 }, { WAIT_IDLE },
1359{ 0xc, 0x20 }, { WAIT_IDLE },
1360{ 0xc, 0x00 }, { WAIT_IDLE },
1361{ 0xc, 0x60 }, { WAIT_IDLE },
1362{ 0xc, 0x00 }, { WAIT_IDLE },
1363{ 0xc, 0x20 }, { WAIT_IDLE },
1364{ 0xc, 0x00 }, { WAIT_IDLE },
1365{ 0xc, 0x20 }, { WAIT_IDLE },
1366{ 0xc, 0x00 }, { WAIT_IDLE },
1367{ 0xc, 0x20 }, { WAIT_IDLE },
1368{ 0xc, 0x00 }, { WAIT_IDLE },
1369{ 0xc, 0x20 }, { WAIT_IDLE },
1370{ 0xc, 0x00 }, { WAIT_IDLE },
1371{ 0xc, 0x20 }, { WAIT_IDLE },
1372{ 0xc, 0x00 }, { WAIT_IDLE },
1373{ 0xc, 0x20 }, { WAIT_IDLE },
1374{ 0xc, 0x00 }, { WAIT_IDLE },
1375{ 0xc, 0x20 }, { WAIT_IDLE },
1376{ 0xc, 0x00 }, { WAIT_IDLE },
1377{ 0xc, 0x20 }, { WAIT_IDLE },
1378{ 0xc, 0x00 }, { WAIT_IDLE },
1379{ 0xc, 0x60 }, { WAIT_IDLE },
1380{ 0xc, 0x00 }, { WAIT_IDLE },
1381{ 0xc, 0x20 }, { WAIT_IDLE },
1382{ 0xc, 0x00 }, { WAIT_IDLE },
1383{ 0xc, 0x60 }, { WAIT_IDLE },
1384{ 0xc, 0x00 }, { WAIT_IDLE },
1385{ 0xc, 0x20 }, { WAIT_IDLE },
1386{ 0xc, 0x00 }, { WAIT_IDLE },
1387{ 0xc, 0x60 }, { WAIT_IDLE },
1388{ 0xc, 0x00 }, { WAIT_IDLE },
1389{ 0xc, 0x20 }, { WAIT_IDLE },
1390{ 0xc, 0x00 }, { WAIT_IDLE },
1391{ 0xc, 0x60 }, { WAIT_IDLE },
1392{ 0xc, 0x00 }, { WAIT_IDLE },
1393{ 0xc, 0x20 }, { WAIT_IDLE },
1394{ 0xc, 0x00 }, { WAIT_IDLE },
1395{ 0xc, 0x60 }, { WAIT_IDLE },
1396{ 0xc, 0x00 }, { WAIT_IDLE },
1397{ 0xc, 0x20 }, { WAIT_IDLE },
1398{ 0xc, 0x00 }, { WAIT_IDLE },
1399{ 0xc, 0x60 }, { WAIT_IDLE },
1400{ 0xc, 0x00 }, { WAIT_IDLE },
1401{ 0xc, 0x20 }, { WAIT_IDLE },
1402{ 0xc, 0x00 }, { WAIT_IDLE },
1403{ 0xc, 0x20 }, { WAIT_IDLE },
1404{ 0xc, 0x00 }, { WAIT_IDLE },
1405{ 0xc, 0x22 }, { WAIT_IDLE },
1406{ 0xc, 0x02 }, { WAIT_IDLE },
1407{ 0xc, 0x22 }, { WAIT_IDLE },
1408{ 0xc, 0x02 }, { WAIT_IDLE },
1409{ 0xc, 0x20 }, { WAIT_IDLE },
1410{ 0xc, 0x00 }, { WAIT_IDLE },
1411{ 0xc, 0x60 }, { WAIT_IDLE },
1412{ 0xc, 0x00 }, { WAIT_IDLE },
1413{ 0xc, 0x22 }, { WAIT_IDLE },
1414{ 0xc, 0x02 }, { WAIT_IDLE },
1415{ 0xc, 0x62 }, { WAIT_IDLE },
1416{ 0xc, 0x02 }, { WAIT_IDLE },
1417{ 0xc, 0x20 }, { WAIT_IDLE },
1418{ 0xc, 0x01 }, { WAIT_IDLE },
1419{ 0xc, 0x21 }, { WAIT_IDLE },
1420{ 0xc, 0x01 }, { WAIT_IDLE },
1421
1422/* Load memory area (page six) */
1423{ 0x9, 0x01 }, { 0xb, 0x06 },
1424
1425{ 0xa, 0x00 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1426{ 0xa, 0x02 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1427{ 0xa, 0x04 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1428{ 0xa, 0x06 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1429{ 0xa, 0x08 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1430{ 0xa, 0x0a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1431{ 0xa, 0x0c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1432{ 0xa, 0x0e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1433{ 0xa, 0x10 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1434{ 0xa, 0x12 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1435{ 0xa, 0x14 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1436{ 0xa, 0x16 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1437{ 0xa, 0x18 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1438{ 0xa, 0x1a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1439{ 0xa, 0x1c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1440{ 0xa, 0x1e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1441{ 0xa, 0x20 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1442{ 0xa, 0x22 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1443{ 0xa, 0x24 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1444{ 0xa, 0x26 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1445{ 0xa, 0x28 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1446{ 0xa, 0x2a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1447{ 0xa, 0x2c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1448{ 0xa, 0x2e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1449{ 0xa, 0x30 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1450{ 0xa, 0x32 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1451{ 0xa, 0x34 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1452{ 0xa, 0x36 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1453{ 0xa, 0x38 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1454{ 0xa, 0x3a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1455{ 0xa, 0x3c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1456{ 0xa, 0x3e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1457{ 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1458{ 0xa, 0x42 }, { 0xd, 0x03 }, { 0xc, 0x00 }, { WAIT_IDLE },
1459{ 0xa, 0x44 }, { 0xd, 0x01 }, { 0xc, 0x00 }, { WAIT_IDLE },
1460{ 0xa, 0x46 }, { 0xd, 0x0a }, { 0xc, 0x21 }, { WAIT_IDLE },
1461{ 0xa, 0x48 }, { 0xd, 0x0d }, { 0xc, 0x23 }, { WAIT_IDLE },
1462{ 0xa, 0x4a }, { 0xd, 0x23 }, { 0xc, 0x1b }, { WAIT_IDLE },
1463{ 0xa, 0x4c }, { 0xd, 0x37 }, { 0xc, 0x8f }, { WAIT_IDLE },
1464{ 0xa, 0x4e }, { 0xd, 0x45 }, { 0xc, 0x77 }, { WAIT_IDLE },
1465{ 0xa, 0x50 }, { 0xd, 0x52 }, { 0xc, 0xe2 }, { WAIT_IDLE },
1466{ 0xa, 0x52 }, { 0xd, 0x1c }, { 0xc, 0x92 }, { WAIT_IDLE },
1467{ 0xa, 0x54 }, { 0xd, 0x1c }, { 0xc, 0x52 }, { WAIT_IDLE },
1468{ 0xa, 0x56 }, { 0xd, 0x07 }, { 0xc, 0x00 }, { WAIT_IDLE },
1469{ 0xa, 0x58 }, { 0xd, 0x2f }, { 0xc, 0xc6 }, { WAIT_IDLE },
1470{ 0xa, 0x5a }, { 0xd, 0x0b }, { 0xc, 0x00 }, { WAIT_IDLE },
1471{ 0xa, 0x5c }, { 0xd, 0x30 }, { 0xc, 0x06 }, { WAIT_IDLE },
1472{ 0xa, 0x5e }, { 0xd, 0x17 }, { 0xc, 0x00 }, { WAIT_IDLE },
1473{ 0xa, 0x60 }, { 0xd, 0x3d }, { 0xc, 0xda }, { WAIT_IDLE },
1474{ 0xa, 0x62 }, { 0xd, 0x29 }, { 0xc, 0x00 }, { WAIT_IDLE },
1475{ 0xa, 0x64 }, { 0xd, 0x3e }, { 0xc, 0x41 }, { WAIT_IDLE },
1476{ 0xa, 0x66 }, { 0xd, 0x39 }, { 0xc, 0x00 }, { WAIT_IDLE },
1477{ 0xa, 0x68 }, { 0xd, 0x4c }, { 0xc, 0x48 }, { WAIT_IDLE },
1478{ 0xa, 0x6a }, { 0xd, 0x49 }, { 0xc, 0x00 }, { WAIT_IDLE },
1479{ 0xa, 0x6c }, { 0xd, 0x4c }, { 0xc, 0x6c }, { WAIT_IDLE },
1480{ 0xa, 0x6e }, { 0xd, 0x11 }, { 0xc, 0xd2 }, { WAIT_IDLE },
1481{ 0xa, 0x70 }, { 0xd, 0x16 }, { 0xc, 0x0c }, { WAIT_IDLE },
1482{ 0xa, 0x72 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1483{ 0xa, 0x74 }, { 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
1484{ 0xa, 0x76 }, { 0xd, 0x0f }, { 0xc, 0x00 }, { WAIT_IDLE },
1485{ 0xa, 0x78 }, { 0xd, 0x00 }, { 0xc, 0x80 }, { WAIT_IDLE },
1486{ 0xa, 0x7a }, { 0xd, 0x13 }, { 0xc, 0x00 }, { WAIT_IDLE },
1487{ 0xa, 0x7c }, { 0xd, 0x80 }, { 0xc, 0x00 }, { WAIT_IDLE },
1488{ 0xa, 0x7e }, { 0xd, 0x80 }, { 0xc, 0x80 }, { WAIT_IDLE },
1489
1490{ 0x9, 0x05 }, { 0xb, 0x07 }, { 0xa, 0x00 },
1491
1492{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1493{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1494{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE },
1495{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE },
1496{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
1497{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1498{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1499{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1500{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1501{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1502{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE },
1503{ 0xd, 0x08 }, { 0xc, 0x00 }, { WAIT_IDLE },
1504{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1505{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1506{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1507{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1508{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1509{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1510{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1511{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1512{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1513{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1514{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1515{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1516{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1517{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1518{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1519{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1520{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1521{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1522{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1523{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1524{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1525{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1526{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1527{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1528{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1529{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1530{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1531{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1532{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1533{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1534{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1535{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1536{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1537{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1538{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1539{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1540{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1541{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1542{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1543{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1544{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1545{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1546{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1547{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1548{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1549{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1550{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1551{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1552{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1553{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1554{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1555{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1556{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1557{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1558{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1559{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1560{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1561{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1562{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1563{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1564{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1565{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1566{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1567{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1568{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1569{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1570{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1571{ 0xd, 0x02 }, { 0xc, 0xe9 }, { WAIT_IDLE },
1572{ 0xd, 0x06 }, { 0xc, 0x8c }, { WAIT_IDLE },
1573{ 0xd, 0x06 }, { 0xc, 0x8c }, { WAIT_IDLE },
1574{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1575{ 0xd, 0x1a }, { 0xc, 0x75 }, { WAIT_IDLE },
1576{ 0xd, 0x0d }, { 0xc, 0x8b }, { WAIT_IDLE },
1577{ 0xd, 0x04 }, { 0xc, 0xe9 }, { WAIT_IDLE },
1578{ 0xd, 0x0b }, { 0xc, 0x16 }, { WAIT_IDLE },
1579{ 0xd, 0x1a }, { 0xc, 0x38 }, { WAIT_IDLE },
1580{ 0xd, 0x0d }, { 0xc, 0xc8 }, { WAIT_IDLE },
1581{ 0xd, 0x04 }, { 0xc, 0x6f }, { WAIT_IDLE },
1582{ 0xd, 0x0b }, { 0xc, 0x91 }, { WAIT_IDLE },
1583{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1584{ 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE },
1585{ 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE },
1586{ 0xd, 0x02 }, { 0xc, 0x8f }, { WAIT_IDLE },
1587{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1588{ 0xd, 0x06 }, { 0xc, 0x62 }, { WAIT_IDLE },
1589{ 0xd, 0x06 }, { 0xc, 0x62 }, { WAIT_IDLE },
1590{ 0xd, 0x02 }, { 0xc, 0x7b }, { WAIT_IDLE },
1591{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1592{ 0xd, 0x06 }, { 0xc, 0x97 }, { WAIT_IDLE },
1593{ 0xd, 0x06 }, { 0xc, 0x97 }, { WAIT_IDLE },
1594{ 0xd, 0x02 }, { 0xc, 0x52 }, { WAIT_IDLE },
1595{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1596{ 0xd, 0x06 }, { 0xc, 0xf6 }, { WAIT_IDLE },
1597{ 0xd, 0x06 }, { 0xc, 0xf6 }, { WAIT_IDLE },
1598{ 0xd, 0x02 }, { 0xc, 0x19 }, { WAIT_IDLE },
1599{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
1600{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
1601{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
1602{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
1603{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
1604{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
1605{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
1606{ 0xd, 0x05 }, { 0xc, 0x55 }, { WAIT_IDLE },
1607{ 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE },
1608{ 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE },
1609{ 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE },
1610{ 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE },
1611{ 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE },
1612{ 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE },
1613{ 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE },
1614{ 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE },
1615{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1616{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1617{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1618{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1619{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
1620
1621/* Now setup the MOD area. */
1622{ 0xe, 0x01 }, { 0xf, 0x00 }, { WAIT_IDLE },
1623{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1624{ 0xe, 0x01 }, { 0xf, 0x01 }, { WAIT_IDLE },
1625{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1626{ 0xe, 0x01 }, { 0xf, 0x02 }, { WAIT_IDLE },
1627{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1628{ 0xe, 0x01 }, { 0xf, 0x03 }, { WAIT_IDLE },
1629{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1630{ 0xe, 0x01 }, { 0xf, 0x04 }, { WAIT_IDLE },
1631{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1632{ 0xe, 0x01 }, { 0xf, 0x05 }, { WAIT_IDLE },
1633{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1634{ 0xe, 0x01 }, { 0xf, 0x06 }, { WAIT_IDLE },
1635{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1636{ 0xe, 0x01 }, { 0xf, 0x07 }, { WAIT_IDLE },
1637{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1638{ 0xe, 0x01 }, { 0xf, 0x08 }, { WAIT_IDLE },
1639{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1640{ 0xe, 0x01 }, { 0xf, 0x09 }, { WAIT_IDLE },
1641{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1642{ 0xe, 0x01 }, { 0xf, 0x0a }, { WAIT_IDLE },
1643{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1644{ 0xe, 0x01 }, { 0xf, 0x0b }, { WAIT_IDLE },
1645{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1646{ 0xe, 0x01 }, { 0xf, 0x0c }, { WAIT_IDLE },
1647{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1648{ 0xe, 0x01 }, { 0xf, 0x0d }, { WAIT_IDLE },
1649{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1650{ 0xe, 0x01 }, { 0xf, 0x0e }, { WAIT_IDLE },
1651{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1652{ 0xe, 0x01 }, { 0xf, 0x0f }, { WAIT_IDLE },
1653{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
1654
1655{ 0xe, 0xb0 }, { 0xf, 0x20 }, { WAIT_IDLE },
1656{ 0xe, 0xb1 }, { 0xf, 0x20 }, { WAIT_IDLE },
1657{ 0xe, 0xb2 }, { 0xf, 0x20 }, { WAIT_IDLE },
1658{ 0xe, 0xb3 }, { 0xf, 0x20 }, { WAIT_IDLE },
1659{ 0xe, 0xb4 }, { 0xf, 0x20 }, { WAIT_IDLE },
1660{ 0xe, 0xb5 }, { 0xf, 0x20 }, { WAIT_IDLE },
1661{ 0xe, 0xb6 }, { 0xf, 0x20 }, { WAIT_IDLE },
1662{ 0xe, 0xb7 }, { 0xf, 0x20 }, { WAIT_IDLE },
1663{ 0xe, 0xb8 }, { 0xf, 0x20 }, { WAIT_IDLE },
1664{ 0xe, 0xb9 }, { 0xf, 0x20 }, { WAIT_IDLE },
1665{ 0xe, 0xba }, { 0xf, 0x20 }, { WAIT_IDLE },
1666{ 0xe, 0xbb }, { 0xf, 0x20 }, { WAIT_IDLE },
1667{ 0xe, 0xbc }, { 0xf, 0x20 }, { WAIT_IDLE },
1668{ 0xe, 0xbd }, { 0xf, 0x20 }, { WAIT_IDLE },
1669{ 0xe, 0xbe }, { 0xf, 0x20 }, { WAIT_IDLE },
1670{ 0xe, 0xbf }, { 0xf, 0x20 }, { WAIT_IDLE },
1671
1672{ 0xe, 0xf0 }, { 0xf, 0x20 }, { WAIT_IDLE },
1673{ 0xe, 0xf1 }, { 0xf, 0x20 }, { WAIT_IDLE },
1674{ 0xe, 0xf2 }, { 0xf, 0x20 }, { WAIT_IDLE },
1675{ 0xe, 0xf3 }, { 0xf, 0x20 }, { WAIT_IDLE },
1676{ 0xe, 0xf4 }, { 0xf, 0x20 }, { WAIT_IDLE },
1677{ 0xe, 0xf5 }, { 0xf, 0x20 }, { WAIT_IDLE },
1678{ 0xe, 0xf6 }, { 0xf, 0x20 }, { WAIT_IDLE },
1679{ 0xe, 0xf7 }, { 0xf, 0x20 }, { WAIT_IDLE },
1680{ 0xe, 0xf8 }, { 0xf, 0x20 }, { WAIT_IDLE },
1681{ 0xe, 0xf9 }, { 0xf, 0x20 }, { WAIT_IDLE },
1682{ 0xe, 0xfa }, { 0xf, 0x20 }, { WAIT_IDLE },
1683{ 0xe, 0xfb }, { 0xf, 0x20 }, { WAIT_IDLE },
1684{ 0xe, 0xfc }, { 0xf, 0x20 }, { WAIT_IDLE },
1685{ 0xe, 0xfd }, { 0xf, 0x20 }, { WAIT_IDLE },
1686{ 0xe, 0xfe }, { 0xf, 0x20 }, { WAIT_IDLE },
1687{ 0xe, 0xff }, { 0xf, 0x20 }, { WAIT_IDLE },
1688
1689{ 0xe, 0x10 }, { 0xf, 0xff }, { WAIT_IDLE },
1690{ 0xe, 0x11 }, { 0xf, 0xff }, { WAIT_IDLE },
1691{ 0xe, 0x12 }, { 0xf, 0xff }, { WAIT_IDLE },
1692{ 0xe, 0x13 }, { 0xf, 0xff }, { WAIT_IDLE },
1693{ 0xe, 0x14 }, { 0xf, 0xff }, { WAIT_IDLE },
1694{ 0xe, 0x15 }, { 0xf, 0xff }, { WAIT_IDLE },
1695{ 0xe, 0x16 }, { 0xf, 0xff }, { WAIT_IDLE },
1696{ 0xe, 0x17 }, { 0xf, 0xff }, { WAIT_IDLE },
1697{ 0xe, 0x18 }, { 0xf, 0xff }, { WAIT_IDLE },
1698{ 0xe, 0x19 }, { 0xf, 0xff }, { WAIT_IDLE },
1699{ 0xe, 0x1a }, { 0xf, 0xff }, { WAIT_IDLE },
1700{ 0xe, 0x1b }, { 0xf, 0xff }, { WAIT_IDLE },
1701{ 0xe, 0x1c }, { 0xf, 0xff }, { WAIT_IDLE },
1702{ 0xe, 0x1d }, { 0xf, 0xff }, { WAIT_IDLE },
1703{ 0xe, 0x1e }, { 0xf, 0x40 }, { WAIT_IDLE },
1704{ 0xe, 0x1f }, { 0xf, 0xff }, { WAIT_IDLE },
1705{ 0xe, 0x20 }, { 0xf, 0xff }, { WAIT_IDLE },
1706{ 0xe, 0x21 }, { 0xf, 0xff }, { WAIT_IDLE },
1707{ 0xe, 0x22 }, { 0xf, 0xff }, { WAIT_IDLE },
1708{ 0xe, 0x23 }, { 0xf, 0xff }, { WAIT_IDLE },
1709{ 0xe, 0x24 }, { 0xf, 0xff }, { WAIT_IDLE },
1710{ 0xe, 0x25 }, { 0xf, 0xff }, { WAIT_IDLE },
1711{ 0xe, 0x26 }, { 0xf, 0xff }, { WAIT_IDLE },
1712{ 0xe, 0x27 }, { 0xf, 0xff }, { WAIT_IDLE },
1713{ 0xe, 0x28 }, { 0xf, 0xff }, { WAIT_IDLE },
1714{ 0xe, 0x29 }, { 0xf, 0xff }, { WAIT_IDLE },
1715{ 0xe, 0x2a }, { 0xf, 0xff }, { WAIT_IDLE },
1716{ 0xe, 0x2b }, { 0xf, 0xff }, { WAIT_IDLE },
1717{ 0xe, 0x2c }, { 0xf, 0xff }, { WAIT_IDLE },
1718{ 0xe, 0x2d }, { 0xf, 0xff }, { WAIT_IDLE },
1719{ 0xe, 0x2e }, { 0xf, 0x00 }, { WAIT_IDLE },
1720{ 0xe, 0x2f }, { 0xf, 0x00 }, { WAIT_IDLE },
1721{ 0xe, 0x30 }, { 0xf, 0x00 }, { WAIT_IDLE },
1722{ 0xe, 0x31 }, { 0xf, 0x00 }, { WAIT_IDLE },
1723{ 0xe, 0x32 }, { 0xf, 0x00 }, { WAIT_IDLE },
1724{ 0xe, 0x33 }, { 0xf, 0x00 }, { WAIT_IDLE },
1725{ 0xe, 0x34 }, { 0xf, 0x00 }, { WAIT_IDLE },
1726{ 0xe, 0x35 }, { 0xf, 0x00 }, { WAIT_IDLE },
1727{ 0xe, 0x36 }, { 0xf, 0x00 }, { WAIT_IDLE },
1728{ 0xe, 0x37 }, { 0xf, 0x00 }, { WAIT_IDLE },
1729{ 0xe, 0x38 }, { 0xf, 0x00 }, { WAIT_IDLE },
1730{ 0xe, 0x39 }, { 0xf, 0x00 }, { WAIT_IDLE },
1731{ 0xe, 0x3a }, { 0xf, 0x00 }, { WAIT_IDLE },
1732{ 0xe, 0x3b }, { 0xf, 0x00 }, { WAIT_IDLE },
1733{ 0xe, 0x3c }, { 0xf, 0x00 }, { WAIT_IDLE },
1734{ 0xe, 0x3d }, { 0xf, 0x00 }, { WAIT_IDLE },
1735{ 0xe, 0x3e }, { 0xf, 0x00 }, { WAIT_IDLE },
1736{ 0xe, 0x3f }, { 0xf, 0x20 }, { WAIT_IDLE },
1737{ 0xe, 0x40 }, { 0xf, 0x00 }, { WAIT_IDLE },
1738{ 0xe, 0x41 }, { 0xf, 0x00 }, { WAIT_IDLE },
1739{ 0xe, 0x42 }, { 0xf, 0x00 }, { WAIT_IDLE },
1740{ 0xe, 0x43 }, { 0xf, 0x00 }, { WAIT_IDLE },
1741{ 0xe, 0x44 }, { 0xf, 0x00 }, { WAIT_IDLE },
1742{ 0xe, 0x45 }, { 0xf, 0x00 }, { WAIT_IDLE },
1743{ 0xe, 0x46 }, { 0xf, 0x00 }, { WAIT_IDLE },
1744{ 0xe, 0x47 }, { 0xf, 0x00 }, { WAIT_IDLE },
1745{ 0xe, 0x48 }, { 0xf, 0x00 }, { WAIT_IDLE },
1746{ 0xe, 0x49 }, { 0xf, 0x00 }, { WAIT_IDLE },
1747{ 0xe, 0x4a }, { 0xf, 0x00 }, { WAIT_IDLE },
1748{ 0xe, 0x4b }, { 0xf, 0x00 }, { WAIT_IDLE },
1749{ 0xe, 0x4c }, { 0xf, 0x00 }, { WAIT_IDLE },
1750{ 0xe, 0x4d }, { 0xf, 0x00 }, { WAIT_IDLE },
1751{ 0xe, 0x4e }, { 0xf, 0x0e }, { WAIT_IDLE },
1752{ 0xe, 0x4f }, { 0xf, 0x0e }, { WAIT_IDLE },
1753{ 0xe, 0x50 }, { 0xf, 0x00 }, { WAIT_IDLE },
1754{ 0xe, 0x51 }, { 0xf, 0x00 }, { WAIT_IDLE },
1755{ 0xe, 0x52 }, { 0xf, 0x00 }, { WAIT_IDLE },
1756{ 0xe, 0x53 }, { 0xf, 0x00 }, { WAIT_IDLE },
1757{ 0xe, 0x54 }, { 0xf, 0x00 }, { WAIT_IDLE },
1758{ 0xe, 0x55 }, { 0xf, 0x00 }, { WAIT_IDLE },
1759{ 0xe, 0x56 }, { 0xf, 0x00 }, { WAIT_IDLE },
1760{ 0xe, 0x57 }, { 0xf, 0x00 }, { WAIT_IDLE },
1761{ 0xe, 0x58 }, { 0xf, 0x00 }, { WAIT_IDLE },
1762{ 0xe, 0x59 }, { 0xf, 0x00 }, { WAIT_IDLE },
1763{ 0xe, 0x5a }, { 0xf, 0x00 }, { WAIT_IDLE },
1764{ 0xe, 0x5b }, { 0xf, 0x00 }, { WAIT_IDLE },
1765{ 0xe, 0x5c }, { 0xf, 0x00 }, { WAIT_IDLE },
1766{ 0xe, 0x5d }, { 0xf, 0x00 }, { WAIT_IDLE },
1767{ 0xe, 0x5e }, { 0xf, 0x00 }, { WAIT_IDLE },
1768{ 0xe, 0x5f }, { 0xf, 0x00 }, { WAIT_IDLE },
1769{ 0xe, 0x60 }, { 0xf, 0x00 }, { WAIT_IDLE },
1770{ 0xe, 0x61 }, { 0xf, 0x00 }, { WAIT_IDLE },
1771{ 0xe, 0x62 }, { 0xf, 0x00 }, { WAIT_IDLE },
1772{ 0xe, 0x63 }, { 0xf, 0x00 }, { WAIT_IDLE },
1773{ 0xe, 0x64 }, { 0xf, 0x00 }, { WAIT_IDLE },
1774{ 0xe, 0x65 }, { 0xf, 0x00 }, { WAIT_IDLE },
1775{ 0xe, 0x66 }, { 0xf, 0x00 }, { WAIT_IDLE },
1776{ 0xe, 0x67 }, { 0xf, 0x00 }, { WAIT_IDLE },
1777{ 0xe, 0x68 }, { 0xf, 0x00 }, { WAIT_IDLE },
1778{ 0xe, 0x69 }, { 0xf, 0x00 }, { WAIT_IDLE },
1779{ 0xe, 0x6a }, { 0xf, 0x00 }, { WAIT_IDLE },
1780{ 0xe, 0x6b }, { 0xf, 0x00 }, { WAIT_IDLE },
1781{ 0xe, 0x6c }, { 0xf, 0x40 }, { WAIT_IDLE },
1782{ 0xe, 0x6d }, { 0xf, 0x00 }, { WAIT_IDLE },
1783{ 0xe, 0x6e }, { 0xf, 0x40 }, { WAIT_IDLE },
1784{ 0xe, 0x6f }, { 0xf, 0x40 }, { WAIT_IDLE },
1785{ 0xe, 0x70 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1786{ 0xe, 0x71 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1787{ 0xe, 0x72 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1788{ 0xe, 0x73 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1789{ 0xe, 0x74 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1790{ 0xe, 0x75 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1791{ 0xe, 0x76 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1792{ 0xe, 0x77 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1793{ 0xe, 0x78 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1794{ 0xe, 0x79 }, { 0xf, 0xc0 }, { WAIT_IDLE },
1795{ 0xe, 0x7a }, { 0xf, 0xc0 }, { WAIT_IDLE },
1796{ 0xe, 0x7b }, { 0xf, 0xc0 }, { WAIT_IDLE },
1797{ 0xe, 0x7c }, { 0xf, 0xc0 }, { WAIT_IDLE },
1798{ 0xe, 0x7d }, { 0xf, 0xc0 }, { WAIT_IDLE },
1799{ 0xe, 0x7e }, { 0xf, 0xc0 }, { WAIT_IDLE },
1800{ 0xe, 0x7f }, { 0xf, 0xc0 }, { WAIT_IDLE },
1801{ 0xe, 0x80 }, { 0xf, 0x00 }, { WAIT_IDLE },
1802{ 0xe, 0x81 }, { 0xf, 0x00 }, { WAIT_IDLE },
1803{ 0xe, 0x82 }, { 0xf, 0x00 }, { WAIT_IDLE },
1804{ 0xe, 0x83 }, { 0xf, 0x00 }, { WAIT_IDLE },
1805{ 0xe, 0x84 }, { 0xf, 0x00 }, { WAIT_IDLE },
1806{ 0xe, 0x85 }, { 0xf, 0x00 }, { WAIT_IDLE },
1807{ 0xe, 0x86 }, { 0xf, 0x00 }, { WAIT_IDLE },
1808{ 0xe, 0x87 }, { 0xf, 0x00 }, { WAIT_IDLE },
1809{ 0xe, 0x88 }, { 0xf, 0x00 }, { WAIT_IDLE },
1810{ 0xe, 0x89 }, { 0xf, 0x00 }, { WAIT_IDLE },
1811{ 0xe, 0x8a }, { 0xf, 0x00 }, { WAIT_IDLE },
1812{ 0xe, 0x8b }, { 0xf, 0x00 }, { WAIT_IDLE },
1813{ 0xe, 0x8c }, { 0xf, 0x00 }, { WAIT_IDLE },
1814{ 0xe, 0x8d }, { 0xf, 0x00 }, { WAIT_IDLE },
1815{ 0xe, 0x8e }, { 0xf, 0x00 }, { WAIT_IDLE },
1816{ 0xe, 0x8f }, { 0xf, 0x00 }, { WAIT_IDLE },
1817{ 0xe, 0x90 }, { 0xf, 0x00 }, { WAIT_IDLE },
1818{ 0xe, 0x91 }, { 0xf, 0x00 }, { WAIT_IDLE },
1819{ 0xe, 0x92 }, { 0xf, 0x00 }, { WAIT_IDLE },
1820{ 0xe, 0x93 }, { 0xf, 0x00 }, { WAIT_IDLE },
1821{ 0xe, 0x94 }, { 0xf, 0x00 }, { WAIT_IDLE },
1822{ 0xe, 0x95 }, { 0xf, 0x00 }, { WAIT_IDLE },
1823{ 0xe, 0x96 }, { 0xf, 0x00 }, { WAIT_IDLE },
1824{ 0xe, 0x97 }, { 0xf, 0x00 }, { WAIT_IDLE },
1825{ 0xe, 0x98 }, { 0xf, 0x00 }, { WAIT_IDLE },
1826{ 0xe, 0x99 }, { 0xf, 0x00 }, { WAIT_IDLE },
1827{ 0xe, 0x9a }, { 0xf, 0x00 }, { WAIT_IDLE },
1828{ 0xe, 0x9b }, { 0xf, 0x00 }, { WAIT_IDLE },
1829{ 0xe, 0x9c }, { 0xf, 0x00 }, { WAIT_IDLE },
1830{ 0xe, 0x9d }, { 0xf, 0x00 }, { WAIT_IDLE },
1831{ 0xe, 0x9e }, { 0xf, 0x00 }, { WAIT_IDLE },
1832{ 0xe, 0x9f }, { 0xf, 0x00 }, { WAIT_IDLE },
1833{ 0xe, 0xa0 }, { 0xf, 0x00 }, { WAIT_IDLE },
1834{ 0xe, 0xa1 }, { 0xf, 0x00 }, { WAIT_IDLE },
1835{ 0xe, 0xa2 }, { 0xf, 0x00 }, { WAIT_IDLE },
1836{ 0xe, 0xa3 }, { 0xf, 0x00 }, { WAIT_IDLE },
1837{ 0xe, 0xa4 }, { 0xf, 0x00 }, { WAIT_IDLE },
1838{ 0xe, 0xa5 }, { 0xf, 0x00 }, { WAIT_IDLE },
1839{ 0xe, 0xa6 }, { 0xf, 0x00 }, { WAIT_IDLE },
1840{ 0xe, 0xa7 }, { 0xf, 0x00 }, { WAIT_IDLE },
1841{ 0xe, 0xa8 }, { 0xf, 0x00 }, { WAIT_IDLE },
1842{ 0xe, 0xa9 }, { 0xf, 0x00 }, { WAIT_IDLE },
1843{ 0xe, 0xaa }, { 0xf, 0x00 }, { WAIT_IDLE },
1844{ 0xe, 0xab }, { 0xf, 0x00 }, { WAIT_IDLE },
1845{ 0xe, 0xac }, { 0xf, 0x00 }, { WAIT_IDLE },
1846{ 0xe, 0xad }, { 0xf, 0x00 }, { WAIT_IDLE },
1847{ 0xe, 0xae }, { 0xf, 0x00 }, { WAIT_IDLE },
1848{ 0xe, 0xaf }, { 0xf, 0x00 }, { WAIT_IDLE },
1849
1850{ 0xe, 0xc0 }, { 0xf, 0x00 }, { WAIT_IDLE },
1851{ 0xe, 0xc1 }, { 0xf, 0x00 }, { WAIT_IDLE },
1852{ 0xe, 0xc2 }, { 0xf, 0x00 }, { WAIT_IDLE },
1853{ 0xe, 0xc3 }, { 0xf, 0x00 }, { WAIT_IDLE },
1854{ 0xe, 0xc4 }, { 0xf, 0x00 }, { WAIT_IDLE },
1855{ 0xe, 0xc5 }, { 0xf, 0x00 }, { WAIT_IDLE },
1856{ 0xe, 0xc6 }, { 0xf, 0x00 }, { WAIT_IDLE },
1857{ 0xe, 0xc7 }, { 0xf, 0x00 }, { WAIT_IDLE },
1858{ 0xe, 0xc8 }, { 0xf, 0x00 }, { WAIT_IDLE },
1859{ 0xe, 0xc9 }, { 0xf, 0x00 }, { WAIT_IDLE },
1860{ 0xe, 0xca }, { 0xf, 0x00 }, { WAIT_IDLE },
1861{ 0xe, 0xcb }, { 0xf, 0x00 }, { WAIT_IDLE },
1862{ 0xe, 0xcc }, { 0xf, 0x00 }, { WAIT_IDLE },
1863{ 0xe, 0xcd }, { 0xf, 0x00 }, { WAIT_IDLE },
1864{ 0xe, 0xce }, { 0xf, 0x00 }, { WAIT_IDLE },
1865{ 0xe, 0xcf }, { 0xf, 0x00 }, { WAIT_IDLE },
1866{ 0xe, 0xd0 }, { 0xf, 0x00 }, { WAIT_IDLE },
1867{ 0xe, 0xd1 }, { 0xf, 0x00 }, { WAIT_IDLE },
1868{ 0xe, 0xd2 }, { 0xf, 0x00 }, { WAIT_IDLE },
1869{ 0xe, 0xd3 }, { 0xf, 0x00 }, { WAIT_IDLE },
1870{ 0xe, 0xd4 }, { 0xf, 0x00 }, { WAIT_IDLE },
1871{ 0xe, 0xd5 }, { 0xf, 0x00 }, { WAIT_IDLE },
1872{ 0xe, 0xd6 }, { 0xf, 0x00 }, { WAIT_IDLE },
1873{ 0xe, 0xd7 }, { 0xf, 0x00 }, { WAIT_IDLE },
1874{ 0xe, 0xd8 }, { 0xf, 0x00 }, { WAIT_IDLE },
1875{ 0xe, 0xd9 }, { 0xf, 0x00 }, { WAIT_IDLE },
1876{ 0xe, 0xda }, { 0xf, 0x00 }, { WAIT_IDLE },
1877{ 0xe, 0xdb }, { 0xf, 0x00 }, { WAIT_IDLE },
1878{ 0xe, 0xdc }, { 0xf, 0x00 }, { WAIT_IDLE },
1879{ 0xe, 0xdd }, { 0xf, 0x00 }, { WAIT_IDLE },
1880{ 0xe, 0xde }, { 0xf, 0x10 }, { WAIT_IDLE },
1881{ 0xe, 0xdf }, { 0xf, 0x10 }, { WAIT_IDLE },
1882{ 0xe, 0xe0 }, { 0xf, 0x00 }, { WAIT_IDLE },
1883{ 0xe, 0xe1 }, { 0xf, 0x00 }, { WAIT_IDLE },
1884{ 0xe, 0xe2 }, { 0xf, 0x00 }, { WAIT_IDLE },
1885{ 0xe, 0xe3 }, { 0xf, 0x00 }, { WAIT_IDLE },
1886{ 0xe, 0xe4 }, { 0xf, 0x00 }, { WAIT_IDLE },
1887{ 0xe, 0xe5 }, { 0xf, 0x00 }, { WAIT_IDLE },
1888{ 0xe, 0xe6 }, { 0xf, 0x00 }, { WAIT_IDLE },
1889{ 0xe, 0xe7 }, { 0xf, 0x00 }, { WAIT_IDLE },
1890{ 0xe, 0xe8 }, { 0xf, 0x00 }, { WAIT_IDLE },
1891{ 0xe, 0xe9 }, { 0xf, 0x00 }, { WAIT_IDLE },
1892{ 0xe, 0xea }, { 0xf, 0x00 }, { WAIT_IDLE },
1893{ 0xe, 0xeb }, { 0xf, 0x00 }, { WAIT_IDLE },
1894{ 0xe, 0xec }, { 0xf, 0x00 }, { WAIT_IDLE },
1895{ 0xe, 0xed }, { 0xf, 0x00 }, { WAIT_IDLE },
1896{ 0xe, 0xee }, { 0xf, 0x00 }, { WAIT_IDLE },
1897{ 0xe, 0xef }, { 0xf, 0x00 }, { WAIT_IDLE },
1898
1899{ 0xe, 0x01 }, { 0xf, 0x00 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1900{ 0xe, 0x01 }, { 0xf, 0x01 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1901{ 0xe, 0x01 }, { 0xf, 0x02 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1902{ 0xe, 0x01 }, { 0xf, 0x03 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1903{ 0xe, 0x01 }, { 0xf, 0x04 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1904{ 0xe, 0x01 }, { 0xf, 0x05 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1905{ 0xe, 0x01 }, { 0xf, 0x06 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1906{ 0xe, 0x01 }, { 0xf, 0x07 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1907{ 0xe, 0x01 }, { 0xf, 0x08 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1908{ 0xe, 0x01 }, { 0xf, 0x09 }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1909{ 0xe, 0x01 }, { 0xf, 0x0a }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1910{ 0xe, 0x01 }, { 0xf, 0x0b }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1911{ 0xe, 0x01 }, { 0xf, 0x0c }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1912{ 0xe, 0x01 }, { 0xf, 0x0d }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1913{ 0xe, 0x01 }, { 0xf, 0x0e }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1914{ 0xe, 0x01 }, { 0xf, 0x0f }, { 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
1915
1916/* mute on */
1917{ 0x8, 0x02 },
1918
1919/* Now set the coefficients and so forth for the programs above */
1920{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1921{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1922{ 0xb, 0x00 }, { 0xa, 0x4b }, { 0xd, 0x03 }, { 0xc, 0x11 }, { WAIT_IDLE },
1923{ 0xb, 0x00 }, { 0xa, 0x4d }, { 0xd, 0x01 }, { 0xc, 0x32 }, { WAIT_IDLE },
1924{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1925{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1926{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1927{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1928{ 0xb, 0x01 }, { 0xa, 0x40 }, { 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE },
1929{ 0xb, 0x01 }, { 0xa, 0x41 }, { 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE },
1930{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1931{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1932{ 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1933{ 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1934{ 0xb, 0x00 }, { 0xa, 0x47 }, { 0xd, 0x01 }, { 0xc, 0x00 }, { WAIT_IDLE },
1935{ 0xb, 0x00 }, { 0xa, 0x4a }, { 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE },
1936{ 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1937{ 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1938{ 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1939{ 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1940{ 0xb, 0x00 }, { 0xa, 0x00 }, { 0xd, 0x01 }, { 0xc, 0x1c }, { WAIT_IDLE },
1941{ 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1942{ 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1943{ 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1944{ 0xb, 0x00 }, { 0xa, 0x44 }, { 0xd, 0x01 }, { 0xc, 0x00 }, { WAIT_IDLE },
1945{ 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1946{ 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1947{ 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1948{ 0xb, 0x00 }, { 0xa, 0x42 }, { 0xd, 0x01 }, { 0xc, 0x1a }, { WAIT_IDLE },
1949{ 0xb, 0x00 }, { 0xa, 0x43 }, { 0xd, 0x01 }, { 0xc, 0x20 }, { WAIT_IDLE },
1950{ 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1951{ 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1952{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1953{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1954{ 0xb, 0x01 }, { 0xa, 0x40 }, { 0xd, 0x02 }, { 0xc, 0x40 }, { WAIT_IDLE },
1955{ 0xb, 0x01 }, { 0xa, 0x41 }, { 0xd, 0x02 }, { 0xc, 0x60 }, { WAIT_IDLE },
1956{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1957{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1958{ 0xb, 0x07 }, { 0xa, 0x44 }, { 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
1959{ 0xb, 0x07 }, { 0xa, 0x42 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1960{ 0xb, 0x07 }, { 0xa, 0x43 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1961{ 0xb, 0x07 }, { 0xa, 0x40 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1962{ 0xb, 0x07 }, { 0xa, 0x41 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
1963{ 0xb, 0x07 }, { 0xa, 0x51 }, { 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE },
1964{ 0xb, 0x07 }, { 0xa, 0x50 }, { 0xd, 0x06 }, { 0xc, 0x40 }, { WAIT_IDLE },
1965{ 0xb, 0x07 }, { 0xa, 0x4f }, { 0xd, 0x03 }, { 0xc, 0x81 }, { WAIT_IDLE },
1966{ 0xb, 0x07 }, { 0xa, 0x53 }, { 0xd, 0x1a }, { 0xc, 0x76 }, { WAIT_IDLE },
1967{ 0xb, 0x07 }, { 0xa, 0x54 }, { 0xd, 0x0d }, { 0xc, 0x8b }, { WAIT_IDLE },
1968{ 0xb, 0x07 }, { 0xa, 0x55 }, { 0xd, 0x04 }, { 0xc, 0xe9 }, { WAIT_IDLE },
1969{ 0xb, 0x07 }, { 0xa, 0x56 }, { 0xd, 0x0b }, { 0xc, 0x17 }, { WAIT_IDLE },
1970{ 0xb, 0x07 }, { 0xa, 0x57 }, { 0xd, 0x1a }, { 0xc, 0x38 }, { WAIT_IDLE },
1971{ 0xb, 0x07 }, { 0xa, 0x58 }, { 0xd, 0x0d }, { 0xc, 0xc9 }, { WAIT_IDLE },
1972{ 0xb, 0x07 }, { 0xa, 0x59 }, { 0xd, 0x04 }, { 0xc, 0x6f }, { WAIT_IDLE },
1973{ 0xb, 0x07 }, { 0xa, 0x5a }, { 0xd, 0x0b }, { 0xc, 0x91 }, { WAIT_IDLE },
1974{ 0xb, 0x07 }, { 0xa, 0x73 }, { 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE },
1975{ 0xb, 0x07 }, { 0xa, 0x74 }, { 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE },
1976{ 0xb, 0x07 }, { 0xa, 0x75 }, { 0xd, 0x04 }, { 0xc, 0xd9 }, { WAIT_IDLE },
1977{ 0xb, 0x07 }, { 0xa, 0x76 }, { 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE },
1978{ 0xb, 0x07 }, { 0xa, 0x77 }, { 0xd, 0x14 }, { 0xc, 0xda }, { WAIT_IDLE },
1979{ 0xb, 0x07 }, { 0xa, 0x78 }, { 0xd, 0x0d }, { 0xc, 0x93 }, { WAIT_IDLE },
1980{ 0xb, 0x07 }, { 0xa, 0x79 }, { 0xd, 0x04 }, { 0xc, 0xd9 }, { WAIT_IDLE },
1981{ 0xb, 0x07 }, { 0xa, 0x7a }, { 0xd, 0x05 }, { 0xc, 0x93 }, { WAIT_IDLE },
1982{ 0xb, 0x07 }, { 0xa, 0x5e }, { 0xd, 0x03 }, { 0xc, 0x68 }, { WAIT_IDLE },
1983{ 0xb, 0x07 }, { 0xa, 0x5c }, { 0xd, 0x04 }, { 0xc, 0x31 }, { WAIT_IDLE },
1984{ 0xb, 0x07 }, { 0xa, 0x5d }, { 0xd, 0x04 }, { 0xc, 0x31 }, { WAIT_IDLE },
1985{ 0xb, 0x07 }, { 0xa, 0x62 }, { 0xd, 0x03 }, { 0xc, 0x52 }, { WAIT_IDLE },
1986{ 0xb, 0x07 }, { 0xa, 0x60 }, { 0xd, 0x04 }, { 0xc, 0x76 }, { WAIT_IDLE },
1987{ 0xb, 0x07 }, { 0xa, 0x61 }, { 0xd, 0x04 }, { 0xc, 0x76 }, { WAIT_IDLE },
1988{ 0xb, 0x07 }, { 0xa, 0x66 }, { 0xd, 0x03 }, { 0xc, 0x2e }, { WAIT_IDLE },
1989{ 0xb, 0x07 }, { 0xa, 0x64 }, { 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE },
1990{ 0xb, 0x07 }, { 0xa, 0x65 }, { 0xd, 0x04 }, { 0xc, 0xda }, { WAIT_IDLE },
1991{ 0xb, 0x07 }, { 0xa, 0x6a }, { 0xd, 0x02 }, { 0xc, 0xf6 }, { WAIT_IDLE },
1992{ 0xb, 0x07 }, { 0xa, 0x68 }, { 0xd, 0x05 }, { 0xc, 0x62 }, { WAIT_IDLE },
1993{ 0xb, 0x07 }, { 0xa, 0x69 }, { 0xd, 0x05 }, { 0xc, 0x62 }, { WAIT_IDLE },
1994{ 0xb, 0x06 }, { 0xa, 0x46 }, { 0xd, 0x0a }, { 0xc, 0x22 }, { WAIT_IDLE },
1995{ 0xb, 0x06 }, { 0xa, 0x48 }, { 0xd, 0x0d }, { 0xc, 0x24 }, { WAIT_IDLE },
1996{ 0xb, 0x06 }, { 0xa, 0x6e }, { 0xd, 0x11 }, { 0xc, 0xd3 }, { WAIT_IDLE },
1997{ 0xb, 0x06 }, { 0xa, 0x70 }, { 0xd, 0x15 }, { 0xc, 0xcb }, { WAIT_IDLE },
1998{ 0xb, 0x06 }, { 0xa, 0x52 }, { 0xd, 0x20 }, { 0xc, 0x93 }, { WAIT_IDLE },
1999{ 0xb, 0x06 }, { 0xa, 0x54 }, { 0xd, 0x20 }, { 0xc, 0x54 }, { WAIT_IDLE },
2000{ 0xb, 0x06 }, { 0xa, 0x4a }, { 0xd, 0x27 }, { 0xc, 0x1d }, { WAIT_IDLE },
2001{ 0xb, 0x06 }, { 0xa, 0x58 }, { 0xd, 0x2f }, { 0xc, 0xc8 }, { WAIT_IDLE },
2002{ 0xb, 0x06 }, { 0xa, 0x5c }, { 0xd, 0x30 }, { 0xc, 0x07 }, { WAIT_IDLE },
2003{ 0xb, 0x06 }, { 0xa, 0x4c }, { 0xd, 0x37 }, { 0xc, 0x90 }, { WAIT_IDLE },
2004{ 0xb, 0x06 }, { 0xa, 0x60 }, { 0xd, 0x3d }, { 0xc, 0xdb }, { WAIT_IDLE },
2005{ 0xb, 0x06 }, { 0xa, 0x64 }, { 0xd, 0x3e }, { 0xc, 0x42 }, { WAIT_IDLE },
2006{ 0xb, 0x06 }, { 0xa, 0x4e }, { 0xd, 0x45 }, { 0xc, 0x78 }, { WAIT_IDLE },
2007{ 0xb, 0x06 }, { 0xa, 0x68 }, { 0xd, 0x4c }, { 0xc, 0x48 }, { WAIT_IDLE },
2008{ 0xb, 0x06 }, { 0xa, 0x6c }, { 0xd, 0x4c }, { 0xc, 0x6c }, { WAIT_IDLE },
2009{ 0xb, 0x06 }, { 0xa, 0x50 }, { 0xd, 0x52 }, { 0xc, 0xe2 }, { WAIT_IDLE },
2010{ 0xb, 0x06 }, { 0xa, 0x42 }, { 0xd, 0x02 }, { 0xc, 0xba }, { WAIT_IDLE },
2011
2012/* Some settings (?) */
2013{ WAIT_IDLE }, { 0xe, 0x1e }, { 0xf, 0x14 },
2014{ WAIT_IDLE }, { 0xe, 0xde }, { 0xf, 0x20 },
2015{ WAIT_IDLE }, { 0xe, 0xdf }, { 0xf, 0x20 },
2016
2017/* some more coefficients */
2018{ WAIT_IDLE }, { 0xb, 0x06 }, { 0xa, 0x78 }, { 0xd, 0x00 }, { 0xc, 0x40 },
2019{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x03 }, { 0xd, 0x0f }, { 0xc, 0xff },
2020{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x0b }, { 0xd, 0x0f }, { 0xc, 0xff },
2021{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x02 }, { 0xd, 0x00 }, { 0xc, 0x00 },
2022{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x0a }, { 0xd, 0x00 }, { 0xc, 0x00 },
2023{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 },
2024{ WAIT_IDLE }, { 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 },
2025
2026/* Now, for some strange reason, lets reload every page
2027 and all the coefficients over again. I have *NO* idea
2028 why this is done. I do know that no sound is produced
2029 is this phase is omitted. */
2030{ 0x9, 0x05 }, { 0xb, 0x00 }, { 0xa, 0x10 },
2031
2032{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2033{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2034{ 0xd, 0x02 }, { 0xc, 0x00 }, { WAIT_IDLE },
2035{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2036{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2037{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2038{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2039{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2040{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2041{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2042{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2043{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2044{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2045{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2046{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2047{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2048{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2049{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2050{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2051{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2052{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2053{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2054{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2055{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2056{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2057{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2058{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2059{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2060{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2061{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2062{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2063{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2064{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2065{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2066{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2067{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2068{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2069{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2070{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2071{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2072{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2073{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2074{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2075{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2076{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2077{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2078{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2079{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2080
2081{ 0x9, 0x05 }, { 0xb, 0x01 }, { 0xa, 0x10 },
2082
2083{ 0xd, 0x01 }, { 0xc, 0xc0 }, { WAIT_IDLE },
2084{ 0xd, 0x01 }, { 0xc, 0xfa }, { WAIT_IDLE },
2085{ 0xd, 0x00 }, { 0xc, 0x1a }, { WAIT_IDLE },
2086{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2087{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2088{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2089{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2090{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2091{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2092{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2093{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2094{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2095{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2096{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2097{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2098{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2099{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2100{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2101{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2102{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2103{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2104{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2105{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2106{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2107{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2108{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2109{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2110{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2111{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2112{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2113{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2114{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2115{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2116{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2117{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2118{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2119{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2120{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2121{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2122{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2123{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2124{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2125{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2126{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2127{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2128{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2129{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2130{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2131
2132{ WAIT_IDLE }, { WAIT_IDLE },
2133
2134{ 0x9, 0x05 }, { 0xb, 0x02 }, { 0xa, 0x10 },
2135
2136{ 0xc, 0x46 }, { WAIT_IDLE },
2137{ 0xc, 0x46 }, { WAIT_IDLE },
2138{ 0xc, 0x00 }, { WAIT_IDLE },
2139{ 0xc, 0x00 }, { WAIT_IDLE },
2140{ 0xc, 0x00 }, { WAIT_IDLE },
2141{ 0xc, 0x00 }, { WAIT_IDLE },
2142{ 0xc, 0x00 }, { WAIT_IDLE },
2143{ 0xc, 0x00 }, { WAIT_IDLE },
2144{ 0xc, 0x00 }, { WAIT_IDLE },
2145{ 0xc, 0x00 }, { WAIT_IDLE },
2146{ 0xc, 0x00 }, { WAIT_IDLE },
2147{ 0xc, 0x00 }, { WAIT_IDLE },
2148{ 0xc, 0x00 }, { WAIT_IDLE },
2149{ 0xc, 0x00 }, { WAIT_IDLE },
2150{ 0xc, 0x00 }, { WAIT_IDLE },
2151{ 0xc, 0x00 }, { WAIT_IDLE },
2152{ 0xc, 0x00 }, { WAIT_IDLE },
2153{ 0xc, 0x00 }, { WAIT_IDLE },
2154{ 0xc, 0x00 }, { WAIT_IDLE },
2155{ 0xc, 0x00 }, { WAIT_IDLE },
2156{ 0xc, 0x00 }, { WAIT_IDLE },
2157{ 0xc, 0x00 }, { WAIT_IDLE },
2158{ 0xc, 0x00 }, { WAIT_IDLE },
2159{ 0xc, 0x00 }, { WAIT_IDLE },
2160{ 0xc, 0x00 }, { WAIT_IDLE },
2161{ 0xc, 0x00 }, { WAIT_IDLE },
2162{ 0xc, 0x00 }, { WAIT_IDLE },
2163{ 0xc, 0x00 }, { WAIT_IDLE },
2164{ 0xc, 0x00 }, { WAIT_IDLE },
2165{ 0xc, 0x00 }, { WAIT_IDLE },
2166{ 0xc, 0x00 }, { WAIT_IDLE },
2167{ 0xc, 0x00 }, { WAIT_IDLE },
2168{ 0xc, 0x00 }, { WAIT_IDLE },
2169{ 0xc, 0x00 }, { WAIT_IDLE },
2170{ 0xc, 0x00 }, { WAIT_IDLE },
2171{ 0xc, 0x00 }, { WAIT_IDLE },
2172{ 0xc, 0x00 }, { WAIT_IDLE },
2173{ 0xc, 0x00 }, { WAIT_IDLE },
2174{ 0xc, 0x00 }, { WAIT_IDLE },
2175{ 0xc, 0x00 }, { WAIT_IDLE },
2176{ 0xc, 0x00 }, { WAIT_IDLE },
2177{ 0xc, 0x00 }, { WAIT_IDLE },
2178{ 0xc, 0x00 }, { WAIT_IDLE },
2179{ 0xc, 0x00 }, { WAIT_IDLE },
2180{ 0xc, 0x00 }, { WAIT_IDLE },
2181{ 0xc, 0x00 }, { WAIT_IDLE },
2182{ 0xc, 0x00 }, { WAIT_IDLE },
2183{ 0xc, 0x00 }, { WAIT_IDLE },
2184
2185{ 0x9, 0x05 }, { 0xb, 0x03 }, { 0xa, 0x10 },
2186
2187{ 0xc, 0x00 }, { WAIT_IDLE },
2188{ 0xc, 0x00 }, { WAIT_IDLE },
2189{ 0xc, 0x00 }, { WAIT_IDLE },
2190{ 0xc, 0x00 }, { WAIT_IDLE },
2191{ 0xc, 0x00 }, { WAIT_IDLE },
2192{ 0xc, 0x00 }, { WAIT_IDLE },
2193{ 0xc, 0x00 }, { WAIT_IDLE },
2194{ 0xc, 0x00 }, { WAIT_IDLE },
2195{ 0xc, 0x00 }, { WAIT_IDLE },
2196{ 0xc, 0x00 }, { WAIT_IDLE },
2197{ 0xc, 0x00 }, { WAIT_IDLE },
2198{ 0xc, 0x00 }, { WAIT_IDLE },
2199{ 0xc, 0x00 }, { WAIT_IDLE },
2200{ 0xc, 0x00 }, { WAIT_IDLE },
2201{ 0xc, 0x00 }, { WAIT_IDLE },
2202{ 0xc, 0x00 }, { WAIT_IDLE },
2203{ 0xc, 0x00 }, { WAIT_IDLE },
2204{ 0xc, 0x00 }, { WAIT_IDLE },
2205{ 0xc, 0x00 }, { WAIT_IDLE },
2206{ 0xc, 0x00 }, { WAIT_IDLE },
2207{ 0xc, 0x00 }, { WAIT_IDLE },
2208{ 0xc, 0x00 }, { WAIT_IDLE },
2209{ 0xc, 0x00 }, { WAIT_IDLE },
2210{ 0xc, 0x00 }, { WAIT_IDLE },
2211{ 0xc, 0x00 }, { WAIT_IDLE },
2212{ 0xc, 0x00 }, { WAIT_IDLE },
2213{ 0xc, 0x00 }, { WAIT_IDLE },
2214{ 0xc, 0x00 }, { WAIT_IDLE },
2215{ 0xc, 0x00 }, { WAIT_IDLE },
2216{ 0xc, 0x00 }, { WAIT_IDLE },
2217{ 0xc, 0x00 }, { WAIT_IDLE },
2218{ 0xc, 0x00 }, { WAIT_IDLE },
2219{ 0xc, 0x00 }, { WAIT_IDLE },
2220{ 0xc, 0x00 }, { WAIT_IDLE },
2221{ 0xc, 0x00 }, { WAIT_IDLE },
2222{ 0xc, 0x00 }, { WAIT_IDLE },
2223{ 0xc, 0x00 }, { WAIT_IDLE },
2224{ 0xc, 0x00 }, { WAIT_IDLE },
2225{ 0xc, 0x00 }, { WAIT_IDLE },
2226{ 0xc, 0x00 }, { WAIT_IDLE },
2227{ 0xc, 0x00 }, { WAIT_IDLE },
2228{ 0xc, 0x00 }, { WAIT_IDLE },
2229{ 0xc, 0x00 }, { WAIT_IDLE },
2230{ 0xc, 0x00 }, { WAIT_IDLE },
2231{ 0xc, 0x00 }, { WAIT_IDLE },
2232{ 0xc, 0x00 }, { WAIT_IDLE },
2233{ 0xc, 0x00 }, { WAIT_IDLE },
2234{ 0xc, 0x00 }, { WAIT_IDLE },
2235
2236{ 0x9, 0x05 }, { 0xb, 0x04 }, { 0xa, 0x10 },
2237
2238{ 0xc, 0x00 }, { WAIT_IDLE },
2239{ 0xc, 0x00 }, { WAIT_IDLE },
2240{ 0xc, 0x00 }, { WAIT_IDLE },
2241{ 0xc, 0x00 }, { WAIT_IDLE },
2242{ 0xc, 0x00 }, { WAIT_IDLE },
2243{ 0xc, 0x00 }, { WAIT_IDLE },
2244{ 0xc, 0x00 }, { WAIT_IDLE },
2245{ 0xc, 0x00 }, { WAIT_IDLE },
2246{ 0xc, 0x00 }, { WAIT_IDLE },
2247{ 0xc, 0x00 }, { WAIT_IDLE },
2248{ 0xc, 0x00 }, { WAIT_IDLE },
2249{ 0xc, 0x00 }, { WAIT_IDLE },
2250{ 0xc, 0x00 }, { WAIT_IDLE },
2251{ 0xc, 0x00 }, { WAIT_IDLE },
2252{ 0xc, 0x00 }, { WAIT_IDLE },
2253{ 0xc, 0x00 }, { WAIT_IDLE },
2254{ 0xc, 0x00 }, { WAIT_IDLE },
2255{ 0xc, 0x00 }, { WAIT_IDLE },
2256{ 0xc, 0x00 }, { WAIT_IDLE },
2257{ 0xc, 0x00 }, { WAIT_IDLE },
2258{ 0xc, 0x00 }, { WAIT_IDLE },
2259{ 0xc, 0x00 }, { WAIT_IDLE },
2260{ 0xc, 0x00 }, { WAIT_IDLE },
2261{ 0xc, 0x00 }, { WAIT_IDLE },
2262{ 0xc, 0x00 }, { WAIT_IDLE },
2263{ 0xc, 0x00 }, { WAIT_IDLE },
2264{ 0xc, 0x00 }, { WAIT_IDLE },
2265{ 0xc, 0x00 }, { WAIT_IDLE },
2266{ 0xc, 0x00 }, { WAIT_IDLE },
2267{ 0xc, 0x00 }, { WAIT_IDLE },
2268{ 0xc, 0x00 }, { WAIT_IDLE },
2269{ 0xc, 0x00 }, { WAIT_IDLE },
2270{ 0xc, 0x00 }, { WAIT_IDLE },
2271{ 0xc, 0x00 }, { WAIT_IDLE },
2272{ 0xc, 0x00 }, { WAIT_IDLE },
2273{ 0xc, 0x00 }, { WAIT_IDLE },
2274{ 0xc, 0x00 }, { WAIT_IDLE },
2275{ 0xc, 0x00 }, { WAIT_IDLE },
2276{ 0xc, 0x00 }, { WAIT_IDLE },
2277{ 0xc, 0x00 }, { WAIT_IDLE },
2278{ 0xc, 0x00 }, { WAIT_IDLE },
2279{ 0xc, 0x00 }, { WAIT_IDLE },
2280{ 0xc, 0x00 }, { WAIT_IDLE },
2281{ 0xc, 0x00 }, { WAIT_IDLE },
2282{ 0xc, 0x00 }, { WAIT_IDLE },
2283{ 0xc, 0x00 }, { WAIT_IDLE },
2284{ 0xc, 0x00 }, { WAIT_IDLE },
2285{ 0xc, 0x00 }, { WAIT_IDLE },
2286
2287/* Page six v.2 */
2288{ 0x9, 0x01 }, { 0xb, 0x06 },
2289
2290{ 0xa, 0x10 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2291{ 0xa, 0x12 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2292{ 0xa, 0x14 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2293{ 0xa, 0x16 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2294{ 0xa, 0x18 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2295{ 0xa, 0x1a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2296{ 0xa, 0x1c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2297{ 0xa, 0x1e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2298{ 0xa, 0x20 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2299{ 0xa, 0x22 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2300{ 0xa, 0x24 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2301{ 0xa, 0x26 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2302{ 0xa, 0x28 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2303{ 0xa, 0x2a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2304{ 0xa, 0x2c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2305{ 0xa, 0x2e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2306{ 0xa, 0x30 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2307{ 0xa, 0x32 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2308{ 0xa, 0x34 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2309{ 0xa, 0x36 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2310{ 0xa, 0x38 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2311{ 0xa, 0x3a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2312{ 0xa, 0x3c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2313{ 0xa, 0x3e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2314
2315{ 0x9, 0x05 }, { 0xb, 0x07 }, { 0xa, 0x10 },
2316
2317{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
2318{ 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
2319{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2320{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2321{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2322{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2323{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2324{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2325{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2326{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2327{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2328{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2329{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2330{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2331{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2332{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2333{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2334{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2335{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2336{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2337{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2338{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2339{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2340{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2341{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2342{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2343{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2344{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2345{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2346{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2347{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2348{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2349{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2350{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2351{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2352{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2353{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2354{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2355{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2356{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2357{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2358{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2359{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2360{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2361{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2362{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2363{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2364{ 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2365
2366{ 0xe, 0x01 }, { 0xf, 0x00 }, { WAIT_IDLE },
2367{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
2368{ 0xe, 0x01 }, { 0xf, 0x01 }, { WAIT_IDLE },
2369{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
2370{ 0xe, 0x01 }, { 0xf, 0x02 }, { WAIT_IDLE },
2371{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
2372{ 0xe, 0x01 }, { 0xf, 0x03 }, { WAIT_IDLE },
2373{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
2374{ 0xe, 0x01 }, { 0xf, 0x04 }, { WAIT_IDLE },
2375{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
2376{ 0xe, 0x01 }, { 0xf, 0x05 }, { WAIT_IDLE },
2377{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
2378{ 0xe, 0x01 }, { 0xf, 0x06 }, { WAIT_IDLE },
2379{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
2380{ 0xe, 0x01 }, { 0xf, 0x07 }, { WAIT_IDLE },
2381{ 0xe, 0x02 }, { 0xf, 0x00 }, { WAIT_IDLE },
2382{ 0xe, 0xb0 }, { 0xf, 0x20 }, { WAIT_IDLE },
2383{ 0xe, 0xb1 }, { 0xf, 0x20 }, { WAIT_IDLE },
2384{ 0xe, 0xb2 }, { 0xf, 0x20 }, { WAIT_IDLE },
2385{ 0xe, 0xb3 }, { 0xf, 0x20 }, { WAIT_IDLE },
2386{ 0xe, 0xb4 }, { 0xf, 0x20 }, { WAIT_IDLE },
2387{ 0xe, 0xb5 }, { 0xf, 0x20 }, { WAIT_IDLE },
2388{ 0xe, 0xb6 }, { 0xf, 0x20 }, { WAIT_IDLE },
2389{ 0xe, 0xb7 }, { 0xf, 0x20 }, { WAIT_IDLE },
2390{ 0xe, 0xf0 }, { 0xf, 0x20 }, { WAIT_IDLE },
2391{ 0xe, 0xf1 }, { 0xf, 0x20 }, { WAIT_IDLE },
2392{ 0xe, 0xf2 }, { 0xf, 0x20 }, { WAIT_IDLE },
2393{ 0xe, 0xf3 }, { 0xf, 0x20 }, { WAIT_IDLE },
2394{ 0xe, 0xf4 }, { 0xf, 0x20 }, { WAIT_IDLE },
2395{ 0xe, 0xf5 }, { 0xf, 0x20 }, { WAIT_IDLE },
2396{ 0xe, 0xf6 }, { 0xf, 0x20 }, { WAIT_IDLE },
2397{ 0xe, 0xf7 }, { 0xf, 0x20 }, { WAIT_IDLE },
2398{ 0xe, 0x10 }, { 0xf, 0xff }, { WAIT_IDLE },
2399{ 0xe, 0x11 }, { 0xf, 0xff }, { WAIT_IDLE },
2400{ 0xe, 0x12 }, { 0xf, 0xff }, { WAIT_IDLE },
2401{ 0xe, 0x13 }, { 0xf, 0xff }, { WAIT_IDLE },
2402{ 0xe, 0x14 }, { 0xf, 0xff }, { WAIT_IDLE },
2403{ 0xe, 0x15 }, { 0xf, 0xff }, { WAIT_IDLE },
2404{ 0xe, 0x16 }, { 0xf, 0xff }, { WAIT_IDLE },
2405{ 0xe, 0x17 }, { 0xf, 0xff }, { WAIT_IDLE },
2406{ 0xe, 0x20 }, { 0xf, 0xff }, { WAIT_IDLE },
2407{ 0xe, 0x21 }, { 0xf, 0xff }, { WAIT_IDLE },
2408{ 0xe, 0x22 }, { 0xf, 0xff }, { WAIT_IDLE },
2409{ 0xe, 0x23 }, { 0xf, 0xff }, { WAIT_IDLE },
2410{ 0xe, 0x24 }, { 0xf, 0xff }, { WAIT_IDLE },
2411{ 0xe, 0x25 }, { 0xf, 0xff }, { WAIT_IDLE },
2412{ 0xe, 0x26 }, { 0xf, 0xff }, { WAIT_IDLE },
2413{ 0xe, 0x27 }, { 0xf, 0xff }, { WAIT_IDLE },
2414{ 0xe, 0x30 }, { 0xf, 0x00 }, { WAIT_IDLE },
2415{ 0xe, 0x31 }, { 0xf, 0x00 }, { WAIT_IDLE },
2416{ 0xe, 0x32 }, { 0xf, 0x00 }, { WAIT_IDLE },
2417{ 0xe, 0x33 }, { 0xf, 0x00 }, { WAIT_IDLE },
2418{ 0xe, 0x34 }, { 0xf, 0x00 }, { WAIT_IDLE },
2419{ 0xe, 0x35 }, { 0xf, 0x00 }, { WAIT_IDLE },
2420{ 0xe, 0x36 }, { 0xf, 0x00 }, { WAIT_IDLE },
2421{ 0xe, 0x37 }, { 0xf, 0x00 }, { WAIT_IDLE },
2422{ 0xe, 0x40 }, { 0xf, 0x00 }, { WAIT_IDLE },
2423{ 0xe, 0x41 }, { 0xf, 0x00 }, { WAIT_IDLE },
2424{ 0xe, 0x42 }, { 0xf, 0x00 }, { WAIT_IDLE },
2425{ 0xe, 0x43 }, { 0xf, 0x00 }, { WAIT_IDLE },
2426{ 0xe, 0x44 }, { 0xf, 0x00 }, { WAIT_IDLE },
2427{ 0xe, 0x45 }, { 0xf, 0x00 }, { WAIT_IDLE },
2428{ 0xe, 0x46 }, { 0xf, 0x00 }, { WAIT_IDLE },
2429{ 0xe, 0x47 }, { 0xf, 0x00 }, { WAIT_IDLE },
2430{ 0xe, 0x50 }, { 0xf, 0x00 }, { WAIT_IDLE },
2431{ 0xe, 0x51 }, { 0xf, 0x00 }, { WAIT_IDLE },
2432{ 0xe, 0x52 }, { 0xf, 0x00 }, { WAIT_IDLE },
2433{ 0xe, 0x53 }, { 0xf, 0x00 }, { WAIT_IDLE },
2434{ 0xe, 0x54 }, { 0xf, 0x00 }, { WAIT_IDLE },
2435{ 0xe, 0x55 }, { 0xf, 0x00 }, { WAIT_IDLE },
2436{ 0xe, 0x56 }, { 0xf, 0x00 }, { WAIT_IDLE },
2437{ 0xe, 0x57 }, { 0xf, 0x00 }, { WAIT_IDLE },
2438{ 0xe, 0x60 }, { 0xf, 0x00 }, { WAIT_IDLE },
2439{ 0xe, 0x61 }, { 0xf, 0x00 }, { WAIT_IDLE },
2440{ 0xe, 0x62 }, { 0xf, 0x00 }, { WAIT_IDLE },
2441{ 0xe, 0x63 }, { 0xf, 0x00 }, { WAIT_IDLE },
2442{ 0xe, 0x64 }, { 0xf, 0x00 }, { WAIT_IDLE },
2443{ 0xe, 0x65 }, { 0xf, 0x00 }, { WAIT_IDLE },
2444{ 0xe, 0x66 }, { 0xf, 0x00 }, { WAIT_IDLE },
2445{ 0xe, 0x67 }, { 0xf, 0x00 }, { WAIT_IDLE },
2446{ 0xe, 0x70 }, { 0xf, 0xc0 }, { WAIT_IDLE },
2447{ 0xe, 0x71 }, { 0xf, 0xc0 }, { WAIT_IDLE },
2448{ 0xe, 0x72 }, { 0xf, 0xc0 }, { WAIT_IDLE },
2449{ 0xe, 0x73 }, { 0xf, 0xc0 }, { WAIT_IDLE },
2450{ 0xe, 0x74 }, { 0xf, 0xc0 }, { WAIT_IDLE },
2451{ 0xe, 0x75 }, { 0xf, 0xc0 }, { WAIT_IDLE },
2452{ 0xe, 0x76 }, { 0xf, 0xc0 }, { WAIT_IDLE },
2453{ 0xe, 0x77 }, { 0xf, 0xc0 }, { WAIT_IDLE },
2454{ 0xe, 0x80 }, { 0xf, 0x00 }, { WAIT_IDLE },
2455{ 0xe, 0x81 }, { 0xf, 0x00 }, { WAIT_IDLE },
2456{ 0xe, 0x82 }, { 0xf, 0x00 }, { WAIT_IDLE },
2457{ 0xe, 0x83 }, { 0xf, 0x00 }, { WAIT_IDLE },
2458{ 0xe, 0x84 }, { 0xf, 0x00 }, { WAIT_IDLE },
2459{ 0xe, 0x85 }, { 0xf, 0x00 }, { WAIT_IDLE },
2460{ 0xe, 0x86 }, { 0xf, 0x00 }, { WAIT_IDLE },
2461{ 0xe, 0x87 }, { 0xf, 0x00 }, { WAIT_IDLE },
2462{ 0xe, 0x90 }, { 0xf, 0x00 }, { WAIT_IDLE },
2463{ 0xe, 0x91 }, { 0xf, 0x00 }, { WAIT_IDLE },
2464{ 0xe, 0x92 }, { 0xf, 0x00 }, { WAIT_IDLE },
2465{ 0xe, 0x93 }, { 0xf, 0x00 }, { WAIT_IDLE },
2466{ 0xe, 0x94 }, { 0xf, 0x00 }, { WAIT_IDLE },
2467{ 0xe, 0x95 }, { 0xf, 0x00 }, { WAIT_IDLE },
2468{ 0xe, 0x96 }, { 0xf, 0x00 }, { WAIT_IDLE },
2469{ 0xe, 0x97 }, { 0xf, 0x00 }, { WAIT_IDLE },
2470{ 0xe, 0xa0 }, { 0xf, 0x00 }, { WAIT_IDLE },
2471{ 0xe, 0xa1 }, { 0xf, 0x00 }, { WAIT_IDLE },
2472{ 0xe, 0xa2 }, { 0xf, 0x00 }, { WAIT_IDLE },
2473{ 0xe, 0xa3 }, { 0xf, 0x00 }, { WAIT_IDLE },
2474{ 0xe, 0xa4 }, { 0xf, 0x00 }, { WAIT_IDLE },
2475{ 0xe, 0xa5 }, { 0xf, 0x00 }, { WAIT_IDLE },
2476{ 0xe, 0xa6 }, { 0xf, 0x00 }, { WAIT_IDLE },
2477{ 0xe, 0xa7 }, { 0xf, 0x00 }, { WAIT_IDLE },
2478{ 0xe, 0xc0 }, { 0xf, 0x00 }, { WAIT_IDLE },
2479{ 0xe, 0xc1 }, { 0xf, 0x00 }, { WAIT_IDLE },
2480{ 0xe, 0xc2 }, { 0xf, 0x00 }, { WAIT_IDLE },
2481{ 0xe, 0xc3 }, { 0xf, 0x00 }, { WAIT_IDLE },
2482{ 0xe, 0xc4 }, { 0xf, 0x00 }, { WAIT_IDLE },
2483{ 0xe, 0xc5 }, { 0xf, 0x00 }, { WAIT_IDLE },
2484{ 0xe, 0xc6 }, { 0xf, 0x00 }, { WAIT_IDLE },
2485{ 0xe, 0xc7 }, { 0xf, 0x00 }, { WAIT_IDLE },
2486{ 0xe, 0xd0 }, { 0xf, 0x00 }, { WAIT_IDLE },
2487{ 0xe, 0xd1 }, { 0xf, 0x00 }, { WAIT_IDLE },
2488{ 0xe, 0xd2 }, { 0xf, 0x00 }, { WAIT_IDLE },
2489{ 0xe, 0xd3 }, { 0xf, 0x00 }, { WAIT_IDLE },
2490{ 0xe, 0xd4 }, { 0xf, 0x00 }, { WAIT_IDLE },
2491{ 0xe, 0xd5 }, { 0xf, 0x00 }, { WAIT_IDLE },
2492{ 0xe, 0xd6 }, { 0xf, 0x00 }, { WAIT_IDLE },
2493{ 0xe, 0xd7 }, { 0xf, 0x00 }, { WAIT_IDLE },
2494{ 0xe, 0xe0 }, { 0xf, 0x00 }, { WAIT_IDLE },
2495{ 0xe, 0xe1 }, { 0xf, 0x00 }, { WAIT_IDLE },
2496{ 0xe, 0xe2 }, { 0xf, 0x00 }, { WAIT_IDLE },
2497{ 0xe, 0xe3 }, { 0xf, 0x00 }, { WAIT_IDLE },
2498{ 0xe, 0xe4 }, { 0xf, 0x00 }, { WAIT_IDLE },
2499{ 0xe, 0xe5 }, { 0xf, 0x00 }, { WAIT_IDLE },
2500{ 0xe, 0xe6 }, { 0xf, 0x00 }, { WAIT_IDLE },
2501{ 0xe, 0xe7 }, { 0xf, 0x00 }, { WAIT_IDLE },
2502{ 0xe, 0x01 }, { 0xf, 0x00 }, { WAIT_IDLE },
2503{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
2504{ 0xe, 0x01 }, { 0xf, 0x01 }, { WAIT_IDLE },
2505{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
2506{ 0xe, 0x01 }, { 0xf, 0x02 }, { WAIT_IDLE },
2507{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
2508{ 0xe, 0x01 }, { 0xf, 0x03 }, { WAIT_IDLE },
2509{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
2510{ 0xe, 0x01 }, { 0xf, 0x04 }, { WAIT_IDLE },
2511{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
2512{ 0xe, 0x01 }, { 0xf, 0x05 }, { WAIT_IDLE },
2513{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
2514{ 0xe, 0x01 }, { 0xf, 0x06 }, { WAIT_IDLE },
2515{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
2516{ 0xe, 0x01 }, { 0xf, 0x07 }, { WAIT_IDLE },
2517{ 0xe, 0x02 }, { 0xf, 0x01 }, { WAIT_IDLE },
2518
2519{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2520{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2521{ 0xb, 0x07 }, { 0xa, 0x45 }, { 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
2522{ 0xb, 0x07 }, { 0xa, 0x48 }, { 0xd, 0x0f }, { 0xc, 0xff }, { WAIT_IDLE },
2523{ 0xb, 0x07 }, { 0xa, 0x7b }, { 0xd, 0x04 }, { 0xc, 0xcc }, { WAIT_IDLE },
2524{ 0xb, 0x07 }, { 0xa, 0x7d }, { 0xd, 0x04 }, { 0xc, 0xcc }, { WAIT_IDLE },
2525{ 0xb, 0x07 }, { 0xa, 0x7c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2526{ 0xb, 0x07 }, { 0xa, 0x7e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2527{ 0xb, 0x07 }, { 0xa, 0x46 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2528{ 0xb, 0x07 }, { 0xa, 0x49 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2529{ 0xb, 0x07 }, { 0xa, 0x47 }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2530{ 0xb, 0x07 }, { 0xa, 0x4a }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2531{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2532{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x00 }, { WAIT_IDLE },
2533
2534{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x00 },
2535{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x00 },
2536{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x28 },
2537{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x28 },
2538{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x51 },
2539{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x51 },
2540{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0x7a },
2541{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0x7a },
2542{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0xa3 },
2543{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0xa3 },
2544{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0xcc },
2545{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0xcc },
2546{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x00 }, { 0xc, 0xf5 },
2547{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x00 }, { 0xc, 0xf5 },
2548{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x1e },
2549{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x1e },
2550{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x47 },
2551{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x47 },
2552{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x70 },
2553{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x70 },
2554{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0x99 },
2555{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0x99 },
2556{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0xc2 },
2557{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0xc2 },
2558{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x01 }, { 0xc, 0xeb },
2559{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x01 }, { 0xc, 0xeb },
2560{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x14 },
2561{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x14 },
2562{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x3d },
2563{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x3d },
2564{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x66 },
2565{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x66 },
2566{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0x8f },
2567{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0x8f },
2568{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0xb8 },
2569{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0xb8 },
2570{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x02 }, { 0xc, 0xe1 },
2571{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x02 }, { 0xc, 0xe1 },
2572{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x0a },
2573{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x0a },
2574{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x33 },
2575{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x33 },
2576{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x5c },
2577{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x5c },
2578{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0x85 },
2579{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0x85 },
2580{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0xae },
2581{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0xae },
2582{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x03 }, { 0xc, 0xd7 },
2583{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x03 }, { 0xc, 0xd7 },
2584{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x00 },
2585{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x00 },
2586{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x28 },
2587{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x28 },
2588{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x51 },
2589{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x51 },
2590{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0x7a },
2591{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0x7a },
2592{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0xa3 },
2593{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0xa3 },
2594{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0xcc },
2595{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0xcc },
2596{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x04 }, { 0xc, 0xf5 },
2597{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x04 }, { 0xc, 0xf5 },
2598{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x1e },
2599{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x1e },
2600{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x47 },
2601{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x47 },
2602{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x70 },
2603{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x70 },
2604{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0x99 },
2605{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0x99 },
2606{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0xc2 },
2607{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0xc2 },
2608{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x05 }, { 0xc, 0xeb },
2609{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x05 }, { 0xc, 0xeb },
2610{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x14 },
2611{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x14 },
2612{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x3d },
2613{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x3d },
2614{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x66 },
2615{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x66 },
2616{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0x8f },
2617{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0x8f },
2618{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0xb8 },
2619{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0xb8 },
2620{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x06 }, { 0xc, 0xe1 },
2621{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x06 }, { 0xc, 0xe1 },
2622{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x0a },
2623{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x0a },
2624{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x33 },
2625{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x33 },
2626{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x5c },
2627{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x5c },
2628{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0x85 },
2629{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0x85 },
2630{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0xae },
2631{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0xae },
2632{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x07 }, { 0xc, 0xd7 },
2633{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x07 }, { 0xc, 0xd7 },
2634{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x00 },
2635{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x00 },
2636{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x28 },
2637{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x28 },
2638{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x51 },
2639{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x51 },
2640{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0x7a },
2641{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0x7a },
2642{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0xa3 },
2643{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0xa3 },
2644{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0xcc },
2645{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0xcc },
2646{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x08 }, { 0xc, 0xf5 },
2647{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x08 }, { 0xc, 0xf5 },
2648{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x1e },
2649{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x1e },
2650{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x47 },
2651{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x47 },
2652{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x70 },
2653{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x70 },
2654{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0x99 },
2655{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0x99 },
2656{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0xc2 },
2657{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0xc2 },
2658{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x09 }, { 0xc, 0xeb },
2659{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x09 }, { 0xc, 0xeb },
2660{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x14 },
2661{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x14 },
2662{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x3d },
2663{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x3d },
2664{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x66 },
2665{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x66 },
2666{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0x8f },
2667{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0x8f },
2668{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0xb8 },
2669{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0xb8 },
2670{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0a }, { 0xc, 0xe1 },
2671{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0a }, { 0xc, 0xe1 },
2672{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x0a },
2673{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x0a },
2674{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x33 },
2675{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x33 },
2676{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x5c },
2677{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x5c },
2678{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0x85 },
2679{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0x85 },
2680{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0xae },
2681{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0xae },
2682{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0b }, { 0xc, 0xd7 },
2683{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0b }, { 0xc, 0xd7 },
2684{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x00 },
2685{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x00 },
2686{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x28 },
2687{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x28 },
2688{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x51 },
2689{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x51 },
2690{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0x7a },
2691{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0x7a },
2692{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0xa3 },
2693{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0xa3 },
2694{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0xcc },
2695{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0xcc },
2696{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0c }, { 0xc, 0xf5 },
2697{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0c }, { 0xc, 0xf5 },
2698{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x1e },
2699{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x1e },
2700{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x47 },
2701{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x47 },
2702{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x70 },
2703{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x70 },
2704{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0x99 },
2705{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0x99 },
2706{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0xc2 },
2707{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0xc2 },
2708{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0d }, { 0xc, 0xeb },
2709{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0d }, { 0xc, 0xeb },
2710{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x14 },
2711{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x14 },
2712{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x3d },
2713{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x3d },
2714{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x66 },
2715{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x66 },
2716{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0x8f },
2717{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0x8f },
2718{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0xb8 },
2719{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0xb8 },
2720{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0e }, { 0xc, 0xe1 },
2721{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0e }, { 0xc, 0xe1 },
2722{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x0a },
2723{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x0a },
2724{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x33 },
2725{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x33 },
2726{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x5c },
2727{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x5c },
2728{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0x85 },
2729{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0x85 },
2730{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0xae },
2731{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0xae },
2732{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0xd7 },
2733{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0xd7 },
2734{ 0xb, 0x07 }, { 0xa, 0x4c }, { 0xd, 0x0f }, { 0xc, 0xff },
2735{ 0xb, 0x07 }, { 0xa, 0x4e }, { 0xd, 0x0f }, { 0xc, 0xff },
2736
2737/* mute off */
2738{ 0x8, 0x00 }, { WAIT_IDLE }
2739};
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 8a6b1803c763..1bcfb3aac18d 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -236,7 +236,7 @@ config SND_CS5535AUDIO
236config SND_DARLA20 236config SND_DARLA20
237 tristate "(Echoaudio) Darla20" 237 tristate "(Echoaudio) Darla20"
238 depends on SND 238 depends on SND
239 depends on FW_LOADER 239 select FW_LOADER
240 select SND_PCM 240 select SND_PCM
241 help 241 help
242 Say 'Y' or 'M' to include support for Echoaudio Darla. 242 Say 'Y' or 'M' to include support for Echoaudio Darla.
@@ -247,7 +247,7 @@ config SND_DARLA20
247config SND_GINA20 247config SND_GINA20
248 tristate "(Echoaudio) Gina20" 248 tristate "(Echoaudio) Gina20"
249 depends on SND 249 depends on SND
250 depends on FW_LOADER 250 select FW_LOADER
251 select SND_PCM 251 select SND_PCM
252 help 252 help
253 Say 'Y' or 'M' to include support for Echoaudio Gina. 253 Say 'Y' or 'M' to include support for Echoaudio Gina.
@@ -258,7 +258,7 @@ config SND_GINA20
258config SND_LAYLA20 258config SND_LAYLA20
259 tristate "(Echoaudio) Layla20" 259 tristate "(Echoaudio) Layla20"
260 depends on SND 260 depends on SND
261 depends on FW_LOADER 261 select FW_LOADER
262 select SND_RAWMIDI 262 select SND_RAWMIDI
263 select SND_PCM 263 select SND_PCM
264 help 264 help
@@ -270,7 +270,7 @@ config SND_LAYLA20
270config SND_DARLA24 270config SND_DARLA24
271 tristate "(Echoaudio) Darla24" 271 tristate "(Echoaudio) Darla24"
272 depends on SND 272 depends on SND
273 depends on FW_LOADER 273 select FW_LOADER
274 select SND_PCM 274 select SND_PCM
275 help 275 help
276 Say 'Y' or 'M' to include support for Echoaudio Darla24. 276 Say 'Y' or 'M' to include support for Echoaudio Darla24.
@@ -281,7 +281,7 @@ config SND_DARLA24
281config SND_GINA24 281config SND_GINA24
282 tristate "(Echoaudio) Gina24" 282 tristate "(Echoaudio) Gina24"
283 depends on SND 283 depends on SND
284 depends on FW_LOADER 284 select FW_LOADER
285 select SND_PCM 285 select SND_PCM
286 help 286 help
287 Say 'Y' or 'M' to include support for Echoaudio Gina24. 287 Say 'Y' or 'M' to include support for Echoaudio Gina24.
@@ -292,7 +292,7 @@ config SND_GINA24
292config SND_LAYLA24 292config SND_LAYLA24
293 tristate "(Echoaudio) Layla24" 293 tristate "(Echoaudio) Layla24"
294 depends on SND 294 depends on SND
295 depends on FW_LOADER 295 select FW_LOADER
296 select SND_RAWMIDI 296 select SND_RAWMIDI
297 select SND_PCM 297 select SND_PCM
298 help 298 help
@@ -304,7 +304,7 @@ config SND_LAYLA24
304config SND_MONA 304config SND_MONA
305 tristate "(Echoaudio) Mona" 305 tristate "(Echoaudio) Mona"
306 depends on SND 306 depends on SND
307 depends on FW_LOADER 307 select FW_LOADER
308 select SND_RAWMIDI 308 select SND_RAWMIDI
309 select SND_PCM 309 select SND_PCM
310 help 310 help
@@ -316,7 +316,7 @@ config SND_MONA
316config SND_MIA 316config SND_MIA
317 tristate "(Echoaudio) Mia" 317 tristate "(Echoaudio) Mia"
318 depends on SND 318 depends on SND
319 depends on FW_LOADER 319 select FW_LOADER
320 select SND_RAWMIDI 320 select SND_RAWMIDI
321 select SND_PCM 321 select SND_PCM
322 help 322 help
@@ -328,7 +328,7 @@ config SND_MIA
328config SND_ECHO3G 328config SND_ECHO3G
329 tristate "(Echoaudio) 3G cards" 329 tristate "(Echoaudio) 3G cards"
330 depends on SND 330 depends on SND
331 depends on FW_LOADER 331 select FW_LOADER
332 select SND_RAWMIDI 332 select SND_RAWMIDI
333 select SND_PCM 333 select SND_PCM
334 help 334 help
@@ -340,7 +340,7 @@ config SND_ECHO3G
340config SND_INDIGO 340config SND_INDIGO
341 tristate "(Echoaudio) Indigo" 341 tristate "(Echoaudio) Indigo"
342 depends on SND 342 depends on SND
343 depends on FW_LOADER 343 select FW_LOADER
344 select SND_PCM 344 select SND_PCM
345 help 345 help
346 Say 'Y' or 'M' to include support for Echoaudio Indigo. 346 Say 'Y' or 'M' to include support for Echoaudio Indigo.
@@ -351,7 +351,7 @@ config SND_INDIGO
351config SND_INDIGOIO 351config SND_INDIGOIO
352 tristate "(Echoaudio) Indigo IO" 352 tristate "(Echoaudio) Indigo IO"
353 depends on SND 353 depends on SND
354 depends on FW_LOADER 354 select FW_LOADER
355 select SND_PCM 355 select SND_PCM
356 help 356 help
357 Say 'Y' or 'M' to include support for Echoaudio Indigo IO. 357 Say 'Y' or 'M' to include support for Echoaudio Indigo IO.
@@ -362,7 +362,7 @@ config SND_INDIGOIO
362config SND_INDIGODJ 362config SND_INDIGODJ
363 tristate "(Echoaudio) Indigo DJ" 363 tristate "(Echoaudio) Indigo DJ"
364 depends on SND 364 depends on SND
365 depends on FW_LOADER 365 select FW_LOADER
366 select SND_PCM 366 select SND_PCM
367 help 367 help
368 Say 'Y' or 'M' to include support for Echoaudio Indigo DJ. 368 Say 'Y' or 'M' to include support for Echoaudio Indigo DJ.
@@ -373,6 +373,7 @@ config SND_INDIGODJ
373config SND_EMU10K1 373config SND_EMU10K1
374 tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)" 374 tristate "Emu10k1 (SB Live!, Audigy, E-mu APS)"
375 depends on SND 375 depends on SND
376 select FW_LOADER
376 select SND_HWDEP 377 select SND_HWDEP
377 select SND_RAWMIDI 378 select SND_RAWMIDI
378 select SND_AC97_CODEC 379 select SND_AC97_CODEC
@@ -575,6 +576,7 @@ config SND_INTEL8X0M
575config SND_KORG1212 576config SND_KORG1212
576 tristate "Korg 1212 IO" 577 tristate "Korg 1212 IO"
577 depends on SND 578 depends on SND
579 select FW_LOADER
578 select SND_PCM 580 select SND_PCM
579 help 581 help
580 Say Y here to include support for Korg 1212IO soundcards. 582 Say Y here to include support for Korg 1212IO soundcards.
@@ -585,6 +587,7 @@ config SND_KORG1212
585config SND_MAESTRO3 587config SND_MAESTRO3
586 tristate "ESS Allegro/Maestro3" 588 tristate "ESS Allegro/Maestro3"
587 depends on SND 589 depends on SND
590 select FW_LOADER
588 select SND_AC97_CODEC 591 select SND_AC97_CODEC
589 help 592 help
590 Say Y here to include support for soundcards based on ESS Maestro 3 593 Say Y here to include support for soundcards based on ESS Maestro 3
@@ -629,7 +632,7 @@ config SND_PCXHR
629config SND_RIPTIDE 632config SND_RIPTIDE
630 tristate "Conexant Riptide" 633 tristate "Conexant Riptide"
631 depends on SND 634 depends on SND
632 depends on FW_LOADER 635 select FW_LOADER
633 select SND_OPL3_LIB 636 select SND_OPL3_LIB
634 select SND_MPU401_UART 637 select SND_MPU401_UART
635 select SND_AC97_CODEC 638 select SND_AC97_CODEC
@@ -734,6 +737,7 @@ config SND_VX222
734config SND_YMFPCI 737config SND_YMFPCI
735 tristate "Yamaha YMF724/740/744/754" 738 tristate "Yamaha YMF724/740/744/754"
736 depends on SND 739 depends on SND
740 select FW_LOADER
737 select SND_OPL3_LIB 741 select SND_OPL3_LIB
738 select SND_MPU401_UART 742 select SND_MPU401_UART
739 select SND_AC97_CODEC 743 select SND_AC97_CODEC
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index d2994cb4c8c9..74ed81081478 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -111,7 +111,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
111{ 0x41445372, 0xffffffff, "AD1981A", patch_ad1981a, NULL }, 111{ 0x41445372, 0xffffffff, "AD1981A", patch_ad1981a, NULL },
112{ 0x41445374, 0xffffffff, "AD1981B", patch_ad1981b, NULL }, 112{ 0x41445374, 0xffffffff, "AD1981B", patch_ad1981b, NULL },
113{ 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL }, 113{ 0x41445375, 0xffffffff, "AD1985", patch_ad1985, NULL },
114{ 0x41445378, 0xffffffff, "AD1986", patch_ad1985, NULL }, 114{ 0x41445378, 0xffffffff, "AD1986", patch_ad1986, NULL },
115{ 0x414c4300, 0xffffff00, "ALC100,100P", NULL, NULL }, 115{ 0x414c4300, 0xffffff00, "ALC100,100P", NULL, NULL },
116{ 0x414c4710, 0xfffffff0, "ALC200,200P", NULL, NULL }, 116{ 0x414c4710, 0xfffffff0, "ALC200,200P", NULL, NULL },
117{ 0x414c4721, 0xffffffff, "ALC650D", NULL, NULL }, /* already patched */ 117{ 0x414c4721, 0xffffffff, "ALC650D", NULL, NULL }, /* already patched */
@@ -194,6 +194,13 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
194 194
195 195
196static void update_power_regs(struct snd_ac97 *ac97); 196static void update_power_regs(struct snd_ac97 *ac97);
197#ifdef CONFIG_SND_AC97_POWER_SAVE
198#define ac97_is_power_save_mode(ac97) \
199 ((ac97->scaps & AC97_SCAP_POWER_SAVE) && power_save)
200#else
201#define ac97_is_power_save_mode(ac97) 0
202#endif
203
197 204
198/* 205/*
199 * I/O routines 206 * I/O routines
@@ -982,8 +989,8 @@ static int snd_ac97_free(struct snd_ac97 *ac97)
982{ 989{
983 if (ac97) { 990 if (ac97) {
984#ifdef CONFIG_SND_AC97_POWER_SAVE 991#ifdef CONFIG_SND_AC97_POWER_SAVE
985 if (ac97->power_workq) 992 cancel_delayed_work(&ac97->power_work);
986 destroy_workqueue(ac97->power_workq); 993 flush_scheduled_work();
987#endif 994#endif
988 snd_ac97_proc_done(ac97); 995 snd_ac97_proc_done(ac97);
989 if (ac97->bus) 996 if (ac97->bus)
@@ -1184,13 +1191,13 @@ static int snd_ac97_cmute_new_stereo(struct snd_card *card, char *name, int reg,
1184/* 1191/*
1185 * set dB information 1192 * set dB information
1186 */ 1193 */
1187static DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0); 1194static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
1188static DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0); 1195static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
1189static DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0); 1196static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
1190static DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0); 1197static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
1191static DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0); 1198static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
1192 1199
1193static unsigned int *find_db_scale(unsigned int maxval) 1200static const unsigned int *find_db_scale(unsigned int maxval)
1194{ 1201{
1195 switch (maxval) { 1202 switch (maxval) {
1196 case 0x0f: return db_scale_4bit; 1203 case 0x0f: return db_scale_4bit;
@@ -1200,8 +1207,8 @@ static unsigned int *find_db_scale(unsigned int maxval)
1200 return NULL; 1207 return NULL;
1201} 1208}
1202 1209
1203static void set_tlv_db_scale(struct snd_kcontrol *kctl, unsigned int *tlv) 1210static void set_tlv_db_scale(struct snd_kcontrol *kctl, const unsigned int *tlv)
1204{ 1211{
1205 kctl->tlv.p = tlv; 1212 kctl->tlv.p = tlv;
1206 if (tlv) 1213 if (tlv)
1207 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ; 1214 kctl->vd[0].access |= SNDRV_CTL_ELEM_ACCESS_TLV_READ;
@@ -1989,7 +1996,6 @@ int snd_ac97_mixer(struct snd_ac97_bus *bus, struct snd_ac97_template *template,
1989 mutex_init(&ac97->reg_mutex); 1996 mutex_init(&ac97->reg_mutex);
1990 mutex_init(&ac97->page_mutex); 1997 mutex_init(&ac97->page_mutex);
1991#ifdef CONFIG_SND_AC97_POWER_SAVE 1998#ifdef CONFIG_SND_AC97_POWER_SAVE
1992 ac97->power_workq = create_workqueue("ac97");
1993 INIT_DELAYED_WORK(&ac97->power_work, do_update_power); 1999 INIT_DELAYED_WORK(&ac97->power_work, do_update_power);
1994#endif 2000#endif
1995 2001
@@ -2275,15 +2281,13 @@ static void snd_ac97_powerdown(struct snd_ac97 *ac97)
2275 udelay(100); 2281 udelay(100);
2276 power |= AC97_PD_PR2 | AC97_PD_PR3; /* Analog Mixer powerdown */ 2282 power |= AC97_PD_PR2 | AC97_PD_PR3; /* Analog Mixer powerdown */
2277 snd_ac97_write(ac97, AC97_POWERDOWN, power); 2283 snd_ac97_write(ac97, AC97_POWERDOWN, power);
2278#ifdef CONFIG_SND_AC97_POWER_SAVE 2284 if (ac97_is_power_save_mode(ac97)) {
2279 if (power_save) {
2280 udelay(100); 2285 udelay(100);
2281 /* AC-link powerdown, internal Clk disable */ 2286 /* AC-link powerdown, internal Clk disable */
2282 /* FIXME: this may cause click noises on some boards */ 2287 /* FIXME: this may cause click noises on some boards */
2283 power |= AC97_PD_PR4 | AC97_PD_PR5; 2288 power |= AC97_PD_PR4 | AC97_PD_PR5;
2284 snd_ac97_write(ac97, AC97_POWERDOWN, power); 2289 snd_ac97_write(ac97, AC97_POWERDOWN, power);
2285 } 2290 }
2286#endif
2287} 2291}
2288 2292
2289 2293
@@ -2337,14 +2341,16 @@ int snd_ac97_update_power(struct snd_ac97 *ac97, int reg, int powerup)
2337 } 2341 }
2338 } 2342 }
2339 2343
2340 if (power_save && !powerup && ac97->power_workq) 2344 if (ac97_is_power_save_mode(ac97) && !powerup)
2341 /* adjust power-down bits after two seconds delay 2345 /* adjust power-down bits after two seconds delay
2342 * (for avoiding loud click noises for many (OSS) apps 2346 * (for avoiding loud click noises for many (OSS) apps
2343 * that open/close frequently) 2347 * that open/close frequently)
2344 */ 2348 */
2345 queue_delayed_work(ac97->power_workq, &ac97->power_work, HZ*2); 2349 schedule_delayed_work(&ac97->power_work, HZ*2);
2346 else 2350 else {
2351 cancel_delayed_work(&ac97->power_work);
2347 update_power_regs(ac97); 2352 update_power_regs(ac97);
2353 }
2348 2354
2349 return 0; 2355 return 0;
2350} 2356}
@@ -2357,19 +2363,15 @@ static void update_power_regs(struct snd_ac97 *ac97)
2357 unsigned int power_up, bits; 2363 unsigned int power_up, bits;
2358 int i; 2364 int i;
2359 2365
2366 power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC);
2367 power_up |= (1 << PWIDX_MIC);
2368 if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
2369 power_up |= (1 << PWIDX_SURR);
2370 if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
2371 power_up |= (1 << PWIDX_CLFE);
2360#ifdef CONFIG_SND_AC97_POWER_SAVE 2372#ifdef CONFIG_SND_AC97_POWER_SAVE
2361 if (power_save) 2373 if (ac97_is_power_save_mode(ac97))
2362 power_up = ac97->power_up; 2374 power_up = ac97->power_up;
2363 else {
2364#endif
2365 power_up = (1 << PWIDX_FRONT) | (1 << PWIDX_ADC);
2366 power_up |= (1 << PWIDX_MIC);
2367 if (ac97->scaps & AC97_SCAP_SURROUND_DAC)
2368 power_up |= (1 << PWIDX_SURR);
2369 if (ac97->scaps & AC97_SCAP_CENTER_LFE_DAC)
2370 power_up |= (1 << PWIDX_CLFE);
2371#ifdef CONFIG_SND_AC97_POWER_SAVE
2372 }
2373#endif 2375#endif
2374 if (power_up) { 2376 if (power_up) {
2375 if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) { 2377 if (ac97->regs[AC97_POWERDOWN] & AC97_PD_PR2) {
@@ -2414,6 +2416,10 @@ void snd_ac97_suspend(struct snd_ac97 *ac97)
2414 return; 2416 return;
2415 if (ac97->build_ops->suspend) 2417 if (ac97->build_ops->suspend)
2416 ac97->build_ops->suspend(ac97); 2418 ac97->build_ops->suspend(ac97);
2419#ifdef CONFIG_SND_AC97_POWER_SAVE
2420 cancel_delayed_work(&ac97->power_work);
2421 flush_scheduled_work();
2422#endif
2417 snd_ac97_powerdown(ac97); 2423 snd_ac97_powerdown(ac97);
2418} 2424}
2419 2425
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index e813968e0cf8..641d0c8d659e 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -54,7 +54,7 @@ static int patch_build_controls(struct snd_ac97 * ac97, const struct snd_kcontro
54 54
55/* replace with a new TLV */ 55/* replace with a new TLV */
56static void reset_tlv(struct snd_ac97 *ac97, const char *name, 56static void reset_tlv(struct snd_ac97 *ac97, const char *name,
57 unsigned int *tlv) 57 const unsigned int *tlv)
58{ 58{
59 struct snd_ctl_elem_id sid; 59 struct snd_ctl_elem_id sid;
60 struct snd_kcontrol *kctl; 60 struct snd_kcontrol *kctl;
@@ -190,14 +190,28 @@ static inline int is_clfe_on(struct snd_ac97 *ac97)
190 return ac97->channel_mode >= 2; 190 return ac97->channel_mode >= 2;
191} 191}
192 192
193/* system has shared jacks with surround out enabled */
194static inline int is_shared_surrout(struct snd_ac97 *ac97)
195{
196 return !ac97->indep_surround && is_surround_on(ac97);
197}
198
199/* system has shared jacks with center/lfe out enabled */
200static inline int is_shared_clfeout(struct snd_ac97 *ac97)
201{
202 return !ac97->indep_surround && is_clfe_on(ac97);
203}
204
205/* system has shared jacks with line in enabled */
193static inline int is_shared_linein(struct snd_ac97 *ac97) 206static inline int is_shared_linein(struct snd_ac97 *ac97)
194{ 207{
195 return ! ac97->indep_surround && is_surround_on(ac97); 208 return !ac97->indep_surround && !is_surround_on(ac97);
196} 209}
197 210
211/* system has shared jacks with mic in enabled */
198static inline int is_shared_micin(struct snd_ac97 *ac97) 212static inline int is_shared_micin(struct snd_ac97 *ac97)
199{ 213{
200 return ! ac97->indep_surround && is_clfe_on(ac97); 214 return !ac97->indep_surround && !is_clfe_on(ac97);
201} 215}
202 216
203 217
@@ -941,6 +955,9 @@ static int patch_sigmatel_stac9708_specific(struct snd_ac97 *ac97)
941{ 955{
942 int err; 956 int err;
943 957
958 /* the register bit is writable, but the function is not implemented: */
959 snd_ac97_remove_ctl(ac97, "PCM Out Path & Mute", NULL);
960
944 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback"); 961 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Sigmatel Surround Playback");
945 if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0) 962 if ((err = patch_build_controls(ac97, &snd_ac97_stac9708_bias_control, 1)) < 0)
946 return err; 963 return err;
@@ -1552,7 +1569,7 @@ static const struct snd_kcontrol_new snd_ac97_controls_ad1885[] = {
1552 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */ 1569 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 8, 1, 1), /* inverted */
1553}; 1570};
1554 1571
1555static DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0); 1572static const DECLARE_TLV_DB_SCALE(db_scale_6bit_6db_max, -8850, 150, 0);
1556 1573
1557static int patch_ad1885_specific(struct snd_ac97 * ac97) 1574static int patch_ad1885_specific(struct snd_ac97 * ac97)
1558{ 1575{
@@ -1609,19 +1626,22 @@ int patch_ad1886(struct snd_ac97 * ac97)
1609 return 0; 1626 return 0;
1610} 1627}
1611 1628
1612/* MISC bits */ 1629/* MISC bits (AD1888/AD1980/AD1985 register 0x76) */
1613#define AC97_AD198X_MBC 0x0003 /* mic boost */ 1630#define AC97_AD198X_MBC 0x0003 /* mic boost */
1614#define AC97_AD198X_MBC_20 0x0000 /* +20dB */ 1631#define AC97_AD198X_MBC_20 0x0000 /* +20dB */
1615#define AC97_AD198X_MBC_10 0x0001 /* +10dB */ 1632#define AC97_AD198X_MBC_10 0x0001 /* +10dB */
1616#define AC97_AD198X_MBC_30 0x0002 /* +30dB */ 1633#define AC97_AD198X_MBC_30 0x0002 /* +30dB */
1617#define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */ 1634#define AC97_AD198X_VREFD 0x0004 /* VREF high-Z */
1618#define AC97_AD198X_VREFH 0x0008 /* 2.25V, 3.7V */ 1635#define AC97_AD198X_VREFH 0x0008 /* 0=2.25V, 1=3.7V */
1619#define AC97_AD198X_VREF_0 0x000c /* 0V */ 1636#define AC97_AD198X_VREF_0 0x000c /* 0V (AD1985 only) */
1637#define AC97_AD198X_VREF_MASK (AC97_AD198X_VREFH | AC97_AD198X_VREFD)
1638#define AC97_AD198X_VREF_SHIFT 2
1620#define AC97_AD198X_SRU 0x0010 /* sample rate unlock */ 1639#define AC97_AD198X_SRU 0x0010 /* sample rate unlock */
1621#define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */ 1640#define AC97_AD198X_LOSEL 0x0020 /* LINE_OUT amplifiers input select */
1622#define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */ 1641#define AC97_AD198X_2MIC 0x0040 /* 2-channel mic select */
1623#define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */ 1642#define AC97_AD198X_SPRD 0x0080 /* SPREAD enable */
1624#define AC97_AD198X_DMIX0 0x0100 /* downmix mode: 0 = 6-to-4, 1 = 6-to-2 downmix */ 1643#define AC97_AD198X_DMIX0 0x0100 /* downmix mode: */
1644 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1625#define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */ 1645#define AC97_AD198X_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1626#define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */ 1646#define AC97_AD198X_HPSEL 0x0400 /* headphone amplifier input select */
1627#define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */ 1647#define AC97_AD198X_CLDIS 0x0800 /* center/lfe disable */
@@ -1630,6 +1650,83 @@ int patch_ad1886(struct snd_ac97 * ac97)
1630#define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */ 1650#define AC97_AD198X_AC97NC 0x4000 /* AC97 no compatible mode */
1631#define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */ 1651#define AC97_AD198X_DACZ 0x8000 /* DAC zero-fill mode */
1632 1652
1653/* MISC 1 bits (AD1986 register 0x76) */
1654#define AC97_AD1986_MBC 0x0003 /* mic boost */
1655#define AC97_AD1986_MBC_20 0x0000 /* +20dB */
1656#define AC97_AD1986_MBC_10 0x0001 /* +10dB */
1657#define AC97_AD1986_MBC_30 0x0002 /* +30dB */
1658#define AC97_AD1986_LISEL0 0x0004 /* LINE_IN select bit 0 */
1659#define AC97_AD1986_LISEL1 0x0008 /* LINE_IN select bit 1 */
1660#define AC97_AD1986_LISEL_MASK (AC97_AD1986_LISEL1 | AC97_AD1986_LISEL0)
1661#define AC97_AD1986_LISEL_LI 0x0000 /* LINE_IN pins as LINE_IN source */
1662#define AC97_AD1986_LISEL_SURR 0x0004 /* SURROUND pins as LINE_IN source */
1663#define AC97_AD1986_LISEL_MIC 0x0008 /* MIC_1/2 pins as LINE_IN source */
1664#define AC97_AD1986_SRU 0x0010 /* sample rate unlock */
1665#define AC97_AD1986_SOSEL 0x0020 /* SURROUND_OUT amplifiers input sel */
1666#define AC97_AD1986_2MIC 0x0040 /* 2-channel mic select */
1667#define AC97_AD1986_SPRD 0x0080 /* SPREAD enable */
1668#define AC97_AD1986_DMIX0 0x0100 /* downmix mode: */
1669 /* 0 = 6-to-4, 1 = 6-to-2 downmix */
1670#define AC97_AD1986_DMIX1 0x0200 /* downmix mode: 1 = enabled */
1671#define AC97_AD1986_CLDIS 0x0800 /* center/lfe disable */
1672#define AC97_AD1986_SODIS 0x1000 /* SURROUND_OUT disable */
1673#define AC97_AD1986_MSPLT 0x2000 /* mute split (read only 1) */
1674#define AC97_AD1986_AC97NC 0x4000 /* AC97 no compatible mode (r/o 1) */
1675#define AC97_AD1986_DACZ 0x8000 /* DAC zero-fill mode */
1676
1677/* MISC 2 bits (AD1986 register 0x70) */
1678#define AC97_AD_MISC2 0x70 /* Misc Control Bits 2 (AD1986) */
1679
1680#define AC97_AD1986_CVREF0 0x0004 /* C/LFE VREF_OUT 2.25V */
1681#define AC97_AD1986_CVREF1 0x0008 /* C/LFE VREF_OUT 0V */
1682#define AC97_AD1986_CVREF2 0x0010 /* C/LFE VREF_OUT 3.7V */
1683#define AC97_AD1986_CVREF_MASK \
1684 (AC97_AD1986_CVREF2 | AC97_AD1986_CVREF1 | AC97_AD1986_CVREF0)
1685#define AC97_AD1986_JSMAP 0x0020 /* Jack Sense Mapping 1 = alternate */
1686#define AC97_AD1986_MMDIS 0x0080 /* Mono Mute Disable */
1687#define AC97_AD1986_MVREF0 0x0400 /* MIC VREF_OUT 2.25V */
1688#define AC97_AD1986_MVREF1 0x0800 /* MIC VREF_OUT 0V */
1689#define AC97_AD1986_MVREF2 0x1000 /* MIC VREF_OUT 3.7V */
1690#define AC97_AD1986_MVREF_MASK \
1691 (AC97_AD1986_MVREF2 | AC97_AD1986_MVREF1 | AC97_AD1986_MVREF0)
1692
1693/* MISC 3 bits (AD1986 register 0x7a) */
1694#define AC97_AD_MISC3 0x7a /* Misc Control Bits 3 (AD1986) */
1695
1696#define AC97_AD1986_MMIX 0x0004 /* Mic Mix, left/right */
1697#define AC97_AD1986_GPO 0x0008 /* General Purpose Out */
1698#define AC97_AD1986_LOHPEN 0x0010 /* LINE_OUT headphone drive */
1699#define AC97_AD1986_LVREF0 0x0100 /* LINE_OUT VREF_OUT 2.25V */
1700#define AC97_AD1986_LVREF1 0x0200 /* LINE_OUT VREF_OUT 0V */
1701#define AC97_AD1986_LVREF2 0x0400 /* LINE_OUT VREF_OUT 3.7V */
1702#define AC97_AD1986_LVREF_MASK \
1703 (AC97_AD1986_LVREF2 | AC97_AD1986_LVREF1 | AC97_AD1986_LVREF0)
1704#define AC97_AD1986_JSINVA 0x0800 /* Jack Sense Invert SENSE_A */
1705#define AC97_AD1986_LOSEL 0x1000 /* LINE_OUT amplifiers input select */
1706#define AC97_AD1986_HPSEL0 0x2000 /* Headphone amplifiers */
1707 /* input select Surround DACs */
1708#define AC97_AD1986_HPSEL1 0x4000 /* Headphone amplifiers input */
1709 /* select C/LFE DACs */
1710#define AC97_AD1986_JSINVB 0x8000 /* Jack Sense Invert SENSE_B */
1711
1712/* Serial Config bits (AD1986 register 0x74) (incomplete) */
1713#define AC97_AD1986_OMS0 0x0100 /* Optional Mic Selector bit 0 */
1714#define AC97_AD1986_OMS1 0x0200 /* Optional Mic Selector bit 1 */
1715#define AC97_AD1986_OMS2 0x0400 /* Optional Mic Selector bit 2 */
1716#define AC97_AD1986_OMS_MASK \
1717 (AC97_AD1986_OMS2 | AC97_AD1986_OMS1 | AC97_AD1986_OMS0)
1718#define AC97_AD1986_OMS_M 0x0000 /* MIC_1/2 pins are MIC sources */
1719#define AC97_AD1986_OMS_L 0x0100 /* LINE_IN pins are MIC sources */
1720#define AC97_AD1986_OMS_C 0x0200 /* Center/LFE pins are MCI sources */
1721#define AC97_AD1986_OMS_MC 0x0400 /* Mix of MIC and C/LFE pins */
1722 /* are MIC sources */
1723#define AC97_AD1986_OMS_ML 0x0500 /* MIX of MIC and LINE_IN pins */
1724 /* are MIC sources */
1725#define AC97_AD1986_OMS_LC 0x0600 /* MIX of LINE_IN and C/LFE pins */
1726 /* are MIC sources */
1727#define AC97_AD1986_OMS_MLC 0x0700 /* MIX of MIC, LINE_IN, C/LFE pins */
1728 /* are MIC sources */
1729
1633 1730
1634static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1731static int snd_ac97_ad198x_spdif_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1635{ 1732{
@@ -1952,8 +2049,80 @@ int patch_ad1980(struct snd_ac97 * ac97)
1952 return 0; 2049 return 0;
1953} 2050}
1954 2051
2052static int snd_ac97_ad1985_vrefout_info(struct snd_kcontrol *kcontrol,
2053 struct snd_ctl_elem_info *uinfo)
2054{
2055 static char *texts[4] = {"High-Z", "3.7 V", "2.25 V", "0 V"};
2056
2057 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2058 uinfo->count = 1;
2059 uinfo->value.enumerated.items = 4;
2060 if (uinfo->value.enumerated.item > 3)
2061 uinfo->value.enumerated.item = 3;
2062 strcpy(uinfo->value.enumerated.name,
2063 texts[uinfo->value.enumerated.item]);
2064 return 0;
2065}
2066
2067static int snd_ac97_ad1985_vrefout_get(struct snd_kcontrol *kcontrol,
2068 struct snd_ctl_elem_value *ucontrol)
2069{
2070 static const int reg2ctrl[4] = {2, 0, 1, 3};
2071 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2072 unsigned short val;
2073 val = (ac97->regs[AC97_AD_MISC] & AC97_AD198X_VREF_MASK)
2074 >> AC97_AD198X_VREF_SHIFT;
2075 ucontrol->value.enumerated.item[0] = reg2ctrl[val];
2076 return 0;
2077}
2078
2079static int snd_ac97_ad1985_vrefout_put(struct snd_kcontrol *kcontrol,
2080 struct snd_ctl_elem_value *ucontrol)
2081{
2082 static const int ctrl2reg[4] = {1, 2, 0, 3};
2083 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2084 unsigned short val;
2085
2086 if (ucontrol->value.enumerated.item[0] > 3
2087 || ucontrol->value.enumerated.item[0] < 0)
2088 return -EINVAL;
2089 val = ctrl2reg[ucontrol->value.enumerated.item[0]]
2090 << AC97_AD198X_VREF_SHIFT;
2091 return snd_ac97_update_bits(ac97, AC97_AD_MISC,
2092 AC97_AD198X_VREF_MASK, val);
2093}
2094
1955static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = { 2095static const struct snd_kcontrol_new snd_ac97_ad1985_controls[] = {
1956 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0) 2096 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2097 {
2098 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2099 .name = "Exchange Front/Surround",
2100 .info = snd_ac97_ad1888_lohpsel_info,
2101 .get = snd_ac97_ad1888_lohpsel_get,
2102 .put = snd_ac97_ad1888_lohpsel_put
2103 },
2104 AC97_SINGLE("High Pass Filter Enable", AC97_AD_TEST2, 12, 1, 1),
2105 AC97_SINGLE("Spread Front to Surround and Center/LFE",
2106 AC97_AD_MISC, 7, 1, 0),
2107 {
2108 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2109 .name = "Downmix",
2110 .info = snd_ac97_ad1888_downmix_info,
2111 .get = snd_ac97_ad1888_downmix_get,
2112 .put = snd_ac97_ad1888_downmix_put
2113 },
2114 {
2115 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2116 .name = "V_REFOUT",
2117 .info = snd_ac97_ad1985_vrefout_info,
2118 .get = snd_ac97_ad1985_vrefout_get,
2119 .put = snd_ac97_ad1985_vrefout_put
2120 },
2121 AC97_SURROUND_JACK_MODE_CTL,
2122 AC97_CHANNEL_MODE_CTL,
2123
2124 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2125 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0),
1957}; 2126};
1958 2127
1959static void ad1985_update_jacks(struct snd_ac97 *ac97) 2128static void ad1985_update_jacks(struct snd_ac97 *ac97)
@@ -1967,9 +2136,16 @@ static int patch_ad1985_specific(struct snd_ac97 *ac97)
1967{ 2136{
1968 int err; 2137 int err;
1969 2138
1970 if ((err = patch_ad1980_specific(ac97)) < 0) 2139 /* rename 0x04 as "Master" and 0x02 as "Master Surround" */
2140 snd_ac97_rename_vol_ctl(ac97, "Master Playback",
2141 "Master Surround Playback");
2142 snd_ac97_rename_vol_ctl(ac97, "Headphone Playback", "Master Playback");
2143
2144 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
1971 return err; 2145 return err;
1972 return patch_build_controls(ac97, snd_ac97_ad1985_controls, ARRAY_SIZE(snd_ac97_ad1985_controls)); 2146
2147 return patch_build_controls(ac97, snd_ac97_ad1985_controls,
2148 ARRAY_SIZE(snd_ac97_ad1985_controls));
1973} 2149}
1974 2150
1975static struct snd_ac97_build_ops patch_ad1985_build_ops = { 2151static struct snd_ac97_build_ops patch_ad1985_build_ops = {
@@ -1989,24 +2165,311 @@ int patch_ad1985(struct snd_ac97 * ac97)
1989 ac97->build_ops = &patch_ad1985_build_ops; 2165 ac97->build_ops = &patch_ad1985_build_ops;
1990 misc = snd_ac97_read(ac97, AC97_AD_MISC); 2166 misc = snd_ac97_read(ac97, AC97_AD_MISC);
1991 /* switch front/surround line-out/hp-out */ 2167 /* switch front/surround line-out/hp-out */
1992 /* center/LFE, mic in 3.75V mode */
1993 /* AD-compatible mode */ 2168 /* AD-compatible mode */
1994 /* Stereo mutes enabled */ 2169 /* Stereo mutes enabled */
1995 /* in accordance with ADI driver: misc | 0x5c28 */
1996 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc | 2170 snd_ac97_write_cache(ac97, AC97_AD_MISC, misc |
1997 AC97_AD198X_VREFH |
1998 AC97_AD198X_LOSEL | 2171 AC97_AD198X_LOSEL |
1999 AC97_AD198X_HPSEL | 2172 AC97_AD198X_HPSEL |
2000 AC97_AD198X_CLDIS |
2001 AC97_AD198X_LODIS |
2002 AC97_AD198X_MSPLT | 2173 AC97_AD198X_MSPLT |
2003 AC97_AD198X_AC97NC); 2174 AC97_AD198X_AC97NC);
2004 ac97->flags |= AC97_STEREO_MUTES; 2175 ac97->flags |= AC97_STEREO_MUTES;
2176
2177 /* update current jack configuration */
2178 ad1985_update_jacks(ac97);
2179
2005 /* on AD1985 rev. 3, AC'97 revision bits are zero */ 2180 /* on AD1985 rev. 3, AC'97 revision bits are zero */
2006 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23; 2181 ac97->ext_id = (ac97->ext_id & ~AC97_EI_REV_MASK) | AC97_EI_REV_23;
2007 return 0; 2182 return 0;
2008} 2183}
2009 2184
2185static int snd_ac97_ad1986_bool_info(struct snd_kcontrol *kcontrol,
2186 struct snd_ctl_elem_info *uinfo)
2187{
2188 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2189 uinfo->count = 1;
2190 uinfo->value.integer.min = 0;
2191 uinfo->value.integer.max = 1;
2192 return 0;
2193}
2194
2195static int snd_ac97_ad1986_lososel_get(struct snd_kcontrol *kcontrol,
2196 struct snd_ctl_elem_value *ucontrol)
2197{
2198 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2199 unsigned short val;
2200
2201 val = ac97->regs[AC97_AD_MISC3];
2202 ucontrol->value.integer.value[0] = (val & AC97_AD1986_LOSEL) != 0;
2203 return 0;
2204}
2205
2206static int snd_ac97_ad1986_lososel_put(struct snd_kcontrol *kcontrol,
2207 struct snd_ctl_elem_value *ucontrol)
2208{
2209 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2210 int ret0;
2211 int ret1;
2212 int sprd = (ac97->regs[AC97_AD_MISC] & AC97_AD1986_SPRD) != 0;
2213
2214 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC3, AC97_AD1986_LOSEL,
2215 ucontrol->value.integer.value[0] != 0
2216 ? AC97_AD1986_LOSEL : 0);
2217 if (ret0 < 0)
2218 return ret0;
2219
2220 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2221 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2222 (ucontrol->value.integer.value[0] != 0
2223 || sprd)
2224 ? AC97_AD1986_SOSEL : 0);
2225 if (ret1 < 0)
2226 return ret1;
2227
2228 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2229}
2230
2231static int snd_ac97_ad1986_spread_get(struct snd_kcontrol *kcontrol,
2232 struct snd_ctl_elem_value *ucontrol)
2233{
2234 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2235 unsigned short val;
2236
2237 val = ac97->regs[AC97_AD_MISC];
2238 ucontrol->value.integer.value[0] = (val & AC97_AD1986_SPRD) != 0;
2239 return 0;
2240}
2241
2242static int snd_ac97_ad1986_spread_put(struct snd_kcontrol *kcontrol,
2243 struct snd_ctl_elem_value *ucontrol)
2244{
2245 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2246 int ret0;
2247 int ret1;
2248 int sprd = (ac97->regs[AC97_AD_MISC3] & AC97_AD1986_LOSEL) != 0;
2249
2250 ret0 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SPRD,
2251 ucontrol->value.integer.value[0] != 0
2252 ? AC97_AD1986_SPRD : 0);
2253 if (ret0 < 0)
2254 return ret0;
2255
2256 /* SOSEL is set to values of "Spread" or "Exchange F/S" controls */
2257 ret1 = snd_ac97_update_bits(ac97, AC97_AD_MISC, AC97_AD1986_SOSEL,
2258 (ucontrol->value.integer.value[0] != 0
2259 || sprd)
2260 ? AC97_AD1986_SOSEL : 0);
2261 if (ret1 < 0)
2262 return ret1;
2263
2264 return (ret0 > 0 || ret1 > 0) ? 1 : 0;
2265}
2266
2267static int snd_ac97_ad1986_miclisel_get(struct snd_kcontrol *kcontrol,
2268 struct snd_ctl_elem_value *ucontrol)
2269{
2270 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2271
2272 ucontrol->value.integer.value[0] = ac97->spec.ad18xx.swap_mic_linein;
2273 return 0;
2274}
2275
2276static int snd_ac97_ad1986_miclisel_put(struct snd_kcontrol *kcontrol,
2277 struct snd_ctl_elem_value *ucontrol)
2278{
2279 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2280 unsigned char swap = ucontrol->value.integer.value[0] != 0;
2281
2282 if (swap != ac97->spec.ad18xx.swap_mic_linein) {
2283 ac97->spec.ad18xx.swap_mic_linein = swap;
2284 if (ac97->build_ops->update_jacks)
2285 ac97->build_ops->update_jacks(ac97);
2286 return 1;
2287 }
2288 return 0;
2289}
2290
2291static int snd_ac97_ad1986_vrefout_get(struct snd_kcontrol *kcontrol,
2292 struct snd_ctl_elem_value *ucontrol)
2293{
2294 /* Use MIC_1/2 V_REFOUT as the "get" value */
2295 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2296 unsigned short val;
2297 unsigned short reg = ac97->regs[AC97_AD_MISC2];
2298 if ((reg & AC97_AD1986_MVREF0) != 0)
2299 val = 2;
2300 else if ((reg & AC97_AD1986_MVREF1) != 0)
2301 val = 3;
2302 else if ((reg & AC97_AD1986_MVREF2) != 0)
2303 val = 1;
2304 else
2305 val = 0;
2306 ucontrol->value.enumerated.item[0] = val;
2307 return 0;
2308}
2309
2310static int snd_ac97_ad1986_vrefout_put(struct snd_kcontrol *kcontrol,
2311 struct snd_ctl_elem_value *ucontrol)
2312{
2313 struct snd_ac97 *ac97 = snd_kcontrol_chip(kcontrol);
2314 unsigned short cval;
2315 unsigned short lval;
2316 unsigned short mval;
2317 int cret;
2318 int lret;
2319 int mret;
2320
2321 switch (ucontrol->value.enumerated.item[0])
2322 {
2323 case 0: /* High-Z */
2324 cval = 0;
2325 lval = 0;
2326 mval = 0;
2327 break;
2328 case 1: /* 3.7 V */
2329 cval = AC97_AD1986_CVREF2;
2330 lval = AC97_AD1986_LVREF2;
2331 mval = AC97_AD1986_MVREF2;
2332 break;
2333 case 2: /* 2.25 V */
2334 cval = AC97_AD1986_CVREF0;
2335 lval = AC97_AD1986_LVREF0;
2336 mval = AC97_AD1986_MVREF0;
2337 break;
2338 case 3: /* 0 V */
2339 cval = AC97_AD1986_CVREF1;
2340 lval = AC97_AD1986_LVREF1;
2341 mval = AC97_AD1986_MVREF1;
2342 break;
2343 default:
2344 return -EINVAL;
2345 }
2346
2347 cret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2348 AC97_AD1986_CVREF_MASK, cval);
2349 if (cret < 0)
2350 return cret;
2351 lret = snd_ac97_update_bits(ac97, AC97_AD_MISC3,
2352 AC97_AD1986_LVREF_MASK, lval);
2353 if (lret < 0)
2354 return lret;
2355 mret = snd_ac97_update_bits(ac97, AC97_AD_MISC2,
2356 AC97_AD1986_MVREF_MASK, mval);
2357 if (mret < 0)
2358 return mret;
2359
2360 return (cret > 0 || lret > 0 || mret > 0) ? 1 : 0;
2361}
2362
2363static const struct snd_kcontrol_new snd_ac97_ad1986_controls[] = {
2364 AC97_SINGLE("Exchange Center/LFE", AC97_AD_SERIAL_CFG, 3, 1, 0),
2365 {
2366 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2367 .name = "Exchange Front/Surround",
2368 .info = snd_ac97_ad1986_bool_info,
2369 .get = snd_ac97_ad1986_lososel_get,
2370 .put = snd_ac97_ad1986_lososel_put
2371 },
2372 {
2373 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2374 .name = "Exchange Mic/Line In",
2375 .info = snd_ac97_ad1986_bool_info,
2376 .get = snd_ac97_ad1986_miclisel_get,
2377 .put = snd_ac97_ad1986_miclisel_put
2378 },
2379 {
2380 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2381 .name = "Spread Front to Surround and Center/LFE",
2382 .info = snd_ac97_ad1986_bool_info,
2383 .get = snd_ac97_ad1986_spread_get,
2384 .put = snd_ac97_ad1986_spread_put
2385 },
2386 {
2387 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2388 .name = "Downmix",
2389 .info = snd_ac97_ad1888_downmix_info,
2390 .get = snd_ac97_ad1888_downmix_get,
2391 .put = snd_ac97_ad1888_downmix_put
2392 },
2393 {
2394 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2395 .name = "V_REFOUT",
2396 .info = snd_ac97_ad1985_vrefout_info,
2397 .get = snd_ac97_ad1986_vrefout_get,
2398 .put = snd_ac97_ad1986_vrefout_put
2399 },
2400 AC97_SURROUND_JACK_MODE_CTL,
2401 AC97_CHANNEL_MODE_CTL,
2402
2403 AC97_SINGLE("Headphone Jack Sense", AC97_AD_JACK_SPDIF, 10, 1, 0),
2404 AC97_SINGLE("Line Jack Sense", AC97_AD_JACK_SPDIF, 12, 1, 0)
2405};
2406
2407static void ad1986_update_jacks(struct snd_ac97 *ac97)
2408{
2409 unsigned short misc_val = 0;
2410 unsigned short ser_val;
2411
2412 /* disable SURROUND and CENTER/LFE if not surround mode */
2413 if (! is_surround_on(ac97))
2414 misc_val |= AC97_AD1986_SODIS;
2415 if (! is_clfe_on(ac97))
2416 misc_val |= AC97_AD1986_CLDIS;
2417
2418 /* select line input (default=LINE_IN, SURROUND or MIC_1/2) */
2419 if (is_shared_linein(ac97))
2420 misc_val |= AC97_AD1986_LISEL_SURR;
2421 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2422 misc_val |= AC97_AD1986_LISEL_MIC;
2423 snd_ac97_update_bits(ac97, AC97_AD_MISC,
2424 AC97_AD1986_SODIS | AC97_AD1986_CLDIS |
2425 AC97_AD1986_LISEL_MASK,
2426 misc_val);
2427
2428 /* select microphone input (MIC_1/2, Center/LFE or LINE_IN) */
2429 if (is_shared_micin(ac97))
2430 ser_val = AC97_AD1986_OMS_C;
2431 else if (ac97->spec.ad18xx.swap_mic_linein != 0)
2432 ser_val = AC97_AD1986_OMS_L;
2433 else
2434 ser_val = AC97_AD1986_OMS_M;
2435 snd_ac97_update_bits(ac97, AC97_AD_SERIAL_CFG,
2436 AC97_AD1986_OMS_MASK,
2437 ser_val);
2438}
2439
2440static int patch_ad1986_specific(struct snd_ac97 *ac97)
2441{
2442 int err;
2443
2444 if ((err = patch_build_controls(ac97, &snd_ac97_ad198x_2cmic, 1)) < 0)
2445 return err;
2446
2447 return patch_build_controls(ac97, snd_ac97_ad1986_controls,
2448 ARRAY_SIZE(snd_ac97_ad1985_controls));
2449}
2450
2451static struct snd_ac97_build_ops patch_ad1986_build_ops = {
2452 .build_post_spdif = patch_ad198x_post_spdif,
2453 .build_specific = patch_ad1986_specific,
2454#ifdef CONFIG_PM
2455 .resume = ad18xx_resume,
2456#endif
2457 .update_jacks = ad1986_update_jacks,
2458};
2459
2460int patch_ad1986(struct snd_ac97 * ac97)
2461{
2462 patch_ad1881(ac97);
2463 ac97->build_ops = &patch_ad1986_build_ops;
2464 ac97->flags |= AC97_STEREO_MUTES;
2465
2466 /* update current jack configuration */
2467 ad1986_update_jacks(ac97);
2468
2469 return 0;
2470}
2471
2472
2010/* 2473/*
2011 * realtek ALC65x/850 codecs 2474 * realtek ALC65x/850 codecs
2012 */ 2475 */
@@ -2014,12 +2477,12 @@ static void alc650_update_jacks(struct snd_ac97 *ac97)
2014{ 2477{
2015 int shared; 2478 int shared;
2016 2479
2017 /* shared Line-In */ 2480 /* shared Line-In / Surround Out */
2018 shared = is_shared_linein(ac97); 2481 shared = is_shared_surrout(ac97);
2019 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9, 2482 snd_ac97_update_bits(ac97, AC97_ALC650_MULTICH, 1 << 9,
2020 shared ? (1 << 9) : 0); 2483 shared ? (1 << 9) : 0);
2021 /* update shared Mic */ 2484 /* update shared Mic In / Center/LFE Out */
2022 shared = is_shared_micin(ac97); 2485 shared = is_shared_clfeout(ac97);
2023 /* disable/enable vref */ 2486 /* disable/enable vref */
2024 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, 2487 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2025 shared ? (1 << 12) : 0); 2488 shared ? (1 << 12) : 0);
@@ -2064,7 +2527,7 @@ static const struct snd_kcontrol_new snd_ac97_spdif_controls_alc650[] = {
2064 /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */ 2527 /* AC97_SINGLE("IEC958 Input Monitor", AC97_ALC650_MULTICH, 13, 1, 0), */
2065}; 2528};
2066 2529
2067static DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0); 2530static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_max, -4350, 150, 0);
2068 2531
2069static int patch_alc650_specific(struct snd_ac97 * ac97) 2532static int patch_alc650_specific(struct snd_ac97 * ac97)
2070{ 2533{
@@ -2149,12 +2612,12 @@ static void alc655_update_jacks(struct snd_ac97 *ac97)
2149{ 2612{
2150 int shared; 2613 int shared;
2151 2614
2152 /* shared Line-In */ 2615 /* shared Line-In / Surround Out */
2153 shared = is_shared_linein(ac97); 2616 shared = is_shared_surrout(ac97);
2154 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9, 2617 ac97_update_bits_page(ac97, AC97_ALC650_MULTICH, 1 << 9,
2155 shared ? (1 << 9) : 0, 0); 2618 shared ? (1 << 9) : 0, 0);
2156 /* update shared mic */ 2619 /* update shared Mic In / Center/LFE Out */
2157 shared = is_shared_micin(ac97); 2620 shared = is_shared_clfeout(ac97);
2158 /* misc control; vrefout disable */ 2621 /* misc control; vrefout disable */
2159 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12, 2622 snd_ac97_update_bits(ac97, AC97_ALC650_CLOCK, 1 << 12,
2160 shared ? (1 << 12) : 0); 2623 shared ? (1 << 12) : 0);
@@ -2264,7 +2727,8 @@ int patch_alc655(struct snd_ac97 * ac97)
2264 if (ac97->subsystem_vendor == 0x1462 && 2727 if (ac97->subsystem_vendor == 0x1462 &&
2265 (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */ 2728 (ac97->subsystem_device == 0x0131 || /* MSI S270 laptop */
2266 ac97->subsystem_device == 0x0161 || /* LG K1 Express */ 2729 ac97->subsystem_device == 0x0161 || /* LG K1 Express */
2267 ac97->subsystem_device == 0x0351)) /* MSI L725 laptop */ 2730 ac97->subsystem_device == 0x0351 || /* MSI L725 laptop */
2731 ac97->subsystem_device == 0x0061)) /* MSI S250 laptop */
2268 val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */ 2732 val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
2269 else 2733 else
2270 val |= (1 << 1); /* Pin 47 is spdif input pin */ 2734 val |= (1 << 1); /* Pin 47 is spdif input pin */
@@ -2297,16 +2761,16 @@ static void alc850_update_jacks(struct snd_ac97 *ac97)
2297{ 2761{
2298 int shared; 2762 int shared;
2299 2763
2300 /* shared Line-In */ 2764 /* shared Line-In / Surround Out */
2301 shared = is_shared_linein(ac97); 2765 shared = is_shared_surrout(ac97);
2302 /* SURR 1kOhm (bit4), Amp (bit5) */ 2766 /* SURR 1kOhm (bit4), Amp (bit5) */
2303 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5), 2767 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<4)|(1<<5),
2304 shared ? (1<<5) : (1<<4)); 2768 shared ? (1<<5) : (1<<4));
2305 /* LINE-IN = 0, SURROUND = 2 */ 2769 /* LINE-IN = 0, SURROUND = 2 */
2306 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12, 2770 snd_ac97_update_bits(ac97, AC97_ALC850_JACK_SELECT, 7 << 12,
2307 shared ? (2<<12) : (0<<12)); 2771 shared ? (2<<12) : (0<<12));
2308 /* update shared mic */ 2772 /* update shared Mic In / Center/LFE Out */
2309 shared = is_shared_micin(ac97); 2773 shared = is_shared_clfeout(ac97);
2310 /* Vref disable (bit12), 1kOhm (bit13) */ 2774 /* Vref disable (bit12), 1kOhm (bit13) */
2311 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13), 2775 snd_ac97_update_bits(ac97, AC97_ALC850_MISC1, (1<<12)|(1<<13),
2312 shared ? (1<<12) : (1<<13)); 2776 shared ? (1<<12) : (1<<13));
@@ -2379,9 +2843,9 @@ int patch_alc850(struct snd_ac97 *ac97)
2379 */ 2843 */
2380static void cm9738_update_jacks(struct snd_ac97 *ac97) 2844static void cm9738_update_jacks(struct snd_ac97 *ac97)
2381{ 2845{
2382 /* shared Line-In */ 2846 /* shared Line-In / Surround Out */
2383 snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10, 2847 snd_ac97_update_bits(ac97, AC97_CM9738_VENDOR_CTRL, 1 << 10,
2384 is_shared_linein(ac97) ? (1 << 10) : 0); 2848 is_shared_surrout(ac97) ? (1 << 10) : 0);
2385} 2849}
2386 2850
2387static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = { 2851static const struct snd_kcontrol_new snd_ac97_cm9738_controls[] = {
@@ -2463,12 +2927,12 @@ static const struct snd_kcontrol_new snd_ac97_cm9739_controls_spdif[] = {
2463 2927
2464static void cm9739_update_jacks(struct snd_ac97 *ac97) 2928static void cm9739_update_jacks(struct snd_ac97 *ac97)
2465{ 2929{
2466 /* shared Line-In */ 2930 /* shared Line-In / Surround Out */
2467 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10, 2931 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 1 << 10,
2468 is_shared_linein(ac97) ? (1 << 10) : 0); 2932 is_shared_surrout(ac97) ? (1 << 10) : 0);
2469 /* shared Mic */ 2933 /* shared Mic In / Center/LFE Out **/
2470 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000, 2934 snd_ac97_update_bits(ac97, AC97_CM9739_MULTI_CHAN, 0x3000,
2471 is_shared_micin(ac97) ? 0x1000 : 0x2000); 2935 is_shared_clfeout(ac97) ? 0x1000 : 0x2000);
2472} 2936}
2473 2937
2474static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = { 2938static const struct snd_kcontrol_new snd_ac97_cm9739_controls[] = {
@@ -2580,8 +3044,8 @@ static void cm9761_update_jacks(struct snd_ac97 *ac97)
2580 3044
2581 val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)]; 3045 val |= surr_on[ac97->spec.dev_flags][is_surround_on(ac97)];
2582 val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)]; 3046 val |= clfe_on[ac97->spec.dev_flags][is_clfe_on(ac97)];
2583 val |= surr_shared[ac97->spec.dev_flags][is_shared_linein(ac97)]; 3047 val |= surr_shared[ac97->spec.dev_flags][is_shared_surrout(ac97)];
2584 val |= clfe_shared[ac97->spec.dev_flags][is_shared_micin(ac97)]; 3048 val |= clfe_shared[ac97->spec.dev_flags][is_shared_clfeout(ac97)];
2585 3049
2586 snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val); 3050 snd_ac97_update_bits(ac97, AC97_CM9761_MULTI_CHAN, 0x3c88, val);
2587} 3051}
@@ -2821,6 +3285,7 @@ int patch_vt1617a(struct snd_ac97 * ac97)
2821 snd_ac97_write_cache(ac97, 0x5c, 0x20); 3285 snd_ac97_write_cache(ac97, 0x5c, 0x20);
2822 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */ 3286 ac97->ext_id |= AC97_EI_SPDIF; /* force the detection of spdif */
2823 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000; 3287 ac97->rates[AC97_RATES_SPDIF] = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000;
3288 ac97->build_ops = &patch_vt1616_ops;
2824 return 0; 3289 return 0;
2825} 3290}
2826 3291
@@ -2828,12 +3293,12 @@ int patch_vt1617a(struct snd_ac97 * ac97)
2828 */ 3293 */
2829static void it2646_update_jacks(struct snd_ac97 *ac97) 3294static void it2646_update_jacks(struct snd_ac97 *ac97)
2830{ 3295{
2831 /* shared Line-In */ 3296 /* shared Line-In / Surround Out */
2832 snd_ac97_update_bits(ac97, 0x76, 1 << 9, 3297 snd_ac97_update_bits(ac97, 0x76, 1 << 9,
2833 is_shared_linein(ac97) ? (1<<9) : 0); 3298 is_shared_surrout(ac97) ? (1<<9) : 0);
2834 /* shared Mic */ 3299 /* shared Mic / Center/LFE Out */
2835 snd_ac97_update_bits(ac97, 0x76, 1 << 10, 3300 snd_ac97_update_bits(ac97, 0x76, 1 << 10,
2836 is_shared_micin(ac97) ? (1<<10) : 0); 3301 is_shared_clfeout(ac97) ? (1<<10) : 0);
2837} 3302}
2838 3303
2839static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = { 3304static const struct snd_kcontrol_new snd_ac97_controls_it2646[] = {
diff --git a/sound/pci/ac97/ac97_patch.h b/sound/pci/ac97/ac97_patch.h
index 741979217207..94340daaaf1f 100644
--- a/sound/pci/ac97/ac97_patch.h
+++ b/sound/pci/ac97/ac97_patch.h
@@ -48,6 +48,7 @@ int patch_ad1980(struct snd_ac97 * ac97);
48int patch_ad1981a(struct snd_ac97 * ac97); 48int patch_ad1981a(struct snd_ac97 * ac97);
49int patch_ad1981b(struct snd_ac97 * ac97); 49int patch_ad1981b(struct snd_ac97 * ac97);
50int patch_ad1985(struct snd_ac97 * ac97); 50int patch_ad1985(struct snd_ac97 * ac97);
51int patch_ad1986(struct snd_ac97 * ac97);
51int patch_alc650(struct snd_ac97 * ac97); 52int patch_alc650(struct snd_ac97 * ac97);
52int patch_alc655(struct snd_ac97 * ac97); 53int patch_alc655(struct snd_ac97 * ac97);
53int patch_alc850(struct snd_ac97 * ac97); 54int patch_alc850(struct snd_ac97 * ac97);
diff --git a/sound/pci/ac97/ak4531_codec.c b/sound/pci/ac97/ak4531_codec.c
index c153cb79c518..dc26820a03a5 100644
--- a/sound/pci/ac97/ak4531_codec.c
+++ b/sound/pci/ac97/ak4531_codec.c
@@ -267,9 +267,9 @@ static int snd_ak4531_put_input_sw(struct snd_kcontrol *kcontrol, struct snd_ctl
267 return change; 267 return change;
268} 268}
269 269
270static DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0); 270static const DECLARE_TLV_DB_SCALE(db_scale_master, -6200, 200, 0);
271static DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0); 271static const DECLARE_TLV_DB_SCALE(db_scale_mono, -2800, 400, 0);
272static DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0); 272static const DECLARE_TLV_DB_SCALE(db_scale_input, -5000, 200, 0);
273 273
274static struct snd_kcontrol_new snd_ak4531_controls[] = { 274static struct snd_kcontrol_new snd_ak4531_controls[] = {
275 275
diff --git a/sound/pci/als300.c b/sound/pci/als300.c
index 9f406fbe0d95..8afcb98ca7bb 100644
--- a/sound/pci/als300.c
+++ b/sound/pci/als300.c
@@ -444,7 +444,7 @@ static int snd_als300_capture_close(struct snd_pcm_substream *substream)
444} 444}
445 445
446static int snd_als300_pcm_hw_params(struct snd_pcm_substream *substream, 446static int snd_als300_pcm_hw_params(struct snd_pcm_substream *substream,
447 snd_pcm_hw_params_t * hw_params) 447 struct snd_pcm_hw_params *hw_params)
448{ 448{
449 return snd_pcm_lib_malloc_pages(substream, 449 return snd_pcm_lib_malloc_pages(substream,
450 params_buffer_bytes(hw_params)); 450 params_buffer_bytes(hw_params));
@@ -673,7 +673,7 @@ static void snd_als300_init(struct snd_als300 *chip)
673 snd_als300_dbgcallleave(); 673 snd_als300_dbgcallleave();
674} 674}
675 675
676static int __devinit snd_als300_create(snd_card_t *card, 676static int __devinit snd_als300_create(struct snd_card *card,
677 struct pci_dev *pci, int chip_type, 677 struct pci_dev *pci, int chip_type,
678 struct snd_als300 **rchip) 678 struct snd_als300 **rchip)
679{ 679{
@@ -681,7 +681,7 @@ static int __devinit snd_als300_create(snd_card_t *card,
681 void *irq_handler; 681 void *irq_handler;
682 int err; 682 int err;
683 683
684 static snd_device_ops_t ops = { 684 static struct snd_device_ops ops = {
685 .dev_free = snd_als300_dev_free, 685 .dev_free = snd_als300_dev_free,
686 }; 686 };
687 *rchip = NULL; 687 *rchip = NULL;
diff --git a/sound/pci/atiixp.c b/sound/pci/atiixp.c
index 476c3433073e..7d8053b5e8d5 100644
--- a/sound/pci/atiixp.c
+++ b/sound/pci/atiixp.c
@@ -45,6 +45,7 @@ static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
45static int ac97_clock = 48000; 45static int ac97_clock = 48000;
46static char *ac97_quirk; 46static char *ac97_quirk;
47static int spdif_aclink = 1; 47static int spdif_aclink = 1;
48static int ac97_codec = -1;
48 49
49module_param(index, int, 0444); 50module_param(index, int, 0444);
50MODULE_PARM_DESC(index, "Index value for ATI IXP controller."); 51MODULE_PARM_DESC(index, "Index value for ATI IXP controller.");
@@ -54,6 +55,8 @@ module_param(ac97_clock, int, 0444);
54MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz)."); 55MODULE_PARM_DESC(ac97_clock, "AC'97 codec clock (default 48000Hz).");
55module_param(ac97_quirk, charp, 0444); 56module_param(ac97_quirk, charp, 0444);
56MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware."); 57MODULE_PARM_DESC(ac97_quirk, "AC'97 workaround for strange hardware.");
58module_param(ac97_codec, int, 0444);
59MODULE_PARM_DESC(ac97_codec, "Specify codec instead of probing.");
57module_param(spdif_aclink, bool, 0444); 60module_param(spdif_aclink, bool, 0444);
58MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link."); 61MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
59 62
@@ -293,6 +296,10 @@ static struct pci_device_id snd_atiixp_ids[] = {
293 296
294MODULE_DEVICE_TABLE(pci, snd_atiixp_ids); 297MODULE_DEVICE_TABLE(pci, snd_atiixp_ids);
295 298
299static struct snd_pci_quirk atiixp_quirks[] __devinitdata = {
300 SND_PCI_QUIRK(0x15bd, 0x3100, "DFI RS482", 0),
301 { } /* terminator */
302};
296 303
297/* 304/*
298 * lowlevel functions 305 * lowlevel functions
@@ -553,11 +560,33 @@ static int snd_atiixp_aclink_down(struct atiixp *chip)
553 ATI_REG_ISR_CODEC2_NOT_READY) 560 ATI_REG_ISR_CODEC2_NOT_READY)
554#define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME) 561#define CODEC_CHECK_BITS (ALL_CODEC_NOT_READY|ATI_REG_ISR_NEW_FRAME)
555 562
563static int ac97_probing_bugs(struct pci_dev *pci)
564{
565 const struct snd_pci_quirk *q;
566
567 q = snd_pci_quirk_lookup(pci, atiixp_quirks);
568 if (q) {
569 snd_printdd(KERN_INFO "Atiixp quirk for %s. "
570 "Forcing codec %d\n", q->name, q->value);
571 return q->value;
572 }
573 /* this hardware doesn't need workarounds. Probe for codec */
574 return -1;
575}
576
556static int snd_atiixp_codec_detect(struct atiixp *chip) 577static int snd_atiixp_codec_detect(struct atiixp *chip)
557{ 578{
558 int timeout; 579 int timeout;
559 580
560 chip->codec_not_ready_bits = 0; 581 chip->codec_not_ready_bits = 0;
582 if (ac97_codec == -1)
583 ac97_codec = ac97_probing_bugs(chip->pci);
584 if (ac97_codec >= 0) {
585 chip->codec_not_ready_bits |=
586 CODEC_CHECK_BITS ^ (1 << (ac97_codec + 10));
587 return 0;
588 }
589
561 atiixp_write(chip, IER, CODEC_CHECK_BITS); 590 atiixp_write(chip, IER, CODEC_CHECK_BITS);
562 /* wait for the interrupts */ 591 /* wait for the interrupts */
563 timeout = 50; 592 timeout = 50;
@@ -1396,7 +1425,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp *chip, int clock,
1396 ac97.private_data = chip; 1425 ac97.private_data = chip;
1397 ac97.pci = chip->pci; 1426 ac97.pci = chip->pci;
1398 ac97.num = i; 1427 ac97.num = i;
1399 ac97.scaps = AC97_SCAP_SKIP_MODEM; 1428 ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
1400 if (! chip->spdif_over_aclink) 1429 if (! chip->spdif_over_aclink)
1401 ac97.scaps |= AC97_SCAP_NO_SPDIF; 1430 ac97.scaps |= AC97_SCAP_NO_SPDIF;
1402 if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { 1431 if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
diff --git a/sound/pci/atiixp_modem.c b/sound/pci/atiixp_modem.c
index cc2e6b9d407e..904023fe4f26 100644
--- a/sound/pci/atiixp_modem.c
+++ b/sound/pci/atiixp_modem.c
@@ -1090,7 +1090,7 @@ static int __devinit snd_atiixp_mixer_new(struct atiixp_modem *chip, int clock)
1090 ac97.private_data = chip; 1090 ac97.private_data = chip;
1091 ac97.pci = chip->pci; 1091 ac97.pci = chip->pci;
1092 ac97.num = i; 1092 ac97.num = i;
1093 ac97.scaps = AC97_SCAP_SKIP_AUDIO; 1093 ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
1094 if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) { 1094 if ((err = snd_ac97_mixer(pbus, &ac97, &chip->ac97[i])) < 0) {
1095 chip->ac97[i] = NULL; /* to be sure */ 1095 chip->ac97[i] = NULL; /* to be sure */
1096 snd_printdd("atiixp-modem: codec %d not available for modem\n", i); 1096 snd_printdd("atiixp-modem: codec %d not available for modem\n", i);
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index f61f052f6d14..ea6712b63c9f 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -1382,7 +1382,6 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
1382 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf); 1382 snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
1383 snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */ 1383 snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
1384 chip->spdif_enable = 0; /* Set digital SPDIF output off */ 1384 chip->spdif_enable = 0; /* Set digital SPDIF output off */
1385 chip->capture_source = 3; /* Set CAPTURE_SOURCE */
1386 //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */ 1385 //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
1387 //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */ 1386 //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
1388 1387
@@ -1402,8 +1401,22 @@ static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
1402 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */ 1401 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
1403 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */ 1402 snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
1404 } 1403 }
1405 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC, Line in, TAD in, AUX in */ 1404 if (chip->details->i2c_adc == 1) {
1406 chip->capture_source = 3; /* Set CAPTURE_SOURCE */ 1405 /* Select MIC, Line in, TAD in, AUX in */
1406 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1407 /* Default to CAPTURE_SOURCE to i2s in */
1408 chip->capture_source = 3;
1409 } else if (chip->details->ac97 == 1) {
1410 /* Default to AC97 in */
1411 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x444400e4);
1412 /* Default to CAPTURE_SOURCE to AC97 in */
1413 chip->capture_source = 4;
1414 } else {
1415 /* Select MIC, Line in, TAD in, AUX in */
1416 snd_ca0106_ptr_write(chip, CAPTURE_SOURCE, 0x0, 0x333300e4);
1417 /* Default to Set CAPTURE_SOURCE to i2s in */
1418 chip->capture_source = 3;
1419 }
1407 1420
1408 if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */ 1421 if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
1409 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */ 1422 /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
@@ -1605,6 +1618,8 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
1605 snd_ca0106_proc_init(chip); 1618 snd_ca0106_proc_init(chip);
1606#endif 1619#endif
1607 1620
1621 snd_card_set_dev(card, &pci->dev);
1622
1608 if ((err = snd_card_register(card)) < 0) { 1623 if ((err = snd_card_register(card)) < 0) {
1609 snd_card_free(card); 1624 snd_card_free(card);
1610 return err; 1625 return err;
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index 9855f528ea78..b913a1fb8c21 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -74,8 +74,8 @@
74 74
75#include "ca0106.h" 75#include "ca0106.h"
76 76
77static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1); 77static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
78static DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1); 78static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
79 79
80static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol, 80static int snd_ca0106_shared_spdif_info(struct snd_kcontrol *kcontrol,
81 struct snd_ctl_elem_info *uinfo) 81 struct snd_ctl_elem_info *uinfo)
@@ -482,19 +482,6 @@ static int snd_ca0106_i2c_volume_put(struct snd_kcontrol *kcontrol,
482 .private_value = ((chid) << 8) | (reg) \ 482 .private_value = ((chid) << 8) | (reg) \
483} 483}
484 484
485#define I2C_VOLUME(xname,chid) \
486{ \
487 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
488 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
489 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
490 .info = snd_ca0106_i2c_volume_info, \
491 .get = snd_ca0106_i2c_volume_get, \
492 .put = snd_ca0106_i2c_volume_put, \
493 .tlv = { .p = snd_ca0106_db_scale2 }, \
494 .private_value = chid \
495}
496
497
498static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = { 485static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
499 CA_VOLUME("Analog Front Playback Volume", 486 CA_VOLUME("Analog Front Playback Volume",
500 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2), 487 CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2),
@@ -517,11 +504,6 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
517 CA_VOLUME("CAPTURE feedback Playback Volume", 504 CA_VOLUME("CAPTURE feedback Playback Volume",
518 1, CAPTURE_CONTROL), 505 1, CAPTURE_CONTROL),
519 506
520 I2C_VOLUME("Phone Capture Volume", 0),
521 I2C_VOLUME("Mic Capture Volume", 1),
522 I2C_VOLUME("Line in Capture Volume", 2),
523 I2C_VOLUME("Aux Capture Volume", 3),
524
525 { 507 {
526 .access = SNDRV_CTL_ELEM_ACCESS_READ, 508 .access = SNDRV_CTL_ELEM_ACCESS_READ,
527 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 509 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -539,14 +521,14 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
539 }, 521 },
540 { 522 {
541 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 523 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
542 .name = "Digital Capture Source", 524 .name = "Digital Source Capture Enum",
543 .info = snd_ca0106_capture_source_info, 525 .info = snd_ca0106_capture_source_info,
544 .get = snd_ca0106_capture_source_get, 526 .get = snd_ca0106_capture_source_get,
545 .put = snd_ca0106_capture_source_put 527 .put = snd_ca0106_capture_source_put
546 }, 528 },
547 { 529 {
548 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 530 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
549 .name = "Capture Source", 531 .name = "Analog Source Capture Enum",
550 .info = snd_ca0106_i2c_capture_source_info, 532 .info = snd_ca0106_i2c_capture_source_info,
551 .get = snd_ca0106_i2c_capture_source_get, 533 .get = snd_ca0106_i2c_capture_source_get,
552 .put = snd_ca0106_i2c_capture_source_put 534 .put = snd_ca0106_i2c_capture_source_put
@@ -561,6 +543,25 @@ static struct snd_kcontrol_new snd_ca0106_volume_ctls[] __devinitdata = {
561 }, 543 },
562}; 544};
563 545
546#define I2C_VOLUME(xname,chid) \
547{ \
548 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
549 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
550 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
551 .info = snd_ca0106_i2c_volume_info, \
552 .get = snd_ca0106_i2c_volume_get, \
553 .put = snd_ca0106_i2c_volume_put, \
554 .tlv = { .p = snd_ca0106_db_scale2 }, \
555 .private_value = chid \
556}
557
558static struct snd_kcontrol_new snd_ca0106_volume_i2c_adc_ctls[] __devinitdata = {
559 I2C_VOLUME("Phone Capture Volume", 0),
560 I2C_VOLUME("Mic Capture Volume", 1),
561 I2C_VOLUME("Line in Capture Volume", 2),
562 I2C_VOLUME("Aux Capture Volume", 3),
563};
564
564static int __devinit remove_ctl(struct snd_card *card, const char *name) 565static int __devinit remove_ctl(struct snd_card *card, const char *name)
565{ 566{
566 struct snd_ctl_elem_id id; 567 struct snd_ctl_elem_id id;
@@ -645,6 +646,11 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
645 return err; 646 return err;
646 } 647 }
647 if (emu->details->i2c_adc == 1) { 648 if (emu->details->i2c_adc == 1) {
649 for (i = 0; i < ARRAY_SIZE(snd_ca0106_volume_i2c_adc_ctls); i++) {
650 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_volume_i2c_adc_ctls[i], emu));
651 if (err < 0)
652 return err;
653 }
648 if (emu->details->gpio_type == 1) 654 if (emu->details->gpio_type == 1)
649 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu)); 655 err = snd_ctl_add(card, snd_ctl_new1(&snd_ca0106_capture_mic_line_in, emu));
650 else /* gpio_type == 2 */ 656 else /* gpio_type == 2 */
diff --git a/sound/pci/cs4281.c b/sound/pci/cs4281.c
index 8e5519de7115..44cf54607647 100644
--- a/sound/pci/cs4281.c
+++ b/sound/pci/cs4281.c
@@ -1055,7 +1055,7 @@ static int snd_cs4281_put_volume(struct snd_kcontrol *kcontrol,
1055 return change; 1055 return change;
1056} 1056}
1057 1057
1058static DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0); 1058static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -4650, 150, 0);
1059 1059
1060static struct snd_kcontrol_new snd_cs4281_fm_vol = 1060static struct snd_kcontrol_new snd_cs4281_fm_vol =
1061{ 1061{
diff --git a/sound/pci/echoaudio/darla20.c b/sound/pci/echoaudio/darla20.c
index b7108e29a668..8e7fe033270f 100644
--- a/sound/pci/echoaudio/darla20.c
+++ b/sound/pci/echoaudio/darla20.c
@@ -47,6 +47,7 @@
47#include <sound/core.h> 47#include <sound/core.h>
48#include <sound/info.h> 48#include <sound/info.h>
49#include <sound/control.h> 49#include <sound/control.h>
50#include <sound/tlv.h>
50#include <sound/pcm.h> 51#include <sound/pcm.h>
51#include <sound/pcm_params.h> 52#include <sound/pcm_params.h>
52#include <sound/asoundef.h> 53#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/darla24.c b/sound/pci/echoaudio/darla24.c
index e59a982ee361..a13c623eb999 100644
--- a/sound/pci/echoaudio/darla24.c
+++ b/sound/pci/echoaudio/darla24.c
@@ -51,6 +51,7 @@
51#include <sound/core.h> 51#include <sound/core.h>
52#include <sound/info.h> 52#include <sound/info.h>
53#include <sound/control.h> 53#include <sound/control.h>
54#include <sound/tlv.h>
54#include <sound/pcm.h> 55#include <sound/pcm.h>
55#include <sound/pcm_params.h> 56#include <sound/pcm_params.h>
56#include <sound/asoundef.h> 57#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/echo3g.c b/sound/pci/echoaudio/echo3g.c
index 12099fe1547d..8fb15823aca5 100644
--- a/sound/pci/echoaudio/echo3g.c
+++ b/sound/pci/echoaudio/echo3g.c
@@ -58,6 +58,7 @@
58#include <sound/core.h> 58#include <sound/core.h>
59#include <sound/info.h> 59#include <sound/info.h>
60#include <sound/control.h> 60#include <sound/control.h>
61#include <sound/tlv.h>
61#include <sound/pcm.h> 62#include <sound/pcm.h>
62#include <sound/pcm_params.h> 63#include <sound/pcm_params.h>
63#include <sound/asoundef.h> 64#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/echo3g_dsp.c b/sound/pci/echoaudio/echo3g_dsp.c
index d26a1d1f3ed1..48eb7c599111 100644
--- a/sound/pci/echoaudio/echo3g_dsp.c
+++ b/sound/pci/echoaudio/echo3g_dsp.c
@@ -39,7 +39,7 @@ static int set_phantom_power(struct echoaudio *chip, char on);
39static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq, 39static int write_control_reg(struct echoaudio *chip, u32 ctl, u32 frq,
40 char force); 40 char force);
41 41
42#include <linux/irq.h> 42#include <linux/interrupt.h>
43 43
44static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id) 44static int init_hw(struct echoaudio *chip, u16 device_id, u16 subdevice_id)
45{ 45{
diff --git a/sound/pci/echoaudio/echoaudio.c b/sound/pci/echoaudio/echoaudio.c
index 047e0b5bf15d..6a428b81dba6 100644
--- a/sound/pci/echoaudio/echoaudio.c
+++ b/sound/pci/echoaudio/echoaudio.c
@@ -34,6 +34,7 @@ module_param_array(enable, bool, NULL, 0444);
34MODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard."); 34MODULE_PARM_DESC(enable, "Enable " ECHOCARD_NAME " soundcard.");
35 35
36static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999}; 36static unsigned int channels_list[10] = {1, 2, 4, 6, 8, 10, 12, 14, 16, 999999};
37static const DECLARE_TLV_DB_SCALE(db_scale_output_gain, -12800, 100, 1);
37 38
38static int get_firmware(const struct firmware **fw_entry, 39static int get_firmware(const struct firmware **fw_entry,
39 const struct firmware *frm, struct echoaudio *chip) 40 const struct firmware *frm, struct echoaudio *chip)
@@ -1011,17 +1012,21 @@ static int snd_echo_output_gain_put(struct snd_kcontrol *kcontrol,
1011static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = { 1012static struct snd_kcontrol_new snd_echo_line_output_gain __devinitdata = {
1012 .name = "Line Playback Volume", 1013 .name = "Line Playback Volume",
1013 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1014 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1015 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1014 .info = snd_echo_output_gain_info, 1016 .info = snd_echo_output_gain_info,
1015 .get = snd_echo_output_gain_get, 1017 .get = snd_echo_output_gain_get,
1016 .put = snd_echo_output_gain_put, 1018 .put = snd_echo_output_gain_put,
1019 .tlv = {.p = db_scale_output_gain},
1017}; 1020};
1018#else 1021#else
1019static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = { 1022static struct snd_kcontrol_new snd_echo_pcm_output_gain __devinitdata = {
1020 .name = "PCM Playback Volume", 1023 .name = "PCM Playback Volume",
1021 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1024 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1025 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1022 .info = snd_echo_output_gain_info, 1026 .info = snd_echo_output_gain_info,
1023 .get = snd_echo_output_gain_get, 1027 .get = snd_echo_output_gain_get,
1024 .put = snd_echo_output_gain_put, 1028 .put = snd_echo_output_gain_put,
1029 .tlv = {.p = db_scale_output_gain},
1025}; 1030};
1026#endif 1031#endif
1027 1032
@@ -1080,12 +1085,16 @@ static int snd_echo_input_gain_put(struct snd_kcontrol *kcontrol,
1080 return changed; 1085 return changed;
1081} 1086}
1082 1087
1088static const DECLARE_TLV_DB_SCALE(db_scale_input_gain, -2500, 50, 0);
1089
1083static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = { 1090static struct snd_kcontrol_new snd_echo_line_input_gain __devinitdata = {
1084 .name = "Line Capture Volume", 1091 .name = "Line Capture Volume",
1085 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1092 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1093 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1086 .info = snd_echo_input_gain_info, 1094 .info = snd_echo_input_gain_info,
1087 .get = snd_echo_input_gain_get, 1095 .get = snd_echo_input_gain_get,
1088 .put = snd_echo_input_gain_put, 1096 .put = snd_echo_input_gain_put,
1097 .tlv = {.p = db_scale_input_gain},
1089}; 1098};
1090 1099
1091#endif /* ECHOCARD_HAS_INPUT_GAIN */ 1100#endif /* ECHOCARD_HAS_INPUT_GAIN */
@@ -1277,9 +1286,11 @@ static int snd_echo_mixer_put(struct snd_kcontrol *kcontrol,
1277static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = { 1286static struct snd_kcontrol_new snd_echo_monitor_mixer __devinitdata = {
1278 .name = "Monitor Mixer Volume", 1287 .name = "Monitor Mixer Volume",
1279 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1288 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1289 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1280 .info = snd_echo_mixer_info, 1290 .info = snd_echo_mixer_info,
1281 .get = snd_echo_mixer_get, 1291 .get = snd_echo_mixer_get,
1282 .put = snd_echo_mixer_put, 1292 .put = snd_echo_mixer_put,
1293 .tlv = {.p = db_scale_output_gain},
1283}; 1294};
1284 1295
1285#endif /* ECHOCARD_HAS_MONITOR */ 1296#endif /* ECHOCARD_HAS_MONITOR */
@@ -1343,9 +1354,11 @@ static int snd_echo_vmixer_put(struct snd_kcontrol *kcontrol,
1343static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = { 1354static struct snd_kcontrol_new snd_echo_vmixer __devinitdata = {
1344 .name = "VMixer Volume", 1355 .name = "VMixer Volume",
1345 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1356 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1357 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1346 .info = snd_echo_vmixer_info, 1358 .info = snd_echo_vmixer_info,
1347 .get = snd_echo_vmixer_get, 1359 .get = snd_echo_vmixer_get,
1348 .put = snd_echo_vmixer_put, 1360 .put = snd_echo_vmixer_put,
1361 .tlv = {.p = db_scale_output_gain},
1349}; 1362};
1350 1363
1351#endif /* ECHOCARD_HAS_VMIXER */ 1364#endif /* ECHOCARD_HAS_VMIXER */
@@ -1753,9 +1766,12 @@ static int snd_echo_vumeters_get(struct snd_kcontrol *kcontrol,
1753static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = { 1766static struct snd_kcontrol_new snd_echo_vumeters __devinitdata = {
1754 .name = "VU-meters", 1767 .name = "VU-meters",
1755 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1768 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1756 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 1769 .access = SNDRV_CTL_ELEM_ACCESS_READ |
1770 SNDRV_CTL_ELEM_ACCESS_VOLATILE |
1771 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
1757 .info = snd_echo_vumeters_info, 1772 .info = snd_echo_vumeters_info,
1758 .get = snd_echo_vumeters_get, 1773 .get = snd_echo_vumeters_get,
1774 .tlv = {.p = db_scale_output_gain},
1759}; 1775};
1760 1776
1761 1777
diff --git a/sound/pci/echoaudio/gina20.c b/sound/pci/echoaudio/gina20.c
index 29d6d12f80ca..af4d32026e4a 100644
--- a/sound/pci/echoaudio/gina20.c
+++ b/sound/pci/echoaudio/gina20.c
@@ -51,6 +51,7 @@
51#include <sound/core.h> 51#include <sound/core.h>
52#include <sound/info.h> 52#include <sound/info.h>
53#include <sound/control.h> 53#include <sound/control.h>
54#include <sound/tlv.h>
54#include <sound/pcm.h> 55#include <sound/pcm.h>
55#include <sound/pcm_params.h> 56#include <sound/pcm_params.h>
56#include <sound/asoundef.h> 57#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/gina24.c b/sound/pci/echoaudio/gina24.c
index e464d720d0bd..9ff454a947ed 100644
--- a/sound/pci/echoaudio/gina24.c
+++ b/sound/pci/echoaudio/gina24.c
@@ -57,6 +57,7 @@
57#include <sound/core.h> 57#include <sound/core.h>
58#include <sound/info.h> 58#include <sound/info.h>
59#include <sound/control.h> 59#include <sound/control.h>
60#include <sound/tlv.h>
60#include <sound/pcm.h> 61#include <sound/pcm.h>
61#include <sound/pcm_params.h> 62#include <sound/pcm_params.h>
62#include <sound/asoundef.h> 63#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/indigo.c b/sound/pci/echoaudio/indigo.c
index bfd2467099ac..37eb726fd03d 100644
--- a/sound/pci/echoaudio/indigo.c
+++ b/sound/pci/echoaudio/indigo.c
@@ -49,6 +49,7 @@
49#include <sound/core.h> 49#include <sound/core.h>
50#include <sound/info.h> 50#include <sound/info.h>
51#include <sound/control.h> 51#include <sound/control.h>
52#include <sound/tlv.h>
52#include <sound/pcm.h> 53#include <sound/pcm.h>
53#include <sound/pcm_params.h> 54#include <sound/pcm_params.h>
54#include <sound/asoundef.h> 55#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/indigodj.c b/sound/pci/echoaudio/indigodj.c
index 8ed7ff1fd875..dc8b91824181 100644
--- a/sound/pci/echoaudio/indigodj.c
+++ b/sound/pci/echoaudio/indigodj.c
@@ -49,6 +49,7 @@
49#include <sound/core.h> 49#include <sound/core.h>
50#include <sound/info.h> 50#include <sound/info.h>
51#include <sound/control.h> 51#include <sound/control.h>
52#include <sound/tlv.h>
52#include <sound/pcm.h> 53#include <sound/pcm.h>
53#include <sound/pcm_params.h> 54#include <sound/pcm_params.h>
54#include <sound/asoundef.h> 55#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/indigoio.c b/sound/pci/echoaudio/indigoio.c
index a8788e959171..eadf3263453a 100644
--- a/sound/pci/echoaudio/indigoio.c
+++ b/sound/pci/echoaudio/indigoio.c
@@ -50,6 +50,7 @@
50#include <sound/core.h> 50#include <sound/core.h>
51#include <sound/info.h> 51#include <sound/info.h>
52#include <sound/control.h> 52#include <sound/control.h>
53#include <sound/tlv.h>
53#include <sound/pcm.h> 54#include <sound/pcm.h>
54#include <sound/pcm_params.h> 55#include <sound/pcm_params.h>
55#include <sound/asoundef.h> 56#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/layla20.c b/sound/pci/echoaudio/layla20.c
index e503d74b3ba9..6cede497579e 100644
--- a/sound/pci/echoaudio/layla20.c
+++ b/sound/pci/echoaudio/layla20.c
@@ -56,6 +56,7 @@
56#include <sound/core.h> 56#include <sound/core.h>
57#include <sound/info.h> 57#include <sound/info.h>
58#include <sound/control.h> 58#include <sound/control.h>
59#include <sound/tlv.h>
59#include <sound/pcm.h> 60#include <sound/pcm.h>
60#include <sound/pcm_params.h> 61#include <sound/pcm_params.h>
61#include <sound/asoundef.h> 62#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/layla24.c b/sound/pci/echoaudio/layla24.c
index d4581fdc841c..44f735426aa0 100644
--- a/sound/pci/echoaudio/layla24.c
+++ b/sound/pci/echoaudio/layla24.c
@@ -58,6 +58,7 @@
58#include <sound/core.h> 58#include <sound/core.h>
59#include <sound/info.h> 59#include <sound/info.h>
60#include <sound/control.h> 60#include <sound/control.h>
61#include <sound/tlv.h>
61#include <sound/pcm.h> 62#include <sound/pcm.h>
62#include <sound/pcm_params.h> 63#include <sound/pcm_params.h>
63#include <sound/asoundef.h> 64#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/mia.c b/sound/pci/echoaudio/mia.c
index be40c64263d2..dc172d03ac3f 100644
--- a/sound/pci/echoaudio/mia.c
+++ b/sound/pci/echoaudio/mia.c
@@ -56,6 +56,7 @@
56#include <sound/core.h> 56#include <sound/core.h>
57#include <sound/info.h> 57#include <sound/info.h>
58#include <sound/control.h> 58#include <sound/control.h>
59#include <sound/tlv.h>
59#include <sound/pcm.h> 60#include <sound/pcm.h>
60#include <sound/pcm_params.h> 61#include <sound/pcm_params.h>
61#include <sound/asoundef.h> 62#include <sound/asoundef.h>
diff --git a/sound/pci/echoaudio/mona.c b/sound/pci/echoaudio/mona.c
index 5dc512add372..c856ed50dd9a 100644
--- a/sound/pci/echoaudio/mona.c
+++ b/sound/pci/echoaudio/mona.c
@@ -55,6 +55,7 @@
55#include <sound/core.h> 55#include <sound/core.h>
56#include <sound/info.h> 56#include <sound/info.h>
57#include <sound/control.h> 57#include <sound/control.h>
58#include <sound/tlv.h>
58#include <sound/pcm.h> 59#include <sound/pcm.h>
59#include <sound/pcm_params.h> 60#include <sound/pcm_params.h>
60#include <sound/asoundef.h> 61#include <sound/asoundef.h>
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 972ec40d8166..80aa585eade4 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -3,8 +3,10 @@
3 * Creative Labs, Inc. 3 * Creative Labs, Inc.
4 * Routines for control of EMU10K1 chips 4 * Routines for control of EMU10K1 chips
5 * 5 *
6 * Copyright (c) by James Courtier-Dutton <James@superbug.demon.co.uk> 6 * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
7 * Added support for Audigy 2 Value. 7 * Added support for Audigy 2 Value.
8 * Added EMU 1010 support.
9 * General bug fixes and enhancements.
8 * 10 *
9 * 11 *
10 * BUGS: 12 * BUGS:
@@ -41,8 +43,10 @@
41 43
42#include <sound/core.h> 44#include <sound/core.h>
43#include <sound/emu10k1.h> 45#include <sound/emu10k1.h>
46#include <linux/firmware.h>
44#include "p16v.h" 47#include "p16v.h"
45#include "tina2.h" 48#include "tina2.h"
49#include "p17v.h"
46 50
47 51
48/************************************************************************* 52/*************************************************************************
@@ -117,11 +121,28 @@ static unsigned int spi_dac_init[] = {
117 0x0622, 121 0x0622,
118 0x1400, 122 0x1400,
119}; 123};
124
125static unsigned int i2c_adc_init[][2] = {
126 { 0x17, 0x00 }, /* Reset */
127 { 0x07, 0x00 }, /* Timeout */
128 { 0x0b, 0x22 }, /* Interface control */
129 { 0x0c, 0x22 }, /* Master mode control */
130 { 0x0d, 0x08 }, /* Powerdown control */
131 { 0x0e, 0xcf }, /* Attenuation Left 0x01 = -103dB, 0xff = 24dB */
132 { 0x0f, 0xcf }, /* Attenuation Right 0.5dB steps */
133 { 0x10, 0x7b }, /* ALC Control 1 */
134 { 0x11, 0x00 }, /* ALC Control 2 */
135 { 0x12, 0x32 }, /* ALC Control 3 */
136 { 0x13, 0x00 }, /* Noise gate control */
137 { 0x14, 0xa6 }, /* Limiter control */
138 { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for Audigy 2 ZS Notebook */
139};
120 140
121static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume) 141static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
122{ 142{
123 unsigned int silent_page; 143 unsigned int silent_page;
124 int ch; 144 int ch;
145 u32 tmp;
125 146
126 /* disable audio and lock cache */ 147 /* disable audio and lock cache */
127 outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE, 148 outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
@@ -160,8 +181,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
160 181
161 if (emu->card_capabilities->ca0151_chip) { /* audigy2 */ 182 if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
162 /* Hacks for Alice3 to work independent of haP16V driver */ 183 /* Hacks for Alice3 to work independent of haP16V driver */
163 u32 tmp;
164
165 //Setup SRCMulti_I2S SamplingRate 184 //Setup SRCMulti_I2S SamplingRate
166 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); 185 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
167 tmp &= 0xfffff1ff; 186 tmp &= 0xfffff1ff;
@@ -181,8 +200,6 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
181 } 200 }
182 if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */ 201 if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
183 /* Hacks for Alice3 to work independent of haP16V driver */ 202 /* Hacks for Alice3 to work independent of haP16V driver */
184 u32 tmp;
185
186 snd_printk(KERN_INFO "Audigy2 value: Special config.\n"); 203 snd_printk(KERN_INFO "Audigy2 value: Special config.\n");
187 //Setup SRCMulti_I2S SamplingRate 204 //Setup SRCMulti_I2S SamplingRate
188 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0); 205 tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
@@ -211,7 +228,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
211 int size, n; 228 int size, n;
212 229
213 size = ARRAY_SIZE(spi_dac_init); 230 size = ARRAY_SIZE(spi_dac_init);
214 for (n=0; n < size; n++) 231 for (n = 0; n < size; n++)
215 snd_emu10k1_spi_write(emu, spi_dac_init[n]); 232 snd_emu10k1_spi_write(emu, spi_dac_init[n]);
216 233
217 snd_emu10k1_ptr20_write(emu, 0x60, 0, 0x10); 234 snd_emu10k1_ptr20_write(emu, 0x60, 0, 0x10);
@@ -228,6 +245,23 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
228 outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */ 245 outl(0x76, emu->port + A_IOCFG); /* Windows uses 0x3f76 */
229 246
230 } 247 }
248 if (emu->card_capabilities->i2c_adc) { /* Audigy 2 ZS Notebook with ADC Wolfson WM8775 */
249 int size, n;
250
251 snd_emu10k1_ptr20_write(emu, P17V_I2S_SRC_SEL, 0, 0x2020205f);
252 tmp = inl(emu->port + A_IOCFG);
253 outl(tmp | 0x4, emu->port + A_IOCFG); /* Set bit 2 for mic input */
254 tmp = inl(emu->port + A_IOCFG);
255 size = ARRAY_SIZE(i2c_adc_init);
256 for (n = 0; n < size; n++)
257 snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]);
258 for (n=0; n < 4; n++) {
259 emu->i2c_capture_volume[n][0]= 0xcf;
260 emu->i2c_capture_volume[n][1]= 0xcf;
261 }
262
263 }
264
231 265
232 snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr); 266 snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
233 snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */ 267 snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */
@@ -239,6 +273,10 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
239 snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page); 273 snd_emu10k1_ptr_write(emu, MAPB, ch, silent_page);
240 } 274 }
241 275
276 if (emu->card_capabilities->emu1010) {
277 outl(HCFG_AUTOMUTE_ASYNC |
278 HCFG_EMU32_SLAVE |
279 HCFG_AUDIOENABLE, emu->port + HCFG);
242 /* 280 /*
243 * Hokay, setup HCFG 281 * Hokay, setup HCFG
244 * Mute Disable Audio = 0 282 * Mute Disable Audio = 0
@@ -246,7 +284,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
246 * Lock Sound Memory = 0 284 * Lock Sound Memory = 0
247 * Auto Mute = 1 285 * Auto Mute = 1
248 */ 286 */
249 if (emu->audigy) { 287 } else if (emu->audigy) {
250 if (emu->revision == 4) /* audigy2 */ 288 if (emu->revision == 4) /* audigy2 */
251 outl(HCFG_AUDIOENABLE | 289 outl(HCFG_AUDIOENABLE |
252 HCFG_AC3ENABLE_CDSPDIF | 290 HCFG_AC3ENABLE_CDSPDIF |
@@ -265,8 +303,10 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
265 outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG); 303 outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
266 304
267 if (enable_ir) { /* enable IR for SB Live */ 305 if (enable_ir) { /* enable IR for SB Live */
268 if ( emu->card_capabilities->emu1212m) { 306 if (emu->card_capabilities->emu1010) {
269 ; /* Disable all access to A_IOCFG for the emu1212m */ 307 ; /* Disable all access to A_IOCFG for the emu1010 */
308 } else if (emu->card_capabilities->i2c_adc) {
309 ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
270 } else if (emu->audigy) { 310 } else if (emu->audigy) {
271 unsigned int reg = inl(emu->port + A_IOCFG); 311 unsigned int reg = inl(emu->port + A_IOCFG);
272 outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG); 312 outl(reg | A_IOCFG_GPOUT2, emu->port + A_IOCFG);
@@ -284,8 +324,10 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
284 } 324 }
285 } 325 }
286 326
287 if ( emu->card_capabilities->emu1212m) { 327 if (emu->card_capabilities->emu1010) {
288 ; /* Disable all access to A_IOCFG for the emu1212m */ 328 ; /* Disable all access to A_IOCFG for the emu1010 */
329 } else if (emu->card_capabilities->i2c_adc) {
330 ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
289 } else if (emu->audigy) { /* enable analog output */ 331 } else if (emu->audigy) { /* enable analog output */
290 unsigned int reg = inl(emu->port + A_IOCFG); 332 unsigned int reg = inl(emu->port + A_IOCFG);
291 outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG); 333 outl(reg | A_IOCFG_GPOUT0, emu->port + A_IOCFG);
@@ -302,8 +344,10 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
302 outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG); 344 outl(inl(emu->port + HCFG) | HCFG_AUDIOENABLE, emu->port + HCFG);
303 345
304 /* Enable analog/digital outs on audigy */ 346 /* Enable analog/digital outs on audigy */
305 if ( emu->card_capabilities->emu1212m) { 347 if (emu->card_capabilities->emu1010) {
306 ; /* Disable all access to A_IOCFG for the emu1212m */ 348 ; /* Disable all access to A_IOCFG for the emu1010 */
349 } else if (emu->card_capabilities->i2c_adc) {
350 ; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
307 } else if (emu->audigy) { 351 } else if (emu->audigy) {
308 outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG); 352 outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
309 353
@@ -596,133 +640,423 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu)
596 return 0; 640 return 0;
597} 641}
598 642
599static int snd_emu1212m_fpga_write(struct snd_emu10k1 * emu, int reg, int value) 643static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * filename)
600{ 644{
601 if (reg<0 || reg>0x3f) 645 int err;
602 return 1; 646 int n, i;
603 reg+=0x40; /* 0x40 upwards are registers. */ 647 int reg;
604 if (value<0 || value>0x3f) /* 0 to 0x3f are values */ 648 int value;
605 return 1; 649 const struct firmware *fw_entry;
606 outl(reg, emu->port + A_IOCFG); 650
607 outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ 651 if ((err = request_firmware(&fw_entry, filename, &emu->pci->dev)) != 0) {
608 outl(value, emu->port + A_IOCFG); 652 snd_printk(KERN_ERR "firmware: %s not found. Err=%d\n",filename, err);
609 outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */ 653 return err;
610 654 }
611 return 0; 655 snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size);
612} 656 if (fw_entry->size != 0x133a4) {
613 657 snd_printk(KERN_ERR "firmware: %s wrong size.\n",filename);
614static int snd_emu1212m_fpga_read(struct snd_emu10k1 * emu, int reg, int *value) 658 return -EINVAL;
615{ 659 }
616 if (reg<0 || reg>0x3f)
617 return 1;
618 reg+=0x40; /* 0x40 upwards are registers. */
619 outl(reg, emu->port + A_IOCFG);
620 outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
621 *value = inl(emu->port + A_IOCFG);
622
623 return 0;
624}
625 660
626static int snd_emu1212m_fpga_netlist_write(struct snd_emu10k1 * emu, int reg, int value) 661 /* The FPGA is a Xilinx Spartan IIE XC2S50E */
627{ 662 /* GPIO7 -> FPGA PGMN
628 snd_emu1212m_fpga_write(emu, 0x00, ((reg >> 8) & 0x3f) ); 663 * GPIO6 -> FPGA CCLK
629 snd_emu1212m_fpga_write(emu, 0x01, (reg & 0x3f) ); 664 * GPIO5 -> FPGA DIN
630 snd_emu1212m_fpga_write(emu, 0x02, ((value >> 8) & 0x3f) ); 665 * FPGA CONFIG OFF -> FPGA PGMN
631 snd_emu1212m_fpga_write(emu, 0x03, (value & 0x3f) ); 666 */
667 outl(0x00, emu->port + A_IOCFG); /* Set PGMN low for 1uS. */
668 udelay(1);
669 outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */
670 udelay(100); /* Allow FPGA memory to clean */
671 for(n = 0; n < fw_entry->size; n++) {
672 value=fw_entry->data[n];
673 for(i = 0; i < 8; i++) {
674 reg = 0x80;
675 if (value & 0x1)
676 reg = reg | 0x20;
677 value = value >> 1;
678 outl(reg, emu->port + A_IOCFG);
679 outl(reg | 0x40, emu->port + A_IOCFG);
680 }
681 }
682 /* After programming, set GPIO bit 4 high again. */
683 outl(0x10, emu->port + A_IOCFG);
684
632 685
686 release_firmware(fw_entry);
633 return 0; 687 return 0;
634} 688}
635 689
636static int snd_emu10k1_emu1212m_init(struct snd_emu10k1 * emu) 690static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
637{ 691{
638 unsigned int i; 692 unsigned int i;
639 int tmp; 693 int tmp,tmp2;
640 694 int reg;
641 snd_printk(KERN_ERR "emu1212m: Special config.\n"); 695 int err;
696 const char *hana_filename = "emu/hana.fw";
697 const char *dock_filename = "emu/audio_dock.fw";
698
699 snd_printk(KERN_INFO "emu1010: Special config.\n");
700 /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
701 * Lock Sound Memory Cache, Lock Tank Memory Cache,
702 * Mute all codecs.
703 */
642 outl(0x0005a00c, emu->port + HCFG); 704 outl(0x0005a00c, emu->port + HCFG);
643 outl(0x0005a004, emu->port + HCFG); 705 /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
706 * Lock Tank Memory Cache,
707 * Mute all codecs.
708 */
709 outl(0x0005a004, emu->port + HCFG);
710 /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
711 * Mute all codecs.
712 */
644 outl(0x0005a000, emu->port + HCFG); 713 outl(0x0005a000, emu->port + HCFG);
714 /* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
715 * Mute all codecs.
716 */
645 outl(0x0005a000, emu->port + HCFG); 717 outl(0x0005a000, emu->port + HCFG);
646 718
647 snd_emu1212m_fpga_read(emu, 0x22, &tmp ); 719 /* Disable 48Volt power to Audio Dock */
648 snd_emu1212m_fpga_read(emu, 0x23, &tmp ); 720 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 );
649 snd_emu1212m_fpga_read(emu, 0x24, &tmp ); 721
650 snd_emu1212m_fpga_write(emu, 0x04, 0x01 ); 722 /* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */
651 snd_emu1212m_fpga_read(emu, 0x0b, &tmp ); 723 snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
652 snd_emu1212m_fpga_write(emu, 0x0b, 0x01 ); 724 snd_printdd("reg1=0x%x\n",reg);
653 snd_emu1212m_fpga_read(emu, 0x10, &tmp ); 725 if (reg == 0x55) {
654 snd_emu1212m_fpga_write(emu, 0x10, 0x00 ); 726 /* FPGA netlist already present so clear it */
655 snd_emu1212m_fpga_read(emu, 0x11, &tmp ); 727 /* Return to programming mode */
656 snd_emu1212m_fpga_write(emu, 0x11, 0x30 ); 728
657 snd_emu1212m_fpga_read(emu, 0x13, &tmp ); 729 snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02 );
658 snd_emu1212m_fpga_write(emu, 0x13, 0x0f );
659 snd_emu1212m_fpga_read(emu, 0x11, &tmp );
660 snd_emu1212m_fpga_write(emu, 0x11, 0x30 );
661 snd_emu1212m_fpga_read(emu, 0x0a, &tmp );
662 snd_emu1212m_fpga_write(emu, 0x0a, 0x10 );
663 snd_emu1212m_fpga_write(emu, 0x0c, 0x19 );
664 snd_emu1212m_fpga_write(emu, 0x12, 0x0c );
665 snd_emu1212m_fpga_write(emu, 0x09, 0x0f );
666 snd_emu1212m_fpga_write(emu, 0x06, 0x00 );
667 snd_emu1212m_fpga_write(emu, 0x05, 0x00 );
668 snd_emu1212m_fpga_write(emu, 0x0e, 0x12 );
669 snd_emu1212m_fpga_netlist_write(emu, 0x0000, 0x0200);
670 snd_emu1212m_fpga_netlist_write(emu, 0x0001, 0x0201);
671 snd_emu1212m_fpga_netlist_write(emu, 0x0002, 0x0500);
672 snd_emu1212m_fpga_netlist_write(emu, 0x0003, 0x0501);
673 snd_emu1212m_fpga_netlist_write(emu, 0x0004, 0x0400);
674 snd_emu1212m_fpga_netlist_write(emu, 0x0005, 0x0401);
675 snd_emu1212m_fpga_netlist_write(emu, 0x0006, 0x0402);
676 snd_emu1212m_fpga_netlist_write(emu, 0x0007, 0x0403);
677 snd_emu1212m_fpga_netlist_write(emu, 0x0008, 0x0404);
678 snd_emu1212m_fpga_netlist_write(emu, 0x0009, 0x0405);
679 snd_emu1212m_fpga_netlist_write(emu, 0x000a, 0x0406);
680 snd_emu1212m_fpga_netlist_write(emu, 0x000b, 0x0407);
681 snd_emu1212m_fpga_netlist_write(emu, 0x000c, 0x0100);
682 snd_emu1212m_fpga_netlist_write(emu, 0x000d, 0x0104);
683 snd_emu1212m_fpga_netlist_write(emu, 0x000e, 0x0200);
684 snd_emu1212m_fpga_netlist_write(emu, 0x000f, 0x0201);
685 for (i=0;i < 0x20;i++) {
686 snd_emu1212m_fpga_netlist_write(emu, 0x0100+i, 0x0000);
687 } 730 }
688 for (i=0;i < 4;i++) { 731 snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
689 snd_emu1212m_fpga_netlist_write(emu, 0x0200+i, 0x0000); 732 snd_printdd("reg2=0x%x\n",reg);
733 if (reg == 0x55) {
734 /* FPGA failed to return to programming mode */
735 return -ENODEV;
690 } 736 }
691 for (i=0;i < 7;i++) { 737 snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg);
692 snd_emu1212m_fpga_netlist_write(emu, 0x0300+i, 0x0000); 738 if ((err = snd_emu1010_load_firmware(emu, hana_filename)) != 0) {
739 snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file %s failed\n", hana_filename);
740 return err;
693 } 741 }
694 for (i=0;i < 7;i++) { 742
695 snd_emu1212m_fpga_netlist_write(emu, 0x0400+i, 0x0000); 743 /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
744 snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
745 if (reg != 0x55) {
746 /* FPGA failed to be programmed */
747 snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg);
748 return -ENODEV;
696 } 749 }
697 snd_emu1212m_fpga_netlist_write(emu, 0x0500, 0x0108);
698 snd_emu1212m_fpga_netlist_write(emu, 0x0501, 0x010c);
699 snd_emu1212m_fpga_netlist_write(emu, 0x0600, 0x0110);
700 snd_emu1212m_fpga_netlist_write(emu, 0x0601, 0x0114);
701 snd_emu1212m_fpga_netlist_write(emu, 0x0700, 0x0118);
702 snd_emu1212m_fpga_netlist_write(emu, 0x0701, 0x011c);
703 snd_emu1212m_fpga_write(emu, 0x07, 0x01 );
704 750
705 snd_emu1212m_fpga_read(emu, 0x21, &tmp ); 751 snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n");
752 snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp );
753 snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2 );
754 snd_printk("Hana ver:%d.%d\n",tmp ,tmp2);
755 /* Enable 48Volt power to Audio Dock */
756 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON );
757
758 snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
759 snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
760 snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
761 snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
762 snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp );
763 /* ADAT input. */
764 snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x01 );
765 snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp );
766 /* Set no attenuation on Audio Dock pads. */
767 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 );
768 emu->emu1010.adc_pads = 0x00;
769 snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
770 /* Unmute Audio dock DACs, Headphone source DAC-4. */
771 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
772 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
773 snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp );
774 /* DAC PADs. */
775 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f );
776 emu->emu1010.dac_pads = 0x0f;
777 snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
778 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
779 snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp );
780 /* SPDIF Format. Set Consumer mode, 24bit, copy enable */
781 snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 );
782 /* MIDI routing */
783 snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 );
784 /* Unknown. */
785 snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c );
786 /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); // IRQ Enable: All on */
787 /* IRQ Enable: All off */
788 snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00 );
789
790 snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
791 snd_printk(KERN_INFO "emu1010: Card options3=0x%x\n",reg);
792 /* Default WCLK set to 48kHz. */
793 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00 );
794 /* Word Clock source, Internal 48kHz x1 */
795 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
796 //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
797 /* Audio Dock LEDs. */
798 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
706 799
707 outl(0x0000a000, emu->port + HCFG); 800#if 0
801 /* For 96kHz */
802 snd_emu1010_fpga_link_dst_src_write(emu,
803 EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1);
804 snd_emu1010_fpga_link_dst_src_write(emu,
805 EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1);
806 snd_emu1010_fpga_link_dst_src_write(emu,
807 EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT2);
808 snd_emu1010_fpga_link_dst_src_write(emu,
809 EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT2);
810#endif
811#if 0
812 /* For 192kHz */
813 snd_emu1010_fpga_link_dst_src_write(emu,
814 EMU_DST_ALICE2_EMU32_0, EMU_SRC_HAMOA_ADC_LEFT1);
815 snd_emu1010_fpga_link_dst_src_write(emu,
816 EMU_DST_ALICE2_EMU32_1, EMU_SRC_HAMOA_ADC_RIGHT1);
817 snd_emu1010_fpga_link_dst_src_write(emu,
818 EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2);
819 snd_emu1010_fpga_link_dst_src_write(emu,
820 EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_RIGHT2);
821 snd_emu1010_fpga_link_dst_src_write(emu,
822 EMU_DST_ALICE2_EMU32_4, EMU_SRC_HAMOA_ADC_LEFT3);
823 snd_emu1010_fpga_link_dst_src_write(emu,
824 EMU_DST_ALICE2_EMU32_5, EMU_SRC_HAMOA_ADC_RIGHT3);
825 snd_emu1010_fpga_link_dst_src_write(emu,
826 EMU_DST_ALICE2_EMU32_6, EMU_SRC_HAMOA_ADC_LEFT4);
827 snd_emu1010_fpga_link_dst_src_write(emu,
828 EMU_DST_ALICE2_EMU32_7, EMU_SRC_HAMOA_ADC_RIGHT4);
829#endif
830#if 1
831 /* For 48kHz */
832 snd_emu1010_fpga_link_dst_src_write(emu,
833 EMU_DST_ALICE2_EMU32_0, EMU_SRC_DOCK_MIC_A1);
834 snd_emu1010_fpga_link_dst_src_write(emu,
835 EMU_DST_ALICE2_EMU32_1, EMU_SRC_DOCK_MIC_B1);
836 snd_emu1010_fpga_link_dst_src_write(emu,
837 EMU_DST_ALICE2_EMU32_2, EMU_SRC_HAMOA_ADC_LEFT2);
838 snd_emu1010_fpga_link_dst_src_write(emu,
839 EMU_DST_ALICE2_EMU32_3, EMU_SRC_HAMOA_ADC_LEFT2);
840 snd_emu1010_fpga_link_dst_src_write(emu,
841 EMU_DST_ALICE2_EMU32_4, EMU_SRC_DOCK_ADC1_LEFT1);
842 snd_emu1010_fpga_link_dst_src_write(emu,
843 EMU_DST_ALICE2_EMU32_5, EMU_SRC_DOCK_ADC1_RIGHT1);
844 snd_emu1010_fpga_link_dst_src_write(emu,
845 EMU_DST_ALICE2_EMU32_6, EMU_SRC_DOCK_ADC2_LEFT1);
846 snd_emu1010_fpga_link_dst_src_write(emu,
847 EMU_DST_ALICE2_EMU32_7, EMU_SRC_DOCK_ADC2_RIGHT1);
848#endif
849#if 0
850 /* Original */
851 snd_emu1010_fpga_link_dst_src_write(emu,
852 EMU_DST_ALICE2_EMU32_4, EMU_SRC_HANA_ADAT);
853 snd_emu1010_fpga_link_dst_src_write(emu,
854 EMU_DST_ALICE2_EMU32_5, EMU_SRC_HANA_ADAT + 1);
855 snd_emu1010_fpga_link_dst_src_write(emu,
856 EMU_DST_ALICE2_EMU32_6, EMU_SRC_HANA_ADAT + 2);
857 snd_emu1010_fpga_link_dst_src_write(emu,
858 EMU_DST_ALICE2_EMU32_7, EMU_SRC_HANA_ADAT + 3);
859 snd_emu1010_fpga_link_dst_src_write(emu,
860 EMU_DST_ALICE2_EMU32_8, EMU_SRC_HANA_ADAT + 4);
861 snd_emu1010_fpga_link_dst_src_write(emu,
862 EMU_DST_ALICE2_EMU32_9, EMU_SRC_HANA_ADAT + 5);
863 snd_emu1010_fpga_link_dst_src_write(emu,
864 EMU_DST_ALICE2_EMU32_A, EMU_SRC_HANA_ADAT + 6);
865 snd_emu1010_fpga_link_dst_src_write(emu,
866 EMU_DST_ALICE2_EMU32_B, EMU_SRC_HANA_ADAT + 7);
867 snd_emu1010_fpga_link_dst_src_write(emu,
868 EMU_DST_ALICE2_EMU32_C, EMU_SRC_DOCK_MIC_A1);
869 snd_emu1010_fpga_link_dst_src_write(emu,
870 EMU_DST_ALICE2_EMU32_D, EMU_SRC_DOCK_MIC_B1);
871 snd_emu1010_fpga_link_dst_src_write(emu,
872 EMU_DST_ALICE2_EMU32_E, EMU_SRC_HAMOA_ADC_LEFT2);
873 snd_emu1010_fpga_link_dst_src_write(emu,
874 EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2);
875#endif
876 for (i = 0;i < 0x20; i++ ) {
877 /* AudioDock Elink <- Silence */
878 snd_emu1010_fpga_link_dst_src_write(emu, 0x0100+i, EMU_SRC_SILENCE);
879 }
880 for (i = 0;i < 4; i++) {
881 /* Hana SPDIF Out <- Silence */
882 snd_emu1010_fpga_link_dst_src_write(emu, 0x0200+i, EMU_SRC_SILENCE);
883 }
884 for (i = 0;i < 7; i++) {
885 /* Hamoa DAC <- Silence */
886 snd_emu1010_fpga_link_dst_src_write(emu, 0x0300+i, EMU_SRC_SILENCE);
887 }
888 for (i = 0;i < 7; i++) {
889 /* Hana ADAT Out <- Silence */
890 snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE);
891 }
892 snd_emu1010_fpga_link_dst_src_write(emu,
893 EMU_DST_ALICE_I2S0_LEFT, EMU_SRC_DOCK_ADC1_LEFT1);
894 snd_emu1010_fpga_link_dst_src_write(emu,
895 EMU_DST_ALICE_I2S0_RIGHT, EMU_SRC_DOCK_ADC1_RIGHT1);
896 snd_emu1010_fpga_link_dst_src_write(emu,
897 EMU_DST_ALICE_I2S1_LEFT, EMU_SRC_DOCK_ADC2_LEFT1);
898 snd_emu1010_fpga_link_dst_src_write(emu,
899 EMU_DST_ALICE_I2S1_RIGHT, EMU_SRC_DOCK_ADC2_RIGHT1);
900 snd_emu1010_fpga_link_dst_src_write(emu,
901 EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1);
902 snd_emu1010_fpga_link_dst_src_write(emu,
903 EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1);
904 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01 ); // Unmute all
905
906 snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
907
908 /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
909 * Lock Sound Memory Cache, Lock Tank Memory Cache,
910 * Mute all codecs.
911 */
912 outl(0x0000a000, emu->port + HCFG);
913 /* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
914 * Lock Sound Memory Cache, Lock Tank Memory Cache,
915 * Un-Mute all codecs.
916 */
708 outl(0x0000a001, emu->port + HCFG); 917 outl(0x0000a001, emu->port + HCFG);
918
709 /* Initial boot complete. Now patches */ 919 /* Initial boot complete. Now patches */
710 920
711 snd_emu1212m_fpga_read(emu, 0x21, &tmp ); 921 snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
712 snd_emu1212m_fpga_write(emu, 0x0c, 0x19 ); 922 snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */
713 snd_emu1212m_fpga_write(emu, 0x12, 0x0c ); 923 snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */
714 snd_emu1212m_fpga_write(emu, 0x0c, 0x19 ); 924 snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */
715 snd_emu1212m_fpga_write(emu, 0x12, 0x0c ); 925 snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */
716 snd_emu1212m_fpga_read(emu, 0x0a, &tmp ); 926 snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp );
717 snd_emu1212m_fpga_write(emu, 0x0a, 0x10 ); 927 snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */
718 928
719 snd_emu1212m_fpga_read(emu, 0x20, &tmp ); 929 /* Delay to allow Audio Dock to settle */
720 snd_emu1212m_fpga_read(emu, 0x21, &tmp ); 930 msleep(100);
721 931 snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */
722 snd_emu1212m_fpga_netlist_write(emu, 0x0300, 0x0312); 932 snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg ); /* OPTIONS: Which cards are attached to the EMU */
723 snd_emu1212m_fpga_netlist_write(emu, 0x0301, 0x0313); 933 /* FIXME: The loading of this should be able to happen any time,
724 snd_emu1212m_fpga_netlist_write(emu, 0x0200, 0x0302); 934 * as the user can plug/unplug it at any time
725 snd_emu1212m_fpga_netlist_write(emu, 0x0201, 0x0303); 935 */
936 if (reg & (EMU_HANA_OPTION_DOCK_ONLINE | EMU_HANA_OPTION_DOCK_OFFLINE) ) {
937 /* Audio Dock attached */
938 /* Return to Audio Dock programming mode */
939 snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
940 snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
941 if ((err = snd_emu1010_load_firmware(emu, dock_filename)) != 0) {
942 return err;
943 }
944 snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 );
945 snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg );
946 snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg);
947 /* ID, should read & 0x7f = 0x55 when FPGA programmed. */
948 snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
949 snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg);
950 if (reg != 0x55) {
951 /* FPGA failed to be programmed */
952 snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg);
953 return 0;
954 return -ENODEV;
955 }
956 snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n");
957 snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp );
958 snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 );
959 snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2);
960 }
961#if 0
962 snd_emu1010_fpga_link_dst_src_write(emu,
963 EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32B + 2); /* ALICE2 bus 0xa2 */
964 snd_emu1010_fpga_link_dst_src_write(emu,
965 EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32B + 3); /* ALICE2 bus 0xa3 */
966 snd_emu1010_fpga_link_dst_src_write(emu,
967 EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 2); /* ALICE2 bus 0xb2 */
968 snd_emu1010_fpga_link_dst_src_write(emu,
969 EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 3); /* ALICE2 bus 0xb3 */
970#endif
971 /* Default outputs */
972 snd_emu1010_fpga_link_dst_src_write(emu,
973 EMU_DST_DOCK_DAC1_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
974 emu->emu1010.output_source[0] = 21;
975 snd_emu1010_fpga_link_dst_src_write(emu,
976 EMU_DST_DOCK_DAC1_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
977 emu->emu1010.output_source[1] = 22;
978 snd_emu1010_fpga_link_dst_src_write(emu,
979 EMU_DST_DOCK_DAC2_LEFT1, EMU_SRC_ALICE_EMU32A + 2);
980 emu->emu1010.output_source[2] = 23;
981 snd_emu1010_fpga_link_dst_src_write(emu,
982 EMU_DST_DOCK_DAC2_RIGHT1, EMU_SRC_ALICE_EMU32A + 3);
983 emu->emu1010.output_source[3] = 24;
984 snd_emu1010_fpga_link_dst_src_write(emu,
985 EMU_DST_DOCK_DAC3_LEFT1, EMU_SRC_ALICE_EMU32A + 4);
986 emu->emu1010.output_source[4] = 25;
987 snd_emu1010_fpga_link_dst_src_write(emu,
988 EMU_DST_DOCK_DAC3_RIGHT1, EMU_SRC_ALICE_EMU32A + 5);
989 emu->emu1010.output_source[5] = 26;
990 snd_emu1010_fpga_link_dst_src_write(emu,
991 EMU_DST_DOCK_DAC4_LEFT1, EMU_SRC_ALICE_EMU32A + 6);
992 emu->emu1010.output_source[6] = 27;
993 snd_emu1010_fpga_link_dst_src_write(emu,
994 EMU_DST_DOCK_DAC4_RIGHT1, EMU_SRC_ALICE_EMU32A + 7);
995 emu->emu1010.output_source[7] = 28;
996 snd_emu1010_fpga_link_dst_src_write(emu,
997 EMU_DST_DOCK_PHONES_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
998 emu->emu1010.output_source[8] = 21;
999 snd_emu1010_fpga_link_dst_src_write(emu,
1000 EMU_DST_DOCK_PHONES_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
1001 emu->emu1010.output_source[9] = 22;
1002 snd_emu1010_fpga_link_dst_src_write(emu,
1003 EMU_DST_DOCK_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
1004 emu->emu1010.output_source[10] = 21;
1005 snd_emu1010_fpga_link_dst_src_write(emu,
1006 EMU_DST_DOCK_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
1007 emu->emu1010.output_source[11] = 22;
1008 snd_emu1010_fpga_link_dst_src_write(emu,
1009 EMU_DST_HANA_SPDIF_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
1010 emu->emu1010.output_source[12] = 21;
1011 snd_emu1010_fpga_link_dst_src_write(emu,
1012 EMU_DST_HANA_SPDIF_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
1013 emu->emu1010.output_source[13] = 22;
1014 snd_emu1010_fpga_link_dst_src_write(emu,
1015 EMU_DST_HAMOA_DAC_LEFT1, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
1016 emu->emu1010.output_source[14] = 21;
1017 snd_emu1010_fpga_link_dst_src_write(emu,
1018 EMU_DST_HAMOA_DAC_RIGHT1, EMU_SRC_ALICE_EMU32A + 1);
1019 emu->emu1010.output_source[15] = 22;
1020 snd_emu1010_fpga_link_dst_src_write(emu,
1021 EMU_DST_HANA_ADAT, EMU_SRC_ALICE_EMU32A + 0); /* ALICE2 bus 0xa0 */
1022 emu->emu1010.output_source[16] = 21;
1023 snd_emu1010_fpga_link_dst_src_write(emu,
1024 EMU_DST_HANA_ADAT + 1, EMU_SRC_ALICE_EMU32A + 1);
1025 emu->emu1010.output_source[17] = 22;
1026 snd_emu1010_fpga_link_dst_src_write(emu,
1027 EMU_DST_HANA_ADAT + 2, EMU_SRC_ALICE_EMU32A + 2);
1028 emu->emu1010.output_source[18] = 23;
1029 snd_emu1010_fpga_link_dst_src_write(emu,
1030 EMU_DST_HANA_ADAT + 3, EMU_SRC_ALICE_EMU32A + 3);
1031 emu->emu1010.output_source[19] = 24;
1032 snd_emu1010_fpga_link_dst_src_write(emu,
1033 EMU_DST_HANA_ADAT + 4, EMU_SRC_ALICE_EMU32A + 4);
1034 emu->emu1010.output_source[20] = 25;
1035 snd_emu1010_fpga_link_dst_src_write(emu,
1036 EMU_DST_HANA_ADAT + 5, EMU_SRC_ALICE_EMU32A + 5);
1037 emu->emu1010.output_source[21] = 26;
1038 snd_emu1010_fpga_link_dst_src_write(emu,
1039 EMU_DST_HANA_ADAT + 6, EMU_SRC_ALICE_EMU32A + 6);
1040 emu->emu1010.output_source[22] = 27;
1041 snd_emu1010_fpga_link_dst_src_write(emu,
1042 EMU_DST_HANA_ADAT + 7, EMU_SRC_ALICE_EMU32A + 7);
1043 emu->emu1010.output_source[23] = 28;
1044
1045 /* TEMP: Select SPDIF in/out */
1046 snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */
1047
1048 /* TEMP: Select 48kHz SPDIF out */
1049 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */
1050 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */
1051 /* Word Clock source, Internal 48kHz x1 */
1052 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
1053 //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
1054 emu->emu1010.internal_clock = 1; /* 48000 */
1055 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);/* Set LEDs on Audio Dock */
1056 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */
1057 //snd_emu1010_fpga_write(emu, 0x7, 0x0); /* Mute all */
1058 //snd_emu1010_fpga_write(emu, 0x7, 0x1); /* Unmute all */
1059 //snd_emu1010_fpga_write(emu, 0xe, 0x12); /* Set LEDs on Audio Dock */
726 1060
727 return 0; 1061 return 0;
728} 1062}
@@ -747,6 +1081,10 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
747 } 1081 }
748 snd_emu10k1_free_efx(emu); 1082 snd_emu10k1_free_efx(emu);
749 } 1083 }
1084 if (emu->card_capabilities->emu1010) {
1085 /* Disable 48Volt power to Audio Dock */
1086 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 );
1087 }
750 if (emu->memhdr) 1088 if (emu->memhdr)
751 snd_util_memhdr_free(emu->memhdr); 1089 snd_util_memhdr_free(emu->memhdr);
752 if (emu->silent_page.area) 1090 if (emu->silent_page.area)
@@ -838,10 +1176,11 @@ static struct snd_emu_chip_details emu_chip_details[] = {
838 .adc_1361t = 1, /* 24 bit capture instead of 16bit */ 1176 .adc_1361t = 1, /* 24 bit capture instead of 16bit */
839 .ac97_chip = 1} , 1177 .ac97_chip = 1} ,
840 /* Audigy 2 ZS Notebook Cardbus card.*/ 1178 /* Audigy 2 ZS Notebook Cardbus card.*/
841 /* Tested by James@superbug.co.uk 22th December 2005 */ 1179 /* Tested by James@superbug.co.uk 6th November 2006 */
842 /* Audio output 7.1/Headphones working. 1180 /* Audio output 7.1/Headphones working.
843 * Digital output working. (AC3 not checked, only PCM) 1181 * Digital output working. (AC3 not checked, only PCM)
844 * Audio inputs not tested. 1182 * Audio Mic/Line inputs working.
1183 * Digital input not tested.
845 */ 1184 */
846 /* DSP: Tina2 1185 /* DSP: Tina2
847 * DAC: Wolfson WM8768/WM8568 1186 * DAC: Wolfson WM8768/WM8568
@@ -849,6 +1188,25 @@ static struct snd_emu_chip_details emu_chip_details[] = {
849 * AC97: None 1188 * AC97: None
850 * CA0151: None 1189 * CA0151: None
851 */ 1190 */
1191 /* Tested by James@superbug.co.uk 4th April 2006 */
1192 /* A_IOCFG bits
1193 * Output
1194 * 0: Not Used
1195 * 1: 0 = Mute all the 7.1 channel out. 1 = unmute.
1196 * 2: Analog input 0 = line in, 1 = mic in
1197 * 3: Not Used
1198 * 4: Digital output 0 = off, 1 = on.
1199 * 5: Not Used
1200 * 6: Not Used
1201 * 7: Not Used
1202 * Input
1203 * All bits 1 (0x3fxx) means nothing plugged in.
1204 * 8-9: 0 = Line in/Mic, 2 = Optical in, 3 = Nothing.
1205 * A-B: 0 = Headphones, 2 = Optical out, 3 = Nothing.
1206 * C-D: 2 = Front/Rear/etc, 3 = nothing.
1207 * E-F: Always 0
1208 *
1209 */
852 {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102, 1210 {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
853 .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]", 1211 .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
854 .id = "Audigy2", 1212 .id = "Audigy2",
@@ -856,6 +1214,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
856 .ca0108_chip = 1, 1214 .ca0108_chip = 1,
857 .ca_cardbus_chip = 1, 1215 .ca_cardbus_chip = 1,
858 .spi_dac = 1, 1216 .spi_dac = 1,
1217 .i2c_adc = 1,
859 .spk71 = 1} , 1218 .spk71 = 1} ,
860 {.vendor = 0x1102, .device = 0x0008, 1219 {.vendor = 0x1102, .device = 0x0008,
861 .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]", 1220 .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
@@ -865,11 +1224,12 @@ static struct snd_emu_chip_details emu_chip_details[] = {
865 .ac97_chip = 1} , 1224 .ac97_chip = 1} ,
866 /* Tested by James@superbug.co.uk 8th July 2005. No sound available yet. */ 1225 /* Tested by James@superbug.co.uk 8th July 2005. No sound available yet. */
867 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102, 1226 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
868 .driver = "Audigy2", .name = "E-mu 1212m [4001]", 1227 .driver = "Audigy2", .name = "E-mu 1010 [4001]",
869 .id = "EMU1212m", 1228 .id = "EMU1010",
870 .emu10k2_chip = 1, 1229 .emu10k2_chip = 1,
871 .ca0102_chip = 1, 1230 .ca0102_chip = 1,
872 .emu1212m = 1} , 1231 .spk71 = 1,
1232 .emu1010 = 1} ,
873 /* Tested by James@superbug.co.uk 3rd July 2005 */ 1233 /* Tested by James@superbug.co.uk 3rd July 2005 */
874 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102, 1234 {.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
875 .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]", 1235 .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
@@ -1297,8 +1657,8 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
1297 } else if (emu->card_capabilities->ca_cardbus_chip) { 1657 } else if (emu->card_capabilities->ca_cardbus_chip) {
1298 if ((err = snd_emu10k1_cardbus_init(emu)) < 0) 1658 if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
1299 goto error; 1659 goto error;
1300 } else if (emu->card_capabilities->emu1212m) { 1660 } else if (emu->card_capabilities->emu1010) {
1301 if ((err = snd_emu10k1_emu1212m_init(emu)) < 0) { 1661 if ((err = snd_emu10k1_emu1010_init(emu)) < 0) {
1302 snd_emu10k1_free(emu); 1662 snd_emu10k1_free(emu);
1303 return err; 1663 return err;
1304 } 1664 }
@@ -1446,8 +1806,8 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
1446 snd_emu10k1_ecard_init(emu); 1806 snd_emu10k1_ecard_init(emu);
1447 else if (emu->card_capabilities->ca_cardbus_chip) 1807 else if (emu->card_capabilities->ca_cardbus_chip)
1448 snd_emu10k1_cardbus_init(emu); 1808 snd_emu10k1_cardbus_init(emu);
1449 else if (emu->card_capabilities->emu1212m) 1809 else if (emu->card_capabilities->emu1010)
1450 snd_emu10k1_emu1212m_init(emu); 1810 snd_emu10k1_emu1010_init(emu);
1451 else 1811 else
1452 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE); 1812 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
1453 snd_emu10k1_init(emu, emu->enable_ir, 1); 1813 snd_emu10k1_init(emu, emu->enable_ir, 1);
diff --git a/sound/pci/emu10k1/emu10k1x.c b/sound/pci/emu10k1/emu10k1x.c
index 2199b42a6019..bb0fec7f7e1b 100644
--- a/sound/pci/emu10k1/emu10k1x.c
+++ b/sound/pci/emu10k1/emu10k1x.c
@@ -460,7 +460,7 @@ static int snd_emu10k1x_pcm_prepare(struct snd_pcm_substream *substream)
460 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size); 460 u32 period_size_bytes = frames_to_bytes(runtime, runtime->period_size);
461 int i; 461 int i;
462 462
463 for(i=0; i < runtime->periods; i++) { 463 for(i = 0; i < runtime->periods; i++) {
464 *table_base++=runtime->dma_addr+(i*period_size_bytes); 464 *table_base++=runtime->dma_addr+(i*period_size_bytes);
465 *table_base++=period_size_bytes<<16; 465 *table_base++=period_size_bytes<<16;
466 } 466 }
@@ -1042,8 +1042,8 @@ static void snd_emu10k1x_proc_reg_write(struct snd_info_entry *entry,
1042 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3) 1042 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
1043 continue; 1043 continue;
1044 1044
1045 if ((reg < 0x49) && (reg >=0) && (val <= 0xffffffff) 1045 if ((reg < 0x49) && (reg >= 0) && (val <= 0xffffffff)
1046 && (channel_id >=0) && (channel_id <= 2) ) 1046 && (channel_id >= 0) && (channel_id <= 2) )
1047 snd_emu10k1x_ptr_write(emu, reg, channel_id, val); 1047 snd_emu10k1x_ptr_write(emu, reg, channel_id, val);
1048 } 1048 }
1049} 1049}
diff --git a/sound/pci/emu10k1/emufx.c b/sound/pci/emu10k1/emufx.c
index 13cd6ce89811..c02012cccd8e 100644
--- a/sound/pci/emu10k1/emufx.c
+++ b/sound/pci/emu10k1/emufx.c
@@ -3,6 +3,9 @@
3 * Creative Labs, Inc. 3 * Creative Labs, Inc.
4 * Routines for effect processor FX8010 4 * Routines for effect processor FX8010
5 * 5 *
6 * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
7 * Added EMU 1010 support.
8 *
6 * BUGS: 9 * BUGS:
7 * -- 10 * --
8 * 11 *
@@ -293,7 +296,7 @@ static const u32 db_table[101] = {
293}; 296};
294 297
295/* EMU10k1/EMU10k2 DSP control db gain */ 298/* EMU10k1/EMU10k2 DSP control db gain */
296static DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1); 299static const DECLARE_TLV_DB_SCALE(snd_emu10k1_db_scale1, -4000, 40, 1);
297 300
298static const u32 onoff_table[2] = { 301static const u32 onoff_table[2] = {
299 0x00000000, 0x00000001 302 0x00000000, 0x00000001
@@ -652,13 +655,66 @@ snd_emu10k1_look_for_ctl(struct snd_emu10k1 *emu, struct snd_ctl_elem_id *id)
652 return NULL; 655 return NULL;
653} 656}
654 657
658#define MAX_TLV_SIZE 256
659
660static unsigned int *copy_tlv(const unsigned int __user *_tlv)
661{
662 unsigned int data[2];
663 unsigned int *tlv;
664
665 if (!_tlv)
666 return NULL;
667 if (copy_from_user(data, _tlv, sizeof(data)))
668 return NULL;
669 if (data[1] >= MAX_TLV_SIZE)
670 return NULL;
671 tlv = kmalloc(data[1] * 4 + sizeof(data), GFP_KERNEL);
672 if (!tlv)
673 return NULL;
674 memcpy(tlv, data, sizeof(data));
675 if (copy_from_user(tlv + 2, _tlv + 2, data[1])) {
676 kfree(tlv);
677 return NULL;
678 }
679 return tlv;
680}
681
682static int copy_gctl(struct snd_emu10k1 *emu,
683 struct snd_emu10k1_fx8010_control_gpr *gctl,
684 struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
685 int idx)
686{
687 struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
688
689 if (emu->support_tlv)
690 return copy_from_user(gctl, &_gctl[idx], sizeof(*gctl));
691 octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
692 if (copy_from_user(gctl, &octl[idx], sizeof(*octl)))
693 return -EFAULT;
694 gctl->tlv = NULL;
695 return 0;
696}
697
698static int copy_gctl_to_user(struct snd_emu10k1 *emu,
699 struct snd_emu10k1_fx8010_control_gpr __user *_gctl,
700 struct snd_emu10k1_fx8010_control_gpr *gctl,
701 int idx)
702{
703 struct snd_emu10k1_fx8010_control_old_gpr __user *octl;
704
705 if (emu->support_tlv)
706 return copy_to_user(&_gctl[idx], gctl, sizeof(*gctl));
707
708 octl = (struct snd_emu10k1_fx8010_control_old_gpr __user *)_gctl;
709 return copy_to_user(&octl[idx], gctl, sizeof(*octl));
710}
711
655static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu, 712static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
656 struct snd_emu10k1_fx8010_code *icode) 713 struct snd_emu10k1_fx8010_code *icode)
657{ 714{
658 unsigned int i; 715 unsigned int i;
659 struct snd_ctl_elem_id __user *_id; 716 struct snd_ctl_elem_id __user *_id;
660 struct snd_ctl_elem_id id; 717 struct snd_ctl_elem_id id;
661 struct snd_emu10k1_fx8010_control_gpr __user *_gctl;
662 struct snd_emu10k1_fx8010_control_gpr *gctl; 718 struct snd_emu10k1_fx8010_control_gpr *gctl;
663 int err; 719 int err;
664 720
@@ -673,9 +729,8 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
673 if (! gctl) 729 if (! gctl)
674 return -ENOMEM; 730 return -ENOMEM;
675 err = 0; 731 err = 0;
676 for (i = 0, _gctl = icode->gpr_add_controls; 732 for (i = 0; i < icode->gpr_add_control_count; i++) {
677 i < icode->gpr_add_control_count; i++, _gctl++) { 733 if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
678 if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
679 err = -EFAULT; 734 err = -EFAULT;
680 goto __error; 735 goto __error;
681 } 736 }
@@ -694,10 +749,9 @@ static int snd_emu10k1_verify_controls(struct snd_emu10k1 *emu,
694 goto __error; 749 goto __error;
695 } 750 }
696 } 751 }
697 for (i = 0, _gctl = icode->gpr_list_controls; 752 for (i = 0; i < icode->gpr_list_control_count; i++) {
698 i < icode->gpr_list_control_count; i++, _gctl++) {
699 /* FIXME: we need to check the WRITE access */ 753 /* FIXME: we need to check the WRITE access */
700 if (copy_from_user(gctl, _gctl, sizeof(*gctl))) { 754 if (copy_gctl(emu, gctl, icode->gpr_list_controls, i)) {
701 err = -EFAULT; 755 err = -EFAULT;
702 goto __error; 756 goto __error;
703 } 757 }
@@ -715,13 +769,14 @@ static void snd_emu10k1_ctl_private_free(struct snd_kcontrol *kctl)
715 kctl->private_value = 0; 769 kctl->private_value = 0;
716 list_del(&ctl->list); 770 list_del(&ctl->list);
717 kfree(ctl); 771 kfree(ctl);
772 if (kctl->tlv.p)
773 kfree(kctl->tlv.p);
718} 774}
719 775
720static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu, 776static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
721 struct snd_emu10k1_fx8010_code *icode) 777 struct snd_emu10k1_fx8010_code *icode)
722{ 778{
723 unsigned int i, j; 779 unsigned int i, j;
724 struct snd_emu10k1_fx8010_control_gpr __user *_gctl;
725 struct snd_emu10k1_fx8010_control_gpr *gctl; 780 struct snd_emu10k1_fx8010_control_gpr *gctl;
726 struct snd_emu10k1_fx8010_ctl *ctl, *nctl; 781 struct snd_emu10k1_fx8010_ctl *ctl, *nctl;
727 struct snd_kcontrol_new knew; 782 struct snd_kcontrol_new knew;
@@ -737,9 +792,8 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
737 goto __error; 792 goto __error;
738 } 793 }
739 794
740 for (i = 0, _gctl = icode->gpr_add_controls; 795 for (i = 0; i < icode->gpr_add_control_count; i++) {
741 i < icode->gpr_add_control_count; i++, _gctl++) { 796 if (copy_gctl(emu, gctl, icode->gpr_add_controls, i)) {
742 if (copy_from_user(gctl, _gctl, sizeof(*gctl))) {
743 err = -EFAULT; 797 err = -EFAULT;
744 goto __error; 798 goto __error;
745 } 799 }
@@ -760,11 +814,10 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
760 knew.device = gctl->id.device; 814 knew.device = gctl->id.device;
761 knew.subdevice = gctl->id.subdevice; 815 knew.subdevice = gctl->id.subdevice;
762 knew.info = snd_emu10k1_gpr_ctl_info; 816 knew.info = snd_emu10k1_gpr_ctl_info;
763 if (gctl->tlv.p) { 817 knew.tlv.p = copy_tlv(gctl->tlv);
764 knew.tlv.p = gctl->tlv.p; 818 if (knew.tlv.p)
765 knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE | 819 knew.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
766 SNDRV_CTL_ELEM_ACCESS_TLV_READ; 820 SNDRV_CTL_ELEM_ACCESS_TLV_READ;
767 }
768 knew.get = snd_emu10k1_gpr_ctl_get; 821 knew.get = snd_emu10k1_gpr_ctl_get;
769 knew.put = snd_emu10k1_gpr_ctl_put; 822 knew.put = snd_emu10k1_gpr_ctl_put;
770 memset(nctl, 0, sizeof(*nctl)); 823 memset(nctl, 0, sizeof(*nctl));
@@ -782,12 +835,14 @@ static int snd_emu10k1_add_controls(struct snd_emu10k1 *emu,
782 ctl = kmalloc(sizeof(*ctl), GFP_KERNEL); 835 ctl = kmalloc(sizeof(*ctl), GFP_KERNEL);
783 if (ctl == NULL) { 836 if (ctl == NULL) {
784 err = -ENOMEM; 837 err = -ENOMEM;
838 kfree(knew.tlv.p);
785 goto __error; 839 goto __error;
786 } 840 }
787 knew.private_value = (unsigned long)ctl; 841 knew.private_value = (unsigned long)ctl;
788 *ctl = *nctl; 842 *ctl = *nctl;
789 if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) { 843 if ((err = snd_ctl_add(emu->card, kctl = snd_ctl_new1(&knew, emu))) < 0) {
790 kfree(ctl); 844 kfree(ctl);
845 kfree(knew.tlv.p);
791 goto __error; 846 goto __error;
792 } 847 }
793 kctl->private_free = snd_emu10k1_ctl_private_free; 848 kctl->private_free = snd_emu10k1_ctl_private_free;
@@ -838,7 +893,6 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
838 unsigned int i = 0, j; 893 unsigned int i = 0, j;
839 unsigned int total = 0; 894 unsigned int total = 0;
840 struct snd_emu10k1_fx8010_control_gpr *gctl; 895 struct snd_emu10k1_fx8010_control_gpr *gctl;
841 struct snd_emu10k1_fx8010_control_gpr __user *_gctl;
842 struct snd_emu10k1_fx8010_ctl *ctl; 896 struct snd_emu10k1_fx8010_ctl *ctl;
843 struct snd_ctl_elem_id *id; 897 struct snd_ctl_elem_id *id;
844 struct list_head *list; 898 struct list_head *list;
@@ -847,11 +901,11 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
847 if (! gctl) 901 if (! gctl)
848 return -ENOMEM; 902 return -ENOMEM;
849 903
850 _gctl = icode->gpr_list_controls;
851 list_for_each(list, &emu->fx8010.gpr_ctl) { 904 list_for_each(list, &emu->fx8010.gpr_ctl) {
852 ctl = emu10k1_gpr_ctl(list); 905 ctl = emu10k1_gpr_ctl(list);
853 total++; 906 total++;
854 if (_gctl && i < icode->gpr_list_control_count) { 907 if (icode->gpr_list_controls &&
908 i < icode->gpr_list_control_count) {
855 memset(gctl, 0, sizeof(*gctl)); 909 memset(gctl, 0, sizeof(*gctl));
856 id = &ctl->kcontrol->id; 910 id = &ctl->kcontrol->id;
857 gctl->id.iface = id->iface; 911 gctl->id.iface = id->iface;
@@ -868,11 +922,11 @@ static int snd_emu10k1_list_controls(struct snd_emu10k1 *emu,
868 gctl->min = ctl->min; 922 gctl->min = ctl->min;
869 gctl->max = ctl->max; 923 gctl->max = ctl->max;
870 gctl->translation = ctl->translation; 924 gctl->translation = ctl->translation;
871 if (copy_to_user(_gctl, gctl, sizeof(*gctl))) { 925 if (copy_gctl_to_user(emu, icode->gpr_list_controls,
926 gctl, i)) {
872 kfree(gctl); 927 kfree(gctl);
873 return -EFAULT; 928 return -EFAULT;
874 } 929 }
875 _gctl++;
876 i++; 930 i++;
877 } 931 }
878 } 932 }
@@ -1023,7 +1077,7 @@ snd_emu10k1_init_mono_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1023 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval; 1077 ctl->gpr[0] = gpr + 0; ctl->value[0] = defval;
1024 ctl->min = 0; 1078 ctl->min = 0;
1025 ctl->max = 100; 1079 ctl->max = 100;
1026 ctl->tlv.p = snd_emu10k1_db_scale1; 1080 ctl->tlv = snd_emu10k1_db_scale1;
1027 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; 1081 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
1028} 1082}
1029 1083
@@ -1038,7 +1092,7 @@ snd_emu10k1_init_stereo_control(struct snd_emu10k1_fx8010_control_gpr *ctl,
1038 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval; 1092 ctl->gpr[1] = gpr + 1; ctl->value[1] = defval;
1039 ctl->min = 0; 1093 ctl->min = 0;
1040 ctl->max = 100; 1094 ctl->max = 100;
1041 ctl->tlv.p = snd_emu10k1_db_scale1; 1095 ctl->tlv = snd_emu10k1_db_scale1;
1042 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100; 1096 ctl->translation = EMU10K1_GPR_TRANSLATION_TABLE100;
1043} 1097}
1044 1098
@@ -1069,6 +1123,21 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl
1069 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF; 1123 ctl->translation = EMU10K1_GPR_TRANSLATION_ONOFF;
1070} 1124}
1071 1125
1126static int snd_emu10k1_audigy_dsp_convert_32_to_2x16(
1127 struct snd_emu10k1_fx8010_code *icode,
1128 u32 *ptr, int tmp, int bit_shifter16,
1129 int reg_in, int reg_out)
1130{
1131 A_OP(icode, ptr, iACC3, A_GPR(tmp + 1), reg_in, A_C_00000000, A_C_00000000);
1132 A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp + 1), A_GPR(bit_shifter16 - 1), A_C_00000000);
1133 A_OP(icode, ptr, iTSTNEG, A_GPR(tmp + 2), A_GPR(tmp), A_C_80000000, A_GPR(bit_shifter16 - 2));
1134 A_OP(icode, ptr, iANDXOR, A_GPR(tmp + 2), A_GPR(tmp + 2), A_C_80000000, A_C_00000000);
1135 A_OP(icode, ptr, iANDXOR, A_GPR(tmp), A_GPR(tmp), A_GPR(bit_shifter16 - 3), A_C_00000000);
1136 A_OP(icode, ptr, iMACINT0, A_GPR(tmp), A_C_00000000, A_GPR(tmp), A_C_00010000);
1137 A_OP(icode, ptr, iANDXOR, reg_out, A_GPR(tmp), A_C_ffffffff, A_GPR(tmp + 2));
1138 A_OP(icode, ptr, iACC3, reg_out + 1, A_GPR(tmp + 1), A_C_00000000, A_C_00000000);
1139 return 1;
1140}
1072 1141
1073/* 1142/*
1074 * initial DSP configuration for Audigy 1143 * initial DSP configuration for Audigy
@@ -1077,6 +1146,7 @@ snd_emu10k1_init_stereo_onoff_control(struct snd_emu10k1_fx8010_control_gpr *ctl
1077static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu) 1146static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
1078{ 1147{
1079 int err, i, z, gpr, nctl; 1148 int err, i, z, gpr, nctl;
1149 int bit_shifter16;
1080 const int playback = 10; 1150 const int playback = 10;
1081 const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */ 1151 const int capture = playback + (SND_EMU10K1_PLAYBACK_CHANNELS * 2); /* we reserve 10 voices */
1082 const int stereo_mix = capture + 2; 1152 const int stereo_mix = capture + 2;
@@ -1114,17 +1184,14 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
1114 ptr = 0; 1184 ptr = 0;
1115 nctl = 0; 1185 nctl = 0;
1116 gpr = stereo_mix + 10; 1186 gpr = stereo_mix + 10;
1187 gpr_map[gpr++] = 0x00007fff;
1188 gpr_map[gpr++] = 0x00008000;
1189 gpr_map[gpr++] = 0x0000ffff;
1190 bit_shifter16 = gpr;
1117 1191
1118 /* stop FX processor */ 1192 /* stop FX processor */
1119 snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP); 1193 snd_emu10k1_ptr_write(emu, A_DBG, 0, (emu->fx8010.dbg = 0) | A_DBG_SINGLE_STEP);
1120 1194
1121#if 0
1122 /* FIX: jcd test */
1123 for (z = 0; z < 80; z=z+2) {
1124 A_OP(icode, &ptr, iACC3, A_EXTOUT(z), A_FXBUS(FXBUS_PCM_LEFT_FRONT), A_C_00000000, A_C_00000000); /* left */
1125 A_OP(icode, &ptr, iACC3, A_EXTOUT(z+1), A_FXBUS(FXBUS_PCM_RIGHT_FRONT), A_C_00000000, A_C_00000000); /* right */
1126 }
1127#endif /* jcd test */
1128#if 1 1195#if 1
1129 /* PCM front Playback Volume (independent from stereo mix) */ 1196 /* PCM front Playback Volume (independent from stereo mix) */
1130 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT)); 1197 A_OP(icode, &ptr, iMAC0, A_GPR(playback), A_C_00000000, A_GPR(gpr), A_FXBUS(FXBUS_PCM_LEFT_FRONT));
@@ -1182,13 +1249,20 @@ static int __devinit _snd_emu10k1_audigy_init_efx(struct snd_emu10k1 *emu)
1182 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT)); 1249 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_FXBUS(FXBUS_MIDI_RIGHT));
1183 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0); 1250 snd_emu10k1_init_stereo_control(&controls[nctl++], "Synth Capture Volume", gpr, 0);
1184 gpr += 2; 1251 gpr += 2;
1185 1252
1186 /* 1253 /*
1187 * inputs 1254 * inputs
1188 */ 1255 */
1189#define A_ADD_VOLUME_IN(var,vol,input) \ 1256#define A_ADD_VOLUME_IN(var,vol,input) \
1190A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input)) 1257A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
1191 1258
1259 /* emu1212 DSP 0 and DSP 1 Capture */
1260 if (emu->card_capabilities->emu1010) {
1261 A_OP(icode, &ptr, iMAC0, A_GPR(capture+0), A_GPR(capture+0), A_GPR(gpr), A_P16VIN(0x0));
1262 A_OP(icode, &ptr, iMAC0, A_GPR(capture+1), A_GPR(capture+1), A_GPR(gpr+1), A_P16VIN(0x1));
1263 snd_emu10k1_init_stereo_control(&controls[nctl++], "EMU Capture Volume", gpr, 0);
1264 gpr += 2;
1265 }
1192 /* AC'97 Playback Volume - used only for mic (renamed later) */ 1266 /* AC'97 Playback Volume - used only for mic (renamed later) */
1193 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L); 1267 A_ADD_VOLUME_IN(stereo_mix, gpr, A_EXTIN_AC97_L);
1194 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R); 1268 A_ADD_VOLUME_IN(stereo_mix+1, gpr+1, A_EXTIN_AC97_R);
@@ -1429,6 +1503,13 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
1429 1503
1430 /* digital outputs */ 1504 /* digital outputs */
1431 /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */ 1505 /* A_PUT_STEREO_OUTPUT(A_EXTOUT_FRONT_L, A_EXTOUT_FRONT_R, playback + SND_EMU10K1_PLAYBACK_CHANNELS); */
1506 if (emu->card_capabilities->emu1010) {
1507 /* EMU1010 Outputs from PCM Front, Rear, Center, LFE, Side */
1508 snd_printk("EMU outputs on\n");
1509 for (z = 0; z < 8; z++) {
1510 A_OP(icode, &ptr, iACC3, A_EMU32OUTL(z), A_GPR(playback + SND_EMU10K1_PLAYBACK_CHANNELS + z), A_C_00000000, A_C_00000000);
1511 }
1512 }
1432 1513
1433 /* IEC958 Optical Raw Playback Switch */ 1514 /* IEC958 Optical Raw Playback Switch */
1434 gpr_map[gpr++] = 0; 1515 gpr_map[gpr++] = 0;
@@ -1466,9 +1547,57 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
1466 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1); 1547 A_PUT_OUTPUT(A_EXTOUT_ADC_CAP_R, capture+1);
1467#endif 1548#endif
1468 1549
1469 /* EFX capture - capture the 16 EXTINs */ 1550 if (emu->card_capabilities->emu1010) {
1470 for (z = 0; z < 16; z++) { 1551 snd_printk("EMU inputs on\n");
1471 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z)); 1552 /* Capture 8 channels of S32_LE sound */
1553
1554 /* printk("emufx.c: gpr=0x%x, tmp=0x%x\n",gpr, tmp); */
1555 /* For the EMU1010: How to get 32bit values from the DSP. High 16bits into L, low 16bits into R. */
1556 /* A_P16VIN(0) is delayed by one sample,
1557 * so all other A_P16VIN channels will need to also be delayed
1558 */
1559 /* Left ADC in. 1 of 2 */
1560 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_P16VIN(0x0), A_FXBUS2(0) );
1561 /* Right ADC in 1 of 2 */
1562 gpr_map[gpr++] = 0x00000000;
1563 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(2) );
1564 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x1), A_C_00000000, A_C_00000000);
1565 gpr_map[gpr++] = 0x00000000;
1566 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(4) );
1567 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x2), A_C_00000000, A_C_00000000);
1568 gpr_map[gpr++] = 0x00000000;
1569 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(6) );
1570 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x3), A_C_00000000, A_C_00000000);
1571 /* For 96kHz mode */
1572 /* Left ADC in. 2 of 2 */
1573 gpr_map[gpr++] = 0x00000000;
1574 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0x8) );
1575 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x4), A_C_00000000, A_C_00000000);
1576 /* Right ADC in 2 of 2 */
1577 gpr_map[gpr++] = 0x00000000;
1578 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xa) );
1579 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x5), A_C_00000000, A_C_00000000);
1580 gpr_map[gpr++] = 0x00000000;
1581 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xc) );
1582 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x6), A_C_00000000, A_C_00000000);
1583 gpr_map[gpr++] = 0x00000000;
1584 snd_emu10k1_audigy_dsp_convert_32_to_2x16( icode, &ptr, tmp, bit_shifter16, A_GPR(gpr - 1), A_FXBUS2(0xe) );
1585 A_OP(icode, &ptr, iACC3, A_GPR(gpr - 1), A_P16VIN(0x7), A_C_00000000, A_C_00000000);
1586
1587#if 0
1588 for (z = 4; z < 8; z++) {
1589 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
1590 }
1591 for (z = 0xc; z < 0x10; z++) {
1592 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_C_00000000);
1593 }
1594#endif
1595 } else {
1596 /* EFX capture - capture the 16 EXTINs */
1597 /* Capture 16 channels of S16_LE sound */
1598 for (z = 0; z < 16; z++) {
1599 A_OP(icode, &ptr, iACC3, A_FXBUS2(z), A_C_00000000, A_C_00000000, A_EXTIN(z));
1600 }
1472 } 1601 }
1473 1602
1474#endif /* JCD test */ 1603#endif /* JCD test */
@@ -1488,7 +1617,9 @@ A_OP(icode, &ptr, iMAC0, A_GPR(var), A_GPR(var), A_GPR(vol), A_EXTIN(input))
1488 seg = snd_enter_user(); 1617 seg = snd_enter_user();
1489 icode->gpr_add_control_count = nctl; 1618 icode->gpr_add_control_count = nctl;
1490 icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; 1619 icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
1620 emu->support_tlv = 1; /* support TLV */
1491 err = snd_emu10k1_icode_poke(emu, icode); 1621 err = snd_emu10k1_icode_poke(emu, icode);
1622 emu->support_tlv = 0; /* clear again */
1492 snd_leave_user(seg); 1623 snd_leave_user(seg);
1493 1624
1494 __err: 1625 __err:
@@ -2105,7 +2236,9 @@ static int __devinit _snd_emu10k1_init_efx(struct snd_emu10k1 *emu)
2105 seg = snd_enter_user(); 2236 seg = snd_enter_user();
2106 icode->gpr_add_control_count = i; 2237 icode->gpr_add_control_count = i;
2107 icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls; 2238 icode->gpr_add_controls = (struct snd_emu10k1_fx8010_control_gpr __user *)controls;
2239 emu->support_tlv = 1; /* support TLV */
2108 err = snd_emu10k1_icode_poke(emu, icode); 2240 err = snd_emu10k1_icode_poke(emu, icode);
2241 emu->support_tlv = 0; /* clear again */
2109 snd_leave_user(seg); 2242 snd_leave_user(seg);
2110 if (err >= 0) 2243 if (err >= 0)
2111 err = snd_emu10k1_ipcm_poke(emu, ipcm); 2244 err = snd_emu10k1_ipcm_poke(emu, ipcm);
@@ -2138,7 +2271,7 @@ void snd_emu10k1_free_efx(struct snd_emu10k1 *emu)
2138 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP); 2271 snd_emu10k1_ptr_write(emu, DBG, 0, emu->fx8010.dbg = EMU10K1_DBG_SINGLE_STEP);
2139} 2272}
2140 2273
2141#if 0 // FIXME: who use them? 2274#if 0 /* FIXME: who use them? */
2142int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output) 2275int snd_emu10k1_fx8010_tone_control_activate(struct snd_emu10k1 *emu, int output)
2143{ 2276{
2144 if (output < 0 || output >= 6) 2277 if (output < 0 || output >= 6)
@@ -2249,6 +2382,9 @@ static int snd_emu10k1_fx8010_ioctl(struct snd_hwdep * hw, struct file *file, un
2249 int res; 2382 int res;
2250 2383
2251 switch (cmd) { 2384 switch (cmd) {
2385 case SNDRV_EMU10K1_IOCTL_PVERSION:
2386 emu->support_tlv = 1;
2387 return put_user(SNDRV_EMU10K1_VERSION, (int __user *)argp);
2252 case SNDRV_EMU10K1_IOCTL_INFO: 2388 case SNDRV_EMU10K1_IOCTL_INFO:
2253 info = kmalloc(sizeof(*info), GFP_KERNEL); 2389 info = kmalloc(sizeof(*info), GFP_KERNEL);
2254 if (!info) 2390 if (!info)
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index c31f3d0877fa..4db6e1ca1665 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -5,6 +5,9 @@
5 * Routines for control of EMU10K1 chips / mixer routines 5 * Routines for control of EMU10K1 chips / mixer routines
6 * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com> 6 * Multichannel PCM support Copyright (c) Lee Revell <rlrevell@joe-job.com>
7 * 7 *
8 * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
9 * Added EMU 1010 support.
10 *
8 * BUGS: 11 * BUGS:
9 * -- 12 * --
10 * 13 *
@@ -32,9 +35,15 @@
32#include <linux/init.h> 35#include <linux/init.h>
33#include <sound/core.h> 36#include <sound/core.h>
34#include <sound/emu10k1.h> 37#include <sound/emu10k1.h>
38#include <linux/delay.h>
39#include <sound/tlv.h>
40
41#include "p17v.h"
35 42
36#define AC97_ID_STAC9758 0x83847658 43#define AC97_ID_STAC9758 0x83847658
37 44
45static const DECLARE_TLV_DB_SCALE(snd_audigy_db_scale2, -10350, 50, 1); /* WM8775 gain scale */
46
38static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 47static int snd_emu10k1_spdif_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
39{ 48{
40 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958; 49 uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
@@ -68,6 +77,669 @@ static int snd_emu10k1_spdif_get_mask(struct snd_kcontrol *kcontrol,
68 return 0; 77 return 0;
69} 78}
70 79
80static char *emu1010_src_texts[] = {
81 "Silence",
82 "Dock Mic A",
83 "Dock Mic B",
84 "Dock ADC1 Left",
85 "Dock ADC1 Right",
86 "Dock ADC2 Left",
87 "Dock ADC2 Right",
88 "Dock ADC3 Left",
89 "Dock ADC3 Right",
90 "0202 ADC Left",
91 "0202 ADC Right",
92 "0202 SPDIF Left",
93 "0202 SPDIF Right",
94 "ADAT 0",
95 "ADAT 1",
96 "ADAT 2",
97 "ADAT 3",
98 "ADAT 4",
99 "ADAT 5",
100 "ADAT 6",
101 "ADAT 7",
102 "DSP 0",
103 "DSP 1",
104 "DSP 2",
105 "DSP 3",
106 "DSP 4",
107 "DSP 5",
108 "DSP 6",
109 "DSP 7",
110 "DSP 8",
111 "DSP 9",
112 "DSP 10",
113 "DSP 11",
114 "DSP 12",
115 "DSP 13",
116 "DSP 14",
117 "DSP 15",
118 "DSP 16",
119 "DSP 17",
120 "DSP 18",
121 "DSP 19",
122 "DSP 20",
123 "DSP 21",
124 "DSP 22",
125 "DSP 23",
126 "DSP 24",
127 "DSP 25",
128 "DSP 26",
129 "DSP 27",
130 "DSP 28",
131 "DSP 29",
132 "DSP 30",
133 "DSP 31",
134};
135
136static unsigned int emu1010_src_regs[] = {
137 EMU_SRC_SILENCE,/* 0 */
138 EMU_SRC_DOCK_MIC_A1, /* 1 */
139 EMU_SRC_DOCK_MIC_B1, /* 2 */
140 EMU_SRC_DOCK_ADC1_LEFT1, /* 3 */
141 EMU_SRC_DOCK_ADC1_RIGHT1, /* 4 */
142 EMU_SRC_DOCK_ADC2_LEFT1, /* 5 */
143 EMU_SRC_DOCK_ADC2_RIGHT1, /* 6 */
144 EMU_SRC_DOCK_ADC3_LEFT1, /* 7 */
145 EMU_SRC_DOCK_ADC3_RIGHT1, /* 8 */
146 EMU_SRC_HAMOA_ADC_LEFT1, /* 9 */
147 EMU_SRC_HAMOA_ADC_RIGHT1, /* 10 */
148 EMU_SRC_HANA_SPDIF_LEFT1, /* 11 */
149 EMU_SRC_HANA_SPDIF_RIGHT1, /* 12 */
150 EMU_SRC_HANA_ADAT, /* 13 */
151 EMU_SRC_HANA_ADAT+1, /* 14 */
152 EMU_SRC_HANA_ADAT+2, /* 15 */
153 EMU_SRC_HANA_ADAT+3, /* 16 */
154 EMU_SRC_HANA_ADAT+4, /* 17 */
155 EMU_SRC_HANA_ADAT+5, /* 18 */
156 EMU_SRC_HANA_ADAT+6, /* 19 */
157 EMU_SRC_HANA_ADAT+7, /* 20 */
158 EMU_SRC_ALICE_EMU32A, /* 21 */
159 EMU_SRC_ALICE_EMU32A+1, /* 22 */
160 EMU_SRC_ALICE_EMU32A+2, /* 23 */
161 EMU_SRC_ALICE_EMU32A+3, /* 24 */
162 EMU_SRC_ALICE_EMU32A+4, /* 25 */
163 EMU_SRC_ALICE_EMU32A+5, /* 26 */
164 EMU_SRC_ALICE_EMU32A+6, /* 27 */
165 EMU_SRC_ALICE_EMU32A+7, /* 28 */
166 EMU_SRC_ALICE_EMU32A+8, /* 29 */
167 EMU_SRC_ALICE_EMU32A+9, /* 30 */
168 EMU_SRC_ALICE_EMU32A+0xa, /* 31 */
169 EMU_SRC_ALICE_EMU32A+0xb, /* 32 */
170 EMU_SRC_ALICE_EMU32A+0xc, /* 33 */
171 EMU_SRC_ALICE_EMU32A+0xd, /* 34 */
172 EMU_SRC_ALICE_EMU32A+0xe, /* 35 */
173 EMU_SRC_ALICE_EMU32A+0xf, /* 36 */
174 EMU_SRC_ALICE_EMU32B, /* 37 */
175 EMU_SRC_ALICE_EMU32B+1, /* 38 */
176 EMU_SRC_ALICE_EMU32B+2, /* 39 */
177 EMU_SRC_ALICE_EMU32B+3, /* 40 */
178 EMU_SRC_ALICE_EMU32B+4, /* 41 */
179 EMU_SRC_ALICE_EMU32B+5, /* 42 */
180 EMU_SRC_ALICE_EMU32B+6, /* 43 */
181 EMU_SRC_ALICE_EMU32B+7, /* 44 */
182 EMU_SRC_ALICE_EMU32B+8, /* 45 */
183 EMU_SRC_ALICE_EMU32B+9, /* 46 */
184 EMU_SRC_ALICE_EMU32B+0xa, /* 47 */
185 EMU_SRC_ALICE_EMU32B+0xb, /* 48 */
186 EMU_SRC_ALICE_EMU32B+0xc, /* 49 */
187 EMU_SRC_ALICE_EMU32B+0xd, /* 50 */
188 EMU_SRC_ALICE_EMU32B+0xe, /* 51 */
189 EMU_SRC_ALICE_EMU32B+0xf, /* 52 */
190};
191
192static unsigned int emu1010_output_dst[] = {
193 EMU_DST_DOCK_DAC1_LEFT1, /* 0 */
194 EMU_DST_DOCK_DAC1_RIGHT1, /* 1 */
195 EMU_DST_DOCK_DAC2_LEFT1, /* 2 */
196 EMU_DST_DOCK_DAC2_RIGHT1, /* 3 */
197 EMU_DST_DOCK_DAC3_LEFT1, /* 4 */
198 EMU_DST_DOCK_DAC3_RIGHT1, /* 5 */
199 EMU_DST_DOCK_DAC4_LEFT1, /* 6 */
200 EMU_DST_DOCK_DAC4_RIGHT1, /* 7 */
201 EMU_DST_DOCK_PHONES_LEFT1, /* 8 */
202 EMU_DST_DOCK_PHONES_RIGHT1, /* 9 */
203 EMU_DST_DOCK_SPDIF_LEFT1, /* 10 */
204 EMU_DST_DOCK_SPDIF_RIGHT1, /* 11 */
205 EMU_DST_HANA_SPDIF_LEFT1, /* 12 */
206 EMU_DST_HANA_SPDIF_RIGHT1, /* 13 */
207 EMU_DST_HAMOA_DAC_LEFT1, /* 14 */
208 EMU_DST_HAMOA_DAC_RIGHT1, /* 15 */
209 EMU_DST_HANA_ADAT, /* 16 */
210 EMU_DST_HANA_ADAT+1, /* 17 */
211 EMU_DST_HANA_ADAT+2, /* 18 */
212 EMU_DST_HANA_ADAT+3, /* 19 */
213 EMU_DST_HANA_ADAT+4, /* 20 */
214 EMU_DST_HANA_ADAT+5, /* 21 */
215 EMU_DST_HANA_ADAT+6, /* 22 */
216 EMU_DST_HANA_ADAT+7, /* 23 */
217};
218
219static unsigned int emu1010_input_dst[] = {
220 EMU_DST_ALICE2_EMU32_0,
221 EMU_DST_ALICE2_EMU32_1,
222 EMU_DST_ALICE2_EMU32_2,
223 EMU_DST_ALICE2_EMU32_3,
224 EMU_DST_ALICE2_EMU32_4,
225 EMU_DST_ALICE2_EMU32_5,
226 EMU_DST_ALICE2_EMU32_6,
227 EMU_DST_ALICE2_EMU32_7,
228 EMU_DST_ALICE2_EMU32_8,
229 EMU_DST_ALICE2_EMU32_9,
230 EMU_DST_ALICE2_EMU32_A,
231 EMU_DST_ALICE2_EMU32_B,
232 EMU_DST_ALICE2_EMU32_C,
233 EMU_DST_ALICE2_EMU32_D,
234 EMU_DST_ALICE2_EMU32_E,
235 EMU_DST_ALICE2_EMU32_F,
236 EMU_DST_ALICE_I2S0_LEFT,
237 EMU_DST_ALICE_I2S0_RIGHT,
238 EMU_DST_ALICE_I2S1_LEFT,
239 EMU_DST_ALICE_I2S1_RIGHT,
240 EMU_DST_ALICE_I2S2_LEFT,
241 EMU_DST_ALICE_I2S2_RIGHT,
242};
243
244static int snd_emu1010_input_output_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
245{
246 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
247 uinfo->count = 1;
248 uinfo->value.enumerated.items = 53;
249 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
250 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
251 strcpy(uinfo->value.enumerated.name, emu1010_src_texts[uinfo->value.enumerated.item]);
252 return 0;
253}
254
255static int snd_emu1010_output_source_get(struct snd_kcontrol *kcontrol,
256 struct snd_ctl_elem_value *ucontrol)
257{
258 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
259 int channel;
260
261 channel = (kcontrol->private_value) & 0xff;
262 ucontrol->value.enumerated.item[0] = emu->emu1010.output_source[channel];
263 return 0;
264}
265
266static int snd_emu1010_output_source_put(struct snd_kcontrol *kcontrol,
267 struct snd_ctl_elem_value *ucontrol)
268{
269 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
270 int change = 0;
271 unsigned int val;
272 int channel;
273
274 channel = (kcontrol->private_value) & 0xff;
275 if (emu->emu1010.output_source[channel] != ucontrol->value.enumerated.item[0]) {
276 val = emu->emu1010.output_source[channel] = ucontrol->value.enumerated.item[0];
277 change = 1;
278 snd_emu1010_fpga_link_dst_src_write(emu,
279 emu1010_output_dst[channel], emu1010_src_regs[val]);
280 }
281 return change;
282}
283
284static int snd_emu1010_input_source_get(struct snd_kcontrol *kcontrol,
285 struct snd_ctl_elem_value *ucontrol)
286{
287 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
288 int channel;
289
290 channel = (kcontrol->private_value) & 0xff;
291 ucontrol->value.enumerated.item[0] = emu->emu1010.input_source[channel];
292 return 0;
293}
294
295static int snd_emu1010_input_source_put(struct snd_kcontrol *kcontrol,
296 struct snd_ctl_elem_value *ucontrol)
297{
298 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
299 int change = 0;
300 unsigned int val;
301 int channel;
302
303 channel = (kcontrol->private_value) & 0xff;
304 if (emu->emu1010.input_source[channel] != ucontrol->value.enumerated.item[0]) {
305 val = emu->emu1010.input_source[channel] = ucontrol->value.enumerated.item[0];
306 change = 1;
307 snd_emu1010_fpga_link_dst_src_write(emu,
308 emu1010_input_dst[channel], emu1010_src_regs[val]);
309 }
310 return change;
311}
312
313#define EMU1010_SOURCE_OUTPUT(xname,chid) \
314{ \
315 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
316 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
317 .info = snd_emu1010_input_output_source_info, \
318 .get = snd_emu1010_output_source_get, \
319 .put = snd_emu1010_output_source_put, \
320 .private_value = chid \
321}
322
323static struct snd_kcontrol_new snd_emu1010_output_enum_ctls[] __devinitdata = {
324 EMU1010_SOURCE_OUTPUT("Dock DAC1 Left Playback Enum", 0),
325 EMU1010_SOURCE_OUTPUT("Dock DAC1 Right Playback Enum", 1),
326 EMU1010_SOURCE_OUTPUT("Dock DAC2 Left Playback Enum", 2),
327 EMU1010_SOURCE_OUTPUT("Dock DAC2 Right Playback Enum", 3),
328 EMU1010_SOURCE_OUTPUT("Dock DAC3 Left Playback Enum", 4),
329 EMU1010_SOURCE_OUTPUT("Dock DAC3 Right Playback Enum", 5),
330 EMU1010_SOURCE_OUTPUT("Dock DAC4 Left Playback Enum", 6),
331 EMU1010_SOURCE_OUTPUT("Dock DAC4 Right Playback Enum", 7),
332 EMU1010_SOURCE_OUTPUT("Dock Phones Left Playback Enum", 8),
333 EMU1010_SOURCE_OUTPUT("Dock Phones Right Playback Enum", 9),
334 EMU1010_SOURCE_OUTPUT("Dock SPDIF Left Playback Enum", 0xa),
335 EMU1010_SOURCE_OUTPUT("Dock SPDIF Right Playback Enum", 0xb),
336 EMU1010_SOURCE_OUTPUT("1010 SPDIF Left Playback Enum", 0xc),
337 EMU1010_SOURCE_OUTPUT("1010 SPDIF Right Playback Enum", 0xd),
338 EMU1010_SOURCE_OUTPUT("0202 DAC Left Playback Enum", 0xe),
339 EMU1010_SOURCE_OUTPUT("0202 DAC Right Playback Enum", 0xf),
340 EMU1010_SOURCE_OUTPUT("1010 ADAT 0 Playback Enum", 0x10),
341 EMU1010_SOURCE_OUTPUT("1010 ADAT 1 Playback Enum", 0x11),
342 EMU1010_SOURCE_OUTPUT("1010 ADAT 2 Playback Enum", 0x12),
343 EMU1010_SOURCE_OUTPUT("1010 ADAT 3 Playback Enum", 0x13),
344 EMU1010_SOURCE_OUTPUT("1010 ADAT 4 Playback Enum", 0x14),
345 EMU1010_SOURCE_OUTPUT("1010 ADAT 5 Playback Enum", 0x15),
346 EMU1010_SOURCE_OUTPUT("1010 ADAT 6 Playback Enum", 0x16),
347 EMU1010_SOURCE_OUTPUT("1010 ADAT 7 Playback Enum", 0x17),
348};
349
350#define EMU1010_SOURCE_INPUT(xname,chid) \
351{ \
352 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
353 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
354 .info = snd_emu1010_input_output_source_info, \
355 .get = snd_emu1010_input_source_get, \
356 .put = snd_emu1010_input_source_put, \
357 .private_value = chid \
358}
359
360static struct snd_kcontrol_new snd_emu1010_input_enum_ctls[] __devinitdata = {
361 EMU1010_SOURCE_INPUT("DSP 0 Capture Enum", 0),
362 EMU1010_SOURCE_INPUT("DSP 1 Capture Enum", 1),
363 EMU1010_SOURCE_INPUT("DSP 2 Capture Enum", 2),
364 EMU1010_SOURCE_INPUT("DSP 3 Capture Enum", 3),
365 EMU1010_SOURCE_INPUT("DSP 4 Capture Enum", 4),
366 EMU1010_SOURCE_INPUT("DSP 5 Capture Enum", 5),
367 EMU1010_SOURCE_INPUT("DSP 6 Capture Enum", 6),
368 EMU1010_SOURCE_INPUT("DSP 7 Capture Enum", 7),
369 EMU1010_SOURCE_INPUT("DSP 8 Capture Enum", 8),
370 EMU1010_SOURCE_INPUT("DSP 9 Capture Enum", 9),
371 EMU1010_SOURCE_INPUT("DSP A Capture Enum", 0xa),
372 EMU1010_SOURCE_INPUT("DSP B Capture Enum", 0xb),
373 EMU1010_SOURCE_INPUT("DSP C Capture Enum", 0xc),
374 EMU1010_SOURCE_INPUT("DSP D Capture Enum", 0xd),
375 EMU1010_SOURCE_INPUT("DSP E Capture Enum", 0xe),
376 EMU1010_SOURCE_INPUT("DSP F Capture Enum", 0xf),
377 EMU1010_SOURCE_INPUT("DSP 10 Capture Enum", 0x10),
378 EMU1010_SOURCE_INPUT("DSP 11 Capture Enum", 0x11),
379 EMU1010_SOURCE_INPUT("DSP 12 Capture Enum", 0x12),
380 EMU1010_SOURCE_INPUT("DSP 13 Capture Enum", 0x13),
381 EMU1010_SOURCE_INPUT("DSP 14 Capture Enum", 0x14),
382 EMU1010_SOURCE_INPUT("DSP 15 Capture Enum", 0x15),
383};
384
385
386
387
388static int snd_emu1010_adc_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
389{
390 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
391 uinfo->count = 1;
392 uinfo->value.integer.min = 0;
393 uinfo->value.integer.max = 1;
394 return 0;
395}
396
397static int snd_emu1010_adc_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
398{
399 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
400 unsigned int mask = kcontrol->private_value & 0xff;
401 ucontrol->value.integer.value[0] = (emu->emu1010.adc_pads & mask) ? 1 : 0;
402 return 0;
403}
404
405static int snd_emu1010_adc_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
406{
407 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
408 unsigned int mask = kcontrol->private_value & 0xff;
409 unsigned int val, cache;
410 val = ucontrol->value.integer.value[0];
411 cache = emu->emu1010.adc_pads;
412 if (val == 1)
413 cache = cache | mask;
414 else
415 cache = cache & ~mask;
416 if (cache != emu->emu1010.adc_pads) {
417 snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, cache );
418 emu->emu1010.adc_pads = cache;
419 }
420
421 return 0;
422}
423
424
425
426#define EMU1010_ADC_PADS(xname,chid) \
427{ \
428 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
429 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
430 .info = snd_emu1010_adc_pads_info, \
431 .get = snd_emu1010_adc_pads_get, \
432 .put = snd_emu1010_adc_pads_put, \
433 .private_value = chid \
434}
435
436static struct snd_kcontrol_new snd_emu1010_adc_pads[] __devinitdata = {
437 EMU1010_ADC_PADS("ADC1 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD1),
438 EMU1010_ADC_PADS("ADC2 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD2),
439 EMU1010_ADC_PADS("ADC3 14dB PAD Audio Dock Capture Switch", EMU_HANA_DOCK_ADC_PAD3),
440 EMU1010_ADC_PADS("ADC1 14dB PAD 0202 Capture Switch", EMU_HANA_0202_ADC_PAD1),
441};
442
443static int snd_emu1010_dac_pads_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
444{
445 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
446 uinfo->count = 1;
447 uinfo->value.integer.min = 0;
448 uinfo->value.integer.max = 1;
449 return 0;
450}
451
452static int snd_emu1010_dac_pads_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
453{
454 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
455 unsigned int mask = kcontrol->private_value & 0xff;
456 ucontrol->value.integer.value[0] = (emu->emu1010.dac_pads & mask) ? 1 : 0;
457 return 0;
458}
459
460static int snd_emu1010_dac_pads_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
461{
462 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
463 unsigned int mask = kcontrol->private_value & 0xff;
464 unsigned int val, cache;
465 val = ucontrol->value.integer.value[0];
466 cache = emu->emu1010.dac_pads;
467 if (val == 1)
468 cache = cache | mask;
469 else
470 cache = cache & ~mask;
471 if (cache != emu->emu1010.dac_pads) {
472 snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, cache );
473 emu->emu1010.dac_pads = cache;
474 }
475
476 return 0;
477}
478
479
480
481#define EMU1010_DAC_PADS(xname,chid) \
482{ \
483 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
484 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
485 .info = snd_emu1010_dac_pads_info, \
486 .get = snd_emu1010_dac_pads_get, \
487 .put = snd_emu1010_dac_pads_put, \
488 .private_value = chid \
489}
490
491static struct snd_kcontrol_new snd_emu1010_dac_pads[] __devinitdata = {
492 EMU1010_DAC_PADS("DAC1 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD1),
493 EMU1010_DAC_PADS("DAC2 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD2),
494 EMU1010_DAC_PADS("DAC3 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD3),
495 EMU1010_DAC_PADS("DAC4 Audio Dock 14dB PAD Playback Switch", EMU_HANA_DOCK_DAC_PAD4),
496 EMU1010_DAC_PADS("DAC1 0202 14dB PAD Playback Switch", EMU_HANA_0202_DAC_PAD1),
497};
498
499
500static int snd_emu1010_internal_clock_info(struct snd_kcontrol *kcontrol,
501 struct snd_ctl_elem_info *uinfo)
502{
503 static char *texts[2] = {
504 "44100", "48000"
505 };
506
507 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
508 uinfo->count = 1;
509 uinfo->value.enumerated.items = 2;
510 if (uinfo->value.enumerated.item > 1)
511 uinfo->value.enumerated.item = 1;
512 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
513 return 0;
514}
515
516static int snd_emu1010_internal_clock_get(struct snd_kcontrol *kcontrol,
517 struct snd_ctl_elem_value *ucontrol)
518{
519 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
520
521 ucontrol->value.enumerated.item[0] = emu->emu1010.internal_clock;
522 return 0;
523}
524
525static int snd_emu1010_internal_clock_put(struct snd_kcontrol *kcontrol,
526 struct snd_ctl_elem_value *ucontrol)
527{
528 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
529 unsigned int val;
530 int change = 0;
531
532 val = ucontrol->value.enumerated.item[0] ;
533 change = (emu->emu1010.internal_clock != val);
534 if (change) {
535 emu->emu1010.internal_clock = val;
536 switch (val) {
537 case 0:
538 /* 44100 */
539 /* Mute all */
540 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
541 /* Default fallback clock 48kHz */
542 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_44_1K );
543 /* Word Clock source, Internal 44.1kHz x1 */
544 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
545 EMU_HANA_WCLOCK_INT_44_1K | EMU_HANA_WCLOCK_1X );
546 /* Set LEDs on Audio Dock */
547 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
548 EMU_HANA_DOCK_LEDS_2_44K | EMU_HANA_DOCK_LEDS_2_LOCK );
549 /* Allow DLL to settle */
550 msleep(10);
551 /* Unmute all */
552 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
553 break;
554 case 1:
555 /* 48000 */
556 /* Mute all */
557 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_MUTE );
558 /* Default fallback clock 48kHz */
559 snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, EMU_HANA_DEFCLOCK_48K );
560 /* Word Clock source, Internal 48kHz x1 */
561 snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK,
562 EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_1X );
563 /* Set LEDs on Audio Dock */
564 snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2,
565 EMU_HANA_DOCK_LEDS_2_48K | EMU_HANA_DOCK_LEDS_2_LOCK );
566 /* Allow DLL to settle */
567 msleep(10);
568 /* Unmute all */
569 snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
570 break;
571 }
572 }
573 return change;
574}
575
576static struct snd_kcontrol_new snd_emu1010_internal_clock =
577{
578 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE,
579 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
580 .name = "Clock Internal Rate",
581 .count = 1,
582 .info = snd_emu1010_internal_clock_info,
583 .get = snd_emu1010_internal_clock_get,
584 .put = snd_emu1010_internal_clock_put
585};
586
587static int snd_audigy_i2c_capture_source_info(struct snd_kcontrol *kcontrol,
588 struct snd_ctl_elem_info *uinfo)
589{
590#if 0
591 static char *texts[4] = {
592 "Unknown1", "Unknown2", "Mic", "Line"
593 };
594#endif
595 static char *texts[2] = {
596 "Mic", "Line"
597 };
598
599 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
600 uinfo->count = 1;
601 uinfo->value.enumerated.items = 2;
602 if (uinfo->value.enumerated.item > 1)
603 uinfo->value.enumerated.item = 1;
604 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
605 return 0;
606}
607
608static int snd_audigy_i2c_capture_source_get(struct snd_kcontrol *kcontrol,
609 struct snd_ctl_elem_value *ucontrol)
610{
611 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
612
613 ucontrol->value.enumerated.item[0] = emu->i2c_capture_source;
614 return 0;
615}
616
617static int snd_audigy_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
618 struct snd_ctl_elem_value *ucontrol)
619{
620 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
621 unsigned int source_id;
622 unsigned int ngain, ogain;
623 u32 gpio;
624 int change = 0;
625 unsigned long flags;
626 u32 source;
627 /* If the capture source has changed,
628 * update the capture volume from the cached value
629 * for the particular source.
630 */
631 source_id = ucontrol->value.enumerated.item[0]; /* Use 2 and 3 */
632 change = (emu->i2c_capture_source != source_id);
633 if (change) {
634 snd_emu10k1_i2c_write(emu, ADC_MUX, 0); /* Mute input */
635 spin_lock_irqsave(&emu->emu_lock, flags);
636 gpio = inl(emu->port + A_IOCFG);
637 if (source_id==0)
638 outl(gpio | 0x4, emu->port + A_IOCFG);
639 else
640 outl(gpio & ~0x4, emu->port + A_IOCFG);
641 spin_unlock_irqrestore(&emu->emu_lock, flags);
642
643 ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
644 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
645 if (ngain != ogain)
646 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
647 ngain = emu->i2c_capture_volume[source_id][1]; /* Right */
648 ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
649 if (ngain != ogain)
650 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
651
652 source = 1 << (source_id + 2);
653 snd_emu10k1_i2c_write(emu, ADC_MUX, source); /* Set source */
654 emu->i2c_capture_source = source_id;
655 }
656 return change;
657}
658
659static struct snd_kcontrol_new snd_audigy_i2c_capture_source =
660{
661 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
662 .name = "Capture Source",
663 .info = snd_audigy_i2c_capture_source_info,
664 .get = snd_audigy_i2c_capture_source_get,
665 .put = snd_audigy_i2c_capture_source_put
666};
667
668static int snd_audigy_i2c_volume_info(struct snd_kcontrol *kcontrol,
669 struct snd_ctl_elem_info *uinfo)
670{
671 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
672 uinfo->count = 2;
673 uinfo->value.integer.min = 0;
674 uinfo->value.integer.max = 255;
675 return 0;
676}
677
678static int snd_audigy_i2c_volume_get(struct snd_kcontrol *kcontrol,
679 struct snd_ctl_elem_value *ucontrol)
680{
681 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
682 int source_id;
683
684 source_id = kcontrol->private_value;
685
686 ucontrol->value.integer.value[0] = emu->i2c_capture_volume[source_id][0];
687 ucontrol->value.integer.value[1] = emu->i2c_capture_volume[source_id][1];
688 return 0;
689}
690
691static int snd_audigy_i2c_volume_put(struct snd_kcontrol *kcontrol,
692 struct snd_ctl_elem_value *ucontrol)
693{
694 struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
695 unsigned int ogain;
696 unsigned int ngain;
697 int source_id;
698 int change = 0;
699
700 source_id = kcontrol->private_value;
701 ogain = emu->i2c_capture_volume[source_id][0]; /* Left */
702 ngain = ucontrol->value.integer.value[0];
703 if (ngain > 0xff)
704 return 0;
705 if (ogain != ngain) {
706 if (emu->i2c_capture_source == source_id)
707 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff) );
708 emu->i2c_capture_volume[source_id][0] = ucontrol->value.integer.value[0];
709 change = 1;
710 }
711 ogain = emu->i2c_capture_volume[source_id][1]; /* Right */
712 ngain = ucontrol->value.integer.value[1];
713 if (ngain > 0xff)
714 return 0;
715 if (ogain != ngain) {
716 if (emu->i2c_capture_source == source_id)
717 snd_emu10k1_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
718 emu->i2c_capture_volume[source_id][1] = ucontrol->value.integer.value[1];
719 change = 1;
720 }
721
722 return change;
723}
724
725#define I2C_VOLUME(xname,chid) \
726{ \
727 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
728 .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \
729 SNDRV_CTL_ELEM_ACCESS_TLV_READ, \
730 .info = snd_audigy_i2c_volume_info, \
731 .get = snd_audigy_i2c_volume_get, \
732 .put = snd_audigy_i2c_volume_put, \
733 .tlv = { .p = snd_audigy_db_scale2 }, \
734 .private_value = chid \
735}
736
737
738static struct snd_kcontrol_new snd_audigy_i2c_volume_ctls[] __devinitdata = {
739 I2C_VOLUME("Mic Capture Volume", 0),
740 I2C_VOLUME("Line Capture Volume", 0)
741};
742
71#if 0 743#if 0
72static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 744static int snd_audigy_spdif_output_rate_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
73{ 745{
@@ -668,7 +1340,9 @@ static int snd_emu10k1_shared_spdif_put(struct snd_kcontrol *kcontrol,
668 int change = 0; 1340 int change = 0;
669 1341
670 spin_lock_irqsave(&emu->reg_lock, flags); 1342 spin_lock_irqsave(&emu->reg_lock, flags);
671 if (emu->audigy) { 1343 if ( emu->card_capabilities->i2c_adc) {
1344 /* Do nothing for Audigy 2 ZS Notebook */
1345 } else if (emu->audigy) {
672 reg = inl(emu->port + A_IOCFG); 1346 reg = inl(emu->port + A_IOCFG);
673 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0; 1347 val = ucontrol->value.integer.value[0] ? A_IOCFG_GPOUT0 : 0;
674 change = (reg & A_IOCFG_GPOUT0) != val; 1348 change = (reg & A_IOCFG_GPOUT0) != val;
@@ -806,6 +1480,24 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
806 "AMic Playback Volume", "Mic Playback Volume", 1480 "AMic Playback Volume", "Mic Playback Volume",
807 NULL 1481 NULL
808 }; 1482 };
1483 static char *audigy_rename_ctls_i2c_adc[] = {
1484 //"Analog Mix Capture Volume","OLD Analog Mix Capture Volume",
1485 "Line Capture Volume", "Analog Mix Capture Volume",
1486 "Wave Playback Volume", "OLD PCM Playback Volume",
1487 "Wave Master Playback Volume", "Master Playback Volume",
1488 "AMic Playback Volume", "Old Mic Playback Volume",
1489 "CD Capture Volume", "IEC958 Optical Capture Volume",
1490 NULL
1491 };
1492 static char *audigy_remove_ctls_i2c_adc[] = {
1493 /* On the Audigy2 ZS Notebook
1494 * Capture via WM8775 */
1495 "Mic Capture Volume",
1496 "Analog Mix Capture Volume",
1497 "Aux Capture Volume",
1498 "IEC958 Optical Capture Volume",
1499 NULL
1500 };
809 static char *audigy_remove_ctls_1361t_adc[] = { 1501 static char *audigy_remove_ctls_1361t_adc[] = {
810 /* On the Audigy2 the AC97 playback is piped into 1502 /* On the Audigy2 the AC97 playback is piped into
811 * the Philips ADC for 24bit capture */ 1503 * the Philips ADC for 24bit capture */
@@ -890,6 +1582,7 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
890 if (emu->ac97->id == AC97_ID_STAC9758) { 1582 if (emu->ac97->id == AC97_ID_STAC9758) {
891 emu->rear_ac97 = 1; 1583 emu->rear_ac97 = 1;
892 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT); 1584 snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE|AC97SLOT_REAR_LEFT|AC97SLOT_REAR_RIGHT);
1585 snd_ac97_write_cache(emu->ac97, AC97_HEADPHONE, 0x0202);
893 } 1586 }
894 /* remove unused AC97 controls */ 1587 /* remove unused AC97 controls */
895 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202); 1588 snd_ac97_write_cache(emu->ac97, AC97_SURROUND_MASTER, 0x0202);
@@ -898,6 +1591,10 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
898 } 1591 }
899 for (; *c; c++) 1592 for (; *c; c++)
900 remove_ctl(card, *c); 1593 remove_ctl(card, *c);
1594 } else if (emu->card_capabilities->i2c_adc) {
1595 c = audigy_remove_ctls_i2c_adc;
1596 for (; *c; c++)
1597 remove_ctl(card, *c);
901 } else { 1598 } else {
902 no_ac97: 1599 no_ac97:
903 if (emu->card_capabilities->ecard) 1600 if (emu->card_capabilities->ecard)
@@ -911,6 +1608,8 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
911 if (emu->audigy) 1608 if (emu->audigy)
912 if (emu->card_capabilities->adc_1361t) 1609 if (emu->card_capabilities->adc_1361t)
913 c = audigy_rename_ctls_1361t_adc; 1610 c = audigy_rename_ctls_1361t_adc;
1611 else if (emu->card_capabilities->i2c_adc)
1612 c = audigy_rename_ctls_i2c_adc;
914 else 1613 else
915 c = audigy_rename_ctls; 1614 c = audigy_rename_ctls;
916 else 1615 else
@@ -1021,7 +1720,7 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1021 return err; 1720 return err;
1022 } 1721 }
1023 1722
1024 if ( emu->card_capabilities->emu1212m) { 1723 if ( emu->card_capabilities->emu1010) {
1025 ; /* Disable the snd_audigy_spdif_shared_spdif */ 1724 ; /* Disable the snd_audigy_spdif_shared_spdif */
1026 } else if (emu->audigy) { 1725 } else if (emu->audigy) {
1027 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL) 1726 if ((kctl = snd_ctl_new1(&snd_audigy_shared_spdif, emu)) == NULL)
@@ -1045,6 +1744,48 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
1045 if ((err = snd_p16v_mixer(emu))) 1744 if ((err = snd_p16v_mixer(emu)))
1046 return err; 1745 return err;
1047 } 1746 }
1747
1748 if ( emu->card_capabilities->emu1010) {
1749 int i;
1750
1751 for (i = 0; i < ARRAY_SIZE(snd_emu1010_output_enum_ctls); i++) {
1752 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_output_enum_ctls[i], emu));
1753 if (err < 0)
1754 return err;
1755 }
1756 for (i = 0; i < ARRAY_SIZE(snd_emu1010_input_enum_ctls); i++) {
1757 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_input_enum_ctls[i], emu));
1758 if (err < 0)
1759 return err;
1760 }
1761 for (i = 0; i < ARRAY_SIZE(snd_emu1010_adc_pads); i++) {
1762 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_adc_pads[i], emu));
1763 if (err < 0)
1764 return err;
1765 }
1766 for (i = 0; i < ARRAY_SIZE(snd_emu1010_dac_pads); i++) {
1767 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_dac_pads[i], emu));
1768 if (err < 0)
1769 return err;
1770 }
1771 err = snd_ctl_add(card, snd_ctl_new1(&snd_emu1010_internal_clock, emu));
1772 if (err < 0)
1773 return err;
1774 }
1775
1776 if ( emu->card_capabilities->i2c_adc) {
1777 int i;
1778
1779 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_capture_source, emu));
1780 if (err < 0)
1781 return err;
1782
1783 for (i = 0; i < ARRAY_SIZE(snd_audigy_i2c_volume_ctls); i++) {
1784 err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_i2c_volume_ctls[i], emu));
1785 if (err < 0)
1786 return err;
1787 }
1788 }
1048 1789
1049 return 0; 1790 return 0;
1050} 1791}
diff --git a/sound/pci/emu10k1/emupcm.c b/sound/pci/emu10k1/emupcm.c
index 717e92ec9e0a..ab4f5df5241b 100644
--- a/sound/pci/emu10k1/emupcm.c
+++ b/sound/pci/emu10k1/emupcm.c
@@ -147,7 +147,7 @@ static int snd_emu10k1_pcm_channel_alloc(struct snd_emu10k1_pcm * epcm, int voic
147 1, 147 1,
148 &epcm->extra); 148 &epcm->extra);
149 if (err < 0) { 149 if (err < 0) {
150 // printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); 150 /* printk("pcm_channel_alloc: failed extra: voices=%d, frame=%d\n", voices, frame); */
151 for (i = 0; i < voices; i++) { 151 for (i = 0; i < voices; i++) {
152 snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); 152 snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
153 epcm->voices[i] = NULL; 153 epcm->voices[i] = NULL;
@@ -339,7 +339,7 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
339 } 339 }
340 } 340 }
341 341
342 // setup routing 342 /* setup routing */
343 if (emu->audigy) { 343 if (emu->audigy) {
344 snd_emu10k1_ptr_write(emu, A_FXRT1, voice, 344 snd_emu10k1_ptr_write(emu, A_FXRT1, voice,
345 snd_emu10k1_compose_audigy_fxrt1(send_routing)); 345 snd_emu10k1_compose_audigy_fxrt1(send_routing));
@@ -353,12 +353,15 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
353 } else 353 } else
354 snd_emu10k1_ptr_write(emu, FXRT, voice, 354 snd_emu10k1_ptr_write(emu, FXRT, voice,
355 snd_emu10k1_compose_send_routing(send_routing)); 355 snd_emu10k1_compose_send_routing(send_routing));
356 // Stop CA 356 /* Stop CA */
357 // Assumption that PT is already 0 so no harm overwriting 357 /* Assumption that PT is already 0 so no harm overwriting */
358 snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]); 358 snd_emu10k1_ptr_write(emu, PTRX, voice, (send_amount[0] << 8) | send_amount[1]);
359 snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24)); 359 snd_emu10k1_ptr_write(emu, DSL, voice, end_addr | (send_amount[3] << 24));
360 snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24)); 360 snd_emu10k1_ptr_write(emu, PSST, voice, start_addr | (send_amount[2] << 24));
361 pitch_target = emu10k1_calc_pitch_target(runtime->rate); 361 if (emu->card_capabilities->emu1010)
362 pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
363 else
364 pitch_target = emu10k1_calc_pitch_target(runtime->rate);
362 if (extra) 365 if (extra)
363 snd_emu10k1_ptr_write(emu, CCCA, voice, start_addr | 366 snd_emu10k1_ptr_write(emu, CCCA, voice, start_addr |
364 emu10k1_select_interprom(pitch_target) | 367 emu10k1_select_interprom(pitch_target) |
@@ -367,14 +370,14 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
367 snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) | 370 snd_emu10k1_ptr_write(emu, CCCA, voice, (start_addr + ccis) |
368 emu10k1_select_interprom(pitch_target) | 371 emu10k1_select_interprom(pitch_target) |
369 (w_16 ? 0 : CCCA_8BITSELECT)); 372 (w_16 ? 0 : CCCA_8BITSELECT));
370 // Clear filter delay memory 373 /* Clear filter delay memory */
371 snd_emu10k1_ptr_write(emu, Z1, voice, 0); 374 snd_emu10k1_ptr_write(emu, Z1, voice, 0);
372 snd_emu10k1_ptr_write(emu, Z2, voice, 0); 375 snd_emu10k1_ptr_write(emu, Z2, voice, 0);
373 // invalidate maps 376 /* invalidate maps */
374 silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK; 377 silent_page = ((unsigned int)emu->silent_page.addr << 1) | MAP_PTI_MASK;
375 snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page); 378 snd_emu10k1_ptr_write(emu, MAPA, voice, silent_page);
376 snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page); 379 snd_emu10k1_ptr_write(emu, MAPB, voice, silent_page);
377 // modulation envelope 380 /* modulation envelope */
378 snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff); 381 snd_emu10k1_ptr_write(emu, CVCF, voice, 0xffff);
379 snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff); 382 snd_emu10k1_ptr_write(emu, VTFT, voice, 0xffff);
380 snd_emu10k1_ptr_write(emu, ATKHLDM, voice, 0); 383 snd_emu10k1_ptr_write(emu, ATKHLDM, voice, 0);
@@ -385,12 +388,12 @@ static void snd_emu10k1_pcm_init_voice(struct snd_emu10k1 *emu,
385 snd_emu10k1_ptr_write(emu, TREMFRQ, voice, 0); 388 snd_emu10k1_ptr_write(emu, TREMFRQ, voice, 0);
386 snd_emu10k1_ptr_write(emu, FM2FRQ2, voice, 0); 389 snd_emu10k1_ptr_write(emu, FM2FRQ2, voice, 0);
387 snd_emu10k1_ptr_write(emu, ENVVAL, voice, 0x8000); 390 snd_emu10k1_ptr_write(emu, ENVVAL, voice, 0x8000);
388 // volume envelope 391 /* volume envelope */
389 snd_emu10k1_ptr_write(emu, ATKHLDV, voice, 0x7f7f); 392 snd_emu10k1_ptr_write(emu, ATKHLDV, voice, 0x7f7f);
390 snd_emu10k1_ptr_write(emu, ENVVOL, voice, 0x0000); 393 snd_emu10k1_ptr_write(emu, ENVVOL, voice, 0x0000);
391 // filter envelope 394 /* filter envelope */
392 snd_emu10k1_ptr_write(emu, PEFE_FILTERAMOUNT, voice, 0x7f); 395 snd_emu10k1_ptr_write(emu, PEFE_FILTERAMOUNT, voice, 0x7f);
393 // pitch envelope 396 /* pitch envelope */
394 snd_emu10k1_ptr_write(emu, PEFE_PITCHAMOUNT, voice, 0); 397 snd_emu10k1_ptr_write(emu, PEFE_PITCHAMOUNT, voice, 0);
395 398
396 spin_unlock_irqrestore(&emu->reg_lock, flags); 399 spin_unlock_irqrestore(&emu->reg_lock, flags);
@@ -468,7 +471,7 @@ static int snd_emu10k1_efx_playback_hw_free(struct snd_pcm_substream *substream)
468 snd_emu10k1_voice_free(epcm->emu, epcm->extra); 471 snd_emu10k1_voice_free(epcm->emu, epcm->extra);
469 epcm->extra = NULL; 472 epcm->extra = NULL;
470 } 473 }
471 for (i=0; i < NUM_EFX_PLAYBACK; i++) { 474 for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
472 if (epcm->voices[i]) { 475 if (epcm->voices[i]) {
473 snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]); 476 snd_emu10k1_voice_free(epcm->emu, epcm->voices[i]);
474 epcm->voices[i] = NULL; 477 epcm->voices[i] = NULL;
@@ -637,7 +640,7 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
637 stereo = (!extra && runtime->channels == 2); 640 stereo = (!extra && runtime->channels == 2);
638 sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080; 641 sample = snd_pcm_format_width(runtime->format) == 16 ? 0 : 0x80808080;
639 ccis = emu10k1_ccis(stereo, sample == 0); 642 ccis = emu10k1_ccis(stereo, sample == 0);
640 // set cs to 2 * number of cache registers beside the invalidated 643 /* set cs to 2 * number of cache registers beside the invalidated */
641 cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1; 644 cs = (sample == 0) ? (32-ccis) : (64-ccis+1) >> 1;
642 if (cs > 16) cs = 16; 645 if (cs > 16) cs = 16;
643 for (i = 0; i < cs; i++) { 646 for (i = 0; i < cs; i++) {
@@ -646,14 +649,14 @@ static void snd_emu10k1_playback_invalidate_cache(struct snd_emu10k1 *emu, int e
646 snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample); 649 snd_emu10k1_ptr_write(emu, CD0 + i, voice + 1, sample);
647 } 650 }
648 } 651 }
649 // reset cache 652 /* reset cache */
650 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0); 653 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, 0);
651 snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra); 654 snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice, cra);
652 if (stereo) { 655 if (stereo) {
653 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0); 656 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice + 1, 0);
654 snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra); 657 snd_emu10k1_ptr_write(emu, CCR_READADDRESS, voice + 1, cra);
655 } 658 }
656 // fill cache 659 /* fill cache */
657 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis); 660 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice, ccis);
658 if (stereo) { 661 if (stereo) {
659 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis); 662 snd_emu10k1_ptr_write(emu, CCR_CACHEINVALIDSIZE, voice+1, ccis);
@@ -698,7 +701,10 @@ static void snd_emu10k1_playback_trigger_voice(struct snd_emu10k1 *emu, struct s
698 voice = evoice->number; 701 voice = evoice->number;
699 702
700 pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8; 703 pitch = snd_emu10k1_rate_to_pitch(runtime->rate) >> 8;
701 pitch_target = emu10k1_calc_pitch_target(runtime->rate); 704 if (emu->card_capabilities->emu1010)
705 pitch_target = PITCH_48000; /* Disable interpolators on emu1010 card */
706 else
707 pitch_target = emu10k1_calc_pitch_target(runtime->rate);
702 snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target); 708 snd_emu10k1_ptr_write(emu, PTRX_PITCHTARGET, voice, pitch_target);
703 if (master || evoice->epcm->type == PLAYBACK_EFX) 709 if (master || evoice->epcm->type == PLAYBACK_EFX)
704 snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target); 710 snd_emu10k1_ptr_write(emu, CPF_CURRENTPITCH, voice, pitch_target);
@@ -732,7 +738,7 @@ static int snd_emu10k1_playback_trigger(struct snd_pcm_substream *substream,
732 struct snd_emu10k1_pcm_mixer *mix; 738 struct snd_emu10k1_pcm_mixer *mix;
733 int result = 0; 739 int result = 0;
734 740
735 // printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); 741 /* printk("trigger - emu10k1 = 0x%x, cmd = %i, pointer = %i\n", (int)emu, cmd, substream->ops->pointer(substream)); */
736 spin_lock(&emu->reg_lock); 742 spin_lock(&emu->reg_lock);
737 switch (cmd) { 743 switch (cmd) {
738 case SNDRV_PCM_TRIGGER_START: 744 case SNDRV_PCM_TRIGGER_START:
@@ -778,10 +784,10 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
778 switch (cmd) { 784 switch (cmd) {
779 case SNDRV_PCM_TRIGGER_START: 785 case SNDRV_PCM_TRIGGER_START:
780 case SNDRV_PCM_TRIGGER_RESUME: 786 case SNDRV_PCM_TRIGGER_RESUME:
781 // hmm this should cause full and half full interrupt to be raised? 787 /* hmm this should cause full and half full interrupt to be raised? */
782 outl(epcm->capture_ipr, emu->port + IPR); 788 outl(epcm->capture_ipr, emu->port + IPR);
783 snd_emu10k1_intr_enable(emu, epcm->capture_inte); 789 snd_emu10k1_intr_enable(emu, epcm->capture_inte);
784 // printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); 790 /* printk("adccr = 0x%x, adcbs = 0x%x\n", epcm->adccr, epcm->adcbs); */
785 switch (epcm->type) { 791 switch (epcm->type) {
786 case CAPTURE_AC97ADC: 792 case CAPTURE_AC97ADC:
787 snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val); 793 snd_emu10k1_ptr_write(emu, ADCCR, 0, epcm->capture_cr_val);
@@ -790,6 +796,7 @@ static int snd_emu10k1_capture_trigger(struct snd_pcm_substream *substream,
790 if (emu->audigy) { 796 if (emu->audigy) {
791 snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val); 797 snd_emu10k1_ptr_write(emu, A_FXWC1, 0, epcm->capture_cr_val);
792 snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2); 798 snd_emu10k1_ptr_write(emu, A_FXWC2, 0, epcm->capture_cr_val2);
799 snd_printdd("cr_val=0x%x, cr_val2=0x%x\n", epcm->capture_cr_val, epcm->capture_cr_val2);
793 } else 800 } else
794 snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val); 801 snd_emu10k1_ptr_write(emu, FXWC, 0, epcm->capture_cr_val);
795 break; 802 break;
@@ -851,7 +858,7 @@ static snd_pcm_uframes_t snd_emu10k1_playback_pointer(struct snd_pcm_substream *
851 ptr -= runtime->buffer_size; 858 ptr -= runtime->buffer_size;
852 } 859 }
853#endif 860#endif
854 // printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size); 861 /* printk("ptr = 0x%x, buffer_size = 0x%x, period_size = 0x%x\n", ptr, runtime->buffer_size, runtime->period_size); */
855 return ptr; 862 return ptr;
856} 863}
857 864
@@ -868,7 +875,7 @@ static int snd_emu10k1_efx_playback_trigger(struct snd_pcm_substream *substream,
868 spin_lock(&emu->reg_lock); 875 spin_lock(&emu->reg_lock);
869 switch (cmd) { 876 switch (cmd) {
870 case SNDRV_PCM_TRIGGER_START: 877 case SNDRV_PCM_TRIGGER_START:
871 // prepare voices 878 /* prepare voices */
872 for (i = 0; i < NUM_EFX_PLAYBACK; i++) { 879 for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
873 snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]); 880 snd_emu10k1_playback_invalidate_cache(emu, 0, epcm->voices[i]);
874 } 881 }
@@ -917,7 +924,7 @@ static snd_pcm_uframes_t snd_emu10k1_capture_pointer(struct snd_pcm_substream *s
917 if (!epcm->running) 924 if (!epcm->running)
918 return 0; 925 return 0;
919 if (epcm->first_ptr) { 926 if (epcm->first_ptr) {
920 udelay(50); // hack, it takes awhile until capture is started 927 udelay(50); /* hack, it takes awhile until capture is started */
921 epcm->first_ptr = 0; 928 epcm->first_ptr = 0;
922 } 929 }
923 ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff; 930 ptr = snd_emu10k1_ptr_read(emu, epcm->capture_idx_reg, 0) & 0x0000ffff;
@@ -972,6 +979,28 @@ static struct snd_pcm_hardware snd_emu10k1_capture =
972 .fifo_size = 0, 979 .fifo_size = 0,
973}; 980};
974 981
982static struct snd_pcm_hardware snd_emu10k1_capture_efx =
983{
984 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
985 SNDRV_PCM_INFO_BLOCK_TRANSFER |
986 SNDRV_PCM_INFO_RESUME |
987 SNDRV_PCM_INFO_MMAP_VALID),
988 .formats = SNDRV_PCM_FMTBIT_S16_LE,
989 .rates = SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
990 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
991 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000,
992 .rate_min = 44100,
993 .rate_max = 192000,
994 .channels_min = 8,
995 .channels_max = 8,
996 .buffer_bytes_max = (64*1024),
997 .period_bytes_min = 384,
998 .period_bytes_max = (64*1024),
999 .periods_min = 2,
1000 .periods_max = 2,
1001 .fifo_size = 0,
1002};
1003
975/* 1004/*
976 * 1005 *
977 */ 1006 */
@@ -1016,7 +1045,7 @@ static int snd_emu10k1_efx_playback_close(struct snd_pcm_substream *substream)
1016 struct snd_emu10k1_pcm_mixer *mix; 1045 struct snd_emu10k1_pcm_mixer *mix;
1017 int i; 1046 int i;
1018 1047
1019 for (i=0; i < NUM_EFX_PLAYBACK; i++) { 1048 for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
1020 mix = &emu->efx_pcm_mixer[i]; 1049 mix = &emu->efx_pcm_mixer[i];
1021 mix->epcm = NULL; 1050 mix->epcm = NULL;
1022 snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0); 1051 snd_emu10k1_pcm_efx_mixer_notify(emu, i, 0);
@@ -1045,7 +1074,7 @@ static int snd_emu10k1_efx_playback_open(struct snd_pcm_substream *substream)
1045 runtime->private_free = snd_emu10k1_pcm_free_substream; 1074 runtime->private_free = snd_emu10k1_pcm_free_substream;
1046 runtime->hw = snd_emu10k1_efx_playback; 1075 runtime->hw = snd_emu10k1_efx_playback;
1047 1076
1048 for (i=0; i < NUM_EFX_PLAYBACK; i++) { 1077 for (i = 0; i < NUM_EFX_PLAYBACK; i++) {
1049 mix = &emu->efx_pcm_mixer[i]; 1078 mix = &emu->efx_pcm_mixer[i];
1050 mix->send_routing[0][0] = i; 1079 mix->send_routing[0][0] = i;
1051 memset(&mix->send_volume, 0, sizeof(mix->send_volume)); 1080 memset(&mix->send_volume, 0, sizeof(mix->send_volume));
@@ -1199,15 +1228,69 @@ static int snd_emu10k1_capture_efx_open(struct snd_pcm_substream *substream)
1199 epcm->capture_idx_reg = FXIDX; 1228 epcm->capture_idx_reg = FXIDX;
1200 substream->runtime->private_data = epcm; 1229 substream->runtime->private_data = epcm;
1201 substream->runtime->private_free = snd_emu10k1_pcm_free_substream; 1230 substream->runtime->private_free = snd_emu10k1_pcm_free_substream;
1202 runtime->hw = snd_emu10k1_capture; 1231 runtime->hw = snd_emu10k1_capture_efx;
1203 runtime->hw.rates = SNDRV_PCM_RATE_48000; 1232 runtime->hw.rates = SNDRV_PCM_RATE_48000;
1204 runtime->hw.rate_min = runtime->hw.rate_max = 48000; 1233 runtime->hw.rate_min = runtime->hw.rate_max = 48000;
1205 spin_lock_irq(&emu->reg_lock); 1234 spin_lock_irq(&emu->reg_lock);
1206 runtime->hw.channels_min = runtime->hw.channels_max = 0; 1235 if (emu->card_capabilities->emu1010) {
1207 for (idx = 0; idx < nefx; idx++) { 1236 /* TODO
1208 if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) { 1237 * SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE
1209 runtime->hw.channels_min++; 1238 * SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |
1210 runtime->hw.channels_max++; 1239 * SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
1240 * SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000
1241 * rate_min = 44100,
1242 * rate_max = 192000,
1243 * channels_min = 8,
1244 * channels_max = 8,
1245 * Need to add mixer control to fix sample rate
1246 *
1247 * There are 16 mono channels of 16bits each.
1248 * 24bit Audio uses 2x channels over 16bit
1249 * 96kHz uses 2x channels over 48kHz
1250 * 192kHz uses 4x channels over 48kHz
1251 * So, for 48kHz 24bit, one has 8 channels
1252 * for 96kHz 24bit, one has 4 channels
1253 * for 192kHz 24bit, one has 2 channels
1254 */
1255#if 1
1256 switch (emu->emu1010.internal_clock) {
1257 case 0:
1258 /* For 44.1kHz */
1259 runtime->hw.rates = SNDRV_PCM_RATE_44100;
1260 runtime->hw.rate_min = runtime->hw.rate_max = 44100;
1261 runtime->hw.channels_min = runtime->hw.channels_max = 8;
1262 break;
1263 case 1:
1264 /* For 48kHz */
1265 runtime->hw.rates = SNDRV_PCM_RATE_48000;
1266 runtime->hw.rate_min = runtime->hw.rate_max = 48000;
1267 runtime->hw.channels_min = runtime->hw.channels_max = 8;
1268 break;
1269 };
1270#endif
1271#if 0
1272 /* For 96kHz */
1273 runtime->hw.rates = SNDRV_PCM_RATE_96000;
1274 runtime->hw.rate_min = runtime->hw.rate_max = 96000;
1275 runtime->hw.channels_min = runtime->hw.channels_max = 4;
1276#endif
1277#if 0
1278 /* For 192kHz */
1279 runtime->hw.rates = SNDRV_PCM_RATE_192000;
1280 runtime->hw.rate_min = runtime->hw.rate_max = 192000;
1281 runtime->hw.channels_min = runtime->hw.channels_max = 2;
1282#endif
1283 runtime->hw.formats = SNDRV_PCM_FMTBIT_S32_LE;
1284 /* efx_voices_mask[0] is expected to be zero
1285 * efx_voices_mask[1] is expected to have 16bits set
1286 */
1287 } else {
1288 runtime->hw.channels_min = runtime->hw.channels_max = 0;
1289 for (idx = 0; idx < nefx; idx++) {
1290 if (emu->efx_voices_mask[idx/32] & (1 << (idx%32))) {
1291 runtime->hw.channels_min++;
1292 runtime->hw.channels_max++;
1293 }
1211 } 1294 }
1212 } 1295 }
1213 epcm->capture_cr_val = emu->efx_voices_mask[0]; 1296 epcm->capture_cr_val = emu->efx_voices_mask[0];
@@ -1460,7 +1543,7 @@ static void snd_emu10k1_fx8010_playback_tram_poke1(unsigned short *dst_left,
1460 unsigned int count, 1543 unsigned int count,
1461 unsigned int tram_shift) 1544 unsigned int tram_shift)
1462{ 1545{
1463 // printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); 1546 /* printk("tram_poke1: dst_left = 0x%p, dst_right = 0x%p, src = 0x%p, count = 0x%x\n", dst_left, dst_right, src, count); */
1464 if ((tram_shift & 1) == 0) { 1547 if ((tram_shift & 1) == 0) {
1465 while (count--) { 1548 while (count--) {
1466 *dst_left-- = *src++; 1549 *dst_left-- = *src++;
@@ -1537,7 +1620,7 @@ static int snd_emu10k1_fx8010_playback_prepare(struct snd_pcm_substream *substre
1537 struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number]; 1620 struct snd_emu10k1_fx8010_pcm *pcm = &emu->fx8010.pcm[substream->number];
1538 unsigned int i; 1621 unsigned int i;
1539 1622
1540 // printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); 1623 /* printk("prepare: etram_pages = 0x%p, dma_area = 0x%x, buffer_size = 0x%x (0x%x)\n", emu->fx8010.etram_pages, runtime->dma_area, runtime->buffer_size, runtime->buffer_size << 2); */
1541 memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec)); 1624 memset(&pcm->pcm_rec, 0, sizeof(pcm->pcm_rec));
1542 pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */ 1625 pcm->pcm_rec.hw_buffer_size = pcm->buffer_size * 2; /* byte size */
1543 pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream); 1626 pcm->pcm_rec.sw_buffer_size = snd_pcm_lib_buffer_bytes(substream);
diff --git a/sound/pci/emu10k1/emuproc.c b/sound/pci/emu10k1/emuproc.c
index b939e03aaedf..2c1585991bc8 100644
--- a/sound/pci/emu10k1/emuproc.c
+++ b/sound/pci/emu10k1/emuproc.c
@@ -3,6 +3,9 @@
3 * Creative Labs, Inc. 3 * Creative Labs, Inc.
4 * Routines for control of EMU10K1 chips / proc interface routines 4 * Routines for control of EMU10K1 chips / proc interface routines
5 * 5 *
6 * Copyright (c) by James Courtier-Dutton <James@superbug.co.uk>
7 * Added EMU 1010 support.
8 *
6 * BUGS: 9 * BUGS:
7 * -- 10 * --
8 * 11 *
@@ -255,7 +258,7 @@ static void snd_emu10k1_proc_rates_read(struct snd_info_entry *entry,
255 unsigned int val, tmp, n; 258 unsigned int val, tmp, n;
256 val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0); 259 val = snd_emu10k1_ptr20_read(emu, CAPTURE_RATE_STATUS, 0);
257 tmp = (val >> 16) & 0x8; 260 tmp = (val >> 16) & 0x8;
258 for (n=0;n<4;n++) { 261 for (n = 0; n < 4; n++) {
259 tmp = val >> (16 + (n*4)); 262 tmp = val >> (16 + (n*4));
260 if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]); 263 if (tmp & 0x8) snd_iprintf(buffer, "Channel %d: Rate=%d\n", n, samplerate[tmp & 0x7]);
261 else snd_iprintf(buffer, "Channel %d: No input\n", n); 264 else snd_iprintf(buffer, "Channel %d: No input\n", n);
@@ -372,6 +375,27 @@ static void snd_emu10k1_proc_voices_read(struct snd_info_entry *entry,
372} 375}
373 376
374#ifdef CONFIG_SND_DEBUG 377#ifdef CONFIG_SND_DEBUG
378static void snd_emu_proc_emu1010_reg_read(struct snd_info_entry *entry,
379 struct snd_info_buffer *buffer)
380{
381 struct snd_emu10k1 *emu = entry->private_data;
382 unsigned long value;
383 unsigned long flags;
384 unsigned long regs;
385 int i;
386 snd_iprintf(buffer, "EMU1010 Registers:\n\n");
387
388 for(i = 0; i < 0x30; i+=1) {
389 spin_lock_irqsave(&emu->emu_lock, flags);
390 regs=i+0x40; /* 0x40 upwards are registers. */
391 outl(regs, emu->port + A_IOCFG);
392 outl(regs | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
393 value = inl(emu->port + A_IOCFG);
394 spin_unlock_irqrestore(&emu->emu_lock, flags);
395 snd_iprintf(buffer, "%02X: %08lX, %02lX\n", i, value, (value >> 8) & 0x7f);
396 }
397}
398
375static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry, 399static void snd_emu_proc_io_reg_read(struct snd_info_entry *entry,
376 struct snd_info_buffer *buffer) 400 struct snd_info_buffer *buffer)
377{ 401{
@@ -398,7 +422,7 @@ static void snd_emu_proc_io_reg_write(struct snd_info_entry *entry,
398 while (!snd_info_get_line(buffer, line, sizeof(line))) { 422 while (!snd_info_get_line(buffer, line, sizeof(line))) {
399 if (sscanf(line, "%x %x", &reg, &val) != 2) 423 if (sscanf(line, "%x %x", &reg, &val) != 2)
400 continue; 424 continue;
401 if ((reg < 0x40) && (reg >=0) && (val <= 0xffffffff) ) { 425 if ((reg < 0x40) && (reg >= 0) && (val <= 0xffffffff) ) {
402 spin_lock_irqsave(&emu->emu_lock, flags); 426 spin_lock_irqsave(&emu->emu_lock, flags);
403 outl(val, emu->port + (reg & 0xfffffffc)); 427 outl(val, emu->port + (reg & 0xfffffffc));
404 spin_unlock_irqrestore(&emu->emu_lock, flags); 428 spin_unlock_irqrestore(&emu->emu_lock, flags);
@@ -474,7 +498,7 @@ static void snd_emu_proc_ptr_reg_write(struct snd_info_entry *entry,
474 while (!snd_info_get_line(buffer, line, sizeof(line))) { 498 while (!snd_info_get_line(buffer, line, sizeof(line))) {
475 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3) 499 if (sscanf(line, "%x %x %x", &reg, &channel_id, &val) != 3)
476 continue; 500 continue;
477 if ((reg < 0xa0) && (reg >=0) && (val <= 0xffffffff) && (channel_id >=0) && (channel_id <= 3) ) 501 if ((reg < 0xa0) && (reg >= 0) && (val <= 0xffffffff) && (channel_id >= 0) && (channel_id <= 3) )
478 snd_ptr_write(emu, iobase, reg, channel_id, val); 502 snd_ptr_write(emu, iobase, reg, channel_id, val);
479 } 503 }
480} 504}
@@ -531,6 +555,10 @@ int __devinit snd_emu10k1_proc_init(struct snd_emu10k1 * emu)
531{ 555{
532 struct snd_info_entry *entry; 556 struct snd_info_entry *entry;
533#ifdef CONFIG_SND_DEBUG 557#ifdef CONFIG_SND_DEBUG
558 if ((emu->card_capabilities->emu1010) &&
559 snd_card_proc_new(emu->card, "emu1010_regs", &entry)) {
560 snd_info_set_text_ops(entry, emu, snd_emu_proc_emu1010_reg_read);
561 }
534 if (! snd_card_proc_new(emu->card, "io_regs", &entry)) { 562 if (! snd_card_proc_new(emu->card, "io_regs", &entry)) {
535 snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read); 563 snd_info_set_text_ops(entry, emu, snd_emu_proc_io_reg_read);
536 entry->c.text.write = snd_emu_proc_io_reg_write; 564 entry->c.text.write = snd_emu_proc_io_reg_write;
diff --git a/sound/pci/emu10k1/io.c b/sound/pci/emu10k1/io.c
index 029e7856c43b..116e1c8d9361 100644
--- a/sound/pci/emu10k1/io.c
+++ b/sound/pci/emu10k1/io.c
@@ -30,6 +30,7 @@
30#include <sound/core.h> 30#include <sound/core.h>
31#include <sound/emu10k1.h> 31#include <sound/emu10k1.h>
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include "p17v.h"
33 34
34unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn) 35unsigned int snd_emu10k1_ptr_read(struct snd_emu10k1 * emu, unsigned int reg, unsigned int chn)
35{ 36{
@@ -167,6 +168,109 @@ int snd_emu10k1_spi_write(struct snd_emu10k1 * emu,
167 return 0; 168 return 0;
168} 169}
169 170
171/* The ADC does not support i2c read, so only write is implemented */
172int snd_emu10k1_i2c_write(struct snd_emu10k1 *emu,
173 u32 reg,
174 u32 value)
175{
176 u32 tmp;
177 int timeout = 0;
178 int status;
179 int retry;
180 if ((reg > 0x7f) || (value > 0x1ff)) {
181 snd_printk(KERN_ERR "i2c_write: invalid values.\n");
182 return -EINVAL;
183 }
184
185 tmp = reg << 25 | value << 16;
186 // snd_printk("I2C-write:reg=0x%x, value=0x%x\n", reg, value);
187 /* Not sure what this I2C channel controls. */
188 /* snd_emu10k1_ptr_write(emu, P17V_I2C_0, 0, tmp); */
189
190 /* This controls the I2C connected to the WM8775 ADC Codec */
191 snd_emu10k1_ptr20_write(emu, P17V_I2C_1, 0, tmp);
192 tmp = snd_emu10k1_ptr20_read(emu, P17V_I2C_1, 0); /* write post */
193
194 for (retry = 0; retry < 10; retry++) {
195 /* Send the data to i2c */
196 //tmp = snd_emu10k1_ptr_read(emu, P17V_I2C_ADDR, 0);
197 //tmp = tmp & ~(I2C_A_ADC_READ|I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD_MASK);
198 tmp = 0;
199 tmp = tmp | (I2C_A_ADC_LAST|I2C_A_ADC_START|I2C_A_ADC_ADD);
200 snd_emu10k1_ptr20_write(emu, P17V_I2C_ADDR, 0, tmp);
201
202 /* Wait till the transaction ends */
203 while (1) {
204 udelay(10);
205 status = snd_emu10k1_ptr20_read(emu, P17V_I2C_ADDR, 0);
206 // snd_printk("I2C:status=0x%x\n", status);
207 timeout++;
208 if ((status & I2C_A_ADC_START) == 0)
209 break;
210
211 if (timeout > 1000) {
212 snd_printk("emu10k1:I2C:timeout status=0x%x\n", status);
213 break;
214 }
215 }
216 //Read back and see if the transaction is successful
217 if ((status & I2C_A_ADC_ABORT) == 0)
218 break;
219 }
220
221 if (retry == 10) {
222 snd_printk(KERN_ERR "Writing to ADC failed!\n");
223 return -EINVAL;
224 }
225
226 return 0;
227}
228
229int snd_emu1010_fpga_write(struct snd_emu10k1 * emu, int reg, int value)
230{
231 if (reg < 0 || reg > 0x3f)
232 return 1;
233 reg += 0x40; /* 0x40 upwards are registers. */
234 if (value < 0 || value > 0x3f) /* 0 to 0x3f are values */
235 return 1;
236 outl(reg, emu->port + A_IOCFG);
237 udelay(10);
238 outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
239 udelay(10);
240 outl(value, emu->port + A_IOCFG);
241 udelay(10);
242 outl(value | 0x80 , emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
243
244 return 0;
245}
246
247int snd_emu1010_fpga_read(struct snd_emu10k1 * emu, int reg, int *value)
248{
249 if (reg < 0 || reg > 0x3f)
250 return 1;
251 reg += 0x40; /* 0x40 upwards are registers. */
252 outl(reg, emu->port + A_IOCFG);
253 udelay(10);
254 outl(reg | 0x80, emu->port + A_IOCFG); /* High bit clocks the value into the fpga. */
255 udelay(10);
256 *value = ((inl(emu->port + A_IOCFG) >> 8) & 0x7f);
257
258 return 0;
259}
260
261/* Each Destination has one and only one Source,
262 * but one Source can feed any number of Destinations simultaneously.
263 */
264int snd_emu1010_fpga_link_dst_src_write(struct snd_emu10k1 * emu, int dst, int src)
265{
266 snd_emu1010_fpga_write(emu, 0x00, ((dst >> 8) & 0x3f) );
267 snd_emu1010_fpga_write(emu, 0x01, (dst & 0x3f) );
268 snd_emu1010_fpga_write(emu, 0x02, ((src >> 8) & 0x3f) );
269 snd_emu1010_fpga_write(emu, 0x03, (src & 0x3f) );
270
271 return 0;
272}
273
170void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb) 274void snd_emu10k1_intr_enable(struct snd_emu10k1 *emu, unsigned int intrenb)
171{ 275{
172 unsigned long flags; 276 unsigned long flags;
diff --git a/sound/pci/emu10k1/p16v.c b/sound/pci/emu10k1/p16v.c
index 4e0f95438f47..465f8d505329 100644
--- a/sound/pci/emu10k1/p16v.c
+++ b/sound/pci/emu10k1/p16v.c
@@ -253,7 +253,7 @@ static int snd_p16v_pcm_close_playback(struct snd_pcm_substream *substream)
253 struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); 253 struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
254 //struct snd_pcm_runtime *runtime = substream->runtime; 254 //struct snd_pcm_runtime *runtime = substream->runtime;
255 //struct snd_emu10k1_pcm *epcm = runtime->private_data; 255 //struct snd_emu10k1_pcm *epcm = runtime->private_data;
256 emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use=0; 256 emu->p16v_voices[substream->pcm->device - emu->p16v_device_offset].use = 0;
257 /* FIXME: maybe zero others */ 257 /* FIXME: maybe zero others */
258 return 0; 258 return 0;
259} 259}
@@ -264,7 +264,7 @@ static int snd_p16v_pcm_close_capture(struct snd_pcm_substream *substream)
264 struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream); 264 struct snd_emu10k1 *emu = snd_pcm_substream_chip(substream);
265 //struct snd_pcm_runtime *runtime = substream->runtime; 265 //struct snd_pcm_runtime *runtime = substream->runtime;
266 //struct snd_emu10k1_pcm *epcm = runtime->private_data; 266 //struct snd_emu10k1_pcm *epcm = runtime->private_data;
267 emu->p16v_capture_voice.use=0; 267 emu->p16v_capture_voice.use = 0;
268 /* FIXME: maybe zero others */ 268 /* FIXME: maybe zero others */
269 return 0; 269 return 0;
270} 270}
@@ -349,7 +349,7 @@ static int snd_p16v_pcm_prepare_playback(struct snd_pcm_substream *substream)
349 break; 349 break;
350 } 350 }
351 /* FIXME: Check emu->buffer.size before actually writing to it. */ 351 /* FIXME: Check emu->buffer.size before actually writing to it. */
352 for(i=0; i < runtime->periods; i++) { 352 for(i = 0; i < runtime->periods; i++) {
353 table_base[i*2]=runtime->dma_addr+(i*period_size_bytes); 353 table_base[i*2]=runtime->dma_addr+(i*period_size_bytes);
354 table_base[(i*2)+1]=period_size_bytes<<16; 354 table_base[(i*2)+1]=period_size_bytes<<16;
355 } 355 }
@@ -394,7 +394,7 @@ static int snd_p16v_pcm_prepare_capture(struct snd_pcm_substream *substream)
394 /* FIXME: Check emu->buffer.size before actually writing to it. */ 394 /* FIXME: Check emu->buffer.size before actually writing to it. */
395 snd_emu10k1_ptr20_write(emu, 0x13, channel, 0); 395 snd_emu10k1_ptr20_write(emu, 0x13, channel, 0);
396 snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr); 396 snd_emu10k1_ptr20_write(emu, CAPTURE_DMA_ADDR, channel, runtime->dma_addr);
397 snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size)<<16); // buffer size in bytes 397 snd_emu10k1_ptr20_write(emu, CAPTURE_BUFFER_SIZE, channel, frames_to_bytes(runtime, runtime->buffer_size) << 16); // buffer size in bytes
398 snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0); 398 snd_emu10k1_ptr20_write(emu, CAPTURE_POINTER, channel, 0);
399 //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */ 399 //snd_emu10k1_ptr20_write(emu, CAPTURE_SOURCE, 0x0, 0x333300e4); /* Select MIC or Line in */
400 //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel)); 400 //snd_emu10k1_ptr20_write(emu, EXTENDED_INT_MASK, 0, snd_emu10k1_ptr20_read(emu, EXTENDED_INT_MASK, 0) | (0x110000<<channel));
@@ -437,7 +437,7 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
437 struct snd_pcm_substream *s; 437 struct snd_pcm_substream *s;
438 u32 basic = 0; 438 u32 basic = 0;
439 u32 inte = 0; 439 u32 inte = 0;
440 int running=0; 440 int running = 0;
441 441
442 switch (cmd) { 442 switch (cmd) {
443 case SNDRV_PCM_TRIGGER_START: 443 case SNDRV_PCM_TRIGGER_START:
@@ -445,7 +445,7 @@ static int snd_p16v_pcm_trigger_playback(struct snd_pcm_substream *substream,
445 break; 445 break;
446 case SNDRV_PCM_TRIGGER_STOP: 446 case SNDRV_PCM_TRIGGER_STOP:
447 default: 447 default:
448 running=0; 448 running = 0;
449 break; 449 break;
450 } 450 }
451 snd_pcm_group_for_each(pos, substream) { 451 snd_pcm_group_for_each(pos, substream) {
@@ -785,7 +785,7 @@ static int snd_p16v_capture_channel_put(struct snd_kcontrol *kcontrol,
785 } 785 }
786 return change; 786 return change;
787} 787}
788static DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1); 788static const DECLARE_TLV_DB_SCALE(snd_p16v_db_scale1, -5175, 25, 1);
789 789
790#define P16V_VOL(xname,xreg,xhl) { \ 790#define P16V_VOL(xname,xreg,xhl) { \
791 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ 791 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
diff --git a/sound/pci/emu10k1/p17v.h b/sound/pci/emu10k1/p17v.h
index 7ddb5be632cf..4ef5f68a9cd0 100644
--- a/sound/pci/emu10k1/p17v.h
+++ b/sound/pci/emu10k1/p17v.h
@@ -43,6 +43,53 @@
43#define P17V_I2C_ADDR 0x3d /* I2C Address */ 43#define P17V_I2C_ADDR 0x3d /* I2C Address */
44#define P17V_I2C_0 0x3e /* I2C Data */ 44#define P17V_I2C_0 0x3e /* I2C Data */
45#define P17V_I2C_1 0x3f /* I2C Data */ 45#define P17V_I2C_1 0x3f /* I2C Data */
46/* I2C values */
47#define I2C_A_ADC_ADD_MASK 0x000000fe /*The address is a 7 bit address */
48#define I2C_A_ADC_RW_MASK 0x00000001 /*bit mask for R/W */
49#define I2C_A_ADC_TRANS_MASK 0x00000010 /*Bit mask for I2c address DAC value */
50#define I2C_A_ADC_ABORT_MASK 0x00000020 /*Bit mask for I2C transaction abort flag */
51#define I2C_A_ADC_LAST_MASK 0x00000040 /*Bit mask for Last word transaction */
52#define I2C_A_ADC_BYTE_MASK 0x00000080 /*Bit mask for Byte Mode */
53
54#define I2C_A_ADC_ADD 0x00000034 /*This is the Device address for ADC */
55#define I2C_A_ADC_READ 0x00000001 /*To perform a read operation */
56#define I2C_A_ADC_START 0x00000100 /*Start I2C transaction */
57#define I2C_A_ADC_ABORT 0x00000200 /*I2C transaction abort */
58#define I2C_A_ADC_LAST 0x00000400 /*I2C last transaction */
59#define I2C_A_ADC_BYTE 0x00000800 /*I2C one byte mode */
60
61#define I2C_D_ADC_REG_MASK 0xfe000000 /*ADC address register */
62#define I2C_D_ADC_DAT_MASK 0x01ff0000 /*ADC data register */
63
64#define ADC_TIMEOUT 0x00000007 /*ADC Timeout Clock Disable */
65#define ADC_IFC_CTRL 0x0000000b /*ADC Interface Control */
66#define ADC_MASTER 0x0000000c /*ADC Master Mode Control */
67#define ADC_POWER 0x0000000d /*ADC PowerDown Control */
68#define ADC_ATTEN_ADCL 0x0000000e /*ADC Attenuation ADCL */
69#define ADC_ATTEN_ADCR 0x0000000f /*ADC Attenuation ADCR */
70#define ADC_ALC_CTRL1 0x00000010 /*ADC ALC Control 1 */
71#define ADC_ALC_CTRL2 0x00000011 /*ADC ALC Control 2 */
72#define ADC_ALC_CTRL3 0x00000012 /*ADC ALC Control 3 */
73#define ADC_NOISE_CTRL 0x00000013 /*ADC Noise Gate Control */
74#define ADC_LIMIT_CTRL 0x00000014 /*ADC Limiter Control */
75#define ADC_MUX 0x00000015 /*ADC Mux offset */
76#if 0
77/* FIXME: Not tested yet. */
78#define ADC_GAIN_MASK 0x000000ff //Mask for ADC Gain
79#define ADC_ZERODB 0x000000cf //Value to set ADC to 0dB
80#define ADC_MUTE_MASK 0x000000c0 //Mask for ADC mute
81#define ADC_MUTE 0x000000c0 //Value to mute ADC
82#define ADC_OSR 0x00000008 //Mask for ADC oversample rate select
83#define ADC_TIMEOUT_DISABLE 0x00000008 //Value and mask to disable Timeout clock
84#define ADC_HPF_DISABLE 0x00000100 //Value and mask to disable High pass filter
85#define ADC_TRANWIN_MASK 0x00000070 //Mask for Length of Transient Window
86#endif
87
88#define ADC_MUX_MASK 0x0000000f //Mask for ADC Mux
89#define ADC_MUX_0 0x00000001 //Value to select Unknown at ADC Mux (Not used)
90#define ADC_MUX_1 0x00000002 //Value to select Unknown at ADC Mux (Not used)
91#define ADC_MUX_2 0x00000004 //Value to select Mic at ADC Mux
92#define ADC_MUX_3 0x00000008 //Value to select Line-In at ADC Mux
46 93
47#define P17V_START_AUDIO 0x40 /* Start Audio bit */ 94#define P17V_START_AUDIO 0x40 /* Start Audio bit */
48/* 41 - 47: Reserved */ 95/* 41 - 47: Reserved */
diff --git a/sound/pci/emu10k1/voice.c b/sound/pci/emu10k1/voice.c
index 94eca82dd4fc..1db50fe61475 100644
--- a/sound/pci/emu10k1/voice.c
+++ b/sound/pci/emu10k1/voice.c
@@ -83,7 +83,7 @@ static int voice_alloc(struct snd_emu10k1 *emu, int type, int number,
83 if (first_voice == last_voice) 83 if (first_voice == last_voice)
84 return -ENOMEM; 84 return -ENOMEM;
85 85
86 for (i=0; i < number; i++) { 86 for (i = 0; i < number; i++) {
87 voice = &emu->voices[(first_voice + i) % NUM_G]; 87 voice = &emu->voices[(first_voice + i) % NUM_G];
88 // printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number); 88 // printk("voice alloc - %i, %i of %i\n", voice->number, idx-first_voice+1, number);
89 voice->use = 1; 89 voice->use = 1;
diff --git a/sound/pci/ens1370.c b/sound/pci/ens1370.c
index a84f6b21024f..425b167522d5 100644
--- a/sound/pci/ens1370.c
+++ b/sound/pci/ens1370.c
@@ -413,8 +413,6 @@ struct ensoniq {
413 } u; 413 } u;
414 414
415 struct pci_dev *pci; 415 struct pci_dev *pci;
416 unsigned short subsystem_vendor_id;
417 unsigned short subsystem_device_id;
418 struct snd_card *card; 416 struct snd_card *card;
419 struct snd_pcm *pcm1; /* DAC1/ADC PCM */ 417 struct snd_pcm *pcm1; /* DAC1/ADC PCM */
420 struct snd_pcm *pcm2; /* DAC2 PCM */ 418 struct snd_pcm *pcm2; /* DAC2 PCM */
@@ -1607,11 +1605,26 @@ static void snd_ensoniq_mixer_free_ac97(struct snd_ac97 *ac97)
1607 ensoniq->u.es1371.ac97 = NULL; 1605 ensoniq->u.es1371.ac97 = NULL;
1608} 1606}
1609 1607
1610static struct { 1608struct es1371_quirk {
1611 unsigned short vid; /* vendor ID */ 1609 unsigned short vid; /* vendor ID */
1612 unsigned short did; /* device ID */ 1610 unsigned short did; /* device ID */
1613 unsigned char rev; /* revision */ 1611 unsigned char rev; /* revision */
1614} es1371_spdif_present[] __devinitdata = { 1612};
1613
1614static int __devinit es1371_quirk_lookup(struct ensoniq *ensoniq,
1615 struct es1371_quirk *list)
1616{
1617 while (list->vid != (unsigned short)PCI_ANY_ID) {
1618 if (ensoniq->pci->vendor == list->vid &&
1619 ensoniq->pci->device == list->did &&
1620 ensoniq->rev == list->rev)
1621 return 1;
1622 list++;
1623 }
1624 return 0;
1625}
1626
1627static struct es1371_quirk es1371_spdif_present[] __devinitdata = {
1615 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, 1628 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
1616 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, 1629 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
1617 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, 1630 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@@ -1620,12 +1633,19 @@ static struct {
1620 { .vid = PCI_ANY_ID, .did = PCI_ANY_ID } 1633 { .vid = PCI_ANY_ID, .did = PCI_ANY_ID }
1621}; 1634};
1622 1635
1623static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int has_line) 1636static struct snd_pci_quirk ens1373_line_quirk[] __devinitdata = {
1637 SND_PCI_QUIRK_ID(0x1274, 0x2000), /* GA-7DXR */
1638 SND_PCI_QUIRK_ID(0x1458, 0xa000), /* GA-8IEXP */
1639 { } /* end */
1640};
1641
1642static int __devinit snd_ensoniq_1371_mixer(struct ensoniq *ensoniq,
1643 int has_spdif, int has_line)
1624{ 1644{
1625 struct snd_card *card = ensoniq->card; 1645 struct snd_card *card = ensoniq->card;
1626 struct snd_ac97_bus *pbus; 1646 struct snd_ac97_bus *pbus;
1627 struct snd_ac97_template ac97; 1647 struct snd_ac97_template ac97;
1628 int err, idx; 1648 int err;
1629 static struct snd_ac97_bus_ops ops = { 1649 static struct snd_ac97_bus_ops ops = {
1630 .write = snd_es1371_codec_write, 1650 .write = snd_es1371_codec_write,
1631 .read = snd_es1371_codec_read, 1651 .read = snd_es1371_codec_read,
@@ -1641,33 +1661,28 @@ static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int h
1641 ac97.scaps = AC97_SCAP_AUDIO; 1661 ac97.scaps = AC97_SCAP_AUDIO;
1642 if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0) 1662 if ((err = snd_ac97_mixer(pbus, &ac97, &ensoniq->u.es1371.ac97)) < 0)
1643 return err; 1663 return err;
1644 for (idx = 0; es1371_spdif_present[idx].vid != (unsigned short)PCI_ANY_ID; idx++) 1664 if (has_spdif > 0 ||
1645 if ((ensoniq->pci->vendor == es1371_spdif_present[idx].vid && 1665 (!has_spdif && es1371_quirk_lookup(ensoniq, es1371_spdif_present))) {
1646 ensoniq->pci->device == es1371_spdif_present[idx].did && 1666 struct snd_kcontrol *kctl;
1647 ensoniq->rev == es1371_spdif_present[idx].rev) || has_spdif > 0) { 1667 int i, index = 0;
1648 struct snd_kcontrol *kctl; 1668
1649 int i, index = 0; 1669 ensoniq->spdif_default = ensoniq->spdif_stream =
1650 1670 SNDRV_PCM_DEFAULT_CON_SPDIF;
1651 if (has_spdif < 0) 1671 outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS));
1652 break; 1672
1653 1673 if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF)
1654 ensoniq->spdif_default = ensoniq->spdif_stream = 1674 index++;
1655 SNDRV_PCM_DEFAULT_CON_SPDIF; 1675
1656 outl(ensoniq->spdif_default, ES_REG(ensoniq, CHANNEL_STATUS)); 1676 for (i = 0; i < ARRAY_SIZE(snd_es1371_mixer_spdif); i++) {
1657 1677 kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq);
1658 if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SPDIF) 1678 if (!kctl)
1659 index++; 1679 return -ENOMEM;
1660 1680 kctl->id.index = index;
1661 for (i = 0; i < (int)ARRAY_SIZE(snd_es1371_mixer_spdif); i++) { 1681 err = snd_ctl_add(card, kctl);
1662 kctl = snd_ctl_new1(&snd_es1371_mixer_spdif[i], ensoniq); 1682 if (err < 0)
1663 if (! kctl) 1683 return err;
1664 return -ENOMEM;
1665 kctl->id.index = index;
1666 if ((err = snd_ctl_add(card, kctl)) < 0)
1667 return err;
1668 }
1669 break;
1670 } 1684 }
1685 }
1671 if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) { 1686 if (ensoniq->u.es1371.ac97->ext_id & AC97_EI_SDAC) {
1672 /* mirror rear to front speakers */ 1687 /* mirror rear to front speakers */
1673 ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT24); 1688 ensoniq->cssr &= ~(ES_1373_REAR_BIT27|ES_1373_REAR_BIT24);
@@ -1676,12 +1691,10 @@ static int snd_ensoniq_1371_mixer(struct ensoniq * ensoniq, int has_spdif, int h
1676 if (err < 0) 1691 if (err < 0)
1677 return err; 1692 return err;
1678 } 1693 }
1679 if (((ensoniq->subsystem_vendor_id == 0x1274) && 1694 if (has_line > 0 ||
1680 (ensoniq->subsystem_device_id == 0x2000)) || /* GA-7DXR */ 1695 snd_pci_quirk_lookup(ensoniq->pci, ens1373_line_quirk)) {
1681 ((ensoniq->subsystem_vendor_id == 0x1458) && 1696 err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line,
1682 (ensoniq->subsystem_device_id == 0xa000)) || /* GA-8IEXP */ 1697 ensoniq));
1683 has_line > 0) {
1684 err = snd_ctl_add(card, snd_ctl_new1(&snd_ens1373_line, ensoniq));
1685 if (err < 0) 1698 if (err < 0)
1686 return err; 1699 return err;
1687 } 1700 }
@@ -1956,21 +1969,15 @@ static int snd_ensoniq_dev_free(struct snd_device *device)
1956} 1969}
1957 1970
1958#ifdef CHIP1371 1971#ifdef CHIP1371
1959static struct { 1972static struct snd_pci_quirk es1371_amplifier_hack[] __devinitdata = {
1960 unsigned short svid; /* subsystem vendor ID */ 1973 SND_PCI_QUIRK_ID(0x107b, 0x2150), /* Gateway Solo 2150 */
1961 unsigned short sdid; /* subsystem device ID */ 1974 SND_PCI_QUIRK_ID(0x13bd, 0x100c), /* EV1938 on Mebius PC-MJ100V */
1962} es1371_amplifier_hack[] = { 1975 SND_PCI_QUIRK_ID(0x1102, 0x5938), /* Targa Xtender300 */
1963 { .svid = 0x107b, .sdid = 0x2150 }, /* Gateway Solo 2150 */ 1976 SND_PCI_QUIRK_ID(0x1102, 0x8938), /* IPC Topnote G notebook */
1964 { .svid = 0x13bd, .sdid = 0x100c }, /* EV1938 on Mebius PC-MJ100V */ 1977 { } /* end */
1965 { .svid = 0x1102, .sdid = 0x5938 }, /* Targa Xtender300 */
1966 { .svid = 0x1102, .sdid = 0x8938 }, /* IPC Topnote G notebook */
1967 { .svid = PCI_ANY_ID, .sdid = PCI_ANY_ID }
1968}; 1978};
1969static struct { 1979
1970 unsigned short vid; /* vendor ID */ 1980static struct es1371_quirk es1371_ac97_reset_hack[] = {
1971 unsigned short did; /* device ID */
1972 unsigned char rev; /* revision */
1973} es1371_ac97_reset_hack[] = {
1974 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C }, 1981 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_C },
1975 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D }, 1982 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_D },
1976 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E }, 1983 { .vid = PCI_VENDOR_ID_ENSONIQ, .did = PCI_DEVICE_ID_ENSONIQ_CT5880, .rev = CT5880REV_CT5880_E },
@@ -1984,7 +1991,6 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
1984{ 1991{
1985#ifdef CHIP1371 1992#ifdef CHIP1371
1986 int idx; 1993 int idx;
1987 struct pci_dev *pci = ensoniq->pci;
1988#endif 1994#endif
1989 /* this code was part of snd_ensoniq_create before intruduction 1995 /* this code was part of snd_ensoniq_create before intruduction
1990 * of suspend/resume 1996 * of suspend/resume
@@ -1999,16 +2005,12 @@ static void snd_ensoniq_chip_init(struct ensoniq *ensoniq)
1999 outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL)); 2005 outl(ensoniq->ctrl, ES_REG(ensoniq, CONTROL));
2000 outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL)); 2006 outl(ensoniq->sctrl, ES_REG(ensoniq, SERIAL));
2001 outl(0, ES_REG(ensoniq, 1371_LEGACY)); 2007 outl(0, ES_REG(ensoniq, 1371_LEGACY));
2002 for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++) 2008 if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack)) {
2003 if (pci->vendor == es1371_ac97_reset_hack[idx].vid && 2009 outl(ensoniq->cssr, ES_REG(ensoniq, STATUS));
2004 pci->device == es1371_ac97_reset_hack[idx].did && 2010 /* need to delay around 20ms(bleech) to give
2005 ensoniq->rev == es1371_ac97_reset_hack[idx].rev) { 2011 some CODECs enough time to wakeup */
2006 outl(ensoniq->cssr, ES_REG(ensoniq, STATUS)); 2012 msleep(20);
2007 /* need to delay around 20ms(bleech) to give 2013 }
2008 some CODECs enough time to wakeup */
2009 msleep(20);
2010 break;
2011 }
2012 /* AC'97 warm reset to start the bitclk */ 2014 /* AC'97 warm reset to start the bitclk */
2013 outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL)); 2015 outl(ensoniq->ctrl | ES_1371_SYNC_RES, ES_REG(ensoniq, CONTROL));
2014 inl(ES_REG(ensoniq, CONTROL)); 2016 inl(ES_REG(ensoniq, CONTROL));
@@ -2112,11 +2114,7 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
2112 struct ensoniq ** rensoniq) 2114 struct ensoniq ** rensoniq)
2113{ 2115{
2114 struct ensoniq *ensoniq; 2116 struct ensoniq *ensoniq;
2115 unsigned short cmdw;
2116 unsigned char cmdb; 2117 unsigned char cmdb;
2117#ifdef CHIP1371
2118 int idx;
2119#endif
2120 int err; 2118 int err;
2121 static struct snd_device_ops ops = { 2119 static struct snd_device_ops ops = {
2122 .dev_free = snd_ensoniq_dev_free, 2120 .dev_free = snd_ensoniq_dev_free,
@@ -2159,10 +2157,6 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
2159 pci_set_master(pci); 2157 pci_set_master(pci);
2160 pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb); 2158 pci_read_config_byte(pci, PCI_REVISION_ID, &cmdb);
2161 ensoniq->rev = cmdb; 2159 ensoniq->rev = cmdb;
2162 pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &cmdw);
2163 ensoniq->subsystem_vendor_id = cmdw;
2164 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &cmdw);
2165 ensoniq->subsystem_device_id = cmdw;
2166#ifdef CHIP1370 2160#ifdef CHIP1370
2167#if 0 2161#if 0
2168 ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE | 2162 ensoniq->ctrl = ES_1370_CDC_EN | ES_1370_SERR_DISABLE |
@@ -2175,19 +2169,11 @@ static int __devinit snd_ensoniq_create(struct snd_card *card,
2175 ensoniq->ctrl = 0; 2169 ensoniq->ctrl = 0;
2176 ensoniq->sctrl = 0; 2170 ensoniq->sctrl = 0;
2177 ensoniq->cssr = 0; 2171 ensoniq->cssr = 0;
2178 for (idx = 0; es1371_amplifier_hack[idx].svid != (unsigned short)PCI_ANY_ID; idx++) 2172 if (snd_pci_quirk_lookup(pci, es1371_amplifier_hack))
2179 if (ensoniq->subsystem_vendor_id == es1371_amplifier_hack[idx].svid && 2173 ensoniq->ctrl |= ES_1371_GPIO_OUT(1); /* turn amplifier on */
2180 ensoniq->subsystem_device_id == es1371_amplifier_hack[idx].sdid) { 2174
2181 ensoniq->ctrl |= ES_1371_GPIO_OUT(1); /* turn amplifier on */ 2175 if (es1371_quirk_lookup(ensoniq, es1371_ac97_reset_hack))
2182 break; 2176 ensoniq->cssr |= ES_1371_ST_AC97_RST;
2183 }
2184 for (idx = 0; es1371_ac97_reset_hack[idx].vid != (unsigned short)PCI_ANY_ID; idx++)
2185 if (pci->vendor == es1371_ac97_reset_hack[idx].vid &&
2186 pci->device == es1371_ac97_reset_hack[idx].did &&
2187 ensoniq->rev == es1371_ac97_reset_hack[idx].rev) {
2188 ensoniq->cssr |= ES_1371_ST_AC97_RST;
2189 break;
2190 }
2191#endif 2177#endif
2192 2178
2193 snd_ensoniq_chip_init(ensoniq); 2179 snd_ensoniq_chip_init(ensoniq);
diff --git a/sound/pci/es1938.c b/sound/pci/es1938.c
index 66ac26c5a240..fec29a108945 100644
--- a/sound/pci/es1938.c
+++ b/sound/pci/es1938.c
@@ -1344,7 +1344,7 @@ static unsigned int db_scale_line[] = {
1344 8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0), 1344 8, 15, TLV_DB_SCALE_ITEM(-750, 150, 0),
1345}; 1345};
1346 1346
1347static DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0); 1347static const DECLARE_TLV_DB_SCALE(db_scale_capture, 0, 150, 0);
1348 1348
1349static struct snd_kcontrol_new snd_es1938_controls[] = { 1349static struct snd_kcontrol_new snd_es1938_controls[] = {
1350ES1938_DOUBLE_TLV("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0, 1350ES1938_DOUBLE_TLV("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0,
diff --git a/sound/pci/fm801.c b/sound/pci/fm801.c
index b7b361ce3a93..6dc578bbeec9 100644
--- a/sound/pci/fm801.c
+++ b/sound/pci/fm801.c
@@ -1157,7 +1157,7 @@ static int snd_fm801_put_mux(struct snd_kcontrol *kcontrol,
1157 return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val); 1157 return snd_fm801_update_bits(chip, FM801_REC_SRC, 7, val);
1158} 1158}
1159 1159
1160static DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0); 1160static const DECLARE_TLV_DB_SCALE(db_scale_dsp, -3450, 150, 0);
1161 1161
1162#define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls) 1162#define FM801_CONTROLS ARRAY_SIZE(snd_fm801_controls)
1163 1163
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index dbacba6177db..60d7b05a204a 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,5 +1,14 @@
1snd-hda-intel-objs := hda_intel.o 1snd-hda-intel-objs := hda_intel.o
2snd-hda-codec-objs := hda_codec.o hda_generic.o patch_realtek.o patch_cmedia.o patch_analog.o patch_sigmatel.o patch_si3054.o patch_atihdmi.o 2snd-hda-codec-objs := hda_codec.o \
3 hda_generic.o \
4 patch_realtek.o \
5 patch_cmedia.o \
6 patch_analog.o \
7 patch_sigmatel.o \
8 patch_si3054.o \
9 patch_atihdmi.o \
10 patch_conexant.o \
11 patch_via.o
3ifdef CONFIG_PROC_FS 12ifdef CONFIG_PROC_FS
4snd-hda-codec-objs += hda_proc.o 13snd-hda-codec-objs += hda_proc.o
5endif 14endif
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index 18bbc87e376f..8f34fb447983 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -52,6 +52,7 @@ struct hda_vendor_id {
52static struct hda_vendor_id hda_vendor_ids[] = { 52static struct hda_vendor_id hda_vendor_ids[] = {
53 { 0x10ec, "Realtek" }, 53 { 0x10ec, "Realtek" },
54 { 0x1057, "Motorola" }, 54 { 0x1057, "Motorola" },
55 { 0x1106, "VIA" },
55 { 0x11d4, "Analog Devices" }, 56 { 0x11d4, "Analog Devices" },
56 { 0x13f6, "C-Media" }, 57 { 0x13f6, "C-Media" },
57 { 0x14f1, "Conexant" }, 58 { 0x14f1, "Conexant" },
@@ -262,7 +263,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
262 unsol->queue[wp] = res; 263 unsol->queue[wp] = res;
263 unsol->queue[wp + 1] = res_ex; 264 unsol->queue[wp + 1] = res_ex;
264 265
265 queue_work(unsol->workq, &unsol->work); 266 schedule_work(&unsol->work);
266 267
267 return 0; 268 return 0;
268} 269}
@@ -309,12 +310,6 @@ static int init_unsol_queue(struct hda_bus *bus)
309 snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n"); 310 snd_printk(KERN_ERR "hda_codec: can't allocate unsolicited queue\n");
310 return -ENOMEM; 311 return -ENOMEM;
311 } 312 }
312 unsol->workq = create_singlethread_workqueue("hda_codec");
313 if (! unsol->workq) {
314 snd_printk(KERN_ERR "hda_codec: can't create workqueue\n");
315 kfree(unsol);
316 return -ENOMEM;
317 }
318 INIT_WORK(&unsol->work, process_unsol_events); 313 INIT_WORK(&unsol->work, process_unsol_events);
319 unsol->bus = bus; 314 unsol->bus = bus;
320 bus->unsol = unsol; 315 bus->unsol = unsol;
@@ -333,7 +328,7 @@ static int snd_hda_bus_free(struct hda_bus *bus)
333 if (! bus) 328 if (! bus)
334 return 0; 329 return 0;
335 if (bus->unsol) { 330 if (bus->unsol) {
336 destroy_workqueue(bus->unsol->workq); 331 flush_scheduled_work();
337 kfree(bus->unsol); 332 kfree(bus->unsol);
338 } 333 }
339 list_for_each_safe(p, n, &bus->codec_list) { 334 list_for_each_safe(p, n, &bus->codec_list) {
@@ -1714,6 +1709,8 @@ EXPORT_SYMBOL(snd_hda_build_pcms);
1714/** 1709/**
1715 * snd_hda_check_board_config - compare the current codec with the config table 1710 * snd_hda_check_board_config - compare the current codec with the config table
1716 * @codec: the HDA codec 1711 * @codec: the HDA codec
1712 * @num_configs: number of config enums
1713 * @models: array of model name strings
1717 * @tbl: configuration table, terminated by null entries 1714 * @tbl: configuration table, terminated by null entries
1718 * 1715 *
1719 * Compares the modelname or PCI subsystem id of the current codec with the 1716 * Compares the modelname or PCI subsystem id of the current codec with the
@@ -1722,33 +1719,44 @@ EXPORT_SYMBOL(snd_hda_build_pcms);
1722 * 1719 *
1723 * If no entries are matching, the function returns a negative value. 1720 * If no entries are matching, the function returns a negative value.
1724 */ 1721 */
1725int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl) 1722int snd_hda_check_board_config(struct hda_codec *codec,
1726{ 1723 int num_configs, const char **models,
1727 const struct hda_board_config *c; 1724 const struct snd_pci_quirk *tbl)
1728 1725{
1729 if (codec->bus->modelname) { 1726 if (codec->bus->modelname && models) {
1730 for (c = tbl; c->modelname || c->pci_subvendor; c++) { 1727 int i;
1731 if (c->modelname && 1728 for (i = 0; i < num_configs; i++) {
1732 ! strcmp(codec->bus->modelname, c->modelname)) { 1729 if (models[i] &&
1733 snd_printd(KERN_INFO "hda_codec: model '%s' is selected\n", c->modelname); 1730 !strcmp(codec->bus->modelname, models[i])) {
1734 return c->config; 1731 snd_printd(KERN_INFO "hda_codec: model '%s' is "
1732 "selected\n", models[i]);
1733 return i;
1735 } 1734 }
1736 } 1735 }
1737 } 1736 }
1738 1737
1739 if (codec->bus->pci) { 1738 if (!codec->bus->pci || !tbl)
1740 u16 subsystem_vendor, subsystem_device; 1739 return -1;
1741 pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); 1740
1742 pci_read_config_word(codec->bus->pci, PCI_SUBSYSTEM_ID, &subsystem_device); 1741 tbl = snd_pci_quirk_lookup(codec->bus->pci, tbl);
1743 for (c = tbl; c->modelname || c->pci_subvendor; c++) { 1742 if (!tbl)
1744 if (c->pci_subvendor == subsystem_vendor && 1743 return -1;
1745 (! c->pci_subdevice /* all match */|| 1744 if (tbl->value >= 0 && tbl->value < num_configs) {
1746 (c->pci_subdevice == subsystem_device))) { 1745#ifdef CONFIG_SND_DEBUG_DETECT
1747 snd_printdd(KERN_INFO "hda_codec: PCI %x:%x, codec config %d is selected\n", 1746 char tmp[10];
1748 subsystem_vendor, subsystem_device, c->config); 1747 const char *model = NULL;
1749 return c->config; 1748 if (models)
1750 } 1749 model = models[tbl->value];
1750 if (!model) {
1751 sprintf(tmp, "#%d", tbl->value);
1752 model = tmp;
1751 } 1753 }
1754 snd_printdd(KERN_INFO "hda_codec: model '%s' is selected "
1755 "for config %x:%x (%s)\n",
1756 model, tbl->subvendor, tbl->subdevice,
1757 (tbl->name ? tbl->name : "Unknown device"));
1758#endif
1759 return tbl->value;
1752 } 1760 }
1753 return -1; 1761 return -1;
1754} 1762}
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 1a7e82104bb9..b9a8e238b0a8 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -199,7 +199,7 @@ enum { SDI0, SDI1, SDI2, SDI3, SDO0, SDO1, SDO2, SDO3 };
199 199
200/* STATESTS int mask: SD2,SD1,SD0 */ 200/* STATESTS int mask: SD2,SD1,SD0 */
201#define STATESTS_INT_MASK 0x07 201#define STATESTS_INT_MASK 0x07
202#define AZX_MAX_CODECS 4 202#define AZX_MAX_CODECS 3
203 203
204/* SD_CTL bits */ 204/* SD_CTL bits */
205#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */ 205#define SD_CTL_STREAM_RESET 0x01 /* stream reset bit */
@@ -1285,7 +1285,7 @@ static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
1285 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops); 1285 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
1286 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, 1286 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1287 snd_dma_pci_data(chip->pci), 1287 snd_dma_pci_data(chip->pci),
1288 1024 * 64, 1024 * 128); 1288 1024 * 64, 1024 * 1024);
1289 chip->pcm[pcm_dev] = pcm; 1289 chip->pcm[pcm_dev] = pcm;
1290 if (chip->pcm_devs < pcm_dev + 1) 1290 if (chip->pcm_devs < pcm_dev + 1)
1291 chip->pcm_devs = pcm_dev + 1; 1291 chip->pcm_devs = pcm_dev + 1;
@@ -1391,6 +1391,7 @@ static int azx_acquire_irq(struct azx *chip, int do_disconnect)
1391 return -1; 1391 return -1;
1392 } 1392 }
1393 chip->irq = chip->pci->irq; 1393 chip->irq = chip->pci->irq;
1394 pci_intx(chip->pci, !chip->msi);
1394 return 0; 1395 return 0;
1395} 1396}
1396 1397
@@ -1502,6 +1503,31 @@ static int azx_dev_free(struct snd_device *device)
1502} 1503}
1503 1504
1504/* 1505/*
1506 * white/black-listing for position_fix
1507 */
1508static const struct snd_pci_quirk position_fix_list[] __devinitdata = {
1509 SND_PCI_QUIRK(0x1028, 0x01cc, "Dell D820", POS_FIX_NONE),
1510 {}
1511};
1512
1513static int __devinit check_position_fix(struct azx *chip, int fix)
1514{
1515 const struct snd_pci_quirk *q;
1516
1517 if (fix == POS_FIX_AUTO) {
1518 q = snd_pci_quirk_lookup(chip->pci, position_fix_list);
1519 if (q) {
1520 snd_printdd(KERN_INFO
1521 "hda_intel: position_fix set to %d "
1522 "for device %04x:%04x\n",
1523 q->value, q->subvendor, q->subdevice);
1524 return q->value;
1525 }
1526 }
1527 return fix;
1528}
1529
1530/*
1505 * constructor 1531 * constructor
1506 */ 1532 */
1507static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci, 1533static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
@@ -1535,7 +1561,8 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
1535 chip->driver_type = driver_type; 1561 chip->driver_type = driver_type;
1536 chip->msi = enable_msi; 1562 chip->msi = enable_msi;
1537 1563
1538 chip->position_fix = position_fix; 1564 chip->position_fix = check_position_fix(chip, position_fix);
1565
1539 chip->single_cmd = single_cmd; 1566 chip->single_cmd = single_cmd;
1540 1567
1541#if BITS_PER_LONG != 64 1568#if BITS_PER_LONG != 64
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 9ca1baf860bd..39718d6cdadd 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -173,14 +173,9 @@ static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
173/* 173/*
174 * Misc 174 * Misc
175 */ 175 */
176struct hda_board_config { 176int snd_hda_check_board_config(struct hda_codec *codec, int num_configs,
177 const char *modelname; 177 const char **modelnames,
178 int config; 178 const struct snd_pci_quirk *pci_list);
179 unsigned short pci_subvendor;
180 unsigned short pci_subdevice;
181};
182
183int snd_hda_check_board_config(struct hda_codec *codec, const struct hda_board_config *tbl);
184int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew); 179int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew);
185 180
186/* 181/*
@@ -204,7 +199,6 @@ struct hda_bus_unsolicited {
204 unsigned int rp, wp; 199 unsigned int rp, wp;
205 200
206 /* workqueue */ 201 /* workqueue */
207 struct workqueue_struct *workq;
208 struct work_struct work; 202 struct work_struct work;
209 struct hda_bus *bus; 203 struct hda_bus *bus;
210}; 204};
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
index 0b668793face..9f9e9ae44a9d 100644
--- a/sound/pci/hda/hda_patch.h
+++ b/sound/pci/hda/hda_patch.h
@@ -14,6 +14,10 @@ extern struct hda_codec_preset snd_hda_preset_sigmatel[];
14extern struct hda_codec_preset snd_hda_preset_si3054[]; 14extern struct hda_codec_preset snd_hda_preset_si3054[];
15/* ATI HDMI codecs */ 15/* ATI HDMI codecs */
16extern struct hda_codec_preset snd_hda_preset_atihdmi[]; 16extern struct hda_codec_preset snd_hda_preset_atihdmi[];
17/* Conexant audio codec */
18extern struct hda_codec_preset snd_hda_preset_conexant[];
19/* VIA codecs */
20extern struct hda_codec_preset snd_hda_preset_via[];
17 21
18static const struct hda_codec_preset *hda_preset_tables[] = { 22static const struct hda_codec_preset *hda_preset_tables[] = {
19 snd_hda_preset_realtek, 23 snd_hda_preset_realtek,
@@ -22,5 +26,7 @@ static const struct hda_codec_preset *hda_preset_tables[] = {
22 snd_hda_preset_sigmatel, 26 snd_hda_preset_sigmatel,
23 snd_hda_preset_si3054, 27 snd_hda_preset_si3054,
24 snd_hda_preset_atihdmi, 28 snd_hda_preset_atihdmi,
29 snd_hda_preset_conexant,
30 snd_hda_preset_via,
25 NULL 31 NULL
26}; 32};
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index 076365bc10e9..38977bce70e2 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -782,54 +782,63 @@ static struct hda_channel_mode ad1986a_modes[3] = {
782 782
783/* eapd initialization */ 783/* eapd initialization */
784static struct hda_verb ad1986a_eapd_init_verbs[] = { 784static struct hda_verb ad1986a_eapd_init_verbs[] = {
785 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00}, 785 {0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
786 {} 786 {}
787}; 787};
788 788
789/* Ultra initialization */
790static struct hda_verb ad1986a_ultra_init[] = {
791 /* eapd initialization */
792 { 0x1b, AC_VERB_SET_EAPD_BTLENABLE, 0x00 },
793 /* CLFE -> Mic in */
794 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x2 },
795 { 0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
796 { 0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
797 { } /* end */
798};
799
789/* models */ 800/* models */
790enum { AD1986A_6STACK, AD1986A_3STACK, AD1986A_LAPTOP, AD1986A_LAPTOP_EAPD }; 801enum {
791 802 AD1986A_6STACK,
792static struct hda_board_config ad1986a_cfg_tbl[] = { 803 AD1986A_3STACK,
793 { .modelname = "6stack", .config = AD1986A_6STACK }, 804 AD1986A_LAPTOP,
794 { .modelname = "3stack", .config = AD1986A_3STACK }, 805 AD1986A_LAPTOP_EAPD,
795 { .pci_subvendor = 0x10de, .pci_subdevice = 0xcb84, 806 AD1986A_ULTRA,
796 .config = AD1986A_3STACK }, /* ASUS A8N-VM CSM */ 807 AD1986A_MODELS
797 { .pci_subvendor = 0x1043, .pci_subdevice = 0x817f, 808};
798 .config = AD1986A_3STACK }, /* ASUS P5P-L2 */ 809
799 { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b3, 810static const char *ad1986a_models[AD1986A_MODELS] = {
800 .config = AD1986A_3STACK }, /* ASUS P5RD2-VM / P5GPL-X SE */ 811 [AD1986A_6STACK] = "6stack",
801 { .pci_subvendor = 0x1043, .pci_subdevice = 0x81cb, 812 [AD1986A_3STACK] = "3stack",
802 .config = AD1986A_3STACK }, /* ASUS M2NPV-VM */ 813 [AD1986A_LAPTOP] = "laptop",
803 { .modelname = "laptop", .config = AD1986A_LAPTOP }, 814 [AD1986A_LAPTOP_EAPD] = "laptop-eapd",
804 { .pci_subvendor = 0x144d, .pci_subdevice = 0xc01e, 815 [AD1986A_ULTRA] = "ultra",
805 .config = AD1986A_LAPTOP }, /* FSC V2060 */ 816};
806 { .pci_subvendor = 0x17c0, .pci_subdevice = 0x2017, 817
807 .config = AD1986A_LAPTOP }, /* Samsung M50 */ 818static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
808 { .pci_subvendor = 0x1043, .pci_subdevice = 0x818f, 819 SND_PCI_QUIRK(0x103c, 0x30af, "HP B2800", AD1986A_LAPTOP_EAPD),
809 .config = AD1986A_LAPTOP }, /* ASUS P5GV-MX */ 820 SND_PCI_QUIRK(0x10de, 0xcb84, "ASUS A8N-VM", AD1986A_3STACK),
810 { .modelname = "laptop-eapd", .config = AD1986A_LAPTOP_EAPD }, 821 SND_PCI_QUIRK(0x1043, 0x1153, "ASUS M9", AD1986A_LAPTOP_EAPD),
811 { .pci_subvendor = 0x144d, .pci_subdevice = 0xc023, 822 SND_PCI_QUIRK(0x1043, 0x1213, "ASUS A6J", AD1986A_LAPTOP_EAPD),
812 .config = AD1986A_LAPTOP_EAPD }, /* Samsung X60 Chane */ 823 SND_PCI_QUIRK(0x1043, 0x11f7, "ASUS U5A", AD1986A_LAPTOP_EAPD),
813 { .pci_subvendor = 0x144d, .pci_subdevice = 0xc024, 824 SND_PCI_QUIRK(0x1043, 0x1263, "ASUS U5F", AD1986A_LAPTOP_EAPD),
814 .config = AD1986A_LAPTOP_EAPD }, /* Samsung R65-T2300 Charis */ 825 SND_PCI_QUIRK(0x1043, 0x1297, "ASUS Z62F", AD1986A_LAPTOP_EAPD),
815 { .pci_subvendor = 0x144d, .pci_subdevice = 0xc026, 826 SND_PCI_QUIRK(0x1043, 0x12b3, "ASUS V1j", AD1986A_LAPTOP_EAPD),
816 .config = AD1986A_LAPTOP_EAPD }, /* Samsung X11-T2300 Culesa */ 827 SND_PCI_QUIRK(0x1043, 0x1302, "ASUS W3j", AD1986A_LAPTOP_EAPD),
817 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1153, 828 SND_PCI_QUIRK(0x1043, 0x817f, "ASUS P5", AD1986A_3STACK),
818 .config = AD1986A_LAPTOP_EAPD }, /* ASUS M9 */ 829 SND_PCI_QUIRK(0x1043, 0x818f, "ASUS P5", AD1986A_LAPTOP),
819 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1213, 830 SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS P5", AD1986A_3STACK),
820 .config = AD1986A_LAPTOP_EAPD }, /* ASUS A6J */ 831 SND_PCI_QUIRK(0x1043, 0x81cb, "ASUS M2N", AD1986A_3STACK),
821 { .pci_subvendor = 0x1043, .pci_subdevice = 0x11f7, 832 SND_PCI_QUIRK(0x1043, 0x8234, "ASUS M2N", AD1986A_3STACK),
822 .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5A */ 833 SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
823 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1263, 834 SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_LAPTOP_EAPD),
824 .config = AD1986A_LAPTOP_EAPD }, /* ASUS U5F */ 835 SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_LAPTOP_EAPD),
825 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1297, 836 SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_LAPTOP_EAPD),
826 .config = AD1986A_LAPTOP_EAPD }, /* ASUS Z62F */ 837 SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
827 { .pci_subvendor = 0x1043, .pci_subdevice = 0x12b3, 838 SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
828 .config = AD1986A_LAPTOP_EAPD }, /* ASUS V1j */ 839 SND_PCI_QUIRK(0x17aa, 0x1017, "Lenovo A60", AD1986A_3STACK),
829 { .pci_subvendor = 0x103c, .pci_subdevice = 0x30af, 840 SND_PCI_QUIRK(0x17aa, 0x2066, "Lenovo N100", AD1986A_LAPTOP_EAPD),
830 .config = AD1986A_LAPTOP_EAPD }, /* HP Compaq Presario B2800 */ 841 SND_PCI_QUIRK(0x17c0, 0x2017, "Samsung M50", AD1986A_LAPTOP),
831 { .pci_subvendor = 0x17aa, .pci_subdevice = 0x2066,
832 .config = AD1986A_LAPTOP_EAPD }, /* Lenovo 3000 N100-07684JU */
833 {} 842 {}
834}; 843};
835 844
@@ -861,7 +870,9 @@ static int patch_ad1986a(struct hda_codec *codec)
861 codec->patch_ops = ad198x_patch_ops; 870 codec->patch_ops = ad198x_patch_ops;
862 871
863 /* override some parameters */ 872 /* override some parameters */
864 board_config = snd_hda_check_board_config(codec, ad1986a_cfg_tbl); 873 board_config = snd_hda_check_board_config(codec, AD1986A_MODELS,
874 ad1986a_models,
875 ad1986a_cfg_tbl);
865 switch (board_config) { 876 switch (board_config) {
866 case AD1986A_3STACK: 877 case AD1986A_3STACK:
867 spec->num_mixers = 2; 878 spec->num_mixers = 2;
@@ -891,6 +902,15 @@ static int patch_ad1986a(struct hda_codec *codec)
891 spec->multiout.dig_out_nid = 0; 902 spec->multiout.dig_out_nid = 0;
892 spec->input_mux = &ad1986a_laptop_eapd_capture_source; 903 spec->input_mux = &ad1986a_laptop_eapd_capture_source;
893 break; 904 break;
905 case AD1986A_ULTRA:
906 spec->mixers[0] = ad1986a_laptop_eapd_mixers;
907 spec->num_init_verbs = 2;
908 spec->init_verbs[1] = ad1986a_ultra_init;
909 spec->multiout.max_channels = 2;
910 spec->multiout.num_dacs = 1;
911 spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
912 spec->multiout.dig_out_nid = 0;
913 break;
894 } 914 }
895 915
896 return 0; 916 return 0;
@@ -1391,20 +1411,27 @@ static struct hda_input_mux ad1981_thinkpad_capture_source = {
1391}; 1411};
1392 1412
1393/* models */ 1413/* models */
1394enum { AD1981_BASIC, AD1981_HP, AD1981_THINKPAD }; 1414enum {
1415 AD1981_BASIC,
1416 AD1981_HP,
1417 AD1981_THINKPAD,
1418 AD1981_MODELS
1419};
1420
1421static const char *ad1981_models[AD1981_MODELS] = {
1422 [AD1981_HP] = "hp",
1423 [AD1981_THINKPAD] = "thinkpad",
1424 [AD1981_BASIC] = "basic",
1425};
1395 1426
1396static struct hda_board_config ad1981_cfg_tbl[] = { 1427static struct snd_pci_quirk ad1981_cfg_tbl[] = {
1397 { .modelname = "hp", .config = AD1981_HP },
1398 /* All HP models */ 1428 /* All HP models */
1399 { .pci_subvendor = 0x103c, .config = AD1981_HP }, 1429 SND_PCI_QUIRK(0x103c, 0, "HP nx", AD1981_HP),
1400 { .pci_subvendor = 0x30b0, .pci_subdevice = 0x103c, 1430 /* HP nx6320 (reversed SSID, H/W bug) */
1401 .config = AD1981_HP }, /* HP nx6320 (reversed SSID, H/W bug) */ 1431 SND_PCI_QUIRK(0x30b0, 0x103c, "HP nx6320", AD1981_HP),
1402 { .modelname = "thinkpad", .config = AD1981_THINKPAD },
1403 /* Lenovo Thinkpad T60/X60/Z6xx */ 1432 /* Lenovo Thinkpad T60/X60/Z6xx */
1404 { .pci_subvendor = 0x17aa, .config = AD1981_THINKPAD }, 1433 SND_PCI_QUIRK(0x17aa, 0, "Lenovo Thinkpad", AD1981_THINKPAD),
1405 { .pci_subvendor = 0x1014, .pci_subdevice = 0x0597, 1434 SND_PCI_QUIRK(0x1014, 0x0597, "Lenovo Z60", AD1981_THINKPAD),
1406 .config = AD1981_THINKPAD }, /* Z60m/t */
1407 { .modelname = "basic", .config = AD1981_BASIC },
1408 {} 1435 {}
1409}; 1436};
1410 1437
@@ -1437,7 +1464,9 @@ static int patch_ad1981(struct hda_codec *codec)
1437 codec->patch_ops = ad198x_patch_ops; 1464 codec->patch_ops = ad198x_patch_ops;
1438 1465
1439 /* override some parameters */ 1466 /* override some parameters */
1440 board_config = snd_hda_check_board_config(codec, ad1981_cfg_tbl); 1467 board_config = snd_hda_check_board_config(codec, AD1981_MODELS,
1468 ad1981_models,
1469 ad1981_cfg_tbl);
1441 switch (board_config) { 1470 switch (board_config) {
1442 case AD1981_HP: 1471 case AD1981_HP:
1443 spec->mixers[0] = ad1981_hp_mixers; 1472 spec->mixers[0] = ad1981_hp_mixers;
@@ -2565,15 +2594,14 @@ static int ad1988_auto_init(struct hda_codec *codec)
2565/* 2594/*
2566 */ 2595 */
2567 2596
2568static struct hda_board_config ad1988_cfg_tbl[] = { 2597static const char *ad1988_models[AD1988_MODEL_LAST] = {
2569 { .modelname = "6stack", .config = AD1988_6STACK }, 2598 [AD1988_6STACK] = "6stack",
2570 { .modelname = "6stack-dig", .config = AD1988_6STACK_DIG }, 2599 [AD1988_6STACK_DIG] = "6stack-dig",
2571 { .modelname = "3stack", .config = AD1988_3STACK }, 2600 [AD1988_3STACK] = "3stack",
2572 { .modelname = "3stack-dig", .config = AD1988_3STACK_DIG }, 2601 [AD1988_3STACK_DIG] = "3stack-dig",
2573 { .modelname = "laptop", .config = AD1988_LAPTOP }, 2602 [AD1988_LAPTOP] = "laptop",
2574 { .modelname = "laptop-dig", .config = AD1988_LAPTOP_DIG }, 2603 [AD1988_LAPTOP_DIG] = "laptop-dig",
2575 { .modelname = "auto", .config = AD1988_AUTO }, 2604 [AD1988_AUTO] = "auto",
2576 {}
2577}; 2605};
2578 2606
2579static int patch_ad1988(struct hda_codec *codec) 2607static int patch_ad1988(struct hda_codec *codec)
@@ -2591,8 +2619,9 @@ static int patch_ad1988(struct hda_codec *codec)
2591 if (is_rev2(codec)) 2619 if (is_rev2(codec))
2592 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n"); 2620 snd_printk(KERN_INFO "patch_analog: AD1988A rev.2 is detected, enable workarounds\n");
2593 2621
2594 board_config = snd_hda_check_board_config(codec, ad1988_cfg_tbl); 2622 board_config = snd_hda_check_board_config(codec, AD1988_MODEL_LAST,
2595 if (board_config < 0 || board_config >= AD1988_MODEL_LAST) { 2623 ad1988_models, NULL);
2624 if (board_config < 0) {
2596 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n"); 2625 printk(KERN_INFO "hda_codec: Unknown model for AD1988, trying auto-probe from BIOS...\n");
2597 board_config = AD1988_AUTO; 2626 board_config = AD1988_AUTO;
2598 } 2627 }
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index d38ce22507ae..5b9d3a31a1ae 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -40,6 +40,7 @@ enum {
40 CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */ 40 CMI_FULL_DIG, /* back 6-jack + front-panel 2-jack + digital I/O */
41 CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */ 41 CMI_ALLOUT, /* back 5-jack + front-panel 2-jack + digital out */
42 CMI_AUTO, /* let driver guess it */ 42 CMI_AUTO, /* let driver guess it */
43 CMI_MODELS
43}; 44};
44 45
45struct cmi_spec { 46struct cmi_spec {
@@ -603,14 +604,17 @@ static void cmi9880_free(struct hda_codec *codec)
603/* 604/*
604 */ 605 */
605 606
606static struct hda_board_config cmi9880_cfg_tbl[] = { 607static const char *cmi9880_models[CMI_MODELS] = {
607 { .modelname = "minimal", .config = CMI_MINIMAL }, 608 [CMI_MINIMAL] = "minimal",
608 { .modelname = "min_fp", .config = CMI_MIN_FP }, 609 [CMI_MIN_FP] = "min_fp",
609 { .modelname = "full", .config = CMI_FULL }, 610 [CMI_FULL] = "full",
610 { .modelname = "full_dig", .config = CMI_FULL_DIG }, 611 [CMI_FULL_DIG] = "full_dig",
611 { .pci_subvendor = 0x1043, .pci_subdevice = 0x813d, .config = CMI_FULL_DIG }, /* ASUS P5AD2 */ 612 [CMI_ALLOUT] = "allout",
612 { .modelname = "allout", .config = CMI_ALLOUT }, 613 [CMI_AUTO] = "auto",
613 { .modelname = "auto", .config = CMI_AUTO }, 614};
615
616static struct snd_pci_quirk cmi9880_cfg_tbl[] = {
617 SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", CMI_FULL_DIG),
614 {} /* terminator */ 618 {} /* terminator */
615}; 619};
616 620
@@ -633,7 +637,9 @@ static int patch_cmi9880(struct hda_codec *codec)
633 return -ENOMEM; 637 return -ENOMEM;
634 638
635 codec->spec = spec; 639 codec->spec = spec;
636 spec->board_config = snd_hda_check_board_config(codec, cmi9880_cfg_tbl); 640 spec->board_config = snd_hda_check_board_config(codec, CMI_MODELS,
641 cmi9880_models,
642 cmi9880_cfg_tbl);
637 if (spec->board_config < 0) { 643 if (spec->board_config < 0) {
638 snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n"); 644 snd_printdd(KERN_INFO "hda_codec: Unknown model for CMI9880\n");
639 spec->board_config = CMI_AUTO; /* try everything */ 645 spec->board_config = CMI_AUTO; /* try everything */
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
new file mode 100644
index 000000000000..73f4668238c6
--- /dev/null
+++ b/sound/pci/hda/patch_conexant.c
@@ -0,0 +1,1311 @@
1/*
2 * HD audio interface patch for Conexant HDA audio codec
3 *
4 * Copyright (c) 2006 Pototskiy Akex <alex.pototskiy@gmail.com>
5 * Takashi Iwai <tiwai@suse.de>
6 * Tobin Davis <tdavis@dsl-only.net>
7 *
8 * This driver is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This driver is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23#include <sound/driver.h>
24#include <linux/init.h>
25#include <linux/delay.h>
26#include <linux/slab.h>
27#include <linux/pci.h>
28#include <sound/core.h>
29#include "hda_codec.h"
30#include "hda_local.h"
31
32#define CXT_PIN_DIR_IN 0x00
33#define CXT_PIN_DIR_OUT 0x01
34#define CXT_PIN_DIR_INOUT 0x02
35#define CXT_PIN_DIR_IN_NOMICBIAS 0x03
36#define CXT_PIN_DIR_INOUT_NOMICBIAS 0x04
37
38#define CONEXANT_HP_EVENT 0x37
39#define CONEXANT_MIC_EVENT 0x38
40
41
42
43struct conexant_spec {
44
45 struct snd_kcontrol_new *mixers[5];
46 int num_mixers;
47
48 const struct hda_verb *init_verbs[5]; /* initialization verbs
49 * don't forget NULL
50 * termination!
51 */
52 unsigned int num_init_verbs;
53
54 /* playback */
55 struct hda_multi_out multiout; /* playback set-up
56 * max_channels, dacs must be set
57 * dig_out_nid and hp_nid are optional
58 */
59 unsigned int cur_eapd;
60 unsigned int need_dac_fix;
61
62 /* capture */
63 unsigned int num_adc_nids;
64 hda_nid_t *adc_nids;
65 hda_nid_t dig_in_nid; /* digital-in NID; optional */
66
67 /* capture source */
68 const struct hda_input_mux *input_mux;
69 hda_nid_t *capsrc_nids;
70 unsigned int cur_mux[3];
71
72 /* channel model */
73 const struct hda_channel_mode *channel_mode;
74 int num_channel_mode;
75
76 /* PCM information */
77 struct hda_pcm pcm_rec[2]; /* used in build_pcms() */
78
79 struct mutex amp_mutex; /* PCM volume/mute control mutex */
80 unsigned int spdif_route;
81
82 /* dynamic controls, init_verbs and input_mux */
83 struct auto_pin_cfg autocfg;
84 unsigned int num_kctl_alloc, num_kctl_used;
85 struct snd_kcontrol_new *kctl_alloc;
86 struct hda_input_mux private_imux;
87 hda_nid_t private_dac_nids[4];
88
89};
90
91static int conexant_playback_pcm_open(struct hda_pcm_stream *hinfo,
92 struct hda_codec *codec,
93 struct snd_pcm_substream *substream)
94{
95 struct conexant_spec *spec = codec->spec;
96 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
97}
98
99static int conexant_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
100 struct hda_codec *codec,
101 unsigned int stream_tag,
102 unsigned int format,
103 struct snd_pcm_substream *substream)
104{
105 struct conexant_spec *spec = codec->spec;
106 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
107 stream_tag,
108 format, substream);
109}
110
111static int conexant_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
112 struct hda_codec *codec,
113 struct snd_pcm_substream *substream)
114{
115 struct conexant_spec *spec = codec->spec;
116 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
117}
118
119/*
120 * Digital out
121 */
122static int conexant_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
123 struct hda_codec *codec,
124 struct snd_pcm_substream *substream)
125{
126 struct conexant_spec *spec = codec->spec;
127 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
128}
129
130static int conexant_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
131 struct hda_codec *codec,
132 struct snd_pcm_substream *substream)
133{
134 struct conexant_spec *spec = codec->spec;
135 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
136}
137
138/*
139 * Analog capture
140 */
141static int conexant_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
142 struct hda_codec *codec,
143 unsigned int stream_tag,
144 unsigned int format,
145 struct snd_pcm_substream *substream)
146{
147 struct conexant_spec *spec = codec->spec;
148 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
149 stream_tag, 0, format);
150 return 0;
151}
152
153static int conexant_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
154 struct hda_codec *codec,
155 struct snd_pcm_substream *substream)
156{
157 struct conexant_spec *spec = codec->spec;
158 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
159 0, 0, 0);
160 return 0;
161}
162
163
164
165static struct hda_pcm_stream conexant_pcm_analog_playback = {
166 .substreams = 1,
167 .channels_min = 2,
168 .channels_max = 2,
169 .nid = 0, /* fill later */
170 .ops = {
171 .open = conexant_playback_pcm_open,
172 .prepare = conexant_playback_pcm_prepare,
173 .cleanup = conexant_playback_pcm_cleanup
174 },
175};
176
177static struct hda_pcm_stream conexant_pcm_analog_capture = {
178 .substreams = 1,
179 .channels_min = 2,
180 .channels_max = 2,
181 .nid = 0, /* fill later */
182 .ops = {
183 .prepare = conexant_capture_pcm_prepare,
184 .cleanup = conexant_capture_pcm_cleanup
185 },
186};
187
188
189static struct hda_pcm_stream conexant_pcm_digital_playback = {
190 .substreams = 1,
191 .channels_min = 2,
192 .channels_max = 2,
193 .nid = 0, /* fill later */
194 .ops = {
195 .open = conexant_dig_playback_pcm_open,
196 .close = conexant_dig_playback_pcm_close
197 },
198};
199
200static struct hda_pcm_stream conexant_pcm_digital_capture = {
201 .substreams = 1,
202 .channels_min = 2,
203 .channels_max = 2,
204 /* NID is set in alc_build_pcms */
205};
206
207static int conexant_build_pcms(struct hda_codec *codec)
208{
209 struct conexant_spec *spec = codec->spec;
210 struct hda_pcm *info = spec->pcm_rec;
211
212 codec->num_pcms = 1;
213 codec->pcm_info = info;
214
215 info->name = "CONEXANT Analog";
216 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = conexant_pcm_analog_playback;
217 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
218 spec->multiout.max_channels;
219 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
220 spec->multiout.dac_nids[0];
221 info->stream[SNDRV_PCM_STREAM_CAPTURE] = conexant_pcm_analog_capture;
222 info->stream[SNDRV_PCM_STREAM_CAPTURE].substreams = spec->num_adc_nids;
223 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
224
225 if (spec->multiout.dig_out_nid) {
226 info++;
227 codec->num_pcms++;
228 info->name = "Conexant Digital";
229 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
230 conexant_pcm_digital_playback;
231 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
232 spec->multiout.dig_out_nid;
233 if (spec->dig_in_nid) {
234 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
235 conexant_pcm_digital_capture;
236 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
237 spec->dig_in_nid;
238 }
239 }
240
241 return 0;
242}
243
244static int conexant_mux_enum_info(struct snd_kcontrol *kcontrol,
245 struct snd_ctl_elem_info *uinfo)
246{
247 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
248 struct conexant_spec *spec = codec->spec;
249
250 return snd_hda_input_mux_info(spec->input_mux, uinfo);
251}
252
253static int conexant_mux_enum_get(struct snd_kcontrol *kcontrol,
254 struct snd_ctl_elem_value *ucontrol)
255{
256 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
257 struct conexant_spec *spec = codec->spec;
258 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
259
260 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
261 return 0;
262}
263
264static int conexant_mux_enum_put(struct snd_kcontrol *kcontrol,
265 struct snd_ctl_elem_value *ucontrol)
266{
267 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
268 struct conexant_spec *spec = codec->spec;
269 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
270
271 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
272 spec->capsrc_nids[adc_idx],
273 &spec->cur_mux[adc_idx]);
274}
275
276static int conexant_init(struct hda_codec *codec)
277{
278 struct conexant_spec *spec = codec->spec;
279 int i;
280
281 for (i = 0; i < spec->num_init_verbs; i++)
282 snd_hda_sequence_write(codec, spec->init_verbs[i]);
283 return 0;
284}
285
286static void conexant_free(struct hda_codec *codec)
287{
288 struct conexant_spec *spec = codec->spec;
289 unsigned int i;
290
291 if (spec->kctl_alloc) {
292 for (i = 0; i < spec->num_kctl_used; i++)
293 kfree(spec->kctl_alloc[i].name);
294 kfree(spec->kctl_alloc);
295 }
296
297 kfree(codec->spec);
298}
299
300#ifdef CONFIG_PM
301static int conexant_resume(struct hda_codec *codec)
302{
303 struct conexant_spec *spec = codec->spec;
304 int i;
305
306 codec->patch_ops.init(codec);
307 for (i = 0; i < spec->num_mixers; i++)
308 snd_hda_resume_ctls(codec, spec->mixers[i]);
309 if (spec->multiout.dig_out_nid)
310 snd_hda_resume_spdif_out(codec);
311 if (spec->dig_in_nid)
312 snd_hda_resume_spdif_in(codec);
313 return 0;
314}
315#endif
316
317static int conexant_build_controls(struct hda_codec *codec)
318{
319 struct conexant_spec *spec = codec->spec;
320 unsigned int i;
321 int err;
322
323 for (i = 0; i < spec->num_mixers; i++) {
324 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
325 if (err < 0)
326 return err;
327 }
328 if (spec->multiout.dig_out_nid) {
329 err = snd_hda_create_spdif_out_ctls(codec,
330 spec->multiout.dig_out_nid);
331 if (err < 0)
332 return err;
333 }
334 if (spec->dig_in_nid) {
335 err = snd_hda_create_spdif_in_ctls(codec,spec->dig_in_nid);
336 if (err < 0)
337 return err;
338 }
339 return 0;
340}
341
342static struct hda_codec_ops conexant_patch_ops = {
343 .build_controls = conexant_build_controls,
344 .build_pcms = conexant_build_pcms,
345 .init = conexant_init,
346 .free = conexant_free,
347#ifdef CONFIG_PM
348 .resume = conexant_resume,
349#endif
350};
351
352/*
353 * EAPD control
354 * the private value = nid | (invert << 8)
355 */
356
357static int conexant_eapd_info(struct snd_kcontrol *kcontrol,
358 struct snd_ctl_elem_info *uinfo)
359{
360 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
361 uinfo->count = 1;
362 uinfo->value.integer.min = 0;
363 uinfo->value.integer.max = 1;
364 return 0;
365}
366
367static int conexant_eapd_get(struct snd_kcontrol *kcontrol,
368 struct snd_ctl_elem_value *ucontrol)
369{
370 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
371 struct conexant_spec *spec = codec->spec;
372 int invert = (kcontrol->private_value >> 8) & 1;
373 if (invert)
374 ucontrol->value.integer.value[0] = !spec->cur_eapd;
375 else
376 ucontrol->value.integer.value[0] = spec->cur_eapd;
377 return 0;
378}
379
380static int conexant_eapd_put(struct snd_kcontrol *kcontrol,
381 struct snd_ctl_elem_value *ucontrol)
382{
383 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
384 struct conexant_spec *spec = codec->spec;
385 int invert = (kcontrol->private_value >> 8) & 1;
386 hda_nid_t nid = kcontrol->private_value & 0xff;
387 unsigned int eapd;
388 eapd = ucontrol->value.integer.value[0];
389 if (invert)
390 eapd = !eapd;
391 if (eapd == spec->cur_eapd && !codec->in_resume)
392 return 0;
393 spec->cur_eapd = eapd;
394 snd_hda_codec_write(codec, nid,
395 0, AC_VERB_SET_EAPD_BTLENABLE,
396 eapd ? 0x02 : 0x00);
397 return 1;
398}
399
400/* controls for test mode */
401#ifdef CONFIG_SND_DEBUG
402
403static int conexant_ch_mode_info(struct snd_kcontrol *kcontrol,
404 struct snd_ctl_elem_info *uinfo)
405{
406 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
407 struct conexant_spec *spec = codec->spec;
408 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
409 spec->num_channel_mode);
410}
411
412static int conexant_ch_mode_get(struct snd_kcontrol *kcontrol,
413 struct snd_ctl_elem_value *ucontrol)
414{
415 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
416 struct conexant_spec *spec = codec->spec;
417 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
418 spec->num_channel_mode,
419 spec->multiout.max_channels);
420}
421
422static int conexant_ch_mode_put(struct snd_kcontrol *kcontrol,
423 struct snd_ctl_elem_value *ucontrol)
424{
425 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
426 struct conexant_spec *spec = codec->spec;
427 int err = snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
428 spec->num_channel_mode,
429 &spec->multiout.max_channels);
430 if (err >= 0 && spec->need_dac_fix)
431 spec->multiout.num_dacs = spec->multiout.max_channels / 2;
432 return err;
433}
434
435#define CXT_PIN_MODE(xname, nid, dir) \
436 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
437 .info = conexant_ch_mode_info, \
438 .get = conexant_ch_mode_get, \
439 .put = conexant_ch_mode_put, \
440 .private_value = nid | (dir<<16) }
441
442static int cxt_gpio_data_info(struct snd_kcontrol *kcontrol,
443 struct snd_ctl_elem_info *uinfo)
444{
445 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
446 uinfo->count = 1;
447 uinfo->value.integer.min = 0;
448 uinfo->value.integer.max = 1;
449 return 0;
450}
451
452static int cxt_gpio_data_get(struct snd_kcontrol *kcontrol,
453 struct snd_ctl_elem_value *ucontrol)
454{
455 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
456 hda_nid_t nid = kcontrol->private_value & 0xffff;
457 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
458 long *valp = ucontrol->value.integer.value;
459 unsigned int val = snd_hda_codec_read(codec, nid, 0,
460 AC_VERB_GET_GPIO_DATA, 0x00);
461
462 *valp = (val & mask) != 0;
463 return 0;
464}
465
466static int cxt_gpio_data_put(struct snd_kcontrol *kcontrol,
467 struct snd_ctl_elem_value *ucontrol)
468{
469 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
470 hda_nid_t nid = kcontrol->private_value & 0xffff;
471 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
472 long val = *ucontrol->value.integer.value;
473 unsigned int gpio_data = snd_hda_codec_read(codec, nid, 0,
474 AC_VERB_GET_GPIO_DATA,
475 0x00);
476 unsigned int old_data = gpio_data;
477
478 /* Set/unset the masked GPIO bit(s) as needed */
479 if (val == 0)
480 gpio_data &= ~mask;
481 else
482 gpio_data |= mask;
483 if (gpio_data == old_data && !codec->in_resume)
484 return 0;
485 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_GPIO_DATA, gpio_data);
486 return 1;
487}
488
489#define CXT_GPIO_DATA_SWITCH(xname, nid, mask) \
490 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
491 .info = cxt_gpio_data_info, \
492 .get = cxt_gpio_data_get, \
493 .put = cxt_gpio_data_put, \
494 .private_value = nid | (mask<<16) }
495
496static int cxt_spdif_ctrl_info(struct snd_kcontrol *kcontrol,
497 struct snd_ctl_elem_info *uinfo)
498{
499 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
500 uinfo->count = 1;
501 uinfo->value.integer.min = 0;
502 uinfo->value.integer.max = 1;
503 return 0;
504}
505
506static int cxt_spdif_ctrl_get(struct snd_kcontrol *kcontrol,
507 struct snd_ctl_elem_value *ucontrol)
508{
509 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
510 hda_nid_t nid = kcontrol->private_value & 0xffff;
511 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
512 long *valp = ucontrol->value.integer.value;
513 unsigned int val = snd_hda_codec_read(codec, nid, 0,
514 AC_VERB_GET_DIGI_CONVERT, 0x00);
515
516 *valp = (val & mask) != 0;
517 return 0;
518}
519
520static int cxt_spdif_ctrl_put(struct snd_kcontrol *kcontrol,
521 struct snd_ctl_elem_value *ucontrol)
522{
523 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
524 hda_nid_t nid = kcontrol->private_value & 0xffff;
525 unsigned char mask = (kcontrol->private_value >> 16) & 0xff;
526 long val = *ucontrol->value.integer.value;
527 unsigned int ctrl_data = snd_hda_codec_read(codec, nid, 0,
528 AC_VERB_GET_DIGI_CONVERT,
529 0x00);
530 unsigned int old_data = ctrl_data;
531
532 /* Set/unset the masked control bit(s) as needed */
533 if (val == 0)
534 ctrl_data &= ~mask;
535 else
536 ctrl_data |= mask;
537 if (ctrl_data == old_data && !codec->in_resume)
538 return 0;
539 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_DIGI_CONVERT_1,
540 ctrl_data);
541 return 1;
542}
543
544#define CXT_SPDIF_CTRL_SWITCH(xname, nid, mask) \
545 { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = 0, \
546 .info = cxt_spdif_ctrl_info, \
547 .get = cxt_spdif_ctrl_get, \
548 .put = cxt_spdif_ctrl_put, \
549 .private_value = nid | (mask<<16) }
550
551#endif /* CONFIG_SND_DEBUG */
552
553/* Conexant 5045 specific */
554
555static hda_nid_t cxt5045_dac_nids[1] = { 0x19 };
556static hda_nid_t cxt5045_adc_nids[1] = { 0x1a };
557static hda_nid_t cxt5045_capsrc_nids[1] = { 0x1a };
558#define CXT5045_SPDIF_OUT 0x13
559
560static struct hda_channel_mode cxt5045_modes[1] = {
561 { 2, NULL },
562};
563
564static struct hda_input_mux cxt5045_capture_source = {
565 .num_items = 2,
566 .items = {
567 { "ExtMic", 0x1 },
568 { "LineIn", 0x2 },
569 }
570};
571
572/* turn on/off EAPD (+ mute HP) as a master switch */
573static int cxt5045_hp_master_sw_put(struct snd_kcontrol *kcontrol,
574 struct snd_ctl_elem_value *ucontrol)
575{
576 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
577 struct conexant_spec *spec = codec->spec;
578
579 if (!conexant_eapd_put(kcontrol, ucontrol))
580 return 0;
581
582 /* toggle HP mute appropriately */
583 snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0,
584 0x80, spec->cur_eapd ? 0 : 0x80);
585 snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0,
586 0x80, spec->cur_eapd ? 0 : 0x80);
587 return 1;
588}
589
590/* bind volumes of both NID 0x10 and 0x11 */
591static int cxt5045_hp_master_vol_put(struct snd_kcontrol *kcontrol,
592 struct snd_ctl_elem_value *ucontrol)
593{
594 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
595 long *valp = ucontrol->value.integer.value;
596 int change;
597
598 change = snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0,
599 0x7f, valp[0] & 0x7f);
600 change |= snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0,
601 0x7f, valp[1] & 0x7f);
602 snd_hda_codec_amp_update(codec, 0x11, 0, HDA_OUTPUT, 0,
603 0x7f, valp[0] & 0x7f);
604 snd_hda_codec_amp_update(codec, 0x11, 1, HDA_OUTPUT, 0,
605 0x7f, valp[1] & 0x7f);
606 return change;
607}
608
609
610/* mute internal speaker if HP is plugged */
611static void cxt5045_hp_automute(struct hda_codec *codec)
612{
613 unsigned int present;
614
615 present = snd_hda_codec_read(codec, 0x11, 0,
616 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
617 snd_hda_codec_amp_update(codec, 0x10, 0, HDA_OUTPUT, 0,
618 0x80, present ? 0x80 : 0);
619 snd_hda_codec_amp_update(codec, 0x10, 1, HDA_OUTPUT, 0,
620 0x80, present ? 0x80 : 0);
621}
622
623/* unsolicited event for HP jack sensing */
624static void cxt5045_hp_unsol_event(struct hda_codec *codec,
625 unsigned int res)
626{
627 res >>= 26;
628 switch (res) {
629 case CONEXANT_HP_EVENT:
630 cxt5045_hp_automute(codec);
631 break;
632 }
633}
634
635static struct snd_kcontrol_new cxt5045_mixers[] = {
636 {
637 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
638 .name = "Capture Source",
639 .info = conexant_mux_enum_info,
640 .get = conexant_mux_enum_get,
641 .put = conexant_mux_enum_put
642 },
643 HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x17, 0x02, HDA_INPUT),
644 HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x17, 0x02, HDA_INPUT),
645 HDA_CODEC_VOLUME("Capture Volume", 0x1a, 0x02, HDA_INPUT),
646 HDA_CODEC_MUTE("Capture Switch", 0x1a, 0x02, HDA_INPUT),
647 {
648 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
649 .name = "Master Playback Volume",
650 .info = snd_hda_mixer_amp_volume_info,
651 .get = snd_hda_mixer_amp_volume_get,
652 .put = cxt5045_hp_master_vol_put,
653 .private_value = HDA_COMPOSE_AMP_VAL(0x11, 3, 0, HDA_OUTPUT),
654 },
655 {
656 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
657 .name = "Master Playback Switch",
658 .info = conexant_eapd_info,
659 .get = conexant_eapd_get,
660 .put = cxt5045_hp_master_sw_put,
661 .private_value = 0x11,
662 },
663
664 {}
665};
666
667static struct hda_verb cxt5045_init_verbs[] = {
668 /* Line in, Mic */
669 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
670 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
671 /* HP, Amp */
672 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
673 {0x1A, AC_VERB_SET_CONNECT_SEL,0x01},
674 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
675 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
676 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
677 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
678 /* Record selector: Front mic */
679 {0x14, AC_VERB_SET_CONNECT_SEL,0x03},
680 {0x17, AC_VERB_SET_AMP_GAIN_MUTE,
681 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
682 /* SPDIF route: PCM */
683 { 0x13, AC_VERB_SET_CONNECT_SEL, 0x0 },
684 /* pin sensing on HP and Mic jacks */
685 {0x11, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
686 /* EAPD */
687 {0x10, AC_VERB_SET_EAPD_BTLENABLE, 0x0 }, /* default on */
688 { } /* end */
689};
690
691#ifdef CONFIG_SND_DEBUG
692/* Test configuration for debugging, modelled after the ALC260 test
693 * configuration.
694 */
695static struct hda_input_mux cxt5045_test_capture_source = {
696 .num_items = 5,
697 .items = {
698 { "MIXER", 0x0 },
699 { "MIC1 pin", 0x1 },
700 { "LINE1 pin", 0x2 },
701 { "HP-OUT pin", 0x3 },
702 { "CD pin", 0x4 },
703 },
704};
705
706static struct snd_kcontrol_new cxt5045_test_mixer[] = {
707
708 /* Output controls */
709 HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x19, 0x00, HDA_OUTPUT),
710 HDA_CODEC_MUTE("OutAmp-1 Switch", 0x19,0x00, HDA_OUTPUT),
711 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x10, 0x0, HDA_OUTPUT),
712 HDA_CODEC_MUTE("Speaker Playback Switch", 0x10, 0x0, HDA_OUTPUT),
713
714 /* Modes for retasking pin widgets */
715 CXT_PIN_MODE("HP-OUT pin mode", 0x11, CXT_PIN_DIR_INOUT),
716 CXT_PIN_MODE("LINE1 pin mode", 0x12, CXT_PIN_DIR_INOUT),
717
718 /* Loopback mixer controls */
719 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x17, 0x01, HDA_INPUT),
720 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x17, 0x01, HDA_INPUT),
721 HDA_CODEC_VOLUME("LINE loopback Playback Volume", 0x17, 0x02, HDA_INPUT),
722 HDA_CODEC_MUTE("LINE loopback Playback Switch", 0x17, 0x02, HDA_INPUT),
723 HDA_CODEC_VOLUME("HP-OUT loopback Playback Volume", 0x17, 0x03, HDA_INPUT),
724 HDA_CODEC_MUTE("HP-OUT loopback Playback Switch", 0x17, 0x03, HDA_INPUT),
725 HDA_CODEC_VOLUME("CD Playback Volume", 0x17, 0x04, HDA_INPUT),
726 HDA_CODEC_MUTE("CD Playback Switch", 0x17, 0x04, HDA_INPUT),
727
728 /* Controls for GPIO pins, assuming they exist and are configured as outputs */
729 CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
730#if 0 /* limit this to one GPIO pin for now */
731 CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
732 CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
733 CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
734#endif
735 CXT_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x13, 0x01),
736
737 HDA_CODEC_VOLUME("Capture Volume", 0x17, 0x0, HDA_OUTPUT),
738 HDA_CODEC_MUTE("Capture Switch", 0x17, 0x0, HDA_OUTPUT),
739 {
740 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
741 .name = "Input Source",
742 .info = conexant_mux_enum_info,
743 .get = conexant_mux_enum_get,
744 .put = conexant_mux_enum_put,
745 },
746
747 { } /* end */
748};
749
750static struct hda_verb cxt5045_test_init_verbs[] = {
751 /* Enable all GPIOs as outputs with an initial value of 0 */
752 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
753 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
754 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
755
756 /* Enable retasking pins as output, initially without power amp */
757 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
758 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
759
760 /* Disable digital (SPDIF) pins initially, but users can enable
761 * them via a mixer switch. In the case of SPDIF-out, this initverb
762 * payload also sets the generation to 0, output to be in "consumer"
763 * PCM format, copyright asserted, no pre-emphasis and no validity
764 * control.
765 */
766 {0x13, AC_VERB_SET_DIGI_CONVERT_1, 0},
767
768 /* Start with output sum widgets muted and their output gains at min */
769 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
770 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
771
772 /* Unmute retasking pin widget output buffers since the default
773 * state appears to be output. As the pin mode is changed by the
774 * user the pin mode control will take care of enabling the pin's
775 * input/output buffers as needed.
776 */
777 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
778 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
779
780 /* Mute capture amp left and right */
781 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
782
783 /* Set ADC connection select to match default mixer setting (mic1
784 * pin)
785 */
786 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x00},
787
788 /* Mute all inputs to mixer widget (even unconnected ones) */
789 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* Mixer pin */
790 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* Mic1 pin */
791 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* Line pin */
792 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* HP pin */
793 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
794
795 { }
796};
797#endif
798
799
800/* initialize jack-sensing, too */
801static int cxt5045_init(struct hda_codec *codec)
802{
803 conexant_init(codec);
804 cxt5045_hp_automute(codec);
805 return 0;
806}
807
808
809enum {
810 CXT5045_LAPTOP, /* Laptops w/ EAPD support */
811#ifdef CONFIG_SND_DEBUG
812 CXT5045_TEST,
813#endif
814 CXT5045_MODELS
815};
816
817static const char *cxt5045_models[CXT5045_MODELS] = {
818 [CXT5045_LAPTOP] = "laptop",
819#ifdef CONFIG_SND_DEBUG
820 [CXT5045_TEST] = "test",
821#endif
822};
823
824static struct snd_pci_quirk cxt5045_cfg_tbl[] = {
825 SND_PCI_QUIRK(0x103c, 0x30b7, "HP DV6000Z", CXT5045_LAPTOP),
826 {}
827};
828
829static int patch_cxt5045(struct hda_codec *codec)
830{
831 struct conexant_spec *spec;
832 int board_config;
833
834 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
835 if (!spec)
836 return -ENOMEM;
837 mutex_init(&spec->amp_mutex);
838 codec->spec = spec;
839
840 spec->multiout.max_channels = 2;
841 spec->multiout.num_dacs = ARRAY_SIZE(cxt5045_dac_nids);
842 spec->multiout.dac_nids = cxt5045_dac_nids;
843 spec->multiout.dig_out_nid = CXT5045_SPDIF_OUT;
844 spec->num_adc_nids = 1;
845 spec->adc_nids = cxt5045_adc_nids;
846 spec->capsrc_nids = cxt5045_capsrc_nids;
847 spec->input_mux = &cxt5045_capture_source;
848 spec->num_mixers = 1;
849 spec->mixers[0] = cxt5045_mixers;
850 spec->num_init_verbs = 1;
851 spec->init_verbs[0] = cxt5045_init_verbs;
852 spec->spdif_route = 0;
853 spec->num_channel_mode = ARRAY_SIZE(cxt5045_modes),
854 spec->channel_mode = cxt5045_modes,
855
856
857 codec->patch_ops = conexant_patch_ops;
858 codec->patch_ops.unsol_event = cxt5045_hp_unsol_event;
859
860 board_config = snd_hda_check_board_config(codec, CXT5045_MODELS,
861 cxt5045_models,
862 cxt5045_cfg_tbl);
863 switch (board_config) {
864 case CXT5045_LAPTOP:
865 spec->input_mux = &cxt5045_capture_source;
866 spec->num_init_verbs = 2;
867 spec->init_verbs[1] = cxt5045_init_verbs;
868 spec->mixers[0] = cxt5045_mixers;
869 codec->patch_ops.init = cxt5045_init;
870 break;
871#ifdef CONFIG_SND_DEBUG
872 case CXT5045_TEST:
873 spec->input_mux = &cxt5045_test_capture_source;
874 spec->mixers[0] = cxt5045_test_mixer;
875 spec->init_verbs[0] = cxt5045_test_init_verbs;
876#endif
877 }
878 return 0;
879}
880
881
882/* Conexant 5047 specific */
883
884static hda_nid_t cxt5047_dac_nids[1] = { 0x10 };
885static hda_nid_t cxt5047_adc_nids[1] = { 0x12 };
886static hda_nid_t cxt5047_capsrc_nids[1] = { 0x1a };
887#define CXT5047_SPDIF_OUT 0x11
888
889static struct hda_channel_mode cxt5047_modes[1] = {
890 { 2, NULL },
891};
892
893static struct hda_input_mux cxt5047_capture_source = {
894 .num_items = 2,
895 .items = {
896 { "ExtMic", 0x1 },
897 { "IntMic", 0x2 },
898 }
899};
900
901static struct hda_input_mux cxt5047_hp_capture_source = {
902 .num_items = 1,
903 .items = {
904 { "ExtMic", 0x1 },
905 }
906};
907
908/* turn on/off EAPD (+ mute HP) as a master switch */
909static int cxt5047_hp_master_sw_put(struct snd_kcontrol *kcontrol,
910 struct snd_ctl_elem_value *ucontrol)
911{
912 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
913 struct conexant_spec *spec = codec->spec;
914
915 if (!conexant_eapd_put(kcontrol, ucontrol))
916 return 0;
917
918 /* toggle HP mute appropriately */
919 snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0,
920 0x80, spec->cur_eapd ? 0 : 0x80);
921 snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0,
922 0x80, spec->cur_eapd ? 0 : 0x80);
923 return 1;
924}
925
926#if 0
927/* bind volumes of both NID 0x13 and 0x1d */
928static int cxt5047_hp_master_vol_put(struct snd_kcontrol *kcontrol,
929 struct snd_ctl_elem_value *ucontrol)
930{
931 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
932 long *valp = ucontrol->value.integer.value;
933 int change;
934
935 change = snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0,
936 0x7f, valp[0] & 0x7f);
937 change |= snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0,
938 0x7f, valp[1] & 0x7f);
939 snd_hda_codec_amp_update(codec, 0x13, 0, HDA_OUTPUT, 0,
940 0x7f, valp[0] & 0x7f);
941 snd_hda_codec_amp_update(codec, 0x13, 1, HDA_OUTPUT, 0,
942 0x7f, valp[1] & 0x7f);
943 return change;
944}
945#endif
946
947/* mute internal speaker if HP is plugged */
948static void cxt5047_hp_automute(struct hda_codec *codec)
949{
950 unsigned int present;
951
952 present = snd_hda_codec_read(codec, 0x13, 0,
953 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
954 snd_hda_codec_amp_update(codec, 0x1c, 0, HDA_OUTPUT, 0,
955 0x80, present ? 0x80 : 0);
956 snd_hda_codec_amp_update(codec, 0x1c, 1, HDA_OUTPUT, 0,
957 0x80, present ? 0x80 : 0);
958}
959
960/* toggle input of built-in and mic jack appropriately */
961static void cxt5047_hp_automic(struct hda_codec *codec)
962{
963 static struct hda_verb mic_jack_on[] = {
964 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
965 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
966 {}
967 };
968 static struct hda_verb mic_jack_off[] = {
969 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080},
970 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb000},
971 {}
972 };
973 unsigned int present;
974
975 present = snd_hda_codec_read(codec, 0x08, 0,
976 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
977 if (present)
978 snd_hda_sequence_write(codec, mic_jack_on);
979 else
980 snd_hda_sequence_write(codec, mic_jack_off);
981}
982
983/* unsolicited event for HP jack sensing */
984static void cxt5047_hp_unsol_event(struct hda_codec *codec,
985 unsigned int res)
986{
987 res >>= 26;
988 switch (res) {
989 case CONEXANT_HP_EVENT:
990 cxt5047_hp_automute(codec);
991 break;
992 case CONEXANT_MIC_EVENT:
993 cxt5047_hp_automic(codec);
994 break;
995 }
996}
997
998static struct snd_kcontrol_new cxt5047_mixers[] = {
999 {
1000 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1001 .name = "Capture Source",
1002 .info = conexant_mux_enum_info,
1003 .get = conexant_mux_enum_get,
1004 .put = conexant_mux_enum_put
1005 },
1006 HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
1007 HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19, 0x02, HDA_INPUT),
1008 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
1009 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
1010 HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
1011 HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
1012 HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1013 {
1014 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1015 .name = "Master Playback Switch",
1016 .info = conexant_eapd_info,
1017 .get = conexant_eapd_get,
1018 .put = cxt5047_hp_master_sw_put,
1019 .private_value = 0x13,
1020 },
1021
1022 {}
1023};
1024
1025static struct snd_kcontrol_new cxt5047_hp_mixers[] = {
1026 {
1027 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1028 .name = "Capture Source",
1029 .info = conexant_mux_enum_info,
1030 .get = conexant_mux_enum_get,
1031 .put = conexant_mux_enum_put
1032 },
1033 HDA_CODEC_VOLUME("Mic Bypass Capture Volume", 0x19, 0x02, HDA_INPUT),
1034 HDA_CODEC_MUTE("Mic Bypass Capture Switch", 0x19,0x02,HDA_INPUT),
1035 HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x03, HDA_INPUT),
1036 HDA_CODEC_MUTE("Capture Switch", 0x12, 0x03, HDA_INPUT),
1037 HDA_CODEC_VOLUME("PCM Volume", 0x10, 0x00, HDA_OUTPUT),
1038 HDA_CODEC_MUTE("PCM Switch", 0x10, 0x00, HDA_OUTPUT),
1039 HDA_CODEC_VOLUME("Master Playback Volume", 0x13, 0x00, HDA_OUTPUT),
1040 {
1041 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1042 .name = "Master Playback Switch",
1043 .info = conexant_eapd_info,
1044 .get = conexant_eapd_get,
1045 .put = cxt5047_hp_master_sw_put,
1046 .private_value = 0x13,
1047 },
1048 { } /* end */
1049};
1050
1051static struct hda_verb cxt5047_init_verbs[] = {
1052 /* Line in, Mic, Built-in Mic */
1053 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
1054 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
1055 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN|AC_PINCTL_VREF_50 },
1056 /* HP, Amp */
1057 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
1058 {0x1A, AC_VERB_SET_CONNECT_SEL,0x03},
1059 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
1060 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x00},
1061 {0x1A, AC_VERB_SET_AMP_GAIN_MUTE,
1062 AC_AMP_SET_OUTPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x03},
1063 /* Record selector: Front mic */
1064 {0x12, AC_VERB_SET_CONNECT_SEL,0x03},
1065 {0x19, AC_VERB_SET_AMP_GAIN_MUTE,
1066 AC_AMP_SET_INPUT|AC_AMP_SET_RIGHT|AC_AMP_SET_LEFT|0x17},
1067 /* SPDIF route: PCM */
1068 { 0x18, AC_VERB_SET_CONNECT_SEL, 0x0 },
1069 { } /* end */
1070};
1071
1072/* configuration for Toshiba Laptops */
1073static struct hda_verb cxt5047_toshiba_init_verbs[] = {
1074 {0x13, AC_VERB_SET_EAPD_BTLENABLE, 0x0 }, /* default on */
1075 /* pin sensing on HP and Mic jacks */
1076 {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
1077 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
1078 {}
1079};
1080
1081/* configuration for HP Laptops */
1082static struct hda_verb cxt5047_hp_init_verbs[] = {
1083 /* pin sensing on HP and Mic jacks */
1084 {0x13, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_HP_EVENT},
1085 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | CONEXANT_MIC_EVENT},
1086 {}
1087};
1088
1089/* Test configuration for debugging, modelled after the ALC260 test
1090 * configuration.
1091 */
1092#ifdef CONFIG_SND_DEBUG
1093static struct hda_input_mux cxt5047_test_capture_source = {
1094 .num_items = 5,
1095 .items = {
1096 { "MIXER", 0x0 },
1097 { "LINE1 pin", 0x1 },
1098 { "MIC1 pin", 0x2 },
1099 { "MIC2 pin", 0x3 },
1100 { "CD pin", 0x4 },
1101 },
1102};
1103
1104static struct snd_kcontrol_new cxt5047_test_mixer[] = {
1105
1106 /* Output only controls */
1107 HDA_CODEC_VOLUME("OutAmp-1 Volume", 0x10, 0x00, HDA_OUTPUT),
1108 HDA_CODEC_MUTE("OutAmp-1 Switch", 0x10,0x00, HDA_OUTPUT),
1109 HDA_CODEC_VOLUME("OutAmp-2 Volume", 0x1c, 0x00, HDA_OUTPUT),
1110 HDA_CODEC_MUTE("OutAmp-2 Switch", 0x1c, 0x00, HDA_OUTPUT),
1111 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x1d, 0x0, HDA_OUTPUT),
1112 HDA_CODEC_MUTE("Speaker Playback Switch", 0x1d, 0x0, HDA_OUTPUT),
1113 HDA_CODEC_VOLUME("HeadPhone Playback Volume", 0x13, 0x0, HDA_OUTPUT),
1114 HDA_CODEC_MUTE("HeadPhone Playback Switch", 0x13, 0x0, HDA_OUTPUT),
1115
1116 /* Modes for retasking pin widgets */
1117 CXT_PIN_MODE("LINE1 pin mode", 0x14, CXT_PIN_DIR_INOUT),
1118 CXT_PIN_MODE("MIC1 pin mode", 0x15, CXT_PIN_DIR_INOUT),
1119
1120 /* Loopback mixer controls */
1121 HDA_CODEC_VOLUME("MIC1 Playback Volume", 0x19, 0x02, HDA_INPUT),
1122 HDA_CODEC_MUTE("MIC1 Playback Switch", 0x19, 0x02, HDA_INPUT),
1123 HDA_CODEC_VOLUME("MIC2 Playback Volume", 0x19, 0x03, HDA_INPUT),
1124 HDA_CODEC_MUTE("MIC2 Playback Switch", 0x19, 0x03, HDA_INPUT),
1125 HDA_CODEC_VOLUME("LINE Playback Volume", 0x19, 0x01, HDA_INPUT),
1126 HDA_CODEC_MUTE("LINE Playback Switch", 0x19, 0x01, HDA_INPUT),
1127 HDA_CODEC_VOLUME("CD Playback Volume", 0x19, 0x04, HDA_INPUT),
1128 HDA_CODEC_MUTE("CD Playback Switch", 0x19, 0x04, HDA_INPUT),
1129
1130#if 0
1131 /* Controls for GPIO pins, assuming they exist and are configured as outputs */
1132 CXT_GPIO_DATA_SWITCH("GPIO pin 0", 0x01, 0x01),
1133 CXT_GPIO_DATA_SWITCH("GPIO pin 1", 0x01, 0x02),
1134 CXT_GPIO_DATA_SWITCH("GPIO pin 2", 0x01, 0x04),
1135 CXT_GPIO_DATA_SWITCH("GPIO pin 3", 0x01, 0x08),
1136#endif
1137 CXT_SPDIF_CTRL_SWITCH("SPDIF Playback Switch", 0x18, 0x01),
1138
1139 HDA_CODEC_VOLUME("Capture Volume", 0x19, 0x0, HDA_OUTPUT),
1140 HDA_CODEC_MUTE("Capture Switch", 0x19, 0x0, HDA_OUTPUT),
1141 {
1142 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1143 .name = "Input Source",
1144 .info = conexant_mux_enum_info,
1145 .get = conexant_mux_enum_get,
1146 .put = conexant_mux_enum_put,
1147 },
1148
1149 { } /* end */
1150};
1151
1152static struct hda_verb cxt5047_test_init_verbs[] = {
1153 /* Enable all GPIOs as outputs with an initial value of 0 */
1154 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x0f},
1155 {0x01, AC_VERB_SET_GPIO_DATA, 0x00},
1156 {0x01, AC_VERB_SET_GPIO_MASK, 0x0f},
1157
1158 /* Enable retasking pins as output, initially without power amp */
1159 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1160 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1161 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1162
1163 /* Disable digital (SPDIF) pins initially, but users can enable
1164 * them via a mixer switch. In the case of SPDIF-out, this initverb
1165 * payload also sets the generation to 0, output to be in "consumer"
1166 * PCM format, copyright asserted, no pre-emphasis and no validity
1167 * control.
1168 */
1169 {0x18, AC_VERB_SET_DIGI_CONVERT_1, 0},
1170
1171 /* Ensure mic1, mic2, line1 pin widgets take input from the
1172 * OUT1 sum bus when acting as an output.
1173 */
1174 {0x1a, AC_VERB_SET_CONNECT_SEL, 0},
1175 {0x1b, AC_VERB_SET_CONNECT_SEL, 0},
1176
1177 /* Start with output sum widgets muted and their output gains at min */
1178 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1179 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
1180
1181 /* Unmute retasking pin widget output buffers since the default
1182 * state appears to be output. As the pin mode is changed by the
1183 * user the pin mode control will take care of enabling the pin's
1184 * input/output buffers as needed.
1185 */
1186 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1187 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1188 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1189
1190 /* Mute capture amp left and right */
1191 {0x12, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
1192
1193 /* Set ADC connection select to match default mixer setting (mic1
1194 * pin)
1195 */
1196 {0x12, AC_VERB_SET_CONNECT_SEL, 0x00},
1197
1198 /* Mute all inputs to mixer widget (even unconnected ones) */
1199 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, /* mic1 pin */
1200 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)}, /* mic2 pin */
1201 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)}, /* line1 pin */
1202 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)}, /* line2 pin */
1203 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)}, /* CD pin */
1204 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(5)}, /* Beep-gen pin */
1205 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(6)}, /* Line-out pin */
1206 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(7)}, /* HP-pin pin */
1207
1208 { }
1209};
1210#endif
1211
1212
1213/* initialize jack-sensing, too */
1214static int cxt5047_hp_init(struct hda_codec *codec)
1215{
1216 conexant_init(codec);
1217 cxt5047_hp_automute(codec);
1218 cxt5047_hp_automic(codec);
1219 return 0;
1220}
1221
1222
1223enum {
1224 CXT5047_LAPTOP, /* Laptops w/o EAPD support */
1225 CXT5047_LAPTOP_HP, /* Some HP laptops */
1226 CXT5047_LAPTOP_EAPD, /* Laptops with EAPD support */
1227#ifdef CONFIG_SND_DEBUG
1228 CXT5047_TEST,
1229#endif
1230 CXT5047_MODELS
1231};
1232
1233static const char *cxt5047_models[CXT5047_MODELS] = {
1234 [CXT5047_LAPTOP] = "laptop",
1235 [CXT5047_LAPTOP_HP] = "laptop-hp",
1236 [CXT5047_LAPTOP_EAPD] = "laptop-eapd",
1237#ifdef CONFIG_SND_DEBUG
1238 [CXT5047_TEST] = "test",
1239#endif
1240};
1241
1242static struct snd_pci_quirk cxt5047_cfg_tbl[] = {
1243 SND_PCI_QUIRK(0x103c, 0x30a0, "HP DV1000", CXT5047_LAPTOP),
1244 SND_PCI_QUIRK(0x103c, 0x30b2, "HP DV2000T/DV3000T", CXT5047_LAPTOP),
1245 SND_PCI_QUIRK(0x103c, 0x30a5, "HP DV5200T/DV8000T", CXT5047_LAPTOP_HP),
1246 SND_PCI_QUIRK(0x1179, 0xff31, "Toshiba P100", CXT5047_LAPTOP_EAPD),
1247 {}
1248};
1249
1250static int patch_cxt5047(struct hda_codec *codec)
1251{
1252 struct conexant_spec *spec;
1253 int board_config;
1254
1255 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1256 if (!spec)
1257 return -ENOMEM;
1258 mutex_init(&spec->amp_mutex);
1259 codec->spec = spec;
1260
1261 spec->multiout.max_channels = 2;
1262 spec->multiout.num_dacs = ARRAY_SIZE(cxt5047_dac_nids);
1263 spec->multiout.dac_nids = cxt5047_dac_nids;
1264 spec->multiout.dig_out_nid = CXT5047_SPDIF_OUT;
1265 spec->num_adc_nids = 1;
1266 spec->adc_nids = cxt5047_adc_nids;
1267 spec->capsrc_nids = cxt5047_capsrc_nids;
1268 spec->input_mux = &cxt5047_capture_source;
1269 spec->num_mixers = 1;
1270 spec->mixers[0] = cxt5047_mixers;
1271 spec->num_init_verbs = 1;
1272 spec->init_verbs[0] = cxt5047_init_verbs;
1273 spec->spdif_route = 0;
1274 spec->num_channel_mode = ARRAY_SIZE(cxt5047_modes),
1275 spec->channel_mode = cxt5047_modes,
1276
1277 codec->patch_ops = conexant_patch_ops;
1278 codec->patch_ops.unsol_event = cxt5047_hp_unsol_event;
1279
1280 board_config = snd_hda_check_board_config(codec, CXT5047_MODELS,
1281 cxt5047_models,
1282 cxt5047_cfg_tbl);
1283 switch (board_config) {
1284 case CXT5047_LAPTOP:
1285 break;
1286 case CXT5047_LAPTOP_HP:
1287 spec->input_mux = &cxt5047_hp_capture_source;
1288 spec->num_init_verbs = 2;
1289 spec->init_verbs[1] = cxt5047_hp_init_verbs;
1290 spec->mixers[0] = cxt5047_hp_mixers;
1291 codec->patch_ops.init = cxt5047_hp_init;
1292 break;
1293 case CXT5047_LAPTOP_EAPD:
1294 spec->num_init_verbs = 2;
1295 spec->init_verbs[1] = cxt5047_toshiba_init_verbs;
1296 break;
1297#ifdef CONFIG_SND_DEBUG
1298 case CXT5047_TEST:
1299 spec->input_mux = &cxt5047_test_capture_source;
1300 spec->mixers[0] = cxt5047_test_mixer;
1301 spec->init_verbs[0] = cxt5047_test_init_verbs;
1302#endif
1303 }
1304 return 0;
1305}
1306
1307struct hda_codec_preset snd_hda_preset_conexant[] = {
1308 { .id = 0x14f15045, .name = "CXT5045", .patch = patch_cxt5045 },
1309 { .id = 0x14f15047, .name = "CXT5047", .patch = patch_cxt5047 },
1310 {} /* terminator */
1311};
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 4e0c3c1b908b..145682b78071 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -32,6 +32,10 @@
32#include "hda_codec.h" 32#include "hda_codec.h"
33#include "hda_local.h" 33#include "hda_local.h"
34 34
35#define ALC880_FRONT_EVENT 0x01
36#define ALC880_DCVOL_EVENT 0x02
37#define ALC880_HP_EVENT 0x04
38#define ALC880_MIC_EVENT 0x08
35 39
36/* ALC880 board config type */ 40/* ALC880 board config type */
37enum { 41enum {
@@ -48,7 +52,10 @@ enum {
48 ALC880_ASUS_DIG, 52 ALC880_ASUS_DIG,
49 ALC880_ASUS_W1V, 53 ALC880_ASUS_W1V,
50 ALC880_ASUS_DIG2, 54 ALC880_ASUS_DIG2,
55 ALC880_FUJITSU,
51 ALC880_UNIWILL_DIG, 56 ALC880_UNIWILL_DIG,
57 ALC880_UNIWILL,
58 ALC880_UNIWILL_P53,
52 ALC880_CLEVO, 59 ALC880_CLEVO,
53 ALC880_TCL_S700, 60 ALC880_TCL_S700,
54 ALC880_LG, 61 ALC880_LG,
@@ -77,8 +84,12 @@ enum {
77/* ALC262 models */ 84/* ALC262 models */
78enum { 85enum {
79 ALC262_BASIC, 86 ALC262_BASIC,
87 ALC262_HIPPO,
88 ALC262_HIPPO_1,
80 ALC262_FUJITSU, 89 ALC262_FUJITSU,
81 ALC262_HP_BPC, 90 ALC262_HP_BPC,
91 ALC262_HP_BPC_D7000_WL,
92 ALC262_HP_BPC_D7000_WF,
82 ALC262_BENQ_ED8, 93 ALC262_BENQ_ED8,
83 ALC262_AUTO, 94 ALC262_AUTO,
84 ALC262_MODEL_LAST /* last tag */ 95 ALC262_MODEL_LAST /* last tag */
@@ -91,16 +102,30 @@ enum {
91 ALC861_3ST_DIG, 102 ALC861_3ST_DIG,
92 ALC861_6ST_DIG, 103 ALC861_6ST_DIG,
93 ALC861_UNIWILL_M31, 104 ALC861_UNIWILL_M31,
105 ALC861_TOSHIBA,
106 ALC861_ASUS,
107 ALC861_ASUS_LAPTOP,
94 ALC861_AUTO, 108 ALC861_AUTO,
95 ALC861_MODEL_LAST, 109 ALC861_MODEL_LAST,
96}; 110};
97 111
112/* ALC861-VD models */
113enum {
114 ALC660VD_3ST,
115 ALC861VD_3ST,
116 ALC861VD_3ST_DIG,
117 ALC861VD_6ST_DIG,
118 ALC861VD_AUTO,
119 ALC861VD_MODEL_LAST,
120};
121
98/* ALC882 models */ 122/* ALC882 models */
99enum { 123enum {
100 ALC882_3ST_DIG, 124 ALC882_3ST_DIG,
101 ALC882_6ST_DIG, 125 ALC882_6ST_DIG,
102 ALC882_ARIMA, 126 ALC882_ARIMA,
103 ALC882_AUTO, 127 ALC882_AUTO,
128 ALC885_MACPRO,
104 ALC882_MODEL_LAST, 129 ALC882_MODEL_LAST,
105}; 130};
106 131
@@ -110,8 +135,12 @@ enum {
110 ALC883_3ST_6ch_DIG, 135 ALC883_3ST_6ch_DIG,
111 ALC883_3ST_6ch, 136 ALC883_3ST_6ch,
112 ALC883_6ST_DIG, 137 ALC883_6ST_DIG,
138 ALC883_TARGA_DIG,
139 ALC883_TARGA_2ch_DIG,
113 ALC888_DEMO_BOARD, 140 ALC888_DEMO_BOARD,
114 ALC883_ACER, 141 ALC883_ACER,
142 ALC883_MEDION,
143 ALC883_LAPTOP_EAPD,
115 ALC883_AUTO, 144 ALC883_AUTO,
116 ALC883_MODEL_LAST, 145 ALC883_MODEL_LAST,
117}; 146};
@@ -1015,6 +1044,60 @@ static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
1015 { } /* end */ 1044 { } /* end */
1016}; 1045};
1017 1046
1047/* Uniwill */
1048static struct snd_kcontrol_new alc880_uniwill_mixer[] = {
1049 HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1050 HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
1051 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1052 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
1053 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
1054 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
1055 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
1056 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
1057 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1058 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1059 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
1060 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
1061 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1062 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1063 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1064 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1065 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
1066 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
1067 {
1068 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1069 .name = "Channel Mode",
1070 .info = alc_ch_mode_info,
1071 .get = alc_ch_mode_get,
1072 .put = alc_ch_mode_put,
1073 },
1074 { } /* end */
1075};
1076
1077static struct snd_kcontrol_new alc880_fujitsu_mixer[] = {
1078 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1079 HDA_BIND_MUTE("Headphone Playback Switch", 0x0c, 2, HDA_INPUT),
1080 HDA_CODEC_VOLUME("Speaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1081 HDA_BIND_MUTE("Speaker Playback Switch", 0x0d, 2, HDA_INPUT),
1082 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
1083 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
1084 HDA_CODEC_VOLUME("Ext Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1085 HDA_CODEC_MUTE("Ext Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1086 HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
1087 HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
1088 { } /* end */
1089};
1090
1091static struct snd_kcontrol_new alc880_uniwill_p53_mixer[] = {
1092 HDA_CODEC_VOLUME("HPhone Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
1093 HDA_BIND_MUTE("HPhone Playback Switch", 0x0c, 2, HDA_INPUT),
1094 HDA_CODEC_VOLUME("iSpeaker Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
1095 HDA_BIND_MUTE("iSpeaker Playback Switch", 0x0d, 2, HDA_INPUT),
1096 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
1097 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
1098 { } /* end */
1099};
1100
1018/* 1101/*
1019 * build control elements 1102 * build control elements
1020 */ 1103 */
@@ -1248,6 +1331,159 @@ static struct hda_verb alc880_pin_6stack_init_verbs[] = {
1248 { } 1331 { }
1249}; 1332};
1250 1333
1334/*
1335 * Uniwill pin configuration:
1336 * HP = 0x14, InternalSpeaker = 0x15, mic = 0x18, internal mic = 0x19,
1337 * line = 0x1a
1338 */
1339static struct hda_verb alc880_uniwill_init_verbs[] = {
1340 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1341
1342 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1343 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1344 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1345 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1346 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1347 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1348 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
1349 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1350 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1351 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1352 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1353 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1354 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1355 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1356
1357 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1358 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1359 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1360 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1361 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1362 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1363 /* {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP}, */
1364 /* {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, */
1365 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1366
1367 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
1368 {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
1369
1370 { }
1371};
1372
1373/*
1374* Uniwill P53
1375* HP = 0x14, InternalSpeaker = 0x15, mic = 0x19,
1376 */
1377static struct hda_verb alc880_uniwill_p53_init_verbs[] = {
1378 {0x13, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
1379
1380 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1381 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1382 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1383 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1384 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
1385 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
1386 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1387 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1388 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1389 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1390 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
1391 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
1392
1393 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1394 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1395 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
1396 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1397 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
1398 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
1399
1400 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
1401 {0x21, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_DCVOL_EVENT},
1402
1403 { }
1404};
1405
1406static struct hda_verb alc880_beep_init_verbs[] = {
1407 { 0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5) },
1408 { }
1409};
1410
1411/* toggle speaker-output according to the hp-jack state */
1412static void alc880_uniwill_automute(struct hda_codec *codec)
1413{
1414 unsigned int present;
1415
1416 present = snd_hda_codec_read(codec, 0x14, 0,
1417 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1418 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_OUTPUT, 0,
1419 0x80, present ? 0x80 : 0);
1420 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_OUTPUT, 0,
1421 0x80, present ? 0x80 : 0);
1422 snd_hda_codec_amp_update(codec, 0x16, 0, HDA_OUTPUT, 0,
1423 0x80, present ? 0x80 : 0);
1424 snd_hda_codec_amp_update(codec, 0x16, 1, HDA_OUTPUT, 0,
1425 0x80, present ? 0x80 : 0);
1426
1427 present = snd_hda_codec_read(codec, 0x18, 0,
1428 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1429 snd_hda_codec_write(codec, 0x0b, 0, AC_VERB_SET_AMP_GAIN_MUTE,
1430 0x7000 | (0x01 << 8) | (present ? 0x80 : 0));
1431}
1432
1433static void alc880_uniwill_unsol_event(struct hda_codec *codec,
1434 unsigned int res)
1435{
1436 /* Looks like the unsol event is incompatible with the standard
1437 * definition. 4bit tag is placed at 28 bit!
1438 */
1439 if ((res >> 28) == ALC880_HP_EVENT ||
1440 (res >> 28) == ALC880_MIC_EVENT)
1441 alc880_uniwill_automute(codec);
1442}
1443
1444static void alc880_uniwill_p53_hp_automute(struct hda_codec *codec)
1445{
1446 unsigned int present;
1447
1448 present = snd_hda_codec_read(codec, 0x14, 0,
1449 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
1450
1451 snd_hda_codec_amp_update(codec, 0x15, 0, HDA_INPUT, 0,
1452 0x80, present ? 0x80 : 0);
1453 snd_hda_codec_amp_update(codec, 0x15, 1, HDA_INPUT, 0,
1454 0x80, present ? 0x80 : 0);
1455}
1456
1457static void alc880_uniwill_p53_dcvol_automute(struct hda_codec *codec)
1458{
1459 unsigned int present;
1460
1461 present = snd_hda_codec_read(codec, 0x21, 0,
1462 AC_VERB_GET_VOLUME_KNOB_CONTROL, 0) & 0x7f;
1463
1464 snd_hda_codec_amp_update(codec, 0x0c, 0, HDA_OUTPUT, 0,
1465 0x7f, present);
1466 snd_hda_codec_amp_update(codec, 0x0c, 1, HDA_OUTPUT, 0,
1467 0x7f, present);
1468
1469 snd_hda_codec_amp_update(codec, 0x0d, 0, HDA_OUTPUT, 0,
1470 0x7f, present);
1471 snd_hda_codec_amp_update(codec, 0x0d, 1, HDA_OUTPUT, 0,
1472 0x7f, present);
1473
1474}
1475static void alc880_uniwill_p53_unsol_event(struct hda_codec *codec,
1476 unsigned int res)
1477{
1478 /* Looks like the unsol event is incompatible with the standard
1479 * definition. 4bit tag is placed at 28 bit!
1480 */
1481 if ((res >> 28) == ALC880_HP_EVENT)
1482 alc880_uniwill_p53_hp_automute(codec);
1483 if ((res >> 28) == ALC880_DCVOL_EVENT)
1484 alc880_uniwill_p53_dcvol_automute(codec);
1485}
1486
1251/* FIXME! */ 1487/* FIXME! */
1252/* 1488/*
1253 * F1734 pin configuration: 1489 * F1734 pin configuration:
@@ -2125,159 +2361,112 @@ static struct hda_verb alc880_test_init_verbs[] = {
2125/* 2361/*
2126 */ 2362 */
2127 2363
2128static struct hda_board_config alc880_cfg_tbl[] = { 2364static const char *alc880_models[ALC880_MODEL_LAST] = {
2129 /* Back 3 jack, front 2 jack */ 2365 [ALC880_3ST] = "3stack",
2130 { .modelname = "3stack", .config = ALC880_3ST }, 2366 [ALC880_TCL_S700] = "tcl",
2131 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe200, .config = ALC880_3ST }, 2367 [ALC880_3ST_DIG] = "3stack-digout",
2132 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe201, .config = ALC880_3ST }, 2368 [ALC880_CLEVO] = "clevo",
2133 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe202, .config = ALC880_3ST }, 2369 [ALC880_5ST] = "5stack",
2134 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe203, .config = ALC880_3ST }, 2370 [ALC880_5ST_DIG] = "5stack-digout",
2135 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe204, .config = ALC880_3ST }, 2371 [ALC880_W810] = "w810",
2136 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe205, .config = ALC880_3ST }, 2372 [ALC880_Z71V] = "z71v",
2137 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe206, .config = ALC880_3ST }, 2373 [ALC880_6ST] = "6stack",
2138 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe207, .config = ALC880_3ST }, 2374 [ALC880_6ST_DIG] = "6stack-digout",
2139 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe208, .config = ALC880_3ST }, 2375 [ALC880_ASUS] = "asus",
2140 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe209, .config = ALC880_3ST }, 2376 [ALC880_ASUS_W1V] = "asus-w1v",
2141 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20a, .config = ALC880_3ST }, 2377 [ALC880_ASUS_DIG] = "asus-dig",
2142 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20b, .config = ALC880_3ST }, 2378 [ALC880_ASUS_DIG2] = "asus-dig2",
2143 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20c, .config = ALC880_3ST }, 2379 [ALC880_UNIWILL_DIG] = "uniwill",
2144 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20d, .config = ALC880_3ST }, 2380 [ALC880_UNIWILL_P53] = "uniwill-p53",
2145 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20e, .config = ALC880_3ST }, 2381 [ALC880_FUJITSU] = "fujitsu",
2146 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe20f, .config = ALC880_3ST }, 2382 [ALC880_F1734] = "F1734",
2147 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe210, .config = ALC880_3ST }, 2383 [ALC880_LG] = "lg",
2148 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe211, .config = ALC880_3ST }, 2384 [ALC880_LG_LW] = "lg-lw",
2149 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe212, .config = ALC880_3ST },
2150 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe213, .config = ALC880_3ST },
2151 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe214, .config = ALC880_3ST },
2152 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe234, .config = ALC880_3ST },
2153 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe302, .config = ALC880_3ST },
2154 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe303, .config = ALC880_3ST },
2155 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe304, .config = ALC880_3ST },
2156 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe306, .config = ALC880_3ST },
2157 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe307, .config = ALC880_3ST },
2158 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe404, .config = ALC880_3ST },
2159 { .pci_subvendor = 0x8086, .pci_subdevice = 0xa101, .config = ALC880_3ST },
2160 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3031, .config = ALC880_3ST },
2161 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4036, .config = ALC880_3ST },
2162 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4037, .config = ALC880_3ST },
2163 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4038, .config = ALC880_3ST },
2164 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4040, .config = ALC880_3ST },
2165 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4041, .config = ALC880_3ST },
2166 /* TCL S700 */
2167 { .modelname = "tcl", .config = ALC880_TCL_S700 },
2168 { .pci_subvendor = 0x19db, .pci_subdevice = 0x4188, .config = ALC880_TCL_S700 },
2169
2170 /* Back 3 jack, front 2 jack (Internal add Aux-In) */
2171 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe310, .config = ALC880_3ST },
2172 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81d6, .config = ALC880_3ST },
2173 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81a0, .config = ALC880_3ST },
2174
2175 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack */
2176 { .modelname = "3stack-digout", .config = ALC880_3ST_DIG },
2177 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe308, .config = ALC880_3ST_DIG },
2178 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0070, .config = ALC880_3ST_DIG },
2179
2180 /* Clevo laptops */
2181 { .modelname = "clevo", .config = ALC880_CLEVO },
2182 { .pci_subvendor = 0x1558, .pci_subdevice = 0x0520,
2183 .config = ALC880_CLEVO }, /* Clevo m520G NB */
2184 { .pci_subvendor = 0x1558, .pci_subdevice = 0x0660,
2185 .config = ALC880_CLEVO }, /* Clevo m665n */
2186
2187 /* Back 3 jack plus 1 SPDIF out jack, front 2 jack (Internal add Aux-In)*/
2188 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe305, .config = ALC880_3ST_DIG },
2189 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd402, .config = ALC880_3ST_DIG },
2190 { .pci_subvendor = 0x1025, .pci_subdevice = 0xe309, .config = ALC880_3ST_DIG },
2191
2192 /* Back 5 jack, front 2 jack */
2193 { .modelname = "5stack", .config = ALC880_5ST },
2194 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3033, .config = ALC880_5ST },
2195 { .pci_subvendor = 0x107b, .pci_subdevice = 0x4039, .config = ALC880_5ST },
2196 { .pci_subvendor = 0x107b, .pci_subdevice = 0x3032, .config = ALC880_5ST },
2197 { .pci_subvendor = 0x103c, .pci_subdevice = 0x2a09, .config = ALC880_5ST },
2198 { .pci_subvendor = 0x1043, .pci_subdevice = 0x814e, .config = ALC880_5ST },
2199
2200 /* Back 5 jack plus 1 SPDIF out jack, front 2 jack */
2201 { .modelname = "5stack-digout", .config = ALC880_5ST_DIG },
2202 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe224, .config = ALC880_5ST_DIG },
2203 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe400, .config = ALC880_5ST_DIG },
2204 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe401, .config = ALC880_5ST_DIG },
2205 { .pci_subvendor = 0x8086, .pci_subdevice = 0xe402, .config = ALC880_5ST_DIG },
2206 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd400, .config = ALC880_5ST_DIG },
2207 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd401, .config = ALC880_5ST_DIG },
2208 { .pci_subvendor = 0x8086, .pci_subdevice = 0xa100, .config = ALC880_5ST_DIG },
2209 { .pci_subvendor = 0x1565, .pci_subdevice = 0x8202, .config = ALC880_5ST_DIG },
2210 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa880, .config = ALC880_5ST_DIG },
2211 { .pci_subvendor = 0xa0a0, .pci_subdevice = 0x0560,
2212 .config = ALC880_5ST_DIG }, /* Aopen i915GMm-HFS */
2213 /* { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_5ST_DIG }, */ /* conflict with 6stack */
2214 { .pci_subvendor = 0x1695, .pci_subdevice = 0x400d, .config = ALC880_5ST_DIG },
2215 /* note subvendor = 0 below */
2216 /* { .pci_subvendor = 0x0000, .pci_subdevice = 0x8086, .config = ALC880_5ST_DIG }, */
2217
2218 { .modelname = "w810", .config = ALC880_W810 },
2219 { .pci_subvendor = 0x161f, .pci_subdevice = 0x203d, .config = ALC880_W810 },
2220
2221 { .modelname = "z71v", .config = ALC880_Z71V },
2222 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_Z71V },
2223
2224 { .modelname = "6stack", .config = ALC880_6ST },
2225 { .pci_subvendor = 0x1043, .pci_subdevice = 0x8196, .config = ALC880_6ST }, /* ASUS P5GD1-HVM */
2226 { .pci_subvendor = 0x1043, .pci_subdevice = 0x81b4, .config = ALC880_6ST },
2227 { .pci_subvendor = 0x1019, .pci_subdevice = 0xa884, .config = ALC880_6ST }, /* Acer APFV */
2228 { .pci_subvendor = 0x1458, .pci_subdevice = 0xa102, .config = ALC880_6ST }, /* Gigabyte K8N51 */
2229
2230 { .modelname = "6stack-digout", .config = ALC880_6ST_DIG },
2231 { .pci_subvendor = 0x2668, .pci_subdevice = 0x8086, .config = ALC880_6ST_DIG },
2232 { .pci_subvendor = 0x8086, .pci_subdevice = 0x2668, .config = ALC880_6ST_DIG },
2233 { .pci_subvendor = 0x1462, .pci_subdevice = 0x1150, .config = ALC880_6ST_DIG },
2234 { .pci_subvendor = 0xe803, .pci_subdevice = 0x1019, .config = ALC880_6ST_DIG },
2235 { .pci_subvendor = 0x1039, .pci_subdevice = 0x1234, .config = ALC880_6ST_DIG },
2236 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0077, .config = ALC880_6ST_DIG },
2237 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0078, .config = ALC880_6ST_DIG },
2238 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0087, .config = ALC880_6ST_DIG },
2239 { .pci_subvendor = 0x1297, .pci_subdevice = 0xc790, .config = ALC880_6ST_DIG }, /* Shuttle ST20G5 */
2240 { .pci_subvendor = 0x1509, .pci_subdevice = 0x925d, .config = ALC880_6ST_DIG }, /* FIC P4M-915GD1 */
2241 { .pci_subvendor = 0x1695, .pci_subdevice = 0x4012, .config = ALC880_5ST_DIG }, /* Epox EP-5LDA+ GLi */
2242
2243 { .modelname = "asus", .config = ALC880_ASUS },
2244 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1964, .config = ALC880_ASUS_DIG },
2245 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1973, .config = ALC880_ASUS_DIG },
2246 { .pci_subvendor = 0x1043, .pci_subdevice = 0x19b3, .config = ALC880_ASUS_DIG },
2247 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1113, .config = ALC880_ASUS_DIG },
2248 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1173, .config = ALC880_ASUS_DIG },
2249 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1993, .config = ALC880_ASUS },
2250 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c2, .config = ALC880_ASUS_DIG }, /* Asus W6A */
2251 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10c3, .config = ALC880_ASUS_DIG },
2252 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1133, .config = ALC880_ASUS },
2253 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1123, .config = ALC880_ASUS_DIG },
2254 { .pci_subvendor = 0x1043, .pci_subdevice = 0x1143, .config = ALC880_ASUS },
2255 { .modelname = "asus-w1v", .config = ALC880_ASUS_W1V },
2256 { .pci_subvendor = 0x1043, .pci_subdevice = 0x10b3, .config = ALC880_ASUS_W1V },
2257 { .modelname = "asus-dig", .config = ALC880_ASUS_DIG },
2258 { .pci_subvendor = 0x1043, .pci_subdevice = 0x8181, .config = ALC880_ASUS_DIG }, /* ASUS P4GPL-X */
2259 { .modelname = "asus-dig2", .config = ALC880_ASUS_DIG2 },
2260 { .pci_subvendor = 0x1558, .pci_subdevice = 0x5401, .config = ALC880_ASUS_DIG2 },
2261
2262 { .modelname = "uniwill", .config = ALC880_UNIWILL_DIG },
2263 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9050, .config = ALC880_UNIWILL_DIG },
2264
2265 { .modelname = "F1734", .config = ALC880_F1734 },
2266 { .pci_subvendor = 0x1734, .pci_subdevice = 0x107c, .config = ALC880_F1734 },
2267 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9054, .config = ALC880_F1734 },
2268
2269 { .modelname = "lg", .config = ALC880_LG },
2270 { .pci_subvendor = 0x1854, .pci_subdevice = 0x003b, .config = ALC880_LG },
2271 { .pci_subvendor = 0x1854, .pci_subdevice = 0x0068, .config = ALC880_LG },
2272
2273 { .modelname = "lg-lw", .config = ALC880_LG_LW },
2274 { .pci_subvendor = 0x1854, .pci_subdevice = 0x0018, .config = ALC880_LG_LW },
2275 { .pci_subvendor = 0x1854, .pci_subdevice = 0x0077, .config = ALC880_LG_LW },
2276
2277#ifdef CONFIG_SND_DEBUG 2385#ifdef CONFIG_SND_DEBUG
2278 { .modelname = "test", .config = ALC880_TEST }, 2386 [ALC880_TEST] = "test",
2279#endif 2387#endif
2280 { .modelname = "auto", .config = ALC880_AUTO }, 2388 [ALC880_AUTO] = "auto",
2389};
2390
2391static struct snd_pci_quirk alc880_cfg_tbl[] = {
2392 /* Broken BIOS configuration */
2393 SND_PCI_QUIRK(0x2668, 0x8086, NULL, ALC880_6ST_DIG),
2394 SND_PCI_QUIRK(0x8086, 0x2668, NULL, ALC880_6ST_DIG),
2395
2396 SND_PCI_QUIRK(0x1019, 0xa880, "ECS", ALC880_5ST_DIG),
2397 SND_PCI_QUIRK(0x1019, 0xa884, "Acer APFV", ALC880_6ST),
2398 SND_PCI_QUIRK(0x1019, 0x0f69, "Coeus G610P", ALC880_W810),
2399 SND_PCI_QUIRK(0x1025, 0x0070, "ULI", ALC880_3ST_DIG),
2400 SND_PCI_QUIRK(0x1025, 0x0077, "ULI", ALC880_6ST_DIG),
2401 SND_PCI_QUIRK(0x1025, 0x0078, "ULI", ALC880_6ST_DIG),
2402 SND_PCI_QUIRK(0x1025, 0x0087, "ULI", ALC880_6ST_DIG),
2403 SND_PCI_QUIRK(0x1025, 0xe309, "ULI", ALC880_3ST_DIG),
2404 SND_PCI_QUIRK(0x1025, 0xe310, "ULI", ALC880_3ST),
2405
2406 SND_PCI_QUIRK(0x1039, 0x1234, NULL, ALC880_6ST_DIG),
2407 SND_PCI_QUIRK(0x103c, 0x2a09, "HP", ALC880_5ST),
2408
2409 SND_PCI_QUIRK(0x1043, 0x10b3, "ASUS W1V", ALC880_ASUS_W1V),
2410 SND_PCI_QUIRK(0x1043, 0x10c2, "ASUS W6A", ALC880_ASUS_DIG),
2411 SND_PCI_QUIRK(0x1043, 0x10c3, "ASUS Wxx", ALC880_ASUS_DIG),
2412 SND_PCI_QUIRK(0x1043, 0x1113, "ASUS", ALC880_ASUS_DIG),
2413 SND_PCI_QUIRK(0x1043, 0x1123, "ASUS", ALC880_ASUS_DIG),
2414 SND_PCI_QUIRK(0x1043, 0x1173, "ASUS", ALC880_ASUS_DIG),
2415 SND_PCI_QUIRK(0x1043, 0x1964, "ASUS Z71V", ALC880_Z71V),
2416 /* SND_PCI_QUIRK(0x1043, 0x1964, "ASUS", ALC880_ASUS_DIG), */
2417 SND_PCI_QUIRK(0x1043, 0x1973, "ASUS", ALC880_ASUS_DIG),
2418 SND_PCI_QUIRK(0x1043, 0x19b3, "ASUS", ALC880_ASUS_DIG),
2419 SND_PCI_QUIRK(0x1043, 0x814e, "ASUS", ALC880_ASUS),
2420 SND_PCI_QUIRK(0x1043, 0x8181, "ASUS P4GPL", ALC880_ASUS_DIG),
2421 SND_PCI_QUIRK(0x1043, 0x8196, "ASUS P5GD1", ALC880_6ST),
2422 SND_PCI_QUIRK(0x1043, 0x81b4, "ASUS", ALC880_6ST),
2423 SND_PCI_QUIRK(0x1043, 0, "ASUS", ALC880_ASUS),
2424
2425 SND_PCI_QUIRK(0x104d, 0x81d6, "Sony", ALC880_3ST),
2426 SND_PCI_QUIRK(0x104d, 0x81a0, "Sony", ALC880_3ST),
2427 SND_PCI_QUIRK(0x107b, 0x3033, "Gateway", ALC880_5ST),
2428 SND_PCI_QUIRK(0x107b, 0x4039, "Gateway", ALC880_5ST),
2429 SND_PCI_QUIRK(0x107b, 0x3032, "Gateway", ALC880_5ST),
2430 SND_PCI_QUIRK(0x1558, 0x0520, "Clevo m520G", ALC880_CLEVO),
2431 SND_PCI_QUIRK(0x1558, 0x0660, "Clevo m655n", ALC880_CLEVO),
2432 SND_PCI_QUIRK(0x1565, 0x8202, "Biostar", ALC880_5ST_DIG),
2433 SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_W810),
2434 SND_PCI_QUIRK(0x1695, 0x400d, "EPoX", ALC880_5ST_DIG),
2435 SND_PCI_QUIRK(0x19db, 0x4188, "TCL S700", ALC880_TCL_S700),
2436 SND_PCI_QUIRK(0xa0a0, 0x0560, "AOpen i915GMm-HFS", ALC880_5ST_DIG),
2437 SND_PCI_QUIRK(0xe803, 0x1019, NULL, ALC880_6ST_DIG),
2438 SND_PCI_QUIRK(0x1297, 0xc790, "Shuttle ST20G5", ALC880_6ST_DIG),
2439 SND_PCI_QUIRK(0x1458, 0xa102, "Gigabyte K8", ALC880_6ST_DIG),
2440 SND_PCI_QUIRK(0x1462, 0x1150, "MSI", ALC880_6ST_DIG),
2441 SND_PCI_QUIRK(0x1509, 0x925d, "FIC P4M", ALC880_6ST_DIG),
2442 SND_PCI_QUIRK(0x1558, 0x5401, "ASUS", ALC880_ASUS_DIG2),
2443
2444 SND_PCI_QUIRK(0x1584, 0x9050, "Uniwill", ALC880_UNIWILL_DIG),
2445 SND_PCI_QUIRK(0x1584, 0x9070, "Uniwill", ALC880_UNIWILL),
2446 SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_UNIWILL_P53),
2447 SND_PCI_QUIRK(0x1584, 0x9054, "Uniwlll", ALC880_F1734),
2448
2449 SND_PCI_QUIRK(0x1695, 0x4012, "EPox EP-5LDA", ALC880_5ST_DIG),
2450 SND_PCI_QUIRK(0x1734, 0x10ac, "FSC", ALC880_UNIWILL),
2451 SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_F1734),
2452 SND_PCI_QUIRK(0x1734, 0x10b0, "Fujitsu", ALC880_FUJITSU),
2453
2454 SND_PCI_QUIRK(0x1854, 0x003b, "LG", ALC880_LG),
2455 SND_PCI_QUIRK(0x1854, 0x0068, "LG w1", ALC880_LG),
2456 SND_PCI_QUIRK(0x1854, 0x0018, "LG LW20", ALC880_LG_LW),
2457 SND_PCI_QUIRK(0x1854, 0x0077, "LG LW25", ALC880_LG_LW),
2458
2459 SND_PCI_QUIRK(0x8086, 0xe308, "Intel mobo", ALC880_3ST_DIG),
2460 SND_PCI_QUIRK(0x8086, 0xe305, "Intel mobo", ALC880_3ST_DIG),
2461 SND_PCI_QUIRK(0x8086, 0xd402, "Intel mobo", ALC880_3ST_DIG),
2462 SND_PCI_QUIRK(0x8086, 0xd400, "Intel mobo", ALC880_5ST_DIG),
2463 SND_PCI_QUIRK(0x8086, 0xd401, "Intel mobo", ALC880_5ST_DIG),
2464 SND_PCI_QUIRK(0x8086, 0xe224, "Intel mobo", ALC880_5ST_DIG),
2465 SND_PCI_QUIRK(0x8086, 0xe400, "Intel mobo", ALC880_5ST_DIG),
2466 SND_PCI_QUIRK(0x8086, 0xe401, "Intel mobo", ALC880_5ST_DIG),
2467 SND_PCI_QUIRK(0x8086, 0xe402, "Intel mobo", ALC880_5ST_DIG),
2468 SND_PCI_QUIRK(0x8086, 0xa100, "Intel mobo", ALC880_5ST_DIG),
2469 SND_PCI_QUIRK(0x8086, 0, "Intel mobo", ALC880_3ST),
2281 2470
2282 {} 2471 {}
2283}; 2472};
@@ -2438,7 +2627,8 @@ static struct alc_config_preset alc880_presets[] = {
2438 }, 2627 },
2439 [ALC880_UNIWILL_DIG] = { 2628 [ALC880_UNIWILL_DIG] = {
2440 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer }, 2629 .mixers = { alc880_asus_mixer, alc880_pcbeep_mixer },
2441 .init_verbs = { alc880_volume_init_verbs, alc880_pin_asus_init_verbs }, 2630 .init_verbs = { alc880_volume_init_verbs,
2631 alc880_pin_asus_init_verbs },
2442 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids), 2632 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2443 .dac_nids = alc880_asus_dac_nids, 2633 .dac_nids = alc880_asus_dac_nids,
2444 .dig_out_nid = ALC880_DIGOUT_NID, 2634 .dig_out_nid = ALC880_DIGOUT_NID,
@@ -2447,6 +2637,46 @@ static struct alc_config_preset alc880_presets[] = {
2447 .need_dac_fix = 1, 2637 .need_dac_fix = 1,
2448 .input_mux = &alc880_capture_source, 2638 .input_mux = &alc880_capture_source,
2449 }, 2639 },
2640 [ALC880_UNIWILL] = {
2641 .mixers = { alc880_uniwill_mixer },
2642 .init_verbs = { alc880_volume_init_verbs,
2643 alc880_uniwill_init_verbs },
2644 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2645 .dac_nids = alc880_asus_dac_nids,
2646 .dig_out_nid = ALC880_DIGOUT_NID,
2647 .num_channel_mode = ARRAY_SIZE(alc880_threestack_modes),
2648 .channel_mode = alc880_threestack_modes,
2649 .need_dac_fix = 1,
2650 .input_mux = &alc880_capture_source,
2651 .unsol_event = alc880_uniwill_unsol_event,
2652 .init_hook = alc880_uniwill_automute,
2653 },
2654 [ALC880_UNIWILL_P53] = {
2655 .mixers = { alc880_uniwill_p53_mixer },
2656 .init_verbs = { alc880_volume_init_verbs,
2657 alc880_uniwill_p53_init_verbs },
2658 .num_dacs = ARRAY_SIZE(alc880_asus_dac_nids),
2659 .dac_nids = alc880_asus_dac_nids,
2660 .num_channel_mode = ARRAY_SIZE(alc880_w810_modes),
2661 .channel_mode = alc880_threestack_modes,
2662 .input_mux = &alc880_capture_source,
2663 .unsol_event = alc880_uniwill_p53_unsol_event,
2664 .init_hook = alc880_uniwill_p53_hp_automute,
2665 },
2666 [ALC880_FUJITSU] = {
2667 .mixers = { alc880_fujitsu_mixer,
2668 alc880_pcbeep_mixer, },
2669 .init_verbs = { alc880_volume_init_verbs,
2670 alc880_uniwill_p53_init_verbs,
2671 alc880_beep_init_verbs },
2672 .num_dacs = ARRAY_SIZE(alc880_dac_nids),
2673 .dac_nids = alc880_dac_nids,
2674 .num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
2675 .channel_mode = alc880_2_jack_modes,
2676 .input_mux = &alc880_capture_source,
2677 .unsol_event = alc880_uniwill_p53_unsol_event,
2678 .init_hook = alc880_uniwill_p53_hp_automute,
2679 },
2450 [ALC880_CLEVO] = { 2680 [ALC880_CLEVO] = {
2451 .mixers = { alc880_three_stack_mixer }, 2681 .mixers = { alc880_three_stack_mixer },
2452 .init_verbs = { alc880_volume_init_verbs, 2682 .init_verbs = { alc880_volume_init_verbs,
@@ -2841,8 +3071,10 @@ static int patch_alc880(struct hda_codec *codec)
2841 3071
2842 codec->spec = spec; 3072 codec->spec = spec;
2843 3073
2844 board_config = snd_hda_check_board_config(codec, alc880_cfg_tbl); 3074 board_config = snd_hda_check_board_config(codec, ALC880_MODEL_LAST,
2845 if (board_config < 0 || board_config >= ALC880_MODEL_LAST) { 3075 alc880_models,
3076 alc880_cfg_tbl);
3077 if (board_config < 0) {
2846 printk(KERN_INFO "hda_codec: Unknown model for ALC880, " 3078 printk(KERN_INFO "hda_codec: Unknown model for ALC880, "
2847 "trying auto-probe from BIOS...\n"); 3079 "trying auto-probe from BIOS...\n");
2848 board_config = ALC880_AUTO; 3080 board_config = ALC880_AUTO;
@@ -3090,11 +3322,20 @@ static struct snd_kcontrol_new alc260_fujitsu_mixer[] = {
3090 * and the output jack. If this turns out to be the case for all such 3322 * and the output jack. If this turns out to be the case for all such
3091 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT 3323 * models the "Line Jack Mode" mode could be changed from ALC_PIN_DIR_INOUT
3092 * to ALC_PIN_DIR_INOUT_NOMICBIAS. 3324 * to ALC_PIN_DIR_INOUT_NOMICBIAS.
3325 *
3326 * The C20x Tablet series have a mono internal speaker which is controlled
3327 * via the chip's Mono sum widget and pin complex, so include the necessary
3328 * controls for such models. On models without a "mono speaker" the control
3329 * won't do anything.
3093 */ 3330 */
3094static struct snd_kcontrol_new alc260_acer_mixer[] = { 3331static struct snd_kcontrol_new alc260_acer_mixer[] = {
3095 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT), 3332 HDA_CODEC_VOLUME("Master Playback Volume", 0x08, 0x0, HDA_OUTPUT),
3096 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT), 3333 HDA_BIND_MUTE("Master Playback Switch", 0x08, 2, HDA_INPUT),
3097 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT), 3334 ALC_PIN_MODE("Headphone Jack Mode", 0x0f, ALC_PIN_DIR_INOUT),
3335 HDA_CODEC_VOLUME_MONO("Mono Speaker Playback Volume", 0x0a, 1, 0x0,
3336 HDA_OUTPUT),
3337 HDA_BIND_MUTE_MONO("Mono Speaker Playback Switch", 0x0a, 1, 2,
3338 HDA_INPUT),
3098 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT), 3339 HDA_CODEC_VOLUME("CD Playback Volume", 0x07, 0x04, HDA_INPUT),
3099 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT), 3340 HDA_CODEC_MUTE("CD Playback Switch", 0x07, 0x04, HDA_INPUT),
3100 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT), 3341 HDA_CODEC_VOLUME("Mic Playback Volume", 0x07, 0x0, HDA_INPUT),
@@ -3409,11 +3650,11 @@ static struct hda_verb alc260_acer_init_verbs[] = {
3409 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50}, 3650 {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50},
3410 /* Line In jack is connected to Line1 pin */ 3651 /* Line In jack is connected to Line1 pin */
3411 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN}, 3652 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
3653 /* Some Acers (eg: C20x Tablets) use Mono pin for internal speaker */
3654 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
3412 /* Ensure all other unused pins are disabled and muted. */ 3655 /* Ensure all other unused pins are disabled and muted. */
3413 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3656 {0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3414 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3657 {0x10, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3415 {0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3416 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3417 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3658 {0x13, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
3418 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)}, 3659 {0x13, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
3419 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0}, 3660 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, 0},
@@ -3441,6 +3682,8 @@ static struct hda_verb alc260_acer_init_verbs[] = {
3441 3682
3442 /* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */ 3683 /* Unmute Line-out pin widget amp left and right (no equiv mixer ctrl) */
3443 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE}, 3684 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3685 /* Unmute mono pin widget amp output (no equiv mixer ctrl) */
3686 {0x11, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
3444 /* Unmute Mic1 and Line1 pin widget input buffers since they start as 3687 /* Unmute Mic1 and Line1 pin widget input buffers since they start as
3445 * inputs. If the pin mode is changed by the user the pin mode control 3688 * inputs. If the pin mode is changed by the user the pin mode control
3446 * will take care of enabling the pin's input/output buffers as needed. 3689 * will take care of enabling the pin's input/output buffers as needed.
@@ -3928,33 +4171,33 @@ static void alc260_auto_init(struct hda_codec *codec)
3928/* 4171/*
3929 * ALC260 configurations 4172 * ALC260 configurations
3930 */ 4173 */
3931static struct hda_board_config alc260_cfg_tbl[] = { 4174static const char *alc260_models[ALC260_MODEL_LAST] = {
3932 { .modelname = "basic", .config = ALC260_BASIC }, 4175 [ALC260_BASIC] = "basic",
3933 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81bb, 4176 [ALC260_HP] = "hp",
3934 .config = ALC260_BASIC }, /* Sony VAIO */ 4177 [ALC260_HP_3013] = "hp-3013",
3935 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81cc, 4178 [ALC260_FUJITSU_S702X] = "fujitsu",
3936 .config = ALC260_BASIC }, /* Sony VAIO VGN-S3HP */ 4179 [ALC260_ACER] = "acer",
3937 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81cd,
3938 .config = ALC260_BASIC }, /* Sony VAIO */
3939 { .pci_subvendor = 0x152d, .pci_subdevice = 0x0729,
3940 .config = ALC260_BASIC }, /* CTL Travel Master U553W */
3941 { .modelname = "hp", .config = ALC260_HP },
3942 { .modelname = "hp-3013", .config = ALC260_HP_3013 },
3943 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3010, .config = ALC260_HP_3013 },
3944 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3011, .config = ALC260_HP },
3945 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3012, .config = ALC260_HP_3013 },
3946 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3013, .config = ALC260_HP_3013 },
3947 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, .config = ALC260_HP },
3948 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, .config = ALC260_HP },
3949 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3016, .config = ALC260_HP },
3950 { .modelname = "fujitsu", .config = ALC260_FUJITSU_S702X },
3951 { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1326, .config = ALC260_FUJITSU_S702X },
3952 { .modelname = "acer", .config = ALC260_ACER },
3953 { .pci_subvendor = 0x1025, .pci_subdevice = 0x008f, .config = ALC260_ACER },
3954#ifdef CONFIG_SND_DEBUG 4180#ifdef CONFIG_SND_DEBUG
3955 { .modelname = "test", .config = ALC260_TEST }, 4181 [ALC260_TEST] = "test",
3956#endif 4182#endif
3957 { .modelname = "auto", .config = ALC260_AUTO }, 4183 [ALC260_AUTO] = "auto",
4184};
4185
4186static struct snd_pci_quirk alc260_cfg_tbl[] = {
4187 SND_PCI_QUIRK(0x1025, 0x007b, "Acer C20x", ALC260_ACER),
4188 SND_PCI_QUIRK(0x1025, 0x008f, "Acer", ALC260_ACER),
4189 SND_PCI_QUIRK(0x103c, 0x3010, "HP", ALC260_HP_3013),
4190 SND_PCI_QUIRK(0x103c, 0x3011, "HP", ALC260_HP),
4191 SND_PCI_QUIRK(0x103c, 0x3012, "HP", ALC260_HP_3013),
4192 SND_PCI_QUIRK(0x103c, 0x3013, "HP", ALC260_HP_3013),
4193 SND_PCI_QUIRK(0x103c, 0x3014, "HP", ALC260_HP),
4194 SND_PCI_QUIRK(0x103c, 0x3015, "HP", ALC260_HP),
4195 SND_PCI_QUIRK(0x103c, 0x3016, "HP", ALC260_HP),
4196 SND_PCI_QUIRK(0x104d, 0x81bb, "Sony VAIO", ALC260_BASIC),
4197 SND_PCI_QUIRK(0x104d, 0x81cc, "Sony VAIO", ALC260_BASIC),
4198 SND_PCI_QUIRK(0x104d, 0x81cd, "Sony VAIO", ALC260_BASIC),
4199 SND_PCI_QUIRK(0x10cf, 0x1326, "Fujitsu S702X", ALC260_FUJITSU_S702X),
4200 SND_PCI_QUIRK(0x152d, 0x0729, "CTL U553W", ALC260_BASIC),
3958 {} 4201 {}
3959}; 4202};
3960 4203
@@ -4053,8 +4296,10 @@ static int patch_alc260(struct hda_codec *codec)
4053 4296
4054 codec->spec = spec; 4297 codec->spec = spec;
4055 4298
4056 board_config = snd_hda_check_board_config(codec, alc260_cfg_tbl); 4299 board_config = snd_hda_check_board_config(codec, ALC260_MODEL_LAST,
4057 if (board_config < 0 || board_config >= ALC260_MODEL_LAST) { 4300 alc260_models,
4301 alc260_cfg_tbl);
4302 if (board_config < 0) {
4058 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, " 4303 snd_printd(KERN_INFO "hda_codec: Unknown model for ALC260, "
4059 "trying auto-probe from BIOS...\n"); 4304 "trying auto-probe from BIOS...\n");
4060 board_config = ALC260_AUTO; 4305 board_config = ALC260_AUTO;
@@ -4207,8 +4452,10 @@ static struct snd_kcontrol_new alc882_base_mixer[] = {
4207 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 4452 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4208 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 4453 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4209 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 4454 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
4455 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
4210 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 4456 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4211 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 4457 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
4458 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
4212 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 4459 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
4213 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 4460 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
4214 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 4461 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
@@ -4313,6 +4560,100 @@ static struct hda_verb alc882_eapd_verbs[] = {
4313 { } 4560 { }
4314}; 4561};
4315 4562
4563/* Mac Pro test */
4564static struct snd_kcontrol_new alc882_macpro_mixer[] = {
4565 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
4566 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
4567 HDA_CODEC_MUTE("Headphone Playback Switch", 0x18, 0x0, HDA_OUTPUT),
4568 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
4569 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
4570 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x02, HDA_INPUT),
4571 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x02, HDA_INPUT),
4572 { } /* end */
4573};
4574
4575static struct hda_verb alc882_macpro_init_verbs[] = {
4576 /* Front mixer: unmute input/output amp left and right (volume = 0) */
4577 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
4578 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4579 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
4580 /* Front Pin: output 0 (0x0c) */
4581 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4582 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4583 {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
4584 /* Front Mic pin: input vref at 80% */
4585 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
4586 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
4587 /* Speaker: output */
4588 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
4589 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4590 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x04},
4591 /* Headphone output (output 0 - 0x0c) */
4592 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
4593 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
4594 {0x18, AC_VERB_SET_CONNECT_SEL, 0x00},
4595
4596 /* FIXME: use matrix-type input source selection */
4597 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
4598 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
4599 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4600 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4601 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4602 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4603 /* Input mixer2 */
4604 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4605 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4606 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4607 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4608 /* Input mixer3 */
4609 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
4610 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(3)},
4611 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2)},
4612 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(4)},
4613 /* ADC1: mute amp left and right */
4614 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4615 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
4616 /* ADC2: mute amp left and right */
4617 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4618 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
4619 /* ADC3: mute amp left and right */
4620 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
4621 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
4622
4623 { }
4624};
4625static void alc882_gpio_mute(struct hda_codec *codec, int pin, int muted)
4626{
4627 unsigned int gpiostate, gpiomask, gpiodir;
4628
4629 gpiostate = snd_hda_codec_read(codec, codec->afg, 0,
4630 AC_VERB_GET_GPIO_DATA, 0);
4631
4632 if (!muted)
4633 gpiostate |= (1 << pin);
4634 else
4635 gpiostate &= ~(1 << pin);
4636
4637 gpiomask = snd_hda_codec_read(codec, codec->afg, 0,
4638 AC_VERB_GET_GPIO_MASK, 0);
4639 gpiomask |= (1 << pin);
4640
4641 gpiodir = snd_hda_codec_read(codec, codec->afg, 0,
4642 AC_VERB_GET_GPIO_DIRECTION, 0);
4643 gpiodir |= (1 << pin);
4644
4645
4646 snd_hda_codec_write(codec, codec->afg, 0,
4647 AC_VERB_SET_GPIO_MASK, gpiomask);
4648 snd_hda_codec_write(codec, codec->afg, 0,
4649 AC_VERB_SET_GPIO_DIRECTION, gpiodir);
4650
4651 msleep(1);
4652
4653 snd_hda_codec_write(codec, codec->afg, 0,
4654 AC_VERB_SET_GPIO_DATA, gpiostate);
4655}
4656
4316/* 4657/*
4317 * generic initialization of ADC, input mixers and output mixers 4658 * generic initialization of ADC, input mixers and output mixers
4318 */ 4659 */
@@ -4435,19 +4776,20 @@ static struct snd_kcontrol_new alc882_capture_mixer[] = {
4435/* 4776/*
4436 * configuration and preset 4777 * configuration and preset
4437 */ 4778 */
4438static struct hda_board_config alc882_cfg_tbl[] = { 4779static const char *alc882_models[ALC882_MODEL_LAST] = {
4439 { .modelname = "3stack-dig", .config = ALC882_3ST_DIG }, 4780 [ALC882_3ST_DIG] = "3stack-dig",
4440 { .modelname = "6stack-dig", .config = ALC882_6ST_DIG }, 4781 [ALC882_6ST_DIG] = "6stack-dig",
4441 { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, 4782 [ALC882_ARIMA] = "arima",
4442 .config = ALC882_6ST_DIG }, /* MSI */ 4783 [ALC885_MACPRO] = "macpro",
4443 { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, 4784 [ALC882_AUTO] = "auto",
4444 .config = ALC882_6ST_DIG }, /* Foxconn */ 4785};
4445 { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, 4786
4446 .config = ALC882_6ST_DIG }, /* ECS to Intel*/ 4787static struct snd_pci_quirk alc882_cfg_tbl[] = {
4447 { .modelname = "arima", .config = ALC882_ARIMA }, 4788 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC882_6ST_DIG),
4448 { .pci_subvendor = 0x161f, .pci_subdevice = 0x2054, 4789 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC882_6ST_DIG),
4449 .config = ALC882_ARIMA }, /* Arima W820Di1 */ 4790 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC882_6ST_DIG),
4450 { .modelname = "auto", .config = ALC882_AUTO }, 4791 SND_PCI_QUIRK(0x161f, 0x2054, "Arima W820", ALC882_ARIMA),
4792 SND_PCI_QUIRK(0x1043, 0x81d8, "Asus P5WD", ALC882_6ST_DIG),
4451 {} 4793 {}
4452}; 4794};
4453 4795
@@ -4484,6 +4826,17 @@ static struct alc_config_preset alc882_presets[] = {
4484 .channel_mode = alc882_sixstack_modes, 4826 .channel_mode = alc882_sixstack_modes,
4485 .input_mux = &alc882_capture_source, 4827 .input_mux = &alc882_capture_source,
4486 }, 4828 },
4829 [ALC885_MACPRO] = {
4830 .mixers = { alc882_macpro_mixer },
4831 .init_verbs = { alc882_macpro_init_verbs },
4832 .num_dacs = ARRAY_SIZE(alc882_dac_nids),
4833 .dac_nids = alc882_dac_nids,
4834 .dig_out_nid = ALC882_DIGOUT_NID,
4835 .dig_in_nid = ALC882_DIGIN_NID,
4836 .num_channel_mode = ARRAY_SIZE(alc882_ch_modes),
4837 .channel_mode = alc882_ch_modes,
4838 .input_mux = &alc882_capture_source,
4839 },
4487}; 4840};
4488 4841
4489 4842
@@ -4584,7 +4937,9 @@ static int patch_alc882(struct hda_codec *codec)
4584 4937
4585 codec->spec = spec; 4938 codec->spec = spec;
4586 4939
4587 board_config = snd_hda_check_board_config(codec, alc882_cfg_tbl); 4940 board_config = snd_hda_check_board_config(codec, ALC882_MODEL_LAST,
4941 alc882_models,
4942 alc882_cfg_tbl);
4588 4943
4589 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) { 4944 if (board_config < 0 || board_config >= ALC882_MODEL_LAST) {
4590 printk(KERN_INFO "hda_codec: Unknown model for ALC882, " 4945 printk(KERN_INFO "hda_codec: Unknown model for ALC882, "
@@ -4609,6 +4964,11 @@ static int patch_alc882(struct hda_codec *codec)
4609 if (board_config != ALC882_AUTO) 4964 if (board_config != ALC882_AUTO)
4610 setup_preset(spec, &alc882_presets[board_config]); 4965 setup_preset(spec, &alc882_presets[board_config]);
4611 4966
4967 if (board_config == ALC885_MACPRO) {
4968 alc882_gpio_mute(codec, 0, 0);
4969 alc882_gpio_mute(codec, 1, 0);
4970 }
4971
4612 spec->stream_name_analog = "ALC882 Analog"; 4972 spec->stream_name_analog = "ALC882 Analog";
4613 spec->stream_analog_playback = &alc882_pcm_analog_playback; 4973 spec->stream_analog_playback = &alc882_pcm_analog_playback;
4614 spec->stream_analog_capture = &alc882_pcm_analog_capture; 4974 spec->stream_analog_capture = &alc882_pcm_analog_capture;
@@ -4767,6 +5127,13 @@ static struct hda_channel_mode alc883_sixstack_modes[2] = {
4767 { 8, alc883_sixstack_ch8_init }, 5127 { 8, alc883_sixstack_ch8_init },
4768}; 5128};
4769 5129
5130static struct hda_verb alc883_medion_eapd_verbs[] = {
5131 /* eanable EAPD on medion laptop */
5132 {0x20, AC_VERB_SET_COEF_INDEX, 0x07},
5133 {0x20, AC_VERB_SET_PROC_COEF, 0x3070},
5134 { }
5135};
5136
4770/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17 5137/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
4771 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b 5138 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
4772 */ 5139 */
@@ -4788,8 +5155,10 @@ static struct snd_kcontrol_new alc883_base_mixer[] = {
4788 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5155 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4789 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5156 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4790 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5157 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5158 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
4791 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5159 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4792 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5160 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5161 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
4793 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5162 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
4794 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5163 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
4795 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5164 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
@@ -4818,8 +5187,10 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
4818 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5187 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4819 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5188 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4820 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5189 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5190 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
4821 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5191 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4822 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5192 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5193 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
4823 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5194 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
4824 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5195 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
4825 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5196 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
@@ -4854,8 +5225,10 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
4854 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT), 5225 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
4855 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT), 5226 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
4856 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT), 5227 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5228 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
4857 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT), 5229 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
4858 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT), 5230 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5231 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
4859 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT), 5232 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
4860 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT), 5233 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
4861 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT), 5234 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
@@ -4875,6 +5248,101 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
4875 { } /* end */ 5248 { } /* end */
4876}; 5249};
4877 5250
5251static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
5252 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5253 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5254 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5255 HDA_CODEC_MUTE("Surround Playback Switch", 0x15, 0x0, HDA_OUTPUT),
5256 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5257 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5258 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x16, 1, 0x0, HDA_OUTPUT),
5259 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
5260 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5261 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5262 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5263 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5264 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5265 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5266 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5267 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5268 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
5269 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
5270 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
5271 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
5272 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
5273 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5274 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5275
5276 {
5277 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5278 /* .name = "Capture Source", */
5279 .name = "Input Source",
5280 .count = 1,
5281 .info = alc883_mux_enum_info,
5282 .get = alc883_mux_enum_get,
5283 .put = alc883_mux_enum_put,
5284 },
5285 { } /* end */
5286};
5287
5288static struct snd_kcontrol_new alc883_tagra_mixer[] = {
5289 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5290 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5291 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5292 HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5293 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
5294 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0, HDA_OUTPUT),
5295 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5296 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
5297 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
5298 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5299 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5300 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5301 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5302 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5303 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5304 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5305 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5306 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5307 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5308 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5309 {
5310 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5311 /* .name = "Capture Source", */
5312 .name = "Input Source",
5313 .count = 2,
5314 .info = alc883_mux_enum_info,
5315 .get = alc883_mux_enum_get,
5316 .put = alc883_mux_enum_put,
5317 },
5318 { } /* end */
5319};
5320
5321static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
5322 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5323 HDA_CODEC_MUTE("Headphone Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5324 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5325 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5326 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5327 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5328 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
5329 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5330 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
5331 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
5332 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
5333 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
5334 {
5335 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
5336 /* .name = "Capture Source", */
5337 .name = "Input Source",
5338 .count = 2,
5339 .info = alc883_mux_enum_info,
5340 .get = alc883_mux_enum_get,
5341 .put = alc883_mux_enum_put,
5342 },
5343 { } /* end */
5344};
5345
4878static struct snd_kcontrol_new alc883_chmode_mixer[] = { 5346static struct snd_kcontrol_new alc883_chmode_mixer[] = {
4879 { 5347 {
4880 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 5348 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -4963,6 +5431,45 @@ static struct hda_verb alc883_init_verbs[] = {
4963 { } 5431 { }
4964}; 5432};
4965 5433
5434static struct hda_verb alc883_tagra_verbs[] = {
5435 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
5436 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
5437
5438 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
5439 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
5440
5441 {0x18, AC_VERB_SET_CONNECT_SEL, 0x02}, /* mic/clfe */
5442 {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01}, /* line/surround */
5443 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00}, /* HP */
5444
5445 {0x14, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
5446 {0x01, AC_VERB_SET_GPIO_MASK, 0x03},
5447 {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x03},
5448 {0x01, AC_VERB_SET_GPIO_DATA, 0x03},
5449
5450 { } /* end */
5451};
5452
5453/* toggle speaker-output according to the hp-jack state */
5454static void alc883_tagra_automute(struct hda_codec *codec)
5455{
5456 unsigned int present;
5457
5458 present = snd_hda_codec_read(codec, 0x14, 0,
5459 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
5460 snd_hda_codec_amp_update(codec, 0x1b, 0, HDA_OUTPUT, 0,
5461 0x80, present ? 0x80 : 0);
5462 snd_hda_codec_amp_update(codec, 0x1b, 1, HDA_OUTPUT, 0,
5463 0x80, present ? 0x80 : 0);
5464 snd_hda_codec_write(codec, 1, 0, AC_VERB_SET_GPIO_DATA, present ? 1 : 3);
5465}
5466
5467static void alc883_tagra_unsol_event(struct hda_codec *codec, unsigned int res)
5468{
5469 if ((res >> 26) == ALC880_HP_EVENT)
5470 alc883_tagra_automute(codec);
5471}
5472
4966/* 5473/*
4967 * generic initialization of ADC, input mixers and output mixers 5474 * generic initialization of ADC, input mixers and output mixers
4968 */ 5475 */
@@ -5057,32 +5564,42 @@ static struct snd_kcontrol_new alc883_capture_mixer[] = {
5057/* 5564/*
5058 * configuration and preset 5565 * configuration and preset
5059 */ 5566 */
5060static struct hda_board_config alc883_cfg_tbl[] = { 5567static const char *alc883_models[ALC883_MODEL_LAST] = {
5061 { .modelname = "3stack-dig", .config = ALC883_3ST_2ch_DIG }, 5568 [ALC883_3ST_2ch_DIG] = "3stack-dig",
5062 { .modelname = "3stack-6ch-dig", .config = ALC883_3ST_6ch_DIG }, 5569 [ALC883_3ST_6ch_DIG] = "3stack-6ch-dig",
5063 { .pci_subvendor = 0x1019, .pci_subdevice = 0x6668, 5570 [ALC883_3ST_6ch] = "3stack-6ch",
5064 .config = ALC883_3ST_6ch_DIG }, /* ECS to Intel*/ 5571 [ALC883_6ST_DIG] = "6stack-dig",
5065 { .modelname = "3stack-6ch", .config = ALC883_3ST_6ch }, 5572 [ALC883_TARGA_DIG] = "targa-dig",
5066 { .pci_subvendor = 0x108e, .pci_subdevice = 0x534d, 5573 [ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
5067 .config = ALC883_3ST_6ch }, 5574 [ALC888_DEMO_BOARD] = "6stack-dig-demo",
5068 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd601, 5575 [ALC883_ACER] = "acer",
5069 .config = ALC883_3ST_6ch }, /* D102GGC */ 5576 [ALC883_MEDION] = "medion",
5070 { .modelname = "6stack-dig", .config = ALC883_6ST_DIG }, 5577 [ALC883_LAPTOP_EAPD] = "laptop-eapd",
5071 { .pci_subvendor = 0x1462, .pci_subdevice = 0x6668, 5578 [ALC883_AUTO] = "auto",
5072 .config = ALC883_6ST_DIG }, /* MSI */ 5579};
5073 { .pci_subvendor = 0x1462, .pci_subdevice = 0x7280, 5580
5074 .config = ALC883_6ST_DIG }, /* MSI K9A Platinum (MS-7280) */ 5581static struct snd_pci_quirk alc883_cfg_tbl[] = {
5075 { .pci_subvendor = 0x105b, .pci_subdevice = 0x6668, 5582 SND_PCI_QUIRK(0x1019, 0x6668, "ECS", ALC883_3ST_6ch_DIG),
5076 .config = ALC883_6ST_DIG }, /* Foxconn */ 5583 SND_PCI_QUIRK(0x108e, 0x534d, NULL, ALC883_3ST_6ch),
5077 { .modelname = "6stack-dig-demo", .config = ALC888_DEMO_BOARD }, 5584 SND_PCI_QUIRK(0x1558, 0, "Clevo laptop", ALC883_LAPTOP_EAPD),
5078 { .modelname = "acer", .config = ALC883_ACER }, 5585 SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
5079 { .pci_subvendor = 0x1025, .pci_subdevice = 0/*0x0102*/, 5586 SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
5080 .config = ALC883_ACER }, 5587 SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
5081 { .pci_subvendor = 0x1025, .pci_subdevice = 0x0102, 5588 SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
5082 .config = ALC883_ACER }, 5589 SND_PCI_QUIRK(0x1462, 0x0579, "MSI", ALC883_TARGA_2ch_DIG),
5083 { .pci_subvendor = 0x1025, .pci_subdevice = 0x009f, 5590 SND_PCI_QUIRK(0x1462, 0x3ef9, "MSI", ALC883_TARGA_DIG),
5084 .config = ALC883_ACER }, 5591 SND_PCI_QUIRK(0x1462, 0x3b7f, "MSI", ALC883_TARGA_2ch_DIG),
5085 { .modelname = "auto", .config = ALC883_AUTO }, 5592 SND_PCI_QUIRK(0x1462, 0x3fcc, "MSI", ALC883_TARGA_DIG),
5593 SND_PCI_QUIRK(0x1462, 0x3fc1, "MSI", ALC883_TARGA_DIG),
5594 SND_PCI_QUIRK(0x1462, 0x3fc3, "MSI", ALC883_TARGA_DIG),
5595 SND_PCI_QUIRK(0x1462, 0x4314, "MSI", ALC883_TARGA_DIG),
5596 SND_PCI_QUIRK(0x1462, 0x4319, "MSI", ALC883_TARGA_DIG),
5597 SND_PCI_QUIRK(0x1462, 0x4324, "MSI", ALC883_TARGA_DIG),
5598 SND_PCI_QUIRK(0x1462, 0xa422, "MSI", ALC883_TARGA_2ch_DIG),
5599 SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER),
5600 SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
5601 SND_PCI_QUIRK(0x1071, 0x8258, "Evesham Voyaeger", ALC883_LAPTOP_EAPD),
5602 SND_PCI_QUIRK(0x8086, 0xd601, "D102GGC", ALC883_3ST_6ch),
5086 {} 5603 {}
5087}; 5604};
5088 5605
@@ -5139,6 +5656,35 @@ static struct alc_config_preset alc883_presets[] = {
5139 .channel_mode = alc883_sixstack_modes, 5656 .channel_mode = alc883_sixstack_modes,
5140 .input_mux = &alc883_capture_source, 5657 .input_mux = &alc883_capture_source,
5141 }, 5658 },
5659 [ALC883_TARGA_DIG] = {
5660 .mixers = { alc883_tagra_mixer, alc883_chmode_mixer },
5661 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
5662 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
5663 .dac_nids = alc883_dac_nids,
5664 .dig_out_nid = ALC883_DIGOUT_NID,
5665 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5666 .adc_nids = alc883_adc_nids,
5667 .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
5668 .channel_mode = alc883_3ST_6ch_modes,
5669 .need_dac_fix = 1,
5670 .input_mux = &alc883_capture_source,
5671 .unsol_event = alc883_tagra_unsol_event,
5672 .init_hook = alc883_tagra_automute,
5673 },
5674 [ALC883_TARGA_2ch_DIG] = {
5675 .mixers = { alc883_tagra_2ch_mixer},
5676 .init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
5677 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
5678 .dac_nids = alc883_dac_nids,
5679 .dig_out_nid = ALC883_DIGOUT_NID,
5680 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5681 .adc_nids = alc883_adc_nids,
5682 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
5683 .channel_mode = alc883_3ST_2ch_modes,
5684 .input_mux = &alc883_capture_source,
5685 .unsol_event = alc883_tagra_unsol_event,
5686 .init_hook = alc883_tagra_automute,
5687 },
5142 [ALC888_DEMO_BOARD] = { 5688 [ALC888_DEMO_BOARD] = {
5143 .mixers = { alc883_base_mixer, alc883_chmode_mixer }, 5689 .mixers = { alc883_base_mixer, alc883_chmode_mixer },
5144 .init_verbs = { alc883_init_verbs }, 5690 .init_verbs = { alc883_init_verbs },
@@ -5169,6 +5715,31 @@ static struct alc_config_preset alc883_presets[] = {
5169 .channel_mode = alc883_3ST_2ch_modes, 5715 .channel_mode = alc883_3ST_2ch_modes,
5170 .input_mux = &alc883_capture_source, 5716 .input_mux = &alc883_capture_source,
5171 }, 5717 },
5718 [ALC883_MEDION] = {
5719 .mixers = { alc883_fivestack_mixer,
5720 alc883_chmode_mixer },
5721 .init_verbs = { alc883_init_verbs,
5722 alc883_medion_eapd_verbs },
5723 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
5724 .dac_nids = alc883_dac_nids,
5725 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5726 .adc_nids = alc883_adc_nids,
5727 .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
5728 .channel_mode = alc883_sixstack_modes,
5729 .input_mux = &alc883_capture_source,
5730 },
5731 [ALC883_LAPTOP_EAPD] = {
5732 .mixers = { alc883_base_mixer,
5733 alc883_chmode_mixer },
5734 .init_verbs = { alc883_init_verbs, alc882_eapd_verbs },
5735 .num_dacs = ARRAY_SIZE(alc883_dac_nids),
5736 .dac_nids = alc883_dac_nids,
5737 .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
5738 .adc_nids = alc883_adc_nids,
5739 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
5740 .channel_mode = alc883_3ST_2ch_modes,
5741 .input_mux = &alc883_capture_source,
5742 },
5172}; 5743};
5173 5744
5174 5745
@@ -5277,8 +5848,10 @@ static int patch_alc883(struct hda_codec *codec)
5277 5848
5278 codec->spec = spec; 5849 codec->spec = spec;
5279 5850
5280 board_config = snd_hda_check_board_config(codec, alc883_cfg_tbl); 5851 board_config = snd_hda_check_board_config(codec, ALC883_MODEL_LAST,
5281 if (board_config < 0 || board_config >= ALC883_MODEL_LAST) { 5852 alc883_models,
5853 alc883_cfg_tbl);
5854 if (board_config < 0) {
5282 printk(KERN_INFO "hda_codec: Unknown model for ALC883, " 5855 printk(KERN_INFO "hda_codec: Unknown model for ALC883, "
5283 "trying auto-probe from BIOS...\n"); 5856 "trying auto-probe from BIOS...\n");
5284 board_config = ALC883_AUTO; 5857 board_config = ALC883_AUTO;
@@ -5355,6 +5928,24 @@ static struct snd_kcontrol_new alc262_base_mixer[] = {
5355 { } /* end */ 5928 { } /* end */
5356}; 5929};
5357 5930
5931static struct snd_kcontrol_new alc262_hippo1_mixer[] = {
5932 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5933 HDA_CODEC_MUTE("Front Playback Switch", 0x14, 0x0, HDA_OUTPUT),
5934 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5935 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5936 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
5937 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
5938 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5939 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5940 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
5941 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
5942 /* HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
5943 HDA_CODEC_MUTE("PC Beelp Playback Switch", 0x0b, 0x05, HDA_INPUT), */
5944 /*HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0D, 0x0, HDA_OUTPUT),*/
5945 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5946 { } /* end */
5947};
5948
5358static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = { 5949static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
5359 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT), 5950 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5360 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT), 5951 HDA_CODEC_MUTE("Front Playback Switch", 0x15, 0x0, HDA_OUTPUT),
@@ -5377,6 +5968,30 @@ static struct snd_kcontrol_new alc262_HP_BPC_mixer[] = {
5377 { } /* end */ 5968 { } /* end */
5378}; 5969};
5379 5970
5971static struct snd_kcontrol_new alc262_HP_BPC_WildWest_mixer[] = {
5972 HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
5973 HDA_CODEC_MUTE("Front Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
5974 HDA_CODEC_VOLUME("Headphone Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
5975 HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
5976 HDA_CODEC_VOLUME_MONO("Mono Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
5977 HDA_CODEC_MUTE_MONO("Mono Playback Switch", 0x16, 2, 0x0, HDA_OUTPUT),
5978 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x02, HDA_INPUT),
5979 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x02, HDA_INPUT),
5980 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x01, HDA_INPUT),
5981 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x01, HDA_INPUT),
5982 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
5983 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
5984 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x0b, 0x05, HDA_INPUT),
5985 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x0b, 0x05, HDA_INPUT),
5986 { } /* end */
5987};
5988
5989static struct snd_kcontrol_new alc262_HP_BPC_WildWest_option_mixer[] = {
5990 HDA_CODEC_VOLUME("Rear Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
5991 HDA_CODEC_MUTE("Rear Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
5992 { } /* end */
5993};
5994
5380#define alc262_capture_mixer alc882_capture_mixer 5995#define alc262_capture_mixer alc882_capture_mixer
5381#define alc262_capture_alt_mixer alc882_capture_alt_mixer 5996#define alc262_capture_alt_mixer alc882_capture_alt_mixer
5382 5997
@@ -5459,6 +6074,103 @@ static struct hda_verb alc262_init_verbs[] = {
5459 { } 6074 { }
5460}; 6075};
5461 6076
6077static struct hda_verb alc262_hippo_unsol_verbs[] = {
6078 {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6079 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6080 {}
6081};
6082
6083static struct hda_verb alc262_hippo1_unsol_verbs[] = {
6084 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0},
6085 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
6086 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, 0x0000},
6087
6088 {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
6089 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
6090 {}
6091};
6092
6093/* mute/unmute internal speaker according to the hp jack and mute state */
6094static void alc262_hippo_automute(struct hda_codec *codec, int force)
6095{
6096 struct alc_spec *spec = codec->spec;
6097 unsigned int mute;
6098
6099 if (force || ! spec->sense_updated) {
6100 unsigned int present;
6101 /* need to execute and sync at first */
6102 snd_hda_codec_read(codec, 0x15, 0, AC_VERB_SET_PIN_SENSE, 0);
6103 present = snd_hda_codec_read(codec, 0x15, 0,
6104 AC_VERB_GET_PIN_SENSE, 0);
6105 spec->jack_present = (present & 0x80000000) != 0;
6106 spec->sense_updated = 1;
6107 }
6108 if (spec->jack_present) {
6109 /* mute internal speaker */
6110 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6111 0x80, 0x80);
6112 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6113 0x80, 0x80);
6114 } else {
6115 /* unmute internal speaker if necessary */
6116 mute = snd_hda_codec_amp_read(codec, 0x15, 0, HDA_OUTPUT, 0);
6117 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6118 0x80, mute & 0x80);
6119 mute = snd_hda_codec_amp_read(codec, 0x15, 1, HDA_OUTPUT, 0);
6120 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6121 0x80, mute & 0x80);
6122 }
6123}
6124
6125/* unsolicited event for HP jack sensing */
6126static void alc262_hippo_unsol_event(struct hda_codec *codec,
6127 unsigned int res)
6128{
6129 if ((res >> 26) != ALC880_HP_EVENT)
6130 return;
6131 alc262_hippo_automute(codec, 1);
6132}
6133
6134static void alc262_hippo1_automute(struct hda_codec *codec, int force)
6135{
6136 struct alc_spec *spec = codec->spec;
6137 unsigned int mute;
6138
6139 if (force || ! spec->sense_updated) {
6140 unsigned int present;
6141 /* need to execute and sync at first */
6142 snd_hda_codec_read(codec, 0x1b, 0, AC_VERB_SET_PIN_SENSE, 0);
6143 present = snd_hda_codec_read(codec, 0x1b, 0,
6144 AC_VERB_GET_PIN_SENSE, 0);
6145 spec->jack_present = (present & 0x80000000) != 0;
6146 spec->sense_updated = 1;
6147 }
6148 if (spec->jack_present) {
6149 /* mute internal speaker */
6150 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6151 0x80, 0x80);
6152 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6153 0x80, 0x80);
6154 } else {
6155 /* unmute internal speaker if necessary */
6156 mute = snd_hda_codec_amp_read(codec, 0x1b, 0, HDA_OUTPUT, 0);
6157 snd_hda_codec_amp_update(codec, 0x14, 0, HDA_OUTPUT, 0,
6158 0x80, mute & 0x80);
6159 mute = snd_hda_codec_amp_read(codec, 0x1b, 1, HDA_OUTPUT, 0);
6160 snd_hda_codec_amp_update(codec, 0x14, 1, HDA_OUTPUT, 0,
6161 0x80, mute & 0x80);
6162 }
6163}
6164
6165/* unsolicited event for HP jack sensing */
6166static void alc262_hippo1_unsol_event(struct hda_codec *codec,
6167 unsigned int res)
6168{
6169 if ((res >> 26) != ALC880_HP_EVENT)
6170 return;
6171 alc262_hippo1_automute(codec, 1);
6172}
6173
5462/* 6174/*
5463 * fujitsu model 6175 * fujitsu model
5464 * 0x14 = headphone/spdif-out, 0x15 = internal speaker 6176 * 0x14 = headphone/spdif-out, 0x15 = internal speaker
@@ -5809,6 +6521,100 @@ static struct hda_verb alc262_HP_BPC_init_verbs[] = {
5809 { } 6521 { }
5810}; 6522};
5811 6523
6524static struct hda_verb alc262_HP_BPC_WildWest_init_verbs[] = {
6525 /*
6526 * Unmute ADC0-2 and set the default input to mic-in
6527 */
6528 {0x07, AC_VERB_SET_CONNECT_SEL, 0x00},
6529 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6530 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
6531 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6532 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
6533 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6534
6535 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
6536 * mixer widget
6537 * Note: PASD motherboards uses the Line In 2 as the input for front
6538 * panel mic (mic 2)
6539 */
6540 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
6541 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6542 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6543 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
6544 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
6545 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
6546 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
6547 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
6548 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(7)},
6549 /*
6550 * Set up output mixers (0x0c - 0x0e)
6551 */
6552 /* set vol=0 to output mixers */
6553 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6554 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6555 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
6556
6557 /* set up input amps for analog loopback */
6558 /* Amp Indices: DAC = 0, mixer = 1 */
6559 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6560 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6561 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6562 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6563 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
6564 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
6565
6566
6567 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP }, /* HP */
6568 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Mono */
6569 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* rear MIC */
6570 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* Line in */
6571 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 }, /* Front MIC */
6572 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, /* Line out */
6573 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN }, /* CD in */
6574
6575 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6576 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
6577
6578 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
6579 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
6580
6581 /* {0x14, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 }, */
6582 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
6583 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
6584 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, 0x7023 },
6585 {0x1c, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
6586 {0x1d, AC_VERB_SET_AMP_GAIN_MUTE, 0x7000 },
6587
6588 /* FIXME: use matrix-type input source selection */
6589 /* Mixer elements: 0x18, 19, 1a, 1b, 1c, 1d, 14, 15, 16, 17, 0b */
6590 /* Input mixer1: unmute Mic, F-Mic, Line, CD inputs */
6591 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))}, /*rear MIC*/
6592 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))}, /*Line in*/
6593 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))}, /*F MIC*/
6594 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))}, /*Front*/
6595 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))}, /*CD*/
6596 /* {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
6597 {0x24, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))}, /*HP*/
6598 /* Input mixer2 */
6599 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6600 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6601 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
6602 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
6603 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
6604 /* {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
6605 {0x23, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
6606 /* Input mixer3 */
6607 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x00 << 8))},
6608 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8))},
6609 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8))},
6610 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x03 << 8))},
6611 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x04 << 8))},
6612 /* {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x06 << 8))}, */
6613 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x07 << 8))},
6614
6615 { }
6616};
6617
5812/* pcm configuration: identiacal with ALC880 */ 6618/* pcm configuration: identiacal with ALC880 */
5813#define alc262_pcm_analog_playback alc880_pcm_analog_playback 6619#define alc262_pcm_analog_playback alc880_pcm_analog_playback
5814#define alc262_pcm_analog_capture alc880_pcm_analog_capture 6620#define alc262_pcm_analog_capture alc880_pcm_analog_capture
@@ -5866,26 +6672,35 @@ static void alc262_auto_init(struct hda_codec *codec)
5866/* 6672/*
5867 * configuration and preset 6673 * configuration and preset
5868 */ 6674 */
5869static struct hda_board_config alc262_cfg_tbl[] = { 6675static const char *alc262_models[ALC262_MODEL_LAST] = {
5870 { .modelname = "basic", .config = ALC262_BASIC }, 6676 [ALC262_BASIC] = "basic",
5871 { .modelname = "fujitsu", .config = ALC262_FUJITSU }, 6677 [ALC262_HIPPO] = "hippo",
5872 { .pci_subvendor = 0x10cf, .pci_subdevice = 0x1397, 6678 [ALC262_HIPPO_1] = "hippo_1",
5873 .config = ALC262_FUJITSU }, 6679 [ALC262_FUJITSU] = "fujitsu",
5874 { .modelname = "hp-bpc", .config = ALC262_HP_BPC }, 6680 [ALC262_HP_BPC] = "hp-bpc",
5875 { .pci_subvendor = 0x103c, .pci_subdevice = 0x280c, 6681 [ALC262_HP_BPC_D7000_WL]= "hp-bpc-d7000",
5876 .config = ALC262_HP_BPC }, /* xw4400 */ 6682 [ALC262_BENQ_ED8] = "benq",
5877 { .pci_subvendor = 0x103c, .pci_subdevice = 0x2801, 6683 [ALC262_AUTO] = "auto",
5878 .config = ALC262_HP_BPC }, /* q965 */ 6684};
5879 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3014, 6685
5880 .config = ALC262_HP_BPC }, /* xw6400 */ 6686static struct snd_pci_quirk alc262_cfg_tbl[] = {
5881 { .pci_subvendor = 0x103c, .pci_subdevice = 0x3015, 6687 SND_PCI_QUIRK(0x1002, 0x437b, "Hippo", ALC262_HIPPO),
5882 .config = ALC262_HP_BPC }, /* xw8400 */ 6688 SND_PCI_QUIRK(0x103c, 0x12fe, "HP xw9400", ALC262_HP_BPC),
5883 { .pci_subvendor = 0x103c, .pci_subdevice = 0x12fe, 6689 SND_PCI_QUIRK(0x103c, 0x280c, "HP xw4400", ALC262_HP_BPC),
5884 .config = ALC262_HP_BPC }, /* xw9400 */ 6690 SND_PCI_QUIRK(0x103c, 0x3014, "HP xw6400", ALC262_HP_BPC),
5885 { .modelname = "benq", .config = ALC262_BENQ_ED8 }, 6691 SND_PCI_QUIRK(0x103c, 0x3015, "HP xw8400", ALC262_HP_BPC),
5886 { .pci_subvendor = 0x17ff, .pci_subdevice = 0x0560, 6692 SND_PCI_QUIRK(0x103c, 0x2800, "HP D7000", ALC262_HP_BPC_D7000_WL),
5887 .config = ALC262_BENQ_ED8 }, 6693 SND_PCI_QUIRK(0x103c, 0x2802, "HP D7000", ALC262_HP_BPC_D7000_WL),
5888 { .modelname = "auto", .config = ALC262_AUTO }, 6694 SND_PCI_QUIRK(0x103c, 0x2804, "HP D7000", ALC262_HP_BPC_D7000_WL),
6695 SND_PCI_QUIRK(0x103c, 0x2806, "HP D7000", ALC262_HP_BPC_D7000_WL),
6696 SND_PCI_QUIRK(0x103c, 0x2801, "HP D7000", ALC262_HP_BPC_D7000_WF),
6697 SND_PCI_QUIRK(0x103c, 0x2803, "HP D7000", ALC262_HP_BPC_D7000_WF),
6698 SND_PCI_QUIRK(0x103c, 0x2805, "HP D7000", ALC262_HP_BPC_D7000_WF),
6699 SND_PCI_QUIRK(0x103c, 0x2807, "HP D7000", ALC262_HP_BPC_D7000_WF),
6700 SND_PCI_QUIRK(0x104d, 0x8203, "Sony UX-90", ALC262_HIPPO),
6701 SND_PCI_QUIRK(0x10cf, 0x1397, "Fujitsu", ALC262_FUJITSU),
6702 SND_PCI_QUIRK(0x17ff, 0x058f, "Benq Hippo", ALC262_HIPPO_1),
6703 SND_PCI_QUIRK(0x17ff, 0x0560, "Benq ED8", ALC262_BENQ_ED8),
5889 {} 6704 {}
5890}; 6705};
5891 6706
@@ -5900,6 +6715,30 @@ static struct alc_config_preset alc262_presets[] = {
5900 .channel_mode = alc262_modes, 6715 .channel_mode = alc262_modes,
5901 .input_mux = &alc262_capture_source, 6716 .input_mux = &alc262_capture_source,
5902 }, 6717 },
6718 [ALC262_HIPPO] = {
6719 .mixers = { alc262_base_mixer },
6720 .init_verbs = { alc262_init_verbs, alc262_hippo_unsol_verbs},
6721 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
6722 .dac_nids = alc262_dac_nids,
6723 .hp_nid = 0x03,
6724 .dig_out_nid = ALC262_DIGOUT_NID,
6725 .num_channel_mode = ARRAY_SIZE(alc262_modes),
6726 .channel_mode = alc262_modes,
6727 .input_mux = &alc262_capture_source,
6728 .unsol_event = alc262_hippo_unsol_event,
6729 },
6730 [ALC262_HIPPO_1] = {
6731 .mixers = { alc262_hippo1_mixer },
6732 .init_verbs = { alc262_init_verbs, alc262_hippo1_unsol_verbs},
6733 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
6734 .dac_nids = alc262_dac_nids,
6735 .hp_nid = 0x02,
6736 .dig_out_nid = ALC262_DIGOUT_NID,
6737 .num_channel_mode = ARRAY_SIZE(alc262_modes),
6738 .channel_mode = alc262_modes,
6739 .input_mux = &alc262_capture_source,
6740 .unsol_event = alc262_hippo1_unsol_event,
6741 },
5903 [ALC262_FUJITSU] = { 6742 [ALC262_FUJITSU] = {
5904 .mixers = { alc262_fujitsu_mixer }, 6743 .mixers = { alc262_fujitsu_mixer },
5905 .init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs }, 6744 .init_verbs = { alc262_init_verbs, alc262_fujitsu_unsol_verbs },
@@ -5922,6 +6761,27 @@ static struct alc_config_preset alc262_presets[] = {
5922 .channel_mode = alc262_modes, 6761 .channel_mode = alc262_modes,
5923 .input_mux = &alc262_HP_capture_source, 6762 .input_mux = &alc262_HP_capture_source,
5924 }, 6763 },
6764 [ALC262_HP_BPC_D7000_WF] = {
6765 .mixers = { alc262_HP_BPC_WildWest_mixer },
6766 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
6767 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
6768 .dac_nids = alc262_dac_nids,
6769 .hp_nid = 0x03,
6770 .num_channel_mode = ARRAY_SIZE(alc262_modes),
6771 .channel_mode = alc262_modes,
6772 .input_mux = &alc262_HP_capture_source,
6773 },
6774 [ALC262_HP_BPC_D7000_WL] = {
6775 .mixers = { alc262_HP_BPC_WildWest_mixer,
6776 alc262_HP_BPC_WildWest_option_mixer },
6777 .init_verbs = { alc262_HP_BPC_WildWest_init_verbs },
6778 .num_dacs = ARRAY_SIZE(alc262_dac_nids),
6779 .dac_nids = alc262_dac_nids,
6780 .hp_nid = 0x03,
6781 .num_channel_mode = ARRAY_SIZE(alc262_modes),
6782 .channel_mode = alc262_modes,
6783 .input_mux = &alc262_HP_capture_source,
6784 },
5925 [ALC262_BENQ_ED8] = { 6785 [ALC262_BENQ_ED8] = {
5926 .mixers = { alc262_base_mixer }, 6786 .mixers = { alc262_base_mixer },
5927 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs }, 6787 .init_verbs = { alc262_init_verbs, alc262_EAPD_verbs },
@@ -5940,7 +6800,7 @@ static int patch_alc262(struct hda_codec *codec)
5940 int board_config; 6800 int board_config;
5941 int err; 6801 int err;
5942 6802
5943 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); 6803 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
5944 if (spec == NULL) 6804 if (spec == NULL)
5945 return -ENOMEM; 6805 return -ENOMEM;
5946 6806
@@ -5956,9 +6816,11 @@ static int patch_alc262(struct hda_codec *codec)
5956 } 6816 }
5957#endif 6817#endif
5958 6818
5959 board_config = snd_hda_check_board_config(codec, alc262_cfg_tbl); 6819 board_config = snd_hda_check_board_config(codec, ALC262_MODEL_LAST,
5960 6820 alc262_models,
5961 if (board_config < 0 || board_config >= ALC262_MODEL_LAST) { 6821 alc262_cfg_tbl);
6822
6823 if (board_config < 0) {
5962 printk(KERN_INFO "hda_codec: Unknown model for ALC262, " 6824 printk(KERN_INFO "hda_codec: Unknown model for ALC262, "
5963 "trying auto-probe from BIOS...\n"); 6825 "trying auto-probe from BIOS...\n");
5964 board_config = ALC262_AUTO; 6826 board_config = ALC262_AUTO;
@@ -6078,6 +6940,44 @@ static struct hda_channel_mode alc861_uniwill_m31_modes[2] = {
6078 { 4, alc861_uniwill_m31_ch4_init }, 6940 { 4, alc861_uniwill_m31_ch4_init },
6079}; 6941};
6080 6942
6943/* Set mic1 and line-in as input and unmute the mixer */
6944static struct hda_verb alc861_asus_ch2_init[] = {
6945 /* set pin widget 1Ah (line in) for input */
6946 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
6947 /* set pin widget 18h (mic1/2) for input, for mic also enable the vref */
6948 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
6949
6950 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c },
6951#if 0
6952 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x01 << 8)) }, /*mic*/
6953 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7000 | (0x02 << 8)) }, /*line-in*/
6954#endif
6955 { } /* end */
6956};
6957/* Set mic1 nad line-in as output and mute mixer */
6958static struct hda_verb alc861_asus_ch6_init[] = {
6959 /* set pin widget 1Ah (line in) for output (Back Surround)*/
6960 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6961 /* { 0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
6962 /* set pin widget 18h (mic1) for output (CLFE)*/
6963 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
6964 /* { 0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE }, */
6965 { 0x0c, AC_VERB_SET_CONNECT_SEL, 0x00 },
6966 { 0x0d, AC_VERB_SET_CONNECT_SEL, 0x00 },
6967
6968 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb080 },
6969#if 0
6970 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x01 << 8)) }, /*mic*/
6971 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, (0x7080 | (0x02 << 8)) }, /*line in*/
6972#endif
6973 { } /* end */
6974};
6975
6976static struct hda_channel_mode alc861_asus_modes[2] = {
6977 { 2, alc861_asus_ch2_init },
6978 { 6, alc861_asus_ch6_init },
6979};
6980
6081/* patch-ALC861 */ 6981/* patch-ALC861 */
6082 6982
6083static struct snd_kcontrol_new alc861_base_mixer[] = { 6983static struct snd_kcontrol_new alc861_base_mixer[] = {
@@ -6154,7 +7054,29 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = {
6154 .private_value = ARRAY_SIZE(alc861_threestack_modes), 7054 .private_value = ARRAY_SIZE(alc861_threestack_modes),
6155 }, 7055 },
6156 { } /* end */ 7056 { } /* end */
6157}; 7057};
7058
7059static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
7060 /* output mixer control */
7061 HDA_CODEC_MUTE("Master Playback Switch", 0x03, 0x0, HDA_OUTPUT),
7062 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
7063 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
7064
7065 /*Capture mixer control */
7066 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7067 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7068 {
7069 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7070 .name = "Capture Source",
7071 .count = 1,
7072 .info = alc_mux_enum_info,
7073 .get = alc_mux_enum_get,
7074 .put = alc_mux_enum_put,
7075 },
7076
7077 { } /* end */
7078};
7079
6158static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = { 7080static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
6159 /* output mixer control */ 7081 /* output mixer control */
6160 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT), 7082 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
@@ -6196,7 +7118,58 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
6196 }, 7118 },
6197 { } /* end */ 7119 { } /* end */
6198}; 7120};
6199 7121
7122static struct snd_kcontrol_new alc861_asus_mixer[] = {
7123 /* output mixer control */
7124 HDA_CODEC_MUTE("Front Playback Switch", 0x03, 0x0, HDA_OUTPUT),
7125 HDA_CODEC_MUTE("Surround Playback Switch", 0x06, 0x0, HDA_OUTPUT),
7126 HDA_CODEC_MUTE_MONO("Center Playback Switch", 0x05, 1, 0x0, HDA_OUTPUT),
7127 HDA_CODEC_MUTE_MONO("LFE Playback Switch", 0x05, 2, 0x0, HDA_OUTPUT),
7128 HDA_CODEC_MUTE("Side Playback Switch", 0x04, 0x0, HDA_OUTPUT),
7129
7130 /* Input mixer control */
7131 HDA_CODEC_VOLUME("Input Playback Volume", 0x15, 0x0, HDA_OUTPUT),
7132 HDA_CODEC_MUTE("Input Playback Switch", 0x15, 0x0, HDA_OUTPUT),
7133 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
7134 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
7135 HDA_CODEC_VOLUME("Line Playback Volume", 0x15, 0x02, HDA_INPUT),
7136 HDA_CODEC_MUTE("Line Playback Switch", 0x15, 0x02, HDA_INPUT),
7137 HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
7138 HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
7139 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
7140 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT), /* was HDA_INPUT (why?) */
7141
7142 /* Capture mixer control */
7143 HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
7144 HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
7145 {
7146 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7147 .name = "Capture Source",
7148 .count = 1,
7149 .info = alc_mux_enum_info,
7150 .get = alc_mux_enum_get,
7151 .put = alc_mux_enum_put,
7152 },
7153 {
7154 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
7155 .name = "Channel Mode",
7156 .info = alc_ch_mode_info,
7157 .get = alc_ch_mode_get,
7158 .put = alc_ch_mode_put,
7159 .private_value = ARRAY_SIZE(alc861_asus_modes),
7160 },
7161 { }
7162};
7163
7164/* additional mixer */
7165static struct snd_kcontrol_new alc861_asus_laptop_mixer[] = {
7166 HDA_CODEC_VOLUME("CD Playback Volume", 0x15, 0x0, HDA_INPUT),
7167 HDA_CODEC_MUTE("CD Playback Switch", 0x15, 0x0, HDA_INPUT),
7168 HDA_CODEC_VOLUME("PC Beep Playback Volume", 0x23, 0x0, HDA_OUTPUT),
7169 HDA_CODEC_MUTE("PC Beep Playback Switch", 0x23, 0x0, HDA_OUTPUT),
7170 { }
7171};
7172
6200/* 7173/*
6201 * generic initialization of ADC, input mixers and output mixers 7174 * generic initialization of ADC, input mixers and output mixers
6202 */ 7175 */
@@ -6217,7 +7190,7 @@ static struct hda_verb alc861_base_init_verbs[] = {
6217 /* port-E for HP out (front panel) */ 7190 /* port-E for HP out (front panel) */
6218 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 7191 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
6219 /* route front PCM to HP */ 7192 /* route front PCM to HP */
6220 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 }, 7193 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
6221 /* port-F for mic-in (front panel) with vref */ 7194 /* port-F for mic-in (front panel) with vref */
6222 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 7195 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
6223 /* port-G for CLFE (rear panel) */ 7196 /* port-G for CLFE (rear panel) */
@@ -6281,7 +7254,7 @@ static struct hda_verb alc861_threestack_init_verbs[] = {
6281 /* port-E for HP out (front panel) */ 7254 /* port-E for HP out (front panel) */
6282 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, 7255 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 },
6283 /* route front PCM to HP */ 7256 /* route front PCM to HP */
6284 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 }, 7257 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
6285 /* port-F for mic-in (front panel) with vref */ 7258 /* port-F for mic-in (front panel) with vref */
6286 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 7259 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
6287 /* port-G for CLFE (rear panel) */ 7260 /* port-G for CLFE (rear panel) */
@@ -6341,7 +7314,7 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
6341 /* port-E for HP out (front panel) */ 7314 /* port-E for HP out (front panel) */
6342 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80 7315 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, // this has to be set to VREF80
6343 /* route front PCM to HP */ 7316 /* route front PCM to HP */
6344 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x01 }, 7317 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
6345 /* port-F for mic-in (front panel) with vref */ 7318 /* port-F for mic-in (front panel) with vref */
6346 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, 7319 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
6347 /* port-G for CLFE (rear panel) */ 7320 /* port-G for CLFE (rear panel) */
@@ -6385,6 +7358,74 @@ static struct hda_verb alc861_uniwill_m31_init_verbs[] = {
6385 { } 7358 { }
6386}; 7359};
6387 7360
7361static struct hda_verb alc861_asus_init_verbs[] = {
7362 /*
7363 * Unmute ADC0 and set the default input to mic-in
7364 */
7365 /* port-A for surround (rear panel) | according to codec#0 this is the HP jack*/
7366 { 0x0e, AC_VERB_SET_PIN_WIDGET_CONTROL, 0xc0 }, /* was 0x00 */
7367 /* route front PCM to HP */
7368 { 0x0e, AC_VERB_SET_CONNECT_SEL, 0x01 },
7369 /* port-B for mic-in (rear panel) with vref */
7370 { 0x0d, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7371 /* port-C for line-in (rear panel) */
7372 { 0x0c, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7373 /* port-D for Front */
7374 { 0x0b, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7375 { 0x0b, AC_VERB_SET_CONNECT_SEL, 0x00 },
7376 /* port-E for HP out (front panel) */
7377 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 }, /* this has to be set to VREF80 */
7378 /* route front PCM to HP */
7379 { 0x0f, AC_VERB_SET_CONNECT_SEL, 0x00 },
7380 /* port-F for mic-in (front panel) with vref */
7381 { 0x10, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x24 },
7382 /* port-G for CLFE (rear panel) */
7383 { 0x1f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7384 /* port-H for side (rear panel) */
7385 { 0x20, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40 },
7386 /* CD-in */
7387 { 0x11, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x20 },
7388 /* route front mic to ADC1*/
7389 {0x08, AC_VERB_SET_CONNECT_SEL, 0x00},
7390 {0x08, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7391 /* Unmute DAC0~3 & spdif out*/
7392 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7393 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7394 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7395 {0x06, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7396 {0x07, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
7397 /* Unmute Mixer 14 (mic) 1c (Line in)*/
7398 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7399 {0x014, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7400 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7401 {0x01c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7402
7403 /* Unmute Stereo Mixer 15 */
7404 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7405 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7406 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7407 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, 0xb00c }, /* Output 0~12 step */
7408
7409 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7410 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7411 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7412 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7413 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7414 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7415 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
7416 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
7417 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)}, /* hp used DAC 3 (Front) */
7418 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
7419 { }
7420};
7421
7422/* additional init verbs for ASUS laptops */
7423static struct hda_verb alc861_asus_laptop_init_verbs[] = {
7424 { 0x0f, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x45 }, /* HP-out */
7425 { 0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(2) }, /* mute line-in */
7426 { }
7427};
7428
6388/* 7429/*
6389 * generic initialization of ADC, input mixers and output mixers 7430 * generic initialization of ADC, input mixers and output mixers
6390 */ 7431 */
@@ -6437,6 +7478,39 @@ static struct hda_verb alc861_auto_init_verbs[] = {
6437 { } 7478 { }
6438}; 7479};
6439 7480
7481static struct hda_verb alc861_toshiba_init_verbs[] = {
7482 {0x0f, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_HP_EVENT},
7483
7484 { }
7485};
7486
7487/* toggle speaker-output according to the hp-jack state */
7488static void alc861_toshiba_automute(struct hda_codec *codec)
7489{
7490 unsigned int present;
7491
7492 present = snd_hda_codec_read(codec, 0x0f, 0,
7493 AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
7494 snd_hda_codec_amp_update(codec, 0x16, 0, HDA_INPUT, 0,
7495 0x80, present ? 0x80 : 0);
7496 snd_hda_codec_amp_update(codec, 0x16, 1, HDA_INPUT, 0,
7497 0x80, present ? 0x80 : 0);
7498 snd_hda_codec_amp_update(codec, 0x1a, 0, HDA_INPUT, 3,
7499 0x80, present ? 0 : 0x80);
7500 snd_hda_codec_amp_update(codec, 0x1a, 1, HDA_INPUT, 3,
7501 0x80, present ? 0 : 0x80);
7502}
7503
7504static void alc861_toshiba_unsol_event(struct hda_codec *codec,
7505 unsigned int res)
7506{
7507 /* Looks like the unsol event is incompatible with the standard
7508 * definition. 6bit tag is placed at 26 bit!
7509 */
7510 if ((res >> 26) == ALC880_HP_EVENT)
7511 alc861_toshiba_automute(codec);
7512}
7513
6440/* pcm configuration: identiacal with ALC880 */ 7514/* pcm configuration: identiacal with ALC880 */
6441#define alc861_pcm_analog_playback alc880_pcm_analog_playback 7515#define alc861_pcm_analog_playback alc880_pcm_analog_playback
6442#define alc861_pcm_analog_capture alc880_pcm_analog_capture 7516#define alc861_pcm_analog_capture alc880_pcm_analog_capture
@@ -6710,19 +7784,29 @@ static void alc861_auto_init(struct hda_codec *codec)
6710/* 7784/*
6711 * configuration and preset 7785 * configuration and preset
6712 */ 7786 */
6713static struct hda_board_config alc861_cfg_tbl[] = { 7787static const char *alc861_models[ALC861_MODEL_LAST] = {
6714 { .modelname = "3stack", .config = ALC861_3ST }, 7788 [ALC861_3ST] = "3stack",
6715 { .pci_subvendor = 0x8086, .pci_subdevice = 0xd600, 7789 [ALC660_3ST] = "3stack-660",
6716 .config = ALC861_3ST }, 7790 [ALC861_3ST_DIG] = "3stack-dig",
6717 { .modelname = "3stack-660", .config = ALC660_3ST }, 7791 [ALC861_6ST_DIG] = "6stack-dig",
6718 { .pci_subvendor = 0x1043, .pci_subdevice = 0x81e7, 7792 [ALC861_UNIWILL_M31] = "uniwill-m31",
6719 .config = ALC660_3ST }, 7793 [ALC861_TOSHIBA] = "toshiba",
6720 { .modelname = "3stack-dig", .config = ALC861_3ST_DIG }, 7794 [ALC861_ASUS] = "asus",
6721 { .modelname = "6stack-dig", .config = ALC861_6ST_DIG }, 7795 [ALC861_ASUS_LAPTOP] = "asus-laptop",
6722 { .modelname = "uniwill-m31", .config = ALC861_UNIWILL_M31}, 7796 [ALC861_AUTO] = "auto",
6723 { .pci_subvendor = 0x1584, .pci_subdevice = 0x9072, 7797};
6724 .config = ALC861_UNIWILL_M31 }, 7798
6725 { .modelname = "auto", .config = ALC861_AUTO }, 7799static struct snd_pci_quirk alc861_cfg_tbl[] = {
7800 SND_PCI_QUIRK(0x1043, 0x1205, "ASUS W7J", ALC861_3ST),
7801 SND_PCI_QUIRK(0x1043, 0x1335, "ASUS F2/3", ALC861_ASUS_LAPTOP),
7802 SND_PCI_QUIRK(0x1043, 0x1338, "ASUS F2/3", ALC861_ASUS_LAPTOP),
7803 SND_PCI_QUIRK(0x1043, 0x1393, "ASUS", ALC861_ASUS),
7804 SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660_3ST),
7805 SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba", ALC861_TOSHIBA),
7806 SND_PCI_QUIRK(0x1179, 0xff10, "Toshiba", ALC861_TOSHIBA),
7807 SND_PCI_QUIRK(0x1584, 0x9072, "Uniwill m31", ALC861_UNIWILL_M31),
7808 SND_PCI_QUIRK(0x1584, 0x2b01, "Uniwill X40AIx", ALC861_UNIWILL_M31),
7809 SND_PCI_QUIRK(0x8086, 0xd600, "Intel", ALC861_3ST),
6726 {} 7810 {}
6727}; 7811};
6728 7812
@@ -6789,8 +7873,48 @@ static struct alc_config_preset alc861_presets[] = {
6789 .adc_nids = alc861_adc_nids, 7873 .adc_nids = alc861_adc_nids,
6790 .input_mux = &alc861_capture_source, 7874 .input_mux = &alc861_capture_source,
6791 }, 7875 },
6792 7876 [ALC861_TOSHIBA] = {
6793}; 7877 .mixers = { alc861_toshiba_mixer },
7878 .init_verbs = { alc861_base_init_verbs, alc861_toshiba_init_verbs },
7879 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
7880 .dac_nids = alc861_dac_nids,
7881 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
7882 .channel_mode = alc883_3ST_2ch_modes,
7883 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7884 .adc_nids = alc861_adc_nids,
7885 .input_mux = &alc861_capture_source,
7886 .unsol_event = alc861_toshiba_unsol_event,
7887 .init_hook = alc861_toshiba_automute,
7888 },
7889 [ALC861_ASUS] = {
7890 .mixers = { alc861_asus_mixer },
7891 .init_verbs = { alc861_asus_init_verbs },
7892 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
7893 .dac_nids = alc861_dac_nids,
7894 .dig_out_nid = ALC861_DIGOUT_NID,
7895 .num_channel_mode = ARRAY_SIZE(alc861_asus_modes),
7896 .channel_mode = alc861_asus_modes,
7897 .need_dac_fix = 1,
7898 .hp_nid = 0x06,
7899 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7900 .adc_nids = alc861_adc_nids,
7901 .input_mux = &alc861_capture_source,
7902 },
7903 [ALC861_ASUS_LAPTOP] = {
7904 .mixers = { alc861_toshiba_mixer, alc861_asus_laptop_mixer },
7905 .init_verbs = { alc861_asus_init_verbs,
7906 alc861_asus_laptop_init_verbs },
7907 .num_dacs = ARRAY_SIZE(alc861_dac_nids),
7908 .dac_nids = alc861_dac_nids,
7909 .dig_out_nid = ALC861_DIGOUT_NID,
7910 .num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
7911 .channel_mode = alc883_3ST_2ch_modes,
7912 .need_dac_fix = 1,
7913 .num_adc_nids = ARRAY_SIZE(alc861_adc_nids),
7914 .adc_nids = alc861_adc_nids,
7915 .input_mux = &alc861_capture_source,
7916 },
7917};
6794 7918
6795 7919
6796static int patch_alc861(struct hda_codec *codec) 7920static int patch_alc861(struct hda_codec *codec)
@@ -6799,15 +7923,17 @@ static int patch_alc861(struct hda_codec *codec)
6799 int board_config; 7923 int board_config;
6800 int err; 7924 int err;
6801 7925
6802 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL); 7926 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
6803 if (spec == NULL) 7927 if (spec == NULL)
6804 return -ENOMEM; 7928 return -ENOMEM;
6805 7929
6806 codec->spec = spec; 7930 codec->spec = spec;
6807 7931
6808 board_config = snd_hda_check_board_config(codec, alc861_cfg_tbl); 7932 board_config = snd_hda_check_board_config(codec, ALC861_MODEL_LAST,
7933 alc861_models,
7934 alc861_cfg_tbl);
6809 7935
6810 if (board_config < 0 || board_config >= ALC861_MODEL_LAST) { 7936 if (board_config < 0) {
6811 printk(KERN_INFO "hda_codec: Unknown model for ALC861, " 7937 printk(KERN_INFO "hda_codec: Unknown model for ALC861, "
6812 "trying auto-probe from BIOS...\n"); 7938 "trying auto-probe from BIOS...\n");
6813 board_config = ALC861_AUTO; 7939 board_config = ALC861_AUTO;
@@ -6846,19 +7972,706 @@ static int patch_alc861(struct hda_codec *codec)
6846} 7972}
6847 7973
6848/* 7974/*
7975 * ALC861-VD support
7976 *
7977 * Based on ALC882
7978 *
7979 * In addition, an independent DAC
7980 */
7981#define ALC861VD_DIGOUT_NID 0x06
7982
7983static hda_nid_t alc861vd_dac_nids[4] = {
7984 /* front, surr, clfe, side surr */
7985 0x02, 0x03, 0x04, 0x05
7986};
7987
7988/* dac_nids for ALC660vd are in a different order - according to
7989 * Realtek's driver.
7990 * This should probably tesult in a different mixer for 6stack models
7991 * of ALC660vd codecs, but for now there is only 3stack mixer
7992 * - and it is the same as in 861vd.
7993 * adc_nids in ALC660vd are (is) the same as in 861vd
7994 */
7995static hda_nid_t alc660vd_dac_nids[3] = {
7996 /* front, rear, clfe, rear_surr */
7997 0x02, 0x04, 0x03
7998};
7999
8000static hda_nid_t alc861vd_adc_nids[1] = {
8001 /* ADC0 */
8002 0x09,
8003};
8004
8005/* input MUX */
8006/* FIXME: should be a matrix-type input source selection */
8007static struct hda_input_mux alc861vd_capture_source = {
8008 .num_items = 4,
8009 .items = {
8010 { "Mic", 0x0 },
8011 { "Front Mic", 0x1 },
8012 { "Line", 0x2 },
8013 { "CD", 0x4 },
8014 },
8015};
8016
8017#define alc861vd_mux_enum_info alc_mux_enum_info
8018#define alc861vd_mux_enum_get alc_mux_enum_get
8019
8020static int alc861vd_mux_enum_put(struct snd_kcontrol *kcontrol,
8021 struct snd_ctl_elem_value *ucontrol)
8022{
8023 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
8024 struct alc_spec *spec = codec->spec;
8025 const struct hda_input_mux *imux = spec->input_mux;
8026 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
8027 static hda_nid_t capture_mixers[1] = { 0x22 };
8028 hda_nid_t nid = capture_mixers[adc_idx];
8029 unsigned int *cur_val = &spec->cur_mux[adc_idx];
8030 unsigned int i, idx;
8031
8032 idx = ucontrol->value.enumerated.item[0];
8033 if (idx >= imux->num_items)
8034 idx = imux->num_items - 1;
8035 if (*cur_val == idx && ! codec->in_resume)
8036 return 0;
8037 for (i = 0; i < imux->num_items; i++) {
8038 unsigned int v = (i == idx) ? 0x7000 : 0x7080;
8039 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
8040 v | (imux->items[i].index << 8));
8041 }
8042 *cur_val = idx;
8043 return 1;
8044}
8045
8046/*
8047 * 2ch mode
8048 */
8049static struct hda_channel_mode alc861vd_3stack_2ch_modes[1] = {
8050 { 2, NULL }
8051};
8052
8053/*
8054 * 6ch mode
8055 */
8056static struct hda_verb alc861vd_6stack_ch6_init[] = {
8057 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00 },
8058 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8059 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8060 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8061 { } /* end */
8062};
8063
8064/*
8065 * 8ch mode
8066 */
8067static struct hda_verb alc861vd_6stack_ch8_init[] = {
8068 { 0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8069 { 0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8070 { 0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8071 { 0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
8072 { } /* end */
8073};
8074
8075static struct hda_channel_mode alc861vd_6stack_modes[2] = {
8076 { 6, alc861vd_6stack_ch6_init },
8077 { 8, alc861vd_6stack_ch8_init },
8078};
8079
8080static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
8081 {
8082 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8083 .name = "Channel Mode",
8084 .info = alc_ch_mode_info,
8085 .get = alc_ch_mode_get,
8086 .put = alc_ch_mode_put,
8087 },
8088 { } /* end */
8089};
8090
8091static struct snd_kcontrol_new alc861vd_capture_mixer[] = {
8092 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
8093 HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
8094
8095 {
8096 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
8097 /* The multiple "Capture Source" controls confuse alsamixer
8098 * So call somewhat different..
8099 *FIXME: the controls appear in the "playback" view!
8100 */
8101 /* .name = "Capture Source", */
8102 .name = "Input Source",
8103 .count = 1,
8104 .info = alc861vd_mux_enum_info,
8105 .get = alc861vd_mux_enum_get,
8106 .put = alc861vd_mux_enum_put,
8107 },
8108 { } /* end */
8109};
8110
8111/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
8112 * Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
8113 */
8114static struct snd_kcontrol_new alc861vd_6st_mixer[] = {
8115 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
8116 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8117
8118 HDA_CODEC_VOLUME("Surround Playback Volume", 0x03, 0x0, HDA_OUTPUT),
8119 HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
8120
8121 HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x04, 1, 0x0,
8122 HDA_OUTPUT),
8123 HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x04, 2, 0x0,
8124 HDA_OUTPUT),
8125 HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
8126 HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
8127
8128 HDA_CODEC_VOLUME("Side Playback Volume", 0x05, 0x0, HDA_OUTPUT),
8129 HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
8130
8131 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8132
8133 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8134 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8135 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8136
8137 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8138 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8139 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8140
8141 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8142 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8143
8144 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8145 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8146
8147 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
8148 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
8149
8150 { } /* end */
8151};
8152
8153static struct snd_kcontrol_new alc861vd_3st_mixer[] = {
8154 HDA_CODEC_VOLUME("Front Playback Volume", 0x02, 0x0, HDA_OUTPUT),
8155 HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
8156
8157 HDA_CODEC_MUTE("Headphone Playback Switch", 0x1b, 0x0, HDA_OUTPUT),
8158
8159 HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
8160 HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
8161 HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
8162
8163 HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
8164 HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
8165 HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
8166
8167 HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
8168 HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
8169
8170 HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
8171 HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
8172
8173 HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
8174 HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
8175
8176 { } /* end */
8177};
8178
8179/*
8180 * generic initialization of ADC, input mixers and output mixers
8181 */
8182static struct hda_verb alc861vd_volume_init_verbs[] = {
8183 /*
8184 * Unmute ADC0 and set the default input to mic-in
8185 */
8186 {0x09, AC_VERB_SET_CONNECT_SEL, 0x00},
8187 {0x09, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8188
8189 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of
8190 * the analog-loopback mixer widget
8191 */
8192 /* Amp Indices: Mic1 = 0, Mic2 = 1, Line1 = 2, Line2 = 3, CD = 4 */
8193 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
8194 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
8195 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
8196 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
8197 {0x0b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
8198
8199 /* Capture mixer: unmute Mic, F-Mic, Line, CD inputs */
8200 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
8201 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(5)},
8202 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(6)},
8203 {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(8)},
8204
8205 /*
8206 * Set up output mixers (0x02 - 0x05)
8207 */
8208 /* set vol=0 to output mixers */
8209 {0x02, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8210 {0x03, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8211 {0x04, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8212 {0x05, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
8213
8214 /* set up input amps for analog loopback */
8215 /* Amp Indices: DAC = 0, mixer = 1 */
8216 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8217 {0x0c, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8218 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8219 {0x0d, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8220 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8221 {0x0e, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8222 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
8223 {0x0f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(1)},
8224
8225 { }
8226};
8227
8228/*
8229 * 3-stack pin configuration:
8230 * front = 0x14, mic/clfe = 0x18, HP = 0x19, line/surr = 0x1a, f-mic = 0x1b
8231 */
8232static struct hda_verb alc861vd_3stack_init_verbs[] = {
8233 /*
8234 * Set pin mode and muting
8235 */
8236 /* set front pin widgets 0x14 for output */
8237 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8238 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8239 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8240
8241 /* Mic (rear) pin: input vref at 80% */
8242 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8243 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8244 /* Front Mic pin: input vref at 80% */
8245 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8246 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8247 /* Line In pin: input */
8248 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8249 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8250 /* Line-2 In: Headphone output (output 0 - 0x0c) */
8251 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8252 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8253 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
8254 /* CD pin widget for input */
8255 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8256
8257 { }
8258};
8259
8260/*
8261 * 6-stack pin configuration:
8262 */
8263static struct hda_verb alc861vd_6stack_init_verbs[] = {
8264 /*
8265 * Set pin mode and muting
8266 */
8267 /* set front pin widgets 0x14 for output */
8268 {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8269 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8270 {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
8271
8272 /* Rear Pin: output 1 (0x0d) */
8273 {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8274 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8275 {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
8276 /* CLFE Pin: output 2 (0x0e) */
8277 {0x16, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8278 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8279 {0x16, AC_VERB_SET_CONNECT_SEL, 0x02},
8280 /* Side Pin: output 3 (0x0f) */
8281 {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
8282 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8283 {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
8284
8285 /* Mic (rear) pin: input vref at 80% */
8286 {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8287 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8288 /* Front Mic pin: input vref at 80% */
8289 {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80},
8290 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8291 /* Line In pin: input */
8292 {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8293 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE},
8294 /* Line-2 In: Headphone output (output 0 - 0x0c) */
8295 {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
8296 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
8297 {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
8298 /* CD pin widget for input */
8299 {0x1c, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
8300
8301 { }
8302};
8303
8304/* pcm configuration: identiacal with ALC880 */
8305#define alc861vd_pcm_analog_playback alc880_pcm_analog_playback
8306#define alc861vd_pcm_analog_capture alc880_pcm_analog_capture
8307#define alc861vd_pcm_digital_playback alc880_pcm_digital_playback
8308#define alc861vd_pcm_digital_capture alc880_pcm_digital_capture
8309
8310/*
8311 * configuration and preset
8312 */
8313static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
8314 [ALC660VD_3ST] = "3stack-660",
8315 [ALC861VD_3ST] = "3stack",
8316 [ALC861VD_3ST_DIG] = "3stack-digout",
8317 [ALC861VD_6ST_DIG] = "6stack-digout",
8318 [ALC861VD_AUTO] = "auto",
8319};
8320
8321static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
8322 SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
8323 SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
8324 SND_PCI_QUIRK(0x1019, 0xa88d, "Realtek ALC660 demo", ALC660VD_3ST),
8325
8326 SND_PCI_QUIRK(0x17aa, 0x3802, "Lenovo 3000 C200", ALC861VD_3ST),
8327 {}
8328};
8329
8330static struct alc_config_preset alc861vd_presets[] = {
8331 [ALC660VD_3ST] = {
8332 .mixers = { alc861vd_3st_mixer },
8333 .init_verbs = { alc861vd_volume_init_verbs,
8334 alc861vd_3stack_init_verbs },
8335 .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
8336 .dac_nids = alc660vd_dac_nids,
8337 .num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids),
8338 .adc_nids = alc861vd_adc_nids,
8339 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
8340 .channel_mode = alc861vd_3stack_2ch_modes,
8341 .input_mux = &alc861vd_capture_source,
8342 },
8343 [ALC861VD_3ST] = {
8344 .mixers = { alc861vd_3st_mixer },
8345 .init_verbs = { alc861vd_volume_init_verbs,
8346 alc861vd_3stack_init_verbs },
8347 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
8348 .dac_nids = alc861vd_dac_nids,
8349 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
8350 .channel_mode = alc861vd_3stack_2ch_modes,
8351 .input_mux = &alc861vd_capture_source,
8352 },
8353 [ALC861VD_3ST_DIG] = {
8354 .mixers = { alc861vd_3st_mixer },
8355 .init_verbs = { alc861vd_volume_init_verbs,
8356 alc861vd_3stack_init_verbs },
8357 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
8358 .dac_nids = alc861vd_dac_nids,
8359 .dig_out_nid = ALC861VD_DIGOUT_NID,
8360 .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
8361 .channel_mode = alc861vd_3stack_2ch_modes,
8362 .input_mux = &alc861vd_capture_source,
8363 },
8364 [ALC861VD_6ST_DIG] = {
8365 .mixers = { alc861vd_6st_mixer, alc861vd_chmode_mixer },
8366 .init_verbs = { alc861vd_volume_init_verbs,
8367 alc861vd_6stack_init_verbs },
8368 .num_dacs = ARRAY_SIZE(alc861vd_dac_nids),
8369 .dac_nids = alc861vd_dac_nids,
8370 .dig_out_nid = ALC861VD_DIGOUT_NID,
8371 .num_channel_mode = ARRAY_SIZE(alc861vd_6stack_modes),
8372 .channel_mode = alc861vd_6stack_modes,
8373 .input_mux = &alc861vd_capture_source,
8374 },
8375};
8376
8377/*
8378 * BIOS auto configuration
8379 */
8380static void alc861vd_auto_set_output_and_unmute(struct hda_codec *codec,
8381 hda_nid_t nid, int pin_type, int dac_idx)
8382{
8383 /* set as output */
8384 snd_hda_codec_write(codec, nid, 0,
8385 AC_VERB_SET_PIN_WIDGET_CONTROL, pin_type);
8386 snd_hda_codec_write(codec, nid, 0,
8387 AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
8388}
8389
8390static void alc861vd_auto_init_multi_out(struct hda_codec *codec)
8391{
8392 struct alc_spec *spec = codec->spec;
8393 int i;
8394
8395 for (i = 0; i <= HDA_SIDE; i++) {
8396 hda_nid_t nid = spec->autocfg.line_out_pins[i];
8397 if (nid)
8398 alc861vd_auto_set_output_and_unmute(codec, nid,
8399 PIN_OUT, i);
8400 }
8401}
8402
8403
8404static void alc861vd_auto_init_hp_out(struct hda_codec *codec)
8405{
8406 struct alc_spec *spec = codec->spec;
8407 hda_nid_t pin;
8408
8409 pin = spec->autocfg.hp_pins[0];
8410 if (pin) /* connect to front and use dac 0 */
8411 alc861vd_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
8412}
8413
8414#define alc861vd_is_input_pin(nid) alc880_is_input_pin(nid)
8415#define ALC861VD_PIN_CD_NID ALC880_PIN_CD_NID
8416
8417static void alc861vd_auto_init_analog_input(struct hda_codec *codec)
8418{
8419 struct alc_spec *spec = codec->spec;
8420 int i;
8421
8422 for (i = 0; i < AUTO_PIN_LAST; i++) {
8423 hda_nid_t nid = spec->autocfg.input_pins[i];
8424 if (alc861vd_is_input_pin(nid)) {
8425 snd_hda_codec_write(codec, nid, 0,
8426 AC_VERB_SET_PIN_WIDGET_CONTROL,
8427 i <= AUTO_PIN_FRONT_MIC ?
8428 PIN_VREF80 : PIN_IN);
8429 if (nid != ALC861VD_PIN_CD_NID)
8430 snd_hda_codec_write(codec, nid, 0,
8431 AC_VERB_SET_AMP_GAIN_MUTE,
8432 AMP_OUT_MUTE);
8433 }
8434 }
8435}
8436
8437#define alc861vd_idx_to_mixer_vol(nid) ((nid) + 0x02)
8438#define alc861vd_idx_to_mixer_switch(nid) ((nid) + 0x0c)
8439
8440/* add playback controls from the parsed DAC table */
8441/* Based on ALC880 version. But ALC861VD has separate,
8442 * different NIDs for mute/unmute switch and volume control */
8443static int alc861vd_auto_create_multi_out_ctls(struct alc_spec *spec,
8444 const struct auto_pin_cfg *cfg)
8445{
8446 char name[32];
8447 static const char *chname[4] = {"Front", "Surround", "CLFE", "Side"};
8448 hda_nid_t nid_v, nid_s;
8449 int i, err;
8450
8451 for (i = 0; i < cfg->line_outs; i++) {
8452 if (! spec->multiout.dac_nids[i])
8453 continue;
8454 nid_v = alc861vd_idx_to_mixer_vol(
8455 alc880_dac_to_idx(
8456 spec->multiout.dac_nids[i]));
8457 nid_s = alc861vd_idx_to_mixer_switch(
8458 alc880_dac_to_idx(
8459 spec->multiout.dac_nids[i]));
8460
8461 if (i == 2) {
8462 /* Center/LFE */
8463 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL,
8464 "Center Playback Volume",
8465 HDA_COMPOSE_AMP_VAL(nid_v, 1,
8466 0, HDA_OUTPUT))) < 0)
8467 return err;
8468 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL,
8469 "LFE Playback Volume",
8470 HDA_COMPOSE_AMP_VAL(nid_v, 2,
8471 0, HDA_OUTPUT))) < 0)
8472 return err;
8473 if ((err = add_control(spec, ALC_CTL_BIND_MUTE,
8474 "Center Playback Switch",
8475 HDA_COMPOSE_AMP_VAL(nid_s, 1,
8476 2, HDA_INPUT))) < 0)
8477 return err;
8478 if ((err = add_control(spec, ALC_CTL_BIND_MUTE,
8479 "LFE Playback Switch",
8480 HDA_COMPOSE_AMP_VAL(nid_s, 2,
8481 2, HDA_INPUT))) < 0)
8482 return err;
8483 } else {
8484 sprintf(name, "%s Playback Volume", chname[i]);
8485 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
8486 HDA_COMPOSE_AMP_VAL(nid_v, 3,
8487 0, HDA_OUTPUT))) < 0)
8488 return err;
8489 sprintf(name, "%s Playback Switch", chname[i]);
8490 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
8491 HDA_COMPOSE_AMP_VAL(nid_v, 3,
8492 2, HDA_INPUT))) < 0)
8493 return err;
8494 }
8495 }
8496 return 0;
8497}
8498
8499/* add playback controls for speaker and HP outputs */
8500/* Based on ALC880 version. But ALC861VD has separate,
8501 * different NIDs for mute/unmute switch and volume control */
8502static int alc861vd_auto_create_extra_out(struct alc_spec *spec,
8503 hda_nid_t pin, const char *pfx)
8504{
8505 hda_nid_t nid_v, nid_s;
8506 int err;
8507 char name[32];
8508
8509 if (! pin)
8510 return 0;
8511
8512 if (alc880_is_fixed_pin(pin)) {
8513 nid_v = alc880_idx_to_dac(alc880_fixed_pin_idx(pin));
8514 /* specify the DAC as the extra output */
8515 if (! spec->multiout.hp_nid)
8516 spec->multiout.hp_nid = nid_v;
8517 else
8518 spec->multiout.extra_out_nid[0] = nid_v;
8519 /* control HP volume/switch on the output mixer amp */
8520 nid_v = alc861vd_idx_to_mixer_vol(
8521 alc880_fixed_pin_idx(pin));
8522 nid_s = alc861vd_idx_to_mixer_switch(
8523 alc880_fixed_pin_idx(pin));
8524
8525 sprintf(name, "%s Playback Volume", pfx);
8526 if ((err = add_control(spec, ALC_CTL_WIDGET_VOL, name,
8527 HDA_COMPOSE_AMP_VAL(nid_v, 3, 0,
8528 HDA_OUTPUT))) < 0)
8529 return err;
8530 sprintf(name, "%s Playback Switch", pfx);
8531 if ((err = add_control(spec, ALC_CTL_BIND_MUTE, name,
8532 HDA_COMPOSE_AMP_VAL(nid_s, 3, 2,
8533 HDA_INPUT))) < 0)
8534 return err;
8535 } else if (alc880_is_multi_pin(pin)) {
8536 /* set manual connection */
8537 /* we have only a switch on HP-out PIN */
8538 sprintf(name, "%s Playback Switch", pfx);
8539 if ((err = add_control(spec, ALC_CTL_WIDGET_MUTE, name,
8540 HDA_COMPOSE_AMP_VAL(pin, 3, 0,
8541 HDA_OUTPUT))) < 0)
8542 return err;
8543 }
8544 return 0;
8545}
8546
8547/* parse the BIOS configuration and set up the alc_spec
8548 * return 1 if successful, 0 if the proper config is not found,
8549 * or a negative error code
8550 * Based on ALC880 version - had to change it to override
8551 * alc880_auto_create_extra_out and alc880_auto_create_multi_out_ctls */
8552static int alc861vd_parse_auto_config(struct hda_codec *codec)
8553{
8554 struct alc_spec *spec = codec->spec;
8555 int err;
8556 static hda_nid_t alc861vd_ignore[] = { 0x1d, 0 };
8557
8558 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg,
8559 alc861vd_ignore)) < 0)
8560 return err;
8561 if (! spec->autocfg.line_outs)
8562 return 0; /* can't find valid BIOS pin config */
8563
8564 if ((err = alc880_auto_fill_dac_nids(spec, &spec->autocfg)) < 0 ||
8565 (err = alc861vd_auto_create_multi_out_ctls(spec,
8566 &spec->autocfg)) < 0 ||
8567 (err = alc861vd_auto_create_extra_out(spec,
8568 spec->autocfg.speaker_pins[0], "Speaker")) < 0 ||
8569 (err = alc861vd_auto_create_extra_out(spec,
8570 spec->autocfg.hp_pins[0], "Headphone")) < 0 ||
8571 (err = alc880_auto_create_analog_input_ctls(spec,
8572 &spec->autocfg)) < 0)
8573 return err;
8574
8575 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
8576
8577 if (spec->autocfg.dig_out_pin)
8578 spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
8579
8580 if (spec->kctl_alloc)
8581 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
8582
8583 spec->init_verbs[spec->num_init_verbs++]
8584 = alc861vd_volume_init_verbs;
8585
8586 spec->num_mux_defs = 1;
8587 spec->input_mux = &spec->private_imux;
8588
8589 return 1;
8590}
8591
8592/* additional initialization for auto-configuration model */
8593static void alc861vd_auto_init(struct hda_codec *codec)
8594{
8595 alc861vd_auto_init_multi_out(codec);
8596 alc861vd_auto_init_hp_out(codec);
8597 alc861vd_auto_init_analog_input(codec);
8598}
8599
8600static int patch_alc861vd(struct hda_codec *codec)
8601{
8602 struct alc_spec *spec;
8603 int err, board_config;
8604
8605 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
8606 if (spec == NULL)
8607 return -ENOMEM;
8608
8609 codec->spec = spec;
8610
8611 board_config = snd_hda_check_board_config(codec, ALC861VD_MODEL_LAST,
8612 alc861vd_models,
8613 alc861vd_cfg_tbl);
8614
8615 if (board_config < 0 || board_config >= ALC861VD_MODEL_LAST) {
8616 printk(KERN_INFO "hda_codec: Unknown model for ALC660VD/"
8617 "ALC861VD, trying auto-probe from BIOS...\n");
8618 board_config = ALC861VD_AUTO;
8619 }
8620
8621 if (board_config == ALC861VD_AUTO) {
8622 /* automatic parse from the BIOS config */
8623 err = alc861vd_parse_auto_config(codec);
8624 if (err < 0) {
8625 alc_free(codec);
8626 return err;
8627 } else if (! err) {
8628 printk(KERN_INFO
8629 "hda_codec: Cannot set up configuration "
8630 "from BIOS. Using base mode...\n");
8631 board_config = ALC861VD_3ST;
8632 }
8633 }
8634
8635 if (board_config != ALC861VD_AUTO)
8636 setup_preset(spec, &alc861vd_presets[board_config]);
8637
8638 spec->stream_name_analog = "ALC861VD Analog";
8639 spec->stream_analog_playback = &alc861vd_pcm_analog_playback;
8640 spec->stream_analog_capture = &alc861vd_pcm_analog_capture;
8641
8642 spec->stream_name_digital = "ALC861VD Digital";
8643 spec->stream_digital_playback = &alc861vd_pcm_digital_playback;
8644 spec->stream_digital_capture = &alc861vd_pcm_digital_capture;
8645
8646 spec->adc_nids = alc861vd_adc_nids;
8647 spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
8648
8649 spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
8650 spec->num_mixers++;
8651
8652 codec->patch_ops = alc_patch_ops;
8653
8654 if (board_config == ALC861VD_AUTO)
8655 spec->init_hook = alc861vd_auto_init;
8656
8657 return 0;
8658}
8659
8660/*
6849 * patch entries 8661 * patch entries
6850 */ 8662 */
6851struct hda_codec_preset snd_hda_preset_realtek[] = { 8663struct hda_codec_preset snd_hda_preset_realtek[] = {
6852 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 }, 8664 { .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
6853 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 }, 8665 { .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
6854 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 }, 8666 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
8667 .patch = patch_alc861 },
8668 { .id = 0x10ec0660, .name = "ALC660-VD", .patch = patch_alc861vd },
8669 { .id = 0x10ec0861, .name = "ALC861", .patch = patch_alc861 },
8670 { .id = 0x10ec0862, .name = "ALC861-VD", .patch = patch_alc861vd },
8671 { .id = 0x10ec0880, .name = "ALC880", .patch = patch_alc880 },
6855 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 }, 8672 { .id = 0x10ec0882, .name = "ALC882", .patch = patch_alc882 },
6856 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 }, 8673 { .id = 0x10ec0883, .name = "ALC883", .patch = patch_alc883 },
6857 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 }, 8674 { .id = 0x10ec0885, .name = "ALC885", .patch = patch_alc882 },
6858 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 }, 8675 { .id = 0x10ec0888, .name = "ALC888", .patch = patch_alc883 },
6859 { .id = 0x10ec0861, .rev = 0x100300, .name = "ALC861",
6860 .patch = patch_alc861 },
6861 { .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
6862 .patch = patch_alc861 },
6863 {} /* terminator */ 8676 {} /* terminator */
6864}; 8677};
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index fe51ef3e49d2..6f4a39273b98 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -37,14 +37,37 @@
37#define NUM_CONTROL_ALLOC 32 37#define NUM_CONTROL_ALLOC 32
38#define STAC_HP_EVENT 0x37 38#define STAC_HP_EVENT 0x37
39 39
40#define STAC_REF 0 40enum {
41#define STAC_D945GTP3 1 41 STAC_REF,
42#define STAC_D945GTP5 2 42 STAC_9200_MODELS
43#define STAC_MACMINI 3 43};
44#define STAC_922X_MODELS 4 /* number of 922x models */ 44
45#define STAC_D965_3ST 4 45enum {
46#define STAC_D965_5ST 5 46 STAC_9205_REF,
47#define STAC_927X_MODELS 6 /* number of 922x models */ 47 STAC_9205_MODELS
48};
49
50enum {
51 STAC_925x_REF,
52 STAC_M2_2,
53 STAC_MA6,
54 STAC_925x_MODELS
55};
56
57enum {
58 STAC_D945_REF,
59 STAC_D945GTP3,
60 STAC_D945GTP5,
61 STAC_MACMINI,
62 STAC_922X_MODELS
63};
64
65enum {
66 STAC_D965_REF,
67 STAC_D965_3ST,
68 STAC_D965_5ST,
69 STAC_927X_MODELS
70};
48 71
49struct sigmatel_spec { 72struct sigmatel_spec {
50 struct snd_kcontrol_new *mixers[4]; 73 struct snd_kcontrol_new *mixers[4];
@@ -67,6 +90,9 @@ struct sigmatel_spec {
67 unsigned int num_adcs; 90 unsigned int num_adcs;
68 hda_nid_t *mux_nids; 91 hda_nid_t *mux_nids;
69 unsigned int num_muxes; 92 unsigned int num_muxes;
93 hda_nid_t *dmic_nids;
94 unsigned int num_dmics;
95 hda_nid_t dmux_nid;
70 hda_nid_t dig_in_nid; 96 hda_nid_t dig_in_nid;
71 97
72 /* pin widgets */ 98 /* pin widgets */
@@ -80,6 +106,8 @@ struct sigmatel_spec {
80 struct snd_kcontrol_new *mixer; 106 struct snd_kcontrol_new *mixer;
81 107
82 /* capture source */ 108 /* capture source */
109 struct hda_input_mux *dinput_mux;
110 unsigned int cur_dmux;
83 struct hda_input_mux *input_mux; 111 struct hda_input_mux *input_mux;
84 unsigned int cur_mux[3]; 112 unsigned int cur_mux[3];
85 113
@@ -92,6 +120,7 @@ struct sigmatel_spec {
92 struct auto_pin_cfg autocfg; 120 struct auto_pin_cfg autocfg;
93 unsigned int num_kctl_alloc, num_kctl_used; 121 unsigned int num_kctl_alloc, num_kctl_used;
94 struct snd_kcontrol_new *kctl_alloc; 122 struct snd_kcontrol_new *kctl_alloc;
123 struct hda_input_mux private_dimux;
95 struct hda_input_mux private_imux; 124 struct hda_input_mux private_imux;
96}; 125};
97 126
@@ -107,6 +136,18 @@ static hda_nid_t stac9200_dac_nids[1] = {
107 0x02, 136 0x02,
108}; 137};
109 138
139static hda_nid_t stac925x_adc_nids[1] = {
140 0x03,
141};
142
143static hda_nid_t stac925x_mux_nids[1] = {
144 0x0f,
145};
146
147static hda_nid_t stac925x_dac_nids[1] = {
148 0x02,
149};
150
110static hda_nid_t stac922x_adc_nids[2] = { 151static hda_nid_t stac922x_adc_nids[2] = {
111 0x06, 0x07, 152 0x06, 0x07,
112}; 153};
@@ -131,11 +172,20 @@ static hda_nid_t stac9205_mux_nids[2] = {
131 0x19, 0x1a 172 0x19, 0x1a
132}; 173};
133 174
175static hda_nid_t stac9205_dmic_nids[3] = {
176 0x17, 0x18, 0
177};
178
134static hda_nid_t stac9200_pin_nids[8] = { 179static hda_nid_t stac9200_pin_nids[8] = {
135 0x08, 0x09, 0x0d, 0x0e, 180 0x08, 0x09, 0x0d, 0x0e,
136 0x0f, 0x10, 0x11, 0x12, 181 0x0f, 0x10, 0x11, 0x12,
137}; 182};
138 183
184static hda_nid_t stac925x_pin_nids[8] = {
185 0x07, 0x08, 0x0a, 0x0b,
186 0x0c, 0x0d, 0x10, 0x11,
187};
188
139static hda_nid_t stac922x_pin_nids[10] = { 189static hda_nid_t stac922x_pin_nids[10] = {
140 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 190 0x0a, 0x0b, 0x0c, 0x0d, 0x0e,
141 0x0f, 0x10, 0x11, 0x15, 0x1b, 191 0x0f, 0x10, 0x11, 0x15, 0x1b,
@@ -154,6 +204,34 @@ static hda_nid_t stac9205_pin_nids[12] = {
154 204
155}; 205};
156 206
207static int stac92xx_dmux_enum_info(struct snd_kcontrol *kcontrol,
208 struct snd_ctl_elem_info *uinfo)
209{
210 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
211 struct sigmatel_spec *spec = codec->spec;
212 return snd_hda_input_mux_info(spec->dinput_mux, uinfo);
213}
214
215static int stac92xx_dmux_enum_get(struct snd_kcontrol *kcontrol,
216 struct snd_ctl_elem_value *ucontrol)
217{
218 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
219 struct sigmatel_spec *spec = codec->spec;
220
221 ucontrol->value.enumerated.item[0] = spec->cur_dmux;
222 return 0;
223}
224
225static int stac92xx_dmux_enum_put(struct snd_kcontrol *kcontrol,
226 struct snd_ctl_elem_value *ucontrol)
227{
228 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
229 struct sigmatel_spec *spec = codec->spec;
230
231 return snd_hda_input_mux_put(codec, spec->dinput_mux, ucontrol,
232 spec->dmux_nid, &spec->cur_dmux);
233}
234
157static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 235static int stac92xx_mux_enum_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
158{ 236{
159 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 237 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
@@ -187,6 +265,12 @@ static struct hda_verb stac9200_core_init[] = {
187 {} 265 {}
188}; 266};
189 267
268static struct hda_verb stac925x_core_init[] = {
269 /* set dac0mux for dac converter */
270 { 0x06, AC_VERB_SET_CONNECT_SEL, 0x00},
271 {}
272};
273
190static struct hda_verb stac922x_core_init[] = { 274static struct hda_verb stac922x_core_init[] = {
191 /* set master volume and direct control */ 275 /* set master volume and direct control */
192 { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff}, 276 { 0x16, AC_VERB_SET_VOLUME_KNOB_CONTROL, 0xff},
@@ -232,6 +316,23 @@ static struct snd_kcontrol_new stac9200_mixer[] = {
232 { } /* end */ 316 { } /* end */
233}; 317};
234 318
319static struct snd_kcontrol_new stac925x_mixer[] = {
320 HDA_CODEC_VOLUME("Master Playback Volume", 0xe, 0, HDA_OUTPUT),
321 HDA_CODEC_MUTE("Master Playback Switch", 0xe, 0, HDA_OUTPUT),
322 {
323 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
324 .name = "Input Source",
325 .count = 1,
326 .info = stac92xx_mux_enum_info,
327 .get = stac92xx_mux_enum_get,
328 .put = stac92xx_mux_enum_put,
329 },
330 HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_OUTPUT),
331 HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_OUTPUT),
332 HDA_CODEC_VOLUME("Capture Mux Volume", 0x0f, 0, HDA_OUTPUT),
333 { } /* end */
334};
335
235/* This needs to be generated dynamically based on sequence */ 336/* This needs to be generated dynamically based on sequence */
236static struct snd_kcontrol_new stac922x_mixer[] = { 337static struct snd_kcontrol_new stac922x_mixer[] = {
237 { 338 {
@@ -263,7 +364,7 @@ static struct snd_kcontrol_new stac9227_mixer[] = {
263 { } /* end */ 364 { } /* end */
264}; 365};
265 366
266static snd_kcontrol_new_t stac927x_mixer[] = { 367static struct snd_kcontrol_new stac927x_mixer[] = {
267 { 368 {
268 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 369 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
269 .name = "Input Source", 370 .name = "Input Source",
@@ -278,7 +379,15 @@ static snd_kcontrol_new_t stac927x_mixer[] = {
278 { } /* end */ 379 { } /* end */
279}; 380};
280 381
281static snd_kcontrol_new_t stac9205_mixer[] = { 382static struct snd_kcontrol_new stac9205_mixer[] = {
383 {
384 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
385 .name = "Digital Input Source",
386 .count = 1,
387 .info = stac92xx_dmux_enum_info,
388 .get = stac92xx_dmux_enum_get,
389 .put = stac92xx_dmux_enum_put,
390 },
282 { 391 {
283 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 392 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
284 .name = "Input Source", 393 .name = "Input Source",
@@ -327,22 +436,64 @@ static unsigned int ref9200_pin_configs[8] = {
327 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, 436 0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
328}; 437};
329 438
330static unsigned int *stac9200_brd_tbl[] = { 439static unsigned int *stac9200_brd_tbl[STAC_9200_MODELS] = {
331 ref9200_pin_configs, 440 [STAC_REF] = ref9200_pin_configs,
441};
442
443static const char *stac9200_models[STAC_9200_MODELS] = {
444 [STAC_REF] = "ref",
332}; 445};
333 446
334static struct hda_board_config stac9200_cfg_tbl[] = { 447static struct snd_pci_quirk stac9200_cfg_tbl[] = {
335 { .modelname = "ref", 448 /* SigmaTel reference board */
336 .pci_subvendor = PCI_VENDOR_ID_INTEL, 449 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
337 .pci_subdevice = 0x2668, /* DFI LanParty */ 450 "DFI LanParty", STAC_REF),
338 .config = STAC_REF },
339 /* Dell laptops have BIOS problem */ 451 /* Dell laptops have BIOS problem */
340 { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01b5, 452 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01b5,
341 .config = STAC_REF }, /* Dell Inspiron 630m */ 453 "Dell Inspiron 630m", STAC_REF),
342 { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01c2, 454 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01c2,
343 .config = STAC_REF }, /* Dell Latitude D620 */ 455 "Dell Latitude D620", STAC_REF),
344 { .pci_subvendor = PCI_VENDOR_ID_DELL, .pci_subdevice = 0x01cb, 456 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cb,
345 .config = STAC_REF }, /* Dell Latitude 120L */ 457 "Dell Latitude 120L", STAC_REF),
458 SND_PCI_QUIRK(PCI_VENDOR_ID_DELL, 0x01cc,
459 "Dell Latitude D820", STAC_REF),
460 {} /* terminator */
461};
462
463static unsigned int ref925x_pin_configs[8] = {
464 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,
465 0x90a70320, 0x02214210, 0x400003f1, 0x9033032e,
466};
467
468static unsigned int stac925x_MA6_pin_configs[8] = {
469 0x40c003f0, 0x424503f2, 0x01813022, 0x02a19021,
470 0x90a70320, 0x90100211, 0x400003f1, 0x9033032e,
471};
472
473static unsigned int stac925xM2_2_pin_configs[8] = {
474 0x40c003f3, 0x424503f2, 0x041800f4, 0x02a19020,
475 0x50a103F0, 0x90100210, 0x400003f1, 0x9033032e,
476};
477
478static unsigned int *stac925x_brd_tbl[STAC_925x_MODELS] = {
479 [STAC_REF] = ref925x_pin_configs,
480 [STAC_M2_2] = stac925xM2_2_pin_configs,
481 [STAC_MA6] = stac925x_MA6_pin_configs,
482};
483
484static const char *stac925x_models[STAC_925x_MODELS] = {
485 [STAC_REF] = "ref",
486 [STAC_M2_2] = "m2-2",
487 [STAC_MA6] = "m6",
488};
489
490static struct snd_pci_quirk stac925x_cfg_tbl[] = {
491 /* SigmaTel reference board */
492 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668, "DFI LanParty", STAC_REF),
493 SND_PCI_QUIRK(0x107b, 0x0316, "Gateway M255", STAC_REF),
494 SND_PCI_QUIRK(0x107b, 0x0366, "Gateway MP6954", STAC_REF),
495 SND_PCI_QUIRK(0x107b, 0x0461, "Gateway NX560XL", STAC_MA6),
496 SND_PCI_QUIRK(0x1002, 0x437b, "Gateway MX6453", STAC_M2_2),
346 {} /* terminator */ 497 {} /* terminator */
347}; 498};
348 499
@@ -365,100 +516,80 @@ static unsigned int d945gtp5_pin_configs[10] = {
365}; 516};
366 517
367static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = { 518static unsigned int *stac922x_brd_tbl[STAC_922X_MODELS] = {
368 [STAC_REF] = ref922x_pin_configs, 519 [STAC_D945_REF] = ref922x_pin_configs,
369 [STAC_D945GTP3] = d945gtp3_pin_configs, 520 [STAC_D945GTP3] = d945gtp3_pin_configs,
370 [STAC_D945GTP5] = d945gtp5_pin_configs, 521 [STAC_D945GTP5] = d945gtp5_pin_configs,
371 [STAC_MACMINI] = d945gtp5_pin_configs, 522 [STAC_MACMINI] = d945gtp5_pin_configs,
372}; 523};
373 524
374static struct hda_board_config stac922x_cfg_tbl[] = { 525static const char *stac922x_models[STAC_922X_MODELS] = {
375 { .modelname = "5stack", .config = STAC_D945GTP5 }, 526 [STAC_D945_REF] = "ref",
376 { .modelname = "3stack", .config = STAC_D945GTP3 }, 527 [STAC_D945GTP5] = "5stack",
377 { .modelname = "ref", 528 [STAC_D945GTP3] = "3stack",
378 .pci_subvendor = PCI_VENDOR_ID_INTEL, 529 [STAC_MACMINI] = "macmini",
379 .pci_subdevice = 0x2668, /* DFI LanParty */ 530};
380 .config = STAC_REF }, /* SigmaTel reference board */ 531
381 /* Intel 945G based systems */ 532static struct snd_pci_quirk stac922x_cfg_tbl[] = {
382 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 533 /* SigmaTel reference board */
383 .pci_subdevice = 0x0101, 534 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
384 .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ 535 "DFI LanParty", STAC_D945_REF),
385 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 536 /* Intel 945G based systems */
386 .pci_subdevice = 0x0202, 537 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0101,
387 .config = STAC_D945GTP3 }, /* Intel D945GNT - 3 Stack */ 538 "Intel D945G", STAC_D945GTP3),
388 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 539 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0202,
389 .pci_subdevice = 0x0606, 540 "Intel D945G", STAC_D945GTP3),
390 .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ 541 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0606,
391 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 542 "Intel D945G", STAC_D945GTP3),
392 .pci_subdevice = 0x0601, 543 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0601,
393 .config = STAC_D945GTP3 }, /* Intel D945GTP - 3 Stack */ 544 "Intel D945G", STAC_D945GTP3),
394 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 545 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0111,
395 .pci_subdevice = 0x0111, 546 "Intel D945G", STAC_D945GTP3),
396 .config = STAC_D945GTP3 }, /* Intel D945GZP - 3 Stack */ 547 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1115,
397 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 548 "Intel D945G", STAC_D945GTP3),
398 .pci_subdevice = 0x1115, 549 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1116,
399 .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ 550 "Intel D945G", STAC_D945GTP3),
400 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 551 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1117,
401 .pci_subdevice = 0x1116, 552 "Intel D945G", STAC_D945GTP3),
402 .config = STAC_D945GTP3 }, /* Intel D945GBO - 3 Stack */ 553 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1118,
403 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 554 "Intel D945G", STAC_D945GTP3),
404 .pci_subdevice = 0x1117, 555 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x1119,
405 .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ 556 "Intel D945G", STAC_D945GTP3),
406 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 557 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x8826,
407 .pci_subdevice = 0x1118, 558 "Intel D945G", STAC_D945GTP3),
408 .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ 559 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5049,
409 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 560 "Intel D945G", STAC_D945GTP3),
410 .pci_subdevice = 0x1119, 561 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5055,
411 .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ 562 "Intel D945G", STAC_D945GTP3),
412 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 563 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x5048,
413 .pci_subdevice = 0x8826, 564 "Intel D945G", STAC_D945GTP3),
414 .config = STAC_D945GTP3 }, /* Intel D945GPM - 3 Stack */ 565 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0110,
415 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 566 "Intel D945G", STAC_D945GTP3),
416 .pci_subdevice = 0x5049, 567 /* Intel D945G 5-stack systems */
417 .config = STAC_D945GTP3 }, /* Intel D945GCZ - 3 Stack */ 568 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0404,
418 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 569 "Intel D945G", STAC_D945GTP5),
419 .pci_subdevice = 0x5055, 570 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0303,
420 .config = STAC_D945GTP3 }, /* Intel D945GCZ - 3 Stack */ 571 "Intel D945G", STAC_D945GTP5),
421 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 572 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0013,
422 .pci_subdevice = 0x5048, 573 "Intel D945G", STAC_D945GTP5),
423 .config = STAC_D945GTP3 }, /* Intel D945GPB - 3 Stack */ 574 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0417,
424 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 575 "Intel D945G", STAC_D945GTP5),
425 .pci_subdevice = 0x0110, 576 /* Intel 945P based systems */
426 .config = STAC_D945GTP3 }, /* Intel D945GLR - 3 Stack */ 577 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0b0b,
427 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 578 "Intel D945P", STAC_D945GTP3),
428 .pci_subdevice = 0x0404, 579 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0112,
429 .config = STAC_D945GTP5 }, /* Intel D945GTP - 5 Stack */ 580 "Intel D945P", STAC_D945GTP3),
430 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 581 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0d0d,
431 .pci_subdevice = 0x0303, 582 "Intel D945P", STAC_D945GTP3),
432 .config = STAC_D945GTP5 }, /* Intel D945GNT - 5 Stack */ 583 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0909,
433 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 584 "Intel D945P", STAC_D945GTP3),
434 .pci_subdevice = 0x0013, 585 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0505,
435 .config = STAC_D945GTP5 }, /* Intel D955XBK - 5 Stack */ 586 "Intel D945P", STAC_D945GTP3),
436 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 587 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x0707,
437 .pci_subdevice = 0x0417, 588 "Intel D945P", STAC_D945GTP5),
438 .config = STAC_D945GTP5 }, /* Intel D975XBK - 5 Stack */ 589 /* other systems */
439 /* Intel 945P based systems */ 590 /* Apple Mac Mini (early 2006) */
440 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 591 SND_PCI_QUIRK(0x8384, 0x7680,
441 .pci_subdevice = 0x0b0b, 592 "Mac Mini", STAC_MACMINI),
442 .config = STAC_D945GTP3 }, /* Intel D945PSN - 3 Stack */
443 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
444 .pci_subdevice = 0x0112,
445 .config = STAC_D945GTP3 }, /* Intel D945PLN - 3 Stack */
446 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
447 .pci_subdevice = 0x0d0d,
448 .config = STAC_D945GTP3 }, /* Intel D945PLM - 3 Stack */
449 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
450 .pci_subdevice = 0x0909,
451 .config = STAC_D945GTP3 }, /* Intel D945PAW - 3 Stack */
452 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
453 .pci_subdevice = 0x0505,
454 .config = STAC_D945GTP3 }, /* Intel D945PLM - 3 Stack */
455 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
456 .pci_subdevice = 0x0707,
457 .config = STAC_D945GTP5 }, /* Intel D945PSV - 5 Stack */
458 /* other systems */
459 { .pci_subvendor = 0x8384,
460 .pci_subdevice = 0x7680,
461 .config = STAC_MACMINI }, /* Apple Mac Mini (early 2006) */
462 {} /* terminator */ 593 {} /* terminator */
463}; 594};
464 595
@@ -484,120 +615,72 @@ static unsigned int d965_5st_pin_configs[14] = {
484}; 615};
485 616
486static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = { 617static unsigned int *stac927x_brd_tbl[STAC_927X_MODELS] = {
487 [STAC_REF] = ref927x_pin_configs, 618 [STAC_D965_REF] = ref927x_pin_configs,
488 [STAC_D965_3ST] = d965_3st_pin_configs, 619 [STAC_D965_3ST] = d965_3st_pin_configs,
489 [STAC_D965_5ST] = d965_5st_pin_configs, 620 [STAC_D965_5ST] = d965_5st_pin_configs,
490}; 621};
491 622
492static struct hda_board_config stac927x_cfg_tbl[] = { 623static const char *stac927x_models[STAC_927X_MODELS] = {
493 { .modelname = "5stack", .config = STAC_D965_5ST }, 624 [STAC_D965_REF] = "ref",
494 { .modelname = "3stack", .config = STAC_D965_3ST }, 625 [STAC_D965_3ST] = "3stack",
495 { .modelname = "ref", 626 [STAC_D965_5ST] = "5stack",
496 .pci_subvendor = PCI_VENDOR_ID_INTEL, 627};
497 .pci_subdevice = 0x2668, /* DFI LanParty */ 628
498 .config = STAC_REF }, /* SigmaTel reference board */ 629static struct snd_pci_quirk stac927x_cfg_tbl[] = {
630 /* SigmaTel reference board */
631 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
632 "DFI LanParty", STAC_D965_REF),
499 /* Intel 946 based systems */ 633 /* Intel 946 based systems */
500 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 634 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x3d01, "Intel D946", STAC_D965_3ST),
501 .pci_subdevice = 0x3d01, 635 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0xa301, "Intel D946", STAC_D965_3ST),
502 .config = STAC_D965_3ST }, /* D946 configuration */
503 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
504 .pci_subdevice = 0xa301,
505 .config = STAC_D965_3ST }, /* Intel D946GZT - 3 stack */
506 /* 965 based 3 stack systems */ 636 /* 965 based 3 stack systems */
507 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 637 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2116, "Intel D965", STAC_D965_3ST),
508 .pci_subdevice = 0x2116, 638 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2115, "Intel D965", STAC_D965_3ST),
509 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ 639 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2114, "Intel D965", STAC_D965_3ST),
510 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 640 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2113, "Intel D965", STAC_D965_3ST),
511 .pci_subdevice = 0x2115, 641 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2112, "Intel D965", STAC_D965_3ST),
512 .config = STAC_D965_3ST }, /* Intel DQ965WC - 3 Stack */ 642 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2111, "Intel D965", STAC_D965_3ST),
513 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 643 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2110, "Intel D965", STAC_D965_3ST),
514 .pci_subdevice = 0x2114, 644 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2009, "Intel D965", STAC_D965_3ST),
515 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ 645 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2008, "Intel D965", STAC_D965_3ST),
516 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 646 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2007, "Intel D965", STAC_D965_3ST),
517 .pci_subdevice = 0x2113, 647 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2006, "Intel D965", STAC_D965_3ST),
518 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */ 648 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2005, "Intel D965", STAC_D965_3ST),
519 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 649 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2004, "Intel D965", STAC_D965_3ST),
520 .pci_subdevice = 0x2112, 650 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2003, "Intel D965", STAC_D965_3ST),
521 .config = STAC_D965_3ST }, /* Intel DG965MS - 3 Stack */ 651 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2002, "Intel D965", STAC_D965_3ST),
522 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 652 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2001, "Intel D965", STAC_D965_3ST),
523 .pci_subdevice = 0x2111,
524 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
525 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
526 .pci_subdevice = 0x2110,
527 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
528 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
529 .pci_subdevice = 0x2009,
530 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
531 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
532 .pci_subdevice = 0x2008,
533 .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack */
534 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
535 .pci_subdevice = 0x2007,
536 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
537 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
538 .pci_subdevice = 0x2006,
539 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
540 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
541 .pci_subdevice = 0x2005,
542 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
543 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
544 .pci_subdevice = 0x2004,
545 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
546 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
547 .pci_subdevice = 0x2003,
548 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
549 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
550 .pci_subdevice = 0x2002,
551 .config = STAC_D965_3ST }, /* Intel D965 3Stack config */
552 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
553 .pci_subdevice = 0x2001,
554 .config = STAC_D965_3ST }, /* Intel DQ965GF - 3 Stack */
555 /* 965 based 5 stack systems */ 653 /* 965 based 5 stack systems */
556 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 654 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2301, "Intel D965", STAC_D965_5ST),
557 .pci_subdevice = 0x2301, 655 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2302, "Intel D965", STAC_D965_5ST),
558 .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ 656 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2303, "Intel D965", STAC_D965_5ST),
559 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 657 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2304, "Intel D965", STAC_D965_5ST),
560 .pci_subdevice = 0x2302, 658 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2305, "Intel D965", STAC_D965_5ST),
561 .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ 659 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2501, "Intel D965", STAC_D965_5ST),
562 { .pci_subvendor = PCI_VENDOR_ID_INTEL, 660 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2502, "Intel D965", STAC_D965_5ST),
563 .pci_subdevice = 0x2303, 661 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2503, "Intel D965", STAC_D965_5ST),
564 .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */ 662 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2504, "Intel D965", STAC_D965_5ST),
565 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
566 .pci_subdevice = 0x2304,
567 .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
568 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
569 .pci_subdevice = 0x2305,
570 .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
571 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
572 .pci_subdevice = 0x2501,
573 .config = STAC_D965_5ST }, /* Intel DG965MQ - 5 Stack */
574 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
575 .pci_subdevice = 0x2502,
576 .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
577 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
578 .pci_subdevice = 0x2503,
579 .config = STAC_D965_5ST }, /* Intel DG965 - 5 Stack */
580 { .pci_subvendor = PCI_VENDOR_ID_INTEL,
581 .pci_subdevice = 0x2504,
582 .config = STAC_D965_5ST }, /* Intel DQ965GF - 5 Stack */
583 {} /* terminator */ 663 {} /* terminator */
584}; 664};
585 665
586static unsigned int ref9205_pin_configs[12] = { 666static unsigned int ref9205_pin_configs[12] = {
587 0x40000100, 0x40000100, 0x01016011, 0x01014010, 667 0x40000100, 0x40000100, 0x01016011, 0x01014010,
588 0x01813122, 0x01a19021, 0x40000100, 0x40000100, 668 0x01813122, 0x01a19021, 0x40000100, 0x40000100,
589 0x40000100, 0x40000100, 0x01441030, 0x01c41030 669 0x90a000f0, 0x90a000f0, 0x01441030, 0x01c41030
590}; 670};
591 671
592static unsigned int *stac9205_brd_tbl[] = { 672static unsigned int *stac9205_brd_tbl[STAC_9205_MODELS] = {
593 ref9205_pin_configs, 673 ref9205_pin_configs,
594}; 674};
595 675
596static struct hda_board_config stac9205_cfg_tbl[] = { 676static const char *stac9205_models[STAC_9205_MODELS] = {
597 { .modelname = "ref", 677 [STAC_9205_REF] = "ref",
598 .pci_subvendor = PCI_VENDOR_ID_INTEL, 678};
599 .pci_subdevice = 0x2668, /* DFI LanParty */ 679
600 .config = STAC_REF }, /* SigmaTel reference board */ 680static struct snd_pci_quirk stac9205_cfg_tbl[] = {
681 /* SigmaTel reference board */
682 SND_PCI_QUIRK(PCI_VENDOR_ID_INTEL, 0x2668,
683 "DFI LanParty", STAC_9205_REF),
601 {} /* terminator */ 684 {} /* terminator */
602}; 685};
603 686
@@ -1154,6 +1237,58 @@ static int stac92xx_auto_create_hp_ctls(struct hda_codec *codec,
1154 return 0; 1237 return 0;
1155} 1238}
1156 1239
1240/* labels for dmic mux inputs */
1241static const char *stac92xx_dmic_labels[5] = {
1242 "Analog Inputs", "Digital Mic 1", "Digital Mic 2",
1243 "Digital Mic 3", "Digital Mic 4"
1244};
1245
1246/* create playback/capture controls for input pins on dmic capable codecs */
1247static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec,
1248 const struct auto_pin_cfg *cfg)
1249{
1250 struct sigmatel_spec *spec = codec->spec;
1251 struct hda_input_mux *dimux = &spec->private_dimux;
1252 hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];
1253 int i, j;
1254
1255 dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0];
1256 dimux->items[dimux->num_items].index = 0;
1257 dimux->num_items++;
1258
1259 for (i = 0; i < spec->num_dmics; i++) {
1260 int index;
1261 int num_cons;
1262 unsigned int def_conf;
1263
1264 def_conf = snd_hda_codec_read(codec,
1265 spec->dmic_nids[i],
1266 0,
1267 AC_VERB_GET_CONFIG_DEFAULT,
1268 0);
1269 if (get_defcfg_connect(def_conf) == AC_JACK_PORT_NONE)
1270 continue;
1271
1272 num_cons = snd_hda_get_connections(codec,
1273 spec->dmux_nid,
1274 con_lst,
1275 HDA_MAX_NUM_INPUTS);
1276 for (j = 0; j < num_cons; j++)
1277 if (con_lst[j] == spec->dmic_nids[i]) {
1278 index = j;
1279 goto found;
1280 }
1281 continue;
1282found:
1283 dimux->items[dimux->num_items].label =
1284 stac92xx_dmic_labels[dimux->num_items];
1285 dimux->items[dimux->num_items].index = index;
1286 dimux->num_items++;
1287 }
1288
1289 return 0;
1290}
1291
1157/* create playback/capture controls for input pins */ 1292/* create playback/capture controls for input pins */
1158static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg) 1293static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const struct auto_pin_cfg *cfg)
1159{ 1294{
@@ -1238,7 +1373,9 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
1238 struct sigmatel_spec *spec = codec->spec; 1373 struct sigmatel_spec *spec = codec->spec;
1239 int err; 1374 int err;
1240 1375
1241 if ((err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL)) < 0) 1376 if ((err = snd_hda_parse_pin_def_config(codec,
1377 &spec->autocfg,
1378 spec->dmic_nids)) < 0)
1242 return err; 1379 return err;
1243 if (! spec->autocfg.line_outs) 1380 if (! spec->autocfg.line_outs)
1244 return 0; /* can't find valid pin config */ 1381 return 0; /* can't find valid pin config */
@@ -1254,6 +1391,11 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
1254 (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) 1391 (err = stac92xx_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0)
1255 return err; 1392 return err;
1256 1393
1394 if (spec->num_dmics > 0)
1395 if ((err = stac92xx_auto_create_dmic_input_ctls(codec,
1396 &spec->autocfg)) < 0)
1397 return err;
1398
1257 spec->multiout.max_channels = spec->multiout.num_dacs * 2; 1399 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1258 if (spec->multiout.max_channels > 2) 1400 if (spec->multiout.max_channels > 2)
1259 spec->surr_switch = 1; 1401 spec->surr_switch = 1;
@@ -1267,6 +1409,7 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
1267 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 1409 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1268 1410
1269 spec->input_mux = &spec->private_imux; 1411 spec->input_mux = &spec->private_imux;
1412 spec->dinput_mux = &spec->private_dimux;
1270 1413
1271 return 1; 1414 return 1;
1272} 1415}
@@ -1366,6 +1509,7 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
1366 spec->mixers[spec->num_mixers++] = spec->kctl_alloc; 1509 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1367 1510
1368 spec->input_mux = &spec->private_imux; 1511 spec->input_mux = &spec->private_imux;
1512 spec->dinput_mux = &spec->private_dimux;
1369 1513
1370 return 1; 1514 return 1;
1371} 1515}
@@ -1448,6 +1592,11 @@ static int stac92xx_init(struct hda_codec *codec)
1448 stac92xx_auto_set_pinctl(codec, nid, pinctl); 1592 stac92xx_auto_set_pinctl(codec, nid, pinctl);
1449 } 1593 }
1450 } 1594 }
1595 if (spec->num_dmics > 0)
1596 for (i = 0; i < spec->num_dmics; i++)
1597 stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i],
1598 AC_PINCTL_IN_EN);
1599
1451 if (cfg->dig_out_pin) 1600 if (cfg->dig_out_pin)
1452 stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin, 1601 stac92xx_auto_set_pinctl(codec, cfg->dig_out_pin,
1453 AC_PINCTL_OUT_EN); 1602 AC_PINCTL_OUT_EN);
@@ -1598,7 +1747,9 @@ static int patch_stac9200(struct hda_codec *codec)
1598 codec->spec = spec; 1747 codec->spec = spec;
1599 spec->num_pins = 8; 1748 spec->num_pins = 8;
1600 spec->pin_nids = stac9200_pin_nids; 1749 spec->pin_nids = stac9200_pin_nids;
1601 spec->board_config = snd_hda_check_board_config(codec, stac9200_cfg_tbl); 1750 spec->board_config = snd_hda_check_board_config(codec, STAC_9200_MODELS,
1751 stac9200_models,
1752 stac9200_cfg_tbl);
1602 if (spec->board_config < 0) { 1753 if (spec->board_config < 0) {
1603 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n"); 1754 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
1604 err = stac92xx_save_bios_config_regs(codec); 1755 err = stac92xx_save_bios_config_regs(codec);
@@ -1618,6 +1769,7 @@ static int patch_stac9200(struct hda_codec *codec)
1618 spec->adc_nids = stac9200_adc_nids; 1769 spec->adc_nids = stac9200_adc_nids;
1619 spec->mux_nids = stac9200_mux_nids; 1770 spec->mux_nids = stac9200_mux_nids;
1620 spec->num_muxes = 1; 1771 spec->num_muxes = 1;
1772 spec->num_dmics = 0;
1621 1773
1622 spec->init = stac9200_core_init; 1774 spec->init = stac9200_core_init;
1623 spec->mixer = stac9200_mixer; 1775 spec->mixer = stac9200_mixer;
@@ -1633,6 +1785,56 @@ static int patch_stac9200(struct hda_codec *codec)
1633 return 0; 1785 return 0;
1634} 1786}
1635 1787
1788static int patch_stac925x(struct hda_codec *codec)
1789{
1790 struct sigmatel_spec *spec;
1791 int err;
1792
1793 spec = kzalloc(sizeof(*spec), GFP_KERNEL);
1794 if (spec == NULL)
1795 return -ENOMEM;
1796
1797 codec->spec = spec;
1798 spec->num_pins = 8;
1799 spec->pin_nids = stac925x_pin_nids;
1800 spec->board_config = snd_hda_check_board_config(codec, STAC_925x_MODELS,
1801 stac925x_models,
1802 stac925x_cfg_tbl);
1803 if (spec->board_config < 0) {
1804 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x, using BIOS defaults\n");
1805 err = stac92xx_save_bios_config_regs(codec);
1806 if (err < 0) {
1807 stac92xx_free(codec);
1808 return err;
1809 }
1810 spec->pin_configs = spec->bios_pin_configs;
1811 } else if (stac925x_brd_tbl[spec->board_config] != NULL){
1812 spec->pin_configs = stac925x_brd_tbl[spec->board_config];
1813 stac92xx_set_config_regs(codec);
1814 }
1815
1816 spec->multiout.max_channels = 2;
1817 spec->multiout.num_dacs = 1;
1818 spec->multiout.dac_nids = stac925x_dac_nids;
1819 spec->adc_nids = stac925x_adc_nids;
1820 spec->mux_nids = stac925x_mux_nids;
1821 spec->num_muxes = 1;
1822 spec->num_dmics = 0;
1823
1824 spec->init = stac925x_core_init;
1825 spec->mixer = stac925x_mixer;
1826
1827 err = stac92xx_parse_auto_config(codec, 0x8, 0x7);
1828 if (err < 0) {
1829 stac92xx_free(codec);
1830 return err;
1831 }
1832
1833 codec->patch_ops = stac92xx_patch_ops;
1834
1835 return 0;
1836}
1837
1636static int patch_stac922x(struct hda_codec *codec) 1838static int patch_stac922x(struct hda_codec *codec)
1637{ 1839{
1638 struct sigmatel_spec *spec; 1840 struct sigmatel_spec *spec;
@@ -1645,7 +1847,9 @@ static int patch_stac922x(struct hda_codec *codec)
1645 codec->spec = spec; 1847 codec->spec = spec;
1646 spec->num_pins = 10; 1848 spec->num_pins = 10;
1647 spec->pin_nids = stac922x_pin_nids; 1849 spec->pin_nids = stac922x_pin_nids;
1648 spec->board_config = snd_hda_check_board_config(codec, stac922x_cfg_tbl); 1850 spec->board_config = snd_hda_check_board_config(codec, STAC_922X_MODELS,
1851 stac922x_models,
1852 stac922x_cfg_tbl);
1649 if (spec->board_config < 0) { 1853 if (spec->board_config < 0) {
1650 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, " 1854 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
1651 "using BIOS defaults\n"); 1855 "using BIOS defaults\n");
@@ -1663,6 +1867,7 @@ static int patch_stac922x(struct hda_codec *codec)
1663 spec->adc_nids = stac922x_adc_nids; 1867 spec->adc_nids = stac922x_adc_nids;
1664 spec->mux_nids = stac922x_mux_nids; 1868 spec->mux_nids = stac922x_mux_nids;
1665 spec->num_muxes = 2; 1869 spec->num_muxes = 2;
1870 spec->num_dmics = 0;
1666 1871
1667 spec->init = stac922x_core_init; 1872 spec->init = stac922x_core_init;
1668 spec->mixer = stac922x_mixer; 1873 spec->mixer = stac922x_mixer;
@@ -1695,7 +1900,9 @@ static int patch_stac927x(struct hda_codec *codec)
1695 codec->spec = spec; 1900 codec->spec = spec;
1696 spec->num_pins = 14; 1901 spec->num_pins = 14;
1697 spec->pin_nids = stac927x_pin_nids; 1902 spec->pin_nids = stac927x_pin_nids;
1698 spec->board_config = snd_hda_check_board_config(codec, stac927x_cfg_tbl); 1903 spec->board_config = snd_hda_check_board_config(codec, STAC_927X_MODELS,
1904 stac927x_models,
1905 stac927x_cfg_tbl);
1699 if (spec->board_config < 0) { 1906 if (spec->board_config < 0) {
1700 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n"); 1907 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC927x, using BIOS defaults\n");
1701 err = stac92xx_save_bios_config_regs(codec); 1908 err = stac92xx_save_bios_config_regs(codec);
@@ -1714,6 +1921,7 @@ static int patch_stac927x(struct hda_codec *codec)
1714 spec->adc_nids = stac927x_adc_nids; 1921 spec->adc_nids = stac927x_adc_nids;
1715 spec->mux_nids = stac927x_mux_nids; 1922 spec->mux_nids = stac927x_mux_nids;
1716 spec->num_muxes = 3; 1923 spec->num_muxes = 3;
1924 spec->num_dmics = 0;
1717 spec->init = d965_core_init; 1925 spec->init = d965_core_init;
1718 spec->mixer = stac9227_mixer; 1926 spec->mixer = stac9227_mixer;
1719 break; 1927 break;
@@ -1721,6 +1929,7 @@ static int patch_stac927x(struct hda_codec *codec)
1721 spec->adc_nids = stac927x_adc_nids; 1929 spec->adc_nids = stac927x_adc_nids;
1722 spec->mux_nids = stac927x_mux_nids; 1930 spec->mux_nids = stac927x_mux_nids;
1723 spec->num_muxes = 3; 1931 spec->num_muxes = 3;
1932 spec->num_dmics = 0;
1724 spec->init = d965_core_init; 1933 spec->init = d965_core_init;
1725 spec->mixer = stac9227_mixer; 1934 spec->mixer = stac9227_mixer;
1726 break; 1935 break;
@@ -1728,6 +1937,7 @@ static int patch_stac927x(struct hda_codec *codec)
1728 spec->adc_nids = stac927x_adc_nids; 1937 spec->adc_nids = stac927x_adc_nids;
1729 spec->mux_nids = stac927x_mux_nids; 1938 spec->mux_nids = stac927x_mux_nids;
1730 spec->num_muxes = 3; 1939 spec->num_muxes = 3;
1940 spec->num_dmics = 0;
1731 spec->init = stac927x_core_init; 1941 spec->init = stac927x_core_init;
1732 spec->mixer = stac927x_mixer; 1942 spec->mixer = stac927x_mixer;
1733 } 1943 }
@@ -1757,7 +1967,9 @@ static int patch_stac9205(struct hda_codec *codec)
1757 codec->spec = spec; 1967 codec->spec = spec;
1758 spec->num_pins = 14; 1968 spec->num_pins = 14;
1759 spec->pin_nids = stac9205_pin_nids; 1969 spec->pin_nids = stac9205_pin_nids;
1760 spec->board_config = snd_hda_check_board_config(codec, stac9205_cfg_tbl); 1970 spec->board_config = snd_hda_check_board_config(codec, STAC_9205_MODELS,
1971 stac9205_models,
1972 stac9205_cfg_tbl);
1761 if (spec->board_config < 0) { 1973 if (spec->board_config < 0) {
1762 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n"); 1974 snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
1763 err = stac92xx_save_bios_config_regs(codec); 1975 err = stac92xx_save_bios_config_regs(codec);
@@ -1773,13 +1985,28 @@ static int patch_stac9205(struct hda_codec *codec)
1773 1985
1774 spec->adc_nids = stac9205_adc_nids; 1986 spec->adc_nids = stac9205_adc_nids;
1775 spec->mux_nids = stac9205_mux_nids; 1987 spec->mux_nids = stac9205_mux_nids;
1776 spec->num_muxes = 3; 1988 spec->num_muxes = 2;
1989 spec->dmic_nids = stac9205_dmic_nids;
1990 spec->num_dmics = 2;
1991 spec->dmux_nid = 0x1d;
1777 1992
1778 spec->init = stac9205_core_init; 1993 spec->init = stac9205_core_init;
1779 spec->mixer = stac9205_mixer; 1994 spec->mixer = stac9205_mixer;
1780 1995
1781 spec->multiout.dac_nids = spec->dac_nids; 1996 spec->multiout.dac_nids = spec->dac_nids;
1782 1997
1998 /* Configure GPIO0 as EAPD output */
1999 snd_hda_codec_write(codec, codec->afg, 0,
2000 AC_VERB_SET_GPIO_DIRECTION, 0x00000001);
2001 /* Configure GPIO0 as CMOS */
2002 snd_hda_codec_write(codec, codec->afg, 0, 0x7e7, 0x00000000);
2003 /* Assert GPIO0 high */
2004 snd_hda_codec_write(codec, codec->afg, 0,
2005 AC_VERB_SET_GPIO_DATA, 0x00000001);
2006 /* Enable GPIO0 */
2007 snd_hda_codec_write(codec, codec->afg, 0,
2008 AC_VERB_SET_GPIO_MASK, 0x00000001);
2009
1783 err = stac92xx_parse_auto_config(codec, 0x1f, 0x20); 2010 err = stac92xx_parse_auto_config(codec, 0x1f, 0x20);
1784 if (err < 0) { 2011 if (err < 0) {
1785 stac92xx_free(codec); 2012 stac92xx_free(codec);
@@ -1963,18 +2190,19 @@ enum { /* FE and SZ series. id=0x83847661 and subsys=0x104D0700 or 104D1000. */
1963 /* Unknown. id=0x83847661 and subsys=0x104D1200. */ 2190 /* Unknown. id=0x83847661 and subsys=0x104D1200. */
1964 STAC9872K_VAIO, 2191 STAC9872K_VAIO,
1965 /* AR Series. id=0x83847664 and subsys=104D1300 */ 2192 /* AR Series. id=0x83847664 and subsys=104D1300 */
1966 CXD9872AKD_VAIO 2193 CXD9872AKD_VAIO,
1967 }; 2194 STAC_9872_MODELS,
1968 2195};
1969static struct hda_board_config stac9872_cfg_tbl[] = { 2196
1970 { .modelname = "vaio", .config = CXD9872RD_VAIO }, 2197static const char *stac9872_models[STAC_9872_MODELS] = {
1971 { .modelname = "vaio-ar", .config = CXD9872AKD_VAIO }, 2198 [CXD9872RD_VAIO] = "vaio",
1972 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81e6, 2199 [CXD9872AKD_VAIO] = "vaio-ar",
1973 .config = CXD9872RD_VAIO }, 2200};
1974 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81ef, 2201
1975 .config = CXD9872RD_VAIO }, 2202static struct snd_pci_quirk stac9872_cfg_tbl[] = {
1976 { .pci_subvendor = 0x104d, .pci_subdevice = 0x81fd, 2203 SND_PCI_QUIRK(0x104d, 0x81e6, "Sony VAIO F/S", CXD9872RD_VAIO),
1977 .config = CXD9872AKD_VAIO }, 2204 SND_PCI_QUIRK(0x104d, 0x81ef, "Sony VAIO F/S", CXD9872RD_VAIO),
2205 SND_PCI_QUIRK(0x104d, 0x81fd, "Sony VAIO AR", CXD9872AKD_VAIO),
1978 {} 2206 {}
1979}; 2207};
1980 2208
@@ -1983,7 +2211,9 @@ static int patch_stac9872(struct hda_codec *codec)
1983 struct sigmatel_spec *spec; 2211 struct sigmatel_spec *spec;
1984 int board_config; 2212 int board_config;
1985 2213
1986 board_config = snd_hda_check_board_config(codec, stac9872_cfg_tbl); 2214 board_config = snd_hda_check_board_config(codec, STAC_9872_MODELS,
2215 stac9872_models,
2216 stac9872_cfg_tbl);
1987 if (board_config < 0) 2217 if (board_config < 0)
1988 /* unknown config, let generic-parser do its job... */ 2218 /* unknown config, let generic-parser do its job... */
1989 return snd_hda_parse_generic_codec(codec); 2219 return snd_hda_parse_generic_codec(codec);
@@ -2055,6 +2285,12 @@ struct hda_codec_preset snd_hda_preset_sigmatel[] = {
2055 { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x }, 2285 { .id = 0x83847627, .name = "STAC9271D", .patch = patch_stac927x },
2056 { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x }, 2286 { .id = 0x83847628, .name = "STAC9274X5NH", .patch = patch_stac927x },
2057 { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x }, 2287 { .id = 0x83847629, .name = "STAC9274D5NH", .patch = patch_stac927x },
2288 { .id = 0x83847632, .name = "STAC9202", .patch = patch_stac925x },
2289 { .id = 0x83847633, .name = "STAC9202D", .patch = patch_stac925x },
2290 { .id = 0x83847634, .name = "STAC9250", .patch = patch_stac925x },
2291 { .id = 0x83847635, .name = "STAC9250D", .patch = patch_stac925x },
2292 { .id = 0x83847636, .name = "STAC9251", .patch = patch_stac925x },
2293 { .id = 0x83847637, .name = "STAC9250D", .patch = patch_stac925x },
2058 /* The following does not take into account .id=0x83847661 when subsys = 2294 /* The following does not take into account .id=0x83847661 when subsys =
2059 * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are 2295 * 104D0C00 which is STAC9225s. Because of this, some SZ Notebooks are
2060 * currently not fully supported. 2296 * currently not fully supported.
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
new file mode 100644
index 000000000000..4c839b031729
--- /dev/null
+++ b/sound/pci/hda/patch_via.c
@@ -0,0 +1,1396 @@
1/*
2 * Universal Interface for Intel High Definition Audio Codec
3 *
4 * HD audio interface patch for VIA VT1708 codec
5 *
6 * Copyright (c) 2006 Lydia Wang <lydiawang@viatech.com>
7 * Takashi Iwai <tiwai@suse.de>
8 *
9 * This driver is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This driver is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 */
23
24/* * * * * * * * * * * * * * Release History * * * * * * * * * * * * * * * * */
25/* */
26/* 2006-03-03 Lydia Wang Create the basic patch to support VT1708 codec */
27/* 2006-03-14 Lydia Wang Modify hard code for some pin widget nid */
28/* 2006-08-02 Lydia Wang Add support to VT1709 codec */
29/* 2006-09-08 Lydia Wang Fix internal loopback recording source select bug */
30/* */
31/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
32
33
34#include <sound/driver.h>
35#include <linux/init.h>
36#include <linux/delay.h>
37#include <linux/slab.h>
38#include <linux/pci.h>
39#include <sound/core.h>
40#include "hda_codec.h"
41#include "hda_local.h"
42
43
44/* amp values */
45#define AMP_VAL_IDX_SHIFT 19
46#define AMP_VAL_IDX_MASK (0x0f<<19)
47
48#define NUM_CONTROL_ALLOC 32
49#define NUM_VERB_ALLOC 32
50
51/* Pin Widget NID */
52#define VT1708_HP_NID 0x13
53#define VT1708_DIGOUT_NID 0x14
54#define VT1708_DIGIN_NID 0x16
55
56#define VT1709_HP_DAC_NID 0x28
57#define VT1709_DIGOUT_NID 0x13
58#define VT1709_DIGIN_NID 0x17
59
60#define IS_VT1708_VENDORID(x) ((x) >= 0x11061708 && (x) <= 0x1106170b)
61#define IS_VT1709_10CH_VENDORID(x) ((x) >= 0x1106e710 && (x) <= 0x1106e713)
62#define IS_VT1709_6CH_VENDORID(x) ((x) >= 0x1106e714 && (x) <= 0x1106e717)
63
64
65enum {
66 VIA_CTL_WIDGET_VOL,
67 VIA_CTL_WIDGET_MUTE,
68};
69
70enum {
71 AUTO_SEQ_FRONT,
72 AUTO_SEQ_SURROUND,
73 AUTO_SEQ_CENLFE,
74 AUTO_SEQ_SIDE
75};
76
77static struct snd_kcontrol_new vt1708_control_templates[] = {
78 HDA_CODEC_VOLUME(NULL, 0, 0, 0),
79 HDA_CODEC_MUTE(NULL, 0, 0, 0),
80};
81
82
83struct via_spec {
84 /* codec parameterization */
85 struct snd_kcontrol_new *mixers[3];
86 unsigned int num_mixers;
87
88 struct hda_verb *init_verbs;
89
90 char *stream_name_analog;
91 struct hda_pcm_stream *stream_analog_playback;
92 struct hda_pcm_stream *stream_analog_capture;
93
94 char *stream_name_digital;
95 struct hda_pcm_stream *stream_digital_playback;
96 struct hda_pcm_stream *stream_digital_capture;
97
98 /* playback */
99 struct hda_multi_out multiout;
100
101 /* capture */
102 unsigned int num_adc_nids;
103 hda_nid_t *adc_nids;
104 hda_nid_t dig_in_nid;
105
106 /* capture source */
107 const struct hda_input_mux *input_mux;
108 unsigned int cur_mux[3];
109
110 /* PCM information */
111 struct hda_pcm pcm_rec[2];
112
113 /* dynamic controls, init_verbs and input_mux */
114 struct auto_pin_cfg autocfg;
115 unsigned int num_kctl_alloc, num_kctl_used;
116 struct snd_kcontrol_new *kctl_alloc;
117 struct hda_input_mux private_imux;
118 hda_nid_t private_dac_nids[4];
119};
120
121static hda_nid_t vt1708_adc_nids[2] = {
122 /* ADC1-2 */
123 0x15, 0x27
124};
125
126static hda_nid_t vt1709_adc_nids[3] = {
127 /* ADC1-2 */
128 0x14, 0x15, 0x16
129};
130
131/* add dynamic controls */
132static int via_add_control(struct via_spec *spec, int type, const char *name,
133 unsigned long val)
134{
135 struct snd_kcontrol_new *knew;
136
137 if (spec->num_kctl_used >= spec->num_kctl_alloc) {
138 int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
139
140 /* array + terminator */
141 knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
142 if (!knew)
143 return -ENOMEM;
144 if (spec->kctl_alloc) {
145 memcpy(knew, spec->kctl_alloc,
146 sizeof(*knew) * spec->num_kctl_alloc);
147 kfree(spec->kctl_alloc);
148 }
149 spec->kctl_alloc = knew;
150 spec->num_kctl_alloc = num;
151 }
152
153 knew = &spec->kctl_alloc[spec->num_kctl_used];
154 *knew = vt1708_control_templates[type];
155 knew->name = kstrdup(name, GFP_KERNEL);
156
157 if (!knew->name)
158 return -ENOMEM;
159 knew->private_value = val;
160 spec->num_kctl_used++;
161 return 0;
162}
163
164/* create input playback/capture controls for the given pin */
165static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
166 const char *ctlname, int idx, int mix_nid)
167{
168 char name[32];
169 int err;
170
171 sprintf(name, "%s Playback Volume", ctlname);
172 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
173 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
174 if (err < 0)
175 return err;
176 sprintf(name, "%s Playback Switch", ctlname);
177 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
178 HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT));
179 if (err < 0)
180 return err;
181 return 0;
182}
183
184static void via_auto_set_output_and_unmute(struct hda_codec *codec,
185 hda_nid_t nid, int pin_type,
186 int dac_idx)
187{
188 /* set as output */
189 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
190 pin_type);
191 snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE,
192 AMP_OUT_UNMUTE);
193}
194
195
196static void via_auto_init_multi_out(struct hda_codec *codec)
197{
198 struct via_spec *spec = codec->spec;
199 int i;
200
201 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
202 hda_nid_t nid = spec->autocfg.line_out_pins[i];
203 if (nid)
204 via_auto_set_output_and_unmute(codec, nid, PIN_OUT, i);
205 }
206}
207
208static void via_auto_init_hp_out(struct hda_codec *codec)
209{
210 struct via_spec *spec = codec->spec;
211 hda_nid_t pin;
212
213 pin = spec->autocfg.hp_pins[0];
214 if (pin) /* connect to front */
215 via_auto_set_output_and_unmute(codec, pin, PIN_HP, 0);
216}
217
218static void via_auto_init_analog_input(struct hda_codec *codec)
219{
220 struct via_spec *spec = codec->spec;
221 int i;
222
223 for (i = 0; i < AUTO_PIN_LAST; i++) {
224 hda_nid_t nid = spec->autocfg.input_pins[i];
225
226 snd_hda_codec_write(codec, nid, 0,
227 AC_VERB_SET_PIN_WIDGET_CONTROL,
228 (i <= AUTO_PIN_FRONT_MIC ?
229 PIN_VREF50 : PIN_IN));
230
231 }
232}
233/*
234 * input MUX handling
235 */
236static int via_mux_enum_info(struct snd_kcontrol *kcontrol,
237 struct snd_ctl_elem_info *uinfo)
238{
239 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
240 struct via_spec *spec = codec->spec;
241 return snd_hda_input_mux_info(spec->input_mux, uinfo);
242}
243
244static int via_mux_enum_get(struct snd_kcontrol *kcontrol,
245 struct snd_ctl_elem_value *ucontrol)
246{
247 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
248 struct via_spec *spec = codec->spec;
249 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
250
251 ucontrol->value.enumerated.item[0] = spec->cur_mux[adc_idx];
252 return 0;
253}
254
255static int via_mux_enum_put(struct snd_kcontrol *kcontrol,
256 struct snd_ctl_elem_value *ucontrol)
257{
258 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
259 struct via_spec *spec = codec->spec;
260 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
261 unsigned int vendor_id = codec->vendor_id;
262
263 /* AIW0 lydia 060801 add for correct sw0 input select */
264 if (IS_VT1708_VENDORID(vendor_id) && (adc_idx == 0))
265 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
266 0x18, &spec->cur_mux[adc_idx]);
267 else if ((IS_VT1709_10CH_VENDORID(vendor_id) ||
268 IS_VT1709_6CH_VENDORID(vendor_id)) && (adc_idx == 0) )
269 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
270 0x19, &spec->cur_mux[adc_idx]);
271 else
272 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol,
273 spec->adc_nids[adc_idx],
274 &spec->cur_mux[adc_idx]);
275}
276
277/* capture mixer elements */
278static struct snd_kcontrol_new vt1708_capture_mixer[] = {
279 HDA_CODEC_VOLUME("Capture Volume", 0x15, 0x0, HDA_INPUT),
280 HDA_CODEC_MUTE("Capture Switch", 0x15, 0x0, HDA_INPUT),
281 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x27, 0x0, HDA_INPUT),
282 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x27, 0x0, HDA_INPUT),
283 {
284 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
285 /* The multiple "Capture Source" controls confuse alsamixer
286 * So call somewhat different..
287 * FIXME: the controls appear in the "playback" view!
288 */
289 /* .name = "Capture Source", */
290 .name = "Input Source",
291 .count = 1,
292 .info = via_mux_enum_info,
293 .get = via_mux_enum_get,
294 .put = via_mux_enum_put,
295 },
296 { } /* end */
297};
298/*
299 * generic initialization of ADC, input mixers and output mixers
300 */
301static struct hda_verb vt1708_volume_init_verbs[] = {
302 /*
303 * Unmute ADC0-1 and set the default input to mic-in
304 */
305 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
306 {0x27, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
307
308
309 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
310 * mixer widget
311 */
312 /* Amp Indices: CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
313 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
314 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
315 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
316 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
317 {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
318
319 /*
320 * Set up output mixers (0x19 - 0x1b)
321 */
322 /* set vol=0 to output mixers */
323 {0x19, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
324 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
325 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
326
327 /* Setup default input to PW4 */
328 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
329 /* Set mic as default input of sw0 */
330 {0x18, AC_VERB_SET_CONNECT_SEL, 0x2},
331 /* PW9 Output enable */
332 {0x25, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
333};
334
335static int via_playback_pcm_open(struct hda_pcm_stream *hinfo,
336 struct hda_codec *codec,
337 struct snd_pcm_substream *substream)
338{
339 struct via_spec *spec = codec->spec;
340 return snd_hda_multi_out_analog_open(codec, &spec->multiout, substream);
341}
342
343static int via_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
344 struct hda_codec *codec,
345 unsigned int stream_tag,
346 unsigned int format,
347 struct snd_pcm_substream *substream)
348{
349 struct via_spec *spec = codec->spec;
350 return snd_hda_multi_out_analog_prepare(codec, &spec->multiout,
351 stream_tag, format, substream);
352}
353
354static int via_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
355 struct hda_codec *codec,
356 struct snd_pcm_substream *substream)
357{
358 struct via_spec *spec = codec->spec;
359 return snd_hda_multi_out_analog_cleanup(codec, &spec->multiout);
360}
361
362/*
363 * Digital out
364 */
365static int via_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
366 struct hda_codec *codec,
367 struct snd_pcm_substream *substream)
368{
369 struct via_spec *spec = codec->spec;
370 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
371}
372
373static int via_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
374 struct hda_codec *codec,
375 struct snd_pcm_substream *substream)
376{
377 struct via_spec *spec = codec->spec;
378 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
379}
380
381/*
382 * Analog capture
383 */
384static int via_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
385 struct hda_codec *codec,
386 unsigned int stream_tag,
387 unsigned int format,
388 struct snd_pcm_substream *substream)
389{
390 struct via_spec *spec = codec->spec;
391
392 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
393 stream_tag, 0, format);
394 return 0;
395}
396
397static int via_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
398 struct hda_codec *codec,
399 struct snd_pcm_substream *substream)
400{
401 struct via_spec *spec = codec->spec;
402 snd_hda_codec_setup_stream(codec, spec->adc_nids[substream->number],
403 0, 0, 0);
404 return 0;
405}
406
407static struct hda_pcm_stream vt1708_pcm_analog_playback = {
408 .substreams = 1,
409 .channels_min = 2,
410 .channels_max = 8,
411 .nid = 0x10, /* NID to query formats and rates */
412 .ops = {
413 .open = via_playback_pcm_open,
414 .prepare = via_playback_pcm_prepare,
415 .cleanup = via_playback_pcm_cleanup
416 },
417};
418
419static struct hda_pcm_stream vt1708_pcm_analog_capture = {
420 .substreams = 2,
421 .channels_min = 2,
422 .channels_max = 2,
423 .nid = 0x15, /* NID to query formats and rates */
424 .ops = {
425 .prepare = via_capture_pcm_prepare,
426 .cleanup = via_capture_pcm_cleanup
427 },
428};
429
430static struct hda_pcm_stream vt1708_pcm_digital_playback = {
431 .substreams = 1,
432 .channels_min = 2,
433 .channels_max = 2,
434 /* NID is set in via_build_pcms */
435 .ops = {
436 .open = via_dig_playback_pcm_open,
437 .close = via_dig_playback_pcm_close
438 },
439};
440
441static struct hda_pcm_stream vt1708_pcm_digital_capture = {
442 .substreams = 1,
443 .channels_min = 2,
444 .channels_max = 2,
445};
446
447static int via_build_controls(struct hda_codec *codec)
448{
449 struct via_spec *spec = codec->spec;
450 int err;
451 int i;
452
453 for (i = 0; i < spec->num_mixers; i++) {
454 err = snd_hda_add_new_ctls(codec, spec->mixers[i]);
455 if (err < 0)
456 return err;
457 }
458
459 if (spec->multiout.dig_out_nid) {
460 err = snd_hda_create_spdif_out_ctls(codec,
461 spec->multiout.dig_out_nid);
462 if (err < 0)
463 return err;
464 }
465 if (spec->dig_in_nid) {
466 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
467 if (err < 0)
468 return err;
469 }
470 return 0;
471}
472
473static int via_build_pcms(struct hda_codec *codec)
474{
475 struct via_spec *spec = codec->spec;
476 struct hda_pcm *info = spec->pcm_rec;
477
478 codec->num_pcms = 1;
479 codec->pcm_info = info;
480
481 info->name = spec->stream_name_analog;
482 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = *(spec->stream_analog_playback);
483 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dac_nids[0];
484 info->stream[SNDRV_PCM_STREAM_CAPTURE] = *(spec->stream_analog_capture);
485 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->adc_nids[0];
486
487 info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max =
488 spec->multiout.max_channels;
489
490 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
491 codec->num_pcms++;
492 info++;
493 info->name = spec->stream_name_digital;
494 if (spec->multiout.dig_out_nid) {
495 info->stream[SNDRV_PCM_STREAM_PLAYBACK] =
496 *(spec->stream_digital_playback);
497 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid =
498 spec->multiout.dig_out_nid;
499 }
500 if (spec->dig_in_nid) {
501 info->stream[SNDRV_PCM_STREAM_CAPTURE] =
502 *(spec->stream_digital_capture);
503 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid =
504 spec->dig_in_nid;
505 }
506 }
507
508 return 0;
509}
510
511static void via_free(struct hda_codec *codec)
512{
513 struct via_spec *spec = codec->spec;
514 unsigned int i;
515
516 if (!spec)
517 return;
518
519 if (spec->kctl_alloc) {
520 for (i = 0; i < spec->num_kctl_used; i++)
521 kfree(spec->kctl_alloc[i].name);
522 kfree(spec->kctl_alloc);
523 }
524
525 kfree(codec->spec);
526}
527
528static int via_init(struct hda_codec *codec)
529{
530 struct via_spec *spec = codec->spec;
531 snd_hda_sequence_write(codec, spec->init_verbs);
532 return 0;
533}
534
535#ifdef CONFIG_PM
536/*
537 * resume
538 */
539static int via_resume(struct hda_codec *codec)
540{
541 struct via_spec *spec = codec->spec;
542 int i;
543
544 via_init(codec);
545 for (i = 0; i < spec->num_mixers; i++)
546 snd_hda_resume_ctls(codec, spec->mixers[i]);
547 if (spec->multiout.dig_out_nid)
548 snd_hda_resume_spdif_out(codec);
549 if (spec->dig_in_nid)
550 snd_hda_resume_spdif_in(codec);
551
552 return 0;
553}
554#endif
555
556/*
557 */
558static struct hda_codec_ops via_patch_ops = {
559 .build_controls = via_build_controls,
560 .build_pcms = via_build_pcms,
561 .init = via_init,
562 .free = via_free,
563#ifdef CONFIG_PM
564 .resume = via_resume,
565#endif
566};
567
568/* fill in the dac_nids table from the parsed pin configuration */
569static int vt1708_auto_fill_dac_nids(struct via_spec *spec,
570 const struct auto_pin_cfg *cfg)
571{
572 int i;
573 hda_nid_t nid;
574
575 spec->multiout.num_dacs = cfg->line_outs;
576
577 spec->multiout.dac_nids = spec->private_dac_nids;
578
579 for(i = 0; i < 4; i++) {
580 nid = cfg->line_out_pins[i];
581 if (nid) {
582 /* config dac list */
583 switch (i) {
584 case AUTO_SEQ_FRONT:
585 spec->multiout.dac_nids[i] = 0x10;
586 break;
587 case AUTO_SEQ_CENLFE:
588 spec->multiout.dac_nids[i] = 0x12;
589 break;
590 case AUTO_SEQ_SURROUND:
591 spec->multiout.dac_nids[i] = 0x13;
592 break;
593 case AUTO_SEQ_SIDE:
594 spec->multiout.dac_nids[i] = 0x11;
595 break;
596 }
597 }
598 }
599
600 return 0;
601}
602
603/* add playback controls from the parsed DAC table */
604static int vt1708_auto_create_multi_out_ctls(struct via_spec *spec,
605 const struct auto_pin_cfg *cfg)
606{
607 char name[32];
608 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
609 hda_nid_t nid, nid_vol = 0;
610 int i, err;
611
612 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
613 nid = cfg->line_out_pins[i];
614
615 if (!nid)
616 continue;
617
618 if (i != AUTO_SEQ_FRONT)
619 nid_vol = 0x1b - i + 1;
620
621 if (i == AUTO_SEQ_CENLFE) {
622 /* Center/LFE */
623 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
624 "Center Playback Volume",
625 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
626 if (err < 0)
627 return err;
628 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
629 "LFE Playback Volume",
630 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
631 if (err < 0)
632 return err;
633 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
634 "Center Playback Switch",
635 HDA_COMPOSE_AMP_VAL(nid_vol, 1, 0, HDA_OUTPUT));
636 if (err < 0)
637 return err;
638 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
639 "LFE Playback Switch",
640 HDA_COMPOSE_AMP_VAL(nid_vol, 2, 0, HDA_OUTPUT));
641 if (err < 0)
642 return err;
643 } else if (i == AUTO_SEQ_FRONT){
644 /* add control to mixer index 0 */
645 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
646 "Master Front Playback Volume",
647 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
648 if (err < 0)
649 return err;
650 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
651 "Master Front Playback Switch",
652 HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_INPUT));
653 if (err < 0)
654 return err;
655
656 /* add control to PW3 */
657 sprintf(name, "%s Playback Volume", chname[i]);
658 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
659 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
660 if (err < 0)
661 return err;
662 sprintf(name, "%s Playback Switch", chname[i]);
663 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
664 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
665 if (err < 0)
666 return err;
667 } else {
668 sprintf(name, "%s Playback Volume", chname[i]);
669 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
670 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
671 if (err < 0)
672 return err;
673 sprintf(name, "%s Playback Switch", chname[i]);
674 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
675 HDA_COMPOSE_AMP_VAL(nid_vol, 3, 0, HDA_OUTPUT));
676 if (err < 0)
677 return err;
678 }
679 }
680
681 return 0;
682}
683
684static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
685{
686 int err;
687
688 if (!pin)
689 return 0;
690
691 spec->multiout.hp_nid = VT1708_HP_NID; /* AOW3 */
692
693 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
694 "Headphone Playback Volume",
695 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
696 if (err < 0)
697 return err;
698 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
699 "Headphone Playback Switch",
700 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
701 if (err < 0)
702 return err;
703
704 return 0;
705}
706
707/* create playback/capture controls for input pins */
708static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec,
709 const struct auto_pin_cfg *cfg)
710{
711 static char *labels[] = {
712 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
713 };
714 struct hda_input_mux *imux = &spec->private_imux;
715 int i, err, idx = 0;
716
717 /* for internal loopback recording select */
718 imux->items[imux->num_items].label = "Stereo Mixer";
719 imux->items[imux->num_items].index = idx;
720 imux->num_items++;
721
722 for (i = 0; i < AUTO_PIN_LAST; i++) {
723 if (!cfg->input_pins[i])
724 continue;
725
726 switch (cfg->input_pins[i]) {
727 case 0x1d: /* Mic */
728 idx = 2;
729 break;
730
731 case 0x1e: /* Line In */
732 idx = 3;
733 break;
734
735 case 0x21: /* Front Mic */
736 idx = 4;
737 break;
738
739 case 0x24: /* CD */
740 idx = 1;
741 break;
742 }
743 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
744 idx, 0x17);
745 if (err < 0)
746 return err;
747 imux->items[imux->num_items].label = labels[i];
748 imux->items[imux->num_items].index = idx;
749 imux->num_items++;
750 }
751 return 0;
752}
753
754static int vt1708_parse_auto_config(struct hda_codec *codec)
755{
756 struct via_spec *spec = codec->spec;
757 int err;
758
759 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
760 if (err < 0)
761 return err;
762 err = vt1708_auto_fill_dac_nids(spec, &spec->autocfg);
763 if (err < 0)
764 return err;
765 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
766 return 0; /* can't find valid BIOS pin config */
767
768 err = vt1708_auto_create_multi_out_ctls(spec, &spec->autocfg);
769 if (err < 0)
770 return err;
771 err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
772 if (err < 0)
773 return err;
774 err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg);
775 if (err < 0)
776 return err;
777
778 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
779
780 if (spec->autocfg.dig_out_pin)
781 spec->multiout.dig_out_nid = VT1708_DIGOUT_NID;
782 if (spec->autocfg.dig_in_pin)
783 spec->dig_in_nid = VT1708_DIGIN_NID;
784
785 if (spec->kctl_alloc)
786 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
787
788 spec->init_verbs = vt1708_volume_init_verbs;
789
790 spec->input_mux = &spec->private_imux;
791
792 return 1;
793}
794
795/* init callback for auto-configuration model -- overriding the default init */
796static int via_auto_init(struct hda_codec *codec)
797{
798 via_init(codec);
799 via_auto_init_multi_out(codec);
800 via_auto_init_hp_out(codec);
801 via_auto_init_analog_input(codec);
802 return 0;
803}
804
805static int patch_vt1708(struct hda_codec *codec)
806{
807 struct via_spec *spec;
808 int err;
809
810 /* create a codec specific record */
811 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
812 if (spec == NULL)
813 return -ENOMEM;
814
815 codec->spec = spec;
816
817 /* automatic parse from the BIOS config */
818 err = vt1708_parse_auto_config(codec);
819 if (err < 0) {
820 via_free(codec);
821 return err;
822 } else if (!err) {
823 printk(KERN_INFO "hda_codec: Cannot set up configuration "
824 "from BIOS. Using genenic mode...\n");
825 }
826
827
828 spec->stream_name_analog = "VT1708 Analog";
829 spec->stream_analog_playback = &vt1708_pcm_analog_playback;
830 spec->stream_analog_capture = &vt1708_pcm_analog_capture;
831
832 spec->stream_name_digital = "VT1708 Digital";
833 spec->stream_digital_playback = &vt1708_pcm_digital_playback;
834 spec->stream_digital_capture = &vt1708_pcm_digital_capture;
835
836
837 if (!spec->adc_nids && spec->input_mux) {
838 spec->adc_nids = vt1708_adc_nids;
839 spec->num_adc_nids = ARRAY_SIZE(vt1708_adc_nids);
840 spec->mixers[spec->num_mixers] = vt1708_capture_mixer;
841 spec->num_mixers++;
842 }
843
844 codec->patch_ops = via_patch_ops;
845
846 codec->patch_ops.init = via_auto_init;
847
848 return 0;
849}
850
851/* capture mixer elements */
852static struct snd_kcontrol_new vt1709_capture_mixer[] = {
853 HDA_CODEC_VOLUME("Capture Volume", 0x14, 0x0, HDA_INPUT),
854 HDA_CODEC_MUTE("Capture Switch", 0x14, 0x0, HDA_INPUT),
855 HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x15, 0x0, HDA_INPUT),
856 HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x15, 0x0, HDA_INPUT),
857 HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x16, 0x0, HDA_INPUT),
858 HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x16, 0x0, HDA_INPUT),
859 {
860 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
861 /* The multiple "Capture Source" controls confuse alsamixer
862 * So call somewhat different..
863 * FIXME: the controls appear in the "playback" view!
864 */
865 /* .name = "Capture Source", */
866 .name = "Input Source",
867 .count = 1,
868 .info = via_mux_enum_info,
869 .get = via_mux_enum_get,
870 .put = via_mux_enum_put,
871 },
872 { } /* end */
873};
874
875/*
876 * generic initialization of ADC, input mixers and output mixers
877 */
878static struct hda_verb vt1709_10ch_volume_init_verbs[] = {
879 /*
880 * Unmute ADC0-2 and set the default input to mic-in
881 */
882 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
883 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
884 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
885
886
887 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
888 * mixer widget
889 */
890 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
891 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
892 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
893 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
894 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
895 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
896
897 /*
898 * Set up output selector (0x1a, 0x1b, 0x29)
899 */
900 /* set vol=0 to output mixers */
901 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
902 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
903 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
904
905 /*
906 * Unmute PW3 and PW4
907 */
908 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
909 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
910
911 /* Set input of PW4 as AOW4 */
912 {0x20, AC_VERB_SET_CONNECT_SEL, 0x1},
913 /* Set mic as default input of sw0 */
914 {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
915 /* PW9 Output enable */
916 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
917 { }
918};
919
920static struct hda_pcm_stream vt1709_10ch_pcm_analog_playback = {
921 .substreams = 1,
922 .channels_min = 2,
923 .channels_max = 10,
924 .nid = 0x10, /* NID to query formats and rates */
925 .ops = {
926 .open = via_playback_pcm_open,
927 .prepare = via_playback_pcm_prepare,
928 .cleanup = via_playback_pcm_cleanup
929 },
930};
931
932static struct hda_pcm_stream vt1709_6ch_pcm_analog_playback = {
933 .substreams = 1,
934 .channels_min = 2,
935 .channels_max = 6,
936 .nid = 0x10, /* NID to query formats and rates */
937 .ops = {
938 .open = via_playback_pcm_open,
939 .prepare = via_playback_pcm_prepare,
940 .cleanup = via_playback_pcm_cleanup
941 },
942};
943
944static struct hda_pcm_stream vt1709_pcm_analog_capture = {
945 .substreams = 2,
946 .channels_min = 2,
947 .channels_max = 2,
948 .nid = 0x14, /* NID to query formats and rates */
949 .ops = {
950 .prepare = via_capture_pcm_prepare,
951 .cleanup = via_capture_pcm_cleanup
952 },
953};
954
955static struct hda_pcm_stream vt1709_pcm_digital_playback = {
956 .substreams = 1,
957 .channels_min = 2,
958 .channels_max = 2,
959 /* NID is set in via_build_pcms */
960 .ops = {
961 .open = via_dig_playback_pcm_open,
962 .close = via_dig_playback_pcm_close
963 },
964};
965
966static struct hda_pcm_stream vt1709_pcm_digital_capture = {
967 .substreams = 1,
968 .channels_min = 2,
969 .channels_max = 2,
970};
971
972static int vt1709_auto_fill_dac_nids(struct via_spec *spec,
973 const struct auto_pin_cfg *cfg)
974{
975 int i;
976 hda_nid_t nid;
977
978 if (cfg->line_outs == 4) /* 10 channels */
979 spec->multiout.num_dacs = cfg->line_outs+1; /* AOW0~AOW4 */
980 else if (cfg->line_outs == 3) /* 6 channels */
981 spec->multiout.num_dacs = cfg->line_outs; /* AOW0~AOW2 */
982
983 spec->multiout.dac_nids = spec->private_dac_nids;
984
985 if (cfg->line_outs == 4) { /* 10 channels */
986 for (i = 0; i < cfg->line_outs; i++) {
987 nid = cfg->line_out_pins[i];
988 if (nid) {
989 /* config dac list */
990 switch (i) {
991 case AUTO_SEQ_FRONT:
992 /* AOW0 */
993 spec->multiout.dac_nids[i] = 0x10;
994 break;
995 case AUTO_SEQ_CENLFE:
996 /* AOW2 */
997 spec->multiout.dac_nids[i] = 0x12;
998 break;
999 case AUTO_SEQ_SURROUND:
1000 /* AOW3 */
1001 spec->multiout.dac_nids[i] = 0x27;
1002 break;
1003 case AUTO_SEQ_SIDE:
1004 /* AOW1 */
1005 spec->multiout.dac_nids[i] = 0x11;
1006 break;
1007 default:
1008 break;
1009 }
1010 }
1011 }
1012 spec->multiout.dac_nids[cfg->line_outs] = 0x28; /* AOW4 */
1013
1014 } else if (cfg->line_outs == 3) { /* 6 channels */
1015 for(i = 0; i < cfg->line_outs; i++) {
1016 nid = cfg->line_out_pins[i];
1017 if (nid) {
1018 /* config dac list */
1019 switch(i) {
1020 case AUTO_SEQ_FRONT:
1021 /* AOW0 */
1022 spec->multiout.dac_nids[i] = 0x10;
1023 break;
1024 case AUTO_SEQ_CENLFE:
1025 /* AOW2 */
1026 spec->multiout.dac_nids[i] = 0x12;
1027 break;
1028 case AUTO_SEQ_SURROUND:
1029 /* AOW1 */
1030 spec->multiout.dac_nids[i] = 0x11;
1031 break;
1032 default:
1033 break;
1034 }
1035 }
1036 }
1037 }
1038
1039 return 0;
1040}
1041
1042/* add playback controls from the parsed DAC table */
1043static int vt1709_auto_create_multi_out_ctls(struct via_spec *spec,
1044 const struct auto_pin_cfg *cfg)
1045{
1046 char name[32];
1047 static const char *chname[4] = { "Front", "Surround", "C/LFE", "Side" };
1048 hda_nid_t nid = 0;
1049 int i, err;
1050
1051 for (i = 0; i <= AUTO_SEQ_SIDE; i++) {
1052 nid = cfg->line_out_pins[i];
1053
1054 if (!nid)
1055 continue;
1056
1057 if (i == AUTO_SEQ_CENLFE) {
1058 /* Center/LFE */
1059 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1060 "Center Playback Volume",
1061 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1062 if (err < 0)
1063 return err;
1064 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1065 "LFE Playback Volume",
1066 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1067 if (err < 0)
1068 return err;
1069 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1070 "Center Playback Switch",
1071 HDA_COMPOSE_AMP_VAL(0x1b, 1, 0, HDA_OUTPUT));
1072 if (err < 0)
1073 return err;
1074 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1075 "LFE Playback Switch",
1076 HDA_COMPOSE_AMP_VAL(0x1b, 2, 0, HDA_OUTPUT));
1077 if (err < 0)
1078 return err;
1079 } else if (i == AUTO_SEQ_FRONT){
1080 /* add control to mixer index 0 */
1081 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1082 "Master Front Playback Volume",
1083 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1084 if (err < 0)
1085 return err;
1086 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1087 "Master Front Playback Switch",
1088 HDA_COMPOSE_AMP_VAL(0x18, 3, 0, HDA_INPUT));
1089 if (err < 0)
1090 return err;
1091
1092 /* add control to PW3 */
1093 sprintf(name, "%s Playback Volume", chname[i]);
1094 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1095 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1096 if (err < 0)
1097 return err;
1098 sprintf(name, "%s Playback Switch", chname[i]);
1099 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1100 HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT));
1101 if (err < 0)
1102 return err;
1103 } else if (i == AUTO_SEQ_SURROUND) {
1104 sprintf(name, "%s Playback Volume", chname[i]);
1105 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1106 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1107 if (err < 0)
1108 return err;
1109 sprintf(name, "%s Playback Switch", chname[i]);
1110 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1111 HDA_COMPOSE_AMP_VAL(0x29, 3, 0, HDA_OUTPUT));
1112 if (err < 0)
1113 return err;
1114 } else if (i == AUTO_SEQ_SIDE) {
1115 sprintf(name, "%s Playback Volume", chname[i]);
1116 err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name,
1117 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1118 if (err < 0)
1119 return err;
1120 sprintf(name, "%s Playback Switch", chname[i]);
1121 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE, name,
1122 HDA_COMPOSE_AMP_VAL(0x1a, 3, 0, HDA_OUTPUT));
1123 if (err < 0)
1124 return err;
1125 }
1126 }
1127
1128 return 0;
1129}
1130
1131static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin)
1132{
1133 int err;
1134
1135 if (!pin)
1136 return 0;
1137
1138 if (spec->multiout.num_dacs == 5) /* 10 channels */
1139 spec->multiout.hp_nid = VT1709_HP_DAC_NID;
1140 else if (spec->multiout.num_dacs == 3) /* 6 channels */
1141 spec->multiout.hp_nid = 0;
1142
1143 err = via_add_control(spec, VIA_CTL_WIDGET_VOL,
1144 "Headphone Playback Volume",
1145 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1146 if (err < 0)
1147 return err;
1148 err = via_add_control(spec, VIA_CTL_WIDGET_MUTE,
1149 "Headphone Playback Switch",
1150 HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_OUTPUT));
1151 if (err < 0)
1152 return err;
1153
1154 return 0;
1155}
1156
1157/* create playback/capture controls for input pins */
1158static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec,
1159 const struct auto_pin_cfg *cfg)
1160{
1161 static char *labels[] = {
1162 "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL
1163 };
1164 struct hda_input_mux *imux = &spec->private_imux;
1165 int i, err, idx = 0;
1166
1167 /* for internal loopback recording select */
1168 imux->items[imux->num_items].label = "Stereo Mixer";
1169 imux->items[imux->num_items].index = idx;
1170 imux->num_items++;
1171
1172 for (i = 0; i < AUTO_PIN_LAST; i++) {
1173 if (!cfg->input_pins[i])
1174 continue;
1175
1176 switch (cfg->input_pins[i]) {
1177 case 0x1d: /* Mic */
1178 idx = 2;
1179 break;
1180
1181 case 0x1e: /* Line In */
1182 idx = 3;
1183 break;
1184
1185 case 0x21: /* Front Mic */
1186 idx = 4;
1187 break;
1188
1189 case 0x23: /* CD */
1190 idx = 1;
1191 break;
1192 }
1193 err = via_new_analog_input(spec, cfg->input_pins[i], labels[i],
1194 idx, 0x18);
1195 if (err < 0)
1196 return err;
1197 imux->items[imux->num_items].label = labels[i];
1198 imux->items[imux->num_items].index = idx;
1199 imux->num_items++;
1200 }
1201 return 0;
1202}
1203
1204static int vt1709_parse_auto_config(struct hda_codec *codec)
1205{
1206 struct via_spec *spec = codec->spec;
1207 int err;
1208
1209 err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL);
1210 if (err < 0)
1211 return err;
1212 err = vt1709_auto_fill_dac_nids(spec, &spec->autocfg);
1213 if (err < 0)
1214 return err;
1215 if (!spec->autocfg.line_outs && !spec->autocfg.hp_pins[0])
1216 return 0; /* can't find valid BIOS pin config */
1217
1218 err = vt1709_auto_create_multi_out_ctls(spec, &spec->autocfg);
1219 if (err < 0)
1220 return err;
1221 err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]);
1222 if (err < 0)
1223 return err;
1224 err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg);
1225 if (err < 0)
1226 return err;
1227
1228 spec->multiout.max_channels = spec->multiout.num_dacs * 2;
1229
1230 if (spec->autocfg.dig_out_pin)
1231 spec->multiout.dig_out_nid = VT1709_DIGOUT_NID;
1232 if (spec->autocfg.dig_in_pin)
1233 spec->dig_in_nid = VT1709_DIGIN_NID;
1234
1235 if (spec->kctl_alloc)
1236 spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
1237
1238 spec->input_mux = &spec->private_imux;
1239
1240 return 1;
1241}
1242
1243static int patch_vt1709_10ch(struct hda_codec *codec)
1244{
1245 struct via_spec *spec;
1246 int err;
1247
1248 /* create a codec specific record */
1249 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1250 if (spec == NULL)
1251 return -ENOMEM;
1252
1253 codec->spec = spec;
1254
1255 err = vt1709_parse_auto_config(codec);
1256 if (err < 0) {
1257 via_free(codec);
1258 return err;
1259 } else if (!err) {
1260 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1261 "Using genenic mode...\n");
1262 }
1263
1264 spec->init_verbs = vt1709_10ch_volume_init_verbs;
1265
1266 spec->stream_name_analog = "VT1709 Analog";
1267 spec->stream_analog_playback = &vt1709_10ch_pcm_analog_playback;
1268 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1269
1270 spec->stream_name_digital = "VT1709 Digital";
1271 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1272 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1273
1274
1275 if (!spec->adc_nids && spec->input_mux) {
1276 spec->adc_nids = vt1709_adc_nids;
1277 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1278 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1279 spec->num_mixers++;
1280 }
1281
1282 codec->patch_ops = via_patch_ops;
1283
1284 codec->patch_ops.init = via_auto_init;
1285
1286 return 0;
1287}
1288/*
1289 * generic initialization of ADC, input mixers and output mixers
1290 */
1291static struct hda_verb vt1709_6ch_volume_init_verbs[] = {
1292 /*
1293 * Unmute ADC0-2 and set the default input to mic-in
1294 */
1295 {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1296 {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1297 {0x16, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1298
1299
1300 /* Unmute input amps (CD, Line In, Mic 1 & Mic 2) of the analog-loopback
1301 * mixer widget
1302 */
1303 /* Amp Indices: AOW0=0, CD = 1, Mic1 = 2, Line = 3, Mic2 = 4 */
1304 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(0)},
1305 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(1)},
1306 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(2)},
1307 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(3)},
1308 {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_UNMUTE(4)},
1309
1310 /*
1311 * Set up output selector (0x1a, 0x1b, 0x29)
1312 */
1313 /* set vol=0 to output mixers */
1314 {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1315 {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1316 {0x29, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1317
1318 /*
1319 * Unmute PW3 and PW4
1320 */
1321 {0x1f, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1322 {0x20, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_ZERO},
1323
1324 /* Set input of PW4 as MW0 */
1325 {0x20, AC_VERB_SET_CONNECT_SEL, 0},
1326 /* Set mic as default input of sw0 */
1327 {0x19, AC_VERB_SET_CONNECT_SEL, 0x2},
1328 /* PW9 Output enable */
1329 {0x24, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x40},
1330 { }
1331};
1332
1333static int patch_vt1709_6ch(struct hda_codec *codec)
1334{
1335 struct via_spec *spec;
1336 int err;
1337
1338 /* create a codec specific record */
1339 spec = kcalloc(1, sizeof(*spec), GFP_KERNEL);
1340 if (spec == NULL)
1341 return -ENOMEM;
1342
1343 codec->spec = spec;
1344
1345 err = vt1709_parse_auto_config(codec);
1346 if (err < 0) {
1347 via_free(codec);
1348 return err;
1349 } else if (!err) {
1350 printk(KERN_INFO "hda_codec: Cannot set up configuration. "
1351 "Using genenic mode...\n");
1352 }
1353
1354 spec->init_verbs = vt1709_6ch_volume_init_verbs;
1355
1356 spec->stream_name_analog = "VT1709 Analog";
1357 spec->stream_analog_playback = &vt1709_6ch_pcm_analog_playback;
1358 spec->stream_analog_capture = &vt1709_pcm_analog_capture;
1359
1360 spec->stream_name_digital = "VT1709 Digital";
1361 spec->stream_digital_playback = &vt1709_pcm_digital_playback;
1362 spec->stream_digital_capture = &vt1709_pcm_digital_capture;
1363
1364
1365 if (!spec->adc_nids && spec->input_mux) {
1366 spec->adc_nids = vt1709_adc_nids;
1367 spec->num_adc_nids = ARRAY_SIZE(vt1709_adc_nids);
1368 spec->mixers[spec->num_mixers] = vt1709_capture_mixer;
1369 spec->num_mixers++;
1370 }
1371
1372 codec->patch_ops = via_patch_ops;
1373
1374 codec->patch_ops.init = via_auto_init;
1375
1376 return 0;
1377}
1378
1379/*
1380 * patch entries
1381 */
1382struct hda_codec_preset snd_hda_preset_via[] = {
1383 { .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
1384 { .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
1385 { .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
1386 { .id = 0x1106170B, .name = "VIA VT1708", .patch = patch_vt1708},
1387 { .id = 0x1106E710, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1388 { .id = 0x1106E711, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1389 { .id = 0x1106E712, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1390 { .id = 0x1106E713, .name = "VIA VT1709 10-Ch", .patch = patch_vt1709_10ch},
1391 { .id = 0x1106E714, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1392 { .id = 0x1106E715, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1393 { .id = 0x1106E716, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1394 { .id = 0x1106E717, .name = "VIA VT1709 6-Ch", .patch = patch_vt1709_6ch},
1395 {} /* terminator */
1396};
diff --git a/sound/pci/ice1712/Makefile b/sound/pci/ice1712/Makefile
index 7837cef8855c..6efdd62f6837 100644
--- a/sound/pci/ice1712/Makefile
+++ b/sound/pci/ice1712/Makefile
@@ -5,7 +5,7 @@
5 5
6snd-ice17xx-ak4xxx-objs := ak4xxx.o 6snd-ice17xx-ak4xxx-objs := ak4xxx.o
7snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o 7snd-ice1712-objs := ice1712.o delta.o hoontech.o ews.o
8snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o 8snd-ice1724-objs := ice1724.o amp.o revo.o aureon.o vt1720_mobo.o pontis.o prodigy192.o juli.o phase.o wtm.o
9 9
10# Toplevel Module Dependency 10# Toplevel Module Dependency
11obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o 11obj-$(CONFIG_SND_ICE1712) += snd-ice1712.o snd-ice17xx-ak4xxx.o
diff --git a/sound/pci/ice1712/amp.c b/sound/pci/ice1712/amp.c
index 59c4078ad331..6e22d326df32 100644
--- a/sound/pci/ice1712/amp.c
+++ b/sound/pci/ice1712/amp.c
@@ -42,7 +42,7 @@ static void wm_put(struct snd_ice1712 *ice, int reg, unsigned short val)
42 42
43static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice) 43static int __devinit snd_vt1724_amp_init(struct snd_ice1712 *ice)
44{ 44{
45 static unsigned short wm_inits[] = { 45 static const unsigned short wm_inits[] = {
46 WM_ATTEN_L, 0x0000, /* 0 db */ 46 WM_ATTEN_L, 0x0000, /* 0 db */
47 WM_ATTEN_R, 0x0000, /* 0 db */ 47 WM_ATTEN_R, 0x0000, /* 0 db */
48 WM_DAC_CTRL, 0x0008, /* 24bit I2S */ 48 WM_DAC_CTRL, 0x0008, /* 24bit I2S */
@@ -75,7 +75,7 @@ static int __devinit snd_vt1724_amp_add_controls(struct snd_ice1712 *ice)
75 75
76 76
77/* entry point */ 77/* entry point */
78struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = { 78const struct snd_ice1712_card_info snd_vt1724_amp_cards[] __devinitdata = {
79 { 79 {
80 .subvendor = VT1724_SUBDEVICE_AV710, 80 .subvendor = VT1724_SUBDEVICE_AV710,
81 .name = "Chaintech AV-710", 81 .name = "Chaintech AV-710",
diff --git a/sound/pci/ice1712/amp.h b/sound/pci/ice1712/amp.h
index a0fc89b48122..7b667bad0c6b 100644
--- a/sound/pci/ice1712/amp.h
+++ b/sound/pci/ice1712/amp.h
@@ -42,7 +42,7 @@
42#define WM_DAC_CTRL 0x02 42#define WM_DAC_CTRL 0x02
43#define WM_INT_CTRL 0x03 43#define WM_INT_CTRL 0x03
44 44
45extern struct snd_ice1712_card_info snd_vt1724_amp_cards[]; 45extern const struct snd_ice1712_card_info snd_vt1724_amp_cards[];
46 46
47 47
48#endif /* __SOUND_AMP_H */ 48#endif /* __SOUND_AMP_H */
diff --git a/sound/pci/ice1712/aureon.c b/sound/pci/ice1712/aureon.c
index 9e76cebd2d22..6941d85dfec9 100644
--- a/sound/pci/ice1712/aureon.c
+++ b/sound/pci/ice1712/aureon.c
@@ -294,7 +294,7 @@ static unsigned short aureon_ac97_read(struct snd_ice1712 *ice, unsigned short r
294static int aureon_ac97_init (struct snd_ice1712 *ice) 294static int aureon_ac97_init (struct snd_ice1712 *ice)
295{ 295{
296 int i; 296 int i;
297 static unsigned short ac97_defaults[] = { 297 static const unsigned short ac97_defaults[] = {
298 0x00, 0x9640, 298 0x00, 0x9640,
299 0x02, 0x8000, 299 0x02, 0x8000,
300 0x04, 0x8000, 300 0x04, 0x8000,
@@ -474,7 +474,8 @@ static void aureon_spi_write(struct snd_ice1712 *ice, unsigned int cs, unsigned
474 474
475 tmp = snd_ice1712_gpio_read(ice); 475 tmp = snd_ice1712_gpio_read(ice);
476 476
477 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT) { 477 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
478 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) {
478 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS)); 479 snd_ice1712_gpio_set_mask(ice, ~(PRODIGY_SPI_MOSI|PRODIGY_SPI_CLK|PRODIGY_WM_CS));
479 mosi = PRODIGY_SPI_MOSI; 480 mosi = PRODIGY_SPI_MOSI;
480 clk = PRODIGY_SPI_CLK; 481 clk = PRODIGY_SPI_CLK;
@@ -601,7 +602,9 @@ static unsigned short wm_get(struct snd_ice1712 *ice, int reg)
601static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val) 602static void wm_put_nocache(struct snd_ice1712 *ice, int reg, unsigned short val)
602{ 603{
603 aureon_spi_write(ice, 604 aureon_spi_write(ice,
604 (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ? PRODIGY_WM_CS : AUREON_WM_CS), 605 ((ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
606 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT) ?
607 PRODIGY_WM_CS : AUREON_WM_CS),
605 (reg << 9) | (val & 0x1ff), 16); 608 (reg << 9) | (val & 0x1ff), 16);
606} 609}
607 610
@@ -661,17 +664,17 @@ static int aureon_ac97_mmute_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
661 return change; 664 return change;
662} 665}
663 666
664static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); 667static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
665static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); 668static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
666static DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0); 669static const DECLARE_TLV_DB_SCALE(db_scale_wm_adc, -1200, 100, 0);
667static DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0); 670static const DECLARE_TLV_DB_SCALE(db_scale_ac97_master, -4650, 150, 0);
668static DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0); 671static const DECLARE_TLV_DB_SCALE(db_scale_ac97_gain, -3450, 150, 0);
669 672
670/* 673/*
671 * Logarithmic volume values for WM8770 674 * Logarithmic volume values for WM8770
672 * Computed as 20 * Log10(255 / x) 675 * Computed as 20 * Log10(255 / x)
673 */ 676 */
674static unsigned char wm_vol[256] = { 677static const unsigned char wm_vol[256] = {
675 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23, 678 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
676 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, 679 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
677 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 680 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
@@ -1064,14 +1067,14 @@ static int wm_adc_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
1064 */ 1067 */
1065static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1068static int wm_adc_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1066{ 1069{
1067 static char *texts[] = { 1070 static const char * const texts[] = {
1068 "CD", //AIN1 1071 "CD", //AIN1
1069 "Aux", //AIN2 1072 "Aux", //AIN2
1070 "Line", //AIN3 1073 "Line", //AIN3
1071 "Mic", //AIN4 1074 "Mic", //AIN4
1072 "AC97" //AIN5 1075 "AC97" //AIN5
1073 }; 1076 };
1074 static char *universe_texts[] = { 1077 static const char * const universe_texts[] = {
1075 "Aux1", //AIN1 1078 "Aux1", //AIN1
1076 "CD", //AIN2 1079 "CD", //AIN2
1077 "Phono", //AIN3 1080 "Phono", //AIN3
@@ -1137,11 +1140,11 @@ static int wm_adc_mux_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_val
1137static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 1140static int aureon_cs8415_mux_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
1138{ 1141{
1139 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 1142 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1140 static char *aureon_texts[] = { 1143 static const char * const aureon_texts[] = {
1141 "CD", //RXP0 1144 "CD", //RXP0
1142 "Optical" //RXP1 1145 "Optical" //RXP1
1143 }; 1146 };
1144 static char *prodigy_texts[] = { 1147 static const char * const prodigy_texts[] = {
1145 "CD", 1148 "CD",
1146 "Coax" 1149 "Coax"
1147 }; 1150 };
@@ -1288,12 +1291,14 @@ static int aureon_set_headphone_amp(struct snd_ice1712 *ice, int enable)
1288 1291
1289 tmp2 = tmp = snd_ice1712_gpio_read(ice); 1292 tmp2 = tmp = snd_ice1712_gpio_read(ice);
1290 if (enable) 1293 if (enable)
1291 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) 1294 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1295 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1292 tmp |= AUREON_HP_SEL; 1296 tmp |= AUREON_HP_SEL;
1293 else 1297 else
1294 tmp |= PRODIGY_HP_SEL; 1298 tmp |= PRODIGY_HP_SEL;
1295 else 1299 else
1296 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) 1300 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1301 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT)
1297 tmp &= ~ AUREON_HP_SEL; 1302 tmp &= ~ AUREON_HP_SEL;
1298 else 1303 else
1299 tmp &= ~ PRODIGY_HP_SEL; 1304 tmp &= ~ PRODIGY_HP_SEL;
@@ -1363,7 +1368,7 @@ static int aureon_deemp_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
1363 */ 1368 */
1364static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo) 1369static int aureon_oversampling_info(struct snd_kcontrol *k, struct snd_ctl_elem_info *uinfo)
1365{ 1370{
1366 static char *texts[2] = { "128x", "64x" }; 1371 static const char * const texts[2] = { "128x", "64x" };
1367 1372
1368 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1373 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1369 uinfo->count = 1; 1374 uinfo->count = 1;
@@ -1406,7 +1411,7 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl
1406 * mixers 1411 * mixers
1407 */ 1412 */
1408 1413
1409static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = { 1414static const struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1410 { 1415 {
1411 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1416 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1412 .name = "Master Playback Switch", 1417 .name = "Master Playback Switch",
@@ -1521,7 +1526,7 @@ static struct snd_kcontrol_new aureon_dac_controls[] __devinitdata = {
1521 } 1526 }
1522}; 1527};
1523 1528
1524static struct snd_kcontrol_new wm_controls[] __devinitdata = { 1529static const struct snd_kcontrol_new wm_controls[] __devinitdata = {
1525 { 1530 {
1526 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1531 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1527 .name = "PCM Playback Switch", 1532 .name = "PCM Playback Switch",
@@ -1587,7 +1592,7 @@ static struct snd_kcontrol_new wm_controls[] __devinitdata = {
1587 } 1592 }
1588}; 1593};
1589 1594
1590static struct snd_kcontrol_new ac97_controls[] __devinitdata = { 1595static const struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1591 { 1596 {
1592 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1597 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1593 .name = "AC97 Playback Switch", 1598 .name = "AC97 Playback Switch",
@@ -1692,7 +1697,7 @@ static struct snd_kcontrol_new ac97_controls[] __devinitdata = {
1692 } 1697 }
1693}; 1698};
1694 1699
1695static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = { 1700static const struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1696 { 1701 {
1697 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1702 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1698 .name = "AC97 Playback Switch", 1703 .name = "AC97 Playback Switch",
@@ -1824,8 +1829,7 @@ static struct snd_kcontrol_new universe_ac97_controls[] __devinitdata = {
1824 1829
1825}; 1830};
1826 1831
1827 1832static const struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1828static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1829 { 1833 {
1830 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1834 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1831 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH), 1835 .name = SNDRV_CTL_NAME_IEC958("",CAPTURE,SWITCH),
@@ -1870,7 +1874,6 @@ static struct snd_kcontrol_new cs8415_controls[] __devinitdata = {
1870 } 1874 }
1871}; 1875};
1872 1876
1873
1874static int __devinit aureon_add_controls(struct snd_ice1712 *ice) 1877static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1875{ 1878{
1876 unsigned int i, counts; 1879 unsigned int i, counts;
@@ -1898,7 +1901,8 @@ static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1898 return err; 1901 return err;
1899 } 1902 }
1900 } 1903 }
1901 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) { 1904 else if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1905 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1902 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) { 1906 for (i = 0; i < ARRAY_SIZE(ac97_controls); i++) {
1903 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice)); 1907 err = snd_ctl_add(ice->card, snd_ctl_new1(&ac97_controls[i], ice));
1904 if (err < 0) 1908 if (err < 0)
@@ -1906,7 +1910,8 @@ static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1906 } 1910 }
1907 } 1911 }
1908 1912
1909 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) { 1913 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
1914 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
1910 unsigned char id; 1915 unsigned char id;
1911 snd_ice1712_save_gpio_status(ice); 1916 snd_ice1712_save_gpio_status(ice);
1912 id = aureon_cs8415_get(ice, CS8415_ID); 1917 id = aureon_cs8415_get(ice, CS8415_ID);
@@ -1936,7 +1941,7 @@ static int __devinit aureon_add_controls(struct snd_ice1712 *ice)
1936 */ 1941 */
1937static int __devinit aureon_init(struct snd_ice1712 *ice) 1942static int __devinit aureon_init(struct snd_ice1712 *ice)
1938{ 1943{
1939 static unsigned short wm_inits_aureon[] = { 1944 static const unsigned short wm_inits_aureon[] = {
1940 /* These come first to reduce init pop noise */ 1945 /* These come first to reduce init pop noise */
1941 0x1b, 0x044, /* ADC Mux (AC'97 source) */ 1946 0x1b, 0x044, /* ADC Mux (AC'97 source) */
1942 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ 1947 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
@@ -1972,7 +1977,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
1972 0x1a, 0x000, /* -12dB ADC/R */ 1977 0x1a, 0x000, /* -12dB ADC/R */
1973 (unsigned short)-1 1978 (unsigned short)-1
1974 }; 1979 };
1975 static unsigned short wm_inits_prodigy[] = { 1980 static const unsigned short wm_inits_prodigy[] = {
1976 1981
1977 /* These come first to reduce init pop noise */ 1982 /* These come first to reduce init pop noise */
1978 0x1b, 0x000, /* ADC Mux */ 1983 0x1b, 0x000, /* ADC Mux */
@@ -2014,7 +2019,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
2014 (unsigned short)-1 2019 (unsigned short)-1
2015 2020
2016 }; 2021 };
2017 static unsigned short cs_inits[] = { 2022 static const unsigned short cs_inits[] = {
2018 0x0441, /* RUN */ 2023 0x0441, /* RUN */
2019 0x0180, /* no mute, OMCK output on RMCK pin */ 2024 0x0180, /* no mute, OMCK output on RMCK pin */
2020 0x0201, /* S/PDIF source on RXP1 */ 2025 0x0201, /* S/PDIF source on RXP1 */
@@ -2022,7 +2027,7 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
2022 (unsigned short)-1 2027 (unsigned short)-1
2023 }; 2028 };
2024 unsigned int tmp; 2029 unsigned int tmp;
2025 unsigned short *p; 2030 const unsigned short *p;
2026 int err, i; 2031 int err, i;
2027 2032
2028 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) { 2033 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_AUREON51_SKY) {
@@ -2062,7 +2067,8 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
2062 2067
2063 /* initialize WM8770 codec */ 2068 /* initialize WM8770 codec */
2064 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 || 2069 if (ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71 ||
2065 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT) 2070 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71LT ||
2071 ice->eeprom.subvendor == VT1724_SUBDEVICE_PRODIGY71XT)
2066 p = wm_inits_prodigy; 2072 p = wm_inits_prodigy;
2067 else 2073 else
2068 p = wm_inits_aureon; 2074 p = wm_inits_aureon;
@@ -2070,7 +2076,8 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
2070 wm_put(ice, p[0], p[1]); 2076 wm_put(ice, p[0], p[1]);
2071 2077
2072 /* initialize CS8415A codec */ 2078 /* initialize CS8415A codec */
2073 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT) { 2079 if (ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71LT &&
2080 ice->eeprom.subvendor != VT1724_SUBDEVICE_PRODIGY71XT) {
2074 for (p = cs_inits; *p != (unsigned short)-1; p++) 2081 for (p = cs_inits; *p != (unsigned short)-1; p++)
2075 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24); 2082 aureon_spi_write(ice, AUREON_CS8415_CS, *p | 0x200000, 24);
2076 ice->spec.aureon.cs8415_mux = 1; 2083 ice->spec.aureon.cs8415_mux = 1;
@@ -2100,73 +2107,58 @@ static int __devinit aureon_init(struct snd_ice1712 *ice)
2100 * hence the driver needs to sets up it properly. 2107 * hence the driver needs to sets up it properly.
2101 */ 2108 */
2102 2109
2103static unsigned char aureon51_eeprom[] __devinitdata = { 2110static const unsigned char aureon51_eeprom[] __devinitdata = {
2104 0x0a, /* SYSCONF: clock 512, spdif-in/ADC, 3DACs */ 2111 [ICE_EEP2_SYSCONF] = 0x0a, /* clock 512, spdif-in/ADC, 3DACs */
2105 0x80, /* ACLINK: I2S */ 2112 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2106 0xfc, /* I2S: vol, 96k, 24bit, 192k */ 2113 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2107 0xc3, /* SPDIF: out-en, out-int, spdif-in */ 2114 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2108 0xff, /* GPIO_DIR */ 2115 [ICE_EEP2_GPIO_DIR] = 0xff,
2109 0xff, /* GPIO_DIR1 */ 2116 [ICE_EEP2_GPIO_DIR1] = 0xff,
2110 0x5f, /* GPIO_DIR2 */ 2117 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2111 0x00, /* GPIO_MASK */ 2118 [ICE_EEP2_GPIO_MASK] = 0x00,
2112 0x00, /* GPIO_MASK1 */ 2119 [ICE_EEP2_GPIO_MASK1] = 0x00,
2113 0x00, /* GPIO_MASK2 */ 2120 [ICE_EEP2_GPIO_MASK2] = 0x00,
2114 0x00, /* GPIO_STATE */ 2121 [ICE_EEP2_GPIO_STATE] = 0x00,
2115 0x00, /* GPIO_STATE1 */ 2122 [ICE_EEP2_GPIO_STATE1] = 0x00,
2116 0x00, /* GPIO_STATE2 */ 2123 [ICE_EEP2_GPIO_STATE2] = 0x00,
2117}; 2124};
2118 2125
2119static unsigned char aureon71_eeprom[] __devinitdata = { 2126static const unsigned char aureon71_eeprom[] __devinitdata = {
2120 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */ 2127 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
2121 0x80, /* ACLINK: I2S */ 2128 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2122 0xfc, /* I2S: vol, 96k, 24bit, 192k */ 2129 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2123 0xc3, /* SPDIF: out-en, out-int, spdif-in */ 2130 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2124 0xff, /* GPIO_DIR */ 2131 [ICE_EEP2_GPIO_DIR] = 0xff,
2125 0xff, /* GPIO_DIR1 */ 2132 [ICE_EEP2_GPIO_DIR1] = 0xff,
2126 0x5f, /* GPIO_DIR2 */ 2133 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2127 0x00, /* GPIO_MASK */ 2134 [ICE_EEP2_GPIO_MASK] = 0x00,
2128 0x00, /* GPIO_MASK1 */ 2135 [ICE_EEP2_GPIO_MASK1] = 0x00,
2129 0x00, /* GPIO_MASK2 */ 2136 [ICE_EEP2_GPIO_MASK2] = 0x00,
2130 0x00, /* GPIO_STATE */ 2137 [ICE_EEP2_GPIO_STATE] = 0x00,
2131 0x00, /* GPIO_STATE1 */ 2138 [ICE_EEP2_GPIO_STATE1] = 0x00,
2132 0x00, /* GPIO_STATE2 */ 2139 [ICE_EEP2_GPIO_STATE2] = 0x00,
2133}; 2140};
2134 2141#define prodigy71_eeprom aureon71_eeprom
2135static unsigned char prodigy71_eeprom[] __devinitdata = { 2142
2136 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */ 2143static const unsigned char prodigy71lt_eeprom[] __devinitdata = {
2137 0x80, /* ACLINK: I2S */ 2144 [ICE_EEP2_SYSCONF] = 0x4b, /* clock 384, spdif-in/ADC, 4DACs */
2138 0xfc, /* I2S: vol, 96k, 24bit, 192k */ 2145 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
2139 0xc3, /* SPDIF: out-en, out-int, spdif-in */ 2146 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
2140 0xff, /* GPIO_DIR */ 2147 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
2141 0xff, /* GPIO_DIR1 */ 2148 [ICE_EEP2_GPIO_DIR] = 0xff,
2142 0x5f, /* GPIO_DIR2 */ 2149 [ICE_EEP2_GPIO_DIR1] = 0xff,
2143 0x00, /* GPIO_MASK */ 2150 [ICE_EEP2_GPIO_DIR2] = 0x5f,
2144 0x00, /* GPIO_MASK1 */ 2151 [ICE_EEP2_GPIO_MASK] = 0x00,
2145 0x00, /* GPIO_MASK2 */ 2152 [ICE_EEP2_GPIO_MASK1] = 0x00,
2146 0x00, /* GPIO_STATE */ 2153 [ICE_EEP2_GPIO_MASK2] = 0x00,
2147 0x00, /* GPIO_STATE1 */ 2154 [ICE_EEP2_GPIO_STATE] = 0x00,
2148 0x00, /* GPIO_STATE2 */ 2155 [ICE_EEP2_GPIO_STATE1] = 0x00,
2156 [ICE_EEP2_GPIO_STATE2] = 0x00,
2149}; 2157};
2150 2158#define prodigy71xt_eeprom prodigy71lt_eeprom
2151static unsigned char prodigy71lt_eeprom[] __devinitdata = {
2152 0x4b, /* SYSCINF: clock 512, spdif-in/ADC, 4DACs */
2153 0x80, /* ACLINK: I2S */
2154 0xfc, /* I2S: vol, 96k, 24bit, 192k */
2155 0xc3, /* SPDIF: out-en, out-int, spdif-in */
2156 0xff, /* GPIO_DIR */
2157 0xff, /* GPIO_DIR1 */
2158 0x5f, /* GPIO_DIR2 */
2159 0x00, /* GPIO_MASK */
2160 0x00, /* GPIO_MASK1 */
2161 0x00, /* GPIO_MASK2 */
2162 0x00, /* GPIO_STATE */
2163 0x00, /* GPIO_STATE1 */
2164 0x00, /* GPIO_STATE2 */
2165};
2166
2167 2159
2168/* entry point */ 2160/* entry point */
2169struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = { 2161const struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2170 { 2162 {
2171 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY, 2163 .subvendor = VT1724_SUBDEVICE_AUREON51_SKY,
2172 .name = "Terratec Aureon 5.1-Sky", 2164 .name = "Terratec Aureon 5.1-Sky",
@@ -2217,5 +2209,15 @@ struct snd_ice1712_card_info snd_vt1724_aureon_cards[] __devinitdata = {
2217 .eeprom_data = prodigy71lt_eeprom, 2209 .eeprom_data = prodigy71lt_eeprom,
2218 .driver = "Prodigy71LT", 2210 .driver = "Prodigy71LT",
2219 }, 2211 },
2212 {
2213 .subvendor = VT1724_SUBDEVICE_PRODIGY71XT,
2214 .name = "Audiotrak Prodigy 7.1 XT",
2215 .model = "prodigy71xt",
2216 .chip_init = aureon_init,
2217 .build_controls = aureon_add_controls,
2218 .eeprom_size = sizeof(prodigy71xt_eeprom),
2219 .eeprom_data = prodigy71xt_eeprom,
2220 .driver = "Prodigy71LT",
2221 },
2220 { } /* terminator */ 2222 { } /* terminator */
2221}; 2223};
diff --git a/sound/pci/ice1712/aureon.h b/sound/pci/ice1712/aureon.h
index 3b7bea656c57..79e58e88ed47 100644
--- a/sound/pci/ice1712/aureon.h
+++ b/sound/pci/ice1712/aureon.h
@@ -28,15 +28,17 @@
28 "{Terratec,Aureon 7.1 Space},"\ 28 "{Terratec,Aureon 7.1 Space},"\
29 "{Terratec,Aureon 7.1 Universe}," \ 29 "{Terratec,Aureon 7.1 Universe}," \
30 "{AudioTrak,Prodigy 7.1}," \ 30 "{AudioTrak,Prodigy 7.1}," \
31 "{AudioTrak,Prodigy 7.1 LT}," 31 "{AudioTrak,Prodigy 7.1 LT},"\
32 "{AudioTrak,Prodigy 7.1 XT},"
32 33
33#define VT1724_SUBDEVICE_AUREON51_SKY 0x3b154711 /* Aureon 5.1 Sky */ 34#define VT1724_SUBDEVICE_AUREON51_SKY 0x3b154711 /* Aureon 5.1 Sky */
34#define VT1724_SUBDEVICE_AUREON71_SPACE 0x3b154511 /* Aureon 7.1 Space */ 35#define VT1724_SUBDEVICE_AUREON71_SPACE 0x3b154511 /* Aureon 7.1 Space */
35#define VT1724_SUBDEVICE_AUREON71_UNIVERSE 0x3b155311 /* Aureon 7.1 Universe */ 36#define VT1724_SUBDEVICE_AUREON71_UNIVERSE 0x3b155311 /* Aureon 7.1 Universe */
36#define VT1724_SUBDEVICE_PRODIGY71 0x33495345 /* PRODIGY 7.1 */ 37#define VT1724_SUBDEVICE_PRODIGY71 0x33495345 /* PRODIGY 7.1 */
37#define VT1724_SUBDEVICE_PRODIGY71LT 0x32315441 /* PRODIGY 7.1 LT */ 38#define VT1724_SUBDEVICE_PRODIGY71LT 0x32315441 /* PRODIGY 7.1 LT */
39#define VT1724_SUBDEVICE_PRODIGY71XT 0x36315441 /* PRODIGY 7.1 XT*/
38 40
39extern struct snd_ice1712_card_info snd_vt1724_aureon_cards[]; 41extern const struct snd_ice1712_card_info snd_vt1724_aureon_cards[];
40 42
41/* GPIO bits */ 43/* GPIO bits */
42#define AUREON_CS8415_CS (1 << 22) 44#define AUREON_CS8415_CS (1 << 22)
diff --git a/sound/pci/ice1712/delta.c b/sound/pci/ice1712/delta.c
index af659800c9b0..3eeb36c6e985 100644
--- a/sound/pci/ice1712/delta.c
+++ b/sound/pci/ice1712/delta.c
@@ -416,7 +416,7 @@ static int snd_ice1712_delta1010lt_wordclock_status_get(struct snd_kcontrol *kco
416 return 0; 416 return 0;
417} 417}
418 418
419static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata = 419static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devinitdata =
420{ 420{
421 .access = (SNDRV_CTL_ELEM_ACCESS_READ), 421 .access = (SNDRV_CTL_ELEM_ACCESS_READ),
422 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 422 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -429,7 +429,7 @@ static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_status __devini
429 * initialize the chips on M-Audio cards 429 * initialize the chips on M-Audio cards
430 */ 430 */
431 431
432static struct snd_akm4xxx akm_audiophile __devinitdata = { 432static const struct snd_akm4xxx akm_audiophile __devinitdata = {
433 .type = SND_AK4528, 433 .type = SND_AK4528,
434 .num_adcs = 2, 434 .num_adcs = 2,
435 .num_dacs = 2, 435 .num_dacs = 2,
@@ -438,7 +438,7 @@ static struct snd_akm4xxx akm_audiophile __devinitdata = {
438 } 438 }
439}; 439};
440 440
441static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = { 441static const struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
442 .caddr = 2, 442 .caddr = 2,
443 .cif = 0, 443 .cif = 0,
444 .data_mask = ICE1712_DELTA_AP_DOUT, 444 .data_mask = ICE1712_DELTA_AP_DOUT,
@@ -450,7 +450,7 @@ static struct snd_ak4xxx_private akm_audiophile_priv __devinitdata = {
450 .mask_flags = 0, 450 .mask_flags = 0,
451}; 451};
452 452
453static struct snd_akm4xxx akm_delta410 __devinitdata = { 453static const struct snd_akm4xxx akm_delta410 __devinitdata = {
454 .type = SND_AK4529, 454 .type = SND_AK4529,
455 .num_adcs = 2, 455 .num_adcs = 2,
456 .num_dacs = 8, 456 .num_dacs = 8,
@@ -459,7 +459,7 @@ static struct snd_akm4xxx akm_delta410 __devinitdata = {
459 } 459 }
460}; 460};
461 461
462static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = { 462static const struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
463 .caddr = 0, 463 .caddr = 0,
464 .cif = 0, 464 .cif = 0,
465 .data_mask = ICE1712_DELTA_AP_DOUT, 465 .data_mask = ICE1712_DELTA_AP_DOUT,
@@ -471,7 +471,7 @@ static struct snd_ak4xxx_private akm_delta410_priv __devinitdata = {
471 .mask_flags = 0, 471 .mask_flags = 0,
472}; 472};
473 473
474static struct snd_akm4xxx akm_delta1010lt __devinitdata = { 474static const struct snd_akm4xxx akm_delta1010lt __devinitdata = {
475 .type = SND_AK4524, 475 .type = SND_AK4524,
476 .num_adcs = 8, 476 .num_adcs = 8,
477 .num_dacs = 8, 477 .num_dacs = 8,
@@ -481,7 +481,7 @@ static struct snd_akm4xxx akm_delta1010lt __devinitdata = {
481 } 481 }
482}; 482};
483 483
484static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = { 484static const struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
485 .caddr = 2, 485 .caddr = 2,
486 .cif = 0, /* the default level of the CIF pin from AK4524 */ 486 .cif = 0, /* the default level of the CIF pin from AK4524 */
487 .data_mask = ICE1712_DELTA_1010LT_DOUT, 487 .data_mask = ICE1712_DELTA_1010LT_DOUT,
@@ -493,7 +493,7 @@ static struct snd_ak4xxx_private akm_delta1010lt_priv __devinitdata = {
493 .mask_flags = 0, 493 .mask_flags = 0,
494}; 494};
495 495
496static struct snd_akm4xxx akm_delta44 __devinitdata = { 496static const struct snd_akm4xxx akm_delta44 __devinitdata = {
497 .type = SND_AK4524, 497 .type = SND_AK4524,
498 .num_adcs = 4, 498 .num_adcs = 4,
499 .num_dacs = 4, 499 .num_dacs = 4,
@@ -503,7 +503,7 @@ static struct snd_akm4xxx akm_delta44 __devinitdata = {
503 } 503 }
504}; 504};
505 505
506static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = { 506static const struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
507 .caddr = 2, 507 .caddr = 2,
508 .cif = 0, /* the default level of the CIF pin from AK4524 */ 508 .cif = 0, /* the default level of the CIF pin from AK4524 */
509 .data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA, 509 .data_mask = ICE1712_DELTA_CODEC_SERIAL_DATA,
@@ -515,7 +515,7 @@ static struct snd_ak4xxx_private akm_delta44_priv __devinitdata = {
515 .mask_flags = 0, 515 .mask_flags = 0,
516}; 516};
517 517
518static struct snd_akm4xxx akm_vx442 __devinitdata = { 518static const struct snd_akm4xxx akm_vx442 __devinitdata = {
519 .type = SND_AK4524, 519 .type = SND_AK4524,
520 .num_adcs = 4, 520 .num_adcs = 4,
521 .num_dacs = 4, 521 .num_dacs = 4,
@@ -525,7 +525,7 @@ static struct snd_akm4xxx akm_vx442 __devinitdata = {
525 } 525 }
526}; 526};
527 527
528static struct snd_ak4xxx_private akm_vx442_priv __devinitdata = { 528static const struct snd_ak4xxx_private akm_vx442_priv __devinitdata = {
529 .caddr = 2, 529 .caddr = 2,
530 .cif = 0, 530 .cif = 0,
531 .data_mask = ICE1712_VX442_DOUT, 531 .data_mask = ICE1712_VX442_DOUT,
@@ -650,15 +650,15 @@ static int __devinit snd_ice1712_delta_init(struct snd_ice1712 *ice)
650 * additional controls for M-Audio cards 650 * additional controls for M-Audio cards
651 */ 651 */
652 652
653static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata = 653static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_select __devinitdata =
654ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0); 654ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_WORD_CLOCK_SELECT, 1, 0);
655static struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata = 655static const struct snd_kcontrol_new snd_ice1712_delta1010lt_wordclock_select __devinitdata =
656ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0); 656ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Sync", 0, ICE1712_DELTA_1010LT_WORDCLOCK, 0, 0);
657static struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata = 657static const struct snd_kcontrol_new snd_ice1712_delta1010_wordclock_status __devinitdata =
658ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE); 658ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Word Clock Status", 0, ICE1712_DELTA_WORD_CLOCK_STATUS, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
659static struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata = 659static const struct snd_kcontrol_new snd_ice1712_deltadio2496_spdif_in_select __devinitdata =
660ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0); 660ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, ICE1712_DELTA_SPDIF_INPUT_SELECT, 0, 0);
661static struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata = 661static const struct snd_kcontrol_new snd_ice1712_delta_spdif_in_status __devinitdata =
662ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE); 662ICE1712_GPIO(SNDRV_CTL_ELEM_IFACE_MIXER, "Delta IEC958 Input Status", 0, ICE1712_DELTA_SPDIF_IN_STAT, 1, SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE);
663 663
664 664
@@ -735,7 +735,7 @@ static int __devinit snd_ice1712_delta_add_controls(struct snd_ice1712 *ice)
735 735
736 736
737/* entry point */ 737/* entry point */
738struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = { 738const struct snd_ice1712_card_info snd_ice1712_delta_cards[] __devinitdata = {
739 { 739 {
740 .subvendor = ICE1712_SUBDEVICE_DELTA1010, 740 .subvendor = ICE1712_SUBDEVICE_DELTA1010,
741 .name = "M Audio Delta 1010", 741 .name = "M Audio Delta 1010",
diff --git a/sound/pci/ice1712/delta.h b/sound/pci/ice1712/delta.h
index 746ebde94522..e65d669af639 100644
--- a/sound/pci/ice1712/delta.h
+++ b/sound/pci/ice1712/delta.h
@@ -46,7 +46,7 @@
46#define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100 46#define ICE1712_SUBDEVICE_MEDIASTATION 0x694c0100
47 47
48/* entry point */ 48/* entry point */
49extern struct snd_ice1712_card_info snd_ice1712_delta_cards[]; 49extern const struct snd_ice1712_card_info snd_ice1712_delta_cards[];
50 50
51 51
52/* 52/*
diff --git a/sound/pci/ice1712/ews.c b/sound/pci/ice1712/ews.c
index b135389fec6c..9b7ff302c072 100644
--- a/sound/pci/ice1712/ews.c
+++ b/sound/pci/ice1712/ews.c
@@ -332,7 +332,7 @@ static void ews88_setup_spdif(struct snd_ice1712 *ice, int rate)
332 332
333/* 333/*
334 */ 334 */
335static struct snd_akm4xxx akm_ews88mt __devinitdata = { 335static const struct snd_akm4xxx akm_ews88mt __devinitdata = {
336 .num_adcs = 8, 336 .num_adcs = 8,
337 .num_dacs = 8, 337 .num_dacs = 8,
338 .type = SND_AK4524, 338 .type = SND_AK4524,
@@ -342,7 +342,7 @@ static struct snd_akm4xxx akm_ews88mt __devinitdata = {
342 } 342 }
343}; 343};
344 344
345static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = { 345static const struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
346 .caddr = 2, 346 .caddr = 2,
347 .cif = 1, /* CIF high */ 347 .cif = 1, /* CIF high */
348 .data_mask = ICE1712_EWS88_SERIAL_DATA, 348 .data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -354,7 +354,7 @@ static struct snd_ak4xxx_private akm_ews88mt_priv __devinitdata = {
354 .mask_flags = 0, 354 .mask_flags = 0,
355}; 355};
356 356
357static struct snd_akm4xxx akm_ewx2496 __devinitdata = { 357static const struct snd_akm4xxx akm_ewx2496 __devinitdata = {
358 .num_adcs = 2, 358 .num_adcs = 2,
359 .num_dacs = 2, 359 .num_dacs = 2,
360 .type = SND_AK4524, 360 .type = SND_AK4524,
@@ -363,7 +363,7 @@ static struct snd_akm4xxx akm_ewx2496 __devinitdata = {
363 } 363 }
364}; 364};
365 365
366static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = { 366static const struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
367 .caddr = 2, 367 .caddr = 2,
368 .cif = 1, /* CIF high */ 368 .cif = 1, /* CIF high */
369 .data_mask = ICE1712_EWS88_SERIAL_DATA, 369 .data_mask = ICE1712_EWS88_SERIAL_DATA,
@@ -375,7 +375,7 @@ static struct snd_ak4xxx_private akm_ewx2496_priv __devinitdata = {
375 .mask_flags = 0, 375 .mask_flags = 0,
376}; 376};
377 377
378static struct snd_akm4xxx akm_6fire __devinitdata = { 378static const struct snd_akm4xxx akm_6fire __devinitdata = {
379 .num_adcs = 6, 379 .num_adcs = 6,
380 .num_dacs = 6, 380 .num_dacs = 6,
381 .type = SND_AK4524, 381 .type = SND_AK4524,
@@ -384,7 +384,7 @@ static struct snd_akm4xxx akm_6fire __devinitdata = {
384 } 384 }
385}; 385};
386 386
387static struct snd_ak4xxx_private akm_6fire_priv __devinitdata = { 387static const struct snd_ak4xxx_private akm_6fire_priv __devinitdata = {
388 .caddr = 2, 388 .caddr = 2,
389 .cif = 1, /* CIF high */ 389 .cif = 1, /* CIF high */
390 .data_mask = ICE1712_6FIRE_SERIAL_DATA, 390 .data_mask = ICE1712_6FIRE_SERIAL_DATA,
@@ -578,7 +578,7 @@ static int snd_ice1712_ewx_io_sense_put(struct snd_kcontrol *kcontrol, struct sn
578 return val != nval; 578 return val != nval;
579} 579}
580 580
581static struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = { 581static const struct snd_kcontrol_new snd_ice1712_ewx2496_controls[] __devinitdata = {
582 { 582 {
583 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 583 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
584 .name = "Input Sensitivity Switch", 584 .name = "Input Sensitivity Switch",
@@ -678,7 +678,7 @@ static int snd_ice1712_ews88mt_input_sense_put(struct snd_kcontrol *kcontrol, st
678 return ndata != data; 678 return ndata != data;
679} 679}
680 680
681static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = { 681static const struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
682 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 682 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
683 .name = "Input Sensitivity Switch", 683 .name = "Input Sensitivity Switch",
684 .info = snd_ice1712_ewx_io_sense_info, 684 .info = snd_ice1712_ewx_io_sense_info,
@@ -687,7 +687,7 @@ static struct snd_kcontrol_new snd_ice1712_ews88mt_input_sense __devinitdata = {
687 .count = 8, 687 .count = 8,
688}; 688};
689 689
690static struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = { 690static const struct snd_kcontrol_new snd_ice1712_ews88mt_output_sense __devinitdata = {
691 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 691 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
692 .name = "Output Sensitivity Switch", 692 .name = "Output Sensitivity Switch",
693 .info = snd_ice1712_ewx_io_sense_info, 693 .info = snd_ice1712_ewx_io_sense_info,
@@ -769,7 +769,7 @@ static int snd_ice1712_ews88d_control_put(struct snd_kcontrol *kcontrol, struct
769 .private_value = xshift | (xinvert << 8),\ 769 .private_value = xshift | (xinvert << 8),\
770} 770}
771 771
772static struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = { 772static const struct snd_kcontrol_new snd_ice1712_ews88d_controls[] __devinitdata = {
773 EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */ 773 EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "IEC958 Input Optical", 0, 1, 0), /* inverted */
774 EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0), 774 EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT Output Optical", 1, 0, 0),
775 EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0), 775 EWS88D_CONTROL(SNDRV_CTL_ELEM_IFACE_MIXER, "ADAT External Master Clock", 2, 0, 0),
@@ -909,7 +909,7 @@ static int snd_ice1712_6fire_select_input_put(struct snd_kcontrol *kcontrol, str
909 .private_value = xshift | (xinvert << 8),\ 909 .private_value = xshift | (xinvert << 8),\
910} 910}
911 911
912static struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = { 912static const struct snd_kcontrol_new snd_ice1712_6fire_controls[] __devinitdata = {
913 { 913 {
914 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 914 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
915 .name = "Analog Input Select", 915 .name = "Analog Input Select",
@@ -989,7 +989,7 @@ static int __devinit snd_ice1712_ews_add_controls(struct snd_ice1712 *ice)
989 989
990 990
991/* entry point */ 991/* entry point */
992struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = { 992const struct snd_ice1712_card_info snd_ice1712_ews_cards[] __devinitdata = {
993 { 993 {
994 .subvendor = ICE1712_SUBDEVICE_EWX2496, 994 .subvendor = ICE1712_SUBDEVICE_EWX2496,
995 .name = "TerraTec EWX24/96", 995 .name = "TerraTec EWX24/96",
diff --git a/sound/pci/ice1712/ews.h b/sound/pci/ice1712/ews.h
index a12a0b053558..df449b4741f6 100644
--- a/sound/pci/ice1712/ews.h
+++ b/sound/pci/ice1712/ews.h
@@ -40,7 +40,7 @@
40#define ICE1712_SUBDEVICE_PHASE88 0x3b155111 40#define ICE1712_SUBDEVICE_PHASE88 0x3b155111
41 41
42/* entry point */ 42/* entry point */
43extern struct snd_ice1712_card_info snd_ice1712_ews_cards[]; 43extern const struct snd_ice1712_card_info snd_ice1712_ews_cards[];
44 44
45 45
46/* TerraTec EWX 24/96 configuration definitions */ 46/* TerraTec EWX 24/96 configuration definitions */
diff --git a/sound/pci/ice1712/hoontech.c b/sound/pci/ice1712/hoontech.c
index 3f27d04e7d3c..df97313aaf83 100644
--- a/sound/pci/ice1712/hoontech.c
+++ b/sound/pci/ice1712/hoontech.c
@@ -239,7 +239,7 @@ static void stdsp24_ak4524_lock(struct snd_akm4xxx *ak, int chip)
239static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice) 239static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
240{ 240{
241 /* Hoontech STDSP24 with modified hardware */ 241 /* Hoontech STDSP24 with modified hardware */
242 static struct snd_akm4xxx akm_stdsp24_mv __devinitdata = { 242 static const struct snd_akm4xxx akm_stdsp24_mv __devinitdata = {
243 .num_adcs = 2, 243 .num_adcs = 2,
244 .num_dacs = 2, 244 .num_dacs = 2,
245 .type = SND_AK4524, 245 .type = SND_AK4524,
@@ -248,7 +248,7 @@ static int __devinit snd_ice1712_value_init(struct snd_ice1712 *ice)
248 } 248 }
249 }; 249 };
250 250
251 static struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = { 251 static const struct snd_ak4xxx_private akm_stdsp24_mv_priv __devinitdata = {
252 .caddr = 2, 252 .caddr = 2,
253 .cif = 1, /* CIF high */ 253 .cif = 1, /* CIF high */
254 .data_mask = ICE1712_STDSP24_SERIAL_DATA, 254 .data_mask = ICE1712_STDSP24_SERIAL_DATA,
@@ -298,7 +298,7 @@ static int __devinit snd_ice1712_ez8_init(struct snd_ice1712 *ice)
298 298
299 299
300/* entry point */ 300/* entry point */
301struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = { 301const struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
302 { 302 {
303 .subvendor = ICE1712_SUBDEVICE_STDSP24, 303 .subvendor = ICE1712_SUBDEVICE_STDSP24,
304 .name = "Hoontech SoundTrack Audio DSP24", 304 .name = "Hoontech SoundTrack Audio DSP24",
@@ -325,4 +325,3 @@ struct snd_ice1712_card_info snd_ice1712_hoontech_cards[] __devinitdata = {
325 }, 325 },
326 { } /* terminator */ 326 { } /* terminator */
327}; 327};
328
diff --git a/sound/pci/ice1712/hoontech.h b/sound/pci/ice1712/hoontech.h
index 1ee538b20fbf..b62d6e4f6c71 100644
--- a/sound/pci/ice1712/hoontech.h
+++ b/sound/pci/ice1712/hoontech.h
@@ -35,7 +35,7 @@
35#define ICE1712_SUBDEVICE_STDSP24_MEDIA7_1 0x16141217 /* Hoontech ST Audio DSP24 Media 7.1 */ 35#define ICE1712_SUBDEVICE_STDSP24_MEDIA7_1 0x16141217 /* Hoontech ST Audio DSP24 Media 7.1 */
36#define ICE1712_SUBDEVICE_EVENT_EZ8 0x00010001 /* A dummy id for EZ8 */ 36#define ICE1712_SUBDEVICE_EVENT_EZ8 0x00010001 /* A dummy id for EZ8 */
37 37
38extern struct snd_ice1712_card_info snd_ice1712_hoontech_cards[]; 38extern const struct snd_ice1712_card_info snd_ice1712_hoontech_cards[];
39 39
40 40
41/* Hoontech SoundTrack Audio DSP 24 GPIO definitions */ 41/* Hoontech SoundTrack Audio DSP 24 GPIO definitions */
diff --git a/sound/pci/ice1712/ice1712.c b/sound/pci/ice1712/ice1712.c
index 8ba31cfb9045..830a1bbd7110 100644
--- a/sound/pci/ice1712/ice1712.c
+++ b/sound/pci/ice1712/ice1712.c
@@ -107,7 +107,7 @@ module_param_array(dxr_enable, int, NULL, 0444);
107MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE."); 107MODULE_PARM_DESC(dxr_enable, "Enable DXR support for Terratec DMX6FIRE.");
108 108
109 109
110static struct pci_device_id snd_ice1712_ids[] = { 110static const struct pci_device_id snd_ice1712_ids[] = {
111 { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICE1712 */ 111 { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_ICE_1712, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* ICE1712 */
112 { 0, } 112 { 0, }
113}; 113};
@@ -287,7 +287,7 @@ static int snd_ice1712_digmix_route_ac97_put(struct snd_kcontrol *kcontrol, stru
287 return val != nval; 287 return val != nval;
288} 288}
289 289
290static struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = { 290static const struct snd_kcontrol_new snd_ice1712_mixer_digmix_route_ac97 __devinitdata = {
291 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 291 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
292 .name = "Digital Mixer To AC97", 292 .name = "Digital Mixer To AC97",
293 .info = snd_ice1712_digmix_route_ac97_info, 293 .info = snd_ice1712_digmix_route_ac97_info,
@@ -719,7 +719,7 @@ static snd_pcm_uframes_t snd_ice1712_capture_pointer(struct snd_pcm_substream *s
719 return bytes_to_frames(substream->runtime, ptr); 719 return bytes_to_frames(substream->runtime, ptr);
720} 720}
721 721
722static struct snd_pcm_hardware snd_ice1712_playback = 722static const struct snd_pcm_hardware snd_ice1712_playback =
723{ 723{
724 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 724 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
725 SNDRV_PCM_INFO_BLOCK_TRANSFER | 725 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -739,7 +739,7 @@ static struct snd_pcm_hardware snd_ice1712_playback =
739 .fifo_size = 0, 739 .fifo_size = 0,
740}; 740};
741 741
742static struct snd_pcm_hardware snd_ice1712_playback_ds = 742static const struct snd_pcm_hardware snd_ice1712_playback_ds =
743{ 743{
744 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 744 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
745 SNDRV_PCM_INFO_BLOCK_TRANSFER | 745 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -759,7 +759,7 @@ static struct snd_pcm_hardware snd_ice1712_playback_ds =
759 .fifo_size = 0, 759 .fifo_size = 0,
760}; 760};
761 761
762static struct snd_pcm_hardware snd_ice1712_capture = 762static const struct snd_pcm_hardware snd_ice1712_capture =
763{ 763{
764 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 764 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
765 SNDRV_PCM_INFO_BLOCK_TRANSFER | 765 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1133,7 +1133,7 @@ static snd_pcm_uframes_t snd_ice1712_capture_pro_pointer(struct snd_pcm_substrea
1133 return bytes_to_frames(substream->runtime, ptr); 1133 return bytes_to_frames(substream->runtime, ptr);
1134} 1134}
1135 1135
1136static struct snd_pcm_hardware snd_ice1712_playback_pro = 1136static const struct snd_pcm_hardware snd_ice1712_playback_pro =
1137{ 1137{
1138 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 1138 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1139 SNDRV_PCM_INFO_BLOCK_TRANSFER | 1139 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1153,7 +1153,7 @@ static struct snd_pcm_hardware snd_ice1712_playback_pro =
1153 .fifo_size = 0, 1153 .fifo_size = 0,
1154}; 1154};
1155 1155
1156static struct snd_pcm_hardware snd_ice1712_capture_pro = 1156static const struct snd_pcm_hardware snd_ice1712_capture_pro =
1157{ 1157{
1158 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 1158 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1159 SNDRV_PCM_INFO_BLOCK_TRANSFER | 1159 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -1378,9 +1378,9 @@ static int snd_ice1712_pro_mixer_volume_put(struct snd_kcontrol *kcontrol, struc
1378 return change; 1378 return change;
1379} 1379}
1380 1380
1381static DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0); 1381static const DECLARE_TLV_DB_SCALE(db_scale_playback, -14400, 150, 0);
1382 1382
1383static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = { 1383static const struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata = {
1384 { 1384 {
1385 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1385 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1386 .name = "Multi Playback Switch", 1386 .name = "Multi Playback Switch",
@@ -1404,7 +1404,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_playback_ctrls[] __devinitdata
1404 }, 1404 },
1405}; 1405};
1406 1406
1407static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = { 1407static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinitdata = {
1408 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1408 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1409 .name = "H/W Multi Capture Switch", 1409 .name = "H/W Multi Capture Switch",
1410 .info = snd_ice1712_pro_mixer_switch_info, 1410 .info = snd_ice1712_pro_mixer_switch_info,
@@ -1413,7 +1413,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_switch __devinit
1413 .private_value = 10, 1413 .private_value = 10,
1414}; 1414};
1415 1415
1416static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = { 1416static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitdata = {
1417 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1417 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1418 .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,SWITCH), 1418 .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,SWITCH),
1419 .info = snd_ice1712_pro_mixer_switch_info, 1419 .info = snd_ice1712_pro_mixer_switch_info,
@@ -1423,7 +1423,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_switch __devinitd
1423 .count = 2, 1423 .count = 2,
1424}; 1424};
1425 1425
1426static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = { 1426static const struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinitdata = {
1427 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1427 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1428 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1428 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1429 SNDRV_CTL_ELEM_ACCESS_TLV_READ), 1429 SNDRV_CTL_ELEM_ACCESS_TLV_READ),
@@ -1435,7 +1435,7 @@ static struct snd_kcontrol_new snd_ice1712_multi_capture_analog_volume __devinit
1435 .tlv = { .p = db_scale_playback } 1435 .tlv = { .p = db_scale_playback }
1436}; 1436};
1437 1437
1438static struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = { 1438static const struct snd_kcontrol_new snd_ice1712_multi_capture_spdif_volume __devinitdata = {
1439 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1439 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1440 .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,VOLUME), 1440 .name = SNDRV_CTL_NAME_IEC958("Multi ",CAPTURE,VOLUME),
1441 .info = snd_ice1712_pro_mixer_volume_info, 1441 .info = snd_ice1712_pro_mixer_volume_info,
@@ -1627,7 +1627,7 @@ static int snd_ice1712_eeprom_get(struct snd_kcontrol *kcontrol,
1627 return 0; 1627 return 0;
1628} 1628}
1629 1629
1630static struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = { 1630static const struct snd_kcontrol_new snd_ice1712_eeprom __devinitdata = {
1631 .iface = SNDRV_CTL_ELEM_IFACE_CARD, 1631 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
1632 .name = "ICE1712 EEPROM", 1632 .name = "ICE1712 EEPROM",
1633 .access = SNDRV_CTL_ELEM_ACCESS_READ, 1633 .access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1663,7 +1663,7 @@ static int snd_ice1712_spdif_default_put(struct snd_kcontrol *kcontrol,
1663 return 0; 1663 return 0;
1664} 1664}
1665 1665
1666static struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata = 1666static const struct snd_kcontrol_new snd_ice1712_spdif_default __devinitdata =
1667{ 1667{
1668 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1668 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1669 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 1669 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1714,7 +1714,7 @@ static int snd_ice1712_spdif_maskp_get(struct snd_kcontrol *kcontrol,
1714 return 0; 1714 return 0;
1715} 1715}
1716 1716
1717static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata = 1717static const struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
1718{ 1718{
1719 .access = SNDRV_CTL_ELEM_ACCESS_READ, 1719 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1720 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1720 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1723,7 +1723,7 @@ static struct snd_kcontrol_new snd_ice1712_spdif_maskc __devinitdata =
1723 .get = snd_ice1712_spdif_maskc_get, 1723 .get = snd_ice1712_spdif_maskc_get,
1724}; 1724};
1725 1725
1726static struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata = 1726static const struct snd_kcontrol_new snd_ice1712_spdif_maskp __devinitdata =
1727{ 1727{
1728 .access = SNDRV_CTL_ELEM_ACCESS_READ, 1728 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1729 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1729 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1750,7 +1750,7 @@ static int snd_ice1712_spdif_stream_put(struct snd_kcontrol *kcontrol,
1750 return 0; 1750 return 0;
1751} 1751}
1752 1752
1753static struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata = 1753static const struct snd_kcontrol_new snd_ice1712_spdif_stream __devinitdata =
1754{ 1754{
1755 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 1755 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
1756 SNDRV_CTL_ELEM_ACCESS_INACTIVE), 1756 SNDRV_CTL_ELEM_ACCESS_INACTIVE),
@@ -1811,7 +1811,7 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
1811static int snd_ice1712_pro_internal_clock_info(struct snd_kcontrol *kcontrol, 1811static int snd_ice1712_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
1812 struct snd_ctl_elem_info *uinfo) 1812 struct snd_ctl_elem_info *uinfo)
1813{ 1813{
1814 static char *texts[] = { 1814 static const char * const texts[] = {
1815 "8000", /* 0: 6 */ 1815 "8000", /* 0: 6 */
1816 "9600", /* 1: 3 */ 1816 "9600", /* 1: 3 */
1817 "11025", /* 2: 10 */ 1817 "11025", /* 2: 10 */
@@ -1840,7 +1840,7 @@ static int snd_ice1712_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
1840 struct snd_ctl_elem_value *ucontrol) 1840 struct snd_ctl_elem_value *ucontrol)
1841{ 1841{
1842 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 1842 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1843 static unsigned char xlate[16] = { 1843 static const unsigned char xlate[16] = {
1844 9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 255, 255, 255, 10 1844 9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 255, 255, 255, 10
1845 }; 1845 };
1846 unsigned char val; 1846 unsigned char val;
@@ -1864,7 +1864,7 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
1864 struct snd_ctl_elem_value *ucontrol) 1864 struct snd_ctl_elem_value *ucontrol)
1865{ 1865{
1866 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 1866 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1867 static unsigned int xrate[13] = { 1867 static const unsigned int xrate[13] = {
1868 8000, 9600, 11025, 12000, 16000, 22050, 24000, 1868 8000, 9600, 11025, 12000, 16000, 22050, 24000,
1869 32000, 44100, 48000, 64000, 88200, 96000 1869 32000, 44100, 48000, 64000, 88200, 96000
1870 }; 1870 };
@@ -1891,7 +1891,7 @@ static int snd_ice1712_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
1891 return change; 1891 return change;
1892} 1892}
1893 1893
1894static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = { 1894static const struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
1895 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1895 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1896 .name = "Multi Track Internal Clock", 1896 .name = "Multi Track Internal Clock",
1897 .info = snd_ice1712_pro_internal_clock_info, 1897 .info = snd_ice1712_pro_internal_clock_info,
@@ -1902,7 +1902,7 @@ static struct snd_kcontrol_new snd_ice1712_pro_internal_clock __devinitdata = {
1902static int snd_ice1712_pro_internal_clock_default_info(struct snd_kcontrol *kcontrol, 1902static int snd_ice1712_pro_internal_clock_default_info(struct snd_kcontrol *kcontrol,
1903 struct snd_ctl_elem_info *uinfo) 1903 struct snd_ctl_elem_info *uinfo)
1904{ 1904{
1905 static char *texts[] = { 1905 static const char * const texts[] = {
1906 "8000", /* 0: 6 */ 1906 "8000", /* 0: 6 */
1907 "9600", /* 1: 3 */ 1907 "9600", /* 1: 3 */
1908 "11025", /* 2: 10 */ 1908 "11025", /* 2: 10 */
@@ -1931,7 +1931,7 @@ static int snd_ice1712_pro_internal_clock_default_get(struct snd_kcontrol *kcont
1931 struct snd_ctl_elem_value *ucontrol) 1931 struct snd_ctl_elem_value *ucontrol)
1932{ 1932{
1933 int val; 1933 int val;
1934 static unsigned int xrate[13] = { 1934 static const unsigned int xrate[13] = {
1935 8000, 9600, 11025, 12000, 16000, 22050, 24000, 1935 8000, 9600, 11025, 12000, 16000, 22050, 24000,
1936 32000, 44100, 48000, 64000, 88200, 96000 1936 32000, 44100, 48000, 64000, 88200, 96000
1937 }; 1937 };
@@ -1948,7 +1948,7 @@ static int snd_ice1712_pro_internal_clock_default_get(struct snd_kcontrol *kcont
1948static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcontrol, 1948static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcontrol,
1949 struct snd_ctl_elem_value *ucontrol) 1949 struct snd_ctl_elem_value *ucontrol)
1950{ 1950{
1951 static unsigned int xrate[13] = { 1951 static const unsigned int xrate[13] = {
1952 8000, 9600, 11025, 12000, 16000, 22050, 24000, 1952 8000, 9600, 11025, 12000, 16000, 22050, 24000,
1953 32000, 44100, 48000, 64000, 88200, 96000 1953 32000, 44100, 48000, 64000, 88200, 96000
1954 }; 1954 };
@@ -1962,7 +1962,7 @@ static int snd_ice1712_pro_internal_clock_default_put(struct snd_kcontrol *kcont
1962 return change; 1962 return change;
1963} 1963}
1964 1964
1965static struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = { 1965static const struct snd_kcontrol_new snd_ice1712_pro_internal_clock_default __devinitdata = {
1966 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1966 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1967 .name = "Multi Track Internal Clock Default", 1967 .name = "Multi Track Internal Clock Default",
1968 .info = snd_ice1712_pro_internal_clock_default_info, 1968 .info = snd_ice1712_pro_internal_clock_default_info,
@@ -2001,7 +2001,7 @@ static int snd_ice1712_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
2001 return change; 2001 return change;
2002} 2002}
2003 2003
2004static struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = { 2004static const struct snd_kcontrol_new snd_ice1712_pro_rate_locking __devinitdata = {
2005 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2005 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2006 .name = "Multi Track Rate Locking", 2006 .name = "Multi Track Rate Locking",
2007 .info = snd_ice1712_pro_rate_locking_info, 2007 .info = snd_ice1712_pro_rate_locking_info,
@@ -2040,7 +2040,7 @@ static int snd_ice1712_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
2040 return change; 2040 return change;
2041} 2041}
2042 2042
2043static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = { 2043static const struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
2044 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2044 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2045 .name = "Multi Track Rate Reset", 2045 .name = "Multi Track Rate Reset",
2046 .info = snd_ice1712_pro_rate_reset_info, 2046 .info = snd_ice1712_pro_rate_reset_info,
@@ -2054,7 +2054,7 @@ static struct snd_kcontrol_new snd_ice1712_pro_rate_reset __devinitdata = {
2054static int snd_ice1712_pro_route_info(struct snd_kcontrol *kcontrol, 2054static int snd_ice1712_pro_route_info(struct snd_kcontrol *kcontrol,
2055 struct snd_ctl_elem_info *uinfo) 2055 struct snd_ctl_elem_info *uinfo)
2056{ 2056{
2057 static char *texts[] = { 2057 static const char * const texts[] = {
2058 "PCM Out", /* 0 */ 2058 "PCM Out", /* 0 */
2059 "H/W In 0", "H/W In 1", "H/W In 2", "H/W In 3", /* 1-4 */ 2059 "H/W In 0", "H/W In 1", "H/W In 2", "H/W In 3", /* 1-4 */
2060 "H/W In 4", "H/W In 5", "H/W In 6", "H/W In 7", /* 5-8 */ 2060 "H/W In 4", "H/W In 5", "H/W In 6", "H/W In 7", /* 5-8 */
@@ -2207,7 +2207,7 @@ static int snd_ice1712_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
2207 return change; 2207 return change;
2208} 2208}
2209 2209
2210static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = { 2210static const struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata = {
2211 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2211 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2212 .name = "H/W Playback Route", 2212 .name = "H/W Playback Route",
2213 .info = snd_ice1712_pro_route_info, 2213 .info = snd_ice1712_pro_route_info,
@@ -2215,7 +2215,7 @@ static struct snd_kcontrol_new snd_ice1712_mixer_pro_analog_route __devinitdata
2215 .put = snd_ice1712_pro_route_analog_put, 2215 .put = snd_ice1712_pro_route_analog_put,
2216}; 2216};
2217 2217
2218static struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = { 2218static const struct snd_kcontrol_new snd_ice1712_mixer_pro_spdif_route __devinitdata = {
2219 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2219 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2220 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", 2220 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
2221 .info = snd_ice1712_pro_route_info, 2221 .info = snd_ice1712_pro_route_info,
@@ -2257,7 +2257,7 @@ static int snd_ice1712_pro_volume_rate_put(struct snd_kcontrol *kcontrol,
2257 return change; 2257 return change;
2258} 2258}
2259 2259
2260static struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = { 2260static const struct snd_kcontrol_new snd_ice1712_mixer_pro_volume_rate __devinitdata = {
2261 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2261 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2262 .name = "Multi Track Volume Rate", 2262 .name = "Multi Track Volume Rate",
2263 .info = snd_ice1712_pro_volume_rate_info, 2263 .info = snd_ice1712_pro_volume_rate_info,
@@ -2290,7 +2290,7 @@ static int snd_ice1712_pro_peak_get(struct snd_kcontrol *kcontrol,
2290 return 0; 2290 return 0;
2291} 2291}
2292 2292
2293static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = { 2293static const struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
2294 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 2294 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
2295 .name = "Multi Track Peak", 2295 .name = "Multi Track Peak",
2296 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 2296 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -2305,7 +2305,7 @@ static struct snd_kcontrol_new snd_ice1712_mixer_pro_peak __devinitdata = {
2305/* 2305/*
2306 * list of available boards 2306 * list of available boards
2307 */ 2307 */
2308static struct snd_ice1712_card_info *card_tables[] __devinitdata = { 2308static const struct snd_ice1712_card_info *card_tables[] __devinitdata = {
2309 snd_ice1712_hoontech_cards, 2309 snd_ice1712_hoontech_cards,
2310 snd_ice1712_delta_cards, 2310 snd_ice1712_delta_cards,
2311 snd_ice1712_ews_cards, 2311 snd_ice1712_ews_cards,
@@ -2329,7 +2329,7 @@ static int __devinit snd_ice1712_read_eeprom(struct snd_ice1712 *ice,
2329{ 2329{
2330 int dev = 0xa0; /* EEPROM device address */ 2330 int dev = 0xa0; /* EEPROM device address */
2331 unsigned int i, size; 2331 unsigned int i, size;
2332 struct snd_ice1712_card_info **tbl, *c; 2332 const struct snd_ice1712_card_info **tbl, *c;
2333 2333
2334 if (! modelname || ! *modelname) { 2334 if (! modelname || ! *modelname) {
2335 ice->eeprom.subvendor = 0; 2335 ice->eeprom.subvendor = 0;
@@ -2658,7 +2658,7 @@ static int __devinit snd_ice1712_create(struct snd_card *card,
2658 * 2658 *
2659 */ 2659 */
2660 2660
2661static struct snd_ice1712_card_info no_matched __devinitdata; 2661static const struct snd_ice1712_card_info no_matched __devinitdata;
2662 2662
2663static int __devinit snd_ice1712_probe(struct pci_dev *pci, 2663static int __devinit snd_ice1712_probe(struct pci_dev *pci,
2664 const struct pci_device_id *pci_id) 2664 const struct pci_device_id *pci_id)
@@ -2667,7 +2667,7 @@ static int __devinit snd_ice1712_probe(struct pci_dev *pci,
2667 struct snd_card *card; 2667 struct snd_card *card;
2668 struct snd_ice1712 *ice; 2668 struct snd_ice1712 *ice;
2669 int pcm_dev = 0, err; 2669 int pcm_dev = 0, err;
2670 struct snd_ice1712_card_info **tbl, *c; 2670 const struct snd_ice1712_card_info **tbl, *c;
2671 2671
2672 if (dev >= SNDRV_CARDS) 2672 if (dev >= SNDRV_CARDS)
2673 return -ENODEV; 2673 return -ENODEV;
diff --git a/sound/pci/ice1712/ice1712.h b/sound/pci/ice1712/ice1712.h
index ce27eac40d4e..c3d9feaaf57d 100644
--- a/sound/pci/ice1712/ice1712.h
+++ b/sound/pci/ice1712/ice1712.h
@@ -28,6 +28,7 @@
28#include <sound/i2c.h> 28#include <sound/i2c.h>
29#include <sound/ak4xxx-adda.h> 29#include <sound/ak4xxx-adda.h>
30#include <sound/ak4114.h> 30#include <sound/ak4114.h>
31#include <sound/pt2258.h>
31#include <sound/pcm.h> 32#include <sound/pcm.h>
32#include <sound/mpu401.h> 33#include <sound/mpu401.h>
33 34
@@ -381,6 +382,11 @@ struct snd_ice1712 {
381 unsigned short master[2]; 382 unsigned short master[2];
382 unsigned short vol[8]; 383 unsigned short vol[8];
383 } phase28; 384 } phase28;
385 /* a non-standard I2C device for revo51 */
386 struct revo51_spec {
387 struct snd_i2c_device *dev;
388 struct snd_pt2258 *pt2258;
389 } revo51;
384 /* Hoontech-specific setting */ 390 /* Hoontech-specific setting */
385 struct hoontech_spec { 391 struct hoontech_spec {
386 unsigned char boxbits[4]; 392 unsigned char boxbits[4];
@@ -462,6 +468,14 @@ static inline void snd_ice1712_gpio_write_bits(struct snd_ice1712 *ice,
462 snd_ice1712_gpio_write(ice, mask & bits); 468 snd_ice1712_gpio_write(ice, mask & bits);
463} 469}
464 470
471static inline int snd_ice1712_gpio_read_bits(struct snd_ice1712 *ice,
472 unsigned int mask)
473{
474 ice->gpio.direction &= ~mask;
475 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
476 return (snd_ice1712_gpio_read(ice) & mask);
477}
478
465int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice); 479int snd_ice1712_spdif_build_controls(struct snd_ice1712 *ice);
466 480
467int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *template, 481int snd_ice1712_akm4xxx_init(struct snd_akm4xxx *ak, const struct snd_akm4xxx *template,
@@ -500,8 +514,8 @@ struct snd_ice1712_card_info {
500 unsigned int mpu401_2_info_flags; 514 unsigned int mpu401_2_info_flags;
501 const char *mpu401_1_name; 515 const char *mpu401_1_name;
502 const char *mpu401_2_name; 516 const char *mpu401_2_name;
503 unsigned int eeprom_size; 517 const unsigned int eeprom_size;
504 unsigned char *eeprom_data; 518 const unsigned char *eeprom_data;
505}; 519};
506 520
507 521
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 3e3a102e6c34..1127ebdf5fec 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -50,7 +50,7 @@
50#include "prodigy192.h" 50#include "prodigy192.h"
51#include "juli.h" 51#include "juli.h"
52#include "phase.h" 52#include "phase.h"
53 53#include "wtm.h"
54 54
55MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>"); 55MODULE_AUTHOR("Jaroslav Kysela <perex@suse.cz>");
56MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)"); 56MODULE_DESCRIPTION("VIA ICEnsemble ICE1724/1720 (Envy24HT/PT)");
@@ -64,6 +64,7 @@ MODULE_SUPPORTED_DEVICE("{"
64 PRODIGY192_DEVICE_DESC 64 PRODIGY192_DEVICE_DESC
65 JULI_DEVICE_DESC 65 JULI_DEVICE_DESC
66 PHASE_DEVICE_DESC 66 PHASE_DEVICE_DESC
67 WTM_DEVICE_DESC
67 "{VIA,VT1720}," 68 "{VIA,VT1720},"
68 "{VIA,VT1724}," 69 "{VIA,VT1724},"
69 "{ICEnsemble,Generic ICE1724}," 70 "{ICEnsemble,Generic ICE1724},"
@@ -86,7 +87,7 @@ MODULE_PARM_DESC(model, "Use the given board model.");
86 87
87 88
88/* Both VT1720 and VT1724 have the same PCI IDs */ 89/* Both VT1720 and VT1724 have the same PCI IDs */
89static struct pci_device_id snd_vt1724_ids[] = { 90static const struct pci_device_id snd_vt1724_ids[] = {
90 { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_VT1724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, 91 { PCI_VENDOR_ID_ICE, PCI_DEVICE_ID_VT1724, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
91 { 0, } 92 { 0, }
92}; 93};
@@ -341,7 +342,7 @@ static int snd_vt1724_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
341 342
342 what = 0; 343 what = 0;
343 snd_pcm_group_for_each(pos, substream) { 344 snd_pcm_group_for_each(pos, substream) {
344 struct vt1724_pcm_reg *reg; 345 const struct vt1724_pcm_reg *reg;
345 s = snd_pcm_group_substream_entry(pos); 346 s = snd_pcm_group_substream_entry(pos);
346 reg = s->runtime->private_data; 347 reg = s->runtime->private_data;
347 what |= reg->start; 348 what |= reg->start;
@@ -605,7 +606,7 @@ static snd_pcm_uframes_t snd_vt1724_playback_pro_pointer(struct snd_pcm_substrea
605static int snd_vt1724_pcm_prepare(struct snd_pcm_substream *substream) 606static int snd_vt1724_pcm_prepare(struct snd_pcm_substream *substream)
606{ 607{
607 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); 608 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
608 struct vt1724_pcm_reg *reg = substream->runtime->private_data; 609 const struct vt1724_pcm_reg *reg = substream->runtime->private_data;
609 610
610 spin_lock_irq(&ice->reg_lock); 611 spin_lock_irq(&ice->reg_lock);
611 outl(substream->runtime->dma_addr, ice->profi_port + reg->addr); 612 outl(substream->runtime->dma_addr, ice->profi_port + reg->addr);
@@ -620,7 +621,7 @@ static int snd_vt1724_pcm_prepare(struct snd_pcm_substream *substream)
620static snd_pcm_uframes_t snd_vt1724_pcm_pointer(struct snd_pcm_substream *substream) 621static snd_pcm_uframes_t snd_vt1724_pcm_pointer(struct snd_pcm_substream *substream)
621{ 622{
622 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); 623 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
623 struct vt1724_pcm_reg *reg = substream->runtime->private_data; 624 const struct vt1724_pcm_reg *reg = substream->runtime->private_data;
624 size_t ptr; 625 size_t ptr;
625 626
626 if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & reg->start)) 627 if (!(inl(ICEMT1724(ice, DMA_CONTROL)) & reg->start))
@@ -646,21 +647,21 @@ static snd_pcm_uframes_t snd_vt1724_pcm_pointer(struct snd_pcm_substream *substr
646#endif 647#endif
647} 648}
648 649
649static struct vt1724_pcm_reg vt1724_playback_pro_reg = { 650static const struct vt1724_pcm_reg vt1724_playback_pro_reg = {
650 .addr = VT1724_MT_PLAYBACK_ADDR, 651 .addr = VT1724_MT_PLAYBACK_ADDR,
651 .size = VT1724_MT_PLAYBACK_SIZE, 652 .size = VT1724_MT_PLAYBACK_SIZE,
652 .count = VT1724_MT_PLAYBACK_COUNT, 653 .count = VT1724_MT_PLAYBACK_COUNT,
653 .start = VT1724_PDMA0_START, 654 .start = VT1724_PDMA0_START,
654}; 655};
655 656
656static struct vt1724_pcm_reg vt1724_capture_pro_reg = { 657static const struct vt1724_pcm_reg vt1724_capture_pro_reg = {
657 .addr = VT1724_MT_CAPTURE_ADDR, 658 .addr = VT1724_MT_CAPTURE_ADDR,
658 .size = VT1724_MT_CAPTURE_SIZE, 659 .size = VT1724_MT_CAPTURE_SIZE,
659 .count = VT1724_MT_CAPTURE_COUNT, 660 .count = VT1724_MT_CAPTURE_COUNT,
660 .start = VT1724_RDMA0_START, 661 .start = VT1724_RDMA0_START,
661}; 662};
662 663
663static struct snd_pcm_hardware snd_vt1724_playback_pro = 664static const struct snd_pcm_hardware snd_vt1724_playback_pro =
664{ 665{
665 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 666 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
666 SNDRV_PCM_INFO_BLOCK_TRANSFER | 667 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -679,7 +680,7 @@ static struct snd_pcm_hardware snd_vt1724_playback_pro =
679 .periods_max = 1024, 680 .periods_max = 1024,
680}; 681};
681 682
682static struct snd_pcm_hardware snd_vt1724_spdif = 683static const struct snd_pcm_hardware snd_vt1724_spdif =
683{ 684{
684 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 685 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
685 SNDRV_PCM_INFO_BLOCK_TRANSFER | 686 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -701,7 +702,7 @@ static struct snd_pcm_hardware snd_vt1724_spdif =
701 .periods_max = 1024, 702 .periods_max = 1024,
702}; 703};
703 704
704static struct snd_pcm_hardware snd_vt1724_2ch_stereo = 705static const struct snd_pcm_hardware snd_vt1724_2ch_stereo =
705{ 706{
706 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | 707 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
707 SNDRV_PCM_INFO_BLOCK_TRANSFER | 708 SNDRV_PCM_INFO_BLOCK_TRANSFER |
@@ -773,7 +774,7 @@ static int snd_vt1724_playback_pro_open(struct snd_pcm_substream *substream)
773 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); 774 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
774 int chs; 775 int chs;
775 776
776 runtime->private_data = &vt1724_playback_pro_reg; 777 runtime->private_data = (void *)&vt1724_playback_pro_reg;
777 ice->playback_pro_substream = substream; 778 ice->playback_pro_substream = substream;
778 runtime->hw = snd_vt1724_playback_pro; 779 runtime->hw = snd_vt1724_playback_pro;
779 snd_pcm_set_sync(substream); 780 snd_pcm_set_sync(substream);
@@ -802,7 +803,7 @@ static int snd_vt1724_capture_pro_open(struct snd_pcm_substream *substream)
802 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); 803 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
803 struct snd_pcm_runtime *runtime = substream->runtime; 804 struct snd_pcm_runtime *runtime = substream->runtime;
804 805
805 runtime->private_data = &vt1724_capture_pro_reg; 806 runtime->private_data = (void *)&vt1724_capture_pro_reg;
806 ice->capture_pro_substream = substream; 807 ice->capture_pro_substream = substream;
807 runtime->hw = snd_vt1724_2ch_stereo; 808 runtime->hw = snd_vt1724_2ch_stereo;
808 snd_pcm_set_sync(substream); 809 snd_pcm_set_sync(substream);
@@ -888,14 +889,14 @@ static int __devinit snd_vt1724_pcm_profi(struct snd_ice1712 * ice, int device)
888 * SPDIF PCM 889 * SPDIF PCM
889 */ 890 */
890 891
891static struct vt1724_pcm_reg vt1724_playback_spdif_reg = { 892static const struct vt1724_pcm_reg vt1724_playback_spdif_reg = {
892 .addr = VT1724_MT_PDMA4_ADDR, 893 .addr = VT1724_MT_PDMA4_ADDR,
893 .size = VT1724_MT_PDMA4_SIZE, 894 .size = VT1724_MT_PDMA4_SIZE,
894 .count = VT1724_MT_PDMA4_COUNT, 895 .count = VT1724_MT_PDMA4_COUNT,
895 .start = VT1724_PDMA4_START, 896 .start = VT1724_PDMA4_START,
896}; 897};
897 898
898static struct vt1724_pcm_reg vt1724_capture_spdif_reg = { 899static const struct vt1724_pcm_reg vt1724_capture_spdif_reg = {
899 .addr = VT1724_MT_RDMA1_ADDR, 900 .addr = VT1724_MT_RDMA1_ADDR,
900 .size = VT1724_MT_RDMA1_SIZE, 901 .size = VT1724_MT_RDMA1_SIZE,
901 .count = VT1724_MT_RDMA1_COUNT, 902 .count = VT1724_MT_RDMA1_COUNT,
@@ -953,7 +954,7 @@ static int snd_vt1724_playback_spdif_open(struct snd_pcm_substream *substream)
953 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); 954 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
954 struct snd_pcm_runtime *runtime = substream->runtime; 955 struct snd_pcm_runtime *runtime = substream->runtime;
955 956
956 runtime->private_data = &vt1724_playback_spdif_reg; 957 runtime->private_data = (void *)&vt1724_playback_spdif_reg;
957 ice->playback_con_substream = substream; 958 ice->playback_con_substream = substream;
958 if (ice->force_pdma4) { 959 if (ice->force_pdma4) {
959 runtime->hw = snd_vt1724_2ch_stereo; 960 runtime->hw = snd_vt1724_2ch_stereo;
@@ -985,7 +986,7 @@ static int snd_vt1724_capture_spdif_open(struct snd_pcm_substream *substream)
985 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream); 986 struct snd_ice1712 *ice = snd_pcm_substream_chip(substream);
986 struct snd_pcm_runtime *runtime = substream->runtime; 987 struct snd_pcm_runtime *runtime = substream->runtime;
987 988
988 runtime->private_data = &vt1724_capture_spdif_reg; 989 runtime->private_data = (void *)&vt1724_capture_spdif_reg;
989 ice->capture_con_substream = substream; 990 ice->capture_con_substream = substream;
990 if (ice->force_rdma1) { 991 if (ice->force_rdma1) {
991 runtime->hw = snd_vt1724_2ch_stereo; 992 runtime->hw = snd_vt1724_2ch_stereo;
@@ -1090,7 +1091,7 @@ static int __devinit snd_vt1724_pcm_spdif(struct snd_ice1712 * ice, int device)
1090 * independent surround PCMs 1091 * independent surround PCMs
1091 */ 1092 */
1092 1093
1093static struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = { 1094static const struct vt1724_pcm_reg vt1724_playback_dma_regs[3] = {
1094 { 1095 {
1095 .addr = VT1724_MT_PDMA1_ADDR, 1096 .addr = VT1724_MT_PDMA1_ADDR,
1096 .size = VT1724_MT_PDMA1_SIZE, 1097 .size = VT1724_MT_PDMA1_SIZE,
@@ -1136,7 +1137,7 @@ static int snd_vt1724_playback_indep_open(struct snd_pcm_substream *substream)
1136 return -EBUSY; /* FIXME: should handle blocking mode properly */ 1137 return -EBUSY; /* FIXME: should handle blocking mode properly */
1137 } 1138 }
1138 mutex_unlock(&ice->open_mutex); 1139 mutex_unlock(&ice->open_mutex);
1139 runtime->private_data = &vt1724_playback_dma_regs[substream->number]; 1140 runtime->private_data = (void *)&vt1724_playback_dma_regs[substream->number];
1140 ice->playback_con_substream_ds[substream->number] = substream; 1141 ice->playback_con_substream_ds[substream->number] = substream;
1141 runtime->hw = snd_vt1724_2ch_stereo; 1142 runtime->hw = snd_vt1724_2ch_stereo;
1142 snd_pcm_set_sync(substream); 1143 snd_pcm_set_sync(substream);
@@ -1317,7 +1318,7 @@ static int snd_vt1724_eeprom_get(struct snd_kcontrol *kcontrol,
1317 return 0; 1318 return 0;
1318} 1319}
1319 1320
1320static struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = { 1321static const struct snd_kcontrol_new snd_vt1724_eeprom __devinitdata = {
1321 .iface = SNDRV_CTL_ELEM_IFACE_CARD, 1322 .iface = SNDRV_CTL_ELEM_IFACE_CARD,
1322 .name = "ICE1724 EEPROM", 1323 .name = "ICE1724 EEPROM",
1323 .access = SNDRV_CTL_ELEM_ACCESS_READ, 1324 .access = SNDRV_CTL_ELEM_ACCESS_READ,
@@ -1430,7 +1431,7 @@ static int snd_vt1724_spdif_default_put(struct snd_kcontrol *kcontrol,
1430 return (val != old); 1431 return (val != old);
1431} 1432}
1432 1433
1433static struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata = 1434static const struct snd_kcontrol_new snd_vt1724_spdif_default __devinitdata =
1434{ 1435{
1435 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1436 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
1436 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT), 1437 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,DEFAULT),
@@ -1462,7 +1463,7 @@ static int snd_vt1724_spdif_maskp_get(struct snd_kcontrol *kcontrol,
1462 return 0; 1463 return 0;
1463} 1464}
1464 1465
1465static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata = 1466static const struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
1466{ 1467{
1467 .access = SNDRV_CTL_ELEM_ACCESS_READ, 1468 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1468 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1469 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1471,7 +1472,7 @@ static struct snd_kcontrol_new snd_vt1724_spdif_maskc __devinitdata =
1471 .get = snd_vt1724_spdif_maskc_get, 1472 .get = snd_vt1724_spdif_maskc_get,
1472}; 1473};
1473 1474
1474static struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata = 1475static const struct snd_kcontrol_new snd_vt1724_spdif_maskp __devinitdata =
1475{ 1476{
1476 .access = SNDRV_CTL_ELEM_ACCESS_READ, 1477 .access = SNDRV_CTL_ELEM_ACCESS_READ,
1477 .iface = SNDRV_CTL_ELEM_IFACE_PCM, 1478 .iface = SNDRV_CTL_ELEM_IFACE_PCM,
@@ -1516,7 +1517,7 @@ static int snd_vt1724_spdif_sw_put(struct snd_kcontrol *kcontrol,
1516 return old != val; 1517 return old != val;
1517} 1518}
1518 1519
1519static struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata = 1520static const struct snd_kcontrol_new snd_vt1724_spdif_switch __devinitdata =
1520{ 1521{
1521 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1522 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1522 /* FIXME: the following conflict with IEC958 Playback Route */ 1523 /* FIXME: the following conflict with IEC958 Playback Route */
@@ -1584,7 +1585,7 @@ int snd_ice1712_gpio_put(struct snd_kcontrol *kcontrol,
1584static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol, 1585static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
1585 struct snd_ctl_elem_info *uinfo) 1586 struct snd_ctl_elem_info *uinfo)
1586{ 1587{
1587 static char *texts_1724[] = { 1588 static const char * const texts_1724[] = {
1588 "8000", /* 0: 6 */ 1589 "8000", /* 0: 6 */
1589 "9600", /* 1: 3 */ 1590 "9600", /* 1: 3 */
1590 "11025", /* 2: 10 */ 1591 "11025", /* 2: 10 */
@@ -1602,7 +1603,7 @@ static int snd_vt1724_pro_internal_clock_info(struct snd_kcontrol *kcontrol,
1602 "192000", /* 14: 14 */ 1603 "192000", /* 14: 14 */
1603 "IEC958 Input", /* 15: -- */ 1604 "IEC958 Input", /* 15: -- */
1604 }; 1605 };
1605 static char *texts_1720[] = { 1606 static const char * const texts_1720[] = {
1606 "8000", /* 0: 6 */ 1607 "8000", /* 0: 6 */
1607 "9600", /* 1: 3 */ 1608 "9600", /* 1: 3 */
1608 "11025", /* 2: 10 */ 1609 "11025", /* 2: 10 */
@@ -1635,7 +1636,7 @@ static int snd_vt1724_pro_internal_clock_get(struct snd_kcontrol *kcontrol,
1635 struct snd_ctl_elem_value *ucontrol) 1636 struct snd_ctl_elem_value *ucontrol)
1636{ 1637{
1637 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol); 1638 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
1638 static unsigned char xlate[16] = { 1639 static const unsigned char xlate[16] = {
1639 9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10 1640 9, 6, 3, 1, 7, 4, 0, 12, 8, 5, 2, 11, 13, 255, 14, 10
1640 }; 1641 };
1641 unsigned char val; 1642 unsigned char val;
@@ -1694,7 +1695,7 @@ static int snd_vt1724_pro_internal_clock_put(struct snd_kcontrol *kcontrol,
1694 return change; 1695 return change;
1695} 1696}
1696 1697
1697static struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = { 1698static const struct snd_kcontrol_new snd_vt1724_pro_internal_clock __devinitdata = {
1698 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1699 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1699 .name = "Multi Track Internal Clock", 1700 .name = "Multi Track Internal Clock",
1700 .info = snd_vt1724_pro_internal_clock_info, 1701 .info = snd_vt1724_pro_internal_clock_info,
@@ -1733,7 +1734,7 @@ static int snd_vt1724_pro_rate_locking_put(struct snd_kcontrol *kcontrol,
1733 return change; 1734 return change;
1734} 1735}
1735 1736
1736static struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = { 1737static const struct snd_kcontrol_new snd_vt1724_pro_rate_locking __devinitdata = {
1737 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1738 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1738 .name = "Multi Track Rate Locking", 1739 .name = "Multi Track Rate Locking",
1739 .info = snd_vt1724_pro_rate_locking_info, 1740 .info = snd_vt1724_pro_rate_locking_info,
@@ -1772,7 +1773,7 @@ static int snd_vt1724_pro_rate_reset_put(struct snd_kcontrol *kcontrol,
1772 return change; 1773 return change;
1773} 1774}
1774 1775
1775static struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = { 1776static const struct snd_kcontrol_new snd_vt1724_pro_rate_reset __devinitdata = {
1776 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1777 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1777 .name = "Multi Track Rate Reset", 1778 .name = "Multi Track Rate Reset",
1778 .info = snd_vt1724_pro_rate_reset_info, 1779 .info = snd_vt1724_pro_rate_reset_info,
@@ -1816,7 +1817,7 @@ static int get_route_val(struct snd_ice1712 *ice, int shift)
1816{ 1817{
1817 unsigned long val; 1818 unsigned long val;
1818 unsigned char eitem; 1819 unsigned char eitem;
1819 static unsigned char xlate[8] = { 1820 static const unsigned char xlate[8] = {
1820 0, 255, 1, 2, 255, 255, 3, 4, 1821 0, 255, 1, 2, 255, 255, 3, 4,
1821 }; 1822 };
1822 1823
@@ -1835,7 +1836,7 @@ static int put_route_val(struct snd_ice1712 *ice, unsigned int val, int shift)
1835{ 1836{
1836 unsigned int old_val, nval; 1837 unsigned int old_val, nval;
1837 int change; 1838 int change;
1838 static unsigned char xroute[8] = { 1839 static const unsigned char xroute[8] = {
1839 0, /* PCM */ 1840 0, /* PCM */
1840 2, /* PSDIN0 Left */ 1841 2, /* PSDIN0 Left */
1841 3, /* PSDIN0 Right */ 1842 3, /* PSDIN0 Right */
@@ -1891,7 +1892,7 @@ static int snd_vt1724_pro_route_spdif_put(struct snd_kcontrol *kcontrol,
1891 digital_route_shift(idx)); 1892 digital_route_shift(idx));
1892} 1893}
1893 1894
1894static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = { 1895static const struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata = {
1895 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1896 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1896 .name = "H/W Playback Route", 1897 .name = "H/W Playback Route",
1897 .info = snd_vt1724_pro_route_info, 1898 .info = snd_vt1724_pro_route_info,
@@ -1899,7 +1900,7 @@ static struct snd_kcontrol_new snd_vt1724_mixer_pro_analog_route __devinitdata =
1899 .put = snd_vt1724_pro_route_analog_put, 1900 .put = snd_vt1724_pro_route_analog_put,
1900}; 1901};
1901 1902
1902static struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = { 1903static const struct snd_kcontrol_new snd_vt1724_mixer_pro_spdif_route __devinitdata = {
1903 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1904 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1904 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route", 1905 .name = SNDRV_CTL_NAME_IEC958("",PLAYBACK,NONE) "Route",
1905 .info = snd_vt1724_pro_route_info, 1906 .info = snd_vt1724_pro_route_info,
@@ -1935,7 +1936,7 @@ static int snd_vt1724_pro_peak_get(struct snd_kcontrol *kcontrol,
1935 return 0; 1936 return 0;
1936} 1937}
1937 1938
1938static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = { 1939static const struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
1939 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 1940 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1940 .name = "Multi Track Peak", 1941 .name = "Multi Track Peak",
1941 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, 1942 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE,
@@ -1947,9 +1948,9 @@ static struct snd_kcontrol_new snd_vt1724_mixer_pro_peak __devinitdata = {
1947 * 1948 *
1948 */ 1949 */
1949 1950
1950static struct snd_ice1712_card_info no_matched __devinitdata; 1951static const struct snd_ice1712_card_info no_matched __devinitdata;
1951 1952
1952static struct snd_ice1712_card_info *card_tables[] __devinitdata = { 1953static const struct snd_ice1712_card_info *card_tables[] __devinitdata = {
1953 snd_vt1724_revo_cards, 1954 snd_vt1724_revo_cards,
1954 snd_vt1724_amp_cards, 1955 snd_vt1724_amp_cards,
1955 snd_vt1724_aureon_cards, 1956 snd_vt1724_aureon_cards,
@@ -1958,6 +1959,7 @@ static struct snd_ice1712_card_info *card_tables[] __devinitdata = {
1958 snd_vt1724_prodigy192_cards, 1959 snd_vt1724_prodigy192_cards,
1959 snd_vt1724_juli_cards, 1960 snd_vt1724_juli_cards,
1960 snd_vt1724_phase_cards, 1961 snd_vt1724_phase_cards,
1962 snd_vt1724_wtm_cards,
1961 NULL, 1963 NULL,
1962}; 1964};
1963 1965
@@ -2007,7 +2009,7 @@ static int __devinit snd_vt1724_read_eeprom(struct snd_ice1712 *ice,
2007{ 2009{
2008 const int dev = 0xa0; /* EEPROM device address */ 2010 const int dev = 0xa0; /* EEPROM device address */
2009 unsigned int i, size; 2011 unsigned int i, size;
2010 struct snd_ice1712_card_info **tbl, *c; 2012 const struct snd_ice1712_card_info **tbl, *c;
2011 2013
2012 if (! modelname || ! *modelname) { 2014 if (! modelname || ! *modelname) {
2013 ice->eeprom.subvendor = 0; 2015 ice->eeprom.subvendor = 0;
@@ -2306,7 +2308,7 @@ static int __devinit snd_vt1724_probe(struct pci_dev *pci,
2306 struct snd_card *card; 2308 struct snd_card *card;
2307 struct snd_ice1712 *ice; 2309 struct snd_ice1712 *ice;
2308 int pcm_dev = 0, err; 2310 int pcm_dev = 0, err;
2309 struct snd_ice1712_card_info **tbl, *c; 2311 const struct snd_ice1712_card_info **tbl, *c;
2310 2312
2311 if (dev >= SNDRV_CARDS) 2313 if (dev >= SNDRV_CARDS)
2312 return -ENODEV; 2314 return -ENODEV;
diff --git a/sound/pci/ice1712/juli.c b/sound/pci/ice1712/juli.c
index 5176b41ea9d3..d88172fa95da 100644
--- a/sound/pci/ice1712/juli.c
+++ b/sound/pci/ice1712/juli.c
@@ -125,7 +125,7 @@ static void juli_akm_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
125 snd_akm4xxx_reset(ak, 0); 125 snd_akm4xxx_reset(ak, 0);
126} 126}
127 127
128static struct snd_akm4xxx akm_juli_dac __devinitdata = { 128static const struct snd_akm4xxx akm_juli_dac __devinitdata = {
129 .type = SND_AK4358, 129 .type = SND_AK4358,
130 .num_dacs = 2, 130 .num_dacs = 2,
131 .ops = { 131 .ops = {
@@ -146,7 +146,7 @@ static int __devinit juli_add_controls(struct snd_ice1712 *ice)
146 */ 146 */
147static int __devinit juli_init(struct snd_ice1712 *ice) 147static int __devinit juli_init(struct snd_ice1712 *ice)
148{ 148{
149 static unsigned char ak4114_init_vals[] = { 149 static const unsigned char ak4114_init_vals[] = {
150 /* AK4117_REG_PWRDN */ AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1, 150 /* AK4117_REG_PWRDN */ AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
151 /* AK4114_REQ_FORMAT */ AK4114_DIF_I24I2S, 151 /* AK4114_REQ_FORMAT */ AK4114_DIF_I24I2S,
152 /* AK4114_REG_IO0 */ AK4114_TX1E, 152 /* AK4114_REG_IO0 */ AK4114_TX1E,
@@ -154,7 +154,7 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
154 /* AK4114_REG_INT0_MASK */ 0, 154 /* AK4114_REG_INT0_MASK */ 0,
155 /* AK4114_REG_INT1_MASK */ 0 155 /* AK4114_REG_INT1_MASK */ 0
156 }; 156 };
157 static unsigned char ak4114_init_txcsb[] = { 157 static const unsigned char ak4114_init_txcsb[] = {
158 0x41, 0x02, 0x2c, 0x00, 0x00 158 0x41, 0x02, 0x2c, 0x00, 0x00
159 }; 159 };
160 int err; 160 int err;
@@ -206,24 +206,24 @@ static int __devinit juli_init(struct snd_ice1712 *ice)
206 * hence the driver needs to sets up it properly. 206 * hence the driver needs to sets up it properly.
207 */ 207 */
208 208
209static unsigned char juli_eeprom[] __devinitdata = { 209static const unsigned char juli_eeprom[] __devinitdata = {
210 0x20, /* SYSCONF: clock 512, mpu401, 1xADC, 1xDACs */ 210 [ICE_EEP2_SYSCONF] = 0x20, /* clock 512, mpu401, 1xADC, 1xDACs */
211 0x80, /* ACLINK: I2S */ 211 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
212 0xf8, /* I2S: vol, 96k, 24bit, 192k */ 212 [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */
213 0xc3, /* SPDIF: out-en, out-int, spdif-in */ 213 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
214 0x9f, /* GPIO_DIR */ 214 [ICE_EEP2_GPIO_DIR] = 0x9f,
215 0xff, /* GPIO_DIR1 */ 215 [ICE_EEP2_GPIO_DIR1] = 0xff,
216 0x7f, /* GPIO_DIR2 */ 216 [ICE_EEP2_GPIO_DIR2] = 0x7f,
217 0x9f, /* GPIO_MASK */ 217 [ICE_EEP2_GPIO_MASK] = 0x9f,
218 0xff, /* GPIO_MASK1 */ 218 [ICE_EEP2_GPIO_MASK1] = 0xff,
219 0x7f, /* GPIO_MASK2 */ 219 [ICE_EEP2_GPIO_MASK2] = 0x7f,
220 0x16, /* GPIO_STATE: internal clock, multiple 1x, 48kHz */ 220 [ICE_EEP2_GPIO_STATE] = 0x16, /* internal clock, multiple 1x, 48kHz */
221 0x80, /* GPIO_STATE1: mute */ 221 [ICE_EEP2_GPIO_STATE1] = 0x80, /* mute */
222 0x00, /* GPIO_STATE2 */ 222 [ICE_EEP2_GPIO_STATE2] = 0x00,
223}; 223};
224 224
225/* entry point */ 225/* entry point */
226struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = { 226const struct snd_ice1712_card_info snd_vt1724_juli_cards[] __devinitdata = {
227 { 227 {
228 .subvendor = VT1724_SUBDEVICE_JULI, 228 .subvendor = VT1724_SUBDEVICE_JULI,
229 .name = "ESI Juli@", 229 .name = "ESI Juli@",
diff --git a/sound/pci/ice1712/juli.h b/sound/pci/ice1712/juli.h
index d9f8534fd92e..1b9294f8bce3 100644
--- a/sound/pci/ice1712/juli.h
+++ b/sound/pci/ice1712/juli.h
@@ -5,6 +5,6 @@
5 5
6#define VT1724_SUBDEVICE_JULI 0x31305345 /* Juli@ */ 6#define VT1724_SUBDEVICE_JULI 0x31305345 /* Juli@ */
7 7
8extern struct snd_ice1712_card_info snd_vt1724_juli_cards[]; 8extern const struct snd_ice1712_card_info snd_vt1724_juli_cards[];
9 9
10#endif /* __SOUND_JULI_H */ 10#endif /* __SOUND_JULI_H */
diff --git a/sound/pci/ice1712/phase.c b/sound/pci/ice1712/phase.c
index e08d73f4ff85..0751718f4d7b 100644
--- a/sound/pci/ice1712/phase.c
+++ b/sound/pci/ice1712/phase.c
@@ -71,7 +71,7 @@
71 * Logarithmic volume values for WM8770 71 * Logarithmic volume values for WM8770
72 * Computed as 20 * Log10(255 / x) 72 * Computed as 20 * Log10(255 / x)
73 */ 73 */
74static unsigned char wm_vol[256] = { 74static const unsigned char wm_vol[256] = {
75 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23, 75 127, 48, 42, 39, 36, 34, 33, 31, 30, 29, 28, 27, 27, 26, 25, 25, 24, 24, 23,
76 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17, 76 23, 22, 22, 21, 21, 21, 20, 20, 20, 19, 19, 19, 18, 18, 18, 18, 17, 17, 17,
77 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13, 77 17, 16, 16, 16, 16, 15, 15, 15, 15, 15, 15, 14, 14, 14, 14, 14, 13, 13, 13,
@@ -89,13 +89,13 @@ static unsigned char wm_vol[256] = {
89#define WM_VOL_MAX (sizeof(wm_vol) - 1) 89#define WM_VOL_MAX (sizeof(wm_vol) - 1)
90#define WM_VOL_MUTE 0x8000 90#define WM_VOL_MUTE 0x8000
91 91
92static struct snd_akm4xxx akm_phase22 __devinitdata = { 92static const struct snd_akm4xxx akm_phase22 __devinitdata = {
93 .type = SND_AK4524, 93 .type = SND_AK4524,
94 .num_dacs = 2, 94 .num_dacs = 2,
95 .num_adcs = 2, 95 .num_adcs = 2,
96}; 96};
97 97
98static struct snd_ak4xxx_private akm_phase22_priv __devinitdata = { 98static const struct snd_ak4xxx_private akm_phase22_priv __devinitdata = {
99 .caddr = 2, 99 .caddr = 2,
100 .cif = 1, 100 .cif = 1,
101 .data_mask = 1 << 4, 101 .data_mask = 1 << 4,
@@ -152,36 +152,36 @@ static int __devinit phase22_add_controls(struct snd_ice1712 *ice)
152 return 0; 152 return 0;
153} 153}
154 154
155static unsigned char phase22_eeprom[] __devinitdata = { 155static const unsigned char phase22_eeprom[] __devinitdata = {
156 0x00, /* SYSCONF: 1xADC, 1xDACs */ 156 [ICE_EEP2_SYSCONF] = 0x00, /* 1xADC, 1xDACs */
157 0x80, /* ACLINK: I2S */ 157 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
158 0xf8, /* I2S: vol, 96k, 24bit*/ 158 [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit */
159 0xc3, /* SPDIF: out-en, out-int, spdif-in */ 159 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
160 0xFF, /* GPIO_DIR */ 160 [ICE_EEP2_GPIO_DIR] = 0xff,
161 0xFF, /* GPIO_DIR1 */ 161 [ICE_EEP2_GPIO_DIR1] = 0xff,
162 0xFF, /* GPIO_DIR2 */ 162 [ICE_EEP2_GPIO_DIR2] = 0xff,
163 0x00, /* GPIO_MASK */ 163 [ICE_EEP2_GPIO_MASK] = 0x00,
164 0x00, /* GPIO_MASK1 */ 164 [ICE_EEP2_GPIO_MASK1] = 0x00,
165 0x00, /* GPIO_MASK2 */ 165 [ICE_EEP2_GPIO_MASK2] = 0x00,
166 0x00, /* GPIO_STATE: */ 166 [ICE_EEP2_GPIO_STATE] = 0x00,
167 0x00, /* GPIO_STATE1: */ 167 [ICE_EEP2_GPIO_STATE1] = 0x00,
168 0x00, /* GPIO_STATE2 */ 168 [ICE_EEP2_GPIO_STATE2] = 0x00,
169}; 169};
170 170
171static unsigned char phase28_eeprom[] __devinitdata = { 171static const unsigned char phase28_eeprom[] __devinitdata = {
172 0x0b, /* SYSCONF: clock 512, spdif-in/ADC, 4DACs */ 172 [ICE_EEP2_SYSCONF] = 0x0b, /* clock 512, spdif-in/ADC, 4DACs */
173 0x80, /* ACLINK: I2S */ 173 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
174 0xfc, /* I2S: vol, 96k, 24bit, 192k */ 174 [ICE_EEP2_I2S] = 0xfc, /* vol, 96k, 24bit, 192k */
175 0xc3, /* SPDIF: out-en, out-int, spdif-in */ 175 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
176 0xff, /* GPIO_DIR */ 176 [ICE_EEP2_GPIO_DIR] = 0xff,
177 0xff, /* GPIO_DIR1 */ 177 [ICE_EEP2_GPIO_DIR1] = 0xff,
178 0x5f, /* GPIO_DIR2 */ 178 [ICE_EEP2_GPIO_DIR2] = 0x5f,
179 0x00, /* GPIO_MASK */ 179 [ICE_EEP2_GPIO_MASK] = 0x00,
180 0x00, /* GPIO_MASK1 */ 180 [ICE_EEP2_GPIO_MASK1] = 0x00,
181 0x00, /* GPIO_MASK2 */ 181 [ICE_EEP2_GPIO_MASK2] = 0x00,
182 0x00, /* GPIO_STATE */ 182 [ICE_EEP2_GPIO_STATE] = 0x00,
183 0x00, /* GPIO_STATE1 */ 183 [ICE_EEP2_GPIO_STATE1] = 0x00,
184 0x00, /* GPIO_STATE2 */ 184 [ICE_EEP2_GPIO_STATE2] = 0x00,
185}; 185};
186 186
187/* 187/*
@@ -343,7 +343,7 @@ static int wm_master_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_
343 343
344static int __devinit phase28_init(struct snd_ice1712 *ice) 344static int __devinit phase28_init(struct snd_ice1712 *ice)
345{ 345{
346 static unsigned short wm_inits_phase28[] = { 346 static const unsigned short wm_inits_phase28[] = {
347 /* These come first to reduce init pop noise */ 347 /* These come first to reduce init pop noise */
348 0x1b, 0x044, /* ADC Mux (AC'97 source) */ 348 0x1b, 0x044, /* ADC Mux (AC'97 source) */
349 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */ 349 0x1c, 0x00B, /* Out Mux1 (VOUT1 = DAC+AUX, VOUT2 = DAC) */
@@ -382,7 +382,7 @@ static int __devinit phase28_init(struct snd_ice1712 *ice)
382 382
383 unsigned int tmp; 383 unsigned int tmp;
384 struct snd_akm4xxx *ak; 384 struct snd_akm4xxx *ak;
385 unsigned short *p; 385 const unsigned short *p;
386 int i; 386 int i;
387 387
388 ice->num_total_dacs = 8; 388 ice->num_total_dacs = 8;
@@ -697,10 +697,10 @@ static int phase28_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ct
697 return 0; 697 return 0;
698} 698}
699 699
700static DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1); 700static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
701static DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1); 701static const DECLARE_TLV_DB_SCALE(db_scale_wm_pcm, -6400, 50, 1);
702 702
703static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = { 703static const struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
704 { 704 {
705 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 705 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
706 .name = "Master Playback Switch", 706 .name = "Master Playback Switch",
@@ -815,7 +815,7 @@ static struct snd_kcontrol_new phase28_dac_controls[] __devinitdata = {
815 } 815 }
816}; 816};
817 817
818static struct snd_kcontrol_new wm_controls[] __devinitdata = { 818static const struct snd_kcontrol_new wm_controls[] __devinitdata = {
819 { 819 {
820 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 820 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
821 .name = "PCM Playback Switch", 821 .name = "PCM Playback Switch",
@@ -870,7 +870,7 @@ static int __devinit phase28_add_controls(struct snd_ice1712 *ice)
870 return 0; 870 return 0;
871} 871}
872 872
873struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = { 873const struct snd_ice1712_card_info snd_vt1724_phase_cards[] __devinitdata = {
874 { 874 {
875 .subvendor = VT1724_SUBDEVICE_PHASE22, 875 .subvendor = VT1724_SUBDEVICE_PHASE22,
876 .name = "Terratec PHASE 22", 876 .name = "Terratec PHASE 22",
diff --git a/sound/pci/ice1712/phase.h b/sound/pci/ice1712/phase.h
index 13e841b55488..ad379a99bf92 100644
--- a/sound/pci/ice1712/phase.h
+++ b/sound/pci/ice1712/phase.h
@@ -31,7 +31,7 @@
31#define VT1724_SUBDEVICE_PHASE28 0x3b154911 31#define VT1724_SUBDEVICE_PHASE28 0x3b154911
32 32
33/* entry point */ 33/* entry point */
34extern struct snd_ice1712_card_info snd_vt1724_phase_cards[]; 34extern const struct snd_ice1712_card_info snd_vt1724_phase_cards[];
35 35
36/* PHASE28 GPIO bits */ 36/* PHASE28 GPIO bits */
37#define PHASE28_SPI_MISO (1 << 21) 37#define PHASE28_SPI_MISO (1 << 21)
diff --git a/sound/pci/ice1712/pontis.c b/sound/pci/ice1712/pontis.c
index 6c74c2d2e7f3..9552497f0765 100644
--- a/sound/pci/ice1712/pontis.c
+++ b/sound/pci/ice1712/pontis.c
@@ -434,7 +434,7 @@ static unsigned int spi_read(struct snd_ice1712 *ice, unsigned int dev, unsigned
434 */ 434 */
435static int cs_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo) 435static int cs_source_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
436{ 436{
437 static char *texts[] = { 437 static const char * const texts[] = {
438 "Coax", /* RXP0 */ 438 "Coax", /* RXP0 */
439 "Optical", /* RXP1 */ 439 "Optical", /* RXP1 */
440 "CD", /* RXP2 */ 440 "CD", /* RXP2 */
@@ -565,13 +565,13 @@ static int pontis_gpio_data_put(struct snd_kcontrol *kcontrol, struct snd_ctl_el
565 return changed; 565 return changed;
566} 566}
567 567
568static DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1); 568static const DECLARE_TLV_DB_SCALE(db_scale_volume, -6400, 50, 1);
569 569
570/* 570/*
571 * mixers 571 * mixers
572 */ 572 */
573 573
574static struct snd_kcontrol_new pontis_controls[] __devinitdata = { 574static const struct snd_kcontrol_new pontis_controls[] __devinitdata = {
575 { 575 {
576 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 576 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
577 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | 577 .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
@@ -741,7 +741,7 @@ static int __devinit pontis_add_controls(struct snd_ice1712 *ice)
741 */ 741 */
742static int __devinit pontis_init(struct snd_ice1712 *ice) 742static int __devinit pontis_init(struct snd_ice1712 *ice)
743{ 743{
744 static unsigned short wm_inits[] = { 744 static const unsigned short wm_inits[] = {
745 /* These come first to reduce init pop noise */ 745 /* These come first to reduce init pop noise */
746 WM_ADC_MUX, 0x00c0, /* ADC mute */ 746 WM_ADC_MUX, 0x00c0, /* ADC mute */
747 WM_DAC_MUTE, 0x0001, /* DAC softmute */ 747 WM_DAC_MUTE, 0x0001, /* DAC softmute */
@@ -750,7 +750,7 @@ static int __devinit pontis_init(struct snd_ice1712 *ice)
750 WM_POWERDOWN, 0x0008, /* All power-up except HP */ 750 WM_POWERDOWN, 0x0008, /* All power-up except HP */
751 WM_RESET, 0x0000, /* reset */ 751 WM_RESET, 0x0000, /* reset */
752 }; 752 };
753 static unsigned short wm_inits2[] = { 753 static const unsigned short wm_inits2[] = {
754 WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */ 754 WM_MASTER_CTRL, 0x0022, /* 256fs, slave mode */
755 WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */ 755 WM_DAC_INT, 0x0022, /* I2S, normal polarity, 24bit */
756 WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */ 756 WM_ADC_INT, 0x0022, /* I2S, normal polarity, 24bit */
@@ -776,7 +776,7 @@ static int __devinit pontis_init(struct snd_ice1712 *ice)
776 WM_DAC_MUTE, 0x0000, /* DAC unmute */ 776 WM_DAC_MUTE, 0x0000, /* DAC unmute */
777 WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */ 777 WM_ADC_MUX, 0x0003, /* ADC unmute, both CD/Line On */
778 }; 778 };
779 static unsigned char cs_inits[] = { 779 static const unsigned char cs_inits[] = {
780 0x04, 0x80, /* RUN, RXP0 */ 780 0x04, 0x80, /* RUN, RXP0 */
781 0x05, 0x05, /* slave, 24bit */ 781 0x05, 0x05, /* slave, 24bit */
782 0x01, 0x00, 782 0x01, 0x00,
@@ -826,24 +826,24 @@ static int __devinit pontis_init(struct snd_ice1712 *ice)
826 * hence the driver needs to sets up it properly. 826 * hence the driver needs to sets up it properly.
827 */ 827 */
828 828
829static unsigned char pontis_eeprom[] __devinitdata = { 829static const unsigned char pontis_eeprom[] __devinitdata = {
830 0x08, /* SYSCONF: clock 256, mpu401, spdif-in/ADC, 1DAC */ 830 [ICE_EEP2_SYSCONF] = 0x08, /* clock 256, mpu401, spdif-in/ADC, 1DAC */
831 0x80, /* ACLINK: I2S */ 831 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
832 0xf8, /* I2S: vol, 96k, 24bit, 192k */ 832 [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */
833 0xc3, /* SPDIF: out-en, out-int, spdif-in */ 833 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
834 0x07, /* GPIO_DIR */ 834 [ICE_EEP2_GPIO_DIR] = 0x07,
835 0x00, /* GPIO_DIR1 */ 835 [ICE_EEP2_GPIO_DIR1] = 0x00,
836 0x00, /* GPIO_DIR2 (ignored) */ 836 [ICE_EEP2_GPIO_DIR2] = 0x00, /* ignored */
837 0x0f, /* GPIO_MASK (4-7 reserved for CS8416) */ 837 [ICE_EEP2_GPIO_MASK] = 0x0f, /* 4-7 reserved for CS8416 */
838 0xff, /* GPIO_MASK1 */ 838 [ICE_EEP2_GPIO_MASK1] = 0xff,
839 0x00, /* GPIO_MASK2 (ignored) */ 839 [ICE_EEP2_GPIO_MASK2] = 0x00, /* ignored */
840 0x06, /* GPIO_STATE (0-low, 1-high, 2-high) */ 840 [ICE_EEP2_GPIO_STATE] = 0x06, /* 0-low, 1-high, 2-high */
841 0x00, /* GPIO_STATE1 */ 841 [ICE_EEP2_GPIO_STATE1] = 0x00,
842 0x00, /* GPIO_STATE2 (ignored) */ 842 [ICE_EEP2_GPIO_STATE2] = 0x00, /* ignored */
843}; 843};
844 844
845/* entry point */ 845/* entry point */
846struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = { 846const struct snd_ice1712_card_info snd_vt1720_pontis_cards[] __devinitdata = {
847 { 847 {
848 .subvendor = VT1720_SUBDEVICE_PONTIS_MS300, 848 .subvendor = VT1720_SUBDEVICE_PONTIS_MS300,
849 .name = "Pontis MS300", 849 .name = "Pontis MS300",
diff --git a/sound/pci/ice1712/pontis.h b/sound/pci/ice1712/pontis.h
index d0d1378b935c..1a418255c19e 100644
--- a/sound/pci/ice1712/pontis.h
+++ b/sound/pci/ice1712/pontis.h
@@ -28,6 +28,6 @@
28 28
29#define VT1720_SUBDEVICE_PONTIS_MS300 0x00020002 /* a dummy id for MS300 */ 29#define VT1720_SUBDEVICE_PONTIS_MS300 0x00020002 /* a dummy id for MS300 */
30 30
31extern struct snd_ice1712_card_info snd_vt1720_pontis_cards[]; 31extern const struct snd_ice1712_card_info snd_vt1720_pontis_cards[];
32 32
33#endif /* __SOUND_PONTIS_H */ 33#endif /* __SOUND_PONTIS_H */
diff --git a/sound/pci/ice1712/prodigy192.c b/sound/pci/ice1712/prodigy192.c
index 41b2605daa3a..31cc66eb9f8f 100644
--- a/sound/pci/ice1712/prodigy192.c
+++ b/sound/pci/ice1712/prodigy192.c
@@ -357,14 +357,14 @@ static int aureon_oversampling_put(struct snd_kcontrol *kcontrol, struct snd_ctl
357} 357}
358#endif 358#endif
359 359
360static DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0); 360static const DECLARE_TLV_DB_SCALE(db_scale_dac, -19125, 75, 0);
361static DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0); 361static const DECLARE_TLV_DB_SCALE(db_scale_adc, 0, 150, 0);
362 362
363/* 363/*
364 * mixers 364 * mixers
365 */ 365 */
366 366
367static struct snd_kcontrol_new stac_controls[] __devinitdata = { 367static const struct snd_kcontrol_new stac_controls[] __devinitdata = {
368 { 368 {
369 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 369 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
370 .name = "Master Playback Switch", 370 .name = "Master Playback Switch",
@@ -475,7 +475,7 @@ static int __devinit prodigy192_add_controls(struct snd_ice1712 *ice)
475 */ 475 */
476static int __devinit prodigy192_init(struct snd_ice1712 *ice) 476static int __devinit prodigy192_init(struct snd_ice1712 *ice)
477{ 477{
478 static unsigned short stac_inits_prodigy[] = { 478 static const unsigned short stac_inits_prodigy[] = {
479 STAC946X_RESET, 0, 479 STAC946X_RESET, 0,
480/* STAC946X_MASTER_VOLUME, 0, 480/* STAC946X_MASTER_VOLUME, 0,
481 STAC946X_LF_VOLUME, 0, 481 STAC946X_LF_VOLUME, 0,
@@ -486,7 +486,7 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
486 STAC946X_LFE_VOLUME, 0,*/ 486 STAC946X_LFE_VOLUME, 0,*/
487 (unsigned short)-1 487 (unsigned short)-1
488 }; 488 };
489 unsigned short *p; 489 const unsigned short *p;
490 490
491 /* prodigy 192 */ 491 /* prodigy 192 */
492 ice->num_total_dacs = 6; 492 ice->num_total_dacs = 6;
@@ -506,25 +506,25 @@ static int __devinit prodigy192_init(struct snd_ice1712 *ice)
506 * hence the driver needs to sets up it properly. 506 * hence the driver needs to sets up it properly.
507 */ 507 */
508 508
509static unsigned char prodigy71_eeprom[] __devinitdata = { 509static const unsigned char prodigy71_eeprom[] __devinitdata = {
510 0x2b, /* SYSCONF: clock 512, mpu401, spdif-in/ADC, 4DACs */ 510 [ICE_EEP2_SYSCONF] = 0x2b, /* clock 512, mpu401, spdif-in/ADC, 4DACs */
511 0x80, /* ACLINK: I2S */ 511 [ICE_EEP2_ACLINK] = 0x80, /* I2S */
512 0xf8, /* I2S: vol, 96k, 24bit, 192k */ 512 [ICE_EEP2_I2S] = 0xf8, /* vol, 96k, 24bit, 192k */
513 0xc3, /* SPDIF: out-en, out-int, spdif-in */ 513 [ICE_EEP2_SPDIF] = 0xc3, /* out-en, out-int, spdif-in */
514 0xff, /* GPIO_DIR */ 514 [ICE_EEP2_GPIO_DIR] = 0xff,
515 0xff, /* GPIO_DIR1 */ 515 [ICE_EEP2_GPIO_DIR1] = 0xff,
516 0xbf, /* GPIO_DIR2 */ 516 [ICE_EEP2_GPIO_DIR2] = 0xbf,
517 0x00, /* GPIO_MASK */ 517 [ICE_EEP2_GPIO_MASK] = 0x00,
518 0x00, /* GPIO_MASK1 */ 518 [ICE_EEP2_GPIO_MASK1] = 0x00,
519 0x00, /* GPIO_MASK2 */ 519 [ICE_EEP2_GPIO_MASK2] = 0x00,
520 0x00, /* GPIO_STATE */ 520 [ICE_EEP2_GPIO_STATE] = 0x00,
521 0x00, /* GPIO_STATE1 */ 521 [ICE_EEP2_GPIO_STATE1] = 0x00,
522 0x00, /* GPIO_STATE2 */ 522 [ICE_EEP2_GPIO_STATE2] = 0x00,
523}; 523};
524 524
525 525
526/* entry point */ 526/* entry point */
527struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = { 527const struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[] __devinitdata = {
528 { 528 {
529 .subvendor = VT1724_SUBDEVICE_PRODIGY192VE, 529 .subvendor = VT1724_SUBDEVICE_PRODIGY192VE,
530 .name = "Audiotrak Prodigy 192", 530 .name = "Audiotrak Prodigy 192",
diff --git a/sound/pci/ice1712/prodigy192.h b/sound/pci/ice1712/prodigy192.h
index 94c824e24e06..2fa2e62b9e04 100644
--- a/sound/pci/ice1712/prodigy192.h
+++ b/sound/pci/ice1712/prodigy192.h
@@ -6,6 +6,6 @@
6 6
7#define VT1724_SUBDEVICE_PRODIGY192VE 0x34495345 /* PRODIGY 192 VE */ 7#define VT1724_SUBDEVICE_PRODIGY192VE 0x34495345 /* PRODIGY 192 VE */
8 8
9extern struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[]; 9extern const struct snd_ice1712_card_info snd_vt1724_prodigy192_cards[];
10 10
11#endif /* __SOUND_PRODIGY192_H */ 11#endif /* __SOUND_PRODIGY192_H */
diff --git a/sound/pci/ice1712/revo.c b/sound/pci/ice1712/revo.c
index bf98ea34feb0..025a7e8497c3 100644
--- a/sound/pci/ice1712/revo.c
+++ b/sound/pci/ice1712/revo.c
@@ -84,38 +84,142 @@ static void revo_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
84} 84}
85 85
86/* 86/*
87 * I2C access to the PT2258 volume controller on GPIO 6/7 (Revolution 5.1)
88 */
89
90static void revo_i2c_start(struct snd_i2c_bus *bus)
91{
92 struct snd_ice1712 *ice = bus->private_data;
93 snd_ice1712_save_gpio_status(ice);
94}
95
96static void revo_i2c_stop(struct snd_i2c_bus *bus)
97{
98 struct snd_ice1712 *ice = bus->private_data;
99 snd_ice1712_restore_gpio_status(ice);
100}
101
102static void revo_i2c_direction(struct snd_i2c_bus *bus, int clock, int data)
103{
104 struct snd_ice1712 *ice = bus->private_data;
105 unsigned int mask, val;
106
107 val = 0;
108 if (clock)
109 val |= VT1724_REVO_I2C_CLOCK; /* write SCL */
110 if (data)
111 val |= VT1724_REVO_I2C_DATA; /* write SDA */
112 mask = VT1724_REVO_I2C_CLOCK | VT1724_REVO_I2C_DATA;
113 ice->gpio.direction &= ~mask;
114 ice->gpio.direction |= val;
115 snd_ice1712_gpio_set_dir(ice, ice->gpio.direction);
116 snd_ice1712_gpio_set_mask(ice, ~mask);
117}
118
119static void revo_i2c_setlines(struct snd_i2c_bus *bus, int clk, int data)
120{
121 struct snd_ice1712 *ice = bus->private_data;
122 unsigned int val = 0;
123
124 if (clk)
125 val |= VT1724_REVO_I2C_CLOCK;
126 if (data)
127 val |= VT1724_REVO_I2C_DATA;
128 snd_ice1712_gpio_write_bits(ice,
129 VT1724_REVO_I2C_DATA |
130 VT1724_REVO_I2C_CLOCK, val);
131 udelay(5);
132}
133
134static int revo_i2c_getdata(struct snd_i2c_bus *bus, int ack)
135{
136 struct snd_ice1712 *ice = bus->private_data;
137 int bit;
138
139 if (ack)
140 udelay(5);
141 bit = snd_ice1712_gpio_read_bits(ice, VT1724_REVO_I2C_DATA) ? 1 : 0;
142 return bit;
143}
144
145static struct snd_i2c_bit_ops revo51_bit_ops = {
146 .start = revo_i2c_start,
147 .stop = revo_i2c_stop,
148 .direction = revo_i2c_direction,
149 .setlines = revo_i2c_setlines,
150 .getdata = revo_i2c_getdata,
151};
152
153static int revo51_i2c_init(struct snd_ice1712 *ice,
154 struct snd_pt2258 *pt)
155{
156 int err;
157
158 /* create the I2C bus */
159 err = snd_i2c_bus_create(ice->card, "ICE1724 GPIO6", NULL, &ice->i2c);
160 if (err < 0)
161 return err;
162
163 ice->i2c->private_data = ice;
164 ice->i2c->hw_ops.bit = &revo51_bit_ops;
165
166 /* create the I2C device */
167 err = snd_i2c_device_create(ice->i2c, "PT2258", 0x40,
168 &ice->spec.revo51.dev);
169 if (err < 0)
170 return err;
171
172 pt->card = ice->card;
173 pt->i2c_bus = ice->i2c;
174 pt->i2c_dev = ice->spec.revo51.dev;
175 ice->spec.revo51.pt2258 = pt;
176
177 snd_pt2258_reset(pt);
178
179 return 0;
180}
181
182/*
87 * initialize the chips on M-Audio Revolution cards 183 * initialize the chips on M-Audio Revolution cards
88 */ 184 */
89 185
90#define AK_DAC(xname,xch) { .name = xname, .num_channels = xch } 186#define AK_DAC(xname,xch) { .name = xname, .num_channels = xch }
91 187
92static struct snd_akm4xxx_dac_channel revo71_front[] = { 188static const struct snd_akm4xxx_dac_channel revo71_front[] = {
93 AK_DAC("PCM Playback Volume", 2) 189 AK_DAC("PCM Playback Volume", 2)
94}; 190};
95 191
96static struct snd_akm4xxx_dac_channel revo71_surround[] = { 192static const struct snd_akm4xxx_dac_channel revo71_surround[] = {
97 AK_DAC("PCM Center Playback Volume", 1), 193 AK_DAC("PCM Center Playback Volume", 1),
98 AK_DAC("PCM LFE Playback Volume", 1), 194 AK_DAC("PCM LFE Playback Volume", 1),
99 AK_DAC("PCM Side Playback Volume", 2), 195 AK_DAC("PCM Side Playback Volume", 2),
100 AK_DAC("PCM Rear Playback Volume", 2), 196 AK_DAC("PCM Rear Playback Volume", 2),
101}; 197};
102 198
103static struct snd_akm4xxx_dac_channel revo51_dac[] = { 199static const struct snd_akm4xxx_dac_channel revo51_dac[] = {
104 AK_DAC("PCM Playback Volume", 2), 200 AK_DAC("PCM Playback Volume", 2),
105 AK_DAC("PCM Center Playback Volume", 1), 201 AK_DAC("PCM Center Playback Volume", 1),
106 AK_DAC("PCM LFE Playback Volume", 1), 202 AK_DAC("PCM LFE Playback Volume", 1),
107 AK_DAC("PCM Rear Playback Volume", 2), 203 AK_DAC("PCM Rear Playback Volume", 2),
108}; 204};
109 205
110static struct snd_akm4xxx_adc_channel revo51_adc[] = { 206static const char *revo51_adc_input_names[] = {
207 "Mic",
208 "Line",
209 "CD",
210 NULL
211};
212
213static const struct snd_akm4xxx_adc_channel revo51_adc[] = {
111 { 214 {
112 .name = "PCM Capture Volume", 215 .name = "PCM Capture Volume",
113 .switch_name = "PCM Capture Switch", 216 .switch_name = "PCM Capture Switch",
114 .num_channels = 2 217 .num_channels = 2,
218 .input_names = revo51_adc_input_names
115 }, 219 },
116}; 220};
117 221
118static struct snd_akm4xxx akm_revo_front __devinitdata = { 222static const struct snd_akm4xxx akm_revo_front __devinitdata = {
119 .type = SND_AK4381, 223 .type = SND_AK4381,
120 .num_dacs = 2, 224 .num_dacs = 2,
121 .ops = { 225 .ops = {
@@ -124,7 +228,7 @@ static struct snd_akm4xxx akm_revo_front __devinitdata = {
124 .dac_info = revo71_front, 228 .dac_info = revo71_front,
125}; 229};
126 230
127static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = { 231static const struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
128 .caddr = 1, 232 .caddr = 1,
129 .cif = 0, 233 .cif = 0,
130 .data_mask = VT1724_REVO_CDOUT, 234 .data_mask = VT1724_REVO_CDOUT,
@@ -136,7 +240,7 @@ static struct snd_ak4xxx_private akm_revo_front_priv __devinitdata = {
136 .mask_flags = 0, 240 .mask_flags = 0,
137}; 241};
138 242
139static struct snd_akm4xxx akm_revo_surround __devinitdata = { 243static const struct snd_akm4xxx akm_revo_surround __devinitdata = {
140 .type = SND_AK4355, 244 .type = SND_AK4355,
141 .idx_offset = 1, 245 .idx_offset = 1,
142 .num_dacs = 6, 246 .num_dacs = 6,
@@ -146,7 +250,7 @@ static struct snd_akm4xxx akm_revo_surround __devinitdata = {
146 .dac_info = revo71_surround, 250 .dac_info = revo71_surround,
147}; 251};
148 252
149static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = { 253static const struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
150 .caddr = 3, 254 .caddr = 3,
151 .cif = 0, 255 .cif = 0,
152 .data_mask = VT1724_REVO_CDOUT, 256 .data_mask = VT1724_REVO_CDOUT,
@@ -158,7 +262,7 @@ static struct snd_ak4xxx_private akm_revo_surround_priv __devinitdata = {
158 .mask_flags = 0, 262 .mask_flags = 0,
159}; 263};
160 264
161static struct snd_akm4xxx akm_revo51 __devinitdata = { 265static const struct snd_akm4xxx akm_revo51 __devinitdata = {
162 .type = SND_AK4358, 266 .type = SND_AK4358,
163 .num_dacs = 6, 267 .num_dacs = 6,
164 .ops = { 268 .ops = {
@@ -167,36 +271,213 @@ static struct snd_akm4xxx akm_revo51 __devinitdata = {
167 .dac_info = revo51_dac, 271 .dac_info = revo51_dac,
168}; 272};
169 273
170static struct snd_ak4xxx_private akm_revo51_priv __devinitdata = { 274static const struct snd_ak4xxx_private akm_revo51_priv __devinitdata = {
171 .caddr = 2, 275 .caddr = 2,
172 .cif = 0, 276 .cif = 0,
173 .data_mask = VT1724_REVO_CDOUT, 277 .data_mask = VT1724_REVO_CDOUT,
174 .clk_mask = VT1724_REVO_CCLK, 278 .clk_mask = VT1724_REVO_CCLK,
175 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 279 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
176 .cs_addr = VT1724_REVO_CS1 | VT1724_REVO_CS2, 280 .cs_addr = VT1724_REVO_CS1,
177 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 281 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
178 .add_flags = VT1724_REVO_CCLK, /* high at init */ 282 .add_flags = VT1724_REVO_CCLK, /* high at init */
179 .mask_flags = 0, 283 .mask_flags = 0,
180}; 284};
181 285
182static struct snd_akm4xxx akm_revo51_adc __devinitdata = { 286static const struct snd_akm4xxx akm_revo51_adc __devinitdata = {
183 .type = SND_AK5365, 287 .type = SND_AK5365,
184 .num_adcs = 2, 288 .num_adcs = 2,
185 .adc_info = revo51_adc, 289 .adc_info = revo51_adc,
186}; 290};
187 291
188static struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = { 292static const struct snd_ak4xxx_private akm_revo51_adc_priv __devinitdata = {
189 .caddr = 2, 293 .caddr = 2,
190 .cif = 0, 294 .cif = 0,
191 .data_mask = VT1724_REVO_CDOUT, 295 .data_mask = VT1724_REVO_CDOUT,
192 .clk_mask = VT1724_REVO_CCLK, 296 .clk_mask = VT1724_REVO_CCLK,
193 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 297 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS1,
194 .cs_addr = VT1724_REVO_CS0 | VT1724_REVO_CS2, 298 .cs_addr = VT1724_REVO_CS0,
195 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1 | VT1724_REVO_CS2, 299 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS1,
300 .add_flags = VT1724_REVO_CCLK, /* high at init */
301 .mask_flags = 0,
302};
303
304static struct snd_pt2258 ptc_revo51_volume;
305
306/* AK4358 for AP192 DAC, AK5385A for ADC */
307static void ap192_set_rate_val(struct snd_akm4xxx *ak, unsigned int rate)
308{
309 struct snd_ice1712 *ice = ak->private_data[0];
310
311 revo_set_rate_val(ak, rate);
312
313#if 1 /* FIXME: do we need this procedure? */
314 /* reset DFS pin of AK5385A for ADC, too */
315 /* DFS0 (pin 18) -- GPIO10 pin 77 */
316 snd_ice1712_save_gpio_status(ice);
317 snd_ice1712_gpio_write_bits(ice, 1 << 10,
318 rate > 48000 ? (1 << 10) : 0);
319 snd_ice1712_restore_gpio_status(ice);
320#endif
321}
322
323static const struct snd_akm4xxx_dac_channel ap192_dac[] = {
324 AK_DAC("PCM Playback Volume", 2)
325};
326
327static const struct snd_akm4xxx akm_ap192 __devinitdata = {
328 .type = SND_AK4358,
329 .num_dacs = 2,
330 .ops = {
331 .set_rate_val = ap192_set_rate_val
332 },
333 .dac_info = ap192_dac,
334};
335
336static const struct snd_ak4xxx_private akm_ap192_priv __devinitdata = {
337 .caddr = 2,
338 .cif = 0,
339 .data_mask = VT1724_REVO_CDOUT,
340 .clk_mask = VT1724_REVO_CCLK,
341 .cs_mask = VT1724_REVO_CS0 | VT1724_REVO_CS3,
342 .cs_addr = VT1724_REVO_CS3,
343 .cs_none = VT1724_REVO_CS0 | VT1724_REVO_CS3,
196 .add_flags = VT1724_REVO_CCLK, /* high at init */ 344 .add_flags = VT1724_REVO_CCLK, /* high at init */
197 .mask_flags = 0, 345 .mask_flags = 0,
198}; 346};
199 347
348#if 0
349/* FIXME: ak4114 makes the sound much lower due to some confliction,
350 * so let's disable it right now...
351 */
352#define BUILD_AK4114_AP192
353#endif
354
355#ifdef BUILD_AK4114_AP192
356/* AK4114 support on Audiophile 192 */
357/* CDTO (pin 32) -- GPIO2 pin 52
358 * CDTI (pin 33) -- GPIO3 pin 53 (shared with AK4358)
359 * CCLK (pin 34) -- GPIO1 pin 51 (shared with AK4358)
360 * CSN (pin 35) -- GPIO7 pin 59
361 */
362#define AK4114_ADDR 0x00
363
364static void write_data(struct snd_ice1712 *ice, unsigned int gpio,
365 unsigned int data, int idx)
366{
367 for (; idx >= 0; idx--) {
368 /* drop clock */
369 gpio &= ~VT1724_REVO_CCLK;
370 snd_ice1712_gpio_write(ice, gpio);
371 udelay(1);
372 /* set data */
373 if (data & (1 << idx))
374 gpio |= VT1724_REVO_CDOUT;
375 else
376 gpio &= ~VT1724_REVO_CDOUT;
377 snd_ice1712_gpio_write(ice, gpio);
378 udelay(1);
379 /* raise clock */
380 gpio |= VT1724_REVO_CCLK;
381 snd_ice1712_gpio_write(ice, gpio);
382 udelay(1);
383 }
384}
385
386static unsigned char read_data(struct snd_ice1712 *ice, unsigned int gpio,
387 int idx)
388{
389 unsigned char data = 0;
390
391 for (; idx >= 0; idx--) {
392 /* drop clock */
393 gpio &= ~VT1724_REVO_CCLK;
394 snd_ice1712_gpio_write(ice, gpio);
395 udelay(1);
396 /* read data */
397 if (snd_ice1712_gpio_read(ice) & VT1724_REVO_CDIN)
398 data |= (1 << idx);
399 udelay(1);
400 /* raise clock */
401 gpio |= VT1724_REVO_CCLK;
402 snd_ice1712_gpio_write(ice, gpio);
403 udelay(1);
404 }
405 return data;
406}
407
408static unsigned char ap192_4wire_start(struct snd_ice1712 *ice)
409{
410 unsigned int tmp;
411
412 snd_ice1712_save_gpio_status(ice);
413 tmp = snd_ice1712_gpio_read(ice);
414 tmp |= VT1724_REVO_CCLK; /* high at init */
415 tmp |= VT1724_REVO_CS0;
416 tmp &= ~VT1724_REVO_CS3;
417 snd_ice1712_gpio_write(ice, tmp);
418 udelay(1);
419 return tmp;
420}
421
422static void ap192_4wire_finish(struct snd_ice1712 *ice, unsigned int tmp)
423{
424 tmp |= VT1724_REVO_CS3;
425 tmp |= VT1724_REVO_CS0;
426 snd_ice1712_gpio_write(ice, tmp);
427 udelay(1);
428 snd_ice1712_restore_gpio_status(ice);
429}
430
431static void ap192_ak4114_write(void *private_data, unsigned char addr,
432 unsigned char data)
433{
434 struct snd_ice1712 *ice = private_data;
435 unsigned int tmp, addrdata;
436
437 tmp = ap192_4wire_start(ice);
438 addrdata = (AK4114_ADDR << 6) | 0x20 | (addr & 0x1f);
439 addrdata = (addrdata << 8) | data;
440 write_data(ice, tmp, addrdata, 15);
441 ap192_4wire_finish(ice, tmp);
442}
443
444static unsigned char ap192_ak4114_read(void *private_data, unsigned char addr)
445{
446 struct snd_ice1712 *ice = private_data;
447 unsigned int tmp;
448 unsigned char data;
449
450 tmp = ap192_4wire_start(ice);
451 write_data(ice, tmp, (AK4114_ADDR << 6) | (addr & 0x1f), 7);
452 data = read_data(ice, tmp, 7);
453 ap192_4wire_finish(ice, tmp);
454 return data;
455}
456
457static int ap192_ak4114_init(struct snd_ice1712 *ice)
458{
459 static const unsigned char ak4114_init_vals[] = {
460 AK4114_RST | AK4114_PWN | AK4114_OCKS0 | AK4114_OCKS1,
461 AK4114_DIF_I24I2S,
462 AK4114_TX1E,
463 AK4114_EFH_1024 | AK4114_DIT | AK4114_IPS(1),
464 0,
465 0
466 };
467 static const unsigned char ak4114_init_txcsb[] = {
468 0x41, 0x02, 0x2c, 0x00, 0x00
469 };
470 struct ak4114 *ak;
471 int err;
472
473 return snd_ak4114_create(ice->card,
474 ap192_ak4114_read,
475 ap192_ak4114_write,
476 ak4114_init_vals, ak4114_init_txcsb,
477 ice, &ak);
478}
479#endif /* BUILD_AK4114_AP192 */
480
200static int __devinit revo_init(struct snd_ice1712 *ice) 481static int __devinit revo_init(struct snd_ice1712 *ice)
201{ 482{
202 struct snd_akm4xxx *ak; 483 struct snd_akm4xxx *ak;
@@ -213,6 +494,10 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
213 ice->num_total_dacs = 6; 494 ice->num_total_dacs = 6;
214 ice->num_total_adcs = 2; 495 ice->num_total_adcs = 2;
215 break; 496 break;
497 case VT1724_SUBDEVICE_AUDIOPHILE192:
498 ice->num_total_dacs = 2;
499 ice->num_total_adcs = 2;
500 break;
216 default: 501 default:
217 snd_BUG(); 502 snd_BUG();
218 return -EINVAL; 503 return -EINVAL;
@@ -235,14 +520,28 @@ static int __devinit revo_init(struct snd_ice1712 *ice)
235 break; 520 break;
236 case VT1724_SUBDEVICE_REVOLUTION51: 521 case VT1724_SUBDEVICE_REVOLUTION51:
237 ice->akm_codecs = 2; 522 ice->akm_codecs = 2;
238 if ((err = snd_ice1712_akm4xxx_init(ak, &akm_revo51, &akm_revo51_priv, ice)) < 0) 523 err = snd_ice1712_akm4xxx_init(ak, &akm_revo51,
524 &akm_revo51_priv, ice);
525 if (err < 0)
239 return err; 526 return err;
240 err = snd_ice1712_akm4xxx_init(ak + 1, &akm_revo51_adc, 527 err = snd_ice1712_akm4xxx_init(ak+1, &akm_revo51_adc,
241 &akm_revo51_adc_priv, ice); 528 &akm_revo51_adc_priv, ice);
242 if (err < 0) 529 if (err < 0)
243 return err; 530 return err;
244 /* unmute all codecs - needed! */ 531 err = revo51_i2c_init(ice, &ptc_revo51_volume);
245 snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE, VT1724_REVO_MUTE); 532 if (err < 0)
533 return err;
534 /* unmute all codecs */
535 snd_ice1712_gpio_write_bits(ice, VT1724_REVO_MUTE,
536 VT1724_REVO_MUTE);
537 break;
538 case VT1724_SUBDEVICE_AUDIOPHILE192:
539 ice->akm_codecs = 1;
540 err = snd_ice1712_akm4xxx_init(ak, &akm_ap192, &akm_ap192_priv,
541 ice);
542 if (err < 0)
543 return err;
544
246 break; 545 break;
247 } 546 }
248 547
@@ -256,16 +555,34 @@ static int __devinit revo_add_controls(struct snd_ice1712 *ice)
256 555
257 switch (ice->eeprom.subvendor) { 556 switch (ice->eeprom.subvendor) {
258 case VT1724_SUBDEVICE_REVOLUTION71: 557 case VT1724_SUBDEVICE_REVOLUTION71:
558 err = snd_ice1712_akm4xxx_build_controls(ice);
559 if (err < 0)
560 return err;
561 break;
259 case VT1724_SUBDEVICE_REVOLUTION51: 562 case VT1724_SUBDEVICE_REVOLUTION51:
260 err = snd_ice1712_akm4xxx_build_controls(ice); 563 err = snd_ice1712_akm4xxx_build_controls(ice);
261 if (err < 0) 564 if (err < 0)
262 return err; 565 return err;
566 err = snd_pt2258_build_controls(ice->spec.revo51.pt2258);
567 if (err < 0)
568 return err;
569 break;
570 case VT1724_SUBDEVICE_AUDIOPHILE192:
571 err = snd_ice1712_akm4xxx_build_controls(ice);
572 if (err < 0)
573 return err;
574#ifdef BUILD_AK4114_AP192
575 err = ap192_ak4114_init(ice);
576 if (err < 0)
577 return err;
578#endif
579 break;
263 } 580 }
264 return 0; 581 return 0;
265} 582}
266 583
267/* entry point */ 584/* entry point */
268struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = { 585const struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
269 { 586 {
270 .subvendor = VT1724_SUBDEVICE_REVOLUTION71, 587 .subvendor = VT1724_SUBDEVICE_REVOLUTION71,
271 .name = "M Audio Revolution-7.1", 588 .name = "M Audio Revolution-7.1",
@@ -280,5 +597,12 @@ struct snd_ice1712_card_info snd_vt1724_revo_cards[] __devinitdata = {
280 .chip_init = revo_init, 597 .chip_init = revo_init,
281 .build_controls = revo_add_controls, 598 .build_controls = revo_add_controls,
282 }, 599 },
600 {
601 .subvendor = VT1724_SUBDEVICE_AUDIOPHILE192,
602 .name = "M Audio Audiophile192",
603 .model = "ap192",
604 .chip_init = revo_init,
605 .build_controls = revo_add_controls,
606 },
283 { } /* terminator */ 607 { } /* terminator */
284}; 608};
diff --git a/sound/pci/ice1712/revo.h b/sound/pci/ice1712/revo.h
index efbb86ec3289..2a24488fad80 100644
--- a/sound/pci/ice1712/revo.h
+++ b/sound/pci/ice1712/revo.h
@@ -26,13 +26,15 @@
26 26
27#define REVO_DEVICE_DESC \ 27#define REVO_DEVICE_DESC \
28 "{MidiMan M Audio,Revolution 7.1},"\ 28 "{MidiMan M Audio,Revolution 7.1},"\
29 "{MidiMan M Audio,Revolution 5.1}," 29 "{MidiMan M Audio,Revolution 5.1},"\
30 "{MidiMan M Audio,Audiophile 192},"
30 31
31#define VT1724_SUBDEVICE_REVOLUTION71 0x12143036 32#define VT1724_SUBDEVICE_REVOLUTION71 0x12143036
32#define VT1724_SUBDEVICE_REVOLUTION51 0x12143136 33#define VT1724_SUBDEVICE_REVOLUTION51 0x12143136
34#define VT1724_SUBDEVICE_AUDIOPHILE192 0x12143236
33 35
34/* entry point */ 36/* entry point */
35extern struct snd_ice1712_card_info snd_vt1724_revo_cards[]; 37extern const struct snd_ice1712_card_info snd_vt1724_revo_cards[];
36 38
37 39
38/* 40/*
@@ -42,9 +44,12 @@ extern struct snd_ice1712_card_info snd_vt1724_revo_cards[];
42#define VT1724_REVO_CCLK 0x02 44#define VT1724_REVO_CCLK 0x02
43#define VT1724_REVO_CDIN 0x04 /* not used */ 45#define VT1724_REVO_CDIN 0x04 /* not used */
44#define VT1724_REVO_CDOUT 0x08 46#define VT1724_REVO_CDOUT 0x08
45#define VT1724_REVO_CS0 0x10 /* AK5365 chipselect for Rev. 5.1 */ 47#define VT1724_REVO_CS0 0x10 /* AK5365 chipselect for (revo51) */
46#define VT1724_REVO_CS1 0x20 /* front AKM4381 chipselect */ 48#define VT1724_REVO_CS1 0x20 /* front AKM4381 chipselect */
47#define VT1724_REVO_CS2 0x40 /* surround AKM4355 chipselect */ 49#define VT1724_REVO_CS2 0x40 /* surround AKM4355 CS (revo71) */
50#define VT1724_REVO_I2C_DATA 0x40 /* I2C: PT 2258 SDA (on revo51) */
51#define VT1724_REVO_I2C_CLOCK 0x80 /* I2C: PT 2258 SCL (on revo51) */
52#define VT1724_REVO_CS3 0x80 /* AK4114 for AP192 */
48#define VT1724_REVO_MUTE (1<<22) /* 0 = all mute, 1 = normal operation */ 53#define VT1724_REVO_MUTE (1<<22) /* 0 = all mute, 1 = normal operation */
49 54
50#endif /* __SOUND_REVO_H */ 55#endif /* __SOUND_REVO_H */
diff --git a/sound/pci/ice1712/vt1720_mobo.c b/sound/pci/ice1712/vt1720_mobo.c
index 7ca263c13091..72b060d63c29 100644
--- a/sound/pci/ice1712/vt1720_mobo.c
+++ b/sound/pci/ice1712/vt1720_mobo.c
@@ -30,6 +30,7 @@
30#include <sound/core.h> 30#include <sound/core.h>
31 31
32#include "ice1712.h" 32#include "ice1712.h"
33#include "envy24ht.h"
33#include "vt1720_mobo.h" 34#include "vt1720_mobo.h"
34 35
35 36
@@ -55,41 +56,41 @@ static int __devinit k8x800_add_controls(struct snd_ice1712 *ice)
55 56
56/* EEPROM image */ 57/* EEPROM image */
57 58
58static unsigned char k8x800_eeprom[] __devinitdata = { 59static const unsigned char k8x800_eeprom[] __devinitdata = {
59 0x01, /* SYSCONF: clock 256, 1ADC, 2DACs */ 60 [ICE_EEP2_SYSCONF] = 0x01, /* clock 256, 1ADC, 2DACs */
60 0x02, /* ACLINK: ACLINK, packed */ 61 [ICE_EEP2_ACLINK] = 0x02, /* ACLINK, packed */
61 0x00, /* I2S: - */ 62 [ICE_EEP2_I2S] = 0x00, /* - */
62 0x00, /* SPDIF: - */ 63 [ICE_EEP2_SPDIF] = 0x00, /* - */
63 0xff, /* GPIO_DIR */ 64 [ICE_EEP2_GPIO_DIR] = 0xff,
64 0xff, /* GPIO_DIR1 */ 65 [ICE_EEP2_GPIO_DIR1] = 0xff,
65 0x00, /* - */ 66 [ICE_EEP2_GPIO_DIR2] = 0x00, /* - */
66 0xff, /* GPIO_MASK */ 67 [ICE_EEP2_GPIO_MASK] = 0xff,
67 0xff, /* GPIO_MASK1 */ 68 [ICE_EEP2_GPIO_MASK1] = 0xff,
68 0x00, /* - */ 69 [ICE_EEP2_GPIO_MASK2] = 0x00, /* - */
69 0x00, /* GPIO_STATE */ 70 [ICE_EEP2_GPIO_STATE] = 0x00,
70 0x00, /* GPIO_STATE1 */ 71 [ICE_EEP2_GPIO_STATE1] = 0x00,
71 0x00, /* - */ 72 [ICE_EEP2_GPIO_STATE2] = 0x00, /* - */
72}; 73};
73 74
74static unsigned char sn25p_eeprom[] __devinitdata = { 75static const unsigned char sn25p_eeprom[] __devinitdata = {
75 0x01, /* SYSCONF: clock 256, 1ADC, 2DACs */ 76 [ICE_EEP2_SYSCONF] = 0x01, /* clock 256, 1ADC, 2DACs */
76 0x02, /* ACLINK: ACLINK, packed */ 77 [ICE_EEP2_ACLINK] = 0x02, /* ACLINK, packed */
77 0x00, /* I2S: - */ 78 [ICE_EEP2_I2S] = 0x00, /* - */
78 0x41, /* SPDIF: - */ 79 [ICE_EEP2_SPDIF] = 0x41, /* - */
79 0xff, /* GPIO_DIR */ 80 [ICE_EEP2_GPIO_DIR] = 0xff,
80 0xff, /* GPIO_DIR1 */ 81 [ICE_EEP2_GPIO_DIR1] = 0xff,
81 0x00, /* - */ 82 [ICE_EEP2_GPIO_DIR2] = 0x00, /* - */
82 0xff, /* GPIO_MASK */ 83 [ICE_EEP2_GPIO_MASK] = 0xff,
83 0xff, /* GPIO_MASK1 */ 84 [ICE_EEP2_GPIO_MASK1] = 0xff,
84 0x00, /* - */ 85 [ICE_EEP2_GPIO_MASK2] = 0x00, /* - */
85 0x00, /* GPIO_STATE */ 86 [ICE_EEP2_GPIO_STATE] = 0x00,
86 0x00, /* GPIO_STATE1 */ 87 [ICE_EEP2_GPIO_STATE1] = 0x00,
87 0x00, /* - */ 88 [ICE_EEP2_GPIO_STATE2] = 0x00, /* - */
88}; 89};
89 90
90 91
91/* entry point */ 92/* entry point */
92struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = { 93const struct snd_ice1712_card_info snd_vt1720_mobo_cards[] __devinitdata = {
93 { 94 {
94 .subvendor = VT1720_SUBDEVICE_K8X800, 95 .subvendor = VT1720_SUBDEVICE_K8X800,
95 .name = "Albatron K8X800 Pro II", 96 .name = "Albatron K8X800 Pro II",
diff --git a/sound/pci/ice1712/vt1720_mobo.h b/sound/pci/ice1712/vt1720_mobo.h
index 0b1b0ee1bea7..70af3ad64a5d 100644
--- a/sound/pci/ice1712/vt1720_mobo.h
+++ b/sound/pci/ice1712/vt1720_mobo.h
@@ -36,6 +36,6 @@
36#define VT1720_SUBDEVICE_9CJS 0x0f272327 36#define VT1720_SUBDEVICE_9CJS 0x0f272327
37#define VT1720_SUBDEVICE_SN25P 0x97123650 37#define VT1720_SUBDEVICE_SN25P 0x97123650
38 38
39extern struct snd_ice1712_card_info snd_vt1720_mobo_cards[]; 39extern const struct snd_ice1712_card_info snd_vt1720_mobo_cards[];
40 40
41#endif /* __SOUND_VT1720_MOBO_H */ 41#endif /* __SOUND_VT1720_MOBO_H */
diff --git a/sound/pci/ice1712/wtm.c b/sound/pci/ice1712/wtm.c
new file mode 100644
index 000000000000..4a706b16a0b9
--- /dev/null
+++ b/sound/pci/ice1712/wtm.c
@@ -0,0 +1,542 @@
1/*
2 * ALSA driver for ICEnsemble VT1724 (Envy24HT)
3 *
4 * Lowlevel functions for Ego Sys Waveterminal 192M
5 *
6 * Copyright (c) 2006 Guedez Clement <klem.dev@gmail.com>
7 * Some functions are taken from the Prodigy192 driver
8 * source
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26
27
28#include <sound/driver.h>
29#include <asm/io.h>
30#include <linux/delay.h>
31#include <linux/interrupt.h>
32#include <linux/init.h>
33#include <linux/slab.h>
34#include <sound/core.h>
35
36#include "ice1712.h"
37#include "envy24ht.h"
38#include "wtm.h"
39#include "stac946x.h"
40
41
42/*
43 * 2*ADC 6*DAC no1 ringbuffer r/w on i2c bus
44 */
45static inline void stac9460_put(struct snd_ice1712 *ice, int reg,
46 unsigned char val)
47{
48 snd_vt1724_write_i2c(ice, STAC9460_I2C_ADDR, reg, val);
49}
50
51static inline unsigned char stac9460_get(struct snd_ice1712 *ice, int reg)
52{
53 return snd_vt1724_read_i2c(ice, STAC9460_I2C_ADDR, reg);
54}
55
56/*
57 * 2*ADC 2*DAC no2 ringbuffer r/w on i2c bus
58 */
59static inline void stac9460_2_put(struct snd_ice1712 *ice, int reg,
60 unsigned char val)
61{
62 snd_vt1724_write_i2c(ice, STAC9460_2_I2C_ADDR, reg, val);
63}
64
65static inline unsigned char stac9460_2_get(struct snd_ice1712 *ice, int reg)
66{
67 return snd_vt1724_read_i2c(ice, STAC9460_2_I2C_ADDR, reg);
68}
69
70
71/*
72 * DAC mute control
73 */
74static int stac9460_dac_mute_info(struct snd_kcontrol *kcontrol,
75 struct snd_ctl_elem_info *uinfo)
76{
77 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
78 uinfo->count = 1;
79 uinfo->value.integer.min = 0;
80 return 0;
81}
82
83static int stac9460_dac_mute_get(struct snd_kcontrol *kcontrol,
84 struct snd_ctl_elem_value *ucontrol)
85{
86 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
87 unsigned char val;
88 int idx, id;
89
90 if (kcontrol->private_value) {
91 idx = STAC946X_MASTER_VOLUME;
92 id = 0;
93 } else {
94 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
95 idx = id + STAC946X_LF_VOLUME;
96 }
97 if (id < 6)
98 val = stac9460_get(ice, idx);
99 else
100 val = stac9460_2_get(ice,idx - 6);
101 ucontrol->value.integer.value[0] = (~val >> 7) & 0x1;
102 return 0;
103}
104
105static int stac9460_dac_mute_put(struct snd_kcontrol *kcontrol,
106 struct snd_ctl_elem_value *ucontrol)
107{
108 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
109 unsigned char new, old;
110 int id, idx;
111 int change;
112
113 if (kcontrol->private_value) {
114 idx = STAC946X_MASTER_VOLUME;
115 old = stac9460_get(ice, idx);
116 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
117 (old & ~0x80);
118 change = (new != old);
119 if (change) {
120 stac9460_put(ice, idx, new);
121 stac9460_2_put(ice, idx, new);
122 }
123 } else {
124 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
125 idx = id + STAC946X_LF_VOLUME;
126 if (id < 6)
127 old = stac9460_get(ice, idx);
128 else
129 old = stac9460_2_get(ice, idx - 6);
130 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) |
131 (old & ~0x80);
132 change = (new != old);
133 if (change) {
134 if (id < 6)
135 stac9460_put(ice, idx, new);
136 else
137 stac9460_2_put(ice, idx - 6, new);
138 }
139 }
140 return change;
141}
142
143/*
144 * DAC volume attenuation mixer control
145 */
146static int stac9460_dac_vol_info(struct snd_kcontrol *kcontrol,
147 struct snd_ctl_elem_info *uinfo)
148{
149 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
150 uinfo->count = 1;
151 uinfo->value.integer.min = 0; /* mute */
152 uinfo->value.integer.max = 0x7f; /* 0dB */
153 return 0;
154}
155
156static int stac9460_dac_vol_get(struct snd_kcontrol *kcontrol,
157 struct snd_ctl_elem_value *ucontrol)
158{
159 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
160 int idx, id;
161 unsigned char vol;
162
163 if (kcontrol->private_value) {
164 idx = STAC946X_MASTER_VOLUME;
165 id = 0;
166 } else {
167 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
168 idx = id + STAC946X_LF_VOLUME;
169 }
170 if (id < 6)
171 vol = stac9460_get(ice, idx) & 0x7f;
172 else
173 vol = stac9460_2_get(ice, idx - 6) & 0x7f;
174 ucontrol->value.integer.value[0] = 0x7f - vol;
175 return 0;
176}
177
178static int stac9460_dac_vol_put(struct snd_kcontrol *kcontrol,
179 struct snd_ctl_elem_value *ucontrol)
180{
181 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
182 int idx, id;
183 unsigned char tmp, ovol, nvol;
184 int change;
185
186 if (kcontrol->private_value) {
187 idx = STAC946X_MASTER_VOLUME;
188 nvol = ucontrol->value.integer.value[0];
189 tmp = stac9460_get(ice, idx);
190 ovol = 0x7f - (tmp & 0x7f);
191 change = (ovol != nvol);
192 if (change) {
193 stac9460_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
194 stac9460_2_put(ice, idx, (0x7f - nvol) | (tmp & 0x80));
195 }
196 } else {
197 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
198 idx = id + STAC946X_LF_VOLUME;
199 nvol = ucontrol->value.integer.value[0];
200 if (id < 6)
201 tmp = stac9460_get(ice, idx);
202 else
203 tmp = stac9460_2_get(ice, idx - 6);
204 ovol = 0x7f - (tmp & 0x7f);
205 change = (ovol != nvol);
206 if (change) {
207 if (id < 6)
208 stac9460_put(ice, idx, (0x7f - nvol) |
209 (tmp & 0x80));
210 else
211 stac9460_2_put(ice, idx-6, (0x7f - nvol) |
212 (tmp & 0x80));
213 }
214 }
215 return change;
216}
217
218/*
219 * ADC mute control
220 */
221static int stac9460_adc_mute_info(struct snd_kcontrol *kcontrol,
222 struct snd_ctl_elem_info *uinfo)
223{
224 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
225 uinfo->count = 2;
226 uinfo->value.integer.min = 0;
227 uinfo->value.integer.max = 1;
228 return 0;
229}
230
231static int stac9460_adc_mute_get(struct snd_kcontrol *kcontrol,
232 struct snd_ctl_elem_value *ucontrol)
233{
234 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
235 unsigned char val;
236 int i, id;
237
238 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
239 if (id == 0) {
240 for (i = 0; i < 2; ++i) {
241 val = stac9460_get(ice, STAC946X_MIC_L_VOLUME + i);
242 ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
243 }
244 } else {
245 for (i = 0; i < 2; ++i) {
246 val = stac9460_2_get(ice, STAC946X_MIC_L_VOLUME + i);
247 ucontrol->value.integer.value[i] = ~val>>7 & 0x1;
248 }
249 }
250 return 0;
251}
252
253static int stac9460_adc_mute_put(struct snd_kcontrol *kcontrol,
254 struct snd_ctl_elem_value *ucontrol)
255{
256 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
257 unsigned char new, old;
258 int i, reg, id;
259 int change;
260
261 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
262 if (id == 0) {
263 for (i = 0; i < 2; ++i) {
264 reg = STAC946X_MIC_L_VOLUME + i;
265 old = stac9460_get(ice, reg);
266 new = (~ucontrol->value.integer.value[i]<<7&0x80) |
267 (old&~0x80);
268 change = (new != old);
269 if (change)
270 stac9460_put(ice, reg, new);
271 }
272 } else {
273 for (i = 0; i < 2; ++i) {
274 reg = STAC946X_MIC_L_VOLUME + i;
275 old = stac9460_2_get(ice, reg);
276 new = (~ucontrol->value.integer.value[i]<<7&0x80) |
277 (old&~0x80);
278 change = (new != old);
279 if (change)
280 stac9460_2_put(ice, reg, new);
281 }
282 }
283 return change;
284}
285
286/*
287 *ADC gain mixer control
288 */
289static int stac9460_adc_vol_info(struct snd_kcontrol *kcontrol,
290 struct snd_ctl_elem_info *uinfo)
291{
292 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
293 uinfo->count = 2;
294 uinfo->value.integer.min = 0; /* 0dB */
295 uinfo->value.integer.max = 0x0f; /* 22.5dB */
296 return 0;
297}
298
299static int stac9460_adc_vol_get(struct snd_kcontrol *kcontrol,
300 struct snd_ctl_elem_value *ucontrol)
301{
302 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
303 int i, reg, id;
304 unsigned char vol;
305
306 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
307 if (id == 0) {
308 for (i = 0; i < 2; ++i) {
309 reg = STAC946X_MIC_L_VOLUME + i;
310 vol = stac9460_get(ice, reg) & 0x0f;
311 ucontrol->value.integer.value[i] = 0x0f - vol;
312 }
313 } else {
314 for (i = 0; i < 2; ++i) {
315 reg = STAC946X_MIC_L_VOLUME + i;
316 vol = stac9460_2_get(ice, reg) & 0x0f;
317 ucontrol->value.integer.value[i] = 0x0f - vol;
318 }
319 }
320 return 0;
321}
322
323static int stac9460_adc_vol_put(struct snd_kcontrol *kcontrol,
324 struct snd_ctl_elem_value *ucontrol)
325{
326 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
327 int i, reg, id;
328 unsigned char ovol, nvol;
329 int change;
330
331 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
332 if (id == 0) {
333 for (i = 0; i < 2; ++i) {
334 reg = STAC946X_MIC_L_VOLUME + i;
335 nvol = ucontrol->value.integer.value[i];
336 ovol = 0x0f - stac9460_get(ice, reg);
337 change = ((ovol & 0x0f) != nvol);
338 if (change)
339 stac9460_put(ice, reg, (0x0f - nvol) |
340 (ovol & ~0x0f));
341 }
342 } else {
343 for (i = 0; i < 2; ++i) {
344 reg = STAC946X_MIC_L_VOLUME + i;
345 nvol = ucontrol->value.integer.value[i];
346 ovol = 0x0f - stac9460_2_get(ice, reg);
347 change = ((ovol & 0x0f) != nvol);
348 if (change)
349 stac9460_2_put(ice, reg, (0x0f - nvol) |
350 (ovol & ~0x0f));
351 }
352 }
353 return change;
354}
355
356/*
357 * MIC / LINE switch fonction
358 */
359
360static int stac9460_mic_sw_info(struct snd_kcontrol *kcontrol,
361 struct snd_ctl_elem_info *uinfo)
362{
363 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
364 uinfo->count = 1;
365 uinfo->value.integer.min = 0;
366 uinfo->value.integer.max = 1;
367 return 0;
368}
369
370static int stac9460_mic_sw_get(struct snd_kcontrol *kcontrol,
371 struct snd_ctl_elem_value *ucontrol)
372{
373 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
374 unsigned char val;
375 int id;
376
377 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
378 if (id == 0)
379 val = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
380 else
381 val = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
382 ucontrol->value.integer.value[0] = ~val>>7 & 0x1;
383 return 0;
384}
385
386static int stac9460_mic_sw_put(struct snd_kcontrol *kcontrol,
387 struct snd_ctl_elem_value *ucontrol)
388{
389 struct snd_ice1712 *ice = snd_kcontrol_chip(kcontrol);
390 unsigned char new, old;
391 int change, id;
392
393 id = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
394 if (id == 0)
395 old = stac9460_get(ice, STAC946X_GENERAL_PURPOSE);
396 else
397 old = stac9460_2_get(ice, STAC946X_GENERAL_PURPOSE);
398 new = (~ucontrol->value.integer.value[0]<< 7 & 0x80) | (old & ~0x80);
399 change = (new != old);
400 if (change) {
401 if (id == 0)
402 stac9460_put(ice, STAC946X_GENERAL_PURPOSE, new);
403 else
404 stac9460_2_put(ice, STAC946X_GENERAL_PURPOSE, new);
405 }
406 return change;
407}
408
409/*
410 * Control tabs
411 */
412static const struct snd_kcontrol_new stac9640_controls[] __devinitdata = {
413 {
414 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
415 .name = "Master Playback Switch",
416 .info = stac9460_dac_mute_info,
417 .get = stac9460_dac_mute_get,
418 .put = stac9460_dac_mute_put,
419 .private_value = 1
420 },
421 {
422 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
423 .name = "Master Playback Volume",
424 .info = stac9460_dac_vol_info,
425 .get = stac9460_dac_vol_get,
426 .put = stac9460_dac_vol_put,
427 .private_value = 1,
428 },
429 {
430 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
431 .name = "MIC/Line switch",
432 .count = 2,
433 .info = stac9460_mic_sw_info,
434 .get = stac9460_mic_sw_get,
435 .put = stac9460_mic_sw_put,
436
437 },
438 {
439 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
440 .name = "DAC Switch",
441 .count = 8,
442 .info = stac9460_dac_mute_info,
443 .get = stac9460_dac_mute_get,
444 .put = stac9460_dac_mute_put,
445 },
446 {
447 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
448 .name = "DAC Volume",
449 .count = 8,
450 .info = stac9460_dac_vol_info,
451 .get = stac9460_dac_vol_get,
452 .put = stac9460_dac_vol_put,
453 },
454 {
455 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
456 .name = "ADC Switch",
457 .count = 2,
458 .info = stac9460_adc_mute_info,
459 .get = stac9460_adc_mute_get,
460 .put = stac9460_adc_mute_put,
461 },
462 {
463 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
464 .name = "ADC Volume",
465 .count = 2,
466 .info = stac9460_adc_vol_info,
467 .get = stac9460_adc_vol_get,
468 .put = stac9460_adc_vol_put,
469
470 }
471};
472
473
474
475/*INIT*/
476static int __devinit wtm_add_controls(struct snd_ice1712 *ice)
477{
478 unsigned int i;
479 int err;
480
481 for (i = 0; i < ARRAY_SIZE(stac9640_controls); i++) {
482 err = snd_ctl_add(ice->card,
483 snd_ctl_new1(&stac9640_controls[i], ice));
484 if (err < 0)
485 return err;
486 }
487 return 0;
488}
489
490static int __devinit wtm_init(struct snd_ice1712 *ice)
491{
492 static unsigned short stac_inits_prodigy[] = {
493 STAC946X_RESET, 0,
494 (unsigned short)-1
495 };
496 unsigned short *p;
497
498 /*WTM 192M*/
499 ice->num_total_dacs = 8;
500 ice->num_total_adcs = 4;
501 ice->force_rdma1 = 1;
502
503 /*initialize codec*/
504 p = stac_inits_prodigy;
505 for (; *p != (unsigned short)-1; p += 2) {
506 stac9460_put(ice, p[0], p[1]);
507 stac9460_2_put(ice, p[0], p[1]);
508 }
509 return 0;
510}
511
512
513static unsigned char wtm_eeprom[] __devinitdata = {
514 0x47, /*SYSCONF: clock 192KHz, 4ADC, 8DAC */
515 0x80, /* ACLINK : I2S */
516 0xf8, /* I2S: vol; 96k, 24bit, 192k */
517 0xc1 /*SPDIF: out-en, spidf ext out*/,
518 0x9f, /* GPIO_DIR */
519 0xff, /* GPIO_DIR1 */
520 0x7f, /* GPIO_DIR2 */
521 0x9f, /* GPIO_MASK */
522 0xff, /* GPIO_MASK1 */
523 0x7f, /* GPIO_MASK2 */
524 0x16, /* GPIO_STATE */
525 0x80, /* GPIO_STATE1 */
526 0x00, /* GPIO_STATE2 */
527};
528
529
530/*entry point*/
531struct snd_ice1712_card_info snd_vt1724_wtm_cards[] __devinitdata = {
532 {
533 .subvendor = VT1724_SUBDEVICE_WTM,
534 .name = "ESI Waveterminal 192M",
535 .model = "WT192M",
536 .chip_init = wtm_init,
537 .build_controls = wtm_add_controls,
538 .eeprom_size = sizeof(wtm_eeprom),
539 .eeprom_data = wtm_eeprom,
540 },
541 {} /*terminator*/
542};
diff --git a/sound/pci/ice1712/wtm.h b/sound/pci/ice1712/wtm.h
new file mode 100644
index 000000000000..03a394e442f1
--- /dev/null
+++ b/sound/pci/ice1712/wtm.h
@@ -0,0 +1,20 @@
1#ifndef __SOUND_WTM_H
2#define __SOUND_WTM_H
3
4/* ID */
5#define WTM_DEVICE_DESC "{EGO SYS INC,WaveTerminal 192M},"
6#define VT1724_SUBDEVICE_WTM 0x36495345 /* WT192M ver1.0 */
7
8/*
9 *chip addresses on I2C bus
10 */
11
12#define AK4114_ADDR 0x20 /*S/PDIF receiver*/
13#define STAC9460_I2C_ADDR 0x54 /* ADC*2 | DAC*6 */
14#define STAC9460_2_I2C_ADDR 0x56 /* ADC|DAC *2 */
15
16
17extern struct snd_ice1712_card_info snd_vt1724_wtm_cards[];
18
19#endif /* __SOUND_WTM_H */
20
diff --git a/sound/pci/intel8x0.c b/sound/pci/intel8x0.c
index 30aaa6092a84..a289abfc7172 100644
--- a/sound/pci/intel8x0.c
+++ b/sound/pci/intel8x0.c
@@ -71,6 +71,7 @@ static char *ac97_quirk;
71static int buggy_semaphore; 71static int buggy_semaphore;
72static int buggy_irq = -1; /* auto-check */ 72static int buggy_irq = -1; /* auto-check */
73static int xbox; 73static int xbox;
74static int spdif_aclink = -1;
74 75
75module_param(index, int, 0444); 76module_param(index, int, 0444);
76MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard."); 77MODULE_PARM_DESC(index, "Index value for Intel i8x0 soundcard.");
@@ -86,6 +87,8 @@ module_param(buggy_irq, bool, 0444);
86MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards."); 87MODULE_PARM_DESC(buggy_irq, "Enable workaround for buggy interrupts on some motherboards.");
87module_param(xbox, bool, 0444); 88module_param(xbox, bool, 0444);
88MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection."); 89MODULE_PARM_DESC(xbox, "Set to 1 for Xbox, if you have problems with the AC'97 codec detection.");
90module_param(spdif_aclink, int, 0444);
91MODULE_PARM_DESC(spdif_aclink, "S/PDIF over AC-link.");
89 92
90/* just for backward compatibility */ 93/* just for backward compatibility */
91static int enable; 94static int enable;
@@ -368,12 +371,8 @@ struct intel8x0 {
368 371
369 int irq; 372 int irq;
370 373
371 unsigned int mmio; 374 void __iomem *addr;
372 unsigned long addr; 375 void __iomem *bmaddr;
373 void __iomem *remap_addr;
374 unsigned int bm_mmio;
375 unsigned long bmaddr;
376 void __iomem *remap_bmaddr;
377 376
378 struct pci_dev *pci; 377 struct pci_dev *pci;
379 struct snd_card *card; 378 struct snd_card *card;
@@ -446,72 +445,48 @@ MODULE_DEVICE_TABLE(pci, snd_intel8x0_ids);
446 * Lowlevel I/O - busmaster 445 * Lowlevel I/O - busmaster
447 */ 446 */
448 447
449static u8 igetbyte(struct intel8x0 *chip, u32 offset) 448static inline u8 igetbyte(struct intel8x0 *chip, u32 offset)
450{ 449{
451 if (chip->bm_mmio) 450 return ioread8(chip->bmaddr + offset);
452 return readb(chip->remap_bmaddr + offset);
453 else
454 return inb(chip->bmaddr + offset);
455} 451}
456 452
457static u16 igetword(struct intel8x0 *chip, u32 offset) 453static inline u16 igetword(struct intel8x0 *chip, u32 offset)
458{ 454{
459 if (chip->bm_mmio) 455 return ioread16(chip->bmaddr + offset);
460 return readw(chip->remap_bmaddr + offset);
461 else
462 return inw(chip->bmaddr + offset);
463} 456}
464 457
465static u32 igetdword(struct intel8x0 *chip, u32 offset) 458static inline u32 igetdword(struct intel8x0 *chip, u32 offset)
466{ 459{
467 if (chip->bm_mmio) 460 return ioread32(chip->bmaddr + offset);
468 return readl(chip->remap_bmaddr + offset);
469 else
470 return inl(chip->bmaddr + offset);
471} 461}
472 462
473static void iputbyte(struct intel8x0 *chip, u32 offset, u8 val) 463static inline void iputbyte(struct intel8x0 *chip, u32 offset, u8 val)
474{ 464{
475 if (chip->bm_mmio) 465 iowrite8(val, chip->bmaddr + offset);
476 writeb(val, chip->remap_bmaddr + offset);
477 else
478 outb(val, chip->bmaddr + offset);
479} 466}
480 467
481static void iputword(struct intel8x0 *chip, u32 offset, u16 val) 468static inline void iputword(struct intel8x0 *chip, u32 offset, u16 val)
482{ 469{
483 if (chip->bm_mmio) 470 iowrite16(val, chip->bmaddr + offset);
484 writew(val, chip->remap_bmaddr + offset);
485 else
486 outw(val, chip->bmaddr + offset);
487} 471}
488 472
489static void iputdword(struct intel8x0 *chip, u32 offset, u32 val) 473static inline void iputdword(struct intel8x0 *chip, u32 offset, u32 val)
490{ 474{
491 if (chip->bm_mmio) 475 iowrite32(val, chip->bmaddr + offset);
492 writel(val, chip->remap_bmaddr + offset);
493 else
494 outl(val, chip->bmaddr + offset);
495} 476}
496 477
497/* 478/*
498 * Lowlevel I/O - AC'97 registers 479 * Lowlevel I/O - AC'97 registers
499 */ 480 */
500 481
501static u16 iagetword(struct intel8x0 *chip, u32 offset) 482static inline u16 iagetword(struct intel8x0 *chip, u32 offset)
502{ 483{
503 if (chip->mmio) 484 return ioread16(chip->addr + offset);
504 return readw(chip->remap_addr + offset);
505 else
506 return inw(chip->addr + offset);
507} 485}
508 486
509static void iaputword(struct intel8x0 *chip, u32 offset, u16 val) 487static inline void iaputword(struct intel8x0 *chip, u32 offset, u16 val)
510{ 488{
511 if (chip->mmio) 489 iowrite16(val, chip->addr + offset);
512 writew(val, chip->remap_addr + offset);
513 else
514 outw(val, chip->addr + offset);
515} 490}
516 491
517/* 492/*
@@ -1606,10 +1581,14 @@ static int __devinit snd_intel8x0_pcm(struct intel8x0 *chip)
1606 case DEVICE_INTEL_ICH4: 1581 case DEVICE_INTEL_ICH4:
1607 tbl = intel_pcms; 1582 tbl = intel_pcms;
1608 tblsize = ARRAY_SIZE(intel_pcms); 1583 tblsize = ARRAY_SIZE(intel_pcms);
1584 if (spdif_aclink)
1585 tblsize--;
1609 break; 1586 break;
1610 case DEVICE_NFORCE: 1587 case DEVICE_NFORCE:
1611 tbl = nforce_pcms; 1588 tbl = nforce_pcms;
1612 tblsize = ARRAY_SIZE(nforce_pcms); 1589 tblsize = ARRAY_SIZE(nforce_pcms);
1590 if (spdif_aclink)
1591 tblsize--;
1613 break; 1592 break;
1614 case DEVICE_ALI: 1593 case DEVICE_ALI:
1615 tbl = ali_pcms; 1594 tbl = ali_pcms;
@@ -2068,24 +2047,26 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
2068 }; 2047 };
2069 2048
2070 chip->spdif_idx = -1; /* use PCMOUT (or disabled) */ 2049 chip->spdif_idx = -1; /* use PCMOUT (or disabled) */
2071 switch (chip->device_type) { 2050 if (!spdif_aclink) {
2072 case DEVICE_NFORCE: 2051 switch (chip->device_type) {
2073 chip->spdif_idx = NVD_SPBAR; 2052 case DEVICE_NFORCE:
2074 break; 2053 chip->spdif_idx = NVD_SPBAR;
2075 case DEVICE_ALI: 2054 break;
2076 chip->spdif_idx = ALID_AC97SPDIFOUT; 2055 case DEVICE_ALI:
2077 break; 2056 chip->spdif_idx = ALID_AC97SPDIFOUT;
2078 case DEVICE_INTEL_ICH4: 2057 break;
2079 chip->spdif_idx = ICHD_SPBAR; 2058 case DEVICE_INTEL_ICH4:
2080 break; 2059 chip->spdif_idx = ICHD_SPBAR;
2081 }; 2060 break;
2061 };
2062 }
2082 2063
2083 chip->in_ac97_init = 1; 2064 chip->in_ac97_init = 1;
2084 2065
2085 memset(&ac97, 0, sizeof(ac97)); 2066 memset(&ac97, 0, sizeof(ac97));
2086 ac97.private_data = chip; 2067 ac97.private_data = chip;
2087 ac97.private_free = snd_intel8x0_mixer_free_ac97; 2068 ac97.private_free = snd_intel8x0_mixer_free_ac97;
2088 ac97.scaps = AC97_SCAP_SKIP_MODEM; 2069 ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
2089 if (chip->xbox) 2070 if (chip->xbox)
2090 ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR; 2071 ac97.scaps |= AC97_SCAP_DETECT_BY_VENDOR;
2091 if (chip->device_type != DEVICE_ALI) { 2072 if (chip->device_type != DEVICE_ALI) {
@@ -2201,11 +2182,11 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0 *chip, int ac97_clock,
2201 if ((igetdword(chip, ICHREG(GLOB_STA)) & ICH_SAMPLE_CAP) == ICH_SAMPLE_16_20) 2182 if ((igetdword(chip, ICHREG(GLOB_STA)) & ICH_SAMPLE_CAP) == ICH_SAMPLE_16_20)
2202 chip->smp20bit = 1; 2183 chip->smp20bit = 1;
2203 } 2184 }
2204 if (chip->device_type == DEVICE_NFORCE) { 2185 if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) {
2205 /* 48kHz only */ 2186 /* 48kHz only */
2206 chip->ichd[chip->spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000; 2187 chip->ichd[chip->spdif_idx].pcm->rates = SNDRV_PCM_RATE_48000;
2207 } 2188 }
2208 if (chip->device_type == DEVICE_INTEL_ICH4) { 2189 if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) {
2209 /* use slot 10/11 for SPDIF */ 2190 /* use slot 10/11 for SPDIF */
2210 u32 val; 2191 u32 val;
2211 val = igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK; 2192 val = igetdword(chip, ICHREG(GLOB_CNT)) & ~ICH_PCM_SPDIF_MASK;
@@ -2333,7 +2314,7 @@ static int snd_intel8x0_ich_chip_init(struct intel8x0 *chip, int probing)
2333 /* unmute the output on SIS7012 */ 2314 /* unmute the output on SIS7012 */
2334 iputword(chip, 0x4c, igetword(chip, 0x4c) | 1); 2315 iputword(chip, 0x4c, igetword(chip, 0x4c) | 1);
2335 } 2316 }
2336 if (chip->device_type == DEVICE_NFORCE) { 2317 if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) {
2337 /* enable SPDIF interrupt */ 2318 /* enable SPDIF interrupt */
2338 unsigned int val; 2319 unsigned int val;
2339 pci_read_config_dword(chip->pci, 0x4c, &val); 2320 pci_read_config_dword(chip->pci, 0x4c, &val);
@@ -2426,7 +2407,7 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
2426 /* reset channels */ 2407 /* reset channels */
2427 for (i = 0; i < chip->bdbars_count; i++) 2408 for (i = 0; i < chip->bdbars_count; i++)
2428 iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS); 2409 iputbyte(chip, ICH_REG_OFF_CR + chip->ichd[i].reg_offset, ICH_RESETREGS);
2429 if (chip->device_type == DEVICE_NFORCE) { 2410 if (chip->device_type == DEVICE_NFORCE && !spdif_aclink) {
2430 /* stop the spdif interrupt */ 2411 /* stop the spdif interrupt */
2431 unsigned int val; 2412 unsigned int val;
2432 pci_read_config_dword(chip->pci, 0x4c, &val); 2413 pci_read_config_dword(chip->pci, 0x4c, &val);
@@ -2443,10 +2424,10 @@ static int snd_intel8x0_free(struct intel8x0 *chip)
2443 fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0); 2424 fill_nocache(chip->bdbars.area, chip->bdbars.bytes, 0);
2444 snd_dma_free_pages(&chip->bdbars); 2425 snd_dma_free_pages(&chip->bdbars);
2445 } 2426 }
2446 if (chip->remap_addr) 2427 if (chip->addr)
2447 iounmap(chip->remap_addr); 2428 pci_iounmap(chip->pci, chip->addr);
2448 if (chip->remap_bmaddr) 2429 if (chip->bmaddr)
2449 iounmap(chip->remap_bmaddr); 2430 pci_iounmap(chip->pci, chip->bmaddr);
2450 pci_release_regions(chip->pci); 2431 pci_release_regions(chip->pci);
2451 pci_disable_device(chip->pci); 2432 pci_disable_device(chip->pci);
2452 kfree(chip); 2433 kfree(chip);
@@ -2520,7 +2501,7 @@ static int intel8x0_resume(struct pci_dev *pci)
2520 snd_intel8x0_chip_init(chip, 0); 2501 snd_intel8x0_chip_init(chip, 0);
2521 2502
2522 /* re-initialize mixer stuff */ 2503 /* re-initialize mixer stuff */
2523 if (chip->device_type == DEVICE_INTEL_ICH4) { 2504 if (chip->device_type == DEVICE_INTEL_ICH4 && !spdif_aclink) {
2524 /* enable separate SDINs for ICH4 */ 2505 /* enable separate SDINs for ICH4 */
2525 iputbyte(chip, ICHREG(SDM), chip->sdm_saved); 2506 iputbyte(chip, ICHREG(SDM), chip->sdm_saved);
2526 /* use slot 10/11 for SPDIF */ 2507 /* use slot 10/11 for SPDIF */
@@ -2793,35 +2774,27 @@ static int __devinit snd_intel8x0_create(struct snd_card *card,
2793 2774
2794 if (device_type == DEVICE_ALI) { 2775 if (device_type == DEVICE_ALI) {
2795 /* ALI5455 has no ac97 region */ 2776 /* ALI5455 has no ac97 region */
2796 chip->bmaddr = pci_resource_start(pci, 0); 2777 chip->bmaddr = pci_iomap(pci, 0, 0);
2797 goto port_inited; 2778 goto port_inited;
2798 } 2779 }
2799 2780
2800 if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) { /* ICH4 and Nforce */ 2781 if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
2801 chip->mmio = 1; 2782 chip->addr = pci_iomap(pci, 2, 0);
2802 chip->addr = pci_resource_start(pci, 2); 2783 else
2803 chip->remap_addr = ioremap_nocache(chip->addr, 2784 chip->addr = pci_iomap(pci, 0, 0);
2804 pci_resource_len(pci, 2)); 2785 if (!chip->addr) {
2805 if (chip->remap_addr == NULL) { 2786 snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
2806 snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); 2787 snd_intel8x0_free(chip);
2807 snd_intel8x0_free(chip); 2788 return -EIO;
2808 return -EIO; 2789 }
2809 } 2790 if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
2810 } else { 2791 chip->bmaddr = pci_iomap(pci, 3, 0);
2811 chip->addr = pci_resource_start(pci, 0); 2792 else
2812 } 2793 chip->bmaddr = pci_iomap(pci, 1, 0);
2813 if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) { /* ICH4 */ 2794 if (!chip->bmaddr) {
2814 chip->bm_mmio = 1; 2795 snd_printk(KERN_ERR "Controller space ioremap problem\n");
2815 chip->bmaddr = pci_resource_start(pci, 3); 2796 snd_intel8x0_free(chip);
2816 chip->remap_bmaddr = ioremap_nocache(chip->bmaddr, 2797 return -EIO;
2817 pci_resource_len(pci, 3));
2818 if (chip->remap_bmaddr == NULL) {
2819 snd_printk(KERN_ERR "Controller space ioremap problem\n");
2820 snd_intel8x0_free(chip);
2821 return -EIO;
2822 }
2823 } else {
2824 chip->bmaddr = pci_resource_start(pci, 1);
2825 } 2798 }
2826 2799
2827 port_inited: 2800 port_inited:
@@ -2964,6 +2937,29 @@ static struct shortname_table {
2964 { 0, NULL }, 2937 { 0, NULL },
2965}; 2938};
2966 2939
2940static struct snd_pci_quirk spdif_aclink_defaults[] __devinitdata = {
2941 SND_PCI_QUIRK(0x147b, 0x1c1a, "ASUS KN8", 1),
2942 { } /* end */
2943};
2944
2945/* look up white/black list for SPDIF over ac-link */
2946static int __devinit check_default_spdif_aclink(struct pci_dev *pci)
2947{
2948 const struct snd_pci_quirk *w;
2949
2950 w = snd_pci_quirk_lookup(pci, spdif_aclink_defaults);
2951 if (w) {
2952 if (w->value)
2953 snd_printdd(KERN_INFO "intel8x0: Using SPDIF over "
2954 "AC-Link for %s\n", w->name);
2955 else
2956 snd_printdd(KERN_INFO "intel8x0: Using integrated "
2957 "SPDIF DMA for %s\n", w->name);
2958 return w->value;
2959 }
2960 return 0;
2961}
2962
2967static int __devinit snd_intel8x0_probe(struct pci_dev *pci, 2963static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
2968 const struct pci_device_id *pci_id) 2964 const struct pci_device_id *pci_id)
2969{ 2965{
@@ -2976,16 +2972,18 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
2976 if (card == NULL) 2972 if (card == NULL)
2977 return -ENOMEM; 2973 return -ENOMEM;
2978 2974
2979 switch (pci_id->driver_data) { 2975 if (spdif_aclink < 0)
2980 case DEVICE_NFORCE: 2976 spdif_aclink = check_default_spdif_aclink(pci);
2981 strcpy(card->driver, "NFORCE"); 2977
2982 break; 2978 strcpy(card->driver, "ICH");
2983 case DEVICE_INTEL_ICH4: 2979 if (!spdif_aclink) {
2984 strcpy(card->driver, "ICH4"); 2980 switch (pci_id->driver_data) {
2985 break; 2981 case DEVICE_NFORCE:
2986 default: 2982 strcpy(card->driver, "NFORCE");
2987 strcpy(card->driver, "ICH"); 2983 break;
2988 break; 2984 case DEVICE_INTEL_ICH4:
2985 strcpy(card->driver, "ICH4");
2986 }
2989 } 2987 }
2990 2988
2991 strcpy(card->shortname, "Intel ICH"); 2989 strcpy(card->shortname, "Intel ICH");
@@ -3025,8 +3023,8 @@ static int __devinit snd_intel8x0_probe(struct pci_dev *pci,
3025 snd_intel8x0_proc_init(chip); 3023 snd_intel8x0_proc_init(chip);
3026 3024
3027 snprintf(card->longname, sizeof(card->longname), 3025 snprintf(card->longname, sizeof(card->longname),
3028 "%s with %s at %#lx, irq %i", card->shortname, 3026 "%s with %s at irq %i", card->shortname,
3029 snd_ac97_get_short_name(chip->ac97[0]), chip->addr, chip->irq); 3027 snd_ac97_get_short_name(chip->ac97[0]), chip->irq);
3030 3028
3031 if (! ac97_clock) 3029 if (! ac97_clock)
3032 intel8x0_measure_ac97_clock(chip); 3030 intel8x0_measure_ac97_clock(chip);
diff --git a/sound/pci/intel8x0m.c b/sound/pci/intel8x0m.c
index 09dcf923b547..c155e1f3a0e5 100644
--- a/sound/pci/intel8x0m.c
+++ b/sound/pci/intel8x0m.c
@@ -196,12 +196,8 @@ struct intel8x0m {
196 196
197 int irq; 197 int irq;
198 198
199 unsigned int mmio; 199 void __iomem *addr;
200 unsigned long addr; 200 void __iomem *bmaddr;
201 void __iomem *remap_addr;
202 unsigned int bm_mmio;
203 unsigned long bmaddr;
204 void __iomem *remap_bmaddr;
205 201
206 struct pci_dev *pci; 202 struct pci_dev *pci;
207 struct snd_card *card; 203 struct snd_card *card;
@@ -253,72 +249,48 @@ MODULE_DEVICE_TABLE(pci, snd_intel8x0m_ids);
253 * Lowlevel I/O - busmaster 249 * Lowlevel I/O - busmaster
254 */ 250 */
255 251
256static u8 igetbyte(struct intel8x0m *chip, u32 offset) 252static inline u8 igetbyte(struct intel8x0m *chip, u32 offset)
257{ 253{
258 if (chip->bm_mmio) 254 return ioread8(chip->bmaddr + offset);
259 return readb(chip->remap_bmaddr + offset);
260 else
261 return inb(chip->bmaddr + offset);
262} 255}
263 256
264static u16 igetword(struct intel8x0m *chip, u32 offset) 257static inline u16 igetword(struct intel8x0m *chip, u32 offset)
265{ 258{
266 if (chip->bm_mmio) 259 return ioread16(chip->bmaddr + offset);
267 return readw(chip->remap_bmaddr + offset);
268 else
269 return inw(chip->bmaddr + offset);
270} 260}
271 261
272static u32 igetdword(struct intel8x0m *chip, u32 offset) 262static inline u32 igetdword(struct intel8x0m *chip, u32 offset)
273{ 263{
274 if (chip->bm_mmio) 264 return ioread32(chip->bmaddr + offset);
275 return readl(chip->remap_bmaddr + offset);
276 else
277 return inl(chip->bmaddr + offset);
278} 265}
279 266
280static void iputbyte(struct intel8x0m *chip, u32 offset, u8 val) 267static inline void iputbyte(struct intel8x0m *chip, u32 offset, u8 val)
281{ 268{
282 if (chip->bm_mmio) 269 iowrite8(val, chip->bmaddr + offset);
283 writeb(val, chip->remap_bmaddr + offset);
284 else
285 outb(val, chip->bmaddr + offset);
286} 270}
287 271
288static void iputword(struct intel8x0m *chip, u32 offset, u16 val) 272static inline void iputword(struct intel8x0m *chip, u32 offset, u16 val)
289{ 273{
290 if (chip->bm_mmio) 274 iowrite16(val, chip->bmaddr + offset);
291 writew(val, chip->remap_bmaddr + offset);
292 else
293 outw(val, chip->bmaddr + offset);
294} 275}
295 276
296static void iputdword(struct intel8x0m *chip, u32 offset, u32 val) 277static inline void iputdword(struct intel8x0m *chip, u32 offset, u32 val)
297{ 278{
298 if (chip->bm_mmio) 279 iowrite32(val, chip->bmaddr + offset);
299 writel(val, chip->remap_bmaddr + offset);
300 else
301 outl(val, chip->bmaddr + offset);
302} 280}
303 281
304/* 282/*
305 * Lowlevel I/O - AC'97 registers 283 * Lowlevel I/O - AC'97 registers
306 */ 284 */
307 285
308static u16 iagetword(struct intel8x0m *chip, u32 offset) 286static inline u16 iagetword(struct intel8x0m *chip, u32 offset)
309{ 287{
310 if (chip->mmio) 288 return ioread16(chip->addr + offset);
311 return readw(chip->remap_addr + offset);
312 else
313 return inw(chip->addr + offset);
314} 289}
315 290
316static void iaputword(struct intel8x0m *chip, u32 offset, u16 val) 291static inline void iaputword(struct intel8x0m *chip, u32 offset, u16 val)
317{ 292{
318 if (chip->mmio) 293 iowrite16(val, chip->addr + offset);
319 writew(val, chip->remap_addr + offset);
320 else
321 outw(val, chip->addr + offset);
322} 294}
323 295
324/* 296/*
@@ -858,7 +830,7 @@ static int __devinit snd_intel8x0_mixer(struct intel8x0m *chip, int ac97_clock)
858 memset(&ac97, 0, sizeof(ac97)); 830 memset(&ac97, 0, sizeof(ac97));
859 ac97.private_data = chip; 831 ac97.private_data = chip;
860 ac97.private_free = snd_intel8x0_mixer_free_ac97; 832 ac97.private_free = snd_intel8x0_mixer_free_ac97;
861 ac97.scaps = AC97_SCAP_SKIP_AUDIO; 833 ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
862 834
863 glob_sta = igetdword(chip, ICHREG(GLOB_STA)); 835 glob_sta = igetdword(chip, ICHREG(GLOB_STA));
864 836
@@ -1019,10 +991,10 @@ static int snd_intel8x0_free(struct intel8x0m *chip)
1019 __hw_end: 991 __hw_end:
1020 if (chip->bdbars.area) 992 if (chip->bdbars.area)
1021 snd_dma_free_pages(&chip->bdbars); 993 snd_dma_free_pages(&chip->bdbars);
1022 if (chip->remap_addr) 994 if (chip->addr)
1023 iounmap(chip->remap_addr); 995 pci_iounmap(chip->pci, chip->addr);
1024 if (chip->remap_bmaddr) 996 if (chip->bmaddr)
1025 iounmap(chip->remap_bmaddr); 997 pci_iounmap(chip->pci, chip->bmaddr);
1026 if (chip->irq >= 0) 998 if (chip->irq >= 0)
1027 free_irq(chip->irq, chip); 999 free_irq(chip->irq, chip);
1028 pci_release_regions(chip->pci); 1000 pci_release_regions(chip->pci);
@@ -1173,35 +1145,27 @@ static int __devinit snd_intel8x0m_create(struct snd_card *card,
1173 1145
1174 if (device_type == DEVICE_ALI) { 1146 if (device_type == DEVICE_ALI) {
1175 /* ALI5455 has no ac97 region */ 1147 /* ALI5455 has no ac97 region */
1176 chip->bmaddr = pci_resource_start(pci, 0); 1148 chip->bmaddr = pci_iomap(pci, 0, 0);
1177 goto port_inited; 1149 goto port_inited;
1178 } 1150 }
1179 1151
1180 if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) { /* ICH4 and Nforce */ 1152 if (pci_resource_flags(pci, 2) & IORESOURCE_MEM) /* ICH4 and Nforce */
1181 chip->mmio = 1; 1153 chip->addr = pci_iomap(pci, 2, 0);
1182 chip->addr = pci_resource_start(pci, 2); 1154 else
1183 chip->remap_addr = ioremap_nocache(chip->addr, 1155 chip->addr = pci_iomap(pci, 0, 0);
1184 pci_resource_len(pci, 2)); 1156 if (!chip->addr) {
1185 if (chip->remap_addr == NULL) { 1157 snd_printk(KERN_ERR "AC'97 space ioremap problem\n");
1186 snd_printk(KERN_ERR "AC'97 space ioremap problem\n"); 1158 snd_intel8x0_free(chip);
1187 snd_intel8x0_free(chip); 1159 return -EIO;
1188 return -EIO;
1189 }
1190 } else {
1191 chip->addr = pci_resource_start(pci, 0);
1192 } 1160 }
1193 if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) { /* ICH4 */ 1161 if (pci_resource_flags(pci, 3) & IORESOURCE_MEM) /* ICH4 */
1194 chip->bm_mmio = 1; 1162 chip->bmaddr = pci_iomap(pci, 3, 0);
1195 chip->bmaddr = pci_resource_start(pci, 3); 1163 else
1196 chip->remap_bmaddr = ioremap_nocache(chip->bmaddr, 1164 chip->bmaddr = pci_iomap(pci, 1, 0);
1197 pci_resource_len(pci, 3)); 1165 if (!chip->bmaddr) {
1198 if (chip->remap_bmaddr == NULL) { 1166 snd_printk(KERN_ERR "Controller space ioremap problem\n");
1199 snd_printk(KERN_ERR "Controller space ioremap problem\n"); 1167 snd_intel8x0_free(chip);
1200 snd_intel8x0_free(chip); 1168 return -EIO;
1201 return -EIO;
1202 }
1203 } else {
1204 chip->bmaddr = pci_resource_start(pci, 1);
1205 } 1169 }
1206 1170
1207 port_inited: 1171 port_inited:
@@ -1339,8 +1303,8 @@ static int __devinit snd_intel8x0m_probe(struct pci_dev *pci,
1339 1303
1340 snd_intel8x0m_proc_init(chip); 1304 snd_intel8x0m_proc_init(chip);
1341 1305
1342 sprintf(card->longname, "%s at 0x%lx, irq %i", 1306 sprintf(card->longname, "%s at irq %i",
1343 card->shortname, chip->addr, chip->irq); 1307 card->shortname, chip->irq);
1344 1308
1345 if ((err = snd_card_register(card)) < 0) { 1309 if ((err = snd_card_register(card)) < 0) {
1346 snd_card_free(card); 1310 snd_card_free(card);
diff --git a/sound/pci/korg1212/korg1212.c b/sound/pci/korg1212/korg1212.c
index 345eefeedb39..21d0899ac382 100644
--- a/sound/pci/korg1212/korg1212.c
+++ b/sound/pci/korg1212/korg1212.c
@@ -28,6 +28,7 @@
28#include <linux/wait.h> 28#include <linux/wait.h>
29#include <linux/moduleparam.h> 29#include <linux/moduleparam.h>
30#include <linux/mutex.h> 30#include <linux/mutex.h>
31#include <linux/firmware.h>
31 32
32#include <sound/core.h> 33#include <sound/core.h>
33#include <sound/info.h> 34#include <sound/info.h>
@@ -263,7 +264,15 @@ enum MonitorModeSelector {
263#define COMMAND_ACK_DELAY 13 // number of RTC ticks to wait for an acknowledgement 264#define COMMAND_ACK_DELAY 13 // number of RTC ticks to wait for an acknowledgement
264 // from the card after sending a command. 265 // from the card after sending a command.
265 266
267#define FIRMWARE_IN_THE_KERNEL
268
269#ifdef FIRMWARE_IN_THE_KERNEL
266#include "korg1212-firmware.h" 270#include "korg1212-firmware.h"
271static const struct firmware static_dsp_code = {
272 .data = (u8 *)dspCode,
273 .size = sizeof dspCode
274};
275#endif
267 276
268enum ClockSourceIndex { 277enum ClockSourceIndex {
269 K1212_CLKIDX_AdatAt44_1K = 0, // selects source as ADAT at 44.1 kHz 278 K1212_CLKIDX_AdatAt44_1K = 0, // selects source as ADAT at 44.1 kHz
@@ -345,8 +354,6 @@ struct snd_korg1212 {
345 struct snd_dma_buffer dma_rec; 354 struct snd_dma_buffer dma_rec;
346 struct snd_dma_buffer dma_shared; 355 struct snd_dma_buffer dma_shared;
347 356
348 u32 dspCodeSize;
349
350 u32 DataBufsSize; 357 u32 DataBufsSize;
351 358
352 struct KorgAudioBuffer * playDataBufsPtr; 359 struct KorgAudioBuffer * playDataBufsPtr;
@@ -1223,8 +1230,6 @@ static int snd_korg1212_downloadDSPCode(struct snd_korg1212 *korg1212)
1223 1230
1224 snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS); 1231 snd_korg1212_setCardState(korg1212, K1212_STATE_DSP_IN_PROCESS);
1225 1232
1226 memcpy(korg1212->dma_dsp.area, dspCode, korg1212->dspCodeSize);
1227
1228 rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload, 1233 rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_StartDSPDownload,
1229 UpperWordSwap(korg1212->dma_dsp.addr), 1234 UpperWordSwap(korg1212->dma_dsp.addr),
1230 0, 0, 0); 1235 0, 0, 0);
@@ -2156,6 +2161,7 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
2156 unsigned int i; 2161 unsigned int i;
2157 unsigned ioport_size, iomem_size, iomem2_size; 2162 unsigned ioport_size, iomem_size, iomem2_size;
2158 struct snd_korg1212 * korg1212; 2163 struct snd_korg1212 * korg1212;
2164 const struct firmware *dsp_code;
2159 2165
2160 static struct snd_device_ops ops = { 2166 static struct snd_device_ops ops = {
2161 .dev_free = snd_korg1212_dev_free, 2167 .dev_free = snd_korg1212_dev_free,
@@ -2329,8 +2335,6 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
2329 2335
2330#endif // K1212_LARGEALLOC 2336#endif // K1212_LARGEALLOC
2331 2337
2332 korg1212->dspCodeSize = sizeof (dspCode);
2333
2334 korg1212->VolumeTablePhy = korg1212->sharedBufferPhy + 2338 korg1212->VolumeTablePhy = korg1212->sharedBufferPhy +
2335 offsetof(struct KorgSharedBuffer, volumeData); 2339 offsetof(struct KorgSharedBuffer, volumeData);
2336 korg1212->RoutingTablePhy = korg1212->sharedBufferPhy + 2340 korg1212->RoutingTablePhy = korg1212->sharedBufferPhy +
@@ -2338,17 +2342,40 @@ static int __devinit snd_korg1212_create(struct snd_card *card, struct pci_dev *
2338 korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy + 2342 korg1212->AdatTimeCodePhy = korg1212->sharedBufferPhy +
2339 offsetof(struct KorgSharedBuffer, AdatTimeCode); 2343 offsetof(struct KorgSharedBuffer, AdatTimeCode);
2340 2344
2345 err = request_firmware(&dsp_code, "korg/k1212.dsp", &pci->dev);
2346 if (err < 0) {
2347 release_firmware(dsp_code);
2348#ifdef FIRMWARE_IN_THE_KERNEL
2349 dsp_code = &static_dsp_code;
2350#else
2351 snd_printk(KERN_ERR "firmware not available\n");
2352 snd_korg1212_free(korg1212);
2353 return err;
2354#endif
2355 }
2356
2341 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 2357 if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
2342 korg1212->dspCodeSize, &korg1212->dma_dsp) < 0) { 2358 dsp_code->size, &korg1212->dma_dsp) < 0) {
2343 snd_printk(KERN_ERR "korg1212: can not allocate dsp code memory (%d bytes)\n", korg1212->dspCodeSize); 2359 snd_printk(KERN_ERR "korg1212: cannot allocate dsp code memory (%zd bytes)\n", dsp_code->size);
2344 snd_korg1212_free(korg1212); 2360 snd_korg1212_free(korg1212);
2361#ifdef FIRMWARE_IN_THE_KERNEL
2362 if (dsp_code != &static_dsp_code)
2363#endif
2364 release_firmware(dsp_code);
2345 return -ENOMEM; 2365 return -ENOMEM;
2346 } 2366 }
2347 2367
2348 K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n", 2368 K1212_DEBUG_PRINTK("K1212_DEBUG: DSP Code area = 0x%p (0x%08x) %d bytes [%s]\n",
2349 korg1212->dma_dsp.area, korg1212->dma_dsp.addr, korg1212->dspCodeSize, 2369 korg1212->dma_dsp.area, korg1212->dma_dsp.addr, dsp_code->size,
2350 stateName[korg1212->cardState]); 2370 stateName[korg1212->cardState]);
2351 2371
2372 memcpy(korg1212->dma_dsp.area, dsp_code->data, dsp_code->size);
2373
2374#ifdef FIRMWARE_IN_THE_KERNEL
2375 if (dsp_code != &static_dsp_code)
2376#endif
2377 release_firmware(dsp_code);
2378
2352 rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0); 2379 rc = snd_korg1212_Send1212Command(korg1212, K1212_DB_RebootCard, 0, 0, 0, 0);
2353 2380
2354 if (rc) 2381 if (rc)
diff --git a/sound/pci/maestro3.c b/sound/pci/maestro3.c
index 6efe6d5ade1e..4526904e3f86 100644
--- a/sound/pci/maestro3.c
+++ b/sound/pci/maestro3.c
@@ -41,6 +41,7 @@
41#include <linux/slab.h> 41#include <linux/slab.h>
42#include <linux/vmalloc.h> 42#include <linux/vmalloc.h>
43#include <linux/moduleparam.h> 43#include <linux/moduleparam.h>
44#include <linux/firmware.h>
44#include <sound/core.h> 45#include <sound/core.h>
45#include <sound/info.h> 46#include <sound/info.h>
46#include <sound/control.h> 47#include <sound/control.h>
@@ -48,6 +49,7 @@
48#include <sound/mpu401.h> 49#include <sound/mpu401.h>
49#include <sound/ac97_codec.h> 50#include <sound/ac97_codec.h>
50#include <sound/initval.h> 51#include <sound/initval.h>
52#include <asm/byteorder.h>
51 53
52MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Takashi Iwai <tiwai@suse.de>"); 54MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Takashi Iwai <tiwai@suse.de>");
53MODULE_DESCRIPTION("ESS Maestro3 PCI"); 55MODULE_DESCRIPTION("ESS Maestro3 PCI");
@@ -768,21 +770,6 @@ MODULE_PARM_DESC(amp_gpio, "GPIO pin number for external amp. (default = -1)");
768/* 770/*
769 */ 771 */
770 772
771/* quirk lists */
772struct m3_quirk {
773 const char *name; /* device name */
774 u16 vendor, device; /* subsystem ids */
775 int amp_gpio; /* gpio pin # for external amp, -1 = default */
776 int irda_workaround; /* non-zero if avoid to touch 0x10 on GPIO_DIRECTION
777 (e.g. for IrDA on Dell Inspirons) */
778};
779
780struct m3_hv_quirk {
781 u16 vendor, device, subsystem_vendor, subsystem_device;
782 u32 config; /* ALLEGRO_CONFIG hardware volume bits */
783 int is_omnibook; /* Do HP OmniBook GPIO magic? */
784};
785
786struct m3_list { 773struct m3_list {
787 int curlen; 774 int curlen;
788 int mem_addr; 775 int mem_addr;
@@ -830,8 +817,6 @@ struct snd_m3 {
830 struct snd_pcm *pcm; 817 struct snd_pcm *pcm;
831 818
832 struct pci_dev *pci; 819 struct pci_dev *pci;
833 const struct m3_quirk *quirk;
834 const struct m3_hv_quirk *hv_quirk;
835 820
836 int dacs_active; 821 int dacs_active;
837 int timer_users; 822 int timer_users;
@@ -845,7 +830,11 @@ struct snd_m3 {
845 u8 reset_state; 830 u8 reset_state;
846 831
847 int external_amp; 832 int external_amp;
848 int amp_gpio; 833 int amp_gpio; /* gpio pin # for external amp, -1 = default */
834 unsigned int hv_config; /* hardware-volume config bits */
835 unsigned irda_workaround :1; /* avoid to touch 0x10 on GPIO_DIRECTION
836 (e.g. for IrDA on Dell Inspirons) */
837 unsigned is_omnibook :1; /* Do HP OmniBook GPIO magic? */
849 838
850 /* midi */ 839 /* midi */
851 struct snd_rawmidi *rmidi; 840 struct snd_rawmidi *rmidi;
@@ -864,6 +853,9 @@ struct snd_m3 {
864#ifdef CONFIG_PM 853#ifdef CONFIG_PM
865 u16 *suspend_mem; 854 u16 *suspend_mem;
866#endif 855#endif
856
857 const struct firmware *assp_kernel_image;
858 const struct firmware *assp_minisrc_image;
867}; 859};
868 860
869/* 861/*
@@ -891,127 +883,104 @@ static struct pci_device_id snd_m3_ids[] = {
891 883
892MODULE_DEVICE_TABLE(pci, snd_m3_ids); 884MODULE_DEVICE_TABLE(pci, snd_m3_ids);
893 885
894static const struct m3_quirk m3_quirk_list[] = { 886static struct snd_pci_quirk m3_amp_quirk_list[] __devinitdata = {
895 /* panasonic CF-28 "toughbook" */ 887 SND_PCI_QUIRK(0x10f7, 0x833e, "Panasonic CF-28", 0x0d),
896 { 888 SND_PCI_QUIRK(0x10f7, 0x833d, "Panasonic CF-72", 0x0d),
897 .name = "Panasonic CF-28", 889 SND_PCI_QUIRK(0x1033, 0x80f1, "NEC LM800J/7", 0x03),
898 .vendor = 0x10f7, 890 SND_PCI_QUIRK(0x1509, 0x1740, "LEGEND ZhaoYang 3100CF", 0x03),
899 .device = 0x833e, 891 { } /* END */
900 .amp_gpio = 0x0d,
901 },
902 /* panasonic CF-72 "toughbook" */
903 {
904 .name = "Panasonic CF-72",
905 .vendor = 0x10f7,
906 .device = 0x833d,
907 .amp_gpio = 0x0d,
908 },
909 /* Dell Inspiron 4000 */
910 {
911 .name = "Dell Inspiron 4000",
912 .vendor = 0x1028,
913 .device = 0x00b0,
914 .amp_gpio = -1,
915 .irda_workaround = 1,
916 },
917 /* Dell Inspiron 8000 */
918 {
919 .name = "Dell Inspiron 8000",
920 .vendor = 0x1028,
921 .device = 0x00a4,
922 .amp_gpio = -1,
923 .irda_workaround = 1,
924 },
925 /* Dell Inspiron 8100 */
926 {
927 .name = "Dell Inspiron 8100",
928 .vendor = 0x1028,
929 .device = 0x00e6,
930 .amp_gpio = -1,
931 .irda_workaround = 1,
932 },
933 /* NEC LM800J/7 */
934 {
935 .name = "NEC LM800J/7",
936 .vendor = 0x1033,
937 .device = 0x80f1,
938 .amp_gpio = 0x03,
939 },
940 /* LEGEND ZhaoYang 3100CF */
941 {
942 .name = "LEGEND ZhaoYang 3100CF",
943 .vendor = 0x1509,
944 .device = 0x1740,
945 .amp_gpio = 0x03,
946 },
947 /* END */
948 { NULL }
949}; 892};
950 893
951/* These values came from the Windows driver. */ 894static struct snd_pci_quirk m3_irda_quirk_list[] __devinitdata = {
952static const struct m3_hv_quirk m3_hv_quirk_list[] = { 895 SND_PCI_QUIRK(0x1028, 0x00b0, "Dell Inspiron 4000", 1),
896 SND_PCI_QUIRK(0x1028, 0x00a4, "Dell Inspiron 8000", 1),
897 SND_PCI_QUIRK(0x1028, 0x00e6, "Dell Inspiron 8100", 1),
898 { } /* END */
899};
900
901/* hardware volume quirks */
902static struct snd_pci_quirk m3_hv_quirk_list[] __devinitdata = {
953 /* Allegro chips */ 903 /* Allegro chips */
954 { 0x125D, 0x1988, 0x0E11, 0x002E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 904 SND_PCI_QUIRK(0x0E11, 0x002E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
955 { 0x125D, 0x1988, 0x0E11, 0x0094, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 905 SND_PCI_QUIRK(0x0E11, 0x0094, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
956 { 0x125D, 0x1988, 0x0E11, 0xB112, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 906 SND_PCI_QUIRK(0x0E11, 0xB112, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
957 { 0x125D, 0x1988, 0x0E11, 0xB114, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 907 SND_PCI_QUIRK(0x0E11, 0xB114, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
958 { 0x125D, 0x1988, 0x103C, 0x0012, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 908 SND_PCI_QUIRK(0x103C, 0x0012, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
959 { 0x125D, 0x1988, 0x103C, 0x0018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 909 SND_PCI_QUIRK(0x103C, 0x0018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
960 { 0x125D, 0x1988, 0x103C, 0x001C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 910 SND_PCI_QUIRK(0x103C, 0x001C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
961 { 0x125D, 0x1988, 0x103C, 0x001D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 911 SND_PCI_QUIRK(0x103C, 0x001D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
962 { 0x125D, 0x1988, 0x103C, 0x001E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 912 SND_PCI_QUIRK(0x103C, 0x001E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
963 { 0x125D, 0x1988, 0x107B, 0x3350, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 913 SND_PCI_QUIRK(0x107B, 0x3350, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
964 { 0x125D, 0x1988, 0x10F7, 0x8338, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 914 SND_PCI_QUIRK(0x10F7, 0x8338, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
965 { 0x125D, 0x1988, 0x10F7, 0x833C, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 915 SND_PCI_QUIRK(0x10F7, 0x833C, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
966 { 0x125D, 0x1988, 0x10F7, 0x833D, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 916 SND_PCI_QUIRK(0x10F7, 0x833D, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
967 { 0x125D, 0x1988, 0x10F7, 0x833E, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 917 SND_PCI_QUIRK(0x10F7, 0x833E, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
968 { 0x125D, 0x1988, 0x10F7, 0x833F, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 918 SND_PCI_QUIRK(0x10F7, 0x833F, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
969 { 0x125D, 0x1988, 0x13BD, 0x1018, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 919 SND_PCI_QUIRK(0x13BD, 0x1018, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
970 { 0x125D, 0x1988, 0x13BD, 0x1019, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 920 SND_PCI_QUIRK(0x13BD, 0x1019, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
971 { 0x125D, 0x1988, 0x13BD, 0x101A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 921 SND_PCI_QUIRK(0x13BD, 0x101A, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
972 { 0x125D, 0x1988, 0x14FF, 0x0F03, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 922 SND_PCI_QUIRK(0x14FF, 0x0F03, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
973 { 0x125D, 0x1988, 0x14FF, 0x0F04, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 923 SND_PCI_QUIRK(0x14FF, 0x0F04, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
974 { 0x125D, 0x1988, 0x14FF, 0x0F05, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 924 SND_PCI_QUIRK(0x14FF, 0x0F05, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
975 { 0x125D, 0x1988, 0x156D, 0xB400, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 925 SND_PCI_QUIRK(0x156D, 0xB400, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
976 { 0x125D, 0x1988, 0x156D, 0xB795, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 926 SND_PCI_QUIRK(0x156D, 0xB795, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
977 { 0x125D, 0x1988, 0x156D, 0xB797, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 927 SND_PCI_QUIRK(0x156D, 0xB797, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
978 { 0x125D, 0x1988, 0x156D, 0xC700, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD, 0 }, 928 SND_PCI_QUIRK(0x156D, 0xC700, NULL, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD),
979 { 0x125D, 0x1988, 0x1033, 0x80F1, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 929 SND_PCI_QUIRK(0x1033, 0x80F1, NULL,
980 { 0x125D, 0x1988, 0x103C, 0x001A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, /* HP OmniBook 6100 */ 930 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
981 { 0x125D, 0x1988, 0x107B, 0x340A, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 931 SND_PCI_QUIRK(0x103C, 0x001A, NULL, /* HP OmniBook 6100 */
982 { 0x125D, 0x1988, 0x107B, 0x3450, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 932 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
983 { 0x125D, 0x1988, 0x109F, 0x3134, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 933 SND_PCI_QUIRK(0x107B, 0x340A, NULL,
984 { 0x125D, 0x1988, 0x109F, 0x3161, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 934 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
985 { 0x125D, 0x1988, 0x144D, 0x3280, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 935 SND_PCI_QUIRK(0x107B, 0x3450, NULL,
986 { 0x125D, 0x1988, 0x144D, 0x3281, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 936 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
987 { 0x125D, 0x1988, 0x144D, 0xC002, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 937 SND_PCI_QUIRK(0x109F, 0x3134, NULL,
988 { 0x125D, 0x1988, 0x144D, 0xC003, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 938 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
989 { 0x125D, 0x1988, 0x1509, 0x1740, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 939 SND_PCI_QUIRK(0x109F, 0x3161, NULL,
990 { 0x125D, 0x1988, 0x1610, 0x0010, HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE, 0 }, 940 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
991 { 0x125D, 0x1988, 0x1042, 0x1042, HV_CTRL_ENABLE, 0 }, 941 SND_PCI_QUIRK(0x144D, 0x3280, NULL,
992 { 0x125D, 0x1988, 0x107B, 0x9500, HV_CTRL_ENABLE, 0 }, 942 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
993 { 0x125D, 0x1988, 0x14FF, 0x0F06, HV_CTRL_ENABLE, 0 }, 943 SND_PCI_QUIRK(0x144D, 0x3281, NULL,
994 { 0x125D, 0x1988, 0x1558, 0x8586, HV_CTRL_ENABLE, 0 }, 944 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
995 { 0x125D, 0x1988, 0x161F, 0x2011, HV_CTRL_ENABLE, 0 }, 945 SND_PCI_QUIRK(0x144D, 0xC002, NULL,
946 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
947 SND_PCI_QUIRK(0x144D, 0xC003, NULL,
948 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
949 SND_PCI_QUIRK(0x1509, 0x1740, NULL,
950 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
951 SND_PCI_QUIRK(0x1610, 0x0010, NULL,
952 HV_CTRL_ENABLE | HV_BUTTON_FROM_GD | REDUCED_DEBOUNCE),
953 SND_PCI_QUIRK(0x1042, 0x1042, NULL, HV_CTRL_ENABLE),
954 SND_PCI_QUIRK(0x107B, 0x9500, NULL, HV_CTRL_ENABLE),
955 SND_PCI_QUIRK(0x14FF, 0x0F06, NULL, HV_CTRL_ENABLE),
956 SND_PCI_QUIRK(0x1558, 0x8586, NULL, HV_CTRL_ENABLE),
957 SND_PCI_QUIRK(0x161F, 0x2011, NULL, HV_CTRL_ENABLE),
996 /* Maestro3 chips */ 958 /* Maestro3 chips */
997 { 0x125D, 0x1998, 0x103C, 0x000E, HV_CTRL_ENABLE, 0 }, 959 SND_PCI_QUIRK(0x103C, 0x000E, NULL, HV_CTRL_ENABLE),
998 { 0x125D, 0x1998, 0x103C, 0x0010, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 6000 */ 960 SND_PCI_QUIRK(0x103C, 0x0010, NULL, HV_CTRL_ENABLE),
999 { 0x125D, 0x1998, 0x103C, 0x0011, HV_CTRL_ENABLE, 1 }, /* HP OmniBook 500 */ 961 SND_PCI_QUIRK(0x103C, 0x0011, NULL, HV_CTRL_ENABLE),
1000 { 0x125D, 0x1998, 0x103C, 0x001B, HV_CTRL_ENABLE, 0 }, 962 SND_PCI_QUIRK(0x103C, 0x001B, NULL, HV_CTRL_ENABLE),
1001 { 0x125D, 0x1998, 0x104D, 0x80A6, HV_CTRL_ENABLE, 0 }, 963 SND_PCI_QUIRK(0x104D, 0x80A6, NULL, HV_CTRL_ENABLE),
1002 { 0x125D, 0x1998, 0x104D, 0x80AA, HV_CTRL_ENABLE, 0 }, 964 SND_PCI_QUIRK(0x104D, 0x80AA, NULL, HV_CTRL_ENABLE),
1003 { 0x125D, 0x1998, 0x107B, 0x5300, HV_CTRL_ENABLE, 0 }, 965 SND_PCI_QUIRK(0x107B, 0x5300, NULL, HV_CTRL_ENABLE),
1004 { 0x125D, 0x1998, 0x110A, 0x1998, HV_CTRL_ENABLE, 0 }, 966 SND_PCI_QUIRK(0x110A, 0x1998, NULL, HV_CTRL_ENABLE),
1005 { 0x125D, 0x1998, 0x13BD, 0x1015, HV_CTRL_ENABLE, 0 }, 967 SND_PCI_QUIRK(0x13BD, 0x1015, NULL, HV_CTRL_ENABLE),
1006 { 0x125D, 0x1998, 0x13BD, 0x101C, HV_CTRL_ENABLE, 0 }, 968 SND_PCI_QUIRK(0x13BD, 0x101C, NULL, HV_CTRL_ENABLE),
1007 { 0x125D, 0x1998, 0x13BD, 0x1802, HV_CTRL_ENABLE, 0 }, 969 SND_PCI_QUIRK(0x13BD, 0x1802, NULL, HV_CTRL_ENABLE),
1008 { 0x125D, 0x1998, 0x1599, 0x0715, HV_CTRL_ENABLE, 0 }, 970 SND_PCI_QUIRK(0x1599, 0x0715, NULL, HV_CTRL_ENABLE),
1009 { 0x125D, 0x1998, 0x5643, 0x5643, HV_CTRL_ENABLE, 0 }, 971 SND_PCI_QUIRK(0x5643, 0x5643, NULL, HV_CTRL_ENABLE),
1010 { 0x125D, 0x199A, 0x144D, 0x3260, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, 972 SND_PCI_QUIRK(0x144D, 0x3260, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),
1011 { 0x125D, 0x199A, 0x144D, 0x3261, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, 973 SND_PCI_QUIRK(0x144D, 0x3261, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),
1012 { 0x125D, 0x199A, 0x144D, 0xC000, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, 974 SND_PCI_QUIRK(0x144D, 0xC000, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),
1013 { 0x125D, 0x199A, 0x144D, 0xC001, HV_CTRL_ENABLE | REDUCED_DEBOUNCE, 0 }, 975 SND_PCI_QUIRK(0x144D, 0xC001, NULL, HV_CTRL_ENABLE | REDUCED_DEBOUNCE),
1014 { 0 } 976 { } /* END */
977};
978
979/* HP Omnibook quirks */
980static struct snd_pci_quirk m3_omnibook_quirk_list[] __devinitdata = {
981 SND_PCI_QUIRK_ID(0x103c, 0x0010), /* HP OmniBook 6000 */
982 SND_PCI_QUIRK_ID(0x103c, 0x0011), /* HP OmniBook 500 */
983 { } /* END */
1015}; 984};
1016 985
1017/* 986/*
@@ -2050,7 +2019,7 @@ static void snd_m3_ac97_reset(struct snd_m3 *chip)
2050 2019
2051 for (i = 0; i < 5; i++) { 2020 for (i = 0; i < 5; i++) {
2052 dir = inw(io + GPIO_DIRECTION); 2021 dir = inw(io + GPIO_DIRECTION);
2053 if (! chip->quirk || ! chip->quirk->irda_workaround) 2022 if (!chip->irda_workaround)
2054 dir |= 0x10; /* assuming pci bus master? */ 2023 dir |= 0x10; /* assuming pci bus master? */
2055 2024
2056 snd_m3_remote_codec_config(io, 0); 2025 snd_m3_remote_codec_config(io, 0);
@@ -2132,6 +2101,10 @@ static int __devinit snd_m3_mixer(struct snd_m3 *chip)
2132} 2101}
2133 2102
2134 2103
2104#define FIRMWARE_IN_THE_KERNEL
2105
2106#ifdef FIRMWARE_IN_THE_KERNEL
2107
2135/* 2108/*
2136 * DSP Code images 2109 * DSP Code images
2137 */ 2110 */
@@ -2260,6 +2233,30 @@ static const u16 assp_minisrc_image[] = {
2260 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 2233 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
2261}; 2234};
2262 2235
2236static const struct firmware assp_kernel = {
2237 .data = (u8 *)assp_kernel_image,
2238 .size = sizeof assp_kernel_image
2239};
2240static const struct firmware assp_minisrc = {
2241 .data = (u8 *)assp_minisrc_image,
2242 .size = sizeof assp_minisrc_image
2243};
2244
2245#endif /* FIRMWARE_IN_THE_KERNEL */
2246
2247#ifdef __LITTLE_ENDIAN
2248static inline void snd_m3_convert_from_le(const struct firmware *fw) { }
2249#else
2250static void snd_m3_convert_from_le(const struct firmware *fw)
2251{
2252 int i;
2253 u16 *data = (u16 *)fw->data;
2254
2255 for (i = 0; i < fw->size / 2; ++i)
2256 le16_to_cpus(&data[i]);
2257}
2258#endif
2259
2263 2260
2264/* 2261/*
2265 * initialize ASSP 2262 * initialize ASSP
@@ -2274,6 +2271,7 @@ static const u16 minisrc_lpf[MINISRC_LPF_LEN] = {
2274static void snd_m3_assp_init(struct snd_m3 *chip) 2271static void snd_m3_assp_init(struct snd_m3 *chip)
2275{ 2272{
2276 unsigned int i; 2273 unsigned int i;
2274 u16 *data;
2277 2275
2278 /* zero kernel data */ 2276 /* zero kernel data */
2279 for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++) 2277 for (i = 0; i < (REV_B_DATA_MEMORY_UNIT_LENGTH * NUM_UNITS_KERNEL_DATA) / 2; i++)
@@ -2291,10 +2289,10 @@ static void snd_m3_assp_init(struct snd_m3 *chip)
2291 KDATA_DMA_XFER0); 2289 KDATA_DMA_XFER0);
2292 2290
2293 /* write kernel into code memory.. */ 2291 /* write kernel into code memory.. */
2294 for (i = 0 ; i < ARRAY_SIZE(assp_kernel_image); i++) { 2292 data = (u16 *)chip->assp_kernel_image->data;
2293 for (i = 0 ; i * 2 < chip->assp_kernel_image->size; i++) {
2295 snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 2294 snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE,
2296 REV_B_CODE_MEMORY_BEGIN + i, 2295 REV_B_CODE_MEMORY_BEGIN + i, data[i]);
2297 assp_kernel_image[i]);
2298 } 2296 }
2299 2297
2300 /* 2298 /*
@@ -2303,10 +2301,10 @@ static void snd_m3_assp_init(struct snd_m3 *chip)
2303 * drop it there. It seems that the minisrc doesn't 2301 * drop it there. It seems that the minisrc doesn't
2304 * need vectors, so we won't bother with them.. 2302 * need vectors, so we won't bother with them..
2305 */ 2303 */
2306 for (i = 0; i < ARRAY_SIZE(assp_minisrc_image); i++) { 2304 data = (u16 *)chip->assp_minisrc_image->data;
2305 for (i = 0; i * 2 < chip->assp_minisrc_image->size; i++) {
2307 snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE, 2306 snd_m3_assp_write(chip, MEMTYPE_INTERNAL_CODE,
2308 0x400 + i, 2307 0x400 + i, data[i]);
2309 assp_minisrc_image[i]);
2310 } 2308 }
2311 2309
2312 /* 2310 /*
@@ -2444,7 +2442,7 @@ snd_m3_chip_init(struct snd_m3 *chip)
2444 DISABLE_LEGACY); 2442 DISABLE_LEGACY);
2445 pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w); 2443 pci_write_config_word(pcidev, PCI_LEGACY_AUDIO_CTRL, w);
2446 2444
2447 if (chip->hv_quirk && chip->hv_quirk->is_omnibook) { 2445 if (chip->is_omnibook) {
2448 /* 2446 /*
2449 * Volume buttons on some HP OmniBook laptops don't work 2447 * Volume buttons on some HP OmniBook laptops don't work
2450 * correctly. This makes them work for the most part. 2448 * correctly. This makes them work for the most part.
@@ -2461,8 +2459,7 @@ snd_m3_chip_init(struct snd_m3 *chip)
2461 } 2459 }
2462 pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n); 2460 pci_read_config_dword(pcidev, PCI_ALLEGRO_CONFIG, &n);
2463 n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD); 2461 n &= ~(HV_CTRL_ENABLE | REDUCED_DEBOUNCE | HV_BUTTON_FROM_GD);
2464 if (chip->hv_quirk) 2462 n |= chip->hv_config;
2465 n |= chip->hv_quirk->config;
2466 /* For some reason we must always use reduced debounce. */ 2463 /* For some reason we must always use reduced debounce. */
2467 n |= REDUCED_DEBOUNCE; 2464 n |= REDUCED_DEBOUNCE;
2468 n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING; 2465 n |= PM_CTRL_ENABLE | CLK_DIV_BY_49 | USE_PCI_TIMING;
@@ -2510,7 +2507,7 @@ snd_m3_enable_ints(struct snd_m3 *chip)
2510 2507
2511 /* TODO: MPU401 not supported yet */ 2508 /* TODO: MPU401 not supported yet */
2512 val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/; 2509 val = ASSP_INT_ENABLE /*| MPU401_INT_ENABLE*/;
2513 if (chip->hv_quirk && (chip->hv_quirk->config & HV_CTRL_ENABLE)) 2510 if (chip->hv_config & HV_CTRL_ENABLE)
2514 val |= HV_INT_ENABLE; 2511 val |= HV_INT_ENABLE;
2515 outw(val, io + HOST_INT_CTRL); 2512 outw(val, io + HOST_INT_CTRL);
2516 outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE, 2513 outb(inb(io + ASSP_CONTROL_C) | ASSP_HOST_INT_ENABLE,
@@ -2553,6 +2550,15 @@ static int snd_m3_free(struct snd_m3 *chip)
2553 if (chip->iobase) 2550 if (chip->iobase)
2554 pci_release_regions(chip->pci); 2551 pci_release_regions(chip->pci);
2555 2552
2553#ifdef FIRMWARE_IN_THE_KERNEL
2554 if (chip->assp_kernel_image != &assp_kernel)
2555#endif
2556 release_firmware(chip->assp_kernel_image);
2557#ifdef FIRMWARE_IN_THE_KERNEL
2558 if (chip->assp_minisrc_image != &assp_minisrc)
2559#endif
2560 release_firmware(chip->assp_minisrc_image);
2561
2556 pci_disable_device(chip->pci); 2562 pci_disable_device(chip->pci);
2557 kfree(chip); 2563 kfree(chip);
2558 return 0; 2564 return 0;
@@ -2665,8 +2671,7 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
2665{ 2671{
2666 struct snd_m3 *chip; 2672 struct snd_m3 *chip;
2667 int i, err; 2673 int i, err;
2668 const struct m3_quirk *quirk; 2674 const struct snd_pci_quirk *quirk;
2669 const struct m3_hv_quirk *hv_quirk;
2670 static struct snd_device_ops ops = { 2675 static struct snd_device_ops ops = {
2671 .dev_free = snd_m3_dev_free, 2676 .dev_free = snd_m3_dev_free,
2672 }; 2677 };
@@ -2706,34 +2711,32 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
2706 chip->pci = pci; 2711 chip->pci = pci;
2707 chip->irq = -1; 2712 chip->irq = -1;
2708 2713
2709 for (quirk = m3_quirk_list; quirk->vendor; quirk++) {
2710 if (pci->subsystem_vendor == quirk->vendor &&
2711 pci->subsystem_device == quirk->device) {
2712 printk(KERN_INFO "maestro3: enabled hack for '%s'\n", quirk->name);
2713 chip->quirk = quirk;
2714 break;
2715 }
2716 }
2717
2718 for (hv_quirk = m3_hv_quirk_list; hv_quirk->vendor; hv_quirk++) {
2719 if (pci->vendor == hv_quirk->vendor &&
2720 pci->device == hv_quirk->device &&
2721 pci->subsystem_vendor == hv_quirk->subsystem_vendor &&
2722 pci->subsystem_device == hv_quirk->subsystem_device) {
2723 chip->hv_quirk = hv_quirk;
2724 break;
2725 }
2726 }
2727
2728 chip->external_amp = enable_amp; 2714 chip->external_amp = enable_amp;
2729 if (amp_gpio >= 0 && amp_gpio <= 0x0f) 2715 if (amp_gpio >= 0 && amp_gpio <= 0x0f)
2730 chip->amp_gpio = amp_gpio; 2716 chip->amp_gpio = amp_gpio;
2731 else if (chip->quirk && chip->quirk->amp_gpio >= 0) 2717 else {
2732 chip->amp_gpio = chip->quirk->amp_gpio; 2718 quirk = snd_pci_quirk_lookup(pci, m3_amp_quirk_list);
2733 else if (chip->allegro_flag) 2719 if (quirk) {
2734 chip->amp_gpio = GPO_EXT_AMP_ALLEGRO; 2720 snd_printdd(KERN_INFO "maestro3: set amp-gpio "
2735 else /* presumably this is for all 'maestro3's.. */ 2721 "for '%s'\n", quirk->name);
2736 chip->amp_gpio = GPO_EXT_AMP_M3; 2722 chip->amp_gpio = quirk->value;
2723 } else if (chip->allegro_flag)
2724 chip->amp_gpio = GPO_EXT_AMP_ALLEGRO;
2725 else /* presumably this is for all 'maestro3's.. */
2726 chip->amp_gpio = GPO_EXT_AMP_M3;
2727 }
2728
2729 quirk = snd_pci_quirk_lookup(pci, m3_irda_quirk_list);
2730 if (quirk) {
2731 snd_printdd(KERN_INFO "maestro3: enabled irda workaround "
2732 "for '%s'\n", quirk->name);
2733 chip->irda_workaround = 1;
2734 }
2735 quirk = snd_pci_quirk_lookup(pci, m3_hv_quirk_list);
2736 if (quirk)
2737 chip->hv_config = quirk->value;
2738 if (snd_pci_quirk_lookup(pci, m3_omnibook_quirk_list))
2739 chip->is_omnibook = 1;
2737 2740
2738 chip->num_substreams = NR_DSPS; 2741 chip->num_substreams = NR_DSPS;
2739 chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma), 2742 chip->substreams = kcalloc(chip->num_substreams, sizeof(struct m3_dma),
@@ -2744,6 +2747,30 @@ snd_m3_create(struct snd_card *card, struct pci_dev *pci,
2744 return -ENOMEM; 2747 return -ENOMEM;
2745 } 2748 }
2746 2749
2750 err = request_firmware(&chip->assp_kernel_image,
2751 "ess/maestro3_assp_kernel.fw", &pci->dev);
2752 if (err < 0) {
2753#ifdef FIRMWARE_IN_THE_KERNEL
2754 chip->assp_kernel_image = &assp_kernel;
2755#else
2756 snd_m3_free(chip);
2757 return err;
2758#endif
2759 } else
2760 snd_m3_convert_from_le(chip->assp_kernel_image);
2761
2762 err = request_firmware(&chip->assp_minisrc_image,
2763 "ess/maestro3_assp_minisrc.fw", &pci->dev);
2764 if (err < 0) {
2765#ifdef FIRMWARE_IN_THE_KERNEL
2766 chip->assp_minisrc_image = &assp_minisrc;
2767#else
2768 snd_m3_free(chip);
2769 return err;
2770#endif
2771 } else
2772 snd_m3_convert_from_le(chip->assp_minisrc_image);
2773
2747 if ((err = pci_request_regions(pci, card->driver)) < 0) { 2774 if ((err = pci_request_regions(pci, card->driver)) < 0) {
2748 snd_m3_free(chip); 2775 snd_m3_free(chip);
2749 return err; 2776 return err;
diff --git a/sound/pci/mixart/mixart_mixer.c b/sound/pci/mixart/mixart_mixer.c
index 13de0f71d4b7..d7d15c036e02 100644
--- a/sound/pci/mixart/mixart_mixer.c
+++ b/sound/pci/mixart/mixart_mixer.c
@@ -389,7 +389,7 @@ static int mixart_analog_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_e
389 return changed; 389 return changed;
390} 390}
391 391
392static DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0); 392static const DECLARE_TLV_DB_SCALE(db_scale_analog, -9600, 50, 0);
393 393
394static struct snd_kcontrol_new mixart_control_analog_level = { 394static struct snd_kcontrol_new mixart_control_analog_level = {
395 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 395 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
@@ -872,7 +872,7 @@ static int mixart_pcm_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
872 return changed; 872 return changed;
873} 873}
874 874
875static DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); 875static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0);
876 876
877static struct snd_kcontrol_new snd_mixart_pcm_vol = 877static struct snd_kcontrol_new snd_mixart_pcm_vol =
878{ 878{
diff --git a/sound/pci/nm256/nm256.c b/sound/pci/nm256/nm256.c
index 879e31a9f9c6..03b3a4792f73 100644
--- a/sound/pci/nm256/nm256.c
+++ b/sound/pci/nm256/nm256.c
@@ -1628,23 +1628,15 @@ __error:
1628} 1628}
1629 1629
1630 1630
1631struct nm256_quirk {
1632 unsigned short vendor;
1633 unsigned short device;
1634 int type;
1635};
1636
1637enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 }; 1631enum { NM_BLACKLISTED, NM_RESET_WORKAROUND, NM_RESET_WORKAROUND_2 };
1638 1632
1639static struct nm256_quirk nm256_quirks[] __devinitdata = { 1633static struct snd_pci_quirk nm256_quirks[] __devinitdata = {
1640 /* HP omnibook 4150 has cs4232 codec internally */ 1634 /* HP omnibook 4150 has cs4232 codec internally */
1641 { .vendor = 0x103c, .device = 0x0007, .type = NM_BLACKLISTED }, 1635 SND_PCI_QUIRK(0x103c, 0x0007, "HP omnibook 4150", NM_BLACKLISTED),
1642 /* Sony PCG-F305 */ 1636 /* Reset workarounds to avoid lock-ups */
1643 { .vendor = 0x104d, .device = 0x8041, .type = NM_RESET_WORKAROUND }, 1637 SND_PCI_QUIRK(0x104d, 0x8041, "Sony PCG-F305", NM_RESET_WORKAROUND),
1644 /* Dell Latitude LS */ 1638 SND_PCI_QUIRK(0x1028, 0x0080, "Dell Latitude LS", NM_RESET_WORKAROUND),
1645 { .vendor = 0x1028, .device = 0x0080, .type = NM_RESET_WORKAROUND }, 1639 SND_PCI_QUIRK(0x1028, 0x0091, "Dell Latitude CSx", NM_RESET_WORKAROUND_2),
1646 /* Dell Latitude CSx */
1647 { .vendor = 0x1028, .device = 0x0091, .type = NM_RESET_WORKAROUND_2 },
1648 { } /* terminator */ 1640 { } /* terminator */
1649}; 1641};
1650 1642
@@ -1655,26 +1647,22 @@ static int __devinit snd_nm256_probe(struct pci_dev *pci,
1655 struct snd_card *card; 1647 struct snd_card *card;
1656 struct nm256 *chip; 1648 struct nm256 *chip;
1657 int err; 1649 int err;
1658 struct nm256_quirk *q; 1650 const struct snd_pci_quirk *q;
1659 u16 subsystem_vendor, subsystem_device; 1651
1660 1652 q = snd_pci_quirk_lookup(pci, nm256_quirks);
1661 pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor); 1653 if (q) {
1662 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device); 1654 snd_printdd(KERN_INFO "nm256: Enabled quirk for %s.\n", q->name);
1663 1655 switch (q->value) {
1664 for (q = nm256_quirks; q->vendor; q++) { 1656 case NM_BLACKLISTED:
1665 if (q->vendor == subsystem_vendor && q->device == subsystem_device) { 1657 printk(KERN_INFO "nm256: The device is blacklisted. "
1666 switch (q->type) { 1658 "Loading stopped\n");
1667 case NM_BLACKLISTED: 1659 return -ENODEV;
1668 printk(KERN_INFO "nm256: The device is blacklisted. " 1660 case NM_RESET_WORKAROUND_2:
1669 "Loading stopped\n"); 1661 reset_workaround_2 = 1;
1670 return -ENODEV; 1662 /* Fall-through */
1671 case NM_RESET_WORKAROUND_2: 1663 case NM_RESET_WORKAROUND:
1672 reset_workaround_2 = 1; 1664 reset_workaround = 1;
1673 /* Fall-through */ 1665 break;
1674 case NM_RESET_WORKAROUND:
1675 reset_workaround = 1;
1676 break;
1677 }
1678 } 1666 }
1679 } 1667 }
1680 1668
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c
index b133ad9e095e..d9cc8d2beb6d 100644
--- a/sound/pci/pcxhr/pcxhr_mixer.c
+++ b/sound/pci/pcxhr/pcxhr_mixer.c
@@ -44,8 +44,8 @@
44#define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */ 44#define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */
45#define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */ 45#define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */
46 46
47static DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 0); 47static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 0);
48static DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -12800, 100, 0); 48static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -12800, 100, 0);
49 49
50static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel) 50static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel)
51{ 51{
@@ -195,7 +195,7 @@ static struct snd_kcontrol_new pcxhr_control_output_switch = {
195#define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */ 195#define PCXHR_DIGITAL_LEVEL_MAX 0x1ff /* +18 dB */
196#define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */ 196#define PCXHR_DIGITAL_ZERO_LEVEL 0x1b7 /* 0 dB */
197 197
198static DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0); 198static const DECLARE_TLV_DB_SCALE(db_scale_digital, -10950, 50, 0);
199 199
200#define MORE_THAN_ONE_STREAM_LEVEL 0x000001 200#define MORE_THAN_ONE_STREAM_LEVEL 0x000001
201#define VALID_STREAM_PAN_LEVEL_MASK 0x800000 201#define VALID_STREAM_PAN_LEVEL_MASK 0x800000
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index 6383987b460e..89b3c7ff5037 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -80,6 +80,7 @@ MODULE_SUPPORTED_DEVICE("{{RME Hammerfall-DSP},"
80/* Write registers. These are defined as byte-offsets from the iobase value. 80/* Write registers. These are defined as byte-offsets from the iobase value.
81 */ 81 */
82#define HDSP_resetPointer 0 82#define HDSP_resetPointer 0
83#define HDSP_freqReg 0
83#define HDSP_outputBufferAddress 32 84#define HDSP_outputBufferAddress 32
84#define HDSP_inputBufferAddress 36 85#define HDSP_inputBufferAddress 36
85#define HDSP_controlRegister 64 86#define HDSP_controlRegister 64
@@ -469,6 +470,7 @@ struct hdsp {
469 struct pci_dev *pci; 470 struct pci_dev *pci;
470 struct snd_kcontrol *spdif_ctl; 471 struct snd_kcontrol *spdif_ctl;
471 unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE]; 472 unsigned short mixer_matrix[HDSP_MATRIX_MIXER_SIZE];
473 unsigned int dds_value; /* last value written to freq register */
472}; 474};
473 475
474/* These tables map the ALSA channels 1..N to the channels that we 476/* These tables map the ALSA channels 1..N to the channels that we
@@ -598,6 +600,7 @@ static int hdsp_playback_to_output_key (struct hdsp *hdsp, int in, int out)
598 return (64 * out) + (32 + (in)); 600 return (64 * out) + (32 + (in));
599 case 0x96: 601 case 0x96:
600 case 0x97: 602 case 0x97:
603 case 0x98:
601 return (32 * out) + (16 + (in)); 604 return (32 * out) + (16 + (in));
602 default: 605 default:
603 return (52 * out) + (26 + (in)); 606 return (52 * out) + (26 + (in));
@@ -611,6 +614,7 @@ static int hdsp_input_to_output_key (struct hdsp *hdsp, int in, int out)
611 return (64 * out) + in; 614 return (64 * out) + in;
612 case 0x96: 615 case 0x96:
613 case 0x97: 616 case 0x97:
617 case 0x98:
614 return (32 * out) + in; 618 return (32 * out) + in;
615 default: 619 default:
616 return (52 * out) + in; 620 return (52 * out) + in;
@@ -938,6 +942,11 @@ static snd_pcm_uframes_t hdsp_hw_pointer(struct hdsp *hdsp)
938static void hdsp_reset_hw_pointer(struct hdsp *hdsp) 942static void hdsp_reset_hw_pointer(struct hdsp *hdsp)
939{ 943{
940 hdsp_write (hdsp, HDSP_resetPointer, 0); 944 hdsp_write (hdsp, HDSP_resetPointer, 0);
945 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
946 /* HDSP_resetPointer = HDSP_freqReg, which is strange and
947 * requires (?) to write again DDS value after a reset pointer
948 * (at least, it works like this) */
949 hdsp_write (hdsp, HDSP_freqReg, hdsp->dds_value);
941} 950}
942 951
943static void hdsp_start_audio(struct hdsp *s) 952static void hdsp_start_audio(struct hdsp *s)
@@ -982,6 +991,30 @@ static int hdsp_set_interrupt_interval(struct hdsp *s, unsigned int frames)
982 return 0; 991 return 0;
983} 992}
984 993
994static void hdsp_set_dds_value(struct hdsp *hdsp, int rate)
995{
996 u64 n;
997 u32 r;
998
999 if (rate >= 112000)
1000 rate /= 4;
1001 else if (rate >= 56000)
1002 rate /= 2;
1003
1004 /* RME says n = 104857600000000, but in the windows MADI driver, I see:
1005// return 104857600000000 / rate; // 100 MHz
1006 return 110100480000000 / rate; // 105 MHz
1007 */
1008 n = 104857600000000ULL; /* = 2^20 * 10^8 */
1009 div64_32(&n, rate, &r);
1010 /* n should be less than 2^32 for being written to FREQ register */
1011 snd_assert((n >> 32) == 0);
1012 /* HDSP_freqReg and HDSP_resetPointer are the same, so keep the DDS
1013 value to write it after a reset */
1014 hdsp->dds_value = n;
1015 hdsp_write(hdsp, HDSP_freqReg, hdsp->dds_value);
1016}
1017
985static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally) 1018static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
986{ 1019{
987 int reject_if_open = 0; 1020 int reject_if_open = 0;
@@ -1090,6 +1123,10 @@ static int hdsp_set_rate(struct hdsp *hdsp, int rate, int called_internally)
1090 hdsp->control_register |= rate_bits; 1123 hdsp->control_register |= rate_bits;
1091 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register); 1124 hdsp_write(hdsp, HDSP_controlRegister, hdsp->control_register);
1092 1125
1126 /* For HDSP9632 rev 152, need to set DDS value in FREQ register */
1127 if (hdsp->io_type == H9632 && hdsp->firmware_rev >= 152)
1128 hdsp_set_dds_value(hdsp, rate);
1129
1093 if (rate >= 128000) { 1130 if (rate >= 128000) {
1094 hdsp->channel_map = channel_map_H9632_qs; 1131 hdsp->channel_map = channel_map_H9632_qs;
1095 } else if (rate > 48000) { 1132 } else if (rate > 48000) {
@@ -4943,6 +4980,7 @@ static int __devinit snd_hdsp_create(struct snd_card *card,
4943 hdsp->irq = pci->irq; 4980 hdsp->irq = pci->irq;
4944 hdsp->precise_ptr = 0; 4981 hdsp->precise_ptr = 0;
4945 hdsp->use_midi_tasklet = 1; 4982 hdsp->use_midi_tasklet = 1;
4983 hdsp->dds_value = 0;
4946 4984
4947 if ((err = snd_hdsp_initialize_memory(hdsp)) < 0) 4985 if ((err = snd_hdsp_initialize_memory(hdsp)) < 0)
4948 return err; 4986 return err;
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 0547f6f04bdc..e0215aca1193 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -6,6 +6,8 @@
6 * code based on hdsp.c Paul Davis 6 * code based on hdsp.c Paul Davis
7 * Marcus Andersson 7 * Marcus Andersson
8 * Thomas Charbonnel 8 * Thomas Charbonnel
9 * Modified 2006-06-01 for AES32 support by Remy Bruno
10 * <remy.bruno@trinnov.com>
9 * 11 *
10 * This program is free software; you can redistribute it and/or modify 12 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by 13 * it under the terms of the GNU General Public License as published by
@@ -77,7 +79,8 @@ MODULE_PARM_DESC(enable_monitor,
77 79
78MODULE_AUTHOR 80MODULE_AUTHOR
79 ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, " 81 ("Winfried Ritsch <ritsch_AT_iem.at>, Paul Davis <paul@linuxaudiosystems.com>, "
80 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>"); 82 "Marcus Andersson, Thomas Charbonnel <thomas@undata.org>, "
83 "Remy Bruno <remy.bruno@trinnov.com>");
81MODULE_DESCRIPTION("RME HDSPM"); 84MODULE_DESCRIPTION("RME HDSPM");
82MODULE_LICENSE("GPL"); 85MODULE_LICENSE("GPL");
83MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}"); 86MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
@@ -107,7 +110,12 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
107/* --- Read registers. --- 110/* --- Read registers. ---
108 These are defined as byte-offsets from the iobase value */ 111 These are defined as byte-offsets from the iobase value */
109#define HDSPM_statusRegister 0 112#define HDSPM_statusRegister 0
110#define HDSPM_statusRegister2 96 113/*#define HDSPM_statusRegister2 96 */
114/* after RME Windows driver sources, status2 is 4-byte word # 48 = word at
115 * offset 192, for AES32 *and* MADI
116 * => need to check that offset 192 is working on MADI */
117#define HDSPM_statusRegister2 192
118#define HDSPM_timecodeRegister 128
111 119
112#define HDSPM_midiDataIn0 360 120#define HDSPM_midiDataIn0 360
113#define HDSPM_midiDataIn1 364 121#define HDSPM_midiDataIn1 364
@@ -140,37 +148,50 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
140#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */ 148#define HDSPM_Frequency0 (1<<6) /* 0=44.1kHz/88.2kHz 1=48kHz/96kHz */
141#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */ 149#define HDSPM_Frequency1 (1<<7) /* 0=32kHz/64kHz */
142#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */ 150#define HDSPM_DoubleSpeed (1<<8) /* 0=normal speed, 1=double speed */
143#define HDSPM_QuadSpeed (1<<31) /* quad speed bit, not implemented now */ 151#define HDSPM_QuadSpeed (1<<31) /* quad speed bit */
144 152
153#define HDSPM_Professional (1<<9) /* Professional */ /* AES32 ONLY */
145#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1, 154#define HDSPM_TX_64ch (1<<10) /* Output 64channel MODE=1,
146 56channelMODE=0 */ 155 56channelMODE=0 */ /* MADI ONLY*/
156#define HDSPM_Emphasis (1<<10) /* Emphasis */ /* AES32 ONLY */
147 157
148#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode, 158#define HDSPM_AutoInp (1<<11) /* Auto Input (takeover) == Safe Mode,
149 0=off, 1=on */ 159 0=off, 1=on */ /* MADI ONLY */
160#define HDSPM_Dolby (1<<11) /* Dolby = "NonAudio" ?? */ /* AES32 ONLY */
150 161
151#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ 162#define HDSPM_InputSelect0 (1<<14) /* Input select 0= optical, 1=coax */ /* MADI ONLY*/
152#define HDSPM_InputSelect1 (1<<15) /* should be 0 */ 163#define HDSPM_InputSelect1 (1<<15) /* should be 0 */
153 164
154#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */ 165#define HDSPM_SyncRef0 (1<<16) /* 0=WOrd, 1=MADI */
155#define HDSPM_SyncRef1 (1<<17) /* should be 0 */ 166#define HDSPM_SyncRef1 (1<<17) /* for AES32: SyncRefN codes the AES # */
167#define HDSPM_SyncRef2 (1<<13)
168#define HDSPM_SyncRef3 (1<<25)
156 169
170#define HDSPM_SMUX (1<<18) /* Frame ??? */ /* MADI ONY */
157#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use 171#define HDSPM_clr_tms (1<<19) /* clear track marker, do not use
158 AES additional bits in 172 AES additional bits in
159 lower 5 Audiodatabits ??? */ 173 lower 5 Audiodatabits ??? */
174#define HDSPM_taxi_reset (1<<20) /* ??? */ /* MADI ONLY ? */
175#define HDSPM_WCK48 (1<<20) /* Frame ??? = HDSPM_SMUX */ /* AES32 ONLY */
160 176
161#define HDSPM_Midi0InterruptEnable (1<<22) 177#define HDSPM_Midi0InterruptEnable (1<<22)
162#define HDSPM_Midi1InterruptEnable (1<<23) 178#define HDSPM_Midi1InterruptEnable (1<<23)
163 179
164#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */ 180#define HDSPM_LineOut (1<<24) /* Analog Out on channel 63/64 on=1, mute=0 */
165 181
182#define HDSPM_DS_DoubleWire (1<<26) /* AES32 ONLY */
183#define HDSPM_QS_DoubleWire (1<<27) /* AES32 ONLY */
184#define HDSPM_QS_QuadWire (1<<28) /* AES32 ONLY */
185
186#define HDSPM_wclk_sel (1<<30)
166 187
167/* --- bit helper defines */ 188/* --- bit helper defines */
168#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2) 189#define HDSPM_LatencyMask (HDSPM_Latency0|HDSPM_Latency1|HDSPM_Latency2)
169#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1) 190#define HDSPM_FrequencyMask (HDSPM_Frequency0|HDSPM_Frequency1|HDSPM_DoubleSpeed|HDSPM_QuadSpeed)
170#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1) 191#define HDSPM_InputMask (HDSPM_InputSelect0|HDSPM_InputSelect1)
171#define HDSPM_InputOptical 0 192#define HDSPM_InputOptical 0
172#define HDSPM_InputCoaxial (HDSPM_InputSelect0) 193#define HDSPM_InputCoaxial (HDSPM_InputSelect0)
173#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1) 194#define HDSPM_SyncRefMask (HDSPM_SyncRef0|HDSPM_SyncRef1|HDSPM_SyncRef2|HDSPM_SyncRef3)
174#define HDSPM_SyncRef_Word 0 195#define HDSPM_SyncRef_Word 0
175#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0) 196#define HDSPM_SyncRef_MADI (HDSPM_SyncRef0)
176 197
@@ -183,6 +204,9 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
183#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0) 204#define HDSPM_Frequency64KHz (HDSPM_DoubleSpeed|HDSPM_Frequency0)
184#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1) 205#define HDSPM_Frequency88_2KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1)
185#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0) 206#define HDSPM_Frequency96KHz (HDSPM_DoubleSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
207#define HDSPM_Frequency128KHz (HDSPM_QuadSpeed|HDSPM_Frequency0)
208#define HDSPM_Frequency176_4KHz (HDSPM_QuadSpeed|HDSPM_Frequency1)
209#define HDSPM_Frequency192KHz (HDSPM_QuadSpeed|HDSPM_Frequency1|HDSPM_Frequency0)
186 210
187/* --- for internal discrimination */ 211/* --- for internal discrimination */
188#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */ 212#define HDSPM_CLOCK_SOURCE_AUTOSYNC 0 /* Sample Clock Sources */
@@ -229,7 +253,8 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
229#define HDSPM_BIGENDIAN_MODE (1<<9) 253#define HDSPM_BIGENDIAN_MODE (1<<9)
230#define HDSPM_RD_MULTIPLE (1<<10) 254#define HDSPM_RD_MULTIPLE (1<<10)
231 255
232/* --- Status Register bits --- */ 256/* --- Status Register bits --- */ /* MADI ONLY */ /* Bits defined here and
257 that do not conflict with specific bits for AES32 seem to be valid also for the AES32 */
233#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */ 258#define HDSPM_audioIRQPending (1<<0) /* IRQ is high and pending */
234#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */ 259#define HDSPM_RX_64ch (1<<1) /* Input 64chan. MODE=1, 56chn. MODE=0 */
235#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */ 260#define HDSPM_AB_int (1<<2) /* InputChannel Opt=0, Coax=1 (like inp0) */
@@ -263,7 +288,7 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
263#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3) 288#define HDSPM_madiFreq176_4 (HDSPM_madiFreq3)
264#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0) 289#define HDSPM_madiFreq192 (HDSPM_madiFreq3|HDSPM_madiFreq0)
265 290
266/* Status2 Register bits */ 291/* Status2 Register bits */ /* MADI ONLY */
267 292
268#define HDSPM_version0 (1<<0) /* not realy defined but I guess */ 293#define HDSPM_version0 (1<<0) /* not realy defined but I guess */
269#define HDSPM_version1 (1<<1) /* in former cards it was ??? */ 294#define HDSPM_version1 (1<<1) /* in former cards it was ??? */
@@ -297,6 +322,56 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
297#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0) 322#define HDSPM_SelSyncRef_MADI (HDSPM_SelSyncRef0)
298#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2) 323#define HDSPM_SelSyncRef_NVALID (HDSPM_SelSyncRef0|HDSPM_SelSyncRef1|HDSPM_SelSyncRef2)
299 324
325/*
326 For AES32, bits for status, status2 and timecode are different
327*/
328/* status */
329#define HDSPM_AES32_wcLock 0x0200000
330#define HDSPM_AES32_wcFreq_bit 22
331/* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
332 HDSPM_bit2freq */
333#define HDSPM_AES32_syncref_bit 16
334/* (status >> HDSPM_AES32_syncref_bit) & 0xF gives sync source */
335
336#define HDSPM_AES32_AUTOSYNC_FROM_WORD 0
337#define HDSPM_AES32_AUTOSYNC_FROM_AES1 1
338#define HDSPM_AES32_AUTOSYNC_FROM_AES2 2
339#define HDSPM_AES32_AUTOSYNC_FROM_AES3 3
340#define HDSPM_AES32_AUTOSYNC_FROM_AES4 4
341#define HDSPM_AES32_AUTOSYNC_FROM_AES5 5
342#define HDSPM_AES32_AUTOSYNC_FROM_AES6 6
343#define HDSPM_AES32_AUTOSYNC_FROM_AES7 7
344#define HDSPM_AES32_AUTOSYNC_FROM_AES8 8
345#define HDSPM_AES32_AUTOSYNC_FROM_NONE -1
346
347/* status2 */
348/* HDSPM_LockAES_bit is given by HDSPM_LockAES >> (AES# - 1) */
349#define HDSPM_LockAES 0x80
350#define HDSPM_LockAES1 0x80
351#define HDSPM_LockAES2 0x40
352#define HDSPM_LockAES3 0x20
353#define HDSPM_LockAES4 0x10
354#define HDSPM_LockAES5 0x8
355#define HDSPM_LockAES6 0x4
356#define HDSPM_LockAES7 0x2
357#define HDSPM_LockAES8 0x1
358/*
359 Timecode
360 After windows driver sources, bits 4*i to 4*i+3 give the input frequency on
361 AES i+1
362 bits 3210
363 0001 32kHz
364 0010 44.1kHz
365 0011 48kHz
366 0100 64kHz
367 0101 88.2kHz
368 0110 96kHz
369 0111 128kHz
370 1000 176.4kHz
371 1001 192kHz
372 NB: Timecode register doesn't seem to work on AES32 card revision 230
373*/
374
300/* Mixer Values */ 375/* Mixer Values */
301#define UNITY_GAIN 32768 /* = 65536/2 */ 376#define UNITY_GAIN 32768 /* = 65536/2 */
302#define MINUS_INFINITY_GAIN 0 377#define MINUS_INFINITY_GAIN 0
@@ -314,10 +389,14 @@ MODULE_SUPPORTED_DEVICE("{{RME HDSPM-MADI}}");
314 size is the same regardless of the number of channels, and 389 size is the same regardless of the number of channels, and
315 also the latency to use. 390 also the latency to use.
316 for one direction !!! 391 for one direction !!!
392 => need to mupltiply by 2!!
317*/ 393*/
318#define HDSPM_DMA_AREA_BYTES (HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES) 394#define HDSPM_DMA_AREA_BYTES (2 * HDSPM_MAX_CHANNELS * HDSPM_CHANNEL_BUFFER_BYTES)
319#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024) 395#define HDSPM_DMA_AREA_KILOBYTES (HDSPM_DMA_AREA_BYTES/1024)
320 396
397/* revisions >= 230 indicate AES32 card */
398#define HDSPM_AESREVISION 230
399
321struct hdspm_midi { 400struct hdspm_midi {
322 struct hdspm *hdspm; 401 struct hdspm *hdspm;
323 int id; 402 int id;
@@ -336,7 +415,9 @@ struct hdspm {
336 struct snd_pcm_substream *playback_substream; /* and/or capture stream */ 415 struct snd_pcm_substream *playback_substream; /* and/or capture stream */
337 416
338 char *card_name; /* for procinfo */ 417 char *card_name; /* for procinfo */
339 unsigned short firmware_rev; /* dont know if relevant */ 418 unsigned short firmware_rev; /* dont know if relevant (yes if AES32)*/
419
420 unsigned char is_aes32; /* indicates if card is AES32 */
340 421
341 int precise_ptr; /* use precise pointers, to be tested */ 422 int precise_ptr; /* use precise pointers, to be tested */
342 int monitor_outs; /* set up monitoring outs init flag */ 423 int monitor_outs; /* set up monitoring outs init flag */
@@ -453,6 +534,15 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm);
453static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf, 534static void hdspm_set_sgbuf(struct hdspm * hdspm, struct snd_sg_buf *sgbuf,
454 unsigned int reg, int channels); 535 unsigned int reg, int channels);
455 536
537static inline int HDSPM_bit2freq(int n)
538{
539 static int bit2freq_tab[] = { 0, 32000, 44100, 48000, 64000, 88200,
540 96000, 128000, 176400, 192000 };
541 if (n < 1 || n > 9)
542 return 0;
543 return bit2freq_tab[n];
544}
545
456/* Write/read to/from HDSPM with Adresses in Bytes 546/* Write/read to/from HDSPM with Adresses in Bytes
457 not words but only 32Bit writes are allowed */ 547 not words but only 32Bit writes are allowed */
458 548
@@ -544,86 +634,105 @@ static inline int snd_hdspm_use_is_exclusive(struct hdspm * hdspm)
544/* check for external sample rate */ 634/* check for external sample rate */
545static inline int hdspm_external_sample_rate(struct hdspm * hdspm) 635static inline int hdspm_external_sample_rate(struct hdspm * hdspm)
546{ 636{
547 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); 637 if (hdspm->is_aes32) {
548 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister); 638 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
549 unsigned int rate_bits; 639 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
550 int rate = 0; 640 unsigned int timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
641
642 int syncref = hdspm_autosync_ref(hdspm);
643
644 if (syncref == HDSPM_AES32_AUTOSYNC_FROM_WORD &&
645 status & HDSPM_AES32_wcLock)
646 return HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF);
647 if (syncref >= HDSPM_AES32_AUTOSYNC_FROM_AES1 &&
648 syncref <= HDSPM_AES32_AUTOSYNC_FROM_AES8 &&
649 status2 & (HDSPM_LockAES >>
650 (syncref - HDSPM_AES32_AUTOSYNC_FROM_AES1)))
651 return HDSPM_bit2freq((timecode >>
652 (4*(syncref-HDSPM_AES32_AUTOSYNC_FROM_AES1))) & 0xF);
653 return 0;
654 } else {
655 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
656 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
657 unsigned int rate_bits;
658 int rate = 0;
551 659
552 /* if wordclock has synced freq and wordclock is valid */ 660 /* if wordclock has synced freq and wordclock is valid */
553 if ((status2 & HDSPM_wcLock) != 0 && 661 if ((status2 & HDSPM_wcLock) != 0 &&
554 (status & HDSPM_SelSyncRef0) == 0) { 662 (status & HDSPM_SelSyncRef0) == 0) {
555 663
556 rate_bits = status2 & HDSPM_wcFreqMask; 664 rate_bits = status2 & HDSPM_wcFreqMask;
557 665
558 switch (rate_bits) { 666 switch (rate_bits) {
559 case HDSPM_wcFreq32: 667 case HDSPM_wcFreq32:
560 rate = 32000; 668 rate = 32000;
561 break; 669 break;
562 case HDSPM_wcFreq44_1: 670 case HDSPM_wcFreq44_1:
563 rate = 44100; 671 rate = 44100;
564 break; 672 break;
565 case HDSPM_wcFreq48: 673 case HDSPM_wcFreq48:
566 rate = 48000; 674 rate = 48000;
567 break; 675 break;
568 case HDSPM_wcFreq64: 676 case HDSPM_wcFreq64:
569 rate = 64000; 677 rate = 64000;
570 break; 678 break;
571 case HDSPM_wcFreq88_2: 679 case HDSPM_wcFreq88_2:
572 rate = 88200; 680 rate = 88200;
573 break; 681 break;
574 case HDSPM_wcFreq96: 682 case HDSPM_wcFreq96:
575 rate = 96000; 683 rate = 96000;
576 break; 684 break;
577 /* Quadspeed Bit missing ???? */ 685 /* Quadspeed Bit missing ???? */
578 default: 686 default:
579 rate = 0; 687 rate = 0;
580 break; 688 break;
689 }
581 } 690 }
582 }
583 691
584 /* if rate detected and Syncref is Word than have it, word has priority to MADI */ 692 /* if rate detected and Syncref is Word than have it, word has priority to MADI */
585 if (rate != 0 693 if (rate != 0 &&
586 && (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD) 694 (status2 & HDSPM_SelSyncRefMask) == HDSPM_SelSyncRef_WORD)
587 return rate; 695 return rate;
588 696
589 /* maby a madi input (which is taken if sel sync is madi) */ 697 /* maby a madi input (which is taken if sel sync is madi) */
590 if (status & HDSPM_madiLock) { 698 if (status & HDSPM_madiLock) {
591 rate_bits = status & HDSPM_madiFreqMask; 699 rate_bits = status & HDSPM_madiFreqMask;
592 700
593 switch (rate_bits) { 701 switch (rate_bits) {
594 case HDSPM_madiFreq32: 702 case HDSPM_madiFreq32:
595 rate = 32000; 703 rate = 32000;
596 break; 704 break;
597 case HDSPM_madiFreq44_1: 705 case HDSPM_madiFreq44_1:
598 rate = 44100; 706 rate = 44100;
599 break; 707 break;
600 case HDSPM_madiFreq48: 708 case HDSPM_madiFreq48:
601 rate = 48000; 709 rate = 48000;
602 break; 710 break;
603 case HDSPM_madiFreq64: 711 case HDSPM_madiFreq64:
604 rate = 64000; 712 rate = 64000;
605 break; 713 break;
606 case HDSPM_madiFreq88_2: 714 case HDSPM_madiFreq88_2:
607 rate = 88200; 715 rate = 88200;
608 break; 716 break;
609 case HDSPM_madiFreq96: 717 case HDSPM_madiFreq96:
610 rate = 96000; 718 rate = 96000;
611 break; 719 break;
612 case HDSPM_madiFreq128: 720 case HDSPM_madiFreq128:
613 rate = 128000; 721 rate = 128000;
614 break; 722 break;
615 case HDSPM_madiFreq176_4: 723 case HDSPM_madiFreq176_4:
616 rate = 176400; 724 rate = 176400;
617 break; 725 break;
618 case HDSPM_madiFreq192: 726 case HDSPM_madiFreq192:
619 rate = 192000; 727 rate = 192000;
620 break; 728 break;
621 default: 729 default:
622 rate = 0; 730 rate = 0;
623 break; 731 break;
732 }
624 } 733 }
734 return rate;
625 } 735 }
626 return rate;
627} 736}
628 737
629/* Latency function */ 738/* Latency function */
@@ -676,7 +785,8 @@ static inline void hdspm_silence_playback(struct hdspm * hdspm)
676 int n = hdspm->period_bytes; 785 int n = hdspm->period_bytes;
677 void *buf = hdspm->playback_buffer; 786 void *buf = hdspm->playback_buffer;
678 787
679 snd_assert(buf != NULL, return); 788 if (buf == NULL)
789 return;
680 790
681 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) { 791 for (i = 0; i < HDSPM_MAX_CHANNELS; i++) {
682 memset(buf, 0, n); 792 memset(buf, 0, n);
@@ -716,6 +826,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
716 int current_rate; 826 int current_rate;
717 int rate_bits; 827 int rate_bits;
718 int not_set = 0; 828 int not_set = 0;
829 int is_single, is_double, is_quad;
719 830
720 /* ASSUMPTION: hdspm->lock is either set, or there is no need for 831 /* ASSUMPTION: hdspm->lock is either set, or there is no need for
721 it (e.g. during module initialization). 832 it (e.g. during module initialization).
@@ -766,43 +877,56 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
766 changes in the read/write routines. 877 changes in the read/write routines.
767 */ 878 */
768 879
880 is_single = (current_rate <= 48000);
881 is_double = (current_rate > 48000 && current_rate <= 96000);
882 is_quad = (current_rate > 96000);
883
769 switch (rate) { 884 switch (rate) {
770 case 32000: 885 case 32000:
771 if (current_rate > 48000) { 886 if (!is_single)
772 reject_if_open = 1; 887 reject_if_open = 1;
773 }
774 rate_bits = HDSPM_Frequency32KHz; 888 rate_bits = HDSPM_Frequency32KHz;
775 break; 889 break;
776 case 44100: 890 case 44100:
777 if (current_rate > 48000) { 891 if (!is_single)
778 reject_if_open = 1; 892 reject_if_open = 1;
779 }
780 rate_bits = HDSPM_Frequency44_1KHz; 893 rate_bits = HDSPM_Frequency44_1KHz;
781 break; 894 break;
782 case 48000: 895 case 48000:
783 if (current_rate > 48000) { 896 if (!is_single)
784 reject_if_open = 1; 897 reject_if_open = 1;
785 }
786 rate_bits = HDSPM_Frequency48KHz; 898 rate_bits = HDSPM_Frequency48KHz;
787 break; 899 break;
788 case 64000: 900 case 64000:
789 if (current_rate <= 48000) { 901 if (!is_double)
790 reject_if_open = 1; 902 reject_if_open = 1;
791 }
792 rate_bits = HDSPM_Frequency64KHz; 903 rate_bits = HDSPM_Frequency64KHz;
793 break; 904 break;
794 case 88200: 905 case 88200:
795 if (current_rate <= 48000) { 906 if (!is_double)
796 reject_if_open = 1; 907 reject_if_open = 1;
797 }
798 rate_bits = HDSPM_Frequency88_2KHz; 908 rate_bits = HDSPM_Frequency88_2KHz;
799 break; 909 break;
800 case 96000: 910 case 96000:
801 if (current_rate <= 48000) { 911 if (!is_double)
802 reject_if_open = 1; 912 reject_if_open = 1;
803 }
804 rate_bits = HDSPM_Frequency96KHz; 913 rate_bits = HDSPM_Frequency96KHz;
805 break; 914 break;
915 case 128000:
916 if (!is_quad)
917 reject_if_open = 1;
918 rate_bits = HDSPM_Frequency128KHz;
919 break;
920 case 176400:
921 if (!is_quad)
922 reject_if_open = 1;
923 rate_bits = HDSPM_Frequency176_4KHz;
924 break;
925 case 192000:
926 if (!is_quad)
927 reject_if_open = 1;
928 rate_bits = HDSPM_Frequency192KHz;
929 break;
806 default: 930 default:
807 return -EINVAL; 931 return -EINVAL;
808 } 932 }
@@ -819,7 +943,7 @@ static int hdspm_set_rate(struct hdspm * hdspm, int rate, int called_internally)
819 hdspm->control_register |= rate_bits; 943 hdspm->control_register |= rate_bits;
820 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); 944 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
821 945
822 if (rate > 64000) 946 if (rate > 96000 /* 64000*/)
823 hdspm->channel_map = channel_map_madi_qs; 947 hdspm->channel_map = channel_map_madi_qs;
824 else if (rate > 48000) 948 else if (rate > 48000)
825 hdspm->channel_map = channel_map_madi_ds; 949 hdspm->channel_map = channel_map_madi_ds;
@@ -1455,11 +1579,27 @@ static int hdspm_pref_sync_ref(struct hdspm * hdspm)
1455 /* Notice that this looks at the requested sync source, 1579 /* Notice that this looks at the requested sync source,
1456 not the one actually in use. 1580 not the one actually in use.
1457 */ 1581 */
1458 switch (hdspm->control_register & HDSPM_SyncRefMask) { 1582 if (hdspm->is_aes32) {
1459 case HDSPM_SyncRef_Word: 1583 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1460 return HDSPM_SYNC_FROM_WORD; 1584 /* number gives AES index, except for 0 which
1461 case HDSPM_SyncRef_MADI: 1585 corresponds to WordClock */
1462 return HDSPM_SYNC_FROM_MADI; 1586 case 0: return 0;
1587 case HDSPM_SyncRef0: return 1;
1588 case HDSPM_SyncRef1: return 2;
1589 case HDSPM_SyncRef1+HDSPM_SyncRef0: return 3;
1590 case HDSPM_SyncRef2: return 4;
1591 case HDSPM_SyncRef2+HDSPM_SyncRef0: return 5;
1592 case HDSPM_SyncRef2+HDSPM_SyncRef1: return 6;
1593 case HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0: return 7;
1594 case HDSPM_SyncRef3: return 8;
1595 }
1596 } else {
1597 switch (hdspm->control_register & HDSPM_SyncRefMask) {
1598 case HDSPM_SyncRef_Word:
1599 return HDSPM_SYNC_FROM_WORD;
1600 case HDSPM_SyncRef_MADI:
1601 return HDSPM_SYNC_FROM_MADI;
1602 }
1463 } 1603 }
1464 1604
1465 return HDSPM_SYNC_FROM_WORD; 1605 return HDSPM_SYNC_FROM_WORD;
@@ -1469,15 +1609,49 @@ static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
1469{ 1609{
1470 hdspm->control_register &= ~HDSPM_SyncRefMask; 1610 hdspm->control_register &= ~HDSPM_SyncRefMask;
1471 1611
1472 switch (pref) { 1612 if (hdspm->is_aes32) {
1473 case HDSPM_SYNC_FROM_MADI: 1613 switch (pref) {
1474 hdspm->control_register |= HDSPM_SyncRef_MADI; 1614 case 0:
1475 break; 1615 hdspm->control_register |= 0;
1476 case HDSPM_SYNC_FROM_WORD: 1616 break;
1477 hdspm->control_register |= HDSPM_SyncRef_Word; 1617 case 1:
1478 break; 1618 hdspm->control_register |= HDSPM_SyncRef0;
1479 default: 1619 break;
1480 return -1; 1620 case 2:
1621 hdspm->control_register |= HDSPM_SyncRef1;
1622 break;
1623 case 3:
1624 hdspm->control_register |= HDSPM_SyncRef1+HDSPM_SyncRef0;
1625 break;
1626 case 4:
1627 hdspm->control_register |= HDSPM_SyncRef2;
1628 break;
1629 case 5:
1630 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef0;
1631 break;
1632 case 6:
1633 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1;
1634 break;
1635 case 7:
1636 hdspm->control_register |= HDSPM_SyncRef2+HDSPM_SyncRef1+HDSPM_SyncRef0;
1637 break;
1638 case 8:
1639 hdspm->control_register |= HDSPM_SyncRef3;
1640 break;
1641 default:
1642 return -1;
1643 }
1644 } else {
1645 switch (pref) {
1646 case HDSPM_SYNC_FROM_MADI:
1647 hdspm->control_register |= HDSPM_SyncRef_MADI;
1648 break;
1649 case HDSPM_SYNC_FROM_WORD:
1650 hdspm->control_register |= HDSPM_SyncRef_Word;
1651 break;
1652 default:
1653 return -1;
1654 }
1481 } 1655 }
1482 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register); 1656 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
1483 return 0; 1657 return 0;
@@ -1486,18 +1660,36 @@ static int hdspm_set_pref_sync_ref(struct hdspm * hdspm, int pref)
1486static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol, 1660static int snd_hdspm_info_pref_sync_ref(struct snd_kcontrol *kcontrol,
1487 struct snd_ctl_elem_info *uinfo) 1661 struct snd_ctl_elem_info *uinfo)
1488{ 1662{
1489 static char *texts[] = { "Word", "MADI" }; 1663 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
1490 1664
1491 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1665 if (hdspm->is_aes32) {
1492 uinfo->count = 1; 1666 static char *texts[] = { "Word", "AES1", "AES2", "AES3",
1667 "AES4", "AES5", "AES6", "AES7", "AES8" };
1493 1668
1494 uinfo->value.enumerated.items = 2; 1669 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1670 uinfo->count = 1;
1495 1671
1496 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 1672 uinfo->value.enumerated.items = 9;
1497 uinfo->value.enumerated.item = 1673
1498 uinfo->value.enumerated.items - 1; 1674 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1499 strcpy(uinfo->value.enumerated.name, 1675 uinfo->value.enumerated.item =
1500 texts[uinfo->value.enumerated.item]); 1676 uinfo->value.enumerated.items - 1;
1677 strcpy(uinfo->value.enumerated.name,
1678 texts[uinfo->value.enumerated.item]);
1679 } else {
1680 static char *texts[] = { "Word", "MADI" };
1681
1682 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1683 uinfo->count = 1;
1684
1685 uinfo->value.enumerated.items = 2;
1686
1687 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1688 uinfo->value.enumerated.item =
1689 uinfo->value.enumerated.items - 1;
1690 strcpy(uinfo->value.enumerated.name,
1691 texts[uinfo->value.enumerated.item]);
1692 }
1501 return 0; 1693 return 0;
1502} 1694}
1503 1695
@@ -1517,7 +1709,7 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
1517 int change, max; 1709 int change, max;
1518 unsigned int val; 1710 unsigned int val;
1519 1711
1520 max = 2; 1712 max = hdspm->is_aes32 ? 9 : 2;
1521 1713
1522 if (!snd_hdspm_use_is_exclusive(hdspm)) 1714 if (!snd_hdspm_use_is_exclusive(hdspm))
1523 return -EBUSY; 1715 return -EBUSY;
@@ -1542,40 +1734,64 @@ static int snd_hdspm_put_pref_sync_ref(struct snd_kcontrol *kcontrol,
1542 1734
1543static int hdspm_autosync_ref(struct hdspm * hdspm) 1735static int hdspm_autosync_ref(struct hdspm * hdspm)
1544{ 1736{
1545 /* This looks at the autosync selected sync reference */ 1737 if (hdspm->is_aes32) {
1546 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); 1738 unsigned int status = hdspm_read(hdspm, HDSPM_statusRegister);
1547 1739 unsigned int syncref = (status >> HDSPM_AES32_syncref_bit) & 0xF;
1548 switch (status2 & HDSPM_SelSyncRefMask) { 1740 if (syncref == 0)
1549 1741 return HDSPM_AES32_AUTOSYNC_FROM_WORD;
1550 case HDSPM_SelSyncRef_WORD: 1742 if (syncref <= 8)
1551 return HDSPM_AUTOSYNC_FROM_WORD; 1743 return syncref;
1552 1744 return HDSPM_AES32_AUTOSYNC_FROM_NONE;
1553 case HDSPM_SelSyncRef_MADI: 1745 } else {
1554 return HDSPM_AUTOSYNC_FROM_MADI; 1746 /* This looks at the autosync selected sync reference */
1555 1747 unsigned int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
1556 case HDSPM_SelSyncRef_NVALID: 1748
1557 return HDSPM_AUTOSYNC_FROM_NONE; 1749 switch (status2 & HDSPM_SelSyncRefMask) {
1750 case HDSPM_SelSyncRef_WORD:
1751 return HDSPM_AUTOSYNC_FROM_WORD;
1752 case HDSPM_SelSyncRef_MADI:
1753 return HDSPM_AUTOSYNC_FROM_MADI;
1754 case HDSPM_SelSyncRef_NVALID:
1755 return HDSPM_AUTOSYNC_FROM_NONE;
1756 default:
1757 return 0;
1758 }
1558 1759
1559 default:
1560 return 0; 1760 return 0;
1561 } 1761 }
1562
1563 return 0;
1564} 1762}
1565 1763
1566static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol, 1764static int snd_hdspm_info_autosync_ref(struct snd_kcontrol *kcontrol,
1567 struct snd_ctl_elem_info *uinfo) 1765 struct snd_ctl_elem_info *uinfo)
1568{ 1766{
1569 static char *texts[] = { "WordClock", "MADI", "None" }; 1767 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
1570 1768
1571 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; 1769 if (hdspm->is_aes32) {
1572 uinfo->count = 1; 1770 static char *texts[] = { "WordClock", "AES1", "AES2", "AES3",
1573 uinfo->value.enumerated.items = 3; 1771 "AES4", "AES5", "AES6", "AES7", "AES8", "None"};
1574 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items) 1772
1575 uinfo->value.enumerated.item = 1773 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1576 uinfo->value.enumerated.items - 1; 1774 uinfo->count = 1;
1577 strcpy(uinfo->value.enumerated.name, 1775 uinfo->value.enumerated.items = 10;
1578 texts[uinfo->value.enumerated.item]); 1776 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1777 uinfo->value.enumerated.item =
1778 uinfo->value.enumerated.items - 1;
1779 strcpy(uinfo->value.enumerated.name,
1780 texts[uinfo->value.enumerated.item]);
1781 }
1782 else
1783 {
1784 static char *texts[] = { "WordClock", "MADI", "None" };
1785
1786 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1787 uinfo->count = 1;
1788 uinfo->value.enumerated.items = 3;
1789 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
1790 uinfo->value.enumerated.item =
1791 uinfo->value.enumerated.items - 1;
1792 strcpy(uinfo->value.enumerated.name,
1793 texts[uinfo->value.enumerated.item]);
1794 }
1579 return 0; 1795 return 0;
1580} 1796}
1581 1797
@@ -1841,6 +2057,195 @@ static int snd_hdspm_put_safe_mode(struct snd_kcontrol *kcontrol,
1841 return change; 2057 return change;
1842} 2058}
1843 2059
2060#define HDSPM_EMPHASIS(xname, xindex) \
2061{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2062 .name = xname, \
2063 .index = xindex, \
2064 .info = snd_hdspm_info_emphasis, \
2065 .get = snd_hdspm_get_emphasis, \
2066 .put = snd_hdspm_put_emphasis \
2067}
2068
2069static int hdspm_emphasis(struct hdspm * hdspm)
2070{
2071 return (hdspm->control_register & HDSPM_Emphasis) ? 1 : 0;
2072}
2073
2074static int hdspm_set_emphasis(struct hdspm * hdspm, int emp)
2075{
2076 if (emp)
2077 hdspm->control_register |= HDSPM_Emphasis;
2078 else
2079 hdspm->control_register &= ~HDSPM_Emphasis;
2080 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2081
2082 return 0;
2083}
2084
2085static int snd_hdspm_info_emphasis(struct snd_kcontrol *kcontrol,
2086 struct snd_ctl_elem_info *uinfo)
2087{
2088 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2089 uinfo->count = 1;
2090 uinfo->value.integer.min = 0;
2091 uinfo->value.integer.max = 1;
2092 return 0;
2093}
2094
2095static int snd_hdspm_get_emphasis(struct snd_kcontrol *kcontrol,
2096 struct snd_ctl_elem_value *ucontrol)
2097{
2098 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2099
2100 spin_lock_irq(&hdspm->lock);
2101 ucontrol->value.enumerated.item[0] = hdspm_emphasis(hdspm);
2102 spin_unlock_irq(&hdspm->lock);
2103 return 0;
2104}
2105
2106static int snd_hdspm_put_emphasis(struct snd_kcontrol *kcontrol,
2107 struct snd_ctl_elem_value *ucontrol)
2108{
2109 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2110 int change;
2111 unsigned int val;
2112
2113 if (!snd_hdspm_use_is_exclusive(hdspm))
2114 return -EBUSY;
2115 val = ucontrol->value.integer.value[0] & 1;
2116 spin_lock_irq(&hdspm->lock);
2117 change = (int) val != hdspm_emphasis(hdspm);
2118 hdspm_set_emphasis(hdspm, val);
2119 spin_unlock_irq(&hdspm->lock);
2120 return change;
2121}
2122
2123#define HDSPM_DOLBY(xname, xindex) \
2124{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2125 .name = xname, \
2126 .index = xindex, \
2127 .info = snd_hdspm_info_dolby, \
2128 .get = snd_hdspm_get_dolby, \
2129 .put = snd_hdspm_put_dolby \
2130}
2131
2132static int hdspm_dolby(struct hdspm * hdspm)
2133{
2134 return (hdspm->control_register & HDSPM_Dolby) ? 1 : 0;
2135}
2136
2137static int hdspm_set_dolby(struct hdspm * hdspm, int dol)
2138{
2139 if (dol)
2140 hdspm->control_register |= HDSPM_Dolby;
2141 else
2142 hdspm->control_register &= ~HDSPM_Dolby;
2143 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2144
2145 return 0;
2146}
2147
2148static int snd_hdspm_info_dolby(struct snd_kcontrol *kcontrol,
2149 struct snd_ctl_elem_info *uinfo)
2150{
2151 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2152 uinfo->count = 1;
2153 uinfo->value.integer.min = 0;
2154 uinfo->value.integer.max = 1;
2155 return 0;
2156}
2157
2158static int snd_hdspm_get_dolby(struct snd_kcontrol *kcontrol,
2159 struct snd_ctl_elem_value *ucontrol)
2160{
2161 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2162
2163 spin_lock_irq(&hdspm->lock);
2164 ucontrol->value.enumerated.item[0] = hdspm_dolby(hdspm);
2165 spin_unlock_irq(&hdspm->lock);
2166 return 0;
2167}
2168
2169static int snd_hdspm_put_dolby(struct snd_kcontrol *kcontrol,
2170 struct snd_ctl_elem_value *ucontrol)
2171{
2172 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2173 int change;
2174 unsigned int val;
2175
2176 if (!snd_hdspm_use_is_exclusive(hdspm))
2177 return -EBUSY;
2178 val = ucontrol->value.integer.value[0] & 1;
2179 spin_lock_irq(&hdspm->lock);
2180 change = (int) val != hdspm_dolby(hdspm);
2181 hdspm_set_dolby(hdspm, val);
2182 spin_unlock_irq(&hdspm->lock);
2183 return change;
2184}
2185
2186#define HDSPM_PROFESSIONAL(xname, xindex) \
2187{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2188 .name = xname, \
2189 .index = xindex, \
2190 .info = snd_hdspm_info_professional, \
2191 .get = snd_hdspm_get_professional, \
2192 .put = snd_hdspm_put_professional \
2193}
2194
2195static int hdspm_professional(struct hdspm * hdspm)
2196{
2197 return (hdspm->control_register & HDSPM_Professional) ? 1 : 0;
2198}
2199
2200static int hdspm_set_professional(struct hdspm * hdspm, int dol)
2201{
2202 if (dol)
2203 hdspm->control_register |= HDSPM_Professional;
2204 else
2205 hdspm->control_register &= ~HDSPM_Professional;
2206 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2207
2208 return 0;
2209}
2210
2211static int snd_hdspm_info_professional(struct snd_kcontrol *kcontrol,
2212 struct snd_ctl_elem_info *uinfo)
2213{
2214 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
2215 uinfo->count = 1;
2216 uinfo->value.integer.min = 0;
2217 uinfo->value.integer.max = 1;
2218 return 0;
2219}
2220
2221static int snd_hdspm_get_professional(struct snd_kcontrol *kcontrol,
2222 struct snd_ctl_elem_value *ucontrol)
2223{
2224 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2225
2226 spin_lock_irq(&hdspm->lock);
2227 ucontrol->value.enumerated.item[0] = hdspm_professional(hdspm);
2228 spin_unlock_irq(&hdspm->lock);
2229 return 0;
2230}
2231
2232static int snd_hdspm_put_professional(struct snd_kcontrol *kcontrol,
2233 struct snd_ctl_elem_value *ucontrol)
2234{
2235 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2236 int change;
2237 unsigned int val;
2238
2239 if (!snd_hdspm_use_is_exclusive(hdspm))
2240 return -EBUSY;
2241 val = ucontrol->value.integer.value[0] & 1;
2242 spin_lock_irq(&hdspm->lock);
2243 change = (int) val != hdspm_professional(hdspm);
2244 hdspm_set_professional(hdspm, val);
2245 spin_unlock_irq(&hdspm->lock);
2246 return change;
2247}
2248
1844#define HDSPM_INPUT_SELECT(xname, xindex) \ 2249#define HDSPM_INPUT_SELECT(xname, xindex) \
1845{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ 2250{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
1846 .name = xname, \ 2251 .name = xname, \
@@ -1912,6 +2317,163 @@ static int snd_hdspm_put_input_select(struct snd_kcontrol *kcontrol,
1912 return change; 2317 return change;
1913} 2318}
1914 2319
2320#define HDSPM_DS_WIRE(xname, xindex) \
2321{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2322 .name = xname, \
2323 .index = xindex, \
2324 .info = snd_hdspm_info_ds_wire, \
2325 .get = snd_hdspm_get_ds_wire, \
2326 .put = snd_hdspm_put_ds_wire \
2327}
2328
2329static int hdspm_ds_wire(struct hdspm * hdspm)
2330{
2331 return (hdspm->control_register & HDSPM_DS_DoubleWire) ? 1 : 0;
2332}
2333
2334static int hdspm_set_ds_wire(struct hdspm * hdspm, int ds)
2335{
2336 if (ds)
2337 hdspm->control_register |= HDSPM_DS_DoubleWire;
2338 else
2339 hdspm->control_register &= ~HDSPM_DS_DoubleWire;
2340 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2341
2342 return 0;
2343}
2344
2345static int snd_hdspm_info_ds_wire(struct snd_kcontrol *kcontrol,
2346 struct snd_ctl_elem_info *uinfo)
2347{
2348 static char *texts[] = { "Single", "Double" };
2349
2350 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2351 uinfo->count = 1;
2352 uinfo->value.enumerated.items = 2;
2353
2354 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2355 uinfo->value.enumerated.item =
2356 uinfo->value.enumerated.items - 1;
2357 strcpy(uinfo->value.enumerated.name,
2358 texts[uinfo->value.enumerated.item]);
2359
2360 return 0;
2361}
2362
2363static int snd_hdspm_get_ds_wire(struct snd_kcontrol *kcontrol,
2364 struct snd_ctl_elem_value *ucontrol)
2365{
2366 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2367
2368 spin_lock_irq(&hdspm->lock);
2369 ucontrol->value.enumerated.item[0] = hdspm_ds_wire(hdspm);
2370 spin_unlock_irq(&hdspm->lock);
2371 return 0;
2372}
2373
2374static int snd_hdspm_put_ds_wire(struct snd_kcontrol *kcontrol,
2375 struct snd_ctl_elem_value *ucontrol)
2376{
2377 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2378 int change;
2379 unsigned int val;
2380
2381 if (!snd_hdspm_use_is_exclusive(hdspm))
2382 return -EBUSY;
2383 val = ucontrol->value.integer.value[0] & 1;
2384 spin_lock_irq(&hdspm->lock);
2385 change = (int) val != hdspm_ds_wire(hdspm);
2386 hdspm_set_ds_wire(hdspm, val);
2387 spin_unlock_irq(&hdspm->lock);
2388 return change;
2389}
2390
2391#define HDSPM_QS_WIRE(xname, xindex) \
2392{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2393 .name = xname, \
2394 .index = xindex, \
2395 .info = snd_hdspm_info_qs_wire, \
2396 .get = snd_hdspm_get_qs_wire, \
2397 .put = snd_hdspm_put_qs_wire \
2398}
2399
2400static int hdspm_qs_wire(struct hdspm * hdspm)
2401{
2402 if (hdspm->control_register & HDSPM_QS_DoubleWire)
2403 return 1;
2404 if (hdspm->control_register & HDSPM_QS_QuadWire)
2405 return 2;
2406 return 0;
2407}
2408
2409static int hdspm_set_qs_wire(struct hdspm * hdspm, int mode)
2410{
2411 hdspm->control_register &= ~(HDSPM_QS_DoubleWire | HDSPM_QS_QuadWire);
2412 switch (mode) {
2413 case 0:
2414 break;
2415 case 1:
2416 hdspm->control_register |= HDSPM_QS_DoubleWire;
2417 break;
2418 case 2:
2419 hdspm->control_register |= HDSPM_QS_QuadWire;
2420 break;
2421 }
2422 hdspm_write(hdspm, HDSPM_controlRegister, hdspm->control_register);
2423
2424 return 0;
2425}
2426
2427static int snd_hdspm_info_qs_wire(struct snd_kcontrol *kcontrol,
2428 struct snd_ctl_elem_info *uinfo)
2429{
2430 static char *texts[] = { "Single", "Double", "Quad" };
2431
2432 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
2433 uinfo->count = 1;
2434 uinfo->value.enumerated.items = 3;
2435
2436 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
2437 uinfo->value.enumerated.item =
2438 uinfo->value.enumerated.items - 1;
2439 strcpy(uinfo->value.enumerated.name,
2440 texts[uinfo->value.enumerated.item]);
2441
2442 return 0;
2443}
2444
2445static int snd_hdspm_get_qs_wire(struct snd_kcontrol *kcontrol,
2446 struct snd_ctl_elem_value *ucontrol)
2447{
2448 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2449
2450 spin_lock_irq(&hdspm->lock);
2451 ucontrol->value.enumerated.item[0] = hdspm_qs_wire(hdspm);
2452 spin_unlock_irq(&hdspm->lock);
2453 return 0;
2454}
2455
2456static int snd_hdspm_put_qs_wire(struct snd_kcontrol *kcontrol,
2457 struct snd_ctl_elem_value *ucontrol)
2458{
2459 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2460 int change;
2461 int val;
2462
2463 if (!snd_hdspm_use_is_exclusive(hdspm))
2464 return -EBUSY;
2465 val = ucontrol->value.integer.value[0];
2466 if (val < 0)
2467 val = 0;
2468 if (val > 2)
2469 val = 2;
2470 spin_lock_irq(&hdspm->lock);
2471 change = (int) val != hdspm_qs_wire(hdspm);
2472 hdspm_set_qs_wire(hdspm, val);
2473 spin_unlock_irq(&hdspm->lock);
2474 return change;
2475}
2476
1915/* Simple Mixer 2477/* Simple Mixer
1916 deprecated since to much faders ??? 2478 deprecated since to much faders ???
1917 MIXER interface says output (source, destination, value) 2479 MIXER interface says output (source, destination, value)
@@ -2135,14 +2697,24 @@ static int snd_hdspm_info_sync_check(struct snd_kcontrol *kcontrol,
2135 2697
2136static int hdspm_wc_sync_check(struct hdspm * hdspm) 2698static int hdspm_wc_sync_check(struct hdspm * hdspm)
2137{ 2699{
2138 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2); 2700 if (hdspm->is_aes32) {
2139 if (status2 & HDSPM_wcLock) { 2701 int status = hdspm_read(hdspm, HDSPM_statusRegister);
2140 if (status2 & HDSPM_wcSync) 2702 if (status & HDSPM_AES32_wcLock) {
2703 /* I don't know how to differenciate sync from lock.
2704 Doing as if sync for now */
2141 return 2; 2705 return 2;
2142 else 2706 }
2143 return 1; 2707 return 0;
2708 } else {
2709 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2710 if (status2 & HDSPM_wcLock) {
2711 if (status2 & HDSPM_wcSync)
2712 return 2;
2713 else
2714 return 1;
2715 }
2716 return 0;
2144 } 2717 }
2145 return 0;
2146} 2718}
2147 2719
2148static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol, 2720static int snd_hdspm_get_wc_sync_check(struct snd_kcontrol *kcontrol,
@@ -2188,9 +2760,43 @@ static int snd_hdspm_get_madisync_sync_check(struct snd_kcontrol *kcontrol,
2188} 2760}
2189 2761
2190 2762
2763#define HDSPM_AES_SYNC_CHECK(xname, xindex) \
2764{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
2765 .name = xname, \
2766 .index = xindex, \
2767 .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, \
2768 .info = snd_hdspm_info_sync_check, \
2769 .get = snd_hdspm_get_aes_sync_check \
2770}
2771
2772static int hdspm_aes_sync_check(struct hdspm * hdspm, int idx)
2773{
2774 int status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
2775 if (status2 & (HDSPM_LockAES >> idx)) {
2776 /* I don't know how to differenciate sync from lock.
2777 Doing as if sync for now */
2778 return 2;
2779 }
2780 return 0;
2781}
2782
2783static int snd_hdspm_get_aes_sync_check(struct snd_kcontrol *kcontrol,
2784 struct snd_ctl_elem_value *ucontrol)
2785{
2786 int offset;
2787 struct hdspm *hdspm = snd_kcontrol_chip(kcontrol);
2788
2789 offset = ucontrol->id.index - 1;
2790 if (offset < 0 || offset >= 8)
2791 return -EINVAL;
2792
2793 ucontrol->value.enumerated.item[0] =
2794 hdspm_aes_sync_check(hdspm, offset);
2795 return 0;
2796}
2191 2797
2192 2798
2193static struct snd_kcontrol_new snd_hdspm_controls[] = { 2799static struct snd_kcontrol_new snd_hdspm_controls_madi[] = {
2194 2800
2195 HDSPM_MIXER("Mixer", 0), 2801 HDSPM_MIXER("Mixer", 0),
2196/* 'Sample Clock Source' complies with the alsa control naming scheme */ 2802/* 'Sample Clock Source' complies with the alsa control naming scheme */
@@ -2211,6 +2817,29 @@ static struct snd_kcontrol_new snd_hdspm_controls[] = {
2211 HDSPM_INPUT_SELECT("Input Select", 0), 2817 HDSPM_INPUT_SELECT("Input Select", 0),
2212}; 2818};
2213 2819
2820static struct snd_kcontrol_new snd_hdspm_controls_aes32[] = {
2821
2822 HDSPM_MIXER("Mixer", 0),
2823/* 'Sample Clock Source' complies with the alsa control naming scheme */
2824 HDSPM_CLOCK_SOURCE("Sample Clock Source", 0),
2825
2826 HDSPM_SYSTEM_CLOCK_MODE("System Clock Mode", 0),
2827 HDSPM_PREF_SYNC_REF("Preferred Sync Reference", 0),
2828 HDSPM_AUTOSYNC_REF("AutoSync Reference", 0),
2829 HDSPM_SYSTEM_SAMPLE_RATE("System Sample Rate", 0),
2830/* 'External Rate' complies with the alsa control naming scheme */
2831 HDSPM_AUTOSYNC_SAMPLE_RATE("External Rate", 0),
2832 HDSPM_WC_SYNC_CHECK("Word Clock Lock Status", 0),
2833/* HDSPM_AES_SYNC_CHECK("AES Lock Status", 0),*/ /* created in snd_hdspm_create_controls() */
2834 HDSPM_LINE_OUT("Line Out", 0),
2835 HDSPM_EMPHASIS("Emphasis", 0),
2836 HDSPM_DOLBY("Non Audio", 0),
2837 HDSPM_PROFESSIONAL("Professional", 0),
2838 HDSPM_C_TMS("Clear Track Marker", 0),
2839 HDSPM_DS_WIRE("Double Speed Wire Mode", 0),
2840 HDSPM_QS_WIRE("Quad Speed Wire Mode", 0),
2841};
2842
2214static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER; 2843static struct snd_kcontrol_new snd_hdspm_playback_mixer = HDSPM_PLAYBACK_MIXER;
2215 2844
2216 2845
@@ -2245,20 +2874,40 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm
2245 struct snd_kcontrol *kctl; 2874 struct snd_kcontrol *kctl;
2246 2875
2247 /* add control list first */ 2876 /* add control list first */
2248 2877 if (hdspm->is_aes32) {
2249 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls); idx++) { 2878 struct snd_kcontrol_new aes_sync_ctl =
2250 if ((err = 2879 HDSPM_AES_SYNC_CHECK("AES Lock Status", 0);
2251 snd_ctl_add(card, kctl = 2880
2252 snd_ctl_new1(&snd_hdspm_controls[idx], 2881 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_aes32);
2253 hdspm))) < 0) { 2882 idx++) {
2254 return err; 2883 err = snd_ctl_add(card,
2884 snd_ctl_new1(&snd_hdspm_controls_aes32[idx],
2885 hdspm));
2886 if (err < 0)
2887 return err;
2888 }
2889 for (idx = 1; idx <= 8; idx++) {
2890 aes_sync_ctl.index = idx;
2891 err = snd_ctl_add(card,
2892 snd_ctl_new1(&aes_sync_ctl, hdspm));
2893 if (err < 0)
2894 return err;
2895 }
2896 } else {
2897 for (idx = 0; idx < ARRAY_SIZE(snd_hdspm_controls_madi);
2898 idx++) {
2899 err = snd_ctl_add(card,
2900 snd_ctl_new1(&snd_hdspm_controls_madi[idx],
2901 hdspm));
2902 if (err < 0)
2903 return err;
2255 } 2904 }
2256 } 2905 }
2257 2906
2258 /* Channel playback mixer as default control 2907 /* Channel playback mixer as default control
2259 Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer 2908Note: the whole matrix would be 128*HDSPM_MIXER_CHANNELS Faders, thats too big for any alsamixer
2260 they are accesible via special IOCTL on hwdep 2909they are accesible via special IOCTL on hwdep
2261 and the mixer 2dimensional mixer control */ 2910and the mixer 2dimensional mixer control */
2262 2911
2263 snd_hdspm_playback_mixer.name = "Chn"; 2912 snd_hdspm_playback_mixer.name = "Chn";
2264 limit = HDSPM_MAX_CHANNELS; 2913 limit = HDSPM_MAX_CHANNELS;
@@ -2289,7 +2938,8 @@ static int snd_hdspm_create_controls(struct snd_card *card, struct hdspm * hdspm
2289 ------------------------------------------------------------*/ 2938 ------------------------------------------------------------*/
2290 2939
2291static void 2940static void
2292snd_hdspm_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer) 2941snd_hdspm_proc_read_madi(struct snd_info_entry * entry,
2942 struct snd_info_buffer *buffer)
2293{ 2943{
2294 struct hdspm *hdspm = (struct hdspm *) entry->private_data; 2944 struct hdspm *hdspm = (struct hdspm *) entry->private_data;
2295 unsigned int status; 2945 unsigned int status;
@@ -2420,11 +3070,10 @@ snd_hdspm_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffe
2420 clock_source = "Error"; 3070 clock_source = "Error";
2421 } 3071 }
2422 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source); 3072 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
2423 if (!(hdspm->control_register & HDSPM_ClockModeMaster)) { 3073 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
2424 system_clock_mode = "Slave"; 3074 system_clock_mode = "Slave";
2425 } else { 3075 else
2426 system_clock_mode = "Master"; 3076 system_clock_mode = "Master";
2427 }
2428 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode); 3077 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
2429 3078
2430 switch (hdspm_pref_sync_ref(hdspm)) { 3079 switch (hdspm_pref_sync_ref(hdspm)) {
@@ -2484,13 +3133,213 @@ snd_hdspm_proc_read(struct snd_info_entry * entry, struct snd_info_buffer *buffe
2484 snd_iprintf(buffer, "\n"); 3133 snd_iprintf(buffer, "\n");
2485} 3134}
2486 3135
3136static void
3137snd_hdspm_proc_read_aes32(struct snd_info_entry * entry,
3138 struct snd_info_buffer *buffer)
3139{
3140 struct hdspm *hdspm = (struct hdspm *) entry->private_data;
3141 unsigned int status;
3142 unsigned int status2;
3143 unsigned int timecode;
3144 int pref_syncref;
3145 char *autosync_ref;
3146 char *system_clock_mode;
3147 char *clock_source;
3148 int x;
3149
3150 status = hdspm_read(hdspm, HDSPM_statusRegister);
3151 status2 = hdspm_read(hdspm, HDSPM_statusRegister2);
3152 timecode = hdspm_read(hdspm, HDSPM_timecodeRegister);
3153
3154 snd_iprintf(buffer, "%s (Card #%d) Rev.%x\n",
3155 hdspm->card_name, hdspm->card->number + 1,
3156 hdspm->firmware_rev);
3157
3158 snd_iprintf(buffer, "IRQ: %d Registers bus: 0x%lx VM: 0x%lx\n",
3159 hdspm->irq, hdspm->port, (unsigned long)hdspm->iobase);
3160
3161 snd_iprintf(buffer, "--- System ---\n");
3162
3163 snd_iprintf(buffer,
3164 "IRQ Pending: Audio=%d, MIDI0=%d, MIDI1=%d, IRQcount=%d\n",
3165 status & HDSPM_audioIRQPending,
3166 (status & HDSPM_midi0IRQPending) ? 1 : 0,
3167 (status & HDSPM_midi1IRQPending) ? 1 : 0,
3168 hdspm->irq_count);
3169 snd_iprintf(buffer,
3170 "HW pointer: id = %d, rawptr = %d (%d->%d) estimated= %ld (bytes)\n",
3171 ((status & HDSPM_BufferID) ? 1 : 0),
3172 (status & HDSPM_BufferPositionMask),
3173 (status & HDSPM_BufferPositionMask) % (2 *
3174 (int)hdspm->
3175 period_bytes),
3176 ((status & HDSPM_BufferPositionMask) -
3177 64) % (2 * (int)hdspm->period_bytes),
3178 (long) hdspm_hw_pointer(hdspm) * 4);
3179
3180 snd_iprintf(buffer,
3181 "MIDI FIFO: Out1=0x%x, Out2=0x%x, In1=0x%x, In2=0x%x \n",
3182 hdspm_read(hdspm, HDSPM_midiStatusOut0) & 0xFF,
3183 hdspm_read(hdspm, HDSPM_midiStatusOut1) & 0xFF,
3184 hdspm_read(hdspm, HDSPM_midiStatusIn0) & 0xFF,
3185 hdspm_read(hdspm, HDSPM_midiStatusIn1) & 0xFF);
3186 snd_iprintf(buffer,
3187 "Register: ctrl1=0x%x, ctrl2=0x%x, status1=0x%x, status2=0x%x, timecode=0x%x\n",
3188 hdspm->control_register, hdspm->control2_register,
3189 status, status2, timecode);
3190
3191 snd_iprintf(buffer, "--- Settings ---\n");
3192
3193 x = 1 << (6 +
3194 hdspm_decode_latency(hdspm->
3195 control_register &
3196 HDSPM_LatencyMask));
3197
3198 snd_iprintf(buffer,
3199 "Size (Latency): %d samples (2 periods of %lu bytes)\n",
3200 x, (unsigned long) hdspm->period_bytes);
3201
3202 snd_iprintf(buffer, "Line out: %s, Precise Pointer: %s\n",
3203 (hdspm->
3204 control_register & HDSPM_LineOut) ? "on " : "off",
3205 (hdspm->precise_ptr) ? "on" : "off");
3206
3207 snd_iprintf(buffer,
3208 "ClearTrackMarker %s, Emphasis %s, Dolby %s\n",
3209 (hdspm->
3210 control_register & HDSPM_clr_tms) ? "on" : "off",
3211 (hdspm->
3212 control_register & HDSPM_Emphasis) ? "on" : "off",
3213 (hdspm->
3214 control_register & HDSPM_Dolby) ? "on" : "off");
3215
3216 switch (hdspm_clock_source(hdspm)) {
3217 case HDSPM_CLOCK_SOURCE_AUTOSYNC:
3218 clock_source = "AutoSync";
3219 break;
3220 case HDSPM_CLOCK_SOURCE_INTERNAL_32KHZ:
3221 clock_source = "Internal 32 kHz";
3222 break;
3223 case HDSPM_CLOCK_SOURCE_INTERNAL_44_1KHZ:
3224 clock_source = "Internal 44.1 kHz";
3225 break;
3226 case HDSPM_CLOCK_SOURCE_INTERNAL_48KHZ:
3227 clock_source = "Internal 48 kHz";
3228 break;
3229 case HDSPM_CLOCK_SOURCE_INTERNAL_64KHZ:
3230 clock_source = "Internal 64 kHz";
3231 break;
3232 case HDSPM_CLOCK_SOURCE_INTERNAL_88_2KHZ:
3233 clock_source = "Internal 88.2 kHz";
3234 break;
3235 case HDSPM_CLOCK_SOURCE_INTERNAL_96KHZ:
3236 clock_source = "Internal 96 kHz";
3237 break;
3238 case HDSPM_CLOCK_SOURCE_INTERNAL_128KHZ:
3239 clock_source = "Internal 128 kHz";
3240 break;
3241 case HDSPM_CLOCK_SOURCE_INTERNAL_176_4KHZ:
3242 clock_source = "Internal 176.4 kHz";
3243 break;
3244 case HDSPM_CLOCK_SOURCE_INTERNAL_192KHZ:
3245 clock_source = "Internal 192 kHz";
3246 break;
3247 default:
3248 clock_source = "Error";
3249 }
3250 snd_iprintf(buffer, "Sample Clock Source: %s\n", clock_source);
3251 if (!(hdspm->control_register & HDSPM_ClockModeMaster))
3252 system_clock_mode = "Slave";
3253 else
3254 system_clock_mode = "Master";
3255 snd_iprintf(buffer, "System Clock Mode: %s\n", system_clock_mode);
3256
3257 pref_syncref = hdspm_pref_sync_ref(hdspm);
3258 if (pref_syncref == 0)
3259 snd_iprintf(buffer, "Preferred Sync Reference: Word Clock\n");
3260 else
3261 snd_iprintf(buffer, "Preferred Sync Reference: AES%d\n",
3262 pref_syncref);
3263
3264 snd_iprintf(buffer, "System Clock Frequency: %d\n",
3265 hdspm->system_sample_rate);
3266
3267 snd_iprintf(buffer, "Double speed: %s\n",
3268 hdspm->control_register & HDSPM_DS_DoubleWire?
3269 "Double wire" : "Single wire");
3270 snd_iprintf(buffer, "Quad speed: %s\n",
3271 hdspm->control_register & HDSPM_QS_DoubleWire?
3272 "Double wire" :
3273 hdspm->control_register & HDSPM_QS_QuadWire?
3274 "Quad wire" : "Single wire");
3275
3276 snd_iprintf(buffer, "--- Status:\n");
3277
3278 snd_iprintf(buffer, "Word: %s Frequency: %d\n",
3279 (status & HDSPM_AES32_wcLock)? "Sync " : "No Lock",
3280 HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
3281
3282 for (x = 0; x < 8; x++) {
3283 snd_iprintf(buffer, "AES%d: %s Frequency: %d\n",
3284 x+1,
3285 (status2 & (HDSPM_LockAES >> x))? "Sync ": "No Lock",
3286 HDSPM_bit2freq((timecode >> (4*x)) & 0xF));
3287 }
3288
3289 switch (hdspm_autosync_ref(hdspm)) {
3290 case HDSPM_AES32_AUTOSYNC_FROM_NONE: autosync_ref="None"; break;
3291 case HDSPM_AES32_AUTOSYNC_FROM_WORD: autosync_ref="Word Clock"; break;
3292 case HDSPM_AES32_AUTOSYNC_FROM_AES1: autosync_ref="AES1"; break;
3293 case HDSPM_AES32_AUTOSYNC_FROM_AES2: autosync_ref="AES2"; break;
3294 case HDSPM_AES32_AUTOSYNC_FROM_AES3: autosync_ref="AES3"; break;
3295 case HDSPM_AES32_AUTOSYNC_FROM_AES4: autosync_ref="AES4"; break;
3296 case HDSPM_AES32_AUTOSYNC_FROM_AES5: autosync_ref="AES5"; break;
3297 case HDSPM_AES32_AUTOSYNC_FROM_AES6: autosync_ref="AES6"; break;
3298 case HDSPM_AES32_AUTOSYNC_FROM_AES7: autosync_ref="AES7"; break;
3299 case HDSPM_AES32_AUTOSYNC_FROM_AES8: autosync_ref="AES8"; break;
3300 default: autosync_ref = "---"; break;
3301 }
3302 snd_iprintf(buffer, "AutoSync ref = %s\n", autosync_ref);
3303
3304 snd_iprintf(buffer, "\n");
3305}
3306
3307#ifdef CONFIG_SND_DEBUG
3308static void
3309snd_hdspm_proc_read_debug(struct snd_info_entry * entry,
3310 struct snd_info_buffer *buffer)
3311{
3312 struct hdspm *hdspm = (struct hdspm *)entry->private_data;
3313
3314 int j,i;
3315
3316 for (i = 0; i < 256 /* 1024*64 */; i += j)
3317 {
3318 snd_iprintf(buffer, "0x%08X: ", i);
3319 for (j = 0; j < 16; j += 4)
3320 snd_iprintf(buffer, "%08X ", hdspm_read(hdspm, i + j));
3321 snd_iprintf(buffer, "\n");
3322 }
3323}
3324#endif
3325
3326
3327
2487static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm) 3328static void __devinit snd_hdspm_proc_init(struct hdspm * hdspm)
2488{ 3329{
2489 struct snd_info_entry *entry; 3330 struct snd_info_entry *entry;
2490 3331
2491 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry)) 3332 if (!snd_card_proc_new(hdspm->card, "hdspm", &entry))
2492 snd_info_set_text_ops(entry, hdspm, 3333 snd_info_set_text_ops(entry, hdspm,
2493 snd_hdspm_proc_read); 3334 hdspm->is_aes32 ?
3335 snd_hdspm_proc_read_aes32 :
3336 snd_hdspm_proc_read_madi);
3337#ifdef CONFIG_SND_DEBUG
3338 /* debug file to read all hdspm registers */
3339 if (!snd_card_proc_new(hdspm->card, "debug", &entry))
3340 snd_info_set_text_ops(entry, hdspm,
3341 snd_hdspm_proc_read_debug);
3342#endif
2494} 3343}
2495 3344
2496/*------------------------------------------------------------ 3345/*------------------------------------------------------------
@@ -2507,13 +3356,20 @@ static int snd_hdspm_set_defaults(struct hdspm * hdspm)
2507 3356
2508 /* set defaults: */ 3357 /* set defaults: */
2509 3358
2510 hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */ 3359 if (hdspm->is_aes32)
2511 hdspm_encode_latency(7) | /* latency maximum = 8192 samples */ 3360 hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
2512 HDSPM_InputCoaxial | /* Input Coax not Optical */ 3361 hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
2513 HDSPM_SyncRef_MADI | /* Madi is syncclock */ 3362 HDSPM_SyncRef0 | /* AES1 is syncclock */
2514 HDSPM_LineOut | /* Analog output in */ 3363 HDSPM_LineOut | /* Analog output in */
2515 HDSPM_TX_64ch | /* transmit in 64ch mode */ 3364 HDSPM_Professional; /* Professional mode */
2516 HDSPM_AutoInp; /* AutoInput chossing (takeover) */ 3365 else
3366 hdspm->control_register = HDSPM_ClockModeMaster | /* Master Cloack Mode on */
3367 hdspm_encode_latency(7) | /* latency maximum = 8192 samples */
3368 HDSPM_InputCoaxial | /* Input Coax not Optical */
3369 HDSPM_SyncRef_MADI | /* Madi is syncclock */
3370 HDSPM_LineOut | /* Analog output in */
3371 HDSPM_TX_64ch | /* transmit in 64ch mode */
3372 HDSPM_AutoInp; /* AutoInput chossing (takeover) */
2517 3373
2518 /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */ 3374 /* ! HDSPM_Frequency0|HDSPM_Frequency1 = 44.1khz */
2519 /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */ 3375 /* ! HDSPM_DoubleSpeed HDSPM_QuadSpeed = normal speed */
@@ -2822,6 +3678,8 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
2822 3678
2823 hdspm->playback_buffer = 3679 hdspm->playback_buffer =
2824 (unsigned char *) substream->runtime->dma_area; 3680 (unsigned char *) substream->runtime->dma_area;
3681 snd_printdd("Allocated sample buffer for playback at %p\n",
3682 hdspm->playback_buffer);
2825 } else { 3683 } else {
2826 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn, 3684 hdspm_set_sgbuf(hdspm, sgbuf, HDSPM_pageAddressBufferIn,
2827 params_channels(params)); 3685 params_channels(params));
@@ -2831,7 +3689,15 @@ static int snd_hdspm_hw_params(struct snd_pcm_substream *substream,
2831 3689
2832 hdspm->capture_buffer = 3690 hdspm->capture_buffer =
2833 (unsigned char *) substream->runtime->dma_area; 3691 (unsigned char *) substream->runtime->dma_area;
3692 snd_printdd("Allocated sample buffer for capture at %p\n",
3693 hdspm->capture_buffer);
2834 } 3694 }
3695 /*
3696 snd_printdd("Allocated sample buffer for %s at 0x%08X\n",
3697 substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
3698 "playback" : "capture",
3699 snd_pcm_sgbuf_get_addr(sgbuf, 0));
3700 */
2835 return 0; 3701 return 0;
2836} 3702}
2837 3703
@@ -2982,9 +3848,10 @@ static struct snd_pcm_hardware snd_hdspm_playback_subinfo = {
2982 SNDRV_PCM_RATE_44100 | 3848 SNDRV_PCM_RATE_44100 |
2983 SNDRV_PCM_RATE_48000 | 3849 SNDRV_PCM_RATE_48000 |
2984 SNDRV_PCM_RATE_64000 | 3850 SNDRV_PCM_RATE_64000 |
2985 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), 3851 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
3852 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000 ),
2986 .rate_min = 32000, 3853 .rate_min = 32000,
2987 .rate_max = 96000, 3854 .rate_max = 192000,
2988 .channels_min = 1, 3855 .channels_min = 1,
2989 .channels_max = HDSPM_MAX_CHANNELS, 3856 .channels_max = HDSPM_MAX_CHANNELS,
2990 .buffer_bytes_max = 3857 .buffer_bytes_max =
@@ -3006,9 +3873,10 @@ static struct snd_pcm_hardware snd_hdspm_capture_subinfo = {
3006 SNDRV_PCM_RATE_44100 | 3873 SNDRV_PCM_RATE_44100 |
3007 SNDRV_PCM_RATE_48000 | 3874 SNDRV_PCM_RATE_48000 |
3008 SNDRV_PCM_RATE_64000 | 3875 SNDRV_PCM_RATE_64000 |
3009 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000), 3876 SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 |
3877 SNDRV_PCM_RATE_176400 | SNDRV_PCM_RATE_192000),
3010 .rate_min = 32000, 3878 .rate_min = 32000,
3011 .rate_max = 96000, 3879 .rate_max = 192000,
3012 .channels_min = 1, 3880 .channels_min = 1,
3013 .channels_max = HDSPM_MAX_CHANNELS, 3881 .channels_max = HDSPM_MAX_CHANNELS,
3014 .buffer_bytes_max = 3882 .buffer_bytes_max =
@@ -3315,7 +4183,8 @@ static int __devinit snd_hdspm_preallocate_memory(struct hdspm * hdspm)
3315 4183
3316 pcm = hdspm->pcm; 4184 pcm = hdspm->pcm;
3317 4185
3318 wanted = HDSPM_DMA_AREA_BYTES + 4096; /* dont know why, but it works */ 4186/* wanted = HDSPM_DMA_AREA_BYTES + 4096;*/ /* dont know why, but it works */
4187 wanted = HDSPM_DMA_AREA_BYTES;
3319 4188
3320 if ((err = 4189 if ((err =
3321 snd_pcm_lib_preallocate_pages_for_all(pcm, 4190 snd_pcm_lib_preallocate_pages_for_all(pcm,
@@ -3467,9 +4336,16 @@ static int __devinit snd_hdspm_create(struct snd_card *card, struct hdspm * hdsp
3467 pci_read_config_word(hdspm->pci, 4336 pci_read_config_word(hdspm->pci,
3468 PCI_CLASS_REVISION, &hdspm->firmware_rev); 4337 PCI_CLASS_REVISION, &hdspm->firmware_rev);
3469 4338
3470 strcpy(card->driver, "HDSPM"); 4339 hdspm->is_aes32 = (hdspm->firmware_rev >= HDSPM_AESREVISION);
4340
3471 strcpy(card->mixername, "Xilinx FPGA"); 4341 strcpy(card->mixername, "Xilinx FPGA");
3472 hdspm->card_name = "RME HDSPM MADI"; 4342 if (hdspm->is_aes32) {
4343 strcpy(card->driver, "HDSPAES32");
4344 hdspm->card_name = "RME HDSPM AES32";
4345 } else {
4346 strcpy(card->driver, "HDSPM");
4347 hdspm->card_name = "RME HDSPM MADI";
4348 }
3473 4349
3474 if ((err = pci_enable_device(pci)) < 0) 4350 if ((err = pci_enable_device(pci)) < 0)
3475 return err; 4351 return err;
diff --git a/sound/pci/trident/trident_main.c b/sound/pci/trident/trident_main.c
index 474f2d451ae8..3bff32167f66 100644
--- a/sound/pci/trident/trident_main.c
+++ b/sound/pci/trident/trident_main.c
@@ -2627,7 +2627,7 @@ static int snd_trident_vol_control_get(struct snd_kcontrol *kcontrol,
2627 return 0; 2627 return 0;
2628} 2628}
2629 2629
2630static DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0); 2630static const DECLARE_TLV_DB_SCALE(db_scale_gvol, -6375, 25, 0);
2631 2631
2632static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol, 2632static int snd_trident_vol_control_put(struct snd_kcontrol *kcontrol,
2633 struct snd_ctl_elem_value *ucontrol) 2633 struct snd_ctl_elem_value *ucontrol)
@@ -2844,7 +2844,7 @@ static int snd_trident_pcm_rvol_control_put(struct snd_kcontrol *kcontrol,
2844 return change; 2844 return change;
2845} 2845}
2846 2846
2847static DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1); 2847static const DECLARE_TLV_DB_SCALE(db_scale_crvol, -3175, 25, 1);
2848 2848
2849static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata = 2849static struct snd_kcontrol_new snd_trident_pcm_rvol_control __devinitdata =
2850{ 2850{
diff --git a/sound/pci/via82xx.c b/sound/pci/via82xx.c
index a572b018807f..a28992269f5e 100644
--- a/sound/pci/via82xx.c
+++ b/sound/pci/via82xx.c
@@ -1699,7 +1699,7 @@ static int snd_via8233_pcmdxs_volume_put(struct snd_kcontrol *kcontrol,
1699 return change; 1699 return change;
1700} 1700}
1701 1701
1702static DECLARE_TLV_DB_SCALE(db_scale_dxs, -9450, 150, 1); 1702static const DECLARE_TLV_DB_SCALE(db_scale_dxs, -9450, 150, 1);
1703 1703
1704static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = { 1704static struct snd_kcontrol_new snd_via8233_pcmdxs_volume_control __devinitdata = {
1705 .name = "PCM Playback Volume", 1705 .name = "PCM Playback Volume",
@@ -1823,7 +1823,7 @@ static int __devinit snd_via82xx_mixer_new(struct via82xx *chip, const char *qui
1823 ac97.private_data = chip; 1823 ac97.private_data = chip;
1824 ac97.private_free = snd_via82xx_mixer_free_ac97; 1824 ac97.private_free = snd_via82xx_mixer_free_ac97;
1825 ac97.pci = chip->pci; 1825 ac97.pci = chip->pci;
1826 ac97.scaps = AC97_SCAP_SKIP_MODEM; 1826 ac97.scaps = AC97_SCAP_SKIP_MODEM | AC97_SCAP_POWER_SAVE;
1827 if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) 1827 if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)
1828 return err; 1828 return err;
1829 1829
@@ -2357,93 +2357,59 @@ static struct via823x_info via823x_cards[] __devinitdata = {
2357/* 2357/*
2358 * auto detection of DXS channel supports. 2358 * auto detection of DXS channel supports.
2359 */ 2359 */
2360struct dxs_whitelist { 2360
2361 unsigned short subvendor; 2361static struct snd_pci_quirk dxs_whitelist[] __devinitdata = {
2362 unsigned short subdevice; 2362 SND_PCI_QUIRK(0x1005, 0x4710, "Avance Logic Mobo", VIA_DXS_ENABLE),
2363 unsigned short mask; 2363 SND_PCI_QUIRK(0x1019, 0x0996, "ESC Mobo", VIA_DXS_48K),
2364 short action; /* new dxs_support value */ 2364 SND_PCI_QUIRK(0x1019, 0x0a81, "ECS K7VTA3 v8.0", VIA_DXS_NO_VRA),
2365 SND_PCI_QUIRK(0x1019, 0x0a85, "ECS L7VMM2", VIA_DXS_NO_VRA),
2366 SND_PCI_QUIRK(0x1019, 0, "ESC K8", VIA_DXS_SRC),
2367 SND_PCI_QUIRK(0x1019, 0xaa01, "ESC K8T890-A", VIA_DXS_SRC),
2368 SND_PCI_QUIRK(0x1025, 0x0033, "Acer Inspire 1353LM", VIA_DXS_NO_VRA),
2369 SND_PCI_QUIRK(0x1025, 0x0046, "Acer Aspire 1524 WLMi", VIA_DXS_SRC),
2370 SND_PCI_QUIRK(0x1043, 0, "ASUS A7/A8", VIA_DXS_NO_VRA),
2371 SND_PCI_QUIRK(0x1071, 0, "Diverse Notebook", VIA_DXS_NO_VRA),
2372 SND_PCI_QUIRK(0x10cf, 0x118e, "FSC Laptop", VIA_DXS_ENABLE),
2373 SND_PCI_QUIRK(0x1106, 0, "ASRock", VIA_DXS_SRC),
2374 SND_PCI_QUIRK(0x1297, 0xa232, "Shuttle", VIA_DXS_ENABLE),
2375 SND_PCI_QUIRK(0x1297, 0xc160, "Shuttle Sk41G", VIA_DXS_ENABLE),
2376 SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte GA-7VAXP", VIA_DXS_ENABLE),
2377 SND_PCI_QUIRK(0x1462, 0x3800, "MSI KT266", VIA_DXS_ENABLE),
2378 SND_PCI_QUIRK(0x1462, 0x7120, "MSI KT4V", VIA_DXS_ENABLE),
2379 SND_PCI_QUIRK(0x1462, 0x7142, "MSI K8MM-V", VIA_DXS_ENABLE),
2380 SND_PCI_QUIRK(0x1462, 0, "MSI Mobo", VIA_DXS_SRC),
2381 SND_PCI_QUIRK(0x147b, 0x1401, "ABIT KD7(-RAID)", VIA_DXS_ENABLE),
2382 SND_PCI_QUIRK(0x147b, 0x1411, "ABIT VA-20", VIA_DXS_ENABLE),
2383 SND_PCI_QUIRK(0x147b, 0x1413, "ABIT KV8 Pro", VIA_DXS_ENABLE),
2384 SND_PCI_QUIRK(0x147b, 0x1415, "ABIT AV8", VIA_DXS_NO_VRA),
2385 SND_PCI_QUIRK(0x14ff, 0x0403, "Twinhead mobo", VIA_DXS_ENABLE),
2386 SND_PCI_QUIRK(0x14ff, 0x0408, "Twinhead laptop", VIA_DXS_SRC),
2387 SND_PCI_QUIRK(0x1558, 0x4701, "Clevo D470", VIA_DXS_SRC),
2388 SND_PCI_QUIRK(0x1584, 0x8120, "Diverse Laptop", VIA_DXS_ENABLE),
2389 SND_PCI_QUIRK(0x1584, 0x8123, "Targa/Uniwill", VIA_DXS_NO_VRA),
2390 SND_PCI_QUIRK(0x161f, 0x202b, "Amira Notebook", VIA_DXS_NO_VRA),
2391 SND_PCI_QUIRK(0x161f, 0x2032, "m680x machines", VIA_DXS_48K),
2392 SND_PCI_QUIRK(0x1631, 0xe004, "PB EasyNote 3174", VIA_DXS_ENABLE),
2393 SND_PCI_QUIRK(0x1695, 0x3005, "EPoX EP-8K9A", VIA_DXS_ENABLE),
2394 SND_PCI_QUIRK(0x1695, 0, "EPoX mobo", VIA_DXS_SRC),
2395 SND_PCI_QUIRK(0x16f3, 0, "Jetway K8", VIA_DXS_SRC),
2396 SND_PCI_QUIRK(0x1734, 0, "FSC Laptop", VIA_DXS_SRC),
2397 SND_PCI_QUIRK(0x1849, 0x3059, "ASRock K7VM2", VIA_DXS_NO_VRA),
2398 SND_PCI_QUIRK(0x1849, 0, "ASRock mobo", VIA_DXS_SRC),
2399 SND_PCI_QUIRK(0x1919, 0x200a, "Soltek SL-K8", VIA_DXS_NO_VRA),
2400 SND_PCI_QUIRK(0x4005, 0x4710, "MSI K7T266", VIA_DXS_SRC),
2401 { } /* terminator */
2365}; 2402};
2366 2403
2367static int __devinit check_dxs_list(struct pci_dev *pci, int revision) 2404static int __devinit check_dxs_list(struct pci_dev *pci, int revision)
2368{ 2405{
2369 static struct dxs_whitelist whitelist[] __devinitdata = { 2406 const struct snd_pci_quirk *w;
2370 { .subvendor = 0x1005, .subdevice = 0x4710, .action = VIA_DXS_ENABLE }, /* Avance Logic Mobo */
2371 { .subvendor = 0x1019, .subdevice = 0x0996, .action = VIA_DXS_48K },
2372 { .subvendor = 0x1019, .subdevice = 0x0a81, .action = VIA_DXS_NO_VRA }, /* ECS K7VTA3 v8.0 */
2373 { .subvendor = 0x1019, .subdevice = 0x0a85, .action = VIA_DXS_NO_VRA }, /* ECS L7VMM2 */
2374 { .subvendor = 0x1019, .subdevice = 0xa101, .action = VIA_DXS_SRC },
2375 { .subvendor = 0x1019, .subdevice = 0xaa01, .action = VIA_DXS_SRC }, /* ECS K8T890-A */
2376 { .subvendor = 0x1025, .subdevice = 0x0033, .action = VIA_DXS_NO_VRA }, /* Acer Inspire 1353LM */
2377 { .subvendor = 0x1025, .subdevice = 0x0046, .action = VIA_DXS_SRC }, /* Acer Aspire 1524 WLMi */
2378 { .subvendor = 0x1043, .subdevice = 0x8095, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8X (FIXME: possibly VIA_DXS_ENABLE?)*/
2379 { .subvendor = 0x1043, .subdevice = 0x80a1, .action = VIA_DXS_NO_VRA }, /* ASUS A7V8-X */
2380 { .subvendor = 0x1043, .subdevice = 0x80b0, .action = VIA_DXS_NO_VRA }, /* ASUS A7V600 & K8V*/
2381 { .subvendor = 0x1043, .subdevice = 0x810d, .action = VIA_DXS_SRC }, /* ASUS */
2382 { .subvendor = 0x1043, .subdevice = 0x812a, .action = VIA_DXS_SRC }, /* ASUS A8V Deluxe */
2383 { .subvendor = 0x1043, .subdevice = 0x8174, .action = VIA_DXS_SRC }, /* ASUS */
2384 { .subvendor = 0x1043, .subdevice = 0x81b9, .action = VIA_DXS_SRC }, /* ASUS A8V-MX */
2385 { .subvendor = 0x1071, .subdevice = 0x8375, .action = VIA_DXS_NO_VRA }, /* Vobis/Yakumo/Mitac notebook */
2386 { .subvendor = 0x1071, .subdevice = 0x8399, .action = VIA_DXS_NO_VRA }, /* Umax AB 595T (VIA K8N800A - VT8237) */
2387 { .subvendor = 0x10cf, .subdevice = 0x118e, .action = VIA_DXS_ENABLE }, /* FSC laptop */
2388 { .subvendor = 0x1106, .subdevice = 0x4161, .action = VIA_DXS_NO_VRA }, /* ASRock K7VT2 */
2389 { .subvendor = 0x1106, .subdevice = 0x4552, .action = VIA_DXS_NO_VRA }, /* QDI Kudoz 7X/600-6AL */
2390 { .subvendor = 0x1106, .subdevice = 0xaa01, .action = VIA_DXS_NO_VRA }, /* EPIA MII */
2391 { .subvendor = 0x1106, .subdevice = 0xc001, .action = VIA_DXS_SRC }, /* Insight P4-ITX */
2392 { .subvendor = 0x1297, .subdevice = 0xa232, .action = VIA_DXS_ENABLE }, /* Shuttle ?? */
2393 { .subvendor = 0x1297, .subdevice = 0xc160, .action = VIA_DXS_ENABLE }, /* Shuttle SK41G */
2394 { .subvendor = 0x1458, .subdevice = 0xa002, .action = VIA_DXS_ENABLE }, /* Gigabyte GA-7VAXP */
2395 { .subvendor = 0x1462, .subdevice = 0x0080, .action = VIA_DXS_SRC }, /* MSI K8T Neo-FIS2R */
2396 { .subvendor = 0x1462, .subdevice = 0x0430, .action = VIA_DXS_SRC }, /* MSI 7142 (K8MM-V) */
2397 { .subvendor = 0x1462, .subdevice = 0x0470, .action = VIA_DXS_SRC }, /* MSI KT880 Delta-FSR */
2398 { .subvendor = 0x1462, .subdevice = 0x3800, .action = VIA_DXS_ENABLE }, /* MSI KT266 */
2399 { .subvendor = 0x1462, .subdevice = 0x5901, .action = VIA_DXS_NO_VRA }, /* MSI KT6 Delta-SR */
2400 { .subvendor = 0x1462, .subdevice = 0x7023, .action = VIA_DXS_SRC }, /* MSI K8T Neo2-FI */
2401 { .subvendor = 0x1462, .subdevice = 0x7120, .action = VIA_DXS_ENABLE }, /* MSI KT4V */
2402 { .subvendor = 0x1462, .subdevice = 0x7142, .action = VIA_DXS_ENABLE }, /* MSI K8MM-V */
2403 { .subvendor = 0x1462, .subdevice = 0xb012, .action = VIA_DXS_SRC }, /* P4M800/VIA8237R */
2404 { .subvendor = 0x147b, .subdevice = 0x1401, .action = VIA_DXS_ENABLE }, /* ABIT KD7(-RAID) */
2405 { .subvendor = 0x147b, .subdevice = 0x1411, .action = VIA_DXS_ENABLE }, /* ABIT VA-20 */
2406 { .subvendor = 0x147b, .subdevice = 0x1413, .action = VIA_DXS_ENABLE }, /* ABIT KV8 Pro */
2407 { .subvendor = 0x147b, .subdevice = 0x1415, .action = VIA_DXS_NO_VRA }, /* Abit AV8 */
2408 { .subvendor = 0x14ff, .subdevice = 0x0403, .action = VIA_DXS_ENABLE }, /* Twinhead mobo */
2409 { .subvendor = 0x14ff, .subdevice = 0x0408, .action = VIA_DXS_SRC }, /* Twinhead laptop */
2410 { .subvendor = 0x1558, .subdevice = 0x4701, .action = VIA_DXS_SRC }, /* Clevo D470 */
2411 { .subvendor = 0x1584, .subdevice = 0x8120, .action = VIA_DXS_ENABLE }, /* Gericom/Targa/Vobis/Uniwill laptop */
2412 { .subvendor = 0x1584, .subdevice = 0x8123, .action = VIA_DXS_NO_VRA }, /* Uniwill (Targa Visionary XP-210) */
2413 { .subvendor = 0x161f, .subdevice = 0x202b, .action = VIA_DXS_NO_VRA }, /* Amira Note book */
2414 { .subvendor = 0x161f, .subdevice = 0x2032, .action = VIA_DXS_48K }, /* m680x machines */
2415 { .subvendor = 0x1631, .subdevice = 0xe004, .action = VIA_DXS_ENABLE }, /* Easy Note 3174, Packard Bell */
2416 { .subvendor = 0x1695, .subdevice = 0x3005, .action = VIA_DXS_ENABLE }, /* EPoX EP-8K9A */
2417 { .subvendor = 0x1695, .subdevice = 0x300c, .action = VIA_DXS_SRC }, /* EPoX EP-8KRAI */
2418 { .subvendor = 0x1695, .subdevice = 0x300e, .action = VIA_DXS_SRC }, /* EPoX 9HEAI */
2419 { .subvendor = 0x16f3, .subdevice = 0x6405, .action = VIA_DXS_SRC }, /* Jetway K8M8MS */
2420 { .subvendor = 0x1734, .subdevice = 0x1078, .action = VIA_DXS_SRC }, /* FSC Amilo L7300 */
2421 { .subvendor = 0x1734, .subdevice = 0x1093, .action = VIA_DXS_SRC }, /* FSC */
2422 { .subvendor = 0x1734, .subdevice = 0x10ab, .action = VIA_DXS_SRC }, /* FSC */
2423 { .subvendor = 0x1849, .subdevice = 0x3059, .action = VIA_DXS_NO_VRA }, /* ASRock K7VM2 */
2424 { .subvendor = 0x1849, .subdevice = 0x9739, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */
2425 { .subvendor = 0x1849, .subdevice = 0x9761, .action = VIA_DXS_SRC }, /* ASRock mobo(?) */
2426 { .subvendor = 0x1919, .subdevice = 0x200a, .action = VIA_DXS_NO_VRA }, /* Soltek SL-K8Tpro-939 */
2427 { .subvendor = 0x4005, .subdevice = 0x4710, .action = VIA_DXS_SRC }, /* MSI K7T266 Pro2 (MS-6380 V2.0) BIOS 3.7 */
2428 { } /* terminator */
2429 };
2430 const struct dxs_whitelist *w;
2431 unsigned short subsystem_vendor;
2432 unsigned short subsystem_device;
2433
2434 pci_read_config_word(pci, PCI_SUBSYSTEM_VENDOR_ID, &subsystem_vendor);
2435 pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &subsystem_device);
2436 2407
2437 for (w = whitelist; w->subvendor; w++) { 2408 w = snd_pci_quirk_lookup(pci, dxs_whitelist);
2438 if (w->subvendor != subsystem_vendor) 2409 if (w) {
2439 continue; 2410 snd_printdd(KERN_INFO "via82xx: DXS white list for %s found\n",
2440 if (w->mask) { 2411 w->name);
2441 if ((w->mask & subsystem_device) == w->subdevice) 2412 return w->value;
2442 return w->action;
2443 } else {
2444 if (subsystem_device == w->subdevice)
2445 return w->action;
2446 }
2447 } 2413 }
2448 2414
2449 /* for newer revision, default to DXS_SRC */ 2415 /* for newer revision, default to DXS_SRC */
diff --git a/sound/pci/via82xx_modem.c b/sound/pci/via82xx_modem.c
index 17d6b847585f..b338e15db0d9 100644
--- a/sound/pci/via82xx_modem.c
+++ b/sound/pci/via82xx_modem.c
@@ -900,7 +900,7 @@ static int __devinit snd_via82xx_mixer_new(struct via82xx_modem *chip)
900 ac97.private_data = chip; 900 ac97.private_data = chip;
901 ac97.private_free = snd_via82xx_mixer_free_ac97; 901 ac97.private_free = snd_via82xx_mixer_free_ac97;
902 ac97.pci = chip->pci; 902 ac97.pci = chip->pci;
903 ac97.scaps = AC97_SCAP_SKIP_AUDIO; 903 ac97.scaps = AC97_SCAP_SKIP_AUDIO | AC97_SCAP_POWER_SAVE;
904 ac97.num = chip->ac97_secondary; 904 ac97.num = chip->ac97_secondary;
905 905
906 if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0) 906 if ((err = snd_ac97_mixer(chip->ac97_bus, &ac97, &chip->ac97)) < 0)
diff --git a/sound/pci/vx222/vx222.c b/sound/pci/vx222/vx222.c
index 89f58ea180b3..474eac9490ae 100644
--- a/sound/pci/vx222/vx222.c
+++ b/sound/pci/vx222/vx222.c
@@ -73,8 +73,8 @@ MODULE_DEVICE_TABLE(pci, snd_vx222_ids);
73/* 73/*
74 */ 74 */
75 75
76static DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0); 76static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
77static DECLARE_TLV_DB_SCALE(db_scale_akm, -7350, 50, 0); 77static const DECLARE_TLV_DB_SCALE(db_scale_akm, -7350, 50, 0);
78 78
79static struct snd_vx_hardware vx222_old_hw = { 79static struct snd_vx_hardware vx222_old_hw = {
80 80
diff --git a/sound/pci/vx222/vx222_ops.c b/sound/pci/vx222/vx222_ops.c
index 5e51950e05f9..55558bef7166 100644
--- a/sound/pci/vx222/vx222_ops.c
+++ b/sound/pci/vx222/vx222_ops.c
@@ -846,7 +846,7 @@ static void vx2_set_input_level(struct snd_vx222 *chip)
846 846
847#define MIC_LEVEL_MAX 0xff 847#define MIC_LEVEL_MAX 0xff
848 848
849static DECLARE_TLV_DB_SCALE(db_scale_mic, -6450, 50, 0); 849static const DECLARE_TLV_DB_SCALE(db_scale_mic, -6450, 50, 0);
850 850
851/* 851/*
852 * controls API for input levels 852 * controls API for input levels
diff --git a/sound/pci/ymfpci/ymfpci_image.h b/sound/pci/ymfpci/ymfpci_image.h
index 1b0746991669..112f2fff6c8e 100644
--- a/sound/pci/ymfpci/ymfpci_image.h
+++ b/sound/pci/ymfpci/ymfpci_image.h
@@ -1,7 +1,7 @@
1#ifndef _HWMCODE_ 1#ifndef _HWMCODE_
2#define _HWMCODE_ 2#define _HWMCODE_
3 3
4static unsigned long DspInst[YDSXG_DSPLENGTH / 4] = { 4static u32 DspInst[YDSXG_DSPLENGTH / 4] = {
5 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f, 5 0x00000081, 0x000001a4, 0x0000000a, 0x0000002f,
6 0x00080253, 0x01800317, 0x0000407b, 0x0000843f, 6 0x00080253, 0x01800317, 0x0000407b, 0x0000843f,
7 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c, 7 0x0001483c, 0x0001943c, 0x0005d83c, 0x00001c3c,
@@ -12,7 +12,7 @@ static unsigned long DspInst[YDSXG_DSPLENGTH / 4] = {
12 0x00000000, 0x00000000, 0x00000000, 0x00000000 12 0x00000000, 0x00000000, 0x00000000, 0x00000000
13}; 13};
14 14
15static unsigned long CntrlInst[YDSXG_CTRLLENGTH / 4] = { 15static u32 CntrlInst[YDSXG_CTRLLENGTH / 4] = {
16 0x000007, 0x240007, 0x0C0007, 0x1C0007, 16 0x000007, 0x240007, 0x0C0007, 0x1C0007,
17 0x060007, 0x700002, 0x000020, 0x030040, 17 0x060007, 0x700002, 0x000020, 0x030040,
18 0x007104, 0x004286, 0x030040, 0x000F0D, 18 0x007104, 0x004286, 0x030040, 0x000F0D,
@@ -791,7 +791,7 @@ static unsigned long CntrlInst[YDSXG_CTRLLENGTH / 4] = {
791// 04/09 creat 791// 04/09 creat
792// 04/12 stop nise fix 792// 04/12 stop nise fix
793// 06/21 WorkingOff timming 793// 06/21 WorkingOff timming
794static unsigned long CntrlInst1E[YDSXG_CTRLLENGTH / 4] = { 794static u32 CntrlInst1E[YDSXG_CTRLLENGTH / 4] = {
795 0x000007, 0x240007, 0x0C0007, 0x1C0007, 795 0x000007, 0x240007, 0x0C0007, 0x1C0007,
796 0x060007, 0x700002, 0x000020, 0x030040, 796 0x060007, 0x700002, 0x000020, 0x030040,
797 0x007104, 0x004286, 0x030040, 0x000F0D, 797 0x007104, 0x004286, 0x030040, 0x000F0D,
diff --git a/sound/pci/ymfpci/ymfpci_main.c b/sound/pci/ymfpci/ymfpci_main.c
index 7881944a1957..fd12674d0394 100644
--- a/sound/pci/ymfpci/ymfpci_main.c
+++ b/sound/pci/ymfpci/ymfpci_main.c
@@ -2,12 +2,6 @@
2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz> 2 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
3 * Routines for control of YMF724/740/744/754 chips 3 * Routines for control of YMF724/740/744/754 chips
4 * 4 *
5 * BUGS:
6 * --
7 *
8 * TODO:
9 * --
10 *
11 * This program is free software; you can redistribute it and/or modify 5 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by 6 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or 7 * the Free Software Foundation; either version 2 of the License, or
@@ -26,6 +20,7 @@
26 20
27#include <sound/driver.h> 21#include <sound/driver.h>
28#include <linux/delay.h> 22#include <linux/delay.h>
23#include <linux/firmware.h>
29#include <linux/init.h> 24#include <linux/init.h>
30#include <linux/interrupt.h> 25#include <linux/interrupt.h>
31#include <linux/pci.h> 26#include <linux/pci.h>
@@ -42,10 +37,7 @@
42#include <sound/mpu401.h> 37#include <sound/mpu401.h>
43 38
44#include <asm/io.h> 39#include <asm/io.h>
45 40#include <asm/byteorder.h>
46/*
47 * constants
48 */
49 41
50/* 42/*
51 * common I/O routines 43 * common I/O routines
@@ -179,6 +171,17 @@ static u32 snd_ymfpci_calc_lpfQ(u32 rate)
179 return val[0]; 171 return val[0];
180} 172}
181 173
174static void snd_ymfpci_pcm_441_volume_set(struct snd_ymfpci_pcm *ypcm)
175{
176 unsigned int value;
177 struct snd_ymfpci_pcm_mixer *mixer;
178
179 mixer = &ypcm->chip->pcm_mixer[ypcm->substream->number];
180 value = min_t(unsigned int, mixer->left, 0x7fff) >> 1;
181 value |= (min_t(unsigned int, mixer->right, 0x7fff) >> 1) << 16;
182 snd_ymfpci_writel(ypcm->chip, YDSXGR_BUF441OUTVOL, value);
183}
184
182/* 185/*
183 * Hardware start management 186 * Hardware start management
184 */ 187 */
@@ -290,6 +293,10 @@ static int snd_ymfpci_voice_free(struct snd_ymfpci *chip, struct snd_ymfpci_voic
290 snd_assert(pvoice != NULL, return -EINVAL); 293 snd_assert(pvoice != NULL, return -EINVAL);
291 snd_ymfpci_hw_stop(chip); 294 snd_ymfpci_hw_stop(chip);
292 spin_lock_irqsave(&chip->voice_lock, flags); 295 spin_lock_irqsave(&chip->voice_lock, flags);
296 if (pvoice->number == chip->src441_used) {
297 chip->src441_used = -1;
298 pvoice->ypcm->use_441_slot = 0;
299 }
293 pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0; 300 pvoice->use = pvoice->pcm = pvoice->synth = pvoice->midi = 0;
294 pvoice->ypcm = NULL; 301 pvoice->ypcm = NULL;
295 pvoice->interrupt = NULL; 302 pvoice->interrupt = NULL;
@@ -394,7 +401,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
394 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: 401 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
395 case SNDRV_PCM_TRIGGER_RESUME: 402 case SNDRV_PCM_TRIGGER_RESUME:
396 chip->ctrl_playback[ypcm->voices[0]->number + 1] = cpu_to_le32(ypcm->voices[0]->bank_addr); 403 chip->ctrl_playback[ypcm->voices[0]->number + 1] = cpu_to_le32(ypcm->voices[0]->bank_addr);
397 if (ypcm->voices[1] != NULL) 404 if (ypcm->voices[1] != NULL && !ypcm->use_441_slot)
398 chip->ctrl_playback[ypcm->voices[1]->number + 1] = cpu_to_le32(ypcm->voices[1]->bank_addr); 405 chip->ctrl_playback[ypcm->voices[1]->number + 1] = cpu_to_le32(ypcm->voices[1]->bank_addr);
399 ypcm->running = 1; 406 ypcm->running = 1;
400 break; 407 break;
@@ -402,7 +409,7 @@ static int snd_ymfpci_playback_trigger(struct snd_pcm_substream *substream,
402 case SNDRV_PCM_TRIGGER_PAUSE_PUSH: 409 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
403 case SNDRV_PCM_TRIGGER_SUSPEND: 410 case SNDRV_PCM_TRIGGER_SUSPEND:
404 chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0; 411 chip->ctrl_playback[ypcm->voices[0]->number + 1] = 0;
405 if (ypcm->voices[1] != NULL) 412 if (ypcm->voices[1] != NULL && !ypcm->use_441_slot)
406 chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0; 413 chip->ctrl_playback[ypcm->voices[1]->number + 1] = 0;
407 ypcm->running = 0; 414 ypcm->running = 0;
408 break; 415 break;
@@ -489,6 +496,7 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int
489 unsigned int nbank; 496 unsigned int nbank;
490 u32 vol_left, vol_right; 497 u32 vol_left, vol_right;
491 u8 use_left, use_right; 498 u8 use_left, use_right;
499 unsigned long flags;
492 500
493 snd_assert(voice != NULL, return); 501 snd_assert(voice != NULL, return);
494 if (runtime->channels == 1) { 502 if (runtime->channels == 1) {
@@ -507,11 +515,27 @@ static void snd_ymfpci_pcm_init_voice(struct snd_ymfpci_pcm *ypcm, unsigned int
507 vol_left = cpu_to_le32(0x40000000); 515 vol_left = cpu_to_le32(0x40000000);
508 vol_right = cpu_to_le32(0x40000000); 516 vol_right = cpu_to_le32(0x40000000);
509 } 517 }
518 spin_lock_irqsave(&ypcm->chip->voice_lock, flags);
510 format = runtime->channels == 2 ? 0x00010000 : 0; 519 format = runtime->channels == 2 ? 0x00010000 : 0;
511 if (snd_pcm_format_width(runtime->format) == 8) 520 if (snd_pcm_format_width(runtime->format) == 8)
512 format |= 0x80000000; 521 format |= 0x80000000;
522 else if (ypcm->chip->device_id == PCI_DEVICE_ID_YAMAHA_754 &&
523 runtime->rate == 44100 && runtime->channels == 2 &&
524 voiceidx == 0 && (ypcm->chip->src441_used == -1 ||
525 ypcm->chip->src441_used == voice->number)) {
526 ypcm->chip->src441_used = voice->number;
527 ypcm->use_441_slot = 1;
528 format |= 0x10000000;
529 snd_ymfpci_pcm_441_volume_set(ypcm);
530 }
531 if (ypcm->chip->src441_used == voice->number &&
532 (format & 0x10000000) == 0) {
533 ypcm->chip->src441_used = -1;
534 ypcm->use_441_slot = 0;
535 }
513 if (runtime->channels == 2 && (voiceidx & 1) != 0) 536 if (runtime->channels == 2 && (voiceidx & 1) != 0)
514 format |= 1; 537 format |= 1;
538 spin_unlock_irqrestore(&ypcm->chip->voice_lock, flags);
515 for (nbank = 0; nbank < 2; nbank++) { 539 for (nbank = 0; nbank < 2; nbank++) {
516 bank = &voice->bank[nbank]; 540 bank = &voice->bank[nbank];
517 memset(bank, 0, sizeof(*bank)); 541 memset(bank, 0, sizeof(*bank));
@@ -1480,7 +1504,7 @@ static int snd_ymfpci_put_single(struct snd_kcontrol *kcontrol,
1480 return change; 1504 return change;
1481} 1505}
1482 1506
1483static DECLARE_TLV_DB_LINEAR(db_scale_native, TLV_DB_GAIN_MUTE, 0); 1507static const DECLARE_TLV_DB_LINEAR(db_scale_native, TLV_DB_GAIN_MUTE, 0);
1484 1508
1485#define YMFPCI_DOUBLE(xname, xindex, reg) \ 1509#define YMFPCI_DOUBLE(xname, xindex, reg) \
1486{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ 1510{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
@@ -1722,7 +1746,10 @@ static int snd_ymfpci_pcm_vol_put(struct snd_kcontrol *kcontrol,
1722 spin_lock_irqsave(&chip->voice_lock, flags); 1746 spin_lock_irqsave(&chip->voice_lock, flags);
1723 if (substream->runtime && substream->runtime->private_data) { 1747 if (substream->runtime && substream->runtime->private_data) {
1724 struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data; 1748 struct snd_ymfpci_pcm *ypcm = substream->runtime->private_data;
1725 ypcm->update_pcm_vol = 2; 1749 if (!ypcm->use_441_slot)
1750 ypcm->update_pcm_vol = 2;
1751 else
1752 snd_ymfpci_pcm_441_volume_set(ypcm);
1726 } 1753 }
1727 spin_unlock_irqrestore(&chip->voice_lock, flags); 1754 spin_unlock_irqrestore(&chip->voice_lock, flags);
1728 return 1; 1755 return 1;
@@ -1971,13 +1998,94 @@ static void snd_ymfpci_disable_dsp(struct snd_ymfpci *chip)
1971 } 1998 }
1972} 1999}
1973 2000
2001#define FIRMWARE_IN_THE_KERNEL
2002
2003#ifdef FIRMWARE_IN_THE_KERNEL
2004
1974#include "ymfpci_image.h" 2005#include "ymfpci_image.h"
1975 2006
2007static struct firmware snd_ymfpci_dsp_microcode = {
2008 .size = YDSXG_DSPLENGTH,
2009 .data = (u8 *)DspInst,
2010};
2011static struct firmware snd_ymfpci_controller_microcode = {
2012 .size = YDSXG_CTRLLENGTH,
2013 .data = (u8 *)CntrlInst,
2014};
2015static struct firmware snd_ymfpci_controller_1e_microcode = {
2016 .size = YDSXG_CTRLLENGTH,
2017 .data = (u8 *)CntrlInst1E,
2018};
2019#endif
2020
2021#ifdef __LITTLE_ENDIAN
2022static inline void snd_ymfpci_convert_from_le(const struct firmware *fw) { }
2023#else
2024static void snd_ymfpci_convert_from_le(const struct firmware *fw)
2025{
2026 int i;
2027 u32 *data = (u32 *)fw->data;
2028
2029 for (i = 0; i < fw->size / 4; ++i)
2030 le32_to_cpus(&data[i]);
2031}
2032#endif
2033
2034static int snd_ymfpci_request_firmware(struct snd_ymfpci *chip)
2035{
2036 int err, is_1e;
2037 const char *name;
2038
2039 err = request_firmware(&chip->dsp_microcode, "yamaha/ds1_dsp.fw",
2040 &chip->pci->dev);
2041 if (err >= 0) {
2042 if (chip->dsp_microcode->size == YDSXG_DSPLENGTH)
2043 snd_ymfpci_convert_from_le(chip->dsp_microcode);
2044 else {
2045 snd_printk(KERN_ERR "DSP microcode has wrong size\n");
2046 err = -EINVAL;
2047 }
2048 }
2049 if (err < 0) {
2050#ifdef FIRMWARE_IN_THE_KERNEL
2051 chip->dsp_microcode = &snd_ymfpci_dsp_microcode;
2052#else
2053 return err;
2054#endif
2055 }
2056 is_1e = chip->device_id == PCI_DEVICE_ID_YAMAHA_724F ||
2057 chip->device_id == PCI_DEVICE_ID_YAMAHA_740C ||
2058 chip->device_id == PCI_DEVICE_ID_YAMAHA_744 ||
2059 chip->device_id == PCI_DEVICE_ID_YAMAHA_754;
2060 name = is_1e ? "yamaha/ds1e_ctrl.fw" : "yamaha/ds1_ctrl.fw";
2061 err = request_firmware(&chip->controller_microcode, name,
2062 &chip->pci->dev);
2063 if (err >= 0) {
2064 if (chip->controller_microcode->size == YDSXG_CTRLLENGTH)
2065 snd_ymfpci_convert_from_le(chip->controller_microcode);
2066 else {
2067 snd_printk(KERN_ERR "controller microcode"
2068 " has wrong size\n");
2069 err = -EINVAL;
2070 }
2071 }
2072 if (err < 0) {
2073#ifdef FIRMWARE_IN_THE_KERNEL
2074 chip->controller_microcode =
2075 is_1e ? &snd_ymfpci_controller_1e_microcode
2076 : &snd_ymfpci_controller_microcode;
2077#else
2078 return err;
2079#endif
2080 }
2081 return 0;
2082}
2083
1976static void snd_ymfpci_download_image(struct snd_ymfpci *chip) 2084static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
1977{ 2085{
1978 int i; 2086 int i;
1979 u16 ctrl; 2087 u16 ctrl;
1980 unsigned long *inst; 2088 u32 *inst;
1981 2089
1982 snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x00000000); 2090 snd_ymfpci_writel(chip, YDSXGR_NATIVEDACOUTVOL, 0x00000000);
1983 snd_ymfpci_disable_dsp(chip); 2091 snd_ymfpci_disable_dsp(chip);
@@ -1992,21 +2100,12 @@ static void snd_ymfpci_download_image(struct snd_ymfpci *chip)
1992 snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007); 2100 snd_ymfpci_writew(chip, YDSXGR_GLOBALCTRL, ctrl & ~0x0007);
1993 2101
1994 /* setup DSP instruction code */ 2102 /* setup DSP instruction code */
2103 inst = (u32 *)chip->dsp_microcode->data;
1995 for (i = 0; i < YDSXG_DSPLENGTH / 4; i++) 2104 for (i = 0; i < YDSXG_DSPLENGTH / 4; i++)
1996 snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), DspInst[i]); 2105 snd_ymfpci_writel(chip, YDSXGR_DSPINSTRAM + (i << 2), inst[i]);
1997 2106
1998 /* setup control instruction code */ 2107 /* setup control instruction code */
1999 switch (chip->device_id) { 2108 inst = (u32 *)chip->controller_microcode->data;
2000 case PCI_DEVICE_ID_YAMAHA_724F:
2001 case PCI_DEVICE_ID_YAMAHA_740C:
2002 case PCI_DEVICE_ID_YAMAHA_744:
2003 case PCI_DEVICE_ID_YAMAHA_754:
2004 inst = CntrlInst1E;
2005 break;
2006 default:
2007 inst = CntrlInst;
2008 break;
2009 }
2010 for (i = 0; i < YDSXG_CTRLLENGTH / 4; i++) 2109 for (i = 0; i < YDSXG_CTRLLENGTH / 4; i++)
2011 snd_ymfpci_writel(chip, YDSXGR_CTRLINSTRAM + (i << 2), inst[i]); 2110 snd_ymfpci_writel(chip, YDSXGR_CTRLINSTRAM + (i << 2), inst[i]);
2012 2111
@@ -2160,6 +2259,15 @@ static int snd_ymfpci_free(struct snd_ymfpci *chip)
2160 pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl); 2259 pci_write_config_word(chip->pci, 0x40, chip->old_legacy_ctrl);
2161 2260
2162 pci_disable_device(chip->pci); 2261 pci_disable_device(chip->pci);
2262#ifdef FIRMWARE_IN_THE_KERNEL
2263 if (chip->dsp_microcode != &snd_ymfpci_dsp_microcode)
2264#endif
2265 release_firmware(chip->dsp_microcode);
2266#ifdef FIRMWARE_IN_THE_KERNEL
2267 if (chip->controller_microcode != &snd_ymfpci_controller_microcode &&
2268 chip->controller_microcode != &snd_ymfpci_controller_1e_microcode)
2269#endif
2270 release_firmware(chip->controller_microcode);
2163 kfree(chip); 2271 kfree(chip);
2164 return 0; 2272 return 0;
2165} 2273}
@@ -2180,7 +2288,7 @@ static int saved_regs_index[] = {
2180 YDSXGR_PRIADCLOOPVOL, 2288 YDSXGR_PRIADCLOOPVOL,
2181 YDSXGR_NATIVEDACINVOL, 2289 YDSXGR_NATIVEDACINVOL,
2182 YDSXGR_NATIVEDACOUTVOL, 2290 YDSXGR_NATIVEDACOUTVOL,
2183 // YDSXGR_BUF441OUTVOL, 2291 YDSXGR_BUF441OUTVOL,
2184 YDSXGR_NATIVEADCINVOL, 2292 YDSXGR_NATIVEADCINVOL,
2185 YDSXGR_SPDIFLOOPVOL, 2293 YDSXGR_SPDIFLOOPVOL,
2186 YDSXGR_SPDIFOUTVOL, 2294 YDSXGR_SPDIFOUTVOL,
@@ -2295,6 +2403,7 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
2295 chip->reg_area_phys = pci_resource_start(pci, 0); 2403 chip->reg_area_phys = pci_resource_start(pci, 0);
2296 chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000); 2404 chip->reg_area_virt = ioremap_nocache(chip->reg_area_phys, 0x8000);
2297 pci_set_master(pci); 2405 pci_set_master(pci);
2406 chip->src441_used = -1;
2298 2407
2299 if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) { 2408 if ((chip->res_reg_area = request_mem_region(chip->reg_area_phys, 0x8000, "YMFPCI")) == NULL) {
2300 snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1); 2409 snd_printk(KERN_ERR "unable to grab memory region 0x%lx-0x%lx\n", chip->reg_area_phys, chip->reg_area_phys + 0x8000 - 1);
@@ -2315,6 +2424,12 @@ int __devinit snd_ymfpci_create(struct snd_card *card,
2315 return -EIO; 2424 return -EIO;
2316 } 2425 }
2317 2426
2427 err = snd_ymfpci_request_firmware(chip);
2428 if (err < 0) {
2429 snd_printk(KERN_ERR "firmware request failed: %d\n", err);
2430 snd_ymfpci_free(chip);
2431 return err;
2432 }
2318 snd_ymfpci_download_image(chip); 2433 snd_ymfpci_download_image(chip);
2319 2434
2320 udelay(100); /* seems we need a delay after downloading image.. */ 2435 udelay(100); /* seems we need a delay after downloading image.. */
diff --git a/sound/pcmcia/vx/vxp_mixer.c b/sound/pcmcia/vx/vxp_mixer.c
index bced7b623b12..2b1f996c898d 100644
--- a/sound/pcmcia/vx/vxp_mixer.c
+++ b/sound/pcmcia/vx/vxp_mixer.c
@@ -64,7 +64,7 @@ static int vx_mic_level_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_v
64 return 0; 64 return 0;
65} 65}
66 66
67static DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0); 67static const DECLARE_TLV_DB_SCALE(db_scale_mic, -21, 3, 0);
68 68
69static struct snd_kcontrol_new vx_control_mic_level = { 69static struct snd_kcontrol_new vx_control_mic_level = {
70 .iface = SNDRV_CTL_ELEM_IFACE_MIXER, 70 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
diff --git a/sound/pcmcia/vx/vxpocket.c b/sound/pcmcia/vx/vxpocket.c
index d7df59e9c647..363bcb5f08e6 100644
--- a/sound/pcmcia/vx/vxpocket.c
+++ b/sound/pcmcia/vx/vxpocket.c
@@ -91,7 +91,7 @@ static int snd_vxpocket_dev_free(struct snd_device *device)
91 * Only output levels can be modified 91 * Only output levels can be modified
92 */ 92 */
93 93
94static DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0); 94static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
95 95
96static struct snd_vx_hardware vxpocket_hw = { 96static struct snd_vx_hardware vxpocket_hw = {
97 .name = "VXPocket", 97 .name = "VXPocket",
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
new file mode 100644
index 000000000000..ec821a57f843
--- /dev/null
+++ b/sound/soc/Kconfig
@@ -0,0 +1,32 @@
1#
2# SoC audio configuration
3#
4
5menu "SoC audio support"
6 depends on SND!=n
7
8config SND_SOC_AC97_BUS
9 bool
10
11config SND_SOC
12 tristate "SoC audio support"
13 ---help---
14
15 If you want SoC support, you should say Y here and also to the
16 specific driver for your SoC below. You will also need to select the
17 specific codec(s) attached to the SoC
18
19 This SoC audio support can also be built as a module. If so, the module
20 will be called snd-soc-core.
21
22# All the supported Soc's
23menu "SoC Platforms"
24depends on SND_SOC
25source "sound/soc/at91/Kconfig"
26source "sound/soc/pxa/Kconfig"
27endmenu
28
29# Supported codecs
30source "sound/soc/codecs/Kconfig"
31
32endmenu
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
new file mode 100644
index 000000000000..98e6f49dafc2
--- /dev/null
+++ b/sound/soc/Makefile
@@ -0,0 +1,4 @@
1snd-soc-core-objs := soc-core.o soc-dapm.o
2
3obj-$(CONFIG_SND_SOC) += snd-soc-core.o
4obj-$(CONFIG_SND_SOC) += codecs/ at91/ pxa/
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
new file mode 100644
index 000000000000..5bcf08b728b0
--- /dev/null
+++ b/sound/soc/at91/Kconfig
@@ -0,0 +1,32 @@
1menu "SoC Audio for the Atmel AT91"
2
3config SND_AT91_SOC
4 tristate "SoC Audio for the Atmel AT91 System-on-Chip"
5 depends on ARCH_AT91 && SND
6 select SND_PCM
7 help
8 Say Y or M if you want to add support for codecs attached to
9 the AT91 SSC interface. You will also need
10 to select the audio interfaces to support below.
11
12config SND_AT91_SOC_I2S
13 tristate
14
15config SND_AT91_SOC_ETI_B1_WM8731
16 tristate "SoC I2S Audio support for WM8731-based Endrelia ETI-B1 boards"
17 depends on SND_AT91_SOC && (MACH_ETI_B1 || MACH_ETI_C1)
18 select SND_AT91_SOC_I2S
19 select SND_SOC_WM8731
20 help
21 Say Y if you want to add support for SoC audio on WM8731-based
22 Endrelia Technologies Inc ETI-B1 or ETI-C1 boards.
23
24config SND_AT91_SOC_ETI_SLAVE
25 bool "Run codec in slave Mode on Endrelia boards"
26 depends on SND_AT91_SOC_ETI_B1_WM8731
27 default n
28 help
29 Say Y if you want to run with the AT91 SSC generating the BCLK
30 and LRC signals on Endrelia boards.
31
32endmenu
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
new file mode 100644
index 000000000000..b77b01ab2028
--- /dev/null
+++ b/sound/soc/at91/Makefile
@@ -0,0 +1,11 @@
1# AT91 Platform Support
2snd-soc-at91-objs := at91-pcm.o
3snd-soc-at91-i2s-objs := at91-i2s.o
4
5obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
6obj-$(CONFIG_SND_AT91_SOC_I2S) += snd-soc-at91-i2s.o
7
8# AT91 Machine Support
9snd-soc-eti-b1-wm8731-objs := eti_b1_wm8731.o
10
11obj-$(CONFIG_SND_AT91_SOC_ETI_B1_WM8731) += snd-soc-eti-b1-wm8731.o
diff --git a/sound/soc/at91/at91-i2s.c b/sound/soc/at91/at91-i2s.c
new file mode 100644
index 000000000000..fcc544a96ba3
--- /dev/null
+++ b/sound/soc/at91/at91-i2s.c
@@ -0,0 +1,720 @@
1/*
2 * at91-i2s.c -- ALSA SoC I2S Audio Layer Platform driver
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 *
7 * Based on pxa2xx Platform drivers by
8 * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/interrupt.h>
20#include <linux/device.h>
21#include <linux/delay.h>
22#include <linux/clk.h>
23#include <sound/driver.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/initval.h>
27#include <sound/soc.h>
28
29#include <asm/arch/hardware.h>
30#include <asm/arch/at91_pmc.h>
31#include <asm/arch/at91_ssc.h>
32#include <asm/arch/at91_pdc.h>
33
34#include "at91-pcm.h"
35#include "at91-i2s.h"
36
37#if 0
38#define DBG(x...) printk(KERN_DEBUG "at91-i2s:" x)
39#else
40#define DBG(x...)
41#endif
42
43#if defined(CONFIG_ARCH_AT91SAM9260)
44#define NUM_SSC_DEVICES 1
45#else
46#define NUM_SSC_DEVICES 3
47#endif
48
49
50/*
51 * SSC PDC registers required by the PCM DMA engine.
52 */
53static struct at91_pdc_regs pdc_tx_reg = {
54 .xpr = AT91_PDC_TPR,
55 .xcr = AT91_PDC_TCR,
56 .xnpr = AT91_PDC_TNPR,
57 .xncr = AT91_PDC_TNCR,
58};
59
60static struct at91_pdc_regs pdc_rx_reg = {
61 .xpr = AT91_PDC_RPR,
62 .xcr = AT91_PDC_RCR,
63 .xnpr = AT91_PDC_RNPR,
64 .xncr = AT91_PDC_RNCR,
65};
66
67/*
68 * SSC & PDC status bits for transmit and receive.
69 */
70static struct at91_ssc_mask ssc_tx_mask = {
71 .ssc_enable = AT91_SSC_TXEN,
72 .ssc_disable = AT91_SSC_TXDIS,
73 .ssc_endx = AT91_SSC_ENDTX,
74 .ssc_endbuf = AT91_SSC_TXBUFE,
75 .pdc_enable = AT91_PDC_TXTEN,
76 .pdc_disable = AT91_PDC_TXTDIS,
77};
78
79static struct at91_ssc_mask ssc_rx_mask = {
80 .ssc_enable = AT91_SSC_RXEN,
81 .ssc_disable = AT91_SSC_RXDIS,
82 .ssc_endx = AT91_SSC_ENDRX,
83 .ssc_endbuf = AT91_SSC_RXBUFF,
84 .pdc_enable = AT91_PDC_RXTEN,
85 .pdc_disable = AT91_PDC_RXTDIS,
86};
87
88
89/*
90 * DMA parameters.
91 */
92static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
93 {{
94 .name = "SSC0/I2S PCM Stereo out",
95 .pdc = &pdc_tx_reg,
96 .mask = &ssc_tx_mask,
97 },
98 {
99 .name = "SSC0/I2S PCM Stereo in",
100 .pdc = &pdc_rx_reg,
101 .mask = &ssc_rx_mask,
102 }},
103#if NUM_SSC_DEVICES == 3
104 {{
105 .name = "SSC1/I2S PCM Stereo out",
106 .pdc = &pdc_tx_reg,
107 .mask = &ssc_tx_mask,
108 },
109 {
110 .name = "SSC1/I2S PCM Stereo in",
111 .pdc = &pdc_rx_reg,
112 .mask = &ssc_rx_mask,
113 }},
114 {{
115 .name = "SSC2/I2S PCM Stereo out",
116 .pdc = &pdc_tx_reg,
117 .mask = &ssc_tx_mask,
118 },
119 {
120 .name = "SSC1/I2S PCM Stereo in",
121 .pdc = &pdc_rx_reg,
122 .mask = &ssc_rx_mask,
123 }},
124#endif
125};
126
127struct at91_ssc_state {
128 u32 ssc_cmr;
129 u32 ssc_rcmr;
130 u32 ssc_rfmr;
131 u32 ssc_tcmr;
132 u32 ssc_tfmr;
133 u32 ssc_sr;
134 u32 ssc_imr;
135};
136
137static struct at91_ssc_info {
138 char *name;
139 struct at91_ssc_periph ssc;
140 spinlock_t lock; /* lock for dir_mask */
141 unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
142 unsigned short initialized; /* 1=SSC has been initialized */
143 unsigned short daifmt;
144 unsigned short cmr_div;
145 unsigned short tcmr_period;
146 unsigned short rcmr_period;
147 struct at91_pcm_dma_params *dma_params[2];
148 struct at91_ssc_state ssc_state;
149
150} ssc_info[NUM_SSC_DEVICES] = {
151 {
152 .name = "ssc0",
153 .lock = SPIN_LOCK_UNLOCKED,
154 .dir_mask = 0,
155 .initialized = 0,
156 },
157#if NUM_SSC_DEVICES == 3
158 {
159 .name = "ssc1",
160 .lock = SPIN_LOCK_UNLOCKED,
161 .dir_mask = 0,
162 .initialized = 0,
163 },
164 {
165 .name = "ssc2",
166 .lock = SPIN_LOCK_UNLOCKED,
167 .dir_mask = 0,
168 .initialized = 0,
169 },
170#endif
171};
172
173static unsigned int at91_i2s_sysclk;
174
175/*
176 * SSC interrupt handler. Passes PDC interrupts to the DMA
177 * interrupt handler in the PCM driver.
178 */
179static irqreturn_t at91_i2s_interrupt(int irq, void *dev_id)
180{
181 struct at91_ssc_info *ssc_p = dev_id;
182 struct at91_pcm_dma_params *dma_params;
183 u32 ssc_sr;
184 int i;
185
186 ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)
187 & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
188
189 /*
190 * Loop through the substreams attached to this SSC. If
191 * a DMA-related interrupt occurred on that substream, call
192 * the DMA interrupt handler function, if one has been
193 * registered in the dma_params structure by the PCM driver.
194 */
195 for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
196 dma_params = ssc_p->dma_params[i];
197
198 if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
199 (ssc_sr &
200 (dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
201
202 dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
203 }
204
205 return IRQ_HANDLED;
206}
207
208/*
209 * Startup. Only that one substream allowed in each direction.
210 */
211static int at91_i2s_startup(struct snd_pcm_substream *substream)
212{
213 struct snd_soc_pcm_runtime *rtd = substream->private_data;
214 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
215 int dir_mask;
216
217 DBG("i2s_startup: SSC_SR=0x%08lx\n",
218 at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
219 dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
220
221 spin_lock_irq(&ssc_p->lock);
222 if (ssc_p->dir_mask & dir_mask) {
223 spin_unlock_irq(&ssc_p->lock);
224 return -EBUSY;
225 }
226 ssc_p->dir_mask |= dir_mask;
227 spin_unlock_irq(&ssc_p->lock);
228
229 return 0;
230}
231
232/*
233 * Shutdown. Clear DMA parameters and shutdown the SSC if there
234 * are no other substreams open.
235 */
236static void at91_i2s_shutdown(struct snd_pcm_substream *substream)
237{
238 struct snd_soc_pcm_runtime *rtd = substream->private_data;
239 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
240 struct at91_pcm_dma_params *dma_params;
241 int dir, dir_mask;
242
243 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
244 dma_params = ssc_p->dma_params[dir];
245
246 if (dma_params != NULL) {
247 at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
248 dma_params->mask->ssc_disable);
249 DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
250 at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
251
252 dma_params->ssc_base = NULL;
253 dma_params->substream = NULL;
254 ssc_p->dma_params[dir] = NULL;
255 }
256
257 dir_mask = 1 << dir;
258
259 spin_lock_irq(&ssc_p->lock);
260 ssc_p->dir_mask &= ~dir_mask;
261 if (!ssc_p->dir_mask) {
262 /* Shutdown the SSC clock. */
263 DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
264 at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
265
266 if (ssc_p->initialized) {
267 free_irq(ssc_p->ssc.pid, ssc_p);
268 ssc_p->initialized = 0;
269 }
270
271 /* Reset the SSC */
272 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
273
274 /* Clear the SSC dividers */
275 ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
276 }
277 spin_unlock_irq(&ssc_p->lock);
278}
279
280/*
281 * Record the SSC system clock rate.
282 */
283static int at91_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
284 int clk_id, unsigned int freq, int dir)
285{
286 /*
287 * The only clock supplied to the SSC is the AT91 master clock,
288 * which is only used if the SSC is generating BCLK and/or
289 * LRC clocks.
290 */
291 switch (clk_id) {
292 case AT91_SYSCLK_MCK:
293 at91_i2s_sysclk = freq;
294 break;
295 default:
296 return -EINVAL;
297 }
298
299 return 0;
300}
301
302/*
303 * Record the DAI format for use in hw_params().
304 */
305static int at91_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
306 unsigned int fmt)
307{
308 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
309
310 if ((fmt & SND_SOC_DAIFMT_FORMAT_MASK) != SND_SOC_DAIFMT_I2S)
311 return -EINVAL;
312
313 ssc_p->daifmt = fmt;
314 return 0;
315}
316
317/*
318 * Record SSC clock dividers for use in hw_params().
319 */
320static int at91_i2s_set_dai_clkdiv(struct snd_soc_cpu_dai *cpu_dai,
321 int div_id, int div)
322{
323 struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
324
325 switch (div_id) {
326 case AT91SSC_CMR_DIV:
327 /*
328 * The same master clock divider is used for both
329 * transmit and receive, so if a value has already
330 * been set, it must match this value.
331 */
332 if (ssc_p->cmr_div == 0)
333 ssc_p->cmr_div = div;
334 else
335 if (div != ssc_p->cmr_div)
336 return -EBUSY;
337 break;
338
339 case AT91SSC_TCMR_PERIOD:
340 ssc_p->tcmr_period = div;
341 break;
342
343 case AT91SSC_RCMR_PERIOD:
344 ssc_p->rcmr_period = div;
345 break;
346
347 default:
348 return -EINVAL;
349 }
350
351 return 0;
352}
353
354/*
355 * Configure the SSC.
356 */
357static int at91_i2s_hw_params(struct snd_pcm_substream *substream,
358 struct snd_pcm_hw_params *params)
359{
360 struct snd_soc_pcm_runtime *rtd = substream->private_data;
361 int id = rtd->dai->cpu_dai->id;
362 struct at91_ssc_info *ssc_p = &ssc_info[id];
363 struct at91_pcm_dma_params *dma_params;
364 int dir, channels, bits;
365 u32 tfmr, rfmr, tcmr, rcmr;
366 int start_event;
367 int ret;
368
369 /*
370 * Currently, there is only one set of dma params for
371 * each direction. If more are added, this code will
372 * have to be changed to select the proper set.
373 */
374 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
375
376 dma_params = &ssc_dma_params[id][dir];
377 dma_params->ssc_base = ssc_p->ssc.base;
378 dma_params->substream = substream;
379
380 ssc_p->dma_params[dir] = dma_params;
381
382 /*
383 * The cpu_dai->dma_data field is only used to communicate the
384 * appropriate DMA parameters to the pcm driver hw_params()
385 * function. It should not be used for other purposes
386 * as it is common to all substreams.
387 */
388 rtd->dai->cpu_dai->dma_data = dma_params;
389
390 channels = params_channels(params);
391
392 /*
393 * The SSC only supports up to 16-bit samples in I2S format, due
394 * to the size of the Frame Mode Register FSLEN field. Also, I2S
395 * implies signed data.
396 */
397 bits = 16;
398 dma_params->pdc_xfer_size = 2;
399
400 /*
401 * Compute SSC register settings.
402 */
403 switch (ssc_p->daifmt) {
404 case SND_SOC_DAIFMT_CBS_CFS:
405 /*
406 * SSC provides BCLK and LRC clocks.
407 *
408 * The SSC transmit and receive clocks are generated from the
409 * MCK divider, and the BCLK signal is output on the SSC TK line.
410 */
411 rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
412 | (( 1 << 16) & AT91_SSC_STTDLY)
413 | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
414 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
415 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
416 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
417
418 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
419 | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
420 | (((bits - 1) << 16) & AT91_SSC_FSLEN)
421 | (((channels - 1) << 8) & AT91_SSC_DATNB)
422 | (( 1 << 7) & AT91_SSC_MSBF)
423 | (( 0 << 5) & AT91_SSC_LOOP)
424 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
425
426 tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
427 | (( 1 << 16) & AT91_SSC_STTDLY)
428 | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
429 | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
430 | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
431 | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
432
433 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
434 | (( 0 << 23) & AT91_SSC_FSDEN)
435 | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
436 | (((bits - 1) << 16) & AT91_SSC_FSLEN)
437 | (((channels - 1) << 8) & AT91_SSC_DATNB)
438 | (( 1 << 7) & AT91_SSC_MSBF)
439 | (( 0 << 5) & AT91_SSC_DATDEF)
440 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
441 break;
442
443 case SND_SOC_DAIFMT_CBM_CFM:
444
445 /*
446 * CODEC supplies BCLK and LRC clocks.
447 *
448 * The SSC transmit clock is obtained from the BCLK signal on
449 * on the TK line, and the SSC receive clock is generated from the
450 * transmit clock.
451 *
452 * For single channel data, one sample is transferred on the falling
453 * edge of the LRC clock. For two channel data, one sample is
454 * transferred on both edges of the LRC clock.
455 */
456 start_event = channels == 1
457 ? AT91_SSC_START_FALLING_RF
458 : AT91_SSC_START_EDGE_RF;
459
460 rcmr = (( 0 << 24) & AT91_SSC_PERIOD)
461 | (( 1 << 16) & AT91_SSC_STTDLY)
462 | (( start_event ) & AT91_SSC_START)
463 | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
464 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
465 | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS);
466
467 rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
468 | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
469 | (( 0 << 16) & AT91_SSC_FSLEN)
470 | (( 0 << 8) & AT91_SSC_DATNB)
471 | (( 1 << 7) & AT91_SSC_MSBF)
472 | (( 0 << 5) & AT91_SSC_LOOP)
473 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
474
475 tcmr = (( 0 << 24) & AT91_SSC_PERIOD)
476 | (( 1 << 16) & AT91_SSC_STTDLY)
477 | (( start_event ) & AT91_SSC_START)
478 | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
479 | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
480 | (( AT91_SSC_CKS_PIN ) & AT91_SSC_CKS);
481
482 tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
483 | (( 0 << 23) & AT91_SSC_FSDEN)
484 | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
485 | (( 0 << 16) & AT91_SSC_FSLEN)
486 | (( 0 << 8) & AT91_SSC_DATNB)
487 | (( 1 << 7) & AT91_SSC_MSBF)
488 | (( 0 << 5) & AT91_SSC_DATDEF)
489 | (((bits - 1) << 0) & AT91_SSC_DATALEN);
490 break;
491
492 case SND_SOC_DAIFMT_CBS_CFM:
493 case SND_SOC_DAIFMT_CBM_CFS:
494 default:
495 printk(KERN_WARNING "at91-i2s: unsupported DAI format 0x%x.\n",
496 ssc_p->daifmt);
497 return -EINVAL;
498 break;
499 }
500 DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
501
502 if (!ssc_p->initialized) {
503
504 /* Enable PMC peripheral clock for this SSC */
505 DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
506 at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
507
508 /* Reset the SSC and its PDC registers */
509 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
510
511 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RPR, 0);
512 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RCR, 0);
513 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RNPR, 0);
514 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_RNCR, 0);
515 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TPR, 0);
516 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TCR, 0);
517 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNPR, 0);
518 at91_ssc_write(ssc_p->ssc.base + AT91_PDC_TNCR, 0);
519
520 if ((ret = request_irq(ssc_p->ssc.pid, at91_i2s_interrupt,
521 0, ssc_p->name, ssc_p)) < 0) {
522 printk(KERN_WARNING "at91-i2s: request_irq failure\n");
523
524 DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
525 at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
526 return ret;
527 }
528
529 ssc_p->initialized = 1;
530 }
531
532 /* set SSC clock mode register */
533 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
534
535 /* set receive clock mode and format */
536 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
537 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
538
539 /* set transmit clock mode and format */
540 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
541 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
542
543 DBG("hw_params: SSC initialized\n");
544 return 0;
545}
546
547
548static int at91_i2s_prepare(struct snd_pcm_substream *substream)
549{
550 struct snd_soc_pcm_runtime *rtd = substream->private_data;
551 struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
552 struct at91_pcm_dma_params *dma_params;
553 int dir;
554
555 dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
556 dma_params = ssc_p->dma_params[dir];
557
558 at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
559 dma_params->mask->ssc_enable);
560
561 DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
562 at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
563 return 0;
564}
565
566
567#ifdef CONFIG_PM
568static int at91_i2s_suspend(struct platform_device *pdev,
569 struct snd_soc_cpu_dai *cpu_dai)
570{
571 struct at91_ssc_info *ssc_p;
572
573 if(!cpu_dai->active)
574 return 0;
575
576 ssc_p = &ssc_info[cpu_dai->id];
577
578 /* Save the status register before disabling transmit and receive. */
579 ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR);
580 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
581 AT91_SSC_TXDIS | AT91_SSC_RXDIS);
582
583 /* Save the current interrupt mask, then disable unmasked interrupts. */
584 ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
585 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr);
586
587 ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
588 ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
589 ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
590 ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
591 ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
592
593 return 0;
594}
595
596static int at91_i2s_resume(struct platform_device *pdev,
597 struct snd_soc_cpu_dai *cpu_dai)
598{
599 struct at91_ssc_info *ssc_p;
600
601 if(!cpu_dai->active)
602 return 0;
603
604 ssc_p = &ssc_info[cpu_dai->id];
605
606 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
607 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
608 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
609 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
610 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr);
611
612 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr);
613
614 at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
615 ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
616 ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
617
618 return 0;
619}
620
621#else
622#define at91_i2s_suspend NULL
623#define at91_i2s_resume NULL
624#endif
625
626#define AT91_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
627 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
628 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
629 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
630 SNDRV_PCM_RATE_96000)
631
632struct snd_soc_cpu_dai at91_i2s_dai[NUM_SSC_DEVICES] = {
633 { .name = "at91_ssc0/i2s",
634 .id = 0,
635 .type = SND_SOC_DAI_I2S,
636 .suspend = at91_i2s_suspend,
637 .resume = at91_i2s_resume,
638 .playback = {
639 .channels_min = 1,
640 .channels_max = 2,
641 .rates = AT91_I2S_RATES,
642 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
643 .capture = {
644 .channels_min = 1,
645 .channels_max = 2,
646 .rates = AT91_I2S_RATES,
647 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
648 .ops = {
649 .startup = at91_i2s_startup,
650 .shutdown = at91_i2s_shutdown,
651 .prepare = at91_i2s_prepare,
652 .hw_params = at91_i2s_hw_params,},
653 .dai_ops = {
654 .set_sysclk = at91_i2s_set_dai_sysclk,
655 .set_fmt = at91_i2s_set_dai_fmt,
656 .set_clkdiv = at91_i2s_set_dai_clkdiv,},
657 .private_data = &ssc_info[0].ssc,
658 },
659#if NUM_SSC_DEVICES == 3
660 { .name = "at91_ssc1/i2s",
661 .id = 1,
662 .type = SND_SOC_DAI_I2S,
663 .suspend = at91_i2s_suspend,
664 .resume = at91_i2s_resume,
665 .playback = {
666 .channels_min = 1,
667 .channels_max = 2,
668 .rates = AT91_I2S_RATES,
669 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
670 .capture = {
671 .channels_min = 1,
672 .channels_max = 2,
673 .rates = AT91_I2S_RATES,
674 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
675 .ops = {
676 .startup = at91_i2s_startup,
677 .shutdown = at91_i2s_shutdown,
678 .prepare = at91_i2s_prepare,
679 .hw_params = at91_i2s_hw_params,},
680 .dai_ops = {
681 .set_sysclk = at91_i2s_set_dai_sysclk,
682 .set_fmt = at91_i2s_set_dai_fmt,
683 .set_clkdiv = at91_i2s_set_dai_clkdiv,},
684 .private_data = &ssc_info[1].ssc,
685 },
686 { .name = "at91_ssc2/i2s",
687 .id = 2,
688 .type = SND_SOC_DAI_I2S,
689 .suspend = at91_i2s_suspend,
690 .resume = at91_i2s_resume,
691 .playback = {
692 .channels_min = 1,
693 .channels_max = 2,
694 .rates = AT91_I2S_RATES,
695 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
696 .capture = {
697 .channels_min = 1,
698 .channels_max = 2,
699 .rates = AT91_I2S_RATES,
700 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
701 .ops = {
702 .startup = at91_i2s_startup,
703 .shutdown = at91_i2s_shutdown,
704 .prepare = at91_i2s_prepare,
705 .hw_params = at91_i2s_hw_params,},
706 .dai_ops = {
707 .set_sysclk = at91_i2s_set_dai_sysclk,
708 .set_fmt = at91_i2s_set_dai_fmt,
709 .set_clkdiv = at91_i2s_set_dai_clkdiv,},
710 .private_data = &ssc_info[2].ssc,
711 },
712#endif
713};
714
715EXPORT_SYMBOL_GPL(at91_i2s_dai);
716
717/* Module information */
718MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
719MODULE_DESCRIPTION("AT91 I2S ASoC Interface");
720MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-i2s.h b/sound/soc/at91/at91-i2s.h
new file mode 100644
index 000000000000..f8a875ba0ccc
--- /dev/null
+++ b/sound/soc/at91/at91-i2s.h
@@ -0,0 +1,27 @@
1/*
2 * at91-i2s.h - ALSA I2S interface for the Atmel AT91 SoC
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Jan 9, 2007
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _AT91_I2S_H
14#define _AT91_I2S_H
15
16/* I2S system clock ids */
17#define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
18
19/* I2S divider ids */
20#define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */
21#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
22#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
23
24extern struct snd_soc_cpu_dai at91_i2s_dai[];
25
26#endif /* _AT91_I2S_H */
27
diff --git a/sound/soc/at91/at91-pcm.c b/sound/soc/at91/at91-pcm.c
new file mode 100644
index 000000000000..e88b12e7cc40
--- /dev/null
+++ b/sound/soc/at91/at91-pcm.c
@@ -0,0 +1,432 @@
1/*
2 * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Mar 3, 2006
7 *
8 * Based on pxa2xx-pcm.c by:
9 *
10 * Author: Nicolas Pitre
11 * Created: Nov 30, 2004
12 * Copyright: (C) 2004 MontaVista Software, Inc.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#include <linux/module.h>
20#include <linux/init.h>
21#include <linux/platform_device.h>
22#include <linux/slab.h>
23#include <linux/dma-mapping.h>
24
25#include <sound/driver.h>
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/pcm_params.h>
29#include <sound/soc.h>
30
31#include <asm/arch/hardware.h>
32#include <asm/arch/at91_ssc.h>
33#include <asm/arch/at91_pdc.h>
34
35#include "at91-pcm.h"
36
37#if 0
38#define DBG(x...) printk(KERN_INFO "at91-pcm: " x)
39#else
40#define DBG(x...)
41#endif
42
43static const struct snd_pcm_hardware at91_pcm_hardware = {
44 .info = SNDRV_PCM_INFO_MMAP |
45 SNDRV_PCM_INFO_MMAP_VALID |
46 SNDRV_PCM_INFO_INTERLEAVED |
47 SNDRV_PCM_INFO_PAUSE,
48 .formats = SNDRV_PCM_FMTBIT_S16_LE,
49 .period_bytes_min = 32,
50 .period_bytes_max = 8192,
51 .periods_min = 2,
52 .periods_max = 1024,
53 .buffer_bytes_max = 32 * 1024,
54};
55
56struct at91_runtime_data {
57 struct at91_pcm_dma_params *params;
58 dma_addr_t dma_buffer; /* physical address of dma buffer */
59 dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
60 size_t period_size;
61 dma_addr_t period_ptr; /* physical address of next period */
62 u32 pdc_xpr_save; /* PDC register save */
63 u32 pdc_xcr_save;
64 u32 pdc_xnpr_save;
65 u32 pdc_xncr_save;
66};
67
68static void at91_pcm_dma_irq(u32 ssc_sr,
69 struct snd_pcm_substream *substream)
70{
71 struct at91_runtime_data *prtd = substream->runtime->private_data;
72 struct at91_pcm_dma_params *params = prtd->params;
73 static int count = 0;
74
75 count++;
76
77 if (ssc_sr & params->mask->ssc_endbuf) {
78
79 printk(KERN_WARNING
80 "at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
81 substream->stream == SNDRV_PCM_STREAM_PLAYBACK
82 ? "underrun" : "overrun",
83 params->name, ssc_sr, count);
84
85 /* re-start the PDC */
86 at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
87
88 prtd->period_ptr += prtd->period_size;
89 if (prtd->period_ptr >= prtd->dma_buffer_end) {
90 prtd->period_ptr = prtd->dma_buffer;
91 }
92
93 at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
94 at91_ssc_write(params->ssc_base + params->pdc->xcr,
95 prtd->period_size / params->pdc_xfer_size);
96
97 at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
98 }
99
100 if (ssc_sr & params->mask->ssc_endx) {
101
102 /* Load the PDC next pointer and counter registers */
103 prtd->period_ptr += prtd->period_size;
104 if (prtd->period_ptr >= prtd->dma_buffer_end) {
105 prtd->period_ptr = prtd->dma_buffer;
106 }
107 at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
108 at91_ssc_write(params->ssc_base + params->pdc->xncr,
109 prtd->period_size / params->pdc_xfer_size);
110 }
111
112 snd_pcm_period_elapsed(substream);
113}
114
115static int at91_pcm_hw_params(struct snd_pcm_substream *substream,
116 struct snd_pcm_hw_params *params)
117{
118 struct snd_pcm_runtime *runtime = substream->runtime;
119 struct at91_runtime_data *prtd = runtime->private_data;
120 struct snd_soc_pcm_runtime *rtd = substream->private_data;
121
122 /* this may get called several times by oss emulation
123 * with different params */
124
125 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
126 runtime->dma_bytes = params_buffer_bytes(params);
127
128 prtd->params = rtd->dai->cpu_dai->dma_data;
129 prtd->params->dma_intr_handler = at91_pcm_dma_irq;
130
131 prtd->dma_buffer = runtime->dma_addr;
132 prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
133 prtd->period_size = params_period_bytes(params);
134
135 DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n",
136 prtd->params->name, runtime->dma_bytes, prtd->period_size);
137 return 0;
138}
139
140static int at91_pcm_hw_free(struct snd_pcm_substream *substream)
141{
142 struct at91_runtime_data *prtd = substream->runtime->private_data;
143 struct at91_pcm_dma_params *params = prtd->params;
144
145 if (params != NULL) {
146 at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
147 prtd->params->dma_intr_handler = NULL;
148 }
149
150 return 0;
151}
152
153static int at91_pcm_prepare(struct snd_pcm_substream *substream)
154{
155 struct at91_runtime_data *prtd = substream->runtime->private_data;
156 struct at91_pcm_dma_params *params = prtd->params;
157
158 at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
159 params->mask->ssc_endx | params->mask->ssc_endbuf);
160
161 at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
162 return 0;
163}
164
165static int at91_pcm_trigger(struct snd_pcm_substream *substream,
166 int cmd)
167{
168 struct at91_runtime_data *prtd = substream->runtime->private_data;
169 struct at91_pcm_dma_params *params = prtd->params;
170 int ret = 0;
171
172 switch (cmd) {
173 case SNDRV_PCM_TRIGGER_START:
174 prtd->period_ptr = prtd->dma_buffer;
175
176 at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
177 at91_ssc_write(params->ssc_base + params->pdc->xcr,
178 prtd->period_size / params->pdc_xfer_size);
179
180 prtd->period_ptr += prtd->period_size;
181 at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
182 at91_ssc_write(params->ssc_base + params->pdc->xncr,
183 prtd->period_size / params->pdc_xfer_size);
184
185 DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n",
186 (unsigned long) prtd->period_ptr,
187 at91_ssc_read(params->ssc_base + params->pdc->xpr),
188 at91_ssc_read(params->ssc_base + params->pdc->xcr),
189 at91_ssc_read(params->ssc_base + params->pdc->xnpr),
190 at91_ssc_read(params->ssc_base + params->pdc->xncr));
191
192 at91_ssc_write(params->ssc_base + AT91_SSC_IER,
193 params->mask->ssc_endx | params->mask->ssc_endbuf);
194
195 at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
196
197 DBG("sr=%lx imr=%lx\n", at91_ssc_read(params->ssc_base + AT91_SSC_SR),
198 at91_ssc_read(params->ssc_base + AT91_SSC_IER));
199 break;
200
201 case SNDRV_PCM_TRIGGER_STOP:
202 case SNDRV_PCM_TRIGGER_SUSPEND:
203 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
204 at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
205 break;
206
207 case SNDRV_PCM_TRIGGER_RESUME:
208 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
209 at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
210 break;
211
212 default:
213 ret = -EINVAL;
214 }
215
216 return ret;
217}
218
219static snd_pcm_uframes_t at91_pcm_pointer(
220 struct snd_pcm_substream *substream)
221{
222 struct snd_pcm_runtime *runtime = substream->runtime;
223 struct at91_runtime_data *prtd = runtime->private_data;
224 struct at91_pcm_dma_params *params = prtd->params;
225 dma_addr_t ptr;
226 snd_pcm_uframes_t x;
227
228 ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr);
229 x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
230
231 if (x == runtime->buffer_size)
232 x = 0;
233 return x;
234}
235
236static int at91_pcm_open(struct snd_pcm_substream *substream)
237{
238 struct snd_pcm_runtime *runtime = substream->runtime;
239 struct at91_runtime_data *prtd;
240 int ret = 0;
241
242 snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware);
243
244 /* ensure that buffer size is a multiple of period size */
245 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
246 if (ret < 0)
247 goto out;
248
249 prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL);
250 if (prtd == NULL) {
251 ret = -ENOMEM;
252 goto out;
253 }
254 runtime->private_data = prtd;
255
256 out:
257 return ret;
258}
259
260static int at91_pcm_close(struct snd_pcm_substream *substream)
261{
262 struct at91_runtime_data *prtd = substream->runtime->private_data;
263
264 kfree(prtd);
265 return 0;
266}
267
268static int at91_pcm_mmap(struct snd_pcm_substream *substream,
269 struct vm_area_struct *vma)
270{
271 struct snd_pcm_runtime *runtime = substream->runtime;
272
273 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
274 runtime->dma_area,
275 runtime->dma_addr,
276 runtime->dma_bytes);
277}
278
279struct snd_pcm_ops at91_pcm_ops = {
280 .open = at91_pcm_open,
281 .close = at91_pcm_close,
282 .ioctl = snd_pcm_lib_ioctl,
283 .hw_params = at91_pcm_hw_params,
284 .hw_free = at91_pcm_hw_free,
285 .prepare = at91_pcm_prepare,
286 .trigger = at91_pcm_trigger,
287 .pointer = at91_pcm_pointer,
288 .mmap = at91_pcm_mmap,
289};
290
291static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
292 int stream)
293{
294 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
295 struct snd_dma_buffer *buf = &substream->dma_buffer;
296 size_t size = at91_pcm_hardware.buffer_bytes_max;
297
298 buf->dev.type = SNDRV_DMA_TYPE_DEV;
299 buf->dev.dev = pcm->card->dev;
300 buf->private_data = NULL;
301 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
302 &buf->addr, GFP_KERNEL);
303
304 DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
305 (void *) buf->area,
306 (void *) buf->addr,
307 size);
308
309 if (!buf->area)
310 return -ENOMEM;
311
312 buf->bytes = size;
313 return 0;
314}
315
316static u64 at91_pcm_dmamask = 0xffffffff;
317
318static int at91_pcm_new(struct snd_card *card,
319 struct snd_soc_codec_dai *dai, struct snd_pcm *pcm)
320{
321 int ret = 0;
322
323 if (!card->dev->dma_mask)
324 card->dev->dma_mask = &at91_pcm_dmamask;
325 if (!card->dev->coherent_dma_mask)
326 card->dev->coherent_dma_mask = 0xffffffff;
327
328 if (dai->playback.channels_min) {
329 ret = at91_pcm_preallocate_dma_buffer(pcm,
330 SNDRV_PCM_STREAM_PLAYBACK);
331 if (ret)
332 goto out;
333 }
334
335 if (dai->capture.channels_min) {
336 ret = at91_pcm_preallocate_dma_buffer(pcm,
337 SNDRV_PCM_STREAM_CAPTURE);
338 if (ret)
339 goto out;
340 }
341 out:
342 return ret;
343}
344
345static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm)
346{
347 struct snd_pcm_substream *substream;
348 struct snd_dma_buffer *buf;
349 int stream;
350
351 for (stream = 0; stream < 2; stream++) {
352 substream = pcm->streams[stream].substream;
353 if (!substream)
354 continue;
355
356 buf = &substream->dma_buffer;
357 if (!buf->area)
358 continue;
359
360 dma_free_writecombine(pcm->card->dev, buf->bytes,
361 buf->area, buf->addr);
362 buf->area = NULL;
363 }
364}
365
366#ifdef CONFIG_PM
367static int at91_pcm_suspend(struct platform_device *pdev,
368 struct snd_soc_cpu_dai *dai)
369{
370 struct snd_pcm_runtime *runtime = dai->runtime;
371 struct at91_runtime_data *prtd;
372 struct at91_pcm_dma_params *params;
373
374 if (!runtime)
375 return 0;
376
377 prtd = runtime->private_data;
378 params = prtd->params;
379
380 /* disable the PDC and save the PDC registers */
381
382 at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_disable);
383
384 prtd->pdc_xpr_save = at91_ssc_read(params->ssc_base + params->pdc->xpr);
385 prtd->pdc_xcr_save = at91_ssc_read(params->ssc_base + params->pdc->xcr);
386 prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr);
387 prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr);
388
389 return 0;
390}
391
392static int at91_pcm_resume(struct platform_device *pdev,
393 struct snd_soc_cpu_dai *dai)
394{
395 struct snd_pcm_runtime *runtime = dai->runtime;
396 struct at91_runtime_data *prtd;
397 struct at91_pcm_dma_params *params;
398
399 if (!runtime)
400 return 0;
401
402 prtd = runtime->private_data;
403 params = prtd->params;
404
405 /* restore the PDC registers and enable the PDC */
406 at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->pdc_xpr_save);
407 at91_ssc_write(params->ssc_base + params->pdc->xcr, prtd->pdc_xcr_save);
408 at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
409 at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
410
411 at91_ssc_write(params->ssc_base + AT91_PDC_PTCR, params->mask->pdc_enable);
412 return 0;
413}
414#else
415#define at91_pcm_suspend NULL
416#define at91_pcm_resume NULL
417#endif
418
419struct snd_soc_platform at91_soc_platform = {
420 .name = "at91-audio",
421 .pcm_ops = &at91_pcm_ops,
422 .pcm_new = at91_pcm_new,
423 .pcm_free = at91_pcm_free_dma_buffers,
424 .suspend = at91_pcm_suspend,
425 .resume = at91_pcm_resume,
426};
427
428EXPORT_SYMBOL_GPL(at91_soc_platform);
429
430MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
431MODULE_DESCRIPTION("Atmel AT91 PCM module");
432MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-pcm.h b/sound/soc/at91/at91-pcm.h
new file mode 100644
index 000000000000..58d0f00a07b2
--- /dev/null
+++ b/sound/soc/at91/at91-pcm.h
@@ -0,0 +1,72 @@
1/*
2 * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Mar 3, 2006
7 *
8 * Based on pxa2xx-pcm.h by:
9 *
10 * Author: Nicolas Pitre
11 * Created: Nov 30, 2004
12 * Copyright: MontaVista Software, Inc.
13 *
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License version 2 as
16 * published by the Free Software Foundation.
17 */
18
19#ifndef _AT91_PCM_H
20#define _AT91_PCM_H
21
22#include <asm/arch/hardware.h>
23
24struct at91_ssc_periph {
25 void __iomem *base;
26 u32 pid;
27};
28
29/*
30 * Registers and status bits that are required by the PCM driver.
31 */
32struct at91_pdc_regs {
33 unsigned int xpr; /* PDC recv/trans pointer */
34 unsigned int xcr; /* PDC recv/trans counter */
35 unsigned int xnpr; /* PDC next recv/trans pointer */
36 unsigned int xncr; /* PDC next recv/trans counter */
37 unsigned int ptcr; /* PDC transfer control */
38};
39
40struct at91_ssc_mask {
41 u32 ssc_enable; /* SSC recv/trans enable */
42 u32 ssc_disable; /* SSC recv/trans disable */
43 u32 ssc_endx; /* SSC ENDTX or ENDRX */
44 u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
45 u32 pdc_enable; /* PDC recv/trans enable */
46 u32 pdc_disable; /* PDC recv/trans disable */
47};
48
49/*
50 * This structure, shared between the PCM driver and the interface,
51 * contains all information required by the PCM driver to perform the
52 * PDC DMA operation. All fields except dma_intr_handler() are initialized
53 * by the interface. The dms_intr_handler() pointer is set by the PCM
54 * driver and called by the interface SSC interrupt handler if it is
55 * non-NULL.
56 */
57struct at91_pcm_dma_params {
58 char *name; /* stream identifier */
59 int pdc_xfer_size; /* PDC counter increment in bytes */
60 void __iomem *ssc_base; /* SSC base address */
61 struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */
62 struct at91_ssc_mask *mask;/* SSC & PDC status bits */
63 struct snd_pcm_substream *substream;
64 void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
65};
66
67extern struct snd_soc_platform at91_soc_platform;
68
69#define at91_ssc_read(a) ((unsigned long) __raw_readl(a))
70#define at91_ssc_write(a,v) __raw_writel((v),(a))
71
72#endif /* _AT91_PCM_H */
diff --git a/sound/soc/at91/eti_b1_wm8731.c b/sound/soc/at91/eti_b1_wm8731.c
new file mode 100644
index 000000000000..8179df3bb2f3
--- /dev/null
+++ b/sound/soc/at91/eti_b1_wm8731.c
@@ -0,0 +1,375 @@
1/*
2 * eti_b1_wm8731 -- SoC audio for AT91RM9200-based Endrelia ETI_B1 board.
3 *
4 * Author: Frank Mandarino <fmandarino@endrelia.com>
5 * Endrelia Technologies Inc.
6 * Created: Mar 29, 2006
7 *
8 * Based on corgi.c by:
9 *
10 * Copyright 2005 Wolfson Microelectronics PLC.
11 * Copyright 2005 Openedhand Ltd.
12 *
13 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
14 * Richard Purdie <richard@openedhand.com>
15 *
16 * This program is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the
18 * Free Software Foundation; either version 2 of the License, or (at your
19 * option) any later version.
20 *
21 */
22
23#include <linux/module.h>
24#include <linux/moduleparam.h>
25#include <linux/version.h>
26#include <linux/kernel.h>
27#include <linux/clk.h>
28#include <linux/timer.h>
29#include <linux/interrupt.h>
30#include <linux/platform_device.h>
31#include <sound/driver.h>
32#include <sound/core.h>
33#include <sound/pcm.h>
34#include <sound/soc.h>
35#include <sound/soc-dapm.h>
36
37#include <asm/arch/hardware.h>
38#include <asm/arch/at91_pio.h>
39#include <asm/arch/gpio.h>
40
41#include "../codecs/wm8731.h"
42#include "at91-pcm.h"
43#include "at91-i2s.h"
44
45#if 0
46#define DBG(x...) printk(KERN_INFO "eti_b1_wm8731: " x)
47#else
48#define DBG(x...)
49#endif
50
51#define AT91_PIO_TF1 (1 << (AT91_PIN_PB6 - PIN_BASE) % 32)
52#define AT91_PIO_TK1 (1 << (AT91_PIN_PB7 - PIN_BASE) % 32)
53#define AT91_PIO_TD1 (1 << (AT91_PIN_PB8 - PIN_BASE) % 32)
54#define AT91_PIO_RD1 (1 << (AT91_PIN_PB9 - PIN_BASE) % 32)
55#define AT91_PIO_RK1 (1 << (AT91_PIN_PB10 - PIN_BASE) % 32)
56#define AT91_PIO_RF1 (1 << (AT91_PIN_PB11 - PIN_BASE) % 32)
57
58static struct clk *pck1_clk;
59static struct clk *pllb_clk;
60
61
62static int eti_b1_startup(struct snd_pcm_substream *substream)
63{
64 struct snd_soc_pcm_runtime *rtd = substream->private_data;
65 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
66 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
67 int ret;
68
69 /* cpu clock is the AT91 master clock sent to the SSC */
70 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, AT91_SYSCLK_MCK,
71 60000000, SND_SOC_CLOCK_IN);
72 if (ret < 0)
73 return ret;
74
75 /* codec system clock is supplied by PCK1, set to 12MHz */
76 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK,
77 12000000, SND_SOC_CLOCK_IN);
78 if (ret < 0)
79 return ret;
80
81 /* Start PCK1 clock. */
82 clk_enable(pck1_clk);
83 DBG("pck1 started\n");
84
85 return 0;
86}
87
88static void eti_b1_shutdown(struct snd_pcm_substream *substream)
89{
90 /* Stop PCK1 clock. */
91 clk_disable(pck1_clk);
92 DBG("pck1 stopped\n");
93}
94
95static int eti_b1_hw_params(struct snd_pcm_substream *substream,
96 struct snd_pcm_hw_params *params)
97{
98 struct snd_soc_pcm_runtime *rtd = substream->private_data;
99 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
100 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
101 int ret;
102
103#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
104 unsigned int rate;
105 int cmr_div, period;
106
107 /* set codec DAI configuration */
108 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
109 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
110 if (ret < 0)
111 return ret;
112
113 /* set cpu DAI configuration */
114 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
115 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
116 if (ret < 0)
117 return ret;
118
119 /*
120 * The SSC clock dividers depend on the sample rate. The CMR.DIV
121 * field divides the system master clock MCK to drive the SSC TK
122 * signal which provides the codec BCLK. The TCMR.PERIOD and
123 * RCMR.PERIOD fields further divide the BCLK signal to drive
124 * the SSC TF and RF signals which provide the codec DACLRC and
125 * ADCLRC clocks.
126 *
127 * The dividers were determined through trial and error, where a
128 * CMR.DIV value is chosen such that the resulting BCLK value is
129 * divisible, or almost divisible, by (2 * sample rate), and then
130 * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
131 */
132 rate = params_rate(params);
133
134 switch (rate) {
135 case 8000:
136 cmr_div = 25; /* BCLK = 60MHz/(2*25) = 1.2MHz */
137 period = 74; /* LRC = BCLK/(2*(74+1)) = 8000Hz */
138 break;
139 case 32000:
140 cmr_div = 7; /* BCLK = 60MHz/(2*7) ~= 4.28571428MHz */
141 period = 66; /* LRC = BCLK/(2*(66+1)) = 31982.942Hz */
142 break;
143 case 48000:
144 cmr_div = 13; /* BCLK = 60MHz/(2*13) ~= 2.3076923MHz */
145 period = 23; /* LRC = BCLK/(2*(23+1)) = 48076.923Hz */
146 break;
147 default:
148 printk(KERN_WARNING "unsupported rate %d on ETI-B1 board\n", rate);
149 return -EINVAL;
150 }
151
152 /* set the MCK divider for BCLK */
153 ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai, AT91SSC_CMR_DIV, cmr_div);
154 if (ret < 0)
155 return ret;
156
157 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
158 /* set the BCLK divider for DACLRC */
159 ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
160 AT91SSC_TCMR_PERIOD, period);
161 } else {
162 /* set the BCLK divider for ADCLRC */
163 ret = cpu_dai->dai_ops.set_clkdiv(cpu_dai,
164 AT91SSC_RCMR_PERIOD, period);
165 }
166 if (ret < 0)
167 return ret;
168
169#else /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
170 /*
171 * Codec in Master Mode.
172 */
173
174 /* set codec DAI configuration */
175 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
176 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
177 if (ret < 0)
178 return ret;
179
180 /* set cpu DAI configuration */
181 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
182 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
183 if (ret < 0)
184 return ret;
185
186#endif /* CONFIG_SND_AT91_SOC_ETI_SLAVE */
187
188 return 0;
189}
190
191static struct snd_soc_ops eti_b1_ops = {
192 .startup = eti_b1_startup,
193 .hw_params = eti_b1_hw_params,
194 .shutdown = eti_b1_shutdown,
195};
196
197
198static const struct snd_soc_dapm_widget eti_b1_dapm_widgets[] = {
199 SND_SOC_DAPM_MIC("Int Mic", NULL),
200 SND_SOC_DAPM_SPK("Ext Spk", NULL),
201};
202
203static const char *intercon[][3] = {
204
205 /* speaker connected to LHPOUT */
206 {"Ext Spk", NULL, "LHPOUT"},
207
208 /* mic is connected to Mic Jack, with WM8731 Mic Bias */
209 {"MICIN", NULL, "Mic Bias"},
210 {"Mic Bias", NULL, "Int Mic"},
211
212 /* terminator */
213 {NULL, NULL, NULL},
214};
215
216/*
217 * Logic for a wm8731 as connected on a Endrelia ETI-B1 board.
218 */
219static int eti_b1_wm8731_init(struct snd_soc_codec *codec)
220{
221 int i;
222
223 DBG("eti_b1_wm8731_init() called\n");
224
225 /* Add specific widgets */
226 for(i = 0; i < ARRAY_SIZE(eti_b1_dapm_widgets); i++) {
227 snd_soc_dapm_new_control(codec, &eti_b1_dapm_widgets[i]);
228 }
229
230 /* Set up specific audio path interconnects */
231 for(i = 0; intercon[i][0] != NULL; i++) {
232 snd_soc_dapm_connect_input(codec, intercon[i][0],
233 intercon[i][1], intercon[i][2]);
234 }
235
236 /* not connected */
237 snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
238 snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
239
240 /* always connected */
241 snd_soc_dapm_set_endpoint(codec, "Int Mic", 1);
242 snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
243
244 snd_soc_dapm_sync_endpoints(codec);
245
246 return 0;
247}
248
249static struct snd_soc_dai_link eti_b1_dai = {
250 .name = "WM8731",
251 .stream_name = "WM8731",
252 .cpu_dai = &at91_i2s_dai[1],
253 .codec_dai = &wm8731_dai,
254 .init = eti_b1_wm8731_init,
255 .ops = &eti_b1_ops,
256};
257
258static struct snd_soc_machine snd_soc_machine_eti_b1 = {
259 .name = "ETI_B1",
260 .dai_link = &eti_b1_dai,
261 .num_links = 1,
262};
263
264static struct wm8731_setup_data eti_b1_wm8731_setup = {
265 .i2c_address = 0x1a,
266};
267
268static struct snd_soc_device eti_b1_snd_devdata = {
269 .machine = &snd_soc_machine_eti_b1,
270 .platform = &at91_soc_platform,
271 .codec_dev = &soc_codec_dev_wm8731,
272 .codec_data = &eti_b1_wm8731_setup,
273};
274
275static struct platform_device *eti_b1_snd_device;
276
277static int __init eti_b1_init(void)
278{
279 int ret;
280 u32 ssc_pio_lines;
281 struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
282
283 if (!request_mem_region(AT91RM9200_BASE_SSC1, SZ_16K, "soc-audio")) {
284 DBG("SSC1 memory region is busy\n");
285 return -EBUSY;
286 }
287
288 ssc->base = ioremap(AT91RM9200_BASE_SSC1, SZ_16K);
289 if (!ssc->base) {
290 DBG("SSC1 memory ioremap failed\n");
291 ret = -ENOMEM;
292 goto fail_release_mem;
293 }
294
295 ssc->pid = AT91RM9200_ID_SSC1;
296
297 eti_b1_snd_device = platform_device_alloc("soc-audio", -1);
298 if (!eti_b1_snd_device) {
299 DBG("platform device allocation failed\n");
300 ret = -ENOMEM;
301 goto fail_io_unmap;
302 }
303
304 platform_set_drvdata(eti_b1_snd_device, &eti_b1_snd_devdata);
305 eti_b1_snd_devdata.dev = &eti_b1_snd_device->dev;
306
307 ret = platform_device_add(eti_b1_snd_device);
308 if (ret) {
309 DBG("platform device add failed\n");
310 platform_device_put(eti_b1_snd_device);
311 goto fail_io_unmap;
312 }
313
314 ssc_pio_lines = AT91_PIO_TF1 | AT91_PIO_TK1 | AT91_PIO_TD1
315 | AT91_PIO_RD1 /* | AT91_PIO_RK1 */ | AT91_PIO_RF1;
316
317 /* Reset all PIO registers and assign lines to peripheral A */
318 at91_sys_write(AT91_PIOB + PIO_PDR, ssc_pio_lines);
319 at91_sys_write(AT91_PIOB + PIO_ODR, ssc_pio_lines);
320 at91_sys_write(AT91_PIOB + PIO_IFDR, ssc_pio_lines);
321 at91_sys_write(AT91_PIOB + PIO_CODR, ssc_pio_lines);
322 at91_sys_write(AT91_PIOB + PIO_IDR, ssc_pio_lines);
323 at91_sys_write(AT91_PIOB + PIO_MDDR, ssc_pio_lines);
324 at91_sys_write(AT91_PIOB + PIO_PUDR, ssc_pio_lines);
325 at91_sys_write(AT91_PIOB + PIO_ASR, ssc_pio_lines);
326 at91_sys_write(AT91_PIOB + PIO_OWDR, ssc_pio_lines);
327
328 /*
329 * Set PCK1 parent to PLLB and its rate to 12 Mhz.
330 */
331 pllb_clk = clk_get(NULL, "pllb");
332 pck1_clk = clk_get(NULL, "pck1");
333
334 clk_set_parent(pck1_clk, pllb_clk);
335 clk_set_rate(pck1_clk, 12000000);
336
337 DBG("MCLK rate %luHz\n", clk_get_rate(pck1_clk));
338
339 /* assign the GPIO pin to PCK1 */
340 at91_set_B_periph(AT91_PIN_PA24, 0);
341
342#ifdef CONFIG_SND_AT91_SOC_ETI_SLAVE
343 printk(KERN_INFO "eti_b1_wm8731: Codec in Slave Mode\n");
344#else
345 printk(KERN_INFO "eti_b1_wm8731: Codec in Master Mode\n");
346#endif
347 return ret;
348
349fail_io_unmap:
350 iounmap(ssc->base);
351fail_release_mem:
352 release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
353 return ret;
354}
355
356static void __exit eti_b1_exit(void)
357{
358 struct at91_ssc_periph *ssc = eti_b1_dai.cpu_dai->private_data;
359
360 clk_put(pck1_clk);
361 clk_put(pllb_clk);
362
363 platform_device_unregister(eti_b1_snd_device);
364
365 iounmap(ssc->base);
366 release_mem_region(AT91RM9200_BASE_SSC1, SZ_16K);
367}
368
369module_init(eti_b1_init);
370module_exit(eti_b1_exit);
371
372/* Module information */
373MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
374MODULE_DESCRIPTION("ALSA SoC ETI-B1-WM8731");
375MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
new file mode 100644
index 000000000000..78ac2688e124
--- /dev/null
+++ b/sound/soc/codecs/Kconfig
@@ -0,0 +1,15 @@
1config SND_SOC_AC97_CODEC
2 tristate
3 depends SND_SOC
4
5config SND_SOC_WM8731
6 tristate
7 depends SND_SOC
8
9config SND_SOC_WM8750
10 tristate
11 depends SND_SOC
12
13config SND_SOC_WM9712
14 tristate
15 depends SND_SOC
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
new file mode 100644
index 000000000000..3249a6e4f1d0
--- /dev/null
+++ b/sound/soc/codecs/Makefile
@@ -0,0 +1,9 @@
1snd-soc-ac97-objs := ac97.o
2snd-soc-wm8731-objs := wm8731.o
3snd-soc-wm8750-objs := wm8750.o
4snd-soc-wm9712-objs := wm9712.o
5
6obj-$(CONFIG_SND_SOC_AC97_CODEC) += snd-soc-ac97.o
7obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
8obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
9obj-$(CONFIG_SND_SOC_WM9712) += snd-soc-wm9712.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
new file mode 100644
index 000000000000..55bc55eb6e24
--- /dev/null
+++ b/sound/soc/codecs/ac97.c
@@ -0,0 +1,156 @@
1/*
2 * ac97.c -- ALSA Soc AC97 codec support
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Revision history
14 * 17th Oct 2005 Initial version.
15 *
16 * Generic AC97 support.
17 */
18
19#include <linux/init.h>
20#include <linux/kernel.h>
21#include <linux/device.h>
22#include <sound/driver.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/ac97_codec.h>
26#include <sound/initval.h>
27#include <sound/soc.h>
28
29#define AC97_VERSION "0.6"
30
31static int ac97_prepare(struct snd_pcm_substream *substream)
32{
33 struct snd_pcm_runtime *runtime = substream->runtime;
34 struct snd_soc_pcm_runtime *rtd = substream->private_data;
35 struct snd_soc_device *socdev = rtd->socdev;
36 struct snd_soc_codec *codec = socdev->codec;
37
38 int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
39 AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE;
40 return snd_ac97_set_rate(codec->ac97, reg, runtime->rate);
41}
42
43#define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
44 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
45
46static struct snd_soc_codec_dai ac97_dai = {
47 .name = "AC97 HiFi",
48 .playback = {
49 .stream_name = "AC97 Playback",
50 .channels_min = 1,
51 .channels_max = 2,
52 .rates = STD_AC97_RATES,
53 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
54 .capture = {
55 .stream_name = "AC97 Capture",
56 .channels_min = 1,
57 .channels_max = 2,
58 .rates = STD_AC97_RATES,
59 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
60 .ops = {
61 .prepare = ac97_prepare,},
62};
63
64static unsigned int ac97_read(struct snd_soc_codec *codec,
65 unsigned int reg)
66{
67 return soc_ac97_ops.read(codec->ac97, reg);
68}
69
70static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
71 unsigned int val)
72{
73 soc_ac97_ops.write(codec->ac97, reg, val);
74 return 0;
75}
76
77static int ac97_soc_probe(struct platform_device *pdev)
78{
79 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
80 struct snd_soc_codec *codec;
81 struct snd_ac97_bus *ac97_bus;
82 struct snd_ac97_template ac97_template;
83 int ret = 0;
84
85 printk(KERN_INFO "AC97 SoC Audio Codec %s\n", AC97_VERSION);
86
87 socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
88 if (socdev->codec == NULL)
89 return -ENOMEM;
90 codec = socdev->codec;
91 mutex_init(&codec->mutex);
92
93 codec->name = "AC97";
94 codec->owner = THIS_MODULE;
95 codec->dai = &ac97_dai;
96 codec->num_dai = 1;
97 codec->write = ac97_write;
98 codec->read = ac97_read;
99 INIT_LIST_HEAD(&codec->dapm_widgets);
100 INIT_LIST_HEAD(&codec->dapm_paths);
101
102 /* register pcms */
103 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
104 if(ret < 0)
105 goto err;
106
107 /* add codec as bus device for standard ac97 */
108 ret = snd_ac97_bus(codec->card, 0, &soc_ac97_ops, NULL, &ac97_bus);
109 if(ret < 0)
110 goto bus_err;
111
112 memset(&ac97_template, 0, sizeof(struct snd_ac97_template));
113 ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97);
114 if(ret < 0)
115 goto bus_err;
116
117 ret = snd_soc_register_card(socdev);
118 if (ret < 0)
119 goto bus_err;
120 return 0;
121
122bus_err:
123 snd_soc_free_pcms(socdev);
124
125err:
126 kfree(socdev->codec->reg_cache);
127 kfree(socdev->codec);
128 socdev->codec = NULL;
129 return ret;
130}
131
132static int ac97_soc_remove(struct platform_device *pdev)
133{
134 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
135 struct snd_soc_codec *codec = socdev->codec;
136
137 if(codec == NULL)
138 return 0;
139
140 snd_soc_free_pcms(socdev);
141 kfree(socdev->codec->reg_cache);
142 kfree(socdev->codec);
143
144 return 0;
145}
146
147struct snd_soc_codec_device soc_codec_dev_ac97= {
148 .probe = ac97_soc_probe,
149 .remove = ac97_soc_remove,
150};
151
152EXPORT_SYMBOL_GPL(soc_codec_dev_ac97);
153
154MODULE_DESCRIPTION("Soc Generic AC97 driver");
155MODULE_AUTHOR("Liam Girdwood");
156MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ac97.h b/sound/soc/codecs/ac97.h
new file mode 100644
index 000000000000..930ddfc2321a
--- /dev/null
+++ b/sound/soc/codecs/ac97.h
@@ -0,0 +1,18 @@
1/*
2 * linux/sound/codecs/ac97.h -- ALSA SoC Layer
3 *
4 * Author: Liam Girdwood
5 * Created: Dec 1st 2005
6 * Copyright: Wolfson Microelectronics. PLC.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef __LINUX_SND_SOC_AC97_H
14#define __LINUX_SND_SOC_AC97_H
15
16extern struct snd_soc_codec_device soc_codec_dev_ac97;
17
18#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
new file mode 100644
index 000000000000..7ca0b5268289
--- /dev/null
+++ b/sound/soc/codecs/wm8731.c
@@ -0,0 +1,758 @@
1/*
2 * wm8731.c -- WM8731 ALSA SoC Audio driver
3 *
4 * Copyright 2005 Openedhand Ltd.
5 *
6 * Author: Richard Purdie <richard@openedhand.com>
7 *
8 * Based on wm8753.c by Liam Girdwood
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
22#include <sound/driver.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/initval.h>
29
30#include "wm8731.h"
31
32#define AUDIO_NAME "wm8731"
33#define WM8731_VERSION "0.13"
34
35/*
36 * Debug
37 */
38
39#define WM8731_DEBUG 0
40
41#ifdef WM8731_DEBUG
42#define dbg(format, arg...) \
43 printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
44#else
45#define dbg(format, arg...) do {} while (0)
46#endif
47#define err(format, arg...) \
48 printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
49#define info(format, arg...) \
50 printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
51#define warn(format, arg...) \
52 printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
53
54struct snd_soc_codec_device soc_codec_dev_wm8731;
55
56/* codec private data */
57struct wm8731_priv {
58 unsigned int sysclk;
59};
60
61/*
62 * wm8731 register cache
63 * We can't read the WM8731 register space when we are
64 * using 2 wire for device control, so we cache them instead.
65 * There is no point in caching the reset register
66 */
67static const u16 wm8731_reg[WM8731_CACHEREGNUM] = {
68 0x0097, 0x0097, 0x0079, 0x0079,
69 0x000a, 0x0008, 0x009f, 0x000a,
70 0x0000, 0x0000
71};
72
73/*
74 * read wm8731 register cache
75 */
76static inline unsigned int wm8731_read_reg_cache(struct snd_soc_codec *codec,
77 unsigned int reg)
78{
79 u16 *cache = codec->reg_cache;
80 if (reg == WM8731_RESET)
81 return 0;
82 if (reg >= WM8731_CACHEREGNUM)
83 return -1;
84 return cache[reg];
85}
86
87/*
88 * write wm8731 register cache
89 */
90static inline void wm8731_write_reg_cache(struct snd_soc_codec *codec,
91 u16 reg, unsigned int value)
92{
93 u16 *cache = codec->reg_cache;
94 if (reg >= WM8731_CACHEREGNUM)
95 return;
96 cache[reg] = value;
97}
98
99/*
100 * write to the WM8731 register space
101 */
102static int wm8731_write(struct snd_soc_codec *codec, unsigned int reg,
103 unsigned int value)
104{
105 u8 data[2];
106
107 /* data is
108 * D15..D9 WM8731 register offset
109 * D8...D0 register data
110 */
111 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
112 data[1] = value & 0x00ff;
113
114 wm8731_write_reg_cache (codec, reg, value);
115 if (codec->hw_write(codec->control_data, data, 2) == 2)
116 return 0;
117 else
118 return -EIO;
119}
120
121#define wm8731_reset(c) wm8731_write(c, WM8731_RESET, 0)
122
123static const char *wm8731_input_select[] = {"Line In", "Mic"};
124static const char *wm8731_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
125
126static const struct soc_enum wm8731_enum[] = {
127 SOC_ENUM_SINGLE(WM8731_APANA, 2, 2, wm8731_input_select),
128 SOC_ENUM_SINGLE(WM8731_APDIGI, 1, 4, wm8731_deemph),
129};
130
131static const struct snd_kcontrol_new wm8731_snd_controls[] = {
132
133SOC_DOUBLE_R("Master Playback Volume", WM8731_LOUT1V, WM8731_ROUT1V,
134 0, 127, 0),
135SOC_DOUBLE_R("Master Playback ZC Switch", WM8731_LOUT1V, WM8731_ROUT1V,
136 7, 1, 0),
137
138SOC_DOUBLE_R("Capture Volume", WM8731_LINVOL, WM8731_RINVOL, 0, 31, 0),
139SOC_DOUBLE_R("Line Capture Switch", WM8731_LINVOL, WM8731_RINVOL, 7, 1, 1),
140
141SOC_SINGLE("Mic Boost (+20dB)", WM8731_APANA, 0, 1, 0),
142SOC_SINGLE("Capture Mic Switch", WM8731_APANA, 1, 1, 1),
143
144SOC_SINGLE("Sidetone Playback Volume", WM8731_APANA, 6, 3, 1),
145
146SOC_SINGLE("ADC High Pass Filter Switch", WM8731_APDIGI, 0, 1, 1),
147SOC_SINGLE("Store DC Offset Switch", WM8731_APDIGI, 4, 1, 0),
148
149SOC_ENUM("Playback De-emphasis", wm8731_enum[1]),
150};
151
152/* add non dapm controls */
153static int wm8731_add_controls(struct snd_soc_codec *codec)
154{
155 int err, i;
156
157 for (i = 0; i < ARRAY_SIZE(wm8731_snd_controls); i++) {
158 if ((err = snd_ctl_add(codec->card,
159 snd_soc_cnew(&wm8731_snd_controls[i],codec, NULL))) < 0)
160 return err;
161 }
162
163 return 0;
164}
165
166/* Output Mixer */
167static const struct snd_kcontrol_new wm8731_output_mixer_controls[] = {
168SOC_DAPM_SINGLE("Line Bypass Switch", WM8731_APANA, 3, 1, 0),
169SOC_DAPM_SINGLE("Mic Sidetone Switch", WM8731_APANA, 5, 1, 0),
170SOC_DAPM_SINGLE("HiFi Playback Switch", WM8731_APANA, 4, 1, 0),
171};
172
173/* Input mux */
174static const struct snd_kcontrol_new wm8731_input_mux_controls =
175SOC_DAPM_ENUM("Input Select", wm8731_enum[0]);
176
177static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
178SND_SOC_DAPM_MIXER("Output Mixer", WM8731_PWR, 4, 1,
179 &wm8731_output_mixer_controls[0],
180 ARRAY_SIZE(wm8731_output_mixer_controls)),
181SND_SOC_DAPM_DAC("DAC", "HiFi Playback", WM8731_PWR, 3, 1),
182SND_SOC_DAPM_OUTPUT("LOUT"),
183SND_SOC_DAPM_OUTPUT("LHPOUT"),
184SND_SOC_DAPM_OUTPUT("ROUT"),
185SND_SOC_DAPM_OUTPUT("RHPOUT"),
186SND_SOC_DAPM_ADC("ADC", "HiFi Capture", WM8731_PWR, 2, 1),
187SND_SOC_DAPM_MUX("Input Mux", SND_SOC_NOPM, 0, 0, &wm8731_input_mux_controls),
188SND_SOC_DAPM_PGA("Line Input", WM8731_PWR, 0, 1, NULL, 0),
189SND_SOC_DAPM_MICBIAS("Mic Bias", WM8731_PWR, 1, 1),
190SND_SOC_DAPM_INPUT("MICIN"),
191SND_SOC_DAPM_INPUT("RLINEIN"),
192SND_SOC_DAPM_INPUT("LLINEIN"),
193};
194
195static const char *intercon[][3] = {
196 /* output mixer */
197 {"Output Mixer", "Line Bypass Switch", "Line Input"},
198 {"Output Mixer", "HiFi Playback Switch", "DAC"},
199 {"Output Mixer", "Mic Sidetone Switch", "Mic Bias"},
200
201 /* outputs */
202 {"RHPOUT", NULL, "Output Mixer"},
203 {"ROUT", NULL, "Output Mixer"},
204 {"LHPOUT", NULL, "Output Mixer"},
205 {"LOUT", NULL, "Output Mixer"},
206
207 /* input mux */
208 {"Input Mux", "Line In", "Line Input"},
209 {"Input Mux", "Mic", "Mic Bias"},
210 {"ADC", NULL, "Input Mux"},
211
212 /* inputs */
213 {"Line Input", NULL, "LLINEIN"},
214 {"Line Input", NULL, "RLINEIN"},
215 {"Mic Bias", NULL, "MICIN"},
216
217 /* terminator */
218 {NULL, NULL, NULL},
219};
220
221static int wm8731_add_widgets(struct snd_soc_codec *codec)
222{
223 int i;
224
225 for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
226 snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
227 }
228
229 /* set up audio path interconnects */
230 for(i = 0; intercon[i][0] != NULL; i++) {
231 snd_soc_dapm_connect_input(codec, intercon[i][0],
232 intercon[i][1], intercon[i][2]);
233 }
234
235 snd_soc_dapm_new_widgets(codec);
236 return 0;
237}
238
239struct _coeff_div {
240 u32 mclk;
241 u32 rate;
242 u16 fs;
243 u8 sr:4;
244 u8 bosr:1;
245 u8 usb:1;
246};
247
248/* codec mclk clock divider coefficients */
249static const struct _coeff_div coeff_div[] = {
250 /* 48k */
251 {12288000, 48000, 256, 0x0, 0x0, 0x0},
252 {18432000, 48000, 384, 0x0, 0x1, 0x0},
253 {12000000, 48000, 250, 0x0, 0x0, 0x1},
254
255 /* 32k */
256 {12288000, 32000, 384, 0x6, 0x0, 0x0},
257 {18432000, 32000, 576, 0x6, 0x1, 0x0},
258 {12000000, 32000, 375, 0x6, 0x0, 0x1},
259
260 /* 8k */
261 {12288000, 8000, 1536, 0x3, 0x0, 0x0},
262 {18432000, 8000, 2304, 0x3, 0x1, 0x0},
263 {11289600, 8000, 1408, 0xb, 0x0, 0x0},
264 {16934400, 8000, 2112, 0xb, 0x1, 0x0},
265 {12000000, 8000, 1500, 0x3, 0x0, 0x1},
266
267 /* 96k */
268 {12288000, 96000, 128, 0x7, 0x0, 0x0},
269 {18432000, 96000, 192, 0x7, 0x1, 0x0},
270 {12000000, 96000, 125, 0x7, 0x0, 0x1},
271
272 /* 44.1k */
273 {11289600, 44100, 256, 0x8, 0x0, 0x0},
274 {16934400, 44100, 384, 0x8, 0x1, 0x0},
275 {12000000, 44100, 272, 0x8, 0x1, 0x1},
276
277 /* 88.2k */
278 {11289600, 88200, 128, 0xf, 0x0, 0x0},
279 {16934400, 88200, 192, 0xf, 0x1, 0x0},
280 {12000000, 88200, 136, 0xf, 0x1, 0x1},
281};
282
283static inline int get_coeff(int mclk, int rate)
284{
285 int i;
286
287 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
288 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
289 return i;
290 }
291 return 0;
292}
293
294static int wm8731_hw_params(struct snd_pcm_substream *substream,
295 struct snd_pcm_hw_params *params)
296{
297 struct snd_soc_pcm_runtime *rtd = substream->private_data;
298 struct snd_soc_device *socdev = rtd->socdev;
299 struct snd_soc_codec *codec = socdev->codec;
300 struct wm8731_priv *wm8731 = codec->private_data;
301 u16 iface = wm8731_read_reg_cache(codec, WM8731_IFACE) & 0xfff3;
302 int i = get_coeff(wm8731->sysclk, params_rate(params));
303 u16 srate = (coeff_div[i].sr << 2) |
304 (coeff_div[i].bosr << 1) | coeff_div[i].usb;
305
306 wm8731_write(codec, WM8731_SRATE, srate);
307
308 /* bit size */
309 switch (params_format(params)) {
310 case SNDRV_PCM_FORMAT_S16_LE:
311 break;
312 case SNDRV_PCM_FORMAT_S20_3LE:
313 iface |= 0x0004;
314 break;
315 case SNDRV_PCM_FORMAT_S24_LE:
316 iface |= 0x0008;
317 break;
318 }
319
320 wm8731_write(codec, WM8731_IFACE, iface);
321 return 0;
322}
323
324static int wm8731_pcm_prepare(struct snd_pcm_substream *substream)
325{
326 struct snd_soc_pcm_runtime *rtd = substream->private_data;
327 struct snd_soc_device *socdev = rtd->socdev;
328 struct snd_soc_codec *codec = socdev->codec;
329
330 /* set active */
331 wm8731_write(codec, WM8731_ACTIVE, 0x0001);
332
333 return 0;
334}
335
336static void wm8731_shutdown(struct snd_pcm_substream *substream)
337{
338 struct snd_soc_pcm_runtime *rtd = substream->private_data;
339 struct snd_soc_device *socdev = rtd->socdev;
340 struct snd_soc_codec *codec = socdev->codec;
341
342 /* deactivate */
343 if (!codec->active) {
344 udelay(50);
345 wm8731_write(codec, WM8731_ACTIVE, 0x0);
346 }
347}
348
349static int wm8731_mute(struct snd_soc_codec_dai *dai, int mute)
350{
351 struct snd_soc_codec *codec = dai->codec;
352 u16 mute_reg = wm8731_read_reg_cache(codec, WM8731_APDIGI) & 0xfff7;
353
354 if (mute)
355 wm8731_write(codec, WM8731_APDIGI, mute_reg | 0x8);
356 else
357 wm8731_write(codec, WM8731_APDIGI, mute_reg);
358 return 0;
359}
360
361static int wm8731_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
362 int clk_id, unsigned int freq, int dir)
363{
364 struct snd_soc_codec *codec = codec_dai->codec;
365 struct wm8731_priv *wm8731 = codec->private_data;
366
367 switch (freq) {
368 case 11289600:
369 case 12000000:
370 case 12288000:
371 case 16934400:
372 case 18432000:
373 wm8731->sysclk = freq;
374 return 0;
375 }
376 return -EINVAL;
377}
378
379
380static int wm8731_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
381 unsigned int fmt)
382{
383 struct snd_soc_codec *codec = codec_dai->codec;
384 u16 iface = 0;
385
386 /* set master/slave audio interface */
387 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
388 case SND_SOC_DAIFMT_CBM_CFM:
389 iface |= 0x0040;
390 break;
391 case SND_SOC_DAIFMT_CBS_CFS:
392 break;
393 default:
394 return -EINVAL;
395 }
396
397 /* interface format */
398 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
399 case SND_SOC_DAIFMT_I2S:
400 iface |= 0x0002;
401 break;
402 case SND_SOC_DAIFMT_RIGHT_J:
403 break;
404 case SND_SOC_DAIFMT_LEFT_J:
405 iface |= 0x0001;
406 break;
407 case SND_SOC_DAIFMT_DSP_A:
408 iface |= 0x0003;
409 break;
410 case SND_SOC_DAIFMT_DSP_B:
411 iface |= 0x0013;
412 break;
413 default:
414 return -EINVAL;
415 }
416
417 /* clock inversion */
418 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
419 case SND_SOC_DAIFMT_NB_NF:
420 break;
421 case SND_SOC_DAIFMT_IB_IF:
422 iface |= 0x0090;
423 break;
424 case SND_SOC_DAIFMT_IB_NF:
425 iface |= 0x0080;
426 break;
427 case SND_SOC_DAIFMT_NB_IF:
428 iface |= 0x0010;
429 break;
430 default:
431 return -EINVAL;
432 }
433
434 /* set iface */
435 wm8731_write(codec, WM8731_IFACE, iface);
436 return 0;
437}
438
439static int wm8731_dapm_event(struct snd_soc_codec *codec, int event)
440{
441 u16 reg = wm8731_read_reg_cache(codec, WM8731_PWR) & 0xff7f;
442
443 switch (event) {
444 case SNDRV_CTL_POWER_D0: /* full On */
445 /* vref/mid, osc on, dac unmute */
446 wm8731_write(codec, WM8731_PWR, reg);
447 break;
448 case SNDRV_CTL_POWER_D1: /* partial On */
449 case SNDRV_CTL_POWER_D2: /* partial On */
450 break;
451 case SNDRV_CTL_POWER_D3hot: /* Off, with power */
452 /* everything off except vref/vmid, */
453 wm8731_write(codec, WM8731_PWR, reg | 0x0040);
454 break;
455 case SNDRV_CTL_POWER_D3cold: /* Off, without power */
456 /* everything off, dac mute, inactive */
457 wm8731_write(codec, WM8731_ACTIVE, 0x0);
458 wm8731_write(codec, WM8731_PWR, 0xffff);
459 break;
460 }
461 codec->dapm_state = event;
462 return 0;
463}
464
465#define WM8731_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
466 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
467 SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
468 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
469 SNDRV_PCM_RATE_96000)
470
471#define WM8731_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
472 SNDRV_PCM_FMTBIT_S24_LE)
473
474struct snd_soc_codec_dai wm8731_dai = {
475 .name = "WM8731",
476 .playback = {
477 .stream_name = "Playback",
478 .channels_min = 1,
479 .channels_max = 2,
480 .rates = WM8731_RATES,
481 .formats = WM8731_FORMATS,},
482 .capture = {
483 .stream_name = "Capture",
484 .channels_min = 1,
485 .channels_max = 2,
486 .rates = WM8731_RATES,
487 .formats = WM8731_FORMATS,},
488 .ops = {
489 .prepare = wm8731_pcm_prepare,
490 .hw_params = wm8731_hw_params,
491 .shutdown = wm8731_shutdown,
492 },
493 .dai_ops = {
494 .digital_mute = wm8731_mute,
495 .set_sysclk = wm8731_set_dai_sysclk,
496 .set_fmt = wm8731_set_dai_fmt,
497 }
498};
499EXPORT_SYMBOL_GPL(wm8731_dai);
500
501static int wm8731_suspend(struct platform_device *pdev, pm_message_t state)
502{
503 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
504 struct snd_soc_codec *codec = socdev->codec;
505
506 wm8731_write(codec, WM8731_ACTIVE, 0x0);
507 wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
508 return 0;
509}
510
511static int wm8731_resume(struct platform_device *pdev)
512{
513 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
514 struct snd_soc_codec *codec = socdev->codec;
515 int i;
516 u8 data[2];
517 u16 *cache = codec->reg_cache;
518
519 /* Sync reg_cache with the hardware */
520 for (i = 0; i < ARRAY_SIZE(wm8731_reg); i++) {
521 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
522 data[1] = cache[i] & 0x00ff;
523 codec->hw_write(codec->control_data, data, 2);
524 }
525 wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
526 wm8731_dapm_event(codec, codec->suspend_dapm_state);
527 return 0;
528}
529
530/*
531 * initialise the WM8731 driver
532 * register the mixer and dsp interfaces with the kernel
533 */
534static int wm8731_init(struct snd_soc_device *socdev)
535{
536 struct snd_soc_codec *codec = socdev->codec;
537 int reg, ret = 0;
538
539 codec->name = "WM8731";
540 codec->owner = THIS_MODULE;
541 codec->read = wm8731_read_reg_cache;
542 codec->write = wm8731_write;
543 codec->dapm_event = wm8731_dapm_event;
544 codec->dai = &wm8731_dai;
545 codec->num_dai = 1;
546 codec->reg_cache_size = sizeof(wm8731_reg);
547 codec->reg_cache = kmemdup(wm8731_reg, sizeof(wm8731_reg), GFP_KERNEL);
548 if (codec->reg_cache == NULL)
549 return -ENOMEM;
550
551 wm8731_reset(codec);
552
553 /* register pcms */
554 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
555 if (ret < 0) {
556 printk(KERN_ERR "wm8731: failed to create pcms\n");
557 goto pcm_err;
558 }
559
560 /* power on device */
561 wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
562
563 /* set the update bits */
564 reg = wm8731_read_reg_cache(codec, WM8731_LOUT1V);
565 wm8731_write(codec, WM8731_LOUT1V, reg | 0x0100);
566 reg = wm8731_read_reg_cache(codec, WM8731_ROUT1V);
567 wm8731_write(codec, WM8731_ROUT1V, reg | 0x0100);
568 reg = wm8731_read_reg_cache(codec, WM8731_LINVOL);
569 wm8731_write(codec, WM8731_LINVOL, reg | 0x0100);
570 reg = wm8731_read_reg_cache(codec, WM8731_RINVOL);
571 wm8731_write(codec, WM8731_RINVOL, reg | 0x0100);
572
573 wm8731_add_controls(codec);
574 wm8731_add_widgets(codec);
575 ret = snd_soc_register_card(socdev);
576 if (ret < 0) {
577 printk(KERN_ERR "wm8731: failed to register card\n");
578 goto card_err;
579 }
580
581 return ret;
582
583card_err:
584 snd_soc_free_pcms(socdev);
585 snd_soc_dapm_free(socdev);
586pcm_err:
587 kfree(codec->reg_cache);
588 return ret;
589}
590
591static struct snd_soc_device *wm8731_socdev;
592
593#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
594
595/*
596 * WM8731 2 wire address is determined by GPIO5
597 * state during powerup.
598 * low = 0x1a
599 * high = 0x1b
600 */
601static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
602
603/* Magic definition of all other variables and things */
604I2C_CLIENT_INSMOD;
605
606static struct i2c_driver wm8731_i2c_driver;
607static struct i2c_client client_template;
608
609/* If the i2c layer weren't so broken, we could pass this kind of data
610 around */
611
612static int wm8731_codec_probe(struct i2c_adapter *adap, int addr, int kind)
613{
614 struct snd_soc_device *socdev = wm8731_socdev;
615 struct wm8731_setup_data *setup = socdev->codec_data;
616 struct snd_soc_codec *codec = socdev->codec;
617 struct i2c_client *i2c;
618 int ret;
619
620 if (addr != setup->i2c_address)
621 return -ENODEV;
622
623 client_template.adapter = adap;
624 client_template.addr = addr;
625
626 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
627 if (i2c == NULL) {
628 kfree(codec);
629 return -ENOMEM;
630 }
631 i2c_set_clientdata(i2c, codec);
632 codec->control_data = i2c;
633
634 ret = i2c_attach_client(i2c);
635 if (ret < 0) {
636 err("failed to attach codec at addr %x\n", addr);
637 goto err;
638 }
639
640 ret = wm8731_init(socdev);
641 if (ret < 0) {
642 err("failed to initialise WM8731\n");
643 goto err;
644 }
645 return ret;
646
647err:
648 kfree(codec);
649 kfree(i2c);
650 return ret;
651}
652
653static int wm8731_i2c_detach(struct i2c_client *client)
654{
655 struct snd_soc_codec* codec = i2c_get_clientdata(client);
656 i2c_detach_client(client);
657 kfree(codec->reg_cache);
658 kfree(client);
659 return 0;
660}
661
662static int wm8731_i2c_attach(struct i2c_adapter *adap)
663{
664 return i2c_probe(adap, &addr_data, wm8731_codec_probe);
665}
666
667/* corgi i2c codec control layer */
668static struct i2c_driver wm8731_i2c_driver = {
669 .driver = {
670 .name = "WM8731 I2C Codec",
671 .owner = THIS_MODULE,
672 },
673 .id = I2C_DRIVERID_WM8731,
674 .attach_adapter = wm8731_i2c_attach,
675 .detach_client = wm8731_i2c_detach,
676 .command = NULL,
677};
678
679static struct i2c_client client_template = {
680 .name = "WM8731",
681 .driver = &wm8731_i2c_driver,
682};
683#endif
684
685static int wm8731_probe(struct platform_device *pdev)
686{
687 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
688 struct wm8731_setup_data *setup;
689 struct snd_soc_codec *codec;
690 struct wm8731_priv *wm8731;
691 int ret = 0;
692
693 info("WM8731 Audio Codec %s", WM8731_VERSION);
694
695 setup = socdev->codec_data;
696 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
697 if (codec == NULL)
698 return -ENOMEM;
699
700 wm8731 = kzalloc(sizeof(struct wm8731_priv), GFP_KERNEL);
701 if (wm8731 == NULL) {
702 kfree(codec);
703 return -ENOMEM;
704 }
705
706 codec->private_data = wm8731;
707 socdev->codec = codec;
708 mutex_init(&codec->mutex);
709 INIT_LIST_HEAD(&codec->dapm_widgets);
710 INIT_LIST_HEAD(&codec->dapm_paths);
711
712 wm8731_socdev = socdev;
713#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
714 if (setup->i2c_address) {
715 normal_i2c[0] = setup->i2c_address;
716 codec->hw_write = (hw_write_t)i2c_master_send;
717 ret = i2c_add_driver(&wm8731_i2c_driver);
718 if (ret != 0)
719 printk(KERN_ERR "can't add i2c driver");
720 }
721#else
722 /* Add other interfaces here */
723#endif
724 return ret;
725}
726
727/* power down chip */
728static int wm8731_remove(struct platform_device *pdev)
729{
730 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
731 struct snd_soc_codec *codec = socdev->codec;
732
733 if (codec->control_data)
734 wm8731_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
735
736 snd_soc_free_pcms(socdev);
737 snd_soc_dapm_free(socdev);
738#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
739 i2c_del_driver(&wm8731_i2c_driver);
740#endif
741 kfree(codec->private_data);
742 kfree(codec);
743
744 return 0;
745}
746
747struct snd_soc_codec_device soc_codec_dev_wm8731 = {
748 .probe = wm8731_probe,
749 .remove = wm8731_remove,
750 .suspend = wm8731_suspend,
751 .resume = wm8731_resume,
752};
753
754EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
755
756MODULE_DESCRIPTION("ASoC WM8731 driver");
757MODULE_AUTHOR("Richard Purdie");
758MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8731.h b/sound/soc/codecs/wm8731.h
new file mode 100644
index 000000000000..5bcab6a7afb4
--- /dev/null
+++ b/sound/soc/codecs/wm8731.h
@@ -0,0 +1,44 @@
1/*
2 * wm8731.h -- WM8731 Soc Audio driver
3 *
4 * Copyright 2005 Openedhand Ltd.
5 *
6 * Author: Richard Purdie <richard@openedhand.com>
7 *
8 * Based on wm8753.h
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#ifndef _WM8731_H
16#define _WM8731_H
17
18/* WM8731 register space */
19
20#define WM8731_LINVOL 0x00
21#define WM8731_RINVOL 0x01
22#define WM8731_LOUT1V 0x02
23#define WM8731_ROUT1V 0x03
24#define WM8731_APANA 0x04
25#define WM8731_APDIGI 0x05
26#define WM8731_PWR 0x06
27#define WM8731_IFACE 0x07
28#define WM8731_SRATE 0x08
29#define WM8731_ACTIVE 0x09
30#define WM8731_RESET 0x0f
31
32#define WM8731_CACHEREGNUM 10
33
34#define WM8731_SYSCLK 0
35#define WM8731_DAI 0
36
37struct wm8731_setup_data {
38 unsigned short i2c_address;
39};
40
41extern struct snd_soc_codec_dai wm8731_dai;
42extern struct snd_soc_codec_device soc_codec_dev_wm8731;
43
44#endif
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
new file mode 100644
index 000000000000..7073e8e294fc
--- /dev/null
+++ b/sound/soc/codecs/wm8750.c
@@ -0,0 +1,1049 @@
1/*
2 * wm8750.c -- WM8750 ALSA SoC audio driver
3 *
4 * Copyright 2005 Openedhand Ltd.
5 *
6 * Author: Richard Purdie <richard@openedhand.com>
7 *
8 * Based on WM8753.c
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/init.h>
18#include <linux/delay.h>
19#include <linux/pm.h>
20#include <linux/i2c.h>
21#include <linux/platform_device.h>
22#include <sound/driver.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/pcm_params.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28#include <sound/initval.h>
29
30#include "wm8750.h"
31
32#define AUDIO_NAME "WM8750"
33#define WM8750_VERSION "0.12"
34
35/*
36 * Debug
37 */
38
39#define WM8750_DEBUG 0
40
41#ifdef WM8750_DEBUG
42#define dbg(format, arg...) \
43 printk(KERN_DEBUG AUDIO_NAME ": " format "\n" , ## arg)
44#else
45#define dbg(format, arg...) do {} while (0)
46#endif
47#define err(format, arg...) \
48 printk(KERN_ERR AUDIO_NAME ": " format "\n" , ## arg)
49#define info(format, arg...) \
50 printk(KERN_INFO AUDIO_NAME ": " format "\n" , ## arg)
51#define warn(format, arg...) \
52 printk(KERN_WARNING AUDIO_NAME ": " format "\n" , ## arg)
53
54/* codec private data */
55struct wm8750_priv {
56 unsigned int sysclk;
57};
58
59/*
60 * wm8750 register cache
61 * We can't read the WM8750 register space when we
62 * are using 2 wire for device control, so we cache them instead.
63 */
64static const u16 wm8750_reg[] = {
65 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */
66 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */
67 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */
68 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */
69 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */
70 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */
71 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */
72 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */
73 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */
74 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */
75 0x0079, 0x0079, 0x0079, /* 40 */
76};
77
78/*
79 * read wm8750 register cache
80 */
81static inline unsigned int wm8750_read_reg_cache(struct snd_soc_codec *codec,
82 unsigned int reg)
83{
84 u16 *cache = codec->reg_cache;
85 if (reg > WM8750_CACHE_REGNUM)
86 return -1;
87 return cache[reg];
88}
89
90/*
91 * write wm8750 register cache
92 */
93static inline void wm8750_write_reg_cache(struct snd_soc_codec *codec,
94 unsigned int reg, unsigned int value)
95{
96 u16 *cache = codec->reg_cache;
97 if (reg > WM8750_CACHE_REGNUM)
98 return;
99 cache[reg] = value;
100}
101
102static int wm8750_write(struct snd_soc_codec *codec, unsigned int reg,
103 unsigned int value)
104{
105 u8 data[2];
106
107 /* data is
108 * D15..D9 WM8753 register offset
109 * D8...D0 register data
110 */
111 data[0] = (reg << 1) | ((value >> 8) & 0x0001);
112 data[1] = value & 0x00ff;
113
114 wm8750_write_reg_cache (codec, reg, value);
115 if (codec->hw_write(codec->control_data, data, 2) == 2)
116 return 0;
117 else
118 return -EIO;
119}
120
121#define wm8750_reset(c) wm8750_write(c, WM8750_RESET, 0)
122
123/*
124 * WM8750 Controls
125 */
126static const char *wm8750_bass[] = {"Linear Control", "Adaptive Boost"};
127static const char *wm8750_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" };
128static const char *wm8750_treble[] = {"8kHz", "4kHz"};
129static const char *wm8750_3d_lc[] = {"200Hz", "500Hz"};
130static const char *wm8750_3d_uc[] = {"2.2kHz", "1.5kHz"};
131static const char *wm8750_3d_func[] = {"Capture", "Playback"};
132static const char *wm8750_alc_func[] = {"Off", "Right", "Left", "Stereo"};
133static const char *wm8750_ng_type[] = {"Constant PGA Gain",
134 "Mute ADC Output"};
135static const char *wm8750_line_mux[] = {"Line 1", "Line 2", "Line 3", "PGA",
136 "Differential"};
137static const char *wm8750_pga_sel[] = {"Line 1", "Line 2", "Line 3",
138 "Differential"};
139static const char *wm8750_out3[] = {"VREF", "ROUT1 + Vol", "MonoOut",
140 "ROUT1"};
141static const char *wm8750_diff_sel[] = {"Line 1", "Line 2"};
142static const char *wm8750_adcpol[] = {"Normal", "L Invert", "R Invert",
143 "L + R Invert"};
144static const char *wm8750_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
145static const char *wm8750_mono_mux[] = {"Stereo", "Mono (Left)",
146 "Mono (Right)", "Digital Mono"};
147
148static const struct soc_enum wm8750_enum[] = {
149SOC_ENUM_SINGLE(WM8750_BASS, 7, 2, wm8750_bass),
150SOC_ENUM_SINGLE(WM8750_BASS, 6, 2, wm8750_bass_filter),
151SOC_ENUM_SINGLE(WM8750_TREBLE, 6, 2, wm8750_treble),
152SOC_ENUM_SINGLE(WM8750_3D, 5, 2, wm8750_3d_lc),
153SOC_ENUM_SINGLE(WM8750_3D, 6, 2, wm8750_3d_uc),
154SOC_ENUM_SINGLE(WM8750_3D, 7, 2, wm8750_3d_func),
155SOC_ENUM_SINGLE(WM8750_ALC1, 7, 4, wm8750_alc_func),
156SOC_ENUM_SINGLE(WM8750_NGATE, 1, 2, wm8750_ng_type),
157SOC_ENUM_SINGLE(WM8750_LOUTM1, 0, 5, wm8750_line_mux),
158SOC_ENUM_SINGLE(WM8750_ROUTM1, 0, 5, wm8750_line_mux),
159SOC_ENUM_SINGLE(WM8750_LADCIN, 6, 4, wm8750_pga_sel), /* 10 */
160SOC_ENUM_SINGLE(WM8750_RADCIN, 6, 4, wm8750_pga_sel),
161SOC_ENUM_SINGLE(WM8750_ADCTL2, 7, 4, wm8750_out3),
162SOC_ENUM_SINGLE(WM8750_ADCIN, 8, 2, wm8750_diff_sel),
163SOC_ENUM_SINGLE(WM8750_ADCDAC, 5, 4, wm8750_adcpol),
164SOC_ENUM_SINGLE(WM8750_ADCDAC, 1, 4, wm8750_deemph),
165SOC_ENUM_SINGLE(WM8750_ADCIN, 6, 4, wm8750_mono_mux), /* 16 */
166
167};
168
169static const struct snd_kcontrol_new wm8750_snd_controls[] = {
170
171SOC_DOUBLE_R("Capture Volume", WM8750_LINVOL, WM8750_RINVOL, 0, 63, 0),
172SOC_DOUBLE_R("Capture ZC Switch", WM8750_LINVOL, WM8750_RINVOL, 6, 1, 0),
173SOC_DOUBLE_R("Capture Switch", WM8750_LINVOL, WM8750_RINVOL, 7, 1, 1),
174
175SOC_DOUBLE_R("Headphone Playback ZC Switch", WM8750_LOUT1V,
176 WM8750_ROUT1V, 7, 1, 0),
177SOC_DOUBLE_R("Speaker Playback ZC Switch", WM8750_LOUT2V,
178 WM8750_ROUT2V, 7, 1, 0),
179
180SOC_ENUM("Playback De-emphasis", wm8750_enum[15]),
181
182SOC_ENUM("Capture Polarity", wm8750_enum[14]),
183SOC_SINGLE("Playback 6dB Attenuate", WM8750_ADCDAC, 7, 1, 0),
184SOC_SINGLE("Capture 6dB Attenuate", WM8750_ADCDAC, 8, 1, 0),
185
186SOC_DOUBLE_R("PCM Volume", WM8750_LDAC, WM8750_RDAC, 0, 255, 0),
187
188SOC_ENUM("Bass Boost", wm8750_enum[0]),
189SOC_ENUM("Bass Filter", wm8750_enum[1]),
190SOC_SINGLE("Bass Volume", WM8750_BASS, 0, 15, 1),
191
192SOC_SINGLE("Treble Volume", WM8750_TREBLE, 0, 15, 0),
193SOC_ENUM("Treble Cut-off", wm8750_enum[2]),
194
195SOC_SINGLE("3D Switch", WM8750_3D, 0, 1, 0),
196SOC_SINGLE("3D Volume", WM8750_3D, 1, 15, 0),
197SOC_ENUM("3D Lower Cut-off", wm8750_enum[3]),
198SOC_ENUM("3D Upper Cut-off", wm8750_enum[4]),
199SOC_ENUM("3D Mode", wm8750_enum[5]),
200
201SOC_SINGLE("ALC Capture Target Volume", WM8750_ALC1, 0, 7, 0),
202SOC_SINGLE("ALC Capture Max Volume", WM8750_ALC1, 4, 7, 0),
203SOC_ENUM("ALC Capture Function", wm8750_enum[6]),
204SOC_SINGLE("ALC Capture ZC Switch", WM8750_ALC2, 7, 1, 0),
205SOC_SINGLE("ALC Capture Hold Time", WM8750_ALC2, 0, 15, 0),
206SOC_SINGLE("ALC Capture Decay Time", WM8750_ALC3, 4, 15, 0),
207SOC_SINGLE("ALC Capture Attack Time", WM8750_ALC3, 0, 15, 0),
208SOC_SINGLE("ALC Capture NG Threshold", WM8750_NGATE, 3, 31, 0),
209SOC_ENUM("ALC Capture NG Type", wm8750_enum[4]),
210SOC_SINGLE("ALC Capture NG Switch", WM8750_NGATE, 0, 1, 0),
211
212SOC_SINGLE("Left ADC Capture Volume", WM8750_LADC, 0, 255, 0),
213SOC_SINGLE("Right ADC Capture Volume", WM8750_RADC, 0, 255, 0),
214
215SOC_SINGLE("ZC Timeout Switch", WM8750_ADCTL1, 0, 1, 0),
216SOC_SINGLE("Playback Invert Switch", WM8750_ADCTL1, 1, 1, 0),
217
218SOC_SINGLE("Right Speaker Playback Invert Switch", WM8750_ADCTL2, 4, 1, 0),
219
220/* Unimplemented */
221/* ADCDAC Bit 0 - ADCHPD */
222/* ADCDAC Bit 4 - HPOR */
223/* ADCTL1 Bit 2,3 - DATSEL */
224/* ADCTL1 Bit 4,5 - DMONOMIX */
225/* ADCTL1 Bit 6,7 - VSEL */
226/* ADCTL2 Bit 2 - LRCM */
227/* ADCTL2 Bit 3 - TRI */
228/* ADCTL3 Bit 5 - HPFLREN */
229/* ADCTL3 Bit 6 - VROI */
230/* ADCTL3 Bit 7,8 - ADCLRM */
231/* ADCIN Bit 4 - LDCM */
232/* ADCIN Bit 5 - RDCM */
233
234SOC_DOUBLE_R("Mic Boost", WM8750_LADCIN, WM8750_RADCIN, 4, 3, 0),
235
236SOC_DOUBLE_R("Bypass Left Playback Volume", WM8750_LOUTM1,
237 WM8750_LOUTM2, 4, 7, 1),
238SOC_DOUBLE_R("Bypass Right Playback Volume", WM8750_ROUTM1,
239 WM8750_ROUTM2, 4, 7, 1),
240SOC_DOUBLE_R("Bypass Mono Playback Volume", WM8750_MOUTM1,
241 WM8750_MOUTM2, 4, 7, 1),
242
243SOC_SINGLE("Mono Playback ZC Switch", WM8750_MOUTV, 7, 1, 0),
244
245SOC_DOUBLE_R("Headphone Playback Volume", WM8750_LOUT1V, WM8750_ROUT1V,
246 0, 127, 0),
247SOC_DOUBLE_R("Speaker Playback Volume", WM8750_LOUT2V, WM8750_ROUT2V,
248 0, 127, 0),
249
250SOC_SINGLE("Mono Playback Volume", WM8750_MOUTV, 0, 127, 0),
251
252};
253
254/* add non dapm controls */
255static int wm8750_add_controls(struct snd_soc_codec *codec)
256{
257 int err, i;
258
259 for (i = 0; i < ARRAY_SIZE(wm8750_snd_controls); i++) {
260 err = snd_ctl_add(codec->card,
261 snd_soc_cnew(&wm8750_snd_controls[i],codec, NULL));
262 if (err < 0)
263 return err;
264 }
265 return 0;
266}
267
268/*
269 * DAPM Controls
270 */
271
272/* Left Mixer */
273static const struct snd_kcontrol_new wm8750_left_mixer_controls[] = {
274SOC_DAPM_SINGLE("Playback Switch", WM8750_LOUTM1, 8, 1, 0),
275SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_LOUTM1, 7, 1, 0),
276SOC_DAPM_SINGLE("Right Playback Switch", WM8750_LOUTM2, 8, 1, 0),
277SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_LOUTM2, 7, 1, 0),
278};
279
280/* Right Mixer */
281static const struct snd_kcontrol_new wm8750_right_mixer_controls[] = {
282SOC_DAPM_SINGLE("Left Playback Switch", WM8750_ROUTM1, 8, 1, 0),
283SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_ROUTM1, 7, 1, 0),
284SOC_DAPM_SINGLE("Playback Switch", WM8750_ROUTM2, 8, 1, 0),
285SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_ROUTM2, 7, 1, 0),
286};
287
288/* Mono Mixer */
289static const struct snd_kcontrol_new wm8750_mono_mixer_controls[] = {
290SOC_DAPM_SINGLE("Left Playback Switch", WM8750_MOUTM1, 8, 1, 0),
291SOC_DAPM_SINGLE("Left Bypass Switch", WM8750_MOUTM1, 7, 1, 0),
292SOC_DAPM_SINGLE("Right Playback Switch", WM8750_MOUTM2, 8, 1, 0),
293SOC_DAPM_SINGLE("Right Bypass Switch", WM8750_MOUTM2, 7, 1, 0),
294};
295
296/* Left Line Mux */
297static const struct snd_kcontrol_new wm8750_left_line_controls =
298SOC_DAPM_ENUM("Route", wm8750_enum[8]);
299
300/* Right Line Mux */
301static const struct snd_kcontrol_new wm8750_right_line_controls =
302SOC_DAPM_ENUM("Route", wm8750_enum[9]);
303
304/* Left PGA Mux */
305static const struct snd_kcontrol_new wm8750_left_pga_controls =
306SOC_DAPM_ENUM("Route", wm8750_enum[10]);
307
308/* Right PGA Mux */
309static const struct snd_kcontrol_new wm8750_right_pga_controls =
310SOC_DAPM_ENUM("Route", wm8750_enum[11]);
311
312/* Out 3 Mux */
313static const struct snd_kcontrol_new wm8750_out3_controls =
314SOC_DAPM_ENUM("Route", wm8750_enum[12]);
315
316/* Differential Mux */
317static const struct snd_kcontrol_new wm8750_diffmux_controls =
318SOC_DAPM_ENUM("Route", wm8750_enum[13]);
319
320/* Mono ADC Mux */
321static const struct snd_kcontrol_new wm8750_monomux_controls =
322SOC_DAPM_ENUM("Route", wm8750_enum[16]);
323
324static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
325 SND_SOC_DAPM_MIXER("Left Mixer", SND_SOC_NOPM, 0, 0,
326 &wm8750_left_mixer_controls[0],
327 ARRAY_SIZE(wm8750_left_mixer_controls)),
328 SND_SOC_DAPM_MIXER("Right Mixer", SND_SOC_NOPM, 0, 0,
329 &wm8750_right_mixer_controls[0],
330 ARRAY_SIZE(wm8750_right_mixer_controls)),
331 SND_SOC_DAPM_MIXER("Mono Mixer", WM8750_PWR2, 2, 0,
332 &wm8750_mono_mixer_controls[0],
333 ARRAY_SIZE(wm8750_mono_mixer_controls)),
334
335 SND_SOC_DAPM_PGA("Right Out 2", WM8750_PWR2, 3, 0, NULL, 0),
336 SND_SOC_DAPM_PGA("Left Out 2", WM8750_PWR2, 4, 0, NULL, 0),
337 SND_SOC_DAPM_PGA("Right Out 1", WM8750_PWR2, 5, 0, NULL, 0),
338 SND_SOC_DAPM_PGA("Left Out 1", WM8750_PWR2, 6, 0, NULL, 0),
339 SND_SOC_DAPM_DAC("Right DAC", "Right Playback", WM8750_PWR2, 7, 0),
340 SND_SOC_DAPM_DAC("Left DAC", "Left Playback", WM8750_PWR2, 8, 0),
341
342 SND_SOC_DAPM_MICBIAS("Mic Bias", WM8750_PWR1, 1, 0),
343 SND_SOC_DAPM_ADC("Right ADC", "Right Capture", WM8750_PWR1, 2, 0),
344 SND_SOC_DAPM_ADC("Left ADC", "Left Capture", WM8750_PWR1, 3, 0),
345
346 SND_SOC_DAPM_MUX("Left PGA Mux", WM8750_PWR1, 5, 0,
347 &wm8750_left_pga_controls),
348 SND_SOC_DAPM_MUX("Right PGA Mux", WM8750_PWR1, 4, 0,
349 &wm8750_right_pga_controls),
350 SND_SOC_DAPM_MUX("Left Line Mux", SND_SOC_NOPM, 0, 0,
351 &wm8750_left_line_controls),
352 SND_SOC_DAPM_MUX("Right Line Mux", SND_SOC_NOPM, 0, 0,
353 &wm8750_right_line_controls),
354
355 SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0, &wm8750_out3_controls),
356 SND_SOC_DAPM_PGA("Out 3", WM8750_PWR2, 1, 0, NULL, 0),
357 SND_SOC_DAPM_PGA("Mono Out 1", WM8750_PWR2, 2, 0, NULL, 0),
358
359 SND_SOC_DAPM_MUX("Differential Mux", SND_SOC_NOPM, 0, 0,
360 &wm8750_diffmux_controls),
361 SND_SOC_DAPM_MUX("Left ADC Mux", SND_SOC_NOPM, 0, 0,
362 &wm8750_monomux_controls),
363 SND_SOC_DAPM_MUX("Right ADC Mux", SND_SOC_NOPM, 0, 0,
364 &wm8750_monomux_controls),
365
366 SND_SOC_DAPM_OUTPUT("LOUT1"),
367 SND_SOC_DAPM_OUTPUT("ROUT1"),
368 SND_SOC_DAPM_OUTPUT("LOUT2"),
369 SND_SOC_DAPM_OUTPUT("ROUT2"),
370 SND_SOC_DAPM_OUTPUT("MONO"),
371 SND_SOC_DAPM_OUTPUT("OUT3"),
372
373 SND_SOC_DAPM_INPUT("LINPUT1"),
374 SND_SOC_DAPM_INPUT("LINPUT2"),
375 SND_SOC_DAPM_INPUT("LINPUT3"),
376 SND_SOC_DAPM_INPUT("RINPUT1"),
377 SND_SOC_DAPM_INPUT("RINPUT2"),
378 SND_SOC_DAPM_INPUT("RINPUT3"),
379};
380
381static const char *audio_map[][3] = {
382 /* left mixer */
383 {"Left Mixer", "Playback Switch", "Left DAC"},
384 {"Left Mixer", "Left Bypass Switch", "Left Line Mux"},
385 {"Left Mixer", "Right Playback Switch", "Right DAC"},
386 {"Left Mixer", "Right Bypass Switch", "Right Line Mux"},
387
388 /* right mixer */
389 {"Right Mixer", "Left Playback Switch", "Left DAC"},
390 {"Right Mixer", "Left Bypass Switch", "Left Line Mux"},
391 {"Right Mixer", "Playback Switch", "Right DAC"},
392 {"Right Mixer", "Right Bypass Switch", "Right Line Mux"},
393
394 /* left out 1 */
395 {"Left Out 1", NULL, "Left Mixer"},
396 {"LOUT1", NULL, "Left Out 1"},
397
398 /* left out 2 */
399 {"Left Out 2", NULL, "Left Mixer"},
400 {"LOUT2", NULL, "Left Out 2"},
401
402 /* right out 1 */
403 {"Right Out 1", NULL, "Right Mixer"},
404 {"ROUT1", NULL, "Right Out 1"},
405
406 /* right out 2 */
407 {"Right Out 2", NULL, "Right Mixer"},
408 {"ROUT2", NULL, "Right Out 2"},
409
410 /* mono mixer */
411 {"Mono Mixer", "Left Playback Switch", "Left DAC"},
412 {"Mono Mixer", "Left Bypass Switch", "Left Line Mux"},
413 {"Mono Mixer", "Right Playback Switch", "Right DAC"},
414 {"Mono Mixer", "Right Bypass Switch", "Right Line Mux"},
415
416 /* mono out */
417 {"Mono Out 1", NULL, "Mono Mixer"},
418 {"MONO1", NULL, "Mono Out 1"},
419
420 /* out 3 */
421 {"Out3 Mux", "VREF", "VREF"},
422 {"Out3 Mux", "ROUT1 + Vol", "ROUT1"},
423 {"Out3 Mux", "ROUT1", "Right Mixer"},
424 {"Out3 Mux", "MonoOut", "MONO1"},
425 {"Out 3", NULL, "Out3 Mux"},
426 {"OUT3", NULL, "Out 3"},
427
428 /* Left Line Mux */
429 {"Left Line Mux", "Line 1", "LINPUT1"},
430 {"Left Line Mux", "Line 2", "LINPUT2"},
431 {"Left Line Mux", "Line 3", "LINPUT3"},
432 {"Left Line Mux", "PGA", "Left PGA Mux"},
433 {"Left Line Mux", "Differential", "Differential Mux"},
434
435 /* Right Line Mux */
436 {"Right Line Mux", "Line 1", "RINPUT1"},
437 {"Right Line Mux", "Line 2", "RINPUT2"},
438 {"Right Line Mux", "Line 3", "RINPUT3"},
439 {"Right Line Mux", "PGA", "Right PGA Mux"},
440 {"Right Line Mux", "Differential", "Differential Mux"},
441
442 /* Left PGA Mux */
443 {"Left PGA Mux", "Line 1", "LINPUT1"},
444 {"Left PGA Mux", "Line 2", "LINPUT2"},
445 {"Left PGA Mux", "Line 3", "LINPUT3"},
446 {"Left PGA Mux", "Differential", "Differential Mux"},
447
448 /* Right PGA Mux */
449 {"Right PGA Mux", "Line 1", "RINPUT1"},
450 {"Right PGA Mux", "Line 2", "RINPUT2"},
451 {"Right PGA Mux", "Line 3", "RINPUT3"},
452 {"Right PGA Mux", "Differential", "Differential Mux"},
453
454 /* Differential Mux */
455 {"Differential Mux", "Line 1", "LINPUT1"},
456 {"Differential Mux", "Line 1", "RINPUT1"},
457 {"Differential Mux", "Line 2", "LINPUT2"},
458 {"Differential Mux", "Line 2", "RINPUT2"},
459
460 /* Left ADC Mux */
461 {"Left ADC Mux", "Stereo", "Left PGA Mux"},
462 {"Left ADC Mux", "Mono (Left)", "Left PGA Mux"},
463 {"Left ADC Mux", "Digital Mono", "Left PGA Mux"},
464
465 /* Right ADC Mux */
466 {"Right ADC Mux", "Stereo", "Right PGA Mux"},
467 {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"},
468 {"Right ADC Mux", "Digital Mono", "Right PGA Mux"},
469
470 /* ADC */
471 {"Left ADC", NULL, "Left ADC Mux"},
472 {"Right ADC", NULL, "Right ADC Mux"},
473
474 /* terminator */
475 {NULL, NULL, NULL},
476};
477
478static int wm8750_add_widgets(struct snd_soc_codec *codec)
479{
480 int i;
481
482 for(i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
483 snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
484 }
485
486 /* set up audio path audio_mapnects */
487 for(i = 0; audio_map[i][0] != NULL; i++) {
488 snd_soc_dapm_connect_input(codec, audio_map[i][0],
489 audio_map[i][1], audio_map[i][2]);
490 }
491
492 snd_soc_dapm_new_widgets(codec);
493 return 0;
494}
495
496struct _coeff_div {
497 u32 mclk;
498 u32 rate;
499 u16 fs;
500 u8 sr:5;
501 u8 usb:1;
502};
503
504/* codec hifi mclk clock divider coefficients */
505static const struct _coeff_div coeff_div[] = {
506 /* 8k */
507 {12288000, 8000, 1536, 0x6, 0x0},
508 {11289600, 8000, 1408, 0x16, 0x0},
509 {18432000, 8000, 2304, 0x7, 0x0},
510 {16934400, 8000, 2112, 0x17, 0x0},
511 {12000000, 8000, 1500, 0x6, 0x1},
512
513 /* 11.025k */
514 {11289600, 11025, 1024, 0x18, 0x0},
515 {16934400, 11025, 1536, 0x19, 0x0},
516 {12000000, 11025, 1088, 0x19, 0x1},
517
518 /* 16k */
519 {12288000, 16000, 768, 0xa, 0x0},
520 {18432000, 16000, 1152, 0xb, 0x0},
521 {12000000, 16000, 750, 0xa, 0x1},
522
523 /* 22.05k */
524 {11289600, 22050, 512, 0x1a, 0x0},
525 {16934400, 22050, 768, 0x1b, 0x0},
526 {12000000, 22050, 544, 0x1b, 0x1},
527
528 /* 32k */
529 {12288000, 32000, 384, 0xc, 0x0},
530 {18432000, 32000, 576, 0xd, 0x0},
531 {12000000, 32000, 375, 0xa, 0x1},
532
533 /* 44.1k */
534 {11289600, 44100, 256, 0x10, 0x0},
535 {16934400, 44100, 384, 0x11, 0x0},
536 {12000000, 44100, 272, 0x11, 0x1},
537
538 /* 48k */
539 {12288000, 48000, 256, 0x0, 0x0},
540 {18432000, 48000, 384, 0x1, 0x0},
541 {12000000, 48000, 250, 0x0, 0x1},
542
543 /* 88.2k */
544 {11289600, 88200, 128, 0x1e, 0x0},
545 {16934400, 88200, 192, 0x1f, 0x0},
546 {12000000, 88200, 136, 0x1f, 0x1},
547
548 /* 96k */
549 {12288000, 96000, 128, 0xe, 0x0},
550 {18432000, 96000, 192, 0xf, 0x0},
551 {12000000, 96000, 125, 0xe, 0x1},
552};
553
554static inline int get_coeff(int mclk, int rate)
555{
556 int i;
557
558 for (i = 0; i < ARRAY_SIZE(coeff_div); i++) {
559 if (coeff_div[i].rate == rate && coeff_div[i].mclk == mclk)
560 return i;
561 }
562
563 printk(KERN_ERR "wm8750: could not get coeff for mclk %d @ rate %d\n",
564 mclk, rate);
565 return -EINVAL;
566}
567
568static int wm8750_set_dai_sysclk(struct snd_soc_codec_dai *codec_dai,
569 int clk_id, unsigned int freq, int dir)
570{
571 struct snd_soc_codec *codec = codec_dai->codec;
572 struct wm8750_priv *wm8750 = codec->private_data;
573
574 switch (freq) {
575 case 11289600:
576 case 12000000:
577 case 12288000:
578 case 16934400:
579 case 18432000:
580 wm8750->sysclk = freq;
581 return 0;
582 }
583 return -EINVAL;
584}
585
586static int wm8750_set_dai_fmt(struct snd_soc_codec_dai *codec_dai,
587 unsigned int fmt)
588{
589 struct snd_soc_codec *codec = codec_dai->codec;
590 u16 iface = 0;
591
592 /* set master/slave audio interface */
593 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
594 case SND_SOC_DAIFMT_CBM_CFM:
595 iface = 0x0040;
596 break;
597 case SND_SOC_DAIFMT_CBS_CFS:
598 break;
599 default:
600 return -EINVAL;
601 }
602
603 /* interface format */
604 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
605 case SND_SOC_DAIFMT_I2S:
606 iface |= 0x0002;
607 break;
608 case SND_SOC_DAIFMT_RIGHT_J:
609 break;
610 case SND_SOC_DAIFMT_LEFT_J:
611 iface |= 0x0001;
612 break;
613 case SND_SOC_DAIFMT_DSP_A:
614 iface |= 0x0003;
615 break;
616 case SND_SOC_DAIFMT_DSP_B:
617 iface |= 0x0013;
618 break;
619 default:
620 return -EINVAL;
621 }
622
623 /* clock inversion */
624 switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
625 case SND_SOC_DAIFMT_NB_NF:
626 break;
627 case SND_SOC_DAIFMT_IB_IF:
628 iface |= 0x0090;
629 break;
630 case SND_SOC_DAIFMT_IB_NF:
631 iface |= 0x0080;
632 break;
633 case SND_SOC_DAIFMT_NB_IF:
634 iface |= 0x0010;
635 break;
636 default:
637 return -EINVAL;
638 }
639
640 wm8750_write(codec, WM8750_IFACE, iface);
641 return 0;
642}
643
644static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
645 struct snd_pcm_hw_params *params)
646{
647 struct snd_soc_pcm_runtime *rtd = substream->private_data;
648 struct snd_soc_device *socdev = rtd->socdev;
649 struct snd_soc_codec *codec = socdev->codec;
650 struct wm8750_priv *wm8750 = codec->private_data;
651 u16 iface = wm8750_read_reg_cache(codec, WM8750_IFACE) & 0x1f3;
652 u16 srate = wm8750_read_reg_cache(codec, WM8750_SRATE) & 0x1c0;
653 int coeff = get_coeff(wm8750->sysclk, params_rate(params));
654
655 /* bit size */
656 switch (params_format(params)) {
657 case SNDRV_PCM_FORMAT_S16_LE:
658 break;
659 case SNDRV_PCM_FORMAT_S20_3LE:
660 iface |= 0x0004;
661 break;
662 case SNDRV_PCM_FORMAT_S24_LE:
663 iface |= 0x0008;
664 break;
665 case SNDRV_PCM_FORMAT_S32_LE:
666 iface |= 0x000c;
667 break;
668 }
669
670 /* set iface & srate */
671 wm8750_write(codec, WM8750_IFACE, iface);
672 if (coeff >= 0)
673 wm8750_write(codec, WM8750_SRATE, srate |
674 (coeff_div[coeff].sr << 1) | coeff_div[coeff].usb);
675
676 return 0;
677}
678
679static int wm8750_mute(struct snd_soc_codec_dai *dai, int mute)
680{
681 struct snd_soc_codec *codec = dai->codec;
682 u16 mute_reg = wm8750_read_reg_cache(codec, WM8750_ADCDAC) & 0xfff7;
683
684 if (mute)
685 wm8750_write(codec, WM8750_ADCDAC, mute_reg | 0x8);
686 else
687 wm8750_write(codec, WM8750_ADCDAC, mute_reg);
688 return 0;
689}
690
691static int wm8750_dapm_event(struct snd_soc_codec *codec, int event)
692{
693 u16 pwr_reg = wm8750_read_reg_cache(codec, WM8750_PWR1) & 0xfe3e;
694
695 switch (event) {
696 case SNDRV_CTL_POWER_D0: /* full On */
697 /* set vmid to 50k and unmute dac */
698 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x00c0);
699 break;
700 case SNDRV_CTL_POWER_D1: /* partial On */
701 case SNDRV_CTL_POWER_D2: /* partial On */
702 /* set vmid to 5k for quick power up */
703 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x01c1);
704 break;
705 case SNDRV_CTL_POWER_D3hot: /* Off, with power */
706 /* mute dac and set vmid to 500k, enable VREF */
707 wm8750_write(codec, WM8750_PWR1, pwr_reg | 0x0141);
708 break;
709 case SNDRV_CTL_POWER_D3cold: /* Off, without power */
710 wm8750_write(codec, WM8750_PWR1, 0x0001);
711 break;
712 }
713 codec->dapm_state = event;
714 return 0;
715}
716
717#define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
718 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
719 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
720
721#define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
722 SNDRV_PCM_FMTBIT_S24_LE)
723
724struct snd_soc_codec_dai wm8750_dai = {
725 .name = "WM8750",
726 .playback = {
727 .stream_name = "Playback",
728 .channels_min = 1,
729 .channels_max = 2,
730 .rates = WM8750_RATES,
731 .formats = WM8750_FORMATS,},
732 .capture = {
733 .stream_name = "Capture",
734 .channels_min = 1,
735 .channels_max = 2,
736 .rates = WM8750_RATES,
737 .formats = WM8750_FORMATS,},
738 .ops = {
739 .hw_params = wm8750_pcm_hw_params,
740 },
741 .dai_ops = {
742 .digital_mute = wm8750_mute,
743 .set_fmt = wm8750_set_dai_fmt,
744 .set_sysclk = wm8750_set_dai_sysclk,
745 },
746};
747EXPORT_SYMBOL_GPL(wm8750_dai);
748
749static void wm8750_work(struct work_struct *work)
750{
751 struct snd_soc_codec *codec =
752 container_of(work, struct snd_soc_codec, delayed_work.work);
753 wm8750_dapm_event(codec, codec->dapm_state);
754}
755
756static int wm8750_suspend(struct platform_device *pdev, pm_message_t state)
757{
758 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
759 struct snd_soc_codec *codec = socdev->codec;
760
761 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
762 return 0;
763}
764
765static int wm8750_resume(struct platform_device *pdev)
766{
767 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
768 struct snd_soc_codec *codec = socdev->codec;
769 int i;
770 u8 data[2];
771 u16 *cache = codec->reg_cache;
772
773 /* Sync reg_cache with the hardware */
774 for (i = 0; i < ARRAY_SIZE(wm8750_reg); i++) {
775 if (i == WM8750_RESET)
776 continue;
777 data[0] = (i << 1) | ((cache[i] >> 8) & 0x0001);
778 data[1] = cache[i] & 0x00ff;
779 codec->hw_write(codec->control_data, data, 2);
780 }
781
782 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
783
784 /* charge wm8750 caps */
785 if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0) {
786 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
787 codec->dapm_state = SNDRV_CTL_POWER_D0;
788 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
789 }
790
791 return 0;
792}
793
794/*
795 * initialise the WM8750 driver
796 * register the mixer and dsp interfaces with the kernel
797 */
798static int wm8750_init(struct snd_soc_device *socdev)
799{
800 struct snd_soc_codec *codec = socdev->codec;
801 int reg, ret = 0;
802
803 codec->name = "WM8750";
804 codec->owner = THIS_MODULE;
805 codec->read = wm8750_read_reg_cache;
806 codec->write = wm8750_write;
807 codec->dapm_event = wm8750_dapm_event;
808 codec->dai = &wm8750_dai;
809 codec->num_dai = 1;
810 codec->reg_cache_size = sizeof(wm8750_reg);
811 codec->reg_cache = kmemdup(wm8750_reg, sizeof(wm8750_reg), GFP_KRENEL);
812 if (codec->reg_cache == NULL)
813 return -ENOMEM;
814
815 wm8750_reset(codec);
816
817 /* register pcms */
818 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
819 if (ret < 0) {
820 printk(KERN_ERR "wm8750: failed to create pcms\n");
821 goto pcm_err;
822 }
823
824 /* charge output caps */
825 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D2);
826 codec->dapm_state = SNDRV_CTL_POWER_D3hot;
827 schedule_delayed_work(&codec->delayed_work, msecs_to_jiffies(1000));
828
829 /* set the update bits */
830 reg = wm8750_read_reg_cache(codec, WM8750_LDAC);
831 wm8750_write(codec, WM8750_LDAC, reg | 0x0100);
832 reg = wm8750_read_reg_cache(codec, WM8750_RDAC);
833 wm8750_write(codec, WM8750_RDAC, reg | 0x0100);
834 reg = wm8750_read_reg_cache(codec, WM8750_LOUT1V);
835 wm8750_write(codec, WM8750_LOUT1V, reg | 0x0100);
836 reg = wm8750_read_reg_cache(codec, WM8750_ROUT1V);
837 wm8750_write(codec, WM8750_ROUT1V, reg | 0x0100);
838 reg = wm8750_read_reg_cache(codec, WM8750_LOUT2V);
839 wm8750_write(codec, WM8750_LOUT2V, reg | 0x0100);
840 reg = wm8750_read_reg_cache(codec, WM8750_ROUT2V);
841 wm8750_write(codec, WM8750_ROUT2V, reg | 0x0100);
842 reg = wm8750_read_reg_cache(codec, WM8750_LINVOL);
843 wm8750_write(codec, WM8750_LINVOL, reg | 0x0100);
844 reg = wm8750_read_reg_cache(codec, WM8750_RINVOL);
845 wm8750_write(codec, WM8750_RINVOL, reg | 0x0100);
846
847 wm8750_add_controls(codec);
848 wm8750_add_widgets(codec);
849 ret = snd_soc_register_card(socdev);
850 if (ret < 0) {
851 printk(KERN_ERR "wm8750: failed to register card\n");
852 goto card_err;
853 }
854 return ret;
855
856card_err:
857 snd_soc_free_pcms(socdev);
858 snd_soc_dapm_free(socdev);
859pcm_err:
860 kfree(codec->reg_cache);
861 return ret;
862}
863
864/* If the i2c layer weren't so broken, we could pass this kind of data
865 around */
866static struct snd_soc_device *wm8750_socdev;
867
868#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
869
870/*
871 * WM8731 2 wire address is determined by GPIO5
872 * state during powerup.
873 * low = 0x1a
874 * high = 0x1b
875 */
876static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
877
878/* Magic definition of all other variables and things */
879I2C_CLIENT_INSMOD;
880
881static struct i2c_driver wm8750_i2c_driver;
882static struct i2c_client client_template;
883
884static int wm8750_codec_probe(struct i2c_adapter *adap, int addr, int kind)
885{
886 struct snd_soc_device *socdev = wm8750_socdev;
887 struct wm8750_setup_data *setup = socdev->codec_data;
888 struct snd_soc_codec *codec = socdev->codec;
889 struct i2c_client *i2c;
890 int ret;
891
892 if (addr != setup->i2c_address)
893 return -ENODEV;
894
895 client_template.adapter = adap;
896 client_template.addr = addr;
897
898 i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
899 if (i2c == NULL) {
900 kfree(codec);
901 return -ENOMEM;
902 }
903 i2c_set_clientdata(i2c, codec);
904 codec->control_data = i2c;
905
906 ret = i2c_attach_client(i2c);
907 if (ret < 0) {
908 err("failed to attach codec at addr %x\n", addr);
909 goto err;
910 }
911
912 ret = wm8750_init(socdev);
913 if (ret < 0) {
914 err("failed to initialise WM8750\n");
915 goto err;
916 }
917 return ret;
918
919err:
920 kfree(codec);
921 kfree(i2c);
922 return ret;
923}
924
925static int wm8750_i2c_detach(struct i2c_client *client)
926{
927 struct snd_soc_codec *codec = i2c_get_clientdata(client);
928 i2c_detach_client(client);
929 kfree(codec->reg_cache);
930 kfree(client);
931 return 0;
932}
933
934static int wm8750_i2c_attach(struct i2c_adapter *adap)
935{
936 return i2c_probe(adap, &addr_data, wm8750_codec_probe);
937}
938
939/* corgi i2c codec control layer */
940static struct i2c_driver wm8750_i2c_driver = {
941 .driver = {
942 .name = "WM8750 I2C Codec",
943 .owner = THIS_MODULE,
944 },
945 .id = I2C_DRIVERID_WM8750,
946 .attach_adapter = wm8750_i2c_attach,
947 .detach_client = wm8750_i2c_detach,
948 .command = NULL,
949};
950
951static struct i2c_client client_template = {
952 .name = "WM8750",
953 .driver = &wm8750_i2c_driver,
954};
955#endif
956
957static int wm8750_probe(struct platform_device *pdev)
958{
959 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
960 struct wm8750_setup_data *setup = socdev->codec_data;
961 struct snd_soc_codec *codec;
962 struct wm8750_priv *wm8750;
963 int ret = 0;
964
965 info("WM8750 Audio Codec %s", WM8750_VERSION);
966 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
967 if (codec == NULL)
968 return -ENOMEM;
969
970 wm8750 = kzalloc(sizeof(struct wm8750_priv), GFP_KERNEL);
971 if (wm8750 == NULL) {
972 kfree(codec);
973 return -ENOMEM;
974 }
975
976 codec->private_data = wm8750;
977 socdev->codec = codec;
978 mutex_init(&codec->mutex);
979 INIT_LIST_HEAD(&codec->dapm_widgets);
980 INIT_LIST_HEAD(&codec->dapm_paths);
981 wm8750_socdev = socdev;
982 INIT_DELAYED_WORK(&codec->delayed_work, wm8750_work);
983
984#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
985 if (setup->i2c_address) {
986 normal_i2c[0] = setup->i2c_address;
987 codec->hw_write = (hw_write_t)i2c_master_send;
988 ret = i2c_add_driver(&wm8750_i2c_driver);
989 if (ret != 0)
990 printk(KERN_ERR "can't add i2c driver");
991 }
992#else
993 /* Add other interfaces here */
994#endif
995
996 return ret;
997}
998
999/*
1000 * This function forces any delayed work to be queued and run.
1001 */
1002static int run_delayed_work(struct delayed_work *dwork)
1003{
1004 int ret;
1005
1006 /* cancel any work waiting to be queued. */
1007 ret = cancel_delayed_work(dwork);
1008
1009 /* if there was any work waiting then we run it now and
1010 * wait for it's completion */
1011 if (ret) {
1012 schedule_delayed_work(dwork, 0);
1013 flush_scheduled_work();
1014 }
1015 return ret;
1016}
1017
1018/* power down chip */
1019static int wm8750_remove(struct platform_device *pdev)
1020{
1021 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1022 struct snd_soc_codec *codec = socdev->codec;
1023
1024 if (codec->control_data)
1025 wm8750_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
1026 run_delayed_work(&codec->delayed_work);
1027 snd_soc_free_pcms(socdev);
1028 snd_soc_dapm_free(socdev);
1029#if defined (CONFIG_I2C) || defined (CONFIG_I2C_MODULE)
1030 i2c_del_driver(&wm8750_i2c_driver);
1031#endif
1032 kfree(codec->private_data);
1033 kfree(codec);
1034
1035 return 0;
1036}
1037
1038struct snd_soc_codec_device soc_codec_dev_wm8750 = {
1039 .probe = wm8750_probe,
1040 .remove = wm8750_remove,
1041 .suspend = wm8750_suspend,
1042 .resume = wm8750_resume,
1043};
1044
1045EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
1046
1047MODULE_DESCRIPTION("ASoC WM8750 driver");
1048MODULE_AUTHOR("Liam Girdwood");
1049MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8750.h b/sound/soc/codecs/wm8750.h
new file mode 100644
index 000000000000..a97a54a6348e
--- /dev/null
+++ b/sound/soc/codecs/wm8750.h
@@ -0,0 +1,67 @@
1/*
2 * Copyright 2005 Openedhand Ltd.
3 *
4 * Author: Richard Purdie <richard@openedhand.com>
5 *
6 * Based on WM8753.h
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 */
13
14#ifndef _WM8750_H
15#define _WM8750_H
16
17/* WM8750 register space */
18
19#define WM8750_LINVOL 0x00
20#define WM8750_RINVOL 0x01
21#define WM8750_LOUT1V 0x02
22#define WM8750_ROUT1V 0x03
23#define WM8750_ADCDAC 0x05
24#define WM8750_IFACE 0x07
25#define WM8750_SRATE 0x08
26#define WM8750_LDAC 0x0a
27#define WM8750_RDAC 0x0b
28#define WM8750_BASS 0x0c
29#define WM8750_TREBLE 0x0d
30#define WM8750_RESET 0x0f
31#define WM8750_3D 0x10
32#define WM8750_ALC1 0x11
33#define WM8750_ALC2 0x12
34#define WM8750_ALC3 0x13
35#define WM8750_NGATE 0x14
36#define WM8750_LADC 0x15
37#define WM8750_RADC 0x16
38#define WM8750_ADCTL1 0x17
39#define WM8750_ADCTL2 0x18
40#define WM8750_PWR1 0x19
41#define WM8750_PWR2 0x1a
42#define WM8750_ADCTL3 0x1b
43#define WM8750_ADCIN 0x1f
44#define WM8750_LADCIN 0x20
45#define WM8750_RADCIN 0x21
46#define WM8750_LOUTM1 0x22
47#define WM8750_LOUTM2 0x23
48#define WM8750_ROUTM1 0x24
49#define WM8750_ROUTM2 0x25
50#define WM8750_MOUTM1 0x26
51#define WM8750_MOUTM2 0x27
52#define WM8750_LOUT2V 0x28
53#define WM8750_ROUT2V 0x29
54#define WM8750_MOUTV 0x2a
55
56#define WM8750_CACHE_REGNUM 0x2a
57
58#define WM8750_SYSCLK 0
59
60struct wm8750_setup_data {
61 unsigned short i2c_address;
62};
63
64extern struct snd_soc_codec_dai wm8750_dai;
65extern struct snd_soc_codec_device soc_codec_dev_wm8750;
66
67#endif
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
new file mode 100644
index 000000000000..92a64871bcd0
--- /dev/null
+++ b/sound/soc/codecs/wm9712.c
@@ -0,0 +1,771 @@
1/*
2 * wm9712.c -- ALSA Soc WM9712 codec support
3 *
4 * Copyright 2006 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Revision history
14 * 4th Feb 2006 Initial version.
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/version.h>
20#include <linux/kernel.h>
21#include <linux/device.h>
22#include <sound/driver.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/ac97_codec.h>
26#include <sound/initval.h>
27#include <sound/soc.h>
28#include <sound/soc-dapm.h>
29
30#define WM9712_VERSION "0.4"
31
32static unsigned int ac97_read(struct snd_soc_codec *codec,
33 unsigned int reg);
34static int ac97_write(struct snd_soc_codec *codec,
35 unsigned int reg, unsigned int val);
36
37/*
38 * WM9712 register cache
39 */
40static const u16 wm9712_reg[] = {
41 0x6174, 0x8000, 0x8000, 0x8000, // 6
42 0xf0f0, 0xaaa0, 0xc008, 0x6808, // e
43 0xe808, 0xaaa0, 0xad00, 0x8000, // 16
44 0xe808, 0x3000, 0x8000, 0x0000, // 1e
45 0x0000, 0x0000, 0x0000, 0x000f, // 26
46 0x0405, 0x0410, 0xbb80, 0xbb80, // 2e
47 0x0000, 0xbb80, 0x0000, 0x0000, // 36
48 0x0000, 0x2000, 0x0000, 0x0000, // 3e
49 0x0000, 0x0000, 0x0000, 0x0000, // 46
50 0x0000, 0x0000, 0xf83e, 0xffff, // 4e
51 0x0000, 0x0000, 0x0000, 0xf83e, // 56
52 0x0008, 0x0000, 0x0000, 0x0000, // 5e
53 0xb032, 0x3e00, 0x0000, 0x0000, // 66
54 0x0000, 0x0000, 0x0000, 0x0000, // 6e
55 0x0000, 0x0000, 0x0000, 0x0006, // 76
56 0x0001, 0x0000, 0x574d, 0x4c12, // 7e
57 0x0000, 0x0000 // virtual hp mixers
58};
59
60/* virtual HP mixers regs */
61#define HPL_MIXER 0x80
62#define HPR_MIXER 0x82
63
64static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"};
65static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"};
66static const char *wm9712_out3_src[] = {"Left", "VREF", "Left + Right",
67 "Mono"};
68static const char *wm9712_spk_src[] = {"Speaker Mix", "Headphone Mix"};
69static const char *wm9712_rec_adc[] = {"Stereo", "Left", "Right", "Mute"};
70static const char *wm9712_base[] = {"Linear Control", "Adaptive Boost"};
71static const char *wm9712_rec_gain[] = {"+1.5dB Steps", "+0.75dB Steps"};
72static const char *wm9712_mic[] = {"Mic 1", "Differential", "Mic 2",
73 "Stereo"};
74static const char *wm9712_rec_sel[] = {"Mic", "NC", "NC", "Speaker Mixer",
75 "Line", "Headphone Mixer", "Phone Mixer", "Phone"};
76static const char *wm9712_ng_type[] = {"Constant Gain", "Mute"};
77static const char *wm9712_diff_sel[] = {"Mic", "Line"};
78
79static const struct soc_enum wm9712_enum[] = {
80SOC_ENUM_SINGLE(AC97_PCI_SVID, 14, 4, wm9712_alc_select),
81SOC_ENUM_SINGLE(AC97_VIDEO, 12, 4, wm9712_alc_mux),
82SOC_ENUM_SINGLE(AC97_AUX, 9, 4, wm9712_out3_src),
83SOC_ENUM_SINGLE(AC97_AUX, 8, 2, wm9712_spk_src),
84SOC_ENUM_SINGLE(AC97_REC_SEL, 12, 4, wm9712_rec_adc),
85SOC_ENUM_SINGLE(AC97_MASTER_TONE, 15, 2, wm9712_base),
86SOC_ENUM_DOUBLE(AC97_REC_GAIN, 14, 6, 2, wm9712_rec_gain),
87SOC_ENUM_SINGLE(AC97_MIC, 5, 4, wm9712_mic),
88SOC_ENUM_SINGLE(AC97_REC_SEL, 8, 8, wm9712_rec_sel),
89SOC_ENUM_SINGLE(AC97_REC_SEL, 0, 8, wm9712_rec_sel),
90SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9712_ng_type),
91SOC_ENUM_SINGLE(0x5c, 8, 2, wm9712_diff_sel),
92};
93
94static const struct snd_kcontrol_new wm9712_snd_ac97_controls[] = {
95SOC_DOUBLE("Speaker Playback Volume", AC97_MASTER, 8, 0, 31, 1),
96SOC_SINGLE("Speaker Playback Switch", AC97_MASTER, 15, 1, 1),
97SOC_DOUBLE("Headphone Playback Volume", AC97_HEADPHONE, 8, 0, 31, 1),
98SOC_SINGLE("Headphone Playback Switch", AC97_HEADPHONE,15, 1, 1),
99
100SOC_SINGLE("Speaker Playback ZC Switch", AC97_MASTER, 7, 1, 0),
101SOC_SINGLE("Speaker Playback Invert Switch", AC97_MASTER, 6, 1, 0),
102SOC_SINGLE("Headphone Playback ZC Switch", AC97_HEADPHONE, 7, 1, 0),
103SOC_SINGLE("Mono Playback ZC Switch", AC97_MASTER_MONO, 7, 1, 0),
104SOC_SINGLE("Mono Playback Volume", AC97_MASTER_MONO, 0, 31, 0),
105
106SOC_SINGLE("ALC Target Volume", AC97_CODEC_CLASS_REV, 12, 15, 0),
107SOC_SINGLE("ALC Hold Time", AC97_CODEC_CLASS_REV, 8, 15, 0),
108SOC_SINGLE("ALC Decay Time", AC97_CODEC_CLASS_REV, 4, 15, 0),
109SOC_SINGLE("ALC Attack Time", AC97_CODEC_CLASS_REV, 0, 15, 0),
110SOC_ENUM("ALC Function", wm9712_enum[0]),
111SOC_SINGLE("ALC Max Volume", AC97_PCI_SVID, 11, 7, 0),
112SOC_SINGLE("ALC ZC Timeout", AC97_PCI_SVID, 9, 3, 1),
113SOC_SINGLE("ALC ZC Switch", AC97_PCI_SVID, 8, 1, 0),
114SOC_SINGLE("ALC NG Switch", AC97_PCI_SVID, 7, 1, 0),
115SOC_ENUM("ALC NG Type", wm9712_enum[10]),
116SOC_SINGLE("ALC NG Threshold", AC97_PCI_SVID, 0, 31, 1),
117
118SOC_SINGLE("Mic Headphone Volume", AC97_VIDEO, 12, 7, 1),
119SOC_SINGLE("ALC Headphone Volume", AC97_VIDEO, 7, 7, 1),
120
121SOC_SINGLE("Out3 Switch", AC97_AUX, 15, 1, 1),
122SOC_SINGLE("Out3 ZC Switch", AC97_AUX, 7, 1, 1),
123SOC_SINGLE("Out3 Volume", AC97_AUX, 0, 31, 1),
124
125SOC_SINGLE("PCBeep Bypass Headphone Volume", AC97_PC_BEEP, 12, 7, 1),
126SOC_SINGLE("PCBeep Bypass Speaker Volume", AC97_PC_BEEP, 8, 7, 1),
127SOC_SINGLE("PCBeep Bypass Phone Volume", AC97_PC_BEEP, 4, 7, 1),
128
129SOC_SINGLE("Aux Playback Headphone Volume", AC97_CD, 12, 7, 1),
130SOC_SINGLE("Aux Playback Speaker Volume", AC97_CD, 8, 7, 1),
131SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1),
132
133SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 0),
134SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1),
135
136SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0),
137SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1),
138
139SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1),
140SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1),
141SOC_SINGLE("3D Playback Volume", AC97_3D_CONTROL, 0, 15, 0),
142
143SOC_ENUM("Bass Control", wm9712_enum[5]),
144SOC_SINGLE("Bass Cut-off Switch", AC97_MASTER_TONE, 12, 1, 1),
145SOC_SINGLE("Tone Cut-off Switch", AC97_MASTER_TONE, 4, 1, 1),
146SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0),
147SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 0),
148SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 0),
149
150SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1),
151SOC_ENUM("Capture Volume Steps", wm9712_enum[6]),
152SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 1),
153SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0),
154
155SOC_SINGLE("Mic 1 Volume", AC97_MIC, 8, 31, 1),
156SOC_SINGLE("Mic 2 Volume", AC97_MIC, 0, 31, 1),
157SOC_SINGLE("Mic 20dB Boost Switch", AC97_MIC, 7, 1, 0),
158};
159
160/* add non dapm controls */
161static int wm9712_add_controls(struct snd_soc_codec *codec)
162{
163 int err, i;
164
165 for (i = 0; i < ARRAY_SIZE(wm9712_snd_ac97_controls); i++) {
166 err = snd_ctl_add(codec->card,
167 snd_soc_cnew(&wm9712_snd_ac97_controls[i],codec, NULL));
168 if (err < 0)
169 return err;
170 }
171 return 0;
172}
173
174/* We have to create a fake left and right HP mixers because
175 * the codec only has a single control that is shared by both channels.
176 * This makes it impossible to determine the audio path.
177 */
178static int mixer_event (struct snd_soc_dapm_widget *w, int event)
179{
180 u16 l, r, beep, line, phone, mic, pcm, aux;
181
182 l = ac97_read(w->codec, HPL_MIXER);
183 r = ac97_read(w->codec, HPR_MIXER);
184 beep = ac97_read(w->codec, AC97_PC_BEEP);
185 mic = ac97_read(w->codec, AC97_VIDEO);
186 phone = ac97_read(w->codec, AC97_PHONE);
187 line = ac97_read(w->codec, AC97_LINE);
188 pcm = ac97_read(w->codec, AC97_PCM);
189 aux = ac97_read(w->codec, AC97_CD);
190
191 if (l & 0x1 || r & 0x1)
192 ac97_write(w->codec, AC97_VIDEO, mic & 0x7fff);
193 else
194 ac97_write(w->codec, AC97_VIDEO, mic | 0x8000);
195
196 if (l & 0x2 || r & 0x2)
197 ac97_write(w->codec, AC97_PCM, pcm & 0x7fff);
198 else
199 ac97_write(w->codec, AC97_PCM, pcm | 0x8000);
200
201 if (l & 0x4 || r & 0x4)
202 ac97_write(w->codec, AC97_LINE, line & 0x7fff);
203 else
204 ac97_write(w->codec, AC97_LINE, line | 0x8000);
205
206 if (l & 0x8 || r & 0x8)
207 ac97_write(w->codec, AC97_PHONE, phone & 0x7fff);
208 else
209 ac97_write(w->codec, AC97_PHONE, phone | 0x8000);
210
211 if (l & 0x10 || r & 0x10)
212 ac97_write(w->codec, AC97_CD, aux & 0x7fff);
213 else
214 ac97_write(w->codec, AC97_CD, aux | 0x8000);
215
216 if (l & 0x20 || r & 0x20)
217 ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff);
218 else
219 ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000);
220
221 return 0;
222}
223
224/* Left Headphone Mixers */
225static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = {
226 SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPL_MIXER, 5, 1, 0),
227 SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 4, 1, 0),
228 SOC_DAPM_SINGLE("Phone Bypass Switch", HPL_MIXER, 3, 1, 0),
229 SOC_DAPM_SINGLE("Line Bypass Switch", HPL_MIXER, 2, 1, 0),
230 SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 1, 1, 0),
231 SOC_DAPM_SINGLE("Mic Sidetone Switch", HPL_MIXER, 0, 1, 0),
232};
233
234/* Right Headphone Mixers */
235static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = {
236 SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPR_MIXER, 5, 1, 0),
237 SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 4, 1, 0),
238 SOC_DAPM_SINGLE("Phone Bypass Switch", HPR_MIXER, 3, 1, 0),
239 SOC_DAPM_SINGLE("Line Bypass Switch", HPR_MIXER, 2, 1, 0),
240 SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 1, 1, 0),
241 SOC_DAPM_SINGLE("Mic Sidetone Switch", HPR_MIXER, 0, 1, 0),
242};
243
244/* Speaker Mixer */
245static const struct snd_kcontrol_new wm9712_speaker_mixer_controls[] = {
246 SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 11, 1, 1),
247 SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 11, 1, 1),
248 SOC_DAPM_SINGLE("Phone Bypass Switch", AC97_PHONE, 14, 1, 1),
249 SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 14, 1, 1),
250 SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 14, 1, 1),
251};
252
253/* Phone Mixer */
254static const struct snd_kcontrol_new wm9712_phone_mixer_controls[] = {
255 SOC_DAPM_SINGLE("PCBeep Bypass Switch", AC97_PC_BEEP, 7, 1, 1),
256 SOC_DAPM_SINGLE("Aux Playback Switch", AC97_CD, 7, 1, 1),
257 SOC_DAPM_SINGLE("Line Bypass Switch", AC97_LINE, 13, 1, 1),
258 SOC_DAPM_SINGLE("PCM Playback Switch", AC97_PCM, 13, 1, 1),
259 SOC_DAPM_SINGLE("Mic 1 Sidetone Switch", AC97_MIC, 14, 1, 1),
260 SOC_DAPM_SINGLE("Mic 2 Sidetone Switch", AC97_MIC, 13, 1, 1),
261};
262
263/* ALC headphone mux */
264static const struct snd_kcontrol_new wm9712_alc_mux_controls =
265SOC_DAPM_ENUM("Route", wm9712_enum[1]);
266
267/* out 3 mux */
268static const struct snd_kcontrol_new wm9712_out3_mux_controls =
269SOC_DAPM_ENUM("Route", wm9712_enum[2]);
270
271/* spk mux */
272static const struct snd_kcontrol_new wm9712_spk_mux_controls =
273SOC_DAPM_ENUM("Route", wm9712_enum[3]);
274
275/* Capture to Phone mux */
276static const struct snd_kcontrol_new wm9712_capture_phone_mux_controls =
277SOC_DAPM_ENUM("Route", wm9712_enum[4]);
278
279/* Capture left select */
280static const struct snd_kcontrol_new wm9712_capture_selectl_controls =
281SOC_DAPM_ENUM("Route", wm9712_enum[8]);
282
283/* Capture right select */
284static const struct snd_kcontrol_new wm9712_capture_selectr_controls =
285SOC_DAPM_ENUM("Route", wm9712_enum[9]);
286
287/* Mic select */
288static const struct snd_kcontrol_new wm9712_mic_src_controls =
289SOC_DAPM_ENUM("Route", wm9712_enum[7]);
290
291/* diff select */
292static const struct snd_kcontrol_new wm9712_diff_sel_controls =
293SOC_DAPM_ENUM("Route", wm9712_enum[11]);
294
295static const struct snd_soc_dapm_widget wm9712_dapm_widgets[] = {
296SND_SOC_DAPM_MUX("ALC Sidetone Mux", SND_SOC_NOPM, 0, 0,
297 &wm9712_alc_mux_controls),
298SND_SOC_DAPM_MUX("Out3 Mux", SND_SOC_NOPM, 0, 0,
299 &wm9712_out3_mux_controls),
300SND_SOC_DAPM_MUX("Speaker Mux", SND_SOC_NOPM, 0, 0,
301 &wm9712_spk_mux_controls),
302SND_SOC_DAPM_MUX("Capture Phone Mux", SND_SOC_NOPM, 0, 0,
303 &wm9712_capture_phone_mux_controls),
304SND_SOC_DAPM_MUX("Left Capture Select", SND_SOC_NOPM, 0, 0,
305 &wm9712_capture_selectl_controls),
306SND_SOC_DAPM_MUX("Right Capture Select", SND_SOC_NOPM, 0, 0,
307 &wm9712_capture_selectr_controls),
308SND_SOC_DAPM_MUX("Mic Select Source", SND_SOC_NOPM, 0, 0,
309 &wm9712_mic_src_controls),
310SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0,
311 &wm9712_diff_sel_controls),
312SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
313SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT_PAGING, 9, 1,
314 &wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls),
315 mixer_event, SND_SOC_DAPM_POST_REG),
316SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_INT_PAGING, 8, 1,
317 &wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls),
318 mixer_event, SND_SOC_DAPM_POST_REG),
319SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1,
320 &wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)),
321SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1,
322 &wm9712_speaker_mixer_controls[0],
323 ARRAY_SIZE(wm9712_speaker_mixer_controls)),
324SND_SOC_DAPM_MIXER("Mono Mixer", SND_SOC_NOPM, 0, 0, NULL, 0),
325SND_SOC_DAPM_DAC("Left DAC", "Left HiFi Playback", AC97_INT_PAGING, 14, 1),
326SND_SOC_DAPM_DAC("Right DAC", "Right HiFi Playback", AC97_INT_PAGING, 13, 1),
327SND_SOC_DAPM_DAC("Aux DAC", "Aux Playback", SND_SOC_NOPM, 0, 0),
328SND_SOC_DAPM_ADC("Left ADC", "Left HiFi Capture", AC97_INT_PAGING, 12, 1),
329SND_SOC_DAPM_ADC("Right ADC", "Right HiFi Capture", AC97_INT_PAGING, 11, 1),
330SND_SOC_DAPM_PGA("Headphone PGA", AC97_INT_PAGING, 4, 1, NULL, 0),
331SND_SOC_DAPM_PGA("Speaker PGA", AC97_INT_PAGING, 3, 1, NULL, 0),
332SND_SOC_DAPM_PGA("Out 3 PGA", AC97_INT_PAGING, 5, 1, NULL, 0),
333SND_SOC_DAPM_PGA("Line PGA", AC97_INT_PAGING, 2, 1, NULL, 0),
334SND_SOC_DAPM_PGA("Phone PGA", AC97_INT_PAGING, 1, 1, NULL, 0),
335SND_SOC_DAPM_PGA("Mic PGA", AC97_INT_PAGING, 0, 1, NULL, 0),
336SND_SOC_DAPM_MICBIAS("Mic Bias", AC97_INT_PAGING, 10, 1),
337SND_SOC_DAPM_OUTPUT("MONOOUT"),
338SND_SOC_DAPM_OUTPUT("HPOUTL"),
339SND_SOC_DAPM_OUTPUT("HPOUTR"),
340SND_SOC_DAPM_OUTPUT("LOUT2"),
341SND_SOC_DAPM_OUTPUT("ROUT2"),
342SND_SOC_DAPM_OUTPUT("OUT3"),
343SND_SOC_DAPM_INPUT("LINEINL"),
344SND_SOC_DAPM_INPUT("LINEINR"),
345SND_SOC_DAPM_INPUT("PHONE"),
346SND_SOC_DAPM_INPUT("PCBEEP"),
347SND_SOC_DAPM_INPUT("MIC1"),
348SND_SOC_DAPM_INPUT("MIC2"),
349};
350
351static const char *audio_map[][3] = {
352 /* virtual mixer - mixes left & right channels for spk and mono */
353 {"AC97 Mixer", NULL, "Left DAC"},
354 {"AC97 Mixer", NULL, "Right DAC"},
355
356 /* Left HP mixer */
357 {"Left HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
358 {"Left HP Mixer", "Aux Playback Switch", "Aux DAC"},
359 {"Left HP Mixer", "Phone Bypass Switch", "Phone PGA"},
360 {"Left HP Mixer", "Line Bypass Switch", "Line PGA"},
361 {"Left HP Mixer", "PCM Playback Switch", "Left DAC"},
362 {"Left HP Mixer", "Mic Sidetone Switch", "Mic PGA"},
363 {"Left HP Mixer", NULL, "ALC Sidetone Mux"},
364 //{"Right HP Mixer", NULL, "HP Mixer"},
365
366 /* Right HP mixer */
367 {"Right HP Mixer", "PCBeep Bypass Switch", "PCBEEP"},
368 {"Right HP Mixer", "Aux Playback Switch", "Aux DAC"},
369 {"Right HP Mixer", "Phone Bypass Switch", "Phone PGA"},
370 {"Right HP Mixer", "Line Bypass Switch", "Line PGA"},
371 {"Right HP Mixer", "PCM Playback Switch", "Right DAC"},
372 {"Right HP Mixer", "Mic Sidetone Switch", "Mic PGA"},
373 {"Right HP Mixer", NULL, "ALC Sidetone Mux"},
374
375 /* speaker mixer */
376 {"Speaker Mixer", "PCBeep Bypass Switch", "PCBEEP"},
377 {"Speaker Mixer", "Line Bypass Switch", "Line PGA"},
378 {"Speaker Mixer", "PCM Playback Switch", "AC97 Mixer"},
379 {"Speaker Mixer", "Phone Bypass Switch", "Phone PGA"},
380 {"Speaker Mixer", "Aux Playback Switch", "Aux DAC"},
381
382 /* Phone mixer */
383 {"Phone Mixer", "PCBeep Bypass Switch", "PCBEEP"},
384 {"Phone Mixer", "Line Bypass Switch", "Line PGA"},
385 {"Phone Mixer", "Aux Playback Switch", "Aux DAC"},
386 {"Phone Mixer", "PCM Playback Switch", "AC97 Mixer"},
387 {"Phone Mixer", "Mic 1 Sidetone Switch", "Mic PGA"},
388 {"Phone Mixer", "Mic 2 Sidetone Switch", "Mic PGA"},
389
390 /* inputs */
391 {"Line PGA", NULL, "LINEINL"},
392 {"Line PGA", NULL, "LINEINR"},
393 {"Phone PGA", NULL, "PHONE"},
394 {"Mic PGA", NULL, "MIC1"},
395 {"Mic PGA", NULL, "MIC2"},
396
397 /* left capture selector */
398 {"Left Capture Select", "Mic", "MIC1"},
399 {"Left Capture Select", "Speaker Mixer", "Speaker Mixer"},
400 {"Left Capture Select", "Line", "LINEINL"},
401 {"Left Capture Select", "Headphone Mixer", "Left HP Mixer"},
402 {"Left Capture Select", "Phone Mixer", "Phone Mixer"},
403 {"Left Capture Select", "Phone", "PHONE"},
404
405 /* right capture selector */
406 {"Right Capture Select", "Mic", "MIC2"},
407 {"Right Capture Select", "Speaker Mixer", "Speaker Mixer"},
408 {"Right Capture Select", "Line", "LINEINR"},
409 {"Right Capture Select", "Headphone Mixer", "Right HP Mixer"},
410 {"Right Capture Select", "Phone Mixer", "Phone Mixer"},
411 {"Right Capture Select", "Phone", "PHONE"},
412
413 /* ALC Sidetone */
414 {"ALC Sidetone Mux", "Stereo", "Left Capture Select"},
415 {"ALC Sidetone Mux", "Stereo", "Right Capture Select"},
416 {"ALC Sidetone Mux", "Left", "Left Capture Select"},
417 {"ALC Sidetone Mux", "Right", "Right Capture Select"},
418
419 /* ADC's */
420 {"Left ADC", NULL, "Left Capture Select"},
421 {"Right ADC", NULL, "Right Capture Select"},
422
423 /* outputs */
424 {"MONOOUT", NULL, "Phone Mixer"},
425 {"HPOUTL", NULL, "Headphone PGA"},
426 {"Headphone PGA", NULL, "Left HP Mixer"},
427 {"HPOUTR", NULL, "Headphone PGA"},
428 {"Headphone PGA", NULL, "Right HP Mixer"},
429
430 /* mono hp mixer */
431 {"Mono HP Mixer", NULL, "Left HP Mixer"},
432 {"Mono HP Mixer", NULL, "Right HP Mixer"},
433
434 /* Out3 Mux */
435 {"Out3 Mux", "Left", "Left HP Mixer"},
436 {"Out3 Mux", "Mono", "Phone Mixer"},
437 {"Out3 Mux", "Left + Right", "Mono HP Mixer"},
438 {"Out 3 PGA", NULL, "Out3 Mux"},
439 {"OUT3", NULL, "Out 3 PGA"},
440
441 /* speaker Mux */
442 {"Speaker Mux", "Speaker Mix", "Speaker Mixer"},
443 {"Speaker Mux", "Headphone Mix", "Mono HP Mixer"},
444 {"Speaker PGA", NULL, "Speaker Mux"},
445 {"LOUT2", NULL, "Speaker PGA"},
446 {"ROUT2", NULL, "Speaker PGA"},
447
448 {NULL, NULL, NULL},
449};
450
451static int wm9712_add_widgets(struct snd_soc_codec *codec)
452{
453 int i;
454
455 for(i = 0; i < ARRAY_SIZE(wm9712_dapm_widgets); i++) {
456 snd_soc_dapm_new_control(codec, &wm9712_dapm_widgets[i]);
457 }
458
459 /* set up audio path audio_mapnects */
460 for(i = 0; audio_map[i][0] != NULL; i++) {
461 snd_soc_dapm_connect_input(codec, audio_map[i][0],
462 audio_map[i][1], audio_map[i][2]);
463 }
464
465 snd_soc_dapm_new_widgets(codec);
466 return 0;
467}
468
469static unsigned int ac97_read(struct snd_soc_codec *codec,
470 unsigned int reg)
471{
472 u16 *cache = codec->reg_cache;
473
474 if (reg == AC97_RESET || reg == AC97_GPIO_STATUS ||
475 reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 ||
476 reg == AC97_REC_GAIN)
477 return soc_ac97_ops.read(codec->ac97, reg);
478 else {
479 reg = reg >> 1;
480
481 if (reg > (ARRAY_SIZE(wm9712_reg)))
482 return -EIO;
483
484 return cache[reg];
485 }
486}
487
488static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
489 unsigned int val)
490{
491 u16 *cache = codec->reg_cache;
492
493 soc_ac97_ops.write(codec->ac97, reg, val);
494 reg = reg >> 1;
495 if (reg <= (ARRAY_SIZE(wm9712_reg)))
496 cache[reg] = val;
497
498 return 0;
499}
500
501static int ac97_prepare(struct snd_pcm_substream *substream)
502{
503 struct snd_pcm_runtime *runtime = substream->runtime;
504 struct snd_soc_pcm_runtime *rtd = substream->private_data;
505 struct snd_soc_device *socdev = rtd->socdev;
506 struct snd_soc_codec *codec = socdev->codec;
507 int reg;
508 u16 vra;
509
510 vra = ac97_read(codec, AC97_EXTENDED_STATUS);
511 ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
512
513 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
514 reg = AC97_PCM_FRONT_DAC_RATE;
515 else
516 reg = AC97_PCM_LR_ADC_RATE;
517
518 return ac97_write(codec, reg, runtime->rate);
519}
520
521static int ac97_aux_prepare(struct snd_pcm_substream *substream)
522{
523 struct snd_pcm_runtime *runtime = substream->runtime;
524 struct snd_soc_pcm_runtime *rtd = substream->private_data;
525 struct snd_soc_device *socdev = rtd->socdev;
526 struct snd_soc_codec *codec = socdev->codec;
527 u16 vra, xsle;
528
529 vra = ac97_read(codec, AC97_EXTENDED_STATUS);
530 ac97_write(codec, AC97_EXTENDED_STATUS, vra | 0x1);
531 xsle = ac97_read(codec, AC97_PCI_SID);
532 ac97_write(codec, AC97_PCI_SID, xsle | 0x8000);
533
534 if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
535 return -ENODEV;
536
537 return ac97_write(codec, AC97_PCM_SURR_DAC_RATE, runtime->rate);
538}
539
540#define WM9712_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
541 SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000)
542
543struct snd_soc_codec_dai wm9712_dai[] = {
544{
545 .name = "AC97 HiFi",
546 .playback = {
547 .stream_name = "HiFi Playback",
548 .channels_min = 1,
549 .channels_max = 2,
550 .rates = WM9712_AC97_RATES,
551 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
552 .capture = {
553 .stream_name = "HiFi Capture",
554 .channels_min = 1,
555 .channels_max = 2,
556 .rates = WM9712_AC97_RATES,
557 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
558 .ops = {
559 .prepare = ac97_prepare,},
560},
561{
562 .name = "AC97 Aux",
563 .playback = {
564 .stream_name = "Aux Playback",
565 .channels_min = 1,
566 .channels_max = 1,
567 .rates = WM9712_AC97_RATES,
568 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
569 .ops = {
570 .prepare = ac97_aux_prepare,},
571}
572};
573EXPORT_SYMBOL_GPL(wm9712_dai);
574
575static int wm9712_dapm_event(struct snd_soc_codec *codec, int event)
576{
577 u16 reg;
578
579 switch (event) {
580 case SNDRV_CTL_POWER_D0: /* full On */
581 /* liam - maybe enable thermal shutdown */
582 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xdfff;
583 ac97_write(codec, AC97_EXTENDED_MID, reg);
584 break;
585 case SNDRV_CTL_POWER_D1: /* partial On */
586 case SNDRV_CTL_POWER_D2: /* partial On */
587 break;
588 case SNDRV_CTL_POWER_D3hot: /* Off, with power */
589 /* enable master bias and vmid */
590 reg = ac97_read(codec, AC97_EXTENDED_MID) & 0xbbff;
591 ac97_write(codec, AC97_EXTENDED_MID, reg);
592 ac97_write(codec, AC97_POWERDOWN, 0x0000);
593 break;
594 case SNDRV_CTL_POWER_D3cold: /* Off, without power */
595 /* disable everything including AC link */
596 ac97_write(codec, AC97_EXTENDED_MID, 0xffff);
597 ac97_write(codec, AC97_EXTENDED_MSTATUS, 0xffff);
598 ac97_write(codec, AC97_POWERDOWN, 0xffff);
599 break;
600 }
601 codec->dapm_state = event;
602 return 0;
603}
604
605static int wm9712_reset(struct snd_soc_codec *codec, int try_warm)
606{
607 if (try_warm && soc_ac97_ops.warm_reset) {
608 soc_ac97_ops.warm_reset(codec->ac97);
609 if (!(ac97_read(codec, 0) & 0x8000))
610 return 1;
611 }
612
613 soc_ac97_ops.reset(codec->ac97);
614 if (ac97_read(codec, 0) & 0x8000)
615 goto err;
616 return 0;
617
618err:
619 printk(KERN_ERR "WM9712 AC97 reset failed\n");
620 return -EIO;
621}
622
623static int wm9712_soc_suspend(struct platform_device *pdev,
624 pm_message_t state)
625{
626 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
627 struct snd_soc_codec *codec = socdev->codec;
628
629 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3cold);
630 return 0;
631}
632
633static int wm9712_soc_resume(struct platform_device *pdev)
634{
635 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
636 struct snd_soc_codec *codec = socdev->codec;
637 int i, ret;
638 u16 *cache = codec->reg_cache;
639
640 ret = wm9712_reset(codec, 1);
641 if (ret < 0){
642 printk(KERN_ERR "could not reset AC97 codec\n");
643 return ret;
644 }
645
646 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
647
648 if (ret == 0) {
649 /* Sync reg_cache with the hardware after cold reset */
650 for (i = 2; i < ARRAY_SIZE(wm9712_reg) << 1; i+=2) {
651 if (i == AC97_INT_PAGING || i == AC97_POWERDOWN ||
652 (i > 0x58 && i != 0x5c))
653 continue;
654 soc_ac97_ops.write(codec->ac97, i, cache[i>>1]);
655 }
656 }
657
658 if (codec->suspend_dapm_state == SNDRV_CTL_POWER_D0)
659 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D0);
660
661 return ret;
662}
663
664static int wm9712_soc_probe(struct platform_device *pdev)
665{
666 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
667 struct snd_soc_codec *codec;
668 int ret = 0;
669
670 printk(KERN_INFO "WM9711/WM9712 SoC Audio Codec %s\n", WM9712_VERSION);
671
672 socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
673 if (socdev->codec == NULL)
674 return -ENOMEM;
675 codec = socdev->codec;
676 mutex_init(&codec->mutex);
677
678 codec->reg_cache =
679 kzalloc(sizeof(u16) * ARRAY_SIZE(wm9712_reg), GFP_KERNEL);
680 if (codec->reg_cache == NULL) {
681 ret = -ENOMEM;
682 goto cache_err;
683 }
684 memcpy(codec->reg_cache, wm9712_reg, sizeof(u16) * ARRAY_SIZE(wm9712_reg));
685 codec->reg_cache_size = sizeof(u16) * ARRAY_SIZE(wm9712_reg);
686 codec->reg_cache_step = 2;
687
688 codec->name = "WM9712";
689 codec->owner = THIS_MODULE;
690 codec->dai = wm9712_dai;
691 codec->num_dai = ARRAY_SIZE(wm9712_dai);
692 codec->write = ac97_write;
693 codec->read = ac97_read;
694 codec->dapm_event = wm9712_dapm_event;
695 INIT_LIST_HEAD(&codec->dapm_widgets);
696 INIT_LIST_HEAD(&codec->dapm_paths);
697
698 ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0);
699 if (ret < 0) {
700 printk(KERN_ERR "wm9712: failed to register AC97 codec\n");
701 goto codec_err;
702 }
703
704 /* register pcms */
705 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
706 if (ret < 0)
707 goto pcm_err;
708
709 ret = wm9712_reset(codec, 0);
710 if (ret < 0) {
711 printk(KERN_ERR "AC97 link error\n");
712 goto reset_err;
713 }
714
715 /* set alc mux to none */
716 ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000);
717
718 wm9712_dapm_event(codec, SNDRV_CTL_POWER_D3hot);
719 wm9712_add_controls(codec);
720 wm9712_add_widgets(codec);
721 ret = snd_soc_register_card(socdev);
722 if (ret < 0) {
723 printk(KERN_ERR "wm9712: failed to register card\n");
724 goto reset_err;
725 }
726
727 return 0;
728
729reset_err:
730 snd_soc_free_pcms(socdev);
731
732pcm_err:
733 snd_soc_free_ac97_codec(codec);
734
735codec_err:
736 kfree(codec->reg_cache);
737
738cache_err:
739 kfree(socdev->codec);
740 socdev->codec = NULL;
741 return ret;
742}
743
744static int wm9712_soc_remove(struct platform_device *pdev)
745{
746 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
747 struct snd_soc_codec *codec = socdev->codec;
748
749 if (codec == NULL)
750 return 0;
751
752 snd_soc_dapm_free(socdev);
753 snd_soc_free_pcms(socdev);
754 snd_soc_free_ac97_codec(codec);
755 kfree(codec->reg_cache);
756 kfree(codec);
757 return 0;
758}
759
760struct snd_soc_codec_device soc_codec_dev_wm9712 = {
761 .probe = wm9712_soc_probe,
762 .remove = wm9712_soc_remove,
763 .suspend = wm9712_soc_suspend,
764 .resume = wm9712_soc_resume,
765};
766
767EXPORT_SYMBOL_GPL(soc_codec_dev_wm9712);
768
769MODULE_DESCRIPTION("ASoC WM9711/WM9712 driver");
770MODULE_AUTHOR("Liam Girdwood");
771MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm9712.h b/sound/soc/codecs/wm9712.h
new file mode 100644
index 000000000000..719105d61e65
--- /dev/null
+++ b/sound/soc/codecs/wm9712.h
@@ -0,0 +1,14 @@
1/*
2 * wm9712.h -- WM9712 Soc Audio driver
3 */
4
5#ifndef _WM9712_H
6#define _WM9712_H
7
8#define WM9712_DAI_AC97_HIFI 0
9#define WM9712_DAI_AC97_AUX 1
10
11extern struct snd_soc_codec_dai wm9712_dai[2];
12extern struct snd_soc_codec_device soc_codec_dev_wm9712;
13
14#endif
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
new file mode 100644
index 000000000000..579e1c8d2b28
--- /dev/null
+++ b/sound/soc/pxa/Kconfig
@@ -0,0 +1,60 @@
1menu "SoC Audio for the Intel PXA2xx"
2
3config SND_PXA2XX_SOC
4 tristate "SoC Audio for the Intel PXA2xx chip"
5 depends on ARCH_PXA && SND
6 select SND_PCM
7 help
8 Say Y or M if you want to add support for codecs attached to
9 the PXA2xx AC97, I2S or SSP interface. You will also need
10 to select the audio interfaces to support below.
11
12config SND_PXA2XX_AC97
13 tristate
14 select SND_AC97_CODEC
15
16config SND_PXA2XX_SOC_AC97
17 tristate
18 select AC97_BUS
19 select SND_SOC_AC97_BUS
20
21config SND_PXA2XX_SOC_I2S
22 tristate
23
24config SND_PXA2XX_SOC_CORGI
25 tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
26 depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
27 select SND_PXA2XX_SOC_I2S
28 select SND_SOC_WM8731
29 help
30 Say Y if you want to add support for SoC audio on Sharp
31 Zaurus SL-C7x0 models (Corgi, Shepherd, Husky).
32
33config SND_PXA2XX_SOC_SPITZ
34 tristate "SoC Audio support for Sharp Zaurus SL-Cxx00"
35 depends on SND_PXA2XX_SOC && PXA_SHARP_Cxx00
36 select SND_PXA2XX_SOC_I2S
37 select SND_SOC_WM8750
38 help
39 Say Y if you want to add support for SoC audio on Sharp
40 Zaurus SL-Cxx00 models (Spitz, Borzoi and Akita).
41
42config SND_PXA2XX_SOC_POODLE
43 tristate "SoC Audio support for Poodle"
44 depends on SND_PXA2XX_SOC && MACH_POODLE
45 select SND_PXA2XX_SOC_I2S
46 select SND_SOC_WM8731
47 help
48 Say Y if you want to add support for SoC audio on Sharp
49 Zaurus SL-5600 model (Poodle).
50
51config SND_PXA2XX_SOC_TOSA
52 tristate "SoC AC97 Audio support for Tosa"
53 depends on SND_PXA2XX_SOC && MACH_TOSA
54 select SND_PXA2XX_SOC_AC97
55 select SND_SOC_WM9712
56 help
57 Say Y if you want to add support for SoC audio on Sharp
58 Zaurus SL-C6000x models (Tosa).
59
60endmenu
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
new file mode 100644
index 000000000000..78e0d6b07d1d
--- /dev/null
+++ b/sound/soc/pxa/Makefile
@@ -0,0 +1,20 @@
1# PXA Platform Support
2snd-soc-pxa2xx-objs := pxa2xx-pcm.o
3snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
4snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
5
6obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
7obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
8obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
9
10# PXA Machine Support
11snd-soc-corgi-objs := corgi.o
12snd-soc-poodle-objs := poodle.o
13snd-soc-tosa-objs := tosa.o
14snd-soc-spitz-objs := spitz.o
15
16obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
17obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
18obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
19obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
20
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
new file mode 100644
index 000000000000..5ee51a994ac3
--- /dev/null
+++ b/sound/soc/pxa/corgi.c
@@ -0,0 +1,383 @@
1/*
2 * corgi.c -- SoC audio for Corgi
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd.
6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
8 * Richard Purdie <richard@openedhand.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * Revision history
16 * 30th Nov 2005 Initial version.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/timer.h>
23#include <linux/interrupt.h>
24#include <linux/platform_device.h>
25#include <sound/driver.h>
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/soc.h>
29#include <sound/soc-dapm.h>
30
31#include <asm/mach-types.h>
32#include <asm/hardware/scoop.h>
33#include <asm/arch/pxa-regs.h>
34#include <asm/arch/hardware.h>
35#include <asm/arch/corgi.h>
36#include <asm/arch/audio.h>
37
38#include "../codecs/wm8731.h"
39#include "pxa2xx-pcm.h"
40#include "pxa2xx-i2s.h"
41
42#define CORGI_HP 0
43#define CORGI_MIC 1
44#define CORGI_LINE 2
45#define CORGI_HEADSET 3
46#define CORGI_HP_OFF 4
47#define CORGI_SPK_ON 0
48#define CORGI_SPK_OFF 1
49
50 /* audio clock in Hz - rounded from 12.235MHz */
51#define CORGI_AUDIO_CLOCK 12288000
52
53static int corgi_jack_func;
54static int corgi_spk_func;
55
56static void corgi_ext_control(struct snd_soc_codec *codec)
57{
58 int spk = 0, mic = 0, line = 0, hp = 0, hs = 0;
59
60 /* set up jack connection */
61 switch (corgi_jack_func) {
62 case CORGI_HP:
63 hp = 1;
64 /* set = unmute headphone */
65 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
66 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
67 break;
68 case CORGI_MIC:
69 mic = 1;
70 /* reset = mute headphone */
71 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
72 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
73 break;
74 case CORGI_LINE:
75 line = 1;
76 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
77 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
78 break;
79 case CORGI_HEADSET:
80 hs = 1;
81 mic = 1;
82 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
83 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
84 break;
85 }
86
87 if (corgi_spk_func == CORGI_SPK_ON)
88 spk = 1;
89
90 /* set the enpoints to their new connetion states */
91 snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
92 snd_soc_dapm_set_endpoint(codec, "Mic Jack", mic);
93 snd_soc_dapm_set_endpoint(codec, "Line Jack", line);
94 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
95 snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
96
97 /* signal a DAPM event */
98 snd_soc_dapm_sync_endpoints(codec);
99}
100
101static int corgi_startup(struct snd_pcm_substream *substream)
102{
103 struct snd_soc_pcm_runtime *rtd = substream->private_data;
104 struct snd_soc_codec *codec = rtd->socdev->codec;
105
106 /* check the jack status at stream startup */
107 corgi_ext_control(codec);
108 return 0;
109}
110
111/* we need to unmute the HP at shutdown as the mute burns power on corgi */
112static int corgi_shutdown(struct snd_pcm_substream *substream)
113{
114 struct snd_soc_pcm_runtime *rtd = substream->private_data;
115 struct snd_soc_codec *codec = rtd->socdev->codec;
116
117 /* set = unmute headphone */
118 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_L);
119 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MUTE_R);
120 return 0;
121}
122
123static int corgi_hw_params(struct snd_pcm_substream *substream,
124 struct snd_pcm_hw_params *params)
125{
126 struct snd_soc_pcm_runtime *rtd = substream->private_data;
127 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
128 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
129 unsigned int clk = 0;
130 int ret = 0;
131
132 switch (params_rate(params)) {
133 case 8000:
134 case 16000:
135 case 48000:
136 case 96000:
137 clk = 12288000;
138 break;
139 case 11025:
140 case 22050:
141 case 44100:
142 clk = 11289600;
143 break;
144 }
145
146 /* set codec DAI configuration */
147 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
148 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
149 if (ret < 0)
150 return ret;
151
152 /* set cpu DAI configuration */
153 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
154 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
155 if (ret < 0)
156 return ret;
157
158 /* set the codec system clock for DAC and ADC */
159 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk,
160 SND_SOC_CLOCK_IN);
161 if (ret < 0)
162 return ret;
163
164 /* set the I2S system clock as input (unused) */
165 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
166 SND_SOC_CLOCK_IN);
167 if (ret < 0)
168 return ret;
169
170 return 0;
171}
172
173static struct snd_soc_ops corgi_ops = {
174 .startup = corgi_startup,
175 .hw_params = corgi_hw_params,
176 .shutdown = corgi_shutdown,
177};
178
179static int corgi_get_jack(struct snd_kcontrol *kcontrol,
180 struct snd_ctl_elem_value *ucontrol)
181{
182 ucontrol->value.integer.value[0] = corgi_jack_func;
183 return 0;
184}
185
186static int corgi_set_jack(struct snd_kcontrol *kcontrol,
187 struct snd_ctl_elem_value *ucontrol)
188{
189 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
190
191 if (corgi_jack_func == ucontrol->value.integer.value[0])
192 return 0;
193
194 corgi_jack_func = ucontrol->value.integer.value[0];
195 corgi_ext_control(codec);
196 return 1;
197}
198
199static int corgi_get_spk(struct snd_kcontrol *kcontrol,
200 struct snd_ctl_elem_value *ucontrol)
201{
202 ucontrol->value.integer.value[0] = corgi_spk_func;
203 return 0;
204}
205
206static int corgi_set_spk(struct snd_kcontrol *kcontrol,
207 struct snd_ctl_elem_value *ucontrol)
208{
209 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
210
211 if (corgi_spk_func == ucontrol->value.integer.value[0])
212 return 0;
213
214 corgi_spk_func = ucontrol->value.integer.value[0];
215 corgi_ext_control(codec);
216 return 1;
217}
218
219static int corgi_amp_event(struct snd_soc_dapm_widget *w, int event)
220{
221 if (SND_SOC_DAPM_EVENT_ON(event))
222 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
223 else
224 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_APM_ON);
225
226 return 0;
227}
228
229static int corgi_mic_event(struct snd_soc_dapm_widget *w, int event)
230{
231 if (SND_SOC_DAPM_EVENT_ON(event))
232 set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
233 else
234 reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_MIC_BIAS);
235
236 return 0;
237}
238
239/* corgi machine dapm widgets */
240static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
241SND_SOC_DAPM_HP("Headphone Jack", NULL),
242SND_SOC_DAPM_MIC("Mic Jack", corgi_mic_event),
243SND_SOC_DAPM_SPK("Ext Spk", corgi_amp_event),
244SND_SOC_DAPM_LINE("Line Jack", NULL),
245SND_SOC_DAPM_HP("Headset Jack", NULL),
246};
247
248/* Corgi machine audio map (connections to the codec pins) */
249static const char *audio_map[][3] = {
250
251 /* headset Jack - in = micin, out = LHPOUT*/
252 {"Headset Jack", NULL, "LHPOUT"},
253
254 /* headphone connected to LHPOUT1, RHPOUT1 */
255 {"Headphone Jack", NULL, "LHPOUT"},
256 {"Headphone Jack", NULL, "RHPOUT"},
257
258 /* speaker connected to LOUT, ROUT */
259 {"Ext Spk", NULL, "ROUT"},
260 {"Ext Spk", NULL, "LOUT"},
261
262 /* mic is connected to MICIN (via right channel of headphone jack) */
263 {"MICIN", NULL, "Mic Jack"},
264
265 /* Same as the above but no mic bias for line signals */
266 {"MICIN", NULL, "Line Jack"},
267
268 {NULL, NULL, NULL},
269};
270
271static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
272 "Off"};
273static const char *spk_function[] = {"On", "Off"};
274static const struct soc_enum corgi_enum[] = {
275 SOC_ENUM_SINGLE_EXT(5, jack_function),
276 SOC_ENUM_SINGLE_EXT(2, spk_function),
277};
278
279static const struct snd_kcontrol_new wm8731_corgi_controls[] = {
280 SOC_ENUM_EXT("Jack Function", corgi_enum[0], corgi_get_jack,
281 corgi_set_jack),
282 SOC_ENUM_EXT("Speaker Function", corgi_enum[1], corgi_get_spk,
283 corgi_set_spk),
284};
285
286/*
287 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
288 */
289static int corgi_wm8731_init(struct snd_soc_codec *codec)
290{
291 int i, err;
292
293 snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
294 snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
295
296 /* Add corgi specific controls */
297 for (i = 0; i < ARRAY_SIZE(wm8731_corgi_controls); i++) {
298 err = snd_ctl_add(codec->card,
299 snd_soc_cnew(&wm8731_corgi_controls[i],codec, NULL));
300 if (err < 0)
301 return err;
302 }
303
304 /* Add corgi specific widgets */
305 for(i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
306 snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
307 }
308
309 /* Set up corgi specific audio path audio_map */
310 for(i = 0; audio_map[i][0] != NULL; i++) {
311 snd_soc_dapm_connect_input(codec, audio_map[i][0],
312 audio_map[i][1], audio_map[i][2]);
313 }
314
315 snd_soc_dapm_sync_endpoints(codec);
316 return 0;
317}
318
319/* corgi digital audio interface glue - connects codec <--> CPU */
320static struct snd_soc_dai_link corgi_dai = {
321 .name = "WM8731",
322 .stream_name = "WM8731",
323 .cpu_dai = &pxa_i2s_dai,
324 .codec_dai = &wm8731_dai,
325 .init = corgi_wm8731_init,
326 .ops = &corgi_ops,
327};
328
329/* corgi audio machine driver */
330static struct snd_soc_machine snd_soc_machine_corgi = {
331 .name = "Corgi",
332 .dai_link = &corgi_dai,
333 .num_links = 1,
334};
335
336/* corgi audio private data */
337static struct wm8731_setup_data corgi_wm8731_setup = {
338 .i2c_address = 0x1b,
339};
340
341/* corgi audio subsystem */
342static struct snd_soc_device corgi_snd_devdata = {
343 .machine = &snd_soc_machine_corgi,
344 .platform = &pxa2xx_soc_platform,
345 .codec_dev = &soc_codec_dev_wm8731,
346 .codec_data = &corgi_wm8731_setup,
347};
348
349static struct platform_device *corgi_snd_device;
350
351static int __init corgi_init(void)
352{
353 int ret;
354
355 if (!(machine_is_corgi() || machine_is_shepherd() || machine_is_husky()))
356 return -ENODEV;
357
358 corgi_snd_device = platform_device_alloc("soc-audio", -1);
359 if (!corgi_snd_device)
360 return -ENOMEM;
361
362 platform_set_drvdata(corgi_snd_device, &corgi_snd_devdata);
363 corgi_snd_devdata.dev = &corgi_snd_device->dev;
364 ret = platform_device_add(corgi_snd_device);
365
366 if (ret)
367 platform_device_put(corgi_snd_device);
368
369 return ret;
370}
371
372static void __exit corgi_exit(void)
373{
374 platform_device_unregister(corgi_snd_device);
375}
376
377module_init(corgi_init);
378module_exit(corgi_exit);
379
380/* Module information */
381MODULE_AUTHOR("Richard Purdie");
382MODULE_DESCRIPTION("ALSA SoC Corgi");
383MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
new file mode 100644
index 000000000000..0915cf740421
--- /dev/null
+++ b/sound/soc/pxa/poodle.c
@@ -0,0 +1,352 @@
1/*
2 * poodle.c -- SoC audio for Poodle
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd.
6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
8 * Richard Purdie <richard@openedhand.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 */
16
17#include <linux/module.h>
18#include <linux/moduleparam.h>
19#include <linux/timer.h>
20#include <linux/interrupt.h>
21#include <linux/platform_device.h>
22#include <sound/driver.h>
23#include <sound/core.h>
24#include <sound/pcm.h>
25#include <sound/soc.h>
26#include <sound/soc-dapm.h>
27
28#include <asm/mach-types.h>
29#include <asm/hardware/locomo.h>
30#include <asm/arch/pxa-regs.h>
31#include <asm/arch/hardware.h>
32#include <asm/arch/poodle.h>
33#include <asm/arch/audio.h>
34
35#include "../codecs/wm8731.h"
36#include "pxa2xx-pcm.h"
37#include "pxa2xx-i2s.h"
38
39#define POODLE_HP 1
40#define POODLE_HP_OFF 0
41#define POODLE_SPK_ON 1
42#define POODLE_SPK_OFF 0
43
44 /* audio clock in Hz - rounded from 12.235MHz */
45#define POODLE_AUDIO_CLOCK 12288000
46
47static int poodle_jack_func;
48static int poodle_spk_func;
49
50static void poodle_ext_control(struct snd_soc_codec *codec)
51{
52 int spk = 0;
53
54 /* set up jack connection */
55 if (poodle_jack_func == POODLE_HP) {
56 /* set = unmute headphone */
57 locomo_gpio_write(&poodle_locomo_device.dev,
58 POODLE_LOCOMO_GPIO_MUTE_L, 1);
59 locomo_gpio_write(&poodle_locomo_device.dev,
60 POODLE_LOCOMO_GPIO_MUTE_R, 1);
61 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
62 } else {
63 locomo_gpio_write(&poodle_locomo_device.dev,
64 POODLE_LOCOMO_GPIO_MUTE_L, 0);
65 locomo_gpio_write(&poodle_locomo_device.dev,
66 POODLE_LOCOMO_GPIO_MUTE_R, 0);
67 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
68 }
69
70 if (poodle_spk_func == POODLE_SPK_ON)
71 spk = 1;
72
73 /* set the enpoints to their new connetion states */
74 snd_soc_dapm_set_endpoint(codec, "Ext Spk", spk);
75
76 /* signal a DAPM event */
77 snd_soc_dapm_sync_endpoints(codec);
78}
79
80static int poodle_startup(struct snd_pcm_substream *substream)
81{
82 struct snd_soc_pcm_runtime *rtd = substream->private_data;
83 struct snd_soc_codec *codec = rtd->socdev->codec;
84
85 /* check the jack status at stream startup */
86 poodle_ext_control(codec);
87 return 0;
88}
89
90/* we need to unmute the HP at shutdown as the mute burns power on poodle */
91static int poodle_shutdown(struct snd_pcm_substream *substream)
92{
93 struct snd_soc_pcm_runtime *rtd = substream->private_data;
94 struct snd_soc_codec *codec = rtd->socdev->codec;
95
96 /* set = unmute headphone */
97 locomo_gpio_write(&poodle_locomo_device.dev,
98 POODLE_LOCOMO_GPIO_MUTE_L, 1);
99 locomo_gpio_write(&poodle_locomo_device.dev,
100 POODLE_LOCOMO_GPIO_MUTE_R, 1);
101 return 0;
102}
103
104static int poodle_hw_params(struct snd_pcm_substream *substream,
105 struct snd_pcm_hw_params *params)
106{
107 struct snd_soc_pcm_runtime *rtd = substream->private_data;
108 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
109 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
110 unsigned int clk = 0;
111 int ret = 0;
112
113 switch (params_rate(params)) {
114 case 8000:
115 case 16000:
116 case 48000:
117 case 96000:
118 clk = 12288000;
119 break;
120 case 11025:
121 case 22050:
122 case 44100:
123 clk = 11289600;
124 break;
125 }
126
127 /* set codec DAI configuration */
128 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
129 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
130 if (ret < 0)
131 return ret;
132
133 /* set cpu DAI configuration */
134 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
135 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
136 if (ret < 0)
137 return ret;
138
139 /* set the codec system clock for DAC and ADC */
140 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8731_SYSCLK, clk,
141 SND_SOC_CLOCK_IN);
142 if (ret < 0)
143 return ret;
144
145 /* set the I2S system clock as input (unused) */
146 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
147 SND_SOC_CLOCK_IN);
148 if (ret < 0)
149 return ret;
150
151 return 0;
152}
153
154static struct snd_soc_ops poodle_ops = {
155 .startup = poodle_startup,
156 .hw_params = poodle_hw_params,
157 .shutdown = poodle_shutdown,
158};
159
160static int poodle_get_jack(struct snd_kcontrol *kcontrol,
161 struct snd_ctl_elem_value *ucontrol)
162{
163 ucontrol->value.integer.value[0] = poodle_jack_func;
164 return 0;
165}
166
167static int poodle_set_jack(struct snd_kcontrol *kcontrol,
168 struct snd_ctl_elem_value *ucontrol)
169{
170 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
171
172 if (poodle_jack_func == ucontrol->value.integer.value[0])
173 return 0;
174
175 poodle_jack_func = ucontrol->value.integer.value[0];
176 poodle_ext_control(codec);
177 return 1;
178}
179
180static int poodle_get_spk(struct snd_kcontrol *kcontrol,
181 struct snd_ctl_elem_value *ucontrol)
182{
183 ucontrol->value.integer.value[0] = poodle_spk_func;
184 return 0;
185}
186
187static int poodle_set_spk(struct snd_kcontrol *kcontrol,
188 struct snd_ctl_elem_value *ucontrol)
189{
190 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
191
192 if (poodle_spk_func == ucontrol->value.integer.value[0])
193 return 0;
194
195 poodle_spk_func = ucontrol->value.integer.value[0];
196 poodle_ext_control(codec);
197 return 1;
198}
199
200static int poodle_amp_event(struct snd_soc_dapm_widget *w, int event)
201{
202 if (SND_SOC_DAPM_EVENT_ON(event))
203 locomo_gpio_write(&poodle_locomo_device.dev,
204 POODLE_LOCOMO_GPIO_AMP_ON, 0);
205 else
206 locomo_gpio_write(&poodle_locomo_device.dev,
207 POODLE_LOCOMO_GPIO_AMP_ON, 1);
208
209 return 0;
210}
211
212/* poodle machine dapm widgets */
213static const struct snd_soc_dapm_widget wm8731_dapm_widgets[] = {
214SND_SOC_DAPM_HP("Headphone Jack", NULL),
215SND_SOC_DAPM_SPK("Ext Spk", poodle_amp_event),
216};
217
218/* Corgi machine audio_mapnections to the codec pins */
219static const char *audio_map[][3] = {
220
221 /* headphone connected to LHPOUT1, RHPOUT1 */
222 {"Headphone Jack", NULL, "LHPOUT"},
223 {"Headphone Jack", NULL, "RHPOUT"},
224
225 /* speaker connected to LOUT, ROUT */
226 {"Ext Spk", NULL, "ROUT"},
227 {"Ext Spk", NULL, "LOUT"},
228
229 {NULL, NULL, NULL},
230};
231
232static const char *jack_function[] = {"Off", "Headphone"};
233static const char *spk_function[] = {"Off", "On"};
234static const struct soc_enum poodle_enum[] = {
235 SOC_ENUM_SINGLE_EXT(2, jack_function),
236 SOC_ENUM_SINGLE_EXT(2, spk_function),
237};
238
239static const snd_kcontrol_new_t wm8731_poodle_controls[] = {
240 SOC_ENUM_EXT("Jack Function", poodle_enum[0], poodle_get_jack,
241 poodle_set_jack),
242 SOC_ENUM_EXT("Speaker Function", poodle_enum[1], poodle_get_spk,
243 poodle_set_spk),
244};
245
246/*
247 * Logic for a wm8731 as connected on a Sharp SL-C7x0 Device
248 */
249static int poodle_wm8731_init(struct snd_soc_codec *codec)
250{
251 int i, err;
252
253 snd_soc_dapm_set_endpoint(codec, "LLINEIN", 0);
254 snd_soc_dapm_set_endpoint(codec, "RLINEIN", 0);
255 snd_soc_dapm_set_endpoint(codec, "MICIN", 1);
256
257 /* Add poodle specific controls */
258 for (i = 0; i < ARRAY_SIZE(wm8731_poodle_controls); i++) {
259 err = snd_ctl_add(codec->card,
260 snd_soc_cnew(&wm8731_poodle_controls[i],codec, NULL));
261 if (err < 0)
262 return err;
263 }
264
265 /* Add poodle specific widgets */
266 for (i = 0; i < ARRAY_SIZE(wm8731_dapm_widgets); i++) {
267 snd_soc_dapm_new_control(codec, &wm8731_dapm_widgets[i]);
268 }
269
270 /* Set up poodle specific audio path audio_map */
271 for (i = 0; audio_map[i][0] != NULL; i++) {
272 snd_soc_dapm_connect_input(codec, audio_map[i][0],
273 audio_map[i][1], audio_map[i][2]);
274 }
275
276 snd_soc_dapm_sync_endpoints(codec);
277 return 0;
278}
279
280/* poodle digital audio interface glue - connects codec <--> CPU */
281static struct snd_soc_dai_link poodle_dai = {
282 .name = "WM8731",
283 .stream_name = "WM8731",
284 .cpu_dai = &pxa_i2s_dai,
285 .codec_dai = &wm8731_dai,
286 .init = poodle_wm8731_init,
287 .ops = &poodle_ops,
288};
289
290/* poodle audio machine driver */
291static struct snd_soc_machine snd_soc_machine_poodle = {
292 .name = "Poodle",
293 .dai_link = &poodle_dai,
294 .num_links = 1,
295};
296
297/* poodle audio private data */
298static struct wm8731_setup_data poodle_wm8731_setup = {
299 .i2c_address = 0x1b,
300};
301
302/* poodle audio subsystem */
303static struct snd_soc_device poodle_snd_devdata = {
304 .machine = &snd_soc_machine_poodle,
305 .platform = &pxa2xx_soc_platform,
306 .codec_dev = &soc_codec_dev_wm8731,
307 .codec_data = &poodle_wm8731_setup,
308};
309
310static struct platform_device *poodle_snd_device;
311
312static int __init poodle_init(void)
313{
314 int ret;
315
316 if (!machine_is_poodle())
317 return -ENODEV;
318
319 locomo_gpio_set_dir(&poodle_locomo_device.dev,
320 POODLE_LOCOMO_GPIO_AMP_ON, 0);
321 /* should we mute HP at startup - burning power ?*/
322 locomo_gpio_set_dir(&poodle_locomo_device.dev,
323 POODLE_LOCOMO_GPIO_MUTE_L, 0);
324 locomo_gpio_set_dir(&poodle_locomo_device.dev,
325 POODLE_LOCOMO_GPIO_MUTE_R, 0);
326
327 poodle_snd_device = platform_device_alloc("soc-audio", -1);
328 if (!poodle_snd_device)
329 return -ENOMEM;
330
331 platform_set_drvdata(poodle_snd_device, &poodle_snd_devdata);
332 poodle_snd_devdata.dev = &poodle_snd_device->dev;
333 ret = platform_device_add(poodle_snd_device);
334
335 if (ret)
336 platform_device_put(poodle_snd_device);
337
338 return ret;
339}
340
341static void __exit poodle_exit(void)
342{
343 platform_device_unregister(poodle_snd_device);
344}
345
346module_init(poodle_init);
347module_exit(poodle_exit);
348
349/* Module information */
350MODULE_AUTHOR("Richard Purdie");
351MODULE_DESCRIPTION("ALSA SoC Poodle");
352MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
new file mode 100644
index 000000000000..1bbbeff84ef0
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -0,0 +1,431 @@
1/*
2 * linux/sound/pxa2xx-ac97.c -- AC97 support for the Intel PXA2xx chip.
3 *
4 * Author: Nicolas Pitre
5 * Created: Dec 02, 2004
6 * Copyright: MontaVista Software Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/init.h>
14#include <linux/module.h>
15#include <linux/platform_device.h>
16#include <linux/interrupt.h>
17#include <linux/wait.h>
18#include <linux/delay.h>
19
20#include <sound/driver.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/ac97_codec.h>
24#include <sound/initval.h>
25#include <sound/soc.h>
26
27#include <asm/irq.h>
28#include <linux/mutex.h>
29#include <asm/hardware.h>
30#include <asm/arch/pxa-regs.h>
31#include <asm/arch/audio.h>
32
33#include "pxa2xx-pcm.h"
34#include "pxa2xx-ac97.h"
35
36static DEFINE_MUTEX(car_mutex);
37static DECLARE_WAIT_QUEUE_HEAD(gsr_wq);
38static volatile long gsr_bits;
39
40/*
41 * Beware PXA27x bugs:
42 *
43 * o Slot 12 read from modem space will hang controller.
44 * o CDONE, SDONE interrupt fails after any slot 12 IO.
45 *
46 * We therefore have an hybrid approach for waiting on SDONE (interrupt or
47 * 1 jiffy timeout if interrupt never comes).
48 */
49
50static unsigned short pxa2xx_ac97_read(struct snd_ac97 *ac97,
51 unsigned short reg)
52{
53 unsigned short val = -1;
54 volatile u32 *reg_addr;
55
56 mutex_lock(&car_mutex);
57
58 /* set up primary or secondary codec/modem space */
59#ifdef CONFIG_PXA27x
60 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
61#else
62 if (reg == AC97_GPIO_STATUS)
63 reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
64 else
65 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
66#endif
67 reg_addr += (reg >> 1);
68
69#ifndef CONFIG_PXA27x
70 if (reg == AC97_GPIO_STATUS) {
71 /* read from controller cache */
72 val = *reg_addr;
73 goto out;
74 }
75#endif
76
77 /* start read access across the ac97 link */
78 GSR = GSR_CDONE | GSR_SDONE;
79 gsr_bits = 0;
80 val = *reg_addr;
81
82 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
83 if (!((GSR | gsr_bits) & GSR_SDONE)) {
84 printk(KERN_ERR "%s: read error (ac97_reg=%x GSR=%#lx)\n",
85 __FUNCTION__, reg, GSR | gsr_bits);
86 val = -1;
87 goto out;
88 }
89
90 /* valid data now */
91 GSR = GSR_CDONE | GSR_SDONE;
92 gsr_bits = 0;
93 val = *reg_addr;
94 /* but we've just started another cycle... */
95 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_SDONE, 1);
96
97out: mutex_unlock(&car_mutex);
98 return val;
99}
100
101static void pxa2xx_ac97_write(struct snd_ac97 *ac97, unsigned short reg,
102 unsigned short val)
103{
104 volatile u32 *reg_addr;
105
106 mutex_lock(&car_mutex);
107
108 /* set up primary or secondary codec/modem space */
109#ifdef CONFIG_PXA27x
110 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
111#else
112 if (reg == AC97_GPIO_STATUS)
113 reg_addr = ac97->num ? &SMC_REG_BASE : &PMC_REG_BASE;
114 else
115 reg_addr = ac97->num ? &SAC_REG_BASE : &PAC_REG_BASE;
116#endif
117 reg_addr += (reg >> 1);
118
119 GSR = GSR_CDONE | GSR_SDONE;
120 gsr_bits = 0;
121 *reg_addr = val;
122 wait_event_timeout(gsr_wq, (GSR | gsr_bits) & GSR_CDONE, 1);
123 if (!((GSR | gsr_bits) & GSR_CDONE))
124 printk(KERN_ERR "%s: write error (ac97_reg=%x GSR=%#lx)\n",
125 __FUNCTION__, reg, GSR | gsr_bits);
126
127 mutex_unlock(&car_mutex);
128}
129
130static void pxa2xx_ac97_warm_reset(struct snd_ac97 *ac97)
131{
132 gsr_bits = 0;
133
134#ifdef CONFIG_PXA27x
135 /* warm reset broken on Bulverde,
136 so manually keep AC97 reset high */
137 pxa_gpio_mode(113 | GPIO_OUT | GPIO_DFLT_HIGH);
138 udelay(10);
139 GCR |= GCR_WARM_RST;
140 pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
141 udelay(500);
142#else
143 GCR |= GCR_WARM_RST | GCR_PRIRDY_IEN | GCR_SECRDY_IEN;
144 wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
145#endif
146
147 if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
148 printk(KERN_INFO "%s: warm reset timeout (GSR=%#lx)\n",
149 __FUNCTION__, gsr_bits);
150
151 GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
152 GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
153}
154
155static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97)
156{
157 GCR &= GCR_COLD_RST; /* clear everything but nCRST */
158 GCR &= ~GCR_COLD_RST; /* then assert nCRST */
159
160 gsr_bits = 0;
161#ifdef CONFIG_PXA27x
162 /* PXA27x Developers Manual section 13.5.2.2.1 */
163 pxa_set_cken(1 << 31, 1);
164 udelay(5);
165 pxa_set_cken(1 << 31, 0);
166 GCR = GCR_COLD_RST;
167 udelay(50);
168#else
169 GCR = GCR_COLD_RST;
170 GCR |= GCR_CDONE_IE|GCR_SDONE_IE;
171 wait_event_timeout(gsr_wq, gsr_bits & (GSR_PCR | GSR_SCR), 1);
172#endif
173
174 if (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)))
175 printk(KERN_INFO "%s: cold reset timeout (GSR=%#lx)\n",
176 __FUNCTION__, gsr_bits);
177
178 GCR &= ~(GCR_PRIRDY_IEN|GCR_SECRDY_IEN);
179 GCR |= GCR_SDONE_IE|GCR_CDONE_IE;
180}
181
182static irqreturn_t pxa2xx_ac97_irq(int irq, void *dev_id)
183{
184 long status;
185
186 status = GSR;
187 if (status) {
188 GSR = status;
189 gsr_bits |= status;
190 wake_up(&gsr_wq);
191
192#ifdef CONFIG_PXA27x
193 /* Although we don't use those we still need to clear them
194 since they tend to spuriously trigger when MMC is used
195 (hardware bug? go figure)... */
196 MISR = MISR_EOC;
197 PISR = PISR_EOC;
198 MCSR = MCSR_EOC;
199#endif
200
201 return IRQ_HANDLED;
202 }
203
204 return IRQ_NONE;
205}
206
207struct snd_ac97_bus_ops soc_ac97_ops = {
208 .read = pxa2xx_ac97_read,
209 .write = pxa2xx_ac97_write,
210 .warm_reset = pxa2xx_ac97_warm_reset,
211 .reset = pxa2xx_ac97_cold_reset,
212};
213
214static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = {
215 .name = "AC97 PCM Stereo out",
216 .dev_addr = __PREG(PCDR),
217 .drcmr = &DRCMRTXPCDR,
218 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
219 DCMD_BURST32 | DCMD_WIDTH4,
220};
221
222static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_in = {
223 .name = "AC97 PCM Stereo in",
224 .dev_addr = __PREG(PCDR),
225 .drcmr = &DRCMRRXPCDR,
226 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
227 DCMD_BURST32 | DCMD_WIDTH4,
228};
229
230static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_out = {
231 .name = "AC97 Aux PCM (Slot 5) Mono out",
232 .dev_addr = __PREG(MODR),
233 .drcmr = &DRCMRTXMODR,
234 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
235 DCMD_BURST16 | DCMD_WIDTH2,
236};
237
238static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_aux_mono_in = {
239 .name = "AC97 Aux PCM (Slot 5) Mono in",
240 .dev_addr = __PREG(MODR),
241 .drcmr = &DRCMRRXMODR,
242 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
243 DCMD_BURST16 | DCMD_WIDTH2,
244};
245
246static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
247 .name = "AC97 Mic PCM (Slot 6) Mono in",
248 .dev_addr = __PREG(MCDR),
249 .drcmr = &DRCMRRXMCDR,
250 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
251 DCMD_BURST16 | DCMD_WIDTH2,
252};
253
254#ifdef CONFIG_PM
255static int pxa2xx_ac97_suspend(struct platform_device *pdev,
256 struct snd_soc_cpu_dai *dai)
257{
258 GCR |= GCR_ACLINK_OFF;
259 pxa_set_cken(CKEN2_AC97, 0);
260 return 0;
261}
262
263static int pxa2xx_ac97_resume(struct platform_device *pdev,
264 struct snd_soc_cpu_dai *dai)
265{
266 pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
267 pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
268 pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
269 pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
270#ifdef CONFIG_PXA27x
271 /* Use GPIO 113 as AC97 Reset on Bulverde */
272 pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
273#endif
274 pxa_set_cken(CKEN2_AC97, 1);
275 return 0;
276}
277
278#else
279#define pxa2xx_ac97_suspend NULL
280#define pxa2xx_ac97_resume NULL
281#endif
282
283static int pxa2xx_ac97_probe(struct platform_device *pdev)
284{
285 int ret;
286
287 ret = request_irq(IRQ_AC97, pxa2xx_ac97_irq, IRQF_DISABLED, "AC97", NULL);
288 if (ret < 0)
289 goto err;
290
291 pxa_gpio_mode(GPIO31_SYNC_AC97_MD);
292 pxa_gpio_mode(GPIO30_SDATA_OUT_AC97_MD);
293 pxa_gpio_mode(GPIO28_BITCLK_AC97_MD);
294 pxa_gpio_mode(GPIO29_SDATA_IN_AC97_MD);
295#ifdef CONFIG_PXA27x
296 /* Use GPIO 113 as AC97 Reset on Bulverde */
297 pxa_gpio_mode(113 | GPIO_ALT_FN_2_OUT);
298#endif
299 pxa_set_cken(CKEN2_AC97, 1);
300 return 0;
301
302 err:
303 if (CKEN & CKEN2_AC97) {
304 GCR |= GCR_ACLINK_OFF;
305 free_irq(IRQ_AC97, NULL);
306 pxa_set_cken(CKEN2_AC97, 0);
307 }
308 return ret;
309}
310
311static void pxa2xx_ac97_remove(struct platform_device *pdev)
312{
313 GCR |= GCR_ACLINK_OFF;
314 free_irq(IRQ_AC97, NULL);
315 pxa_set_cken(CKEN2_AC97, 0);
316}
317
318static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
319 struct snd_pcm_hw_params *params)
320{
321 struct snd_soc_pcm_runtime *rtd = substream->private_data;
322 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
323
324 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
325 cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_out;
326 else
327 cpu_dai->dma_data = &pxa2xx_ac97_pcm_stereo_in;
328
329 return 0;
330}
331
332static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
333 struct snd_pcm_hw_params *params)
334{
335 struct snd_soc_pcm_runtime *rtd = substream->private_data;
336 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
337
338 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
339 cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_out;
340 else
341 cpu_dai->dma_data = &pxa2xx_ac97_pcm_aux_mono_in;
342
343 return 0;
344}
345
346static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
347 struct snd_pcm_hw_params *params)
348{
349 struct snd_soc_pcm_runtime *rtd = substream->private_data;
350 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
351
352 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
353 return -ENODEV;
354 else
355 cpu_dai->dma_data = &pxa2xx_ac97_pcm_mic_mono_in;
356
357 return 0;
358}
359
360#define PXA2XX_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
361 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
362 SNDRV_PCM_RATE_48000)
363
364/*
365 * There is only 1 physical AC97 interface for pxa2xx, but it
366 * has extra fifo's that can be used for aux DACs and ADCs.
367 */
368struct snd_soc_cpu_dai pxa_ac97_dai[] = {
369{
370 .name = "pxa2xx-ac97",
371 .id = 0,
372 .type = SND_SOC_DAI_AC97,
373 .probe = pxa2xx_ac97_probe,
374 .remove = pxa2xx_ac97_remove,
375 .suspend = pxa2xx_ac97_suspend,
376 .resume = pxa2xx_ac97_resume,
377 .playback = {
378 .stream_name = "AC97 Playback",
379 .channels_min = 2,
380 .channels_max = 2,
381 .rates = PXA2XX_AC97_RATES,
382 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
383 .capture = {
384 .stream_name = "AC97 Capture",
385 .channels_min = 2,
386 .channels_max = 2,
387 .rates = PXA2XX_AC97_RATES,
388 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
389 .ops = {
390 .hw_params = pxa2xx_ac97_hw_params,},
391},
392{
393 .name = "pxa2xx-ac97-aux",
394 .id = 1,
395 .type = SND_SOC_DAI_AC97,
396 .playback = {
397 .stream_name = "AC97 Aux Playback",
398 .channels_min = 1,
399 .channels_max = 1,
400 .rates = PXA2XX_AC97_RATES,
401 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
402 .capture = {
403 .stream_name = "AC97 Aux Capture",
404 .channels_min = 1,
405 .channels_max = 1,
406 .rates = PXA2XX_AC97_RATES,
407 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
408 .ops = {
409 .hw_params = pxa2xx_ac97_hw_aux_params,},
410},
411{
412 .name = "pxa2xx-ac97-mic",
413 .id = 2,
414 .type = SND_SOC_DAI_AC97,
415 .capture = {
416 .stream_name = "AC97 Mic Capture",
417 .channels_min = 1,
418 .channels_max = 1,
419 .rates = PXA2XX_AC97_RATES,
420 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
421 .ops = {
422 .hw_params = pxa2xx_ac97_hw_mic_params,},
423},
424};
425
426EXPORT_SYMBOL_GPL(pxa_ac97_dai);
427EXPORT_SYMBOL_GPL(soc_ac97_ops);
428
429MODULE_AUTHOR("Nicolas Pitre");
430MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
431MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-ac97.h b/sound/soc/pxa/pxa2xx-ac97.h
new file mode 100644
index 000000000000..4c4b882316ac
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-ac97.h
@@ -0,0 +1,22 @@
1/*
2 * linux/sound/arm/pxa2xx-ac97.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _PXA2XX_AC97_H
10#define _PXA2XX_AC97_H
11
12/* pxa2xx DAI ID's */
13#define PXA2XX_DAI_AC97_HIFI 0
14#define PXA2XX_DAI_AC97_AUX 1
15#define PXA2XX_DAI_AC97_MIC 2
16
17extern struct snd_soc_cpu_dai pxa_ac97_dai[3];
18
19/* platform data */
20extern struct snd_ac97_bus_ops pxa2xx_ac97_ops;
21
22#endif
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
new file mode 100644
index 000000000000..575a6137c040
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -0,0 +1,318 @@
1/*
2 * pxa2xx-i2s.c -- ALSA Soc Audio Layer
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Revision history
14 * 12th Aug 2005 Initial version.
15 */
16
17#include <linux/init.h>
18#include <linux/module.h>
19#include <linux/device.h>
20#include <linux/delay.h>
21#include <sound/driver.h>
22#include <sound/core.h>
23#include <sound/pcm.h>
24#include <sound/initval.h>
25#include <sound/soc.h>
26
27#include <asm/hardware.h>
28#include <asm/arch/pxa-regs.h>
29#include <asm/arch/audio.h>
30
31#include "pxa2xx-pcm.h"
32#include "pxa2xx-i2s.h"
33
34struct pxa_i2s_port {
35 u32 sadiv;
36 u32 sacr0;
37 u32 sacr1;
38 u32 saimr;
39 int master;
40 u32 fmt;
41};
42static struct pxa_i2s_port pxa_i2s;
43
44static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_out = {
45 .name = "I2S PCM Stereo out",
46 .dev_addr = __PREG(SADR),
47 .drcmr = &DRCMRTXSADR,
48 .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
49 DCMD_BURST32 | DCMD_WIDTH4,
50};
51
52static struct pxa2xx_pcm_dma_params pxa2xx_i2s_pcm_stereo_in = {
53 .name = "I2S PCM Stereo in",
54 .dev_addr = __PREG(SADR),
55 .drcmr = &DRCMRRXSADR,
56 .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
57 DCMD_BURST32 | DCMD_WIDTH4,
58};
59
60static struct pxa2xx_gpio gpio_bus[] = {
61 { /* I2S SoC Slave */
62 .rx = GPIO29_SDATA_IN_I2S_MD,
63 .tx = GPIO30_SDATA_OUT_I2S_MD,
64 .clk = GPIO28_BITCLK_IN_I2S_MD,
65 .frm = GPIO31_SYNC_I2S_MD,
66 },
67 { /* I2S SoC Master */
68#ifdef CONFIG_PXA27x
69 .sys = GPIO113_I2S_SYSCLK_MD,
70#else
71 .sys = GPIO32_SYSCLK_I2S_MD,
72#endif
73 .rx = GPIO29_SDATA_IN_I2S_MD,
74 .tx = GPIO30_SDATA_OUT_I2S_MD,
75 .clk = GPIO28_BITCLK_OUT_I2S_MD,
76 .frm = GPIO31_SYNC_I2S_MD,
77 },
78};
79
80static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
81{
82 struct snd_soc_pcm_runtime *rtd = substream->private_data;
83 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
84
85 if (!cpu_dai->active) {
86 SACR0 |= SACR0_RST;
87 SACR0 = 0;
88 }
89
90 return 0;
91}
92
93/* wait for I2S controller to be ready */
94static int pxa_i2s_wait(void)
95{
96 int i;
97
98 /* flush the Rx FIFO */
99 for(i = 0; i < 16; i++)
100 SADR;
101 return 0;
102}
103
104static int pxa2xx_i2s_set_dai_fmt(struct snd_soc_cpu_dai *cpu_dai,
105 unsigned int fmt)
106{
107 /* interface format */
108 switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
109 case SND_SOC_DAIFMT_I2S:
110 pxa_i2s.fmt = 0;
111 break;
112 case SND_SOC_DAIFMT_LEFT_J:
113 pxa_i2s.fmt = SACR1_AMSL;
114 break;
115 }
116
117 switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
118 case SND_SOC_DAIFMT_CBS_CFS:
119 pxa_i2s.master = 1;
120 break;
121 case SND_SOC_DAIFMT_CBM_CFS:
122 pxa_i2s.master = 0;
123 break;
124 default:
125 break;
126 }
127 return 0;
128}
129
130static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_cpu_dai *cpu_dai,
131 int clk_id, unsigned int freq, int dir)
132{
133 if (clk_id != PXA2XX_I2S_SYSCLK)
134 return -ENODEV;
135
136 if (pxa_i2s.master && dir == SND_SOC_CLOCK_OUT)
137 pxa_gpio_mode(gpio_bus[pxa_i2s.master].sys);
138
139 return 0;
140}
141
142static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
143 struct snd_pcm_hw_params *params)
144{
145 struct snd_soc_pcm_runtime *rtd = substream->private_data;
146 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
147
148 pxa_gpio_mode(gpio_bus[pxa_i2s.master].rx);
149 pxa_gpio_mode(gpio_bus[pxa_i2s.master].tx);
150 pxa_gpio_mode(gpio_bus[pxa_i2s.master].frm);
151 pxa_gpio_mode(gpio_bus[pxa_i2s.master].clk);
152 pxa_set_cken(CKEN8_I2S, 1);
153 pxa_i2s_wait();
154
155 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
156 cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_out;
157 else
158 cpu_dai->dma_data = &pxa2xx_i2s_pcm_stereo_in;
159
160 /* is port used by another stream */
161 if (!(SACR0 & SACR0_ENB)) {
162
163 SACR0 = 0;
164 SACR1 = 0;
165 if (pxa_i2s.master)
166 SACR0 |= SACR0_BCKD;
167
168 SACR0 |= SACR0_RFTH(14) | SACR0_TFTH(1);
169 SACR1 |= pxa_i2s.fmt;
170 }
171 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
172 SAIMR |= SAIMR_TFS;
173 else
174 SAIMR |= SAIMR_RFS;
175
176 switch (params_rate(params)) {
177 case 8000:
178 SADIV = 0x48;
179 break;
180 case 11025:
181 SADIV = 0x34;
182 break;
183 case 16000:
184 SADIV = 0x24;
185 break;
186 case 22050:
187 SADIV = 0x1a;
188 break;
189 case 44100:
190 SADIV = 0xd;
191 break;
192 case 48000:
193 SADIV = 0xc;
194 break;
195 case 96000: /* not in manual and possibly slightly inaccurate */
196 SADIV = 0x6;
197 break;
198 }
199
200 return 0;
201}
202
203static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
204{
205 int ret = 0;
206
207 switch (cmd) {
208 case SNDRV_PCM_TRIGGER_START:
209 SACR0 |= SACR0_ENB;
210 break;
211 case SNDRV_PCM_TRIGGER_RESUME:
212 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
213 case SNDRV_PCM_TRIGGER_STOP:
214 case SNDRV_PCM_TRIGGER_SUSPEND:
215 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
216 break;
217 default:
218 ret = -EINVAL;
219 }
220
221 return ret;
222}
223
224static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
225{
226 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
227 SACR1 |= SACR1_DRPL;
228 SAIMR &= ~SAIMR_TFS;
229 } else {
230 SACR1 |= SACR1_DREC;
231 SAIMR &= ~SAIMR_RFS;
232 }
233
234 if (SACR1 & (SACR1_DREC | SACR1_DRPL)) {
235 SACR0 &= ~SACR0_ENB;
236 pxa_i2s_wait();
237 pxa_set_cken(CKEN8_I2S, 0);
238 }
239}
240
241#ifdef CONFIG_PM
242static int pxa2xx_i2s_suspend(struct platform_device *dev,
243 struct snd_soc_cpu_dai *dai)
244{
245 if (!dai->active)
246 return 0;
247
248 /* store registers */
249 pxa_i2s.sacr0 = SACR0;
250 pxa_i2s.sacr1 = SACR1;
251 pxa_i2s.saimr = SAIMR;
252 pxa_i2s.sadiv = SADIV;
253
254 /* deactivate link */
255 SACR0 &= ~SACR0_ENB;
256 pxa_i2s_wait();
257 return 0;
258}
259
260static int pxa2xx_i2s_resume(struct platform_device *pdev,
261 struct snd_soc_cpu_dai *dai)
262{
263 if (!dai->active)
264 return 0;
265
266 pxa_i2s_wait();
267
268 SACR0 = pxa_i2s.sacr0 &= ~SACR0_ENB;
269 SACR1 = pxa_i2s.sacr1;
270 SAIMR = pxa_i2s.saimr;
271 SADIV = pxa_i2s.sadiv;
272 SACR0 |= SACR0_ENB;
273
274 return 0;
275}
276
277#else
278#define pxa2xx_i2s_suspend NULL
279#define pxa2xx_i2s_resume NULL
280#endif
281
282#define PXA2XX_I2S_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
283 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \
284 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000)
285
286struct snd_soc_cpu_dai pxa_i2s_dai = {
287 .name = "pxa2xx-i2s",
288 .id = 0,
289 .type = SND_SOC_DAI_I2S,
290 .suspend = pxa2xx_i2s_suspend,
291 .resume = pxa2xx_i2s_resume,
292 .playback = {
293 .channels_min = 2,
294 .channels_max = 2,
295 .rates = PXA2XX_I2S_RATES,
296 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
297 .capture = {
298 .channels_min = 2,
299 .channels_max = 2,
300 .rates = PXA2XX_I2S_RATES,
301 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
302 .ops = {
303 .startup = pxa2xx_i2s_startup,
304 .shutdown = pxa2xx_i2s_shutdown,
305 .trigger = pxa2xx_i2s_trigger,
306 .hw_params = pxa2xx_i2s_hw_params,},
307 .dai_ops = {
308 .set_fmt = pxa2xx_i2s_set_dai_fmt,
309 .set_sysclk = pxa2xx_i2s_set_dai_sysclk,
310 },
311};
312
313EXPORT_SYMBOL_GPL(pxa_i2s_dai);
314
315/* Module information */
316MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
317MODULE_DESCRIPTION("pxa2xx I2S SoC Interface");
318MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-i2s.h b/sound/soc/pxa/pxa2xx-i2s.h
new file mode 100644
index 000000000000..a2484f0881f1
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-i2s.h
@@ -0,0 +1,20 @@
1/*
2 * linux/sound/arm/pxa2xx-i2s.h
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 */
8
9#ifndef _PXA2XX_I2S_H
10#define _PXA2XX_I2S_H
11
12/* pxa2xx DAI ID's */
13#define PXA2XX_DAI_I2S 0
14
15/* I2S clock */
16#define PXA2XX_I2S_SYSCLK 0
17
18extern struct snd_soc_cpu_dai pxa_i2s_dai;
19
20#endif
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
new file mode 100644
index 000000000000..35e8fa3a469c
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -0,0 +1,372 @@
1/*
2 * linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip
3 *
4 * Author: Nicolas Pitre
5 * Created: Nov 30, 2004
6 * Copyright: (C) 2004 MontaVista Software, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#include <linux/module.h>
14#include <linux/init.h>
15#include <linux/platform_device.h>
16#include <linux/slab.h>
17#include <linux/dma-mapping.h>
18
19#include <sound/driver.h>
20#include <sound/core.h>
21#include <sound/pcm.h>
22#include <sound/pcm_params.h>
23#include <sound/soc.h>
24
25#include <asm/dma.h>
26#include <asm/hardware.h>
27#include <asm/arch/pxa-regs.h>
28#include <asm/arch/audio.h>
29
30#include "pxa2xx-pcm.h"
31
32static const struct snd_pcm_hardware pxa2xx_pcm_hardware = {
33 .info = SNDRV_PCM_INFO_MMAP |
34 SNDRV_PCM_INFO_MMAP_VALID |
35 SNDRV_PCM_INFO_INTERLEAVED |
36 SNDRV_PCM_INFO_PAUSE |
37 SNDRV_PCM_INFO_RESUME,
38 .formats = SNDRV_PCM_FMTBIT_S16_LE |
39 SNDRV_PCM_FMTBIT_S24_LE |
40 SNDRV_PCM_FMTBIT_S32_LE,
41 .period_bytes_min = 32,
42 .period_bytes_max = 8192 - 32,
43 .periods_min = 1,
44 .periods_max = PAGE_SIZE/sizeof(pxa_dma_desc),
45 .buffer_bytes_max = 128 * 1024,
46 .fifo_size = 32,
47};
48
49struct pxa2xx_runtime_data {
50 int dma_ch;
51 struct pxa2xx_pcm_dma_params *params;
52 pxa_dma_desc *dma_desc_array;
53 dma_addr_t dma_desc_array_phys;
54};
55
56static void pxa2xx_pcm_dma_irq(int dma_ch, void *dev_id)
57{
58 struct snd_pcm_substream *substream = dev_id;
59 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
60 int dcsr;
61
62 dcsr = DCSR(dma_ch);
63 DCSR(dma_ch) = dcsr & ~DCSR_STOPIRQEN;
64
65 if (dcsr & DCSR_ENDINTR) {
66 snd_pcm_period_elapsed(substream);
67 } else {
68 printk( KERN_ERR "%s: DMA error on channel %d (DCSR=%#x)\n",
69 prtd->params->name, dma_ch, dcsr );
70 }
71}
72
73static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
74 struct snd_pcm_hw_params *params)
75{
76 struct snd_pcm_runtime *runtime = substream->runtime;
77 struct pxa2xx_runtime_data *prtd = runtime->private_data;
78 struct snd_soc_pcm_runtime *rtd = substream->private_data;
79 struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
80 size_t totsize = params_buffer_bytes(params);
81 size_t period = params_period_bytes(params);
82 pxa_dma_desc *dma_desc;
83 dma_addr_t dma_buff_phys, next_desc_phys;
84 int ret;
85
86 /* return if this is a bufferless transfer e.g.
87 * codec <--> BT codec or GSM modem -- lg FIXME */
88 if (!dma)
89 return 0;
90
91 /* this may get called several times by oss emulation
92 * with different params */
93 if (prtd->params == NULL) {
94 prtd->params = dma;
95 ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
96 pxa2xx_pcm_dma_irq, substream);
97 if (ret < 0)
98 return ret;
99 prtd->dma_ch = ret;
100 } else if (prtd->params != dma) {
101 pxa_free_dma(prtd->dma_ch);
102 prtd->params = dma;
103 ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
104 pxa2xx_pcm_dma_irq, substream);
105 if (ret < 0)
106 return ret;
107 prtd->dma_ch = ret;
108 }
109
110 snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
111 runtime->dma_bytes = totsize;
112
113 dma_desc = prtd->dma_desc_array;
114 next_desc_phys = prtd->dma_desc_array_phys;
115 dma_buff_phys = runtime->dma_addr;
116 do {
117 next_desc_phys += sizeof(pxa_dma_desc);
118 dma_desc->ddadr = next_desc_phys;
119 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
120 dma_desc->dsadr = dma_buff_phys;
121 dma_desc->dtadr = prtd->params->dev_addr;
122 } else {
123 dma_desc->dsadr = prtd->params->dev_addr;
124 dma_desc->dtadr = dma_buff_phys;
125 }
126 if (period > totsize)
127 period = totsize;
128 dma_desc->dcmd = prtd->params->dcmd | period | DCMD_ENDIRQEN;
129 dma_desc++;
130 dma_buff_phys += period;
131 } while (totsize -= period);
132 dma_desc[-1].ddadr = prtd->dma_desc_array_phys;
133
134 return 0;
135}
136
137static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
138{
139 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
140
141 if (prtd && prtd->params)
142 *prtd->params->drcmr = 0;
143
144 if (prtd->dma_ch) {
145 snd_pcm_set_runtime_buffer(substream, NULL);
146 pxa_free_dma(prtd->dma_ch);
147 prtd->dma_ch = 0;
148 }
149
150 return 0;
151}
152
153static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
154{
155 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
156
157 DCSR(prtd->dma_ch) &= ~DCSR_RUN;
158 DCSR(prtd->dma_ch) = 0;
159 DCMD(prtd->dma_ch) = 0;
160 *prtd->params->drcmr = prtd->dma_ch | DRCMR_MAPVLD;
161
162 return 0;
163}
164
165static int pxa2xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
166{
167 struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;
168 int ret = 0;
169
170 switch (cmd) {
171 case SNDRV_PCM_TRIGGER_START:
172 DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
173 DCSR(prtd->dma_ch) = DCSR_RUN;
174 break;
175
176 case SNDRV_PCM_TRIGGER_STOP:
177 case SNDRV_PCM_TRIGGER_SUSPEND:
178 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
179 DCSR(prtd->dma_ch) &= ~DCSR_RUN;
180 break;
181
182 case SNDRV_PCM_TRIGGER_RESUME:
183 DCSR(prtd->dma_ch) |= DCSR_RUN;
184 break;
185 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
186 DDADR(prtd->dma_ch) = prtd->dma_desc_array_phys;
187 DCSR(prtd->dma_ch) |= DCSR_RUN;
188 break;
189
190 default:
191 ret = -EINVAL;
192 }
193
194 return ret;
195}
196
197static snd_pcm_uframes_t
198pxa2xx_pcm_pointer(struct snd_pcm_substream *substream)
199{
200 struct snd_pcm_runtime *runtime = substream->runtime;
201 struct pxa2xx_runtime_data *prtd = runtime->private_data;
202
203 dma_addr_t ptr = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
204 DSADR(prtd->dma_ch) : DTADR(prtd->dma_ch);
205 snd_pcm_uframes_t x = bytes_to_frames(runtime, ptr - runtime->dma_addr);
206
207 if (x == runtime->buffer_size)
208 x = 0;
209 return x;
210}
211
212static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
213{
214 struct snd_pcm_runtime *runtime = substream->runtime;
215 struct pxa2xx_runtime_data *prtd;
216 int ret;
217
218 snd_soc_set_runtime_hwparams(substream, &pxa2xx_pcm_hardware);
219
220 /*
221 * For mysterious reasons (and despite what the manual says)
222 * playback samples are lost if the DMA count is not a multiple
223 * of the DMA burst size. Let's add a rule to enforce that.
224 */
225 ret = snd_pcm_hw_constraint_step(runtime, 0,
226 SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
227 if (ret)
228 goto out;
229
230 ret = snd_pcm_hw_constraint_step(runtime, 0,
231 SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
232 if (ret)
233 goto out;
234
235 ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
236 if (ret < 0)
237 goto out;
238
239 prtd = kzalloc(sizeof(struct pxa2xx_runtime_data), GFP_KERNEL);
240 if (prtd == NULL) {
241 ret = -ENOMEM;
242 goto out;
243 }
244
245 prtd->dma_desc_array =
246 dma_alloc_writecombine(substream->pcm->card->dev, PAGE_SIZE,
247 &prtd->dma_desc_array_phys, GFP_KERNEL);
248 if (!prtd->dma_desc_array) {
249 ret = -ENOMEM;
250 goto err1;
251 }
252
253 runtime->private_data = prtd;
254 return 0;
255
256 err1:
257 kfree(prtd);
258 out:
259 return ret;
260}
261
262static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
263{
264 struct snd_pcm_runtime *runtime = substream->runtime;
265 struct pxa2xx_runtime_data *prtd = runtime->private_data;
266
267 dma_free_writecombine(substream->pcm->card->dev, PAGE_SIZE,
268 prtd->dma_desc_array, prtd->dma_desc_array_phys);
269 kfree(prtd);
270 return 0;
271}
272
273static int pxa2xx_pcm_mmap(struct snd_pcm_substream *substream,
274 struct vm_area_struct *vma)
275{
276 struct snd_pcm_runtime *runtime = substream->runtime;
277 return dma_mmap_writecombine(substream->pcm->card->dev, vma,
278 runtime->dma_area,
279 runtime->dma_addr,
280 runtime->dma_bytes);
281}
282
283struct snd_pcm_ops pxa2xx_pcm_ops = {
284 .open = pxa2xx_pcm_open,
285 .close = pxa2xx_pcm_close,
286 .ioctl = snd_pcm_lib_ioctl,
287 .hw_params = pxa2xx_pcm_hw_params,
288 .hw_free = pxa2xx_pcm_hw_free,
289 .prepare = pxa2xx_pcm_prepare,
290 .trigger = pxa2xx_pcm_trigger,
291 .pointer = pxa2xx_pcm_pointer,
292 .mmap = pxa2xx_pcm_mmap,
293};
294
295static int pxa2xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
296{
297 struct snd_pcm_substream *substream = pcm->streams[stream].substream;
298 struct snd_dma_buffer *buf = &substream->dma_buffer;
299 size_t size = pxa2xx_pcm_hardware.buffer_bytes_max;
300 buf->dev.type = SNDRV_DMA_TYPE_DEV;
301 buf->dev.dev = pcm->card->dev;
302 buf->private_data = NULL;
303 buf->area = dma_alloc_writecombine(pcm->card->dev, size,
304 &buf->addr, GFP_KERNEL);
305 if (!buf->area)
306 return -ENOMEM;
307 buf->bytes = size;
308 return 0;
309}
310
311static void pxa2xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
312{
313 struct snd_pcm_substream *substream;
314 struct snd_dma_buffer *buf;
315 int stream;
316
317 for (stream = 0; stream < 2; stream++) {
318 substream = pcm->streams[stream].substream;
319 if (!substream)
320 continue;
321
322 buf = &substream->dma_buffer;
323 if (!buf->area)
324 continue;
325
326 dma_free_writecombine(pcm->card->dev, buf->bytes,
327 buf->area, buf->addr);
328 buf->area = NULL;
329 }
330}
331
332static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK;
333
334int pxa2xx_pcm_new(struct snd_card *card, struct snd_soc_codec_dai *dai,
335 struct snd_pcm *pcm)
336{
337 int ret = 0;
338
339 if (!card->dev->dma_mask)
340 card->dev->dma_mask = &pxa2xx_pcm_dmamask;
341 if (!card->dev->coherent_dma_mask)
342 card->dev->coherent_dma_mask = DMA_32BIT_MASK;
343
344 if (dai->playback.channels_min) {
345 ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
346 SNDRV_PCM_STREAM_PLAYBACK);
347 if (ret)
348 goto out;
349 }
350
351 if (dai->capture.channels_min) {
352 ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
353 SNDRV_PCM_STREAM_CAPTURE);
354 if (ret)
355 goto out;
356 }
357 out:
358 return ret;
359}
360
361struct snd_soc_platform pxa2xx_soc_platform = {
362 .name = "pxa2xx-audio",
363 .pcm_ops = &pxa2xx_pcm_ops,
364 .pcm_new = pxa2xx_pcm_new,
365 .pcm_free = pxa2xx_pcm_free_dma_buffers,
366};
367
368EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
369
370MODULE_AUTHOR("Nicolas Pitre");
371MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
372MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-pcm.h b/sound/soc/pxa/pxa2xx-pcm.h
new file mode 100644
index 000000000000..54c9c755e508
--- /dev/null
+++ b/sound/soc/pxa/pxa2xx-pcm.h
@@ -0,0 +1,34 @@
1/*
2 * linux/sound/arm/pxa2xx-pcm.h -- ALSA PCM interface for the Intel PXA2xx chip
3 *
4 * Author: Nicolas Pitre
5 * Created: Nov 30, 2004
6 * Copyright: MontaVista Software, Inc.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
13#ifndef _PXA2XX_PCM_H
14#define _PXA2XX_PCM_H
15
16struct pxa2xx_pcm_dma_params {
17 char *name; /* stream identifier */
18 u32 dcmd; /* DMA descriptor dcmd field */
19 volatile u32 *drcmr; /* the DMA request channel to use */
20 u32 dev_addr; /* device physical address for DMA */
21};
22
23struct pxa2xx_gpio {
24 u32 sys;
25 u32 rx;
26 u32 tx;
27 u32 clk;
28 u32 frm;
29};
30
31/* platform data */
32extern struct snd_soc_platform pxa2xx_soc_platform;
33
34#endif
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
new file mode 100644
index 000000000000..80e82109fef7
--- /dev/null
+++ b/sound/soc/pxa/spitz.c
@@ -0,0 +1,394 @@
1/*
2 * spitz.c -- SoC audio for Sharp SL-Cxx00 models Spitz, Borzoi and Akita
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd.
6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
8 * Richard Purdie <richard@openedhand.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * Revision history
16 * 30th Nov 2005 Initial version.
17 *
18 */
19
20#include <linux/module.h>
21#include <linux/moduleparam.h>
22#include <linux/timer.h>
23#include <linux/interrupt.h>
24#include <linux/platform_device.h>
25#include <sound/driver.h>
26#include <sound/core.h>
27#include <sound/pcm.h>
28#include <sound/soc.h>
29#include <sound/soc-dapm.h>
30
31#include <asm/mach-types.h>
32#include <asm/hardware/scoop.h>
33#include <asm/arch/pxa-regs.h>
34#include <asm/arch/hardware.h>
35#include <asm/arch/akita.h>
36#include <asm/arch/spitz.h>
37#include <asm/mach-types.h>
38#include "../codecs/wm8750.h"
39#include "pxa2xx-pcm.h"
40#include "pxa2xx-i2s.h"
41
42#define SPITZ_HP 0
43#define SPITZ_MIC 1
44#define SPITZ_LINE 2
45#define SPITZ_HEADSET 3
46#define SPITZ_HP_OFF 4
47#define SPITZ_SPK_ON 0
48#define SPITZ_SPK_OFF 1
49
50 /* audio clock in Hz - rounded from 12.235MHz */
51#define SPITZ_AUDIO_CLOCK 12288000
52
53static int spitz_jack_func;
54static int spitz_spk_func;
55
56static void spitz_ext_control(struct snd_soc_codec *codec)
57{
58 if (spitz_spk_func == SPITZ_SPK_ON)
59 snd_soc_dapm_set_endpoint(codec, "Ext Spk", 1);
60 else
61 snd_soc_dapm_set_endpoint(codec, "Ext Spk", 0);
62
63 /* set up jack connection */
64 switch (spitz_jack_func) {
65 case SPITZ_HP:
66 /* enable and unmute hp jack, disable mic bias */
67 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
68 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
69 snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
70 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 1);
71 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
72 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
73 break;
74 case SPITZ_MIC:
75 /* enable mic jack and bias, mute hp */
76 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
77 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
78 snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
79 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
80 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
81 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
82 break;
83 case SPITZ_LINE:
84 /* enable line jack, disable mic bias and mute hp */
85 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
86 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
87 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
88 snd_soc_dapm_set_endpoint(codec, "Line Jack", 1);
89 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
90 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
91 break;
92 case SPITZ_HEADSET:
93 /* enable and unmute headset jack enable mic bias, mute L hp */
94 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
95 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 1);
96 snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
97 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 1);
98 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
99 set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
100 break;
101 case SPITZ_HP_OFF:
102
103 /* jack removed, everything off */
104 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", 0);
105 snd_soc_dapm_set_endpoint(codec, "Headset Jack", 0);
106 snd_soc_dapm_set_endpoint(codec, "Mic Jack", 0);
107 snd_soc_dapm_set_endpoint(codec, "Line Jack", 0);
108 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_L);
109 reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_MUTE_R);
110 break;
111 }
112 snd_soc_dapm_sync_endpoints(codec);
113}
114
115static int spitz_startup(struct snd_pcm_substream *substream)
116{
117 struct snd_soc_pcm_runtime *rtd = substream->private_data;
118 struct snd_soc_codec *codec = rtd->socdev->codec;
119
120 /* check the jack status at stream startup */
121 spitz_ext_control(codec);
122 return 0;
123}
124
125static int spitz_hw_params(struct snd_pcm_substream *substream,
126 struct snd_pcm_hw_params *params)
127{
128 struct snd_soc_pcm_runtime *rtd = substream->private_data;
129 struct snd_soc_codec_dai *codec_dai = rtd->dai->codec_dai;
130 struct snd_soc_cpu_dai *cpu_dai = rtd->dai->cpu_dai;
131 unsigned int clk = 0;
132 int ret = 0;
133
134 switch (params_rate(params)) {
135 case 8000:
136 case 16000:
137 case 48000:
138 case 96000:
139 clk = 12288000;
140 break;
141 case 11025:
142 case 22050:
143 case 44100:
144 clk = 11289600;
145 break;
146 }
147
148 /* set codec DAI configuration */
149 ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
150 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
151 if (ret < 0)
152 return ret;
153
154 /* set cpu DAI configuration */
155 ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
156 SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
157 if (ret < 0)
158 return ret;
159
160 /* set the codec system clock for DAC and ADC */
161 ret = codec_dai->dai_ops.set_sysclk(codec_dai, WM8750_SYSCLK, clk,
162 SND_SOC_CLOCK_IN);
163 if (ret < 0)
164 return ret;
165
166 /* set the I2S system clock as input (unused) */
167 ret = cpu_dai->dai_ops.set_sysclk(cpu_dai, PXA2XX_I2S_SYSCLK, 0,
168 SND_SOC_CLOCK_IN);
169 if (ret < 0)
170 return ret;
171
172 return 0;
173}
174
175static struct snd_soc_ops spitz_ops = {
176 .startup = spitz_startup,
177 .hw_params = spitz_hw_params,
178};
179
180static int spitz_get_jack(struct snd_kcontrol *kcontrol,
181 struct snd_ctl_elem_value *ucontrol)
182{
183 ucontrol->value.integer.value[0] = spitz_jack_func;
184 return 0;
185}
186
187static int spitz_set_jack(struct snd_kcontrol *kcontrol,
188 struct snd_ctl_elem_value *ucontrol)
189{
190 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
191
192 if (spitz_jack_func == ucontrol->value.integer.value[0])
193 return 0;
194
195 spitz_jack_func = ucontrol->value.integer.value[0];
196 spitz_ext_control(codec);
197 return 1;
198}
199
200static int spitz_get_spk(struct snd_kcontrol *kcontrol,
201 struct snd_ctl_elem_value *ucontrol)
202{
203 ucontrol->value.integer.value[0] = spitz_spk_func;
204 return 0;
205}
206
207static int spitz_set_spk(struct snd_kcontrol *kcontrol,
208 struct snd_ctl_elem_value *ucontrol)
209{
210 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
211
212 if (spitz_spk_func == ucontrol->value.integer.value[0])
213 return 0;
214
215 spitz_spk_func = ucontrol->value.integer.value[0];
216 spitz_ext_control(codec);
217 return 1;
218}
219
220static int spitz_mic_bias(struct snd_soc_dapm_widget *w, int event)
221{
222 if (machine_is_borzoi() || machine_is_spitz()) {
223 if (SND_SOC_DAPM_EVENT_ON(event))
224 set_scoop_gpio(&spitzscoop2_device.dev,
225 SPITZ_SCP2_MIC_BIAS);
226 else
227 reset_scoop_gpio(&spitzscoop2_device.dev,
228 SPITZ_SCP2_MIC_BIAS);
229 }
230
231 if (machine_is_akita()) {
232 if (SND_SOC_DAPM_EVENT_ON(event))
233 akita_set_ioexp(&akitaioexp_device.dev,
234 AKITA_IOEXP_MIC_BIAS);
235 else
236 akita_reset_ioexp(&akitaioexp_device.dev,
237 AKITA_IOEXP_MIC_BIAS);
238 }
239 return 0;
240}
241
242/* spitz machine dapm widgets */
243static const struct snd_soc_dapm_widget wm8750_dapm_widgets[] = {
244 SND_SOC_DAPM_HP("Headphone Jack", NULL),
245 SND_SOC_DAPM_MIC("Mic Jack", spitz_mic_bias),
246 SND_SOC_DAPM_SPK("Ext Spk", NULL),
247 SND_SOC_DAPM_LINE("Line Jack", NULL),
248
249 /* headset is a mic and mono headphone */
250 SND_SOC_DAPM_HP("Headset Jack", NULL),
251};
252
253/* Spitz machine audio_map */
254static const char *audio_map[][3] = {
255
256 /* headphone connected to LOUT1, ROUT1 */
257 {"Headphone Jack", NULL, "LOUT1"},
258 {"Headphone Jack", NULL, "ROUT1"},
259
260 /* headset connected to ROUT1 and LINPUT1 with bias (def below) */
261 {"Headset Jack", NULL, "ROUT1"},
262
263 /* ext speaker connected to LOUT2, ROUT2 */
264 {"Ext Spk", NULL , "ROUT2"},
265 {"Ext Spk", NULL , "LOUT2"},
266
267 /* mic is connected to input 1 - with bias */
268 {"LINPUT1", NULL, "Mic Bias"},
269 {"Mic Bias", NULL, "Mic Jack"},
270
271 /* line is connected to input 1 - no bias */
272 {"LINPUT1", NULL, "Line Jack"},
273
274 {NULL, NULL, NULL},
275};
276
277static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
278 "Off"};
279static const char *spk_function[] = {"On", "Off"};
280static const struct soc_enum spitz_enum[] = {
281 SOC_ENUM_SINGLE_EXT(5, jack_function),
282 SOC_ENUM_SINGLE_EXT(2, spk_function),
283};
284
285static const struct snd_kcontrol_new wm8750_spitz_controls[] = {
286 SOC_ENUM_EXT("Jack Function", spitz_enum[0], spitz_get_jack,
287 spitz_set_jack),
288 SOC_ENUM_EXT("Speaker Function", spitz_enum[1], spitz_get_spk,
289 spitz_set_spk),
290};
291
292/*
293 * Logic for a wm8750 as connected on a Sharp SL-Cxx00 Device
294 */
295static int spitz_wm8750_init(struct snd_soc_codec *codec)
296{
297 int i, err;
298
299 /* NC codec pins */
300 snd_soc_dapm_set_endpoint(codec, "RINPUT1", 0);
301 snd_soc_dapm_set_endpoint(codec, "LINPUT2", 0);
302 snd_soc_dapm_set_endpoint(codec, "RINPUT2", 0);
303 snd_soc_dapm_set_endpoint(codec, "LINPUT3", 0);
304 snd_soc_dapm_set_endpoint(codec, "RINPUT3", 0);
305 snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
306 snd_soc_dapm_set_endpoint(codec, "MONO", 0);
307
308 /* Add spitz specific controls */
309 for (i = 0; i < ARRAY_SIZE(wm8750_spitz_controls); i++) {
310 err = snd_ctl_add(codec->card,
311 snd_soc_cnew(&wm8750_spitz_controls[i], codec, NULL));
312 if (err < 0)
313 return err;
314 }
315
316 /* Add spitz specific widgets */
317 for (i = 0; i < ARRAY_SIZE(wm8750_dapm_widgets); i++) {
318 snd_soc_dapm_new_control(codec, &wm8750_dapm_widgets[i]);
319 }
320
321 /* Set up spitz specific audio path audio_map */
322 for (i = 0; audio_map[i][0] != NULL; i++) {
323 snd_soc_dapm_connect_input(codec, audio_map[i][0],
324 audio_map[i][1], audio_map[i][2]);
325 }
326
327 snd_soc_dapm_sync_endpoints(codec);
328 return 0;
329}
330
331/* spitz digital audio interface glue - connects codec <--> CPU */
332static struct snd_soc_dai_link spitz_dai = {
333 .name = "wm8750",
334 .stream_name = "WM8750",
335 .cpu_dai = &pxa_i2s_dai,
336 .codec_dai = &wm8750_dai,
337 .init = spitz_wm8750_init,
338 .ops = &spitz_ops,
339};
340
341/* spitz audio machine driver */
342static struct snd_soc_machine snd_soc_machine_spitz = {
343 .name = "Spitz",
344 .dai_link = &spitz_dai,
345 .num_links = 1,
346};
347
348/* spitz audio private data */
349static struct wm8750_setup_data spitz_wm8750_setup = {
350 .i2c_address = 0x1b,
351};
352
353/* spitz audio subsystem */
354static struct snd_soc_device spitz_snd_devdata = {
355 .machine = &snd_soc_machine_spitz,
356 .platform = &pxa2xx_soc_platform,
357 .codec_dev = &soc_codec_dev_wm8750,
358 .codec_data = &spitz_wm8750_setup,
359};
360
361static struct platform_device *spitz_snd_device;
362
363static int __init spitz_init(void)
364{
365 int ret;
366
367 if (!(machine_is_spitz() || machine_is_borzoi() || machine_is_akita()))
368 return -ENODEV;
369
370 spitz_snd_device = platform_device_alloc("soc-audio", -1);
371 if (!spitz_snd_device)
372 return -ENOMEM;
373
374 platform_set_drvdata(spitz_snd_device, &spitz_snd_devdata);
375 spitz_snd_devdata.dev = &spitz_snd_device->dev;
376 ret = platform_device_add(spitz_snd_device);
377
378 if (ret)
379 platform_device_put(spitz_snd_device);
380
381 return ret;
382}
383
384static void __exit spitz_exit(void)
385{
386 platform_device_unregister(spitz_snd_device);
387}
388
389module_init(spitz_init);
390module_exit(spitz_exit);
391
392MODULE_AUTHOR("Richard Purdie");
393MODULE_DESCRIPTION("ALSA SoC Spitz");
394MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
new file mode 100644
index 000000000000..5504e30acf14
--- /dev/null
+++ b/sound/soc/pxa/tosa.c
@@ -0,0 +1,289 @@
1/*
2 * tosa.c -- SoC audio for Tosa
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd.
6 *
7 * Authors: Liam Girdwood <liam.girdwood@wolfsonmicro.com>
8 * Richard Purdie <richard@openedhand.com>
9 *
10 * This program is free software; you can redistribute it and/or modify it
11 * under the terms of the GNU General Public License as published by the
12 * Free Software Foundation; either version 2 of the License, or (at your
13 * option) any later version.
14 *
15 * Revision history
16 * 30th Nov 2005 Initial version.
17 *
18 * GPIO's
19 * 1 - Jack Insertion
20 * 5 - Hookswitch (headset answer/hang up switch)
21 *
22 */
23
24#include <linux/module.h>
25#include <linux/moduleparam.h>
26#include <linux/device.h>
27
28#include <sound/driver.h>
29#include <sound/core.h>
30#include <sound/pcm.h>
31#include <sound/soc.h>
32#include <sound/soc-dapm.h>
33
34#include <asm/mach-types.h>
35#include <asm/hardware/tmio.h>
36#include <asm/arch/pxa-regs.h>
37#include <asm/arch/hardware.h>
38#include <asm/arch/audio.h>
39#include <asm/arch/tosa.h>
40
41#include "../codecs/wm9712.h"
42#include "pxa2xx-pcm.h"
43#include "pxa2xx-ac97.h"
44
45static struct snd_soc_machine tosa;
46
47#define TOSA_HP 0
48#define TOSA_MIC_INT 1
49#define TOSA_HEADSET 2
50#define TOSA_HP_OFF 3
51#define TOSA_SPK_ON 0
52#define TOSA_SPK_OFF 1
53
54static int tosa_jack_func;
55static int tosa_spk_func;
56
57static void tosa_ext_control(struct snd_soc_codec *codec)
58{
59 int spk = 0, mic_int = 0, hp = 0, hs = 0;
60
61 /* set up jack connection */
62 switch (tosa_jack_func) {
63 case TOSA_HP:
64 hp = 1;
65 break;
66 case TOSA_MIC_INT:
67 mic_int = 1;
68 break;
69 case TOSA_HEADSET:
70 hs = 1;
71 break;
72 }
73
74 if (tosa_spk_func == TOSA_SPK_ON)
75 spk = 1;
76
77 snd_soc_dapm_set_endpoint(codec, "Speaker", spk);
78 snd_soc_dapm_set_endpoint(codec, "Mic (Internal)", mic_int);
79 snd_soc_dapm_set_endpoint(codec, "Headphone Jack", hp);
80 snd_soc_dapm_set_endpoint(codec, "Headset Jack", hs);
81 snd_soc_dapm_sync_endpoints(codec);
82}
83
84static int tosa_startup(struct snd_pcm_substream *substream)
85{
86 struct snd_soc_pcm_runtime *rtd = substream->private_data;
87 struct snd_soc_codec *codec = rtd->socdev->codec;
88
89 /* check the jack status at stream startup */
90 tosa_ext_control(codec);
91 return 0;
92}
93
94static struct snd_soc_ops tosa_ops = {
95 .startup = tosa_startup,
96};
97
98static int tosa_get_jack(struct snd_kcontrol *kcontrol,
99 struct snd_ctl_elem_value *ucontrol)
100{
101 ucontrol->value.integer.value[0] = tosa_jack_func;
102 return 0;
103}
104
105static int tosa_set_jack(struct snd_kcontrol *kcontrol,
106 struct snd_ctl_elem_value *ucontrol)
107{
108 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
109
110 if (tosa_jack_func == ucontrol->value.integer.value[0])
111 return 0;
112
113 tosa_jack_func = ucontrol->value.integer.value[0];
114 tosa_ext_control(codec);
115 return 1;
116}
117
118static int tosa_get_spk(struct snd_kcontrol *kcontrol,
119 struct snd_ctl_elem_value *ucontrol)
120{
121 ucontrol->value.integer.value[0] = tosa_spk_func;
122 return 0;
123}
124
125static int tosa_set_spk(struct snd_kcontrol *kcontrol,
126 struct snd_ctl_elem_value *ucontrol)
127{
128 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
129
130 if (tosa_spk_func == ucontrol->value.integer.value[0])
131 return 0;
132
133 tosa_spk_func = ucontrol->value.integer.value[0];
134 tosa_ext_control(codec);
135 return 1;
136}
137
138/* tosa dapm event handlers */
139static int tosa_hp_event(struct snd_soc_dapm_widget *w, int event)
140{
141 if (SND_SOC_DAPM_EVENT_ON(event))
142 set_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
143 else
144 reset_tc6393_gpio(&tc6393_device.dev,TOSA_TC6393_L_MUTE);
145 return 0;
146}
147
148/* tosa machine dapm widgets */
149static const struct snd_soc_dapm_widget tosa_dapm_widgets[] = {
150SND_SOC_DAPM_HP("Headphone Jack", tosa_hp_event),
151SND_SOC_DAPM_HP("Headset Jack", NULL),
152SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
153SND_SOC_DAPM_SPK("Speaker", NULL),
154};
155
156/* tosa audio map */
157static const char *audio_map[][3] = {
158
159 /* headphone connected to HPOUTL, HPOUTR */
160 {"Headphone Jack", NULL, "HPOUTL"},
161 {"Headphone Jack", NULL, "HPOUTR"},
162
163 /* ext speaker connected to LOUT2, ROUT2 */
164 {"Speaker", NULL, "LOUT2"},
165 {"Speaker", NULL, "ROUT2"},
166
167 /* internal mic is connected to mic1, mic2 differential - with bias */
168 {"MIC1", NULL, "Mic Bias"},
169 {"MIC2", NULL, "Mic Bias"},
170 {"Mic Bias", NULL, "Mic (Internal)"},
171
172 /* headset is connected to HPOUTR, and LINEINR with bias */
173 {"Headset Jack", NULL, "HPOUTR"},
174 {"LINEINR", NULL, "Mic Bias"},
175 {"Mic Bias", NULL, "Headset Jack"},
176
177 {NULL, NULL, NULL},
178};
179
180static const char *jack_function[] = {"Headphone", "Mic", "Line", "Headset",
181 "Off"};
182static const char *spk_function[] = {"On", "Off"};
183static const struct soc_enum tosa_enum[] = {
184 SOC_ENUM_SINGLE_EXT(5, jack_function),
185 SOC_ENUM_SINGLE_EXT(2, spk_function),
186};
187
188static const struct snd_kcontrol_new tosa_controls[] = {
189 SOC_ENUM_EXT("Jack Function", tosa_enum[0], tosa_get_jack,
190 tosa_set_jack),
191 SOC_ENUM_EXT("Speaker Function", tosa_enum[1], tosa_get_spk,
192 tosa_set_spk),
193};
194
195static int tosa_ac97_init(struct snd_soc_codec *codec)
196{
197 int i, err;
198
199 snd_soc_dapm_set_endpoint(codec, "OUT3", 0);
200 snd_soc_dapm_set_endpoint(codec, "MONOOUT", 0);
201
202 /* add tosa specific controls */
203 for (i = 0; i < ARRAY_SIZE(tosa_controls); i++) {
204 err = snd_ctl_add(codec->card,
205 snd_soc_cnew(&tosa_controls[i],codec, NULL));
206 if (err < 0)
207 return err;
208 }
209
210 /* add tosa specific widgets */
211 for (i = 0; i < ARRAY_SIZE(tosa_dapm_widgets); i++) {
212 snd_soc_dapm_new_control(codec, &tosa_dapm_widgets[i]);
213 }
214
215 /* set up tosa specific audio path audio_map */
216 for (i = 0; audio_map[i][0] != NULL; i++) {
217 snd_soc_dapm_connect_input(codec, audio_map[i][0],
218 audio_map[i][1], audio_map[i][2]);
219 }
220
221 snd_soc_dapm_sync_endpoints(codec);
222 return 0;
223}
224
225static struct snd_soc_dai_link tosa_dai[] = {
226{
227 .name = "AC97",
228 .stream_name = "AC97 HiFi",
229 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
230 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
231 .init = tosa_ac97_init,
232 .ops = &tosa_ops,
233},
234{
235 .name = "AC97 Aux",
236 .stream_name = "AC97 Aux",
237 .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
238 .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
239 .ops = &tosa_ops,
240},
241};
242
243static struct snd_soc_machine tosa = {
244 .name = "Tosa",
245 .dai_link = tosa_dai,
246 .num_links = ARRAY_SIZE(tosa_dai),
247};
248
249static struct snd_soc_device tosa_snd_devdata = {
250 .machine = &tosa,
251 .platform = &pxa2xx_soc_platform,
252 .codec_dev = &soc_codec_dev_wm9712,
253};
254
255static struct platform_device *tosa_snd_device;
256
257static int __init tosa_init(void)
258{
259 int ret;
260
261 if (!machine_is_tosa())
262 return -ENODEV;
263
264 tosa_snd_device = platform_device_alloc("soc-audio", -1);
265 if (!tosa_snd_device)
266 return -ENOMEM;
267
268 platform_set_drvdata(tosa_snd_device, &tosa_snd_devdata);
269 tosa_snd_devdata.dev = &tosa_snd_device->dev;
270 ret = platform_device_add(tosa_snd_device);
271
272 if (ret)
273 platform_device_put(tosa_snd_device);
274
275 return ret;
276}
277
278static void __exit tosa_exit(void)
279{
280 platform_device_unregister(tosa_snd_device);
281}
282
283module_init(tosa_init);
284module_exit(tosa_exit);
285
286/* Module information */
287MODULE_AUTHOR("Richard Purdie");
288MODULE_DESCRIPTION("ALSA SoC Tosa");
289MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
new file mode 100644
index 000000000000..36519aef55d9
--- /dev/null
+++ b/sound/soc/soc-core.c
@@ -0,0 +1,1587 @@
1/*
2 * soc-core.c -- ALSA SoC Audio Layer
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Copyright 2005 Openedhand Ltd.
6 *
7 * Author: Liam Girdwood
8 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
9 * with code, comments and ideas from :-
10 * Richard Purdie <richard@openedhand.com>
11 *
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the
14 * Free Software Foundation; either version 2 of the License, or (at your
15 * option) any later version.
16 *
17 * Revision history
18 * 12th Aug 2005 Initial version.
19 * 25th Oct 2005 Working Codec, Interface and Platform registration.
20 *
21 * TODO:
22 * o Add hw rules to enforce rates, etc.
23 * o More testing with other codecs/machines.
24 * o Add more codecs and platforms to ensure good API coverage.
25 * o Support TDM on PCM and I2S
26 */
27
28#include <linux/module.h>
29#include <linux/moduleparam.h>
30#include <linux/init.h>
31#include <linux/delay.h>
32#include <linux/pm.h>
33#include <linux/bitops.h>
34#include <linux/platform_device.h>
35#include <sound/driver.h>
36#include <sound/core.h>
37#include <sound/pcm.h>
38#include <sound/pcm_params.h>
39#include <sound/soc.h>
40#include <sound/soc-dapm.h>
41#include <sound/initval.h>
42
43/* debug */
44#define SOC_DEBUG 0
45#if SOC_DEBUG
46#define dbg(format, arg...) printk(format, ## arg)
47#else
48#define dbg(format, arg...)
49#endif
50
51static DEFINE_MUTEX(pcm_mutex);
52static DEFINE_MUTEX(io_mutex);
53static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
54
55/*
56 * This is a timeout to do a DAPM powerdown after a stream is closed().
57 * It can be used to eliminate pops between different playback streams, e.g.
58 * between two audio tracks.
59 */
60static int pmdown_time = 5000;
61module_param(pmdown_time, int, 0);
62MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)");
63
64/*
65 * This function forces any delayed work to be queued and run.
66 */
67static int run_delayed_work(struct delayed_work *dwork)
68{
69 int ret;
70
71 /* cancel any work waiting to be queued. */
72 ret = cancel_delayed_work(dwork);
73
74 /* if there was any work waiting then we run it now and
75 * wait for it's completion */
76 if (ret) {
77 schedule_delayed_work(dwork, 0);
78 flush_scheduled_work();
79 }
80 return ret;
81}
82
83#ifdef CONFIG_SND_SOC_AC97_BUS
84/* unregister ac97 codec */
85static int soc_ac97_dev_unregister(struct snd_soc_codec *codec)
86{
87 if (codec->ac97->dev.bus)
88 device_unregister(&codec->ac97->dev);
89 return 0;
90}
91
92/* stop no dev release warning */
93static void soc_ac97_device_release(struct device *dev){}
94
95/* register ac97 codec to bus */
96static int soc_ac97_dev_register(struct snd_soc_codec *codec)
97{
98 int err;
99
100 codec->ac97->dev.bus = &ac97_bus_type;
101 codec->ac97->dev.parent = NULL;
102 codec->ac97->dev.release = soc_ac97_device_release;
103
104 snprintf(codec->ac97->dev.bus_id, BUS_ID_SIZE, "%d-%d:%s",
105 codec->card->number, 0, codec->name);
106 err = device_register(&codec->ac97->dev);
107 if (err < 0) {
108 snd_printk(KERN_ERR "Can't register ac97 bus\n");
109 codec->ac97->dev.bus = NULL;
110 return err;
111 }
112 return 0;
113}
114#endif
115
116static inline const char* get_dai_name(int type)
117{
118 switch(type) {
119 case SND_SOC_DAI_AC97:
120 return "AC97";
121 case SND_SOC_DAI_I2S:
122 return "I2S";
123 case SND_SOC_DAI_PCM:
124 return "PCM";
125 }
126 return NULL;
127}
128
129/*
130 * Called by ALSA when a PCM substream is opened, the runtime->hw record is
131 * then initialized and any private data can be allocated. This also calls
132 * startup for the cpu DAI, platform, machine and codec DAI.
133 */
134static int soc_pcm_open(struct snd_pcm_substream *substream)
135{
136 struct snd_soc_pcm_runtime *rtd = substream->private_data;
137 struct snd_soc_device *socdev = rtd->socdev;
138 struct snd_pcm_runtime *runtime = substream->runtime;
139 struct snd_soc_dai_link *machine = rtd->dai;
140 struct snd_soc_platform *platform = socdev->platform;
141 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
142 struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
143 int ret = 0;
144
145 mutex_lock(&pcm_mutex);
146
147 /* startup the audio subsystem */
148 if (cpu_dai->ops.startup) {
149 ret = cpu_dai->ops.startup(substream);
150 if (ret < 0) {
151 printk(KERN_ERR "asoc: can't open interface %s\n",
152 cpu_dai->name);
153 goto out;
154 }
155 }
156
157 if (platform->pcm_ops->open) {
158 ret = platform->pcm_ops->open(substream);
159 if (ret < 0) {
160 printk(KERN_ERR "asoc: can't open platform %s\n", platform->name);
161 goto platform_err;
162 }
163 }
164
165 if (codec_dai->ops.startup) {
166 ret = codec_dai->ops.startup(substream);
167 if (ret < 0) {
168 printk(KERN_ERR "asoc: can't open codec %s\n",
169 codec_dai->name);
170 goto codec_dai_err;
171 }
172 }
173
174 if (machine->ops && machine->ops->startup) {
175 ret = machine->ops->startup(substream);
176 if (ret < 0) {
177 printk(KERN_ERR "asoc: %s startup failed\n", machine->name);
178 goto machine_err;
179 }
180 }
181
182 /* Check that the codec and cpu DAI's are compatible */
183 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
184 runtime->hw.rate_min =
185 max(codec_dai->playback.rate_min, cpu_dai->playback.rate_min);
186 runtime->hw.rate_max =
187 min(codec_dai->playback.rate_max, cpu_dai->playback.rate_max);
188 runtime->hw.channels_min =
189 max(codec_dai->playback.channels_min,
190 cpu_dai->playback.channels_min);
191 runtime->hw.channels_max =
192 min(codec_dai->playback.channels_max,
193 cpu_dai->playback.channels_max);
194 runtime->hw.formats =
195 codec_dai->playback.formats & cpu_dai->playback.formats;
196 runtime->hw.rates =
197 codec_dai->playback.rates & cpu_dai->playback.rates;
198 } else {
199 runtime->hw.rate_min =
200 max(codec_dai->capture.rate_min, cpu_dai->capture.rate_min);
201 runtime->hw.rate_max =
202 min(codec_dai->capture.rate_max, cpu_dai->capture.rate_max);
203 runtime->hw.channels_min =
204 max(codec_dai->capture.channels_min,
205 cpu_dai->capture.channels_min);
206 runtime->hw.channels_max =
207 min(codec_dai->capture.channels_max,
208 cpu_dai->capture.channels_max);
209 runtime->hw.formats =
210 codec_dai->capture.formats & cpu_dai->capture.formats;
211 runtime->hw.rates =
212 codec_dai->capture.rates & cpu_dai->capture.rates;
213 }
214
215 snd_pcm_limit_hw_rates(runtime);
216 if (!runtime->hw.rates) {
217 printk(KERN_ERR "asoc: %s <-> %s No matching rates\n",
218 codec_dai->name, cpu_dai->name);
219 goto machine_err;
220 }
221 if (!runtime->hw.formats) {
222 printk(KERN_ERR "asoc: %s <-> %s No matching formats\n",
223 codec_dai->name, cpu_dai->name);
224 goto machine_err;
225 }
226 if (!runtime->hw.channels_min || !runtime->hw.channels_max) {
227 printk(KERN_ERR "asoc: %s <-> %s No matching channels\n",
228 codec_dai->name, cpu_dai->name);
229 goto machine_err;
230 }
231
232 dbg("asoc: %s <-> %s info:\n",codec_dai->name, cpu_dai->name);
233 dbg("asoc: rate mask 0x%x\n", runtime->hw.rates);
234 dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
235 runtime->hw.channels_max);
236 dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
237 runtime->hw.rate_max);
238
239 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
240 cpu_dai->playback.active = codec_dai->playback.active = 1;
241 else
242 cpu_dai->capture.active = codec_dai->capture.active = 1;
243 cpu_dai->active = codec_dai->active = 1;
244 cpu_dai->runtime = runtime;
245 socdev->codec->active++;
246 mutex_unlock(&pcm_mutex);
247 return 0;
248
249machine_err:
250 if (machine->ops && machine->ops->shutdown)
251 machine->ops->shutdown(substream);
252
253codec_dai_err:
254 if (platform->pcm_ops->close)
255 platform->pcm_ops->close(substream);
256
257platform_err:
258 if (cpu_dai->ops.shutdown)
259 cpu_dai->ops.shutdown(substream);
260out:
261 mutex_unlock(&pcm_mutex);
262 return ret;
263}
264
265/*
266 * Power down the audio subsytem pmdown_time msecs after close is called.
267 * This is to ensure there are no pops or clicks in between any music tracks
268 * due to DAPM power cycling.
269 */
270static void close_delayed_work(struct work_struct *work)
271{
272 struct snd_soc_device *socdev =
273 container_of(work, struct snd_soc_device, delayed_work.work);
274 struct snd_soc_codec *codec = socdev->codec;
275 struct snd_soc_codec_dai *codec_dai;
276 int i;
277
278 mutex_lock(&pcm_mutex);
279 for(i = 0; i < codec->num_dai; i++) {
280 codec_dai = &codec->dai[i];
281
282 dbg("pop wq checking: %s status: %s waiting: %s\n",
283 codec_dai->playback.stream_name,
284 codec_dai->playback.active ? "active" : "inactive",
285 codec_dai->pop_wait ? "yes" : "no");
286
287 /* are we waiting on this codec DAI stream */
288 if (codec_dai->pop_wait == 1) {
289
290 codec_dai->pop_wait = 0;
291 snd_soc_dapm_stream_event(codec, codec_dai->playback.stream_name,
292 SND_SOC_DAPM_STREAM_STOP);
293
294 /* power down the codec power domain if no longer active */
295 if (codec->active == 0) {
296 dbg("pop wq D3 %s %s\n", codec->name,
297 codec_dai->playback.stream_name);
298 if (codec->dapm_event)
299 codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot);
300 }
301 }
302 }
303 mutex_unlock(&pcm_mutex);
304}
305
306/*
307 * Called by ALSA when a PCM substream is closed. Private data can be
308 * freed here. The cpu DAI, codec DAI, machine and platform are also
309 * shutdown.
310 */
311static int soc_codec_close(struct snd_pcm_substream *substream)
312{
313 struct snd_soc_pcm_runtime *rtd = substream->private_data;
314 struct snd_soc_device *socdev = rtd->socdev;
315 struct snd_soc_dai_link *machine = rtd->dai;
316 struct snd_soc_platform *platform = socdev->platform;
317 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
318 struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
319 struct snd_soc_codec *codec = socdev->codec;
320
321 mutex_lock(&pcm_mutex);
322
323 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
324 cpu_dai->playback.active = codec_dai->playback.active = 0;
325 else
326 cpu_dai->capture.active = codec_dai->capture.active = 0;
327
328 if (codec_dai->playback.active == 0 &&
329 codec_dai->capture.active == 0) {
330 cpu_dai->active = codec_dai->active = 0;
331 }
332 codec->active--;
333
334 if (cpu_dai->ops.shutdown)
335 cpu_dai->ops.shutdown(substream);
336
337 if (codec_dai->ops.shutdown)
338 codec_dai->ops.shutdown(substream);
339
340 if (machine->ops && machine->ops->shutdown)
341 machine->ops->shutdown(substream);
342
343 if (platform->pcm_ops->close)
344 platform->pcm_ops->close(substream);
345 cpu_dai->runtime = NULL;
346
347 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
348 /* start delayed pop wq here for playback streams */
349 codec_dai->pop_wait = 1;
350 schedule_delayed_work(&socdev->delayed_work,
351 msecs_to_jiffies(pmdown_time));
352 } else {
353 /* capture streams can be powered down now */
354 snd_soc_dapm_stream_event(codec,
355 codec_dai->capture.stream_name, SND_SOC_DAPM_STREAM_STOP);
356
357 if (codec->active == 0 && codec_dai->pop_wait == 0){
358 if (codec->dapm_event)
359 codec->dapm_event(codec, SNDRV_CTL_POWER_D3hot);
360 }
361 }
362
363 mutex_unlock(&pcm_mutex);
364 return 0;
365}
366
367/*
368 * Called by ALSA when the PCM substream is prepared, can set format, sample
369 * rate, etc. This function is non atomic and can be called multiple times,
370 * it can refer to the runtime info.
371 */
372static int soc_pcm_prepare(struct snd_pcm_substream *substream)
373{
374 struct snd_soc_pcm_runtime *rtd = substream->private_data;
375 struct snd_soc_device *socdev = rtd->socdev;
376 struct snd_soc_dai_link *machine = rtd->dai;
377 struct snd_soc_platform *platform = socdev->platform;
378 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
379 struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
380 struct snd_soc_codec *codec = socdev->codec;
381 int ret = 0;
382
383 mutex_lock(&pcm_mutex);
384
385 if (machine->ops && machine->ops->prepare) {
386 ret = machine->ops->prepare(substream);
387 if (ret < 0) {
388 printk(KERN_ERR "asoc: machine prepare error\n");
389 goto out;
390 }
391 }
392
393 if (platform->pcm_ops->prepare) {
394 ret = platform->pcm_ops->prepare(substream);
395 if (ret < 0) {
396 printk(KERN_ERR "asoc: platform prepare error\n");
397 goto out;
398 }
399 }
400
401 if (codec_dai->ops.prepare) {
402 ret = codec_dai->ops.prepare(substream);
403 if (ret < 0) {
404 printk(KERN_ERR "asoc: codec DAI prepare error\n");
405 goto out;
406 }
407 }
408
409 if (cpu_dai->ops.prepare) {
410 ret = cpu_dai->ops.prepare(substream);
411 if (ret < 0) {
412 printk(KERN_ERR "asoc: cpu DAI prepare error\n");
413 goto out;
414 }
415 }
416
417 /* we only want to start a DAPM playback stream if we are not waiting
418 * on an existing one stopping */
419 if (codec_dai->pop_wait) {
420 /* we are waiting for the delayed work to start */
421 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
422 snd_soc_dapm_stream_event(socdev->codec,
423 codec_dai->capture.stream_name,
424 SND_SOC_DAPM_STREAM_START);
425 else {
426 codec_dai->pop_wait = 0;
427 cancel_delayed_work(&socdev->delayed_work);
428 if (codec_dai->dai_ops.digital_mute)
429 codec_dai->dai_ops.digital_mute(codec_dai, 0);
430 }
431 } else {
432 /* no delayed work - do we need to power up codec */
433 if (codec->dapm_state != SNDRV_CTL_POWER_D0) {
434
435 if (codec->dapm_event)
436 codec->dapm_event(codec, SNDRV_CTL_POWER_D1);
437
438 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
439 snd_soc_dapm_stream_event(codec,
440 codec_dai->playback.stream_name,
441 SND_SOC_DAPM_STREAM_START);
442 else
443 snd_soc_dapm_stream_event(codec,
444 codec_dai->capture.stream_name,
445 SND_SOC_DAPM_STREAM_START);
446
447 if (codec->dapm_event)
448 codec->dapm_event(codec, SNDRV_CTL_POWER_D0);
449 if (codec_dai->dai_ops.digital_mute)
450 codec_dai->dai_ops.digital_mute(codec_dai, 0);
451
452 } else {
453 /* codec already powered - power on widgets */
454 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
455 snd_soc_dapm_stream_event(codec,
456 codec_dai->playback.stream_name,
457 SND_SOC_DAPM_STREAM_START);
458 else
459 snd_soc_dapm_stream_event(codec,
460 codec_dai->capture.stream_name,
461 SND_SOC_DAPM_STREAM_START);
462 if (codec_dai->dai_ops.digital_mute)
463 codec_dai->dai_ops.digital_mute(codec_dai, 0);
464 }
465 }
466
467out:
468 mutex_unlock(&pcm_mutex);
469 return ret;
470}
471
472/*
473 * Called by ALSA when the hardware params are set by application. This
474 * function can also be called multiple times and can allocate buffers
475 * (using snd_pcm_lib_* ). It's non-atomic.
476 */
477static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
478 struct snd_pcm_hw_params *params)
479{
480 struct snd_soc_pcm_runtime *rtd = substream->private_data;
481 struct snd_soc_device *socdev = rtd->socdev;
482 struct snd_soc_dai_link *machine = rtd->dai;
483 struct snd_soc_platform *platform = socdev->platform;
484 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
485 struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
486 int ret = 0;
487
488 mutex_lock(&pcm_mutex);
489
490 if (machine->ops && machine->ops->hw_params) {
491 ret = machine->ops->hw_params(substream, params);
492 if (ret < 0) {
493 printk(KERN_ERR "asoc: machine hw_params failed\n");
494 goto out;
495 }
496 }
497
498 if (codec_dai->ops.hw_params) {
499 ret = codec_dai->ops.hw_params(substream, params);
500 if (ret < 0) {
501 printk(KERN_ERR "asoc: can't set codec %s hw params\n",
502 codec_dai->name);
503 goto codec_err;
504 }
505 }
506
507 if (cpu_dai->ops.hw_params) {
508 ret = cpu_dai->ops.hw_params(substream, params);
509 if (ret < 0) {
510 printk(KERN_ERR "asoc: can't set interface %s hw params\n",
511 cpu_dai->name);
512 goto interface_err;
513 }
514 }
515
516 if (platform->pcm_ops->hw_params) {
517 ret = platform->pcm_ops->hw_params(substream, params);
518 if (ret < 0) {
519 printk(KERN_ERR "asoc: can't set platform %s hw params\n",
520 platform->name);
521 goto platform_err;
522 }
523 }
524
525out:
526 mutex_unlock(&pcm_mutex);
527 return ret;
528
529platform_err:
530 if (cpu_dai->ops.hw_free)
531 cpu_dai->ops.hw_free(substream);
532
533interface_err:
534 if (codec_dai->ops.hw_free)
535 codec_dai->ops.hw_free(substream);
536
537codec_err:
538 if(machine->ops && machine->ops->hw_free)
539 machine->ops->hw_free(substream);
540
541 mutex_unlock(&pcm_mutex);
542 return ret;
543}
544
545/*
546 * Free's resources allocated by hw_params, can be called multiple times
547 */
548static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
549{
550 struct snd_soc_pcm_runtime *rtd = substream->private_data;
551 struct snd_soc_device *socdev = rtd->socdev;
552 struct snd_soc_dai_link *machine = rtd->dai;
553 struct snd_soc_platform *platform = socdev->platform;
554 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
555 struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
556 struct snd_soc_codec *codec = socdev->codec;
557
558 mutex_lock(&pcm_mutex);
559
560 /* apply codec digital mute */
561 if (!codec->active && codec_dai->dai_ops.digital_mute)
562 codec_dai->dai_ops.digital_mute(codec_dai, 1);
563
564 /* free any machine hw params */
565 if (machine->ops && machine->ops->hw_free)
566 machine->ops->hw_free(substream);
567
568 /* free any DMA resources */
569 if (platform->pcm_ops->hw_free)
570 platform->pcm_ops->hw_free(substream);
571
572 /* now free hw params for the DAI's */
573 if (codec_dai->ops.hw_free)
574 codec_dai->ops.hw_free(substream);
575
576 if (cpu_dai->ops.hw_free)
577 cpu_dai->ops.hw_free(substream);
578
579 mutex_unlock(&pcm_mutex);
580 return 0;
581}
582
583static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
584{
585 struct snd_soc_pcm_runtime *rtd = substream->private_data;
586 struct snd_soc_device *socdev = rtd->socdev;
587 struct snd_soc_dai_link *machine = rtd->dai;
588 struct snd_soc_platform *platform = socdev->platform;
589 struct snd_soc_cpu_dai *cpu_dai = machine->cpu_dai;
590 struct snd_soc_codec_dai *codec_dai = machine->codec_dai;
591 int ret;
592
593 if (codec_dai->ops.trigger) {
594 ret = codec_dai->ops.trigger(substream, cmd);
595 if (ret < 0)
596 return ret;
597 }
598
599 if (platform->pcm_ops->trigger) {
600 ret = platform->pcm_ops->trigger(substream, cmd);
601 if (ret < 0)
602 return ret;
603 }
604
605 if (cpu_dai->ops.trigger) {
606 ret = cpu_dai->ops.trigger(substream, cmd);
607 if (ret < 0)
608 return ret;
609 }
610 return 0;
611}
612
613/* ASoC PCM operations */
614static struct snd_pcm_ops soc_pcm_ops = {
615 .open = soc_pcm_open,
616 .close = soc_codec_close,
617 .hw_params = soc_pcm_hw_params,
618 .hw_free = soc_pcm_hw_free,
619 .prepare = soc_pcm_prepare,
620 .trigger = soc_pcm_trigger,
621};
622
623#ifdef CONFIG_PM
624/* powers down audio subsystem for suspend */
625static int soc_suspend(struct platform_device *pdev, pm_message_t state)
626{
627 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
628 struct snd_soc_machine *machine = socdev->machine;
629 struct snd_soc_platform *platform = socdev->platform;
630 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
631 struct snd_soc_codec *codec = socdev->codec;
632 int i;
633
634 /* mute any active DAC's */
635 for(i = 0; i < machine->num_links; i++) {
636 struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
637 if (dai->dai_ops.digital_mute && dai->playback.active)
638 dai->dai_ops.digital_mute(dai, 1);
639 }
640
641 if (machine->suspend_pre)
642 machine->suspend_pre(pdev, state);
643
644 for(i = 0; i < machine->num_links; i++) {
645 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
646 if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97)
647 cpu_dai->suspend(pdev, cpu_dai);
648 if (platform->suspend)
649 platform->suspend(pdev, cpu_dai);
650 }
651
652 /* close any waiting streams and save state */
653 run_delayed_work(&socdev->delayed_work);
654 codec->suspend_dapm_state = codec->dapm_state;
655
656 for(i = 0; i < codec->num_dai; i++) {
657 char *stream = codec->dai[i].playback.stream_name;
658 if (stream != NULL)
659 snd_soc_dapm_stream_event(codec, stream,
660 SND_SOC_DAPM_STREAM_SUSPEND);
661 stream = codec->dai[i].capture.stream_name;
662 if (stream != NULL)
663 snd_soc_dapm_stream_event(codec, stream,
664 SND_SOC_DAPM_STREAM_SUSPEND);
665 }
666
667 if (codec_dev->suspend)
668 codec_dev->suspend(pdev, state);
669
670 for(i = 0; i < machine->num_links; i++) {
671 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
672 if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97)
673 cpu_dai->suspend(pdev, cpu_dai);
674 }
675
676 if (machine->suspend_post)
677 machine->suspend_post(pdev, state);
678
679 return 0;
680}
681
682/* powers up audio subsystem after a suspend */
683static int soc_resume(struct platform_device *pdev)
684{
685 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
686 struct snd_soc_machine *machine = socdev->machine;
687 struct snd_soc_platform *platform = socdev->platform;
688 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
689 struct snd_soc_codec *codec = socdev->codec;
690 int i;
691
692 if (machine->resume_pre)
693 machine->resume_pre(pdev);
694
695 for(i = 0; i < machine->num_links; i++) {
696 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
697 if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97)
698 cpu_dai->resume(pdev, cpu_dai);
699 }
700
701 if (codec_dev->resume)
702 codec_dev->resume(pdev);
703
704 for(i = 0; i < codec->num_dai; i++) {
705 char* stream = codec->dai[i].playback.stream_name;
706 if (stream != NULL)
707 snd_soc_dapm_stream_event(codec, stream,
708 SND_SOC_DAPM_STREAM_RESUME);
709 stream = codec->dai[i].capture.stream_name;
710 if (stream != NULL)
711 snd_soc_dapm_stream_event(codec, stream,
712 SND_SOC_DAPM_STREAM_RESUME);
713 }
714
715 /* unmute any active DAC's */
716 for(i = 0; i < machine->num_links; i++) {
717 struct snd_soc_codec_dai *dai = machine->dai_link[i].codec_dai;
718 if (dai->dai_ops.digital_mute && dai->playback.active)
719 dai->dai_ops.digital_mute(dai, 0);
720 }
721
722 for(i = 0; i < machine->num_links; i++) {
723 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
724 if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97)
725 cpu_dai->resume(pdev, cpu_dai);
726 if (platform->resume)
727 platform->resume(pdev, cpu_dai);
728 }
729
730 if (machine->resume_post)
731 machine->resume_post(pdev);
732
733 return 0;
734}
735
736#else
737#define soc_suspend NULL
738#define soc_resume NULL
739#endif
740
741/* probes a new socdev */
742static int soc_probe(struct platform_device *pdev)
743{
744 int ret = 0, i;
745 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
746 struct snd_soc_machine *machine = socdev->machine;
747 struct snd_soc_platform *platform = socdev->platform;
748 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
749
750 if (machine->probe) {
751 ret = machine->probe(pdev);
752 if(ret < 0)
753 return ret;
754 }
755
756 for (i = 0; i < machine->num_links; i++) {
757 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
758 if (cpu_dai->probe) {
759 ret = cpu_dai->probe(pdev);
760 if(ret < 0)
761 goto cpu_dai_err;
762 }
763 }
764
765 if (codec_dev->probe) {
766 ret = codec_dev->probe(pdev);
767 if(ret < 0)
768 goto cpu_dai_err;
769 }
770
771 if (platform->probe) {
772 ret = platform->probe(pdev);
773 if(ret < 0)
774 goto platform_err;
775 }
776
777 /* DAPM stream work */
778 INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
779 return 0;
780
781platform_err:
782 if (codec_dev->remove)
783 codec_dev->remove(pdev);
784
785cpu_dai_err:
786 for (i--; i >= 0; i--) {
787 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
788 if (cpu_dai->remove)
789 cpu_dai->remove(pdev);
790 }
791
792 if (machine->remove)
793 machine->remove(pdev);
794
795 return ret;
796}
797
798/* removes a socdev */
799static int soc_remove(struct platform_device *pdev)
800{
801 int i;
802 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
803 struct snd_soc_machine *machine = socdev->machine;
804 struct snd_soc_platform *platform = socdev->platform;
805 struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
806
807 run_delayed_work(&socdev->delayed_work);
808
809 if (platform->remove)
810 platform->remove(pdev);
811
812 if (codec_dev->remove)
813 codec_dev->remove(pdev);
814
815 for (i = 0; i < machine->num_links; i++) {
816 struct snd_soc_cpu_dai *cpu_dai = machine->dai_link[i].cpu_dai;
817 if (cpu_dai->remove)
818 cpu_dai->remove(pdev);
819 }
820
821 if (machine->remove)
822 machine->remove(pdev);
823
824 return 0;
825}
826
827/* ASoC platform driver */
828static struct platform_driver soc_driver = {
829 .driver = {
830 .name = "soc-audio",
831 },
832 .probe = soc_probe,
833 .remove = soc_remove,
834 .suspend = soc_suspend,
835 .resume = soc_resume,
836};
837
838/* create a new pcm */
839static int soc_new_pcm(struct snd_soc_device *socdev,
840 struct snd_soc_dai_link *dai_link, int num)
841{
842 struct snd_soc_codec *codec = socdev->codec;
843 struct snd_soc_codec_dai *codec_dai = dai_link->codec_dai;
844 struct snd_soc_cpu_dai *cpu_dai = dai_link->cpu_dai;
845 struct snd_soc_pcm_runtime *rtd;
846 struct snd_pcm *pcm;
847 char new_name[64];
848 int ret = 0, playback = 0, capture = 0;
849
850 rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime), GFP_KERNEL);
851 if (rtd == NULL)
852 return -ENOMEM;
853
854 rtd->dai = dai_link;
855 rtd->socdev = socdev;
856 codec_dai->codec = socdev->codec;
857
858 /* check client and interface hw capabilities */
859 sprintf(new_name, "%s %s-%s-%d",dai_link->stream_name, codec_dai->name,
860 get_dai_name(cpu_dai->type), num);
861
862 if (codec_dai->playback.channels_min)
863 playback = 1;
864 if (codec_dai->capture.channels_min)
865 capture = 1;
866
867 ret = snd_pcm_new(codec->card, new_name, codec->pcm_devs++, playback,
868 capture, &pcm);
869 if (ret < 0) {
870 printk(KERN_ERR "asoc: can't create pcm for codec %s\n", codec->name);
871 kfree(rtd);
872 return ret;
873 }
874
875 pcm->private_data = rtd;
876 soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap;
877 soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer;
878 soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl;
879 soc_pcm_ops.copy = socdev->platform->pcm_ops->copy;
880 soc_pcm_ops.silence = socdev->platform->pcm_ops->silence;
881 soc_pcm_ops.ack = socdev->platform->pcm_ops->ack;
882 soc_pcm_ops.page = socdev->platform->pcm_ops->page;
883
884 if (playback)
885 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
886
887 if (capture)
888 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
889
890 ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm);
891 if (ret < 0) {
892 printk(KERN_ERR "asoc: platform pcm constructor failed\n");
893 kfree(rtd);
894 return ret;
895 }
896
897 pcm->private_free = socdev->platform->pcm_free;
898 printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
899 cpu_dai->name);
900 return ret;
901}
902
903/* codec register dump */
904static ssize_t codec_reg_show(struct device *dev,
905 struct device_attribute *attr, char *buf)
906{
907 struct snd_soc_device *devdata = dev_get_drvdata(dev);
908 struct snd_soc_codec *codec = devdata->codec;
909 int i, step = 1, count = 0;
910
911 if (!codec->reg_cache_size)
912 return 0;
913
914 if (codec->reg_cache_step)
915 step = codec->reg_cache_step;
916
917 count += sprintf(buf, "%s registers\n", codec->name);
918 for(i = 0; i < codec->reg_cache_size; i += step)
919 count += sprintf(buf + count, "%2x: %4x\n", i, codec->read(codec, i));
920
921 return count;
922}
923static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
924
925/**
926 * snd_soc_new_ac97_codec - initailise AC97 device
927 * @codec: audio codec
928 * @ops: AC97 bus operations
929 * @num: AC97 codec number
930 *
931 * Initialises AC97 codec resources for use by ad-hoc devices only.
932 */
933int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
934 struct snd_ac97_bus_ops *ops, int num)
935{
936 mutex_lock(&codec->mutex);
937
938 codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL);
939 if (codec->ac97 == NULL) {
940 mutex_unlock(&codec->mutex);
941 return -ENOMEM;
942 }
943
944 codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL);
945 if (codec->ac97->bus == NULL) {
946 kfree(codec->ac97);
947 codec->ac97 = NULL;
948 mutex_unlock(&codec->mutex);
949 return -ENOMEM;
950 }
951
952 codec->ac97->bus->ops = ops;
953 codec->ac97->num = num;
954 mutex_unlock(&codec->mutex);
955 return 0;
956}
957EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec);
958
959/**
960 * snd_soc_free_ac97_codec - free AC97 codec device
961 * @codec: audio codec
962 *
963 * Frees AC97 codec device resources.
964 */
965void snd_soc_free_ac97_codec(struct snd_soc_codec *codec)
966{
967 mutex_lock(&codec->mutex);
968 kfree(codec->ac97->bus);
969 kfree(codec->ac97);
970 codec->ac97 = NULL;
971 mutex_unlock(&codec->mutex);
972}
973EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec);
974
975/**
976 * snd_soc_update_bits - update codec register bits
977 * @codec: audio codec
978 * @reg: codec register
979 * @mask: register mask
980 * @value: new value
981 *
982 * Writes new register value.
983 *
984 * Returns 1 for change else 0.
985 */
986int snd_soc_update_bits(struct snd_soc_codec *codec, unsigned short reg,
987 unsigned short mask, unsigned short value)
988{
989 int change;
990 unsigned short old, new;
991
992 mutex_lock(&io_mutex);
993 old = snd_soc_read(codec, reg);
994 new = (old & ~mask) | value;
995 change = old != new;
996 if (change)
997 snd_soc_write(codec, reg, new);
998
999 mutex_unlock(&io_mutex);
1000 return change;
1001}
1002EXPORT_SYMBOL_GPL(snd_soc_update_bits);
1003
1004/**
1005 * snd_soc_test_bits - test register for change
1006 * @codec: audio codec
1007 * @reg: codec register
1008 * @mask: register mask
1009 * @value: new value
1010 *
1011 * Tests a register with a new value and checks if the new value is
1012 * different from the old value.
1013 *
1014 * Returns 1 for change else 0.
1015 */
1016int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned short reg,
1017 unsigned short mask, unsigned short value)
1018{
1019 int change;
1020 unsigned short old, new;
1021
1022 mutex_lock(&io_mutex);
1023 old = snd_soc_read(codec, reg);
1024 new = (old & ~mask) | value;
1025 change = old != new;
1026 mutex_unlock(&io_mutex);
1027
1028 return change;
1029}
1030EXPORT_SYMBOL_GPL(snd_soc_test_bits);
1031
1032/**
1033 * snd_soc_new_pcms - create new sound card and pcms
1034 * @socdev: the SoC audio device
1035 *
1036 * Create a new sound card based upon the codec and interface pcms.
1037 *
1038 * Returns 0 for success, else error.
1039 */
1040int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
1041{
1042 struct snd_soc_codec *codec = socdev->codec;
1043 struct snd_soc_machine *machine = socdev->machine;
1044 int ret = 0, i;
1045
1046 mutex_lock(&codec->mutex);
1047
1048 /* register a sound card */
1049 codec->card = snd_card_new(idx, xid, codec->owner, 0);
1050 if (!codec->card) {
1051 printk(KERN_ERR "asoc: can't create sound card for codec %s\n",
1052 codec->name);
1053 mutex_unlock(&codec->mutex);
1054 return -ENODEV;
1055 }
1056
1057 codec->card->dev = socdev->dev;
1058 codec->card->private_data = codec;
1059 strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
1060
1061 /* create the pcms */
1062 for(i = 0; i < machine->num_links; i++) {
1063 ret = soc_new_pcm(socdev, &machine->dai_link[i], i);
1064 if (ret < 0) {
1065 printk(KERN_ERR "asoc: can't create pcm %s\n",
1066 machine->dai_link[i].stream_name);
1067 mutex_unlock(&codec->mutex);
1068 return ret;
1069 }
1070 }
1071
1072 mutex_unlock(&codec->mutex);
1073 return ret;
1074}
1075EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
1076
1077/**
1078 * snd_soc_register_card - register sound card
1079 * @socdev: the SoC audio device
1080 *
1081 * Register a SoC sound card. Also registers an AC97 device if the
1082 * codec is AC97 for ad hoc devices.
1083 *
1084 * Returns 0 for success, else error.
1085 */
1086int snd_soc_register_card(struct snd_soc_device *socdev)
1087{
1088 struct snd_soc_codec *codec = socdev->codec;
1089 struct snd_soc_machine *machine = socdev->machine;
1090 int ret = 0, i, ac97 = 0, err = 0;
1091
1092 mutex_lock(&codec->mutex);
1093 for(i = 0; i < machine->num_links; i++) {
1094 if (socdev->machine->dai_link[i].init) {
1095 err = socdev->machine->dai_link[i].init(codec);
1096 if (err < 0) {
1097 printk(KERN_ERR "asoc: failed to init %s\n",
1098 socdev->machine->dai_link[i].stream_name);
1099 continue;
1100 }
1101 }
1102 if (socdev->machine->dai_link[i].cpu_dai->type == SND_SOC_DAI_AC97)
1103 ac97 = 1;
1104 }
1105 snprintf(codec->card->shortname, sizeof(codec->card->shortname),
1106 "%s", machine->name);
1107 snprintf(codec->card->longname, sizeof(codec->card->longname),
1108 "%s (%s)", machine->name, codec->name);
1109
1110 ret = snd_card_register(codec->card);
1111 if (ret < 0) {
1112 printk(KERN_ERR "asoc: failed to register soundcard for codec %s\n",
1113 codec->name);
1114 goto out;
1115 }
1116
1117#ifdef CONFIG_SND_SOC_AC97_BUS
1118 if (ac97) {
1119 ret = soc_ac97_dev_register(codec);
1120 if (ret < 0) {
1121 printk(KERN_ERR "asoc: AC97 device register failed\n");
1122 snd_card_free(codec->card);
1123 goto out;
1124 }
1125 }
1126#endif
1127
1128 err = snd_soc_dapm_sys_add(socdev->dev);
1129 if (err < 0)
1130 printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n");
1131
1132 err = device_create_file(socdev->dev, &dev_attr_codec_reg);
1133 if (err < 0)
1134 printk(KERN_WARNING "asoc: failed to add codec sysfs entries\n");
1135out:
1136 mutex_unlock(&codec->mutex);
1137 return ret;
1138}
1139EXPORT_SYMBOL_GPL(snd_soc_register_card);
1140
1141/**
1142 * snd_soc_free_pcms - free sound card and pcms
1143 * @socdev: the SoC audio device
1144 *
1145 * Frees sound card and pcms associated with the socdev.
1146 * Also unregister the codec if it is an AC97 device.
1147 */
1148void snd_soc_free_pcms(struct snd_soc_device *socdev)
1149{
1150 struct snd_soc_codec *codec = socdev->codec;
1151
1152 mutex_lock(&codec->mutex);
1153#ifdef CONFIG_SND_SOC_AC97_BUS
1154 if (codec->ac97)
1155 soc_ac97_dev_unregister(codec);
1156#endif
1157
1158 if (codec->card)
1159 snd_card_free(codec->card);
1160 device_remove_file(socdev->dev, &dev_attr_codec_reg);
1161 mutex_unlock(&codec->mutex);
1162}
1163EXPORT_SYMBOL_GPL(snd_soc_free_pcms);
1164
1165/**
1166 * snd_soc_set_runtime_hwparams - set the runtime hardware parameters
1167 * @substream: the pcm substream
1168 * @hw: the hardware parameters
1169 *
1170 * Sets the substream runtime hardware parameters.
1171 */
1172int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
1173 const struct snd_pcm_hardware *hw)
1174{
1175 struct snd_pcm_runtime *runtime = substream->runtime;
1176 runtime->hw.info = hw->info;
1177 runtime->hw.formats = hw->formats;
1178 runtime->hw.period_bytes_min = hw->period_bytes_min;
1179 runtime->hw.period_bytes_max = hw->period_bytes_max;
1180 runtime->hw.periods_min = hw->periods_min;
1181 runtime->hw.periods_max = hw->periods_max;
1182 runtime->hw.buffer_bytes_max = hw->buffer_bytes_max;
1183 runtime->hw.fifo_size = hw->fifo_size;
1184 return 0;
1185}
1186EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams);
1187
1188/**
1189 * snd_soc_cnew - create new control
1190 * @_template: control template
1191 * @data: control private data
1192 * @lnng_name: control long name
1193 *
1194 * Create a new mixer control from a template control.
1195 *
1196 * Returns 0 for success, else error.
1197 */
1198struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template,
1199 void *data, char *long_name)
1200{
1201 struct snd_kcontrol_new template;
1202
1203 memcpy(&template, _template, sizeof(template));
1204 if (long_name)
1205 template.name = long_name;
1206 template.access = SNDRV_CTL_ELEM_ACCESS_READWRITE;
1207 template.index = 0;
1208
1209 return snd_ctl_new1(&template, data);
1210}
1211EXPORT_SYMBOL_GPL(snd_soc_cnew);
1212
1213/**
1214 * snd_soc_info_enum_double - enumerated double mixer info callback
1215 * @kcontrol: mixer control
1216 * @uinfo: control element information
1217 *
1218 * Callback to provide information about a double enumerated
1219 * mixer control.
1220 *
1221 * Returns 0 for success.
1222 */
1223int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol,
1224 struct snd_ctl_elem_info *uinfo)
1225{
1226 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1227
1228 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1229 uinfo->count = e->shift_l == e->shift_r ? 1 : 2;
1230 uinfo->value.enumerated.items = e->mask;
1231
1232 if (uinfo->value.enumerated.item > e->mask - 1)
1233 uinfo->value.enumerated.item = e->mask - 1;
1234 strcpy(uinfo->value.enumerated.name,
1235 e->texts[uinfo->value.enumerated.item]);
1236 return 0;
1237}
1238EXPORT_SYMBOL_GPL(snd_soc_info_enum_double);
1239
1240/**
1241 * snd_soc_get_enum_double - enumerated double mixer get callback
1242 * @kcontrol: mixer control
1243 * @uinfo: control element information
1244 *
1245 * Callback to get the value of a double enumerated mixer.
1246 *
1247 * Returns 0 for success.
1248 */
1249int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol,
1250 struct snd_ctl_elem_value *ucontrol)
1251{
1252 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1253 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1254 unsigned short val, bitmask;
1255
1256 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
1257 ;
1258 val = snd_soc_read(codec, e->reg);
1259 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
1260 if (e->shift_l != e->shift_r)
1261 ucontrol->value.enumerated.item[1] =
1262 (val >> e->shift_r) & (bitmask - 1);
1263
1264 return 0;
1265}
1266EXPORT_SYMBOL_GPL(snd_soc_get_enum_double);
1267
1268/**
1269 * snd_soc_put_enum_double - enumerated double mixer put callback
1270 * @kcontrol: mixer control
1271 * @uinfo: control element information
1272 *
1273 * Callback to set the value of a double enumerated mixer.
1274 *
1275 * Returns 0 for success.
1276 */
1277int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol,
1278 struct snd_ctl_elem_value *ucontrol)
1279{
1280 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1281 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1282 unsigned short val;
1283 unsigned short mask, bitmask;
1284
1285 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
1286 ;
1287 if (ucontrol->value.enumerated.item[0] > e->mask - 1)
1288 return -EINVAL;
1289 val = ucontrol->value.enumerated.item[0] << e->shift_l;
1290 mask = (bitmask - 1) << e->shift_l;
1291 if (e->shift_l != e->shift_r) {
1292 if (ucontrol->value.enumerated.item[1] > e->mask - 1)
1293 return -EINVAL;
1294 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
1295 mask |= (bitmask - 1) << e->shift_r;
1296 }
1297
1298 return snd_soc_update_bits(codec, e->reg, mask, val);
1299}
1300EXPORT_SYMBOL_GPL(snd_soc_put_enum_double);
1301
1302/**
1303 * snd_soc_info_enum_ext - external enumerated single mixer info callback
1304 * @kcontrol: mixer control
1305 * @uinfo: control element information
1306 *
1307 * Callback to provide information about an external enumerated
1308 * single mixer.
1309 *
1310 * Returns 0 for success.
1311 */
1312int snd_soc_info_enum_ext(struct snd_kcontrol *kcontrol,
1313 struct snd_ctl_elem_info *uinfo)
1314{
1315 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1316
1317 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1318 uinfo->count = 1;
1319 uinfo->value.enumerated.items = e->mask;
1320
1321 if (uinfo->value.enumerated.item > e->mask - 1)
1322 uinfo->value.enumerated.item = e->mask - 1;
1323 strcpy(uinfo->value.enumerated.name,
1324 e->texts[uinfo->value.enumerated.item]);
1325 return 0;
1326}
1327EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext);
1328
1329/**
1330 * snd_soc_info_volsw_ext - external single mixer info callback
1331 * @kcontrol: mixer control
1332 * @uinfo: control element information
1333 *
1334 * Callback to provide information about a single external mixer control.
1335 *
1336 * Returns 0 for success.
1337 */
1338int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol,
1339 struct snd_ctl_elem_info *uinfo)
1340{
1341 int mask = kcontrol->private_value;
1342
1343 uinfo->type =
1344 mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1345 uinfo->count = 1;
1346 uinfo->value.integer.min = 0;
1347 uinfo->value.integer.max = mask;
1348 return 0;
1349}
1350EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext);
1351
1352/**
1353 * snd_soc_info_bool_ext - external single boolean mixer info callback
1354 * @kcontrol: mixer control
1355 * @uinfo: control element information
1356 *
1357 * Callback to provide information about a single boolean external mixer control.
1358 *
1359 * Returns 0 for success.
1360 */
1361int snd_soc_info_bool_ext(struct snd_kcontrol *kcontrol,
1362 struct snd_ctl_elem_info *uinfo)
1363{
1364 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1365 uinfo->count = 1;
1366 uinfo->value.integer.min = 0;
1367 uinfo->value.integer.max = 1;
1368 return 0;
1369}
1370EXPORT_SYMBOL_GPL(snd_soc_info_bool_ext);
1371
1372/**
1373 * snd_soc_info_volsw - single mixer info callback
1374 * @kcontrol: mixer control
1375 * @uinfo: control element information
1376 *
1377 * Callback to provide information about a single mixer control.
1378 *
1379 * Returns 0 for success.
1380 */
1381int snd_soc_info_volsw(struct snd_kcontrol *kcontrol,
1382 struct snd_ctl_elem_info *uinfo)
1383{
1384 int mask = (kcontrol->private_value >> 16) & 0xff;
1385 int shift = (kcontrol->private_value >> 8) & 0x0f;
1386 int rshift = (kcontrol->private_value >> 12) & 0x0f;
1387
1388 uinfo->type =
1389 mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1390 uinfo->count = shift == rshift ? 1 : 2;
1391 uinfo->value.integer.min = 0;
1392 uinfo->value.integer.max = mask;
1393 return 0;
1394}
1395EXPORT_SYMBOL_GPL(snd_soc_info_volsw);
1396
1397/**
1398 * snd_soc_get_volsw - single mixer get callback
1399 * @kcontrol: mixer control
1400 * @uinfo: control element information
1401 *
1402 * Callback to get the value of a single mixer control.
1403 *
1404 * Returns 0 for success.
1405 */
1406int snd_soc_get_volsw(struct snd_kcontrol *kcontrol,
1407 struct snd_ctl_elem_value *ucontrol)
1408{
1409 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1410 int reg = kcontrol->private_value & 0xff;
1411 int shift = (kcontrol->private_value >> 8) & 0x0f;
1412 int rshift = (kcontrol->private_value >> 12) & 0x0f;
1413 int mask = (kcontrol->private_value >> 16) & 0xff;
1414 int invert = (kcontrol->private_value >> 24) & 0x01;
1415
1416 ucontrol->value.integer.value[0] =
1417 (snd_soc_read(codec, reg) >> shift) & mask;
1418 if (shift != rshift)
1419 ucontrol->value.integer.value[1] =
1420 (snd_soc_read(codec, reg) >> rshift) & mask;
1421 if (invert) {
1422 ucontrol->value.integer.value[0] =
1423 mask - ucontrol->value.integer.value[0];
1424 if (shift != rshift)
1425 ucontrol->value.integer.value[1] =
1426 mask - ucontrol->value.integer.value[1];
1427 }
1428
1429 return 0;
1430}
1431EXPORT_SYMBOL_GPL(snd_soc_get_volsw);
1432
1433/**
1434 * snd_soc_put_volsw - single mixer put callback
1435 * @kcontrol: mixer control
1436 * @uinfo: control element information
1437 *
1438 * Callback to set the value of a single mixer control.
1439 *
1440 * Returns 0 for success.
1441 */
1442int snd_soc_put_volsw(struct snd_kcontrol *kcontrol,
1443 struct snd_ctl_elem_value *ucontrol)
1444{
1445 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1446 int reg = kcontrol->private_value & 0xff;
1447 int shift = (kcontrol->private_value >> 8) & 0x0f;
1448 int rshift = (kcontrol->private_value >> 12) & 0x0f;
1449 int mask = (kcontrol->private_value >> 16) & 0xff;
1450 int invert = (kcontrol->private_value >> 24) & 0x01;
1451 int err;
1452 unsigned short val, val2, val_mask;
1453
1454 val = (ucontrol->value.integer.value[0] & mask);
1455 if (invert)
1456 val = mask - val;
1457 val_mask = mask << shift;
1458 val = val << shift;
1459 if (shift != rshift) {
1460 val2 = (ucontrol->value.integer.value[1] & mask);
1461 if (invert)
1462 val2 = mask - val2;
1463 val_mask |= mask << rshift;
1464 val |= val2 << rshift;
1465 }
1466 err = snd_soc_update_bits(codec, reg, val_mask, val);
1467 return err;
1468}
1469EXPORT_SYMBOL_GPL(snd_soc_put_volsw);
1470
1471/**
1472 * snd_soc_info_volsw_2r - double mixer info callback
1473 * @kcontrol: mixer control
1474 * @uinfo: control element information
1475 *
1476 * Callback to provide information about a double mixer control that
1477 * spans 2 codec registers.
1478 *
1479 * Returns 0 for success.
1480 */
1481int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol,
1482 struct snd_ctl_elem_info *uinfo)
1483{
1484 int mask = (kcontrol->private_value >> 12) & 0xff;
1485
1486 uinfo->type =
1487 mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1488 uinfo->count = 2;
1489 uinfo->value.integer.min = 0;
1490 uinfo->value.integer.max = mask;
1491 return 0;
1492}
1493EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r);
1494
1495/**
1496 * snd_soc_get_volsw_2r - double mixer get callback
1497 * @kcontrol: mixer control
1498 * @uinfo: control element information
1499 *
1500 * Callback to get the value of a double mixer control that spans 2 registers.
1501 *
1502 * Returns 0 for success.
1503 */
1504int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol,
1505 struct snd_ctl_elem_value *ucontrol)
1506{
1507 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1508 int reg = kcontrol->private_value & 0xff;
1509 int reg2 = (kcontrol->private_value >> 24) & 0xff;
1510 int shift = (kcontrol->private_value >> 8) & 0x0f;
1511 int mask = (kcontrol->private_value >> 12) & 0xff;
1512 int invert = (kcontrol->private_value >> 20) & 0x01;
1513
1514 ucontrol->value.integer.value[0] =
1515 (snd_soc_read(codec, reg) >> shift) & mask;
1516 ucontrol->value.integer.value[1] =
1517 (snd_soc_read(codec, reg2) >> shift) & mask;
1518 if (invert) {
1519 ucontrol->value.integer.value[0] =
1520 mask - ucontrol->value.integer.value[0];
1521 ucontrol->value.integer.value[1] =
1522 mask - ucontrol->value.integer.value[1];
1523 }
1524
1525 return 0;
1526}
1527EXPORT_SYMBOL_GPL(snd_soc_get_volsw_2r);
1528
1529/**
1530 * snd_soc_put_volsw_2r - double mixer set callback
1531 * @kcontrol: mixer control
1532 * @uinfo: control element information
1533 *
1534 * Callback to set the value of a double mixer control that spans 2 registers.
1535 *
1536 * Returns 0 for success.
1537 */
1538int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol,
1539 struct snd_ctl_elem_value *ucontrol)
1540{
1541 struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
1542 int reg = kcontrol->private_value & 0xff;
1543 int reg2 = (kcontrol->private_value >> 24) & 0xff;
1544 int shift = (kcontrol->private_value >> 8) & 0x0f;
1545 int mask = (kcontrol->private_value >> 12) & 0xff;
1546 int invert = (kcontrol->private_value >> 20) & 0x01;
1547 int err;
1548 unsigned short val, val2, val_mask;
1549
1550 val_mask = mask << shift;
1551 val = (ucontrol->value.integer.value[0] & mask);
1552 val2 = (ucontrol->value.integer.value[1] & mask);
1553
1554 if (invert) {
1555 val = mask - val;
1556 val2 = mask - val2;
1557 }
1558
1559 val = val << shift;
1560 val2 = val2 << shift;
1561
1562 if ((err = snd_soc_update_bits(codec, reg, val_mask, val)) < 0)
1563 return err;
1564
1565 err = snd_soc_update_bits(codec, reg2, val_mask, val2);
1566 return err;
1567}
1568EXPORT_SYMBOL_GPL(snd_soc_put_volsw_2r);
1569
1570static int __devinit snd_soc_init(void)
1571{
1572 printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
1573 return platform_driver_register(&soc_driver);
1574}
1575
1576static void snd_soc_exit(void)
1577{
1578 platform_driver_unregister(&soc_driver);
1579}
1580
1581module_init(snd_soc_init);
1582module_exit(snd_soc_exit);
1583
1584/* Module information */
1585MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
1586MODULE_DESCRIPTION("ALSA SoC Core");
1587MODULE_LICENSE("GPL");
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
new file mode 100644
index 000000000000..7caf8c7b0ac5
--- /dev/null
+++ b/sound/soc/soc-dapm.c
@@ -0,0 +1,1323 @@
1/*
2 * soc-dapm.c -- ALSA SoC Dynamic Audio Power Management
3 *
4 * Copyright 2005 Wolfson Microelectronics PLC.
5 * Author: Liam Girdwood
6 * liam.girdwood@wolfsonmicro.com or linux@wolfsonmicro.com
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 *
13 * Revision history
14 * 12th Aug 2005 Initial version.
15 * 25th Oct 2005 Implemented path power domain.
16 * 18th Dec 2005 Implemented machine and stream level power domain.
17 *
18 * Features:
19 * o Changes power status of internal codec blocks depending on the
20 * dynamic configuration of codec internal audio paths and active
21 * DAC's/ADC's.
22 * o Platform power domain - can support external components i.e. amps and
23 * mic/meadphone insertion events.
24 * o Automatic Mic Bias support
25 * o Jack insertion power event initiation - e.g. hp insertion will enable
26 * sinks, dacs, etc
27 * o Delayed powerdown of audio susbsytem to reduce pops between a quick
28 * device reopen.
29 *
30 * Todo:
31 * o DAPM power change sequencing - allow for configurable per
32 * codec sequences.
33 * o Support for analogue bias optimisation.
34 * o Support for reduced codec oversampling rates.
35 * o Support for reduced codec bias currents.
36 */
37
38#include <linux/module.h>
39#include <linux/moduleparam.h>
40#include <linux/init.h>
41#include <linux/delay.h>
42#include <linux/pm.h>
43#include <linux/bitops.h>
44#include <linux/platform_device.h>
45#include <linux/jiffies.h>
46#include <sound/driver.h>
47#include <sound/core.h>
48#include <sound/pcm.h>
49#include <sound/pcm_params.h>
50#include <sound/soc-dapm.h>
51#include <sound/initval.h>
52
53/* debug */
54#define DAPM_DEBUG 0
55#if DAPM_DEBUG
56#define dump_dapm(codec, action) dbg_dump_dapm(codec, action)
57#define dbg(format, arg...) printk(format, ## arg)
58#else
59#define dump_dapm(codec, action)
60#define dbg(format, arg...)
61#endif
62
63#define POP_DEBUG 0
64#if POP_DEBUG
65#define POP_TIME 500 /* 500 msecs - change if pop debug is too fast */
66#define pop_wait(time) schedule_timeout_interruptible(msecs_to_jiffies(time))
67#define pop_dbg(format, arg...) printk(format, ## arg); pop_wait(POP_TIME)
68#else
69#define pop_dbg(format, arg...)
70#define pop_wait(time)
71#endif
72
73/* dapm power sequences - make this per codec in the future */
74static int dapm_up_seq[] = {
75 snd_soc_dapm_pre, snd_soc_dapm_micbias, snd_soc_dapm_mic,
76 snd_soc_dapm_mux, snd_soc_dapm_dac, snd_soc_dapm_mixer, snd_soc_dapm_pga,
77 snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk, snd_soc_dapm_post
78};
79static int dapm_down_seq[] = {
80 snd_soc_dapm_pre, snd_soc_dapm_adc, snd_soc_dapm_hp, snd_soc_dapm_spk,
81 snd_soc_dapm_pga, snd_soc_dapm_mixer, snd_soc_dapm_dac, snd_soc_dapm_mic,
82 snd_soc_dapm_micbias, snd_soc_dapm_mux, snd_soc_dapm_post
83};
84
85static int dapm_status = 1;
86module_param(dapm_status, int, 0);
87MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
88
89/* create a new dapm widget */
90static inline struct snd_soc_dapm_widget *dapm_cnew_widget(
91 const struct snd_soc_dapm_widget *_widget)
92{
93 return kmemdup(_widget, sizeof(*_widget), GFP_KERNEL);
94}
95
96/* set up initial codec paths */
97static void dapm_set_path_status(struct snd_soc_dapm_widget *w,
98 struct snd_soc_dapm_path *p, int i)
99{
100 switch (w->id) {
101 case snd_soc_dapm_switch:
102 case snd_soc_dapm_mixer: {
103 int val;
104 int reg = w->kcontrols[i].private_value & 0xff;
105 int shift = (w->kcontrols[i].private_value >> 8) & 0x0f;
106 int mask = (w->kcontrols[i].private_value >> 16) & 0xff;
107 int invert = (w->kcontrols[i].private_value >> 24) & 0x01;
108
109 val = snd_soc_read(w->codec, reg);
110 val = (val >> shift) & mask;
111
112 if ((invert && !val) || (!invert && val))
113 p->connect = 1;
114 else
115 p->connect = 0;
116 }
117 break;
118 case snd_soc_dapm_mux: {
119 struct soc_enum *e = (struct soc_enum *)w->kcontrols[i].private_value;
120 int val, item, bitmask;
121
122 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
123 ;
124 val = snd_soc_read(w->codec, e->reg);
125 item = (val >> e->shift_l) & (bitmask - 1);
126
127 p->connect = 0;
128 for (i = 0; i < e->mask; i++) {
129 if (!(strcmp(p->name, e->texts[i])) && item == i)
130 p->connect = 1;
131 }
132 }
133 break;
134 /* does not effect routing - always connected */
135 case snd_soc_dapm_pga:
136 case snd_soc_dapm_output:
137 case snd_soc_dapm_adc:
138 case snd_soc_dapm_input:
139 case snd_soc_dapm_dac:
140 case snd_soc_dapm_micbias:
141 case snd_soc_dapm_vmid:
142 p->connect = 1;
143 break;
144 /* does effect routing - dynamically connected */
145 case snd_soc_dapm_hp:
146 case snd_soc_dapm_mic:
147 case snd_soc_dapm_spk:
148 case snd_soc_dapm_line:
149 case snd_soc_dapm_pre:
150 case snd_soc_dapm_post:
151 p->connect = 0;
152 break;
153 }
154}
155
156/* connect mux widget to it's interconnecting audio paths */
157static int dapm_connect_mux(struct snd_soc_codec *codec,
158 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
159 struct snd_soc_dapm_path *path, const char *control_name,
160 const struct snd_kcontrol_new *kcontrol)
161{
162 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
163 int i;
164
165 for (i = 0; i < e->mask; i++) {
166 if (!(strcmp(control_name, e->texts[i]))) {
167 list_add(&path->list, &codec->dapm_paths);
168 list_add(&path->list_sink, &dest->sources);
169 list_add(&path->list_source, &src->sinks);
170 path->name = (char*)e->texts[i];
171 dapm_set_path_status(dest, path, 0);
172 return 0;
173 }
174 }
175
176 return -ENODEV;
177}
178
179/* connect mixer widget to it's interconnecting audio paths */
180static int dapm_connect_mixer(struct snd_soc_codec *codec,
181 struct snd_soc_dapm_widget *src, struct snd_soc_dapm_widget *dest,
182 struct snd_soc_dapm_path *path, const char *control_name)
183{
184 int i;
185
186 /* search for mixer kcontrol */
187 for (i = 0; i < dest->num_kcontrols; i++) {
188 if (!strcmp(control_name, dest->kcontrols[i].name)) {
189 list_add(&path->list, &codec->dapm_paths);
190 list_add(&path->list_sink, &dest->sources);
191 list_add(&path->list_source, &src->sinks);
192 path->name = dest->kcontrols[i].name;
193 dapm_set_path_status(dest, path, i);
194 return 0;
195 }
196 }
197 return -ENODEV;
198}
199
200/* update dapm codec register bits */
201static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
202{
203 int change, power;
204 unsigned short old, new;
205 struct snd_soc_codec *codec = widget->codec;
206
207 /* check for valid widgets */
208 if (widget->reg < 0 || widget->id == snd_soc_dapm_input ||
209 widget->id == snd_soc_dapm_output ||
210 widget->id == snd_soc_dapm_hp ||
211 widget->id == snd_soc_dapm_mic ||
212 widget->id == snd_soc_dapm_line ||
213 widget->id == snd_soc_dapm_spk)
214 return 0;
215
216 power = widget->power;
217 if (widget->invert)
218 power = (power ? 0:1);
219
220 old = snd_soc_read(codec, widget->reg);
221 new = (old & ~(0x1 << widget->shift)) | (power << widget->shift);
222
223 change = old != new;
224 if (change) {
225 pop_dbg("pop test %s : %s in %d ms\n", widget->name,
226 widget->power ? "on" : "off", POP_TIME);
227 snd_soc_write(codec, widget->reg, new);
228 pop_wait(POP_TIME);
229 }
230 dbg("reg old %x new %x change %d\n", old, new, change);
231 return change;
232}
233
234/* ramps the volume up or down to minimise pops before or after a
235 * DAPM power event */
236static int dapm_set_pga(struct snd_soc_dapm_widget *widget, int power)
237{
238 const struct snd_kcontrol_new *k = widget->kcontrols;
239
240 if (widget->muted && !power)
241 return 0;
242 if (!widget->muted && power)
243 return 0;
244
245 if (widget->num_kcontrols && k) {
246 int reg = k->private_value & 0xff;
247 int shift = (k->private_value >> 8) & 0x0f;
248 int mask = (k->private_value >> 16) & 0xff;
249 int invert = (k->private_value >> 24) & 0x01;
250
251 if (power) {
252 int i;
253 /* power up has happended, increase volume to last level */
254 if (invert) {
255 for (i = mask; i > widget->saved_value; i--)
256 snd_soc_update_bits(widget->codec, reg, mask, i);
257 } else {
258 for (i = 0; i < widget->saved_value; i++)
259 snd_soc_update_bits(widget->codec, reg, mask, i);
260 }
261 widget->muted = 0;
262 } else {
263 /* power down is about to occur, decrease volume to mute */
264 int val = snd_soc_read(widget->codec, reg);
265 int i = widget->saved_value = (val >> shift) & mask;
266 if (invert) {
267 for (; i < mask; i++)
268 snd_soc_update_bits(widget->codec, reg, mask, i);
269 } else {
270 for (; i > 0; i--)
271 snd_soc_update_bits(widget->codec, reg, mask, i);
272 }
273 widget->muted = 1;
274 }
275 }
276 return 0;
277}
278
279/* create new dapm mixer control */
280static int dapm_new_mixer(struct snd_soc_codec *codec,
281 struct snd_soc_dapm_widget *w)
282{
283 int i, ret = 0;
284 char name[32];
285 struct snd_soc_dapm_path *path;
286
287 /* add kcontrol */
288 for (i = 0; i < w->num_kcontrols; i++) {
289
290 /* match name */
291 list_for_each_entry(path, &w->sources, list_sink) {
292
293 /* mixer/mux paths name must match control name */
294 if (path->name != (char*)w->kcontrols[i].name)
295 continue;
296
297 /* add dapm control with long name */
298 snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
299 path->long_name = kstrdup (name, GFP_KERNEL);
300 if (path->long_name == NULL)
301 return -ENOMEM;
302
303 path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
304 path->long_name);
305 ret = snd_ctl_add(codec->card, path->kcontrol);
306 if (ret < 0) {
307 printk(KERN_ERR "asoc: failed to add dapm kcontrol %s\n",
308 path->long_name);
309 kfree(path->long_name);
310 path->long_name = NULL;
311 return ret;
312 }
313 }
314 }
315 return ret;
316}
317
318/* create new dapm mux control */
319static int dapm_new_mux(struct snd_soc_codec *codec,
320 struct snd_soc_dapm_widget *w)
321{
322 struct snd_soc_dapm_path *path = NULL;
323 struct snd_kcontrol *kcontrol;
324 int ret = 0;
325
326 if (!w->num_kcontrols) {
327 printk(KERN_ERR "asoc: mux %s has no controls\n", w->name);
328 return -EINVAL;
329 }
330
331 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
332 ret = snd_ctl_add(codec->card, kcontrol);
333 if (ret < 0)
334 goto err;
335
336 list_for_each_entry(path, &w->sources, list_sink)
337 path->kcontrol = kcontrol;
338
339 return ret;
340
341err:
342 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
343 return ret;
344}
345
346/* create new dapm volume control */
347static int dapm_new_pga(struct snd_soc_codec *codec,
348 struct snd_soc_dapm_widget *w)
349{
350 struct snd_kcontrol *kcontrol;
351 int ret = 0;
352
353 if (!w->num_kcontrols)
354 return -EINVAL;
355
356 kcontrol = snd_soc_cnew(&w->kcontrols[0], w, w->name);
357 ret = snd_ctl_add(codec->card, kcontrol);
358 if (ret < 0) {
359 printk(KERN_ERR "asoc: failed to add kcontrol %s\n", w->name);
360 return ret;
361 }
362
363 return ret;
364}
365
366/* reset 'walked' bit for each dapm path */
367static inline void dapm_clear_walk(struct snd_soc_codec *codec)
368{
369 struct snd_soc_dapm_path *p;
370
371 list_for_each_entry(p, &codec->dapm_paths, list)
372 p->walked = 0;
373}
374
375/*
376 * Recursively check for a completed path to an active or physically connected
377 * output widget. Returns number of complete paths.
378 */
379static int is_connected_output_ep(struct snd_soc_dapm_widget *widget)
380{
381 struct snd_soc_dapm_path *path;
382 int con = 0;
383
384 if (widget->id == snd_soc_dapm_adc && widget->active)
385 return 1;
386
387 if (widget->connected) {
388 /* connected pin ? */
389 if (widget->id == snd_soc_dapm_output && !widget->ext)
390 return 1;
391
392 /* connected jack or spk ? */
393 if (widget->id == snd_soc_dapm_hp || widget->id == snd_soc_dapm_spk ||
394 widget->id == snd_soc_dapm_line)
395 return 1;
396 }
397
398 list_for_each_entry(path, &widget->sinks, list_source) {
399 if (path->walked)
400 continue;
401
402 if (path->sink && path->connect) {
403 path->walked = 1;
404 con += is_connected_output_ep(path->sink);
405 }
406 }
407
408 return con;
409}
410
411/*
412 * Recursively check for a completed path to an active or physically connected
413 * input widget. Returns number of complete paths.
414 */
415static int is_connected_input_ep(struct snd_soc_dapm_widget *widget)
416{
417 struct snd_soc_dapm_path *path;
418 int con = 0;
419
420 /* active stream ? */
421 if (widget->id == snd_soc_dapm_dac && widget->active)
422 return 1;
423
424 if (widget->connected) {
425 /* connected pin ? */
426 if (widget->id == snd_soc_dapm_input && !widget->ext)
427 return 1;
428
429 /* connected VMID/Bias for lower pops */
430 if (widget->id == snd_soc_dapm_vmid)
431 return 1;
432
433 /* connected jack ? */
434 if (widget->id == snd_soc_dapm_mic || widget->id == snd_soc_dapm_line)
435 return 1;
436 }
437
438 list_for_each_entry(path, &widget->sources, list_sink) {
439 if (path->walked)
440 continue;
441
442 if (path->source && path->connect) {
443 path->walked = 1;
444 con += is_connected_input_ep(path->source);
445 }
446 }
447
448 return con;
449}
450
451/*
452 * Scan each dapm widget for complete audio path.
453 * A complete path is a route that has valid endpoints i.e.:-
454 *
455 * o DAC to output pin.
456 * o Input Pin to ADC.
457 * o Input pin to Output pin (bypass, sidetone)
458 * o DAC to ADC (loopback).
459 */
460static int dapm_power_widgets(struct snd_soc_codec *codec, int event)
461{
462 struct snd_soc_dapm_widget *w;
463 int in, out, i, c = 1, *seq = NULL, ret = 0, power_change, power;
464
465 /* do we have a sequenced stream event */
466 if (event == SND_SOC_DAPM_STREAM_START) {
467 c = ARRAY_SIZE(dapm_up_seq);
468 seq = dapm_up_seq;
469 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
470 c = ARRAY_SIZE(dapm_down_seq);
471 seq = dapm_down_seq;
472 }
473
474 for(i = 0; i < c; i++) {
475 list_for_each_entry(w, &codec->dapm_widgets, list) {
476
477 /* is widget in stream order */
478 if (seq && seq[i] && w->id != seq[i])
479 continue;
480
481 /* vmid - no action */
482 if (w->id == snd_soc_dapm_vmid)
483 continue;
484
485 /* active ADC */
486 if (w->id == snd_soc_dapm_adc && w->active) {
487 in = is_connected_input_ep(w);
488 dapm_clear_walk(w->codec);
489 w->power = (in != 0) ? 1 : 0;
490 dapm_update_bits(w);
491 continue;
492 }
493
494 /* active DAC */
495 if (w->id == snd_soc_dapm_dac && w->active) {
496 out = is_connected_output_ep(w);
497 dapm_clear_walk(w->codec);
498 w->power = (out != 0) ? 1 : 0;
499 dapm_update_bits(w);
500 continue;
501 }
502
503 /* programmable gain/attenuation */
504 if (w->id == snd_soc_dapm_pga) {
505 int on;
506 in = is_connected_input_ep(w);
507 dapm_clear_walk(w->codec);
508 out = is_connected_output_ep(w);
509 dapm_clear_walk(w->codec);
510 w->power = on = (out != 0 && in != 0) ? 1 : 0;
511
512 if (!on)
513 dapm_set_pga(w, on); /* lower volume to reduce pops */
514 dapm_update_bits(w);
515 if (on)
516 dapm_set_pga(w, on); /* restore volume from zero */
517
518 continue;
519 }
520
521 /* pre and post event widgets */
522 if (w->id == snd_soc_dapm_pre) {
523 if (!w->event)
524 continue;
525
526 if (event == SND_SOC_DAPM_STREAM_START) {
527 ret = w->event(w, SND_SOC_DAPM_PRE_PMU);
528 if (ret < 0)
529 return ret;
530 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
531 ret = w->event(w, SND_SOC_DAPM_PRE_PMD);
532 if (ret < 0)
533 return ret;
534 }
535 continue;
536 }
537 if (w->id == snd_soc_dapm_post) {
538 if (!w->event)
539 continue;
540
541 if (event == SND_SOC_DAPM_STREAM_START) {
542 ret = w->event(w, SND_SOC_DAPM_POST_PMU);
543 if (ret < 0)
544 return ret;
545 } else if (event == SND_SOC_DAPM_STREAM_STOP) {
546 ret = w->event(w, SND_SOC_DAPM_POST_PMD);
547 if (ret < 0)
548 return ret;
549 }
550 continue;
551 }
552
553 /* all other widgets */
554 in = is_connected_input_ep(w);
555 dapm_clear_walk(w->codec);
556 out = is_connected_output_ep(w);
557 dapm_clear_walk(w->codec);
558 power = (out != 0 && in != 0) ? 1 : 0;
559 power_change = (w->power == power) ? 0: 1;
560 w->power = power;
561
562 /* call any power change event handlers */
563 if (power_change) {
564 if (w->event) {
565 dbg("power %s event for %s flags %x\n",
566 w->power ? "on" : "off", w->name, w->event_flags);
567 if (power) {
568 /* power up event */
569 if (w->event_flags & SND_SOC_DAPM_PRE_PMU) {
570 ret = w->event(w, SND_SOC_DAPM_PRE_PMU);
571 if (ret < 0)
572 return ret;
573 }
574 dapm_update_bits(w);
575 if (w->event_flags & SND_SOC_DAPM_POST_PMU){
576 ret = w->event(w, SND_SOC_DAPM_POST_PMU);
577 if (ret < 0)
578 return ret;
579 }
580 } else {
581 /* power down event */
582 if (w->event_flags & SND_SOC_DAPM_PRE_PMD) {
583 ret = w->event(w, SND_SOC_DAPM_PRE_PMD);
584 if (ret < 0)
585 return ret;
586 }
587 dapm_update_bits(w);
588 if (w->event_flags & SND_SOC_DAPM_POST_PMD) {
589 ret = w->event(w, SND_SOC_DAPM_POST_PMD);
590 if (ret < 0)
591 return ret;
592 }
593 }
594 } else
595 /* no event handler */
596 dapm_update_bits(w);
597 }
598 }
599 }
600
601 return ret;
602}
603
604#if DAPM_DEBUG
605static void dbg_dump_dapm(struct snd_soc_codec* codec, const char *action)
606{
607 struct snd_soc_dapm_widget *w;
608 struct snd_soc_dapm_path *p = NULL;
609 int in, out;
610
611 printk("DAPM %s %s\n", codec->name, action);
612
613 list_for_each_entry(w, &codec->dapm_widgets, list) {
614
615 /* only display widgets that effect routing */
616 switch (w->id) {
617 case snd_soc_dapm_pre:
618 case snd_soc_dapm_post:
619 case snd_soc_dapm_vmid:
620 continue;
621 case snd_soc_dapm_mux:
622 case snd_soc_dapm_output:
623 case snd_soc_dapm_input:
624 case snd_soc_dapm_switch:
625 case snd_soc_dapm_hp:
626 case snd_soc_dapm_mic:
627 case snd_soc_dapm_spk:
628 case snd_soc_dapm_line:
629 case snd_soc_dapm_micbias:
630 case snd_soc_dapm_dac:
631 case snd_soc_dapm_adc:
632 case snd_soc_dapm_pga:
633 case snd_soc_dapm_mixer:
634 if (w->name) {
635 in = is_connected_input_ep(w);
636 dapm_clear_walk(w->codec);
637 out = is_connected_output_ep(w);
638 dapm_clear_walk(w->codec);
639 printk("%s: %s in %d out %d\n", w->name,
640 w->power ? "On":"Off",in, out);
641
642 list_for_each_entry(p, &w->sources, list_sink) {
643 if (p->connect)
644 printk(" in %s %s\n", p->name ? p->name : "static",
645 p->source->name);
646 }
647 list_for_each_entry(p, &w->sinks, list_source) {
648 if (p->connect)
649 printk(" out %s %s\n", p->name ? p->name : "static",
650 p->sink->name);
651 }
652 }
653 break;
654 }
655 }
656}
657#endif
658
659/* test and update the power status of a mux widget */
660static int dapm_mux_update_power(struct snd_soc_dapm_widget *widget,
661 struct snd_kcontrol *kcontrol, int mask,
662 int val, struct soc_enum* e)
663{
664 struct snd_soc_dapm_path *path;
665 int found = 0;
666
667 if (widget->id != snd_soc_dapm_mux)
668 return -ENODEV;
669
670 if (!snd_soc_test_bits(widget->codec, e->reg, mask, val))
671 return 0;
672
673 /* find dapm widget path assoc with kcontrol */
674 list_for_each_entry(path, &widget->codec->dapm_paths, list) {
675 if (path->kcontrol != kcontrol)
676 continue;
677
678 if (!path->name || ! e->texts[val])
679 continue;
680
681 found = 1;
682 /* we now need to match the string in the enum to the path */
683 if (!(strcmp(path->name, e->texts[val])))
684 path->connect = 1; /* new connection */
685 else
686 path->connect = 0; /* old connection must be powered down */
687 }
688
689 if (found)
690 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
691
692 return 0;
693}
694
695/* test and update the power status of a mixer widget */
696static int dapm_mixer_update_power(struct snd_soc_dapm_widget *widget,
697 struct snd_kcontrol *kcontrol, int reg,
698 int val_mask, int val, int invert)
699{
700 struct snd_soc_dapm_path *path;
701 int found = 0;
702
703 if (widget->id != snd_soc_dapm_mixer)
704 return -ENODEV;
705
706 if (!snd_soc_test_bits(widget->codec, reg, val_mask, val))
707 return 0;
708
709 /* find dapm widget path assoc with kcontrol */
710 list_for_each_entry(path, &widget->codec->dapm_paths, list) {
711 if (path->kcontrol != kcontrol)
712 continue;
713
714 /* found, now check type */
715 found = 1;
716 if (val)
717 /* new connection */
718 path->connect = invert ? 0:1;
719 else
720 /* old connection must be powered down */
721 path->connect = invert ? 1:0;
722 break;
723 }
724
725 if (found)
726 dapm_power_widgets(widget->codec, SND_SOC_DAPM_STREAM_NOP);
727
728 return 0;
729}
730
731/* show dapm widget status in sys fs */
732static ssize_t dapm_widget_show(struct device *dev,
733 struct device_attribute *attr, char *buf)
734{
735 struct snd_soc_device *devdata = dev_get_drvdata(dev);
736 struct snd_soc_codec *codec = devdata->codec;
737 struct snd_soc_dapm_widget *w;
738 int count = 0;
739 char *state = "not set";
740
741 list_for_each_entry(w, &codec->dapm_widgets, list) {
742
743 /* only display widgets that burnm power */
744 switch (w->id) {
745 case snd_soc_dapm_hp:
746 case snd_soc_dapm_mic:
747 case snd_soc_dapm_spk:
748 case snd_soc_dapm_line:
749 case snd_soc_dapm_micbias:
750 case snd_soc_dapm_dac:
751 case snd_soc_dapm_adc:
752 case snd_soc_dapm_pga:
753 case snd_soc_dapm_mixer:
754 if (w->name)
755 count += sprintf(buf + count, "%s: %s\n",
756 w->name, w->power ? "On":"Off");
757 break;
758 default:
759 break;
760 }
761 }
762
763 switch(codec->dapm_state){
764 case SNDRV_CTL_POWER_D0:
765 state = "D0";
766 break;
767 case SNDRV_CTL_POWER_D1:
768 state = "D1";
769 break;
770 case SNDRV_CTL_POWER_D2:
771 state = "D2";
772 break;
773 case SNDRV_CTL_POWER_D3hot:
774 state = "D3hot";
775 break;
776 case SNDRV_CTL_POWER_D3cold:
777 state = "D3cold";
778 break;
779 }
780 count += sprintf(buf + count, "PM State: %s\n", state);
781
782 return count;
783}
784
785static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
786
787int snd_soc_dapm_sys_add(struct device *dev)
788{
789 int ret = 0;
790
791 if (dapm_status)
792 ret = device_create_file(dev, &dev_attr_dapm_widget);
793
794 return ret;
795}
796
797static void snd_soc_dapm_sys_remove(struct device *dev)
798{
799 if (dapm_status)
800 device_remove_file(dev, &dev_attr_dapm_widget);
801}
802
803/* free all dapm widgets and resources */
804static void dapm_free_widgets(struct snd_soc_codec *codec)
805{
806 struct snd_soc_dapm_widget *w, *next_w;
807 struct snd_soc_dapm_path *p, *next_p;
808
809 list_for_each_entry_safe(w, next_w, &codec->dapm_widgets, list) {
810 list_del(&w->list);
811 kfree(w);
812 }
813
814 list_for_each_entry_safe(p, next_p, &codec->dapm_paths, list) {
815 list_del(&p->list);
816 kfree(p->long_name);
817 kfree(p);
818 }
819}
820
821/**
822 * snd_soc_dapm_sync_endpoints - scan and power dapm paths
823 * @codec: audio codec
824 *
825 * Walks all dapm audio paths and powers widgets according to their
826 * stream or path usage.
827 *
828 * Returns 0 for success.
829 */
830int snd_soc_dapm_sync_endpoints(struct snd_soc_codec *codec)
831{
832 return dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
833}
834EXPORT_SYMBOL_GPL(snd_soc_dapm_sync_endpoints);
835
836/**
837 * snd_soc_dapm_connect_input - connect dapm widgets
838 * @codec: audio codec
839 * @sink: name of target widget
840 * @control: mixer control name
841 * @source: name of source name
842 *
843 * Connects 2 dapm widgets together via a named audio path. The sink is
844 * the widget receiving the audio signal, whilst the source is the sender
845 * of the audio signal.
846 *
847 * Returns 0 for success else error.
848 */
849int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
850 const char * control, const char *source)
851{
852 struct snd_soc_dapm_path *path;
853 struct snd_soc_dapm_widget *wsource = NULL, *wsink = NULL, *w;
854 int ret = 0;
855
856 /* find src and dest widgets */
857 list_for_each_entry(w, &codec->dapm_widgets, list) {
858
859 if (!wsink && !(strcmp(w->name, sink))) {
860 wsink = w;
861 continue;
862 }
863 if (!wsource && !(strcmp(w->name, source))) {
864 wsource = w;
865 }
866 }
867
868 if (wsource == NULL || wsink == NULL)
869 return -ENODEV;
870
871 path = kzalloc(sizeof(struct snd_soc_dapm_path), GFP_KERNEL);
872 if (!path)
873 return -ENOMEM;
874
875 path->source = wsource;
876 path->sink = wsink;
877 INIT_LIST_HEAD(&path->list);
878 INIT_LIST_HEAD(&path->list_source);
879 INIT_LIST_HEAD(&path->list_sink);
880
881 /* check for external widgets */
882 if (wsink->id == snd_soc_dapm_input) {
883 if (wsource->id == snd_soc_dapm_micbias ||
884 wsource->id == snd_soc_dapm_mic ||
885 wsink->id == snd_soc_dapm_line)
886 wsink->ext = 1;
887 }
888 if (wsource->id == snd_soc_dapm_output) {
889 if (wsink->id == snd_soc_dapm_spk ||
890 wsink->id == snd_soc_dapm_hp ||
891 wsink->id == snd_soc_dapm_line)
892 wsource->ext = 1;
893 }
894
895 /* connect static paths */
896 if (control == NULL) {
897 list_add(&path->list, &codec->dapm_paths);
898 list_add(&path->list_sink, &wsink->sources);
899 list_add(&path->list_source, &wsource->sinks);
900 path->connect = 1;
901 return 0;
902 }
903
904 /* connect dynamic paths */
905 switch(wsink->id) {
906 case snd_soc_dapm_adc:
907 case snd_soc_dapm_dac:
908 case snd_soc_dapm_pga:
909 case snd_soc_dapm_input:
910 case snd_soc_dapm_output:
911 case snd_soc_dapm_micbias:
912 case snd_soc_dapm_vmid:
913 case snd_soc_dapm_pre:
914 case snd_soc_dapm_post:
915 list_add(&path->list, &codec->dapm_paths);
916 list_add(&path->list_sink, &wsink->sources);
917 list_add(&path->list_source, &wsource->sinks);
918 path->connect = 1;
919 return 0;
920 case snd_soc_dapm_mux:
921 ret = dapm_connect_mux(codec, wsource, wsink, path, control,
922 &wsink->kcontrols[0]);
923 if (ret != 0)
924 goto err;
925 break;
926 case snd_soc_dapm_switch:
927 case snd_soc_dapm_mixer:
928 ret = dapm_connect_mixer(codec, wsource, wsink, path, control);
929 if (ret != 0)
930 goto err;
931 break;
932 case snd_soc_dapm_hp:
933 case snd_soc_dapm_mic:
934 case snd_soc_dapm_line:
935 case snd_soc_dapm_spk:
936 list_add(&path->list, &codec->dapm_paths);
937 list_add(&path->list_sink, &wsink->sources);
938 list_add(&path->list_source, &wsource->sinks);
939 path->connect = 0;
940 return 0;
941 }
942 return 0;
943
944err:
945 printk(KERN_WARNING "asoc: no dapm match for %s --> %s --> %s\n", source,
946 control, sink);
947 kfree(path);
948 return ret;
949}
950EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
951
952/**
953 * snd_soc_dapm_new_widgets - add new dapm widgets
954 * @codec: audio codec
955 *
956 * Checks the codec for any new dapm widgets and creates them if found.
957 *
958 * Returns 0 for success.
959 */
960int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec)
961{
962 struct snd_soc_dapm_widget *w;
963
964 mutex_lock(&codec->mutex);
965 list_for_each_entry(w, &codec->dapm_widgets, list)
966 {
967 if (w->new)
968 continue;
969
970 switch(w->id) {
971 case snd_soc_dapm_switch:
972 case snd_soc_dapm_mixer:
973 dapm_new_mixer(codec, w);
974 break;
975 case snd_soc_dapm_mux:
976 dapm_new_mux(codec, w);
977 break;
978 case snd_soc_dapm_adc:
979 case snd_soc_dapm_dac:
980 case snd_soc_dapm_pga:
981 dapm_new_pga(codec, w);
982 break;
983 case snd_soc_dapm_input:
984 case snd_soc_dapm_output:
985 case snd_soc_dapm_micbias:
986 case snd_soc_dapm_spk:
987 case snd_soc_dapm_hp:
988 case snd_soc_dapm_mic:
989 case snd_soc_dapm_line:
990 case snd_soc_dapm_vmid:
991 case snd_soc_dapm_pre:
992 case snd_soc_dapm_post:
993 break;
994 }
995 w->new = 1;
996 }
997
998 dapm_power_widgets(codec, SND_SOC_DAPM_STREAM_NOP);
999 mutex_unlock(&codec->mutex);
1000 return 0;
1001}
1002EXPORT_SYMBOL_GPL(snd_soc_dapm_new_widgets);
1003
1004/**
1005 * snd_soc_dapm_get_volsw - dapm mixer get callback
1006 * @kcontrol: mixer control
1007 * @uinfo: control element information
1008 *
1009 * Callback to get the value of a dapm mixer control.
1010 *
1011 * Returns 0 for success.
1012 */
1013int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol,
1014 struct snd_ctl_elem_value *ucontrol)
1015{
1016 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1017 int reg = kcontrol->private_value & 0xff;
1018 int shift = (kcontrol->private_value >> 8) & 0x0f;
1019 int rshift = (kcontrol->private_value >> 12) & 0x0f;
1020 int mask = (kcontrol->private_value >> 16) & 0xff;
1021 int invert = (kcontrol->private_value >> 24) & 0x01;
1022
1023 /* return the saved value if we are powered down */
1024 if (widget->id == snd_soc_dapm_pga && !widget->power) {
1025 ucontrol->value.integer.value[0] = widget->saved_value;
1026 return 0;
1027 }
1028
1029 ucontrol->value.integer.value[0] =
1030 (snd_soc_read(widget->codec, reg) >> shift) & mask;
1031 if (shift != rshift)
1032 ucontrol->value.integer.value[1] =
1033 (snd_soc_read(widget->codec, reg) >> rshift) & mask;
1034 if (invert) {
1035 ucontrol->value.integer.value[0] =
1036 mask - ucontrol->value.integer.value[0];
1037 if (shift != rshift)
1038 ucontrol->value.integer.value[1] =
1039 mask - ucontrol->value.integer.value[1];
1040 }
1041
1042 return 0;
1043}
1044EXPORT_SYMBOL_GPL(snd_soc_dapm_get_volsw);
1045
1046/**
1047 * snd_soc_dapm_put_volsw - dapm mixer set callback
1048 * @kcontrol: mixer control
1049 * @uinfo: control element information
1050 *
1051 * Callback to set the value of a dapm mixer control.
1052 *
1053 * Returns 0 for success.
1054 */
1055int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol,
1056 struct snd_ctl_elem_value *ucontrol)
1057{
1058 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1059 int reg = kcontrol->private_value & 0xff;
1060 int shift = (kcontrol->private_value >> 8) & 0x0f;
1061 int rshift = (kcontrol->private_value >> 12) & 0x0f;
1062 int mask = (kcontrol->private_value >> 16) & 0xff;
1063 int invert = (kcontrol->private_value >> 24) & 0x01;
1064 unsigned short val, val2, val_mask;
1065 int ret;
1066
1067 val = (ucontrol->value.integer.value[0] & mask);
1068
1069 if (invert)
1070 val = mask - val;
1071 val_mask = mask << shift;
1072 val = val << shift;
1073 if (shift != rshift) {
1074 val2 = (ucontrol->value.integer.value[1] & mask);
1075 if (invert)
1076 val2 = mask - val2;
1077 val_mask |= mask << rshift;
1078 val |= val2 << rshift;
1079 }
1080
1081 mutex_lock(&widget->codec->mutex);
1082 widget->value = val;
1083
1084 /* save volume value if the widget is powered down */
1085 if (widget->id == snd_soc_dapm_pga && !widget->power) {
1086 widget->saved_value = val;
1087 mutex_unlock(&widget->codec->mutex);
1088 return 1;
1089 }
1090
1091 dapm_mixer_update_power(widget, kcontrol, reg, val_mask, val, invert);
1092 if (widget->event) {
1093 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1094 ret = widget->event(widget, SND_SOC_DAPM_PRE_REG);
1095 if (ret < 0)
1096 goto out;
1097 }
1098 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
1099 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1100 ret = widget->event(widget, SND_SOC_DAPM_POST_REG);
1101 } else
1102 ret = snd_soc_update_bits(widget->codec, reg, val_mask, val);
1103
1104out:
1105 mutex_unlock(&widget->codec->mutex);
1106 return ret;
1107}
1108EXPORT_SYMBOL_GPL(snd_soc_dapm_put_volsw);
1109
1110/**
1111 * snd_soc_dapm_get_enum_double - dapm enumerated double mixer get callback
1112 * @kcontrol: mixer control
1113 * @uinfo: control element information
1114 *
1115 * Callback to get the value of a dapm enumerated double mixer control.
1116 *
1117 * Returns 0 for success.
1118 */
1119int snd_soc_dapm_get_enum_double(struct snd_kcontrol *kcontrol,
1120 struct snd_ctl_elem_value *ucontrol)
1121{
1122 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1123 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1124 unsigned short val, bitmask;
1125
1126 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
1127 ;
1128 val = snd_soc_read(widget->codec, e->reg);
1129 ucontrol->value.enumerated.item[0] = (val >> e->shift_l) & (bitmask - 1);
1130 if (e->shift_l != e->shift_r)
1131 ucontrol->value.enumerated.item[1] =
1132 (val >> e->shift_r) & (bitmask - 1);
1133
1134 return 0;
1135}
1136EXPORT_SYMBOL_GPL(snd_soc_dapm_get_enum_double);
1137
1138/**
1139 * snd_soc_dapm_put_enum_double - dapm enumerated double mixer set callback
1140 * @kcontrol: mixer control
1141 * @uinfo: control element information
1142 *
1143 * Callback to set the value of a dapm enumerated double mixer control.
1144 *
1145 * Returns 0 for success.
1146 */
1147int snd_soc_dapm_put_enum_double(struct snd_kcontrol *kcontrol,
1148 struct snd_ctl_elem_value *ucontrol)
1149{
1150 struct snd_soc_dapm_widget *widget = snd_kcontrol_chip(kcontrol);
1151 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
1152 unsigned short val, mux;
1153 unsigned short mask, bitmask;
1154 int ret = 0;
1155
1156 for (bitmask = 1; bitmask < e->mask; bitmask <<= 1)
1157 ;
1158 if (ucontrol->value.enumerated.item[0] > e->mask - 1)
1159 return -EINVAL;
1160 mux = ucontrol->value.enumerated.item[0];
1161 val = mux << e->shift_l;
1162 mask = (bitmask - 1) << e->shift_l;
1163 if (e->shift_l != e->shift_r) {
1164 if (ucontrol->value.enumerated.item[1] > e->mask - 1)
1165 return -EINVAL;
1166 val |= ucontrol->value.enumerated.item[1] << e->shift_r;
1167 mask |= (bitmask - 1) << e->shift_r;
1168 }
1169
1170 mutex_lock(&widget->codec->mutex);
1171 widget->value = val;
1172 dapm_mux_update_power(widget, kcontrol, mask, mux, e);
1173 if (widget->event) {
1174 if (widget->event_flags & SND_SOC_DAPM_PRE_REG) {
1175 ret = widget->event(widget, SND_SOC_DAPM_PRE_REG);
1176 if (ret < 0)
1177 goto out;
1178 }
1179 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1180 if (widget->event_flags & SND_SOC_DAPM_POST_REG)
1181 ret = widget->event(widget, SND_SOC_DAPM_POST_REG);
1182 } else
1183 ret = snd_soc_update_bits(widget->codec, e->reg, mask, val);
1184
1185out:
1186 mutex_unlock(&widget->codec->mutex);
1187 return ret;
1188}
1189EXPORT_SYMBOL_GPL(snd_soc_dapm_put_enum_double);
1190
1191/**
1192 * snd_soc_dapm_new_control - create new dapm control
1193 * @codec: audio codec
1194 * @widget: widget template
1195 *
1196 * Creates a new dapm control based upon the template.
1197 *
1198 * Returns 0 for success else error.
1199 */
1200int snd_soc_dapm_new_control(struct snd_soc_codec *codec,
1201 const struct snd_soc_dapm_widget *widget)
1202{
1203 struct snd_soc_dapm_widget *w;
1204
1205 if ((w = dapm_cnew_widget(widget)) == NULL)
1206 return -ENOMEM;
1207
1208 w->codec = codec;
1209 INIT_LIST_HEAD(&w->sources);
1210 INIT_LIST_HEAD(&w->sinks);
1211 INIT_LIST_HEAD(&w->list);
1212 list_add(&w->list, &codec->dapm_widgets);
1213
1214 /* machine layer set ups unconnected pins and insertions */
1215 w->connected = 1;
1216 return 0;
1217}
1218EXPORT_SYMBOL_GPL(snd_soc_dapm_new_control);
1219
1220/**
1221 * snd_soc_dapm_stream_event - send a stream event to the dapm core
1222 * @codec: audio codec
1223 * @stream: stream name
1224 * @event: stream event
1225 *
1226 * Sends a stream event to the dapm core. The core then makes any
1227 * necessary widget power changes.
1228 *
1229 * Returns 0 for success else error.
1230 */
1231int snd_soc_dapm_stream_event(struct snd_soc_codec *codec,
1232 char *stream, int event)
1233{
1234 struct snd_soc_dapm_widget *w;
1235
1236 if (stream == NULL)
1237 return 0;
1238
1239 mutex_lock(&codec->mutex);
1240 list_for_each_entry(w, &codec->dapm_widgets, list)
1241 {
1242 if (!w->sname)
1243 continue;
1244 dbg("widget %s\n %s stream %s event %d\n", w->name, w->sname,
1245 stream, event);
1246 if (strstr(w->sname, stream)) {
1247 switch(event) {
1248 case SND_SOC_DAPM_STREAM_START:
1249 w->active = 1;
1250 break;
1251 case SND_SOC_DAPM_STREAM_STOP:
1252 w->active = 0;
1253 break;
1254 case SND_SOC_DAPM_STREAM_SUSPEND:
1255 if (w->active)
1256 w->suspend = 1;
1257 w->active = 0;
1258 break;
1259 case SND_SOC_DAPM_STREAM_RESUME:
1260 if (w->suspend) {
1261 w->active = 1;
1262 w->suspend = 0;
1263 }
1264 break;
1265 case SND_SOC_DAPM_STREAM_PAUSE_PUSH:
1266 break;
1267 case SND_SOC_DAPM_STREAM_PAUSE_RELEASE:
1268 break;
1269 }
1270 }
1271 }
1272 mutex_unlock(&codec->mutex);
1273
1274 dapm_power_widgets(codec, event);
1275 dump_dapm(codec, __FUNCTION__);
1276 return 0;
1277}
1278EXPORT_SYMBOL_GPL(snd_soc_dapm_stream_event);
1279
1280/**
1281 * snd_soc_dapm_set_endpoint - set audio endpoint status
1282 * @codec: audio codec
1283 * @endpoint: audio signal endpoint (or start point)
1284 * @status: point status
1285 *
1286 * Set audio endpoint status - connected or disconnected.
1287 *
1288 * Returns 0 for success else error.
1289 */
1290int snd_soc_dapm_set_endpoint(struct snd_soc_codec *codec,
1291 char *endpoint, int status)
1292{
1293 struct snd_soc_dapm_widget *w;
1294
1295 list_for_each_entry(w, &codec->dapm_widgets, list) {
1296 if (!strcmp(w->name, endpoint)) {
1297 w->connected = status;
1298 }
1299 }
1300
1301 return 0;
1302}
1303EXPORT_SYMBOL_GPL(snd_soc_dapm_set_endpoint);
1304
1305/**
1306 * snd_soc_dapm_free - free dapm resources
1307 * @socdev: SoC device
1308 *
1309 * Free all dapm widgets and resources.
1310 */
1311void snd_soc_dapm_free(struct snd_soc_device *socdev)
1312{
1313 struct snd_soc_codec *codec = socdev->codec;
1314
1315 snd_soc_dapm_sys_remove(socdev->dev);
1316 dapm_free_widgets(codec);
1317}
1318EXPORT_SYMBOL_GPL(snd_soc_dapm_free);
1319
1320/* Module information */
1321MODULE_AUTHOR("Liam Girdwood, liam.girdwood@wolfsonmicro.com, www.wolfsonmicro.com");
1322MODULE_DESCRIPTION("Dynamic Audio Power Management core for ALSA SoC");
1323MODULE_LICENSE("GPL");
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c
index 4ceb09d215d8..25a2a7333006 100644
--- a/sound/sparc/dbri.c
+++ b/sound/sparc/dbri.c
@@ -678,7 +678,7 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len)
678 * The JUMP cmd points to the new cmd string. 678 * The JUMP cmd points to the new cmd string.
679 * It also releases the cmdlock spinlock. 679 * It also releases the cmdlock spinlock.
680 * 680 *
681 * Lock must not be held before calling this. 681 * Lock must be held before calling this.
682 */ 682 */
683static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) 683static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len)
684{ 684{
diff --git a/sound/usb/usbaudio.c b/sound/usb/usbaudio.c
index 19bdcc74c96c..4dfb91d4398a 100644
--- a/sound/usb/usbaudio.c
+++ b/sound/usb/usbaudio.c
@@ -186,6 +186,7 @@ struct snd_usb_substream {
186 u64 formats; /* format bitmasks (all or'ed) */ 186 u64 formats; /* format bitmasks (all or'ed) */
187 unsigned int num_formats; /* number of supported audio formats (list) */ 187 unsigned int num_formats; /* number of supported audio formats (list) */
188 struct list_head fmt_list; /* format list */ 188 struct list_head fmt_list; /* format list */
189 struct snd_pcm_hw_constraint_list rate_list; /* limited rates */
189 spinlock_t lock; 190 spinlock_t lock;
190 191
191 struct snd_urb_ops ops; /* callbacks (must be filled at init) */ 192 struct snd_urb_ops ops; /* callbacks (must be filled at init) */
@@ -253,7 +254,7 @@ static int prepare_capture_sync_urb(struct snd_usb_substream *subs,
253 struct urb *urb) 254 struct urb *urb)
254{ 255{
255 unsigned char *cp = urb->transfer_buffer; 256 unsigned char *cp = urb->transfer_buffer;
256 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 257 struct snd_urb_ctx *ctx = urb->context;
257 258
258 urb->dev = ctx->subs->dev; /* we need to set this at each time */ 259 urb->dev = ctx->subs->dev; /* we need to set this at each time */
259 urb->iso_frame_desc[0].length = 3; 260 urb->iso_frame_desc[0].length = 3;
@@ -275,7 +276,7 @@ static int prepare_capture_sync_urb_hs(struct snd_usb_substream *subs,
275 struct urb *urb) 276 struct urb *urb)
276{ 277{
277 unsigned char *cp = urb->transfer_buffer; 278 unsigned char *cp = urb->transfer_buffer;
278 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 279 struct snd_urb_ctx *ctx = urb->context;
279 280
280 urb->dev = ctx->subs->dev; /* we need to set this at each time */ 281 urb->dev = ctx->subs->dev; /* we need to set this at each time */
281 urb->iso_frame_desc[0].length = 4; 282 urb->iso_frame_desc[0].length = 4;
@@ -313,7 +314,7 @@ static int prepare_capture_urb(struct snd_usb_substream *subs,
313 struct urb *urb) 314 struct urb *urb)
314{ 315{
315 int i, offs; 316 int i, offs;
316 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 317 struct snd_urb_ctx *ctx = urb->context;
317 318
318 offs = 0; 319 offs = 0;
319 urb->dev = ctx->subs->dev; /* we need to set this at each time */ 320 urb->dev = ctx->subs->dev; /* we need to set this at each time */
@@ -391,6 +392,16 @@ static int retire_capture_urb(struct snd_usb_substream *subs,
391 return 0; 392 return 0;
392} 393}
393 394
395/*
396 * Process after capture complete when paused. Nothing to do.
397 */
398static int retire_paused_capture_urb(struct snd_usb_substream *subs,
399 struct snd_pcm_runtime *runtime,
400 struct urb *urb)
401{
402 return 0;
403}
404
394 405
395/* 406/*
396 * prepare urb for full speed playback sync pipe 407 * prepare urb for full speed playback sync pipe
@@ -402,7 +413,7 @@ static int prepare_playback_sync_urb(struct snd_usb_substream *subs,
402 struct snd_pcm_runtime *runtime, 413 struct snd_pcm_runtime *runtime,
403 struct urb *urb) 414 struct urb *urb)
404{ 415{
405 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 416 struct snd_urb_ctx *ctx = urb->context;
406 417
407 urb->dev = ctx->subs->dev; /* we need to set this at each time */ 418 urb->dev = ctx->subs->dev; /* we need to set this at each time */
408 urb->iso_frame_desc[0].length = 3; 419 urb->iso_frame_desc[0].length = 3;
@@ -420,7 +431,7 @@ static int prepare_playback_sync_urb_hs(struct snd_usb_substream *subs,
420 struct snd_pcm_runtime *runtime, 431 struct snd_pcm_runtime *runtime,
421 struct urb *urb) 432 struct urb *urb)
422{ 433{
423 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 434 struct snd_urb_ctx *ctx = urb->context;
424 435
425 urb->dev = ctx->subs->dev; /* we need to set this at each time */ 436 urb->dev = ctx->subs->dev; /* we need to set this at each time */
426 urb->iso_frame_desc[0].length = 4; 437 urb->iso_frame_desc[0].length = 4;
@@ -493,13 +504,13 @@ static int snd_usb_audio_next_packet_size(struct snd_usb_substream *subs)
493} 504}
494 505
495/* 506/*
496 * Prepare urb for streaming before playback starts. 507 * Prepare urb for streaming before playback starts or when paused.
497 * 508 *
498 * We don't yet have data, so we send a frame of silence. 509 * We don't have any data, so we send a frame of silence.
499 */ 510 */
500static int prepare_startup_playback_urb(struct snd_usb_substream *subs, 511static int prepare_nodata_playback_urb(struct snd_usb_substream *subs,
501 struct snd_pcm_runtime *runtime, 512 struct snd_pcm_runtime *runtime,
502 struct urb *urb) 513 struct urb *urb)
503{ 514{
504 unsigned int i, offs, counts; 515 unsigned int i, offs, counts;
505 struct snd_urb_ctx *ctx = urb->context; 516 struct snd_urb_ctx *ctx = urb->context;
@@ -537,7 +548,7 @@ static int prepare_playback_urb(struct snd_usb_substream *subs,
537 unsigned int counts; 548 unsigned int counts;
538 unsigned long flags; 549 unsigned long flags;
539 int period_elapsed = 0; 550 int period_elapsed = 0;
540 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 551 struct snd_urb_ctx *ctx = urb->context;
541 552
542 stride = runtime->frame_bits >> 3; 553 stride = runtime->frame_bits >> 3;
543 554
@@ -622,7 +633,7 @@ static int retire_playback_urb(struct snd_usb_substream *subs,
622 */ 633 */
623static struct snd_urb_ops audio_urb_ops[2] = { 634static struct snd_urb_ops audio_urb_ops[2] = {
624 { 635 {
625 .prepare = prepare_startup_playback_urb, 636 .prepare = prepare_nodata_playback_urb,
626 .retire = retire_playback_urb, 637 .retire = retire_playback_urb,
627 .prepare_sync = prepare_playback_sync_urb, 638 .prepare_sync = prepare_playback_sync_urb,
628 .retire_sync = retire_playback_sync_urb, 639 .retire_sync = retire_playback_sync_urb,
@@ -637,7 +648,7 @@ static struct snd_urb_ops audio_urb_ops[2] = {
637 648
638static struct snd_urb_ops audio_urb_ops_high_speed[2] = { 649static struct snd_urb_ops audio_urb_ops_high_speed[2] = {
639 { 650 {
640 .prepare = prepare_startup_playback_urb, 651 .prepare = prepare_nodata_playback_urb,
641 .retire = retire_playback_urb, 652 .retire = retire_playback_urb,
642 .prepare_sync = prepare_playback_sync_urb_hs, 653 .prepare_sync = prepare_playback_sync_urb_hs,
643 .retire_sync = retire_playback_sync_urb_hs, 654 .retire_sync = retire_playback_sync_urb_hs,
@@ -655,7 +666,7 @@ static struct snd_urb_ops audio_urb_ops_high_speed[2] = {
655 */ 666 */
656static void snd_complete_urb(struct urb *urb) 667static void snd_complete_urb(struct urb *urb)
657{ 668{
658 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 669 struct snd_urb_ctx *ctx = urb->context;
659 struct snd_usb_substream *subs = ctx->subs; 670 struct snd_usb_substream *subs = ctx->subs;
660 struct snd_pcm_substream *substream = ctx->subs->pcm_substream; 671 struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
661 int err = 0; 672 int err = 0;
@@ -678,7 +689,7 @@ static void snd_complete_urb(struct urb *urb)
678 */ 689 */
679static void snd_complete_sync_urb(struct urb *urb) 690static void snd_complete_sync_urb(struct urb *urb)
680{ 691{
681 struct snd_urb_ctx *ctx = (struct snd_urb_ctx *)urb->context; 692 struct snd_urb_ctx *ctx = urb->context;
682 struct snd_usb_substream *subs = ctx->subs; 693 struct snd_usb_substream *subs = ctx->subs;
683 struct snd_pcm_substream *substream = ctx->subs->pcm_substream; 694 struct snd_pcm_substream *substream = ctx->subs->pcm_substream;
684 int err = 0; 695 int err = 0;
@@ -925,10 +936,14 @@ static int snd_usb_pcm_playback_trigger(struct snd_pcm_substream *substream,
925 936
926 switch (cmd) { 937 switch (cmd) {
927 case SNDRV_PCM_TRIGGER_START: 938 case SNDRV_PCM_TRIGGER_START:
939 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
928 subs->ops.prepare = prepare_playback_urb; 940 subs->ops.prepare = prepare_playback_urb;
929 return 0; 941 return 0;
930 case SNDRV_PCM_TRIGGER_STOP: 942 case SNDRV_PCM_TRIGGER_STOP:
931 return deactivate_urbs(subs, 0, 0); 943 return deactivate_urbs(subs, 0, 0);
944 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
945 subs->ops.prepare = prepare_nodata_playback_urb;
946 return 0;
932 default: 947 default:
933 return -EINVAL; 948 return -EINVAL;
934 } 949 }
@@ -944,9 +959,16 @@ static int snd_usb_pcm_capture_trigger(struct snd_pcm_substream *substream,
944 959
945 switch (cmd) { 960 switch (cmd) {
946 case SNDRV_PCM_TRIGGER_START: 961 case SNDRV_PCM_TRIGGER_START:
962 subs->ops.retire = retire_capture_urb;
947 return start_urbs(subs, substream->runtime); 963 return start_urbs(subs, substream->runtime);
948 case SNDRV_PCM_TRIGGER_STOP: 964 case SNDRV_PCM_TRIGGER_STOP:
949 return deactivate_urbs(subs, 0, 0); 965 return deactivate_urbs(subs, 0, 0);
966 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
967 subs->ops.retire = retire_paused_capture_urb;
968 return 0;
969 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
970 subs->ops.retire = retire_capture_urb;
971 return 0;
950 default: 972 default:
951 return -EINVAL; 973 return -EINVAL;
952 } 974 }
@@ -1408,7 +1430,7 @@ static int set_format(struct snd_usb_substream *subs, struct audioformat *fmt)
1408static int snd_usb_hw_params(struct snd_pcm_substream *substream, 1430static int snd_usb_hw_params(struct snd_pcm_substream *substream,
1409 struct snd_pcm_hw_params *hw_params) 1431 struct snd_pcm_hw_params *hw_params)
1410{ 1432{
1411 struct snd_usb_substream *subs = (struct snd_usb_substream *)substream->runtime->private_data; 1433 struct snd_usb_substream *subs = substream->runtime->private_data;
1412 struct audioformat *fmt; 1434 struct audioformat *fmt;
1413 unsigned int channels, rate, format; 1435 unsigned int channels, rate, format;
1414 int ret, changed; 1436 int ret, changed;
@@ -1464,7 +1486,7 @@ static int snd_usb_hw_params(struct snd_pcm_substream *substream,
1464 */ 1486 */
1465static int snd_usb_hw_free(struct snd_pcm_substream *substream) 1487static int snd_usb_hw_free(struct snd_pcm_substream *substream)
1466{ 1488{
1467 struct snd_usb_substream *subs = (struct snd_usb_substream *)substream->runtime->private_data; 1489 struct snd_usb_substream *subs = substream->runtime->private_data;
1468 1490
1469 subs->cur_audiofmt = NULL; 1491 subs->cur_audiofmt = NULL;
1470 subs->cur_rate = 0; 1492 subs->cur_rate = 0;
@@ -1505,33 +1527,20 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
1505 /* for playback, submit the URBs now; otherwise, the first hwptr_done 1527 /* for playback, submit the URBs now; otherwise, the first hwptr_done
1506 * updates for all URBs would happen at the same time when starting */ 1528 * updates for all URBs would happen at the same time when starting */
1507 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) { 1529 if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK) {
1508 subs->ops.prepare = prepare_startup_playback_urb; 1530 subs->ops.prepare = prepare_nodata_playback_urb;
1509 return start_urbs(subs, runtime); 1531 return start_urbs(subs, runtime);
1510 } else 1532 } else
1511 return 0; 1533 return 0;
1512} 1534}
1513 1535
1514static struct snd_pcm_hardware snd_usb_playback = 1536static struct snd_pcm_hardware snd_usb_hardware =
1515{ 1537{
1516 .info = SNDRV_PCM_INFO_MMAP | 1538 .info = SNDRV_PCM_INFO_MMAP |
1517 SNDRV_PCM_INFO_MMAP_VALID | 1539 SNDRV_PCM_INFO_MMAP_VALID |
1518 SNDRV_PCM_INFO_BATCH | 1540 SNDRV_PCM_INFO_BATCH |
1519 SNDRV_PCM_INFO_INTERLEAVED | 1541 SNDRV_PCM_INFO_INTERLEAVED |
1520 SNDRV_PCM_INFO_BLOCK_TRANSFER, 1542 SNDRV_PCM_INFO_BLOCK_TRANSFER |
1521 .buffer_bytes_max = 1024 * 1024, 1543 SNDRV_PCM_INFO_PAUSE,
1522 .period_bytes_min = 64,
1523 .period_bytes_max = 512 * 1024,
1524 .periods_min = 2,
1525 .periods_max = 1024,
1526};
1527
1528static struct snd_pcm_hardware snd_usb_capture =
1529{
1530 .info = SNDRV_PCM_INFO_MMAP |
1531 SNDRV_PCM_INFO_MMAP_VALID |
1532 SNDRV_PCM_INFO_BATCH |
1533 SNDRV_PCM_INFO_INTERLEAVED |
1534 SNDRV_PCM_INFO_BLOCK_TRANSFER,
1535 .buffer_bytes_max = 1024 * 1024, 1544 .buffer_bytes_max = 1024 * 1024,
1536 .period_bytes_min = 64, 1545 .period_bytes_min = 64,
1537 .period_bytes_max = 512 * 1024, 1546 .period_bytes_max = 512 * 1024,
@@ -1810,28 +1819,33 @@ static int check_hw_params_convention(struct snd_usb_substream *subs)
1810static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime, 1819static int snd_usb_pcm_check_knot(struct snd_pcm_runtime *runtime,
1811 struct snd_usb_substream *subs) 1820 struct snd_usb_substream *subs)
1812{ 1821{
1813 struct list_head *p; 1822 struct audioformat *fp;
1814 struct snd_pcm_hw_constraint_list constraints_rates; 1823 int count = 0, needs_knot = 0;
1815 int err; 1824 int err;
1816 1825
1817 list_for_each(p, &subs->fmt_list) { 1826 list_for_each_entry(fp, &subs->fmt_list, list) {
1818 struct audioformat *fp; 1827 if (fp->rates & SNDRV_PCM_RATE_CONTINUOUS)
1819 fp = list_entry(p, struct audioformat, list); 1828 return 0;
1820 1829 count += fp->nr_rates;
1821 if (!fp->needs_knot) 1830 if (fp->needs_knot)
1822 continue; 1831 needs_knot = 1;
1823
1824 constraints_rates.count = fp->nr_rates;
1825 constraints_rates.list = fp->rate_table;
1826 constraints_rates.mask = 0;
1827
1828 err = snd_pcm_hw_constraint_list(runtime, 0,
1829 SNDRV_PCM_HW_PARAM_RATE,
1830 &constraints_rates);
1831
1832 if (err < 0)
1833 return err;
1834 } 1832 }
1833 if (!needs_knot)
1834 return 0;
1835
1836 subs->rate_list.count = count;
1837 subs->rate_list.list = kmalloc(sizeof(int) * count, GFP_KERNEL);
1838 subs->rate_list.mask = 0;
1839 count = 0;
1840 list_for_each_entry(fp, &subs->fmt_list, list) {
1841 int i;
1842 for (i = 0; i < fp->nr_rates; i++)
1843 subs->rate_list.list[count++] = fp->rate_table[i];
1844 }
1845 err = snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
1846 &subs->rate_list);
1847 if (err < 0)
1848 return err;
1835 1849
1836 return 0; 1850 return 0;
1837} 1851}
@@ -1904,8 +1918,7 @@ static int setup_hw_info(struct snd_pcm_runtime *runtime, struct snd_usb_substre
1904 return 0; 1918 return 0;
1905} 1919}
1906 1920
1907static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction, 1921static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction)
1908 struct snd_pcm_hardware *hw)
1909{ 1922{
1910 struct snd_usb_stream *as = snd_pcm_substream_chip(substream); 1923 struct snd_usb_stream *as = snd_pcm_substream_chip(substream);
1911 struct snd_pcm_runtime *runtime = substream->runtime; 1924 struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1913,7 +1926,7 @@ static int snd_usb_pcm_open(struct snd_pcm_substream *substream, int direction,
1913 1926
1914 subs->interface = -1; 1927 subs->interface = -1;
1915 subs->format = 0; 1928 subs->format = 0;
1916 runtime->hw = *hw; 1929 runtime->hw = snd_usb_hardware;
1917 runtime->private_data = subs; 1930 runtime->private_data = subs;
1918 subs->pcm_substream = substream; 1931 subs->pcm_substream = substream;
1919 return setup_hw_info(runtime, subs); 1932 return setup_hw_info(runtime, subs);
@@ -1934,7 +1947,7 @@ static int snd_usb_pcm_close(struct snd_pcm_substream *substream, int direction)
1934 1947
1935static int snd_usb_playback_open(struct snd_pcm_substream *substream) 1948static int snd_usb_playback_open(struct snd_pcm_substream *substream)
1936{ 1949{
1937 return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK, &snd_usb_playback); 1950 return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_PLAYBACK);
1938} 1951}
1939 1952
1940static int snd_usb_playback_close(struct snd_pcm_substream *substream) 1953static int snd_usb_playback_close(struct snd_pcm_substream *substream)
@@ -1944,7 +1957,7 @@ static int snd_usb_playback_close(struct snd_pcm_substream *substream)
1944 1957
1945static int snd_usb_capture_open(struct snd_pcm_substream *substream) 1958static int snd_usb_capture_open(struct snd_pcm_substream *substream)
1946{ 1959{
1947 return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE, &snd_usb_capture); 1960 return snd_usb_pcm_open(substream, SNDRV_PCM_STREAM_CAPTURE);
1948} 1961}
1949 1962
1950static int snd_usb_capture_close(struct snd_pcm_substream *substream) 1963static int snd_usb_capture_close(struct snd_pcm_substream *substream)
@@ -2231,6 +2244,7 @@ static void free_substream(struct snd_usb_substream *subs)
2231 kfree(fp->rate_table); 2244 kfree(fp->rate_table);
2232 kfree(fp); 2245 kfree(fp);
2233 } 2246 }
2247 kfree(subs->rate_list.list);
2234} 2248}
2235 2249
2236 2250
@@ -2456,6 +2470,7 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
2456 * build the rate table and bitmap flags 2470 * build the rate table and bitmap flags
2457 */ 2471 */
2458 int r, idx, c; 2472 int r, idx, c;
2473 unsigned int nonzero_rates = 0;
2459 /* this table corresponds to the SNDRV_PCM_RATE_XXX bit */ 2474 /* this table corresponds to the SNDRV_PCM_RATE_XXX bit */
2460 static unsigned int conv_rates[] = { 2475 static unsigned int conv_rates[] = {
2461 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000, 2476 5512, 8000, 11025, 16000, 22050, 32000, 44100, 48000,
@@ -2478,6 +2493,7 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
2478 fp->altsetting == 5 && fp->maxpacksize == 392) 2493 fp->altsetting == 5 && fp->maxpacksize == 392)
2479 rate = 96000; 2494 rate = 96000;
2480 fp->rate_table[r] = rate; 2495 fp->rate_table[r] = rate;
2496 nonzero_rates |= rate;
2481 if (rate < fp->rate_min) 2497 if (rate < fp->rate_min)
2482 fp->rate_min = rate; 2498 fp->rate_min = rate;
2483 else if (rate > fp->rate_max) 2499 else if (rate > fp->rate_max)
@@ -2493,6 +2509,10 @@ static int parse_audio_format_rates(struct snd_usb_audio *chip, struct audioform
2493 if (!found) 2509 if (!found)
2494 fp->needs_knot = 1; 2510 fp->needs_knot = 1;
2495 } 2511 }
2512 if (!nonzero_rates) {
2513 hwc_debug("All rates were zero. Skipping format!\n");
2514 return -1;
2515 }
2496 if (fp->needs_knot) 2516 if (fp->needs_knot)
2497 fp->rates |= SNDRV_PCM_RATE_KNOT; 2517 fp->rates |= SNDRV_PCM_RATE_KNOT;
2498 } else { 2518 } else {
@@ -3057,6 +3077,58 @@ static int create_ua1000_quirk(struct snd_usb_audio *chip,
3057 return 0; 3077 return 0;
3058} 3078}
3059 3079
3080/*
3081 * Create a stream for an Edirol UA-101 interface.
3082 * Copy, paste and modify from Edirol UA-1000
3083 */
3084static int create_ua101_quirk(struct snd_usb_audio *chip,
3085 struct usb_interface *iface,
3086 const struct snd_usb_audio_quirk *quirk)
3087{
3088 static const struct audioformat ua101_format = {
3089 .format = SNDRV_PCM_FORMAT_S32_LE,
3090 .fmt_type = USB_FORMAT_TYPE_I,
3091 .altsetting = 1,
3092 .altset_idx = 1,
3093 .attributes = 0,
3094 .rates = SNDRV_PCM_RATE_CONTINUOUS,
3095 };
3096 struct usb_host_interface *alts;
3097 struct usb_interface_descriptor *altsd;
3098 struct audioformat *fp;
3099 int stream, err;
3100
3101 if (iface->num_altsetting != 2)
3102 return -ENXIO;
3103 alts = &iface->altsetting[1];
3104 altsd = get_iface_desc(alts);
3105 if (alts->extralen != 18 || alts->extra[1] != USB_DT_CS_INTERFACE ||
3106 altsd->bNumEndpoints != 1)
3107 return -ENXIO;
3108
3109 fp = kmemdup(&ua101_format, sizeof(*fp), GFP_KERNEL);
3110 if (!fp)
3111 return -ENOMEM;
3112
3113 fp->channels = alts->extra[11];
3114 fp->iface = altsd->bInterfaceNumber;
3115 fp->endpoint = get_endpoint(alts, 0)->bEndpointAddress;
3116 fp->ep_attr = get_endpoint(alts, 0)->bmAttributes;
3117 fp->maxpacksize = le16_to_cpu(get_endpoint(alts, 0)->wMaxPacketSize);
3118 fp->rate_max = fp->rate_min = combine_triple(&alts->extra[15]);
3119
3120 stream = (fp->endpoint & USB_DIR_IN)
3121 ? SNDRV_PCM_STREAM_CAPTURE : SNDRV_PCM_STREAM_PLAYBACK;
3122 err = add_audio_endpoint(chip, stream, fp);
3123 if (err < 0) {
3124 kfree(fp);
3125 return err;
3126 }
3127 /* FIXME: playback must be synchronized to capture */
3128 usb_set_interface(chip->dev, fp->iface, 0);
3129 return 0;
3130}
3131
3060static int snd_usb_create_quirk(struct snd_usb_audio *chip, 3132static int snd_usb_create_quirk(struct snd_usb_audio *chip,
3061 struct usb_interface *iface, 3133 struct usb_interface *iface,
3062 const struct snd_usb_audio_quirk *quirk); 3134 const struct snd_usb_audio_quirk *quirk);
@@ -3238,6 +3310,7 @@ static int snd_usb_create_quirk(struct snd_usb_audio *chip,
3238 [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk, 3310 [QUIRK_AUDIO_FIXED_ENDPOINT] = create_fixed_stream_quirk,
3239 [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk, 3311 [QUIRK_AUDIO_EDIROL_UA700_UA25] = create_ua700_ua25_quirk,
3240 [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk, 3312 [QUIRK_AUDIO_EDIROL_UA1000] = create_ua1000_quirk,
3313 [QUIRK_AUDIO_EDIROL_UA101] = create_ua101_quirk,
3241 }; 3314 };
3242 3315
3243 if (quirk->type < QUIRK_TYPE_COUNT) { 3316 if (quirk->type < QUIRK_TYPE_COUNT) {
diff --git a/sound/usb/usbaudio.h b/sound/usb/usbaudio.h
index 0f4b2b8541d6..2272f45a1867 100644
--- a/sound/usb/usbaudio.h
+++ b/sound/usb/usbaudio.h
@@ -159,6 +159,7 @@ enum quirk_type {
159 QUIRK_AUDIO_FIXED_ENDPOINT, 159 QUIRK_AUDIO_FIXED_ENDPOINT,
160 QUIRK_AUDIO_EDIROL_UA700_UA25, 160 QUIRK_AUDIO_EDIROL_UA700_UA25,
161 QUIRK_AUDIO_EDIROL_UA1000, 161 QUIRK_AUDIO_EDIROL_UA1000,
162 QUIRK_AUDIO_EDIROL_UA101,
162 163
163 QUIRK_TYPE_COUNT 164 QUIRK_TYPE_COUNT
164}; 165};
diff --git a/sound/usb/usbquirks.h b/sound/usb/usbquirks.h
index a7e9563a01df..25b4ab4f61e7 100644
--- a/sound/usb/usbquirks.h
+++ b/sound/usb/usbquirks.h
@@ -1098,7 +1098,37 @@ YAMAHA_DEVICE(0x7010, "UB99"),
1098 } 1098 }
1099 } 1099 }
1100}, 1100},
1101 /* TODO: add Edirol UA-101 support */ 1101/* Roland UA-101 in High-Speed Mode only */
1102{
1103 USB_DEVICE(0x0582, 0x007d),
1104 .driver_info = (unsigned long) & (const struct snd_usb_audio_quirk) {
1105 .vendor_name = "Roland",
1106 .product_name = "UA-101",
1107 .ifnum = QUIRK_ANY_INTERFACE,
1108 .type = QUIRK_COMPOSITE,
1109 .data = (const struct snd_usb_audio_quirk[]) {
1110 {
1111 .ifnum = 0,
1112 .type = QUIRK_AUDIO_EDIROL_UA101
1113 },
1114 {
1115 .ifnum = 1,
1116 .type = QUIRK_AUDIO_EDIROL_UA101
1117 },
1118 {
1119 .ifnum = 2,
1120 .type = QUIRK_MIDI_FIXED_ENDPOINT,
1121 .data = & (const struct snd_usb_midi_endpoint_info) {
1122 .out_cables = 0x0001,
1123 .in_cables = 0x0001
1124 }
1125 },
1126 {
1127 .ifnum = -1
1128 }
1129 }
1130 }
1131},
1102{ 1132{
1103 /* has ID 0x0081 when not in "Advanced Driver" mode */ 1133 /* has ID 0x0081 when not in "Advanced Driver" mode */
1104 USB_DEVICE(0x0582, 0x0080), 1134 USB_DEVICE(0x0582, 0x0080),