summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStephen Rothwell <sfr@canb.auug.org.au>2008-12-10 16:20:14 +1100
committerStephen Rothwell <sfr@canb.auug.org.au>2008-12-10 16:20:14 +1100
commitc4f764d8782dc4591068827d332f386eb95ce078 (patch)
treee45c6091f0dfe4ffd85346bf6b0cdb5aedec0fc7
parent95e22584496e9e6eb1628ffc5d7448f1d45090f7 (diff)
Revert "Merge commit 'sound/for-next'"
This reverts commit f55a178f9de332704d5c386b7403f006fde8646e.
-rw-r--r--Documentation/sound/alsa/ALSA-Configuration.txt25
-rw-r--r--Documentation/sound/alsa/HD-Audio.txt535
-rw-r--r--Documentation/sound/alsa/Procfile.txt10
-rw-r--r--Documentation/sound/alsa/soc/machine.txt8
-rw-r--r--MAINTAINERS2
-rw-r--r--arch/arm/mach-pxa/include/mach/palmasoc.h13
-rw-r--r--include/linux/input.h1
-rw-r--r--include/sound/asound.h1
-rw-r--r--include/sound/core.h28
-rw-r--r--include/sound/info.h106
-rw-r--r--include/sound/jack.h1
-rw-r--r--include/sound/l3.h18
-rw-r--r--include/sound/s3c24xx_uda134x.h14
-rw-r--r--include/sound/soc-dai.h231
-rw-r--r--include/sound/soc-dapm.h2
-rw-r--r--include/sound/soc.h201
-rw-r--r--include/sound/uda134x.h26
-rw-r--r--include/sound/version.h2
-rw-r--r--sound/ac97_bus.c1
-rw-r--r--sound/aoa/codecs/Makefile4
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-onyx.c (renamed from sound/aoa/codecs/onyx.c)12
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-onyx.h (renamed from sound/aoa/codecs/onyx.h)0
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h (renamed from sound/aoa/codecs/tas-basstreble.h)0
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h (renamed from sound/aoa/codecs/tas-gain-table.h)0
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.c (renamed from sound/aoa/codecs/tas.c)8
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-tas.h (renamed from sound/aoa/codecs/tas.h)0
-rw-r--r--sound/aoa/codecs/snd-aoa-codec-toonie.c (renamed from sound/aoa/codecs/toonie.c)2
-rw-r--r--sound/aoa/core/Makefile8
-rw-r--r--sound/aoa/core/snd-aoa-alsa.c (renamed from sound/aoa/core/alsa.c)4
-rw-r--r--sound/aoa/core/snd-aoa-alsa.h (renamed from sound/aoa/core/alsa.h)0
-rw-r--r--sound/aoa/core/snd-aoa-core.c (renamed from sound/aoa/core/core.c)2
-rw-r--r--sound/aoa/core/snd-aoa-gpio-feature.c (renamed from sound/aoa/core/gpio-feature.c)2
-rw-r--r--sound/aoa/core/snd-aoa-gpio-pmf.c (renamed from sound/aoa/core/gpio-pmf.c)0
-rw-r--r--sound/aoa/fabrics/Makefile2
-rw-r--r--sound/aoa/fabrics/snd-aoa-fabric-layout.c (renamed from sound/aoa/fabrics/layout.c)2
-rw-r--r--sound/aoa/soundbus/i2sbus/Makefile2
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-control.c (renamed from sound/aoa/soundbus/i2sbus/control.c)0
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-core.c (renamed from sound/aoa/soundbus/i2sbus/core.c)4
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-interface.h (renamed from sound/aoa/soundbus/i2sbus/interface.h)0
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus-pcm.c (renamed from sound/aoa/soundbus/i2sbus/pcm.c)0
-rw-r--r--sound/aoa/soundbus/i2sbus/i2sbus.h2
-rw-r--r--sound/core/Kconfig21
-rw-r--r--sound/core/Makefile2
-rw-r--r--sound/core/device.c4
-rw-r--r--sound/core/hrtimer.c155
-rw-r--r--sound/core/info.c17
-rw-r--r--sound/core/init.c71
-rw-r--r--sound/core/jack.c9
-rw-r--r--sound/core/seq/seq.c4
-rw-r--r--sound/drivers/Kconfig2
-rw-r--r--sound/drivers/pcsp/pcsp.c8
-rw-r--r--sound/drivers/pcsp/pcsp.h3
-rw-r--r--sound/drivers/pcsp/pcsp_lib.c168
-rw-r--r--sound/pci/Kconfig127
-rw-r--r--sound/pci/ac97/ac97_codec.c2
-rw-r--r--sound/pci/ac97/ac97_patch.c2
-rw-r--r--sound/pci/ca0106/ca0106.h15
-rw-r--r--sound/pci/ca0106/ca0106_main.c519
-rw-r--r--sound/pci/ca0106/ca0106_mixer.c182
-rw-r--r--sound/pci/cs46xx/cs46xx_lib.c5
-rw-r--r--sound/pci/emu10k1/emu10k1_main.c494
-rw-r--r--sound/pci/emu10k1/emumixer.c46
-rw-r--r--sound/pci/hda/Kconfig188
-rw-r--r--sound/pci/hda/Makefile75
-rw-r--r--sound/pci/hda/hda_beep.c2
-rw-r--r--sound/pci/hda/hda_codec.c773
-rw-r--r--sound/pci/hda/hda_codec.h105
-rw-r--r--sound/pci/hda/hda_eld.c590
-rw-r--r--sound/pci/hda/hda_generic.c21
-rw-r--r--sound/pci/hda/hda_hwdep.c234
-rw-r--r--sound/pci/hda/hda_intel.c338
-rw-r--r--sound/pci/hda/hda_local.h100
-rw-r--r--sound/pci/hda/hda_patch.h22
-rw-r--r--sound/pci/hda/hda_proc.c91
-rw-r--r--sound/pci/hda/patch_analog.c131
-rw-r--r--sound/pci/hda/patch_atihdmi.c32
-rw-r--r--sound/pci/hda/patch_cmedia.c27
-rw-r--r--sound/pci/hda/patch_conexant.c39
-rw-r--r--sound/pci/hda/patch_intelhdmi.c711
-rw-r--r--sound/pci/hda/patch_nvhdmi.c28
-rw-r--r--sound/pci/hda/patch_realtek.c1663
-rw-r--r--sound/pci/hda/patch_si3054.c35
-rw-r--r--sound/pci/hda/patch_sigmatel.c780
-rw-r--r--sound/pci/hda/patch_via.c99
-rw-r--r--sound/pci/ice1712/ice1724.c23
-rw-r--r--sound/pci/mixart/mixart.c4
-rw-r--r--sound/pci/oxygen/oxygen.c4
-rw-r--r--sound/pci/pcxhr/Makefile2
-rw-r--r--sound/pci/pcxhr/pcxhr.c556
-rw-r--r--sound/pci/pcxhr/pcxhr.h76
-rw-r--r--sound/pci/pcxhr/pcxhr_core.c291
-rw-r--r--sound/pci/pcxhr/pcxhr_core.h5
-rw-r--r--sound/pci/pcxhr/pcxhr_hwdep.c158
-rw-r--r--sound/pci/pcxhr/pcxhr_mix22.c820
-rw-r--r--sound/pci/pcxhr/pcxhr_mix22.h56
-rw-r--r--sound/pci/pcxhr/pcxhr_mixer.c556
-rw-r--r--sound/pci/riptide/riptide.c2
-rw-r--r--sound/pci/rme9652/hdsp.c2
-rw-r--r--sound/pci/rme9652/hdspm.c2
-rw-r--r--sound/ppc/pmac.c2
-rw-r--r--sound/ppc/tumbler.c3
-rw-r--r--sound/soc/Kconfig3
-rw-r--r--sound/soc/Makefile2
-rw-r--r--sound/soc/at32/Kconfig34
-rw-r--r--sound/soc/at32/Makefile11
-rw-r--r--sound/soc/at32/at32-pcm.c492
-rw-r--r--sound/soc/at32/at32-pcm.h79
-rw-r--r--sound/soc/at32/at32-ssc.c849
-rw-r--r--sound/soc/at32/at32-ssc.h59
-rw-r--r--sound/soc/at32/playpaq_wm8510.c (renamed from sound/soc/atmel/playpaq_wm8510.c)11
-rw-r--r--sound/soc/at91/Kconfig10
-rw-r--r--sound/soc/at91/Makefile6
-rw-r--r--sound/soc/at91/at91-pcm.c434
-rw-r--r--sound/soc/at91/at91-pcm.h72
-rw-r--r--sound/soc/at91/at91-ssc.c791
-rw-r--r--sound/soc/at91/at91-ssc.h27
-rw-r--r--sound/soc/atmel/Kconfig43
-rw-r--r--sound/soc/atmel/Makefile15
-rw-r--r--sound/soc/atmel/atmel-pcm.c494
-rw-r--r--sound/soc/atmel/atmel-pcm.h86
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.c790
-rw-r--r--sound/soc/atmel/atmel_ssc_dai.h121
-rw-r--r--sound/soc/atmel/sam9g20_wm8731.c328
-rw-r--r--sound/soc/au1x/dbdma2.c3
-rw-r--r--sound/soc/au1x/psc-ac97.c16
-rw-r--r--sound/soc/au1x/psc-i2s.c18
-rw-r--r--sound/soc/au1x/sample-ac97.c4
-rw-r--r--sound/soc/blackfin/Kconfig22
-rw-r--r--sound/soc/blackfin/bf5xx-ac97-pcm.c113
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.c178
-rw-r--r--sound/soc/blackfin/bf5xx-ac97.h35
-rw-r--r--sound/soc/blackfin/bf5xx-ad1980.c8
-rw-r--r--sound/soc/blackfin/bf5xx-ad73311.c10
-rw-r--r--sound/soc/blackfin/bf5xx-i2s-pcm.c12
-rw-r--r--sound/soc/blackfin/bf5xx-i2s.c31
-rw-r--r--sound/soc/blackfin/bf5xx-sport.h2
-rw-r--r--sound/soc/blackfin/bf5xx-ssm2602.c14
-rw-r--r--sound/soc/codecs/Kconfig65
-rw-r--r--sound/soc/codecs/Makefile10
-rw-r--r--sound/soc/codecs/ac97.c7
-rw-r--r--sound/soc/codecs/ad1980.c24
-rw-r--r--sound/soc/codecs/ad73311.c18
-rw-r--r--sound/soc/codecs/ak4535.c19
-rw-r--r--sound/soc/codecs/cs4270.c38
-rw-r--r--sound/soc/codecs/l3.c91
-rw-r--r--sound/soc/codecs/pcm3008.c212
-rw-r--r--sound/soc/codecs/pcm3008.h25
-rw-r--r--sound/soc/codecs/ssm2602.c53
-rw-r--r--sound/soc/codecs/tlv320aic23.c260
-rw-r--r--sound/soc/codecs/tlv320aic26.c22
-rw-r--r--sound/soc/codecs/tlv320aic3x.c162
-rw-r--r--sound/soc/codecs/tlv320aic3x.h58
-rw-r--r--sound/soc/codecs/twl4030.c1292
-rw-r--r--sound/soc/codecs/twl4030.h213
-rw-r--r--sound/soc/codecs/uda134x.c668
-rw-r--r--sound/soc/codecs/uda134x.h36
-rw-r--r--sound/soc/codecs/uda1380.c29
-rw-r--r--sound/soc/codecs/wm8510.c19
-rw-r--r--sound/soc/codecs/wm8580.c134
-rw-r--r--sound/soc/codecs/wm8580.h1
-rw-r--r--sound/soc/codecs/wm8728.c585
-rw-r--r--sound/soc/codecs/wm8728.h30
-rw-r--r--sound/soc/codecs/wm8731.c25
-rw-r--r--sound/soc/codecs/wm8750.c19
-rw-r--r--sound/soc/codecs/wm8753.c39
-rw-r--r--sound/soc/codecs/wm8900.c139
-rw-r--r--sound/soc/codecs/wm8900.h1
-rw-r--r--sound/soc/codecs/wm8903.c33
-rw-r--r--sound/soc/codecs/wm8971.c19
-rw-r--r--sound/soc/codecs/wm8990.c43
-rw-r--r--sound/soc/codecs/wm8990.h4
-rw-r--r--sound/soc/codecs/wm9712.c12
-rw-r--r--sound/soc/codecs/wm9713.c46
-rw-r--r--sound/soc/davinci/Kconfig10
-rw-r--r--sound/soc/davinci/Makefile2
-rw-r--r--sound/soc/davinci/davinci-evm.c6
-rw-r--r--sound/soc/davinci/davinci-i2s.c153
-rw-r--r--sound/soc/davinci/davinci-pcm.c12
-rw-r--r--sound/soc/davinci/davinci-sffsdr.c157
-rw-r--r--sound/soc/fsl/Kconfig2
-rw-r--r--sound/soc/fsl/fsl_dma.c14
-rw-r--r--sound/soc/fsl/fsl_ssi.c24
-rw-r--r--sound/soc/fsl/mpc5200_psc_i2s.c22
-rw-r--r--sound/soc/fsl/mpc8610_hpcd.c8
-rw-r--r--sound/soc/fsl/soc-of-simple.c12
-rw-r--r--sound/soc/omap/Kconfig35
-rw-r--r--sound/soc/omap/Makefile8
-rw-r--r--sound/soc/omap/n810.c10
-rw-r--r--sound/soc/omap/omap-mcbsp.c57
-rw-r--r--sound/soc/omap/omap-pcm.c12
-rw-r--r--sound/soc/omap/omap2evm.c151
-rw-r--r--sound/soc/omap/omap3beagle.c149
-rw-r--r--sound/soc/omap/omap3pandora.c311
-rw-r--r--sound/soc/omap/osk5912.c6
-rw-r--r--sound/soc/omap/overo.c148
-rw-r--r--sound/soc/omap/sdp3430.c152
-rw-r--r--sound/soc/pxa/Kconfig22
-rw-r--r--sound/soc/pxa/Makefile6
-rw-r--r--sound/soc/pxa/corgi.c12
-rw-r--r--sound/soc/pxa/e800_wm9712.c8
-rw-r--r--sound/soc/pxa/em-x270.c7
-rw-r--r--sound/soc/pxa/palm27x.c269
-rw-r--r--sound/soc/pxa/poodle.c6
-rw-r--r--sound/soc/pxa/pxa-ssp.c931
-rw-r--r--sound/soc/pxa/pxa-ssp.h47
-rw-r--r--sound/soc/pxa/pxa2xx-ac97.c33
-rw-r--r--sound/soc/pxa/pxa2xx-i2s.c35
-rw-r--r--sound/soc/pxa/pxa2xx-pcm.c14
-rw-r--r--sound/soc/pxa/spitz.c6
-rw-r--r--sound/soc/pxa/tosa.c38
-rw-r--r--sound/soc/pxa/zylonite.c219
-rw-r--r--sound/soc/s3c24xx/Kconfig5
-rw-r--r--sound/soc/s3c24xx/Makefile2
-rw-r--r--sound/soc/s3c24xx/ln2440sbc_alc650.c8
-rw-r--r--sound/soc/s3c24xx/neo1973_wm8753.c9
-rw-r--r--sound/soc/s3c24xx/s3c2412-i2s.c38
-rw-r--r--sound/soc/s3c24xx/s3c2443-ac97.c28
-rw-r--r--sound/soc/s3c24xx/s3c24xx-i2s.c35
-rw-r--r--sound/soc/s3c24xx/s3c24xx-pcm.c12
-rw-r--r--sound/soc/s3c24xx/s3c24xx_uda134x.c373
-rw-r--r--sound/soc/s3c24xx/smdk2443_wm9710.c8
-rw-r--r--sound/soc/sh/dma-sh7760.c12
-rw-r--r--sound/soc/sh/hac.c19
-rw-r--r--sound/soc/sh/sh7760-ac97.c6
-rw-r--r--sound/soc/sh/ssi.c30
-rw-r--r--sound/soc/soc-core.c795
-rw-r--r--sound/soc/soc-dapm.c76
-rw-r--r--sound/usb/caiaq/caiaq-control.c73
-rw-r--r--sound/usb/caiaq/caiaq-device.c2
229 files changed, 7077 insertions, 19023 deletions
diff --git a/Documentation/sound/alsa/ALSA-Configuration.txt b/Documentation/sound/alsa/ALSA-Configuration.txt
index 83d3a562fe86..3cd2ad958176 100644
--- a/Documentation/sound/alsa/ALSA-Configuration.txt
+++ b/Documentation/sound/alsa/ALSA-Configuration.txt
@@ -778,8 +778,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
specify a certain model in such a case. There are different
models depending on the codec chip.
- See Documentation/sound/alsa/HD-Audio.txt for some details.
-
Model name Description
---------- -----------
ALC880
@@ -846,7 +844,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
3stack 3-stack model
toshiba Toshiba A205
acer Acer laptops
- acer-dmic Acer laptops with digital-mic
acer-aspire Acer Aspire One
dell Dell OEM laptops (Vostro 1200)
zepto Zepto laptops
@@ -860,8 +857,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
quanta Quanta FL1
eeepc-p703 ASUS Eeepc P703 P900A
eeepc-p901 ASUS Eeepc P901 S101
- fujitsu FSC Amilo
- auto auto-config reading BIOS (default)
ALC662/663
3stack-dig 3-stack (2-channel) with SPDIF
@@ -905,7 +900,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
6stack-dig-demo 6-jack digital for Intel demo board
acer Acer laptops (Travelmate 3012WTMi, Aspire 5600, etc)
acer-aspire Acer Aspire 9810
- acer-aspire-4930g Acer Aspire 4930G
medion Medion Laptops
medion-md2 Medion MD2
targa-dig Targa/MSI
@@ -921,7 +915,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
mitac Mitac 8252D
clevo-m720 Clevo M720 laptop series
fujitsu-pi2515 Fujitsu AMILO Pi2515
- fujitsu-xa3530 Fujitsu AMILO XA3530
3stack-6ch-intel Intel DG33* boards
auto auto-config reading BIOS (default)
@@ -945,7 +938,6 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
lenovo Lenovo 3000 C200
dallas Dallas laptops
hp HP TX1000
- asus-v1s ASUS V1Sn
auto auto-config reading BIOS (default)
CMI9880
@@ -987,10 +979,9 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
6stack 6-jack, separate surrounds (default)
3stack 3-stack, shared surrounds
laptop 2-channel only (FSC V2060, Samsung M50)
- laptop-eapd 2-channel with EAPD (ASUS A6J)
+ laptop-eapd 2-channel with EAPD (Samsung R65, ASUS A6J)
laptop-automute 2-channel with EAPD and HP-automute (Lenovo N100)
ultra 2-channel with EAPD (Samsung Ultra tablet PC)
- samsung 2-channel with EAPD (Samsung R65)
AD1988/AD1988B/AD1989A/AD1989B
6stack 6-jack
@@ -1098,8 +1089,8 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
"codec-patch". It's sometimes good for testing and debugging.
If the default configuration doesn't work and one of the above
- matches with your device, report it together with alsa-info.sh
- output (with --no-upload option) to kernel bugzilla or alsa-devel
+ matches with your device, report it together with the PCI
+ subsystem ID (output of "lspci -nv") to ALSA BTS or alsa-devel
ML (see the section "Links and Addresses").
power_save and power_save_controller options are for power-saving
@@ -1659,8 +1650,7 @@ Prior to version 0.9.0rc4 options had a 'snd_' prefix. This was removed.
* AuzenTech X-Meridian
* Bgears b-Enspirer
* Club3D Theatron DTS
- * HT-Omega Claro (plus)
- * HT-Omega Claro halo (XT)
+ * HT-Omega Claro
* Razer Barracuda AC-1
* Sondigo Inferno
@@ -2417,11 +2407,8 @@ Links and Addresses
ALSA project homepage
http://www.alsa-project.org
- Kernel Bugzilla
- http://bugzilla.kernel.org/
+ ALSA Bug Tracking System
+ https://bugtrack.alsa-project.org/bugs/
ALSA Developers ML
mailto:alsa-devel@alsa-project.org
-
- alsa-info.sh script
- http://www.alsa-project.org/alsa-info.sh
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt
deleted file mode 100644
index e758f24017bf..000000000000
--- a/Documentation/sound/alsa/HD-Audio.txt
+++ /dev/null
@@ -1,535 +0,0 @@
-MORE NOTES ON HD-AUDIO DRIVER
-=============================
- Takashi Iwai <tiwai@suse.de>
-
-
-GENERAL
--------
-
-HD-audio is the new standard on-board audio component on modern PCs
-after AC97. Although Linux has been supporting HD-audio since long
-time ago, there are often problems with new machines. A part of the
-problem is broken BIOS, and rest is the driver implementation. This
-document explains the trouble-shooting and debugging methods for the
-HD-audio hardware.
-
-The HD-audio component consists of two parts: the controller chip and
-the codec chips on the HD-audio bus. Linux provides a single driver
-for all controllers, snd-hda-intel. Since the HD-audio controllers
-are supposed to be compatible, the single snd-hda-driver should work
-in most cases. But, not surprisingly, there are known bugs and issues
-specific to each controller type. The snd-hda-intel driver has a
-bunch of workarounds for these as described below.
-
-A controller may have multiple codecs. Usually you have one audio
-codec and optionally one modem codec. In some cases, there can be
-multiple audio codecs, e.g. for analog and digital outputs, but the
-driver might not work properly.
-
-The snd-hda-intel driver has several different codec parsers depending
-on the codec. It has a generic parser as a fallback, but this
-functionality is fairly limited until now. Instead of the generic
-parser, usually the codec-specific parser (coded in patch_*.c) is used
-for the codec-specific implementations. The details about the
-codec-specific problems are explained in the later sections.
-
-If you are interested in the deep debugging of HD-audio, read the
-HD-audio specification at first. The specification is found on
-Intel's web page, for example:
-
-- http://www.intel.com/standards/hdaudio/
-
-
-HD-AUDIO CONTROLLER
--------------------
-
-DMA-Position Problem
-~~~~~~~~~~~~~~~~~~~~
-The most common problem of the controller is the inaccurate DMA
-pointer reporting. The DMA pointer for playback and capture can be
-read in two ways, either via a LPIB register or via a position-buffer
-map. As default the driver tries to reads from the io-mapped
-position-buffer, and falls back to LPIB if it appears unupdated.
-However, this detection isn't perfect on some devices. In such a
-case, you can change the default method via `position_fix` option.
-
-`position_fix=1` means to use LPIB method explicitly.
-`position_fix=2` means to use the position-buffer. 0 is the default
-value, the automatic check. If you get a problem of repeated sounds,
-this option might help.
-
-In addition to that, every controller is known to be broken regarding
-the wake-up timing. It wakes up a few samples before actually
-processing the data on the buffer. This caused a lot of problems, for
-example, with ALSA dmix or JACK. Since 2.6.27 kernel, the driver puts
-an artificial delay to the wake up timing. This delay is controlled
-via `bdl_pos_adj` option.
-
-When `bdl_pos_adj` is a negative value (as default), it's assigned to
-an appropriate value depending on the controller chip. For Intel
-chip, it'd be 1 while it'd be 32 for others. Usually this works.
-Only in case it doesn't work and you get warning messages, you should
-change to other values.
-
-
-Codec-Probing Problem
-~~~~~~~~~~~~~~~~~~~~~
-A less often but a more severe problem is the codec probing. When
-BIOS reports the available codec slots wrongly, the driver gets
-confused and tries to access the non-existing codec slot. This often
-results in the total screw-up, and destruct the further communication
-with the codec chips. The symptom appears usually as the error
-message like:
-------------------------------------------------------------------------
- hda_intel: azx_get_response timeout, switching to polling mode: \
- last cmd=0x12345678
- hda_intel: azx_get_response timeout, switching to single_cmd mode: \
- last cmd=0x12345678
-------------------------------------------------------------------------
-
-The first line is a warning, and this is usually relatively harmless.
-It means that the codec response isn't notified via an IRQ. The
-driver uses explicit polling method to read the response. It gives
-very slight CPU overhead, but you'd unlikely notice it.
-
-The second line is, however, a fatal error. If this happens, usually
-it means that something is really wrong. Most likely you are
-accessing a non-existing codec slot.
-
-Thus, if the second error message appears, try to narrow the probed
-codec slots via `probe_mask` option. It's a bitmask, and each bit
-corresponding to the codec slot. For example, to probe only the
-first slot, pass `probe_mask=1`. For the first and the third slots,
-pass `probe_mask=5` (where 5 = 1 | 4), and so on.
-
-Since 2.6.29 kernel, the driver has a more robust probing method, so
-this error might happen rarely, though.
-
-
-Interrupt Handling
-~~~~~~~~~~~~~~~~~~
-In rare but some cases, the interrupt isn't properly handled as
-default. You would notice this by the DMA transfer error reported by
-ALSA PCM core, for example. Using MSI might help in such a case.
-Pass `enable_msi=1` option for enabling MSI.
-
-
-HD-AUDIO CODEC
---------------
-
-Model Option
-~~~~~~~~~~~~
-The most common problems with the HD-audio driver is the unsupported
-codec features or the mismatched device configuration. Most of
-codec-specific code has several preset models, either to override the
-BIOS setup or to provide more comprehensive features.
-
-The driver checks PCI SSID and looks through the static configuration
-table until any matching entry is found. If you have a new machine,
-you may see a message like below:
-------------------------------------------------------------------------
- hda_codec: Unknown model for ALC880, trying auto-probe from BIOS...
-------------------------------------------------------------------------
-Even if you such a message, DON'T PANIC. Take a deep breath (and keep
-your towel). First of all, it's an informational message, no warning,
-no error. This means that the PCI SSID of your device isn't listed in
-the known preset model list. But, this doesn't mean that the driver
-is broken. Many codec-driver provides the automatic configuration
-based on the BIOS setup.
-
-The HD-audio codec has usually "pin" widgets, and BIOS sets the default
-configuration of each pin, which indicates the location, the
-connection type, the jack color, etc. The HD-audio driver can guess
-the right connection judging from these default configuration values.
-However -- some codec support codes, such as patch_analog.c, don't
-support the automatic probing (yet as of 2.6.28). And, BIOS is often,
-yes, pretty often broken. It sets up wrong values and screws up the
-driver.
-
-The preset model is provided basically to override such a situation.
-When the matching preset model is found in the list, the driver
-assumes the static configuration of that preset and builds the mixer
-and PCM based on the static information. Thus, if you have a newer
-machine with a slightly different PCI SSID from the existing one, you
-may have a good chance to re-use the same model. You can pass the
-`model` option to specify the preset model instead of PCI SSID
-look-up.
-
-What `model` option values are available depends on the codec chip.
-Check your codec chip from the codec proc file (see "Codec Proc-File"
-section below). It will show the vendor/product name of your codec
-chip. Then, see Documentation/sound/alsa/ALSA-Configuration.txt file.
-In the section of HD-audio driver, you can find a list of codecs and
-`model` options belonging to each codec. For example, for Realtek
-ALC262 codec chip, pass `model=ultra` for devices that are compatible
-with Samsung Q1 Ultra.
-
-Thus, the first thing you can do for any brand-new, unsupported
-HD-audio hardware is to check HD-audio codec and several different
-`model` option values. If you have a luck, some of them might suit
-with your device well.
-
-Some codecs such as ALC880 have a special model option `model=test`.
-This configures the driver to provide as many mixer controls as
-possible for every single pin feature except for the unsolicited
-events (and maybe some other specials). Adjust each mixer element and
-try the I/O in the way of trial-and-error until figuring out the whole
-I/O pin mappings.
-
-Note that `model=generic` has a special meaning. It means to use the
-generic parser regardless of the codec. Usually the codec-specific
-parser is much better than the generic parser (as now). Thus this
-option is more about the debugging purpose.
-
-
-Speaker and Headphone Output
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-One of the most frequent (and obvious) bugs with HD-audio is the
-silent output from either or both of a built-in speaker and a
-headphone jack. In general, you should try a headphone output at
-first. A speaker output often requires more additional controls like
-the amplifier. Thus a headphone output has a slightly better chance.
-
-Before making a bug report, double-check whether the mixer is set up
-correctly. The recent version of snd-hda-intel driver provides mostly
-"Master" volume control as well as "Front" volume. In addition, there
-are individual "Headphone" and "Speaker" controls.
-
-Ditto for the speaker output. There can be "External Amplifier"
-switch on some codecs. Turn on this if present.
-
-Another related problem is the automatic mute of speaker output by
-headphone plugging. This feature is implemented in most cases, but
-not on every preset model or codec-support code.
-
-In anyway, try a different model option if you have such a problem.
-Some other models may match better and give you more matching
-functionality. If none of the available models works, send a bug
-report. See the bug report section for details.
-
-If you are masochistic enough to debug the driver problem, note the
-following:
-
-- The speaker (and the headphone, too) output often requires the
- external amplifier. This can be set usually via EAPD verb or a
- certain GPIO. If the codec pin supports EAPD, you have a better
- chance via SET_EAPD_BTL verb (0x70c). On others, GPIO pin (mostly
- it's either GPIO0 or GPIO1) can turn on/off EAPD.
-- Some Realtek codecs require special vendor-specific coefficients to
- turn on the amplifier. See patch_realtek.c.
-- IDT codecs may have extra power-enable/disable controls on each
- analog pin. See patch_sigmatel.c.
-- Very rare but some devices don't accept the pin-detection verb until
- triggered. Issuing GET_PIN_SENSE verb (0xf09) may result in the
- codec-communication stall. Some examples are found in
- patch_realtek.c.
-
-
-Capture Problems
-~~~~~~~~~~~~~~~~
-The capture problems are often missing setups of mixers. Thus, before
-submitting a bug report, make sure that you set up the mixer
-correctly. For example, both "Capture Volume" and "Capture Switch"
-have to be set properly in addition to the right "Capture Source" or
-"Input Source" selection. Some devices have "Mic Boost" volume or
-switch.
-
-When the PCM device is opened via "default" PCM (without pulse-audio
-plugin), you'll likely have "Digital Capture Volume" control as well.
-This is provided for the extra gain/attenuation of the signal in
-software, especially for the inputs without the hardware volume
-control such as digital microphones. Unless really needed, this
-should be set to exactly 50%, corresponding to 0dB. When you use "hw"
-PCM, i.e., a raw access PCM, this control will have no influence,
-though.
-
-It's known that some codecs / devices have fairly bad analog circuits,
-and the recorded sound contains a certain DC-offset. This is no bug
-of the driver.
-
-Most of modern laptops have no analog CD-input connection. Thus, the
-recording from CD input won't work in many cases although the driver
-provides it as the capture source.
-
-The automatic switching of the built-in and external mic per plugging
-is implemented on some codec models but not on every model. Partly
-because of my laziness but mostly lack of testers. Feel free to
-submit the improvement patch to the author.
-
-
-Direct Debugging
-~~~~~~~~~~~~~~~~
-If no model option gives you a better result, and you are a touch guy
-to fight again the evil, try debugging via hitting the raw HD-audio
-codec verbs to the device. Some tools are available: hda-emu and
-hda-analyzer. The detailed description is found in the sections
-below. You'd need to enable hwdep for using these tools. See "Kernel
-Configuration".
-
-
-OTHER ISSUES
-------------
-
-Kernel Configuration
-~~~~~~~~~~~~~~~~~~~~
-In general, I recommend you to enable the sound debug option,
-`CONFIG_SND_DEBUG=y`, no matter whether you are debugging or not.
-This enables snd_printd() macro and others, and you'll get additional
-kernel messages at probing.
-
-In addition, you can enable `CONFIG_SND_DEBUG_VERBOSE=y`. But this
-will give you far more messages. Thus turn this on only when you are
-sure to want it.
-
-Don't forget to turn on the appropriate `CONFIG_SND_HDA_CODEC_*`
-options. Note that each of them corresponds to the codec chip, not
-the controller chip. Thus, even if lspci shows the Nvidia controller,
-you may choose the option for other vendors. If you are unsure, just
-choose all yes.
-
-`CONFIG_SND_HDA_HWDEP` is a useful option for debugging the driver.
-When this is enabled, the driver creates hardware-dependent devices
-(one per each codec), and you have a raw access to the device via
-hda-verb program. For example, `hwC0D2` will be created for the card
-0 codec slot #2. For debug tools such as hda-verb and hda-analyzer,
-the hwdep device has to be enabled. Thus, turn this on always.
-
-`CONFIG_SND_HDA_RECONFIG` is a new option, and this depends on the
-hwdep option above. When enabled, you'll have some sysfs files under
-the corresponding hwdep directory. See "HD-audio reconfiguration"
-section below.
-
-`CONFIG_SND_HDA_POWER_SAVE` option enables the power-saving feature.
-See "Power-saving" section below.
-
-
-Codec Proc-File
-~~~~~~~~~~~~~~~
-The codec proc-file is a treasure-chest for debugging HD-audio.
-It shows most of useful information of each codec widget.
-
-The proc file is located in /proc/asound/card*/codec#*, one file per
-each codec slot. You can know the codec vendor, product id and
-names, the type of each widget, capabilities and so on.
-This file, however, doesn't show the jack sensing state, so far. This
-is because the jack-sensing might be depending on the trigger state.
-
-This file will be picked up by the debug tools, and also it can be fed
-to the emulator as the primary codec information. See the debug tools
-section below.
-
-This proc file can be also used to check whether the generic parser is
-used. When the generic parser is used, the vendor/product ID name
-will appear as "Realtek ID 0262", instead of "Realtek ALC262".
-
-
-HD-Audio Reconfiguration
-~~~~~~~~~~~~~~~~~~~~~~~~
-This is an experimental feature to allow you re-configure the HD-audio
-codec dynamically without reloading the driver. The following sysfs
-files are available under each codec-hwdep device directory (e.g.
-/sys/class/sound/hwC0D0):
-
-vendor_id::
- Shows the 32bit codec vendor-id hex number. You can change the
- vendor-id value by writing to this file.
-subsystem_id::
- Shows the 32bit codec subsystem-id hex number. You can change the
- subsystem-id value by writing to this file.
-revision_id::
- Shows the 32bit codec revision-id hex number. You can change the
- revision-id value by writing to this file.
-afg::
- Shows the AFG ID. This is read-only.
-mfg::
- Shows the MFG ID. This is read-only.
-name::
- Shows the codec name string. Can be changed by writing to this
- file.
-modelname::
- Shows the currently set `model` option. Can be changed by writing
- to this file.
-init_verbs::
- The extra verbs to execute at initialization. You can add a verb by
- writing to this file. Pass tree numbers, nid, verb and parameter.
-hints::
- Shows hint strings for codec parsers for any use. Right now it's
- not used.
-reconfig::
- Triggers the codec re-configuration. When any value is written to
- this file, the driver re-initialize and parses the codec tree
- again. All the changes done by the sysfs entries above are taken
- into account.
-clear::
- Resets the codec, removes the mixer elements and PCM stuff of the
- specified codec, and clear all init verbs and hints.
-
-
-Power-Saving
-~~~~~~~~~~~~
-The power-saving is a kind of auto-suspend of the device. When the
-device is inactive for a certain time, the device is automatically
-turned off to save the power. The time to go down is specified via
-`power_save` module option, and this option can be changed dynamically
-via sysfs.
-
-The power-saving won't work when the analog loopback is enabled on
-some codecs. Make sure that you mute all unneeded signal routes when
-you want the power-saving.
-
-The power-saving feature might cause audible click noises at each
-power-down/up depending on the device. Some of them might be
-solvable, but some are hard, I'm afraid. Some distros such as
-openSUSE enables the power-saving feature automatically when the power
-cable is unplugged. Thus, if you hear noises, suspect first the
-power-saving. See /sys/modules/snd_hda_intel/parameters/power_save to
-check the current value. If it's non-zero, the feature is turned on.
-
-
-Sending a Bug Report
-~~~~~~~~~~~~~~~~~~~~
-If any model or module options don't work for your device, it's time
-to send a bug report to the developers. Give the following in your
-bug report:
-
-- Hardware vendor, product and model names
-- Kernel version (and ALSA-driver version if you built externally)
-- `alsa-info.sh` output; run with `--no-upload` option. See the
- section below about alsa-info
-
-If it's a regression, at best, send alsa-info outputs of both working
-and non-working kernels. This is really helpful because we can
-compare the codec registers directly.
-
-Send a bug report either the followings:
-
-kernel-bugzilla::
- http://bugme.linux-foundation.org/
-alsa-devel ML::
- alsa-devel@alsa-project.org
-
-
-DEBUG TOOLS
------------
-
-This section describes some tools available for debugging HD-audio
-problems.
-
-alsa-info
-~~~~~~~~~
-The script `alsa-info.sh` is a very useful tool to gather the audio
-device information. You can fetch the latest version from:
-
-- http://www.alsa-project.org/alsa-info.sh
-
-Run this script as root, and it will gather the important information
-such as the module lists, module parameters, proc file contents
-including the codec proc files, mixer outputs and the control
-elements. As default, it will store the information onto a web server
-on alsa-project.org. But, if you send a bug report, it'd be better to
-run with `--no-upload` option, and attach the generated file.
-
-There are some other useful options. See `--help` option output for
-details.
-
-
-hda-verb
-~~~~~~~~
-hda-verb is a tiny program that allows you to access the HD-audio
-codec directly. It executes a HD-audio codec verb directly.
-This program accesses the hwdep device, thus you need to enable the
-kernel config `CONFIG_SND_HDA_HWDEP=y` beforehand.
-
-The hda-verb program takes four arguments: the hwdep device file, the
-widget NID, the verb and the parameter. When you access to the codec
-on the slot 2 of the card 0, pass /dev/snd/hwC0D2 to the first
-argument, typically. (However, the real path name depends on the
-system.)
-
-The second parameter is the widget number-id to access. The third
-parameter can be either a hex/digit number or a string corresponding
-to a verb. Similarly, the last parameter is the value to write, or
-can be a string for the parameter type.
-
-------------------------------------------------------------------------
- % hda-verb /dev/snd/hwC0D0 0x12 0x701 2
- nid = 0x12, verb = 0x701, param = 0x2
- value = 0x0
-
- % hda-verb /dev/snd/hwC0D0 0x0 PARAMETERS VENDOR_ID
- nid = 0x0, verb = 0xf00, param = 0x0
- value = 0x10ec0262
-
- % hda-verb /dev/snd/hwC0D0 2 set_a 0xb080
- nid = 0x2, verb = 0x300, param = 0xb080
- value = 0x0
-------------------------------------------------------------------------
-
-Although you can issue any verbs with this program, the driver state
-won't be always updated. For example, the volume values are usually
-cached in the driver, and thus changing the widget amp value directly
-via hda-verb won't change the mixer value.
-
-The hda-verb program is found in the ftp directory:
-
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
-
-Also a git repository is available:
-
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-verb.git
-
-See README file in the tarball for more details about hda-verb
-program.
-
-
-hda-analyzer
-~~~~~~~~~~~~
-hda-analyzer provides a graphical interface to access the raw HD-audio
-control, based on pyGTK2 binding. It's a more powerful version of
-hda-verb. The program gives you a easy-to-use GUI stuff for showing
-the widget information and adjusting the amp values, as well as the
-proc-compatible output.
-
-The hda-analyzer is a part of alsa.git repository in
-alsa-project.org:
-
-- http://git.alsa-project.org/?p=alsa.git;a=tree;f=hda-analyzer
-
-
-hda-emu
-~~~~~~~
-hda-emu is a HD-audio emulator. The main purpose of this program is
-to debug an HD-audio codec without the real hardware. Thus, it
-doesn't emulate the behavior with the real audio I/O, but it just
-dumps the codec register changes and the ALSA-driver internal changes
-at probing and operating the HD-audio driver.
-
-The program requires a codec proc-file to simulate. Get a proc file
-for the target codec beforehand, or pick up an example codec from the
-codec proc collections in the tarball. Then, run the program with the
-proc file, and the hda-emu program will start parsing the codec file
-and simulates the HD-audio driver:
-
-------------------------------------------------------------------------
- % hda-emu codecs/stac9200-dell-d820-laptop
- # Parsing..
- hda_codec: Unknown model for STAC9200, using BIOS defaults
- hda_codec: pin nid 08 bios pin config 40c003fa
- ....
-------------------------------------------------------------------------
-
-The program gives you only a very dumb command-line interface. You
-can get a proc-file dump at the current state, get a list of control
-(mixer) elements, set/get the control element value, simulate the PCM
-operation, the jack plugging simulation, etc.
-
-The package is found in:
-
-- ftp://ftp.kernel.org/pub/linux/kernel/people/tiwai/misc/
-
-A git repository is available:
-
-- git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/hda-emu.git
-
-See README file in the tarball for more details about hda-emu
-program.
diff --git a/Documentation/sound/alsa/Procfile.txt b/Documentation/sound/alsa/Procfile.txt
index bba2dbb79d81..f738b296440a 100644
--- a/Documentation/sound/alsa/Procfile.txt
+++ b/Documentation/sound/alsa/Procfile.txt
@@ -153,16 +153,6 @@ card*/codec#*
Shows the general codec information and the attribute of each
widget node.
-card*/eld#*
- Available for HDMI or DisplayPort interfaces.
- Shows ELD(EDID Like Data) info retrieved from the attached HDMI sink,
- and describes its audio capabilities and configurations.
-
- Some ELD fields may be modified by doing `echo name hex_value > eld#*`.
- Only do this if you are sure the HDMI sink provided value is wrong.
- And if that makes your HDMI audio work, please report to us so that we
- can fix it in future kernel releases.
-
Sequencer Information
---------------------
diff --git a/Documentation/sound/alsa/soc/machine.txt b/Documentation/sound/alsa/soc/machine.txt
index bab7711ce963..f370e7db86af 100644
--- a/Documentation/sound/alsa/soc/machine.txt
+++ b/Documentation/sound/alsa/soc/machine.txt
@@ -9,7 +9,7 @@ the audio subsystem with the kernel as a platform device and is represented by
the following struct:-
/* SoC machine */
-struct snd_soc_card {
+struct snd_soc_machine {
char *name;
int (*probe)(struct platform_device *pdev);
@@ -67,10 +67,10 @@ static struct snd_soc_dai_link corgi_dai = {
.ops = &corgi_ops,
};
-struct snd_soc_card then sets up the machine with it's DAIs. e.g.
+struct snd_soc_machine then sets up the machine with it's DAIs. e.g.
/* corgi audio machine driver */
-static struct snd_soc_card snd_soc_corgi = {
+static struct snd_soc_machine snd_soc_machine_corgi = {
.name = "Corgi",
.dai_link = &corgi_dai,
.num_links = 1,
@@ -90,7 +90,7 @@ static struct wm8731_setup_data corgi_wm8731_setup = {
/* corgi audio subsystem */
static struct snd_soc_device corgi_snd_devdata = {
- .machine = &snd_soc_corgi,
+ .machine = &snd_soc_machine_corgi,
.platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &corgi_wm8731_setup,
diff --git a/MAINTAINERS b/MAINTAINERS
index 6dad667e9fcc..b791a13afec8 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4020,7 +4020,7 @@ M: tiwai@suse.de
L: alsa-devel@alsa-project.org (subscribers-only)
S: Maintained
-SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
+SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT
P: Liam Girdwood
M: lrg@slimlogic.co.uk
P: Mark Brown
diff --git a/arch/arm/mach-pxa/include/mach/palmasoc.h b/arch/arm/mach-pxa/include/mach/palmasoc.h
deleted file mode 100644
index 6c4b1f7de20a..000000000000
--- a/arch/arm/mach-pxa/include/mach/palmasoc.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef _INCLUDE_PALMASOC_H_
-#define _INCLUDE_PALMASOC_H_
-struct palm27x_asoc_info {
- int jack_gpio;
-};
-
-#ifdef CONFIG_SND_PXA2XX_SOC_PALM27X
-void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data);
-#else
-static inline void palm27x_asoc_set_pdata(struct palm27x_asoc_info *data) {}
-#endif
-
-#endif
diff --git a/include/linux/input.h b/include/linux/input.h
index 1a958cd90ce9..5341e8251f8c 100644
--- a/include/linux/input.h
+++ b/include/linux/input.h
@@ -659,7 +659,6 @@ struct input_absinfo {
#define SW_RADIO SW_RFKILL_ALL /* deprecated */
#define SW_MICROPHONE_INSERT 0x04 /* set = inserted */
#define SW_DOCK 0x05 /* set = plugged into dock */
-#define SW_LINEOUT_INSERT 0x06 /* set = inserted */
#define SW_MAX 0x0f
#define SW_CNT (SW_MAX+1)
diff --git a/include/sound/asound.h b/include/sound/asound.h
index 1c02ed1d7c4a..2c4dc908a54a 100644
--- a/include/sound/asound.h
+++ b/include/sound/asound.h
@@ -575,7 +575,6 @@ enum {
#define SNDRV_TIMER_GLOBAL_SYSTEM 0
#define SNDRV_TIMER_GLOBAL_RTC 1
#define SNDRV_TIMER_GLOBAL_HPET 2
-#define SNDRV_TIMER_GLOBAL_HRTIMER 3
/* info flags */
#define SNDRV_TIMER_FLG_SLAVE (1<<0) /* cannot be controlled */
diff --git a/include/sound/core.h b/include/sound/core.h
index f632484bc743..1508c4ec1ba9 100644
--- a/include/sound/core.h
+++ b/include/sound/core.h
@@ -353,7 +353,7 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
* snd_printk - printk wrapper
* @fmt: format string
*
- * Works like printk() but prints the file and the line of the caller
+ * Works like print() but prints the file and the line of the caller
* when configured with CONFIG_SND_VERBOSE_PRINTK.
*/
#define snd_printk(fmt, args...) \
@@ -380,40 +380,18 @@ void snd_verbose_printd(const char *file, int line, const char *format, ...)
printk(fmt ,##args)
#endif
-/**
- * snd_BUG - give a BUG warning message and stack trace
- *
- * Calls WARN() if CONFIG_SND_DEBUG is set.
- * Ignored when CONFIG_SND_DEBUG is not set.
- */
#define snd_BUG() WARN(1, "BUG?\n")
-
-/**
- * snd_BUG_ON - debugging check macro
- * @cond: condition to evaluate
- *
- * When CONFIG_SND_DEBUG is set, this macro evaluates the given condition,
- * and call WARN() and returns the value if it's non-zero.
- *
- * When CONFIG_SND_DEBUG is not set, this just returns zero, and the given
- * condition is ignored.
- *
- * NOTE: the argument won't be evaluated at all when CONFIG_SND_DEBUG=n.
- * Thus, don't put any statement that influences on the code behavior,
- * such as pre/post increment, to the argument of this macro.
- * If you want to evaluate and give a warning, use standard WARN_ON().
- */
#define snd_BUG_ON(cond) WARN((cond), "BUG? (%s)\n", __stringify(cond))
#else /* !CONFIG_SND_DEBUG */
#define snd_printd(fmt, args...) do { } while (0)
#define snd_BUG() do { } while (0)
-static inline int __snd_bug_on(int cond)
+static inline int __snd_bug_on(void)
{
return 0;
}
-#define snd_BUG_ON(cond) __snd_bug_on(0 && (cond)) /* always false */
+#define snd_BUG_ON(cond) __snd_bug_on() /* always false */
#endif /* CONFIG_SND_DEBUG */
diff --git a/include/sound/info.h b/include/sound/info.h
index 7c2ee1a21b00..8ae72e74f898 100644
--- a/include/sound/info.h
+++ b/include/sound/info.h
@@ -40,34 +40,30 @@ struct snd_info_buffer {
struct snd_info_entry;
struct snd_info_entry_text {
- void (*read)(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer);
- void (*write)(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer);
+ void (*read) (struct snd_info_entry *entry, struct snd_info_buffer *buffer);
+ void (*write) (struct snd_info_entry *entry, struct snd_info_buffer *buffer);
};
struct snd_info_entry_ops {
- int (*open)(struct snd_info_entry *entry,
- unsigned short mode, void **file_private_data);
- int (*release)(struct snd_info_entry *entry,
- unsigned short mode, void *file_private_data);
- long (*read)(struct snd_info_entry *entry, void *file_private_data,
- struct file *file, char __user *buf,
- unsigned long count, unsigned long pos);
- long (*write)(struct snd_info_entry *entry, void *file_private_data,
- struct file *file, const char __user *buf,
+ int (*open) (struct snd_info_entry *entry,
+ unsigned short mode, void **file_private_data);
+ int (*release) (struct snd_info_entry * entry,
+ unsigned short mode, void *file_private_data);
+ long (*read) (struct snd_info_entry *entry, void *file_private_data,
+ struct file * file, char __user *buf,
unsigned long count, unsigned long pos);
- long long (*llseek)(struct snd_info_entry *entry,
- void *file_private_data, struct file *file,
- long long offset, int orig);
- unsigned int(*poll)(struct snd_info_entry *entry,
- void *file_private_data, struct file *file,
- poll_table *wait);
- int (*ioctl)(struct snd_info_entry *entry, void *file_private_data,
- struct file *file, unsigned int cmd, unsigned long arg);
- int (*mmap)(struct snd_info_entry *entry, void *file_private_data,
- struct inode *inode, struct file *file,
- struct vm_area_struct *vma);
+ long (*write) (struct snd_info_entry *entry, void *file_private_data,
+ struct file * file, const char __user *buf,
+ unsigned long count, unsigned long pos);
+ long long (*llseek) (struct snd_info_entry *entry, void *file_private_data,
+ struct file * file, long long offset, int orig);
+ unsigned int (*poll) (struct snd_info_entry *entry, void *file_private_data,
+ struct file * file, poll_table * wait);
+ int (*ioctl) (struct snd_info_entry *entry, void *file_private_data,
+ struct file * file, unsigned int cmd, unsigned long arg);
+ int (*mmap) (struct snd_info_entry *entry, void *file_private_data,
+ struct inode * inode, struct file * file,
+ struct vm_area_struct * vma);
};
struct snd_info_entry {
@@ -110,37 +106,34 @@ void snd_card_info_read_oss(struct snd_info_buffer *buffer);
static inline void snd_card_info_read_oss(struct snd_info_buffer *buffer) {}
#endif
-int snd_iprintf(struct snd_info_buffer *buffer, char *fmt, ...) \
- __attribute__ ((format (printf, 2, 3)));
+int snd_iprintf(struct snd_info_buffer * buffer, char *fmt,...) __attribute__ ((format (printf, 2, 3)));
int snd_info_init(void);
int snd_info_done(void);
-int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len);
+int snd_info_get_line(struct snd_info_buffer * buffer, char *line, int len);
char *snd_info_get_str(char *dest, char *src, int len);
-struct snd_info_entry *snd_info_create_module_entry(struct module *module,
+struct snd_info_entry *snd_info_create_module_entry(struct module * module,
const char *name,
- struct snd_info_entry *parent);
-struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card,
+ struct snd_info_entry * parent);
+struct snd_info_entry *snd_info_create_card_entry(struct snd_card * card,
const char *name,
- struct snd_info_entry *parent);
-void snd_info_free_entry(struct snd_info_entry *entry);
-int snd_info_store_text(struct snd_info_entry *entry);
-int snd_info_restore_text(struct snd_info_entry *entry);
-
-int snd_info_card_create(struct snd_card *card);
-int snd_info_card_register(struct snd_card *card);
-int snd_info_card_free(struct snd_card *card);
-void snd_info_card_disconnect(struct snd_card *card);
-void snd_info_card_id_change(struct snd_card *card);
-int snd_info_register(struct snd_info_entry *entry);
+ struct snd_info_entry * parent);
+void snd_info_free_entry(struct snd_info_entry * entry);
+int snd_info_store_text(struct snd_info_entry * entry);
+int snd_info_restore_text(struct snd_info_entry * entry);
+
+int snd_info_card_create(struct snd_card * card);
+int snd_info_card_register(struct snd_card * card);
+int snd_info_card_free(struct snd_card * card);
+void snd_info_card_disconnect(struct snd_card * card);
+int snd_info_register(struct snd_info_entry * entry);
/* for card drivers */
-int snd_card_proc_new(struct snd_card *card, const char *name,
- struct snd_info_entry **entryp);
+int snd_card_proc_new(struct snd_card *card, const char *name, struct snd_info_entry **entryp);
static inline void snd_info_set_text_ops(struct snd_info_entry *entry,
- void *private_data,
- void (*read)(struct snd_info_entry *, struct snd_info_buffer *))
+ void *private_data,
+ void (*read)(struct snd_info_entry *, struct snd_info_buffer *))
{
entry->private_data = private_data;
entry->c.text.read = read;
@@ -153,22 +146,21 @@ int snd_info_check_reserved_words(const char *str);
#define snd_seq_root NULL
#define snd_oss_root NULL
-static inline int snd_iprintf(struct snd_info_buffer *buffer, char *fmt, ...) { return 0; }
+static inline int snd_iprintf(struct snd_info_buffer * buffer, char *fmt,...) { return 0; }
static inline int snd_info_init(void) { return 0; }
static inline int snd_info_done(void) { return 0; }
-static inline int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) { return 0; }
+static inline int snd_info_get_line(struct snd_info_buffer * buffer, char *line, int len) { return 0; }
static inline char *snd_info_get_str(char *dest, char *src, int len) { return NULL; }
-static inline struct snd_info_entry *snd_info_create_module_entry(struct module *module, const char *name, struct snd_info_entry *parent) { return NULL; }
-static inline struct snd_info_entry *snd_info_create_card_entry(struct snd_card *card, const char *name, struct snd_info_entry *parent) { return NULL; }
-static inline void snd_info_free_entry(struct snd_info_entry *entry) { ; }
-
-static inline int snd_info_card_create(struct snd_card *card) { return 0; }
-static inline int snd_info_card_register(struct snd_card *card) { return 0; }
-static inline int snd_info_card_free(struct snd_card *card) { return 0; }
-static inline void snd_info_card_disconnect(struct snd_card *card) { }
-static inline void snd_info_card_id_change(struct snd_card *card) { }
-static inline int snd_info_register(struct snd_info_entry *entry) { return 0; }
+static inline struct snd_info_entry *snd_info_create_module_entry(struct module * module, const char *name, struct snd_info_entry * parent) { return NULL; }
+static inline struct snd_info_entry *snd_info_create_card_entry(struct snd_card * card, const char *name, struct snd_info_entry * parent) { return NULL; }
+static inline void snd_info_free_entry(struct snd_info_entry * entry) { ; }
+
+static inline int snd_info_card_create(struct snd_card * card) { return 0; }
+static inline int snd_info_card_register(struct snd_card * card) { return 0; }
+static inline int snd_info_card_free(struct snd_card * card) { return 0; }
+static inline void snd_info_card_disconnect(struct snd_card * card) { }
+static inline int snd_info_register(struct snd_info_entry * entry) { return 0; }
static inline int snd_card_proc_new(struct snd_card *card, const char *name,
struct snd_info_entry **entryp) { return -EINVAL; }
diff --git a/include/sound/jack.h b/include/sound/jack.h
index 7cb25f4b50bb..b1b2b8b59adb 100644
--- a/include/sound/jack.h
+++ b/include/sound/jack.h
@@ -35,7 +35,6 @@ enum snd_jack_types {
SND_JACK_HEADPHONE = 0x0001,
SND_JACK_MICROPHONE = 0x0002,
SND_JACK_HEADSET = SND_JACK_HEADPHONE | SND_JACK_MICROPHONE,
- SND_JACK_LINEOUT = 0x0004,
};
struct snd_jack {
diff --git a/include/sound/l3.h b/include/sound/l3.h
deleted file mode 100644
index 423a08f0f1b0..000000000000
--- a/include/sound/l3.h
+++ /dev/null
@@ -1,18 +0,0 @@
-#ifndef _L3_H_
-#define _L3_H_ 1
-
-struct l3_pins {
- void (*setdat)(int);
- void (*setclk)(int);
- void (*setmode)(int);
- int data_hold;
- int data_setup;
- int clock_high;
- int mode_hold;
- int mode;
- int mode_setup;
-};
-
-int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len);
-
-#endif
diff --git a/include/sound/s3c24xx_uda134x.h b/include/sound/s3c24xx_uda134x.h
deleted file mode 100644
index 33df4cb909d3..000000000000
--- a/include/sound/s3c24xx_uda134x.h
+++ /dev/null
@@ -1,14 +0,0 @@
-#ifndef _S3C24XX_UDA134X_H_
-#define _S3C24XX_UDA134X_H_ 1
-
-#include <sound/uda134x.h>
-
-struct s3c24xx_uda134x_platform_data {
- int l3_clk;
- int l3_mode;
- int l3_data;
- void (*power) (int);
- int model;
-};
-
-#endif
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h
deleted file mode 100644
index 24247f763608..000000000000
--- a/include/sound/soc-dai.h
+++ /dev/null
@@ -1,231 +0,0 @@
-/*
- * linux/sound/soc-dai.h -- ALSA SoC Layer
- *
- * Copyright: 2005-2008 Wolfson Microelectronics. PLC.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Digital Audio Interface (DAI) API.
- */
-
-#ifndef __LINUX_SND_SOC_DAI_H
-#define __LINUX_SND_SOC_DAI_H
-
-
-#include <linux/list.h>
-
-struct snd_pcm_substream;
-
-/*
- * DAI hardware audio formats.
- *
- * Describes the physical PCM data formating and clocking. Add new formats
- * to the end.
- */
-#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
-#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right Justified mode */
-#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
-#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM LRC */
-#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM LRC */
-#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
-
-/* left and right justified also known as MSB and LSB respectively */
-#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
-#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
-
-/*
- * DAI Clock gating.
- *
- * DAI bit clocks can be be gated (disabled) when not the DAI is not
- * sending or receiving PCM data in a frame. This can be used to save power.
- */
-#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
-#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated */
-
-/*
- * DAI Left/Right Clocks.
- *
- * Specifies whether the DAI can support different samples for similtanious
- * playback and capture. This usually requires a seperate physical frame
- * clock for playback and capture.
- */
-#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
-#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
-
-/*
- * TDM
- *
- * Time Division Multiplexing. Allows PCM data to be multplexed with other
- * data on the DAI.
- */
-#define SND_SOC_DAIFMT_TDM (1 << 6)
-
-/*
- * DAI hardware signal inversions.
- *
- * Specifies whether the DAI can also support inverted clocks for the specified
- * format.
- */
-#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */
-#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
-#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
-#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
-
-/*
- * DAI hardware clock masters.
- *
- * This is wrt the codec, the inverse is true for the interface
- * i.e. if the codec is clk and frm master then the interface is
- * clk and frame slave.
- */
-#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */
-#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */
-#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
-#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */
-
-#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
-#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
-#define SND_SOC_DAIFMT_INV_MASK 0x0f00
-#define SND_SOC_DAIFMT_MASTER_MASK 0xf000
-
-/*
- * Master Clock Directions
- */
-#define SND_SOC_CLOCK_IN 0
-#define SND_SOC_CLOCK_OUT 1
-
-struct snd_soc_dai_ops;
-struct snd_soc_dai;
-struct snd_ac97_bus_ops;
-
-/* Digital Audio Interface registration */
-int snd_soc_register_dai(struct snd_soc_dai *dai);
-void snd_soc_unregister_dai(struct snd_soc_dai *dai);
-int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count);
-void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count);
-
-/* Digital Audio Interface clocking API.*/
-int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
- unsigned int freq, int dir);
-
-int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
- int div_id, int div);
-
-int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
- int pll_id, unsigned int freq_in, unsigned int freq_out);
-
-/* Digital Audio interface formatting */
-int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
-
-int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
- unsigned int mask, int slots);
-
-int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
-
-/* Digital Audio Interface mute */
-int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
-
-/*
- * Digital Audio Interface.
- *
- * Describes the Digital Audio Interface in terms of it's ALSA, DAI and AC97
- * operations an capabilities. Codec and platfom drivers will register a this
- * structure for every DAI they have.
- *
- * This structure covers the clocking, formating and ALSA operations for each
- * interface a
- */
-struct snd_soc_dai_ops {
- /*
- * DAI clocking configuration, all optional.
- * Called by soc_card drivers, normally in their hw_params.
- */
- int (*set_sysclk)(struct snd_soc_dai *dai,
- int clk_id, unsigned int freq, int dir);
- int (*set_pll)(struct snd_soc_dai *dai,
- int pll_id, unsigned int freq_in, unsigned int freq_out);
- int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
-
- /*
- * DAI format configuration
- * Called by soc_card drivers, normally in their hw_params.
- */
- int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
- int (*set_tdm_slot)(struct snd_soc_dai *dai,
- unsigned int mask, int slots);
- int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
-
- /*
- * DAI digital mute - optional.
- * Called by soc-core to minimise any pops.
- */
- int (*digital_mute)(struct snd_soc_dai *dai, int mute);
-
- /*
- * ALSA PCM audio operations - all optional.
- * Called by soc-core during audio PCM operations.
- */
- int (*startup)(struct snd_pcm_substream *,
- struct snd_soc_dai *);
- void (*shutdown)(struct snd_pcm_substream *,
- struct snd_soc_dai *);
- int (*hw_params)(struct snd_pcm_substream *,
- struct snd_pcm_hw_params *, struct snd_soc_dai *);
- int (*hw_free)(struct snd_pcm_substream *,
- struct snd_soc_dai *);
- int (*prepare)(struct snd_pcm_substream *,
- struct snd_soc_dai *);
- int (*trigger)(struct snd_pcm_substream *, int,
- struct snd_soc_dai *);
-};
-
-/*
- * Digital Audio Interface runtime data.
- *
- * Holds runtime data for a DAI.
- */
-struct snd_soc_dai {
- /* DAI description */
- char *name;
- unsigned int id;
- int ac97_control;
-
- struct device *dev;
-
- /* DAI callbacks */
- int (*probe)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- void (*remove)(struct platform_device *pdev,
- struct snd_soc_dai *dai);
- int (*suspend)(struct snd_soc_dai *dai);
- int (*resume)(struct snd_soc_dai *dai);
-
- /* ops */
- struct snd_soc_dai_ops ops;
-
- /* DAI capabilities */
- struct snd_soc_pcm_stream capture;
- struct snd_soc_pcm_stream playback;
-
- /* DAI runtime info */
- struct snd_pcm_runtime *runtime;
- struct snd_soc_codec *codec;
- unsigned int active;
- unsigned char pop_wait:1;
- void *dma_data;
-
- /* DAI private data */
- void *private_data;
-
- /* parent codec/platform */
- union {
- struct snd_soc_codec *codec;
- struct snd_soc_platform *platform;
- };
-
- struct list_head list;
-};
-
-#endif
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h
index 7ee2f70ca42e..ca699a3017f3 100644
--- a/include/sound/soc-dapm.h
+++ b/include/sound/soc-dapm.h
@@ -221,6 +221,8 @@ int snd_soc_dapm_new_controls(struct snd_soc_codec *codec,
int num);
/* dapm path setup */
+int __deprecated snd_soc_dapm_connect_input(struct snd_soc_codec *codec,
+ const char *sink_name, const char *control_name, const char *src_name);
int snd_soc_dapm_new_widgets(struct snd_soc_codec *codec);
void snd_soc_dapm_free(struct snd_soc_device *socdev);
int snd_soc_dapm_add_routes(struct snd_soc_codec *codec,
diff --git a/include/sound/soc.h b/include/sound/soc.h
index ce3661d07c24..5e0189876afd 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -21,6 +21,8 @@
#include <sound/control.h>
#include <sound/ac97_codec.h>
+#define SND_SOC_VERSION "0.13.2"
+
/*
* Convenience kcontrol builders
*/
@@ -143,29 +145,105 @@ enum snd_soc_bias_level {
SND_SOC_BIAS_OFF,
};
+/*
+ * Digital Audio Interface (DAI) types
+ */
+#define SND_SOC_DAI_AC97 0x1
+#define SND_SOC_DAI_I2S 0x2
+#define SND_SOC_DAI_PCM 0x4
+#define SND_SOC_DAI_AC97_BUS 0x8 /* for custom i.e. non ac97_codec.c */
+
+/*
+ * DAI hardware audio formats
+ */
+#define SND_SOC_DAIFMT_I2S 0 /* I2S mode */
+#define SND_SOC_DAIFMT_RIGHT_J 1 /* Right justified mode */
+#define SND_SOC_DAIFMT_LEFT_J 2 /* Left Justified mode */
+#define SND_SOC_DAIFMT_DSP_A 3 /* L data msb after FRM or LRC */
+#define SND_SOC_DAIFMT_DSP_B 4 /* L data msb during FRM or LRC */
+#define SND_SOC_DAIFMT_AC97 5 /* AC97 */
+
+#define SND_SOC_DAIFMT_MSB SND_SOC_DAIFMT_LEFT_J
+#define SND_SOC_DAIFMT_LSB SND_SOC_DAIFMT_RIGHT_J
+
+/*
+ * DAI Gating
+ */
+#define SND_SOC_DAIFMT_CONT (0 << 4) /* continuous clock */
+#define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */
+
+/*
+ * DAI Sync
+ * Synchronous LR (Left Right) clocks and Frame signals.
+ */
+#define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */
+#define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */
+
+/*
+ * TDM
+ */
+#define SND_SOC_DAIFMT_TDM (1 << 6)
+
+/*
+ * DAI hardware signal inversions
+ */
+#define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bclk + frm */
+#define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */
+#define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */
+#define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */
+
+/*
+ * DAI hardware clock masters
+ * This is wrt the codec, the inverse is true for the interface
+ * i.e. if the codec is clk and frm master then the interface is
+ * clk and frame slave.
+ */
+#define SND_SOC_DAIFMT_CBM_CFM (0 << 12) /* codec clk & frm master */
+#define SND_SOC_DAIFMT_CBS_CFM (1 << 12) /* codec clk slave & frm master */
+#define SND_SOC_DAIFMT_CBM_CFS (2 << 12) /* codec clk master & frame slave */
+#define SND_SOC_DAIFMT_CBS_CFS (3 << 12) /* codec clk & frm slave */
+
+#define SND_SOC_DAIFMT_FORMAT_MASK 0x000f
+#define SND_SOC_DAIFMT_CLOCK_MASK 0x00f0
+#define SND_SOC_DAIFMT_INV_MASK 0x0f00
+#define SND_SOC_DAIFMT_MASTER_MASK 0xf000
+
+
+/*
+ * Master Clock Directions
+ */
+#define SND_SOC_CLOCK_IN 0
+#define SND_SOC_CLOCK_OUT 1
+
+/*
+ * AC97 codec ID's bitmask
+ */
+#define SND_SOC_DAI_AC97_ID0 (1 << 0)
+#define SND_SOC_DAI_AC97_ID1 (1 << 1)
+#define SND_SOC_DAI_AC97_ID2 (1 << 2)
+#define SND_SOC_DAI_AC97_ID3 (1 << 3)
+
struct snd_soc_device;
struct snd_soc_pcm_stream;
struct snd_soc_ops;
struct snd_soc_dai_mode;
struct snd_soc_pcm_runtime;
struct snd_soc_dai;
-struct snd_soc_platform;
struct snd_soc_codec;
+struct snd_soc_machine_config;
struct soc_enum;
struct snd_soc_ac97_ops;
+struct snd_soc_clock_info;
typedef int (*hw_write_t)(void *,const char* ,int);
typedef int (*hw_read_t)(void *,char* ,int);
extern struct snd_ac97_bus_ops soc_ac97_ops;
-int snd_soc_register_platform(struct snd_soc_platform *platform);
-void snd_soc_unregister_platform(struct snd_soc_platform *platform);
-
/* pcm <-> DAI connect */
void snd_soc_free_pcms(struct snd_soc_device *socdev);
int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid);
-int snd_soc_init_card(struct snd_soc_device *socdev);
+int snd_soc_register_card(struct snd_soc_device *socdev);
/* set runtime hw params */
int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream,
@@ -185,6 +263,27 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec,
struct snd_ac97_bus_ops *ops, int num);
void snd_soc_free_ac97_codec(struct snd_soc_codec *codec);
+/* Digital Audio Interface clocking API.*/
+int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
+ unsigned int freq, int dir);
+
+int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
+ int div_id, int div);
+
+int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out);
+
+/* Digital Audio interface formatting */
+int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt);
+
+int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
+ unsigned int mask, int slots);
+
+int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate);
+
+/* Digital Audio Interface mute */
+int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute);
+
/*
*Controls
*/
@@ -242,6 +341,61 @@ struct snd_soc_ops {
int (*trigger)(struct snd_pcm_substream *, int);
};
+/* ASoC DAI ops */
+struct snd_soc_dai_ops {
+ /* DAI clocking configuration */
+ int (*set_sysclk)(struct snd_soc_dai *dai,
+ int clk_id, unsigned int freq, int dir);
+ int (*set_pll)(struct snd_soc_dai *dai,
+ int pll_id, unsigned int freq_in, unsigned int freq_out);
+ int (*set_clkdiv)(struct snd_soc_dai *dai, int div_id, int div);
+
+ /* DAI format configuration */
+ int (*set_fmt)(struct snd_soc_dai *dai, unsigned int fmt);
+ int (*set_tdm_slot)(struct snd_soc_dai *dai,
+ unsigned int mask, int slots);
+ int (*set_tristate)(struct snd_soc_dai *dai, int tristate);
+
+ /* digital mute */
+ int (*digital_mute)(struct snd_soc_dai *dai, int mute);
+};
+
+/* SoC DAI (Digital Audio Interface) */
+struct snd_soc_dai {
+ /* DAI description */
+ char *name;
+ unsigned int id;
+ unsigned char type;
+
+ /* DAI callbacks */
+ int (*probe)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
+ void (*remove)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
+ int (*suspend)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
+ int (*resume)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
+
+ /* ops */
+ struct snd_soc_ops ops;
+ struct snd_soc_dai_ops dai_ops;
+
+ /* DAI capabilities */
+ struct snd_soc_pcm_stream capture;
+ struct snd_soc_pcm_stream playback;
+
+ /* DAI runtime info */
+ struct snd_pcm_runtime *runtime;
+ struct snd_soc_codec *codec;
+ unsigned int active;
+ unsigned char pop_wait:1;
+ void *dma_data;
+
+ /* DAI private data */
+ void *private_data;
+};
+
/* SoC Audio Codec */
struct snd_soc_codec {
char *name;
@@ -272,7 +426,6 @@ struct snd_soc_codec {
short reg_cache_step;
/* dapm */
- u32 pop_time;
struct list_head dapm_widgets;
struct list_head dapm_paths;
enum snd_soc_bias_level bias_level;
@@ -282,11 +435,6 @@ struct snd_soc_codec {
/* codec DAI's */
struct snd_soc_dai *dai;
unsigned int num_dai;
-
-#ifdef CONFIG_DEBUG_FS
- struct dentry *debugfs_reg;
- struct dentry *debugfs_pop_time;
-#endif
};
/* codec device */
@@ -300,12 +448,13 @@ struct snd_soc_codec_device {
/* SoC platform interface */
struct snd_soc_platform {
char *name;
- struct list_head list;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
- int (*suspend)(struct snd_soc_dai *dai);
- int (*resume)(struct snd_soc_dai *dai);
+ int (*suspend)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
+ int (*resume)(struct platform_device *pdev,
+ struct snd_soc_dai *dai);
/* pcm creation and destruction */
int (*pcm_new)(struct snd_card *, struct snd_soc_dai *,
@@ -335,14 +484,9 @@ struct snd_soc_dai_link {
struct snd_pcm *pcm;
};
-/* SoC card */
-struct snd_soc_card {
+/* SoC machine */
+struct snd_soc_machine {
char *name;
- struct device *dev;
-
- struct list_head list;
-
- int instantiated;
int (*probe)(struct platform_device *pdev);
int (*remove)(struct platform_device *pdev);
@@ -355,26 +499,23 @@ struct snd_soc_card {
int (*resume_post)(struct platform_device *pdev);
/* callbacks */
- int (*set_bias_level)(struct snd_soc_card *,
+ int (*set_bias_level)(struct snd_soc_machine *,
enum snd_soc_bias_level level);
/* CPU <--> Codec DAI links */
struct snd_soc_dai_link *dai_link;
int num_links;
-
- struct snd_soc_device *socdev;
-
- struct snd_soc_platform *platform;
- struct delayed_work delayed_work;
- struct work_struct deferred_resume_work;
};
/* SoC Device - the audio subsystem */
struct snd_soc_device {
struct device *dev;
- struct snd_soc_card *card;
+ struct snd_soc_machine *machine;
+ struct snd_soc_platform *platform;
struct snd_soc_codec *codec;
struct snd_soc_codec_device *codec_dev;
+ struct delayed_work delayed_work;
+ struct work_struct deferred_resume_work;
void *codec_data;
};
@@ -401,6 +542,4 @@ struct soc_enum {
void *dapm;
};
-#include <sound/soc-dai.h>
-
#endif
diff --git a/include/sound/uda134x.h b/include/sound/uda134x.h
deleted file mode 100644
index 475ef8bb7dcd..000000000000
--- a/include/sound/uda134x.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * uda134x.h -- UDA134x ALSA SoC Codec driver
- *
- * Copyright 2007 Dension Audio Systems Ltd.
- * Author: Zoltan Devai
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _UDA134X_H
-#define _UDA134X_H
-
-#include <sound/l3.h>
-
-struct uda134x_platform_data {
- struct l3_pins l3;
- void (*power) (int);
- int model;
-#define UDA134X_UDA1340 1
-#define UDA134X_UDA1341 2
-#define UDA134X_UDA1344 3
-};
-
-#endif /* _UDA134X_H */
diff --git a/include/sound/version.h b/include/sound/version.h
index 2b48237e23bf..4aafeda88634 100644
--- a/include/sound/version.h
+++ b/include/sound/version.h
@@ -1,3 +1,3 @@
/* include/version.h */
-#define CONFIG_SND_VERSION "1.0.18a"
+#define CONFIG_SND_VERSION "1.0.18rc3"
#define CONFIG_SND_DATE ""
diff --git a/sound/ac97_bus.c b/sound/ac97_bus.c
index a351dd0a09c7..7fa37e15f196 100644
--- a/sound/ac97_bus.c
+++ b/sound/ac97_bus.c
@@ -15,7 +15,6 @@
#include <linux/init.h>
#include <linux/device.h>
#include <linux/string.h>
-#include <sound/ac97_codec.h>
/*
* Let drivers decide whether they want to support given codec from their
diff --git a/sound/aoa/codecs/Makefile b/sound/aoa/codecs/Makefile
index c3ee77fc4b2d..31cbe68fd42f 100644
--- a/sound/aoa/codecs/Makefile
+++ b/sound/aoa/codecs/Makefile
@@ -1,7 +1,3 @@
-snd-aoa-codec-onyx-objs := onyx.o
-snd-aoa-codec-tas-objs := tas.o
-snd-aoa-codec-toonie-objs := toonie.o
-
obj-$(CONFIG_SND_AOA_ONYX) += snd-aoa-codec-onyx.o
obj-$(CONFIG_SND_AOA_TAS) += snd-aoa-codec-tas.o
obj-$(CONFIG_SND_AOA_TOONIE) += snd-aoa-codec-toonie.o
diff --git a/sound/aoa/codecs/onyx.c b/sound/aoa/codecs/snd-aoa-codec-onyx.c
index 15500b9d2da0..6a3837d480e5 100644
--- a/sound/aoa/codecs/onyx.c
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.c
@@ -37,7 +37,7 @@ MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("pcm3052 (onyx) codec driver for snd-aoa");
-#include "onyx.h"
+#include "snd-aoa-codec-onyx.h"
#include "../aoa.h"
#include "../soundbus/soundbus.h"
@@ -292,7 +292,7 @@ static int onyx_snd_capture_source_put(struct snd_kcontrol *kcontrol,
static struct snd_kcontrol_new capture_source_control = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
/* If we name this 'Input Source', it properly shows up in
- * alsamixer as a selection, * but it's shown under the
+ * alsamixer as a selection, * but it's shown under the
* 'Playback' category.
* If I name it 'Capture Source', it shows up in strange
* ways (two bools of which one can be selected at a
@@ -477,7 +477,7 @@ static int onyx_spdif_mask_get(struct snd_kcontrol *kcontrol,
ucontrol->value.iec958.status[3] = 0x3f;
ucontrol->value.iec958.status[4] = 0x0f;
-
+
return 0;
}
@@ -682,7 +682,7 @@ static int onyx_usable(struct codec_info_item *cii,
onyx_read_register(onyx, ONYX_REG_DIG_INFO4, &v);
spdif_enabled = !!(v & ONYX_SPDIF_ENABLE);
onyx_read_register(onyx, ONYX_REG_DAC_CONTROL, &v);
- analog_enabled =
+ analog_enabled =
(v & (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT))
!= (ONYX_MUTE_RIGHT|ONYX_MUTE_LEFT);
mutex_unlock(&onyx->mutex);
@@ -882,7 +882,7 @@ static int onyx_init_codec(struct aoa_codec *codec)
msleep(1);
onyx->codec.gpio->methods->set_hw_reset(onyx->codec.gpio, 0);
msleep(1);
-
+
if (onyx_register_init(onyx)) {
printk(KERN_ERR PFX "failed to initialise onyx registers\n");
return -ENODEV;
@@ -1069,7 +1069,7 @@ static int onyx_i2c_attach(struct i2c_adapter *adapter)
/* if that didn't work, try desperate mode for older
* machines that have stuff missing from the device tree */
-
+
if (!of_device_is_compatible(busnode, "k2-i2c"))
return -ENODEV;
diff --git a/sound/aoa/codecs/onyx.h b/sound/aoa/codecs/snd-aoa-codec-onyx.h
index ffd20254ff76..ffd20254ff76 100644
--- a/sound/aoa/codecs/onyx.h
+++ b/sound/aoa/codecs/snd-aoa-codec-onyx.h
diff --git a/sound/aoa/codecs/tas-basstreble.h b/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h
index 69b61136fd54..69b61136fd54 100644
--- a/sound/aoa/codecs/tas-basstreble.h
+++ b/sound/aoa/codecs/snd-aoa-codec-tas-basstreble.h
diff --git a/sound/aoa/codecs/tas-gain-table.h b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h
index 4cfa6757715e..4cfa6757715e 100644
--- a/sound/aoa/codecs/tas-gain-table.h
+++ b/sound/aoa/codecs/snd-aoa-codec-tas-gain-table.h
diff --git a/sound/aoa/codecs/tas.c b/sound/aoa/codecs/snd-aoa-codec-tas.c
index 008e0f85097d..6c515b2b8bbd 100644
--- a/sound/aoa/codecs/tas.c
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.c
@@ -71,9 +71,9 @@ MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("tas codec driver for snd-aoa");
-#include "tas.h"
-#include "tas-gain-table.h"
-#include "tas-basstreble.h"
+#include "snd-aoa-codec-tas.h"
+#include "snd-aoa-codec-tas-gain-table.h"
+#include "snd-aoa-codec-tas-basstreble.h"
#include "../aoa.h"
#include "../soundbus/soundbus.h"
@@ -880,7 +880,7 @@ static void tas_exit_codec(struct aoa_codec *codec)
return;
tas->codec.soundbus_dev->detach_codec(tas->codec.soundbus_dev, tas);
}
-
+
static struct i2c_driver tas_driver;
diff --git a/sound/aoa/codecs/tas.h b/sound/aoa/codecs/snd-aoa-codec-tas.h
index ae177e3466e6..ae177e3466e6 100644
--- a/sound/aoa/codecs/tas.h
+++ b/sound/aoa/codecs/snd-aoa-codec-tas.h
diff --git a/sound/aoa/codecs/toonie.c b/sound/aoa/codecs/snd-aoa-codec-toonie.c
index f13827e17562..3c7d1d8a9a6f 100644
--- a/sound/aoa/codecs/toonie.c
+++ b/sound/aoa/codecs/snd-aoa-codec-toonie.c
@@ -131,7 +131,7 @@ static int __init toonie_init(void)
toonie->codec.owner = THIS_MODULE;
toonie->codec.init = toonie_init_codec;
toonie->codec.exit = toonie_exit_codec;
-
+
if (aoa_codec_register(&toonie->codec)) {
kfree(toonie);
return -EINVAL;
diff --git a/sound/aoa/core/Makefile b/sound/aoa/core/Makefile
index a1596e88c718..62dc7287f663 100644
--- a/sound/aoa/core/Makefile
+++ b/sound/aoa/core/Makefile
@@ -1,5 +1,5 @@
obj-$(CONFIG_SND_AOA) += snd-aoa.o
-snd-aoa-objs := core.o \
- alsa.o \
- gpio-pmf.o \
- gpio-feature.o
+snd-aoa-objs := snd-aoa-core.o \
+ snd-aoa-alsa.o \
+ snd-aoa-gpio-pmf.o \
+ snd-aoa-gpio-feature.o
diff --git a/sound/aoa/core/alsa.c b/sound/aoa/core/snd-aoa-alsa.c
index 617850463582..17fe689ed287 100644
--- a/sound/aoa/core/alsa.c
+++ b/sound/aoa/core/snd-aoa-alsa.c
@@ -6,7 +6,7 @@
* GPL v2, can be found in COPYING.
*/
#include <linux/module.h>
-#include "alsa.h"
+#include "snd-aoa-alsa.h"
static int index = -1;
module_param(index, int, 0444);
@@ -64,7 +64,7 @@ int aoa_snd_device_new(snd_device_type_t type,
{
struct snd_card *card = aoa_get_card();
int err;
-
+
if (!card) return -ENOMEM;
err = snd_device_new(card, type, device_data, ops);
diff --git a/sound/aoa/core/alsa.h b/sound/aoa/core/snd-aoa-alsa.h
index 9669e4489cab..9669e4489cab 100644
--- a/sound/aoa/core/alsa.h
+++ b/sound/aoa/core/snd-aoa-alsa.h
diff --git a/sound/aoa/core/core.c b/sound/aoa/core/snd-aoa-core.c
index 10bec6c61382..19fdae400687 100644
--- a/sound/aoa/core/core.c
+++ b/sound/aoa/core/snd-aoa-core.c
@@ -10,7 +10,7 @@
#include <linux/module.h>
#include <linux/list.h>
#include "../aoa.h"
-#include "alsa.h"
+#include "snd-aoa-alsa.h"
MODULE_DESCRIPTION("Apple Onboard Audio Sound Driver");
MODULE_AUTHOR("Johannes Berg <johannes@sipsolutions.net>");
diff --git a/sound/aoa/core/gpio-feature.c b/sound/aoa/core/snd-aoa-gpio-feature.c
index c93ad5dec66b..805dcbff2257 100644
--- a/sound/aoa/core/gpio-feature.c
+++ b/sound/aoa/core/snd-aoa-gpio-feature.c
@@ -5,7 +5,7 @@
*
* GPL v2, can be found in COPYING.
*
- * This file contains the GPIO control routines for
+ * This file contains the GPIO control routines for
* direct (through feature calls) access to the GPIO
* registers.
*/
diff --git a/sound/aoa/core/gpio-pmf.c b/sound/aoa/core/snd-aoa-gpio-pmf.c
index 5ca2220eac7d..5ca2220eac7d 100644
--- a/sound/aoa/core/gpio-pmf.c
+++ b/sound/aoa/core/snd-aoa-gpio-pmf.c
diff --git a/sound/aoa/fabrics/Makefile b/sound/aoa/fabrics/Makefile
index da37c10eca51..55fc5e7e52cf 100644
--- a/sound/aoa/fabrics/Makefile
+++ b/sound/aoa/fabrics/Makefile
@@ -1,3 +1 @@
-snd-aoa-fabric-layout-objs += layout.o
-
obj-$(CONFIG_SND_AOA_FABRIC_LAYOUT) += snd-aoa-fabric-layout.o
diff --git a/sound/aoa/fabrics/layout.c b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
index ad60f5d10e82..dea7abb082cd 100644
--- a/sound/aoa/fabrics/layout.c
+++ b/sound/aoa/fabrics/snd-aoa-fabric-layout.c
@@ -66,7 +66,7 @@ struct layout {
unsigned int layout_id;
struct codec_connect_info codecs[MAX_CODECS_PER_BUS];
int flags;
-
+
/* if busname is not assigned, we use 'Master' below,
* so that our layout table doesn't need to be filled
* too much.
diff --git a/sound/aoa/soundbus/i2sbus/Makefile b/sound/aoa/soundbus/i2sbus/Makefile
index 1b949b2a4028..e57a5cf65655 100644
--- a/sound/aoa/soundbus/i2sbus/Makefile
+++ b/sound/aoa/soundbus/i2sbus/Makefile
@@ -1,2 +1,2 @@
obj-$(CONFIG_SND_AOA_SOUNDBUS_I2S) += snd-aoa-i2sbus.o
-snd-aoa-i2sbus-objs := core.o pcm.o control.o
+snd-aoa-i2sbus-objs := i2sbus-core.o i2sbus-pcm.o i2sbus-control.o
diff --git a/sound/aoa/soundbus/i2sbus/control.c b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
index 87beb4ad4d63..87beb4ad4d63 100644
--- a/sound/aoa/soundbus/i2sbus/control.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-control.c
diff --git a/sound/aoa/soundbus/i2sbus/core.c b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
index be468edf3ecb..b4590df07466 100644
--- a/sound/aoa/soundbus/i2sbus/core.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-core.c
@@ -64,7 +64,7 @@ static void free_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
struct dbdma_command_mem *r)
{
if (!r->space) return;
-
+
dma_free_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
r->size, r->space, r->bus_addr);
}
@@ -247,7 +247,7 @@ static int i2sbus_add_dev(struct macio_dev *macio,
* but request_resource doesn't know about parents and
* contained resources...
*/
- dev->allocated_resource[i] =
+ dev->allocated_resource[i] =
request_mem_region(dev->resources[i].start,
dev->resources[i].end -
dev->resources[i].start + 1,
diff --git a/sound/aoa/soundbus/i2sbus/interface.h b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
index c6b5f5452d20..c6b5f5452d20 100644
--- a/sound/aoa/soundbus/i2sbus/interface.h
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-interface.h
diff --git a/sound/aoa/soundbus/i2sbus/pcm.c b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
index 59bacd365733..59bacd365733 100644
--- a/sound/aoa/soundbus/i2sbus/pcm.c
+++ b/sound/aoa/soundbus/i2sbus/i2sbus-pcm.c
diff --git a/sound/aoa/soundbus/i2sbus/i2sbus.h b/sound/aoa/soundbus/i2sbus/i2sbus.h
index befefd99e271..ff29654782c9 100644
--- a/sound/aoa/soundbus/i2sbus/i2sbus.h
+++ b/sound/aoa/soundbus/i2sbus/i2sbus.h
@@ -18,7 +18,7 @@
#include <asm/pmac_feature.h>
#include <asm/dbdma.h>
-#include "interface.h"
+#include "i2sbus-interface.h"
#include "../soundbus.h"
struct i2sbus_control {
diff --git a/sound/core/Kconfig b/sound/core/Kconfig
index 7bbdda041a99..66348c92f88d 100644
--- a/sound/core/Kconfig
+++ b/sound/core/Kconfig
@@ -95,26 +95,6 @@ config SND_SEQUENCER_OSS
this will be compiled as a module. The module will be called
snd-seq-oss.
-config SND_HRTIMER
- tristate "HR-timer backend support"
- depends on HIGH_RES_TIMERS
- select SND_TIMER
- help
- Say Y here to enable HR-timer backend for ALSA timer. ALSA uses
- the hrtimer as a precise timing source. The ALSA sequencer code
- also can use this timing source.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-hrtimer.
-
-config SND_SEQ_HRTIMER_DEFAULT
- bool "Use HR-timer as default sequencer timer"
- depends on SND_HRTIMER && SND_SEQUENCER
- default y
- help
- Say Y here to use the HR-timer backend as the default sequencer
- timer.
-
config SND_RTCTIMER
tristate "RTC Timer support"
depends on RTC
@@ -134,7 +114,6 @@ config SND_RTCTIMER
config SND_SEQ_RTCTIMER_DEFAULT
bool "Use RTC as default sequencer timer"
depends on SND_RTCTIMER && SND_SEQUENCER
- depends on !SND_SEQ_HRTIMER_DEFAULT
default y
help
Say Y here to use the RTC timer as the default sequencer
diff --git a/sound/core/Makefile b/sound/core/Makefile
index 4229052e7b91..d57125a5687d 100644
--- a/sound/core/Makefile
+++ b/sound/core/Makefile
@@ -17,14 +17,12 @@ snd-page-alloc-$(CONFIG_HAS_DMA) += sgbuf.o
snd-rawmidi-objs := rawmidi.o
snd-timer-objs := timer.o
-snd-hrtimer-objs := hrtimer.o
snd-rtctimer-objs := rtctimer.o
snd-hwdep-objs := hwdep.o
obj-$(CONFIG_SND) += snd.o
obj-$(CONFIG_SND_HWDEP) += snd-hwdep.o
obj-$(CONFIG_SND_TIMER) += snd-timer.o
-obj-$(CONFIG_SND_HRTIMER) += snd-hrtimer.o
obj-$(CONFIG_SND_RTCTIMER) += snd-rtctimer.o
obj-$(CONFIG_SND_PCM) += snd-pcm.o snd-page-alloc.o
obj-$(CONFIG_SND_RAWMIDI) += snd-rawmidi.o
diff --git a/sound/core/device.c b/sound/core/device.c
index a67dfac08c03..c58d8227254c 100644
--- a/sound/core/device.c
+++ b/sound/core/device.c
@@ -98,7 +98,7 @@ int snd_device_free(struct snd_card *card, void *device_data)
kfree(dev);
return 0;
}
- snd_printd("device free %p (from %pF), not found\n", device_data,
+ snd_printd("device free %p (from %p), not found\n", device_data,
__builtin_return_address(0));
return -ENXIO;
}
@@ -135,7 +135,7 @@ int snd_device_disconnect(struct snd_card *card, void *device_data)
}
return 0;
}
- snd_printd("device disconnect %p (from %pF), not found\n", device_data,
+ snd_printd("device disconnect %p (from %p), not found\n", device_data,
__builtin_return_address(0));
return -ENXIO;
}
diff --git a/sound/core/hrtimer.c b/sound/core/hrtimer.c
deleted file mode 100644
index c1d285921f80..000000000000
--- a/sound/core/hrtimer.c
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * ALSA timer back-end using hrtimer
- * Copyright (C) 2008 Takashi Iwai
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- *
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/hrtimer.h>
-#include <sound/core.h>
-#include <sound/timer.h>
-
-MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
-MODULE_DESCRIPTION("ALSA hrtimer backend");
-MODULE_LICENSE("GPL");
-
-MODULE_ALIAS("snd-timer-" __stringify(SNDRV_TIMER_GLOBAL_HRTIMER));
-
-#define NANO_SEC 1000000000UL /* 10^9 in sec */
-static unsigned int resolution;
-
-struct snd_hrtimer {
- struct snd_timer *timer;
- struct hrtimer hrt;
-};
-
-static enum hrtimer_restart snd_hrtimer_callback(struct hrtimer *hrt)
-{
- struct snd_hrtimer *stime = container_of(hrt, struct snd_hrtimer, hrt);
- struct snd_timer *t = stime->timer;
- hrtimer_forward_now(hrt, ns_to_ktime(t->sticks * resolution));
- snd_timer_interrupt(stime->timer, t->sticks);
- return HRTIMER_RESTART;
-}
-
-static int snd_hrtimer_open(struct snd_timer *t)
-{
- struct snd_hrtimer *stime;
-
- stime = kmalloc(sizeof(*stime), GFP_KERNEL);
- if (!stime)
- return -ENOMEM;
- hrtimer_init(&stime->hrt, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- stime->timer = t;
- stime->hrt.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
- stime->hrt.function = snd_hrtimer_callback;
- t->private_data = stime;
- return 0;
-}
-
-static int snd_hrtimer_close(struct snd_timer *t)
-{
- struct snd_hrtimer *stime = t->private_data;
-
- if (stime) {
- hrtimer_cancel(&stime->hrt);
- kfree(stime);
- t->private_data = NULL;
- }
- return 0;
-}
-
-static int snd_hrtimer_start(struct snd_timer *t)
-{
- struct snd_hrtimer *stime = t->private_data;
-
- hrtimer_start(&stime->hrt, ns_to_ktime(t->sticks * resolution),
- HRTIMER_MODE_REL);
- return 0;
-}
-
-static int snd_hrtimer_stop(struct snd_timer *t)
-{
- struct snd_hrtimer *stime = t->private_data;
-
- hrtimer_cancel(&stime->hrt);
- return 0;
-}
-
-static struct snd_timer_hardware hrtimer_hw = {
- .flags = SNDRV_TIMER_HW_AUTO,
- .open = snd_hrtimer_open,
- .close = snd_hrtimer_close,
- .start = snd_hrtimer_start,
- .stop = snd_hrtimer_stop,
-};
-
-/*
- * entry functions
- */
-
-static struct snd_timer *mytimer;
-
-static int __init snd_hrtimer_init(void)
-{
- struct snd_timer *timer;
- struct timespec tp;
- int err;
-
- hrtimer_get_res(CLOCK_MONOTONIC, &tp);
- if (tp.tv_sec > 0 || !tp.tv_nsec) {
- snd_printk(KERN_ERR
- "snd-hrtimer: Invalid resolution %u.%09u",
- (unsigned)tp.tv_sec, (unsigned)tp.tv_nsec);
- return -EINVAL;
- }
- resolution = tp.tv_nsec;
-
- /* Create a new timer and set up the fields */
- err = snd_timer_global_new("hrtimer", SNDRV_TIMER_GLOBAL_HRTIMER,
- &timer);
- if (err < 0)
- return err;
-
- timer->module = THIS_MODULE;
- strcpy(timer->name, "HR timer");
- timer->hw = hrtimer_hw;
- timer->hw.resolution = resolution;
- timer->hw.ticks = NANO_SEC / resolution;
-
- err = snd_timer_global_register(timer);
- if (err < 0) {
- snd_timer_global_free(timer);
- return err;
- }
- mytimer = timer; /* remember this */
-
- return 0;
-}
-
-static void __exit snd_hrtimer_exit(void)
-{
- if (mytimer) {
- snd_timer_global_free(mytimer);
- mytimer = NULL;
- }
-}
-
-module_init(snd_hrtimer_init);
-module_exit(snd_hrtimer_exit);
diff --git a/sound/core/info.c b/sound/core/info.c
index 70fa87189f36..527b207462b0 100644
--- a/sound/core/info.c
+++ b/sound/core/info.c
@@ -653,23 +653,6 @@ int snd_info_card_register(struct snd_card *card)
}
/*
- * called on card->id change
- */
-void snd_info_card_id_change(struct snd_card *card)
-{
- mutex_lock(&info_mutex);
- if (card->proc_root_link) {
- snd_remove_proc_entry(snd_proc_root, card->proc_root_link);
- card->proc_root_link = NULL;
- }
- if (strcmp(card->id, card->proc_root->name))
- card->proc_root_link = proc_symlink(card->id,
- snd_proc_root,
- card->proc_root->name);
- mutex_unlock(&info_mutex);
-}
-
-/*
* de-register the card proc file
* called from init.c
*/
diff --git a/sound/core/init.c b/sound/core/init.c
index 0d5520c415d3..b47ff8b44be8 100644
--- a/sound/core/init.c
+++ b/sound/core/init.c
@@ -533,65 +533,6 @@ static void choose_default_id(struct snd_card *card)
}
}
-#ifndef CONFIG_SYSFS_DEPRECATED
-static ssize_t
-card_id_show_attr(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%s\n", card ? card->id : "(null)");
-}
-
-static ssize_t
-card_id_store_attr(struct device *dev, struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- char buf1[sizeof(card->id)];
- size_t copy = count > sizeof(card->id) - 1 ?
- sizeof(card->id) - 1 : count;
- size_t idx;
- int c;
-
- for (idx = 0; idx < copy; idx++) {
- c = buf[idx];
- if (!isalnum(c) && c != '_' && c != '-')
- return -EINVAL;
- }
- memcpy(buf1, buf, copy);
- buf1[copy] = '\0';
- mutex_lock(&snd_card_mutex);
- if (!snd_info_check_reserved_words(buf1)) {
- __exist:
- mutex_unlock(&snd_card_mutex);
- return -EEXIST;
- }
- for (idx = 0; idx < snd_ecards_limit; idx++) {
- if (snd_cards[idx] && !strcmp(snd_cards[idx]->id, buf1))
- goto __exist;
- }
- strcpy(card->id, buf1);
- snd_info_card_id_change(card);
- mutex_unlock(&snd_card_mutex);
-
- return count;
-}
-
-static struct device_attribute card_id_attrs =
- __ATTR(id, S_IRUGO | S_IWUSR, card_id_show_attr, card_id_store_attr);
-
-static ssize_t
-card_number_show_attr(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct snd_card *card = dev_get_drvdata(dev);
- return snprintf(buf, PAGE_SIZE, "%i\n", card ? card->number : -1);
-}
-
-static struct device_attribute card_number_attrs =
- __ATTR(number, S_IRUGO, card_number_show_attr, NULL);
-#endif /* CONFIG_SYSFS_DEPRECATED */
-
/**
* snd_card_register - register the soundcard
* @card: soundcard structure
@@ -612,7 +553,7 @@ int snd_card_register(struct snd_card *card)
#ifndef CONFIG_SYSFS_DEPRECATED
if (!card->card_dev) {
card->card_dev = device_create(sound_class, card->dev,
- MKDEV(0, 0), card,
+ MKDEV(0, 0), NULL,
"card%i", card->number);
if (IS_ERR(card->card_dev))
card->card_dev = NULL;
@@ -635,16 +576,6 @@ int snd_card_register(struct snd_card *card)
if (snd_mixer_oss_notify_callback)
snd_mixer_oss_notify_callback(card, SND_MIXER_OSS_NOTIFY_REGISTER);
#endif
-#ifndef CONFIG_SYSFS_DEPRECATED
- if (card->card_dev) {
- err = device_create_file(card->card_dev, &card_id_attrs);
- if (err < 0)
- return err;
- err = device_create_file(card->card_dev, &card_number_attrs);
- if (err < 0)
- return err;
- }
-#endif
return 0;
}
diff --git a/sound/core/jack.c b/sound/core/jack.c
index 284432f427f4..bd2d9e6b55e9 100644
--- a/sound/core/jack.c
+++ b/sound/core/jack.c
@@ -34,7 +34,6 @@ static int snd_jack_dev_free(struct snd_device *device)
else
input_free_device(jack->input_dev);
- kfree(jack->id);
kfree(jack);
return 0;
@@ -88,7 +87,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
if (jack == NULL)
return -ENOMEM;
- jack->id = kstrdup(id, GFP_KERNEL);
+ jack->id = id;
jack->input_dev = input_allocate_device();
if (jack->input_dev == NULL) {
@@ -103,9 +102,6 @@ int snd_jack_new(struct snd_card *card, const char *id, int type,
if (type & SND_JACK_HEADPHONE)
input_set_capability(jack->input_dev, EV_SW,
SW_HEADPHONE_INSERT);
- if (type & SND_JACK_LINEOUT)
- input_set_capability(jack->input_dev, EV_SW,
- SW_LINEOUT_INSERT);
if (type & SND_JACK_MICROPHONE)
input_set_capability(jack->input_dev, EV_SW,
SW_MICROPHONE_INSERT);
@@ -157,9 +153,6 @@ void snd_jack_report(struct snd_jack *jack, int status)
if (jack->type & SND_JACK_HEADPHONE)
input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT,
status & SND_JACK_HEADPHONE);
- if (jack->type & SND_JACK_LINEOUT)
- input_report_switch(jack->input_dev, SW_LINEOUT_INSERT,
- status & SND_JACK_LINEOUT);
if (jack->type & SND_JACK_MICROPHONE)
input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT,
status & SND_JACK_MICROPHONE);
diff --git a/sound/core/seq/seq.c b/sound/core/seq/seq.c
index bf09a5ad1865..ee0f8405ab35 100644
--- a/sound/core/seq/seq.c
+++ b/sound/core/seq/seq.c
@@ -43,9 +43,7 @@ int seq_default_timer_class = SNDRV_TIMER_CLASS_GLOBAL;
int seq_default_timer_sclass = SNDRV_TIMER_SCLASS_NONE;
int seq_default_timer_card = -1;
int seq_default_timer_device =
-#ifdef CONFIG_SND_SEQ_HRTIMER_DEFAULT
- SNDRV_TIMER_GLOBAL_HRTIMER
-#elif defined(CONFIG_SND_SEQ_RTCTIMER_DEFAULT)
+#ifdef CONFIG_SND_SEQ_RTCTIMER_DEFAULT
SNDRV_TIMER_GLOBAL_RTC
#else
SNDRV_TIMER_GLOBAL_SYSTEM
diff --git a/sound/drivers/Kconfig b/sound/drivers/Kconfig
index 0bcf14640fde..255fd18b9aec 100644
--- a/sound/drivers/Kconfig
+++ b/sound/drivers/Kconfig
@@ -163,7 +163,7 @@ config SND_ML403_AC97CR
config SND_AC97_POWER_SAVE
bool "AC97 Power-Saving Mode"
- depends on SND_AC97_CODEC
+ depends on SND_AC97_CODEC && EXPERIMENTAL
default n
help
Say Y here to enable the aggressive power-saving support of
diff --git a/sound/drivers/pcsp/pcsp.c b/sound/drivers/pcsp/pcsp.c
index 2a02f704f366..1899cf0685bc 100644
--- a/sound/drivers/pcsp/pcsp.c
+++ b/sound/drivers/pcsp/pcsp.c
@@ -96,7 +96,7 @@ static int __devinit snd_card_pcsp_probe(int devnum, struct device *dev)
return -EINVAL;
hrtimer_init(&pcsp_chip.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
- pcsp_chip.timer.cb_mode = HRTIMER_CB_IRQSAFE_UNLOCKED;
+ pcsp_chip.timer.cb_mode = HRTIMER_CB_SOFTIRQ;
pcsp_chip.timer.function = pcsp_do_timer;
card = snd_card_new(index, id, THIS_MODULE, 0);
@@ -188,8 +188,10 @@ static int __devexit pcsp_remove(struct platform_device *dev)
static void pcsp_stop_beep(struct snd_pcsp *chip)
{
- pcsp_sync_stop(chip);
- pcspkr_stop_sound();
+ spin_lock_irq(&chip->substream_lock);
+ if (!chip->playback_substream)
+ pcspkr_stop_sound();
+ spin_unlock_irq(&chip->substream_lock);
}
#ifdef CONFIG_PM
diff --git a/sound/drivers/pcsp/pcsp.h b/sound/drivers/pcsp/pcsp.h
index cdef2664218f..1d661f795e8c 100644
--- a/sound/drivers/pcsp/pcsp.h
+++ b/sound/drivers/pcsp/pcsp.h
@@ -62,8 +62,6 @@ struct snd_pcsp {
unsigned short port, irq, dma;
spinlock_t substream_lock;
struct snd_pcm_substream *playback_substream;
- unsigned int fmt_size;
- unsigned int is_signed;
size_t playback_ptr;
size_t period_ptr;
atomic_t timer_active;
@@ -79,7 +77,6 @@ struct snd_pcsp {
extern struct snd_pcsp pcsp_chip;
extern enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle);
-extern void pcsp_sync_stop(struct snd_pcsp *chip);
extern int snd_pcsp_new_pcm(struct snd_pcsp *chip);
extern int snd_pcsp_new_mixer(struct snd_pcsp *chip);
diff --git a/sound/drivers/pcsp/pcsp_lib.c b/sound/drivers/pcsp/pcsp_lib.c
index 84cc2658c05b..1f42e4063118 100644
--- a/sound/drivers/pcsp/pcsp_lib.c
+++ b/sound/drivers/pcsp/pcsp_lib.c
@@ -8,7 +8,6 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
-#include <linux/interrupt.h>
#include <sound/pcm.h>
#include <asm/io.h>
#include "pcsp.h"
@@ -20,57 +19,61 @@ MODULE_PARM_DESC(nforce_wa, "Apply NForce chipset workaround "
#define DMIX_WANTS_S16 1
-/*
- * Call snd_pcm_period_elapsed in a tasklet
- * This avoids spinlock messes and long-running irq contexts
- */
-static void pcsp_call_pcm_elapsed(unsigned long priv)
-{
- if (atomic_read(&pcsp_chip.timer_active)) {
- struct snd_pcm_substream *substream;
- substream = pcsp_chip.playback_substream;
- if (substream)
- snd_pcm_period_elapsed(substream);
- }
-}
-
-static DECLARE_TASKLET(pcsp_pcm_tasklet, pcsp_call_pcm_elapsed, 0);
-
-/* write the port and returns the next expire time in ns;
- * called at the trigger-start and in hrtimer callback
- */
-static unsigned long pcsp_timer_update(struct hrtimer *handle)
+enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
{
unsigned char timer_cnt, val;
+ int fmt_size, periods_elapsed;
u64 ns;
+ size_t period_bytes, buffer_bytes;
struct snd_pcm_substream *substream;
struct snd_pcm_runtime *runtime;
struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
- unsigned long flags;
if (chip->thalf) {
outb(chip->val61, 0x61);
chip->thalf = 0;
if (!atomic_read(&chip->timer_active))
- return 0;
- return chip->ns_rem;
+ return HRTIMER_NORESTART;
+ hrtimer_forward(&chip->timer, hrtimer_get_expires(&chip->timer),
+ ktime_set(0, chip->ns_rem));
+ return HRTIMER_RESTART;
}
- if (!atomic_read(&chip->timer_active))
- return 0;
+ spin_lock_irq(&chip->substream_lock);
+ /* Takashi Iwai says regarding this extra lock:
+
+ If the irq handler handles some data on the DMA buffer, it should
+ do snd_pcm_stream_lock().
+ That protects basically against all races among PCM callbacks, yes.
+ However, there are two remaining issues:
+ 1. The substream pointer you try to lock isn't protected _before_
+ this lock yet.
+ 2. snd_pcm_period_elapsed() itself acquires the lock.
+ The requirement of another lock is because of 1. When you get
+ chip->playback_substream, it's not protected.
+ Keeping this lock while snd_pcm_period_elapsed() assures the substream
+ is still protected (at least, not released). And the other status is
+ handled properly inside snd_pcm_stream_lock() in
+ snd_pcm_period_elapsed().
+
+ */
+ if (!chip->playback_substream)
+ goto exit_nr_unlock1;
substream = chip->playback_substream;
- if (!substream)
- return 0;
+ snd_pcm_stream_lock(substream);
+ if (!atomic_read(&chip->timer_active))
+ goto exit_nr_unlock2;
runtime = substream->runtime;
+ fmt_size = snd_pcm_format_physical_width(runtime->format) >> 3;
/* assume it is mono! */
- val = runtime->dma_area[chip->playback_ptr + chip->fmt_size - 1];
- if (chip->is_signed)
+ val = runtime->dma_area[chip->playback_ptr + fmt_size - 1];
+ if (snd_pcm_format_signed(runtime->format))
val ^= 0x80;
timer_cnt = val * CUR_DIV() / 256;
if (timer_cnt && chip->enable) {
- spin_lock_irqsave(&i8253_lock, flags);
+ spin_lock(&i8253_lock);
if (!nforce_wa) {
outb_p(chip->val61, 0x61);
outb_p(timer_cnt, 0x42);
@@ -79,39 +82,12 @@ static unsigned long pcsp_timer_update(struct hrtimer *handle)
outb(chip->val61 ^ 2, 0x61);
chip->thalf = 1;
}
- spin_unlock_irqrestore(&i8253_lock, flags);
+ spin_unlock(&i8253_lock);
}
- chip->ns_rem = PCSP_PERIOD_NS();
- ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem);
- chip->ns_rem -= ns;
- return ns;
-}
-
-enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
-{
- struct snd_pcsp *chip = container_of(handle, struct snd_pcsp, timer);
- struct snd_pcm_substream *substream;
- int periods_elapsed, pointer_update;
- size_t period_bytes, buffer_bytes;
- unsigned long ns;
- unsigned long flags;
-
- pointer_update = !chip->thalf;
- ns = pcsp_timer_update(handle);
- if (!ns)
- return HRTIMER_NORESTART;
-
- /* update the playback position */
- substream = chip->playback_substream;
- if (!substream)
- return HRTIMER_NORESTART;
-
period_bytes = snd_pcm_lib_period_bytes(substream);
buffer_bytes = snd_pcm_lib_buffer_bytes(substream);
-
- spin_lock_irqsave(&chip->substream_lock, flags);
- chip->playback_ptr += PCSP_INDEX_INC() * chip->fmt_size;
+ chip->playback_ptr += PCSP_INDEX_INC() * fmt_size;
periods_elapsed = chip->playback_ptr - chip->period_ptr;
if (periods_elapsed < 0) {
#if PCSP_DEBUG
@@ -126,30 +102,41 @@ enum hrtimer_restart pcsp_do_timer(struct hrtimer *handle)
* or ALSA will BUG on us. */
chip->playback_ptr %= buffer_bytes;
+ snd_pcm_stream_unlock(substream);
+
if (periods_elapsed) {
+ snd_pcm_period_elapsed(substream);
chip->period_ptr += periods_elapsed * period_bytes;
chip->period_ptr %= buffer_bytes;
}
- spin_unlock_irqrestore(&chip->substream_lock, flags);
- if (periods_elapsed)
- tasklet_schedule(&pcsp_pcm_tasklet);
+ spin_unlock_irq(&chip->substream_lock);
- hrtimer_forward(handle, hrtimer_get_expires(handle), ns_to_ktime(ns));
+ if (!atomic_read(&chip->timer_active))
+ return HRTIMER_NORESTART;
+ chip->ns_rem = PCSP_PERIOD_NS();
+ ns = (chip->thalf ? PCSP_CALC_NS(timer_cnt) : chip->ns_rem);
+ chip->ns_rem -= ns;
+ hrtimer_forward(&chip->timer, hrtimer_get_expires(&chip->timer),
+ ktime_set(0, ns));
return HRTIMER_RESTART;
+
+exit_nr_unlock2:
+ snd_pcm_stream_unlock(substream);
+exit_nr_unlock1:
+ spin_unlock_irq(&chip->substream_lock);
+ return HRTIMER_NORESTART;
}
-static int pcsp_start_playing(struct snd_pcsp *chip)
+static void pcsp_start_playing(struct snd_pcsp *chip)
{
- unsigned long ns;
-
#if PCSP_DEBUG
printk(KERN_INFO "PCSP: start_playing called\n");
#endif
if (atomic_read(&chip->timer_active)) {
printk(KERN_ERR "PCSP: Timer already active\n");
- return -EIO;
+ return;
}
spin_lock(&i8253_lock);
@@ -159,12 +146,7 @@ static int pcsp_start_playing(struct snd_pcsp *chip)
atomic_set(&chip->timer_active, 1);
chip->thalf = 0;
- ns = pcsp_timer_update(&pcsp_chip.timer);
- if (!ns)
- return -EIO;
-
- hrtimer_start(&pcsp_chip.timer, ktime_set(0, ns), HRTIMER_MODE_REL);
- return 0;
+ hrtimer_start(&pcsp_chip.timer, ktime_set(0, 0), HRTIMER_MODE_REL);
}
static void pcsp_stop_playing(struct snd_pcsp *chip)
@@ -183,35 +165,26 @@ static void pcsp_stop_playing(struct snd_pcsp *chip)
spin_unlock(&i8253_lock);
}
-/*
- * Force to stop and sync the stream
- */
-void pcsp_sync_stop(struct snd_pcsp *chip)
-{
- local_irq_disable();
- pcsp_stop_playing(chip);
- local_irq_enable();
- hrtimer_cancel(&chip->timer);
- tasklet_kill(&pcsp_pcm_tasklet);
-}
-
static int snd_pcsp_playback_close(struct snd_pcm_substream *substream)
{
struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
#if PCSP_DEBUG
printk(KERN_INFO "PCSP: close called\n");
#endif
- pcsp_sync_stop(chip);
+ if (atomic_read(&chip->timer_active)) {
+ printk(KERN_ERR "PCSP: timer still active\n");
+ pcsp_stop_playing(chip);
+ }
+ spin_lock_irq(&chip->substream_lock);
chip->playback_substream = NULL;
+ spin_unlock_irq(&chip->substream_lock);
return 0;
}
static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *hw_params)
{
- struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
int err;
- pcsp_sync_stop(chip);
err = snd_pcm_lib_malloc_pages(substream,
params_buffer_bytes(hw_params));
if (err < 0)
@@ -221,11 +194,9 @@ static int snd_pcsp_playback_hw_params(struct snd_pcm_substream *substream,
static int snd_pcsp_playback_hw_free(struct snd_pcm_substream *substream)
{
- struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
#if PCSP_DEBUG
printk(KERN_INFO "PCSP: hw_free called\n");
#endif
- pcsp_sync_stop(chip);
return snd_pcm_lib_free_pages(substream);
}
@@ -241,12 +212,8 @@ static int snd_pcsp_playback_prepare(struct snd_pcm_substream *substream)
snd_pcm_lib_period_bytes(substream),
substream->runtime->periods);
#endif
- pcsp_sync_stop(chip);
chip->playback_ptr = 0;
chip->period_ptr = 0;
- chip->fmt_size =
- snd_pcm_format_physical_width(substream->runtime->format) >> 3;
- chip->is_signed = snd_pcm_format_signed(substream->runtime->format);
return 0;
}
@@ -259,7 +226,8 @@ static int snd_pcsp_trigger(struct snd_pcm_substream *substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
- return pcsp_start_playing(chip);
+ pcsp_start_playing(chip);
+ break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
pcsp_stop_playing(chip);
@@ -274,11 +242,7 @@ static snd_pcm_uframes_t snd_pcsp_playback_pointer(struct snd_pcm_substream
*substream)
{
struct snd_pcsp *chip = snd_pcm_substream_chip(substream);
- unsigned int pos;
- spin_lock(&chip->substream_lock);
- pos = chip->playback_ptr;
- spin_unlock(&chip->substream_lock);
- return bytes_to_frames(substream->runtime, pos);
+ return bytes_to_frames(substream->runtime, chip->playback_ptr);
}
static struct snd_pcm_hardware snd_pcsp_playback = {
@@ -315,7 +279,9 @@ static int snd_pcsp_playback_open(struct snd_pcm_substream *substream)
return -EBUSY;
}
runtime->hw = snd_pcsp_playback;
+ spin_lock_irq(&chip->substream_lock);
chip->playback_substream = substream;
+ spin_unlock_irq(&chip->substream_lock);
return 0;
}
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 6e3a1848447c..7003711f4fcc 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -208,8 +208,7 @@ config SND_OXYGEN
* AuzenTech X-Meridian
* Bgears b-Enspirer
* Club3D Theatron DTS
- * HT-Omega Claro (plus)
- * HT-Omega Claro halo (XT)
+ * HT-Omega Claro
* Razer Barracuda AC-1
* Sondigo Inferno
@@ -498,7 +497,129 @@ config SND_FM801_TEA575X
depends on SND_FM801_TEA575X_BOOL
default SND_FM801
-source "sound/pci/hda/Kconfig"
+config SND_HDA_INTEL
+ tristate "Intel HD Audio"
+ select SND_PCM
+ select SND_VMASTER
+ help
+ Say Y here to include support for Intel "High Definition
+ Audio" (Azalia) motherboard devices.
+
+ To compile this driver as a module, choose M here: the module
+ will be called snd-hda-intel.
+
+config SND_HDA_HWDEP
+ bool "Build hwdep interface for HD-audio driver"
+ depends on SND_HDA_INTEL
+ select SND_HWDEP
+ help
+ Say Y here to build a hwdep interface for HD-audio driver.
+ This interface can be used for out-of-band communication
+ with codecs for debugging purposes.
+
+config SND_HDA_INPUT_BEEP
+ bool "Support digital beep via input layer"
+ depends on SND_HDA_INTEL
+ depends on INPUT=y || INPUT=SND_HDA_INTEL
+ help
+ Say Y here to build a digital beep interface for HD-audio
+ driver. This interface is used to generate digital beeps.
+
+config SND_HDA_CODEC_REALTEK
+ bool "Build Realtek HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include Realtek HD-audio codec support in
+ snd-hda-intel driver, such as ALC880.
+
+config SND_HDA_CODEC_ANALOG
+ bool "Build Analog Device HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include Analog Device HD-audio codec support in
+ snd-hda-intel driver, such as AD1986A.
+
+config SND_HDA_CODEC_SIGMATEL
+ bool "Build IDT/Sigmatel HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include IDT (Sigmatel) HD-audio codec support in
+ snd-hda-intel driver, such as STAC9200.
+
+config SND_HDA_CODEC_VIA
+ bool "Build VIA HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include VIA HD-audio codec support in
+ snd-hda-intel driver, such as VT1708.
+
+config SND_HDA_CODEC_ATIHDMI
+ bool "Build ATI HDMI HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include ATI HDMI HD-audio codec support in
+ snd-hda-intel driver, such as ATI RS600 HDMI.
+
+config SND_HDA_CODEC_NVHDMI
+ bool "Build NVIDIA HDMI HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include NVIDIA HDMI HD-audio codec support in
+ snd-hda-intel driver, such as NVIDIA MCP78 HDMI.
+
+config SND_HDA_CODEC_CONEXANT
+ bool "Build Conexant HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include Conexant HD-audio codec support in
+ snd-hda-intel driver, such as CX20549.
+
+config SND_HDA_CODEC_CMEDIA
+ bool "Build C-Media HD-audio codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include C-Media HD-audio codec support in
+ snd-hda-intel driver, such as CMI9880.
+
+config SND_HDA_CODEC_SI3054
+ bool "Build Silicon Labs 3054 HD-modem codec support"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to include Silicon Labs 3054 HD-modem codec
+ (and compatibles) support in snd-hda-intel driver.
+
+config SND_HDA_GENERIC
+ bool "Enable generic HD-audio codec parser"
+ depends on SND_HDA_INTEL
+ default y
+ help
+ Say Y here to enable the generic HD-audio codec parser
+ in snd-hda-intel driver.
+
+config SND_HDA_POWER_SAVE
+ bool "Aggressive power-saving on HD-audio"
+ depends on SND_HDA_INTEL && EXPERIMENTAL
+ help
+ Say Y here to enable more aggressive power-saving mode on
+ HD-audio driver. The power-saving timeout can be configured
+ via power_save option or over sysfs on-the-fly.
+
+config SND_HDA_POWER_SAVE_DEFAULT
+ int "Default time-out for HD-audio power-save mode"
+ depends on SND_HDA_POWER_SAVE
+ default 0
+ help
+ The default time-out value in seconds for HD-audio automatic
+ power-save mode. 0 means to disable the power-save mode.
config SND_HDSP
tristate "RME Hammerfall DSP Audio"
diff --git a/sound/pci/ac97/ac97_codec.c b/sound/pci/ac97/ac97_codec.c
index e2b843b4f9d0..bd510eceff1f 100644
--- a/sound/pci/ac97/ac97_codec.c
+++ b/sound/pci/ac97/ac97_codec.c
@@ -175,7 +175,7 @@ static const struct ac97_codec_id snd_ac97_codec_ids[] = {
{ 0x574d4C04, 0xffffffff, "WM9704M,WM9704Q", patch_wolfson04, NULL},
{ 0x574d4C05, 0xffffffff, "WM9705,WM9710", patch_wolfson05, NULL},
{ 0x574d4C09, 0xffffffff, "WM9709", NULL, NULL},
-{ 0x574d4C12, 0xffffffff, "WM9711,WM9712,WM9715", patch_wolfson11, NULL},
+{ 0x574d4C12, 0xffffffff, "WM9711,WM9712", patch_wolfson11, NULL},
{ 0x574d4c13, 0xffffffff, "WM9713,WM9714", patch_wolfson13, NULL, AC97_DEFAULT_POWER_OFF},
{ 0x594d4800, 0xffffffff, "YMF743", patch_yamaha_ymf743, NULL },
{ 0x594d4802, 0xffffffff, "YMF752", NULL, NULL },
diff --git a/sound/pci/ac97/ac97_patch.c b/sound/pci/ac97/ac97_patch.c
index 2c7cd97d2234..6e831aff1bd0 100644
--- a/sound/pci/ac97/ac97_patch.c
+++ b/sound/pci/ac97/ac97_patch.c
@@ -2832,8 +2832,6 @@ static int patch_alc655(struct snd_ac97 * ac97)
val &= ~(1 << 1); /* Pin 47 is EAPD (for internal speaker) */
else
val |= (1 << 1); /* Pin 47 is spdif input pin */
- /* this seems missing on some hardwares */
- ac97->ext_id |= AC97_EI_SPDIF;
}
val &= ~(1 << 12); /* vref enable */
snd_ac97_write_cache(ac97, 0x7a, val);
diff --git a/sound/pci/ca0106/ca0106.h b/sound/pci/ca0106/ca0106.h
index 1c14ff424116..74175fc80c7f 100644
--- a/sound/pci/ca0106/ca0106.h
+++ b/sound/pci/ca0106/ca0106.h
@@ -686,7 +686,7 @@ struct snd_ca0106 {
spinlock_t emu_lock;
struct snd_ac97 *ac97;
- struct snd_pcm *pcm[4];
+ struct snd_pcm *pcm;
struct snd_ca0106_channel playback_channels[4];
struct snd_ca0106_channel capture_channels[4];
@@ -703,11 +703,6 @@ struct snd_ca0106 {
struct snd_ca_midi midi2;
u16 spi_dac_reg[16];
-
-#ifdef CONFIG_PM
-#define NUM_SAVED_VOLUMES 9
- unsigned int saved_vol[NUM_SAVED_VOLUMES];
-#endif
};
int snd_ca0106_mixer(struct snd_ca0106 *emu);
@@ -726,11 +721,3 @@ int snd_ca0106_i2c_write(struct snd_ca0106 *emu, u32 reg, u32 value);
int snd_ca0106_spi_write(struct snd_ca0106 * emu,
unsigned int data);
-
-#ifdef CONFIG_PM
-void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip);
-void snd_ca0106_mixer_resume(struct snd_ca0106 *chip);
-#else
-#define snd_ca0106_mixer_suspend(chip) do { } while (0)
-#define snd_ca0106_mixer_resume(chip) do { } while (0)
-#endif
diff --git a/sound/pci/ca0106/ca0106_main.c b/sound/pci/ca0106/ca0106_main.c
index cea8a7cdb1d5..88fbf285d2b7 100644
--- a/sound/pci/ca0106/ca0106_main.c
+++ b/sound/pci/ca0106/ca0106_main.c
@@ -847,18 +847,15 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
struct snd_pcm_substream *s;
u32 basic = 0;
u32 extended = 0;
- u32 bits;
- int running = 0;
+ int running=0;
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- running = 1;
+ running=1;
break;
case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
default:
- running = 0;
+ running=0;
break;
}
snd_pcm_group_for_each_entry(s, substream) {
@@ -868,32 +865,22 @@ static int snd_ca0106_pcm_trigger_playback(struct snd_pcm_substream *substream,
runtime = s->runtime;
epcm = runtime->private_data;
channel = epcm->channel_id;
- /* snd_printk("channel=%d\n",channel); */
+ //snd_printk("channel=%d\n",channel);
epcm->running = running;
- basic |= (0x1 << channel);
- extended |= (0x10 << channel);
+ basic |= (0x1<<channel);
+ extended |= (0x10<<channel);
snd_pcm_trigger_done(s, substream);
}
- /* snd_printk("basic=0x%x, extended=0x%x\n",basic, extended); */
+ //snd_printk("basic=0x%x, extended=0x%x\n",basic, extended);
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
- case SNDRV_PCM_TRIGGER_RESUME:
- bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0);
- bits |= extended;
- snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits);
- bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0);
- bits |= basic;
- snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits);
+ snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) | (extended));
+ snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0)|(basic));
break;
case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- bits = snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0);
- bits &= ~basic;
- snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, bits);
- bits = snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0);
- bits &= ~extended;
- snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, bits);
+ snd_ca0106_ptr_write(emu, BASIC_INTERRUPT, 0, snd_ca0106_ptr_read(emu, BASIC_INTERRUPT, 0) & ~(basic));
+ snd_ca0106_ptr_write(emu, EXTENDED_INT_MASK, 0, snd_ca0106_ptr_read(emu, EXTENDED_INT_MASK, 0) & ~(extended));
break;
default:
result = -EINVAL;
@@ -1116,13 +1103,21 @@ static int snd_ca0106_ac97(struct snd_ca0106 *chip)
return snd_ac97_mixer(pbus, &ac97, &chip->ac97);
}
-static void ca0106_stop_chip(struct snd_ca0106 *chip);
-
static int snd_ca0106_free(struct snd_ca0106 *chip)
{
- if (chip->res_port != NULL) {
- /* avoid access to already used hardware */
- ca0106_stop_chip(chip);
+ if (chip->res_port != NULL) { /* avoid access to already used hardware */
+ // disable interrupts
+ snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
+ outl(0, chip->port + INTE);
+ snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
+ udelay(1000);
+ // disable audio
+ //outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG);
+ outl(0, chip->port + HCFG);
+ /* FIXME: We need to stop and DMA transfers here.
+ * But as I am not sure how yet, we cannot from the dma pages.
+ * So we can fix: snd-malloc: Memory leak? pages not freed = 8
+ */
}
if (chip->irq >= 0)
free_irq(chip->irq, chip);
@@ -1208,14 +1203,15 @@ static irqreturn_t snd_ca0106_interrupt(int irq, void *dev_id)
return IRQ_HANDLED;
}
-static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
+static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device, struct snd_pcm **rpcm)
{
struct snd_pcm *pcm;
struct snd_pcm_substream *substream;
int err;
- err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm);
- if (err < 0)
+ if (rpcm)
+ *rpcm = NULL;
+ if ((err = snd_pcm_new(emu->card, "ca0106", device, 1, 1, &pcm)) < 0)
return err;
pcm->private_data = emu;
@@ -1242,6 +1238,7 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
pcm->info_flags = 0;
pcm->dev_subclass = SNDRV_PCM_SUBCLASS_GENERIC_MIX;
strcpy(pcm->name, "CA0106");
+ emu->pcm = pcm;
for(substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
substream;
@@ -1263,7 +1260,8 @@ static int __devinit snd_ca0106_pcm(struct snd_ca0106 *emu, int device)
return err;
}
- emu->pcm[device] = pcm;
+ if (rpcm)
+ *rpcm = pcm;
return 0;
}
@@ -1303,9 +1301,89 @@ static unsigned int i2c_adc_init[][2] = {
{ 0x15, ADC_MUX_LINEIN }, /* ADC Mixer control */
};
-static void ca0106_init_chip(struct snd_ca0106 *chip)
+static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
+ struct pci_dev *pci,
+ struct snd_ca0106 **rchip)
{
+ struct snd_ca0106 *chip;
+ struct snd_ca0106_details *c;
+ int err;
int ch;
+ static struct snd_device_ops ops = {
+ .dev_free = snd_ca0106_dev_free,
+ };
+
+ *rchip = NULL;
+
+ if ((err = pci_enable_device(pci)) < 0)
+ return err;
+ if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
+ pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
+ printk(KERN_ERR "error to set 32bit mask DMA\n");
+ pci_disable_device(pci);
+ return -ENXIO;
+ }
+
+ chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ if (chip == NULL) {
+ pci_disable_device(pci);
+ return -ENOMEM;
+ }
+
+ chip->card = card;
+ chip->pci = pci;
+ chip->irq = -1;
+
+ spin_lock_init(&chip->emu_lock);
+
+ chip->port = pci_resource_start(pci, 0);
+ if ((chip->res_port = request_region(chip->port, 0x20,
+ "snd_ca0106")) == NULL) {
+ snd_ca0106_free(chip);
+ printk(KERN_ERR "cannot allocate the port\n");
+ return -EBUSY;
+ }
+
+ if (request_irq(pci->irq, snd_ca0106_interrupt,
+ IRQF_SHARED, "snd_ca0106", chip)) {
+ snd_ca0106_free(chip);
+ printk(KERN_ERR "cannot grab irq\n");
+ return -EBUSY;
+ }
+ chip->irq = pci->irq;
+
+ /* This stores the periods table. */
+ if(snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci), 1024, &chip->buffer) < 0) {
+ snd_ca0106_free(chip);
+ return -ENOMEM;
+ }
+
+ pci_set_master(pci);
+ /* read serial */
+ pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
+ pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
+#if 1
+ printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n", chip->model,
+ pci->revision, chip->serial);
+#endif
+ strcpy(card->driver, "CA0106");
+ strcpy(card->shortname, "CA0106");
+
+ for (c = ca0106_chip_details; c->serial; c++) {
+ if (subsystem[dev]) {
+ if (c->serial == subsystem[dev])
+ break;
+ } else if (c->serial == chip->serial)
+ break;
+ }
+ chip->details = c;
+ if (subsystem[dev]) {
+ printk(KERN_INFO "snd-ca0106: Sound card name=%s, subsystem=0x%x. Forced to subsystem=0x%x\n",
+ c->name, chip->serial, subsystem[dev]);
+ }
+
+ sprintf(card->longname, "%s at 0x%lx irq %i",
+ c->name, chip->port, chip->irq);
outl(0, chip->port + INTE);
@@ -1323,31 +1401,31 @@ static void ca0106_init_chip(struct snd_ca0106 *chip)
* AN = 0 (Audio data)
* P = 0 (Consumer)
*/
- chip->spdif_bits[0] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
- snd_ca0106_ptr_write(chip, SPCS0, 0, chip->spdif_bits[0]);
+ snd_ca0106_ptr_write(chip, SPCS0, 0,
+ chip->spdif_bits[0] =
+ SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
+ SPCS_GENERATIONSTATUS | 0x00001200 |
+ 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
/* Only SPCS1 has been tested */
- chip->spdif_bits[1] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
- snd_ca0106_ptr_write(chip, SPCS1, 0, chip->spdif_bits[1]);
- chip->spdif_bits[2] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
- snd_ca0106_ptr_write(chip, SPCS2, 0, chip->spdif_bits[2]);
- chip->spdif_bits[3] =
- SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
- SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
- SPCS_GENERATIONSTATUS | 0x00001200 |
- 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT;
- snd_ca0106_ptr_write(chip, SPCS3, 0, chip->spdif_bits[3]);
+ snd_ca0106_ptr_write(chip, SPCS1, 0,
+ chip->spdif_bits[1] =
+ SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
+ SPCS_GENERATIONSTATUS | 0x00001200 |
+ 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
+ snd_ca0106_ptr_write(chip, SPCS2, 0,
+ chip->spdif_bits[2] =
+ SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
+ SPCS_GENERATIONSTATUS | 0x00001200 |
+ 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
+ snd_ca0106_ptr_write(chip, SPCS3, 0,
+ chip->spdif_bits[3] =
+ SPCS_CLKACCY_1000PPM | SPCS_SAMPLERATE_48 |
+ SPCS_CHANNELNUM_LEFT | SPCS_SOURCENUM_UNSPEC |
+ SPCS_GENERATIONSTATUS | 0x00001200 |
+ 0x00000000 | SPCS_EMPHASIS_NONE | SPCS_COPYRIGHT);
snd_ca0106_ptr_write(chip, PLAYBACK_MUTE, 0, 0x00fc0000);
snd_ca0106_ptr_write(chip, CAPTURE_MUTE, 0, 0x00fc0000);
@@ -1355,53 +1433,36 @@ static void ca0106_init_chip(struct snd_ca0106 *chip)
/* Write 0x8000 to AC97_REC_GAIN to mute it. */
outb(AC97_REC_GAIN, chip->port + AC97ADDRESS);
outw(0x8000, chip->port + AC97DATA);
-#if 0 /* FIXME: what are these? */
+#if 0
snd_ca0106_ptr_write(chip, SPCS0, 0, 0x2108006);
snd_ca0106_ptr_write(chip, 0x42, 0, 0x2108006);
snd_ca0106_ptr_write(chip, 0x43, 0, 0x2108006);
snd_ca0106_ptr_write(chip, 0x44, 0, 0x2108006);
#endif
- /* OSS drivers set this. */
- /* snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); */
-
+ //snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0xf0f003f); /* OSS drivers set this. */
/* Analog or Digital output */
snd_ca0106_ptr_write(chip, SPDIF_SELECT1, 0, 0xf);
- /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers.
- * Use 0x000f0000 for surround71
- */
- snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000);
-
+ snd_ca0106_ptr_write(chip, SPDIF_SELECT2, 0, 0x000f0000); /* 0x0b000000 for digital, 0x000b0000 for analog, from win2000 drivers. Use 0x000f0000 for surround71 */
chip->spdif_enable = 0; /* Set digital SPDIF output off */
- /*snd_ca0106_ptr_write(chip, 0x45, 0, 0);*/ /* Analogue out */
- /*snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00);*/ /* Digital out */
-
- /* goes to 0x40c80000 when doing SPDIF IN/OUT */
- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000);
- /* (Mute) CAPTURE feedback into PLAYBACK volume.
- * Only lower 16 bits matter.
- */
- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff);
- /* SPDIF IN Volume */
- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000);
- /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
- snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000);
+ //snd_ca0106_ptr_write(chip, 0x45, 0, 0); /* Analogue out */
+ //snd_ca0106_ptr_write(chip, 0x45, 0, 0xf00); /* Digital out */
+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 0, 0x40c81000); /* goes to 0x40c80000 when doing SPDIF IN/OUT */
+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 1, 0xffffffff); /* (Mute) CAPTURE feedback into PLAYBACK volume. Only lower 16 bits matter. */
+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 2, 0x30300000); /* SPDIF IN Volume */
+ snd_ca0106_ptr_write(chip, CAPTURE_CONTROL, 3, 0x00700000); /* SPDIF IN Volume, 0x70 = (vol & 0x3f) | 0x40 */
snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING1, 0, 0x32765410);
snd_ca0106_ptr_write(chip, PLAYBACK_ROUTING2, 0, 0x76767676);
snd_ca0106_ptr_write(chip, CAPTURE_ROUTING1, 0, 0x32765410);
snd_ca0106_ptr_write(chip, CAPTURE_ROUTING2, 0, 0x76767676);
-
- for (ch = 0; ch < 4; ch++) {
- /* Only high 16 bits matter */
- snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030);
+ for(ch = 0; ch < 4; ch++) {
+ snd_ca0106_ptr_write(chip, CAPTURE_VOLUME1, ch, 0x30303030); /* Only high 16 bits matter */
snd_ca0106_ptr_write(chip, CAPTURE_VOLUME2, ch, 0x30303030);
-#if 0 /* Mute */
- snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040);
- snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040);
- snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff);
- snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff);
-#endif
+ //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0x40404040); /* Mute */
+ //snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0x40404040); /* Mute */
+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME1, ch, 0xffffffff); /* Mute */
+ snd_ca0106_ptr_write(chip, PLAYBACK_VOLUME2, ch, 0xffffffff); /* Mute */
}
if (chip->details->i2c_adc == 1) {
/* Select MIC, Line in, TAD in, AUX in */
@@ -1420,56 +1481,44 @@ static void ca0106_init_chip(struct snd_ca0106 *chip)
chip->capture_source = 3;
}
- if (chip->details->gpio_type == 2) {
- /* The SB0438 use GPIO differently. */
- /* FIXME: Still need to find out what the other GPIO bits do.
- * E.g. For digital spdif out.
- */
+ if (chip->details->gpio_type == 2) { /* The SB0438 use GPIO differently. */
+ /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
outl(0x0, chip->port+GPIO);
- /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */
+ //outl(0x00f0e000, chip->port+GPIO); /* Analog */
outl(0x005f5301, chip->port+GPIO); /* Analog */
- } else if (chip->details->gpio_type == 1) {
- /* The SB0410 and SB0413 use GPIO differently. */
- /* FIXME: Still need to find out what the other GPIO bits do.
- * E.g. For digital spdif out.
- */
+ } else if (chip->details->gpio_type == 1) { /* The SB0410 and SB0413 use GPIO differently. */
+ /* FIXME: Still need to find out what the other GPIO bits do. E.g. For digital spdif out. */
outl(0x0, chip->port+GPIO);
- /* outl(0x00f0e000, chip->port+GPIO); */ /* Analog */
+ //outl(0x00f0e000, chip->port+GPIO); /* Analog */
outl(0x005f5301, chip->port+GPIO); /* Analog */
} else {
outl(0x0, chip->port+GPIO);
outl(0x005f03a3, chip->port+GPIO); /* Analog */
- /* outl(0x005f02a2, chip->port+GPIO); */ /* SPDIF */
+ //outl(0x005f02a2, chip->port+GPIO); /* SPDIF */
}
snd_ca0106_intr_enable(chip, 0x105); /* Win2000 uses 0x1e0 */
- /* outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG); */
- /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
- /* outl(0x00001409, chip->port+HCFG); */
- /* outl(0x00000009, chip->port+HCFG); */
- /* AC97 2.0, Enable outputs. */
- outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG);
+ //outl(HCFG_LOCKSOUNDCACHE|HCFG_AUDIOENABLE, chip->port+HCFG);
+ //outl(0x00001409, chip->port+HCFG); /* 0x1000 causes AC3 to fails. Maybe it effects 24 bit output. */
+ //outl(0x00000009, chip->port+HCFG);
+ outl(HCFG_AC97 | HCFG_AUDIOENABLE, chip->port+HCFG); /* AC97 2.0, Enable outputs. */
- if (chip->details->i2c_adc == 1) {
- /* The SB0410 and SB0413 use I2C to control ADC. */
+ if (chip->details->i2c_adc == 1) { /* The SB0410 and SB0413 use I2C to control ADC. */
int size, n;
size = ARRAY_SIZE(i2c_adc_init);
- /* snd_printk("I2C:array size=0x%x\n", size); */
- for (n = 0; n < size; n++)
- snd_ca0106_i2c_write(chip, i2c_adc_init[n][0],
- i2c_adc_init[n][1]);
- for (n = 0; n < 4; n++) {
- chip->i2c_capture_volume[n][0] = 0xcf;
- chip->i2c_capture_volume[n][1] = 0xcf;
+ //snd_printk("I2C:array size=0x%x\n", size);
+ for (n=0; n < size; n++) {
+ snd_ca0106_i2c_write(chip, i2c_adc_init[n][0], i2c_adc_init[n][1]);
+ }
+ for (n=0; n < 4; n++) {
+ chip->i2c_capture_volume[n][0]= 0xcf;
+ chip->i2c_capture_volume[n][1]= 0xcf;
}
- chip->i2c_capture_source = 2; /* Line in */
- /* Enable Line-in capture. MIC in currently untested. */
- /* snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); */
+ chip->i2c_capture_source=2; /* Line in */
+ //snd_ca0106_i2c_write(chip, ADC_MUX, ADC_MUX_LINEIN); /* Enable Line-in capture. MIC in currently untested. */
}
-
- if (chip->details->spi_dac == 1) {
- /* The SB0570 use SPI to control DAC. */
+ if (chip->details->spi_dac == 1) { /* The SB0570 use SPI to control DAC. */
int size, n;
size = ARRAY_SIZE(spi_dac_init);
@@ -1481,112 +1530,9 @@ static void ca0106_init_chip(struct snd_ca0106 *chip)
chip->spi_dac_reg[reg] = spi_dac_init[n];
}
}
-}
-
-static void ca0106_stop_chip(struct snd_ca0106 *chip)
-{
- /* disable interrupts */
- snd_ca0106_ptr_write(chip, BASIC_INTERRUPT, 0, 0);
- outl(0, chip->port + INTE);
- snd_ca0106_ptr_write(chip, EXTENDED_INT_MASK, 0, 0);
- udelay(1000);
- /* disable audio */
- /* outl(HCFG_LOCKSOUNDCACHE, chip->port + HCFG); */
- outl(0, chip->port + HCFG);
- /* FIXME: We need to stop and DMA transfers here.
- * But as I am not sure how yet, we cannot from the dma pages.
- * So we can fix: snd-malloc: Memory leak? pages not freed = 8
- */
-}
-static int __devinit snd_ca0106_create(int dev, struct snd_card *card,
- struct pci_dev *pci,
- struct snd_ca0106 **rchip)
-{
- struct snd_ca0106 *chip;
- struct snd_ca0106_details *c;
- int err;
- static struct snd_device_ops ops = {
- .dev_free = snd_ca0106_dev_free,
- };
-
- *rchip = NULL;
-
- err = pci_enable_device(pci);
- if (err < 0)
- return err;
- if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0 ||
- pci_set_consistent_dma_mask(pci, DMA_32BIT_MASK) < 0) {
- printk(KERN_ERR "error to set 32bit mask DMA\n");
- pci_disable_device(pci);
- return -ENXIO;
- }
-
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
- if (chip == NULL) {
- pci_disable_device(pci);
- return -ENOMEM;
- }
-
- chip->card = card;
- chip->pci = pci;
- chip->irq = -1;
-
- spin_lock_init(&chip->emu_lock);
-
- chip->port = pci_resource_start(pci, 0);
- chip->res_port = request_region(chip->port, 0x20, "snd_ca0106");
- if (!chip->res_port) {
- snd_ca0106_free(chip);
- printk(KERN_ERR "cannot allocate the port\n");
- return -EBUSY;
- }
-
- if (request_irq(pci->irq, snd_ca0106_interrupt,
- IRQF_SHARED, "snd_ca0106", chip)) {
- snd_ca0106_free(chip);
- printk(KERN_ERR "cannot grab irq\n");
- return -EBUSY;
- }
- chip->irq = pci->irq;
-
- /* This stores the periods table. */
- if (snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, snd_dma_pci_data(pci),
- 1024, &chip->buffer) < 0) {
- snd_ca0106_free(chip);
- return -ENOMEM;
- }
-
- pci_set_master(pci);
- /* read serial */
- pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &chip->serial);
- pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &chip->model);
- printk(KERN_INFO "snd-ca0106: Model %04x Rev %08x Serial %08x\n",
- chip->model, pci->revision, chip->serial);
- strcpy(card->driver, "CA0106");
- strcpy(card->shortname, "CA0106");
-
- for (c = ca0106_chip_details; c->serial; c++) {
- if (subsystem[dev]) {
- if (c->serial == subsystem[dev])
- break;
- } else if (c->serial == chip->serial)
- break;
- }
- chip->details = c;
- if (subsystem[dev]) {
- printk(KERN_INFO "snd-ca0106: Sound card name=%s, "
- "subsystem=0x%x. Forced to subsystem=0x%x\n",
- c->name, chip->serial, subsystem[dev]);
- }
-
- sprintf(card->longname, "%s at 0x%lx irq %i",
- c->name, chip->port, chip->irq);
-
- ca0106_init_chip(chip);
-
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops);
- if (err < 0) {
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
+ chip, &ops)) < 0) {
snd_ca0106_free(chip);
return err;
}
@@ -1683,7 +1629,7 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
static int dev;
struct snd_card *card;
struct snd_ca0106 *chip;
- int i, err;
+ int err;
if (dev >= SNDRV_CARDS)
return -ENODEV;
@@ -1696,30 +1642,44 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
if (card == NULL)
return -ENOMEM;
- err = snd_ca0106_create(dev, card, pci, &chip);
- if (err < 0)
- goto error;
-
- for (i = 0; i < 4; i++) {
- err = snd_ca0106_pcm(chip, i);
- if (err < 0)
- goto error;
+ if ((err = snd_ca0106_create(dev, card, pci, &chip)) < 0) {
+ snd_card_free(card);
+ return err;
}
- if (chip->details->ac97 == 1) {
- /* The SB0410 and SB0413 do not have an AC97 chip. */
- err = snd_ca0106_ac97(chip);
- if (err < 0)
- goto error;
+ if ((err = snd_ca0106_pcm(chip, 0, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ if ((err = snd_ca0106_pcm(chip, 1, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ if ((err = snd_ca0106_pcm(chip, 2, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ if ((err = snd_ca0106_pcm(chip, 3, NULL)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ if (chip->details->ac97 == 1) { /* The SB0410 and SB0413 do not have an AC97 chip. */
+ if ((err = snd_ca0106_ac97(chip)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
+ }
+ if ((err = snd_ca0106_mixer(chip)) < 0) {
+ snd_card_free(card);
+ return err;
}
- err = snd_ca0106_mixer(chip);
- if (err < 0)
- goto error;
snd_printdd("ca0106: probe for MIDI channel A ...");
- err = snd_ca0106_midi(chip, CA0106_MIDI_CHAN_A);
- if (err < 0)
- goto error;
+ if ((err = snd_ca0106_midi(chip,CA0106_MIDI_CHAN_A)) < 0) {
+ snd_card_free(card);
+ snd_printdd(" failed, err=0x%x\n",err);
+ return err;
+ }
snd_printdd(" done.\n");
#ifdef CONFIG_PROC_FS
@@ -1728,17 +1688,14 @@ static int __devinit snd_ca0106_probe(struct pci_dev *pci,
snd_card_set_dev(card, &pci->dev);
- err = snd_card_register(card);
- if (err < 0)
- goto error;
+ if ((err = snd_card_register(card)) < 0) {
+ snd_card_free(card);
+ return err;
+ }
pci_set_drvdata(pci, card);
dev++;
return 0;
-
- error:
- snd_card_free(card);
- return err;
}
static void __devexit snd_ca0106_remove(struct pci_dev *pci)
@@ -1747,52 +1704,6 @@ static void __devexit snd_ca0106_remove(struct pci_dev *pci)
pci_set_drvdata(pci, NULL);
}
-#ifdef CONFIG_PM
-static int snd_ca0106_suspend(struct pci_dev *pci, pm_message_t state)
-{
- struct snd_card *card = pci_get_drvdata(pci);
- struct snd_ca0106 *chip = card->private_data;
- int i;
-
- snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
- for (i = 0; i < 4; i++)
- snd_pcm_suspend_all(chip->pcm[i]);
- snd_ac97_suspend(chip->ac97);
- snd_ca0106_mixer_suspend(chip);
-
- ca0106_stop_chip(chip);
-
- pci_disable_device(pci);
- pci_save_state(pci);
- pci_set_power_state(pci, pci_choose_state(pci, state));
- return 0;
-}
-
-static int snd_ca0106_resume(struct pci_dev *pci)
-{
- struct snd_card *card = pci_get_drvdata(pci);
- struct snd_ca0106 *chip = card->private_data;
- int i;
-
- pci_set_power_state(pci, PCI_D0);
- pci_restore_state(pci);
- pci_enable_device(pci);
- pci_set_master(pci);
-
- ca0106_init_chip(chip);
-
- snd_ac97_resume(chip->ac97);
- snd_ca0106_mixer_resume(chip);
- if (chip->details->spi_dac) {
- for (i = 0; i < ARRAY_SIZE(chip->spi_dac_reg); i++)
- snd_ca0106_spi_write(chip, chip->spi_dac_reg[i]);
- }
-
- snd_power_change_state(card, SNDRV_CTL_POWER_D0);
- return 0;
-}
-#endif
-
// PCI IDs
static struct pci_device_id snd_ca0106_ids[] = {
{ 0x1102, 0x0007, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 }, /* Audigy LS or Live 24bit */
@@ -1806,10 +1717,6 @@ static struct pci_driver driver = {
.id_table = snd_ca0106_ids,
.probe = snd_ca0106_probe,
.remove = __devexit_p(snd_ca0106_remove),
-#ifdef CONFIG_PM
- .suspend = snd_ca0106_suspend,
- .resume = snd_ca0106_resume,
-#endif
};
// initialization of the module
diff --git a/sound/pci/ca0106/ca0106_mixer.c b/sound/pci/ca0106/ca0106_mixer.c
index cccc32cdb943..3025ed1b6e1e 100644
--- a/sound/pci/ca0106/ca0106_mixer.c
+++ b/sound/pci/ca0106/ca0106_mixer.c
@@ -75,84 +75,6 @@
#include "ca0106.h"
-static void ca0106_spdif_enable(struct snd_ca0106 *emu)
-{
- unsigned int val;
-
- if (emu->spdif_enable) {
- /* Digital */
- snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
- snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
- val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000;
- snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
- val = inl(emu->port + GPIO) & ~0x101;
- outl(val, emu->port + GPIO);
-
- } else {
- /* Analog */
- snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
- snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
- val = snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000;
- snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0, val);
- val = inl(emu->port + GPIO) | 0x101;
- outl(val, emu->port + GPIO);
- }
-}
-
-static void ca0106_set_capture_source(struct snd_ca0106 *emu)
-{
- unsigned int val = emu->capture_source;
- unsigned int source, mask;
- source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
- mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
- snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
-}
-
-static void ca0106_set_i2c_capture_source(struct snd_ca0106 *emu,
- unsigned int val, int force)
-{
- unsigned int ngain, ogain;
- u32 source;
-
- snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
- ngain = emu->i2c_capture_volume[val][0]; /* Left */
- ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
- if (force || ngain != ogain)
- snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ngain & 0xff);
- ngain = emu->i2c_capture_volume[val][1]; /* Right */
- ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Right */
- if (force || ngain != ogain)
- snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ngain & 0xff);
- source = 1 << val;
- snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
- emu->i2c_capture_source = val;
-}
-
-static void ca0106_set_capture_mic_line_in(struct snd_ca0106 *emu)
-{
- u32 tmp;
-
- if (emu->capture_mic_line_in) {
- /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
- tmp = inl(emu->port+GPIO) & ~0x400;
- tmp = tmp | 0x400;
- outl(tmp, emu->port+GPIO);
- /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC); */
- } else {
- /* snd_ca0106_i2c_write(emu, ADC_MUX, 0); */ /* Mute input */
- tmp = inl(emu->port+GPIO) & ~0x400;
- outl(tmp, emu->port+GPIO);
- /* snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN); */
- }
-}
-
-static void ca0106_set_spdif_bits(struct snd_ca0106 *emu, int idx)
-{
- snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, emu->spdif_bits[idx]);
-}
-
-/*
- */
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale1, -5175, 25, 1);
static const DECLARE_TLV_DB_SCALE(snd_ca0106_db_scale2, -10350, 50, 1);
@@ -173,12 +95,30 @@ static int snd_ca0106_shared_spdif_put(struct snd_kcontrol *kcontrol,
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
+ u32 mask;
val = !!ucontrol->value.integer.value[0];
change = (emu->spdif_enable != val);
if (change) {
emu->spdif_enable = val;
- ca0106_spdif_enable(emu);
+ if (val) {
+ /* Digital */
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x0b000000);
+ snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
+ snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) & ~0x1000);
+ mask = inl(emu->port + GPIO) & ~0x101;
+ outl(mask, emu->port + GPIO);
+
+ } else {
+ /* Analog */
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT1, 0, 0xf);
+ snd_ca0106_ptr_write(emu, SPDIF_SELECT2, 0, 0x000f0000);
+ snd_ca0106_ptr_write(emu, CAPTURE_CONTROL, 0,
+ snd_ca0106_ptr_read(emu, CAPTURE_CONTROL, 0) | 0x1000);
+ mask = inl(emu->port + GPIO) | 0x101;
+ outl(mask, emu->port + GPIO);
+ }
}
return change;
}
@@ -214,6 +154,8 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
+ u32 mask;
+ u32 source;
val = ucontrol->value.enumerated.item[0] ;
if (val >= 6)
@@ -221,7 +163,9 @@ static int snd_ca0106_capture_source_put(struct snd_kcontrol *kcontrol,
change = (emu->capture_source != val);
if (change) {
emu->capture_source = val;
- ca0106_set_capture_source(emu);
+ source = (val << 28) | (val << 24) | (val << 20) | (val << 16);
+ mask = snd_ca0106_ptr_read(emu, CAPTURE_SOURCE, 0) & 0xffff;
+ snd_ca0106_ptr_write(emu, CAPTURE_SOURCE, 0, source | mask);
}
return change;
}
@@ -256,7 +200,9 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
{
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int source_id;
+ unsigned int ngain, ogain;
int change = 0;
+ u32 source;
/* If the capture source has changed,
* update the capture volume from the cached value
* for the particular source.
@@ -266,7 +212,18 @@ static int snd_ca0106_i2c_capture_source_put(struct snd_kcontrol *kcontrol,
return -EINVAL;
change = (emu->i2c_capture_source != source_id);
if (change) {
- ca0106_set_i2c_capture_source(emu, source_id, 0);
+ snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
+ ngain = emu->i2c_capture_volume[source_id][0]; /* Left */
+ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][0]; /* Left */
+ if (ngain != ogain)
+ snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCL, ((ngain) & 0xff));
+ ngain = emu->i2c_capture_volume[source_id][1]; /* Left */
+ ogain = emu->i2c_capture_volume[emu->i2c_capture_source][1]; /* Left */
+ if (ngain != ogain)
+ snd_ca0106_i2c_write(emu, ADC_ATTEN_ADCR, ((ngain) & 0xff));
+ source = 1 << source_id;
+ snd_ca0106_i2c_write(emu, ADC_MUX, source); /* Set source */
+ emu->i2c_capture_source = source_id;
}
return change;
}
@@ -314,6 +271,7 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
struct snd_ca0106 *emu = snd_kcontrol_chip(kcontrol);
unsigned int val;
int change = 0;
+ u32 tmp;
val = ucontrol->value.enumerated.item[0] ;
if (val > 1)
@@ -321,7 +279,18 @@ static int snd_ca0106_capture_mic_line_in_put(struct snd_kcontrol *kcontrol,
change = (emu->capture_mic_line_in != val);
if (change) {
emu->capture_mic_line_in = val;
- ca0106_set_capture_mic_line_in(emu);
+ if (val) {
+ //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
+ tmp = inl(emu->port+GPIO) & ~0x400;
+ tmp = tmp | 0x400;
+ outl(tmp, emu->port+GPIO);
+ //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_MIC);
+ } else {
+ //snd_ca0106_i2c_write(emu, ADC_MUX, 0); /* Mute input */
+ tmp = inl(emu->port+GPIO) & ~0x400;
+ outl(tmp, emu->port+GPIO);
+ //snd_ca0106_i2c_write(emu, ADC_MUX, ADC_MUX_LINEIN);
+ }
}
return change;
}
@@ -390,8 +359,8 @@ static int snd_ca0106_spdif_put(struct snd_kcontrol *kcontrol,
(ucontrol->value.iec958.status[3] << 24);
change = val != emu->spdif_bits[idx];
if (change) {
+ snd_ca0106_ptr_write(emu, SPCS0 + idx, 0, val);
emu->spdif_bits[idx] = val;
- ca0106_set_spdif_bits(emu, idx);
}
return change;
}
@@ -804,50 +773,3 @@ int __devinit snd_ca0106_mixer(struct snd_ca0106 *emu)
return 0;
}
-#ifdef CONFIG_PM
-struct ca0106_vol_tbl {
- unsigned int reg;
- unsigned int channel_id;
-};
-
-static struct ca0106_vol_tbl saved_volumes[NUM_SAVED_VOLUMES] = {
- { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME2 },
- { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME2 },
- { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME2 },
- { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME2 },
- { CONTROL_FRONT_CHANNEL, PLAYBACK_VOLUME1 },
- { CONTROL_REAR_CHANNEL, PLAYBACK_VOLUME1 },
- { CONTROL_CENTER_LFE_CHANNEL, PLAYBACK_VOLUME1 },
- { CONTROL_UNKNOWN_CHANNEL, PLAYBACK_VOLUME1 },
- { 1, CAPTURE_CONTROL },
-};
-
-void snd_ca0106_mixer_suspend(struct snd_ca0106 *chip)
-{
- int i;
-
- /* save volumes */
- for (i = 0; i < NUM_SAVED_VOLUMES; i++)
- chip->saved_vol[i] =
- snd_ca0106_ptr_read(chip, saved_volumes[i].reg,
- saved_volumes[i].channel_id);
-}
-
-void snd_ca0106_mixer_resume(struct snd_ca0106 *chip)
-{
- int i;
-
- for (i = 0; i < NUM_SAVED_VOLUMES; i++)
- snd_ca0106_ptr_write(chip, saved_volumes[i].reg,
- saved_volumes[i].channel_id,
- chip->saved_vol[i]);
-
- ca0106_spdif_enable(chip);
- ca0106_set_capture_source(chip);
- ca0106_set_i2c_capture_source(chip, chip->i2c_capture_source, 1);
- for (i = 0; i < 4; i++)
- ca0106_set_spdif_bits(chip, i);
- if (chip->details->i2c_adc)
- ca0106_set_capture_mic_line_in(chip);
-}
-#endif /* CONFIG_PM */
diff --git a/sound/pci/cs46xx/cs46xx_lib.c b/sound/pci/cs46xx/cs46xx_lib.c
index 8ab07aa63652..fb6dc3980257 100644
--- a/sound/pci/cs46xx/cs46xx_lib.c
+++ b/sound/pci/cs46xx/cs46xx_lib.c
@@ -3640,10 +3640,7 @@ int snd_cs46xx_resume(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
struct snd_cs46xx *chip = card->private_data;
- int amp_saved;
-#ifdef CONFIG_SND_CS46XX_NEW_DSP
- int i;
-#endif
+ int i, amp_saved;
pci_set_power_state(pci, PCI_D0);
pci_restore_state(pci);
diff --git a/sound/pci/emu10k1/emu10k1_main.c b/sound/pci/emu10k1/emu10k1_main.c
index 7958006a1d66..de5ee8f097f6 100644
--- a/sound/pci/emu10k1/emu10k1_main.c
+++ b/sound/pci/emu10k1/emu10k1_main.c
@@ -69,7 +69,7 @@ MODULE_FIRMWARE(EMU1010_NOTEBOOK_FILENAME);
* EMU10K1 init / done
*************************************************************************/
-void snd_emu10k1_voice_init(struct snd_emu10k1 *emu, int ch)
+void snd_emu10k1_voice_init(struct snd_emu10k1 * emu, int ch)
{
snd_emu10k1_ptr_write(emu, DCYSUSV, ch, 0);
snd_emu10k1_ptr_write(emu, IP, ch, 0);
@@ -151,9 +151,9 @@ static unsigned int i2c_adc_init[][2] = {
{ 0x12, 0x32 }, /* ALC Control 3 */
{ 0x13, 0x00 }, /* Noise gate control */
{ 0x14, 0xa6 }, /* Limiter control */
- { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for A2ZS Notebook */
+ { 0x15, ADC_MUX_2 }, /* ADC Mixer control. Mic for Audigy 2 ZS Notebook */
};
-
+
static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
{
unsigned int silent_page;
@@ -161,8 +161,8 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
u32 tmp;
/* disable audio and lock cache */
- outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK |
- HCFG_MUTEBUTTONENABLE, emu->port + HCFG);
+ outl(HCFG_LOCKSOUNDCACHE | HCFG_LOCKTANKCACHE_MASK | HCFG_MUTEBUTTONENABLE,
+ emu->port + HCFG);
/* reset recording buffers */
snd_emu10k1_ptr_write(emu, MICBS, 0, ADCBS_BUFSIZE_NONE);
@@ -179,7 +179,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
snd_emu10k1_ptr_write(emu, SOLEL, 0, 0);
snd_emu10k1_ptr_write(emu, SOLEH, 0, 0);
- if (emu->audigy) {
+ if (emu->audigy){
/* set SPDIF bypass mode */
snd_emu10k1_ptr_write(emu, SPBYPASS, 0, SPBYPASS_FORMAT);
/* enable rear left + rear right AC97 slots */
@@ -197,12 +197,12 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
/* Hacks for Alice3 to work independent of haP16V driver */
- /* Setup SRCMulti_I2S SamplingRate */
+ //Setup SRCMulti_I2S SamplingRate
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
tmp &= 0xfffff1ff;
tmp |= (0x2<<9);
snd_emu10k1_ptr_write(emu, A_SPDIF_SAMPLERATE, 0, tmp);
-
+
/* Setup SRCSel (Enable Spdif,I2S SRCMulti) */
snd_emu10k1_ptr20_write(emu, SRCSel, 0, 0x14);
/* Setup SRCMulti Input Audio Enable */
@@ -217,7 +217,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
if (emu->card_capabilities->ca0108_chip) { /* audigy2 Value */
/* Hacks for Alice3 to work independent of haP16V driver */
snd_printk(KERN_INFO "Audigy2 value: Special config.\n");
- /* Setup SRCMulti_I2S SamplingRate */
+ //Setup SRCMulti_I2S SamplingRate
tmp = snd_emu10k1_ptr_read(emu, A_SPDIF_SAMPLERATE, 0);
tmp &= 0xfffff1ff;
tmp |= (0x2<<9);
@@ -270,13 +270,13 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
size = ARRAY_SIZE(i2c_adc_init);
for (n = 0; n < size; n++)
snd_emu10k1_i2c_write(emu, i2c_adc_init[n][0], i2c_adc_init[n][1]);
- for (n = 0; n < 4; n++) {
- emu->i2c_capture_volume[n][0] = 0xcf;
- emu->i2c_capture_volume[n][1] = 0xcf;
+ for (n=0; n < 4; n++) {
+ emu->i2c_capture_volume[n][0]= 0xcf;
+ emu->i2c_capture_volume[n][1]= 0xcf;
}
}
-
+
snd_emu10k1_ptr_write(emu, PTB, 0, emu->ptb_pages.addr);
snd_emu10k1_ptr_write(emu, TCB, 0, 0); /* taken from original driver */
snd_emu10k1_ptr_write(emu, TCBS, 0, 4); /* taken from original driver */
@@ -313,7 +313,7 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
(emu->model == 0x21 && emu->revision < 6))
outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE, emu->port + HCFG);
else
- /* With on-chip joystick */
+ // With on-chip joystick
outl(HCFG_LOCKTANKCACHE_MASK | HCFG_AUTOMUTE | HCFG_JOYENABLE, emu->port + HCFG);
if (enable_ir) { /* enable IR for SB Live */
@@ -335,9 +335,9 @@ static int snd_emu10k1_init(struct snd_emu10k1 *emu, int enable_ir, int resume)
outl(reg | HCFG_GPOUT1 | HCFG_GPOUT2, emu->port + HCFG);
udelay(100);
outl(reg, emu->port + HCFG);
- }
+ }
}
-
+
if (emu->card_capabilities->emu_model) {
; /* Disable all access to A_IOCFG for the emu1010 */
} else if (emu->card_capabilities->i2c_adc) {
@@ -364,7 +364,7 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
; /* Disable A_IOCFG for Audigy 2 ZS Notebook */
} else if (emu->audigy) {
outl(inl(emu->port + A_IOCFG) & ~0x44, emu->port + A_IOCFG);
-
+
if (emu->card_capabilities->ca0151_chip) { /* audigy2 */
/* Unmute Analog now. Set GPO6 to 1 for Apollo.
* This has to be done after init ALice3 I2SOut beyond 48KHz.
@@ -378,12 +378,12 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
outl(inl(emu->port + A_IOCFG) | 0x0080, emu->port + A_IOCFG);
}
}
-
+
#if 0
{
unsigned int tmp;
/* FIXME: the following routine disables LiveDrive-II !! */
- /* TOSLink detection */
+ // TOSLink detection
emu->tos_link = 0;
tmp = inl(emu->port + HCFG);
if (tmp & (HCFG_GPINPUT0 | HCFG_GPINPUT1)) {
@@ -400,7 +400,7 @@ static void snd_emu10k1_audio_enable(struct snd_emu10k1 *emu)
snd_emu10k1_intr_enable(emu, INTE_PCIERRORENABLE);
}
-int snd_emu10k1_done(struct snd_emu10k1 *emu)
+int snd_emu10k1_done(struct snd_emu10k1 * emu)
{
int ch;
@@ -495,7 +495,7 @@ int snd_emu10k1_done(struct snd_emu10k1 *emu)
#define EC_LAST_PROMFILE_ADDR 0x2f
-#define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The
+#define EC_SERIALNUM_ADDR 0x30 /* First word of serial number. The
* can be up to 30 characters in length
* and is stored as a NULL-terminated
* ASCII string. Any unused bytes must be
@@ -503,8 +503,8 @@ int snd_emu10k1_done(struct snd_emu10k1 *emu)
#define EC_CHECKSUM_ADDR 0x3f /* Location at which checksum is stored */
-/* Most of this stuff is pretty self-evident. According to the hardware
- * dudes, we need to leave the ADCCAL bit low in order to avoid a DC
+/* Most of this stuff is pretty self-evident. According to the hardware
+ * dudes, we need to leave the ADCCAL bit low in order to avoid a DC
* offset problem. Weird.
*/
#define EC_RAW_RUN_MODE (EC_DACMUTEN | EC_ADCRSTN | EC_TRIM_MUTEN | \
@@ -523,7 +523,7 @@ int snd_emu10k1_done(struct snd_emu10k1 *emu)
* register.
*/
-static void snd_emu10k1_ecard_write(struct snd_emu10k1 *emu, unsigned int value)
+static void snd_emu10k1_ecard_write(struct snd_emu10k1 * emu, unsigned int value)
{
unsigned short count;
unsigned int data;
@@ -561,7 +561,7 @@ static void snd_emu10k1_ecard_write(struct snd_emu10k1 *emu, unsigned int value)
* channel.
*/
-static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 *emu,
+static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 * emu,
unsigned short gain)
{
unsigned int bit;
@@ -574,7 +574,7 @@ static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 *emu,
for (bit = (1 << 15); bit; bit >>= 1) {
unsigned int value;
-
+
value = emu->ecard_ctrl & ~(EC_TRIM_CSN | EC_TRIM_SDATA);
if (gain & bit)
@@ -589,7 +589,7 @@ static void snd_emu10k1_ecard_setadcgain(struct snd_emu10k1 *emu,
snd_emu10k1_ecard_write(emu, emu->ecard_ctrl);
}
-static int snd_emu10k1_ecard_init(struct snd_emu10k1 *emu)
+static int snd_emu10k1_ecard_init(struct snd_emu10k1 * emu)
{
unsigned int hc_value;
@@ -598,7 +598,7 @@ static int snd_emu10k1_ecard_init(struct snd_emu10k1 *emu)
EC_SPDIF0_SELECT(EC_DEFAULT_SPDIF0_SEL) |
EC_SPDIF1_SELECT(EC_DEFAULT_SPDIF1_SEL);
- /* Step 0: Set the codec type in the hardware control register
+ /* Step 0: Set the codec type in the hardware control register
* and enable audio output */
hc_value = inl(emu->port + HCFG);
outl(hc_value | HCFG_AUDIOENABLE | HCFG_CODECFORMAT_I2S, emu->port + HCFG);
@@ -629,7 +629,7 @@ static int snd_emu10k1_ecard_init(struct snd_emu10k1 *emu)
return 0;
}
-static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
+static int snd_emu10k1_cardbus_init(struct snd_emu10k1 * emu)
{
unsigned long special_port;
unsigned int value;
@@ -656,7 +656,7 @@ static int snd_emu10k1_cardbus_init(struct snd_emu10k1 *emu)
return 0;
}
-static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filename)
+static int snd_emu1010_load_firmware(struct snd_emu10k1 * emu, const char * filename)
{
int err;
int n, i;
@@ -666,12 +666,11 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filena
unsigned long flags;
const struct firmware *fw_entry;
- err = request_firmware(&fw_entry, filename, &emu->pci->dev);
- if (err != 0) {
- snd_printk(KERN_ERR "firmware: %s not found. Err = %d\n", filename, err);
+ if ((err = request_firmware(&fw_entry, filename, &emu->pci->dev)) != 0) {
+ snd_printk(KERN_ERR "firmware: %s not found. Err=%d\n",filename, err);
return err;
}
- snd_printk(KERN_INFO "firmware size = 0x%zx\n", fw_entry->size);
+ snd_printk(KERN_INFO "firmware size=0x%zx\n", fw_entry->size);
/* The FPGA is a Xilinx Spartan IIE XC2S50E */
/* GPIO7 -> FPGA PGMN
@@ -686,13 +685,13 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filena
outl(0x80, emu->port + A_IOCFG); /* Leave bit 7 set during netlist setup. */
write_post = inl(emu->port + A_IOCFG);
udelay(100); /* Allow FPGA memory to clean */
- for (n = 0; n < fw_entry->size; n++) {
- value = fw_entry->data[n];
- for (i = 0; i < 8; i++) {
+ for(n = 0; n < fw_entry->size; n++) {
+ value=fw_entry->data[n];
+ for(i = 0; i < 8; i++) {
reg = 0x80;
if (value & 0x1)
reg = reg | 0x20;
- value = value >> 1;
+ value = value >> 1;
outl(reg, emu->port + A_IOCFG);
write_post = inl(emu->port + A_IOCFG);
outl(reg | 0x40, emu->port + A_IOCFG);
@@ -704,14 +703,14 @@ static int snd_emu1010_load_firmware(struct snd_emu10k1 *emu, const char *filena
write_post = inl(emu->port + A_IOCFG);
spin_unlock_irqrestore(&emu->emu_lock, flags);
- release_firmware(fw_entry);
+ release_firmware(fw_entry);
return 0;
}
static int emu1010_firmware_thread(void *data)
{
- struct snd_emu10k1 *emu = data;
- int tmp, tmp2;
+ struct snd_emu10k1 * emu = data;
+ int tmp,tmp2;
int reg;
int err;
@@ -720,50 +719,50 @@ static int emu1010_firmware_thread(void *data)
msleep_interruptible(1000);
if (kthread_should_stop())
break;
- snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp); /* IRQ Status */
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg); /* OPTIONS: Which cards are attached to the EMU */
+ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &tmp ); /* IRQ Status */
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg ); /* OPTIONS: Which cards are attached to the EMU */
if (reg & EMU_HANA_OPTION_DOCK_OFFLINE) {
/* Audio Dock attached */
/* Return to Audio Dock programming mode */
snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware\n");
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK);
+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, EMU_HANA_FPGA_CONFIG_AUDIODOCK );
if (emu->card_capabilities->emu_model ==
EMU_MODEL_EMU1010) {
- err = snd_emu1010_load_firmware(emu, DOCK_FILENAME);
- if (err != 0)
+ if ((err = snd_emu1010_load_firmware(emu, DOCK_FILENAME)) != 0) {
continue;
+ }
} else if (emu->card_capabilities->emu_model ==
EMU_MODEL_EMU1010B) {
- err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME);
- if (err != 0)
+ if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
continue;
+ }
} else if (emu->card_capabilities->emu_model ==
EMU_MODEL_EMU1616) {
- err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME);
- if (err != 0)
+ if ((err = snd_emu1010_load_firmware(emu, MICRO_DOCK_FILENAME)) != 0) {
continue;
+ }
}
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0);
- snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg);
- snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS = 0x%x\n", reg);
+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0 );
+ snd_emu1010_fpga_read(emu, EMU_HANA_IRQ_STATUS, &reg );
+ snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_IRQ_STATUS=0x%x\n",reg);
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
- snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID = 0x%x\n", reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+ snd_printk(KERN_INFO "emu1010: EMU_HANA+DOCK_ID=0x%x\n",reg);
if ((reg & 0x1f) != 0x15) {
/* FPGA failed to be programmed */
- snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg = 0x%x\n", reg);
+ snd_printk(KERN_INFO "emu1010: Loading Audio Dock Firmware file failed, reg=0x%x\n", reg);
continue;
}
snd_printk(KERN_INFO "emu1010: Audio Dock Firmware loaded\n");
- snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp);
- snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2);
- snd_printk("Audio Dock ver:%d.%d\n", tmp, tmp2);
+ snd_emu1010_fpga_read(emu, EMU_DOCK_MAJOR_REV, &tmp );
+ snd_emu1010_fpga_read(emu, EMU_DOCK_MINOR_REV, &tmp2 );
+ snd_printk("Audio Dock ver:%d.%d\n",tmp ,tmp2);
/* Sync clocking between 1010 and Dock */
/* Allow DLL to settle */
msleep(10);
/* Unmute all. Default is muted after a firmware load */
- snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE);
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, EMU_UNMUTE );
}
}
snd_printk(KERN_INFO "emu1010: firmware thread stopping\n");
@@ -801,10 +800,10 @@ static int emu1010_firmware_thread(void *data)
* 16 x 16-bit playback - snd_emu10k1_fx8010_playback_ops
* 16 x 32-bit capture - snd_emu10k1_capture_efx_ops
*/
-static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
+static int snd_emu10k1_emu1010_init(struct snd_emu10k1 * emu)
{
unsigned int i;
- int tmp, tmp2;
+ int tmp,tmp2;
int reg;
int err;
const char *filename = NULL;
@@ -819,7 +818,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
* Lock Tank Memory Cache,
* Mute all codecs.
*/
- outl(0x0005a004, emu->port + HCFG);
+ outl(0x0005a004, emu->port + HCFG);
/* AC97 2.1, Any 16Meg of 4Gig address, Auto-Mute, EMU32 Slave,
* Mute all codecs.
*/
@@ -830,25 +829,25 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
outl(0x0005a000, emu->port + HCFG);
/* Disable 48Volt power to Audio Dock */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 );
/* ID, should read & 0x7f = 0x55. (Bit 7 is the IRQ bit) */
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
- snd_printdd("reg1 = 0x%x\n", reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+ snd_printdd("reg1=0x%x\n",reg);
if ((reg & 0x3f) == 0x15) {
/* FPGA netlist already present so clear it */
/* Return to programming mode */
- snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02);
+ snd_emu1010_fpga_write(emu, EMU_HANA_FPGA_CONFIG, 0x02 );
}
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
- snd_printdd("reg2 = 0x%x\n", reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
+ snd_printdd("reg2=0x%x\n",reg);
if ((reg & 0x3f) == 0x15) {
/* FPGA failed to return to programming mode */
snd_printk(KERN_INFO "emu1010: FPGA failed to return to programming mode\n");
return -ENODEV;
}
- snd_printk(KERN_INFO "emu1010: EMU_HANA_ID = 0x%x\n", reg);
+ snd_printk(KERN_INFO "emu1010: EMU_HANA_ID=0x%x\n",reg);
switch (emu->card_capabilities->emu_model) {
case EMU_MODEL_EMU1010:
filename = HANA_FILENAME;
@@ -877,25 +876,25 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
}
/* ID, should read & 0x7f = 0x55 when FPGA programmed. */
- snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_ID, &reg );
if ((reg & 0x3f) != 0x15) {
/* FPGA failed to be programmed */
- snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg = 0x%x\n", reg);
+ snd_printk(KERN_INFO "emu1010: Loading Hana Firmware file failed, reg=0x%x\n", reg);
return -ENODEV;
}
snd_printk(KERN_INFO "emu1010: Hana Firmware loaded\n");
- snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp);
- snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2);
- snd_printk("emu1010: Hana version: %d.%d\n", tmp, tmp2);
+ snd_emu1010_fpga_read(emu, EMU_HANA_MAJOR_REV, &tmp );
+ snd_emu1010_fpga_read(emu, EMU_HANA_MINOR_REV, &tmp2 );
+ snd_printk("Hana ver:%d.%d\n",tmp ,tmp2);
/* Enable 48Volt power to Audio Dock */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, EMU_HANA_DOCK_PWR_ON );
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
- snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
- snd_printk(KERN_INFO "emu1010: Card options = 0x%x\n", reg);
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp);
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
+ snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
+ snd_printk(KERN_INFO "emu1010: Card options=0x%x\n",reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTICAL_TYPE, &tmp );
/* Optical -> ADAT I/O */
/* 0 : SPDIF
* 1 : ADAT
@@ -905,42 +904,41 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
tmp = 0;
tmp = (emu->emu1010.optical_in ? EMU_HANA_OPTICAL_IN_ADAT : 0) |
(emu->emu1010.optical_out ? EMU_HANA_OPTICAL_OUT_ADAT : 0);
- snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp);
- snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp);
+ snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, tmp );
+ snd_emu1010_fpga_read(emu, EMU_HANA_ADC_PADS, &tmp );
/* Set no attenuation on Audio Dock pads. */
- snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00);
+ snd_emu1010_fpga_write(emu, EMU_HANA_ADC_PADS, 0x00 );
emu->emu1010.adc_pads = 0x00;
- snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp);
+ snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
/* Unmute Audio dock DACs, Headphone source DAC-4. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30);
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);
- snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
+ snd_emu1010_fpga_read(emu, EMU_HANA_DAC_PADS, &tmp );
/* DAC PADs. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DAC_PADS, 0x0f );
emu->emu1010.dac_pads = 0x0f;
- snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp);
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30);
- snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp);
+ snd_emu1010_fpga_read(emu, EMU_HANA_DOCK_MISC, &tmp );
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_MISC, 0x30 );
+ snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp );
/* SPDIF Format. Set Consumer mode, 24bit, copy enable */
- snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10);
+ snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 );
/* MIDI routing */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19);
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 );
/* Unknown. */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c);
- /* IRQ Enable: Alll on */
- /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); */
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c );
+ /* snd_emu1010_fpga_write(emu, 0x09, 0x0f ); // IRQ Enable: All on */
/* IRQ Enable: All off */
- snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00);
+ snd_emu1010_fpga_write(emu, EMU_HANA_IRQ_ENABLE, 0x00 );
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg);
- snd_printk(KERN_INFO "emu1010: Card options3 = 0x%x\n", reg);
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &reg );
+ snd_printk(KERN_INFO "emu1010: Card options3=0x%x\n",reg);
/* Default WCLK set to 48kHz. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x00 );
/* Word Clock source, Internal 48kHz x1 */
- snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K);
- /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */
+ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
+ //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
/* Audio Dock LEDs. */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12 );
#if 0
/* For 96kHz */
@@ -994,7 +992,7 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
* Defaults only, users will set their own values anyways, let's
* just copy/paste.
*/
-
+
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_8, EMU_SRC_DOCK_MIC_A1);
snd_emu1010_fpga_link_dst_src_write(emu,
@@ -1039,19 +1037,19 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE2_EMU32_F, EMU_SRC_HAMOA_ADC_LEFT2);
#endif
- for (i = 0; i < 0x20; i++) {
- /* AudioDock Elink <- Silence */
- snd_emu1010_fpga_link_dst_src_write(emu, 0x0100 + i, EMU_SRC_SILENCE);
+ for (i = 0;i < 0x20; i++ ) {
+ /* AudioDock Elink <- Silence */
+ snd_emu1010_fpga_link_dst_src_write(emu, 0x0100+i, EMU_SRC_SILENCE);
}
- for (i = 0; i < 4; i++) {
+ for (i = 0;i < 4; i++) {
/* Hana SPDIF Out <- Silence */
- snd_emu1010_fpga_link_dst_src_write(emu, 0x0200 + i, EMU_SRC_SILENCE);
+ snd_emu1010_fpga_link_dst_src_write(emu, 0x0200+i, EMU_SRC_SILENCE);
}
- for (i = 0; i < 7; i++) {
+ for (i = 0;i < 7; i++) {
/* Hamoa DAC <- Silence */
- snd_emu1010_fpga_link_dst_src_write(emu, 0x0300 + i, EMU_SRC_SILENCE);
+ snd_emu1010_fpga_link_dst_src_write(emu, 0x0300+i, EMU_SRC_SILENCE);
}
- for (i = 0; i < 7; i++) {
+ for (i = 0;i < 7; i++) {
/* Hana ADAT Out <- Silence */
snd_emu1010_fpga_link_dst_src_write(emu, EMU_DST_HANA_ADAT + i, EMU_SRC_SILENCE);
}
@@ -1067,30 +1065,30 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
EMU_DST_ALICE_I2S2_LEFT, EMU_SRC_DOCK_ADC3_LEFT1);
snd_emu1010_fpga_link_dst_src_write(emu,
EMU_DST_ALICE_I2S2_RIGHT, EMU_SRC_DOCK_ADC3_RIGHT1);
- snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01); /* Unmute all */
-
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp);
+ snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x01 ); // Unmute all
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
+
/* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
* Lock Sound Memory Cache, Lock Tank Memory Cache,
* Mute all codecs.
*/
- outl(0x0000a000, emu->port + HCFG);
+ outl(0x0000a000, emu->port + HCFG);
/* AC97 1.03, Any 32Meg of 2Gig address, Auto-Mute, EMU32 Slave,
* Lock Sound Memory Cache, Lock Tank Memory Cache,
* Un-Mute all codecs.
*/
outl(0x0000a001, emu->port + HCFG);
-
+
/* Initial boot complete. Now patches */
- snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp);
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19); /* MIDI Route */
- snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c); /* Unknown */
- snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp);
- snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10); /* SPDIF Format spdif (or 0x11 for aes/ebu) */
+ snd_emu1010_fpga_read(emu, EMU_HANA_OPTION_CARDS, &tmp );
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_IN, 0x19 ); /* MIDI Route */
+ snd_emu1010_fpga_write(emu, EMU_HANA_MIDI_OUT, 0x0c ); /* Unknown */
+ snd_emu1010_fpga_read(emu, EMU_HANA_SPDIF_MODE, &tmp );
+ snd_emu1010_fpga_write(emu, EMU_HANA_SPDIF_MODE, 0x10 ); /* SPDIF Format spdif (or 0x11 for aes/ebu) */
/* Start Micro/Audio Dock firmware loader thread */
if (!emu->emu1010.firmware_thread) {
@@ -1220,20 +1218,20 @@ static int snd_emu10k1_emu1010_init(struct snd_emu10k1 *emu)
emu->emu1010.output_source[23] = 28;
}
/* TEMP: Select SPDIF in/out */
- /* snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); */ /* Output spdif */
+ //snd_emu1010_fpga_write(emu, EMU_HANA_OPTICAL_TYPE, 0x0); /* Output spdif */
/* TEMP: Select 48kHz SPDIF out */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x0); /* Mute all */
snd_emu1010_fpga_write(emu, EMU_HANA_DEFCLOCK, 0x0); /* Default fallback clock 48kHz */
/* Word Clock source, Internal 48kHz x1 */
- snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K);
- /* snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X); */
+ snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K );
+ //snd_emu1010_fpga_write(emu, EMU_HANA_WCLOCK, EMU_HANA_WCLOCK_INT_48K | EMU_HANA_WCLOCK_4X );
emu->emu1010.internal_clock = 1; /* 48000 */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12); /* Set LEDs on Audio Dock */
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_LEDS_2, 0x12);/* Set LEDs on Audio Dock */
snd_emu1010_fpga_write(emu, EMU_HANA_UNMUTE, 0x1); /* Unmute all */
- /* snd_emu1010_fpga_write(emu, 0x7, 0x0); */ /* Mute all */
- /* snd_emu1010_fpga_write(emu, 0x7, 0x1); */ /* Unmute all */
- /* snd_emu1010_fpga_write(emu, 0xe, 0x12); */ /* Set LEDs on Audio Dock */
+ //snd_emu1010_fpga_write(emu, 0x7, 0x0); /* Mute all */
+ //snd_emu1010_fpga_write(emu, 0x7, 0x1); /* Unmute all */
+ //snd_emu1010_fpga_write(emu, 0xe, 0x12); /* Set LEDs on Audio Dock */
return 0;
}
@@ -1249,13 +1247,13 @@ static void free_pm_buffer(struct snd_emu10k1 *emu);
static int snd_emu10k1_free(struct snd_emu10k1 *emu)
{
if (emu->port) { /* avoid access to already used hardware */
- snd_emu10k1_fx8010_tram_setup(emu, 0);
+ snd_emu10k1_fx8010_tram_setup(emu, 0);
snd_emu10k1_done(emu);
snd_emu10k1_free_efx(emu);
- }
+ }
if (emu->card_capabilities->emu_model == EMU_MODEL_EMU1010) {
/* Disable 48Volt power to Audio Dock */
- snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0);
+ snd_emu1010_fpga_write(emu, EMU_HANA_DOCK_PWR, 0 );
}
if (emu->emu1010.firmware_thread)
kthread_stop(emu->emu1010.firmware_thread);
@@ -1280,7 +1278,7 @@ static int snd_emu10k1_free(struct snd_emu10k1 *emu)
#endif
if (emu->port)
pci_release_regions(emu->pci);
- if (emu->card_capabilities->ca0151_chip) /* P16V */
+ if (emu->card_capabilities->ca0151_chip) /* P16V */
snd_p16v_free(emu);
pci_disable_device(emu->pci);
kfree(emu);
@@ -1294,6 +1292,21 @@ static int snd_emu10k1_dev_free(struct snd_device *device)
}
static struct snd_emu_chip_details emu_chip_details[] = {
+ /* Audigy 2 Value AC3 out does not work yet. Need to find out how to turn off interpolators.*/
+ /* Tested by James@superbug.co.uk 3rd July 2005 */
+ /* DSP: CA0108-IAT
+ * DAC: CS4382-KQ
+ * ADC: Philips 1361T
+ * AC97: STAC9750
+ * CA0151: None
+ */
+ {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
+ .driver = "Audigy2", .name = "Audigy 2 Value [SB0400]",
+ .id = "Audigy2",
+ .emu10k2_chip = 1,
+ .ca0108_chip = 1,
+ .spk71 = 1,
+ .ac97_chip = 1} ,
/* Audigy4 (Not PRO) SB0610 */
/* Tested by James@superbug.co.uk 4th April 2006 */
/* A_IOCFG bits
@@ -1333,37 +1346,20 @@ static struct snd_emu_chip_details emu_chip_details[] = {
* CA0151: None
*/
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10211102,
- .driver = "Audigy2", .name = "SB Audigy 4 [SB0610]",
+ .driver = "Audigy2", .name = "Audigy 4 [SB0610]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.spk71 = 1,
.adc_1361t = 1, /* 24 bit capture instead of 16bit */
.ac97_chip = 1} ,
- /* Audigy 2 Value AC3 out does not work yet.
- * Need to find out how to turn off interpolators.
- */
- /* Tested by James@superbug.co.uk 3rd July 2005 */
- /* DSP: CA0108-IAT
- * DAC: CS4382-KQ
- * ADC: Philips 1361T
- * AC97: STAC9750
- * CA0151: None
- */
- {.vendor = 0x1102, .device = 0x0008, .subsystem = 0x10011102,
- .driver = "Audigy2", .name = "SB Audigy 2 Value [SB0400]",
- .id = "Audigy2",
- .emu10k2_chip = 1,
- .ca0108_chip = 1,
- .spk71 = 1,
- .ac97_chip = 1} ,
/* Audigy 2 ZS Notebook Cardbus card.*/
/* Tested by James@superbug.co.uk 6th November 2006 */
/* Audio output 7.1/Headphones working.
* Digital output working. (AC3 not checked, only PCM)
* Audio Mic/Line inputs working.
* Digital input not tested.
- */
+ */
/* DSP: Tina2
* DAC: Wolfson WM8768/WM8568
* ADC: Wolfson WM8775
@@ -1390,7 +1386,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
*
*/
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x20011102,
- .driver = "Audigy2", .name = "SB Audigy 2 ZS Notebook [SB0530]",
+ .driver = "Audigy2", .name = "Audigy 2 ZS Notebook [SB0530]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0108_chip = 1,
@@ -1400,7 +1396,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spk71 = 1} ,
/* Tested by James@superbug.co.uk 4th Nov 2007. */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x42011102,
- .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]",
+ .driver = "Audigy2", .name = "E-mu 1010 Notebook [MAEM8950]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0108_chip = 1,
@@ -1408,49 +1404,47 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spk71 = 1 ,
.emu_model = EMU_MODEL_EMU1616},
/* Tested by James@superbug.co.uk 4th Nov 2007. */
- /* This is MAEM8960, 0202 is MAEM 8980 */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40041102,
- .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM8960]",
+ .driver = "Audigy2", .name = "E-mu 1010b PCI [MAEM????]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.spk71 = 1,
- .emu_model = EMU_MODEL_EMU1010B}, /* EMU 1010 new revision */
+ .emu_model = EMU_MODEL_EMU1010B},
/* Tested by James@superbug.co.uk 8th July 2005. */
- /* This is MAEM8810, 0202 is MAEM8820 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40011102,
- .driver = "Audigy2", .name = "E-mu 1010 [MAEM8810]",
+ .driver = "Audigy2", .name = "E-mu 1010 [4001]",
.id = "EMU1010",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.spk71 = 1,
- .emu_model = EMU_MODEL_EMU1010}, /* EMU 1010 old revision */
+ .emu_model = EMU_MODEL_EMU1010}, /* Emu 1010 */
/* EMU0404b */
{.vendor = 0x1102, .device = 0x0008, .subsystem = 0x40021102,
- .driver = "Audigy2", .name = "E-mu 0404b PCI [MAEM8852]",
+ .driver = "Audigy2", .name = "E-mu 0404b [4002]",
.id = "EMU0404",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.spk71 = 1,
- .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 new revision */
+ .emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */
/* Tested by James@superbug.co.uk 20-3-2007. */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x40021102,
- .driver = "Audigy2", .name = "E-mu 0404 [MAEM8850]",
+ .driver = "Audigy2", .name = "E-mu 0404 [4002]",
.id = "EMU0404",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.spk71 = 1,
.emu_model = EMU_MODEL_EMU0404}, /* EMU 0404 */
- /* Note that all E-mu cards require kernel 2.6 or newer. */
- {.vendor = 0x1102, .device = 0x0008,
- .driver = "Audigy2", .name = "SB Audigy 2 Value [Unknown]",
+ /* Audigy4 (Not PRO) SB0610 */
+ {.vendor = 0x1102, .device = 0x0008,
+ .driver = "Audigy2", .name = "Audigy 2 Value [Unknown]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0108_chip = 1,
.ac97_chip = 1} ,
/* Tested by James@superbug.co.uk 3rd July 2005 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20071102,
- .driver = "Audigy2", .name = "SB Audigy 4 PRO [SB0380]",
+ .driver = "Audigy2", .name = "Audigy 4 PRO [SB0380]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1463,7 +1457,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
* Just like 0x20021102
*/
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20061102,
- .driver = "Audigy2", .name = "SB Audigy 2 [SB0350b]",
+ .driver = "Audigy2", .name = "Audigy 2 [SB0350b]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1473,7 +1467,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.invert_shared_spdif = 1, /* digital/analog switch swapped */
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20021102,
- .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0350]",
+ .driver = "Audigy2", .name = "Audigy 2 ZS [SB0350]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1483,7 +1477,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.invert_shared_spdif = 1, /* digital/analog switch swapped */
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x20011102,
- .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0360]",
+ .driver = "Audigy2", .name = "Audigy 2 ZS [2001]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1501,7 +1495,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
* CA0151: Yes
*/
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10071102,
- .driver = "Audigy2", .name = "SB Audigy 2 [SB0240]",
+ .driver = "Audigy2", .name = "Audigy 2 [SB0240]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1511,7 +1505,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.adc_1361t = 1, /* 24 bit capture instead of 16bit */
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10051102,
- .driver = "Audigy2", .name = "SB Audigy 2 Platinum EX [SB0280]",
+ .driver = "Audigy2", .name = "Audigy 2 EX [1005]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1521,7 +1515,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
/* Dell OEM/Creative Labs Audigy 2 ZS */
/* See ALSA bug#1365 */
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10031102,
- .driver = "Audigy2", .name = "SB Audigy 2 ZS [SB0353]",
+ .driver = "Audigy2", .name = "Audigy 2 ZS [SB0353]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1530,7 +1524,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spdif_bug = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x10021102,
- .driver = "Audigy2", .name = "SB Audigy 2 Platinum [SB0240P]",
+ .driver = "Audigy2", .name = "Audigy 2 Platinum [SB0240P]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1541,7 +1535,7 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.adc_1361t = 1, /* 24 bit capture instead of 16bit. Fixes ALSA bug#324 */
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .revision = 0x04,
- .driver = "Audigy2", .name = "SB Audigy 2 [Unknown]",
+ .driver = "Audigy2", .name = "Audigy 2 [Unknown]",
.id = "Audigy2",
.emu10k2_chip = 1,
.ca0102_chip = 1,
@@ -1549,79 +1543,78 @@ static struct snd_emu_chip_details emu_chip_details[] = {
.spdif_bug = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00531102,
- .driver = "Audigy", .name = "SB Audigy 1 [SB0092]",
+ .driver = "Audigy", .name = "Audigy 1 [SB0090]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00521102,
- .driver = "Audigy", .name = "SB Audigy 1 ES [SB0160]",
+ .driver = "Audigy", .name = "Audigy 1 ES [SB0160]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.spdif_bug = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004, .subsystem = 0x00511102,
- .driver = "Audigy", .name = "SB Audigy 1 [SB0090]",
+ .driver = "Audigy", .name = "Audigy 1 [SB0090]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0004,
- .driver = "Audigy", .name = "Audigy 1 [Unknown]",
+ .driver = "Audigy", .name = "Audigy 1 [Unknown]",
.id = "Audigy",
.emu10k2_chip = 1,
.ca0102_chip = 1,
.ac97_chip = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102,
- .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]",
- .id = "Live",
- .emu10k1_chip = 1,
- .ac97_chip = 1,
- .sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806b1102,
- .driver = "EMU10K1", .name = "SB Live! [SB0105]",
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806B1102,
+ .driver = "EMU10K1", .name = "SBLive! [SB0105]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
- {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806a1102,
- .driver = "EMU10K1", .name = "SB Live! Value [SB0103]",
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x806A1102,
+ .driver = "EMU10K1", .name = "SBLive! Value [SB0103]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80691102,
- .driver = "EMU10K1", .name = "SB Live! Value [SB0101]",
+ .driver = "EMU10K1", .name = "SBLive! Value [SB0101]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
/* Tested by ALSA bug#1680 26th December 2005 */
- /* note: It really has SB0220 written on the card, */
- /* but it's SB0228 according to kx.inf */
+ /* note: It really has SB0220 written on the card. */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80661102,
- .driver = "EMU10K1", .name = "SB Live! 5.1 Dell OEM [SB0228]",
+ .driver = "EMU10K1", .name = "SB Live 5.1 Dell OEM [SB0220]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
/* Tested by Thomas Zehetbauer 27th Aug 2005 */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80651102,
- .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0220]",
+ .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]",
+ .id = "Live",
+ .emu10k1_chip = 1,
+ .ac97_chip = 1,
+ .sblive51 = 1} ,
+ {.vendor = 0x1102, .device = 0x0002, .subsystem = 0x100a1102,
+ .driver = "EMU10K1", .name = "SB Live 5.1 [SB0220]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80641102,
- .driver = "EMU10K1", .name = "SB Live! 5.1",
+ .driver = "EMU10K1", .name = "SB Live 5.1",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
/* Tested by alsa bugtrack user "hus" bug #1297 12th Aug 2005 */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80611102,
- .driver = "EMU10K1", .name = "SB Live! 5.1 [SB0060]",
+ .driver = "EMU10K1", .name = "SBLive 5.1 [SB0060]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 2, /* ac97 is optional; both SBLive 5.1 and platinum
@@ -1629,78 +1622,78 @@ static struct snd_emu_chip_details emu_chip_details[] = {
*/
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80511102,
- .driver = "EMU10K1", .name = "SB Live! Value [CT4850]",
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4850]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80401102,
- .driver = "EMU10K1", .name = "SB Live! Platinum [CT4760P]",
+ .driver = "EMU10K1", .name = "SBLive! Platinum [CT4760P]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80321102,
- .driver = "EMU10K1", .name = "SB Live! Value [CT4871]",
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4871]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80311102,
- .driver = "EMU10K1", .name = "SB Live! Value [CT4831]",
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4831]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80281102,
- .driver = "EMU10K1", .name = "SB Live! Value [CT4870]",
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4870]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
/* Tested by James@superbug.co.uk 3rd July 2005 */
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80271102,
- .driver = "EMU10K1", .name = "SB Live! Value [CT4832]",
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4832]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80261102,
- .driver = "EMU10K1", .name = "SB Live! Value [CT4830]",
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4830]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80231102,
- .driver = "EMU10K1", .name = "SB PCI512 [CT4790]",
+ .driver = "EMU10K1", .name = "SB PCI512 [CT4790]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x80221102,
- .driver = "EMU10K1", .name = "SB Live! Value [CT4780]",
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4780]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x40011102,
- .driver = "EMU10K1", .name = "E-mu APS [PC545]",
+ .driver = "EMU10K1", .name = "E-mu APS [4001]",
.id = "APS",
.emu10k1_chip = 1,
.ecard = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00211102,
- .driver = "EMU10K1", .name = "SB Live! [CT4620]",
+ .driver = "EMU10K1", .name = "SBLive! [CT4620]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002, .subsystem = 0x00201102,
- .driver = "EMU10K1", .name = "SB Live! Value [CT4670]",
+ .driver = "EMU10K1", .name = "SBLive! Value [CT4670]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
.sblive51 = 1} ,
{.vendor = 0x1102, .device = 0x0002,
- .driver = "EMU10K1", .name = "SB Live! [Unknown]",
+ .driver = "EMU10K1", .name = "SB Live [Unknown]",
.id = "Live",
.emu10k1_chip = 1,
.ac97_chip = 1,
@@ -1709,13 +1702,13 @@ static struct snd_emu_chip_details emu_chip_details[] = {
};
int __devinit snd_emu10k1_create(struct snd_card *card,
- struct pci_dev *pci,
+ struct pci_dev * pci,
unsigned short extin_mask,
unsigned short extout_mask,
long max_cache_bytes,
int enable_ir,
uint subsystem,
- struct snd_emu10k1 **remu)
+ struct snd_emu10k1 ** remu)
{
struct snd_emu10k1 *emu;
int idx, err;
@@ -1725,12 +1718,11 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
static struct snd_device_ops ops = {
.dev_free = snd_emu10k1_dev_free,
};
-
+
*remu = NULL;
/* enable PCI device */
- err = pci_enable_device(pci);
- if (err < 0)
+ if ((err = pci_enable_device(pci)) < 0)
return err;
emu = kzalloc(sizeof(*emu), GFP_KERNEL);
@@ -1757,17 +1749,16 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
emu->revision = pci->revision;
pci_read_config_dword(pci, PCI_SUBSYSTEM_VENDOR_ID, &emu->serial);
pci_read_config_word(pci, PCI_SUBSYSTEM_ID, &emu->model);
- snd_printdd("vendor = 0x%x, device = 0x%x, subsystem_vendor_id = 0x%x, subsystem_id = 0x%x\n", pci->vendor, pci->device, emu->serial, emu->model);
+ snd_printdd("vendor=0x%x, device=0x%x, subsystem_vendor_id=0x%x, subsystem_id=0x%x\n",pci->vendor, pci->device, emu->serial, emu->model);
for (c = emu_chip_details; c->vendor; c++) {
if (c->vendor == pci->vendor && c->device == pci->device) {
if (subsystem) {
- if (c->subsystem && (c->subsystem == subsystem))
+ if (c->subsystem && (c->subsystem == subsystem) ) {
break;
- else
- continue;
+ } else continue;
} else {
- if (c->subsystem && (c->subsystem != emu->serial))
+ if (c->subsystem && (c->subsystem != emu->serial) )
continue;
if (c->revision && c->revision != emu->revision)
continue;
@@ -1783,18 +1774,14 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
}
emu->card_capabilities = c;
if (c->subsystem && !subsystem)
- snd_printdd("Sound card name = %s\n", c->name);
- else if (subsystem)
- snd_printdd("Sound card name = %s, "
- "vendor = 0x%x, device = 0x%x, subsystem = 0x%x. "
- "Forced to subsytem = 0x%x\n", c->name,
- pci->vendor, pci->device, emu->serial, c->subsystem);
- else
- snd_printdd("Sound card name = %s, "
- "vendor = 0x%x, device = 0x%x, subsystem = 0x%x.\n",
- c->name, pci->vendor, pci->device,
- emu->serial);
-
+ snd_printdd("Sound card name=%s\n", c->name);
+ else if (subsystem)
+ snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x. Forced to subsytem=0x%x\n",
+ c->name, pci->vendor, pci->device, emu->serial, c->subsystem);
+ else
+ snd_printdd("Sound card name=%s, vendor=0x%x, device=0x%x, subsystem=0x%x.\n",
+ c->name, pci->vendor, pci->device, emu->serial);
+
if (!*card->id && c->id) {
int i, n = 0;
strlcpy(card->id, c->id, sizeof(card->id));
@@ -1828,8 +1815,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
else
emu->gpr_base = FXGPREGBASE;
- err = pci_request_regions(pci, "EMU10K1");
- if (err < 0) {
+ if ((err = pci_request_regions(pci, "EMU10K1")) < 0) {
kfree(emu);
pci_disable_device(pci);
return err;
@@ -1876,25 +1862,21 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
emu->enable_ir = enable_ir;
if (emu->card_capabilities->ca_cardbus_chip) {
- err = snd_emu10k1_cardbus_init(emu);
- if (err < 0)
+ if ((err = snd_emu10k1_cardbus_init(emu)) < 0)
goto error;
}
if (emu->card_capabilities->ecard) {
- err = snd_emu10k1_ecard_init(emu);
- if (err < 0)
+ if ((err = snd_emu10k1_ecard_init(emu)) < 0)
goto error;
} else if (emu->card_capabilities->emu_model) {
- err = snd_emu10k1_emu1010_init(emu);
- if (err < 0) {
- snd_emu10k1_free(emu);
- return err;
- }
+ if ((err = snd_emu10k1_emu1010_init(emu)) < 0) {
+ snd_emu10k1_free(emu);
+ return err;
+ }
} else {
/* 5.1: Enable the additional AC97 Slots. If the emu10k1 version
does not support this, it shouldn't do any harm */
- snd_emu10k1_ptr_write(emu, AC97SLOT, 0,
- AC97SLOT_CNTR|AC97SLOT_LFE);
+ snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
}
/* initialize TRAM setup */
@@ -1934,7 +1916,7 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
snd_emu10k1_synth_alloc(emu, 4096);
if (emu->reserved_page)
emu->reserved_page->map_locked = 1;
-
+
/* Clear silent pages and set up pointers */
memset(emu->silent_page.area, 0, PAGE_SIZE);
silent_page = emu->silent_page.addr << 1;
@@ -1947,23 +1929,19 @@ int __devinit snd_emu10k1_create(struct snd_card *card,
emu->voices[idx].number = idx;
}
- err = snd_emu10k1_init(emu, enable_ir, 0);
- if (err < 0)
+ if ((err = snd_emu10k1_init(emu, enable_ir, 0)) < 0)
goto error;
#ifdef CONFIG_PM
- err = alloc_pm_buffer(emu);
- if (err < 0)
+ if ((err = alloc_pm_buffer(emu)) < 0)
goto error;
#endif
/* Initialize the effect engine */
- err = snd_emu10k1_init_efx(emu);
- if (err < 0)
+ if ((err = snd_emu10k1_init_efx(emu)) < 0)
goto error;
snd_emu10k1_audio_enable(emu);
- err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops);
- if (err < 0)
+ if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, emu, &ops)) < 0)
goto error;
#ifdef CONFIG_PROC_FS
@@ -2003,7 +1981,7 @@ static int __devinit alloc_pm_buffer(struct snd_emu10k1 *emu)
if (emu->audigy)
size += ARRAY_SIZE(saved_regs_audigy);
emu->saved_ptr = vmalloc(4 * NUM_G * size);
- if (!emu->saved_ptr)
+ if (! emu->saved_ptr)
return -ENOMEM;
if (snd_emu10k1_efx_alloc_pm_buffer(emu) < 0)
return -ENOMEM;
@@ -2048,7 +2026,7 @@ void snd_emu10k1_resume_init(struct snd_emu10k1 *emu)
if (emu->card_capabilities->ecard)
snd_emu10k1_ecard_init(emu);
else if (emu->card_capabilities->emu_model)
- snd_emu10k1_emu1010_init(emu);
+ snd_emu10k1_emu1010_init(emu);
else
snd_emu10k1_ptr_write(emu, AC97SLOT, 0, AC97SLOT_CNTR|AC97SLOT_LFE);
snd_emu10k1_init(emu, emu->enable_ir, 1);
diff --git a/sound/pci/emu10k1/emumixer.c b/sound/pci/emu10k1/emumixer.c
index b0fb6c917c38..f34bbfb705f5 100644
--- a/sound/pci/emu10k1/emumixer.c
+++ b/sound/pci/emu10k1/emumixer.c
@@ -1639,45 +1639,6 @@ static struct snd_kcontrol_new snd_audigy_shared_spdif __devinitdata =
.put = snd_emu10k1_shared_spdif_put
};
-/* workaround for too low volume on Audigy due to 16bit/24bit conversion */
-
-#define snd_audigy_capture_boost_info snd_ctl_boolean_mono_info
-
-static int snd_audigy_capture_boost_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
- unsigned int val;
-
- /* FIXME: better to use a cached version */
- val = snd_ac97_read(emu->ac97, AC97_REC_GAIN);
- ucontrol->value.integer.value[0] = !!val;
- return 0;
-}
-
-static int snd_audigy_capture_boost_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_emu10k1 *emu = snd_kcontrol_chip(kcontrol);
- unsigned int val;
-
- if (ucontrol->value.integer.value[0])
- val = 0x0f0f;
- else
- val = 0;
- return snd_ac97_update(emu->ac97, AC97_REC_GAIN, val);
-}
-
-static struct snd_kcontrol_new snd_audigy_capture_boost __devinitdata =
-{
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Analog Capture Boost",
- .info = snd_audigy_capture_boost_info,
- .get = snd_audigy_capture_boost_get,
- .put = snd_audigy_capture_boost_put
-};
-
-
/*
*/
static void snd_emu10k1_mixer_free_ac97(struct snd_ac97 *ac97)
@@ -2126,12 +2087,5 @@ int __devinit snd_emu10k1_mixer(struct snd_emu10k1 *emu,
}
}
- if (emu->card_capabilities->ac97_chip && emu->audigy) {
- err = snd_ctl_add(card, snd_ctl_new1(&snd_audigy_capture_boost,
- emu));
- if (err < 0)
- return err;
- }
-
return 0;
}
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig
deleted file mode 100644
index eb2a19b894a0..000000000000
--- a/sound/pci/hda/Kconfig
+++ /dev/null
@@ -1,188 +0,0 @@
-menuconfig SND_HDA_INTEL
- tristate "Intel HD Audio"
- select SND_PCM
- select SND_VMASTER
- select SND_JACK if INPUT=y || INPUT=SND
- help
- Say Y here to include support for Intel "High Definition
- Audio" (Azalia) and its compatible devices.
-
- This option enables the HD-audio controller. Don't forget
- to choose the appropriate codec options below.
-
- To compile this driver as a module, choose M here: the module
- will be called snd-hda-intel.
-
-if SND_HDA_INTEL
-
-config SND_HDA_HWDEP
- bool "Build hwdep interface for HD-audio driver"
- select SND_HWDEP
- help
- Say Y here to build a hwdep interface for HD-audio driver.
- This interface can be used for out-of-band communication
- with codecs for debugging purposes.
-
-config SND_HDA_RECONFIG
- bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)"
- depends on SND_HDA_HWDEP && EXPERIMENTAL
- help
- Say Y here to enable the HD-audio codec re-configuration feature.
- This adds the sysfs interfaces to allow user to clear the whole
- codec configuration, change the codec setup, add extra verbs,
- and re-configure the codec dynamically.
-
-config SND_HDA_INPUT_BEEP
- bool "Support digital beep via input layer"
- depends on INPUT=y || INPUT=SND_HDA_INTEL
- help
- Say Y here to build a digital beep interface for HD-audio
- driver. This interface is used to generate digital beeps.
-
-config SND_HDA_CODEC_REALTEK
- bool "Build Realtek HD-audio codec support"
- default y
- help
- Say Y here to include Realtek HD-audio codec support in
- snd-hda-intel driver, such as ALC880.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-realtek.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_ANALOG
- bool "Build Analog Device HD-audio codec support"
- default y
- help
- Say Y here to include Analog Device HD-audio codec support in
- snd-hda-intel driver, such as AD1986A.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-analog.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_SIGMATEL
- bool "Build IDT/Sigmatel HD-audio codec support"
- default y
- help
- Say Y here to include IDT (Sigmatel) HD-audio codec support in
- snd-hda-intel driver, such as STAC9200.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-idt.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_VIA
- bool "Build VIA HD-audio codec support"
- default y
- help
- Say Y here to include VIA HD-audio codec support in
- snd-hda-intel driver, such as VT1708.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-via.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_ATIHDMI
- bool "Build ATI HDMI HD-audio codec support"
- default y
- help
- Say Y here to include ATI HDMI HD-audio codec support in
- snd-hda-intel driver, such as ATI RS600 HDMI.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-atihdmi.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_NVHDMI
- bool "Build NVIDIA HDMI HD-audio codec support"
- default y
- help
- Say Y here to include NVIDIA HDMI HD-audio codec support in
- snd-hda-intel driver, such as NVIDIA MCP78 HDMI.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-nvhdmi.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_INTELHDMI
- bool "Build INTEL HDMI HD-audio codec support"
- default y
- help
- Say Y here to include INTEL HDMI HD-audio codec support in
- snd-hda-intel driver, such as Eaglelake integrated HDMI.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-intelhdmi.
- This module is automatically loaded at probing.
-
-config SND_HDA_ELD
- def_bool y
- depends on SND_HDA_CODEC_INTELHDMI
-
-config SND_HDA_CODEC_CONEXANT
- bool "Build Conexant HD-audio codec support"
- default y
- help
- Say Y here to include Conexant HD-audio codec support in
- snd-hda-intel driver, such as CX20549.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-conexant.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_CMEDIA
- bool "Build C-Media HD-audio codec support"
- default y
- help
- Say Y here to include C-Media HD-audio codec support in
- snd-hda-intel driver, such as CMI9880.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-cmedia.
- This module is automatically loaded at probing.
-
-config SND_HDA_CODEC_SI3054
- bool "Build Silicon Labs 3054 HD-modem codec support"
- default y
- help
- Say Y here to include Silicon Labs 3054 HD-modem codec
- (and compatibles) support in snd-hda-intel driver.
-
- When the HD-audio driver is built as a module, the codec
- support code is also built as another module,
- snd-hda-codec-si3054.
- This module is automatically loaded at probing.
-
-config SND_HDA_GENERIC
- bool "Enable generic HD-audio codec parser"
- default y
- help
- Say Y here to enable the generic HD-audio codec parser
- in snd-hda-intel driver.
-
-config SND_HDA_POWER_SAVE
- bool "Aggressive power-saving on HD-audio"
- help
- Say Y here to enable more aggressive power-saving mode on
- HD-audio driver. The power-saving timeout can be configured
- via power_save option or over sysfs on-the-fly.
-
-config SND_HDA_POWER_SAVE_DEFAULT
- int "Default time-out for HD-audio power-save mode"
- depends on SND_HDA_POWER_SAVE
- default 0
- help
- The default time-out value in seconds for HD-audio automatic
- power-save mode. 0 means to disable the power-save mode.
-
-endif
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile
index 50f9d0967251..1980c6d207e7 100644
--- a/sound/pci/hda/Makefile
+++ b/sound/pci/hda/Makefile
@@ -1,59 +1,20 @@
-snd-hda-intel-objs := hda_intel.o
+snd-hda-intel-y := hda_intel.o
+# since snd-hda-intel is the only driver using hda-codec,
+# merge it into a single module although it was originally
+# designed to be individual modules
+snd-hda-intel-y += hda_codec.o
+snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o
+snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
+snd-hda-intel-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
+snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_REALTEK) += patch_realtek.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CMEDIA) += patch_cmedia.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ANALOG) += patch_analog.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += patch_sigmatel.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SI3054) += patch_si3054.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ATIHDMI) += patch_atihdmi.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o
+snd-hda-intel-$(CONFIG_SND_HDA_CODEC_NVHDMI) += patch_nvhdmi.o
-snd-hda-codec-y := hda_codec.o
-snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o
-snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o
-# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o
-snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o
-snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o
-
-snd-hda-codec-realtek-objs := patch_realtek.o
-snd-hda-codec-cmedia-objs := patch_cmedia.o
-snd-hda-codec-analog-objs := patch_analog.o
-snd-hda-codec-idt-objs := patch_sigmatel.o
-snd-hda-codec-si3054-objs := patch_si3054.o
-snd-hda-codec-atihdmi-objs := patch_atihdmi.o
-snd-hda-codec-conexant-objs := patch_conexant.o
-snd-hda-codec-via-objs := patch_via.o
-snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o
-snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o
-
-# common driver
-obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o
-
-# codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans)
-ifdef CONFIG_SND_HDA_CODEC_REALTEK
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-realtek.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_CMEDIA
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cmedia.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_ANALOG
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-analog.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-idt.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_SI3054
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_CONEXANT
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_VIA
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_NVHDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-nvhdmi.o
-endif
-ifdef CONFIG_SND_HDA_CODEC_INTELHDMI
-obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-intelhdmi.o
-endif
-
-# this must be the last entry after codec drivers;
-# otherwise the codec patches won't be hooked before the PCI probe
-# when built in kernel
obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o
diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c
index e00421c0d8ba..3ecd7e797dee 100644
--- a/sound/pci/hda/hda_beep.c
+++ b/sound/pci/hda/hda_beep.c
@@ -128,7 +128,6 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid)
INIT_WORK(&beep->beep_work, &snd_hda_generate_beep);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device);
void snd_hda_detach_beep_device(struct hda_codec *codec)
{
@@ -141,4 +140,3 @@ void snd_hda_detach_beep_device(struct hda_codec *codec)
kfree(beep);
}
}
-EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device);
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index d49d0b698687..eb9164176dab 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -31,6 +31,15 @@
#include <sound/initval.h>
#include "hda_local.h"
#include <sound/hda_hwdep.h>
+#include "hda_patch.h" /* codec presets */
+
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+/* define this option here to hide as static */
+static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
+module_param(power_save, int, 0644);
+MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
+ "(in second, 0 = disable).");
+#endif
/*
* vendor / preset table
@@ -61,26 +70,36 @@ static struct hda_vendor_id hda_vendor_ids[] = {
{} /* terminator */
};
-static DEFINE_MUTEX(preset_mutex);
-static LIST_HEAD(hda_preset_tables);
-
-int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset)
-{
- mutex_lock(&preset_mutex);
- list_add_tail(&preset->list, &hda_preset_tables);
- mutex_unlock(&preset_mutex);
- return 0;
-}
-EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset);
-
-int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset)
-{
- mutex_lock(&preset_mutex);
- list_del(&preset->list);
- mutex_unlock(&preset_mutex);
- return 0;
-}
-EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset);
+static const struct hda_codec_preset *hda_preset_tables[] = {
+#ifdef CONFIG_SND_HDA_CODEC_REALTEK
+ snd_hda_preset_realtek,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_CMEDIA
+ snd_hda_preset_cmedia,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_ANALOG
+ snd_hda_preset_analog,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL
+ snd_hda_preset_sigmatel,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_SI3054
+ snd_hda_preset_si3054,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI
+ snd_hda_preset_atihdmi,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_CONEXANT
+ snd_hda_preset_conexant,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_VIA
+ snd_hda_preset_via,
+#endif
+#ifdef CONFIG_SND_HDA_CODEC_NVHDMI
+ snd_hda_preset_nvhdmi,
+#endif
+ NULL
+};
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void hda_power_work(struct work_struct *work);
@@ -89,72 +108,6 @@ static void hda_keep_power_on(struct hda_codec *codec);
static inline void hda_keep_power_on(struct hda_codec *codec) {}
#endif
-const char *snd_hda_get_jack_location(u32 cfg)
-{
- static char *bases[7] = {
- "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
- };
- static unsigned char specials_idx[] = {
- 0x07, 0x08,
- 0x17, 0x18, 0x19,
- 0x37, 0x38
- };
- static char *specials[] = {
- "Rear Panel", "Drive Bar",
- "Riser", "HDMI", "ATAPI",
- "Mobile-In", "Mobile-Out"
- };
- int i;
- cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
- if ((cfg & 0x0f) < 7)
- return bases[cfg & 0x0f];
- for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
- if (cfg == specials_idx[i])
- return specials[i];
- }
- return "UNKNOWN";
-}
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_location);
-
-const char *snd_hda_get_jack_connectivity(u32 cfg)
-{
- static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
-
- return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3];
-}
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity);
-
-const char *snd_hda_get_jack_type(u32 cfg)
-{
- static char *jack_types[16] = {
- "Line Out", "Speaker", "HP Out", "CD",
- "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
- "Line In", "Aux", "Mic", "Telephony",
- "SPDIF In", "Digitial In", "Reserved", "Other"
- };
-
- return jack_types[(cfg & AC_DEFCFG_DEVICE)
- >> AC_DEFCFG_DEVICE_SHIFT];
-}
-EXPORT_SYMBOL_HDA(snd_hda_get_jack_type);
-
-/*
- * Compose a 32bit command word to be sent to the HD-audio controller
- */
-static inline unsigned int
-make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct,
- unsigned int verb, unsigned int parm)
-{
- u32 val;
-
- val = (u32)(codec->addr & 0x0f) << 28;
- val |= (u32)direct << 27;
- val |= (u32)nid << 20;
- val |= verb << 8;
- val |= parm;
- return val;
-}
-
/**
* snd_hda_codec_read - send a command and get the response
* @codec: the HDA codec
@@ -171,21 +124,17 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid,
int direct,
unsigned int verb, unsigned int parm)
{
- struct hda_bus *bus = codec->bus;
unsigned int res;
-
- res = make_codec_cmd(codec, nid, direct, verb, parm);
snd_hda_power_up(codec);
- mutex_lock(&bus->cmd_mutex);
- if (!bus->ops.command(bus, res))
- res = bus->ops.get_response(bus);
+ mutex_lock(&codec->bus->cmd_mutex);
+ if (!codec->bus->ops.command(codec, nid, direct, verb, parm))
+ res = codec->bus->ops.get_response(codec);
else
res = (unsigned int)-1;
- mutex_unlock(&bus->cmd_mutex);
+ mutex_unlock(&codec->bus->cmd_mutex);
snd_hda_power_down(codec);
return res;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_read);
/**
* snd_hda_codec_write - send a single command without waiting for response
@@ -202,19 +151,14 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_read);
int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct,
unsigned int verb, unsigned int parm)
{
- struct hda_bus *bus = codec->bus;
- unsigned int res;
int err;
-
- res = make_codec_cmd(codec, nid, direct, verb, parm);
snd_hda_power_up(codec);
- mutex_lock(&bus->cmd_mutex);
- err = bus->ops.command(bus, res);
- mutex_unlock(&bus->cmd_mutex);
+ mutex_lock(&codec->bus->cmd_mutex);
+ err = codec->bus->ops.command(codec, nid, direct, verb, parm);
+ mutex_unlock(&codec->bus->cmd_mutex);
snd_hda_power_down(codec);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_write);
/**
* snd_hda_sequence_write - sequence writes
@@ -229,7 +173,6 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq)
for (; seq->nid; seq++)
snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param);
}
-EXPORT_SYMBOL_HDA(snd_hda_sequence_write);
/**
* snd_hda_get_sub_nodes - get the range of sub nodes
@@ -251,7 +194,6 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid,
*start_id = (parm >> 16) & 0x7fff;
return (int)(parm & 0x7fff);
}
-EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes);
/**
* snd_hda_get_connections - get connection list
@@ -340,7 +282,6 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid,
}
return conns;
}
-EXPORT_SYMBOL_HDA(snd_hda_get_connections);
/**
@@ -375,7 +316,6 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex)
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event);
/*
* process queued unsolicited events
@@ -405,7 +345,7 @@ static void process_unsol_events(struct work_struct *work)
/*
* initialize unsolicited queue
*/
-static int init_unsol_queue(struct hda_bus *bus)
+static int __devinit init_unsol_queue(struct hda_bus *bus)
{
struct hda_bus_unsolicited *unsol;
@@ -451,24 +391,9 @@ static int snd_hda_bus_free(struct hda_bus *bus)
static int snd_hda_bus_dev_free(struct snd_device *device)
{
struct hda_bus *bus = device->device_data;
- bus->shutdown = 1;
return snd_hda_bus_free(bus);
}
-#ifdef CONFIG_SND_HDA_HWDEP
-static int snd_hda_bus_dev_register(struct snd_device *device)
-{
- struct hda_bus *bus = device->device_data;
- struct hda_codec *codec;
- list_for_each_entry(codec, &bus->codec_list, list) {
- snd_hda_hwdep_add_sysfs(codec);
- }
- return 0;
-}
-#else
-#define snd_hda_bus_dev_register NULL
-#endif
-
/**
* snd_hda_bus_new - create a HDA bus
* @card: the card entry
@@ -477,14 +402,13 @@ static int snd_hda_bus_dev_register(struct snd_device *device)
*
* Returns 0 if successful, or a negative error code.
*/
-int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
+int __devinit snd_hda_bus_new(struct snd_card *card,
const struct hda_bus_template *temp,
struct hda_bus **busp)
{
struct hda_bus *bus;
int err;
static struct snd_device_ops dev_ops = {
- .dev_register = snd_hda_bus_dev_register,
.dev_free = snd_hda_bus_dev_free,
};
@@ -506,7 +430,6 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
bus->private_data = temp->private_data;
bus->pci = temp->pci;
bus->modelname = temp->modelname;
- bus->power_save = temp->power_save;
bus->ops = temp->ops;
mutex_init(&bus->cmd_mutex);
@@ -521,42 +444,27 @@ int /*__devinit*/ snd_hda_bus_new(struct snd_card *card,
*busp = bus;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_bus_new);
#ifdef CONFIG_SND_HDA_GENERIC
#define is_generic_config(codec) \
- (codec->modelname && !strcmp(codec->modelname, "generic"))
+ (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic"))
#else
#define is_generic_config(codec) 0
#endif
-#ifdef MODULE
-#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */
-#else
-#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */
-#endif
-
/*
* find a matching codec preset
*/
-static const struct hda_codec_preset *
+static const struct hda_codec_preset __devinit *
find_codec_preset(struct hda_codec *codec)
{
- struct hda_codec_preset_list *tbl;
- const struct hda_codec_preset *preset;
- int mod_requested = 0;
+ const struct hda_codec_preset **tbl, *preset;
if (is_generic_config(codec))
return NULL; /* use the generic parser */
- again:
- mutex_lock(&preset_mutex);
- list_for_each_entry(tbl, &hda_preset_tables, list) {
- if (!try_module_get(tbl->owner)) {
- snd_printk(KERN_ERR "hda_codec: cannot module_get\n");
- continue;
- }
- for (preset = tbl->preset; preset->id; preset++) {
+ for (tbl = hda_preset_tables; *tbl; tbl++) {
+ for (preset = *tbl; preset->id; preset++) {
u32 mask = preset->mask;
if (preset->afg && preset->afg != codec->afg)
continue;
@@ -566,40 +474,23 @@ find_codec_preset(struct hda_codec *codec)
mask = ~0;
if (preset->id == (codec->vendor_id & mask) &&
(!preset->rev ||
- preset->rev == codec->revision_id)) {
- mutex_unlock(&preset_mutex);
- codec->owner = tbl->owner;
+ preset->rev == codec->revision_id))
return preset;
- }
}
- module_put(tbl->owner);
- }
- mutex_unlock(&preset_mutex);
-
- if (mod_requested < HDA_MODREQ_MAX_COUNT) {
- char name[32];
- if (!mod_requested)
- snprintf(name, sizeof(name), "snd-hda-codec-id:%08x",
- codec->vendor_id);
- else
- snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*",
- (codec->vendor_id >> 16) & 0xffff);
- request_module(name);
- mod_requested++;
- goto again;
}
return NULL;
}
/*
- * get_codec_name - store the codec name
+ * snd_hda_get_codec_name - store the codec name
*/
-static int get_codec_name(struct hda_codec *codec)
+void snd_hda_get_codec_name(struct hda_codec *codec,
+ char *name, int namelen)
{
const struct hda_vendor_id *c;
const char *vendor = NULL;
u16 vendor_id = codec->vendor_id >> 16;
- char tmp[16], name[32];
+ char tmp[16];
for (c = hda_vendor_ids; c->id; c++) {
if (c->id == vendor_id) {
@@ -612,21 +503,16 @@ static int get_codec_name(struct hda_codec *codec)
vendor = tmp;
}
if (codec->preset && codec->preset->name)
- snprintf(name, sizeof(name), "%s %s", vendor,
- codec->preset->name);
+ snprintf(name, namelen, "%s %s", vendor, codec->preset->name);
else
- snprintf(name, sizeof(name), "%s ID %x", vendor,
+ snprintf(name, namelen, "%s ID %x", vendor,
codec->vendor_id & 0xffff);
- codec->name = kstrdup(name, GFP_KERNEL);
- if (!codec->name)
- return -ENOMEM;
- return 0;
}
/*
* look for an AFG and MFG nodes
*/
-static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec)
+static void __devinit setup_fg_nodes(struct hda_codec *codec)
{
int i, total_nodes;
hda_nid_t nid;
@@ -685,15 +571,11 @@ static void snd_hda_codec_free(struct hda_codec *codec)
flush_scheduled_work();
#endif
list_del(&codec->list);
- snd_array_free(&codec->mixers);
codec->bus->caddr_tbl[codec->addr] = NULL;
if (codec->patch_ops.free)
codec->patch_ops.free(codec);
- module_put(codec->owner);
free_hda_cache(&codec->amp_cache);
free_hda_cache(&codec->cmd_cache);
- kfree(codec->name);
- kfree(codec->modelname);
kfree(codec->wcaps);
kfree(codec);
}
@@ -706,7 +588,7 @@ static void snd_hda_codec_free(struct hda_codec *codec)
*
* Returns 0 if successful, or a negative error code.
*/
-int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
+int __devinit snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr,
struct hda_codec **codecp)
{
struct hda_codec *codec;
@@ -735,14 +617,6 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
mutex_init(&codec->spdif_mutex);
init_hda_cache(&codec->amp_cache, sizeof(struct hda_amp_info));
init_hda_cache(&codec->cmd_cache, sizeof(struct hda_cache_head));
- snd_array_init(&codec->mixers, sizeof(struct snd_kcontrol *), 32);
- if (codec->bus->modelname) {
- codec->modelname = kstrdup(codec->bus->modelname, GFP_KERNEL);
- if (!codec->modelname) {
- snd_hda_codec_free(codec);
- return -ENODEV;
- }
- }
#ifdef CONFIG_SND_HDA_POWER_SAVE
INIT_DELAYED_WORK(&codec->power_work, hda_power_work);
@@ -788,42 +662,12 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, unsigned int codec_addr
snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_SUBSYSTEM_ID, 0);
}
- if (bus->modelname)
- codec->modelname = kstrdup(bus->modelname, GFP_KERNEL);
-
- err = snd_hda_codec_configure(codec);
- if (err < 0) {
- snd_hda_codec_free(codec);
- return err;
- }
- snd_hda_codec_proc_new(codec);
-
- snd_hda_create_hwdep(codec);
-
- sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id,
- codec->subsystem_id, codec->revision_id);
- snd_component_add(codec->bus->card, component);
-
- if (codecp)
- *codecp = codec;
- return 0;
-}
-EXPORT_SYMBOL_HDA(snd_hda_codec_new);
-
-int snd_hda_codec_configure(struct hda_codec *codec)
-{
- int err;
codec->preset = find_codec_preset(codec);
- if (!codec->name) {
- err = get_codec_name(codec);
- if (err < 0)
- return err;
- }
/* audio codec should override the mixer name */
- if (codec->afg || !*codec->bus->card->mixername)
- strlcpy(codec->bus->card->mixername, codec->name,
- sizeof(codec->bus->card->mixername));
+ if (codec->afg || !*bus->card->mixername)
+ snd_hda_get_codec_name(codec, bus->card->mixername,
+ sizeof(bus->card->mixername));
if (is_generic_config(codec)) {
err = snd_hda_parse_generic_codec(codec);
@@ -840,9 +684,25 @@ int snd_hda_codec_configure(struct hda_codec *codec)
printk(KERN_ERR "hda-codec: No codec parser is available\n");
patched:
- if (!err && codec->patch_ops.unsol_event)
- err = init_unsol_queue(codec->bus);
- return err;
+ if (err < 0) {
+ snd_hda_codec_free(codec);
+ return err;
+ }
+
+ if (codec->patch_ops.unsol_event)
+ init_unsol_queue(bus);
+
+ snd_hda_codec_proc_new(codec);
+#ifdef CONFIG_SND_HDA_HWDEP
+ snd_hda_create_hwdep(codec);
+#endif
+
+ sprintf(component, "HDA:%08x,%08x,%08x", codec->vendor_id, codec->subsystem_id, codec->revision_id);
+ snd_component_add(codec->bus->card, component);
+
+ if (codecp)
+ *codecp = codec;
+ return 0;
}
/**
@@ -868,7 +728,6 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
msleep(1);
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, format);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_setup_stream);
void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
{
@@ -882,7 +741,6 @@ void snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid)
snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_STREAM_FORMAT, 0);
#endif
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
/*
* amp access functions
@@ -894,17 +752,17 @@ EXPORT_SYMBOL_HDA(snd_hda_codec_cleanup_stream);
#define INFO_AMP_VOL(ch) (1 << (1 + (ch)))
/* initialize the hash table */
-static void /*__devinit*/ init_hda_cache(struct hda_cache_rec *cache,
+static void __devinit init_hda_cache(struct hda_cache_rec *cache,
unsigned int record_size)
{
memset(cache, 0, sizeof(*cache));
memset(cache->hash, 0xff, sizeof(cache->hash));
- snd_array_init(&cache->buf, record_size, 64);
+ cache->record_size = record_size;
}
static void free_hda_cache(struct hda_cache_rec *cache)
{
- snd_array_free(&cache->buf);
+ kfree(cache->buffer);
}
/* query the hash. allocate an entry if not found. */
@@ -916,17 +774,35 @@ static struct hda_cache_head *get_alloc_hash(struct hda_cache_rec *cache,
struct hda_cache_head *info;
while (cur != 0xffff) {
- info = snd_array_elem(&cache->buf, cur);
+ info = (struct hda_cache_head *)(cache->buffer +
+ cur * cache->record_size);
if (info->key == key)
return info;
cur = info->next;
}
/* add a new hash entry */
- info = snd_array_new(&cache->buf);
- if (!info)
- return NULL;
- cur = snd_array_index(&cache->buf, info);
+ if (cache->num_entries >= cache->size) {
+ /* reallocate the array */
+ unsigned int new_size = cache->size + 64;
+ void *new_buffer;
+ new_buffer = kcalloc(new_size, cache->record_size, GFP_KERNEL);
+ if (!new_buffer) {
+ snd_printk(KERN_ERR "hda_codec: "
+ "can't malloc amp_info\n");
+ return NULL;
+ }
+ if (cache->buffer) {
+ memcpy(new_buffer, cache->buffer,
+ cache->size * cache->record_size);
+ kfree(cache->buffer);
+ }
+ cache->size = new_size;
+ cache->buffer = new_buffer;
+ }
+ cur = cache->num_entries++;
+ info = (struct hda_cache_head *)(cache->buffer +
+ cur * cache->record_size);
info->key = key;
info->val = 0;
info->next = cache->hash[idx];
@@ -964,7 +840,6 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction)
}
return info->amp_caps;
}
-EXPORT_SYMBOL_HDA(query_amp_caps);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps)
@@ -978,7 +853,6 @@ int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
info->head.val |= INFO_AMP_CAPS;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_override_amp_caps);
/*
* read the current volume to info
@@ -1032,7 +906,6 @@ int snd_hda_codec_amp_read(struct hda_codec *codec, hda_nid_t nid, int ch,
return 0;
return get_vol_mute(codec, info, nid, ch, direction, index);
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_read);
/*
* update the AMP value, mask = bit mask to set, val = the value
@@ -1052,7 +925,6 @@ int snd_hda_codec_amp_update(struct hda_codec *codec, hda_nid_t nid, int ch,
put_vol_mute(codec, info, nid, ch, direction, idx, val);
return 1;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_update);
/*
* update the AMP stereo with the same mask and value
@@ -1066,16 +938,15 @@ int snd_hda_codec_amp_stereo(struct hda_codec *codec, hda_nid_t nid,
idx, mask, val);
return ret;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_amp_stereo);
#ifdef SND_HDA_NEEDS_RESUME
/* resume the all amp commands from the cache */
void snd_hda_codec_resume_amp(struct hda_codec *codec)
{
- struct hda_amp_info *buffer = codec->amp_cache.buf.list;
+ struct hda_amp_info *buffer = codec->amp_cache.buffer;
int i;
- for (i = 0; i < codec->amp_cache.buf.used; i++, buffer++) {
+ for (i = 0; i < codec->amp_cache.size; i++, buffer++) {
u32 key = buffer->head.key;
hda_nid_t nid;
unsigned int idx, dir, ch;
@@ -1092,7 +963,6 @@ void snd_hda_codec_resume_amp(struct hda_codec *codec)
}
}
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_resume_amp);
#endif /* SND_HDA_NEEDS_RESUME */
/* volume */
@@ -1120,7 +990,6 @@ int snd_hda_mixer_amp_volume_info(struct snd_kcontrol *kcontrol,
uinfo->value.integer.max = caps;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_info);
int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1140,7 +1009,6 @@ int snd_hda_mixer_amp_volume_get(struct snd_kcontrol *kcontrol,
& HDA_AMP_VOLMASK;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_get);
int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1165,7 +1033,6 @@ int snd_hda_mixer_amp_volume_put(struct snd_kcontrol *kcontrol,
snd_hda_power_down(codec);
return change;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_volume_put);
int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *_tlv)
@@ -1192,7 +1059,6 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag,
return -EFAULT;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_tlv);
/*
* set (static) TLV for virtual master volume; recalculated as max 0dB
@@ -1212,7 +1078,6 @@ void snd_hda_set_vmaster_tlv(struct hda_codec *codec, hda_nid_t nid, int dir,
tlv[2] = -nums * step;
tlv[3] = step;
}
-EXPORT_SYMBOL_HDA(snd_hda_set_vmaster_tlv);
/* find a mixer control element with the given name */
static struct snd_kcontrol *
@@ -1232,67 +1097,6 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
{
return _snd_hda_find_mixer_ctl(codec, name, 0);
}
-EXPORT_SYMBOL_HDA(snd_hda_find_mixer_ctl);
-
-/* Add a control element and assign to the codec */
-int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl)
-{
- int err;
- struct snd_kcontrol **knewp;
-
- err = snd_ctl_add(codec->bus->card, kctl);
- if (err < 0)
- return err;
- knewp = snd_array_new(&codec->mixers);
- if (!knewp)
- return -ENOMEM;
- *knewp = kctl;
- return 0;
-}
-EXPORT_SYMBOL_HDA(snd_hda_ctl_add);
-
-#ifdef CONFIG_SND_HDA_RECONFIG
-/* Clear all controls assigned to the given codec */
-void snd_hda_ctls_clear(struct hda_codec *codec)
-{
- int i;
- struct snd_kcontrol **kctls = codec->mixers.list;
- for (i = 0; i < codec->mixers.used; i++)
- snd_ctl_remove(codec->bus->card, kctls[i]);
- snd_array_free(&codec->mixers);
-}
-
-void snd_hda_codec_reset(struct hda_codec *codec)
-{
- int i;
-
-#ifdef CONFIG_SND_HDA_POWER_SAVE
- cancel_delayed_work(&codec->power_work);
- flush_scheduled_work();
-#endif
- snd_hda_ctls_clear(codec);
- /* relase PCMs */
- for (i = 0; i < codec->num_pcms; i++) {
- if (codec->pcm_info[i].pcm) {
- snd_device_free(codec->bus->card,
- codec->pcm_info[i].pcm);
- clear_bit(codec->pcm_info[i].device,
- codec->bus->pcm_dev_bits);
- }
- }
- if (codec->patch_ops.free)
- codec->patch_ops.free(codec);
- codec->proc_widget_hook = NULL;
- codec->spec = NULL;
- free_hda_cache(&codec->amp_cache);
- free_hda_cache(&codec->cmd_cache);
- codec->num_pcms = 0;
- codec->pcm_info = NULL;
- codec->preset = NULL;
- module_put(codec->owner);
- codec->owner = NULL;
-}
-#endif /* CONFIG_SND_HDA_RECONFIG */
/* create a virtual master control and add slaves */
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
@@ -1311,7 +1115,7 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
kctl = snd_ctl_make_virtual_master(name, tlv);
if (!kctl)
return -ENOMEM;
- err = snd_hda_ctl_add(codec, kctl);
+ err = snd_ctl_add(codec->bus->card, kctl);
if (err < 0)
return err;
@@ -1329,7 +1133,6 @@ int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_add_vmaster);
/* switch */
int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
@@ -1343,7 +1146,6 @@ int snd_hda_mixer_amp_switch_info(struct snd_kcontrol *kcontrol,
uinfo->value.integer.max = 1;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_info);
int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1363,7 +1165,6 @@ int snd_hda_mixer_amp_switch_get(struct snd_kcontrol *kcontrol,
HDA_AMP_MUTE) ? 0 : 1;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_get);
int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1394,7 +1195,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol,
snd_hda_power_down(codec);
return change;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put);
/*
* bound volume controls
@@ -1420,7 +1220,6 @@ int snd_hda_mixer_bind_switch_get(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_get);
int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1444,7 +1243,6 @@ int snd_hda_mixer_bind_switch_put(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err < 0 ? err : change;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_switch_put);
/*
* generic bound volume/swtich controls
@@ -1464,7 +1262,6 @@ int snd_hda_mixer_bind_ctls_info(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_info);
int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1481,7 +1278,6 @@ int snd_hda_mixer_bind_ctls_get(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_get);
int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
@@ -1504,7 +1300,6 @@ int snd_hda_mixer_bind_ctls_put(struct snd_kcontrol *kcontrol,
mutex_unlock(&codec->spdif_mutex);
return err < 0 ? err : change;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_ctls_put);
int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
unsigned int size, unsigned int __user *tlv)
@@ -1521,7 +1316,6 @@ int snd_hda_mixer_bind_tlv(struct snd_kcontrol *kcontrol, int op_flag,
mutex_unlock(&codec->spdif_mutex);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_mixer_bind_tlv);
struct hda_ctl_ops snd_hda_bind_vol = {
.info = snd_hda_mixer_amp_volume_info,
@@ -1529,7 +1323,6 @@ struct hda_ctl_ops snd_hda_bind_vol = {
.put = snd_hda_mixer_amp_volume_put,
.tlv = snd_hda_mixer_amp_tlv
};
-EXPORT_SYMBOL_HDA(snd_hda_bind_vol);
struct hda_ctl_ops snd_hda_bind_sw = {
.info = snd_hda_mixer_amp_switch_info,
@@ -1537,7 +1330,6 @@ struct hda_ctl_ops snd_hda_bind_sw = {
.put = snd_hda_mixer_amp_switch_put,
.tlv = snd_hda_mixer_amp_tlv
};
-EXPORT_SYMBOL_HDA(snd_hda_bind_sw);
/*
* SPDIF out controls
@@ -1785,11 +1577,9 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
}
for (dig_mix = dig_mixes; dig_mix->name; dig_mix++) {
kctl = snd_ctl_new1(dig_mix, codec);
- if (!kctl)
- return -ENOMEM;
kctl->id.index = idx;
kctl->private_value = nid;
- err = snd_hda_ctl_add(codec, kctl);
+ err = snd_ctl_add(codec->bus->card, kctl);
if (err < 0)
return err;
}
@@ -1799,7 +1589,6 @@ int snd_hda_create_spdif_out_ctls(struct hda_codec *codec, hda_nid_t nid)
codec->spdif_status = convert_to_spdif_status(codec->spdif_ctls);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_out_ctls);
/*
* SPDIF sharing with analog output
@@ -1834,10 +1623,9 @@ int snd_hda_create_spdif_share_sw(struct hda_codec *codec,
if (!mout->dig_out_nid)
return 0;
/* ATTENTION: here mout is passed as private_data, instead of codec */
- return snd_hda_ctl_add(codec,
+ return snd_ctl_add(codec->bus->card,
snd_ctl_new1(&spdif_share_sw, mout));
}
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_share_sw);
/*
* SPDIF input
@@ -1937,7 +1725,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
for (dig_mix = dig_in_ctls; dig_mix->name; dig_mix++) {
kctl = snd_ctl_new1(dig_mix, codec);
kctl->private_value = nid;
- err = snd_hda_ctl_add(codec, kctl);
+ err = snd_ctl_add(codec->bus->card, kctl);
if (err < 0)
return err;
}
@@ -1947,7 +1735,6 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid)
AC_DIG1_ENABLE;
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
#ifdef SND_HDA_NEEDS_RESUME
/*
@@ -1974,14 +1761,10 @@ EXPORT_SYMBOL_HDA(snd_hda_create_spdif_in_ctls);
int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
int direct, unsigned int verb, unsigned int parm)
{
- struct hda_bus *bus = codec->bus;
- unsigned int res;
int err;
-
- res = make_codec_cmd(codec, nid, direct, verb, parm);
snd_hda_power_up(codec);
- mutex_lock(&bus->cmd_mutex);
- err = bus->ops.command(bus, res);
+ mutex_lock(&codec->bus->cmd_mutex);
+ err = codec->bus->ops.command(codec, nid, direct, verb, parm);
if (!err) {
struct hda_cache_head *c;
u32 key = build_cmd_cache_key(nid, verb);
@@ -1989,19 +1772,18 @@ int snd_hda_codec_write_cache(struct hda_codec *codec, hda_nid_t nid,
if (c)
c->val = parm;
}
- mutex_unlock(&bus->cmd_mutex);
+ mutex_unlock(&codec->bus->cmd_mutex);
snd_hda_power_down(codec);
return err;
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_write_cache);
/* resume the all commands from the cache */
void snd_hda_codec_resume_cache(struct hda_codec *codec)
{
- struct hda_cache_head *buffer = codec->cmd_cache.buf.list;
+ struct hda_cache_head *buffer = codec->cmd_cache.buffer;
int i;
- for (i = 0; i < codec->cmd_cache.buf.used; i++, buffer++) {
+ for (i = 0; i < codec->cmd_cache.size; i++, buffer++) {
u32 key = buffer->key;
if (!key)
continue;
@@ -2009,7 +1791,6 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec)
get_cmd_cache_cmd(key), buffer->val);
}
}
-EXPORT_SYMBOL_HDA(snd_hda_codec_resume_cache);
/**
* snd_hda_sequence_write_cache - sequence writes with caching
@@ -2027,7 +1808,6 @@ void snd_hda_sequence_write_cache(struct hda_codec *codec,
snd_hda_codec_write_cache(codec, seq->nid, 0, seq->verb,
seq->param);
}
-EXPORT_SYMBOL_HDA(snd_hda_sequence_write_cache);
#endif /* SND_HDA_NEEDS_RESUME */
/*
@@ -2088,17 +1868,6 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
}
}
-#ifdef CONFIG_SND_HDA_HWDEP
-/* execute additional init verbs */
-static void hda_exec_init_verbs(struct hda_codec *codec)
-{
- if (codec->init_verbs.list)
- snd_hda_sequence_write(codec, codec->init_verbs.list);
-}
-#else
-static inline void hda_exec_init_verbs(struct hda_codec *codec) {}
-#endif
-
#ifdef SND_HDA_NEEDS_RESUME
/*
* call suspend and power-down; used both from PM and power-save
@@ -2125,7 +1894,6 @@ static void hda_call_codec_resume(struct hda_codec *codec)
hda_set_power_state(codec,
codec->afg ? codec->afg : codec->mfg,
AC_PWRST_D0);
- hda_exec_init_verbs(codec);
if (codec->patch_ops.resume)
codec->patch_ops.resume(codec);
else {
@@ -2146,37 +1914,28 @@ static void hda_call_codec_resume(struct hda_codec *codec)
*
* Returns 0 if successful, otherwise a negative error code.
*/
-int /*__devinit*/ snd_hda_build_controls(struct hda_bus *bus)
+int __devinit snd_hda_build_controls(struct hda_bus *bus)
{
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
- int err = snd_hda_codec_build_controls(codec);
+ int err = 0;
+ /* fake as if already powered-on */
+ hda_keep_power_on(codec);
+ /* then fire up */
+ hda_set_power_state(codec,
+ codec->afg ? codec->afg : codec->mfg,
+ AC_PWRST_D0);
+ /* continue to initialize... */
+ if (codec->patch_ops.init)
+ err = codec->patch_ops.init(codec);
+ if (!err && codec->patch_ops.build_controls)
+ err = codec->patch_ops.build_controls(codec);
+ snd_hda_power_down(codec);
if (err < 0)
return err;
}
- return 0;
-}
-EXPORT_SYMBOL_HDA(snd_hda_build_controls);
-int snd_hda_codec_build_controls(struct hda_codec *codec)
-{
- int err = 0;
- /* fake as if already powered-on */
- hda_keep_power_on(codec);
- /* then fire up */
- hda_set_power_state(codec,
- codec->afg ? codec->afg : codec->mfg,
- AC_PWRST_D0);
- hda_exec_init_verbs(codec);
- /* continue to initialize... */
- if (codec->patch_ops.init)
- err = codec->patch_ops.init(codec);
- if (!err && codec->patch_ops.build_controls)
- err = codec->patch_ops.build_controls(codec);
- snd_hda_power_down(codec);
- if (err < 0)
- return err;
return 0;
}
@@ -2269,7 +2028,6 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
return val;
}
-EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
/**
* snd_hda_query_supported_pcm - query the supported PCM rates and formats
@@ -2284,7 +2042,7 @@ EXPORT_SYMBOL_HDA(snd_hda_calc_stream_format);
*
* Returns 0 if successful, otherwise a negative error code.
*/
-static int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
u32 *ratesp, u64 *formatsp, unsigned int *bpsp)
{
int i;
@@ -2449,7 +2207,6 @@ int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
return 1;
}
-EXPORT_SYMBOL_HDA(snd_hda_is_supported_format);
/*
* PCM stuff
@@ -2479,8 +2236,8 @@ static int hda_pcm_default_cleanup(struct hda_pcm_stream *hinfo,
return 0;
}
-static int set_pcm_default_values(struct hda_codec *codec,
- struct hda_pcm_stream *info)
+static int __devinit set_pcm_default_values(struct hda_codec *codec,
+ struct hda_pcm_stream *info)
{
/* query support PCM information from the given NID */
if (info->nid && (!info->rates || !info->formats)) {
@@ -2506,110 +2263,6 @@ static int set_pcm_default_values(struct hda_codec *codec,
return 0;
}
-/*
- * get the empty PCM device number to assign
- */
-static int get_empty_pcm_device(struct hda_bus *bus, int type)
-{
- static const char *dev_name[HDA_PCM_NTYPES] = {
- "Audio", "SPDIF", "HDMI", "Modem"
- };
- /* starting device index for each PCM type */
- static int dev_idx[HDA_PCM_NTYPES] = {
- [HDA_PCM_TYPE_AUDIO] = 0,
- [HDA_PCM_TYPE_SPDIF] = 1,
- [HDA_PCM_TYPE_HDMI] = 3,
- [HDA_PCM_TYPE_MODEM] = 6
- };
- /* normal audio device indices; not linear to keep compatibility */
- static int audio_idx[4] = { 0, 2, 4, 5 };
- int i, dev;
-
- switch (type) {
- case HDA_PCM_TYPE_AUDIO:
- for (i = 0; i < ARRAY_SIZE(audio_idx); i++) {
- dev = audio_idx[i];
- if (!test_bit(dev, bus->pcm_dev_bits))
- break;
- }
- if (i >= ARRAY_SIZE(audio_idx)) {
- snd_printk(KERN_WARNING "Too many audio devices\n");
- return -EAGAIN;
- }
- break;
- case HDA_PCM_TYPE_SPDIF:
- case HDA_PCM_TYPE_HDMI:
- case HDA_PCM_TYPE_MODEM:
- dev = dev_idx[type];
- if (test_bit(dev, bus->pcm_dev_bits)) {
- snd_printk(KERN_WARNING "%s already defined\n",
- dev_name[type]);
- return -EAGAIN;
- }
- break;
- default:
- snd_printk(KERN_WARNING "Invalid PCM type %d\n", type);
- return -EINVAL;
- }
- set_bit(dev, bus->pcm_dev_bits);
- return dev;
-}
-
-/*
- * attach a new PCM stream
- */
-static int snd_hda_attach_pcm(struct hda_codec *codec, struct hda_pcm *pcm)
-{
- struct hda_bus *bus = codec->bus;
- struct hda_pcm_stream *info;
- int stream, err;
-
- if (snd_BUG_ON(!pcm->name))
- return -EINVAL;
- for (stream = 0; stream < 2; stream++) {
- info = &pcm->stream[stream];
- if (info->substreams) {
- err = set_pcm_default_values(codec, info);
- if (err < 0)
- return err;
- }
- }
- return bus->ops.attach_pcm(bus, codec, pcm);
-}
-
-/* assign all PCMs of the given codec */
-int snd_hda_codec_build_pcms(struct hda_codec *codec)
-{
- unsigned int pcm;
- int err;
-
- if (!codec->num_pcms) {
- if (!codec->patch_ops.build_pcms)
- return 0;
- err = codec->patch_ops.build_pcms(codec);
- if (err < 0)
- return err;
- }
- for (pcm = 0; pcm < codec->num_pcms; pcm++) {
- struct hda_pcm *cpcm = &codec->pcm_info[pcm];
- int dev;
-
- if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
- return 0; /* no substreams assigned */
-
- if (!cpcm->pcm) {
- dev = get_empty_pcm_device(codec->bus, cpcm->pcm_type);
- if (dev < 0)
- return 0;
- cpcm->device = dev;
- err = snd_hda_attach_pcm(codec, cpcm);
- if (err < 0)
- return err;
- }
- }
- return 0;
-}
-
/**
* snd_hda_build_pcms - build PCM information
* @bus: the BUS
@@ -2641,13 +2294,27 @@ int __devinit snd_hda_build_pcms(struct hda_bus *bus)
struct hda_codec *codec;
list_for_each_entry(codec, &bus->codec_list, list) {
- int err = snd_hda_codec_build_pcms(codec);
+ unsigned int pcm, s;
+ int err;
+ if (!codec->patch_ops.build_pcms)
+ continue;
+ err = codec->patch_ops.build_pcms(codec);
if (err < 0)
return err;
+ for (pcm = 0; pcm < codec->num_pcms; pcm++) {
+ for (s = 0; s < 2; s++) {
+ struct hda_pcm_stream *info;
+ info = &codec->pcm_info[pcm].stream[s];
+ if (!info->substreams)
+ continue;
+ err = set_pcm_default_values(codec, info);
+ if (err < 0)
+ return err;
+ }
+ }
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_build_pcms);
/**
* snd_hda_check_board_config - compare the current codec with the config table
@@ -2666,11 +2333,11 @@ int snd_hda_check_board_config(struct hda_codec *codec,
int num_configs, const char **models,
const struct snd_pci_quirk *tbl)
{
- if (codec->modelname && models) {
+ if (codec->bus->modelname && models) {
int i;
for (i = 0; i < num_configs; i++) {
if (models[i] &&
- !strcmp(codec->modelname, models[i])) {
+ !strcmp(codec->bus->modelname, models[i])) {
snd_printd(KERN_INFO "hda_codec: model '%s' is "
"selected\n", models[i]);
return i;
@@ -2703,7 +2370,6 @@ int snd_hda_check_board_config(struct hda_codec *codec,
}
return -1;
}
-EXPORT_SYMBOL_HDA(snd_hda_check_board_config);
/**
* snd_hda_add_new_ctls - create controls from the array
@@ -2724,7 +2390,7 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
kctl = snd_ctl_new1(knew, codec);
if (!kctl)
return -ENOMEM;
- err = snd_hda_ctl_add(codec, kctl);
+ err = snd_ctl_add(codec->bus->card, kctl);
if (err < 0) {
if (!codec->addr)
return err;
@@ -2732,14 +2398,13 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, struct snd_kcontrol_new *knew)
if (!kctl)
return -ENOMEM;
kctl->id.device = codec->addr;
- err = snd_hda_ctl_add(codec, kctl);
+ err = snd_ctl_add(codec->bus->card, kctl);
if (err < 0)
return err;
}
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_add_new_ctls);
#ifdef CONFIG_SND_HDA_POWER_SAVE
static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
@@ -2749,7 +2414,6 @@ static void hda_power_work(struct work_struct *work)
{
struct hda_codec *codec =
container_of(work, struct hda_codec, power_work.work);
- struct hda_bus *bus = codec->bus;
if (!codec->power_on || codec->power_count) {
codec->power_transition = 0;
@@ -2757,8 +2421,8 @@ static void hda_power_work(struct work_struct *work)
}
hda_call_codec_suspend(codec);
- if (bus->ops.pm_notify)
- bus->ops.pm_notify(bus);
+ if (codec->bus->ops.pm_notify)
+ codec->bus->ops.pm_notify(codec);
}
static void hda_keep_power_on(struct hda_codec *codec)
@@ -2769,39 +2433,29 @@ static void hda_keep_power_on(struct hda_codec *codec)
void snd_hda_power_up(struct hda_codec *codec)
{
- struct hda_bus *bus = codec->bus;
-
codec->power_count++;
if (codec->power_on || codec->power_transition)
return;
codec->power_on = 1;
- if (bus->ops.pm_notify)
- bus->ops.pm_notify(bus);
+ if (codec->bus->ops.pm_notify)
+ codec->bus->ops.pm_notify(codec);
hda_call_codec_resume(codec);
cancel_delayed_work(&codec->power_work);
codec->power_transition = 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_power_up);
-
-#define power_save(codec) \
- ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
-
-#define power_save(codec) \
- ((codec)->bus->power_save ? *(codec)->bus->power_save : 0)
void snd_hda_power_down(struct hda_codec *codec)
{
--codec->power_count;
if (!codec->power_on || codec->power_count || codec->power_transition)
return;
- if (power_save(codec)) {
+ if (power_save) {
codec->power_transition = 1; /* avoid reentrance */
schedule_delayed_work(&codec->power_work,
- msecs_to_jiffies(power_save(codec) * 1000));
+ msecs_to_jiffies(power_save * 1000));
}
}
-EXPORT_SYMBOL_HDA(snd_hda_power_down);
int snd_hda_check_amp_list_power(struct hda_codec *codec,
struct hda_loopback_check *check,
@@ -2838,7 +2492,6 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_check_amp_list_power);
#endif
/*
@@ -2858,7 +2511,6 @@ int snd_hda_ch_mode_info(struct hda_codec *codec,
chmode[uinfo->value.enumerated.item].channels);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_info);
int snd_hda_ch_mode_get(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
@@ -2876,7 +2528,6 @@ int snd_hda_ch_mode_get(struct hda_codec *codec,
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_get);
int snd_hda_ch_mode_put(struct hda_codec *codec,
struct snd_ctl_elem_value *ucontrol,
@@ -2897,7 +2548,6 @@ int snd_hda_ch_mode_put(struct hda_codec *codec,
snd_hda_sequence_write_cache(codec, chmode[mode].sequence);
return 1;
}
-EXPORT_SYMBOL_HDA(snd_hda_ch_mode_put);
/*
* input MUX helper
@@ -2918,7 +2568,6 @@ int snd_hda_input_mux_info(const struct hda_input_mux *imux,
strcpy(uinfo->value.enumerated.name, imux->items[index].label);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_input_mux_info);
int snd_hda_input_mux_put(struct hda_codec *codec,
const struct hda_input_mux *imux,
@@ -2940,7 +2589,6 @@ int snd_hda_input_mux_put(struct hda_codec *codec,
*cur_val = idx;
return 1;
}
-EXPORT_SYMBOL_HDA(snd_hda_input_mux_put);
/*
@@ -2993,7 +2641,6 @@ int snd_hda_multi_out_dig_open(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_open);
int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
struct hda_multi_out *mout,
@@ -3006,7 +2653,6 @@ int snd_hda_multi_out_dig_prepare(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_prepare);
/*
* release the digital out
@@ -3019,7 +2665,6 @@ int snd_hda_multi_out_dig_close(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_dig_close);
/*
* set up more restrictions for analog out
@@ -3059,7 +2704,6 @@ int snd_hda_multi_out_analog_open(struct hda_codec *codec,
return snd_pcm_hw_constraint_step(substream->runtime, 0,
SNDRV_PCM_HW_PARAM_CHANNELS, 2);
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_open);
/*
* set up the i/o for analog out
@@ -3118,7 +2762,6 @@ int snd_hda_multi_out_analog_prepare(struct hda_codec *codec,
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_prepare);
/*
* clean up the setting for analog out
@@ -3145,7 +2788,6 @@ int snd_hda_multi_out_analog_cleanup(struct hda_codec *codec,
mutex_unlock(&codec->spdif_mutex);
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_multi_out_analog_cleanup);
/*
* Helper for automatic pin configuration
@@ -3431,13 +3073,11 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config);
/* labels for input pins */
const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = {
"Mic", "Front Mic", "Line", "Front Line", "CD", "Aux"
};
-EXPORT_SYMBOL_HDA(auto_pin_cfg_labels);
#ifdef CONFIG_PM
@@ -3465,11 +3105,11 @@ int snd_hda_suspend(struct hda_bus *bus, pm_message_t state)
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_suspend);
/**
* snd_hda_resume - resume the codecs
* @bus: the HDA bus
+ * @state: resume state
*
* Returns 0 if successful.
*
@@ -3486,79 +3126,16 @@ int snd_hda_resume(struct hda_bus *bus)
}
return 0;
}
-EXPORT_SYMBOL_HDA(snd_hda_resume);
-#endif /* CONFIG_PM */
-
-/*
- * generic arrays
- */
-
-/* get a new element from the given array
- * if it exceeds the pre-allocated array size, re-allocate the array
- */
-void *snd_array_new(struct snd_array *array)
-{
- if (array->used >= array->alloced) {
- int num = array->alloced + array->alloc_align;
- void *nlist;
- if (snd_BUG_ON(num >= 4096))
- return NULL;
- nlist = kcalloc(num + 1, array->elem_size, GFP_KERNEL);
- if (!nlist)
- return NULL;
- if (array->list) {
- memcpy(nlist, array->list,
- array->elem_size * array->alloced);
- kfree(array->list);
- }
- array->list = nlist;
- array->alloced = num;
- }
- return snd_array_elem(array, array->used++);
-}
-EXPORT_SYMBOL_HDA(snd_array_new);
-
-/* free the given array elements */
-void snd_array_free(struct snd_array *array)
-{
- kfree(array->list);
- array->used = 0;
- array->alloced = 0;
- array->list = NULL;
-}
-EXPORT_SYMBOL_HDA(snd_array_free);
-
-/*
- * used by hda_proc.c and hda_eld.c
- */
-void snd_print_pcm_rates(int pcm, char *buf, int buflen)
-{
- static unsigned int rates[] = {
- 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
- 96000, 176400, 192000, 384000
- };
- int i, j;
-
- for (i = 0, j = 0; i < ARRAY_SIZE(rates); i++)
- if (pcm & (1 << i))
- j += snprintf(buf + j, buflen - j, " %d", rates[i]);
-
- buf[j] = '\0'; /* necessary when j == 0 */
-}
-EXPORT_SYMBOL_HDA(snd_print_pcm_rates);
-
-void snd_print_pcm_bits(int pcm, char *buf, int buflen)
+#ifdef CONFIG_SND_HDA_POWER_SAVE
+int snd_hda_codecs_inuse(struct hda_bus *bus)
{
- static unsigned int bits[] = { 8, 16, 20, 24, 32 };
- int i, j;
-
- for (i = 0, j = 0; i < ARRAY_SIZE(bits); i++)
- if (pcm & (AC_SUPPCM_BITS_8 << i))
- j += snprintf(buf + j, buflen - j, " %d", bits[i]);
+ struct hda_codec *codec;
- buf[j] = '\0'; /* necessary when j == 0 */
+ list_for_each_entry(codec, &bus->codec_list, list) {
+ if (snd_hda_codec_needs_resume(codec))
+ return 1;
+ }
+ return 0;
}
-EXPORT_SYMBOL_HDA(snd_print_pcm_bits);
-
-MODULE_DESCRIPTION("HDA codec core");
-MODULE_LICENSE("GPL");
+#endif
+#endif
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h
index 5587d416229f..60468f562400 100644
--- a/sound/pci/hda/hda_codec.h
+++ b/sound/pci/hda/hda_codec.h
@@ -520,36 +520,6 @@ enum {
#define HDA_MAX_CODEC_ADDRESS 0x0f
/*
- * generic arrays
- */
-struct snd_array {
- unsigned int used;
- unsigned int alloced;
- unsigned int elem_size;
- unsigned int alloc_align;
- void *list;
-};
-
-void *snd_array_new(struct snd_array *array);
-void snd_array_free(struct snd_array *array);
-static inline void snd_array_init(struct snd_array *array, unsigned int size,
- unsigned int align)
-{
- array->elem_size = size;
- array->alloc_align = align;
-}
-
-static inline void *snd_array_elem(struct snd_array *array, unsigned int idx)
-{
- return array->list + idx * array->elem_size;
-}
-
-static inline unsigned int snd_array_index(struct snd_array *array, void *ptr)
-{
- return (unsigned long)(ptr - array->list) / array->elem_size;
-}
-
-/*
* Structures
*/
@@ -566,17 +536,15 @@ typedef u16 hda_nid_t;
/* bus operators */
struct hda_bus_ops {
/* send a single command */
- int (*command)(struct hda_bus *bus, unsigned int cmd);
+ int (*command)(struct hda_codec *codec, hda_nid_t nid, int direct,
+ unsigned int verb, unsigned int parm);
/* get a response from the last command */
- unsigned int (*get_response)(struct hda_bus *bus);
+ unsigned int (*get_response)(struct hda_codec *codec);
/* free the private data */
void (*private_free)(struct hda_bus *);
- /* attach a PCM stream */
- int (*attach_pcm)(struct hda_bus *bus, struct hda_codec *codec,
- struct hda_pcm *pcm);
#ifdef CONFIG_SND_HDA_POWER_SAVE
/* notify power-up/down from codec to controller */
- void (*pm_notify)(struct hda_bus *bus);
+ void (*pm_notify)(struct hda_codec *codec);
#endif
};
@@ -585,7 +553,6 @@ struct hda_bus_template {
void *private_data;
struct pci_dev *pci;
const char *modelname;
- int *power_save;
struct hda_bus_ops ops;
};
@@ -602,7 +569,6 @@ struct hda_bus {
void *private_data;
struct pci_dev *pci;
const char *modelname;
- int *power_save;
struct hda_bus_ops ops;
/* codec linked list */
@@ -615,12 +581,10 @@ struct hda_bus {
/* unsolicited event queue */
struct hda_bus_unsolicited *unsol;
- /* assigned PCMs */
- DECLARE_BITMAP(pcm_dev_bits, SNDRV_PCM_DEVICES);
+ struct snd_info_entry *proc;
/* misc op flags */
unsigned int needs_damn_long_delay :1;
- unsigned int shutdown :1; /* being unloaded */
};
/*
@@ -640,16 +604,6 @@ struct hda_codec_preset {
int (*patch)(struct hda_codec *codec);
};
-struct hda_codec_preset_list {
- const struct hda_codec_preset *preset;
- struct module *owner;
- struct list_head list;
-};
-
-/* initial hook */
-int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset);
-int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset);
-
/* ops set by the preset patch */
struct hda_codec_ops {
int (*build_controls)(struct hda_codec *codec);
@@ -681,7 +635,10 @@ struct hda_amp_info {
struct hda_cache_rec {
u16 hash[64]; /* hash table for index */
- struct snd_array buf; /* record entries */
+ unsigned int num_entries; /* number of assigned entries */
+ unsigned int size; /* allocated size */
+ unsigned int record_size; /* record size (including header) */
+ void *buffer; /* hash table entries */
};
/* PCM callbacks */
@@ -723,8 +680,7 @@ struct hda_pcm {
char *name;
struct hda_pcm_stream stream[2];
unsigned int pcm_type; /* HDA_PCM_TYPE_XXX */
- int device; /* device number to assign */
- struct snd_pcm *pcm; /* assigned PCM instance */
+ int device; /* assigned device number */
};
/* codec information */
@@ -743,9 +699,6 @@ struct hda_codec {
/* detected preset */
const struct hda_codec_preset *preset;
- struct module *owner;
- const char *name; /* codec name */
- const char *modelname; /* model name for preset */
/* set by patch */
struct hda_codec_ops patch_ops;
@@ -765,8 +718,6 @@ struct hda_codec {
hda_nid_t start_nid;
u32 *wcaps;
- struct snd_array mixers; /* list of assigned mixer elements */
-
struct hda_cache_rec amp_cache; /* cache for amp access */
struct hda_cache_rec cmd_cache; /* cache for other commands */
@@ -776,11 +727,7 @@ struct hda_codec {
unsigned int spdif_in_enable; /* SPDIF input enable? */
hda_nid_t *slave_dig_outs; /* optional digital out slave widgets */
-#ifdef CONFIG_SND_HDA_HWDEP
struct snd_hwdep *hwdep; /* assigned hwdep device */
- struct snd_array init_verbs; /* additional init verbs */
- struct snd_array hints; /* additional hints */
-#endif
/* misc flags */
unsigned int spdif_status_reset :1; /* needs to toggle SPDIF for each
@@ -793,10 +740,6 @@ struct hda_codec {
int power_count; /* current (global) power refcount */
struct delayed_work power_work; /* delayed task for powerdown */
#endif
-
- /* codec-specific additional proc output */
- void (*proc_widget_hook)(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid);
};
/* direction */
@@ -856,13 +799,11 @@ void snd_hda_codec_resume_cache(struct hda_codec *codec);
* Mixer
*/
int snd_hda_build_controls(struct hda_bus *bus);
-int snd_hda_codec_build_controls(struct hda_codec *codec);
/*
* PCM
*/
int snd_hda_build_pcms(struct hda_bus *bus);
-int snd_hda_codec_build_pcms(struct hda_codec *codec);
void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid,
u32 stream_tag,
int channel_id, int format);
@@ -871,6 +812,8 @@ unsigned int snd_hda_calc_stream_format(unsigned int rate,
unsigned int channels,
unsigned int format,
unsigned int maxbps);
+int snd_hda_query_supported_pcm(struct hda_codec *codec, hda_nid_t nid,
+ u32 *ratesp, u64 *formatsp, unsigned int *bpsp);
int snd_hda_is_supported_format(struct hda_codec *codec, hda_nid_t nid,
unsigned int format);
@@ -888,38 +831,18 @@ int snd_hda_resume(struct hda_bus *bus);
#endif
/*
- * get widget information
- */
-const char *snd_hda_get_jack_connectivity(u32 cfg);
-const char *snd_hda_get_jack_type(u32 cfg);
-const char *snd_hda_get_jack_location(u32 cfg);
-
-/*
* power saving
*/
#ifdef CONFIG_SND_HDA_POWER_SAVE
void snd_hda_power_up(struct hda_codec *codec);
void snd_hda_power_down(struct hda_codec *codec);
#define snd_hda_codec_needs_resume(codec) codec->power_count
+int snd_hda_codecs_inuse(struct hda_bus *bus);
#else
static inline void snd_hda_power_up(struct hda_codec *codec) {}
static inline void snd_hda_power_down(struct hda_codec *codec) {}
#define snd_hda_codec_needs_resume(codec) 1
-#endif
-
-/*
- * Codec modularization
- */
-
-/* Export symbols only for communication with codec drivers;
- * When built in kernel, all HD-audio drivers are supposed to be statically
- * linked to the kernel. Thus, the symbols don't have to (or shouldn't) be
- * exported unless it's built as a module.
- */
-#ifdef MODULE
-#define EXPORT_SYMBOL_HDA(sym) EXPORT_SYMBOL_GPL(sym)
-#else
-#define EXPORT_SYMBOL_HDA(sym)
+#define snd_hda_codecs_inuse(bus) 1
#endif
#endif /* __SOUND_HDA_CODEC_H */
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c
deleted file mode 100644
index fcad5ec31773..000000000000
--- a/sound/pci/hda/hda_eld.c
+++ /dev/null
@@ -1,590 +0,0 @@
-/*
- * Generic routines and proc interface for ELD(EDID Like Data) information
- *
- * Copyright(c) 2008 Intel Corporation.
- *
- * Authors:
- * Wu Fengguang <wfg@linux.intel.com>
- *
- * This driver is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This driver is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/init.h>
-#include <sound/core.h>
-#include <asm/unaligned.h>
-#include "hda_codec.h"
-#include "hda_local.h"
-
-enum eld_versions {
- ELD_VER_CEA_861D = 2,
- ELD_VER_PARTIAL = 31,
-};
-
-enum cea_edid_versions {
- CEA_EDID_VER_NONE = 0,
- CEA_EDID_VER_CEA861 = 1,
- CEA_EDID_VER_CEA861A = 2,
- CEA_EDID_VER_CEA861BCD = 3,
- CEA_EDID_VER_RESERVED = 4,
-};
-
-static char *cea_speaker_allocation_names[] = {
- /* 0 */ "FL/FR",
- /* 1 */ "LFE",
- /* 2 */ "FC",
- /* 3 */ "RL/RR",
- /* 4 */ "RC",
- /* 5 */ "FLC/FRC",
- /* 6 */ "RLC/RRC",
- /* 7 */ "FLW/FRW",
- /* 8 */ "FLH/FRH",
- /* 9 */ "TC",
- /* 10 */ "FCH",
-};
-
-static char *eld_connection_type_names[4] = {
- "HDMI",
- "DisplayPort",
- "2-reserved",
- "3-reserved"
-};
-
-enum cea_audio_coding_types {
- AUDIO_CODING_TYPE_REF_STREAM_HEADER = 0,
- AUDIO_CODING_TYPE_LPCM = 1,
- AUDIO_CODING_TYPE_AC3 = 2,
- AUDIO_CODING_TYPE_MPEG1 = 3,
- AUDIO_CODING_TYPE_MP3 = 4,
- AUDIO_CODING_TYPE_MPEG2 = 5,
- AUDIO_CODING_TYPE_AACLC = 6,
- AUDIO_CODING_TYPE_DTS = 7,
- AUDIO_CODING_TYPE_ATRAC = 8,
- AUDIO_CODING_TYPE_SACD = 9,
- AUDIO_CODING_TYPE_EAC3 = 10,
- AUDIO_CODING_TYPE_DTS_HD = 11,
- AUDIO_CODING_TYPE_MLP = 12,
- AUDIO_CODING_TYPE_DST = 13,
- AUDIO_CODING_TYPE_WMAPRO = 14,
- AUDIO_CODING_TYPE_REF_CXT = 15,
- /* also include valid xtypes below */
- AUDIO_CODING_TYPE_HE_AAC = 15,
- AUDIO_CODING_TYPE_HE_AAC2 = 16,
- AUDIO_CODING_TYPE_MPEG_SURROUND = 17,
-};
-
-enum cea_audio_coding_xtypes {
- AUDIO_CODING_XTYPE_HE_REF_CT = 0,
- AUDIO_CODING_XTYPE_HE_AAC = 1,
- AUDIO_CODING_XTYPE_HE_AAC2 = 2,
- AUDIO_CODING_XTYPE_MPEG_SURROUND = 3,
- AUDIO_CODING_XTYPE_FIRST_RESERVED = 4,
-};
-
-static char *cea_audio_coding_type_names[] = {
- /* 0 */ "undefined",
- /* 1 */ "LPCM",
- /* 2 */ "AC-3",
- /* 3 */ "MPEG1",
- /* 4 */ "MP3",
- /* 5 */ "MPEG2",
- /* 6 */ "AAC-LC",
- /* 7 */ "DTS",
- /* 8 */ "ATRAC",
- /* 9 */ "DSD (One Bit Audio)",
- /* 10 */ "E-AC-3/DD+ (Dolby Digital Plus)",
- /* 11 */ "DTS-HD",
- /* 12 */ "MLP (Dolby TrueHD)",
- /* 13 */ "DST",
- /* 14 */ "WMAPro",
- /* 15 */ "HE-AAC",
- /* 16 */ "HE-AACv2",
- /* 17 */ "MPEG Surround",
-};
-
-/*
- * The following two lists are shared between
- * - HDMI audio InfoFrame (source to sink)
- * - CEA E-EDID Extension (sink to source)
- */
-
-/*
- * SS1:SS0 index => sample size
- */
-static int cea_sample_sizes[4] = {
- 0, /* 0: Refer to Stream Header */
- AC_SUPPCM_BITS_16, /* 1: 16 bits */
- AC_SUPPCM_BITS_20, /* 2: 20 bits */
- AC_SUPPCM_BITS_24, /* 3: 24 bits */
-};
-
-/*
- * SF2:SF1:SF0 index => sampling frequency
- */
-static int cea_sampling_frequencies[8] = {
- 0, /* 0: Refer to Stream Header */
- SNDRV_PCM_RATE_32000, /* 1: 32000Hz */
- SNDRV_PCM_RATE_44100, /* 2: 44100Hz */
- SNDRV_PCM_RATE_48000, /* 3: 48000Hz */
- SNDRV_PCM_RATE_88200, /* 4: 88200Hz */
- SNDRV_PCM_RATE_96000, /* 5: 96000Hz */
- SNDRV_PCM_RATE_176400, /* 6: 176400Hz */
- SNDRV_PCM_RATE_192000, /* 7: 192000Hz */
-};
-
-static unsigned char hdmi_get_eld_byte(struct hda_codec *codec, hda_nid_t nid,
- int byte_index)
-{
- unsigned int val;
-
- val = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_HDMI_ELDD, byte_index);
-
-#ifdef BE_PARANOID
- printk(KERN_INFO "HDMI: ELD data byte %d: 0x%x\n", byte_index, val);
-#endif
-
- if ((val & AC_ELDD_ELD_VALID) == 0) {
- snd_printd(KERN_INFO "HDMI: invalid ELD data byte %d\n",
- byte_index);
- val = 0;
- }
-
- return val & AC_ELDD_ELD_DATA;
-}
-
-#define GRAB_BITS(buf, byte, lowbit, bits) \
-({ \
- BUILD_BUG_ON(lowbit > 7); \
- BUILD_BUG_ON(bits > 8); \
- BUILD_BUG_ON(bits <= 0); \
- \
- (buf[byte] >> (lowbit)) & ((1 << (bits)) - 1); \
-})
-
-static void hdmi_update_short_audio_desc(struct cea_sad *a,
- const unsigned char *buf)
-{
- int i;
- int val;
-
- val = GRAB_BITS(buf, 1, 0, 7);
- a->rates = 0;
- for (i = 0; i < 7; i++)
- if (val & (1 << i))
- a->rates |= cea_sampling_frequencies[i + 1];
-
- a->channels = GRAB_BITS(buf, 0, 0, 3);
- a->channels++;
-
- a->format = GRAB_BITS(buf, 0, 3, 4);
- switch (a->format) {
- case AUDIO_CODING_TYPE_REF_STREAM_HEADER:
- snd_printd(KERN_INFO
- "HDMI: audio coding type 0 not expected\n");
- break;
-
- case AUDIO_CODING_TYPE_LPCM:
- val = GRAB_BITS(buf, 2, 0, 3);
- a->sample_bits = 0;
- for (i = 0; i < 3; i++)
- if (val & (1 << i))
- a->sample_bits |= cea_sample_sizes[i + 1];
- break;
-
- case AUDIO_CODING_TYPE_AC3:
- case AUDIO_CODING_TYPE_MPEG1:
- case AUDIO_CODING_TYPE_MP3:
- case AUDIO_CODING_TYPE_MPEG2:
- case AUDIO_CODING_TYPE_AACLC:
- case AUDIO_CODING_TYPE_DTS:
- case AUDIO_CODING_TYPE_ATRAC:
- a->max_bitrate = GRAB_BITS(buf, 2, 0, 8);
- a->max_bitrate *= 8000;
- break;
-
- case AUDIO_CODING_TYPE_SACD:
- break;
-
- case AUDIO_CODING_TYPE_EAC3:
- break;
-
- case AUDIO_CODING_TYPE_DTS_HD:
- break;
-
- case AUDIO_CODING_TYPE_MLP:
- break;
-
- case AUDIO_CODING_TYPE_DST:
- break;
-
- case AUDIO_CODING_TYPE_WMAPRO:
- a->profile = GRAB_BITS(buf, 2, 0, 3);
- break;
-
- case AUDIO_CODING_TYPE_REF_CXT:
- a->format = GRAB_BITS(buf, 2, 3, 5);
- if (a->format == AUDIO_CODING_XTYPE_HE_REF_CT ||
- a->format >= AUDIO_CODING_XTYPE_FIRST_RESERVED) {
- snd_printd(KERN_INFO
- "HDMI: audio coding xtype %d not expected\n",
- a->format);
- a->format = 0;
- } else
- a->format += AUDIO_CODING_TYPE_HE_AAC -
- AUDIO_CODING_XTYPE_HE_AAC;
- break;
- }
-}
-
-/*
- * Be careful, ELD buf could be totally rubbish!
- */
-static int hdmi_update_eld(struct hdmi_eld *e,
- const unsigned char *buf, int size)
-{
- int mnl;
- int i;
-
- e->eld_ver = GRAB_BITS(buf, 0, 3, 5);
- if (e->eld_ver != ELD_VER_CEA_861D &&
- e->eld_ver != ELD_VER_PARTIAL) {
- snd_printd(KERN_INFO "HDMI: Unknown ELD version %d\n",
- e->eld_ver);
- goto out_fail;
- }
-
- e->eld_size = size;
- e->baseline_len = GRAB_BITS(buf, 2, 0, 8);
- mnl = GRAB_BITS(buf, 4, 0, 5);
- e->cea_edid_ver = GRAB_BITS(buf, 4, 5, 3);
-
- e->support_hdcp = GRAB_BITS(buf, 5, 0, 1);
- e->support_ai = GRAB_BITS(buf, 5, 1, 1);
- e->conn_type = GRAB_BITS(buf, 5, 2, 2);
- e->sad_count = GRAB_BITS(buf, 5, 4, 4);
-
- e->aud_synch_delay = GRAB_BITS(buf, 6, 0, 8) * 2;
- e->spk_alloc = GRAB_BITS(buf, 7, 0, 7);
-
- e->port_id = get_unaligned_le64(buf + 8);
-
- /* not specified, but the spec's tendency is little endian */
- e->manufacture_id = get_unaligned_le16(buf + 16);
- e->product_id = get_unaligned_le16(buf + 18);
-
- if (mnl > ELD_MAX_MNL) {
- snd_printd(KERN_INFO "HDMI: MNL is reserved value %d\n", mnl);
- goto out_fail;
- } else if (ELD_FIXED_BYTES + mnl > size) {
- snd_printd(KERN_INFO "HDMI: out of range MNL %d\n", mnl);
- goto out_fail;
- } else
- strlcpy(e->monitor_name, buf + ELD_FIXED_BYTES, mnl);
-
- for (i = 0; i < e->sad_count; i++) {
- if (ELD_FIXED_BYTES + mnl + 3 * (i + 1) > size) {
- snd_printd(KERN_INFO "HDMI: out of range SAD %d\n", i);
- goto out_fail;
- }
- hdmi_update_short_audio_desc(e->sad + i,
- buf + ELD_FIXED_BYTES + mnl + 3 * i);
- }
-
- return 0;
-
-out_fail:
- e->eld_ver = 0;
- return -EINVAL;
-}
-
-static int hdmi_present_sense(struct hda_codec *codec, hda_nid_t nid)
-{
- return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0);
-}
-
-static int hdmi_eld_valid(struct hda_codec *codec, hda_nid_t nid)
-{
- int eldv;
- int present;
-
- present = hdmi_present_sense(codec, nid);
- eldv = (present & AC_PINSENSE_ELDV);
- present = (present & AC_PINSENSE_PRESENCE);
-
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- printk(KERN_INFO "HDMI: sink_present = %d, eld_valid = %d\n",
- !!present, !!eldv);
-#endif
-
- return eldv && present;
-}
-
-int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid)
-{
- return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE,
- AC_DIPSIZE_ELD_BUF);
-}
-
-int snd_hdmi_get_eld(struct hdmi_eld *eld,
- struct hda_codec *codec, hda_nid_t nid)
-{
- int i;
- int ret;
- int size;
- unsigned char *buf;
-
- if (!hdmi_eld_valid(codec, nid))
- return -ENOENT;
-
- size = snd_hdmi_get_eld_size(codec, nid);
- if (size == 0) {
- /* wfg: workaround for ASUS P5E-VM HDMI board */
- snd_printd(KERN_INFO "HDMI: ELD buf size is 0, force 128\n");
- size = 128;
- }
- if (size < ELD_FIXED_BYTES || size > PAGE_SIZE) {
- snd_printd(KERN_INFO "HDMI: invalid ELD buf size %d\n", size);
- return -ERANGE;
- }
-
- buf = kmalloc(size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- for (i = 0; i < size; i++)
- buf[i] = hdmi_get_eld_byte(codec, nid, i);
-
- ret = hdmi_update_eld(eld, buf, size);
-
- kfree(buf);
- return ret;
-}
-
-static void hdmi_show_short_audio_desc(struct cea_sad *a)
-{
- char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
- char buf2[8 + SND_PRINT_BITS_ADVISED_BUFSIZE] = ", bits =";
-
- if (!a->format)
- return;
-
- snd_print_pcm_rates(a->rates, buf, sizeof(buf));
-
- if (a->format == AUDIO_CODING_TYPE_LPCM)
- snd_print_pcm_bits(a->sample_bits, buf2 + 8, sizeof(buf2 - 8));
- else if (a->max_bitrate)
- snprintf(buf2, sizeof(buf2),
- ", max bitrate = %d", a->max_bitrate);
- else
- buf2[0] = '\0';
-
- printk(KERN_INFO "HDMI: supports coding type %s:"
- " channels = %d, rates =%s%s\n",
- cea_audio_coding_type_names[a->format],
- a->channels,
- buf,
- buf2);
-}
-
-void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen)
-{
- int i, j;
-
- for (i = 0, j = 0; i < ARRAY_SIZE(cea_speaker_allocation_names); i++) {
- if (spk_alloc & (1 << i))
- j += snprintf(buf + j, buflen - j, " %s",
- cea_speaker_allocation_names[i]);
- }
- buf[j] = '\0'; /* necessary when j == 0 */
-}
-
-void snd_hdmi_show_eld(struct hdmi_eld *e)
-{
- int i;
-
- printk(KERN_INFO "HDMI: detected monitor %s at connection type %s\n",
- e->monitor_name,
- eld_connection_type_names[e->conn_type]);
-
- if (e->spk_alloc) {
- char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
- snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
- printk(KERN_INFO "HDMI: available speakers:%s\n", buf);
- }
-
- for (i = 0; i < e->sad_count; i++)
- hdmi_show_short_audio_desc(e->sad + i);
-}
-
-#ifdef CONFIG_PROC_FS
-
-static void hdmi_print_sad_info(int i, struct cea_sad *a,
- struct snd_info_buffer *buffer)
-{
- char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
-
- snd_iprintf(buffer, "sad%d_coding_type\t[0x%x] %s\n",
- i, a->format, cea_audio_coding_type_names[a->format]);
- snd_iprintf(buffer, "sad%d_channels\t\t%d\n", i, a->channels);
-
- snd_print_pcm_rates(a->rates, buf, sizeof(buf));
- snd_iprintf(buffer, "sad%d_rates\t\t[0x%x]%s\n", i, a->rates, buf);
-
- if (a->format == AUDIO_CODING_TYPE_LPCM) {
- snd_print_pcm_bits(a->sample_bits, buf, sizeof(buf));
- snd_iprintf(buffer, "sad%d_bits\t\t[0x%x]%s\n",
- i, a->sample_bits, buf);
- }
-
- if (a->max_bitrate)
- snd_iprintf(buffer, "sad%d_max_bitrate\t%d\n",
- i, a->max_bitrate);
-
- if (a->profile)
- snd_iprintf(buffer, "sad%d_profile\t\t%d\n", i, a->profile);
-}
-
-static void hdmi_print_eld_info(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct hdmi_eld *e = entry->private_data;
- char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
- int i;
- static char *eld_versoin_names[32] = {
- "reserved",
- "reserved",
- "CEA-861D or below",
- [3 ... 30] = "reserved",
- [31] = "partial"
- };
- static char *cea_edid_version_names[8] = {
- "no CEA EDID Timing Extension block present",
- "CEA-861",
- "CEA-861-A",
- "CEA-861-B, C or D",
- [4 ... 7] = "reserved"
- };
-
- snd_iprintf(buffer, "monitor_name\t\t%s\n", e->monitor_name);
- snd_iprintf(buffer, "connection_type\t\t%s\n",
- eld_connection_type_names[e->conn_type]);
- snd_iprintf(buffer, "eld_version\t\t[0x%x] %s\n", e->eld_ver,
- eld_versoin_names[e->eld_ver]);
- snd_iprintf(buffer, "edid_version\t\t[0x%x] %s\n", e->cea_edid_ver,
- cea_edid_version_names[e->cea_edid_ver]);
- snd_iprintf(buffer, "manufacture_id\t\t0x%x\n", e->manufacture_id);
- snd_iprintf(buffer, "product_id\t\t0x%x\n", e->product_id);
- snd_iprintf(buffer, "port_id\t\t\t0x%llx\n", (long long)e->port_id);
- snd_iprintf(buffer, "support_hdcp\t\t%d\n", e->support_hdcp);
- snd_iprintf(buffer, "support_ai\t\t%d\n", e->support_ai);
- snd_iprintf(buffer, "audio_sync_delay\t%d\n", e->aud_synch_delay);
-
- snd_print_channel_allocation(e->spk_alloc, buf, sizeof(buf));
- snd_iprintf(buffer, "speakers\t\t[0x%x]%s\n", e->spk_alloc, buf);
-
- snd_iprintf(buffer, "sad_count\t\t%d\n", e->sad_count);
-
- for (i = 0; i < e->sad_count; i++)
- hdmi_print_sad_info(i, e->sad + i, buffer);
-}
-
-static void hdmi_write_eld_info(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
-{
- struct hdmi_eld *e = entry->private_data;
- char line[64];
- char name[64];
- char *sname;
- long long val;
- int n;
-
- while (!snd_info_get_line(buffer, line, sizeof(line))) {
- if (sscanf(line, "%s %llx", name, &val) != 2)
- continue;
- /*
- * We don't allow modification to these fields:
- * monitor_name manufacture_id product_id
- * eld_version edid_version
- */
- if (!strcmp(name, "connection_type"))
- e->conn_type = val;
- else if (!strcmp(name, "port_id"))
- e->port_id = val;
- else if (!strcmp(name, "support_hdcp"))
- e->support_hdcp = val;
- else if (!strcmp(name, "support_ai"))
- e->support_ai = val;
- else if (!strcmp(name, "audio_sync_delay"))
- e->aud_synch_delay = val;
- else if (!strcmp(name, "speakers"))
- e->spk_alloc = val;
- else if (!strcmp(name, "sad_count"))
- e->sad_count = val;
- else if (!strncmp(name, "sad", 3)) {
- sname = name + 4;
- n = name[3] - '0';
- if (name[4] >= '0' && name[4] <= '9') {
- sname++;
- n = 10 * n + name[4] - '0';
- }
- if (n < 0 || n > 31) /* double the CEA limit */
- continue;
- if (!strcmp(sname, "_coding_type"))
- e->sad[n].format = val;
- else if (!strcmp(sname, "_channels"))
- e->sad[n].channels = val;
- else if (!strcmp(sname, "_rates"))
- e->sad[n].rates = val;
- else if (!strcmp(sname, "_bits"))
- e->sad[n].sample_bits = val;
- else if (!strcmp(sname, "_max_bitrate"))
- e->sad[n].max_bitrate = val;
- else if (!strcmp(sname, "_profile"))
- e->sad[n].profile = val;
- if (n >= e->sad_count)
- e->sad_count = n + 1;
- }
- }
-}
-
-
-int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld)
-{
- char name[32];
- struct snd_info_entry *entry;
- int err;
-
- snprintf(name, sizeof(name), "eld#%d", codec->addr);
- err = snd_card_proc_new(codec->bus->card, name, &entry);
- if (err < 0)
- return err;
-
- snd_info_set_text_ops(entry, eld, hdmi_print_eld_info);
- entry->c.text.write = hdmi_write_eld_info;
- entry->mode |= S_IWUSR;
- eld->proc_entry = entry;
-
- return 0;
-}
-
-void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld)
-{
- if (!codec->bus->shutdown && eld->proc_entry) {
- snd_device_free(codec->bus->card, eld->proc_entry);
- eld->proc_entry = NULL;
- }
-}
-
-#endif /* CONFIG_PROC_FS */
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index 65745e96dc70..0ca30894f7c6 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -723,8 +723,7 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
if (is_loopback)
add_input_loopback(codec, node->nid, HDA_INPUT, index);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
- err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
- if (err < 0)
+ if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
created = 1;
} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
@@ -733,8 +732,7 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
if (is_loopback)
add_input_loopback(codec, node->nid, HDA_OUTPUT, 0);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
- err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
- if (err < 0)
+ if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
created = 1;
}
@@ -747,16 +745,14 @@ static int create_mixer(struct hda_codec *codec, struct hda_gnode *node,
(node->amp_in_caps & AC_AMPCAP_NUM_STEPS)) {
knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, index, HDA_INPUT);
snd_printdd("[%s] NID=0x%x, DIR=IN, IDX=0x%x\n", name, node->nid, index);
- err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
- if (err < 0)
+ if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
created = 1;
} else if ((node->wid_caps & AC_WCAP_OUT_AMP) &&
(node->amp_out_caps & AC_AMPCAP_NUM_STEPS)) {
knew = (struct snd_kcontrol_new)HDA_CODEC_VOLUME(name, node->nid, 0, HDA_OUTPUT);
snd_printdd("[%s] NID=0x%x, DIR=OUT\n", name, node->nid);
- err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
- if (err < 0)
+ if ((err = snd_ctl_add(codec->bus->card, snd_ctl_new1(&knew, codec))) < 0)
return err;
created = 1;
}
@@ -853,8 +849,8 @@ static int build_input_controls(struct hda_codec *codec)
}
/* create input MUX if multiple sources are available */
- err = snd_hda_ctl_add(codec, snd_ctl_new1(&cap_sel, codec));
- if (err < 0)
+ if ((err = snd_ctl_add(codec->bus->card,
+ snd_ctl_new1(&cap_sel, codec))) < 0)
return err;
/* no volume control? */
@@ -871,8 +867,8 @@ static int build_input_controls(struct hda_codec *codec)
HDA_CODEC_VOLUME(name, adc_node->nid,
spec->input_mux.items[i].index,
HDA_INPUT);
- err = snd_hda_ctl_add(codec, snd_ctl_new1(&knew, codec));
- if (err < 0)
+ if ((err = snd_ctl_add(codec->bus->card,
+ snd_ctl_new1(&knew, codec))) < 0)
return err;
}
@@ -1101,4 +1097,3 @@ int snd_hda_parse_generic_codec(struct hda_codec *codec)
snd_hda_generic_free(codec);
return err;
}
-EXPORT_SYMBOL(snd_hda_parse_generic_codec);
diff --git a/sound/pci/hda/hda_hwdep.c b/sound/pci/hda/hda_hwdep.c
index 300ab407cf42..6e18a422d993 100644
--- a/sound/pci/hda/hda_hwdep.c
+++ b/sound/pci/hda/hda_hwdep.c
@@ -23,12 +23,10 @@
#include <linux/pci.h>
#include <linux/compat.h>
#include <linux/mutex.h>
-#include <linux/ctype.h>
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
#include <sound/hda_hwdep.h>
-#include <sound/minors.h>
/*
* write/read an out-of-bound verb
@@ -97,26 +95,7 @@ static int hda_hwdep_open(struct snd_hwdep *hw, struct file *file)
return 0;
}
-static void clear_hwdep_elements(struct hda_codec *codec)
-{
- char **head;
- int i;
-
- /* clear init verbs */
- snd_array_free(&codec->init_verbs);
- /* clear hints */
- head = codec->hints.list;
- for (i = 0; i < codec->hints.used; i++, head++)
- kfree(*head);
- snd_array_free(&codec->hints);
-}
-
-static void hwdep_free(struct snd_hwdep *hwdep)
-{
- clear_hwdep_elements(hwdep->private_data);
-}
-
-int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
+int __devinit snd_hda_create_hwdep(struct hda_codec *codec)
{
char hwname[16];
struct snd_hwdep *hwdep;
@@ -130,7 +109,6 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
sprintf(hwdep->name, "HDA Codec %d", codec->addr);
hwdep->iface = SNDRV_HWDEP_IFACE_HDA;
hwdep->private_data = codec;
- hwdep->private_free = hwdep_free;
hwdep->exclusive = 1;
hwdep->ops.open = hda_hwdep_open;
@@ -139,215 +117,5 @@ int /*__devinit*/ snd_hda_create_hwdep(struct hda_codec *codec)
hwdep->ops.ioctl_compat = hda_hwdep_ioctl_compat;
#endif
- snd_array_init(&codec->init_verbs, sizeof(struct hda_verb), 32);
- snd_array_init(&codec->hints, sizeof(char *), 32);
-
return 0;
}
-
-#ifdef CONFIG_SND_HDA_RECONFIG
-
-/*
- * sysfs interface
- */
-
-static int clear_codec(struct hda_codec *codec)
-{
- snd_hda_codec_reset(codec);
- clear_hwdep_elements(codec);
- return 0;
-}
-
-static int reconfig_codec(struct hda_codec *codec)
-{
- int err;
-
- snd_printk(KERN_INFO "hda-codec: reconfiguring\n");
- snd_hda_codec_reset(codec);
- err = snd_hda_codec_configure(codec);
- if (err < 0)
- return err;
- /* rebuild PCMs */
- err = snd_hda_codec_build_pcms(codec);
- if (err < 0)
- return err;
- /* rebuild mixers */
- err = snd_hda_codec_build_controls(codec);
- if (err < 0)
- return err;
- return 0;
-}
-
-/*
- * allocate a string at most len chars, and remove the trailing EOL
- */
-static char *kstrndup_noeol(const char *src, size_t len)
-{
- char *s = kstrndup(src, len, GFP_KERNEL);
- char *p;
- if (!s)
- return NULL;
- p = strchr(s, '\n');
- if (p)
- *p = 0;
- return s;
-}
-
-#define CODEC_INFO_SHOW(type) \
-static ssize_t type##_show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
- struct hda_codec *codec = hwdep->private_data; \
- return sprintf(buf, "0x%x\n", codec->type); \
-}
-
-#define CODEC_INFO_STR_SHOW(type) \
-static ssize_t type##_show(struct device *dev, \
- struct device_attribute *attr, \
- char *buf) \
-{ \
- struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
- struct hda_codec *codec = hwdep->private_data; \
- return sprintf(buf, "%s\n", \
- codec->type ? codec->type : ""); \
-}
-
-CODEC_INFO_SHOW(vendor_id);
-CODEC_INFO_SHOW(subsystem_id);
-CODEC_INFO_SHOW(revision_id);
-CODEC_INFO_SHOW(afg);
-CODEC_INFO_SHOW(mfg);
-CODEC_INFO_STR_SHOW(name);
-CODEC_INFO_STR_SHOW(modelname);
-
-#define CODEC_INFO_STORE(type) \
-static ssize_t type##_store(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
- struct hda_codec *codec = hwdep->private_data; \
- char *after; \
- codec->type = simple_strtoul(buf, &after, 0); \
- return count; \
-}
-
-#define CODEC_INFO_STR_STORE(type) \
-static ssize_t type##_store(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
- struct hda_codec *codec = hwdep->private_data; \
- char *s = kstrndup_noeol(buf, 64); \
- if (!s) \
- return -ENOMEM; \
- kfree(codec->type); \
- codec->type = s; \
- return count; \
-}
-
-CODEC_INFO_STORE(vendor_id);
-CODEC_INFO_STORE(subsystem_id);
-CODEC_INFO_STORE(revision_id);
-CODEC_INFO_STR_STORE(name);
-CODEC_INFO_STR_STORE(modelname);
-
-#define CODEC_ACTION_STORE(type) \
-static ssize_t type##_store(struct device *dev, \
- struct device_attribute *attr, \
- const char *buf, size_t count) \
-{ \
- struct snd_hwdep *hwdep = dev_get_drvdata(dev); \
- struct hda_codec *codec = hwdep->private_data; \
- int err = 0; \
- if (*buf) \
- err = type##_codec(codec); \
- return err < 0 ? err : count; \
-}
-
-CODEC_ACTION_STORE(reconfig);
-CODEC_ACTION_STORE(clear);
-
-static ssize_t init_verbs_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct snd_hwdep *hwdep = dev_get_drvdata(dev);
- struct hda_codec *codec = hwdep->private_data;
- char *p;
- struct hda_verb verb, *v;
-
- verb.nid = simple_strtoul(buf, &p, 0);
- verb.verb = simple_strtoul(p, &p, 0);
- verb.param = simple_strtoul(p, &p, 0);
- if (!verb.nid || !verb.verb || !verb.param)
- return -EINVAL;
- v = snd_array_new(&codec->init_verbs);
- if (!v)
- return -ENOMEM;
- *v = verb;
- return count;
-}
-
-static ssize_t hints_store(struct device *dev,
- struct device_attribute *attr,
- const char *buf, size_t count)
-{
- struct snd_hwdep *hwdep = dev_get_drvdata(dev);
- struct hda_codec *codec = hwdep->private_data;
- char *p;
- char **hint;
-
- if (!*buf || isspace(*buf) || *buf == '#' || *buf == '\n')
- return count;
- p = kstrndup_noeol(buf, 1024);
- if (!p)
- return -ENOMEM;
- hint = snd_array_new(&codec->hints);
- if (!hint) {
- kfree(p);
- return -ENOMEM;
- }
- *hint = p;
- return count;
-}
-
-#define CODEC_ATTR_RW(type) \
- __ATTR(type, 0644, type##_show, type##_store)
-#define CODEC_ATTR_RO(type) \
- __ATTR_RO(type)
-#define CODEC_ATTR_WO(type) \
- __ATTR(type, 0200, NULL, type##_store)
-
-static struct device_attribute codec_attrs[] = {
- CODEC_ATTR_RW(vendor_id),
- CODEC_ATTR_RW(subsystem_id),
- CODEC_ATTR_RW(revision_id),
- CODEC_ATTR_RO(afg),
- CODEC_ATTR_RO(mfg),
- CODEC_ATTR_RW(name),
- CODEC_ATTR_RW(modelname),
- CODEC_ATTR_WO(init_verbs),
- CODEC_ATTR_WO(hints),
- CODEC_ATTR_WO(reconfig),
- CODEC_ATTR_WO(clear),
-};
-
-/*
- * create sysfs files on hwdep directory
- */
-int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
-{
- struct snd_hwdep *hwdep = codec->hwdep;
- int i;
-
- for (i = 0; i < ARRAY_SIZE(codec_attrs); i++)
- snd_add_device_sysfs_file(SNDRV_DEVICE_TYPE_HWDEP, hwdep->card,
- hwdep->device, &codec_attrs[i]);
- return 0;
-}
-
-#endif /* CONFIG_SND_HDA_RECONFIG */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 29836cc63d8f..35722ec920cb 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -83,10 +83,7 @@ module_param(enable_msi, int, 0444);
MODULE_PARM_DESC(enable_msi, "Enable Message Signaled Interrupt (MSI)");
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT;
-module_param(power_save, int, 0644);
-MODULE_PARM_DESC(power_save, "Automatic power-saving timeout "
- "(in second, 0 = disable).");
+/* power_save option is defined in hda_codec.c */
/* reset the HD-audio controller in power save mode.
* this may give more power-saving, but will take longer time to
@@ -295,8 +292,6 @@ enum {
/* Define VIA HD Audio Device ID*/
#define VIA_HDAC_DEVICE_ID 0x3288
-/* HD Audio class code */
-#define PCI_CLASS_MULTIMEDIA_HD_AUDIO 0x0403
/*
*/
@@ -397,7 +392,6 @@ struct azx {
unsigned int msi :1;
unsigned int irq_pending_warned :1;
unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */
- unsigned int probing :1; /* codec probing phase */
/* for debugging */
unsigned int last_cmd; /* last issued command (to sync) */
@@ -420,7 +414,6 @@ enum {
AZX_DRIVER_ULI,
AZX_DRIVER_NVIDIA,
AZX_DRIVER_TERA,
- AZX_DRIVER_GENERIC,
AZX_NUM_DRIVERS, /* keep this as last entry */
};
@@ -434,7 +427,6 @@ static char *driver_short_names[] __devinitdata = {
[AZX_DRIVER_ULI] = "HDA ULI M5461",
[AZX_DRIVER_NVIDIA] = "HDA NVidia",
[AZX_DRIVER_TERA] = "HDA Teradici",
- [AZX_DRIVER_GENERIC] = "HD-Audio Generic",
};
/*
@@ -535,9 +527,9 @@ static void azx_free_cmd_io(struct azx *chip)
}
/* send a command */
-static int azx_corb_send_cmd(struct hda_bus *bus, u32 val)
+static int azx_corb_send_cmd(struct hda_codec *codec, u32 val)
{
- struct azx *chip = bus->private_data;
+ struct azx *chip = codec->bus->private_data;
unsigned int wp;
/* add command to corb */
@@ -585,9 +577,9 @@ static void azx_update_rirb(struct azx *chip)
}
/* receive a response */
-static unsigned int azx_rirb_get_response(struct hda_bus *bus)
+static unsigned int azx_rirb_get_response(struct hda_codec *codec)
{
- struct azx *chip = bus->private_data;
+ struct azx *chip = codec->bus->private_data;
unsigned long timeout;
again:
@@ -604,7 +596,7 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
}
if (time_after(jiffies, timeout))
break;
- if (bus->needs_damn_long_delay)
+ if (codec->bus->needs_damn_long_delay)
msleep(2); /* temporary workaround */
else {
udelay(10);
@@ -632,14 +624,6 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
goto again;
}
- if (chip->probing) {
- /* If this critical timeout happens during the codec probing
- * phase, this is likely an access to a non-existing codec
- * slot. Better to return an error and reset the system.
- */
- return -1;
- }
-
snd_printk(KERN_ERR "hda_intel: azx_get_response timeout, "
"switching to single_cmd mode: last cmd=0x%08x\n",
chip->last_cmd);
@@ -662,9 +646,9 @@ static unsigned int azx_rirb_get_response(struct hda_bus *bus)
*/
/* send a command */
-static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
+static int azx_single_send_cmd(struct hda_codec *codec, u32 val)
{
- struct azx *chip = bus->private_data;
+ struct azx *chip = codec->bus->private_data;
int timeout = 50;
while (timeout--) {
@@ -687,9 +671,9 @@ static int azx_single_send_cmd(struct hda_bus *bus, u32 val)
}
/* receive a response */
-static unsigned int azx_single_get_response(struct hda_bus *bus)
+static unsigned int azx_single_get_response(struct hda_codec *codec)
{
- struct azx *chip = bus->private_data;
+ struct azx *chip = codec->bus->private_data;
int timeout = 50;
while (timeout--) {
@@ -712,29 +696,38 @@ static unsigned int azx_single_get_response(struct hda_bus *bus)
*/
/* send a command */
-static int azx_send_cmd(struct hda_bus *bus, unsigned int val)
+static int azx_send_cmd(struct hda_codec *codec, hda_nid_t nid,
+ int direct, unsigned int verb,
+ unsigned int para)
{
- struct azx *chip = bus->private_data;
-
+ struct azx *chip = codec->bus->private_data;
+ u32 val;
+
+ val = (u32)(codec->addr & 0x0f) << 28;
+ val |= (u32)direct << 27;
+ val |= (u32)nid << 20;
+ val |= verb << 8;
+ val |= para;
chip->last_cmd = val;
+
if (chip->single_cmd)
- return azx_single_send_cmd(bus, val);
+ return azx_single_send_cmd(codec, val);
else
- return azx_corb_send_cmd(bus, val);
+ return azx_corb_send_cmd(codec, val);
}
/* get a response */
-static unsigned int azx_get_response(struct hda_bus *bus)
+static unsigned int azx_get_response(struct hda_codec *codec)
{
- struct azx *chip = bus->private_data;
+ struct azx *chip = codec->bus->private_data;
if (chip->single_cmd)
- return azx_single_get_response(bus);
+ return azx_single_get_response(codec);
else
- return azx_rirb_get_response(bus);
+ return azx_rirb_get_response(codec);
}
#ifdef CONFIG_SND_HDA_POWER_SAVE
-static void azx_power_notify(struct hda_bus *bus);
+static void azx_power_notify(struct hda_codec *codec);
#endif
/* reset codec link */
@@ -1191,28 +1184,6 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev)
return 0;
}
-/*
- * Probe the given codec address
- */
-static int probe_codec(struct azx *chip, int addr)
-{
- unsigned int cmd = (addr << 28) | (AC_NODE_ROOT << 20) |
- (AC_VERB_PARAMETERS << 8) | AC_PAR_VENDOR_ID;
- unsigned int res;
-
- chip->probing = 1;
- azx_send_cmd(chip->bus, cmd);
- res = azx_get_response(chip->bus);
- chip->probing = 0;
- if (res == -1)
- return -EIO;
- snd_printdd("hda_intel: codec #%d probed OK\n", addr);
- return 0;
-}
-
-static int azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
- struct hda_pcm *cpcm);
-static void azx_stop_chip(struct azx *chip);
/*
* Codec initialization
@@ -1223,12 +1194,21 @@ static unsigned int azx_max_codecs[AZX_NUM_DRIVERS] __devinitdata = {
[AZX_DRIVER_TERA] = 1,
};
+/* number of slots to probe as default
+ * this can be different from azx_max_codecs[] -- e.g. some boards
+ * report wrongly the non-existing 4th slot availability
+ */
+static unsigned int azx_default_codecs[AZX_NUM_DRIVERS] __devinitdata = {
+ [AZX_DRIVER_ICH] = 3,
+ [AZX_DRIVER_ATI] = 3,
+};
+
static int __devinit azx_codec_create(struct azx *chip, const char *model,
unsigned int codec_probe_mask)
{
struct hda_bus_template bus_temp;
- int c, codecs, err;
- int max_slots;
+ int c, codecs, audio_codecs, err;
+ int def_slots, max_slots;
memset(&bus_temp, 0, sizeof(bus_temp));
bus_temp.private_data = chip;
@@ -1236,9 +1216,7 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
bus_temp.pci = chip->pci;
bus_temp.ops.command = azx_send_cmd;
bus_temp.ops.get_response = azx_get_response;
- bus_temp.ops.attach_pcm = azx_attach_pcm_stream;
#ifdef CONFIG_SND_HDA_POWER_SAVE
- bus_temp.power_save = &power_save;
bus_temp.ops.pm_notify = azx_power_notify;
#endif
@@ -1249,43 +1227,33 @@ static int __devinit azx_codec_create(struct azx *chip, const char *model,
if (chip->driver_type == AZX_DRIVER_NVIDIA)
chip->bus->needs_damn_long_delay = 1;
- codecs = 0;
+ codecs = audio_codecs = 0;
max_slots = azx_max_codecs[chip->driver_type];
if (!max_slots)
max_slots = AZX_MAX_CODECS;
-
- /* First try to probe all given codec slots */
- for (c = 0; c < max_slots; c++) {
- if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
- if (probe_codec(chip, c) < 0) {
- /* Some BIOSen give you wrong codec addresses
- * that don't exist
- */
- snd_printk(KERN_WARNING
- "hda_intel: Codec #%d probe error; "
- "disabling it...\n", c);
- chip->codec_mask &= ~(1 << c);
- /* More badly, accessing to a non-existing
- * codec often screws up the controller chip,
- * and distrubs the further communications.
- * Thus if an error occurs during probing,
- * better to reset the controller chip to
- * get back to the sanity state.
- */
- azx_stop_chip(chip);
- azx_init_chip(chip);
- }
- }
- }
-
- /* Then create codec instances */
- for (c = 0; c < max_slots; c++) {
+ def_slots = azx_default_codecs[chip->driver_type];
+ if (!def_slots)
+ def_slots = max_slots;
+ for (c = 0; c < def_slots; c++) {
if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
struct hda_codec *codec;
err = snd_hda_codec_new(chip->bus, c, &codec);
if (err < 0)
continue;
codecs++;
+ if (codec->afg)
+ audio_codecs++;
+ }
+ }
+ if (!audio_codecs) {
+ /* probe additional slots if no codec is found */
+ for (; c < max_slots; c++) {
+ if ((chip->codec_mask & (1 << c)) & codec_probe_mask) {
+ err = snd_hda_codec_new(chip->bus, c, NULL);
+ if (err < 0)
+ continue;
+ codecs++;
+ }
}
}
if (!codecs) {
@@ -1754,59 +1722,111 @@ static struct snd_pcm_ops azx_pcm_ops = {
static void azx_pcm_free(struct snd_pcm *pcm)
{
- struct azx_pcm *apcm = pcm->private_data;
- if (apcm) {
- apcm->chip->pcm[pcm->device] = NULL;
- kfree(apcm);
- }
+ kfree(pcm->private_data);
}
-static int
-azx_attach_pcm_stream(struct hda_bus *bus, struct hda_codec *codec,
- struct hda_pcm *cpcm)
+static int __devinit create_codec_pcm(struct azx *chip, struct hda_codec *codec,
+ struct hda_pcm *cpcm)
{
- struct azx *chip = bus->private_data;
+ int err;
struct snd_pcm *pcm;
struct azx_pcm *apcm;
- int pcm_dev = cpcm->device;
- int s, err;
- if (pcm_dev >= AZX_MAX_PCMS) {
- snd_printk(KERN_ERR SFX "Invalid PCM device number %d\n",
- pcm_dev);
+ /* if no substreams are defined for both playback and capture,
+ * it's just a placeholder. ignore it.
+ */
+ if (!cpcm->stream[0].substreams && !cpcm->stream[1].substreams)
+ return 0;
+
+ if (snd_BUG_ON(!cpcm->name))
return -EINVAL;
- }
- if (chip->pcm[pcm_dev]) {
- snd_printk(KERN_ERR SFX "PCM %d already exists\n", pcm_dev);
- return -EBUSY;
- }
- err = snd_pcm_new(chip->card, cpcm->name, pcm_dev,
- cpcm->stream[SNDRV_PCM_STREAM_PLAYBACK].substreams,
- cpcm->stream[SNDRV_PCM_STREAM_CAPTURE].substreams,
+
+ err = snd_pcm_new(chip->card, cpcm->name, cpcm->device,
+ cpcm->stream[0].substreams,
+ cpcm->stream[1].substreams,
&pcm);
if (err < 0)
return err;
strcpy(pcm->name, cpcm->name);
- apcm = kzalloc(sizeof(*apcm), GFP_KERNEL);
+ apcm = kmalloc(sizeof(*apcm), GFP_KERNEL);
if (apcm == NULL)
return -ENOMEM;
apcm->chip = chip;
apcm->codec = codec;
+ apcm->hinfo[0] = &cpcm->stream[0];
+ apcm->hinfo[1] = &cpcm->stream[1];
pcm->private_data = apcm;
pcm->private_free = azx_pcm_free;
- if (cpcm->pcm_type == HDA_PCM_TYPE_MODEM)
- pcm->dev_class = SNDRV_PCM_CLASS_MODEM;
- chip->pcm[pcm_dev] = pcm;
- cpcm->pcm = pcm;
- for (s = 0; s < 2; s++) {
- apcm->hinfo[s] = &cpcm->stream[s];
- if (cpcm->stream[s].substreams)
- snd_pcm_set_ops(pcm, s, &azx_pcm_ops);
- }
- /* buffer pre-allocation */
+ if (cpcm->stream[0].substreams)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &azx_pcm_ops);
+ if (cpcm->stream[1].substreams)
+ snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &azx_pcm_ops);
snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV_SG,
snd_dma_pci_data(chip->pci),
1024 * 64, 32 * 1024 * 1024);
+ chip->pcm[cpcm->device] = pcm;
+ return 0;
+}
+
+static int __devinit azx_pcm_create(struct azx *chip)
+{
+ static const char *dev_name[HDA_PCM_NTYPES] = {
+ "Audio", "SPDIF", "HDMI", "Modem"
+ };
+ /* starting device index for each PCM type */
+ static int dev_idx[HDA_PCM_NTYPES] = {
+ [HDA_PCM_TYPE_AUDIO] = 0,
+ [HDA_PCM_TYPE_SPDIF] = 1,
+ [HDA_PCM_TYPE_HDMI] = 3,
+ [HDA_PCM_TYPE_MODEM] = 6
+ };
+ /* normal audio device indices; not linear to keep compatibility */
+ static int audio_idx[4] = { 0, 2, 4, 5 };
+ struct hda_codec *codec;
+ int c, err;
+ int num_devs[HDA_PCM_NTYPES];
+
+ err = snd_hda_build_pcms(chip->bus);
+ if (err < 0)
+ return err;
+
+ /* create audio PCMs */
+ memset(num_devs, 0, sizeof(num_devs));
+ list_for_each_entry(codec, &chip->bus->codec_list, list) {
+ for (c = 0; c < codec->num_pcms; c++) {
+ struct hda_pcm *cpcm = &codec->pcm_info[c];
+ int type = cpcm->pcm_type;
+ switch (type) {
+ case HDA_PCM_TYPE_AUDIO:
+ if (num_devs[type] >= ARRAY_SIZE(audio_idx)) {
+ snd_printk(KERN_WARNING
+ "Too many audio devices\n");
+ continue;
+ }
+ cpcm->device = audio_idx[num_devs[type]];
+ break;
+ case HDA_PCM_TYPE_SPDIF:
+ case HDA_PCM_TYPE_HDMI:
+ case HDA_PCM_TYPE_MODEM:
+ if (num_devs[type]) {
+ snd_printk(KERN_WARNING
+ "%s already defined\n",
+ dev_name[type]);
+ continue;
+ }
+ cpcm->device = dev_idx[type];
+ break;
+ default:
+ snd_printk(KERN_WARNING
+ "Invalid PCM type %d\n", type);
+ continue;
+ }
+ num_devs[type]++;
+ err = create_codec_pcm(chip, codec, cpcm);
+ if (err < 0)
+ return err;
+ }
+ }
return 0;
}
@@ -1883,13 +1903,13 @@ static void azx_stop_chip(struct azx *chip)
#ifdef CONFIG_SND_HDA_POWER_SAVE
/* power-up/down the controller */
-static void azx_power_notify(struct hda_bus *bus)
+static void azx_power_notify(struct hda_codec *codec)
{
- struct azx *chip = bus->private_data;
+ struct azx *chip = codec->bus->private_data;
struct hda_codec *c;
int power_on = 0;
- list_for_each_entry(c, &bus->codec_list, list) {
+ list_for_each_entry(c, &codec->bus->codec_list, list) {
if (c->power_on) {
power_on = 1;
break;
@@ -1900,19 +1920,6 @@ static void azx_power_notify(struct hda_bus *bus)
else if (chip->running && power_save_controller)
azx_stop_chip(chip);
}
-
-static int snd_hda_codecs_inuse(struct hda_bus *bus)
-{
- struct hda_codec *codec;
-
- list_for_each_entry(codec, &bus->codec_list, list) {
- if (snd_hda_codec_needs_resume(codec))
- return 1;
- }
- return 0;
-}
-#else /* !CONFIG_SND_HDA_POWER_SAVE */
-#define snd_hda_codecs_inuse(bus) 1
#endif /* CONFIG_SND_HDA_POWER_SAVE */
#ifdef CONFIG_PM
@@ -1944,16 +1951,13 @@ static int azx_suspend(struct pci_dev *pci, pm_message_t state)
return 0;
}
-static int azx_resume_early(struct pci_dev *pci)
-{
- return pci_restore_state(pci);
-}
-
static int azx_resume(struct pci_dev *pci)
{
struct snd_card *card = pci_get_drvdata(pci);
struct azx *chip = card->private_data;
+ pci_set_power_state(pci, PCI_D0);
+ pci_restore_state(pci);
if (pci_enable_device(pci) < 0) {
printk(KERN_ERR "hda-intel: pci_enable_device failed, "
"disabling device\n");
@@ -2091,10 +2095,6 @@ static struct snd_pci_quirk probe_mask_list[] __devinitdata = {
SND_PCI_QUIRK(0x1014, 0x05b7, "Thinkpad Z60", 0x01),
SND_PCI_QUIRK(0x17aa, 0x2010, "Thinkpad X/T/R60", 0x01),
SND_PCI_QUIRK(0x17aa, 0x20ac, "Thinkpad X/T/R61", 0x01),
- /* broken BIOS */
- SND_PCI_QUIRK(0x1028, 0x20ac, "Dell Studio Desktop", 0x01),
- /* including bogus ALC268 in slot#2 that conflicts with ALC888 */
- SND_PCI_QUIRK(0x17c0, 0x4085, "Medion MD96630", 0x01),
{}
};
@@ -2229,7 +2229,6 @@ static int __devinit azx_create(struct snd_card *card, struct pci_dev *pci,
chip->playback_streams = ATIHDMI_NUM_PLAYBACK;
chip->capture_streams = ATIHDMI_NUM_CAPTURE;
break;
- case AZX_DRIVER_GENERIC:
default:
chip->playback_streams = ICH6_NUM_PLAYBACK;
chip->capture_streams = ICH6_NUM_CAPTURE;
@@ -2339,30 +2338,40 @@ static int __devinit azx_probe(struct pci_dev *pci,
}
err = azx_create(card, pci, dev, pci_id->driver_data, &chip);
- if (err < 0)
- goto out_free;
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
card->private_data = chip;
/* create codec instances */
err = azx_codec_create(chip, model[dev], probe_mask[dev]);
- if (err < 0)
- goto out_free;
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
/* create PCM streams */
- err = snd_hda_build_pcms(chip->bus);
- if (err < 0)
- goto out_free;
+ err = azx_pcm_create(chip);
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
/* create mixer controls */
err = azx_mixer_create(chip);
- if (err < 0)
- goto out_free;
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
snd_card_set_dev(card, &pci->dev);
err = snd_card_register(card);
- if (err < 0)
- goto out_free;
+ if (err < 0) {
+ snd_card_free(card);
+ return err;
+ }
pci_set_drvdata(pci, card);
chip->running = 1;
@@ -2371,9 +2380,6 @@ static int __devinit azx_probe(struct pci_dev *pci,
dev++;
return err;
-out_free:
- snd_card_free(card);
- return err;
}
static void __devexit azx_remove(struct pci_dev *pci)
@@ -2447,11 +2453,6 @@ static struct pci_device_id azx_ids[] = {
{ PCI_DEVICE(0x10de, 0x0bd7), .driver_data = AZX_DRIVER_NVIDIA },
/* Teradici */
{ PCI_DEVICE(0x6549, 0x1200), .driver_data = AZX_DRIVER_TERA },
- /* AMD Generic, PCI class code and Vendor ID for HD Audio */
- { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID),
- .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8,
- .class_mask = 0xffffff,
- .driver_data = AZX_DRIVER_GENERIC },
{ 0, }
};
MODULE_DEVICE_TABLE(pci, azx_ids);
@@ -2464,7 +2465,6 @@ static struct pci_driver driver = {
.remove = __devexit_p(azx_remove),
#ifdef CONFIG_PM
.suspend = azx_suspend,
- .resume_early = azx_resume_early,
.resume = azx_resume,
#endif
};
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index 6f2fe0f9fdd8..7957fefda730 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -96,8 +96,6 @@ struct snd_kcontrol *snd_hda_find_mixer_ctl(struct hda_codec *codec,
const char *name);
int snd_hda_add_vmaster(struct hda_codec *codec, char *name,
unsigned int *tlv, const char **slaves);
-void snd_hda_codec_reset(struct hda_codec *codec);
-int snd_hda_codec_configure(struct hda_codec *codec);
/* amp value bits */
#define HDA_AMP_MUTE 0x80
@@ -284,12 +282,6 @@ int snd_hda_codec_proc_new(struct hda_codec *codec);
static inline int snd_hda_codec_proc_new(struct hda_codec *codec) { return 0; }
#endif
-#define SND_PRINT_RATES_ADVISED_BUFSIZE 80
-void snd_print_pcm_rates(int pcm, char *buf, int buflen);
-
-#define SND_PRINT_BITS_ADVISED_BUFSIZE 16
-void snd_print_pcm_bits(int pcm, char *buf, int buflen);
-
/*
* Misc
*/
@@ -372,17 +364,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec,
/* amp values */
#define AMP_IN_MUTE(idx) (0x7080 | ((idx)<<8))
#define AMP_IN_UNMUTE(idx) (0x7000 | ((idx)<<8))
-#define AMP_OUT_MUTE 0xb080
-#define AMP_OUT_UNMUTE 0xb000
-#define AMP_OUT_ZERO 0xb000
+#define AMP_OUT_MUTE 0xb080
+#define AMP_OUT_UNMUTE 0xb000
+#define AMP_OUT_ZERO 0xb000
/* pinctl values */
#define PIN_IN (AC_PINCTL_IN_EN)
-#define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ)
+#define PIN_VREFHIZ (AC_PINCTL_IN_EN | AC_PINCTL_VREF_HIZ)
#define PIN_VREF50 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_50)
-#define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD)
+#define PIN_VREFGRD (AC_PINCTL_IN_EN | AC_PINCTL_VREF_GRD)
#define PIN_VREF80 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_80)
-#define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100)
-#define PIN_OUT (AC_PINCTL_OUT_EN)
+#define PIN_VREF100 (AC_PINCTL_IN_EN | AC_PINCTL_VREF_100)
+#define PIN_OUT (AC_PINCTL_OUT_EN)
#define PIN_HP (AC_PINCTL_OUT_EN | AC_PINCTL_HP_EN)
#define PIN_HP_AMP (AC_PINCTL_HP_EN)
@@ -401,26 +393,10 @@ u32 query_amp_caps(struct hda_codec *codec, hda_nid_t nid, int direction);
int snd_hda_override_amp_caps(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps);
-int snd_hda_ctl_add(struct hda_codec *codec, struct snd_kcontrol *kctl);
-void snd_hda_ctls_clear(struct hda_codec *codec);
-
/*
* hwdep interface
*/
-#ifdef CONFIG_SND_HDA_HWDEP
int snd_hda_create_hwdep(struct hda_codec *codec);
-#else
-static inline int snd_hda_create_hwdep(struct hda_codec *codec) { return 0; }
-#endif
-
-#ifdef CONFIG_SND_HDA_RECONFIG
-int snd_hda_hwdep_add_sysfs(struct hda_codec *codec);
-#else
-static inline int snd_hda_hwdep_add_sysfs(struct hda_codec *codec)
-{
- return 0;
-}
-#endif
/*
* power-management
@@ -454,66 +430,4 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec,
#define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1)
#define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf)
-/*
- * CEA Short Audio Descriptor data
- */
-struct cea_sad {
- int channels;
- int format; /* (format == 0) indicates invalid SAD */
- int rates;
- int sample_bits; /* for LPCM */
- int max_bitrate; /* for AC3...ATRAC */
- int profile; /* for WMAPRO */
-};
-
-#define ELD_FIXED_BYTES 20
-#define ELD_MAX_MNL 16
-#define ELD_MAX_SAD 16
-
-/*
- * ELD: EDID Like Data
- */
-struct hdmi_eld {
- int eld_size;
- int baseline_len;
- int eld_ver; /* (eld_ver == 0) indicates invalid ELD */
- int cea_edid_ver;
- char monitor_name[ELD_MAX_MNL + 1];
- int manufacture_id;
- int product_id;
- u64 port_id;
- int support_hdcp;
- int support_ai;
- int conn_type;
- int aud_synch_delay;
- int spk_alloc;
- int sad_count;
- struct cea_sad sad[ELD_MAX_SAD];
-#ifdef CONFIG_PROC_FS
- struct snd_info_entry *proc_entry;
-#endif
-};
-
-int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid);
-int snd_hdmi_get_eld(struct hdmi_eld *, struct hda_codec *, hda_nid_t);
-void snd_hdmi_show_eld(struct hdmi_eld *eld);
-
-#ifdef CONFIG_PROC_FS
-int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld);
-void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld);
-#else
-static inline int snd_hda_eld_proc_new(struct hda_codec *codec,
- struct hdmi_eld *eld)
-{
- return 0;
-}
-static inline void snd_hda_eld_proc_free(struct hda_codec *codec,
- struct hdmi_eld *eld)
-{
-}
-#endif
-
-#define SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE 80
-void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen);
-
#endif /* __SOUND_HDA_LOCAL_H */
diff --git a/sound/pci/hda/hda_patch.h b/sound/pci/hda/hda_patch.h
new file mode 100644
index 000000000000..dfbcfa88da44
--- /dev/null
+++ b/sound/pci/hda/hda_patch.h
@@ -0,0 +1,22 @@
+/*
+ * HDA Patches - included by hda_codec.c
+ */
+
+/* Realtek codecs */
+extern struct hda_codec_preset snd_hda_preset_realtek[];
+/* C-Media codecs */
+extern struct hda_codec_preset snd_hda_preset_cmedia[];
+/* Analog Devices codecs */
+extern struct hda_codec_preset snd_hda_preset_analog[];
+/* SigmaTel codecs */
+extern struct hda_codec_preset snd_hda_preset_sigmatel[];
+/* SiLabs 3054/3055 modem codecs */
+extern struct hda_codec_preset snd_hda_preset_si3054[];
+/* ATI HDMI codecs */
+extern struct hda_codec_preset snd_hda_preset_atihdmi[];
+/* Conexant audio codec */
+extern struct hda_codec_preset snd_hda_preset_conexant[];
+/* VIA codecs */
+extern struct hda_codec_preset snd_hda_preset_via[];
+/* NVIDIA HDMI codecs */
+extern struct hda_codec_preset snd_hda_preset_nvhdmi[];
diff --git a/sound/pci/hda/hda_proc.c b/sound/pci/hda/hda_proc.c
index 7ca66d654148..c39af986bff1 100644
--- a/sound/pci/hda/hda_proc.c
+++ b/sound/pci/hda/hda_proc.c
@@ -91,21 +91,31 @@ static void print_amp_vals(struct snd_info_buffer *buffer,
static void print_pcm_rates(struct snd_info_buffer *buffer, unsigned int pcm)
{
- char buf[SND_PRINT_RATES_ADVISED_BUFSIZE];
+ static unsigned int rates[] = {
+ 8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
+ 96000, 176400, 192000, 384000
+ };
+ int i;
pcm &= AC_SUPPCM_RATES;
snd_iprintf(buffer, " rates [0x%x]:", pcm);
- snd_print_pcm_rates(pcm, buf, sizeof(buf));
- snd_iprintf(buffer, "%s\n", buf);
+ for (i = 0; i < ARRAY_SIZE(rates); i++)
+ if (pcm & (1 << i))
+ snd_iprintf(buffer, " %d", rates[i]);
+ snd_iprintf(buffer, "\n");
}
static void print_pcm_bits(struct snd_info_buffer *buffer, unsigned int pcm)
{
- char buf[SND_PRINT_BITS_ADVISED_BUFSIZE];
+ static unsigned int bits[] = { 8, 16, 20, 24, 32 };
+ int i;
- snd_iprintf(buffer, " bits [0x%x]:", (pcm >> 16) & 0xff);
- snd_print_pcm_bits(pcm, buf, sizeof(buf));
- snd_iprintf(buffer, "%s\n", buf);
+ pcm = (pcm >> 16) & 0xff;
+ snd_iprintf(buffer, " bits [0x%x]:", pcm);
+ for (i = 0; i < ARRAY_SIZE(bits); i++)
+ if (pcm & (1 << i))
+ snd_iprintf(buffer, " %d", bits[i]);
+ snd_iprintf(buffer, "\n");
}
static void print_pcm_formats(struct snd_info_buffer *buffer,
@@ -135,6 +145,32 @@ static void print_pcm_caps(struct snd_info_buffer *buffer,
print_pcm_formats(buffer, stream);
}
+static const char *get_jack_location(u32 cfg)
+{
+ static char *bases[7] = {
+ "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom",
+ };
+ static unsigned char specials_idx[] = {
+ 0x07, 0x08,
+ 0x17, 0x18, 0x19,
+ 0x37, 0x38
+ };
+ static char *specials[] = {
+ "Rear Panel", "Drive Bar",
+ "Riser", "HDMI", "ATAPI",
+ "Mobile-In", "Mobile-Out"
+ };
+ int i;
+ cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT;
+ if ((cfg & 0x0f) < 7)
+ return bases[cfg & 0x0f];
+ for (i = 0; i < ARRAY_SIZE(specials_idx); i++) {
+ if (cfg == specials_idx[i])
+ return specials[i];
+ }
+ return "UNKNOWN";
+}
+
static const char *get_jack_connection(u32 cfg)
{
static char *names[16] = {
@@ -170,6 +206,13 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
int *supports_vref)
{
static char *jack_conns[4] = { "Jack", "N/A", "Fixed", "Both" };
+ static char *jack_types[16] = {
+ "Line Out", "Speaker", "HP Out", "CD",
+ "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand",
+ "Line In", "Aux", "Mic", "Telephony",
+ "SPDIF In", "Digitial In", "Reserved", "Other"
+ };
+ static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" };
unsigned int caps, val;
caps = snd_hda_param_read(codec, nid, AC_PAR_PIN_CAP);
@@ -231,9 +274,9 @@ static void print_pin_caps(struct snd_info_buffer *buffer,
caps = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
snd_iprintf(buffer, " Pin Default 0x%08x: [%s] %s at %s %s\n", caps,
jack_conns[(caps & AC_DEFCFG_PORT_CONN) >> AC_DEFCFG_PORT_CONN_SHIFT],
- snd_hda_get_jack_type(caps),
- snd_hda_get_jack_connectivity(caps),
- snd_hda_get_jack_location(caps));
+ jack_types[(caps & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT],
+ jack_locations[(caps >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3],
+ get_jack_location(caps));
snd_iprintf(buffer, " Conn = %s, Color = %s\n",
get_jack_connection(caps),
get_jack_color(caps));
@@ -414,6 +457,17 @@ static void print_conn_list(struct snd_info_buffer *buffer,
}
}
+static void print_realtek_coef(struct snd_info_buffer *buffer,
+ struct hda_codec *codec, hda_nid_t nid)
+{
+ int coeff = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PROC_COEF, 0);
+ snd_iprintf(buffer, " Processing Coefficient: 0x%02x\n", coeff);
+ coeff = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_COEF_INDEX, 0);
+ snd_iprintf(buffer, " Coefficient Index: 0x%02x\n", coeff);
+}
+
static void print_gpio(struct snd_info_buffer *buffer,
struct hda_codec *codec, hda_nid_t nid)
{
@@ -446,13 +500,12 @@ static void print_gpio(struct snd_info_buffer *buffer,
for (i = 0; i < max; ++i)
snd_iprintf(buffer,
" IO[%d]: enable=%d, dir=%d, wake=%d, "
- "sticky=%d, data=%d, unsol=%d\n", i,
+ "sticky=%d, data=%d\n", i,
(enable & (1<<i)) ? 1 : 0,
(direction & (1<<i)) ? 1 : 0,
(wake & (1<<i)) ? 1 : 0,
(sticky & (1<<i)) ? 1 : 0,
- (data & (1<<i)) ? 1 : 0,
- (unsol & (1<<i)) ? 1 : 0);
+ (data & (1<<i)) ? 1 : 0);
/* FIXME: add GPO and GPI pin information */
}
@@ -460,11 +513,12 @@ static void print_codec_info(struct snd_info_entry *entry,
struct snd_info_buffer *buffer)
{
struct hda_codec *codec = entry->private_data;
+ char buf[32];
hda_nid_t nid;
int i, nodes;
- snd_iprintf(buffer, "Codec: %s\n",
- codec->name ? codec->name : "Not Set");
+ snd_hda_get_codec_name(codec, buf, sizeof(buf));
+ snd_iprintf(buffer, "Codec: %s\n", buf);
snd_iprintf(buffer, "Address: %d\n", codec->addr);
snd_iprintf(buffer, "Vendor Id: 0x%x\n", codec->vendor_id);
snd_iprintf(buffer, "Subsystem Id: 0x%x\n", codec->subsystem_id);
@@ -493,8 +547,6 @@ static void print_codec_info(struct snd_info_entry *entry,
}
print_gpio(buffer, codec, codec->afg);
- if (codec->proc_widget_hook)
- codec->proc_widget_hook(buffer, codec, codec->afg);
for (i = 0; i < nodes; i++, nid++) {
unsigned int wid_caps =
@@ -597,8 +649,9 @@ static void print_codec_info(struct snd_info_entry *entry,
if (wid_caps & AC_WCAP_PROC_WID)
print_proc_caps(buffer, codec, nid);
- if (codec->proc_widget_hook)
- codec->proc_widget_hook(buffer, codec, nid);
+ /* NID 0x20 == Realtek Define Registers */
+ if (codec->vendor_id == 0x10ec && nid == 0x20)
+ print_realtek_coef(buffer, codec, nid);
}
snd_hda_power_down(codec);
}
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index c1918a1a6df9..686c77491dea 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -27,6 +27,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_patch.h"
struct ad198x_spec {
struct snd_kcontrol_new *mixers[5];
@@ -66,7 +67,8 @@ struct ad198x_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- struct snd_array kctls;
+ unsigned int num_kctl_alloc, num_kctl_used;
+ struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -152,8 +154,6 @@ static const char *ad_slave_sws[] = {
NULL
};
-static void ad198x_free_kctls(struct hda_codec *codec);
-
static int ad198x_build_controls(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
@@ -202,7 +202,6 @@ static int ad198x_build_controls(struct hda_codec *codec)
return err;
}
- ad198x_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -376,27 +375,16 @@ static int ad198x_build_pcms(struct hda_codec *codec)
return 0;
}
-static void ad198x_free_kctls(struct hda_codec *codec)
-{
- struct ad198x_spec *spec = codec->spec;
-
- if (spec->kctls.list) {
- struct snd_kcontrol_new *kctl = spec->kctls.list;
- int i;
- for (i = 0; i < spec->kctls.used; i++)
- kfree(kctl[i].name);
- }
- snd_array_free(&spec->kctls);
-}
-
static void ad198x_free(struct hda_codec *codec)
{
struct ad198x_spec *spec = codec->spec;
+ unsigned int i;
- if (!spec)
- return;
-
- ad198x_free_kctls(codec);
+ if (spec->kctl_alloc) {
+ for (i = 0; i < spec->num_kctl_used; i++)
+ kfree(spec->kctl_alloc[i].name);
+ kfree(spec->kctl_alloc);
+ }
kfree(codec->spec);
}
@@ -641,36 +629,6 @@ static struct snd_kcontrol_new ad1986a_laptop_eapd_mixers[] = {
HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x17, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x17, 0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Capture Volume", 0x12, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Capture Switch", 0x12, 0x0, HDA_OUTPUT),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Capture Source",
- .info = ad198x_mux_enum_info,
- .get = ad198x_mux_enum_get,
- .put = ad198x_mux_enum_put,
- },
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "External Amplifier",
- .info = ad198x_eapd_info,
- .get = ad198x_eapd_get,
- .put = ad198x_eapd_put,
- .private_value = 0x1b | (1 << 8), /* port-D, inversed */
- },
- { } /* end */
-};
-
-static struct snd_kcontrol_new ad1986a_samsung_mixers[] = {
- HDA_BIND_VOL("Master Playback Volume", &ad1986a_laptop_master_vol),
- HDA_BIND_SW("Master Playback Switch", &ad1986a_laptop_master_sw),
- HDA_CODEC_VOLUME("PCM Playback Volume", 0x03, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("PCM Playback Switch", 0x03, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x13, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x13, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x0f, 0x0, HDA_OUTPUT),
@@ -959,7 +917,6 @@ enum {
AD1986A_LAPTOP_EAPD,
AD1986A_LAPTOP_AUTOMUTE,
AD1986A_ULTRA,
- AD1986A_SAMSUNG,
AD1986A_MODELS
};
@@ -970,7 +927,6 @@ static const char *ad1986a_models[AD1986A_MODELS] = {
[AD1986A_LAPTOP_EAPD] = "laptop-eapd",
[AD1986A_LAPTOP_AUTOMUTE] = "laptop-automute",
[AD1986A_ULTRA] = "ultra",
- [AD1986A_SAMSUNG] = "samsung",
};
static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
@@ -993,9 +949,9 @@ static struct snd_pci_quirk ad1986a_cfg_tbl[] = {
SND_PCI_QUIRK(0x1179, 0xff40, "Toshiba", AD1986A_LAPTOP_EAPD),
SND_PCI_QUIRK(0x144d, 0xb03c, "Samsung R55", AD1986A_3STACK),
SND_PCI_QUIRK(0x144d, 0xc01e, "FSC V2060", AD1986A_LAPTOP),
- SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_SAMSUNG),
- SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_SAMSUNG),
- SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_SAMSUNG),
+ SND_PCI_QUIRK(0x144d, 0xc023, "Samsung X60", AD1986A_LAPTOP_EAPD),
+ SND_PCI_QUIRK(0x144d, 0xc024, "Samsung R65", AD1986A_LAPTOP_EAPD),
+ SND_PCI_QUIRK(0x144d, 0xc026, "Samsung X11", AD1986A_LAPTOP_EAPD),
SND_PCI_QUIRK(0x144d, 0xc027, "Samsung Q1", AD1986A_ULTRA),
SND_PCI_QUIRK(0x144d, 0xc504, "Samsung Q35", AD1986A_3STACK),
SND_PCI_QUIRK(0x17aa, 0x1011, "Lenovo M55", AD1986A_LAPTOP),
@@ -1077,17 +1033,6 @@ static int patch_ad1986a(struct hda_codec *codec)
break;
case AD1986A_LAPTOP_EAPD:
spec->mixers[0] = ad1986a_laptop_eapd_mixers;
- spec->num_init_verbs = 2;
- spec->init_verbs[1] = ad1986a_eapd_init_verbs;
- spec->multiout.max_channels = 2;
- spec->multiout.num_dacs = 1;
- spec->multiout.dac_nids = ad1986a_laptop_dac_nids;
- if (!is_jack_available(codec, 0x25))
- spec->multiout.dig_out_nid = 0;
- spec->input_mux = &ad1986a_laptop_eapd_capture_source;
- break;
- case AD1986A_SAMSUNG:
- spec->mixers[0] = ad1986a_samsung_mixers;
spec->num_init_verbs = 3;
spec->init_verbs[1] = ad1986a_eapd_init_verbs;
spec->init_verbs[2] = ad1986a_automic_verbs;
@@ -2507,6 +2452,9 @@ static struct hda_amp_list ad1988_loopbacks[] = {
* Automatic parse of I/O pins from the BIOS configuration
*/
+#define NUM_CONTROL_ALLOC 32
+#define NUM_VERB_ALLOC 32
+
enum {
AD_CTL_WIDGET_VOL,
AD_CTL_WIDGET_MUTE,
@@ -2524,15 +2472,27 @@ static int add_control(struct ad198x_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- snd_array_init(&spec->kctls, sizeof(*knew), 32);
- knew = snd_array_new(&spec->kctls);
- if (!knew)
- return -ENOMEM;
+ if (spec->num_kctl_used >= spec->num_kctl_alloc) {
+ int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
+
+ knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
+ if (! knew)
+ return -ENOMEM;
+ if (spec->kctl_alloc) {
+ memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
+ kfree(spec->kctl_alloc);
+ }
+ spec->kctl_alloc = knew;
+ spec->num_kctl_alloc = num;
+ }
+
+ knew = &spec->kctl_alloc[spec->num_kctl_used];
*knew = ad1988_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL);
if (! knew->name)
return -ENOMEM;
knew->private_value = val;
+ spec->num_kctl_used++;
return 0;
}
@@ -2886,8 +2846,8 @@ static int ad1988_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = AD1988_SPDIF_IN;
- if (spec->kctls.list)
- spec->mixers[spec->num_mixers++] = spec->kctls.list;
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->init_verbs[spec->num_init_verbs++] = ad1988_6stack_init_verbs;
@@ -4307,7 +4267,7 @@ static int patch_ad1882(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_analog[] = {
+struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d4184a, .name = "AD1884A", .patch = patch_ad1884a },
{ .id = 0x11d41882, .name = "AD1882", .patch = patch_ad1882 },
{ .id = 0x11d41883, .name = "AD1883", .patch = patch_ad1884a },
@@ -4325,26 +4285,3 @@ static struct hda_codec_preset snd_hda_preset_analog[] = {
{ .id = 0x11d4989b, .name = "AD1989B", .patch = patch_ad1988 },
{} /* terminator */
};
-
-MODULE_ALIAS("snd-hda-codec-id:11d4*");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Analog Devices HD-audio codec");
-
-static struct hda_codec_preset_list analog_list = {
- .preset = snd_hda_preset_analog,
- .owner = THIS_MODULE,
-};
-
-static int __init patch_analog_init(void)
-{
- return snd_hda_add_codec_preset(&analog_list);
-}
-
-static void __exit patch_analog_exit(void)
-{
- snd_hda_delete_codec_preset(&analog_list);
-}
-
-module_init(patch_analog_init)
-module_exit(patch_analog_exit)
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c
index 5887b827bb32..ba61575983fd 100644
--- a/sound/pci/hda/patch_atihdmi.c
+++ b/sound/pci/hda/patch_atihdmi.c
@@ -27,6 +27,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_patch.h"
struct atihdmi_spec {
struct hda_multi_out multiout;
@@ -186,40 +187,13 @@ static int patch_atihdmi(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_atihdmi[] = {
+struct hda_codec_preset snd_hda_preset_atihdmi[] = {
{ .id = 0x1002793c, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
{ .id = 0x10027919, .name = "ATI RS600 HDMI", .patch = patch_atihdmi },
{ .id = 0x1002791a, .name = "ATI RS690/780 HDMI", .patch = patch_atihdmi },
{ .id = 0x1002aa01, .name = "ATI R6xx HDMI", .patch = patch_atihdmi },
{ .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_atihdmi },
+ { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_atihdmi },
{ .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi },
{} /* terminator */
};
-
-MODULE_ALIAS("snd-hda-codec-id:1002793c");
-MODULE_ALIAS("snd-hda-codec-id:10027919");
-MODULE_ALIAS("snd-hda-codec-id:1002791a");
-MODULE_ALIAS("snd-hda-codec-id:1002aa01");
-MODULE_ALIAS("snd-hda-codec-id:10951390");
-MODULE_ALIAS("snd-hda-codec-id:17e80047");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("ATI HDMI HD-audio codec");
-
-static struct hda_codec_preset_list atihdmi_list = {
- .preset = snd_hda_preset_atihdmi,
- .owner = THIS_MODULE,
-};
-
-static int __init patch_atihdmi_init(void)
-{
- return snd_hda_add_codec_preset(&atihdmi_list);
-}
-
-static void __exit patch_atihdmi_exit(void)
-{
- snd_hda_delete_codec_preset(&atihdmi_list);
-}
-
-module_init(patch_atihdmi_init)
-module_exit(patch_atihdmi_exit)
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index f3ebe837f2d5..6ef57fbfb6eb 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -28,6 +28,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_patch.h"
#define NUM_PINS 11
@@ -735,32 +736,8 @@ static int patch_cmi9880(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_cmedia[] = {
+struct hda_codec_preset snd_hda_preset_cmedia[] = {
{ .id = 0x13f69880, .name = "CMI9880", .patch = patch_cmi9880 },
{ .id = 0x434d4980, .name = "CMI9880", .patch = patch_cmi9880 },
{} /* terminator */
};
-
-MODULE_ALIAS("snd-hda-codec-id:13f69880");
-MODULE_ALIAS("snd-hda-codec-id:434d4980");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("C-Media HD-audio codec");
-
-static struct hda_codec_preset_list cmedia_list = {
- .preset = snd_hda_preset_cmedia,
- .owner = THIS_MODULE,
-};
-
-static int __init patch_cmedia_init(void)
-{
- return snd_hda_add_codec_preset(&cmedia_list);
-}
-
-static void __exit patch_cmedia_exit(void)
-{
- snd_hda_delete_codec_preset(&cmedia_list);
-}
-
-module_init(patch_cmedia_init)
-module_exit(patch_cmedia_exit)
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index b20e1cede00b..7c1eb23f0cec 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -27,6 +27,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_patch.h"
#define CXT_PIN_DIR_IN 0x00
#define CXT_PIN_DIR_OUT 0x01
@@ -85,6 +86,8 @@ struct conexant_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
+ unsigned int num_kctl_alloc, num_kctl_used;
+ struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -341,6 +344,15 @@ static int conexant_init(struct hda_codec *codec)
static void conexant_free(struct hda_codec *codec)
{
+ struct conexant_spec *spec = codec->spec;
+ unsigned int i;
+
+ if (spec->kctl_alloc) {
+ for (i = 0; i < spec->num_kctl_used; i++)
+ kfree(spec->kctl_alloc[i].name);
+ kfree(spec->kctl_alloc);
+ }
+
kfree(codec->spec);
}
@@ -1770,7 +1782,7 @@ static int patch_cxt5051(struct hda_codec *codec)
/*
*/
-static struct hda_codec_preset snd_hda_preset_conexant[] = {
+struct hda_codec_preset snd_hda_preset_conexant[] = {
{ .id = 0x14f15045, .name = "CX20549 (Venice)",
.patch = patch_cxt5045 },
{ .id = 0x14f15047, .name = "CX20551 (Waikiki)",
@@ -1779,28 +1791,3 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = {
.patch = patch_cxt5051 },
{} /* terminator */
};
-
-MODULE_ALIAS("snd-hda-codec-id:14f15045");
-MODULE_ALIAS("snd-hda-codec-id:14f15047");
-MODULE_ALIAS("snd-hda-codec-id:14f15051");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Conexant HD-audio codec");
-
-static struct hda_codec_preset_list conexant_list = {
- .preset = snd_hda_preset_conexant,
- .owner = THIS_MODULE,
-};
-
-static int __init patch_conexant_init(void)
-{
- return snd_hda_add_codec_preset(&conexant_list);
-}
-
-static void __exit patch_conexant_exit(void)
-{
- snd_hda_delete_codec_preset(&conexant_list);
-}
-
-module_init(patch_conexant_init)
-module_exit(patch_conexant_exit)
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c
deleted file mode 100644
index 290da562f29b..000000000000
--- a/sound/pci/hda/patch_intelhdmi.c
+++ /dev/null
@@ -1,711 +0,0 @@
-/*
- *
- * patch_intelhdmi.c - Patch for Intel HDMI codecs
- *
- * Copyright(c) 2008 Intel Corporation. All rights reserved.
- *
- * Authors:
- * Jiang Zhe <zhe.jiang@intel.com>
- * Wu Fengguang <wfg@linux.intel.com>
- *
- * Maintained by:
- * Wu Fengguang <wfg@linux.intel.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the Free
- * Software Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <sound/core.h>
-#include "hda_codec.h"
-#include "hda_local.h"
-
-#define CVT_NID 0x02 /* audio converter */
-#define PIN_NID 0x03 /* HDMI output pin */
-
-#define INTEL_HDMI_EVENT_TAG 0x08
-
-struct intel_hdmi_spec {
- struct hda_multi_out multiout;
- struct hda_pcm pcm_rec;
- struct hdmi_eld sink_eld;
-};
-
-static struct hda_verb pinout_enable_verb[] = {
- {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {} /* terminator */
-};
-
-static struct hda_verb pinout_disable_verb[] = {
- {PIN_NID, AC_VERB_SET_PIN_WIDGET_CONTROL, 0x00},
- {}
-};
-
-static struct hda_verb unsolicited_response_verb[] = {
- {PIN_NID, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN |
- INTEL_HDMI_EVENT_TAG},
- {}
-};
-
-static struct hda_verb def_chan_map[] = {
- {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x00},
- {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x11},
- {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x22},
- {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x33},
- {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x44},
- {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x55},
- {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x66},
- {CVT_NID, AC_VERB_SET_HDMI_CHAN_SLOT, 0x77},
- {}
-};
-
-
-struct hdmi_audio_infoframe {
- u8 type; /* 0x84 */
- u8 ver; /* 0x01 */
- u8 len; /* 0x0a */
-
- u8 checksum; /* PB0 */
- u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */
- u8 SS01_SF24;
- u8 CXT04;
- u8 CA;
- u8 LFEPBL01_LSV36_DM_INH7;
- u8 reserved[5]; /* PB6 - PB10 */
-};
-
-/*
- * CEA speaker placement:
- *
- * FLH FCH FRH
- * FLW FL FLC FC FRC FR FRW
- *
- * LFE
- * TC
- *
- * RL RLC RC RRC RR
- *
- * The Left/Right Surround channel _notions_ LS/RS in SMPTE 320M corresponds to
- * CEA RL/RR; The SMPTE channel _assignment_ C/LFE is swapped to CEA LFE/FC.
- */
-enum cea_speaker_placement {
- FL = (1 << 0), /* Front Left */
- FC = (1 << 1), /* Front Center */
- FR = (1 << 2), /* Front Right */
- FLC = (1 << 3), /* Front Left Center */
- FRC = (1 << 4), /* Front Right Center */
- RL = (1 << 5), /* Rear Left */
- RC = (1 << 6), /* Rear Center */
- RR = (1 << 7), /* Rear Right */
- RLC = (1 << 8), /* Rear Left Center */
- RRC = (1 << 9), /* Rear Right Center */
- LFE = (1 << 10), /* Low Frequency Effect */
- FLW = (1 << 11), /* Front Left Wide */
- FRW = (1 << 12), /* Front Right Wide */
- FLH = (1 << 13), /* Front Left High */
- FCH = (1 << 14), /* Front Center High */
- FRH = (1 << 15), /* Front Right High */
- TC = (1 << 16), /* Top Center */
-};
-
-/*
- * ELD SA bits in the CEA Speaker Allocation data block
- */
-static int eld_speaker_allocation_bits[] = {
- [0] = FL | FR,
- [1] = LFE,
- [2] = FC,
- [3] = RL | RR,
- [4] = RC,
- [5] = FLC | FRC,
- [6] = RLC | RRC,
- /* the following are not defined in ELD yet */
- [7] = FLW | FRW,
- [8] = FLH | FRH,
- [9] = TC,
- [10] = FCH,
-};
-
-struct cea_channel_speaker_allocation {
- int ca_index;
- int speakers[8];
-
- /* derived values, just for convenience */
- int channels;
- int spk_mask;
-};
-
-/*
- * This is an ordered list!
- *
- * The preceding ones have better chances to be selected by
- * hdmi_setup_channel_allocation().
- */
-static struct cea_channel_speaker_allocation channel_allocations[] = {
-/* channel: 8 7 6 5 4 3 2 1 */
-{ .ca_index = 0x00, .speakers = { 0, 0, 0, 0, 0, 0, FR, FL } },
- /* 2.1 */
-{ .ca_index = 0x01, .speakers = { 0, 0, 0, 0, 0, LFE, FR, FL } },
- /* Dolby Surround */
-{ .ca_index = 0x02, .speakers = { 0, 0, 0, 0, FC, 0, FR, FL } },
-{ .ca_index = 0x03, .speakers = { 0, 0, 0, 0, FC, LFE, FR, FL } },
-{ .ca_index = 0x04, .speakers = { 0, 0, 0, RC, 0, 0, FR, FL } },
-{ .ca_index = 0x05, .speakers = { 0, 0, 0, RC, 0, LFE, FR, FL } },
-{ .ca_index = 0x06, .speakers = { 0, 0, 0, RC, FC, 0, FR, FL } },
-{ .ca_index = 0x07, .speakers = { 0, 0, 0, RC, FC, LFE, FR, FL } },
-{ .ca_index = 0x08, .speakers = { 0, 0, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x09, .speakers = { 0, 0, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x0a, .speakers = { 0, 0, RR, RL, FC, 0, FR, FL } },
- /* 5.1 */
-{ .ca_index = 0x0b, .speakers = { 0, 0, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x0c, .speakers = { 0, RC, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x0d, .speakers = { 0, RC, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x0e, .speakers = { 0, RC, RR, RL, FC, 0, FR, FL } },
- /* 6.1 */
-{ .ca_index = 0x0f, .speakers = { 0, RC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x10, .speakers = { RRC, RLC, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x11, .speakers = { RRC, RLC, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x12, .speakers = { RRC, RLC, RR, RL, FC, 0, FR, FL } },
- /* 7.1 */
-{ .ca_index = 0x13, .speakers = { RRC, RLC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x14, .speakers = { FRC, FLC, 0, 0, 0, 0, FR, FL } },
-{ .ca_index = 0x15, .speakers = { FRC, FLC, 0, 0, 0, LFE, FR, FL } },
-{ .ca_index = 0x16, .speakers = { FRC, FLC, 0, 0, FC, 0, FR, FL } },
-{ .ca_index = 0x17, .speakers = { FRC, FLC, 0, 0, FC, LFE, FR, FL } },
-{ .ca_index = 0x18, .speakers = { FRC, FLC, 0, RC, 0, 0, FR, FL } },
-{ .ca_index = 0x19, .speakers = { FRC, FLC, 0, RC, 0, LFE, FR, FL } },
-{ .ca_index = 0x1a, .speakers = { FRC, FLC, 0, RC, FC, 0, FR, FL } },
-{ .ca_index = 0x1b, .speakers = { FRC, FLC, 0, RC, FC, LFE, FR, FL } },
-{ .ca_index = 0x1c, .speakers = { FRC, FLC, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x1d, .speakers = { FRC, FLC, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x1e, .speakers = { FRC, FLC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x1f, .speakers = { FRC, FLC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x20, .speakers = { 0, FCH, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x21, .speakers = { 0, FCH, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x22, .speakers = { TC, 0, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x23, .speakers = { TC, 0, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x24, .speakers = { FRH, FLH, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x25, .speakers = { FRH, FLH, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x26, .speakers = { FRW, FLW, RR, RL, 0, 0, FR, FL } },
-{ .ca_index = 0x27, .speakers = { FRW, FLW, RR, RL, 0, LFE, FR, FL } },
-{ .ca_index = 0x28, .speakers = { TC, RC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x29, .speakers = { TC, RC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x2a, .speakers = { FCH, RC, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x2b, .speakers = { FCH, RC, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x2c, .speakers = { TC, FCH, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x2d, .speakers = { TC, FCH, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x2e, .speakers = { FRH, FLH, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x2f, .speakers = { FRH, FLH, RR, RL, FC, LFE, FR, FL } },
-{ .ca_index = 0x30, .speakers = { FRW, FLW, RR, RL, FC, 0, FR, FL } },
-{ .ca_index = 0x31, .speakers = { FRW, FLW, RR, RL, FC, LFE, FR, FL } },
-};
-
-/*
- * HDMI routines
- */
-
-#ifdef BE_PARANOID
-static void hdmi_get_dip_index(struct hda_codec *codec, hda_nid_t nid,
- int *packet_index, int *byte_index)
-{
- int val;
-
- val = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_INDEX, 0);
-
- *packet_index = val >> 5;
- *byte_index = val & 0x1f;
-}
-#endif
-
-static void hdmi_set_dip_index(struct hda_codec *codec, hda_nid_t nid,
- int packet_index, int byte_index)
-{
- int val;
-
- val = (packet_index << 5) | (byte_index & 0x1f);
-
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_INDEX, val);
-}
-
-static void hdmi_write_dip_byte(struct hda_codec *codec, hda_nid_t nid,
- unsigned char val)
-{
- snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_HDMI_DIP_DATA, val);
-}
-
-static void hdmi_enable_output(struct hda_codec *codec)
-{
- /* Enable Audio InfoFrame Transmission */
- hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0);
- snd_hda_codec_write(codec, PIN_NID, 0, AC_VERB_SET_HDMI_DIP_XMIT,
- AC_DIPXMIT_BEST);
- /* Unmute */
- if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP)
- snd_hda_codec_write(codec, PIN_NID, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE);
- /* Enable pin out */
- snd_hda_sequence_write(codec, pinout_enable_verb);
-}
-
-static void hdmi_disable_output(struct hda_codec *codec)
-{
- snd_hda_sequence_write(codec, pinout_disable_verb);
- if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP)
- snd_hda_codec_write(codec, PIN_NID, 0,
- AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
- /*
- * FIXME: noises may arise when playing music after reloading the
- * kernel module, until the next X restart or monitor repower.
- */
-}
-
-static int hdmi_get_channel_count(struct hda_codec *codec)
-{
- return 1 + snd_hda_codec_read(codec, CVT_NID, 0,
- AC_VERB_GET_CVT_CHAN_COUNT, 0);
-}
-
-static void hdmi_set_channel_count(struct hda_codec *codec, int chs)
-{
- snd_hda_codec_write(codec, CVT_NID, 0,
- AC_VERB_SET_CVT_CHAN_COUNT, chs - 1);
-
- if (chs != hdmi_get_channel_count(codec))
- snd_printd(KERN_INFO "HDMI channel count: expect %d, get %d\n",
- chs, hdmi_get_channel_count(codec));
-}
-
-static void hdmi_debug_channel_mapping(struct hda_codec *codec)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- int i;
- int slot;
-
- for (i = 0; i < 8; i++) {
- slot = snd_hda_codec_read(codec, CVT_NID, 0,
- AC_VERB_GET_HDMI_CHAN_SLOT, i);
- printk(KERN_DEBUG "HDMI: ASP channel %d => slot %d\n",
- slot >> 4, slot & 0x7);
- }
-#endif
-}
-
-static void hdmi_parse_eld(struct hda_codec *codec)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- struct hdmi_eld *eld = &spec->sink_eld;
-
- if (!snd_hdmi_get_eld(eld, codec, PIN_NID))
- snd_hdmi_show_eld(eld);
-}
-
-
-/*
- * Audio InfoFrame routines
- */
-
-static void hdmi_debug_dip_size(struct hda_codec *codec)
-{
-#ifdef CONFIG_SND_DEBUG_VERBOSE
- int i;
- int size;
-
- size = snd_hdmi_get_eld_size(codec, PIN_NID);
- printk(KERN_DEBUG "HDMI: ELD buf size is %d\n", size);
-
- for (i = 0; i < 8; i++) {
- size = snd_hda_codec_read(codec, PIN_NID, 0,
- AC_VERB_GET_HDMI_DIP_SIZE, i);
- printk(KERN_DEBUG "HDMI: DIP GP[%d] buf size is %d\n", i, size);
- }
-#endif
-}
-
-static void hdmi_clear_dip_buffers(struct hda_codec *codec)
-{
-#ifdef BE_PARANOID
- int i, j;
- int size;
- int pi, bi;
- for (i = 0; i < 8; i++) {
- size = snd_hda_codec_read(codec, PIN_NID, 0,
- AC_VERB_GET_HDMI_DIP_SIZE, i);
- if (size == 0)
- continue;
-
- hdmi_set_dip_index(codec, PIN_NID, i, 0x0);
- for (j = 1; j < 1000; j++) {
- hdmi_write_dip_byte(codec, PIN_NID, 0x0);
- hdmi_get_dip_index(codec, PIN_NID, &pi, &bi);
- if (pi != i)
- snd_printd(KERN_INFO "dip index %d: %d != %d\n",
- bi, pi, i);
- if (bi == 0) /* byte index wrapped around */
- break;
- }
- snd_printd(KERN_INFO
- "HDMI: DIP GP[%d] buf reported size=%d, written=%d\n",
- i, size, j);
- }
-#endif
-}
-
-static void hdmi_fill_audio_infoframe(struct hda_codec *codec,
- struct hdmi_audio_infoframe *ai)
-{
- u8 *params = (u8 *)ai;
- int i;
-
- hdmi_debug_dip_size(codec);
- hdmi_clear_dip_buffers(codec); /* be paranoid */
-
- hdmi_set_dip_index(codec, PIN_NID, 0x0, 0x0);
- for (i = 0; i < sizeof(ai); i++)
- hdmi_write_dip_byte(codec, PIN_NID, params[i]);
-}
-
-/*
- * Compute derived values in channel_allocations[].
- */
-static void init_channel_allocations(void)
-{
- int i, j;
- struct cea_channel_speaker_allocation *p;
-
- for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
- p = channel_allocations + i;
- p->channels = 0;
- p->spk_mask = 0;
- for (j = 0; j < ARRAY_SIZE(p->speakers); j++)
- if (p->speakers[j]) {
- p->channels++;
- p->spk_mask |= p->speakers[j];
- }
- }
-}
-
-/*
- * The transformation takes two steps:
- *
- * eld->spk_alloc => (eld_speaker_allocation_bits[]) => spk_mask
- * spk_mask => (channel_allocations[]) => ai->CA
- *
- * TODO: it could select the wrong CA from multiple candidates.
-*/
-static int hdmi_setup_channel_allocation(struct hda_codec *codec,
- struct hdmi_audio_infoframe *ai)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- struct hdmi_eld *eld = &spec->sink_eld;
- int i;
- int spk_mask = 0;
- int channels = 1 + (ai->CC02_CT47 & 0x7);
- char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE];
-
- /*
- * CA defaults to 0 for basic stereo audio
- */
- if (!eld->eld_ver)
- return 0;
- if (!eld->spk_alloc)
- return 0;
- if (channels <= 2)
- return 0;
-
- /*
- * expand ELD's speaker allocation mask
- *
- * ELD tells the speaker mask in a compact(paired) form,
- * expand ELD's notions to match the ones used by Audio InfoFrame.
- */
- for (i = 0; i < ARRAY_SIZE(eld_speaker_allocation_bits); i++) {
- if (eld->spk_alloc & (1 << i))
- spk_mask |= eld_speaker_allocation_bits[i];
- }
-
- /* search for the first working match in the CA table */
- for (i = 0; i < ARRAY_SIZE(channel_allocations); i++) {
- if (channels == channel_allocations[i].channels &&
- (spk_mask & channel_allocations[i].spk_mask) ==
- channel_allocations[i].spk_mask) {
- ai->CA = channel_allocations[i].ca_index;
- break;
- }
- }
-
- snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf));
- snd_printdd(KERN_INFO
- "HDMI: select CA 0x%x for %d-channel allocation: %s\n",
- ai->CA, channels, buf);
-
- return ai->CA;
-}
-
-static void hdmi_setup_channel_mapping(struct hda_codec *codec,
- struct hdmi_audio_infoframe *ai)
-{
- if (!ai->CA)
- return;
-
- /*
- * TODO: adjust channel mapping if necessary
- * ALSA sequence is front/surr/clfe/side?
- */
-
- snd_hda_sequence_write(codec, def_chan_map);
- hdmi_debug_channel_mapping(codec);
-}
-
-
-static void hdmi_setup_audio_infoframe(struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct hdmi_audio_infoframe ai = {
- .type = 0x84,
- .ver = 0x01,
- .len = 0x0a,
- .CC02_CT47 = substream->runtime->channels - 1,
- };
-
- hdmi_setup_channel_allocation(codec, &ai);
- hdmi_setup_channel_mapping(codec, &ai);
-
- hdmi_fill_audio_infoframe(codec, &ai);
-}
-
-
-/*
- * Unsolicited events
- */
-
-static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
- int pind = !!(res & AC_UNSOL_RES_PD);
- int eldv = !!(res & AC_UNSOL_RES_ELDV);
-
- printk(KERN_INFO
- "HDMI hot plug event: Presence_Detect=%d ELD_Valid=%d\n",
- pind, eldv);
-
- if (pind && eldv) {
- hdmi_parse_eld(codec);
- /* TODO: do real things about ELD */
- }
-}
-
-static void hdmi_non_intrinsic_event(struct hda_codec *codec, unsigned int res)
-{
- int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
- int cp_state = !!(res & AC_UNSOL_RES_CP_STATE);
- int cp_ready = !!(res & AC_UNSOL_RES_CP_READY);
-
- printk(KERN_INFO
- "HDMI content protection event: SUBTAG=0x%x CP_STATE=%d CP_READY=%d\n",
- subtag,
- cp_state,
- cp_ready);
-
- /* TODO */
- if (cp_state)
- ;
- if (cp_ready)
- ;
-}
-
-
-static void intel_hdmi_unsol_event(struct hda_codec *codec, unsigned int res)
-{
- int tag = res >> AC_UNSOL_RES_TAG_SHIFT;
- int subtag = (res & AC_UNSOL_RES_SUBTAG) >> AC_UNSOL_RES_SUBTAG_SHIFT;
-
- if (tag != INTEL_HDMI_EVENT_TAG) {
- snd_printd(KERN_INFO "Unexpected HDMI event tag 0x%x\n", tag);
- return;
- }
-
- if (subtag == 0)
- hdmi_intrinsic_event(codec, res);
- else
- hdmi_non_intrinsic_event(codec, res);
-}
-
-/*
- * Callbacks
- */
-
-static int intel_hdmi_playback_pcm_open(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct intel_hdmi_spec *spec = codec->spec;
-
- return snd_hda_multi_out_dig_open(codec, &spec->multiout);
-}
-
-static int intel_hdmi_playback_pcm_close(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- struct snd_pcm_substream *substream)
-{
- struct intel_hdmi_spec *spec = codec->spec;
-
- hdmi_disable_output(codec);
-
- return snd_hda_multi_out_dig_close(codec, &spec->multiout);
-}
-
-static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo,
- struct hda_codec *codec,
- unsigned int stream_tag,
- unsigned int format,
- struct snd_pcm_substream *substream)
-{
- struct intel_hdmi_spec *spec = codec->spec;
-
- snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag,
- format, substream);
-
- hdmi_set_channel_count(codec, substream->runtime->channels);
-
- hdmi_setup_audio_infoframe(codec, substream);
-
- hdmi_enable_output(codec);
-
- return 0;
-}
-
-static struct hda_pcm_stream intel_hdmi_pcm_playback = {
- .substreams = 1,
- .channels_min = 2,
- .channels_max = 8,
- .nid = CVT_NID, /* NID to query formats and rates and setup streams */
- .ops = {
- .open = intel_hdmi_playback_pcm_open,
- .close = intel_hdmi_playback_pcm_close,
- .prepare = intel_hdmi_playback_pcm_prepare
- },
-};
-
-static int intel_hdmi_build_pcms(struct hda_codec *codec)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- struct hda_pcm *info = &spec->pcm_rec;
-
- codec->num_pcms = 1;
- codec->pcm_info = info;
-
- info->name = "INTEL HDMI";
- info->pcm_type = HDA_PCM_TYPE_HDMI;
- info->stream[SNDRV_PCM_STREAM_PLAYBACK] = intel_hdmi_pcm_playback;
-
- return 0;
-}
-
-static int intel_hdmi_build_controls(struct hda_codec *codec)
-{
- struct intel_hdmi_spec *spec = codec->spec;
- int err;
-
- err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
- if (err < 0)
- return err;
-
- return 0;
-}
-
-static int intel_hdmi_init(struct hda_codec *codec)
-{
- /* disable audio output as early as possible */
- hdmi_disable_output(codec);
-
- snd_hda_sequence_write(codec, unsolicited_response_verb);
-
- return 0;
-}
-
-static void intel_hdmi_free(struct hda_codec *codec)
-{
- struct intel_hdmi_spec *spec = codec->spec;
-
- snd_hda_eld_proc_free(codec, &spec->sink_eld);
- kfree(spec);
-}
-
-static struct hda_codec_ops intel_hdmi_patch_ops = {
- .init = intel_hdmi_init,
- .free = intel_hdmi_free,
- .build_pcms = intel_hdmi_build_pcms,
- .build_controls = intel_hdmi_build_controls,
- .unsol_event = intel_hdmi_unsol_event,
-};
-
-static int patch_intel_hdmi(struct hda_codec *codec)
-{
- struct intel_hdmi_spec *spec;
-
- spec = kzalloc(sizeof(*spec), GFP_KERNEL);
- if (spec == NULL)
- return -ENOMEM;
-
- spec->multiout.num_dacs = 0; /* no analog */
- spec->multiout.max_channels = 8;
- spec->multiout.dig_out_nid = CVT_NID;
-
- codec->spec = spec;
- codec->patch_ops = intel_hdmi_patch_ops;
-
- snd_hda_eld_proc_new(codec, &spec->sink_eld);
-
- init_channel_allocations();
-
- return 0;
-}
-
-static struct hda_codec_preset snd_hda_preset_intelhdmi[] = {
- { .id = 0x808629fb, .name = "INTEL G45 DEVCL", .patch = patch_intel_hdmi },
- { .id = 0x80862801, .name = "INTEL G45 DEVBLC", .patch = patch_intel_hdmi },
- { .id = 0x80862802, .name = "INTEL G45 DEVCTG", .patch = patch_intel_hdmi },
- { .id = 0x80862803, .name = "INTEL G45 DEVELK", .patch = patch_intel_hdmi },
- { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi },
- {} /* terminator */
-};
-
-MODULE_ALIAS("snd-hda-codec-id:808629fb");
-MODULE_ALIAS("snd-hda-codec-id:80862801");
-MODULE_ALIAS("snd-hda-codec-id:80862802");
-MODULE_ALIAS("snd-hda-codec-id:80862803");
-MODULE_ALIAS("snd-hda-codec-id:10951392");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Intel HDMI HD-audio codec");
-
-static struct hda_codec_preset_list intel_list = {
- .preset = snd_hda_preset_intelhdmi,
- .owner = THIS_MODULE,
-};
-
-static int __init patch_intelhdmi_init(void)
-{
- return snd_hda_add_codec_preset(&intel_list);
-}
-
-static void __exit patch_intelhdmi_exit(void)
-{
- snd_hda_delete_codec_preset(&intel_list);
-}
-
-module_init(patch_intelhdmi_init)
-module_exit(patch_intelhdmi_exit)
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c
index 0cd53063e62e..2eed2c8b98da 100644
--- a/sound/pci/hda/patch_nvhdmi.c
+++ b/sound/pci/hda/patch_nvhdmi.c
@@ -158,34 +158,8 @@ static int patch_nvhdmi(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
+struct hda_codec_preset snd_hda_preset_nvhdmi[] = {
{ .id = 0x10de0002, .name = "NVIDIA MCP78 HDMI", .patch = patch_nvhdmi },
{ .id = 0x10de0007, .name = "NVIDIA MCP7A HDMI", .patch = patch_nvhdmi },
- { .id = 0x10de0067, .name = "NVIDIA MCP67 HDMI", .patch = patch_nvhdmi },
{} /* terminator */
};
-
-MODULE_ALIAS("snd-hda-codec-id:10de0002");
-MODULE_ALIAS("snd-hda-codec-id:10de0007");
-MODULE_ALIAS("snd-hda-codec-id:10de0067");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Nvidia HDMI HD-audio codec");
-
-static struct hda_codec_preset_list nvhdmi_list = {
- .preset = snd_hda_preset_nvhdmi,
- .owner = THIS_MODULE,
-};
-
-static int __init patch_nvhdmi_init(void)
-{
- return snd_hda_add_codec_preset(&nvhdmi_list);
-}
-
-static void __exit patch_nvhdmi_exit(void)
-{
- snd_hda_delete_codec_preset(&nvhdmi_list);
-}
-
-module_init(patch_nvhdmi_init)
-module_exit(patch_nvhdmi_exit)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 0bd4e6bf354d..a378c0145125 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -30,6 +30,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_patch.h"
#define ALC880_FRONT_EVENT 0x01
#define ALC880_DCVOL_EVENT 0x02
@@ -113,7 +114,6 @@ enum {
ALC268_3ST,
ALC268_TOSHIBA,
ALC268_ACER,
- ALC268_ACER_DMIC,
ALC268_ACER_ASPIRE_ONE,
ALC268_DELL,
ALC268_ZEPTO,
@@ -130,8 +130,6 @@ enum {
ALC269_QUANTA_FL1,
ALC269_ASUS_EEEPC_P703,
ALC269_ASUS_EEEPC_P901,
- ALC269_FUJITSU,
- ALC269_LIFEBOOK,
ALC269_AUTO,
ALC269_MODEL_LAST /* last tag */
};
@@ -154,7 +152,6 @@ enum {
enum {
ALC660VD_3ST,
ALC660VD_3ST_DIG,
- ALC660VD_ASUS_V1S,
ALC861VD_3ST,
ALC861VD_3ST_DIG,
ALC861VD_6ST_DIG,
@@ -215,7 +212,6 @@ enum {
ALC883_TARGA_2ch_DIG,
ALC883_ACER,
ALC883_ACER_ASPIRE,
- ALC888_ACER_ASPIRE_4930G,
ALC883_MEDION,
ALC883_MEDION_MD2,
ALC883_LAPTOP_EAPD,
@@ -229,11 +225,9 @@ enum {
ALC883_MITAC,
ALC883_CLEVO_M720,
ALC883_FUJITSU_PI2515,
- ALC888_FUJITSU_XA3530,
ALC883_3ST_6ch_INTEL,
ALC888_ASUS_M90V,
ALC888_ASUS_EEE1601,
- ALC1200_ASUS_P5Q,
ALC883_AUTO,
ALC883_MODEL_LAST,
};
@@ -245,7 +239,6 @@ struct alc_spec {
/* codec parameterization */
struct snd_kcontrol_new *mixers[5]; /* mixer arrays */
unsigned int num_mixers;
- struct snd_kcontrol_new *cap_mixer; /* capture mixer */
const struct hda_verb *init_verbs[5]; /* initialization verbs
* don't forget NULL
@@ -275,7 +268,6 @@ struct alc_spec {
hda_nid_t *adc_nids;
hda_nid_t *capsrc_nids;
hda_nid_t dig_in_nid; /* digital-in NID; optional */
- unsigned char is_mix_capture; /* matrix-style capture (non-mux) */
/* capture source */
unsigned int num_mux_defs;
@@ -292,7 +284,8 @@ struct alc_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- struct snd_array kctls;
+ unsigned int num_kctl_alloc, num_kctl_used;
+ struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux;
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -330,7 +323,6 @@ struct alc_config_preset {
struct snd_kcontrol_new *mixers[5]; /* should be identical size
* with spec
*/
- struct snd_kcontrol_new *cap_mixer; /* capture mixer */
const struct hda_verb *init_verbs[5];
unsigned int num_dacs;
hda_nid_t *dac_nids;
@@ -383,40 +375,15 @@ static int alc_mux_enum_put(struct snd_kcontrol *kcontrol,
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct alc_spec *spec = codec->spec;
- const struct hda_input_mux *imux;
unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- unsigned int mux_idx;
+ unsigned int mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
hda_nid_t nid = spec->capsrc_nids ?
spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
-
- mux_idx = adc_idx >= spec->num_mux_defs ? 0 : adc_idx;
- imux = &spec->input_mux[mux_idx];
-
- if (spec->is_mix_capture) {
- /* Matrix-mixer style (e.g. ALC882) */
- unsigned int *cur_val = &spec->cur_mux[adc_idx];
- unsigned int i, idx;
-
- idx = ucontrol->value.enumerated.item[0];
- if (idx >= imux->num_items)
- idx = imux->num_items - 1;
- if (*cur_val == idx)
- return 0;
- for (i = 0; i < imux->num_items; i++) {
- unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
- snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
- imux->items[i].index,
- HDA_AMP_MUTE, v);
- }
- *cur_val = idx;
- return 1;
- } else {
- /* MUX style (e.g. ALC880) */
- return snd_hda_input_mux_put(codec, imux, ucontrol, nid,
- &spec->cur_mux[adc_idx]);
- }
+ return snd_hda_input_mux_put(codec, &spec->input_mux[mux_idx], ucontrol,
+ nid, &spec->cur_mux[adc_idx]);
}
+
/*
* channel mode setting
*/
@@ -750,43 +717,6 @@ static int alc_eapd_ctrl_put(struct snd_kcontrol *kcontrol,
#endif /* CONFIG_SND_DEBUG */
/*
- */
-static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix)
-{
- if (snd_BUG_ON(spec->num_mixers >= ARRAY_SIZE(spec->mixers)))
- return;
- spec->mixers[spec->num_mixers++] = mix;
-}
-
-static void add_verb(struct alc_spec *spec, const struct hda_verb *verb)
-{
- if (snd_BUG_ON(spec->num_init_verbs >= ARRAY_SIZE(spec->init_verbs)))
- return;
- spec->init_verbs[spec->num_init_verbs++] = verb;
-}
-
-#ifdef CONFIG_PROC_FS
-/*
- * hook for proc
- */
-static void print_realtek_coef(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- int coeff;
-
- if (nid != 0x20)
- return;
- coeff = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PROC_COEF, 0);
- snd_iprintf(buffer, " Processing Coefficient: 0x%02x\n", coeff);
- coeff = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_COEF_INDEX, 0);
- snd_iprintf(buffer, " Coefficient Index: 0x%02x\n", coeff);
-}
-#else
-#define print_realtek_coef NULL
-#endif
-
-/*
* set up from the preset table
*/
static void setup_preset(struct alc_spec *spec,
@@ -795,11 +725,11 @@ static void setup_preset(struct alc_spec *spec,
int i;
for (i = 0; i < ARRAY_SIZE(preset->mixers) && preset->mixers[i]; i++)
- add_mixer(spec, preset->mixers[i]);
- spec->cap_mixer = preset->cap_mixer;
+ spec->mixers[spec->num_mixers++] = preset->mixers[i];
for (i = 0; i < ARRAY_SIZE(preset->init_verbs) && preset->init_verbs[i];
i++)
- add_verb(spec, preset->init_verbs[i]);
+ spec->init_verbs[spec->num_init_verbs++] =
+ preset->init_verbs[i];
spec->channel_mode = preset->channel_mode;
spec->num_channel_mode = preset->num_channel_mode;
@@ -1177,226 +1107,6 @@ static void alc_fix_pincfg(struct hda_codec *codec,
}
/*
- * ALC888
- */
-
-/*
- * 2ch mode
- */
-static struct hda_verb alc888_4ST_ch2_intel_init[] = {
-/* Mic-in jack as mic in */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-/* Line-in jack as Line in */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-/* Line-Out as Front */
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
- { } /* end */
-};
-
-/*
- * 4ch mode
- */
-static struct hda_verb alc888_4ST_ch4_intel_init[] = {
-/* Mic-in jack as mic in */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF80 },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE },
-/* Line-in jack as Surround */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-Out as Front */
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x00},
- { } /* end */
-};
-
-/*
- * 6ch mode
- */
-static struct hda_verb alc888_4ST_ch6_intel_init[] = {
-/* Mic-in jack as CLFE */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-in jack as Surround */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-Out as CLFE (workaround because Mic-in is not loud enough) */
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
- { } /* end */
-};
-
-/*
- * 8ch mode
- */
-static struct hda_verb alc888_4ST_ch8_intel_init[] = {
-/* Mic-in jack as CLFE */
- { 0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-in jack as Surround */
- { 0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT },
- { 0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE },
-/* Line-Out as Side */
- { 0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
- { } /* end */
-};
-
-static struct hda_channel_mode alc888_4ST_8ch_intel_modes[4] = {
- { 2, alc888_4ST_ch2_intel_init },
- { 4, alc888_4ST_ch4_intel_init },
- { 6, alc888_4ST_ch6_intel_init },
- { 8, alc888_4ST_ch8_intel_init },
-};
-
-/*
- * ALC888 Fujitsu Siemens Amillo xa3530
- */
-
-static struct hda_verb alc888_fujitsu_xa3530_verbs[] = {
-/* Front Mic: set to PIN_IN (empty by default) */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Connect Internal HP to Front */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect Bass HP to Front */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect Line-Out side jack (SPDIF) to Side */
- {0x17, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x17, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x17, AC_VERB_SET_CONNECT_SEL, 0x03},
-/* Connect Mic jack to CLFE */
- {0x18, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x18, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x18, AC_VERB_SET_CONNECT_SEL, 0x02},
-/* Connect Line-in jack to Surround */
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
-/* Connect HP out jack to Front */
- {0x1b, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x1b, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1b, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Enable unsolicited event for HP jack and Line-out jack */
- {0x1b, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
- {0x17, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
- {}
-};
-
-static void alc888_fujitsu_xa3530_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned int bits;
- /* Line out presence */
- present = snd_hda_codec_read(codec, 0x17, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- /* HP out presence */
- present = present || snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? HDA_AMP_MUTE : 0;
- /* Toggle internal speakers muting */
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
- /* Toggle internal bass muting */
- snd_hda_codec_amp_stereo(codec, 0x15, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc888_fujitsu_xa3530_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if (res >> 26 == ALC880_HP_EVENT)
- alc888_fujitsu_xa3530_automute(codec);
-}
-
-
-/*
- * ALC888 Acer Aspire 4930G model
- */
-
-static struct hda_verb alc888_acer_aspire_4930g_verbs[] = {
-/* Front Mic: set to PIN_IN (empty by default) */
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
-/* Unselect Front Mic by default in input mixer 3 */
- {0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0xb)},
-/* Enable unsolicited event for HP jack */
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
-/* Connect Internal HP to front */
- {0x14, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x14, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x14, AC_VERB_SET_CONNECT_SEL, 0x00},
-/* Connect HP out to front */
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT},
- {0x15, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x00},
- { }
-};
-
-static struct hda_input_mux alc888_2_capture_sources[2] = {
- /* Front mic only available on one ADC */
- {
- .num_items = 4,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- { "Front Mic", 0xb },
- },
- },
- {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
- { "Line", 0x2 },
- { "CD", 0x4 },
- },
- }
-};
-
-static struct snd_kcontrol_new alc888_base_mixer[] = {
- HDA_CODEC_VOLUME("Front Playback Volume", 0x0c, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Front Playback Switch", 0x0c, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Surround Playback Volume", 0x0d, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Surround Playback Switch", 0x0d, 2, HDA_INPUT),
- HDA_CODEC_VOLUME_MONO("Center Playback Volume", 0x0e, 1, 0x0,
- HDA_OUTPUT),
- HDA_CODEC_VOLUME_MONO("LFE Playback Volume", 0x0e, 2, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE_MONO("Center Playback Switch", 0x0e, 1, 2, HDA_INPUT),
- HDA_BIND_MUTE_MONO("LFE Playback Switch", 0x0e, 2, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("Side Playback Volume", 0x0f, 0x0, HDA_OUTPUT),
- HDA_BIND_MUTE("Side Playback Switch", 0x0f, 2, HDA_INPUT),
- HDA_CODEC_VOLUME("CD Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("CD Playback Switch", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
- HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
- { } /* end */
-};
-
-static void alc888_acer_aspire_4930g_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned int bits;
- present = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
- bits = present ? HDA_AMP_MUTE : 0;
- snd_hda_codec_amp_stereo(codec, 0x14, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, bits);
-}
-
-static void alc888_acer_aspire_4930g_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if (res >> 26 == ALC880_HP_EVENT)
- alc888_acer_aspire_4930g_automute(codec);
-}
-
-/*
* ALC880 3-stack model
*
* DAC: Front = 0x02 (0x0c), Surr = 0x05 (0x0f), CLFE = 0x04 (0x0e)
@@ -1495,126 +1205,49 @@ static struct snd_kcontrol_new alc880_three_stack_mixer[] = {
};
/* capture mixer elements */
-static int alc_cap_vol_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int err;
-
- mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
- HDA_INPUT);
- err = snd_hda_mixer_amp_volume_info(kcontrol, uinfo);
- mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */
- return err;
-}
-
-static int alc_cap_vol_tlv(struct snd_kcontrol *kcontrol, int op_flag,
- unsigned int size, unsigned int __user *tlv)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- int err;
-
- mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[0], 3, 0,
- HDA_INPUT);
- err = snd_hda_mixer_amp_tlv(kcontrol, op_flag, size, tlv);
- mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */
- return err;
-}
-
-typedef int (*getput_call_t)(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol);
-
-static int alc_cap_getput_caller(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol,
- getput_call_t func)
-{
- struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
- struct alc_spec *spec = codec->spec;
- unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
- int err;
-
- mutex_lock(&codec->spdif_mutex); /* reuse spdif_mutex */
- kcontrol->private_value = HDA_COMPOSE_AMP_VAL(spec->adc_nids[adc_idx],
- 3, 0, HDA_INPUT);
- err = func(kcontrol, ucontrol);
- mutex_unlock(&codec->spdif_mutex); /* reuse spdif_mutex */
- return err;
-}
-
-static int alc_cap_vol_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return alc_cap_getput_caller(kcontrol, ucontrol,
- snd_hda_mixer_amp_volume_get);
-}
+static struct snd_kcontrol_new alc880_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 3,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
-static int alc_cap_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return alc_cap_getput_caller(kcontrol, ucontrol,
- snd_hda_mixer_amp_volume_put);
-}
+/* capture mixer elements (in case NID 0x07 not available) */
+static struct snd_kcontrol_new alc880_capture_alt_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
-/* capture mixer elements */
-#define alc_cap_sw_info snd_ctl_boolean_stereo_info
-
-static int alc_cap_sw_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return alc_cap_getput_caller(kcontrol, ucontrol,
- snd_hda_mixer_amp_switch_get);
-}
-
-static int alc_cap_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- return alc_cap_getput_caller(kcontrol, ucontrol,
- snd_hda_mixer_amp_switch_put);
-}
-
-#define DEFINE_CAPMIX(num) \
-static struct snd_kcontrol_new alc_capture_mixer ## num[] = { \
- { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = "Capture Switch", \
- .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, \
- .count = num, \
- .info = alc_cap_sw_info, \
- .get = alc_cap_sw_get, \
- .put = alc_cap_sw_put, \
- }, \
- { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- .name = "Capture Volume", \
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE | \
- SNDRV_CTL_ELEM_ACCESS_TLV_READ | \
- SNDRV_CTL_ELEM_ACCESS_TLV_CALLBACK), \
- .count = num, \
- .info = alc_cap_vol_info, \
- .get = alc_cap_vol_get, \
- .put = alc_cap_vol_put, \
- .tlv = { .c = alc_cap_vol_tlv }, \
- }, \
- { \
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
- /* .name = "Capture Source", */ \
- .name = "Input Source", \
- .count = num, \
- .info = alc_mux_enum_info, \
- .get = alc_mux_enum_get, \
- .put = alc_mux_enum_put, \
- }, \
- { } /* end */ \
-}
-
-/* up to three ADCs */
-DEFINE_CAPMIX(1);
-DEFINE_CAPMIX(2);
-DEFINE_CAPMIX(3);
/*
@@ -1900,6 +1533,18 @@ static struct snd_kcontrol_new alc880_tcl_s700_mixer[] = {
HDA_CODEC_MUTE("Mic Playback Switch", 0x0B, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
{ } /* end */
};
@@ -1974,7 +1619,6 @@ static const char *alc_slave_vols[] = {
"Speaker Playback Volume",
"Mono Playback Volume",
"Line-Out Playback Volume",
- "PCM Playback Volume",
NULL,
};
@@ -1994,9 +1638,6 @@ static const char *alc_slave_sws[] = {
/*
* build control elements
*/
-
-static void alc_free_kctls(struct hda_codec *codec);
-
static int alc_build_controls(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
@@ -2008,11 +1649,7 @@ static int alc_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
}
- if (spec->cap_mixer) {
- err = snd_hda_add_new_ctls(codec, spec->cap_mixer);
- if (err < 0)
- return err;
- }
+
if (spec->multiout.dig_out_nid) {
err = snd_hda_create_spdif_out_ctls(codec,
spec->multiout.dig_out_nid);
@@ -2047,7 +1684,6 @@ static int alc_build_controls(struct hda_codec *codec)
return err;
}
- alc_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -3138,27 +2774,19 @@ static int alc_build_pcms(struct hda_codec *codec)
return 0;
}
-static void alc_free_kctls(struct hda_codec *codec)
-{
- struct alc_spec *spec = codec->spec;
-
- if (spec->kctls.list) {
- struct snd_kcontrol_new *kctl = spec->kctls.list;
- int i;
- for (i = 0; i < spec->kctls.used; i++)
- kfree(kctl[i].name);
- }
- snd_array_free(&spec->kctls);
-}
-
static void alc_free(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ unsigned int i;
if (!spec)
return;
- alc_free_kctls(codec);
+ if (spec->kctl_alloc) {
+ for (i = 0; i < spec->num_kctl_used; i++)
+ kfree(spec->kctl_alloc[i].name);
+ kfree(spec->kctl_alloc);
+ }
kfree(spec);
codec->spec = NULL; /* to be sure */
}
@@ -3640,8 +3268,6 @@ static struct alc_config_preset alc880_presets[] = {
alc880_gpio2_init_verbs },
.num_dacs = ARRAY_SIZE(alc880_dac_nids),
.dac_nids = alc880_dac_nids,
- .adc_nids = alc880_adc_nids_alt, /* FIXME: correct? */
- .num_adc_nids = 1, /* single ADC */
.hp_nid = 0x03,
.num_channel_mode = ARRAY_SIZE(alc880_2_jack_modes),
.channel_mode = alc880_2_jack_modes,
@@ -3906,6 +3532,9 @@ static struct alc_config_preset alc880_presets[] = {
* Automatic parse of I/O pins from the BIOS configuration
*/
+#define NUM_CONTROL_ALLOC 32
+#define NUM_VERB_ALLOC 32
+
enum {
ALC_CTL_WIDGET_VOL,
ALC_CTL_WIDGET_MUTE,
@@ -3923,15 +3552,29 @@ static int add_control(struct alc_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- snd_array_init(&spec->kctls, sizeof(*knew), 32);
- knew = snd_array_new(&spec->kctls);
- if (!knew)
- return -ENOMEM;
+ if (spec->num_kctl_used >= spec->num_kctl_alloc) {
+ int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
+
+ /* array + terminator */
+ knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
+ if (!knew)
+ return -ENOMEM;
+ if (spec->kctl_alloc) {
+ memcpy(knew, spec->kctl_alloc,
+ sizeof(*knew) * spec->num_kctl_alloc);
+ kfree(spec->kctl_alloc);
+ }
+ spec->kctl_alloc = knew;
+ spec->num_kctl_alloc = num;
+ }
+
+ knew = &spec->kctl_alloc[spec->num_kctl_used];
*knew = alc880_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL);
if (!knew->name)
return -ENOMEM;
knew->private_value = val;
+ spec->num_kctl_used++;
return 0;
}
@@ -4255,10 +3898,10 @@ static int alc880_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = ALC880_DIGIN_NID;
- if (spec->kctls.list)
- add_mixer(spec, spec->kctls.list);
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
- add_verb(spec, alc880_volume_init_verbs);
+ spec->init_verbs[spec->num_init_verbs++] = alc880_volume_init_verbs;
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
@@ -4282,17 +3925,6 @@ static void alc880_auto_init(struct hda_codec *codec)
* OK, here we have finally the patch for ALC880
*/
-static void set_capture_mixer(struct alc_spec *spec)
-{
- static struct snd_kcontrol_new *caps[3] = {
- alc_capture_mixer1,
- alc_capture_mixer2,
- alc_capture_mixer3,
- };
- if (spec->num_adc_nids > 0 && spec->num_adc_nids <= 3)
- spec->cap_mixer = caps[spec->num_adc_nids - 1];
-}
-
static int patch_alc880(struct hda_codec *codec)
{
struct alc_spec *spec;
@@ -4348,12 +3980,16 @@ static int patch_alc880(struct hda_codec *codec)
if (wcap != AC_WID_AUD_IN) {
spec->adc_nids = alc880_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids_alt);
+ spec->mixers[spec->num_mixers] =
+ alc880_capture_alt_mixer;
+ spec->num_mixers++;
} else {
spec->adc_nids = alc880_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc880_adc_nids);
+ spec->mixers[spec->num_mixers] = alc880_capture_mixer;
+ spec->num_mixers++;
}
}
- set_capture_mixer(spec);
spec->vmaster_nid = 0x0c;
@@ -4364,7 +4000,6 @@ static int patch_alc880(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc880_loopbacks;
#endif
- codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -4389,6 +4024,11 @@ static hda_nid_t alc260_adc_nids_alt[1] = {
0x05,
};
+static hda_nid_t alc260_hp_adc_nids[2] = {
+ /* ADC1, 0 */
+ 0x05, 0x04
+};
+
/* NIDs used when simultaneous access to both ADCs makes sense. Note that
* alc260_capture_mixer assumes ADC0 (nid 0x04) is the first ADC.
*/
@@ -4517,13 +4157,13 @@ static void alc260_hp_master_update(struct hda_codec *codec,
struct alc_spec *spec = codec->spec;
unsigned int val = spec->master_sw ? PIN_HP : 0;
/* change HP and line-out pins */
- snd_hda_codec_write(codec, hp, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_codec_write(codec, 0x0f, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
val);
- snd_hda_codec_write(codec, line, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_codec_write(codec, 0x10, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
val);
/* mono (speaker) depending on the HP jack sense */
val = (val && !spec->jack_present) ? PIN_OUT : 0;
- snd_hda_codec_write(codec, mono, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
+ snd_hda_codec_write(codec, 0x11, 0, AC_VERB_SET_PIN_WIDGET_CONTROL,
val);
}
@@ -4602,7 +4242,7 @@ static struct snd_kcontrol_new alc260_hp_3013_mixer[] = {
.info = snd_ctl_boolean_mono_info,
.get = alc260_hp_master_sw_get,
.put = alc260_hp_master_sw_put,
- .private_value = (0x15 << 16) | (0x10 << 8) | 0x11
+ .private_value = (0x10 << 16) | (0x15 << 8) | 0x11
},
HDA_CODEC_VOLUME("Front Playback Volume", 0x09, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Front Playback Switch", 0x10, 0x0, HDA_OUTPUT),
@@ -4655,7 +4295,7 @@ static void alc260_hp_3013_automute(struct hda_codec *codec)
present = snd_hda_codec_read(codec, 0x15, 0,
AC_VERB_GET_PIN_SENSE, 0);
spec->jack_present = (present & AC_PINSENSE_PRESENCE) != 0;
- alc260_hp_master_update(codec, 0x15, 0x10, 0x11);
+ alc260_hp_master_update(codec, 0x10, 0x15, 0x11);
}
static void alc260_hp_3013_unsol_event(struct hda_codec *codec,
@@ -4787,6 +4427,45 @@ static struct snd_kcontrol_new alc260_replacer_672v_mixer[] = {
{ } /* end */
};
+/* capture mixer elements */
+static struct snd_kcontrol_new alc260_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x04, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x04, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x05, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x05, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc260_capture_alt_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x05, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x05, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
+
/*
* initialization verbs
*/
@@ -5603,6 +5282,7 @@ static struct hda_verb alc260_volume_init_verbs[] = {
static int alc260_parse_auto_config(struct hda_codec *codec)
{
struct alc_spec *spec = codec->spec;
+ unsigned int wcap;
int err;
static hda_nid_t alc260_ignore[] = { 0x17, 0 };
@@ -5613,7 +5293,7 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
err = alc260_auto_create_multi_out_ctls(spec, &spec->autocfg);
if (err < 0)
return err;
- if (!spec->kctls.list)
+ if (!spec->kctl_alloc)
return 0; /* can't find valid BIOS pin config */
err = alc260_auto_create_analog_input_ctls(spec, &spec->autocfg);
if (err < 0)
@@ -5623,14 +5303,28 @@ static int alc260_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC260_DIGOUT_NID;
- if (spec->kctls.list)
- add_mixer(spec, spec->kctls.list);
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
- add_verb(spec, alc260_volume_init_verbs);
+ spec->init_verbs[spec->num_init_verbs++] = alc260_volume_init_verbs;
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
+ /* check whether NID 0x04 is valid */
+ wcap = get_wcaps(codec, 0x04);
+ wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT; /* get type */
+ if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
+ spec->adc_nids = alc260_adc_nids_alt;
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
+ spec->mixers[spec->num_mixers] = alc260_capture_alt_mixer;
+ } else {
+ spec->adc_nids = alc260_adc_nids;
+ spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
+ spec->mixers[spec->num_mixers] = alc260_capture_mixer;
+ }
+ spec->num_mixers++;
+
store_pin_configs(codec);
return 1;
}
@@ -5700,11 +5394,12 @@ static struct alc_config_preset alc260_presets[] = {
[ALC260_BASIC] = {
.mixers = { alc260_base_output_mixer,
alc260_input_mixer,
- alc260_pc_beep_mixer },
+ alc260_pc_beep_mixer,
+ alc260_capture_mixer },
.init_verbs = { alc260_init_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_dual_adc_nids),
+ .num_adc_nids = ARRAY_SIZE(alc260_adc_nids),
.adc_nids = alc260_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
@@ -5712,13 +5407,14 @@ static struct alc_config_preset alc260_presets[] = {
},
[ALC260_HP] = {
.mixers = { alc260_hp_output_mixer,
- alc260_input_mixer },
+ alc260_input_mixer,
+ alc260_capture_alt_mixer },
.init_verbs = { alc260_init_verbs,
alc260_hp_unsol_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
- .adc_nids = alc260_adc_nids_alt,
+ .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
+ .adc_nids = alc260_hp_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
@@ -5727,13 +5423,14 @@ static struct alc_config_preset alc260_presets[] = {
},
[ALC260_HP_DC7600] = {
.mixers = { alc260_hp_dc7600_mixer,
- alc260_input_mixer },
+ alc260_input_mixer,
+ alc260_capture_alt_mixer },
.init_verbs = { alc260_init_verbs,
alc260_hp_dc7600_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
- .adc_nids = alc260_adc_nids_alt,
+ .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
+ .adc_nids = alc260_hp_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
@@ -5742,13 +5439,14 @@ static struct alc_config_preset alc260_presets[] = {
},
[ALC260_HP_3013] = {
.mixers = { alc260_hp_3013_mixer,
- alc260_input_mixer },
+ alc260_input_mixer,
+ alc260_capture_alt_mixer },
.init_verbs = { alc260_hp_3013_init_verbs,
alc260_hp_3013_unsol_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt),
- .adc_nids = alc260_adc_nids_alt,
+ .num_adc_nids = ARRAY_SIZE(alc260_hp_adc_nids),
+ .adc_nids = alc260_hp_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc260_modes),
.channel_mode = alc260_modes,
.input_mux = &alc260_capture_source,
@@ -5756,7 +5454,8 @@ static struct alc_config_preset alc260_presets[] = {
.init_hook = alc260_hp_3013_automute,
},
[ALC260_FUJITSU_S702X] = {
- .mixers = { alc260_fujitsu_mixer },
+ .mixers = { alc260_fujitsu_mixer,
+ alc260_capture_mixer },
.init_verbs = { alc260_fujitsu_init_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
@@ -5768,7 +5467,8 @@ static struct alc_config_preset alc260_presets[] = {
.input_mux = alc260_fujitsu_capture_sources,
},
[ALC260_ACER] = {
- .mixers = { alc260_acer_mixer },
+ .mixers = { alc260_acer_mixer,
+ alc260_capture_mixer },
.init_verbs = { alc260_acer_init_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
@@ -5780,7 +5480,8 @@ static struct alc_config_preset alc260_presets[] = {
.input_mux = alc260_acer_capture_sources,
},
[ALC260_WILL] = {
- .mixers = { alc260_will_mixer },
+ .mixers = { alc260_will_mixer,
+ alc260_capture_mixer },
.init_verbs = { alc260_init_verbs, alc260_will_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
@@ -5792,7 +5493,8 @@ static struct alc_config_preset alc260_presets[] = {
.input_mux = &alc260_capture_source,
},
[ALC260_REPLACER_672V] = {
- .mixers = { alc260_replacer_672v_mixer },
+ .mixers = { alc260_replacer_672v_mixer,
+ alc260_capture_mixer },
.init_verbs = { alc260_init_verbs, alc260_replacer_672v_verbs },
.num_dacs = ARRAY_SIZE(alc260_dac_nids),
.dac_nids = alc260_dac_nids,
@@ -5807,7 +5509,8 @@ static struct alc_config_preset alc260_presets[] = {
},
#ifdef CONFIG_SND_DEBUG
[ALC260_TEST] = {
- .mixers = { alc260_test_mixer },
+ .mixers = { alc260_test_mixer,
+ alc260_capture_mixer },
.init_verbs = { alc260_test_init_verbs },
.num_dacs = ARRAY_SIZE(alc260_test_dac_nids),
.dac_nids = alc260_test_dac_nids,
@@ -5866,21 +5569,6 @@ static int patch_alc260(struct hda_codec *codec)
spec->stream_digital_playback = &alc260_pcm_digital_playback;
spec->stream_digital_capture = &alc260_pcm_digital_capture;
- if (!spec->adc_nids && spec->input_mux) {
- /* check whether NID 0x04 is valid */
- unsigned int wcap = get_wcaps(codec, 0x04);
- wcap = (wcap & AC_WCAP_TYPE) >> AC_WCAP_TYPE_SHIFT;
- /* get type */
- if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
- spec->adc_nids = alc260_adc_nids_alt;
- spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids_alt);
- } else {
- spec->adc_nids = alc260_adc_nids;
- spec->num_adc_nids = ARRAY_SIZE(alc260_adc_nids);
- }
- }
- set_capture_mixer(spec);
-
spec->vmaster_nid = 0x08;
codec->patch_ops = alc_patch_ops;
@@ -5890,7 +5578,6 @@ static int patch_alc260(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc260_loopbacks;
#endif
- codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -5938,6 +5625,36 @@ static struct hda_input_mux alc882_capture_source = {
{ "CD", 0x4 },
},
};
+#define alc882_mux_enum_info alc_mux_enum_info
+#define alc882_mux_enum_get alc_mux_enum_get
+
+static int alc882_mux_enum_put(struct snd_kcontrol *kcontrol,
+ struct snd_ctl_elem_value *ucontrol)
+{
+ struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
+ struct alc_spec *spec = codec->spec;
+ const struct hda_input_mux *imux = spec->input_mux;
+ unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
+ hda_nid_t nid = spec->capsrc_nids ?
+ spec->capsrc_nids[adc_idx] : spec->adc_nids[adc_idx];
+ unsigned int *cur_val = &spec->cur_mux[adc_idx];
+ unsigned int i, idx;
+
+ idx = ucontrol->value.enumerated.item[0];
+ if (idx >= imux->num_items)
+ idx = imux->num_items - 1;
+ if (*cur_val == idx)
+ return 0;
+ for (i = 0; i < imux->num_items; i++) {
+ unsigned int v = (i == idx) ? 0 : HDA_AMP_MUTE;
+ snd_hda_codec_amp_stereo(codec, nid, HDA_INPUT,
+ imux->items[i].index,
+ HDA_AMP_MUTE, v);
+ }
+ *cur_val = idx;
+ return 1;
+}
+
/*
* 2ch mode
*/
@@ -6620,6 +6337,49 @@ static struct hda_verb alc882_auto_init_verbs[] = {
{ }
};
+/* capture mixer elements */
+static struct snd_kcontrol_new alc882_capture_alt_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc882_mux_enum_info,
+ .get = alc882_mux_enum_get,
+ .put = alc882_mux_enum_put,
+ },
+ { } /* end */
+};
+
+static struct snd_kcontrol_new alc882_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x07, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 2, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 2, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 3,
+ .info = alc882_mux_enum_info,
+ .get = alc882_mux_enum_get,
+ .put = alc882_mux_enum_put,
+ },
+ { } /* end */
+};
+
#ifdef CONFIG_SND_HDA_POWER_SAVE
#define alc882_loopbacks alc880_loopbacks
#endif
@@ -6748,7 +6508,8 @@ static struct alc_config_preset alc882_presets[] = {
.init_hook = alc885_imac24_init_hook,
},
[ALC882_TARGA] = {
- .mixers = { alc882_targa_mixer, alc882_chmode_mixer },
+ .mixers = { alc882_targa_mixer, alc882_chmode_mixer,
+ alc882_capture_mixer },
.init_verbs = { alc882_init_verbs, alc882_targa_verbs},
.num_dacs = ARRAY_SIZE(alc882_dac_nids),
.dac_nids = alc882_dac_nids,
@@ -6764,7 +6525,8 @@ static struct alc_config_preset alc882_presets[] = {
.init_hook = alc882_targa_automute,
},
[ALC882_ASUS_A7J] = {
- .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer },
+ .mixers = { alc882_asus_a7j_mixer, alc882_chmode_mixer,
+ alc882_capture_mixer },
.init_verbs = { alc882_init_verbs, alc882_asus_a7j_verbs},
.num_dacs = ARRAY_SIZE(alc882_dac_nids),
.dac_nids = alc882_dac_nids,
@@ -7069,7 +6831,6 @@ static int patch_alc882(struct hda_codec *codec)
spec->stream_digital_playback = &alc882_pcm_digital_playback;
spec->stream_digital_capture = &alc882_pcm_digital_capture;
- spec->is_mix_capture = 1; /* matrix-style capture */
if (!spec->adc_nids && spec->input_mux) {
/* check whether NID 0x07 is valid */
unsigned int wcap = get_wcaps(codec, 0x07);
@@ -7079,13 +6840,17 @@ static int patch_alc882(struct hda_codec *codec)
spec->adc_nids = alc882_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids_alt);
spec->capsrc_nids = alc882_capsrc_nids_alt;
+ spec->mixers[spec->num_mixers] =
+ alc882_capture_alt_mixer;
+ spec->num_mixers++;
} else {
spec->adc_nids = alc882_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc882_adc_nids);
spec->capsrc_nids = alc882_capsrc_nids;
+ spec->mixers[spec->num_mixers] = alc882_capture_mixer;
+ spec->num_mixers++;
}
}
- set_capture_mixer(spec);
spec->vmaster_nid = 0x0c;
@@ -7096,7 +6861,6 @@ static int patch_alc882(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc882_loopbacks;
#endif
- codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -7115,8 +6879,6 @@ static int patch_alc882(struct hda_codec *codec)
#define ALC883_DIGOUT_NID 0x06
#define ALC883_DIGIN_NID 0x0a
-#define ALC1200_DIGOUT_NID 0x10
-
static hda_nid_t alc883_dac_nids[4] = {
/* front, rear, clfe, rear_surr */
0x02, 0x03, 0x04, 0x05
@@ -7127,20 +6889,8 @@ static hda_nid_t alc883_adc_nids[2] = {
0x08, 0x09,
};
-static hda_nid_t alc883_adc_nids_alt[1] = {
- /* ADC1 */
- 0x08,
-};
-
-static hda_nid_t alc883_adc_nids_rev[2] = {
- /* ADC2-1 */
- 0x09, 0x08
-};
-
static hda_nid_t alc883_capsrc_nids[2] = { 0x23, 0x22 };
-static hda_nid_t alc883_capsrc_nids_rev[2] = { 0x22, 0x23 };
-
/* input MUX */
/* FIXME: should be a matrix-type input source selection */
@@ -7207,6 +6957,11 @@ static struct hda_input_mux alc883_asus_eee1601_capture_source = {
},
};
+#define alc883_mux_enum_info alc_mux_enum_info
+#define alc883_mux_enum_get alc_mux_enum_get
+/* ALC883 has the ALC882-type input selection */
+#define alc883_mux_enum_put alc882_mux_enum_put
+
/*
* 2ch mode
*/
@@ -7360,6 +7115,19 @@ static struct snd_kcontrol_new alc883_base_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7377,6 +7145,19 @@ static struct snd_kcontrol_new alc883_mitac_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7391,6 +7172,19 @@ static struct snd_kcontrol_new alc883_clevo_m720_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7405,6 +7199,19 @@ static struct snd_kcontrol_new alc883_2ch_fujitsu_pi2515_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7424,6 +7231,19 @@ static struct snd_kcontrol_new alc883_3ST_2ch_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7449,6 +7269,17 @@ static struct snd_kcontrol_new alc883_3ST_6ch_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7475,6 +7306,19 @@ static struct snd_kcontrol_new alc883_3ST_6ch_intel_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7500,6 +7344,18 @@ static struct snd_kcontrol_new alc883_fivestack_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x05, HDA_INPUT),
HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x05, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7520,6 +7376,19 @@ static struct snd_kcontrol_new alc883_tagra_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7535,6 +7404,19 @@ static struct snd_kcontrol_new alc883_tagra_2ch_mixer[] = {
HDA_CODEC_VOLUME("Int Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Int Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Int Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7547,6 +7429,17 @@ static struct snd_kcontrol_new alc883_lenovo_101e_2ch_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7560,6 +7453,19 @@ static struct snd_kcontrol_new alc883_lenovo_nb0763_mixer[] = {
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("iMic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_MUTE("iMic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7573,6 +7479,19 @@ static struct snd_kcontrol_new alc883_medion_md2_mixer[] = {
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Line Playback Volume", 0x0b, 0x02, HDA_INPUT),
HDA_CODEC_MUTE("Line Playback Switch", 0x0b, 0x02, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7585,6 +7504,19 @@ static struct snd_kcontrol_new alc883_acer_aspire_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7612,6 +7544,19 @@ static struct snd_kcontrol_new alc888_lenovo_sky_mixer[] = {
HDA_CODEC_VOLUME("Front Mic Playback Volume", 0x0b, 0x1, HDA_INPUT),
HDA_CODEC_VOLUME("Front Mic Boost", 0x19, 0, HDA_INPUT),
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x0b, 0x1, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
+ },
{ } /* end */
};
@@ -7642,10 +7587,6 @@ static struct snd_kcontrol_new alc883_asus_eee1601_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- { } /* end */
-};
-
-static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
HDA_BIND_VOL("Capture Volume", &alc883_bind_cap_vol),
HDA_BIND_SW("Capture Switch", &alc883_bind_cap_switch),
{
@@ -7653,9 +7594,9 @@ static struct snd_kcontrol_new alc883_asus_eee1601_cap_mixer[] = {
/* .name = "Capture Source", */
.name = "Input Source",
.count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
+ .info = alc883_mux_enum_info,
+ .get = alc883_mux_enum_get,
+ .put = alc883_mux_enum_put,
},
{ } /* end */
};
@@ -8310,6 +8251,27 @@ static struct hda_verb alc883_auto_init_verbs[] = {
{ }
};
+/* capture mixer elements */
+static struct snd_kcontrol_new alc883_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME_IDX("Capture Volume", 1, 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE_IDX("Capture Switch", 1, 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 2,
+ .info = alc882_mux_enum_info,
+ .get = alc882_mux_enum_get,
+ .put = alc882_mux_enum_put,
+ },
+ { } /* end */
+};
+
static struct hda_verb alc888_asus_m90v_verbs[] = {
{0x22, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
{0x23, AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)},
@@ -8432,7 +8394,6 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
[ALC883_TARGA_2ch_DIG] = "targa-2ch-dig",
[ALC883_ACER] = "acer",
[ALC883_ACER_ASPIRE] = "acer-aspire",
- [ALC888_ACER_ASPIRE_4930G] = "acer-aspire-4930g",
[ALC883_MEDION] = "medion",
[ALC883_MEDION_MD2] = "medion-md2",
[ALC883_LAPTOP_EAPD] = "laptop-eapd",
@@ -8446,9 +8407,7 @@ static const char *alc883_models[ALC883_MODEL_LAST] = {
[ALC883_MITAC] = "mitac",
[ALC883_CLEVO_M720] = "clevo-m720",
[ALC883_FUJITSU_PI2515] = "fujitsu-pi2515",
- [ALC888_FUJITSU_XA3530] = "fujitsu-xa3530",
[ALC883_3ST_6ch_INTEL] = "3stack-6ch-intel",
- [ALC1200_ASUS_P5Q] = "asus-p5q",
[ALC883_AUTO] = "auto",
};
@@ -8459,8 +8418,6 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1025, 0x0110, "Acer Aspire", ALC883_ACER_ASPIRE),
SND_PCI_QUIRK(0x1025, 0x0112, "Acer Aspire 9303", ALC883_ACER_ASPIRE),
SND_PCI_QUIRK(0x1025, 0x0121, "Acer Aspire 5920G", ALC883_ACER_ASPIRE),
- SND_PCI_QUIRK(0x1025, 0x013e, "Acer Aspire 4930G",
- ALC888_ACER_ASPIRE_4930G),
SND_PCI_QUIRK(0x1025, 0, "Acer laptop", ALC883_ACER), /* default Acer */
SND_PCI_QUIRK(0x1028, 0x020d, "Dell Inspiron 530", ALC888_6ST_DELL),
SND_PCI_QUIRK(0x103c, 0x2a3d, "HP Pavillion", ALC883_6ST_DIG),
@@ -8469,7 +8426,6 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x2a61, "HP Nettle", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1043, 0x1873, "Asus M90V", ALC888_ASUS_M90V),
SND_PCI_QUIRK(0x1043, 0x8249, "Asus M2A-VM HDMI", ALC883_3ST_6ch_DIG),
- SND_PCI_QUIRK(0x1043, 0x82fe, "Asus P5Q-EM HDMI", ALC1200_ASUS_P5Q),
SND_PCI_QUIRK(0x1043, 0x835f, "Asus Eee 1601", ALC888_ASUS_EEE1601),
SND_PCI_QUIRK(0x105b, 0x0ce8, "Foxconn P35AX-S", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x105b, 0x6668, "Foxconn", ALC883_6ST_DIG),
@@ -8496,7 +8452,6 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x6668, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7187, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7250, "MSI", ALC883_6ST_DIG),
- SND_PCI_QUIRK(0x1462, 0x7260, "MSI 7260", ALC883_TARGA_DIG),
SND_PCI_QUIRK(0x1462, 0x7267, "MSI", ALC883_3ST_6ch_DIG),
SND_PCI_QUIRK(0x1462, 0x7280, "MSI", ALC883_6ST_DIG),
SND_PCI_QUIRK(0x1462, 0x7327, "MSI", ALC883_6ST_DIG),
@@ -8508,8 +8463,6 @@ static struct snd_pci_quirk alc883_cfg_tbl[] = {
SND_PCI_QUIRK(0x15d9, 0x8780, "Supermicro PDSBA", ALC883_3ST_6ch),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_MEDION),
SND_PCI_QUIRK(0x1734, 0x1108, "Fujitsu AMILO Pi2515", ALC883_FUJITSU_PI2515),
- SND_PCI_QUIRK(0x1734, 0x113d, "Fujitsu AMILO Xa3530",
- ALC888_FUJITSU_XA3530),
SND_PCI_QUIRK(0x17aa, 0x101e, "Lenovo 101e", ALC883_LENOVO_101E_2ch),
SND_PCI_QUIRK(0x17aa, 0x2085, "Lenovo NB0763", ALC883_LENOVO_NB0763),
SND_PCI_QUIRK(0x17aa, 0x3bfc, "Lenovo NB0763", ALC883_LENOVO_NB0763),
@@ -8600,8 +8553,6 @@ static struct alc_config_preset alc883_presets[] = {
.init_verbs = { alc883_init_verbs, alc883_tagra_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
- .adc_nids = alc883_adc_nids_alt,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
.dig_out_nid = ALC883_DIGOUT_NID,
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
@@ -8635,26 +8586,6 @@ static struct alc_config_preset alc883_presets[] = {
.unsol_event = alc883_acer_aspire_unsol_event,
.init_hook = alc883_acer_aspire_automute,
},
- [ALC888_ACER_ASPIRE_4930G] = {
- .mixers = { alc888_base_mixer,
- alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs, alc880_gpio1_init_verbs,
- alc888_acer_aspire_4930g_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
- .adc_nids = alc883_adc_nids_rev,
- .capsrc_nids = alc883_capsrc_nids_rev,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_3ST_6ch_modes),
- .channel_mode = alc883_3ST_6ch_modes,
- .need_dac_fix = 1,
- .num_mux_defs =
- ARRAY_SIZE(alc888_2_capture_sources),
- .input_mux = alc888_2_capture_sources,
- .unsol_event = alc888_acer_aspire_4930g_unsol_event,
- .init_hook = alc888_acer_aspire_4930g_automute,
- },
[ALC883_MEDION] = {
.mixers = { alc883_fivestack_mixer,
alc883_chmode_mixer },
@@ -8662,8 +8593,6 @@ static struct alc_config_preset alc883_presets[] = {
alc883_medion_eapd_verbs },
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
- .adc_nids = alc883_adc_nids_alt,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.input_mux = &alc883_capture_source,
@@ -8706,8 +8635,6 @@ static struct alc_config_preset alc883_presets[] = {
.init_verbs = { alc883_init_verbs, alc883_lenovo_101e_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
- .adc_nids = alc883_adc_nids_alt,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_alt),
.num_channel_mode = ARRAY_SIZE(alc883_3ST_2ch_modes),
.channel_mode = alc883_3ST_2ch_modes,
.input_mux = &alc883_lenovo_101e_capture_source,
@@ -8798,30 +8725,14 @@ static struct alc_config_preset alc883_presets[] = {
.unsol_event = alc883_2ch_fujitsu_pi2515_unsol_event,
.init_hook = alc883_2ch_fujitsu_pi2515_automute,
},
- [ALC888_FUJITSU_XA3530] = {
- .mixers = { alc888_base_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs,
- alc888_fujitsu_xa3530_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc883_adc_nids_rev),
- .adc_nids = alc883_adc_nids_rev,
- .capsrc_nids = alc883_capsrc_nids_rev,
- .dig_out_nid = ALC883_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc888_4ST_8ch_intel_modes),
- .channel_mode = alc888_4ST_8ch_intel_modes,
- .num_mux_defs =
- ARRAY_SIZE(alc888_2_capture_sources),
- .input_mux = alc888_2_capture_sources,
- .unsol_event = alc888_fujitsu_xa3530_unsol_event,
- .init_hook = alc888_fujitsu_xa3530_automute,
- },
[ALC888_LENOVO_SKY] = {
.mixers = { alc888_lenovo_sky_mixer, alc883_chmode_mixer },
.init_verbs = { alc883_init_verbs, alc888_lenovo_sky_verbs},
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
.dig_out_nid = ALC883_DIGOUT_NID,
+ .num_adc_nids = ARRAY_SIZE(alc883_adc_nids),
+ .adc_nids = alc883_adc_nids,
.num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
.channel_mode = alc883_sixstack_modes,
.need_dac_fix = 1,
@@ -8845,7 +8756,6 @@ static struct alc_config_preset alc883_presets[] = {
},
[ALC888_ASUS_EEE1601] = {
.mixers = { alc883_asus_eee1601_mixer },
- .cap_mixer = alc883_asus_eee1601_cap_mixer,
.init_verbs = { alc883_init_verbs, alc888_asus_eee1601_verbs },
.num_dacs = ARRAY_SIZE(alc883_dac_nids),
.dac_nids = alc883_dac_nids,
@@ -8858,17 +8768,6 @@ static struct alc_config_preset alc883_presets[] = {
.unsol_event = alc883_eee1601_unsol_event,
.init_hook = alc883_eee1601_inithook,
},
- [ALC1200_ASUS_P5Q] = {
- .mixers = { alc883_base_mixer, alc883_chmode_mixer },
- .init_verbs = { alc883_init_verbs },
- .num_dacs = ARRAY_SIZE(alc883_dac_nids),
- .dac_nids = alc883_dac_nids,
- .dig_out_nid = ALC1200_DIGOUT_NID,
- .dig_in_nid = ALC883_DIGIN_NID,
- .num_channel_mode = ARRAY_SIZE(alc883_sixstack_modes),
- .channel_mode = alc883_sixstack_modes,
- .input_mux = &alc883_capture_source,
- },
};
@@ -8963,6 +8862,8 @@ static int alc883_parse_auto_config(struct hda_codec *codec)
/* hack - override the init verbs */
spec->init_verbs[0] = alc883_auto_init_verbs;
+ spec->mixers[spec->num_mixers] = alc883_capture_mixer;
+ spec->num_mixers++;
return 1; /* config found */
}
@@ -9045,15 +8946,9 @@ static int patch_alc883(struct hda_codec *codec)
spec->stream_digital_playback = &alc883_pcm_digital_playback;
spec->stream_digital_capture = &alc883_pcm_digital_capture;
- if (!spec->num_adc_nids) {
- spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
- spec->adc_nids = alc883_adc_nids;
- }
- if (!spec->capsrc_nids)
- spec->capsrc_nids = alc883_capsrc_nids;
- spec->is_mix_capture = 1; /* matrix-style capture */
- if (!spec->cap_mixer)
- set_capture_mixer(spec);
+ spec->num_adc_nids = ARRAY_SIZE(alc883_adc_nids);
+ spec->adc_nids = alc883_adc_nids;
+ spec->capsrc_nids = alc883_capsrc_nids;
spec->vmaster_nid = 0x0c;
@@ -9065,7 +8960,6 @@ static int patch_alc883(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc883_loopbacks;
#endif
- codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -9545,6 +9439,20 @@ static struct snd_kcontrol_new alc262_toshiba_s06_mixer[] = {
HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
+ HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
{ } /* end */
};
@@ -10061,7 +9969,7 @@ static int alc262_ultra_mux_enum_put(struct snd_kcontrol *kcontrol,
struct alc_spec *spec = codec->spec;
int ret;
- ret = alc_mux_enum_put(kcontrol, ucontrol);
+ ret = alc882_mux_enum_put(kcontrol, ucontrol);
if (!ret)
return 0;
/* reprogram the HP pin as mic or HP according to the input source */
@@ -10078,8 +9986,8 @@ static struct snd_kcontrol_new alc262_ultra_capture_mixer[] = {
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Capture Source",
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
+ .info = alc882_mux_enum_info,
+ .get = alc882_mux_enum_get,
.put = alc262_ultra_mux_enum_put,
},
{ } /* end */
@@ -10472,10 +10380,10 @@ static int alc262_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = ALC262_DIGIN_NID;
- if (spec->kctls.list)
- add_mixer(spec, spec->kctls.list);
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
- add_verb(spec, alc262_volume_init_verbs);
+ spec->init_verbs[spec->num_init_verbs++] = alc262_volume_init_verbs;
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
@@ -10558,8 +10466,6 @@ static struct snd_pci_quirk alc262_cfg_tbl[] = {
SND_PCI_QUIRK(0x104d, 0x820f, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x900e, "Sony ASSAMD", ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x104d, 0x9015, "Sony 0x9015", ALC262_SONY_ASSAMD),
- SND_PCI_QUIRK(0x104d, 0x9033, "Sony VAIO VGN-SR19XN",
- ALC262_SONY_ASSAMD),
SND_PCI_QUIRK(0x1179, 0x0001, "Toshiba dynabook SS RX1",
ALC262_TOSHIBA_RX1),
SND_PCI_QUIRK(0x1179, 0xff7b, "Toshiba S06", ALC262_TOSHIBA_S06),
@@ -10718,8 +10624,7 @@ static struct alc_config_preset alc262_presets[] = {
.init_hook = alc262_hippo_automute,
},
[ALC262_ULTRA] = {
- .mixers = { alc262_ultra_mixer },
- .cap_mixer = alc262_ultra_capture_mixer,
+ .mixers = { alc262_ultra_mixer, alc262_ultra_capture_mixer },
.init_verbs = { alc262_ultra_verbs },
.num_dacs = ARRAY_SIZE(alc262_dac_nids),
.dac_nids = alc262_dac_nids,
@@ -10845,7 +10750,6 @@ static int patch_alc262(struct hda_codec *codec)
spec->stream_digital_playback = &alc262_pcm_digital_playback;
spec->stream_digital_capture = &alc262_pcm_digital_capture;
- spec->is_mix_capture = 1;
if (!spec->adc_nids && spec->input_mux) {
/* check whether NID 0x07 is valid */
unsigned int wcap = get_wcaps(codec, 0x07);
@@ -10856,14 +10760,17 @@ static int patch_alc262(struct hda_codec *codec)
spec->adc_nids = alc262_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids_alt);
spec->capsrc_nids = alc262_capsrc_nids_alt;
+ spec->mixers[spec->num_mixers] =
+ alc262_capture_alt_mixer;
+ spec->num_mixers++;
} else {
spec->adc_nids = alc262_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc262_adc_nids);
spec->capsrc_nids = alc262_capsrc_nids;
+ spec->mixers[spec->num_mixers] = alc262_capture_mixer;
+ spec->num_mixers++;
}
}
- if (!spec->cap_mixer)
- set_capture_mixer(spec);
spec->vmaster_nid = 0x0c;
@@ -10874,7 +10781,6 @@ static int patch_alc262(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc262_loopbacks;
#endif
- codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -11036,22 +10942,6 @@ static struct snd_kcontrol_new alc268_acer_mixer[] = {
{ }
};
-static struct snd_kcontrol_new alc268_acer_dmic_mixer[] = {
- /* output mixer control */
- HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- },
- HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Line In Boost", 0x1a, 0, HDA_INPUT),
- { }
-};
-
static struct hda_verb alc268_acer_aspire_one_verbs[] = {
{0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
{0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
@@ -11328,6 +11218,10 @@ static struct hda_verb alc268_volume_init_verbs[] = {
{ }
};
+#define alc268_mux_enum_info alc_mux_enum_info
+#define alc268_mux_enum_get alc_mux_enum_get
+#define alc268_mux_enum_put alc_mux_enum_put
+
static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x23, 0x0, HDA_OUTPUT),
HDA_CODEC_MUTE("Capture Switch", 0x23, 0x0, HDA_OUTPUT),
@@ -11339,9 +11233,9 @@ static struct snd_kcontrol_new alc268_capture_alt_mixer[] = {
/* .name = "Capture Source", */
.name = "Input Source",
.count = 1,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
+ .info = alc268_mux_enum_info,
+ .get = alc268_mux_enum_get,
+ .put = alc268_mux_enum_put,
},
{ } /* end */
};
@@ -11359,9 +11253,9 @@ static struct snd_kcontrol_new alc268_capture_mixer[] = {
/* .name = "Capture Source", */
.name = "Input Source",
.count = 2,
- .info = alc_mux_enum_info,
- .get = alc_mux_enum_get,
- .put = alc_mux_enum_put,
+ .info = alc268_mux_enum_info,
+ .get = alc268_mux_enum_get,
+ .put = alc268_mux_enum_put,
},
{ } /* end */
};
@@ -11380,15 +11274,6 @@ static struct hda_input_mux alc268_acer_capture_source = {
.num_items = 3,
.items = {
{ "Mic", 0x0 },
- { "Internal Mic", 0x1 },
- { "Line", 0x2 },
- },
-};
-
-static struct hda_input_mux alc268_acer_dmic_capture_source = {
- .num_items = 3,
- .items = {
- { "Mic", 0x0 },
{ "Internal Mic", 0x6 },
{ "Line", 0x2 },
},
@@ -11627,13 +11512,13 @@ static int alc268_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC268_DIGOUT_NID;
- if (spec->kctls.list)
- add_mixer(spec, spec->kctls.list);
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
if (spec->autocfg.speaker_pins[0] != 0x1d)
- add_mixer(spec, alc268_beep_mixer);
+ spec->mixers[spec->num_mixers++] = alc268_beep_mixer;
- add_verb(spec, alc268_volume_init_verbs);
+ spec->init_verbs[spec->num_init_verbs++] = alc268_volume_init_verbs;
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
@@ -11669,7 +11554,6 @@ static const char *alc268_models[ALC268_MODEL_LAST] = {
[ALC268_3ST] = "3stack",
[ALC268_TOSHIBA] = "toshiba",
[ALC268_ACER] = "acer",
- [ALC268_ACER_DMIC] = "acer-dmic",
[ALC268_ACER_ASPIRE_ONE] = "acer-aspire",
[ALC268_DELL] = "dell",
[ALC268_ZEPTO] = "zepto",
@@ -11765,23 +11649,6 @@ static struct alc_config_preset alc268_presets[] = {
.unsol_event = alc268_acer_unsol_event,
.init_hook = alc268_acer_init_hook,
},
- [ALC268_ACER_DMIC] = {
- .mixers = { alc268_acer_dmic_mixer, alc268_capture_alt_mixer,
- alc268_beep_mixer },
- .init_verbs = { alc268_base_init_verbs, alc268_eapd_verbs,
- alc268_acer_verbs },
- .num_dacs = ARRAY_SIZE(alc268_dac_nids),
- .dac_nids = alc268_dac_nids,
- .num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt),
- .adc_nids = alc268_adc_nids_alt,
- .capsrc_nids = alc268_capsrc_nids,
- .hp_nid = 0x02,
- .num_channel_mode = ARRAY_SIZE(alc268_modes),
- .channel_mode = alc268_modes,
- .input_mux = &alc268_acer_dmic_capture_source,
- .unsol_event = alc268_acer_unsol_event,
- .init_hook = alc268_acer_init_hook,
- },
[ALC268_ACER_ASPIRE_ONE] = {
.mixers = { alc268_acer_aspire_one_mixer,
alc268_capture_alt_mixer },
@@ -11920,11 +11787,15 @@ static int patch_alc268(struct hda_codec *codec)
if (wcap != AC_WID_AUD_IN || spec->input_mux->num_items == 1) {
spec->adc_nids = alc268_adc_nids_alt;
spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids_alt);
- add_mixer(spec, alc268_capture_alt_mixer);
+ spec->mixers[spec->num_mixers] =
+ alc268_capture_alt_mixer;
+ spec->num_mixers++;
} else {
spec->adc_nids = alc268_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc268_adc_nids);
- add_mixer(spec, alc268_capture_mixer);
+ spec->mixers[spec->num_mixers] =
+ alc268_capture_mixer;
+ spec->num_mixers++;
}
spec->capsrc_nids = alc268_capsrc_nids;
/* set default input source */
@@ -11940,8 +11811,6 @@ static int patch_alc268(struct hda_codec *codec)
if (board_config == ALC268_AUTO)
spec->init_hook = alc268_auto_init;
- codec->proc_widget_hook = print_realtek_coef;
-
return 0;
}
@@ -12024,31 +11893,6 @@ static struct snd_kcontrol_new alc269_quanta_fl1_mixer[] = {
{ }
};
-static struct snd_kcontrol_new alc269_lifebook_mixer[] = {
- /* output mixer control */
- HDA_BIND_VOL("Master Playback Volume", &alc268_acer_bind_master_vol),
- {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Master Playback Switch",
- .info = snd_hda_mixer_amp_switch_info,
- .get = snd_hda_mixer_amp_switch_get,
- .put = alc268_acer_master_sw_put,
- .private_value = HDA_COMPOSE_AMP_VAL(0x14, 3, 0, HDA_OUTPUT),
- },
- HDA_CODEC_VOLUME("Mic Playback Volume", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_MUTE("Mic Playback Switch", 0x0b, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Playback Volume", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_MUTE("Internal Mic Playback Switch", 0x0b, 0x01, HDA_INPUT),
- HDA_CODEC_VOLUME("Internal Mic Boost", 0x19, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("Dock Mic Playback Volume", 0x0b, 0x03, HDA_INPUT),
- HDA_CODEC_MUTE("Dock Mic Playback Switch", 0x0b, 0x03, HDA_INPUT),
- HDA_CODEC_VOLUME("Dock Mic Boost", 0x1b, 0, HDA_INPUT),
- HDA_CODEC_VOLUME("PC Speaker Playback Volume", 0x0b, 0x04, HDA_INPUT),
- HDA_CODEC_MUTE("PC Speaker Playback Switch", 0x0b, 0x04, HDA_INPUT),
- { }
-};
-
/* bind volumes of both NID 0x0c and 0x0d */
static struct hda_bind_ctls alc269_epc_bind_vol = {
.ops = &snd_hda_bind_vol,
@@ -12067,18 +11911,28 @@ static struct snd_kcontrol_new alc269_eeepc_mixer[] = {
};
/* capture mixer elements */
-static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
+static struct snd_kcontrol_new alc269_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
- HDA_CODEC_VOLUME("Mic Boost", 0x18, 0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
{ } /* end */
};
-/* FSC amilo */
-static struct snd_kcontrol_new alc269_fujitsu_mixer[] = {
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x14, 0x0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x15, 0x0, HDA_OUTPUT),
- HDA_BIND_VOL("PCM Playback Volume", &alc269_epc_bind_vol),
+/* capture mixer elements */
+static struct snd_kcontrol_new alc269_epc_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
{ } /* end */
};
@@ -12099,20 +11953,6 @@ static struct hda_verb alc269_quanta_fl1_verbs[] = {
{ }
};
-static struct hda_verb alc269_lifebook_verbs[] = {
- {0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x1a, AC_VERB_SET_CONNECT_SEL, 0x01},
- {0x12, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- {0x15, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x15, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
- {0x1a, AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_UNMUTE},
- {0x1a, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP},
- {0x1a, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN},
- {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, AC_USRSP_EN | ALC880_MIC_EVENT},
- {0x1d, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN},
- { }
-};
-
/* toggle speaker-output according to the hp-jack state */
static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
{
@@ -12138,37 +11978,6 @@ static void alc269_quanta_fl1_speaker_automute(struct hda_codec *codec)
AC_VERB_SET_PROC_COEF, 0x480);
}
-/* toggle speaker-output according to the hp-jacks state */
-static void alc269_lifebook_speaker_automute(struct hda_codec *codec)
-{
- unsigned int present;
- unsigned char bits;
-
- /* Check laptop headphone socket */
- present = snd_hda_codec_read(codec, 0x15, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-
- /* Check port replicator headphone socket */
- present |= snd_hda_codec_read(codec, 0x1a, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-
- bits = present ? AMP_IN_MUTE(0) : 0;
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 0,
- AMP_IN_MUTE(0), bits);
- snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1,
- AMP_IN_MUTE(0), bits);
-
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_COEF_INDEX, 0x0c);
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_PROC_COEF, 0x680);
-
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_COEF_INDEX, 0x0c);
- snd_hda_codec_write(codec, 0x20, 0,
- AC_VERB_SET_PROC_COEF, 0x480);
-}
-
static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec)
{
unsigned int present;
@@ -12179,29 +11988,6 @@ static void alc269_quanta_fl1_mic_automute(struct hda_codec *codec)
AC_VERB_SET_CONNECT_SEL, present ? 0x0 : 0x1);
}
-static void alc269_lifebook_mic_autoswitch(struct hda_codec *codec)
-{
- unsigned int present_laptop;
- unsigned int present_dock;
-
- present_laptop = snd_hda_codec_read(codec, 0x18, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-
- present_dock = snd_hda_codec_read(codec, 0x1b, 0,
- AC_VERB_GET_PIN_SENSE, 0) & 0x80000000;
-
- /* Laptop mic port overrides dock mic port, design decision */
- if (present_dock)
- snd_hda_codec_write(codec, 0x23, 0,
- AC_VERB_SET_CONNECT_SEL, 0x3);
- if (present_laptop)
- snd_hda_codec_write(codec, 0x23, 0,
- AC_VERB_SET_CONNECT_SEL, 0x0);
- if (!present_dock && !present_laptop)
- snd_hda_codec_write(codec, 0x23, 0,
- AC_VERB_SET_CONNECT_SEL, 0x1);
-}
-
static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
unsigned int res)
{
@@ -12211,27 +11997,12 @@ static void alc269_quanta_fl1_unsol_event(struct hda_codec *codec,
alc269_quanta_fl1_mic_automute(codec);
}
-static void alc269_lifebook_unsol_event(struct hda_codec *codec,
- unsigned int res)
-{
- if ((res >> 26) == ALC880_HP_EVENT)
- alc269_lifebook_speaker_automute(codec);
- if ((res >> 26) == ALC880_MIC_EVENT)
- alc269_lifebook_mic_autoswitch(codec);
-}
-
static void alc269_quanta_fl1_init_hook(struct hda_codec *codec)
{
alc269_quanta_fl1_speaker_automute(codec);
alc269_quanta_fl1_mic_automute(codec);
}
-static void alc269_lifebook_init_hook(struct hda_codec *codec)
-{
- alc269_lifebook_speaker_automute(codec);
- alc269_lifebook_mic_autoswitch(codec);
-}
-
static struct hda_verb alc269_eeepc_dmic_init_verbs[] = {
{0x15, AC_VERB_SET_CONNECT_SEL, 0x01},
{0x23, AC_VERB_SET_CONNECT_SEL, 0x05},
@@ -12532,17 +12303,17 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC269_DIGOUT_NID;
- if (spec->kctls.list)
- add_mixer(spec, spec->kctls.list);
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
/* create a beep mixer control if the pin 0x1d isn't assigned */
for (i = 0; i < ARRAY_SIZE(spec->autocfg.input_pins); i++)
if (spec->autocfg.input_pins[i] == 0x1d)
break;
if (i >= ARRAY_SIZE(spec->autocfg.input_pins))
- add_mixer(spec, alc269_beep_mixer);
+ spec->mixers[spec->num_mixers++] = alc269_beep_mixer;
- add_verb(spec, alc269_init_verbs);
+ spec->init_verbs[spec->num_init_verbs++] = alc269_init_verbs;
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
/* set default input source */
@@ -12554,8 +12325,8 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
if (err < 0)
return err;
- if (!spec->cap_mixer)
- set_capture_mixer(spec);
+ spec->mixers[spec->num_mixers] = alc269_capture_mixer;
+ spec->num_mixers++;
store_pin_configs(codec);
return 1;
@@ -12584,9 +12355,7 @@ static const char *alc269_models[ALC269_MODEL_LAST] = {
[ALC269_BASIC] = "basic",
[ALC269_QUANTA_FL1] = "quanta",
[ALC269_ASUS_EEEPC_P703] = "eeepc-p703",
- [ALC269_ASUS_EEEPC_P901] = "eeepc-p901",
- [ALC269_FUJITSU] = "fujitsu",
- [ALC269_LIFEBOOK] = "lifebook"
+ [ALC269_ASUS_EEEPC_P901] = "eeepc-p901"
};
static struct snd_pci_quirk alc269_cfg_tbl[] = {
@@ -12597,14 +12366,12 @@ static struct snd_pci_quirk alc269_cfg_tbl[] = {
ALC269_ASUS_EEEPC_P901),
SND_PCI_QUIRK(0x1043, 0x834a, "ASUS Eeepc S101",
ALC269_ASUS_EEEPC_P901),
- SND_PCI_QUIRK(0x1734, 0x115d, "FSC Amilo", ALC269_FUJITSU),
- SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook ICH9M-based", ALC269_LIFEBOOK),
{}
};
static struct alc_config_preset alc269_presets[] = {
[ALC269_BASIC] = {
- .mixers = { alc269_base_mixer },
+ .mixers = { alc269_base_mixer, alc269_capture_mixer },
.init_verbs = { alc269_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
.dac_nids = alc269_dac_nids,
@@ -12626,8 +12393,7 @@ static struct alc_config_preset alc269_presets[] = {
.init_hook = alc269_quanta_fl1_init_hook,
},
[ALC269_ASUS_EEEPC_P703] = {
- .mixers = { alc269_eeepc_mixer },
- .cap_mixer = alc269_epc_capture_mixer,
+ .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer },
.init_verbs = { alc269_init_verbs,
alc269_eeepc_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
@@ -12640,8 +12406,7 @@ static struct alc_config_preset alc269_presets[] = {
.init_hook = alc269_eeepc_amic_inithook,
},
[ALC269_ASUS_EEEPC_P901] = {
- .mixers = { alc269_eeepc_mixer },
- .cap_mixer = alc269_epc_capture_mixer,
+ .mixers = { alc269_eeepc_mixer, alc269_epc_capture_mixer},
.init_verbs = { alc269_init_verbs,
alc269_eeepc_dmic_init_verbs },
.num_dacs = ARRAY_SIZE(alc269_dac_nids),
@@ -12653,32 +12418,6 @@ static struct alc_config_preset alc269_presets[] = {
.unsol_event = alc269_eeepc_dmic_unsol_event,
.init_hook = alc269_eeepc_dmic_inithook,
},
- [ALC269_FUJITSU] = {
- .mixers = { alc269_fujitsu_mixer, alc269_beep_mixer },
- .cap_mixer = alc269_epc_capture_mixer,
- .init_verbs = { alc269_init_verbs,
- alc269_eeepc_dmic_init_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .input_mux = &alc269_eeepc_dmic_capture_source,
- .unsol_event = alc269_eeepc_dmic_unsol_event,
- .init_hook = alc269_eeepc_dmic_inithook,
- },
- [ALC269_LIFEBOOK] = {
- .mixers = { alc269_lifebook_mixer },
- .init_verbs = { alc269_init_verbs, alc269_lifebook_verbs },
- .num_dacs = ARRAY_SIZE(alc269_dac_nids),
- .dac_nids = alc269_dac_nids,
- .hp_nid = 0x03,
- .num_channel_mode = ARRAY_SIZE(alc269_modes),
- .channel_mode = alc269_modes,
- .input_mux = &alc269_capture_source,
- .unsol_event = alc269_lifebook_unsol_event,
- .init_hook = alc269_lifebook_init_hook,
- },
};
static int patch_alc269(struct hda_codec *codec)
@@ -12733,8 +12472,6 @@ static int patch_alc269(struct hda_codec *codec)
spec->adc_nids = alc269_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids);
spec->capsrc_nids = alc269_capsrc_nids;
- if (!spec->cap_mixer)
- set_capture_mixer(spec);
codec->patch_ops = alc_patch_ops;
if (board_config == ALC269_AUTO)
@@ -12743,7 +12480,6 @@ static int patch_alc269(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc269_loopbacks;
#endif
- codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -12876,6 +12612,17 @@ static struct snd_kcontrol_new alc861_base_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+ /* Capture mixer control */
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
{ } /* end */
};
@@ -12899,6 +12646,17 @@ static struct snd_kcontrol_new alc861_3ST_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+ /* Capture mixer control */
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -12916,6 +12674,18 @@ static struct snd_kcontrol_new alc861_toshiba_mixer[] = {
HDA_CODEC_VOLUME("Mic Playback Volume", 0x15, 0x01, HDA_INPUT),
HDA_CODEC_MUTE("Mic Playback Switch", 0x15, 0x01, HDA_INPUT),
+ /*Capture mixer control */
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+
{ } /* end */
};
@@ -12939,6 +12709,17 @@ static struct snd_kcontrol_new alc861_uniwill_m31_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_INPUT),
+ /* Capture mixer control */
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -12970,6 +12751,17 @@ static struct snd_kcontrol_new alc861_asus_mixer[] = {
HDA_CODEC_MUTE("Front Mic Playback Switch", 0x10, 0x01, HDA_OUTPUT),
HDA_CODEC_MUTE("Headphone Playback Switch", 0x1a, 0x03, HDA_OUTPUT),
+ /* Capture mixer control */
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ .name = "Capture Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
{
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.name = "Channel Mode",
@@ -13501,6 +13293,25 @@ static int alc861_auto_create_analog_input_ctls(struct alc_spec *spec,
return 0;
}
+static struct snd_kcontrol_new alc861_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x08, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x08, 0x0, HDA_INPUT),
+
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc_mux_enum_info,
+ .get = alc_mux_enum_get,
+ .put = alc_mux_enum_put,
+ },
+ { } /* end */
+};
+
static void alc861_auto_set_output_and_unmute(struct hda_codec *codec,
hda_nid_t nid,
int pin_type, int dac_idx)
@@ -13591,17 +13402,18 @@ static int alc861_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC861_DIGOUT_NID;
- if (spec->kctls.list)
- add_mixer(spec, spec->kctls.list);
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
- add_verb(spec, alc861_auto_init_verbs);
+ spec->init_verbs[spec->num_init_verbs++] = alc861_auto_init_verbs;
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
spec->adc_nids = alc861_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc861_adc_nids);
- set_capture_mixer(spec);
+ spec->mixers[spec->num_mixers] = alc861_capture_mixer;
+ spec->num_mixers++;
store_pin_configs(codec);
return 1;
@@ -13832,7 +13644,6 @@ static int patch_alc861(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc861_loopbacks;
#endif
- codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -13898,6 +13709,11 @@ static struct hda_input_mux alc861vd_hp_capture_source = {
},
};
+#define alc861vd_mux_enum_info alc_mux_enum_info
+#define alc861vd_mux_enum_get alc_mux_enum_get
+/* ALC861VD has the ALC882-type input selection (but has only one ADC) */
+#define alc861vd_mux_enum_put alc882_mux_enum_put
+
/*
* 2ch mode
*/
@@ -13943,6 +13759,25 @@ static struct snd_kcontrol_new alc861vd_chmode_mixer[] = {
{ } /* end */
};
+static struct snd_kcontrol_new alc861vd_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc861vd_mux_enum_info,
+ .get = alc861vd_mux_enum_get,
+ .put = alc861vd_mux_enum_put,
+ },
+ { } /* end */
+};
+
/* Pin assignment: Front=0x14, Rear=0x15, CLFE=0x16, Side=0x17
* Mic=0x18, Front Mic=0x19, Line-In=0x1a, HP=0x1b
*/
@@ -14334,7 +14169,6 @@ static void alc861vd_dallas_unsol_event(struct hda_codec *codec, unsigned int re
static const char *alc861vd_models[ALC861VD_MODEL_LAST] = {
[ALC660VD_3ST] = "3stack-660",
[ALC660VD_3ST_DIG] = "3stack-660-digout",
- [ALC660VD_ASUS_V1S] = "asus-v1s",
[ALC861VD_3ST] = "3stack",
[ALC861VD_3ST_DIG] = "3stack-digout",
[ALC861VD_6ST_DIG] = "6stack-digout",
@@ -14349,7 +14183,7 @@ static struct snd_pci_quirk alc861vd_cfg_tbl[] = {
SND_PCI_QUIRK(0x103c, 0x30bf, "HP TX1000", ALC861VD_HP),
SND_PCI_QUIRK(0x1043, 0x12e2, "Asus z35m", ALC660VD_3ST),
SND_PCI_QUIRK(0x1043, 0x1339, "Asus G1", ALC660VD_3ST),
- SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC660VD_ASUS_V1S),
+ SND_PCI_QUIRK(0x1043, 0x1633, "Asus V1Sn", ALC861VD_LENOVO),
SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS", ALC660VD_3ST_DIG),
SND_PCI_QUIRK(0x10de, 0x03f0, "Realtek ALC660 demo", ALC660VD_3ST),
SND_PCI_QUIRK(0x1179, 0xff00, "Toshiba A135", ALC861VD_LENOVO),
@@ -14456,21 +14290,6 @@ static struct alc_config_preset alc861vd_presets[] = {
.unsol_event = alc861vd_dallas_unsol_event,
.init_hook = alc861vd_dallas_automute,
},
- [ALC660VD_ASUS_V1S] = {
- .mixers = { alc861vd_lenovo_mixer },
- .init_verbs = { alc861vd_volume_init_verbs,
- alc861vd_3stack_init_verbs,
- alc861vd_eapd_verbs,
- alc861vd_lenovo_unsol_verbs },
- .num_dacs = ARRAY_SIZE(alc660vd_dac_nids),
- .dac_nids = alc660vd_dac_nids,
- .dig_out_nid = ALC861VD_DIGOUT_NID,
- .num_channel_mode = ARRAY_SIZE(alc861vd_3stack_2ch_modes),
- .channel_mode = alc861vd_3stack_2ch_modes,
- .input_mux = &alc861vd_capture_source,
- .unsol_event = alc861vd_lenovo_unsol_event,
- .init_hook = alc861vd_lenovo_automute,
- },
};
/*
@@ -14695,10 +14514,11 @@ static int alc861vd_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC861VD_DIGOUT_NID;
- if (spec->kctls.list)
- add_mixer(spec, spec->kctls.list);
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
- add_verb(spec, alc861vd_volume_init_verbs);
+ spec->init_verbs[spec->num_init_verbs++]
+ = alc861vd_volume_init_verbs;
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
@@ -14765,7 +14585,7 @@ static int patch_alc861vd(struct hda_codec *codec)
spec->stream_name_analog = "ALC660-VD Analog";
spec->stream_name_digital = "ALC660-VD Digital";
/* always turn on EAPD */
- add_verb(spec, alc660vd_eapd_verbs);
+ spec->init_verbs[spec->num_init_verbs++] = alc660vd_eapd_verbs;
} else {
spec->stream_name_analog = "ALC861VD Analog";
spec->stream_name_digital = "ALC861VD Digital";
@@ -14780,9 +14600,9 @@ static int patch_alc861vd(struct hda_codec *codec)
spec->adc_nids = alc861vd_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc861vd_adc_nids);
spec->capsrc_nids = alc861vd_capsrc_nids;
- spec->is_mix_capture = 1;
- set_capture_mixer(spec);
+ spec->mixers[spec->num_mixers] = alc861vd_capture_mixer;
+ spec->num_mixers++;
spec->vmaster_nid = 0x02;
@@ -14794,7 +14614,6 @@ static int patch_alc861vd(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc861vd_loopbacks;
#endif
- codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -14870,6 +14689,10 @@ static struct hda_input_mux alc663_m51va_capture_source = {
},
};
+#define alc662_mux_enum_info alc_mux_enum_info
+#define alc662_mux_enum_get alc_mux_enum_get
+#define alc662_mux_enum_put alc882_mux_enum_put
+
/*
* 2ch mode
*/
@@ -15455,6 +15278,25 @@ static struct hda_verb alc662_ecs_init_verbs[] = {
{}
};
+/* capture mixer elements */
+static struct snd_kcontrol_new alc662_capture_mixer[] = {
+ HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
+ HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
+ {
+ .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+ /* The multiple "Capture Source" controls confuse alsamixer
+ * So call somewhat different..
+ */
+ /* .name = "Capture Source", */
+ .name = "Input Source",
+ .count = 1,
+ .info = alc662_mux_enum_info,
+ .get = alc662_mux_enum_get,
+ .put = alc662_mux_enum_put,
+ },
+ { } /* end */
+};
+
static struct snd_kcontrol_new alc662_auto_capture_mixer[] = {
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0x0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0x0, HDA_INPUT),
@@ -16026,7 +15868,7 @@ static struct snd_pci_quirk alc662_cfg_tbl[] = {
static struct alc_config_preset alc662_presets[] = {
[ALC662_3ST_2ch_DIG] = {
- .mixers = { alc662_3ST_2ch_mixer },
+ .mixers = { alc662_3ST_2ch_mixer, alc662_capture_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16037,7 +15879,8 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_3ST_6ch_DIG] = {
- .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
+ .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,
+ alc662_capture_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16049,7 +15892,8 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_3ST_6ch] = {
- .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer },
+ .mixers = { alc662_3ST_6ch_mixer, alc662_chmode_mixer,
+ alc662_capture_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16059,7 +15903,8 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_5ST_DIG] = {
- .mixers = { alc662_base_mixer, alc662_chmode_mixer },
+ .mixers = { alc662_base_mixer, alc662_chmode_mixer,
+ alc662_capture_mixer },
.init_verbs = { alc662_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16070,7 +15915,7 @@ static struct alc_config_preset alc662_presets[] = {
.input_mux = &alc662_capture_source,
},
[ALC662_LENOVO_101E] = {
- .mixers = { alc662_lenovo_101e_mixer },
+ .mixers = { alc662_lenovo_101e_mixer, alc662_capture_mixer },
.init_verbs = { alc662_init_verbs, alc662_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16081,7 +15926,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_lenovo_101e_all_automute,
},
[ALC662_ASUS_EEEPC_P701] = {
- .mixers = { alc662_eeepc_p701_mixer },
+ .mixers = { alc662_eeepc_p701_mixer, alc662_capture_mixer },
.init_verbs = { alc662_init_verbs,
alc662_eeepc_sue_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16093,7 +15938,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_eeepc_inithook,
},
[ALC662_ASUS_EEEPC_EP20] = {
- .mixers = { alc662_eeepc_ep20_mixer,
+ .mixers = { alc662_eeepc_ep20_mixer, alc662_capture_mixer,
alc662_chmode_mixer },
.init_verbs = { alc662_init_verbs,
alc662_eeepc_ep20_sue_init_verbs },
@@ -16106,7 +15951,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_eeepc_ep20_inithook,
},
[ALC662_ECS] = {
- .mixers = { alc662_ecs_mixer },
+ .mixers = { alc662_ecs_mixer, alc662_capture_mixer },
.init_verbs = { alc662_init_verbs,
alc662_ecs_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16118,7 +15963,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_eeepc_inithook,
},
[ALC663_ASUS_M51VA] = {
- .mixers = { alc663_m51va_mixer },
+ .mixers = { alc663_m51va_mixer, alc662_capture_mixer},
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16130,7 +15975,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_m51va_inithook,
},
[ALC663_ASUS_G71V] = {
- .mixers = { alc663_g71v_mixer },
+ .mixers = { alc663_g71v_mixer, alc662_capture_mixer},
.init_verbs = { alc662_init_verbs, alc663_g71v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16142,7 +15987,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_g71v_inithook,
},
[ALC663_ASUS_H13] = {
- .mixers = { alc663_m51va_mixer },
+ .mixers = { alc663_m51va_mixer, alc662_capture_mixer},
.init_verbs = { alc662_init_verbs, alc663_m51va_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16153,7 +15998,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_m51va_inithook,
},
[ALC663_ASUS_G50V] = {
- .mixers = { alc663_g50v_mixer },
+ .mixers = { alc663_g50v_mixer, alc662_capture_mixer},
.init_verbs = { alc662_init_verbs, alc663_g50v_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
.dac_nids = alc662_dac_nids,
@@ -16165,8 +16010,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_g50v_inithook,
},
[ALC663_ASUS_MODE1] = {
- .mixers = { alc663_m51va_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
+ .mixers = { alc663_m51va_mixer, alc662_auto_capture_mixer },
.init_verbs = { alc662_init_verbs,
alc663_21jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16180,8 +16024,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode1_inithook,
},
[ALC662_ASUS_MODE2] = {
- .mixers = { alc662_1bjd_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
+ .mixers = { alc662_1bjd_mixer, alc662_auto_capture_mixer },
.init_verbs = { alc662_init_verbs,
alc662_1bjd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16194,8 +16037,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc662_mode2_inithook,
},
[ALC663_ASUS_MODE3] = {
- .mixers = { alc663_two_hp_m1_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
+ .mixers = { alc663_two_hp_m1_mixer, alc662_auto_capture_mixer },
.init_verbs = { alc662_init_verbs,
alc663_two_hp_amic_m1_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16209,8 +16051,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode3_inithook,
},
[ALC663_ASUS_MODE4] = {
- .mixers = { alc663_asus_21jd_clfe_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
+ .mixers = { alc663_asus_21jd_clfe_mixer,
+ alc662_auto_capture_mixer},
.init_verbs = { alc662_init_verbs,
alc663_21jd_amic_init_verbs},
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16224,8 +16066,8 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode4_inithook,
},
[ALC663_ASUS_MODE5] = {
- .mixers = { alc663_asus_15jd_clfe_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
+ .mixers = { alc663_asus_15jd_clfe_mixer,
+ alc662_auto_capture_mixer },
.init_verbs = { alc662_init_verbs,
alc663_15jd_amic_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16239,8 +16081,7 @@ static struct alc_config_preset alc662_presets[] = {
.init_hook = alc663_mode5_inithook,
},
[ALC663_ASUS_MODE6] = {
- .mixers = { alc663_two_hp_m2_mixer },
- .cap_mixer = alc662_auto_capture_mixer,
+ .mixers = { alc663_two_hp_m2_mixer, alc662_auto_capture_mixer },
.init_verbs = { alc662_init_verbs,
alc663_two_hp_amic_m2_init_verbs },
.num_dacs = ARRAY_SIZE(alc662_dac_nids),
@@ -16501,20 +16342,24 @@ static int alc662_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_out_pin)
spec->multiout.dig_out_nid = ALC880_DIGOUT_NID;
- if (spec->kctls.list)
- add_mixer(spec, spec->kctls.list);
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->num_mux_defs = 1;
spec->input_mux = &spec->private_imux;
- add_verb(spec, alc662_auto_init_verbs);
+ spec->init_verbs[spec->num_init_verbs++] = alc662_auto_init_verbs;
if (codec->vendor_id == 0x10ec0663)
- add_verb(spec, alc663_auto_init_verbs);
+ spec->init_verbs[spec->num_init_verbs++] =
+ alc663_auto_init_verbs;
err = alc_auto_add_mic_boost(codec);
if (err < 0)
return err;
+ spec->mixers[spec->num_mixers] = alc662_capture_mixer;
+ spec->num_mixers++;
+
store_pin_configs(codec);
return 1;
}
@@ -16590,10 +16435,6 @@ static int patch_alc662(struct hda_codec *codec)
spec->adc_nids = alc662_adc_nids;
spec->num_adc_nids = ARRAY_SIZE(alc662_adc_nids);
spec->capsrc_nids = alc662_capsrc_nids;
- spec->is_mix_capture = 1;
-
- if (!spec->cap_mixer)
- set_capture_mixer(spec);
spec->vmaster_nid = 0x02;
@@ -16604,7 +16445,6 @@ static int patch_alc662(struct hda_codec *codec)
if (!spec->loopback.amplist)
spec->loopback.amplist = alc662_loopbacks;
#endif
- codec->proc_widget_hook = print_realtek_coef;
return 0;
}
@@ -16612,7 +16452,7 @@ static int patch_alc662(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_realtek[] = {
+struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0260, .name = "ALC260", .patch = patch_alc260 },
{ .id = 0x10ec0262, .name = "ALC262", .patch = patch_alc262 },
{ .id = 0x10ec0267, .name = "ALC267", .patch = patch_alc268 },
@@ -16644,26 +16484,3 @@ static struct hda_codec_preset snd_hda_preset_realtek[] = {
{ .id = 0x10ec0889, .name = "ALC889", .patch = patch_alc883 },
{} /* terminator */
};
-
-MODULE_ALIAS("snd-hda-codec-id:10ec*");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Realtek HD-audio codec");
-
-static struct hda_codec_preset_list realtek_list = {
- .preset = snd_hda_preset_realtek,
- .owner = THIS_MODULE,
-};
-
-static int __init patch_realtek_init(void)
-{
- return snd_hda_add_codec_preset(&realtek_list);
-}
-
-static void __exit patch_realtek_exit(void)
-{
- snd_hda_delete_codec_preset(&realtek_list);
-}
-
-module_init(patch_realtek_init)
-module_exit(patch_realtek_exit)
diff --git a/sound/pci/hda/patch_si3054.c b/sound/pci/hda/patch_si3054.c
index 43b436c5d01b..9332b63e406c 100644
--- a/sound/pci/hda/patch_si3054.c
+++ b/sound/pci/hda/patch_si3054.c
@@ -28,6 +28,7 @@
#include <sound/core.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_patch.h"
/* si3054 verbs */
#define SI3054_VERB_READ_NODE 0x900
@@ -282,7 +283,7 @@ static int patch_si3054(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_si3054[] = {
+struct hda_codec_preset snd_hda_preset_si3054[] = {
{ .id = 0x163c3055, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x163c3155, .name = "Si3054", .patch = patch_si3054 },
{ .id = 0x11c13026, .name = "Si3054", .patch = patch_si3054 },
@@ -300,35 +301,3 @@ static struct hda_codec_preset snd_hda_preset_si3054[] = {
{}
};
-MODULE_ALIAS("snd-hda-codec-id:163c3055");
-MODULE_ALIAS("snd-hda-codec-id:163c3155");
-MODULE_ALIAS("snd-hda-codec-id:11c13026");
-MODULE_ALIAS("snd-hda-codec-id:11c13055");
-MODULE_ALIAS("snd-hda-codec-id:11c13155");
-MODULE_ALIAS("snd-hda-codec-id:10573055");
-MODULE_ALIAS("snd-hda-codec-id:10573057");
-MODULE_ALIAS("snd-hda-codec-id:10573155");
-MODULE_ALIAS("snd-hda-codec-id:11063288");
-MODULE_ALIAS("snd-hda-codec-id:15433155");
-MODULE_ALIAS("snd-hda-codec-id:18540018");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("Si3054 HD-audio modem codec");
-
-static struct hda_codec_preset_list si3054_list = {
- .preset = snd_hda_preset_si3054,
- .owner = THIS_MODULE,
-};
-
-static int __init patch_si3054_init(void)
-{
- return snd_hda_add_codec_preset(&si3054_list);
-}
-
-static void __exit patch_si3054_exit(void)
-{
- snd_hda_delete_codec_preset(&si3054_list);
-}
-
-module_init(patch_si3054_init)
-module_exit(patch_si3054_exit)
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 4c851fd55565..5dd3e89f620a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -30,17 +30,17 @@
#include <linux/pci.h>
#include <sound/core.h>
#include <sound/asoundef.h>
-#include <sound/jack.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_patch.h"
#include "hda_beep.h"
-enum {
- STAC_VREF_EVENT = 1,
- STAC_INSERT_EVENT,
- STAC_PWR_EVENT,
- STAC_HP_EVENT,
-};
+#define NUM_CONTROL_ALLOC 32
+
+#define STAC_VREF_EVENT 0x00
+#define STAC_INSERT_EVENT 0x10
+#define STAC_PWR_EVENT 0x20
+#define STAC_HP_EVENT 0x30
enum {
STAC_REF,
@@ -135,19 +135,6 @@ enum {
STAC_927X_MODELS
};
-struct sigmatel_event {
- hda_nid_t nid;
- unsigned char type;
- unsigned char tag;
- int data;
-};
-
-struct sigmatel_jack {
- hda_nid_t nid;
- int type;
- struct snd_jack *jack;
-};
-
struct sigmatel_spec {
struct snd_kcontrol_new *mixers[4];
unsigned int num_mixers;
@@ -181,12 +168,6 @@ struct sigmatel_spec {
hda_nid_t *pwr_nids;
hda_nid_t *dac_list;
- /* jack detection */
- struct snd_array jacks;
-
- /* events */
- struct snd_array events;
-
/* playback */
struct hda_input_mux *mono_mux;
struct hda_input_mux *amp_mux;
@@ -216,6 +197,7 @@ struct sigmatel_spec {
hda_nid_t *pin_nids;
unsigned int num_pins;
unsigned int *pin_configs;
+ unsigned int *bios_pin_configs;
/* codec specific stuff */
struct hda_verb *init;
@@ -243,7 +225,8 @@ struct sigmatel_spec {
/* dynamic controls and input_mux */
struct auto_pin_cfg autocfg;
- struct snd_array kctls;
+ unsigned int num_kctl_alloc, num_kctl_used;
+ struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_dimux;
struct hda_input_mux private_imux;
struct hda_input_mux private_smux;
@@ -589,12 +572,12 @@ static int stac92xx_smux_enum_put(struct snd_kcontrol *kcontrol,
else
nid = codec->slave_dig_outs[smux_idx - 1];
if (spec->cur_smux[smux_idx] == smux->num_items - 1)
- val = HDA_AMP_MUTE;
+ val = AMP_OUT_MUTE;
else
- val = 0;
+ val = AMP_OUT_UNMUTE;
/* un/mute SPDIF out */
- snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0,
- HDA_AMP_MUTE, val);
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_AMP_GAIN_MUTE, val);
}
return 0;
}
@@ -1253,14 +1236,9 @@ static const char *slave_sws[] = {
NULL
};
-static void stac92xx_free_kctls(struct hda_codec *codec);
-static int stac92xx_add_jack(struct hda_codec *codec, hda_nid_t nid, int type);
-
static int stac92xx_build_controls(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
- struct auto_pin_cfg *cfg = &spec->autocfg;
- hda_nid_t nid;
int err;
int i;
@@ -1275,7 +1253,7 @@ static int stac92xx_build_controls(struct hda_codec *codec)
}
if (spec->num_dmuxes > 0) {
stac_dmux_mixer.count = spec->num_dmuxes;
- err = snd_hda_ctl_add(codec,
+ err = snd_ctl_add(codec->bus->card,
snd_ctl_new1(&stac_dmux_mixer, codec));
if (err < 0)
return err;
@@ -1330,37 +1308,6 @@ static int stac92xx_build_controls(struct hda_codec *codec)
return err;
}
- stac92xx_free_kctls(codec); /* no longer needed */
-
- /* create jack input elements */
- if (spec->hp_detect) {
- for (i = 0; i < cfg->hp_outs; i++) {
- int type = SND_JACK_HEADPHONE;
- nid = cfg->hp_pins[i];
- /* jack detection */
- if (cfg->hp_outs == i)
- type |= SND_JACK_LINEOUT;
- err = stac92xx_add_jack(codec, nid, type);
- if (err < 0)
- return err;
- }
- }
- for (i = 0; i < cfg->line_outs; i++) {
- err = stac92xx_add_jack(codec, cfg->line_out_pins[i],
- SND_JACK_LINEOUT);
- if (err < 0)
- return err;
- }
- for (i = 0; i < AUTO_PIN_LAST; i++) {
- nid = cfg->input_pins[i];
- if (nid) {
- err = stac92xx_add_jack(codec, nid,
- SND_JACK_MICROPHONE);
- if (err < 0)
- return err;
- }
- }
-
return 0;
}
@@ -2246,11 +2193,12 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
int i;
struct sigmatel_spec *spec = codec->spec;
- kfree(spec->pin_configs);
- spec->pin_configs = kcalloc(spec->num_pins, sizeof(*spec->pin_configs),
- GFP_KERNEL);
- if (!spec->pin_configs)
- return -ENOMEM;
+ if (! spec->bios_pin_configs) {
+ spec->bios_pin_configs = kcalloc(spec->num_pins,
+ sizeof(*spec->bios_pin_configs), GFP_KERNEL);
+ if (! spec->bios_pin_configs)
+ return -ENOMEM;
+ }
for (i = 0; i < spec->num_pins; i++) {
hda_nid_t nid = spec->pin_nids[i];
@@ -2260,7 +2208,7 @@ static int stac92xx_save_bios_config_regs(struct hda_codec *codec)
AC_VERB_GET_CONFIG_DEFAULT, 0x00);
snd_printdd(KERN_INFO "hda_codec: pin nid %2.2x bios pin config %8.8x\n",
nid, pin_cfg);
- spec->pin_configs[i] = pin_cfg;
+ spec->bios_pin_configs[i] = pin_cfg;
}
return 0;
@@ -2302,39 +2250,6 @@ static void stac92xx_set_config_regs(struct hda_codec *codec)
spec->pin_configs[i]);
}
-static int stac_save_pin_cfgs(struct hda_codec *codec, unsigned int *pins)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (!pins)
- return stac92xx_save_bios_config_regs(codec);
-
- kfree(spec->pin_configs);
- spec->pin_configs = kmemdup(pins,
- spec->num_pins * sizeof(*pins),
- GFP_KERNEL);
- if (!spec->pin_configs)
- return -ENOMEM;
-
- stac92xx_set_config_regs(codec);
- return 0;
-}
-
-static void stac_change_pin_config(struct hda_codec *codec, hda_nid_t nid,
- unsigned int cfg)
-{
- struct sigmatel_spec *spec = codec->spec;
- int i;
-
- for (i = 0; i < spec->num_pins; i++) {
- if (spec->pin_nids[i] == nid) {
- spec->pin_configs[i] = cfg;
- stac92xx_set_config_reg(codec, nid, cfg);
- break;
- }
- }
-}
-
/*
* Analog playback callbacks
*/
@@ -2412,7 +2327,7 @@ static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
if (spec->powerdown_adcs) {
msleep(40);
- snd_hda_codec_write(codec, nid, 0,
+ snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D0);
}
snd_hda_codec_setup_stream(codec, nid, stream_tag, 0, format);
@@ -2428,7 +2343,7 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
snd_hda_codec_cleanup_stream(codec, nid);
if (spec->powerdown_adcs)
- snd_hda_codec_write(codec, nid, 0,
+ snd_hda_codec_write_cache(codec, nid, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
return 0;
}
@@ -2560,9 +2475,6 @@ static int stac92xx_hp_switch_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
- unsigned char type);
-
static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -2575,7 +2487,7 @@ static int stac92xx_hp_switch_put(struct snd_kcontrol *kcontrol,
/* check to be sure that the ports are upto date with
* switch changes
*/
- stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
+ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
return 1;
}
@@ -2615,7 +2527,7 @@ static int stac92xx_io_switch_put(struct snd_kcontrol *kcontrol, struct snd_ctl_
* appropriately according to the pin direction
*/
if (spec->hp_detect)
- stac_issue_unsol_event(codec, nid, STAC_HP_EVENT);
+ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
return 1;
}
@@ -2710,16 +2622,28 @@ static int stac92xx_add_control_temp(struct sigmatel_spec *spec,
{
struct snd_kcontrol_new *knew;
- snd_array_init(&spec->kctls, sizeof(*knew), 32);
- knew = snd_array_new(&spec->kctls);
- if (!knew)
- return -ENOMEM;
+ if (spec->num_kctl_used >= spec->num_kctl_alloc) {
+ int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
+
+ knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL); /* array + terminator */
+ if (! knew)
+ return -ENOMEM;
+ if (spec->kctl_alloc) {
+ memcpy(knew, spec->kctl_alloc, sizeof(*knew) * spec->num_kctl_alloc);
+ kfree(spec->kctl_alloc);
+ }
+ spec->kctl_alloc = knew;
+ spec->num_kctl_alloc = num;
+ }
+
+ knew = &spec->kctl_alloc[spec->num_kctl_used];
*knew = *ktemp;
knew->index = idx;
knew->name = kstrdup(name, GFP_KERNEL);
if (!knew->name)
return -ENOMEM;
knew->private_value = val;
+ spec->num_kctl_used++;
return 0;
}
@@ -3596,8 +3520,8 @@ static int stac92xx_parse_auto_config(struct hda_codec *codec, hda_nid_t dig_out
if (dig_in && spec->autocfg.dig_in_pin)
spec->dig_in_nid = dig_in;
- if (spec->kctls.list)
- spec->mixers[spec->num_mixers++] = spec->kctls.list;
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux;
@@ -3704,8 +3628,8 @@ static int stac9200_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = 0x04;
- if (spec->kctls.list)
- spec->mixers[spec->num_mixers++] = spec->kctls.list;
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->input_mux = &spec->private_imux;
spec->dinput_mux = &spec->private_dimux;
@@ -3749,101 +3673,13 @@ static void stac_gpio_set(struct hda_codec *codec, unsigned int mask,
AC_VERB_SET_GPIO_DATA, gpiostate); /* sync */
}
-static int stac92xx_add_jack(struct hda_codec *codec,
- hda_nid_t nid, int type)
-{
-#ifdef CONFIG_SND_JACK
- struct sigmatel_spec *spec = codec->spec;
- struct sigmatel_jack *jack;
- int def_conf = snd_hda_codec_read(codec, nid,
- 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
- int connectivity = get_defcfg_connect(def_conf);
- char name[32];
-
- if (connectivity && connectivity != AC_JACK_PORT_FIXED)
- return 0;
-
- snd_array_init(&spec->jacks, sizeof(*jack), 32);
- jack = snd_array_new(&spec->jacks);
- if (!jack)
- return -ENOMEM;
- jack->nid = nid;
- jack->type = type;
-
- sprintf(name, "%s at %s %s Jack",
- snd_hda_get_jack_type(def_conf),
- snd_hda_get_jack_connectivity(def_conf),
- snd_hda_get_jack_location(def_conf));
-
- return snd_jack_new(codec->bus->card, name, type, &jack->jack);
-#else
- return 0;
-#endif
-}
-
-static int stac_add_event(struct sigmatel_spec *spec, hda_nid_t nid,
- unsigned char type, int data)
-{
- struct sigmatel_event *event;
-
- snd_array_init(&spec->events, sizeof(*event), 32);
- event = snd_array_new(&spec->events);
- if (!event)
- return -ENOMEM;
- event->nid = nid;
- event->type = type;
- event->tag = spec->events.used;
- event->data = data;
-
- return event->tag;
-}
-
-static struct sigmatel_event *stac_get_event(struct hda_codec *codec,
- hda_nid_t nid, unsigned char type)
-{
- struct sigmatel_spec *spec = codec->spec;
- struct sigmatel_event *event = spec->events.list;
- int i;
-
- for (i = 0; i < spec->events.used; i++, event++) {
- if (event->nid == nid && event->type == type)
- return event;
- }
- return NULL;
-}
-
-static struct sigmatel_event *stac_get_event_from_tag(struct hda_codec *codec,
- unsigned char tag)
-{
- struct sigmatel_spec *spec = codec->spec;
- struct sigmatel_event *event = spec->events.list;
- int i;
-
- for (i = 0; i < spec->events.used; i++, event++) {
- if (event->tag == tag)
- return event;
- }
- return NULL;
-}
-
static void enable_pin_detect(struct hda_codec *codec, hda_nid_t nid,
- unsigned int type)
+ unsigned int event)
{
- struct sigmatel_event *event;
- int tag;
-
- if (!(get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP))
- return;
- event = stac_get_event(codec, nid, type);
- if (event)
- tag = event->tag;
- else
- tag = stac_add_event(codec->spec, nid, type, 0);
- if (tag < 0)
- return;
- snd_hda_codec_write_cache(codec, nid, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | tag);
+ if (get_wcaps(codec, nid) & AC_WCAP_UNSOL_CAP)
+ snd_hda_codec_write_cache(codec, nid, 0,
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ (AC_USRSP_EN | event));
}
static int is_nid_hp_pin(struct auto_pin_cfg *cfg, hda_nid_t nid)
@@ -3865,7 +3701,7 @@ static void stac92xx_power_down(struct hda_codec *codec)
for (dac = spec->dac_list; *dac; dac++)
if (!is_in_dac_nids(spec, *dac) &&
spec->multiout.hp_nid != *dac)
- snd_hda_codec_write(codec, *dac, 0,
+ snd_hda_codec_write_cache(codec, *dac, 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
}
@@ -3884,7 +3720,7 @@ static int stac92xx_init(struct hda_codec *codec)
/* power down adcs initially */
if (spec->powerdown_adcs)
for (i = 0; i < spec->num_adcs; i++)
- snd_hda_codec_write(codec,
+ snd_hda_codec_write_cache(codec,
spec->adc_nids[i], 0,
AC_VERB_SET_POWER_STATE, AC_PWRST_D3);
@@ -3900,51 +3736,37 @@ static int stac92xx_init(struct hda_codec *codec)
/* set up pins */
if (spec->hp_detect) {
/* Enable unsolicited responses on the HP widget */
- for (i = 0; i < cfg->hp_outs; i++) {
- hda_nid_t nid = cfg->hp_pins[i];
- enable_pin_detect(codec, nid, STAC_HP_EVENT);
- }
+ for (i = 0; i < cfg->hp_outs; i++)
+ enable_pin_detect(codec, cfg->hp_pins[i],
+ STAC_HP_EVENT);
/* force to enable the first line-out; the others are set up
* in unsol_event
*/
stac92xx_auto_set_pinctl(codec, spec->autocfg.line_out_pins[0],
- AC_PINCTL_OUT_EN);
+ AC_PINCTL_OUT_EN);
+ stac92xx_auto_init_hp_out(codec);
/* fake event to set up pins */
- stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
- STAC_HP_EVENT);
+ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
} else {
stac92xx_auto_init_multi_out(codec);
stac92xx_auto_init_hp_out(codec);
- for (i = 0; i < cfg->hp_outs; i++)
- stac_toggle_power_map(codec, cfg->hp_pins[i], 1);
}
for (i = 0; i < AUTO_PIN_LAST; i++) {
hda_nid_t nid = cfg->input_pins[i];
if (nid) {
- unsigned int pinctl, conf;
+ unsigned int pinctl;
if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) {
/* for mic pins, force to initialize */
pinctl = stac92xx_get_vref(codec, nid);
- pinctl |= AC_PINCTL_IN_EN;
- stac92xx_auto_set_pinctl(codec, nid, pinctl);
} else {
pinctl = snd_hda_codec_read(codec, nid, 0,
AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
/* if PINCTL already set then skip */
- if (!(pinctl & AC_PINCTL_IN_EN)) {
- pinctl |= AC_PINCTL_IN_EN;
- stac92xx_auto_set_pinctl(codec, nid,
- pinctl);
- }
- }
- conf = snd_hda_codec_read(codec, nid, 0,
- AC_VERB_GET_CONFIG_DEFAULT, 0);
- if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) {
- enable_pin_detect(codec, nid,
- STAC_INSERT_EVENT);
- stac_issue_unsol_event(codec, nid,
- STAC_INSERT_EVENT);
+ if (pinctl & AC_PINCTL_IN_EN)
+ continue;
}
+ pinctl |= AC_PINCTL_IN_EN;
+ stac92xx_auto_set_pinctl(codec, nid, pinctl);
}
}
for (i = 0; i < spec->num_dmics; i++)
@@ -3959,6 +3781,7 @@ static int stac92xx_init(struct hda_codec *codec)
for (i = 0; i < spec->num_pwrs; i++) {
hda_nid_t nid = spec->pwr_nids[i];
int pinctl, def_conf;
+ int event = STAC_PWR_EVENT;
if (is_nid_hp_pin(cfg, nid) && spec->hp_detect)
continue; /* already has an unsol event */
@@ -3981,54 +3804,30 @@ static int stac92xx_init(struct hda_codec *codec)
stac_toggle_power_map(codec, nid, 1);
continue;
}
- if (!stac_get_event(codec, nid, STAC_INSERT_EVENT)) {
- enable_pin_detect(codec, nid, STAC_PWR_EVENT);
- stac_issue_unsol_event(codec, nid, STAC_PWR_EVENT);
- }
+ enable_pin_detect(codec, spec->pwr_nids[i], event | i);
+ codec->patch_ops.unsol_event(codec, (event | i) << 26);
}
if (spec->dac_list)
stac92xx_power_down(codec);
return 0;
}
-static void stac92xx_free_jacks(struct hda_codec *codec)
-{
-#ifdef CONFIG_SND_JACK
- /* free jack instances manually when clearing/reconfiguring */
- struct sigmatel_spec *spec = codec->spec;
- if (!codec->bus->shutdown && spec->jacks.list) {
- struct sigmatel_jack *jacks = spec->jacks.list;
- int i;
- for (i = 0; i < spec->jacks.used; i++)
- snd_device_free(codec->bus->card, &jacks[i].jack);
- }
- snd_array_free(&spec->jacks);
-#endif
-}
-
-static void stac92xx_free_kctls(struct hda_codec *codec)
-{
- struct sigmatel_spec *spec = codec->spec;
-
- if (spec->kctls.list) {
- struct snd_kcontrol_new *kctl = spec->kctls.list;
- int i;
- for (i = 0; i < spec->kctls.used; i++)
- kfree(kctl[i].name);
- }
- snd_array_free(&spec->kctls);
-}
-
static void stac92xx_free(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
+ int i;
if (! spec)
return;
- kfree(spec->pin_configs);
- stac92xx_free_jacks(codec);
- snd_array_free(&spec->events);
+ if (spec->kctl_alloc) {
+ for (i = 0; i < spec->num_kctl_used; i++)
+ kfree(spec->kctl_alloc[i].name);
+ kfree(spec->kctl_alloc);
+ }
+
+ if (spec->bios_pin_configs)
+ kfree(spec->bios_pin_configs);
kfree(spec);
snd_hda_detach_beep_device(codec);
@@ -4075,13 +3874,20 @@ static void stac92xx_reset_pinctl(struct hda_codec *codec, hda_nid_t nid,
pin_ctl & ~flag);
}
-static int get_pin_presence(struct hda_codec *codec, hda_nid_t nid)
+static int get_hp_pin_presence(struct hda_codec *codec, hda_nid_t nid)
{
if (!nid)
return 0;
if (snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_PIN_SENSE, 0x00)
- & (1 << 31))
- return 1;
+ & (1 << 31)) {
+ unsigned int pinctl;
+ pinctl = snd_hda_codec_read(codec, nid, 0,
+ AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
+ if (pinctl & AC_PINCTL_IN_EN)
+ return 0; /* mic- or line-input */
+ else
+ return 1; /* HP-output */
+ }
return 0;
}
@@ -4105,7 +3911,7 @@ static int no_hp_sensing(struct sigmatel_spec *spec, int i)
return 0;
}
-static void stac92xx_hp_detect(struct hda_codec *codec)
+static void stac92xx_hp_detect(struct hda_codec *codec, unsigned int res)
{
struct sigmatel_spec *spec = codec->spec;
struct auto_pin_cfg *cfg = &spec->autocfg;
@@ -4121,14 +3927,7 @@ static void stac92xx_hp_detect(struct hda_codec *codec)
break;
if (no_hp_sensing(spec, i))
continue;
- presence = get_pin_presence(codec, cfg->hp_pins[i]);
- if (presence) {
- unsigned int pinctl;
- pinctl = snd_hda_codec_read(codec, cfg->hp_pins[i], 0,
- AC_VERB_GET_PIN_WIDGET_CONTROL, 0);
- if (pinctl & AC_PINCTL_IN_EN)
- presence = 0; /* mic- or line-input */
- }
+ presence = get_hp_pin_presence(codec, cfg->hp_pins[i]);
}
if (presence) {
@@ -4205,145 +4004,50 @@ static void stac_toggle_power_map(struct hda_codec *codec, hda_nid_t nid,
static void stac92xx_pin_sense(struct hda_codec *codec, hda_nid_t nid)
{
- stac_toggle_power_map(codec, nid, get_pin_presence(codec, nid));
-}
-
-static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid)
-{
- struct sigmatel_spec *spec = codec->spec;
- struct sigmatel_jack *jacks = spec->jacks.list;
-
- if (jacks) {
- int i;
- for (i = 0; i < spec->jacks.used; i++) {
- if (jacks->nid == nid) {
- unsigned int pin_ctl =
- snd_hda_codec_read(codec, nid,
- 0, AC_VERB_GET_PIN_WIDGET_CONTROL,
- 0x00);
- int type = jacks->type;
- if (type == (SND_JACK_LINEOUT
- | SND_JACK_HEADPHONE))
- type = (pin_ctl & AC_PINCTL_HP_EN)
- ? SND_JACK_HEADPHONE : SND_JACK_LINEOUT;
- snd_jack_report(jacks->jack,
- get_pin_presence(codec, nid)
- ? type : 0);
- }
- jacks++;
- }
- }
-}
-
-static void stac_issue_unsol_event(struct hda_codec *codec, hda_nid_t nid,
- unsigned char type)
-{
- struct sigmatel_event *event = stac_get_event(codec, nid, type);
- if (!event)
- return;
- codec->patch_ops.unsol_event(codec, (unsigned)event->tag << 26);
+ stac_toggle_power_map(codec, nid, get_hp_pin_presence(codec, nid));
}
static void stac92xx_unsol_event(struct hda_codec *codec, unsigned int res)
{
struct sigmatel_spec *spec = codec->spec;
- struct sigmatel_event *event;
- int tag, data;
+ int idx = res >> 26 & 0x0f;
- tag = (res >> 26) & 0x7f;
- event = stac_get_event_from_tag(codec, tag);
- if (!event)
- return;
-
- switch (event->type) {
+ switch ((res >> 26) & 0x70) {
case STAC_HP_EVENT:
- stac92xx_hp_detect(codec);
+ stac92xx_hp_detect(codec, res);
/* fallthru */
- case STAC_INSERT_EVENT:
case STAC_PWR_EVENT:
if (spec->num_pwrs > 0)
- stac92xx_pin_sense(codec, event->nid);
- stac92xx_report_jack(codec, event->nid);
+ stac92xx_pin_sense(codec, idx);
break;
- case STAC_VREF_EVENT:
- data = snd_hda_codec_read(codec, codec->afg, 0,
- AC_VERB_GET_GPIO_DATA, 0);
+ case STAC_VREF_EVENT: {
+ int data = snd_hda_codec_read(codec, codec->afg, 0,
+ AC_VERB_GET_GPIO_DATA, 0);
/* toggle VREF state based on GPIOx status */
snd_hda_codec_write(codec, codec->afg, 0, 0x7e0,
- !!(data & (1 << event->data)));
+ !!(data & (1 << idx)));
break;
+ }
}
}
-#ifdef CONFIG_PROC_FS
-static void stac92hd_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- if (nid == codec->afg)
- snd_iprintf(buffer, "Power-Map: 0x%02x\n",
- snd_hda_codec_read(codec, nid, 0, 0x0fec, 0x0));
-}
-
-static void analog_loop_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec,
- unsigned int verb)
-{
- snd_iprintf(buffer, "Analog Loopback: 0x%02x\n",
- snd_hda_codec_read(codec, codec->afg, 0, verb, 0));
-}
-
-/* stac92hd71bxx, stac92hd73xx */
-static void stac92hd7x_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- stac92hd_proc_hook(buffer, codec, nid);
- if (nid == codec->afg)
- analog_loop_proc_hook(buffer, codec, 0xfa0);
-}
-
-static void stac9205_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- if (nid == codec->afg)
- analog_loop_proc_hook(buffer, codec, 0xfe0);
-}
-
-static void stac927x_proc_hook(struct snd_info_buffer *buffer,
- struct hda_codec *codec, hda_nid_t nid)
-{
- if (nid == codec->afg)
- analog_loop_proc_hook(buffer, codec, 0xfeb);
-}
-#else
-#define stac92hd_proc_hook NULL
-#define stac92hd7x_proc_hook NULL
-#define stac9205_proc_hook NULL
-#define stac927x_proc_hook NULL
-#endif
-
#ifdef SND_HDA_NEEDS_RESUME
static int stac92xx_resume(struct hda_codec *codec)
{
struct sigmatel_spec *spec = codec->spec;
stac92xx_set_config_regs(codec);
- stac92xx_init(codec);
+ snd_hda_sequence_write(codec, spec->init);
+ stac_gpio_set(codec, spec->gpio_mask,
+ spec->gpio_dir, spec->gpio_data);
snd_hda_codec_resume_amp(codec);
snd_hda_codec_resume_cache(codec);
- /* fake event to set up pins again to override cached values */
+ /* power down inactive DACs */
+ if (spec->dac_list)
+ stac92xx_power_down(codec);
+ /* invoke unsolicited event to reset the HP state */
if (spec->hp_detect)
- stac_issue_unsol_event(codec, spec->autocfg.hp_pins[0],
- STAC_HP_EVENT);
- return 0;
-}
-
-static int stac92xx_suspend(struct hda_codec *codec, pm_message_t state)
-{
- struct sigmatel_spec *spec = codec->spec;
- if (spec->eapd_mask)
- stac_gpio_set(codec, spec->gpio_mask,
- spec->gpio_dir, spec->gpio_data &
- ~spec->eapd_mask);
+ codec->patch_ops.unsol_event(codec, STAC_HP_EVENT << 26);
return 0;
}
#endif
@@ -4355,7 +4059,6 @@ static struct hda_codec_ops stac92xx_patch_ops = {
.free = stac92xx_free,
.unsol_event = stac92xx_unsol_event,
#ifdef SND_HDA_NEEDS_RESUME
- .suspend = stac92xx_suspend,
.resume = stac92xx_resume,
#endif
};
@@ -4378,12 +4081,14 @@ static int patch_stac9200(struct hda_codec *codec)
if (spec->board_config < 0) {
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9200, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
- stac9200_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
+ }
+ spec->pin_configs = spec->bios_pin_configs;
+ } else {
+ spec->pin_configs = stac9200_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
}
spec->multiout.max_channels = 2;
@@ -4439,12 +4144,14 @@ static int patch_stac925x(struct hda_codec *codec)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC925x,"
"using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
- stac925x_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
+ }
+ spec->pin_configs = spec->bios_pin_configs;
+ } else if (stac925x_brd_tbl[spec->board_config] != NULL){
+ spec->pin_configs = stac925x_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
}
spec->multiout.max_channels = 2;
@@ -4526,12 +4233,14 @@ again:
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD73XX, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
- stac92hd73xx_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
+ }
+ spec->pin_configs = spec->bios_pin_configs;
+ } else {
+ spec->pin_configs = stac92hd73xx_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
}
spec->multiout.num_dacs = snd_hda_get_connections(codec, 0x0a,
@@ -4644,8 +4353,6 @@ again:
codec->patch_ops = stac92xx_patch_ops;
- codec->proc_widget_hook = stac92hd7x_proc_hook;
-
return 0;
}
@@ -4706,12 +4413,14 @@ again:
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD83XXX, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
- stac92hd83xxx_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
+ }
+ spec->pin_configs = spec->bios_pin_configs;
+ } else {
+ spec->pin_configs = stac92hd83xxx_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
}
err = stac92xx_parse_auto_config(codec, 0x1d, 0);
@@ -4732,11 +4441,57 @@ again:
codec->patch_ops = stac92xx_patch_ops;
- codec->proc_widget_hook = stac92hd_proc_hook;
-
return 0;
}
+#ifdef SND_HDA_NEEDS_RESUME
+static void stac92hd71xx_set_power_state(struct hda_codec *codec, int pwr)
+{
+ struct sigmatel_spec *spec = codec->spec;
+ int i;
+ snd_hda_codec_write_cache(codec, codec->afg, 0,
+ AC_VERB_SET_POWER_STATE, pwr);
+
+ msleep(1);
+ for (i = 0; i < spec->num_adcs; i++) {
+ snd_hda_codec_write_cache(codec,
+ spec->adc_nids[i], 0,
+ AC_VERB_SET_POWER_STATE, pwr);
+ }
+};
+
+static int stac92hd71xx_resume(struct hda_codec *codec)
+{
+ stac92hd71xx_set_power_state(codec, AC_PWRST_D0);
+ return stac92xx_resume(codec);
+}
+
+static int stac92hd71xx_suspend(struct hda_codec *codec, pm_message_t state)
+{
+ struct sigmatel_spec *spec = codec->spec;
+
+ stac92hd71xx_set_power_state(codec, AC_PWRST_D3);
+ if (spec->eapd_mask)
+ stac_gpio_set(codec, spec->gpio_mask,
+ spec->gpio_dir, spec->gpio_data &
+ ~spec->eapd_mask);
+ return 0;
+};
+
+#endif
+
+static struct hda_codec_ops stac92hd71bxx_patch_ops = {
+ .build_controls = stac92xx_build_controls,
+ .build_pcms = stac92xx_build_pcms,
+ .init = stac92xx_init,
+ .free = stac92xx_free,
+ .unsol_event = stac92xx_unsol_event,
+#ifdef SND_HDA_NEEDS_RESUME
+ .resume = stac92hd71xx_resume,
+ .suspend = stac92hd71xx_suspend,
+#endif
+};
+
static struct hda_input_mux stac92hd71bxx_dmux = {
.num_items = 4,
.items = {
@@ -4772,12 +4527,14 @@ again:
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
" STAC92HD71BXX, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
- stac92hd71bxx_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
+ }
+ spec->pin_configs = spec->bios_pin_configs;
+ } else {
+ spec->pin_configs = stac92hd71bxx_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
}
if (spec->board_config > STAC_92HD71BXX_REF) {
@@ -4800,21 +4557,21 @@ again:
switch (spec->board_config) {
case STAC_HP_M4:
/* Enable VREF power saving on GPIO1 detect */
- err = stac_add_event(spec, codec->afg,
- STAC_VREF_EVENT, 0x02);
- if (err < 0)
- return err;
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x02);
snd_hda_codec_write_cache(codec, codec->afg, 0,
- AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | err);
+ AC_VERB_SET_UNSOLICITED_ENABLE,
+ (AC_USRSP_EN | STAC_VREF_EVENT | 0x01));
spec->gpio_mask |= 0x02;
break;
}
if ((codec->revision_id & 0xf) == 0 ||
- (codec->revision_id & 0xf) == 1)
+ (codec->revision_id & 0xf) == 1) {
+#ifdef SND_HDA_NEEDS_RESUME
+ codec->patch_ops = stac92hd71bxx_patch_ops;
+#endif
spec->stream_delay = 40; /* 40 milliseconds */
+ }
/* no output amps */
spec->num_pwrs = 0;
@@ -4823,11 +4580,15 @@ again:
/* disable VSW */
spec->init = &stac92hd71bxx_analog_core_init[HD_DISABLE_PORTF];
- stac_change_pin_config(codec, 0xf, 0x40f000f0);
+ stac92xx_set_config_reg(codec, 0xf, 0x40f000f0);
break;
case 0x111d7603: /* 6 Port with Analog Mixer */
- if ((codec->revision_id & 0xf) == 1)
+ if ((codec->revision_id & 0xf) == 1) {
+#ifdef SND_HDA_NEEDS_RESUME
+ codec->patch_ops = stac92hd71bxx_patch_ops;
+#endif
spec->stream_delay = 40; /* 40 milliseconds */
+ }
/* no output amps */
spec->num_pwrs = 0;
@@ -4857,7 +4618,7 @@ again:
switch (spec->board_config) {
case STAC_HP_M4:
/* enable internal microphone */
- stac_change_pin_config(codec, 0x0e, 0x01813040);
+ stac92xx_set_config_reg(codec, 0x0e, 0x01813040);
stac92xx_auto_set_pinctl(codec, 0x0e,
AC_PINCTL_IN_EN | AC_PINCTL_VREF_80);
/* fallthru */
@@ -4902,8 +4663,6 @@ again:
return err;
}
- codec->proc_widget_hook = stac92hd7x_proc_hook;
-
return 0;
};
@@ -4965,12 +4724,14 @@ static int patch_stac922x(struct hda_codec *codec)
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC922x, "
"using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
- stac922x_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
+ }
+ spec->pin_configs = spec->bios_pin_configs;
+ } else if (stac922x_brd_tbl[spec->board_config] != NULL) {
+ spec->pin_configs = stac922x_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
}
spec->adc_nids = stac922x_adc_nids;
@@ -5033,12 +4794,14 @@ static int patch_stac927x(struct hda_codec *codec)
snd_printdd(KERN_INFO "hda_codec: Unknown model for"
"STAC927x, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
- stac927x_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
+ }
+ spec->pin_configs = spec->bios_pin_configs;
+ } else {
+ spec->pin_configs = stac927x_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
}
spec->digbeep_nid = 0x23;
@@ -5068,15 +4831,15 @@ static int patch_stac927x(struct hda_codec *codec)
case 0x10280209:
case 0x1028022e:
/* correct the device field to SPDIF out */
- stac_change_pin_config(codec, 0x21, 0x01442070);
+ stac92xx_set_config_reg(codec, 0x21, 0x01442070);
break;
};
/* configure the analog microphone on some laptops */
- stac_change_pin_config(codec, 0x0c, 0x90a79130);
+ stac92xx_set_config_reg(codec, 0x0c, 0x90a79130);
/* correct the front output jack as a hp out */
- stac_change_pin_config(codec, 0x0f, 0x0227011f);
+ stac92xx_set_config_reg(codec, 0x0f, 0x0227011f);
/* correct the front input jack as a mic */
- stac_change_pin_config(codec, 0x0e, 0x02a79130);
+ stac92xx_set_config_reg(codec, 0x0e, 0x02a79130);
/* fallthru */
case STAC_DELL_3ST:
/* GPIO2 High = Enable EAPD */
@@ -5124,8 +4887,6 @@ static int patch_stac927x(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops;
- codec->proc_widget_hook = stac927x_proc_hook;
-
/*
* !!FIXME!!
* The STAC927x seem to require fairly long delays for certain
@@ -5160,12 +4921,14 @@ static int patch_stac9205(struct hda_codec *codec)
if (spec->board_config < 0) {
snd_printdd(KERN_INFO "hda_codec: Unknown model for STAC9205, using BIOS defaults\n");
err = stac92xx_save_bios_config_regs(codec);
- } else
- err = stac_save_pin_cfgs(codec,
- stac9205_brd_tbl[spec->board_config]);
- if (err < 0) {
- stac92xx_free(codec);
- return err;
+ if (err < 0) {
+ stac92xx_free(codec);
+ return err;
+ }
+ spec->pin_configs = spec->bios_pin_configs;
+ } else {
+ spec->pin_configs = stac9205_brd_tbl[spec->board_config];
+ stac92xx_set_config_regs(codec);
}
spec->digbeep_nid = 0x23;
@@ -5192,18 +4955,15 @@ static int patch_stac9205(struct hda_codec *codec)
switch (spec->board_config){
case STAC_9205_DELL_M43:
/* Enable SPDIF in/out */
- stac_change_pin_config(codec, 0x1f, 0x01441030);
- stac_change_pin_config(codec, 0x20, 0x1c410030);
+ stac92xx_set_config_reg(codec, 0x1f, 0x01441030);
+ stac92xx_set_config_reg(codec, 0x20, 0x1c410030);
/* Enable unsol response for GPIO4/Dock HP connection */
- err = stac_add_event(spec, codec->afg, STAC_VREF_EVENT, 0x01);
- if (err < 0)
- return err;
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_GPIO_UNSOLICITED_RSP_MASK, 0x10);
snd_hda_codec_write_cache(codec, codec->afg, 0,
AC_VERB_SET_UNSOLICITED_ENABLE,
- AC_USRSP_EN | err);
+ (AC_USRSP_EN | STAC_HP_EVENT));
spec->gpio_dir = 0x0b;
spec->eapd_mask = 0x01;
@@ -5241,8 +5001,6 @@ static int patch_stac9205(struct hda_codec *codec)
codec->patch_ops = stac92xx_patch_ops;
- codec->proc_widget_hook = stac9205_proc_hook;
-
return 0;
}
@@ -5299,11 +5057,29 @@ static struct hda_verb vaio_ar_init[] = {
{}
};
+/* bind volumes of both NID 0x02 and 0x05 */
+static struct hda_bind_ctls vaio_bind_master_vol = {
+ .ops = &snd_hda_bind_vol,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
+ 0
+ },
+};
+
+/* bind volumes of both NID 0x02 and 0x05 */
+static struct hda_bind_ctls vaio_bind_master_sw = {
+ .ops = &snd_hda_bind_sw,
+ .values = {
+ HDA_COMPOSE_AMP_VAL(0x02, 3, 0, HDA_OUTPUT),
+ HDA_COMPOSE_AMP_VAL(0x05, 3, 0, HDA_OUTPUT),
+ 0,
+ },
+};
+
static struct snd_kcontrol_new vaio_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
+ HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
+ HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -5319,10 +5095,8 @@ static struct snd_kcontrol_new vaio_mixer[] = {
};
static struct snd_kcontrol_new vaio_ar_mixer[] = {
- HDA_CODEC_VOLUME("Headphone Playback Volume", 0x02, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Headphone Playback Switch", 0x02, 0, HDA_OUTPUT),
- HDA_CODEC_VOLUME("Speaker Playback Volume", 0x05, 0, HDA_OUTPUT),
- HDA_CODEC_MUTE("Speaker Playback Switch", 0x05, 0, HDA_OUTPUT),
+ HDA_BIND_VOL("Master Playback Volume", &vaio_bind_master_vol),
+ HDA_BIND_SW("Master Playback Switch", &vaio_bind_master_sw),
/* HDA_CODEC_VOLUME("CD Capture Volume", 0x07, 0, HDA_INPUT), */
HDA_CODEC_VOLUME("Capture Volume", 0x09, 0, HDA_INPUT),
HDA_CODEC_MUTE("Capture Switch", 0x09, 0, HDA_INPUT),
@@ -5363,7 +5137,7 @@ static int stac9872_vaio_init(struct hda_codec *codec)
static void stac9872_vaio_hp_detect(struct hda_codec *codec, unsigned int res)
{
- if (get_pin_presence(codec, 0x0a)) {
+ if (get_hp_pin_presence(codec, 0x0a)) {
stac92xx_reset_pinctl(codec, 0x0f, AC_PINCTL_OUT_EN);
stac92xx_set_pinctl(codec, 0x0a, AC_PINCTL_OUT_EN);
} else {
@@ -5474,7 +5248,7 @@ static int patch_stac9872(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
+struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x83847690, .name = "STAC9200", .patch = patch_stac9200 },
{ .id = 0x83847882, .name = "STAC9220 A1", .patch = patch_stac922x },
{ .id = 0x83847680, .name = "STAC9221 A1", .patch = patch_stac922x },
@@ -5538,27 +5312,3 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = {
{ .id = 0x111d76b7, .name = "92HD71B5X", .patch = patch_stac92hd71bxx },
{} /* terminator */
};
-
-MODULE_ALIAS("snd-hda-codec-id:8384*");
-MODULE_ALIAS("snd-hda-codec-id:111d*");
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("IDT/Sigmatel HD-audio codec");
-
-static struct hda_codec_preset_list sigmatel_list = {
- .preset = snd_hda_preset_sigmatel,
- .owner = THIS_MODULE,
-};
-
-static int __init patch_sigmatel_init(void)
-{
- return snd_hda_add_codec_preset(&sigmatel_list);
-}
-
-static void __exit patch_sigmatel_exit(void)
-{
- snd_hda_delete_codec_preset(&sigmatel_list);
-}
-
-module_init(patch_sigmatel_init)
-module_exit(patch_sigmatel_exit)
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c
index 6e4d01d1d502..63e4871e5d8f 100644
--- a/sound/pci/hda/patch_via.c
+++ b/sound/pci/hda/patch_via.c
@@ -47,11 +47,15 @@
#include <sound/asoundef.h>
#include "hda_codec.h"
#include "hda_local.h"
+#include "hda_patch.h"
/* amp values */
#define AMP_VAL_IDX_SHIFT 19
#define AMP_VAL_IDX_MASK (0x0f<<19)
+#define NUM_CONTROL_ALLOC 32
+#define NUM_VERB_ALLOC 32
+
/* Pin Widget NID */
#define VT1708_HP_NID 0x13
#define VT1708_DIGOUT_NID 0x14
@@ -141,6 +145,8 @@ enum {
AUTO_SEQ_SIDE
};
+#define get_amp_nid(kc) ((kc)->private_value & 0xffff)
+
/* Some VT1708S based boards gets the micboost setting wrong, so we have
* to apply some brute-force and re-write the TLV's by software. */
static int mic_boost_tlv(struct snd_kcontrol *kcontrol, int op_flag,
@@ -221,7 +227,8 @@ struct via_spec {
/* dynamic controls, init_verbs and input_mux */
struct auto_pin_cfg autocfg;
- struct snd_array kctls;
+ unsigned int num_kctl_alloc, num_kctl_used;
+ struct snd_kcontrol_new *kctl_alloc;
struct hda_input_mux private_imux[2];
hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS];
@@ -265,31 +272,33 @@ static int via_add_control(struct via_spec *spec, int type, const char *name,
{
struct snd_kcontrol_new *knew;
- snd_array_init(&spec->kctls, sizeof(*knew), 32);
- knew = snd_array_new(&spec->kctls);
- if (!knew)
- return -ENOMEM;
+ if (spec->num_kctl_used >= spec->num_kctl_alloc) {
+ int num = spec->num_kctl_alloc + NUM_CONTROL_ALLOC;
+
+ /* array + terminator */
+ knew = kcalloc(num + 1, sizeof(*knew), GFP_KERNEL);
+ if (!knew)
+ return -ENOMEM;
+ if (spec->kctl_alloc) {
+ memcpy(knew, spec->kctl_alloc,
+ sizeof(*knew) * spec->num_kctl_alloc);
+ kfree(spec->kctl_alloc);
+ }
+ spec->kctl_alloc = knew;
+ spec->num_kctl_alloc = num;
+ }
+
+ knew = &spec->kctl_alloc[spec->num_kctl_used];
*knew = vt1708_control_templates[type];
knew->name = kstrdup(name, GFP_KERNEL);
+
if (!knew->name)
return -ENOMEM;
knew->private_value = val;
+ spec->num_kctl_used++;
return 0;
}
-static void via_free_kctls(struct hda_codec *codec)
-{
- struct via_spec *spec = codec->spec;
-
- if (spec->kctls.list) {
- struct snd_kcontrol_new *kctl = spec->kctls.list;
- int i;
- for (i = 0; i < spec->kctls.used; i++)
- kfree(kctl[i].name);
- }
- snd_array_free(&spec->kctls);
-}
-
/* create input playback/capture controls for the given pin */
static int via_new_analog_input(struct via_spec *spec, hda_nid_t pin,
const char *ctlname, int idx, int mix_nid)
@@ -887,7 +896,6 @@ static int via_build_controls(struct hda_codec *codec)
if (err < 0)
return err;
}
- via_free_kctls(codec); /* no longer needed */
return 0;
}
@@ -933,11 +941,17 @@ static int via_build_pcms(struct hda_codec *codec)
static void via_free(struct hda_codec *codec)
{
struct via_spec *spec = codec->spec;
+ unsigned int i;
if (!spec)
return;
- via_free_kctls(codec);
+ if (spec->kctl_alloc) {
+ for (i = 0; i < spec->num_kctl_used; i++)
+ kfree(spec->kctl_alloc[i].name);
+ kfree(spec->kctl_alloc);
+ }
+
kfree(codec->spec);
}
@@ -1359,8 +1373,8 @@ static int vt1708_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708_DIGIN_NID;
- if (spec->kctls.list)
- spec->mixers[spec->num_mixers++] = spec->kctls.list;
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->init_verbs[spec->num_iverbs++] = vt1708_volume_init_verbs;
@@ -1832,8 +1846,8 @@ static int vt1709_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1709_DIGIN_NID;
- if (spec->kctls.list)
- spec->mixers[spec->num_mixers++] = spec->kctls.list;
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->input_mux = &spec->private_imux[0];
@@ -2376,8 +2390,8 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec)
if (spec->autocfg.dig_in_pin)
spec->dig_in_nid = VT1708B_DIGIN_NID;
- if (spec->kctls.list)
- spec->mixers[spec->num_mixers++] = spec->kctls.list;
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->input_mux = &spec->private_imux[0];
@@ -2841,8 +2855,8 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec)
spec->extra_dig_out_nid = 0x15;
- if (spec->kctls.list)
- spec->mixers[spec->num_mixers++] = spec->kctls.list;
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->input_mux = &spec->private_imux[0];
@@ -3160,8 +3174,8 @@ static int vt1702_parse_auto_config(struct hda_codec *codec)
spec->extra_dig_out_nid = 0x1B;
- if (spec->kctls.list)
- spec->mixers[spec->num_mixers++] = spec->kctls.list;
+ if (spec->kctl_alloc)
+ spec->mixers[spec->num_mixers++] = spec->kctl_alloc;
spec->input_mux = &spec->private_imux[0];
@@ -3248,7 +3262,7 @@ static int patch_vt1702(struct hda_codec *codec)
/*
* patch entries
*/
-static struct hda_codec_preset snd_hda_preset_via[] = {
+struct hda_codec_preset snd_hda_preset_via[] = {
{ .id = 0x11061708, .name = "VIA VT1708", .patch = patch_vt1708},
{ .id = 0x11061709, .name = "VIA VT1708", .patch = patch_vt1708},
{ .id = 0x1106170A, .name = "VIA VT1708", .patch = patch_vt1708},
@@ -3319,26 +3333,3 @@ static struct hda_codec_preset snd_hda_preset_via[] = {
.patch = patch_vt1702},
{} /* terminator */
};
-
-MODULE_ALIAS("snd-hda-codec-id:1106*");
-
-static struct hda_codec_preset_list via_list = {
- .preset = snd_hda_preset_via,
- .owner = THIS_MODULE,
-};
-
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("VIA HD-audio codec");
-
-static int __init patch_via_init(void)
-{
- return snd_hda_add_codec_preset(&via_list);
-}
-
-static void __exit patch_via_exit(void)
-{
- snd_hda_delete_codec_preset(&via_list);
-}
-
-module_init(patch_via_init)
-module_exit(patch_via_exit)
diff --git a/sound/pci/ice1712/ice1724.c b/sound/pci/ice1712/ice1724.c
index 0dfa0540ce2c..1b3f11702713 100644
--- a/sound/pci/ice1712/ice1724.c
+++ b/sound/pci/ice1712/ice1724.c
@@ -382,25 +382,23 @@ static irqreturn_t snd_vt1724_interrupt(int irq, void *dev_id)
unsigned char status_mask =
VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX | VT1724_IRQ_MTPCM;
int handled = 0;
+#ifdef CONFIG_SND_DEBUG
int timeout = 0;
+#endif
while (1) {
status = inb(ICEREG1724(ice, IRQSTAT));
status &= status_mask;
if (status == 0)
break;
+#ifdef CONFIG_SND_DEBUG
if (++timeout > 10) {
- status = inb(ICEREG1724(ice, IRQSTAT));
- printk(KERN_ERR "ice1724: Too long irq loop, "
- "status = 0x%x\n", status);
- if (status & VT1724_IRQ_MPU_TX) {
- printk(KERN_ERR "ice1724: Disabling MPU_TX\n");
- outb(inb(ICEREG1724(ice, IRQMASK)) |
- VT1724_IRQ_MPU_TX,
- ICEREG1724(ice, IRQMASK));
- }
+ printk(KERN_ERR
+ "ice1724: Too long irq loop, status = 0x%x\n",
+ status);
break;
}
+#endif
handled = 1;
if (status & VT1724_IRQ_MPU_TX) {
spin_lock(&ice->reg_lock);
@@ -2353,6 +2351,7 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
{
struct snd_ice1712 *ice;
int err;
+ unsigned char mask;
static struct snd_device_ops ops = {
.dev_free = snd_vt1724_dev_free,
};
@@ -2413,9 +2412,9 @@ static int __devinit snd_vt1724_create(struct snd_card *card,
return -EIO;
}
- /* MPU_RX and TX irq masks are cleared later dynamically */
- outb(VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX , ICEREG1724(ice, IRQMASK));
-
+ /* unmask used interrupts */
+ mask = VT1724_IRQ_MPU_RX | VT1724_IRQ_MPU_TX;
+ outb(mask, ICEREG1724(ice, IRQMASK));
/* don't handle FIFO overrun/underruns (just yet),
* since they cause machine lockups
*/
diff --git a/sound/pci/mixart/mixart.c b/sound/pci/mixart/mixart.c
index f23a73577c22..ae7601f353a7 100644
--- a/sound/pci/mixart/mixart.c
+++ b/sound/pci/mixart/mixart.c
@@ -1010,7 +1010,7 @@ static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *
.dev_free = snd_mixart_chip_dev_free,
};
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
snd_printk(KERN_ERR "cannot allocate chip\n");
return -ENOMEM;
@@ -1025,7 +1025,6 @@ static int __devinit snd_mixart_create(struct mixart_mgr *mgr, struct snd_card *
return err;
}
- mgr->chip[idx] = chip;
snd_card_set_dev(card, &mgr->pci->dev);
return 0;
@@ -1378,7 +1377,6 @@ static int __devinit snd_mixart_probe(struct pci_dev *pci,
sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i);
if ((err = snd_mixart_create(mgr, card, i)) < 0) {
- snd_card_free(card);
snd_mixart_free(mgr);
return err;
}
diff --git a/sound/pci/oxygen/oxygen.c b/sound/pci/oxygen/oxygen.c
index de999c6d6dd3..b60f6212745a 100644
--- a/sound/pci/oxygen/oxygen.c
+++ b/sound/pci/oxygen/oxygen.c
@@ -61,7 +61,6 @@ MODULE_PARM_DESC(enable, "enable card");
enum {
MODEL_CMEDIA_REF, /* C-Media's reference design */
MODEL_MERIDIAN, /* AuzenTech X-Meridian */
- MODEL_HALO, /* HT-Omega Claro halo */
};
static struct pci_device_id oxygen_ids[] __devinitdata = {
@@ -75,7 +74,6 @@ static struct pci_device_id oxygen_ids[] __devinitdata = {
{ OXYGEN_PCI_SUBID(0x1a58, 0x0910), .driver_data = MODEL_CMEDIA_REF },
{ OXYGEN_PCI_SUBID(0x415a, 0x5431), .driver_data = MODEL_MERIDIAN },
{ OXYGEN_PCI_SUBID(0x7284, 0x9761), .driver_data = MODEL_CMEDIA_REF },
- { OXYGEN_PCI_SUBID(0x7284, 0x9781), .driver_data = MODEL_HALO },
{ }
};
MODULE_DEVICE_TABLE(pci, oxygen_ids);
@@ -303,8 +301,6 @@ static int generic_probe(struct oxygen *chip, unsigned long driver_data)
PLAYBACK_1_TO_SPDIF |
CAPTURE_0_FROM_I2S_2 |
CAPTURE_1_FROM_SPDIF;
- }
- if (driver_data == MODEL_MERIDIAN || driver_data == MODEL_HALO) {
chip->model.misc_flags = OXYGEN_MISC_MIDI;
chip->model.device_config |= MIDI_OUTPUT | MIDI_INPUT;
}
diff --git a/sound/pci/pcxhr/Makefile b/sound/pci/pcxhr/Makefile
index b06128e918ca..10473c05918d 100644
--- a/sound/pci/pcxhr/Makefile
+++ b/sound/pci/pcxhr/Makefile
@@ -1,2 +1,2 @@
-snd-pcxhr-objs := pcxhr.o pcxhr_hwdep.o pcxhr_mixer.o pcxhr_core.o pcxhr_mix22.o
+snd-pcxhr-objs := pcxhr.o pcxhr_hwdep.o pcxhr_mixer.o pcxhr_core.o
obj-$(CONFIG_SND_PCXHR) += snd-pcxhr.o
diff --git a/sound/pci/pcxhr/pcxhr.c b/sound/pci/pcxhr/pcxhr.c
index 05a1b6cbd72b..73de6e989b3d 100644
--- a/sound/pci/pcxhr/pcxhr.c
+++ b/sound/pci/pcxhr/pcxhr.c
@@ -40,20 +40,18 @@
#include "pcxhr_mixer.h"
#include "pcxhr_hwdep.h"
#include "pcxhr_core.h"
-#include "pcxhr_mix22.h"
#define DRIVER_NAME "pcxhr"
-MODULE_AUTHOR("Markus Bollinger <bollinger@digigram.com>, "
- "Marc Titinger <titinger@digigram.com>");
+MODULE_AUTHOR("Markus Bollinger <bollinger@digigram.com>");
MODULE_DESCRIPTION("Digigram " DRIVER_NAME " " PCXHR_DRIVER_VERSION_STRING);
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Digigram," DRIVER_NAME "}}");
-static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
-static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
-static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;/* Enable this card */
-static int mono[SNDRV_CARDS]; /* capture mono only */
+static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
+static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
+static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
+static int mono[SNDRV_CARDS]; /* capture in mono only */
module_param_array(index, int, NULL, 0444);
MODULE_PARM_DESC(index, "Index value for Digigram " DRIVER_NAME " soundcard");
@@ -69,58 +67,18 @@ enum {
PCI_ID_PCX882HR,
PCI_ID_VX881HR,
PCI_ID_PCX881HR,
- PCI_ID_VX882E,
- PCI_ID_PCX882E,
- PCI_ID_VX881E,
- PCI_ID_PCX881E,
- PCI_ID_VX1222HR,
PCI_ID_PCX1222HR,
- PCI_ID_VX1221HR,
PCI_ID_PCX1221HR,
- PCI_ID_VX1222E,
- PCI_ID_PCX1222E,
- PCI_ID_VX1221E,
- PCI_ID_PCX1221E,
- PCI_ID_VX222HR,
- PCI_ID_VX222E,
- PCI_ID_PCX22HR,
- PCI_ID_PCX22E,
- PCI_ID_VX222HRMIC,
- PCI_ID_VX222E_MIC,
- PCI_ID_PCX924HR,
- PCI_ID_PCX924E,
- PCI_ID_PCX924HRMIC,
- PCI_ID_PCX924E_MIC,
PCI_ID_LAST
};
static struct pci_device_id pcxhr_ids[] = {
- { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, },
- { 0x10b5, 0x9056, 0x1369, 0xb021, 0, 0, PCI_ID_VX882E, },
- { 0x10b5, 0x9056, 0x1369, 0xb121, 0, 0, PCI_ID_PCX882E, },
- { 0x10b5, 0x9056, 0x1369, 0xb221, 0, 0, PCI_ID_VX881E, },
- { 0x10b5, 0x9056, 0x1369, 0xb321, 0, 0, PCI_ID_PCX881E, },
- { 0x10b5, 0x9656, 0x1369, 0xb401, 0, 0, PCI_ID_VX1222HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb601, 0, 0, PCI_ID_VX1221HR, },
- { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, },
- { 0x10b5, 0x9056, 0x1369, 0xb421, 0, 0, PCI_ID_VX1222E, },
- { 0x10b5, 0x9056, 0x1369, 0xb521, 0, 0, PCI_ID_PCX1222E, },
- { 0x10b5, 0x9056, 0x1369, 0xb621, 0, 0, PCI_ID_VX1221E, },
- { 0x10b5, 0x9056, 0x1369, 0xb721, 0, 0, PCI_ID_PCX1221E, },
- { 0x10b5, 0x9056, 0x1369, 0xba01, 0, 0, PCI_ID_VX222HR, },
- { 0x10b5, 0x9056, 0x1369, 0xba21, 0, 0, PCI_ID_VX222E, },
- { 0x10b5, 0x9056, 0x1369, 0xbd01, 0, 0, PCI_ID_PCX22HR, },
- { 0x10b5, 0x9056, 0x1369, 0xbd21, 0, 0, PCI_ID_PCX22E, },
- { 0x10b5, 0x9056, 0x1369, 0xbc01, 0, 0, PCI_ID_VX222HRMIC, },
- { 0x10b5, 0x9056, 0x1369, 0xbc21, 0, 0, PCI_ID_VX222E_MIC, },
- { 0x10b5, 0x9056, 0x1369, 0xbb01, 0, 0, PCI_ID_PCX924HR, },
- { 0x10b5, 0x9056, 0x1369, 0xbb21, 0, 0, PCI_ID_PCX924E, },
- { 0x10b5, 0x9056, 0x1369, 0xbf01, 0, 0, PCI_ID_PCX924HRMIC, },
- { 0x10b5, 0x9056, 0x1369, 0xbf21, 0, 0, PCI_ID_PCX924E_MIC, },
+ { 0x10b5, 0x9656, 0x1369, 0xb001, 0, 0, PCI_ID_VX882HR, }, /* VX882HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb101, 0, 0, PCI_ID_PCX882HR, }, /* PCX882HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb201, 0, 0, PCI_ID_VX881HR, }, /* VX881HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb301, 0, 0, PCI_ID_PCX881HR, }, /* PCX881HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb501, 0, 0, PCI_ID_PCX1222HR, }, /* PCX1222HR */
+ { 0x10b5, 0x9656, 0x1369, 0xb701, 0, 0, PCI_ID_PCX1221HR, }, /* PCX1221HR */
{ 0, }
};
@@ -130,55 +88,27 @@ struct board_parameters {
char* board_name;
short playback_chips;
short capture_chips;
- short fw_file_set;
short firmware_num;
};
static struct board_parameters pcxhr_board_params[] = {
-[PCI_ID_VX882HR] = { "VX882HR", 4, 4, 0, 41 },
-[PCI_ID_PCX882HR] = { "PCX882HR", 4, 4, 0, 41 },
-[PCI_ID_VX881HR] = { "VX881HR", 4, 4, 0, 41 },
-[PCI_ID_PCX881HR] = { "PCX881HR", 4, 4, 0, 41 },
-[PCI_ID_VX882E] = { "VX882e", 4, 4, 1, 41 },
-[PCI_ID_PCX882E] = { "PCX882e", 4, 4, 1, 41 },
-[PCI_ID_VX881E] = { "VX881e", 4, 4, 1, 41 },
-[PCI_ID_PCX881E] = { "PCX881e", 4, 4, 1, 41 },
-[PCI_ID_VX1222HR] = { "VX1222HR", 6, 1, 2, 42 },
-[PCI_ID_PCX1222HR] = { "PCX1222HR", 6, 1, 2, 42 },
-[PCI_ID_VX1221HR] = { "VX1221HR", 6, 1, 2, 42 },
-[PCI_ID_PCX1221HR] = { "PCX1221HR", 6, 1, 2, 42 },
-[PCI_ID_VX1222E] = { "VX1222e", 6, 1, 3, 42 },
-[PCI_ID_PCX1222E] = { "PCX1222e", 6, 1, 3, 42 },
-[PCI_ID_VX1221E] = { "VX1221e", 6, 1, 3, 42 },
-[PCI_ID_PCX1221E] = { "PCX1221e", 6, 1, 3, 42 },
-[PCI_ID_VX222HR] = { "VX222HR", 1, 1, 4, 44 },
-[PCI_ID_VX222E] = { "VX222e", 1, 1, 4, 44 },
-[PCI_ID_PCX22HR] = { "PCX22HR", 1, 0, 4, 44 },
-[PCI_ID_PCX22E] = { "PCX22e", 1, 0, 4, 44 },
-[PCI_ID_VX222HRMIC] = { "VX222HR-Mic", 1, 1, 5, 44 },
-[PCI_ID_VX222E_MIC] = { "VX222e-Mic", 1, 1, 5, 44 },
-[PCI_ID_PCX924HR] = { "PCX924HR", 1, 1, 5, 44 },
-[PCI_ID_PCX924E] = { "PCX924e", 1, 1, 5, 44 },
-[PCI_ID_PCX924HRMIC] = { "PCX924HR-Mic", 1, 1, 5, 44 },
-[PCI_ID_PCX924E_MIC] = { "PCX924e-Mic", 1, 1, 5, 44 },
+[PCI_ID_VX882HR] = { "VX882HR", 4, 4, 41, },
+[PCI_ID_PCX882HR] = { "PCX882HR", 4, 4, 41, },
+[PCI_ID_VX881HR] = { "VX881HR", 4, 4, 41, },
+[PCI_ID_PCX881HR] = { "PCX881HR", 4, 4, 41, },
+[PCI_ID_PCX1222HR] = { "PCX1222HR", 6, 1, 42, },
+[PCI_ID_PCX1221HR] = { "PCX1221HR", 6, 1, 42, },
};
-/* boards without hw AES1 and SRC onboard are all using fw_file_set==4 */
-/* VX222HR, VX222e, PCX22HR and PCX22e */
-#define PCXHR_BOARD_HAS_AES1(x) (x->fw_file_set != 4)
-/* some boards do not support 192kHz on digital AES input plugs */
-#define PCXHR_BOARD_AESIN_NO_192K(x) ((x->capture_chips == 0) || \
- (x->fw_file_set == 0) || \
- (x->fw_file_set == 2))
static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
unsigned int* realfreq)
{
unsigned int reg;
- if (freq < 6900 || freq > 110000)
+ if (freq < 6900 || freq > 110250)
return -EINVAL;
- reg = (28224000 * 2) / freq;
- reg = (reg - 1) / 2;
+ reg = (28224000 * 10) / freq;
+ reg = (reg + 5) / 10;
if (reg < 0x200)
*pllreg = reg + 0x800;
else if (reg < 0x400)
@@ -191,7 +121,7 @@ static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
reg &= ~3;
}
if (realfreq)
- *realfreq = (28224000 / (reg + 1));
+ *realfreq = ((28224000 * 10) / reg + 5) / 10;
return 0;
}
@@ -221,6 +151,11 @@ static int pcxhr_pll_freq_register(unsigned int freq, unsigned int* pllreg,
#define PCXHR_FREQ_AES_3 0x03
#define PCXHR_FREQ_AES_4 0x0d
+#define PCXHR_MODIFY_CLOCK_S_BIT 0x04
+
+#define PCXHR_IRQ_TIMER_FREQ 92000
+#define PCXHR_IRQ_TIMER_PERIOD 48
+
static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
unsigned int *reg, unsigned int *freq)
{
@@ -261,32 +196,19 @@ static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
err = pcxhr_send_msg(mgr, &rmh);
if (err < 0) {
snd_printk(KERN_ERR
- "error CMD_ACCESS_IO_WRITE "
- "for PLL register : %x!\n", err);
+ "error CMD_ACCESS_IO_WRITE for PLL register : %x!\n",
+ err );
return err;
}
}
break;
- case PCXHR_CLOCK_TYPE_WORD_CLOCK:
- val = PCXHR_FREQ_WORD_CLOCK;
- break;
- case PCXHR_CLOCK_TYPE_AES_SYNC:
- val = PCXHR_FREQ_SYNC_AES;
- break;
- case PCXHR_CLOCK_TYPE_AES_1:
- val = PCXHR_FREQ_AES_1;
- break;
- case PCXHR_CLOCK_TYPE_AES_2:
- val = PCXHR_FREQ_AES_2;
- break;
- case PCXHR_CLOCK_TYPE_AES_3:
- val = PCXHR_FREQ_AES_3;
- break;
- case PCXHR_CLOCK_TYPE_AES_4:
- val = PCXHR_FREQ_AES_4;
- break;
- default:
- return -EINVAL;
+ case PCXHR_CLOCK_TYPE_WORD_CLOCK : val = PCXHR_FREQ_WORD_CLOCK; break;
+ case PCXHR_CLOCK_TYPE_AES_SYNC : val = PCXHR_FREQ_SYNC_AES; break;
+ case PCXHR_CLOCK_TYPE_AES_1 : val = PCXHR_FREQ_AES_1; break;
+ case PCXHR_CLOCK_TYPE_AES_2 : val = PCXHR_FREQ_AES_2; break;
+ case PCXHR_CLOCK_TYPE_AES_3 : val = PCXHR_FREQ_AES_3; break;
+ case PCXHR_CLOCK_TYPE_AES_4 : val = PCXHR_FREQ_AES_4; break;
+ default : return -EINVAL;
}
*reg = val;
*freq = realfreq;
@@ -294,13 +216,14 @@ static int pcxhr_get_clock_reg(struct pcxhr_mgr *mgr, unsigned int rate,
}
-static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr,
- unsigned int rate,
- int *changed)
+int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
{
unsigned int val, realfreq, speed;
struct pcxhr_rmh rmh;
- int err;
+ int err, changed;
+
+ if (rate == 0)
+ return 0; /* nothing to do */
err = pcxhr_get_clock_reg(mgr, rate, &val, &realfreq);
if (err)
@@ -314,17 +237,13 @@ static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr,
else
speed = 2; /* quad speed */
if (mgr->codec_speed != speed) {
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* mute outputs */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* mute outputs */
rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
- if (DSP_EXT_CMD_SET(mgr)) {
- rmh.cmd[1] = 1;
- rmh.cmd_len = 2;
- }
err = pcxhr_send_msg(mgr, &rmh);
if (err)
return err;
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set speed ratio */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set speed ratio */
rmh.cmd[0] |= IO_NUM_SPEED_RATIO;
rmh.cmd[1] = speed;
rmh.cmd_len = 2;
@@ -334,57 +253,25 @@ static int pcxhr_sub_set_clock(struct pcxhr_mgr *mgr,
}
/* set the new frequency */
snd_printdd("clock register : set %x\n", val);
- err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK,
- val, changed);
+ err = pcxhr_write_io_num_reg_cont(mgr, PCXHR_FREQ_REG_MASK, val, &changed);
if (err)
return err;
-
mgr->sample_rate_real = realfreq;
mgr->cur_clock_type = mgr->use_clock_type;
/* unmute after codec speed modes */
if (mgr->codec_speed != speed) {
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* unmute outputs */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* unmute outputs */
rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
- if (DSP_EXT_CMD_SET(mgr)) {
- rmh.cmd[1] = 1;
- rmh.cmd_len = 2;
- }
err = pcxhr_send_msg(mgr, &rmh);
if (err)
return err;
- mgr->codec_speed = speed; /* save new codec speed */
+ mgr->codec_speed = speed; /* save new codec speed */
}
- snd_printdd("pcxhr_sub_set_clock to %dHz (realfreq=%d)\n",
- rate, realfreq);
- return 0;
-}
-
-#define PCXHR_MODIFY_CLOCK_S_BIT 0x04
-
-#define PCXHR_IRQ_TIMER_FREQ 92000
-#define PCXHR_IRQ_TIMER_PERIOD 48
-
-int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
-{
- struct pcxhr_rmh rmh;
- int err, changed;
-
- if (rate == 0)
- return 0; /* nothing to do */
-
- if (mgr->is_hr_stereo)
- err = hr222_sub_set_clock(mgr, rate, &changed);
- else
- err = pcxhr_sub_set_clock(mgr, rate, &changed);
-
- if (err)
- return err;
-
if (changed) {
pcxhr_init_rmh(&rmh, CMD_MODIFY_CLOCK);
- rmh.cmd[0] |= PCXHR_MODIFY_CLOCK_S_BIT; /* resync fifos */
+ rmh.cmd[0] |= PCXHR_MODIFY_CLOCK_S_BIT; /* resync fifos */
if (rate < PCXHR_IRQ_TIMER_FREQ)
rmh.cmd[1] = PCXHR_IRQ_TIMER_PERIOD;
else
@@ -395,39 +282,26 @@ int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate)
if (err)
return err;
}
+ snd_printdd("pcxhr_set_clock to %dHz (realfreq=%d)\n", rate, realfreq);
return 0;
}
-static int pcxhr_sub_get_external_clock(struct pcxhr_mgr *mgr,
- enum pcxhr_clock_type clock_type,
- int *sample_rate)
+int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_type,
+ int *sample_rate)
{
struct pcxhr_rmh rmh;
unsigned char reg;
int err, rate;
switch (clock_type) {
- case PCXHR_CLOCK_TYPE_WORD_CLOCK:
- reg = REG_STATUS_WORD_CLOCK;
- break;
- case PCXHR_CLOCK_TYPE_AES_SYNC:
- reg = REG_STATUS_AES_SYNC;
- break;
- case PCXHR_CLOCK_TYPE_AES_1:
- reg = REG_STATUS_AES_1;
- break;
- case PCXHR_CLOCK_TYPE_AES_2:
- reg = REG_STATUS_AES_2;
- break;
- case PCXHR_CLOCK_TYPE_AES_3:
- reg = REG_STATUS_AES_3;
- break;
- case PCXHR_CLOCK_TYPE_AES_4:
- reg = REG_STATUS_AES_4;
- break;
- default:
- return -EINVAL;
+ case PCXHR_CLOCK_TYPE_WORD_CLOCK : reg = REG_STATUS_WORD_CLOCK; break;
+ case PCXHR_CLOCK_TYPE_AES_SYNC : reg = REG_STATUS_AES_SYNC; break;
+ case PCXHR_CLOCK_TYPE_AES_1 : reg = REG_STATUS_AES_1; break;
+ case PCXHR_CLOCK_TYPE_AES_2 : reg = REG_STATUS_AES_2; break;
+ case PCXHR_CLOCK_TYPE_AES_3 : reg = REG_STATUS_AES_3; break;
+ case PCXHR_CLOCK_TYPE_AES_4 : reg = REG_STATUS_AES_4; break;
+ default : return -EINVAL;
}
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
rmh.cmd_len = 2;
@@ -437,7 +311,7 @@ static int pcxhr_sub_get_external_clock(struct pcxhr_mgr *mgr,
err = pcxhr_send_msg(mgr, &rmh);
if (err)
return err;
- udelay(100); /* wait minimum 2 sample_frames at 32kHz ! */
+ udelay(100); /* wait minimum 2 sample_frames at 32kHz ! */
mgr->last_reg_stat = reg;
}
rmh.cmd[1] = REG_STATUS_CURRENT;
@@ -462,18 +336,6 @@ static int pcxhr_sub_get_external_clock(struct pcxhr_mgr *mgr,
}
-int pcxhr_get_external_clock(struct pcxhr_mgr *mgr,
- enum pcxhr_clock_type clock_type,
- int *sample_rate)
-{
- if (mgr->is_hr_stereo)
- return hr222_get_external_clock(mgr, clock_type,
- sample_rate);
- else
- return pcxhr_sub_get_external_clock(mgr, clock_type,
- sample_rate);
-}
-
/*
* start or stop playback/capture substream
*/
@@ -488,8 +350,7 @@ static int pcxhr_set_stream_state(struct pcxhr_stream *stream)
start = 1;
else {
if (stream->status != PCXHR_STREAM_STATUS_SCHEDULE_STOP) {
- snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state "
- "CANNOT be stopped\n");
+ snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state CANNOT be stopped\n");
return -EINVAL;
}
start = 0;
@@ -498,12 +359,11 @@ static int pcxhr_set_stream_state(struct pcxhr_stream *stream)
return -EINVAL;
stream->timer_abs_periods = 0;
- stream->timer_period_frag = 0; /* reset theoretical stream pos */
+ stream->timer_period_frag = 0; /* reset theoretical stream pos */
stream->timer_buf_periods = 0;
stream->timer_is_synced = 0;
- stream_mask =
- stream->pipe->is_capture ? 1 : 1<<stream->substream->number;
+ stream_mask = stream->pipe->is_capture ? 1 : 1<<stream->substream->number;
pcxhr_init_rmh(&rmh, start ? CMD_START_STREAM : CMD_STOP_STREAM);
pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture,
@@ -513,10 +373,8 @@ static int pcxhr_set_stream_state(struct pcxhr_stream *stream)
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
- snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state err=%x;\n",
- err);
- stream->status =
- start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
+ snd_printk(KERN_ERR "ERROR pcxhr_set_stream_state err=%x;\n", err);
+ stream->status = start ? PCXHR_STREAM_STATUS_STARTED : PCXHR_STREAM_STATUS_STOPPED;
return err;
}
@@ -541,15 +399,13 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
header = HEADER_FMT_BASE_LIN;
break;
case SNDRV_PCM_FORMAT_S16_LE:
- header = HEADER_FMT_BASE_LIN |
- HEADER_FMT_16BITS | HEADER_FMT_INTEL;
+ header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS | HEADER_FMT_INTEL;
break;
case SNDRV_PCM_FORMAT_S16_BE:
header = HEADER_FMT_BASE_LIN | HEADER_FMT_16BITS;
break;
case SNDRV_PCM_FORMAT_S24_3LE:
- header = HEADER_FMT_BASE_LIN |
- HEADER_FMT_24BITS | HEADER_FMT_INTEL;
+ header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS | HEADER_FMT_INTEL;
break;
case SNDRV_PCM_FORMAT_S24_3BE:
header = HEADER_FMT_BASE_LIN | HEADER_FMT_24BITS;
@@ -558,8 +414,7 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
header = HEADER_FMT_BASE_FLOAT | HEADER_FMT_INTEL;
break;
default:
- snd_printk(KERN_ERR
- "error pcxhr_set_format() : unknown format\n");
+ snd_printk(KERN_ERR "error pcxhr_set_format() : unknown format\n");
return -EINVAL;
}
chip = snd_pcm_substream_chip(stream->substream);
@@ -577,31 +432,14 @@ static int pcxhr_set_format(struct pcxhr_stream *stream)
is_capture = stream->pipe->is_capture;
stream_num = is_capture ? 0 : stream->substream->number;
- pcxhr_init_rmh(&rmh, is_capture ?
- CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
- pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio,
- stream_num, 0);
- if (is_capture) {
- /* bug with old dsp versions: */
- /* bit 12 also sets the format of the playback stream */
- if (DSP_EXT_CMD_SET(chip->mgr))
- rmh.cmd[0] |= 1<<10;
- else
- rmh.cmd[0] |= 1<<12;
- }
+ pcxhr_init_rmh(&rmh, is_capture ? CMD_FORMAT_STREAM_IN : CMD_FORMAT_STREAM_OUT);
+ pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, stream_num, 0);
+ if (is_capture)
+ rmh.cmd[0] |= 1<<12;
rmh.cmd[1] = 0;
- rmh.cmd_len = 2;
- if (DSP_EXT_CMD_SET(chip->mgr)) {
- /* add channels and set bit 19 if channels>2 */
- rmh.cmd[1] = stream->channels;
- if (!is_capture) {
- /* playback : add channel mask to command */
- rmh.cmd[2] = (stream->channels == 1) ? 0x01 : 0x03;
- rmh.cmd_len = 3;
- }
- }
- rmh.cmd[rmh.cmd_len++] = header >> 8;
- rmh.cmd[rmh.cmd_len++] = (header & 0xff) << 16;
+ rmh.cmd[2] = header >> 8;
+ rmh.cmd[3] = (header & 0xff) << 16;
+ rmh.cmd_len = 4;
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
snd_printk(KERN_ERR "ERROR pcxhr_set_format err=%x;\n", err);
@@ -618,38 +456,30 @@ static int pcxhr_update_r_buffer(struct pcxhr_stream *stream)
is_capture = (subs->stream == SNDRV_PCM_STREAM_CAPTURE);
stream_num = is_capture ? 0 : subs->number;
- snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : "
- "addr(%p) bytes(%zx) subs(%d)\n",
+ snd_printdd("pcxhr_update_r_buffer(pcm%c%d) : addr(%p) bytes(%zx) subs(%d)\n",
is_capture ? 'c' : 'p',
chip->chip_idx, (void *)(long)subs->runtime->dma_addr,
subs->runtime->dma_bytes, subs->number);
pcxhr_init_rmh(&rmh, CMD_UPDATE_R_BUFFERS);
- pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio,
- stream_num, 0);
+ pcxhr_set_pipe_cmd_params(&rmh, is_capture, stream->pipe->first_audio, stream_num, 0);
/* max buffer size is 2 MByte */
snd_BUG_ON(subs->runtime->dma_bytes >= 0x200000);
- /* size in bits */
- rmh.cmd[1] = subs->runtime->dma_bytes * 8;
- /* most significant byte */
- rmh.cmd[2] = subs->runtime->dma_addr >> 24;
- /* this is a circular buffer */
- rmh.cmd[2] |= 1<<19;
- /* least 3 significant bytes */
- rmh.cmd[3] = subs->runtime->dma_addr & MASK_DSP_WORD;
+ rmh.cmd[1] = subs->runtime->dma_bytes * 8; /* size in bits */
+ rmh.cmd[2] = subs->runtime->dma_addr >> 24; /* most significant byte */
+ rmh.cmd[2] |= 1<<19; /* this is a circular buffer */
+ rmh.cmd[3] = subs->runtime->dma_addr & MASK_DSP_WORD; /* least 3 significant bytes */
rmh.cmd_len = 4;
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
- snd_printk(KERN_ERR
- "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err);
+ snd_printk(KERN_ERR "ERROR CMD_UPDATE_R_BUFFERS err=%x;\n", err);
return err;
}
#if 0
-static int pcxhr_pipe_sample_count(struct pcxhr_stream *stream,
- snd_pcm_uframes_t *sample_count)
+static int pcxhr_pipe_sample_count(struct pcxhr_stream *stream, snd_pcm_uframes_t *sample_count)
{
struct pcxhr_rmh rmh;
int err;
@@ -703,8 +533,8 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
for (j = 0; j < chip->nb_streams_play; j++) {
if (pcxhr_stream_scheduled_get_pipe(&chip->playback_stream[j], &pipe)) {
playback_mask |= (1 << pipe->first_audio);
- break; /* add only once, as all playback
- * streams of one chip use the same pipe
+ break; /* add only once, as all playback streams of
+ * one chip use the same pipe
*/
}
}
@@ -715,21 +545,19 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
return;
}
- snd_printdd("pcxhr_trigger_tasklet : "
- "playback_mask=%x capture_mask=%x\n",
+ snd_printdd("pcxhr_trigger_tasklet : playback_mask=%x capture_mask=%x\n",
playback_mask, capture_mask);
/* synchronous stop of all the pipes concerned */
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 0);
if (err) {
mutex_unlock(&mgr->setup_mutex);
- snd_printk(KERN_ERR "pcxhr_trigger_tasklet : "
- "error stop pipes (P%x C%x)\n",
+ snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error stop pipes (P%x C%x)\n",
playback_mask, capture_mask);
return;
}
- /* the dsp lost format and buffer info with the stop pipe */
+ /* unfortunately the dsp lost format and buffer info with the stop pipe */
for (i = 0; i < mgr->num_cards; i++) {
struct pcxhr_stream *stream;
chip = mgr->chip[i];
@@ -768,15 +596,12 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
err = pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
if (err) {
mutex_unlock(&mgr->setup_mutex);
- snd_printk(KERN_ERR "pcxhr_trigger_tasklet : "
- "error start pipes (P%x C%x)\n",
+ snd_printk(KERN_ERR "pcxhr_trigger_tasklet : error start pipes (P%x C%x)\n",
playback_mask, capture_mask);
return;
}
- /* put the streams into the running state now
- * (increment pointer by interrupt)
- */
+ /* put the streams into the running state now (increment pointer by interrupt) */
spin_lock_irqsave(&mgr->lock, flags);
for ( i =0; i < mgr->num_cards; i++) {
struct pcxhr_stream *stream;
@@ -790,7 +615,7 @@ static void pcxhr_trigger_tasklet(unsigned long arg)
stream = &chip->playback_stream[j];
if (stream->status == PCXHR_STREAM_STATUS_STARTED) {
/* playback will already have advanced ! */
- stream->timer_period_frag += mgr->granularity;
+ stream->timer_period_frag += PCXHR_GRANULARITY;
stream->status = PCXHR_STREAM_STATUS_RUNNING;
}
}
@@ -872,14 +697,12 @@ static int pcxhr_hardware_timer(struct pcxhr_mgr *mgr, int start)
pcxhr_init_rmh(&rmh, CMD_SET_TIMER_INTERRUPT);
if (start) {
- /* last dsp time invalid */
- mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
- rmh.cmd[0] |= mgr->granularity;
+ mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID; /* last dsp time invalid */
+ rmh.cmd[0] |= PCXHR_GRANULARITY;
}
err = pcxhr_send_msg(mgr, &rmh);
if (err < 0)
- snd_printk(KERN_ERR "error pcxhr_hardware_timer err(%x)\n",
- err);
+ snd_printk(KERN_ERR "error pcxhr_hardware_timer err(%x)\n", err);
return err;
}
@@ -890,16 +713,38 @@ static int pcxhr_prepare(struct snd_pcm_substream *subs)
{
struct snd_pcxhr *chip = snd_pcm_substream_chip(subs);
struct pcxhr_mgr *mgr = chip->mgr;
+ /*
+ struct pcxhr_stream *stream = (pcxhr_stream_t*)subs->runtime->private_data;
+ */
int err = 0;
snd_printdd("pcxhr_prepare : period_size(%lx) periods(%x) buffer_size(%lx)\n",
subs->runtime->period_size, subs->runtime->periods,
subs->runtime->buffer_size);
+ /*
+ if(subs->runtime->period_size <= PCXHR_GRANULARITY) {
+ snd_printk(KERN_ERR "pcxhr_prepare : error period_size too small (%x)\n",
+ (unsigned int)subs->runtime->period_size);
+ return -EINVAL;
+ }
+ */
+
mutex_lock(&mgr->setup_mutex);
do {
+ /* if the stream was stopped before, format and buffer were reset */
+ /*
+ if(stream->status == PCXHR_STREAM_STATUS_STOPPED) {
+ err = pcxhr_set_format(stream);
+ if(err) break;
+ err = pcxhr_update_r_buffer(stream);
+ if(err) break;
+ }
+ */
+
/* only the first stream can choose the sample rate */
+ /* the further opened streams will be limited to its frequency (see open) */
/* set the clock only once (first stream) */
if (mgr->sample_rate != subs->runtime->rate) {
err = pcxhr_set_clock(mgr, subs->runtime->rate);
@@ -942,9 +787,22 @@ static int pcxhr_hw_params(struct snd_pcm_substream *subs,
stream->channels = channels;
stream->format = format;
+ /* set the format to the board */
+ /*
+ err = pcxhr_set_format(stream);
+ if(err) {
+ mutex_unlock(&mgr->setup_mutex);
+ return err;
+ }
+ */
/* allocate buffer */
err = snd_pcm_lib_malloc_pages(subs, params_buffer_bytes(hw));
+ /*
+ if (err > 0) {
+ err = pcxhr_update_r_buffer(stream);
+ }
+ */
mutex_unlock(&mgr->setup_mutex);
return err;
@@ -962,18 +820,14 @@ static int pcxhr_hw_free(struct snd_pcm_substream *subs)
*/
static struct snd_pcm_hardware pcxhr_caps =
{
- .info = (SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_SYNC_START),
- .formats = (SNDRV_PCM_FMTBIT_U8 |
- SNDRV_PCM_FMTBIT_S16_LE |
- SNDRV_PCM_FMTBIT_S16_BE |
- SNDRV_PCM_FMTBIT_S24_3LE |
- SNDRV_PCM_FMTBIT_S24_3BE |
- SNDRV_PCM_FMTBIT_FLOAT_LE),
- .rates = (SNDRV_PCM_RATE_CONTINUOUS |
- SNDRV_PCM_RATE_8000_192000),
+ .info = ( SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START |
+ 0 /*SNDRV_PCM_INFO_PAUSE*/),
+ .formats = ( SNDRV_PCM_FMTBIT_U8 |
+ SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE |
+ SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S24_3BE |
+ SNDRV_PCM_FMTBIT_FLOAT_LE ),
+ .rates = SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_192000,
.rate_min = 8000,
.rate_max = 192000,
.channels_min = 1,
@@ -993,7 +847,6 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
struct pcxhr_mgr *mgr = chip->mgr;
struct snd_pcm_runtime *runtime = subs->runtime;
struct pcxhr_stream *stream;
- int err;
mutex_lock(&mgr->setup_mutex);
@@ -1021,18 +874,6 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
return -EBUSY;
}
- /* float format support is in some cases buggy on stereo cards */
- if (mgr->is_hr_stereo)
- runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_FLOAT_LE;
-
- /* buffer-size should better be multiple of period-size */
- err = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (err < 0) {
- mutex_unlock(&mgr->setup_mutex);
- return err;
- }
-
/* if a sample rate is already used or fixed by external clock,
* the stream cannot change
*/
@@ -1048,8 +889,7 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
mutex_unlock(&mgr->setup_mutex);
return -EBUSY;
}
- runtime->hw.rate_min = external_rate;
- runtime->hw.rate_max = external_rate;
+ runtime->hw.rate_min = runtime->hw.rate_max = external_rate;
}
}
@@ -1059,11 +899,9 @@ static int pcxhr_open(struct snd_pcm_substream *subs)
runtime->private_data = stream;
- /* better get a divisor of granularity values (96 or 192) */
- snd_pcm_hw_constraint_step(runtime, 0,
- SNDRV_PCM_HW_PARAM_BUFFER_SIZE, 32);
- snd_pcm_hw_constraint_step(runtime, 0,
- SNDRV_PCM_HW_PARAM_PERIOD_SIZE, 32);
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 4);
+ snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 4);
+
snd_pcm_set_sync(subs);
mgr->ref_count_rate++;
@@ -1081,12 +919,11 @@ static int pcxhr_close(struct snd_pcm_substream *subs)
mutex_lock(&mgr->setup_mutex);
- snd_printdd("pcxhr_close chip%d subs%d\n",
- chip->chip_idx, subs->number);
+ snd_printdd("pcxhr_close chip%d subs%d\n", chip->chip_idx, subs->number);
/* sample rate released */
if (--mgr->ref_count_rate == 0) {
- mgr->sample_rate = 0; /* the sample rate is no more locked */
+ mgr->sample_rate = 0; /* the sample rate is no more locked */
pcxhr_hardware_timer(mgr, 0); /* stop the DSP-timer */
}
@@ -1179,8 +1016,7 @@ static int pcxhr_chip_dev_free(struct snd_device *device)
/*
*/
-static int __devinit pcxhr_create(struct pcxhr_mgr *mgr,
- struct snd_card *card, int idx)
+static int __devinit pcxhr_create(struct pcxhr_mgr *mgr, struct snd_card *card, int idx)
{
int err;
struct snd_pcxhr *chip;
@@ -1188,7 +1024,7 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr,
.dev_free = pcxhr_chip_dev_free,
};
- chip = kzalloc(sizeof(*chip), GFP_KERNEL);
+ mgr->chip[idx] = chip = kzalloc(sizeof(*chip), GFP_KERNEL);
if (! chip) {
snd_printk(KERN_ERR "cannot allocate chip\n");
return -ENOMEM;
@@ -1204,7 +1040,7 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr,
if (idx < mgr->capture_chips) {
if (mgr->mono_capture)
- chip->nb_streams_capt = 2; /* 2 mono streams */
+ chip->nb_streams_capt = 2; /* 2 mono streams (left+right) */
else
chip->nb_streams_capt = 1; /* or 1 stereo stream */
}
@@ -1214,15 +1050,13 @@ static int __devinit pcxhr_create(struct pcxhr_mgr *mgr,
return err;
}
- mgr->chip[idx] = chip;
snd_card_set_dev(card, &mgr->pci->dev);
return 0;
}
/* proc interface */
-static void pcxhr_proc_info(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
+static void pcxhr_proc_info(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
struct snd_pcxhr *chip = entry->private_data;
struct pcxhr_mgr *mgr = chip->mgr;
@@ -1235,10 +1069,8 @@ static void pcxhr_proc_info(struct snd_info_entry *entry,
short ver_maj = (mgr->dsp_version >> 16) & 0xff;
short ver_min = (mgr->dsp_version >> 8) & 0xff;
short ver_build = mgr->dsp_version & 0xff;
- snd_iprintf(buffer, "module version %s\n",
- PCXHR_DRIVER_VERSION_STRING);
- snd_iprintf(buffer, "dsp version %d.%d.%d\n",
- ver_maj, ver_min, ver_build);
+ snd_iprintf(buffer, "module version %s\n", PCXHR_DRIVER_VERSION_STRING);
+ snd_iprintf(buffer, "dsp version %d.%d.%d\n", ver_maj, ver_min, ver_build);
if (mgr->board_has_analog)
snd_iprintf(buffer, "analog io available\n");
else
@@ -1252,22 +1084,18 @@ static void pcxhr_proc_info(struct snd_info_entry *entry,
if (ref > 0) {
if (mgr->sample_rate_real != 0 &&
mgr->sample_rate_real != 48000) {
- ref = (ref * 48000) /
- mgr->sample_rate_real;
- if (mgr->sample_rate_real >=
- PCXHR_IRQ_TIMER_FREQ)
+ ref = (ref * 48000) / mgr->sample_rate_real;
+ if (mgr->sample_rate_real >= PCXHR_IRQ_TIMER_FREQ)
ref *= 2;
}
cur = 100 - (100 * cur) / ref;
snd_iprintf(buffer, "cpu load %d%%\n", cur);
- snd_iprintf(buffer, "buffer pool %d/%d\n",
+ snd_iprintf(buffer, "buffer pool %d/%d kWords\n",
rmh.stat[2], rmh.stat[3]);
}
}
- snd_iprintf(buffer, "dma granularity : %d\n",
- mgr->granularity);
- snd_iprintf(buffer, "dsp time errors : %d\n",
- mgr->dsp_time_err);
+ snd_iprintf(buffer, "dma granularity : %d\n", PCXHR_GRANULARITY);
+ snd_iprintf(buffer, "dsp time errors : %d\n", mgr->dsp_time_err);
snd_iprintf(buffer, "dsp async pipe xrun errors : %d\n",
mgr->async_err_pipe_xrun);
snd_iprintf(buffer, "dsp async stream xrun errors : %d\n",
@@ -1282,52 +1110,33 @@ static void pcxhr_proc_info(struct snd_info_entry *entry,
rmh.cmd_idx = CMD_LAST_INDEX;
if( ! pcxhr_send_msg(mgr, &rmh) ) {
int i;
- if (rmh.stat_len > 8)
- rmh.stat_len = 8;
for (i = 0; i < rmh.stat_len; i++)
- snd_iprintf(buffer, "debug[%02d] = %06x\n",
- i, rmh.stat[i]);
+ snd_iprintf(buffer, "debug[%02d] = %06x\n", i, rmh.stat[i]);
}
} else
snd_iprintf(buffer, "no firmware loaded\n");
snd_iprintf(buffer, "\n");
}
-static void pcxhr_proc_sync(struct snd_info_entry *entry,
- struct snd_info_buffer *buffer)
+static void pcxhr_proc_sync(struct snd_info_entry *entry, struct snd_info_buffer *buffer)
{
struct snd_pcxhr *chip = entry->private_data;
struct pcxhr_mgr *mgr = chip->mgr;
- static const char *textsHR22[3] = {
- "Internal", "AES Sync", "AES 1"
- };
- static const char *textsPCXHR[7] = {
- "Internal", "Word", "AES Sync",
- "AES 1", "AES 2", "AES 3", "AES 4"
+ static char *texts[7] = {
+ "Internal", "Word", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
};
- const char **texts;
- int max_clock;
- if (mgr->is_hr_stereo) {
- texts = textsHR22;
- max_clock = HR22_CLOCK_TYPE_MAX;
- } else {
- texts = textsPCXHR;
- max_clock = PCXHR_CLOCK_TYPE_MAX;
- }
snd_iprintf(buffer, "\n%s\n", mgr->longname);
- snd_iprintf(buffer, "Current Sample Clock\t: %s\n",
- texts[mgr->cur_clock_type]);
- snd_iprintf(buffer, "Current Sample Rate\t= %d\n",
- mgr->sample_rate_real);
+ snd_iprintf(buffer, "Current Sample Clock\t: %s\n", texts[mgr->cur_clock_type]);
+ snd_iprintf(buffer, "Current Sample Rate\t= %d\n", mgr->sample_rate_real);
+
/* commands available when embedded DSP is running */
if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
int i, err, sample_rate;
- for (i = 1; i <= max_clock; i++) {
+ for (i = PCXHR_CLOCK_TYPE_WORD_CLOCK; i< (3 + mgr->capture_chips); i++) {
err = pcxhr_get_external_clock(mgr, i, &sample_rate);
if (err)
break;
- snd_iprintf(buffer, "%s Clock\t\t= %d\n",
- texts[i], sample_rate);
+ snd_iprintf(buffer, "%s Clock\t\t= %d\n", texts[i], sample_rate);
}
} else
snd_iprintf(buffer, "no firmware loaded\n");
@@ -1385,8 +1194,7 @@ static int pcxhr_free(struct pcxhr_mgr *mgr)
/*
* probe function - creates the card manager
*/
-static int __devinit pcxhr_probe(struct pci_dev *pci,
- const struct pci_device_id *pci_id)
+static int __devinit pcxhr_probe(struct pci_dev *pci, const struct pci_device_id *pci_id)
{
static int dev;
struct pcxhr_mgr *mgr;
@@ -1409,8 +1217,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
/* check if we can restrict PCI DMA transfers to 32 bits */
if (pci_set_dma_mask(pci, DMA_32BIT_MASK) < 0) {
- snd_printk(KERN_ERR "architecture does not support "
- "32bit PCI busmaster DMA\n");
+ snd_printk(KERN_ERR "architecture does not support 32bit PCI busmaster DMA\n");
pci_disable_device(pci);
return -ENXIO;
}
@@ -1427,25 +1234,11 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
pci_disable_device(pci);
return -ENODEV;
}
- card_name =
- pcxhr_board_params[pci_id->driver_data].board_name;
- mgr->playback_chips =
- pcxhr_board_params[pci_id->driver_data].playback_chips;
- mgr->capture_chips =
- pcxhr_board_params[pci_id->driver_data].capture_chips;
- mgr->fw_file_set =
- pcxhr_board_params[pci_id->driver_data].fw_file_set;
- mgr->firmware_num =
- pcxhr_board_params[pci_id->driver_data].firmware_num;
+ card_name = pcxhr_board_params[pci_id->driver_data].board_name;
+ mgr->playback_chips = pcxhr_board_params[pci_id->driver_data].playback_chips;
+ mgr->capture_chips = pcxhr_board_params[pci_id->driver_data].capture_chips;
+ mgr->firmware_num = pcxhr_board_params[pci_id->driver_data].firmware_num;
mgr->mono_capture = mono[dev];
- mgr->is_hr_stereo = (mgr->playback_chips == 1);
- mgr->board_has_aes1 = PCXHR_BOARD_HAS_AES1(mgr);
- mgr->board_aes_in_192k = !PCXHR_BOARD_AESIN_NO_192K(mgr);
-
- if (mgr->is_hr_stereo)
- mgr->granularity = PCXHR_GRANULARITY_HR22;
- else
- mgr->granularity = PCXHR_GRANULARITY;
/* resource assignment */
if ((err = pci_request_regions(pci, card_name)) < 0) {
@@ -1468,8 +1261,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
mgr->irq = pci->irq;
sprintf(mgr->shortname, "Digigram %s", card_name);
- sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, 0x%lx irq %i",
- mgr->shortname,
+ sprintf(mgr->longname, "%s at 0x%lx & 0x%lx, 0x%lx irq %i", mgr->shortname,
mgr->port[0], mgr->port[1], mgr->port[2], mgr->irq);
/* ISR spinlock */
@@ -1480,14 +1272,10 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
mutex_init(&mgr->setup_mutex);
/* init taslket */
- tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet,
- (unsigned long) mgr);
- tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet,
- (unsigned long) mgr);
-
+ tasklet_init(&mgr->msg_taskq, pcxhr_msg_tasklet, (unsigned long) mgr);
+ tasklet_init(&mgr->trigger_taskq, pcxhr_trigger_tasklet, (unsigned long) mgr);
mgr->prmh = kmalloc(sizeof(*mgr->prmh) +
- sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS -
- PCXHR_SIZE_MAX_STATUS),
+ sizeof(u32) * (PCXHR_SIZE_MAX_LONG_STATUS - PCXHR_SIZE_MAX_STATUS),
GFP_KERNEL);
if (! mgr->prmh) {
pcxhr_free(mgr);
@@ -1508,8 +1296,7 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
else
idx = index[dev] + i;
- snprintf(tmpid, sizeof(tmpid), "%s-%d",
- id[dev] ? id[dev] : card_name, i);
+ snprintf(tmpid, sizeof(tmpid), "%s-%d", id[dev] ? id[dev] : card_name, i);
card = snd_card_new(idx, tmpid, THIS_MODULE, 0);
if (! card) {
@@ -1523,7 +1310,6 @@ static int __devinit pcxhr_probe(struct pci_dev *pci,
sprintf(card->longname, "%s [PCM #%d]", mgr->longname, i);
if ((err = pcxhr_create(mgr, card, i)) < 0) {
- snd_card_free(card);
pcxhr_free(mgr);
return err;
}
diff --git a/sound/pci/pcxhr/pcxhr.h b/sound/pci/pcxhr/pcxhr.h
index 84131a916c92..652064787a55 100644
--- a/sound/pci/pcxhr/pcxhr.h
+++ b/sound/pci/pcxhr/pcxhr.h
@@ -27,18 +27,15 @@
#include <linux/mutex.h>
#include <sound/pcm.h>
-#define PCXHR_DRIVER_VERSION 0x000905 /* 0.9.5 */
-#define PCXHR_DRIVER_VERSION_STRING "0.9.5" /* 0.9.5 */
+#define PCXHR_DRIVER_VERSION 0x000804 /* 0.8.4 */
+#define PCXHR_DRIVER_VERSION_STRING "0.8.4" /* 0.8.4 */
-#define PCXHR_MAX_CARDS 6
-#define PCXHR_PLAYBACK_STREAMS 4
+#define PCXHR_MAX_CARDS 6
+#define PCXHR_PLAYBACK_STREAMS 4
-#define PCXHR_GRANULARITY 96 /* min 96 and multiple of 48 */
-/* transfer granularity of pipes and the dsp time (MBOX4) */
-#define PCXHR_GRANULARITY_MIN 96
-/* TODO : granularity could be 64 or 128 */
-#define PCXHR_GRANULARITY_HR22 192 /* granularity for stereo cards */
+#define PCXHR_GRANULARITY 96 /* transfer granularity (should be min 96 and multiple of 48) */
+#define PCXHR_GRANULARITY_MIN 96 /* transfer granularity of pipes and the dsp time (MBOX4) */
struct snd_pcxhr;
struct pcxhr_mgr;
@@ -54,11 +51,6 @@ enum pcxhr_clock_type {
PCXHR_CLOCK_TYPE_AES_2,
PCXHR_CLOCK_TYPE_AES_3,
PCXHR_CLOCK_TYPE_AES_4,
- PCXHR_CLOCK_TYPE_MAX = PCXHR_CLOCK_TYPE_AES_4,
- HR22_CLOCK_TYPE_INTERNAL = PCXHR_CLOCK_TYPE_INTERNAL,
- HR22_CLOCK_TYPE_AES_SYNC,
- HR22_CLOCK_TYPE_AES_1,
- HR22_CLOCK_TYPE_MAX = HR22_CLOCK_TYPE_AES_1,
};
struct pcxhr_mgr {
@@ -69,8 +61,6 @@ struct pcxhr_mgr {
int irq;
- int granularity;
-
/* card access with 1 mem bar and 2 io bar's */
unsigned long port[3];
@@ -93,16 +83,11 @@ struct pcxhr_mgr {
/* hardware interface */
unsigned int dsp_loaded; /* bit flags of loaded dsp indices */
unsigned int dsp_version; /* read from embedded once firmware is loaded */
- int playback_chips;
- int capture_chips;
- int fw_file_set;
- int firmware_num;
- int is_hr_stereo:1;
- int board_has_aes1:1; /* if 1 board has AES1 plug and SRC */
- int board_has_analog:1; /* if 0 the board is digital only */
- int board_has_mic:1; /* if 1 the board has microphone input */
- int board_aes_in_192k:1;/* if 1 the aes input plugs do support 192kHz */
- int mono_capture:1; /* if 1 the board does mono capture */
+ int board_has_analog; /* if 0 the board is digital only */
+ int mono_capture; /* if 1 the board does mono capture */
+ int playback_chips; /* 4 or 6 */
+ int capture_chips; /* 4 or 1 */
+ int firmware_num; /* 41 or 42 */
struct snd_dma_buffer hostport;
@@ -121,9 +106,6 @@ struct pcxhr_mgr {
int async_err_stream_xrun;
int async_err_pipe_xrun;
int async_err_other_last;
-
- unsigned char xlx_cfg; /* copy of PCXHR_XLX_CFG register */
- unsigned char xlx_selmic; /* copy of PCXHR_XLX_SELMIC register */
};
@@ -173,30 +155,24 @@ struct snd_pcxhr {
struct snd_pcm *pcm; /* PCM */
- struct pcxhr_pipe playback_pipe; /* 1 stereo pipe only */
- struct pcxhr_pipe capture_pipe[2]; /* 1 stereo or 2 mono pipes */
+ struct pcxhr_pipe playback_pipe; /* 1 stereo pipe only */
+ struct pcxhr_pipe capture_pipe[2]; /* 1 stereo pipe or 2 mono pipes */
struct pcxhr_stream playback_stream[PCXHR_PLAYBACK_STREAMS];
- struct pcxhr_stream capture_stream[2]; /* 1 stereo or 2 mono streams */
+ struct pcxhr_stream capture_stream[2]; /* 1 stereo stream or 2 mono streams */
int nb_streams_play;
int nb_streams_capt;
- int analog_playback_active[2]; /* Mixer : Master Playback !mute */
- int analog_playback_volume[2]; /* Mixer : Master Playback Volume */
- int analog_capture_volume[2]; /* Mixer : Master Capture Volume */
- int digital_playback_active[PCXHR_PLAYBACK_STREAMS][2];
- int digital_playback_volume[PCXHR_PLAYBACK_STREAMS][2];
- int digital_capture_volume[2]; /* Mixer : Digital Capture Volume */
- int monitoring_active[2]; /* Mixer : Monitoring Active */
- int monitoring_volume[2]; /* Mixer : Monitoring Volume */
- int audio_capture_source; /* Mixer : Audio Capture Source */
- int mic_volume; /* used by cards with MIC only */
- int mic_boost; /* used by cards with MIC only */
- int mic_active; /* used by cards with MIC only */
- int analog_capture_active; /* used by cards with MIC only */
- int phantom_power; /* used by cards with MIC only */
-
- unsigned char aes_bits[5]; /* Mixer : IEC958_AES bits */
+ int analog_playback_active[2]; /* Mixer : Master Playback active (!mute) */
+ int analog_playback_volume[2]; /* Mixer : Master Playback Volume */
+ int analog_capture_volume[2]; /* Mixer : Master Capture Volume */
+ int digital_playback_active[PCXHR_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Active [streams][stereo]*/
+ int digital_playback_volume[PCXHR_PLAYBACK_STREAMS][2]; /* Mixer : Digital Playback Volume [streams][stereo]*/
+ int digital_capture_volume[2]; /* Mixer : Digital Capture Volume [stereo] */
+ int monitoring_active[2]; /* Mixer : Monitoring Active */
+ int monitoring_volume[2]; /* Mixer : Monitoring Volume */
+ int audio_capture_source; /* Mixer : Audio Capture Source */
+ unsigned char aes_bits[5]; /* Mixer : IEC958_AES bits */
};
struct pcxhr_hostport
@@ -208,8 +184,6 @@ struct pcxhr_hostport
/* exported */
int pcxhr_create_pcm(struct snd_pcxhr *chip);
int pcxhr_set_clock(struct pcxhr_mgr *mgr, unsigned int rate);
-int pcxhr_get_external_clock(struct pcxhr_mgr *mgr,
- enum pcxhr_clock_type clock_type,
- int *sample_rate);
+int pcxhr_get_external_clock(struct pcxhr_mgr *mgr, enum pcxhr_clock_type clock_type, int *sample_rate);
#endif /* __SOUND_PCXHR_H */
diff --git a/sound/pci/pcxhr/pcxhr_core.c b/sound/pci/pcxhr/pcxhr_core.c
index d5f18226261d..7143259cfe34 100644
--- a/sound/pci/pcxhr/pcxhr_core.c
+++ b/sound/pci/pcxhr/pcxhr_core.c
@@ -132,15 +132,13 @@ static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int reg,
*read = PCXHR_INPB(mgr, reg);
if ((*read & mask) == bit) {
if (i > 100)
- snd_printdd("ATTENTION! check_reg(%x) "
- "loopcount=%d\n",
+ snd_printdd("ATTENTION! check_reg(%x) loopcount=%d\n",
reg, i);
return 0;
}
i++;
} while (time_after_eq(end_time, jiffies));
- snd_printk(KERN_ERR
- "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=%x\n",
+ snd_printk(KERN_ERR "pcxhr_check_reg_bit: timeout, reg=%x, mask=0x%x, val=0x%x\n",
reg, mask, *read);
return -EIO;
}
@@ -161,22 +159,18 @@ static int pcxhr_check_reg_bit(struct pcxhr_mgr *mgr, unsigned int reg,
#define PCXHR_IT_TEST_XILINX (0x0000003C | PCXHR_MASK_IT_HF1 | \
PCXHR_MASK_IT_MANAGE_HF5)
#define PCXHR_IT_DOWNLOAD_BOOT (0x0000000C | PCXHR_MASK_IT_HF1 | \
- PCXHR_MASK_IT_MANAGE_HF5 | \
- PCXHR_MASK_IT_WAIT)
+ PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT)
#define PCXHR_IT_RESET_BOARD_FUNC (0x0000000C | PCXHR_MASK_IT_HF0 | \
- PCXHR_MASK_IT_MANAGE_HF5 | \
- PCXHR_MASK_IT_WAIT_EXTRA)
+ PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT_EXTRA)
#define PCXHR_IT_DOWNLOAD_DSP (0x0000000C | \
- PCXHR_MASK_IT_MANAGE_HF5 | \
- PCXHR_MASK_IT_WAIT)
+ PCXHR_MASK_IT_MANAGE_HF5 | PCXHR_MASK_IT_WAIT)
#define PCXHR_IT_DEBUG (0x0000005A | PCXHR_MASK_IT_NO_HF0_HF1)
#define PCXHR_IT_RESET_SEMAPHORE (0x0000005C | PCXHR_MASK_IT_NO_HF0_HF1)
#define PCXHR_IT_MESSAGE (0x00000074 | PCXHR_MASK_IT_NO_HF0_HF1)
#define PCXHR_IT_RESET_CHK (0x00000076 | PCXHR_MASK_IT_NO_HF0_HF1)
#define PCXHR_IT_UPDATE_RBUFFER (0x00000078 | PCXHR_MASK_IT_NO_HF0_HF1)
-static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr,
- unsigned int itdsp, int atomic)
+static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr, unsigned int itdsp, int atomic)
{
int err;
unsigned char reg;
@@ -184,21 +178,17 @@ static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr,
if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) {
/* clear hf5 bit */
PCXHR_OUTPL(mgr, PCXHR_PLX_MBOX0,
- PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) &
- ~PCXHR_MBOX0_HF5);
+ PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & ~PCXHR_MBOX0_HF5);
}
if ((itdsp & PCXHR_MASK_IT_NO_HF0_HF1) == 0) {
- reg = (PCXHR_ICR_HI08_RREQ |
- PCXHR_ICR_HI08_TREQ |
- PCXHR_ICR_HI08_HDRQ);
+ reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ;
if (itdsp & PCXHR_MASK_IT_HF0)
reg |= PCXHR_ICR_HI08_HF0;
if (itdsp & PCXHR_MASK_IT_HF1)
reg |= PCXHR_ICR_HI08_HF1;
PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg);
}
- reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) |
- PCXHR_CVR_HI08_HC);
+ reg = (unsigned char)(((itdsp & PCXHR_MASK_EXTRA_INFO) >> 1) | PCXHR_CVR_HI08_HC);
PCXHR_OUTPB(mgr, PCXHR_DSP_CVR, reg);
if (itdsp & PCXHR_MASK_IT_WAIT) {
if (atomic)
@@ -221,14 +211,10 @@ static int pcxhr_send_it_dsp(struct pcxhr_mgr *mgr,
}
if (itdsp & PCXHR_MASK_IT_MANAGE_HF5) {
/* wait for hf5 bit */
- err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0,
- PCXHR_MBOX0_HF5,
- PCXHR_MBOX0_HF5,
- PCXHR_TIMEOUT_DSP,
- &reg);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_PLX_MBOX0, PCXHR_MBOX0_HF5,
+ PCXHR_MBOX0_HF5, PCXHR_TIMEOUT_DSP, &reg);
if (err) {
- snd_printk(KERN_ERR
- "pcxhr_send_it_dsp : TIMEOUT HF5\n");
+ snd_printk(KERN_ERR "pcxhr_send_it_dsp : TIMEOUT HF5\n");
return err;
}
}
@@ -277,8 +263,7 @@ void pcxhr_enable_dsp(struct pcxhr_mgr *mgr)
/*
* load the xilinx image
*/
-int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr,
- const struct firmware *xilinx, int second)
+int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr, const struct firmware *xilinx, int second)
{
unsigned int i;
unsigned int chipsc;
@@ -289,9 +274,7 @@ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr,
/* test first xilinx */
chipsc = PCXHR_INPL(mgr, PCXHR_PLX_CHIPSC);
/* REV01 cards do not support the PCXHR_CHIPSC_GPI_USERI bit anymore */
- /* this bit will always be 1;
- * no possibility to test presence of first xilinx
- */
+ /* this bit will always be 1; no possibility to test presence of first xilinx */
if(second) {
if ((chipsc & PCXHR_CHIPSC_GPI_USERI) == 0) {
snd_printk(KERN_ERR "error loading first xilinx\n");
@@ -307,8 +290,7 @@ int pcxhr_load_xilinx_binary(struct pcxhr_mgr *mgr,
data = *image;
mask = 0x80;
while (mask) {
- chipsc &= ~(PCXHR_CHIPSC_DATA_CLK |
- PCXHR_CHIPSC_DATA_IN);
+ chipsc &= ~(PCXHR_CHIPSC_DATA_CLK | PCXHR_CHIPSC_DATA_IN);
if (data & mask)
chipsc |= PCXHR_CHIPSC_DATA_IN;
PCXHR_OUTPL(mgr, PCXHR_PLX_CHIPSC, chipsc);
@@ -348,20 +330,15 @@ static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp)
data = dsp->data + i;
if (i == 0) {
/* test data header consistency */
- len = (unsigned int)((data[0]<<16) +
- (data[1]<<8) +
- data[2]);
- if (len && (dsp->size != (len + 2) * 3))
+ len = (unsigned int)((data[0]<<16) + (data[1]<<8) + data[2]);
+ if (len && dsp->size != (len + 2) * 3)
return -EINVAL;
}
/* wait DSP ready for new transfer */
- err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
- PCXHR_ISR_HI08_TRDY,
- PCXHR_ISR_HI08_TRDY,
- PCXHR_TIMEOUT_DSP, &dummy);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
+ PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &dummy);
if (err) {
- snd_printk(KERN_ERR
- "dsp loading error at position %d\n", i);
+ snd_printk(KERN_ERR "dsp loading error at position %d\n", i);
return err;
}
/* send host data */
@@ -380,8 +357,7 @@ static int pcxhr_download_dsp(struct pcxhr_mgr *mgr, const struct firmware *dsp)
/*
* load the eeprom image
*/
-int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr,
- const struct firmware *eeprom)
+int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr, const struct firmware *eeprom)
{
int err;
unsigned char reg;
@@ -389,9 +365,7 @@ int pcxhr_load_eeprom_binary(struct pcxhr_mgr *mgr,
/* init value of the ICR register */
reg = PCXHR_ICR_HI08_RREQ | PCXHR_ICR_HI08_TREQ | PCXHR_ICR_HI08_HDRQ;
if (PCXHR_INPL(mgr, PCXHR_PLX_MBOX0) & PCXHR_MBOX0_BOOT_HERE) {
- /* no need to load the eeprom binary,
- * but init the HI08 interface
- */
+ /* no need to load the eeprom binary, but init the HI08 interface */
PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg | PCXHR_ICR_HI08_INIT);
msleep(PCXHR_WAIT_DEFAULT);
PCXHR_OUTPB(mgr, PCXHR_DSP_ICR, reg);
@@ -455,10 +429,8 @@ int pcxhr_load_dsp_binary(struct pcxhr_mgr *mgr, const struct firmware *dsp)
if (err)
return err;
/* wait for chk bit */
- return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
- PCXHR_ISR_HI08_CHK,
- PCXHR_ISR_HI08_CHK,
- PCXHR_TIMEOUT_DSP, &dummy);
+ return pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_CHK,
+ PCXHR_ISR_HI08_CHK, PCXHR_TIMEOUT_DSP, &dummy);
}
@@ -471,8 +443,8 @@ struct pcxhr_cmd_info {
/* RMH status type */
enum {
RMH_SSIZE_FIXED = 0, /* status size fix (st_length = 0..x) */
- RMH_SSIZE_ARG = 1, /* status size given in the LSB byte */
- RMH_SSIZE_MASK = 2, /* status size given in bitmask */
+ RMH_SSIZE_ARG = 1, /* status size given in the LSB byte (used with st_length = 1) */
+ RMH_SSIZE_MASK = 2, /* status size given in bitmask (used with st_length = 1) */
};
/*
@@ -502,7 +474,7 @@ static struct pcxhr_cmd_info pcxhr_dsp_cmds[] = {
[CMD_UPDATE_R_BUFFERS] = { 0x840000, 0, RMH_SSIZE_FIXED },
[CMD_FORMAT_STREAM_OUT] = { 0x860000, 0, RMH_SSIZE_FIXED },
[CMD_FORMAT_STREAM_IN] = { 0x870000, 0, RMH_SSIZE_FIXED },
-[CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED },
+[CMD_STREAM_SAMPLE_COUNT] = { 0x902000, 2, RMH_SSIZE_FIXED }, /* stat_len = nb_streams * 2 */
[CMD_AUDIO_LEVEL_ADJUST] = { 0xc22000, 0, RMH_SSIZE_FIXED },
};
@@ -552,13 +524,10 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
for (i = 0; i < rmh->stat_len; i++) {
/* wait for receiver full */
- err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
- PCXHR_ISR_HI08_RXDF,
- PCXHR_ISR_HI08_RXDF,
- PCXHR_TIMEOUT_DSP, &reg);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,
+ PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);
if (err) {
- snd_printk(KERN_ERR "ERROR RMH stat: "
- "ISR:RXDF=1 (ISR = %x; i=%d )\n",
+ snd_printk(KERN_ERR "ERROR RMH stat: ISR:RXDF=1 (ISR = %x; i=%d )\n",
reg, i);
return err;
}
@@ -568,10 +537,10 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);
/* need to update rmh->stat_len on the fly ?? */
- if (!i) {
+ if (i==0) {
if (rmh->dsp_stat != RMH_SSIZE_FIXED) {
if (rmh->dsp_stat == RMH_SSIZE_ARG) {
- rmh->stat_len = (data & 0x0000ff) + 1;
+ rmh->stat_len = (u16)(data & 0x0000ff) + 1;
data &= 0xffff00;
} else {
/* rmh->dsp_stat == RMH_SSIZE_MASK */
@@ -593,8 +562,7 @@ static int pcxhr_read_rmh_status(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
rmh->stat[i] = data;
}
if (rmh->stat_len > max_stat_len) {
- snd_printdd("PCXHR : rmh->stat_len=%x too big\n",
- rmh->stat_len);
+ snd_printdd("PCXHR : rmh->stat_len=%x too big\n", rmh->stat_len);
rmh->stat_len = max_stat_len;
}
return 0;
@@ -637,8 +605,7 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
data &= 0xff7fff; /* MASK_1_WORD_COMMAND */
#ifdef CONFIG_SND_DEBUG_VERBOSE
if (rmh->cmd_idx < CMD_LAST_INDEX)
- snd_printdd("MSG cmd[0]=%x (%s)\n",
- data, cmd_names[rmh->cmd_idx]);
+ snd_printdd("MSG cmd[0]=%x (%s)\n", data, cmd_names[rmh->cmd_idx]);
#endif
err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
@@ -652,10 +619,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
if (rmh->cmd_len > 1) {
/* send length */
data = rmh->cmd_len - 1;
- err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
- PCXHR_ISR_HI08_TRDY,
- PCXHR_ISR_HI08_TRDY,
- PCXHR_TIMEOUT_DSP, &reg);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_TRDY,
+ PCXHR_ISR_HI08_TRDY, PCXHR_TIMEOUT_DSP, &reg);
if (err)
return err;
PCXHR_OUTPB(mgr, PCXHR_DSP_TXH, (data>>16)&0xFF);
@@ -688,10 +653,8 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
/* test status ISR */
if (reg & PCXHR_ISR_HI08_ERR) {
/* ERROR, wait for receiver full */
- err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR,
- PCXHR_ISR_HI08_RXDF,
- PCXHR_ISR_HI08_RXDF,
- PCXHR_TIMEOUT_DSP, &reg);
+ err = pcxhr_check_reg_bit(mgr, PCXHR_DSP_ISR, PCXHR_ISR_HI08_RXDF,
+ PCXHR_ISR_HI08_RXDF, PCXHR_TIMEOUT_DSP, &reg);
if (err) {
snd_printk(KERN_ERR "ERROR RMH: ISR:RXDF=1 (ISR = %x)\n", reg);
return err;
@@ -700,8 +663,7 @@ static int pcxhr_send_msg_nolock(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
data = PCXHR_INPB(mgr, PCXHR_DSP_TXH) << 16;
data |= PCXHR_INPB(mgr, PCXHR_DSP_TXM) << 8;
data |= PCXHR_INPB(mgr, PCXHR_DSP_TXL);
- snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n",
- rmh->cmd_idx, data);
+ snd_printk(KERN_ERR "ERROR RMH(%d): 0x%x\n", rmh->cmd_idx, data);
err = -EINVAL;
} else {
/* read the response data */
@@ -770,9 +732,8 @@ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh)
static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr)
{
int start_mask = PCXHR_INPL(mgr, PCXHR_PLX_MBOX2);
- /* least segnificant 12 bits are the pipe states
- * for the playback audios
- * next 12 bits are the pipe states for the capture audios
+ /* least segnificant 12 bits are the pipe states for the playback audios */
+ /* next 12 bits are the pipe states for the capture audios
* (PCXHR_PIPE_STATE_CAPTURE_OFFSET)
*/
start_mask &= 0xffffff;
@@ -783,8 +744,7 @@ static inline int pcxhr_pipes_running(struct pcxhr_mgr *mgr)
#define PCXHR_PIPE_STATE_CAPTURE_OFFSET 12
#define MAX_WAIT_FOR_DSP 20
-static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr,
- int audio_mask, int *retry)
+static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr, int audio_mask, int *retry)
{
struct pcxhr_rmh rmh;
int err;
@@ -800,20 +760,17 @@ static int pcxhr_prepair_pipe_start(struct pcxhr_mgr *mgr,
} else {
/* can start capture pipe */
pcxhr_set_pipe_cmd_params(&rmh, 1, audio -
- PCXHR_PIPE_STATE_CAPTURE_OFFSET,
- 0, 0);
+ PCXHR_PIPE_STATE_CAPTURE_OFFSET,
+ 0, 0);
}
err = pcxhr_send_msg(mgr, &rmh);
if (err) {
snd_printk(KERN_ERR
- "error pipe start "
- "(CMD_CAN_START_PIPE) err=%x!\n",
+ "error pipe start (CMD_CAN_START_PIPE) err=%x!\n",
err);
return err;
}
- /* if the pipe couldn't be prepaired for start,
- * retry it later
- */
+ /* if the pipe couldn't be prepaired for start, retry it later */
if (rmh.stat[0] == 0)
*retry |= (1<<audio);
}
@@ -838,14 +795,14 @@ static int pcxhr_stop_pipes(struct pcxhr_mgr *mgr, int audio_mask)
} else {
/* stop capture pipe */
pcxhr_set_pipe_cmd_params(&rmh, 1, audio -
- PCXHR_PIPE_STATE_CAPTURE_OFFSET,
- 0, 0);
+ PCXHR_PIPE_STATE_CAPTURE_OFFSET,
+ 0, 0);
}
err = pcxhr_send_msg(mgr, &rmh);
if (err) {
snd_printk(KERN_ERR
- "error pipe stop "
- "(CMD_STOP_PIPE) err=%x!\n", err);
+ "error pipe stop (CMD_STOP_PIPE) err=%x!\n",
+ err);
return err;
}
}
@@ -865,16 +822,15 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask)
if (audio_mask & 1) {
pcxhr_init_rmh(&rmh, CMD_CONF_PIPE);
if (audio < PCXHR_PIPE_STATE_CAPTURE_OFFSET)
- pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0,
- 1 << audio);
+ pcxhr_set_pipe_cmd_params(&rmh, 0, 0, 0, 1 << audio);
else
pcxhr_set_pipe_cmd_params(&rmh, 1, 0, 0,
1 << (audio - PCXHR_PIPE_STATE_CAPTURE_OFFSET));
err = pcxhr_send_msg(mgr, &rmh);
if (err) {
snd_printk(KERN_ERR
- "error pipe start "
- "(CMD_CONF_PIPE) err=%x!\n", err);
+ "error pipe start (CMD_CONF_PIPE) err=%x!\n",
+ err);
return err;
}
}
@@ -885,9 +841,7 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask)
pcxhr_init_rmh(&rmh, CMD_SEND_IRQA);
err = pcxhr_send_msg(mgr, &rmh);
if (err) {
- snd_printk(KERN_ERR
- "error pipe start (CMD_SEND_IRQA) err=%x!\n",
- err);
+ snd_printk(KERN_ERR "error pipe start (CMD_SEND_IRQA) err=%x!\n", err );
return err;
}
return 0;
@@ -895,8 +849,7 @@ static int pcxhr_toggle_pipes(struct pcxhr_mgr *mgr, int audio_mask)
-int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask,
- int capture_mask, int start)
+int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask, int capture_mask, int start)
{
int state, i, err;
int audio_mask;
@@ -905,23 +858,21 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask,
struct timeval my_tv1, my_tv2;
do_gettimeofday(&my_tv1);
#endif
- audio_mask = (playback_mask |
- (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET));
+ audio_mask = (playback_mask | (capture_mask << PCXHR_PIPE_STATE_CAPTURE_OFFSET));
/* current pipe state (playback + record) */
state = pcxhr_pipes_running(mgr);
snd_printdd("pcxhr_set_pipe_state %s (mask %x current %x)\n",
start ? "START" : "STOP", audio_mask, state);
if (start) {
- /* start only pipes that are not yet started */
- audio_mask &= ~state;
+ audio_mask &= ~state; /* start only pipes that are not yet started */
state = audio_mask;
for (i = 0; i < MAX_WAIT_FOR_DSP; i++) {
err = pcxhr_prepair_pipe_start(mgr, state, &state);
if (err)
return err;
if (state == 0)
- break; /* success, all pipes prepaired */
- mdelay(1); /* wait 1 millisecond and retry */
+ break; /* success, all pipes prepaired for start */
+ mdelay(1); /* otherwise wait 1 millisecond and retry */
}
} else {
audio_mask &= state; /* stop only pipes that are started */
@@ -940,7 +891,7 @@ int pcxhr_set_pipe_state(struct pcxhr_mgr *mgr, int playback_mask,
if ((state & audio_mask) == (start ? audio_mask : 0))
break;
if (++i >= MAX_WAIT_FOR_DSP * 100) {
- snd_printk(KERN_ERR "error pipe start/stop\n");
+ snd_printk(KERN_ERR "error pipe start/stop (ED_NO_RESPONSE_AT_IRQA)\n");
return -EBUSY;
}
udelay(10); /* wait 10 microseconds */
@@ -967,8 +918,7 @@ int pcxhr_write_io_num_reg_cont(struct pcxhr_mgr *mgr, unsigned int mask,
spin_lock_irqsave(&mgr->msg_lock, flags);
if ((mgr->io_num_reg_cont & mask) == value) {
- snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n",
- mask, value);
+ snd_printdd("IO_NUM_REG_CONT mask %x already is set to %x\n", mask, value);
if (changed)
*changed = 0;
spin_unlock_irqrestore(&mgr->msg_lock, flags);
@@ -1021,8 +971,7 @@ static int pcxhr_handle_async_err(struct pcxhr_mgr *mgr, u32 err,
err = ((err >> 12) & 0xfff);
if (!err)
return 0;
- snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n",
- err_src_name[err_src],
+ snd_printdd("CMD_ASYNC : Error %s %s Pipe %d err=%x\n", err_src_name[err_src],
is_capture ? "Record" : "Play", pipe, err);
if (err == 0xe01)
mgr->async_err_stream_xrun++;
@@ -1047,13 +996,6 @@ void pcxhr_msg_tasklet(unsigned long arg)
snd_printdd("TASKLET : PCXHR_IRQ_TIME_CODE event occured\n");
if (mgr->src_it_dsp & PCXHR_IRQ_NOTIFY)
snd_printdd("TASKLET : PCXHR_IRQ_NOTIFY event occured\n");
- if (mgr->src_it_dsp & (PCXHR_IRQ_FREQ_CHANGE | PCXHR_IRQ_TIME_CODE)) {
- /* clear events FREQ_CHANGE and TIME_CODE */
- pcxhr_init_rmh(prmh, CMD_TEST_IT);
- err = pcxhr_send_msg(mgr, prmh);
- snd_printdd("CMD_TEST_IT : err=%x, stat=%x\n",
- err, prmh->stat[0]);
- }
if (mgr->src_it_dsp & PCXHR_IRQ_ASYNC) {
snd_printdd("TASKLET : PCXHR_IRQ_ASYNC event occured\n");
@@ -1063,22 +1005,18 @@ void pcxhr_msg_tasklet(unsigned long arg)
prmh->stat_len = PCXHR_SIZE_MAX_LONG_STATUS;
err = pcxhr_send_msg(mgr, prmh);
if (err)
- snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n",
- err);
+ snd_printk(KERN_ERR "ERROR pcxhr_msg_tasklet=%x;\n", err);
i = 1;
while (i < prmh->stat_len) {
- int nb_audio = ((prmh->stat[i] >> FIELD_SIZE) &
- MASK_FIRST_FIELD);
- int nb_stream = ((prmh->stat[i] >> (2*FIELD_SIZE)) &
- MASK_FIRST_FIELD);
+ int nb_audio = (prmh->stat[i] >> FIELD_SIZE) & MASK_FIRST_FIELD;
+ int nb_stream = (prmh->stat[i] >> (2*FIELD_SIZE)) & MASK_FIRST_FIELD;
int pipe = prmh->stat[i] & MASK_FIRST_FIELD;
int is_capture = prmh->stat[i] & 0x400000;
u32 err2;
if (prmh->stat[i] & 0x800000) { /* if BIT_END */
snd_printdd("TASKLET : End%sPipe %d\n",
- is_capture ? "Record" : "Play",
- pipe);
+ is_capture ? "Record" : "Play", pipe);
}
i++;
err2 = prmh->stat[i] ? prmh->stat[i] : prmh->stat[i+1];
@@ -1124,7 +1062,7 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr,
pcxhr_init_rmh(&rmh, CMD_STREAM_SAMPLE_COUNT);
pcxhr_set_pipe_cmd_params(&rmh, stream->pipe->is_capture,
stream->pipe->first_audio, 0, stream_mask);
- /* rmh.stat_len = 2; */ /* 2 resp data for each stream of the pipe */
+ /* rmh.stat_len = 2; */ /* 2 resp data for each stream of the pipe */
err = pcxhr_send_msg(mgr, &rmh);
if (err)
@@ -1134,21 +1072,18 @@ static u_int64_t pcxhr_stream_read_position(struct pcxhr_mgr *mgr,
hw_sample_count += (u_int64_t)rmh.stat[1];
snd_printdd("stream %c%d : abs samples real(%ld) timer(%ld)\n",
- stream->pipe->is_capture ? 'C' : 'P',
- stream->substream->number,
+ stream->pipe->is_capture ? 'C':'P', stream->substream->number,
(long unsigned int)hw_sample_count,
(long unsigned int)(stream->timer_abs_periods +
- stream->timer_period_frag +
- mgr->granularity));
+ stream->timer_period_frag + PCXHR_GRANULARITY));
+
return hw_sample_count;
}
static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
- struct pcxhr_stream *stream,
- int samples_to_add)
+ struct pcxhr_stream *stream, int samples_to_add)
{
- if (stream->substream &&
- (stream->status == PCXHR_STREAM_STATUS_RUNNING)) {
+ if (stream->substream && (stream->status == PCXHR_STREAM_STATUS_RUNNING)) {
u_int64_t new_sample_count;
int elapsed = 0;
int hardware_read = 0;
@@ -1157,22 +1092,20 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
if (samples_to_add < 0) {
stream->timer_is_synced = 0;
/* add default if no hardware_read possible */
- samples_to_add = mgr->granularity;
+ samples_to_add = PCXHR_GRANULARITY;
}
if (!stream->timer_is_synced) {
- if ((stream->timer_abs_periods != 0) ||
- ((stream->timer_period_frag + samples_to_add) >=
- runtime->period_size)) {
- new_sample_count =
- pcxhr_stream_read_position(mgr, stream);
+ if (stream->timer_abs_periods != 0 ||
+ stream->timer_period_frag + PCXHR_GRANULARITY >=
+ runtime->period_size) {
+ new_sample_count = pcxhr_stream_read_position(mgr, stream);
hardware_read = 1;
- if (new_sample_count >= mgr->granularity) {
- /* sub security offset because of
- * jitter and finer granularity of
- * dsp time (MBOX4)
+ if (new_sample_count >= PCXHR_GRANULARITY_MIN) {
+ /* sub security offset because of jitter and
+ * finer granularity of dsp time (MBOX4)
*/
- new_sample_count -= mgr->granularity;
+ new_sample_count -= PCXHR_GRANULARITY_MIN;
stream->timer_is_synced = 1;
}
}
@@ -1195,15 +1128,12 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
stream->timer_buf_periods = 0;
stream->timer_abs_periods = new_elapse_pos;
}
- if (new_sample_count >= stream->timer_abs_periods) {
- stream->timer_period_frag =
- (u_int32_t)(new_sample_count -
- stream->timer_abs_periods);
- } else {
- snd_printk(KERN_ERR
- "ERROR new_sample_count too small ??? %ld\n",
+ if (new_sample_count >= stream->timer_abs_periods)
+ stream->timer_period_frag = (u_int32_t)(new_sample_count -
+ stream->timer_abs_periods);
+ else
+ snd_printk(KERN_ERR "ERROR new_sample_count too small ??? %lx\n",
(long unsigned int)new_sample_count);
- }
if (elapsed) {
spin_unlock(&mgr->lock);
@@ -1213,6 +1143,7 @@ static void pcxhr_update_timer_pos(struct pcxhr_mgr *mgr,
}
}
+
irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
{
struct pcxhr_mgr *mgr = dev_id;
@@ -1225,8 +1156,7 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
reg = PCXHR_INPL(mgr, PCXHR_PLX_IRQCS);
if (! (reg & PCXHR_IRQCS_ACTIVE_PCIDB)) {
spin_unlock(&mgr->lock);
- /* this device did not cause the interrupt */
- return IRQ_NONE;
+ return IRQ_NONE; /* this device did not cause the interrupt */
}
/* clear interrupt */
@@ -1237,12 +1167,10 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
if (reg & PCXHR_IRQ_TIMER) {
int timer_toggle = reg & PCXHR_IRQ_TIMER;
/* is a 24 bit counter */
- int dsp_time_new =
- PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
+ int dsp_time_new = PCXHR_INPL(mgr, PCXHR_PLX_MBOX4) & PCXHR_DSP_TIME_MASK;
int dsp_time_diff = dsp_time_new - mgr->dsp_time_last;
- if ((dsp_time_diff < 0) &&
- (mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID)) {
+ if (dsp_time_diff < 0 && mgr->dsp_time_last != PCXHR_DSP_TIME_INVALID) {
snd_printdd("ERROR DSP TIME old(%d) new(%d) -> "
"resynchronize all streams\n",
mgr->dsp_time_last, dsp_time_new);
@@ -1250,49 +1178,40 @@ irqreturn_t pcxhr_interrupt(int irq, void *dev_id)
}
#ifdef CONFIG_SND_DEBUG_VERBOSE
if (dsp_time_diff == 0)
- snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n",
- dsp_time_new);
- else if (dsp_time_diff >= (2*mgr->granularity))
+ snd_printdd("ERROR DSP TIME NO DIFF time(%d)\n", dsp_time_new);
+ else if (dsp_time_diff >= (2*PCXHR_GRANULARITY))
snd_printdd("ERROR DSP TIME TOO BIG old(%d) add(%d)\n",
- mgr->dsp_time_last,
- dsp_time_new - mgr->dsp_time_last);
- else if (dsp_time_diff % mgr->granularity)
- snd_printdd("ERROR DSP TIME increased by %d\n",
- dsp_time_diff);
+ mgr->dsp_time_last, dsp_time_new - mgr->dsp_time_last);
#endif
mgr->dsp_time_last = dsp_time_new;
- if (timer_toggle == mgr->timer_toggle) {
+ if (timer_toggle == mgr->timer_toggle)
snd_printdd("ERROR TIMER TOGGLE\n");
- mgr->dsp_time_err++;
- }
mgr->timer_toggle = timer_toggle;
reg &= ~PCXHR_IRQ_TIMER;
for (i = 0; i < mgr->num_cards; i++) {
chip = mgr->chip[i];
for (j = 0; j < chip->nb_streams_capt; j++)
- pcxhr_update_timer_pos(mgr,
- &chip->capture_stream[j],
- dsp_time_diff);
+ pcxhr_update_timer_pos(mgr, &chip->capture_stream[j],
+ dsp_time_diff);
}
for (i = 0; i < mgr->num_cards; i++) {
chip = mgr->chip[i];
for (j = 0; j < chip->nb_streams_play; j++)
- pcxhr_update_timer_pos(mgr,
- &chip->playback_stream[j],
- dsp_time_diff);
+ pcxhr_update_timer_pos(mgr, &chip->playback_stream[j],
+ dsp_time_diff);
}
}
/* other irq's handled in the tasklet */
if (reg & PCXHR_IRQ_MASK) {
- if (reg & PCXHR_IRQ_ASYNC) {
- /* as we didn't request any async notifications,
- * some kind of xrun error will probably occured
- */
- /* better resynchronize all streams next interrupt : */
- mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
- }
+
+ /* as we didn't request any notifications, some kind of xrun error
+ * will probably occured
+ */
+ /* better resynchronize all streams next interrupt : */
+ mgr->dsp_time_last = PCXHR_DSP_TIME_INVALID;
+
mgr->src_it_dsp = reg;
tasklet_hi_schedule(&mgr->msg_taskq);
}
diff --git a/sound/pci/pcxhr/pcxhr_core.h b/sound/pci/pcxhr/pcxhr_core.h
index bbbd66d13a64..d9a4ab609875 100644
--- a/sound/pci/pcxhr/pcxhr_core.h
+++ b/sound/pci/pcxhr/pcxhr_core.h
@@ -65,7 +65,7 @@ enum {
CMD_RESYNC_AUDIO_INPUTS, /* cmd_len = 1 stat_len = 0 */
CMD_GET_DSP_RESOURCES, /* cmd_len = 1 stat_len = 4 */
CMD_SET_TIMER_INTERRUPT, /* cmd_len = 1 stat_len = 0 */
- CMD_RES_PIPE, /* cmd_len >=2 stat_len = 0 */
+ CMD_RES_PIPE, /* cmd_len = 2 stat_len = 0 */
CMD_FREE_PIPE, /* cmd_len = 1 stat_len = 0 */
CMD_CONF_PIPE, /* cmd_len = 2 stat_len = 0 */
CMD_STOP_PIPE, /* cmd_len = 1 stat_len = 0 */
@@ -96,8 +96,6 @@ void pcxhr_init_rmh(struct pcxhr_rmh *rmh, int cmd);
void pcxhr_set_pipe_cmd_params(struct pcxhr_rmh* rmh, int capture, unsigned int param1,
unsigned int param2, unsigned int param3);
-#define DSP_EXT_CMD_SET(x) (x->dsp_version > 0x012800)
-
/*
send the rmh
*/
@@ -112,7 +110,6 @@ int pcxhr_send_msg(struct pcxhr_mgr *mgr, struct pcxhr_rmh *rmh);
#define IO_NUM_REG_STATUS 5
#define IO_NUM_REG_CUER 10
#define IO_NUM_UER_CHIP_REG 11
-#define IO_NUM_REG_CONFIG_SRC 12
#define IO_NUM_REG_OUT_ANA_LEVEL 20
#define IO_NUM_REG_IN_ANA_LEVEL 21
diff --git a/sound/pci/pcxhr/pcxhr_hwdep.c b/sound/pci/pcxhr/pcxhr_hwdep.c
index 592743a298b0..96640d9c227d 100644
--- a/sound/pci/pcxhr/pcxhr_hwdep.c
+++ b/sound/pci/pcxhr/pcxhr_hwdep.c
@@ -31,7 +31,6 @@
#include "pcxhr_mixer.h"
#include "pcxhr_hwdep.h"
#include "pcxhr_core.h"
-#include "pcxhr_mix22.h"
#if defined(CONFIG_FW_LOADER) || defined(CONFIG_FW_LOADER_MODULE)
@@ -41,10 +40,10 @@
#endif
-static int pcxhr_sub_init(struct pcxhr_mgr *mgr);
/*
* get basic information and init pcxhr card
*/
+
static int pcxhr_init_board(struct pcxhr_mgr *mgr)
{
int err;
@@ -69,7 +68,7 @@ static int pcxhr_init_board(struct pcxhr_mgr *mgr)
if ((rmh.stat[0] & MASK_FIRST_FIELD) != mgr->playback_chips * 2)
return -EINVAL;
/* test 8 or 2 phys in */
- if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) <
+ if (((rmh.stat[0] >> (2 * FIELD_SIZE)) & MASK_FIRST_FIELD) !=
mgr->capture_chips * 2)
return -EINVAL;
/* test max nb substream per board */
@@ -78,34 +77,20 @@ static int pcxhr_init_board(struct pcxhr_mgr *mgr)
/* test max nb substream per pipe */
if (((rmh.stat[1] >> 7) & 0x5F) < PCXHR_PLAYBACK_STREAMS)
return -EINVAL;
- snd_printdd("supported formats : playback=%x capture=%x\n",
- rmh.stat[2], rmh.stat[3]);
pcxhr_init_rmh(&rmh, CMD_VERSION);
/* firmware num for DSP */
rmh.cmd[0] |= mgr->firmware_num;
/* transfer granularity in samples (should be multiple of 48) */
- rmh.cmd[1] = (1<<23) + mgr->granularity;
+ rmh.cmd[1] = (1<<23) + PCXHR_GRANULARITY;
rmh.cmd_len = 2;
err = pcxhr_send_msg(mgr, &rmh);
if (err)
return err;
- snd_printdd("PCXHR DSP version is %d.%d.%d\n", (rmh.stat[0]>>16)&0xff,
- (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff);
+ snd_printdd("PCXHR DSP version is %d.%d.%d\n",
+ (rmh.stat[0]>>16)&0xff, (rmh.stat[0]>>8)&0xff, rmh.stat[0]&0xff);
mgr->dsp_version = rmh.stat[0];
- if (mgr->is_hr_stereo)
- err = hr222_sub_init(mgr);
- else
- err = pcxhr_sub_init(mgr);
- return err;
-}
-
-static int pcxhr_sub_init(struct pcxhr_mgr *mgr)
-{
- int err;
- struct pcxhr_rmh rmh;
-
/* get options */
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
rmh.cmd[0] |= IO_NUM_REG_STATUS;
@@ -115,22 +100,20 @@ static int pcxhr_sub_init(struct pcxhr_mgr *mgr)
if (err)
return err;
- if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) ==
- REG_STATUS_OPT_ANALOG_BOARD)
- mgr->board_has_analog = 1; /* analog addon board found */
+ if ((rmh.stat[1] & REG_STATUS_OPT_DAUGHTER_MASK) == REG_STATUS_OPT_ANALOG_BOARD)
+ mgr->board_has_analog = 1; /* analog addon board available */
+ else
+ /* analog addon board not available -> no support for instance */
+ return -EINVAL;
/* unmute inputs */
err = pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
REG_CONT_UNMUTE_INPUTS, NULL);
if (err)
return err;
- /* unmute outputs (a write to IO_NUM_REG_MUTE_OUT mutes!) */
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
+ /* unmute outputs */
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ); /* a write to IO_NUM_REG_MUTE_OUT mutes! */
rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
- if (DSP_EXT_CMD_SET(mgr)) {
- rmh.cmd[1] = 1; /* unmute digital plugs */
- rmh.cmd_len = 2;
- }
err = pcxhr_send_msg(mgr, &rmh);
return err;
}
@@ -141,25 +124,19 @@ void pcxhr_reset_board(struct pcxhr_mgr *mgr)
if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX)) {
/* mute outputs */
- if (!mgr->is_hr_stereo) {
/* a read to IO_NUM_REG_MUTE_OUT register unmutes! */
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
rmh.cmd[0] |= IO_NUM_REG_MUTE_OUT;
pcxhr_send_msg(mgr, &rmh);
/* mute inputs */
- pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS,
- 0, NULL);
- }
- /* stereo cards mute with reset of dsp */
+ pcxhr_write_io_num_reg_cont(mgr, REG_CONT_UNMUTE_INPUTS, 0, NULL);
}
/* reset pcxhr dsp */
- if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX))
+ if (mgr->dsp_loaded & ( 1 << PCXHR_FIRMWARE_DSP_EPRM_INDEX))
pcxhr_reset_dsp(mgr);
/* reset second xilinx */
- if (mgr->dsp_loaded & (1 << PCXHR_FIRMWARE_XLX_COM_INDEX)) {
+ if (mgr->dsp_loaded & ( 1 << PCXHR_FIRMWARE_XLX_COM_INDEX))
pcxhr_reset_xilinx_com(mgr);
- mgr->dsp_loaded = 1;
- }
return;
}
@@ -167,9 +144,8 @@ void pcxhr_reset_board(struct pcxhr_mgr *mgr)
/*
* allocate a playback/capture pipe (pcmp0/pcmc0)
*/
-static int pcxhr_dsp_allocate_pipe(struct pcxhr_mgr *mgr,
- struct pcxhr_pipe *pipe,
- int is_capture, int pin)
+static int pcxhr_dsp_allocate_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe,
+ int is_capture, int pin)
{
int stream_count, audio_count;
int err;
@@ -185,23 +161,15 @@ static int pcxhr_dsp_allocate_pipe(struct pcxhr_mgr *mgr,
stream_count = PCXHR_PLAYBACK_STREAMS;
audio_count = 2; /* always stereo */
}
- snd_printdd("snd_add_ref_pipe pin(%d) pcm%c0\n",
- pin, is_capture ? 'c' : 'p');
+ snd_printdd("snd_add_ref_pipe pin(%d) pcm%c0\n", pin, is_capture ? 'c' : 'p');
pipe->is_capture = is_capture;
pipe->first_audio = pin;
/* define pipe (P_PCM_ONLY_MASK (0x020000) is not necessary) */
pcxhr_init_rmh(&rmh, CMD_RES_PIPE);
- pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin,
- audio_count, stream_count);
- rmh.cmd[1] |= 0x020000; /* add P_PCM_ONLY_MASK */
- if (DSP_EXT_CMD_SET(mgr)) {
- /* add channel mask to command */
- rmh.cmd[rmh.cmd_len++] = (audio_count == 1) ? 0x01 : 0x03;
- }
+ pcxhr_set_pipe_cmd_params(&rmh, is_capture, pin, audio_count, stream_count);
err = pcxhr_send_msg(mgr, &rmh);
if (err < 0) {
- snd_printk(KERN_ERR "error pipe allocation "
- "(CMD_RES_PIPE) err=%x!\n", err);
+ snd_printk(KERN_ERR "error pipe allocation (CMD_RES_PIPE) err=%x!\n", err );
return err;
}
pipe->status = PCXHR_PIPE_DEFINED;
@@ -231,12 +199,10 @@ static int pcxhr_dsp_free_pipe( struct pcxhr_mgr *mgr, struct pcxhr_pipe *pipe)
snd_printk(KERN_ERR "error stopping pipe!\n");
/* release the pipe */
pcxhr_init_rmh(&rmh, CMD_FREE_PIPE);
- pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio,
- 0, 0);
+ pcxhr_set_pipe_cmd_params(&rmh, pipe->is_capture, pipe->first_audio, 0, 0);
err = pcxhr_send_msg(mgr, &rmh);
if (err < 0)
- snd_printk(KERN_ERR "error pipe release "
- "(CMD_FREE_PIPE) err(%x)\n", err);
+ snd_printk(KERN_ERR "error pipe release (CMD_FREE_PIPE) err(%x)\n", err);
pipe->status = PCXHR_PIPE_UNDEFINED;
return err;
}
@@ -282,16 +248,15 @@ static int pcxhr_start_pipes(struct pcxhr_mgr *mgr)
for (i = 0; i < mgr->num_cards; i++) {
chip = mgr->chip[i];
if (chip->nb_streams_play)
- playback_mask |= 1 << chip->playback_pipe.first_audio;
+ playback_mask |= (1 << chip->playback_pipe.first_audio);
for (j = 0; j < chip->nb_streams_capt; j++)
- capture_mask |= 1 << chip->capture_pipe[j].first_audio;
+ capture_mask |= (1 << chip->capture_pipe[j].first_audio);
}
return pcxhr_set_pipe_state(mgr, playback_mask, capture_mask, 1);
}
-static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index,
- const struct firmware *dsp)
+static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index, const struct firmware *dsp)
{
int err, card_index;
@@ -365,33 +330,22 @@ static int pcxhr_dsp_load(struct pcxhr_mgr *mgr, int index,
int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
{
- static char *fw_files[][5] = {
- [0] = { "xlxint.dat", "xlxc882hr.dat",
- "dspe882.e56", "dspb882hr.b56", "dspd882.d56" },
- [1] = { "xlxint.dat", "xlxc882e.dat",
- "dspe882.e56", "dspb882e.b56", "dspd882.d56" },
- [2] = { "xlxint.dat", "xlxc1222hr.dat",
- "dspe882.e56", "dspb1222hr.b56", "dspd1222.d56" },
- [3] = { "xlxint.dat", "xlxc1222e.dat",
- "dspe882.e56", "dspb1222e.b56", "dspd1222.d56" },
- [4] = { NULL, "xlxc222.dat",
- "dspe924.e56", "dspb924.b56", "dspd222.d56" },
- [5] = { NULL, "xlxc924.dat",
- "dspe924.e56", "dspb924.b56", "dspd222.d56" },
+ static char *fw_files[5] = {
+ "xi_1_882.dat",
+ "xc_1_882.dat",
+ "e321_512.e56",
+ "b321_512.b56",
+ "d321_512.d56"
};
char path[32];
const struct firmware *fw_entry;
int i, err;
- int fw_set = mgr->fw_file_set;
- for (i = 0; i < 5; i++) {
- if (!fw_files[fw_set][i])
- continue;
- sprintf(path, "pcxhr/%s", fw_files[fw_set][i]);
+ for (i = 0; i < ARRAY_SIZE(fw_files); i++) {
+ sprintf(path, "pcxhr/%s", fw_files[i]);
if (request_firmware(&fw_entry, path, &mgr->pci->dev)) {
- snd_printk(KERN_ERR "pcxhr: can't load firmware %s\n",
- path);
+ snd_printk(KERN_ERR "pcxhr: can't load firmware %s\n", path);
return -ENOENT;
}
/* fake hwdep dsp record */
@@ -404,26 +358,11 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
return 0;
}
-MODULE_FIRMWARE("pcxhr/xlxint.dat");
-MODULE_FIRMWARE("pcxhr/xlxc882hr.dat");
-MODULE_FIRMWARE("pcxhr/xlxc882e.dat");
-MODULE_FIRMWARE("pcxhr/dspe882.e56");
-MODULE_FIRMWARE("pcxhr/dspb882hr.b56");
-MODULE_FIRMWARE("pcxhr/dspb882e.b56");
-MODULE_FIRMWARE("pcxhr/dspd882.d56");
-
-MODULE_FIRMWARE("pcxhr/xlxc1222hr.dat");
-MODULE_FIRMWARE("pcxhr/xlxc1222e.dat");
-MODULE_FIRMWARE("pcxhr/dspb1222hr.b56");
-MODULE_FIRMWARE("pcxhr/dspb1222e.b56");
-MODULE_FIRMWARE("pcxhr/dspd1222.d56");
-
-MODULE_FIRMWARE("pcxhr/xlxc222.dat");
-MODULE_FIRMWARE("pcxhr/xlxc924.dat");
-MODULE_FIRMWARE("pcxhr/dspe924.e56");
-MODULE_FIRMWARE("pcxhr/dspb924.b56");
-MODULE_FIRMWARE("pcxhr/dspd222.d56");
-
+MODULE_FIRMWARE("pcxhr/xi_1_882.dat");
+MODULE_FIRMWARE("pcxhr/xc_1_882.dat");
+MODULE_FIRMWARE("pcxhr/e321_512.e56");
+MODULE_FIRMWARE("pcxhr/b321_512.b56");
+MODULE_FIRMWARE("pcxhr/d321_512.d56");
#else /* old style firmware loading */
@@ -434,8 +373,7 @@ MODULE_FIRMWARE("pcxhr/dspd222.d56");
static int pcxhr_hwdep_dsp_status(struct snd_hwdep *hw,
struct snd_hwdep_dsp_status *info)
{
- struct pcxhr_mgr *mgr = hw->private_data;
- sprintf(info->id, "pcxhr%d", mgr->fw_file_set);
+ strcpy(info->id, "pcxhr");
info->num_dsps = PCXHR_FIRMWARE_FILES_MAX_INDEX;
if (hw->dsp_loaded & (1 << PCXHR_FIRMWARE_DSP_MAIN_INDEX))
@@ -455,8 +393,8 @@ static int pcxhr_hwdep_dsp_load(struct snd_hwdep *hw,
fw.size = dsp->length;
fw.data = vmalloc(fw.size);
if (! fw.data) {
- snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image "
- "(%lu bytes)\n", (unsigned long)fw.size);
+ snd_printk(KERN_ERR "pcxhr: cannot allocate dsp image (%lu bytes)\n",
+ (unsigned long)fw.size);
return -ENOMEM;
}
if (copy_from_user((void *)fw.data, dsp->image, dsp->length)) {
@@ -486,11 +424,8 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
int err;
struct snd_hwdep *hw;
- /* only create hwdep interface for first cardX
- * (see "index" module parameter)
- */
- err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw);
- if (err < 0)
+ /* only create hwdep interface for first cardX (see "index" module parameter)*/
+ if ((err = snd_hwdep_new(mgr->chip[0]->card, PCXHR_HWDEP_ID, 0, &hw)) < 0)
return err;
hw->iface = SNDRV_HWDEP_IFACE_PCXHR;
@@ -500,13 +435,10 @@ int pcxhr_setup_firmware(struct pcxhr_mgr *mgr)
hw->ops.dsp_status = pcxhr_hwdep_dsp_status;
hw->ops.dsp_load = pcxhr_hwdep_dsp_load;
hw->exclusive = 1;
- /* stereo cards don't need fw_file_0 -> dsp_loaded = 1 */
- hw->dsp_loaded = mgr->is_hr_stereo ? 1 : 0;
mgr->dsp_loaded = 0;
sprintf(hw->name, PCXHR_HWDEP_ID);
- err = snd_card_register(mgr->chip[0]->card);
- if (err < 0)
+ if ((err = snd_card_register(mgr->chip[0]->card)) < 0)
return err;
return 0;
}
diff --git a/sound/pci/pcxhr/pcxhr_mix22.c b/sound/pci/pcxhr/pcxhr_mix22.c
deleted file mode 100644
index ff019126b672..000000000000
--- a/sound/pci/pcxhr/pcxhr_mix22.c
+++ /dev/null
@@ -1,820 +0,0 @@
-/*
- * Driver for Digigram pcxhr compatible soundcards
- *
- * mixer interface for stereo cards
- *
- * Copyright (c) 2004 by Digigram <alsa@digigram.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <sound/core.h>
-#include <sound/control.h>
-#include <sound/tlv.h>
-#include <sound/asoundef.h>
-#include "pcxhr.h"
-#include "pcxhr_core.h"
-#include "pcxhr_mix22.h"
-
-
-/* registers used on the DSP and Xilinx (port 2) : HR stereo cards only */
-#define PCXHR_DSP_RESET 0x20
-#define PCXHR_XLX_CFG 0x24
-#define PCXHR_XLX_RUER 0x28
-#define PCXHR_XLX_DATA 0x2C
-#define PCXHR_XLX_STATUS 0x30
-#define PCXHR_XLX_LOFREQ 0x34
-#define PCXHR_XLX_HIFREQ 0x38
-#define PCXHR_XLX_CSUER 0x3C
-#define PCXHR_XLX_SELMIC 0x40
-
-#define PCXHR_DSP 2
-
-/* byte access only ! */
-#define PCXHR_INPB(mgr, x) inb((mgr)->port[PCXHR_DSP] + (x))
-#define PCXHR_OUTPB(mgr, x, data) outb((data), (mgr)->port[PCXHR_DSP] + (x))
-
-
-/* values for PCHR_DSP_RESET register */
-#define PCXHR_DSP_RESET_DSP 0x01
-#define PCXHR_DSP_RESET_MUTE 0x02
-#define PCXHR_DSP_RESET_CODEC 0x08
-
-/* values for PCHR_XLX_CFG register */
-#define PCXHR_CFG_SYNCDSP_MASK 0x80
-#define PCXHR_CFG_DEPENDENCY_MASK 0x60
-#define PCXHR_CFG_INDEPENDANT_SEL 0x00
-#define PCXHR_CFG_MASTER_SEL 0x40
-#define PCXHR_CFG_SLAVE_SEL 0x20
-#define PCXHR_CFG_DATA_UER1_SEL_MASK 0x10 /* 0 (UER0), 1(UER1) */
-#define PCXHR_CFG_DATAIN_SEL_MASK 0x08 /* 0 (ana), 1 (UER) */
-#define PCXHR_CFG_SRC_MASK 0x04 /* 0 (Bypass), 1 (SRC Actif) */
-#define PCXHR_CFG_CLOCK_UER1_SEL_MASK 0x02 /* 0 (UER0), 1(UER1) */
-#define PCXHR_CFG_CLOCKIN_SEL_MASK 0x01 /* 0 (internal), 1 (AES/EBU) */
-
-/* values for PCHR_XLX_DATA register */
-#define PCXHR_DATA_CODEC 0x80
-#define AKM_POWER_CONTROL_CMD 0xA007
-#define AKM_RESET_ON_CMD 0xA100
-#define AKM_RESET_OFF_CMD 0xA103
-#define AKM_CLOCK_INF_55K_CMD 0xA240
-#define AKM_CLOCK_SUP_55K_CMD 0xA24D
-#define AKM_MUTE_CMD 0xA38D
-#define AKM_UNMUTE_CMD 0xA30D
-#define AKM_LEFT_LEVEL_CMD 0xA600
-#define AKM_RIGHT_LEVEL_CMD 0xA700
-
-/* values for PCHR_XLX_STATUS register - READ */
-#define PCXHR_STAT_SRC_LOCK 0x01
-#define PCXHR_STAT_LEVEL_IN 0x02
-#define PCXHR_STAT_MIC_CAPS 0x10
-/* values for PCHR_XLX_STATUS register - WRITE */
-#define PCXHR_STAT_FREQ_SYNC_MASK 0x01
-#define PCXHR_STAT_FREQ_UER1_MASK 0x02
-#define PCXHR_STAT_FREQ_SAVE_MASK 0x80
-
-/* values for PCHR_XLX_CSUER register */
-#define PCXHR_SUER1_BIT_U_READ_MASK 0x80
-#define PCXHR_SUER1_BIT_C_READ_MASK 0x40
-#define PCXHR_SUER1_DATA_PRESENT_MASK 0x20
-#define PCXHR_SUER1_CLOCK_PRESENT_MASK 0x10
-#define PCXHR_SUER_BIT_U_READ_MASK 0x08
-#define PCXHR_SUER_BIT_C_READ_MASK 0x04
-#define PCXHR_SUER_DATA_PRESENT_MASK 0x02
-#define PCXHR_SUER_CLOCK_PRESENT_MASK 0x01
-
-#define PCXHR_SUER_BIT_U_WRITE_MASK 0x02
-#define PCXHR_SUER_BIT_C_WRITE_MASK 0x01
-
-/* values for PCXHR_XLX_SELMIC register - WRITE */
-#define PCXHR_SELMIC_PREAMPLI_OFFSET 2
-#define PCXHR_SELMIC_PREAMPLI_MASK 0x0C
-#define PCXHR_SELMIC_PHANTOM_ALIM 0x80
-
-
-static const unsigned char g_hr222_p_level[] = {
- 0x00, /* [000] -49.5 dB: AKM[000] = -1.#INF dB (mute) */
- 0x01, /* [001] -49.0 dB: AKM[001] = -48.131 dB (diff=0.86920 dB) */
- 0x01, /* [002] -48.5 dB: AKM[001] = -48.131 dB (diff=0.36920 dB) */
- 0x01, /* [003] -48.0 dB: AKM[001] = -48.131 dB (diff=0.13080 dB) */
- 0x01, /* [004] -47.5 dB: AKM[001] = -48.131 dB (diff=0.63080 dB) */
- 0x01, /* [005] -46.5 dB: AKM[001] = -48.131 dB (diff=1.63080 dB) */
- 0x01, /* [006] -47.0 dB: AKM[001] = -48.131 dB (diff=1.13080 dB) */
- 0x01, /* [007] -46.0 dB: AKM[001] = -48.131 dB (diff=2.13080 dB) */
- 0x01, /* [008] -45.5 dB: AKM[001] = -48.131 dB (diff=2.63080 dB) */
- 0x02, /* [009] -45.0 dB: AKM[002] = -42.110 dB (diff=2.88980 dB) */
- 0x02, /* [010] -44.5 dB: AKM[002] = -42.110 dB (diff=2.38980 dB) */
- 0x02, /* [011] -44.0 dB: AKM[002] = -42.110 dB (diff=1.88980 dB) */
- 0x02, /* [012] -43.5 dB: AKM[002] = -42.110 dB (diff=1.38980 dB) */
- 0x02, /* [013] -43.0 dB: AKM[002] = -42.110 dB (diff=0.88980 dB) */
- 0x02, /* [014] -42.5 dB: AKM[002] = -42.110 dB (diff=0.38980 dB) */
- 0x02, /* [015] -42.0 dB: AKM[002] = -42.110 dB (diff=0.11020 dB) */
- 0x02, /* [016] -41.5 dB: AKM[002] = -42.110 dB (diff=0.61020 dB) */
- 0x02, /* [017] -41.0 dB: AKM[002] = -42.110 dB (diff=1.11020 dB) */
- 0x02, /* [018] -40.5 dB: AKM[002] = -42.110 dB (diff=1.61020 dB) */
- 0x03, /* [019] -40.0 dB: AKM[003] = -38.588 dB (diff=1.41162 dB) */
- 0x03, /* [020] -39.5 dB: AKM[003] = -38.588 dB (diff=0.91162 dB) */
- 0x03, /* [021] -39.0 dB: AKM[003] = -38.588 dB (diff=0.41162 dB) */
- 0x03, /* [022] -38.5 dB: AKM[003] = -38.588 dB (diff=0.08838 dB) */
- 0x03, /* [023] -38.0 dB: AKM[003] = -38.588 dB (diff=0.58838 dB) */
- 0x03, /* [024] -37.5 dB: AKM[003] = -38.588 dB (diff=1.08838 dB) */
- 0x04, /* [025] -37.0 dB: AKM[004] = -36.090 dB (diff=0.91040 dB) */
- 0x04, /* [026] -36.5 dB: AKM[004] = -36.090 dB (diff=0.41040 dB) */
- 0x04, /* [027] -36.0 dB: AKM[004] = -36.090 dB (diff=0.08960 dB) */
- 0x04, /* [028] -35.5 dB: AKM[004] = -36.090 dB (diff=0.58960 dB) */
- 0x05, /* [029] -35.0 dB: AKM[005] = -34.151 dB (diff=0.84860 dB) */
- 0x05, /* [030] -34.5 dB: AKM[005] = -34.151 dB (diff=0.34860 dB) */
- 0x05, /* [031] -34.0 dB: AKM[005] = -34.151 dB (diff=0.15140 dB) */
- 0x05, /* [032] -33.5 dB: AKM[005] = -34.151 dB (diff=0.65140 dB) */
- 0x06, /* [033] -33.0 dB: AKM[006] = -32.568 dB (diff=0.43222 dB) */
- 0x06, /* [034] -32.5 dB: AKM[006] = -32.568 dB (diff=0.06778 dB) */
- 0x06, /* [035] -32.0 dB: AKM[006] = -32.568 dB (diff=0.56778 dB) */
- 0x07, /* [036] -31.5 dB: AKM[007] = -31.229 dB (diff=0.27116 dB) */
- 0x07, /* [037] -31.0 dB: AKM[007] = -31.229 dB (diff=0.22884 dB) */
- 0x08, /* [038] -30.5 dB: AKM[008] = -30.069 dB (diff=0.43100 dB) */
- 0x08, /* [039] -30.0 dB: AKM[008] = -30.069 dB (diff=0.06900 dB) */
- 0x09, /* [040] -29.5 dB: AKM[009] = -29.046 dB (diff=0.45405 dB) */
- 0x09, /* [041] -29.0 dB: AKM[009] = -29.046 dB (diff=0.04595 dB) */
- 0x0a, /* [042] -28.5 dB: AKM[010] = -28.131 dB (diff=0.36920 dB) */
- 0x0a, /* [043] -28.0 dB: AKM[010] = -28.131 dB (diff=0.13080 dB) */
- 0x0b, /* [044] -27.5 dB: AKM[011] = -27.303 dB (diff=0.19705 dB) */
- 0x0b, /* [045] -27.0 dB: AKM[011] = -27.303 dB (diff=0.30295 dB) */
- 0x0c, /* [046] -26.5 dB: AKM[012] = -26.547 dB (diff=0.04718 dB) */
- 0x0d, /* [047] -26.0 dB: AKM[013] = -25.852 dB (diff=0.14806 dB) */
- 0x0e, /* [048] -25.5 dB: AKM[014] = -25.208 dB (diff=0.29176 dB) */
- 0x0e, /* [049] -25.0 dB: AKM[014] = -25.208 dB (diff=0.20824 dB) */
- 0x0f, /* [050] -24.5 dB: AKM[015] = -24.609 dB (diff=0.10898 dB) */
- 0x10, /* [051] -24.0 dB: AKM[016] = -24.048 dB (diff=0.04840 dB) */
- 0x11, /* [052] -23.5 dB: AKM[017] = -23.522 dB (diff=0.02183 dB) */
- 0x12, /* [053] -23.0 dB: AKM[018] = -23.025 dB (diff=0.02535 dB) */
- 0x13, /* [054] -22.5 dB: AKM[019] = -22.556 dB (diff=0.05573 dB) */
- 0x14, /* [055] -22.0 dB: AKM[020] = -22.110 dB (diff=0.11020 dB) */
- 0x15, /* [056] -21.5 dB: AKM[021] = -21.686 dB (diff=0.18642 dB) */
- 0x17, /* [057] -21.0 dB: AKM[023] = -20.896 dB (diff=0.10375 dB) */
- 0x18, /* [058] -20.5 dB: AKM[024] = -20.527 dB (diff=0.02658 dB) */
- 0x1a, /* [059] -20.0 dB: AKM[026] = -19.831 dB (diff=0.16866 dB) */
- 0x1b, /* [060] -19.5 dB: AKM[027] = -19.504 dB (diff=0.00353 dB) */
- 0x1d, /* [061] -19.0 dB: AKM[029] = -18.883 dB (diff=0.11716 dB) */
- 0x1e, /* [062] -18.5 dB: AKM[030] = -18.588 dB (diff=0.08838 dB) */
- 0x20, /* [063] -18.0 dB: AKM[032] = -18.028 dB (diff=0.02780 dB) */
- 0x22, /* [064] -17.5 dB: AKM[034] = -17.501 dB (diff=0.00123 dB) */
- 0x24, /* [065] -17.0 dB: AKM[036] = -17.005 dB (diff=0.00475 dB) */
- 0x26, /* [066] -16.5 dB: AKM[038] = -16.535 dB (diff=0.03513 dB) */
- 0x28, /* [067] -16.0 dB: AKM[040] = -16.090 dB (diff=0.08960 dB) */
- 0x2b, /* [068] -15.5 dB: AKM[043] = -15.461 dB (diff=0.03857 dB) */
- 0x2d, /* [069] -15.0 dB: AKM[045] = -15.067 dB (diff=0.06655 dB) */
- 0x30, /* [070] -14.5 dB: AKM[048] = -14.506 dB (diff=0.00598 dB) */
- 0x33, /* [071] -14.0 dB: AKM[051] = -13.979 dB (diff=0.02060 dB) */
- 0x36, /* [072] -13.5 dB: AKM[054] = -13.483 dB (diff=0.01707 dB) */
- 0x39, /* [073] -13.0 dB: AKM[057] = -13.013 dB (diff=0.01331 dB) */
- 0x3c, /* [074] -12.5 dB: AKM[060] = -12.568 dB (diff=0.06778 dB) */
- 0x40, /* [075] -12.0 dB: AKM[064] = -12.007 dB (diff=0.00720 dB) */
- 0x44, /* [076] -11.5 dB: AKM[068] = -11.481 dB (diff=0.01937 dB) */
- 0x48, /* [077] -11.0 dB: AKM[072] = -10.984 dB (diff=0.01585 dB) */
- 0x4c, /* [078] -10.5 dB: AKM[076] = -10.515 dB (diff=0.01453 dB) */
- 0x51, /* [079] -10.0 dB: AKM[081] = -9.961 dB (diff=0.03890 dB) */
- 0x55, /* [080] -9.5 dB: AKM[085] = -9.542 dB (diff=0.04243 dB) */
- 0x5a, /* [081] -9.0 dB: AKM[090] = -9.046 dB (diff=0.04595 dB) */
- 0x60, /* [082] -8.5 dB: AKM[096] = -8.485 dB (diff=0.01462 dB) */
- 0x66, /* [083] -8.0 dB: AKM[102] = -7.959 dB (diff=0.04120 dB) */
- 0x6c, /* [084] -7.5 dB: AKM[108] = -7.462 dB (diff=0.03767 dB) */
- 0x72, /* [085] -7.0 dB: AKM[114] = -6.993 dB (diff=0.00729 dB) */
- 0x79, /* [086] -6.5 dB: AKM[121] = -6.475 dB (diff=0.02490 dB) */
- 0x80, /* [087] -6.0 dB: AKM[128] = -5.987 dB (diff=0.01340 dB) */
- 0x87, /* [088] -5.5 dB: AKM[135] = -5.524 dB (diff=0.02413 dB) */
- 0x8f, /* [089] -5.0 dB: AKM[143] = -5.024 dB (diff=0.02408 dB) */
- 0x98, /* [090] -4.5 dB: AKM[152] = -4.494 dB (diff=0.00607 dB) */
- 0xa1, /* [091] -4.0 dB: AKM[161] = -3.994 dB (diff=0.00571 dB) */
- 0xaa, /* [092] -3.5 dB: AKM[170] = -3.522 dB (diff=0.02183 dB) */
- 0xb5, /* [093] -3.0 dB: AKM[181] = -2.977 dB (diff=0.02277 dB) */
- 0xbf, /* [094] -2.5 dB: AKM[191] = -2.510 dB (diff=0.01014 dB) */
- 0xcb, /* [095] -2.0 dB: AKM[203] = -1.981 dB (diff=0.01912 dB) */
- 0xd7, /* [096] -1.5 dB: AKM[215] = -1.482 dB (diff=0.01797 dB) */
- 0xe3, /* [097] -1.0 dB: AKM[227] = -1.010 dB (diff=0.01029 dB) */
- 0xf1, /* [098] -0.5 dB: AKM[241] = -0.490 dB (diff=0.00954 dB) */
- 0xff, /* [099] +0.0 dB: AKM[255] = +0.000 dB (diff=0.00000 dB) */
-};
-
-
-static void hr222_config_akm(struct pcxhr_mgr *mgr, unsigned short data)
-{
- unsigned short mask = 0x8000;
- /* activate access to codec registers */
- PCXHR_INPB(mgr, PCXHR_XLX_HIFREQ);
-
- while (mask) {
- PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
- data & mask ? PCXHR_DATA_CODEC : 0);
- mask >>= 1;
- }
- /* termiate access to codec registers */
- PCXHR_INPB(mgr, PCXHR_XLX_RUER);
-}
-
-
-static int hr222_set_hw_playback_level(struct pcxhr_mgr *mgr,
- int idx, int level)
-{
- unsigned short cmd;
- if (idx > 1 ||
- level < 0 ||
- level >= ARRAY_SIZE(g_hr222_p_level))
- return -EINVAL;
-
- if (idx == 0)
- cmd = AKM_LEFT_LEVEL_CMD;
- else
- cmd = AKM_RIGHT_LEVEL_CMD;
-
- /* conversion from PmBoardCodedLevel to AKM nonlinear programming */
- cmd += g_hr222_p_level[level];
-
- hr222_config_akm(mgr, cmd);
- return 0;
-}
-
-
-static int hr222_set_hw_capture_level(struct pcxhr_mgr *mgr,
- int level_l, int level_r, int level_mic)
-{
- /* program all input levels at the same time */
- unsigned int data;
- int i;
-
- if (!mgr->capture_chips)
- return -EINVAL; /* no PCX22 */
-
- data = ((level_mic & 0xff) << 24); /* micro is mono, but apply */
- data |= ((level_mic & 0xff) << 16); /* level on both channels */
- data |= ((level_r & 0xff) << 8); /* line input right channel */
- data |= (level_l & 0xff); /* line input left channel */
-
- PCXHR_INPB(mgr, PCXHR_XLX_DATA); /* activate input codec */
- /* send 32 bits (4 x 8 bits) */
- for (i = 0; i < 32; i++, data <<= 1) {
- PCXHR_OUTPB(mgr, PCXHR_XLX_DATA,
- (data & 0x80000000) ? PCXHR_DATA_CODEC : 0);
- }
- PCXHR_INPB(mgr, PCXHR_XLX_RUER); /* close input level codec */
- return 0;
-}
-
-static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level);
-
-int hr222_sub_init(struct pcxhr_mgr *mgr)
-{
- unsigned char reg;
-
- mgr->board_has_analog = 1; /* analog always available */
- mgr->xlx_cfg = PCXHR_CFG_SYNCDSP_MASK;
-
- reg = PCXHR_INPB(mgr, PCXHR_XLX_STATUS);
- if (reg & PCXHR_STAT_MIC_CAPS)
- mgr->board_has_mic = 1; /* microphone available */
- snd_printdd("MIC input available = %d\n", mgr->board_has_mic);
-
- /* reset codec */
- PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
- PCXHR_DSP_RESET_DSP);
- msleep(5);
- PCXHR_OUTPB(mgr, PCXHR_DSP_RESET,
- PCXHR_DSP_RESET_DSP |
- PCXHR_DSP_RESET_MUTE |
- PCXHR_DSP_RESET_CODEC);
- msleep(5);
-
- /* config AKM */
- hr222_config_akm(mgr, AKM_POWER_CONTROL_CMD);
- hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
- hr222_config_akm(mgr, AKM_UNMUTE_CMD);
- hr222_config_akm(mgr, AKM_RESET_OFF_CMD);
-
- /* init micro boost */
- hr222_micro_boost(mgr, 0);
-
- return 0;
-}
-
-
-/* calc PLL register */
-/* TODO : there is a very similar fct in pcxhr.c */
-static int hr222_pll_freq_register(unsigned int freq,
- unsigned int *pllreg,
- unsigned int *realfreq)
-{
- unsigned int reg;
-
- if (freq < 6900 || freq > 219000)
- return -EINVAL;
- reg = (28224000 * 2) / freq;
- reg = (reg - 1) / 2;
- if (reg < 0x100)
- *pllreg = reg + 0xC00;
- else if (reg < 0x200)
- *pllreg = reg + 0x800;
- else if (reg < 0x400)
- *pllreg = reg & 0x1ff;
- else if (reg < 0x800) {
- *pllreg = ((reg >> 1) & 0x1ff) + 0x200;
- reg &= ~1;
- } else {
- *pllreg = ((reg >> 2) & 0x1ff) + 0x400;
- reg &= ~3;
- }
- if (realfreq)
- *realfreq = (28224000 / (reg + 1));
- return 0;
-}
-
-int hr222_sub_set_clock(struct pcxhr_mgr *mgr,
- unsigned int rate,
- int *changed)
-{
- unsigned int speed, pllreg = 0;
- int err;
- unsigned realfreq = rate;
-
- switch (mgr->use_clock_type) {
- case HR22_CLOCK_TYPE_INTERNAL:
- err = hr222_pll_freq_register(rate, &pllreg, &realfreq);
- if (err)
- return err;
-
- mgr->xlx_cfg &= ~(PCXHR_CFG_CLOCKIN_SEL_MASK |
- PCXHR_CFG_CLOCK_UER1_SEL_MASK);
- break;
- case HR22_CLOCK_TYPE_AES_SYNC:
- mgr->xlx_cfg |= PCXHR_CFG_CLOCKIN_SEL_MASK;
- mgr->xlx_cfg &= ~PCXHR_CFG_CLOCK_UER1_SEL_MASK;
- break;
- case HR22_CLOCK_TYPE_AES_1:
- if (!mgr->board_has_aes1)
- return -EINVAL;
-
- mgr->xlx_cfg |= (PCXHR_CFG_CLOCKIN_SEL_MASK |
- PCXHR_CFG_CLOCK_UER1_SEL_MASK);
- break;
- default:
- return -EINVAL;
- }
- hr222_config_akm(mgr, AKM_MUTE_CMD);
-
- if (mgr->use_clock_type == HR22_CLOCK_TYPE_INTERNAL) {
- PCXHR_OUTPB(mgr, PCXHR_XLX_HIFREQ, pllreg >> 8);
- PCXHR_OUTPB(mgr, PCXHR_XLX_LOFREQ, pllreg & 0xff);
- }
-
- /* set clock source */
- PCXHR_OUTPB(mgr, PCXHR_XLX_CFG, mgr->xlx_cfg);
-
- /* codec speed modes */
- speed = rate < 55000 ? 0 : 1;
- if (mgr->codec_speed != speed) {
- mgr->codec_speed = speed;
- if (speed == 0)
- hr222_config_akm(mgr, AKM_CLOCK_INF_55K_CMD);
- else
- hr222_config_akm(mgr, AKM_CLOCK_SUP_55K_CMD);
- }
-
- mgr->sample_rate_real = realfreq;
- mgr->cur_clock_type = mgr->use_clock_type;
-
- if (changed)
- *changed = 1;
-
- hr222_config_akm(mgr, AKM_UNMUTE_CMD);
-
- snd_printdd("set_clock to %dHz (realfreq=%d pllreg=%x)\n",
- rate, realfreq, pllreg);
- return 0;
-}
-
-int hr222_get_external_clock(struct pcxhr_mgr *mgr,
- enum pcxhr_clock_type clock_type,
- int *sample_rate)
-{
- int rate, calc_rate = 0;
- unsigned int ticks;
- unsigned char mask, reg;
-
- if (clock_type == HR22_CLOCK_TYPE_AES_SYNC) {
-
- mask = (PCXHR_SUER_CLOCK_PRESENT_MASK |
- PCXHR_SUER_DATA_PRESENT_MASK);
- reg = PCXHR_STAT_FREQ_SYNC_MASK;
-
- } else if (clock_type == HR22_CLOCK_TYPE_AES_1 && mgr->board_has_aes1) {
-
- mask = (PCXHR_SUER1_CLOCK_PRESENT_MASK |
- PCXHR_SUER1_DATA_PRESENT_MASK);
- reg = PCXHR_STAT_FREQ_UER1_MASK;
-
- } else {
- snd_printdd("get_external_clock : type %d not supported\n",
- clock_type);
- return -EINVAL; /* other clocks not supported */
- }
-
- if ((PCXHR_INPB(mgr, PCXHR_XLX_CSUER) & mask) != mask) {
- snd_printdd("get_external_clock(%d) = 0 Hz\n", clock_type);
- *sample_rate = 0;
- return 0; /* no external clock locked */
- }
-
- PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg); /* calculate freq */
-
- /* save the measured clock frequency */
- reg |= PCXHR_STAT_FREQ_SAVE_MASK;
-
- if (mgr->last_reg_stat != reg) {
- udelay(500); /* wait min 2 cycles of lowest freq (8000) */
- mgr->last_reg_stat = reg;
- }
-
- PCXHR_OUTPB(mgr, PCXHR_XLX_STATUS, reg); /* save */
-
- /* get the frequency */
- ticks = (unsigned int)PCXHR_INPB(mgr, PCXHR_XLX_CFG);
- ticks = (ticks & 0x03) << 8;
- ticks |= (unsigned int)PCXHR_INPB(mgr, PCXHR_DSP_RESET);
-
- if (ticks != 0)
- calc_rate = 28224000 / ticks;
- /* rounding */
- if (calc_rate > 184200)
- rate = 192000;
- else if (calc_rate > 152200)
- rate = 176400;
- else if (calc_rate > 112000)
- rate = 128000;
- else if (calc_rate > 92100)
- rate = 96000;
- else if (calc_rate > 76100)
- rate = 88200;
- else if (calc_rate > 56000)
- rate = 64000;
- else if (calc_rate > 46050)
- rate = 48000;
- else if (calc_rate > 38050)
- rate = 44100;
- else if (calc_rate > 28000)
- rate = 32000;
- else if (calc_rate > 23025)
- rate = 24000;
- else if (calc_rate > 19025)
- rate = 22050;
- else if (calc_rate > 14000)
- rate = 16000;
- else if (calc_rate > 11512)
- rate = 12000;
- else if (calc_rate > 9512)
- rate = 11025;
- else if (calc_rate > 7000)
- rate = 8000;
- else
- rate = 0;
-
- snd_printdd("External clock is at %d Hz (measured %d Hz)\n",
- rate, calc_rate);
- *sample_rate = rate;
- return 0;
-}
-
-
-int hr222_update_analog_audio_level(struct snd_pcxhr *chip,
- int is_capture, int channel)
-{
- snd_printdd("hr222_update_analog_audio_level(%s chan=%d)\n",
- is_capture ? "capture" : "playback", channel);
- if (is_capture) {
- int level_l, level_r, level_mic;
- /* we have to update all levels */
- if (chip->analog_capture_active) {
- level_l = chip->analog_capture_volume[0];
- level_r = chip->analog_capture_volume[1];
- } else {
- level_l = HR222_LINE_CAPTURE_LEVEL_MIN;
- level_r = HR222_LINE_CAPTURE_LEVEL_MIN;
- }
- if (chip->mic_active)
- level_mic = chip->mic_volume;
- else
- level_mic = HR222_MICRO_CAPTURE_LEVEL_MIN;
- return hr222_set_hw_capture_level(chip->mgr,
- level_l, level_r, level_mic);
- } else {
- int vol;
- if (chip->analog_playback_active[channel])
- vol = chip->analog_playback_volume[channel];
- else
- vol = HR222_LINE_PLAYBACK_LEVEL_MIN;
- return hr222_set_hw_playback_level(chip->mgr, channel, vol);
- }
-}
-
-
-/*texts[5] = {"Line", "Digital", "Digi+SRC", "Mic", "Line+Mic"}*/
-#define SOURCE_LINE 0
-#define SOURCE_DIGITAL 1
-#define SOURCE_DIGISRC 2
-#define SOURCE_MIC 3
-#define SOURCE_LINEMIC 4
-
-int hr222_set_audio_source(struct snd_pcxhr *chip)
-{
- int digital = 0;
- /* default analog source */
- chip->mgr->xlx_cfg &= ~(PCXHR_CFG_SRC_MASK |
- PCXHR_CFG_DATAIN_SEL_MASK |
- PCXHR_CFG_DATA_UER1_SEL_MASK);
-
- if (chip->audio_capture_source == SOURCE_DIGISRC) {
- chip->mgr->xlx_cfg |= PCXHR_CFG_SRC_MASK;
- digital = 1;
- } else {
- if (chip->audio_capture_source == SOURCE_DIGITAL)
- digital = 1;
- }
- if (digital) {
- chip->mgr->xlx_cfg |= PCXHR_CFG_DATAIN_SEL_MASK;
- if (chip->mgr->board_has_aes1) {
- /* get data from the AES1 plug */
- chip->mgr->xlx_cfg |= PCXHR_CFG_DATA_UER1_SEL_MASK;
- }
- /* chip->mic_active = 0; */
- /* chip->analog_capture_active = 0; */
- } else {
- int update_lvl = 0;
- chip->analog_capture_active = 0;
- chip->mic_active = 0;
- if (chip->audio_capture_source == SOURCE_LINE ||
- chip->audio_capture_source == SOURCE_LINEMIC) {
- if (chip->analog_capture_active == 0)
- update_lvl = 1;
- chip->analog_capture_active = 1;
- }
- if (chip->audio_capture_source == SOURCE_MIC ||
- chip->audio_capture_source == SOURCE_LINEMIC) {
- if (chip->mic_active == 0)
- update_lvl = 1;
- chip->mic_active = 1;
- }
- if (update_lvl) {
- /* capture: update all 3 mutes/unmutes with one call */
- hr222_update_analog_audio_level(chip, 1, 0);
- }
- }
- /* set the source infos (max 3 bits modified) */
- PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CFG, chip->mgr->xlx_cfg);
- return 0;
-}
-
-
-int hr222_iec958_capture_byte(struct snd_pcxhr *chip,
- int aes_idx, unsigned char *aes_bits)
-{
- unsigned char idx = (unsigned char)(aes_idx * 8);
- unsigned char temp = 0;
- unsigned char mask = chip->mgr->board_has_aes1 ?
- PCXHR_SUER1_BIT_C_READ_MASK : PCXHR_SUER_BIT_C_READ_MASK;
- int i;
- for (i = 0; i < 8; i++) {
- PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx++); /* idx < 192 */
- temp <<= 1;
- if (PCXHR_INPB(chip->mgr, PCXHR_XLX_CSUER) & mask)
- temp |= 1;
- }
- snd_printdd("read iec958 AES %d byte %d = 0x%x\n",
- chip->chip_idx, aes_idx, temp);
- *aes_bits = temp;
- return 0;
-}
-
-
-int hr222_iec958_update_byte(struct snd_pcxhr *chip,
- int aes_idx, unsigned char aes_bits)
-{
- int i;
- unsigned char new_bits = aes_bits;
- unsigned char old_bits = chip->aes_bits[aes_idx];
- unsigned char idx = (unsigned char)(aes_idx * 8);
- for (i = 0; i < 8; i++) {
- if ((old_bits & 0x01) != (new_bits & 0x01)) {
- /* idx < 192 */
- PCXHR_OUTPB(chip->mgr, PCXHR_XLX_RUER, idx);
- /* write C and U bit */
- PCXHR_OUTPB(chip->mgr, PCXHR_XLX_CSUER, new_bits&0x01 ?
- PCXHR_SUER_BIT_C_WRITE_MASK : 0);
- }
- idx++;
- old_bits >>= 1;
- new_bits >>= 1;
- }
- chip->aes_bits[aes_idx] = aes_bits;
- return 0;
-}
-
-static void hr222_micro_boost(struct pcxhr_mgr *mgr, int level)
-{
- unsigned char boost_mask;
- boost_mask = (unsigned char) (level << PCXHR_SELMIC_PREAMPLI_OFFSET);
- if (boost_mask & (~PCXHR_SELMIC_PREAMPLI_MASK))
- return; /* only values form 0 to 3 accepted */
-
- mgr->xlx_selmic &= ~PCXHR_SELMIC_PREAMPLI_MASK;
- mgr->xlx_selmic |= boost_mask;
-
- PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
-
- snd_printdd("hr222_micro_boost : set %x\n", boost_mask);
-}
-
-static void hr222_phantom_power(struct pcxhr_mgr *mgr, int power)
-{
- if (power)
- mgr->xlx_selmic |= PCXHR_SELMIC_PHANTOM_ALIM;
- else
- mgr->xlx_selmic &= ~PCXHR_SELMIC_PHANTOM_ALIM;
-
- PCXHR_OUTPB(mgr, PCXHR_XLX_SELMIC, mgr->xlx_selmic);
-
- snd_printdd("hr222_phantom_power : set %d\n", power);
-}
-
-
-/* mic level */
-static const DECLARE_TLV_DB_SCALE(db_scale_mic_hr222, -9850, 50, 650);
-
-static int hr222_mic_vol_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = HR222_MICRO_CAPTURE_LEVEL_MIN; /* -98 dB */
- /* gains from 9 dB to 31.5 dB not recommended; use micboost instead */
- uinfo->value.integer.max = HR222_MICRO_CAPTURE_LEVEL_MAX; /* +7 dB */
- return 0;
-}
-
-static int hr222_mic_vol_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- mutex_lock(&chip->mgr->mixer_mutex);
- ucontrol->value.integer.value[0] = chip->mic_volume;
- mutex_unlock(&chip->mgr->mixer_mutex);
- return 0;
-}
-
-static int hr222_mic_vol_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- int changed = 0;
- mutex_lock(&chip->mgr->mixer_mutex);
- if (chip->mic_volume != ucontrol->value.integer.value[0]) {
- changed = 1;
- chip->mic_volume = ucontrol->value.integer.value[0];
- hr222_update_analog_audio_level(chip, 1, 0);
- }
- mutex_unlock(&chip->mgr->mixer_mutex);
- return changed;
-}
-
-static struct snd_kcontrol_new hr222_control_mic_level = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
- SNDRV_CTL_ELEM_ACCESS_TLV_READ),
- .name = "Mic Capture Volume",
- .info = hr222_mic_vol_info,
- .get = hr222_mic_vol_get,
- .put = hr222_mic_vol_put,
- .tlv = { .p = db_scale_mic_hr222 },
-};
-
-
-/* mic boost level */
-static const DECLARE_TLV_DB_SCALE(db_scale_micboost_hr222, 0, 1800, 5400);
-
-static int hr222_mic_boost_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
-{
- uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
- uinfo->count = 1;
- uinfo->value.integer.min = 0; /* 0 dB */
- uinfo->value.integer.max = 3; /* 54 dB */
- return 0;
-}
-
-static int hr222_mic_boost_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- mutex_lock(&chip->mgr->mixer_mutex);
- ucontrol->value.integer.value[0] = chip->mic_boost;
- mutex_unlock(&chip->mgr->mixer_mutex);
- return 0;
-}
-
-static int hr222_mic_boost_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- int changed = 0;
- mutex_lock(&chip->mgr->mixer_mutex);
- if (chip->mic_boost != ucontrol->value.integer.value[0]) {
- changed = 1;
- chip->mic_boost = ucontrol->value.integer.value[0];
- hr222_micro_boost(chip->mgr, chip->mic_boost);
- }
- mutex_unlock(&chip->mgr->mixer_mutex);
- return changed;
-}
-
-static struct snd_kcontrol_new hr222_control_mic_boost = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
- SNDRV_CTL_ELEM_ACCESS_TLV_READ),
- .name = "MicBoost Capture Volume",
- .info = hr222_mic_boost_info,
- .get = hr222_mic_boost_get,
- .put = hr222_mic_boost_put,
- .tlv = { .p = db_scale_micboost_hr222 },
-};
-
-
-/******************* Phantom power switch *******************/
-#define hr222_phantom_power_info snd_ctl_boolean_mono_info
-
-static int hr222_phantom_power_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- mutex_lock(&chip->mgr->mixer_mutex);
- ucontrol->value.integer.value[0] = chip->phantom_power;
- mutex_unlock(&chip->mgr->mixer_mutex);
- return 0;
-}
-
-static int hr222_phantom_power_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- int power, changed = 0;
-
- mutex_lock(&chip->mgr->mixer_mutex);
- power = !!ucontrol->value.integer.value[0];
- if (chip->phantom_power != power) {
- hr222_phantom_power(chip->mgr, power);
- chip->phantom_power = power;
- changed = 1;
- }
- mutex_unlock(&chip->mgr->mixer_mutex);
- return changed;
-}
-
-static struct snd_kcontrol_new hr222_phantom_power_switch = {
- .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Phantom Power Switch",
- .info = hr222_phantom_power_info,
- .get = hr222_phantom_power_get,
- .put = hr222_phantom_power_put,
-};
-
-
-int hr222_add_mic_controls(struct snd_pcxhr *chip)
-{
- int err;
- if (!chip->mgr->board_has_mic)
- return 0;
-
- /* controls */
- err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_level,
- chip));
- if (err < 0)
- return err;
-
- err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_control_mic_boost,
- chip));
- if (err < 0)
- return err;
-
- err = snd_ctl_add(chip->card, snd_ctl_new1(&hr222_phantom_power_switch,
- chip));
- return err;
-}
diff --git a/sound/pci/pcxhr/pcxhr_mix22.h b/sound/pci/pcxhr/pcxhr_mix22.h
deleted file mode 100644
index 6b318b2f0100..000000000000
--- a/sound/pci/pcxhr/pcxhr_mix22.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Driver for Digigram pcxhr compatible soundcards
- *
- * low level interface with interrupt ans message handling
- *
- * Copyright (c) 2004 by Digigram <alsa@digigram.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef __SOUND_PCXHR_MIX22_H
-#define __SOUND_PCXHR_MIX22_H
-
-struct pcxhr_mgr;
-
-int hr222_sub_init(struct pcxhr_mgr *mgr);
-int hr222_sub_set_clock(struct pcxhr_mgr *mgr, unsigned int rate,
- int *changed);
-int hr222_get_external_clock(struct pcxhr_mgr *mgr,
- enum pcxhr_clock_type clock_type,
- int *sample_rate);
-
-#define HR222_LINE_PLAYBACK_LEVEL_MIN 0 /* -25.5 dB */
-#define HR222_LINE_PLAYBACK_ZERO_LEVEL 51 /* 0.0 dB */
-#define HR222_LINE_PLAYBACK_LEVEL_MAX 99 /* +24.0 dB */
-
-#define HR222_LINE_CAPTURE_LEVEL_MIN 0 /* -111.5 dB */
-#define HR222_LINE_CAPTURE_ZERO_LEVEL 223 /* 0.0 dB */
-#define HR222_LINE_CAPTURE_LEVEL_MAX 255 /* +16 dB */
-#define HR222_MICRO_CAPTURE_LEVEL_MIN 0 /* -98.5 dB */
-#define HR222_MICRO_CAPTURE_LEVEL_MAX 210 /* +6.5 dB */
-
-int hr222_update_analog_audio_level(struct snd_pcxhr *chip,
- int is_capture,
- int channel);
-int hr222_set_audio_source(struct snd_pcxhr *chip);
-int hr222_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx,
- unsigned char *aes_bits);
-int hr222_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx,
- unsigned char aes_bits);
-
-int hr222_add_mic_controls(struct snd_pcxhr *chip);
-
-#endif /* __SOUND_PCXHR_MIX22_H */
diff --git a/sound/pci/pcxhr/pcxhr_mixer.c b/sound/pci/pcxhr/pcxhr_mixer.c
index 2436e374586f..aabc7bc5321e 100644
--- a/sound/pci/pcxhr/pcxhr_mixer.c
+++ b/sound/pci/pcxhr/pcxhr_mixer.c
@@ -33,24 +33,20 @@
#include <sound/tlv.h>
#include <sound/asoundef.h>
#include "pcxhr_mixer.h"
-#include "pcxhr_mix22.h"
-#define PCXHR_LINE_CAPTURE_LEVEL_MIN 0 /* -112.0 dB */
-#define PCXHR_LINE_CAPTURE_LEVEL_MAX 255 /* +15.5 dB */
-#define PCXHR_LINE_CAPTURE_ZERO_LEVEL 224 /* 0.0 dB ( 0 dBu -> 0 dBFS ) */
-#define PCXHR_LINE_PLAYBACK_LEVEL_MIN 0 /* -104.0 dB */
-#define PCXHR_LINE_PLAYBACK_LEVEL_MAX 128 /* +24.0 dB */
-#define PCXHR_LINE_PLAYBACK_ZERO_LEVEL 104 /* 0.0 dB ( 0 dBFS -> 0 dBu ) */
+#define PCXHR_ANALOG_CAPTURE_LEVEL_MIN 0 /* -96.0 dB */
+#define PCXHR_ANALOG_CAPTURE_LEVEL_MAX 255 /* +31.5 dB */
+#define PCXHR_ANALOG_CAPTURE_ZERO_LEVEL 224 /* +16.0 dB ( +31.5 dB - fix level +15.5 dB ) */
-static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -11200, 50, 1550);
-static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400);
+#define PCXHR_ANALOG_PLAYBACK_LEVEL_MIN 0 /* -128.0 dB */
+#define PCXHR_ANALOG_PLAYBACK_LEVEL_MAX 128 /* 0.0 dB */
+#define PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL 104 /* -24.0 dB ( 0.0 dB - fix level +24.0 dB ) */
-static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_capture, -11150, 50, 1600);
-static const DECLARE_TLV_DB_SCALE(db_scale_a_hr222_playback, -2550, 50, 2400);
+static const DECLARE_TLV_DB_SCALE(db_scale_analog_capture, -9600, 50, 3150);
+static const DECLARE_TLV_DB_SCALE(db_scale_analog_playback, -10400, 100, 2400);
-static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip,
- int is_capture, int channel)
+static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip, int is_capture, int channel)
{
int err, vol;
struct pcxhr_rmh rmh;
@@ -64,17 +60,15 @@ static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip,
if (chip->analog_playback_active[channel])
vol = chip->analog_playback_volume[channel];
else
- vol = PCXHR_LINE_PLAYBACK_LEVEL_MIN;
- /* playback analog levels are inversed */
- rmh.cmd[2] = PCXHR_LINE_PLAYBACK_LEVEL_MAX - vol;
+ vol = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN;
+ rmh.cmd[2] = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX - vol; /* playback analog levels are inversed */
}
rmh.cmd[1] = 1 << ((2 * chip->chip_idx) + channel); /* audio mask */
rmh.cmd_len = 3;
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err < 0) {
- snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d)"
- " is_capture(%d) err(%x)\n",
- chip->chip_idx, is_capture, err);
+ snd_printk(KERN_DEBUG "error update_analog_audio_level card(%d) "
+ "is_capture(%d) err(%x)\n", chip->chip_idx, is_capture, err);
return -EINVAL;
}
return 0;
@@ -86,34 +80,14 @@ static int pcxhr_update_analog_audio_level(struct snd_pcxhr *chip,
static int pcxhr_analog_vol_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
-
uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
uinfo->count = 2;
if (kcontrol->private_value == 0) { /* playback */
- if (chip->mgr->is_hr_stereo) {
- uinfo->value.integer.min =
- HR222_LINE_PLAYBACK_LEVEL_MIN; /* -25 dB */
- uinfo->value.integer.max =
- HR222_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */
- } else {
- uinfo->value.integer.min =
- PCXHR_LINE_PLAYBACK_LEVEL_MIN; /*-104 dB */
- uinfo->value.integer.max =
- PCXHR_LINE_PLAYBACK_LEVEL_MAX; /* +24 dB */
- }
+ uinfo->value.integer.min = PCXHR_ANALOG_PLAYBACK_LEVEL_MIN; /* -128 dB */
+ uinfo->value.integer.max = PCXHR_ANALOG_PLAYBACK_LEVEL_MAX; /* 0 dB */
} else { /* capture */
- if (chip->mgr->is_hr_stereo) {
- uinfo->value.integer.min =
- HR222_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */
- uinfo->value.integer.max =
- HR222_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */
- } else {
- uinfo->value.integer.min =
- PCXHR_LINE_CAPTURE_LEVEL_MIN; /*-112 dB */
- uinfo->value.integer.max =
- PCXHR_LINE_CAPTURE_LEVEL_MAX; /* +15.5 dB */
- }
+ uinfo->value.integer.min = PCXHR_ANALOG_CAPTURE_LEVEL_MIN; /* -96 dB */
+ uinfo->value.integer.max = PCXHR_ANALOG_CAPTURE_LEVEL_MAX; /* 31.5 dB */
}
return 0;
}
@@ -124,11 +98,11 @@ static int pcxhr_analog_vol_get(struct snd_kcontrol *kcontrol,
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
mutex_lock(&chip->mgr->mixer_mutex);
if (kcontrol->private_value == 0) { /* playback */
- ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
- ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
+ ucontrol->value.integer.value[0] = chip->analog_playback_volume[0];
+ ucontrol->value.integer.value[1] = chip->analog_playback_volume[1];
} else { /* capture */
- ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
- ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
+ ucontrol->value.integer.value[0] = chip->analog_capture_volume[0];
+ ucontrol->value.integer.value[1] = chip->analog_capture_volume[1];
}
mutex_unlock(&chip->mgr->mixer_mutex);
return 0;
@@ -149,35 +123,18 @@ static int pcxhr_analog_vol_put(struct snd_kcontrol *kcontrol,
&chip->analog_capture_volume[i] :
&chip->analog_playback_volume[i];
if (is_capture) {
- if (chip->mgr->is_hr_stereo) {
- if (new_volume < HR222_LINE_CAPTURE_LEVEL_MIN ||
- new_volume > HR222_LINE_CAPTURE_LEVEL_MAX)
- continue;
- } else {
- if (new_volume < PCXHR_LINE_CAPTURE_LEVEL_MIN ||
- new_volume > PCXHR_LINE_CAPTURE_LEVEL_MAX)
- continue;
- }
+ if (new_volume < PCXHR_ANALOG_CAPTURE_LEVEL_MIN ||
+ new_volume > PCXHR_ANALOG_CAPTURE_LEVEL_MAX)
+ continue;
} else {
- if (chip->mgr->is_hr_stereo) {
- if (new_volume < HR222_LINE_PLAYBACK_LEVEL_MIN ||
- new_volume > HR222_LINE_PLAYBACK_LEVEL_MAX)
- continue;
- } else {
- if (new_volume < PCXHR_LINE_PLAYBACK_LEVEL_MIN ||
- new_volume > PCXHR_LINE_PLAYBACK_LEVEL_MAX)
- continue;
- }
+ if (new_volume < PCXHR_ANALOG_PLAYBACK_LEVEL_MIN ||
+ new_volume > PCXHR_ANALOG_PLAYBACK_LEVEL_MAX)
+ continue;
}
if (*stored_volume != new_volume) {
*stored_volume = new_volume;
changed = 1;
- if (chip->mgr->is_hr_stereo)
- hr222_update_analog_audio_level(chip,
- is_capture, i);
- else
- pcxhr_update_analog_audio_level(chip,
- is_capture, i);
+ pcxhr_update_analog_audio_level(chip, is_capture, i);
}
}
mutex_unlock(&chip->mgr->mixer_mutex);
@@ -196,7 +153,6 @@ static struct snd_kcontrol_new pcxhr_control_analog_level = {
};
/* shared */
-
#define pcxhr_sw_info snd_ctl_boolean_stereo_info
static int pcxhr_audio_sw_get(struct snd_kcontrol *kcontrol,
@@ -224,10 +180,7 @@ static int pcxhr_audio_sw_put(struct snd_kcontrol *kcontrol,
!!ucontrol->value.integer.value[i];
changed = 1;
/* update playback levels */
- if (chip->mgr->is_hr_stereo)
- hr222_update_analog_audio_level(chip, 0, i);
- else
- pcxhr_update_analog_audio_level(chip, 0, i);
+ pcxhr_update_analog_audio_level(chip, 0, i);
}
}
mutex_unlock(&chip->mgr->mixer_mutex);
@@ -298,8 +251,7 @@ static int pcxhr_update_playback_stream_level(struct snd_pcxhr* chip, int idx)
#define VALID_AUDIO_IO_MUTE_LEVEL 0x000004
#define VALID_AUDIO_IO_MUTE_MONITOR_1 0x000008
-static int pcxhr_update_audio_pipe_level(struct snd_pcxhr *chip,
- int capture, int channel)
+static int pcxhr_update_audio_pipe_level(struct snd_pcxhr* chip, int capture, int channel)
{
int err;
struct pcxhr_rmh rmh;
@@ -312,20 +264,18 @@ static int pcxhr_update_audio_pipe_level(struct snd_pcxhr *chip,
pcxhr_init_rmh(&rmh, CMD_AUDIO_LEVEL_ADJUST);
/* add channel mask */
- pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0,
- 1 << (channel + pipe->first_audio));
- /* TODO : if mask (3 << pipe->first_audio) is used, left and right
- * channel will be programmed to the same params */
+ pcxhr_set_pipe_cmd_params(&rmh, capture, 0, 0, 1 << (channel + pipe->first_audio));
+ /* TODO : if mask (3 << pipe->first_audio) is used, left and right channel
+ * will be programmed to the same params
+ */
if (capture) {
rmh.cmd[0] |= VALID_AUDIO_IO_DIGITAL_LEVEL;
- /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled
- * (capture pipe level) */
+ /* VALID_AUDIO_IO_MUTE_LEVEL not yet handled (capture pipe level) */
rmh.cmd[2] = chip->digital_capture_volume[channel];
} else {
- rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL |
- VALID_AUDIO_IO_MUTE_MONITOR_1;
- /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL
- * not yet handled (playback pipe level)
+ rmh.cmd[0] |= VALID_AUDIO_IO_MONITOR_LEVEL | VALID_AUDIO_IO_MUTE_MONITOR_1;
+ /* VALID_AUDIO_IO_DIGITAL_LEVEL and VALID_AUDIO_IO_MUTE_LEVEL not yet
+ * handled (playback pipe level)
*/
rmh.cmd[2] = chip->monitoring_volume[channel] << 10;
if (chip->monitoring_active[channel] == 0)
@@ -334,8 +284,8 @@ static int pcxhr_update_audio_pipe_level(struct snd_pcxhr *chip,
rmh.cmd_len = 3;
err = pcxhr_send_msg(chip->mgr, &rmh);
- if (err < 0) {
- snd_printk(KERN_DEBUG "error update_audio_level(%d) err=%x\n",
+ if(err<0) {
+ snd_printk(KERN_DEBUG "error update_audio_level card(%d) err(%x)\n",
chip->chip_idx, err);
return -EINVAL;
}
@@ -359,15 +309,15 @@ static int pcxhr_pcm_vol_get(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
int *stored_volume;
int is_capture = kcontrol->private_value;
mutex_lock(&chip->mgr->mixer_mutex);
- if (is_capture) /* digital capture */
- stored_volume = chip->digital_capture_volume;
- else /* digital playback */
- stored_volume = chip->digital_playback_volume[idx];
+ if (is_capture)
+ stored_volume = chip->digital_capture_volume; /* digital capture */
+ else
+ stored_volume = chip->digital_playback_volume[idx]; /* digital playback */
ucontrol->value.integer.value[0] = stored_volume[0];
ucontrol->value.integer.value[1] = stored_volume[1];
mutex_unlock(&chip->mgr->mixer_mutex);
@@ -378,7 +328,7 @@ static int pcxhr_pcm_vol_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
- int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
+ int idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); /* index */
int changed = 0;
int is_capture = kcontrol->private_value;
int *stored_volume;
@@ -434,8 +384,7 @@ static int pcxhr_pcm_sw_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int pcxhr_pcm_sw_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
int changed = 0;
@@ -495,8 +444,8 @@ static int pcxhr_monitor_vol_put(struct snd_kcontrol *kcontrol,
if (chip->monitoring_volume[i] !=
ucontrol->value.integer.value[i]) {
chip->monitoring_volume[i] =
- ucontrol->value.integer.value[i];
- if (chip->monitoring_active[i])
+ !!ucontrol->value.integer.value[i];
+ if(chip->monitoring_active[i])
/* update monitoring volume and mute */
/* do only when monitoring is unmuted */
pcxhr_update_audio_pipe_level(chip, 0, i);
@@ -511,7 +460,7 @@ static struct snd_kcontrol_new pcxhr_control_monitor_vol = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
.access = (SNDRV_CTL_ELEM_ACCESS_READWRITE |
SNDRV_CTL_ELEM_ACCESS_TLV_READ),
- .name = "Monitoring Playback Volume",
+ .name = "Monitoring Volume",
.info = pcxhr_digital_vol_info, /* shared */
.get = pcxhr_monitor_vol_get,
.put = pcxhr_monitor_vol_put,
@@ -562,7 +511,7 @@ static int pcxhr_monitor_sw_put(struct snd_kcontrol *kcontrol,
static struct snd_kcontrol_new pcxhr_control_monitor_sw = {
.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
- .name = "Monitoring Playback Switch",
+ .name = "Monitoring Switch",
.info = pcxhr_sw_info, /* shared */
.get = pcxhr_monitor_sw_get,
.put = pcxhr_monitor_sw_put
@@ -584,7 +533,7 @@ static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
struct pcxhr_rmh rmh;
unsigned int mask, reg;
unsigned int codec;
- int err, changed;
+ int err, use_src, changed;
switch (chip->chip_idx) {
case 0 : mask = PCXHR_SOURCE_AUDIO01_UER; codec = CS8420_01_CS; break;
@@ -593,10 +542,13 @@ static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
case 3 : mask = PCXHR_SOURCE_AUDIO67_UER; codec = CS8420_67_CS; break;
default: return -EINVAL;
}
+ reg = 0; /* audio source from analog plug */
+ use_src = 0; /* do not activate codec SRC */
+
if (chip->audio_capture_source != 0) {
reg = mask; /* audio source from digital plug */
- } else {
- reg = 0; /* audio source from analog plug */
+ if (chip->audio_capture_source == 2)
+ use_src = 1;
}
/* set the input source */
pcxhr_write_io_num_reg_cont(chip->mgr, mask, reg, &changed);
@@ -608,61 +560,29 @@ static int pcxhr_set_audio_source(struct snd_pcxhr* chip)
if (err)
return err;
}
- if (chip->mgr->board_aes_in_192k) {
- int i;
- unsigned int src_config = 0xC0;
- /* update all src configs with one call */
- for (i = 0; (i < 4) && (i < chip->mgr->capture_chips); i++) {
- if (chip->mgr->chip[i]->audio_capture_source == 2)
- src_config |= (1 << (3 - i));
- }
- /* set codec SRC on off */
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
- rmh.cmd_len = 2;
- rmh.cmd[0] |= IO_NUM_REG_CONFIG_SRC;
- rmh.cmd[1] = src_config;
- err = pcxhr_send_msg(chip->mgr, &rmh);
- } else {
- int use_src = 0;
- if (chip->audio_capture_source == 2)
- use_src = 1;
- /* set codec SRC on off */
- pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
- rmh.cmd_len = 3;
- rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
- rmh.cmd[1] = codec;
- rmh.cmd[2] = ((CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) |
- (use_src ? 0x41 : 0x54));
- err = pcxhr_send_msg(chip->mgr, &rmh);
- if (err)
- return err;
- rmh.cmd[2] = ((CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) |
- (use_src ? 0x41 : 0x49));
- err = pcxhr_send_msg(chip->mgr, &rmh);
- }
+ pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE); /* set codec SRC on off */
+ rmh.cmd_len = 3;
+ rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
+ rmh.cmd[1] = codec;
+ rmh.cmd[2] = (CS8420_DATA_FLOW_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x54);
+ err = pcxhr_send_msg(chip->mgr, &rmh);
+ if(err)
+ return err;
+ rmh.cmd[2] = (CS8420_CLOCK_SRC_CTL & CHIP_SIG_AND_MAP_SPI) | (use_src ? 0x41 : 0x49);
+ err = pcxhr_send_msg(chip->mgr, &rmh);
return err;
}
static int pcxhr_audio_src_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static const char *texts[5] = {
- "Line", "Digital", "Digi+SRC", "Mic", "Line+Mic"
- };
- int i;
- struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
+ static char *texts[3] = {"Analog", "Digital", "Digi+SRC"};
- i = 2; /* no SRC, no Mic available */
- if (chip->mgr->board_has_aes1) {
- i = 3; /* SRC available */
- if (chip->mgr->board_has_mic)
- i = 5; /* Mic and MicroMix available */
- }
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
- uinfo->value.enumerated.items = i;
- if (uinfo->value.enumerated.item > (i-1))
- uinfo->value.enumerated.item = i-1;
+ uinfo->value.enumerated.items = 3;
+ if (uinfo->value.enumerated.item > 2)
+ uinfo->value.enumerated.item = 2;
strcpy(uinfo->value.enumerated.name,
texts[uinfo->value.enumerated.item]);
return 0;
@@ -681,21 +601,13 @@ static int pcxhr_audio_src_put(struct snd_kcontrol *kcontrol,
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
int ret = 0;
- int i = 2; /* no SRC, no Mic available */
- if (chip->mgr->board_has_aes1) {
- i = 3; /* SRC available */
- if (chip->mgr->board_has_mic)
- i = 5; /* Mic and MicroMix available */
- }
- if (ucontrol->value.enumerated.item[0] >= i)
+
+ if (ucontrol->value.enumerated.item[0] >= 3)
return -EINVAL;
mutex_lock(&chip->mgr->mixer_mutex);
if (chip->audio_capture_source != ucontrol->value.enumerated.item[0]) {
chip->audio_capture_source = ucontrol->value.enumerated.item[0];
- if (chip->mgr->is_hr_stereo)
- hr222_set_audio_source(chip);
- else
- pcxhr_set_audio_source(chip);
+ pcxhr_set_audio_source(chip);
ret = 1;
}
mutex_unlock(&chip->mgr->mixer_mutex);
@@ -714,46 +626,25 @@ static struct snd_kcontrol_new pcxhr_control_audio_src = {
/*
* clock type selection
* enum pcxhr_clock_type {
- * PCXHR_CLOCK_TYPE_INTERNAL = 0,
- * PCXHR_CLOCK_TYPE_WORD_CLOCK,
- * PCXHR_CLOCK_TYPE_AES_SYNC,
- * PCXHR_CLOCK_TYPE_AES_1,
- * PCXHR_CLOCK_TYPE_AES_2,
- * PCXHR_CLOCK_TYPE_AES_3,
- * PCXHR_CLOCK_TYPE_AES_4,
- * PCXHR_CLOCK_TYPE_MAX = PCXHR_CLOCK_TYPE_AES_4,
- * HR22_CLOCK_TYPE_INTERNAL = PCXHR_CLOCK_TYPE_INTERNAL,
- * HR22_CLOCK_TYPE_AES_SYNC,
- * HR22_CLOCK_TYPE_AES_1,
- * HR22_CLOCK_TYPE_MAX = HR22_CLOCK_TYPE_AES_1,
- * };
+ * PCXHR_CLOCK_TYPE_INTERNAL = 0,
+ * PCXHR_CLOCK_TYPE_WORD_CLOCK,
+ * PCXHR_CLOCK_TYPE_AES_SYNC,
+ * PCXHR_CLOCK_TYPE_AES_1,
+ * PCXHR_CLOCK_TYPE_AES_2,
+ * PCXHR_CLOCK_TYPE_AES_3,
+ * PCXHR_CLOCK_TYPE_AES_4,
+ * };
*/
static int pcxhr_clock_type_info(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_info *uinfo)
{
- static const char *textsPCXHR[7] = {
- "Internal", "WordClock", "AES Sync",
- "AES 1", "AES 2", "AES 3", "AES 4"
- };
- static const char *textsHR22[3] = {
- "Internal", "AES Sync", "AES 1"
+ static char *texts[7] = {
+ "Internal", "WordClock", "AES Sync", "AES 1", "AES 2", "AES 3", "AES 4"
};
- const char **texts;
struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
- int clock_items = 2; /* at least Internal and AES Sync clock */
- if (mgr->board_has_aes1) {
- clock_items += mgr->capture_chips; /* add AES x */
- if (!mgr->is_hr_stereo)
- clock_items += 1; /* add word clock */
- }
- if (mgr->is_hr_stereo) {
- texts = textsHR22;
- snd_BUG_ON(clock_items > (HR22_CLOCK_TYPE_MAX+1));
- } else {
- texts = textsPCXHR;
- snd_BUG_ON(clock_items > (PCXHR_CLOCK_TYPE_MAX+1));
- }
+ int clock_items = 3 + mgr->capture_chips;
+
uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
uinfo->count = 1;
uinfo->value.enumerated.items = clock_items;
@@ -776,13 +667,9 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct pcxhr_mgr *mgr = snd_kcontrol_chip(kcontrol);
+ unsigned int clock_items = 3 + mgr->capture_chips;
int rate, ret = 0;
- unsigned int clock_items = 2; /* at least Internal and AES Sync clock */
- if (mgr->board_has_aes1) {
- clock_items += mgr->capture_chips; /* add AES x */
- if (!mgr->is_hr_stereo)
- clock_items += 1; /* add word clock */
- }
+
if (ucontrol->value.enumerated.item[0] >= clock_items)
return -EINVAL;
mutex_lock(&mgr->mixer_mutex);
@@ -790,8 +677,7 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
mutex_lock(&mgr->setup_mutex);
mgr->use_clock_type = ucontrol->value.enumerated.item[0];
if (mgr->use_clock_type)
- pcxhr_get_external_clock(mgr, mgr->use_clock_type,
- &rate);
+ pcxhr_get_external_clock(mgr, mgr->use_clock_type, &rate);
else
rate = mgr->sample_rate;
if (rate) {
@@ -800,7 +686,7 @@ static int pcxhr_clock_type_put(struct snd_kcontrol *kcontrol,
mgr->sample_rate = rate;
}
mutex_unlock(&mgr->setup_mutex);
- ret = 1; /* return 1 even if the set was not done. ok ? */
+ ret = 1; /* return 1 even if the set was not done. ok ? */
}
mutex_unlock(&mgr->mixer_mutex);
return ret;
@@ -861,16 +747,14 @@ static struct snd_kcontrol_new pcxhr_control_clock_rate = {
/*
* IEC958 status bits
*/
-static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_info *uinfo)
+static int pcxhr_iec958_info(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{
uinfo->type = SNDRV_CTL_ELEM_TYPE_IEC958;
uinfo->count = 1;
return 0;
}
-static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip,
- int aes_idx, unsigned char *aes_bits)
+static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char* aes_bits)
{
int i, err;
unsigned char temp;
@@ -879,61 +763,39 @@ static int pcxhr_iec958_capture_byte(struct snd_pcxhr *chip,
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_READ);
rmh.cmd[0] |= IO_NUM_UER_CHIP_REG;
switch (chip->chip_idx) {
- /* instead of CS8420_01_CS use CS8416_01_CS for AES SYNC plug */
- case 0: rmh.cmd[1] = CS8420_01_CS; break;
+ case 0: rmh.cmd[1] = CS8420_01_CS; break; /* use CS8416_01_CS for AES SYNC plug */
case 1: rmh.cmd[1] = CS8420_23_CS; break;
case 2: rmh.cmd[1] = CS8420_45_CS; break;
case 3: rmh.cmd[1] = CS8420_67_CS; break;
default: return -EINVAL;
}
- if (chip->mgr->board_aes_in_192k) {
- switch (aes_idx) {
- case 0: rmh.cmd[2] = CS8416_CSB0; break;
- case 1: rmh.cmd[2] = CS8416_CSB1; break;
- case 2: rmh.cmd[2] = CS8416_CSB2; break;
- case 3: rmh.cmd[2] = CS8416_CSB3; break;
- case 4: rmh.cmd[2] = CS8416_CSB4; break;
- default: return -EINVAL;
- }
- } else {
- switch (aes_idx) {
- /* instead of CS8420_CSB0 use CS8416_CSBx for AES SYNC plug */
- case 0: rmh.cmd[2] = CS8420_CSB0; break;
- case 1: rmh.cmd[2] = CS8420_CSB1; break;
- case 2: rmh.cmd[2] = CS8420_CSB2; break;
- case 3: rmh.cmd[2] = CS8420_CSB3; break;
- case 4: rmh.cmd[2] = CS8420_CSB4; break;
- default: return -EINVAL;
- }
+ switch (aes_idx) {
+ case 0: rmh.cmd[2] = CS8420_CSB0; break; /* use CS8416_CSBx for AES SYNC plug */
+ case 1: rmh.cmd[2] = CS8420_CSB1; break;
+ case 2: rmh.cmd[2] = CS8420_CSB2; break;
+ case 3: rmh.cmd[2] = CS8420_CSB3; break;
+ case 4: rmh.cmd[2] = CS8420_CSB4; break;
+ default: return -EINVAL;
}
- /* size and code the chip id for the fpga */
- rmh.cmd[1] &= 0x0fffff;
- /* chip signature + map for spi read */
- rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI;
+ rmh.cmd[1] &= 0x0fffff; /* size and code the chip id for the fpga */
+ rmh.cmd[2] &= CHIP_SIG_AND_MAP_SPI; /* chip signature + map for spi read */
rmh.cmd_len = 3;
err = pcxhr_send_msg(chip->mgr, &rmh);
if (err)
return err;
-
- if (chip->mgr->board_aes_in_192k) {
- temp = (unsigned char)rmh.stat[1];
- } else {
- temp = 0;
- /* reversed bit order (not with CS8416_01_CS) */
- for (i = 0; i < 8; i++) {
- temp <<= 1;
- if (rmh.stat[1] & (1 << i))
- temp |= 1;
- }
+ temp = 0;
+ for (i = 0; i < 8; i++) {
+ /* attention : reversed bit order (not with CS8416_01_CS) */
+ temp <<= 1;
+ if (rmh.stat[1] & (1 << i))
+ temp |= 1;
}
- snd_printdd("read iec958 AES %d byte %d = 0x%x\n",
- chip->chip_idx, aes_idx, temp);
+ snd_printdd("read iec958 AES %d byte %d = 0x%x\n", chip->chip_idx, aes_idx, temp);
*aes_bits = temp;
return 0;
}
-static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
+static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{
struct snd_pcxhr *chip = snd_kcontrol_chip(kcontrol);
unsigned char aes_bits;
@@ -944,12 +806,7 @@ static int pcxhr_iec958_get(struct snd_kcontrol *kcontrol,
if (kcontrol->private_value == 0) /* playback */
aes_bits = chip->aes_bits[i];
else { /* capture */
- if (chip->mgr->is_hr_stereo)
- err = hr222_iec958_capture_byte(chip, i,
- &aes_bits);
- else
- err = pcxhr_iec958_capture_byte(chip, i,
- &aes_bits);
+ err = pcxhr_iec958_capture_byte(chip, i, &aes_bits);
if (err)
break;
}
@@ -968,8 +825,7 @@ static int pcxhr_iec958_mask_get(struct snd_kcontrol *kcontrol,
return 0;
}
-static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip,
- int aes_idx, unsigned char aes_bits)
+static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip, int aes_idx, unsigned char aes_bits)
{
int i, err, cmd;
unsigned char new_bits = aes_bits;
@@ -978,12 +834,12 @@ static int pcxhr_iec958_update_byte(struct snd_pcxhr *chip,
for (i = 0; i < 8; i++) {
if ((old_bits & 0x01) != (new_bits & 0x01)) {
- cmd = chip->chip_idx & 0x03; /* chip index 0..3 */
- if (chip->chip_idx > 3)
+ cmd = chip->chip_idx & 0x03; /* chip index 0..3 */
+ if(chip->chip_idx > 3)
/* new bit used if chip_idx>3 (PCX1222HR) */
cmd |= 1 << 22;
- cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */
- cmd |= (new_bits & 0x01) << 23; /* add bit value */
+ cmd |= ((aes_idx << 3) + i) << 2; /* add bit offset */
+ cmd |= (new_bits & 0x01) << 23; /* add bit value */
pcxhr_init_rmh(&rmh, CMD_ACCESS_IO_WRITE);
rmh.cmd[0] |= IO_NUM_REG_CUER;
rmh.cmd[1] = cmd;
@@ -1011,12 +867,7 @@ static int pcxhr_iec958_put(struct snd_kcontrol *kcontrol,
mutex_lock(&chip->mgr->mixer_mutex);
for (i = 0; i < 5; i++) {
if (ucontrol->value.iec958.status[i] != chip->aes_bits[i]) {
- if (chip->mgr->is_hr_stereo)
- hr222_iec958_update_byte(chip, i,
- ucontrol->value.iec958.status[i]);
- else
- pcxhr_iec958_update_byte(chip, i,
- ucontrol->value.iec958.status[i]);
+ pcxhr_iec958_update_byte(chip, i, ucontrol->value.iec958.status[i]);
changed = 1;
}
}
@@ -1066,53 +917,29 @@ static void pcxhr_init_audio_levels(struct snd_pcxhr *chip)
/* at boot time the digital volumes are unmuted 0dB */
for (j = 0; j < PCXHR_PLAYBACK_STREAMS; j++) {
chip->digital_playback_active[j][i] = 1;
- chip->digital_playback_volume[j][i] =
- PCXHR_DIGITAL_ZERO_LEVEL;
+ chip->digital_playback_volume[j][i] = PCXHR_DIGITAL_ZERO_LEVEL;
}
- /* after boot, only two bits are set on the uer
- * interface
- */
- chip->aes_bits[0] = (IEC958_AES0_PROFESSIONAL |
- IEC958_AES0_PRO_FS_48000);
+ /* after boot, only two bits are set on the uer interface */
+ chip->aes_bits[0] = IEC958_AES0_PROFESSIONAL | IEC958_AES0_PRO_FS_48000;
+/* only for test purpose, remove later */
#ifdef CONFIG_SND_DEBUG
- /* analog volumes for playback
- * (is LEVEL_MIN after boot)
- */
+ /* analog volumes for playback (is LEVEL_MIN after boot) */
chip->analog_playback_active[i] = 1;
- if (chip->mgr->is_hr_stereo)
- chip->analog_playback_volume[i] =
- HR222_LINE_PLAYBACK_ZERO_LEVEL;
- else {
- chip->analog_playback_volume[i] =
- PCXHR_LINE_PLAYBACK_ZERO_LEVEL;
- pcxhr_update_analog_audio_level(chip, 0, i);
- }
+ chip->analog_playback_volume[i] = PCXHR_ANALOG_PLAYBACK_ZERO_LEVEL;
+ pcxhr_update_analog_audio_level(chip, 0, i);
#endif
- /* stereo cards need to be initialised after boot */
- if (chip->mgr->is_hr_stereo)
- hr222_update_analog_audio_level(chip, 0, i);
+/* test end */
}
if (chip->nb_streams_capt) {
/* at boot time the digital volumes are unmuted 0dB */
- chip->digital_capture_volume[i] =
- PCXHR_DIGITAL_ZERO_LEVEL;
- chip->analog_capture_active = 1;
+ chip->digital_capture_volume[i] = PCXHR_DIGITAL_ZERO_LEVEL;
+/* only for test purpose, remove later */
#ifdef CONFIG_SND_DEBUG
- /* analog volumes for playback
- * (is LEVEL_MIN after boot)
- */
- if (chip->mgr->is_hr_stereo)
- chip->analog_capture_volume[i] =
- HR222_LINE_CAPTURE_ZERO_LEVEL;
- else {
- chip->analog_capture_volume[i] =
- PCXHR_LINE_CAPTURE_ZERO_LEVEL;
- pcxhr_update_analog_audio_level(chip, 1, i);
- }
+ /* analog volumes for playback (is LEVEL_MIN after boot) */
+ chip->analog_capture_volume[i] = PCXHR_ANALOG_CAPTURE_ZERO_LEVEL;
+ pcxhr_update_analog_audio_level(chip, 1, i);
#endif
- /* stereo cards need to be initialised after boot */
- if (chip->mgr->is_hr_stereo)
- hr222_update_analog_audio_level(chip, 1, i);
+/* test end */
}
}
@@ -1136,125 +963,90 @@ int pcxhr_create_mixer(struct pcxhr_mgr *mgr)
temp = pcxhr_control_analog_level;
temp.name = "Master Playback Volume";
temp.private_value = 0; /* playback */
- if (mgr->is_hr_stereo)
- temp.tlv.p = db_scale_a_hr222_playback;
- else
- temp.tlv.p = db_scale_analog_playback;
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&temp, chip));
- if (err < 0)
+ temp.tlv.p = db_scale_analog_playback;
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
return err;
-
/* output mute controls */
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_output_switch,
- chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_output_switch,
+ chip))) < 0)
return err;
-
+
temp = snd_pcxhr_pcm_vol;
temp.name = "PCM Playback Volume";
temp.count = PCXHR_PLAYBACK_STREAMS;
temp.private_value = 0; /* playback */
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&temp, chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
return err;
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_pcm_switch, chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_pcm_switch,
+ chip))) < 0)
return err;
/* IEC958 controls */
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_playback_iec958_mask,
- chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_playback_iec958_mask,
+ chip))) < 0)
return err;
-
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_playback_iec958,
- chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_playback_iec958,
+ chip))) < 0)
return err;
}
if (chip->nb_streams_capt) {
- /* analog input level control */
+ /* analog input level control only on first two chips !*/
temp = pcxhr_control_analog_level;
- temp.name = "Line Capture Volume";
+ temp.name = "Master Capture Volume";
temp.private_value = 1; /* capture */
- if (mgr->is_hr_stereo)
- temp.tlv.p = db_scale_a_hr222_capture;
- else
- temp.tlv.p = db_scale_analog_capture;
-
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&temp, chip));
- if (err < 0)
+ temp.tlv.p = db_scale_analog_capture;
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
return err;
temp = snd_pcxhr_pcm_vol;
temp.name = "PCM Capture Volume";
temp.count = 1;
temp.private_value = 1; /* capture */
-
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&temp, chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card, snd_ctl_new1(&temp, chip))) < 0)
return err;
-
/* Audio source */
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_audio_src, chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_audio_src,
+ chip))) < 0)
return err;
-
/* IEC958 controls */
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_capture_iec958_mask,
- chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_capture_iec958_mask,
+ chip))) < 0)
return err;
-
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_capture_iec958,
- chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_capture_iec958,
+ chip))) < 0)
return err;
-
- if (mgr->is_hr_stereo) {
- err = hr222_add_mic_controls(chip);
- if (err < 0)
- return err;
- }
}
/* monitoring only if playback and capture device available */
if (chip->nb_streams_capt > 0 && chip->nb_streams_play > 0) {
/* monitoring */
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_monitor_vol, chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_monitor_vol,
+ chip))) < 0)
return err;
-
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_monitor_sw, chip));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_monitor_sw,
+ chip))) < 0)
return err;
}
if (i == 0) {
/* clock mode only one control per pcxhr */
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_clock_type, mgr));
- if (err < 0)
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_clock_type,
+ mgr))) < 0)
return err;
- /* non standard control used to scan
- * the external clock presence/frequencies
- */
- err = snd_ctl_add(chip->card,
- snd_ctl_new1(&pcxhr_control_clock_rate, mgr));
- if (err < 0)
+ /* non standard control used to scan the external clock presence/frequencies */
+ if ((err = snd_ctl_add(chip->card,
+ snd_ctl_new1(&pcxhr_control_clock_rate,
+ mgr))) < 0)
return err;
}
diff --git a/sound/pci/riptide/riptide.c b/sound/pci/riptide/riptide.c
index d0ccfc68c522..e9f0706ed3e4 100644
--- a/sound/pci/riptide/riptide.c
+++ b/sound/pci/riptide/riptide.c
@@ -172,7 +172,7 @@ MODULE_PARM_DESC(opl3_port, "OPL3 port # for Riptide driver.");
#define MAX_WRITE_RETRY 10 /* cmd interface limits */
#define MAX_ERROR_COUNT 10
-#define CMDIF_TIMEOUT 50000
+#define CMDIF_TIMEOUT 500000
#define RESET_TRIES 5
#define READ_PORT_ULONG(p) inl((unsigned long)&(p))
diff --git a/sound/pci/rme9652/hdsp.c b/sound/pci/rme9652/hdsp.c
index fdd3be5b439d..736246f98acc 100644
--- a/sound/pci/rme9652/hdsp.c
+++ b/sound/pci/rme9652/hdsp.c
@@ -1452,7 +1452,7 @@ static int snd_hdsp_create_midi (struct snd_card *card, struct hdsp *hdsp, int i
if (snd_rawmidi_new (card, buf, id, 1, 1, &hdsp->midi[id].rmidi) < 0)
return -1;
- sprintf(hdsp->midi[id].rmidi->name, "HDSP MIDI %d", id+1);
+ sprintf (hdsp->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
hdsp->midi[id].rmidi->private_data = &hdsp->midi[id];
snd_rawmidi_set_ops (hdsp->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT, &snd_hdsp_midi_output);
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index dc5c4baa1e64..98762f909d64 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -1293,7 +1293,7 @@ static int __devinit snd_hdspm_create_midi (struct snd_card *card,
if (err < 0)
return err;
- sprintf(hdspm->midi[id].rmidi->name, "HDSPM MIDI %d", id+1);
+ sprintf (hdspm->midi[id].rmidi->name, "%s MIDI %d", card->id, id+1);
hdspm->midi[id].rmidi->private_data = &hdspm->midi[id];
snd_rawmidi_set_ops(hdspm->midi[id].rmidi, SNDRV_RAWMIDI_STREAM_OUTPUT,
diff --git a/sound/ppc/pmac.c b/sound/ppc/pmac.c
index af76ee862d27..a38c0c790d2b 100644
--- a/sound/ppc/pmac.c
+++ b/sound/ppc/pmac.c
@@ -1033,7 +1033,7 @@ static int __init snd_pmac_detect(struct snd_pmac *chip)
}
if (of_device_is_compatible(sound, "tumbler")) {
chip->model = PMAC_TUMBLER;
- chip->can_capture = machine_is_compatible("PowerMac4,2");
+ chip->can_capture = 0; /* no capture */
chip->can_duplex = 0;
// chip->can_byte_swap = 0; /* FIXME: check this */
chip->num_freqs = ARRAY_SIZE(tumbler_freqs);
diff --git a/sound/ppc/tumbler.c b/sound/ppc/tumbler.c
index 3eb223385416..f746e15b8481 100644
--- a/sound/ppc/tumbler.c
+++ b/sound/ppc/tumbler.c
@@ -875,8 +875,7 @@ static struct snd_kcontrol_new snapper_mixers[] __initdata = {
.put = tumbler_put_master_switch
},
DEFINE_SNAPPER_MIX("PCM Playback Volume", 0, VOL_IDX_PCM),
- /* Alternative PCM is assigned to Mic analog loopback on iBook G4 */
- DEFINE_SNAPPER_MIX("Mic Playback Volume", 0, VOL_IDX_PCM2),
+ DEFINE_SNAPPER_MIX("PCM Playback Volume", 1, VOL_IDX_PCM2),
DEFINE_SNAPPER_MIX("Monitor Mix Volume", 0, VOL_IDX_ADC),
DEFINE_SNAPPER_MONO("Tone Control - Bass", bass),
DEFINE_SNAPPER_MONO("Tone Control - Treble", treble),
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index 615ebf0b76e7..4dfda6674bec 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -23,7 +23,8 @@ config SND_SOC_AC97_BUS
bool
# All the supported Soc's
-source "sound/soc/atmel/Kconfig"
+source "sound/soc/at32/Kconfig"
+source "sound/soc/at91/Kconfig"
source "sound/soc/au1x/Kconfig"
source "sound/soc/pxa/Kconfig"
source "sound/soc/s3c24xx/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index 4d475c3ceb91..d849349f2c66 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -1,5 +1,5 @@
snd-soc-core-objs := soc-core.o soc-dapm.o
obj-$(CONFIG_SND_SOC) += snd-soc-core.o
-obj-$(CONFIG_SND_SOC) += codecs/ atmel/ pxa/ s3c24xx/ sh/ fsl/ davinci/
+obj-$(CONFIG_SND_SOC) += codecs/ at32/ at91/ pxa/ s3c24xx/ sh/ fsl/ davinci/
obj-$(CONFIG_SND_SOC) += omap/ au1x/ blackfin/
diff --git a/sound/soc/at32/Kconfig b/sound/soc/at32/Kconfig
new file mode 100644
index 000000000000..b0765e86c085
--- /dev/null
+++ b/sound/soc/at32/Kconfig
@@ -0,0 +1,34 @@
+config SND_AT32_SOC
+ tristate "SoC Audio for the Atmel AT32 System-on-a-Chip"
+ depends on AVR32 && SND_SOC
+ help
+ Say Y or M if you want to add support for codecs attached to
+ the AT32 SSC interface. You will also need to
+ to select the audio interfaces to support below.
+
+
+config SND_AT32_SOC_SSC
+ tristate
+
+
+
+config SND_AT32_SOC_PLAYPAQ
+ tristate "SoC Audio support for PlayPaq with WM8510"
+ depends on SND_AT32_SOC && BOARD_PLAYPAQ
+ select SND_AT32_SOC_SSC
+ select SND_SOC_WM8510
+ help
+ Say Y or M here if you want to add support for SoC audio
+ on the LRS PlayPaq.
+
+
+
+config SND_AT32_SOC_PLAYPAQ_SLAVE
+ bool "Run CODEC on PlayPaq in slave mode"
+ depends on SND_AT32_SOC_PLAYPAQ
+ default n
+ help
+ Say Y if you want to run with the AT32 SSC generating the BCLK
+ and FRAME signals on the PlayPaq. Unless you want to play
+ with the AT32 as the SSC master, you probably want to say N here,
+ as this will give you better sound quality.
diff --git a/sound/soc/at32/Makefile b/sound/soc/at32/Makefile
new file mode 100644
index 000000000000..c03e55ececeb
--- /dev/null
+++ b/sound/soc/at32/Makefile
@@ -0,0 +1,11 @@
+# AT32 Platform Support
+snd-soc-at32-objs := at32-pcm.o
+snd-soc-at32-ssc-objs := at32-ssc.o
+
+obj-$(CONFIG_SND_AT32_SOC) += snd-soc-at32.o
+obj-$(CONFIG_SND_AT32_SOC_SSC) += snd-soc-at32-ssc.o
+
+# AT32 Machine Support
+snd-soc-playpaq-objs := playpaq_wm8510.o
+
+obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/at32/at32-pcm.c b/sound/soc/at32/at32-pcm.c
new file mode 100644
index 000000000000..c83584f989a9
--- /dev/null
+++ b/sound/soc/at32/at32-pcm.c
@@ -0,0 +1,492 @@
+/* sound/soc/at32/at32-pcm.c
+ * ASoC PCM interface for Atmel AT32 SoC
+ *
+ * Copyright (C) 2008 Long Range Systems
+ * Geoffrey Wossum <gwossum@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Note that this is basically a port of the sound/soc/at91-pcm.c to
+ * the AVR32 kernel. Thanks to Frank Mandarino for that code.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include "at32-pcm.h"
+
+
+
+/*--------------------------------------------------------------------------*\
+ * Hardware definition
+\*--------------------------------------------------------------------------*/
+/* TODO: These values were taken from the AT91 platform driver, check
+ * them against real values for AT32
+ */
+static const struct snd_pcm_hardware at32_pcm_hardware = {
+ .info = (SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER |
+ SNDRV_PCM_INFO_PAUSE),
+
+ .formats = SNDRV_PCM_FMTBIT_S16,
+ .period_bytes_min = 32,
+ .period_bytes_max = 8192, /* 512 frames * 16 bytes / frame */
+ .periods_min = 2,
+ .periods_max = 1024,
+ .buffer_bytes_max = 32 * 1024,
+};
+
+
+
+/*--------------------------------------------------------------------------*\
+ * Data types
+\*--------------------------------------------------------------------------*/
+struct at32_runtime_data {
+ struct at32_pcm_dma_params *params;
+ dma_addr_t dma_buffer; /* physical address of DMA buffer */
+ dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
+ size_t period_size;
+
+ dma_addr_t period_ptr; /* physical address of next period */
+ int periods; /* period index of period_ptr */
+
+ /* Save PDC registers (for power management) */
+ u32 pdc_xpr_save;
+ u32 pdc_xcr_save;
+ u32 pdc_xnpr_save;
+ u32 pdc_xncr_save;
+};
+
+
+
+/*--------------------------------------------------------------------------*\
+ * Helper functions
+\*--------------------------------------------------------------------------*/
+static int at32_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *dmabuf = &substream->dma_buffer;
+ size_t size = at32_pcm_hardware.buffer_bytes_max;
+
+ dmabuf->dev.type = SNDRV_DMA_TYPE_DEV;
+ dmabuf->dev.dev = pcm->card->dev;
+ dmabuf->private_data = NULL;
+ dmabuf->area = dma_alloc_coherent(pcm->card->dev, size,
+ &dmabuf->addr, GFP_KERNEL);
+ pr_debug("at32_pcm: preallocate_dma_buffer: "
+ "area=%p, addr=%p, size=%ld\n",
+ (void *)dmabuf->area, (void *)dmabuf->addr, size);
+
+ if (!dmabuf->area)
+ return -ENOMEM;
+
+ dmabuf->bytes = size;
+ return 0;
+}
+
+
+
+/*--------------------------------------------------------------------------*\
+ * ISR
+\*--------------------------------------------------------------------------*/
+static void at32_pcm_dma_irq(u32 ssc_sr, struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *rtd = substream->runtime;
+ struct at32_runtime_data *prtd = rtd->private_data;
+ struct at32_pcm_dma_params *params = prtd->params;
+ static int count;
+
+ count++;
+ if (ssc_sr & params->mask->ssc_endbuf) {
+ pr_warning("at32-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK ?
+ "underrun" : "overrun", params->name, ssc_sr, count);
+
+ /* re-start the PDC */
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end)
+ prtd->period_ptr = prtd->dma_buffer;
+
+
+ ssc_writex(params->ssc->regs, params->pdc->xpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_enable);
+ }
+
+
+ if (ssc_sr & params->mask->ssc_endx) {
+ /* Load the PDC next pointer and counter registers */
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end)
+ prtd->period_ptr = prtd->dma_buffer;
+ ssc_writex(params->ssc->regs, params->pdc->xnpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+ }
+
+
+ snd_pcm_period_elapsed(substream);
+}
+
+
+
+/*--------------------------------------------------------------------------*\
+ * PCM operations
+\*--------------------------------------------------------------------------*/
+static int at32_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct at32_runtime_data *prtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+ /* this may get called several times by oss emulation
+ * with different params
+ */
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = params_buffer_bytes(params);
+
+ prtd->params = rtd->dai->cpu_dai->dma_data;
+ prtd->params->dma_intr_handler = at32_pcm_dma_irq;
+
+ prtd->dma_buffer = runtime->dma_addr;
+ prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
+ prtd->period_size = params_period_bytes(params);
+
+ pr_debug("hw_params: DMA for %s initialized "
+ "(dma_bytes=%ld, period_size=%ld)\n",
+ prtd->params->name, runtime->dma_bytes, prtd->period_size);
+
+ return 0;
+}
+
+
+
+static int at32_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct at32_runtime_data *prtd = substream->runtime->private_data;
+ struct at32_pcm_dma_params *params = prtd->params;
+
+ if (params != NULL) {
+ ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+ params->mask->pdc_disable);
+ prtd->params->dma_intr_handler = NULL;
+ }
+
+ return 0;
+}
+
+
+
+static int at32_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct at32_runtime_data *prtd = substream->runtime->private_data;
+ struct at32_pcm_dma_params *params = prtd->params;
+
+ ssc_writex(params->ssc->regs, SSC_IDR,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+
+ return 0;
+}
+
+
+static int at32_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+ struct snd_pcm_runtime *rtd = substream->runtime;
+ struct at32_runtime_data *prtd = rtd->private_data;
+ struct at32_pcm_dma_params *params = prtd->params;
+ int ret = 0;
+
+ pr_debug("at32_pcm_trigger: buffer_size = %ld, "
+ "dma_area = %p, dma_bytes = %ld\n",
+ rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ prtd->period_ptr = prtd->dma_buffer;
+
+ ssc_writex(params->ssc->regs, params->pdc->xpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ prtd->period_ptr += prtd->period_size;
+ ssc_writex(params->ssc->regs, params->pdc->xnpr,
+ prtd->period_ptr);
+ ssc_writex(params->ssc->regs, params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ pr_debug("trigger: period_ptr=%lx, xpr=%x, "
+ "xcr=%d, xnpr=%x, xncr=%d\n",
+ (unsigned long)prtd->period_ptr,
+ ssc_readx(params->ssc->regs, params->pdc->xpr),
+ ssc_readx(params->ssc->regs, params->pdc->xcr),
+ ssc_readx(params->ssc->regs, params->pdc->xnpr),
+ ssc_readx(params->ssc->regs, params->pdc->xncr));
+
+ ssc_writex(params->ssc->regs, SSC_IER,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+ ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
+ params->mask->pdc_enable);
+
+ pr_debug("sr=%x, imr=%x\n",
+ ssc_readx(params->ssc->regs, SSC_SR),
+ ssc_readx(params->ssc->regs, SSC_IER));
+ break; /* SNDRV_PCM_TRIGGER_START */
+
+
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+ break;
+
+
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_enable);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+
+
+static snd_pcm_uframes_t at32_pcm_pointer(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct at32_runtime_data *prtd = runtime->private_data;
+ struct at32_pcm_dma_params *params = prtd->params;
+ dma_addr_t ptr;
+ snd_pcm_uframes_t x;
+
+ ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
+ x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
+
+ if (x == runtime->buffer_size)
+ x = 0;
+
+ return x;
+}
+
+
+
+static int at32_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct at32_runtime_data *prtd;
+ int ret = 0;
+
+ snd_soc_set_runtime_hwparams(substream, &at32_pcm_hardware);
+
+ /* ensure that buffer size is a multiple of period size */
+ ret = snd_pcm_hw_constraint_integer(runtime,
+ SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ goto out;
+
+ prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
+ if (prtd == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ runtime->private_data = prtd;
+
+
+out:
+ return ret;
+}
+
+
+
+static int at32_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct at32_runtime_data *prtd = substream->runtime->private_data;
+
+ kfree(prtd);
+ return 0;
+}
+
+
+static int at32_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ return remap_pfn_range(vma, vma->vm_start,
+ substream->dma_buffer.addr >> PAGE_SHIFT,
+ vma->vm_end - vma->vm_start, vma->vm_page_prot);
+}
+
+
+
+static struct snd_pcm_ops at32_pcm_ops = {
+ .open = at32_pcm_open,
+ .close = at32_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = at32_pcm_hw_params,
+ .hw_free = at32_pcm_hw_free,
+ .prepare = at32_pcm_prepare,
+ .trigger = at32_pcm_trigger,
+ .pointer = at32_pcm_pointer,
+ .mmap = at32_pcm_mmap,
+};
+
+
+
+/*--------------------------------------------------------------------------*\
+ * ASoC platform driver
+\*--------------------------------------------------------------------------*/
+static u64 at32_pcm_dmamask = 0xffffffff;
+
+static int at32_pcm_new(struct snd_card *card,
+ struct snd_soc_dai *dai,
+ struct snd_pcm *pcm)
+{
+ int ret = 0;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &at32_pcm_dmamask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = 0xffffffff;
+
+ if (dai->playback.channels_min) {
+ ret = at32_pcm_preallocate_dma_buffer(
+ pcm, SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+ if (dai->capture.channels_min) {
+ pr_debug("at32-pcm: Allocating PCM capture DMA buffer\n");
+ ret = at32_pcm_preallocate_dma_buffer(
+ pcm, SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+
+
+out:
+ return ret;
+}
+
+
+
+static void at32_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (substream == NULL)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+ dma_free_coherent(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+
+
+
+#ifdef CONFIG_PM
+static int at32_pcm_suspend(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct at32_runtime_data *prtd;
+ struct at32_pcm_dma_params *params;
+
+ if (runtime == NULL)
+ return 0;
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* Disable the PDC and save the PDC registers */
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
+ params->mask->pdc_disable);
+
+ prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
+ prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
+ prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
+ prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
+
+ return 0;
+}
+
+
+
+static int at32_pcm_resume(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct at32_runtime_data *prtd;
+ struct at32_pcm_dma_params *params;
+
+ if (runtime == NULL)
+ return 0;
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* Restore the PDC registers and enable the PDC */
+ ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
+ ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
+
+ ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR, params->mask->pdc_enable);
+ return 0;
+}
+#else /* CONFIG_PM */
+# define at32_pcm_suspend NULL
+# define at32_pcm_resume NULL
+#endif /* CONFIG_PM */
+
+
+
+struct snd_soc_platform at32_soc_platform = {
+ .name = "at32-audio",
+ .pcm_ops = &at32_pcm_ops,
+ .pcm_new = at32_pcm_new,
+ .pcm_free = at32_pcm_free_dma_buffers,
+ .suspend = at32_pcm_suspend,
+ .resume = at32_pcm_resume,
+};
+EXPORT_SYMBOL_GPL(at32_soc_platform);
+
+
+
+MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
+MODULE_DESCRIPTION("Atmel AT32 PCM module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-pcm.h b/sound/soc/at32/at32-pcm.h
new file mode 100644
index 000000000000..2a52430417da
--- /dev/null
+++ b/sound/soc/at32/at32-pcm.h
@@ -0,0 +1,79 @@
+/* sound/soc/at32/at32-pcm.h
+ * ASoC PCM interface for Atmel AT32 SoC
+ *
+ * Copyright (C) 2008 Long Range Systems
+ * Geoffrey Wossum <gwossum@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SOUND_SOC_AT32_AT32_PCM_H
+#define __SOUND_SOC_AT32_AT32_PCM_H __FILE__
+
+#include <linux/atmel-ssc.h>
+
+
+/*
+ * Registers and status bits that are required by the PCM driver
+ * TODO: Is ptcr really used?
+ */
+struct at32_pdc_regs {
+ u32 xpr; /* PDC RX/TX pointer */
+ u32 xcr; /* PDC RX/TX counter */
+ u32 xnpr; /* PDC next RX/TX pointer */
+ u32 xncr; /* PDC next RX/TX counter */
+ u32 ptcr; /* PDC transfer control */
+};
+
+
+
+/*
+ * SSC mask info
+ */
+struct at32_ssc_mask {
+ u32 ssc_enable; /* SSC RX/TX enable */
+ u32 ssc_disable; /* SSC RX/TX disable */
+ u32 ssc_endx; /* SSC ENDTX or ENDRX */
+ u32 ssc_endbuf; /* SSC TXBUFF or RXBUFF */
+ u32 pdc_enable; /* PDC RX/TX enable */
+ u32 pdc_disable; /* PDC RX/TX disable */
+};
+
+
+
+/*
+ * This structure, shared between the PCM driver and the interface,
+ * contains all information required by the PCM driver to perform the
+ * PDC DMA operation. All fields except dma_intr_handler() are initialized
+ * by the interface. The dms_intr_handler() pointer is set by the PCM
+ * driver and called by the interface SSC interrupt handler if it is
+ * non-NULL.
+ */
+struct at32_pcm_dma_params {
+ char *name; /* stream identifier */
+ int pdc_xfer_size; /* PDC counter increment in bytes */
+ struct ssc_device *ssc; /* SSC device for stream */
+ struct at32_pdc_regs *pdc; /* PDC register info */
+ struct at32_ssc_mask *mask; /* SSC mask info */
+ struct snd_pcm_substream *substream;
+ void (*dma_intr_handler) (u32, struct snd_pcm_substream *);
+};
+
+
+
+/*
+ * The AT32 ASoC platform driver
+ */
+extern struct snd_soc_platform at32_soc_platform;
+
+
+
+/*
+ * SSC register access (since ssc_writel() / ssc_readl() require literal name)
+ */
+#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
+#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
+
+#endif /* __SOUND_SOC_AT32_AT32_PCM_H */
diff --git a/sound/soc/at32/at32-ssc.c b/sound/soc/at32/at32-ssc.c
new file mode 100644
index 000000000000..4ef6492c902e
--- /dev/null
+++ b/sound/soc/at32/at32-ssc.c
@@ -0,0 +1,849 @@
+/* sound/soc/at32/at32-ssc.c
+ * ASoC platform driver for AT32 using SSC as DAI
+ *
+ * Copyright (C) 2008 Long Range Systems
+ * Geoffrey Wossum <gwossum@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Note that this is basically a port of the sound/soc/at91-ssc.c to
+ * the AVR32 kernel. Thanks to Frank Mandarino for that code.
+ */
+
+/* #define DEBUG */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/atmel_pdc.h>
+#include <linux/atmel-ssc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include "at32-pcm.h"
+#include "at32-ssc.h"
+
+
+
+/*-------------------------------------------------------------------------*\
+ * Constants
+\*-------------------------------------------------------------------------*/
+#define NUM_SSC_DEVICES 3
+
+/*
+ * SSC direction masks
+ */
+#define SSC_DIR_MASK_UNUSED 0
+#define SSC_DIR_MASK_PLAYBACK 1
+#define SSC_DIR_MASK_CAPTURE 2
+
+/*
+ * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
+ * are expected to be used with SSC_BF
+ */
+/* START bit field values */
+#define SSC_START_CONTINUOUS 0
+#define SSC_START_TX_RX 1
+#define SSC_START_LOW_RF 2
+#define SSC_START_HIGH_RF 3
+#define SSC_START_FALLING_RF 4
+#define SSC_START_RISING_RF 5
+#define SSC_START_LEVEL_RF 6
+#define SSC_START_EDGE_RF 7
+#define SSS_START_COMPARE_0 8
+
+/* CKI bit field values */
+#define SSC_CKI_FALLING 0
+#define SSC_CKI_RISING 1
+
+/* CKO bit field values */
+#define SSC_CKO_NONE 0
+#define SSC_CKO_CONTINUOUS 1
+#define SSC_CKO_TRANSFER 2
+
+/* CKS bit field values */
+#define SSC_CKS_DIV 0
+#define SSC_CKS_CLOCK 1
+#define SSC_CKS_PIN 2
+
+/* FSEDGE bit field values */
+#define SSC_FSEDGE_POSITIVE 0
+#define SSC_FSEDGE_NEGATIVE 1
+
+/* FSOS bit field values */
+#define SSC_FSOS_NONE 0
+#define SSC_FSOS_NEGATIVE 1
+#define SSC_FSOS_POSITIVE 2
+#define SSC_FSOS_LOW 3
+#define SSC_FSOS_HIGH 4
+#define SSC_FSOS_TOGGLE 5
+
+#define START_DELAY 1
+
+
+
+/*-------------------------------------------------------------------------*\
+ * Module data
+\*-------------------------------------------------------------------------*/
+/*
+ * SSC PDC registered required by the PCM DMA engine
+ */
+static struct at32_pdc_regs pdc_tx_reg = {
+ .xpr = SSC_PDC_TPR,
+ .xcr = SSC_PDC_TCR,
+ .xnpr = SSC_PDC_TNPR,
+ .xncr = SSC_PDC_TNCR,
+};
+
+
+
+static struct at32_pdc_regs pdc_rx_reg = {
+ .xpr = SSC_PDC_RPR,
+ .xcr = SSC_PDC_RCR,
+ .xnpr = SSC_PDC_RNPR,
+ .xncr = SSC_PDC_RNCR,
+};
+
+
+
+/*
+ * SSC and PDC status bits for transmit and receive
+ */
+static struct at32_ssc_mask ssc_tx_mask = {
+ .ssc_enable = SSC_BIT(CR_TXEN),
+ .ssc_disable = SSC_BIT(CR_TXDIS),
+ .ssc_endx = SSC_BIT(SR_ENDTX),
+ .ssc_endbuf = SSC_BIT(SR_TXBUFE),
+ .pdc_enable = SSC_BIT(PDC_PTCR_TXTEN),
+ .pdc_disable = SSC_BIT(PDC_PTCR_TXTDIS),
+};
+
+
+
+static struct at32_ssc_mask ssc_rx_mask = {
+ .ssc_enable = SSC_BIT(CR_RXEN),
+ .ssc_disable = SSC_BIT(CR_RXDIS),
+ .ssc_endx = SSC_BIT(SR_ENDRX),
+ .ssc_endbuf = SSC_BIT(SR_RXBUFF),
+ .pdc_enable = SSC_BIT(PDC_PTCR_RXTEN),
+ .pdc_disable = SSC_BIT(PDC_PTCR_RXTDIS),
+};
+
+
+
+/*
+ * DMA parameters for each SSC
+ */
+static struct at32_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
+ {
+ {
+ .name = "SSC0 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC0 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ },
+ },
+ {
+ {
+ .name = "SSC1 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC1 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ },
+ },
+ {
+ {
+ .name = "SSC2 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC2 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ },
+ },
+};
+
+
+
+static struct at32_ssc_info ssc_info[NUM_SSC_DEVICES] = {
+ {
+ .name = "ssc0",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
+ .dir_mask = SSC_DIR_MASK_UNUSED,
+ .initialized = 0,
+ },
+ {
+ .name = "ssc1",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
+ .dir_mask = SSC_DIR_MASK_UNUSED,
+ .initialized = 0,
+ },
+ {
+ .name = "ssc2",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
+ .dir_mask = SSC_DIR_MASK_UNUSED,
+ .initialized = 0,
+ },
+};
+
+
+
+
+/*-------------------------------------------------------------------------*\
+ * ISR
+\*-------------------------------------------------------------------------*/
+/*
+ * SSC interrupt handler. Passes PDC interrupts to the DMA interrupt
+ * handler in the PCM driver.
+ */
+static irqreturn_t at32_ssc_interrupt(int irq, void *dev_id)
+{
+ struct at32_ssc_info *ssc_p = dev_id;
+ struct at32_pcm_dma_params *dma_params;
+ u32 ssc_sr;
+ u32 ssc_substream_mask;
+ int i;
+
+ ssc_sr = (ssc_readl(ssc_p->ssc->regs, SR) &
+ ssc_readl(ssc_p->ssc->regs, IMR));
+
+ /*
+ * Loop through substreams attached to this SSC. If a DMA-related
+ * interrupt occured on that substream, call the DMA interrupt
+ * handler function, if one has been registered in the dma_param
+ * structure by the PCM driver.
+ */
+ for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
+ dma_params = ssc_p->dma_params[i];
+
+ if ((dma_params != NULL) &&
+ (dma_params->dma_intr_handler != NULL)) {
+ ssc_substream_mask = (dma_params->mask->ssc_endx |
+ dma_params->mask->ssc_endbuf);
+ if (ssc_sr & ssc_substream_mask) {
+ dma_params->dma_intr_handler(ssc_sr,
+ dma_params->
+ substream);
+ }
+ }
+ }
+
+
+ return IRQ_HANDLED;
+}
+
+/*-------------------------------------------------------------------------*\
+ * DAI functions
+\*-------------------------------------------------------------------------*/
+/*
+ * Startup. Only that one substream allowed in each direction.
+ */
+static int at32_ssc_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ int dir_mask;
+
+ dir_mask = ((substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
+ SSC_DIR_MASK_PLAYBACK : SSC_DIR_MASK_CAPTURE);
+
+ spin_lock_irq(&ssc_p->lock);
+ if (ssc_p->dir_mask & dir_mask) {
+ spin_unlock_irq(&ssc_p->lock);
+ return -EBUSY;
+ }
+ ssc_p->dir_mask |= dir_mask;
+ spin_unlock_irq(&ssc_p->lock);
+
+ return 0;
+}
+
+
+
+/*
+ * Shutdown. Clear DMA parameters and shutdown the SSC if there
+ * are no other substreams open.
+ */
+static void at32_ssc_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ struct at32_pcm_dma_params *dma_params;
+ int dir_mask;
+
+ dma_params = ssc_p->dma_params[substream->stream];
+
+ if (dma_params != NULL) {
+ ssc_writel(dma_params->ssc->regs, CR,
+ dma_params->mask->ssc_disable);
+ pr_debug("%s disabled SSC_SR=0x%08x\n",
+ (substream->stream ? "receiver" : "transmit"),
+ ssc_readl(ssc_p->ssc->regs, SR));
+
+ dma_params->ssc = NULL;
+ dma_params->substream = NULL;
+ ssc_p->dma_params[substream->stream] = NULL;
+ }
+
+
+ dir_mask = 1 << substream->stream;
+ spin_lock_irq(&ssc_p->lock);
+ ssc_p->dir_mask &= ~dir_mask;
+ if (!ssc_p->dir_mask) {
+ /* Shutdown the SSC clock */
+ pr_debug("at32-ssc: Stopping user %d clock\n",
+ ssc_p->ssc->user);
+ clk_disable(ssc_p->ssc->clk);
+
+ if (ssc_p->initialized) {
+ free_irq(ssc_p->ssc->irq, ssc_p);
+ ssc_p->initialized = 0;
+ }
+
+ /* Reset the SSC */
+ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
+
+ /* clear the SSC dividers */
+ ssc_p->cmr_div = 0;
+ ssc_p->tcmr_period = 0;
+ ssc_p->rcmr_period = 0;
+ }
+ spin_unlock_irq(&ssc_p->lock);
+}
+
+
+
+/*
+ * Set the SSC system clock rate
+ */
+static int at32_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ /* TODO: What the heck do I do here? */
+ return 0;
+}
+
+
+
+/*
+ * Record DAI format for use by hw_params()
+ */
+static int at32_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+ ssc_p->daifmt = fmt;
+ return 0;
+}
+
+
+
+/*
+ * Record SSC clock dividers for use in hw_params()
+ */
+static int at32_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
+ int div_id, int div)
+{
+ struct at32_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+ switch (div_id) {
+ case AT32_SSC_CMR_DIV:
+ /*
+ * The same master clock divider is used for both
+ * transmit and receive, so if a value has already
+ * been set, it must match this value
+ */
+ if (ssc_p->cmr_div == 0)
+ ssc_p->cmr_div = div;
+ else if (div != ssc_p->cmr_div)
+ return -EBUSY;
+ break;
+
+ case AT32_SSC_TCMR_PERIOD:
+ ssc_p->tcmr_period = div;
+ break;
+
+ case AT32_SSC_RCMR_PERIOD:
+ ssc_p->rcmr_period = div;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+
+
+/*
+ * Configure the SSC
+ */
+static int at32_ssc_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int id = rtd->dai->cpu_dai->id;
+ struct at32_ssc_info *ssc_p = &ssc_info[id];
+ struct at32_pcm_dma_params *dma_params;
+ int channels, bits;
+ u32 tfmr, rfmr, tcmr, rcmr;
+ int start_event;
+ int ret;
+
+
+ /*
+ * Currently, there is only one set of dma_params for each direction.
+ * If more are added, this code will have to be changed to select
+ * the proper set
+ */
+ dma_params = &ssc_dma_params[id][substream->stream];
+ dma_params->ssc = ssc_p->ssc;
+ dma_params->substream = substream;
+
+ ssc_p->dma_params[substream->stream] = dma_params;
+
+
+ /*
+ * The cpu_dai->dma_data field is only used to communicate the
+ * appropriate DMA parameters to the PCM driver's hw_params()
+ * function. It should not be used for other purposes as it
+ * is common to all substreams.
+ */
+ rtd->dai->cpu_dai->dma_data = dma_params;
+
+ channels = params_channels(params);
+
+
+ /*
+ * Determine sample size in bits and the PDC increment
+ */
+ switch (params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ bits = 8;
+ dma_params->pdc_xfer_size = 1;
+ break;
+
+ case SNDRV_PCM_FORMAT_S16:
+ bits = 16;
+ dma_params->pdc_xfer_size = 2;
+ break;
+
+ case SNDRV_PCM_FORMAT_S24:
+ bits = 24;
+ dma_params->pdc_xfer_size = 4;
+ break;
+
+ case SNDRV_PCM_FORMAT_S32:
+ bits = 32;
+ dma_params->pdc_xfer_size = 4;
+ break;
+
+ default:
+ pr_warning("at32-ssc: Unsupported PCM format %d",
+ params_format(params));
+ return -EINVAL;
+ }
+ pr_debug("at32-ssc: bits = %d, pdc_xfer_size = %d, channels = %d\n",
+ bits, dma_params->pdc_xfer_size, channels);
+
+
+ /*
+ * The SSC only supports up to 16-bit samples in I2S format, due
+ * to the size of the Frame Mode Register FSLEN field.
+ */
+ if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S)
+ if (bits > 16) {
+ pr_warning("at32-ssc: "
+ "sample size %d is too large for I2S\n",
+ bits);
+ return -EINVAL;
+ }
+
+
+ /*
+ * Compute the SSC register settings
+ */
+ switch (ssc_p->daifmt & (SND_SOC_DAIFMT_FORMAT_MASK |
+ SND_SOC_DAIFMT_MASTER_MASK)) {
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
+ /*
+ * I2S format, SSC provides BCLK and LRS clocks.
+ *
+ * The SSC transmit and receive clocks are generated from the
+ * MCK divider, and the BCLK signal is output on the SSC TK line
+ */
+ pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME master\n");
+ rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
+ SSC_BF(RCMR_STTDLY, START_DELAY) |
+ SSC_BF(RCMR_START, SSC_START_FALLING_RF) |
+ SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
+ SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
+ SSC_BF(RCMR_CKS, SSC_CKS_DIV));
+
+ rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+ SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE) |
+ SSC_BF(RFMR_FSLEN, bits - 1) |
+ SSC_BF(RFMR_DATNB, channels - 1) |
+ SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
+
+ tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
+ SSC_BF(TCMR_STTDLY, START_DELAY) |
+ SSC_BF(TCMR_START, SSC_START_FALLING_RF) |
+ SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
+ SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
+ SSC_BF(TCMR_CKS, SSC_CKS_DIV));
+
+ tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+ SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE) |
+ SSC_BF(TFMR_FSLEN, bits - 1) |
+ SSC_BF(TFMR_DATNB, channels - 1) | SSC_BIT(TFMR_MSBF) |
+ SSC_BF(TFMR_DATLEN, bits - 1));
+ break;
+
+
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
+ /*
+ * I2S format, CODEC supplies BCLK and LRC clock.
+ *
+ * The SSC transmit clock is obtained from the BCLK signal
+ * on the TK line, and the SSC receive clock is generated from
+ * the transmit clock.
+ *
+ * For single channel data, one sample is transferred on the
+ * falling edge of the LRC clock. For two channel data, one
+ * sample is transferred on both edges of the LRC clock.
+ */
+ pr_debug("at32-ssc: SSC mode is I2S BCLK / FRAME slave\n");
+ start_event = ((channels == 1) ?
+ SSC_START_FALLING_RF : SSC_START_EDGE_RF);
+
+ rcmr = (SSC_BF(RCMR_STTDLY, START_DELAY) |
+ SSC_BF(RCMR_START, start_event) |
+ SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
+ SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
+ SSC_BF(RCMR_CKS, SSC_CKS_CLOCK));
+
+ rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+ SSC_BF(RFMR_FSOS, SSC_FSOS_NONE) |
+ SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
+
+ tcmr = (SSC_BF(TCMR_STTDLY, START_DELAY) |
+ SSC_BF(TCMR_START, start_event) |
+ SSC_BF(TCMR_CKI, SSC_CKI_FALLING) |
+ SSC_BF(TCMR_CKO, SSC_CKO_NONE) |
+ SSC_BF(TCMR_CKS, SSC_CKS_PIN));
+
+ tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+ SSC_BF(TFMR_FSOS, SSC_FSOS_NONE) |
+ SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
+ break;
+
+
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
+ /*
+ * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
+ *
+ * The SSC transmit and receive clocks are generated from the
+ * MCK divider, and the BCLK signal is output on the SSC TK line
+ */
+ pr_debug("at32-ssc: SSC mode is DSP A BCLK / FRAME master\n");
+ rcmr = (SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period) |
+ SSC_BF(RCMR_STTDLY, 1) |
+ SSC_BF(RCMR_START, SSC_START_RISING_RF) |
+ SSC_BF(RCMR_CKI, SSC_CKI_RISING) |
+ SSC_BF(RCMR_CKO, SSC_CKO_NONE) |
+ SSC_BF(RCMR_CKS, SSC_CKS_DIV));
+
+ rfmr = (SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+ SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE) |
+ SSC_BF(RFMR_DATNB, channels - 1) |
+ SSC_BIT(RFMR_MSBF) | SSC_BF(RFMR_DATLEN, bits - 1));
+
+ tcmr = (SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period) |
+ SSC_BF(TCMR_STTDLY, 1) |
+ SSC_BF(TCMR_START, SSC_START_RISING_RF) |
+ SSC_BF(TCMR_CKI, SSC_CKI_RISING) |
+ SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS) |
+ SSC_BF(TCMR_CKS, SSC_CKS_DIV));
+
+ tfmr = (SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE) |
+ SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE) |
+ SSC_BF(TFMR_DATNB, channels - 1) |
+ SSC_BIT(TFMR_MSBF) | SSC_BF(TFMR_DATLEN, bits - 1));
+ break;
+
+
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
+ default:
+ pr_warning("at32-ssc: unsupported DAI format 0x%x\n",
+ ssc_p->daifmt);
+ return -EINVAL;
+ break;
+ }
+ pr_debug("at32-ssc: RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
+ rcmr, rfmr, tcmr, tfmr);
+
+
+ if (!ssc_p->initialized) {
+ /* enable peripheral clock */
+ pr_debug("at32-ssc: Starting clock\n");
+ clk_enable(ssc_p->ssc->clk);
+
+ /* Reset the SSC and its PDC registers */
+ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
+
+ ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
+
+ ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
+ ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
+
+ ret = request_irq(ssc_p->ssc->irq, at32_ssc_interrupt, 0,
+ ssc_p->name, ssc_p);
+ if (ret < 0) {
+ pr_warning("at32-ssc: request irq failed (%d)\n", ret);
+ pr_debug("at32-ssc: Stopping clock\n");
+ clk_disable(ssc_p->ssc->clk);
+ return ret;
+ }
+
+ ssc_p->initialized = 1;
+ }
+
+ /* Set SSC clock mode register */
+ ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
+
+ /* set receive clock mode and format */
+ ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
+ ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
+
+ /* set transmit clock mode and format */
+ ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
+ ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
+
+ pr_debug("at32-ssc: SSC initialized\n");
+ return 0;
+}
+
+
+
+static int at32_ssc_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct at32_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ struct at32_pcm_dma_params *dma_params;
+
+ dma_params = ssc_p->dma_params[substream->stream];
+
+ ssc_writel(dma_params->ssc->regs, CR, dma_params->mask->ssc_enable);
+
+ return 0;
+}
+
+
+
+#ifdef CONFIG_PM
+static int at32_ssc_suspend(struct platform_device *pdev,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct at32_ssc_info *ssc_p;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ ssc_p = &ssc_info[cpu_dai->id];
+
+ /* Save the status register before disabling transmit and receive */
+ ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
+ ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
+
+ /* Save the current interrupt mask, then disable unmasked interrupts */
+ ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
+ ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
+
+ ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
+ ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
+ ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
+ ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
+ ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
+
+ return 0;
+}
+
+
+
+static int at32_ssc_resume(struct platform_device *pdev,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct at32_ssc_info *ssc_p;
+ u32 cr;
+
+ if (!cpu_dai->active)
+ return 0;
+
+ ssc_p = &ssc_info[cpu_dai->id];
+
+ /* restore SSC register settings */
+ ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
+ ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
+ ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
+ ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
+ ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
+
+ /* re-enable interrupts */
+ ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
+
+ /* Re-enable recieve and transmit as appropriate */
+ cr = 0;
+ cr |=
+ (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
+ cr |=
+ (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
+ ssc_writel(ssc_p->ssc->regs, CR, cr);
+
+ return 0;
+}
+#else /* CONFIG_PM */
+# define at32_ssc_suspend NULL
+# define at32_ssc_resume NULL
+#endif /* CONFIG_PM */
+
+
+#define AT32_SSC_RATES \
+ (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 | SNDRV_PCM_RATE_16000 | \
+ SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
+
+
+#define AT32_SSC_FORMATS \
+ (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16 | \
+ SNDRV_PCM_FMTBIT_S24 | SNDRV_PCM_FMTBIT_S32)
+
+
+struct snd_soc_dai at32_ssc_dai[NUM_SSC_DEVICES] = {
+ {
+ .name = "at32-ssc0",
+ .id = 0,
+ .type = SND_SOC_DAI_PCM,
+ .suspend = at32_ssc_suspend,
+ .resume = at32_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT32_SSC_RATES,
+ .formats = AT32_SSC_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT32_SSC_RATES,
+ .formats = AT32_SSC_FORMATS,
+ },
+ .ops = {
+ .startup = at32_ssc_startup,
+ .shutdown = at32_ssc_shutdown,
+ .prepare = at32_ssc_prepare,
+ .hw_params = at32_ssc_hw_params,
+ },
+ .dai_ops = {
+ .set_sysclk = at32_ssc_set_dai_sysclk,
+ .set_fmt = at32_ssc_set_dai_fmt,
+ .set_clkdiv = at32_ssc_set_dai_clkdiv,
+ },
+ .private_data = &ssc_info[0],
+ },
+ {
+ .name = "at32-ssc1",
+ .id = 1,
+ .type = SND_SOC_DAI_PCM,
+ .suspend = at32_ssc_suspend,
+ .resume = at32_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT32_SSC_RATES,
+ .formats = AT32_SSC_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT32_SSC_RATES,
+ .formats = AT32_SSC_FORMATS,
+ },
+ .ops = {
+ .startup = at32_ssc_startup,
+ .shutdown = at32_ssc_shutdown,
+ .prepare = at32_ssc_prepare,
+ .hw_params = at32_ssc_hw_params,
+ },
+ .dai_ops = {
+ .set_sysclk = at32_ssc_set_dai_sysclk,
+ .set_fmt = at32_ssc_set_dai_fmt,
+ .set_clkdiv = at32_ssc_set_dai_clkdiv,
+ },
+ .private_data = &ssc_info[1],
+ },
+ {
+ .name = "at32-ssc2",
+ .id = 2,
+ .type = SND_SOC_DAI_PCM,
+ .suspend = at32_ssc_suspend,
+ .resume = at32_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT32_SSC_RATES,
+ .formats = AT32_SSC_FORMATS,
+ },
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT32_SSC_RATES,
+ .formats = AT32_SSC_FORMATS,
+ },
+ .ops = {
+ .startup = at32_ssc_startup,
+ .shutdown = at32_ssc_shutdown,
+ .prepare = at32_ssc_prepare,
+ .hw_params = at32_ssc_hw_params,
+ },
+ .dai_ops = {
+ .set_sysclk = at32_ssc_set_dai_sysclk,
+ .set_fmt = at32_ssc_set_dai_fmt,
+ .set_clkdiv = at32_ssc_set_dai_clkdiv,
+ },
+ .private_data = &ssc_info[2],
+ },
+};
+EXPORT_SYMBOL_GPL(at32_ssc_dai);
+
+
+MODULE_AUTHOR("Geoffrey Wossum <gwossum@acm.org>");
+MODULE_DESCRIPTION("AT32 SSC ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/at32/at32-ssc.h b/sound/soc/at32/at32-ssc.h
new file mode 100644
index 000000000000..3c052dbbe460
--- /dev/null
+++ b/sound/soc/at32/at32-ssc.h
@@ -0,0 +1,59 @@
+/* sound/soc/at32/at32-ssc.h
+ * ASoC SSC interface for Atmel AT32 SoC
+ *
+ * Copyright (C) 2008 Long Range Systems
+ * Geoffrey Wossum <gwossum@acm.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __SOUND_SOC_AT32_AT32_SSC_H
+#define __SOUND_SOC_AT32_AT32_SSC_H __FILE__
+
+#include <linux/types.h>
+#include <linux/atmel-ssc.h>
+
+#include "at32-pcm.h"
+
+
+
+struct at32_ssc_state {
+ u32 ssc_cmr;
+ u32 ssc_rcmr;
+ u32 ssc_rfmr;
+ u32 ssc_tcmr;
+ u32 ssc_tfmr;
+ u32 ssc_sr;
+ u32 ssc_imr;
+};
+
+
+
+struct at32_ssc_info {
+ char *name;
+ struct ssc_device *ssc;
+ spinlock_t lock; /* lock for dir_mask */
+ unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
+ unsigned short initialized; /* true if SSC has been initialized */
+ unsigned short daifmt;
+ unsigned short cmr_div;
+ unsigned short tcmr_period;
+ unsigned short rcmr_period;
+ struct at32_pcm_dma_params *dma_params[2];
+ struct at32_ssc_state ssc_state;
+};
+
+
+/* SSC divider ids */
+#define AT32_SSC_CMR_DIV 0 /* MCK divider for BCLK */
+#define AT32_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
+#define AT32_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
+
+
+extern struct snd_soc_dai at32_ssc_dai[];
+
+
+
+#endif /* __SOUND_SOC_AT32_AT32_SSC_H */
diff --git a/sound/soc/atmel/playpaq_wm8510.c b/sound/soc/at32/playpaq_wm8510.c
index 43dd8cee83c6..b1966e4dfcd3 100644
--- a/sound/soc/atmel/playpaq_wm8510.c
+++ b/sound/soc/at32/playpaq_wm8510.c
@@ -22,6 +22,7 @@
#include <linux/module.h>
#include <linux/moduleparam.h>
+#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/clk.h>
@@ -39,8 +40,8 @@
#include <mach/portmux.h>
#include "../codecs/wm8510.h"
-#include "atmel-pcm.h"
-#include "atmel_ssc_dai.h"
+#include "at32-pcm.h"
+#include "at32-ssc.h"
/*-------------------------------------------------------------------------*\
@@ -361,9 +362,8 @@ static struct snd_soc_dai_link playpaq_wm8510_dai = {
-static struct snd_soc_card snd_soc_playpaq = {
+static struct snd_soc_machine snd_soc_machine_playpaq = {
.name = "LRS_PlayPaq_WM8510",
- .platform = &at32_soc_platform,
.dai_link = &playpaq_wm8510_dai,
.num_links = 1,
};
@@ -378,7 +378,8 @@ static struct wm8510_setup_data playpaq_wm8510_setup = {
static struct snd_soc_device playpaq_wm8510_snd_devdata = {
- .card = &snd_soc_playpaq,
+ .machine = &snd_soc_machine_playpaq,
+ .platform = &at32_soc_platform,
.codec_dev = &soc_codec_dev_wm8510,
.codec_data = &playpaq_wm8510_setup,
};
diff --git a/sound/soc/at91/Kconfig b/sound/soc/at91/Kconfig
new file mode 100644
index 000000000000..85a883299c2e
--- /dev/null
+++ b/sound/soc/at91/Kconfig
@@ -0,0 +1,10 @@
+config SND_AT91_SOC
+ tristate "SoC Audio for the Atmel AT91 System-on-Chip"
+ depends on ARCH_AT91
+ help
+ Say Y or M if you want to add support for codecs attached to
+ the AT91 SSC interface. You will also need
+ to select the audio interfaces to support below.
+
+config SND_AT91_SOC_SSC
+ tristate
diff --git a/sound/soc/at91/Makefile b/sound/soc/at91/Makefile
new file mode 100644
index 000000000000..b817f11df286
--- /dev/null
+++ b/sound/soc/at91/Makefile
@@ -0,0 +1,6 @@
+# AT91 Platform Support
+snd-soc-at91-objs := at91-pcm.o
+snd-soc-at91-ssc-objs := at91-ssc.o
+
+obj-$(CONFIG_SND_AT91_SOC) += snd-soc-at91.o
+obj-$(CONFIG_SND_AT91_SOC_SSC) += snd-soc-at91-ssc.o
diff --git a/sound/soc/at91/at91-pcm.c b/sound/soc/at91/at91-pcm.c
new file mode 100644
index 000000000000..7ab48bd25e4c
--- /dev/null
+++ b/sound/soc/at91/at91-pcm.c
@@ -0,0 +1,434 @@
+/*
+ * at91-pcm.c -- ALSA PCM interface for the Atmel AT91 SoC
+ *
+ * Author: Frank Mandarino <fmandarino@endrelia.com>
+ * Endrelia Technologies Inc.
+ * Created: Mar 3, 2006
+ *
+ * Based on pxa2xx-pcm.c by:
+ *
+ * Author: Nicolas Pitre
+ * Created: Nov 30, 2004
+ * Copyright: (C) 2004 MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/atmel_pdc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/soc.h>
+
+#include <mach/hardware.h>
+#include <mach/at91_ssc.h>
+
+#include "at91-pcm.h"
+
+#if 0
+#define DBG(x...) printk(KERN_INFO "at91-pcm: " x)
+#else
+#define DBG(x...)
+#endif
+
+static const struct snd_pcm_hardware at91_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_MMAP |
+ SNDRV_PCM_INFO_MMAP_VALID |
+ SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_PAUSE,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ .period_bytes_min = 32,
+ .period_bytes_max = 8192,
+ .periods_min = 2,
+ .periods_max = 1024,
+ .buffer_bytes_max = 32 * 1024,
+};
+
+struct at91_runtime_data {
+ struct at91_pcm_dma_params *params;
+ dma_addr_t dma_buffer; /* physical address of dma buffer */
+ dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
+ size_t period_size;
+ dma_addr_t period_ptr; /* physical address of next period */
+ u32 pdc_xpr_save; /* PDC register save */
+ u32 pdc_xcr_save;
+ u32 pdc_xnpr_save;
+ u32 pdc_xncr_save;
+};
+
+static void at91_pcm_dma_irq(u32 ssc_sr,
+ struct snd_pcm_substream *substream)
+{
+ struct at91_runtime_data *prtd = substream->runtime->private_data;
+ struct at91_pcm_dma_params *params = prtd->params;
+ static int count = 0;
+
+ count++;
+
+ if (ssc_sr & params->mask->ssc_endbuf) {
+
+ printk(KERN_WARNING
+ "at91-pcm: buffer %s on %s (SSC_SR=%#x, count=%d)\n",
+ substream->stream == SNDRV_PCM_STREAM_PLAYBACK
+ ? "underrun" : "overrun",
+ params->name, ssc_sr, count);
+
+ /* re-start the PDC */
+ at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end) {
+ prtd->period_ptr = prtd->dma_buffer;
+ }
+
+ at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
+ at91_ssc_write(params->ssc_base + params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
+ }
+
+ if (ssc_sr & params->mask->ssc_endx) {
+
+ /* Load the PDC next pointer and counter registers */
+ prtd->period_ptr += prtd->period_size;
+ if (prtd->period_ptr >= prtd->dma_buffer_end) {
+ prtd->period_ptr = prtd->dma_buffer;
+ }
+ at91_ssc_write(params->ssc_base + params->pdc->xnpr,
+ prtd->period_ptr);
+ at91_ssc_write(params->ssc_base + params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+ }
+
+ snd_pcm_period_elapsed(substream);
+}
+
+static int at91_pcm_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct at91_runtime_data *prtd = runtime->private_data;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+
+ /* this may get called several times by oss emulation
+ * with different params */
+
+ snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
+ runtime->dma_bytes = params_buffer_bytes(params);
+
+ prtd->params = rtd->dai->cpu_dai->dma_data;
+ prtd->params->dma_intr_handler = at91_pcm_dma_irq;
+
+ prtd->dma_buffer = runtime->dma_addr;
+ prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
+ prtd->period_size = params_period_bytes(params);
+
+ DBG("hw_params: DMA for %s initialized (dma_bytes=%d, period_size=%d)\n",
+ prtd->params->name, runtime->dma_bytes, prtd->period_size);
+ return 0;
+}
+
+static int at91_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+ struct at91_runtime_data *prtd = substream->runtime->private_data;
+ struct at91_pcm_dma_params *params = prtd->params;
+
+ if (params != NULL) {
+ at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+ prtd->params->dma_intr_handler = NULL;
+ }
+
+ return 0;
+}
+
+static int at91_pcm_prepare(struct snd_pcm_substream *substream)
+{
+ struct at91_runtime_data *prtd = substream->runtime->private_data;
+ struct at91_pcm_dma_params *params = prtd->params;
+
+ at91_ssc_write(params->ssc_base + AT91_SSC_IDR,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+
+ at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+ return 0;
+}
+
+static int at91_pcm_trigger(struct snd_pcm_substream *substream,
+ int cmd)
+{
+ struct at91_runtime_data *prtd = substream->runtime->private_data;
+ struct at91_pcm_dma_params *params = prtd->params;
+ int ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ prtd->period_ptr = prtd->dma_buffer;
+
+ at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->period_ptr);
+ at91_ssc_write(params->ssc_base + params->pdc->xcr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ prtd->period_ptr += prtd->period_size;
+ at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->period_ptr);
+ at91_ssc_write(params->ssc_base + params->pdc->xncr,
+ prtd->period_size / params->pdc_xfer_size);
+
+ DBG("trigger: period_ptr=%lx, xpr=%lx, xcr=%ld, xnpr=%lx, xncr=%ld\n",
+ (unsigned long) prtd->period_ptr,
+ at91_ssc_read(params->ssc_base + params->pdc->xpr),
+ at91_ssc_read(params->ssc_base + params->pdc->xcr),
+ at91_ssc_read(params->ssc_base + params->pdc->xnpr),
+ at91_ssc_read(params->ssc_base + params->pdc->xncr));
+
+ at91_ssc_write(params->ssc_base + AT91_SSC_IER,
+ params->mask->ssc_endx | params->mask->ssc_endbuf);
+
+ at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR,
+ params->mask->pdc_enable);
+
+ DBG("sr=%lx imr=%lx\n",
+ at91_ssc_read(params->ssc_base + AT91_SSC_SR),
+ at91_ssc_read(params->ssc_base + AT91_SSC_IMR));
+ break;
+
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+ break;
+
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
+ break;
+
+ default:
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static snd_pcm_uframes_t at91_pcm_pointer(
+ struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct at91_runtime_data *prtd = runtime->private_data;
+ struct at91_pcm_dma_params *params = prtd->params;
+ dma_addr_t ptr;
+ snd_pcm_uframes_t x;
+
+ ptr = (dma_addr_t) at91_ssc_read(params->ssc_base + params->pdc->xpr);
+ x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
+
+ if (x == runtime->buffer_size)
+ x = 0;
+ return x;
+}
+
+static int at91_pcm_open(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct at91_runtime_data *prtd;
+ int ret = 0;
+
+ snd_soc_set_runtime_hwparams(substream, &at91_pcm_hardware);
+
+ /* ensure that buffer size is a multiple of period size */
+ ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+ if (ret < 0)
+ goto out;
+
+ prtd = kzalloc(sizeof(struct at91_runtime_data), GFP_KERNEL);
+ if (prtd == NULL) {
+ ret = -ENOMEM;
+ goto out;
+ }
+ runtime->private_data = prtd;
+
+ out:
+ return ret;
+}
+
+static int at91_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct at91_runtime_data *prtd = substream->runtime->private_data;
+
+ kfree(prtd);
+ return 0;
+}
+
+static int at91_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+
+ return dma_mmap_writecombine(substream->pcm->card->dev, vma,
+ runtime->dma_area,
+ runtime->dma_addr,
+ runtime->dma_bytes);
+}
+
+struct snd_pcm_ops at91_pcm_ops = {
+ .open = at91_pcm_open,
+ .close = at91_pcm_close,
+ .ioctl = snd_pcm_lib_ioctl,
+ .hw_params = at91_pcm_hw_params,
+ .hw_free = at91_pcm_hw_free,
+ .prepare = at91_pcm_prepare,
+ .trigger = at91_pcm_trigger,
+ .pointer = at91_pcm_pointer,
+ .mmap = at91_pcm_mmap,
+};
+
+static int at91_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
+ int stream)
+{
+ struct snd_pcm_substream *substream = pcm->streams[stream].substream;
+ struct snd_dma_buffer *buf = &substream->dma_buffer;
+ size_t size = at91_pcm_hardware.buffer_bytes_max;
+
+ buf->dev.type = SNDRV_DMA_TYPE_DEV;
+ buf->dev.dev = pcm->card->dev;
+ buf->private_data = NULL;
+ buf->area = dma_alloc_writecombine(pcm->card->dev, size,
+ &buf->addr, GFP_KERNEL);
+
+ DBG("preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
+ (void *) buf->area,
+ (void *) buf->addr,
+ size);
+
+ if (!buf->area)
+ return -ENOMEM;
+
+ buf->bytes = size;
+ return 0;
+}
+
+static u64 at91_pcm_dmamask = 0xffffffff;
+
+static int at91_pcm_new(struct snd_card *card,
+ struct snd_soc_dai *dai, struct snd_pcm *pcm)
+{
+ int ret = 0;
+
+ if (!card->dev->dma_mask)
+ card->dev->dma_mask = &at91_pcm_dmamask;
+ if (!card->dev->coherent_dma_mask)
+ card->dev->coherent_dma_mask = 0xffffffff;
+
+ if (dai->playback.channels_min) {
+ ret = at91_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_PLAYBACK);
+ if (ret)
+ goto out;
+ }
+
+ if (dai->capture.channels_min) {
+ ret = at91_pcm_preallocate_dma_buffer(pcm,
+ SNDRV_PCM_STREAM_CAPTURE);
+ if (ret)
+ goto out;
+ }
+ out:
+ return ret;
+}
+
+static void at91_pcm_free_dma_buffers(struct snd_pcm *pcm)
+{
+ struct snd_pcm_substream *substream;
+ struct snd_dma_buffer *buf;
+ int stream;
+
+ for (stream = 0; stream < 2; stream++) {
+ substream = pcm->streams[stream].substream;
+ if (!substream)
+ continue;
+
+ buf = &substream->dma_buffer;
+ if (!buf->area)
+ continue;
+
+ dma_free_writecombine(pcm->card->dev, buf->bytes,
+ buf->area, buf->addr);
+ buf->area = NULL;
+ }
+}
+
+#ifdef CONFIG_PM
+static int at91_pcm_suspend(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct at91_runtime_data *prtd;
+ struct at91_pcm_dma_params *params;
+
+ if (!runtime)
+ return 0;
+
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* disable the PDC and save the PDC registers */
+
+ at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_disable);
+
+ prtd->pdc_xpr_save = at91_ssc_read(params->ssc_base + params->pdc->xpr);
+ prtd->pdc_xcr_save = at91_ssc_read(params->ssc_base + params->pdc->xcr);
+ prtd->pdc_xnpr_save = at91_ssc_read(params->ssc_base + params->pdc->xnpr);
+ prtd->pdc_xncr_save = at91_ssc_read(params->ssc_base + params->pdc->xncr);
+
+ return 0;
+}
+
+static int at91_pcm_resume(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
+{
+ struct snd_pcm_runtime *runtime = dai->runtime;
+ struct at91_runtime_data *prtd;
+ struct at91_pcm_dma_params *params;
+
+ if (!runtime)
+ return 0;
+
+ prtd = runtime->private_data;
+ params = prtd->params;
+
+ /* restore the PDC registers and enable the PDC */
+ at91_ssc_write(params->ssc_base + params->pdc->xpr, prtd->pdc_xpr_save);
+ at91_ssc_write(params->ssc_base + params->pdc->xcr, prtd->pdc_xcr_save);
+ at91_ssc_write(params->ssc_base + params->pdc->xnpr, prtd->pdc_xnpr_save);
+ at91_ssc_write(params->ssc_base + params->pdc->xncr, prtd->pdc_xncr_save);
+
+ at91_ssc_write(params->ssc_base + ATMEL_PDC_PTCR, params->mask->pdc_enable);
+ return 0;
+}
+#else
+#define at91_pcm_suspend NULL
+#define at91_pcm_resume NULL
+#endif
+
+struct snd_soc_platform at91_soc_platform = {
+ .name = "at91-audio",
+ .pcm_ops = &at91_pcm_ops,
+ .pcm_new = at91_pcm_new,
+ .pcm_free = at91_pcm_free_dma_buffers,
+ .suspend = at91_pcm_suspend,
+ .resume = at91_pcm_resume,
+};
+
+EXPORT_SYMBOL_GPL(at91_soc_platform);
+
+MODULE_AUTHOR("Frank Mandarino <fmandarino@endrelia.com>");
+MODULE_DESCRIPTION("Atmel AT91 PCM module");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-pcm.h b/sound/soc/at91/at91-pcm.h
new file mode 100644
index 000000000000..e5aada2cb102
--- /dev/null
+++ b/sound/soc/at91/at91-pcm.h
@@ -0,0 +1,72 @@
+/*
+ * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC
+ *
+ * Author: Frank Mandarino <fmandarino@endrelia.com>
+ * Endrelia Technologies Inc.
+ * Created: Mar 3, 2006
+ *
+ * Based on pxa2xx-pcm.h by:
+ *
+ * Author: Nicolas Pitre
+ * Created: Nov 30, 2004
+ * Copyright: MontaVista Software, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _AT91_PCM_H
+#define _AT91_PCM_H
+
+#include <mach/hardware.h>
+
+struct at91_ssc_periph {
+ void __iomem *base;
+ u32 pid;
+};
+
+/*
+ * Registers and status bits that are required by the PCM driver.
+ */
+struct at91_pdc_regs {
+ unsigned int xpr; /* PDC recv/trans pointer */
+ unsigned int xcr; /* PDC recv/trans counter */
+ unsigned int xnpr; /* PDC next recv/trans pointer */
+ unsigned int xncr; /* PDC next recv/trans counter */
+ unsigned int ptcr; /* PDC transfer control */
+};
+
+struct at91_ssc_mask {
+ u32 ssc_enable; /* SSC recv/trans enable */
+ u32 ssc_disable; /* SSC recv/trans disable */
+ u32 ssc_endx; /* SSC ENDTX or ENDRX */
+ u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
+ u32 pdc_enable; /* PDC recv/trans enable */
+ u32 pdc_disable; /* PDC recv/trans disable */
+};
+
+/*
+ * This structure, shared between the PCM driver and the interface,
+ * contains all information required by the PCM driver to perform the
+ * PDC DMA operation. All fields except dma_intr_handler() are initialized
+ * by the interface. The dms_intr_handler() pointer is set by the PCM
+ * driver and called by the interface SSC interrupt handler if it is
+ * non-NULL.
+ */
+struct at91_pcm_dma_params {
+ char *name; /* stream identifier */
+ int pdc_xfer_size; /* PDC counter increment in bytes */
+ void __iomem *ssc_base; /* SSC base address */
+ struct at91_pdc_regs *pdc; /* PDC receive or transmit registers */
+ struct at91_ssc_mask *mask;/* SSC & PDC status bits */
+ struct snd_pcm_substream *substream;
+ void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
+};
+
+extern struct snd_soc_platform at91_soc_platform;
+
+#define at91_ssc_read(a) ((unsigned long) __raw_readl(a))
+#define at91_ssc_write(a,v) __raw_writel((v),(a))
+
+#endif /* _AT91_PCM_H */
diff --git a/sound/soc/at91/at91-ssc.c b/sound/soc/at91/at91-ssc.c
new file mode 100644
index 000000000000..1b61cc461261
--- /dev/null
+++ b/sound/soc/at91/at91-ssc.c
@@ -0,0 +1,791 @@
+/*
+ * at91-ssc.c -- ALSA SoC AT91 SSC Audio Layer Platform driver
+ *
+ * Author: Frank Mandarino <fmandarino@endrelia.com>
+ * Endrelia Technologies Inc.
+ *
+ * Based on pxa2xx Platform drivers by
+ * Liam Girdwood <lrg@slimlogic.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/atmel_pdc.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+#include <sound/pcm_params.h>
+#include <sound/initval.h>
+#include <sound/soc.h>
+
+#include <mach/hardware.h>
+#include <mach/at91_pmc.h>
+#include <mach/at91_ssc.h>
+
+#include "at91-pcm.h"
+#include "at91-ssc.h"
+
+#if 0
+#define DBG(x...) printk(KERN_DEBUG "at91-ssc:" x)
+#else
+#define DBG(x...)
+#endif
+
+#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
+#define NUM_SSC_DEVICES 1
+#else
+#define NUM_SSC_DEVICES 3
+#endif
+
+
+/*
+ * SSC PDC registers required by the PCM DMA engine.
+ */
+static struct at91_pdc_regs pdc_tx_reg = {
+ .xpr = ATMEL_PDC_TPR,
+ .xcr = ATMEL_PDC_TCR,
+ .xnpr = ATMEL_PDC_TNPR,
+ .xncr = ATMEL_PDC_TNCR,
+};
+
+static struct at91_pdc_regs pdc_rx_reg = {
+ .xpr = ATMEL_PDC_RPR,
+ .xcr = ATMEL_PDC_RCR,
+ .xnpr = ATMEL_PDC_RNPR,
+ .xncr = ATMEL_PDC_RNCR,
+};
+
+/*
+ * SSC & PDC status bits for transmit and receive.
+ */
+static struct at91_ssc_mask ssc_tx_mask = {
+ .ssc_enable = AT91_SSC_TXEN,
+ .ssc_disable = AT91_SSC_TXDIS,
+ .ssc_endx = AT91_SSC_ENDTX,
+ .ssc_endbuf = AT91_SSC_TXBUFE,
+ .pdc_enable = ATMEL_PDC_TXTEN,
+ .pdc_disable = ATMEL_PDC_TXTDIS,
+};
+
+static struct at91_ssc_mask ssc_rx_mask = {
+ .ssc_enable = AT91_SSC_RXEN,
+ .ssc_disable = AT91_SSC_RXDIS,
+ .ssc_endx = AT91_SSC_ENDRX,
+ .ssc_endbuf = AT91_SSC_RXBUFF,
+ .pdc_enable = ATMEL_PDC_RXTEN,
+ .pdc_disable = ATMEL_PDC_RXTDIS,
+};
+
+
+/*
+ * DMA parameters.
+ */
+static struct at91_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
+ {{
+ .name = "SSC0 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC0 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ }},
+#if NUM_SSC_DEVICES == 3
+ {{
+ .name = "SSC1 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC1 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ }},
+ {{
+ .name = "SSC2 PCM out",
+ .pdc = &pdc_tx_reg,
+ .mask = &ssc_tx_mask,
+ },
+ {
+ .name = "SSC2 PCM in",
+ .pdc = &pdc_rx_reg,
+ .mask = &ssc_rx_mask,
+ }},
+#endif
+};
+
+struct at91_ssc_state {
+ u32 ssc_cmr;
+ u32 ssc_rcmr;
+ u32 ssc_rfmr;
+ u32 ssc_tcmr;
+ u32 ssc_tfmr;
+ u32 ssc_sr;
+ u32 ssc_imr;
+};
+
+static struct at91_ssc_info {
+ char *name;
+ struct at91_ssc_periph ssc;
+ spinlock_t lock; /* lock for dir_mask */
+ unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
+ unsigned short initialized; /* 1=SSC has been initialized */
+ unsigned short daifmt;
+ unsigned short cmr_div;
+ unsigned short tcmr_period;
+ unsigned short rcmr_period;
+ struct at91_pcm_dma_params *dma_params[2];
+ struct at91_ssc_state ssc_state;
+
+} ssc_info[NUM_SSC_DEVICES] = {
+ {
+ .name = "ssc0",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
+ .dir_mask = 0,
+ .initialized = 0,
+ },
+#if NUM_SSC_DEVICES == 3
+ {
+ .name = "ssc1",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
+ .dir_mask = 0,
+ .initialized = 0,
+ },
+ {
+ .name = "ssc2",
+ .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
+ .dir_mask = 0,
+ .initialized = 0,
+ },
+#endif
+};
+
+static unsigned int at91_ssc_sysclk;
+
+/*
+ * SSC interrupt handler. Passes PDC interrupts to the DMA
+ * interrupt handler in the PCM driver.
+ */
+static irqreturn_t at91_ssc_interrupt(int irq, void *dev_id)
+{
+ struct at91_ssc_info *ssc_p = dev_id;
+ struct at91_pcm_dma_params *dma_params;
+ u32 ssc_sr;
+ int i;
+
+ ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR)
+ & at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
+
+ /*
+ * Loop through the substreams attached to this SSC. If
+ * a DMA-related interrupt occurred on that substream, call
+ * the DMA interrupt handler function, if one has been
+ * registered in the dma_params structure by the PCM driver.
+ */
+ for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
+ dma_params = ssc_p->dma_params[i];
+
+ if (dma_params != NULL && dma_params->dma_intr_handler != NULL &&
+ (ssc_sr &
+ (dma_params->mask->ssc_endx | dma_params->mask->ssc_endbuf)))
+
+ dma_params->dma_intr_handler(ssc_sr, dma_params->substream);
+ }
+
+ return IRQ_HANDLED;
+}
+
+/*
+ * Startup. Only that one substream allowed in each direction.
+ */
+static int at91_ssc_startup(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ int dir_mask;
+
+ DBG("ssc_startup: SSC_SR=0x%08lx\n",
+ at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
+ dir_mask = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0x1 : 0x2;
+
+ spin_lock_irq(&ssc_p->lock);
+ if (ssc_p->dir_mask & dir_mask) {
+ spin_unlock_irq(&ssc_p->lock);
+ return -EBUSY;
+ }
+ ssc_p->dir_mask |= dir_mask;
+ spin_unlock_irq(&ssc_p->lock);
+
+ return 0;
+}
+
+/*
+ * Shutdown. Clear DMA parameters and shutdown the SSC if there
+ * are no other substreams open.
+ */
+static void at91_ssc_shutdown(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ struct at91_pcm_dma_params *dma_params;
+ int dir, dir_mask;
+
+ dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
+ dma_params = ssc_p->dma_params[dir];
+
+ if (dma_params != NULL) {
+ at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
+ dma_params->mask->ssc_disable);
+ DBG("%s disabled SSC_SR=0x%08lx\n", (dir ? "receive" : "transmit"),
+ at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR));
+
+ dma_params->ssc_base = NULL;
+ dma_params->substream = NULL;
+ ssc_p->dma_params[dir] = NULL;
+ }
+
+ dir_mask = 1 << dir;
+
+ spin_lock_irq(&ssc_p->lock);
+ ssc_p->dir_mask &= ~dir_mask;
+ if (!ssc_p->dir_mask) {
+ /* Shutdown the SSC clock. */
+ DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
+ at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
+
+ if (ssc_p->initialized) {
+ free_irq(ssc_p->ssc.pid, ssc_p);
+ ssc_p->initialized = 0;
+ }
+
+ /* Reset the SSC */
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
+
+ /* Clear the SSC dividers */
+ ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
+ }
+ spin_unlock_irq(&ssc_p->lock);
+}
+
+/*
+ * Record the SSC system clock rate.
+ */
+static int at91_ssc_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
+ int clk_id, unsigned int freq, int dir)
+{
+ /*
+ * The only clock supplied to the SSC is the AT91 master clock,
+ * which is only used if the SSC is generating BCLK and/or
+ * LRC clocks.
+ */
+ switch (clk_id) {
+ case AT91_SYSCLK_MCK:
+ at91_ssc_sysclk = freq;
+ break;
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Record the DAI format for use in hw_params().
+ */
+static int at91_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
+ unsigned int fmt)
+{
+ struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+ ssc_p->daifmt = fmt;
+ return 0;
+}
+
+/*
+ * Record SSC clock dividers for use in hw_params().
+ */
+static int at91_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
+ int div_id, int div)
+{
+ struct at91_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
+
+ switch (div_id) {
+ case AT91SSC_CMR_DIV:
+ /*
+ * The same master clock divider is used for both
+ * transmit and receive, so if a value has already
+ * been set, it must match this value.
+ */
+ if (ssc_p->cmr_div == 0)
+ ssc_p->cmr_div = div;
+ else
+ if (div != ssc_p->cmr_div)
+ return -EBUSY;
+ break;
+
+ case AT91SSC_TCMR_PERIOD:
+ ssc_p->tcmr_period = div;
+ break;
+
+ case AT91SSC_RCMR_PERIOD:
+ ssc_p->rcmr_period = div;
+ break;
+
+ default:
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/*
+ * Configure the SSC.
+ */
+static int at91_ssc_hw_params(struct snd_pcm_substream *substream,
+ struct snd_pcm_hw_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ int id = rtd->dai->cpu_dai->id;
+ struct at91_ssc_info *ssc_p = &ssc_info[id];
+ struct at91_pcm_dma_params *dma_params;
+ int dir, channels, bits;
+ u32 tfmr, rfmr, tcmr, rcmr;
+ int start_event;
+ int ret;
+
+ /*
+ * Currently, there is only one set of dma params for
+ * each direction. If more are added, this code will
+ * have to be changed to select the proper set.
+ */
+ dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
+
+ dma_params = &ssc_dma_params[id][dir];
+ dma_params->ssc_base = ssc_p->ssc.base;
+ dma_params->substream = substream;
+
+ ssc_p->dma_params[dir] = dma_params;
+
+ /*
+ * The cpu_dai->dma_data field is only used to communicate the
+ * appropriate DMA parameters to the pcm driver hw_params()
+ * function. It should not be used for other purposes
+ * as it is common to all substreams.
+ */
+ rtd->dai->cpu_dai->dma_data = dma_params;
+
+ channels = params_channels(params);
+
+ /*
+ * Determine sample size in bits and the PDC increment.
+ */
+ switch(params_format(params)) {
+ case SNDRV_PCM_FORMAT_S8:
+ bits = 8;
+ dma_params->pdc_xfer_size = 1;
+ break;
+ case SNDRV_PCM_FORMAT_S16_LE:
+ bits = 16;
+ dma_params->pdc_xfer_size = 2;
+ break;
+ case SNDRV_PCM_FORMAT_S24_LE:
+ bits = 24;
+ dma_params->pdc_xfer_size = 4;
+ break;
+ case SNDRV_PCM_FORMAT_S32_LE:
+ bits = 32;
+ dma_params->pdc_xfer_size = 4;
+ break;
+ default:
+ printk(KERN_WARNING "at91-ssc: unsupported PCM format\n");
+ return -EINVAL;
+ }
+
+ /*
+ * The SSC only supports up to 16-bit samples in I2S format, due
+ * to the size of the Frame Mode Register FSLEN field.
+ */
+ if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
+ && bits > 16) {
+ printk(KERN_WARNING
+ "at91-ssc: sample size %d is too large for I2S\n", bits);
+ return -EINVAL;
+ }
+
+ /*
+ * Compute SSC register settings.
+ */
+ switch (ssc_p->daifmt
+ & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
+
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
+ /*
+ * I2S format, SSC provides BCLK and LRC clocks.
+ *
+ * The SSC transmit and receive clocks are generated from the
+ * MCK divider, and the BCLK signal is output on the SSC TK line.
+ */
+ rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
+ | (( 1 << 16) & AT91_SSC_STTDLY)
+ | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
+ | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
+ | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
+ | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
+
+ rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
+ | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
+ | (((bits - 1) << 16) & AT91_SSC_FSLEN)
+ | (((channels - 1) << 8) & AT91_SSC_DATNB)
+ | (( 1 << 7) & AT91_SSC_MSBF)
+ | (( 0 << 5) & AT91_SSC_LOOP)
+ | (((bits - 1) << 0) & AT91_SSC_DATALEN);
+
+ tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
+ | (( 1 << 16) & AT91_SSC_STTDLY)
+ | (( AT91_SSC_START_FALLING_RF ) & AT91_SSC_START)
+ | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
+ | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
+ | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
+
+ tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
+ | (( 0 << 23) & AT91_SSC_FSDEN)
+ | (( AT91_SSC_FSOS_NEGATIVE ) & AT91_SSC_FSOS)
+ | (((bits - 1) << 16) & AT91_SSC_FSLEN)
+ | (((channels - 1) << 8) & AT91_SSC_DATNB)
+ | (( 1 << 7) & AT91_SSC_MSBF)
+ | (( 0 << 5) & AT91_SSC_DATDEF)
+ | (((bits - 1) << 0) & AT91_SSC_DATALEN);
+ break;
+
+ case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
+ /*
+ * I2S format, CODEC supplies BCLK and LRC clocks.
+ *
+ * The SSC transmit clock is obtained from the BCLK signal on
+ * on the TK line, and the SSC receive clock is generated from the
+ * transmit clock.
+ *
+ * For single channel data, one sample is transferred on the falling
+ * edge of the LRC clock. For two channel data, one sample is
+ * transferred on both edges of the LRC clock.
+ */
+ start_event = channels == 1
+ ? AT91_SSC_START_FALLING_RF
+ : AT91_SSC_START_EDGE_RF;
+
+ rcmr = (( 0 << 24) & AT91_SSC_PERIOD)
+ | (( 1 << 16) & AT91_SSC_STTDLY)
+ | (( start_event ) & AT91_SSC_START)
+ | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
+ | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
+ | (( AT91_SSC_CKS_CLOCK ) & AT91_SSC_CKS);
+
+ rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
+ | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
+ | (( 0 << 16) & AT91_SSC_FSLEN)
+ | (( 0 << 8) & AT91_SSC_DATNB)
+ | (( 1 << 7) & AT91_SSC_MSBF)
+ | (( 0 << 5) & AT91_SSC_LOOP)
+ | (((bits - 1) << 0) & AT91_SSC_DATALEN);
+
+ tcmr = (( 0 << 24) & AT91_SSC_PERIOD)
+ | (( 1 << 16) & AT91_SSC_STTDLY)
+ | (( start_event ) & AT91_SSC_START)
+ | (( AT91_SSC_CKI_FALLING ) & AT91_SSC_CKI)
+ | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
+ | (( AT91_SSC_CKS_PIN ) & AT91_SSC_CKS);
+
+ tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
+ | (( 0 << 23) & AT91_SSC_FSDEN)
+ | (( AT91_SSC_FSOS_NONE ) & AT91_SSC_FSOS)
+ | (( 0 << 16) & AT91_SSC_FSLEN)
+ | (( 0 << 8) & AT91_SSC_DATNB)
+ | (( 1 << 7) & AT91_SSC_MSBF)
+ | (( 0 << 5) & AT91_SSC_DATDEF)
+ | (((bits - 1) << 0) & AT91_SSC_DATALEN);
+ break;
+
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
+ /*
+ * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
+ *
+ * The SSC transmit and receive clocks are generated from the
+ * MCK divider, and the BCLK signal is output on the SSC TK line.
+ */
+ rcmr = (( ssc_p->rcmr_period << 24) & AT91_SSC_PERIOD)
+ | (( 1 << 16) & AT91_SSC_STTDLY)
+ | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
+ | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
+ | (( AT91_SSC_CKO_NONE ) & AT91_SSC_CKO)
+ | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
+
+ rfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
+ | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
+ | (( 0 << 16) & AT91_SSC_FSLEN)
+ | (((channels - 1) << 8) & AT91_SSC_DATNB)
+ | (( 1 << 7) & AT91_SSC_MSBF)
+ | (( 0 << 5) & AT91_SSC_LOOP)
+ | (((bits - 1) << 0) & AT91_SSC_DATALEN);
+
+ tcmr = (( ssc_p->tcmr_period << 24) & AT91_SSC_PERIOD)
+ | (( 1 << 16) & AT91_SSC_STTDLY)
+ | (( AT91_SSC_START_RISING_RF ) & AT91_SSC_START)
+ | (( AT91_SSC_CK_RISING ) & AT91_SSC_CKI)
+ | (( AT91_SSC_CKO_CONTINUOUS ) & AT91_SSC_CKO)
+ | (( AT91_SSC_CKS_DIV ) & AT91_SSC_CKS);
+
+ tfmr = (( AT91_SSC_FSEDGE_POSITIVE ) & AT91_SSC_FSEDGE)
+ | (( 0 << 23) & AT91_SSC_FSDEN)
+ | (( AT91_SSC_FSOS_POSITIVE ) & AT91_SSC_FSOS)
+ | (( 0 << 16) & AT91_SSC_FSLEN)
+ | (((channels - 1) << 8) & AT91_SSC_DATNB)
+ | (( 1 << 7) & AT91_SSC_MSBF)
+ | (( 0 << 5) & AT91_SSC_DATDEF)
+ | (((bits - 1) << 0) & AT91_SSC_DATALEN);
+
+
+
+ break;
+
+ case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
+ default:
+ printk(KERN_WARNING "at91-ssc: unsupported DAI format 0x%x.\n",
+ ssc_p->daifmt);
+ return -EINVAL;
+ break;
+ }
+ DBG("RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n", rcmr, rfmr, tcmr, tfmr);
+
+ if (!ssc_p->initialized) {
+
+ /* Enable PMC peripheral clock for this SSC */
+ DBG("Starting pid %d clock\n", ssc_p->ssc.pid);
+ at91_sys_write(AT91_PMC_PCER, 1<<ssc_p->ssc.pid);
+
+ /* Reset the SSC and its PDC registers */
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR, AT91_SSC_SWRST);
+
+ at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RPR, 0);
+ at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RCR, 0);
+ at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNPR, 0);
+ at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_RNCR, 0);
+ at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TPR, 0);
+ at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TCR, 0);
+ at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNPR, 0);
+ at91_ssc_write(ssc_p->ssc.base + ATMEL_PDC_TNCR, 0);
+
+ if ((ret = request_irq(ssc_p->ssc.pid, at91_ssc_interrupt,
+ 0, ssc_p->name, ssc_p)) < 0) {
+ printk(KERN_WARNING "at91-ssc: request_irq failure\n");
+
+ DBG("Stopping pid %d clock\n", ssc_p->ssc.pid);
+ at91_sys_write(AT91_PMC_PCDR, 1<<ssc_p->ssc.pid);
+ return ret;
+ }
+
+ ssc_p->initialized = 1;
+ }
+
+ /* set SSC clock mode register */
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->cmr_div);
+
+ /* set receive clock mode and format */
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, rcmr);
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, rfmr);
+
+ /* set transmit clock mode and format */
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, tcmr);
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, tfmr);
+
+ DBG("hw_params: SSC initialized\n");
+ return 0;
+}
+
+
+static int at91_ssc_prepare(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct at91_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
+ struct at91_pcm_dma_params *dma_params;
+ int dir;
+
+ dir = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1;
+ dma_params = ssc_p->dma_params[dir];
+
+ at91_ssc_write(dma_params->ssc_base + AT91_SSC_CR,
+ dma_params->mask->ssc_enable);
+
+ DBG("%s enabled SSC_SR=0x%08lx\n", dir ? "receive" : "transmit",
+ at91_ssc_read(dma_params->ssc_base + AT91_SSC_SR));
+ return 0;
+}
+
+
+#ifdef CONFIG_PM
+static int at91_ssc_suspend(struct platform_device *pdev,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct at91_ssc_info *ssc_p;
+
+ if(!cpu_dai->active)
+ return 0;
+
+ ssc_p = &ssc_info[cpu_dai->id];
+
+ /* Save the status register before disabling transmit and receive. */
+ ssc_p->ssc_state.ssc_sr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_SR);
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
+ AT91_SSC_TXDIS | AT91_SSC_RXDIS);
+
+ /* Save the current interrupt mask, then disable unmasked interrupts. */
+ ssc_p->ssc_state.ssc_imr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_IMR);
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IDR, ssc_p->ssc_state.ssc_imr);
+
+ ssc_p->ssc_state.ssc_cmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_CMR);
+ ssc_p->ssc_state.ssc_rcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RCMR);
+ ssc_p->ssc_state.ssc_rfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_RFMR);
+ ssc_p->ssc_state.ssc_tcmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TCMR);
+ ssc_p->ssc_state.ssc_tfmr = at91_ssc_read(ssc_p->ssc.base + AT91_SSC_TFMR);
+
+ return 0;
+}
+
+static int at91_ssc_resume(struct platform_device *pdev,
+ struct snd_soc_dai *cpu_dai)
+{
+ struct at91_ssc_info *ssc_p;
+
+ if(!cpu_dai->active)
+ return 0;
+
+ ssc_p = &ssc_info[cpu_dai->id];
+
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TFMR, ssc_p->ssc_state.ssc_tfmr);
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_TCMR, ssc_p->ssc_state.ssc_tcmr);
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RFMR, ssc_p->ssc_state.ssc_rfmr);
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_RCMR, ssc_p->ssc_state.ssc_rcmr);
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CMR, ssc_p->ssc_state.ssc_cmr);
+
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_IER, ssc_p->ssc_state.ssc_imr);
+
+ at91_ssc_write(ssc_p->ssc.base + AT91_SSC_CR,
+ ((ssc_p->ssc_state.ssc_sr & AT91_SSC_RXENA) ? AT91_SSC_RXEN : 0) |
+ ((ssc_p->ssc_state.ssc_sr & AT91_SSC_TXENA) ? AT91_SSC_TXEN : 0));
+
+ return 0;
+}
+
+#else
+#define at91_ssc_suspend NULL
+#define at91_ssc_resume NULL
+#endif
+
+#define AT91_SSC_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
+ SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 |\
+ SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\
+ SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
+ SNDRV_PCM_RATE_96000)
+
+#define AT91_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
+ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
+
+struct snd_soc_dai at91_ssc_dai[NUM_SSC_DEVICES] = {
+ { .name = "at91-ssc0",
+ .id = 0,
+ .type = SND_SOC_DAI_PCM,
+ .suspend = at91_ssc_suspend,
+ .resume = at91_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT91_SSC_RATES,
+ .formats = AT91_SSC_FORMATS,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT91_SSC_RATES,
+ .formats = AT91_SSC_FORMATS,},
+ .ops = {
+ .startup = at91_ssc_startup,
+ .shutdown = at91_ssc_shutdown,
+ .prepare = at91_ssc_prepare,
+ .hw_params = at91_ssc_hw_params,},
+ .dai_ops = {
+ .set_sysclk = at91_ssc_set_dai_sysclk,
+ .set_fmt = at91_ssc_set_dai_fmt,
+ .set_clkdiv = at91_ssc_set_dai_clkdiv,},
+ .private_data = &ssc_info[0].ssc,
+ },
+#if NUM_SSC_DEVICES == 3
+ { .name = "at91-ssc1",
+ .id = 1,
+ .type = SND_SOC_DAI_PCM,
+ .suspend = at91_ssc_suspend,
+ .resume = at91_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT91_SSC_RATES,
+ .formats = AT91_SSC_FORMATS,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT91_SSC_RATES,
+ .formats = AT91_SSC_FORMATS,},
+ .ops = {
+ .startup = at91_ssc_startup,
+ .shutdown = at91_ssc_shutdown,
+ .prepare = at91_ssc_prepare,
+ .hw_params = at91_ssc_hw_params,},
+ .dai_ops = {
+ .set_sysclk = at91_ssc_set_dai_sysclk,
+ .set_fmt = at91_ssc_set_dai_fmt,
+ .set_clkdiv = at91_ssc_set_dai_clkdiv,},
+ .private_data = &ssc_info[1].ssc,
+ },
+ { .name = "at91-ssc2",
+ .id = 2,
+ .type = SND_SOC_DAI_PCM,
+ .suspend = at91_ssc_suspend,
+ .resume = at91_ssc_resume,
+ .playback = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT91_SSC_RATES,
+ .formats = AT91_SSC_FORMATS,},
+ .capture = {
+ .channels_min = 1,
+ .channels_max = 2,
+ .rates = AT91_SSC_RATES,
+ .formats = AT91_SSC_FORMATS,},
+ .ops = {
+ .startup = at91_ssc_startup,
+ .shutdown = at91_ssc_shutdown,
+ .prepare = at91_ssc_prepare,
+ .hw_params = at91_ssc_hw_params,},
+ .dai_ops = {
+ .set_sysclk = at91_ssc_set_dai_sysclk,
+ .set_fmt = at91_ssc_set_dai_fmt,
+ .set_clkdiv = at91_ssc_set_dai_clkdiv,},
+ .private_data = &ssc_info[2].ssc,
+ },
+#endif
+};
+
+EXPORT_SYMBOL_GPL(at91_ssc_dai);
+
+/* Module information */
+MODULE_AUTHOR("Frank Mandarino, fmandarino@endrelia.com, www.endrelia.com");
+MODULE_DESCRIPTION("AT91 SSC ASoC Interface");
+MODULE_LICENSE("GPL");
diff --git a/sound/soc/at91/at91-ssc.h b/sound/soc/at91/at91-ssc.h
new file mode 100644
index 000000000000..6b7bf382d06f
--- /dev/null
+++ b/sound/soc/at91/at91-ssc.h
@@ -0,0 +1,27 @@
+/*
+ * at91-ssc.h - ALSA SSC interface for the Atmel AT91 SoC
+ *
+ * Author: Frank Mandarino <fmandarino@endrelia.com>
+ * Endrelia Technologies Inc.
+ * Created: Jan 9, 2007
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _AT91_SSC_H
+#define _AT91_SSC_H
+
+/* SSC system clock ids */
+#define AT91_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
+
+/* SSC divider ids */
+#define AT91SSC_CMR_DIV 0 /* MCK divider for BCLK */
+#define AT91SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
+#define AT91SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
+
+extern struct snd_soc_dai at91_ssc_dai[];
+
+#endif /* _AT91_SSC_H */
+
diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig
deleted file mode 100644
index a608d7009dbd..000000000000
--- a/sound/soc/atmel/Kconfig
+++ /dev/null
@@ -1,43 +0,0 @@
-config SND_ATMEL_SOC
- tristate "SoC Audio for the Atmel System-on-Chip"
- depends on ARCH_AT91 || AVR32
- help
- Say Y or M if you want to add support for codecs attached to
- the ATMEL SSC interface. You will also need
- to select the audio interfaces to support below.
-
-config SND_ATMEL_SOC_SSC
- tristate
- depends on SND_ATMEL_SOC
- help
- Say Y or M if you want to add support for codecs the
- ATMEL SSC interface. You will also needs to select the individual
- machine drivers to support below.
-
-config SND_AT91_SOC_SAM9G20_WM8731
- tristate "SoC Audio support for WM8731-based At91sam9g20 evaluation board"
- depends on ATMEL_SSC && ARCH_AT91SAM9G20 && SND_ATMEL_SOC
- select SND_ATMEL_SOC_SSC
- select SND_SOC_WM8731
- help
- Say Y if you want to add support for SoC audio on WM8731-based
- AT91sam9g20 evaluation board.
-
-config SND_AT32_SOC_PLAYPAQ
- tristate "SoC Audio support for PlayPaq with WM8510"
- depends on SND_ATMEL_SOC && BOARD_PLAYPAQ
- select SND_ATMEL_SOC_SSC
- select SND_SOC_WM8510
- help
- Say Y or M here if you want to add support for SoC audio
- on the LRS PlayPaq.
-
-config SND_AT32_SOC_PLAYPAQ_SLAVE
- bool "Run CODEC on PlayPaq in slave mode"
- depends on SND_AT32_SOC_PLAYPAQ
- default n
- help
- Say Y if you want to run with the AT32 SSC generating the BCLK
- and FRAME signals on the PlayPaq. Unless you want to play
- with the AT32 as the SSC master, you probably want to say N here,
- as this will give you better sound quality.
diff --git a/sound/soc/atmel/Makefile b/sound/soc/atmel/Makefile
deleted file mode 100644
index f54a7cc68e66..000000000000
--- a/sound/soc/atmel/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-# AT91 Platform Support
-snd-soc-atmel-pcm-objs := atmel-pcm.o
-snd-soc-atmel_ssc_dai-objs := atmel_ssc_dai.o
-
-obj-$(CONFIG_SND_ATMEL_SOC) += snd-soc-atmel-pcm.o
-obj-$(CONFIG_SND_ATMEL_SOC_SSC) += snd-soc-atmel_ssc_dai.o
-
-# AT91 Machine Support
-snd-soc-sam9g20-wm8731-objs := sam9g20_wm8731.o
-
-# AT32 Machine Support
-snd-soc-playpaq-objs := playpaq_wm8510.o
-
-obj-$(CONFIG_SND_AT91_SOC_SAM9G20_WM8731) += snd-soc-sam9g20-wm8731.o
-obj-$(CONFIG_SND_AT32_SOC_PLAYPAQ) += snd-soc-playpaq.o
diff --git a/sound/soc/atmel/atmel-pcm.c b/sound/soc/atmel/atmel-pcm.c
deleted file mode 100644
index 027eb13f9dd0..000000000000
--- a/sound/soc/atmel/atmel-pcm.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/*
- * atmel-pcm.c -- ALSA PCM interface for the Atmel atmel SoC.
- *
- * Copyright (C) 2005 SAN People
- * Copyright (C) 2008 Atmel
- *
- * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
- *
- * Based on at91-pcm. by:
- * Frank Mandarino <fmandarino@endrelia.com>
- * Copyright 2006 Endrelia Technologies Inc.
- *
- * Based on pxa2xx-pcm.c by:
- *
- * Author: Nicolas Pitre
- * Created: Nov 30, 2004
- * Copyright: (C) 2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/atmel_pdc.h>
-#include <linux/atmel-ssc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-
-#include <mach/hardware.h>
-
-#include "atmel-pcm.h"
-
-
-/*--------------------------------------------------------------------------*\
- * Hardware definition
-\*--------------------------------------------------------------------------*/
-/* TODO: These values were taken from the AT91 platform driver, check
- * them against real values for AT32
- */
-static const struct snd_pcm_hardware atmel_pcm_hardware = {
- .info = SNDRV_PCM_INFO_MMAP |
- SNDRV_PCM_INFO_MMAP_VALID |
- SNDRV_PCM_INFO_INTERLEAVED |
- SNDRV_PCM_INFO_PAUSE,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- .period_bytes_min = 32,
- .period_bytes_max = 8192,
- .periods_min = 2,
- .periods_max = 1024,
- .buffer_bytes_max = 32 * 1024,
-};
-
-
-/*--------------------------------------------------------------------------*\
- * Data types
-\*--------------------------------------------------------------------------*/
-struct atmel_runtime_data {
- struct atmel_pcm_dma_params *params;
- dma_addr_t dma_buffer; /* physical address of dma buffer */
- dma_addr_t dma_buffer_end; /* first address beyond DMA buffer */
- size_t period_size;
-
- dma_addr_t period_ptr; /* physical address of next period */
- int periods; /* period index of period_ptr */
-
- /* PDC register save */
- u32 pdc_xpr_save;
- u32 pdc_xcr_save;
- u32 pdc_xnpr_save;
- u32 pdc_xncr_save;
-};
-
-
-/*--------------------------------------------------------------------------*\
- * Helper functions
-\*--------------------------------------------------------------------------*/
-static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
- int stream)
-{
- struct snd_pcm_substream *substream = pcm->streams[stream].substream;
- struct snd_dma_buffer *buf = &substream->dma_buffer;
- size_t size = atmel_pcm_hardware.buffer_bytes_max;
-
- buf->dev.type = SNDRV_DMA_TYPE_DEV;
- buf->dev.dev = pcm->card->dev;
- buf->private_data = NULL;
- buf->area = dma_alloc_coherent(pcm->card->dev, size,
- &buf->addr, GFP_KERNEL);
- pr_debug("atmel-pcm:"
- "preallocate_dma_buffer: area=%p, addr=%p, size=%d\n",
- (void *) buf->area,
- (void *) buf->addr,
- size);
-
- if (!buf->area)
- return -ENOMEM;
-
- buf->bytes = size;
- return 0;
-}
-/*--------------------------------------------------------------------------*\
- * ISR
-\*--------------------------------------------------------------------------*/
-static void atmel_pcm_dma_irq(u32 ssc_sr,
- struct snd_pcm_substream *substream)
-{
- struct atmel_runtime_data *prtd = substream->runtime->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
- static int count;
-
- count++;
-
- if (ssc_sr & params->mask->ssc_endbuf) {
- pr_warning("atmel-pcm: buffer %s on %s"
- " (SSC_SR=%#x, count=%d)\n",
- substream->stream == SNDRV_PCM_STREAM_PLAYBACK
- ? "underrun" : "overrun",
- params->name, ssc_sr, count);
-
- /* re-start the PDC */
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end)
- prtd->period_ptr = prtd->dma_buffer;
-
- ssc_writex(params->ssc->regs, params->pdc->xpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
- }
-
- if (ssc_sr & params->mask->ssc_endx) {
- /* Load the PDC next pointer and counter registers */
- prtd->period_ptr += prtd->period_size;
- if (prtd->period_ptr >= prtd->dma_buffer_end)
- prtd->period_ptr = prtd->dma_buffer;
-
- ssc_writex(params->ssc->regs, params->pdc->xnpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
- }
-
- snd_pcm_period_elapsed(substream);
-}
-
-
-/*--------------------------------------------------------------------------*\
- * PCM operations
-\*--------------------------------------------------------------------------*/
-static int atmel_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct atmel_runtime_data *prtd = runtime->private_data;
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
-
- /* this may get called several times by oss emulation
- * with different params */
-
- snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
- runtime->dma_bytes = params_buffer_bytes(params);
-
- prtd->params = rtd->dai->cpu_dai->dma_data;
- prtd->params->dma_intr_handler = atmel_pcm_dma_irq;
-
- prtd->dma_buffer = runtime->dma_addr;
- prtd->dma_buffer_end = runtime->dma_addr + runtime->dma_bytes;
- prtd->period_size = params_period_bytes(params);
-
- pr_debug("atmel-pcm: "
- "hw_params: DMA for %s initialized "
- "(dma_bytes=%u, period_size=%u)\n",
- prtd->params->name,
- runtime->dma_bytes,
- prtd->period_size);
- return 0;
-}
-
-static int atmel_pcm_hw_free(struct snd_pcm_substream *substream)
-{
- struct atmel_runtime_data *prtd = substream->runtime->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
-
- if (params != NULL) {
- ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
- params->mask->pdc_disable);
- prtd->params->dma_intr_handler = NULL;
- }
-
- return 0;
-}
-
-static int atmel_pcm_prepare(struct snd_pcm_substream *substream)
-{
- struct atmel_runtime_data *prtd = substream->runtime->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
-
- ssc_writex(params->ssc->regs, SSC_IDR,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- return 0;
-}
-
-static int atmel_pcm_trigger(struct snd_pcm_substream *substream,
- int cmd)
-{
- struct snd_pcm_runtime *rtd = substream->runtime;
- struct atmel_runtime_data *prtd = rtd->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
- int ret = 0;
-
- pr_debug("atmel-pcm:buffer_size = %ld,"
- "dma_area = %p, dma_bytes = %u\n",
- rtd->buffer_size, rtd->dma_area, rtd->dma_bytes);
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_START:
- prtd->period_ptr = prtd->dma_buffer;
-
- ssc_writex(params->ssc->regs, params->pdc->xpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xcr,
- prtd->period_size / params->pdc_xfer_size);
-
- prtd->period_ptr += prtd->period_size;
- ssc_writex(params->ssc->regs, params->pdc->xnpr,
- prtd->period_ptr);
- ssc_writex(params->ssc->regs, params->pdc->xncr,
- prtd->period_size / params->pdc_xfer_size);
-
- pr_debug("atmel-pcm: trigger: "
- "period_ptr=%lx, xpr=%u, "
- "xcr=%u, xnpr=%u, xncr=%u\n",
- (unsigned long)prtd->period_ptr,
- ssc_readx(params->ssc->regs, params->pdc->xpr),
- ssc_readx(params->ssc->regs, params->pdc->xcr),
- ssc_readx(params->ssc->regs, params->pdc->xnpr),
- ssc_readx(params->ssc->regs, params->pdc->xncr));
-
- ssc_writex(params->ssc->regs, SSC_IER,
- params->mask->ssc_endx | params->mask->ssc_endbuf);
- ssc_writex(params->ssc->regs, SSC_PDC_PTCR,
- params->mask->pdc_enable);
-
- pr_debug("sr=%u imr=%u\n",
- ssc_readx(params->ssc->regs, SSC_SR),
- ssc_readx(params->ssc->regs, SSC_IER));
- break; /* SNDRV_PCM_TRIGGER_START */
-
- case SNDRV_PCM_TRIGGER_STOP:
- case SNDRV_PCM_TRIGGER_SUSPEND:
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_disable);
- break;
-
- case SNDRV_PCM_TRIGGER_RESUME:
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- ssc_writex(params->ssc->regs, ATMEL_PDC_PTCR,
- params->mask->pdc_enable);
- break;
-
- default:
- ret = -EINVAL;
- }
-
- return ret;
-}
-
-static snd_pcm_uframes_t atmel_pcm_pointer(
- struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct atmel_runtime_data *prtd = runtime->private_data;
- struct atmel_pcm_dma_params *params = prtd->params;
- dma_addr_t ptr;
- snd_pcm_uframes_t x;
-
- ptr = (dma_addr_t) ssc_readx(params->ssc->regs, params->pdc->xpr);
- x = bytes_to_frames(runtime, ptr - prtd->dma_buffer);
-
- if (x == runtime->buffer_size)
- x = 0;
-
- return x;
-}
-
-static int atmel_pcm_open(struct snd_pcm_substream *substream)
-{
- struct snd_pcm_runtime *runtime = substream->runtime;
- struct atmel_runtime_data *prtd;
- int ret = 0;
-
- snd_soc_set_runtime_hwparams(substream, &atmel_pcm_hardware);
-
- /* ensure that buffer size is a multiple of period size */
- ret = snd_pcm_hw_constraint_integer(runtime,
- SNDRV_PCM_HW_PARAM_PERIODS);
- if (ret < 0)
- goto out;
-
- prtd = kzalloc(sizeof(struct atmel_runtime_data), GFP_KERNEL);
- if (prtd == NULL) {
- ret = -ENOMEM;
- goto out;
- }
- runtime->private_data = prtd;
-
- out:
- return ret;
-}
-
-static int atmel_pcm_close(struct snd_pcm_substream *substream)
-{
- struct atmel_runtime_data *prtd = substream->runtime->private_data;
-
- kfree(prtd);
- return 0;
-}
-
-static int atmel_pcm_mmap(struct snd_pcm_substream *substream,
- struct vm_area_struct *vma)
-{
- return remap_pfn_range(vma, vma->vm_start,
- substream->dma_buffer.addr >> PAGE_SHIFT,
- vma->vm_end - vma->vm_start, vma->vm_page_prot);
-}
-
-struct snd_pcm_ops atmel_pcm_ops = {
- .open = atmel_pcm_open,
- .close = atmel_pcm_close,
- .ioctl = snd_pcm_lib_ioctl,
- .hw_params = atmel_pcm_hw_params,
- .hw_free = atmel_pcm_hw_free,
- .prepare = atmel_pcm_prepare,
- .trigger = atmel_pcm_trigger,
- .pointer = atmel_pcm_pointer,
- .mmap = atmel_pcm_mmap,
-};
-
-
-/*--------------------------------------------------------------------------*\
- * ASoC platform driver
-\*--------------------------------------------------------------------------*/
-static u64 atmel_pcm_dmamask = 0xffffffff;
-
-static int atmel_pcm_new(struct snd_card *card,
- struct snd_soc_dai *dai, struct snd_pcm *pcm)
-{
- int ret = 0;
-
- if (!card->dev->dma_mask)
- card->dev->dma_mask = &atmel_pcm_dmamask;
- if (!card->dev->coherent_dma_mask)
- card->dev->coherent_dma_mask = 0xffffffff;
-
- if (dai->playback.channels_min) {
- ret = atmel_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_PLAYBACK);
- if (ret)
- goto out;
- }
-
- if (dai->capture.channels_min) {
- pr_debug("at32-pcm:"
- "Allocating PCM capture DMA buffer\n");
- ret = atmel_pcm_preallocate_dma_buffer(pcm,
- SNDRV_PCM_STREAM_CAPTURE);
- if (ret)
- goto out;
- }
- out:
- return ret;
-}
-
-static void atmel_pcm_free_dma_buffers(struct snd_pcm *pcm)
-{
- struct snd_pcm_substream *substream;
- struct snd_dma_buffer *buf;
- int stream;
-
- for (stream = 0; stream < 2; stream++) {
- substream = pcm->streams[stream].substream;
- if (!substream)
- continue;
-
- buf = &substream->dma_buffer;
- if (!buf->area)
- continue;
- dma_free_coherent(pcm->card->dev, buf->bytes,
- buf->area, buf->addr);
- buf->area = NULL;
- }
-}
-
-#ifdef CONFIG_PM
-static int atmel_pcm_suspend(struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct atmel_runtime_data *prtd;
- struct atmel_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* disable the PDC and save the PDC registers */
-
- ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_disable);
-
- prtd->pdc_xpr_save = ssc_readx(params->ssc->regs, params->pdc->xpr);
- prtd->pdc_xcr_save = ssc_readx(params->ssc->regs, params->pdc->xcr);
- prtd->pdc_xnpr_save = ssc_readx(params->ssc->regs, params->pdc->xnpr);
- prtd->pdc_xncr_save = ssc_readx(params->ssc->regs, params->pdc->xncr);
-
- return 0;
-}
-
-static int atmel_pcm_resume(struct snd_soc_dai *dai)
-{
- struct snd_pcm_runtime *runtime = dai->runtime;
- struct atmel_runtime_data *prtd;
- struct atmel_pcm_dma_params *params;
-
- if (!runtime)
- return 0;
-
- prtd = runtime->private_data;
- params = prtd->params;
-
- /* restore the PDC registers and enable the PDC */
- ssc_writex(params->ssc->regs, params->pdc->xpr, prtd->pdc_xpr_save);
- ssc_writex(params->ssc->regs, params->pdc->xcr, prtd->pdc_xcr_save);
- ssc_writex(params->ssc->regs, params->pdc->xnpr, prtd->pdc_xnpr_save);
- ssc_writex(params->ssc->regs, params->pdc->xncr, prtd->pdc_xncr_save);
-
- ssc_writel(params->ssc->regs, PDC_PTCR, params->mask->pdc_enable);
- return 0;
-}
-#else
-#define atmel_pcm_suspend NULL
-#define atmel_pcm_resume NULL
-#endif
-
-struct snd_soc_platform atmel_soc_platform = {
- .name = "atmel-audio",
- .pcm_ops = &atmel_pcm_ops,
- .pcm_new = atmel_pcm_new,
- .pcm_free = atmel_pcm_free_dma_buffers,
- .suspend = atmel_pcm_suspend,
- .resume = atmel_pcm_resume,
-};
-EXPORT_SYMBOL_GPL(atmel_soc_platform);
-
-static int __devinit atmel_pcm_modinit(void)
-{
- return snd_soc_register_platform(&atmel_soc_platform);
-}
-module_init(atmel_pcm_modinit);
-
-static void __exit atmel_pcm_modexit(void)
-{
- snd_soc_unregister_platform(&atmel_soc_platform);
-}
-module_exit(atmel_pcm_modexit);
-
-MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
-MODULE_DESCRIPTION("Atmel PCM module");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel-pcm.h b/sound/soc/atmel/atmel-pcm.h
deleted file mode 100644
index ec9b2824b663..000000000000
--- a/sound/soc/atmel/atmel-pcm.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * at91-pcm.h - ALSA PCM interface for the Atmel AT91 SoC.
- *
- * Copyright (C) 2005 SAN People
- * Copyright (C) 2008 Atmel
- *
- * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
- *
- * Based on at91-pcm. by:
- * Frank Mandarino <fmandarino@endrelia.com>
- * Copyright 2006 Endrelia Technologies Inc.
- *
- * Based on pxa2xx-pcm.c by:
- *
- * Author: Nicolas Pitre
- * Created: Nov 30, 2004
- * Copyright: (C) 2004 MontaVista Software, Inc.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _ATMEL_PCM_H
-#define _ATMEL_PCM_H
-
-#include <linux/atmel-ssc.h>
-
-/*
- * Registers and status bits that are required by the PCM driver.
- */
-struct atmel_pdc_regs {
- unsigned int xpr; /* PDC recv/trans pointer */
- unsigned int xcr; /* PDC recv/trans counter */
- unsigned int xnpr; /* PDC next recv/trans pointer */
- unsigned int xncr; /* PDC next recv/trans counter */
- unsigned int ptcr; /* PDC transfer control */
-};
-
-struct atmel_ssc_mask {
- u32 ssc_enable; /* SSC recv/trans enable */
- u32 ssc_disable; /* SSC recv/trans disable */
- u32 ssc_endx; /* SSC ENDTX or ENDRX */
- u32 ssc_endbuf; /* SSC TXBUFE or RXBUFF */
- u32 pdc_enable; /* PDC recv/trans enable */
- u32 pdc_disable; /* PDC recv/trans disable */
-};
-
-/*
- * This structure, shared between the PCM driver and the interface,
- * contains all information required by the PCM driver to perform the
- * PDC DMA operation. All fields except dma_intr_handler() are initialized
- * by the interface. The dms_intr_handler() pointer is set by the PCM
- * driver and called by the interface SSC interrupt handler if it is
- * non-NULL.
- */
-struct atmel_pcm_dma_params {
- char *name; /* stream identifier */
- int pdc_xfer_size; /* PDC counter increment in bytes */
- struct ssc_device *ssc; /* SSC device for stream */
- struct atmel_pdc_regs *pdc; /* PDC receive or transmit registers */
- struct atmel_ssc_mask *mask; /* SSC & PDC status bits */
- struct snd_pcm_substream *substream;
- void (*dma_intr_handler)(u32, struct snd_pcm_substream *);
-};
-
-extern struct snd_soc_platform atmel_soc_platform;
-
-
-/*
- * SSC register access (since ssc_writel() / ssc_readl() require literal name)
- */
-#define ssc_readx(base, reg) (__raw_readl((base) + (reg)))
-#define ssc_writex(base, reg, value) __raw_writel((value), (base) + (reg))
-
-#endif /* _ATMEL_PCM_H */
diff --git a/sound/soc/atmel/atmel_ssc_dai.c b/sound/soc/atmel/atmel_ssc_dai.c
deleted file mode 100644
index 87904b6ab8c2..000000000000
--- a/sound/soc/atmel/atmel_ssc_dai.c
+++ /dev/null
@@ -1,790 +0,0 @@
-/*
- * atmel_ssc_dai.c -- ALSA SoC ATMEL SSC Audio Layer Platform driver
- *
- * Copyright (C) 2005 SAN People
- * Copyright (C) 2008 Atmel
- *
- * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
- * ATMEL CORP.
- *
- * Based on at91-ssc.c by
- * Frank Mandarino <fmandarino@endrelia.com>
- * Based on pxa2xx Platform drivers by
- * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/interrupt.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-#include <linux/atmel_pdc.h>
-
-#include <linux/atmel-ssc.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-
-#include <mach/hardware.h>
-
-#include "atmel-pcm.h"
-#include "atmel_ssc_dai.h"
-
-
-#if defined(CONFIG_ARCH_AT91SAM9260) || defined(CONFIG_ARCH_AT91SAM9G20)
-#define NUM_SSC_DEVICES 1
-#else
-#define NUM_SSC_DEVICES 3
-#endif
-
-/*
- * SSC PDC registers required by the PCM DMA engine.
- */
-static struct atmel_pdc_regs pdc_tx_reg = {
- .xpr = ATMEL_PDC_TPR,
- .xcr = ATMEL_PDC_TCR,
- .xnpr = ATMEL_PDC_TNPR,
- .xncr = ATMEL_PDC_TNCR,
-};
-
-static struct atmel_pdc_regs pdc_rx_reg = {
- .xpr = ATMEL_PDC_RPR,
- .xcr = ATMEL_PDC_RCR,
- .xnpr = ATMEL_PDC_RNPR,
- .xncr = ATMEL_PDC_RNCR,
-};
-
-/*
- * SSC & PDC status bits for transmit and receive.
- */
-static struct atmel_ssc_mask ssc_tx_mask = {
- .ssc_enable = SSC_BIT(CR_TXEN),
- .ssc_disable = SSC_BIT(CR_TXDIS),
- .ssc_endx = SSC_BIT(SR_ENDTX),
- .ssc_endbuf = SSC_BIT(SR_TXBUFE),
- .pdc_enable = ATMEL_PDC_TXTEN,
- .pdc_disable = ATMEL_PDC_TXTDIS,
-};
-
-static struct atmel_ssc_mask ssc_rx_mask = {
- .ssc_enable = SSC_BIT(CR_RXEN),
- .ssc_disable = SSC_BIT(CR_RXDIS),
- .ssc_endx = SSC_BIT(SR_ENDRX),
- .ssc_endbuf = SSC_BIT(SR_RXBUFF),
- .pdc_enable = ATMEL_PDC_RXTEN,
- .pdc_disable = ATMEL_PDC_RXTDIS,
-};
-
-
-/*
- * DMA parameters.
- */
-static struct atmel_pcm_dma_params ssc_dma_params[NUM_SSC_DEVICES][2] = {
- {{
- .name = "SSC0 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC0 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- } },
-#if NUM_SSC_DEVICES == 3
- {{
- .name = "SSC1 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC1 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- } },
- {{
- .name = "SSC2 PCM out",
- .pdc = &pdc_tx_reg,
- .mask = &ssc_tx_mask,
- },
- {
- .name = "SSC2 PCM in",
- .pdc = &pdc_rx_reg,
- .mask = &ssc_rx_mask,
- } },
-#endif
-};
-
-
-static struct atmel_ssc_info ssc_info[NUM_SSC_DEVICES] = {
- {
- .name = "ssc0",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[0].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
-#if NUM_SSC_DEVICES == 3
- {
- .name = "ssc1",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[1].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
- {
- .name = "ssc2",
- .lock = __SPIN_LOCK_UNLOCKED(ssc_info[2].lock),
- .dir_mask = SSC_DIR_MASK_UNUSED,
- .initialized = 0,
- },
-#endif
-};
-
-
-/*
- * SSC interrupt handler. Passes PDC interrupts to the DMA
- * interrupt handler in the PCM driver.
- */
-static irqreturn_t atmel_ssc_interrupt(int irq, void *dev_id)
-{
- struct atmel_ssc_info *ssc_p = dev_id;
- struct atmel_pcm_dma_params *dma_params;
- u32 ssc_sr;
- u32 ssc_substream_mask;
- int i;
-
- ssc_sr = (unsigned long)ssc_readl(ssc_p->ssc->regs, SR)
- & (unsigned long)ssc_readl(ssc_p->ssc->regs, IMR);
-
- /*
- * Loop through the substreams attached to this SSC. If
- * a DMA-related interrupt occurred on that substream, call
- * the DMA interrupt handler function, if one has been
- * registered in the dma_params structure by the PCM driver.
- */
- for (i = 0; i < ARRAY_SIZE(ssc_p->dma_params); i++) {
- dma_params = ssc_p->dma_params[i];
-
- if ((dma_params != NULL) &&
- (dma_params->dma_intr_handler != NULL)) {
- ssc_substream_mask = (dma_params->mask->ssc_endx |
- dma_params->mask->ssc_endbuf);
- if (ssc_sr & ssc_substream_mask) {
- dma_params->dma_intr_handler(ssc_sr,
- dma_params->
- substream);
- }
- }
- }
-
- return IRQ_HANDLED;
-}
-
-
-/*-------------------------------------------------------------------------*\
- * DAI functions
-\*-------------------------------------------------------------------------*/
-/*
- * Startup. Only that one substream allowed in each direction.
- */
-static int atmel_ssc_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
- struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- int dir_mask;
-
- pr_debug("atmel_ssc_startup: SSC_SR=0x%u\n",
- ssc_readl(ssc_p->ssc->regs, SR));
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- dir_mask = SSC_DIR_MASK_PLAYBACK;
- else
- dir_mask = SSC_DIR_MASK_CAPTURE;
-
- spin_lock_irq(&ssc_p->lock);
- if (ssc_p->dir_mask & dir_mask) {
- spin_unlock_irq(&ssc_p->lock);
- return -EBUSY;
- }
- ssc_p->dir_mask |= dir_mask;
- spin_unlock_irq(&ssc_p->lock);
-
- return 0;
-}
-
-/*
- * Shutdown. Clear DMA parameters and shutdown the SSC if there
- * are no other substreams open.
- */
-static void atmel_ssc_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
- struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct atmel_pcm_dma_params *dma_params;
- int dir, dir_mask;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- dir = 0;
- else
- dir = 1;
-
- dma_params = ssc_p->dma_params[dir];
-
- if (dma_params != NULL) {
- ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_disable);
- pr_debug("atmel_ssc_shutdown: %s disabled SSC_SR=0x%08x\n",
- (dir ? "receive" : "transmit"),
- ssc_readl(ssc_p->ssc->regs, SR));
-
- dma_params->ssc = NULL;
- dma_params->substream = NULL;
- ssc_p->dma_params[dir] = NULL;
- }
-
- dir_mask = 1 << dir;
-
- spin_lock_irq(&ssc_p->lock);
- ssc_p->dir_mask &= ~dir_mask;
- if (!ssc_p->dir_mask) {
- if (ssc_p->initialized) {
- /* Shutdown the SSC clock. */
- pr_debug("atmel_ssc_dau: Stopping clock\n");
- clk_disable(ssc_p->ssc->clk);
-
- free_irq(ssc_p->ssc->irq, ssc_p);
- ssc_p->initialized = 0;
- }
-
- /* Reset the SSC */
- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
- /* Clear the SSC dividers */
- ssc_p->cmr_div = ssc_p->tcmr_period = ssc_p->rcmr_period = 0;
- }
- spin_unlock_irq(&ssc_p->lock);
-}
-
-
-/*
- * Record the DAI format for use in hw_params().
- */
-static int atmel_ssc_set_dai_fmt(struct snd_soc_dai *cpu_dai,
- unsigned int fmt)
-{
- struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- ssc_p->daifmt = fmt;
- return 0;
-}
-
-/*
- * Record SSC clock dividers for use in hw_params().
- */
-static int atmel_ssc_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
- int div_id, int div)
-{
- struct atmel_ssc_info *ssc_p = &ssc_info[cpu_dai->id];
-
- switch (div_id) {
- case ATMEL_SSC_CMR_DIV:
- /*
- * The same master clock divider is used for both
- * transmit and receive, so if a value has already
- * been set, it must match this value.
- */
- if (ssc_p->cmr_div == 0)
- ssc_p->cmr_div = div;
- else
- if (div != ssc_p->cmr_div)
- return -EBUSY;
- break;
-
- case ATMEL_SSC_TCMR_PERIOD:
- ssc_p->tcmr_period = div;
- break;
-
- case ATMEL_SSC_RCMR_PERIOD:
- ssc_p->rcmr_period = div;
- break;
-
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Configure the SSC.
- */
-static int atmel_ssc_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
- int id = rtd->dai->cpu_dai->id;
- struct atmel_ssc_info *ssc_p = &ssc_info[id];
- struct atmel_pcm_dma_params *dma_params;
- int dir, channels, bits;
- u32 tfmr, rfmr, tcmr, rcmr;
- int start_event;
- int ret;
-
- /*
- * Currently, there is only one set of dma params for
- * each direction. If more are added, this code will
- * have to be changed to select the proper set.
- */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- dir = 0;
- else
- dir = 1;
-
- dma_params = &ssc_dma_params[id][dir];
- dma_params->ssc = ssc_p->ssc;
- dma_params->substream = substream;
-
- ssc_p->dma_params[dir] = dma_params;
-
- /*
- * The cpu_dai->dma_data field is only used to communicate the
- * appropriate DMA parameters to the pcm driver hw_params()
- * function. It should not be used for other purposes
- * as it is common to all substreams.
- */
- rtd->dai->cpu_dai->dma_data = dma_params;
-
- channels = params_channels(params);
-
- /*
- * Determine sample size in bits and the PDC increment.
- */
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S8:
- bits = 8;
- dma_params->pdc_xfer_size = 1;
- break;
- case SNDRV_PCM_FORMAT_S16_LE:
- bits = 16;
- dma_params->pdc_xfer_size = 2;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- bits = 24;
- dma_params->pdc_xfer_size = 4;
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- bits = 32;
- dma_params->pdc_xfer_size = 4;
- break;
- default:
- printk(KERN_WARNING "atmel_ssc_dai: unsupported PCM format");
- return -EINVAL;
- }
-
- /*
- * The SSC only supports up to 16-bit samples in I2S format, due
- * to the size of the Frame Mode Register FSLEN field.
- */
- if ((ssc_p->daifmt & SND_SOC_DAIFMT_FORMAT_MASK) == SND_SOC_DAIFMT_I2S
- && bits > 16) {
- printk(KERN_WARNING
- "atmel_ssc_dai: sample size %d"
- "is too large for I2S\n", bits);
- return -EINVAL;
- }
-
- /*
- * Compute SSC register settings.
- */
- switch (ssc_p->daifmt
- & (SND_SOC_DAIFMT_FORMAT_MASK | SND_SOC_DAIFMT_MASTER_MASK)) {
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * I2S format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated
- * from the MCK divider, and the BCLK signal
- * is output on the SSC TK line.
- */
- rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
- | SSC_BF(RCMR_STTDLY, START_DELAY)
- | SSC_BF(RCMR_START, SSC_START_FALLING_RF)
- | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
- | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
- | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
-
- rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
- | SSC_BF(RFMR_FSOS, SSC_FSOS_NEGATIVE)
- | SSC_BF(RFMR_FSLEN, (bits - 1))
- | SSC_BF(RFMR_DATNB, (channels - 1))
- | SSC_BIT(RFMR_MSBF)
- | SSC_BF(RFMR_LOOP, 0)
- | SSC_BF(RFMR_DATLEN, (bits - 1));
-
- tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
- | SSC_BF(TCMR_STTDLY, START_DELAY)
- | SSC_BF(TCMR_START, SSC_START_FALLING_RF)
- | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
- | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
- | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
-
- tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
- | SSC_BF(TFMR_FSDEN, 0)
- | SSC_BF(TFMR_FSOS, SSC_FSOS_NEGATIVE)
- | SSC_BF(TFMR_FSLEN, (bits - 1))
- | SSC_BF(TFMR_DATNB, (channels - 1))
- | SSC_BIT(TFMR_MSBF)
- | SSC_BF(TFMR_DATDEF, 0)
- | SSC_BF(TFMR_DATLEN, (bits - 1));
- break;
-
- case SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_CBM_CFM:
- /*
- * I2S format, CODEC supplies BCLK and LRC clocks.
- *
- * The SSC transmit clock is obtained from the BCLK signal on
- * on the TK line, and the SSC receive clock is
- * generated from the transmit clock.
- *
- * For single channel data, one sample is transferred
- * on the falling edge of the LRC clock.
- * For two channel data, one sample is
- * transferred on both edges of the LRC clock.
- */
- start_event = ((channels == 1)
- ? SSC_START_FALLING_RF
- : SSC_START_EDGE_RF);
-
- rcmr = SSC_BF(RCMR_PERIOD, 0)
- | SSC_BF(RCMR_STTDLY, START_DELAY)
- | SSC_BF(RCMR_START, start_event)
- | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
- | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
- | SSC_BF(RCMR_CKS, SSC_CKS_CLOCK);
-
- rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
- | SSC_BF(RFMR_FSOS, SSC_FSOS_NONE)
- | SSC_BF(RFMR_FSLEN, 0)
- | SSC_BF(RFMR_DATNB, 0)
- | SSC_BIT(RFMR_MSBF)
- | SSC_BF(RFMR_LOOP, 0)
- | SSC_BF(RFMR_DATLEN, (bits - 1));
-
- tcmr = SSC_BF(TCMR_PERIOD, 0)
- | SSC_BF(TCMR_STTDLY, START_DELAY)
- | SSC_BF(TCMR_START, start_event)
- | SSC_BF(TCMR_CKI, SSC_CKI_FALLING)
- | SSC_BF(TCMR_CKO, SSC_CKO_NONE)
- | SSC_BF(TCMR_CKS, SSC_CKS_PIN);
-
- tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
- | SSC_BF(TFMR_FSDEN, 0)
- | SSC_BF(TFMR_FSOS, SSC_FSOS_NONE)
- | SSC_BF(TFMR_FSLEN, 0)
- | SSC_BF(TFMR_DATNB, 0)
- | SSC_BIT(TFMR_MSBF)
- | SSC_BF(TFMR_DATDEF, 0)
- | SSC_BF(TFMR_DATLEN, (bits - 1));
- break;
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBS_CFS:
- /*
- * DSP/PCM Mode A format, SSC provides BCLK and LRC clocks.
- *
- * The SSC transmit and receive clocks are generated from the
- * MCK divider, and the BCLK signal is output
- * on the SSC TK line.
- */
- rcmr = SSC_BF(RCMR_PERIOD, ssc_p->rcmr_period)
- | SSC_BF(RCMR_STTDLY, 1)
- | SSC_BF(RCMR_START, SSC_START_RISING_RF)
- | SSC_BF(RCMR_CKI, SSC_CKI_RISING)
- | SSC_BF(RCMR_CKO, SSC_CKO_NONE)
- | SSC_BF(RCMR_CKS, SSC_CKS_DIV);
-
- rfmr = SSC_BF(RFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
- | SSC_BF(RFMR_FSOS, SSC_FSOS_POSITIVE)
- | SSC_BF(RFMR_FSLEN, 0)
- | SSC_BF(RFMR_DATNB, (channels - 1))
- | SSC_BIT(RFMR_MSBF)
- | SSC_BF(RFMR_LOOP, 0)
- | SSC_BF(RFMR_DATLEN, (bits - 1));
-
- tcmr = SSC_BF(TCMR_PERIOD, ssc_p->tcmr_period)
- | SSC_BF(TCMR_STTDLY, 1)
- | SSC_BF(TCMR_START, SSC_START_RISING_RF)
- | SSC_BF(TCMR_CKI, SSC_CKI_RISING)
- | SSC_BF(TCMR_CKO, SSC_CKO_CONTINUOUS)
- | SSC_BF(TCMR_CKS, SSC_CKS_DIV);
-
- tfmr = SSC_BF(TFMR_FSEDGE, SSC_FSEDGE_POSITIVE)
- | SSC_BF(TFMR_FSDEN, 0)
- | SSC_BF(TFMR_FSOS, SSC_FSOS_POSITIVE)
- | SSC_BF(TFMR_FSLEN, 0)
- | SSC_BF(TFMR_DATNB, (channels - 1))
- | SSC_BIT(TFMR_MSBF)
- | SSC_BF(TFMR_DATDEF, 0)
- | SSC_BF(TFMR_DATLEN, (bits - 1));
- break;
-
- case SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_CBM_CFM:
- default:
- printk(KERN_WARNING "atmel_ssc_dai: unsupported DAI format 0x%x\n",
- ssc_p->daifmt);
- return -EINVAL;
- break;
- }
- pr_debug("atmel_ssc_hw_params: "
- "RCMR=%08x RFMR=%08x TCMR=%08x TFMR=%08x\n",
- rcmr, rfmr, tcmr, tfmr);
-
- if (!ssc_p->initialized) {
-
- /* Enable PMC peripheral clock for this SSC */
- pr_debug("atmel_ssc_dai: Starting clock\n");
- clk_enable(ssc_p->ssc->clk);
-
- /* Reset the SSC and its PDC registers */
- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_SWRST));
-
- ssc_writel(ssc_p->ssc->regs, PDC_RPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_RCR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_RNPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_RNCR, 0);
-
- ssc_writel(ssc_p->ssc->regs, PDC_TPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_TCR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_TNPR, 0);
- ssc_writel(ssc_p->ssc->regs, PDC_TNCR, 0);
-
- ret = request_irq(ssc_p->ssc->irq, atmel_ssc_interrupt, 0,
- ssc_p->name, ssc_p);
- if (ret < 0) {
- printk(KERN_WARNING
- "atmel_ssc_dai: request_irq failure\n");
- pr_debug("Atmel_ssc_dai: Stoping clock\n");
- clk_disable(ssc_p->ssc->clk);
- return ret;
- }
-
- ssc_p->initialized = 1;
- }
-
- /* set SSC clock mode register */
- ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->cmr_div);
-
- /* set receive clock mode and format */
- ssc_writel(ssc_p->ssc->regs, RCMR, rcmr);
- ssc_writel(ssc_p->ssc->regs, RFMR, rfmr);
-
- /* set transmit clock mode and format */
- ssc_writel(ssc_p->ssc->regs, TCMR, tcmr);
- ssc_writel(ssc_p->ssc->regs, TFMR, tfmr);
-
- pr_debug("atmel_ssc_dai,hw_params: SSC initialized\n");
- return 0;
-}
-
-
-static int atmel_ssc_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
- struct atmel_ssc_info *ssc_p = &ssc_info[rtd->dai->cpu_dai->id];
- struct atmel_pcm_dma_params *dma_params;
- int dir;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- dir = 0;
- else
- dir = 1;
-
- dma_params = ssc_p->dma_params[dir];
-
- ssc_writel(ssc_p->ssc->regs, CR, dma_params->mask->ssc_enable);
-
- pr_debug("%s enabled SSC_SR=0x%08x\n",
- dir ? "receive" : "transmit",
- ssc_readl(ssc_p->ssc->regs, SR));
- return 0;
-}
-
-
-#ifdef CONFIG_PM
-static int atmel_ssc_suspend(struct snd_soc_dai *cpu_dai)
-{
- struct atmel_ssc_info *ssc_p;
-
- if (!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- /* Save the status register before disabling transmit and receive */
- ssc_p->ssc_state.ssc_sr = ssc_readl(ssc_p->ssc->regs, SR);
- ssc_writel(ssc_p->ssc->regs, CR, SSC_BIT(CR_TXDIS) | SSC_BIT(CR_RXDIS));
-
- /* Save the current interrupt mask, then disable unmasked interrupts */
- ssc_p->ssc_state.ssc_imr = ssc_readl(ssc_p->ssc->regs, IMR);
- ssc_writel(ssc_p->ssc->regs, IDR, ssc_p->ssc_state.ssc_imr);
-
- ssc_p->ssc_state.ssc_cmr = ssc_readl(ssc_p->ssc->regs, CMR);
- ssc_p->ssc_state.ssc_rcmr = ssc_readl(ssc_p->ssc->regs, RCMR);
- ssc_p->ssc_state.ssc_rfmr = ssc_readl(ssc_p->ssc->regs, RFMR);
- ssc_p->ssc_state.ssc_tcmr = ssc_readl(ssc_p->ssc->regs, TCMR);
- ssc_p->ssc_state.ssc_tfmr = ssc_readl(ssc_p->ssc->regs, TFMR);
-
- return 0;
-}
-
-
-
-static int atmel_ssc_resume(struct snd_soc_dai *cpu_dai)
-{
- struct atmel_ssc_info *ssc_p;
- u32 cr;
-
- if (!cpu_dai->active)
- return 0;
-
- ssc_p = &ssc_info[cpu_dai->id];
-
- /* restore SSC register settings */
- ssc_writel(ssc_p->ssc->regs, TFMR, ssc_p->ssc_state.ssc_tfmr);
- ssc_writel(ssc_p->ssc->regs, TCMR, ssc_p->ssc_state.ssc_tcmr);
- ssc_writel(ssc_p->ssc->regs, RFMR, ssc_p->ssc_state.ssc_rfmr);
- ssc_writel(ssc_p->ssc->regs, RCMR, ssc_p->ssc_state.ssc_rcmr);
- ssc_writel(ssc_p->ssc->regs, CMR, ssc_p->ssc_state.ssc_cmr);
-
- /* re-enable interrupts */
- ssc_writel(ssc_p->ssc->regs, IER, ssc_p->ssc_state.ssc_imr);
-
- /* Re-enable recieve and transmit as appropriate */
- cr = 0;
- cr |=
- (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_RXEN)) ? SSC_BIT(CR_RXEN) : 0;
- cr |=
- (ssc_p->ssc_state.ssc_sr & SSC_BIT(SR_TXEN)) ? SSC_BIT(CR_TXEN) : 0;
- ssc_writel(ssc_p->ssc->regs, CR, cr);
-
- return 0;
-}
-#else /* CONFIG_PM */
-# define atmel_ssc_suspend NULL
-# define atmel_ssc_resume NULL
-#endif /* CONFIG_PM */
-
-
-#define ATMEL_SSC_RATES (SNDRV_PCM_RATE_8000_96000)
-
-#define ATMEL_SSC_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-
-struct snd_soc_dai atmel_ssc_dai[NUM_SSC_DEVICES] = {
- { .name = "atmel-ssc0",
- .id = 0,
- .suspend = atmel_ssc_suspend,
- .resume = atmel_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .ops = {
- .startup = atmel_ssc_startup,
- .shutdown = atmel_ssc_shutdown,
- .prepare = atmel_ssc_prepare,
- .hw_params = atmel_ssc_hw_params,
- .set_fmt = atmel_ssc_set_dai_fmt,
- .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[0],
- },
-#if NUM_SSC_DEVICES == 3
- { .name = "atmel-ssc1",
- .id = 1,
- .suspend = atmel_ssc_suspend,
- .resume = atmel_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .ops = {
- .startup = atmel_ssc_startup,
- .shutdown = atmel_ssc_shutdown,
- .prepare = atmel_ssc_prepare,
- .hw_params = atmel_ssc_hw_params,
- .set_fmt = atmel_ssc_set_dai_fmt,
- .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[1],
- },
- { .name = "atmel-ssc2",
- .id = 2,
- .suspend = atmel_ssc_suspend,
- .resume = atmel_ssc_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = ATMEL_SSC_RATES,
- .formats = ATMEL_SSC_FORMATS,},
- .ops = {
- .startup = atmel_ssc_startup,
- .shutdown = atmel_ssc_shutdown,
- .prepare = atmel_ssc_prepare,
- .hw_params = atmel_ssc_hw_params,
- .set_fmt = atmel_ssc_set_dai_fmt,
- .set_clkdiv = atmel_ssc_set_dai_clkdiv,},
- .private_data = &ssc_info[2],
- },
-#endif
-};
-EXPORT_SYMBOL_GPL(atmel_ssc_dai);
-
-static int __devinit atmel_ssc_modinit(void)
-{
- return snd_soc_register_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
-}
-module_init(atmel_ssc_modinit);
-
-static void __exit atmel_ssc_modexit(void)
-{
- snd_soc_unregister_dais(atmel_ssc_dai, ARRAY_SIZE(atmel_ssc_dai));
-}
-module_exit(atmel_ssc_modexit);
-
-/* Module information */
-MODULE_AUTHOR("Sedji Gaouaou, sedji.gaouaou@atmel.com, www.atmel.com");
-MODULE_DESCRIPTION("ATMEL SSC ASoC Interface");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/atmel/atmel_ssc_dai.h b/sound/soc/atmel/atmel_ssc_dai.h
deleted file mode 100644
index a828746e8a2f..000000000000
--- a/sound/soc/atmel/atmel_ssc_dai.h
+++ /dev/null
@@ -1,121 +0,0 @@
-/*
- * atmel_ssc_dai.h - ALSA SSC interface for the Atmel SoC
- *
- * Copyright (C) 2005 SAN People
- * Copyright (C) 2008 Atmel
- *
- * Author: Sedji Gaouaou <sedji.gaouaou@atmel.com>
- * ATMEL CORP.
- *
- * Based on at91-ssc.c by
- * Frank Mandarino <fmandarino@endrelia.com>
- * Based on pxa2xx Platform drivers by
- * Liam Girdwood <liam.girdwood@wolfsonmicro.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#ifndef _ATMEL_SSC_DAI_H
-#define _ATMEL_SSC_DAI_H
-
-#include <linux/types.h>
-#include <linux/atmel-ssc.h>
-
-#include "atmel-pcm.h"
-
-/* SSC system clock ids */
-#define ATMEL_SYSCLK_MCK 0 /* SSC uses AT91 MCK as system clock */
-
-/* SSC divider ids */
-#define ATMEL_SSC_CMR_DIV 0 /* MCK divider for BCLK */
-#define ATMEL_SSC_TCMR_PERIOD 1 /* BCLK divider for transmit FS */
-#define ATMEL_SSC_RCMR_PERIOD 2 /* BCLK divider for receive FS */
-/*
- * SSC direction masks
- */
-#define SSC_DIR_MASK_UNUSED 0
-#define SSC_DIR_MASK_PLAYBACK 1
-#define SSC_DIR_MASK_CAPTURE 2
-
-/*
- * SSC register values that Atmel left out of <linux/atmel-ssc.h>. These
- * are expected to be used with SSC_BF
- */
-/* START bit field values */
-#define SSC_START_CONTINUOUS 0
-#define SSC_START_TX_RX 1
-#define SSC_START_LOW_RF 2
-#define SSC_START_HIGH_RF 3
-#define SSC_START_FALLING_RF 4
-#define SSC_START_RISING_RF 5
-#define SSC_START_LEVEL_RF 6
-#define SSC_START_EDGE_RF 7
-#define SSS_START_COMPARE_0 8
-
-/* CKI bit field values */
-#define SSC_CKI_FALLING 0
-#define SSC_CKI_RISING 1
-
-/* CKO bit field values */
-#define SSC_CKO_NONE 0
-#define SSC_CKO_CONTINUOUS 1
-#define SSC_CKO_TRANSFER 2
-
-/* CKS bit field values */
-#define SSC_CKS_DIV 0
-#define SSC_CKS_CLOCK 1
-#define SSC_CKS_PIN 2
-
-/* FSEDGE bit field values */
-#define SSC_FSEDGE_POSITIVE 0
-#define SSC_FSEDGE_NEGATIVE 1
-
-/* FSOS bit field values */
-#define SSC_FSOS_NONE 0
-#define SSC_FSOS_NEGATIVE 1
-#define SSC_FSOS_POSITIVE 2
-#define SSC_FSOS_LOW 3
-#define SSC_FSOS_HIGH 4
-#define SSC_FSOS_TOGGLE 5
-
-#define START_DELAY 1
-
-struct atmel_ssc_state {
- u32 ssc_cmr;
- u32 ssc_rcmr;
- u32 ssc_rfmr;
- u32 ssc_tcmr;
- u32 ssc_tfmr;
- u32 ssc_sr;
- u32 ssc_imr;
-};
-
-
-struct atmel_ssc_info {
- char *name;
- struct ssc_device *ssc;
- spinlock_t lock; /* lock for dir_mask */
- unsigned short dir_mask; /* 0=unused, 1=playback, 2=capture */
- unsigned short initialized; /* true if SSC has been initialized */
- unsigned short daifmt;
- unsigned short cmr_div;
- unsigned short tcmr_period;
- unsigned short rcmr_period;
- struct atmel_pcm_dma_params *dma_params[2];
- struct atmel_ssc_state ssc_state;
-};
-extern struct snd_soc_dai atmel_ssc_dai[];
-
-#endif /* _AT91_SSC_DAI_H */
diff --git a/sound/soc/atmel/sam9g20_wm8731.c b/sound/soc/atmel/sam9g20_wm8731.c
deleted file mode 100644
index 1fb59a9d3719..000000000000
--- a/sound/soc/atmel/sam9g20_wm8731.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/*
- * sam9g20_wm8731 -- SoC audio for AT91SAM9G20-based
- * ATMEL AT91SAM9G20ek board.
- *
- * Copyright (C) 2005 SAN People
- * Copyright (C) 2008 Atmel
- *
- * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
- *
- * Based on ati_b1_wm8731.c by:
- * Frank Mandarino <fmandarino@endrelia.com>
- * Copyright 2006 Endrelia Technologies Inc.
- * Based on corgi.c by:
- * Copyright 2005 Wolfson Microelectronics PLC.
- * Copyright 2005 Openedhand Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-
-#include <linux/atmel-ssc.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-
-#include "../codecs/wm8731.h"
-#include "atmel-pcm.h"
-#include "atmel_ssc_dai.h"
-
-
-static int at91sam9g20ek_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- int ret;
-
- /* codec system clock is supplied by PCK0, set to 12MHz */
- ret = snd_soc_dai_set_sysclk(codec_dai, WM8731_SYSCLK,
- 12000000, SND_SOC_CLOCK_IN);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static void at91sam9g20ek_shutdown(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = snd_pcm_substream_chip(substream);
-
- dev_dbg(rtd->socdev->dev, "shutdown");
-}
-
-static int at91sam9g20ek_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- struct atmel_ssc_info *ssc_p = cpu_dai->private_data;
- struct ssc_device *ssc = ssc_p->ssc;
- int ret;
-
- unsigned int rate;
- int cmr_div, period;
-
- if (ssc == NULL) {
- printk(KERN_INFO "at91sam9g20ek_hw_params: ssc is NULL!\n");
- return -EINVAL;
- }
-
- /* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- /*
- * The SSC clock dividers depend on the sample rate. The CMR.DIV
- * field divides the system master clock MCK to drive the SSC TK
- * signal which provides the codec BCLK. The TCMR.PERIOD and
- * RCMR.PERIOD fields further divide the BCLK signal to drive
- * the SSC TF and RF signals which provide the codec DACLRC and
- * ADCLRC clocks.
- *
- * The dividers were determined through trial and error, where a
- * CMR.DIV value is chosen such that the resulting BCLK value is
- * divisible, or almost divisible, by (2 * sample rate), and then
- * the TCMR.PERIOD or RCMR.PERIOD is BCLK / (2 * sample rate) - 1.
- */
- rate = params_rate(params);
-
- switch (rate) {
- case 8000:
- cmr_div = 55; /* BCLK = 133MHz/(2*55) = 1.209MHz */
- period = 74; /* LRC = BCLK/(2*(74+1)) ~= 8060,6Hz */
- break;
- case 11025:
- cmr_div = 67; /* BCLK = 133MHz/(2*60) = 1.108MHz */
- period = 45; /* LRC = BCLK/(2*(49+1)) = 11083,3Hz */
- break;
- case 16000:
- cmr_div = 63; /* BCLK = 133MHz/(2*63) = 1.055MHz */
- period = 32; /* LRC = BCLK/(2*(32+1)) = 15993,2Hz */
- break;
- case 22050:
- cmr_div = 52; /* BCLK = 133MHz/(2*52) = 1.278MHz */
- period = 28; /* LRC = BCLK/(2*(28+1)) = 22049Hz */
- break;
- case 32000:
- cmr_div = 66; /* BCLK = 133MHz/(2*66) = 1.007MHz */
- period = 15; /* LRC = BCLK/(2*(15+1)) = 31486,742Hz */
- break;
- case 44100:
- cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
- period = 25; /* LRC = BCLK/(2*(25+1)) = 44098Hz */
- break;
- case 48000:
- cmr_div = 33; /* BCLK = 133MHz/(2*33) = 2.015MHz */
- period = 20; /* LRC = BCLK/(2*(20+1)) = 47979,79Hz */
- break;
- case 88200:
- cmr_div = 29; /* BCLK = 133MHz/(2*29) = 2.293MHz */
- period = 12; /* LRC = BCLK/(2*(12+1)) = 88196Hz */
- break;
- case 96000:
- cmr_div = 23; /* BCLK = 133MHz/(2*23) = 2.891MHz */
- period = 14; /* LRC = BCLK/(2*(14+1)) = 96376Hz */
- break;
- default:
- printk(KERN_WARNING "unsupported rate %d"
- " on at91sam9g20ek board\n", rate);
- return -EINVAL;
- }
-
- /* set the MCK divider for BCLK */
- ret = snd_soc_dai_set_clkdiv(cpu_dai, ATMEL_SSC_CMR_DIV, cmr_div);
- if (ret < 0)
- return ret;
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* set the BCLK divider for DACLRC */
- ret = snd_soc_dai_set_clkdiv(cpu_dai,
- ATMEL_SSC_TCMR_PERIOD, period);
- } else {
- /* set the BCLK divider for ADCLRC */
- ret = snd_soc_dai_set_clkdiv(cpu_dai,
- ATMEL_SSC_RCMR_PERIOD, period);
- }
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct snd_soc_ops at91sam9g20ek_ops = {
- .startup = at91sam9g20ek_startup,
- .hw_params = at91sam9g20ek_hw_params,
- .shutdown = at91sam9g20ek_shutdown,
-};
-
-
-static const struct snd_soc_dapm_widget at91sam9g20ek_dapm_widgets[] = {
- SND_SOC_DAPM_MIC("Int Mic", NULL),
- SND_SOC_DAPM_SPK("Ext Spk", NULL),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
-
- /* speaker connected to LHPOUT */
- {"Ext Spk", NULL, "LHPOUT"},
-
- /* mic is connected to Mic Jack, with WM8731 Mic Bias */
- {"MICIN", NULL, "Mic Bias"},
- {"Mic Bias", NULL, "Int Mic"},
-};
-
-/*
- * Logic for a wm8731 as connected on a at91sam9g20ek board.
- */
-static int at91sam9g20ek_wm8731_init(struct snd_soc_codec *codec)
-{
- printk(KERN_DEBUG
- "at91sam9g20ek_wm8731 "
- ": at91sam9g20ek_wm8731_init() called\n");
-
- /* Add specific widgets */
- snd_soc_dapm_new_controls(codec, at91sam9g20ek_dapm_widgets,
- ARRAY_SIZE(at91sam9g20ek_dapm_widgets));
- /* Set up specific audio path interconnects */
- snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
-
- /* not connected */
- snd_soc_dapm_disable_pin(codec, "RLINEIN");
- snd_soc_dapm_disable_pin(codec, "LLINEIN");
-
- /* always connected */
- snd_soc_dapm_enable_pin(codec, "Int Mic");
- snd_soc_dapm_enable_pin(codec, "Ext Spk");
-
- snd_soc_dapm_sync(codec);
-
- return 0;
-}
-
-static struct snd_soc_dai_link at91sam9g20ek_dai = {
- .name = "WM8731",
- .stream_name = "WM8731 PCM",
- .cpu_dai = &atmel_ssc_dai[0],
- .codec_dai = &wm8731_dai,
- .init = at91sam9g20ek_wm8731_init,
- .ops = &at91sam9g20ek_ops,
-};
-
-static struct snd_soc_card snd_soc_at91sam9g20ek = {
- .name = "WM8731",
- .platform = &atmel_soc_platform,
- .dai_link = &at91sam9g20ek_dai,
- .num_links = 1,
-};
-
-static struct wm8731_setup_data at91sam9g20ek_wm8731_setup = {
- .i2c_bus = 0,
- .i2c_address = 0x1b,
-};
-
-static struct snd_soc_device at91sam9g20ek_snd_devdata = {
- .card = &snd_soc_at91sam9g20ek,
- .codec_dev = &soc_codec_dev_wm8731,
- .codec_data = &at91sam9g20ek_wm8731_setup,
-};
-
-static struct platform_device *at91sam9g20ek_snd_device;
-
-static int __init at91sam9g20ek_init(void)
-{
- struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
- struct ssc_device *ssc = NULL;
- int ret;
-
- /*
- * Request SSC device
- */
- ssc = ssc_request(0);
- if (IS_ERR(ssc)) {
- ret = PTR_ERR(ssc);
- ssc = NULL;
- goto err_ssc;
- }
- ssc_p->ssc = ssc;
-
- at91sam9g20ek_snd_device = platform_device_alloc("soc-audio", -1);
- if (!at91sam9g20ek_snd_device) {
- printk(KERN_DEBUG
- "platform device allocation failed\n");
- ret = -ENOMEM;
- }
-
- platform_set_drvdata(at91sam9g20ek_snd_device,
- &at91sam9g20ek_snd_devdata);
- at91sam9g20ek_snd_devdata.dev = &at91sam9g20ek_snd_device->dev;
-
- ret = platform_device_add(at91sam9g20ek_snd_device);
- if (ret) {
- printk(KERN_DEBUG
- "platform device allocation failed\n");
- platform_device_put(at91sam9g20ek_snd_device);
- }
-
- return ret;
-
-err_ssc:
- return ret;
-}
-
-static void __exit at91sam9g20ek_exit(void)
-{
- struct atmel_ssc_info *ssc_p = at91sam9g20ek_dai.cpu_dai->private_data;
- struct ssc_device *ssc;
-
- if (ssc_p != NULL) {
- ssc = ssc_p->ssc;
- if (ssc != NULL)
- ssc_free(ssc);
- ssc_p->ssc = NULL;
- }
-
- platform_device_unregister(at91sam9g20ek_snd_device);
- at91sam9g20ek_snd_device = NULL;
-}
-
-module_init(at91sam9g20ek_init);
-module_exit(at91sam9g20ek_exit);
-
-/* Module information */
-MODULE_AUTHOR("Sedji Gaouaou <sedji.gaouaou@atmel.com>");
-MODULE_DESCRIPTION("ALSA SoC AT91SAM9G20EK_WM8731");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/au1x/dbdma2.c b/sound/soc/au1x/dbdma2.c
index 74c823d60f91..1466d9328800 100644
--- a/sound/soc/au1x/dbdma2.c
+++ b/sound/soc/au1x/dbdma2.c
@@ -406,12 +406,11 @@ static int __init au1xpsc_audio_dbdma_init(void)
{
au1xpsc_audio_pcmdma[PCM_TX] = NULL;
au1xpsc_audio_pcmdma[PCM_RX] = NULL;
- return snd_soc_register_platform(&au1xpsc_soc_platform);
+ return 0;
}
static void __exit au1xpsc_audio_dbdma_exit(void)
{
- snd_soc_unregister_platform(&au1xpsc_soc_platform);
}
module_init(au1xpsc_audio_dbdma_init);
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c
index f0e30aec7f23..57facbad6825 100644
--- a/sound/soc/au1x/psc-ac97.c
+++ b/sound/soc/au1x/psc-ac97.c
@@ -160,8 +160,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
EXPORT_SYMBOL_GPL(soc_ac97_ops);
static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
/* FIXME */
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
@@ -211,7 +210,7 @@ static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream,
}
static int au1xpsc_ac97_trigger(struct snd_pcm_substream *substream,
- int cmd, struct snd_soc_dai *dai)
+ int cmd)
{
/* FIXME */
struct au1xpsc_audio_data *pscdata = au1xpsc_ac97_workdata;
@@ -314,7 +313,8 @@ static void au1xpsc_ac97_remove(struct platform_device *pdev,
au1xpsc_ac97_workdata = NULL;
}
-static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai)
+static int au1xpsc_ac97_suspend(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
{
/* save interesting registers and disable PSC */
au1xpsc_ac97_workdata->pm[0] =
@@ -328,7 +328,8 @@ static int au1xpsc_ac97_suspend(struct snd_soc_dai *dai)
return 0;
}
-static int au1xpsc_ac97_resume(struct snd_soc_dai *dai)
+static int au1xpsc_ac97_resume(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
{
/* restore PSC clock config */
au_writel(au1xpsc_ac97_workdata->pm[0] | PSC_SEL_PS_AC97MODE,
@@ -344,7 +345,7 @@ static int au1xpsc_ac97_resume(struct snd_soc_dai *dai)
struct snd_soc_dai au1xpsc_ac97_dai = {
.name = "au1xpsc_ac97",
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97,
.probe = au1xpsc_ac97_probe,
.remove = au1xpsc_ac97_remove,
.suspend = au1xpsc_ac97_suspend,
@@ -371,12 +372,11 @@ EXPORT_SYMBOL_GPL(au1xpsc_ac97_dai);
static int __init au1xpsc_ac97_init(void)
{
au1xpsc_ac97_workdata = NULL;
- return snd_soc_register_dai(&au1xpsc_ac97_dai);
+ return 0;
}
static void __exit au1xpsc_ac97_exit(void)
{
- snd_soc_unregister_dai(&au1xpsc_ac97_dai);
}
module_init(au1xpsc_ac97_init);
diff --git a/sound/soc/au1x/psc-i2s.c b/sound/soc/au1x/psc-i2s.c
index f916de4400ed..9384702c7ebd 100644
--- a/sound/soc/au1x/psc-i2s.c
+++ b/sound/soc/au1x/psc-i2s.c
@@ -116,8 +116,7 @@ out:
}
static int au1xpsc_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
@@ -241,8 +240,7 @@ static int au1xpsc_i2s_stop(struct au1xpsc_audio_data *pscdata, int stype)
return 0;
}
-static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int au1xpsc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct au1xpsc_audio_data *pscdata = au1xpsc_i2s_workdata;
int ret, stype = SUBSTREAM_TYPE(substream);
@@ -339,7 +337,8 @@ static void au1xpsc_i2s_remove(struct platform_device *pdev,
au1xpsc_i2s_workdata = NULL;
}
-static int au1xpsc_i2s_suspend(struct snd_soc_dai *cpu_dai)
+static int au1xpsc_i2s_suspend(struct platform_device *pdev,
+ struct snd_soc_dai *cpu_dai)
{
/* save interesting register and disable PSC */
au1xpsc_i2s_workdata->pm[0] =
@@ -353,7 +352,8 @@ static int au1xpsc_i2s_suspend(struct snd_soc_dai *cpu_dai)
return 0;
}
-static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai)
+static int au1xpsc_i2s_resume(struct platform_device *pdev,
+ struct snd_soc_dai *cpu_dai)
{
/* select I2S mode and PSC clock */
au_writel(PSC_CTRL_DISABLE, PSC_CTRL(au1xpsc_i2s_workdata));
@@ -369,6 +369,7 @@ static int au1xpsc_i2s_resume(struct snd_soc_dai *cpu_dai)
struct snd_soc_dai au1xpsc_i2s_dai = {
.name = "au1xpsc_i2s",
+ .type = SND_SOC_DAI_I2S,
.probe = au1xpsc_i2s_probe,
.remove = au1xpsc_i2s_remove,
.suspend = au1xpsc_i2s_suspend,
@@ -388,6 +389,8 @@ struct snd_soc_dai au1xpsc_i2s_dai = {
.ops = {
.trigger = au1xpsc_i2s_trigger,
.hw_params = au1xpsc_i2s_hw_params,
+ },
+ .dai_ops = {
.set_fmt = au1xpsc_i2s_set_fmt,
},
};
@@ -396,12 +399,11 @@ EXPORT_SYMBOL(au1xpsc_i2s_dai);
static int __init au1xpsc_i2s_init(void)
{
au1xpsc_i2s_workdata = NULL;
- return snd_soc_register_dai(&au1xpsc_i2s_dai);
+ return 0;
}
static void __exit au1xpsc_i2s_exit(void)
{
- snd_soc_unregister_dai(&au1xpsc_i2s_dai);
}
module_init(au1xpsc_i2s_init);
diff --git a/sound/soc/au1x/sample-ac97.c b/sound/soc/au1x/sample-ac97.c
index 27683eb7905e..f75ae7f62c3d 100644
--- a/sound/soc/au1x/sample-ac97.c
+++ b/sound/soc/au1x/sample-ac97.c
@@ -42,14 +42,14 @@ static struct snd_soc_dai_link au1xpsc_sample_ac97_dai = {
.ops = NULL,
};
-static struct snd_soc_card au1xpsc_sample_ac97_machine = {
+static struct snd_soc_machine au1xpsc_sample_ac97_machine = {
.name = "Au1xxx PSC AC97 Audio",
.dai_link = &au1xpsc_sample_ac97_dai,
.num_links = 1,
};
static struct snd_soc_device au1xpsc_sample_ac97_devdata = {
- .card = &au1xpsc_sample_ac97_machine,
+ .machine = &au1xpsc_sample_ac97_machine,
.platform = &au1xpsc_soc_platform, /* see dbdma2.c */
.codec_dev = &soc_codec_dev_ac97,
};
diff --git a/sound/soc/blackfin/Kconfig b/sound/soc/blackfin/Kconfig
index 0a2f8f9eff53..dc006206f622 100644
--- a/sound/soc/blackfin/Kconfig
+++ b/sound/soc/blackfin/Kconfig
@@ -1,6 +1,6 @@
config SND_BF5XX_I2S
tristate "SoC I2S Audio for the ADI BF5xx chip"
- depends on BLACKFIN
+ depends on BLACKFIN && SND_SOC
help
Say Y or M if you want to add support for codecs attached to
the Blackfin SPORT (synchronous serial ports) interface in I2S
@@ -13,6 +13,7 @@ config SND_BF5XX_SOC_SSM2602
select SND_BF5XX_SOC_I2S
select SND_SOC_SSM2602
select I2C
+ select I2C_BLACKFIN_TWI
help
Say Y if you want to add support for SoC audio on BF527-EZKIT.
@@ -34,7 +35,7 @@ config SND_BFIN_AD73311_SE
config SND_BF5XX_AC97
tristate "SoC AC97 Audio for the ADI BF5xx chip"
- depends on BLACKFIN
+ depends on BLACKFIN && SND_SOC
help
Say Y or M if you want to add support for codecs attached to
the Blackfin SPORT (synchronous serial ports) interface in slot 16
@@ -46,7 +47,7 @@ config SND_BF5XX_AC97
properly with this driver. This driver is known to work with the
Analog Devices line of AC97 codecs.
-config SND_BF5XX_MMAP_SUPPORT
+config SND_MMAP_SUPPORT
bool "Enable MMAP Support"
depends on SND_BF5XX_AC97
default y
@@ -54,17 +55,9 @@ config SND_BF5XX_MMAP_SUPPORT
Say y if you want AC97 driver to support mmap mode.
We introduce an intermediate buffer to simulate mmap.
-config SND_BF5XX_MULTICHAN_SUPPORT
- bool "Enable Multichannel Support"
- depends on SND_BF5XX_AC97
- default n
- help
- Say y if you want AC97 driver to support up to 5.1 channel audio.
- this mode will consume much more memory for DMA.
-
config SND_BF5XX_SOC_SPORT
tristate
-
+
config SND_BF5XX_SOC_I2S
tristate
select SND_BF5XX_SOC_SPORT
@@ -87,7 +80,7 @@ config SND_BF5XX_SPORT_NUM
int "Set a SPORT for Sound chip"
depends on (SND_BF5XX_I2S || SND_BF5XX_AC97)
range 0 3 if BF54x
- range 0 1 if !BF54x
+ range 0 1 if (BF53x || BF561)
default 0
help
Set the correct SPORT for sound chip.
@@ -97,13 +90,12 @@ config SND_BF5XX_HAVE_COLD_RESET
depends on SND_BF5XX_AC97
default y if BFIN548_EZKIT
default n if !BFIN548_EZKIT
-
+
config SND_BF5XX_RESET_GPIO_NUM
int "Set a GPIO for cold reset"
depends on SND_BF5XX_HAVE_COLD_RESET
range 0 159
default 19 if BFIN548_EZKIT
default 5 if BFIN537_STAMP
- default 0
help
Set the correct GPIO for RESET the sound chip.
diff --git a/sound/soc/blackfin/bf5xx-ac97-pcm.c b/sound/soc/blackfin/bf5xx-ac97-pcm.c
index 5b27e0d9d0ec..25e50d2ea1ec 100644
--- a/sound/soc/blackfin/bf5xx-ac97-pcm.c
+++ b/sound/soc/blackfin/bf5xx-ac97-pcm.c
@@ -43,34 +43,24 @@
#include "bf5xx-ac97.h"
#include "bf5xx-sport.h"
-static unsigned int ac97_chan_mask[] = {
- SP_FL, /* Mono */
- SP_STEREO, /* Stereo */
- SP_2DOT1, /* 2.1*/
- SP_QUAD,/*Quadraquic*/
- SP_FL | SP_FR | SP_FC | SP_SL | SP_SR,/*5 channels */
- SP_5DOT1, /* 5.1 */
-};
-
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#if defined(CONFIG_SND_MMAP_SUPPORT)
static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
snd_pcm_uframes_t count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct sport_device *sport = runtime->private_data;
- unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- bf5xx_pcm_to_ac97((struct ac97_frame *)sport->tx_dma_buf +
- sport->tx_pos, (__u16 *)runtime->dma_area + sport->tx_pos *
- runtime->channels, count, chan_mask);
+ bf5xx_pcm_to_ac97(
+ (struct ac97_frame *)sport->tx_dma_buf + sport->tx_pos,
+ (__u32 *)runtime->dma_area + sport->tx_pos, count);
sport->tx_pos += runtime->period_size;
if (sport->tx_pos >= runtime->buffer_size)
sport->tx_pos %= runtime->buffer_size;
sport->tx_delay_pos = sport->tx_pos;
} else {
- bf5xx_ac97_to_pcm((struct ac97_frame *)sport->rx_dma_buf +
- sport->rx_pos, (__u16 *)runtime->dma_area + sport->rx_pos *
- runtime->channels, count);
+ bf5xx_ac97_to_pcm(
+ (struct ac97_frame *)sport->rx_dma_buf + sport->rx_pos,
+ (__u32 *)runtime->dma_area + sport->rx_pos, count);
sport->rx_pos += runtime->period_size;
if (sport->rx_pos >= runtime->buffer_size)
sport->rx_pos %= runtime->buffer_size;
@@ -81,7 +71,7 @@ static void bf5xx_mmap_copy(struct snd_pcm_substream *substream,
static void bf5xx_dma_irq(void *data)
{
struct snd_pcm_substream *pcm = data;
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#if defined(CONFIG_SND_MMAP_SUPPORT)
struct snd_pcm_runtime *runtime = pcm->runtime;
struct sport_device *sport = runtime->private_data;
bf5xx_mmap_copy(pcm, runtime->period_size);
@@ -100,14 +90,17 @@ static void bf5xx_dma_irq(void *data)
* The total rx/tx buffer is for ac97 frame to hold all pcm data
* is 0x20000 * sizeof(struct ac97_frame) / 4.
*/
+#ifdef CONFIG_SND_MMAP_SUPPORT
static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
.info = SNDRV_PCM_INFO_INTERLEAVED |
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
SNDRV_PCM_INFO_MMAP |
SNDRV_PCM_INFO_MMAP_VALID |
-#endif
SNDRV_PCM_INFO_BLOCK_TRANSFER,
-
+#else
+static const struct snd_pcm_hardware bf5xx_pcm_hardware = {
+ .info = SNDRV_PCM_INFO_INTERLEAVED |
+ SNDRV_PCM_INFO_BLOCK_TRANSFER,
+#endif
.formats = SNDRV_PCM_FMTBIT_S16_LE,
.period_bytes_min = 32,
.period_bytes_max = 0x10000,
@@ -130,20 +123,10 @@ static int bf5xx_pcm_hw_params(struct snd_pcm_substream *substream,
static int bf5xx_pcm_hw_free(struct snd_pcm_substream *substream)
{
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
struct snd_pcm_runtime *runtime = substream->runtime;
- struct sport_device *sport = runtime->private_data;
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- sport->once = 0;
- if (runtime->dma_area)
- memset(runtime->dma_area, 0, runtime->buffer_size);
- memset(sport->tx_dma_buf, 0, runtime->buffer_size *
- sizeof(struct ac97_frame));
- } else
- memset(sport->rx_dma_buf, 0, runtime->buffer_size *
- sizeof(struct ac97_frame));
-#endif
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ memset(runtime->dma_area, 0, runtime->buffer_size);
snd_pcm_lib_free_pages(substream);
return 0;
}
@@ -156,7 +139,7 @@ static int bf5xx_pcm_prepare(struct snd_pcm_substream *substream)
/* An intermediate buffer is introduced for implementing mmap for
* SPORT working in TMD mode(include AC97).
*/
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#if defined(CONFIG_SND_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
sport_set_tx_callback(sport, bf5xx_dma_irq, substream);
sport_config_tx_dma(sport, sport->tx_dma_buf, runtime->periods,
@@ -190,24 +173,24 @@ static int bf5xx_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
bf5xx_mmap_copy(substream, runtime->period_size);
+ snd_pcm_period_elapsed(substream);
sport->tx_delay_pos = 0;
-#endif
sport_tx_start(sport);
- } else
+ }
+ else
sport_rx_start(sport);
break;
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#if defined(CONFIG_SND_MMAP_SUPPORT)
sport->tx_pos = 0;
#endif
sport_tx_stop(sport);
} else {
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#if defined(CONFIG_SND_MMAP_SUPPORT)
sport->rx_pos = 0;
#endif
sport_rx_stop(sport);
@@ -225,7 +208,7 @@ static snd_pcm_uframes_t bf5xx_pcm_pointer(struct snd_pcm_substream *substream)
struct sport_device *sport = runtime->private_data;
unsigned int curr;
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#if defined(CONFIG_SND_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
curr = sport->tx_delay_pos;
else
@@ -266,7 +249,22 @@ static int bf5xx_pcm_open(struct snd_pcm_substream *substream)
return ret;
}
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+static int bf5xx_pcm_close(struct snd_pcm_substream *substream)
+{
+ struct snd_pcm_runtime *runtime = substream->runtime;
+ struct sport_device *sport = runtime->private_data;
+
+ pr_debug("%s enter\n", __func__);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
+ sport->once = 0;
+ memset(sport->tx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
+ } else
+ memset(sport->rx_dma_buf, 0, runtime->buffer_size * sizeof(struct ac97_frame));
+
+ return 0;
+}
+
+#ifdef CONFIG_SND_MMAP_SUPPORT
static int bf5xx_pcm_mmap(struct snd_pcm_substream *substream,
struct vm_area_struct *vma)
{
@@ -283,29 +281,32 @@ static int bf5xx_pcm_copy(struct snd_pcm_substream *substream, int channel,
void __user *buf, snd_pcm_uframes_t count)
{
struct snd_pcm_runtime *runtime = substream->runtime;
- unsigned int chan_mask = ac97_chan_mask[runtime->channels - 1];
+
pr_debug("%s copy pos:0x%lx count:0x%lx\n",
substream->stream ? "Capture" : "Playback", pos, count);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- bf5xx_pcm_to_ac97((struct ac97_frame *)runtime->dma_area + pos,
- (__u16 *)buf, count, chan_mask);
+ bf5xx_pcm_to_ac97(
+ (struct ac97_frame *)runtime->dma_area + pos,
+ buf, count);
else
- bf5xx_ac97_to_pcm((struct ac97_frame *)runtime->dma_area + pos,
- (__u16 *)buf, count);
+ bf5xx_ac97_to_pcm(
+ (struct ac97_frame *)runtime->dma_area + pos,
+ buf, count);
return 0;
}
#endif
struct snd_pcm_ops bf5xx_pcm_ac97_ops = {
.open = bf5xx_pcm_open,
+ .close = bf5xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
.hw_params = bf5xx_pcm_hw_params,
.hw_free = bf5xx_pcm_hw_free,
.prepare = bf5xx_pcm_prepare,
.trigger = bf5xx_pcm_trigger,
.pointer = bf5xx_pcm_pointer,
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#ifdef CONFIG_SND_MMAP_SUPPORT
.mmap = bf5xx_pcm_mmap,
#else
.copy = bf5xx_pcm_copy,
@@ -343,7 +344,7 @@ static int bf5xx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
* Need to allocate local buffer when enable
* MMAP for SPORT working in TMD mode (include AC97).
*/
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#if defined(CONFIG_SND_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (!sport_handle->tx_dma_buf) {
sport_handle->tx_dma_buf = dma_alloc_coherent(NULL, \
@@ -380,7 +381,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
struct snd_pcm_substream *substream;
struct snd_dma_buffer *buf;
int stream;
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#if defined(CONFIG_SND_MMAP_SUPPORT)
size_t size = bf5xx_pcm_hardware.buffer_bytes_max *
sizeof(struct ac97_frame) / 4;
#endif
@@ -394,7 +395,7 @@ static void bf5xx_pcm_free_dma_buffers(struct snd_pcm *pcm)
continue;
dma_free_coherent(NULL, buf->bytes, buf->area, 0);
buf->area = NULL;
-#if defined(CONFIG_SND_BF5XX_MMAP_SUPPORT)
+#if defined(CONFIG_SND_MMAP_SUPPORT)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (sport_handle->tx_dma_buf)
dma_free_coherent(NULL, size, \
@@ -451,18 +452,6 @@ struct snd_soc_platform bf5xx_ac97_soc_platform = {
};
EXPORT_SYMBOL_GPL(bf5xx_ac97_soc_platform);
-static int __devinit bfin_ac97_init(void)
-{
- return snd_soc_register_platform(&bf5xx_ac97_soc_platform);
-}
-module_init(bfin_ac97_init);
-
-static void __exit bfin_ac97_exit(void)
-{
- snd_soc_unregister_platform(&bf5xx_ac97_soc_platform);
-}
-module_exit(bfin_ac97_exit);
-
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin AC97 PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c
index ad3efeeb6d44..5e5aafb6485f 100644
--- a/sound/soc/blackfin/bf5xx-ac97.c
+++ b/sound/soc/blackfin/bf5xx-ac97.c
@@ -54,103 +54,71 @@
static int *cmd_count;
static int sport_num = CONFIG_SND_BF5XX_SPORT_NUM;
-static u16 sport_req[][7] = {
- PIN_REQ_SPORT_0,
-#ifdef PIN_REQ_SPORT_1
- PIN_REQ_SPORT_1,
-#endif
-#ifdef PIN_REQ_SPORT_2
- PIN_REQ_SPORT_2,
-#endif
-#ifdef PIN_REQ_SPORT_3
- PIN_REQ_SPORT_3,
-#endif
- };
-
+#if defined(CONFIG_BF54x)
static struct sport_param sport_params[4] = {
{
.dma_rx_chan = CH_SPORT0_RX,
.dma_tx_chan = CH_SPORT0_TX,
- .err_irq = IRQ_SPORT0_ERROR,
+ .err_irq = IRQ_SPORT0_ERR,
.regs = (struct sport_register *)SPORT0_TCR1,
},
-#ifdef PIN_REQ_SPORT_1
{
.dma_rx_chan = CH_SPORT1_RX,
.dma_tx_chan = CH_SPORT1_TX,
- .err_irq = IRQ_SPORT1_ERROR,
+ .err_irq = IRQ_SPORT1_ERR,
.regs = (struct sport_register *)SPORT1_TCR1,
},
-#endif
-#ifdef PIN_REQ_SPORT_2
{
.dma_rx_chan = CH_SPORT2_RX,
.dma_tx_chan = CH_SPORT2_TX,
- .err_irq = IRQ_SPORT2_ERROR,
+ .err_irq = IRQ_SPORT2_ERR,
.regs = (struct sport_register *)SPORT2_TCR1,
},
-#endif
-#ifdef PIN_REQ_SPORT_3
{
.dma_rx_chan = CH_SPORT3_RX,
.dma_tx_chan = CH_SPORT3_TX,
- .err_irq = IRQ_SPORT3_ERROR,
+ .err_irq = IRQ_SPORT3_ERR,
.regs = (struct sport_register *)SPORT3_TCR1,
}
-#endif
};
+#else
+static struct sport_param sport_params[2] = {
+ {
+ .dma_rx_chan = CH_SPORT0_RX,
+ .dma_tx_chan = CH_SPORT0_TX,
+ .err_irq = IRQ_SPORT0_ERROR,
+ .regs = (struct sport_register *)SPORT0_TCR1,
+ },
+ {
+ .dma_rx_chan = CH_SPORT1_RX,
+ .dma_tx_chan = CH_SPORT1_TX,
+ .err_irq = IRQ_SPORT1_ERROR,
+ .regs = (struct sport_register *)SPORT1_TCR1,
+ }
+};
+#endif
-void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src,
- size_t count, unsigned int chan_mask)
+void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \
+ size_t count)
{
while (count--) {
- dst->ac97_tag = TAG_VALID;
- if (chan_mask & SP_FL) {
- dst->ac97_pcm_r = *src++;
- dst->ac97_tag |= TAG_PCM_RIGHT;
- }
- if (chan_mask & SP_FR) {
- dst->ac97_pcm_l = *src++;
- dst->ac97_tag |= TAG_PCM_LEFT;
-
- }
-#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
- if (chan_mask & SP_SR) {
- dst->ac97_sl = *src++;
- dst->ac97_tag |= TAG_PCM_SL;
- }
- if (chan_mask & SP_SL) {
- dst->ac97_sr = *src++;
- dst->ac97_tag |= TAG_PCM_SR;
- }
- if (chan_mask & SP_LFE) {
- dst->ac97_lfe = *src++;
- dst->ac97_tag |= TAG_PCM_LFE;
- }
- if (chan_mask & SP_FC) {
- dst->ac97_center = *src++;
- dst->ac97_tag |= TAG_PCM_CENTER;
- }
-#endif
- dst++;
+ dst->ac97_tag = TAG_VALID | TAG_PCM;
+ (dst++)->ac97_pcm = *src++;
}
}
EXPORT_SYMBOL(bf5xx_pcm_to_ac97);
-void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst,
+void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \
size_t count)
{
- while (count--) {
- *(dst++) = src->ac97_pcm_l;
- *(dst++) = src->ac97_pcm_r;
- src++;
- }
+ while (count--)
+ *(dst++) = (src++)->ac97_pcm;
}
EXPORT_SYMBOL(bf5xx_ac97_to_pcm);
static unsigned int sport_tx_curr_frag(struct sport_device *sport)
{
- return sport->tx_curr_frag = sport_curr_offset_tx(sport) /
+ return sport->tx_curr_frag = sport_curr_offset_tx(sport) / \
sport->tx_fragsize;
}
@@ -162,7 +130,7 @@ static void enqueue_cmd(struct snd_ac97 *ac97, __u16 addr, __u16 data)
sport_incfrag(sport, &nextfrag, 1);
- nextwrite = (struct ac97_frame *)(sport->tx_buf +
+ nextwrite = (struct ac97_frame *)(sport->tx_buf + \
nextfrag * sport->tx_fragsize);
pr_debug("sport->tx_buf:%p, nextfrag:0x%x nextwrite:%p, cmd_count:%d\n",
sport->tx_buf, nextfrag, nextwrite, cmd_count[nextfrag]);
@@ -269,7 +237,8 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
EXPORT_SYMBOL_GPL(soc_ac97_ops);
#ifdef CONFIG_PM
-static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
+static int bf5xx_ac97_suspend(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
{
struct sport_device *sport =
(struct sport_device *)dai->private_data;
@@ -284,7 +253,8 @@ static int bf5xx_ac97_suspend(struct snd_soc_dai *dai)
return 0;
}
-static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
+static int bf5xx_ac97_resume(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
{
int ret;
struct sport_device *sport =
@@ -327,15 +297,20 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai)
static int bf5xx_ac97_probe(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
- int ret = 0;
+ int ret;
+#if defined(CONFIG_BF54x)
+ u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1,
+ PIN_REQ_SPORT_2, PIN_REQ_SPORT_3};
+#else
+ u16 sport_req[][7] = {PIN_REQ_SPORT_0, PIN_REQ_SPORT_1};
+#endif
cmd_count = (int *)get_zeroed_page(GFP_KERNEL);
if (cmd_count == NULL)
return -ENOMEM;
if (peripheral_request_list(&sport_req[sport_num][0], "soc-audio")) {
pr_err("Requesting Peripherals failed\n");
- ret = -EFAULT;
- goto peripheral_err;
+ return -EFAULT;
}
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
@@ -343,54 +318,54 @@ static int bf5xx_ac97_probe(struct platform_device *pdev,
if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) {
pr_err("Failed to request GPIO_%d for reset\n",
CONFIG_SND_BF5XX_RESET_GPIO_NUM);
- ret = -1;
- goto gpio_err;
+ peripheral_free_list(&sport_req[sport_num][0]);
+ return -1;
}
gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1);
#endif
sport_handle = sport_init(&sport_params[sport_num], 2, \
sizeof(struct ac97_frame), NULL);
if (!sport_handle) {
- ret = -ENODEV;
- goto sport_err;
+ peripheral_free_list(&sport_req[sport_num][0]);
+#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
+ gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
+#endif
+ return -ENODEV;
}
/*SPORT works in TDM mode to simulate AC97 transfers*/
ret = sport_set_multichannel(sport_handle, 16, 0x1F, 1);
if (ret) {
pr_err("SPORT is busy!\n");
- ret = -EBUSY;
- goto sport_config_err;
+ kfree(sport_handle);
+ peripheral_free_list(&sport_req[sport_num][0]);
+#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
+ gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
+#endif
+ return -EBUSY;
}
ret = sport_config_rx(sport_handle, IRFS, 0xF, 0, (16*16-1));
if (ret) {
pr_err("SPORT is busy!\n");
- ret = -EBUSY;
- goto sport_config_err;
+ kfree(sport_handle);
+ peripheral_free_list(&sport_req[sport_num][0]);
+#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
+ gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
+#endif
+ return -EBUSY;
}
ret = sport_config_tx(sport_handle, ITFS, 0xF, 0, (16*16-1));
if (ret) {
pr_err("SPORT is busy!\n");
- ret = -EBUSY;
- goto sport_config_err;
- }
-
- return 0;
-
-sport_config_err:
- kfree(sport_handle);
-sport_err:
+ kfree(sport_handle);
+ peripheral_free_list(&sport_req[sport_num][0]);
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
- gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
+ gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
#endif
-gpio_err:
- peripheral_free_list(&sport_req[sport_num][0]);
-peripheral_err:
- free_page((unsigned long)cmd_count);
- cmd_count = NULL;
-
- return ret;
+ return -EBUSY;
+ }
+ return 0;
}
static void bf5xx_ac97_remove(struct platform_device *pdev,
@@ -398,7 +373,6 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
{
free_page((unsigned long)cmd_count);
cmd_count = NULL;
- peripheral_free_list(&sport_req[sport_num][0]);
#ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET
gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM);
#endif
@@ -407,7 +381,7 @@ static void bf5xx_ac97_remove(struct platform_device *pdev,
struct snd_soc_dai bfin_ac97_dai = {
.name = "bf5xx-ac97",
.id = 0,
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97,
.probe = bf5xx_ac97_probe,
.remove = bf5xx_ac97_remove,
.suspend = bf5xx_ac97_suspend,
@@ -415,11 +389,7 @@ struct snd_soc_dai bfin_ac97_dai = {
.playback = {
.stream_name = "AC97 Playback",
.channels_min = 2,
-#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
- .channels_max = 6,
-#else
.channels_max = 2,
-#endif
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
.capture = {
@@ -431,18 +401,6 @@ struct snd_soc_dai bfin_ac97_dai = {
};
EXPORT_SYMBOL_GPL(bfin_ac97_dai);
-static int __devinit bfin_ac97_init(void)
-{
- return snd_soc_register_dai(&bfin_ac97_dai);
-}
-module_init(bfin_ac97_init);
-
-static void __exit bfin_ac97_exit(void)
-{
- snd_soc_unregister_dai(&bfin_ac97_dai);
-}
-module_exit(bfin_ac97_exit);
-
MODULE_AUTHOR("Roy Huang");
MODULE_DESCRIPTION("AC97 driver for ADI Blackfin");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-ac97.h b/sound/soc/blackfin/bf5xx-ac97.h
index 3f2a911fe0cb..3f77cc558dc0 100644
--- a/sound/soc/blackfin/bf5xx-ac97.h
+++ b/sound/soc/blackfin/bf5xx-ac97.h
@@ -16,46 +16,21 @@ struct ac97_frame {
u16 ac97_tag; /* slot 0 */
u16 ac97_addr; /* slot 1 */
u16 ac97_data; /* slot 2 */
- u16 ac97_pcm_l; /*slot 3:front left*/
- u16 ac97_pcm_r; /*slot 4:front left*/
-#if defined(CONFIG_SND_BF5XX_MULTICHAN_SUPPORT)
- u16 ac97_mdm_l1;
- u16 ac97_center; /*slot 6:center*/
- u16 ac97_sl; /*slot 7:surround left*/
- u16 ac97_sr; /*slot 8:surround right*/
- u16 ac97_lfe; /*slot 9:lfe*/
-#endif
+ u32 ac97_pcm; /* slot 3 and 4: left and right pcm data */
} __attribute__ ((packed));
-/* Speaker location */
-#define SP_FL 0x0001
-#define SP_FR 0x0010
-#define SP_FC 0x0002
-#define SP_LFE 0x0020
-#define SP_SL 0x0004
-#define SP_SR 0x0040
-
-#define SP_STEREO (SP_FL | SP_FR)
-#define SP_2DOT1 (SP_FL | SP_FR | SP_LFE)
-#define SP_QUAD (SP_FL | SP_FR | SP_SL | SP_SR)
-#define SP_5DOT1 (SP_FL | SP_FR | SP_FC | SP_LFE | SP_SL | SP_SR)
-
#define TAG_VALID 0x8000
#define TAG_CMD 0x6000
#define TAG_PCM_LEFT 0x1000
#define TAG_PCM_RIGHT 0x0800
-#define TAG_PCM_MDM_L1 0x0400
-#define TAG_PCM_CENTER 0x0200
-#define TAG_PCM_SL 0x0100
-#define TAG_PCM_SR 0x0080
-#define TAG_PCM_LFE 0x0040
+#define TAG_PCM (TAG_PCM_LEFT | TAG_PCM_RIGHT)
extern struct snd_soc_dai bfin_ac97_dai;
-void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u16 *src, \
- size_t count, unsigned int chan_mask);
+void bf5xx_pcm_to_ac97(struct ac97_frame *dst, const __u32 *src, \
+ size_t count);
-void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u16 *dst, \
+void bf5xx_ac97_to_pcm(const struct ac97_frame *src, __u32 *dst, \
size_t count);
#endif
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c
index d8f591273778..124425d22320 100644
--- a/sound/soc/blackfin/bf5xx-ad1980.c
+++ b/sound/soc/blackfin/bf5xx-ad1980.c
@@ -43,7 +43,7 @@
#include "bf5xx-ac97-pcm.h"
#include "bf5xx-ac97.h"
-static struct snd_soc_card bf5xx_board;
+static struct snd_soc_machine bf5xx_board;
static int bf5xx_board_startup(struct snd_pcm_substream *substream)
{
@@ -67,15 +67,15 @@ static struct snd_soc_dai_link bf5xx_board_dai = {
.ops = &bf5xx_board_ops,
};
-static struct snd_soc_card bf5xx_board = {
+static struct snd_soc_machine bf5xx_board = {
.name = "bf5xx-board",
- .platform = &bf5xx_ac97_soc_platform,
.dai_link = &bf5xx_board_dai,
.num_links = 1,
};
static struct snd_soc_device bf5xx_board_snd_devdata = {
- .card = &bf5xx_board,
+ .machine = &bf5xx_board,
+ .platform = &bf5xx_ac97_soc_platform,
.codec_dev = &soc_codec_dev_ad1980,
};
diff --git a/sound/soc/blackfin/bf5xx-ad73311.c b/sound/soc/blackfin/bf5xx-ad73311.c
index 7f2a5e199075..622c9b909532 100644
--- a/sound/soc/blackfin/bf5xx-ad73311.c
+++ b/sound/soc/blackfin/bf5xx-ad73311.c
@@ -65,7 +65,7 @@
#define GPIO_SE CONFIG_SND_BFIN_AD73311_SE
-static struct snd_soc_card bf5xx_ad73311;
+static struct snd_soc_machine bf5xx_ad73311;
static int snd_ad73311_startup(void)
{
@@ -168,7 +168,7 @@ static int bf5xx_ad73311_hw_params(struct snd_pcm_substream *substream,
params_format(params));
/* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
+ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_DSP_A |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
@@ -190,16 +190,16 @@ static struct snd_soc_dai_link bf5xx_ad73311_dai = {
.ops = &bf5xx_ad73311_ops,
};
-static struct snd_soc_card bf5xx_ad73311 = {
+static struct snd_soc_machine bf5xx_ad73311 = {
.name = "bf5xx_ad73311",
- .platform = &bf5xx_i2s_soc_platform,
.probe = bf5xx_probe,
.dai_link = &bf5xx_ad73311_dai,
.num_links = 1,
};
static struct snd_soc_device bf5xx_ad73311_snd_devdata = {
- .card = &bf5xx_ad73311,
+ .machine = &bf5xx_ad73311,
+ .platform = &bf5xx_i2s_soc_platform,
.codec_dev = &soc_codec_dev_ad73311,
};
diff --git a/sound/soc/blackfin/bf5xx-i2s-pcm.c b/sound/soc/blackfin/bf5xx-i2s-pcm.c
index c58b12a44870..61fccf925192 100644
--- a/sound/soc/blackfin/bf5xx-i2s-pcm.c
+++ b/sound/soc/blackfin/bf5xx-i2s-pcm.c
@@ -283,18 +283,6 @@ struct snd_soc_platform bf5xx_i2s_soc_platform = {
};
EXPORT_SYMBOL_GPL(bf5xx_i2s_soc_platform);
-static int __devinit bfin_i2s_init(void)
-{
- return snd_soc_register_platform(&bf5xx_i2s_soc_platform);
-}
-module_init(bfin_i2s_init);
-
-static void __exit bfin_i2s_exit(void)
-{
- snd_soc_unregister_platform(&bf5xx_i2s_soc_platform);
-}
-module_exit(bfin_i2s_exit);
-
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("ADI Blackfin I2S PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/blackfin/bf5xx-i2s.c b/sound/soc/blackfin/bf5xx-i2s.c
index 0d58d2b6db6a..e020c160ee44 100644
--- a/sound/soc/blackfin/bf5xx-i2s.c
+++ b/sound/soc/blackfin/bf5xx-i2s.c
@@ -132,8 +132,7 @@ static int bf5xx_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
return ret;
}
-static int bf5xx_i2s_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int bf5xx_i2s_startup(struct snd_pcm_substream *substream)
{
pr_debug("%s enter\n", __func__);
@@ -143,8 +142,7 @@ static int bf5xx_i2s_startup(struct snd_pcm_substream *substream,
}
static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
int ret = 0;
@@ -195,8 +193,7 @@ static int bf5xx_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void bf5xx_i2s_shutdown(struct snd_pcm_substream *substream)
{
pr_debug("%s enter\n", __func__);
bf5xx_i2s.counter--;
@@ -222,14 +219,16 @@ static int bf5xx_i2s_probe(struct platform_device *pdev,
return 0;
}
-static void bf5xx_i2s_remove(struct snd_soc_dai *dai)
+static void bf5xx_i2s_remove(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
{
pr_debug("%s enter\n", __func__);
peripheral_free_list(&sport_req[sport_num][0]);
}
#ifdef CONFIG_PM
-static int bf5xx_i2s_suspend(struct snd_soc_dai *dai)
+static int bf5xx_i2s_suspend(struct platform_device *dev,
+ struct snd_soc_dai *dai)
{
struct sport_device *sport =
(struct sport_device *)dai->private_data;
@@ -290,6 +289,7 @@ static int bf5xx_i2s_resume(struct platform_device *pdev,
struct snd_soc_dai bf5xx_i2s_dai = {
.name = "bf5xx-i2s",
.id = 0,
+ .type = SND_SOC_DAI_I2S,
.probe = bf5xx_i2s_probe,
.remove = bf5xx_i2s_remove,
.suspend = bf5xx_i2s_suspend,
@@ -307,24 +307,13 @@ struct snd_soc_dai bf5xx_i2s_dai = {
.ops = {
.startup = bf5xx_i2s_startup,
.shutdown = bf5xx_i2s_shutdown,
- .hw_params = bf5xx_i2s_hw_params,
+ .hw_params = bf5xx_i2s_hw_params,},
+ .dai_ops = {
.set_fmt = bf5xx_i2s_set_dai_fmt,
},
};
EXPORT_SYMBOL_GPL(bf5xx_i2s_dai);
-static int __devinit bfin_i2s_init(void)
-{
- return snd_soc_register_dai(&bfin_i2s_dai);
-}
-module_init(bfin_i2s_init);
-
-static void __exit bfin_i2s_exit(void)
-{
- snd_soc_unregister_dai(&bfin_i2s_dai);
-}
-module_exit(bfin_i2s_exit);
-
/* Module information */
MODULE_AUTHOR("Cliff Cai");
MODULE_DESCRIPTION("I2S driver for ADI Blackfin");
diff --git a/sound/soc/blackfin/bf5xx-sport.h b/sound/soc/blackfin/bf5xx-sport.h
index 2e63dea73e9c..fcadcc081f7f 100644
--- a/sound/soc/blackfin/bf5xx-sport.h
+++ b/sound/soc/blackfin/bf5xx-sport.h
@@ -116,7 +116,7 @@ struct sport_device {
void *err_data;
unsigned char *tx_dma_buf;
unsigned char *rx_dma_buf;
-#ifdef CONFIG_SND_BF5XX_MMAP_SUPPORT
+#ifdef CONFIG_SND_MMAP_SUPPORT
dma_addr_t tx_dma_phy;
dma_addr_t rx_dma_phy;
int tx_pos;/*pcm sample count*/
diff --git a/sound/soc/blackfin/bf5xx-ssm2602.c b/sound/soc/blackfin/bf5xx-ssm2602.c
index bc0cdded7116..e15f67fd7769 100644
--- a/sound/soc/blackfin/bf5xx-ssm2602.c
+++ b/sound/soc/blackfin/bf5xx-ssm2602.c
@@ -44,7 +44,7 @@
#include "bf5xx-i2s-pcm.h"
#include "bf5xx-i2s.h"
-static struct snd_soc_card bf5xx_ssm2602;
+static struct snd_soc_machine bf5xx_ssm2602;
static int bf5xx_ssm2602_startup(struct snd_pcm_substream *substream)
{
@@ -92,17 +92,17 @@ static int bf5xx_ssm2602_hw_params(struct snd_pcm_substream *substream,
*/
/* set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
+ ret = codec_dai->dai_ops.set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
/* set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
+ ret = cpu_dai->dai_ops.set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBM_CFM);
if (ret < 0)
return ret;
- ret = snd_soc_dai_set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
+ ret = codec_dai->dai_ops.set_sysclk(codec_dai, SSM2602_SYSCLK, clk,
SND_SOC_CLOCK_IN);
if (ret < 0)
return ret;
@@ -135,15 +135,15 @@ static struct ssm2602_setup_data bf5xx_ssm2602_setup = {
.i2c_address = 0x1b,
};
-static struct snd_soc_card bf5xx_ssm2602 = {
+static struct snd_soc_machine bf5xx_ssm2602 = {
.name = "bf5xx_ssm2602",
- .platform = &bf5xx_i2s_soc_platform,
.dai_link = &bf5xx_ssm2602_dai,
.num_links = 1,
};
static struct snd_soc_device bf5xx_ssm2602_snd_devdata = {
- .card = &bf5xx_ssm2602,
+ .machine = &bf5xx_ssm2602,
+ .platform = &bf5xx_i2s_soc_platform,
.codec_dev = &soc_codec_dev_ssm2602,
.codec_data = &bf5xx_ssm2602_setup,
};
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index bf68052d6924..38a0e3b620a7 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -1,39 +1,31 @@
config SND_SOC_ALL_CODECS
tristate "Build all ASoC CODEC drivers"
- select SND_SOC_AC97_CODEC if SND_SOC_AC97_BUS
- select SND_SOC_AD1980 if SND_SOC_AC97_BUS
- select SND_SOC_AD73311 if I2C
- select SND_SOC_AK4535 if I2C
- select SND_SOC_CS4270 if I2C
- select SND_SOC_PCM3008
- select SND_SOC_SSM2602 if I2C
- select SND_SOC_TLV320AIC23 if I2C
- select SND_SOC_TLV320AIC26 if SPI_MASTER
- select SND_SOC_TLV320AIC3X if I2C
- select SND_SOC_TWL4030 if TWL4030_CORE
- select SND_SOC_UDA134X
- select SND_SOC_UDA1380 if I2C
- select SND_SOC_WM8510 if (I2C || SPI_MASTER)
- select SND_SOC_WM8580 if I2C
- select SND_SOC_WM8728 if (I2C || SPI_MASTER)
- select SND_SOC_WM8731 if (I2C || SPI_MASTER)
- select SND_SOC_WM8750 if (I2C || SPI_MASTER)
- select SND_SOC_WM8753 if (I2C || SPI_MASTER)
- select SND_SOC_WM8900 if I2C
- select SND_SOC_WM8903 if I2C
- select SND_SOC_WM8971 if I2C
- select SND_SOC_WM8990 if I2C
- select SND_SOC_WM9712 if SND_SOC_AC97_BUS
- select SND_SOC_WM9713 if SND_SOC_AC97_BUS
+ depends on I2C
+ select SPI
+ select SPI_MASTER
+ select SND_SOC_AD73311
+ select SND_SOC_AK4535
+ select SND_SOC_CS4270
+ select SND_SOC_SSM2602
+ select SND_SOC_TLV320AIC23
+ select SND_SOC_TLV320AIC26
+ select SND_SOC_TLV320AIC3X
+ select SND_SOC_UDA1380
+ select SND_SOC_WM8510
+ select SND_SOC_WM8580
+ select SND_SOC_WM8731
+ select SND_SOC_WM8750
+ select SND_SOC_WM8753
+ select SND_SOC_WM8900
+ select SND_SOC_WM8903
+ select SND_SOC_WM8971
+ select SND_SOC_WM8990
help
Normally ASoC codec drivers are only built if a machine driver which
uses them is also built since they are only usable with a machine
driver. Selecting this option will allow these drivers to be built
without an explicit machine driver for test and development purposes.
- Support for the bus types used to access the codecs to be built must
- be selected separately.
-
If unsure select "N".
@@ -68,12 +60,6 @@ config SND_SOC_CS4270_VD33_ERRATA
bool
depends on SND_SOC_CS4270
-config SND_SOC_L3
- tristate
-
-config SND_SOC_PCM3008
- tristate
-
config SND_SOC_SSM2602
tristate
@@ -89,14 +75,6 @@ config SND_SOC_TLV320AIC3X
tristate
depends on I2C
-config SND_SOC_TWL4030
- tristate
- depends on TWL4030_CORE
-
-config SND_SOC_UDA134X
- tristate
- select SND_SOC_L3
-
config SND_SOC_UDA1380
tristate
@@ -106,9 +84,6 @@ config SND_SOC_WM8510
config SND_SOC_WM8580
tristate
-config SND_SOC_WM8728
- tristate
-
config SND_SOC_WM8731
tristate
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 9a20fddd09c7..90f0a585fc70 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -3,18 +3,13 @@ snd-soc-ad1980-objs := ad1980.o
snd-soc-ad73311-objs := ad73311.o
snd-soc-ak4535-objs := ak4535.o
snd-soc-cs4270-objs := cs4270.o
-snd-soc-l3-objs := l3.o
-snd-soc-pcm3008-objs := pcm3008.o
snd-soc-ssm2602-objs := ssm2602.o
snd-soc-tlv320aic23-objs := tlv320aic23.o
snd-soc-tlv320aic26-objs := tlv320aic26.o
snd-soc-tlv320aic3x-objs := tlv320aic3x.o
-snd-soc-twl4030-objs := twl4030.o
-snd-soc-uda134x-objs := uda134x.o
snd-soc-uda1380-objs := uda1380.o
snd-soc-wm8510-objs := wm8510.o
snd-soc-wm8580-objs := wm8580.o
-snd-soc-wm8728-objs := wm8728.o
snd-soc-wm8731-objs := wm8731.o
snd-soc-wm8750-objs := wm8750.o
snd-soc-wm8753-objs := wm8753.o
@@ -30,18 +25,13 @@ obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o
obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o
obj-$(CONFIG_SND_SOC_AK4535) += snd-soc-ak4535.o
obj-$(CONFIG_SND_SOC_CS4270) += snd-soc-cs4270.o
-obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o
-obj-$(CONFIG_SND_SOC_PCM3008) += snd-soc-pcm3008.o
obj-$(CONFIG_SND_SOC_SSM2602) += snd-soc-ssm2602.o
obj-$(CONFIG_SND_SOC_TLV320AIC23) += snd-soc-tlv320aic23.o
obj-$(CONFIG_SND_SOC_TLV320AIC26) += snd-soc-tlv320aic26.o
obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o
-obj-$(CONFIG_SND_SOC_TWL4030) += snd-soc-twl4030.o
-obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
obj-$(CONFIG_SND_SOC_WM8510) += snd-soc-wm8510.o
obj-$(CONFIG_SND_SOC_WM8580) += snd-soc-wm8580.o
-obj-$(CONFIG_SND_SOC_WM8728) += snd-soc-wm8728.o
obj-$(CONFIG_SND_SOC_WM8731) += snd-soc-wm8731.o
obj-$(CONFIG_SND_SOC_WM8750) += snd-soc-wm8750.o
obj-$(CONFIG_SND_SOC_WM8753) += snd-soc-wm8753.o
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c
index fb53e6511af2..bd1ebdc6c86c 100644
--- a/sound/soc/codecs/ac97.c
+++ b/sound/soc/codecs/ac97.c
@@ -24,8 +24,7 @@
#define AC97_VERSION "0.6"
-static int ac97_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int ac97_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -43,7 +42,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai ac97_dai = {
.name = "AC97 HiFi",
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97,
.playback = {
.stream_name = "AC97 Playback",
.channels_min = 1,
@@ -114,7 +113,7 @@ static int ac97_soc_probe(struct platform_device *pdev)
if (ret < 0)
goto bus_err;
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0)
goto bus_err;
return 0;
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c
index 73fdbb4d4a3d..1397b8e06c0b 100644
--- a/sound/soc/codecs/ad1980.c
+++ b/sound/soc/codecs/ad1980.c
@@ -85,9 +85,6 @@ SOC_DOUBLE("Line HP Swap Switch", AC97_AD_MISC, 10, 5, 1, 0),
SOC_DOUBLE("Surround Playback Volume", AC97_SURROUND_MASTER, 8, 0, 31, 1),
SOC_DOUBLE("Surround Playback Switch", AC97_SURROUND_MASTER, 15, 7, 1, 1),
-SOC_DOUBLE("Center/LFE Playback Volume", AC97_CENTER_LFE_MASTER, 8, 0, 31, 1),
-SOC_DOUBLE("Center/LFE Playback Switch", AC97_CENTER_LFE_MASTER, 15, 7, 1, 1),
-
SOC_ENUM("Capture Source", ad1980_cap_src),
SOC_SINGLE("Mic Boost Switch", AC97_MIC, 6, 1, 0),
@@ -145,11 +142,10 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
struct snd_soc_dai ad1980_dai = {
.name = "AC97",
- .ac97_control = 1,
.playback = {
.stream_name = "Playback",
.channels_min = 2,
- .channels_max = 6,
+ .channels_max = 2,
.rates = SNDRV_PCM_RATE_48000,
.formats = SNDRV_PCM_FMTBIT_S16_LE, },
.capture = {
@@ -196,7 +192,6 @@ static int ad1980_soc_probe(struct platform_device *pdev)
struct snd_soc_codec *codec;
int ret = 0;
u16 vendor_id2;
- u16 ext_status;
printk(KERN_INFO "AD1980 SoC Audio Codec\n");
@@ -239,7 +234,7 @@ static int ad1980_soc_probe(struct platform_device *pdev)
ret = ad1980_reset(codec, 0);
if (ret < 0) {
- printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n");
+ printk(KERN_ERR "AC97 link error\n");
goto reset_err;
}
@@ -258,19 +253,12 @@ static int ad1980_soc_probe(struct platform_device *pdev)
"supported\n");
}
- /* unmute captures and playbacks volume */
- ac97_write(codec, AC97_MASTER, 0x0000);
- ac97_write(codec, AC97_PCM, 0x0000);
- ac97_write(codec, AC97_REC_GAIN, 0x0000);
- ac97_write(codec, AC97_CENTER_LFE_MASTER, 0x0000);
- ac97_write(codec, AC97_SURROUND_MASTER, 0x0000);
-
- /*power on LFE/CENTER/Surround DACs*/
- ext_status = ac97_read(codec, AC97_EXTENDED_STATUS);
- ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800);
+ ac97_write(codec, AC97_MASTER, 0x0000); /* unmute line out volume */
+ ac97_write(codec, AC97_PCM, 0x0000); /* unmute PCM out volume */
+ ac97_write(codec, AC97_REC_GAIN, 0x0000);/* unmute record volume */
ad1980_add_controls(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "ad1980: failed to register card\n");
goto reset_err;
diff --git a/sound/soc/codecs/ad73311.c b/sound/soc/codecs/ad73311.c
index e32f55034e64..37af8607b00a 100644
--- a/sound/soc/codecs/ad73311.c
+++ b/sound/soc/codecs/ad73311.c
@@ -8,10 +8,14 @@
* under the terms of the GNU General Public License as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
+ *
+ * Revision history
+ * 25th Sep 2008 Initial version.
*/
#include <linux/init.h>
#include <linux/module.h>
+#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <sound/core.h>
@@ -64,7 +68,7 @@ static int ad73311_soc_probe(struct platform_device *pdev)
goto pcm_err;
}
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "ad73311: failed to register card\n");
goto register_err;
@@ -98,18 +102,6 @@ struct snd_soc_codec_device soc_codec_dev_ad73311 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_ad73311);
-static int __devinit ad73311_init(void)
-{
- return snd_soc_register_dai(&ad73311_dai);
-}
-module_init(ad73311_init);
-
-static void __exit ad73311_exit(void)
-{
- snd_soc_unregister_dai(&ad73311_dai);
-}
-module_exit(ad73311_exit);
-
MODULE_DESCRIPTION("ASoC ad73311 driver");
MODULE_AUTHOR("Cliff Cai ");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/ak4535.c b/sound/soc/codecs/ak4535.c
index 94148fba9119..2a89b5888e11 100644
--- a/sound/soc/codecs/ak4535.c
+++ b/sound/soc/codecs/ak4535.c
@@ -339,8 +339,7 @@ static int ak4535_set_dai_sysclk(struct snd_soc_dai *codec_dai,
}
static int ak4535_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -452,6 +451,8 @@ struct snd_soc_dai ak4535_dai = {
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.hw_params = ak4535_hw_params,
+ },
+ .dai_ops = {
.set_fmt = ak4535_set_dai_fmt,
.digital_mute = ak4535_mute,
.set_sysclk = ak4535_set_dai_sysclk,
@@ -512,7 +513,7 @@ static int ak4535_init(struct snd_soc_device *socdev)
ak4535_add_controls(codec);
ak4535_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "ak4535: failed to register card\n");
goto card_err;
@@ -688,18 +689,6 @@ struct snd_soc_codec_device soc_codec_dev_ak4535 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_ak4535);
-static int __devinit ak4535_modinit(void)
-{
- return snd_soc_register_dai(&ak4535_dai);
-}
-module_init(ak4535_modinit);
-
-static void __exit ak4535_exit(void)
-{
- snd_soc_unregister_dai(&ak4535_dai);
-}
-module_exit(ak4535_exit);
-
MODULE_DESCRIPTION("Soc AK4535 driver");
MODULE_AUTHOR("Richard Purdie");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c
index 73aaf249d782..0bbd94501d7e 100644
--- a/sound/soc/codecs/cs4270.c
+++ b/sound/soc/codecs/cs4270.c
@@ -360,14 +360,13 @@ static int cs4270_i2c_write(struct snd_soc_codec *codec, unsigned int reg,
/*
* Program the CS4270 with the given hardware parameters.
*
- * The .ops functions are used to provide board-specific data, like
+ * The .dai_ops functions are used to provide board-specific data, like
* input frequencies, to this driver. This function takes that information,
* combines it with the hardware parameters provided, and programs the
* hardware accordingly.
*/
static int cs4270_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -451,19 +450,6 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream,
return ret;
}
- /* Disable automatic volume control. It's enabled by default, and
- * it causes volume change commands to be delayed, sometimes until
- * after playback has started.
- */
-
- reg = cs4270_read_reg_cache(codec, CS4270_TRANS);
- reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO);
- ret = cs4270_i2c_write(codec, CS4270_TRANS, reg);
- if (ret < 0) {
- printk(KERN_ERR "I2C write failed\n");
- return ret;
- }
-
/* Thaw and power-up the codec */
ret = snd_soc_write(codec, CS4270_PWRCTL, 0);
@@ -711,10 +697,10 @@ static int cs4270_probe(struct platform_device *pdev)
if (codec->control_data) {
/* Initialize codec ops */
cs4270_dai.ops.hw_params = cs4270_hw_params;
- cs4270_dai.ops.set_sysclk = cs4270_set_dai_sysclk;
- cs4270_dai.ops.set_fmt = cs4270_set_dai_fmt;
+ cs4270_dai.dai_ops.set_sysclk = cs4270_set_dai_sysclk;
+ cs4270_dai.dai_ops.set_fmt = cs4270_set_dai_fmt;
#ifdef CONFIG_SND_SOC_CS4270_HWMUTE
- cs4270_dai.ops.digital_mute = cs4270_mute;
+ cs4270_dai.dai_ops.digital_mute = cs4270_mute;
#endif
} else
printk(KERN_INFO "cs4270: no I2C device found, "
@@ -723,7 +709,7 @@ static int cs4270_probe(struct platform_device *pdev)
printk(KERN_INFO "cs4270: I2C disabled, using stand-alone mode\n");
#endif
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "cs4270: failed to register card\n");
goto error_del_driver;
@@ -774,18 +760,6 @@ struct snd_soc_codec_device soc_codec_device_cs4270 = {
};
EXPORT_SYMBOL_GPL(soc_codec_device_cs4270);
-static int __devinit cs4270_init(void)
-{
- return snd_soc_register_dai(&cs4270_dai);
-}
-module_init(cs4270_init);
-
-static void __exit cs4270_exit(void)
-{
- snd_soc_unregister_dai(&cs4270_dai);
-}
-module_exit(cs4270_exit);
-
MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/l3.c b/sound/soc/codecs/l3.c
deleted file mode 100644
index 5353af58862c..000000000000
--- a/sound/soc/codecs/l3.c
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * L3 code
- *
- * Copyright (C) 2008, Christian Pellegrin <chripell@evolware.org>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- *
- * based on:
- *
- * L3 bus algorithm module.
- *
- * Copyright (C) 2001 Russell King, All Rights Reserved.
- *
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/delay.h>
-
-#include <sound/l3.h>
-
-/*
- * Send one byte of data to the chip. Data is latched into the chip on
- * the rising edge of the clock.
- */
-static void sendbyte(struct l3_pins *adap, unsigned int byte)
-{
- int i;
-
- for (i = 0; i < 8; i++) {
- adap->setclk(0);
- udelay(adap->data_hold);
- adap->setdat(byte & 1);
- udelay(adap->data_setup);
- adap->setclk(1);
- udelay(adap->clock_high);
- byte >>= 1;
- }
-}
-
-/*
- * Send a set of bytes to the chip. We need to pulse the MODE line
- * between each byte, but never at the start nor at the end of the
- * transfer.
- */
-static void sendbytes(struct l3_pins *adap, const u8 *buf,
- int len)
-{
- int i;
-
- for (i = 0; i < len; i++) {
- if (i) {
- udelay(adap->mode_hold);
- adap->setmode(0);
- udelay(adap->mode);
- }
- adap->setmode(1);
- udelay(adap->mode_setup);
- sendbyte(adap, buf[i]);
- }
-}
-
-int l3_write(struct l3_pins *adap, u8 addr, u8 *data, int len)
-{
- adap->setclk(1);
- adap->setdat(1);
- adap->setmode(1);
- udelay(adap->mode);
-
- adap->setmode(0);
- udelay(adap->mode_setup);
- sendbyte(adap, addr);
- udelay(adap->mode_hold);
-
- sendbytes(adap, data, len);
-
- adap->setclk(1);
- adap->setdat(1);
- adap->setmode(0);
-
- return len;
-}
-EXPORT_SYMBOL_GPL(l3_write);
-
-MODULE_DESCRIPTION("L3 bit-banging driver");
-MODULE_AUTHOR("Christian Pellegrin <chripell@evolware.org>");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm3008.c b/sound/soc/codecs/pcm3008.c
deleted file mode 100644
index f333e88ee255..000000000000
--- a/sound/soc/codecs/pcm3008.c
+++ /dev/null
@@ -1,212 +0,0 @@
-/*
- * ALSA Soc PCM3008 codec support
- *
- * Author: Hugo Villeneuve
- * Copyright (C) 2008 Lyrtech inc
- *
- * Based on AC97 Soc codec, original copyright follow:
- * Copyright 2005 Wolfson Microelectronics PLC.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * Generic PCM3008 support.
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/device.h>
-#include <linux/gpio.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-#include <sound/soc.h>
-
-#include "pcm3008.h"
-
-#define PCM3008_VERSION "0.2"
-
-#define PCM3008_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | \
- SNDRV_PCM_RATE_48000)
-
-struct snd_soc_dai pcm3008_dai = {
- .name = "PCM3008 HiFi",
- .playback = {
- .stream_name = "PCM3008 Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = PCM3008_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
- .capture = {
- .stream_name = "PCM3008 Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = PCM3008_RATES,
- .formats = SNDRV_PCM_FMTBIT_S16_LE,
- },
-};
-EXPORT_SYMBOL_GPL(pcm3008_dai);
-
-static void pcm3008_gpio_free(struct pcm3008_setup_data *setup)
-{
- gpio_free(setup->dem0_pin);
- gpio_free(setup->dem1_pin);
- gpio_free(setup->pdad_pin);
- gpio_free(setup->pdda_pin);
-}
-
-static int pcm3008_soc_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct pcm3008_setup_data *setup = socdev->codec_data;
- int ret = 0;
-
- printk(KERN_INFO "PCM3008 SoC Audio Codec %s\n", PCM3008_VERSION);
-
- socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (!socdev->codec)
- return -ENOMEM;
-
- codec = socdev->codec;
- mutex_init(&codec->mutex);
-
- codec->name = "PCM3008";
- codec->owner = THIS_MODULE;
- codec->dai = &pcm3008_dai;
- codec->num_dai = 1;
- codec->write = NULL;
- codec->read = NULL;
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- /* Register PCMs. */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "pcm3008: failed to create pcms\n");
- goto pcm_err;
- }
-
- /* Register Card. */
- ret = snd_soc_init_card(socdev);
- if (ret < 0) {
- printk(KERN_ERR "pcm3008: failed to register card\n");
- goto card_err;
- }
-
- /* DEM1 DEM0 DE-EMPHASIS_MODE
- * Low Low De-emphasis 44.1 kHz ON
- * Low High De-emphasis OFF
- * High Low De-emphasis 48 kHz ON
- * High High De-emphasis 32 kHz ON
- */
-
- /* Configure DEM0 GPIO (turning OFF DAC De-emphasis). */
- ret = gpio_request(setup->dem0_pin, "codec_dem0");
- if (ret == 0)
- ret = gpio_direction_output(setup->dem0_pin, 1);
- if (ret != 0)
- goto gpio_err;
-
- /* Configure DEM1 GPIO (turning OFF DAC De-emphasis). */
- ret = gpio_request(setup->dem1_pin, "codec_dem1");
- if (ret == 0)
- ret = gpio_direction_output(setup->dem1_pin, 0);
- if (ret != 0)
- goto gpio_err;
-
- /* Configure PDAD GPIO. */
- ret = gpio_request(setup->pdad_pin, "codec_pdad");
- if (ret == 0)
- ret = gpio_direction_output(setup->pdad_pin, 1);
- if (ret != 0)
- goto gpio_err;
-
- /* Configure PDDA GPIO. */
- ret = gpio_request(setup->pdda_pin, "codec_pdda");
- if (ret == 0)
- ret = gpio_direction_output(setup->pdda_pin, 1);
- if (ret != 0)
- goto gpio_err;
-
- return ret;
-
-gpio_err:
- pcm3008_gpio_free(setup);
-card_err:
- snd_soc_free_pcms(socdev);
-pcm_err:
- kfree(socdev->codec);
-
- return ret;
-}
-
-static int pcm3008_soc_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
- struct pcm3008_setup_data *setup = socdev->codec_data;
-
- if (!codec)
- return 0;
-
- pcm3008_gpio_free(setup);
- snd_soc_free_pcms(socdev);
- kfree(socdev->codec);
-
- return 0;
-}
-
-#ifdef CONFIG_PM
-static int pcm3008_soc_suspend(struct platform_device *pdev, pm_message_t msg)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct pcm3008_setup_data *setup = socdev->codec_data;
-
- gpio_set_value(setup->pdad_pin, 0);
- gpio_set_value(setup->pdda_pin, 0);
-
- return 0;
-}
-
-static int pcm3008_soc_resume(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct pcm3008_setup_data *setup = socdev->codec_data;
-
- gpio_set_value(setup->pdad_pin, 1);
- gpio_set_value(setup->pdda_pin, 1);
-
- return 0;
-}
-#else
-#define pcm3008_soc_suspend NULL
-#define pcm3008_soc_resume NULL
-#endif
-
-struct snd_soc_codec_device soc_codec_dev_pcm3008 = {
- .probe = pcm3008_soc_probe,
- .remove = pcm3008_soc_remove,
- .suspend = pcm3008_soc_suspend,
- .resume = pcm3008_soc_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_pcm3008);
-
-static int __devinit pcm3008_init(void)
-{
- return snd_soc_register_dai(&pcm3008_dai);
-}
-module_init(pcm3008_init);
-
-static void __exit pcm3008_exit(void)
-{
- snd_soc_unregister_dai(&pcm3008_dai);
-}
-module_exit(pcm3008_exit);
-
-MODULE_DESCRIPTION("Soc PCM3008 driver");
-MODULE_AUTHOR("Hugo Villeneuve");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/pcm3008.h b/sound/soc/codecs/pcm3008.h
deleted file mode 100644
index d04e87d3c060..000000000000
--- a/sound/soc/codecs/pcm3008.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * PCM3008 ALSA SoC Layer
- *
- * Author: Hugo Villeneuve
- * Copyright (C) 2008 Lyrtech inc
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __LINUX_SND_SOC_PCM3008_H
-#define __LINUX_SND_SOC_PCM3008_H
-
-struct pcm3008_setup_data {
- unsigned dem0_pin;
- unsigned dem1_pin;
- unsigned pdad_pin;
- unsigned pdda_pin;
-};
-
-extern struct snd_soc_codec_device soc_codec_dev_pcm3008;
-extern struct snd_soc_dai pcm3008_dai;
-
-#endif
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c
index 77fdcb4b9a1b..44ef0dacd564 100644
--- a/sound/soc/codecs/ssm2602.c
+++ b/sound/soc/codecs/ssm2602.c
@@ -285,23 +285,16 @@ static inline int get_coeff(int mclk, int rate)
}
static int ssm2602_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
u16 srate;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
struct ssm2602_priv *ssm2602 = codec->private_data;
- struct i2c_client *i2c = codec->control_data;
u16 iface = ssm2602_read_reg_cache(codec, SSM2602_IFACE) & 0xfff3;
int i = get_coeff(ssm2602->sysclk, params_rate(params));
- if (substream == ssm2602->slave_substream) {
- dev_dbg(&i2c->dev, "Ignoring hw_params for slave substream\n");
- return 0;
- }
-
/*no match is found*/
if (i == ARRAY_SIZE(coeff_div))
return -EINVAL;
@@ -331,26 +324,19 @@ static int ssm2602_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int ssm2602_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int ssm2602_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
struct ssm2602_priv *ssm2602 = codec->private_data;
- struct i2c_client *i2c = codec->control_data;
struct snd_pcm_runtime *master_runtime;
/* The DAI has shared clocks so if we already have a playback or
* capture going then constrain this substream to match it.
- * TODO: the ssm2602 allows pairs of non-matching PB/REC rates
*/
if (ssm2602->master_substream) {
master_runtime = ssm2602->master_substream->runtime;
- dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n",
- master_runtime->sample_bits,
- master_runtime->rate);
-
snd_pcm_hw_constraint_minmax(substream->runtime,
SNDRV_PCM_HW_PARAM_RATE,
master_runtime->rate,
@@ -368,8 +354,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream,
return 0;
}
-static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -380,21 +365,14 @@ static int ssm2602_pcm_prepare(struct snd_pcm_substream *substream,
return 0;
}
-static void ssm2602_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void ssm2602_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
- struct ssm2602_priv *ssm2602 = codec->private_data;
/* deactivate */
if (!codec->active)
ssm2602_write(codec, SSM2602_ACTIVE, 0);
-
- if (ssm2602->master_substream == substream)
- ssm2602->master_substream = ssm2602->slave_substream;
-
- ssm2602->slave_substream = NULL;
}
static int ssm2602_mute(struct snd_soc_dai *dai, int mute)
@@ -518,9 +496,6 @@ static int ssm2602_set_bias_level(struct snd_soc_codec *codec,
SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\
SNDRV_PCM_RATE_96000)
-#define SSM2602_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
- SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE)
-
struct snd_soc_dai ssm2602_dai = {
.name = "SSM2602",
.playback = {
@@ -528,18 +503,20 @@ struct snd_soc_dai ssm2602_dai = {
.channels_min = 2,
.channels_max = 2,
.rates = SSM2602_RATES,
- .formats = SSM2602_FORMATS,},
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,},
.capture = {
.stream_name = "Capture",
.channels_min = 2,
.channels_max = 2,
.rates = SSM2602_RATES,
- .formats = SSM2602_FORMATS,},
+ .formats = SNDRV_PCM_FMTBIT_S32_LE,},
.ops = {
.startup = ssm2602_startup,
.prepare = ssm2602_pcm_prepare,
.hw_params = ssm2602_hw_params,
.shutdown = ssm2602_shutdown,
+ },
+ .dai_ops = {
.digital_mute = ssm2602_mute,
.set_sysclk = ssm2602_set_dai_sysclk,
.set_fmt = ssm2602_set_dai_fmt,
@@ -624,7 +601,7 @@ static int ssm2602_init(struct snd_soc_device *socdev)
ssm2602_add_controls(codec);
ssm2602_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
pr_err("ssm2602: failed to register card\n");
goto card_err;
@@ -793,18 +770,6 @@ struct snd_soc_codec_device soc_codec_dev_ssm2602 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_ssm2602);
-static int __devinit ssm2602_modinit(void)
-{
- return snd_soc_register_dai(&ssm2602_dai);
-}
-module_init(ssm2602_modinit);
-
-static void __exit ssm2602_exit(void)
-{
- snd_soc_unregister_dai(&ssm2602_dai);
-}
-module_exit(ssm2602_exit);
-
MODULE_DESCRIPTION("ASoC ssm2602 driver");
MODULE_AUTHOR("Cliff Cai");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic23.c b/sound/soc/codecs/tlv320aic23.c
index eac449b92bd5..44308dac9e18 100644
--- a/sound/soc/codecs/tlv320aic23.c
+++ b/sound/soc/codecs/tlv320aic23.c
@@ -37,6 +37,12 @@
#define AIC23_VERSION "0.1"
+struct tlv320aic23_srate_reg_info {
+ u32 sample_rate;
+ u8 control; /* SR3, SR2, SR1, SR0 and BOSR */
+ u8 divider; /* if 0 CLKIN = MCLK, if 1 CLKIN = MCLK/2 */
+};
+
/*
* AIC23 register cache
*/
@@ -255,156 +261,20 @@ static const struct snd_soc_dapm_route intercon[] = {
};
-/* AIC23 driver data */
-struct aic23 {
- struct snd_soc_codec codec;
- int mclk;
- int requested_adc;
- int requested_dac;
-};
-
-/*
- * Common Crystals used
- * 11.2896 Mhz /128 = *88.2k /192 = 58.8k
- * 12.0000 Mhz /125 = *96k /136 = 88.235K
- * 12.2880 Mhz /128 = *96k /192 = 64k
- * 16.9344 Mhz /128 = 132.3k /192 = *88.2k
- * 18.4320 Mhz /128 = 144k /192 = *96k
- */
-
-/*
- * Normal BOSR 0-256/2 = 128, 1-384/2 = 192
- * USB BOSR 0-250/2 = 125, 1-272/2 = 136
- */
-static const int bosr_usb_divisor_table[] = {
- 128, 125, 192, 136
-};
-#define LOWER_GROUP ((1<<0) | (1<<1) | (1<<2) | (1<<3) | (1<<6) | (1<<7))
-#define UPPER_GROUP ((1<<8) | (1<<9) | (1<<10) | (1<<11) | (1<<15))
-static const unsigned short sr_valid_mask[] = {
- LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 0*/
- LOWER_GROUP|UPPER_GROUP, /* Normal, bosr - 1*/
- LOWER_GROUP, /* Usb, bosr - 0*/
- UPPER_GROUP, /* Usb, bosr - 1*/
-};
-/*
- * Every divisor is a factor of 11*12
- */
-#define SR_MULT (11*12)
-#define A(x) (x) ? (SR_MULT/x) : 0
-static const unsigned char sr_adc_mult_table[] = {
- A(2), A(2), A(12), A(12), A(0), A(0), A(3), A(1),
- A(2), A(2), A(11), A(11), A(0), A(0), A(0), A(1)
-};
-static const unsigned char sr_dac_mult_table[] = {
- A(2), A(12), A(2), A(12), A(0), A(0), A(3), A(1),
- A(2), A(11), A(2), A(11), A(0), A(0), A(0), A(1)
+/* tlv320aic23 related */
+static const struct tlv320aic23_srate_reg_info srate_reg_info[] = {
+ {4000, 0x06, 1}, /* 4000 */
+ {8000, 0x06, 0}, /* 8000 */
+ {16000, 0x0C, 1}, /* 16000 */
+ {22050, 0x11, 1}, /* 22050 */
+ {24000, 0x00, 1}, /* 24000 */
+ {32000, 0x0C, 0}, /* 32000 */
+ {44100, 0x11, 0}, /* 44100 */
+ {48000, 0x00, 0}, /* 48000 */
+ {88200, 0x1F, 0}, /* 88200 */
+ {96000, 0x0E, 0}, /* 96000 */
};
-static unsigned get_score(int adc, int adc_l, int adc_h, int need_adc,
- int dac, int dac_l, int dac_h, int need_dac)
-{
- if ((adc >= adc_l) && (adc <= adc_h) &&
- (dac >= dac_l) && (dac <= dac_h)) {
- int diff_adc = need_adc - adc;
- int diff_dac = need_dac - dac;
- return abs(diff_adc) + abs(diff_dac);
- }
- return UINT_MAX;
-}
-
-static int find_rate(int mclk, u32 need_adc, u32 need_dac)
-{
- int i, j;
- int best_i = -1;
- int best_j = -1;
- int best_div = 0;
- unsigned best_score = UINT_MAX;
- int adc_l, adc_h, dac_l, dac_h;
-
- need_adc *= SR_MULT;
- need_dac *= SR_MULT;
- /*
- * rates given are +/- 1/32
- */
- adc_l = need_adc - (need_adc >> 5);
- adc_h = need_adc + (need_adc >> 5);
- dac_l = need_dac - (need_dac >> 5);
- dac_h = need_dac + (need_dac >> 5);
- for (i = 0; i < ARRAY_SIZE(bosr_usb_divisor_table); i++) {
- int base = mclk / bosr_usb_divisor_table[i];
- int mask = sr_valid_mask[i];
- for (j = 0; j < ARRAY_SIZE(sr_adc_mult_table);
- j++, mask >>= 1) {
- int adc;
- int dac;
- int score;
- if ((mask & 1) == 0)
- continue;
- adc = base * sr_adc_mult_table[j];
- dac = base * sr_dac_mult_table[j];
- score = get_score(adc, adc_l, adc_h, need_adc,
- dac, dac_l, dac_h, need_dac);
- if (best_score > score) {
- best_score = score;
- best_i = i;
- best_j = j;
- best_div = 0;
- }
- score = get_score((adc >> 1), adc_l, adc_h, need_adc,
- (dac >> 1), dac_l, dac_h, need_dac);
- /* prefer to have a /2 */
- if ((score != UINT_MAX) && (best_score >= score)) {
- best_score = score;
- best_i = i;
- best_j = j;
- best_div = 1;
- }
- }
- }
- return (best_j << 2) | best_i | (best_div << TLV320AIC23_CLKIN_SHIFT);
-}
-
-#ifdef DEBUG
-static void get_current_sample_rates(struct snd_soc_codec *codec, int mclk,
- u32 *sample_rate_adc, u32 *sample_rate_dac)
-{
- int src = tlv320aic23_read_reg_cache(codec, TLV320AIC23_SRATE);
- int sr = (src >> 2) & 0x0f;
- int val = (mclk / bosr_usb_divisor_table[src & 3]);
- int adc = (val * sr_adc_mult_table[sr]) / SR_MULT;
- int dac = (val * sr_dac_mult_table[sr]) / SR_MULT;
- if (src & TLV320AIC23_CLKIN_HALF) {
- adc >>= 1;
- dac >>= 1;
- }
- *sample_rate_adc = adc;
- *sample_rate_dac = dac;
-}
-#endif
-
-static int set_sample_rate_control(struct snd_soc_codec *codec, int mclk,
- u32 sample_rate_adc, u32 sample_rate_dac)
-{
- /* Search for the right sample rate */
- int data = find_rate(mclk, sample_rate_adc, sample_rate_dac);
- if (data < 0) {
- printk(KERN_ERR "%s:Invalid rate %u,%u requested\n",
- __func__, sample_rate_adc, sample_rate_dac);
- return -EINVAL;
- }
- tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
-#ifdef DEBUG
- {
- u32 adc, dac;
- get_current_sample_rates(codec, mclk, &adc, &dac);
- printk(KERN_DEBUG "actual samplerate = %u,%u reg=%x\n",
- adc, dac, data);
- }
-#endif
- return 0;
-}
-
static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
{
snd_soc_dapm_new_controls(codec, tlv320aic23_dapm_widgets,
@@ -418,36 +288,32 @@ static int tlv320aic23_add_widgets(struct snd_soc_codec *codec)
}
static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
- u16 iface_reg;
- int ret;
- struct aic23 *aic23 = container_of(codec, struct aic23, codec);
- u32 sample_rate_adc = aic23->requested_adc;
- u32 sample_rate_dac = aic23->requested_dac;
- u32 sample_rate = params_rate(params);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- aic23->requested_dac = sample_rate_dac = sample_rate;
- if (!sample_rate_adc)
- sample_rate_adc = sample_rate;
- } else {
- aic23->requested_adc = sample_rate_adc = sample_rate;
- if (!sample_rate_dac)
- sample_rate_dac = sample_rate;
- }
- ret = set_sample_rate_control(codec, aic23->mclk, sample_rate_adc,
- sample_rate_dac);
- if (ret < 0)
- return ret;
+ u16 iface_reg, data;
+ u8 count = 0;
iface_reg =
tlv320aic23_read_reg_cache(codec,
TLV320AIC23_DIGT_FMT) & ~(0x03 << 2);
+
+ /* Search for the right sample rate */
+ /* Verify what happens if the rate is not supported
+ * now it goes to 96Khz */
+ while ((srate_reg_info[count].sample_rate != params_rate(params)) &&
+ (count < ARRAY_SIZE(srate_reg_info))) {
+ count++;
+ }
+
+ data = (srate_reg_info[count].divider << TLV320AIC23_CLKIN_SHIFT) |
+ (srate_reg_info[count]. control << TLV320AIC23_BOSR_SHIFT) |
+ TLV320AIC23_USB_CLK_ON;
+
+ tlv320aic23_write(codec, TLV320AIC23_SRATE, data);
+
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S16_LE:
break;
@@ -466,8 +332,7 @@ static int tlv320aic23_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -479,23 +344,17 @@ static int tlv320aic23_pcm_prepare(struct snd_pcm_substream *substream,
return 0;
}
-static void tlv320aic23_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void tlv320aic23_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
- struct aic23 *aic23 = container_of(codec, struct aic23, codec);
/* deactivate */
if (!codec->active) {
udelay(50);
tlv320aic23_write(codec, TLV320AIC23_ACTIVE, 0x0);
}
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- aic23->requested_dac = 0;
- else
- aic23->requested_adc = 0;
}
static int tlv320aic23_mute(struct snd_soc_dai *dai, int mute)
@@ -563,9 +422,12 @@ static int tlv320aic23_set_dai_sysclk(struct snd_soc_dai *codec_dai,
int clk_id, unsigned int freq, int dir)
{
struct snd_soc_codec *codec = codec_dai->codec;
- struct aic23 *aic23 = container_of(codec, struct aic23, codec);
- aic23->mclk = freq;
- return 0;
+
+ switch (freq) {
+ case 12000000:
+ return 0;
+ }
+ return -EINVAL;
}
static int tlv320aic23_set_bias_level(struct snd_soc_codec *codec,
@@ -616,10 +478,12 @@ struct snd_soc_dai tlv320aic23_dai = {
.prepare = tlv320aic23_pcm_prepare,
.hw_params = tlv320aic23_hw_params,
.shutdown = tlv320aic23_shutdown,
- .digital_mute = tlv320aic23_mute,
- .set_fmt = tlv320aic23_set_dai_fmt,
- .set_sysclk = tlv320aic23_set_dai_sysclk,
- }
+ },
+ .dai_ops = {
+ .digital_mute = tlv320aic23_mute,
+ .set_fmt = tlv320aic23_set_dai_fmt,
+ .set_sysclk = tlv320aic23_set_dai_sysclk,
+ }
};
EXPORT_SYMBOL_GPL(tlv320aic23_dai);
@@ -720,7 +584,7 @@ static int tlv320aic23_init(struct snd_soc_device *socdev)
tlv320aic23_add_controls(codec);
tlv320aic23_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "tlv320aic23: failed to register card\n");
goto card_err;
@@ -795,15 +659,14 @@ static int tlv320aic23_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec;
- struct aic23 *aic23;
int ret = 0;
printk(KERN_INFO "AIC23 Audio Codec %s\n", AIC23_VERSION);
- aic23 = kzalloc(sizeof(struct aic23), GFP_KERNEL);
- if (aic23 == NULL)
+ codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
+ if (codec == NULL)
return -ENOMEM;
- codec = &aic23->codec;
+
socdev->codec = codec;
mutex_init(&codec->mutex);
INIT_LIST_HEAD(&codec->dapm_widgets);
@@ -824,7 +687,6 @@ static int tlv320aic23_remove(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
struct snd_soc_codec *codec = socdev->codec;
- struct aic23 *aic23 = container_of(codec, struct aic23, codec);
if (codec->control_data)
tlv320aic23_set_bias_level(codec, SND_SOC_BIAS_OFF);
@@ -835,7 +697,7 @@ static int tlv320aic23_remove(struct platform_device *pdev)
i2c_del_driver(&tlv320aic23_i2c_driver);
#endif
kfree(codec->reg_cache);
- kfree(aic23);
+ kfree(codec);
return 0;
}
@@ -847,18 +709,6 @@ struct snd_soc_codec_device soc_codec_dev_tlv320aic23 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320aic23);
-static int __devinit tlv320aic23_modinit(void)
-{
- return snd_soc_register_dai(&tlv320aic23_dai);
-}
-module_init(tlv320aic23_modinit);
-
-static void __exit tlv320aic23_exit(void)
-{
- snd_soc_unregister_dai(&tlv320aic23_dai);
-}
-module_exit(tlv320aic23_exit);
-
MODULE_DESCRIPTION("ASoC TLV320AIC23 codec driver");
MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c
index 29f2f1a017fd..bed8a9e63ddc 100644
--- a/sound/soc/codecs/tlv320aic26.c
+++ b/sound/soc/codecs/tlv320aic26.c
@@ -125,8 +125,7 @@ static int aic26_reg_write(struct snd_soc_codec *codec, unsigned int reg,
* Digital Audio Interface Operations
*/
static int aic26_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -288,6 +287,8 @@ struct snd_soc_dai aic26_dai = {
},
.ops = {
.hw_params = aic26_hw_params,
+ },
+ .dai_ops = {
.digital_mute = aic26_mute,
.set_sysclk = aic26_set_sysclk,
.set_fmt = aic26_set_fmt,
@@ -359,7 +360,7 @@ static int aic26_probe(struct platform_device *pdev)
/* CODEC is setup, we can register the card now */
dev_dbg(&pdev->dev, "Registering card\n");
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
dev_err(&pdev->dev, "aic26: failed to register card\n");
goto card_err;
@@ -426,7 +427,7 @@ static DEVICE_ATTR(keyclick, 0644, aic26_keyclick_show, aic26_keyclick_set);
static int aic26_spi_probe(struct spi_device *spi)
{
struct aic26 *aic26;
- int ret, i, reg;
+ int rc, i, reg;
dev_dbg(&spi->dev, "probing tlv320aic26 spi device\n");
@@ -456,14 +457,6 @@ static int aic26_spi_probe(struct spi_device *spi)
aic26->codec.reg_cache_size = AIC26_NUM_REGS;
aic26->codec.reg_cache = aic26->reg_cache;
- aic26_dai.dev = &spi->dev;
- ret = snd_soc_register_dai(&aic26_dai);
- if (ret != 0) {
- dev_err(&spi->dev, "Failed to register DAI: %d\n", ret);
- kfree(aic26);
- return ret;
- }
-
/* Reset the codec to power on defaults */
aic26_reg_write(&aic26->codec, AIC26_REG_RESET, 0xBB00);
@@ -482,8 +475,8 @@ static int aic26_spi_probe(struct spi_device *spi)
/* Register the sysfs files for debugging */
/* Create SysFS files */
- ret = device_create_file(&spi->dev, &dev_attr_keyclick);
- if (ret)
+ rc = device_create_file(&spi->dev, &dev_attr_keyclick);
+ if (rc)
dev_info(&spi->dev, "error creating sysfs files\n");
#if defined(CONFIG_SND_SOC_OF_SIMPLE)
@@ -500,7 +493,6 @@ static int aic26_spi_remove(struct spi_device *spi)
{
struct aic26 *aic26 = dev_get_drvdata(&spi->dev);
- snd_soc_unregister_dai(&aic26_dai);
kfree(aic26);
return 0;
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c
index ccd575961869..cff276ee261e 100644
--- a/sound/soc/codecs/tlv320aic3x.c
+++ b/sound/soc/codecs/tlv320aic3x.c
@@ -253,17 +253,11 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
SOC_DOUBLE_R("Line DAC Playback Volume", DACL1_2_LLOPM_VOL,
DACR1_2_RLOPM_VOL, 0, 0x7f, 1),
- SOC_SINGLE("LineL Playback Switch", LLOPM_CTRL, 3, 0x01, 0),
- SOC_SINGLE("LineR Playback Switch", RLOPM_CTRL, 3, 0x01, 0),
- SOC_DOUBLE_R("LineL DAC Playback Volume", DACL1_2_LLOPM_VOL,
- DACR1_2_LLOPM_VOL, 0, 0x7f, 1),
- SOC_SINGLE("LineL Left PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL,
- 0, 0x7f, 1),
- SOC_SINGLE("LineR Right PGA Bypass Playback Volume", PGAR_2_RLOPM_VOL,
- 0, 0x7f, 1),
- SOC_DOUBLE_R("LineL Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL,
- LINE2R_2_LLOPM_VOL, 0, 0x7f, 1),
- SOC_DOUBLE_R("LineR Line2 Bypass Playback Volume", LINE2L_2_RLOPM_VOL,
+ SOC_DOUBLE_R("Line DAC Playback Switch", LLOPM_CTRL, RLOPM_CTRL, 3,
+ 0x01, 0),
+ SOC_DOUBLE_R("Line PGA Bypass Playback Volume", PGAL_2_LLOPM_VOL,
+ PGAR_2_RLOPM_VOL, 0, 0x7f, 1),
+ SOC_DOUBLE_R("Line Line2 Bypass Playback Volume", LINE2L_2_LLOPM_VOL,
LINE2R_2_RLOPM_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("Mono DAC Playback Volume", DACL1_2_MONOLOPM_VOL,
@@ -278,12 +272,8 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
DACR1_2_HPROUT_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("HP DAC Playback Switch", HPLOUT_CTRL, HPROUT_CTRL, 3,
0x01, 0),
- SOC_DOUBLE_R("HP Right PGA Bypass Playback Volume", PGAR_2_HPLOUT_VOL,
+ SOC_DOUBLE_R("HP PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL,
PGAR_2_HPROUT_VOL, 0, 0x7f, 1),
- SOC_SINGLE("HPL PGA Bypass Playback Volume", PGAL_2_HPLOUT_VOL,
- 0, 0x7f, 1),
- SOC_SINGLE("HPR PGA Bypass Playback Volume", PGAL_2_HPROUT_VOL,
- 0, 0x7f, 1),
SOC_DOUBLE_R("HP Line2 Bypass Playback Volume", LINE2L_2_HPLOUT_VOL,
LINE2R_2_HPROUT_VOL, 0, 0x7f, 1),
@@ -291,10 +281,8 @@ static const struct snd_kcontrol_new aic3x_snd_controls[] = {
DACR1_2_HPRCOM_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("HPCOM DAC Playback Switch", HPLCOM_CTRL, HPRCOM_CTRL, 3,
0x01, 0),
- SOC_SINGLE("HPLCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL,
- 0, 0x7f, 1),
- SOC_SINGLE("HPRCOM PGA Bypass Playback Volume", PGAL_2_HPRCOM_VOL,
- 0, 0x7f, 1),
+ SOC_DOUBLE_R("HPCOM PGA Bypass Playback Volume", PGAL_2_HPLCOM_VOL,
+ PGAR_2_HPRCOM_VOL, 0, 0x7f, 1),
SOC_DOUBLE_R("HPCOM Line2 Bypass Playback Volume", LINE2L_2_HPLCOM_VOL,
LINE2R_2_HPRCOM_VOL, 0, 0x7f, 1),
@@ -345,8 +333,7 @@ SOC_DAPM_ENUM("Route", aic3x_enum[RHPCOM_ENUM]);
/* Left DAC_L1 Mixer */
static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", DACL1_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line Switch", DACL1_2_LLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", DACL1_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", DACL1_2_HPLOUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HPCOM Switch", DACL1_2_HPLCOM_VOL, 7, 1, 0),
@@ -354,8 +341,7 @@ static const struct snd_kcontrol_new aic3x_left_dac_mixer_controls[] = {
/* Right DAC_R1 Mixer */
static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", DACR1_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line Switch", DACR1_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", DACR1_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", DACR1_2_HPROUT_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HPCOM Switch", DACR1_2_HPRCOM_VOL, 7, 1, 0),
@@ -364,18 +350,14 @@ static const struct snd_kcontrol_new aic3x_right_dac_mixer_controls[] = {
/* Left PGA Mixer */
static const struct snd_kcontrol_new aic3x_left_pga_mixer_controls[] = {
SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_LADC_CTRL, 3, 1, 1),
- SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_LADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Line2L Switch", LINE2L_2_LADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_LADC_CTRL, 4, 1, 1),
- SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_LADC_CTRL, 0, 1, 1),
};
/* Right PGA Mixer */
static const struct snd_kcontrol_new aic3x_right_pga_mixer_controls[] = {
SOC_DAPM_SINGLE_AIC3X("Line1R Switch", LINE1R_2_RADC_CTRL, 3, 1, 1),
- SOC_DAPM_SINGLE_AIC3X("Line1L Switch", LINE1L_2_RADC_CTRL, 3, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Line2R Switch", LINE2R_2_RADC_CTRL, 3, 1, 1),
- SOC_DAPM_SINGLE_AIC3X("Mic3L Switch", MIC3LR_2_RADC_CTRL, 4, 1, 1),
SOC_DAPM_SINGLE_AIC3X("Mic3R Switch", MIC3LR_2_RADC_CTRL, 0, 1, 1),
};
@@ -397,42 +379,34 @@ SOC_DAPM_ENUM("Route", aic3x_enum[LINE2R_ENUM]);
/* Left PGA Bypass Mixer */
static const struct snd_kcontrol_new aic3x_left_pga_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", PGAL_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line Switch", PGAL_2_LLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", PGAL_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPL Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPR Switch", PGAL_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPLCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPRCOM Switch", PGAL_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HP Switch", PGAL_2_HPLOUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPCOM Switch", PGAL_2_HPLCOM_VOL, 7, 1, 0),
};
/* Right PGA Bypass Mixer */
static const struct snd_kcontrol_new aic3x_right_pga_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", PGAR_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line Switch", PGAR_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", PGAR_2_MONOLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPL Switch", PGAR_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPR Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPLCOM Switch", PGAR_2_HPLCOM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPRCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HP Switch", PGAR_2_HPROUT_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPCOM Switch", PGAR_2_HPRCOM_VOL, 7, 1, 0),
};
/* Left Line2 Bypass Mixer */
static const struct snd_kcontrol_new aic3x_left_line2_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", LINE2L_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line Switch", LINE2L_2_LLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", LINE2L_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", LINE2L_2_HPLOUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPLCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPCOM Switch", LINE2L_2_HPLCOM_VOL, 7, 1, 0),
};
/* Right Line2 Bypass Mixer */
static const struct snd_kcontrol_new aic3x_right_line2_bp_mixer_controls[] = {
- SOC_DAPM_SINGLE("LineL Switch", LINE2R_2_LLOPM_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("LineR Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("Line Switch", LINE2R_2_RLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("Mono Switch", LINE2R_2_MONOLOPM_VOL, 7, 1, 0),
SOC_DAPM_SINGLE("HP Switch", LINE2R_2_HPROUT_VOL, 7, 1, 0),
- SOC_DAPM_SINGLE("HPRCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
+ SOC_DAPM_SINGLE("HPCOM Switch", LINE2R_2_HPRCOM_VOL, 7, 1, 0),
};
static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
@@ -465,26 +439,22 @@ static const struct snd_soc_dapm_widget aic3x_dapm_widgets[] = {
/* Mono Output */
SND_SOC_DAPM_PGA("Mono Out", MONOLOPM_CTRL, 0, 0, NULL, 0),
- /* Inputs to Left ADC */
+ /* Left Inputs to Left ADC */
SND_SOC_DAPM_ADC("Left ADC", "Left Capture", LINE1L_2_LADC_CTRL, 2, 0),
SND_SOC_DAPM_MIXER("Left PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_left_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_left_pga_mixer_controls)),
SND_SOC_DAPM_MUX("Left Line1L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line1_mux_controls),
- SND_SOC_DAPM_MUX("Left Line1R Mux", SND_SOC_NOPM, 0, 0,
- &aic3x_left_line1_mux_controls),
SND_SOC_DAPM_MUX("Left Line2L Mux", SND_SOC_NOPM, 0, 0,
&aic3x_left_line2_mux_controls),
- /* Inputs to Right ADC */
+ /* Right Inputs to Right ADC */
SND_SOC_DAPM_ADC("Right ADC", "Right Capture",
LINE1R_2_RADC_CTRL, 2, 0),
SND_SOC_DAPM_MIXER("Right PGA Mixer", SND_SOC_NOPM, 0, 0,
&aic3x_right_pga_mixer_controls[0],
ARRAY_SIZE(aic3x_right_pga_mixer_controls)),
- SND_SOC_DAPM_MUX("Right Line1L Mux", SND_SOC_NOPM, 0, 0,
- &aic3x_right_line1_mux_controls),
SND_SOC_DAPM_MUX("Right Line1R Mux", SND_SOC_NOPM, 0, 0,
&aic3x_right_line1_mux_controls),
SND_SOC_DAPM_MUX("Right Line2R Mux", SND_SOC_NOPM, 0, 0,
@@ -561,8 +531,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left DAC Mux", "DAC_L2", "Left DAC"},
{"Left DAC Mux", "DAC_L3", "Left DAC"},
- {"Left DAC_L1 Mixer", "LineL Switch", "Left DAC Mux"},
- {"Left DAC_L1 Mixer", "LineR Switch", "Left DAC Mux"},
+ {"Left DAC_L1 Mixer", "Line Switch", "Left DAC Mux"},
{"Left DAC_L1 Mixer", "Mono Switch", "Left DAC Mux"},
{"Left DAC_L1 Mixer", "HP Switch", "Left DAC Mux"},
{"Left DAC_L1 Mixer", "HPCOM Switch", "Left DAC Mux"},
@@ -588,8 +557,7 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Right DAC Mux", "DAC_R2", "Right DAC"},
{"Right DAC Mux", "DAC_R3", "Right DAC"},
- {"Right DAC_R1 Mixer", "LineL Switch", "Right DAC Mux"},
- {"Right DAC_R1 Mixer", "LineR Switch", "Right DAC Mux"},
+ {"Right DAC_R1 Mixer", "Line Switch", "Right DAC Mux"},
{"Right DAC_R1 Mixer", "Mono Switch", "Right DAC Mux"},
{"Right DAC_R1 Mixer", "HP Switch", "Right DAC Mux"},
{"Right DAC_R1 Mixer", "HPCOM Switch", "Right DAC Mux"},
@@ -624,10 +592,8 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left Line2L Mux", "differential", "LINE2L"},
{"Left PGA Mixer", "Line1L Switch", "Left Line1L Mux"},
- {"Left PGA Mixer", "Line1R Switch", "Left Line1R Mux"},
{"Left PGA Mixer", "Line2L Switch", "Left Line2L Mux"},
{"Left PGA Mixer", "Mic3L Switch", "MIC3L"},
- {"Left PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Left ADC", NULL, "Left PGA Mixer"},
{"Left ADC", NULL, "GPIO1 dmic modclk"},
@@ -639,23 +605,18 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Right Line2R Mux", "single-ended", "LINE2R"},
{"Right Line2R Mux", "differential", "LINE2R"},
- {"Right PGA Mixer", "Line1L Switch", "Right Line1L Mux"},
{"Right PGA Mixer", "Line1R Switch", "Right Line1R Mux"},
{"Right PGA Mixer", "Line2R Switch", "Right Line2R Mux"},
- {"Right PGA Mixer", "Mic3L Switch", "MIC3L"},
{"Right PGA Mixer", "Mic3R Switch", "MIC3R"},
{"Right ADC", NULL, "Right PGA Mixer"},
{"Right ADC", NULL, "GPIO1 dmic modclk"},
/* Left PGA Bypass */
- {"Left PGA Bypass Mixer", "LineL Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "LineR Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "Line Switch", "Left PGA Mixer"},
{"Left PGA Bypass Mixer", "Mono Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPL Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPR Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPLCOM Switch", "Left PGA Mixer"},
- {"Left PGA Bypass Mixer", "HPRCOM Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HP Switch", "Left PGA Mixer"},
+ {"Left PGA Bypass Mixer", "HPCOM Switch", "Left PGA Mixer"},
{"Left HPCOM Mux", "differential of HPLOUT", "Left PGA Bypass Mixer"},
{"Left HPCOM Mux", "constant VCM", "Left PGA Bypass Mixer"},
@@ -666,13 +627,10 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left HP Out", NULL, "Left PGA Bypass Mixer"},
/* Right PGA Bypass */
- {"Right PGA Bypass Mixer", "LineL Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "LineR Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "Line Switch", "Right PGA Mixer"},
{"Right PGA Bypass Mixer", "Mono Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPL Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPR Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPLCOM Switch", "Right PGA Mixer"},
- {"Right PGA Bypass Mixer", "HPRCOM Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HP Switch", "Right PGA Mixer"},
+ {"Right PGA Bypass Mixer", "HPCOM Switch", "Right PGA Mixer"},
{"Right HPCOM Mux", "differential of HPROUT", "Right PGA Bypass Mixer"},
{"Right HPCOM Mux", "constant VCM", "Right PGA Bypass Mixer"},
@@ -685,11 +643,10 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Right HP Out", NULL, "Right PGA Bypass Mixer"},
/* Left Line2 Bypass */
- {"Left Line2 Bypass Mixer", "LineL Switch", "Left Line2L Mux"},
- {"Left Line2 Bypass Mixer", "LineR Switch", "Left Line2L Mux"},
+ {"Left Line2 Bypass Mixer", "Line Switch", "Left Line2L Mux"},
{"Left Line2 Bypass Mixer", "Mono Switch", "Left Line2L Mux"},
{"Left Line2 Bypass Mixer", "HP Switch", "Left Line2L Mux"},
- {"Left Line2 Bypass Mixer", "HPLCOM Switch", "Left Line2L Mux"},
+ {"Left Line2 Bypass Mixer", "HPCOM Switch", "Left Line2L Mux"},
{"Left HPCOM Mux", "differential of HPLOUT", "Left Line2 Bypass Mixer"},
{"Left HPCOM Mux", "constant VCM", "Left Line2 Bypass Mixer"},
@@ -700,11 +657,10 @@ static const struct snd_soc_dapm_route intercon[] = {
{"Left HP Out", NULL, "Left Line2 Bypass Mixer"},
/* Right Line2 Bypass */
- {"Right Line2 Bypass Mixer", "LineL Switch", "Right Line2R Mux"},
- {"Right Line2 Bypass Mixer", "LineR Switch", "Right Line2R Mux"},
+ {"Right Line2 Bypass Mixer", "Line Switch", "Right Line2R Mux"},
{"Right Line2 Bypass Mixer", "Mono Switch", "Right Line2R Mux"},
{"Right Line2 Bypass Mixer", "HP Switch", "Right Line2R Mux"},
- {"Right Line2 Bypass Mixer", "HPRCOM Switch", "Right Line2R Mux"},
+ {"Right Line2 Bypass Mixer", "HPCOM Switch", "Right Line2R Mux"},
{"Right HPCOM Mux", "differential of HPROUT", "Right Line2 Bypass Mixer"},
{"Right HPCOM Mux", "constant VCM", "Right Line2 Bypass Mixer"},
@@ -738,8 +694,7 @@ static int aic3x_add_widgets(struct snd_soc_codec *codec)
}
static int aic3x_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1026,41 +981,14 @@ int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio)
}
EXPORT_SYMBOL_GPL(aic3x_get_gpio);
-void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
- int headset_debounce, int button_debounce)
-{
- u8 val;
-
- val = ((detect & AIC3X_HEADSET_DETECT_MASK)
- << AIC3X_HEADSET_DETECT_SHIFT) |
- ((headset_debounce & AIC3X_HEADSET_DEBOUNCE_MASK)
- << AIC3X_HEADSET_DEBOUNCE_SHIFT) |
- ((button_debounce & AIC3X_BUTTON_DEBOUNCE_MASK)
- << AIC3X_BUTTON_DEBOUNCE_SHIFT);
-
- if (detect & AIC3X_HEADSET_DETECT_MASK)
- val |= AIC3X_HEADSET_DETECT_ENABLED;
-
- aic3x_write(codec, AIC3X_HEADSET_DETECT_CTRL_A, val);
-}
-EXPORT_SYMBOL_GPL(aic3x_set_headset_detection);
-
int aic3x_headset_detected(struct snd_soc_codec *codec)
{
u8 val;
- aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
- return (val >> 4) & 1;
+ aic3x_read(codec, AIC3X_RT_IRQ_FLAGS_REG, &val);
+ return (val >> 2) & 1;
}
EXPORT_SYMBOL_GPL(aic3x_headset_detected);
-int aic3x_button_pressed(struct snd_soc_codec *codec)
-{
- u8 val;
- aic3x_read(codec, AIC3X_HEADSET_DETECT_CTRL_B, &val);
- return (val >> 5) & 1;
-}
-EXPORT_SYMBOL_GPL(aic3x_button_pressed);
-
#define AIC3X_RATES SNDRV_PCM_RATE_8000_96000
#define AIC3X_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \
SNDRV_PCM_FMTBIT_S24_3LE | SNDRV_PCM_FMTBIT_S32_LE)
@@ -1081,6 +1009,8 @@ struct snd_soc_dai aic3x_dai = {
.formats = AIC3X_FORMATS,},
.ops = {
.hw_params = aic3x_hw_params,
+ },
+ .dai_ops = {
.digital_mute = aic3x_mute,
.set_sysclk = aic3x_set_dai_sysclk,
.set_fmt = aic3x_set_dai_fmt,
@@ -1222,7 +1152,7 @@ static int aic3x_init(struct snd_soc_device *socdev)
aic3x_add_controls(codec);
aic3x_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "aic3x: failed to register card\n");
goto card_err;
@@ -1411,18 +1341,6 @@ struct snd_soc_codec_device soc_codec_dev_aic3x = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_aic3x);
-static int __devinit aic3x_modinit(void)
-{
- return snd_soc_register_dai(&aic3x_dai);
-}
-module_init(aic3x_modinit);
-
-static void __exit aic3x_exit(void)
-{
- snd_soc_unregister_dai(&aic3x_dai);
-}
-module_exit(aic3x_exit);
-
MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver");
MODULE_AUTHOR("Vladimir Barinov");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h
index 73e35b6ec929..00a195aa02e4 100644
--- a/sound/soc/codecs/tlv320aic3x.h
+++ b/sound/soc/codecs/tlv320aic3x.h
@@ -39,9 +39,7 @@
#define AIC3X_OVRF_STATUS_AND_PLLR_REG 11
/* Audio codec digital filter control register */
#define AIC3X_CODEC_DFILT_CTRL 12
-/* Headset/button press detection register */
-#define AIC3X_HEADSET_DETECT_CTRL_A 13
-#define AIC3X_HEADSET_DETECT_CTRL_B 14
+
/* ADC PGA Gain control registers */
#define LADC_VOL 15
#define RADC_VOL 16
@@ -50,9 +48,7 @@
#define MIC3LR_2_RADC_CTRL 18
/* Line1 Input control registers */
#define LINE1L_2_LADC_CTRL 19
-#define LINE1R_2_LADC_CTRL 21
#define LINE1R_2_RADC_CTRL 22
-#define LINE1L_2_RADC_CTRL 24
/* Line2 Input control registers */
#define LINE2L_2_LADC_CTRL 20
#define LINE2R_2_RADC_CTRL 23
@@ -83,8 +79,6 @@
#define LINE2L_2_HPLOUT_VOL 45
#define LINE2R_2_HPROUT_VOL 62
#define PGAL_2_HPLOUT_VOL 46
-#define PGAL_2_HPROUT_VOL 60
-#define PGAR_2_HPLOUT_VOL 49
#define PGAR_2_HPROUT_VOL 63
#define DACL1_2_HPLOUT_VOL 47
#define DACR1_2_HPROUT_VOL 64
@@ -94,8 +88,6 @@
#define LINE2L_2_HPLCOM_VOL 52
#define LINE2R_2_HPRCOM_VOL 69
#define PGAL_2_HPLCOM_VOL 53
-#define PGAR_2_HPLCOM_VOL 56
-#define PGAL_2_HPRCOM_VOL 67
#define PGAR_2_HPRCOM_VOL 70
#define DACL1_2_HPLCOM_VOL 54
#define DACR1_2_HPRCOM_VOL 71
@@ -111,17 +103,11 @@
#define MONOLOPM_CTRL 79
/* Line Output Plus/Minus control registers */
#define LINE2L_2_LLOPM_VOL 80
-#define LINE2L_2_RLOPM_VOL 87
-#define LINE2R_2_LLOPM_VOL 83
#define LINE2R_2_RLOPM_VOL 90
#define PGAL_2_LLOPM_VOL 81
-#define PGAL_2_RLOPM_VOL 88
-#define PGAR_2_LLOPM_VOL 84
#define PGAR_2_RLOPM_VOL 91
#define DACL1_2_LLOPM_VOL 82
-#define DACL1_2_RLOPM_VOL 89
#define DACR1_2_RLOPM_VOL 92
-#define DACR1_2_LLOPM_VOL 85
#define LLOPM_CTRL 86
#define RLOPM_CTRL 93
/* GPIO/IRQ registers */
@@ -235,49 +221,7 @@ enum {
void aic3x_set_gpio(struct snd_soc_codec *codec, int gpio, int state);
int aic3x_get_gpio(struct snd_soc_codec *codec, int gpio);
-
-/* headset detection / button API */
-
-/* The AIC3x supports detection of stereo headsets (GND + left + right signal)
- * and cellular headsets (GND + speaker output + microphone input).
- * It is recommended to enable MIC bias for this function to work properly.
- * For more information, please refer to the datasheet. */
-enum {
- AIC3X_HEADSET_DETECT_OFF = 0,
- AIC3X_HEADSET_DETECT_STEREO = 1,
- AIC3X_HEADSET_DETECT_CELLULAR = 2,
- AIC3X_HEADSET_DETECT_BOTH = 3
-};
-
-enum {
- AIC3X_HEADSET_DEBOUNCE_16MS = 0,
- AIC3X_HEADSET_DEBOUNCE_32MS = 1,
- AIC3X_HEADSET_DEBOUNCE_64MS = 2,
- AIC3X_HEADSET_DEBOUNCE_128MS = 3,
- AIC3X_HEADSET_DEBOUNCE_256MS = 4,
- AIC3X_HEADSET_DEBOUNCE_512MS = 5
-};
-
-enum {
- AIC3X_BUTTON_DEBOUNCE_0MS = 0,
- AIC3X_BUTTON_DEBOUNCE_8MS = 1,
- AIC3X_BUTTON_DEBOUNCE_16MS = 2,
- AIC3X_BUTTON_DEBOUNCE_32MS = 3
-};
-
-#define AIC3X_HEADSET_DETECT_ENABLED 0x80
-#define AIC3X_HEADSET_DETECT_SHIFT 5
-#define AIC3X_HEADSET_DETECT_MASK 3
-#define AIC3X_HEADSET_DEBOUNCE_SHIFT 2
-#define AIC3X_HEADSET_DEBOUNCE_MASK 7
-#define AIC3X_BUTTON_DEBOUNCE_SHIFT 0
-#define AIC3X_BUTTON_DEBOUNCE_MASK 3
-
-/* see the enums above for valid parameters to this function */
-void aic3x_set_headset_detection(struct snd_soc_codec *codec, int detect,
- int headset_debounce, int button_debounce);
int aic3x_headset_detected(struct snd_soc_codec *codec);
-int aic3x_button_pressed(struct snd_soc_codec *codec);
struct aic3x_setup_data {
int i2c_bus;
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
deleted file mode 100644
index 373daa486cea..000000000000
--- a/sound/soc/codecs/twl4030.c
+++ /dev/null
@@ -1,1292 +0,0 @@
-/*
- * ALSA SoC TWL4030 codec driver
- *
- * Author: Steve Sakoman, <steve@sakoman.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/i2c/twl4030.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/initval.h>
-#include <sound/tlv.h>
-
-#include "twl4030.h"
-
-/*
- * twl4030 register cache & default register settings
- */
-static const u8 twl4030_reg[TWL4030_CACHEREGNUM] = {
- 0x00, /* this register not used */
- 0x93, /* REG_CODEC_MODE (0x1) */
- 0xc3, /* REG_OPTION (0x2) */
- 0x00, /* REG_UNKNOWN (0x3) */
- 0x00, /* REG_MICBIAS_CTL (0x4) */
- 0x20, /* REG_ANAMICL (0x5) */
- 0x00, /* REG_ANAMICR (0x6) */
- 0x00, /* REG_AVADC_CTL (0x7) */
- 0x00, /* REG_ADCMICSEL (0x8) */
- 0x00, /* REG_DIGMIXING (0x9) */
- 0x0c, /* REG_ATXL1PGA (0xA) */
- 0x0c, /* REG_ATXR1PGA (0xB) */
- 0x00, /* REG_AVTXL2PGA (0xC) */
- 0x00, /* REG_AVTXR2PGA (0xD) */
- 0x01, /* REG_AUDIO_IF (0xE) */
- 0x00, /* REG_VOICE_IF (0xF) */
- 0x00, /* REG_ARXR1PGA (0x10) */
- 0x00, /* REG_ARXL1PGA (0x11) */
- 0x6c, /* REG_ARXR2PGA (0x12) */
- 0x6c, /* REG_ARXL2PGA (0x13) */
- 0x00, /* REG_VRXPGA (0x14) */
- 0x00, /* REG_VSTPGA (0x15) */
- 0x00, /* REG_VRX2ARXPGA (0x16) */
- 0x0c, /* REG_AVDAC_CTL (0x17) */
- 0x00, /* REG_ARX2VTXPGA (0x18) */
- 0x00, /* REG_ARXL1_APGA_CTL (0x19) */
- 0x00, /* REG_ARXR1_APGA_CTL (0x1A) */
- 0x4b, /* REG_ARXL2_APGA_CTL (0x1B) */
- 0x4b, /* REG_ARXR2_APGA_CTL (0x1C) */
- 0x00, /* REG_ATX2ARXPGA (0x1D) */
- 0x00, /* REG_BT_IF (0x1E) */
- 0x00, /* REG_BTPGA (0x1F) */
- 0x00, /* REG_BTSTPGA (0x20) */
- 0x00, /* REG_EAR_CTL (0x21) */
- 0x24, /* REG_HS_SEL (0x22) */
- 0x0a, /* REG_HS_GAIN_SET (0x23) */
- 0x00, /* REG_HS_POPN_SET (0x24) */
- 0x00, /* REG_PREDL_CTL (0x25) */
- 0x00, /* REG_PREDR_CTL (0x26) */
- 0x00, /* REG_PRECKL_CTL (0x27) */
- 0x00, /* REG_PRECKR_CTL (0x28) */
- 0x00, /* REG_HFL_CTL (0x29) */
- 0x00, /* REG_HFR_CTL (0x2A) */
- 0x00, /* REG_ALC_CTL (0x2B) */
- 0x00, /* REG_ALC_SET1 (0x2C) */
- 0x00, /* REG_ALC_SET2 (0x2D) */
- 0x00, /* REG_BOOST_CTL (0x2E) */
- 0x00, /* REG_SOFTVOL_CTL (0x2F) */
- 0x00, /* REG_DTMF_FREQSEL (0x30) */
- 0x00, /* REG_DTMF_TONEXT1H (0x31) */
- 0x00, /* REG_DTMF_TONEXT1L (0x32) */
- 0x00, /* REG_DTMF_TONEXT2H (0x33) */
- 0x00, /* REG_DTMF_TONEXT2L (0x34) */
- 0x00, /* REG_DTMF_TONOFF (0x35) */
- 0x00, /* REG_DTMF_WANONOFF (0x36) */
- 0x00, /* REG_I2S_RX_SCRAMBLE_H (0x37) */
- 0x00, /* REG_I2S_RX_SCRAMBLE_M (0x38) */
- 0x00, /* REG_I2S_RX_SCRAMBLE_L (0x39) */
- 0x16, /* REG_APLL_CTL (0x3A) */
- 0x00, /* REG_DTMF_CTL (0x3B) */
- 0x00, /* REG_DTMF_PGA_CTL2 (0x3C) */
- 0x00, /* REG_DTMF_PGA_CTL1 (0x3D) */
- 0x00, /* REG_MISC_SET_1 (0x3E) */
- 0x00, /* REG_PCMBTMUX (0x3F) */
- 0x00, /* not used (0x40) */
- 0x00, /* not used (0x41) */
- 0x00, /* not used (0x42) */
- 0x00, /* REG_RX_PATH_SEL (0x43) */
- 0x00, /* REG_VDL_APGA_CTL (0x44) */
- 0x00, /* REG_VIBRA_CTL (0x45) */
- 0x00, /* REG_VIBRA_SET (0x46) */
- 0x00, /* REG_VIBRA_PWM_SET (0x47) */
- 0x00, /* REG_ANAMIC_GAIN (0x48) */
- 0x00, /* REG_MISC_SET_2 (0x49) */
-};
-
-/*
- * read twl4030 register cache
- */
-static inline unsigned int twl4030_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u8 *cache = codec->reg_cache;
-
- return cache[reg];
-}
-
-/*
- * write twl4030 register cache
- */
-static inline void twl4030_write_reg_cache(struct snd_soc_codec *codec,
- u8 reg, u8 value)
-{
- u8 *cache = codec->reg_cache;
-
- if (reg >= TWL4030_CACHEREGNUM)
- return;
- cache[reg] = value;
-}
-
-/*
- * write to the twl4030 register space
- */
-static int twl4030_write(struct snd_soc_codec *codec,
- unsigned int reg, unsigned int value)
-{
- twl4030_write_reg_cache(codec, reg, value);
- return twl4030_i2c_write_u8(TWL4030_MODULE_AUDIO_VOICE, value, reg);
-}
-
-static void twl4030_clear_codecpdz(struct snd_soc_codec *codec)
-{
- u8 mode;
-
- mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
- twl4030_write(codec, TWL4030_REG_CODEC_MODE,
- mode & ~TWL4030_CODECPDZ);
-
- /* REVISIT: this delay is present in TI sample drivers */
- /* but there seems to be no TRM requirement for it */
- udelay(10);
-}
-
-static void twl4030_set_codecpdz(struct snd_soc_codec *codec)
-{
- u8 mode;
-
- mode = twl4030_read_reg_cache(codec, TWL4030_REG_CODEC_MODE);
- twl4030_write(codec, TWL4030_REG_CODEC_MODE,
- mode | TWL4030_CODECPDZ);
-
- /* REVISIT: this delay is present in TI sample drivers */
- /* but there seems to be no TRM requirement for it */
- udelay(10);
-}
-
-static void twl4030_init_chip(struct snd_soc_codec *codec)
-{
- int i;
-
- /* clear CODECPDZ prior to setting register defaults */
- twl4030_clear_codecpdz(codec);
-
- /* set all audio section registers to reasonable defaults */
- for (i = TWL4030_REG_OPTION; i <= TWL4030_REG_MISC_SET_2; i++)
- twl4030_write(codec, i, twl4030_reg[i]);
-
-}
-
-/* Earpiece */
-static const char *twl4030_earpiece_texts[] =
- {"Off", "DACL1", "DACL2", "Invalid",
- "DACR1"};
-
-static const struct soc_enum twl4030_earpiece_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_EAR_CTL, 1,
- ARRAY_SIZE(twl4030_earpiece_texts),
- twl4030_earpiece_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_earpiece_control =
-SOC_DAPM_ENUM("Route", twl4030_earpiece_enum);
-
-/* PreDrive Left */
-static const char *twl4030_predrivel_texts[] =
- {"Off", "DACL1", "DACL2", "Invalid",
- "DACR2"};
-
-static const struct soc_enum twl4030_predrivel_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_PREDL_CTL, 1,
- ARRAY_SIZE(twl4030_predrivel_texts),
- twl4030_predrivel_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_predrivel_control =
-SOC_DAPM_ENUM("Route", twl4030_predrivel_enum);
-
-/* PreDrive Right */
-static const char *twl4030_predriver_texts[] =
- {"Off", "DACR1", "DACR2", "Invalid",
- "DACL2"};
-
-static const struct soc_enum twl4030_predriver_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_PREDR_CTL, 1,
- ARRAY_SIZE(twl4030_predriver_texts),
- twl4030_predriver_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_predriver_control =
-SOC_DAPM_ENUM("Route", twl4030_predriver_enum);
-
-/* Headset Left */
-static const char *twl4030_hsol_texts[] =
- {"Off", "DACL1", "DACL2"};
-
-static const struct soc_enum twl4030_hsol_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 1,
- ARRAY_SIZE(twl4030_hsol_texts),
- twl4030_hsol_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_hsol_control =
-SOC_DAPM_ENUM("Route", twl4030_hsol_enum);
-
-/* Headset Right */
-static const char *twl4030_hsor_texts[] =
- {"Off", "DACR1", "DACR2"};
-
-static const struct soc_enum twl4030_hsor_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_HS_SEL, 4,
- ARRAY_SIZE(twl4030_hsor_texts),
- twl4030_hsor_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_hsor_control =
-SOC_DAPM_ENUM("Route", twl4030_hsor_enum);
-
-/* Carkit Left */
-static const char *twl4030_carkitl_texts[] =
- {"Off", "DACL1", "DACL2"};
-
-static const struct soc_enum twl4030_carkitl_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_PRECKL_CTL, 1,
- ARRAY_SIZE(twl4030_carkitl_texts),
- twl4030_carkitl_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_carkitl_control =
-SOC_DAPM_ENUM("Route", twl4030_carkitl_enum);
-
-/* Carkit Right */
-static const char *twl4030_carkitr_texts[] =
- {"Off", "DACR1", "DACR2"};
-
-static const struct soc_enum twl4030_carkitr_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_PRECKR_CTL, 1,
- ARRAY_SIZE(twl4030_carkitr_texts),
- twl4030_carkitr_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_carkitr_control =
-SOC_DAPM_ENUM("Route", twl4030_carkitr_enum);
-
-/* Handsfree Left */
-static const char *twl4030_handsfreel_texts[] =
- {"Voice", "DACL1", "DACL2", "DACR2"};
-
-static const struct soc_enum twl4030_handsfreel_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_HFL_CTL, 0,
- ARRAY_SIZE(twl4030_handsfreel_texts),
- twl4030_handsfreel_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_handsfreel_control =
-SOC_DAPM_ENUM("Route", twl4030_handsfreel_enum);
-
-/* Handsfree Right */
-static const char *twl4030_handsfreer_texts[] =
- {"Voice", "DACR1", "DACR2", "DACL2"};
-
-static const struct soc_enum twl4030_handsfreer_enum =
- SOC_ENUM_SINGLE(TWL4030_REG_HFR_CTL, 0,
- ARRAY_SIZE(twl4030_handsfreer_texts),
- twl4030_handsfreer_texts);
-
-static const struct snd_kcontrol_new twl4030_dapm_handsfreer_control =
-SOC_DAPM_ENUM("Route", twl4030_handsfreer_enum);
-
-static int outmixer_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *kcontrol, int event)
-{
- struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
- int ret = 0;
- int val;
-
- switch (e->reg) {
- case TWL4030_REG_PREDL_CTL:
- case TWL4030_REG_PREDR_CTL:
- case TWL4030_REG_EAR_CTL:
- val = w->value >> e->shift_l;
- if (val == 3) {
- printk(KERN_WARNING
- "Invalid MUX setting for register 0x%02x (%d)\n",
- e->reg, val);
- ret = -1;
- }
- break;
- }
-
- return ret;
-}
-
-/*
- * Some of the gain controls in TWL (mostly those which are associated with
- * the outputs) are implemented in an interesting way:
- * 0x0 : Power down (mute)
- * 0x1 : 6dB
- * 0x2 : 0 dB
- * 0x3 : -6 dB
- * Inverting not going to help with these.
- * Custom volsw and volsw_2r get/put functions to handle these gain bits.
- */
-#define SOC_DOUBLE_TLV_TWL4030(xname, xreg, shift_left, shift_right, xmax,\
- xinvert, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE,\
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw, \
- .get = snd_soc_get_volsw_twl4030, \
- .put = snd_soc_put_volsw_twl4030, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = xreg, .shift = shift_left, .rshift = shift_right,\
- .max = xmax, .invert = xinvert} }
-#define SOC_DOUBLE_R_TLV_TWL4030(xname, reg_left, reg_right, xshift, xmax,\
- xinvert, tlv_array) \
-{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
- .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
- SNDRV_CTL_ELEM_ACCESS_READWRITE,\
- .tlv.p = (tlv_array), \
- .info = snd_soc_info_volsw_2r, \
- .get = snd_soc_get_volsw_r2_twl4030,\
- .put = snd_soc_put_volsw_r2_twl4030, \
- .private_value = (unsigned long)&(struct soc_mixer_control) \
- {.reg = reg_left, .rreg = reg_right, .shift = xshift, \
- .rshift = xshift, .max = xmax, .invert = xinvert} }
-#define SOC_SINGLE_TLV_TWL4030(xname, xreg, xshift, xmax, xinvert, tlv_array) \
- SOC_DOUBLE_TLV_TWL4030(xname, xreg, xshift, xshift, xmax, \
- xinvert, tlv_array)
-
-static int snd_soc_get_volsw_twl4030(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int reg = mc->reg;
- unsigned int shift = mc->shift;
- unsigned int rshift = mc->rshift;
- int max = mc->max;
- int mask = (1 << fls(max)) - 1;
-
- ucontrol->value.integer.value[0] =
- (snd_soc_read(codec, reg) >> shift) & mask;
- if (ucontrol->value.integer.value[0])
- ucontrol->value.integer.value[0] =
- max + 1 - ucontrol->value.integer.value[0];
-
- if (shift != rshift) {
- ucontrol->value.integer.value[1] =
- (snd_soc_read(codec, reg) >> rshift) & mask;
- if (ucontrol->value.integer.value[1])
- ucontrol->value.integer.value[1] =
- max + 1 - ucontrol->value.integer.value[1];
- }
-
- return 0;
-}
-
-static int snd_soc_put_volsw_twl4030(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int reg = mc->reg;
- unsigned int shift = mc->shift;
- unsigned int rshift = mc->rshift;
- int max = mc->max;
- int mask = (1 << fls(max)) - 1;
- unsigned short val, val2, val_mask;
-
- val = (ucontrol->value.integer.value[0] & mask);
-
- val_mask = mask << shift;
- if (val)
- val = max + 1 - val;
- val = val << shift;
- if (shift != rshift) {
- val2 = (ucontrol->value.integer.value[1] & mask);
- val_mask |= mask << rshift;
- if (val2)
- val2 = max + 1 - val2;
- val |= val2 << rshift;
- }
- return snd_soc_update_bits(codec, reg, val_mask, val);
-}
-
-static int snd_soc_get_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int reg = mc->reg;
- unsigned int reg2 = mc->rreg;
- unsigned int shift = mc->shift;
- int max = mc->max;
- int mask = (1<<fls(max))-1;
-
- ucontrol->value.integer.value[0] =
- (snd_soc_read(codec, reg) >> shift) & mask;
- ucontrol->value.integer.value[1] =
- (snd_soc_read(codec, reg2) >> shift) & mask;
-
- if (ucontrol->value.integer.value[0])
- ucontrol->value.integer.value[0] =
- max + 1 - ucontrol->value.integer.value[0];
- if (ucontrol->value.integer.value[1])
- ucontrol->value.integer.value[1] =
- max + 1 - ucontrol->value.integer.value[1];
-
- return 0;
-}
-
-static int snd_soc_put_volsw_r2_twl4030(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct soc_mixer_control *mc =
- (struct soc_mixer_control *)kcontrol->private_value;
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
- unsigned int reg = mc->reg;
- unsigned int reg2 = mc->rreg;
- unsigned int shift = mc->shift;
- int max = mc->max;
- int mask = (1 << fls(max)) - 1;
- int err;
- unsigned short val, val2, val_mask;
-
- val_mask = mask << shift;
- val = (ucontrol->value.integer.value[0] & mask);
- val2 = (ucontrol->value.integer.value[1] & mask);
-
- if (val)
- val = max + 1 - val;
- if (val2)
- val2 = max + 1 - val2;
-
- val = val << shift;
- val2 = val2 << shift;
-
- err = snd_soc_update_bits(codec, reg, val_mask, val);
- if (err < 0)
- return err;
-
- err = snd_soc_update_bits(codec, reg2, val_mask, val2);
- return err;
-}
-
-static int twl4030_get_left_input(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_codec *codec = kcontrol->private_data;
- u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
- int result = 0;
-
- /* one bit must be set a time */
- reg &= TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
- | TWL4030_MAINMIC_EN;
- if (reg != 0) {
- result++;
- while ((reg & 1) == 0) {
- result++;
- reg >>= 1;
- }
- }
-
- ucontrol->value.integer.value[0] = result;
- return 0;
-}
-
-static int twl4030_put_left_input(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_codec *codec = kcontrol->private_data;
- int value = ucontrol->value.integer.value[0];
- u8 anamicl, micbias, avadc_ctl;
-
- anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
- anamicl &= ~(TWL4030_CKMIC_EN | TWL4030_AUXL_EN | TWL4030_HSMIC_EN
- | TWL4030_MAINMIC_EN);
- micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
- micbias &= ~(TWL4030_HSMICBIAS_EN | TWL4030_MICBIAS1_EN);
- avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
-
- switch (value) {
- case 1:
- anamicl |= TWL4030_MAINMIC_EN;
- micbias |= TWL4030_MICBIAS1_EN;
- break;
- case 2:
- anamicl |= TWL4030_HSMIC_EN;
- micbias |= TWL4030_HSMICBIAS_EN;
- break;
- case 3:
- anamicl |= TWL4030_AUXL_EN;
- break;
- case 4:
- anamicl |= TWL4030_CKMIC_EN;
- break;
- default:
- break;
- }
-
- /* If some input is selected, enable amp and ADC */
- if (value != 0) {
- anamicl |= TWL4030_MICAMPL_EN;
- avadc_ctl |= TWL4030_ADCL_EN;
- } else {
- anamicl &= ~TWL4030_MICAMPL_EN;
- avadc_ctl &= ~TWL4030_ADCL_EN;
- }
-
- twl4030_write(codec, TWL4030_REG_ANAMICL, anamicl);
- twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
- twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
-
- return 1;
-}
-
-static int twl4030_get_right_input(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_codec *codec = kcontrol->private_data;
- u8 reg = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
- int value = 0;
-
- reg &= TWL4030_SUBMIC_EN|TWL4030_AUXR_EN;
- switch (reg) {
- case TWL4030_SUBMIC_EN:
- value = 1;
- break;
- case TWL4030_AUXR_EN:
- value = 2;
- break;
- default:
- break;
- }
-
- ucontrol->value.integer.value[0] = value;
- return 0;
-}
-
-static int twl4030_put_right_input(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_codec *codec = kcontrol->private_data;
- int value = ucontrol->value.integer.value[0];
- u8 anamicr, micbias, avadc_ctl;
-
- anamicr = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICR);
- anamicr &= ~(TWL4030_SUBMIC_EN|TWL4030_AUXR_EN);
- micbias = twl4030_read_reg_cache(codec, TWL4030_REG_MICBIAS_CTL);
- micbias &= ~TWL4030_MICBIAS2_EN;
- avadc_ctl = twl4030_read_reg_cache(codec, TWL4030_REG_AVADC_CTL);
-
- switch (value) {
- case 1:
- anamicr |= TWL4030_SUBMIC_EN;
- micbias |= TWL4030_MICBIAS2_EN;
- break;
- case 2:
- anamicr |= TWL4030_AUXR_EN;
- break;
- default:
- break;
- }
-
- if (value != 0) {
- anamicr |= TWL4030_MICAMPR_EN;
- avadc_ctl |= TWL4030_ADCR_EN;
- } else {
- anamicr &= ~TWL4030_MICAMPR_EN;
- avadc_ctl &= ~TWL4030_ADCR_EN;
- }
-
- twl4030_write(codec, TWL4030_REG_ANAMICR, anamicr);
- twl4030_write(codec, TWL4030_REG_MICBIAS_CTL, micbias);
- twl4030_write(codec, TWL4030_REG_AVADC_CTL, avadc_ctl);
-
- return 1;
-}
-
-static const char *twl4030_left_in_sel[] = {
- "None",
- "Main Mic",
- "Headset Mic",
- "Line In",
- "Carkit Mic",
-};
-
-static const char *twl4030_right_in_sel[] = {
- "None",
- "Sub Mic",
- "Line In",
-};
-
-static const struct soc_enum twl4030_left_input_mux =
- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_left_in_sel),
- twl4030_left_in_sel);
-
-static const struct soc_enum twl4030_right_input_mux =
- SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(twl4030_right_in_sel),
- twl4030_right_in_sel);
-
-/*
- * FGAIN volume control:
- * from -62 to 0 dB in 1 dB steps (mute instead of -63 dB)
- */
-static DECLARE_TLV_DB_SCALE(digital_fine_tlv, -6300, 100, 1);
-
-/*
- * CGAIN volume control:
- * 0 dB to 12 dB in 6 dB steps
- * value 2 and 3 means 12 dB
- */
-static DECLARE_TLV_DB_SCALE(digital_coarse_tlv, 0, 600, 0);
-
-/*
- * Analog playback gain
- * -24 dB to 12 dB in 2 dB steps
- */
-static DECLARE_TLV_DB_SCALE(analog_tlv, -2400, 200, 0);
-
-/*
- * Gain controls tied to outputs
- * -6 dB to 6 dB in 6 dB steps (mute instead of -12)
- */
-static DECLARE_TLV_DB_SCALE(output_tvl, -1200, 600, 1);
-
-/*
- * Capture gain after the ADCs
- * from 0 dB to 31 dB in 1 dB steps
- */
-static DECLARE_TLV_DB_SCALE(digital_capture_tlv, 0, 100, 0);
-
-/*
- * Gain control for input amplifiers
- * 0 dB to 30 dB in 6 dB steps
- */
-static DECLARE_TLV_DB_SCALE(input_gain_tlv, 0, 600, 0);
-
-static const struct snd_kcontrol_new twl4030_snd_controls[] = {
- /* Common playback gain controls */
- SOC_DOUBLE_R_TLV("DAC1 Digital Fine Playback Volume",
- TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
- 0, 0x3f, 0, digital_fine_tlv),
- SOC_DOUBLE_R_TLV("DAC2 Digital Fine Playback Volume",
- TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
- 0, 0x3f, 0, digital_fine_tlv),
-
- SOC_DOUBLE_R_TLV("DAC1 Digital Coarse Playback Volume",
- TWL4030_REG_ARXL1PGA, TWL4030_REG_ARXR1PGA,
- 6, 0x2, 0, digital_coarse_tlv),
- SOC_DOUBLE_R_TLV("DAC2 Digital Coarse Playback Volume",
- TWL4030_REG_ARXL2PGA, TWL4030_REG_ARXR2PGA,
- 6, 0x2, 0, digital_coarse_tlv),
-
- SOC_DOUBLE_R_TLV("DAC1 Analog Playback Volume",
- TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL,
- 3, 0x12, 1, analog_tlv),
- SOC_DOUBLE_R_TLV("DAC2 Analog Playback Volume",
- TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
- 3, 0x12, 1, analog_tlv),
- SOC_DOUBLE_R("DAC1 Analog Playback Switch",
- TWL4030_REG_ARXL1_APGA_CTL, TWL4030_REG_ARXR1_APGA_CTL,
- 1, 1, 0),
- SOC_DOUBLE_R("DAC2 Analog Playback Switch",
- TWL4030_REG_ARXL2_APGA_CTL, TWL4030_REG_ARXR2_APGA_CTL,
- 1, 1, 0),
-
- /* Separate output gain controls */
- SOC_DOUBLE_R_TLV_TWL4030("PreDriv Playback Volume",
- TWL4030_REG_PREDL_CTL, TWL4030_REG_PREDR_CTL,
- 4, 3, 0, output_tvl),
-
- SOC_DOUBLE_TLV_TWL4030("Headset Playback Volume",
- TWL4030_REG_HS_GAIN_SET, 0, 2, 3, 0, output_tvl),
-
- SOC_DOUBLE_R_TLV_TWL4030("Carkit Playback Volume",
- TWL4030_REG_PRECKL_CTL, TWL4030_REG_PRECKR_CTL,
- 4, 3, 0, output_tvl),
-
- SOC_SINGLE_TLV_TWL4030("Earpiece Playback Volume",
- TWL4030_REG_EAR_CTL, 4, 3, 0, output_tvl),
-
- /* Common capture gain controls */
- SOC_DOUBLE_R_TLV("Capture Volume",
- TWL4030_REG_ATXL1PGA, TWL4030_REG_ATXR1PGA,
- 0, 0x1f, 0, digital_capture_tlv),
-
- SOC_DOUBLE_TLV("Input Boost Volume", TWL4030_REG_ANAMIC_GAIN,
- 0, 3, 5, 0, input_gain_tlv),
-
- /* Input source controls */
- SOC_ENUM_EXT("Left Input Source", twl4030_left_input_mux,
- twl4030_get_left_input, twl4030_put_left_input),
- SOC_ENUM_EXT("Right Input Source", twl4030_right_input_mux,
- twl4030_get_right_input, twl4030_put_right_input),
-};
-
-/* add non dapm controls */
-static int twl4030_add_controls(struct snd_soc_codec *codec)
-{
- int err, i;
-
- for (i = 0; i < ARRAY_SIZE(twl4030_snd_controls); i++) {
- err = snd_ctl_add(codec->card,
- snd_soc_cnew(&twl4030_snd_controls[i],
- codec, NULL));
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
- SND_SOC_DAPM_INPUT("INL"),
- SND_SOC_DAPM_INPUT("INR"),
-
- SND_SOC_DAPM_OUTPUT("OUTL"),
- SND_SOC_DAPM_OUTPUT("OUTR"),
- SND_SOC_DAPM_OUTPUT("EARPIECE"),
- SND_SOC_DAPM_OUTPUT("PREDRIVEL"),
- SND_SOC_DAPM_OUTPUT("PREDRIVER"),
- SND_SOC_DAPM_OUTPUT("HSOL"),
- SND_SOC_DAPM_OUTPUT("HSOR"),
- SND_SOC_DAPM_OUTPUT("HFL"),
- SND_SOC_DAPM_OUTPUT("HFR"),
-
- /* DACs */
- SND_SOC_DAPM_DAC("DACR1", "Right Front Playback",
- TWL4030_REG_AVDAC_CTL, 0, 0),
- SND_SOC_DAPM_DAC("DACL1", "Left Front Playback",
- TWL4030_REG_AVDAC_CTL, 1, 0),
- SND_SOC_DAPM_DAC("DACR2", "Right Rear Playback",
- TWL4030_REG_AVDAC_CTL, 2, 0),
- SND_SOC_DAPM_DAC("DACL2", "Left Rear Playback",
- TWL4030_REG_AVDAC_CTL, 3, 0),
-
- /* Analog PGAs */
- SND_SOC_DAPM_PGA("ARXR1_APGA", TWL4030_REG_ARXR1_APGA_CTL,
- 0, 0, NULL, 0),
- SND_SOC_DAPM_PGA("ARXL1_APGA", TWL4030_REG_ARXL1_APGA_CTL,
- 0, 0, NULL, 0),
- SND_SOC_DAPM_PGA("ARXR2_APGA", TWL4030_REG_ARXR2_APGA_CTL,
- 0, 0, NULL, 0),
- SND_SOC_DAPM_PGA("ARXL2_APGA", TWL4030_REG_ARXL2_APGA_CTL,
- 0, 0, NULL, 0),
-
- /* Output MUX controls */
- /* Earpiece */
- SND_SOC_DAPM_MUX_E("Earpiece Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_earpiece_control, outmixer_event,
- SND_SOC_DAPM_PRE_REG),
- /* PreDrivL/R */
- SND_SOC_DAPM_MUX_E("PredriveL Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_predrivel_control, outmixer_event,
- SND_SOC_DAPM_PRE_REG),
- SND_SOC_DAPM_MUX_E("PredriveR Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_predriver_control, outmixer_event,
- SND_SOC_DAPM_PRE_REG),
- /* HeadsetL/R */
- SND_SOC_DAPM_MUX("HeadsetL Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_hsol_control),
- SND_SOC_DAPM_MUX("HeadsetR Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_hsor_control),
- /* CarkitL/R */
- SND_SOC_DAPM_MUX("CarkitL Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_carkitl_control),
- SND_SOC_DAPM_MUX("CarkitR Mux", SND_SOC_NOPM, 0, 0,
- &twl4030_dapm_carkitr_control),
- /* HandsfreeL/R */
- SND_SOC_DAPM_MUX("HandsfreeL Mux", TWL4030_REG_HFL_CTL, 5, 0,
- &twl4030_dapm_handsfreel_control),
- SND_SOC_DAPM_MUX("HandsfreeR Mux", TWL4030_REG_HFR_CTL, 5, 0,
- &twl4030_dapm_handsfreer_control),
-
- SND_SOC_DAPM_ADC("ADCL", "Left Capture", SND_SOC_NOPM, 0, 0),
- SND_SOC_DAPM_ADC("ADCR", "Right Capture", SND_SOC_NOPM, 0, 0),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
- {"ARXL1_APGA", NULL, "DACL1"},
- {"ARXR1_APGA", NULL, "DACR1"},
- {"ARXL2_APGA", NULL, "DACL2"},
- {"ARXR2_APGA", NULL, "DACR2"},
-
- /* Internal playback routings */
- /* Earpiece */
- {"Earpiece Mux", "DACL1", "ARXL1_APGA"},
- {"Earpiece Mux", "DACL2", "ARXL2_APGA"},
- {"Earpiece Mux", "DACR1", "ARXR1_APGA"},
- /* PreDrivL */
- {"PredriveL Mux", "DACL1", "ARXL1_APGA"},
- {"PredriveL Mux", "DACL2", "ARXL2_APGA"},
- {"PredriveL Mux", "DACR2", "ARXR2_APGA"},
- /* PreDrivR */
- {"PredriveR Mux", "DACR1", "ARXR1_APGA"},
- {"PredriveR Mux", "DACR2", "ARXR2_APGA"},
- {"PredriveR Mux", "DACL2", "ARXL2_APGA"},
- /* HeadsetL */
- {"HeadsetL Mux", "DACL1", "ARXL1_APGA"},
- {"HeadsetL Mux", "DACL2", "ARXL2_APGA"},
- /* HeadsetR */
- {"HeadsetR Mux", "DACR1", "ARXR1_APGA"},
- {"HeadsetR Mux", "DACR2", "ARXR2_APGA"},
- /* CarkitL */
- {"CarkitL Mux", "DACL1", "ARXL1_APGA"},
- {"CarkitL Mux", "DACL2", "ARXL2_APGA"},
- /* CarkitR */
- {"CarkitR Mux", "DACR1", "ARXR1_APGA"},
- {"CarkitR Mux", "DACR2", "ARXR2_APGA"},
- /* HandsfreeL */
- {"HandsfreeL Mux", "DACL1", "ARXL1_APGA"},
- {"HandsfreeL Mux", "DACL2", "ARXL2_APGA"},
- {"HandsfreeL Mux", "DACR2", "ARXR2_APGA"},
- /* HandsfreeR */
- {"HandsfreeR Mux", "DACR1", "ARXR1_APGA"},
- {"HandsfreeR Mux", "DACR2", "ARXR2_APGA"},
- {"HandsfreeR Mux", "DACL2", "ARXL2_APGA"},
-
- /* outputs */
- {"OUTL", NULL, "ARXL2_APGA"},
- {"OUTR", NULL, "ARXR2_APGA"},
- {"EARPIECE", NULL, "Earpiece Mux"},
- {"PREDRIVEL", NULL, "PredriveL Mux"},
- {"PREDRIVER", NULL, "PredriveR Mux"},
- {"HSOL", NULL, "HeadsetL Mux"},
- {"HSOR", NULL, "HeadsetR Mux"},
- {"CARKITL", NULL, "CarkitL Mux"},
- {"CARKITR", NULL, "CarkitR Mux"},
- {"HFL", NULL, "HandsfreeL Mux"},
- {"HFR", NULL, "HandsfreeR Mux"},
-
- /* inputs */
- {"ADCL", NULL, "INL"},
- {"ADCR", NULL, "INR"},
-};
-
-static int twl4030_add_widgets(struct snd_soc_codec *codec)
-{
- snd_soc_dapm_new_controls(codec, twl4030_dapm_widgets,
- ARRAY_SIZE(twl4030_dapm_widgets));
-
- snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
-
- snd_soc_dapm_new_widgets(codec);
- return 0;
-}
-
-static void twl4030_power_up(struct snd_soc_codec *codec)
-{
- u8 anamicl, regmisc1, byte, popn;
- int i = 0;
-
- /* set CODECPDZ to turn on codec */
- twl4030_set_codecpdz(codec);
-
- /* initiate offset cancellation */
- anamicl = twl4030_read_reg_cache(codec, TWL4030_REG_ANAMICL);
- twl4030_write(codec, TWL4030_REG_ANAMICL,
- anamicl | TWL4030_CNCL_OFFSET_START);
-
- /* wait for offset cancellation to complete */
- do {
- /* this takes a little while, so don't slam i2c */
- udelay(2000);
- twl4030_i2c_read_u8(TWL4030_MODULE_AUDIO_VOICE, &byte,
- TWL4030_REG_ANAMICL);
- } while ((i++ < 100) &&
- ((byte & TWL4030_CNCL_OFFSET_START) ==
- TWL4030_CNCL_OFFSET_START));
-
- /* anti-pop when changing analog gain */
- regmisc1 = twl4030_read_reg_cache(codec, TWL4030_REG_MISC_SET_1);
- twl4030_write(codec, TWL4030_REG_MISC_SET_1,
- regmisc1 | TWL4030_SMOOTH_ANAVOL_EN);
-
- /* toggle CODECPDZ as per TRM */
- twl4030_clear_codecpdz(codec);
- twl4030_set_codecpdz(codec);
-
- /* program anti-pop with bias ramp delay */
- popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
- popn &= TWL4030_RAMP_DELAY;
- popn |= TWL4030_RAMP_DELAY_645MS;
- twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
- popn |= TWL4030_VMID_EN;
- twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
-
- /* enable anti-pop ramp */
- popn |= TWL4030_RAMP_EN;
- twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
-}
-
-static void twl4030_power_down(struct snd_soc_codec *codec)
-{
- u8 popn;
-
- /* disable anti-pop ramp */
- popn = twl4030_read_reg_cache(codec, TWL4030_REG_HS_POPN_SET);
- popn &= ~TWL4030_RAMP_EN;
- twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
-
- /* disable bias out */
- popn &= ~TWL4030_VMID_EN;
- twl4030_write(codec, TWL4030_REG_HS_POPN_SET, popn);
-
- /* power down */
- twl4030_clear_codecpdz(codec);
-}
-
-static int twl4030_set_bias_level(struct snd_soc_codec *codec,
- enum snd_soc_bias_level level)
-{
- switch (level) {
- case SND_SOC_BIAS_ON:
- twl4030_power_up(codec);
- break;
- case SND_SOC_BIAS_PREPARE:
- /* TODO: develop a twl4030_prepare function */
- break;
- case SND_SOC_BIAS_STANDBY:
- /* TODO: develop a twl4030_standby function */
- twl4030_power_down(codec);
- break;
- case SND_SOC_BIAS_OFF:
- twl4030_power_down(codec);
- break;
- }
- codec->bias_level = level;
-
- return 0;
-}
-
-static int twl4030_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
- u8 mode, old_mode, format, old_format;
-
-
- /* bit rate */
- old_mode = twl4030_read_reg_cache(codec,
- TWL4030_REG_CODEC_MODE) & ~TWL4030_CODECPDZ;
- mode = old_mode & ~TWL4030_APLL_RATE;
-
- switch (params_rate(params)) {
- case 8000:
- mode |= TWL4030_APLL_RATE_8000;
- break;
- case 11025:
- mode |= TWL4030_APLL_RATE_11025;
- break;
- case 12000:
- mode |= TWL4030_APLL_RATE_12000;
- break;
- case 16000:
- mode |= TWL4030_APLL_RATE_16000;
- break;
- case 22050:
- mode |= TWL4030_APLL_RATE_22050;
- break;
- case 24000:
- mode |= TWL4030_APLL_RATE_24000;
- break;
- case 32000:
- mode |= TWL4030_APLL_RATE_32000;
- break;
- case 44100:
- mode |= TWL4030_APLL_RATE_44100;
- break;
- case 48000:
- mode |= TWL4030_APLL_RATE_48000;
- break;
- default:
- printk(KERN_ERR "TWL4030 hw params: unknown rate %d\n",
- params_rate(params));
- return -EINVAL;
- }
-
- if (mode != old_mode) {
- /* change rate and set CODECPDZ */
- twl4030_write(codec, TWL4030_REG_CODEC_MODE, mode);
- twl4030_set_codecpdz(codec);
- }
-
- /* sample size */
- old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
- format = old_format;
- format &= ~TWL4030_DATA_WIDTH;
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- format |= TWL4030_DATA_WIDTH_16S_16W;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- format |= TWL4030_DATA_WIDTH_32S_24W;
- break;
- default:
- printk(KERN_ERR "TWL4030 hw params: unknown format %d\n",
- params_format(params));
- return -EINVAL;
- }
-
- if (format != old_format) {
-
- /* clear CODECPDZ before changing format (codec requirement) */
- twl4030_clear_codecpdz(codec);
-
- /* change format */
- twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
-
- /* set CODECPDZ afterwards */
- twl4030_set_codecpdz(codec);
- }
- return 0;
-}
-
-static int twl4030_set_dai_sysclk(struct snd_soc_dai *codec_dai,
- int clk_id, unsigned int freq, int dir)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- u8 infreq;
-
- switch (freq) {
- case 19200000:
- infreq = TWL4030_APLL_INFREQ_19200KHZ;
- break;
- case 26000000:
- infreq = TWL4030_APLL_INFREQ_26000KHZ;
- break;
- case 38400000:
- infreq = TWL4030_APLL_INFREQ_38400KHZ;
- break;
- default:
- printk(KERN_ERR "TWL4030 set sysclk: unknown rate %d\n",
- freq);
- return -EINVAL;
- }
-
- infreq |= TWL4030_APLL_EN;
- twl4030_write(codec, TWL4030_REG_APLL_CTL, infreq);
-
- return 0;
-}
-
-static int twl4030_set_dai_fmt(struct snd_soc_dai *codec_dai,
- unsigned int fmt)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- u8 old_format, format;
-
- /* get format */
- old_format = twl4030_read_reg_cache(codec, TWL4030_REG_AUDIO_IF);
- format = old_format;
-
- /* set master/slave audio interface */
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM:
- format &= ~(TWL4030_AIF_SLAVE_EN);
- format &= ~(TWL4030_CLK256FS_EN);
- break;
- case SND_SOC_DAIFMT_CBS_CFS:
- format |= TWL4030_AIF_SLAVE_EN;
- format |= TWL4030_CLK256FS_EN;
- break;
- default:
- return -EINVAL;
- }
-
- /* interface format */
- format &= ~TWL4030_AIF_FORMAT;
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- format |= TWL4030_AIF_FORMAT_CODEC;
- break;
- default:
- return -EINVAL;
- }
-
- if (format != old_format) {
-
- /* clear CODECPDZ before changing format (codec requirement) */
- twl4030_clear_codecpdz(codec);
-
- /* change format */
- twl4030_write(codec, TWL4030_REG_AUDIO_IF, format);
-
- /* set CODECPDZ afterwards */
- twl4030_set_codecpdz(codec);
- }
-
- return 0;
-}
-
-#define TWL4030_RATES (SNDRV_PCM_RATE_8000_48000)
-#define TWL4030_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FORMAT_S24_LE)
-
-struct snd_soc_dai twl4030_dai = {
- .name = "twl4030",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 2,
- .channels_max = 2,
- .rates = TWL4030_RATES,
- .formats = TWL4030_FORMATS,},
- .capture = {
- .stream_name = "Capture",
- .channels_min = 2,
- .channels_max = 2,
- .rates = TWL4030_RATES,
- .formats = TWL4030_FORMATS,},
- .ops = {
- .hw_params = twl4030_hw_params,
- .set_sysclk = twl4030_set_dai_sysclk,
- .set_fmt = twl4030_set_dai_fmt,
- }
-};
-EXPORT_SYMBOL_GPL(twl4030_dai);
-
-static int twl4030_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- twl4030_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- return 0;
-}
-
-static int twl4030_resume(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- twl4030_set_bias_level(codec, codec->suspend_bias_level);
- return 0;
-}
-
-/*
- * initialize the driver
- * register the mixer and dsp interfaces with the kernel
- */
-
-static int twl4030_init(struct snd_soc_device *socdev)
-{
- struct snd_soc_codec *codec = socdev->codec;
- int ret = 0;
-
- printk(KERN_INFO "TWL4030 Audio Codec init \n");
-
- codec->name = "twl4030";
- codec->owner = THIS_MODULE;
- codec->read = twl4030_read_reg_cache;
- codec->write = twl4030_write;
- codec->set_bias_level = twl4030_set_bias_level;
- codec->dai = &twl4030_dai;
- codec->num_dai = 1;
- codec->reg_cache_size = sizeof(twl4030_reg);
- codec->reg_cache = kmemdup(twl4030_reg, sizeof(twl4030_reg),
- GFP_KERNEL);
- if (codec->reg_cache == NULL)
- return -ENOMEM;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "twl4030: failed to create pcms\n");
- goto pcm_err;
- }
-
- twl4030_init_chip(codec);
-
- /* power on device */
- twl4030_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- twl4030_add_controls(codec);
- twl4030_add_widgets(codec);
-
- ret = snd_soc_init_card(socdev);
- if (ret < 0) {
- printk(KERN_ERR "twl4030: failed to register card\n");
- goto card_err;
- }
-
- return ret;
-
-card_err:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-pcm_err:
- kfree(codec->reg_cache);
- return ret;
-}
-
-static struct snd_soc_device *twl4030_socdev;
-
-static int twl4030_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
-
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- socdev->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- twl4030_socdev = socdev;
- twl4030_init(socdev);
-
- return 0;
-}
-
-static int twl4030_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- printk(KERN_INFO "TWL4030 Audio Codec remove\n");
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_twl4030 = {
- .probe = twl4030_probe,
- .remove = twl4030_remove,
- .suspend = twl4030_suspend,
- .resume = twl4030_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_twl4030);
-
-static int __devinit twl4030_init(void)
-{
- return snd_soc_register_dai(&twl4030_dai);
-}
-module_init(twl4030_init);
-
-static void __exit twl4030_exit(void)
-{
- snd_soc_unregister_dai(&twl4030_dai);
-}
-module_exit(twl4030_exit);
-
-MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
-MODULE_AUTHOR("Steve Sakoman");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/twl4030.h b/sound/soc/codecs/twl4030.h
deleted file mode 100644
index a2065d417c2e..000000000000
--- a/sound/soc/codecs/twl4030.h
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * ALSA SoC TWL4030 codec driver
- *
- * Author: Steve Sakoman <steve@sakoman.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#ifndef __TWL4030_AUDIO_H__
-#define __TWL4030_AUDIO_H__
-
-#define TWL4030_REG_CODEC_MODE 0x1
-#define TWL4030_REG_OPTION 0x2
-#define TWL4030_REG_UNKNOWN 0x3
-#define TWL4030_REG_MICBIAS_CTL 0x4
-#define TWL4030_REG_ANAMICL 0x5
-#define TWL4030_REG_ANAMICR 0x6
-#define TWL4030_REG_AVADC_CTL 0x7
-#define TWL4030_REG_ADCMICSEL 0x8
-#define TWL4030_REG_DIGMIXING 0x9
-#define TWL4030_REG_ATXL1PGA 0xA
-#define TWL4030_REG_ATXR1PGA 0xB
-#define TWL4030_REG_AVTXL2PGA 0xC
-#define TWL4030_REG_AVTXR2PGA 0xD
-#define TWL4030_REG_AUDIO_IF 0xE
-#define TWL4030_REG_VOICE_IF 0xF
-#define TWL4030_REG_ARXR1PGA 0x10
-#define TWL4030_REG_ARXL1PGA 0x11
-#define TWL4030_REG_ARXR2PGA 0x12
-#define TWL4030_REG_ARXL2PGA 0x13
-#define TWL4030_REG_VRXPGA 0x14
-#define TWL4030_REG_VSTPGA 0x15
-#define TWL4030_REG_VRX2ARXPGA 0x16
-#define TWL4030_REG_AVDAC_CTL 0x17
-#define TWL4030_REG_ARX2VTXPGA 0x18
-#define TWL4030_REG_ARXL1_APGA_CTL 0x19
-#define TWL4030_REG_ARXR1_APGA_CTL 0x1A
-#define TWL4030_REG_ARXL2_APGA_CTL 0x1B
-#define TWL4030_REG_ARXR2_APGA_CTL 0x1C
-#define TWL4030_REG_ATX2ARXPGA 0x1D
-#define TWL4030_REG_BT_IF 0x1E
-#define TWL4030_REG_BTPGA 0x1F
-#define TWL4030_REG_BTSTPGA 0x20
-#define TWL4030_REG_EAR_CTL 0x21
-#define TWL4030_REG_HS_SEL 0x22
-#define TWL4030_REG_HS_GAIN_SET 0x23
-#define TWL4030_REG_HS_POPN_SET 0x24
-#define TWL4030_REG_PREDL_CTL 0x25
-#define TWL4030_REG_PREDR_CTL 0x26
-#define TWL4030_REG_PRECKL_CTL 0x27
-#define TWL4030_REG_PRECKR_CTL 0x28
-#define TWL4030_REG_HFL_CTL 0x29
-#define TWL4030_REG_HFR_CTL 0x2A
-#define TWL4030_REG_ALC_CTL 0x2B
-#define TWL4030_REG_ALC_SET1 0x2C
-#define TWL4030_REG_ALC_SET2 0x2D
-#define TWL4030_REG_BOOST_CTL 0x2E
-#define TWL4030_REG_SOFTVOL_CTL 0x2F
-#define TWL4030_REG_DTMF_FREQSEL 0x30
-#define TWL4030_REG_DTMF_TONEXT1H 0x31
-#define TWL4030_REG_DTMF_TONEXT1L 0x32
-#define TWL4030_REG_DTMF_TONEXT2H 0x33
-#define TWL4030_REG_DTMF_TONEXT2L 0x34
-#define TWL4030_REG_DTMF_TONOFF 0x35
-#define TWL4030_REG_DTMF_WANONOFF 0x36
-#define TWL4030_REG_I2S_RX_SCRAMBLE_H 0x37
-#define TWL4030_REG_I2S_RX_SCRAMBLE_M 0x38
-#define TWL4030_REG_I2S_RX_SCRAMBLE_L 0x39
-#define TWL4030_REG_APLL_CTL 0x3A
-#define TWL4030_REG_DTMF_CTL 0x3B
-#define TWL4030_REG_DTMF_PGA_CTL2 0x3C
-#define TWL4030_REG_DTMF_PGA_CTL1 0x3D
-#define TWL4030_REG_MISC_SET_1 0x3E
-#define TWL4030_REG_PCMBTMUX 0x3F
-#define TWL4030_REG_RX_PATH_SEL 0x43
-#define TWL4030_REG_VDL_APGA_CTL 0x44
-#define TWL4030_REG_VIBRA_CTL 0x45
-#define TWL4030_REG_VIBRA_SET 0x46
-#define TWL4030_REG_VIBRA_PWM_SET 0x47
-#define TWL4030_REG_ANAMIC_GAIN 0x48
-#define TWL4030_REG_MISC_SET_2 0x49
-
-#define TWL4030_CACHEREGNUM (TWL4030_REG_MISC_SET_2 + 1)
-
-/* Bitfield Definitions */
-
-/* TWL4030_CODEC_MODE (0x01) Fields */
-
-#define TWL4030_APLL_RATE 0xF0
-#define TWL4030_APLL_RATE_8000 0x00
-#define TWL4030_APLL_RATE_11025 0x10
-#define TWL4030_APLL_RATE_12000 0x20
-#define TWL4030_APLL_RATE_16000 0x40
-#define TWL4030_APLL_RATE_22050 0x50
-#define TWL4030_APLL_RATE_24000 0x60
-#define TWL4030_APLL_RATE_32000 0x80
-#define TWL4030_APLL_RATE_44100 0x90
-#define TWL4030_APLL_RATE_48000 0xA0
-#define TWL4030_SEL_16K 0x04
-#define TWL4030_CODECPDZ 0x02
-#define TWL4030_OPT_MODE 0x01
-
-/* TWL4030_REG_MICBIAS_CTL (0x04) Fields */
-
-#define TWL4030_MICBIAS2_CTL 0x40
-#define TWL4030_MICBIAS1_CTL 0x20
-#define TWL4030_HSMICBIAS_EN 0x04
-#define TWL4030_MICBIAS2_EN 0x02
-#define TWL4030_MICBIAS1_EN 0x01
-
-/* ANAMICL (0x05) Fields */
-
-#define TWL4030_CNCL_OFFSET_START 0x80
-#define TWL4030_OFFSET_CNCL_SEL 0x60
-#define TWL4030_OFFSET_CNCL_SEL_ARX1 0x00
-#define TWL4030_OFFSET_CNCL_SEL_ARX2 0x20
-#define TWL4030_OFFSET_CNCL_SEL_VRX 0x40
-#define TWL4030_OFFSET_CNCL_SEL_ALL 0x60
-#define TWL4030_MICAMPL_EN 0x10
-#define TWL4030_CKMIC_EN 0x08
-#define TWL4030_AUXL_EN 0x04
-#define TWL4030_HSMIC_EN 0x02
-#define TWL4030_MAINMIC_EN 0x01
-
-/* ANAMICR (0x06) Fields */
-
-#define TWL4030_MICAMPR_EN 0x10
-#define TWL4030_AUXR_EN 0x04
-#define TWL4030_SUBMIC_EN 0x01
-
-/* AVADC_CTL (0x07) Fields */
-
-#define TWL4030_ADCL_EN 0x08
-#define TWL4030_AVADC_CLK_PRIORITY 0x04
-#define TWL4030_ADCR_EN 0x02
-
-/* AUDIO_IF (0x0E) Fields */
-
-#define TWL4030_AIF_SLAVE_EN 0x80
-#define TWL4030_DATA_WIDTH 0x60
-#define TWL4030_DATA_WIDTH_16S_16W 0x00
-#define TWL4030_DATA_WIDTH_32S_16W 0x40
-#define TWL4030_DATA_WIDTH_32S_24W 0x60
-#define TWL4030_AIF_FORMAT 0x18
-#define TWL4030_AIF_FORMAT_CODEC 0x00
-#define TWL4030_AIF_FORMAT_LEFT 0x08
-#define TWL4030_AIF_FORMAT_RIGHT 0x10
-#define TWL4030_AIF_FORMAT_TDM 0x18
-#define TWL4030_AIF_TRI_EN 0x04
-#define TWL4030_CLK256FS_EN 0x02
-#define TWL4030_AIF_EN 0x01
-
-/* HS_GAIN_SET (0x23) Fields */
-
-#define TWL4030_HSR_GAIN 0x0C
-#define TWL4030_HSR_GAIN_PWR_DOWN 0x00
-#define TWL4030_HSR_GAIN_PLUS_6DB 0x04
-#define TWL4030_HSR_GAIN_0DB 0x08
-#define TWL4030_HSR_GAIN_MINUS_6DB 0x0C
-#define TWL4030_HSL_GAIN 0x03
-#define TWL4030_HSL_GAIN_PWR_DOWN 0x00
-#define TWL4030_HSL_GAIN_PLUS_6DB 0x01
-#define TWL4030_HSL_GAIN_0DB 0x02
-#define TWL4030_HSL_GAIN_MINUS_6DB 0x03
-
-/* HS_POPN_SET (0x24) Fields */
-
-#define TWL4030_VMID_EN 0x40
-#define TWL4030_EXTMUTE 0x20
-#define TWL4030_RAMP_DELAY 0x1C
-#define TWL4030_RAMP_DELAY_20MS 0x00
-#define TWL4030_RAMP_DELAY_40MS 0x04
-#define TWL4030_RAMP_DELAY_81MS 0x08
-#define TWL4030_RAMP_DELAY_161MS 0x0C
-#define TWL4030_RAMP_DELAY_323MS 0x10
-#define TWL4030_RAMP_DELAY_645MS 0x14
-#define TWL4030_RAMP_DELAY_1291MS 0x18
-#define TWL4030_RAMP_DELAY_2581MS 0x1C
-#define TWL4030_RAMP_EN 0x02
-
-/* APLL_CTL (0x3A) Fields */
-
-#define TWL4030_APLL_EN 0x10
-#define TWL4030_APLL_INFREQ 0x0F
-#define TWL4030_APLL_INFREQ_19200KHZ 0x05
-#define TWL4030_APLL_INFREQ_26000KHZ 0x06
-#define TWL4030_APLL_INFREQ_38400KHZ 0x0F
-
-/* REG_MISC_SET_1 (0x3E) Fields */
-
-#define TWL4030_CLK64_EN 0x80
-#define TWL4030_SCRAMBLE_EN 0x40
-#define TWL4030_FMLOOP_EN 0x20
-#define TWL4030_SMOOTH_ANAVOL_EN 0x02
-#define TWL4030_DIGMIC_LR_SWAP_EN 0x01
-
-extern struct snd_soc_dai twl4030_dai;
-extern struct snd_soc_codec_device soc_codec_dev_twl4030;
-
-#endif /* End of __TWL4030_AUDIO_H__ */
diff --git a/sound/soc/codecs/uda134x.c b/sound/soc/codecs/uda134x.c
deleted file mode 100644
index 8e035b5d733f..000000000000
--- a/sound/soc/codecs/uda134x.c
+++ /dev/null
@@ -1,668 +0,0 @@
-/*
- * uda134x.c -- UDA134X ALSA SoC Codec driver
- *
- * Modifications by Christian Pellegrin <chripell@evolware.org>
- *
- * Copyright 2007 Dension Audio Systems Ltd.
- * Author: Zoltan Devai
- *
- * Based on the WM87xx drivers by Liam Girdwood and Richard Purdie
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/initval.h>
-
-#include <sound/uda134x.h>
-#include <sound/l3.h>
-
-#include "uda134x.h"
-
-
-#define POWER_OFF_ON_STANDBY 1
-/*
- ALSA SOC usually puts the device in standby mode when it's not used
- for sometime. If you define POWER_OFF_ON_STANDBY the driver will
- turn off the ADC/DAC when this callback is invoked and turn it back
- on when needed. Unfortunately this will result in a very light bump
- (it can be audible only with good earphones). If this bothers you
- just comment this line, you will have slightly higher power
- consumption . Please note that sending the L3 command for ADC is
- enough to make the bump, so it doesn't make difference if you
- completely take off power from the codec.
- */
-
-#define UDA134X_RATES SNDRV_PCM_RATE_8000_48000
-#define UDA134X_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE | \
- SNDRV_PCM_FMTBIT_S18_3LE | SNDRV_PCM_FMTBIT_S20_3LE)
-
-struct uda134x_priv {
- int sysclk;
- int dai_fmt;
-
- struct snd_pcm_substream *master_substream;
- struct snd_pcm_substream *slave_substream;
-};
-
-/* In-data addresses are hard-coded into the reg-cache values */
-static const char uda134x_reg[UDA134X_REGS_NUM] = {
- /* Extended address registers */
- 0x04, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
- /* Status, data regs */
- 0x00, 0x83, 0x00, 0x40, 0x80, 0x00,
-};
-
-/*
- * The codec has no support for reading its registers except for peak level...
- */
-static inline unsigned int uda134x_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u8 *cache = codec->reg_cache;
-
- if (reg >= UDA134X_REGS_NUM)
- return -1;
- return cache[reg];
-}
-
-/*
- * Write the register cache
- */
-static inline void uda134x_write_reg_cache(struct snd_soc_codec *codec,
- u8 reg, unsigned int value)
-{
- u8 *cache = codec->reg_cache;
-
- if (reg >= UDA134X_REGS_NUM)
- return;
- cache[reg] = value;
-}
-
-/*
- * Write to the uda134x registers
- *
- */
-static int uda134x_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- int ret;
- u8 addr;
- u8 data = value;
- struct uda134x_platform_data *pd = codec->control_data;
-
- pr_debug("%s reg: %02X, value:%02X\n", __func__, reg, value);
-
- if (reg >= UDA134X_REGS_NUM) {
- printk(KERN_ERR "%s unkown register: reg: %d",
- __func__, reg);
- return -EINVAL;
- }
-
- uda134x_write_reg_cache(codec, reg, value);
-
- switch (reg) {
- case UDA134X_STATUS0:
- case UDA134X_STATUS1:
- addr = UDA134X_STATUS_ADDR;
- break;
- case UDA134X_DATA000:
- case UDA134X_DATA001:
- case UDA134X_DATA010:
- addr = UDA134X_DATA0_ADDR;
- break;
- case UDA134X_DATA1:
- addr = UDA134X_DATA1_ADDR;
- break;
- default:
- /* It's an extended address register */
- addr = (reg | UDA134X_EXTADDR_PREFIX);
-
- ret = l3_write(&pd->l3,
- UDA134X_DATA0_ADDR, &addr, 1);
- if (ret != 1)
- return -EIO;
-
- addr = UDA134X_DATA0_ADDR;
- data = (value | UDA134X_EXTDATA_PREFIX);
- break;
- }
-
- ret = l3_write(&pd->l3,
- addr, &data, 1);
- if (ret != 1)
- return -EIO;
-
- return 0;
-}
-
-static inline void uda134x_reset(struct snd_soc_codec *codec)
-{
- u8 reset_reg = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
- uda134x_write(codec, UDA134X_STATUS0, reset_reg | (1<<6));
- msleep(1);
- uda134x_write(codec, UDA134X_STATUS0, reset_reg & ~(1<<6));
-}
-
-static int uda134x_mute(struct snd_soc_dai *dai, int mute)
-{
- struct snd_soc_codec *codec = dai->codec;
- u8 mute_reg = uda134x_read_reg_cache(codec, UDA134X_DATA010);
-
- pr_debug("%s mute: %d\n", __func__, mute);
-
- if (mute)
- mute_reg |= (1<<2);
- else
- mute_reg &= ~(1<<2);
-
- uda134x_write(codec, UDA134X_DATA010, mute_reg & ~(1<<2));
-
- return 0;
-}
-
-static int uda134x_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
- struct uda134x_priv *uda134x = codec->private_data;
- struct snd_pcm_runtime *master_runtime;
-
- if (uda134x->master_substream) {
- master_runtime = uda134x->master_substream->runtime;
-
- pr_debug("%s constraining to %d bits at %d\n", __func__,
- master_runtime->sample_bits,
- master_runtime->rate);
-
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_RATE,
- master_runtime->rate,
- master_runtime->rate);
-
- snd_pcm_hw_constraint_minmax(substream->runtime,
- SNDRV_PCM_HW_PARAM_SAMPLE_BITS,
- master_runtime->sample_bits,
- master_runtime->sample_bits);
-
- uda134x->slave_substream = substream;
- } else
- uda134x->master_substream = substream;
-
- return 0;
-}
-
-static void uda134x_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
- struct uda134x_priv *uda134x = codec->private_data;
-
- if (uda134x->master_substream == substream)
- uda134x->master_substream = uda134x->slave_substream;
-
- uda134x->slave_substream = NULL;
-}
-
-static int uda134x_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
- struct uda134x_priv *uda134x = codec->private_data;
- u8 hw_params;
-
- if (substream == uda134x->slave_substream) {
- pr_debug("%s ignoring hw_params for slave substream\n",
- __func__);
- return 0;
- }
-
- hw_params = uda134x_read_reg_cache(codec, UDA134X_STATUS0);
- hw_params &= STATUS0_SYSCLK_MASK;
- hw_params &= STATUS0_DAIFMT_MASK;
-
- pr_debug("%s sysclk: %d, rate:%d\n", __func__,
- uda134x->sysclk, params_rate(params));
-
- /* set SYSCLK / fs ratio */
- switch (uda134x->sysclk / params_rate(params)) {
- case 512:
- break;
- case 384:
- hw_params |= (1<<4);
- break;
- case 256:
- hw_params |= (1<<5);
- break;
- default:
- printk(KERN_ERR "%s unsupported fs\n", __func__);
- return -EINVAL;
- }
-
- pr_debug("%s dai_fmt: %d, params_format:%d\n", __func__,
- uda134x->dai_fmt, params_format(params));
-
- /* set DAI format and word length */
- switch (uda134x->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- break;
- case SND_SOC_DAIFMT_RIGHT_J:
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- hw_params |= (1<<1);
- break;
- case SNDRV_PCM_FORMAT_S18_3LE:
- hw_params |= (1<<2);
- break;
- case SNDRV_PCM_FORMAT_S20_3LE:
- hw_params |= ((1<<2) | (1<<1));
- break;
- default:
- printk(KERN_ERR "%s unsupported format (right)\n",
- __func__);
- return -EINVAL;
- }
- break;
- case SND_SOC_DAIFMT_LEFT_J:
- hw_params |= (1<<3);
- break;
- default:
- printk(KERN_ERR "%s unsupported format\n", __func__);
- return -EINVAL;
- }
-
- uda134x_write(codec, UDA134X_STATUS0, hw_params);
-
- return 0;
-}
-
-static int uda134x_set_dai_sysclk(struct snd_soc_dai *codec_dai,
- int clk_id, unsigned int freq, int dir)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- struct uda134x_priv *uda134x = codec->private_data;
-
- pr_debug("%s clk_id: %d, freq: %d, dir: %d\n", __func__,
- clk_id, freq, dir);
-
- /* Anything between 256fs*8Khz and 512fs*48Khz should be acceptable
- because the codec is slave. Of course limitations of the clock
- master (the IIS controller) apply.
- We'll error out on set_hw_params if it's not OK */
- if ((freq >= (256 * 8000)) && (freq <= (512 * 48000))) {
- uda134x->sysclk = freq;
- return 0;
- }
-
- printk(KERN_ERR "%s unsupported sysclk\n", __func__);
- return -EINVAL;
-}
-
-static int uda134x_set_dai_fmt(struct snd_soc_dai *codec_dai,
- unsigned int fmt)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- struct uda134x_priv *uda134x = codec->private_data;
-
- pr_debug("%s fmt: %08X\n", __func__, fmt);
-
- /* codec supports only full slave mode */
- if ((fmt & SND_SOC_DAIFMT_MASTER_MASK) != SND_SOC_DAIFMT_CBS_CFS) {
- printk(KERN_ERR "%s unsupported slave mode\n", __func__);
- return -EINVAL;
- }
-
- /* no support for clock inversion */
- if ((fmt & SND_SOC_DAIFMT_INV_MASK) != SND_SOC_DAIFMT_NB_NF) {
- printk(KERN_ERR "%s unsupported clock inversion\n", __func__);
- return -EINVAL;
- }
-
- /* We can't setup DAI format here as it depends on the word bit num */
- /* so let's just store the value for later */
- uda134x->dai_fmt = fmt;
-
- return 0;
-}
-
-static int uda134x_set_bias_level(struct snd_soc_codec *codec,
- enum snd_soc_bias_level level)
-{
- u8 reg;
- struct uda134x_platform_data *pd = codec->control_data;
- int i;
- u8 *cache = codec->reg_cache;
-
- pr_debug("%s bias level %d\n", __func__, level);
-
- switch (level) {
- case SND_SOC_BIAS_ON:
- /* ADC, DAC on */
- reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
- uda134x_write(codec, UDA134X_STATUS1, reg | 0x03);
- break;
- case SND_SOC_BIAS_PREPARE:
- /* power on */
- if (pd->power) {
- pd->power(1);
- /* Sync reg_cache with the hardware */
- for (i = 0; i < ARRAY_SIZE(uda134x_reg); i++)
- codec->write(codec, i, *cache++);
- }
- break;
- case SND_SOC_BIAS_STANDBY:
- /* ADC, DAC power off */
- reg = uda134x_read_reg_cache(codec, UDA134X_STATUS1);
- uda134x_write(codec, UDA134X_STATUS1, reg & ~(0x03));
- break;
- case SND_SOC_BIAS_OFF:
- /* power off */
- if (pd->power)
- pd->power(0);
- break;
- }
- codec->bias_level = level;
- return 0;
-}
-
-static const char *uda134x_dsp_setting[] = {"Flat", "Minimum1",
- "Minimum2", "Maximum"};
-static const char *uda134x_deemph[] = {"None", "32Khz", "44.1Khz", "48Khz"};
-static const char *uda134x_mixmode[] = {"Differential", "Analog1",
- "Analog2", "Both"};
-
-static const struct soc_enum uda134x_mixer_enum[] = {
-SOC_ENUM_SINGLE(UDA134X_DATA010, 0, 0x04, uda134x_dsp_setting),
-SOC_ENUM_SINGLE(UDA134X_DATA010, 3, 0x04, uda134x_deemph),
-SOC_ENUM_SINGLE(UDA134X_EA010, 0, 0x04, uda134x_mixmode),
-};
-
-static const struct snd_kcontrol_new uda1341_snd_controls[] = {
-SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
-SOC_SINGLE("Capture Volume", UDA134X_EA010, 2, 0x07, 0),
-SOC_SINGLE("Analog1 Volume", UDA134X_EA000, 0, 0x1F, 1),
-SOC_SINGLE("Analog2 Volume", UDA134X_EA001, 0, 0x1F, 1),
-
-SOC_SINGLE("Mic Sensitivity", UDA134X_EA010, 2, 7, 0),
-SOC_SINGLE("Mic Volume", UDA134X_EA101, 0, 0x1F, 0),
-
-SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
-SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
-
-SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
-SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
-SOC_ENUM("Input Mux", uda134x_mixer_enum[2]),
-
-SOC_SINGLE("AGC Switch", UDA134X_EA100, 4, 1, 0),
-SOC_SINGLE("AGC Target Volume", UDA134X_EA110, 0, 0x03, 1),
-SOC_SINGLE("AGC Timing", UDA134X_EA110, 2, 0x07, 0),
-
-SOC_SINGLE("DAC +6dB Switch", UDA134X_STATUS1, 6, 1, 0),
-SOC_SINGLE("ADC +6dB Switch", UDA134X_STATUS1, 5, 1, 0),
-SOC_SINGLE("ADC Polarity Switch", UDA134X_STATUS1, 4, 1, 0),
-SOC_SINGLE("DAC Polarity Switch", UDA134X_STATUS1, 3, 1, 0),
-SOC_SINGLE("Double Speed Playback Switch", UDA134X_STATUS1, 2, 1, 0),
-SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
-};
-
-static const struct snd_kcontrol_new uda1340_snd_controls[] = {
-SOC_SINGLE("Master Playback Volume", UDA134X_DATA000, 0, 0x3F, 1),
-
-SOC_SINGLE("Tone Control - Bass", UDA134X_DATA001, 2, 0xF, 0),
-SOC_SINGLE("Tone Control - Treble", UDA134X_DATA001, 0, 3, 0),
-
-SOC_ENUM("Sound Processing Filter", uda134x_mixer_enum[0]),
-SOC_ENUM("PCM Playback De-emphasis", uda134x_mixer_enum[1]),
-
-SOC_SINGLE("DC Filter Enable Switch", UDA134X_STATUS0, 0, 1, 0),
-};
-
-static int uda134x_add_controls(struct snd_soc_codec *codec)
-{
- int err, i, n;
- const struct snd_kcontrol_new *ctrls;
- struct uda134x_platform_data *pd = codec->control_data;
-
- switch (pd->model) {
- case UDA134X_UDA1340:
- case UDA134X_UDA1344:
- n = ARRAY_SIZE(uda1340_snd_controls);
- ctrls = uda1340_snd_controls;
- break;
- case UDA134X_UDA1341:
- n = ARRAY_SIZE(uda1341_snd_controls);
- ctrls = uda1341_snd_controls;
- break;
- default:
- printk(KERN_ERR "%s unkown codec type: %d",
- __func__, pd->model);
- return -EINVAL;
- }
-
- for (i = 0; i < n; i++) {
- err = snd_ctl_add(codec->card,
- snd_soc_cnew(&ctrls[i],
- codec, NULL));
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-struct snd_soc_dai uda134x_dai = {
- .name = "UDA134X",
- /* playback capabilities */
- .playback = {
- .stream_name = "Playback",
- .channels_min = 1,
- .channels_max = 2,
- .rates = UDA134X_RATES,
- .formats = UDA134X_FORMATS,
- },
- /* capture capabilities */
- .capture = {
- .stream_name = "Capture",
- .channels_min = 1,
- .channels_max = 2,
- .rates = UDA134X_RATES,
- .formats = UDA134X_FORMATS,
- },
- /* pcm operations */
- .ops = {
- .startup = uda134x_startup,
- .shutdown = uda134x_shutdown,
- .hw_params = uda134x_hw_params,
- .digital_mute = uda134x_mute,
- .set_sysclk = uda134x_set_dai_sysclk,
- .set_fmt = uda134x_set_dai_fmt,
- }
-};
-EXPORT_SYMBOL(uda134x_dai);
-
-
-static int uda134x_soc_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec;
- struct uda134x_priv *uda134x;
- void *codec_setup_data = socdev->codec_data;
- int ret = -ENOMEM;
- struct uda134x_platform_data *pd;
-
- printk(KERN_INFO "UDA134X SoC Audio Codec\n");
-
- if (!codec_setup_data) {
- printk(KERN_ERR "UDA134X SoC codec: "
- "missing L3 bitbang function\n");
- return -ENODEV;
- }
-
- pd = codec_setup_data;
- switch (pd->model) {
- case UDA134X_UDA1340:
- case UDA134X_UDA1341:
- case UDA134X_UDA1344:
- break;
- default:
- printk(KERN_ERR "UDA134X SoC codec: "
- "unsupported model %d\n",
- pd->model);
- return -EINVAL;
- }
-
- socdev->codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (socdev->codec == NULL)
- return ret;
-
- codec = socdev->codec;
-
- uda134x = kzalloc(sizeof(struct uda134x_priv), GFP_KERNEL);
- if (uda134x == NULL)
- goto priv_err;
- codec->private_data = uda134x;
-
- codec->reg_cache = kmemdup(uda134x_reg, sizeof(uda134x_reg),
- GFP_KERNEL);
- if (codec->reg_cache == NULL)
- goto reg_err;
-
- mutex_init(&codec->mutex);
-
- codec->reg_cache_size = sizeof(uda134x_reg);
- codec->reg_cache_step = 1;
-
- codec->name = "UDA134X";
- codec->owner = THIS_MODULE;
- codec->dai = &uda134x_dai;
- codec->num_dai = 1;
- codec->read = uda134x_read_reg_cache;
- codec->write = uda134x_write;
-#ifdef POWER_OFF_ON_STANDBY
- codec->set_bias_level = uda134x_set_bias_level;
-#endif
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- codec->control_data = codec_setup_data;
-
- if (pd->power)
- pd->power(1);
-
- uda134x_reset(codec);
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "UDA134X: failed to register pcms\n");
- goto pcm_err;
- }
-
- ret = uda134x_add_controls(codec);
- if (ret < 0) {
- printk(KERN_ERR "UDA134X: failed to register controls\n");
- goto pcm_err;
- }
-
- ret = snd_soc_init_card(socdev);
- if (ret < 0) {
- printk(KERN_ERR "UDA134X: failed to register card\n");
- goto card_err;
- }
-
- return 0;
-
-card_err:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-pcm_err:
- kfree(codec->reg_cache);
-reg_err:
- kfree(codec->private_data);
-priv_err:
- kfree(codec);
- return ret;
-}
-
-/* power down chip */
-static int uda134x_soc_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-
- kfree(codec->private_data);
- kfree(codec->reg_cache);
- kfree(codec);
-
- return 0;
-}
-
-#if defined(CONFIG_PM)
-static int uda134x_soc_suspend(struct platform_device *pdev,
- pm_message_t state)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- uda134x_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
- uda134x_set_bias_level(codec, SND_SOC_BIAS_OFF);
- return 0;
-}
-
-static int uda134x_soc_resume(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- uda134x_set_bias_level(codec, SND_SOC_BIAS_PREPARE);
- uda134x_set_bias_level(codec, SND_SOC_BIAS_ON);
- return 0;
-}
-#else
-#define uda134x_soc_suspend NULL
-#define uda134x_soc_resume NULL
-#endif /* CONFIG_PM */
-
-struct snd_soc_codec_device soc_codec_dev_uda134x = {
- .probe = uda134x_soc_probe,
- .remove = uda134x_soc_remove,
- .suspend = uda134x_soc_suspend,
- .resume = uda134x_soc_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_uda134x);
-
-static int __devinit uda134x_init(void)
-{
- return snd_soc_register_dai(&uda134x_dai);
-}
-module_init(uda134x_init);
-
-static void __exit uda134x_exit(void)
-{
- snd_soc_unregister_dai(&uda134x_dai);
-}
-module_exit(uda134x_exit);
-
-MODULE_DESCRIPTION("UDA134X ALSA soc codec driver");
-MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/uda134x.h b/sound/soc/codecs/uda134x.h
deleted file mode 100644
index 94f440490b31..000000000000
--- a/sound/soc/codecs/uda134x.h
+++ /dev/null
@@ -1,36 +0,0 @@
-#ifndef _UDA134X_CODEC_H
-#define _UDA134X_CODEC_H
-
-#define UDA134X_L3ADDR 5
-#define UDA134X_DATA0_ADDR ((UDA134X_L3ADDR << 2) | 0)
-#define UDA134X_DATA1_ADDR ((UDA134X_L3ADDR << 2) | 1)
-#define UDA134X_STATUS_ADDR ((UDA134X_L3ADDR << 2) | 2)
-
-#define UDA134X_EXTADDR_PREFIX 0xC0
-#define UDA134X_EXTDATA_PREFIX 0xE0
-
-/* UDA134X registers */
-#define UDA134X_EA000 0
-#define UDA134X_EA001 1
-#define UDA134X_EA010 2
-#define UDA134X_EA011 3
-#define UDA134X_EA100 4
-#define UDA134X_EA101 5
-#define UDA134X_EA110 6
-#define UDA134X_EA111 7
-#define UDA134X_STATUS0 8
-#define UDA134X_STATUS1 9
-#define UDA134X_DATA000 10
-#define UDA134X_DATA001 11
-#define UDA134X_DATA010 12
-#define UDA134X_DATA1 13
-
-#define UDA134X_REGS_NUM 14
-
-#define STATUS0_DAIFMT_MASK (~(7<<1))
-#define STATUS0_SYSCLK_MASK (~(3<<4))
-
-extern struct snd_soc_dai uda134x_dai;
-extern struct snd_soc_codec_device soc_codec_dev_uda134x;
-
-#endif
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 55a99b6a68a1..a69ee72a7af5 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -407,8 +407,7 @@ static int uda1380_set_dai_fmt(struct snd_soc_dai *codec_dai,
* when the DAI is being clocked by the CPU DAI. It's up to the
* machine and cpu DAI driver to do this before we are called.
*/
-static int uda1380_pcm_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int uda1380_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -440,8 +439,7 @@ static int uda1380_pcm_prepare(struct snd_pcm_substream *substream,
}
static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -479,8 +477,7 @@ static int uda1380_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -563,6 +560,8 @@ struct snd_soc_dai uda1380_dai[] = {
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.prepare = uda1380_pcm_prepare,
+ },
+ .dai_ops = {
.digital_mute = uda1380_mute,
.set_fmt = uda1380_set_dai_fmt,
},
@@ -580,6 +579,8 @@ struct snd_soc_dai uda1380_dai[] = {
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.prepare = uda1380_pcm_prepare,
+ },
+ .dai_ops = {
.digital_mute = uda1380_mute,
.set_fmt = uda1380_set_dai_fmt,
},
@@ -597,6 +598,8 @@ struct snd_soc_dai uda1380_dai[] = {
.hw_params = uda1380_pcm_hw_params,
.shutdown = uda1380_pcm_shutdown,
.prepare = uda1380_pcm_prepare,
+ },
+ .dai_ops = {
.set_fmt = uda1380_set_dai_fmt,
},
},
@@ -677,7 +680,7 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
/* uda1380 init */
uda1380_add_controls(codec);
uda1380_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
pr_err("uda1380: failed to register card\n");
goto card_err;
@@ -841,18 +844,6 @@ struct snd_soc_codec_device soc_codec_dev_uda1380 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_uda1380);
-static int __devinit uda1380_modinit(void)
-{
- return snd_soc_register_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
-}
-module_init(uda1380_modinit);
-
-static void __exit uda1380_exit(void)
-{
- snd_soc_unregister_dais(uda1380_dai, ARRAY_SIZE(uda1380_dai));
-}
-module_exit(uda1380_exit);
-
MODULE_AUTHOR("Giorgio Padrin");
MODULE_DESCRIPTION("Audio support for codec Philips UDA1380");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c
index a2af04bb4e9f..d8ca2da8d634 100644
--- a/sound/soc/codecs/wm8510.c
+++ b/sound/soc/codecs/wm8510.c
@@ -463,8 +463,7 @@ static int wm8510_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
static int wm8510_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -586,6 +585,8 @@ struct snd_soc_dai wm8510_dai = {
.formats = WM8510_FORMATS,},
.ops = {
.hw_params = wm8510_pcm_hw_params,
+ },
+ .dai_ops = {
.digital_mute = wm8510_mute,
.set_fmt = wm8510_set_dai_fmt,
.set_clkdiv = wm8510_set_dai_clkdiv,
@@ -658,7 +659,7 @@ static int wm8510_init(struct snd_soc_device *socdev)
wm8510_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm8510_add_controls(codec);
wm8510_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8510: failed to register card\n");
goto card_err;
@@ -889,18 +890,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8510 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8510);
-static int __devinit wm8510_modinit(void)
-{
- return snd_soc_register_dai(&wm8510_dai);
-}
-module_init(wm8510_modinit);
-
-static void __exit wm8510_exit(void)
-{
- snd_soc_unregister_dai(&wm8510_dai);
-}
-module_exit(wm8510_exit);
-
MODULE_DESCRIPTION("ASoC WM8510 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c
index 391ec2978aed..627ebfb4209b 100644
--- a/sound/soc/codecs/wm8580.c
+++ b/sound/soc/codecs/wm8580.c
@@ -548,13 +548,13 @@ static int wm8580_set_dai_pll(struct snd_soc_dai *codec_dai,
* Set PCM DAI bit size and sample rate.
*/
static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_dai_link *dai = rtd->dai;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_codec *codec = socdev->codec;
- u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->id);
+ u16 paifb = wm8580_read(codec, WM8580_PAIF3 + dai->codec_dai->id);
paifb &= ~WM8580_AIF_LENGTH_MASK;
/* bit size */
@@ -574,7 +574,7 @@ static int wm8580_paif_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- wm8580_write(codec, WM8580_PAIF3 + dai->id, paifb);
+ wm8580_write(codec, WM8580_PAIF3 + dai->codec_dai->id, paifb);
return 0;
}
@@ -798,6 +798,8 @@ struct snd_soc_dai wm8580_dai[] = {
},
.ops = {
.hw_params = wm8580_paif_hw_params,
+ },
+ .dai_ops = {
.set_fmt = wm8580_set_paif_dai_fmt,
.set_clkdiv = wm8580_set_dai_clkdiv,
.set_pll = wm8580_set_dai_pll,
@@ -816,6 +818,8 @@ struct snd_soc_dai wm8580_dai[] = {
},
.ops = {
.hw_params = wm8580_paif_hw_params,
+ },
+ .dai_ops = {
.set_fmt = wm8580_set_paif_dai_fmt,
.set_clkdiv = wm8580_set_dai_clkdiv,
.set_pll = wm8580_set_dai_pll,
@@ -869,7 +873,7 @@ static int wm8580_init(struct snd_soc_device *socdev)
wm8580_add_controls(codec);
wm8580_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8580: failed to register card\n");
goto card_err;
@@ -896,85 +900,85 @@ static struct snd_soc_device *wm8580_socdev;
* low = 0x1a
* high = 0x1b
*/
+static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
+
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
-static int wm8580_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+static struct i2c_driver wm8580_i2c_driver;
+static struct i2c_client client_template;
+
+static int wm8580_codec_probe(struct i2c_adapter *adap, int addr, int kind)
{
struct snd_soc_device *socdev = wm8580_socdev;
+ struct wm8580_setup_data *setup = socdev->codec_data;
struct snd_soc_codec *codec = socdev->codec;
+ struct i2c_client *i2c;
int ret;
+ if (addr != setup->i2c_address)
+ return -ENODEV;
+
+ client_template.adapter = adap;
+ client_template.addr = addr;
+
+ i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+ if (i2c == NULL) {
+ kfree(codec);
+ return -ENOMEM;
+ }
i2c_set_clientdata(i2c, codec);
codec->control_data = i2c;
+ ret = i2c_attach_client(i2c);
+ if (ret < 0) {
+ dev_err(&i2c->dev, "failed to attach codec at addr %x\n", addr);
+ goto err;
+ }
+
ret = wm8580_init(socdev);
- if (ret < 0)
+ if (ret < 0) {
dev_err(&i2c->dev, "failed to initialise WM8580\n");
+ goto err;
+ }
+
+ return ret;
+
+err:
+ kfree(codec);
+ kfree(i2c);
return ret;
}
-static int wm8580_i2c_remove(struct i2c_client *client)
+static int wm8580_i2c_detach(struct i2c_client *client)
{
struct snd_soc_codec *codec = i2c_get_clientdata(client);
+ i2c_detach_client(client);
kfree(codec->reg_cache);
+ kfree(client);
return 0;
}
-static const struct i2c_device_id wm8580_i2c_id[] = {
- { "wm8580", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id);
+static int wm8580_i2c_attach(struct i2c_adapter *adap)
+{
+ return i2c_probe(adap, &addr_data, wm8580_codec_probe);
+}
+/* corgi i2c codec control layer */
static struct i2c_driver wm8580_i2c_driver = {
.driver = {
.name = "WM8580 I2C Codec",
.owner = THIS_MODULE,
},
- .probe = wm8580_i2c_probe,
- .remove = wm8580_i2c_remove,
- .id_table = wm8580_i2c_id,
+ .attach_adapter = wm8580_i2c_attach,
+ .detach_client = wm8580_i2c_detach,
+ .command = NULL,
};
-static int wm8580_add_i2c_device(struct platform_device *pdev,
- const struct wm8580_setup_data *setup)
-{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- int ret;
-
- ret = i2c_add_driver(&wm8580_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- return ret;
- }
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = setup->i2c_address;
- strlcpy(info.type, "wm8580", I2C_NAME_SIZE);
-
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "can't get i2c adapter %d\n",
- setup->i2c_bus);
- goto err_driver;
- }
-
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
- (unsigned int)info.addr);
- goto err_driver;
- }
-
- return 0;
-
-err_driver:
- i2c_del_driver(&wm8580_i2c_driver);
- return -ENODEV;
-}
+static struct i2c_client client_template = {
+ .name = "WM8580",
+ .driver = &wm8580_i2c_driver,
+};
#endif
static int wm8580_probe(struct platform_device *pdev)
@@ -1007,8 +1011,11 @@ static int wm8580_probe(struct platform_device *pdev)
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
if (setup->i2c_address) {
+ normal_i2c[0] = setup->i2c_address;
codec->hw_write = (hw_write_t)i2c_master_send;
- ret = wm8580_add_i2c_device(pdev, setup);
+ ret = i2c_add_driver(&wm8580_i2c_driver);
+ if (ret != 0)
+ printk(KERN_ERR "can't add i2c driver");
}
#else
/* Add other interfaces here */
@@ -1027,7 +1034,6 @@ static int wm8580_remove(struct platform_device *pdev)
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_unregister_device(codec->control_data);
i2c_del_driver(&wm8580_i2c_driver);
#endif
kfree(codec->private_data);
@@ -1042,18 +1048,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8580 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8580);
-static int __devinit wm8580_modinit(void)
-{
- return snd_soc_register_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
-}
-module_init(wm8580_modinit);
-
-static void __exit wm8580_exit(void)
-{
- snd_soc_unregister_dais(wm8580_dai, ARRAY_SIZE(wm8580_dai));
-}
-module_exit(wm8580_exit);
-
MODULE_DESCRIPTION("ASoC WM8580 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8580.h b/sound/soc/codecs/wm8580.h
index 09e4422f6f2f..589ddaba21d7 100644
--- a/sound/soc/codecs/wm8580.h
+++ b/sound/soc/codecs/wm8580.h
@@ -29,7 +29,6 @@
#define WM8580_CLKSRC_NONE 5
struct wm8580_setup_data {
- int i2c_bus;
unsigned short i2c_address;
};
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c
deleted file mode 100644
index d905e25b1a93..000000000000
--- a/sound/soc/codecs/wm8728.c
+++ /dev/null
@@ -1,585 +0,0 @@
-/*
- * wm8728.c -- WM8728 ALSA SoC Audio driver
- *
- * Copyright 2008 Wolfson Microelectronics plc
- *
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/pm.h>
-#include <linux/i2c.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/initval.h>
-#include <sound/tlv.h>
-
-#include "wm8728.h"
-
-struct snd_soc_codec_device soc_codec_dev_wm8728;
-
-/*
- * We can't read the WM8728 register space so we cache them instead.
- * Note that the defaults here aren't the physical defaults, we latch
- * the volume update bits, mute the output and enable infinite zero
- * detect.
- */
-static const u16 wm8728_reg_defaults[] = {
- 0x1ff,
- 0x1ff,
- 0x001,
- 0x100,
-};
-
-static inline unsigned int wm8728_read_reg_cache(struct snd_soc_codec *codec,
- unsigned int reg)
-{
- u16 *cache = codec->reg_cache;
- BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
- return cache[reg];
-}
-
-static inline void wm8728_write_reg_cache(struct snd_soc_codec *codec,
- u16 reg, unsigned int value)
-{
- u16 *cache = codec->reg_cache;
- BUG_ON(reg > ARRAY_SIZE(wm8728_reg_defaults));
- cache[reg] = value;
-}
-
-/*
- * write to the WM8728 register space
- */
-static int wm8728_write(struct snd_soc_codec *codec, unsigned int reg,
- unsigned int value)
-{
- u8 data[2];
-
- /* data is
- * D15..D9 WM8728 register offset
- * D8...D0 register data
- */
- data[0] = (reg << 1) | ((value >> 8) & 0x0001);
- data[1] = value & 0x00ff;
-
- wm8728_write_reg_cache(codec, reg, value);
-
- if (codec->hw_write(codec->control_data, data, 2) == 2)
- return 0;
- else
- return -EIO;
-}
-
-static const DECLARE_TLV_DB_SCALE(wm8728_tlv, -12750, 50, 1);
-
-static const struct snd_kcontrol_new wm8728_snd_controls[] = {
-
-SOC_DOUBLE_R_TLV("Digital Playback Volume", WM8728_DACLVOL, WM8728_DACRVOL,
- 0, 255, 0, wm8728_tlv),
-
-SOC_SINGLE("Deemphasis", WM8728_DACCTL, 1, 1, 0),
-};
-
-static int wm8728_add_controls(struct snd_soc_codec *codec)
-{
- int err, i;
-
- for (i = 0; i < ARRAY_SIZE(wm8728_snd_controls); i++) {
- err = snd_ctl_add(codec->card,
- snd_soc_cnew(&wm8728_snd_controls[i],
- codec, NULL));
- if (err < 0)
- return err;
- }
-
- return 0;
-}
-
-/*
- * DAPM controls.
- */
-static const struct snd_soc_dapm_widget wm8728_dapm_widgets[] = {
-SND_SOC_DAPM_DAC("DAC", "HiFi Playback", SND_SOC_NOPM, 0, 0),
-SND_SOC_DAPM_OUTPUT("VOUTL"),
-SND_SOC_DAPM_OUTPUT("VOUTR"),
-};
-
-static const struct snd_soc_dapm_route intercon[] = {
- {"VOUTL", NULL, "DAC"},
- {"VOUTR", NULL, "DAC"},
-};
-
-static int wm8728_add_widgets(struct snd_soc_codec *codec)
-{
- snd_soc_dapm_new_controls(codec, wm8728_dapm_widgets,
- ARRAY_SIZE(wm8728_dapm_widgets));
-
- snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon));
-
- snd_soc_dapm_new_widgets(codec);
-
- return 0;
-}
-
-static int wm8728_mute(struct snd_soc_dai *dai, int mute)
-{
- struct snd_soc_codec *codec = dai->codec;
- u16 mute_reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
-
- if (mute)
- wm8728_write(codec, WM8728_DACCTL, mute_reg | 1);
- else
- wm8728_write(codec, WM8728_DACCTL, mute_reg & ~1);
-
- return 0;
-}
-
-static int wm8728_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_codec *codec = socdev->codec;
- u16 dac = wm8728_read_reg_cache(codec, WM8728_DACCTL);
-
- dac &= ~0x18;
-
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
- break;
- case SNDRV_PCM_FORMAT_S20_3LE:
- dac |= 0x10;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- dac |= 0x08;
- break;
- default:
- return -EINVAL;
- }
-
- wm8728_write(codec, WM8728_DACCTL, dac);
-
- return 0;
-}
-
-static int wm8728_set_dai_fmt(struct snd_soc_dai *codec_dai,
- unsigned int fmt)
-{
- struct snd_soc_codec *codec = codec_dai->codec;
- u16 iface = wm8728_read_reg_cache(codec, WM8728_IFCTL);
-
- /* Currently only I2S is supported by the driver, though the
- * hardware is more flexible.
- */
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- iface |= 1;
- break;
- default:
- return -EINVAL;
- }
-
- /* The hardware only support full slave mode */
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBS_CFS:
- break;
- default:
- return -EINVAL;
- }
-
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- iface &= ~0x22;
- break;
- case SND_SOC_DAIFMT_IB_NF:
- iface |= 0x20;
- iface &= ~0x02;
- break;
- case SND_SOC_DAIFMT_NB_IF:
- iface |= 0x02;
- iface &= ~0x20;
- break;
- case SND_SOC_DAIFMT_IB_IF:
- iface |= 0x22;
- break;
- default:
- return -EINVAL;
- }
-
- wm8728_write(codec, WM8728_IFCTL, iface);
- return 0;
-}
-
-static int wm8728_set_bias_level(struct snd_soc_codec *codec,
- enum snd_soc_bias_level level)
-{
- u16 reg;
- int i;
-
- switch (level) {
- case SND_SOC_BIAS_ON:
- case SND_SOC_BIAS_PREPARE:
- case SND_SOC_BIAS_STANDBY:
- if (codec->bias_level == SND_SOC_BIAS_OFF) {
- /* Power everything up... */
- reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
- wm8728_write(codec, WM8728_DACCTL, reg & ~0x4);
-
- /* ..then sync in the register cache. */
- for (i = 0; i < ARRAY_SIZE(wm8728_reg_defaults); i++)
- wm8728_write(codec, i,
- wm8728_read_reg_cache(codec, i));
- }
- break;
-
- case SND_SOC_BIAS_OFF:
- reg = wm8728_read_reg_cache(codec, WM8728_DACCTL);
- wm8728_write(codec, WM8728_DACCTL, reg | 0x4);
- break;
- }
- codec->bias_level = level;
- return 0;
-}
-
-#define WM8728_RATES (SNDRV_PCM_RATE_8000_192000)
-
-#define WM8728_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\
- SNDRV_PCM_FMTBIT_S24_LE)
-
-struct snd_soc_dai wm8728_dai = {
- .name = "WM8728",
- .playback = {
- .stream_name = "Playback",
- .channels_min = 2,
- .channels_max = 2,
- .rates = WM8728_RATES,
- .formats = WM8728_FORMATS,
- },
- .ops = {
- .hw_params = wm8728_hw_params,
- .digital_mute = wm8728_mute,
- .set_fmt = wm8728_set_dai_fmt,
- }
-};
-EXPORT_SYMBOL_GPL(wm8728_dai);
-
-static int wm8728_suspend(struct platform_device *pdev, pm_message_t state)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- return 0;
-}
-
-static int wm8728_resume(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- wm8728_set_bias_level(codec, codec->suspend_bias_level);
-
- return 0;
-}
-
-/*
- * initialise the WM8728 driver
- * register the mixer and dsp interfaces with the kernel
- */
-static int wm8728_init(struct snd_soc_device *socdev)
-{
- struct snd_soc_codec *codec = socdev->codec;
- int ret = 0;
-
- codec->name = "WM8728";
- codec->owner = THIS_MODULE;
- codec->read = wm8728_read_reg_cache;
- codec->write = wm8728_write;
- codec->set_bias_level = wm8728_set_bias_level;
- codec->dai = &wm8728_dai;
- codec->num_dai = 1;
- codec->bias_level = SND_SOC_BIAS_OFF;
- codec->reg_cache_size = ARRAY_SIZE(wm8728_reg_defaults);
- codec->reg_cache = kmemdup(wm8728_reg_defaults,
- sizeof(wm8728_reg_defaults),
- GFP_KERNEL);
- if (codec->reg_cache == NULL)
- return -ENOMEM;
-
- /* register pcms */
- ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
- if (ret < 0) {
- printk(KERN_ERR "wm8728: failed to create pcms\n");
- goto pcm_err;
- }
-
- /* power on device */
- wm8728_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
-
- wm8728_add_controls(codec);
- wm8728_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
- if (ret < 0) {
- printk(KERN_ERR "wm8728: failed to register card\n");
- goto card_err;
- }
-
- return ret;
-
-card_err:
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-pcm_err:
- kfree(codec->reg_cache);
- return ret;
-}
-
-static struct snd_soc_device *wm8728_socdev;
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
-
-/*
- * WM8728 2 wire address is determined by GPIO5
- * state during powerup.
- * low = 0x1a
- * high = 0x1b
- */
-
-static int wm8728_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
-{
- struct snd_soc_device *socdev = wm8728_socdev;
- struct snd_soc_codec *codec = socdev->codec;
- int ret;
-
- i2c_set_clientdata(i2c, codec);
- codec->control_data = i2c;
-
- ret = wm8728_init(socdev);
- if (ret < 0)
- pr_err("failed to initialise WM8728\n");
-
- return ret;
-}
-
-static int wm8728_i2c_remove(struct i2c_client *client)
-{
- struct snd_soc_codec *codec = i2c_get_clientdata(client);
- kfree(codec->reg_cache);
- return 0;
-}
-
-static const struct i2c_device_id wm8728_i2c_id[] = {
- { "wm8728", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id);
-
-static struct i2c_driver wm8728_i2c_driver = {
- .driver = {
- .name = "WM8728 I2C Codec",
- .owner = THIS_MODULE,
- },
- .probe = wm8728_i2c_probe,
- .remove = wm8728_i2c_remove,
- .id_table = wm8728_i2c_id,
-};
-
-static int wm8728_add_i2c_device(struct platform_device *pdev,
- const struct wm8728_setup_data *setup)
-{
- struct i2c_board_info info;
- struct i2c_adapter *adapter;
- struct i2c_client *client;
- int ret;
-
- ret = i2c_add_driver(&wm8728_i2c_driver);
- if (ret != 0) {
- dev_err(&pdev->dev, "can't add i2c driver\n");
- return ret;
- }
-
- memset(&info, 0, sizeof(struct i2c_board_info));
- info.addr = setup->i2c_address;
- strlcpy(info.type, "wm8728", I2C_NAME_SIZE);
-
- adapter = i2c_get_adapter(setup->i2c_bus);
- if (!adapter) {
- dev_err(&pdev->dev, "can't get i2c adapter %d\n",
- setup->i2c_bus);
- goto err_driver;
- }
-
- client = i2c_new_device(adapter, &info);
- i2c_put_adapter(adapter);
- if (!client) {
- dev_err(&pdev->dev, "can't add i2c device at 0x%x\n",
- (unsigned int)info.addr);
- goto err_driver;
- }
-
- return 0;
-
-err_driver:
- i2c_del_driver(&wm8728_i2c_driver);
- return -ENODEV;
-}
-#endif
-
-#if defined(CONFIG_SPI_MASTER)
-static int __devinit wm8728_spi_probe(struct spi_device *spi)
-{
- struct snd_soc_device *socdev = wm8728_socdev;
- struct snd_soc_codec *codec = socdev->codec;
- int ret;
-
- codec->control_data = spi;
-
- ret = wm8728_init(socdev);
- if (ret < 0)
- dev_err(&spi->dev, "failed to initialise WM8728\n");
-
- return ret;
-}
-
-static int __devexit wm8728_spi_remove(struct spi_device *spi)
-{
- return 0;
-}
-
-static struct spi_driver wm8728_spi_driver = {
- .driver = {
- .name = "wm8728",
- .bus = &spi_bus_type,
- .owner = THIS_MODULE,
- },
- .probe = wm8728_spi_probe,
- .remove = __devexit_p(wm8728_spi_remove),
-};
-
-static int wm8728_spi_write(struct spi_device *spi, const char *data, int len)
-{
- struct spi_transfer t;
- struct spi_message m;
- u8 msg[2];
-
- if (len <= 0)
- return 0;
-
- msg[0] = data[0];
- msg[1] = data[1];
-
- spi_message_init(&m);
- memset(&t, 0, (sizeof t));
-
- t.tx_buf = &msg[0];
- t.len = len;
-
- spi_message_add_tail(&t, &m);
- spi_sync(spi, &m);
-
- return len;
-}
-#endif /* CONFIG_SPI_MASTER */
-
-static int wm8728_probe(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct wm8728_setup_data *setup;
- struct snd_soc_codec *codec;
- int ret = 0;
-
- setup = socdev->codec_data;
- codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
- if (codec == NULL)
- return -ENOMEM;
-
- socdev->codec = codec;
- mutex_init(&codec->mutex);
- INIT_LIST_HEAD(&codec->dapm_widgets);
- INIT_LIST_HEAD(&codec->dapm_paths);
-
- wm8728_socdev = socdev;
- ret = -ENODEV;
-
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- if (setup->i2c_address) {
- codec->hw_write = (hw_write_t)i2c_master_send;
- ret = wm8728_add_i2c_device(pdev, setup);
- }
-#endif
-#if defined(CONFIG_SPI_MASTER)
- if (setup->spi) {
- codec->hw_write = (hw_write_t)wm8728_spi_write;
- ret = spi_register_driver(&wm8728_spi_driver);
- if (ret != 0)
- printk(KERN_ERR "can't add spi driver");
- }
-#endif
-
- if (ret != 0)
- kfree(codec);
-
- return ret;
-}
-
-/* power down chip */
-static int wm8728_remove(struct platform_device *pdev)
-{
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_codec *codec = socdev->codec;
-
- if (codec->control_data)
- wm8728_set_bias_level(codec, SND_SOC_BIAS_OFF);
-
- snd_soc_free_pcms(socdev);
- snd_soc_dapm_free(socdev);
-#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
- i2c_unregister_device(codec->control_data);
- i2c_del_driver(&wm8728_i2c_driver);
-#endif
-#if defined(CONFIG_SPI_MASTER)
- spi_unregister_driver(&wm8728_spi_driver);
-#endif
- kfree(codec);
-
- return 0;
-}
-
-struct snd_soc_codec_device soc_codec_dev_wm8728 = {
- .probe = wm8728_probe,
- .remove = wm8728_remove,
- .suspend = wm8728_suspend,
- .resume = wm8728_resume,
-};
-EXPORT_SYMBOL_GPL(soc_codec_dev_wm8728);
-
-static int __devinit wm8728_modinit(void)
-{
- return snd_soc_register_dai(&wm8728_dai);
-}
-module_init(wm8728_modinit);
-
-static void __exit wm8728_exit(void)
-{
- snd_soc_unregister_dai(&wm8728_dai);
-}
-module_exit(wm8728_exit);
-
-MODULE_DESCRIPTION("ASoC WM8728 driver");
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8728.h b/sound/soc/codecs/wm8728.h
deleted file mode 100644
index d269c132474b..000000000000
--- a/sound/soc/codecs/wm8728.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * wm8728.h -- WM8728 ASoC codec driver
- *
- * Copyright 2008 Wolfson Microelectronics plc
- *
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _WM8728_H
-#define _WM8728_H
-
-#define WM8728_DACLVOL 0x00
-#define WM8728_DACRVOL 0x01
-#define WM8728_DACCTL 0x02
-#define WM8728_IFCTL 0x03
-
-struct wm8728_setup_data {
- int spi;
- int i2c_bus;
- unsigned short i2c_address;
-};
-
-extern struct snd_soc_dai wm8728_dai;
-extern struct snd_soc_codec_device soc_codec_dev_wm8728;
-
-#endif
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c
index 7b455a60d719..7f8a7e36b33e 100644
--- a/sound/soc/codecs/wm8731.c
+++ b/sound/soc/codecs/wm8731.c
@@ -264,8 +264,7 @@ static inline int get_coeff(int mclk, int rate)
}
static int wm8731_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -294,8 +293,7 @@ static int wm8731_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int wm8731_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -307,8 +305,7 @@ static int wm8731_pcm_prepare(struct snd_pcm_substream *substream,
return 0;
}
-static void wm8731_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void wm8731_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -464,6 +461,8 @@ struct snd_soc_dai wm8731_dai = {
.prepare = wm8731_pcm_prepare,
.hw_params = wm8731_hw_params,
.shutdown = wm8731_shutdown,
+ },
+ .dai_ops = {
.digital_mute = wm8731_mute,
.set_sysclk = wm8731_set_dai_sysclk,
.set_fmt = wm8731_set_dai_fmt,
@@ -545,7 +544,7 @@ static int wm8731_init(struct snd_soc_device *socdev)
wm8731_add_controls(codec);
wm8731_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8731: failed to register card\n");
goto card_err;
@@ -793,18 +792,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8731 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8731);
-static int __devinit wm8731_modinit(void)
-{
- return snd_soc_register_dai(&wm8731_dai);
-}
-module_init(wm8731_modinit);
-
-static void __exit wm8731_exit(void)
-{
- snd_soc_unregister_dai(&wm8731_dai);
-}
-module_exit(wm8731_exit);
-
MODULE_DESCRIPTION("ASoC WM8731 driver");
MODULE_AUTHOR("Richard Purdie");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c
index 84a6307de907..9b7296ee5b08 100644
--- a/sound/soc/codecs/wm8750.c
+++ b/sound/soc/codecs/wm8750.c
@@ -614,8 +614,7 @@ static int wm8750_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
static int wm8750_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -710,6 +709,8 @@ struct snd_soc_dai wm8750_dai = {
.formats = WM8750_FORMATS,},
.ops = {
.hw_params = wm8750_pcm_hw_params,
+ },
+ .dai_ops = {
.digital_mute = wm8750_mute,
.set_fmt = wm8750_set_dai_fmt,
.set_sysclk = wm8750_set_dai_sysclk,
@@ -818,7 +819,7 @@ static int wm8750_init(struct snd_soc_device *socdev)
wm8750_add_controls(codec);
wm8750_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8750: failed to register card\n");
goto card_err;
@@ -1085,18 +1086,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8750 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8750);
-static int __devinit wm8750_modinit(void)
-{
- return snd_soc_register_dai(&wm8750_dai);
-}
-module_init(wm8750_modinit);
-
-static void __exit wm8750_exit(void)
-{
- snd_soc_unregister_dai(&wm8750_dai);
-}
-module_exit(wm8750_exit);
-
MODULE_DESCRIPTION("ASoC WM8750 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c
index 1caca30d0812..d426eaa22185 100644
--- a/sound/soc/codecs/wm8753.c
+++ b/sound/soc/codecs/wm8753.c
@@ -922,8 +922,7 @@ static int wm8753_vdac_adc_set_dai_fmt(struct snd_soc_dai *codec_dai,
* Set PCM DAI bit size and sample rate.
*/
static int wm8753_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1156,8 +1155,7 @@ static int wm8753_i2s_set_dai_fmt(struct snd_soc_dai *codec_dai,
* Set PCM DAI bit size and sample rate.
*/
static int wm8753_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1325,15 +1323,16 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.channels_min = 1,
.channels_max = 2,
.rates = WM8753_RATES,
- .formats = WM8753_FORMATS},
+ .formats = WM8753_FORMATS,},
.capture = { /* dummy for fast DAI switching */
.stream_name = "Capture",
.channels_min = 1,
.channels_max = 2,
.rates = WM8753_RATES,
- .formats = WM8753_FORMATS},
+ .formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_i2s_hw_params,
+ .hw_params = wm8753_i2s_hw_params,},
+ .dai_ops = {
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode1h_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1357,7 +1356,8 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_pcm_hw_params,
+ .hw_params = wm8753_pcm_hw_params,},
+ .dai_ops = {
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode1v_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1385,7 +1385,8 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_pcm_hw_params,
+ .hw_params = wm8753_pcm_hw_params,},
+ .dai_ops = {
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode2_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1409,7 +1410,8 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_i2s_hw_params,
+ .hw_params = wm8753_i2s_hw_params,},
+ .dai_ops = {
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode3_4_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1437,7 +1439,8 @@ static const struct snd_soc_dai wm8753_all_dai[] = {
.rates = WM8753_RATES,
.formats = WM8753_FORMATS,},
.ops = {
- .hw_params = wm8753_i2s_hw_params,
+ .hw_params = wm8753_i2s_hw_params,},
+ .dai_ops = {
.digital_mute = wm8753_mute,
.set_fmt = wm8753_mode3_4_set_dai_fmt,
.set_clkdiv = wm8753_set_dai_clkdiv,
@@ -1605,7 +1608,7 @@ static int wm8753_init(struct snd_soc_device *socdev)
wm8753_add_controls(codec);
wm8753_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8753: failed to register card\n");
goto card_err;
@@ -1874,18 +1877,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8753 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8753);
-static int __devinit wm8753_modinit(void)
-{
- return snd_soc_register_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
-}
-module_init(wm8753_modinit);
-
-static void __exit wm8753_exit(void)
-{
- snd_soc_unregister_dais(wm8753_dai, ARRAY_SIZE(wm8753_dai));
-}
-module_exit(wm8753_exit);
-
MODULE_DESCRIPTION("ASoC WM8753 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8900.c b/sound/soc/codecs/wm8900.c
index 34e58af0c65a..3b326c9b5586 100644
--- a/sound/soc/codecs/wm8900.c
+++ b/sound/soc/codecs/wm8900.c
@@ -727,8 +727,7 @@ static int wm8900_add_widgets(struct snd_soc_codec *codec)
}
static int wm8900_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1118,6 +1117,8 @@ struct snd_soc_dai wm8900_dai = {
},
.ops = {
.hw_params = wm8900_hw_params,
+ },
+ .dai_ops = {
.set_clkdiv = wm8900_set_dai_clkdiv,
.set_pll = wm8900_set_dai_pll,
.set_fmt = wm8900_set_dai_fmt,
@@ -1365,7 +1366,7 @@ static int wm8900_init(struct snd_soc_device *socdev)
wm8900_add_controls(codec);
wm8900_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
dev_err(&i2c_client->dev, "Failed to register card\n");
goto card_err;
@@ -1382,51 +1383,105 @@ priv_err:
return ret;
}
-static struct i2c_client *wm8900_client;
+static struct snd_soc_device *wm8900_socdev;
+
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+
+static unsigned short normal_i2c[] = { 0, I2C_CLIENT_END };
-static int wm8900_i2c_probe(struct i2c_client *i2c,
- const struct i2c_device_id *id)
+/* Magic definition of all other variables and things */
+I2C_CLIENT_INSMOD;
+
+static struct i2c_driver wm8900_i2c_driver;
+static struct i2c_client client_template;
+
+/* If the i2c layer weren't so broken, we could pass this kind of data
+ around */
+static int wm8900_codec_probe(struct i2c_adapter *adap, int addr, int kind)
{
- wm8900_client = i2c;
- wm8900_dai.dev = &i2c->dev;
- return snd_soc_register_dai(&wm8900_dai);
+ struct snd_soc_device *socdev = wm8900_socdev;
+ struct wm8900_setup_data *setup = socdev->codec_data;
+ struct snd_soc_codec *codec = socdev->codec;
+ struct i2c_client *i2c;
+ int ret;
+
+ if (addr != setup->i2c_address)
+ return -ENODEV;
+
+ dev_err(&adap->dev, "Probe on %x\n", addr);
+
+ client_template.adapter = adap;
+ client_template.addr = addr;
+
+ i2c = kmemdup(&client_template, sizeof(client_template), GFP_KERNEL);
+ if (i2c == NULL) {
+ kfree(codec);
+ return -ENOMEM;
+ }
+ i2c_set_clientdata(i2c, codec);
+ codec->control_data = i2c;
+
+ ret = i2c_attach_client(i2c);
+ if (ret < 0) {
+ dev_err(&adap->dev,
+ "failed to attach codec at addr %x\n", addr);
+ goto err;
+ }
+
+ ret = wm8900_init(socdev);
+ if (ret < 0) {
+ dev_err(&adap->dev, "failed to initialise WM8900\n");
+ goto err;
+ }
+ return ret;
+
+err:
+ kfree(codec);
+ kfree(i2c);
+ return ret;
}
-static int wm8900_i2c_remove(struct i2c_client *client)
+static int wm8900_i2c_detach(struct i2c_client *client)
{
- snd_soc_unregister_dai(&wm8900_dai);
- wm8900_dai.dev = NULL;
- wm8900_client = NULL;
+ struct snd_soc_codec *codec = i2c_get_clientdata(client);
+ i2c_detach_client(client);
+ kfree(codec->reg_cache);
+ kfree(client);
return 0;
}
-static const struct i2c_device_id wm8900_i2c_id[] = {
- { "wm8900", 0 },
- { }
-};
-MODULE_DEVICE_TABLE(i2c, wm8900_i2c_id);
+static int wm8900_i2c_attach(struct i2c_adapter *adap)
+{
+ return i2c_probe(adap, &addr_data, wm8900_codec_probe);
+}
+/* corgi i2c codec control layer */
static struct i2c_driver wm8900_i2c_driver = {
.driver = {
.name = "WM8900 I2C codec",
.owner = THIS_MODULE,
},
- .probe = wm8900_i2c_probe,
- .remove = wm8900_i2c_remove,
- .id_table = wm8900_i2c_id,
+ .attach_adapter = wm8900_i2c_attach,
+ .detach_client = wm8900_i2c_detach,
+ .command = NULL,
};
+static struct i2c_client client_template = {
+ .name = "WM8900",
+ .driver = &wm8900_i2c_driver,
+};
+#endif
+
static int wm8900_probe(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct wm8900_setup_data *setup;
struct snd_soc_codec *codec;
int ret = 0;
- if (!wm8900_client) {
- dev_err(&pdev->dev, "I2C client not yet instantiated\n");
- return -ENODEV;
- }
+ dev_info(&pdev->dev, "WM8900 Audio Codec\n");
+ setup = socdev->codec_data;
codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL);
if (codec == NULL)
return -ENOMEM;
@@ -1439,13 +1494,18 @@ static int wm8900_probe(struct platform_device *pdev)
codec->set_bias_level = wm8900_set_bias_level;
- codec->hw_write = (hw_write_t)i2c_master_send;
- codec->control_data = wm8900_client;
-
- ret = wm8900_init(socdev);
- if (ret != 0)
- kfree(codec);
-
+ wm8900_socdev = socdev;
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ if (setup->i2c_address) {
+ normal_i2c[0] = setup->i2c_address;
+ codec->hw_write = (hw_write_t)i2c_master_send;
+ ret = i2c_add_driver(&wm8900_i2c_driver);
+ if (ret != 0)
+ printk(KERN_ERR "can't add i2c driver");
+ }
+#else
+#error Non-I2C interfaces not yet supported
+#endif
return ret;
}
@@ -1460,6 +1520,9 @@ static int wm8900_remove(struct platform_device *pdev)
snd_soc_free_pcms(socdev);
snd_soc_dapm_free(socdev);
+#if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE)
+ i2c_del_driver(&wm8900_i2c_driver);
+#endif
kfree(codec);
return 0;
@@ -1473,18 +1536,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8900 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8900);
-static int __devinit wm8900_modinit(void)
-{
- return i2c_add_driver(&wm8900_i2c_driver);
-}
-module_init(wm8900_modinit);
-
-static void __exit wm8900_exit(void)
-{
- i2c_del_driver(&wm8900_i2c_driver);
-}
-module_exit(wm8900_exit);
-
MODULE_DESCRIPTION("ASoC WM8900 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8900.h b/sound/soc/codecs/wm8900.h
index 2249a446ad37..ba450d99e902 100644
--- a/sound/soc/codecs/wm8900.h
+++ b/sound/soc/codecs/wm8900.h
@@ -55,7 +55,6 @@
#define WM8900_
struct wm8900_setup_data {
- int i2c_bus;
unsigned short i2c_address;
};
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index 5d8fe7e1571e..ce40d7877605 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -773,14 +773,14 @@ static const struct snd_kcontrol_new left_output_mixer[] = {
SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0),
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0),
SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0),
-SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 0, 1, 0),
+SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0),
};
static const struct snd_kcontrol_new right_output_mixer[] = {
SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0),
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0),
SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0),
-SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 0, 1, 0),
+SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0),
};
static const struct snd_kcontrol_new left_speaker_mixer[] = {
@@ -788,7 +788,7 @@ SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 3, 1, 0),
SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0),
SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0),
SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0,
- 0, 1, 0),
+ 1, 1, 0),
};
static const struct snd_kcontrol_new right_speaker_mixer[] = {
@@ -797,7 +797,7 @@ SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 2, 1, 0),
SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
1, 1, 0),
SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0,
- 0, 1, 0),
+ 1, 1, 0),
};
static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = {
@@ -1257,8 +1257,7 @@ static struct {
{ 0, 0 },
};
-static int wm8903_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int wm8903_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1299,8 +1298,7 @@ static int wm8903_startup(struct snd_pcm_substream *substream,
return 0;
}
-static void wm8903_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void wm8903_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1319,8 +1317,7 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream,
}
static int wm8903_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1518,6 +1515,8 @@ struct snd_soc_dai wm8903_dai = {
.startup = wm8903_startup,
.shutdown = wm8903_shutdown,
.hw_params = wm8903_hw_params,
+ },
+ .dai_ops = {
.digital_mute = wm8903_digital_mute,
.set_fmt = wm8903_set_dai_fmt,
.set_sysclk = wm8903_set_dai_sysclk
@@ -1648,7 +1647,7 @@ static int wm8903_init(struct snd_soc_device *socdev)
wm8903_add_controls(codec);
wm8903_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
dev_err(&i2c->dev, "wm8903: failed to register card\n");
goto card_err;
@@ -1809,18 +1808,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8903 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903);
-static int __devinit wm8903_modinit(void)
-{
- return snd_soc_register_dai(&wm8903_dai);
-}
-module_init(wm8903_modinit);
-
-static void __exit wm8903_exit(void)
-{
- snd_soc_unregister_dai(&wm8903_dai);
-}
-module_exit(wm8903_exit);
-
MODULE_DESCRIPTION("ASoC WM8903 driver");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c
index 2979fc4f44f1..f41a578ddd4f 100644
--- a/sound/soc/codecs/wm8971.c
+++ b/sound/soc/codecs/wm8971.c
@@ -541,8 +541,7 @@ static int wm8971_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
static int wm8971_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -635,6 +634,8 @@ struct snd_soc_dai wm8971_dai = {
.formats = WM8971_FORMATS,},
.ops = {
.hw_params = wm8971_pcm_hw_params,
+ },
+ .dai_ops = {
.digital_mute = wm8971_mute,
.set_fmt = wm8971_set_dai_fmt,
.set_sysclk = wm8971_set_dai_sysclk,
@@ -747,7 +748,7 @@ static int wm8971_init(struct snd_soc_device *socdev)
wm8971_add_controls(codec);
wm8971_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8971: failed to register card\n");
goto card_err;
@@ -935,18 +936,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8971 = {
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8971);
-static int __devinit wm8971_modinit(void)
-{
- return snd_soc_register_dai(&wm8971_dai);
-}
-module_init(wm8971_modinit);
-
-static void __exit wm8971_exit(void)
-{
- snd_soc_unregister_dai(&wm8971_dai);
-}
-module_exit(wm8971_exit);
-
MODULE_DESCRIPTION("ASoC WM8971 driver");
MODULE_AUTHOR("Lab126");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c
index 53e71aafe6c6..572d22b0880b 100644
--- a/sound/soc/codecs/wm8990.c
+++ b/sound/soc/codecs/wm8990.c
@@ -106,7 +106,6 @@ static const u16 wm8990_reg[] = {
0x0008, /* R60 - PLL1 */
0x0031, /* R61 - PLL2 */
0x0026, /* R62 - PLL3 */
- 0x0000, /* R63 - Driver internal */
};
/*
@@ -127,9 +126,10 @@ static inline void wm8990_write_reg_cache(struct snd_soc_codec *codec,
unsigned int reg, unsigned int value)
{
u16 *cache = codec->reg_cache;
+ BUG_ON(reg > (ARRAY_SIZE(wm8990_reg)) - 1);
- /* Reset register and reserved registers are uncached */
- if (reg == 0 || reg > ARRAY_SIZE(wm8990_reg) - 1)
+ /* Reset register is uncached */
+ if (reg == 0)
return;
cache[reg] = value;
@@ -1172,8 +1172,7 @@ static int wm8990_set_dai_clkdiv(struct snd_soc_dai *codec_dai,
* Set PCM DAI bit size and sample rate.
*/
static int wm8990_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
@@ -1223,14 +1222,8 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
switch (level) {
case SND_SOC_BIAS_ON:
break;
-
case SND_SOC_BIAS_PREPARE:
- /* VMID=2*50k */
- val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
- ~WM8990_VMID_MODE_MASK;
- wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x2);
break;
-
case SND_SOC_BIAS_STANDBY:
if (codec->bias_level == SND_SOC_BIAS_OFF) {
/* Enable all output discharge bits */
@@ -1279,17 +1272,10 @@ static int wm8990_set_bias_level(struct snd_soc_codec *codec,
/* disable POBCTRL, SOFT_ST and BUFDCOPEN */
wm8990_write(codec, WM8990_ANTIPOP2, WM8990_BUFIOEN);
+ } else {
+ /* ON -> standby */
- /* Enable workaround for ADC clocking issue. */
- wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0x2);
- wm8990_write(codec, WM8990_EXT_CTL1, 0xa003);
- wm8990_write(codec, WM8990_EXT_ACCESS_ENA, 0);
}
-
- /* VMID=2*250k */
- val = wm8990_read_reg_cache(codec, WM8990_POWER_MANAGEMENT_1) &
- ~WM8990_VMID_MODE_MASK;
- wm8990_write(codec, WM8990_POWER_MANAGEMENT_1, val | 0x4);
break;
case SND_SOC_BIAS_OFF:
@@ -1363,7 +1349,8 @@ struct snd_soc_dai wm8990_dai = {
.rates = WM8990_RATES,
.formats = WM8990_FORMATS,},
.ops = {
- .hw_params = wm8990_hw_params,
+ .hw_params = wm8990_hw_params,},
+ .dai_ops = {
.digital_mute = wm8990_mute,
.set_fmt = wm8990_set_dai_fmt,
.set_clkdiv = wm8990_set_dai_clkdiv,
@@ -1462,7 +1449,7 @@ static int wm8990_init(struct snd_soc_device *socdev)
wm8990_add_controls(codec);
wm8990_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm8990: failed to register card\n");
goto card_err;
@@ -1643,18 +1630,6 @@ struct snd_soc_codec_device soc_codec_dev_wm8990 = {
};
EXPORT_SYMBOL_GPL(soc_codec_dev_wm8990);
-static int __devinit wm8990_modinit(void)
-{
- return snd_soc_register_dai(&wm8990_dai);
-}
-module_init(wm8990_modinit);
-
-static void __exit wm8990_exit(void)
-{
- snd_soc_unregister_dai(&wm8990_dai);
-}
-module_exit(wm8990_exit);
-
MODULE_DESCRIPTION("ASoC WM8990 driver");
MODULE_AUTHOR("Liam Girdwood");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/codecs/wm8990.h b/sound/soc/codecs/wm8990.h
index 7114ddc88b4b..0e192f3b0788 100644
--- a/sound/soc/codecs/wm8990.h
+++ b/sound/soc/codecs/wm8990.h
@@ -80,8 +80,8 @@
#define WM8990_PLL3 0x3E
#define WM8990_INTDRIVBITS 0x3F
-#define WM8990_EXT_ACCESS_ENA 0x75
-#define WM8990_EXT_CTL1 0x7a
+#define WM8990_REGISTER_COUNT 60
+#define WM8990_MAX_REGISTER 0x3F
/*
* Field Definitions.
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c
index af83d629078a..ffb471e420e2 100644
--- a/sound/soc/codecs/wm9712.c
+++ b/sound/soc/codecs/wm9712.c
@@ -487,8 +487,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg,
return 0;
}
-static int ac97_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int ac97_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -508,8 +507,7 @@ static int ac97_prepare(struct snd_pcm_substream *substream,
return ac97_write(codec, reg, runtime->rate);
}
-static int ac97_aux_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int ac97_aux_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -535,7 +533,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai wm9712_dai[] = {
{
.name = "AC97 HiFi",
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97_BUS,
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -690,7 +688,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
ret = wm9712_reset(codec, 0);
if (ret < 0) {
- printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n");
+ printk(KERN_ERR "AC97 link error\n");
goto reset_err;
}
@@ -700,7 +698,7 @@ static int wm9712_soc_probe(struct platform_device *pdev)
wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY);
wm9712_add_controls(codec);
wm9712_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0) {
printk(KERN_ERR "wm9712: failed to register card\n");
goto reset_err;
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c
index f3ca8aaf0139..945b32ed9884 100644
--- a/sound/soc/codecs/wm9713.c
+++ b/sound/soc/codecs/wm9713.c
@@ -928,10 +928,11 @@ static int wm9713_set_dai_fmt(struct snd_soc_dai *codec_dai,
}
static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
- struct snd_soc_codec *codec = dai->codec;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
u16 reg = ac97_read(codec, AC97_CENTER_LFE_MASTER) & 0xfff3;
switch (params_format(params)) {
@@ -953,10 +954,11 @@ static int wm9713_pcm_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static void wm9713_voiceshutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void wm9713_voiceshutdown(struct snd_pcm_substream *substream)
{
- struct snd_soc_codec *codec = dai->codec;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
u16 status;
/* Gracefully shut down the voice interface. */
@@ -967,11 +969,12 @@ static void wm9713_voiceshutdown(struct snd_pcm_substream *substream,
ac97_write(codec, AC97_EXTENDED_MID, status);
}
-static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int ac97_hifi_prepare(struct snd_pcm_substream *substream)
{
- struct snd_soc_codec *codec = dai->codec;
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
int reg;
u16 vra;
@@ -986,11 +989,12 @@ static int ac97_hifi_prepare(struct snd_pcm_substream *substream,
return ac97_write(codec, reg, runtime->rate);
}
-static int ac97_aux_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int ac97_aux_prepare(struct snd_pcm_substream *substream)
{
- struct snd_soc_codec *codec = dai->codec;
struct snd_pcm_runtime *runtime = substream->runtime;
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_device *socdev = rtd->socdev;
+ struct snd_soc_codec *codec = socdev->codec;
u16 vra, xsle;
vra = ac97_read(codec, AC97_EXTENDED_STATUS);
@@ -1024,7 +1028,7 @@ static int ac97_aux_prepare(struct snd_pcm_substream *substream,
struct snd_soc_dai wm9713_dai[] = {
{
.name = "AC97 HiFi",
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97_BUS,
.playback = {
.stream_name = "HiFi Playback",
.channels_min = 1,
@@ -1038,7 +1042,8 @@ struct snd_soc_dai wm9713_dai[] = {
.rates = WM9713_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
- .prepare = ac97_hifi_prepare,
+ .prepare = ac97_hifi_prepare,},
+ .dai_ops = {
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,},
},
@@ -1051,7 +1056,8 @@ struct snd_soc_dai wm9713_dai[] = {
.rates = WM9713_RATES,
.formats = SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
- .prepare = ac97_aux_prepare,
+ .prepare = ac97_aux_prepare,},
+ .dai_ops = {
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,},
},
@@ -1071,7 +1077,8 @@ struct snd_soc_dai wm9713_dai[] = {
.formats = WM9713_PCM_FORMATS,},
.ops = {
.hw_params = wm9713_pcm_hw_params,
- .shutdown = wm9713_voiceshutdown,
+ .shutdown = wm9713_voiceshutdown,},
+ .dai_ops = {
.set_clkdiv = wm9713_set_dai_clkdiv,
.set_pll = wm9713_set_dai_pll,
.set_fmt = wm9713_set_dai_fmt,
@@ -1090,8 +1097,6 @@ int wm9713_reset(struct snd_soc_codec *codec, int try_warm)
}
soc_ac97_ops.reset(codec->ac97);
- if (soc_ac97_ops.warm_reset)
- soc_ac97_ops.warm_reset(codec->ac97);
if (ac97_read(codec, 0) != wm9713_reg[0])
return -EIO;
return 0;
@@ -1235,7 +1240,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
wm9713_reset(codec, 0);
ret = wm9713_reset(codec, 1);
if (ret < 0) {
- printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n");
+ printk(KERN_ERR "AC97 link error\n");
goto reset_err;
}
@@ -1247,7 +1252,7 @@ static int wm9713_soc_probe(struct platform_device *pdev)
wm9713_add_controls(codec);
wm9713_add_widgets(codec);
- ret = snd_soc_init_card(socdev);
+ ret = snd_soc_register_card(socdev);
if (ret < 0)
goto reset_err;
return 0;
@@ -1283,6 +1288,7 @@ static int wm9713_soc_remove(struct platform_device *pdev)
snd_soc_free_ac97_codec(codec);
kfree(codec->private_data);
kfree(codec->reg_cache);
+ kfree(codec->dai);
kfree(codec);
return 0;
}
diff --git a/sound/soc/davinci/Kconfig b/sound/soc/davinci/Kconfig
index b502741692d6..8f7e33834902 100644
--- a/sound/soc/davinci/Kconfig
+++ b/sound/soc/davinci/Kconfig
@@ -17,13 +17,3 @@ config SND_DAVINCI_SOC_EVM
help
Say Y if you want to add support for SoC audio on TI
DaVinci EVM platform.
-
-config SND_DAVINCI_SOC_SFFSDR
- tristate "SoC Audio support for SFFSDR"
- depends on SND_DAVINCI_SOC && MACH_DAVINCI_SFFSDR
- select SND_DAVINCI_SOC_I2S
- select SND_SOC_PCM3008
- select SFFSDR_FPGA
- help
- Say Y if you want to add support for SoC audio on
- Lyrtech SFFSDR board.
diff --git a/sound/soc/davinci/Makefile b/sound/soc/davinci/Makefile
index ca8bae1fc3f6..ca772e5b4637 100644
--- a/sound/soc/davinci/Makefile
+++ b/sound/soc/davinci/Makefile
@@ -7,7 +7,5 @@ obj-$(CONFIG_SND_DAVINCI_SOC_I2S) += snd-soc-davinci-i2s.o
# DAVINCI Machine Support
snd-soc-evm-objs := davinci-evm.o
-snd-soc-sffsdr-objs := davinci-sffsdr.o
obj-$(CONFIG_SND_DAVINCI_SOC_EVM) += snd-soc-evm.o
-obj-$(CONFIG_SND_DAVINCI_SOC_SFFSDR) += snd-soc-sffsdr.o
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c
index d87b91179cc8..9e6062cd6b59 100644
--- a/sound/soc/davinci/davinci-evm.c
+++ b/sound/soc/davinci/davinci-evm.c
@@ -128,9 +128,8 @@ static struct snd_soc_dai_link evm_dai = {
};
/* davinci-evm audio machine driver */
-static struct snd_soc_card snd_soc_card_evm = {
+static struct snd_soc_machine snd_soc_machine_evm = {
.name = "DaVinci EVM",
- .platform = &davinci_soc_platform,
.dai_link = &evm_dai,
.num_links = 1,
};
@@ -143,7 +142,8 @@ static struct aic3x_setup_data evm_aic3x_setup = {
/* evm audio subsystem */
static struct snd_soc_device evm_snd_devdata = {
- .card = &snd_soc_card_evm,
+ .machine = &snd_soc_machine_evm,
+ .platform = &davinci_soc_platform,
.codec_dev = &soc_codec_dev_aic3x,
.codec_data = &evm_aic3x_setup,
};
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c
index d89fc2f009ab..abb5fedb0b1e 100644
--- a/sound/soc/davinci/davinci-i2s.c
+++ b/sound/soc/davinci/davinci-i2s.c
@@ -59,7 +59,6 @@
#define DAVINCI_MCBSP_PCR_CLKXP (1 << 1)
#define DAVINCI_MCBSP_PCR_FSRP (1 << 2)
#define DAVINCI_MCBSP_PCR_FSXP (1 << 3)
-#define DAVINCI_MCBSP_PCR_SCLKME (1 << 7)
#define DAVINCI_MCBSP_PCR_CLKRM (1 << 8)
#define DAVINCI_MCBSP_PCR_CLKXM (1 << 9)
#define DAVINCI_MCBSP_PCR_FSRM (1 << 10)
@@ -111,59 +110,16 @@ static void davinci_mcbsp_start(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_mcbsp_dev *dev = rtd->dai->cpu_dai->private_data;
- struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_platform *platform = socdev->card->platform;
u32 w;
- int ret;
/* Start the sample generator and enable transmitter/receiver */
w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_GRST, 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
-
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
- /* Stop the DMA to avoid data loss */
- /* while the transmitter is out of reset to handle XSYNCERR */
- if (platform->pcm_ops->trigger) {
- ret = platform->pcm_ops->trigger(substream,
- SNDRV_PCM_TRIGGER_STOP);
- if (ret < 0)
- printk(KERN_DEBUG "Playback DMA stop failed\n");
- }
-
- /* Enable the transmitter */
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
-
- /* wait for any unexpected frame sync error to occur */
- udelay(100);
-
- /* Disable the transmitter to clear any outstanding XSYNCERR */
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 0);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
-
- /* Restart the DMA */
- if (platform->pcm_ops->trigger) {
- ret = platform->pcm_ops->trigger(substream,
- SNDRV_PCM_TRIGGER_START);
- if (ret < 0)
- printk(KERN_DEBUG "Playback DMA start failed\n");
- }
- /* Enable the transmitter */
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_XRST, 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
-
- } else {
-
- /* Enable the reciever */
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
+ else
MOD_REG_BIT(w, DAVINCI_MCBSP_SPCR_RRST, 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
- }
-
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
/* Start frame sync */
w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
@@ -188,8 +144,7 @@ static void davinci_mcbsp_stop(struct snd_pcm_substream *substream)
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
}
-static int davinci_i2s_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int davinci_i2s_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -216,16 +171,6 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG,
DAVINCI_MCBSP_SRGR_FSGM);
break;
- case SND_SOC_DAIFMT_CBM_CFS:
- /* McBSP CLKR pin is the input for the Sample Rate Generator.
- * McBSP FSR and FSX are driven by the Sample Rate Generator. */
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG,
- DAVINCI_MCBSP_PCR_SCLKME |
- DAVINCI_MCBSP_PCR_FSXM |
- DAVINCI_MCBSP_PCR_FSRM);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SRGR_REG,
- DAVINCI_MCBSP_SRGR_FSGM);
- break;
case SND_SOC_DAIFMT_CBM_CFM:
davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_PCR_REG, 0);
break;
@@ -260,34 +205,11 @@ static int davinci_i2s_set_dai_fmt(struct snd_soc_dai *cpu_dai,
return -EINVAL;
}
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_RIGHT_J:
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
- DAVINCI_MCBSP_RCR_RFRLEN1(1) |
- DAVINCI_MCBSP_RCR_RDATDLY(0));
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
- DAVINCI_MCBSP_XCR_XFRLEN1(1) |
- DAVINCI_MCBSP_XCR_XDATDLY(0) |
- DAVINCI_MCBSP_XCR_XFIG);
- break;
- case SND_SOC_DAIFMT_I2S:
- default:
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
- DAVINCI_MCBSP_RCR_RFRLEN1(1) |
- DAVINCI_MCBSP_RCR_RDATDLY(1));
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
- DAVINCI_MCBSP_XCR_XFRLEN1(1) |
- DAVINCI_MCBSP_XCR_XDATDLY(1) |
- DAVINCI_MCBSP_XCR_XFIG);
- break;
- }
-
return 0;
}
static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct davinci_pcm_dma_params *dma_params = rtd->dai->cpu_dai->dma_data;
@@ -297,14 +219,17 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
u32 w;
/* general line settings */
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SPCR_REG);
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- w |= DAVINCI_MCBSP_SPCR_RINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
- } else {
- w |= DAVINCI_MCBSP_SPCR_XINTM(3) | DAVINCI_MCBSP_SPCR_FREE;
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG, w);
- }
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_SPCR_REG,
+ DAVINCI_MCBSP_SPCR_RINTM(3) |
+ DAVINCI_MCBSP_SPCR_XINTM(3) |
+ DAVINCI_MCBSP_SPCR_FREE);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG,
+ DAVINCI_MCBSP_RCR_RFRLEN1(1) |
+ DAVINCI_MCBSP_RCR_RDATDLY(1));
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG,
+ DAVINCI_MCBSP_XCR_XFRLEN1(1) |
+ DAVINCI_MCBSP_XCR_XDATDLY(1) |
+ DAVINCI_MCBSP_XCR_XFIG);
i = hw_param_interval(params, SNDRV_PCM_HW_PARAM_SAMPLE_BITS);
w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_SRGR_REG);
@@ -335,24 +260,20 @@ static int davinci_i2s_hw_params(struct snd_pcm_substream *substream,
return -EINVAL;
}
- if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
- DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_RCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_RCR_RWDLEN1(mcbsp_word_length) |
+ DAVINCI_MCBSP_RCR_RWDLEN2(mcbsp_word_length), 1);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_RCR_REG, w);
- } else {
- w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
- MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
- DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
- davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
+ w = davinci_mcbsp_read_reg(dev, DAVINCI_MCBSP_XCR_REG);
+ MOD_REG_BIT(w, DAVINCI_MCBSP_XCR_XWDLEN1(mcbsp_word_length) |
+ DAVINCI_MCBSP_XCR_XWDLEN2(mcbsp_word_length), 1);
+ davinci_mcbsp_write_reg(dev, DAVINCI_MCBSP_XCR_REG, w);
- }
return 0;
}
-static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int davinci_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
{
int ret = 0;
@@ -378,8 +299,8 @@ static int davinci_i2s_probe(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
+ struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
struct davinci_mcbsp_dev *dev;
struct resource *mem, *ioarea;
struct evm_snd_platform_data *pdata;
@@ -440,8 +361,8 @@ static void davinci_i2s_remove(struct platform_device *pdev,
struct snd_soc_dai *dai)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_dai *cpu_dai = card->dai_link[pdev->id].cpu_dai;
+ struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_dai *cpu_dai = machine->dai_link[pdev->id].cpu_dai;
struct davinci_mcbsp_dev *dev = cpu_dai->private_data;
struct resource *mem;
@@ -460,6 +381,7 @@ static void davinci_i2s_remove(struct platform_device *pdev,
struct snd_soc_dai davinci_i2s_dai = {
.name = "davinci-i2s",
.id = 0,
+ .type = SND_SOC_DAI_I2S,
.probe = davinci_i2s_probe,
.remove = davinci_i2s_remove,
.playback = {
@@ -475,24 +397,13 @@ struct snd_soc_dai davinci_i2s_dai = {
.ops = {
.startup = davinci_i2s_startup,
.trigger = davinci_i2s_trigger,
- .hw_params = davinci_i2s_hw_params,
+ .hw_params = davinci_i2s_hw_params,},
+ .dai_ops = {
.set_fmt = davinci_i2s_set_dai_fmt,
},
};
EXPORT_SYMBOL_GPL(davinci_i2s_dai);
-static int __devinit davinci_i2s_init(void)
-{
- return snd_soc_register_dai(&davinci_i2s_dai);
-}
-module_init(davinci_i2s_init);
-
-static void __exit davinci_i2s_exit(void)
-{
- snd_soc_unregister_dai(&davinci_i2s_dai);
-}
-module_exit(davinci_i2s_exit);
-
MODULE_AUTHOR("Vladimir Barinov");
MODULE_DESCRIPTION("TI DAVINCI I2S (McBSP) SoC Interface");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c
index f1b6e02d24ed..76feaa657375 100644
--- a/sound/soc/davinci/davinci-pcm.c
+++ b/sound/soc/davinci/davinci-pcm.c
@@ -384,18 +384,6 @@ struct snd_soc_platform davinci_soc_platform = {
};
EXPORT_SYMBOL_GPL(davinci_soc_platform);
-static int __devinit davinci_soc_platform_init(void)
-{
- return snd_soc_register_platform(&davinci_soc_platform);
-}
-module_init(davinci_soc_platform_init);
-
-static void __exit davinci_soc_platform_exit(void)
-{
- snd_soc_unregister_platform(&davinci_soc_platform);
-}
-module_exit(davinci_soc_platform_exit);
-
MODULE_AUTHOR("Vladimir Barinov");
MODULE_DESCRIPTION("TI DAVINCI PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c
deleted file mode 100644
index f67579d52765..000000000000
--- a/sound/soc/davinci/davinci-sffsdr.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * ASoC driver for Lyrtech SFFSDR board.
- *
- * Author: Hugo Villeneuve
- * Copyright (C) 2008 Lyrtech inc
- *
- * Based on ASoC driver for TI DAVINCI EVM platform, original copyright follow:
- * Copyright: (C) 2007 MontaVista Software, Inc., <source@mvista.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <asm/dma.h>
-#include <asm/plat-sffsdr/sffsdr-fpga.h>
-
-#include <mach/mcbsp.h>
-#include <mach/edma.h>
-
-#include "../codecs/pcm3008.h"
-#include "davinci-pcm.h"
-#include "davinci-i2s.h"
-
-static int sffsdr_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int fs;
- int ret = 0;
-
- /* Set cpu DAI configuration:
- * CLKX and CLKR are the inputs for the Sample Rate Generator.
- * FSX and FSR are outputs, driven by the sample Rate Generator. */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_RIGHT_J |
- SND_SOC_DAIFMT_CBM_CFS |
- SND_SOC_DAIFMT_IB_NF);
- if (ret < 0)
- return ret;
-
- /* Fsref can be 32000, 44100 or 48000. */
- fs = params_rate(params);
-
- pr_debug("sffsdr_hw_params: rate = %d Hz\n", fs);
-
- return sffsdr_fpga_set_codec_fs(fs);
-}
-
-static struct snd_soc_ops sffsdr_ops = {
- .hw_params = sffsdr_hw_params,
-};
-
-/* davinci-sffsdr digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link sffsdr_dai = {
- .name = "PCM3008", /* Codec name */
- .stream_name = "PCM3008 HiFi",
- .cpu_dai = &davinci_i2s_dai,
- .codec_dai = &pcm3008_dai,
- .ops = &sffsdr_ops,
-};
-
-/* davinci-sffsdr audio machine driver */
-static struct snd_soc_card snd_soc_sffsdr = {
- .name = "DaVinci SFFSDR",
- .platform = &davinci_soc_platform,
- .dai_link = &sffsdr_dai,
- .num_links = 1,
-};
-
-/* sffsdr audio private data */
-static struct pcm3008_setup_data sffsdr_pcm3008_setup = {
- .dem0_pin = GPIO(45),
- .dem1_pin = GPIO(46),
- .pdad_pin = GPIO(47),
- .pdda_pin = GPIO(38),
-};
-
-/* sffsdr audio subsystem */
-static struct snd_soc_device sffsdr_snd_devdata = {
- .card = &snd_soc_sffsdr,
- .codec_dev = &soc_codec_dev_pcm3008,
- .codec_data = &sffsdr_pcm3008_setup,
-};
-
-static struct resource sffsdr_snd_resources[] = {
- {
- .start = DAVINCI_MCBSP_BASE,
- .end = DAVINCI_MCBSP_BASE + SZ_8K - 1,
- .flags = IORESOURCE_MEM,
- },
-};
-
-static struct evm_snd_platform_data sffsdr_snd_data = {
- .tx_dma_ch = DAVINCI_DMA_MCBSP_TX,
- .rx_dma_ch = DAVINCI_DMA_MCBSP_RX,
-};
-
-static struct platform_device *sffsdr_snd_device;
-
-static int __init sffsdr_init(void)
-{
- int ret;
-
- sffsdr_snd_device = platform_device_alloc("soc-audio", 0);
- if (!sffsdr_snd_device) {
- printk(KERN_ERR "platform device allocation failed\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(sffsdr_snd_device, &sffsdr_snd_devdata);
- sffsdr_snd_devdata.dev = &sffsdr_snd_device->dev;
- sffsdr_snd_device->dev.platform_data = &sffsdr_snd_data;
-
- ret = platform_device_add_resources(sffsdr_snd_device,
- sffsdr_snd_resources,
- ARRAY_SIZE(sffsdr_snd_resources));
- if (ret) {
- printk(KERN_ERR "platform device add ressources failed\n");
- goto error;
- }
-
- ret = platform_device_add(sffsdr_snd_device);
- if (ret)
- goto error;
-
- return ret;
-
-error:
- platform_device_put(sffsdr_snd_device);
- return ret;
-}
-
-static void __exit sffsdr_exit(void)
-{
- platform_device_unregister(sffsdr_snd_device);
-}
-
-module_init(sffsdr_init);
-module_exit(sffsdr_exit);
-
-MODULE_AUTHOR("Hugo Villeneuve");
-MODULE_DESCRIPTION("Lyrtech SFFSDR ASoC driver");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 95c12b26fe37..8d73edc56102 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -20,7 +20,7 @@ config SND_SOC_MPC8610_HPCD
config SND_SOC_MPC5200_I2S
tristate "Freescale MPC5200 PSC in I2S mode driver"
- depends on PPC_MPC52xx && PPC_BESTCOMM
+ depends on SND_SOC && PPC_MPC52xx && PPC_BESTCOMM
select SND_SOC_OF_SIMPLE
select PPC_BESTCOMM_GEN_BD
help
diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c
index 646c807163ab..d2d3da9729f2 100644
--- a/sound/soc/fsl/fsl_dma.c
+++ b/sound/soc/fsl/fsl_dma.c
@@ -284,7 +284,7 @@ static irqreturn_t fsl_dma_isr(int irq, void *dev_id)
* fsl_dma_new: initialize this PCM driver.
*
* This function is called when the codec driver calls snd_soc_new_pcms(),
- * once for each .dai_link in the machine driver's snd_soc_card
+ * once for each .dai_link in the machine driver's snd_soc_machine
* structure.
*/
static int fsl_dma_new(struct snd_card *card, struct snd_soc_dai *dai,
@@ -853,18 +853,6 @@ int fsl_dma_configure(struct fsl_dma_info *dma_info)
}
EXPORT_SYMBOL_GPL(fsl_dma_configure);
-static int __devinit fsl_soc_platform_init(void)
-{
- return snd_soc_register_platform(&fsl_soc_platform);
-}
-module_init(fsl_soc_platform_init);
-
-static void __exit fsl_soc_platform_exit(void)
-{
- snd_soc_unregister_platform(&fsl_soc_platform);
-}
-module_exit(fsl_soc_platform_exit);
-
MODULE_AUTHOR("Timur Tabi <timur@freescale.com>");
MODULE_DESCRIPTION("Freescale Elo DMA ASoC PCM module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c
index c6d6eb71dc1d..157a7895ffa1 100644
--- a/sound/soc/fsl/fsl_ssi.c
+++ b/sound/soc/fsl/fsl_ssi.c
@@ -266,8 +266,7 @@ static irqreturn_t fsl_ssi_isr(int irq, void *dev_id)
* If this is the first stream open, then grab the IRQ and program most of
* the SSI registers.
*/
-static int fsl_ssi_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int fsl_ssi_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
@@ -412,8 +411,7 @@ static int fsl_ssi_startup(struct snd_pcm_substream *substream,
* Note: The SxCCR.DC and SxCCR.PM bits are only used if the SSI is the
* clock master.
*/
-static int fsl_ssi_prepare(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int fsl_ssi_prepare(struct snd_pcm_substream *substream)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
@@ -443,8 +441,7 @@ static int fsl_ssi_prepare(struct snd_pcm_substream *substream,
* The DMA channel is in external master start and pause mode, which
* means the SSI completely controls the flow of data.
*/
-static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
@@ -493,8 +490,7 @@ static int fsl_ssi_trigger(struct snd_pcm_substream *substream, int cmd,
*
* Shutdown the SSI if there are no other substreams open.
*/
-static void fsl_ssi_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void fsl_ssi_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct fsl_ssi_private *ssi_private = rtd->dai->cpu_dai->private_data;
@@ -582,6 +578,8 @@ static struct snd_soc_dai fsl_ssi_dai_template = {
.prepare = fsl_ssi_prepare,
.shutdown = fsl_ssi_shutdown,
.trigger = fsl_ssi_trigger,
+ },
+ .dai_ops = {
.set_sysclk = fsl_ssi_set_sysclk,
.set_fmt = fsl_ssi_set_fmt,
},
@@ -673,14 +671,6 @@ struct snd_soc_dai *fsl_ssi_create_dai(struct fsl_ssi_info *ssi_info)
fsl_ssi_dai->private_data = ssi_private;
fsl_ssi_dai->name = ssi_private->name;
fsl_ssi_dai->id = ssi_info->id;
- fsl_ssi_dai->dev = ssi_info->dev;
-
- ret = snd_soc_register_dai(fsl_ssi_dai);
- if (ret != 0) {
- dev_err(ssi_info->dev, "failed to register DAI: %d\n", ret);
- kfree(fsl_ssi_dai);
- return NULL;
- }
return fsl_ssi_dai;
}
@@ -698,8 +688,6 @@ void fsl_ssi_destroy_dai(struct snd_soc_dai *fsl_ssi_dai)
device_remove_file(ssi_private->dev, &ssi_private->dev_attr);
- snd_soc_unregister_dai(&ssi_private->cpu_dai);
-
kfree(ssi_private);
}
EXPORT_SYMBOL_GPL(fsl_ssi_destroy_dai);
diff --git a/sound/soc/fsl/mpc5200_psc_i2s.c b/sound/soc/fsl/mpc5200_psc_i2s.c
index 9eb1ce185bd0..94a02eaa4825 100644
--- a/sound/soc/fsl/mpc5200_psc_i2s.c
+++ b/sound/soc/fsl/mpc5200_psc_i2s.c
@@ -187,8 +187,7 @@ static irqreturn_t psc_i2s_bcom_irq(int irq, void *_psc_i2s_stream)
* If this is the first stream open, then grab the IRQ and program most of
* the PSC registers.
*/
-static int psc_i2s_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int psc_i2s_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -221,8 +220,7 @@ static int psc_i2s_startup(struct snd_pcm_substream *substream,
}
static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -258,8 +256,7 @@ static int psc_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int psc_i2s_hw_free(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int psc_i2s_hw_free(struct snd_pcm_substream *substream)
{
snd_pcm_set_runtime_buffer(substream, NULL);
return 0;
@@ -271,8 +268,7 @@ static int psc_i2s_hw_free(struct snd_pcm_substream *substream,
* This function is called by ALSA to start, stop, pause, and resume the DMA
* transfer of data.
*/
-static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -387,8 +383,7 @@ static int psc_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
*
* Shutdown the PSC if there are no other substreams open.
*/
-static void psc_i2s_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void psc_i2s_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct psc_i2s *psc_i2s = rtd->dai->cpu_dai->private_data;
@@ -469,6 +464,7 @@ static int psc_i2s_set_fmt(struct snd_soc_dai *cpu_dai, unsigned int format)
* psc_i2s_dai_template: template CPU Digital Audio Interface
*/
static struct snd_soc_dai psc_i2s_dai_template = {
+ .type = SND_SOC_DAI_I2S,
.playback = {
.channels_min = 2,
.channels_max = 2,
@@ -487,6 +483,8 @@ static struct snd_soc_dai psc_i2s_dai_template = {
.hw_free = psc_i2s_hw_free,
.shutdown = psc_i2s_shutdown,
.trigger = psc_i2s_trigger,
+ },
+ .dai_ops = {
.set_sysclk = psc_i2s_set_sysclk,
.set_fmt = psc_i2s_set_fmt,
},
@@ -828,8 +826,6 @@ static int __devinit psc_i2s_of_probe(struct of_device *op,
if (rc)
dev_info(psc_i2s->dev, "error creating sysfs files\n");
- snd_soc_register_platform(&psc_i2s_pcm_soc_platform);
-
/* Tell the ASoC OF helpers about it */
of_snd_soc_register_platform(&psc_i2s_pcm_soc_platform, op->node,
&psc_i2s->dai);
@@ -843,8 +839,6 @@ static int __devexit psc_i2s_of_remove(struct of_device *op)
dev_dbg(&op->dev, "psc_i2s_remove()\n");
- snd_soc_unregister_platform(&psc_i2s_pcm_soc_platform);
-
bcom_gen_bd_rx_release(psc_i2s->capture.bcom_task);
bcom_gen_bd_tx_release(psc_i2s->playback.bcom_task);
diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c
index bcec3f60bad9..94f89debde1f 100644
--- a/sound/soc/fsl/mpc8610_hpcd.c
+++ b/sound/soc/fsl/mpc8610_hpcd.c
@@ -29,7 +29,7 @@
struct mpc8610_hpcd_data {
struct snd_soc_device sound_devdata;
struct snd_soc_dai_link dai;
- struct snd_soc_card machine;
+ struct snd_soc_machine machine;
unsigned int dai_format;
unsigned int codec_clk_direction;
unsigned int cpu_clk_direction;
@@ -185,7 +185,7 @@ static struct snd_soc_ops mpc8610_hpcd_ops = {
/**
* mpc8610_hpcd_machine: ASoC machine data
*/
-static struct snd_soc_card mpc8610_hpcd_machine = {
+static struct snd_soc_machine mpc8610_hpcd_machine = {
.probe = mpc8610_hpcd_machine_probe,
.remove = mpc8610_hpcd_machine_remove,
.name = "MPC8610 HPCD",
@@ -465,9 +465,9 @@ static int mpc8610_hpcd_probe(struct of_device *ofdev,
goto error;
}
- machine_data->sound_devdata.card = &mpc8610_hpcd_machine;
+ machine_data->sound_devdata.machine = &mpc8610_hpcd_machine;
machine_data->sound_devdata.codec_dev = &soc_codec_device_cs4270;
- machine_data->machine.platform = &fsl_soc_platform;
+ machine_data->sound_devdata.platform = &fsl_soc_platform;
sound_device->dev.platform_data = machine_data;
diff --git a/sound/soc/fsl/soc-of-simple.c b/sound/soc/fsl/soc-of-simple.c
index 8bc5cd9e972f..0382fdac51cd 100644
--- a/sound/soc/fsl/soc-of-simple.c
+++ b/sound/soc/fsl/soc-of-simple.c
@@ -31,7 +31,7 @@ struct of_snd_soc_device {
int id;
struct list_head list;
struct snd_soc_device device;
- struct snd_soc_card card;
+ struct snd_soc_machine machine;
struct snd_soc_dai_link dai_link;
struct platform_device *pdev;
struct device_node *platform_node;
@@ -58,9 +58,9 @@ of_snd_soc_get_device(struct device_node *codec_node)
/* Initialize the structure and add it to the global list */
of_soc->codec_node = codec_node;
of_soc->id = of_snd_soc_next_index++;
- of_soc->card.dai_link = &of_soc->dai_link;
- of_soc->card.num_links = 1;
- of_soc->device.card = &of_soc->card;
+ of_soc->machine.dai_link = &of_soc->dai_link;
+ of_soc->machine.num_links = 1;
+ of_soc->device.machine = &of_soc->machine;
of_soc->dai_link.ops = &of_snd_soc_ops;
list_add(&of_soc->list, &of_snd_soc_device_list);
@@ -158,8 +158,8 @@ int of_snd_soc_register_platform(struct snd_soc_platform *platform,
of_soc->platform_node = node;
of_soc->dai_link.cpu_dai = cpu_dai;
- of_soc->card.platform = platform;
- of_soc->card.name = of_soc->dai_link.cpu_dai->name;
+ of_soc->device.platform = platform;
+ of_soc->machine.name = of_soc->dai_link.cpu_dai->name;
/* Now try to register the SoC device */
of_snd_soc_register_device(of_soc);
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index a7b1d77b2105..8b7766b998d7 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -1,6 +1,6 @@
config SND_OMAP_SOC
tristate "SoC Audio for the Texas Instruments OMAP chips"
- depends on ARCH_OMAP
+ depends on ARCH_OMAP && SND_SOC
config SND_OMAP_SOC_MCBSP
tristate
@@ -21,36 +21,3 @@ config SND_OMAP_SOC_OSK5912
select SND_SOC_TLV320AIC23
help
Say Y if you want to add support for SoC audio on osk5912.
-
-config SND_OMAP_SOC_OVERO
- tristate "SoC Audio support for Gumstix Overo"
- depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OVERO
- select SND_OMAP_SOC_MCBSP
- select SND_SOC_TWL4030
- help
- Say Y if you want to add support for SoC audio on the Gumstix Overo.
-
-config SND_OMAP_SOC_OMAP2EVM
- tristate "SoC Audio support for OMAP2EVM board"
- depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP2EVM
- select SND_OMAP_SOC_MCBSP
- select SND_SOC_TWL4030
- help
- Say Y if you want to add support for SoC audio on the omap2evm board.
-
-config SND_OMAP_SOC_SDP3430
- tristate "SoC Audio support for Texas Instruments SDP3430"
- depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_3430SDP
- select SND_OMAP_SOC_MCBSP
- select SND_SOC_TWL4030
- help
- Say Y if you want to add support for SoC audio on Texas Instruments
- SDP3430.
-
-config SND_OMAP_SOC_OMAP3_PANDORA
- tristate "SoC Audio support for OMAP3 Pandora"
- depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
- select SND_OMAP_SOC_MCBSP
- select SND_SOC_TWL4030
- help
- Say Y if you want to add support for SoC audio on the OMAP3 Pandora.
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 76fedd96e365..e09d1f297f64 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -8,14 +8,6 @@ obj-$(CONFIG_SND_OMAP_SOC_MCBSP) += snd-soc-omap-mcbsp.o
# OMAP Machine Support
snd-soc-n810-objs := n810.o
snd-soc-osk5912-objs := osk5912.o
-snd-soc-overo-objs := overo.o
-snd-soc-omap2evm-objs := omap2evm.o
-snd-soc-sdp3430-objs := sdp3430.o
-snd-soc-omap3pandora-objs := omap3pandora.o
obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o
obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o
-obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o
-obj-$(CONFIG_MACH_OMAP2EVM) += snd-soc-omap2evm.o
-obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
-obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
diff --git a/sound/soc/omap/n810.c b/sound/soc/omap/n810.c
index 25593fee9121..fae3ad36e0bf 100644
--- a/sound/soc/omap/n810.c
+++ b/sound/soc/omap/n810.c
@@ -70,13 +70,9 @@ static void n810_ext_control(struct snd_soc_codec *codec)
static int n810_startup(struct snd_pcm_substream *substream)
{
- struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_codec *codec = rtd->socdev->codec;
- snd_pcm_hw_constraint_minmax(runtime,
- SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
-
n810_ext_control(codec);
return clk_enable(sys_clkout2);
}
@@ -286,9 +282,8 @@ static struct snd_soc_dai_link n810_dai = {
};
/* Audio machine driver */
-static struct snd_soc_card snd_soc_n810 = {
+static struct snd_soc_machine snd_soc_machine_n810 = {
.name = "N810",
- .platform = &omap_soc_platform,
.dai_link = &n810_dai,
.num_links = 1,
};
@@ -303,7 +298,8 @@ static struct aic3x_setup_data n810_aic33_setup = {
/* Audio subsystem */
static struct snd_soc_device n810_snd_devdata = {
- .card = &snd_soc_n810,
+ .machine = &snd_soc_machine_n810,
+ .platform = &omap_soc_platform,
.codec_dev = &soc_codec_dev_aic3x,
.codec_data = &n810_aic33_setup,
};
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 41cab2034163..8485a8a9d0ff 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -36,7 +36,9 @@
#include "omap-mcbsp.h"
#include "omap-pcm.h"
-#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_8000_96000)
+#define OMAP_MCBSP_RATES (SNDRV_PCM_RATE_44100 | \
+ SNDRV_PCM_RATE_48000 | \
+ SNDRV_PCM_RATE_KNOT)
struct omap_mcbsp_data {
unsigned int bus_id;
@@ -138,8 +140,7 @@ static const unsigned long omap34xx_mcbsp_port[][2] = {
static const unsigned long omap34xx_mcbsp_port[][2] = {};
#endif
-static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -152,8 +153,7 @@ static int omap_mcbsp_dai_startup(struct snd_pcm_substream *substream,
return err;
}
-static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -165,8 +165,7 @@ static void omap_mcbsp_dai_shutdown(struct snd_pcm_substream *substream,
}
}
-static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -195,15 +194,14 @@ static int omap_mcbsp_dai_trigger(struct snd_pcm_substream *substream, int cmd,
}
static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
struct omap_mcbsp_data *mcbsp_data = to_mcbsp(cpu_dai->private_data);
struct omap_mcbsp_reg_cfg *regs = &mcbsp_data->regs;
int dma, bus_id = mcbsp_data->bus_id, id = cpu_dai->id;
- int wlen, channels;
+ int wlen;
unsigned long port;
if (cpu_class_is_omap1()) {
@@ -232,17 +230,12 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
return 0;
}
- channels = params_channels(params);
- switch (channels) {
+ switch (params_channels(params)) {
case 2:
- /* Use dual-phase frames */
- regs->rcr2 |= RPHASE;
- regs->xcr2 |= XPHASE;
- case 1:
- /* Set 1 word per (McBSP) frame */
- regs->rcr2 |= RFRLEN2(1 - 1);
+ /* Set 1 word per (McBPSP) frame and use dual-phase frames */
+ regs->rcr2 |= RFRLEN2(1 - 1) | RPHASE;
regs->rcr1 |= RFRLEN1(1 - 1);
- regs->xcr2 |= XFRLEN2(1 - 1);
+ regs->xcr2 |= XFRLEN2(1 - 1) | XPHASE;
regs->xcr1 |= XFRLEN1(1 - 1);
break;
default:
@@ -271,8 +264,8 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
regs->srgr1 |= FWID(wlen - 1);
break;
case SND_SOC_DAIFMT_DSP_A:
- regs->srgr2 |= FPER(wlen * channels - 1);
- regs->srgr1 |= FWID(wlen * channels - 2);
+ regs->srgr2 |= FPER(wlen * 2 - 1);
+ regs->srgr1 |= FWID(wlen * 2 - 2);
break;
}
@@ -459,16 +452,17 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
#define OMAP_MCBSP_DAI_BUILDER(link_id) \
{ \
- .name = "omap-mcbsp-dai-"#link_id, \
+ .name = "omap-mcbsp-dai-(link_id)", \
.id = (link_id), \
+ .type = SND_SOC_DAI_I2S, \
.playback = { \
- .channels_min = 1, \
+ .channels_min = 2, \
.channels_max = 2, \
.rates = OMAP_MCBSP_RATES, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
}, \
.capture = { \
- .channels_min = 1, \
+ .channels_min = 2, \
.channels_max = 2, \
.rates = OMAP_MCBSP_RATES, \
.formats = SNDRV_PCM_FMTBIT_S16_LE, \
@@ -478,6 +472,8 @@ static int omap_mcbsp_dai_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
.shutdown = omap_mcbsp_dai_shutdown, \
.trigger = omap_mcbsp_dai_trigger, \
.hw_params = omap_mcbsp_dai_hw_params, \
+ }, \
+ .dai_ops = { \
.set_fmt = omap_mcbsp_dai_set_dai_fmt, \
.set_clkdiv = omap_mcbsp_dai_set_clkdiv, \
.set_sysclk = omap_mcbsp_dai_set_dai_sysclk, \
@@ -499,19 +495,6 @@ struct snd_soc_dai omap_mcbsp_dai[] = {
EXPORT_SYMBOL_GPL(omap_mcbsp_dai);
-static int __devinit omap_mcbsp_init(void)
-{
- return snd_soc_register_dais(omap_mcbsp_dai,
- ARRAY_SIZE(omap_mcbsp_dai));
-}
-module_init(omap_mcbsp_init);
-
-static void __exit omap_mcbsp_exit(void)
-{
- snd_soc_unregister_dais(omap_mcbsp_dai, ARRAY_SIZE(omap_mcbsp_dai));
-}
-module_exit(omap_mcbsp_exit);
-
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
MODULE_DESCRIPTION("OMAP I2S SoC Interface");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap-pcm.c b/sound/soc/omap/omap-pcm.c
index 9940de296316..e9084fdd2082 100644
--- a/sound/soc/omap/omap-pcm.c
+++ b/sound/soc/omap/omap-pcm.c
@@ -354,18 +354,6 @@ struct snd_soc_platform omap_soc_platform = {
};
EXPORT_SYMBOL_GPL(omap_soc_platform);
-static int __devinit omap_soc_platform_init(void)
-{
- return snd_soc_register_platform(&omap_soc_platform);
-}
-module_init(omap_soc_platform_init);
-
-static void __exit omap_soc_platform_exit(void)
-{
- snd_soc_unregister_platform(&omap_soc_platform);
-}
-module_exit(omap_soc_platform_exit);
-
MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@nokia.com>");
MODULE_DESCRIPTION("OMAP PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap2evm.c b/sound/soc/omap/omap2evm.c
deleted file mode 100644
index 0c2322dcf02a..000000000000
--- a/sound/soc/omap/omap2evm.c
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * omap2evm.c -- SoC audio machine driver for omap2evm board
- *
- * Author: Arun KS <arunks@mistralsolutions.com>
- *
- * Based on sound/soc/omap/overo.c by Steve Sakoman
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/mcbsp.h>
-
-#include "omap-mcbsp.h"
-#include "omap-pcm.h"
-#include "../codecs/twl4030.h"
-
-static int omap2evm_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ret;
-
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
- /* Set the codec system clock for DAC and ADC */
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec system clock\n");
- return ret;
- }
-
- return 0;
-}
-
-static struct snd_soc_ops omap2evm_ops = {
- .hw_params = omap2evm_hw_params,
-};
-
-/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link omap2evm_dai = {
- .name = "TWL4030",
- .stream_name = "TWL4030",
- .cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
- .ops = &omap2evm_ops,
-};
-
-/* Audio machine driver */
-static struct snd_soc_card snd_soc_omap2evm = {
- .name = "omap2evm",
- .platform = &omap_soc_platform,
- .dai_link = &omap2evm_dai,
- .num_links = 1,
-};
-
-/* Audio subsystem */
-static struct snd_soc_device omap2evm_snd_devdata = {
- .card = &snd_soc_omap2evm,
- .codec_dev = &soc_codec_dev_twl4030,
-};
-
-static struct platform_device *omap2evm_snd_device;
-
-static int __init omap2evm_soc_init(void)
-{
- int ret;
-
- if (!machine_is_omap2evm()) {
- pr_debug("Not omap2evm!\n");
- return -ENODEV;
- }
- printk(KERN_INFO "omap2evm SoC init\n");
-
- omap2evm_snd_device = platform_device_alloc("soc-audio", -1);
- if (!omap2evm_snd_device) {
- printk(KERN_ERR "Platform device allocation failed\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(omap2evm_snd_device, &omap2evm_snd_devdata);
- omap2evm_snd_devdata.dev = &omap2evm_snd_device->dev;
- *(unsigned int *)omap2evm_dai.cpu_dai->private_data = 1; /* McBSP2 */
-
- ret = platform_device_add(omap2evm_snd_device);
- if (ret)
- goto err1;
-
- return 0;
-
-err1:
- printk(KERN_ERR "Unable to add platform device\n");
- platform_device_put(omap2evm_snd_device);
-
- return ret;
-}
-module_init(omap2evm_soc_init);
-
-static void __exit omap2evm_soc_exit(void)
-{
- platform_device_unregister(omap2evm_snd_device);
-}
-module_exit(omap2evm_soc_exit);
-
-MODULE_AUTHOR("Arun KS <arunks@mistralsolutions.com>");
-MODULE_DESCRIPTION("ALSA SoC omap2evm");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap3beagle.c b/sound/soc/omap/omap3beagle.c
deleted file mode 100644
index fd24a4acd2f5..000000000000
--- a/sound/soc/omap/omap3beagle.c
+++ /dev/null
@@ -1,149 +0,0 @@
-/*
- * omap3beagle.c -- SoC audio for OMAP3 Beagle
- *
- * Author: Steve Sakoman <steve@sakoman.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/mcbsp.h>
-
-#include "omap-mcbsp.h"
-#include "omap-pcm.h"
-#include "../codecs/twl4030.h"
-
-static int omap3beagle_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ret;
-
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
- /* Set the codec system clock for DAC and ADC */
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec system clock\n");
- return ret;
- }
-
- return 0;
-}
-
-static struct snd_soc_ops omap3beagle_ops = {
- .hw_params = omap3beagle_hw_params,
-};
-
-/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link omap3beagle_dai = {
- .name = "TWL4030",
- .stream_name = "TWL4030",
- .cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
- .ops = &omap3beagle_ops,
-};
-
-/* Audio machine driver */
-static struct snd_soc_card snd_soc_omap3beagle = {
- .name = "omap3beagle",
- .platform = &omap_soc_platform,
- .dai_link = &omap3beagle_dai,
- .num_links = 1,
-};
-
-/* Audio subsystem */
-static struct snd_soc_device omap3beagle_snd_devdata = {
- .card = &snd_soc_omap3beagle,
- .codec_dev = &soc_codec_dev_twl4030,
-};
-
-static struct platform_device *omap3beagle_snd_device;
-
-static int __init omap3beagle_soc_init(void)
-{
- int ret;
-
- if (!machine_is_omap3_beagle()) {
- pr_debug("Not OMAP3 Beagle!\n");
- return -ENODEV;
- }
- pr_info("OMAP3 Beagle SoC init\n");
-
- omap3beagle_snd_device = platform_device_alloc("soc-audio", -1);
- if (!omap3beagle_snd_device) {
- printk(KERN_ERR "Platform device allocation failed\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(omap3beagle_snd_device, &omap3beagle_snd_devdata);
- omap3beagle_snd_devdata.dev = &omap3beagle_snd_device->dev;
- *(unsigned int *)omap3beagle_dai.cpu_dai->private_data = 1; /* McBSP2 */
-
- ret = platform_device_add(omap3beagle_snd_device);
- if (ret)
- goto err1;
-
- return 0;
-
-err1:
- printk(KERN_ERR "Unable to add platform device\n");
- platform_device_put(omap3beagle_snd_device);
-
- return ret;
-}
-
-static void __exit omap3beagle_soc_exit(void)
-{
- platform_device_unregister(omap3beagle_snd_device);
-}
-
-module_init(omap3beagle_soc_init);
-module_exit(omap3beagle_soc_exit);
-
-MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
-MODULE_DESCRIPTION("ALSA SoC OMAP3 Beagle");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c
deleted file mode 100644
index bd91594496b1..000000000000
--- a/sound/soc/omap/omap3pandora.c
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * omap3pandora.c -- SoC audio for Pandora Handheld Console
- *
- * Author: Gražvydas Ignotas <notasas@gmail.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <asm/mach-types.h>
-
-#include "omap-mcbsp.h"
-#include "omap-pcm.h"
-#include "../codecs/twl4030.h"
-
-#define OMAP3_PANDORA_DAC_POWER_GPIO 118
-#define OMAP3_PANDORA_AMP_POWER_GPIO 14
-
-#define PREFIX "ASoC omap3pandora: "
-
-static int omap3pandora_cmn_hw_params(struct snd_soc_dai *codec_dai,
- struct snd_soc_dai *cpu_dai, unsigned int fmt)
-{
- int ret;
-
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai, fmt);
- if (ret < 0) {
- pr_err(PREFIX "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
- if (ret < 0) {
- pr_err(PREFIX "can't set cpu DAI configuration\n");
- return ret;
- }
-
- /* Set the codec system clock for DAC and ADC */
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- pr_err(PREFIX "can't set codec system clock\n");
- return ret;
- }
-
- /* Set McBSP clock to external */
- ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_SYSCLK_CLKS_EXT, 0,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- pr_err(PREFIX "can't set cpu system clock\n");
- return ret;
- }
-
- ret = snd_soc_dai_set_clkdiv(cpu_dai, OMAP_MCBSP_CLKGDV, 8);
- if (ret < 0) {
- pr_err(PREFIX "can't set SRG clock divider\n");
- return ret;
- }
-
- return 0;
-}
-
-static int omap3pandora_out_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-
- return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_IB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
-}
-
-static int omap3pandora_in_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
-
- return omap3pandora_cmn_hw_params(codec_dai, cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBS_CFS);
-}
-
-static int omap3pandora_hp_event(struct snd_soc_dapm_widget *w,
- struct snd_kcontrol *k, int event)
-{
- if (SND_SOC_DAPM_EVENT_ON(event)) {
- gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 1);
- gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 1);
- } else {
- gpio_set_value(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
- mdelay(1);
- gpio_set_value(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
- }
-
- return 0;
-}
-
-/*
- * Audio paths on Pandora board:
- *
- * |O| ---> PCM DAC +-> AMP -> Headphone Jack
- * |M| A +--------> Line Out
- * |A| <~~clk~~+
- * |P| <--- TWL4030 <--------- Line In and MICs
- */
-static const struct snd_soc_dapm_widget omap3pandora_out_dapm_widgets[] = {
- SND_SOC_DAPM_DAC("PCM DAC", "Playback", SND_SOC_NOPM, 0, 0),
- SND_SOC_DAPM_PGA_E("Headphone Amplifier", SND_SOC_NOPM,
- 0, 0, NULL, 0, omap3pandora_hp_event,
- SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
- SND_SOC_DAPM_HP("Headphone Jack", NULL),
- SND_SOC_DAPM_LINE("Line Out", NULL),
-};
-
-static const struct snd_soc_dapm_widget omap3pandora_in_dapm_widgets[] = {
- SND_SOC_DAPM_MIC("Mic (Internal)", NULL),
- SND_SOC_DAPM_MIC("Mic (external)", NULL),
- SND_SOC_DAPM_LINE("Line In", NULL),
-};
-
-static const struct snd_soc_dapm_route omap3pandora_out_map[] = {
- {"Headphone Amplifier", NULL, "PCM DAC"},
- {"Line Out", NULL, "PCM DAC"},
- {"Headphone Jack", NULL, "Headphone Amplifier"},
-};
-
-static const struct snd_soc_dapm_route omap3pandora_in_map[] = {
- {"INL", NULL, "Line In"},
- {"INR", NULL, "Line In"},
- {"INL", NULL, "Mic (Internal)"},
- {"INR", NULL, "Mic (external)"},
-};
-
-static int omap3pandora_out_init(struct snd_soc_codec *codec)
-{
- int ret;
-
- ret = snd_soc_dapm_new_controls(codec, omap3pandora_out_dapm_widgets,
- ARRAY_SIZE(omap3pandora_out_dapm_widgets));
- if (ret < 0)
- return ret;
-
- snd_soc_dapm_add_routes(codec, omap3pandora_out_map,
- ARRAY_SIZE(omap3pandora_out_map));
-
- return snd_soc_dapm_sync(codec);
-}
-
-static int omap3pandora_in_init(struct snd_soc_codec *codec)
-{
- int ret;
-
- ret = snd_soc_dapm_new_controls(codec, omap3pandora_in_dapm_widgets,
- ARRAY_SIZE(omap3pandora_in_dapm_widgets));
- if (ret < 0)
- return ret;
-
- snd_soc_dapm_add_routes(codec, omap3pandora_in_map,
- ARRAY_SIZE(omap3pandora_in_map));
-
- return snd_soc_dapm_sync(codec);
-}
-
-static struct snd_soc_ops omap3pandora_out_ops = {
- .hw_params = omap3pandora_out_hw_params,
-};
-
-static struct snd_soc_ops omap3pandora_in_ops = {
- .hw_params = omap3pandora_in_hw_params,
-};
-
-/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link omap3pandora_dai[] = {
- {
- .name = "PCM1773",
- .stream_name = "HiFi Out",
- .cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
- .ops = &omap3pandora_out_ops,
- .init = omap3pandora_out_init,
- }, {
- .name = "TWL4030",
- .stream_name = "Line/Mic In",
- .cpu_dai = &omap_mcbsp_dai[1],
- .codec_dai = &twl4030_dai,
- .ops = &omap3pandora_in_ops,
- .init = omap3pandora_in_init,
- }
-};
-
-/* SoC card */
-static struct snd_soc_card snd_soc_card_omap3pandora = {
- .name = "omap3pandora",
- .platform = &omap_soc_platform,
- .dai_link = omap3pandora_dai,
- .num_links = ARRAY_SIZE(omap3pandora_dai),
-};
-
-/* Audio subsystem */
-static struct snd_soc_device omap3pandora_snd_data = {
- .card = &snd_soc_card_omap3pandora,
- .codec_dev = &soc_codec_dev_twl4030,
-};
-
-static struct platform_device *omap3pandora_snd_device;
-
-static int __init omap3pandora_soc_init(void)
-{
- int ret;
-
- if (!machine_is_omap3_pandora()) {
- pr_debug(PREFIX "Not OMAP3 Pandora\n");
- return -ENODEV;
- }
- pr_info("OMAP3 Pandora SoC init\n");
-
- ret = gpio_request(OMAP3_PANDORA_DAC_POWER_GPIO, "dac_power");
- if (ret) {
- pr_err(PREFIX "Failed to get DAC power GPIO\n");
- return ret;
- }
-
- ret = gpio_direction_output(OMAP3_PANDORA_DAC_POWER_GPIO, 0);
- if (ret) {
- pr_err(PREFIX "Failed to set DAC power GPIO direction\n");
- goto fail0;
- }
-
- ret = gpio_request(OMAP3_PANDORA_AMP_POWER_GPIO, "amp_power");
- if (ret) {
- pr_err(PREFIX "Failed to get amp power GPIO\n");
- goto fail0;
- }
-
- ret = gpio_direction_output(OMAP3_PANDORA_AMP_POWER_GPIO, 0);
- if (ret) {
- pr_err(PREFIX "Failed to set amp power GPIO direction\n");
- goto fail1;
- }
-
- omap3pandora_snd_device = platform_device_alloc("soc-audio", -1);
- if (omap3pandora_snd_device == NULL) {
- pr_err(PREFIX "Platform device allocation failed\n");
- ret = -ENOMEM;
- goto fail1;
- }
-
- platform_set_drvdata(omap3pandora_snd_device, &omap3pandora_snd_data);
- omap3pandora_snd_data.dev = &omap3pandora_snd_device->dev;
- *(unsigned int *)omap_mcbsp_dai[0].private_data = 1; /* McBSP2 */
- *(unsigned int *)omap_mcbsp_dai[1].private_data = 3; /* McBSP4 */
-
- ret = platform_device_add(omap3pandora_snd_device);
- if (ret) {
- pr_err(PREFIX "Unable to add platform device\n");
- goto fail2;
- }
-
- return 0;
-
-fail2:
- platform_device_put(omap3pandora_snd_device);
-fail1:
- gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
-fail0:
- gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
- return ret;
-}
-module_init(omap3pandora_soc_init);
-
-static void __exit omap3pandora_soc_exit(void)
-{
- platform_device_unregister(omap3pandora_snd_device);
- gpio_free(OMAP3_PANDORA_AMP_POWER_GPIO);
- gpio_free(OMAP3_PANDORA_DAC_POWER_GPIO);
-}
-module_exit(omap3pandora_soc_exit);
-
-MODULE_AUTHOR("Grazvydas Ignotas <notasas@gmail.com>");
-MODULE_DESCRIPTION("ALSA SoC OMAP3 Pandora");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/osk5912.c b/sound/soc/omap/osk5912.c
index 845bf41335b9..0fe733796898 100644
--- a/sound/soc/omap/osk5912.c
+++ b/sound/soc/omap/osk5912.c
@@ -143,16 +143,16 @@ static struct snd_soc_dai_link osk_dai = {
};
/* Audio machine driver */
-static struct snd_soc_card snd_soc_card_osk = {
+static struct snd_soc_machine snd_soc_machine_osk = {
.name = "OSK5912",
- .platform = &omap_soc_platform,
.dai_link = &osk_dai,
.num_links = 1,
};
/* Audio subsystem */
static struct snd_soc_device osk_snd_devdata = {
- .card = &snd_soc_card_osk,
+ .machine = &snd_soc_machine_osk,
+ .platform = &omap_soc_platform,
.codec_dev = &soc_codec_dev_tlv320aic23,
};
diff --git a/sound/soc/omap/overo.c b/sound/soc/omap/overo.c
deleted file mode 100644
index a72dc4e159e5..000000000000
--- a/sound/soc/omap/overo.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * overo.c -- SoC audio for Gumstix Overo
- *
- * Author: Steve Sakoman <steve@sakoman.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/mcbsp.h>
-
-#include "omap-mcbsp.h"
-#include "omap-pcm.h"
-#include "../codecs/twl4030.h"
-
-static int overo_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ret;
-
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
- /* Set the codec system clock for DAC and ADC */
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec system clock\n");
- return ret;
- }
-
- return 0;
-}
-
-static struct snd_soc_ops overo_ops = {
- .hw_params = overo_hw_params,
-};
-
-/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link overo_dai = {
- .name = "TWL4030",
- .stream_name = "TWL4030",
- .cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
- .ops = &overo_ops,
-};
-
-/* Audio machine driver */
-static struct snd_soc_card snd_soc_card_overo = {
- .name = "overo",
- .platform = &omap_soc_platform,
- .dai_link = &overo_dai,
- .num_links = 1,
-};
-
-/* Audio subsystem */
-static struct snd_soc_device overo_snd_devdata = {
- .card = &snd_soc_card_overo,
- .codec_dev = &soc_codec_dev_twl4030,
-};
-
-static struct platform_device *overo_snd_device;
-
-static int __init overo_soc_init(void)
-{
- int ret;
-
- if (!machine_is_overo()) {
- pr_debug("Not Overo!\n");
- return -ENODEV;
- }
- printk(KERN_INFO "overo SoC init\n");
-
- overo_snd_device = platform_device_alloc("soc-audio", -1);
- if (!overo_snd_device) {
- printk(KERN_ERR "Platform device allocation failed\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(overo_snd_device, &overo_snd_devdata);
- overo_snd_devdata.dev = &overo_snd_device->dev;
- *(unsigned int *)overo_dai.cpu_dai->private_data = 1; /* McBSP2 */
-
- ret = platform_device_add(overo_snd_device);
- if (ret)
- goto err1;
-
- return 0;
-
-err1:
- printk(KERN_ERR "Unable to add platform device\n");
- platform_device_put(overo_snd_device);
-
- return ret;
-}
-module_init(overo_soc_init);
-
-static void __exit overo_soc_exit(void)
-{
- platform_device_unregister(overo_snd_device);
-}
-module_exit(overo_soc_exit);
-
-MODULE_AUTHOR("Steve Sakoman <steve@sakoman.com>");
-MODULE_DESCRIPTION("ALSA SoC overo");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/omap/sdp3430.c b/sound/soc/omap/sdp3430.c
deleted file mode 100644
index ad97836818b1..000000000000
--- a/sound/soc/omap/sdp3430.c
+++ /dev/null
@@ -1,152 +0,0 @@
-/*
- * sdp3430.c -- SoC audio for TI OMAP3430 SDP
- *
- * Author: Misael Lopez Cruz <x0052729@ti.com>
- *
- * Based on:
- * Author: Steve Sakoman <steve@sakoman.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
- * 02110-1301 USA
- *
- */
-
-#include <linux/clk.h>
-#include <linux/platform_device.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <mach/gpio.h>
-#include <mach/mcbsp.h>
-
-#include "omap-mcbsp.h"
-#include "omap-pcm.h"
-#include "../codecs/twl4030.h"
-
-static int sdp3430_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ret;
-
- /* Set codec DAI configuration */
- ret = snd_soc_dai_set_fmt(codec_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec DAI configuration\n");
- return ret;
- }
-
- /* Set cpu DAI configuration */
- ret = snd_soc_dai_set_fmt(cpu_dai,
- SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF |
- SND_SOC_DAIFMT_CBM_CFM);
- if (ret < 0) {
- printk(KERN_ERR "can't set cpu DAI configuration\n");
- return ret;
- }
-
- /* Set the codec system clock for DAC and ADC */
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, 26000000,
- SND_SOC_CLOCK_IN);
- if (ret < 0) {
- printk(KERN_ERR "can't set codec system clock\n");
- return ret;
- }
-
- return 0;
-}
-
-static struct snd_soc_ops sdp3430_ops = {
- .hw_params = sdp3430_hw_params,
-};
-
-/* Digital audio interface glue - connects codec <--> CPU */
-static struct snd_soc_dai_link sdp3430_dai = {
- .name = "TWL4030",
- .stream_name = "TWL4030",
- .cpu_dai = &omap_mcbsp_dai[0],
- .codec_dai = &twl4030_dai,
- .ops = &sdp3430_ops,
-};
-
-/* Audio machine driver */
-static struct snd_soc_machine snd_soc_machine_sdp3430 = {
- .name = "SDP3430",
- .platform = &omap_soc_platform,
- .dai_link = &sdp3430_dai,
- .num_links = 1,
-};
-
-/* Audio subsystem */
-static struct snd_soc_device sdp3430_snd_devdata = {
- .machine = &snd_soc_machine_sdp3430,
- .codec_dev = &soc_codec_dev_twl4030,
-};
-
-static struct platform_device *sdp3430_snd_device;
-
-static int __init sdp3430_soc_init(void)
-{
- int ret;
-
- if (!machine_is_omap_3430sdp()) {
- pr_debug("Not SDP3430!\n");
- return -ENODEV;
- }
- printk(KERN_INFO "SDP3430 SoC init\n");
-
- sdp3430_snd_device = platform_device_alloc("soc-audio", -1);
- if (!sdp3430_snd_device) {
- printk(KERN_ERR "Platform device allocation failed\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(sdp3430_snd_device, &sdp3430_snd_devdata);
- sdp3430_snd_devdata.dev = &sdp3430_snd_device->dev;
- *(unsigned int *)sdp3430_dai.cpu_dai->private_data = 1; /* McBSP2 */
-
- ret = platform_device_add(sdp3430_snd_device);
- if (ret)
- goto err1;
-
- return 0;
-
-err1:
- printk(KERN_ERR "Unable to add platform device\n");
- platform_device_put(sdp3430_snd_device);
-
- return ret;
-}
-module_init(sdp3430_soc_init);
-
-static void __exit sdp3430_soc_exit(void)
-{
- platform_device_unregister(sdp3430_snd_device);
-}
-module_exit(sdp3430_soc_exit);
-
-MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
-MODULE_DESCRIPTION("ALSA SoC SDP3430");
-MODULE_LICENSE("GPL");
-
diff --git a/sound/soc/pxa/Kconfig b/sound/soc/pxa/Kconfig
index f82e10699471..f8c1cdd940ac 100644
--- a/sound/soc/pxa/Kconfig
+++ b/sound/soc/pxa/Kconfig
@@ -21,9 +21,6 @@ config SND_PXA2XX_SOC_AC97
config SND_PXA2XX_SOC_I2S
tristate
-config SND_PXA_SOC_SSP
- tristate
-
config SND_PXA2XX_SOC_CORGI
tristate "SoC Audio support for Sharp Zaurus SL-C7x0"
depends on SND_PXA2XX_SOC && PXA_SHARP_C7xx
@@ -78,22 +75,3 @@ config SND_PXA2XX_SOC_EM_X270
help
Say Y if you want to add support for SoC audio on
CompuLab EM-x270.
-
-config SND_PXA2XX_SOC_PALM27X
- bool "SoC Audio support for Palm T|X, T5 and LifeDrive"
- depends on SND_PXA2XX_SOC && (MACH_PALMLD || MACH_PALMTX || MACH_PALMT5)
- select SND_PXA2XX_SOC_AC97
- select SND_SOC_WM9712
- help
- Say Y if you want to add support for SoC audio on
- Palm T|X, T5 or LifeDrive handheld computer.
-
-config SND_SOC_ZYLONITE
- tristate "SoC Audio support for Marvell Zylonite"
- depends on SND_PXA2XX_SOC && MACH_ZYLONITE
- select SND_PXA2XX_SOC_AC97
- select SND_PXA_SOC_SSP
- select SND_SOC_WM9713
- help
- Say Y if you want to add support for SoC audio on the
- Marvell Zylonite reference platform.
diff --git a/sound/soc/pxa/Makefile b/sound/soc/pxa/Makefile
index 08a9f2797729..5bc8edf9dca9 100644
--- a/sound/soc/pxa/Makefile
+++ b/sound/soc/pxa/Makefile
@@ -2,12 +2,10 @@
snd-soc-pxa2xx-objs := pxa2xx-pcm.o
snd-soc-pxa2xx-ac97-objs := pxa2xx-ac97.o
snd-soc-pxa2xx-i2s-objs := pxa2xx-i2s.o
-snd-soc-pxa-ssp-objs := pxa-ssp.o
obj-$(CONFIG_SND_PXA2XX_SOC) += snd-soc-pxa2xx.o
obj-$(CONFIG_SND_PXA2XX_SOC_AC97) += snd-soc-pxa2xx-ac97.o
obj-$(CONFIG_SND_PXA2XX_SOC_I2S) += snd-soc-pxa2xx-i2s.o
-obj-$(CONFIG_SND_PXA_SOC_SSP) += snd-soc-pxa-ssp.o
# PXA Machine Support
snd-soc-corgi-objs := corgi.o
@@ -16,8 +14,6 @@ snd-soc-tosa-objs := tosa.o
snd-soc-e800-objs := e800_wm9712.o
snd-soc-spitz-objs := spitz.o
snd-soc-em-x270-objs := em-x270.o
-snd-soc-palm27x-objs := palm27x.o
-snd-soc-zylonite-objs := zylonite.o
obj-$(CONFIG_SND_PXA2XX_SOC_CORGI) += snd-soc-corgi.o
obj-$(CONFIG_SND_PXA2XX_SOC_POODLE) += snd-soc-poodle.o
@@ -25,5 +21,3 @@ obj-$(CONFIG_SND_PXA2XX_SOC_TOSA) += snd-soc-tosa.o
obj-$(CONFIG_SND_PXA2XX_SOC_E800) += snd-soc-e800.o
obj-$(CONFIG_SND_PXA2XX_SOC_SPITZ) += snd-soc-spitz.o
obj-$(CONFIG_SND_PXA2XX_SOC_EM_X270) += snd-soc-em-x270.o
-obj-$(CONFIG_SND_PXA2XX_SOC_PALM27X) += snd-soc-palm27x.o
-obj-$(CONFIG_SND_SOC_ZYLONITE) += snd-soc-zylonite.o
diff --git a/sound/soc/pxa/corgi.c b/sound/soc/pxa/corgi.c
index 1ba25a559524..2718eaf7895f 100644
--- a/sound/soc/pxa/corgi.c
+++ b/sound/soc/pxa/corgi.c
@@ -108,11 +108,15 @@ static int corgi_startup(struct snd_pcm_substream *substream)
}
/* we need to unmute the HP at shutdown as the mute burns power on corgi */
-static void corgi_shutdown(struct snd_pcm_substream *substream)
+static int corgi_shutdown(struct snd_pcm_substream *substream)
{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_codec *codec = rtd->socdev->codec;
+
/* set = unmute headphone */
gpio_set_value(CORGI_GPIO_MUTE_L, 1);
gpio_set_value(CORGI_GPIO_MUTE_R, 1);
+ return 0;
}
static int corgi_hw_params(struct snd_pcm_substream *substream,
@@ -310,9 +314,8 @@ static struct snd_soc_dai_link corgi_dai = {
};
/* corgi audio machine driver */
-static struct snd_soc_card snd_soc_corgi = {
+static struct snd_soc_machine snd_soc_machine_corgi = {
.name = "Corgi",
- .platform = &pxa2xx_soc_platform,
.dai_link = &corgi_dai,
.num_links = 1,
};
@@ -325,7 +328,8 @@ static struct wm8731_setup_data corgi_wm8731_setup = {
/* corgi audio subsystem */
static struct snd_soc_device corgi_snd_devdata = {
- .card = &snd_soc_corgi,
+ .machine = &snd_soc_machine_corgi,
+ .platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &corgi_wm8731_setup,
};
diff --git a/sound/soc/pxa/e800_wm9712.c b/sound/soc/pxa/e800_wm9712.c
index 2e3386dfa0f0..6781c5be242f 100644
--- a/sound/soc/pxa/e800_wm9712.c
+++ b/sound/soc/pxa/e800_wm9712.c
@@ -29,7 +29,7 @@
#include "pxa2xx-pcm.h"
#include "pxa2xx-ac97.h"
-static struct snd_soc_card e800;
+static struct snd_soc_machine e800;
static struct snd_soc_dai_link e800_dai[] = {
{
@@ -40,15 +40,15 @@ static struct snd_soc_dai_link e800_dai[] = {
},
};
-static struct snd_soc_card e800 = {
+static struct snd_soc_machine e800 = {
.name = "Toshiba e800",
- .platform = &pxa2xx_soc_platform,
.dai_link = e800_dai,
.num_links = ARRAY_SIZE(e800_dai),
};
static struct snd_soc_device e800_snd_devdata = {
- .card = &e800,
+ .machine = &e800,
+ .platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm9712,
};
diff --git a/sound/soc/pxa/em-x270.c b/sound/soc/pxa/em-x270.c
index fe4a729ea648..e6ff6929ab4b 100644
--- a/sound/soc/pxa/em-x270.c
+++ b/sound/soc/pxa/em-x270.c
@@ -23,6 +23,7 @@
#include <linux/moduleparam.h>
#include <linux/device.h>
+#include <sound/driver.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/soc.h>
@@ -52,15 +53,15 @@ static struct snd_soc_dai_link em_x270_dai[] = {
},
};
-static struct snd_soc_card em_x270 = {
+static struct snd_soc_machine em_x270 = {
.name = "EM-X270",
- .platform = &pxa2xx_soc_platform,
.dai_link = em_x270_dai,
.num_links = ARRAY_SIZE(em_x270_dai),
};
static struct snd_soc_device em_x270_snd_devdata = {
- .card = &em_x270,
+ .machine = &em_x270,
+ .platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm9712,
};
diff --git a/sound/soc/pxa/palm27x.c b/sound/soc/pxa/palm27x.c
deleted file mode 100644
index 4a9cf3083af0..000000000000
--- a/sound/soc/pxa/palm27x.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/*
- * linux/sound/soc/pxa/palm27x.c
- *
- * SoC Audio driver for Palm T|X, T5 and LifeDrive
- *
- * based on tosa.c
- *
- * Copyright (C) 2008 Marek Vasut <marek.vasut@gmail.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include <asm/mach-types.h>
-#include <mach/audio.h>
-#include <mach/palmasoc.h>
-
-#include "../codecs/wm9712.h"
-#include "pxa2xx-pcm.h"
-#include "pxa2xx-ac97.h"
-
-static int palm27x_jack_func = 1;
-static int palm27x_spk_func = 1;
-static int palm27x_ep_gpio = -1;
-
-static void palm27x_ext_control(struct snd_soc_codec *codec)
-{
- if (!palm27x_spk_func)
- snd_soc_dapm_enable_pin(codec, "Speaker");
- else
- snd_soc_dapm_disable_pin(codec, "Speaker");
-
- if (!palm27x_jack_func)
- snd_soc_dapm_enable_pin(codec, "Headphone Jack");
- else
- snd_soc_dapm_disable_pin(codec, "Headphone Jack");
-
- snd_soc_dapm_sync(codec);
-}
-
-static int palm27x_startup(struct snd_pcm_substream *substream)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_codec *codec = rtd->socdev->codec;
-
- /* check the jack status at stream startup */
- palm27x_ext_control(codec);
- return 0;
-}
-
-static struct snd_soc_ops palm27x_ops = {
- .startup = palm27x_startup,
-};
-
-static irqreturn_t palm27x_interrupt(int irq, void *v)
-{
- palm27x_spk_func = gpio_get_value(palm27x_ep_gpio);
- palm27x_jack_func = !palm27x_spk_func;
- return IRQ_HANDLED;
-}
-
-static int palm27x_get_jack(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.integer.value[0] = palm27x_jack_func;
- return 0;
-}
-
-static int palm27x_set_jack(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-
- if (palm27x_jack_func == ucontrol->value.integer.value[0])
- return 0;
-
- palm27x_jack_func = ucontrol->value.integer.value[0];
- palm27x_ext_control(codec);
- return 1;
-}
-
-static int palm27x_get_spk(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- ucontrol->value.integer.value[0] = palm27x_spk_func;
- return 0;
-}
-
-static int palm27x_set_spk(struct snd_kcontrol *kcontrol,
- struct snd_ctl_elem_value *ucontrol)
-{
- struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
-
- if (palm27x_spk_func == ucontrol->value.integer.value[0])
- return 0;
-
- palm27x_spk_func = ucontrol->value.integer.value[0];
- palm27x_ext_control(codec);
- return 1;
-}
-
-/* PalmTX machine dapm widgets */
-static const struct snd_soc_dapm_widget palm27x_dapm_widgets[] = {
- SND_SOC_DAPM_HP("Headphone Jack", NULL),
- SND_SOC_DAPM_SPK("Speaker", NULL),
-};
-
-/* PalmTX audio map */
-static const struct snd_soc_dapm_route audio_map[] = {
- /* headphone connected to HPOUTL, HPOUTR */
- {"Headphone Jack", NULL, "HPOUTL"},
- {"Headphone Jack", NULL, "HPOUTR"},
-
- /* ext speaker connected to ROUT2, LOUT2 */
- {"Speaker", NULL, "LOUT2"},
- {"Speaker", NULL, "ROUT2"},
-};
-
-static const char *jack_function[] = {"Headphone", "Off"};
-static const char *spk_function[] = {"On", "Off"};
-static const struct soc_enum palm27x_enum[] = {
- SOC_ENUM_SINGLE_EXT(2, jack_function),
- SOC_ENUM_SINGLE_EXT(2, spk_function),
-};
-
-static const struct snd_kcontrol_new palm27x_controls[] = {
- SOC_ENUM_EXT("Jack Function", palm27x_enum[0], palm27x_get_jack,
- palm27x_set_jack),
- SOC_ENUM_EXT("Speaker Function", palm27x_enum[1], palm27x_get_spk,
- palm27x_set_spk),
-};
-
-static int palm27x_ac97_init(struct snd_soc_codec *codec)
-{
- int i, err;
-
- snd_soc_dapm_nc_pin(codec, "OUT3");
- snd_soc_dapm_nc_pin(codec, "MONOOUT");
-
- /* add palm27x specific controls */
- for (i = 0; i < ARRAY_SIZE(palm27x_controls); i++) {
- err = snd_ctl_add(codec->card,
- snd_soc_cnew(&palm27x_controls[i],
- codec, NULL));
- if (err < 0)
- return err;
- }
-
- /* add palm27x specific widgets */
- snd_soc_dapm_new_controls(codec, palm27x_dapm_widgets,
- ARRAY_SIZE(palm27x_dapm_widgets));
-
- /* set up palm27x specific audio path audio_map */
- snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
-
- snd_soc_dapm_sync(codec);
- return 0;
-}
-
-static struct snd_soc_dai_link palm27x_dai[] = {
-{
- .name = "AC97 HiFi",
- .stream_name = "AC97 HiFi",
- .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
- .codec_dai = &wm9712_dai[WM9712_DAI_AC97_HIFI],
- .init = palm27x_ac97_init,
- .ops = &palm27x_ops,
-},
-{
- .name = "AC97 Aux",
- .stream_name = "AC97 Aux",
- .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
- .codec_dai = &wm9712_dai[WM9712_DAI_AC97_AUX],
- .ops = &palm27x_ops,
-},
-};
-
-static struct snd_soc_card palm27x_asoc = {
- .name = "Palm/PXA27x",
- .platform = &pxa2xx_soc_platform,
- .dai_link = palm27x_dai,
- .num_links = ARRAY_SIZE(palm27x_dai),
-};
-
-static struct snd_soc_device palm27x_snd_devdata = {
- .card = &palm27x_asoc,
- .codec_dev = &soc_codec_dev_wm9712,
-};
-
-static struct platform_device *palm27x_snd_device;
-
-static int __init palm27x_asoc_init(void)
-{
- int ret;
-
- if (!(machine_is_palmtx() || machine_is_palmt5() ||
- machine_is_palmld()))
- return -ENODEV;
-
- ret = gpio_request(palm27x_ep_gpio, "Headphone Jack");
- if (ret)
- return ret;
- ret = gpio_direction_input(palm27x_ep_gpio);
- if (ret)
- goto err_alloc;
-
- if (request_irq(gpio_to_irq(palm27x_ep_gpio), palm27x_interrupt,
- IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- "Headphone jack", NULL))
- goto err_alloc;
-
- palm27x_snd_device = platform_device_alloc("soc-audio", -1);
- if (!palm27x_snd_device) {
- ret = -ENOMEM;
- goto err_dev;
- }
-
- platform_set_drvdata(palm27x_snd_device, &palm27x_snd_devdata);
- palm27x_snd_devdata.dev = &palm27x_snd_device->dev;
- ret = platform_device_add(palm27x_snd_device);
-
- if (ret != 0)
- goto put_device;
-
- return 0;
-
-put_device:
- platform_device_put(palm27x_snd_device);
-err_dev:
- free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
-err_alloc:
- gpio_free(palm27x_ep_gpio);
-
- return ret;
-}
-
-static void __exit palm27x_asoc_exit(void)
-{
- free_irq(gpio_to_irq(palm27x_ep_gpio), NULL);
- gpio_free(palm27x_ep_gpio);
- platform_device_unregister(palm27x_snd_device);
-}
-
-void __init palm27x_asoc_set_pdata(struct palm27x_asoc_info *data)
-{
- palm27x_ep_gpio = data->jack_gpio;
-}
-
-module_init(palm27x_asoc_init);
-module_exit(palm27x_asoc_exit);
-
-/* Module information */
-MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
-MODULE_DESCRIPTION("ALSA SoC Palm T|X, T5 and LifeDrive");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/poodle.c b/sound/soc/pxa/poodle.c
index 6e9827189fff..4d9930c52789 100644
--- a/sound/soc/pxa/poodle.c
+++ b/sound/soc/pxa/poodle.c
@@ -276,9 +276,8 @@ static struct snd_soc_dai_link poodle_dai = {
};
/* poodle audio machine driver */
-static struct snd_soc_card snd_soc_poodle = {
+static struct snd_soc_machine snd_soc_machine_poodle = {
.name = "Poodle",
- .platform = &pxa2xx_soc_platform,
.dai_link = &poodle_dai,
.num_links = 1,
};
@@ -291,7 +290,8 @@ static struct wm8731_setup_data poodle_wm8731_setup = {
/* poodle audio subsystem */
static struct snd_soc_device poodle_snd_devdata = {
- .card = &snd_soc_poodle,
+ .machine = &snd_soc_machine_poodle,
+ .platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm8731,
.codec_data = &poodle_wm8731_setup,
};
diff --git a/sound/soc/pxa/pxa-ssp.c b/sound/soc/pxa/pxa-ssp.c
deleted file mode 100644
index 3587f2fae5f1..000000000000
--- a/sound/soc/pxa/pxa-ssp.c
+++ /dev/null
@@ -1,931 +0,0 @@
-#define DEBUG
-/*
- * pxa-ssp.c -- ALSA Soc Audio Layer
- *
- * Copyright 2005,2008 Wolfson Microelectronics PLC.
- * Author: Liam Girdwood
- * Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License as published by the
- * Free Software Foundation; either version 2 of the License, or (at your
- * option) any later version.
- *
- * TODO:
- * o Test network mode for > 16bit sample size
- */
-
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/initval.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/pxa2xx-lib.h>
-
-#include <mach/hardware.h>
-#include <mach/pxa-regs.h>
-#include <mach/regs-ssp.h>
-#include <mach/audio.h>
-#include <mach/ssp.h>
-
-#include "pxa2xx-pcm.h"
-#include "pxa-ssp.h"
-
-/*
- * SSP audio private data
- */
-struct ssp_priv {
- struct ssp_dev dev;
- unsigned int sysclk;
- int dai_fmt;
-#ifdef CONFIG_PM
- struct ssp_state state;
-#endif
-};
-
-#define PXA2xx_SSP1_BASE 0x41000000
-#define PXA27x_SSP2_BASE 0x41700000
-#define PXA27x_SSP3_BASE 0x41900000
-#define PXA3xx_SSP4_BASE 0x41a00000
-
-static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_out = {
- .name = "SSP1 PCM Mono out",
- .dev_addr = PXA2xx_SSP1_BASE + SSDR,
- .drcmr = &DRCMR(14),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_mono_in = {
- .name = "SSP1 PCM Mono in",
- .dev_addr = PXA2xx_SSP1_BASE + SSDR,
- .drcmr = &DRCMR(13),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_out = {
- .name = "SSP1 PCM Stereo out",
- .dev_addr = PXA2xx_SSP1_BASE + SSDR,
- .drcmr = &DRCMR(14),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp1_pcm_stereo_in = {
- .name = "SSP1 PCM Stereo in",
- .dev_addr = PXA2xx_SSP1_BASE + SSDR,
- .drcmr = &DRCMR(13),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_out = {
- .name = "SSP2 PCM Mono out",
- .dev_addr = PXA27x_SSP2_BASE + SSDR,
- .drcmr = &DRCMR(16),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_mono_in = {
- .name = "SSP2 PCM Mono in",
- .dev_addr = PXA27x_SSP2_BASE + SSDR,
- .drcmr = &DRCMR(15),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_out = {
- .name = "SSP2 PCM Stereo out",
- .dev_addr = PXA27x_SSP2_BASE + SSDR,
- .drcmr = &DRCMR(16),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp2_pcm_stereo_in = {
- .name = "SSP2 PCM Stereo in",
- .dev_addr = PXA27x_SSP2_BASE + SSDR,
- .drcmr = &DRCMR(15),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_out = {
- .name = "SSP3 PCM Mono out",
- .dev_addr = PXA27x_SSP3_BASE + SSDR,
- .drcmr = &DRCMR(67),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_mono_in = {
- .name = "SSP3 PCM Mono in",
- .dev_addr = PXA27x_SSP3_BASE + SSDR,
- .drcmr = &DRCMR(66),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_out = {
- .name = "SSP3 PCM Stereo out",
- .dev_addr = PXA27x_SSP3_BASE + SSDR,
- .drcmr = &DRCMR(67),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp3_pcm_stereo_in = {
- .name = "SSP3 PCM Stereo in",
- .dev_addr = PXA27x_SSP3_BASE + SSDR,
- .drcmr = &DRCMR(66),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_out = {
- .name = "SSP4 PCM Mono out",
- .dev_addr = PXA3xx_SSP4_BASE + SSDR,
- .drcmr = &DRCMR(67),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_mono_in = {
- .name = "SSP4 PCM Mono in",
- .dev_addr = PXA3xx_SSP4_BASE + SSDR,
- .drcmr = &DRCMR(66),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH2,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_out = {
- .name = "SSP4 PCM Stereo out",
- .dev_addr = PXA3xx_SSP4_BASE + SSDR,
- .drcmr = &DRCMR(67),
- .dcmd = DCMD_INCSRCADDR | DCMD_FLOWTRG |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static struct pxa2xx_pcm_dma_params pxa_ssp4_pcm_stereo_in = {
- .name = "SSP4 PCM Stereo in",
- .dev_addr = PXA3xx_SSP4_BASE + SSDR,
- .drcmr = &DRCMR(66),
- .dcmd = DCMD_INCTRGADDR | DCMD_FLOWSRC |
- DCMD_BURST16 | DCMD_WIDTH4,
-};
-
-static void dump_registers(struct ssp_device *ssp)
-{
- dev_dbg(&ssp->pdev->dev, "SSCR0 0x%08x SSCR1 0x%08x SSTO 0x%08x\n",
- ssp_read_reg(ssp, SSCR0), ssp_read_reg(ssp, SSCR1),
- ssp_read_reg(ssp, SSTO));
-
- dev_dbg(&ssp->pdev->dev, "SSPSP 0x%08x SSSR 0x%08x SSACD 0x%08x\n",
- ssp_read_reg(ssp, SSPSP), ssp_read_reg(ssp, SSSR),
- ssp_read_reg(ssp, SSACD));
-}
-
-static struct pxa2xx_pcm_dma_params *ssp_dma_params[4][4] = {
- {
- &pxa_ssp1_pcm_mono_out, &pxa_ssp1_pcm_mono_in,
- &pxa_ssp1_pcm_stereo_out, &pxa_ssp1_pcm_stereo_in,
- },
- {
- &pxa_ssp2_pcm_mono_out, &pxa_ssp2_pcm_mono_in,
- &pxa_ssp2_pcm_stereo_out, &pxa_ssp2_pcm_stereo_in,
- },
- {
- &pxa_ssp3_pcm_mono_out, &pxa_ssp3_pcm_mono_in,
- &pxa_ssp3_pcm_stereo_out, &pxa_ssp3_pcm_stereo_in,
- },
- {
- &pxa_ssp4_pcm_mono_out, &pxa_ssp4_pcm_mono_in,
- &pxa_ssp4_pcm_stereo_out, &pxa_ssp4_pcm_stereo_in,
- },
-};
-
-static int pxa_ssp_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- struct ssp_priv *priv = cpu_dai->private_data;
- int ret = 0;
-
- if (!cpu_dai->active) {
- ret = ssp_init(&priv->dev, cpu_dai->id + 1, SSP_NO_IRQ);
- if (ret < 0)
- return ret;
- ssp_disable(&priv->dev);
- }
- return ret;
-}
-
-static void pxa_ssp_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- struct ssp_priv *priv = cpu_dai->private_data;
-
- if (!cpu_dai->active) {
- ssp_disable(&priv->dev);
- ssp_exit(&priv->dev);
- }
-}
-
-#ifdef CONFIG_PM
-
-static int pxa_ssp_suspend(struct snd_soc_dai *cpu_dai)
-{
- struct ssp_priv *priv = cpu_dai->private_data;
-
- if (!cpu_dai->active)
- return 0;
-
- ssp_save_state(&priv->dev, &priv->state);
- clk_disable(priv->dev.ssp->clk);
- return 0;
-}
-
-static int pxa_ssp_resume(struct snd_soc_dai *cpu_dai)
-{
- struct ssp_priv *priv = cpu_dai->private_data;
-
- if (!cpu_dai->active)
- return 0;
-
- clk_enable(priv->dev.ssp->clk);
- ssp_restore_state(&priv->dev, &priv->state);
- ssp_enable(&priv->dev);
-
- return 0;
-}
-
-#else
-#define pxa_ssp_suspend NULL
-#define pxa_ssp_resume NULL
-#endif
-
-/**
- * ssp_set_clkdiv - set SSP clock divider
- * @div: serial clock rate divider
- */
-static void ssp_set_scr(struct ssp_dev *dev, u32 div)
-{
- struct ssp_device *ssp = dev->ssp;
- u32 sscr0 = ssp_read_reg(dev->ssp, SSCR0) & ~SSCR0_SCR;
-
- ssp_write_reg(ssp, SSCR0, (sscr0 | SSCR0_SerClkDiv(div)));
-}
-
-/*
- * Set the SSP ports SYSCLK.
- */
-static int pxa_ssp_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
- int clk_id, unsigned int freq, int dir)
-{
- struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
- int val;
-
- u32 sscr0 = ssp_read_reg(ssp, SSCR0) &
- ~(SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
-
- dev_dbg(&ssp->pdev->dev,
- "pxa_ssp_set_dai_sysclk id: %d, clk_id %d, freq %d\n",
- cpu_dai->id, clk_id, freq);
-
- switch (clk_id) {
- case PXA_SSP_CLK_NET_PLL:
- sscr0 |= SSCR0_MOD;
- break;
- case PXA_SSP_CLK_PLL:
- /* Internal PLL is fixed */
- if (cpu_is_pxa25x())
- priv->sysclk = 1843200;
- else
- priv->sysclk = 13000000;
- break;
- case PXA_SSP_CLK_EXT:
- priv->sysclk = freq;
- sscr0 |= SSCR0_ECS;
- break;
- case PXA_SSP_CLK_NET:
- priv->sysclk = freq;
- sscr0 |= SSCR0_NCS | SSCR0_MOD;
- break;
- case PXA_SSP_CLK_AUDIO:
- priv->sysclk = 0;
- ssp_set_scr(&priv->dev, 1);
- sscr0 |= SSCR0_ADC;
- break;
- default:
- return -ENODEV;
- }
-
- /* The SSP clock must be disabled when changing SSP clock mode
- * on PXA2xx. On PXA3xx it must be enabled when doing so. */
- if (!cpu_is_pxa3xx())
- clk_disable(priv->dev.ssp->clk);
- val = ssp_read_reg(ssp, SSCR0) | sscr0;
- ssp_write_reg(ssp, SSCR0, val);
- if (!cpu_is_pxa3xx())
- clk_enable(priv->dev.ssp->clk);
-
- return 0;
-}
-
-/*
- * Set the SSP clock dividers.
- */
-static int pxa_ssp_set_dai_clkdiv(struct snd_soc_dai *cpu_dai,
- int div_id, int div)
-{
- struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
- int val;
-
- switch (div_id) {
- case PXA_SSP_AUDIO_DIV_ACDS:
- val = (ssp_read_reg(ssp, SSACD) & ~0x7) | SSACD_ACDS(div);
- ssp_write_reg(ssp, SSACD, val);
- break;
- case PXA_SSP_AUDIO_DIV_SCDB:
- val = ssp_read_reg(ssp, SSACD);
- val &= ~SSACD_SCDB;
-#if defined(CONFIG_PXA3xx)
- if (cpu_is_pxa3xx())
- val &= ~SSACD_SCDX8;
-#endif
- switch (div) {
- case PXA_SSP_CLK_SCDB_1:
- val |= SSACD_SCDB;
- break;
- case PXA_SSP_CLK_SCDB_4:
- break;
-#if defined(CONFIG_PXA3xx)
- case PXA_SSP_CLK_SCDB_8:
- if (cpu_is_pxa3xx())
- val |= SSACD_SCDX8;
- else
- return -EINVAL;
- break;
-#endif
- default:
- return -EINVAL;
- }
- ssp_write_reg(ssp, SSACD, val);
- break;
- case PXA_SSP_DIV_SCR:
- ssp_set_scr(&priv->dev, div);
- break;
- default:
- return -ENODEV;
- }
-
- return 0;
-}
-
-/*
- * Configure the PLL frequency pxa27x and (afaik - pxa320 only)
- */
-static int pxa_ssp_set_dai_pll(struct snd_soc_dai *cpu_dai,
- int pll_id, unsigned int freq_in, unsigned int freq_out)
-{
- struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
- u32 ssacd = ssp_read_reg(ssp, SSACD) & ~0x70;
-
-#if defined(CONFIG_PXA3xx)
- if (cpu_is_pxa3xx())
- ssp_write_reg(ssp, SSACDD, 0);
-#endif
-
- switch (freq_out) {
- case 5622000:
- break;
- case 11345000:
- ssacd |= (0x1 << 4);
- break;
- case 12235000:
- ssacd |= (0x2 << 4);
- break;
- case 14857000:
- ssacd |= (0x3 << 4);
- break;
- case 32842000:
- ssacd |= (0x4 << 4);
- break;
- case 48000000:
- ssacd |= (0x5 << 4);
- break;
- case 0:
- /* Disable */
- break;
-
- default:
-#ifdef CONFIG_PXA3xx
- /* PXA3xx has a clock ditherer which can be used to generate
- * a wider range of frequencies - calculate a value for it.
- */
- if (cpu_is_pxa3xx()) {
- u32 val;
- u64 tmp = 19968;
- tmp *= 1000000;
- do_div(tmp, freq_out);
- val = tmp;
-
- val = (val << 16) | 64;;
- ssp_write_reg(ssp, SSACDD, val);
-
- ssacd |= (0x6 << 4);
-
- dev_dbg(&ssp->pdev->dev,
- "Using SSACDD %x to supply %dHz\n",
- val, freq_out);
- break;
- }
-#endif
-
- return -EINVAL;
- }
-
- ssp_write_reg(ssp, SSACD, ssacd);
-
- return 0;
-}
-
-/*
- * Set the active slots in TDM/Network mode
- */
-static int pxa_ssp_set_dai_tdm_slot(struct snd_soc_dai *cpu_dai,
- unsigned int mask, int slots)
-{
- struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
- u32 sscr0;
-
- sscr0 = ssp_read_reg(ssp, SSCR0) & ~SSCR0_SlotsPerFrm(7);
-
- /* set number of active slots */
- sscr0 |= SSCR0_SlotsPerFrm(slots);
- ssp_write_reg(ssp, SSCR0, sscr0);
-
- /* set active slot mask */
- ssp_write_reg(ssp, SSTSA, mask);
- ssp_write_reg(ssp, SSRSA, mask);
- return 0;
-}
-
-/*
- * Tristate the SSP DAI lines
- */
-static int pxa_ssp_set_dai_tristate(struct snd_soc_dai *cpu_dai,
- int tristate)
-{
- struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
- u32 sscr1;
-
- sscr1 = ssp_read_reg(ssp, SSCR1);
- if (tristate)
- sscr1 &= ~SSCR1_TTE;
- else
- sscr1 |= SSCR1_TTE;
- ssp_write_reg(ssp, SSCR1, sscr1);
-
- return 0;
-}
-
-/*
- * Set up the SSP DAI format.
- * The SSP Port must be inactive before calling this function as the
- * physical interface format is changed.
- */
-static int pxa_ssp_set_dai_fmt(struct snd_soc_dai *cpu_dai,
- unsigned int fmt)
-{
- struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
- u32 sscr0;
- u32 sscr1;
- u32 sspsp;
-
- /* reset port settings */
- sscr0 = ssp_read_reg(ssp, SSCR0) &
- (SSCR0_ECS | SSCR0_NCS | SSCR0_MOD | SSCR0_ADC);
- sscr1 = SSCR1_RxTresh(8) | SSCR1_TxTresh(7);
- sspsp = 0;
-
- switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) {
- case SND_SOC_DAIFMT_CBM_CFM:
- sscr1 |= SSCR1_SCLKDIR | SSCR1_SFRMDIR;
- break;
- case SND_SOC_DAIFMT_CBM_CFS:
- sscr1 |= SSCR1_SCLKDIR;
- break;
- case SND_SOC_DAIFMT_CBS_CFS:
- break;
- default:
- return -EINVAL;
- }
-
- ssp_write_reg(ssp, SSCR0, sscr0);
- ssp_write_reg(ssp, SSCR1, sscr1);
- ssp_write_reg(ssp, SSPSP, sspsp);
-
- switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- sscr0 |= SSCR0_MOD | SSCR0_PSP;
- sscr1 |= SSCR1_RWOT | SSCR1_TRAIL;
-
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- sspsp |= SSPSP_FSRT;
- break;
- case SND_SOC_DAIFMT_NB_IF:
- sspsp |= SSPSP_SFRMP | SSPSP_FSRT;
- break;
- case SND_SOC_DAIFMT_IB_IF:
- sspsp |= SSPSP_SFRMP;
- break;
- default:
- return -EINVAL;
- }
- break;
-
- case SND_SOC_DAIFMT_DSP_A:
- sspsp |= SSPSP_FSRT;
- case SND_SOC_DAIFMT_DSP_B:
- sscr0 |= SSCR0_MOD | SSCR0_PSP;
- sscr1 |= SSCR1_TRAIL | SSCR1_RWOT;
-
- switch (fmt & SND_SOC_DAIFMT_INV_MASK) {
- case SND_SOC_DAIFMT_NB_NF:
- sspsp |= SSPSP_SFRMP;
- break;
- case SND_SOC_DAIFMT_IB_IF:
- break;
- default:
- return -EINVAL;
- }
- break;
-
- default:
- return -EINVAL;
- }
-
- ssp_write_reg(ssp, SSCR0, sscr0);
- ssp_write_reg(ssp, SSCR1, sscr1);
- ssp_write_reg(ssp, SSPSP, sspsp);
-
- dump_registers(ssp);
-
- /* Since we are configuring the timings for the format by hand
- * we have to defer some things until hw_params() where we
- * know parameters like the sample size.
- */
- priv->dai_fmt = fmt;
-
- return 0;
-}
-
-/*
- * Set the SSP audio DMA parameters and sample size.
- * Can be called multiple times by oss emulation.
- */
-static int pxa_ssp_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
- int dma = 0, chn = params_channels(params);
- u32 sscr0;
- u32 sspsp;
- int width = snd_pcm_format_physical_width(params_format(params));
-
- /* select correct DMA params */
- if (substream->stream != SNDRV_PCM_STREAM_PLAYBACK)
- dma = 1; /* capture DMA offset is 1,3 */
- if (chn == 2)
- dma += 2; /* stereo DMA offset is 2, mono is 0 */
- cpu_dai->dma_data = ssp_dma_params[cpu_dai->id][dma];
-
- dev_dbg(&ssp->pdev->dev, "pxa_ssp_hw_params: dma %d\n", dma);
-
- /* we can only change the settings if the port is not in use */
- if (ssp_read_reg(ssp, SSCR0) & SSCR0_SSE)
- return 0;
-
- /* clear selected SSP bits */
- sscr0 = ssp_read_reg(ssp, SSCR0) & ~(SSCR0_DSS | SSCR0_EDSS);
- ssp_write_reg(ssp, SSCR0, sscr0);
-
- /* bit size */
- sscr0 = ssp_read_reg(ssp, SSCR0);
- switch (params_format(params)) {
- case SNDRV_PCM_FORMAT_S16_LE:
-#ifdef CONFIG_PXA3xx
- if (cpu_is_pxa3xx())
- sscr0 |= SSCR0_FPCKE;
-#endif
- sscr0 |= SSCR0_DataSize(16);
- if (params_channels(params) > 1)
- sscr0 |= SSCR0_EDSS;
- break;
- case SNDRV_PCM_FORMAT_S24_LE:
- sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(8));
- /* we must be in network mode (2 slots) for 24 bit stereo */
- break;
- case SNDRV_PCM_FORMAT_S32_LE:
- sscr0 |= (SSCR0_EDSS | SSCR0_DataSize(16));
- /* we must be in network mode (2 slots) for 32 bit stereo */
- break;
- }
- ssp_write_reg(ssp, SSCR0, sscr0);
-
- switch (priv->dai_fmt & SND_SOC_DAIFMT_FORMAT_MASK) {
- case SND_SOC_DAIFMT_I2S:
- /* Cleared when the DAI format is set */
- sspsp = ssp_read_reg(ssp, SSPSP) | SSPSP_SFRMWDTH(width);
- ssp_write_reg(ssp, SSPSP, sspsp);
- break;
- default:
- break;
- }
-
- /* We always use a network mode so we always require TDM slots
- * - complain loudly and fail if they've not been set up yet.
- */
- if (!(ssp_read_reg(ssp, SSTSA) & 0xf)) {
- dev_err(&ssp->pdev->dev, "No TDM timeslot configured\n");
- return -EINVAL;
- }
-
- dump_registers(ssp);
-
- return 0;
-}
-
-static int pxa_ssp_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- int ret = 0;
- struct ssp_priv *priv = cpu_dai->private_data;
- struct ssp_device *ssp = priv->dev.ssp;
- int val;
-
- switch (cmd) {
- case SNDRV_PCM_TRIGGER_RESUME:
- ssp_enable(&priv->dev);
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
- val = ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val |= SSCR1_TSRE;
- else
- val |= SSCR1_RSRE;
- ssp_write_reg(ssp, SSCR1, val);
- val = ssp_read_reg(ssp, SSSR);
- ssp_write_reg(ssp, SSSR, val);
- break;
- case SNDRV_PCM_TRIGGER_START:
- val = ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val |= SSCR1_TSRE;
- else
- val |= SSCR1_RSRE;
- ssp_write_reg(ssp, SSCR1, val);
- ssp_enable(&priv->dev);
- break;
- case SNDRV_PCM_TRIGGER_STOP:
- val = ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val &= ~SSCR1_TSRE;
- else
- val &= ~SSCR1_RSRE;
- ssp_write_reg(ssp, SSCR1, val);
- break;
- case SNDRV_PCM_TRIGGER_SUSPEND:
- ssp_disable(&priv->dev);
- break;
- case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
- val = ssp_read_reg(ssp, SSCR1);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- val &= ~SSCR1_TSRE;
- else
- val &= ~SSCR1_RSRE;
- ssp_write_reg(ssp, SSCR1, val);
- break;
-
- default:
- ret = -EINVAL;
- }
-
- dump_registers(ssp);
-
- return ret;
-}
-
-static int pxa_ssp_probe(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct ssp_priv *priv;
- int ret;
-
- priv = kzalloc(sizeof(struct ssp_priv), GFP_KERNEL);
- if (!priv)
- return -ENOMEM;
-
- priv->dev.ssp = ssp_request(dai->id, "SoC audio");
- if (priv->dev.ssp == NULL) {
- ret = -ENODEV;
- goto err_priv;
- }
-
- dai->private_data = priv;
-
- return 0;
-
-err_priv:
- kfree(priv);
- return ret;
-}
-
-static void pxa_ssp_remove(struct platform_device *pdev,
- struct snd_soc_dai *dai)
-{
- struct ssp_priv *priv = dai->private_data;
- ssp_free(priv->dev.ssp);
-}
-
-#define PXA_SSP_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\
- SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | \
- SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | \
- SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000)
-
-#define PXA_SSP_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
- SNDRV_PCM_FMTBIT_S24_LE | \
- SNDRV_PCM_FMTBIT_S32_LE)
-
-struct snd_soc_dai pxa_ssp_dai[] = {
- {
- .name = "pxa2xx-ssp1",
- .id = 0,
- .probe = pxa_ssp_probe,
- .remove = pxa_ssp_remove,
- .suspend = pxa_ssp_suspend,
- .resume = pxa_ssp_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = PXA_SSP_RATES,
- .formats = PXA_SSP_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = PXA_SSP_RATES,
- .formats = PXA_SSP_FORMATS,
- },
- .ops = {
- .startup = pxa_ssp_startup,
- .shutdown = pxa_ssp_shutdown,
- .trigger = pxa_ssp_trigger,
- .hw_params = pxa_ssp_hw_params,
- .set_sysclk = pxa_ssp_set_dai_sysclk,
- .set_clkdiv = pxa_ssp_set_dai_clkdiv,
- .set_pll = pxa_ssp_set_dai_pll,
- .set_fmt = pxa_ssp_set_dai_fmt,
- .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
- .set_tristate = pxa_ssp_set_dai_tristate,
- },
- },
- { .name = "pxa2xx-ssp2",
- .id = 1,
- .probe = pxa_ssp_probe,
- .remove = pxa_ssp_remove,
- .suspend = pxa_ssp_suspend,
- .resume = pxa_ssp_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = PXA_SSP_RATES,
- .formats = PXA_SSP_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = PXA_SSP_RATES,
- .formats = PXA_SSP_FORMATS,
- },
- .ops = {
- .startup = pxa_ssp_startup,
- .shutdown = pxa_ssp_shutdown,
- .trigger = pxa_ssp_trigger,
- .hw_params = pxa_ssp_hw_params,
- .set_sysclk = pxa_ssp_set_dai_sysclk,
- .set_clkdiv = pxa_ssp_set_dai_clkdiv,
- .set_pll = pxa_ssp_set_dai_pll,
- .set_fmt = pxa_ssp_set_dai_fmt,
- .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
- .set_tristate = pxa_ssp_set_dai_tristate,
- },
- },
- {
- .name = "pxa2xx-ssp3",
- .id = 2,
- .probe = pxa_ssp_probe,
- .remove = pxa_ssp_remove,
- .suspend = pxa_ssp_suspend,
- .resume = pxa_ssp_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = PXA_SSP_RATES,
- .formats = PXA_SSP_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = PXA_SSP_RATES,
- .formats = PXA_SSP_FORMATS,
- },
- .ops = {
- .startup = pxa_ssp_startup,
- .shutdown = pxa_ssp_shutdown,
- .trigger = pxa_ssp_trigger,
- .hw_params = pxa_ssp_hw_params,
- .set_sysclk = pxa_ssp_set_dai_sysclk,
- .set_clkdiv = pxa_ssp_set_dai_clkdiv,
- .set_pll = pxa_ssp_set_dai_pll,
- .set_fmt = pxa_ssp_set_dai_fmt,
- .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
- .set_tristate = pxa_ssp_set_dai_tristate,
- },
- },
- {
- .name = "pxa2xx-ssp4",
- .id = 3,
- .probe = pxa_ssp_probe,
- .remove = pxa_ssp_remove,
- .suspend = pxa_ssp_suspend,
- .resume = pxa_ssp_resume,
- .playback = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = PXA_SSP_RATES,
- .formats = PXA_SSP_FORMATS,
- },
- .capture = {
- .channels_min = 1,
- .channels_max = 2,
- .rates = PXA_SSP_RATES,
- .formats = PXA_SSP_FORMATS,
- },
- .ops = {
- .startup = pxa_ssp_startup,
- .shutdown = pxa_ssp_shutdown,
- .trigger = pxa_ssp_trigger,
- .hw_params = pxa_ssp_hw_params,
- .set_sysclk = pxa_ssp_set_dai_sysclk,
- .set_clkdiv = pxa_ssp_set_dai_clkdiv,
- .set_pll = pxa_ssp_set_dai_pll,
- .set_fmt = pxa_ssp_set_dai_fmt,
- .set_tdm_slot = pxa_ssp_set_dai_tdm_slot,
- .set_tristate = pxa_ssp_set_dai_tristate,
- },
- },
-};
-EXPORT_SYMBOL_GPL(pxa_ssp_dai);
-
-static int __devinit pxa_ssp_init(void)
-{
- return snd_soc_register_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
-}
-module_init(pxa_ssp_init);
-
-static void __exit pxa_ssp_exit(void)
-{
- snd_soc_unregister_dais(pxa_ssp_dai, ARRAY_SIZE(pxa_ssp_dai));
-}
-module_exit(pxa_ssp_exit);
-
-/* Module information */
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_DESCRIPTION("PXA SSP/PCM SoC Interface");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa-ssp.h b/sound/soc/pxa/pxa-ssp.h
deleted file mode 100644
index 91deadd55675..000000000000
--- a/sound/soc/pxa/pxa-ssp.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * ASoC PXA SSP port support
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef _PXA_SSP_H
-#define _PXA_SSP_H
-
-/* pxa DAI SSP IDs */
-#define PXA_DAI_SSP1 0
-#define PXA_DAI_SSP2 1
-#define PXA_DAI_SSP3 2
-#define PXA_DAI_SSP4 3
-
-/* SSP clock sources */
-#define PXA_SSP_CLK_PLL 0
-#define PXA_SSP_CLK_EXT 1
-#define PXA_SSP_CLK_NET 2
-#define PXA_SSP_CLK_AUDIO 3
-#define PXA_SSP_CLK_NET_PLL 4
-
-/* SSP audio dividers */
-#define PXA_SSP_AUDIO_DIV_ACDS 0
-#define PXA_SSP_AUDIO_DIV_SCDB 1
-#define PXA_SSP_DIV_SCR 2
-
-/* SSP ACDS audio dividers values */
-#define PXA_SSP_CLK_AUDIO_DIV_1 0
-#define PXA_SSP_CLK_AUDIO_DIV_2 1
-#define PXA_SSP_CLK_AUDIO_DIV_4 2
-#define PXA_SSP_CLK_AUDIO_DIV_8 3
-#define PXA_SSP_CLK_AUDIO_DIV_16 4
-#define PXA_SSP_CLK_AUDIO_DIV_32 5
-
-/* SSP divider bypass */
-#define PXA_SSP_CLK_SCDB_4 0
-#define PXA_SSP_CLK_SCDB_1 1
-#define PXA_SSP_CLK_SCDB_8 2
-
-#define PXA_SSP_PLL_OUT 0
-
-extern struct snd_soc_dai pxa_ssp_dai[4];
-
-#endif
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c
index 2574d323ae51..5e727393cfd4 100644
--- a/sound/soc/pxa/pxa2xx-ac97.c
+++ b/sound/soc/pxa/pxa2xx-ac97.c
@@ -88,12 +88,14 @@ static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_mic_mono_in = {
};
#ifdef CONFIG_PM
-static int pxa2xx_ac97_suspend(struct snd_soc_dai *dai)
+static int pxa2xx_ac97_suspend(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_suspend();
}
-static int pxa2xx_ac97_resume(struct snd_soc_dai *dai)
+static int pxa2xx_ac97_resume(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
{
return pxa2xx_ac97_hw_resume();
}
@@ -116,8 +118,7 @@ static void pxa2xx_ac97_remove(struct platform_device *pdev,
}
static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -131,8 +132,7 @@ static int pxa2xx_ac97_hw_params(struct snd_pcm_substream *substream,
}
static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -146,8 +146,7 @@ static int pxa2xx_ac97_hw_aux_params(struct snd_pcm_substream *substream,
}
static int pxa2xx_ac97_hw_mic_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -172,7 +171,7 @@ struct snd_soc_dai pxa_ac97_dai[] = {
{
.name = "pxa2xx-ac97",
.id = 0,
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97,
.probe = pxa2xx_ac97_probe,
.remove = pxa2xx_ac97_remove,
.suspend = pxa2xx_ac97_suspend,
@@ -195,7 +194,7 @@ struct snd_soc_dai pxa_ac97_dai[] = {
{
.name = "pxa2xx-ac97-aux",
.id = 1,
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97,
.playback = {
.stream_name = "AC97 Aux Playback",
.channels_min = 1,
@@ -214,7 +213,7 @@ struct snd_soc_dai pxa_ac97_dai[] = {
{
.name = "pxa2xx-ac97-mic",
.id = 2,
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97,
.capture = {
.stream_name = "AC97 Mic Capture",
.channels_min = 1,
@@ -229,18 +228,6 @@ struct snd_soc_dai pxa_ac97_dai[] = {
EXPORT_SYMBOL_GPL(pxa_ac97_dai);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
-static int __devinit pxa_ac97_init(void)
-{
- return snd_soc_register_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
-}
-module_init(pxa_ac97_init);
-
-static void __exit pxa_ac97_exit(void)
-{
- snd_soc_unregister_dais(pxa_ac97_dai, ARRAY_SIZE(pxa_ac97_dai));
-}
-module_exit(pxa_ac97_exit);
-
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("AC97 driver for the Intel PXA2xx chip");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/pxa2xx-i2s.c b/sound/soc/pxa/pxa2xx-i2s.c
index 517991fb1099..e758034db5c3 100644
--- a/sound/soc/pxa/pxa2xx-i2s.c
+++ b/sound/soc/pxa/pxa2xx-i2s.c
@@ -121,8 +121,7 @@ static struct pxa2xx_gpio gpio_bus[] = {
},
};
-static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int pxa2xx_i2s_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -188,8 +187,7 @@ static int pxa2xx_i2s_set_dai_sysclk(struct snd_soc_dai *cpu_dai,
}
static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -250,8 +248,7 @@ static int pxa2xx_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
{
int ret = 0;
@@ -272,8 +269,7 @@ static int pxa2xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
return ret;
}
-static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream)
{
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
SACR1 |= SACR1_DRPL;
@@ -293,7 +289,8 @@ static void pxa2xx_i2s_shutdown(struct snd_pcm_substream *substream,
}
#ifdef CONFIG_PM
-static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
+static int pxa2xx_i2s_suspend(struct platform_device *dev,
+ struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
@@ -310,7 +307,8 @@ static int pxa2xx_i2s_suspend(struct snd_soc_dai *dai)
return 0;
}
-static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
+static int pxa2xx_i2s_resume(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
{
if (!dai->active)
return 0;
@@ -338,6 +336,7 @@ static int pxa2xx_i2s_resume(struct snd_soc_dai *dai)
struct snd_soc_dai pxa_i2s_dai = {
.name = "pxa2xx-i2s",
.id = 0,
+ .type = SND_SOC_DAI_I2S,
.suspend = pxa2xx_i2s_suspend,
.resume = pxa2xx_i2s_resume,
.playback = {
@@ -354,7 +353,8 @@ struct snd_soc_dai pxa_i2s_dai = {
.startup = pxa2xx_i2s_startup,
.shutdown = pxa2xx_i2s_shutdown,
.trigger = pxa2xx_i2s_trigger,
- .hw_params = pxa2xx_i2s_hw_params,
+ .hw_params = pxa2xx_i2s_hw_params,},
+ .dai_ops = {
.set_fmt = pxa2xx_i2s_set_dai_fmt,
.set_sysclk = pxa2xx_i2s_set_dai_sysclk,
},
@@ -364,23 +364,12 @@ EXPORT_SYMBOL_GPL(pxa_i2s_dai);
static int pxa2xx_i2s_probe(struct platform_device *dev)
{
- int ret;
-
clk_i2s = clk_get(&dev->dev, "I2SCLK");
- if (IS_ERR(clk_i2s))
- return PTR_ERR(clk_i2s);
-
- pxa_i2s_dai.dev = &dev->dev;
- ret = snd_soc_register_dai(&pxa_i2s_dai);
- if (ret != 0)
- clk_put(clk_i2s);
-
- return ret;
+ return IS_ERR(clk_i2s) ? PTR_ERR(clk_i2s) : 0;
}
static int __devexit pxa2xx_i2s_remove(struct platform_device *dev)
{
- snd_soc_unregister_dai(&pxa_i2s_dai);
clk_put(clk_i2s);
clk_i2s = ERR_PTR(-ENOENT);
return 0;
diff --git a/sound/soc/pxa/pxa2xx-pcm.c b/sound/soc/pxa/pxa2xx-pcm.c
index 4fa1578f5d47..afcd892cd2fa 100644
--- a/sound/soc/pxa/pxa2xx-pcm.c
+++ b/sound/soc/pxa/pxa2xx-pcm.c
@@ -69,7 +69,7 @@ static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
return 0;
}
-static struct snd_pcm_ops pxa2xx_pcm_ops = {
+struct snd_pcm_ops pxa2xx_pcm_ops = {
.open = __pxa2xx_pcm_open,
.close = __pxa2xx_pcm_close,
.ioctl = snd_pcm_lib_ioctl,
@@ -118,18 +118,6 @@ struct snd_soc_platform pxa2xx_soc_platform = {
};
EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);
-static int __devinit pxa2xx_soc_platform_init(void)
-{
- return snd_soc_register_platform(&pxa2xx_soc_platform);
-}
-module_init(pxa2xx_soc_platform_init);
-
-static void __exit pxa2xx_soc_platform_exit(void)
-{
- snd_soc_unregister_platform(&pxa2xx_soc_platform);
-}
-module_exit(pxa2xx_soc_platform_exit);
-
MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/pxa/spitz.c b/sound/soc/pxa/spitz.c
index a3b9e6bdf979..d307b6757e95 100644
--- a/sound/soc/pxa/spitz.c
+++ b/sound/soc/pxa/spitz.c
@@ -319,9 +319,8 @@ static struct snd_soc_dai_link spitz_dai = {
};
/* spitz audio machine driver */
-static struct snd_soc_card snd_soc_spitz = {
+static struct snd_soc_machine snd_soc_machine_spitz = {
.name = "Spitz",
- .platform = &pxa2xx_soc_platform,
.dai_link = &spitz_dai,
.num_links = 1,
};
@@ -334,7 +333,8 @@ static struct wm8750_setup_data spitz_wm8750_setup = {
/* spitz audio subsystem */
static struct snd_soc_device spitz_snd_devdata = {
- .card = &snd_soc_spitz,
+ .machine = &snd_soc_machine_spitz,
+ .platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm8750,
.codec_data = &spitz_wm8750_setup,
};
diff --git a/sound/soc/pxa/tosa.c b/sound/soc/pxa/tosa.c
index c77194f74c9b..afefe41b8c46 100644
--- a/sound/soc/pxa/tosa.c
+++ b/sound/soc/pxa/tosa.c
@@ -38,7 +38,7 @@
#include "pxa2xx-pcm.h"
#include "pxa2xx-ac97.h"
-static struct snd_soc_card tosa;
+static struct snd_soc_machine tosa;
#define TOSA_HP 0
#define TOSA_MIC_INT 1
@@ -230,37 +230,15 @@ static struct snd_soc_dai_link tosa_dai[] = {
},
};
-static int tosa_probe(struct platform_device *dev)
-{
- int ret;
-
- ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
- if (ret)
- return ret;
- ret = gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
- if (ret)
- gpio_free(TOSA_GPIO_L_MUTE);
-
- return ret;
-}
-
-static int tosa_remove(struct platform_device *dev)
-{
- gpio_free(TOSA_GPIO_L_MUTE);
- return 0;
-}
-
-static struct snd_soc_card tosa = {
+static struct snd_soc_machine tosa = {
.name = "Tosa",
- .platform = &pxa2xx_soc_platform,
.dai_link = tosa_dai,
.num_links = ARRAY_SIZE(tosa_dai),
- .probe = tosa_probe,
- .remove = tosa_remove,
};
static struct snd_soc_device tosa_snd_devdata = {
- .card = &tosa,
+ .machine = &tosa,
+ .platform = &pxa2xx_soc_platform,
.codec_dev = &soc_codec_dev_wm9712,
};
@@ -273,6 +251,11 @@ static int __init tosa_init(void)
if (!machine_is_tosa())
return -ENODEV;
+ ret = gpio_request(TOSA_GPIO_L_MUTE, "Headphone Jack");
+ if (ret)
+ return ret;
+ gpio_direction_output(TOSA_GPIO_L_MUTE, 0);
+
tosa_snd_device = platform_device_alloc("soc-audio", -1);
if (!tosa_snd_device) {
ret = -ENOMEM;
@@ -289,12 +272,15 @@ static int __init tosa_init(void)
platform_device_put(tosa_snd_device);
err_alloc:
+ gpio_free(TOSA_GPIO_L_MUTE);
+
return ret;
}
static void __exit tosa_exit(void)
{
platform_device_unregister(tosa_snd_device);
+ gpio_free(TOSA_GPIO_L_MUTE);
}
module_init(tosa_init);
diff --git a/sound/soc/pxa/zylonite.c b/sound/soc/pxa/zylonite.c
deleted file mode 100644
index f8e9ecd589d3..000000000000
--- a/sound/soc/pxa/zylonite.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * zylonite.c -- SoC audio for Zylonite
- *
- * Copyright 2008 Wolfson Microelectronics PLC.
- * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- */
-
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/device.h>
-#include <linux/i2c.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-
-#include "../codecs/wm9713.h"
-#include "pxa2xx-pcm.h"
-#include "pxa2xx-ac97.h"
-#include "pxa-ssp.h"
-
-static struct snd_soc_card zylonite;
-
-static const struct snd_soc_dapm_widget zylonite_dapm_widgets[] = {
- SND_SOC_DAPM_HP("Headphone", NULL),
- SND_SOC_DAPM_MIC("Headset Microphone", NULL),
- SND_SOC_DAPM_MIC("Handset Microphone", NULL),
- SND_SOC_DAPM_SPK("Multiactor", NULL),
- SND_SOC_DAPM_SPK("Headset Earpiece", NULL),
-};
-
-/* Currently supported audio map */
-static const struct snd_soc_dapm_route audio_map[] = {
-
- /* Headphone output connected to HPL/HPR */
- { "Headphone", NULL, "HPL" },
- { "Headphone", NULL, "HPR" },
-
- /* On-board earpiece */
- { "Headset Earpiece", NULL, "OUT3" },
-
- /* Headphone mic */
- { "MIC2A", NULL, "Mic Bias" },
- { "Mic Bias", NULL, "Headset Microphone" },
-
- /* On-board mic */
- { "MIC1", NULL, "Mic Bias" },
- { "Mic Bias", NULL, "Handset Microphone" },
-
- /* Multiactor differentially connected over SPKL/SPKR */
- { "Multiactor", NULL, "SPKL" },
- { "Multiactor", NULL, "SPKR" },
-};
-
-static int zylonite_wm9713_init(struct snd_soc_codec *codec)
-{
- /* Currently we only support use of the AC97 clock here. If
- * CLK_POUT is selected by SW15 then the clock API will need
- * to be used to request and enable it here.
- */
-
- snd_soc_dapm_new_controls(codec, zylonite_dapm_widgets,
- ARRAY_SIZE(zylonite_dapm_widgets));
-
- snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
-
- /* Static setup for now */
- snd_soc_dapm_enable_pin(codec, "Headphone");
- snd_soc_dapm_enable_pin(codec, "Headset Earpiece");
-
- snd_soc_dapm_sync(codec);
- return 0;
-}
-
-static int zylonite_voice_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- unsigned int pll_out = 0;
- unsigned int acds = 0;
- unsigned int wm9713_div = 0;
- int ret = 0;
-
- switch (params_rate(params)) {
- case 8000:
- wm9713_div = 12;
- pll_out = 2048000;
- break;
- case 16000:
- wm9713_div = 6;
- pll_out = 4096000;
- break;
- case 48000:
- default:
- wm9713_div = 2;
- pll_out = 12288000;
- acds = 1;
- break;
- }
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_tdm_slot(cpu_dai,
- params_channels(params),
- params_channels(params));
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_pll(cpu_dai, 0, 0, pll_out);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_clkdiv(cpu_dai, PXA_SSP_AUDIO_DIV_ACDS, acds);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_sysclk(cpu_dai, PXA_SSP_CLK_AUDIO, 0, 1);
- if (ret < 0)
- return ret;
-
- /* Note that if the PLL is in use the WM9713_PCMCLK_PLL_DIV needs
- * to be set instead.
- */
- ret = snd_soc_dai_set_clkdiv(codec_dai, WM9713_PCMCLK_DIV,
- WM9713_PCMDIV(wm9713_div));
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct snd_soc_ops zylonite_voice_ops = {
- .hw_params = zylonite_voice_hw_params,
-};
-
-static struct snd_soc_dai_link zylonite_dai[] = {
-{
- .name = "AC97",
- .stream_name = "AC97 HiFi",
- .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_HIFI],
- .codec_dai = &wm9713_dai[WM9713_DAI_AC97_HIFI],
- .init = zylonite_wm9713_init,
-},
-{
- .name = "AC97 Aux",
- .stream_name = "AC97 Aux",
- .cpu_dai = &pxa_ac97_dai[PXA2XX_DAI_AC97_AUX],
- .codec_dai = &wm9713_dai[WM9713_DAI_AC97_AUX],
-},
-{
- .name = "WM9713 Voice",
- .stream_name = "WM9713 Voice",
- .cpu_dai = &pxa_ssp_dai[PXA_DAI_SSP3],
- .codec_dai = &wm9713_dai[WM9713_DAI_PCM_VOICE],
- .ops = &zylonite_voice_ops,
-},
-};
-
-static struct snd_soc_card zylonite = {
- .name = "Zylonite",
- .platform = &pxa2xx_soc_platform,
- .dai_link = zylonite_dai,
- .num_links = ARRAY_SIZE(zylonite_dai),
-};
-
-static struct snd_soc_device zylonite_snd_ac97_devdata = {
- .card = &zylonite,
- .codec_dev = &soc_codec_dev_wm9713,
-};
-
-static struct platform_device *zylonite_snd_ac97_device;
-
-static int __init zylonite_init(void)
-{
- int ret;
-
- zylonite_snd_ac97_device = platform_device_alloc("soc-audio", -1);
- if (!zylonite_snd_ac97_device)
- return -ENOMEM;
-
- platform_set_drvdata(zylonite_snd_ac97_device,
- &zylonite_snd_ac97_devdata);
- zylonite_snd_ac97_devdata.dev = &zylonite_snd_ac97_device->dev;
-
- ret = platform_device_add(zylonite_snd_ac97_device);
- if (ret != 0)
- platform_device_put(zylonite_snd_ac97_device);
-
- return ret;
-}
-
-static void __exit zylonite_exit(void)
-{
- platform_device_unregister(zylonite_snd_ac97_device);
-}
-
-module_init(zylonite_init);
-module_exit(zylonite_exit);
-
-MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
-MODULE_DESCRIPTION("ALSA SoC WM9713 Zylonite");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/Kconfig b/sound/soc/s3c24xx/Kconfig
index fcd03acf10f6..b9f2353effeb 100644
--- a/sound/soc/s3c24xx/Kconfig
+++ b/sound/soc/s3c24xx/Kconfig
@@ -44,8 +44,3 @@ config SND_S3C24XX_SOC_LN2440SBC_ALC650
Say Y if you want to add support for SoC audio on ln2440sbc
with the ALC650.
-config SND_S3C24XX_SOC_S3C24XX_UDA134X
- tristate "SoC I2S Audio support UDA134X wired to a S3C24XX"
- depends on SND_S3C24XX_SOC
- select SND_S3C24XX_SOC_I2S
- select SND_SOC_UDA134X
diff --git a/sound/soc/s3c24xx/Makefile b/sound/soc/s3c24xx/Makefile
index 96b3f3f617d4..0aa5fb0b9700 100644
--- a/sound/soc/s3c24xx/Makefile
+++ b/sound/soc/s3c24xx/Makefile
@@ -13,9 +13,7 @@ obj-$(CONFIG_SND_S3C2412_SOC_I2S) += snd-soc-s3c2412-i2s.o
snd-soc-neo1973-wm8753-objs := neo1973_wm8753.o
snd-soc-smdk2443-wm9710-objs := smdk2443_wm9710.o
snd-soc-ln2440sbc-alc650-objs := ln2440sbc_alc650.o
-snd-soc-s3c24xx-uda134x-objs := s3c24xx_uda134x.o
obj-$(CONFIG_SND_S3C24XX_SOC_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o
obj-$(CONFIG_SND_S3C24XX_SOC_SMDK2443_WM9710) += snd-soc-smdk2443-wm9710.o
obj-$(CONFIG_SND_S3C24XX_SOC_LN2440SBC_ALC650) += snd-soc-ln2440sbc-alc650.o
-obj-$(CONFIG_SND_S3C24XX_SOC_S3C24XX_UDA134X) += snd-soc-s3c24xx-uda134x.o
diff --git a/sound/soc/s3c24xx/ln2440sbc_alc650.c b/sound/soc/s3c24xx/ln2440sbc_alc650.c
index 12c71482d258..4eab2c19c454 100644
--- a/sound/soc/s3c24xx/ln2440sbc_alc650.c
+++ b/sound/soc/s3c24xx/ln2440sbc_alc650.c
@@ -27,7 +27,7 @@
#include "s3c24xx-pcm.h"
#include "s3c24xx-ac97.h"
-static struct snd_soc_card ln2440sbc;
+static struct snd_soc_machine ln2440sbc;
static struct snd_soc_dai_link ln2440sbc_dai[] = {
{
@@ -38,15 +38,15 @@ static struct snd_soc_dai_link ln2440sbc_dai[] = {
},
};
-static struct snd_soc_card ln2440sbc = {
+static struct snd_soc_machine ln2440sbc = {
.name = "LN2440SBC",
- .platform = &s3c24xx_soc_platform,
.dai_link = ln2440sbc_dai,
.num_links = ARRAY_SIZE(ln2440sbc_dai),
};
static struct snd_soc_device ln2440sbc_snd_ac97_devdata = {
- .card = &ln2440sbc,
+ .machine = &ln2440sbc,
+ .platform = &s3c24xx_soc_platform,
.codec_dev = &soc_codec_dev_ac97,
};
diff --git a/sound/soc/s3c24xx/neo1973_wm8753.c b/sound/soc/s3c24xx/neo1973_wm8753.c
index 45bb12e8ea44..87ddfefcc2fb 100644
--- a/sound/soc/s3c24xx/neo1973_wm8753.c
+++ b/sound/soc/s3c24xx/neo1973_wm8753.c
@@ -59,7 +59,7 @@
#define NEO_CAPTURE_HEADSET 7
#define NEO_CAPTURE_BLUETOOTH 8
-static struct snd_soc_card neo1973;
+static struct snd_soc_machine neo1973;
static struct i2c_client *i2c;
static int neo1973_hifi_hw_params(struct snd_pcm_substream *substream,
@@ -548,6 +548,7 @@ static int neo1973_wm8753_init(struct snd_soc_codec *codec)
static struct snd_soc_dai bt_dai = {
.name = "Bluetooth",
.id = 0,
+ .type = SND_SOC_DAI_PCM,
.playback = {
.channels_min = 1,
.channels_max = 1,
@@ -578,9 +579,8 @@ static struct snd_soc_dai_link neo1973_dai[] = {
},
};
-static struct snd_soc_card neo1973 = {
+static struct snd_soc_machine neo1973 = {
.name = "neo1973",
- .platform = &s3c24xx_soc_platform,
.dai_link = neo1973_dai,
.num_links = ARRAY_SIZE(neo1973_dai),
};
@@ -591,7 +591,8 @@ static struct wm8753_setup_data neo1973_wm8753_setup = {
};
static struct snd_soc_device neo1973_snd_devdata = {
- .card = &neo1973,
+ .machine = &neo1973,
+ .platform = &s3c24xx_soc_platform,
.codec_dev = &soc_codec_dev_wm8753,
.codec_data = &neo1973_wm8753_setup,
};
diff --git a/sound/soc/s3c24xx/s3c2412-i2s.c b/sound/soc/s3c24xx/s3c2412-i2s.c
index 2cf050791562..ded7d995a922 100644
--- a/sound/soc/s3c24xx/s3c2412-i2s.c
+++ b/sound/soc/s3c24xx/s3c2412-i2s.c
@@ -343,8 +343,7 @@ static int s3c2412_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
}
static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
u32 iismod;
@@ -374,8 +373,7 @@ static int s3c2412_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int s3c2412_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
{
int capture = (substream->stream == SNDRV_PCM_STREAM_CAPTURE);
unsigned long irqs;
@@ -649,7 +647,8 @@ static int s3c2412_i2s_probe(struct platform_device *pdev,
}
#ifdef CONFIG_PM
-static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
+static int s3c2412_i2s_suspend(struct platform_device *dev,
+ struct snd_soc_dai *dai)
{
struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
u32 iismod;
@@ -664,24 +663,25 @@ static int s3c2412_i2s_suspend(struct snd_soc_dai *dai)
iismod = readl(i2s->regs + S3C2412_IISMOD);
if (iismod & S3C2412_IISCON_RXDMA_ACTIVE)
- pr_warning("%s: RXDMA active?\n", __func__);
+ dev_warn(&dev->dev, "%s: RXDMA active?\n", __func__);
if (iismod & S3C2412_IISCON_TXDMA_ACTIVE)
- pr_warning("%s: TXDMA active?\n", __func__);
+ dev_warn(&dev->dev, "%s: TXDMA active?\n", __func__);
if (iismod & S3C2412_IISCON_IIS_ACTIVE)
- pr_warning("%s: IIS active\n", __func__);
+ dev_warn(&dev->dev, "%s: IIS active\n", __func__);
}
return 0;
}
-static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
+static int s3c2412_i2s_resume(struct platform_device *pdev,
+ struct snd_soc_dai *dai)
{
struct s3c2412_i2s_info *i2s = &s3c2412_i2s;
- pr_info("dai_active %d, IISMOD %08x, IISCON %08x\n",
- dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
+ dev_info(&pdev->dev, "dai_active %d, IISMOD %08x, IISCON %08x\n",
+ dai->active, i2s->suspend_iismod, i2s->suspend_iiscon);
if (dai->active) {
writel(i2s->suspend_iiscon, i2s->regs + S3C2412_IISCON);
@@ -711,6 +711,7 @@ static int s3c2412_i2s_resume(struct snd_soc_dai *dai)
struct snd_soc_dai s3c2412_i2s_dai = {
.name = "s3c2412-i2s",
.id = 0,
+ .type = SND_SOC_DAI_I2S,
.probe = s3c2412_i2s_probe,
.suspend = s3c2412_i2s_suspend,
.resume = s3c2412_i2s_resume,
@@ -729,6 +730,8 @@ struct snd_soc_dai s3c2412_i2s_dai = {
.ops = {
.trigger = s3c2412_i2s_trigger,
.hw_params = s3c2412_i2s_hw_params,
+ },
+ .dai_ops = {
.set_fmt = s3c2412_i2s_set_fmt,
.set_clkdiv = s3c2412_i2s_set_clkdiv,
.set_sysclk = s3c2412_i2s_set_sysclk,
@@ -736,19 +739,6 @@ struct snd_soc_dai s3c2412_i2s_dai = {
};
EXPORT_SYMBOL_GPL(s3c2412_i2s_dai);
-static int __devinit s3c2412_i2s_init(void)
-{
- return snd_soc_register_dai(&s3c2412_i2s_dai);
-}
-module_init(s3c2412_i2s_init);
-
-static void __exit s3c2412_i2s_exit(void)
-{
- snd_soc_unregister_dai(&s3c2412_i2s_dai);
-}
-module_exit(s3c2412_i2s_exit);
-
-
/* Module information */
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("S3C2412 I2S SoC Interface");
diff --git a/sound/soc/s3c24xx/s3c2443-ac97.c b/sound/soc/s3c24xx/s3c2443-ac97.c
index aa99e1615eff..c473a3b97b55 100644
--- a/sound/soc/s3c24xx/s3c2443-ac97.c
+++ b/sound/soc/s3c24xx/s3c2443-ac97.c
@@ -271,8 +271,7 @@ static void s3c2443_ac97_remove(struct platform_device *pdev,
}
static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -285,8 +284,7 @@ static int s3c2443_ac97_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd)
{
u32 ac_glbctrl;
@@ -315,8 +313,7 @@ static int s3c2443_ac97_trigger(struct snd_pcm_substream *substream, int cmd,
}
static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
@@ -330,7 +327,7 @@ static int s3c2443_ac97_hw_mic_params(struct snd_pcm_substream *substream,
}
static int s3c2443_ac97_mic_trigger(struct snd_pcm_substream *substream,
- int cmd, struct snd_soc_dai *dai)
+ int cmd)
{
u32 ac_glbctrl;
@@ -359,7 +356,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = {
{
.name = "s3c2443-ac97",
.id = 0,
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97,
.probe = s3c2443_ac97_probe,
.remove = s3c2443_ac97_remove,
.playback = {
@@ -381,7 +378,7 @@ struct snd_soc_dai s3c2443_ac97_dai[] = {
{
.name = "pxa2xx-ac97-mic",
.id = 1,
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97,
.capture = {
.stream_name = "AC97 Mic Capture",
.channels_min = 1,
@@ -396,19 +393,6 @@ struct snd_soc_dai s3c2443_ac97_dai[] = {
EXPORT_SYMBOL_GPL(s3c2443_ac97_dai);
EXPORT_SYMBOL_GPL(soc_ac97_ops);
-static int __devinit s3c2443_ac97_init(void)
-{
- return snd_soc_register_dai(&s3c2443_ac97_dai);
-}
-module_init(s3c2443_ac97_init);
-
-static void __exit s3c2443_ac97_exit(void)
-{
- snd_soc_unregister_dai(&s3c2443_ac97_dai);
-}
-module_exit(s3c2443_ac97_exit);
-
-
MODULE_AUTHOR("Graeme Gregory");
MODULE_DESCRIPTION("AC97 driver for the Samsung s3c2443 chip");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx-i2s.c b/sound/soc/s3c24xx/s3c24xx-i2s.c
index 897b1ac92cef..ba4476b55fbc 100644
--- a/sound/soc/s3c24xx/s3c24xx-i2s.c
+++ b/sound/soc/s3c24xx/s3c24xx-i2s.c
@@ -243,8 +243,7 @@ static int s3c24xx_i2s_set_fmt(struct snd_soc_dai *cpu_dai,
}
static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
u32 iismod;
@@ -262,17 +261,10 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
switch (params_format(params)) {
case SNDRV_PCM_FORMAT_S8:
- iismod &= ~S3C2410_IISMOD_16BIT;
- ((struct s3c24xx_pcm_dma_params *)
- rtd->dai->cpu_dai->dma_data)->dma_size = 1;
break;
case SNDRV_PCM_FORMAT_S16_LE:
iismod |= S3C2410_IISMOD_16BIT;
- ((struct s3c24xx_pcm_dma_params *)
- rtd->dai->cpu_dai->dma_data)->dma_size = 2;
break;
- default:
- return -EINVAL;
}
writel(iismod, s3c24xx_i2s.regs + S3C2410_IISMOD);
@@ -280,8 +272,7 @@ static int s3c24xx_i2s_hw_params(struct snd_pcm_substream *substream,
return 0;
}
-static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int s3c24xx_i2s_trigger(struct snd_pcm_substream *substream, int cmd)
{
int ret = 0;
@@ -419,7 +410,8 @@ static int s3c24xx_i2s_probe(struct platform_device *pdev,
}
#ifdef CONFIG_PM
-static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
+static int s3c24xx_i2s_suspend(struct platform_device *pdev,
+ struct snd_soc_dai *cpu_dai)
{
DBG("Entered %s\n", __func__);
@@ -433,7 +425,8 @@ static int s3c24xx_i2s_suspend(struct snd_soc_dai *cpu_dai)
return 0;
}
-static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
+static int s3c24xx_i2s_resume(struct platform_device *pdev,
+ struct snd_soc_dai *cpu_dai)
{
DBG("Entered %s\n", __func__);
clk_enable(s3c24xx_i2s.iis_clk);
@@ -459,6 +452,7 @@ static int s3c24xx_i2s_resume(struct snd_soc_dai *cpu_dai)
struct snd_soc_dai s3c24xx_i2s_dai = {
.name = "s3c24xx-i2s",
.id = 0,
+ .type = SND_SOC_DAI_I2S,
.probe = s3c24xx_i2s_probe,
.suspend = s3c24xx_i2s_suspend,
.resume = s3c24xx_i2s_resume,
@@ -474,7 +468,8 @@ struct snd_soc_dai s3c24xx_i2s_dai = {
.formats = SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE,},
.ops = {
.trigger = s3c24xx_i2s_trigger,
- .hw_params = s3c24xx_i2s_hw_params,
+ .hw_params = s3c24xx_i2s_hw_params,},
+ .dai_ops = {
.set_fmt = s3c24xx_i2s_set_fmt,
.set_clkdiv = s3c24xx_i2s_set_clkdiv,
.set_sysclk = s3c24xx_i2s_set_sysclk,
@@ -482,18 +477,6 @@ struct snd_soc_dai s3c24xx_i2s_dai = {
};
EXPORT_SYMBOL_GPL(s3c24xx_i2s_dai);
-static int __devinit s3c24xx_i2s_init(void)
-{
- return snd_soc_register_dai(&s3c24xx_i2s_dai);
-}
-module_init(s3c24xx_i2s_init);
-
-static void __exit s3c24xx_i2s_exit(void)
-{
- snd_soc_unregister_dai(&s3c24xx_i2s_dai);
-}
-module_exit(s3c24xx_i2s_exit);
-
/* Module information */
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("s3c24xx I2S SoC Interface");
diff --git a/sound/soc/s3c24xx/s3c24xx-pcm.c b/sound/soc/s3c24xx/s3c24xx-pcm.c
index ea5a9caec13e..e13e614bada9 100644
--- a/sound/soc/s3c24xx/s3c24xx-pcm.c
+++ b/sound/soc/s3c24xx/s3c24xx-pcm.c
@@ -465,18 +465,6 @@ struct snd_soc_platform s3c24xx_soc_platform = {
};
EXPORT_SYMBOL_GPL(s3c24xx_soc_platform);
-static int __devinit s3c24xx_soc_platform_init(void)
-{
- return snd_soc_register_platform(&s3c24xx_soc_platform);
-}
-module_init(s3c24xx_soc_platform_init);
-
-static void __exit s3c24xx_soc_platform_exit(void)
-{
- snd_soc_unregister_platform(&s3c24xx_soc_platform);
-}
-module_exit(s3c24xx_soc_platform_exit);
-
MODULE_AUTHOR("Ben Dooks, <ben@simtec.co.uk>");
MODULE_DESCRIPTION("Samsung S3C24XX PCM DMA module");
MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/s3c24xx_uda134x.c b/sound/soc/s3c24xx/s3c24xx_uda134x.c
deleted file mode 100644
index a0a4d1832a14..000000000000
--- a/sound/soc/s3c24xx/s3c24xx_uda134x.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/*
- * Modifications by Christian Pellegrin <chripell@evolware.org>
- *
- * s3c24xx_uda134x.c -- S3C24XX_UDA134X ALSA SoC Audio board driver
- *
- * Copyright 2007 Dension Audio Systems Ltd.
- * Author: Zoltan Devai
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <linux/mutex.h>
-#include <linux/gpio.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/soc.h>
-#include <sound/soc-dapm.h>
-#include <sound/s3c24xx_uda134x.h>
-#include <sound/uda134x.h>
-
-#include <asm/plat-s3c24xx/regs-iis.h>
-
-#include "s3c24xx-pcm.h"
-#include "s3c24xx-i2s.h"
-#include "../codecs/uda134x.h"
-
-
-/* #define ENFORCE_RATES 1 */
-/*
- Unfortunately the S3C24XX in master mode has a limited capacity of
- generating the clock for the codec. If you define this only rates
- that are really available will be enforced. But be careful, most
- user level application just want the usual sampling frequencies (8,
- 11.025, 22.050, 44.1 kHz) and anyway resampling is a costly
- operation for embedded systems. So if you aren't very lucky or your
- hardware engineer wasn't very forward-looking it's better to leave
- this undefined. If you do so an approximate value for the requested
- sampling rate in the range -/+ 5% will be chosen. If this in not
- possible an error will be returned.
-*/
-
-static struct clk *xtal;
-static struct clk *pclk;
-/* this is need because we don't have a place where to keep the
- * pointers to the clocks in each substream. We get the clocks only
- * when we are actually using them so we don't block stuff like
- * frequency change or oscillator power-off */
-static int clk_users;
-static DEFINE_MUTEX(clk_lock);
-
-static unsigned int rates[33 * 2];
-#ifdef ENFORCE_RATES
-static struct snd_pcm_hw_constraint_list hw_constraints_rates = {
- .count = ARRAY_SIZE(rates),
- .list = rates,
- .mask = 0,
-};
-#endif
-
-static struct platform_device *s3c24xx_uda134x_snd_device;
-
-static int s3c24xx_uda134x_startup(struct snd_pcm_substream *substream)
-{
- int ret = 0;
-#ifdef ENFORCE_RATES
- struct snd_pcm_runtime *runtime = substream->runtime;;
-#endif
-
- mutex_lock(&clk_lock);
- pr_debug("%s %d\n", __func__, clk_users);
- if (clk_users == 0) {
- xtal = clk_get(&s3c24xx_uda134x_snd_device->dev, "xtal");
- if (!xtal) {
- printk(KERN_ERR "%s cannot get xtal\n", __func__);
- ret = -EBUSY;
- } else {
- pclk = clk_get(&s3c24xx_uda134x_snd_device->dev,
- "pclk");
- if (!pclk) {
- printk(KERN_ERR "%s cannot get pclk\n",
- __func__);
- clk_put(xtal);
- ret = -EBUSY;
- }
- }
- if (!ret) {
- int i, j;
-
- for (i = 0; i < 2; i++) {
- int fs = i ? 256 : 384;
-
- rates[i*33] = clk_get_rate(xtal) / fs;
- for (j = 1; j < 33; j++)
- rates[i*33 + j] = clk_get_rate(pclk) /
- (j * fs);
- }
- }
- }
- clk_users += 1;
- mutex_unlock(&clk_lock);
- if (!ret) {
-#ifdef ENFORCE_RATES
- ret = snd_pcm_hw_constraint_list(runtime, 0,
- SNDRV_PCM_HW_PARAM_RATE,
- &hw_constraints_rates);
- if (ret < 0)
- printk(KERN_ERR "%s cannot set constraints\n",
- __func__);
-#endif
- }
- return ret;
-}
-
-static void s3c24xx_uda134x_shutdown(struct snd_pcm_substream *substream)
-{
- mutex_lock(&clk_lock);
- pr_debug("%s %d\n", __func__, clk_users);
- clk_users -= 1;
- if (clk_users == 0) {
- clk_put(xtal);
- xtal = NULL;
- clk_put(pclk);
- pclk = NULL;
- }
- mutex_unlock(&clk_lock);
-}
-
-static int s3c24xx_uda134x_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params)
-{
- struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
- struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai;
- unsigned int clk = 0;
- int ret = 0;
- int clk_source, fs_mode;
- unsigned long rate = params_rate(params);
- long err, cerr;
- unsigned int div;
- int i, bi;
-
- err = 999999;
- bi = 0;
- for (i = 0; i < 2*33; i++) {
- cerr = rates[i] - rate;
- if (cerr < 0)
- cerr = -cerr;
- if (cerr < err) {
- err = cerr;
- bi = i;
- }
- }
- if (bi / 33 == 1)
- fs_mode = S3C2410_IISMOD_256FS;
- else
- fs_mode = S3C2410_IISMOD_384FS;
- if (bi % 33 == 0) {
- clk_source = S3C24XX_CLKSRC_MPLL;
- div = 1;
- } else {
- clk_source = S3C24XX_CLKSRC_PCLK;
- div = bi % 33;
- }
- pr_debug("%s desired rate %lu, %d\n", __func__, rate, bi);
-
- clk = (fs_mode == S3C2410_IISMOD_384FS ? 384 : 256) * rate;
- pr_debug("%s will use: %s %s %d sysclk %d err %ld\n", __func__,
- fs_mode == S3C2410_IISMOD_384FS ? "384FS" : "256FS",
- clk_source == S3C24XX_CLKSRC_MPLL ? "MPLLin" : "PCLK",
- div, clk, err);
-
- if ((err * 100 / rate) > 5) {
- printk(KERN_ERR "S3C24XX_UDA134X: effective frequency "
- "too different from desired (%ld%%)\n",
- err * 100 / rate);
- return -EINVAL;
- }
-
- ret = snd_soc_dai_set_fmt(codec_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_fmt(cpu_dai, SND_SOC_DAIFMT_I2S |
- SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_sysclk(cpu_dai, clk_source , clk,
- SND_SOC_CLOCK_IN);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_MCLK, fs_mode);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_BCLK,
- S3C2410_IISMOD_32FS);
- if (ret < 0)
- return ret;
-
- ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER,
- S3C24XX_PRESCALE(div, div));
- if (ret < 0)
- return ret;
-
- /* set the codec system clock for DAC and ADC */
- ret = snd_soc_dai_set_sysclk(codec_dai, 0, clk,
- SND_SOC_CLOCK_OUT);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static struct snd_soc_ops s3c24xx_uda134x_ops = {
- .startup = s3c24xx_uda134x_startup,
- .shutdown = s3c24xx_uda134x_shutdown,
- .hw_params = s3c24xx_uda134x_hw_params,
-};
-
-static struct snd_soc_dai_link s3c24xx_uda134x_dai_link = {
- .name = "UDA134X",
- .stream_name = "UDA134X",
- .codec_dai = &uda134x_dai,
- .cpu_dai = &s3c24xx_i2s_dai,
- .ops = &s3c24xx_uda134x_ops,
-};
-
-static struct snd_soc_card snd_soc_s3c24xx_uda134x = {
- .name = "S3C24XX_UDA134X",
- .platform = &s3c24xx_soc_platform,
- .dai_link = &s3c24xx_uda134x_dai_link,
- .num_links = 1,
-};
-
-static struct s3c24xx_uda134x_platform_data *s3c24xx_uda134x_l3_pins;
-
-static void setdat(int v)
-{
- gpio_set_value(s3c24xx_uda134x_l3_pins->l3_data, v > 0);
-}
-
-static void setclk(int v)
-{
- gpio_set_value(s3c24xx_uda134x_l3_pins->l3_clk, v > 0);
-}
-
-static void setmode(int v)
-{
- gpio_set_value(s3c24xx_uda134x_l3_pins->l3_mode, v > 0);
-}
-
-static struct uda134x_platform_data s3c24xx_uda134x = {
- .l3 = {
- .setdat = setdat,
- .setclk = setclk,
- .setmode = setmode,
- .data_hold = 1,
- .data_setup = 1,
- .clock_high = 1,
- .mode_hold = 1,
- .mode = 1,
- .mode_setup = 1,
- },
-};
-
-static struct snd_soc_device s3c24xx_uda134x_snd_devdata = {
- .card = &snd_soc_s3c24xx_uda134x,
- .codec_dev = &soc_codec_dev_uda134x,
- .codec_data = &s3c24xx_uda134x,
-};
-
-static int s3c24xx_uda134x_setup_pin(int pin, char *fun)
-{
- if (gpio_request(pin, "s3c24xx_uda134x") < 0) {
- printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
- "l3 %s pin already in use", fun);
- return -EBUSY;
- }
- gpio_direction_output(pin, 0);
- return 0;
-}
-
-static int s3c24xx_uda134x_probe(struct platform_device *pdev)
-{
- int ret;
-
- printk(KERN_INFO "S3C24XX_UDA134X SoC Audio driver\n");
-
- s3c24xx_uda134x_l3_pins = pdev->dev.platform_data;
- if (s3c24xx_uda134x_l3_pins == NULL) {
- printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
- "unable to find platform data\n");
- return -ENODEV;
- }
- s3c24xx_uda134x.power = s3c24xx_uda134x_l3_pins->power;
- s3c24xx_uda134x.model = s3c24xx_uda134x_l3_pins->model;
-
- if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_data,
- "data") < 0)
- return -EBUSY;
- if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_clk,
- "clk") < 0) {
- gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
- return -EBUSY;
- }
- if (s3c24xx_uda134x_setup_pin(s3c24xx_uda134x_l3_pins->l3_mode,
- "mode") < 0) {
- gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
- gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
- return -EBUSY;
- }
-
- s3c24xx_uda134x_snd_device = platform_device_alloc("soc-audio", -1);
- if (!s3c24xx_uda134x_snd_device) {
- printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: "
- "Unable to register\n");
- return -ENOMEM;
- }
-
- platform_set_drvdata(s3c24xx_uda134x_snd_device,
- &s3c24xx_uda134x_snd_devdata);
- s3c24xx_uda134x_snd_devdata.dev = &s3c24xx_uda134x_snd_device->dev;
- ret = platform_device_add(s3c24xx_uda134x_snd_device);
- if (ret) {
- printk(KERN_ERR "S3C24XX_UDA134X SoC Audio: Unable to add\n");
- platform_device_put(s3c24xx_uda134x_snd_device);
- }
-
- return ret;
-}
-
-static int s3c24xx_uda134x_remove(struct platform_device *pdev)
-{
- platform_device_unregister(s3c24xx_uda134x_snd_device);
- gpio_free(s3c24xx_uda134x_l3_pins->l3_data);
- gpio_free(s3c24xx_uda134x_l3_pins->l3_clk);
- gpio_free(s3c24xx_uda134x_l3_pins->l3_mode);
- return 0;
-}
-
-static struct platform_driver s3c24xx_uda134x_driver = {
- .probe = s3c24xx_uda134x_probe,
- .remove = s3c24xx_uda134x_remove,
- .driver = {
- .name = "s3c24xx_uda134x",
- .owner = THIS_MODULE,
- },
-};
-
-static int __init s3c24xx_uda134x_init(void)
-{
- return platform_driver_register(&s3c24xx_uda134x_driver);
-}
-
-static void __exit s3c24xx_uda134x_exit(void)
-{
- platform_driver_unregister(&s3c24xx_uda134x_driver);
-}
-
-
-module_init(s3c24xx_uda134x_init);
-module_exit(s3c24xx_uda134x_exit);
-
-MODULE_AUTHOR("Zoltan Devai, Christian Pellegrin <chripell@evolware.org>");
-MODULE_DESCRIPTION("S3C24XX_UDA134X ALSA SoC audio driver");
-MODULE_LICENSE("GPL");
diff --git a/sound/soc/s3c24xx/smdk2443_wm9710.c b/sound/soc/s3c24xx/smdk2443_wm9710.c
index a2a4f5323c17..8515d6ff03f2 100644
--- a/sound/soc/s3c24xx/smdk2443_wm9710.c
+++ b/sound/soc/s3c24xx/smdk2443_wm9710.c
@@ -23,7 +23,7 @@
#include "s3c24xx-pcm.h"
#include "s3c24xx-ac97.h"
-static struct snd_soc_card smdk2443;
+static struct snd_soc_machine smdk2443;
static struct snd_soc_dai_link smdk2443_dai[] = {
{
@@ -34,15 +34,15 @@ static struct snd_soc_dai_link smdk2443_dai[] = {
},
};
-static struct snd_soc_card smdk2443 = {
+static struct snd_soc_machine smdk2443 = {
.name = "SMDK2443",
- .platform = &s3c24xx_soc_platform,
.dai_link = smdk2443_dai,
.num_links = ARRAY_SIZE(smdk2443_dai),
};
static struct snd_soc_device smdk2443_snd_ac97_devdata = {
- .card = &smdk2443,
+ .machine = &smdk2443,
+ .platform = &s3c24xx_soc_platform,
.codec_dev = &soc_codec_dev_ac97,
};
diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c
index 39ffca0933a2..9faa12622d09 100644
--- a/sound/soc/sh/dma-sh7760.c
+++ b/sound/soc/sh/dma-sh7760.c
@@ -348,18 +348,6 @@ struct snd_soc_platform sh7760_soc_platform = {
};
EXPORT_SYMBOL_GPL(sh7760_soc_platform);
-static int __devinit sh7760_soc_platform_init(void)
-{
- return snd_soc_register_platform(&sh7760_soc_platform);
-}
-module_init(sh7760_soc_platform_init);
-
-static void __exit sh7760_soc_platform_exit(void)
-{
- snd_soc_unregister_platform(&sh7760_soc_platform);
-}
-module_exit(sh7760_soc_platform_exit);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SH7760 Audio DMA (DMABRG) driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c
index 9169bad1acfb..df7bc345c320 100644
--- a/sound/soc/sh/hac.c
+++ b/sound/soc/sh/hac.c
@@ -236,8 +236,7 @@ struct snd_ac97_bus_ops soc_ac97_ops = {
EXPORT_SYMBOL_GPL(soc_ac97_ops);
static int hac_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct hac_priv *hac = &hac_cpu_data[rtd->dai->cpu_dai->id];
@@ -271,7 +270,7 @@ struct snd_soc_dai sh4_hac_dai[] = {
{
.name = "HAC0",
.id = 0,
- .ac97_control = 1,
+ .type = SND_SOC_DAI_AC97,
.playback = {
.rates = AC97_RATES,
.formats = AC97_FMTS,
@@ -291,8 +290,8 @@ struct snd_soc_dai sh4_hac_dai[] = {
#ifdef CONFIG_CPU_SUBTYPE_SH7760
{
.name = "HAC1",
- .ac97_control = 1,
.id = 1,
+ .type = SND_SOC_DAI_AC97,
.playback = {
.rates = AC97_RATES,
.formats = AC97_FMTS,
@@ -314,18 +313,6 @@ struct snd_soc_dai sh4_hac_dai[] = {
};
EXPORT_SYMBOL_GPL(sh4_hac_dai);
-static int __devinit sh4_hac_init(void)
-{
- return snd_soc_register_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
-}
-module_init(sh4_hac_init);
-
-static void __exit sh4_hac_exit(void)
-{
- snd_soc_unregister_dais(sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai));
-}
-module_exit(sh4_hac_exit);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SuperH onchip HAC (AC97) audio driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/sh/sh7760-ac97.c b/sound/soc/sh/sh7760-ac97.c
index ce7f95b59de3..92bfaf4774a7 100644
--- a/sound/soc/sh/sh7760-ac97.c
+++ b/sound/soc/sh/sh7760-ac97.c
@@ -38,15 +38,15 @@ static struct snd_soc_dai_link sh7760_ac97_dai = {
.ops = NULL,
};
-static struct snd_soc_card sh7760_ac97_soc_machine = {
+static struct snd_soc_machine sh7760_ac97_soc_machine = {
.name = "SH7760 AC97",
- .platform = &sh7760_soc_platform,
.dai_link = &sh7760_ac97_dai,
.num_links = 1,
};
static struct snd_soc_device sh7760_ac97_snd_devdata = {
- .card = &sh7760_ac97_soc_machine,
+ .machine = &sh7760_ac97_soc_machine,
+ .platform = &sh7760_soc_platform,
.codec_dev = &soc_codec_dev_ac97,
};
diff --git a/sound/soc/sh/ssi.c b/sound/soc/sh/ssi.c
index 9093588d4d07..55c3464163ab 100644
--- a/sound/soc/sh/ssi.c
+++ b/sound/soc/sh/ssi.c
@@ -89,8 +89,7 @@ struct ssi_priv {
* track usage of the SSI; it is simplex-only so prevent attempts of
* concurrent playback + capture. FIXME: any locking required?
*/
-static int ssi_startup(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static int ssi_startup(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -102,8 +101,7 @@ static int ssi_startup(struct snd_pcm_substream *substream,
return 0;
}
-static void ssi_shutdown(struct snd_pcm_substream *substream,
- struct snd_soc_dai *dai)
+static void ssi_shutdown(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -111,8 +109,7 @@ static void ssi_shutdown(struct snd_pcm_substream *substream,
ssi->inuse = 0;
}
-static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
- struct snd_soc_dai *dai)
+static int ssi_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -132,8 +129,7 @@ static int ssi_trigger(struct snd_pcm_substream *substream, int cmd,
}
static int ssi_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_dai *dai)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct ssi_priv *ssi = &ssi_cpu_data[rtd->dai->cpu_dai->id];
@@ -340,6 +336,7 @@ struct snd_soc_dai sh4_ssi_dai[] = {
{
.name = "SSI0",
.id = 0,
+ .type = SND_SOC_DAI_I2S,
.playback = {
.rates = SSI_RATES,
.formats = SSI_FMTS,
@@ -357,6 +354,8 @@ struct snd_soc_dai sh4_ssi_dai[] = {
.shutdown = ssi_shutdown,
.trigger = ssi_trigger,
.hw_params = ssi_hw_params,
+ },
+ .dai_ops = {
.set_sysclk = ssi_set_sysclk,
.set_clkdiv = ssi_set_clkdiv,
.set_fmt = ssi_set_fmt,
@@ -366,6 +365,7 @@ struct snd_soc_dai sh4_ssi_dai[] = {
{
.name = "SSI1",
.id = 1,
+ .type = SND_SOC_DAI_I2S,
.playback = {
.rates = SSI_RATES,
.formats = SSI_FMTS,
@@ -383,6 +383,8 @@ struct snd_soc_dai sh4_ssi_dai[] = {
.shutdown = ssi_shutdown,
.trigger = ssi_trigger,
.hw_params = ssi_hw_params,
+ },
+ .dai_ops = {
.set_sysclk = ssi_set_sysclk,
.set_clkdiv = ssi_set_clkdiv,
.set_fmt = ssi_set_fmt,
@@ -392,18 +394,6 @@ struct snd_soc_dai sh4_ssi_dai[] = {
};
EXPORT_SYMBOL_GPL(sh4_ssi_dai);
-static int __devinit sh4_ssi_init(void)
-{
- return snd_soc_register_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
-}
-module_init(sh4_ssi_init);
-
-static void __exit sh4_ssi_exit(void)
-{
- snd_soc_unregister_dais(sh4_ssi_dai, ARRAY_SIZE(sh4_ssi_dai));
-}
-module_exit(sh4_ssi_exit);
-
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("SuperH onchip SSI (I2S) audio driver");
MODULE_AUTHOR("Manuel Lauss <mano@roarinelk.homelinux.net>");
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 76a89eb65baf..16c7453f4946 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -26,7 +26,6 @@
#include <linux/delay.h>
#include <linux/pm.h>
#include <linux/bitops.h>
-#include <linux/debugfs.h>
#include <linux/platform_device.h>
#include <sound/core.h>
#include <sound/pcm.h>
@@ -35,22 +34,18 @@
#include <sound/soc-dapm.h>
#include <sound/initval.h>
+/* debug */
+#define SOC_DEBUG 0
+#if SOC_DEBUG
+#define dbg(format, arg...) printk(format, ## arg)
+#else
+#define dbg(format, arg...)
+#endif
+
static DEFINE_MUTEX(pcm_mutex);
static DEFINE_MUTEX(io_mutex);
static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq);
-#ifdef CONFIG_DEBUG_FS
-static struct dentry *debugfs_root;
-#endif
-
-static DEFINE_MUTEX(client_mutex);
-static LIST_HEAD(card_list);
-static LIST_HEAD(dai_list);
-static LIST_HEAD(platform_list);
-
-static int snd_soc_register_card(struct snd_soc_card *card);
-static int snd_soc_unregister_card(struct snd_soc_card *card);
-
/*
* This is a timeout to do a DAPM powerdown after a stream is closed().
* It can be used to eliminate pops between different playback streams, e.g.
@@ -112,6 +107,20 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec)
}
#endif
+static inline const char *get_dai_name(int type)
+{
+ switch (type) {
+ case SND_SOC_DAI_AC97_BUS:
+ case SND_SOC_DAI_AC97:
+ return "AC97";
+ case SND_SOC_DAI_I2S:
+ return "I2S";
+ case SND_SOC_DAI_PCM:
+ return "PCM";
+ }
+ return NULL;
+}
+
/*
* Called by ALSA when a PCM substream is opened, the runtime->hw record is
* then initialized and any private data can be allocated. This also calls
@@ -121,10 +130,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_card *card = socdev->card;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = card->platform;
+ struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
int ret = 0;
@@ -133,7 +141,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
/* startup the audio subsystem */
if (cpu_dai->ops.startup) {
- ret = cpu_dai->ops.startup(substream, cpu_dai);
+ ret = cpu_dai->ops.startup(substream);
if (ret < 0) {
printk(KERN_ERR "asoc: can't open interface %s\n",
cpu_dai->name);
@@ -150,7 +158,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
}
if (codec_dai->ops.startup) {
- ret = codec_dai->ops.startup(substream, codec_dai);
+ ret = codec_dai->ops.startup(substream);
if (ret < 0) {
printk(KERN_ERR "asoc: can't open codec %s\n",
codec_dai->name);
@@ -220,12 +228,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
goto machine_err;
}
- pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
- pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates);
- pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
- runtime->hw.channels_max);
- pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
- runtime->hw.rate_max);
+ dbg("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name);
+ dbg("asoc: rate mask 0x%x\n", runtime->hw.rates);
+ dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min,
+ runtime->hw.channels_max);
+ dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min,
+ runtime->hw.rate_max);
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
cpu_dai->playback.active = codec_dai->playback.active = 1;
@@ -247,7 +255,7 @@ codec_dai_err:
platform_err:
if (cpu_dai->ops.shutdown)
- cpu_dai->ops.shutdown(substream, cpu_dai);
+ cpu_dai->ops.shutdown(substream);
out:
mutex_unlock(&pcm_mutex);
return ret;
@@ -260,9 +268,8 @@ out:
*/
static void close_delayed_work(struct work_struct *work)
{
- struct snd_soc_card *card = container_of(work, struct snd_soc_card,
- delayed_work.work);
- struct snd_soc_device *socdev = card->socdev;
+ struct snd_soc_device *socdev =
+ container_of(work, struct snd_soc_device, delayed_work.work);
struct snd_soc_codec *codec = socdev->codec;
struct snd_soc_dai *codec_dai;
int i;
@@ -271,18 +278,18 @@ static void close_delayed_work(struct work_struct *work)
for (i = 0; i < codec->num_dai; i++) {
codec_dai = &codec->dai[i];
- pr_debug("pop wq checking: %s status: %s waiting: %s\n",
- codec_dai->playback.stream_name,
- codec_dai->playback.active ? "active" : "inactive",
- codec_dai->pop_wait ? "yes" : "no");
+ dbg("pop wq checking: %s status: %s waiting: %s\n",
+ codec_dai->playback.stream_name,
+ codec_dai->playback.active ? "active" : "inactive",
+ codec_dai->pop_wait ? "yes" : "no");
/* are we waiting on this codec DAI stream */
if (codec_dai->pop_wait == 1) {
/* Reduce power if no longer active */
if (codec->active == 0) {
- pr_debug("pop wq D1 %s %s\n", codec->name,
- codec_dai->playback.stream_name);
+ dbg("pop wq D1 %s %s\n", codec->name,
+ codec_dai->playback.stream_name);
snd_soc_dapm_set_bias_level(socdev,
SND_SOC_BIAS_PREPARE);
}
@@ -294,8 +301,8 @@ static void close_delayed_work(struct work_struct *work)
/* Fall into standby if no longer active */
if (codec->active == 0) {
- pr_debug("pop wq D3 %s %s\n", codec->name,
- codec_dai->playback.stream_name);
+ dbg("pop wq D3 %s %s\n", codec->name,
+ codec_dai->playback.stream_name);
snd_soc_dapm_set_bias_level(socdev,
SND_SOC_BIAS_STANDBY);
}
@@ -313,9 +320,8 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_card *card = socdev->card;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = card->platform;
+ struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->codec;
@@ -340,10 +346,10 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
snd_soc_dai_digital_mute(codec_dai, 1);
if (cpu_dai->ops.shutdown)
- cpu_dai->ops.shutdown(substream, cpu_dai);
+ cpu_dai->ops.shutdown(substream);
if (codec_dai->ops.shutdown)
- codec_dai->ops.shutdown(substream, codec_dai);
+ codec_dai->ops.shutdown(substream);
if (machine->ops && machine->ops->shutdown)
machine->ops->shutdown(substream);
@@ -355,7 +361,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream)
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
/* start delayed pop wq here for playback streams */
codec_dai->pop_wait = 1;
- schedule_delayed_work(&card->delayed_work,
+ schedule_delayed_work(&socdev->delayed_work,
msecs_to_jiffies(pmdown_time));
} else {
/* capture streams can be powered down now */
@@ -381,9 +387,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_card *card = socdev->card;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = card->platform;
+ struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->codec;
@@ -408,7 +413,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
if (codec_dai->ops.prepare) {
- ret = codec_dai->ops.prepare(substream, codec_dai);
+ ret = codec_dai->ops.prepare(substream);
if (ret < 0) {
printk(KERN_ERR "asoc: codec DAI prepare error\n");
goto out;
@@ -416,49 +421,58 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
if (cpu_dai->ops.prepare) {
- ret = cpu_dai->ops.prepare(substream, cpu_dai);
+ ret = cpu_dai->ops.prepare(substream);
if (ret < 0) {
printk(KERN_ERR "asoc: cpu DAI prepare error\n");
goto out;
}
}
- /* cancel any delayed stream shutdown that is pending */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK &&
- codec_dai->pop_wait) {
- codec_dai->pop_wait = 0;
- cancel_delayed_work(&card->delayed_work);
- }
+ /* we only want to start a DAPM playback stream if we are not waiting
+ * on an existing one stopping */
+ if (codec_dai->pop_wait) {
+ /* we are waiting for the delayed work to start */
+ if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
+ snd_soc_dapm_stream_event(socdev->codec,
+ codec_dai->capture.stream_name,
+ SND_SOC_DAPM_STREAM_START);
+ else {
+ codec_dai->pop_wait = 0;
+ cancel_delayed_work(&socdev->delayed_work);
+ snd_soc_dai_digital_mute(codec_dai, 0);
+ }
+ } else {
+ /* no delayed work - do we need to power up codec */
+ if (codec->bias_level != SND_SOC_BIAS_ON) {
- /* do we need to power up codec */
- if (codec->bias_level != SND_SOC_BIAS_ON) {
- snd_soc_dapm_set_bias_level(socdev,
- SND_SOC_BIAS_PREPARE);
+ snd_soc_dapm_set_bias_level(socdev,
+ SND_SOC_BIAS_PREPARE);
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(codec,
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dapm_stream_event(codec,
codec_dai->playback.stream_name,
SND_SOC_DAPM_STREAM_START);
- else
- snd_soc_dapm_stream_event(codec,
+ else
+ snd_soc_dapm_stream_event(codec,
codec_dai->capture.stream_name,
SND_SOC_DAPM_STREAM_START);
- snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
- snd_soc_dai_digital_mute(codec_dai, 0);
+ snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON);
+ snd_soc_dai_digital_mute(codec_dai, 0);
- } else {
- /* codec already powered - power on widgets */
- if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
- snd_soc_dapm_stream_event(codec,
+ } else {
+ /* codec already powered - power on widgets */
+ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
+ snd_soc_dapm_stream_event(codec,
codec_dai->playback.stream_name,
SND_SOC_DAPM_STREAM_START);
- else
- snd_soc_dapm_stream_event(codec,
+ else
+ snd_soc_dapm_stream_event(codec,
codec_dai->capture.stream_name,
SND_SOC_DAPM_STREAM_START);
- snd_soc_dai_digital_mute(codec_dai, 0);
+ snd_soc_dai_digital_mute(codec_dai, 0);
+ }
}
out:
@@ -477,8 +491,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_platform *platform = card->platform;
+ struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
int ret = 0;
@@ -494,7 +507,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
if (codec_dai->ops.hw_params) {
- ret = codec_dai->ops.hw_params(substream, params, codec_dai);
+ ret = codec_dai->ops.hw_params(substream, params);
if (ret < 0) {
printk(KERN_ERR "asoc: can't set codec %s hw params\n",
codec_dai->name);
@@ -503,7 +516,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
}
if (cpu_dai->ops.hw_params) {
- ret = cpu_dai->ops.hw_params(substream, params, cpu_dai);
+ ret = cpu_dai->ops.hw_params(substream, params);
if (ret < 0) {
printk(KERN_ERR "asoc: interface %s hw params failed\n",
cpu_dai->name);
@@ -526,11 +539,11 @@ out:
platform_err:
if (cpu_dai->ops.hw_free)
- cpu_dai->ops.hw_free(substream, cpu_dai);
+ cpu_dai->ops.hw_free(substream);
interface_err:
if (codec_dai->ops.hw_free)
- codec_dai->ops.hw_free(substream, codec_dai);
+ codec_dai->ops.hw_free(substream);
codec_err:
if (machine->ops && machine->ops->hw_free)
@@ -548,8 +561,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_platform *platform = card->platform;
+ struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
struct snd_soc_codec *codec = socdev->codec;
@@ -570,10 +582,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
/* now free hw params for the DAI's */
if (codec_dai->ops.hw_free)
- codec_dai->ops.hw_free(substream, codec_dai);
+ codec_dai->ops.hw_free(substream);
if (cpu_dai->ops.hw_free)
- cpu_dai->ops.hw_free(substream, cpu_dai);
+ cpu_dai->ops.hw_free(substream);
mutex_unlock(&pcm_mutex);
return 0;
@@ -583,15 +595,14 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_device *socdev = rtd->socdev;
- struct snd_soc_card *card= socdev->card;
struct snd_soc_dai_link *machine = rtd->dai;
- struct snd_soc_platform *platform = card->platform;
+ struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_dai *cpu_dai = machine->cpu_dai;
struct snd_soc_dai *codec_dai = machine->codec_dai;
int ret;
if (codec_dai->ops.trigger) {
- ret = codec_dai->ops.trigger(substream, cmd, codec_dai);
+ ret = codec_dai->ops.trigger(substream, cmd);
if (ret < 0)
return ret;
}
@@ -603,7 +614,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
}
if (cpu_dai->ops.trigger) {
- ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai);
+ ret = cpu_dai->ops.trigger(substream, cmd);
if (ret < 0)
return ret;
}
@@ -625,8 +636,8 @@ static struct snd_pcm_ops soc_pcm_ops = {
static int soc_suspend(struct platform_device *pdev, pm_message_t state)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_platform *platform = card->platform;
+ struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
struct snd_soc_codec *codec = socdev->codec;
int i;
@@ -642,29 +653,29 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot);
/* mute any active DAC's */
- for (i = 0; i < card->num_links; i++) {
- struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
- if (dai->ops.digital_mute && dai->playback.active)
- dai->ops.digital_mute(dai, 1);
+ for (i = 0; i < machine->num_links; i++) {
+ struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
+ if (dai->dai_ops.digital_mute && dai->playback.active)
+ dai->dai_ops.digital_mute(dai, 1);
}
/* suspend all pcms */
- for (i = 0; i < card->num_links; i++)
- snd_pcm_suspend_all(card->dai_link[i].pcm);
+ for (i = 0; i < machine->num_links; i++)
+ snd_pcm_suspend_all(machine->dai_link[i].pcm);
- if (card->suspend_pre)
- card->suspend_pre(pdev, state);
+ if (machine->suspend_pre)
+ machine->suspend_pre(pdev, state);
- for (i = 0; i < card->num_links; i++) {
- struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
- if (cpu_dai->suspend && !cpu_dai->ac97_control)
- cpu_dai->suspend(cpu_dai);
+ for (i = 0; i < machine->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97)
+ cpu_dai->suspend(pdev, cpu_dai);
if (platform->suspend)
- platform->suspend(cpu_dai);
+ platform->suspend(pdev, cpu_dai);
}
/* close any waiting streams and save state */
- run_delayed_work(&card->delayed_work);
+ run_delayed_work(&socdev->delayed_work);
codec->suspend_bias_level = codec->bias_level;
for (i = 0; i < codec->num_dai; i++) {
@@ -681,14 +692,14 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
if (codec_dev->suspend)
codec_dev->suspend(pdev, state);
- for (i = 0; i < card->num_links; i++) {
- struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
- if (cpu_dai->suspend && cpu_dai->ac97_control)
- cpu_dai->suspend(cpu_dai);
+ for (i = 0; i < machine->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97)
+ cpu_dai->suspend(pdev, cpu_dai);
}
- if (card->suspend_post)
- card->suspend_post(pdev, state);
+ if (machine->suspend_post)
+ machine->suspend_post(pdev, state);
return 0;
}
@@ -698,11 +709,11 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state)
*/
static void soc_resume_deferred(struct work_struct *work)
{
- struct snd_soc_card *card = container_of(work,
- struct snd_soc_card,
- deferred_resume_work);
- struct snd_soc_device *socdev = card->socdev;
- struct snd_soc_platform *platform = card->platform;
+ struct snd_soc_device *socdev = container_of(work,
+ struct snd_soc_device,
+ deferred_resume_work);
+ struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
struct snd_soc_codec *codec = socdev->codec;
struct platform_device *pdev = to_platform_device(socdev->dev);
@@ -712,15 +723,15 @@ static void soc_resume_deferred(struct work_struct *work)
* so userspace apps are blocked from touching us
*/
- dev_dbg(socdev->dev, "starting resume work\n");
+ dev_info(socdev->dev, "starting resume work\n");
- if (card->resume_pre)
- card->resume_pre(pdev);
+ if (machine->resume_pre)
+ machine->resume_pre(pdev);
- for (i = 0; i < card->num_links; i++) {
- struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
- if (cpu_dai->resume && cpu_dai->ac97_control)
- cpu_dai->resume(cpu_dai);
+ for (i = 0; i < machine->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97)
+ cpu_dai->resume(pdev, cpu_dai);
}
if (codec_dev->resume)
@@ -738,24 +749,24 @@ static void soc_resume_deferred(struct work_struct *work)
}
/* unmute any active DACs */
- for (i = 0; i < card->num_links; i++) {
- struct snd_soc_dai *dai = card->dai_link[i].codec_dai;
- if (dai->ops.digital_mute && dai->playback.active)
- dai->ops.digital_mute(dai, 0);
+ for (i = 0; i < machine->num_links; i++) {
+ struct snd_soc_dai *dai = machine->dai_link[i].codec_dai;
+ if (dai->dai_ops.digital_mute && dai->playback.active)
+ dai->dai_ops.digital_mute(dai, 0);
}
- for (i = 0; i < card->num_links; i++) {
- struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
- if (cpu_dai->resume && !cpu_dai->ac97_control)
- cpu_dai->resume(cpu_dai);
+ for (i = 0; i < machine->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
+ if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97)
+ cpu_dai->resume(pdev, cpu_dai);
if (platform->resume)
- platform->resume(cpu_dai);
+ platform->resume(pdev, cpu_dai);
}
- if (card->resume_post)
- card->resume_post(pdev);
+ if (machine->resume_post)
+ machine->resume_post(pdev);
- dev_dbg(socdev->dev, "resume work completed\n");
+ dev_info(socdev->dev, "resume work completed\n");
/* userspace can access us now we are back as we were before */
snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0);
@@ -765,12 +776,11 @@ static void soc_resume_deferred(struct work_struct *work)
static int soc_resume(struct platform_device *pdev)
{
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_card *card = socdev->card;
- dev_dbg(socdev->dev, "scheduling resume work\n");
+ dev_info(socdev->dev, "scheduling resume work\n");
- if (!schedule_work(&card->deferred_resume_work))
- dev_err(socdev->dev, "resume work item may be lost\n");
+ if (!schedule_work(&socdev->deferred_resume_work))
+ dev_err(socdev->dev, "work item may be lost\n");
return 0;
}
@@ -780,83 +790,23 @@ static int soc_resume(struct platform_device *pdev)
#define soc_resume NULL
#endif
-static void snd_soc_instantiate_card(struct snd_soc_card *card)
+/* probes a new socdev */
+static int soc_probe(struct platform_device *pdev)
{
- struct platform_device *pdev = container_of(card->dev,
- struct platform_device,
- dev);
- struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev;
- struct snd_soc_platform *platform;
- struct snd_soc_dai *dai;
- int i, found, ret, ac97;
-
- if (card->instantiated)
- return;
-
- found = 0;
- list_for_each_entry(platform, &platform_list, list)
- if (card->platform == platform) {
- found = 1;
- break;
- }
- if (!found) {
- dev_dbg(card->dev, "Platform %s not registered\n",
- card->platform->name);
- return;
- }
-
- ac97 = 0;
- for (i = 0; i < card->num_links; i++) {
- found = 0;
- list_for_each_entry(dai, &dai_list, list)
- if (card->dai_link[i].cpu_dai == dai) {
- found = 1;
- break;
- }
- if (!found) {
- dev_dbg(card->dev, "DAI %s not registered\n",
- card->dai_link[i].cpu_dai->name);
- return;
- }
-
- if (card->dai_link[i].cpu_dai->ac97_control)
- ac97 = 1;
- }
-
- /* If we have AC97 in the system then don't wait for the
- * codec. This will need revisiting if we have to handle
- * systems with mixed AC97 and non-AC97 parts. Only check for
- * DAIs currently; we can't do this per link since some AC97
- * codecs have non-AC97 DAIs.
- */
- if (!ac97)
- for (i = 0; i < card->num_links; i++) {
- found = 0;
- list_for_each_entry(dai, &dai_list, list)
- if (card->dai_link[i].codec_dai == dai) {
- found = 1;
- break;
- }
- if (!found) {
- dev_dbg(card->dev, "DAI %s not registered\n",
- card->dai_link[i].codec_dai->name);
- return;
- }
- }
-
- /* Note that we do not current check for codec components */
-
- dev_dbg(card->dev, "All components present, instantiating\n");
+ int ret = 0, i;
+ struct snd_soc_device *socdev = platform_get_drvdata(pdev);
+ struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_platform *platform = socdev->platform;
+ struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
- /* Found everything, bring it up */
- if (card->probe) {
- ret = card->probe(pdev);
+ if (machine->probe) {
+ ret = machine->probe(pdev);
if (ret < 0)
- return;
+ return ret;
}
- for (i = 0; i < card->num_links; i++) {
- struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ for (i = 0; i < machine->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
if (cpu_dai->probe) {
ret = cpu_dai->probe(pdev, cpu_dai);
if (ret < 0)
@@ -877,15 +827,13 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card)
}
/* DAPM stream work */
- INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work);
+ INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work);
#ifdef CONFIG_PM
/* deferred resume work */
- INIT_WORK(&card->deferred_resume_work, soc_resume_deferred);
+ INIT_WORK(&socdev->deferred_resume_work, soc_resume_deferred);
#endif
- card->instantiated = 1;
-
- return;
+ return 0;
platform_err:
if (codec_dev->remove)
@@ -893,45 +841,15 @@ platform_err:
cpu_dai_err:
for (i--; i >= 0; i--) {
- struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
if (cpu_dai->remove)
cpu_dai->remove(pdev, cpu_dai);
}
- if (card->remove)
- card->remove(pdev);
-}
-
-/*
- * Attempt to initialise any uninitalised cards. Must be called with
- * client_mutex.
- */
-static void snd_soc_instantiate_cards(void)
-{
- struct snd_soc_card *card;
- list_for_each_entry(card, &card_list, list)
- snd_soc_instantiate_card(card);
-}
+ if (machine->remove)
+ machine->remove(pdev);
-/* probes a new socdev */
-static int soc_probe(struct platform_device *pdev)
-{
- int ret = 0;
- struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_card *card = socdev->card;
-
- /* Bodge while we push things out of socdev */
- card->socdev = socdev;
-
- /* Bodge while we unpick instantiation */
- card->dev = &pdev->dev;
- ret = snd_soc_register_card(card);
- if (ret != 0) {
- dev_err(&pdev->dev, "Failed to register card\n");
- return ret;
- }
-
- return 0;
+ return ret;
}
/* removes a socdev */
@@ -939,11 +857,11 @@ static int soc_remove(struct platform_device *pdev)
{
int i;
struct snd_soc_device *socdev = platform_get_drvdata(pdev);
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_platform *platform = card->platform;
+ struct snd_soc_machine *machine = socdev->machine;
+ struct snd_soc_platform *platform = socdev->platform;
struct snd_soc_codec_device *codec_dev = socdev->codec_dev;
- run_delayed_work(&card->delayed_work);
+ run_delayed_work(&socdev->delayed_work);
if (platform->remove)
platform->remove(pdev);
@@ -951,16 +869,14 @@ static int soc_remove(struct platform_device *pdev)
if (codec_dev->remove)
codec_dev->remove(pdev);
- for (i = 0; i < card->num_links; i++) {
- struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai;
+ for (i = 0; i < machine->num_links; i++) {
+ struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai;
if (cpu_dai->remove)
cpu_dai->remove(pdev, cpu_dai);
}
- if (card->remove)
- card->remove(pdev);
-
- snd_soc_unregister_card(card);
+ if (machine->remove)
+ machine->remove(pdev);
return 0;
}
@@ -982,8 +898,6 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
struct snd_soc_dai_link *dai_link, int num)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_card *card = socdev->card;
- struct snd_soc_platform *platform = card->platform;
struct snd_soc_dai *codec_dai = dai_link->codec_dai;
struct snd_soc_dai *cpu_dai = dai_link->cpu_dai;
struct snd_soc_pcm_runtime *rtd;
@@ -1000,8 +914,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
codec_dai->codec = socdev->codec;
/* check client and interface hw capabilities */
- sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name,
- num);
+ sprintf(new_name, "%s %s-%s-%d", dai_link->stream_name, codec_dai->name,
+ get_dai_name(cpu_dai->type), num);
if (codec_dai->playback.channels_min)
playback = 1;
@@ -1019,13 +933,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
dai_link->pcm = pcm;
pcm->private_data = rtd;
- soc_pcm_ops.mmap = platform->pcm_ops->mmap;
- soc_pcm_ops.pointer = platform->pcm_ops->pointer;
- soc_pcm_ops.ioctl = platform->pcm_ops->ioctl;
- soc_pcm_ops.copy = platform->pcm_ops->copy;
- soc_pcm_ops.silence = platform->pcm_ops->silence;
- soc_pcm_ops.ack = platform->pcm_ops->ack;
- soc_pcm_ops.page = platform->pcm_ops->page;
+ soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap;
+ soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer;
+ soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl;
+ soc_pcm_ops.copy = socdev->platform->pcm_ops->copy;
+ soc_pcm_ops.silence = socdev->platform->pcm_ops->silence;
+ soc_pcm_ops.ack = socdev->platform->pcm_ops->ack;
+ soc_pcm_ops.page = socdev->platform->pcm_ops->page;
if (playback)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops);
@@ -1033,22 +947,24 @@ static int soc_new_pcm(struct snd_soc_device *socdev,
if (capture)
snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops);
- ret = platform->pcm_new(codec->card, codec_dai, pcm);
+ ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm);
if (ret < 0) {
printk(KERN_ERR "asoc: platform pcm constructor failed\n");
kfree(rtd);
return ret;
}
- pcm->private_free = platform->pcm_free;
+ pcm->private_free = socdev->platform->pcm_free;
printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name,
cpu_dai->name);
return ret;
}
/* codec register dump */
-static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf)
+static ssize_t codec_reg_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
{
+ struct snd_soc_device *devdata = dev_get_drvdata(dev);
struct snd_soc_codec *codec = devdata->codec;
int i, step = 1, count = 0;
@@ -1085,110 +1001,8 @@ static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf)
return count;
}
-static ssize_t codec_reg_show(struct device *dev,
- struct device_attribute *attr, char *buf)
-{
- struct snd_soc_device *devdata = dev_get_drvdata(dev);
- return soc_codec_reg_show(devdata, buf);
-}
-
static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL);
-#ifdef CONFIG_DEBUG_FS
-static int codec_reg_open_file(struct inode *inode, struct file *file)
-{
- file->private_data = inode->i_private;
- return 0;
-}
-
-static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- ssize_t ret;
- struct snd_soc_codec *codec = file->private_data;
- struct device *card_dev = codec->card->dev;
- struct snd_soc_device *devdata = card_dev->driver_data;
- char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
- ret = soc_codec_reg_show(devdata, buf);
- if (ret >= 0)
- ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret);
- kfree(buf);
- return ret;
-}
-
-static ssize_t codec_reg_write_file(struct file *file,
- const char __user *user_buf, size_t count, loff_t *ppos)
-{
- char buf[32];
- int buf_size;
- char *start = buf;
- unsigned long reg, value;
- int step = 1;
- struct snd_soc_codec *codec = file->private_data;
-
- buf_size = min(count, (sizeof(buf)-1));
- if (copy_from_user(buf, user_buf, buf_size))
- return -EFAULT;
- buf[buf_size] = 0;
-
- if (codec->reg_cache_step)
- step = codec->reg_cache_step;
-
- while (*start == ' ')
- start++;
- reg = simple_strtoul(start, &start, 16);
- if ((reg >= codec->reg_cache_size) || (reg % step))
- return -EINVAL;
- while (*start == ' ')
- start++;
- if (strict_strtoul(start, 16, &value))
- return -EINVAL;
- codec->write(codec, reg, value);
- return buf_size;
-}
-
-static const struct file_operations codec_reg_fops = {
- .open = codec_reg_open_file,
- .read = codec_reg_read_file,
- .write = codec_reg_write_file,
-};
-
-static void soc_init_codec_debugfs(struct snd_soc_codec *codec)
-{
- codec->debugfs_reg = debugfs_create_file("codec_reg", 0644,
- debugfs_root, codec,
- &codec_reg_fops);
- if (!codec->debugfs_reg)
- printk(KERN_WARNING
- "ASoC: Failed to create codec register debugfs file\n");
-
- codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744,
- debugfs_root,
- &codec->pop_time);
- if (!codec->debugfs_pop_time)
- printk(KERN_WARNING
- "Failed to create pop time debugfs file\n");
-}
-
-static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
-{
- debugfs_remove(codec->debugfs_pop_time);
- debugfs_remove(codec->debugfs_reg);
-}
-
-#else
-
-static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec)
-{
-}
-
-static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec)
-{
-}
-#endif
-
/**
* snd_soc_new_ac97_codec - initailise AC97 device
* @codec: audio codec
@@ -1307,7 +1121,7 @@ EXPORT_SYMBOL_GPL(snd_soc_test_bits);
int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_card *card = socdev->card;
+ struct snd_soc_machine *machine = socdev->machine;
int ret = 0, i;
mutex_lock(&codec->mutex);
@@ -1326,11 +1140,11 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver));
/* create the pcms */
- for (i = 0; i < card->num_links; i++) {
- ret = soc_new_pcm(socdev, &card->dai_link[i], i);
+ for (i = 0; i < machine->num_links; i++) {
+ ret = soc_new_pcm(socdev, &machine->dai_link[i], i);
if (ret < 0) {
printk(KERN_ERR "asoc: can't create pcm %s\n",
- card->dai_link[i].stream_name);
+ machine->dai_link[i].stream_name);
mutex_unlock(&codec->mutex);
return ret;
}
@@ -1342,7 +1156,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid)
EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
/**
- * snd_soc_init_card - register sound card
+ * snd_soc_register_card - register sound card
* @socdev: the SoC audio device
*
* Register a SoC sound card. Also registers an AC97 device if the
@@ -1350,28 +1164,29 @@ EXPORT_SYMBOL_GPL(snd_soc_new_pcms);
*
* Returns 0 for success, else error.
*/
-int snd_soc_init_card(struct snd_soc_device *socdev)
+int snd_soc_register_card(struct snd_soc_device *socdev)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_card *card = socdev->card;
+ struct snd_soc_machine *machine = socdev->machine;
int ret = 0, i, ac97 = 0, err = 0;
- for (i = 0; i < card->num_links; i++) {
- if (card->dai_link[i].init) {
- err = card->dai_link[i].init(codec);
+ for (i = 0; i < machine->num_links; i++) {
+ if (socdev->machine->dai_link[i].init) {
+ err = socdev->machine->dai_link[i].init(codec);
if (err < 0) {
printk(KERN_ERR "asoc: failed to init %s\n",
- card->dai_link[i].stream_name);
+ socdev->machine->dai_link[i].stream_name);
continue;
}
}
- if (card->dai_link[i].codec_dai->ac97_control)
+ if (socdev->machine->dai_link[i].codec_dai->type ==
+ SND_SOC_DAI_AC97_BUS)
ac97 = 1;
}
snprintf(codec->card->shortname, sizeof(codec->card->shortname),
- "%s", card->name);
+ "%s", machine->name);
snprintf(codec->card->longname, sizeof(codec->card->longname),
- "%s (%s)", card->name, codec->name);
+ "%s (%s)", machine->name, codec->name);
ret = snd_card_register(codec->card);
if (ret < 0) {
@@ -1401,13 +1216,12 @@ int snd_soc_init_card(struct snd_soc_device *socdev)
if (err < 0)
printk(KERN_WARNING "asoc: failed to add codec sysfs files\n");
- soc_init_codec_debugfs(socdev->codec);
mutex_unlock(&codec->mutex);
out:
return ret;
}
-EXPORT_SYMBOL_GPL(snd_soc_init_card);
+EXPORT_SYMBOL_GPL(snd_soc_register_card);
/**
* snd_soc_free_pcms - free sound card and pcms
@@ -1425,11 +1239,10 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev)
#endif
mutex_lock(&codec->mutex);
- soc_cleanup_codec_debugfs(socdev->codec);
#ifdef CONFIG_SND_SOC_AC97_BUS
for (i = 0; i < codec->num_dai; i++) {
codec_dai = &codec->dai[i];
- if (codec_dai->ac97_control && codec->ac97) {
+ if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) {
soc_ac97_dev_unregister(codec);
goto free_card;
}
@@ -1943,8 +1756,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8);
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
- if (dai->ops.set_sysclk)
- return dai->ops.set_sysclk(dai, clk_id, freq, dir);
+ if (dai->dai_ops.set_sysclk)
+ return dai->dai_ops.set_sysclk(dai, clk_id, freq, dir);
else
return -EINVAL;
}
@@ -1963,8 +1776,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk);
int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
int div_id, int div)
{
- if (dai->ops.set_clkdiv)
- return dai->ops.set_clkdiv(dai, div_id, div);
+ if (dai->dai_ops.set_clkdiv)
+ return dai->dai_ops.set_clkdiv(dai, div_id, div);
else
return -EINVAL;
}
@@ -1982,8 +1795,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
int snd_soc_dai_set_pll(struct snd_soc_dai *dai,
int pll_id, unsigned int freq_in, unsigned int freq_out)
{
- if (dai->ops.set_pll)
- return dai->ops.set_pll(dai, pll_id, freq_in, freq_out);
+ if (dai->dai_ops.set_pll)
+ return dai->dai_ops.set_pll(dai, pll_id, freq_in, freq_out);
else
return -EINVAL;
}
@@ -1992,14 +1805,15 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll);
/**
* snd_soc_dai_set_fmt - configure DAI hardware audio format.
* @dai: DAI
+ * @clk_id: DAI specific clock ID
* @fmt: SND_SOC_DAIFMT_ format value.
*
* Configures the DAI hardware format and clocking.
*/
int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt)
{
- if (dai->ops.set_fmt)
- return dai->ops.set_fmt(dai, fmt);
+ if (dai->dai_ops.set_fmt)
+ return dai->dai_ops.set_fmt(dai, fmt);
else
return -EINVAL;
}
@@ -2017,8 +1831,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt);
int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai,
unsigned int mask, int slots)
{
- if (dai->ops.set_sysclk)
- return dai->ops.set_tdm_slot(dai, mask, slots);
+ if (dai->dai_ops.set_sysclk)
+ return dai->dai_ops.set_tdm_slot(dai, mask, slots);
else
return -EINVAL;
}
@@ -2033,8 +1847,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot);
*/
int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate)
{
- if (dai->ops.set_sysclk)
- return dai->ops.set_tristate(dai, tristate);
+ if (dai->dai_ops.set_sysclk)
+ return dai->dai_ops.set_tristate(dai, tristate);
else
return -EINVAL;
}
@@ -2049,200 +1863,21 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate);
*/
int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute)
{
- if (dai->ops.digital_mute)
- return dai->ops.digital_mute(dai, mute);
+ if (dai->dai_ops.digital_mute)
+ return dai->dai_ops.digital_mute(dai, mute);
else
return -EINVAL;
}
EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute);
-/**
- * snd_soc_register_card - Register a card with the ASoC core
- *
- * @param card Card to register
- *
- * Note that currently this is an internal only function: it will be
- * exposed to machine drivers after further backporting of ASoC v2
- * registration APIs.
- */
-static int snd_soc_register_card(struct snd_soc_card *card)
-{
- if (!card->name || !card->dev)
- return -EINVAL;
-
- INIT_LIST_HEAD(&card->list);
- card->instantiated = 0;
-
- mutex_lock(&client_mutex);
- list_add(&card->list, &card_list);
- snd_soc_instantiate_cards();
- mutex_unlock(&client_mutex);
-
- dev_dbg(card->dev, "Registered card '%s'\n", card->name);
-
- return 0;
-}
-
-/**
- * snd_soc_unregister_card - Unregister a card with the ASoC core
- *
- * @param card Card to unregister
- *
- * Note that currently this is an internal only function: it will be
- * exposed to machine drivers after further backporting of ASoC v2
- * registration APIs.
- */
-static int snd_soc_unregister_card(struct snd_soc_card *card)
-{
- mutex_lock(&client_mutex);
- list_del(&card->list);
- mutex_unlock(&client_mutex);
-
- dev_dbg(card->dev, "Unregistered card '%s'\n", card->name);
-
- return 0;
-}
-
-/**
- * snd_soc_register_dai - Register a DAI with the ASoC core
- *
- * @param dai DAI to register
- */
-int snd_soc_register_dai(struct snd_soc_dai *dai)
-{
- if (!dai->name)
- return -EINVAL;
-
- /* The device should become mandatory over time */
- if (!dai->dev)
- printk(KERN_WARNING "No device for DAI %s\n", dai->name);
-
- INIT_LIST_HEAD(&dai->list);
-
- mutex_lock(&client_mutex);
- list_add(&dai->list, &dai_list);
- snd_soc_instantiate_cards();
- mutex_unlock(&client_mutex);
-
- pr_debug("Registered DAI '%s'\n", dai->name);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_register_dai);
-
-/**
- * snd_soc_unregister_dai - Unregister a DAI from the ASoC core
- *
- * @param dai DAI to unregister
- */
-void snd_soc_unregister_dai(struct snd_soc_dai *dai)
-{
- mutex_lock(&client_mutex);
- list_del(&dai->list);
- mutex_unlock(&client_mutex);
-
- pr_debug("Unregistered DAI '%s'\n", dai->name);
-}
-EXPORT_SYMBOL_GPL(snd_soc_unregister_dai);
-
-/**
- * snd_soc_register_dais - Register multiple DAIs with the ASoC core
- *
- * @param dai Array of DAIs to register
- * @param count Number of DAIs
- */
-int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count)
-{
- int i, ret;
-
- for (i = 0; i < count; i++) {
- ret = snd_soc_register_dai(&dai[i]);
- if (ret != 0)
- goto err;
- }
-
- return 0;
-
-err:
- for (i--; i >= 0; i--)
- snd_soc_unregister_dai(&dai[i]);
-
- return ret;
-}
-EXPORT_SYMBOL_GPL(snd_soc_register_dais);
-
-/**
- * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core
- *
- * @param dai Array of DAIs to unregister
- * @param count Number of DAIs
- */
-void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count)
-{
- int i;
-
- for (i = 0; i < count; i++)
- snd_soc_unregister_dai(&dai[i]);
-}
-EXPORT_SYMBOL_GPL(snd_soc_unregister_dais);
-
-/**
- * snd_soc_register_platform - Register a platform with the ASoC core
- *
- * @param platform platform to register
- */
-int snd_soc_register_platform(struct snd_soc_platform *platform)
-{
- if (!platform->name)
- return -EINVAL;
-
- INIT_LIST_HEAD(&platform->list);
-
- mutex_lock(&client_mutex);
- list_add(&platform->list, &platform_list);
- snd_soc_instantiate_cards();
- mutex_unlock(&client_mutex);
-
- pr_debug("Registered platform '%s'\n", platform->name);
-
- return 0;
-}
-EXPORT_SYMBOL_GPL(snd_soc_register_platform);
-
-/**
- * snd_soc_unregister_platform - Unregister a platform from the ASoC core
- *
- * @param platform platform to unregister
- */
-void snd_soc_unregister_platform(struct snd_soc_platform *platform)
-{
- mutex_lock(&client_mutex);
- list_del(&platform->list);
- mutex_unlock(&client_mutex);
-
- pr_debug("Unregistered platform '%s'\n", platform->name);
-}
-EXPORT_SYMBOL_GPL(snd_soc_unregister_platform);
-
static int __devinit snd_soc_init(void)
{
-#ifdef CONFIG_DEBUG_FS
- debugfs_root = debugfs_create_dir("asoc", NULL);
- if (IS_ERR(debugfs_root) || !debugfs_root) {
- printk(KERN_WARNING
- "ASoC: Failed to create debugfs directory\n");
- debugfs_root = NULL;
- }
-#endif
-
+ printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION);
return platform_driver_register(&soc_driver);
}
-static void __exit snd_soc_exit(void)
+static void snd_soc_exit(void)
{
-#ifdef CONFIG_DEBUG_FS
- debugfs_remove_recursive(debugfs_root);
-#endif
platform_driver_unregister(&soc_driver);
}
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 61d7d85aa578..7351db9606e4 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -37,6 +37,7 @@
#include <linux/bitops.h>
#include <linux/platform_device.h>
#include <linux/jiffies.h>
+#include <linux/debugfs.h>
#include <sound/core.h>
#include <sound/pcm.h>
#include <sound/pcm_params.h>
@@ -66,13 +67,17 @@ static int dapm_status = 1;
module_param(dapm_status, int, 0);
MODULE_PARM_DESC(dapm_status, "enable DPM sysfs entries");
-static void pop_wait(u32 pop_time)
+static struct dentry *asoc_debugfs;
+
+static u32 pop_time;
+
+static void pop_wait(void)
{
if (pop_time)
schedule_timeout_uninterruptible(msecs_to_jiffies(pop_time));
}
-static void pop_dbg(u32 pop_time, const char *fmt, ...)
+static void pop_dbg(const char *fmt, ...)
{
va_list args;
@@ -80,7 +85,7 @@ static void pop_dbg(u32 pop_time, const char *fmt, ...)
if (pop_time) {
vprintk(fmt, args);
- pop_wait(pop_time);
+ pop_wait();
}
va_end(args);
@@ -225,11 +230,10 @@ static int dapm_update_bits(struct snd_soc_dapm_widget *widget)
change = old != new;
if (change) {
- pop_dbg(codec->pop_time, "pop test %s : %s in %d ms\n",
- widget->name, widget->power ? "on" : "off",
- codec->pop_time);
+ pop_dbg("pop test %s : %s in %d ms\n", widget->name,
+ widget->power ? "on" : "off", pop_time);
snd_soc_write(codec, widget->reg, new);
- pop_wait(codec->pop_time);
+ pop_wait();
}
pr_debug("reg %x old %x new %x change %d\n", widget->reg,
old, new, change);
@@ -289,7 +293,7 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
struct snd_soc_dapm_widget *w)
{
int i, ret = 0;
- size_t name_len;
+ char name[32];
struct snd_soc_dapm_path *path;
/* add kcontrol */
@@ -303,16 +307,11 @@ static int dapm_new_mixer(struct snd_soc_codec *codec,
continue;
/* add dapm control with long name */
- name_len = 2 + strlen(w->name)
- + strlen(w->kcontrols[i].name);
- path->long_name = kmalloc(name_len, GFP_KERNEL);
+ snprintf(name, 32, "%s %s", w->name, w->kcontrols[i].name);
+ path->long_name = kstrdup (name, GFP_KERNEL);
if (path->long_name == NULL)
return -ENOMEM;
- snprintf(path->long_name, name_len, "%s %s",
- w->name, w->kcontrols[i].name);
- path->long_name[name_len - 1] = '\0';
-
path->kcontrol = snd_soc_cnew(&w->kcontrols[i], w,
path->long_name);
ret = snd_ctl_add(codec->card, path->kcontrol);
@@ -822,9 +821,23 @@ static DEVICE_ATTR(dapm_widget, 0444, dapm_widget_show, NULL);
int snd_soc_dapm_sys_add(struct device *dev)
{
+ int ret = 0;
+
if (!dapm_status)
return 0;
- return device_create_file(dev, &dev_attr_dapm_widget);
+
+ ret = device_create_file(dev, &dev_attr_dapm_widget);
+ if (ret != 0)
+ return ret;
+
+ asoc_debugfs = debugfs_create_dir("asoc", NULL);
+ if (!IS_ERR(asoc_debugfs) && asoc_debugfs)
+ debugfs_create_u32("dapm_pop_time", 0744, asoc_debugfs,
+ &pop_time);
+ else
+ asoc_debugfs = NULL;
+
+ return 0;
}
static void snd_soc_dapm_sys_remove(struct device *dev)
@@ -832,6 +845,9 @@ static void snd_soc_dapm_sys_remove(struct device *dev)
if (dapm_status) {
device_remove_file(dev, &dev_attr_dapm_widget);
}
+
+ if (asoc_debugfs)
+ debugfs_remove_recursive(asoc_debugfs);
}
/* free all dapm widgets and resources */
@@ -991,6 +1007,28 @@ err:
}
/**
+ * snd_soc_dapm_connect_input - connect dapm widgets
+ * @codec: audio codec
+ * @sink: name of target widget
+ * @control: mixer control name
+ * @source: name of source name
+ *
+ * Connects 2 dapm widgets together via a named audio path. The sink is
+ * the widget receiving the audio signal, whilst the source is the sender
+ * of the audio signal.
+ *
+ * This function has been deprecated in favour of snd_soc_dapm_add_routes().
+ *
+ * Returns 0 for success else error.
+ */
+int snd_soc_dapm_connect_input(struct snd_soc_codec *codec, const char *sink,
+ const char *control, const char *source)
+{
+ return snd_soc_dapm_add_route(codec, sink, control, source);
+}
+EXPORT_SYMBOL_GPL(snd_soc_dapm_connect_input);
+
+/**
* snd_soc_dapm_add_routes - Add routes between DAPM widgets
* @codec: codec
* @route: audio routes
@@ -1402,11 +1440,11 @@ int snd_soc_dapm_set_bias_level(struct snd_soc_device *socdev,
enum snd_soc_bias_level level)
{
struct snd_soc_codec *codec = socdev->codec;
- struct snd_soc_card *card = socdev->card;
+ struct snd_soc_machine *machine = socdev->machine;
int ret = 0;
- if (card->set_bias_level)
- ret = card->set_bias_level(card, level);
+ if (machine->set_bias_level)
+ ret = machine->set_bias_level(machine, level);
if (ret == 0 && codec->set_bias_level)
ret = codec->set_bias_level(codec, level);
diff --git a/sound/usb/caiaq/caiaq-control.c b/sound/usb/caiaq/caiaq-control.c
index ccd763dd7167..798ca124da58 100644
--- a/sound/usb/caiaq/caiaq-control.c
+++ b/sound/usb/caiaq/caiaq-control.c
@@ -247,56 +247,69 @@ static struct caiaq_controller a8dj_controller[] = {
{ "Software lock", 40 }
};
-static int __devinit add_controls(struct caiaq_controller *c, int num,
- struct snd_usb_caiaqdev *dev)
-{
- int i, ret;
- struct snd_kcontrol *kc;
-
- for (i = 0; i < num; i++, c++) {
- kcontrol_template.name = c->name;
- kcontrol_template.private_value = c->index;
- kc = snd_ctl_new1(&kcontrol_template, dev);
- ret = snd_ctl_add(dev->chip.card, kc);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
int __devinit snd_usb_caiaq_control_init(struct snd_usb_caiaqdev *dev)
{
- int ret = 0;
+ int i;
+ struct snd_kcontrol *kc;
switch (dev->chip.usb_id) {
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AK1):
- ret = add_controls(ak1_controller,
- ARRAY_SIZE(ak1_controller), dev);
+ for (i = 0; i < ARRAY_SIZE(ak1_controller); i++) {
+ struct caiaq_controller *c = ak1_controller + i;
+ kcontrol_template.name = c->name;
+ kcontrol_template.private_value = c->index;
+ kc = snd_ctl_new1(&kcontrol_template, dev);
+ snd_ctl_add(dev->chip.card, kc);
+ }
+
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL2):
- ret = add_controls(rk2_controller,
- ARRAY_SIZE(rk2_controller), dev);
+ for (i = 0; i < ARRAY_SIZE(rk2_controller); i++) {
+ struct caiaq_controller *c = rk2_controller + i;
+ kcontrol_template.name = c->name;
+ kcontrol_template.private_value = c->index;
+ kc = snd_ctl_new1(&kcontrol_template, dev);
+ snd_ctl_add(dev->chip.card, kc);
+ }
+
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_RIGKONTROL3):
- ret = add_controls(rk3_controller,
- ARRAY_SIZE(rk3_controller), dev);
+ for (i = 0; i < ARRAY_SIZE(rk3_controller); i++) {
+ struct caiaq_controller *c = rk3_controller + i;
+ kcontrol_template.name = c->name;
+ kcontrol_template.private_value = c->index;
+ kc = snd_ctl_new1(&kcontrol_template, dev);
+ snd_ctl_add(dev->chip.card, kc);
+ }
+
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER):
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2):
- ret = add_controls(kore_controller,
- ARRAY_SIZE(kore_controller), dev);
+ for (i = 0; i < ARRAY_SIZE(kore_controller); i++) {
+ struct caiaq_controller *c = kore_controller + i;
+ kcontrol_template.name = c->name;
+ kcontrol_template.private_value = c->index;
+ kc = snd_ctl_new1(&kcontrol_template, dev);
+ snd_ctl_add(dev->chip.card, kc);
+ }
+
break;
case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_AUDIO8DJ):
- ret = add_controls(a8dj_controller,
- ARRAY_SIZE(a8dj_controller), dev);
+ for (i = 0; i < ARRAY_SIZE(a8dj_controller); i++) {
+ struct caiaq_controller *c = a8dj_controller + i;
+ kcontrol_template.name = c->name;
+ kcontrol_template.private_value = c->index;
+ kc = snd_ctl_new1(&kcontrol_template, dev);
+ snd_ctl_add(dev->chip.card, kc);
+ }
+
break;
}
- return ret;
+ return 0;
}
diff --git a/sound/usb/caiaq/caiaq-device.c b/sound/usb/caiaq/caiaq-device.c
index b143ef7152f7..83175083e50f 100644
--- a/sound/usb/caiaq/caiaq-device.c
+++ b/sound/usb/caiaq/caiaq-device.c
@@ -42,7 +42,7 @@
#endif
MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("caiaq USB audio, version 1.3.9");
+MODULE_DESCRIPTION("caiaq USB audio, version 1.3.8");
MODULE_LICENSE("GPL");
MODULE_SUPPORTED_DEVICE("{{Native Instruments, RigKontrol2},"
"{Native Instruments, RigKontrol3},"